libjxl / libjxl

JPEG XL image format reference implementation
BSD 3-Clause "New" or "Revised" License
2.64k stars 250 forks source link

cjxl not properly converting the ICC profiles of some JPGs or djxl not properly decoding the converted JXLs with ICC profile back to JPG #2550

Open Flavored-37860 opened 1 year ago

Flavored-37860 commented 1 year ago

I'm having issues with cjxl not properly converting the ICC profiles of some JPEGs or may be all the viewers are displaying it wrong. I don't know which one of the two is the case.

Here's how to reproduce: source image with ICC profile cjxl E:\Folder\EvltOejWQAYc1Tk.jpg E:\Folder\EvltOejWQAYc1Tk_80.jxl --lossless_jpeg=0 -q 80

result: https://github.com/libjxl/libjxl/assets/92237041/e15daf15-3dee-4407-b3a4-93cb893f4e4c Image viewer used to display = JPEGView

Display result with ImageGlass: 5mgsxxYvYr

Only nomacs is displaying the converted JXL properly which is weird because nomacs can't display JPG's ICC colors. zH40FxFDRT

Decoding the converted JXL back to JPG --pixels_to_jpeg destroys the colors

Source image with ICC profile before converting to JXL: OpnhtLYWDu

JXL decoded back to JPG: b134uBd7Cn

OS = Windows10

qbnu commented 1 year ago

Looks like this was introduced between libjxl 0.6.1 and 0.7.0 (zoom in, you can see what look like artifacts on his suit). The same input JXL file was used.

$ ./djxl --version
djxl v0.7.0 f95da13 [AVX2,SSE4,SSSE3,Unknown]
Copyright (c) the JPEG XL Project
$ ./djxl EvltOejWQAYc1Tk_80.jxl out.png

with-0.7.0

$ ./djxl --version
djxl v0.6.1 a205468 [AVX2,SSE4,Scalar]
Copyright (c) the JPEG XL Project
$ ./djxl EvltOejWQAYc1Tk_80.jxl out.png

with-0.6.1

jonsneyers commented 1 year ago

I don't think there's anything wrong with cjxl/djxl here, and it's just the viewers that are not properly doing color management. The original image does use the Adobe RGB (1998) colorspace.

qbnu commented 1 year ago

If I strip the ICC profiles I get these:
Original JPEG
JXL decoded with djxl 0.7.0
JXL decoded with djxl 0.6.1

sobrus commented 1 year ago

I'm encountering wrong AdobeRGB colors as well. The problem is that cjxl/djxl do not properly recognize AdobeRGB color space.

Example: When encoding Display P3 color space image to lossy JXL and back, we will get:

Display P3 --> XYB --> RGB_D65_DCI_Per_SRG

In this case, JXL properly recognized P3 color space and - when decoding from XYB - it reconstructed DCI-P3 color space with D65 white point and sRGB transfer function - effectively outputting Display P3 image back.

But in case of AdobeRGB image we'll get

AdobeRGB -> XYB -> RGB_D65_SRG_Rel_Lin

And this is plain wrong! AdobeRGB does NOT use linear transfer function (that's why images are too dark) and does NOT use sRGB color space primaries either.

The effect is that images, even when viewed properly using embedded ICC profile and color management, are visibly limited to sRGB color space gamut - any wide gamut aRGB information present, mainly saturated greens and cyans, is lost ON DECODE.

When manually decoded with extended color space and more similar transfer function (sRGB is almost gamma 2.2):

djxl test.jxl output.jpg --color_space=RGB_D65_202_Rel_SRG

(I'm using BT2020 as it seems to be the only color space currently available that covers all of the AdobeRGB colors)

The wide gamut colors are preserved (with CM) and image is not too dark (even without CM). But this is still not ideal, as

We should not rely on CM and color profile to correct invalid decoder output. I'd also like to point out that majority (all?) of digital cameras, even newest and greatest ones, only use either sRGB or AdobeRGB when shooting JPEG. So this is a big bummer if anyone needs to recompress wider gamut images with vardct. This also may prohibit JXL adoption in newer cameras or photography/printing industry as a whole. Thankfully, lossless image recompression preserves color space and icc profile just fine.

gitoss commented 1 year ago

Thankfully, lossless image recompression preserves color space and icc profile just fine.

Indeed - for me lossy is broken even using DisplayP3 (https://github.com/libjxl/libjxl/issues/2070), but png => lossless jxl => png reconstructs the correct icc profile.

gitoss commented 1 year ago

I don't think there's anything wrong with cjxl/djxl here, and it's just the viewers that are not properly doing color management. The original image does use the Adobe RGB (1998) colorspace.

There is something wrong (with djxl), and I cannot understand "unrelated to 1.0" tag. It probably should have a "djxl" tag instead of / in addition to "cjxl" though.

As demonstrated above and in https://github.com/libjxl/libjxl/issues/2070#issuecomment-1695711545 djxl not only fails to reconstruct the icc, but completely screws up - even though the cjxl endoded .jxl works.