python-pillow / Pillow

Python Imaging Library (Fork)
https://python-pillow.org
Other
11.77k stars 2.12k forks source link

Image CMS modes #8007

Open Yay295 opened 3 weeks ago

Yay295 commented 3 weeks ago

When the C code checks the given input and output modes it checks against this list: RGB, RGBA, RGBX, RGBA;16B, CMYK, L, L;16, L;16B, YCCA, YCC, and LAB.

https://github.com/python-pillow/Pillow/blob/e63ae380f1fae30dc8e078f6d588949387e45cbe/src/_imagingcms.c#L214-L244

However, only RGB, RGBA, RGBX, CMYK, L, and LAB are actual imaging modes. RGBA;16B, L;16, and L;16B are rawmodes, YCCA partially exists as a rawmode named YCCA;P, and YCC is a mode but is named YCbCr. That last one is easy enough to fix by just using the correct name, but it doesn't seem like it's possible to use the other four.

radarhere commented 3 weeks ago

it doesn't seem like it's possible to use the other four.

The following code will reach one of those lines.

from PIL import ImageCms
source_profile = ImageCms.createProfile("sRGB")
destination_profile = ImageCms.createProfile("sRGB")
ImageCms.buildTransform(source_profile, destination_profile, "RGB", "YCC")

But it will raise an error afterwards.

I'm guessing you meant reach those lines without error?

Yay295 commented 3 weeks ago

You can't use the ImageCmsTransform that creates because YCC isn't a valid image mode, so you can't create an image with that mode to apply the transform to.

radarhere commented 3 weeks ago

From a documentation perspective, https://pillow.readthedocs.io/en/stable/reference/ImageCms.html#PIL.ImageCms.buildTransform describes inMode and outMode as

String, as a valid PIL mode that the appropriate profile also supports (i.e. “RGB”, “RGBA”, “CMYK”, etc.)

Those are the modes that are passed to findLCMStype(), so I think there's an argument that these options are undocumented, and that YCCA shouldn't be renamed to YCCA;P.

However, from a practical perspective, the following code runs without an error.

from PIL import Image, ImageCms
for inMode in ("L;16", "L;16B"):
    source_profile = ImageCms.getOpenProfile("/Users/andrewmurray/pillow/Pillow/Tests/icc/sGrey-v2-nano.icc")
    destination_profile = ImageCms.createProfile("sRGB")
    transform = ImageCms.buildTransform(source_profile, destination_profile, inMode, "RGB")

    im = Image.new("RGB", (1, 1))
    ImageCms.applyTransform(im, transform)

source_profile = ImageCms.getOpenProfile("/Users/andrewmurray/pillow/Pillow/Tests/icc/sRGB_v4_ICC_preference.icc")
destination_profile = ImageCms.createProfile("sRGB")
transform = ImageCms.buildTransform(source_profile, destination_profile, "RGBA;16B", "RGB")

im = Image.new("RGB", (1, 1))
ImageCms.applyTransform(im, transform)
radarhere commented 2 weeks ago

Would updating the documentation be sufficient to resolve this?

radarhere commented 2 weeks ago

I've created https://github.com/python-pillow/Pillow/pull/8031 to resolve this by deprecating the unexpected modes, and adding replacements for some.