はじめに
WordPressでは初期状態だと、GDというライブラリを使って画像のリサイズや画像ファイルそのもののサイズ削減が行われています。
これらはアップロード時に自動で実行されるため、便利な機能ではあるのですが、画像ファイルのサイズ削減に関しては別のツールを使った方がより効果的にファイルサイズを削減することができます。
この記事ではGDライブラリを使いつつ、画像ファイルのサイズ削減にはOxipngやmozjpeg、pngquantといった画像圧縮ツールを使い、そして画像アップロード時にはそれらを使ってリアルタイムに変換を行う方法を紹介します。
サーバのスペックおよび構成は以下の通りです。
$ cat /etc/lsb-release- DISTRIB_ID=Ubuntu
- DISTRIB_RELEASE=20.04
- DISTRIB_CODENAME=focal
- DISTRIB_DESCRIPTION="Ubuntu 20.04.3 LTS"
Oxipng
Oxipngはマルチスレッドで実行可能な、ロスレス(Lossless)PNG圧縮エンコーダです。
- shssoichiro / oxipng
もともとOptiPNGという有名な画像圧縮ツールの代替として作成されたものであり、OptiPNGを改良する際にはマルチスレッドの実装を目標としていました。
しかし、C言語で作られたOptiPNGの既存コードではそれを実現するには困難であったことから、言語をRustに変更し、その後マルチスレッドを実装しています。
Oxipngではマルチスレッドで実行できることから、従来のシングルスレッドのみを使用するツールと比べ、とても高速に処理を行うことができます。 ではOxipngの導入ですが、まずRustをインストールする必要があるため、 Rustのインストールが完了したら その後 それが完了したら そして 最後に この状態で ただし、 表記無しでは画像のインターレースには何もしません。 ちなみに なお、コマンドのより詳しい情報は 以下は簡単な使用例です。Oxipngのインストール
$ curl https://sh.rustup.rs -sSf | shを実行して各種Rustパッケージをインストールします(オプションは1のProceed with installationを使用)。$ source $HOME/.cargo/envで環境変数をセットします。$ cargo --version、$ rustc --version、$ rustdoc --version、$ rustup --versionでそれぞれのバージョンをチェックし、無事インストールできていることを確認します。$ git clone https://github.com/shssoichiro/oxipng.gitでOxipngのリポジトリを複製します。$ cd oxipngでディレクトリを移動し、/oxipng$ cargo build --releaseによってビルドを実行します。/oxipng$sudo cp target/release/oxipng /usr/local/binでOxipngを簡単に使えるようにします。$ oxipng --versionを実行するとOxipngのバージョンを確認(執筆時点ではv5.0.1)でき、Oxipngが使用可能となりました。Oxipng使用方法
-o 値は最適化レベルを表し、1~6,maxの順に圧縮レベルが高くなります(デフォルトは2)。4を超えた場合の影響は少なく、実行時間に対してより多くを圧縮できることは少ないです。-i 0 or 1はインターレースの有無を表し、0で削除、1で有効化し、アルゴリズムはAdam7PNGを使用します。--out ファイルパスは出力先の場所およびファイル名を指定します。--strip safe or allは画像のメタデータを削除する設定です。safeは画像の描画に影響しないメタデータを削除します(-sでも同じ設定)。allは全てのメタデータを削除します。--zopfliを加えることで、zopfliのアルゴリズムを用いてより効果的な圧縮もできます(ただし処理はかなり遅いのでリアルタイム処理には向いていない)。$ oxipng -hを実行することで閲覧できます。// 通常圧縮
$ oxipng image.png
// 高度な圧縮
$ oxipng -o 4 -i 0 -s image.png --out output.png
// 最高レベルの圧縮
$ oxipng -o max -i 0 -s image.png --out output.png
mozjpeg
mozjpegはJPEGファイルの圧縮効率および品質の向上を目的とした画像処理ツールです。
jpegtranは可逆圧縮(Lossless)を行い、cjpegは非可逆圧縮(Lossy)を行います。
- mozilla / mozjpeg
開発はウェブブラウザのFirefoxで有名なMozillaが行っており、また、mozjpegはlibjpeg-turboからフォークされていることから、コマンドが類似しています。
mozjpegは従来の画像エンコーダーよりも圧縮効率が向上しているにも関わらず、画質の劣化が少ないことから大変便利なツールとなっています。
更にmozjpegで処理したJPEGは大半のJPEGデコーダーと互換性があるため、これまで通り問題なく画像を使用することができます。 まずは 次に 複製後は 次に 最後に これでmozjpegのインストールは完了しましたが、モジュールは jpegtranの場合は これでシンボリックリンクの作成も完了しました。 mozjpegtranの場合、 mozcjpegの場合、 どちらもコマンドの詳細は 以下は簡単な使用例です。mozjpegのインストール
$ sudo apt install cmake autoconf automake libtool nasm make pkg-config git libpng-devで必要となる各種パッケージをインストールします。$ git clone https://github.com/mozilla/mozjpeg.gitでmozjpegのリポジトリを複製します。$ cd mozjpegでディレクトリを移動し、更に/mozjpeg$ mkdir build && cd buildでビルド用ディレクトリに移動します。/mozjpeg/build$ sudo cmake -G"Unix Makefiles" ../を実行してMakefileを作成します。/mozjpeg/build$ sudo make installによりコンパイルされたファイルをインストールします。/opt/mozjpeg/に存在しているため、シンボリックリンクを作成することで使い勝手を良くします。$ sudo ln -s /opt/mozjpeg/bin/jpegtran /usr/bin/mozjpegtran、cjpegでは$ sudo ln -s /opt/mozjpeg/bin/cjpeg /usr/bin/mozcjpegを実行します。mozjpeg使用方法
-copy noneはコメント等の画像内に含まれる情報を削除します。-qualityは画像の品質を0から100までの間で選択します。デフォルトは75です。-outfileは>を使わずに出力ファイルを指定する方法です。この場合、-outfile 出力後ファイル 対象ファイルの順になっています。-hを付けることで閲覧することができます。// 可逆圧縮
$ mozjpegtran image.jpg > output.jpg
// 非可逆圧縮
$ mozcjpeg image.jpg > output.jpg
// 高度な可逆圧縮
$ mozjpegtran -copy none -outfile image.jpg output.jpg
// 高度な非可逆圧縮
$ mozcjpeg -quality 80 -outfile image.jpg output.jpg
pngquant
pngquantはPNG画像の形式を8ビットPNG形式に変換することで、ファイルサイズを削減する非可逆圧縮(Lossy)のエンコーダです。
もともとC言語(C99)で作成されていましたが、Rustで書き直された新しいバージョンが存在しており、今回はRust版を使用します。
- kornelski / pngquant
- pngquant
pngquantで24もしくは32ビットのPNG画像を8ビットに変換させた場合、見た目の悪影響を抑えつつ60~80%ほどファイルサイズを縮小させることが可能です(多彩な画像では見た目の劣化が大きくなる場合があります)。
変換後の互換性も問題が無く、すべてのブラウザおよびOSで正常に描画することができます。 Oxipngの項目でRustは既にインストール済みとみなして進めていきます。 まずは 次に ビルド後は この状態で その他コマンドなどの詳細は 以下は簡単な使用例です。pngquantのインストール
$ git clone --recursive https://github.com/kornelski/pngquant.gitでpngquantのファイルを複製します。$ cd pngquantでディレクトリを移動し、/pngquant$ cargo build --releaseでビルドします。/pngquant$sudo cp target/release/pngquant /usr/local/binによってpngquantを簡単に使えるようにします。$ pngquant --versionを実行することで、現在のバージョンをチェックできます(執筆時点ではv3.0.0-beta.7)。pngquantの使用方法
--quality 数値は画像の品質を意味しており、0から100までの数値を範囲指定することができます。--ext 名前.pngは出力されるファイルを拡張子含めカスタマイズします。--ext = .png --forceを使うと入力ファイルごと上書きされるので注意。--output 名前.pngは指定した場所にファイルを出力します(-oでも可能)。ただし、このオプションを使うと複数の画像を処理できません。--forceは出力した先に同名のファイルが存在している場合に上書きします。--speed 数値はエンコードの速度を1から11までの数値で指定します(デフォルトは4)。1は最も遅いが品質は高くてサイズは小さく、11はその逆です。$ pngquant -hで閲覧できます。// 通常圧縮
$ pngquant image.png
// 高度な圧縮
$ pngquant --quality 80 -o output.png image.png
// 最高レベルの圧縮
$ pngquant --quality=60-70 --speed 1 -o output.png image.png
WordPressでの自動画像処理
では実際にWordPressでこれらエンコーダを使用して圧縮する方法を紹介します。
先述したように、これはWordPressで画像をアップロードした際に自動で圧縮を行う設定です。
これらはすべてfunctions.phpに記載するだけで機能しますが、圧縮率に関してはそれぞれチェックして調整することをおすすめします。
また、今回の例ではJPEG画像に限り非可逆圧縮後に可逆圧縮も施していますが、可逆圧縮のみを行いたい場合など、これも好みで変更してください。
functions.php
/** 省略 **/
// 無駄に圧縮されるため、WordPress側の自動圧縮は無効化
// WPによる自動画像圧縮を無効
add_filter('jpeg_quality', function($arg){return 100;});
add_filter( 'wp_editor_set_quality', function($arg){return 100;});
// 画像のアップロード後に画像を圧縮
function compress_images($metadata, $img_id){
// アップロードした画像のフルパス
$org_path = get_attached_file( $img_id );
// アップロードした画像のファイルタイプを取得
$img_type = get_post_mime_type( $img_id );
// ファイルタイプが [JPEG(JPG)] の場合
if( $img_type == 'image/jpeg' ){
// 元画像を圧縮 START
// 非可逆圧縮後に可逆圧縮(品質80パーセント)
$output = shell_exec("mozcjpeg -quality 80 '$org_path' > '$org_path.jpg' && mozjpegtran -optimise -copy none '$org_path.jpg' > '$org_path' && rm '$org_path.jpg'");
// 元画像を圧縮 END
foreach ( $metadata['sizes'] as $size => $value) {
// 元画像に対する全てのサムネイルを圧縮 START
// 全てのサムネイルのフルパスを取得
$thumb_path = dirname($org_path).'/'.$value[ 'file' ];
// 全てのサムネイルを非可逆圧縮後に可逆圧縮(品質80パーセント)
$output = shell_exec("mozcjpeg -quality 80 '$thumb_path' > '$thumb_path.jpg' && mozjpegtran -optimise -copy none '$thumb_path.jpg' > '$thumb_path' && rm '$thumb_path.jpg'");
// 元画像に対する全てのサムネイルを圧縮 END
}
}
// ファイルタイプが [PNG] の場合
if( $img_type == 'image/png' ){
// 元画像を圧縮 START
// 以下は必要に応じて使いたいものをコメントアウト解除してください
// 可逆圧縮(効果小)
$output = shell_exec("oxipng '$org_path'");
// 可逆圧縮(効果中)
// $output = shell_exec("oxipng -o 6 -s '$org_path'");
// 最大レベルの可逆圧縮(効果中~大・負荷大)
// $output = shell_exec("oxipng -o max -i 0 -s '$org_path'");
// 非可逆圧縮(効果中~大、負荷中、品質65~80)
// $output = shell_exec("pngquant --quality=65-80 --speed 1 --ext .png --force '$org_path'");
// 元画像を圧縮 END
foreach ( $metadata['sizes'] as $size => $value) {
// 元画像に対する全てのサムネイルを圧縮 START
// 全てのサムネイルのフルパスを取得
$thumb_path = dirname($org_path).'/'.$value[ 'file' ];
// 以下は必要に応じて使いたいものをコメントアウト解除してください
// 可逆圧縮(効果小)
$output = shell_exec("oxipng '$thumb_path'");
// 可逆圧縮(効果中)
// $output = shell_exec("oxipng -o 6 -s '$thumb_path'");
// 最大レベルの可逆圧縮(効果中~大、負荷大)
// $output = shell_exec("oxipng -o max -i 0 -s '$thumb_path'");
// 非可逆圧縮(効果中~大、負荷中、品質65~80)
// $output = shell_exec("pngquant --quality=65-80 --speed 1 --ext .png --force '$thumb_path'");
// 元画像に対する全てのサムネイルを圧縮 END
}
}
return $metadata;
}
add_filter( 'wp_generate_attachment_metadata', 'compress_images', 10, 2 );
/** 省略 **/
以上の設定により、画像アップロード時に自動で元画像および全てのサムネイル画像が圧縮されます。
おわりに
GDライブラリの代替として、ImageMagickと呼ばれるライブラリがあるのですが、これは多くの脆弱性を指摘されたり、そもそもGDとの差をそこまで感じられないことから今回は採用を見送っています。
初期状態のWordPressでは多くのサムネイルを作成するため、サーバの空き容量が少ない場合は割と逼迫しがちになりますが、紹介したこれらエンコーダを使用することでより多くのスペースを確保することができます。
画像ファイルの削減だけでなく高品質な画像を保ったまま圧縮できることから、ウェブサイトそのものの品質を向上させることができるでしょう。
参考資料
- 「GD vs ImageMagick」PHPで画像加工性能比較
- 「さようなら ImageMagick」の考察
- UbuntuにRustをインストールする
- Ubuntu に画像エンコーダー「mozjpeg」をインストールする
- How to install MozJPEG on macOS and Ubuntu
- Makefileの書き方
- configure, make, make install とは何か
- tarのコマンドの覚え方(´・ω・`)版
- 「tar zxvf」を使うのはオジサンだけ!?自動で認識されるので「z」「j」「J」の指定は不要!
- get_attached_file()