The palette unused value is treated as alpha and updated when setting the colorkey.
authorSam Lantinga <slouken@libsdl.org>
Sun, 24 Mar 2013 09:51:01 -0700
changeset 70231d49dc7b5ce9
parent 7022 d9f3d2e3bd07
child 7024 72cb3e205571
The palette unused value is treated as alpha and updated when setting the colorkey.
This fixes issues loading palettized images that have a colorkey with the same RGB values as another entry in the palette (e.g. bug 1746)
src/video/SDL_pixels.c
src/video/SDL_pixels_c.h
src/video/SDL_surface.c
     1.1 --- a/src/video/SDL_pixels.c	Sat Mar 23 13:03:36 2013 -0700
     1.2 +++ b/src/video/SDL_pixels.c	Sun Mar 24 09:51:01 2013 -0700
     1.3 @@ -762,12 +762,12 @@
     1.4   * Match an RGB value to a particular palette index
     1.5   */
     1.6  Uint8
     1.7 -SDL_FindColor(SDL_Palette * pal, Uint8 r, Uint8 g, Uint8 b)
     1.8 +SDL_FindColor(SDL_Palette * pal, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
     1.9  {
    1.10      /* Do colorspace distance matching */
    1.11      unsigned int smallest;
    1.12      unsigned int distance;
    1.13 -    int rd, gd, bd;
    1.14 +    int rd, gd, bd, ad;
    1.15      int i;
    1.16      Uint8 pixel = 0;
    1.17  
    1.18 @@ -776,7 +776,8 @@
    1.19          rd = pal->colors[i].r - r;
    1.20          gd = pal->colors[i].g - g;
    1.21          bd = pal->colors[i].b - b;
    1.22 -        distance = (rd * rd) + (gd * gd) + (bd * bd);
    1.23 +        ad = pal->colors[i].unused - a;
    1.24 +        distance = (rd * rd) + (gd * gd) + (bd * bd) + (ad * ad);
    1.25          if (distance < smallest) {
    1.26              pixel = i;
    1.27              if (distance == 0) {        /* Perfect match! */
    1.28 @@ -797,7 +798,7 @@
    1.29              | (g >> format->Gloss) << format->Gshift
    1.30              | (b >> format->Bloss) << format->Bshift | format->Amask;
    1.31      } else {
    1.32 -        return SDL_FindColor(format->palette, r, g, b);
    1.33 +        return SDL_FindColor(format->palette, r, g, b, SDL_ALPHA_OPAQUE);
    1.34      }
    1.35  }
    1.36  
    1.37 @@ -812,7 +813,7 @@
    1.38              | (b >> format->Bloss) << format->Bshift
    1.39              | ((a >> format->Aloss) << format->Ashift & format->Amask);
    1.40      } else {
    1.41 -        return SDL_FindColor(format->palette, r, g, b);
    1.42 +        return SDL_FindColor(format->palette, r, g, b, a);
    1.43      }
    1.44  }
    1.45  
    1.46 @@ -858,7 +859,7 @@
    1.47              *r = format->palette->colors[pixel].r;
    1.48              *g = format->palette->colors[pixel].g;
    1.49              *b = format->palette->colors[pixel].b;
    1.50 -            *a = SDL_ALPHA_OPAQUE;
    1.51 +            *a = format->palette->colors[pixel].unused;
    1.52          } else {
    1.53              *r = *g = *b = *a = 0;
    1.54          }
    1.55 @@ -894,7 +895,7 @@
    1.56      for (i = 0; i < src->ncolors; ++i) {
    1.57          map[i] = SDL_FindColor(dst,
    1.58                                 src->colors[i].r, src->colors[i].g,
    1.59 -                               src->colors[i].b);
    1.60 +                               src->colors[i].b, src->colors[i].unused);
    1.61      }
    1.62      return (map);
    1.63  }
    1.64 @@ -918,10 +919,10 @@
    1.65  
    1.66      /* We memory copy to the pixel map so the endianness is preserved */
    1.67      for (i = 0; i < pal->ncolors; ++i) {
    1.68 -        Uint8 A = Amod;
    1.69          Uint8 R = (Uint8) ((pal->colors[i].r * Rmod) / 255);
    1.70          Uint8 G = (Uint8) ((pal->colors[i].g * Gmod) / 255);
    1.71          Uint8 B = (Uint8) ((pal->colors[i].b * Bmod) / 255);
    1.72 +        Uint8 A = (Uint8) ((pal->colors[i].unused * Amod) / 255);
    1.73          ASSEMBLE_RGBA(&map[i * bpp], dst->BytesPerPixel, dst, R, G, B, A);
    1.74      }
    1.75      return (map);
     2.1 --- a/src/video/SDL_pixels_c.h	Sat Mar 23 13:03:36 2013 -0700
     2.2 +++ b/src/video/SDL_pixels_c.h	Sun Mar 24 09:51:01 2013 -0700
     2.3 @@ -36,6 +36,6 @@
     2.4  /* Miscellaneous functions */
     2.5  extern int SDL_CalculatePitch(SDL_Surface * surface);
     2.6  extern void SDL_DitherColors(SDL_Color * colors, int bpp);
     2.7 -extern Uint8 SDL_FindColor(SDL_Palette * pal, Uint8 r, Uint8 g, Uint8 b);
     2.8 +extern Uint8 SDL_FindColor(SDL_Palette * pal, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
     2.9  
    2.10  /* vi: set ts=4 sw=4 expandtab: */
     3.1 --- a/src/video/SDL_surface.c	Sat Mar 23 13:03:36 2013 -0700
     3.2 +++ b/src/video/SDL_surface.c	Sun Mar 24 09:51:01 2013 -0700
     3.3 @@ -187,7 +187,13 @@
     3.4      if (flag) {
     3.5          surface->map->info.flags |= SDL_COPY_COLORKEY;
     3.6          surface->map->info.colorkey = key;
     3.7 +        if (surface->format->palette) {
     3.8 +            surface->format->palette->colors[surface->map->info.colorkey].unused = SDL_ALPHA_TRANSPARENT;
     3.9 +        }
    3.10      } else {
    3.11 +        if (surface->format->palette) {
    3.12 +            surface->format->palette->colors[surface->map->info.colorkey].unused = SDL_ALPHA_OPAQUE;
    3.13 +        }
    3.14          surface->map->info.flags &= ~SDL_COPY_COLORKEY;
    3.15      }
    3.16      if (surface->map->info.flags != flags) {
    3.17 @@ -843,14 +849,35 @@
    3.18             SDL_COPY_RLE_ALPHAKEY));
    3.19      surface->map->info.flags = copy_flags;
    3.20      if (copy_flags & SDL_COPY_COLORKEY) {
    3.21 -        Uint8 keyR, keyG, keyB, keyA;
    3.22 +        SDL_bool set_colorkey_by_color = SDL_FALSE;
    3.23  
    3.24 -        SDL_GetRGBA(surface->map->info.colorkey, surface->format, &keyR,
    3.25 -                    &keyG, &keyB, &keyA);
    3.26 -        SDL_SetColorKey(convert, 1,
    3.27 -                        SDL_MapRGBA(convert->format, keyR, keyG, keyB, keyA));
    3.28 -        /* This is needed when converting for 3D texture upload */
    3.29 -        SDL_ConvertColorkeyToAlpha(convert);
    3.30 +        if (surface->format->palette) {
    3.31 +            if (format->palette && 
    3.32 +                surface->format->palette->ncolors <= format->palette->ncolors &&
    3.33 +                (SDL_memcmp(surface->format->palette->colors, format->palette->colors,
    3.34 +                  surface->format->palette->ncolors * sizeof(SDL_Color)) == 0)) {
    3.35 +                /* The palette is identical, just set the same colorkey */
    3.36 +                SDL_SetColorKey(convert, 1, surface->map->info.colorkey);
    3.37 +            } else if (format->Amask) {
    3.38 +                /* The alpha was set in the destination from the palette */
    3.39 +            } else {
    3.40 +                set_colorkey_by_color = SDL_TRUE;
    3.41 +            }
    3.42 +        } else {
    3.43 +            set_colorkey_by_color = SDL_TRUE;
    3.44 +        }
    3.45 +
    3.46 +        if (set_colorkey_by_color) {
    3.47 +            /* Set the colorkey by color, which needs to be unique */
    3.48 +            Uint8 keyR, keyG, keyB, keyA;
    3.49 +
    3.50 +            SDL_GetRGBA(surface->map->info.colorkey, surface->format, &keyR,
    3.51 +                        &keyG, &keyB, &keyA);
    3.52 +            SDL_SetColorKey(convert, 1,
    3.53 +                            SDL_MapRGBA(convert->format, keyR, keyG, keyB, keyA));
    3.54 +            /* This is needed when converting for 3D texture upload */
    3.55 +            SDL_ConvertColorkeyToAlpha(convert);
    3.56 +        }
    3.57      }
    3.58      SDL_SetClipRect(convert, &surface->clip_rect);
    3.59