libjxl / libjxl

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

jpegli output fails to be JPEG-recompressible using cjxl #2284

Closed Traneptora closed 11 months ago

Traneptora commented 1 year ago

Describe the bug A legacy JPEG file produced with benchmark_xl/jpegli should be recompressible with cjxl using standard JPEG transcoding. It fails.

To Reproduce

$ benchmark_xl --save_compressed --output_dir=. --codec=jpeg:enc-jpegli:xyb:d1 --input=lenna.png

followed by:

$ cjxl lenna.png.d1.xyb.enc-jpegli.jpeg lenna.jxl
JPEG XL encoder v0.9.0 13caf6f8 [AVX2]
Note: Implicit-default for JPEG is lossless-transcoding. To silence this message, set --lossless_jpeg=(1|0).
Read JPEG image with 54804 bytes.
Encoding [Container | JPEG, lossless transcode, effort: 7 | JPEG reconstruction data], 
./lib/jxl/enc_frame.cc:322: JXL_FAILURE: Chroma subsampling is not supported when color transform is not YCbCr
./lib/jxl/enc_frame.cc:1275: JXL_RETURN_IF_ERROR code=1: MakeFrameHeader(cparams, passes_enc_state->progressive_splitter, frame_info, ib, frame_header.get())
./lib/jxl/encode.cc:569: Failed to encode frame
JxlEncoderProcessOutput failed.
EncodeImageJXL() failed.

Expected behavior It should produce a recompressed legacy JPEG as a JXL file.

Environment

Additional context lenna png d1 xyb enc-jpegli

XYB jpeg attached.

mo271 commented 1 year ago

There are also are number of other, somewhat exotic jpegs, that currently can't be handled by the JPEG recompression: cmyk-images (or more generally anything other than 1 or 3 channels), 410 or 411 subsampled images for example.

jonsneyers commented 1 year ago

I don't think it's a good idea to change the standard (both 18181-1 and 18181-2) at this point to allow recompressing 'exotic' JPEGs (of which CMYK ones are probably the 'least exotic', but also the hardest to fit into the 3-component VarDCT bitstream).

We did put limitations on what kinds of JPEGs can be represented in JXL to hit a good trade-off: we did not want to complicate the jxl spec too much, especially the core codestream, while we did want to be able to recompress most JPEGs "found in the wild". For example, 4:2:0 and 4:4:4 jpegs are very common, 4:2:2 also occurs in the wild but more rarely, and any other kind of subsampling is very rare. So we did add chroma subsampling to the jxl codestream, but only for YCbCr, and only for up to 2x, to keep things as simple as possible.

Basically the goal was to be able to recompress 99.9% of the JPEGs you would encounter in practice on the web, and I think we succeeded.

Now if jpegli is going to produce a new kind of exotic JPEG that we cannot recompress in JXL, then I think we are shooting ourselves in the foot.

Are there any benchmarks that give insight into the advantage of subsampling the B component in XYB? If this is a good idea, then why didn't we do it in jxl too? Unless there is a huge advantage to it, I would suggest to stop producing bitstreams in jpegli that cannot be represented in jxl.

mo271 commented 1 year ago

The consensus is that we should change jpegli not to subsample the B component.

Also we perhaps should document somewhere the very rare cases where recompression doesn't work:

jonsneyers commented 1 year ago

There are a few more things that we cannot do:

Agreed that it's a good idea to document somewhere what can be done and what cannot (and maybe also to compute and share some statistics on what kind of percentage of random web images we do cover).

Traneptora commented 1 year ago

3x and 4x subsampling works in avcodec's mjpeg decoder iirc, but only with YCbCr..

Traneptora commented 11 months ago

This has been fixed at some point so I'm closing the issue.