注明:本人原創翻譯,原版為Essential Image Optimization電子書,這里將其拆分為幾篇文章發布。另外,文中部分鏈接可能會因為“網絡”原因無法打開。不必著急,我會慢慢將其中一些比較好的內容翻譯過來發表,都會在這個“Web圖像技術深究”專題中。
目錄
- ?介紹
- 如何判斷我的圖像是否需要優化?
- 如何選擇正確的圖像格式?
- “素人”JPEG
- JPEG的壓縮模式
-
什么是WebP?
- WebP的表現如何?
- 誰在生產環境中使用WebP?
- WebP編碼如何執行?
- WebP的瀏覽器支持
- 如何將我的圖像轉換為WebP?
- 如何在我的操作系統上查看WebP圖像?
- 如何提供WebP?
- SVG優化
- 避免使用有損編解碼器重復壓縮圖像
-
減少不必要的圖像解碼和尺寸調整帶來的損耗
- 使用srcset提供HiDPI圖像
- 藝術化的響應
- 顏色管理
- 圖像拼合技術
- 延遲加載非關鍵圖像
- 避免<code>display: none;</code>的陷阱
- 圖像CDN服務對你有意義嗎?
- 緩存圖像資源
- 預加載關鍵圖像資源
- 圖像的網絡性能預算
- 最后的建議
- 附注
正文:
什么是WebP?
WebP是一個來自Google的新型圖像格式,它旨在以可接受的視覺質量提供較低文件大小的無損和有損壓縮。另外,WebP還包括了對alpha通道透明度和動畫的支持。
在過去一年中,WebP在有損和無損模式下減少了10%的壓縮體積,并且提高了10%的壓縮速度。WebP并不是一個能夠用于所有目的的工具,但它在圖像壓縮社區中已經具有了一定的地位和不斷增長的用戶群。那么,我們來看看為什么。
WebP:不同質量級別下文件體積和相似度對比。
WebP的表現如何?
有損壓縮
根據WebP團隊的描述,使用VP8或VP9視頻關鍵幀編碼進行處理的WebP壓縮文件平均比JPEG文件小了25-34%。
在較低質量設置(0~50)下,WebP具有比JPEG更大的優勢,因為它可以消除丑陋的塊狀偽影;在中等質量設置(-m 4 -q 75)下,WebP則是速度與體積平衡的默認選擇;而在較高質量設置(80-99)時,WebP的優勢則在縮小。WebP被推薦應用在速度比質量更重要的場景中。
無損壓縮
WebP無損文件的體積比PNG文件小了26%;同時,WebP無損壓縮圖片的加載時間與PNG相比減少了3%。也就是說,您通常不會想在網絡上為您的用戶提供無損壓縮的圖像。另外,無損和銳利邊緣(如non-JPEG)是不同的。無損模式的WebP可能更適合于檔案內容。
透明度
WebP具有一個無損8位透明度通道,而只比PNG多出22%的字節。它還支持有損的RGB透明度,這是WebP獨有的功能。
元數據
WebP文件格式支持EXIF照片元數據和XMP數字文檔元數據,它還包含了一個ICC顏色配置文件。
WebP提供了更好的壓縮,但代價是更多的CPU開銷。在2013年,WebP的壓縮速度會比JPEG慢10倍,但是現在已經可以忽略不計了(有些圖像可能會減慢2倍)。當WebP用于生產作為你應用構建一部分的靜態圖像時,這不應該是一個大問題。然而,作為動態的圖像生產工具,就可能會導致可察覺的CPU開銷,這將是您需要考量的問題。
注意:WebP有損質量設置百分比,與JPEG的質量百分比并不能直接比較。因為WebP通過丟棄更多數據來實現更小的文件體積,因此“70%質量”的JPEG將與“70%質量”的WebP圖像完全不同。
誰在生產環境中使用WebP?
許多大型公司正在生產環境中使用WebP,來降低成本并減少網頁的加載時間。
Google的報告表明,以一天提供430億圖像請求來計算,使用WebP有損壓縮將比其他有損壓縮解決方案節省30%~35%的存儲空間,而使用無損壓縮則是節省26%。這種空間的節省無疑是非常重要的。而如果瀏覽器對WebP支持更好、更廣泛,節省將會更大。Google已經將WebP應用于Google Play和YouTube等網站的生產環境。
Netflix、亞馬遜、Quora、雅虎、沃爾瑪、Ebay、“衛報”、“財富”和“今日美國”均是為已經支持格式的瀏覽器提供了WebP。VoxMedia 通過給他們使用Chrome的用戶提供WebP,將The Verge網站(一個美國科技媒體網站) 減少了1~3倍的加載時間。500px則表示,通過切換為WebP提供給自己的Chrome用戶,在保持類似或更好的圖像質量的同時將文件的體積平均降低的25%。
這個樣本列表顯示,有很多的公司都使用WebP。
WebP在Google的應用:在YouTube、Google Play、Chrome的Data Saver以及G+(Google+,Google的社交網絡服務)上,每日響應430億的WebP請求。
WebP編碼如何執行?
WebP的有損編碼被設計用于與JPEG靜態圖像進行競爭。它有三個關鍵流程:
宏塊分解:將圖像分解成一個16×16亮度像素(宏)塊集合和兩個8×8色度像素塊集合。這可能聽起來很像JPEG的方法,通過色彩空間轉換、色度通道下采樣和圖像細分來處理。
預測:宏塊的每個4×4子塊都具有一個預測模型,可以有效地進行濾波。它定義了一個塊周圍的兩組像素,分別為A(上面的行)和L(左側的列)。編碼器會使用這兩個像素塊A和L,嘗試填充4x4像素的測試塊,并確定哪個像素塊創建的測試塊最接近原始塊的值。Colt McAnlis在他的文章“WebP有損耗模式的工作原理”中更深入地討論了這一點。
最后會使用離散余弦變換(DCT)執行幾步類似于JPEG編碼的過程。之間的一個關鍵區別是,這里會使用一個算術壓縮器,不同于JPEG的霍夫曼編碼。
如果您想深入了解WebP的壓縮技術,Google開發人員的文章“ WebP壓縮技術”將幫助你。
WebP的瀏覽器支持
不是所有的瀏覽器都支持WebP,然而根據CanIUse.com的統計,WebP的瀏覽器用戶支持在全球約為74%。Chrome和Opera本地支持它。Safari,Edge和Firefox已經嘗試了它,但沒有在官方發行版中發布。這就將為用戶獲取WebP圖片的任務移交給了前端開發人員,這個稍后再說。
以下是主要的瀏覽器和WebP的支持情況:
- Chrome:Chrome在第23版開始全面支持。
- Chrome for Android:自Chrome 50起。
- Android:自Android 4.2起。
- Opera: 從12.1版本起。
- Opera Mini:所有版本。
- Firefox:一些beta支持。
- Edge:一些beta支持。
- Internet Explorer:不支持。
- Safari:一些beta支持。
WebP不是沒有缺點的。它缺乏全分辨率的顏色空間選項,并且不支持逐行解碼(漸進式)。總的來說,WebP工具是一個適合的、瀏覽器支持的(寫作時僅限于Chrome和Opera瀏覽器)、可能會覆蓋足夠的用戶的值得你去考慮的壓縮選項。
怎樣將圖片轉換為WebP格式?
一些商業和開源的圖像編輯處理軟件都支持WebP格式。其中有個特別有用的應用叫做XnConvert,一個免費的、跨平臺的批量圖片轉換器。
注意: 一定要避免將低質量或一般質量的JPEG轉換為WebP。這是一個很常見的錯誤,它會導致生成的WebP圖片帶有JPEG壓縮產生的虛影效果。還會使保存的WebP圖片效果變差和失真,甚至損失的質量會翻倍。作為轉換初始的圖像文件,一定要是高質量的,或者原圖。
XnConvert能夠批量的進行圖像處理,并兼容500多種圖像格式。你可以組合超過80種的獨立操作,以多種方式轉換或編輯的圖像。
XnConvert支持批量的圖像優化,允許原圖到WebP或其他格式的直接轉換。除了壓縮,XnConvert還可以執行圖像元數據剝離、裁剪、顏色深度定制以及其他轉換等操作。
下面是XnView網站上列出的XnConvert的一些選項,包括:
- 元數據:編輯
- 轉換:旋轉、裁剪、調整尺寸
- 調整:亮度、對比度、飽和度
- 過濾器:模糊、浮雕、銳化
- 效果:屏蔽、水印、漸暈
使用XnConvert,你可以導出為大約70種不同的文件格式,包括WebP。它支持Linux、Mac以及Windows操作系統。因此,我們強烈推薦XnConvert,它特別適合小企業。
Node模塊
Imagemin是一個非常流行的Node.js的圖像縮小模塊,它還包含了一個WebP轉換插件(imagemin-webp)。支持有損和無損兩種模式。
要安裝imagemin和imagemin-webp,需要運行:
> npm install --save imagemin imagemin-webp
然后,我們可以使用require()調用這兩個模塊,并且運行它們處理在項目目錄中的任意圖片(如JPEG)。下面是使用Imagemin,有損壓縮并批量生成質量為60的WebP圖片:
const imagemin = require('imagemin');
const imageminWebp = require('imagemin-webp');
imagemin(['images/*.{jpg}'], 'images', {
use: [
imageminWebp({quality: 60})
]
}).then(() => {
console.log('Images optimized');
});
與JPEG類似,要注意到輸出后的壓縮效果。評估什么樣質量設置,對你的圖像才是有意義的。Imagemin-webp還可通過傳遞lossless: true
選項,來生成無損壓縮的WebP圖像(支持24位顏色和全透明度):
const imagemin = require('imagemin');
const imageminWebp = require('imagemin-webp');
imagemin(['images/*.{jpg,png}'], 'build/images', {
use: [
imageminWebp({lossless: true})
]
}).then(() => {
console.log('Images optimized');
});
這里還有一個由Sindre Sorhus基于imagemin-webp構建的Gulp的WebP插件;當然,也包括WebPack的插件。Gulp插件可以接收imagemin的任何選項設置,如有損壓縮:
const gulp = require('gulp');
const webp = require('gulp-webp');
gulp.task('webp', () =>
gulp.src('src/*.jpg')
.pipe(webp({
quality: 80,
preset: 'photo',
method: 6
}))
.pipe(gulp.dest('dist'))
);
或無損壓縮:
const gulp = require('gulp');
const webp = require('gulp-webp');
gulp.task('webp-lossless', () =>
gulp.src('src/*.jpg')
.pipe(webp({
lossless: true
}))
.pipe(gulp.dest('dist'))
);
使用Bash批量優化圖像
XNConvert支持批量的圖像壓縮,但是如果你希望避免使用一個應用程序或者一套構建系統,那么可以使用bash命令和圖像優化二進制文件,它們同樣使壓縮變得簡單。
你可以使用cwebp命令,將圖像批量轉換為WebP:
find ./ -type f -name '*.jpg' -exec cwebp -q 70 {} -o {}.webp \;
或者,使用jpeg-recompress采用MozJPEG編碼,批量優化您的原圖:
find ./ -type f -name '*.jpg' -exec jpeg-recompress {} {} \;
并且,使用svgo優化SVG(我們稍后將介紹):
find ./ -type f -name '*.svg' -exec svgo {} \;
Jeremy Wagner有一篇文章《使用Bash優化圖像》比較全面的討論這個問題,同時還有個姊妹篇《使用Bash快速優化圖像》也值得讀一下。
其他的WebP圖像處理和編輯應用程序包括:
- Leptonica — 一個開源圖像處理和圖像分析的應用網站。
- Sketch支持直接導出WebP格式
- GIMP — 免費、開源的Photoshop替代品。一個圖像編輯器。
- ImageMagick — 用于創建、設計、轉換或編輯位圖圖像,一個免費的命令行應用。
- Pixelmator — 適用于Mac的商用圖像編輯器。
- Photoshop的WebP插件 — 免費的,支持圖像導入和導出,來自于Google。
Android: 您可以使用Android Studio將現有的BMP、JPG、PNG或靜態GIF圖像轉換為WebP格式。有關更多信息,請參閱使用Android Studio創建WebP圖像。
如何在我的操作系統上瀏覽WebP圖像?
當你將WebP圖像拖放到基于Blink的瀏覽器(Chrome、Opera、Brave)中進行預覽時,你還可以使用Mac或Windows的附加組件直接從操作系統預覽它們。
幾年前,當Facebook試驗WebP格式時發現,用戶將WebP圖片通過右鍵另存到本地磁盤后,無法通過瀏覽器以外的程序打開瀏覽。這其中主要有三個主要問題:
- “另存為”但無法在本地瀏覽WebP圖片。這個可以通過將Chrome注冊為“.webp”的打開應用來解決。
- “另存為”并將圖片加入郵件中分享給不適用Chrome的其他人。Facebook通過引入一個醒目的“下載”按鈕來解決這個問題,這個按鈕點擊時會返回JPEG給用戶。
- 右鍵 > 復制鏈接 -> 分享鏈接到網絡上。這個最后通過HTTP通訊協議中的content-type來解決。
這些問題可能對你的用戶來說不太重要,但是對于WebP圖片的通用性,Facebook的試驗過程可謂是一個有趣的注解。值得慶幸的是,現在不同的操作系統上,都有用于查看和使用WebP的實用程序了。
在Mac上,可以使用Quick Look的WebP插件(qlImageSize)。它工作的很好:
如何提供WebP?
在不支持WebP的瀏覽器中,WebP圖像最終不會顯示,這明顯不是我們想要的。為了避免這種情況,我們可以使用幾種策略根據瀏覽器支持情況有條件地提供WebP圖像服務。
Chrome的開發者工具中的網絡面板中“類型”一欄顯示,網站對Blink內核的瀏覽器返回了WebP格式。
可以看到Google Play對Blink內核瀏覽器返回WebP的同時,對于像Firefox這樣不支持WebP的瀏覽器返回JPEG。
以下是從服務端返回WebP給你的用戶的幾個方案:
使用 .htaccess配置來提供WebP的副本
下面將說明當在服務器上存在與JPEG或PNG圖像相匹配的.webp版本時,如何使用.htaccess文件將WebP文件提供給支持的瀏覽器。
Vincent Orback推薦使用如下方法:
瀏覽器可以通過Header中指定Accept來顯式的指定WebP支持。通過這個標識,你就可以控制你的服務端,返回圖像的WebP版本(如果這個WebP圖像已經儲存在磁盤上,而不是JPEG或PNG格式)。這個方法并不總是有效(例如,對于靜態化的網站,如Github或S3),所以在選擇這種方案時請先檢查下它對于你的網站是否有效。
以下是Apache Web服務器的.htaccess文件示例:
<IfModule mod_rewrite.c>
RewriteEngine On
# Check if browser support WebP images
RewriteCond %{HTTP_ACCEPT} image/webp
# Check if WebP replacement image exists
RewriteCond %{DOCUMENT_ROOT}/$1.webp -f
# Serve WebP image instead
RewriteRule (.+)\.(jpe?g|png)$ $1.webp [T=image/webp,E=accept:1]
</IfModule>
<IfModule mod_headers.c>
Header append Vary Accept env=REDIRECT_accept
</IfModule>
AddType image/webp .webp
如果頁面上顯示的.webp圖像有問題,那么請確保在服務器上啟用了image/webp類型支持。開啟方法如下:
Apache:將以下代碼添加到.htaccess文件中:
AddType image/webp .webp
Nginx:將以下代碼添加到您的mime.types文件中:
image/webp webp;
注意:Vincent Orback提供了一個htaccess配置示例,可以作為參考;Ilya Grigorik維護一組用于為WebP提供服務配置腳本。
使用 <picture>
標簽
瀏覽器本身能夠通過使用<picture>
標簽,來選擇要顯示的圖像格式。<picture>
標簽利用多個<source>
和一個<img>
來設置顯示的圖像,其中<img>
是包含了圖像的、真實的DOM元素。瀏覽器會循環遍歷<source>
提供的鏈接,并檢索到第一個匹配的結果。如果用戶的瀏覽器中不支持<picture>
,瀏覽器將會將它渲染為一個<div>
,并使用其中的<img>
。
注意: 注意
<source>
的排列順序。不要將image/webp的格式放在舊格式的后面,而是將它們放在前面。瀏覽器將會先解析到它們并得到匹配,而不會解析到其他支持更廣泛的格式。如果物理尺寸相同(不使用media
屬性),也可以按照文件大小的順序放置圖像。一般來說,解析的順序就是擺放的順序。
以下是一些HTML示例:
<picture>
<source srcset="/path/to/image.webp" type="image/webp">

</picture>
<picture>
<source srcset='paul_irish.jxr' type='image/vnd.ms-photo'>
<source srcset='paul_irish.jp2' type='image/jp2'>
<source srcset='paul_irish.webp' type='image/webp'>

</picture>
<picture>
<source srcset="photo.jxr" type="image/vnd.ms-photo">
<source srcset="photo.jp2" type="image/jp2">
<source srcset="photo.webp" type="image/webp">

</picture>
使用自動化的CDN轉換WebP
一些CDN支持將圖像自動轉換為WebP,可以使用Client Hints來讓后端盡可能地提供WebP圖像。請檢查您的CDN,查看服務中是否包含了WebP支持。你可能有一個簡單的解決方案,只是等待著你去尋找。
WordPress的WebP支持
Jetpack — Jetpack是一款流行的WordPress插件,它包括一個名為Photon的CDN映像服務。使用Photon,你就可以獲得無縫的WebP圖像支持。這個叫Photon的CDN服務是包含在Jetpack的免費清單中的,因此這是一個很棒很有效的實現。不過,缺點是Photon會調整您的圖像大小,將一個查詢字符串放在您的URL中,并且每個圖像都需要額外的DNS查找。
Cache Enabler and Optimizer — 如果您使用的是WordPress,那么你至少有一個半開源的選項。WordPress的開源插件Cache Enabler有一個菜單復選框可以勾選,用于緩存WebP圖像,如果當前用戶的瀏覽器支持它就會提供給用戶。這使得WebP圖像服務變得容易。但是,這個插件有一個缺點:Cache Enabler需要使用一個名為Optimizer的姐妹程序,而它則是需要支付年費的。這對于一個需要真正的開源解決方案的情況來說,顯然是不合適的。
Short Pixel — Cache Enabler的另一個搭配選擇是使用Short Pixel,它的功能和Optimizer很像,也是付費的。但是,Short Pixel可以每個月免費優化100張圖片。
最好使用<video>
壓縮GIF動畫
動畫GIF使用依然廣泛,盡管這是一個功能非常有限的格式。雖然從社交網絡到流行的媒體網站都大量嵌入了動畫GIF,但是其實這個格式從未被設計用于視頻或動畫存儲。事實上,GIF89a規范一個在提示“GIF不是作為動畫的平臺”。格式中顏色、圖層和緯度的數量都影響GIF動畫文件的體積,切換到視頻格式可以提供最大的空間節省。
動畫GIF對比視頻:同等質量下不同文件格式的文件大小對比。
提供相同內容和質量的MP4文件可能會在文件體積上節省達到80%或更多。GIF通常不僅會浪費大量的帶寬,而且加載時間較長、只支持較少的顏色,因此只能使網站提供的用戶體驗大打折扣。您可能已經注意到,上傳到Twitter的動畫GIF在Twitter上的表現是要優于其他網站的。這是因為,Twitter上的動畫GIF實際上并不是GIF。為了提高用戶體驗和減少帶寬占用,上傳到Twitter的動畫GIF實際上是被轉換成為了視頻。同樣,Imgur也將上傳的GIF轉換為了靜音的MP4視頻。
為什么GIF多數情況下要大很多?因為,動畫GIF將每個幀存儲為了無損GIF圖像 - 是的,無損。我們經常遇到的GIF的質量下降,其實是因為GIF受限于它的256色調色板。GIF格式下文件通常很大,因為它不像H.264這樣的視頻編解碼器會考慮壓縮相鄰幀。MP4視頻將每個關鍵幀存儲為有損的JPEG,并其丟棄一些原始數據以實現更好的壓縮。
如果您可以切換到視頻
ffmpeg -i animated.gif -movflags faststart -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" video.mp4
- ImageOptim的API還支持轉換動畫GIF為WebM/H.264視頻,另外還可以從GIF中消除抖動,從而幫助視頻編解碼器壓縮視頻到更小。
如果您必須使用動畫GIF
- 可以使用像Gifsicle這樣的工具,清除元數據和未使用的調色板條目,并最小化幀之間的變化。
- 考慮使用一個有損的GIF編碼器。Gifsicle派生的Giflossy支持一個
—lossy
命令標識,可以刪除掉60%~65%文件體積。還有一個很好的基于它的工具,稱為Gifify。對于非動畫GIF,將其轉換為PNG或WebP。
有關更多信息,請查閱Rigor編寫的關于GIF的電子書。