Computer Graphics (4) - Experiment 4: Seed Filling Algorithm

Experiment 4: Seed Filling Algorithm

4.1 Experimental purpose

Master the seed filling algorithm (recursive algorithm), the improved seed filling algorithm, the scan line seed filling algorithm

4.2 Experiment content

The use of stack for writing function
template library in C++

4.3 Algorithm ideas

The core of all seed filling algorithms is actually a recursive algorithm, which starts from the specified seed point, searches in all directions, and processes pixel by pixel until it encounters a boundary. Various seed filling algorithms are only processing colors and boundaries. different from above.
The essence of the boundary filling algorithm and the injection filling algorithm is actually the same. They are both recursion and search. The only difference is the confirmation of the boundary, that is, the end conditions of the recursion are different. The injection filling algorithm has no concept of boundaries, but only replaces the specified color in the connected area. The boundary filling algorithm just emphasizes the existence of the boundary. As long as the point within the boundary is any color, it will be replaced with the specified color. Boundary filling algorithms are also widely used. The "paint bucket" function in drawing software is an example of boundary filling algorithms.
The basic process of the scan line seed filling algorithm is as follows: when a seed point (x, y) is given, first fill a section of the given area on the scan line where the seed point is located in the left and right directions respectively, and at the same time Note down the range [xLeft, xRight] of this section, and then determine the sections within the given area on the upper and lower scan lines connected to this section, and save them in sequence. Repeat this process until filling is complete.

4.4 Flowchart

(1) Seed filling algorithm (recursive algorithm)
insert image description here(2) Boundary seed filling algorithm (improved)
insert image description here(3) Scan line seed filling algorithm
insert image description here

4.5 Experimental steps

(1) The seed filling algorithm (recursive algorithm)
obtains the color of the point through the getpixel method, and determines whether it is the same as the original color. If it is not the same, change its color to a new color, and achieve order by recursing its 4 connected areas. Reach any element within the area without going outside the area.
(2) Boundary seed filling algorithm (improved)
The color of the point is obtained by the getpixel method, and it is judged whether it is the same as the original color and whether it is the same as the border color. 4 Connected regions to achieve order Reach any element in the region without going out of the region.
(3) Scan line seed filling algorithm
1) Initialize an empty stack to store the seed point, and push the seed point (x, y) into the stack;
2) Determine whether the stack is empty, if the stack is empty, end the algorithm, otherwise take it out The top element of the stack is used as the seed point (x, y) of the current scan line, and y is the current scan line;
3) Starting from the seed point (x, y), fill in the left and right directions along the current scan line until the boundary . Mark the left and right endpoint coordinates of the segment as xLeft and xRight
respectively; 4) Check the pixels in the interval [xLeft, xRight] of the two scan lines y - 1 and y + 1 adjacent to the current scan line, from xLeft Start searching in the direction of xRight. If there are non-boundary and unfilled pixels, find the rightmost one of these adjacent pixels, and push it into the stack as a seed point, and then return to step (2) ;

4.6 Experimental code

(1) Add code to CLiHuchenView().h:

public:
	void Draw();//添加画图成员
	CDC* mpDC;//定义指针
	void Scanseedfill(int x,int y,COLORREF oldColor,COLORREF newColor);//定义扫描线种子填充算法
	void FloodFill(int x, int y, COLORREF oldcolor, COLORREF newcolor);//定义递归种子填充算法
	void BoundaryFill(int x, int y, COLORREF oldcolor, COLORREF newcolor);//定义改进的种子填充算法

(2) Add in LiHuchenView.cpp:

//引入种子库
#include "stack"
using namespace std;
extern stack<CPoint> s;

(3) Add in OnDraw() in LiHuchenView.cpp:

Draw();//添加画图函数

(4) Add function

/*
-----------------------------------区域填充算法---------------------------------------
*/
/
//画图
/
void CLiHuchenView::Draw()
{
    
    
	CDC *pDC=GetDC();//定义指针
	mpDC=pDC;
	POINT ptpolygon1[6]={
    
    {
    
    600,50},{
    
    600,250},{
    
    700,250},{
    
    700,230},{
    
    620,230},{
    
    620,50}};//多边形坐标
	mpDC->Polygon(ptpolygon1,6);//绘制多边形


//	Scanseedfill(610,100,RGB(255,255,255),RGB(255,0,0));//扫描线种子填充算法
//  FloodFill(610,100,RGB(255,255,255),RGB(0,255,0));//递归种子填充算法
    BoundaryFill(610,100,RGB(0,0,0),RGB(0,0,255));//边界种子填充算法
}
/
//记录种子点
/
struct Seed
{
    
    
	int x;int y;
};

/
//扫描线种子填充算法
/

void CLiHuchenView::Scanseedfill(int x, int y, COLORREF oldColor, COLORREF newColor)
{
    
    
	stack<Seed> sp;//种子库
	int xl,xr;
	bool spanNeedfill;
	Seed pt;
	pt.x=x;pt.y=y;
	sp.push(pt);
	while(!sp.empty())
	{
    
    
		pt=sp.top();sp.pop();
		y=pt.y;x=pt.x;
		while(mpDC->GetPixel(x,y)==oldColor)//向右填充
		{
    
    
			mpDC->SetPixel(x,y,newColor);
			x++;
		}
		xr=x-1;x=pt.x-1;
		while(mpDC->GetPixel(x,y)==oldColor)//向左填充
		{
    
    
			mpDC->SetPixel(x,y,newColor);
			x--;
		}
		xl=x+1;
		//处理上面一条扫描线
		x=xl;y=y+1;
		while(x<=xr)
		{
    
    
			spanNeedfill=false;
			while(mpDC->GetPixel(x,y)==oldColor)
			{
    
    
				spanNeedfill=true;
				x++;
			}
			if(spanNeedfill)
			{
    
    
				pt.x=x-1;pt.y=y;
				sp.push(pt);
				spanNeedfill=false;
			}
			while((mpDC->GetPixel(x,y)!=oldColor)&&x<=xr) x++;
		}
 
		//处理下面一条扫描线
		x=xl;y=y-2;
		while(x<=xr)
		{
    
    
			spanNeedfill=false;
			while(mpDC->GetPixel(x,y)==oldColor)
			{
    
    
				spanNeedfill=true;
				x++;
			}
			if(spanNeedfill)
			{
    
    
				pt.x=x-1;pt.y=y;
				sp.push(pt);
				spanNeedfill=false;
			}
			while((mpDC->GetPixel(x,y)!=oldColor)&&x<=xr) x++;
		}
	}

}


/
//递归种子填充算法
/
void CLiHuchenView::FloodFill(int x, int y, COLORREF oldcolor, COLORREF newcolor) 
{
    
    
	//判断当前颜色
	if (mpDC->GetPixel(x, y) == oldcolor)
	{
    
    

		mpDC->SetPixel(x, y,newcolor); //修改颜色
		//寻找周围的临近点,递归
        FloodFill(x, y + 1, oldcolor, newcolor);
        FloodFill(x, y - 1, oldcolor, newcolor);
        FloodFill(x - 1, y, oldcolor, newcolor);
        FloodFill(x + 1, y, oldcolor, newcolor);
     }  
}

/
//改进的种子填充算法(边界填充)
/
void CLiHuchenView::BoundaryFill(int x, int y, COLORREF boundarycolor, COLORREF newcolor)
{
    
    
	//判断是否为边界颜色或者新的颜色
	//默认边界颜色为黑色
	if(mpDC->GetPixel(x, y) != boundarycolor &&mpDC->GetPixel(x, y) !=newcolor)
	{
    
    
		mpDC->SetPixel(x, y, newcolor); //修改颜色
		//寻找周围的临近点,递归
        BoundaryFill(x, y + 1, boundarycolor, newcolor);
        BoundaryFill(x, y - 1, boundarycolor, newcolor);
        BoundaryFill(x - 1, y, boundarycolor, newcolor);
        BoundaryFill(x + 1, y, boundarycolor, newcolor);
	}
	
}

4.7 Display of experimental results

(1) Scanline seed filling algorithm
insert image description here(2) Recursive seed filling algorithm
insert image description here(3) Boundary seed filling algorithm (improved)
insert image description here

Guess you like

Origin blog.csdn.net/chengzilhc/article/details/106728860