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

ImageProcessor を使う

NuGetパッケージに ImageProcessor というライブラリがあります。名前は大仰なのに機能は少ないものの、純粋なC#実装で(GDI+)、簡単にちょっとした画像処理ができるので、使う場面によっては有用だと感じました。

以下、ImageProcessor(1.7.1.1)の使い方の紹介です。

NuGetで取得

探せばすぐ見つかります。インストール。

画像読み込み

画像は ImageProcessor.ImageFactory クラスで管理されます(実体はSystem.Drawing.Image のラッパーです)。

var factory = new ImageProcessor.ImageFactory();
factory.Load("piyo.png");

注意点として、ファイルが存在しない場合でも特にエラーは出ませんでした。以下のようにすれば読み込めたかどうかはチェックできるようです。

factory.Load("not-existing-file.png");
if(factory.Image == null)
    throw new Exception("読み込み失敗らしい");

画像処理の実行

以下githubのページを参考にすると良いでしょう。
https://github.com/JimBobSquarePants/ImageProcessor

各メソッドはどれも return this; するようになっており、メソッドチェインでずらずら書いていくことができます。どの処理も破壊的操作です。

factory.Contrast(10)
    .Crop(new System.Drawing.Rectangle(100, 50, 800, 650))
    .Rotate(new ImageProcessor.Imaging.RotateLayer(90))
    .Vignette()
    .Watermark(new ImageProcessor.Imaging.TextLayer()
    {
        Text = "Penguins",
        Position = new System.Drawing.Point(10, 10),
        TextColor = System.Drawing.Color.Red,
        DropShadow = true
    })
    .Filter("comic");

Windows7のサンプルピクチャ "Penguins.jpg" にかけてみた結果が以下です。左が元画像、右が出力画像です。
f:id:Schima:20131212210238p:plain

以下いくつか処理を紹介します。

Crop

画像の一部分を切り取ります。

factory.Crop(new System.Drawing.Rectangle(x, y, width, height));

Watermark

文字列を画像に描きます。

factory.Watermark(new ImageProcessor.Imaging.TextLayer()
{
    Text = "Penguins",
    Position = new System.Drawing.Point(10, 10),
    TextColor = System.Drawing.Color.Red,
    DropShadow = true
});

Filter

文字列で指定したフィルタを画像に適用します(文字列って若干イケてない気が)。指定できる文字列は以下のいずれかです。

  • blackwhite
  • comic
  • lomograph
  • greyscale
  • polaroid
  • sepia
  • gotham
  • hisatch
  • losatch
  • invert
factory.Filter("blackwhite");

画像を保存

Save でできます。
Save一発でできることもありますが、通常はSaveの前にフォーマットを指定するのが正しいようです。以下はTIFFで保存する場合です。

factory.Format(System.Drawing.Imaging.ImageFormat.Tiff)
       .Save("image.tif");

画像のコピーを作成

このImageProcessor、一つ難点があります。すべての処理が破壊的なのは良いのですが、画像のコピーを作る簡単なメソッドは無いようです。

Saveには、ファイルではなくSystem.IO.MemoryStream に書き出すオーバーロードもあります。Loadも同様です。これを利用して、MemoryStreamを媒介させればよいでしょう。
頻繁に使うのであれば、このような拡張メソッドを作るのも良いかもしれません。またはpull requestを投げるとか :-)

static class ImageFactoryExtensions
{
    public static ImageProcessor.ImageFactory Clone(
        this ImageProcessor.ImageFactory factory)
    {
        var stream = new System.IO.MemoryStream();
        factory.Save(stream);
        var result = new ImageProcessor.ImageFactory();
        result.Load(stream);
        return result;
    }
}
var factory2 = factory.Clone().Alpha(30);

デバッグ向け画像確認

ファイルに保存して確認

Saveメソッドもthisを返すので、メソッドチェインの途中に入れることができます。

factory.Contrast(10)
    .Save("after_contrast.jpg")
    .Crop(new System.Drawing.Rectangle(100, 50, 800, 650))
    .Save("after_crop.jpg")
    .Rotate(new ImageProcessor.Imaging.RotateLayer(90))
    .Save("after_rotate.jpg");

ダイアログで確認

例えば以下のような拡張メソッドを作ると、途中でダイアログを出して確認することができます。System.Windows.Forms を参照に追加してください。

static class ImageFactoryExtensions
{
    public static ImageProcessor.ImageFactory Show(
        this ImageProcessor.ImageFactory factory)
    {
        using (var form = new Form())
        using (var pictureBox = new PictureBox())
        {
            pictureBox.Image = factory.Image;
            pictureBox.Dock = DockStyle.Fill;
            pictureBox.SizeMode = PictureBoxSizeMode.Zoom;
            form.Controls.Add(pictureBox);
            form.MinimizeBox = false;
            form.FormBorderStyle = FormBorderStyle.SizableToolWindow;
            form.KeyPreview = true;
            form.KeyPress += (sender, args) => form.Close();
            form.ShowDialog();
        }
        return factory;
    }
}
factory.Contrast(10)
    .Show()
    .Crop(new System.Drawing.Rectangle(100, 50, 800, 650))
    .Show()
    .Rotate(new ImageProcessor.Imaging.RotateLayer(90))
    .Show();