Followers 0

# PNGs with transparency in SDL.

## 6 posts in this topic

I'm drawing some PNGs with transparency in SDL (using SDL_BlitSurface(), which works just fine), but I'm having problems with changing the alpha values (to fade the image in/out).

I've tried doing something like this for all the pixels:

*pixel = SDL_MapRGBA(image->format, r, g, b, a);


Changing the value for "a" in the call to SDL_MapRGBA() works as expected on PNG files without transparency, but if the image has transparency, I instead end up with this:

Here, "a" was set to 255. Changing the alpha still works (changes the opacity), but it's like all the pixels have been replaced by black ones, except for the 40 lines of pixels at the top, which are white.

Any idea what's going on?
0

##### Share on other sites
Maybe you should posts some more code.
0

##### Share on other sites
Alright.

I set the video mode like this:
screen = SDL_SetVideoMode(800, 600, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);


Then I load an image using SDL_image:
SDL_Surface* temp  = IMG_Load(file.c_str());
SDL_Surface* image = SDL_DisplayFormatAlpha(temp);


Then I draw it to the screen:
SDL_BlitSurface(source, NULL, destination, NULL);


This works fine, transparency and everything. If I load a .png without transparency (or a .bmp or whatever) I can play around with the alpha bits and it works fine, but like I said, if I try that with a .png with transparency, everything gets screwed up.
0

##### Share on other sites
I could start throwing guesses at you but it would be easier if you posted the whole code if it's not too long.
0

##### Share on other sites
#include <sdl.h>
#include <sdl_image.h>

void applySurface(SDL_Surface* source, SDL_Surface* destination, int x, int y)
{
SDL_Rect offset;

offset.x = x;
offset.y = y;

SDL_BlitSurface(source, NULL, destination, &offset);
}

{
SDL_Surface* image = SDL_DisplayFormatAlpha(temp);
SDL_FreeSurface(temp);

return(image);
}

int main(int argc, char* argv[])
{
SDL_Init(SDL_INIT_EVERYTHING);

SDL_Surface* screen(nullptr);
screen = SDL_SetVideoMode(800, 600, 32, SDL_HWSURFACE | SDL_DOUBLEBUF);

SDL_ShowCursor(SDL_DISABLE);

bool done(false);
SDL_Event event;

while(!done)
{
while(SDL_PollEvent(&event))
{
if(event.type == SDL_QUIT || (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE))
{
done = true;
}
}

applySurface(bg, screen, 0, 0);

static Uint8 alpha(0);

for(int y(0); y < img1->h; ++y)
{
for(int x(0); x < img1->w; ++x)
{
Uint32* pixel = (Uint32*)img1->pixels + (x + y * img1->w);

Uint8 r;
Uint8 g;
Uint8 b;
Uint8 a;

SDL_GetRGBA(*pixel, img1->format, &r, &g, &b, &a);
*pixel = SDL_MapRGBA(screen->format, r, g, b, alpha);
}
}

++alpha;

applySurface(img1, screen, 0, 0);

SDL_Flip(screen);
}

SDL_Quit();

return(0);
}


I've tried several different ways of changing the alpha value, but all with the same result.
0

##### Share on other sites
You are passing the wrong format to SDL_MapRGBA. screen->format should be img1->format.

When you set the alpha value for each pixel you are ignoring the alpha values that the image was saved as so you will see pixels that are not supposed to be seen.

To not destroy the original alpha values you could draw to the screen surface directly. If you change alpha to a floating point type and slowly change it from 0 to 1 and do something like this inside the loop
*screenPixel = SDL_MapRGBA(screen->format, r, g, b, a * alpha);
I think you will get the effect you want.

Another way I thought would work was to set the per-surface alpha value using SDL_SetAlpha but that doesn't appear to work.
2

##### Share on other sites

To not destroy the original alpha values you could draw to the screen surface directly. If you change alpha to a floating point type and slowly change it from 0 to 1 and do something like this inside the loop

*screenPixel = SDL_MapRGBA(screen->format, r, g, b, a * alpha);
I think you will get the effect you want.

Yes, that works. Thank you.

0

## Create an account

Register a new account