简体   繁体   English

AVFoundation照片大小和旋转

[英]AVFoundation photo size and rotation

I'm having a nightmare time trying to correct a photo taken with AVFoundation captureStillImageAsynchronouslyFromConnection to size and orient to exactly what is shown on the screen. 我遇到了一场噩梦,试图将使用AVFoundation captureStillImageAsynchronouslyFromConnection拍摄的照片更正为大小,并使其完全AVFoundation屏幕上显示的内容。

I show the AVCaptureVideoPreviewLayer with this code to make sure it displays the correct way up at all rotations: 我用以下代码显示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];

Now when I have a returned image it needs cropping as it's much bigger than what was displayed. 现在,当我收到返回的图像时,它需要裁剪,因为它比显示的要大得多。 I know there are loads of UIImage cropping examples, but the first hurdle I seem to have is finding the correct CGRect to use. 我知道有很多UIImage裁剪示例,但是我似乎遇到的第一个障碍是找到要使用的正确CGRect When I simply crop to self.view.frame the image is cropped at the wrong location. 当我简单地裁剪为self.view.frame ,图像裁剪在错误的位置。

The preview is using AVLayerVideoGravityResizeAspectFill and I have my UIImageView also set to AspectFill 预览使用AVLayerVideoGravityResizeAspectFill ,我的UIImageView也设置为AspectFill

So how can I get the correct frame that AVFoundation is displaying on screen from the preview layer? 那么,如何从预览层获得AVFoundation在屏幕上显示的正确帧呢?

EDIT ---- 编辑----

Here's an example of the problem i'm facing. 这是我面临的问题的一个示例。 Using the front camera of an iPad Mini, the camera using the resolution 720x1280 but the display is 768x0124. 使用iPad Mini的前置摄像头,摄像头使用分辨率720x1280,但显示屏为768x0124。 The view displays this (See the dado rail at the top of the image: 该视图将显示此内容(请参见图像顶部的dado导轨:

在此处输入图片说明

Then when I take the image and display it, it looks like this: 然后,当我拍摄并显示图像时,它看起来像这样:

在此处输入图片说明

Obviously the camera display was centred in the view, but the cropped image is taken from the top(none seen) section of the photo. 显然,相机的显示位于视图的中心,但是裁剪后的图像是从照片的顶部(未看到)拍摄的。

I'm working on a similar project right now and thought I might be able to help, if you haven't already figured this out. 我现在正在从事一个类似的项目,并认为如果您尚未弄清这一点,我也许可以提供帮助。

the first hurdle I seem to have is finding the correct CGRect to use. 我似乎遇到的第一个障碍是找到要使用的正确CGRect。 When I simply crop to self.view.frame the image is cropped at the wrong location. 当我简单地裁剪为self.view.frame时,图像裁剪在错误的位置。

Let's say your image is 720x1280 and you want your image to be cropped to the rectangle of your display, which is a CGRect of size 768x1024. 假设您的图片是720x1280,并且您希望将图片裁剪到显示器的矩形,即矩形的CGRect尺寸为CGRect You can't just pass a rectangle of size 768x1024. 您不能只传递尺寸为768x1024的矩形。 First, your image isn't 768 pixels wide. 首先,您的图片不是768像素宽。 Second, you need to specify the placement of that rectangle with respects to the image (ie by specifying the rectangle's origin point). 其次,您需要指定该矩形相对于图像的位置(即,通过指定矩形的原点)。 In your example, self.view.frame is a CGRect that has an origin of (0, 0). 在你的榜样, self.view.frameCGRect拥有的(0,0)的起源。 That's why it's always cropping from the top of your image rather than from the center. 这就是为什么它总是从图像的顶部而不是从中心开始裁剪的原因。

Calculating the cropping rectangle is a bit tricky because you have a few different coordinate systems. 计算裁切矩形有些麻烦,因为您有一些不同的坐标系。

  • You've got your view controller's view, which has... 您已经有了视图控制器的视图,该视图具有...
  • ...a video preview layer as a sublayer, which is displaying an aspect-filled image, but... ...作为子层的视频预览层,正在显示纵横比图像,但是...
  • ...the AVCaptureOutput returns a UIImage that not only has a different width/height than the video preview, but it also has a different aspect ratio. ... AVCaptureOutput返回的UIImage不仅具有与视频预览不同的宽度/高度,而且还具有不同的宽高比。

So because your preview layer is displaying a centered and cropped preview image (ie aspect fill), what you basically want to find is the CGRect that: 因此,由于您的预览层正在显示居中且裁剪后的预览图像(即宽高比填充),因此您基本上想要找到的是CGRect

  • Has the same display ratio as self.view.bounds 显示比例与self.view.bounds相同
  • Has the same smaller dimension size as the smaller dimension of the UIImage (ie aspect fit) 具有与UIImage的较小尺寸相同的较小尺寸大小(即,宽高比合适)
  • Is centered in the UIImage 集中在UIImage

So something like this: 所以像这样:

// 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;
}

So finally, to go back to your original example where the image is 720x1280, and you want your image to be cropped to the rectangle of your display which is 768x1024, you will end up with a CGRect of size 720x960, with an origin of x = 0, y = 1280-960/2 = 160. 因此,最后,回到原始示例,即图像为720x1280,并且您希望将图像裁剪为768x1024的显示矩形,您将得到一个CGRect,大小为720x960,原点为x = 0,y = 1280-960 / 2 = 160。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM