diff --git a/PIL/ImageDraw.py b/PIL/ImageDraw.py index 71e29ee48..7556e5ece 100644 --- a/PIL/ImageDraw.py +++ b/PIL/ImageDraw.py @@ -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,6 +326,10 @@ 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- + homogenous, but similar, colors. """ # based on an implementation by Eric S. Raymond pixel = image.load() @@ -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 distance formula to calculate difference between two rgb values. + """ + return ((rgb1[0]-rgb2[0])**2 + (rgb1[1]-rgb2[1])**2 + (rgb1[2]-rgb2[2])**2)**.5 diff --git a/Tests/test_imagedraw.py b/Tests/test_imagedraw.py index 2ca5d0882..a3f783322 100644 --- a/Tests/test_imagedraw.py +++ b/Tests/test_imagedraw.py @@ -400,6 +400,28 @@ class TestImageDraw(PillowTestCase): self.assert_image_equal( im, Image.open("Tests/images/imagedraw_floodfill2.png")) + + @unittest.skipIf(hasattr(sys, 'pypy_version_info'), + "Causes fatal RPython error on PyPy") + def test_floodfill_thresh(self): + # floodfill() is experimental + + # Arrange + im = Image.new("RGB", (W, H)) + draw = ImageDraw.Draw(im) + draw.rectangle(BBOX2, outline="yellow", fill="green") + centre_point = (int(W/2), int(H/2)) + + # Act + ImageDraw.floodfill( + im, centre_point, ImageColor.getrgb("red"), + thresh=100) + 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,