UIDeviceOrientationからAVCaptureVideoOrientationを決める

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

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

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

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

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

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

```objc
[[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 画面が下向いてる

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

```objc
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;`
としてクラスが定義されていれば、

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

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

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