iOS是如何存储从压缩数据中加载的图片(jpeg2000、png、jpg等)?
示例:[UIImage imageWithData:pngData]
它是将实际编码字节存储在内部并按需解压缩,还是永久性地将其解压缩为原始像素或其他格式?
[UIImage imageNamed]
、[UIImage imageWithContentsOfFile:]
和[UIImage imageWithData]
。jpeg2000文件集合包含100个纹理,我将其复制到额外的100个文件中,并添加了“copy”后缀,以查看iOS是否进行了任何重复文件检查。下面会详细说明。[UIImage imageNamed:]
相同,因此在此阶段进行了重复过滤。
第二步: 内存使用增加到130MB。由于某种原因,这比[UIImage imageNamed:]
低70MB。这个数字更接近200个图像的预期原始像素内存量。
[NSData dataWithContentsOfFile:]
首先使用。
步骤1:内存使用量为15 MB。我认为此处没有进行重复过滤,因为这接近所有jpeg2000数据的总文件大小。
步骤2:内存使用量增加到139 MB。虽然比[UIImage imageWithContentsOfFile:]
更多,但差别不大。
iOS似乎会在需要原始像素时才解码一个使用上述三种方法加载的UIImage
的压缩数据。
[UIImage imageNamed:]
从未释放内存,因为我的所有图像视图都引用了这些图像。如果我交错加载并允许运行循环执行,它将释放非引用图像的内存。其中一个优点是对同一图像的重复调用[UIImage imageNamed:]
实质上是免费的。不要将此方法用于除GUI图像之外的任何东西,否则可能会耗尽内存。
[UIImage imageWithContentsOfFile:]
在内存使用方面的行为类似于[UIImage imageNamed:]
,直到需要原始像素时才更有效地使用内存。当UIImage被释放时,该方法还会立即释放内存。多次使用相同文件调用[UIImage imageWithContentsOfFile:]
似乎会使用缓存副本,直到所有引用文件的UIImage
都被释放。
[UIImage imageWithData:]
不进行缓存或重复检查,并且始终创建新图像。
我测试了相同的PNG文件集,步骤1的结果显示对于imageNamed
和imageWithContentsOfFile
内存使用量更少(约为0.5 MB),而imageWithData
显示了所有压缩的PNG文件的总和。我的猜测是iOS仅存储对文件的引用,并在解码时不执行其他任何操作。PNG的步骤2结果相同。
一旦加载到内存中,UIImage
以未压缩的 RGBA
格式存在。这意味着图像在内存中占用 width x height x 4
字节,其中 width
和 height
是像素的图像大小。
UIImage
在某些情况下可能会提供一些优化,但您应该做好以上规划。
更新:
我想到以上内容并不总是正确的。UIImage
具有 CGImage
属性。然后有各种函数,如 CGImageGetBitmapInfo
和 CGImageGetAlphaInfo
等其他相关函数。这些函数的返回值表明图像可以处于许多不同的格式中。有各种32位格式,以及24位和16位格式。 alpha
可以是第一个、最后一个或完全没有。字节顺序可以是大端或小端。
[UIImage imageNamed:]
从未清除其缓存。这是在哪个iOS版本上?我们已经使用imageNamed:
作为我们的图像缓存已经相当长一段时间了,但还没有遇到内存问题。 - sobriimageNamed:
方法直到收到内存警告才会清空其缓存,而这可能会发生在后续的运行循环中。 - sobri