請問畫圖工具中的填充工具的演算法如何實現? |
尚未結案
|
ychx
一般會員 發表:40 回覆:14 積分:10 註冊:2003-08-03 發送簡訊給我 |
|
aquarius
資深會員 發表:3 回覆:347 積分:330 註冊:2003-05-21 發送簡訊給我 |
|
sigmaccc
一般會員 發表:32 回覆:40 積分:14 註冊:2003-11-13 發送簡訊給我 |
引言: 可以參考一下別人寫的 http://www.delphibox.com/article.asp?articleid=1117 其實這些填充演算法, 在電腦圖學的書上也都會提到, 多看點書應該灳不難做出來啦!! 不過, 更快的是直接呼叫 FloodFill , 呵呵. ...Aquarius那個連結已經不見了,可否再請大大同次提供資料? 因為要用800x600 256色模式寫DOS程式,所以floodfill必需自行撰寫。 發表人 - sigmaccc 於 2004/10/13 10:38:37 |
japhenchen
高階會員 發表:51 回覆:444 積分:184 註冊:2003-07-23 發送簡訊給我 |
給你一個簡單的想法~~用遞迴的方法~~
function FillColor(aCanvas:TCanvas;ax,ay,PickColor,acolor:Integer):boolean; // aCanvas你想要填充的畫布 // ax,ay 要偵測的點 // pickcolor 要被填充的顏色 // acolor 要填充的顏色 begin if aCanvas.Pixels[ax,ay]=PickColor then begin aCanvas.Pixels[ax,ay]:=aColor; // 想法很簡單,如果指定的點跟原來一開始被指定的點相同色,則換色 FillColor(aCanvas,ax,ay-1,PickColor,aColor); FillColor(aCanvas,ax-1,ay,PickColor,aColor); FillColor(aCanvas,ax 1,ay,PickColor,aColor); FillColor(aCanvas,ax,ay 1,PickColor,aColor); //上下左右四點偵測法,遞回這個函數進行重覆的工作 //如果臨近的四個點跟一開始設定的點顏色不同,這里根本不會進行,也就是遇邊界了 end; end; procedure TForm.Image1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin fillcolor(Image1.Picture.Bitmap.Canvas, x,y, Image1.Picture.Bitmap.Canvas.Pixels[x,y], clBlack); end;任何一種多邊形、圓形,只要是封閉的區塊都可以進行,不然就floodfill洪水潰堤了! 這個方法有個大缺點,由於使用遞迴,需要大量的堆疊空間才能跑,不然會出現stack overflow的錯誤,二種改進的方法,一是加大堆疊空間,二就是自己寫堆疊器來記錄(那就不能用遞迴囉) 第二種改進的方法可以請各位大大一塊來發揮唄~ 藏私の禁止 |
japhenchen
高階會員 發表:51 回覆:444 積分:184 註冊:2003-07-23 發送簡訊給我 |
不用遞迴的方法,變相的使用堆疊來做記錄,改用較快的scanline改進填充速度
procedure FillColor(aBmp:TBitmap;ax,ay,PickColor,acolor:Integer); type StackField=Record xl , xr ,y : integer; end; type PArr = ^TRGBTripleArray; TRGBTripleArray = array [Byte] of TRGBTriple; var Stack : array of StackField; NoEdge: boolean ; px,py,nx,ny,pyd : integer; xBmp : TBitmap; pcolor : TColor ; p: PArr; procedure ResetStack; begin SetLength(Stack,1); Stack[0].y:=0; end; function isStackEmpty:boolean; begin Result:=(Stack[0].y=0); end; procedure Push(xl,xr,yd:integer); begin inc(Stack[0].y); if Stack[0].y>length(Stack)-1 then Setlength(Stack,length(Stack) 1); Stack[Stack[0].y].xl:=xl; Stack[Stack[0].y].xr:=xr; Stack[Stack[0].y].y:=yd; end; procedure Pop(var xl,xr,yd:integer); begin if Stack[0].y>0 then begin xl:=Stack[Stack[0].y].xl; xr:=Stack[Stack[0].y].xr; yd:=Stack[Stack[0].y].y; dec(Stack[0].y); setlength(Stack,length(Stack)-1); end; end; begin xBmp:=TBitmap.Create; xBmp.PixelFormat:=pf24bit; xBmp.Width:=aBmp.Width; xBmp.Height:=aBmp.Height; xbmp.Canvas.Draw(0,0,abmp); ResetStack; P:=xBmp.ScanLine[ay]; p[ax*3 1].rgbtRed:=0; pcolor:= p[ax].rgbtRed or(p[ax].rgbtGreen shl 8)or(p[ax].rgbtBlue shl 16); px:=ax; py:=ay; noEdge:=false; Push(px,py,0); p[px].rgbtRed:=aColor and $000000FF; p[px].rgbtGreen:=(aColor and $0000FF00)shr 8; p[px].rgbtBlue:=(aColor and $00FF0000)shr 16; Application.ProcessMessages; while (not NoEdge) and (not isStackEmpty) do begin noEdge:=true; if (px-1)>=0 then begin P:=xBmp.ScanLine[py]; pcolor:= p[px-1].rgbtRed or(p[px-1].rgbtGreen shl 8)or(p[px-1].rgbtBlue shl 16); if pColor=PickColor then begin p[px-1].rgbtRed:=aColor and $000000FF; p[px-1].rgbtGreen:=(aColor and $0000FF00)shr 8; p[px-1].rgbtBlue:=(aColor and $00FF0000)shr 16; noEdge:=false; push(px-1,py,0); end; end; if (py-1)>=0 then begin P:=xBmp.ScanLine[py-1]; pcolor:= p[px].rgbtRed or(p[px].rgbtGreen shl 8)or(p[px].rgbtBlue shl 16); if pColor=PickColor then begin p[px].rgbtRed:=aColor and $000000FF; p[px].rgbtGreen:=(aColor and $0000FF00)shr 8; p[px].rgbtBlue:=(aColor and $00FF0000)shr 16; noEdge:=false; push(px,py-1,0); end; end; if (px 1) |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |