Loading of bitmap image files (BMP files) is natively supported by SDL2. The way to go is as follows (from the flow diagram).
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.
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:
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.