how to Coloring floodfill an image?

Gonza8

Member
Licensed User
Longtime User
Hello, i try to make an application for my kids, is like a coloring book, i make the part of load the jpg file only the borders of the images (Black and white image) and i want to paint the differents parts whit the selected color, are there any command to do that?, i try a recursive algorithm but have a StackOverFlow error.
How do they do it??
Please i really missing.

:sign0085::sign0085::sign0137:


Thanks
 

NFOBoy

Active Member
Licensed User
Longtime User
This looks like a job for clippath's.

Look here for how to do a clip path.

An approach for your application would be to make a Map of ClipPath Lists as shown below.. this is just an outline... need to flesh in each part on how you want it to work.


(I don't want to show off how bad an artist I am by filling in the X and Y's, so up to you on where to put the points)


B4X:
Sub Globals
   'These global variables will be redeclared each time the activity is created.
   'These variables can only be accessed from this module.
   Dim canCanvas As Canvas
   Dim mapParts As Map
End Sub
Sub Activity_Create(FirstTime As Boolean)
   'Do not forget to load the layout file created with the visual designer. For example:
   'Activity.LoadLayout("Layout1")

Dim patheye As Path
Dim pathwings As Path
Dim pathlegs As Path

patheye.Initialize(startX, startY)
patheye.LineTo(nextX, nextY)
patheye.LineTo(nextX, nextY)

pathwings.Initialize(startX, startY)
pathwings.LineTo(nextX, nextY)
pathwings.LineTo(nextX, nextY)




mapParts.Initialize

mapParts.Put(0, patheye)
mapParts.Put(1, pathwings)
mapParts.Put(2, pathlegs)

Dim pnlDraw As Panel
pnlDraw.Initialize("pnlDraw")
Activity.AddView(pnlDraw, 0, 0, 100%x, 100%y)


canCanvas.Initialize(pnlDraw)

End Sub
Sub pnlDraw_Touch (Action As Int, X As Float, Y As Float)
   'need to find out which map was clicked
   Dim drawThisPart As Int
   drawThisPart = whichPartClicked(X,Y)
   
   drawPart(drawThisPart)
End Sub


Sub whichPartClicked(x As Int, y As Int) As Int

For i = 0 To mapParts.Size-1
   'loop thru the maps and see if x,y is inside the boundaries
   'if so return that part
Next

End Sub


Sub drawPart(index As Int)

'draw the part to the canvas
'add a clippath
canCanvas.ClipPath(mapParts.GetValueAt(index))


'pick a color
Dim thisColor As Int
Select index
   Case 0 
      thisColor = Colors.Green
   Case 1
      thisColor = Colors.Yellow
   Case Else
      thisColor = Colors.Yellow
End Select

canCanvas.DrawColor(thisColor)

'remove clippath
canCanvas.RemoveClip

End Sub
 
Upvote 0

sorex

Expert
Licensed User
Longtime User
problem with paths is that you'll need a lot of references to match a circle/bend/curve and then it's still not perfect I think.

traditional floodfill is extremely slow, takes 2-3 seconds on a larger area on my 1024x800 tablet.

I wrote an optimized method that fills instant and pixel perfect tho, but I can't reveal how yet as it was written for someone who might pay for this for a simular app.
 
Upvote 0

Gonza8

Member
Licensed User
Longtime User
Thanks NFOBoy, I was try this method, but I have a problem because I want to load external images, and It's not possible with this method, I think the way is to do a pixel color replacement in the touched area but this is problem.

Sorex, what????
 
Upvote 0

NFOBoy

Active Member
Licensed User
Longtime User
Just so I follow correctly, you are loading images that are already colored in?

If so, are they solid color regions already? Or are they photos (where it is not a trivial color difference between regions, but between specific pixels)

For the case where it is a region, then I think getting the pixel color of that region, and then substituting it with the new desired color would be fairly easy code-wise, and could have some neat effects to take advantage of finding those pixels that match starting from the point of touch.

For example, pick out the pixel that was touched, and find it's color.. then check all pixels that touch it, and any that match, change to new color.. then update screen, if there are no matches, done, else recursively do the same thing for each pixel that matched the old color.

It isn't "instant" (far from it) but it might look neat as it populates the screen.

Or, when loading the pictures, could do an Edge detection algorithm, that creates a clip path around each color and stores that in a map, and then use that for updates to the picture.

If it's not regions, then.... oooooh, don't want to think about that right now :)

Ross
 
Upvote 0
Top