C# 之屏幕找图
2015-09-15 17:31
387 查看
引言
最近,由于工作上的某些原因,又要写类似于外挂的程序,又要用到一个屏幕找图功能,很多程序(eg:按键精灵)都提供了类似的功能,其实在这之前,我也查找过很多类似的C#方法,因为之前有一个试过没有用得起,所以最后就放弃了,知道现在都是使用的自己写的一个,相对来说,除了效率比较慢,没有太大的问题。不过就是由于效率不高,后面又想了其他的一些解决办法。
基础+贴代码。
因为是一些图片处理和操作,所以必不可少的会用到C# GDI+的一些基本知识,对于这个网上应该也有很多,大家可以拿来学习和参考。
再者,其实细细想一下,其实应该很简单,为什么呢,因为就是一个一个像素的比较,比较颜色差异,没有差异就通过,有差异,就继续查找,知道找到必须要,且完全匹配就OK。
于是乎有了下面的代码。1.0
// 基础代码和调用代码 (注释基本,略,后面又没有添加,多多包涵)
ImageManager 2.0
终于支持多线程了,然后测试了一下,效率略有增加,不过没有太大的感觉。但是用别人的工具,感觉特别快,因为软件上面写的50,60毫秒,我就想啊,到底是哪里拖慢了速度呢。。。当然,没有想到。所以这里就抛砖引玉了。。。
总结
博客园的编辑器,每次我都感觉自己不会用,别人写的文章,编辑出来效果杠杠的,为什么我这个不行呢,感觉有点坑。
最后,欢迎拍砖。
谢谢支持。
最近,由于工作上的某些原因,又要写类似于外挂的程序,又要用到一个屏幕找图功能,很多程序(eg:按键精灵)都提供了类似的功能,其实在这之前,我也查找过很多类似的C#方法,因为之前有一个试过没有用得起,所以最后就放弃了,知道现在都是使用的自己写的一个,相对来说,除了效率比较慢,没有太大的问题。不过就是由于效率不高,后面又想了其他的一些解决办法。
基础+贴代码。
因为是一些图片处理和操作,所以必不可少的会用到C# GDI+的一些基本知识,对于这个网上应该也有很多,大家可以拿来学习和参考。
再者,其实细细想一下,其实应该很简单,为什么呢,因为就是一个一个像素的比较,比较颜色差异,没有差异就通过,有差异,就继续查找,知道找到必须要,且完全匹配就OK。
于是乎有了下面的代码。1.0
// 基础代码和调用代码 (注释基本,略,后面又没有添加,多多包涵)
public class ImageManager { private static List<Point> result = new List<Point>(); public static event Action<int, Image> DoPic; private static int width = 0; private static int height = 0; /// <summary> /// 多线程找图 /// </summary> /// <param name="bigImage"></param> /// <param name="smallImage"></param> /// <returns></returns> public static Point ThreadCompare(Bitmap bigImage, Bitmap smallImage) { result = new List<Point>(); // 先拆分大图成为16个小图片,每个小图片都需要加上smallImage的长宽组成一个新图片 // 需要16个线程来完成。 width = (int)Math.Ceiling(bigImage.Width / 4.0); height = (int)Math.Ceiling(bigImage.Height / 4.0); int maxWidth = width + smallImage.Width; int maxHeight = height + smallImage.Height; int index = 0; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { Bitmap bitMap = null; if (i == 3 && j == 3) { bitMap = new Bitmap(width, height); } else if (j == 3) { bitMap = new Bitmap(maxWidth, height); } else if (i == 3) { bitMap = new Bitmap(width, maxWidth); } else { bitMap = new Bitmap(maxWidth, maxHeight); } Graphics resultG = Graphics.FromImage(bitMap); resultG.DrawImage(bigImage, new Rectangle(0, 0, bitMap.Width, bitMap.Height), new Rectangle(i * width, j * height, bitMap.Width, bitMap.Height), GraphicsUnit.Pixel); resultG.Dispose(); if (DoPic != null) { DoPic(index, CloneImg(bitMap)); } ThreadPool.QueueUserWorkItem(new WaitCallback(CompareThread), new object[] { bitMap, CloneImg(smallImage), i, j }); index++; } } while (result.Count != 16) { Thread.Sleep(50); } var point = new Point(-1, -1); if (result.Exists(p => p.X >= 0)) { point = result.Find(a => a.X >= 0); } return point; } public static Point Compare(Bitmap bigImage, Bitmap smallImage) { for (int i = 0; i < bigImage.Width; i++) { for (int j = 0; j < bigImage.Height; j++) { Color c1 = bigImage.GetPixel(i, j); Color c2 = smallImage.GetPixel(0, 0); // 颜色相等,且没有超出边界 if (Compare(c1, c2) && bigImage.Width >= (i + smallImage.Width) && bigImage.Height >= (j + smallImage.Height)) { bool iscontinue = false; for (int x = 0; x < smallImage.Width; x++) { for (int y = 0; y < smallImage.Height; y++) { Color c3 = smallImage.GetPixel(x, y); Color c4 = bigImage.GetPixel(i + x, j + y); if (!Compare(c3, c4)) { iscontinue = true; break; } } if (iscontinue) { break; } } if (!iscontinue) { return new Point(i, j); } } } } return new Point(-1, -1); } private static void CompareThread(object obj) { object[] objs = obj as object[]; Bitmap bigImage = objs[0] as Bitmap; Bitmap smallImage = objs[1] as Bitmap; int indexI = Convert.ToInt32(objs[2]); int indexJ = Convert.ToInt32(objs[3]); bool isbreak = false; Point p = new Point(-1, -1); for (int i = 0; i < bigImage.Width; i++) { for (int j = 0; j < bigImage.Height; j++) { Color c1 = bigImage.GetPixel(i, j); Color c2 = smallImage.GetPixel(0, 0); // 颜色相等,且没有超出边界 if (Compare(c1, c2) && bigImage.Width >= (i + smallImage.Width) && bigImage.Height >= (j + smallImage.Height)) { bool iscontinue = false; for (int x = 0; x < smallImage.Width; x++) { for (int y = 0; y < smallImage.Height; y++) { Color c3 = smallImage.GetPixel(x, y); Color c4 = bigImage.GetPixel(i + x, j + y); if (!Compare(c3, c4)) { iscontinue = true; break; } } if (iscontinue) { break; } } if (!iscontinue) { isbreak = true; p = new Point(i + indexI * width, j + indexJ * height); break; } } } if (isbreak) { break; } } result.Add(p); } private static bool Compare(Color c1, Color c2) { if (c1.A == c2.A && c1.R == c2.R && c1.B == c2.B && c1.G == c2.G) { return true; } return false; } private static Bitmap CloneImg(Image img) { using (MemoryStream mostream = new MemoryStream()) { Bitmap bmp = new Bitmap(img); bmp.Save(mostream, System.Drawing.Imaging.ImageFormat.Jpeg);//将图像以指定的格式存入缓存内存流 byte[] bt = new byte[mostream.Length]; mostream.Position = 0;//设置留的初始位置 mostream.Read(bt, 0, Convert.ToInt32(bt.Length)); return bmp; } } }
ImageManager 2.0
终于支持多线程了,然后测试了一下,效率略有增加,不过没有太大的感觉。但是用别人的工具,感觉特别快,因为软件上面写的50,60毫秒,我就想啊,到底是哪里拖慢了速度呢。。。当然,没有想到。所以这里就抛砖引玉了。。。
总结
博客园的编辑器,每次我都感觉自己不会用,别人写的文章,编辑出来效果杠杠的,为什么我这个不行呢,感觉有点坑。
最后,欢迎拍砖。
谢谢支持。
相关文章推荐
- C# MVC 项目的创建和发布过程
- C#格式化数值结果表
- C# 编写Windows Service(windows服务程序)
- C#创建windows服务搭配定时器Timer使用实例
- C#中缓存的基本用法总结
- C#获取管理员权限
- C#实现邮件发送,可以添加附件,发件人、收件人信息从xml文件读取
- (C# File) 文件操作
- C#去掉窗口最小化时左下角的窗口
- C# 打开目录并选中文件的相关问题
- C# using用法详解
- 重新学习C# 之 变量
- C# 委托及各种写法
- c#绘制表格
- .NET基础--if-else与swirch的区别
- C#操作注册表
- 关于c#调用c编译器
- c#的委托和事件的实例学习
- .NET基础--if与else的匹配问题
- 几个常见的C#小问题