Вторник, 16.04.2024, 06:52
PIXELCODEПриветствую Вас Гость | RSS
Главная | Каталог статей | Регистрация | Вход
Меню сайта

Категории раздела
SDL и C/C++ [6]

Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0

Форма входа

Главная » Статьи » SDL и C/C++

Статья 2. Загрузка и вывод изображения в формате bmp на экран
   Цель урока: загрузить изображение из графического bmp-файла и вывести его в SDL  поверхность для трех настроенных в первой статье платформ (Linux, Windows, WindowsCE).

   Содержание статьи:
1. Введение;
2. Особенности WindowsCE;
3. Компиляция примера;
4. Заключение.

   1. Введение
   Продолжим изучение кросс-платформенной графической библиотеки SDL в Linux. Для компиляции исходников статьи нужно настроить компиляторы, как описано здесь. Сегодня научимся загружать bitmap’ы – графические файлы с расширением .bmp. Почему не gif, или tga, спросите Вы – они же значительно меньше «весят»? Все верно, но SDL без библиотеки-расширения SDL_Image поддерживает только загрузку .bmp-файлов. Со временем научимся грузить и их =)

 
 2. Особенности WindowsCE

   Для загрузки в системах Windows и Linux, если графический файл picture.bmp поместить в папку с исполняемым файлом, достаточно такого кода:

SDL_Surface *loaded_picture=NULL;//поверхность SDL для загружаемой картинки
…инициализация SDL...
loaded_picture= SDL_LoadBMP("picture.bmp”);//сама загрузка


   Этот код в WinCE, к сожалению, ничего не загрузит. А все из-за того, что в WinCE отсутствует понятие текущей директории, там для загрузки картинки в общем случае требуется указать полный путь. Допустим, если файл picture.bmp размещен в корне карты памяти:
loaded_picture= SDL_LoadBMP("Storage Card/picture.bmp”);//простая загрузка в wince
   Так-же полный путь, указанный для загрузки в программе для Linux поможет избежать неуверенной загрузки картинки при запуске программы из GUI-файловых менеджеров (konqueror, dolphin и др.), которые не всегда корректно обозначают текущую директорию.
   Это не прибавляет удобства как для кросс-компиляции, так и для готовой программы. Ведь мы не знаем заранее в какой папке пользователь разместит екзешник и ресурсы. А просить его сделать это в заранее заданном месте как-то не солидно =).
Тут можно попробовать узнать из какой папки был запущен исполняемый файл, и в зависимости от этого настроить загрузку нашей картинки.
   Создайте чистую папку для нового микропроекта. В ней создайте файл main.cpp. Для ресурсов в ней же создайте дополнительную папку res и в нее поместите небольшой файл picture.bmp.(ссылка на готовый проект в конце статьи – можете взять оттуда). Пишем в нашем main.cpp:

//Подключаем заголовочные файлы
#include <cstdio>//для printf
#include "SDL.h"
#include <cstring>//для работы со строками: strcpy и strcat

//Определим подстановки - символические константы
#define MAX_PATH_LENGTH 128 //максимальное кол-во символов пути исполняемого файла
#define RESOURCE_PATH "res/" //директория ресурсов программы
#define PICTURE "picture.bmp" //название файла картинки


Как Вы знаете, подстановки при компиляции будут заменены их значениями. Например, на место PICNURE будет подставлено "picture.bmp”. Это сделано для удобства, теперь, чтобы изменить путь к ресурсам программы или название загружаемого файла не нужно отыскивать все их вхождения в исходник. Достаточно изменить только одну строку в начале программы. Далее:

//Глобальные константы и переменные
const int SCREEN_WIDTH= 240;
const int SCREEN_HEIGHT= 320;
const int SCREEN_BPP= 16;
const char resource_name[]= RESOURCE_PATH;//создаем массив символов с путем от экзешника до ресурсов "res”
const char pict_name[]= PICTURE;//имя .bmp-файла
Uint32 back_color;//Этим цветом буду закрашивать экран
SDL_Surface *screen= NULL;//Основная поверхность SDL
SDL_Surface *loaded_picture=NULL;//поверхность SDL для загружаемой картинки


Выше мы задали две строки – два символьных массива: resource_name и pict_name, оканчивающихся нуль-терминатором. О работе со строками в С/С++ можно прочитать хотя бы здесь, или здесь.

Далее, используя нулевой аргумент функции main посмотрим, что передает ей каждая из наших операционных систем:

linux (console, mc):                              ./prog_name
linux (файловые менеджеры с GUI):     /home/proj/prog_name
win32:                                                 D:\proj\prog_name.exe
wince:                                                 \Storage Card\proj\prog_name.exe

а получить мы в итоге хотим:
linux (console, mc):                              ./res/picture.bmp
linux (файловые менеджеры с GUI):     /home/proj/res/picture.bmp
win32:                                                 /res/picture.bmp
wince:                                                 /Storage Card/proj/res/picture.bmp

Рассмотим код далее:

////////////////////////////////////////////////
// ГЛАВНАЯ ФУНКЦИЯ ПРОГРАММЫ                 
////////////////////////////////////////////////

int main( int argc, char* args[] )
{

  char res_path[MAX_PATH_LENGTH];//Путь запуска файла
  res_path[0] = '\000';//пока стринг пуст
  strcpy(res_path, args[0]);//скопировали полный путь запуска в res_path

  printf("from OS=%s\n", res_path);

  if (res_path[0]!='.')//Если вызов не из консоли linux или mc, то...
    {
      //Перевернем обратные слэши Windows
      for (unsigned int i= 0 ;i!= (strlen(res_path)-1); ++i)//работаем по длине стринга
        {
          if (res_path[i]=='\\') res_path[i]='/';//если нашли \, заменяем на /
        }
    }

  //отсечем имя программы справа до первого слэша - просто заполним нулями
  for (int i= (strlen(res_path)-1);(res_path[i] !='/') && (i>=0); --i) res_path[i]='\000';

#ifndef UNDER_CE//Если это не wince
#ifdef _WIN32//И это 32-разрядная windows
  res_path[0]='\000';//то очистим путь во избежание проблем с кирилицей в папках Windows
#endif
#endif


   Здесь мы получаем в массив символов res_path нулевой аргумент, переданный ОС нашей функции main — путь ее запуска. Что, собственно и распечатывается в строке printf("from OS=%s\n", res_path);.Забыл сказать, что увидеть консольный вывод в WindowsCE штатными средствами нельзя — их просто нет =). Зато есть программа PocketConsole v1.3 (пользователи WinMobile5 не забудьте подправить реестр — там написано как и что сделать). Она автоматически запускается для приложений с консольным выводом. Не спрашивайте как она это делает — я не знаю, но она работает=).
   Далее, для вызова из консоли или mc просто отсекаем имя программы, для всех отальных ОС «переворачиваем» слэши Windows. Именно так — слэши для Linux и  компиляторов семейства GCC должны быть прямыми, а не обратными как в семействе Windows (нужно переворачивать). В конце манипуляций отсекаем имя программы — оно нам не нужно.
Еще один момент: чтобы избежать проблем с русскоязычными названиями в пути «большой» Windows (с CE, как ни странно все нормально), будем грузиться в ней только по относительному пути. Т.е. Для нее res_path очищаем.

В коде выше применена условная компиляция для задания кода только для «большой» Windows:

#ifndef UNDER_CE//Если это не wince
#ifdef _WIN32//И это 32-разрядная windows
  res_path[0]='\000';//то очистим путь во избежание проблем с кирилицей в папках Windows
#endif
#endif


   Аналогично можно иcпользовать  #ifdef linux и #ifdef _WIN32 (соответственно только для Linux и всех 32-битных Windows, включая WinCE). Только в конце блоков условной компиляции не забывайте #endif.
   Итак в переменной (хотя это массив) res_path получили ./ или полный путь до исплняемого файла для linux, пустой стринг для win32 и путь к исполяемому файлу для wince. Добавим res/ имя папки с ресурсами и имя нашей картинки picture.bmp:

  strcat(res_path, resource_name);//добавим наименование каталога ресурсов
  strcat(res_path, pict_name);//добавим имя файла-картинки
  printf("loading path=%s \n", res_path);


   Оператор printf... и здесь позволит нам проконтролировать то ли мы получаем в итоге, что нужно.
Ок. Теперь в res_path все готово для загрузки. Инициализируем SDL и грузим:

//Start SDL
  printf("SDL initialization...\n");
  if (SDL_Init(SDL_INIT_VIDEO)== -1)
    {
      printf("SDL initializing failure!\n");
      return 1;
    }
  else printf("SDL initializing -- Ok\n");

  //Set up the screen
#ifdef UNDER_CE// Под WinCE используем полноэкранное окно, исп. основную память и абсолютный путь файлов
  screen= SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_SWSURFACE | SDL_FULLSCREEN);
#else //Под Win32 и Linux используем стандартное окно и память видеокарты для размещения поверхностей SDL
  screen= SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, SDL_HWSURFACE);
#endif

//If there was an error in setting up the screen
  if (screen== NULL)
    {
      printf("Unable to SetVideoMode\n");
      return 1;
    }
  else printf("VideoMode settings -- Ok\n");

  //очистим экран черным цветом
  SDL_LockSurface(screen);
  back_color= SDL_MapRGB(screen->format, 0, 0, 0); //получили back_color в формате screen
  SDL_FillRect (screen, NULL, back_color);
  SDL_UnlockSurface(screen);
  SDL_Flip (screen);

  //загрузим картинку из найденного ранее пути res_path
  loaded_picture= SDL_LoadBMP(res_path);
  SDL_BlitSurface(loaded_picture, NULL, screen, NULL);
  SDL_Flip (screen);

  SDL_Delay(4000);// Задержка перед выходом чтобы увидеть результат работы программы

  //удалим поверхности SDL перед выходом
  printf("SDL quiting...\n");
  SDL_FreeSurface(loaded_picture);
  SDL_FreeSurface(screen);
  SDL_Quit();

  return 0;
}


   Теперь файл main.cpp сохраним, скомпилируем под linux при помощи Makefile из первой статьи. Запустим. Работает? Если нет, то проверьте, рядом с Вашим исходником должна быть папка с именем res, а в ней должна лежать картинка picture.bmp.
  Получилось? Отлично! Попробуйте сами скомпилировать так же под win32 и wince.
  P.S.: Исходный файл, Makefile, picture.bmp и готовые исполняемые файлы для 3-х платформ можно скачать здесь. Примечание: там-же лежит SDL.dll для запуска в win32 или в Wine.
 
  Статья обновлена 12 января 2010 года.


Категория: SDL и C/C++ | Добавил: J3d1 (06.01.2010)
Просмотров: 12401 | Комментарии: 3 | Теги: SDL, кросскомпиляция, WinCE, Codeblocks, Кросс-компиляция в Linux | Рейтинг: 5.0/1
Всего комментариев: 3
1 dimanche13  
0
познавательная статья

2 Al-Rado  
0
Да, статья полезная. Спасибо!

3 J3d1  
0
smile

Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Поиск

Друзья сайта
  • Все для веб-мастера
  • Программы для всех
  • Мир развлечений
  • Лучшие сайты Рунета

  • Copyright MyCorp © 2024 Создать бесплатный сайт с uCoz