VectorDrawable的工作原理

轉載請註明出處:http://www.jianshu.com/p/c37e119faa55

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

我們已經討論了Android世界裏兩種應用最廣泛的圖片格式(JPG&PNG)了,不放值得注意的是,實際上還有一些壓縮級別是這兩種格式算法無法達到的。說到這,我們得先停止對圖片概念的想象,多瞭解一點算法。

柵格化圖片

通常來講,圖片是一堆排列在一個二維平面的像素點,它代表圖片本身的顏色。直白點說,就是一個像素點是一組顏色標量混合在一起,組成一個顏色,例如RGB。當我從遠處看,像素間邊緣融合在一起,最後呈現出平滑的顏色。這種類型的圖片就叫”柵格化”圖片。一般這些圖片數據都被柵格化成一個2D圖片,這也是我們最終看到的。

柵格化圖片的核心是,它在沒壓縮情況下體積的增長是線性的。圖片面積越大,像素就越多。像素越多,數據量就越大。數據量大會導致文件膨脹。比如你在手機上拍一張兩百萬像素的圖片,這圖片未壓縮的話會達到~6M。

我們之前已經提到,壓縮柵格化圖片,跟圖片本身的相似程度有關。圖片有越多同樣的顏色,越容易壓縮。特殊顏色越多,就越難。這樣導致的結果是,一張樹木或草叢圖會比一張純白色圖片壓縮得更差

例如,下面這張白色背景的紅色實心圓,儘管它非常的簡單,但也得壓縮文件裏的所有柵格化像素。

這對於Android工程師更是一個難題,因爲它得支持mdip,hdpi, xhdpi, xxhdpi, xxhdpi 和xxxhdpi不同屏幕密度的屏幕,這意味同樣圖片在APK裏需要保存多種大小。保存上面三張圖片會使用戶多下載55K數據,儘管有Multiple APKS這種黑科技,還是會保存一些重複的圖片。

矢量圖

如果,我們不是用柵格化像素來生成圖片,而是用描述性語言呢?我們同樣可以用繪圖操作命令來繪製上圖。

這是矢量圖形背後的概念。與柵格化圖片不同,這種圖片格式包含了繪製到屏幕上的各種不同視覺屬性。(總的來說這個過程叫做光柵化)。將所有命令合併到一起執行,最終會生成一個光柵圖形。

重要的一點是:

一張矢量圖可以生成所有分辨率的柵格化圖片,且矢量圖的文件大小不變。

也就是說,無論是 16×16 分辨率的還是 8092×8092 分辨率,一個矢量文件就能搞定。

SVG(可縮放矢量圖形)文件格式

矢量圖最廣泛的實現方式是SVG,它在文件裏定義了一堆繪圖操作,最終生成的圖片可以跨不同的平臺,包括web和圖形編輯器。下圖是一個SVG文件,和柵格化後的樣子。

當然,SVG也有一個廣爲人知的缺點,就是它通常都很臃腫。隨着標準的發展,它必須增加新的繪圖模式,混合模式,對傳統業務的支持,以及更冗長的語法來描述視覺需求。

同時,SVG使用的是XML語法,在大多數實現中,也要符合人類的閱讀習慣。這意味着,複雜的數字如”43.00102302”將替換成11個字節的字符串,而不是4個字節的浮點數。(儘管大多數web工程師會開啓GZIP壓縮SVG文件,但這與二進制文件還是沒法相比的)。

Android的VectorDrawable

這也是爲什麼Android不對SVG提供原生支持的原因:Android對文件大小很敏感。支持SVG的所有功能將允許非常大的和複雜的文件被創建,這並不是我們想要的。

因此,Android自己定義了一種矢量格式叫做VectorDrawable。它的工作原理和SVG很像,但使用了部分更小的繪製屬性。繪製過程是一樣的:加載一個VD文件,然後App把它柵格化成一個Bitmap。Boom~(嘭~)

看,我畫了一個安卓!

雖然VD文件也使用XML當作它們的格式,但它們最後會變編譯成一個二進制序列化格式放到APK裏,以減少它們的大小。

這樣的話節省空間就簡單了,使用VectorDrawable生成的圖片替代原來的多張PNG圖片,就可以節省很多空間。

使用VectorDrawable的另外一個好處是,它們還可以定義動畫。如果你用PNG文件來做動畫,那麼你通常得把動畫的每一幀都用png文件保存起來,它們看起來像這樣:

而用VectorDrawable,你可以定義同樣動畫,但完全由xml生成,這會明顯減少文件大小。

這不是銀彈

雖然矢量格式在文件大小很有優勢,但Android在使用時還是需要注意一些點。

越小越好

在Android系統上,將VectorDrawable轉成一個Bitmap這個柵格化過程是由cpu處理的。因此,創建一張圖片所需要的時間和圖形本身的分辨率/尺寸大小,是呈線性關係的。比如,柵格化一個16x16像素的三角形,可能只需要處理8-12個像素。而處理同樣質感的1024x1024像素的圖片,可能要處理超過10萬個像素,這顯然需要更多的處理時間。

因此,當你的圖片很大時,這將成爲你需要權衡的點,因爲此時加載這張圖片的時間很長,再使用VectorDrawable意義就不大了。

Tip: VectorDrawable最好用於較小的圖片

越簡單越好

矢量圖有一個侷限是,它只能代表一個固定類型的圖片質量。也就是說,矢量圖往往會比較簡單,只使用一組原生類型來定義怎麼在屏幕上生成顏色。你圖片越複雜,你的文件加載時間也會更長。

總的來說,使用VD時,最好先確保你的圖片是一些簡單的圖形,這對一些圖標或者ui控件就很有用。

Tip: VectorDrawable最好用於簡單的圖片

壓縮

矢量格式的強大之處在於,只需很少的文件存儲空間,卻展示了非常大的內容。這個概念遠不止適用於移動&Web框架。

如果你曾經好奇過DemoScene是如何將內容保存在這麼小格式裏的,其實過程很相似。這些圖像是他們用數學算法產生的,2d和3d都可以用這種方式生成。werkkzeug是DemoScene裏最著名的工具之一,儘管Substance已經被遊戲碼農使用了十幾年。

古話說得好:”遇到難題時,用數學解決。

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

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