From 9f88b0a31fcb1ba20370c6363ca94cf78ce20574 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 28 Dec 2023 09:35:52 -0800 Subject: [PATCH] Set the colorkey or expand the palette for indexed PNG images SDL doesn't support alpha blending using the palette alpha Fixes https://github.com/libsdl-org/SDL_image/issues/409 (cherry picked from commit c6f46fe8c5d865bead16cfff7cc7f165303147b9) --- src/IMG_stb.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/IMG_stb.c b/src/IMG_stb.c index 118fcc12c..7ff1b3498 100644 --- a/src/IMG_stb.c +++ b/src/IMG_stb.c @@ -117,6 +117,9 @@ SDL_Surface *IMG_LoadSTB_RW(SDL_RWops *src) rw_callbacks.eof = IMG_LoadSTB_RW_eof; w = h = format = 0; /* silence warning */ if (use_palette) { + /* Unused palette entries will be opaque white */ + SDL_memset(palette_colors, 0xff, sizeof(palette_colors)); + pixels = stbi_load_from_callbacks_with_palette( &rw_callbacks, src, @@ -150,6 +153,8 @@ SDL_Surface *IMG_LoadSTB_RW(SDL_RWops *src) SDL_PIXELFORMAT_INDEX8 ); if (surface) { + SDL_bool has_colorkey = SDL_FALSE; + int colorkey_index = -1; SDL_bool has_alpha = SDL_FALSE; SDL_Palette *palette = surface->format->palette; if (palette) { @@ -162,12 +167,23 @@ SDL_Surface *IMG_LoadSTB_RW(SDL_RWops *src) palette->colors[i].b = *palette_bytes++; palette->colors[i].a = *palette_bytes++; if (palette->colors[i].a != SDL_ALPHA_OPAQUE) { - has_alpha = SDL_TRUE; + if (palette->colors[i].a == SDL_ALPHA_TRANSPARENT && !has_colorkey) { + has_colorkey = SDL_TRUE; + colorkey_index = i; + } else { + /* Partial opacity or multiple colorkeys */ + has_alpha = SDL_TRUE; + } } } } if (has_alpha) { - SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_BLEND); + /* SDL doesn't support blitting with the palette alpha, so expand the palette */ + SDL_Surface *converted = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_RGBA32, 0); + SDL_FreeSurface(surface); + surface = converted; + } else if (has_colorkey) { + SDL_SetColorKey(surface, SDL_TRUE, colorkey_index); } /* FIXME: This sucks. It'd be better to allocate the surface first, then @@ -175,7 +191,9 @@ SDL_Surface *IMG_LoadSTB_RW(SDL_RWops *src) * https://github.com/nothings/stb/issues/58 * -flibit */ - surface->flags &= ~SDL_PREALLOC; + if (surface) { + surface->flags &= ~SDL_PREALLOC; + } } } else if (format == STBI_grey || format == STBI_rgb || format == STBI_rgb_alpha) {