ビットマップイメージに独自のフィルタをかける
ビットマップの各ピクセルに何らかの操作を行いたい場合、C#では GetPixel, SetPixel メソッドが使えます。
しかし、この方法では大量のピクセルを扱う場合、処理が重くなる欠点があります。
効率よく処理するには、以下の例のように Bitmap をシステム メモリにロックしてから行います。
unsafe コードを使用しますので、プロジェクトの設定で「アンセーフ コードの許可」が必要です。
// 白抜き画像に反転する。ソース画像は黒字に白で描画されていることを前提にする
public Bitmap InvertImage(Bitmap source, int color)
{
Bitmap output = new Bitmap(source.Width, source.Height, PixelFormat.Format32bppArgb);
var rect = new Rectangle(0, 0, source.Width, source.Height);
var bitsInput = source.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
var bitsOutput = output.LockBits(rect, ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
byte R = (byte)((color >> 16) & 0xff);
byte G = (byte)((color >> 8) & 0xff);
byte B = (byte)(color & 0xff);
unsafe
{
for (int y = 0; y < source.Height; y++)
{
byte* ptrInput = (byte*)bitsInput.Scan0 + (y * bitsInput.Stride);
byte* ptrOutput = (byte*)bitsOutput.Scan0 + (y * bitsOutput.Stride);
for (int x = 0; x < source.Width; x++)
{
int bp = x * 4;
byte r = ptrInput[bp];
byte g = ptrInput[bp + 1];
byte b = ptrInput[bp + 2];
int brightness = ((r + g + b) / 3);
ptrOutput[bp] = B;
ptrOutput[bp + 1] = G;
ptrOutput[bp + 2] = R;
ptrOutput[bp + 3] = (byte)brightness;
}
}
}
source.UnlockBits(bitsInput);
output.UnlockBits(bitsOutput);
return output;
}