Skip to content
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

Line anti-aliasing issues due to missing sRGB mishandling #65

Open
baryluk opened this issue Jan 6, 2020 · 5 comments
Open

Line anti-aliasing issues due to missing sRGB mishandling #65

baryluk opened this issue Jan 6, 2020 · 5 comments

Comments

@baryluk
Copy link

baryluk commented Jan 6, 2020

Hi,

I just started using aggdraw, and it definitively draws nicer lines than PIL for my application (opacity and antialiassing does help), but I noticed still imperfection and possibly a bug:

dump

Be sure to open it and view at 100% scale.

The issue is visible as uneven luminosity of the lines. I.e. if you look at the top center, and then count 3 or 4 lines to the right, it looks to be oscillating in brightness.

I am not talking about a Moiré pattern that appears in the center, that is somehow expected, but possibly is related partially. I am talking about straight slightly diagonal lines far from the center.

It feels like maybe the sRGB is not used correctly? Which is a bit strange, as I see there is support for gamma, linear and sRGB in the aggdraw.

# Python 3.8.1
from PIL import Image, ImageDraw  # Pillow 6.2.1
import aggdraw  # Version 1.3.11
w, h = 1024, 1024
img = Image.new("RGB", (w, h))
img1 = aggdraw.Draw(img)
img1.setantialias(True)
pen = aggdraw.Pen("white", 1.0, opacity=127)

img1.line(xyxyxy, pen)
# ...

img1.flush()
img.save("dump.png")
img.show()

With opacity=255 effect is visible even more:

dump

dump

When drawing a similar type of lines (width and angle) for example in Inkscape, I see much more uniform luminance and the oscillations are there, but essentially invisible.

@baryluk
Copy link
Author

baryluk commented Jan 6, 2020

Update: Yes, it looks like sRGB issue, either with PIL, with aggdraw, or with the PNG writer in PIL.

I added this piece of code at the end:

from PIL.ImageCms import buildTransform, applyTransform
# SRGB_PROFILE = 'sRGB.icc'
SRGB_PROFILE = '/usr/share/color/icc/sRGB.icc'
LINEARIZED_PROFILE = 'linearized-sRGB.icc'
LINEARIZED_TO_SRGB = buildTransform(LINEARIZED_PROFILE, SRGB_PROFILE, 'RGB', 'RGB')
img = applyTransform(img, LINEARIZED_TO_SRGB)
img.save("dump2.png")

The color profile icc file I got from: python-pillow/Pillow#1604 (comment) based on this post: https://stackoverflow.com/questions/31300865/srgb-aware-image-resize-in-pillow/46613620#46613620

And the result looks much better:

dump2

@baryluk baryluk changed the title Minor issues with antialiassing Minor issues with anti-aliasing due missing sRGB handling Jan 6, 2020
@baryluk baryluk changed the title Minor issues with anti-aliasing due missing sRGB handling Line anti-aliasing issues due to missing sRGB mishandling Jan 6, 2020
@djhoese
Copy link
Member

djhoese commented Jan 6, 2020

Wow, nice examples. Thanks for reporting this.

Could you do a couple things for me?

  1. Could you make a simple example script that includes all the data (x/y locations) needs to reproduce an image that shows this problem? That way I can test it locally.

  2. Could you try this with installing from the current aggdraw master branch? You should be able to do pip install git+https://github.com/pytroll/aggdraw.git. Note that there are other issues we've discovered in the master branch that are being talked about in other issues/PRs so results may not be perfect.

I'm not sure there is much aggdraw, the python package, can do to resolve this unless it is specifically a bug of aggdraw improperly passing things between python and C. Aggdraw depends almost entirely on the antigrain (agg) C library. We keep a copy of it alongside aggdraw in this repository, but it is coming from another group. The reason I asked about you using the master branch is that we are working on switching to agg 2.4 (I think that's the version, can't remember offhand) which had a lot of changes done from the previous versions we used.

If the master branch gives you "better" results then this must be an agg C problem. If not, then it could still be an agg problem or a PIL problem as you've deduced already.

@baryluk
Copy link
Author

baryluk commented Jan 9, 2020

A full script to reproduce the issue in the attachment:

agg-lines-issue.tar.gz

@djhoese
Copy link
Member

djhoese commented Jan 9, 2020

I'm pretty swamped this month, but might have time to look at this this weekend. @baryluk Did you have time to try the master branch and compare it?

Edit: And of course, thank you for putting together this example code and images.

@baryluk
Copy link
Author

baryluk commented Jan 9, 2020

Tested the master branch at commit 6c1cf87 , and confirmed the code is using the locally compiled version.

Same results.

It looks the issue is that the PIL doesn't really understand color spaces, nor the image metadata carry this information. If the PIL supported 16-bit per channel, or multi channel f32 formats, that would be less of an issue.

I did modify aggdraw.cxx line 407 , in the method draw_adaptor::setantialias I did this:

    void setantialias(bool flag)
    {
        if (flag) {
            // rasterizer.gamma(agg::gamma_power(1.0/2.4));
            rasterizer.gamma(&agg::linear_to_sRGB);
        } else
            rasterizer.gamma(agg::gamma_threshold(0.5));
    };

Instead of using rasterizer.gamma(agg::gamma_linear());, and this works and fixes the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants