13

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

拥有解决此问题的关键的 AVCaptureVideoPreviewLayer 对象对这些要求不是很开放:尝试使用 ..

- (id)initWithLayer:(id)layer

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

非常欢迎您提供线索/嘘声。

M。

4

4 回答 4

22

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

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

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

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

  • 除了这些,我还尝试使用AVCaptureVideoPreviewLayer。有这篇文章将 UIView 或 CALayer 保存到 UIImage。但这一切都会产生清晰或白色的图像。我尝试访问该层、视图层、层、presentationLayermodelLayer,但无济于事。我猜AVCaptureVideoPreviewLayer中的数据是非常内部的,并不是常规层基础设施的一部分。

希望这会有所帮助,奥德。

于 2010-08-10T14:10:45.103 回答
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.

于 2012-11-27T02:31:36.327 回答
0

有 2 种方法来抓取预览帧.. AVCaptureVideoDataOutput & AVCaptureStillImageOutput :)

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

于 2010-08-25T02:39:48.797 回答
-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();
于 2015-07-24T23:41:39.390 回答