shibuya

PHPのGDでサムネイル(縮小)画像を生成する

画像を扱うウェブサイトではサムネイル画像も用意していると便利です。今回、サムネイルをPHPで生成するにあたって調べた事をメモしておきます。

GD, or not GD

PHPで画像処理をする場合、GDImageMagickが人気です。これらの違いですが、php.netの関数リファレンスを見比べるにImageMagicGDよりも豊富な機能を提供しているようです。しかしながら、 GDは手軽さの点で優れています。PHP 4.3以降GDライブラリがPHPに付属しているので、何もしなくても、すぐに使いはじめることができるのです。

今回の目的はサムネイルの生成という基本的な操作ですから、GDでも十分です。ということで、以下、GDを使っていることが前提です。

画像のサイズを変更する関数は複数ある

GD および Image 関数を眺めると気付くかもしれませんが、イメージのサイズを変更する関数が複数あります。

  1. imagecopyresized
  2. imagecopyresampled
  3. imagescale

これらの違いは、各関数の説明を読んでも、はっきりとは理解できませんでしたが、なんとなくまとめると次の通り。

  • imagecopyresizedとimagecopyresampledは画像の一部、または全部を切り取ってサイズを変更する。
  • imagescaleは切り抜かずにサイズを変更する。
  • imagecopyresizedと違いimagecopyresampledはより高度な補完処理が行われるので、綺麗にリサイズされる。
  • imagescaleも補完処理が行われるが、補間アルゴリズムを選択できるので品質はアルゴリズムによる。

リサイズとリサンプルの違いが分からなかったので間違っているかもしれないですが、こんな感じで把握しました。

さて、サムネイル画像用途の場合、普通、クリッピングはしないですから、1,2,3の関数の違いは(補完アルゴリズムの)品質の差ということになりそうです。

サムネイルのクオリティを確かめる

それでは実際に各関数でどのようなサムネイルが生成されるのかを見ていきたいと思います。この確認のため、次のようなファイルを書きました。

Thumbnailer.php

test.php

デモ

Shibuya Scramble CrossingYoshikazu TAKADA

最初のデモはこの画像のオリジナルで、6000*4000、9.2MBのjpgです。これを各のアルゴリズムで300pxのサムネイルにして見てみます。



ファイル名から分かるように上から、imagescaleのIMG_NEAREST_NEIGHBOUR、IMG_BILINEAR_FIXED、IMG_BICUBIC、IMG_BICUBIC_FIXEDとimagecopyresized、imagecopyresampledです。

パッと各サムネイルを見て、分かりやすいのがIMG_BICUBICとimagecopyresampledだと思います。他のサムネイルは全体的にノイズが混じったように感じられるのに対して、この二つは若干ぼやけて見えるものの、オリジナルに近い印象を受けます。

また、IMG_BICUBICとimagecopyresampledを比較すると、微妙ではありますが、IMG_BICUBICのサムネイルは全体的に暗くなっている風に見えます。なお、処理にかかった時間は次の通り。

IMG_NEAREST_NEIGHBOUR 0.03600001335144 sec
IMG_BILINEAR_FIXED 0.060999870300293 sec
IMG_BICUBIC 0.35600018501282 sec
IMG_BICUBIC_FIXED 0.093999862670898 sec
RESIZED 0.039000034332275 sec
RESAMPLED 1.6480000019073 sec

一回しか測っていないのでアレですが、imagecopyresampledが圧倒的に重い処理のようです。新しいとは言えないPCですが、1.6秒もかかっています。また、IMG_BICUBICもやや重い処理です。

次に2次元イラストでも確かめてみます。デモに使ったのはこちらの初音ミク(Hatsune Miku by Crypton Future Media, INC. 2007)。600pxから300pxのサムネイルで、順番は同じです。



このデモでも先ほどと同じ傾向があり、IMG_BICUBICとimagecopyresampled以外はエッジにジャギーが目立ちます。なぜかIMG_BICUBICに黒い線が入ってしまっていますが 🙁

処理時間は以下

IMG_NEAREST_NEIGHBOUR 0.068000078201294 sec
IMG_BILINEAR_FIXED 0.072000026702881 sec
IMG_BICUBIC 0.11800003051758 sec
IMG_BICUBIC_FIXED 0.15699982643127 sec
RESIZED 0.069000005722046 sec
RESAMPLED 0.10700011253357 sec

今回、imagecopyresamepledがIMG_BICUBICと同じぐらいになっています。どうやらimagecopyresampledは振り幅が大きいようです。ソース画像が巨大だと苦手なのか、あるいはイラストが得意なのでしょうか。

まとめ

サムネイルの品質で言えばimagecopyresampledに軍配が上がりそうです。リソースに余裕があり、サムネイルを静的に生成するケースに最適ですね。逆に、頻繁に、もしくは動的にサムネイルを生成したりするような場合はimagescaleでIMG_BILINEAR_FIXEDやバランスの良いIMG_BICUBICを使うと良さそうです。