iOS重绘图像以防止延迟解压缩导致更大的图像

时间:2017-04-27 23:46:18

标签: ios core-graphics cgcontext compression cgcontextdrawimage

我注意到有些人在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引入的错误,我们无法做任何事情吗?

1 个答案:

答案 0 :(得分:3)

正如您所发现的那样,行被填充到一个方便的大小。这通常是为了使矢量算法更有效。如果您要以这种方式使用CGImage,则只需要适应该布局。您需要调用CGImageGetBytesPerRow来查找分配的实际字节数,然后根据(bytesPerRow * row + column)调整偏移量。

这对你来说可能是最好的,但是如果你需要摆脱填充,你可以通过创建自己的CGBitmapContext并渲染它来做到这一点。如果您不熟悉Stack Overflow,这是一个备受关注的话题。例如:How to get pixel data from a UIImage (Cocoa Touch) or CGImage (Core Graphics)?