JxlDecoderProcessInput returned JXL_DEC_ERROR on certain images
cheng-chi opened this issue · comments
Hi Christoph,
Thank you so much for maintaining this package! It's super handy for my current research project.
I'm currently countering a bug with JpegXL on Ubuntu 20.04 with this image (attached as png).
Minimal reproducible example:
import imagecodecs
img = imagecodecs.png_decode(open('test.png', 'rb').read())
imagecodecs.jpegxl_decode(imagecodecs.jpegxl_encode(img, level=4, lossless=False))
Looks like the jxl library encoder produces an invalid JPEG XL stream with level > 1
in lossy mode.
The level
parameter maps to the "decoding speed tier", which is probably not what you want. I better change level
to something like the "quality" parameter of the cjxl tool, although that is not part of the public jxl API...
For now, consider the distance
or effort
parameters:
/**
* Sets the distance level for lossy compression: target max butteraugli
* distance, lower = higher quality. Range: 0 .. 15.
* 0.0 = mathematically lossless (however, use JxlEncoderSetFrameLossless
* instead to use true lossless, as setting distance to 0 alone is not the only
* requirement). 1.0 = visually lossless. Recommended range: 0.5 .. 3.0. Default
* value: 1.0.
/** Sets encoder effort/speed level without affecting decoding speed. Valid
* values are, from faster to slower speed: 1:lightning 2:thunder 3:falcon
* 4:cheetah 5:hare 6:wombat 7:squirrel 8:kitten 9:tortoise.
Going to use the formula from the GIMP plugin to map level
/quality
to distance
in the next version of imagecodecs:
https://github.com/libjxl/libjxl/blob/f95da131cf7c7ccd4da256356fde2fec1fa23bb5/plugins/gimp/file-jxl-save.cc#L541-L555
Unfortunately that formula is going to change in the next version of libjxl...
Thanks for the fast response! I can confirm that the following code works. It seems like libjxl is still not stable enough for general usage. I will use Jpeg2k for now!
import imagecodecs
img = imagecodecs.png_decode(open('test.png', 'rb').read())
imagecodecs.jpegxl_decode(imagecodecs.jpegxl_encode(img, effort=3, distance=1.0, lossless=False, decodingspeed=1))
Just to confirm, is "jxl library encoder produces an invalid JPEG XL stream with level > 1 in lossy mode" a bug or expected behavior? Is it documented in libjxl? Or should I submit an issue to libjxl as well?
Looks like a bug. To reproduce the issue, effort
has to be below 5 too. I don't see this documented and would expect an error during writing if this combination of parameters is not valid.
In order to report the issue to libjxl, this needs to be reproduced outside of imagecodecs with the current libjxl development code. Unfortunately the decoding speed parameter cannot be set with the cjxl tool. Let's take that as a hint not to change the default decoding speed...
In v2022.12.22, the level
parameter maps to distance
in a way that it resembles the libjpeg quality
parameter.
Thanks for making the change!