Pillow
Pillow copied to clipboard
It seemed that the box of Draw.rectangle contained the end xy point
I learned this from doc:
xy – Four points to define the bounding box. Sequence of either [(x0, y0), (x1, y1)] or [x0, y0, x1, y1]. The second point is just outside the drawn rectangle.
Then I ran this script
from PIL import Image, ImageDraw
bb=Image.new('RGB',(4,4),(255,255,255))
dr=ImageDraw.Draw(bb)
box=(0,0,2,2)
dr.rectangle(box, fill=(125,45,55))
for i in range(4):
for j in range(4):
print(i,j,bb.getpixel((i,j)))
cc=bb.crop(box)
print(bb.getcolors())
print(cc.getcolors())
The output was
0 0 (125, 45, 55)
0 1 (125, 45, 55)
0 2 (125, 45, 55)
0 3 (255, 255, 255)
1 0 (125, 45, 55)
1 1 (125, 45, 55)
1 2 (125, 45, 55)
1 3 (255, 255, 255)
2 0 (125, 45, 55)
2 1 (125, 45, 55)
2 2 (125, 45, 55)
2 3 (255, 255, 255)
3 0 (255, 255, 255)
3 1 (255, 255, 255)
3 2 (255, 255, 255)
3 3 (255, 255, 255)
[(7, (255, 255, 255)), (9, (125, 45, 55))]
[(4, (125, 45, 55))]
It drew 9 points, while I just wanted the first 4 points to be filled
Hi. While there is not a solution at present, you will be able to find some discussion about this problem in #367
Can we call this a duplicate of #367?
example - there is no need to count pixels, just note that black line appeared + show function.
from PIL import Image, ImageDraw
im = Image.new("RGB", (300, 30), "#fff")
d = ImageDraw.Draw(im)
d.rectangle((10, 10, 290, 10), "#000")
im.save("out.png")
im.show()

I understand this is a bit of a complicated issue (given #367), but is that bug really safe to fix? I know I've written code that would break if rectangle changed to match the documentation now. What are your views on backwards-compatibility? Not sure how serious to treat a change like this. There are clearly advantages to fixing the inconsistencies too.
But I'd like to fix the documentation separately from #367. After all, isn't documentation supposed to describe how software actually works, not how we wish it worked after we fixed all the bugs?
Would anyone mind a change like this?
Four points to define the bounding box. Sequence of either [(x0, y0), (x1, y1)] or [x0, y0, x1, y1]. The second point is the bottom-right corner of the drawn rectangle. Note that this is different from the usual Coordinate System used by e.g. Image.getbbox(). See issue #367.
With a bunch of links added.
I just got bitten by this.
I don't think the behavior of draw.rectangle can be changed at this point; too much code surely depends on it working the way it currently does. So can we at least fix the docs so they aren't lying?
Would anyone mind a change like this?
Four points to define the bounding box. Sequence of either [(x0, y0), (x1, y1)] or [x0, y0, x1, y1]. The second point is the bottom-right corner of the drawn rectangle. Note that this is different from the usual Coordinate System used by e.g. Image.getbbox(). See issue #367.
With a bunch of links added.
I don't think the rectangle docs actually have much to do with #387. If you look at the code, you can see it's a very explicit choice (for whatever reason) to include the final y coordinate in the loop, and including the final x coordinate is a result of the code plus the way hline works, which is surely set in stone. All of this is specific to ImagingDrawRectangle (and thus draw_rectangle and friends in Python) - it doesn't have to do with other issues.
https://github.com/python-pillow/Pillow/blob/aa8877ac5bb7c33939c4503ef56240e7027ac8ad/src/libImaging/Draw.c#L759