Better floodfill

This commit is contained in:
visionmercer 2026-05-04 09:01:12 +02:00
commit 8037406b33
2 changed files with 62 additions and 99 deletions

View file

@ -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

View file

@ -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