无论 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”