重庆免费微网站建设,wordpress 扫描工具,网站开发都需要什么工作,wordpress分类 菜单今天写程序中有一个地方用到了漫水填充#xff08;FloodFill#xff09;。所谓漫水填充#xff0c;简单来说#xff0c;如下图中左图#xff0c;白布上有一块红色的斑点#xff0c;在这个红色的斑点上点一下#xff0c;就自动选中了和该点相连的红色的区域#xff0c;接…今天写程序中有一个地方用到了漫水填充FloodFill。所谓漫水填充简单来说如下图中左图白布上有一块红色的斑点在这个红色的斑点上点一下就自动选中了和该点相连的红色的区域接着将该区域替换成指定的颜色如下图中右图所示。 GDI中有一个函数 ExtFloodFill 可以用于漫水填充。函数原型是 BOOL ExtFloodFill(HDC hdc,int nXStart,int nYStart,COLORREF crColor,UINT fuFillType) 在C#中使用这个函数并不好用这里有一个例子 http://www.codeproject.com/Feature/WickedCode.aspx?msg2364985 。照猫画虎的写了一遍结果返回的结果是false——填充失败。 对win32这些东西看着就烦也没心思去看到底哪里出错了干脆自己写一个 FloodFill 算法得了。 算法很简单 1将最初的点作为种子点压入栈中 2弹出一个种子点把它涂成目标颜色 3对于种子点来说和它相邻的有4个像素判断这4个像素中的颜色是否是背景色如果是则作为新的种子点入栈 4循环至栈空。 实现起来也很简单一共只需要22行代码比用DllImport去调用ExtFloodFill代码量还少 void FloodFill(ImageRgb24 img, Point location, Rgb24 backColor, Rgb24 fillColor) { int width img.Width; int height img.Height; if (location.X 0 || location.X width || location.Y 0 || location.Y height) return; if (backColor fillColor) return; if (img[location.Y, location.X] ! backColor) return; StackPoint points new StackPoint(); points.Push(location); int ww width -1; int hh height -1; while (points.Count 0) { Point p points.Pop(); img[p.Y, p.X] fillColor; if (p.X 0 img[p.Y, p.X - 1] backColor) { img[p.Y, p.X - 1] fillColor; points.Push(new Point(p.X - 1, p.Y)); } if (p.X ww img[p.Y, p.X 1] backColor) { img[p.Y, p.X 1] fillColor; points.Push(new Point(p.X 1, p.Y)); } if (p.Y 0 img[p.Y - 1, p.X] backColor) { img[p.Y - 1, p.X] fillColor; points.Push(new Point(p.X, p.Y - 1)); } if (p.Y hh img[p.Y 1, p.X] backColor) { img[p.Y 1, p.X] fillColor; points.Push(new Point(p.X, p.Y 1)); } } } 有这个算法为基础类似photoshop的魔术棒选择工具就很容易实现了。漫水填充FloodFill是查找和种子点联通的颜色相同的点魔术棒选择工具则是查找和种子点联通的颜色相近的点将和初始种子点颜色相近的点压进栈作为新种子。 在photoshop cs5中新引进了快速选择工具这个工具看起来很神奇它背后的算法也研究了有些年了就是抠图技术有兴趣的可以去研究这里有一篇很好的综述文章《Image and Video Matting: A Survey》。