Xcode的Compress PNG Files作用分析

最近在工作中遇到一個PNG圖片最終渲染出來丟失了Alpha(透明度)的問題,在經(jīng)過不斷地查閱資料和思考后終于解決了這個問題要门,在這里想和大家分享一下過程中學習到的一些知識點。

問題背景

目前所做的項目是一個跨平臺渲染引擎廓啊,使用的是stb_image庫讀取圖片像素數(shù)據(jù)(以RGBA排列)欢搜,之后通過OpenGL的glTexImage2D生成紋理并渲染,iOS平臺使用EAGLLayer來顯示最后的渲染結(jié)果谴轮。

然而發(fā)現(xiàn)了放在Xcode工程下面的PNG圖片能夠正常的顯示炒瘟,而通過下載的PNG圖片卻出現(xiàn)了Alpha信息丟失的情況,如下所示分別是加載Xcode工程中的PNG圖片和加載通過下載的PNG圖片。

Xcode工程下的圖片
下載的圖片

那么為什么會從工程中讀取的PNG像素數(shù)據(jù)能正常顯示第步,而下載的PNG圖片卻丟失了Alpha信息呢疮装?我們發(fā)現(xiàn)在Xcode的Build Settings中有個和PNG相關(guān)的選項叫做Compress PNG Files,默認是開啟的粘都,我們嘗試著關(guān)閉這個選項廓推,發(fā)現(xiàn)再加載工程的PNG圖片也出現(xiàn)了Alpha信息丟失的情況了。那么問題就定位到了這個Compress PNG Files了翩隧,到底這個Compress PNG Files到底做了什么事情呢樊展?

關(guān)于PNG

首先我們來簡單看下PNG是啥,維基百科上面的定義是便攜式網(wǎng)絡(luò)圖形(英語:Portable Network Graphics堆生,縮寫:PNG)是一種無損壓縮的位圖圖形格式专缠,支持索引、灰度淑仆、RGB三種顏色方案以及Alpha通道等特性涝婉。

如果想更具體的了解PNG,可以看一下PNG文件結(jié)構(gòu)蔗怠。

關(guān)于Xcode 中的Compress PNG Files

Compress PNG Files從字面上簡單翻譯一下就是"壓縮PNG文件"的意思墩弯,但是當你把這個選項開啟之后會發(fā)現(xiàn)編譯之后的ipa包不但沒有減小,反而增大了寞射,這是怎么回事呢最住?說好的壓縮呢?這個Compress PNG Files到底做了啥事呢怠惶?

當 Xcode 優(yōu)化一個 PNG 文件的時候涨缚,它將 PNG 文件變成一個從技術(shù)上講不再是有效的PNG文件。但是 iOS 可以讀取這種文件策治,并且這比解壓縮正常的 PNG 文件更快脓魏。

它做了以下幾件事情:

  • 額外關(guān)鍵塊(CgBI)
  • byteswapped(RGBA - > BGRA)像素數(shù)據(jù),大概是用于幀緩沖的高速直接blitting
  • 從IDAT塊中刪除了zlib頁眉通惫,頁腳和CRC
  • 預乘alpha(顏色'=顏色* alpha / 255

明顯的改動就是在IHDR塊之前插入了CgBI塊來表示這種格式茂翔,CgBI文件格式因其額外標題而得名,是Apple對PNG圖像格式的專有擴展履腋,同時修改了IDAT塊中的數(shù)據(jù)珊燎,原因就是在iPhone中惭嚣,圖像是以BGRA格式在內(nèi)存中處理的,到這里就可以發(fā)現(xiàn)悔政,其實這個所謂的Compress PNG Files晚吞,最主要的目的并不是壓縮圖片的大小,而是將圖片轉(zhuǎn)換成iPhone能更方便處理的格式谋国,加快處理速度槽地。

這里我們重點看下有一個和Alpha相關(guān)的操作預乘Alpha,那么什么是預乘Alpha呢芦瘾,這個操作的作用是什么呢捌蚊?

關(guān)于預乘透明度(Premultiplied Alpha)

簡單地說,比如常規(guī)的半透明半純紅色圖像RGBA歸一化值為(0.5, 0, 0, 0.5)近弟,由預乘透明度圖像方式存儲則RGBA值為(0.25, 0, 0, 0.5)缅糟。由此可知,即每個顏色分量都乘以alpha通道值作為結(jié)果值:

`color.rgb *= color.alpha`

為什么要引入預乘呢祷愉?

這種做法可以加速圖片渲染的速度溺拱,如果你的顏色分量是已經(jīng)經(jīng)過預乘處理過的,則在渲染時可以直接使用而不需要再進行3次的乘法運算谣辞,從而提高渲染效率迫摔。此外,實際上它還解決了以下幾個問題泥从。

  • 解決紋理比例縮放映射產(chǎn)生的顏色錯誤問題
  • 可以和其他紋理一起正尘湔迹混合而不打破批次渲染

關(guān)于iOS平臺下的渲染

iOS平臺中如果使用CAEAGLLayer對象作為頂部圖層并且與它下面的圖層進行顏色混合,那么渲染緩存的顏色數(shù)據(jù)必須用一種預先乘好的premultiplied)alpha格式躯嫉。而讀取出來的像素數(shù)據(jù)沒有經(jīng)過預乘Alpha操作纱烘,所以造成了渲染結(jié)果丟失了Alpha的現(xiàn)象。

綜上祈餐,所在我們讀取出來的RGB值分別乘上Alpha后就能夠正常渲染了:

uint8_t alpha;
     for (int y = 0; y < p->s->img_x; y++) {
         for (int x = 0; x < p->s->img_y; x++) {
             alpha = *(pixels + 3); // 取出Alpha值
             *pixels = round(*pixels * alpha / 255.f); // R * Alpha
             *(pixels + 1) = round(*(pixels + 1) * alpha / 255.f); // G * Alpha
             *(pixels + 2) = round(*(pixels + 2) * alpha / 255.f); // B * Alpha
             pixels += 4;
         }
     }

經(jīng)過手動乘上Alpha處理后的圖片:

處理后的下載圖片
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末擂啥,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子帆阳,更是在濱河造成了極大的恐慌哺壶,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蜒谤,死亡現(xiàn)場離奇詭異山宾,居然都是意外死亡,警方通過查閱死者的電腦和手機鳍徽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門资锰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人阶祭,你說我怎么就攤上這事绷杜≈备眩” “怎么了?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵鞭盟,是天一觀的道長圾结。 經(jīng)常有香客問我,道長懊缺,這世上最難降的妖魔是什么疫稿? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任培他,我火速辦了婚禮鹃两,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘舀凛。我一直安慰自己俊扳,他們只是感情好,可當我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布猛遍。 她就那樣靜靜地躺著馋记,像睡著了一般。 火紅的嫁衣襯著肌膚如雪懊烤。 梳的紋絲不亂的頭發(fā)上梯醒,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天,我揣著相機與錄音腌紧,去河邊找鬼茸习。 笑死,一個胖子當著我的面吹牛壁肋,可吹牛的內(nèi)容都是我干的号胚。 我是一名探鬼主播,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼浸遗,長吁一口氣:“原來是場噩夢啊……” “哼猫胁!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起跛锌,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤弃秆,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后髓帽,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體驾茴,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年氢卡,在試婚紗的時候發(fā)現(xiàn)自己被綠了锈至。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡译秦,死狀恐怖峡捡,靈堂內(nèi)的尸體忽然破棺而出击碗,到底是詐尸還是另有隱情,我是刑警寧澤们拙,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布稍途,位于F島的核電站,受9級特大地震影響砚婆,放射性物質(zhì)發(fā)生泄漏械拍。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一装盯、第九天 我趴在偏房一處隱蔽的房頂上張望坷虑。 院中可真熱鬧,春花似錦埂奈、人聲如沸迄损。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽芹敌。三九已至,卻和暖如春垮抗,著一層夾襖步出監(jiān)牢的瞬間氏捞,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工冒版, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留液茎,地道東北人。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓壤玫,卻偏偏與公主長得像豁护,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子欲间,可洞房花燭夜當晚...
    茶點故事閱讀 45,512評論 2 359