AVCaptureVideoPreviewLayer:拍摄快照

Mar*_*wie 13 iphone cocoa-touch avfoundation

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

保存解决此问题的关键的AVCaptureVideoPreviewLayer对象不能满足这些要求:尝试在新层中创建它的副本...

- (id)initWithLayer:(id)layer
Run Code Online (Sandbox Code Playgroud)

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

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

M.

Ode*_*Dov 22

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

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

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

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

  • 除了这些,我还尝试使用AVCaptureVideoPreviewLayer.有这个帖子一个UIView或CALayer的保存到一个UIImage.但它都会产生清晰或白色的图像.我尝试访问图层,视图的图层,超级图层,presentationLayer,modelLayer,但无济于事.我猜AVCaptureVideoPreviewLayer中的数据非常内部,而不是常规层基础结构的一部分.

希望这会有所帮助,Oded.


小智 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);
Run Code Online (Sandbox Code Playgroud)

然后,实现下面的委托方法以获取您的图像快照:

- (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;
    });   
}
Run Code Online (Sandbox Code Playgroud)

这将消耗内存并降低应用程序的性能.要改进,您还可以优化您AVCaptureVideoDataOutput:

videoOutput.minFrameDuration = CMTimeMake(1, 15);
Run Code Online (Sandbox Code Playgroud)

你也可以使用alwaysDiscardsLateVideoFrames.