Skip to content

fix: Preserve GIF transparent color across frames #255

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 16, 2025

Conversation

skidder
Copy link
Contributor

@skidder skidder commented May 16, 2025

Summary

This PR addresses an issue where transparency information from GIF files was being discarded during the decoding process, resulting in incorrect background and transparency color values in GIF-to-GIF conversions.

Change

  • Removed the default initialization of TransparentColor = NO_TRANSPARENT_COLOR in the giflib_get_frame_gcb function
  • This allows the original transparency color index from the source GIF to be preserved when reading GraphicsControlBlock information
  • Added safeguards against removing transparency when background has partial transparency
  • Restores use of No Dispose for case where disposal method is unspecified

Impact

  • Background colors and transparency values are now correctly preserved in round-trip GIF-to-GIF conversions
  • Maintains transparency information as specified in the original GIF files

Testing

Analysis of GIF frame data shows that this change correctly preserves the original background color while the production version incorrectly defaults to black.

Source

orcouldyou

Development (this branch) version

orcouldyou-dev

Stable (prod) version

orcouldyou-prod

Extracted background, transparency, and dispose data for a source image against images from created from this development branch and stable:

  # Extract background and transparency info from source file
  identify -verbose "orcouldyou.gif" | grep -iE "(background color:|transparent color:|dispos)" > source-identify.info

  # Extract info from production version (incorrect)
  identify -verbose "orcouldyou-prod.gif" | grep -iE "(background color:|transparent color:|dispos)" > prod-identify.info

  # Extract info from development version (correct)
  identify -verbose "orcouldyou-dev.gif" | grep -iE "(background color:|transparent color:|dispos)" > dev-identify.info

I then compared that data for the dev and stable (prod) branches against the source. The stable prod branch is mangling the background and transparent color, making them different from the source.

→ diff prod-identify.info source-identify.info
1c1
<   Background color: black
---
>   Background color: white
3,70c3,70
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
<   Background color: black
<   Transparent color: srgba(255,255,255,0)
---
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black
>   Background color: white
>   Transparent color: black

→ diff dev-identify.info source-identify.info
<empty>

Technical Details

The issue was that we were unconditionally initializing the GraphicsControlBlock's TransparentColor field to -1 (no transparency) before reading the actual GCB data from extension blocks. This inadvertently caused the loss of transparency information when no specific transparency data was present in the GIF's extension blocks. As far as I can tell, this issue has always existed in Lilliput.

@skidder skidder merged commit eaa601f into master May 16, 2025
5 checks passed
@skidder skidder deleted the skidder/fix-transparency-color-preservation branch June 23, 2025 17:13
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.

2 participants