C#::ビットマップの全体をクリアするのにかかる時間
いろんなコードの処理時間を計測したら日記にメモするのが確実だという気がするので、ビットマップ全体の塗りつぶしにかかる時間を計測。
//using System.Drawing; //using System.Drawing.Imaging; //using System.Runtime.InteropServices; var bmp = new Bitmap(4096, 4096, PixelFormat.Format32bppArgb);
こんな感じで4096x4096フルカラーのビットマップをメモリに作る。たぶんメモリを7Mぐらい消費してる。
この状態で、素直に↓のコードを100回実行したら4.4秒かかった。遅っ。
var g = Graphics.FromImage(bmp); g.Clear(Color.Transparent);
↓のコードを100回だと、1.1秒ぐらい。
//[DllImport("KERNEL32.DLL", EntryPoint="RtlZeroMemory", SetLastError = true)] //public static extern bool ZeroMemory(IntPtr destinationObject, int length); var dt = bmp.LockBits(new Rectangle(0, 0, 4096, 4096), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); var sz = 4096*4096*4; ZeroMemory(dt.Scan0, sz);
↓のコードを100回だと1.6秒ぐらい(要:/unsafeオプション)。
var dt = bmp.LockBits(new Rectangle(0, 0, 4096, 4096), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); var sz = 4096*4096; unsafe{ int* p = (int*)dt.Scan0; for (var i = 0; i < sz; i ++){ *p++ = 0; } }
LockBitsのサンプル風↓のコードを100回ではなんと16秒!お話になりませんわっ!!
var sz = 4096 * 4096 * 4; for (var c = 0; c < cnt; c++){ for (var i = 0; i < sz; i += 4){ Marshal.WriteInt32(dt.Scan0, i, 0); } }
ちなみに全部デバッグなしで計測した結果。デバッグでやるとunsafeは5倍、Marshalは2倍の時間がかかった。
全部同じことやってるけれど、ZeroMemoryが一番早い。けど透明にしかできない罠。そのほかの方法は任意の色で塗りつぶせる。Marshalを今4byte(1Pixel)ずつ上書きしてるけど、これを1byteずつやると当然四倍の時間がかかるのです。
どちらにしろ、思った以上に時間がかかっているのだった。unsafeの一回あたり0.016秒ってのでもほぼ60fpsだし。まぁ、画像がデカすぎるせいでもあるのだけど。
DirectX使ってビットマップの編集とかできるのかな?