SDL_Image
SDL_Image
- add support for different image types. Convert .png
and .jpeg
files into SDL surfaces, and vice versaIn this lesson, we’ll introduce SDL_Image
, a popular, official SDL extension that allows us to use many different image types - png files, jpg files, and many more.
Additionally, we’ll see how we can convert our surfaces to images, and save them on our hard drive.
Note, this lesson assumes you already have SDL_Image installed. The installation guide at the start of this chapter walked through the setup of everything we’ll need:
This lesson also follows immediately from our previous lesson on Images and Surface Blitting. We’ll be expanding the ideas and code we created there:
The first part of accessing SDL_Image
is including its header file in any location we want to use it:
#include <SDL_image.h>
IMG_Load
The ability to load images of different formats is typically the main reason we want to use SDL Image. The function we need for that is IMG_Load
.
We pass in a C-style string representing the path to our image (relative to our executable):
IMG_Load("birds.png");
As with SDL_LoadBMP
, this loads our image onto an SDL_Surface
, and returns a pointer to that surface.
SDL_Surface* MySurface { IMG_Load("birds.png") };
IMG_Load
supports .bmp
files so, as long as we’re using the library, there’s limited need to use SDL_LoadBMP
anymore. We could update our Image
class from the previous lesson to use SDL_Image instead, allowing it to support many different types of images:
#pragma once
#include <SDL.h>
#include <SDL_image.h>
#include <string>
class Image {
public:
Image(std::string Filename, SDL_Surface* WindowSurface) {
SDL_Surface* Temp { IMG_Load(Filename.c_str()) };
Surface = SDL_ConvertSurface(Temp, WindowSurface->format, 0);
SDL_FreeSurface(Temp);
SDL_BlitSurface(Surface, nullptr, WindowSurface, nullptr);
}
~Image() {
SDL_FreeSurface(Surface);
}
private:
SDL_Surface* Surface;
};
IMG_SavePNG
SDL_Image gives us the ability to save the contents of any of our surfaces to an image file.
We just need to provide a pointer to the surface we want to capture, and the file path we want to save the image as:
IMG_SavePNG(GameWindow.GetSurface(), "screenshot.png");
The file will be stored in the same location as our executable. If it already exists, it will be overwritten.
Here, we save a screenshot of our Window
surface before quitting:
while(SDL_PollEvent(&Event)) {
if (Event.type == SDL_QUIT) {
IMG_SavePNG(GameWindow.GetSurface(), "screenshot.png");
SDL_Quit();
IMG_Quit();
return 0;
}
}
IMG_SaveJPG
We can also save our images using the JPG format, if preferred.
The first two function arguments are the same. However, IMG_SaveJPG
accepts a third argument - an integer for the quality of the saved image. This can range from 0 to 100. A higher number yields a higher quality image, but larger file size.
IMG_SaveJPG(GameWindow.GetSurface(), "screenshot.jpg", 70);
IMG_Init
The IMG_Init
function lets us control the initialization of SDL_Image
. It’s not strictly necessary to call this - SDL_Image
will automatically initialize components as needed. For example, the first time we call IMG_Load
with a .png
file, the codec for PNGs will be intiialised at that point.
However, in a serious project, we’d likely want to take control of this. We don't want to risk it happening at a time where we really need the resources working on something else.
So, we can call SDL_Init
at a suitable time, passing in the codecs we will be using. SDL has provided helper aliases for these codecs. They all which start with IMG_INIT
, for example, IMG_INIT_PNG
:
IMG_Init(IMG_INIT_PNG);
Multiple codecs can be combined using the bitwise ORÂ operator:
IMG_Init(IMG_INIT_PNG | IMG_INIT_JPG);
IMG_Quit
When we no longer need SDL_Image
, we should call SDL_Quit
so it can clean up some resources:
while(true) {
while(SDL_PollEvent(&Event)) {
if (Event.type == SDL_QUIT) {
SDL_Quit();
IMG_Quit();
return 0;
}
}
GameWindow.RenderFrame();
}
The official documentation for SDL_Image
is available here: https://wiki.libsdl.org/SDL_image/CategoryAPI
Learn C++ and SDL development by creating hands on, practical projects inspired by classic retro games