重要经验八---UIImage转换为CVPixelBufferRef

照片时间,是我个人开发的一款显示照片拍摄时间的应用,实用、免费、体积小。
http://itunes.apple.com/app/id571238224

最近做一个视频处理的项目(Rokk!),需要将opengl渲染后的特效保存为视频,由于使用了第三方库,所以不能直接使用opengl的framebuffer,后面使用了一种比较蛋疼的方式:使用glReadPixels来读取每一个渲染帧,转换为UIImage,然后将UIImage转换为CVPixelBufferRef,使用AVAssetWriterInputPixelBufferAdaptor和AVAssetWriter保存CVPixelBufferRef,最后生成视频。【此处应该有很多改进空间,希望能够多多交流】。
在上述过程中,遇到了很多坑,其中就包含“UIImage转换为CVPixelBufferRef”,网上有蛮多关于这方面的代码的,但是真正没有什么bug的,太少了,综合了各家的代码,最终我得到了相对比较正确、简洁的代码:
- (CVPixelBufferRef)pixelBufferFromCGImage:(CGImageRef)image{

NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                         [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey,
                         [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey,
                         nil];

CVPixelBufferRef pxbuffer = NULL;

CGFloat frameWidth = CGImageGetWidth(image);
CGFloat frameHeight = CGImageGetHeight(image);

CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault,
                                      frameWidth,
                                      frameHeight,
                                      kCVPixelFormatType_32ARGB,
                                      (__bridge CFDictionaryRef) options,
                                      &pxbuffer);

NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL);

CVPixelBufferLockBaseAddress(pxbuffer, 0);
void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);
NSParameterAssert(pxdata != NULL);

CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();

CGContextRef context = CGBitmapContextCreate(pxdata,
                                             frameWidth,
                                             frameHeight,
                                             8,
                                             CVPixelBufferGetBytesPerRow(pxbuffer),
                                             rgbColorSpace,
                                             (CGBitmapInfo)kCGImageAlphaNoneSkipFirst);
NSParameterAssert(context);
CGContextConcatCTM(context, CGAffineTransformIdentity);
CGContextDrawImage(context, CGRectMake(0,
                                       0,
                                       frameWidth,
                                       frameHeight),
                   image);
CGColorSpaceRelease(rgbColorSpace);
CGContextRelease(context);

CVPixelBufferUnlockBaseAddress(pxbuffer, 0);

return pxbuffer;

}

猜你喜欢

转载自blog.csdn.net/lvmaker/article/details/51508121