- 图片的显示占用内存与图片的硬盘占用大小, 其质量没有关系, 仅仅和其本身的分辨率以及颜色占用字节有关.
ImageBuffer = widthOfImage * heightOfImage * 4; // in pixel not in point
图片显示占用内存大小 = 图片的宽度 乘以 图片的高度 乘以 颜色 RGBA 占用的4个字节;
- ① 之所有图片的大小与硬盘的占用大小无关是因为硬盘中的图片都是以不同的容器格式被编码了的, 如
png
,jpeg
等格式, 这些不能被用来直接显示; - ② 能够被用来直接显示的只有一种格式就是
bitmap
位图的方式. 要从硬盘中的容器格式变成位图,就会经历 图片解码的过程. 而解码后的位图大小计算方式如上
记录于2018/11/11
大图片的加载经常会出现什么现象?
OOM
- iOS 的图片加载方式一般使用的方法有
imageWithName
initWithContentOfFile
imageWithData
等方式, 当我们调用这些方法时, 系统会自动的将这些从不同途径获取到的图片进行 主线程CPU图片解码 从而让图片正常显示出来. - 少量的图片或者说小图, 对于高配置的手机来说系统默认的解码显示方式没有什么问题.
- 但是如果在列表中快速加载高分辨率的大图,那么就会造成内存暴涨,从而
OOM
导致手机闪退. - 业界常常使用的
SDWebImage
被用来快速加载网络图片, 其底层会对大部分图片进行显示前的解码操作,而不是等系统自己去解码,从而降低了CPU
的负荷,让主线程快速响应任务. - 但是
SDWebImage
有个缺陷是 对于大图的一次性解压操作会使内存暴增,导致闪退.
* Progressive decoding for large images run too frequently and continue even when download finished * Memory problem that caused the crash - 优化方案有,①如果是列表展示占位图,可以重新绘制一个小分辨率的图片用来显示 ② 使用
GPU
分片解码的方式,从而使内存不会出现一次性的暴涨.
当然也有人说可以关闭图片的异步解码
[[[SDImageCache sharedImageCache] config] setShouldDecompressImages:NO];
[[SDWebImageDownloader sharedDownloader] setShouldDecompressImages:NO];
当然我不建议这样处理. if you set this to false, the decompression will be done by the UIKit in main thread which will cause a drop in FPS
- 推荐查看官方关于
Image
的视频, - Image and Graphics Best Practices WWDC 2018
by ljtwan 2018/11/11