ios – 使用YUV颜色空间将CMSampleBufferRef转换为UIImage?

我正在使用AVCaptureVideoDataOutput并希望将CMSampleBufferRef转换为UI Image.许多答案都是一样的,比如 UIImage created from CMSampleBufferRef not displayed in UIImageView?AVCaptureSession with multiple previews

如果我将VideoDataOutput颜色空间设置为BGRA,则可以正常工作(记入此答案CGBitmapContextCreateImage error)

Nsstring* key = (Nsstring*)kCVPixelBufferPixelFormatTypeKey;
NSNumber* value = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA];
NSDictionary* videoSettings = [NSDictionary dictionaryWithObject:value forKey:key];
[dataOutput setVideoSettings:videoSettings];

如果没有上述视频设置,我将收到以下错误

CGBitmapContextCreate: invalid data bytes/row: should be at least 2560 for 8 integer bits/component,3 components,kCGImageAlphaPremultipliedFirst.
<Error>: CGBitmapContextCreateImage: invalid context 0x0

使用BGRA不是一个好选择,因为从YUV(认AVCaptureSession颜色空间)到BGRA的转换开销,如Brad和CodoHow to get the Y component from CMSampleBuffer resulted from the AVCaptureSession?所述

那么有没有办法将CMSampleBufferRef转换为UIImage并使用YUV颜色空间?

解决方法

经过大量研究并阅读了苹果文档和wikipedis.我想出了答案,它对我来说非常有效.因此,对于未来的读者,当视频像素类型设置为kCVPixelFormatType_420YpCbCr8BiPlanarFullRange时,我将共享代码以将CMSampleBufferRef转换为UIImage
// Create a UIImage from sample buffer data
// Works only if pixel format is kCVPixelFormatType_420YpCbCr8BiPlanarFullRange
-(UIImage *) imageFromSamplePlanerPixelBuffer:(CMSampleBufferRef) sampleBuffer{

    @autoreleasepool {
        // Get a CMSampleBuffer's Core Video image buffer for the media data
        CVImageBufferRef imageBuffer = CMSampleBufferGetimageBuffer(sampleBuffer);
        // Lock the base address of the pixel buffer
        CVPixelBufferLockBaseAddress(imageBuffer,0);

        // Get the number of bytes per row for the plane pixel buffer
        void *baseAddress = CVPixelBufferGetBaseAddressOfPlane(imageBuffer,0);

        // Get the number of bytes per row for the plane pixel buffer
        size_t bytesPerRow = CVPixelBufferGetBytesPerRowOfPlane(imageBuffer,0);
        // Get the pixel buffer width and height
        size_t width = CVPixelBufferGetWidth(imageBuffer);
        size_t height = CVPixelBufferGetHeight(imageBuffer);

        // Create a device-dependent gray color space
        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();

        // Create a bitmap graphics context with the sample buffer data
        CGContextRef context = CGBitmapContextCreate(baseAddress,width,height,8,bytesPerRow,colorSpace,kCGImageAlphaNone);
        // Create a Quartz image from the pixel data in the bitmap graphics context
        CGImageRef quartzImage = CGBitmapContextCreateImage(context);
        // Unlock the pixel buffer
        CVPixelBufferUnlockBaseAddress(imageBuffer,0);

        // Free up the context and color space
        CGContextRelease(context);
        CGColorSpaceRelease(colorSpace);

        // Create an image object from the Quartz image
        UIImage *image = [UIImage imageWithCGImage:quartzImage];

        // Release the Quartz image
        CGImageRelease(quartzImage);

        return (image);
    }
}

相关文章

UITabBarController 是 iOS 中用于管理和显示选项卡界面的一...
UITableView的重用机制避免了频繁创建和销毁单元格的开销,使...
Objective-C中,类的实例变量(instance variables)和属性(...
从内存管理的角度来看,block可以作为方法的传入参数是因为b...
WKWebView 是 iOS 开发中用于显示网页内容的组件,它是在 iO...
OC中常用的多线程编程技术: 1. NSThread NSThread是Objecti...