Guetzliを使って画像を軽量化してみた

# はじめに

## 背景

ページの高速化と[Google Page Insights](https://developers.google.com/speed/pagespeed/insights/?hl=ja)の評価を上げるために調査と実験をしてみました。

また、諸事情によりJPEGminiサーバが利用できないため、候補としては外しております。
他にコンソール操作から画像を軽量化できるものがないか探してた結果、
以下の２つが候補にあがりました。
※[Kraken.io](https://kraken.io/)も試してみましたがAPIがなぜかタイムアウトになってしまい上手くいきませんでした。

- Guetzli
- mozjpeg

# Guetzliとは

上記２つは画像の最適度や精度についてはそこまで大差がないみたいですが、
どうやらGuetzilは実行速度自体に難があるということが書かれていました。

```zsh
Unrecognized input file format --- perhaps you need -targa
```

しかし、私のPC上でmozjpegを使って実行するとことごとく以下のエラーとなり、
実行できなく、画像自体に問題があることは知ってはいましたが、成功度としてはGuetzliのほうが高かったため、こちらを使用することにしました。

## 概要
https://github.com/google/guetzli
Guetzli [guɛtsli] とはスイスドイツ語でクッキーの意味。
Google が2016年10月22日に GitHub で Initial Release を公開 2 した JPEG エンコーダ。

## 特徴
Guetzli の JPEG 圧縮は、人間から見た視覚・心理的な誤差を小さくするように設計されています。
品質の指標として AE (absolute error count, number of different pixels) のみを用いるのは誤りです。
MSE や PSNR, SSIM などの手法も、AE よりはベターですが、人間が知覚する誤差の少なさの評価には適していません。（同一手法の異なる圧縮率間での比較には役立ちます）
Google は「Butteraugli」という、人間の知覚に近いという評価手法を提案し、そのスコアが良くなるように Guetzli を設計しました。
Guetzli のエンコード処理が極端に遅いのは、ある意味で 当然 です。通常のJPEGエンコーダは1回しかエンコードを行いませんが、Guetzli では「パラメータを変化させながら"ベターな答え"が見つかるまで何回もエンコード処理を行い」ます。この"ベターな答え"の判断基準として、「Butteraugli」評価アルゴリズムを用いています。

# 環境

## インストール

今回は、Macと仮想上のCentOS両方導入してみたので、２種類書いております。

### Mac X EL Capitan

```zsh
$ brew install guetzli
$ guetzli
Guetzli JPEG compressor. Usage:
guetzli [flags] input_filename output_filename
 
Flags:
  --verbose    - Print a verbose trace of all attempts to standard output.
  --quality Q  - Visual quality to aim for, expressed as a JPEG quality value.
  --memlimit M - Memory limit in MB. Guetzli will fail if unable to stay under
                 the limit. Default is 6000 MB
  --nomemlimit - Do not limit memory usage.
```

### CentOS6.9
```bash
$ curl -L hhttps://github.com/google/guetzli/releases/download/v1.0.1/guetzli_linux_x86-64 -o guetzli
$ chmod a+x guetzli && mv $_ /usr/local/bin
```

※glibcがglibc-2.14以下で実行できない場合

```bash
$ ldd --version
ldd (GNU libc) 2.12
$ wget http://ftp.gnu.org/gnu/glibc/glibc-2.14.tar.gz
$ tar zxvf glibc-2.14.tar.gz
$ cd glibc-2.14
$ ../configure --prefix=/opt/glibc-2.14
$ make -j4
$ sudo make install
$ export LD_LIBRARY_PATH=/opt/glibc-2.14/lib
```

# 実行

## 軽量化

### コマンド
```zsh
guetzli --quality 84 --verbose test.jpg output.jpg
```
### 実行中ログ（一部抜粋）
```zsh
Original Out[ 491666] BA[100.00%] D[0.0000] Score[491666.0000] (*)
Iter  1: f112222 quantization matrix:
  5  3  8 10  9  9  7  9     5  5  8 15 20 20 20 20     5  5  8 15 20 20 20 20   
  4  8 10  7  9  9  7  9     5  7  9 13 20 20 20 20     5  7  9 13 20 20 20 20   
  8 10 10  7  9  7 10  8     8  9 16 20 20 20 20 20     8  9 16 20 20 20 20 20   
  8  7  7  9  7 26 24  8    15 13 20 20 20 20 20 20    15 13 20 20 20 20 20 20   
  7  9  9  7  8 21 31 12    20 20 20 20 20 20 20 20    20 20 20 20 20 20 20 20   
  9  9  7  8 24 31 22 16    20 20 20 20 20 20 20 20    20 20 20 20 20 20 20 20   
  7  7 12 26 31 24 24 30    20 20 20 20 20 20 20 20    20 20 20 20 20 20 20 20   
 10 28 29 29 22 30 31 18    20 20 20 20 20 20 20 20    20 20 20 20 20 20 20 20   
Iter  1: f112222 GQ[118.37] Out[ 491761] BA[100.00%] D[0.0000] Score[491761.0000]
Iter  2: f112222 quantization matrix:
  1  1  1  1  1  1  1  1     1  1  1  1  1  1  1  1     1  1  1  1  1  1  1  1   
  1  1  1  1  1  1  1  1     1  1  1  1  1  1  1  1     1  1  1  1  1  1  1  1   
  1  1  1  1  1  1  1  1     1  1  1  1  1  1  1  1     1  1  1  1  1  1  1  1   
  1  1  1  1  1  1  1  1     1  1  1  1  1  1  1  1     1  1  1  1  1  1  1  1   
  1  1  1  1  1  1  1  1     1  1  1  1  1  1  1  1     1  1  1  1  1  1  1  1   
  1  1  1  1  1  1  1  1     1  1  1  1  1  1  1  1     1  1  1  1  1  1  1  1   
  1  1  1  1  1  1  1  1     1  1  1  1  1  1  1  1     1  1  1  1  1  1  1  1   
  1  1  1  1  1  1  1  1     1  1  1  1  1  1  1  1     1  1  1  1  1  1  1  1   
Iter  2: f112222 GQ[ 0.00] Out[ 746738] BA[100.00%] D[0.0000] Score[746738.0000]
Iter  3: f112222 quantization matrix:
  3  3  3  3  3  3  3  3     3  3  3  3  3  3  3  3     3  3  3  3  3  3  3  3   
  3  3  3  3  3  3  3  3     3  3  3  3  3  3  3  3     3  3  3  3  3  3  3  3   
  3  3  3  3  3  3  3  3     3  3  3  3  3  3  3  3     3  3  3  3  3  3  3  3   
  3  3  3  3  3  3  3  3     3  3  3  3  3  3  3  3     3  3  3  3  3  3  3  3   
  3  3  3  3  3  3  3  3     3  3  3  3  3  3  3  3     3  3  3  3  3  3  3  3   
  3  3  3  3  3  3  3  3     3  3  3  3  3  3  3  3     3  3  3  3  3  3  3  3   
  3  3  3  3  3  3  3  3     3  3  3  3  3  3  3  3     3  3  3  3  3  3  3  3   
  3  3  3  3  3  3  3  3     3  3  3  3  3  3  3  3     3  3  3  3  3  3  3  3   
Iter  3: f112222 GQ[22.56] Out[ 604134] BA[100.00%] D[1.4329] Score[604134.0000]
Iter  4: f112222 quantization matrix:
  5  5  5  5  5  5  5  5     5  5  5  5  5  5  5  5     5  5  5  5  5  5  5  5   
  5  5  5  5  5  5  5  5     5  5  5  5  5  5  5  5     5  5  5  5  5  5  5  5   
  5  5  5  5  5  5  5  5     5  5  5  5  5  5  5  5     5  5  5  5  5  5  5  5   
  5  5  5  5  5  5  5  5     5  5  5  5  5  5  5  5     5  5  5  5  5  5  5  5   
  5  5  5  5  5  5  5  5     5  5  5  5  5  5  5  5     5  5  5  5  5  5  5  5   
  5  5  5  5  5  5  5  5     5  5  5  5  5  5  5  5     5  5  5  5  5  5  5  5   
  5  5  5  5  5  5  5  5     5  5  5  5  5  5  5  5     5  5  5  5  5  5  5  5   
  5  5  5  5  5  5  5  5     5  5  5  5  5  5  5  5     5  5  5  5  5  5  5  5   
Iter  4: f112222 GQ[45.11] Out[ 555529] BA[100.00%] D[1.0045] Score[555529.0000]
Iter  5: f112222 quantization matrix:
  7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7   
  7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7   
  7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7   
  7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7   
  7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7   
  7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7   
  7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7   
  7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7   
Iter  5: f112222 GQ[67.67] Out[ 502877] BA[100.00%] D[2.2508] Score[6724921518196643388170041823330304.0000]
Iter  6: f112222 quantization matrix:
  5  5  5  5  7  7  7  7     5  5  5  5  7  7  7  7     5  5  5  5  7  7  7  7   
  5  5  5  7  7  7  7  7     5  5  5  7  7  7  7  7     5  5  5  7  7  7  7  7   
  5  7  7  7  7  7  7  7     5  7  7  7  7  7  7  7     5  7  7  7  7  7  7  7   
  7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7   
  7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7   
  7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7   
  7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7   
  7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7   
Iter  6: f112222 GQ[56.69] Out[ 529099] BA[100.00%] D[0.9649] Score[529099.0000]
Iter  7: f112222 quantization matrix:
  5  5  7  7  7  7  7  7     5  5  7  7  7  7  7  7     5  5  7  7  7  7  7  7   
  7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7   
  7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7   
  7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7   
  7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7   
  7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7   
  7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7   
  7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7   
Iter  7: f112222 GQ[62.67] Out[ 509931] BA[100.00%] D[1.4110] Score[509931.0000]
Iter  8: f112222 quantization matrix:
  5  7  7  7  7  7  7  7     5  7  7  7  7  7  7  7     5  7  7  7  7  7  7  7   
  7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7   
  7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7   
  7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7   
  7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7   
  7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7   
  7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7   
  7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7     7  7  7  7  7  7  7  7   
Iter  8: f112222 GQ[64.67] Out[ 505838] BA[100.00%] D[1.4712] Score[505838.0000]

YUV420 selected quantization matrix:
  5  3  8 10  9  9  7  9     5  5  8 15 20 20 20 20     5  5  8 15 20 20 20 20   
  4  8 10  7  9  9  7  9     5  7  9 13 20 20 20 20     5  7  9 13 20 20 20 20   
  8 10 10  7  9  7 10  8     8  9 16 20 20 20 20 20     8  9 16 20 20 20 20 20   
  8  7  7  9  7 26 24  8    15 13 20 20 20 20 20 20    15 13 20 20 20 20 20 20   
  7  9  9  7  8 21 31 12    20 20 20 20 20 20 20 20    20 20 20 20 20 20 20 20   
  9  9  7  8 24 31 22 16    20 20 20 20 20 20 20 20    20 20 20 20 20 20 20 20   
  7  7 12 26 31 24 24 30    20 20 20 20 20 20 20 20    20 20 20 20 20 20 20 20   
 10 28 29 29 22 30 31 18    20 20 20 20 20 20 20 20    20 20 20 20 20 20 20 20 
```

## 結果

### 実行時間
約1~2分（ちょっと時間かかりますね）

### クオリティ
84までしか下げられないみたいですが、人の目だとわからないくらい綺麗ですね

### 軽量化前

496KB

![test.jpg](https://qiita-image-store.s3.amazonaws.com/0/90598/cef7f1e6-00e2-d75a-5f21-e073045858cd.jpeg)

### 軽量化後

360KB

![output.jpg](https://qiita-image-store.s3.amazonaws.com/0/90598/4c184f70-e4f1-c963-d116-fb8d0286dcac.jpeg)

# ページ速度検証

## 対象ペーシ

[ぐるなびウエディング](https://wedding.gnavi.co.jp/)
弊社の会場様のページ（テストで行ったのはテスト環境のテスト会場で）でテストを行いました。
※以下キャプチャなどは諸事象により載せられないのであしからず。

## 設定

[Google Page Insights](https://developers.google.com/speed/pagespeed/insights/?hl=ja)が示す容量が代替お願いため--quality 84にしました

## 結果

### ファイル総容量

5.6MB　→　2.2MB

### ページ速度

#### PC

最適化前

Load 2.20sec
Load 2.24sec
Load 4.06sec
Load 2.83sec
Load 2.60sec

最適化後

Load 2.65sec
Load 2.70sec
Load 2.80sec
Load 3.67sec
Load 2.90sec

#### SP

最適化前

Load 2.99sec
Load 2.62sec
Load 2.39sec
Load 2.26sec
Load 2.54sec

最適化後

Load 2.21sec
Load 2.07sec
Load 2.36sec
Load 4.59sec
Load 2.05sec

# まとめ

## 画像軽量化

- 思っていた以上に綺麗なままなかなかの軽量化ができたのではないかとおもいます。
- 即時ではないのでサービスに盛り込む位置や場所や時間などを工夫してあげれば充分サービスに取り込めるものかとおもいました。

## ページ速度

### 総容量
- おおよそ半分と結構良い結果となりました。

### 画質
- SPについては目視だとあまり変化が感じられなかったです。
- PCについては画像の粗さが結構目立ちました。

### ロードタイム
- 簡易テストかつテスト環境のせいかあまり変化が見られなかったです。
- 単純なるリクエストは色々な状態に左右されて正確な結果は取れなさそうでした。
- しかしながらこれらに左右されるということは微々たる差だと予測されます。