みなさんも一度はC#を使って大量の画像を処理したいと考えたことがあると思います。しかし、実際にやってみると、例えばたった458枚をリサイズするのに15.28秒もかかってしまい、使い物になりません。
私はあきらめてしばらくそのまま使っていました。が、しかしネット上で偶然見つけたRalpha Image Resizerというソフトは同じ処理をたった5.15秒でやってのけるじゃありませんか!
調べてみると、このソフトはマルチコアで並列に処理し、高速化を図っているのだそう。
そこでC#で同じことができるように試しに書いてみました。Ralphaを真似てWIC (Windows Imaging Component)を使用してみたらさらなる高速化が期待できましたので、それを使用します。
以下は指定したディレクトリ内の画像ファイルをすべて縦800pxにリサイズし、保存するプログラムです。
//using System.IO;
//using System.Text.RegularExpressions;
//using System.Windows.Media;
//using System.Windows.Media.Imaging;
// リサイズしたい画像が含まれているディレクトリ
var dir = @"C:\Images\";
// ファイルを列挙し、並列で処理
Parallel.ForEach(Directory.EnumerateFiles(dir), path =>
{
// 画像ファイルじゃない場合はスキップ
if (!Regex.IsMatch(path, "\\.(?:png|jpg|gif|bmp)$", RegexOptions.IgnoreCase)) return;
// ファイルを開いて Stream オブジェクトを作成
using (var sourceStream = File.OpenRead(path))
{
// 画像をデコードするための BitmapDecoder オブジェクトを作成する
// (ファイルの種類に応じて適切なデコーダーが作成される)
var decoder = BitmapDecoder.Create(sourceStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
// 画像ファイル内の1フレーム目を取り出す (通常1フレームしかない)
var bitmapSource = decoder.Frames[0];
var scale = 800 / bitmapSource.Height; // 拡大率
// 拡大・縮小されたビットマップを作成する
var scaledBitmapSource = new TransformedBitmap(bitmapSource, new ScaleTransform(scale, scale));
// 元のファイルと同じ形式のエンコーダー (BitmapEncoder) を選択・作成する
var extension = Path.GetExtension(path);
var encoder =
extension == ".png" ? new PngBitmapEncoder() :
extension == ".jpg" ? new JpegBitmapEncoder() :
extension == ".gif" ? new GifBitmapEncoder() :
extension == ".bmp" ? new BmpBitmapEncoder() :
(BitmapEncoder)(new PngBitmapEncoder());
// エンコーダーにフレームを追加する
encoder.Frames.Add(BitmapFrame.Create(scaledBitmapSource));
var destDir = dir + "\\resize\\"; // 出力ディレクトリ
// 出力ディレクトリが存在しない場合は、新しく作成する
if (!Directory.Exists(destDir))
{
Directory.CreateDirectory(destDir);
}
var dest = destDir + Path.GetFileNameWithoutExtension(path) + extension; // 出力ファイル
// 出力ファイルのストリームを開く
using (var destStream = File.OpenWrite(dest))
{
encoder.Save(destStream); // 保存
}
}
});
Console.WriteLine("終了しました");
※実行するには WindowsBase, PresentationCore, System.Xaml の参照が必要です。
実行速度を計測するとこんな感じ