The idea of scanline flood fill is the following
- you are given the initial point (seed) (x, y)
- go left as far as possible until the pixel (x-1, y) is not to be filled or you get to x=0
- the x you reached will be the start of scanline; keep two flags "look for caverns above" and "look for caverns below", both initialized at true
- this is the begin of scanline loop. Check the pixel above (x, y-1) if it's to be filled and now considering the look-above flag and the pixel there are 4 cases:
- if "look above" is true and the pixel is to be filled then you found a "new cavern", store (x, y-1) in the "to-do-list" and mark "look above" as false
- if "look above" is false and the pixel is NOT to be filled then the current cavern is complete and you need to look for another one, so just mark "look_above" as true
- in other cases (look above is true and pixel is not to be filled or look above is false and pixel is to be filled) you just do nothing
- Repeat the same reasoning with the "look below" flag and the color of pixel (x, y+1)
- paint the pixel (x, y) and move to (x+1, y), repeating from (5) unless the pixel you move to is not going to be painted.
- if there is anything in the "to-do list" pick it out and go back at (1) using the coordinates you found in the to-do list as (x, y)
This is the version for a 4-connected flood fill. For an 8-connected fill you also need to check for caverns at (x-1, y-1) and (x-1, y+1) when starting the scanline and you need to check for caverns (x+1, y-1) and (x+1, y+1) at scanline end (if the corresponding flags are true).
When moving on the scanline what you want to do is adding the green points in the picture to your to-do list:
Note that the number of seeds will not be "minimal" (for example the first two "above seeds" in the example will end up in the same cavern and therefore only one of them is really needed). Still the amount of stack needed to store them will be normally much smaller than the amount needed for a pixel-by-pixel recursive approach.
Another possible approach to limit the amount of memory needed is using a frontier painting algorithm:
- You put the initial seed (x, y) in the
current_active
list and paint it
- Initialize a
next_active
list to empty
- for every pixel in the
current_active
list check for neighbors that need to be painted: when you find one paint it and add it to the next_active
list
- when you're done set
current_active
list to next_active
list and repeat from 2 unless the list was empty
You can see an example of the two algorithms in action in this video.