PNG圖片原理二三事

南華Coder發表於2019-08-25

Questions

  • PNG圖片結構是什麼樣的?

  • PNG規範中定義PNG是無失真壓縮(Lossless Compression)的圖片格式,那麼PNG支援有失真壓縮嗎?

一、PNG概述

1、PNG簡介
  • PNG(Portable Network Graphics,行動式網路圖型)是一種無失真壓縮的圖片格式,支援索引、灰度、RGB三種顏色方案以及Alpha通道等特性(iOS的絕大部分切圖都是PNG格式)。
  • PNG圖片主要有三個型別,分別為 PNG 8、 PNG 24 和 PNG 32;其中 PNG 8支援兩種不同的透明形式,索引透明和Alpha透明、 PNG 24不支援透明和 PNG 3224位基礎上增加了8bits透明通道。
  • PNG規範可見: Portable Network Graphics (PNG) Specification (Second Edition)
2、PNG結構
  • PNG結構如下: header,chunk,chunk,chunk….chunk; 其中,header代表png圖片的頭,由固定的8個位元組組成,內容是:89 50 4E 47 OD 0A 1A 0A;而chunk代表png圖片的資料塊。

PNG編碼結構

二進位制檢視PNG圖片

3、PNG的資料塊
  • PNG的資料塊由四個資料域組成:長度、資料塊型別碼、資料塊資料和迴圈冗餘校驗;而資料塊分成兩種:關鍵資料塊可選資料塊,關鍵資料塊包括:檔案頭資料塊調色盤資料塊影像資料塊影像結束資料塊
  • 真正和圖片展示有關是影像資料塊中的資料塊區域
  • IHDR資料塊(檔案頭資料塊):一個PNG圖片中只能有一個IHDR資料塊,它是PNG圖片中第一個資料塊,共13個位元組(0000 000d),具體資訊如下:
域名稱 位元組數(bytes) 說明
width 4 影像寬度,以畫素為單位
height 4 影像高度,以畫素為單位
bit depth 1 表示一個通道的總位數
color type 1 顏色型別. [0]:灰度影像, 1,2,4,8或16 [2]:真彩色影像,8或16 [3]:索引彩色影像,1,2,4或8 [4]:帶α通道資料的灰度影像,8或16 [6]:帶α通道資料的真彩色影像,8或16
compression method 1 壓縮方法(LZ77派生演算法)
filter method 1 濾波器方法
Interlace method 1 隔行掃描方法. 0:非隔行掃描 1: Adam7(7遍隔行掃描方法)
  • 0000 000d是iHDR資料塊的長度,為13,4948 4452是資料塊的type,為IHDR,之後緊跟著是data, 0000 02bc是圖片的寬度,0000 03a5是高度,08是bit depth,也就是一個通道是8位,06是color type,這裡表示圖片是真彩色,00是壓縮方法,png中目前只有一種,也就是LZ77派生的演算法,00是濾波器方法,表示不使用,00是隔行掃描方法,代表不掃描。8f 1434 a4是四個位元組的CRC校驗碼。
  • IDAT資料塊(影像資料塊):存放的就是影像的一個個畫素,一張影像中可以存在多個IDAT資料塊,這裡的資料會被隔行掃描方法(Interlace method)濾波器(filtering)壓縮演算法(compression)處理。
  • IEND資料塊(影像結束資料塊)、PLTE資料塊(調色盤資料塊,在IDAT資料塊之前),介紹略。
4、總結
  • 通過了解PNG的結構可以知道,減少PNG圖片大小可以通過去除PNG檔案中不需要的資訊,或 選擇正確的PNG格式(如,如果圖片中沒有Alpha通道,那麼就應當使用PNG 24,而不是使用PNG 32。類似,如果是灰度的圖片,那麼應當使用PNG 8)

二、PNG的壓縮原理

1、無失真壓縮 VS 有失真壓縮
  • 無失真壓縮(Lossless Compression):資料壓縮格式方法之一,指資料經過壓縮後,資訊不受損失,還能完全恢復到壓縮前的原樣。
  • 有失真壓縮(Lossy compression):資料壓縮格式方法之一,指資料經過壓縮、解壓的資料會與原始資料不同但是非常接近。
  • 無失真壓縮和有失真壓縮是相對的,有失真壓縮將次要的資訊資料捨棄,犧牲一些質量來減少資料量、提高壓縮比。
  • PNG壓縮過程分為兩個階段:Prediction(預解析) 和 Compression(壓縮)

PNG圖片壓縮

2、PNG壓縮之Prediction
  • 簡單理解:在這個階段,對圖片做一些預處理,方便後續的壓縮處理;

  • 每次會處理圖片中一行的資料,首先通過Filter處理這一行當中每一個的畫素點中每條通道的值,然後交由差分處理器來重新計算該通道的值。

  • 差分處理器會根據這個畫素點上通道和之前或者之上畫素點對應通道值之間的差異,進行差分編碼,也就是說,如果原本相鄰畫素點之間通道的值之間很接近,那麼我們就會獲得很多的1,0,-1這種很小的值。(差分編碼器比較的是畫素點之間對應通道的值,而並不是整個畫素點)

  • 整個Prediction階段的目的,也就是選擇合適的差分處理器,讓最終的編碼結果出現儘可能多的零值和重複值,這一結果將會影響到Compression階段的壓縮率。

3、PNG壓縮之Compression
  • Prediction處理完畢之後,再將這一轉換的結果輸出給DeflateDeflate執行真正的壓縮操作,它會通過LZ77Huffman對影像進行編碼,最後將處理之後的結果儲存。在Compression階段,它最終的壓縮率會受到兩方面的影響:

    • Prediction 的處理結果:對於顏色相近的區域,也就是有很多零值的區域,那麼壓縮率將會更高,而如果顏色之間差異很大,那麼壓縮效果就差很多。

    • Deflate 每一行的匹配情況:整個處理過程是按行來處理的。而在處理每一行的資料時,Deflate把處理的符號數限制為3 ~ 258,也就是說,最大的壓縮率為1032:1,當出現符號數小於3個時,那麼就有可能出現無法匹配的情況,因此,對於圖片寬度的改變將有可能影響最終壓縮的效果。

4、總結
  • 從上述內容可以知道,減少PNG的圖片大小,可以通過PNG壓縮優化,壓縮優化有兩個方向:
    • 優化差分編碼器,使得經過差分編碼後的影像有儘可能多的零值和相同的值
    • 優化Deflate的演算法,獲得更高的壓縮率

三、PNG的有失真壓縮方案

1、概述
  • 目前大部分PNG的壓縮採用基於LZ77派生演算法,使得它壓縮比率更高,生成的檔案體積更小,並且不損失資料【無失真壓縮】。
  • 但是有些大神不能接受無失真壓縮的壓縮率,設計並實現了有失真壓縮演算法,並在工程中得到了應用。
2、TinyPNG
  • 這是一個提供PNG有失真壓縮的平臺,地址:tinypng.com/

  • 從官網公開的資訊來看,TinyPNG主要是使用Quantization的技術,通過合併圖片中相似的顏色,通過將 24 位的 PNG 圖片壓縮成小得多的 8 位色值的圖片,並且去掉了圖片中不必要的 metadata(後設資料,從 Photoshop 等工具中匯出的圖片都會帶有此類資訊),這種方式幾乎能完美支援原圖片的透明度。

  • TinyPNG沒有公開他們使用的PNG有失真壓縮演算法。

3、pngquant演算法及其應用
  • 著名的PNG有失真壓縮演算法,詳細介紹地址在:pngquant.org/

mgod3T.jpg

  • ImageAlpha和PNGyu等軟體都採用了pngquant演算法;甚至有猜測,TinyPNG可能綜合利用了pngquant、optipng、advpng,才獲得很好的壓縮效果。

mgoX28.jpg

  • pngquant演算法的核心:通過Vector Quantization (向量量化)減少圖片中顏色的種類

    • 如果影像中的顏色種類小於256,那麼我們可以把它轉換為索引PNG格式,而如果圖片原本的顏色大於256種,那麼可以通過向量量化的方法來建立一個索引PNG格式。
    • 在向量量化的過程中,會把所有的畫素基於它們之間顏色的相似程度進行分組,一個組內畫素的顏色會比較接近。之後根據組內的所有顏色,計算出一箇中心點顏色,組內的所有顏色會被替換成為該中心點的顏色。
    • 向量量化會通過將相近顏色替換成同一種顏色的方法,來減少圖片中顏色的種類,因此有可能會使得圖片失真。
  • 使用有失真壓縮方案,需要在圖片質量和大小之間取一個平衡點。

參考

相關文章