如何将CVImageBufferRef转换为UIImage

iHo*_*rse 23 iphone 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);
}
Run Code Online (Sandbox Code Playgroud)

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

Chr*_*nak 20

传递baseAddress的方式假定图像数据在表单中

ACCC

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

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

警告:我没有这样做,并且假设访问这样的CVPixelBufferRef内容是构建图像的合理方法.我无法保证这实际上有效,但我/可以/告诉你,由于您(可能)捕获视频帧的像素格式,您现在正确处理的方式将无法正常工作.

  • 完全正确的答案,所以就像评论一样:至少在iOS 4.2.1中,kCVPixelFormatType_32RGBA在iPhone 4上不能作为捕获格式使用.BGRA已全面实施. (8认同)

Oli*_*ork 14

如果你只需要将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);
}
Run Code Online (Sandbox Code Playgroud)

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

  • 您不需要所有这些步骤.你可以调用[[UIImage alloc] initWithCIImage ...] (2认同)
  • 我试过这样做,但它对我不起作用,我只是得到一个纯白色的图像.出于某种原因,我需要CIContext来做这件事(比如[这个答案](http://stackoverflow.com/a/7788510/3841734)).也许只是我的具体情况才需要它.老实说,我并不完全理解所有这些图像格式和上下文的东西. (2认同)

abh*_*ran 5

您可以直接致电:

self.yourImageView.image=[[UIImage alloc] initWithCIImage:[CIImage imageWithCVPixelBuffer:imageBuffer]];
Run Code Online (Sandbox Code Playgroud)

  • 这是可行的,但似乎比Livy Storks的方法慢很多 (2认同)