一、引言
區域填充是指先將區域內的乙個畫素 ,一般稱為種子點賦予給定的顏色和輝亮,然後將該顏色擴充套件到整個區域內的過程。
二、已有的填充演算法及缺點
1.掃瞄線法
掃瞄線法可以實現已知多邊形域邊界的填充,多邊形域可以是凹的、凸的、還可以是帶孔的。該填充方法是按掃瞄線的順序,計算掃瞄線與待填充區域的相交區間,再用要求的顏色顯示這些區間的畫素,即完成填充工作。這裡區間的端點通過計算掃瞄線與多邊形邊界線的交點獲得。所以待填充區域的邊界線必須事先知道,因此它的缺點是無法實現對未知邊界的區域填充。
2.邊填充演算法
邊填充的基本思想是:對於每一條掃瞄線和每條多邊形邊的交點,將該掃瞄線上交點右方的所有畫素取補。對多邊形的每條邊作些處理,多邊形的順序隨意。該演算法適用於具有幀緩衝器的圖形系統,按任意順序處理多邊形的邊。處理每條邊時,僅訪問與該邊有交的掃瞄線上交點右方的畫素。所有的邊都被處理之後,按掃瞄線順序讀出幀緩衝器的內容,送入顯示裝置。該演算法的優點是簡單,缺點是對於複雜圖形,每一畫素可能被訪問多次,重要的是必須事先知道待填充多邊形的邊界,所以在填充未知邊界的區域時不適用。
3.遞迴演算法
遞迴演算法的優點是程式設計實現時,語言簡潔。但在vb6.0實際程式設計實現時,這種遞迴演算法填充稍稍大一些的圖形就會出現堆疊溢位現象,據我們的實踐證明,遞迴演算法只能連續遞迴深度在2090次左右,也就是說,如果待填充的圖形大於二千多個畫素那麼堆疊溢位。下面給出八連通填充方法的vb程式實現(四連通演算法同理)。
public sub area(p, q as integer)
if ((imagepixels(0, p, q) = red1) and (imagepixels(1, p, q) = green1) and (imagepixels(2, p, q) = blue1)) then
imagepixels(0, p, q) = 0: imagepixels(2, p, q) = 0: imagepixels(1, p, q) = 0
picture1.pset (p, q), rgb(0, 0, 0)
call area(p + 1, q): call area(p, q + 1)
call area(p - 1, q): call area(p, q - 1)
call area(p + 1, q + 1): call area(p + 1, q - 1)
call area(p - 1, q + 1): call area(p - 1, q - 1)
else: exit sub
end if
end sub
三、 演算法的基本思想
本演算法採用兩個佇列(fifo)filled和unfilled來實現區域填充。設計步驟如下:
1. 找出該區域內部任意一點,作為填充種子。
2. 填充該點,並把該點存入佇列filled。
3. 按逆時針,判斷該點的上、右、下、左鄰畫素是否在filled佇列內。如果在filled,說明該相鄰點已填充,若不在filled佇列內,則判斷該相鄰點在未填充佇列unfilled,如果不在則將該相鄰點存入unfilled。
4. 判斷未填充佇列是否為空,若不空,則從佇列unfilled中取出頭元素,轉向第三步。若為空則表示已完成所有畫素填充,結束程式。
四、 程式實現及說明
本演算法定義的佇列突破了遞迴演算法中受堆疊空間大小的限制的束縛,因為它直接占用記憶體空間,與堆疊大小無關。以下源程式在window 2000環境下用vb6.0程式設計實現。
建立如圖所示標準窗體並畫上控制項-2個commandbutton控制項和乙個picturebox控制項,調整大小,並設定控制項的屬性。
4.1 通用宣告
dim xx as integer, yy as integer
dim array1(9000, 2), array2(9000, 2) as integer
4.2 採集
private sub command1_click()
picture1.mousepointer = 2
end sub
4.3 選取種子
private sub picture1_mousedown(button as integer, shift as integer, x as single, y as single)
xx = x '選擇並記錄種子點的位置
yy = y
end sub
4.4 區域填充
private sub command2_click()
dim i, j, k as integer, boundpoint1, boundpoint2 as integer
dim flag as boolean, pixel as long
dim red, green, blue as integer, bound as boolean
flag = true '初始化
i = xx: j = yy: boundpoint1 = 1
array1(1, 1) = i
array1(1, 2) = j
'搜尋邊界點
do while boundpoint1 > 0
boundpoint2 = 0
for k = 1 to boundpoint1
i = array1(k, 1)
j = array1(k, 2)
'搜尋右點
pixel& = picture1.point(i, j + 1)
call isbound(pixel&, bound)
if not bound then
boundpoint2 = boundpoint2 + 1
array2(boundpoint2, 1) = i
array2(boundpoint2, 2) = j + 1
picture1.pset (i, j + 1), rgb(255, 255, 255)
end if
'搜尋左鄰點
pixel& = picture1.point(i, j - 1)
call isbound(pixel&, bound)
if not bound then
boundpoint2 = boundpoint2 + 1
array2(boundpoint2, 1) = i
array2(boundpoint2, 2) = j - 1
picture1.pset (i, j - 1), rgb(255, 255, 255)
end if
'搜尋上鄰點
pixel& = picture1.point(i - 1, j)
call isbound(pixel&, bound)
if not bound then
boundpoint2 = boundpoint2 + 1
array2(boundpoint2, 1) = i - 1
array2(boundpoint2, 2) = j
picture1.pset (i - 1, j), rgb(255, 255, 255)
end if
'搜尋下鄰點
pixel& = picture1.point(i + 1, j)
call isbound(pixel&, bound)
if not bound then
boundpoint2 = boundpoint2 + 1
array2(boundpoint2, 1) = i + 1
array2(boundpoint2, 2) = j
picture1.pset (i + 1, j), rgb(255, 255, 255)
end if
next k
'陣列array2 中的資料傳給array1
boundpoint1 = boundpoint2
for k = 1 to boundpoint1
array1(k, 1) = array2(k, 1)
array1(k, 2) = array2(k, 2)
next k
picture1.refresh
loop
end sub
public sub isbound(p as long, bound as boolean) '判斷p是否為邊界點
red = p& mod 256
bound = false
green = ((p& and &hff00) / 256&) mod 256&
blue = (p& and &hff0000) / 65536
if red = 255 and green = 255 and blue = 255 then
bound = true
end if
end sub
五、 結束語
本演算法實現了在對填充區域的形狀、大小均未知的情況下,以種子點開始向四周對該區域進行「擴散式」的填充。本演算法解決了傳統的遞迴演算法在填充較大區域時(本例中填充區約9800pixels)堆疊溢位的缺點。我們的實驗結果顯示,本演算法就填充區域大小和運算速度而言,都遠遠超過了傳統的遞迴演算法。
VB6 0函式集合
一 型別轉換類函式 1.ctype x 格式 p cbool x 將x轉換為 布林 boolean 型別 p cbyte x 將x轉換為 位元組 byte 型別 p ccur x 將x轉換為 金額 currency 型別 p cdate x 將x轉換為 日期 date 型別 p cdbl x 將x轉...
VB6 0 程式設計入門
識別符號 使用者在程式設計時定義的名稱。關鍵字 vb中擁有固定含義 不能被重新定義的識別符號。常見關鍵字 as 定義乙個變數 date 日期函式 else 條件語句中的 否則 error 錯誤物件 let 屬性定義的關鍵字 me 當前物件 null 表示變數不包含有效資料 nothing 將物件變數...
原創 在VB6 0中訪問登錄檔
以下宣告定義在模組中 declare function regcreatekey lib advapi32.dll alias regcreatekeya byval hkey as long,byval lpsubkey as string,phkresult as long as long de...