一爵赵、圖像從文件到屏幕的過程
圖片顯示分為三步:加載、解碼绵咱、渲染
CPU 和 GPU 在渲染過程中的分工是什么?
CPU(中央處理器):計算frame熙兔、解壓縮圖片悲伶、將需要繪制的紋理圖片通過數(shù)據(jù)總線交給GPU艾恼。
GPU(圖形處理器):定點的計算與變換、像素點的填充計算和紋理混合麸锉、渲染到幀緩沖區(qū)钠绍。
圖片顯示到屏幕上是CPU和GPU共同完成的。
二花沉、圖片加載的工作流程
以 +(UIImage *)imageWithContentOfFile 為例:
圖片解碼是一個非常耗時的CPU操作柳爽,并且默認是在主線程進行的,所以當圖片較多時對性能會造成很大的影響主穗,特別是在快速滑動的列表上泻拦。
三、為什么要解壓縮
既然是耗時操作忽媒,那么是否可以避免解壓縮直接繪制圖片到屏幕上争拐,答案是否定的。圖片解壓縮的過程其實就是將圖片的二進制數(shù)據(jù)轉換成像素數(shù)據(jù)的過程晦雨,先了解一下位圖, 什么是位圖呢架曹?
圖像分為位圖和矢量圖。
矢量圖是根據(jù)幾何特性來繪制圖形闹瞧,矢量可以是一個點或一條線绑雄,文件占用空間較小,可自由無限制的重新組合 奥邮。
位圖也稱點陣圖像万牺,位圖使用我們稱為像素的一格一格的小點來描繪圖像。
位圖是一個像素數(shù)組, 每一個元素代表圖片中的一個點. 我們在程序中使用的PNG和JPEG 圖片就是位圖.
事實上洽腺,不管是 JPEG? 還是 PNG? 圖片脚粟,都是一種壓縮的位圖圖形格式。只不過 PNG? 圖片是無損壓縮蘸朋,并且支持 alpha 通道核无,而 JPEG? 圖片則是有損壓縮,可以指定 0-100% 的壓縮比.
在將磁盤中的圖片渲染到屏幕之前藕坯,必須先要得到圖片的原始像素數(shù)據(jù)团南,才能執(zhí)行后續(xù)的繪制操作,這就是為什么需要對圖片解壓縮的原因炼彪。
四吐根、強制解壓縮的原理
圖片的解壓縮不可避免,但是又不想讓它在主線程執(zhí)行辐马,會影響應用的響應性佑惠,就要有更好的解決方案。
當未解壓縮的圖片將要渲染到屏幕時,系統(tǒng)會在主線程對圖片進行解壓縮膜楷,而如果圖片已經(jīng)解壓縮了旭咽,系統(tǒng)就不會再對圖片進行解壓縮。因此赌厅,也就有了業(yè)內的解決方案穷绵,在子線程提前對圖片進行強制解壓縮。
而強制解壓縮的原理就是對圖片進行重新繪制特愿,得到一張新的解壓縮后的位圖仲墨。其中,用到的最核心的函數(shù)是 CGBitmapContextCreate
CG_EXTERN CGContextRef __nullable CGBitmapContextCreate(void * __nullable data, size_t width, size_t height, size_t bitsPerComponent, size_t bytesPerRow, CGColorSpaceRef __nullable space, uint32_t bitmapInfo) CG_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);
1)像素格式
位圖其實就是一個像素數(shù)組揍障,而像素格式則是用來描述每個像素的組成格式目养,它包括以下信息:
Bits per component :一個像素中每個獨立的顏色分量使用的 bit 數(shù);
Bits per pixel : 一個像素使用的總 bit 數(shù)毒嫡;
Bytes per row : 位圖中的每一行使用的字節(jié)數(shù)癌蚁。
對于位圖來說,像素格式并不是隨意組合的兜畸,目前只支持以下有限的17種特定組合:官方文檔
2)位圖的布局信息
像素格式是用來描述每個像素的組成格式的努释,比如每個像素使用的總bit數(shù)。而要想確保Quartz能夠正確解析這些bit所代表的含義咬摇,還需要提供位圖的布局信息 CGBitmapInfo:
包含了三方面信息:alpha的信息伐蒂、顏色分量是否為浮點數(shù)、像素格式的字節(jié)順序肛鹏。
CGImageAlphaInfo包含的信息:
(1)是否包含 alpha 逸邦;
(2)如果包含 alpha ,那么 alpha 信息所處的位置在扰,在像素的最低有效位缕减,比如 RGBA ,還是最高有效位健田,比如 ARGB ;
(3)如果包含 alpha 佛纫,那么每個顏色分量是否已經(jīng)乘以 alpha 的值妓局,這種做法可以加速圖片的渲染時間,因為它避免了渲染時的額外乘法運算呈宇。比如好爬,對于 RGB 顏色空間,用已經(jīng)乘以 alpha 的數(shù)據(jù)來渲染圖片甥啄,每個像素都可以避免 3 次乘法運算存炮,紅色乘以 alpha ,綠色乘以 alpha 和藍色乘以 alpha 。
3)參數(shù)選擇
函數(shù)的參數(shù)具體的選擇穆桂,官方文檔有推薦宫盔,如圖所示:
當沒有alpha信息時,選用 kCGImageAlphaNoneSkipFirst享完,當有alpha通道時選擇 kCGImageAlphaPremultipliedFirst灼芭,字節(jié)順序采用 kCGBitmapByteOrder32Host。
4)開源庫的實現(xiàn)
下圖為各開源庫圖片解碼時參數(shù)的選擇般又,其中YYKit 和 SDWebImage 采用相同的參數(shù)彼绷。
五、圖片縮略技術
將Data Buffers解碼到?Image Buffers是一個CPU密集型的操作茴迁。同時它的大小是和與原始圖像大小成比例寄悯,和 View 的大小無關。
如果一個瀏覽照片的應用展示多張照片時堕义,沒有經(jīng)過任何處理猜旬,就直接讀取圖片,然后來展示胳螟。那 Decode? 時昔馋,將會占用極大的內存和 CPU。而我們展示的圖片的 View 的大小糖耸,其實是完全用不到這么大的原始圖像的
圖像是每個應用程序不可缺少的一部分秘遏。尤其面對高精度大圖片的處理時,方式不當可能會出現(xiàn)OOM嘉竟。
首先要知道 什么是壓縮:
“壓” 指文件體積變小邦危,但是像素不變,長寬尺寸不變舍扰,那么質量可能下降
“縮” 指文件的尺寸變小倦蚪,也就是像素數(shù)減少,而長寬尺寸變小边苹,文件體積同樣會減小陵且。
1、圖像的壓處理:
圖片的壓處理个束,我們可以使用UIImageJPEGRepresentation或UIImagePNGRepresentation方法實現(xiàn)
2慕购、圖像的縮處理:
原圖大小為15.4MB,尤其測試條件單一茬底,結果僅供參考沪悲。
3、超大圖片處理
CATiledLayer?分片顯示阱表, iOS大圖展示的解決方法
六殿如、性能優(yōu)化
1贡珊、降采樣
2、子線程解碼和降采樣
3涉馁、使用Image Asset Catalogs
4门岔、合理的圖片格式和尺寸的選用
5、UITableViewDataSourcePrefetching
6谨胞、分片顯示
參考文章:
http://www.reibang.com/p/de7b6aede888
https://juejin.im/post/5b1a7c2c5188257d5a30c820
http://www.reibang.com/p/943dbe3ed608
https://honglu.me/2016/09/02/一張圖片引發(fā)的深思/
https://longtimenoc.com/archives/ios如何避免圖像解壓縮的時間開銷
http://blog.leichunfeng.com/blog/2017/02/20/talking-about-the-decompression-of-the-image-in-ios/
https://blog.csdn.net/y4x5m0nivsrjay3x92c/article/details/80327202
http://www.cocoachina.com/articles/25174