PNG格式圖片原理

轉載請註明出處:http://blog.csdn.net/asdzheng/article/details/51476818

本篇文章翻譯自谷歌出的優化視頻裏面的光頭佬(Colt McAnlis),原文地址需翻牆,以下正文:

便攜式網絡圖型( Portable Network Graphics [PNG])在過去幾十年已經變成App開發裏重要的組成部分。它廣泛的運用在遊戲開發、網頁開發和Android開發裏,但也可能被大量的濫用。

正如我之前討論的那樣,PNG是一個不錯和高分辨率的圖片格式,但也意味着對於數據壓縮率來說我們有很多的提高空間。在探討怎麼壓縮PNG文件前,我們首先得知道PNG格式的原理。

壓縮原理

PNG的壓縮過程是完全無損的,壓縮過的文件可以準確的還原出原圖,這要分兩個階段完成:推斷(又稱過濾[filtering])和壓縮。

1. 過濾

差分編碼(Delta encoding)是最強大的數字壓縮法之一。原理是根據前一個數據的值將後面的值替換成其他值,例如:

[2,3,4,5,6,7,8]可以變成[2,1,1,1,1,1,1],算法是
[2, 3-2=1, 4-3=1, 5-4=1, 6-5=1, 7-6=1, 8-7=1]

這樣看就很明顯了,如果你的數據是線性相關的(線性相關的意思是,一組數據裏的前後值都差別不大,或者具有相關性),就可以把你的數據集轉換成一組重複的、低的值,這樣的值更容易被壓縮。

PNG格式使用了差分編碼(Delta encoding)裏的過濾。原理是,對於每一行的像素,一個當前的像素都跟它的左邊像素、上邊的像素和左上角的像素有關係。



舉個例子,如果我們要編碼一個給定的像素通過它與A和B平均值的差異(X-(A+B)/2),那麼我們將得到:



我們使用了ABC去推斷出X的值,然後我們將X替換成更小的值。

需要注意的是,每一行的像素都有可能不同,PNG允許5種不同的推斷算法,它們是:

  • 不過濾
  • X-A
  • X-B
  • X-(A+B)/2(又稱平均值)
  • Paeth推斷(A,B,C的線性方法,這種比較複雜可看W3C的規定)

這裏說明一下,每一行像素應該選擇最適合的過濾算法,這樣才能得到最少數量的特殊值。下面是我們關於不同模式的例子:



需要注意的是這些過濾器都是對每一行像素起作用而不是單個像素。也就是說過濾器會對每一行的紅色像素起作用,再分別對藍色的像素起作用。(儘管同一行的像素會用同樣的過濾器)

現在PNG格式在選擇過濾器上有一些不錯的方法,開發人員根據對不同類型圖片的使用經驗摸索出一些不錯的規律。例如對於調色板的圖像(palette images)和8位的灰色圖就不要過濾。對於其他圖片,就選擇那種能最大限度地減少絕對差異總和的值的過濾器:將所有值的絕對值相加,然後對比不同過濾器得到的值,選擇那個相加起來得到最小值的過濾器。

2. 壓縮

在一行像素被過濾後,就會執行DEFLATE壓縮,這是LZ77延伸出來的一種算法。該算法結合了LZ77編碼和哈夫曼編碼,它跟PKWARE、PKZIP、GZIP等差不多相同。這種實現方式雖然是現成的,但用在壓縮圖片數據上,還是有一些需要注意的點:

  1. Deflate算法只能匹配3到258個之間符號,所以最大的壓縮比只能到1035:1;

  2. 如果匹配到的符號小於3,那麼你會產生一些額外的開銷來表示這些符號;

上面的這兩點意味着你的圖片大小會受到每一行像素的匹配程度影響。

你可以看一下面這兩張圖片,左邊那張270x90的圖只有20k,而右邊那張270x92的圖是左邊那張的2倍大。



這似乎不符合邏輯,一張圖片多540像素在壓縮率上就少了一半。不過我們看仔細點,就能知道原因了,下面這張圖表示壓縮器怎麼去壓縮一個給定的像素的。深藍色代表壓縮率很高的區域,黃色/紅色代表沒怎麼被壓縮的區域。



這是怎麼出現的呢,原因是小圖的每一行像素的匹配度更高,那麼它的壓縮率就更高。你要是調整了大小,匹配度一變化,這種情況就有可能出現。一些潛在的匹配對象不在壓縮區域裏,它們沒有匹配到,這就又可能導致出現一張大圖。

如果你想知道你的PNG圖片的壓縮率如何,可以下個PNGThermal看一下。

對於格式的理解

值得注意的是,PNG格式不僅僅只有在過濾和壓縮兩個層面,PNG還是一種非常易擴展的容器格式,它可以支持各種類型的圖片和附加數據。

首先PNG文件格式裏面包含不同的區塊(chunks),各個區塊帶有不同類型的數據。例如,PNG的Header chunks(頭部塊)就包含有圖片的寬度、高度、位的深度和顏色類型;

圖片的數據塊(Image data chunk)包含了實際的圖像信息(數據塊可以有多個)。除此之外有一個單獨的區塊來記錄顏色調色板(palette chunk)。最後就是圖片的結束區塊了(end-of-file chunk)。上面的這些都是主要區塊,但也有一大堆附加區塊,例如:

  • 默認的背景色
  • 色度如何顯示白點上的座標
  • 圖像γ數據塊
  • 文本數據,語言或元數據信息
  • 顏色空間信息
  • 立體圖像數據
  • 圖像最後修改時間數據塊
  • 圖像透明數據塊

上面的這些區塊是你特別需要注意的地方,因爲很多垃圾信息是在圖片編輯軟件編輯後添加進去的。舉個例子,你在Photoshop保存了一張PNG格式圖片,這行圖片裏就會有一個區塊記錄着”這張圖片是由photshop創建的”。這樣的信息對於一張顯示給人看的圖片並沒什麼鳥用,但它還是會包含在圖片裏。因此,刪除沒有的區塊是減少文件大小的關鍵。下面是一張16X16像素的圖片,左邊那張是Photoshop保存的普通圖片,右邊那張是用了photoshop的”導出web格式”選項保存的圖片,這個選項會去掉了所有的附加信息。



像素格式

PNG也支持很多種類型的像素格式,你可以選擇一種最佳的:

  • Indexed(索引色) = 1個頻道,可以爲1,2,4,8 bpc
  • Grayscale(灰度) = 1個頻道,可以爲1,2,4,8,16 bpc
  • Gray+Alpha(帶透明通道的灰度) = 2個頻道,可以爲8或16 bpc
  • Truecolor(RGB 真彩色) = 3個頻道,可以爲8或16 bpc
  • RGBA(RGBA 帶透明通道的真彩色) = 4個頻道,可以爲8或16 bpc

像素格式是圖片作者自己選擇,我沒多大的興趣討論,只要你確保選擇正確的像素格式,不要把一張灰度圖片保存爲RGB/RGBA就行了。

GIF和PNG誕生的故事

在今天,當你打開一個大量內容的網頁時,圖片是最大的承載者。(儘管有一種觀點認爲視頻將稍後趕超)

但真正讓人感興趣的是,儘可能多的壓縮可以解決一些網頁的臃腫問題,每個人都應該着手去壓縮圖片。

先讓我們回到1985年,當時Unisys公司申請了LZW壓縮算法專利,沒人對它感興趣。幾年後,CompuServe公司發明了89A格式(也就是後來的GIF格式),他們用了LZW算法作爲主要實現方式,沒有意識到LZW是受專利保護的。而Unisys公司並沒在意,直到1993年,網景瀏覽器增加了對IMG HTML標籤的支持,並將89a格式一併支持。那一年動圖就風靡於互聯網上,之後Unisys就開始執行專利保護。1994年12月CompuServe和Unisys在法院上達成協議,Unisys將對所有使用89a格式圖片的軟件收取專利許可費。在這個協議宣佈後的幾個月裏,一羣工程師開發了一種全新的免專利的格式,這就是大家所熟知的PNG格式。

2004年,LZW算法專利終於過期,但在這10年裏,GIF/PNG圖片格式之爭一直是網絡的熱點話題。

尾聲

PNG是一種非常靈活和強大的圖片格式類型,支持透明度的能力也使它在網頁流行起來。但它並不適用於任何一種情況,在工作上使用最適用你的工具纔是硬道理。如果你的圖片是攝影作品且你對無損沒有要求的話,JPG
或其他一些有損的處理方法可能更有效。不過你要是需要一種更小的像素格式,或者需要支持透明通道,那麼PNG就絕對要比JPG好。

如果你對PNG編碼器的核心技術感興趣的話,可以看看這個叼炸天的gist,僅僅40行代碼就把它搞定。

當然,如果你用WebP格式,小容量和無損都不是問題。不過,那就是另外一篇文章了。

一些翻譯時候找的參考資料:

淺談PNG無損優化
PNG格式文件分析
PNG維基百科
圖片原理與優化

由於文人水平有限,如有翻譯得不好的地方,請留言討論。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章