最近在使用屏幕截图工具的时候发现放大镜的功能有点小问题,准星和实际鼠标位置对不上,取到的颜色并不鼠标所在的点颜色,所以去看“C#软件开发实例.私人订制自己的屏幕截图工具(七)添加放大镜的功能”的代码,发现之前的代码实现效率上应该有问题,所以就试试优化了一下,经过对比相差十几倍。
之前的算法逻辑是:
1、根据放大镜的大小计算需要的原图尺寸,复制到新建的Bitmap;
2、创建一个新的Bitmap保存放大后的图片;
3、采用四层循环通过“GetPixel”获得源像素颜色,通过“SetPixel”设置放大后目标区域颜色;
优化后的逻辑:
1、根据放大镜的大小计算需要的原图尺寸,获取原图在整个屏幕图片上的坐标点;
2、声明单像素放大的区域“zoomRect”,1:10放大,所以Reatangle大小是10*10;
3、声明画笔对象;
4、双层循环,直接从屏幕图片上取像素点的颜色,通过“FillRectangle”方法对像素进行放大绘制到放大镜的对应显示区域;
优化后的代码:
long drawBegin = DateTime.Now.Ticks; //绘制放大镜中的图像 int infoAreaHeight = 32; Size srcSize = new System.Drawing.Size((int)(this.ZoomBoxWidth / 10), (int)(this.ZoomBoxHeight / 10)); Point srcPoint = new Point(MousePosition.X - 5, MousePosition.Y - 4); if (!isCuting) { label1.Text = "!isCuting"; srcPoint = new Point(MousePosition.X - 6, MousePosition.Y - 5); } Rectangle zoomRect = new Rectangle(0, 0, 10, 10); Brush zoomBrush; for (int row = 0; row < srcSize.Height; row++) { for (int col = 0; col < srcSize.Width; col++) { Color pc = screenImage.GetPixel(srcPoint.X + col, srcPoint.Y + row); zoomBrush = new SolidBrush(pc); e.Graphics.FillRectangle(zoomBrush, zoomRect); zoomRect.Offset(10, 0); } zoomRect.Offset(0, 10); zoomRect.X = 0; } //绘制放大镜的准星 int blockX = e.ClipRectangle.Width / 2; int blockY = (e.ClipRectangle.Height - infoAreaHeight) / 2; SolidBrush brush = new SolidBrush(Color.FromArgb(10, 124, 202)); Pen pen = new Pen(brush, 2.0F); e.Graphics.DrawLine(pen, new Point(0, blockY + 5), new Point(e.ClipRectangle.Width, blockY + 5)); //加5解决放大镜准星和实际鼠标位置对不上的问题; e.Graphics.DrawLine(pen, new Point(blockX, 0), new Point(blockX, e.ClipRectangle.Height - infoAreaHeight)); //绘制信息区墨色背景 Rectangle rectInfo = new Rectangle(0, e.ClipRectangle.Height - infoAreaHeight, e.ClipRectangle.Width, infoAreaHeight); brush = new SolidBrush(Color.FromArgb(51, 51, 51)); e.Graphics.FillRectangle(brush, rectInfo); //计算截图区域的大小 if (this.lbl_CutImage.Visible) { this.areaSize = new System.Drawing.Size(this.lbl_CutImage.Width - 4, this.lbl_CutImage.Height - 4); if (this.areaSize.Width < 1) { this.areaSize.Width = 1; } if (this.areaSize.Height < 1) { this.areaSize.Height = 1; } } else { this.areaSize = rect_WindowFromPoint.Size; } //绘制截取区域大小 brush = new SolidBrush(Color.White); Font font = new System.Drawing.Font(FontFamily.GenericSerif, 12.0F, GraphicsUnit.Pixel); string str = this.areaSize.Width + " x " + this.areaSize.Height; e.Graphics.DrawString(str, font, brush, new PointF(5, rectInfo.Top + 1)); //绘制鼠标指针位置的颜色 this.cRGB = screenImage.GetPixel(MousePosition.X, MousePosition.Y); str = "RGB:#" + this.cRGB.R.ToString("X").PadLeft(2, '0') + this.cRGB.G.ToString("X").PadLeft(2, '0') + this.cRGB.B.ToString("X").PadLeft(2, '0'); e.Graphics.DrawString(str, font, brush, new PointF(5, rectInfo.Top + 15)); label1.Text = "," + (DateTime.Now.Ticks - drawBegin); Application.DoEvents();
效率检测方法:
//在要测试的代码前添加变量记录时间 long drawBegin = DateTime.Now.Ticks; //中间为要测试的代码 //在要测试的代码后添加代码显示时间差 label1.Text = "," + (DateTime.Now.Ticks - drawBegin); Application.DoEvents();
小结
这里有这样几个优化点:
1、省去两个Bitmap对象,就省去两次绘制开销;
2、四层循环改为两层循环,计算量减小;
3、使用“FillRectangle”方法代替“SetPixel”;
本项目完整源码请参考:【拥抱开源】十年之做C#屏幕截图工具全面开源
======================文档信息===========================
版权声明:非商用自由转载-保持署名-注明出处
署名(BY) :testcs_dn(微wx笑)
文章出处:[无知人生,记录点滴](http://blog.csdn.net/testcs_dn)