2015-07-03 59 views
0

我正在寻找优化从CGImage提取像素数据的例程。目前完成(非常低效)的方式是创建一个新的CGContext,将CGImage绘制到上下文中,然后从上下文中获取数据。从CGImageRef获取像素数据包含额外的字节?

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

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

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

UPDATE: 这里是我的优化程序(将剪断的代码是刚开的尺寸信息和其他非重要的事情;相关的位是像素数据返回):

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

我不清楚你是如何得到这两个不同的像素缓冲区,什么样的资格作为“优化”和其他“未优化”。我不清楚为什么你要经历你描述的这个过程。要么更清楚地描述你是如何得到这两个像素缓冲区的,或者只是告诉我们你想要做什么。 – Rob

+0

@Rob参见上面的更新。我正在通过该过程从CGImage获取底层像素数据,以便将其传递给对各个像素进行操作的自定义渲染引擎。 – Chris

+0

我的观点是,如果你想要图像的底层像素数据,你不必经历这个往返过程。 (但是,这个过程在处理异构图像格式时很有用,并且您希望以单一一致的格式来获取它。)为了回答为什么有多余的字节,我想保证两个CGImageGetBytesPerRow会返回不同的价值。 – Rob

回答

2

位图数据具有填充在每行像素的端部,舍入每行的字节数达到一较大的价值。 (在这种情况下,是16字节的倍数)。

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

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

请记住,任意CGImage背后的数据可能不是您所期望的格式。您不能假定所有图像都是不带填充的每像素32位ARGB。您应该使用CG函数来确定数据可能的格式,或者将图像重新绘制到您期望的确切格式的位图上下文中。后者通常要容易得多 - 让CG为你做转换。 (你没有显示你传递给CGBitmapContextCreate的参数,你正在计算一个确切的bytesPerRow还是你传入0?如果你传入0,CG可以为你添加填充,你可能会发现绘图的上下文更快。)

+0

它确实看起来像是填充,CGImageGetBytesPerRow()比根据图像的宽度计算大8个字节。是的,我知道CGImage可能有多种格式,但ARGB将被强制执行。并且绘制到位图上下文中是它已经在做的事情,对于被重复调用的方法来说,这太低效了。 – Chris

+0

我刚刚花了整整一个早上试图找出发生了什么事。感谢这个,upvoted。 – Vik