Среда, 15.05.2024, 13:28
Personal dimanche13 site
Главная | Регистрация | Вход Приветствую Вас Гость | RSS
Категории каталога
Мои статьи [22]
BlitzMax [17]
раздел содержит статьи относящиеся к языку программирования BlitzMax
SDL [9]
раздел содержит статьи на тему SDL
Code::Blocks [3]
в этом разделе рассказывается как прикрутить движок к интегрированной среде разработки(IDE) Code::Blocks
Форма входа
Поиск
Друзья сайта
Главная » Статьи » SDL

Загрузка и вывод изображения в формате .bmp на экран
Загрузка и вывод изображения в формате .bmp на экран

Содержание статьи:

1. Введение;
2. Особенности Linux и 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" //название файла картинки


Как Вы знаете, подстановки при компиляции будут заменены их значениями. Например, на место PICTURE будет подставлено "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 (http://pixelcode.ucoz.ru/J3d1/C-Articles/Article2_ldbmp/poccon13.tar.gz) (пользователи 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.

Финальный исходный код (файл 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" //название файла картинки

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


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

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

  char res_path[MAX_PATH_LENGTH];//Путь запуска файла
  res_path[0] = '\000';//Для ОС кроме wince используем текущую директорию

#ifdef UNDER_CE// под wince нужен путь запуска
  strcpy(res_path, args[0]);//скопировали полный путь запуска в res_path
  printf("%s\n", res_path);
  for (int i= 0 ;i!= MAX_PATH_LENGTH-1; ++i)// Перевернем обрантые слэши wince
  {
  if (res_path[i]=='\\') res_path[i]='/';//если нашли \, заменяем на /
  }
  for (int i= MAX_PATH_LENGTH-1;(res_path[i] !='/') && (i>=0); --i) res_path[i]='\000';//Отсечем имя.exe
#endif// закончили блок условной компиляции для wince

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

  printf("%d\n", strlen(resource_name));

  //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-х платформ можно скачать здесь(http://pixelcode.ucoz.ru/J3d1/C-Articles/Article2_ldbmp/a2_source.tar.gz). Примечание: там-же лежит SDL.dll для запуска в win32 или в Wine.
Если что-то не получается – пишите J3d1 (j3d1adm1n@yandex.ru)

Литература:
(1)
http://www.rsdn.ru/article/cpp/cstr.xml
(2)
http://gazette.linux.ru.net/lg76/articles/rus-rogers.html


Категория: SDL | Добавил: dimanche13 (09.01.2010) | Автор: J3d1
Просмотров: 7626 | Комментарии: 6 | Рейтинг: 0.0/0 |
Всего комментариев: 2
2 Aplusfraurdy  
0
Уважаемые покупатели, рады сказать вам о проведении оптовой продажи шин ROYALBLACK 10.00R20, 295/80R22.5, 385/65R22.5 и 9.00R20.

- Мы продаём шины зарекомендованных производителей и разных размеров, для заказа оптовой партии.
- Шины проходят требуемый контроль качества, что обеспечивает эффективность и безопасность при использовании.
- Предлагаем лучшие оптовые цены, которые позволят вам сэкономить деньги при закупке больших партий.

Независимо от того, нужна ли шина для региональной езды, дельнемагистральной езды или работ на скале, мы рады предложить вам хорошие условия при заказе шин оптом.

Свяжитесь с нами уже сегодня, чтобы изучить больше информации о нашей оптовой продаже шин.

<a href=https://asiancatalog.ru>Оптовая продажа шин и дисков</a>
<a href=https://asiancatalog.ru>Шины для легковых автомобилей KAPSEN</a>
<a href=https://asiancatalog.ru>Шины для грузовых автомобилей KORYO</a>
<a href=https://asiancatalog.ru>Шины для спецтехники DOUBLECOIN</a>
<a href=https://asiancatalog.ru>Индустриальные шины YINGBA</a>

Мы осуществляем доставку в город Уссурийск, Артем, Тверь или в любой другой город России.

Оптовая продажа шин и дисков в России и СНГ!
Мы поможем вам с выбором шин и дисков. Свяжитесь с нами по телефону или другим удобным способом для получения консультации.

Тел. +79644340397 (WhatsApp, Telegram, WeChat)

Эл.почта info@asiancatalog.ru

1 SergFrodA  
0
<a href=http://zmkshop.ru/>металлические опоры для мобильной связи</a>

Имя *:
Email *:
Код *:
Copyright MyCorp © 2024