Skip to content

Conversation

@steschu77
Copy link
Contributor

@steschu77 steschu77 commented Nov 14, 2025

This PR introduces a more efficient method for decoding coefficient signs in the WebP decoder.

Background

The existing implementation derived the range shift after decoding a sign of a coefficient by performing a (rather time consuming in terms of bit decoding) leading_zeros() calculation on the range.

Since the range after a sign decoding is guaranteed to lie within a range of 64..127, that shift is always 1. See also libwebp's VP8GetSigned() function in src/utils/bit_reader_inl_utils.h

Similar conditions are true for flag decoding with the exception that the range could still be in the range of 64..128 and 128 doesn't need any shifting.

That difference between flags and signs comes from the initial range value of 255 that can reach flag decoding but not sign decoding since after any symbol has been decoded, range is guaranteed to be within 128..254 and signs are never the first symbol in a VP8 bit stream.

Too bad Google didn't initialize the arithmetic coder with 254 instead of 255...

What Changed

  • Added a dedicated sign-decoding path instead of using the generic flag decoding.
  • Added narrower limits for asserting range.
  • Improved flag decoding by limiting shift to be 0 (for range=128) or 1 (for range in 64..127)

Performance

Performance has been benchmarked using all test images in the repository plus two additional larger WebP images (gallery1/6 and gallery1/7)

Each image was decoded 20 times, and the total decoding time was measured.

Test Current [ms] Improved [ms] Ratio
gallery1/1 60.02 58.13 96.85%
gallery1/2 108.02 104.47 96.72%
gallery1/3 387.78 379.26 97.80%
gallery1/4 332.84 319.92 96.12%
gallery1/5 213.06 208.87 98.04%
gallery1/6 4,866.24 4,698.41 96.55%
gallery1/7 7,073.57 6,968.21 98.51%

Overall, the new method consistently shows a 1–4% improvement in decode time across all tested images.

… within 128..254.

* Add sign decoding to arithmetic decoder.
* Add narrower limits for asserting `range`.
* Improved flag decoding by limiting `shift` to be 0 (for range=128) or 1 (for range in 64..127)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant