FloodFill with threshold possible?

Find quick help here to get you started with Hollywood
Post Reply
amyren
Posts: 410
Joined: Thu May 02, 2019 11:53 am

FloodFill with threshold possible?

Post by amyren »

Is there a way to achieve FloodFill to also fill the surrounding pixels with near-similar colors?
Preferably by being able to set a threshold value to control this.
Something like the threshold setting found in Gimp.

If not, would this be possible to add as an option to FloodFill in the future?
amyren
Posts: 410
Joined: Thu May 02, 2019 11:53 am

Re: FloodFill with threshold possible?

Post by amyren »

Deepseek came up with a way to floodfill with a threshold value.
I asked it to make a small example of a working code that loads a 640x480 testimage and floodfills it with RED color in the area where clicked, and to use a threshold variable to also fill similar colors. After quite a lot of corrections, the code is working. The Filling process is quite slow but it does what it was asked to. Setting the threshold value to 0 will only fill the exact same color.

Here is the working code:
Any suggestions to speed up the process?

Code: Select all

@DISPLAY {Title = "Flood Fill with Threshold", Width = 640, Height = 480, Color = #WHITE}

; Constants
CANVAS_WIDTH = 640
CANVAS_HEIGHT = 480

; Global variables
Global activeBrush
Global threshold = 1 ; Default threshold (1-100)
Global colorToFill = #RED ; Default fill color


; Function to calculate the color difference between two colors
Function ColorDifference(color1, color2)
    ; If the colors are identical, return 0
    If color1 = color2
        Return(0)
    EndIf

    ; Extract RGB components from color1
    r1 = (color1 >> 16) & 255
    g1 = (color1 >> 8) & 255
    b1 = color1 & 255

    ; Extract RGB components from color2
    r2 = (color2 >> 16) & 255
    g2 = (color2 >> 8) & 255
    b2 = color2 & 255

    ; Calculate the Euclidean distance between the two colors
    diff = Sqrt((r1 - r2)^2 + (g1 - g2)^2 + (b1 - b2)^2)

    ; Normalize the difference to a range of 0-100
    normalizedDiff = (diff / 441.67) * 100
    Return(normalizedDiff)
EndFunction

; Custom flood fill function with threshold
Function FloodFillWithThreshold(x, y, targetColor, fillColor, threshold)

    ; Create a stack for storing pixels to process
    stack = CreateList()
    InsertItem(stack, {x = x, y = y})

    ; Create a visited matrix to avoid reprocessing pixels
    visited = {} ; Use a table to simulate a 2D array
    For Local i = 0 To CANVAS_WIDTH - 1
        visited[i] = {}
        For Local j = 0 To CANVAS_HEIGHT - 1
            visited[i][j] = False
        Next
    Next

    ; Process the stack
    While ListItems(stack) > 0
        ; Pop the last pixel from the stack
        pixel = RemoveItem(stack, ListItems(stack) - 1)
        x = pixel.x
        y = pixel.y

        ; Check if the pixel is within bounds
        If x >= 0 And x < CANVAS_WIDTH And y >= 0 And y < CANVAS_HEIGHT
            ; Check if the pixel has already been visited
            If Not visited[x][y]
                ; Get the color of the current pixel from the brush
                currentColor = ReadBrushPixel(activeBrush, x, y)

                ; Calculate the color difference
                diff = ColorDifference(currentColor, targetColor)
                If IsNil(diff)
                Else
                    ; Check if the color difference is within the threshold
                    If diff <= threshold
                        ; Set the pixel in the brush to the fill color
                        SelectBrush(activeBrush)
                        Line(x, y, x, y, fillColor)

                        ; Mark the pixel as visited
                        visited[x][y] = True

                        ; Add neighboring pixels to the stack
                        InsertItem(stack, {x = x + 1, y = y})
                        InsertItem(stack, {x = x - 1, y = y})
                        InsertItem(stack, {x = x, y = y + 1})
                        InsertItem(stack, {x = x, y = y - 1})
                    EndIf
                EndIf

                ; Increment the debug counter
                debugCounter = debugCounter + 1
            EndIf
        EndIf
    Wend
EndFunction

; Main program
Function p_Main()
    ; Load the test image with an explicit brush ID (or use NIL for auto-assign)
    activeBrush = LoadBrush(Nil, "testfile.png")
    If activeBrush = Nil
        DebugPrint("Error: Could not load testfile.png!")
        Return
    EndIf

    ; Display the loaded brush
    DisplayBrush(activeBrush, 0, 0)

    ; Main loop
    Repeat
        ; Wait for a mouse click event
        WaitLeftMouse

        ; Get the mouse position
        x = MouseX()
        y = MouseY()

        ; Check if the click is within the canvas bounds
        If x >= 0 And x < CANVAS_WIDTH And y >= 0 And y < CANVAS_HEIGHT
            ; Get the target color at the clicked pixel from the brush
            targetColor = ReadBrushPixel(activeBrush, x, y)

            ; Perform the flood fill with the specified threshold and color
            FloodFillWithThreshold(x, y, targetColor, colorToFill, threshold)

            ; Update the display
            DisplayBrush(activeBrush, 0, 0)
        EndIf
    Forever
EndFunction

; Run the program
p_Main()
User avatar
airsoftsoftwair
Posts: 5830
Joined: Fri Feb 12, 2010 2:33 pm
Location: Germany
Contact:

Re: FloodFill with threshold possible?

Post by airsoftsoftwair »

amyren wrote: Sat Mar 22, 2025 8:40 am If not, would this be possible to add as an option to FloodFill in the future?
Not likely to come as an addition to Hollywood's graphics core but there may be a dedicated image processing plugin in the future which could do that.
Post Reply