Using the first tutorial as our base, we'll delve more into the world of SDL surfaces. As I attempted to explain in the last lesson, SDL Surfaces are basically images stored in memory. Imagine we have a blank 320x240 pixel surface. Illustrating the SDL coordinate system, we have something like this:

SDL Coordinate System

This coordinate system is quite different than the normal one you are familiar with. Notice how the Y coordinate increases going down, and the X coordinate increases going right. Understanding the SDL coordinate system is important in order to properly draw images on the screen.

Since we already have the main surface (Surf_Display) setup and ready, we are going to need a way to draw images on it. This process is called Blitting, where we basically transfer one image onto another. But before we can do that, we have to have a way to load these images into memory. SDL offers a simple function to do this called SDL_LoadBMP. Some pseudocode might look like this:
SDL_Surface* Surf_Temp;

if((Surf_Temp = SDL_LoadBMP("mypicture.bmp")) == NULL) {
    //Error!
}
It's rather simple, SDL_LoadBMP takes a single argument, the file you want to load, and returns a surface. If the functions returns NULL, either the file is not found, corrupted, or some other error. Unfortunately, for the sake of effeciency, this method is not enough. Often the image loaded will be in a different pixel format than the display. Thus, when we draw an image to the display we can incurr performance loss, lose image colors, and the like. But, thanks to SDL, it offers a quick solution around this, SDL_DisplayFormat. This function takes a surface already loaded, and returns a new surface using the same format as the display.

Let's take this process and throw it into a reusable class. Use SDL Tutorial 1 as the basis for you code, and add the following two new files: CSurface.h, CSurface.cpp. Open up CSurface.h and add the following:
#ifndef _CSURFACE_H_
    #define _CSURFACE_H_

#include <SDL.h>

class CSurface {
    public:
        CSurface();

    public:
        static SDL_Surface* OnLoad(char* File);
};

#endif
We've created a simple static function, OnLoad, that will load a surface for us. Now open CSurface.cpp:
#include "CSurface.h"

CSurface::CSurface() {
}

SDL_Surface* CSurface::OnLoad(char* File) {
    SDL_Surface* Surf_Temp = NULL;
    SDL_Surface* Surf_Return = NULL;

    if((Surf_Temp = SDL_LoadBMP(File)) == NULL) {
        return NULL;
    }

    Surf_Return = SDL_DisplayFormat(Surf_Temp);
    SDL_FreeSurface(Surf_Temp);

    return Surf_Return;
}
There are a couple of important things to note here. Firstly, always remember that when you make a pointer to set it to NULL, or 0. Many problems can come along later if you fail to do this. Secondly, notice how SDL_DisplayFormat returns a new Surface, and doesn't overwrite the original. This important to remember because since it creates a new surface, we have to free the old one. Otherwise, we have a surface floating around in memory.

Now that we have a way of loading surfaces into memory, we are also going to need a way to draw them onto other surfaces. Just like SDL offers a function to load images, it also offers a function to draw (blit) images: SDL_BlitSurface. Unfortunately, this function is not as easy to use as the SDL_LoadBMP, but nonetheless, it's simple enough. Open back up CSurface.h and add the following function prototype:
#ifndef _CSURFACE_H_
    #define _CSURFACE_H_

#include <SDL.h>

class CSurface {
    public:
        CSurface();

    public:
        static SDL_Surface* OnLoad(char* File);

        static bool OnDraw(SDL_Surface* Surf_Dest, SDL_Surface* Surf_Src, int X, int Y);
};

#endif
Now, open back up CSurface.cpp, and add the following:
#include "CSurface.h"

CSurface::CSurface() {
}

SDL_Surface* CSurface::OnLoad(char* File) {
    SDL_Surface* Surf_Temp = NULL;
    SDL_Surface* Surf_Return = NULL;

    if((Surf_Temp = SDL_LoadBMP(File)) == NULL) {
        return NULL;
    }

    Surf_Return = SDL_DisplayFormat(Surf_Temp);
    SDL_FreeSurface(Surf_Temp);

    return Surf_Return;
}

bool CSurface::OnDraw(SDL_Surface* Surf_Dest, SDL_Surface* Surf_Src, int X, int Y) {
    if(Surf_Dest == NULL || Surf_Src == NULL) {
        return false;
    }

    SDL_Rect DestR;

    DestR.x = X;
    DestR.y = Y;

    SDL_BlitSurface(Surf_Src, NULL, Surf_Dest, &DestR);

    return true;
}
First of all, look at the arguments being passed to the OnDraw function. We have two surfaces, and two int variables. The first surface is the destination surface, or the surface we are going to draw on. The second surface is the source surface, or the surface we going to use to draw on another surface. Basically, we are putting Surf_Src on top of Surf_Dest. The X, Y variables is the position on the Surf_Dest where we are drawing this surface to.

The start of the function makes sure we have valid surfaces, if we don't, return false. Next, we find SDL_Rect. This is a SDL structure that basically has four members: x, y, w, h. This, of course, creates the dimensions for a rectangle. We are only worried about where we are drawing to, not the size. So we assign X, Y coordinates to the destination surface. If you are wondering what NULL is within SDL_BlitSurface, it's another parameter for a SDL_Rect. We'll get to this later on in this lesson.

Lastly, we actualy call the function to draw the image, and then return true.

Now, to make sure all of this works, let's create a test surface. Open up CApp.h, and create a new surface, and include the new created CSurface.h:
#ifndef _CAPP_H_
    #define _CAPP_H_

#include <SDL.h>

#include "CSurface.h"

class CApp {
    private:
        bool            Running;

        SDL_Surface*    Surf_Display;

        SDL_Surface*    Surf_Test;

    public:
        CApp();

        int OnExecute();

    public:
        bool OnInit();

        void OnEvent(SDL_Event* Event);

        void OnLoop();

        void OnRender();

        void OnCleanup();
};

#endif
Also, initialize the surface to NULL in the constructor:
CApp::CApp() {
    Surf_Test = NULL;
    Surf_Display = NULL;

    Running = true;
}
And, remember to cleanup:
#include "CApp.h"

void CApp::OnCleanup() {
    SDL_FreeSurface(Surf_Test);
    SDL_FreeSurface(Surf_Display);
    SDL_Quit();
}
Now, lets actually load an image. Open up CApp_OnInit.cpp, and add the code to load a surface:
#include "CApp.h"

bool CApp::OnInit() {
    if(SDL_Init(SDL_INIT_EVERYTHING) < 0) {
        return false;
    }

    if((Surf_Display = SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE | SDL_DOUBLEBUF)) == NULL) {
        return false;
    }

    if((Surf_Test = CSurface::OnLoad("myimage.bmp")) == NULL) {
        return false;
    }

    return true;
}
Be sure to replace "myimage.bmp" with an actual bitmap image you have. If you don't have one, open mspaint and draw something real quick, and save it in the same folder where your executable goes. Now that we have the image loaded, lets actually draw it. Open up CApp_OnRender.cpp and add the following:
#include "CApp.h"

void CApp::OnRender() {
    CSurface::OnDraw(Surf_Display, Surf_Test, 0, 0);

    SDL_Flip(Surf_Display);
}
Notice a new function here SDL_Flip. This basically refreshes the buffer and displays Surf_Display onto the screen. This is called double buffering. It's the process of drawing everything into memory, and then finally drawing everything to the screen. If we didn't do this, we would have images flickering on the screen. Remember the SDL_DOUBLEBUF flag? This is what turns double buffering on.

Compile your code, and make sure everything works correctly. You should see your image on the top left hand corner of the screen. If so, congratulations, you are one step closer to an actual game. If not, make sure you have the myimage.bmp in the same folder as your executable. Also insure it's a valid bitmap file.

Draw Surface

Now lets take this process a little bit further. While it's nice and all to draw images to the screen, often we'll need to draw only parts of an image. Take, for example, a tileset:

Tileset

Though this is one single image, we only want to draw a part of it. Open back up CSurface.h, and add the following code:
#ifndef _CSURFACE_H_
    #define _CSURFACE_H_

#include <SDL.h>

class CSurface {
    public:
        CSurface();

    public:
        static SDL_Surface* OnLoad(char* File);

        static bool OnDraw(SDL_Surface* Surf_Dest, SDL_Surface* Surf_Src, int X, int Y);

        static bool OnDraw(SDL_Surface* Surf_Dest, SDL_Surface* Surf_Src, int X, int Y, int X2, int Y2, int W, int H);
};

#endif
Open back up CSurface.cpp, and add the following function (Important, we are adding a second OnDraw function, we are not replacing the first one):
bool CSurface::OnDraw(SDL_Surface* Surf_Dest, SDL_Surface* Surf_Src, int X, int Y, int X2, int Y2, int W, int H) {
    if(Surf_Dest == NULL || Surf_Src == NULL) {
        return false;
    }

    SDL_Rect DestR;

    DestR.x = X;
    DestR.y = Y;

    SDL_Rect SrcR;

    SrcR.x = X2;
    SrcR.y = Y2;
    SrcR.w = W;
    SrcR.h = H;

    SDL_BlitSurface(Surf_Src, &SrcR, Surf_Dest, &DestR);

    return true;
}
Notice that it's basically the same function as our first one, except we've added another SDL_Rect. This source rect allows use to specify what pixels from the source to copy over to the destination. If we specified 0, 0, 50, 50 as parameters for X2...H, it would only draw upper left part of the surface (a 50x50 square). Draw Surface 2

Lets also test this new function out, open back up CApp_OnRender.cpp, and add the following:
#include "CApp.h"

void CApp::OnRender() {
    CSurface::OnDraw(Surf_Display, Surf_Test, 0, 0);
    CSurface::OnDraw(Surf_Display, Surf_Test, 100, 100, 0, 0, 50, 50);

    SDL_Flip(Surf_Display);
}
You should notice that your image is drawn at 100, 100 and only part of it is being displayed. You should take special care understanding how these functions work, and how the SDL coordinate system is setup, you will be using this quite a bit.

Jump on over to the next SDL tutorial, where we'll look more at SDL events, and how to make that process a whole lot simpler.