一开始我需要做一个快速的实时图像模糊。找到了一个有用的教程Perform a blur using vImage。
这是代码示例
-(UIImage *)boxblurImage:(UIImage *)image boxSize:(int)boxSize {
CGImageRef img = image.CGImage;
vImage_Buffer inBuffer, outBuffer;
vImage_Error error;
void *pixelBuffer;
//create vImage_Buffer with data from CGImageRef
CGDataProviderRef inProvider = CGImageGetDataProvider(img);
CFDataRef inBitmapData = CGDataProviderCopyData(inProvider);
inBuffer.width = CGImageGetWidth(img);
inBuffer.height = CGImageGetHeight(img);
inBuffer.rowBytes = CGImageGetBytesPerRow(img);
inBuffer.data = (void*)CFDataGetBytePtr(inBitmapData);
//create vImage_Buffer for output
pixelBuffer = malloc(CGImageGetBytesPerRow(img) * CGImageGetHeight(img));
if(pixelBuffer == NULL)
NSLog(@"No pixelbuffer");
outBuffer.data = pixelBuffer;
outBuffer.width = CGImageGetWidth(img);
outBuffer.height = CGImageGetHeight(img);
outBuffer.rowBytes = CGImageGetBytesPerRow(img);
//perform convolution
error = vImageBoxConvolve_ARGB8888(&inBuffer, &outBuffer, NULL, 0, 0, boxSize, boxSize, NULL, kvImageEdgeExtend);
if (error) {
NSLog(@"error from convolution %ld", error);
}
//create CGImageRef from vImage_Buffer output
//1 - CGBitmapContextCreateImage -
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef ctx = CGBitmapContextCreate(outBuffer.data,
outBuffer.width,
outBuffer.height,
8,
outBuffer.rowBytes,
colorSpace,
kCGImageAlphaNoneSkipLast);
CGImageRef imageRef = CGBitmapContextCreateImage (ctx);
UIImage *returnImage = [UIImage imageWithCGImage:imageRef];
//clean up
CGContextRelease(ctx);
CGColorSpaceRelease(colorSpace);
free(pixelBuffer);
CFRelease(inBitmapData);
CGImageRelease(imageRef);
return returnImage;
}
问题是该函数在某些图像上引发异常。我只找到一张图片“损坏的图片”(它是 JPEG,不是 PNG)。
有例外
<Error>: CGBitmapContextCreate: unsupported parameter combination: 8 integer bits/component; 32 bits/pixel; 3-component color space; kCGImageAlphaNoneSkipLast; 538 bytes/row.
<Error>: CGBitmapContextCreateImage: invalid context 0x0
我开始用谷歌搜索它。找到了几个解决方案。经过一段时间的调试,我发现CGImageGetBytesPerRow
“损坏的图像”返回错误的值。它适合原始图像宽度,而不是超出它应该的四倍。
我尝试手动更改rowBytes
,CGBitmapContextCreate
但图像上开始出现很多伪影。关键是这个bug很神秘,它时而出现,但仍然存在。
我如何在不检查rowBytes
缓冲区的情况下解决它?我可以对值进行一些预检查rowBytes
并返回原始图像,但它看起来像 hack。又是如何发生的,一些图像,比如我们的图像,返回错误的rowBytes
值?