AVFoundation照片大小和旋转

时间:2014-01-11 11:13:09

标签: ios uiimage avfoundation avcapturesession

我正在做一个噩梦,试图纠正使用AVFoundation captureStillImageAsynchronouslyFromConnection拍摄的照片,以确定屏幕上显示的内容的大小和方向。

我使用此代码显示AVCaptureVideoPreviewLayer,以确保它在所有轮换中显示正确的方式:

previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession];
[previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
previewLayer.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height);
if ([[previewLayer connection] isVideoOrientationSupported])
{
    [[previewLayer connection] setVideoOrientation:(AVCaptureVideoOrientation)[UIApplication sharedApplication].statusBarOrientation];
}
[self.view.layer insertSublayer:previewLayer atIndex:0];

现在当我有一个返回的图像时,它需要裁剪,因为它比显示的要大得多。 我知道有很多UIImage裁剪示例,但我似乎遇到的第一个障碍是找到正确的CGRect使用。当我只是裁剪到self.view.frame时,图像会在错误的位置被裁剪。

预览正在使用AVLayerVideoGravityResizeAspectFill,我的UIImageView也设置为AspectFill

那么我怎样才能从预览图层中获得AVFoundation在屏幕上显示的正确帧?

编辑----

这是我面临的问题的一个例子。使用iPad Mini的前置摄像头,相机使用分辨率720x1280,但显示器为768x0124。视图显示此信息(请参见图像顶部的dado轨道:

enter image description here

然后,当我拍摄并显示图像时,它看起来像这样:

enter image description here

显然相机显示屏位于视图中央,但裁剪后的图像是从照片的顶部(未见)部分拍摄的。

1 个答案:

答案 0 :(得分:3)

我现在正在开展一个类似的项目,如果你还没有想出来,我认为我可以提供帮助。

  

我似乎遇到的第一个障碍就是找到正确的CGRect来使用。当我简单地裁剪为self.view.frame时,图像会在错误的位置被裁剪。

假设您的图片为720x1280,并且您希望将图片裁剪为显示器的矩形,即CGRect,尺寸为768x1024。你不能只传递一个768x1024的矩形。首先,您的图像宽度不是768像素。其次,您需要指定该矩形与图像的位置(即通过指定矩形的原点)。在您的示例中,self.view.frameCGRect,其原点为(0,0)。这就是为什么它总是从图像的顶部而不是从中心裁剪出来。

计算裁剪矩形有点棘手,因为你有几个不同的坐标系。

  • 你有视图控制器的视图,它有......
  • ...视频预览图层作为子图层,显示纵横填充图像,但是......
  • ... AVCaptureOutput返回的UIImage不仅具有与视频预览不同的宽度/高度,而且还具有不同的宽高比。

因为您的预览图层正在显示居中和裁剪的预览图像(即方面填充),您基本上想要找到的是CGRect

  • self.view.bounds
  • 具有相同的显示比率
  • 具有与UIImage的较小尺寸相同的较小尺寸(即纵横比)
  • UIImage
  • 为中心

这样的事情:

// Determine the width:height ratio of the crop rect, based on self.bounds
CGFloat widthToHeightRatio = self.bounds.size.width / self.bounds.size.height;
CGRect cropRect;
// Set the crop rect's smaller dimension to match the image's smaller dimension, and
// scale its other dimension according to the width:height ratio.
if (image.size.width < image.size.height) {
    cropRect.size.width = image.size.width;
    cropRect.size.height = cropRect.size.width / widthToHeightRatio;
} else {
    cropRect.size.width = image.size.height * widthToHeightRatio;
    cropRect.size.height = image.size.height;
}
// Center the rect in the longer dimension
if (cropRect.size.width < cropRect.size.height) {
    cropRect.origin.x = 0;
    cropRect.origin.y = (image.size.height - cropRect.size.height) / 2.0;
} else {
    cropRect.origin.x = (image.size.width - cropRect.size.width) / 2.0;
    cropRect.origin.y = 0;
}

最后,回到图像为720x1280的原始示例,并且您希望将图像裁剪为显示器的矩形(768x1024),最终得到的尺寸为720x960的CGRect, x = 0,y = 1280-960 / 2 = 160的原点。