本篇介紹如何使用 Guetzli 壓縮大量圖片,並比較 Guetzli 與 TinyPNG 的壓縮結果。
Guetzli 是一套由 Google 所開發的 JPEG 圖片壓縮演算法,與現有的 libjpeg 相比,可將高品質的圖片大小減少 20% 至 30% 左右,並且完全相容於現有的瀏覽器與各種應用程式,因此若應用於網頁的圖片壓縮上,可以大幅降低資料傳輸量,增進網頁載入速度。
以下介紹如何在各種系統中安裝與使用 Guetzli,壓縮自己的 JPEG 圖檔。
Guetzli 的 GitHub 網頁上有提供各種編譯好的版本,適用於 Windows、Mac OS X 與 Linux,對於一般只是要壓縮圖片的使用者,建議直接下載這個版本即可。
如果要使用 Guetzli 的演算法自行撰寫應用程式時,就會需要自行編譯原始碼的版本,以下是在各個系統中編譯 Guetzli 的方式,詳細說明請參考 Guetzli 的 GitHub 網頁。
安裝 libpng 與 gflags,在 Debian 的 Linux 可用 apt 安裝:
apt-get install libpng-dev libgflags-dev
Arch Linux 則執行:
pacman -S libpng gflags
接著將 Guetzli 的原始碼解壓縮之後,使用 make
編譯即可。
make
在 Windows 中若要自行編譯 Guetzli,必須安裝 Visual Studio 2015 與 vcpkg,然後使用 vcpkg
安裝 libpng
:
.vcpkg install libpng .vcpkg integrate install
最後再用 Visual Studio 2015 編譯 Guetzli 的專案。
在 Mac OS X 中要先安裝 Homebrew 或 MacPorts,接著再用 Homebrew 或 MacPorts 安裝 libpng:
brew install libpng
或
port install libpng
接著使用 make
編譯:
make
若使用 MacPorts 的話,編譯時再再加上一些參數:
CFLAGS='-I/opt/local/include' LDFLAGS='-L/opt/local/lib' make
另外 Homebrew 也可以直接安裝 Guetzli:
brew install guetzli
在不同作業系統中使用 Guetzli 壓縮圖片的方法都差不多,主要的差異是在指令搞的寫法,Guetzli 指令本身的用法都是一樣的。
在 Mac OS X 與 Linux 中都可以使用 bash 來撰寫壓縮的指令稿,首先將 Guetzli 執行檔下載後,設定可執行的權限:
chmod +x guetzli_darwin_x86-64
指令說明可參考 -help
參數的輸出:
./guetzli_darwin_x86-64 -help
這是將整個目錄下所有的 *.jpg
圖檔交給 Guetzli 壓縮的 bash 指令稿,而輸出的圖檔名稱就是在原本的檔案名稱後面加上 -guetzli
:
for file in *.jpg do ext="${file##*.}" # 主檔名 name="${file%.*}" # 副檔名 ./guetzli_darwin_x86-64 "${file}" "${name}-guetzli.${ext}" done
在 Windows 中也可以利用指令搞的方式壓縮大量圖片,這是我在 StackOverflow 上看到的方法:
setlocal disableDelayedExpansion for /f "delims=" %%A in ('forfiles /s /m *.jpg /c "cmd /c echo @relpath"') do ( set "file=%%~A" setlocal enableDelayedExpansion echo !file:~2! CALL "guetzli.exe" --quality 85 !file:~2! !file:~2! endlocal )
這是一個 DOS 的 batch 指令搞,它在壓縮之後會直接將原始圖檔覆蓋掉。
我從 pixabay 網站上下載了 12 張照片,每張圖片的大小大約是 1920×1280 左右。
我在我的 iMac 電腦(CPU 是 Intel Core i5 3.1 GHz)測試使用 Guetzli 壓縮 12 張圖片,分別以 95%、90%、85% 這幾個 quality 去壓縮,並且與我常用的 TinyPNG 做比較,以下是 12 張圖片的測試結果。
Guetzli 壓縮之後大部份都還是比 TinyPNG 的還大,若要壓的比 TinyPNG 還要小,應該是要選擇 85% 以下的 quality。乍看之下似乎 TinyPNG 比較好,但是我實際使用 ImageMagick 的 identify
去檢查壓縮後的 JPEG 圖檔 quality,發現 TinyPNG 的 quality 變動很大。使用 identify
查詢圖檔 quality 的指令如下:
identify -verbose filename.jpg
若要一次取得多張圖檔的 quality,可以這樣寫:
identify -format '%Qn' *.jpg
我把所有圖檔的 quality 抓出來,結果如下:
看起來 Guetzli 壓縮之後,quality 還是維持相當高的狀態,但是檔案卻可以明顯變小,而 TinyPNG 應該就是犧牲 quality 來換取檔案大小,實務上我們應該是可以使用 Guetzli 配合 80%、甚至更低的 quality 來壓縮圖片,得到的效果應該是不會輸 TinyPNG。
這裡我感覺 Guetzli 所指定的 quality 參數好像跟 JPEG 的 quality 值不太一樣,即便我指定較低的 quality,Guetzli 壓出來的 JPEG 圖的 quality 還是很高,但檔案大寫確實有變小。
在壓縮的時間上,TinyPNG 是一個線上壓縮圖片的服務,一般來說 12 張圖片上傳加上壓縮與下載,一分鐘以內一定可以完成,而 Guetzli 以 95% 的 quality 壓縮 12 張圖片卻花了 38 分 40 秒,真的非常久,其他的 quality 也差不多是這樣的時間。
time ./script.sh
real 38m40.551s user 37m0.860s sys 1m28.546s
Guetzli 的大問題就是壓縮圖片要花很久的時間,可能適合放在伺服器上作為背景服務使用。
這裡的直方圖我是用 R 語言畫的,程式碼如下:
library(reshape2) library(ggplot2) plot.barplot <- function(file, val.name) { df <- read.csv(file) df.reshape <- melt(df, id.vars = c("name"), variable.name = "group") p <- ggplot(df.reshape, aes(name, value, fill = group)) + geom_bar(position = "dodge", stat = "identity") + scale_fill_brewer(palette="YlOrBr") + guides(fill=guide_legend(title = NULL)) + xlab("Image") + ylab(val.name) + coord_flip() print(p) } # 比較檔案大小 plot.barplot("size.csv", "Size") # 比較 quality plot.barplot("quality.csv", "Quality")
測試結果的資料則放在 size.csv 與 quality.csv。
參考資料:TechNews