ちょっと古い記事(2007/05/24)だけど反応。
画像ファイルを高速に読み込むには?[2.0のみ、C#、VB] - @IT
http://www.atmarkit.co.jp/fdotnet/dotnettips/597fastloadimg/fastloadimg.html
この記事では画像ファイルからImageオブジェクトを作成する手順を解説している。気になったのは、Imageクラスのインスタンスを作成する際に「画像データの検証」をするかしないかのオプションがあり、それによって処理速度が大きく左右されるということ。
自分で検証してみる。そのために、フォームにPictureBoxを配置し、画像ファイルを読み込んで生成したImageオブジェクトをPictureBoxにアサインする、という簡単なテストプログラムを作成した。画像ファイルからどのようにImageオブジェクトを生成するか、3つの方法を試してみたい。
方法1: Image.FromFile()を使う
もっとも簡単な方法。
1 2 3 |
Image image = Image.FromFile("C:\\Temp\\ff_x_e1_004.JPG"); Debug.WriteLine("{0} x {1}", image.Width, image.Height); pictureBox1.Image = image; |
方法2: Image.FromStream()を使う
ファイル名だけ指定してFromStream()を使う。
1 2 3 4 |
FileStream stream = File.OpenRead("C:\\Temp\\ff_x_e1_004.JPG"); Image image = Image.FromStream(stream); Debug.WriteLine("{0} x {1}", image.Width, image.Height); pictureBox1.Image = image; |
方法3: Image.FromStream()を使う – イメージデータ検証無し
2つのオプション付きのFromStream()を試してみる。2番目の引数はカラーマネージメント情報の適用の有無、3番目の引数はイメージデータの検証の有無を指定する。共に false と指定。
1 2 3 4 |
FileStream stream = File.OpenRead("C:\\Temp\\ff_x_e1_004.JPG"); Image image = Image.FromStream(stream, false, false); Debug.WriteLine("{0} x {1}", image.Width, image.Height); pictureBox1.Image = image; |
処理速度
前回のエントリ同様に、4896×3264ピクセルのサンプル画像を使って処理時間を計測した。結果は方法3が他の2つより2桁も速い。「イメージデータの検証」を無しにすると読み込み速度を向上できることがわかった。
# | 使用関数 | 処理時間 |
方法1 | Image.FromFile() | 132ms |
方法2 | Image.FromStream() | 155ms |
方法3 | Image.FromStream() イメージデータ検証なし | 2ms |
環境: Windows 7 Ultimate SP1 (64bit), Intel Core i7 3.4GHz, RAM 16GB, Visual Studio 2012
イメージデータの検証は何をしているのか?
イメージデータの検証は何をしているのかという疑問が残った。Image.FromStreamメソッドはMSDNでは以下の通り説明されている。
Image.FromStream メソッド (Stream, Boolean, Boolean) オプションで埋め込み色管理情報の使用とイメージ データの検証を行い、指定したデータ ストリームから Image を作成します。 public static Image FromStream( Stream stream, bool useEmbeddedColorManagement, bool validateImageData ) useEmbeddedColorManagement データ ストリームに埋め込まれている色管理情報を使用する場合は true。それ以外の場合は false。 validateImageData イメージ データを検証する場合は true。それ以外の場合は false。 useEmbeddedColorManagement パラメーターは、データ ストリームに埋め込まれた色管理情報に従って、新しい Image に色補正を適用させるかどうかを指定します。 埋め込み情報には、ICC (International Color Consortium) プロファイル、ガンマ値、および色度情報を含めることができます。
useEmbeddedColorManagementの意味はなんとなくわかる。だけどvalidateImageDataの意味がわからない。「イメージデータを検証する」って何をしてるの?そういえば.NETってオープンソースでPC以外のプラットフォームにも移植されてたよな、と思って調べたらソースらしきものが見つかった。
Image.cs source code in C# .NET
http://www.dotnetframework.org/default.aspx/DotNET/DotNET/8@0/untmp/whidbey/ REDBITS/ndp/fx/src/CommonUI/System/Drawing/Image@cs/1/Image@cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
public static Image FromStream(Stream stream, bool useEmbeddedColorManagement, bool validateImageData) { if (!validateImageData) { IntSecurity.UnmanagedCode.Demand(); } if (stream == null) { throw new ArgumentException(SR.GetString(SR.InvalidArgument, "stream", "null")); } IntPtr image = IntPtr.Zero; int status; if (useEmbeddedColorManagement) { status = SafeNativeMethods.Gdip.GdipLoadImageFromStreamICM(new GPStream(stream), out image); } else { status = SafeNativeMethods.Gdip.GdipLoadImageFromStream(new GPStream(stream), out image); } if (status != SafeNativeMethods.Gdip.Ok) { throw SafeNativeMethods.Gdip.StatusException(status); } if (validateImageData) { status = SafeNativeMethods.Gdip.GdipImageForceValidation(new HandleRef(null, image)); if (status != SafeNativeMethods.Gdip.Ok) { SafeNativeMethods.Gdip.GdipDisposeImage(new HandleRef(null, image)); throw SafeNativeMethods.Gdip.StatusException(status); } } Image img = CreateImageObject(image); EnsureSave(img, null, stream); return img; } |
このソースを見ると、validateImageDataがtrue、すなわち「イメージ データを検証する」とした場合、GDI+のGdipImageForceValidationが呼ばれている。だけど、ネットでGdipImageForceValidationの情報を探すも見つからず。かろうじてMSDNの以下ページに「This function forces validation of the image.」とだけ記載されていた。
Image Functions (Windows)
http://msdn.microsoft.com/en-us/library/ms534041(v=vs.85).aspx
更に情報を求めてネットを検索していたら、Windowsアプリを別プラットフォームで動かすWINEというプロジェクトを見つけた。
WineHQ – Run Windows applications on Linux, BSD, Solaris and Mac OS X
http://www.winehq.org/
GDI+の互換ライブラリが含まれているらしいのでダウンロードしてソースを閲覧したのだが、関数は存在したけど処理は実装されてなかった。Image.FromStreamメソッドの「イメージデータの検証」は何をやっているのか、残念ながらわからずじまい。