Added threshold parameter to ImageDraw.floodfill (#2599)

* added thresh option and test

* fixed up, test works and passes

* Update test_imagedraw.py

* Update test_imagedraw.py

* Update ImageDraw.py

* removed pypy skip decorator from thresh test

* Update ImageDraw.py
This commit is contained in:
nediamond 2017-07-01 05:37:02 -04:00 committed by wiredfool
parent 919150277e
commit d1b66e9dfd
2 changed files with 34 additions and 3 deletions

View File

@ -315,7 +315,7 @@ def getdraw(im=None, hints=None):
return im, handler
def floodfill(image, xy, value, border=None):
def floodfill(image, xy, value, border=None, thresh=0):
"""
(experimental) Fills a bounded region with a given color.
@ -326,13 +326,17 @@ def floodfill(image, xy, value, border=None):
pixels with a color different from the border color. If not given,
the region consists of pixels having the same color as the seed
pixel.
:param thresh: Optional threshold value which specifies a maximum
tolerable difference of a pixel value from the 'background' in
order for it to be replaced. Useful for filling regions of non-
homogeneous, but similar, colors.
"""
# based on an implementation by Eric S. Raymond
pixel = image.load()
x, y = xy
try:
background = pixel[x, y]
if background == value:
if _color_diff(value, background) <= thresh:
return # seed point already has fill color
pixel[x, y] = value
except (ValueError, IndexError):
@ -348,7 +352,7 @@ def floodfill(image, xy, value, border=None):
except IndexError:
pass
else:
if p == background:
if _color_diff(p, background) <= thresh:
pixel[s, t] = value
newedge.append((s, t))
edge = newedge
@ -366,3 +370,10 @@ def floodfill(image, xy, value, border=None):
pixel[s, t] = value
newedge.append((s, t))
edge = newedge
def _color_diff(rgb1, rgb2):
"""
Uses 1-norm distance to calculate difference between two rgb values.
"""
return abs(rgb1[0]-rgb2[0]) + abs(rgb1[1]-rgb2[1]) + abs(rgb1[2]-rgb2[2])

View File

@ -400,6 +400,26 @@ class TestImageDraw(PillowTestCase):
self.assert_image_equal(
im, Image.open("Tests/images/imagedraw_floodfill2.png"))
def test_floodfill_thresh(self):
# floodfill() is experimental
# Arrange
im = Image.new("RGB", (W, H))
draw = ImageDraw.Draw(im)
draw.rectangle(BBOX2, outline="darkgreen", fill="green")
centre_point = (int(W/2), int(H/2))
# Act
ImageDraw.floodfill(
im, centre_point, ImageColor.getrgb("red"),
thresh=30)
del draw
# Assert
self.assert_image_equal(
im, Image.open("Tests/images/imagedraw_floodfill2.png"))
def create_base_image_draw(self, size,
mode=DEFAULT_MODE,
background1=WHITE,