Problem with alpha blending

I’m having some trouble with blitting one surface onto another and alpha blending. Specifically, when both surfaces have an alpha channel, and the source surface has SDL_SRCALPHA set, the destination surface seems to have its alpha channel zeroed out.

This is despite the SDL documentation describing such blits in this way:–
RGBA->RGBA with SDL_SRCALPHA

The source is alpha-blended with the destination using the source alpha channel. The alpha channel in the destination surface is left untouched. SDL_SRCCOLORKEY is ignored.

I have written a small test case demonstrating this problem, which I have appended to this email. The test case loads two images, sets SDL_SRCALPHA, and blits one onto the other. Then the destination surface is blit onto the screen. The image does not appear on the screen, presumably because its alpha channel has been zeroed.

The two images I have used for testing this are available at http://www.wesnoth.org/testing/grassland.png and http://www.wesnoth.org/testing/fog.png

Just save the images in the directory the test case is to be executed from before executing it.

I have tested this on SDL 1.2.7 on Windows and on Linux. Any help would be appreciated.

David White
Lead Developer
Battle for Wesnoth (http://www.wesnoth.org)


#include “SDL.h”
#include “SDL_image.h”

#include <stdio.h>

int main(int argc, char** argv)
{
SDL_Surface *fb, *fog, *grass;

if(SDL_Init(SDL_INIT_VIDEO) == -1) {
fprintf(stderr,“Could not initialize SDL\n”);
return -1;
}

fb = SDL_SetVideoMode(800, 600, 16, 0);
if(fb == NULL) {
fprintf(stderr,“Could not set the video mode\n”);
return -1;
}

/set the screen to a distinctive color, to make it clear
that the image has an alpha value of 0
/
SDL_FillRect(fb,NULL,SDL_MapRGB(fb->format,255,0,0));

fog = IMG_Load(“fog.png”);
if(fog != NULL) {
fog = SDL_DisplayFormatAlpha(fog);
}

grass = IMG_Load(“grassland.png”);
if(grass != NULL) {
grass = SDL_DisplayFormatAlpha(grass);
}

if(grass == NULL || fog == NULL) {
fprintf(stderr,“Could not load images\n”);
return -1;
}

/the following line sets ‘fog’ to use SDL_SRCALPHA, but
this seems to corrupt the alpha channel of surfaces ‘fog’ is
blitted onto
/
SDL_SetAlpha(fog,SDL_SRCALPHA|SDL_RLEACCEL,SDL_ALPHA_OPAQUE);
SDL_SetAlpha(grass,SDL_SRCALPHA|SDL_RLEACCEL,SDL_ALPHA_OPAQUE);

/blit fog onto grass/
SDL_BlitSurface(fog,NULL,grass,NULL);

/blit grass onto the screen - but now it will have a zeroed alpha channel/
SDL_BlitSurface(grass,NULL,fb,NULL);
SDL_Flip(fb);

SDL_Delay(1000);

SDL_Quit();

return 0;
}

Ok I looked at you code (after cleaning the html2text mess) and creating a gcc
command for it

gcc sdltest.c -L/usr/lib -lSDL -lpthread -I/usr/include/SDL -D_REENTRANT
-lSDL_image
(yours could be different check your sdl-config, maybe pointless to write this
in the sdl lib but …)

All I got is a red screen… so you are right intead of blitting the images
with the correct alpha it uses a the wrong one.
This is the cleaned code:-----------------------
#include “SDL.h”
#include “SDL_image.h”

#include <stdio.h>

int main(int argc, char** argv)
{
SDL_Surface *fb, *fog, *grass;

if(SDL_Init(SDL_INIT_VIDEO) == -1) {
fprintf(stderr,“Could not initialize SDL\n”);
return -1;
}

fb = SDL_SetVideoMode(800, 600, 16, 0);
if(fb == NULL) {
fprintf(stderr,“Could not set the video mode\n”);
return -1;
}

/set the screen to a distinctive color, to make it clear
that the image has an alpha value of 0
/
SDL_FillRect(fb,NULL,SDL_MapRGB(fb->format,255,0,0));

fog = IMG_Load(“fog.png”);
if(fog != NULL) {
fog = SDL_DisplayFormatAlpha(fog);
}

grass = IMG_Load(“grassland.png”);
if(grass != NULL) {
grass = SDL_DisplayFormatAlpha(grass);
}

if(grass == NULL || fog == NULL) {
fprintf(stderr,“Could not load images\n”);
return -1;
}

/the following line sets ‘fog’ to use SDL_SRCALPHA, but
this seems to corrupt the alpha channel of surfaces ‘fog’ is
blitted onto
/
SDL_SetAlpha(fog,SDL_SRCALPHA|SDL_RLEACCEL,SDL_ALPHA_OPAQUE);
SDL_SetAlpha(grass,SDL_SRCALPHA|SDL_RLEACCEL,SDL_ALPHA_OPAQUE);

/blit fog onto grass/
SDL_BlitSurface(fog,NULL,grass,NULL);

/blit grass onto the screen - but now it will have a zeroed alpha =
channel
/
SDL_BlitSurface(grass,NULL,fb,NULL);
SDL_Flip(fb);

SDL_Delay(1000);

SDL_Quit();

return 0;
}

David White wrote:

I’m having some trouble with blitting one surface onto another and alpha =
blending. Specifically, when both surfaces have an alpha channel, and =
the source surface has SDL_SRCALPHA set, the destination surface seems =
to have its alpha channel zeroed out.

This is despite the SDL documentation describing such blits in this way:


RGBA->RGBA with SDL_SRCALPHA=20

The source is alpha-blended with the destination using the source alpha =
channel. The alpha channel in the destination surface is left untouched. =
SDL_SRCCOLORKEY is ignored.

I have written a small test case demonstrating this problem, which I =
have appended to this email. The test case loads two images, sets =
SDL_SRCALPHA, and blits one onto the other. Then the destination surface =
is blit onto the screen. The image does not appear on the screen, =
presumably because its alpha channel has been zeroed.

The two images I have used for testing this are available at =
http://www.wesnoth.org/testing/grassland.png and =
http://www.wesnoth.org/testing/fog.png

Just save the images in the directory the test case is to be executed =
from before executing it.

I have tested this on SDL 1.2.7 on Windows and on Linux. Any help would =
be appreciated.

David White
Lead Developer
Battle for Wesnoth (http://www.wesnoth.org)


Arsfortunata
http://arsfortunata.com/