我写了这个函数用于填充闭环, pixvali 是全局声明的,用于存储第一次点击的像素的颜色值(在闭环内)。
但问题是,当第一个* fill(..,..)*结束时,这个递归不会终止,并且它表示堆栈溢出...
void fill(int x,int y)
{
GLfloat pixval[3];
glReadPixels(x,y,1,1,GL_RGB,GL_FLOAT,pixval);
if(pixval[0]==pixvali[0] && pixval[1]==pixvali[1] && pixval[2]== pixvali[2])
{
glBegin(GL_POINTS);
glVertex2i(x,y);
glEnd();
glFlush();
fill(x-1,y);
fill(x+1,y);
fill(x,y-1);
fill(x,y+1);
}
}
答案 0 :(得分:4)
堆栈溢出是因为您正在使用递归,并且递归的深度与您填充的形状中的像素数呈线性关系。
也可能是您尝试使用与现有颜色相同的颜色填充形状。也就是说,当前的gl颜色与pixvali相同。在这种情况下,您将获得无限递归。
答案 1 :(得分:3)
这个问题很难说清楚,但我的猜测是,你会开始进行像素循环。
例如,假设您只有4个像素需要着色(0,0),(0,1),(1,0),(1,1)。
开始着色(0,0)。然后你的递归将输入(1,0),因为(-1,0)不需要着色。然后再次(0,0),因为它再次是(x-1,y)的像素,依此类推。
您需要添加一些方法来标记已经着色的像素。但这只是猜测,因为你无法真正看到那些功能之外发生了什么。
答案 2 :(得分:1)
不确定实现细节,但如果在堆栈上分配12字节本地数组(3个浮点数为4个字节),那么x和y参数各有4个字节,可能有4个字节用于退货地址。每次递归时至少有24个。这意味着你只需要超过40,000次调用就可以吹掉1MB的堆栈空间,如果没有别的东西,那就不行了。
从透视角度来看,43'690像素仅为800x600显示器的10%左右。
答案 3 :(得分:1)
您需要检查您正在编辑的像素。
e.g。如果你有一个从0,0到10,10的图像,并且你编辑了11,10,你就会得到内存。
所以你需要检查x,y是否在图像的边界之间。
x>=left&&x<=right&&y>=top&&y<=bottom
答案 4 :(得分:0)
实现你自己的堆栈,不要使用递归进行泛洪填充,除非你用像素填充表面积相对较小的形状。
典型的实现是:
Stack stack;
stack.push(firstPoint);
while(!stack.isEmpty()){
Point currentPoint= stack.pop();
//do what ever you want to do here, namely paint.
//boundary check ur surrounding points and push them in the stack if they are inbounds
}
答案 5 :(得分:0)
乍一看,算法看起来不错。我有点担心“==”,因为它们与浮点值不兼容。我建议使用
abs(val1 - val2) < limit
代替(limit
是&lt; 1和&gt; 0.例如,尝试0.0001。
为了追踪错误,我建议在函数的开头添加printf()
。当您看到函数尝试填充的内容时,这将有所帮助。也许它被卡在某个地方并且用相同的坐标一次又一次地召唤自己?
此外,堆栈可能对于您尝试填充的区域来说太小。首先尝试使用一个小区域,比如说一个只有4 x 3像素的小矩形。不要试图用鼠标点击它,而是从内部已知的好点开始(只需在代码中调用fill())。
同时打印颜色值也有帮助。
答案 6 :(得分:0)
你为什么滥用OpenGL?你在那里做的是非常不稳定的。例如,如果使用精心选择的投影和模型视图矩阵的组合,则glReadPixels读取的像素将仅对应于顶点位置。此外,填充的每次迭代都将进行完整的往返。仅仅因为你使用的是OpenGL,它的速度并不快。
如果你想要填充帧缓冲区中的某些区域,请读出整个帧缓冲区,对其进行填充并将结果推回到OpenGL。此外,如果帧缓冲的某些部分被遮挡(通过窗口或类似物),那些部分将不会
现在要了解为什么你最终会进行无限递归。考虑一下:
fill(4, 4)
将致电fill(5, 4)
致电fill(5, 5)
致电fill(4, 5)
致电fill(4, 4)
热潮
现在你已经在那里进行了测试:
if( pixval[0] == pixvali[0] &&
pixval[1] == pixvali[1] &&
pixval[2] == pixvali[2] )
请注意,如果要设置的像素已经具有目标颜色,则此计算结果为true,再次以无限递归方式结束。您应该测试不等式。
最后但并非最不重要:图片可能很容易包含数百万像素。通常的堆栈大小最多只允许1000个函数嵌套级别,因此您可以将尾递归转换为迭代。
TL; DR:不要为此使用OpenGL,在本地缓冲区上运行,使用正确的迭代条件测试并使用迭代而不是递归(或者使用函数式语言,然后编译器将处理尾递归)