Частина 7 - SDL2_image: Завантаження файлів зображень різних форматів

Файли зображень для використання в іграх та додатках часто доступні в форматах відмінних від простих растрових растрових зображень (наприклад, jpg, png, tif тощо), оскільки часто файли растрових зображень потребують значно більшої кількості дискової пам’яті.

Також було б бажано завантажити файл зображення безпосередньо і створити з нього текстуру SDL2, замість того, щоб спочатку створювати поверхню SDL2, а потім створювати текстуру SDL2 з поверхні (як видно з розділу про завантаження растрових зображень).

Модуль SDL2_image

І ось тут в гру вступає модуль SDL2_image. Він дозволяє:

  • Завантаження багатьох поширених форматів зображень
  • Формати, що підтримуються: ICO, CUR, BMP, GIF, JPG, LBM, PCX, PNG, PNM, TIF, XCF, XPM, XV, WEBP
  • Безпосереднє створення текстури SDL2 з файлів зображень

Ці функції, очевидно, не рідною частиною SDL 2.0. SDL2_image це офіційне розширення SDL 2.0, який розробляється і підтримується тими ж розробниками. Тому перед тим, як зануритись в кодування нам потрібні відповідні бібліотечні файли.

Встановлення SDL2_image

  • завантажте найсвіжішу версію бінарників періоду виконання бібліотеки SDL2_image для Вашої системи
  • встановіть бібліотеку відповідно до вашої системи (Win32/64, Linux, Mac OS X)

Інструкції з встановлення SDL2_image для Windows

Завантажте відповідний пакет SDL2_image в залежності від вашої системи (32-розрядної або 64-розрядної) та розпакуйте файл. У підсумку ви отримаєте SDL2_image.dll та деякі інші dll, що необхідні для підтримки деяких форматів зображень. Скопіюйте всі ці файли у свою системну папку, наприклад для Windows XP 32-розрядної C:\WINDOWS\system32\. Якщо Ви не впевнені в Вашій системній папці, Ви можете скопіювати всі ці файли в ту саму папку, де знаходиться файл вихідного коду (.pas чи .pp) Вашої програми SDL 2.0.

IMG_Load та IMG_LoadTexture

SDL2 Texture and Surface relation diagram
Creative Commons License Це зображення від https://www.freepascal-meets-sdl.net ліцензовано за Creative Commons Attribution 4.0 International License.
Файл зображення (зліва) може бути завантажено як поверхня або текстура і тоді візуалізовано на екран.

Погляньте на діаграму вище, яка є розширеною версією діаграми, розглянутої в частині про завантаження растрових файлів. Ви бачите, що її розширено двома функціями з префіксом IMG замість SDL, а саме IMG_LoadTexture() та IMG_Load(). Обидві ці функції дозволяють завантажувати файли зображень усіх підтримуваних форматів файлів, згаданих вище. Ви також бачите, що IMG_LoadTexture() створює текстуру напряму з файла зображення, тож ми пропускаємо крок створення спершу поверхні SDL2 з файлу зображення.

Давайте спробуємо наступні файли зображень (розміри: 200 x 200 пікселів, формати: bmp, jpg і png), але сміливо використовуйте будь-який інший файл зображень, який Вам подобається.

Приклад кодування з SDL2_image

А тепер почнемо з коду. Спочатку я покажу код у цілому, а потім обговорюватиму його меншими фрагментами зверху вниз до фінального «end». 🙂

program Chapter4_SDL2;

uses SDL2, SDL2_image;

var
sdlWindow1 : PSDL_Window;
sdlRenderer : PSDL_Renderer;
sdlTexture1 : PSDL_Texture;

begin

  //ініціалізація підсистеми відео
  if SDL_Init( SDL_INIT_VIDEO ) < 0 then HALT;

  sdlWindow1 := SDL_CreateWindow( 'Window1', 50, 50, 500, 500, SDL_WINDOW_SHOWN );
  if sdlWindow1 = nil then HALT;

  sdlRenderer := SDL_CreateRenderer( sdlWindow1, -1, 0 );
  if sdlRenderer = nil then HALT;

  sdlTexture1 := IMG_LoadTexture( sdlRenderer, 'C:\fpsdl.bmp' );
  if sdlTexture1 = nil then HALT;
  SDL_RenderCopy( sdlRenderer, sdlTexture1, nil, nil );
  SDL_RenderPresent (sdlRenderer);
  SDL_Delay( 2000 );

  SDL_DestroyTexture( sdlTexture1 );
  SDL_DestroyRenderer( sdlRenderer );
  SDL_DestroyWindow ( sdlWindow1 );

  //вимкнення відеосистеми
  SDL_Quit;

end.

Ну ось воно. Цей код створить вікно розміром 500 х 500 пікселів, яке протягом двох секунд відображатиме зображення «Freepascal meets SDL». Після цього вікно автоматично закривається. На наступному скріншоті показано результат виконання програми.

Result screenshot for chapter 4
Creative Commons License Це зображення від https://www.freepascal-meets-sdl.net ліцензовано під Creative Commons Attribution 4.0 International License.
Результат виконання програми.

А тепер давайте займемося кодом поетапно. Світло-сині позначені рядки позначають кодові рядки, які будуть обговорені далі. Для кращої орієнтації в лістингу все ще відображається весь код.


program Chapter4_SDL2;

uses SDL2, SDL2_image;

var
sdlWindow1 : PSDL_Window;
sdlRenderer : PSDL_Renderer;
sdlTexture1 : PSDL_Texture;


begin

  //ініціалізація підсистеми відео
  if SDL_Init( SDL_INIT_VIDEO ) < 0 then HALT;

  sdlWindow1 := SDL_CreateWindow( 'Window1', 50, 50, 500, 500, SDL_WINDOW_SHOWN );
  if sdlWindow1 = nil then HALT;

  sdlRenderer := SDL_CreateRenderer( sdlWindow1, -1, 0 );
  if sdlRenderer = nil then HALT;

  sdlTexture1 := IMG_LoadTexture( sdlRenderer, 'C:\fpsdl.bmp' );
  if sdlTexture1 = nil then HALT;
  SDL_RenderCopy( sdlRenderer, sdlTexture1, nil, nil );
  SDL_RenderPresent (sdlRenderer);
  SDL_Delay( 2000 );

  SDL_DestroyTexture( sdlTexture1 );
  SDL_DestroyRenderer( sdlRenderer );
  SDL_DestroyWindow ( sdlWindow1 );

  //вимкнення відеосистеми
  SDL_Quit;

end.

Зараз обговоримо перші вісім рядків. Ну, перший рядок запускає програму Pascal, як зазвичай. На відміну від попередньої частини, в розділ uses додано модуль SDL2_image. Щоб знову було зрозуміло, чистий SDL 2.0 не підтримує різні формати зображень, за винятком файлів зображень BMP. Хоча чистий SDL 2.0 дозволяє завантажувати файли зображень BMP, він просто дозволяє створювати SDL_Surface, але ми хотіли б створити SDL_Texture.

Нам потрібна змінна текстури, до якої ми можемо завантажувати інформацію про зображення з графічного файлу. Це буде “sdlTexture1” типу PSDL_Texture. Усі ці типи змінних є вказівними типами, що позначається великою літерою "P" на початку імен типів змінних.

program Chapter4_SDL2;

uses SDL2, SDL2_image;

var
sdlWindow1 : PSDL_Window;
sdlRenderer : PSDL_Renderer;
sdlTexture1 : PSDL_Texture;

begin

  //ініціалізація підсистеми відео
  if SDL_Init( SDL_INIT_VIDEO ) < 0 then HALT;

  sdlWindow1 := SDL_CreateWindow( 'Window1', 50, 50, 500, 500, SDL_WINDOW_SHOWN );
  if sdlWindow1 = nil then HALT;

  sdlRenderer := SDL_CreateRenderer( sdlWindow1, -1, 0 );
  if sdlRenderer = nil then HALT;

  sdlTexture1 := IMG_LoadTexture( sdlRenderer, 'C:\fpsdl.bmp' );
  if sdlTexture1 = nil then HALT;
  SDL_RenderCopy( sdlRenderer, sdlTexture1, nil, nil );
  SDL_RenderPresent (sdlRenderer);
  SDL_Delay( 2000 );

  SDL_DestroyTexture( sdlTexture1 );
  SDL_DestroyRenderer( sdlRenderer );
  SDL_DestroyWindow ( sdlWindow1 );

  //вимкнення відеосистеми
  SDL_Quit;

end.

Як і будь-яка програма, що написана на Pascal, основна частина програми блок begin-end починається зі службового слова “begin”. Ініціалізація SDL 2.0 починається, як вже детально обговорювалось в попередніх частинах, функцією SDL_Init().

Після успішної ініціалізації SDL 2.0 створюється вікно із заголовком “Window1” та візуалізатором, як відомо з відповідної попередньої частини.

Створення SDL_Texture та візуалізація в SDL 2.0

program Chapter4_SDL2;

uses SDL2, SDL2_image;

var
sdlWindow1 : PSDL_Window;
sdlRenderer : PSDL_Renderer;
sdlTexture1 : PSDL_Texture;

begin

  //ініціалізація підсистеми відео
  if SDL_Init( SDL_INIT_VIDEO ) < 0 then HALT;

  sdlWindow1 := SDL_CreateWindow( 'Window1', 50, 50, 500, 500, SDL_WINDOW_SHOWN );
  if sdlWindow1 = nil then HALT;

  sdlRenderer := SDL_CreateRenderer( sdlWindow1, -1, 0 );
  if sdlRenderer = nil then HALT;

  sdlTexture1 := IMG_LoadTexture( sdlRenderer, 'C:\fpsdl.bmp' );
  if sdlTexture1 = nil then HALT;
  SDL_RenderCopy( sdlRenderer, sdlTexture1, nil, nil );
  SDL_RenderPresent (sdlRenderer);
  SDL_Delay( 2000 );

  SDL_DestroyTexture( sdlTexture1 );
  SDL_DestroyRenderer( sdlRenderer );
  SDL_DestroyWindow ( sdlWindow1 );

  //вимкнення відеосистеми
  SDL_Quit;

end.

Тепер ми завантажуємо зображення з файлу в SDL_Texture, яку ми назвали“sdlTexture1”. Функція, яка це виконує:

IMG_LoadTexture(renderer: PSDL_Renderer; _file: PAnsiChar): PSDL_Texture

Цю функцію надає SDL2_image. Її префікс IMG замість SDL для рідних функцій SDL 2.0. Саме для цієї функції ми додали SDL2_image в розділ uses.Параметри цієї функції - це візуалізатор, тобто “sdlRenderer” для нас, а як другий параметр абсолютний або відносний шлях до файлу зображення, для нас це “C:\fpsdl.bmp”. Звичайно, Ви можете використовувати будь-який інший каталог для зберігання/завантаження зображення або навіть використовувати інше зображення. Функція автоматично розпізнає формат файлу зображення, тому сміливо завантажуйте будь-який із дозволених форматів. Якщо завантаження не вдається, наприклад, Ви вказали неправильний шлях як аргумент, ця функція поверне nil.

Далі ми хотіли б, щоб успішно завантажене зображення в “sdlTexture1” було візуалізовано, з цієї причини ми передаємо його в візуалізатор за функцією

SDL_RenderCopy(renderer: PSDL_Renderer; texture: PSDL_Texture; srcrect: PSDL_Rect; dstrect: PSDL_Rect): SInt32.

Спочатку ця функція запитує візуалізатор (безпосередньо для відповідного вікна), до якого ми хотіли б скопіювати текстуру. У нашому випадку це буде знову “sdlRenderer”. Далі потрібна текстура, яку потрібно скопіювати у візуалізатор/вікно, тут це "sdlTexture1". Останні два параметри називаються "srcrect" і "dstrect" типу PSDL_Rect. PSDL_Rect - це попередньо визначений запис SDL 2.0 для визначення прямокутників, звідси і назва. Я не буду вдаватися в подробиці про це тут, але в наступному розділі Частина 10 ми дізнаємося більше про PSDL_Rect, хоча це буде в іншому контексті. Для простоти ми просто тут використовуємо nil як аргумент. Це виконує функцію передачі повної текстури у візуалізатор/вікно та розтягує її до розмірів вікна. Отже, зображення розміром 200 х 200 пікселів розтягується до 500 х 500 пікселів, останнє - ширина та висота вікна. Ця функція повертає 0 при успіху та негативний код при помилці.

Очистка пам'яті в SDL 2.0

program Chapter4_SDL2;

uses SDL2, SDL2_image;

var
sdlWindow1 : PSDL_Window;
sdlRenderer : PSDL_Renderer;
sdlTexture1 : PSDL_Texture;

begin

  //ініціалізація підсистеми відео
  if SDL_Init( SDL_INIT_VIDEO ) < 0 then HALT;

  sdlWindow1 := SDL_CreateWindow( 'Window1', 50, 50, 500, 500, SDL_WINDOW_SHOWN );
  if sdlWindow1 = nil then HALT;

  sdlRenderer := SDL_CreateRenderer( sdlWindow1, -1, 0 );
  if sdlRenderer = nil then HALT;

  sdlTexture1 := IMG_LoadTexture( sdlRenderer, 'C:\fpsdl.bmp' );
  if sdlTexture1 = nil then HALT;
  SDL_RenderCopy( sdlRenderer, sdlTexture1, nil, nil );
  SDL_RenderPresent (sdlRenderer);
  SDL_Delay( 2000 );

  SDL_DestroyTexture( sdlTexture1 );
  SDL_DestroyRenderer( sdlRenderer );
  SDL_DestroyWindow ( sdlWindow1 );

  //вимкнення відеосистеми
  SDL_Quit;

end.

Спочатку ми створили вікно, потім візуалізатор і, нарешті, текстуру. Отже, зараз ми йдемо протилежним шляхом, спочатку знищуємо текстуру, потім візуалізатор і, нарешті, вікно. Процедури:

SDL_DestroyTexture(texture: PSDL_Texture)

SDL_DestroyRenderer(renderer: PSDL_Renderer)

та

SDL_DestroyWindow(window: PSDL_Window).

Після вилучення об’єктів з пам'яті, потрібно завершити роботу SDL 2.0, як було показано в попередній частині.

Ого, нарешті ми це зробили. Вітаємо, ця частина закінчена :-). Проте чекає наступна частина.

← Попередня частина | Наступна частина →

Немає коментарів:

Дописати коментар