1. 程式人生 > >影象優化原理

影象優化原理

我們都喜歡有圖片的網頁,圖片很美好,很有趣,同時它涵蓋了豐富的資訊。所以,在載入網頁時,大部分流量被影象資源所佔據(平均60%,資料可能不準確)。

影象資源不只佔用網路資源,它也會佔用網頁中大量的視覺空間。所以影象渲染的速度會直接影響使用者體驗。影象優化其實就是最大限度地減少影象的位元組數,從而最大化地縮減網路資源佔用,使瀏覽器下載速度變的更快。下載速度越快,在螢幕上渲染的時間就越早,所以視覺上就會有一個更好的體驗。

當然,優化影象最佳的方式就是不用影象,例如使用CSS效果(漸變,陰影,圓角等)代替影象。使用CSS比同等視覺效果的影象資源的位元組數要小非常多,這是毋庸置疑的。另一個好處是CSS不受解析度影響,使用CSS渲染出的視覺效果可以在任何解析度和縮放級別下始終清晰地顯示。

但必須使用影象資源時,對影象進行合理的優化將對效能有著至關重要的影響。

本文不會介紹如何進行影象優化,有大量線上工具和開源專案供我們使用,使用起來非常的簡單。本文將重點介紹影象優化的原理。

首先,本文會介紹兩種影象資源:向量圖與柵格圖(點陣圖),並分別介紹優化它們的原理。隨後介紹無失真壓縮與有失真壓縮以及它們的區別。在本文的最後,我們會介紹什麼是高解析度螢幕。

希望通過本篇文章的介紹,可以讓您對影象優化的原理有一個直觀的感受。

1. 向量圖與柵格圖(點陣圖)

向量圖與柵格圖(點陣圖)是兩種不同的影象格式。

向量圖與柵格圖
圖1-1 向量圖與柵格圖

  • 向量圖形是計算機圖形學中用點、直線或者多邊形等基於數學方程的幾何圖元表示影象。
  • 柵格圖(英語:Raster graphics),又稱點陣圖(Bitmap)或點陣圖,是使用畫素陣列(Pixel-array/Dot-matrix點陣)來表示的影象。

以向量圖為例,程式繪製一個半徑為r的圓所需的主要資訊是:

  1. 半徑r
  2. 圓心座標
  3. 輪廓樣式與顏色(可能是透明)
  4. 填充樣式與顏色(可能是透明)

向量圖的內容是這些繪製相關的關鍵資訊,同樣的影象如果是柵格圖(點陣圖),則影象是由稱作畫素的單個點組成的。

柵格圖的每個畫素都分配有特定的位置和顏色值。每個畫素的顏色資訊由RGB組合或者灰度值表示。

根據位深度,可將柵格圖分為1、4、8、16、24及32點陣圖像等。每個畫素使用的資訊位數越多,可用的顏色就越多,顏色表現就越逼真。當然,相應的資料量就越大,影象所佔位元組數也就越大。

那什麼是位深度呢?位深度也叫做色彩深度或者色彩位數,即柵格圖中要用多少個二進位制位來表示每個點的顏色,色彩深度越高,每個畫素點可用的顏色就越多。色彩深度是用“n位顏色”(n-bit colour)來說明的。若色彩深度是n位,即有2^n種顏色選擇,而儲存每畫素所用的位數就是n。例如,位深度為 1 的畫素柵格圖只有兩個可能的值(黑色和白色),所以又稱為二值柵格圖。位深度為 8 的影象有 2^8(即 256)個可能的值。

所以向量圖對比柵格圖的優點主要在以下幾點:

  • 儲存最少的資訊,檔案位元組數比柵格圖小,且檔案大小與物體的大小無關
  • 任意放大向量圖形,不會丟失細節或影響清晰度,因為向量圖形是與解析度無關的
  • 在放大的時候,直線與曲線都不會成比例地變粗,它只會保持不變或者要小於縮放比例
  • 儲存的物體引數可以在後面修改。也就是說物體的運動、縮放、旋轉、填充等都不會降低繪製的精度。

但每一種格式都有優缺點,向量圖適用於簡單的幾何影象,如果是場景複雜的照片,向量格式就不能滿足要求了,因為描述所有形狀所需的 SVG 標記量可能高得離譜。即便如此,輸出效果可能仍然無法達到“照片級真實感”,所以這種情況使用柵格圖顯然更合適。

因為柵格圖是由很多個畫素點組成的,所以當我們放大柵格圖時,我們會看到圖形會出現鋸齒並且模糊不清(因為畫素點被放大了),所以我們在使用柵格圖時,需要根據不同的螢幕解析度來儲存多個版本的柵格圖影象,這樣可以提供最佳的使用者體驗。

現在我們已經瞭解了什麼是向量圖與柵格圖,接下來我們將介紹如何優化它們。

2. 優化向量圖

SVG大家應該都不陌生,它是一種可縮放向量圖形。前不久我在寫 《嗨,送你一張Web效能優化地圖》 這篇文章時,@安佳 姐姐幫我畫了一張SVG圖。

SVG向量圖
圖2-1 SVG示例圖

圖2-1您可以通過點選連結在瀏覽器開啟它,然後檢視網頁原始碼,在原始碼中可以看到它涵蓋了大量的元資料,例如圖層資訊、註解和 XML 名稱空間等,而瀏覽器渲染時通常不需要這些資料。

我們可以通過svgo之類的工具將 SVG 檔案縮小。

上面這張圖片,我使用svgo優化完之後,檔案大小縮減了69.3%!原圖16.315 KiB優化後文件大小5.009 KiB。您可以點選連結在瀏覽器開啟優化後的SVG向量圖,並檢視網頁原始碼,對比它們之間的區別,您可以看到原始碼明顯少了很多,但並不影響瀏覽器正常渲染。

SVG優化前後對比
圖2-2 SVG向量圖原始碼優化前後對比

3. 優化柵格圖

通過第一小節的介紹,我們大致可以想象出,其實柵格圖是二維“畫素”柵格。例如一個10*10畫素的影象是 100 個畫素序列,而每個畫素中又儲存了RGBA值(R紅色通道、G綠色通道、B藍色通道、A alpha透明度通道)。

在內部,瀏覽器會為每個通道分配 256 個值(色階),就是說每個通道 8 位(因為2^8=256),那麼一個畫素有四個通道(RGBA),所以每個畫素一共 32 位(4 個通道 * 8 位 = 32 位),32 位 = 4 位元組,也就是說每個畫素 4 佔個位元組。所以,只要我們知道柵格圖尺寸,我們就可以輕易地計算出影象檔案的大小。

尺寸 畫素 檔案大小
100 * 100 10,000 39 KB
200 * 200 40,000 156 KB
300 * 300 90,000 351 KB
500 * 500 250,000 977 KB
800 * 800 640,000 2500 KB

從上表可以看到,隨著圖片尺寸的變大,檔案大小會以驚人的速度暴增。

再基於此特徵的前提下,我們應該怎樣改善柵格圖的檔案大小以獲得更快的載入速度呢?

在第一小節中,我們簡單介紹了”色彩深度“,所以一個簡單的策略是我們可以通過調整影象的色彩深度來降低影象檔案的大小。每個通道 8 位為每個通道提供 256 個值,RGB三個通道一共可以為每個畫素提供 16777216 種顏色(256^3=16777216)。如果我們將色彩深度調整為 RGB 通道一共只需要 8 位,那麼加上 Alpha 透明度通道的 8 位,一共為 16 位,也就是說每個畫素兩個位元組(16位 = 2個位元組),與原來每個畫素 4 個位元組相比,節約了 50% 的位元組!

但是你一定會有疑問,顏色值少了那麼多,影象的質量會不會變得很差?我們可以用一張圖來對比一下。

不同色彩深度的圖片進行對比
圖3-1 不同色彩深度的圖片進行對比

這張圖是上個月(2018-10)我去參加W3C TPAC會議時在法國讓彭星小哥哥幫我拍攝的。這張圖包含漸變色過渡的複雜場景(天空),可以看到,調整了色彩深度後,從肉眼上看到的視覺差異並不明顯。

在優化了各個畫素中儲存的資料之後,我們還可以更進一步。事實上,許多影象的相鄰畫素都具有相似的顏色,壓縮程式可以利用這個特徵採用“增量編碼”的方式對影象進行壓縮。在這種編碼方式下,並不為每個畫素單獨儲存值,而是儲存相鄰畫素之間的差異,如果相鄰畫素相同,則增量為“零”,只需儲存一位即可。通過儲存資料之間的差異,而不是儲存資料本身,這樣的方式可以大幅減少資料的重複,從而降低檔案大小。

當然,影象壓縮領域的解決方案還遠不止這些,因為影象佔據了網路世界中大量的位元組,所以好的影象壓縮方法具有極大的價值,這一領域學術性很強,我們也沒有能力去發明新的演算法,但瞭解這一領域的基本概念還是可以的,例如本文介紹的 RGBA 畫素、色彩深度和各種優化方法。

4. 無失真壓縮與有失真壓縮

無損資料壓縮(Lossless Compression)指資料經過壓縮後,資訊不受損失,還能完全恢復到壓縮前的原樣。

那麼無失真壓縮是如何做到儲存完整的原始資訊的同時降低檔案大小的呢?

舉個例子:一張圖是由100個紅點構成,那麼正常情況下它會以類似“紅點、紅點、...(重複97次)...、紅點”的格式來儲存它(柵格圖的儲存格式我們在本文的第三小節中介紹過)。為了降低檔案大小,我們可以改成用“100個紅點”這樣的格式來儲存這張圖片,這樣就可以在不失去任何資訊的情況下完成壓縮,這就是無失真壓縮。

但如果想儲存檔案的所有資訊,那麼無論使用任何壓縮方法,檔案大小都無法低於一個下界。舉個例子:壓縮後得到的zip檔案會比原始檔更小,但一直重複壓縮同一個檔案並不會讓檔案大小變成0,因為原始檔終究含有一定的資料量。

這個時候,使用有失真壓縮可以突破這個限制。

因為人的肉眼很難觀察到一張高解析度影象裡面的一些細節,所以捨棄這些人類無法察覺的細節,就可以用更小的資料量提供與原始資料相差無幾的感官體驗(當然也可以更進一步,例如:通過失去一部分可以察覺的細節,來達到更好的壓縮率),這就是有失真壓縮。有損資料壓縮又稱破壞性資料壓縮、不可逆壓縮。有損資料壓縮是將次要的資訊資料捨棄,犧牲一些質量來減少資料量,提高壓縮比。

有失真壓縮的一個優點是在有些情況下,它能夠獲得比任何已知無失真壓縮小得多的檔案大小,同時又能滿足系統的需要。

總結

本文重點介紹了什麼是向量圖與柵格圖(點陣圖),以及各種圖片優化工具是如何優化它們的。

最後,我們還討論了什麼是有失真壓縮與無失真壓縮,以及它們之間的區別。