.-- --

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
スポンサー広告 comment(-) trackback(-)
.10 2009

UIGraphics系関数の使い方

Tasaki です。

今回は、久しぶりにグラフィック関連のテーマを採り上げます。
個人的には、グラフィック系に興味があるので本当はこのカテゴリのテーマを増やしていきたいとは思っているんですが。(人気のあるカテゴリだと思うので、もっと詳しい方が書かれたものがいっぱいありそうですけど。)

UIKit の描画系メソッドは、現在のグラフィックコンテキストに対して実行されます。
これでは、任意のグラフィックコンテキストへの描画はできないように思えますが、次のように記述することで、それが可能となります。
- ( void ) drawContext:( CGContextRef ) context {
CGFloat width = CGBitmapContextGetWidth( context );
CGFloat height = CGBitmapContextGetHeight( context );
UIGraphicsBeginImageContext( CGSizeMake( width, height ));
UIGraphicsPushContext( context );
// この間で描画メソッドの呼び出し
UIGraphicsPopContext();
UIGraphicsEndImageContext();
}

このとき、context には任意のビットマップコンテキストを渡すことを想定しています。
また、画面サイズより大きくても問題ありませんので、大きな画像の作成に UIKit の描画メソッドを使用することができるようになります。
ということで、NSString の UIKit 拡張メソッドもいけます。
まだ、お試しでない方はぜひ一度どうぞ。


昨日も書きましたが、iPhone 3G S では OpenGL ES 2.0 に対応するということなので、表現の幅も広がりますし、こっちの方の勉強もしていきたいですね。

.25 2009

Quartz でグラデーション

Tasaki です。

ここのところ、Quartz の機能紹介の特集みたいになってますが、
今回もその辺りの話です。

Mac のプログラミング経験がある方は、難なく扱えるのでしょうが、
なにぶん、iPhone アプリ開発に際して初めて Mac に
触れた僕のような方は、結構いらっしゃるかと思いますので
参考になれば幸いです。

さて、Quartz にはグラデーションを描画するための機能が
備わっており、そのためのデータ型として CGGradient が用意されています。
また、そのパターンも線形と放射状の2通りがあります。
この辺の話は公式ドキュメントの Quartz 2D Programming Guide に
詳しく書かれています。

今回のコードの流れは、こんな感じです。
①グラデーション情報の定義
②パスの生成
③描画
④後処理

まず、グラデーション情報を定義する訳ですが、
これには次の2種類の関数が用意されています。
CGGradientRef CGGradientCreateWithColors( CGColorSpaceRef space, CFArrayRef colors, const CGFloat locations )
CGGradientRef CGGradientCreateWithColorComponents( CGColorSpaceRef space, const CGFloat components[], const CGFloat locations[], size_t count )

見たところ、両者の引数はかなり似ていますが、
色の指定に、Objective-C の配列を使うか C の配列を使うかによって
使い分けを行うための措置というところですかね。

僕はずっと C に親しんできたので、下側の関数を使うことにします。
space は色空間情報、
components は色を表す数値の配列、
locations は色の位置の配列を、
count は1色を表現するのに要するバイト量を表します。
ここでいう、色の位置とは0から1の間の数値を指し、
ある色が、グラデーション全体のどの付近で表れるかを決めるものです。
ここが NULL の場合は、線形的に色が変化していきます。

具体的には、例えば黒から白に線形に変わるグラデーションは、
このように表します。
CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
CGFloat components[] = { 0.0f, 0.0f, 0.0f, 1.0f,
             1.0f, 1.0f, 1.0f, 1.0f };
size_t count = sizeof( components )/ sizeof( CGFloat )* 4;
CGGradientRef gradient = CGGradientCreateWithColorComponents( space, components, NULL, count );

次は、パスの生成ですが、
これは前々回のエントリを参考にしてください。
ただし、描画関数を呼んでしまうと、
設定していたパスがクリアされてしまいますので注意してください。

続いて描画に関してですが、
このために、以下のグラデーション専用の関数が用意されています。
void CGContextDrawLinearGradient( CGContextRef context, CGGradientRef gradient, CGPoint startPoint, CGPoint endPoint, CGGradientDrawingOptions options )
void CGContextDrawRadialGradient( CGContextRef context, CGGradientRef gradient, CGPoint startPoint, CGFloat startRadius, CGPoint endPoint, CGFloat endRadius, CGGradientDrawingOptions options )

前者が線形グラデーション、後者が放射状グラデーションを
描画するための関数です。

今回は線形グラデーションを試してみます。
引数ですが、
context、gradient の説明は省略しまして、
startPoint、endPoint はそれぞれグラデーションの始点と終点を、
options は始点と終点の外側の領域の描画方法を示すフラグを表します。

今回は、始点より前は始点と同じ色、終点より後は終点と同じ色として
描画する場合のコードを紹介します。
startPoint、endPoint はグラデーションをかけたい方向を考えて
与えるといいでしょう。
CGContextDrawLinearGradient( context, gradient, startPoint, endPoint, kCGGradientDrawBeforeStartLocation | kCGGradientAfterEndLocation );

最後に後始末をして、
色空間やグラデーションなどの使用済みのオブジェクトを解放します。
CGGradientRelease( gradient );
CGColorSpaceRelease( space );

今回は少し長くなってしまいましたが、
これで終わりです。お疲れさまでした。

.24 2009

Quartz で影を描く

Tasaki です。

前回、Quartz で角丸矩形のパスを生成して描画する関数を
紹介しましたので、今回はこれに影を付ける場合を考えてみましょう。

Quartz には、図形や文字などの影を描画する機能が備わっており、
影の設定を付け加えるだけで、簡単に描画できるようになっています。

そのための関数がこれです。
void CGContextSetShadow( CGContextRef context, CGSize offset, CGFloat blur )

まず、引数についてですが、
context は描画対象のグラフィックコンテキスト、
offset は、影のオフセット値、これは光源の座標と考えればいいでしょうか、
blur は影のブラーの強さを表しています。

要は、offset の値によって、影の付く方向や長さが変わり、
blur の値によって、境界付近のぼかし具合が変わるといった仕組みです。

これを影を付けたい物体の描画前に設定しておくと、
物体の描画にともない影が表示されることになります。

ただし、影ありと影なしの物体を
同時に描画する場合には注意点があり、
影の設定前にグラフィックステートの退避を、
描画終了後にグラフィックステートの復元を行う必要があります。

グラフィックステートの退避には、
void CGContextSaveGState( CGContextRef c ) を、
復元には、void CGContextRestoreGState( CGContextRef c )
それぞれ呼び出します。

グラフィックステートは、影、フォント、色、線の幅などの
コンテキストが描画に使用するための情報の集まりで、
この場合は、影を付けない状態を事前に保存しておいて、
後でその状態に戻すことになります。

これを踏まえて、コードの流れはこのようになります。
①グラフィックステートの保存
②影を設定
③描画
④グラフィックステートの復元

ちなみに、色付きの影を表示したい場合には、この関数を使います。
void CGContextSetShadowWithColor( CGContextRef context, CGSize offset, CGFloat blur, CGColorRef color )
.23 2009

Quartz でも角丸矩形

連休明けでイマイチ調子の出ない Tasaki です。

以前、角丸ボタンの作成法(というか対処法)について紹介しましたが、
今回は、Quartz を使ってコードのみで
角丸矩形を描画する方法を考えてみようと思います。
(といっても、Apple のサンプルプロジェクト UICatalog で
使われている手法の原理を考察したものでしかありませんが。)

このアプローチは、画像を用意しておく方法に比べて、融通が利きます。
そんなわけで僕は、これをテキスト表示の背景に使用しています。

標準で、これを実現する関数が用意されていないため、
パス生成関数を組み合わせて作成する訳ですが、
下の関数を使えば、コード量を抑えることができます。

void CGContextAddArcToPoint( CGContextRef c, CGFloat x1, CGFloat y1, CGFloat x2, CGFloat y2, CGFloat radius )


引数についてですが、
c は現在のグラフィックコンテキスト、
x1, y1 は弧の始点を通る接線上の点の座標、
x2, y2 は弧の終点の座標、
radius は弧の半径を表します。

この関数は、パスの現在位置を A (x0, y0)、座標(x1, y1)を B、座標(x2, y2) をCとしたとき、
線分ABと線分BCに接する半径radiusの弧をパスに追加し、
パスの現在位置を弧の終点とします。
また、Aが弧の始点でない場合は、Aから弧の始点までを直線として
自動的にパスに追加してくれます。

図で描くとこんな雰囲気です。
glaph.png

で、肝心のコードの流れは以下のようになります。
①パスの始点を設定
②矩形の四隅に対して順番に弧を追加
③パスを閉じる
④描画

CGRect 型の変数に予め矩形情報を設定しておくと、
こんな感じのコードが書けます。
void CGContextFillStrokeRoundedRect( CGContextRef context, CGRect rect, CGFloat radius ) {
 CGContextMoveToPoint( context, CGRectGetMinX( rect ), CGRectGetMidY( rect ));
 CGContextAddArcToPoint( context, CGRectGetMinX( rect ), CGRectGetMinY( rect ), CGRectGetMidX( rect ), CGRectGetMinY( rect ), radius );
 CGContextAddArcToPoint( context, CGRectGetMaxX( rect ), CGRectGetMinY( rect ), CGRectGetMaxX( rect ), CGRectGetMidY( rect ), radius );
 CGContextAddArcToPoint( context, CGRectGetMaxX( rect ), CGRectGetMaxY( rect ), CGRectGetMidX( rect ), CGRectGetMaxY( rect ), radius );
 CGContextAddArcToPoint( context, CGRectGetMinX( rect ), CGRectGetMaxY( rect ), CGRectGetMinX( rect ), CGRectGetMidY( rect ), radius );
 CGContextClosePath( context );
 CGContextDrawPath( context, kCGPathFillStroke );
}

これを使えば角丸矩形を簡単に描くことができます。

 HOME 

ブログ内検索

関連リンク

製品情報

最新記事

カテゴリ

プロフィール

neoxneo



NEXT-SYSTEM iOS Developers Blog


  • UTO:
    カナダ版iPhone4Sは、マナーモードでシャッター音がならない…


  • Ehara:
    ...


  • Hayate:
    ...


  • Tasaki:
    Developer登録完了...したのはいいけど


  • Ueda:
    ...



リンク

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。