C#QQ找茬助手(二)GetPiexl与SetPixel优化

接上一篇内容,首先是对像素处理的优化,我们知道Bitmap中提供了GetPixelSetPixel方法可以访问Bitmap类中的某个位图像素数据,但是效率相当低下。用过OpenCV或者EmguCV的人知道它们使用的是自己的数据结构cvImage。不是每个人都有OpenCV的环境,其实微软中的GDI+BitmapData)也提供了可以用于高速访问内存中Bitmap的单个位图数据的方法。在C#下,有两种可选的方式使用BitmapData类型:Marshal类和指针。

Marshal

Marshal支持从托管内存空间复制数据到非托管内存空间,或是反之。起到托管和非托管编程模型之间的桥梁作用。

指针

C#中保留了指针和指针运算,但是必须在不安全代码中使用。默认下不支持,需要程序员自己通过unsafe来定义不安全上下文。虽然是不安全代码但是并不意味着是不安全的,不安全代码省略了托管内存与非托管内存交换过程,性能更优。但是操作不慎会引起内存泄露,因此使用务必小心。

 

下面将分别提供不同的处理代码,并给出运行时间。源码建立在上一篇基础上,在此不提供完整文件。时间是运行十次取均值结果,处理像素是大约是770*800

 

时间(毫秒)

GetPixel

46287

Marshal

414.4

 

Marshal源码:替换原来开始处理按键的Click事件内容

FileStream fs = new FileStream("default.jpg", System.IO.FileMode.Open, System.IO.FileAccess.Read); bitmap = new Bitmap(fs); fs.Close(); Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height); BitmapData bitmapdata = bitmap.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); IntPtr ptr = bitmapdata.Scan0;//获取像素地址值 int bytes = bitmap.Height * bitmap.Width * 3;//每个图片需要记录长乘以宽*3(RGB,实际顺序应该是BGR) byte[] rgbvalues = new byte[bytes];//数组初始化 //sw.Start();开始计时,用不上 System.Runtime.InteropServices.Marshal.Copy(ptr, rgbvalues, 0, bytes);//Marshal使用 for (int i = 0; i < bitmap.Width - ImageWidth - ImageSpace; i++) { for (int j = 0; j < bitmap.Height; j++) { if (rgbvalues[(i + j * 1280) * 3] == rgbvalues[(i + ImageWidth + ImageSpace + j * 1280) * 3])//如果相同 { rgbvalues[(i + j * 1280) * 3] = 255;//BLUE通道为255 rgbvalues[(i + j * 1280) * 3 + 1] = 255;//GREEN255 rgbvalues[(i + j * 1280) * 3 + 2] = 255;//RED255 } } } System.Runtime.InteropServices.Marshal.Copy(rgbvalues, 0, ptr, bytes);//Marshal bitmap.UnlockBits(bitmapdata); //sw.Stop();结束计时,用不上 //重新加载 this.pictureBox1.Image = bitmap;

总结:

一个简单的替换,使运行速度大大提升(T8100CPU),可以说做好优化是非常重要的。优化的方法很多,这只是一种修改方法,另外可以预先算出(i + j * 1280) * 3的值,减少运算次数~~

注意:

1、使用BitmapData需要先声明using System.Drawing.Imaging;

2unsafe使用方法参照MSDNhttp://msdn.microsoft.com/zh-cn/library/ct597kb0(v=VS.80).aspx

你可能感兴趣的:(数据结构,编程,优化,C#,byte,GDI+)