Subscribed unsubscribe Subscribe Subscribe

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#の画像処理ではわりと常套手段らしいけど知らなかった.