SDL_image: IMG_webp: Fix animated WebP frame composition (thanks @inigomonyota!)

From d21bf6cb711124fe28c10f8c96173c228ae5dc8e Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Thu, 8 Jan 2026 10:26:22 -0800
Subject: [PATCH] IMG_webp: Fix animated WebP frame composition (thanks
 @inigomonyota!)

Combines disposal and blend preparation into a single operation
- Properly handles WEBP_MUX_DISPOSE_BACKGROUND with alpha channel status
- Correctly applies bgcolor for non-alpha WebPs and transparency for alpha WebPs
- Sets appropriate blend modes (BLEND/NONE) based on frame's blend_method

Closes https://github.com/libsdl-org/SDL_image/pull/522
---
 src/IMG_webp.c | 27 ++++++++++++++++++++-------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/src/IMG_webp.c b/src/IMG_webp.c
index f54baf1e2..9b55bca2b 100644
--- a/src/IMG_webp.c
+++ b/src/IMG_webp.c
@@ -355,6 +355,13 @@ IMG_Animation *IMG_LoadWEBPAnimation_RW(SDL_RWops *src)
                           (bgcolor >> 24) & 0xFF);
 #endif
 
+    /* Initialize canvas - 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));
+    } else {
+        SDL_FillRect(canvas, NULL, bgcolor);
+    }
+
     SDL_zero(iter);
     if (lib.WebPDemuxGetFrame(demuxer, 1, &iter)) {
         do {
@@ -365,8 +372,16 @@ 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 and prepare region for new frame */
+            if (iter.dispose_method == WEBP_MUX_DISPOSE_BACKGROUND ||
+                iter.blend_method == WEBP_MUX_NO_BLEND) {
+                SDL_FillRect(canvas, &dst, bgcolor);
             }
 
             curr = SDL_CreateRGBSurfaceWithFormat(0, iter.width, iter.height, 0, SDL_PIXELFORMAT_RGBA32);
@@ -384,21 +399,19 @@ IMG_Animation *IMG_LoadWEBPAnimation_RW(SDL_RWops *src)
                 goto error;
             }
 
+            /* Set blend mode based on the frame's blend method */
             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_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;
-            dispose_method = iter.dispose_method;
 
         } while (lib.WebPDemuxNextFrame(&iter));