Implement a flood fill.

A flood fill is a way of filling an area using color banks to define the contained area or a target color which "determines" the area (the valley that can be flooded; Wikipedia uses the term target color). It works almost like a water flooding from a point towards the banks (or: inside the valley): if there's a hole in the banks, the flood is not contained and all the image (or all the "connected valleys") get filled.

To accomplish the task, you need to implement just one of the possible algorithms (examples are on Wikipedia). Variations on the theme are allowed (e.g. adding a tolerance parameter or argument for color-matching of the banks or target color).

 
Testing: the basic algorithm is not suitable for truecolor images; a possible test image is the one shown on the right box; you can try to fill the white area, or the black inner circle.

'This example requires the Windows API
NoMainWin
WindowWidth = 267.5
WindowHeight = 292.5
UpperLeftX=int((DisplayWidth-WindowWidth)/2)
UpperLeftY=int((DisplayHeight-WindowHeight)/2)
 
Global hDC : hDC = GetDC(0)
Struct point, x As long, y As long
Struct RGB, Red As long, Green As long, Blue As long
Struct rect, left As long, top As long, right As long, bottom As long
 
StyleBits #main.gbox, 0, _WS_BORDER, 0, 0
GraphicBox #main.gbox, 2.5, 2.5, 253, 252
 
Open "Flood Fill - Click a Color" For Window As #main
Print #main, "TrapClose quit"
Print #main.gbox, "Down; Fill Black; Place 125 125; BackColor White; " _
                  + "CircleFilled 115; Place 105 105; BackColor Black; CircleFilled 50; Flush"
Print #main.gbox, "When leftButtonUp gBoxClick"
Print #main.gbox, "Size 1"
Wait
 
    Sub quit handle$
        Call ReleaseDC 0, hDC
        Close #main
        End
    End Sub
 
 
    Sub gBoxClick handle$, MouseX, MouseY
        result = GetCursorPos()
        targetRGB = GetPixel(hDC, point.x.struct, point.y.struct)
        ColorDialog "", replacementColor$
        If replacementColor$ = "" Then Exit Sub
        Print #main.gbox, "Color " + Word$(replacementColor$, 1) + " " + Word$(replacementColor$, 2) + " " + Word$(replacementColor$, 3)
        result = FloodFill(MouseX, MouseY, targetRGB)
        Print #main.gbox, "DelSegment FloodFill"
        Print #main.gbox, "GetBMP FloodFill 0 0 500 500; CLS; DrawBMP FloodFill 0 0; Flush FloodFill"
        Notice "Complete!"
        UnLoadBMP "FloodFill"
    End Sub
 
    Sub ReleaseDC hWnd, hDC
        CallDLL #user32,"ReleaseDC", hWnd As uLong, hDC As uLong, ret As Long
    End Sub
 
    Function GetDC(hWnd)
        CallDLL #user32, "GetDC", hWnd As uLong, GetDC As uLong
    End Function
 
    Function GetCursorPos()
        CallDLL #user32, "GetCursorPos", point As struct, GetCursorPos As uLong
    End Function
 
    Function GetPixel(hDC, x, y)
        CallDLL #gdi32, "GetPixel", hDC As uLong, x As long, y As long, GetPixel As long
    End Function
 
    Function getLongRGB(RGB.Blue)
        getLongRGB = (RGB.Blue * (256 * 256))
    End Function
 
    Function GetWindowRect(hWnd)
        'Get ClientRectangle
        CallDLL #user32, "GetWindowRect", hWnd As ulong, rect As struct, GetWindowRect As ulong
    End Function
 
    Function FloodFill(mouseXX, mouseYY, targetColor)
        Scan
        result = GetWindowRect(Hwnd(#main.gbox))
        X = Int(mouseXX + rect.left.struct)
        Y = Int(mouseYY + rect.top.struct)
        If (GetPixel(hDC, X, Y) <> targetColor) Then
            Exit Function
        Else
            CLS
            Print str$(mouseXX) + "   " + str$(mouseYY)
            Print #main.gbox, "Set " + str$(mouseXX) + " " + str$(mouseYY)
        End If
        If (mouseXX > 0) And (mouseXX < 253) Then
            result = FloodFill((mouseXX - 1), mouseYY, targetColor)
            result = FloodFill((mouseXX + 1), mouseYY, targetColor)
        End If
        If (mouseYY > 0) And (mouseYY < 252) Then
            result = FloodFill(mouseXX, (mouseYY + 1), targetColor)
            result = FloodFill(mouseXX, (mouseYY - 1), targetColor)
        End If
    End Function