mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-28 02:46:18 +03:00
feature improvement: improved performance of ImageDraw.floodfill with Python built-in set() datatype.
This commit is contained in:
parent
69918dcbef
commit
24388addb6
|
@ -325,22 +325,23 @@ def getdraw(im=None, hints=None):
|
||||||
|
|
||||||
def floodfill(image, xy, value, border=None, thresh=0):
|
def floodfill(image, xy, value, border=None, thresh=0):
|
||||||
"""
|
"""
|
||||||
(experimental) Fills a bounded region with a given color.
|
(experimental) Fills a bounded region with a given color.
|
||||||
|
|
||||||
:param image: Target image.
|
:param image: Target image.
|
||||||
:param xy: Seed position (a 2-item coordinate tuple). See
|
:param xy: Seed position (a 2-item coordinate tuple). See
|
||||||
:ref:`coordinate-system`.
|
:ref:`coordinate-system`.
|
||||||
:param value: Fill color.
|
:param value: Fill color.
|
||||||
:param border: Optional border value. If given, the region consists of
|
:param border: Optional border value. If given, the region consists of
|
||||||
pixels with a color different from the border color. If not given,
|
pixels with a color different from the border color. If not given,
|
||||||
the region consists of pixels having the same color as the seed
|
the region consists of pixels having the same color as the seed
|
||||||
pixel.
|
pixel.
|
||||||
:param thresh: Optional threshold value which specifies a maximum
|
:param thresh: Optional threshold value which specifies a maximum
|
||||||
tolerable difference of a pixel value from the 'background' in
|
tolerable difference of a pixel value from the 'background' in
|
||||||
order for it to be replaced. Useful for filling regions of non-
|
order for it to be replaced. Useful for filling regions of non-
|
||||||
homogeneous, but similar, colors.
|
homogeneous, but similar, colors.
|
||||||
"""
|
"""
|
||||||
# based on an implementation by Eric S. Raymond
|
# based on an implementation by Eric S. Raymond
|
||||||
|
# amended by yo1995 @20180806
|
||||||
pixel = image.load()
|
pixel = image.load()
|
||||||
x, y = xy
|
x, y = xy
|
||||||
try:
|
try:
|
||||||
|
@ -350,12 +351,15 @@ def floodfill(image, xy, value, border=None, thresh=0):
|
||||||
pixel[x, y] = value
|
pixel[x, y] = value
|
||||||
except (ValueError, IndexError):
|
except (ValueError, IndexError):
|
||||||
return # seed point outside image
|
return # seed point outside image
|
||||||
edge = [(x, y)]
|
edge = {(x, y)}
|
||||||
|
full_edge = set() # use a set to record each unique pixel processed
|
||||||
if border is None:
|
if border is None:
|
||||||
while edge:
|
while edge:
|
||||||
newedge = []
|
new_edge = set()
|
||||||
for (x, y) in edge:
|
for (x, y) in edge: # 4 adjacent method
|
||||||
for (s, t) in ((x+1, y), (x-1, y), (x, y+1), (x, y-1)):
|
for (s, t) in ((x+1, y), (x-1, y), (x, y+1), (x, y-1)):
|
||||||
|
if (s, t) in full_edge:
|
||||||
|
continue # if already processed, skip
|
||||||
try:
|
try:
|
||||||
p = pixel[s, t]
|
p = pixel[s, t]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
|
@ -363,13 +367,17 @@ def floodfill(image, xy, value, border=None, thresh=0):
|
||||||
else:
|
else:
|
||||||
if _color_diff(p, background) <= thresh:
|
if _color_diff(p, background) <= thresh:
|
||||||
pixel[s, t] = value
|
pixel[s, t] = value
|
||||||
newedge.append((s, t))
|
new_edge.add((s, t))
|
||||||
edge = newedge
|
full_edge.add((s, t))
|
||||||
|
full_edge = edge # do not record useless pixels to reduce memory consumption
|
||||||
|
edge = new_edge
|
||||||
else:
|
else:
|
||||||
while edge:
|
while edge:
|
||||||
newedge = []
|
new_edge = set()
|
||||||
for (x, y) in edge:
|
for (x, y) in edge:
|
||||||
for (s, t) in ((x+1, y), (x-1, y), (x, y+1), (x, y-1)):
|
for (s, t) in ((x+1, y), (x-1, y), (x, y+1), (x, y-1)):
|
||||||
|
if (s, t) in full_edge:
|
||||||
|
continue
|
||||||
try:
|
try:
|
||||||
p = pixel[s, t]
|
p = pixel[s, t]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
|
@ -377,7 +385,9 @@ def floodfill(image, xy, value, border=None, thresh=0):
|
||||||
else:
|
else:
|
||||||
if p != value and p != border:
|
if p != value and p != border:
|
||||||
pixel[s, t] = value
|
pixel[s, t] = value
|
||||||
newedge.append((s, t))
|
new_edge.add((s, t))
|
||||||
|
full_edge.add((s, t))
|
||||||
|
full_edge = edge
|
||||||
edge = newedge
|
edge = newedge
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user