📜 ⬆️ ⬇️

SDL 2 Tutorial: Lesson 4 - PNG Stretch

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:

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:

Windows
You 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.

Linux
If 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 os
Download 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 flags
SDL_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 >>

Source: https://habr.com/ru/post/456656/


All Articles