📜 ⬆️ ⬇️

Writing an image file plugin for OpenSceneGraph

This article is about writing a plugin for OpenSceneGraph. The plugin adds the ability to use the PCX format from ZSoft Corporation. The code is simplified to the limit and includes only the reading function, I suggest writing the writing function yourself. I understand that on the site www.openscenegraph.org you can download the source code of the plug-ins and see how everything works, but the formatting of the source was somewhat surprising and I decided to sort it out. And leave a note for yourself, so as not to forget.

image

Main class


First, we need to create a class, a successor of the osgDB :: ReaderWriter class. 3D plug-ins also use this class:

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); }; 

As is clear from the code above, this is a description of the functions of the plug-in for reading and writing the file, as well as setting the class name and the file extension used. I will not give the rest of the code. You can see it at the link at the end of the article or in the OpenSceneGraph source for another example. It opens the file, checks for matching extensions, file availability, and so on.
')
 ReaderWriterPCX::ReaderWriterPCX() { supportsExtension("pcx","PCX Image format"); } const char* ReaderWriterPCX::className() const { return "PCX Image Reader"; } 

Main function


Although the function type is returned and osgDB :: ReaderWriter :: ReadResult, but in this case it returns osg :: Image. First of all, we need to know some image parameters, such as image dimensions and the pixel data itself. The alpha channel does not use this format, and we will make only 256+ support for the palette. This format uses super duper RLE data compression. Quote from wiki:
The algorithm of such compression is very fast and takes up a small amount of memory, however, it is not very effective, impractical for compressing photos and more detailed computer graphics.

Lossless compression is used. When saving an image, successive pixels of the same color are combined, and instead of specifying the color for each pixel, the color of the group of pixels and their number are indicated. Such an algorithm compresses well images in which there are areas of the same color.

So, open the file and read its signature. If it is correct, go ahead. We also check the rest of the data, read the dimensions, the palette (it is located at the end of the file for 256 colors).

 fin.read((char*) &pcx->Identifier, sizeof(pcx->Identifier)); if (pcx->Identifier != 0x0a) { OSG_WARN << "Invalid PCX Identifier\n"; return 0; } 

And the decompression algorithm itself:

 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; } } 

The imageBuffer array is our data. It consists of three colors, multiplied by the number of pixels. That is, this is our unpacked data. They will be used when installing image data, and the format and size will be selected GL_RGB and 3 bytes, respectively.

The plugin must be copied to the folder with the plug-ins. I have this /usr/lib/osgPlugins-3.2.0/ (I use Linux). You can check it by using osgmovie, which is in the examples. At the end of the file should be specified the code connecting the plugin:

 REGISTER_OSGPLUGIN(pcx, ReaderWriterPCX) 

Epilogue


The presence of plug-ins makes it possible to use OpenSceneGraph to write engines for old games with new graphics or to use their data storage formats in games. In the next article we plan to write a plugin for reading the 3D format.

Sources: bitbucket.org/darkprof/pcx/src

Source: https://habr.com/ru/post/258851/


All Articles