繁体   English   中英

如何将 CVImageBufferRef 转换为 UIImage

[英]How to convert a CVImageBufferRef to UIImage

我正在尝试从相机捕获视频。 我已经得到了captureOutput:didOutputSampleBuffer:回调来触发,它给了我一个样本缓冲区,然后我将其转换为CVImageBufferRef 然后我尝试将该图像转换为UIImage ,然后我可以在我的应用程序中查看。

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
    /*Lock the image buffer*/
    CVPixelBufferLockBaseAddress(imageBuffer,0); 
    /*Get information about the image*/
    uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddress(imageBuffer); 
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); 
    size_t width = CVPixelBufferGetWidth(imageBuffer); 
    size_t height = CVPixelBufferGetHeight(imageBuffer); 

    /*We unlock the  image buffer*/
    CVPixelBufferUnlockBaseAddress(imageBuffer,0);

    /*Create a CGImageRef from the CVImageBufferRef*/
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    CGContextRef newContext = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst); 
    CGImageRef newImage = CGBitmapContextCreateImage(newContext); 

    /*We release some components*/
    CGContextRelease(newContext); 
     CGColorSpaceRelease(colorSpace);

     /*We display the result on the custom layer*/
    /*self.customLayer.contents = (id) newImage;*/

    /*We display the result on the image view (We need to change the orientation of the image so that the video is displayed correctly)*/
    UIImage *image= [UIImage imageWithCGImage:newImage scale:1.0 orientation:UIImageOrientationRight];
    self.capturedView.image = image;

    /*We relase the CGImageRef*/
    CGImageRelease(newImage);
}

在调用CGBitmapContextCreate之前,代码似乎工作正常。 它总是返回一个NULL指针。 因此,该功能的其余部分都不起作用。 不管我似乎通过它函数返回null。 我不知道为什么。

您传递 baseAddress 的方式假定图像数据采用以下形式

ACCC

(其中 C 是一些颜色分量, R || G || B )。

如果您已将 AVCaptureSession 设置为以本机格式捕获视频帧,则很有可能以平面 YUV420 格式获取视频数据。 (请参阅: 链接文本)为了执行您在此处尝试执行的操作,最简单的方法可能是指定您希望在 kCVPixelFormatType_32RGBA 中捕获视频帧。 如果您完全以非平面格式捕获视频帧,Apple 建议您以 kCVPixelFormatType_32BGRA 格式捕获视频帧,原因未说明,但我可以合理地假设是出于性能考虑。

警告:我没有这样做,我假设像这样访问 CVPixelBufferRef 内容是构建图像的合理方法。 我不能保证这确实有效,但我/可以/告诉你,由于你(可能)捕获视频帧的像素格式,你现在做事的方式不会可靠地工作。

如果您需要将CVImageBufferRef转换为UIImage ,这似乎比不幸的是要困难得多。

本质上,您需要先将其转换为CIImage ,然后是CGImage ,最后是UIImage 我希望我能告诉你为什么。 :)

-(void) screenshotOfVideoStream:(CVImageBufferRef)imageBuffer
{
    CIImage *ciImage = [CIImage imageWithCVPixelBuffer:imageBuffer];
    CIContext *temporaryContext = [CIContext contextWithOptions:nil];
    CGImageRef videoImage = [temporaryContext
                                 createCGImage:ciImage
                                 fromRect:CGRectMake(0, 0,
                                 CVPixelBufferGetWidth(imageBuffer),
                                 CVPixelBufferGetHeight(imageBuffer))];

    UIImage *image = [[UIImage alloc] initWithCGImage:videoImage];
    [self doSomethingWithOurUIImage:image];
    CGImageRelease(videoImage);
}

当我使用VTDecompressionSession回调转换 H.264 视频以获取CVImageBufferRef (但它应该适用于任何CVImageBufferRef )时,这种特殊方法对我CVImageBufferRef 我使用的是 iOS 8.1,XCode 6.2。

您可以直接调用:

self.yourImageView.image=[[UIImage alloc] initWithCIImage:[CIImage imageWithCVPixelBuffer:imageBuffer]];

Benjamin Loulier 写了一篇关于在考虑速度的情况下使用多种方法输出 CVImageBufferRef 的非常好的帖子。

您还可以在 github 上找到一个工作示例;)

时光倒流如何? ;) 给你: http : //web.archive.org/web/20140426162537/http : //www.benjaminloulier.com/posts/ios4-and-direct-access-to-the-camera

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM