jpegtranを使った画像最適化について
今回は、jpegtranを使用した画像最適化についてまとめていきます。 経緯として、クスパ-料理教室ポータルサイトで使用している先生方のブログ画像 の容量が膨大になっており、ディスク容量を圧迫していたため画像の最適化を検討しました。
jpegtranについて
jpegtranは、jpeg画像のメタ情報を削除することで、画像の圧縮を実現するためのツールになります。 以下のように使うのが基本形です。 jpegtran -copy none -optimize -outfile "出力ファイル" "投入ファイル" ※投入ファイルが最適化したい元画像、出力ファイルが最適化後のファイルになります。
オプションについて | |
---|---|
-copy none | jpegのメタデータを全て削除する。 |
-optimize | ハフマン符号を最適化する。 |
注意点として、投入ファイルと出力ファイルを同一名にすることが仕様上できないことです。 例えば、投入ファイル名 abc.jpg → 出力ファイル名 abc.jpgという設定はできません。 そのため、出力ファイルを別名とした上で、リネームして投入ファイル名に戻すなどの対応 が必要になります。 ※今回は、拡張子jpgの後に.optを加え元画像と区別した。
画像最適化のために使用したコード例(検証版)
WORK_ROOT=/---/---/--- echo $WORK_ROOT for TARGET in `find $WORK_ROOT/blog \( -name \*.jpeg -o -name \*.JPEG -o -name \*.JPG -o -name \*.jpg \) -and -daystart -mtime +7 | head -n 1000` do echo '####target list is '$TARGET jpegtran -copy none -optimize -outfile "${TARGET}.opt" "${TARGET}" if [ "${TARGET}.opt" ]; then find . -name "*.opt" | xargs rename .opt '' * ※1 fi done
検証段階ではこのような形でシェルスクリプトを作成し、実行していました。 まず、対象となるjpeg画像をfindし、TARGETにセットします。 -daystart -mtime +7としているのは、現在から過去7日目を基準として そこから過去全ての期間を対象とするオプションになります。 負荷対策のため、処理対象をheadで限定し、1000件としました。
$TARGETには、取得した1000件の1件ずつが入り、jpegtranを1件ずつ かけていきます。if文で出力ファイル(.opt)の存在チェックをし、投入ファイル (元画像)を削除するということを行っています。その後、.optファイルを元の 拡張子(jpgなど)に戻すということをしています。
結果的にこのコードを本番でそのまま採用するには至りませんでした。 以下の二点が理由になります。 ① if文の存在チェックがスルーされ、jpegtranが失敗した場合に出力ファイル(.optファイル) ができていないのに、元画像を削除しまっていた。 ② ※1のfindの処理が不必要な範囲で検索をかけてしまっている。
画像最適化のために使用したコード例(本番)
WORK_ROOT=/---/---/--- echo $WORK_ROOT count=0 for TARGET in `find $WORK_ROOT/blog \( -name \*.jpeg -o -name \*.JPEG -o -name \*.JPG -o -name \*.jpg \) -and -daystart -mtime +7 | head -n 1000` echo '####target list is '$TARGET jpegtran -copy none -optimize -outfile "${TARGET}.opt" "${TARGET}" if [ -f "${TARGET}.opt" ]; then rm $TARGET mv ${TARGET}.opt $TARGET fi echo $count count=$((count+1)) if [ $((count%1)) -eq 0 ]; then echo 'sleep' sleep 0.01 fi
理由①の改善として、-fオプション(fileが存在し、且つ、通常のファイル) を入れることでファイル存在のチェックが効くようになりました。 理由②の改善は、renameを使った記述ではうまくいかず、moveで対応して 不必要なfindを省略できました。 さらに、処理する際の負荷を一定にするために1件処理する毎にsleep処理を挟むように 改善しました。
結果・まとめ
Blog画像の容量 (before)173G→(after)169G -4Gという結果で当初予想していたより効果が 出なかったので残念ではありますが、一通りの流れと地雷ポイントがわかったことが収穫でした。 元画像を削除してしまうというリスキーな面があるので、バックアップは必須です! 以上となります。