処理の内容としては以下のとおり。
- LockBitsを使い、bitmapの内部データをシステム メモリにロックします
- そのデータを、Byte[]にコピーします
- 3byteずつを1pixelのカラーデータとし、その平均をセットしなおします(これは[.NET]画像処理グレースケール化(1)と同じ処理)
コードはこんな感じ。
Bitmap bmp = new Bitmap(ctlPicture.Image);
//bitmapをメモリ上にロックします
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite,
PixelFormat.Format24bppRgb);
// RGB値をbyte列にコピーする
IntPtr ptr = bmpData.Scan0;
int stride = bmpData.Stride;
int size = stride * bmp.Height;
byte[] rgbValues = new byte[size];
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, size);
//3byteずつ進む
for (int j = 0; j < size; j = j + 3)
{
byte val = (byte)Math.Round((double)(rgbValues[j + 0] + rgbValues[j + 1] + rgbValues[j + 2]) / 3);
rgbValues[j] = val; //b
rgbValues[j + 1] = val; //g
rgbValues[j + 2] = val; //r
}
// byte列をbitmapに復元し、メモリのロックを開放する
System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, size);
bmp.UnlockBits(bmpData);
ctlPicture.Image = bmp;
//bitmapをメモリ上にロックします
Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadWrite,
PixelFormat.Format24bppRgb);
// RGB値をbyte列にコピーする
IntPtr ptr = bmpData.Scan0;
int stride = bmpData.Stride;
int size = stride * bmp.Height;
byte[] rgbValues = new byte[size];
System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, size);
//3byteずつ進む
for (int j = 0; j < size; j = j + 3)
{
byte val = (byte)Math.Round((double)(rgbValues[j + 0] + rgbValues[j + 1] + rgbValues[j + 2]) / 3);
rgbValues[j] = val; //b
rgbValues[j + 1] = val; //g
rgbValues[j + 2] = val; //r
}
// byte列をbitmapに復元し、メモリのロックを開放する
System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, size);
bmp.UnlockBits(bmpData);
ctlPicture.Image = bmp;
このコードにより、同じ環境でも処理速度が30ms程度になります。パフォーマンスが約23倍になりました。
2 件のコメント:
ソース中に、
rgbValues[j] = val; //r
rgbValues[j + 1] = val; //g
rgbValues[j + 2] = val; //b
とありますが、メモリ上ではBGRの順で格納されているため、
rgbValues[j + 2] = val; //R
rgbValues[j + 1] = val; //G
rgbValues[j] = val; //B
となるはずです。
kobahideさん
確かにおっしゃるとおりBGRの順ですね。というわけでコメントを修正しました。
コメントありがとうございました。
コメントを投稿