我想将UIImage对象转换为CVPixelBufferRef对象,但我完全不知道如何操作。而且我找不到任何类似于这样的示例代码。
有人能帮助我吗?提前感谢!
再见。
有人能帮助我吗?提前感谢!
再见。
有不同的方法来实现这一点,这些函数可以将像素缓冲区从CGImage
转换为UImage
是CGImage
的包装器,因此要获取CGImage只需要调用.CGImage
方法。
其他方法还包括从缓冲区创建CIImage
(已发布)或使用Accelerate
框架,后者可能是最快的,但也是最难的。
- (CVPixelBufferRef) pixelBufferFromCGImage: (CGImageRef) image
{
NSDictionary *options = @{
(NSString*)kCVPixelBufferCGImageCompatibilityKey : @YES,
(NSString*)kCVPixelBufferCGBitmapContextCompatibilityKey : @YES,
};
CVPixelBufferRef pxbuffer = NULL;
CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, CGImageGetWidth(image),
CGImageGetHeight(image), kCVPixelFormatType_32ARGB, (__bridge CFDictionaryRef) options,
&pxbuffer);
if (status!=kCVReturnSuccess) {
NSLog(@"Operation failed");
}
NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL);
CVPixelBufferLockBaseAddress(pxbuffer, 0);
void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);
CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(pxdata, CGImageGetWidth(image),
CGImageGetHeight(image), 8, 4*CGImageGetWidth(image), rgbColorSpace,
kCGImageAlphaNoneSkipFirst);
NSParameterAssert(context);
CGContextConcatCTM(context, CGAffineTransformMakeRotation(0));
CGAffineTransform flipVertical = CGAffineTransformMake( 1, 0, 0, -1, 0, CGImageGetHeight(image) );
CGContextConcatCTM(context, flipVertical);
CGAffineTransform flipHorizontal = CGAffineTransformMake( -1.0, 0.0, 0.0, 1.0, CGImageGetWidth(image), 0.0 );
CGContextConcatCTM(context, flipHorizontal);
CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image),
CGImageGetHeight(image)), image);
CGColorSpaceRelease(rgbColorSpace);
CGContextRelease(context);
CVPixelBufferUnlockBaseAddress(pxbuffer, 0);
return pxbuffer;
}
// 1. Create a CIImage with the underlying CGImage encapsulated by the UIImage (referred to as 'image'):
CIImage *inputImage = [CIImage imageWithCGImage:image.CGImage];
// 2. Create a CIContext:
Context *ciContext = [CIContext contextWithCGContext:UIGraphicsGetCurrentContext() options:nil];
// 3. Render the CIImage to a CVPixelBuffer (referred to as 'outputBuffer'):
[self.ciContext render:img toCVPixelBuffer:outputBuffer];
AVFoundation提供了读取视频文件(称为资产)以及从其他处理资产的AVFoundation对象的输出中读取像素缓冲区的类。如果这是您唯一关心的问题,您可以在"示例照片编辑扩展"的示例代码中找到您需要的内容。
如果您的源自于一系列UIImage对象(也许没有源文件,并且您正在从用户生成的内容创建新文件),那么上面提供的示例代码就足够了。
注意:虽然不是将UIImage转换为CVPixelBuffer的最有效方法,但它绝对是最简单的方法。使用Core Graphics将UIImage转换为CVPixelBuffer需要更多的代码来设置属性,例如像素缓冲区大小和颜色空间,而Core Image会为您处理这些问题。
Google永远是你的好朋友。搜索“CVPixelBufferRef”,第一个结果将引导您访问this snippet,它来自于snipplr:
- (CVPixelBufferRef)fastImageFromNSImage:(NSImage *)image{
CVPixelBufferRef buffer = NULL;
// config
size_t width = [image size].width;
size_t height = [image size].height;
size_t bitsPerComponent = 8; // *not* CGImageGetBitsPerComponent(image);
CGColorSpaceRef cs = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
CGBitmapInfo bi = kCGImageAlphaNoneSkipFirst; // *not* CGImageGetBitmapInfo(image);
NSDictionary *d = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey, [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey, nil];
// create pixel buffer
CVPixelBufferCreate(kCFAllocatorDefault, width, height, k32ARGBPixelFormat, (CFDictionaryRef)d, &buffer);
CVPixelBufferLockBaseAddress(buffer, 0);
void *rasterData = CVPixelBufferGetBaseAddress(buffer);
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(buffer);
// context to draw in, set to pixel buffer's address
CGContextRef ctxt = CGBitmapContextCreate(rasterData, width, height, bitsPerComponent, bytesPerRow, cs, bi);
if(ctxt == NULL){
NSLog(@"could not create context");
return NULL;
}
// draw
NSGraphicsContext *nsctxt = [NSGraphicsContext graphicsContextWithGraphicsPort:ctxt flipped:NO];
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext:nsctxt];
[image compositeToPoint:NSMakePoint(0.0, 0.0) operation:NSCompositeCopy];
[NSGraphicsContext restoreGraphicsState];
CVPixelBufferUnlockBaseAddress(buffer, 0);
CFRelease(ctxt);
return buffer;
}
不知道这是否完全有效。(结果可能会有所不同:)
UIImage
转换为CVPixelBufferRef
,而不是NSImage
。 - srgtuszy虽然很晚了,但对于需要的人来说还是有用的。
// call like this
CVPixelBufferRef videobuffer = [self pixelBufferFromCGImage:yourImage.CGImage];
// 转换的方法
-(CVPixelBufferRef)pixelBufferFromCGImage:(CGImageRef)image{
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey,
[NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey, nil];
CVPixelBufferRef pxbuffer = NULL;
CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, videoSize.width, videoSize.height,
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, videoSize.width, videoSize.height, 8, 4*videoSize.width, rgbColorSpace, kCGImageAlphaNoneSkipFirst);
NSParameterAssert(context);
CGContextConcatCTM(context, CGAffineTransformIdentity);
CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image), CGImageGetHeight(image)), image);
CGColorSpaceRelease(rgbColorSpace);
CGContextRelease(context);
CVPixelBufferUnlockBaseAddress(pxbuffer, 0);
return pxbuffer;
}
CVPixelBufferRef是核心视频用于相机输入的数据类型。
您可以使用CGBitmapContextCreate创建类似的像素位图,然后将图像绘制到位图上下文中。