少し前に WordPress サムネイル再作成はいつやるの と言う記事でサムネイオル画像の再生成と jpg画像の圧縮率変更を行うプログラムに関して紹介しました
その時は jpg画像の画質(圧縮率)を変えただけだったので、png画像についても何とかしたいと思っていました
png画像のサムネイル
画像の形式を jpg にするか png にするかは、目的によって使い分けられ、写真は jpeg 形式(低画質にすると線や文字が判別しにくい)、イラストや文字等なら PNG 形式とされる場合が多いと思います
ただし png 画像は可逆圧縮なので、jpg画像のようにはサイズを縮小化出来ません
そこで、元画像が png形式でもサムネイルだけ jpg形式にすればかなりサイズを縮小化出来るのではないかとやってみました
この機能をceltispack というプラグインに実装してみました
プラグインをインストールして Thumbnail optimize モジュールを有効化すると使用できるようになります
ダウンロードは、WordPress Plugin : Celtispack ページから行うことが出来ます
保存時の jpg画質について
記事に添付された jpeg 画像は、アップロード時に元画像の画質から、サムネイル、中、大サイズにかかわらず画質90という値でリサイズされています
そこで jpeg形式のサムネイル作成時に画質を指定できるようにしています
画質は 0-100 までの間で指定可能ですが、このプラグインでは下記のオプション設定値から選択できるようにしています
- デフォルトモード 画質 [90]
- 画質優先モード 高画質 [100]
- バランスモード 画質 [70]
- サイズ優先モード 低画質 [40]
効果検証
png 形式でキャプチャした画像を PNGoo で縮小化したものを元画像としてサムネイルを作成してみました
元画像
png 形式サムネイル
jpg 形式サムネイル(画質40)
種別 | 大きさ | ビット | サイズ |
元画像 (png) | 480×318 | 8 | 28.8KB |
サムネイル (png) | 160×106 | 32 | 17.7KB |
サムネイル (jpg) | 160×106 | 24 | 2.89KB |
画像をリサイズして、サムネイルを作成するのに jpg形式にするとかなり縮小化出来ることが確認出来ました
png 形式は、文字等を含んだ画像の場合に大変見やすくて良いのですが、サムネイルサイズには jpeg で十分な気がします (^^)
関連記事や新着記事、人気記事等でサムネイル画像を表示する場合に jpg形式にすることで表示スピード等にも結構効いてくるのではないかと思われます
プログラムに興味がある方の為にコードと処理概要を紹介します
処理概要
サムネイルは元画像と同じ形式で作成されている
簡単に説明しますと、サムネイルは画像のアップロード時に自動的に作られるのですが、作成した画像の情報をメタデータとしてデータベースに保存しています
従って、メタデータ(画像情報)は保存時には、元画像をリサイズしてサムネイルを作成する処理は、既に済んでしまっています
例えば、 1920×1080 の jpg 画像なら、サムネイルサイズ、中サイズ、大サイズ、プログラムでカスタムサイズを指定している場合はそのサイズの画像もリサイズして元画像と同じ画像形式で作られています
元画像が png画像ならサムネイルも全て png形式で作成されています
ここまでが、サムネイルを作成する通常の処理です
png から jpg 形式へ変換
ここで、そのメタデータを作成、更新時にフックしてこのプログラムを動作させて、サムネイルサイズごとに jpg画質を変えて保存したり、png形式から jpg形式に変換して保存しようという目論見です (^^)
元の画像が png 形式の場合にサムネイルを jpg形式にすることで、ファイルサイズを縮小化させることを期待できます
サムネイルは画像アップロード時に png形式で作成されますが、そこでフックして png形式の画像を imagecreatefrompng() 関数で読み込み、imagejpeg() 関数で画質を指定して jpeg 形式でも保存します
同じサイズの jpg形式と両方のファイルがファイルが存在することとなりますが、メタデータには jpg画像データを登録しておきます。これにより get_the_post_thumbnail 関数等でサムネイルを取得するときに jpeg形式のサムネイルが取得されるようになります。
プログラム
プログラムは、以前紹介した jpg圧縮率を変えてサムネイルを作成したものを少し修正するだけで実現できました
function celtisone_update_img_quality($meta_id, $attach_id, $meta_key, $attach_meta) { global $celtisone_options; if ($meta_key == '_wp_attachment_metadata') { if ( !empty($attach_meta['sizes'])) { $pathinfo = pathinfo($attach_meta['file']); $uploads = wp_upload_dir(); $dir = $uploads['basedir'] . '/' . $pathinfo['dirname']; $post = get_post($attach_id); if ($post->post_mime_type == 'image/jpeg') { foreach ($attach_meta['sizes'] as $size => $value) { $image = $dir . '/' . $value['file']; $resource = imagecreatefromjpeg($image); if ($size === 'large') { imagejpeg($resource, $image, (int)$celtisone_options['jpeg-large']); } elseif ($size === 'medium') { imagejpeg($resource, $image, (int)$celtisone_options['jpeg-medium']); } elseif ($size === 'thumbnail') { imagejpeg($resource, $image, (int)$celtisone_options['jpeg-thumb']); } elseif ($size === 'small') { imagejpeg($resource, $image, (int)$celtisone_options['jpeg-thumb']); } imagedestroy($resource); } } else if ($post->post_mime_type == 'image/png' && !empty($celtisone_options['thumb-convert'])) { $updatefg = false; foreach ($attach_meta['sizes'] as $size => $value) { if ($size=='small' || $size=='thumbnail' || $size=='medium') { if($value['mime-type'] == "image/png"){ $image = $dir . '/' . $value['file']; $resource = imagecreatefrompng($image); $image = str_ireplace(".png", ".jpg", $image); imagejpeg($resource, $image, (int)$celtisone_options['jpeg-thumb']); imagedestroy($resource); $jpgfile = pathinfo($image); $attach_meta['sizes'][$size]['file'] = $jpgfile['basename']; $attach_meta['sizes'][$size]['mime-type'] = "image/jpeg"; $updatefg = true; } } } if($updatefg) { update_post_meta( $attach_id, '_wp_attachment_metadata', $attach_meta ); //更新すると再帰的にフックされるが、img/png 判定により更新済みとして2回めはスキップさせる } } } } } add_action('added_post_meta', 'celtisone_update_img_quality', 10, 4); add_action('updated_post_meta', 'celtisone_update_img_quality', 10, 4);
プログラム上の注意点としては、メタデータを更新すると再帰的にフックされてくるので、サムネイルサイズ毎の画像形式をチェックして既に処理済みか判定する必要があります
そうしないとフックから抜けられなくなるので注意です (^^)
コードはバージョンアップで追加修正したところもありますので、最新のコードを見たい方は Celtispack プラグインをダウンロードして、modules/thumb-optimize/thumb-optimize.php ファイルを見てください