Introduction to SDL_Image

Introduction to SDL_Image - add support for different image types. Convert .png and .jpeg files into SDL surfaces, and vice versa
This lesson is part of the course:

Game Dev with SDL2

Learn C++ and SDL development by creating hands on, practical projects inspired by classic retro games

Free, Unlimited Access
aSDL9c.jpg
Ryan McCombe
Ryan McCombe
Posted

In 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:

Including SDL Image

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;
};

Creating Screenshots with 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;
  }
}
Screenshot of an image SDL saved to the hard drive

Creating Screenshots with 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

Was this lesson useful?

Ryan McCombe
Ryan McCombe
Posted
Lesson Contents

Introduction to SDL_Image

Introduction to SDL_Image - add support for different image types. Convert .png and .jpeg files into SDL surfaces, and vice versa

sdl2-promo.jpg
This lesson is part of the course:

Game Dev with SDL2

Learn C++ and SDL development by creating hands on, practical projects inspired by classic retro games

Free, Unlimited Access
Rendering Images and Text
  • 25.Making Minesweeper with C++ and SDL2
  • 26.Project Setup
  • 27.GPUs and Rasterization
  • 28.SDL Renderers
sdl2-promo.jpg
This lesson is part of the course:

Game Dev with SDL2

Learn C++ and SDL development by creating hands on, practical projects inspired by classic retro games

Free, unlimited access

This course includes:

  • 27 Lessons
  • 100+ Code Samples
  • 91% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Next Lesson

Introduction to SDL_ttf

A beginner’s introduction to the SDL_ttf library, and how we can use it to add text rendering to our application.
aSDL9d.jpg
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved