libjxl / libjxl

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

-d 1 is much larger than (implicit) -d 0 due to silent switch to VarDCT #1746

Open RubenKelevra opened 2 years ago

RubenKelevra commented 2 years ago

Describe the bug

 -d maxError, --distance=maxError
    Max. butteraugli distance, lower = higher quality. Range: 0 .. 25.
    0.0 = mathematically lossless. Default for already-lossy input (JPEG/GIF).
    1.0 = visually lossless. Default for other input.

This help text gives the impression that selecting -d 1 should lead to a smaller file size than the default -d 0 which is selected for a gif, by dropping some details.

But just adding "-d 1" will lead to a VarDCT encoding instead of a Modular encoding and thus to a significantly larger file size.

To Reproduce

$ wget https://web.archive.org/web/20240731143411/https://discord.com/assets/e4ec7c5d7af5342f57347c9ada429fba.gif
$ cjxl e4ec7c5d7af5342f57347c9ada429fba.gif e4ec7c5d7af5342f57347c9ada429fba_d0.jxl -e 9 2>/dev/null
$ du -h e4ec7c5d7af5342f57347c9ada429fba_d0.jxl
2.6M    e4ec7c5d7af5342f57347c9ada429fba_d0.jxl

And the same procedure, just with '-d 1' added:

$ cjxl e4ec7c5d7af5342f57347c9ada429fba.gif e4ec7c5d7af5342f57347c9ada429fba_d1.jxl -e 9 -d 1 2>/dev/null
$ du -h e4ec7c5d7af5342f57347c9ada429fba_d1.jxl
8.6M    e4ec7c5d7af5342f57347c9ada429fba_d1.jxl

Expected behavior The encoder should not change the encoding type just because the user overrides the quality selection. Instead setting the quality/distance should only affect the quality/distance, nothing else.

Environment

Edit: Fixed gif link with the backup by the internet archive.

Traneptora commented 2 years ago

What happens if you use 0.7.0? It's in the Arch Repos now

Traneptora commented 2 years ago

Expected behavior The encoder should not change the encoding type just because the user overrides the quality selection. Instead setting the quality/distance should only affect the quality/distance, nothing else.

This is a special case because VarDCT is the default unless modular mode is forced. But VarDCT does not support distance=0 so that effectively forces modular mode.

zeroby0 commented 1 year ago

It's still larger in 0.7.0 (at -e 7), and it actually fails with -e 9

$: cjxl e4ec7c5d7af5342f57347c9ada429fba.gif e4ec7c5d7af5342f57347c9ada429fba.jxl -e 9 -d 1

JPEG XL encoder v0.7.0 f95da131 [AVX2,SSE4,SSSE3,Unknown]
Read 600x563 image, 3032897 bytes, 4.3 MP/s
Encoding [VarDCT, d1.000, effort: 9], 
./lib/jxl/image.h:57: JXL_CHECK: xsize <= orig_xsize_
fish: Job 1, 'cjxl e4ec7c5d7af5342f57347c9ada…' terminated by signal SIGILL (Illegal instruction)

JXL_CHECK: xsize <= orig_xsize_ to me implies that the original image is smaller compared to the jpeg-xl image, but that's true even with -e 7. Does JXL_CHECK run only for -e > 7?

Original image size: 3.0 MB (3,032,897 bytes)

-e -d size
9 0 2.6 MB (2,644,358 bytes)
9 1 fails JXL_CHECK: xsize <= origxsize
8 0 3.2 MB (3,245,385 bytes)
8 1 fails JXL_CHECK: xsize <= origxsize
7 0 3.5 MB (3,544,409 bytes)
7 1 5.8 MB (5,803,141 bytes)
6 0 3.7 MB (3,719,591 bytes)
6 1 5.9 MB (5,936,046 bytes)
5 0 3.7 MB (3,732,965 bytes)
5 1 5.9 MB (5,888,449 bytes)
4 0 4.0 MB (3,966,929 bytes)
4 1 5.9 MB (5,902,085 bytes)
Traneptora commented 1 year ago

Failing is a bug, and that should probably be reported separately.

Traneptora commented 1 year ago

Update: I reported the crash with https://github.com/libjxl/libjxl/issues/1929 as that's a different issue than the one being reported here.

RubenKelevra commented 3 months ago

Can confirm with version 0.10.3 (4a3b22d2) - even up to -d 5 is larger than explicit or implicit -d 0:

$ du -h e4ec7c5d7af5342f57347c9ada429fba*.jxl
3.0M    e4ec7c5d7af5342f57347c9ada429fba_d0.jxl
7.5M    e4ec7c5d7af5342f57347c9ada429fba_d1.jxl
5.5M    e4ec7c5d7af5342f57347c9ada429fba_d2.jxl
4.6M    e4ec7c5d7af5342f57347c9ada429fba_d3.jxl
3.9M    e4ec7c5d7af5342f57347c9ada429fba_d4.jxl
3.4M    e4ec7c5d7af5342f57347c9ada429fba_d5.jxl
jonnyawsom3 commented 3 months ago

Checking if the input is GIF and setting -m 1 unless the user overrides it would probably work well enough

Traneptora commented 3 months ago

What happens if you use -m 1 -d 1 instead of just -m 0 -d 1?

RubenKelevra commented 3 months ago

@Traneptora wrote:

What happens if you use -m 1 -d 1

Well, it gets bigger, like without -m1. That's not really what supposed to be happening, right?

File Size Distance Mode (forced)
3.0M -d0
7.5M -d1
7.1M -d1 -m1
5.5M -d2
5.9M -d2 -m1
4.6M -d3
5.5M -d3 -m1
3.9M -d4
5.2M -d4 -m1
3.4M -d5
5.0M -d5 -m1