読者です 読者をやめる 読者になる 読者になる

サムネイル画像の作成 - ImageMagick, GraphicsMagickのコマンドとJava, .NETの標準API

Java C#

サムネイル画像を以下のような方法で作成してみました。

細かいパラメータ指定などは行わず、サイズ 2048x1536, ファイルサイズ 1.4MB の JPEG ファイル(sample.jpg)のサムネイル画像(サイズ 100x75)を作成します。

ちなみに、今回作成した Java .NET のサンプルは ImageMagick 等に比べると処理時間・画質・ファイルサイズ等の点で劣るので、あまり実用的とは言えないかもしれません。

サンプルソースは http://github.com/fits/try_samples/tree/master/blog/20110508/

ImageMagick, GraphicsMagick によるサムネイル画像作成

ImageMagickGraphicsMagickは以下のようなコマンドを使ってサムネイル画像を作成する事ができます。

  • convert コマンド (ImageMagick)
  • gm convert コマンド (GraphicsMagick)

ImageMagick と GraphicsMagick で同じコマンドライン引数が使用でき、今回は以下のような引数を使用しました。

-thumbnail [横幅] [入力ファイル] [出力ファイル]

横幅だけを指定すれば元の画像の縦横比のままでサムネイル画像が作成されます。(横x縦の指定も可能)

使用したソフトウェアは以下の通りです。

ImageMagick によるサムネイル画像作成例
> convert -thumbnail 100 sample.jpg sample_1.jpg
GraphicsMagick によるサムネイル画像作成例
> gm convert -thumbnail 100 sample.jpg sample_3.jpg

両者とも処理時間は 0.2秒程度でしたが、出力ファイルサイズが異なりました。(ImageMagick 5.71KB, GraphicsMagick 2.57KB)

ただし、これはデフォルトの圧縮レベルに違いがあるためで -quality 75 を指定して ImageMagick を実行し直してみたところ、GraphicsMagick と同じ 2.57KB になりました。

ファイルサイズから圧縮レベルのデフォルト値を予想すると以下のようになります。(JPEGファイルの場合)

  • ImageMagick は "-quality 96" 程度
  • GraphicsMagick は "-quality 75" 程度

また、"-define jpeg:size=[横幅]" を指定して実行してみたところ、ImageMagick では処理時間が少し短くなり(0.1秒程度)、ファイルサイズが少し減少しました。(GraphicsMagick の方は特に変化無し)

ImageMagick で -define を指定したサムネイル画像作成例
> convert -define jpeg:size=100 -thumbnail 100 sample.jpg sample_2.jpg

Java 標準APIによるサムネイル画像作成

上記 ImageMagick 等と同等の処理を Java の ImageIO を使って実装すると下記のようになります。

Thumbnail.java
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.awt.image.AffineTransformOp;
import java.io.File;
import javax.imageio.ImageIO;

/**
 * サムネイル用画像作成
 * java Thumbnail [変換後の横幅] [入力JPEGファイル] [出力JPEGファイル]
 */
public class Thumbnail {
    public static void main(String[] args) throws Exception {
        //入力JPEG読み込み
        BufferedImage input = ImageIO.read(new File(args[1]));

        //変換後の横幅
        int toWidth = Integer.parseInt(args[0]);

        double rate = (double)toWidth / input.getWidth();

        int toHeight = (int)(input.getHeight() * rate);

        //出力用イメージ
        BufferedImage output = new BufferedImage(toWidth, toHeight, input.getType());
        //サイズ変換定義
        AffineTransformOp at = new AffineTransformOp(AffineTransform.getScaleInstance(rate, rate), null);

        //サムネイル画像作成(サイズ変換)
        at.filter(input, output);

        //サムネイル画像出力
        ImageIO.write(output, "jpg", new File(args[2]));
    }
}
実行例
> java Thumbnail 100 sample.jpg sample_5.jpg

処理時間は 2.2秒程度でファイルサイズは 3.58KB、画質はイマイチでした。

.NET 標準APIによるサムネイル画像作成

.NET の API を使った C# 版は以下のようになります。

Thumbnail.cs
using System;
using System.Drawing;

/**
 * サムネイル用画像作成
 * Thumbnail.exe [変換後の横幅] [入力画像ファイル] [出力画像ファイル]
 */
class Thumbnail
{
    static void Main(string[] args)
    {
        //画像読み込み
        var inputImg = new Bitmap(args[1]);

        //変換後の横幅
        int toWidth = int.Parse(args[0]);

        double rate = (double)toWidth / inputImg.Width;

        //変換後の縦幅
        int toHeight = (int)(inputImg.Height * rate);

        //サムネイル画像作成
        var outputImg = inputImg.GetThumbnailImage(toWidth, toHeight, () => true, new IntPtr());

        //サムネイル画像出力
        outputImg.Save(args[2]);
    }
}
実行例
> Thumbnail 100 sample.jpg sample_6.jpg

処理時間は 1.8秒程度でファイルサイズが 22.7KB になり、解像度 96dpi で 32bit カラーになってしまっていました。(元ファイルは 72dpi で 24bit)

まとめ

結果をまとめると以下のようになります。(処理時間は厳密な測定をしておらず目安程度です)

番号 方法 処理時間 ファイルサイズ 画質 出力ファイル名
1 ImageMagick 0.2秒 5.71KB sample_1.jpg
2 ImageMagick -define 指定あり 0.1秒 5.60KB sample_2.jpg
3 ImageMagick -quality 75 0.2秒 2.57KB sample_7.jpg
4 GraphicsMagick 0.2秒 2.57KB sample_3.jpg
5 Java 標準API 2.2秒 3.58KB sample_5.jpg
6 C# 標準API 1.8秒 22.7KB sample_6.jpg

3 と 4 のファイルサイズが等しいことから、ImageMagick と GraphicsMagick で圧縮レベルのデフォルト値が異なっている事が予想されます