|
.NET TIPS
画像ファイルを高速に読み込むには?[2.0のみ、C#、VB]
デジタルアドバンテージ 遠藤 孝信
2007/05/24 |
|
|
JPEGファイルなどの画像ファイルを読み込んで画像オブジェクト(=Imageクラス(System.Drawing名前空間)のオブジェクト)を作成する際には、次のように、ImageクラスのFromFileメソッドを利用するのが最も手軽である。
Image img = Image.FromFile("picture.jpg");
|
Dim img As Image = Image.FromFile("picture.jpg")
|
|
FromFileメソッドによる画像ファイルの読み込み(上:C#、下:VB) |
しかしこの方法は内部で「画像データの検証」が行われているため、実はWin32 APIによる画像の読み込みなどに比べるとかなり低速である。
.NET Framework 2.0では、ImageクラスのFromStreamメソッドを使用することにより、画像データの検証をスキップでき、高速に画像オブジェクトを作成できる。このメソッドを使用した画像ファイルの読み込みは次のようなコードにより行う。
FileStream fs = File.OpenRead("picture.jpg");
Image img = Image.FromStream(fs, false, false); // 検証なし
|
Dim fs As FileStream = File.OpenRead("picture.jpg")
Dim img As Image = Image.FromStream(fs, False, False); ' 検証なし
|
|
画像データの検証を行わない画像ファイルの読み込み(上:C#、下:VB) |
FromStreamメソッドの第3パラメータが、画像データの検証を行うかどうかを指定するためのものだ(第2パラメータでは色管理情報を使用するかどうかを指定する。これについてはリファレンス・マニュアルの「Image.FromStream メソッド (Stream, Boolean)」の項目を参照してほしい)。
サンプル・プログラムによる画像読み込み時間の比較
次のサンプル・プログラムは、FromFileメソッドと、画像データの検証を行わないFromStreamメソッドで、画像オブジェクト作成にかかる時間を比較するためのものだ。
このプログラムでは、C:\jpgsディレクトリにある画像を順に読み込んでImageオブジェクトを作成し、その画像の幅と高さを表示する。そして最後にその処理時間を表示する。これを2つのメソッドについて行っている。
// fastloadimg.cs
using System;
using System.Diagnostics;
using System.IO;
using System.Drawing;
class FastLoadImage {
static void Main() {
string dir = @"C:\jpgs";
string[] jpgFiles = Directory.GetFiles(dir, "*.jpg");
Stopwatch sw;
// 画像データの検証をオフにしてロード
sw = Stopwatch.StartNew();
foreach (string jpg in jpgFiles) {
using (FileStream fs = File.OpenRead(jpg))
using (Image img = Image.FromStream(fs, false, false)) {
Console.WriteLine("{0} : {1} x {2}", jpg, img.Width, img.Height);
}
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds + "ミリ秒");
// 出力例:
// C:\jpgs\IMG_0001.jpg : 3456 x 2304
// C:\jpgs\IMG_0002.jpg : 3456 x 2304
// ……省略……
// C:\jpgs\IMG_0199.jpg : 3456 x 2304
// C:\jpgs\IMG_0200.jpg : 3456 x 2304
// 651ミリ秒
// Image.FromFileメソッドによるロード
sw = Stopwatch.StartNew();
foreach (string jpg in jpgFiles) {
using (Image img = Image.FromFile(jpg)) {
Console.WriteLine("{0} : {1} x {2}", jpg, img.Width, img.Height);
}
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds + "ミリ秒");
// 出力例:
// C:\jpgs\IMG_0001.jpg : 3456 x 2304
// C:\jpgs\IMG_0002.jpg : 3456 x 2304
// ……省略……
// C:\jpgs\IMG_0199.jpg : 3456 x 2304
// C:\jpgs\IMG_0200.jpg : 3456 x 2304
// 60069ミリ秒
}
}
// コンパイル方法:csc fastloadimg.cs
|
|
FromFileメソッドとFromStreamメソッドの比較を行うC#のサンプル・プログラム(fastloadimg.cs) |
|
' fastloadimg.vb
Imports System
Imports System.Diagnostics
Imports System.IO
Imports System.Drawing
Class FastLoadImage
Shared Sub main()
Dim dir As String = "C:\jpgs"
Dim jpgFiles As String() = Directory.GetFiles(dir, "*.jpg")
Dim sw As Stopwatch
' 画像データの検証をオフにしてロード
sw = Stopwatch.StartNew()
For Each jpg As String In jpgFiles
Using fs As FileStream = File.OpenRead(jpg)
Using img As Image = Image.FromStream(fs, False, False)
Console.WriteLine("{0} : {1} x {2}", jpg, img.Width, img.Height)
End Using
End Using
Next
sw.Stop()
Console.WriteLine(sw.ElapsedMilliseconds & "ミリ秒")
' 出力例:
' C:\jpgs\IMG_0001.jpg : 3456 x 2304
' C:\jpgs\IMG_0002.jpg : 3456 x 2304
' ……省略……
' C:\jpgs\IMG_0199.jpg : 3456 x 2304
' C:\jpgs\IMG_0200.jpg : 3456 x 2304
' 651ミリ秒
' Image.FromFileメソッドによるロード
sw = Stopwatch.StartNew()
For Each jpg As String In jpgFiles
Using img As Image = Image.FromFile(jpg)
Console.WriteLine("{0} : {1} x {2}", jpg, img.Width, img.Height)
End Using
Next
sw.Stop()
Console.WriteLine(sw.ElapsedMilliseconds & "ミリ秒")
' 出力例:
' C:\jpgs\IMG_0001.jpg : 3456 x 2304
' C:\jpgs\IMG_0002.jpg : 3456 x 2304
' ……省略……
' C:\jpgs\IMG_0199.jpg : 3456 x 2304
' C:\jpgs\IMG_0200.jpg : 3456 x 2304
' 60069ミリ秒
End Sub
End Class
' コンパイル方法:vbc fastloadimg.vb
|
|
FromFileメソッドとFromStreamメソッドの比較を行うVBのサンプル・プログラム(fastloadimg.vb) |
|
コメントで記述している出力例は、筆者のPC(CPU:Intel Core 2 Duo 2.4GHz、メモリ:1Gbytes)でプログラムを実行したときのものだ。C:\jpgsディレクトリには200個のJPEGファイルが保存されている(ファイルの平均サイズは約1.9Mbytes)。処理時間から、画像データの検証を行わない方が90倍以上も速くなっていることが分かる。
ただ実際には、画像データの検証を行っている場合には画像ファイル全体を一度に読み込むのに対して、検証を行っていない場合には必要に応じて画像ファイルを順次読み込んでいるようで、上記のサンプル・プログラムのように画像ファイルの先頭部分の読み込みだけで済む場合には高速だが、画像全体を表示する場合などでは速度差はあまりないようだ。
なお、画像データの検証をスキップすることによる影響については、リファレンス・マニュアルに見当たらなかったため不明である。
利用可能バージョン:.NET Framework 2.0のみ
カテゴリ:クラス・ライブラリ 処理対象:ビットマップ
使用ライブラリ:Imageクラス(System.Drawing名前空間)
|
|
generated by
|
|
Insider.NET 記事ランキング
本日
月間