[Image-SIG] Here's a better flood-fill technique
Bob Klimek
klimek at grc.nasa.gov
Tue Sep 20 20:58:03 CEST 2005
The code is a direct implementation of the pseudo-code in Graphics Gems
1. Nothing more, nothing less. I suppose that I could have gone to the
next step and made it more "pythonic", but... it works! Personally I
would love to see a better and faster version of flood-fill function in PIL.
Bob
Eric S. Raymond wrote:
>On 25 June 2005 William Baxter posted a request for a flood-fill
>algorithm in Python, The following day Bob Klimek posted an effective
>but extremely complex implementation to this list.
>
>At the time I was not interested in this problem. In the last few
>days I have become so. I'm translating some old C graphics code of
>mine into Python, and my naive recursive flood-fill blew the
>interpreter stack.
>
>I found Mr. Klimek's answer while Googling for a Python flood-fill. I
>looked at the code, went "Bletch! This is complicated! I don't want
>to maintain this!" and decided to invent a simpler way.
>
>With all due respect to Mr. Klimek, he wasn't thinking like a Python
>programmer. The right thing to do is exploit Python's list-handling.
>Here is the code:
>
>def __flood_fill(image, x, y, value):
> "Flood fill on a region of non-BORDER_COLOR pixels."
> if not image.within(x, y) or image.get_pixel(x, y) == BORDER_COLOR:
> return
> edge = [(x, y)]
> image.set_pixel(x, y, value)
> while edge:
> newedge = []
> for (x, y) in edge:
> for (s, t) in ((x+1, y), (x-1, y), (x, y+1), (x, y-1)):
> if image.within(s, t) and \
> image.get_pixel(s, t) not in (BORDER_COLOR, value):
> image.set_pixel(s, t, value)
> newedge.append((s, t))
> edge = newedge
>
>At each step there is a list of edge pixels for the flood-filled
>region. You check every pixel adjacent to the edge; for each, if it is
>eligible to be colored, you color it and add it to a new edge list.
>Then you replace the old edge list with the new one. Stop when the
>list is empty.
>
>(The methods have slightly different names than in PIL because I'm
>using a thin wrapper class around Image. Translation is trivial.)
>
>This is nonrecursive and the storage requirement is bounded by the
>number of pixels in the region perimeter. Each pixel will be accessed
>at most three times and set just once. It's simple and efficient.
>Even, dare I say it, elegant.
>
>The lesson: when writing Python, don't forget that you have dynamic
>data types!
>
>Frederik, say the word and I'll ship you a generalized version for PIL.
>
>
More information about the Image-SIG
mailing list