Image files to use in games and applications often are available in other formats, e.g. JPG or PNG. In contrast to simple bitmap files, which need a significant higher amount of disk space memory, are they memory-compressed and need significant less disk space.
Also it would be desirable to create the SDL3 texture directly by loading from an image file, instead of creating a SDL2 surface in-between as seen in the previous chapter.
The SDL3_image Unit
Here comes the SDL3_image unit into play. It allows:
- Loading of many common image formats
- Supported formats: AVIF, ICO, CUR, BMP, GIF, JPG, JXL, LBM, PCX, PNG, PNM, SVG, QOI, TIF, XCF, XPM, XV, WEBP
- Creation of SDL3 texture from image files directly
SDL3_image is an official extension of SDL3, which is developed and maintained by the same developers. Therefore, before right jumping into the code we need the corresponding library files.
Installing SDL3_image
- Get you files here: SDL3_image library releases
- Windows:
- Download the most recent version of the Runtime Binaries (DLL files) of the SDL3_image library for your system (32 bit or 64 bit)
- Copy all these files, especially SDL3_image.dll, to your system folder (system or system32)
- Linux:
- Download the most recent version of the source code and compile it (until the repos are providing a pre-compiled version to install via the paket manager)
- Copy these files, especially libSDL3_image.so, to your library folder; often /usr/local
IMG_Load and IMG_LoadTexture


An image file (left) can be loaded as a surface or a texture and then be rendered to the screen.
Have a look at the flow diagram which is an extended version of the diagram seen in the chapter about loading of bitmap files. You see it is extended by two function with the prefix IMG instead of SDL, namely IMG_LoadTexture() and IMG_Load(). Both of these functions allow to load image files of all the supported file formats mentioned above. Also you see that IMG_LoadTexture() creates a texture directly from the image file, so we can skip creating a SDL3 surface.
Let’s try the following image files (dimensions: 200 x 200 pixels, formats: bmp, jpg and png) but feel free to use any other image file you like.



Code Example using SDL3_image
program SDL_LoadingDifferentFormats;
uses SDL3, SDL3_image;
var
sdlWindow1: PSDL_Window;
sdlRenderer: PSDL_Renderer;
sdlTexture1: PSDL_Texture;
begin
// initilization of video subsystem
if not SDL_Init(SDL_INIT_VIDEO) then Halt;
if not SDL_CreateWindowAndRenderer('Use SDL3_image', 500, 500, 0, @sdlWindow1, @sdlRenderer) then Halt;
// load image file directly to texture
sdlTexture1 := IMG_LoadTexture(sdlRenderer, 'data/fpsdl.png');
if sdlTexture1 = nil then Halt;
// render texture
if not SDL_RenderTexture(sdlRenderer, sdlTexture1, nil, nil) then Halt;
// render to window for 2 seconds
SDL_RenderPresent(sdlRenderer);
SDL_Delay(2000);
// clear memory
SDL_DestroyTexture(sdlTexture1);
SDL_DestroyRenderer(sdlRenderer);
SDL_DestroyWindow (sdlWindow1);
// closing SDL2
SDL_Quit;
end.
This code will create a window of dimensions 500 x 500 pixels which is showing the “Freepascal meets SDL” image for two seconds. After that the window closes automatically. The following screenshot shows the result of the example program.


Result of the program.
Now let’s get into the code step by step.
program SDL_LoadingDifferentFormats;
uses SDL3, SDL3_image;
var
sdlWindow1: PSDL_Window;
sdlRenderer: PSDL_Renderer;
sdlTexture1: PSDL_Texture;
The first eight line starts a Pascal program as usual. In contrast to the previous chapter, the uses clause is extended by SDL3_image. Again, native SDL3 has no support for loading different image formats, except for BMP image files. And native SDL3 doesn’t allow for loading of BMP image files directly into SDL3 textures, but SDL3 surfaces only.
We need a texture variable to which we can load the image information of an image file. This will be “sdlTexture1” of PSDL_Texture type.
begin
// initilization of video subsystem
if not SDL_Init(SDL_INIT_VIDEO) then Halt;
if not SDL_CreateWindowAndRenderer('Use SDL3_image', 500, 500, 0, @sdlWindow1, @sdlRenderer) then Halt;
The initialization of SDL3, the window and renderer creation are done as known from previous chapters.
Creation and Rendering of a SDL3 Texture from an Image File
// load image file directly to texture
sdlTexture1 := IMG_LoadTexture(sdlRenderer, 'data/fpsdl.png');
if sdlTexture1 = nil then Halt;
// render texture
if not SDL_RenderTexture(sdlRenderer, sdlTexture1, nil, nil) then Halt;
// render to window for 2 seconds
SDL_RenderPresent(sdlRenderer);
SDL_Delay(2000);
Now we load the image file to the SDL3 texture we called “sdlTexture1”. The function to do this is IMG_LoadTexture(renderer, path to image file).
This function is provided by SDL3_image. Its prefix is IMG instead of SDL for native SDL3 functions. That function is why we needed to insert SDL2_image in the uses clause. The parameters of this function are a renderer, that is “sdlRenderer” for us, and as a second the absolute or relative path to an image file, for us it is “data/fpsdl.png”, assuming that the “fpsdl.png” image file is in a sub-folder called “data”.
Of course you may use any other directory to store/load the image or even use a different image. The function will recognize the image file’s format automatically, so feel free to load any of the allowed formats. If the loading fails, for instance you gave a wrong path as argument, this function will return nil. Try changing “fpsdl.png” by “fpsdl.jpg” or “fpsdl.bmp” (if these files exist in the data sub-folder).
The loaded SDL3 texture in “sdlTexture1” we can now render as known from previous chapter by SDL_RenderTexture(), followed by SDL_RenderPresent(). SDL_Delay() delays the application by 2 seconds.
Clean up the Memory in SDL3
// clear memory
SDL_DestroyTexture(sdlTexture1);
SDL_DestroyRenderer(sdlRenderer);
SDL_DestroyWindow (sdlWindow1);
// closing SDL2
SDL_Quit;
end.
As known from previous chapters, we free the memory by destroying the objects in reversed order. After removing the objects from memory, SDL3 has to be quit.
Wow, we finally made it. Congratulations, this chapter is finished :-). The next chapter is waiting though.
Previous Chapter | Next Chapter