Hi all,
Okay, I’ve tracked down the offending statement. This appears
to be an SDL bug, since it doesn’t seem to agree with the
descriptions I’ve received on this list.
At the bottom of the message you will find a snippet of code
with a blow-by-blow description of what happens, but basically
it comes down to this:
SUMMARY:
SDL_BlitSurface() does not do a correct alpha blit from an RGBA
alpha surface to an RGBA alpha surface. Instead, all RGB
data are blitted correctly, but the alpha data is lost. The
destination image is left with alpha = 0x00 for all pixels,
regardless of the alpha channel information in the source
image.
This occurs for the specific case of two SDL_SWSURFACE 32-bit
RGBA surfaces. I have not verified all other cases. However,
blitting the source to the screen surface (i.e. the one returned
by SDL_SetVideoMode() appears to work correctly (thank goodness,
otherwise debugging would’ve been really hard!).
If one first converts the destination surface to the screen
format, using SDL_DisplayFormat(), the problem is evaded and
the program works as expected (This is my recommended work-around,
and I’ll probably use this to fix my program).
Turning off SDL_SRCALPHA by using SDL_SetAlpha() “fixes” the
blit in a somewhat trivial way (since the alpha channel will
just be thrown away). Interestingly, you can’t do this by
simply omitting the SDL_SRCALPHA flag, you have to force it
down if you provided a mask for the alpha channel.
Thank you,
Terry Hancock
Mattias Engdeg?rd wrote:
- An 32-bit RGBA surface (with SDL_SRCALPHA – possibly the
result from the above operation) is blitted onto another
32-bit RGBA surface which may be blank/transparent, or may
have previous RGBA data in it.In the transparent case, the result should be essentially
identical to the source RGBA image. In the case where
there was previously data, the previous (dest) data would
show through wherever the source image is transparent
(in my particular example, there’s no partial transparency,
but there could be in principle).since you are using SRCALPHA, the operation is to alpha-blend the
source onto the destination, as if the destination was opaque
(destination alpha channel is not used in the process and is kept
unchanged).if you want to just copy the contents, alpha and all, to another
RGBA surface, make sure SDL_SRCALPHA is not set on the source
surface
LIBRARIES:
SDL 1.1.8
SDL Image 1.1.0
SGE 1.2.24 (this doesn’t appear to involve SGE code, though)
CODE SNIPPET:
Here’s the relevant piece of source code. The problem occurs
in the call marked with “***********” and “PROBLEM HERE” :
//
// Excerpted example code with results:
SDL_Surface *screen;
SDL_Surface *org, *cel, *layer, *layup;
// Naturally we had to declare all the code --
// initial and final code are omitted here
org = IMG_Load(“Background/arbor.set1.c1.fount.gif”);
seeSDL_info(org, “original”);
seeSDL_transparency(org);
// We view the information & transparency on this image as
// loaded by SDL Image library.
//
// 8-Bit Palette image. Color keyed. No alpha channel.
cel = SDL_CreateRGBSurface( SDL_SWSURFACE|SDL_SRCALPHA, 800, 600,
32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
// Fresh surface: 32-bit RGBA alpha surface
// black + transparent everywhere.
istat = -1000;
istat = SDL_BlitSurface(org, NULL, cel, NULL);
printf(“org->cel blit returns: %d\n”, istat);
// Now we blit the color keyed original onto the alpha
// surface. This works.
seeSDL_info(cel, “cel”); /* Check cel is okay first. */
seeSDL_transparency(cel);
// "cel" is RGBA alpha surface.
// Contains RGB picture data from original.
// alpha channel is converted
// from original color-key, so where the colorkey color
// was in the original is filled with 0x00000000, i.e.
// black + fully transparent.
layer = SDL_CreateRGBSurface( SDL_SWSURFACE|SDL_SRCALPHA, 800, 600,
32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
// Another fresh RGBA 32-bit alpha surface
//*****************************************************************
istat = -1000;
istat = SDL_BlitSurface(cel, NULL, layer, NULL); // PROBLEM HERE
printf(“cel->layer blit returns: %d\n”, istat);
//*****************************************************************
// This should do an alpha blit of the cel RGBA surface
// onto the layer RGBA surface.
// This DOES NOT WORK, as we shall see.
//sge_rotate_scaled(layer, cel, 600, 320, 30, 1.5);
// This alternative, which works pixel-by-pixel, but doesn’t
// support alpha blending, works as expected.
seeSDL_info(layer, “layer”);
seeSDL_transparency(layer);
// Now we see the problem, the resulting image is transparent
// everywhere (alpha channel is 0x00 for all pixels), despite
// the blit operation, which should have carried opaque
// pixels from the cel, resulting in opaque pixels here.
SDL_SetColorKey(org, 0, 0x00);
SDL_BlitSurface(org, NULL, screen, NULL);
sge_UpdateRect(screen, 0,0,0,0);
// This shows the original image, with the color key shut
// off to produce an opaque blit. Because the colorkey was
// visible (a light tan color), it provides a background for
// the next blit.
//SDL_SetAlpha(layer, 0, 0xFF); /* Force opaque display */
SDL_SetAlpha(layer, 0, 0xFF); /* Force opaque display */
SDL_BlitSurface(layer, NULL, screen, NULL);
sge_UpdateRect(screen, 0,0,0,0);
// As is, this blit does nothing -- this is the correct behavior
// for a surface with transparent alpha in all pixels, so it
// simply shows the error in the cel->layer blit.
//
// However, we can verify that the RGB data was blitted by
// turning off the SDL_SRCALPHA flag for this surface before
// displaying it (note the commented-out SetAlpha statement).
OUTPUT:
The seeSDL_info() functions spits out some info about flag states
and surface properties, the calls listed above produce the following
output:
Surface " original"
800 x 606 x 8 [-][-][KEY][—][-----]
Color Key = ( E6 DF C5 ) Per-Surface Alpha = FF
Masks: R=00000000 G=00000000 B=00000000 A=00000000
Number of Colors in Palette: 256-----------------------
org->cel blit returns: 0
Surface " cel"
800 x 600 x 32 [-][-][—][—][ALPHA]
Color Key = ( 00 00 00 ) Per-Surface Alpha = FF
Masks: R=FF000000 G=00FF0000 B=0000FF00 A=000000FF
cel->layer blit returns: 0
Surface " layer"
800 x 600 x 32 [-][-][—][—][ALPHA]
Color Key = ( 00 00 00 ) Per-Surface Alpha = FF
Masks: R=FF000000 G=00FF0000 B=0000FF00 A=000000FF
–
Terry Hancock
@Terry_Hancock