从CGImageRef获取像素数据包含额外的字节?

时间:2015-07-03 18:18:19

标签: ios bitmap core-graphics cgimage

我正在考虑优化从CGImage获取像素数据的例程。目前这种方式(非常低效)的方法是创建一个新的CGContext,将CGImage绘制到上下文中,然后从上下文中获取数据。

我有以下优化程序来处理这个问题:

CGImageRef imageRef = image.CGImage;
uint8_t *pixelData = NULL;

CGDataProviderRef imageDataProvider = CGImageGetDataProvider(imageRef);
CFDataRef imageData = CGDataProviderCopyData(imageDataProvider);
pixelData = (uint8_t *)malloc(CFDataGetLength(imageData));
CFDataGetBytes(imageData, CFRangeMake(0, CFDataGetLength(imageData)), pixelData);
CFRelease(imageData);

这几乎可行。在查看和比较通过两种方法获得的像素数据的十六进制转储之后,我发现在上述情况下,每6360字节有8个字节的0。否则,数据是相同的。例如 enter image description here

这是与未优化版本的比较: enter image description here

在0的8个字节之后,正确的像素数据继续。任何人都知道为什么会这样吗?

更新: 这是我正在优化的例程(剪切代码只是获取大小信息,以及其他非重要的东西;相关位是返回的像素数据):

CGContextRef context = NULL;
CGImageRef imageRef = image.CGImage;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();

CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst;

// ... SNIP ...

context = CGBitmapContextCreate(...);
CGColorSpaceRelease(colorSpace);

// ... SNIP ...

CGContextDrawImage(context, rect, imageRef);
uint8_t *pixelData = (uint8_t *)CGBitmapContextGetData(context);

CGContextRelease(context);

显然,这只是获取基础像素数据的大量工作。创建一个上下文,然后绘制它。第一个例程的速度是5到10倍。但正如我所指出的,两个例程返回的像素数据几乎完全相同,只是在优化代码中每6360字节插入8个零字节值(在图像中突出显示)。

否则,其他一切都是相同的 - 颜色值,字节顺序等。

1 个答案:

答案 0 :(得分:4)

位图数据在每行像素的末尾都有填充,以将每行的字节数舍入为更大的值。 (在这种情况下,16个字节的倍数。)

添加此填充以使处理和绘制图像更快。

您应该使用CGImageGetBytesPerRow()来查找每行占用的字节数。不要认为它与CGImageGetWidth() * CGImageGetBitsPerPixel() / 8相同;每行的字节数可能更大。

请注意,任意CGImage背后的数据可能不是您期望的格式。您不能假设所有图像都是32位/像素ARGB,没有填充。您应该使用CG函数来确定数据的格式,或者将图像重新绘制为具有您期望的确切格式的位图上下文。后者通常要容易得多 - 让CG为你做转换。

(你没有显示你传递给CGBitmapContextCreate的参数。你在计算一个确切的bytesPerRow还是你传入0?如果你传入0,CG可能会添加填充你,你可能会发现在上下文中绘图更快。)