From 2c816714bb3fc0486b4cefcac130941fdadf664b Mon Sep 17 00:00:00 2001 From: Glenn Maynard Date: Wed, 8 Oct 2003 01:46:00 +0000 Subject: [PATCH] add mySDL_Palettize --- stepmania/src/SDL_utils.cpp | 110 ++++++++++++++++++++++++++++++++++++ stepmania/src/SDL_utils.h | 1 + 2 files changed, 111 insertions(+) diff --git a/stepmania/src/SDL_utils.cpp b/stepmania/src/SDL_utils.cpp index 51058b6241..e3e87d190b 100644 --- a/stepmania/src/SDL_utils.cpp +++ b/stepmania/src/SDL_utils.cpp @@ -981,3 +981,113 @@ void mySDL_BlitSurface( /* We don't do RGBA->PAL. */ ASSERT(0); } + +/* This converts an image to a special 8-bit paletted format. The palette is set up + * so that palette indexes look like regular, packed components. + * + * For example, an image with 8 bits of grayscale and 0 bits of alpha has a palette + * that looks like { 0,0,0,255 }, { 1,1,1,255 }, { 2,2,2,255 }, ... { 255,255,255,255 }. + * This results in index components that can be treated as grayscale values. + * + * An image with 2 bits of grayscale and 2 bits of alpha look like + * { 0,0,0,0 }, { 85,85,85,0 }, { 170,170,170,0 }, { 255,255,255,0 }, + * { 0,0,0,85 }, { 85,85,85,85 }, { 170,170,170,85 }, { 255,255,255,85 }, ... + * + * This results in index components that can be pulled apart like regular packed + * values: the first two bits of the index are the grayscale component, and the next + * two bits are the alpha component. + * + * This gives us a generic way to handle arbitrary 8-bit texture formats. It could + * possibly be used for 16-bit texture formats, but I doubt those are well-supported + * in hardware, and SDL blits only support 8-bit paletted surfaces. */ +SDL_Surface *mySDL_Palettize( SDL_Surface *src_surf, int GrayBits, int AlphaBits ) +{ + AlphaBits = min( AlphaBits, 8-src_surf->format->Aloss ); + + const int TotalBits = GrayBits + AlphaBits; + ASSERT( TotalBits <= 8 ); + + SDL_Surface *dst_surf = SDL_CreateRGBSurfaceSane(SDL_SWSURFACE, src_surf->w, src_surf->h, + 8, 0,0,0,0 ); + + /* Set up the palette. */ + const int TotalColors = 1 << TotalBits; + const int Ivalues = 1 << GrayBits; // number of intensity values + const int Ishift = 0; // intensity shift + const int Imask = ((1 << GrayBits) - 1) << Ishift; // intensity mask + const int Iloss = 8-GrayBits; + + const int Avalues = 1 << AlphaBits; // number of alpha values + const int Ashift = GrayBits; // alpha shift + const int Amask = ((1 << AlphaBits) - 1) << Ashift; // alpha mask + const int Aloss = 8-AlphaBits; + + for( int index = 0; index < TotalColors; ++index ) + { + const int I = (index & Imask) >> Ishift; + const int A = (index & Amask) >> Ashift; + + int ScaledI; + if( Ivalues == 1 ) + ScaledI = 255; // if only one intensity value, always fullbright + else + ScaledI = clamp( int(roundf(I * (255.0f / (Ivalues-1)))), 0, 255 ); + + int ScaledA; + if( Avalues == 1 ) + ScaledA = 255; // if only one alpha value, always opaque + else + ScaledA = clamp( int(roundf(A * (255.0f / (Avalues-1)))), 0, 255 ); + + SDL_Color c; + c.r = Uint8(ScaledI); + c.g = Uint8(ScaledI); + c.b = Uint8(ScaledI); + c.unused = Uint8(ScaledA); + + SDL_SetColors( dst_surf, &c, index, 1); + } + + const char *src = (const char *) src_surf->pixels; + const char *dst = (const char *) dst_surf->pixels; + + int height = src_surf->h; + int width = src_surf->w; + + /* Bytes to skip at the end of a line. */ + const int srcskip = src_surf->pitch - width*src_surf->format->BytesPerPixel; + const int dstskip = dst_surf->pitch - width*dst_surf->format->BytesPerPixel; + + while( height-- ) + { + int x = 0; + while( x++ < width ) + { + unsigned int pixel = decodepixel((Uint8 *) src, src_surf->format->BytesPerPixel); + + Uint8 colors[4]; + mySDL_GetRGBAV(pixel, src_surf, colors); + + int Ival = 0; + Ival += colors[0]; + Ival += colors[1]; + Ival += colors[2]; + Ival /= 3; + + pixel = (Ival >> Iloss) << Ishift | + (colors[3] >> Aloss) << Ashift; + + /* Store it. */ + *((Uint8 *) dst) = Uint8(pixel); + + src += src_surf->format->BytesPerPixel; + dst += dst_surf->format->BytesPerPixel; + } + + src += srcskip; + dst += dstskip; + } + + return dst_surf; +} + diff --git a/stepmania/src/SDL_utils.h b/stepmania/src/SDL_utils.h index 4e0338d08e..9c17aae527 100644 --- a/stepmania/src/SDL_utils.h +++ b/stepmania/src/SDL_utils.h @@ -64,6 +64,7 @@ void mySDL_BlitTransform( const SDL_Surface *src, SDL_Surface *dst, const float fCoords[8] /* TL, BR, BL, TR */ ); void mySDL_BlitSurface( SDL_Surface *src, SDL_Surface *dst, int width, int height, bool ckey); +SDL_Surface *mySDL_Palettize( SDL_Surface *src_surf, int GrayBits, int AlphaBits ); #endif