Skip to content

Bump weezl to 0.2 (faster decode + multiple LZW fixes; fixes small interlaced GIFs, supersedes #232 + #233)#236

Merged
197g merged 3 commits into
image-rs:masterfrom
lilith:bump-weezl-0.2
May 31, 2026
Merged

Bump weezl to 0.2 (faster decode + multiple LZW fixes; fixes small interlaced GIFs, supersedes #232 + #233)#236
197g merged 3 commits into
image-rs:masterfrom
lilith:bump-weezl-0.2

Conversation

@lilith
Copy link
Copy Markdown
Contributor

@lilith lilith commented May 29, 2026

weezl 0.2.x is a substantial step up from the 0.1.x line this crate currently pins, on both correctness and speed.

Correctness — 0.2.x fixes several decoder bugs over 0.1.10

The #68 fix is the one that matters here: it's exactly what made small interlaced GIFs fail to decode. When read_into_buffer hands weezl a tiny per-row output slice (7–47 bytes for a small interlaced frame), weezl 0.1.x could return NoProgress even though it had advanced its internal word buffer, and the streaming decoder then treated the still-valid input as truncated. On weezl 0.2.1 that no longer happens, so no decoder-side handling is needed — the bump alone fixes it.

Performance

weezl 0.2.0 reworked the decoder around a Wuffs-inspired design (image-rs/weezl#77) that decodes 8 bytes at a time over a pre-built code tree. I measured decode through this crate's full path (master, the only change being the weezl version), interleaved A/B across an 8×8→2048×2048 size sweep on two architectures (x86-64 Zen 4 and aarch64 Neoverse-N1):

On GIFs larger than 16×16, weezl 0.2.1 decodes faster — roughly +7% at 32×32 rising to +24% at 2048×2048 on x86-64, and +9% rising to +32% on aarch64 (about 1.24× / 1.32× per pixel at large sizes; the win grows with image size, and aarch64 benefits most). The interlaced regression GIFs below also now decode correctly where 0.1.10 rejected them.

(Numbers are interleaved-A/B ratios via zenbench, no target-cpu=native; bench notes available on request.)

What this changes

  • weezl dependency 0.1.100.2.1.
  • MSRV 1.851.88 (weezl 0.2.1 declares rust-version = "1.88.0" — see reviewer note).
  • Adds tests/small_interlaced.rs: regression tests for 7×7, 9×9, and 47×63 interlaced GIFs produced by gifsicle 1.95 (valid per GIF89a, verified with giftopnm), which previously failed with DecodingFormatError { underlying: "unexpected data" }.

No source changes are required in src/reader/decoder.rs: the LzwReader wrapper already consumes weezl's BufferResult/VectorResult shape, which is unchanged between 0.1.10 and 0.2.1. The entire non-test diff is the two Cargo.toml version strings.

Supersedes #232 and #233

Both #232 and #233 can be closed in favour of this PR. A/B on a clean master:

Config small_interlaced result
master + weezl 0.1.10 3 failed (unexpected data)
master + weezl 0.2.1 (this PR) 3 passed

Full cargo test is green on the bumped tree.

Reviewer note: MSRV

weezl 0.2.1 raises its MSRV to Rust 1.88.0. image-gif currently declares rust-version = "1.85", so this PR also bumps the declared MSRV to 1.88. If holding MSRV at 1.85 is a hard requirement, this bump can't land as written — that's the trade-off to weigh. For reference, image-tiff already took the same step on main (image-rs/image-tiff#392 bumped weezl to 0.2 and MSRV to 1.88.0).

Refs: image-rs/weezl#64, #67, #68, #72, #77, #78, and #232, #233.

weezl 0.2.x fixes the small-output-buffer false-NoProgress bug
(image-rs/weezl#68, fixed by image-rs#72) that caused small interlaced GIFs to
fail decoding. Bumps weezl 0.1.10 -> 0.2.1 and MSRV 1.85 -> 1.88 (weezl
0.2.1 requires 1.88). Adds tests/small_interlaced.rs (7x7, 9x9, 47x63).

Supersedes image-rs#233.
@lilith lilith changed the title Bump weezl to 0.2 (fixes small interlaced GIF decode; supersedes #233 workaround) Bump weezl to 0.2 (faster decode + multiple LZW fixes; fixes small interlaced GIFs, supersedes #232 + #233) May 29, 2026
@kornelski
Copy link
Copy Markdown
Contributor

CI needs msrv update

lilith added 2 commits May 30, 2026 19:41
The weezl 0.2.1 bump raised rust-version to 1.88, but the CI matrix
still pinned the MSRV job at 1.85.0. Align the CI toolchain (matrix +
test-skip condition) so the MSRV job actually exercises the declared
minimum.
The crate root is `#![cfg(feature = "std")]`, so with --no-default-features
the gif crate exports nothing and the new integration test fails to compile
(E0433: cannot find DecodeOptions/ColorOutput/DecodingError in gif). Every
other test file already opens with `#![cfg(feature = "std")]`; add the same
guard here so the no-default-features clippy job compiles it to empty.
@lilith
Copy link
Copy Markdown
Contributor Author

lilith commented May 31, 2026

I just found out that Ubuntu 26.04 LTS bundles Rust 1.93.1

@197g 197g merged commit a5f89dd into image-rs:master May 31, 2026
13 checks passed
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.

3 participants