Android Question Flood Fill ?

Colin Harvey

Member
Licensed User
Hi, first time posting here after recent purchase of B4A, and am loving this dev system !

I'm writing an App that displays a number of Maps as bitmaps with pre-outlined areas that I want to be able to Flood-Fill depending on user selections. Is there a graphics library that already implements a good Flood-Fill procedure, without having to code it pixel by pixel. I envisage storing a single x,y coordinate for each area, and then calling a FloodFill based on that coordinate to change the colour of entire areas.

Many Thanks,
Colin
 

eurojam

Well-Known Member
Licensed User
Longtime User
Hi Colin,
did you search the forum for? In "similar Threads" above your post, there are some discussions about this ...

additional you can check stackoverflow: https://stackoverflow.com/posts/8505972/edit
together with the canvas object or the jpeg library it should be not that big thing...

Best
Stefan
 
Upvote 0

Colin Harvey

Member
Licensed User
Hi Stefan, I saw a couple of threads where people were discussing implementing a flood fill themselves, but performance is likely to be a significant issue. My expectation was that this was probably something that would have already been done at a low-level (eg. by the Android OS) in a high performance language (assembly or C), so I didnt want to reinvent the wheel unnecessarily ! Most of my Fillable areas are likely to be within 150x150 pixels, so it maybe be feasible to code it in B4A ? (I want the user to tap the screen and get a filled area within say 1 second max., preferably quicker !)
 
Upvote 0

Colin Harvey

Member
Licensed User
OK, I found a C example and recoded it in B4A, to produce the following, which works well enough for my requirements.
My input ImageView object 'imgFill' was loaded with a bitmap produced in Photoshop, using a Black line drawing with Transparent areas
The Fill_IMG_at procedure maintains its own 'stack' array of fill points it needs to go back to. I ran this on a variety of shapes of sizes upto
around 100x100 pixels and my stack never went over 10 items, so the arbitrary size of the array at 1000 should be plenty for similar areas.
If you try to fill an unbounded area you may well get an array overflow error though, so ensure your areas are closed.
The Test code below fills one selected area:

Sub TestFill
Dim intXfill, intYfill,intFillColour, intOldColour As Int

intFillColour = Colors.RGB(255,0,0) 'Red
intOldColour =0 '*.PNG Transparent colour

intXfill = 100 ' a seed point in my image to start the fill at
intYfill = 50
Fill_IMG_at(imgFill,intXfill,intYfill,intFillColour,intOldColour)
End Sub

'Pass in:
' - reference to an existing imageView object, ie "imgFill"
' - an x,y seed point to start filling at
' - a colour to fill with, and the oldColour to replace
Sub Fill_IMG_at(imgPassed As ImageView, floatX As Float, floatY As Float, intNewColour As Int, intOldColour As Int)

'the following code inspired by http://lodev.org/cgtutor/floodfill.html
'using the "floodFillScanlineStack" procedure, by Lode Vandevenne

Dim canvasFill As Canvas
canvasFill.Initialize(imgPassed) 'attach Canvas to image

'Code modelled on floodFillScanlineStack
Dim x1 As Int
Dim spanAbove As Boolean
Dim spanBelow As Boolean
Dim intW As Int = imgPassed.Width
Dim intH As Int = imgPassed.Height

Dim intStackMax As Int = 1000 'arbitrary stack size = 1000 points
Dim arrStack(intStackMax,2) As Float 'subscript 0 = X, subscript 1 = Y
Dim intStackPointer As Int = -1 '-1 = empty stack

'push the first coordinate onto our stack
intStackPointer = intStackPointer + 1
arrStack(intStackPointer,0) = floatX
arrStack(intStackPointer,1) = floatY

'loop as long as stack isnt empty
Do While intStackPointer > -1
'pop a coord off our stack
floatX= arrStack(intStackPointer,0)
floatY= arrStack(intStackPointer,1)
intStackPointer=intStackPointer-1

x1 = floatX

Do While x1 >= 0 And canvasFill.Bitmap.GetPixel(x1,floatY) = intOldColour
x1=x1-1​
Loop
x1=x1+1
spanAbove = False '0
spanBelow = False '0
Do While x1 < intW And canvasFill.Bitmap.GetPixel(x1,floatY) = intOldColour
canvasFill.DrawPoint(x1,floatY,intNewColour)

If spanAbove=False And floatY > 0 And canvasFill.Bitmap.GetPixel(x1,floatY-1) = intOldColour Then
'push the coordinate onto our stack
intStackPointer = intStackPointer + 1
arrStack(intStackPointer,0) = x1
arrStack(intStackPointer,1) = floatY-1

spanAbove = True '1
Else if spanAbove=True And floatY > 0 And canvasFill.Bitmap.GetPixel(x1,floatY-1) <> intOldColour Then
spanAbove = False '0
Else
End If

If spanBelow=False And floatY < intH - 1 And canvasFill.Bitmap.GetPixel(x1,floatY+1) = intOldColour Then
'push the coordinate onto our stack
intStackPointer = intStackPointer + 1
arrStack(intStackPointer,0) = x1
arrStack(intStackPointer,1) = floatY+1

spanBelow = True '1
Else If spanBelow = True And floatY < intH -1 And canvasFill.Bitmap.GetPixel(x1,floatY+1) <> intOldColour Then
spanBelow = False '0
Else
End If

x1 = x1 + 1​
Loop​
Loop

imgPassed.Invalidate 'force redraw of passed image from our attached canvas
End Sub
 
Last edited:
Upvote 0
Top