-
Notifications
You must be signed in to change notification settings - Fork 215
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)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. disposing with the background should use the background color, not black. |
||
} | ||
|
||
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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How do you handle WEBP_MUX_BLEND? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh right, what do you think of this?
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Clearing the region isn't necessary for BLENDMODE_NONE, the entire rectangle is copied from the source. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should just be able to use the original code: if (iter.blend_method == WEBP_MUX_BLEND) {
SDL_SetSurfaceBlendMode(curr, SDL_BLENDMODE_BLEND);
} else {
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