-
Notifications
You must be signed in to change notification settings - Fork 237
IMG_webp: Incorrect frame composition in animated WebP loading #522
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
base: SDL2
Are you sure you want to change the base?
Changes from 10 commits
7ace470
09b4899
374730d
2638cb2
312ae53
b105e30
a27e2ed
387b5d5
8f6c6a0
abeb7bf
f8d4896
ed1bda3
b8c0093
bfbbc2c
609cd35
683d653
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -272,6 +272,8 @@ IMG_Animation *IMG_LoadWEBPAnimation_RW(SDL_RWops *src) | |
| WebPData wd; | ||
| uint32_t bgcolor; | ||
| SDL_Surface *canvas = NULL; | ||
| SDL_Surface *prevCanvas = NULL; | ||
| SDL_Rect prevRect = { 0 }; | ||
| WebPMuxAnimDispose dispose_method = WEBP_MUX_DISPOSE_BACKGROUND; | ||
|
|
||
| if (!src) { | ||
|
|
@@ -327,7 +329,8 @@ IMG_Animation *IMG_LoadWEBPAnimation_RW(SDL_RWops *src) | |
| } | ||
|
|
||
| canvas = SDL_CreateRGBSurfaceWithFormat(0, anim->w, anim->h, 0, features.has_alpha ? SDL_PIXELFORMAT_RGBA32 : SDL_PIXELFORMAT_RGBX32); | ||
| if (!canvas) { | ||
| prevCanvas = SDL_CreateRGBSurfaceWithFormat(0, anim->w, anim->h, 0, features.has_alpha ? SDL_PIXELFORMAT_RGBA32 : SDL_PIXELFORMAT_RGBX32); | ||
| if (!canvas || !prevCanvas) { | ||
| goto error; | ||
| } | ||
|
|
||
|
|
@@ -347,6 +350,15 @@ IMG_Animation *IMG_LoadWEBPAnimation_RW(SDL_RWops *src) | |
| (bgcolor >> 24) & 0xFF); | ||
| #endif | ||
|
|
||
| // Initialize both canvases - use bgcolor for non-alpha format, transparency for alpha | ||
| if (features.has_alpha) { | ||
| SDL_FillRect(canvas, NULL, SDL_MapRGBA(canvas->format, 0, 0, 0, 0)); | ||
| SDL_FillRect(prevCanvas, NULL, SDL_MapRGBA(prevCanvas->format, 0, 0, 0, 0)); | ||
| } else { | ||
| SDL_FillRect(canvas, NULL, bgcolor); | ||
| SDL_FillRect(prevCanvas, NULL, bgcolor); | ||
| } | ||
|
|
||
| SDL_zero(iter); | ||
| if (lib.WebPDemuxGetFrame(demuxer, 1, &iter)) { | ||
| do { | ||
|
|
@@ -357,8 +369,15 @@ IMG_Animation *IMG_LoadWEBPAnimation_RW(SDL_RWops *src) | |
| continue; | ||
| } | ||
|
|
||
| if (dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) { | ||
| SDL_FillRect(canvas, NULL, bgcolor); | ||
| // Set up destination rect for current frame | ||
| dst.x = iter.x_offset; | ||
| dst.y = iter.y_offset; | ||
| dst.w = iter.width; | ||
| dst.h = iter.height; | ||
|
|
||
| // Handle disposal of THIS frame's region before drawing it | ||
| if (iter.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND) { | ||
| SDL_FillRect(canvas, &dst, SDL_MapRGBA(canvas->format, 0, 0, 0, 0)); | ||
|
||
| } | ||
|
|
||
| curr = SDL_CreateRGBSurfaceWithFormat(0, iter.width, iter.height, 0, SDL_PIXELFORMAT_RGBA32); | ||
|
|
@@ -376,27 +395,25 @@ IMG_Animation *IMG_LoadWEBPAnimation_RW(SDL_RWops *src) | |
| goto error; | ||
| } | ||
|
|
||
| if (iter.blend_method == WEBP_MUX_BLEND) { | ||
| SDL_SetSurfaceBlendMode(curr, SDL_BLENDMODE_BLEND); | ||
| } else { | ||
| SDL_SetSurfaceBlendMode(curr, SDL_BLENDMODE_NONE); | ||
| } | ||
| dst.x = iter.x_offset; | ||
| dst.y = iter.y_offset; | ||
| dst.w = iter.width; | ||
| dst.h = iter.height; | ||
| SDL_SetSurfaceBlendMode(curr, SDL_BLENDMODE_NONE); | ||
|
||
| SDL_BlitSurface(curr, NULL, canvas, &dst); | ||
| SDL_FreeSurface(curr); | ||
|
|
||
| // Store complete frame state | ||
| anim->frames[frame_idx] = SDL_DuplicateSurface(canvas); | ||
| anim->delays[frame_idx] = iter.duration; | ||
|
|
||
| // Save current frame region and disposal method for next iteration | ||
| prevRect = dst; | ||
| dispose_method = iter.dispose_method; | ||
|
|
||
| } while (lib.WebPDemuxNextFrame(&iter)); | ||
|
|
||
| lib.WebPDemuxReleaseIterator(&iter); | ||
| } | ||
|
|
||
| SDL_FreeSurface(prevCanvas); | ||
|
|
||
| SDL_FreeSurface(canvas); | ||
|
|
||
| lib.WebPDemuxDelete(demuxer); | ||
|
|
@@ -406,6 +423,9 @@ IMG_Animation *IMG_LoadWEBPAnimation_RW(SDL_RWops *src) | |
| return anim; | ||
|
|
||
| error: | ||
| if (prevCanvas) { | ||
| SDL_FreeSurface(prevCanvas); | ||
| } | ||
| if (canvas) { | ||
| SDL_FreeSurface(canvas); | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure we should use transparency for alpha? is bgcolor a transparent pixel in that case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see white in the non-updated areas if not starting with alpha.
Investigation reveals many viewers just ignore background color entirely.
https://developers.google.com/speed/webp/docs/riff_container#animation
Kind of vague.
Some discussion on the matter:
SixLabors/ImageSharp#2547