【问题标题】:AVFoundation photo size and rotationAVFoundation 照片大小和旋转
【发布时间】:2014-01-11 11:13:09
【问题描述】:

我正经历着噩梦般的时光,试图将使用 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。视图显示了这一点(参见图片顶部的墙板:

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

显然相机显示在视图的中心,但裁剪后的图像是从照片的顶部(看不到)部分拍摄的。

【问题讨论】:

    标签: ios uiimage avfoundation avcapturesession


    【解决方案1】:

    我现在正在做一个类似的项目,如果你还没有弄清楚的话,我想我可能会提供帮助。

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

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

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

    • 您已经获得了视图控制器的视图,它具有...
    • ...一个视频预览层作为子层,它正在显示一个方面填充的图像,但是...
    • ...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。

    【讨论】:

    • Richard,我刚刚花了 2 天时间尝试解决同样的问题,同时拍摄一张预览层占据屏幕顶部 50% 的照片,然后裁剪图像的确切部分在预览中可见。在浏览了 SO 上的每个裁剪线程之后,您的线程是唯一一个可以完美运行的线程。谢谢。
    • 有一件事,由于某种原因,我的“cropRect.origin.y”和“cropRect.origin.x”都得到0值,但奇怪的是,如果我用NSLog它们打印一个值714 所以我不得不手动将该数字输入到最终的 CGRectMake 中。除此之外,您的代码运行良好。
    • 酷!乐意效劳。那段代码是我为了演示该技术而临时编写的,所以如果你得到一些古怪的结果,我并不感到惊讶。很高兴你设法绕过它!
    • 它与除以 2 有关。我可以将它提供给 NSLog 正确的值,但实际方法不能正确除以 2。我是 Objective-c 和一般编程的新手,但这可能只是一个简单的修复。不管怎样,我不是在开玩笑。我花了 2 天时间试图弄清楚这一点,并不断收到诸如“裁剪图像”之类的回复。人们只是不明白,所以再次感谢您提供此代码。
    猜你喜欢
    • 1970-01-01
    • 2020-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-27
    • 2015-10-31
    • 1970-01-01
    • 2015-04-07
    相关资源
    最近更新 更多