2010-08-03 142 views
13

我试图模拟在默认相机应用程序中看到的动画,其中相机取景器的快照在应用程序显示的角落中动画化。AVCaptureVideoPreviewLayer:拍摄快照

持有的关键,解决这个问题

的AVCaptureVideoPreviewLayer对象不是这些要求非常开放:试图用一个新的图层创建一个副本..

- (id)initWithLayer:(id)layer 

..返回一个空层,没有图像快照,很显然这里有一些更深层次的魔法。

你的线索/嘘声是最受欢迎的。

M.

回答

22

面临着同样的困境,从稍微不同的角度。

以下是可能的解决方案,这没有太大IMO:

  • 您可以添加到AVCaptureSession既是AVCaptureStillImageOutputAVCaptureVideoDataOutput。当你设置sessionPresetAVCaptureSessionPresetHigh你会开始通过API获取帧,当你切换到AVCaptureSessionPresetPhoto你可以拍摄真实图像。所以在拍摄照片之前,您可以切换到视频,获取相框,然后返回相机。需要注意的是,摄像机在摄像机和摄像机之间切换需要“很长”的时间(几秒钟)。

  • 另一种选择是只使用摄像机输出(AVCaptureStillImageOutput),并使用UIGetScreenImage拿到手机的屏幕截图。然后,您可以裁剪控件并仅保留图像。如果您在图像上显示UI控件,这会变得复杂。另外,根据this的帖子,苹果开始拒绝使用这个功能的应用程序(它总是如此)。

  • 除了这些,我也尝试玩AVCaptureVideoPreviewLayer。有this后保存UIView或CALayer到UIImage。但它都会产生清晰或白色的图像。我尝试访问图层,视图的图层,超层presentationLayer,modelLayer,但无济于事。我猜想的数据AVCaptureVideoPreviewLayer是非常内部的,而不是真正的普通层基础设施的一部分。

希望这会有所帮助, Oded。

+0

哪一个更好@Old本多夫在上述三。给出最好的建议\ – 2017-12-11 13:39:59

0

有2种方式来获取预览帧.. AVCaptureVideoDataOutput & AVCaptureStillImageOutput :)

是您的捕获会话建立抢到视频帧,然后从选择框的cgimage让你的层。如果它被设置为剧照,请等到获得静止图像并从该cgimage的缩小版本制作图层。如果你的会话还没有输出,你就不得不添加一个我认为的。

5

我想你应该添加一个AVCaptureVideoDataOutput当前会话:

AVCaptureVideoDataOutput *videoOutput = [[AVCaptureVideoDataOutput alloc] init]; 
videoOutput.videoSettings = @{ (NSString *)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_32BGRA) }; 
[session addOutput:videoOutput]; 

dispatch_queue_t queue = dispatch_queue_create("MyQueue", NULL); 
[videoOutput setSampleBufferDelegate:self queue:queue]; 
dispatch_release(queue); 

然后,执行下面的委托方法,让您的图像抓拍:

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection { 

    UIImage *image = [self imageFromSampleBuffer:sampleBuffer]; 
    // Add your code here that uses the image. 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     _imageView.image = image; 
    }); 
} 

这会消耗内存和降低应用程序的性能。要提高,还可以优化您的AVCaptureVideoDataOutput有:

videoOutput.minFrameDuration = CMTimeMake(1, 15); 

您还可以使用alwaysDiscardsLateVideoFrames

+0

小记:默认情况下,alwaysDiscardsLateVideoFrames为true。 – xaphod 2017-09-27 00:16:02

-7

从iOS 7开始,您可以使用UIView::snapshotViewAfterScreenUpdates快照包装AVCaptureVideoPreviewLayer的UIView。这与UIGetScreenImage不一样,它会让你的应用程序被拒绝。

UIView *snapshot = [self.containerView snapshotViewAfterScreenUpdates:YES]; 

回想一下将旧视角变成图像的方式。由于某种原因,它除了相机预览之外的一切工作:

UIGraphicsBeginImageContextWithOptions(self.containerView.bounds.size, NO, [UIScreen mainScreen].scale); 
[self.containerView drawViewHierarchyInRect:self.containerView.bounds afterScreenUpdates:YES]; 
UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext(); 
+3

snapshotViewAfterScreenUpdates:在AVCaptureVideoPreviewLayer上不起作用。 – 2016-03-24 08:17:47

+0

非常烦人,这是张贴,它不适用于AVCaptureVideoPreviewLayer,只是浪费时间 – 2016-11-05 02:01:48