我注意到有些人在CGContext
上重绘图像以防止延迟解压缩,这导致我们的应用中出现了错误。
错误是图像的大小声称保持不变,但CGImageDataProvider
数据附加了额外的字节。
例如,我们从互联网上下载了一张797x500的PNG图像,AsyncImageView
重绘并返回重新绘制的图像。
以下是代码:
UIImage *image = [[UIImage alloc] initWithData:data];
if (image)
{
// Log to compare size and data length...
NSLog(@"BEFORE: %f %f", image.size.width, image.size.height);
NSLog(@"LEN %ld", CFDataGetLength(CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage))));
// Original code from AsyncImageView
//redraw to prevent deferred decompression
UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale);
[image drawAtPoint:CGPointZero];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Log to compare size and data length...
NSLog(@"AFTER: %f %f", image.size.width, image.size.height);
NSLog(@"LEN %ld", CFDataGetLength(CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage))));
// Some other code...
}
日志显示如下:
BEFORE: 797.000000 500.000000
LEN 1594000
AFTER: 797.000000 500.000000
LEN 1600000
我决定逐个打印每个字节,确实每行都附加了12个0
。
基本上,重绘会导致图像数据为800x500图像。因此,我们的应用在查看797 * row + column
像素时会查看错误的像素。
我们没有使用任何大图像,因此延迟解压缩不会造成任何问题,但如果我决定使用此方法重绘图像,我可能会引入一个微妙的错误。
有没有人有解决方案?或者这是Apple引入的错误,我们无法做任何事情吗?
答案 0 :(得分:3)
正如您所发现的那样,行被填充到一个方便的大小。这通常是为了使矢量算法更有效。如果您要以这种方式使用CGImage
,则只需要适应该布局。您需要调用CGImageGetBytesPerRow
来查找分配的实际字节数,然后根据(bytesPerRow * row + column
)调整偏移量。
这对你来说可能是最好的,但是如果你需要摆脱填充,你可以通过创建自己的CGBitmapContext
并渲染它来做到这一点。如果您不熟悉Stack Overflow,这是一个备受关注的话题。例如:How to get pixel data from a UIImage (Cocoa Touch) or CGImage (Core Graphics)?