Repository navigation
ImageDraw.polygon produces the wrong image #8616
Description
Activity
I've created #8620 to resolve this. With it, Pillow creates this image.
I think the bug fix might have created new issues. Take a look at this example:
from PIL import Image, ImageDraw import matplotlib.pyplot as plt pts = [(183.5, 158.0), (184.0, 157.5), (185.0, 157.5), (186.0, 156.5), (189.0, 156.5), (190.00000390625002, 155.5), (192.0, 155.5), (192.99999609374998, 154.5), (195.0, 154.5), (196.0, 153.5), (196.99999609374998, 153.5), (198.00000390625002, 152.5), (199.0, 152.5), (200.0, 151.5), (200.99999609374998, 151.5), (202.00000390625002, 150.5), (203.0, 150.5), (204.99999609374998, 148.5), (206.00000390625002, 148.5), (207.5, 147.0), (207.5, 146.0), (208.49999609374998, 145.0), (208.49999609374998, 144.0), (209.49999609374998, 143.0), (209.49999609374998, 142.0), (210.50000390625002, 141.0), (210.50000390625002, 140.0), (211.5, 139.0), (211.5, 138.0), (211.0, 137.5), (207.0, 141.5), (206.00000390625002, 141.5), (205.50000390625002, 142.0), (205.50000390625002, 143.0), (204.49999609374998, 144.0), (204.49999609374998, 145.0), (202.00000390625002, 147.5), (201.49999609374998, 147.0), (201.49999609374998, 146.0), (202.50000390625002, 145.0), (202.00000390625002, 144.5), (200.99999609374998, 144.5), (200.49999609374998, 144.0), (200.49999609374998, 143.0), (200.0, 142.5), (199.0, 142.5), (198.50000390625002, 142.0), (198.50000390625002, 141.0), (202.50000390625002, 137.0), (202.50000390625002, 136.0), (203.5, 135.0), (203.5, 133.0), (204.99999609374998, 131.5), (206.00000390625002, 131.5), (207.0, 130.5), (208.0, 130.5), (208.99999609374998, 129.5), (211.0, 129.5), (212.0, 128.5), (218.00000390625002, 128.5), (218.50000390625002, 129.0), (218.50000390625002, 130.0), (213.50000390625002, 135.0), (214.00000390625002, 135.5), (215.0, 134.5), (216.0, 134.5), (216.99999609374998, 133.5), (218.00000390625002, 133.5), (219.0, 132.5), (220.0, 132.5), (220.99999609374998, 131.5), (222.00000390625002, 131.5), (223.000001953125, 130.5), (223.999998046875, 130.5), (226.00000390625002, 128.5), (227.000001953125, 128.5), (227.999998046875, 127.5), (232.99999609374998, 127.5), (234.00000390625002, 126.5), (235.000001953125, 126.5), (237.500005859375, 124.0), (235.999998046875, 122.5), (235.000001953125, 122.5), (234.500001953125, 123.0), (234.500001953125, 124.0), (232.99999609374998, 125.5), (230.00000390625002, 125.5), (229.500005859375, 125.0), (232.499998046875, 122.0), (231.999998046875, 121.5), (230.00000390625002, 121.5), (228.99999609374998, 122.5), (224.99999609374998, 122.5), (223.999998046875, 123.5), (220.99999609374998, 123.5), (220.0, 124.5), (216.99999609374998, 124.5), (216.0, 125.5), (212.99999609374998, 125.5), (212.0, 126.5), (208.99999609374998, 126.5), (208.0, 127.5), (206.00000390625002, 127.5), (204.99999609374998, 128.5), (203.0, 128.5), (202.00000390625002, 129.5), (200.99999609374998, 129.5), (190.00000390625002, 140.5), (189.0, 140.5), (187.0, 142.5), (186.0, 142.5), (185.0, 143.5), (184.0, 143.5), (182.0, 145.5), (181.0, 145.5), (178.0, 148.5), (177.0, 148.5), (172.5, 153.0), (173.0, 153.5), (174.0, 152.5), (175.0, 152.5), (176.0, 151.5), (177.0, 151.5), (177.4999921875, 152.0), (177.4999921875, 154.0), (179.0, 155.5), (181.0, 155.5), (182.5, 154.0), (182.5, 151.0), (181.5000078125, 150.0), (181.5000078125, 149.0), (182.0, 148.5), (183.0, 149.5), (184.0, 149.5), (186.0, 151.5), (188.0, 151.5), (188.5, 151.0), (188.5, 150.0), (187.5, 149.0), (187.5, 147.0), (185.4999921875, 145.0), (186.0, 144.5), (188.0, 144.5), (188.5, 145.0), (188.5, 146.0), (189.0, 146.5), (192.0, 146.5), (194.00000390625002, 144.5), (195.0, 144.5), (197.50000390625002, 147.0), (194.00000390625002, 150.5), (192.99999609374998, 150.5), (191.5, 152.0), (191.5, 153.0), (191.0, 153.5), (189.0, 153.5), (188.0, 154.5), (187.0, 154.5), (185.0, 156.5), (181.0, 156.5), (180.0, 157.5), (179.0, 157.5), (178.5, 158.0), (179.0, 158.5), (183.0, 158.5)] pts = [(round(x), round(y)) for x, y in pts] shape = (max([x for x, y in pts]) + 1, max([y for x, y in pts]) + 1) img = Image.new("L", shape, 0) draw = ImageDraw.Draw(img) draw.polygon(pts, fill=255) img.save('polygon.png') x, y = zip(*pts) plt.figure(figsize=shape) plt.plot(x, y, marker='o', linestyle='-', color='blue', markersize=5, label='Points and Lines') plt.scatter(x, y, color='red', zorder=5, label='Points') plt.title("Visualization of Points with Connections") plt.xlabel("X-axis") plt.ylabel("Y-axis") plt.grid(True) plt.legend() plt.savefig('points.png')`
There is a strip of pixels added to the mask which should not be there
Yet another example for debugging:
from PIL import Image, ImageDraw import matplotlib.pyplot as plt pts = [(154.5, 189.0), (155.0, 188.5), (157.0, 188.5), (158.0, 187.5), (159.0, 187.5), (159.5, 187.0), (159.5, 186.0), (160.5, 185.0), (160.5, 182.0), (161.0, 181.5), (169.0, 181.5), (170.0, 182.5), (172.0, 180.5), (184.0, 180.5), (185.0, 179.5), (187.0, 179.5), (188.0, 178.5), (192.0, 178.5), (192.99999609374998, 177.5), (203.0, 177.5), (204.0, 176.5), (212.0, 176.5), (212.99999609374998, 177.5), (214.00000390625002, 177.5), (218.50000390625002, 182.0), (218.50000390625002, 183.0), (219.5, 184.0), (219.5, 185.0), (220.0, 185.5), (220.99999609374998, 185.5), (222.00000390625002, 184.5), (223.000001953125, 184.5), (223.999998046875, 183.5), (224.99999609374998, 183.5), (226.00000390625002, 182.5), (227.999998046875, 182.5), (228.99999609374998, 183.5), (231.000001953125, 183.5), (232.99999609374998, 181.5), (234.00000390625002, 181.5), (235.5, 180.0), (235.5, 178.0), (236.499998046875, 177.0), (236.499998046875, 176.0), (238.500001953125, 174.0), (238.500001953125, 173.0), (239.5, 172.0), (239.5, 168.0), (238.500001953125, 167.0), (238.500001953125, 165.0), (237.500005859375, 164.0), (237.500005859375, 163.0), (236.99999609374998, 162.5), (235.999998046875, 162.5), (235.000001953125, 161.5), (234.00000390625002, 161.5), (233.499994140625, 161.0), (233.499994140625, 160.0), (232.99999609374998, 159.5), (222.00000390625002, 159.5), (220.99999609374998, 158.5), (220.0, 158.5), (219.0, 157.5), (216.99999609374998, 157.5), (216.0, 156.5), (211.0, 156.5), (210.00000390625002, 155.5), (208.0, 155.5), (207.0, 154.5), (190.00000390625002, 154.5), (189.0, 155.5), (184.0, 155.5), (183.0, 156.5), (181.0, 156.5), (180.0, 157.5), (178.0, 157.5), (176.0, 159.5), (175.0, 159.5), (173.0, 161.5), (172.0, 161.5), (171.0, 162.5), (170.0, 162.5), (168.0, 164.5), (166.0, 164.5), (165.0, 165.5), (162.0, 165.5), (161.0, 166.5), (159.5, 165.0), (159.5, 164.0), (157.0, 161.5), (155.0, 161.5), (154.0, 160.5), (152.0, 160.5), (151.0, 161.5), (149.0, 161.5), (147.5, 163.0), (147.5, 166.0), (140.5, 173.0), (140.5, 175.0), (141.0, 175.5), (143.0, 175.5), (144.0, 174.5), (145.0, 174.5), (149.0, 170.5), (155.0, 170.5), (156.0, 169.5), (160.0, 169.5), (161.0, 170.5), (162.0, 169.5), (167.0, 169.5), (168.0, 168.5), (175.0, 168.5), (176.0, 167.5), (180.0, 167.5), (181.0, 166.5), (182.0, 166.5), (183.0, 167.5), (188.0, 167.5), (190.00000390625002, 169.5), (191.0, 169.5), (192.99999609374998, 167.5), (196.0, 167.5), (196.99999609374998, 168.5), (200.99999609374998, 168.5), (202.00000390625002, 169.5), (204.0, 169.5), (204.99999609374998, 170.5), (207.0, 170.5), (208.0, 171.5), (211.0, 171.5), (212.49999609374998, 173.0), (212.0, 173.5), (207.0, 173.5), (206.00000390625002, 174.5), (203.0, 174.5), (202.00000390625002, 175.5), (195.0, 175.5), (194.00000390625002, 176.5), (188.0, 176.5), (187.0, 175.5), (186.0, 175.5), (185.0, 174.5), (184.0, 174.5), (183.0, 175.5), (182.0, 175.5), (181.0, 176.5), (177.0, 176.5), (176.0, 175.5), (175.0, 175.5), (174.0, 174.5), (171.0, 174.5), (170.0, 175.5), (169.0, 174.5), (166.0, 174.5), (165.0, 173.5), (160.0, 173.5), (159.0, 174.5), (158.0, 174.5), (157.0, 175.5), (155.0, 175.5), (152.0, 178.5), (150.0, 178.5), (149.0, 177.5), (142.0, 177.5), (140.5, 179.0), (140.5, 180.0), (146.5, 186.0), (146.5, 187.0), (149.0, 189.5), (154.0, 189.5)] pts = [(round(x), round(y)) for x, y in pts] shape = (max([x for x, y in pts]) + 1, max([y for x, y in pts]) + 1) img = Image.new("L", shape, 0) draw = ImageDraw.Draw(img) draw.polygon(pts, fill=255) img.save('polygon.png') x, y = zip(*pts) plt.figure(figsize=shape) plt.plot(x, y, marker='o', linestyle='-', color='blue', markersize=5, label='Points and Lines') plt.scatter(x, y, color='red', zorder=5, label='Points') plt.title("Visualization of Points with Connections") plt.xlabel("X-axis") plt.ylabel("Y-axis") plt.grid(True) plt.legend() plt.savefig('points.png')
I was able to produce these issues by running
pip install git+https://github.com/python-pillow/Pillow
in my virtual environment after the recent merge to master.I've created #8659.
As far as I can see, it resolves your issues. However, I imagine you have more examples apart from the three you've shared here, so I'm thinking of leaving it as draft until you give it your sign off. Would you be able to test the PR and let us know if it works?
With the recent changes in #8659, all my tests are passing. Thank you!





What did you do?
Drew a polygon with PIL's Image and ImageDraw modules
What did you expect to happen?
The Polygon should look consistent without holes in the middle
What actually happened?
There are holes and gaps.
What are your OS, Python and Pillow versions?
Code to reproduce the issue along with the images: