Pillow icon indicating copy to clipboard operation
Pillow copied to clipboard

It seemed that the box of Draw.rectangle contained the end xy point

Open Morriaty-The-Murderer opened this issue 9 years ago • 4 comments

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

Morriaty-The-Murderer avatar Jan 17 '16 14:01 Morriaty-The-Murderer

Hi. While there is not a solution at present, you will be able to find some discussion about this problem in #367

radarhere avatar Mar 17 '16 09:03 radarhere

Can we call this a duplicate of #367?

aclark4life avatar Jan 07 '17 23:01 aclark4life

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()

out

matkoniecz avatar Mar 23 '19 11:03 matkoniecz

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.

gofr avatar Sep 10 '20 17:09 gofr

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?

d0sboots avatar Sep 29 '22 02:09 d0sboots

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

d0sboots avatar Sep 29 '22 02:09 d0sboots