首先感谢CSDN的朋友laviewpbt为我给我的建议。
laviewpbt提出使用getpixel处理速度太慢,上不了档次。
这里我再给大家写两种处理速度更快的图形处理方式。
下面是个内存操作灰度的程序:
bmp = new Bitmap(Application.StartupPath + "//1.jpg"); Bitmap bmp2 = (Bitmap)bmp.Clone(); int width = bmp2.Width; int height = bmp2.Height; Rectangle rect = new Rectangle(0, 0, width, height); //用可读写的方式锁定全部位图像素 BitmapData bmpData = bmp2.LockBits(rect, ImageLockMode.ReadWrite, bmp2.PixelFormat); //得到首地址 IntPtr ptr = bmpData.Scan0; //24位bmp位图字节数 int bytes = width * height * 3;
byte[] rgbValues = new byte[bytes];
Marshal.Copy(ptr, rgbValues, 0, bytes);
//灰度化 double colorTemp = 0; for (int i = 0; i < bytes; i += 3) { colorTemp = rgbValues[i + 2] * 0.299 + rgbValues[i + 1] * 0.587 + rgbValues[i] * 0.114; rgbValues[i] = rgbValues[i+1] = rgbValues[i+2] = (byte)colorTemp; } //还原位图 Marshal.Copy(rgbValues, 0, ptr, bytes); bmp2.UnlockBits(bmpData); Graphics g = this.CreateGraphics(); g.DrawImage(bmp2, new Rectangle(410, 0, 200, 200)); g.Dispose(); bmp2.Dispose();
够仔细的朋友很容易看出,其实我们只是把图像的像素点放到内存中处理了。我们知道在内存中处理肯定是最快的了。
下面再写一个用指针的
bmp = new Bitmap(Application.StartupPath + "//1.jpg"); Bitmap bmp2 = (Bitmap)bmp.Clone(); int width = bmp2.Width; int height = bmp2.Height; Rectangle rect = new Rectangle(0, 0, width, height); //用可读写的方式锁定全部位图像素 BitmapData bmpData = bmp2.LockBits(rect, ImageLockMode.ReadWrite, bmp2.PixelFormat); byte temp = 0; //启用不安全模式 unsafe { //获取首地址 byte* ptr = (byte*)(bmpData.Scan0); //二维图像循环 for (int i = 0; i < bmpData.Height; i++) { for (int j = 0; j < bmpData.Width; j++) { temp = (byte)(0.299 * ptr[2] + 0.587 * ptr[1] + 0.114 * ptr[0]); ptr[0] = ptr[1] = ptr[2] = temp; ptr += 3; } //指针移向下一行数组的首个字节 ptr += bmpData.Stride - bmpData.Width * 3; } bmp2.UnlockBits(bmpData); } Graphics g = this.CreateGraphics(); g.DrawImage(bmp2, new Rectangle(615, 0, 200, 200)); g.Dispose(); bmp2.Dispose();
C#默认不能使用指针操作,所以我们使用了unsafe(不安全模式),注意:使用不安全模式调试时需要配置VS,在项目的属性内设置启用不安全模式调试
本人也在学习GDI+,写得比较简单,让高手见笑了。欢迎高手给我指点
邮箱:bobui@163.com
QQ:125941562
|