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
Cannot plot a line of width=1 without antialiased #6134
Comments
attn @mdboom |
Can you post an image of what you are talking about? Is this DPI or line position dependent? |
I am talking about pixel width (I don't know what is "line position dependent"). Using a backend such as wx or qt, when plotting the width of the line2D is independent of the zoom factor, but when you capture the screen (or save the picture), the width of the lines in pixel is not the one specified by linewidth (lw). It can be seen on the image below where I superimposed 3 zooms on the horizontal part of the plot with respectively lw=1,5,6. The grid represents the pixels. Therefore I cannot have thin lines & import figures by capturing the screen window. Maybe I can do this by saving the image specifying a larger resolution but it is a pity? When saving the image using the "save icon", ie without specifying the DPI, the default png has the same issue with sometimes slightly different widths. OK my confusion is that lw is in points not in pixels. When using lw=0.01, the width in pixel on the screen is still 2, but when saving the width is 1. I did some more investigation to find the right lw to get w=1pixel on the screen: Maybe it is due to the fact that during your transformation from plot to pixel, the logical y=1 falls always exactly between 2 pixels and not in the center of a pixel? Thanks. |
Our non-antialised rendering doesn't get much testing or use. We do have a code path to ensure that linewidth is always at least 0.5 when antialiasing is off. https://github.com/matplotlib/matplotlib/blob/master/src/_backend_agg.h#L411 However, I don't think that's the issue, since disabling it does not fix the issue. In fact, you are right that the line is falling between two pixels and drawing in both. This is, unfortunately, just how non-antialiased rendering works. It's either in a pixel (or in this case 2) or not, and there's no gradation in between. As a workaround, you can turn on snapping, which will snap to pixel centers when the linewidth (in pixels) is odd, or snap to pixel boundaries when it is even. Then with a linewidth of 0.5 points, you can get a single pixel line.
I'm going to close this as "not a bug", but feel free to continue to comment if you have further questions. |
Thanks for this nice answer. PS: strangely when using lw<0.5, the horizontal segment may get back to 2 pixel width (e.g. lw=0.1). It is not easy to tune :-). What does “odd” mean for floats? PS: Actually I don’t care for antialiased; I just want a thin line with non-fading colors. The best I could get is with lw in [0.5;1] |
Is there any update in the issue? |
@ptr-br if you want to discuss linewidths etc, perhaps open a question at https://discourse.matplotlib.org |
A line has at least a width of size 2, I could not get down to 1.
Using v1.5.1 both with wx and qt backend.
When looking at the pixels, the horizontal segment is of width 2. Same with lw=1.0 & 0.1.
Using lw=5 makes a line of width 6.
Using lw=6 makes a line of width 8.
Regards
The text was updated successfully, but these errors were encountered: