libjxl
libjxl copied to clipboard
jpegli creates too bright output from input HDR JXL
Describe the bug
cjpegli
creates too bright output from input HDR JXL.
To Reproduce
Sample image
- Found here: https://github.com/d2phap/ImageGlass/issues/1677#issuecomment-1819045271
- JXL file: https://github.com/gwy15/hdr/raw/main/IMG01623-HDR.jxl
Encoded with cjpegli from v0.9.1 ( https://github.com/libjxl/libjxl/releases/download/v0.9.1/jxl-x64-windows-static.zip ).
- With XYB:
".\libjxl-v0.9.1\cjpegli.exe" ".\cat.jxl" ".\cat_xyb.jpg" --quality=90 --xyb --chroma_subsampling=444
- Without XYB:
".\libjxl-v0.9.1\cjpegli.exe" ".\cat.jxl" ".\cat.jpg" --quality=90 --chroma_subsampling=444
Both results in a JPG image looking brighter / washed out vs. original JXL file, where the XYB variant looks the worst.
Screenshot from XnView MP v1.6.4 with ICC enabled (Settings -> General -> Color profile).
Screenshot from IrfanView v4.66 with ICC enabled (Options -> Properties/Settings -> Color management -> Enable color management).
Expected behavior
Colors and brightness should look the same on the output JPG file.
Environment
- Windows 11 23H2, 22631.3007
- x86_64
Something somewhere is not tonemapping properly. cjpegli
is decoding to pixels with an ICC profile: ColorSync color profile 4.4, type jxl, RGB/Lab-mntr device by jxl, 4344 bytes, 1-12-2019, 0xde06c4e002fc07e4 MD5 'RGB_D65_202_Per_PeQ'
and then attaching that same profile to the JPEG.
For what it's worth, the resulting jpeg does look correct with lcms2, so it's possible IrfanView is doing something incorrect with its color management.
The XYB jpeg is just incorrect in all accounts though.
As far as I can tell, the non-XYB JPEG is correct: the pixel statistics (per identify -v
) are similar to those of a PNG decoded from the JXL, and so is the ICC profile. It’s just that XnView and IrfanView, instead of noticing the cicp tag in the ICC profile (which, in all fairness, is a recent addition to ICCv4), use its fallback tone-mapping look-up table, which happens to result in different rendering than whatever it is that those viewers do for PQ-tagged JXL files.
The XYB JPEG seems to encode the result of clipping the image to the scaled version of XYB used in jpegli. (JXL’s XYB is unbounded.) We could scale XYB differently for such images, but even then, we wouldn’t be able to display them in HDR anyway (except by forgoing backward compatibility and mandating jpegli, but then one might as well use JPEG XL), because we currently depend on ICC to render XYB appropriately but also on a CICP tag signalling PQ (or HLG) to indicate that an image is HDR. We can’t do both at the same time.
I think the most we can do at the moment is:
-
when encoding to XYB JPEG, tone-map HDR images first;
-
improve our current HDR tone mapping, if it’s deemed unsatisfactory. The fallback tone-mapping LUT in the ICC profile of non-XYB JPEGs will have to be global tone mapping, but the preconversion to SDR when encoding to XYB JPEG need not have that restriction.
Arguments against doing 1 might include the fact that it could make the user fail to realise that the result is not HDR, and that they have more flexibility in creating the SDR version if they do it themselves.