Hello! This is the fourth lesson on SDL 2. I decided to merge two lessons into one, since in the original they are small. But they can be found
here and
here . Well, let's start the lesson.
First, decide what we will do. Today we will learn how to upload images of another extension (not BMP), namely: PNG. Transform the image into another format to speed up the work and resize the image. We will work with this image:
Installation
So first learn how to download PNG. In the standard SDL 2 feature set, there is no non-BMP image download. To download a different format you need to install the extension.
')
Here are the instructions:
WindowsYou go to this
page and download the ZIP or TAR.GZ archives from the
Development Libraries section. Unpack and throw them into the folder with the compiler.
LinuxIf your system uses Debian, then you need to enter these commands:
apt-cache search libsdl2-image apt-get install libsdl2-image-dev
If you use Yellowdog Updater, Modified, then you enter this command:
yum search SDL2_image-devel yum SDL2_image-devel
Mac osDownload the DMG file and read the Readme.
Write the code
After installing
SDL_image, we start writing the code. First, as always, we connect libraries, set the window size and create 3 global variables.
#include <SDL2/SDL.h> #include <SDL2/SDL_image.h> #include <iostream> const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480; SDL_Window *win = NULL; SDL_Surface *scr = NULL; SDL_Surface *flower = NULL;
Note that
SDL_image.h I connected separately, since it is a separate library.
Next, we write 3 functions, known to us, in which we add and change something, as usual.
Init () bool init() { if (SDL_Init(SDL_INIT_VIDEO) != 0) { std::cout << "Can't init video: " << SDL_GetError() << std::endl; return false; } int flags = IMG_INIT_PNG; if ( !( IMG_Init( flags ) & flags ) ) { std::cout << "Can't init image: " << IMG_GetError() << std::endl; return false; } win = SDL_CreateWindow(" PNG", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); if (win == NULL) { std::cout << "Can't create window: " << SDL_GetError() << std::endl; return false; } scr = SDL_GetWindowSurface(win); return true; }
Here we have added the initialization of the SDL_image module. To initialize it, first we create a variable of type
int , we have
flags , and save all the flags that you want to use for initialization.
List of all flagsSDL_INIT_PNG - initializes the PNG image downloader;
SDL_INIT_JPG - initializes the JPG image downloader;
SDL_INIT_TIF - initializes the TIF image downloader;
Further we write the following condition:
if ( !( IMG_Init( flags ) & flags ) )
The
IMG_Init () function returns the flags that it was able to initialize. If she returned the flags, but the one we wanted was missing, we return an error. Very simple. Also, notice that I use
IMG_GetError instead of
SDL_GetError , since we are looking for an error in the function of the
SDL_image module, and not the
SDL .
I also want to note that I decided to use the
bool type for
return, and this is a more rational way.
Let's continue writing our program, write the
Load () function, in which we will load the PNG image and convert it.
Load bool load() { flower = IMG_Load("flower.png"); if (flower == NULL) { std::cout << "Can't load: " << IMG_GetError() << std::endl; return false; } flower = SDL_ConvertSurface(flower, scr->format, NULL); if (flower == NULL) { std::cout << "Can't convert: " << SDL_GetError() << std::endl; return false; } return true; }
Here we load the image with the new
IMG_Load function.
Its function is the same as that of
SDL_LoadBMP and the result is the same - it returns an instance of the
SDL_Surface class. To find errors when loading, we also use
IMG_GetError .
It's time to convert. First, a little theory. Few people know, but when loading an image, it loads in 24bit format, and most modern displays have a 32bit format. And each time when we displayed the image on the screen, it was first altered in 32bit format. For simple programs, this does not matter, but when creating a large project, it will greatly affect performance, so we’ll take them into the display format at the stage of loading images. The
SDL_ConvertSurface function will not help. It takes 3 values: The surface that we want to format, the format into which we want to format and flags. we want to format the
flower image, pass it by the first parameter. The second parameter is the window surface format, we will not use flags. This function returns a copy of the surface, which we immediately assign to the
flower . To find errors, we take the function
SDL_GetError () , since we are already working with surfaces, and they are from
SDL , and not from
SDL_image .
Next, we write the Quit function, add just one function to it.
Quit void quit() { SDL_FreeSurface(flower); SDL_FreeSurface(scr); SDL_DestroyWindow(win); SDL_Quit(); IMG_Quit(); }
We added
IMG_Quit to de-initialize the SDL_image module.
Main
Now the simplest thing is the
main function.
int main (int argc, char ** args) { if (!init()) { system("pause"); quit(); return 1; } if (!load()) { system("pause"); quit(); return 1; }
To begin, initialize and create everything you need and load the necessary files. We will not stop here.
SDL_Rect bg_flower; bg_flower.w = SCREEN_WIDTH; bg_flower.h = SCREEN_HEIGHT; bg_flower.x = 0; bg_flower.y = 0;
After that create an object of class
SDL_Rect . We will need it to stretch the image. If you notice, the image of the flower is 4 times smaller than the window size (2 times thinner and 2 times lower), and we need to stretch it to the window size. So in the width of the rectangle
bg_flower we write the value of the width of the window, and in height - the height of the window. We set the coordinates to 0, so that the image is displayed in the upper left corner.
To display an image with resized dimensions, there is a special function. It looks like this:
SDL_BlitScaled(flower, NULL, scr, &bg_flower);
It takes 4 values. The first is the image we want to display, the second is the Rectangle that we want to cut from this image (if we want to take the whole image, we write NULL), the third is the surface on which we can display the image, and the fourth is the same rectangle, dimensions and the coordinates of which we take to stretch or compress and display the image.
Then simply update the screen surface, set the delay, exit and return 0.
SDL_UpdateWindowSurface(win); SDL_Delay(2000); quit(); return 0; };
This is where our program ends. In order to compile this miracle, add -lSDL2_image, as another compilation parameter.
And on this we finish today. Here is the code we got:
#include <SDL2/SDL.h> #include <SDL2/SDL_image.h> #include <iostream> const int SCREEN_WIDTH = 640; const int SCREEN_HEIGHT = 480; SDL_Window *win = NULL; SDL_Surface *scr = NULL; SDL_Surface *flower = NULL; bool init() { if (SDL_Init(SDL_INIT_VIDEO) != 0) { std::cout << "Can't init video: " << SDL_GetError() << std::endl; return false; } int flags = IMG_INIT_PNG; if ( !( IMG_Init( flags ) & flags ) ) { std::cout << "Can't init image: " << IMG_GetError() << std::endl; return false; } win = SDL_CreateWindow(" PNG", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); if (win == NULL) { std::cout << "Can't create window: " << SDL_GetError() << std::endl; return false; } scr = SDL_GetWindowSurface(win); return true; } bool load() { flower = IMG_Load("flower.png"); if (flower == NULL) { std::cout << "Can't load: " << IMG_GetError() << std::endl; return false; } flower = SDL_ConvertSurface(flower, scr->format, NULL); if (flower == NULL) { std::cout << "Can't convert: " << SDL_GetError() << std::endl; return false; } return true; } void quit() { SDL_FreeSurface(flower); SDL_FreeSurface(scr); SDL_DestroyWindow(win); SDL_Quit(); IMG_Quit(); } int main (int argc, char ** args) { if (!init()) { system("pause"); quit(); return 1; } if (!load()) { system("pause"); quit(); return 1; } SDL_Rect bg_flower; bg_flower.w = SCREEN_WIDTH; bg_flower.h = SCREEN_HEIGHT; bg_flower.x = 0; bg_flower.y = 0; SDL_BlitScaled(flower, NULL, scr, &bg_flower); SDL_UpdateWindowSurface(win); SDL_Delay(2000); quit(); return 0; };
Bye everyone!
<< Previous lesson || Next lesson
>>