Imlib2でImageMagickより3倍高速かつ美しいサムネイル画像の生成

この記事の概要

Imlib2を使って画像のサムネイルを生成してみたところ、ImageMagickより3倍速かった。
また一般的には、Imlib2の方が画質が悪いとされているが、パラメータを調整することで、十分に美しいサムネイル画像を得ることができた。

はじめに

Imlib2は画像処理ライブラリ。mixiの発表資料大規模画像配信とPerl によれば、mixiは高速に高品質なサムネイルを生成するために、ImageMagickでなくImlib2を選んでいる。
上記資料の中では、以下のように説明されている。

速度
  Epeg > Imlib2 > Imager >>> ImageMagick
画質
  ImageMagick > Imlib2 >>> Epeg

Imlibの画質は多少ImageMagickに劣るが、速度は十分に速い、とのこと。
一方で、404 Not Foundという記事では、ImageMagickのベンチマーク記事が紹介されており、やはりImageMagickは遅い、という結論になっている。同記事では、画像を開いて保存するというだけのベンチマークで、ImageMagickとImlib2の速度差は10倍弱の開きがある。ImageMagickはファイルの入出力のオーバヘッドが大きいことが分かる。
というわけで、Imlib2を試してみる。

インストール

Imlib2はCで書かれており、RubyバインディングであるImlib2-Rubyも公開されている。ここでは、このImlib2-Rubyを使ってImlib2を試すことにする。
Imlib2-Rubyは、rubyforgeなどに上がっていないため、自分でgemをダウンロードしてインストールする必要がある。
以下、Macの場合。

$ sudo port install imlib2
$ wget http://pablotron.org/files/gems/imlib2-ruby-0.5.2.gem
$ gem install imlib2-ruby-0.5.2.gem

使い方(サムネイル生成)

ImageMagickには、便利なGeometry機能があって、アスペクト比についてよきにはからってくれるが、Imlib2では自分で計算する必要がある。
とりあえず、横幅180px*1にリサイズしてみる。

require 'rubygems'
require 'imlib2'

img = Imlib2::Image.load("1.jpg")
new_w = 180
new_h = ((new_w.to_f / img.w) * img.h).round
img.crop_scaled!(0, 0, img.w, img.h, new_w, new_h)
img.save("out.jpg")

これで横幅180pxのout.jpgが作成された。
Imlib2にはcropとscaleを同時に行うメソッドしかなく、scaleのみを単体で行うことができないようだ。Rubyバインディングが手抜きなのかと思ったが、元のC APIにもそのようなメソッドが無いので、そういうものらしい。

ImageMagickとの比較1: 速度

ImageMagick(RMagick)とImlib2(Imlib2-Ruby)を用いて、両者のサムネイル作成速度を比較する。

テスト環境
コード

4288x2848のJPG画像(4.8MB)から横幅180pxのサムネイルを10回ずつ作成し、平均速度を比較した。
ベンチマークのコードは以下に上げてある。
Benchmark Imlib2 vs ImageMagick — Gist

結果
ライブラリ 1枚あたりの変換時間
ImageMagick 1.061849 sec
Imlib2 0.348064 sec

約3.05倍Imlib2の方が高速だった。確かに、速い。

ImageMagickとの比較2: 変換後のファイルサイズ

サムネイル変換後のファイルサイズを比較した。

ライブラリ 変換後のファイルサイズ
ImageMagick 59.0KB
Imlib2 5.0KB

ImageMagickの方が約11.8倍大きかった。この差が画質の差にも現れているのかもしれない、とこの時点では思った。

ImageMagickとの比較3: 画質

上記の実験で生成されたサムネイル画像の画質を目視で比較した。
元画像

ImageMagick Imlib2
59.0KB 5.0KB

俺には明らかな違いがあるように見える。肉のエッジに注目されたい。どっちのバンバンジーが美味しそうに見えるだろうか?
拡大してみる。(左:ImageMagick, 右:Imlib2)

Imlib2(右)の方は、肉と皿、皿と机の境界が荒くなっているのが分かる。食材の輪郭もぼやけている。
ただし画質に違いがあると言っても、ファイルサイズは12倍近く違うわけで、画質を比較するのは酷というものだ。

Imlib2で画質を調整してみる

Imlib2-Rubyソースコードを読んでいたら、以下のようにして出力画像のクオリティを調整できることに気づいた。

img.crop_scaled!(0, 0, img.w, img.h, new_w, new_h)
img['quality'] = 80   # このようにしてクオリティを調整できるらしい。値域はたぶん 0〜100
img.save("out.jpg")

クオリティを 80, 90, 100 にしてみて、変換速度およびファイルサイズ、画質を比較してみた。

クオリティ デフォルト 80 90 100
画像
ファイルサイズ 5.0KB 5.4KB 7.6KB 20KB
変換時間 0.363925 sec 0.332079 sec 0.332087 sec 0.329928 sec

quality値を指定しなかった場合のデフォルトのqualityは分からない。ただし、quality=80のときよりもファイルサイズが小さいので、80以下であろうことが予想できる。
qualityを指定しても、変換時間については有意な差が見られなかった。

拡大してみる。(左から、デフォルト、80、90、100)

さすがに100は綺麗であり、ブロックノイズが見られない。90となると、多少ブロックノイズが出ているが、サムネイルを肉眼で見てもあまり差がないことから、90なら許容できる程度の美しさであると感じた。Webサービスなどで、ファイルサイズにシビアであり、さらに画質も求められる場合には、quality=90にするのがいいだろう。なにより、90と100ではファイルサイズが倍以上違う。
デフォルトおよび80については、ブロックノイズが気になった。

ImageMagick再び

最後に、ImageMagickで生成したサムネイルは、一般的に言われているように、本当にImlib2より綺麗なのかを再度比較してみる。
左から、ImageMagick、Imlib2(quality=90)、Imlib2(quality=100)である。

ブロックノイズという観点では、ImageMagickの出力は、Imlib2(quality=90)に劣っているように見える。(しかし、食材の立体感についてはImageMagickの方が上回っているように感じる。)
さらに、ファイルサイズおよび変換時間を比べてみる。

ライブラリ クオリティ 変換後のファイルサイズ 変換時間
ImageMagick デフォルト 59.0KB 1.061849 sec
Imlib2 90 7.6KB 0.332087 sec
Imlib2 100 20.0KB 0.329928 sec

Imlib2で最高画質のサムネイルを生成しても、ImageMagickよりファイルサイズが小さいという点に注目されたい。
今回の条件下においてImlib2は、変換時間、ファイルサイズ、画質ともにImageMagickに優っている。

追記(2010/07/24)

ImageMagickの画像のファイルサイズが大きいのは、EXIF情報が含まれているからだそうです。これを取り除くことで、ファイルサイズを抑えることが可能です。

まとめ

Imlib2を使って画像のサムネイルを生成してみたところ、ImageMagickより3倍速かった。
また一般的には、Imlib2の方が画質が悪いとされているが、qualityパラメータを調整することにより、高品質のサムネイル画像を得ることができた。
ただ、同程度のブロックノイズが入った画像を比較した場合、ImageMagickの出力の方が立体感があり、Imlib2の出力は多少のっぺりとした印象も否めない。
画質の正確な比較のためにはImageMagickにおける画質のチューニングも行うべきであるが、ImageMagickはそもそも入出力の速度がImlib2に劣っているので、それ以上は追究しなかった。

蛇足

Imlib2-Rubyの公式サイトに置かれているサンプル画像がひどい。この画像はImlib2-Rubyにも同梱されており、大変にクレイジー。

参考資料

*1:横幅180pxはmixiのプロフィール画像と同じ。