种子填充算法(简单和扫描线)
2017-10-31 10:56
162 查看
简单的种子填充算法
扫描线种子填充算法
种子填充算法的思路就是通过区域的一点赋予指定的颜色,然后通过填充其周围的像素点,从而将填充颜色扩展到整个颜色区域的过程。
如何画图
我们已经知道有很多工具可以拿来画图,比如MFC或者是
OpenGL都是画图很好的手段。这两个都是拥有很多适应方法的软件接口。但是我使用的是
Easyx这个更加方便便捷的工具。
该工具可以在如下页面下载,安装至相应的编译器即可。
http://www.easyx.cn/
下载完成之后记得安装
Easyx里面的
Easyx_Help.chm,这里面有许多我们开发会运用到的方法。
我们也知道种子填充算法需要获取点的颜色和在某个点再画上你需要的颜色,所以需要用到如下方法
//这个是为了获取某坐标点的颜色 COLORREF getpixel(int x, int y); //这个是为了在某个点画上你想要的颜色 void putpixel(int x, int y, COLORREF color);
简单的种子填充算法
我们需要的是通过getpixel方法来获取点的颜色,判断其是否与原颜色相同,如果不相同,则变化其颜色为新的 颜色,通过递归其4连通区域来达到有序在不越出区域的情况下,到达区域内的任意元素。
void FloodFill4_1(int x, int y, COLORREF oldcolor, COLORREF newcolor) { try { if (x > 100 && x < 300 && y > 100 && y < 300) { if (getpixel(x, y) == oldcolor) { Sleep(1); putpixel(x, y, newcolor); FloodFill4_1(x, y + 1, oldcolor, newcolor); FloodFill4_1(x, y - 1, oldcolor, newcolor); FloodFill4_1(x - 1, y, oldcolor, newcolor); FloodFill4_1(x + 1, y, oldcolor, newcolor); } } } catch (stack) { } }
扫描线种子填充算法
扫描线填充可由以下4个步骤实现初始化:堆栈置空。讲种子点
(x,y)入栈
出栈:若栈空则结束。否则取栈顶元素
(x,y),以y作为当前扫描线。
填充并确定种子点所在区段:从种子点
(x,y)出发,沿当前扫描线向左、右两个方向填充,直到边界。分别标记区段的左、右端点坐标为
xl和
xr。
确定新的种子点:在区间
[xl,xr]中检查与当前扫描线y上、下相邻的两条扫描线上的像素。若存在非边界、未填充的像素,则把每一区间的最右像素作为种子点压入堆栈,返回第2步。
void ScanFill4(int x, int y, int oldcolor, int newcolor) { int xl, xr, i; bool spanNeedFill; Seed pt; stack *stack1 = new stack(); InitStack(stack1); pt.x = x; pt.y = y; Push(stack1, pt); //将前面生成的区段压入堆栈 while (!IsEmpty(stack1)) { Sleep(10); pt = Pop(stack1); y = pt.y; x = pt.x; while (getpixel(x, y) == oldcolor)//向右填充 { putpixel(x, y, newcolor); x++; } xr = x - 1; x = pt.x - 1; while (getpixel(x, y) == oldcolor) //向左填充 { putpixel(x, y, newcolor); x--; } xl = x + 1; //处理上一条扫描线 x = xl; y = y + 1; while (x<xr) { spanNeedFill = false; while (getpixel(x, y) == oldcolor) { spanNeedFill = true; x++; } if (spanNeedFill) { pt.x = x - 1; pt.y = y; Push(stack1, pt); spanNeedFill = false; } while (getpixel(x, y) != oldcolor && x<xr) x++; } //处理下一条扫描线,代码与处理上一条扫描线类似 x = xl; y = y - 2; while (x<xr) { spanNeedFill = false; while (getpixel(x, y) == oldcolor) { spanNeedFill = true; x++; } if (spanNeedFill) { pt.x = x - 1; pt.y = y; Push(stack1, pt); spanNeedFill = false; } while (getpixel(x, y) != oldcolor && x<xr) x++; } } }
上述算法对于每一个待填充区段,只需要压栈一次,而在递归算法中每一个像素都需要压栈一次。大大提高了区域填充的效率。
算法中遇到的问题
在编写简单的种子算法中遇到了堆栈溢出的问题,这也是正常所在,递归每个像素都需要压栈,而Visal Studio的初始设定安全堆栈大小已经过于小了,临时解决办法为:
Project->Property->Linker->All Options中找到Stack Reserve Size 尽量将其调大就行了相关文章推荐
- 算法系列之十二:多边形区域填充算法--扫描线种子填充算法
- 多边形区域填充算法--扫描线种子填充算法
- 算法系列之十二:多边形区域填充算法--扫描线种子填充算法 .
- Android多边形区域扫描线种子填充算法的示例
- Open gl 的不规则图形的4联通种子递归填充和扫描线种子递归填充算法实现
- 多边形区域填充算法--扫描线种子填充算法
- 多边形区域填充算法--扫描线种子填充算法
- 算法系列之十二:多边形区域填充算法--扫描线种子填充算法
- 多边形区域填充算法--扫描线种子填充算法
- 区域填充:扫描线种子填充算法应用(类似魔术棒功能)
- 多边形区域填充算法--扫描线种子填充算法
- 算法系列之十二:多边形区域填充算法--扫描线种子填充算法
- Open gl 的不规则图形的4联通种子递归填充和扫描线种子递归填充算法实现
- Android多边形区域递归种子填充算法的示例代码
- 种子填充算法在验证码识别中的的应用
- 算法系列之十二:多边形区域填充算法--递归种子填充算法
- 多边形区域填充算法--递归种子填充算法
- 漫水填充算法的一个简单实现(Qt版)
- 算法系列之十二:多边形区域填充算法--扫描线填充算法(有序边表法)
- 种子填充算法在验证码识别中的的应用