Better floodfill
This commit is contained in:
parent
218e54ce70
commit
8037406b33
2 changed files with 62 additions and 99 deletions
141
include/tools.bm
141
include/tools.bm
|
|
@ -145,99 +145,62 @@ sub filledcircle(x,y,r,col as long)
|
||||||
wend
|
wend
|
||||||
end sub
|
end sub
|
||||||
|
|
||||||
|
SUB FloodFill (startX, startY, fillColor~&)
|
||||||
|
' We use a simple array as a stack for (x, y) pairs
|
||||||
|
' For large images, you may need to increase this size
|
||||||
|
DIM stackX(2000) AS INTEGER
|
||||||
|
DIM stackY(2000) AS INTEGER
|
||||||
|
targetColor~&=point(startX,startY)
|
||||||
|
stackPtr = 1
|
||||||
|
|
||||||
sub floodfill (x as integer, y as integer, fillcolor as long)
|
stackX(stackPtr) = startX
|
||||||
dim as integer leftx, rightx, currenty
|
stackY(stackPtr) = startY
|
||||||
dim as integer arrsize, stackptr
|
|
||||||
|
|
||||||
' Create a stack for storing coordinates
|
WHILE stackPtr > 0
|
||||||
arrsize = 1000 ' Adjust based on expected complexity
|
curX = stackX(stackPtr)
|
||||||
redim stack(1 to arrsize, 1 to 2) as integer
|
curY = stackY(stackPtr)
|
||||||
stackptr = 0
|
stackPtr = stackPtr - 1
|
||||||
|
|
||||||
' Get the color at starting point
|
' Move to the left edge of the span
|
||||||
dim startcolor as long
|
x = curX
|
||||||
startcolor = point(x, y)
|
WHILE POINT(x, curY) = targetColor~& AND x >= 0
|
||||||
|
x = x - 1
|
||||||
' If starting on boundary color or fill color, exit
|
WEND
|
||||||
if startcolor = fillcolor then exit sub
|
|
||||||
|
|
||||||
' Push starting point to stack
|
|
||||||
stackptr = stackptr + 1
|
|
||||||
stack(stackptr, 1) = x
|
|
||||||
stack(stackptr, 2) = y
|
|
||||||
|
|
||||||
' Process until stack is empty
|
|
||||||
do while stackptr > 0
|
|
||||||
' Pop a point from stack
|
|
||||||
x = stack(stackptr, 1)
|
|
||||||
y = stack(stackptr, 2)
|
|
||||||
stackptr = stackptr - 1
|
|
||||||
|
|
||||||
' Skip if current point is not startcolor
|
|
||||||
if point(x, y) <> startcolor then _continue
|
|
||||||
|
|
||||||
' Find leftmost point on this scanline
|
|
||||||
leftx = x
|
|
||||||
do while leftx > 0 and point(leftx - 1, y) = startcolor
|
|
||||||
leftx = leftx - 1
|
|
||||||
loop
|
|
||||||
|
|
||||||
' Find rightmost point on this scanline
|
|
||||||
rightx = x
|
|
||||||
do while rightx < _width - 1 and point(rightx + 1, y) = startcolor
|
|
||||||
rightx = rightx + 1
|
|
||||||
loop
|
|
||||||
|
|
||||||
' Fill the scanline
|
|
||||||
line (leftx, y)-(rightx, y), fillcolor
|
|
||||||
|
|
||||||
' Check scanline above
|
|
||||||
currenty = y - 1
|
|
||||||
if currenty >= 0 then
|
|
||||||
for x = leftx to rightx
|
|
||||||
if point(x, currenty) = startcolor then
|
|
||||||
' Push seed point to stack
|
|
||||||
stackptr = stackptr + 1
|
|
||||||
if stackptr > arrsize then
|
|
||||||
' Resize stack if needed
|
|
||||||
arrsize = arrsize * 2
|
|
||||||
redim _preserve stack(1 to arrsize, 1 to 2) as integer
|
|
||||||
end if
|
|
||||||
stack(stackptr, 1) = x
|
|
||||||
stack(stackptr, 2) = currenty
|
|
||||||
|
|
||||||
' Skip adjacent pixels of same color
|
|
||||||
do while x <= rightx and point(x, currenty) = startcolor
|
|
||||||
x = x + 1
|
x = x + 1
|
||||||
loop
|
|
||||||
x = x - 1 ' Adjust for loop increment
|
|
||||||
end if
|
|
||||||
next x
|
|
||||||
end if
|
|
||||||
|
|
||||||
' Check scanline below
|
spanAbove = 0
|
||||||
currenty = y + 1
|
spanBelow = 0
|
||||||
if currenty < _height then
|
|
||||||
for x = leftx to rightx
|
' Process the span moving right
|
||||||
if point(x, currenty) = startcolor then
|
WHILE POINT(x, curY) = targetColor~& AND x < _WIDTH
|
||||||
' Push seed point to stack
|
PSET (x, curY), fillColor~&
|
||||||
stackptr = stackptr + 1
|
|
||||||
if stackptr > arrsize then
|
' Check row above
|
||||||
' Resize stack if needed
|
IF curY > 0 THEN
|
||||||
arrsize = arrsize * 2
|
IF spanAbove = 0 AND POINT(x, curY - 1) = targetColor~& THEN
|
||||||
redim _preserve stack(1 to arrsize, 1 to 2) as integer
|
stackPtr = stackPtr + 1
|
||||||
end if
|
stackX(stackPtr) = x
|
||||||
stack(stackptr, 1) = x
|
stackY(stackPtr) = curY - 1
|
||||||
stack(stackptr, 2) = currenty
|
spanAbove = 1
|
||||||
|
ELSEIF spanAbove = 1 AND POINT(x, curY - 1) <> targetColor~& THEN
|
||||||
|
spanAbove = 0
|
||||||
|
END IF
|
||||||
|
END IF
|
||||||
|
|
||||||
|
' Check row below
|
||||||
|
IF curY < _HEIGHT - 1 THEN
|
||||||
|
IF spanBelow = 0 AND POINT(x, curY + 1) = targetColor~& THEN
|
||||||
|
stackPtr = stackPtr + 1
|
||||||
|
stackX(stackPtr) = x
|
||||||
|
stackY(stackPtr) = curY + 1
|
||||||
|
spanBelow = 1
|
||||||
|
ELSEIF spanBelow = 1 AND POINT(x, curY + 1) <> targetColor~& THEN
|
||||||
|
spanBelow = 0
|
||||||
|
END IF
|
||||||
|
END IF
|
||||||
|
|
||||||
' Skip adjacent pixels of same color
|
|
||||||
do while x <= rightx and point(x, currenty) = startcolor
|
|
||||||
x = x + 1
|
x = x + 1
|
||||||
loop
|
WEND
|
||||||
x = x - 1 ' Adjust for loop increment
|
WEND
|
||||||
end if
|
END SUB
|
||||||
next x
|
|
||||||
end if
|
|
||||||
loop
|
|
||||||
end sub
|
|
||||||
|
|
|
||||||
|
|
@ -180,8 +180,8 @@ sub canvas
|
||||||
if _mousex > boxX1 then
|
if _mousex > boxX1 then
|
||||||
' Start Drawing Logic
|
' Start Drawing Logic
|
||||||
if state.tool = 9 and (mouseclicked or rmouseclicked) then
|
if state.tool = 9 and (mouseclicked or rmouseclicked) then
|
||||||
_dest layers(2).ihandle
|
_dest layers(1).ihandle
|
||||||
_source layers(2).ihandle
|
_source layers(1).ihandle
|
||||||
if mouseclicked then
|
if mouseclicked then
|
||||||
floodfill canX,canY,state.fcolor
|
floodfill canX,canY,state.fcolor
|
||||||
else
|
else
|
||||||
|
|
@ -230,7 +230,7 @@ sub canvas
|
||||||
thickline state.startX, canY, state.startX, state.startY, drawCol
|
thickline state.startX, canY, state.startX, state.startY, drawCol
|
||||||
case 6 ' Filled Rect
|
case 6 ' Filled Rect
|
||||||
line (state.startX, state.startY)-(canX, canY), drawCol, bf
|
line (state.startX, state.startY)-(canX, canY), drawCol, bf
|
||||||
case 7, 8 ' Polygons[cite: 2]
|
case 7, 8 ' Polygons
|
||||||
if pointCount > 0 then
|
if pointCount > 0 then
|
||||||
for p = 1 to pointCount - 1
|
for p = 1 to pointCount - 1
|
||||||
thickline polypoints((p - 1) * 2), polypoints((p - 1) * 2 + 1), polypoints(p * 2), polypoints(p * 2 + 1), drawCol
|
thickline polypoints((p - 1) * 2), polypoints((p - 1) * 2 + 1), polypoints(p * 2), polypoints(p * 2 + 1), drawCol
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue