區域:指已經表示成點陣形式的填充圖形,是象素的集合。html
區域填充:將區域內的一點(常稱【種子點】)賦予給定顏色,而後將這種顏色擴展到整個區域內的過程。算法
區域填充算法要求區域是連通的,由於只有在連通區域中,纔可能將種子點的顏色擴展到區域內的其它點。數據結構
1)內點表示:枚舉出區域內部的全部象素,內部全部象素着同一個顏色,邊界像素着與內部象素不一樣的顏色。
2)邊界表示:枚舉出區域外部的全部象素,邊界上的全部象素着同一個顏色,內部像素着與邊界象素不一樣的顏色。spa
1)四向連通區域:從區域上一點出發可經過【上、下、左、右】四個方向移動的組合,在不越出區域的前提下,到達區域內的任意象素。
2)八向連通區域:從區域上一點出發可經過【上、下、左、右、左上、右上、左下、右下】八個方向移動的組合,在不越出區域的前提下,到達區域內的任意象素。code
給定區域G一種子點(x, y),首先判斷該點是不是區域內的一點,若是是,則將該點填充爲新的顏色,而後將該點周圍的四個點(四連通)或八個點(八連通)做爲新的種子點進行一樣的處理,經過這種擴散完成對整個區域的填充。htm
這裏給出一個四連通的種子填充算法(區域填充遞歸算法),使用【棧結構】來實現
原理算法原理以下:種子像素入棧,當【棧非空】時重複以下三步:blog
這裏給出八連通的種子填充算法的代碼:遞歸
void flood_fill_8(int[] pixels, int x, int y, int old_color, int new_color) { if(x<w&&x>0&&y<h&&y>0) { if (pixels[y*w+x]==old_color) { pixels[y*w+x]== new_color); flood_fill_8(pixels, x,y+1,old_color,new_color); flood_fill_8(pixels, x,y-1,old_color,new_color); flood_fill_8(pixels, x-1,y,old_color,new_color); flood_fill_8(pixels, x+1,y,old_color,new_color); flood_fill_8(pixels, x+1,y+1,old_color,new_color); flood_fill_8(pixels, x+1,y-1,old_color,new_color); flood_fill_8(pixels, x-1,y+1,old_color,new_color); flood_fill_8(pixels, x-1,y-1,old_color,new_color); } } }
a)有些像素會屢次入棧,下降算法效率,棧結構佔空間
b)遞歸執行,算法簡單,但效率不高,區域內每一像素都要進/出棧,費時費內存
c)改進算法,減小遞歸次數,提升效率內存
從給定的種子點開始,填充當前掃描線上種子點所在的一區段,而後肯定與這一段相鄰的上下兩條掃描線上位於區域內的區段(須要填充的區間),從這些區間上各取一個種子點依次把它們存起來,做爲下次填充的種子點。反覆進行這過程,直到所保存的各區段都填充完畢。get
步驟 1:(初始化)將算法設置的堆棧置爲空。將給定的種子點(x, y)壓入堆棧
步驟 2:(出棧)若是堆棧爲空,算法結束;不然取棧頂元素(x, y)做爲種子點
步驟 3:(區段填充)從種子點(x, y)開始,沿縱座標爲y的當前掃描線向左右兩個方向逐個像素用新的顏色值進行填充,直到邊界爲止即象素顏色等於邊界色。設區間兩邊界的橫座標分別爲xleft 和xright。
步驟4:在與當前掃描線相鄰的上下兩條掃描線上,以區間[xleft, xright]爲搜索範圍,求出須要填充的各小區間,把各小區間中最右邊的點並做爲種子點壓入堆棧,轉到步驟2。
1)搜索原則:
從前一個填充的區間(邊界之間的範圍xleft, xright)做爲後一條掃描線種子點尋找的範圍。
2)填充原則:
從種子點往左,右填,填到邊界
上述算法的描述過於抽象,直接看演示
Stack stack=new Stack();//堆棧 pixel_stack初始化 Stack.push (point); //(x,y)是給定的種子像素 while (!stack.empty()) { p=(Point)(stack.pop());//出棧,從堆棧中取一像素做種子像素 x=p.x; y=p.y; savex=x;//保存種子點的橫座標x的值 while (pixels [y*w+x]!= boundary_color) { pixels [y*w+x]= new_color; x++; } //從種子像素開始向右填充到邊界 xright=x–1; //保存線段的右端點 x=savex–1; //設定種子點往左填充的起點 while (pixels [y*w+x]!= boundary_color) { pixels [y*w+x] = new_color; x=x–1; } //從種子像素開始向左填充到邊界,以上兩步完成區間填充。 xleft=x+1; //保存線段的左端點,加1是由於前面 循環時多減一次 x=xleft; //起點是上次的左端點 y=y+1; //開始處理上一條掃描線 while(x<=xright) //在上一條掃描線上檢查是否須要填充 { span_need_fill=false; //先設定爲不須要填充 while (pixels [y*w+x] ==old_color&&x<=xright ) { //待填充的線段 span_need_fill=true; //發現有舊象素,須要填充 x=x+1; } //待填充的線段處理完,即遇到邊界色,!=old_color跳出 if (span_need_fill) //若是區間須要填充,則將其右端點做爲種子點壓進堆棧 { p=new Point(x-1,y); stack.push (p); //進棧 span_need_fill=false; } //繼續向右檢查以防有遺漏 while (pixels [y*w+x] !=old_color &&x<=xright ) x=x+1; } //在上一條掃描線上檢查完 x=xleft; y=y–2; //造成下一條掃描線的y值 //在下一條掃描線上從左向右檢查位於區間[xleft,xright]上的像素,其方法與在上一條掃描線上檢查的狀況徹底同樣,見書。 }//出棧完
上一篇博客講述了多邊形的掃描轉換 ,這裏將多邊形掃描轉換和區域填充算法進行比較總結。
多邊形掃描轉換是指將多邊形的頂點表示轉化爲點陣表示
區域填充只改變填充顏色,不改變區域表示方式
在區域填充算法中,要求給定區域內的一點做爲種子點,而後從這一點根據連通性將新的顏色擴展到整個區域。
掃描轉換多邊形是從多邊形的邊界(頂點)信息出發,利用多種形式的連貫性進行填充的。
掃描轉換區域填充的核心是知道多邊形的邊界,要獲得多邊形內部的像素集,有不少種辦法。其中掃描線算法是利用一套特殊的數據結構,避免求交,而後一條條掃描線肯定。
區域填充條件更強一些,不但要知道邊界,並且要知道區域內的一點,能夠利用四連通或八連通區域不斷向外擴展。
填充一個定義的區域的選擇包括:
a)選擇實區域顏色或圖案填充方式
b)選擇某種顏色和圖案
這些填充選擇能夠應用於多邊形區域或用曲線邊界定義的區域;此外,區域可用多種畫筆、顏色和透明度參數來繪製
原文出處:https://www.cnblogs.com/wkfvawl/p/11625712.html