BitMap描画を10倍速くする
かなり間があいてしまった.また覚え書きエントリですが.
C#のSystem.Drawing.Bitmapを使って画像を出そうとすると,場合によってはものすごく重たくなってしまう.ボトルネックとなっているのはSetPixel/GetPixel関数.ググると重いと感じている人は沢山いるようで,こんなものを見つけた.
NonSoft - Bitmap処理を高速化するサンプル(C#.NET)
BitMapをシステムメモリにロックし,RGB値を保持する場所のポインタを取得し,それを直接いじる荒業.C#でポインタを使うにはプロジェクトのコンパイルオプションでunsafeコードを許可してやる必要がある.
ためしに2048×2048pixelの画像を描かせてみる.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.Diagnostics; using BitmapLite; namespace BitMapBenchMark { class Program { static void Main(string[] args) { Stopwatch sw = new Stopwatch(); sw.Start(); //通常のBitmapクラスを使用 Bitmap b = new Bitmap(2048, 2048); for (int h = 0; h < 2048; h++) { for (int v = 0; v < 2048; v++) { b.SetPixel(h, v, Color.White); } } sw.Stop(); Console.WriteLine("BitMap:{0}", sw.Elapsed.ToString()); sw.Reset(); sw.Start(); //ポインタ使用 b = new Bitmap(2048, 2048); BitmapLite bl = new BitmapLite(b); bl.BeginAccess(); for (int h = 0; h < 2048; h++) { for (int v = 0; v < 2048; v++) { bl.SetPixel(h, v, Color.White); } } bl.EndAccess(); sw.Stop(); Console.WriteLine("BitMapLite:{0}", sw.Elapsed.ToString()); sw.Reset(); } } }
結果,描画速度に約10倍の差が出た.
BitMap:00:00:09.4062030 BitMapLite:00:00:00.9526976
PCが相当古株なせいもあるけど,高々2048ピクセルの画像に9秒かかるのは困りものなので,これは有りがたい.C#の画像処理ではわりと常套手段らしいけど知らなかった.