DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Snippets has posted 5883 posts at DZone. View Full User Profile

Useful SDL Functions!

08.17.2008
| 8465 views |
  • submit to reddit
        SDL is a cool library, but I was unhappy to see that it had no resizing or flipping commands. I have remedied this for you guys. :)

This code only works if you #include the SDL_rotozoom.h library, which is part of the SDL_gfx package. Remember to link it with -lSDL_gfx as well as include it. Unfortunately, their library offered a good zoom in / zoom out trick but not really anything in the way of scaling an image to an exact size. I've tested this code, and it works well.

Enjoy!


// For the flipImage function
enum flipDirection{ FLIP_X, FLIP_Y };

// Prototypes
SDL_Surface* create_blank_surface (int width, int height );
SDL_Surface* flipImage( SDL_Surface* origin,
                        const flipDirection dir );
void resizeImage( SDL_Surface*& img, const double newwidth,
                    const double newheight );
void matchColorKeys( SDL_Surface* src, SDL_Surface* dest );
Uint32 get_pixel( SDL_Surface* surface, int x, int y );
void put_pixel( SDL_Surface *surface, int x, int y, Uint32 pixel );


// create_blank_surface: Generates a new surface based on the
//      current video settings.
SDL_Surface *create_blank_surface (int width, int height )
{
    // We acquire the settings in our return surface
    SDL_Surface *basis = SDL_GetVideoSurface();

    // create the new surface using the Right-To_Left principle
    basis = SDL_CreateRGBSurface ( basis->flags, width, height,
                                     basis->format->BitsPerPixel,
                                     basis->format->Rmask,
                                     basis->format->Gmask,
                                     basis->format->Bmask,
                                     basis->format->Amask);
    return basis;
}

// flipImage: This returns a new SDL_Surface with the origin parameter
//      flipped along X or Y depending on the flipDirection supplied.
//
// Note: I chose to make this a new surface because I wanted to cut down
//       on my work for supplying left and right facings for sprite
//       animation.
SDL_Surface* flipImage( SDL_Surface* origin, const flipDirection dir )
{
    // Generate a blank surface of the same size to store the
    // flipped image.
    SDL_Surface* ret = create_blank_surface( origin->w, origin->h );

    // x and y are the original pixels, while rx and ry are the reverse,
    // which will be switched by this function.
    for( int x = 0, rx = ret->w - 1; x < ret->w; x++, rx-- )
    {
        for( int y = 0, ry = ret->h - 1; y < ret->h; y++, ry-- )
        {
            Uint32 pixel = get_pixel( origin, x, y );

            // FLIP_X and FLIP_Y determine which pixels to swap
            if( dir == FLIP_X )
                put_pixel( ret, rx, y, pixel );
            else
                put_pixel( ret, y, ry, pixel );
        }
    }

    // If the original was keyed, this new one should be as well.
    matchColorKeys( origin, ret );

    return ret;
}

// resizeImage: Resizes an image at its current place in memory. This means
//      that if you skew and stretch, you'll lose quality, but it also
//      means no worrying about new pointers. This uses the zoomSurface functions
//      in SDL_rotozoom.h ( SDL_gfx package )
void resizeImage( SDL_Surface*& img, const double newwidth, const double newheight )
{
    // Zoom function uses doubles for rates of scaling, rather than
    // exact size values. This is how we get around that:
    double zoomx = newwidth  / (float)img->w;
    double zoomy = newheight / (float)img->h;

    // This function assumes no smoothing, so that any colorkeys wont bleed.
    SDL_Surface* sized = zoomSurface( img, zoomx, zoomy, SMOOTHING_OFF );

    // Copy transparency data.
    matchColorKeys( img, sized );

    // The original picture is no longer needed.
    SDL_FreeSurface( img );

    // Set it instead to the new image.
    img =  sized;
}

// matchColorKeys: This copies the transparency data from one
//      surface to another.
void matchColorKeys( SDL_Surface* src, SDL_Surface* dest )
{
    // If the original had an alpha color key, give it to the new one.
    if( src->flags & SDL_SRCCOLORKEY )
    {
        // Acquire the original Key
        Uint32 colorkey = src->format->colorkey;

        // Set to the new image
        SDL_SetColorKey( dest, SDL_SRCCOLORKEY, colorkey );
    }
}

// get_pixel: Acquires a 32-bit pixel from a surface at given coordinates
Uint32 get_pixel( SDL_Surface* surface, int x, int y )
{
    //Convert the pixels to 32 bit
    Uint32 *pixels = (Uint32*)surface->pixels;

    //Get the requested pixelSDL_SRCCOLORKEY
    return pixels[ ( y * surface->w ) + x ];
}

// put_pixel: Drops a 32-bit pixel onto a surface at given coordinates.
void put_pixel( SDL_Surface *surface, int x, int y, Uint32 pixel )
{
    //Convert the pixels to 32 bit
    Uint32 *pixels = (Uint32 *)surface->pixels;

    //Set the pixel
    pixels[ ( y * surface->w ) + x ] = pixel;
}