-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Vertical lines drawn with draw.line have one extra width pixel #367
Comments
Ok, I've got this reproduced as a test case. Will dig a bit. |
Notes on what's going on: in Draw.c, about line 690 in ImagingDrawWideLine. The wide line is broken into a polygon with 4 corners, each corner an integral +-dx,dy from the actual endpoints. Since dx and dy are integers, a dx of 1 corresponding to a line width of 2 gives x points from x-1 to x+1, or 3 pixels wide. A line width of 3 gives dx=2, or 5 pixels. 4:2, 5:3 or 7px. I'm getting some inconsistent info out of the debugger on this one, though, the odd ones appear a pixel too high. The same thing applies for horizontal lines, but with a difference. The polygon draw function fills the lines by drawing horizontal lines, one y value at a time. So, horizontal and vertical endpoints are treated differently here. ymin==4, ymax==6, y ranges from ymin+0.5 to ymax-0.5, so the third horizontal line is never drawn. It has issues with 3px wide lines though, they wind up 4px wide. |
Last call for 2.3.0 |
Not happening for now. Pretty sure that this dates back to PIL code. It can probably be fixed, but it's more than a little off by one bug somewhere, it's going to take a bit of a rethink to get the line drawing code right. |
Now targeting 2.4.0 |
@wiredfool I'm trying to fix this bug but, as you said, the polygon functions seems to treat differently x and y axis, and to me this looks like the root of the problem. However I'm not sure of the implications of changing the behavior of the polygon functions due to the possible side-effects and I'm not familiar enough with the PIL code to evaluate it, what do you think about it? If I change the polygon behavior to treat consistently both axis, can it break other Pillow parts? |
I don't think that's a problem. I'd expect the line to include both endpoints. The pixels at 2 and 8 should be filled, and all those in between. So 8-2+1=7.
A horizontal line is a polygon with a height of only one pixel. If you squash the squares in your screenshots to one-pixel-high lines, this is the same line, from 2 to 8 inclusive. @wiredfool, @aclark4life, comments? |
Let's try getting to this for 2.5.0 due in 3 months |
(Correction: "Let's try getting to this for 2.5.0 due in 3 months") |
Thanks, fixed |
Sorry, I was planning making a pull request the past week but I've been busy, if nothing goes wrong I will send it in the next days after writing some basic polygon tests. BTW, I'd checked out the issue #463 and its problem have the same source, since the ellipses are generated as polygons with 360 edges, so probably it'll be fixed too. @hugovk for lines it makes sense, but for polygons like the square it makes more sense to me to be (in the example) 6 pixels width/height instead of 7; I'm leaving that behavior for consistency with the rest of the library but I'm not completely satisfied with the result. |
I still think 7 pixels is correct for polygons: if I draw a square from X=2 to X=8, and Y=2 to Y=8, I'd expect the top-left corner to include pixel (2,2) and the bottom-right corner to include pixel (8,8). |
You see, that's the problem: you think and I think :) |
Ok, I've uploaded the new version (without tests) to a new branch in my fork, just in case I don't have time to write the tests this week, so now you can test it, people :) https://github.com/Terseus/Pillow/tree/fix-367_bad-line-width Feedback will be very appreciated. |
@Terseus How about sending a pull request? |
Regarding which end-pixels to draw, we still need a definitive spec. For starters here's the Pillow documentation (largely inherited from PIL) for ImageDraw. Line:
So Therefore, following this,
Similarly,
|
@hugovk I found that most of the PIL docs are outdated as it doesn't always match the code, the Looking into another library sounds like a good idea but I'm not familiar with another draw API and, honestly, for me dig into this one has been enough for now :) |
😕 |
Targeting Future |
The PIL documentation explicitly asserts that the coordinate origin is at the top left corner (not the centre) of the top left pixel. (E.g. see http://pillow.readthedocs.org/en/3.0.x/handbook/concepts.html#coordinate-system) Thus a square 10 pixel by 10 pixel image canvas spans from (0,0) to (10,10) in coordinate space; (10,10) is the coordinate for the bottom-right corner of the last pixel. Therefore, in Terseus example, the polygon [(2,2), (2,8), (8,8), (8,2)] should be a square with sides of length 6 pixels. Not seven, because that would encroach (overlap) on the polygon [(8,8), (8,10), (10,10), (10,8)], which clearly does not overlap in coordinate space (and is already perfectly aligned with the edges of the pixels). Trying to "include endpoints" can't make consistent sense (since in geometry, it is arbitrary which side you call the start versus the end). |
This was changed with #6625 to say that "The bounding box is inclusive of both endpoints." |
When using the line method of a Draw object on a newly created image to draw vertical lines, all lines drawn with more than 1 pixel width are one pixel widther (a 2 pixels width line is drawn with a 3 pixels width).
How to reproduce the problem:
This "proof of concept" program reproduces the problem creating a 10x10 image with a centered cross of two lines 2 pixels width, one horizontal and one vertical, where the vertical one is clearly widther than the horizontal.
Expected result:
A cross of two lines, both with the same width, 2 pixels.
Current result:
A cross with the horizontal line 2 pixels width and the vertical line 3 pixels width.
Additional information:
This bug only happens when drawing vertical lines with at least two pixels width.
1 pixel width vertical lines and horizontal lines of any width doesn't seem to have this problem.
The text was updated successfully, but these errors were encountered: