画像ファイル(jpg,png)をmozjpegなど使ってサイズを減らしたい

20200112 cjpegの非可逆圧縮オプションを追加
20230715 webp生成コードを追加

# 納品ルールが変わった
ある日納品ルールが変わって、「[TinyPNG](https://tinypng.com/)を通した画像ファイルを納品せよ」となった。
前々から画像ファイルの最適化はしないといけないと思っていたので、
この機会にどんな方法があるか考えてみた。

# スタンドアロンのフロントエンドアプリがあった
https://boldright.co.jp/products/antelope/
これが便利なのでバッチ外で動かしたい場合はこっちをおすすめ。
jpegはかなり圧縮してくれる模様。pngはバッチのほうがサイズ削減される模様。
圧縮レベルは3辺りでよさげ。jpeg q70くらいに設定されるという記述をどこかで見た。

| 設定状況 | サイズが減るイメージ |
|:-----------------|------------------:|
| ![コメント 2020-01-28 151502.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25349/aae6baa5-a785-f12c-01cd-09d41a0fdcfd.png) | ![コメント 2020-01-30 103446.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25349/68129632-2bb0-026a-e676-8359e7243e3b.png)
 |




# Googleの画像圧縮Webアプリもあった
https://squoosh.app/
Webアプリ。クライアントサイドで圧縮するみたいなので負荷は気にする必要なさげ。

# 自然な流れでファイルを最適化したい
Gulp等のタスクランナーで画像ファイルを最適化するタスクがあることは知っていた。
ぜひ開発環境に取り入れたいと思っていて試行錯誤してたんだけど、、
結局、ローカルサーバ上で腰を据えてやる静的コーディングの仕事ばかりではないので、うまい流れで普段のワークフローに取り入れられずにいた。。
（不勉強で言うのもなんだけど、客先サーバー上でWP弄りつつ作業するようなスタイルには向いてないんだと思っている）
なので、別の方法を考えてみた。
いちいちWebアプリ通して納品するのはまずは考えないことにした。。

### WinSCPでファイルアップロード時にバッチとか動かせないか
普段使っているFTPソフトに一段噛ませるソリューション。
ただ、軽く検索した限りだとGUIではそういうのできなさそう、あきらめる。

### SourceTreeでコミット時にバッチ動かせないか
こっちはすぐ見つかった。
[ワークフローにおける画像の最適化](https://1000ch.net/posts/2016/optimize-image-on-workflow.html)や、その参考サイトとして挙げられている[arnaud-lb/pre-commit.sh](https://gist.github.com/arnaud-lb/4181829)などを参考にして、四苦八苦。
やっと動いたのでアツいうちにQiitaにまとめる。

# SourceTreeでのpre-commitで実行バッチ
.git/hooks/pre-commit.sampleをpre-commitにリネームして、内容を置き換える。
その後、ソースの上のほうを環境に合わせて書き換える。
[pngquant](https://pngquant.org/)と、[jpegtran](http://jpegclub.org/jpegtran/)か[mozjpegのcjpeg](https://mozjpeg.codelove.de/binaries.html)を使用するのでDLして、.exeとmozjpegのほうはライブラリファイル(libjpeg-62.dll)を「util一時パス」のとこに置いておく。
gitはOS側にパス通しているならpath記述自体いらないです。

```sh:pre-commit
#!/bin/sh
export PATH="C:\@work\@@utils:$PATH" #util一時パス追加
export PATH="C:\Users\xxxxx\AppData\Local\Atlassian\SourceTree\git_local\bin:$PATH" #git一時パス追加
command -v pngquant.exe >/dev/null 2>&1 || {
    echo "Please install pngquant to reduce images size before commit"
    exit 1;
}
command -v jpegtran.exe >/dev/null 2>&1 || {
    echo "Please install jpegtran to reduce images size before commit"
    exit 1;
}
command -v cjpeg.exe >/dev/null 2>&1 || {
    echo "Please install cjpeg to reduce images size before commit"
    exit 1;
}
command -v cwebp.exe >/dev/null 2>&1 || {
    echo "Please install cwebp to reduce images size before commit"
    exit 1;
}

# 特別フォルダ以下指定 webp作成
for file in `git diff --cached --name-status|awk '$1 ~ /[AM]/ && tolower($2) ~ /XXXXX.+\.(jpe?g|png)$/ {print $2}'`;
do
echo "Crushing ${file%.*}.webp"
  cwebp.exe $file -quiet -q 90 -m 3 -o "${file%.*}.webp"
  git add $"${file%.*}.webp"
done

for file in `git diff --cached --name-status|awk '$1 ~ /[AM]/ && tolower($2) ~ /\.png$/ {print $2}'`;
do
echo "Crushing $file"
  pngquant.exe --force --skip-if-larger --quality=65-100 --ext=.png $file | grep "filesize"
  git add $file
done

for file in `git diff --cached --name-status|awk '$1 ~ /[AM]/ && tolower($2) ~ /\.jpe?g$/ {print $2}'`
do
echo "CrushingJPG $file"
  #jpegtran-static.exe -copy none -optimize -outfile $file $file | grep "filesize"
  # jpegtran.exe -copy none -optimize -outfile $file $file | grep "filesize"
  # cp $file "${file}_tmp"
  cjpeg.exe -optimize -quality 80 -outfile "${file}_tmp" $file | grep "filesize"
  mv "${file}_tmp" $file
  git add $file
done
#exit 1 # test abort
```
ざっくりの解説。
1. 必要なライブラリが無ければ警告をだして終了
2. 画像ファイルを拾って変換。大丈夫だと思うけど、強制上書きしているので画像はちゃんと見れるかアップロード前にチェックしないと取り返しがつかないことになります。
3. 動作テスト時用に、exit 1すれば本コミットが走らない記述を一応コメントアウトで残してます。

# 感想
pngは結構ファイルサイズが減る！1/3～1/4くらいになるね！　~~jpegは全然減らないね。。~~ → -perfectオプションが余計だった模様。。外しました。4/5ぐらいのファイルサイズになる感じ。
ワークフローとしては、コミット後に、納品時にサーバー上の画像ファイルを全上書きアップロードする感じで。

追記(pngの場合）
quality=65-85だと、まれに画質が悪化する模様。100まで可にすると再現しなくなったので、100にしておくと安心。
ただしファイルサイズは1/2くらいになる印象。

追記(jpegの場合)
jpegtranだけでなくcjpegを使った場合をようやく試す。
非可逆圧縮なのでガンガンファイルサイズ減るが、q95くらいでも半分以下サイズにはなるので劇的。
今年はjpegも非可逆圧縮でガンガン攻めていこうと思う。

しっかし、Windows環境でのWeb系技術サンプル挙げてるサイト、まことに少なくなり申した。
Web系はMacの時代なんだなあ…

追記（webp画像の生成追加）
webpを同時に配置したいというケースを受け、webpコードを追加。
画像の圧縮前に動かしたいので、２か所に同内容を追記した。
libwebpを配置してください。
https://developers.google.com/speed/webp/download?hl=ja

コード最適化。webpについては必要な会社が絞られると思うのでその対応コードを追加。
個人的には管理ファイルが増えるのはお好みではないので、WPプラグインで勝手に自動的にでなんとかしたいな。。