System.Drawing.Bitmap画像を使った高速な画像処理プログラミング その2
.Net Framework のベンチマークの公開にはややこしいルールがあるようなので、
ベンチマーク結果を公開する代わりにベンチマークを取れるプログラムを公開します。
こうにすれば画像処理プログラムの雛形としても使えますし…
ベンチマーク結果を公開する代わりにベンチマークを取れるプログラムを公開します。
こうにすれば画像処理プログラムの雛形としても使えますし…
<bench1.cs : SetPixel, GetPixel を使う方法>
using System;
using System.Drawing;
using System.Runtime.InteropServices;
class Bench{
[DllImport("winmm.dll" )]
public static extern int timeGetTime();
public static void Main(string[ ] args){
Bitmap bmp = new Bitmap("test.png" );
int time1 = timeGetTime();
const int TH = 128;
for (int j = 0; j < bmp.Height; ++j){
for (int i = 0; i < bmp.Width; ++i){
Color c = bmp.GetPixel(i,j) ;
byte r = c.R < TH ? (byte)0 : (byte)255, g = c.G < TH ? (byte)0 : (byte)255, b = c.B < TH ? (byte)0 : (byte)255;
bmp.SetPixel(i,j, Color.FromArgb(r,g,b)) ;
}
}
int time2 = timeGetTime();
Console.WriteLine("{0}[msec]", time2 - time1);
bmp.Save("test_o.png" );
}
}
<bench2.cs : LockBits, UnlockBits, BitmapData を使う方法>
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
class Bench{
[DllImport("winmm.dll" )]}
public static extern int timeGetTime();
static void CopyBmp(Bitmap src, Bitmap dst){
Graphics g = Graphics.FromImage(dst) ;}
g.DrawImageUnscaled(src,0,0) ;
g.Dispose() ;
public static void Main(string[ ] args){
Bitmap bmp_ = new Bitmap("test.png" );}
int time1 = timeGetTime();
const int TH = 128;
Bitmap bmp = new Bitmap(bmp_.Width, bmp_.Height, PixelFormat.Format24bppRgb);
CopyBmp(bmp_, bmp);
bmp_.Dispose();
BitmapData bd = bmp.LockBits(new Rectangle(0,0,bmp.Width,bmp.Height), ImageLockMode.ReadWrite, bmp.PixelFormat);
int stride = bmp.Width * 3;
byte[ ] data = new byte[stride * bmp.Height];
Marshal.Copy(bd.Scan0, data, 0, data.Length);
for (int j = 0, ji = 0; j < bmp.Height; ++j, ji += stride){
for (int i = 0; i < bmp.Width * 3; i += 3){}
int p = i + ji;}
data[p] = data[p] < TH ? (byte)0 : (byte)255; // R
data[p+1] = data[p+1] < TH ? (byte)0 : (byte)255; // G
data[p+2] = data[p+2] < TH ? (byte)0 : (byte)255; // B
Marshal.Copy(data, 0, bd.Scan0, data.Length);
bmp.UnlockBits(bd);
int time2 = timeGetTime();
Console.WriteLine("{0}[msec]", time2 - time1);
bmp.Save("test_o.png" );
<bench3.cs : MemoryStream にBMPファイルを書き出す方法>
using System;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
class Bench{
[DllImport("winmm.dll" )]
public static extern int timeGetTime();
static void CopyBmp(Bitmap src, Bitmap dst){
Graphics g = Graphics.FromImage(dst) ;}
g.DrawImageUnscaled(src,0,0) ;
g.Dispose() ;
static int readint32(MemoryStream ms){
byte b = new byte[4];}
ms.Read(b, 0, 4);
return (int)b[0] + (int)b[1] * 0x100 + (int)b[2] * 0x10000 + (int)b[3] * 0x1000000;
public static void Main(string args){
Bitmap bmp_ = new Bitmap("test.png" );
int time1 = timeGetTime();
const int TH = 128;
Bitmap bmp = new Bitmap(bmp_.Width, bmp_.Height, PixelFormat.Format24bppRgb);
CopyBmp(bmp_, bmp);
bmp_.Dispose();
MemoryStream ms = new MemoryStream();
bmp.Save(ms, ImageFormat.Bmp);
ms.Seek(10, SeekOrigin.Begin);
int startRaw = readint32(ms);
ms.Seek(startRaw, SeekOrigin.Begin);
int stride = ((bmp.Width * 3 + 3) / 4) * 4;
byte[] data = new byte[stride * bmp.Height];
ms.Read(data, 0, data.Length);
for (int j = 0, ji = (bmp.Height - 1) * stride; j < bmp.Height; ++j, ji -= stride){
for (int i = 0; i < bmp.Width * 3; i += 3){}
int p = i + ji;}
data[p] = data[p] < TH ? (byte)0 : (byte)255; // B
data[p+1] = data[p+1] < TH ? (byte)0 : (byte)255; // G
data[p+2] = data[p+2] < TH ? (byte)0 : (byte)255; // Rms.Seek (startRaw, SeekOrigin.Begin) ;
ms.Write (data, 0, data.Length);
bmp.Dispose();
bmp_ = new Bitmap(ms);
bmp = new Bitmap(bmp_);
ms.Dispose();
int time2 = timeGetTime();
Console.WriteLine("{0}[msec]", time2 - time1);
bmp.Save("test_o.png" );
}
}
3例ともSystem.Runtime.InteropServices名前空間を参照していますが、3番目については、timeGetTimeのためだけに使っていますので、その部分を外せばSystem.Runtime.InteropServicesの参照を外すことができます。