掃描線種子填充算法不再采用遞歸的方式處理“4-聯通”和“8-聯通”的相鄰點,而是通過沿水平掃描線填充像素段,一段一段地來處理“4-聯通”和“8-聯通”的相鄰點。這樣算法處理過程中就只需要將每個水平像素段的起始點位置壓入一個特殊的棧,而不需要象遞歸算法那樣將當前位置周圍尚未處理的所有相鄰點都壓入堆棧,從而可以節省堆棧空間。應該說,掃描線填充算法只是一種避免遞歸,提高效率的思想。
基本過程
當給定種子點(x, y)時,首先分別向左和向右兩個方向填充種子點所在掃描線上的位於給定區域的一個區段,同時記下這個區段的范圍[xLeft, xRight],然后確定與這一區段相連通的上、下兩條掃描線上位於給定區域內的區段,並依次保存下來。反復這個過程,直到填充結束。
步驟實現
1) 初始化一個空的棧用於存放種子點,將種子像素(x,y)入棧
2) 當棧為非空時,重復執行以下步驟
a. 棧頂像素出棧
b. 沿掃描線對出棧像素的左右像素進行填充,直到遇到邊界像素為止
c. 將上述區間內最左最右像素記為xLeft和xRight
d. 在區間[xLeft,xRight]內檢查與當前掃描線相鄰的上下兩條掃描線是否全為邊界像素或已填充的像素,若為非邊界和未填充,則把每一區間的最右像素xRight作為種子像素壓入堆棧,重復步驟(2)
步驟示例


代碼實現(基於VC 6.0)
1 /* 掃描線種子生成算法 */ 2 int SetRP(int x,int y,COLORREF color,COLORREF mColor,CDrawDC *pDC){ 3 while(pDC->GetPixel(CPoint(x,y))== mColor){ 4 pDC->SetPixel(ROUND(x),ROUND(y),color); 5 x++; 6 } 7 return x-1; 8 } 9 int SetLP(int x,int y,COLORREF color,COLORREF mColor,CDrawDC *pDC){ 10 while(pDC->GetPixel(CPoint(x-1,y))==mColor){ 11 pDC->SetPixel(ROUND(--x),ROUND(y),color); 12 } 13 return x; 14 } 15 void NewLineSeed(std::stack<CPoint> *stk,int lx,int rx,int y,COLORREF color,COLORREF mColor,CDrawDC *pDC){ 16 for(int x=lx+1,e=rx+1;x<e;x++){ 17 if(pDC->GetPixel(CPoint(x,y))!=mColor){ 18 if(pDC->GetPixel(CPoint(x-1,y))==mColor) 19 stk->push(CPoint(x-1,y)); 20 } 21 } 22 if(pDC->GetPixel(CPoint(x-1,y))==mColor) 23 stk->push(CPoint(x-1,y)); 24 } 25 void CDrawDC::ScanLineSeedFill(int x, int y, COLORREF color) 26 { 27 int pRight,pLeft; 28 std::stack<CPoint> stk; 29 mColor = GetPixel(CPoint(x,y)); 30 31 stk.push(CPoint(x,y)); 32 while(!stk.empty()){ 33 CPoint p=stk.top(); 34 stk.pop(); 35 36 pRight = SetRP(p.x,p.y,color,mColor,this); 37 pLeft = SetLP(p.x,p.y,color,mColor,this); 38 39 NewLineSeed(&stk,pLeft,pRight,p.y+1,color,mColor,this); 40 NewLineSeed(&stk,pLeft,pRight,p.y-1,color,mColor,this); 41 } 42 }
