В этой статье речь пойдет о написании плагина для 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 != 0x0a) { 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
ссылка на оригинал статьи http://habrahabr.ru/post/258851/
Добавить комментарий