Sign in to follow this  
Noegddgeon

Lazy Foo SDL Program, Color-Keying

Recommended Posts

Noegddgeon    134
Hello, everybody. I have just finished compiling and running the source code for this SDL program: http://lazyfoo.net/SDL_tutorials/lesson05/index.php It basically color keys a sprite and adds it on top of a background image to demonstrate the concept. However, I ran the source code on my Mac, using XCode 3.1.4, and the image instead showed up with the blue rectangle around it, having not been color keyed. Thus, it wasn't a compile-time error of any kind. I was wondering if perhaps anyone else could compile the source code or spot just in the source code which I will post just below what the problem may be. I appreciate everyone's time:
/*This source code copyrighted by Lazy Foo' Productions (2004-2009) and may not
be redestributed without written permission.*/

//The headers
#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include <string>

//Screen attributes
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;

//The surfaces
SDL_Surface *background = NULL;
SDL_Surface *foo = NULL;
SDL_Surface *screen = NULL;

//The event structure
SDL_Event event;

SDL_Surface *load_image( std::string filename )
{
    //The image that's loaded
    SDL_Surface* loadedImage = NULL;

    //The optimized image that will be used
    SDL_Surface* optimizedImage = NULL;

    //Load the image
    loadedImage = IMG_Load( filename.c_str() );

    //If the image loaded
    if( loadedImage != NULL )
    {
        //Create an optimized image
        optimizedImage = SDL_DisplayFormat( loadedImage );

        //Free the old image
        SDL_FreeSurface( loadedImage );

        //If the image was optimized just fine
        if( optimizedImage != NULL )
        {
            //Map the color key
            Uint32 colorkey = SDL_MapRGB( optimizedImage->format, 0, 0xFF, 0xFF );

            //Set all pixels of color R 0, G 0xFF, B 0xFF to be transparent
            SDL_SetColorKey( optimizedImage, SDL_SRCCOLORKEY, colorkey );
        }
    }

    //Return the optimized image
    return optimizedImage;
}

void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination )
{
    //Temporary rectangle to hold the offsets
    SDL_Rect offset;

    //Get the offsets
    offset.x = x;
    offset.y = y;

    //Blit the surface
    SDL_BlitSurface( source, NULL, destination, &offset );
}

bool init()
{
    //Initialize all SDL subsystems
    if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )
    {
        return 1;
    }

    //Set up the screen
    screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );

    //If there was an error in setting up the screen
    if( screen == NULL )
    {
        return 1;
    }

    //Set the window caption
    SDL_WM_SetCaption( "Foo says \"Hello!\"", NULL );

    //If everything initialized fine
    return true;
}

bool load_files()
{
    //Load the background image
    background = load_image( "background.png" );

    //If the background didn't load
    if( background == NULL )
    {
        return false;
    }

    //Load the stick figure
    foo = load_image( "foo.png" );

    //If the stick figure didn't load
    if( foo == NULL )
    {
        return false;
    }

    return true;
}

void clean_up()
{
    //Free the surfaces
    SDL_FreeSurface( background );
    SDL_FreeSurface( foo );

    //Quit SDL
    SDL_Quit();
}

int main( int argc, char* args[] )
{
    //Quit flag
    bool quit = false;

    //Initialize
    if( init() == false )
    {
        return 1;
    }

    //Load the files
    if( load_files() == false )
    {
        return 1;
    }

    //Apply the surfaces to the screen
    apply_surface( 0, 0, background, screen );
    apply_surface( 240, 190, foo, screen );

    //Update the screen
    if( SDL_Flip( screen ) == -1 )
    {
        return 1;
    }

    //While the user hasn't quit
    while( quit == false )
    {
        //While there's events to handle
        while( SDL_PollEvent( &event ) )
        {
            //If the user has Xed out the window
            if( event.type == SDL_QUIT )
            {
                //Quit the program
                quit = true;
            }
        }
    }

    //Free the surfaces and quit SDL
    clean_up();

    return 0;
}

Colton [Edited by - Noegddgeon on February 14, 2010 4:37:16 PM]

Share this post


Link to post
Share on other sites
Noegddgeon    134
I tried it with another program, this one:


/*This source code copyrighted by Lazy Foo' Productions (2004-2009) and may not
be redestributed without written permission.*/


//The headers
#include "SDL.h"
#include "SDL_image/SDL_image.h"
#include <string>
#include <iostream>

using namespace std;

//Screen attributes
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;

//The surfaces
SDL_Surface *dots = NULL;
SDL_Surface *screen = NULL;

//The event structure
SDL_Event event;

//The portions of the sprite map to be blitted
SDL_Rect clip[ 4 ];

SDL_Surface *load_image( std::string filename )
{
//The image that's loaded
SDL_Surface* loadedImage = NULL;

//The optimized surface that will be used
SDL_Surface* optimizedImage = NULL;

//Load the image
loadedImage = IMG_Load( filename.c_str() );

//If the image loaded
if( loadedImage != NULL )
{
//Create an optimized surface
optimizedImage = SDL_DisplayFormat( loadedImage );

//Free the old surface
SDL_FreeSurface( loadedImage );

//If the surface was optimized
if( optimizedImage != NULL )
{
//Color key surface
if (SDL_SetColorKey( optimizedImage, SDL_SRCCOLORKEY, SDL_MapRGB( optimizedImage->format, 0, 0xFF, 0xFF )) == -1);
{
cout << "Error: Cannot use color key, reason: ";
cout << SDL_GetError() << endl;
}
}

}

//Return the optimized surface
return optimizedImage;
}

void apply_surface( int x, int y, SDL_Surface* source, SDL_Surface* destination, SDL_Rect* clip = NULL )
{
//Holds offsets
SDL_Rect offset;

//Get offsets
offset.x = x;
offset.y = y;

//Blit
SDL_BlitSurface( source, clip, destination, &offset );
}

bool init()
{
//Initialize all SDL subsystems
if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 )
{
return false;
}

//Set up the screen
screen = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE );

//If there was an error in setting up the screen
if( screen == NULL )
{
return false;
}

//Set the window caption
SDL_WM_SetCaption( "Split the dots", NULL );

//If everything initialized fine
return true;
}

bool load_files()
{
//Load the sprite map
dots = load_image( "dots.png" );

//If there was an problem loading the sprite map
if( dots == NULL )
{
return false;
}

//If eveything loaded fine
return true;
}

void clean_up()
{
//Free the sprite map
SDL_FreeSurface( dots );

//Quit SDL
SDL_Quit();
}

int main( int argc, char* args[] )
{
//Quit flag
bool quit = false;

//Initialize
if( init() == false )
{
return 1;
}

//Load the files
if( load_files() == false )
{
return 1;
}

//Clip range for the top left
clip[ 0 ].x = 0;
clip[ 0 ].y = 0;
clip[ 0 ].w = 100;
clip[ 0 ].h = 100;

//Clip range for the top right
clip[ 1 ].x = 100;
clip[ 1 ].y = 0;
clip[ 1 ].w = 100;
clip[ 1 ].h = 100;

//Clip range for the bottom left
clip[ 2 ].x = 0;
clip[ 2 ].y = 100;
clip[ 2 ].w = 100;
clip[ 2 ].h = 100;

//Clip range for the bottom right
clip[ 3 ].x = 100;
clip[ 3 ].y = 100;
clip[ 3 ].w = 100;
clip[ 3 ].h = 100;

//Fill the screen white
SDL_FillRect( screen, &screen->clip_rect, SDL_MapRGB( screen->format, 0xFF, 0xFF, 0xFF ) );

//Apply the sprites to the screen
apply_surface( 0, 0, dots, screen, &clip[ 0 ] );
apply_surface( 540, 0, dots, screen, &clip[ 1 ] );
apply_surface( 0, 380, dots, screen, &clip[ 2 ] );
apply_surface( 540, 380, dots, screen, &clip[ 3 ] );

//Update the screen
if( SDL_Flip( screen ) == -1 )
{
return 1;
}

//While the user hasn't quit
while( quit == false )
{
//While there's events to handle
while( SDL_PollEvent( &event ) )
{
//If the user has Xed out the window
if( event.type == SDL_QUIT )
{
//Quit the program
quit = true;
}
}
}

//Free the images and quit SDL
clean_up();

return 0;
}



I added the error check myself, and it comes up saying that there is, indeed, an error present at the point where it assigns the color key with the line:

if (SDL_SetColorKey( optimizedImage, SDL_SRCCOLORKEY, SDL_MapRGB( optimizedImage->format, 0, 0xFF, 0xFF )) == -1)


It's not letting me set the color key. I'm trying to investigate why this may be the problem, but until then I would greatly appreciate any help possible. O:] Thank you very much.

Colton

Share this post


Link to post
Share on other sites
evillive2    779
From the initial post I would say it is an issue where once the image was converted to the display format the color (0x00,0xff,0xff) used for the color key is not matching the converted color.

Try getting the value of a pixel and see if it matches what you think it should.

From the second post it appears that it could be one of the following:
SDL_Image is not initialized properly (IMG_Init)
The initial image file has not loaded properly

Share this post


Link to post
Share on other sites
Noegddgeon    134
Unfortunately, SDL_GetError() isn't actually returning any sort of error, even though the function isn't working properly. I added this to the first program:


//Map the color key
Uint32 colorkey = SDL_MapRGB( optimizedImage->format, 0x00, 0xFF, 0xFF );

cout << "Color key is: ";
cout << colorkey << endl;

//Set all pixels of color R 0, G 0xFF, B 0xFF to be transparent

if (SDL_SetColorKey( optimizedImage, SDL_SRCCOLORKEY, colorkey ) == -1)
{
cout << "There was an error with the color key: ";
cout << SDL_GetError() << endl;
}


When I run the program, I get the following output:

Color key is: 65535
Color key is: 65535

This leads me to believe that it's calling the statement twice for some reason... which is a bit peculiar. I hope this information can be of use to anyone, perhaps in a way that will enable them to assist further. I would greatly appreciate it. :] Thank you for your time.

Colton

Share this post


Link to post
Share on other sites
Noegddgeon    134
Just on a whim, I changed the bits-per-pixel in the program from 32 to 24 and now it works!

Can anyone please explain to me why this would work? Thank you, evillive2, for suggesting that which inspired me to make such a change O:]

I appreciate everyone's help immensely. :]

Colton

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this