アラのアラアラしい日記

こっそりかいてます

AVFoundationでカメラの明るさを調整しよう

こんにちは!IE9を使う人です。
英語公用語の社内でジャパナイゼーションを進めていることが上司にバレました。

さて、しばらく仕事でカメラアプリを作成していますが、今回はobj-cでの明るさ調整のメモです。

私自身にカメラの知識がなさすぎるので、もどかしいところが多いかと思いますがご了承ください(おじぎ)。

カメラの明るさ(露出度)を調整するには、カメラのオフセット(基準点からの差で表した値)、デュレーション(1カットの編集・特殊効果時間の長さ)、バイアス(000秒で撮影されたときに現れる映像)等が関係しているそうですが、
スライダーでISO感度をユーザに調整してもらうのが一番使いやすいかと思います。
ISOとは、国際標準化機構(International Organization for Standardization)の略で、写真感光材料の感光度を設定したものを言うそうです。
結局のところなんなんでしょうね。カメラって奥が深いんだなァ。

まず、使用する変数を準備します。(カメラ設定等は省略しています)

@property (nonatomic) AVCaptureDeviceInput *videoDeviceInput;
@property (weak, nonatomic) IBOutlet UISlider *exposureSlider;

次にviewDidAppear内でスライダーにISOの値をセットします。

- (void)viewDidAppear:(BOOL)animated
{
    // デバイス情報を取得
    AVCaptureDevice *device = [[self videoDeviceInput] device];

    // sliderの最小値・最大値を設定 (ISOの最大・最小にする)
    self.exposureSlider.minimumValue = device.activeFormat.minISO;
    self.exposureSlider.maximumValue = device.activeFormat.maxISO;

    // ISOの中間値を計算して結果を変数に代入
    float midISO = (self.exposureSlider.minimumValue + self.exposureSlider.maximumValue) / 2;
    self.exposureSlider.value = midISO;

    NSError *error = nil;
    // デバイスのロック
    if ([device lockForConfiguration:&error])
    {
        // ISO初期値(中間値)でカメラを表示
        [device setExposureModeCustomWithDuration:AVCaptureExposureDurationCurrent ISO:midISO completionHandler:nil];
        // デバイスロックの解除
        [device unlockForConfiguration];
    }
    else
    {
    NSLog(@"%@", error);
    }
}

viewDidAppearよりも前のライフサイクル内でカメラ情報を取得しようとすると、
View自体がAVCaptureDeviceを完全に読み込む前にISO値を取得してしまう為、正しい値が取れなくなります。

また、デバイスのロックに関しては、デバイスの設定を変更する為に動いているデバイスのフォーカスや露出をロックする必要があります。
設定の変更が終了したら再度デバイスのロックを解除します。

続きましてスライダーが変更された時の振る舞いです。

- (IBAction)changeISO:(id)sender
{
    // デバイスの取得
    AVCaptureDevice *device = [[self videoDeviceInput] device];

    UISlider *control = sender;
    NSError *error = nil;
    if ([device lockForConfiguration:&error])
    {
        // 取得した値をISO値にセットしてカメラ表示を変更
        [device setExposureModeCustomWithDuration:AVCaptureExposureDurationCurrent ISO:control.value completionHandler:nil];
        [device unlockForConfiguration];
    }
    else
    {
    NSLog(@"%@", error);
    }
}

storyboard内のスライダーにIBActionを付けて値を取得し、ISOを調整します。

こんな感じで、以下のような結果になりました。

最初
f:id:wknar0311:20150825143156p:plain

暗くした
f:id:wknar0311:20150825143134p:plain

明るくした
f:id:wknar0311:20150825143146p:plain

うまくいきましたな。
ちなみに今回のこのカメラの調整はiOS8以降での対応だそうなのでちょっと注意です。
(2015/07時点でiOS8ユーザは8割超のようなので大きな影響はないかと思いますが。)

できなかったこと

本当は最初、初期値を取得する為にAVCaptureISOCurrentを使用する予定でしたが、
maxISOが3桁なのに対して30桁くらいの値しか取得できなかったので利用を断念しました。。。
これ使っている人がいたら是非教えてください〜〜〜