前回はカメラを使って写真を撮るところまで説明した。今回は、この写真を表示するところから始めよう。

UIImageとUIImageView

UIImagePickerControllerを使った写真の撮影が終了すると、デリゲートメソッドであるimagePickerController:didFinishPickingImage:editingInfo:が、呼び出される。このメソッドの第二引数として、UIImageというクラスのオブジェクトが渡ってくる。これが、撮影した写真を表すクラスになる。

ただし、この第二引数として渡されてくるUIImageは、写真撮影後にクロップなどの編集が行われた後のデータであることに注意してほしい。つまり、撮影時に画面に映っていた画像そのものになるが、実際に撮影されたオリジナルのデータではない。画像サイズも、320 x 320とスクリーンサイズにあったものになっている。

では、オリジナルデータにはどうやってアクセスするかというと、第三の引数であるeditingInfoを使う。この引数はNSDictionary型であり、キーとしてUIImagePickerControllerOriginalImageを指定する事でオリジナルデータのUIImageオブジェクトを取り出す事ができる。こちらの画像サイズは、1200 x 1600になっている。これが、iPhoneが搭載しているカメラの解像度になる。

ちなみに、UIImageが表している画像のサイズは、sizeプロパティを使って調べる事ができる。

UIImage.h

@property(nonatomic, readonly) CGSize size;

editingInfoには、同時にユーザが行った編集の情報も入っている。こちらは、UIImagePickerControllerCropRectを使って取り出す事ができる。ユーザによる編集内容を反映させたいときは、こちらも使おう。

取り出したUIImageを表示するには、UIImageViewクラスを使うのが簡単だ。これは、UIImageを表示してくれるビューである。

UIImageViewには、imageというプロパティがある。ここにUIImageオブジェクトを設定する事で、画面に表示させる事ができる。

UIImageView.h

@property(nonatomic, retain) UIImage* image;

このクラスを、ウインドウの中心に貼付けて使う事にしよう。Interface Builderで、ライブラリからドラッグ&ドロップでUIImageViewを追加する。さらに、CameraViewControllerにアウトレットを追加して、これを参照するようにしよう。

オフスクリーン描画

カメラアプリでは、撮影した写真のオリジナルデータを使いたいところだが、この画像サイズはかなり大きい。もちろん、近年のカメラに比べれば、解像度としては決して大きくない。だが、組み込みアプリケーションの中でこのサイズの画像を読み込んで使うのは、なかなか大変なものがある。メモリの容量に大きな制限があるiPhoneでは、できるだけ必要のないメモリの使用を避けたいところだ。

そこで、画像を縮小して使う事にしよう。1200 x 1600の画像を、300 x 400に縮小する事にする。画像の縮小の方法はいくつかあるが、ここではグラフィックスコンテキストを使う事にしよう。

グラフィックスコンテキストとは、描画を行う対象を表すものである。たとえば、iPhoneのスクリーンに描画を行うときは、スクリーン用に提供されるグラフィックスコンテキストを使う。それ以外にも、あるメモリ領域をビットマップ画像として確保して、そこに描画を行うグラフィックスコンテキストもある。つまり、オフスクリーン描画が行えるのだ。

オフスクリーン描画のためのグラフィックスコンテキストを作るには、UIGraphicsBeginImageContext()を使う。グラフィックスコンテキストを作成したら、そこに対して描画を行う。描画した結果は、UIImageで取得する事ができる。これには、UIGraphicsGetImageFromCurrentImageContext()を使う。最後に、オフスクリーン描画を終わりにするには、UIGraphicsEndImageContext()を呼ぼう。

UIGraphcis.h

void UIGraphicsBeginImageContext(CGSize size);
UIImage* UIGraphicsGetImageFromCurrentImageContext(void);
void UIGraphicsEndImageContext(void);

このグラフィックスコンテキストと、画像の縮小がどう関係するのか。鍵は、UIImageクラスが持つ、drawInRect:というメソッドにある。このメソッドは、現在のコンテキストに対して、指定した大きさで画像の描画を行うものだ。つまり、オフスクリーン領域に縮小した画像を描画する事で、縮小画像を得よう、という考え方だ。

この方法を使うと、画像の縮小だけでなく、別の画像やテキストの合成なども行う事ができる。

縮小と表示を行う

では、ソースコードを紹介しよう。前回のソースコードに付け加える形で実装していく。

CameraViewController.m

- (void)imagePickerController:(UIImagePickerController*)picker
        didFinishPickingImage:(UIImage*)image
        editingInfo:(NSDictionary*)editingInfo
{
    // イメージピッカーを隠す
    [self dismissModalViewControllerAnimated:YES];

    // オリジナル画像を取得する
    UIImage*    originalImage;
    originalImage = [editingInfo objectForKey:UIImagePickerControllerOriginalImage];

    // グラフィックスコンテキストを作る
    CGSize  size = { 300, 400 };
    UIGraphicsBeginImageContext(size);

    // 画像を縮小して描画する
    CGRect  rect;
    rect.origin = CGPointZero;
    rect.size = size;
    [originalImage drawInRect:rect];

    // 描画した画像を取得する
    UIImage*    shrinkedImage;
    shrinkedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    // 画像を表示する
    _imageView.image = shrinkedImage;
}

これで撮影した画像を、適切な大きさで表示できるようになった。次回は、この画像に対してエフェクトを加えてみよう。

ここまでのソースコード: Camera-3.zip