Loading and Rendering a Bitmap File

Last updated on November 20th, 2021

Loading of bitmap image files (BMP files) is natively supported by SDL2. The way to go is as follows (from the flow diagram).

 

Creative Commons License This image by https://www.freepascal-meets-sdl.net is licensed under a Creative Commons Attribution 4.0 International License.
Flow diagram of the loading and rendering of a bitmap file in SDL2.

Let’s start on the left in the diagram. The easiest way to get a bitmap (BMP) image file for a game or application ready for usage is to create one in a drawing application. Or use the example bitmap “fpsdl.bmp” we used in the code.

Free Pascal meets SDL sample image bmp format
Creative Commons License This image by https://www.freepascal-meets-sdl.net is licensed under a Creative Commons Attribution 4.0 International License.
The original image is 200×200 pixels wide.

The bmp image file is stored on your hard drive and can be loaded by SDL_LoadBMP function to a SDL2 surface. This SDL2 surface is then transformed into a SDL2 texture by SDL_CreateTextureFromSurface function (whose name is just explaining what is does). And finally this texture is rendered by SDL_RenderPresent, this function we know already.

And now let’s see how it is done in code.

program SDL_LoadingRenderingBMP;

uses SDL2;

var
  sdlWindow1: PSDL_Window;
  sdlRenderer: PSDL_Renderer;
  sdlSurface1: PSDL_Surface;
  sdlTexture1: PSDL_Texture;

begin

  //initilization of video subsystem
  if SDL_Init(SDL_INIT_VIDEO) < 0 then Halt;

  if SDL_CreateWindowAndRenderer(500, 500, SDL_WINDOW_SHOWN, @sdlWindow1, @sdlRenderer) <> 0
    then Halt;

  // create surface from file
  sdlSurface1 := SDL_LoadBMP('fpsdl.bmp');
  if sdlSurface1 = nil then
    Halt;

  // create texture from surface
  sdlTexture1 := SDL_CreateTextureFromSurface(sdlRenderer, sdlSurface1);
  if sdlTexture1 = nil then
    Halt;

  // render texture
  if SDL_RenderCopy(sdlRenderer, sdlTexture1, nil, nil) <> 0 then
    Halt;

  // render to window for 2 seconds
  SDL_RenderPresent(sdlRenderer);
  SDL_Delay(2000);

  // clear memory
  SDL_DestroyTexture(sdlTexture1);
  SDL_FreeSurface(sdlSurface1);
  SDL_DestroyRenderer(sdlRenderer);
  SDL_DestroyWindow (sdlWindow1);

  //closing SDL2
  SDL_Quit;

end.                                                                   

The result is this:

Result screenshot for chapter 4
Creative Commons License This image by https://www.freepascal-meets-sdl.net is licensed under a Creative Commons Attribution 4.0 International License.
This is the result of the code.

The var clause,

var
  sdlWindow1: PSDL_Window;
  sdlRenderer: PSDL_Renderer;
  sdlSurface1: PSDL_Surface;
  sdlTexture1: PSDL_Texture;

contains two new variables, namely “sdlSurface1” and “sdlTexture1” of the pointer types PSDL_Surface and PSDL_Texture, respecitvely.

After setting up SDL2, a window and a renderer as known, we find this.

Step 1: Loading the BMP file to a SDL2 Surface

  // create surface from file
  sdlSurface1 := SDL_LoadBMP('fpsdl.bmp');
  if sdlSurface1 = nil then
    Halt;

SDL_LoadBMP(name of bmp image file) does what you expect, it loads the image file and generates a SDL2 surface from it. Attention though, if you just give a file name, it is assumed that the file is found in the same folder as the executing application. Optionally you can also give a full file path, e.g. in Windows something like ‘C:\MyImages\fpsdl.bmp’. The function is declared as

 SDL_LoadBMP(_file: PAnsiChar): PSDL_Surface

and return nil on error, e.g. if the file is not found.

Step 2: Creating a SDL2 Texture from the SDL2 Surface

The next step is to get a SDL2 texture. That’s achieve as follows.


  // create texture from surface
  sdlTexture1 := SDL_CreateTextureFromSurface(sdlRenderer, sdlSurface1);
  if sdlTexture1 = nil then
    Halt;

The function to use is SDL_CreateTextureFromSurface(renderer, surface)

SDL_CreateTextureFromSurface(renderer: PSDL_Renderer; surface: PSDL_Surface): PSDL_Texture

It just does what you expect and transforms the SDL2 surface into a SDL2 texture with the help of the given renderer.

Step 3: Prepare the SDL2 Texture to be Rendered

Before actually rendering the texture, we need to copy it to the rendering target (our window) by SDL_RenderCopy(renderer, texture, source rectangle (texture), destination rectangle (rendering target)).

// render texture
  if SDL_RenderCopy(sdlRenderer, sdlTexture1, nil, nil) <> 0 then
    Halt;

So the texture is copied to the rendering target (which is the window). The first nil argument means that we want to copy the whole rectangle. The second nil means that we want to copy to the whole dimensions of the rendering target. Let’s have a closer look at the function.

SDL_RenderCopy(renderer: PSDL_Renderer; texture: PSDL_Texture; srcrect: PSDL_Rect; dstrect: PSDL_Rect): SInt32

You see here, that you could use arguments of type PSDL_Rect, which basically describes rectangles.

Step 4: The Rendering

And finally the rendering is done by the known SDL_RenderPresent().

Step 5: Destroying Surfaces and Textures

It is important to free the memory occupied by the surface and texture by SDL_FreeSurface(surface) and SDL_DestroyTexture(texture) right after .

  // clear memory
  SDL_DestroyTexture(sdlTexture1);
  SDL_FreeSurface(sdlSurface1);
  SDL_DestroyRenderer(sdlRenderer);
  SDL_DestroyWindow (sdlWindow1);

Now you know how to load and render a bmp file to a window. 🙂

Remark: DO NEVER combine SDL_CreateTextureFromSurface() and SDL_LoadIMG!

Do never combine step 1 and step 2 to avoid declaring and freeing a surface. DO NEVER do this:

sdlTexture1 := SDL_CreateTextureFromSurface(sdlRenderer, SDL_LoadBMP('fpsdl.bmp'));

This will run without any problem, though SDL_CreateTextureFromSurface() will not free the surface created by SDL_LoadBMP(). And you have no handle to free this surface. This creates a memory leak. 

← previous Chapter | next Chapter →

3 thoughts on “Loading and Rendering a Bitmap File

  1. As a long time Pascal User (from the times of TurboPascal 6/7) i’m delighted with Pascal+SDL, i’m planning to do a simple retro style game for my small kid (4.5 years old) and the combination seems perfect!!
    But i wonder why the extra step of loading the BMP to the surface and then generate a texture with it? Is there any problem in making a SDL_LoadBMP(_file: PAnsiChar): PSDL_Texture function that internally creates a temporary surface and automatically free it after completion? So we must worry to free only the texture (the one we care about) and not the temporary object.

    1. Is there any problem in making a SDL_LoadBMP(_file: PAnsiChar): PSDL_Texture function that internally creates a temporary surface and automatically free it after completion? So we must worry to free only the texture (the one we care about) and not the temporary object.

      That’s perfetcly fine. Have fun! 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *