wagtail / Willow

A wrapper that combines the functionality of multiple Python image libraries into one API
https://willow.wagtail.org/
BSD 3-Clause "New" or "Revised" License
273 stars 53 forks source link

Faulty color profile conversion #114

Closed andre-fuchs closed 9 months ago

andre-fuchs commented 1 year ago

Issue Summary

Photo files with an AdobeRGB color profile are not correctly converted. The result looks less saturated. The resulting images (JPG and WebP format) use a color profile, named "RGB". If I upload the source files with an "sRGB" profile, the results match.

Is there a setting to tell Pillow how to convert these color spaces/profiles? "Relative colorimetric" should be the way to go, I think. I would love to see a setting to configure this properly. "sRGB" could always be the color space for the converted images. But I would love to see more perceptually true results from other color spaces as well. Many users do not know about these technical details at all.

Many other websites seem to handle this better, like you can see on the right image in the screenshot. The difference seems to be more emphasized in Safari on Mac OS. But also in Firefox on Linux I was seeing the difference.

Technical details

Screenshot 2023-06-21 at 15 23 58

Left: Original JPG with AdobeRGB color profile Middle: Wagtail rendition Right: Rendition of contemporaryartdaily.com for comparison

andre-fuchs commented 1 year ago

Reading this issue on stackoverflow, it seems to be that Willow is using its default setting to convert to a generic "RGB" profile. Pillow can read and save icc_profiles, see code below.

original_img = PIL.open(image)
original_icc_profile = img.info.get("icc_profile")

# not sure how to convert this, maybe:
rendition_icc_profile = PIL.ImageCms.createProfile('sRGB')
rendition_img = PIL.ImageCms.profileToProfile(original_img, original_icc_profile, rendition_icc_profile)
rendition_img.save(d, "JPEG", icc_profile=rendition_icc_profile)
zerolab commented 1 year ago

@andre-fuchs thanks for filing this. I've transferred the issue to Willow, which is the library Wagtail uses for image manipulation.

63 is related and we need to restart work on it.

andre-fuchs commented 1 year ago

we need to restart work on it.

Please do! I would propose to not just keep the color profile, but to define a setting if images should be converted to a specific color profile or not. This could be a simple Boolean variable WAGTAILIMAGES_CONVERT_TO_SRGB, which is set to True by default. Other profiles than sRGB are not really relevant for websites to my knowledge.

andre-fuchs commented 11 months ago

Is there any progress on this? I could probably fix this myself if somebody points me to the piece of code that needs to be updated.

zerolab commented 11 months ago

@andre-fuchs alas, this slipped under the mountain of other things to look at. If you have the time, #63 is a good starting point. The PR needs adapting to the latest main branch (and supported versions), as well as checking feedback from kaedroho and others

andre-fuchs commented 10 months ago

ICC color profile and EXIF data implemented!

Following #63 by @stefanistrate, I implemented two methods to add the ICC color profile and the EXIF data that are applied in the save methods of the Pillow plugin. Here is my fork. I tested it manually with an instance of Wagtail v5.2. Color profile take-over does work as expected for JPEG, PNG, WebP and AVIF.

How do I get these tests running?

I did not manage to figure out how to run the unit tests. Could somebody walk me through, please. I just want to be able to test my code locally. With my manual test setup I created a few unnecessary/messy commits. But it seems to do the job finally. I would like to add more tests here and add another feature. But first, please help me to get these tests running.

You can try it yourself. Here are the requirements. Just make sure to remove the standard Willow package before installing via PIP.

wagtail==5.2
git+https://github.com/andre-fuchs/Willow.git@fix-color-management#egg=Willow

Here is a screenshot of my manual tests. sRGB.icc on the left and ECI_RGB_v2.icc on the right. All files generated by Wagtrail with ICC profiles included. Colors do look consistent now. (Photo from Wikipedia) Screenshot from 2023-11-02 15-41-08

zerolab commented 10 months ago

@andre-fuchs locally,

  1. create a virtual environment in the repo root
  2. activate it
  3. pip install -e ".[testing]"
  4. python runtests.py
andre-fuchs commented 10 months ago

Thanks! This was exactly what I needed. I will add more tests and try to wrap this up today.