fix: canvas corruption in dispose-to-background for non-alpha frames#178
Merged
Merged
Conversation
The clear code in `composite_frame` branched on `frame_has_alpha` to decide byte stride, but the canvas is always RGBA (4 bytes/pixel). The `!frame_has_alpha` paths used 3-byte stride — `chunks_exact_mut(3)` for full-size and `* 3` indexing for sub-frames — misaligning pixel writes and corrupting the canvas. This triggers when an animation has `dispose=Background` and the next frame lacks alpha (e.g. lossy VP8 without ALPH chunk). The previous frame's rectangle gets cleared with wrong byte offsets. Fix: always clear with 4-byte pixels. `frame_has_alpha` describes the incoming frame data format, not the canvas format. Adds unit tests for both full-size and sub-frame disposal with RGB frames. The sub-frame test fails against the old code with: pixel (4,3) not cleared: [0, 0, 170, 170]
fintelia
approved these changes
Mar 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
composite_frameclear code branched onframe_has_alphato pick byte stride, but the canvas is always RGBA (4 bytes/pixel)!frame_has_alphapaths used 3-byte stride (chunks_exact_mut(3)for full-size,* 3indexing for sub-frames), misaligning pixel writesdispose=Backgroundand the next frame lacks alpha (e.g. lossy VP8 without ALPH chunk)Test plan
dispose_clear_fullsize_rgb_frameunit testdispose_clear_subframe_rgb_frameunit test (confirms failure on old code:pixel (4,3) not cleared: [0, 0, 170, 170])