iOS中圖片渲染的流程

一. 圖像從文件到屏幕過程

CC.圖片渲染原理.png

接下來我們了解一下CPU和GPU在渲染的過程中的分工是什么?

CPU(中央處理器)

1. 計(jì)算frame.

2.解壓縮圖片.

3. 將需要繪制的紋理圖片通過數(shù)據(jù)總線交給GPU.

GPU(圖形處理器)

1. 頂點(diǎn)的計(jì)算和變換.

2. 像素點(diǎn)的填充計(jì)算和紋理混合.

3. 渲染到幀緩沖區(qū).

圖片顯示到屏幕是CPU和GPU共同完成的


二. 圖片加載的工作流程

1. 假設(shè)我們是用[UIImage imageWithContensOfFile:@"xxx.png"] 方法創(chuàng)建對(duì)象來加載一張圖片, 這個(gè)時(shí)候只是創(chuàng)建一個(gè)管理圖片壓縮二進(jìn)制數(shù)據(jù)的image對(duì)象, 并沒有對(duì)圖片進(jìn)行解碼.

2. 把UIImage對(duì)象賦值給UIImageView, 此時(shí)一個(gè)隱式的CATransaction捕獲到的UIImageView圖形樹的變化.

3. 在線程的下一個(gè)運(yùn)行循環(huán)(Runloop)到來時(shí), Core Animation提交了這個(gè)隱式的transaction, 這個(gè)過程會(huì)對(duì)圖片進(jìn)行copy操作.這個(gè)copy操作可能會(huì)涉及以下部分或全部步驟:

分配內(nèi)存緩沖區(qū)用于管理文件 IO 和解壓縮操作聚凹;

將文件數(shù)據(jù)從磁盤讀到內(nèi)存中;

將壓縮的圖片數(shù)據(jù)解碼成未壓縮的位圖形式,這是一個(gè)非常耗時(shí)的 CPU 操作绣的;

最后Core Animation中CALayer使用未壓縮的位圖數(shù)據(jù)渲染UIImageView的圖層速客。

CPU計(jì)算好圖片的Frame,對(duì)圖片解壓之后.就會(huì)交給GPU來做圖片渲染.

4.渲染流程

GPU獲取到圖片的坐標(biāo).

將坐標(biāo)交給頂點(diǎn)著色器.(頂點(diǎn)計(jì)算)

將圖片光柵化.(根據(jù)頂點(diǎn)坐標(biāo)轉(zhuǎn)化成片元, 片元的每一個(gè)元素對(duì)應(yīng)幀緩沖區(qū)的一個(gè)像素點(diǎn), 并且分配顏色值和深度值到各個(gè)區(qū)域, 光柵化是一個(gè)將模擬信號(hào)轉(zhuǎn)化為離散信號(hào)的過程.)

片元著色器計(jì)算.(計(jì)算屏幕上每個(gè)像素點(diǎn)最終顯示的顏色值)

從幀緩沖區(qū)渲染到屏幕上

我們提到了圖片解碼是一個(gè)非常好使的CPU操作, 并且默認(rèn)是在主線程進(jìn)行的, 所以當(dāng)圖片較多時(shí)對(duì)性能會(huì)造成很大的影響. 特別是快速滑動(dòng)的列表上.


三. 為什么要解壓縮圖片

既然是耗時(shí)操作, 是否可以避免解壓縮直接將圖片顯示到屏幕上呢? 答案是否定的. 要想弄明白這個(gè)問題, 我們應(yīng)該先了解一下位圖, 什么是位圖呢?

其實(shí), 位圖是一個(gè)像素?cái)?shù)組, 每一個(gè)元素代表圖片中的一個(gè)點(diǎn). 我們?cè)诔绦蛑惺褂玫腜NG和JPEG圖片就是位圖.

事實(shí)上戚篙,不管是 JPEG 還是 PNG 圖片,都是一種壓縮的位圖圖形格式溺职。只不過 PNG 圖片是無損壓縮岔擂,并且支持 alpha 通道,而 JPEG 圖片則是有損壓縮浪耘,可以指定 0-100% 的壓縮比.

因此智亮,在將磁盤中的圖片渲染到屏幕之前,必須先要得到圖片的原始像素?cái)?shù)據(jù)点待,才能執(zhí)行后續(xù)的繪制操作阔蛉,這就是為什么需要對(duì)圖片解壓縮的原因。


四.解壓縮原理

既然圖片的解壓縮不可避免癞埠,而我們也不想讓它在主線程執(zhí)行状原,影響我們應(yīng)用的響應(yīng)性聋呢,那么是否有比較好的解決方案呢?

我們前面已經(jīng)提到了颠区,當(dāng)未解壓縮的圖片將要渲染到屏幕時(shí)削锰,系統(tǒng)會(huì)在主線程對(duì)圖片進(jìn)行解壓縮,而如果圖片已經(jīng)解壓縮了毕莱,系統(tǒng)就不會(huì)再對(duì)圖片進(jìn)行解壓縮器贩。因此,也就有了業(yè)內(nèi)的解決方案朋截,在子線程提前對(duì)圖片進(jìn)行強(qiáng)制解壓縮蛹稍。

而強(qiáng)制解壓縮的原理就是對(duì)圖片進(jìn)行重新繪制,得到一張新的解壓縮后的位圖部服。其中唆姐,用到的最核心的函數(shù)是 CGBitmapContextCreate:

解壓縮代碼步驟如下(YYImage實(shí)現(xiàn)):

CGBitmapInfobitmapInfo = kCGBitmapByteOrder32Host;

CGContextRef context =CGBitmapContextCreate(NULL, width, height,8,0, YYCGColorSpaceGetDeviceRGB(), bitmapInfo);//創(chuàng)建一個(gè)位圖上下文

if(!context)returnNULL;

CGContextDrawImage(context,CGRectMake(0,0, width, height), imageRef);//decode 將原始位圖繪制在上下文中

CGImageRef newImage =CGBitmapContextCreateImage(context);//創(chuàng)建一個(gè)新的解壓縮后的位圖

CFRelease(context);

它接受了一個(gè)原始位圖imageRef, 最終返回了一個(gè)新的解壓縮位圖newImage.

事實(shí)上,SDWebImage 中對(duì)圖片的解壓縮過程與上述完全一致廓八,只是傳遞給?CGBitmapContextCreate?函數(shù)的部分參數(shù)存在細(xì)微的差別.

性能對(duì)比:

在解壓PNG圖片,SDWebImage>YYImage

在解壓JPEG圖片,SDWebImage<YYImage


結(jié)論:

1. 圖片文件只有在確認(rèn)要顯示時(shí)才進(jìn)行解壓縮操作, 因?yàn)槭且粋€(gè)耗時(shí)的CPU操作, 解壓縮后會(huì)進(jìn)行緩存, 不會(huì)對(duì)其重復(fù)解壓縮.

2. 圖片渲染的過程: 讀取文件 -> 計(jì)算frame ->圖片解碼 ->解碼后通過數(shù)據(jù)總線交給GPU ->GPU獲取圖片frame后進(jìn)行頂點(diǎn)變換計(jì)算 ->光柵化 ->根據(jù)紋理坐標(biāo)獲取每一個(gè)像素點(diǎn)的顏色值 -> 交給幀緩沖區(qū) ->渲染到屏幕上.

SDWebImage

YYImage

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末奉芦,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子剧蹂,更是在濱河造成了極大的恐慌声功,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宠叼,死亡現(xiàn)場離奇詭異先巴,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)车吹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門筹裕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人窄驹,你說我怎么就攤上這事朝卒。” “怎么了乐埠?”我有些...
    開封第一講書人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵抗斤,是天一觀的道長。 經(jīng)常有香客問我丈咐,道長瑞眼,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任棵逊,我火速辦了婚禮伤疙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己徒像,他們只是感情好黍特,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著锯蛀,像睡著了一般灭衷。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上旁涤,一...
    開封第一講書人閱讀 51,679評(píng)論 1 305
  • 那天翔曲,我揣著相機(jī)與錄音,去河邊找鬼劈愚。 笑死瞳遍,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的造虎。 我是一名探鬼主播傅蹂,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼纷闺,長吁一口氣:“原來是場噩夢啊……” “哼算凿!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起犁功,我...
    開封第一講書人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤氓轰,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后浸卦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體署鸡,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年限嫌,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了靴庆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡怒医,死狀恐怖炉抒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情稚叹,我是刑警寧澤焰薄,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站扒袖,受9級(jí)特大地震影響塞茅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜季率,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一野瘦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧飒泻,春花似錦鞭光、人聲如沸啊掏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽迟蜜。三九已至,卻和暖如春啡省,著一層夾襖步出監(jiān)牢的瞬間娜睛,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來泰國打工卦睹, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留畦戒,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓结序,卻偏偏與公主長得像障斋,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子徐鹤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355