Repository: python-pillow/Pillow

Issue:
ImageDraw.floodfill raises TypeError for one-band images
### What did you do?
Invoke ImageDraw.floodfill for image with mode L
### What did you expect to happen?
success

### What actually happened?
Exception (see bellow)

### What are your OS, Python and Pillow versions?

* OS: Ubuntu 18.04.1 LTS
* Python: Python 2.7.15rc1
* Pillow: 

```python
from PIL import Image, ImageDraw
im = Image.new('L', (2,2), 0)
ImageDraw.floodfill(im, (0,0), 1)
```

```
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/site-packages/PIL/ImageDraw.py", line 346, in floodfill
    if _color_diff(value, background) <= thresh:
  File "/usr/lib64/python2.7/site-packages/PIL/ImageDraw.py", line 386, in _color_diff
    return abs(rgb1[0]-rgb2[0]) +  abs(rgb1[1]-rgb2[1]) +  abs(rgb1[2]-rgb2[2])
TypeError: 'int' object has no attribute '__getitem__'
```



Discussion:

Resolving patch:
diff --git a/src/PIL/ImageDraw.py b/src/PIL/ImageDraw.py
--- a/src/PIL/ImageDraw.py
+++ b/src/PIL/ImageDraw.py
@@ -430,8 +430,11 @@ def floodfill(image, xy, value, border=None, thresh=0):
         edge = new_edge
 
 
-def _color_diff(rgb1, rgb2):
+def _color_diff(color1, color2):
     """
-    Uses 1-norm distance to calculate difference between two rgb values.
+    Uses 1-norm distance to calculate difference between two values.
     """
-    return abs(rgb1[0]-rgb2[0]) + abs(rgb1[1]-rgb2[1]) + abs(rgb1[2]-rgb2[2])
+    if isinstance(color2, tuple):
+        return sum([abs(color1[i]-color2[i]) for i in range(0, len(color2))])
+    else:
+        return abs(color1-color2)


Test patch:
diff --git a/Tests/images/imagedraw_floodfill_L.png b/Tests/images/imagedraw_floodfill_L.png
new file mode 100644
Binary files /dev/null and b/Tests/images/imagedraw_floodfill_L.png differ
diff --git a/Tests/images/imagedraw_floodfill.png b/Tests/images/imagedraw_floodfill_RGB.png
similarity index 100%
rename from Tests/images/imagedraw_floodfill.png
rename to Tests/images/imagedraw_floodfill_RGB.png
diff --git a/Tests/images/imagedraw_floodfill_RGBA.png b/Tests/images/imagedraw_floodfill_RGBA.png
new file mode 100644
Binary files /dev/null and b/Tests/images/imagedraw_floodfill_RGBA.png differ
diff --git a/Tests/test_imagechops.py b/Tests/test_imagechops.py
--- a/Tests/test_imagechops.py
+++ b/Tests/test_imagechops.py
@@ -48,7 +48,7 @@ def test_sanity(self):
     def test_add(self):
         # Arrange
         im1 = Image.open("Tests/images/imagedraw_ellipse_RGB.png")
-        im2 = Image.open("Tests/images/imagedraw_floodfill.png")
+        im2 = Image.open("Tests/images/imagedraw_floodfill_RGB.png")
 
         # Act
         new = ImageChops.add(im1, im2)
@@ -60,7 +60,7 @@ def test_add(self):
     def test_add_scale_offset(self):
         # Arrange
         im1 = Image.open("Tests/images/imagedraw_ellipse_RGB.png")
-        im2 = Image.open("Tests/images/imagedraw_floodfill.png")
+        im2 = Image.open("Tests/images/imagedraw_floodfill_RGB.png")
 
         # Act
         new = ImageChops.add(im1, im2, scale=2.5, offset=100)
@@ -82,7 +82,7 @@ def test_add_clip(self):
     def test_add_modulo(self):
         # Arrange
         im1 = Image.open("Tests/images/imagedraw_ellipse_RGB.png")
-        im2 = Image.open("Tests/images/imagedraw_floodfill.png")
+        im2 = Image.open("Tests/images/imagedraw_floodfill_RGB.png")
 
         # Act
         new = ImageChops.add_modulo(im1, im2)
@@ -104,7 +104,7 @@ def test_add_modulo_no_clip(self):
     def test_blend(self):
         # Arrange
         im1 = Image.open("Tests/images/imagedraw_ellipse_RGB.png")
-        im2 = Image.open("Tests/images/imagedraw_floodfill.png")
+        im2 = Image.open("Tests/images/imagedraw_floodfill_RGB.png")
 
         # Act
         new = ImageChops.blend(im1, im2, 0.5)
@@ -181,7 +181,7 @@ def test_duplicate(self):
 
     def test_invert(self):
         # Arrange
-        im = Image.open("Tests/images/imagedraw_floodfill.png")
+        im = Image.open("Tests/images/imagedraw_floodfill_RGB.png")
 
         # Act
         new = ImageChops.invert(im)
@@ -228,7 +228,7 @@ def test_multiply_black(self):
 
     def test_multiply_green(self):
         # Arrange
-        im = Image.open("Tests/images/imagedraw_floodfill.png")
+        im = Image.open("Tests/images/imagedraw_floodfill_RGB.png")
         green = Image.new("RGB", im.size, "green")
 
         # Act
@@ -273,7 +273,7 @@ def test_offset(self):
     def test_screen(self):
         # Arrange
         im1 = Image.open("Tests/images/imagedraw_ellipse_RGB.png")
-        im2 = Image.open("Tests/images/imagedraw_floodfill.png")
+        im2 = Image.open("Tests/images/imagedraw_floodfill_RGB.png")
 
         # Act
         new = ImageChops.screen(im1, im2)
diff --git a/Tests/test_imagedraw.py b/Tests/test_imagedraw.py
--- a/Tests/test_imagedraw.py
+++ b/Tests/test_imagedraw.py
@@ -344,19 +344,26 @@ def test_big_rectangle(self):
         self.assert_image_similar(im, Image.open(expected), 1)
 
     def test_floodfill(self):
-        # 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))
         red = ImageColor.getrgb("red")
-        im_floodfill = Image.open("Tests/images/imagedraw_floodfill.png")
 
-        # Act
-        ImageDraw.floodfill(im, centre_point, red)
+        for mode, value in [
+            ("L", 1),
+            ("RGBA", (255, 0, 0, 0)),
+            ("RGB", red)
+        ]:
+            # Arrange
+            im = Image.new(mode, (W, H))
+            draw = ImageDraw.Draw(im)
+            draw.rectangle(BBOX2, outline="yellow", fill="green")
+            centre_point = (int(W/2), int(H/2))
 
-        # Assert
-        self.assert_image_equal(im, im_floodfill)
+            # Act
+            ImageDraw.floodfill(im, centre_point, value)
+
+            # Assert
+            expected = "Tests/images/imagedraw_floodfill_"+mode+".png"
+            im_floodfill = Image.open(expected)
+            self.assert_image_equal(im, im_floodfill)
 
         # Test that using the same colour does not change the image
         ImageDraw.floodfill(im, centre_point, red)