我正在编写这个方法来计算图像的平均 R、G、B 值。以下方法将 UIImage 作为输入并返回包含输入图像的 R、G、B 值的数组。但我有一个问题:如何/在哪里正确释放 CGImageRef?
-(NSArray *)getAverageRGBValuesFromImage:(UIImage *)image
{
CGImageRef rawImageRef = [image CGImage];
//This function returns the raw pixel values
const UInt8 *rawPixelData = CFDataGetBytePtr(CGDataProviderCopyData(CGImageGetDataProvider(rawImageRef)));
NSUInteger imageHeight = CGImageGetHeight(rawImageRef);
NSUInteger imageWidth = CGImageGetWidth(rawImageRef);
//Here I sort the R,G,B, values and get the average over the whole image
int i = 0;
unsigned int red = 0;
unsigned int green = 0;
unsigned int blue = 0;
for (int column = 0; column< imageWidth; column++)
{
int r_temp = 0;
int g_temp = 0;
int b_temp = 0;
for (int row = 0; row < imageHeight; row++) {
i = (row * imageWidth + column)*4;
r_temp += (unsigned int)rawPixelData[i];
g_temp += (unsigned int)rawPixelData[i+1];
b_temp += (unsigned int)rawPixelData[i+2];
}
red += r_temp;
green += g_temp;
blue += b_temp;
}
NSNumber *averageRed = [NSNumber numberWithFloat:(1.0*red)/(imageHeight*imageWidth)];
NSNumber *averageGreen = [NSNumber numberWithFloat:(1.0*green)/(imageHeight*imageWidth)];
NSNumber *averageBlue = [NSNumber numberWithFloat:(1.0*blue)/(imageHeight*imageWidth)];
//Then I store the result in an array
NSArray *result = [NSArray arrayWithObjects:averageRed,averageGreen,averageBlue, nil];
return result;
}
我尝试了两件事:
选项1:
我保持原样,但几个周期(5+)后程序崩溃,并且出现“内存不足警告错误”
选项2:
我添加一行
CGImageRelease(rawImageRef)
在方法返回之前。现在它在第二个周期后崩溃,我收到传递给该方法的 UIImage 的 EXC_BAD_ACCESS 错误。当我尝试在 Xcode 中分析(而不是运行)时,我在这一行收到以下警告
“调用者此时不拥有的对象的引用计数的错误递减”
我应该在哪里以及如何释放 CGImageRef?
Thanks!
正如其他人所说,您的内存问题是由复制的数据引起的。但这里有另一个想法:使用 Core Graphics 的优化像素插值来计算平均值。
- 创建 1x1 位图上下文。
- 将插值质量设置为中等(见下文)。
- 将图像缩小到这一像素。
- 从上下文缓冲区读取 RGB 值。
- (当然,要释放上下文。)
这可能会带来更好的性能,因为核心显卡经过高度优化,甚至可能使用 GPU 进行缩减。
测试表明,中等质量似乎通过取颜色值的平均值来插值像素。这就是我们想要的。
至少值得一试。
Edit:好吧,这个想法看起来太有趣了,值得尝试一下。所以这是一个示例项目显示差异。以下测量值是使用包含的 512x512 测试图像进行的,但您可以根据需要更改图像。
通过迭代图像数据中的所有像素来计算平均值大约需要 12.2 毫秒。绘制到一个像素的方法需要 3 毫秒,因此速度大约快 4 倍。使用时似乎会产生相同的结果kCGInterpolationQualityMedium
.
我认为巨大的性能增益是 Quartz 注意到它不必完全解压缩 JPEG 而只使用 DCT 的低频部分的结果。当组合比例低于 0.5 的 JPEG 压缩像素时,这是一个有趣的优化策略。但我只是在这里猜测。
有趣的是,当使用你的方法时,70%的时间花在CGDataProviderCopyData
而像素数据遍历只占30%。这暗示 JPEG 解压缩花费了大量时间。
Note: 这是迟来的跟进在上面的示例图像上。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)