From c6f46fe8c5d865bead16cfff7cc7f165303147b9 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 --- src/IMG_stb.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/IMG_stb.c b/src/IMG_stb.c index 464b5e36..464efce1 100644 --- a/src/IMG_stb.c +++ b/src/IMG_stb.c @@ -113,6 +113,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, @@ -145,6 +148,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) { @@ -157,12 +162,26 @@ 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) { +#if 1 /* SDL doesn't support blitting with the palette alpha, so expand the palette */ + SDL_Surface *converted = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_RGBA32); + SDL_DestroySurface(surface); + surface = converted; +#else SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_BLEND); +#endif + } else if (has_colorkey) { + SDL_SetSurfaceColorKey(surface, SDL_TRUE, colorkey_index); } /* FIXME: This sucks. It'd be better to allocate the surface first, then @@ -170,7 +189,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) {