无论 UIViewContentMode 选择如何,部分屏幕视频预览都会失真

Posted

技术标签:

【中文标题】无论 UIViewContentMode 选择如何,部分屏幕视频预览都会失真【英文标题】:Partial-screen video preview distorted regardless of UIViewContentMode selection 【发布时间】:2016-10-11 20:55:44 【问题描述】:

我正在尝试制作一个简单的应用程序,它将在 iPhone 屏幕的上半部分显示后置摄像头所见内容的原始预览,而在下半部分显示相同的预览,但应用了各种过滤器。

多亏了几篇 SO 和博客文章,我首先得到了原始预览部分的工作,并不太难。我正在显示的 UIImageView 占据了该部分的整个屏幕。

要获得半屏视图,我只需将图像视图的高度除以 2,然后将其 contentMode 设置为显示所有内容,同时保持相同的纵横比:

imageView = UIImageView(frame: CGRectMake(0,0, self.view.frame.size.width, self.view.frame.size.height/2))

imageView.contentMode = UIViewContentMode.ScaleAspectFit

高度降低有效,但视图中的图像被垂直压缩(例如,直视的硬币看起来像水平椭圆形)。我不认为预览的外观看起来像 contentMode 默认的 ScaleToFill 是巧合,但我没有尝试改变模式。

完整代码如下——项目有一个场景,一个视图控制器类;一切都以编程方式完成。

谢谢!

import UIKit
import AVFoundation

class ViewController: UIViewController, AVCaptureVideoDataOutputSampleBufferDelegate

    var imageView : UIImageView!

    override func viewDidLoad()
    
        super.viewDidLoad()

        imageView = UIImageView(frame: CGRectMake(0,0, self.view.frame.size.width, self.view.frame.size.height/2))
        imageView.contentMode = UIViewContentMode.ScaleAspectFit

        view.addSubview(imageView)

        let captureSession = AVCaptureSession()
        captureSession.sessionPreset = AVCaptureSessionPresetHigh

        let backCamera = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)

        do
        
            let input = try AVCaptureDeviceInput(device: backCamera)
            captureSession.addInput(input)
        
        catch
        
            print("Camera not available")
            return
        

        // Unused but required for AVCaptureVideoDataOutputSampleBufferDelegate:captureOutput() events to be fired
        let previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
        view.layer.addSublayer(previewLayer)

        let videoOutput = AVCaptureVideoDataOutput()

        videoOutput.setSampleBufferDelegate(self, queue: dispatch_queue_create("SampleBufferDelegate", DISPATCH_QUEUE_SERIAL))

        if captureSession.canAddOutput(videoOutput)
        
            captureSession.addOutput(videoOutput)
        

        videoOutput.connectionWithMediaType(AVMediaTypeVideo).videoOrientation = AVCaptureVideoOrientation.Portrait

        captureSession.startRunning()
    

    func captureOutput(captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!)
    

        let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)
        let cameraImage = CIImage(CVPixelBuffer: pixelBuffer!)

        dispatch_async(dispatch_get_main_queue())
        
            self.imageView.image = UIImage(CIImage: cameraImage)
        

    


【问题讨论】:

【参考方案1】:

我猜这行有问题,因为它在viewDidLoad() 方法中。

不确定它是否与您的问题有关,但我认为这对您来说很重要。

imageView = UIImageView(frame: CGRectMake(0,0, self.view.frame.size.width, self.view.frame.size.height/2))

您无法在viewDidLoad() 函数中获得正确的视图大小。

此外,从 ios 10 开始,我发现控件最初的大小是来自故事板的 (0, 0, 1000, 1000),然后它们才能被 iOS 布局引擎正确布局。

此外,您在viewDidLoad() 中获得的大小可以是情节提要中视图控制器的大小。因此,如果您在 4 英寸屏幕上布局控件,即使您在 iPhone6 或更大的屏幕上运行应用程序,它也会以viewDidLoad() 方法返回 4 英寸屏幕的大小。

另外,请将 imageView.layer.maskToBounds 属性设置为 true 以防止图像超出范围。

还有一点是,当视图边界发生变化(如屏幕旋转)时,您应该放置适当布局图像视图的代码。

【讨论】:

谢谢,亚历克斯。由于我是 iOS 编程新手,所以我还不熟悉这些要点。

以上是关于无论 UIViewContentMode 选择如何,部分屏幕视频预览都会失真的主要内容,如果未能解决你的问题,请参考以下文章

格式指定类型“int”,但参数的类型为“UIViewContentMode”

UIViewContentMode各类型效果

UIViewContentMode 与 UIControlContentHorizo​​ntalAlignment

iOS UIViewContentMode详解

目标 C:如何将图像放入 imageview

contentMode