4

我已经开始使用 UIImagePickerController 来捕获静止图像的项目。我放弃了使用这种简单的机制,因为叠加层和刚刚捕获的图像之间的交互很差。问题如下:如果您有一个覆盖活动,并拍摄照片,刚刚拍摄的图像会旋转以在纵向方向进行方面填充,当用户被呈现使用或重新拍摄图像的选项时。发生这种情况时,无法解除覆盖或旋转覆盖以对应新的静止图像预览方向。不好。

我决定尝试使用 AV Foundation 的各种机制重新实现 UIImagePickerController 的静态图像捕获行为。这非常容易设置,但我仍然有一些挥之不去的问题:

1)我想重新定位机制,使其类似于标准 UIImagePickerController 中的 UI 工作方式。如您所知,在此控制器中,无论手机如何旋转,按钮栏始终固定在纵向的底部。在此按钮栏中,按钮本身的字形会旋转,但其他一切都保持不变。用于闪光灯设置、相机切换和选项的叠加控件确实会重新定向。如何在旋转这些其他元素时让这个标签栏保持固定?有没有办法从旋转中排除某些元素?

2)在进行自动重定向时,我希望 AVVideoCaptureLayer 始终保持活动状态并占据整个屏幕。当设备执行重新定向旋转时,该层的大小会变得奇怪(缩小),并且视频源本身会偏离 90 度。因此,显然这一层正在旋转,但没有旋转到全屏尺寸,并且视频源本身的行为与预期不同。我希望视频保持固定并通过完全旋转占据全屏,向上始终向上,并且在旋转期间不调整预览大小。但我也希望能够像第 1 项中那样,重新定位某些元素。

任何说明如何实现这一点的示例代码都非常感谢。

4

3 回答 3

6

刚刚发现不推荐使用 AVCaptureVideoPreviewLayer 上的方向属性。这是一个更新的解决方案(尽管@Jaret Ward 共享的先前解决方案的工作量要少得多:):

使用推荐的方法在 AVCaptureConnection 中使用 setVideoOrientation 更改它。我会在 viewDidAppear 和您的一个轮换回调中添加对此的调用。

//setup a connection to the preview layer
AVCaptureConnection *connection;
connection = [self.videoPreviewLayer connection];
[connection setVideoOrientation:[self avOrientationForDeviceOrientation:[[UIDevice currentDevice] orientation]]];

//translate the orientation
 - (AVCaptureVideoOrientation)avOrientationForDeviceOrientation:(UIDeviceOrientation)deviceOrientation {

AVCaptureVideoOrientation result = deviceOrientation;
if ( deviceOrientation == UIDeviceOrientationLandscapeLeft )
    result = AVCaptureVideoOrientationLandscapeRight;
else if ( deviceOrientation == UIDeviceOrientationLandscapeRight )
    result = AVCaptureVideoOrientationLandscapeLeft;
else if( deviceOrientation == UIDeviceOrientationPortrait)
    result = AVCaptureVideoOrientationPortrait;
else if( deviceOrientation == UIDeviceOrientationPortraitUpsideDown)
    result = AVCaptureVideoOrientationPortraitUpsideDown;
return result;
}
于 2013-04-01T05:44:41.603 回答
3

通过在视频预览层的连接上设置方向属性。

这只是@CocoaEv 答案的更简洁版本。除了将方向固定为函数而不是方法之外,它还使用更新的点语法。

self.videoPreviewLayer.connection.videoOrientation = AVOrientationFromDeviceOrientation([UIDevice currentDevice].orientation);

AVCaptureVideoOrientation AVOrientationFromDeviceOrientation(UIDeviceOrientation deviceOrientation) {
    if ( deviceOrientation == UIDeviceOrientationLandscapeLeft )
        return AVCaptureVideoOrientationLandscapeRight;
    else if ( deviceOrientation == UIDeviceOrientationLandscapeRight )
        return AVCaptureVideoOrientationLandscapeLeft;
    else if( deviceOrientation == UIDeviceOrientationPortrait)
        return AVCaptureVideoOrientationPortrait;
    else if( deviceOrientation == UIDeviceOrientationPortraitUpsideDown)
        return AVCaptureVideoOrientationPortraitUpsideDown;
    else
        return deviceOrientation;
}
于 2013-04-26T22:24:56.893 回答
2

我在自己的努力中遇到了类似的问题,最终放弃了试图影响视频流的想法。相反,我专注于 AVCaptureVideoPreviewLayer 本身并提出了这个解决方案:

- (void)orientationChangedMethod {
    self.previewLayer.orientation = [[UIDevice currentDevice] orientation];
    self.previewLayer.frame = self.view.bounds;
}

其中orientationChangedMethod 是对the.ichibod.com 的(非常有用的)代码的填充,而self.previewLayer是对我的AVCaptureVideoPreviewLayer 实例的引用。

自 iOS 6 起,此答案已被弃用!

于 2012-05-07T01:27:41.533 回答