PNG Alpha Transparentcy

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?

Thanks,
Image

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.

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.

Thanks,

ChristianOn Fri, Dec 3, 2010 at 5:11 PM, image28 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?

Thanks,
Image


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

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 Friday 03 December 2010, at 23.38.13, Christian Leger <chrism.leger at gmail.com> wrote:

On Fri, Dec 3, 2010 at 5:11 PM, image28 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. :wink:


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

.— Games, examples, libraries, scripting, sound, music, graphics —.
| http://consulting.olofson.net http://olofsonarcade.com |
’---------------------------------------------------------------------’

It’s SDL 1.2, right? SDL_image does load the alpha channel. If you’re
using OpenGL, you will probably need to enable alpha blending with
glEnable(GL_BLEND).

Jonny DOn Fri, Dec 3, 2010 at 5:38 PM, 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.

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.

Thanks,

Christian

On Fri, Dec 3, 2010 at 5:11 PM, image28 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?

Thanks,
Image


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org

I tried a few different file formats, want it to work for png files, but I tried tga in that copy of the source…

Also I tried changing the blendfunc from GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA to GL_ONE,GL_ONE which kind of worked, the background was blended out, but when objects passed over each other they were opaque… you could see the second object through the first.

also I was playing around and changed glColor4ub(0,0,0,255); to glColor4ub(0,0,0,128); based on what someone said to try on another thread. didn’t work

Got a mail saying my message was rejected because it was too big… so heres the relevant parts of the source code.

void SDL_GL_Enter2DMode()
{
SDL_Surface *screen = SDL_GetVideoSurface();

/* Note, there may be other things you need to change,
   depending on how you have your OpenGL state set up.
*/
glPushAttrib(GL_ENABLE_BIT);
glDisable(GL_DEPTH_TEST);
glDisable(GL_CULL_FACE);
glEnable(GL_TEXTURE_2D);

/* This allows alpha blending of 2D textures with the scene */
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

glViewport(0, 0, screen->w, screen->h);

glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();

glOrtho(0.0, (GLdouble)screen->w, (GLdouble)screen->h, 0.0, 0.0, 1.0);

glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glColor4ub(0,0,0,255);

}

GLuint SDL_GL_LoadTexture(SDL_Surface *surface, GLfloat *texcoord)
{
GLuint texture;
int w, h;
SDL_Surface *image;
SDL_Rect area;
Uint32 saved_flags;
Uint8 saved_alpha;

/* Use the surface width and height expanded to powers of 2 */
w = power_of_two(surface->w);
h = power_of_two(surface->h);
texcoord[0] = 0.0f;			/* Min X */
texcoord[1] = 0.0f;			/* Min Y */
texcoord[2] = (GLfloat)surface->w / w;	/* Max X */
texcoord[3] = (GLfloat)surface->h / h;	/* Max Y */

image = SDL_CreateRGBSurface(
		SDL_SWSURFACE,
		w, h,
		32,

#if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */
0x000000FF,
0x0000FF00,
0x00FF0000,
0xFF000000
#else
0xFF000000,
0x00FF0000,
0x0000FF00,
0x000000FF
#endif
);
if ( image == NULL ) {
return 0;
}

/* Save the alpha blending attributes */
saved_flags = surface->flags&(SDL_SRCALPHA|SDL_RLEACCELOK);
saved_alpha = surface->format->alpha;
if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
	SDL_SetAlpha(surface, 0, 0);
}

/* Copy the surface into the GL texture image */
area.x = 0;
area.y = 0;
area.w = surface->w;
area.h = surface->h;
SDL_BlitSurface(surface, &area, image, &area);

/* Restore the alpha blending attributes */
if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) {
	SDL_SetAlpha(surface, saved_flags, saved_alpha);
	//SDL_SetAlpha(surface, 0, SDL_ALPHA_TRANSPARENT);
}

/* Create an OpenGL texture for the image */
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D,
	     0,
	     GL_RGBA,
	     w, h,
	     0,
	     GL_RGBA,
	     GL_UNSIGNED_BYTE,
	     image->pixels);
SDL_FreeSurface(image); /* No longer needed */

return texture;

}

void DrawLogoCursor(void)
{
static GLfloat texMinX, texMinY;
static GLfloat texMaxX, texMaxY;
static int w, h;
int x, y;

if ( ! cursor_texture ) {
	SDL_Surface *image;
	GLfloat texcoord[4];

	/* Load the image (could use SDL_image library here) */
	image = IMG_Load(LOGO_FILE);
	if ( image == NULL ) {
		return;
	}
	w = image->w;
	h = image->h;

	/* Convert the image into an OpenGL texture */
	cursor_texture = SDL_GL_LoadTexture(image, texcoord);

	/* Make texture coordinates easy to understand */
	texMinX = texcoord[0];
	texMinY = texcoord[1];
	texMaxX = texcoord[2];
	texMaxY = texcoord[3];

	/* We don't need the original image anymore */
	SDL_FreeSurface(image);

	/* Make sure that the texture conversion is okay */
	if ( ! cursor_texture ) {
		return;
	}
}

/* Move the image around */
SDL_GetMouseState(&x, &y);
x -= w/2;
y -= h/2;

/* Show the image on the screen */
SDL_GL_Enter2DMode();
glBindTexture(GL_TEXTURE_2D, cursor_texture);
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2f(texMinX, texMinY); glVertex2i(x,   y  );
glTexCoord2f(texMaxX, texMinY); glVertex2i(x+w, y  );
glTexCoord2f(texMinX, texMaxY); glVertex2i(x,   y+h);
glTexCoord2f(texMaxX, texMaxY); glVertex2i(x+w, y+h);
glEnd();
SDL_GL_Leave2DMode();

}