这是indexloc提供的服务,不要输入任何密码
Skip to content

Conversation

@jonsneyers
Copy link
Member

This allows decoding (some) corrupt bitstreams. Fixes #3712.

Does not catch all kinds of corruptions yet, nor does it handle them in the best possible way, but it's a start.

The function JxlDecoderSetLeniency() is added, as well as the corresponding djxl option --leniency=N.
Default leniency is zero which does not change any behavior.

Leniency 1:
Corrupted HF sections are replaced with LF only (in case of VarDCT) or zeroes (in case of Modular).
This is a reasonable "graceful degradation": in case of lossy (VarDCT or Modular) it means the corrupt region becomes blurry; in case of lossless it means the corrupt region becomes black.

Leniency 2:
On top of leniency 1, also continue if LF sections are corrupt (corresponding to 2048x2048 pixels).
Corrupted LF sections are just turned entirely black.

This creates a basic mechanism for some amount of error recovery; instead of just returning an error when a bitstream is corrupt, you can now get a reasonable image.

TODO: better handle multi-pass and multi-frame.

Negative leniency (not implemented yet) can be useful if we want to have a way to be "stricter than default".

E.g. we currently don't check value ranges / integer overflows in places where checking would cause a slowdown (e.g. checking that modular data remains in int16 / int32 range, etc) so libjxl does decode some invalid codestreams without complaining. Having a way to validate codestreams would be nice, but it's probably best to keep that a non-default option since it will cause slowdown. Also I think we currently only check level 10 limits but not level 5 ones. Anyway: negative leniency is not implemented yet but it could be another use of this decode option besides positive leniency to handle corrupt bitstreams.

@jonsneyers jonsneyers added decoder Related to the libjxl decoder api Related to the libjxl API labels Jan 13, 2025
@jonsneyers jonsneyers requested review from eustas and veluca93 January 13, 2025 14:10
@jonnyawsom3
Copy link
Collaborator

Mentioning a 'negative leniency', perhaps that could have an equivalent in cjxl to make sure lossless files are actually lossless, as some have asked recently. Positive vales enabling invisible pixel zeroing to give it more than 1 use, ect.

@jonsneyers
Copy link
Member Author

Mentioning a 'negative leniency', perhaps that could have an equivalent in cjxl to make sure lossless files are actually lossless, as some have asked recently. Positive vales enabling invisible pixel zeroing to give it more than 1 use, ect.

This PR is a decode option, not an encode option.

There is already an encode option to select what to do with invisible pixels iirc. And lossless should always be lossless, if it's not that's a bug. We could add an explicit roundtrip test option to cjxl if that's a desirable feature, but I don't think there needs to be a libjxl-level feature for it.

* @param leniency amount of leniency regarding invalid input
* @return ::JXL_DEC_SUCCESS if no error, ::JXL_DEC_ERROR otherwise.
*/
JXL_EXPORT JxlDecoderStatus JxlDecoderSetLeniency(JxlDecoder* dec,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I like the name... I think we'll discuss this in the next team meeting and get back to you :-)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could also call it SetStrictness and reverse the scale...

@jonnyawsom3
Copy link
Collaborator

Was testing it out just now and discovered --leniency=2 causes squeeze encoded modular files to break
Test

This allows decoding corrupt bitstreams. Fixes libjxl#3712.
Does not catch all kinds of corruptions yet, nor does it handle them in the best possible way, but it's a start.
Corrupted HF sections are replaced with LF only (in case of VarDCT) or zeroes (in case of Modular).
Corrupted LF sections are just turned entirely black.

Negative leniency (not implemented yet) can be useful if we want to have a way to be "stricter than default".
E.g. we currently don't check value ranges / integer overflows in places where checking would cause a slowdown
(e.g. checking that modular data remains in int16 / int32 range, etc) so libjxl does decode some invalid
codestreams without complaining. Having a way to validate codestreams would be nice, but it's probably best
to keep that a non-default option since it will cause slowdown.
Also I think we currently only check level 10 limits but not level 5 ones.
Anyway: negative leniency is not implemented yet but it could be another use of this decode option besides
positive leniency to handle corrupt bitstreams.
@jonsneyers
Copy link
Member Author

Was testing it out just now and discovered --leniency=2 causes squeeze encoded modular files to break ![Test]

Oops! Thanks for spotting this! Silly mistake, this should fix it.
The image you get is the result of accidentally zeroing modular LF groups (while global LF is still fine and so is the HF), while they should only be zeroed if they are corrupted. That messes up the mid-frequencies, which actually produces a surprisingly reasonable image still, I was expecting something worse :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api Related to the libjxl API decoder Related to the libjxl decoder

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Decode option for decoding corrupted bitstreams

3 participants