iOS 重新绘制图像以防止延迟解压缩导致图像变大
iOS Redrawing image to prevent deferred decompression resulting in a bigger image
我注意到有些人在 CGContext
上重新绘制图像以防止延迟解压缩,这导致我们的应用程序出现错误。
错误是图像的大小声称保持不变,但 CGImageDataProvider
数据附加了额外的字节。
例如,我们从网上下载了一张 797x500 的 PNG 图片,AsyncImageView
重绘,returns重绘后的图片。
代码如下:
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 引入的错误,我们真的无能为力?
如您所见,行被填充到方便的大小。这通常是为了使矢量算法更高效。如果您要以这种方式使用 CGImage
,您只需要适应该布局。您需要调用 CGImageGetBytesPerRow
找出实际分配的字节数,然后根据此调整偏移量 (bytesPerRow * row + column
)。
这可能最适合您,但如果您需要去除填充,可以通过创建自己的 CGBitmapContext
并渲染到其中来实现。如果您不熟悉它,那么这是关于 Stack Overflow 的一个广泛讨论的主题。例如:How to get pixel data from a UIImage (Cocoa Touch) or CGImage (Core Graphics)?
我注意到有些人在 CGContext
上重新绘制图像以防止延迟解压缩,这导致我们的应用程序出现错误。
错误是图像的大小声称保持不变,但 CGImageDataProvider
数据附加了额外的字节。
例如,我们从网上下载了一张 797x500 的 PNG 图片,AsyncImageView
重绘,returns重绘后的图片。
代码如下:
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 引入的错误,我们真的无能为力?
如您所见,行被填充到方便的大小。这通常是为了使矢量算法更高效。如果您要以这种方式使用 CGImage
,您只需要适应该布局。您需要调用 CGImageGetBytesPerRow
找出实际分配的字节数,然后根据此调整偏移量 (bytesPerRow * row + column
)。
这可能最适合您,但如果您需要去除填充,可以通过创建自己的 CGBitmapContext
并渲染到其中来实现。如果您不熟悉它,那么这是关于 Stack Overflow 的一个广泛讨论的主题。例如:How to get pixel data from a UIImage (Cocoa Touch) or CGImage (Core Graphics)?