[Из песочницы] Пишем плагин чтения файла изображений для OpenSceneGraph
В этой статье речь пойдет о написании плагина для OpenSceneGraph. Плагин добавляет возможность использования формата PCX фирмы ZSoft Corporation. Код упрощен до предела и включает в себя только функцию чтения, функцию записи предлагаю написать самим. Я понимаю, что на сайте www.openscenegraph.org можно скачать исходники плагинов и посмотреть, как все работает, но форматирование исходников меня несколько удивило и я решил разложить все по полочкам. И оставить для себя заметку, чтоб не забыть.Главный классВо-первых, нам надо создать класс, наследник класса osgDB: ReaderWriter. Плагины 3D форматов тоже используют этот класс: class ReaderWriterPCX: public osgDB: ReaderWriter { public: ReaderWriterPCX (); const char* className () const; ReadResult readObject (std: istream& fin, const Options* options = 0) const; ReadResult readObject (const std: string& file, const Options* options = 0) const; ReadResult readImage (std: istream& fin, const Options* options = 0) const; ReadResult readImage (const std: string& file, const Options* options = 0) const; WriteResult writeImage (const osg: Image& image, std: ostream& fout, const Options* = 0) const; WriteResult writeImage (const osg: Image& img, const std: string& fileName, const Options* options = 0) const; private: static ReadResult readPCXStream (std: istream& fin); }; Как понятно из кода выше — это описание функций плагина для чтения и записи файла, а также установки имени класса и используемого расширения файла. Остальной код приводить не буду. Его вы сможете посмотреть по ссылке в конце статьи или в исходниках OpenSceneGraph для другого примера. В нем открытие файла, проверка на соответствие расширений, наличие файла и так далее. ReaderWriterPCX: ReaderWriterPCX () { supportsExtension («pcx», «PCX Image format»); }
const char* ReaderWriterPCX: className () const { return «PCX Image Reader»; } Главная функция Хоть возвращаемый тип функций и osgDB: ReaderWriter: ReadResult, но в данном случае возвращается osg: Image. Нам, во-первых, необходимо узнать некоторые параметры изображения, такие как размеры изображения и сами данные пикселей. Альфа-канал данный формат не использует, а поддержку палитры сделаем только 256+. Данный формат использует супер пупер сжатие данных RLE. Цитата из Вики: Алгоритм такого сжатия очень быстрый и занимает небольшой объём памяти, однако не очень эффективен, непрактичен для сжатия фотографий и более детальной компьютерной графики.Используется сжатие без потерь. При сохранении изображения подряд идущие пиксели одинакового цвета объединяются и вместо указания цвета для каждого пикселя указывается цвет группы пикселей и их количество. Такой алгоритм хорошо сжимает изображения, в которых присутствуют области одного цвета.
Итак, открываем файл и считываем его сигнатуру. Если она правильная — идем дальше. Проверяем и остальные данные, считываем размеры, палитру (она находится в конце файла для 256 цветов). fin.read ((char*) &pcx→Identifier, sizeof (pcx→Identifier)); if (pcx→Identifier!= 0×0a) { OSG_WARN << "Invalid PCX Identifier\n"; return 0; } И непосредственно сам алгоритм распаковки: for (int h = height_ret - 1; h >= 0; --h) { for (int w = 0; w < width_ret; ++w) { if(!count) { if(!fin.read((char*) &tmp, sizeof(tmp))) { OSG_WARN << "file truncated\n"; return 0; } if( (tmp & 0xc0) == 0xc0) { count = tmp & 0x3f; if(!fin.read((char*) &tmp, sizeof(tmp))) { OSG_WARN << "file truncated\n"; return 0; } } else { count = 1; } } index = h * width_ret + w; imageBuffer[index].red = colorPalette[tmp].red; imageBuffer[index].green = colorPalette[tmp].green; imageBuffer[index].blue = colorPalette[tmp].blue; --count; } } Массив imageBuffer и есть наши данные. Он состоит трех цветов, помноженных на количество пикселей. То есть это и есть наши распакованные данные. Именно они будут использоваться при установке данных изображения, а формат и размер будет выбран GL_RGB и 3 байта соответственно.Плагин нужно скопировать в папку с плагинами. У меня это /usr/lib/osgPlugins-3.2.0/ (я использую Linux). Проверить его можно открыв с помощью osgmovie, который есть в примерах. В конце файла должен быть указан код, подключающий плагин:
REGISTER_OSGPLUGIN (pcx, ReaderWriterPCX) Эпилог Наличие плагинов дает возможность использовать OpenSceneGraph для написания движков под старые игры с новой графикой или использовать свои форматы хранения данных в играх. В следующей статье планируется написать плагин для чтения 3D формата.Исходники: bitbucket.org/darkprof/pcx/src