動態WebP

1.背景

目前網絡中圖片仍然是佔用流量較大的一部分,對於移動端更是如此,因此,如何在保證圖片視覺不失真前提下縮小體積,對於節省帶寬和電池電量十分重要。

然而目前對於JPEG、PNG、GIF等常用圖片格式的優化已幾乎達到極致,因此Google於2010年提出了一種新的圖片壓縮格式 – WebP,給圖片的優化提供了新的可能。

WebP爲網絡圖片提供了無損和有損壓縮能力,同時在有損條件下支持透明通道。據官方實驗顯示:無損WebP相比PNG減少26%大小;有損WebP在相同的SSIM(Structural Similarity Index,結構相似性)下相比JPEG減少25%~34%的大小;有損WebP也支持透明通道,大小通常約爲對應PNG的1/3。

同時,谷歌於2014年提出了動態WebP,拓展WebP使其支持動圖能力。動態WebP相比GIF支持更豐富的色彩,並且也佔用更小空間,更適應移動網絡的動圖播放。

目前國內外各大互聯網公司已逐步使用WebP,科技博客GigaOM曾報道,YouTube的視頻縮略圖採用WebP後,網頁加載速度提升了10%;谷歌網上應用商店採用WebP後,每天可節省幾TB的帶寬,頁面平均加載時間大約減少1/3;谷歌移動應用市場採用WebP圖片格式後,每天節省了50TB的存儲空間;2014年騰訊新聞客戶端應用了WebP後,流量峯值帶寬降低9GB,網絡連接延時不變的前提下,平均圖片延時和數據下載延時降低了100ms;2014年空間裝扮也全量轉換成WebP,帶寬上也有顯著降低。(雖然聽說目前已轉成SharpP格式…)

WebP的優勢在於它具有更優的圖像數據壓縮算法,在擁有肉眼無法識別差異的圖像質量前提下,帶來更小的圖片體積,同時具備了無損和有損的壓縮模式、Alpha 透明以及動畫的特性,在 JPEG 和 PNG 上的轉化效果都非常優秀、穩定和統一。

本文主要對WebP現狀與原理進行整理,並尤其研究其動圖格式在Android上的支持情況。

2.原理

WebP的壓縮主要分爲有損壓縮、無損壓縮以及有損帶透明通道壓縮。

2.1 有損WebP

有損WebP基於VP8視頻編碼中的預測編碼方法來壓縮圖像數據,其基本步驟類似於JPEG壓縮,主要包含格式轉換、分割子塊、預測編碼、FDCT、量化、Z排列、熵編碼,流程如下圖所示,紅色代表與JPEG不同的部分。

1) 格式轉換

若壓縮前圖像數據爲RGB格式,則需先進行格式轉換成YUV格式,Y表示亮度分量,UV表示色度分量。之所以轉換成YUV格式是因爲人類視覺對亮度遠比色度敏感,所以可通過適當減少色度數據的存儲來節省數據佔用的空間,但卻不會對視覺效果造成太大影響,如可每兩個或四個相鄰的像素點才保存一對UV值。

2) 分割宏塊

接下來將數據分割成一個個8x8或16x16的宏塊。

3) 預測編碼

預測編碼的原理是基於前面編碼好的宏塊,預測多餘的動作顏色等信息,屬於幀內預測。對各宏塊可使用以下幾種幀內預測模式:

  • H_PRED(horizontal prediction).使用block左邊的一列L來填充block中的每一列

  • V_PRED(vertical prediction):使用block上邊的一行A來填充block中的每一行

  • DC_PRED(DC prediction):使用L和A中所有像素的平均值作爲唯一的值填充block

  • TM_PRED(TrueMotion prediction):使用漸進的方式,記錄上面一行的漸進差,以同樣的差值,以L爲基準拓展每一行。

4) FDCT

FDCT(Forward Discrete Cosine Transform,正向離散餘弦變換)是將一組空間域的像素點轉變成頻域中的係數,對每個宏塊執行FDCT,使得變換後數據的低頻部分分佈在數據塊的左上方,高頻部分集中在右下方,其中左上角第一個係數稱爲直流係數,其他均爲交流係數。

5) 量化

量化是壓縮中損失數據的主要步驟,它主要原理是把經過DCT變換後的宏塊中每個數值除以量化表中對應的係數並取整。其中量化表中高頻部分對應的係數比低頻部分系數要大得多,則在經過量化後,高頻部分的頻率係數被大大衰減甚至許多被清零,而低頻部分的頻率係數則較好地被保留。由於人眼對低頻部分更敏感,所以經過量化後再還原成圖像對視覺效果影響較小,但數據得到有效的壓縮。量化的最終目的是減少低頻部分非零係數的幅值並增加高頻部分零值係數的數量。

6) Z排列

爲更便於後續的編碼,需在編碼前對數據塊進行重新的排列,使得低頻部分的數據排在前面,高頻部分的數據排在後面,以增加數組中連續零值的數量,所以採用一種Z字型的排列方式。

7) DPCM

可用DPCM(Differential Pulse Code Modulation,差分脈衝編碼調製)對直流係數進行編碼。由於直流係數的數值較大,且相鄰數據塊的直流係數相差不大,所以可使用DPCM對相鄰數據塊間量化後的直流係數差值進行編碼,從而提高壓縮比。

8) 行程編碼

行程編碼是一種根據相同數據重複多次的情況簡化表示的算法,例如1111222222333按照行程編碼表示爲(1,4)(2,6)(3,3)。由於量化後的交流係數中包含較多連續零值係數,因此可用行程編碼對它們進行編碼來有效壓縮數據長度。

9) 熵編碼

熵編碼是一種無損數據壓縮編碼方式,WebP中採用布爾算術編碼作爲熵編碼方式。和其它熵編碼方法不同的地方在於,其他的熵編碼方法通常是把輸入的消息分割爲符號,然後對每個符號進行編碼,而算術編碼是直接把整個輸入的消息編碼爲一個數,一個滿足(0.0 ≤ n < 1.0)的小數n。消息越長,編碼表示它的間隔就越小,表示這一間隔所需的二進制位就越多。

10) 其他

WebP還有一些細節上的步驟,比如自適應分塊(對不同區域的宏塊分配不同的壓縮參數)、環路濾波等。

爲什麼有損WebP會比JPEG好?

  • 主要原因是預測編碼。

  • 自適應分塊也提供了較好表現。

  • 環路濾波在中、低比特率的情況下有較大幫助。

  • 算數編碼相比霍夫曼增強了5%~10%的壓縮能力。

2.2 無損WebP

無損WebP基於使用不同的技術對圖像數據進行轉換,包括:預測空間變換、色彩空間轉換、使用調色板、多像素打包成一個像素、alpha值替換等技術。對於熵編碼,則採用改進的LZ77-Huffman編碼來緊湊稀疏值,它是一種對距離值的2D編碼技術。

2.3 有損WebP(支持透明)

區別於有損WebP和無損WebP,這種編碼允許對RGB頻道的有損編碼同時可對透明度頻道進行無損編碼。由於這種形式目前其他的格式還未能提供,所以目前需要使用透明度的話都會使用無損的PNG,導致大小膨脹。對於這類圖片,WebP提供了較好的壓縮效果。相比有損的WebP,添加透明通道只增加22%的大小。

因此,將支持透明的PNG換成無損+支持透明的WEBP可以平均節省60%-70%大小,這個已經被一些含較多Icon的移動網站證明。

(如:https://github.com/EverythingMe/webp-test#readme

2.4 動態WebP

動態WebP的原理與GIF和APNG原理類似,每一幀記錄變化區域的座標、長寬、播放延時等用於還原並播放。

3.文件結構

一個WebP文件表示一個靜態圖片或動畫,並可選的包含透明度、色彩

配置文件和元數據等。

3.1 WebP文件首部

RIFF:ASCII字符RIFF。

File Size:文件大小,以字節爲單位。

WEBP:ASCII字符WEBP,標識這是WebP文件

3.2 有損WebP簡要文件格式

這種文件格式支持有損編碼,但不包含透明度以及其他拓展特性,可以被許多舊版本軟件支持。

VP8 chunk:

Chunk Header:VP8塊首部,定義了VP8比特流數據的大小,以及該幀VP8數據的長寬等信息。

VP8 data:VP8比特流數據。

VP8比特流格式的定義可參考rfc6386,主要定義瞭如何將圖像數據轉換成YUV格式。https://tools.ietf.org/html/rfc6386

3.3無損WebP簡要文件格式

這種格式用在無損WebP編碼(可選透明)並且不要求拓展特性時。需要注意的是,較舊的WebP軟件可能不支持該格式。

VP8L chunk:

屬性意義類似於有損WebP的簡要格式,其中VP8L的定義可參考文檔:

https://chromium.googlesource.com/webm/libwebp/+/master/doc/webp-lossless-bitstream-spec.txt

3.4 拓展格式

拓展格式包括:

  • VP8X用於指明使用的特性
  • 可選的‘ICCP’用於色彩配置
  • 可選的‘ANIM’用於動畫控制
  • 可選的‘EXIF’用於EXIF元數據
  • 可選的‘XMP’用於XMP元數據

對於靜態圖像,圖像數據包含一幀數據,由以下組成:

  • 一個可選的透明度子chunk
  • 1個比特流子chunk

對於動態圖像,圖像數據則包含多幀數據。

拓展頭部格式:

ICC profile(I):置位時表示包含ICC配置文件。

Alpha(L):當圖像包含透明數據時置位。

EXIF metadata(E)當包含EXIF元數據時置位。

XMP metadata(X):當包含XMP元數據時置位。

Animation(A):動態WebP置位,此時ANIM和ANMF數據塊中的數據將會被使用來控制動畫。

Canvas Width Minus One:畫布的真實寬度是該數值+1。

Canvas Height Minus One:畫布的真實高度是該數值+1。

動畫

WebP動畫被ANIM和ANMF塊所控制。

ANIM Chunk:

對於一個動圖,該塊數據定義了動畫的全局參數。

Background Color: 定義畫布的背景顏色,以BGRA的順序存儲。這個顏色會被填充到每幀數據沒用到的區域。

LoopCount:循環次數,0表示無限循環。

當動畫標識被置位時,該數據塊必須出現。當動畫標識位沒出現時,該數據塊會被忽略。

ANMF chunk:

對於動圖,該數據塊包含了一幀圖像的數據。

Frame X:該幀數據左上角X座標爲該值*2。

Frame Y:該幀數據左上角Y座標爲該值*2。

Frame Duration: 播放該幀後的延時時間,以ms爲單位。

Blending method (B):標識如何混用前面畫布的相應透明像素點。置0時,處理完前面一幀圖像後,使用透明混合。置1時,不混合,渲染時直接覆蓋矩形區域。

Disposal method (D):標識該幀數據在被顯示後如何處理畫布。置0時不處理;置1時將畫布矩形區域轉換成ANIM定義的背景顏色。

Frame Data:以2字節爲單位,包含圖像比特流數據以及可選的透明度數據。

Alpha

Pre-processing (P): 標識壓縮中使用了預處理。

Filtering method (F): 濾波方法。0-無過濾;1-橫向過濾;2-垂直過濾;3-梯度過濾。

Compression method (C): 0-無壓縮;1-使用WebP無損格式壓縮。

Alpha bitstream:編碼的透明度比特流數據

顏色配置文件、元數據數據的文件格式類似,主要是頭部ASCII碼不同。

3.5 文件佈局示例

帶透明有損WebP文件形如:

無損WebP形如:

無損WebP包含ICC配置文件和XMP元數據形如:

動態WebP包含EXIF元數據形如:

4.與其他格式比較

有損WebP vs JPEG:

谷歌使用Lenna、Kodak、Tecnick還有Image_crawl四個圖像來源來做實驗,在相同或稍高的SSIM基礎上,WebP相比JPEG體積降低25% ~ 34%。詳見:

https://developers.google.com/speed/webp/docs/webp_study

無損WebP 、有損帶透明WebP vs PNG

下圖是選取了1000張網絡中的PNG,對其進行壓縮後,與對應的無損WebP以及有損帶透明WebP比較。可見絕大部分圖片經過兩種WebP壓縮後均比PNG要小。

WebP的編碼時間較長,是PNG的5倍以上,但解碼速度與PNG差不多,甚至很多時候比PNG快。而WebP在編碼時佔用內存比PNG高25%,解碼時比PNG低30%。

詳見:https://developers.google.com/speed/webp/docs/webp_lossless_alpha_study

動態WebP vs GIF

優勢:

  • WebP支持24位RGB和8位透明通道,GIF僅支持8位色彩及1位透明度。

  • WebP支持無損和有損兩種模式,而且對於動態圖,能同時結合有損和無損的圖片。而GIF僅支持無損的壓縮。WebP的有損壓縮技術也更好地適應從現實世界視頻中創建的動圖。

  • WebP相比GIF佔用更小的空間。Animated GIFs轉換爲有損WebP減少64%,轉換成無損WebP減少19%,這對移動網絡十分重要。

  • WebP使用更短的解碼時間,WebP所用解碼時間是GIF的57%。

劣勢:

  • 支持不夠普遍。

  • 添加WebP支持到瀏覽器需要添加較多代碼,但這在將來當WebP和WebM共享更多解碼代碼或者WebP被WebM合併後會有改善。

動態WebP vs APNG

APNG是一種基於PNG的編碼,對動圖的編碼方式類似於WebP,都是對變化的區域進行編碼。雖然理論上單張WebP要比PNG小,但有些整合成動圖形式後WebP會比APNG更大:

WEBP、APNG、GIF簡要比較表格

雖官方給出實驗示例中無論靜態或動態WebP都有比較好的壓縮表現,但實際上,自己嘗試用谷歌提供轉換工具轉換以及查詢某些網站上的示例,都顯示靜態和動態WebP的壓縮率均不太穩定,基於不同的圖片壓縮後的大小反而比JPEG或PNG更大。

5.支持情況

在瀏覽器上的支持:

在終端上的支持:

對於在App中使用WebP,除了Android 4.0以上提供了靜態WebP原生支持外,其他版本和IOS都可以直接使用官方提供的解析庫來支持靜態WebP

Android:https://github.com/alexey-pelykh/webp-android-backport

iOS:https://github.com/carsonmcdonald/WebP-iOS-example

然而,對於動態WebP,目前只能找到facebook的開源庫Fresco對其支持,不過Fresco最低僅支持API 9,且引用的相關庫較多。

https://www.fresco-cn.org/

6.總結

WebP作爲一種較新的圖片格式,在一定程度上提高了圖片的壓縮率,但目前壓縮表現尤其對於動圖,還較不穩定。

而Android對WebP動圖支持較差,目前僅有Fresco一個開源庫支持,要引入項目中,需進一步分離出無關的功能,並考慮最低僅支持API 9的問題。

參考文獻

https://developers.google.com/speed/webp/ 
http://www.jianshu.com/p/555859783f63 
https://isparta.github.io/compare-webp/index_a.html#12 
http://littlesvr.ca/apng/gif_apng_webp1.html 
https://www.fresco-cn.org/

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