PNG格式的壓縮算法原理

PNG格式的壓縮算法原理

在過去的幾十年裡,PNG(便攜式網絡圖形)已經成為應用程序開發的主要部分。從遊戲開發到web開發,再到Android開發,它無處不在,這意味著它被廣泛採用,但也有被廣泛濫用的機會。

正如我之前所討論的,PNG提供了一種不錯的高分辨率圖像格式,但這意味著在數據壓縮方面還有很大的改進空間。但是在我們開始討論如何進一步壓縮PNG文件之前,我們必須先討論格式是如何工作的。

瞭解壓縮

PNG的壓縮過程是完全無損的;這意味著壓縮文件可以準確地重建源圖像。分兩個階段完成:預測(又名過濾)和壓縮。

1 過濾器(預測)

增量編碼是最強大的數字壓縮方法之一,基本思想是您可以將任何值表示為與前一個值不同的值,所以:

[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格式使用稱為“filtering”的delta編碼格式。基本上,對於每一個像素掃描線,當前像素都是按照與左邊像素、上面像素和上面左側像素的某種關係進行編碼的。

PNG格式的壓縮算法原理

例如,如果我們用A和B的平均值的差值(X-(((A + B)/2)來編碼一個給定的像素,那麼我們會得到:

PNG格式的壓縮算法原理

過濾器使用用ABC來預測x的值,使用預測值和實際值之間的差來代替X的值。

現在,值得注意的是,每一行只有很小的差異,PNG允許選擇五種模式中的一種,每行:

  1. 不使用filtering
  2. X和A的差
  3. X和B的差值
  4. X與(A + B)/2的差值(即平均值)
  5. Paeth預測器(A,B,C的線性函數)

這裡的意圖是,每一行都可以為自己選擇最好的filtering方法,這樣就可以產生最少的唯一符號(重複符號越多,壓縮效果越好)。這是我們每個模式的原始例子:

PNG格式的壓縮算法原理

需要注意的是,這些過濾器是按通道而不是按像素設置的。這意味著該過濾器應用於掃描線的一個像素的所有紅色值,然後單獨應用於掃描線的所有藍色值(儘管一行中的所有顏色將使用相同的過濾器)。

PNG格式有一些很好的方式來選擇在一個通道上使用哪個過濾器;雖然蠻力是最直接的,但結果並不理想,相反,開發人員在不同的圖像類型上進行了試驗,並提出了一些接近最優的經驗法則:比如對調色板圖像以及低於8位的灰度圖像不使用過濾器;對於其他的圖像,選擇最小化絕對差和的濾波器;不是使用256模除(%),而是使用標準的帶符號數學,然後獲取abs值,並將它們全部添加到給定行中,然後比較其他篩選器類型的和,選擇給出最小和的過濾器。

2 壓縮(DEFLATE)

一旦在掃描線上進行了濾波,它將傳遞給LZ77算法的變種,稱為DEFLATE;該算法結合了LZ77編碼和一個霍夫曼編碼器。它與PKWARE、PKZIP、GZip等壓縮器幾乎相同。這個實現是開箱即用的標準,但是對於圖像數據有一些有趣的注意事項:

  1. Deflate限制3到258個符號之間的匹配長度;這使得可以想象的最大壓縮比約為1032:1。
  2. 如果匹配的符號小於3個,那麼您將產生一些開銷(overhead)來表示符號

這兩個的結果,意味著如果在掃描線中找到匹配項,圖像的大小可能會有影響。

考慮下面這張圖,270x90版本只有20k,但是270x92版本大了2倍。

PNG格式的壓縮算法原理

從邏輯上看,這似乎是錯誤的。在一張圖片上增加540個像素應該不會導致2倍的壓縮膨脹。然而,當我們仔細觀察時,我們可以看到為什麼會發生這種情況,下面的圖像熱圖表示給定像素的壓縮程度。深藍=高度壓縮,黃色/紅色=非高度壓縮(壓縮率不高)

PNG格式的壓縮算法原理

之所以發生這種情況,雖在較小的圖像中,掃描線有更多的匹配,因此有更好的壓縮率。但是,稍微調整一下大小,就會改變可能出現的匹配類型,一些可能的匹配對象現在在我們的LZ窗口之外,因此沒有被匹配,導致文件變大。

至於LZ77和哈夫曼編碼,話題太大,本文就不再展開,相關的文章很多,讀者可以自行搜索。


分享到:


相關文章: