Automatically figure out if we can use 0alpha or 1alpha. I'll remove the

old code once the new code is stable.
This commit is contained in:
Glenn Maynard
2003-03-27 06:01:43 +00:00
parent b1a2ff88fc
commit 609531c1a7
3 changed files with 171 additions and 32 deletions
+52 -32
View File
@@ -148,24 +148,6 @@ void RageBitmapTexture::Reload()
*/ */
SDL_Surface *RageBitmapTexture::CreateImg(int &pixfmt) SDL_Surface *RageBitmapTexture::CreateImg(int &pixfmt)
{ {
// look in the file name for a format hints
CString HintString = GetFilePath();
HintString.MakeLower();
if( HintString.Find("4alphaonly") != -1 ) m_ActualID.iTransparencyOnly = 4;
else if( HintString.Find("8alphaonly") != -1 ) m_ActualID.iTransparencyOnly = 8;
else if( HintString.Find("no alpha") != -1 ) m_ActualID.iAlphaBits = 0;
else if( HintString.Find("0alpha") != -1 ) m_ActualID.iAlphaBits = 0;
else if( HintString.Find("1 alpha") != -1 ) m_ActualID.iAlphaBits = 1;
else if( HintString.Find("1alpha") != -1 ) m_ActualID.iAlphaBits = 1;
if( HintString.Find("dither") != -1 ) m_ActualID.bDither = true;
if( m_ActualID.iTransparencyOnly )
{
/* Treat the image as 32-bit, so we don't lose any alpha precision. */
m_ActualID.iColorDepth = 32;
}
/* Load the image into an SDL surface. */ /* Load the image into an SDL surface. */
SDL_Surface *img = IMG_Load(GetFilePath()); SDL_Surface *img = IMG_Load(GetFilePath());
@@ -192,6 +174,35 @@ SDL_Surface *RageBitmapTexture::CreateImg(int &pixfmt)
SDL_SetColorKey( img, SDL_SRCCOLORKEY, color); SDL_SetColorKey( img, SDL_SRCCOLORKEY, color);
} }
{
/* This should eventually obsolete 8alphaonly, 0alpha and 1alpha,
* and remove the need to special case background loads. Do this
* after setting the color key for paletted images; it'll also return
* TRAIT_NO_TRANSPARENCY if the color key is never used. */
int traits = FindSurfaceTraits(img);
if(traits & TRAIT_NO_TRANSPARENCY) m_ActualID.iAlphaBits = 0;
else if(traits & TRAIT_BOOL_TRANSPARENCY) m_ActualID.iAlphaBits = 1;
if(traits & TRAIT_WHITE_ONLY) m_ActualID.iTransparencyOnly = 8;
}
// look in the file name for a format hints
CString HintString = GetFilePath();
HintString.MakeLower();
if( HintString.Find("4alphaonly") != -1 ) m_ActualID.iTransparencyOnly = 4;
else if( HintString.Find("8alphaonly") != -1 ) m_ActualID.iTransparencyOnly = 8;
// else if( HintString.Find("no alpha") != -1 ) m_ActualID.iAlphaBits = 0;
// else if( HintString.Find("0alpha") != -1 ) m_ActualID.iAlphaBits = 0;
// else if( HintString.Find("1 alpha") != -1 ) m_ActualID.iAlphaBits = 1;
// else if( HintString.Find("1alpha") != -1 ) m_ActualID.iAlphaBits = 1;
if( HintString.Find("dither") != -1 ) m_ActualID.bDither = true;
if( m_ActualID.iTransparencyOnly )
{
/* Treat the image as 32-bit, so we don't lose any alpha precision. */
m_ActualID.iColorDepth = 32;
}
GLenum fmtTexture; GLenum fmtTexture;
/* Figure out which texture format to use. */ /* Figure out which texture format to use. */
if( m_ActualID.iColorDepth == 16 ) if( m_ActualID.iColorDepth == 16 )
@@ -210,9 +221,6 @@ SDL_Surface *RageBitmapTexture::CreateImg(int &pixfmt)
/* Don't use more than we were hinted to. */ /* Don't use more than we were hinted to. */
src_alpha_bits = min( m_ActualID.iAlphaBits, src_alpha_bits ); src_alpha_bits = min( m_ActualID.iAlphaBits, src_alpha_bits );
/* XXX Scan the image, and see if it actually uses its alpha channel/color key
* (if any). Reduce to 1 or 0 bits of alpha if possible. */
switch( src_alpha_bits ) { switch( src_alpha_bits ) {
case 0: case 0:
case 1: case 1:
@@ -410,12 +418,17 @@ retry:
/* (don't change internalfmt) */ /* (don't change internalfmt) */
} }
/* Override the internalformat with an alpha format if it was requested. */ if(internalfmt != GL_COLOR_INDEX8_EXT)
if(m_ActualID.iTransparencyOnly == 4) {
internalfmt = GL_ALPHA4; /* Override the internalformat with an alpha format if it was requested.
else if(m_ActualID.iTransparencyOnly == 8) * Don't use iTransparencyOnly with paletted images; there's no point--paletted
internalfmt = GL_ALPHA8; * images are as small or smaller (and the load will fail). */
else ASSERT(m_ActualID.iTransparencyOnly == 0); if(m_ActualID.iTransparencyOnly == 4)
internalfmt = GL_ALPHA4;
else if(m_ActualID.iTransparencyOnly == 8)
internalfmt = GL_ALPHA8;
else ASSERT(m_ActualID.iTransparencyOnly == 0);
}
glTexImage2D(GL_TEXTURE_2D, 0, internalfmt, glTexImage2D(GL_TEXTURE_2D, 0, internalfmt,
m_iTextureWidth, m_iTextureHeight, 0, m_iTextureWidth, m_iTextureHeight, 0,
@@ -444,10 +457,17 @@ retry:
SDL_FreeSurface(img); SDL_FreeSurface(img);
CreateFrameRects(); CreateFrameRects();
CString props = " ";
// LOG->Trace( "RageBitmapTexture: Loaded '%s' (%ux%u) from disk. bStretch = %d, source %d,%d; image %d,%d.", if(m_ActualID.iAlphaBits == 0) props += "opaque ";
// m_sFilePath.GetString(), GetTextureWidth(), GetTextureHeight(), if(m_ActualID.iAlphaBits == 1) props += "matte ";
// bStretch, m_iSourceWidth, m_iSourceHeight, if(m_ActualID.iTransparencyOnly) props += "mask ";
// m_iImageWidth, m_iImageHeight); if(m_ActualID.bStretch) props += "stretch ";
if(m_ActualID.bDither) props += "dither ";
if(IsPackedPixelFormat(pixfmt)) props += "paletted ";
props.erase(props.size()-1);
LOG->Trace( "RageBitmapTexture: Loaded '%s' (%ux%u); %s, source %d,%d; image %d,%d.",
m_ActualID.filename.GetString(), GetTextureWidth(), GetTextureHeight(),
props.GetString(), m_iSourceWidth, m_iSourceHeight,
m_iImageWidth, m_iImageHeight);
} }
+108
View File
@@ -232,6 +232,7 @@ SDL_Surface *SDL_CreateRGBSurfaceSane
return SDL_CreateRGBSurface(flags, width, height, depth, return SDL_CreateRGBSurface(flags, width, height, depth,
Rmask, Gmask, Bmask, Amask); Rmask, Gmask, Bmask, Amask);
} }
static void FindAlphaRGB(const SDL_Surface *img, Uint8 &r, Uint8 &g, Uint8 &b, bool reverse) static void FindAlphaRGB(const SDL_Surface *img, Uint8 &r, Uint8 &g, Uint8 &b, bool reverse)
{ {
/* If we have no alpha or no color key, there's no alpha color. */ /* If we have no alpha or no color key, there's no alpha color. */
@@ -339,3 +340,110 @@ void FixHiddenAlpha(SDL_Surface *img)
SetAlphaRGB(img, r, g, b); SetAlphaRGB(img, r, g, b);
} }
/* XXX: currently only TRAIT_NO_TRANSPARENCY and TRAIT_BOOL_TRANSPARENCY work. */
/* Find various traits of a surface. Do these all at once, so we only have to
* iterate the surface once. */
/* We could theoretically do a test to see if an image fits in GL_ALPHA4,
* by looking at the least significant bits of each alpha value. This is
* not likely to ever find a match, though, so don't bother; only use 8alphaonly
* if it's explicitly enabled.
*
* XXX: We could do the FindAlphaRGB search here, too, but we need that information
* in a different place. */
// #define TRAIT_CONSISTENT_TRANSPARENT_COLOR 0x0008
int FindSurfaceTraits(const SDL_Surface *img)
// Uint8 AlphaColor[3])
{
// bool HaveAlphaValue = false; /* whether ar, ag, ab is valid */
// bool HaveConsistentAlphaValue = true;
bool HaveTransparency = false;
bool HaveTranslucensy = false;
// bool WhiteOnly = true;
for(int y = 0; y < img->h; ++y)
{
Uint8 *row = (Uint8 *)img->pixels + img->pitch*y;
// bool FirstVisible = true;
for(int x = 0; x < img->w; ++x)
{
Uint32 val = decodepixel(row, img->format->BytesPerPixel);
bool Transparent = false;
bool Translucent = false;
if( img->format->BitsPerPixel == 8 ) {
if(img->flags & SDL_SRCCOLORKEY && val == img->format->colorkey )
Transparent = true;
} else if(img->format->Amask) {
Uint32 masked_alpha = val & img->format->Amask;
if(masked_alpha == 0) Transparent = true;
else if(masked_alpha != img->format->Amask) Translucent = true;
}
if(Transparent) HaveTransparency = true;
if(Translucent) HaveTranslucensy = true;
#if 0
/* Hmm. This doesn't quite work. For example, the ScreenCompany
* shadow is actually black; we load it as 8alphaonly, which discards
* the black completely (making it a white shadow), and then we make
* it black again by setting the diffuse color to black. This is hard
* to generalize. I guess we could just make the shadow white, but
* that's a little ugly to edit.
*
* Also, for some reason, the font borders are actually a combination
* of a shade of gray and some alpha value. Those need to be simplified
* to white and some alpha value (multiply the luma by alpha), but
* that's another special case.
*
* So, this doesn't actually help anything right now, and we still
* need 8alphaonly. */
if( img->format->BitsPerPixel != 8 ) {
/* If the pixel isn't transparent, and isn't completely white: */
if(!Transparent &&
(val & img->format->Rmask) != img->format->Rmask &&
(val & img->format->Gmask) != img->format->Gmask &&
(val & img->format->Bmask) != img->format->Bmask)
WhiteOnly=false;
}
#endif
#if 0
/* Is this the first non-invisible pixel on this row? */
if(!Invisible && FirstVisible)
{
FirstVisible = false;
Uint8 r, g, b;
SDL_GetRGB(val, img->format, &r, &g, &b);
if(!HaveAlphaValue) {
/* We don't have the border color yet; set it. */
HaveAlphaValue = true;
AlphaColor[0] = r;
AlphaColor[1] = g;
AlphaColor[2] = b;
} else if(HaveConsistentAlphaValue) {
/* We already have an alpha color from the previous row;
* if it's not the same, it's inconsistent. */
if(r != AlphaColor[0] || g != AlphaColor[1] || b != AlphaColor[2])
HaveConsistentAlphaValue = false;
}
}
#endif
row += img->format->BytesPerPixel;
}
}
int ret = 0;
// if(HaveConsistentAlphaValue) ret |= TRAIT_CONSISTENT_TRANSPARENT_COLOR;
if(!HaveTransparency) ret |= TRAIT_NO_TRANSPARENCY;
if(!HaveTranslucensy) ret |= TRAIT_BOOL_TRANSPARENCY;
// if(WhiteOnly) ret |= TRAIT_WHITE_ONLY;
return ret;
}
+11
View File
@@ -28,6 +28,17 @@ SDL_Surface *SDL_CreateRGBSurfaceSane
void FixHiddenAlpha(SDL_Surface *img); void FixHiddenAlpha(SDL_Surface *img);
/* The surface contains no transparent pixels and/or never uses its color
* key, so it doesn't need any alpha bits at all. */
#define TRAIT_NO_TRANSPARENCY 0x0001 /* 0alpha */
/* The surface contains only transparent values of 0 or 1; no translucency.
* It only needs one bit of alpha. */
#define TRAIT_BOOL_TRANSPARENCY 0x0002 /* 1alpha */
/* All opaque pixels in this image are completely white, so it doesn't need
* any color bits at all; use a GL_ALPHA8 and only store the transparency. */
#define TRAIT_WHITE_ONLY 0x0004 /* 8alphaonly */
int FindSurfaceTraits(const SDL_Surface *img);
struct char_traits_Sint32: public char_traits<Sint32> struct char_traits_Sint32: public char_traits<Sint32>
{ {
static Sint32 *copy(Sint32 *s, const Sint32 *p, size_t n) static Sint32 *copy(Sint32 *s, const Sint32 *p, size_t n)