サンプル
まずはサンプルから。起動すると真ん中に四角が表示される。
この状態で任意の場所をタッチするとそこにフォーカスと露出が合う。
手前を合わせてみた。
実装 - プレビュー
カメラ入力をプレビュー表示する部分の説明は今回割愛する。この辺りは下記のドキュメントが詳しい。ひと通り読めば簡単に実装できる。
AV Foundation プログラミングガイド
もしくは
など。後者の本は iOS4 となっているが iOS5 でも十分に役立つ情報が掲載されている。おすすめの本。
実装 - フォーカスと露出
任意の点にフォーカスと露出をあわせるプロパティが用意されている。
AVCaptureDevice.h @property(nonatomic) CGPoint focusPointOfInterest; @property(nonatomic) CGPoint exposurePointOfInterest;基本的にはここにフォーカスもしくは露出を合わせたい座標を入れればいい。
ただしこのプロパティに設定する値は次のルールに従う必要がある。
(1) 0.0〜1.0 に正規化した値
(2) ランドスケープ(横向き/ホームボタン右)の時の左上を原点とする座標系
「AVFoundation プログラミングガイド(PDF)」によれば次のように解説されている。
ホームボタンが右側になる横長モードでは、{0,0}が画像領域の左上を表し、{1,1}が右下を表します。これ
は、デバイスが縦長モードであっても同じです。
つまり通常のポートレイト(縦向き/ホームボタン下)の状態の時に画面上のタッチ位置をこれらに反映させるには、(1)の正規化と(2)の座標系への変換が必要になる。
(1)の正規化は単純に大きさで位置座標を割ってやれば良い。 (x/width, y/height)
ポートレイトの座標系(左上が原点)を使っている時のそれぞれの座標系の関係はこんな感じ。
x と y を入れ替えて、かつ y軸の方向に反転してやればいい。これは(1)の正規化が済んでいれば簡単にできる。
サンプルでのコードはこんな感じ。
- (void)setPoint:(CGPoint)p { CGSize viewSize = self.view.bounds.size; CGPoint pointOfInterest = CGPointMake(p.y / viewSize.height, 1.0 - p.x / viewSize.width);
フォーカスの場合は、この値を focusPointOfInterest へ渡し、focusMode を設定すれば良い。こんな感じ。
if ([videoCaptureDevice isFocusPointOfInterestSupported] && [videoCaptureDevice isFocusModeSupported:AVCaptureFocusModeAutoFocus]) { videoCaptureDevice.focusPointOfInterest = pointOfInterest; videoCaptureDevice.focusMode = AVCaptureFocusModeAutoFocus; }
露出の方は、exposurePointOfInterest 渡すだけでは駄目で、もう少し手間が必要となる。
if ([videoCaptureDevice isExposurePointOfInterestSupported] && [videoCaptureDevice isExposureModeSupported: AVCaptureExposureModeContinuousAutoExposure]){ self.adjustingExposure = YES; videoCaptureDevice.exposurePointOfInterest = pointOfInterest; videoCaptureDevice.exposureMode = AVCaptureExposureModeContinuousAutoExposure; }ここまではフォーカスとほぼ同じ。これに加えて露出の場合は、exposurePointOfInterest設定後に AVCaptureDevice の adjustingExposure プロパティを監視しこの値が NO(つまり露出合わせが終了)になったタイミングで exposureMode を AVCaptureExposureModeLocked にする必要がある。
- (void)viewDidLoad { : [videoCaptureDevice addObserver:self forKeyPath:@"adjustingExposure" options:NSKeyValueObservingOptionNew context:nil]; :監視を設定しておき値が変化したら処理をする。
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if (!self.adjustingExposure) { return; } if ([keyPath isEqual:@"adjustingExposure"]) { if ([[change objectForKey:NSKeyValueChangeNewKey] boolValue] == NO) { self.adjustingExposure = NO; AVCaptureDevice* videoCaptureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; NSError *error = nil; if ([videoCaptureDevice lockForConfiguration:&error]) { [videoCaptureDevice setExposureMode:AVCaptureExposureModeLocked]; [videoCaptureDevice unlockForConfiguration]; } } } }
試してみよう。まずは右にある MacBook Pro の明るい部分に合わせた。
次に手前の暗い 3GS。
うまくいったようだ。
ソースコード
GitHub からどうぞ。
CameraSample at 2011-12-02 from xcatsan/iOS-Sample-Code - GitHub
参考情報
iPhone4でサポートされてない露出モードのエラーが出たけど - Debian GNU/Linux 3.1 on PowerMac G4
露出の位置指定はここの情報が参考になった(