如何将 Accelerate Framework 与 Core Graphics 一起使用?
Posted
技术标签:
【中文标题】如何将 Accelerate Framework 与 Core Graphics 一起使用?【英文标题】:How do I use the Accelerate Framework With Core Graphics? 【发布时间】:2013-12-05 13:51:06 【问题描述】:我有一个项目。它基本上是从 iPhone 相机拍摄照片并对照片应用一些效果。在我应用效果之前,我使用核心图形将图像缩放到适当 尺寸。缩放和旋转图像后,我使用 Accelerate 框架(vImage)来创建效果。我的问题是在应用效果后它最终变成了一些蓝色的图像。但是,如果我不使用核心图形缩放图像,则不会发生这种蓝色外观。
我使用的缩放代码来自this 帖子。
这是我应用效果的代码:
- (UIImage *)applyFiltertoImage:(UIImage *)img
CGImageRef image = img.CGImage;
vImage_Buffer inBuffer, outBuffer;
void *pixelBuffer;
CGDataProviderRef inProvider = CGImageGetDataProvider(image);
CFDataRef inBitmapData = CGDataProviderCopyData(inProvider);
inBuffer.width = CGImageGetWidth(image);
inBuffer.height = CGImageGetHeight(image);
inBuffer.rowBytes = CGImageGetBytesPerRow(image);
inBuffer.data = (void *)CFDataGetBytePtr(inBitmapData);
pixelBuffer = malloc(CGImageGetBytesPerRow(image) * CGImageGetHeight(image));
if (pixelBuffer == NULL)
NSLog(@"No buffer");
outBuffer.data = pixelBuffer;
outBuffer.width = CGImageGetWidth(image);
outBuffer.height = CGImageGetHeight(image);
outBuffer.rowBytes = CGImageGetBytesPerRow(image);
vImageConvolve_ARGB8888(&inBuffer, &outBuffer, NULL, 0, 0, self.kernel, self.size, self.size, self.divisor, NULL, kvImageEdgeExtend);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef ctx = CGBitmapContextCreate(outBuffer.data,
outBuffer.width,
outBuffer.height,
8,
outBuffer.rowBytes,
colorSpace,
kCGImageAlphaNoneSkipLast);
CGImageRef imageRef = CGBitmapContextCreateImage(ctx);
UIImage *blurredImage = [UIImage imageWithCGImage:imageRef];
CGContextRelease(ctx);
CGColorSpaceRelease(colorSpace);
free(pixelBuffer);
CFRelease(inBitmapData);
CGImageRelease(imageRef);
return blurredImage;
【问题讨论】:
【参考方案1】:避免手动重新定义 CGContext
尝试让 vImage 为您初始化这些值。 vImageBuffer_InitWithCGImage
可以帮助你避免一些痛苦。
简单的版本
- (UIImage *)applyFiltertoImage:(UIImage *)image
CGImageRef originalImageRef = image.CGImage;
CGColorSpaceRef originalColorSpace = CGColorSpaceRetain(CGImageGetColorSpace(originalImageRef));
if (_pixelBuffer == NULL)
_pixelBuffer = malloc(CGImageGetBytesPerRow(originalImageRef) * CGImageGetHeight(originalImageRef));
vImage_CGImageFormat inputImageFormat =
.bitsPerComponent = (uint32_t) CGImageGetBitsPerComponent(originalImageRef),
.bitsPerPixel = (uint32_t) CGImageGetBitsPerComponent(originalImageRef) * (uint32_t)(CGColorSpaceGetNumberOfComponents(originalColorSpace) + (kCGImageAlphaNone != CGImageGetAlphaInfo(originalImageRef))),
.colorSpace = originalColorSpace,
.bitmapInfo = CGImageGetBitmapInfo(originalImageRef),
.version = 0,
.decode = NULL,
.renderingIntent = kCGRenderingIntentDefault
;
vImage_Buffer inputImageBuffer;
vImageBuffer_InitWithCGImage(&inputImageBuffer, &inputImageFormat, NULL, originalImageRef, kvImageNoFlags);
vImage_Buffer outputImageBuffer =
.data = _pixelBuffer,
.width = CGImageGetWidth(originalImageRef),
.height = CGImageGetHeight(originalImageRef),
.rowBytes = CGImageGetBytesPerRow(originalImageRef)
;
vImage_Error error;
error = vImageConvolve_ARGB8888(&inputImageBuffer,
&outputImageBuffer,
NULL,
0,
0,
self.kernel,
self.size,
self.divisor,
NULL,
kvImageEdgeExtend);
if (error)
NSLog(@"vImage error %zd", error);
free(inputImageBuffer.data);
vImage_CGImageFormat outFormat =
.bitsPerComponent = (uint32_t) CGImageGetBitsPerComponent(originalImageRef),
.bitsPerPixel = (uint32_t) CGImageGetBitsPerComponent(originalImageRef) * (uint32_t)(CGColorSpaceGetNumberOfComponents(originalColorSpace) + (kCGImageAlphaNone != CGImageGetAlphaInfo(originalImageRef))),
.colorSpace = originalColorSpace,
.bitmapInfo = CGImageGetBitmapInfo(originalImageRef),
.version = 0,
.decode = NULL,
.renderingIntent = kCGRenderingIntentDefault
;
CGImageRef modifiedImageRef = vImageCreateCGImageFromBuffer(&outputImageBuffer,
&outFormat,
NULL,
NULL,
kvImageNoFlags,
&error);
CGColorSpaceRelease(originalColorSpace);
UIImage *returnImage = [UIImage imageWithCGImage:modifiedImageRef];
CGImageRelease(modifiedImageRef);
return returnImage;
高性能版
为每个图像创建一次 _inputImageBuffer、_outputImageBuffer 和 _outputImageFormat,然后将过滤器重新应用到源图像。一旦 vImage 预热,它将开始从调用中缩短几毫秒。
- (UIImage *)applyFilter
vImage_Error error;
error = vImageConvolve_ARGB8888(&_inputImageBuffer,
&_outputImageBuffer,
NULL,
0,
0,
self.kernel,
self.size,
self.divisor,
NULL,
kvImageEdgeExtend);
if (error)
NSLog(@"vImage error %zd", error);
CGImageRef modifiedImageRef = vImageCreateCGImageFromBuffer(&_outputImageBuffer,
&_outputImageFormat,
NULL,
NULL,
kvImageNoFlags,
&error);
UIImage *returnImage = [UIImage imageWithCGImage:modifiedImageRef];
CGImageRelease(modifiedImageRef);
return returnImage;
【讨论】:
【参考方案2】:通常,强烈的色调意味着颜色通道顺序在转换过程中的某处丢失,例如,您使用 BGRA 数据创建了 CG 图像,但它实际上是 ARGB。
你看过 vImage_Utilities.h 了吗?
【讨论】:
以上是关于如何将 Accelerate Framework 与 Core Graphics 一起使用?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Accelerate Framework 将带有遮罩的图像组合成一个 UIImage?
有人可以解释这段代码如何使用 Accelerate Framework 将音量转换为分贝吗?
将 AVCaptureAudioDataOutput 数据传递到 vDSP / Accelerate.framework
如何使用 Metal API 或 Accelerate Framework 绘制裁剪的位图?