AVCaptureVideoPreviewLayer:拍摄快照

时间:2010-08-03 15:10:26

标签: iphone cocoa-touch avfoundation

我正在尝试模拟默认相机应用中看到的动画,其中相机取景器的快照被动画显示在应用程序显示的角落。

保存解决此问题的关键的AVCaptureVideoPreviewLayer对象不能满足这些要求:尝试使用..创建一个新层的副本。

- (id)initWithLayer:(id)layer

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

您的线索/嘘声非常受欢迎。

微米。

4 个答案:

答案 0 :(得分:22)

面对同样的困境,从一个稍微不同的角度。

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

  • 您可以将 AVCaptureSution 添加到 AVCaptureStillImageOutput AVCaptureVideoDataOutput 。当您将 sessionPreset 设置为 AVCaptureSessionPresetHigh 时,您将开始通过API获取帧,并且当您切换到 AVCaptureSessionPresetPhoto 时,您可以拍摄真实图像。因此,在拍摄照片之前,您可以切换到视频,获取一帧,然后返回相机。主要的警告是,摄像机在摄像机和图像摄像机之间切换需要“很长”的时间(几秒钟)。

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

  • 除此之外,我还尝试使用 AVCaptureVideoPreviewLayer 进行游戏。有this帖子将UIView或CALayer保存到UIImage。但它都会产生清晰或白色的图像。我尝试访问图层,视图层,超级层 presentationLayer modelLayer ,但无济于事。我想 AVCaptureVideoPreviewLayer 中的数据非常内部,而不是常规层基础结构的一部分。

希望这有帮助, 奥德。

答案 1 :(得分: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

答案 2 :(得分:0)

有两种方法可以抓取预览的帧... AVCaptureVideoDataOutput& AVCaptureStillImageOutput:)

是您的捕获会话设置为抓取视频帧,然后使用所选帧中的cgimage创建您的图层。如果它是静止图像的设置,请等到获取静止图像并从该cgimage的缩小版本制作图层。如果你的会话还没有输出,你必须添加一个我认为。

答案 3 :(得分:-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();