这是一个试图实现边界填充算法的简单程序。例如,它将尝试用蓝色填充绿色矩形并保留其他所有内容。
这个程序有什么问题?
这是应用算法之前的图片: 这是应用算法时的图片。你可以清楚地看到算法/应用程序停留在一个地方!
这是源代码:
#include <iostream>
#include <glut.h>
using namespace std;
bool b = false;
void init(void)
{
glClearColor(1.0,0.0,0.0,0.0);
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0.0,1366.0,0.0,768.0);
}
bool getpixelcolor(GLint x, GLint y)
{
unsigned char pick_col[3];
float r,g,b;
glReadPixels(x , y , 1 , 1 , GL_RGB , GL_UNSIGNED_BYTE , pick_col);
r = pick_col[0]/255.0;
g = pick_col[1]/255.0;
b = pick_col[2]/255.0;
//cout<<"b:"<<b<<"\r\n";
if ( (r != 1 )&&( b != 1 )&&( g == 1 ) )//g==1
{
return true;
}
else
{
return false;
}
}
void PutPoint( int x, int y )
{
glBegin (GL_POINTS);
glColor3f (1.0,1.0,1.0);
glVertex2i (x,y);
glEnd();
glFlush();
glPointSize(1);
glBegin (GL_POINTS);
glColor3f (0.0,0.0,1.0);
glVertex2i (x,y);
glEnd();
glFlush();
}
void Filling(int x,int y)
{
bool Value = getpixelcolor(x,y);
if (Value==true)
{
PutPoint(x, y);
Filling (x+1,y);
Filling (x-1,y);
Filling (x,y+1);
Filling (x,y-1);
}
}
void displayfnc()
{
if (b==false)
{
glClear(GL_COLOR_BUFFER_BIT);
b=true;
glColor3f(0.0,1.0,0.0);
glRecti(100,100,200,200);
glFlush();
Filling(180,180);
}
}
void Timer(int extra)
{
glutPostRedisplay();
glutTimerFunc(30,Timer,0);
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(1366,768);
glutInitWindowPosition(0, 0);
glutCreateWindow("BoundaryFill");
init();
glutDisplayFunc(displayfnc);
glutTimerFunc(10,Timer,0);
glutMainLoop();
return 0;
}
答案 0 :(得分:3)
首先,你不应该用glReadPixels / glBegin(GL_POINTS)来窥视和挖掘OpenGL中的像素 - 它的速度和它一样慢。如果要在CPU上实现泛洪填充,请回读整个映像并在CPU内存上执行。
你最大的问题之一是:
r = pick_col[0]/255.0;
g = pick_col[1]/255.0;
b = pick_col[2]/255.0;
if ( (r != 1 )&&( b != 1 )&&( g == 1 ) )
从不 对花车执行相等测试!老实说,在我看来,编译器应该发出一个很大的警告,如果你在浮点数上做==
或!=
,甚至可能会出错。浮点数始终与误差范围相关联,当您在大多数情况下比较浮点的相等性时,它们将比较为不等于(即使它们只相隔一个非常小的epsilon> 0),它们在它们的性质。
为什么不直接测试精确定义的无错误整数?
uint8_t r,g,b;
/* ... */
if ( (r != 0xff) && ( b != 0xff )&& ( g == 0xff ) )
如果您启用了全屏抗锯齿(FSAA),则可能遇到的问题是。在这种情况下,你戳的点可能会被反锯齿,导致像素颜色不完全设置为你指定的值,在这种情况下,泛洪填充算法将失败。也许添加一些保证金/门槛。或者做一些合理的事情并控制值如何被放入内存,自己动手,即将整个图片读回CPU内存,进行泛洪填充,并将其上传到OpenGL纹理中并将其打印在帧缓冲区上。
答案 1 :(得分:2)
我的第一个建议是将整个 display 图像读入本地内存,这样就不需要进行大量的OpenGL调用了。然后在本地构建一个新图像,然后将其推送到 display 。
答案 2 :(得分:1)
以下是您需要的程序: 您可以使用两种方法 我认为方法2是你和其他人对于边界4填充算法也需要的。
#include <iostream>
#include <glut.h>
using namespace std;
bool b=true,c=true;
bool A[50][50]={false};
void init(void)
{
glClearColor(1.0,0.0,0.0,0.0);
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0.0,100.0,0.0,100.0);
}
bool getpixelcolor(GLint x, GLint y)
{
unsigned char pick_col[3];
glReadPixels(x , y , 1 , 1 , GL_RGB , GL_UNSIGNED_BYTE , pick_col);
float r,g,b;
r = pick_col[0]/255.0;
g = pick_col[1]/255.0;
b = pick_col[2]/255.0;
if ((r!=1)&&(b!=1)&&(g==1))g==1
{
return true;
}
else
{
return false;
}
}
void PutPoint( int x, int y )
{
glPointSize(2);
glBegin (GL_POINTS);
glColor3f (0.0,0.0,1.0);
glVertex2i (x,y);
glEnd();
glFlush();
}
void Filling(int x,int y)
{
if (A[x][y]==b&&x<50&&y<50&&x>10&&y>10)
{
A[x][y]=c;
PutPoint(x, y);
Filling (x+1,y);
Filling (x-1,y);
Filling (x,y+1);
Filling (x,y-1);
}
}
void displayfnc()
{
glClear(GL_COLOR_BUFFER_BIT);
if(b==false)
{b=true;
c=false;
}
else
{b=false;
c=true;
}
glColor3f(0.0,1.0,0.0);
glRecti(10,50,10,50);
Filling(40,40);
glFlush();
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(100,100);
glutInitWindowPosition(0, 0);
glutCreateWindow("BoundaryFill");
init();
glutDisplayFunc(displayfnc);
glutMainLoop();
return 0;
}
#include <iostream>
#include <glut.h>
using namespace std;
unsigned char pick_col[50][50][3];
void init(void)
{
glClearColor(1.0,0.0,0.0,0.0);
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0.0,100.0,0.0,100.0);
}
void readAllToBuffer( GLint _start, GLint _end )
{
for (int i=_start;i<_end;i++)
{
for (int j=_start;j<_end;j++)
{
glReadPixels(i , j , 1 , 1 , GL_RGB , GL_UNSIGNED_BYTE , pick_col[i][j]);
}
}
}
bool getpixelcolor(GLint x, GLint y)
{
int r,g,b;
r = pick_col[x][y][0];
g = pick_col[x][y][1];
b = pick_col[x][y][2];
//cout<<"b:"<<b<<"\r\n";
if ((r!=255)&&(b!=255)&&(g==255))//g==1
{
return true;
}
else
{
return false;
}
}
void PutPoint( int x, int y )
{
pick_col[x][y][0]=0;
pick_col[x][y][1]=0;
pick_col[x][y][2]=255;
glPointSize(2);
glBegin (GL_POINTS);
glColor3f (0.0,0.0,1.0);
glVertex2i (x,y);
glEnd();
glFlush();
}
void Filling(int x,int y)
{
bool Value=getpixelcolor(x,y);
if (Value==true)
{
PutPoint(x, y);
Filling (x+1,y);
Filling (x-1,y);
Filling (x,y+1);
Filling (x,y-1);
}
}
void displayfnc()
{ glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.0,1.0,0.0);
glRecti(0,0,50,50);
glFlush();
readAllToBuffer(0, 49);
Filling(40,40);
glFlush();
}
void Timer(int extra)
{
glutPostRedisplay();
glutTimerFunc(30,Timer,0);
}
int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(100,100);
glutInitWindowPosition(0, 0);
glutCreateWindow("BoundaryFill");
init();
glutDisplayFunc(displayfnc);
//glutTimerFunc(10,Timer,0);
glutMainLoop();
return 0;
}
答案 3 :(得分:0)
<强> 1 即可。不是glutSwapBuffers()
,这对于看到某些东西是必不可少的。
<强> 2 即可。您不必使用glFlush()
刷新管道,即使不是glutSwapBuffers()
第3 即可。像素一样逐像素地绘制/读取慢,使用纹理或一些聪明的多边形绘制魔法。
答案 4 :(得分:0)
为什么要制作r,g,b花车?
我会将所有功能更改为:
bool getpixelcolor(GLint x, GLint y)
{
unsigned char pick_col[3];
glReadPixels(x , y , 1 , 1 , GL_RGB , GL_UNSIGNED_BYTE , pick_col);
if ( (pick_col[0] != 255 )&&( pick_col[1] != 255 )&&( pick_col[2] == 255 ) )//g==1
{
return true;
}
else
{
return false;
}
}