カメラによる写真撮影とフォトライブラリの写真利用について
フォトライブラリに蓄えられた写真に関しては、アプリケーションから自由に利用できるようです.
またアプリからカメラを起動し、写真撮影を行った画像の利用もおこなえるようです.
iPhone OS プログラミングガイドにも、簡単な概要が書かれているようですが、少々わかりづらかったので
まとめておくことにします.
概要
アプリ中で、カメラから写真撮影した画像をつかったり、フォトライブラリに蓄えられた画像を利用するためには、
UIImagePickerController を利用する.
概要としては、iPhone OS プログラミングガイドで「カメラによる写真の撮影」として紙面が割かれているので
参照すると良い.
ポイントは、次のようになる.
- UIViewController から派生した、独自の ViewController を利用する
- UIImagePickerController には、UIImagePickerControllerDelegate/UINavigationControllerDelegate を割り当てる必要がある.
- カメラはついていないデバイス(iPod touch)が存在するので、利用できるかチェックが必要.
- 撮影(選択)された、Image はデリゲートから渡される.
- 撮影(選択)時/キャンセル時には、Picker の削除が必要.
- UIImagePickerController から、処理したい View への Image の渡し方.
サンプルで作成してみるアプリの外観は、こんな感じ
(機能)
- Camera ボタンを押すと、カメラを起動して画像取得、Photo Library ボタンを押すとフォトライブラリから画像の取得の表示を行う.
- 取得した画像を、View に貼り付けておいた UIImageView に設定して画面表示する.
UIViewController に関して
iPhone OS プログラミングガイドでは、要点しかソースが載っていないし、直接的なサンプルも用意されていないので、
全体像がよく見えてこない.
よって、冗長かとはおもうが、私がテストに利用したソースをそのまま貼り付けておくことにした.
# はてな dialy でファイルの添付ができりゃいいのに...
(CameraViewController.h)
@interface CameraViewController : UIViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate> { IBOutlet UIImageView* m_image_view; } /// PhotoLibrary からのイメージ読み込みボタン押下 - (IBAction) getImageByPhotoLibrary:(id)i_sender; /// Camera からのイメージ読み込みボタン押下 - (IBAction) getImageByCamera:(id)i_sender; @end
(CameraViewController.mm)
#include "CameraViewController.h" // private @interface CameraViewController() /// CameraPicker の開始を行う - (BOOL) startCameraPickerFromViewController:(UIViewController*)i_controller usingDelegate:(id<UIImagePickerControllerDelegate, UINavigationControllerDelegate>)i_delegate sourceType:(UIImagePickerControllerSourceType)i_type; - (void) useImage:(UIImage*)i_image; @end @implementation CameraViewController /// ソースタイプを指定してイメージの取得を行う - (void) getImageBySourceType:(UIImagePickerControllerSourceType)i_type { } /// PhotoLibrary からのイメージ読み込みボタン押下 - (IBAction) getImageByPhotoLibrary:(id)i_sender { [self startCameraPickerFromViewController:self usingDelegate:self sourceType:UIImagePickerControllerSourceTypePhotoLibrary]; } /// Camera からのイメージ読み込みボタン押下 - (IBAction) getImageByCamera:(id)i_sender { [self startCameraPickerFromViewController:self usingDelegate:self sourceType:UIImagePickerControllerSourceTypeCamera]; } /// 解放処理 - (void)dealloc { [super dealloc]; } /// CameraPicker の開始を行う - (BOOL) startCameraPickerFromViewController:(UIViewController*)i_controller usingDelegate:(id<UIImagePickerControllerDelegate, UINavigationControllerDelegate>)i_delegate sourceType:(UIImagePickerControllerSourceType)i_type { if( ![UIImagePickerController isSourceTypeAvailable:i_type] || (i_delegate == nil) || (i_controller == nil ) ){ return NO; } UIImagePickerController* a_picker = [[UIImagePickerController alloc] init]; a_picker.sourceType = i_type; a_picker.delegate = i_delegate; a_picker.allowsImageEditing = YES; // ピッカーは非同期に表示される [i_controller presentModalViewController:a_picker animated:YES]; return YES; } /// 画像が選択されたときに呼ばれるデリゲート関数 - (void) imagePickerController:(UIImagePickerController*)i_picker didFinishPickingImage:(UIImage*)i_image editingInfo:(NSDictionary*)i_editing_info { [self useImage:i_image]; [[i_picker parentViewController] dismissModalViewControllerAnimated:YES]; [i_picker release]; } /// 画像の選択がキャンセルされたときに呼ばれるデリゲート関数 - (void) imagePickerControllerDidCancel:(UIImagePickerController*)i_picker { [[i_picker parentViewController] dismissModalViewControllerAnimated:YES]; [i_picker release]; } - (void) navigationController:(UINavigationController*)i_navigation_controller didShowViewController:(UIViewController*)i_view_controller animated:(BOOL)i_animated { } - (void)useImage:(UIImage*)i_image { m_image_view.image = i_image; } @end || この、 CameraViewController をどうやって利用するかってのに、少し悩んだ. (後述) View に貼り付けたボタンに対応して、 UIImagePickerController を作成するので、 getImageBy* は IBAction 指定にして、ボタンと接続を行っておく. また、View に貼り付けた、UIImageView に対して、 UIImage をセットするので、IBOutlet 指定にして、 IImaageView と接続を行っておく. ** CameraViewController の要点? >|objcpp| @interface CameraViewController : UIViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
UIImagePickerController には、UIImagePickerControllerDelegate, UINavigationControllerDelegate を
設定する必要がある.
通常は、Controller が Delegate プロトコルを実装するらしいが、他のクラスが実装を行っても良い(らしい)
if( ![UIImagePickerController isSourceTypeAvailable:i_type] || (i_delegate == nil) || (i_controller == nil ) ){ return NO; }
上記部分で、カメラ(フォトライブラリ)が利用できるか判断を行っている.
// ピッカーは非同期に表示される [i_controller presentModalViewController:a_picker animated:YES];
上記部分で、モーダルView としてピッカーを登録している.
モードレスView としても利用できるらしいが、利用方法がよく分からなかった.
InterfaceBuilder での設定
(忘れがちなので、一応書き残しておく)
- View の xib ファイルを作成するときに、 Fields Owner には、CameraViewController を設定しておくこと.
- 今回は UIView 派生クラスは利用しないので、View 自体は、UIView に設定しておけばよい.
ImagePickerSampleAppDelegate
アプリケーション起動時には、作成した CameraViewController を UIViewController の代わりに利用する.
このあたりは、解説済みだから要点だけ載せておく.
- (void)applicationDidFinishLaunching:(UIApplication *)application { CameraViewController* a_view_controller = [[CameraViewController alloc] initWithNibName:@"ImageView" bundle:[NSBundle mainBundle]]; self.viewController = a_view_controller; [a_view_controller release]; UIView* a_controllers_view = [m_view_controller view]; [m_window addSubview:a_controllers_view]; [m_window makeKeyAndVisible]; }
まとめとか、わからなかったこと
- 理解できれば、 「iPhone OS プログラミングガイド」に書いてある通りで、補足説明すらいらないのかも...
- 状況に応じて ViewController を使い回したい(複数個の ViewController を利用したい)場合ってどうすればいいんだろう?
- 今回は、 ViewController だけで処理がすんだけれども、実際の処理が他のクラスにまたがる場合、データはどのように管理するのが良いのだろう?
...結局、まだまだ、iPhone OS の文化になじめていないってことですね
次回予告
基礎編としては、たぶんこんなもんでしょう.
もう少し変なことをやってみたいので、もう少し写真利用についての調査をやってみようかとおもいます.