iOS 如何存储从压缩数据(jpeg2000、png、jpg 等)加载的图像
示例:[UIImage imageWithData:pngData]
它是在内部存储实际编码的字节并按需解压缩,还是永久解压缩为原始像素或其他格式?
最佳答案
我在 iPad 2 上创建了一个测试应用程序,它使用以下三种方法加载了 200 个 384x384 像素的 jpeg2000 图像文件(117,964,800 字节的原始像素):[UIImage imageNamed]
, [UIImage imageWithContentsOfFile:]
和 [UIImage imageWithData]
. jpeg2000 文件集是 100 个纹理,然后我将其复制到额外的 100 个带有“复制”后缀的文件中,以查看 iOS 是否进行了任何重复文件检查,它确实如此。更多关于下面的内容。
测试分两步完成
结果如下:
[UIImage imageNamed:]
第一步:内存仅增加了所有 jpeg2000 文件的总和(每个文件约 50K,因此内存增加了约 5 MB)。我假设在这一点上重复文件没有被复制,并且以某种方式被 iOS 合并,因为如果没有重复检查,此时内存会增加 10MB。
第 2 步:内存显着增加(大约 200 MB),大概是因为图像被解码为 BGRA 格式以准备在 UIImageView 中显示。在此阶段似乎没有重复过滤,并且为每个图像分配了单独的原始内存。我不知道为什么,但这比实际的原始像素内存使用量应该多出大约 80 MB。
[UIImage imageWithContentsOfFile:]
第一步:内存使用与
[UIImage imageNamed:]
相同,因此在此阶段存在重复过滤。第 2 步:内存使用量高达 130 MB。出于某种原因,这比
[UIImage imageNamed:]
低 70 MB .这个数字更接近 200 张图像的预期原始像素内存量。[UIImage imageWithData:]
[NSData dataWithContentsOfFile:]
首先使用。第一步:内存使用量为 15 MB。我假设这里没有重复过滤,因为这接近所有 jpeg2000 数据的总文件大小。
第 2 步:内存使用量上升到 139 MB。这比
[UIImage imageWithContentsOfFile:]
,但不是很多。概括
iOS 似乎引用了
UIImage
的压缩数据使用上述三种方法加载,直到真正需要原始像素,此时才对其进行解码。[UIImage imageNamed:]
由于我所有的 ImageView 都引用了图像,因此从未释放过内存。如果我交错加载并允许运行循环执行,它将释放非引用图像的内存。优点之一是重复[UIImage imageNamed:]
调用相同的图像基本上是免费的。不要将此方法用于 GUI 图像以外的任何内容,否则可能会耗尽内存。[UIImage imageWithContentsOfFile:]
表现得像 [UIImage imageNamed:]
在内存使用中,直到需要原始像素为止,此时由于某种原因,内存使用效率更高。当 UIImage 被释放时,这个方法也会导致内存被立即释放。多次调用 [UIImage imageWithContentsOfFile:]
与相同的文件似乎使用缓存副本,直到所有 UIImage
的引用文件被释放。[UIImage imageWithData:]
不缓存或重复检查并始终创建新图像。我测试了与 PNG 文件相同的集合,并且 imageNamed 和 imageWithContentsOfFile 的第 1 步结果显示使用的内存更少(大约 0.5 MB),而 imageWithData 显示了所有压缩的 PNG 文件的总和。我的猜测是 iOS 只是存储对文件的引用,并且在解码时间之前不会对其进行任何其他操作。 PNG 的第 2 步结果是相同的。
关于iOS UIImage 存储格式、内存使用和编码/解码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20588338/