Jump to content

  • Log In with Google      Sign In   
  • Create Account


PNGs with transparency in SDL.


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
6 replies to this topic

#1 brakhage   Members   -  Reputation: 104

Like
0Likes
Like

Posted 09 July 2013 - 01:10 PM

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:
 
lolwut.jpg
 
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?

Sponsor:

#2 Wooh   Members   -  Reputation: 591

Like
0Likes
Like

Posted 09 July 2013 - 02:46 PM

Maybe you should posts some more code.

#3 brakhage   Members   -  Reputation: 104

Like
0Likes
Like

Posted 09 July 2013 - 03:14 PM

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.

#4 Wooh   Members   -  Reputation: 591

Like
0Likes
Like

Posted 09 July 2013 - 04:14 PM

I could start throwing guesses at you but it would be easier if you posted the whole code if it's not too long.

#5 brakhage   Members   -  Reputation: 104

Like
0Likes
Like

Posted 09 July 2013 - 10:55 PM

#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* loadImage(std::string file)
{
    SDL_Surface* temp = IMG_Load(file.c_str());
    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);

    SDL_Surface* bg = loadImage("data/bg.png");
    SDL_Surface* img1 = loadImage("data/img1.png");

    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.

#6 Wooh   Members   -  Reputation: 591

Like
2Likes
Like

Posted 10 July 2013 - 02:44 AM

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.

#7 brakhage   Members   -  Reputation: 104

Like
0Likes
Like

Posted 10 July 2013 - 07:08 AM

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. smile.png






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS