LoginSignup
42

More than 5 years have passed since last update.

UIDeviceOrientationからAVCaptureVideoOrientationを決める

Last updated at Posted at 2013-01-15

カメラ系のプチトピックです。
AVFoundationをつかってカメラの機能を使う時に、本体の向きをカメラAPIに伝える必要がありました。この伝達をしないと、横向きで写真を撮った時におかしくなります。

例えば
↑  という被写体があったとして、iphoneのホームボタンを右にして写真を撮った場合、
カメラAPIは本体が横を向いているのがわからないため、撮った写真は、
→  として出力しちゃうんですね。
でもユーザーはちゃんと
↑  というのを横幅多めで出力されるのを期待するわけです。

それが正常な挙動としてしまうのも一つですが、普通の挙動を目指すなら対応した方がいいと思います。

まずは本体の回転の通知を受けましょう
1行目が落とし穴で、きちんとこれを呼んでおかないと、向きを正しく返さないよ、
とリファレンスに書いてありました。
呼び出す順番には注意を払いたいところです。
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIDevice_Class/Reference/UIDevice.html

    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(onOrientationChanged:)
                                                 name:UIDeviceOrientationDidChangeNotification
                                               object:nil];

そしてきちんと終了処理も書いておきましょう

[[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];
[[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];

面倒なのが、[UIDevice currentDevice].orientationや通知センターで得られる向きは、
UIDeviceOrientationであって、AVFoundationが欲しがっているAVCaptureVideoOrientationとは違うという点です。
しかも左が右だったりUnknownや上向いてる、なんかが定義されています。
ヘッダーに書いてありますので、一つ一つ確認していきます。

AVCaptureVideoOrientationPortrait  ホームボタンが下
AVCaptureVideoOrientationPortraitUpsideDown ホームボタンが上
AVCaptureVideoOrientationLandscapeRight  ホームボタンが右
AVCaptureVideoOrientationLandscapeLeft ホームボタンが左

UIDeviceOrientationUnknown エラー?
UIDeviceOrientationPortrait ホームボタンが下
UIDeviceOrientationPortraitUpsideDown ホームボタンが上
UIDeviceOrientationLandscapeLeft ホームボタンが右
UIDeviceOrientationLandscapeRight ホームボタンが左
UIDeviceOrientationFaceUp 画面が上向いてる
UIDeviceOrientationFaceDown 画面が下向いてる

あとは対応を記述するだけですね

static AVCaptureVideoOrientation videoOrientationFromDeviceOrientation(UIDeviceOrientation deviceOrientation)
{
    AVCaptureVideoOrientation orientation;
    switch (deviceOrientation) {
        case UIDeviceOrientationUnknown:
            orientation = AVCaptureVideoOrientationPortrait;
            break;
        case UIDeviceOrientationPortrait:
            orientation = AVCaptureVideoOrientationPortrait;
            break;
        case UIDeviceOrientationPortraitUpsideDown:
            orientation = AVCaptureVideoOrientationPortraitUpsideDown;
            break;
        case UIDeviceOrientationLandscapeLeft:
            orientation = AVCaptureVideoOrientationLandscapeRight;
            break;
        case UIDeviceOrientationLandscapeRight:
            orientation = AVCaptureVideoOrientationLandscapeLeft;
            break;
        case UIDeviceOrientationFaceUp:
            orientation = AVCaptureVideoOrientationPortrait;
            break;
        case UIDeviceOrientationFaceDown:
            orientation = AVCaptureVideoOrientationPortrait;
            break;
    }
    return orientation;
}

で、あとはAVFoundation側に伝えます。
AVCaptureStillImageOutput *imageOutput;
としてクラスが定義されていれば、

    for(AVCaptureConnection *connection in imageOutput.connections)
    {
        if(connection.supportsVideoOrientation)
        {
            connection.videoOrientation = videoOrientationFromDeviceOrientation([UIDevice currentDevice].orientation);
        }
    }

等の様に書いておけば良いでしょう。

こういうちょっとしたことだけど、意外と気づかないことって結構ありますよね。
今回のケースではいつも縦で撮影する人には盲点になりがちな対応でした。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
42