mozjpeg/WebPについて、qualityに対するSSIM・ファイルサイズの変化を調査 

# 概要

- 配信しているjpeg画像のファイルサイズを小さくすることによる、インフラ費用削減を検討する機会がありました。
- mozjpegのqualityを変えたり、フォーマットをWebPに変えることで、どの程度ファイルサイズを削減することができるのか調査しました。

# 参考記事

- [JPEG画像をImageMagick/mozjpeg/Guetzliでqualityを変えつつ生成した場合のファイルサイズ、入力画像に対するPSNR、SSIM、butteraugliを比較する](https://qiita.com/kazinoue/items/38b34f9d798400c0d129)
- [あなたのサイトのjpeg画像は過剰品質である。多分。](https://qiita.com/masato_makino/items/28cc2d82d66dbdb12d9a)

# 事前準備

環境はMacです。

```shell
# mozjpeg, webpをインストール
$ brew install mozjpeg
$ brew install webp

# 諸事情によりHomebrewにImageMagick7を入れたりパスを通したりしたくなかったので、7のBinary版を利用。
# https://imagemagick.org/script/download.php から ImageMagick-x86_64-apple-darwin17.7.0.tar.gz をDL
$ tar xvzf ImageMagick-x86_64-apple-darwin17.7.0.tar.gz
$ export DYLD_LIBRARY_PATH=~/Downloads/ImageMagick-7.0.8/lib/
$ export PATH="$HOME/Downloads/ImageMagick-7.0.8/bin/:$PATH"
$ convert --version
Version: ImageMagick 7.0.8-9 Q16 x86_64 2018-08-04 https://www.imagemagick.org
...

# Lenna画像から quality=100, YUV=420のjpg画像を作り、これをオリジナル画像とする。
$ cjpeg -quality 100 -sample 2x2 Lenna.bmp > Lenna_quality100_yuv420.jpg
```
# 調査に使用したコマンド

qualityを100から20まで変化させながら、mozjpegとwebpそれぞれで画像変換し、ファイルサイズ・SSIMを確認。
quality、ファイルサイズ、SSIMをCSVに書き出す。

```shell
for quality in `seq 100 -1 20`; do
  mozjpeg_fname=mozjpeg_quality${quality}.jpg
  webp_fname=webp_quality${quality}.jpg
  cjpeg -quality ${quality} -sample 2x2 ${ORIGIN} > ${mozjpeg_fname}
  cwebp -q ${quality} ${ORIGIN} -o ${webp_fname}
  mozjpeg_ssim=$(compare -metric SSIM ${ORIGIN} ${mozjpeg_fname} diff.jpg 2>&1)
  webp_ssim=$(compare -metric SSIM ${ORIGIN} ${webp_fname} diff.jpg 2>&1)
  mozjpeg_fsize=$(wc -c ${mozjpeg_fname} | awk '{print $1}')
  webp_fsize=$(wc -c ${webp_fname} | awk '{print $1}')

  echo "${quality},${mozjpeg_fsize},${mozjpeg_ssim},${webp_fsize},${webp_ssim}" >> result.csv
done
```
# qualityに対するファイルサイズ・SSIMの変化

![graph1.png](https://qiita-image-store.s3.amazonaws.com/0/45091/461d1b94-8fbb-9c56-14f7-d183931e4fe0.png)

- SSIMのY軸(右)は範囲が 0.8〜1 なのでご注意ください。
- 基本的にWebPの方が視覚差を低く抑えたまま、ファイルサイズを削減できている。
- jpegとWebPどちらについても、qualityと引き換えにファイルサイズを削減できる。プロジェクトの中で、画像の種別(バナー、サンプル、有料コンテンツ、etc)ごとに「画質の劣化をここまで許容できる」という基準を設けるのが重要だと思いました。

# SSIMに対するファイルサイズの変化

![graph2.png](https://qiita-image-store.s3.amazonaws.com/0/45091/94a1293a-b1bf-0b26-1743-0f2e90bbf1f2.png)

- SSIM=0.95(mozjpegのquality=90相当) くらいの高画質では、WebPは(mozjpegの)jpegに比べ20%くらいサイズが小さい。
- SSIM=0.9(mozjpegのquality=68相当) くらいの中画質(?)では、30〜40%くらいサイズが小さい。
- 画質の基準が保守的な場合(劣化は認められない、全てquality=90以上など)、WebPを使うメリットは小さい。
逆に攻められる場合(quality=60相当まで下げてOKなど)、WebPを使うメリットが大きくなる。

# まとめ

- 画像配信のためのインフラ費用を削減したい場合、まず「どのような画像を配信していて、それぞれどこまで画質を下げられるか」を決めることが大切。
  - オリジナル画像を保持しつつ変換した画像を配信する設計にしておけば、「下げすぎた」と思った時すぐもとに戻せる。そのため保守的になる必要はなく、攻めのサイズ削減ができる。
- 画質を中画質(mozjpegのquality60〜70相当?)まで下げられる場合、WebPにすることでサイズを30〜40%削減することができる。
  - ただブラウザの種類やバージョンによってはWebPをサポートしてないので、jpegとWebP両方変換しておいて、呼び出し元に応じて切り替えるのが良さそう。

# おまけ

qualityやSSIMの数値だけ見ても、実際どのくらいの画質かイメージしづらいので、変換後の画像を適当に添付します。

| SSIM | quality |画像 |
|:--|:--|:--|
|0.989212|100|![mozjpeg_quality100.jpg](https://qiita-image-store.s3.amazonaws.com/0/45091/77a84a65-05b0-7feb-611e-6b6ba4e33db9.jpeg)|
|0.96|94|![mozjpeg_quality94.jpg](https://qiita-image-store.s3.amazonaws.com/0/45091/c0f1a5d7-5e66-6309-1dc4-e5ac8a98c759.jpeg)|
|0.94|87|![mozjpeg_quality87.jpg](https://qiita-image-store.s3.amazonaws.com/0/45091/19aff6a2-f10b-d5d7-fed5-d6d0cacefd42.jpeg)|
|0.92|77|![mozjpeg_quality77.jpg](https://qiita-image-store.s3.amazonaws.com/0/45091/faf20616-bf04-cfab-ac9b-2a16b89caf17.jpeg)|
|0.90|67|![mozjpeg_quality67.jpg](https://qiita-image-store.s3.amazonaws.com/0/45091/eec0ae34-9346-7dc8-ee30-25e45db12cbe.jpeg)|
|0.88|53|![mozjpeg_quality53.jpg](https://qiita-image-store.s3.amazonaws.com/0/45091/86f6834a-2982-f6ba-252d-e0c1a53d4833.jpeg)|
|0.86|40|![mozjpeg_quality40.jpg](https://qiita-image-store.s3.amazonaws.com/0/45091/dd001092-38d2-f400-8a52-d023a995e50e.jpeg)|