[SDL] PNG Alpha Transparentcy

David Olofson david at olofson.net
Fri Dec 3 17:41:26 PST 2010


On Friday 03 December 2010, at 23.38.13, Christian Leger 
<chrism.leger at gmail.com> wrote:
> Hi,
> 
> I've had this exact problem. I don't even know whether or not the SDL_image
> libs support keeping the alpha when loading png's.

It does - at least, any versions I've used.


> What I've done is to write a simple conversion function which takes a
> 24-bit image and converts it to a 32-bit image, assigning alpha of 255
> everywhere that the image isn't black, and alpha of 0 everywhere else. If
> that sounds like code you could use, I'll gladly send it over.

I don't see why you'd need to do that - unless the images lack transparency 
info altogether. If there is an alpha channel, just use it - and get anti-
aliasing and translucency support as free bonuses! ;-)


> On Fri, Dec 3, 2010 at 5:11 PM, image28 <image28 at slingshot.co.nz> wrote:
> >  I replaced the line SDL_LoadBMP with SDL-image's IMG_Load function in
> >  the
> > 
> > testgl.c program from the tests folder in the SDL source package.
> > But the image no long shows up transparent, it has a black background
> > around it. I made the transparent png file with the gimp... Any ideas?

There are a few things you need to do on the OpenGL side. Obviously, you need 
to enable blending, and you need to set up a suitable blending mode, for 
example:

	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);


For the alpha channel part to work (and not just vertex alpha modulation), you 
also need to get the alpha channel into the texture; something like:

	glTexImage2D(GL_TEXTURE_2D, 0,
			img->flags & SG_IMAGE_ALPHA ? GL_RGBA8 : GL_RGB8,
			s->w, s->h, 0,
			s->format->Amask ? GL_RGBA : GL_RGB,
			GL_UNSIGNED_BYTE, (char *)s->pixels);

This expects an SDL surface that is either 24 or 32 bit, in the endian format 
expected by OpenGL. SG_IMAGE_ALPHA is a flag that is 1 if the alpha channel is 
to actually be *used* - and if the alpha channel is not desired, it's just 
dropped in the upload by selecting an internal texture format without an alpha 
channel.


Speaking of endian and stuff, you can't really depend on IMG_Load() to return 
a surface with any particular pixel format, so doing something like this might 
be a good idea:

SG_enum sgf_Prepare(SG_image *img, SG_filter_args *args)
{
	SDL_Surface *tmp;
	SDL_PixelFormat fmt;
	memset(&fmt, 0, sizeof(fmt));
	fmt.BitsPerPixel = 32;
	fmt.BytesPerPixel = 4;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
	fmt.Rmask = 0xff000000;
	fmt.Gmask = 0x00ff0000;
	fmt.Bmask = 0x0000ff00;
	fmt.Amask = 0x000000ff;
#else
	fmt.Rmask = 0x000000ff;
	fmt.Gmask = 0x0000ff00;
	fmt.Bmask = 0x00ff0000;
	fmt.Amask = 0xff000000;
#endif
	tmp = SDL_ConvertSurface(img->surface, &fmt, SDL_SWSURFACE);
	if(!tmp)
		return SG_MEMORY;
	SDL_FreeSurface(img->surface);
	img->surface = tmp;
	img->w = tmp->w;
	img->h = tmp->h;
	if(img->surface->flags & SDL_SRCALPHA)
		img->flags |= SG_IMAGE_ALPHA;
	return 0;
}


And as you can see, this is where that SG_IMAGE_ALPHA flag is coming from. 
Also note that this will only ever return RGBA surfaces, as that's all my 
image processing filters support. You may want to add RGB support if it 
matters, though it only affects the intermediate surfaces - not the OpenGL 
textures.


If you still can't make it work, I'm quite sure someone on this list will spot 
the problem quickly with some code to look at. ;-)


-- 
//David Olofson - Consultant, Developer, Artist, Open Source Advocate

.--- Games, examples, libraries, scripting, sound, music, graphics ---.
|   http://consulting.olofson.net          http://olofsonarcade.com   |
'---------------------------------------------------------------------'
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20101204/d082a174/attachment-0008.htm>


More information about the SDL mailing list