如何将CVImageBufferRef转换为UIImage

我正试图从相机捕捉video。 我得到了captureOutput:didOutputSampleBuffer:callback触发,它给了我一个样本缓冲区,然后我转换为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指针。 所以其余的function都不起作用。 无论我似乎传递它的函数返回null。 我不知道为什么。

您在baseAddress上传递的方式假定图像数据是在窗体中

ACCC

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

如果您已经设置AVCaptureSession以本机格式捕捉video帧,则很有可能将video数据恢复为平面YUV420格式。 (请参阅: 链接文本 )为了做你在这里尝试做什么,可能最简单的事情就是指定你想要在kCVPixelFormatType_32RGBA中捕获的video帧。 Applebuild议您捕捉kCVPixelFormatType_32BGRA中的video帧,如果您完全以非平面格式捕捉video帧,其原因没有说明,但我可以合理地假设是由于性能考虑。

警告:我没有这样做,并假设访问像这样的CVPixelBufferRef内容是一个合理的方式来构build图像。 我不能担保这个实际工作,但我/可以/告诉你,你现在正在做的事情的方式可靠地不会工作,因为你是(可能)捕获video帧的像素格式。

如果您只是简单地将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); } 

当我使用VTDecompressionSessioncallback来转换H.264video以获取CVImageBufferRef(但它应该适用于任何CVImageBufferRef)时,这种特殊的方法对我很有帮助。 我使用的是iOS 8.1,XCode 6.2。

Benjamin Loulier写了一个非常好的post,在考虑速度和多种方法的情况下输出CVImageBufferRef。

你也可以在github上find一个工作的例子;)

如何回到时间? ;)在这里你去: http : //web.archive.org/web/20140426162537/http : //www.benjaminloulier.com/posts/ios4-and-direct-access-to-the-camera

你可以直接调用:

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