保存用户在AVCaptureVideoPreviewLayer中看到的内容

时间:2016-10-07 10:51:00

标签: ios swift avfoundation

我正在尝试使用自定义相机开发应用,用户可以在其中添加过滤器或贴纸(如在TextCamera应用中)并分享社交Feed。 但我发现了我的第一个问题。

我使用AVCaptureVideoPreviewLayer向用户显示预览,拍摄照片并将其传递给UiImageView中的另一个视图控制器,但第二张图片比第一张图片大。

我尝试使用此功能调整图片大小:

    func resize(image: UIImage) -> UIImage {
       let size = image.size
       let newWidth = CGFloat(size.width)
       let newHeight = CGFloat(size.height - blackBottomTab.bounds.size.height)

       let newSize = CGSizeMake(newWidth,newHeight)
       let rect = CGRectMake(0, 0, newSize.width, newSize.height)

       UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
       image.drawInRect(rect)
       let newImage = UIGraphicsGetImageFromCurrentImageContext()
       UIGraphicsEndImageContext()

       return newImage
}

在此功能中,我从图像高度中减去黑色视图(按钮下方)的高度。但是我的结果是不同的(见附图)。

This is my preview with a black view under the button

This is the photo taken larger than preview one

我还尝试在第二个View Controller的Storyboard Image View中使用Aspect Fit,但结果是一样的。

我的错误在哪里?谢谢所有帮助我的人!

2 个答案:

答案 0 :(得分:0)

我认为AVCaptureVideoPreviewLayer框架与屏幕的框架(UIScreen.mainScreen().bounds)相同,并且您添加了"拍摄照片​​"在它上面的黑色视图。相反,您应该更改AVCaptureVideoPreviewLayer

的框架

你的情况(我的想法):

enter image description here

假设绿色矩形是AVCaptureVideoPreviewLayer帧,红色矩形是黑色视图帧。因此,它覆盖了绿色矩形(顶部)。

让它们看起来像这样:

enter image description here

希望有所帮助。

答案 1 :(得分:0)

我不得不解决类似的问题。正如问题所指出的那样,似乎没有一种简单的方法可以检测视频预览的大小。

https://stackoverflow.com/a/57996039/10449843的答案结尾处提示了我的解决方案,该答案详细说明了我如何拍摄快照并创建带有标签的组合快照。

这里是对该提示的详细说明。

虽然我使用AVCapturePhotoCaptureDelegate拍摄快照,但是我也使用AVCaptureVideoDataOutputSampleBufferDelegate对缓冲区进行一次采样,以便在第一次显示预览时检测快照的比例。

            // The preview layer is displayed with aspect fill
            let previewLayer = AVCaptureVideoPreviewLayer(session: session)
            previewLayer.videoGravity = .resizeAspect
            previewLayer.frame = self.cameraView.bounds

检测预览的大小:

func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
        // Only need to do this once
        guard self.sampleVideoSize == true else {
            return
        }

        guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
            return
        }

        // Sample the size of the preview layer and then store it
        DispatchQueue.main.async {

            let width = CGFloat(CVPixelBufferGetWidth(pixelBuffer))
            let height = CGFloat(CVPixelBufferGetHeight(pixelBuffer))

            // Store the video size in a local variable
            // We don't care which side is which, we just need the
            // picture ratio to decide how to align it on different
            // screens.
            self.videoSize = CGSize.init(width: width, height: height)

            // Now we can set up filters and stickers etc
            ...

            // And we don't need to sample the size again
            self.sampleVideoSize = false
        }
        return
    }