本篇介紹如何使用 Guetzli 壓縮大量圖片,並比較 Guetzli 與 TinyPNG 的壓縮結果。

Guetzli 是一套由 Google 所開發的 JPEG 圖片壓縮演算法,與現有的 libjpeg 相比,可將高品質的圖片大小減少 20% 至 30% 左右,並且完全相容於現有的瀏覽器與各種應用程式,因此若應用於網頁的圖片壓縮上,可以大幅降低資料傳輸量,增進網頁載入速度。


最近 Guetzli 以開放原始碼的授權被釋出,其原始碼可從 GitHub 網站上下載。

名稱:Guetzli JPEG 圖片壓縮編碼器
網站:GitHub
下載:Guetzli Release

以下介紹如何在各種系統中安裝與使用 Guetzli,壓縮自己的 JPEG 圖檔。

安裝 Guetzli

Guetzli 的 GitHub 網頁上有提供各種編譯好的版本,適用於 Windows、Mac OS X 與 Linux,對於一般只是要壓縮圖片的使用者,建議直接下載這個版本即可。

自行編譯安裝

如果要使用 Guetzli 的演算法自行撰寫應用程式時,就會需要自行編譯原始碼的版本,以下是在各個系統中編譯 Guetzli 的方式,詳細說明請參考 Guetzli 的 GitHub 網頁

Linux

安裝 libpnggflags,在 Debian 的 Linux 可用 apt 安裝:

apt-get install libpng-dev libgflags-dev

Arch Linux 則執行:

pacman -S libpng gflags

接著將 Guetzli 的原始碼解壓縮之後,使用 make 編譯即可。

make

Windows

在 Windows 中若要自行編譯 Guetzli,必須安裝 Visual Studio 2015 與 vcpkg,然後使用 vcpkg 安裝 libpng

.\vcpkg install libpng
.\vcpkg integrate install

最後再用 Visual Studio 2015 編譯 Guetzli 的專案。

Mac OS X

在 Mac OS X 中要先安裝 HomebrewMacPorts,接著再用 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 壓縮圖片的方法都差不多,主要的差異是在指令搞的寫法,Guetzli 指令本身的用法都是一樣的。

Mac OS X 與 Linux

在 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

在 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 測試結果(檔案大小)

Guetzli 壓縮之後大部份都還是比 TinyPNG 的還大,若要壓的比 TinyPNG 還要小,應該是要選擇 85% 以下的 quality。乍看之下似乎 TinyPNG 比較好,但是我實際使用 ImageMagick 的 identify 去檢查壓縮後的 JPEG 圖檔 quality,發現 TinyPNG 的 quality 變動很大。使用 identify 查詢圖檔 quality 的指令如下:

identify -verbose filename.jpg

若要一次取得多張圖檔的 quality,可以這樣寫:

identify -format '%Q\n' *.jpg

我把所有圖檔的 quality 抓出來,結果如下:

Guetzli 測試結果(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.csvquality.csv

參考資料:TechNews