root/OpenSceneGraph/trunk/src/osgPlugins/gta/ReaderWriterGTA.cpp @ 13041

Revision 13041, 14.2 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

Line 
1
2#include <osg/Image>
3
4#include <osgDB/Registry>
5#include <osgDB/FileUtils>
6#include <osgDB/FileNameUtils>
7
8#include <string>
9#include <sstream>
10#include <limits>
11#include <gta/gta.hpp>
12
13/* Copyright (C) 2011 Martin Lambers
14 *
15 * This library is open source and may be redistributed and/or modified under
16 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
17 * (at your option) any later version.  The full license is in LICENSE file
18 * included with this distribution, and on the openscenegraph.org website.
19 *
20 * This library is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23 * OpenSceneGraph Public License for more details.
24 */
25
26class ReaderWriterGTA : public osgDB::ReaderWriter
27{
28    public:
29
30        ReaderWriterGTA()
31        {
32            supportsExtension("gta","GTA (Generic Tagged Arrays) file format");
33            supportsOption("COMPRESSION","Set compression method: NONE, ZLIB (default), ZLIB1,...,ZLIB9, BZIP2, or XZ");
34        }
35
36        virtual const char* className() const { return "GTA Image Reader"; }
37
38        virtual bool acceptsExtension(const std::string& extension) const
39        {
40            return osgDB::equalCaseInsensitive(extension,"gta");
41        }
42
43        ReadResult local_readImage(std::istream& fin,const osgDB::ReaderWriter::Options* /* options */) const
44        {
45            int s,t,r;
46            int internalFormat;
47            unsigned int pixelFormat;
48            unsigned int dataType;
49            unsigned char* imageData = NULL;
50
51            std::string my_errmsg;
52            try
53            {
54                gta::header hdr;
55                hdr.read_from(fin);
56                if (hdr.data_size() > static_cast<uintmax_t>(std::numeric_limits<int>::max()))
57                {
58                    my_errmsg = "GTA too large";
59                    throw std::exception();
60                }
61                if (hdr.dimensions() < 1 || hdr.dimensions() > 3)
62                {
63                    my_errmsg = "GTA has less than 1 or more than 3 dimensions";
64                    throw std::exception();
65                }
66                s = t = r = 1;
67                for (uintmax_t i = 0; i < hdr.dimensions(); i++)
68                {
69                    if (hdr.dimension_size(i) > static_cast<uintmax_t>(std::numeric_limits<int>::max()))
70                    {
71                        my_errmsg = "GTA dimensions too large";
72                        throw std::exception();
73                    }
74                    if (i == 0)
75                        s = hdr.dimension_size(i);
76                    else if (i == 1)
77                        t = hdr.dimension_size(i);
78                    else
79                        r = hdr.dimension_size(i);
80                }
81                if (hdr.components() < 1 || hdr.components() > 4)
82                {
83                    my_errmsg = "GTA has less than 1 or more than 4 element components";
84                    throw std::exception();
85                }
86                pixelFormat =
87                    hdr.components() == 1 ? GL_LUMINANCE :
88                    hdr.components() == 2 ? GL_LUMINANCE_ALPHA :
89                    hdr.components() == 3 ? GL_RGB :
90                    GL_RGBA;
91                switch (hdr.component_type(0))
92                {
93                case gta::int8:
94                    dataType = GL_BYTE;
95                    break;
96                case gta::uint8:
97                    dataType = GL_UNSIGNED_BYTE;
98                    break;
99                case gta::int16:
100                    dataType = GL_SHORT;
101                    break;
102                case gta::uint16:
103                    dataType = GL_UNSIGNED_SHORT;
104                    break;
105                case gta::int32:
106                    dataType = GL_INT;
107                    break;
108                case gta::uint32:
109                    dataType = GL_UNSIGNED_INT;
110                    break;
111                case gta::float32:
112                    dataType = GL_FLOAT;
113                    break;
114                default:
115                    my_errmsg = "GTA component type(s) not supported";
116                    throw std::exception();
117                }
118                for (uintmax_t i = 1; i < hdr.components(); i++)
119                {
120                    if (hdr.component_type(i) != hdr.component_type(0))
121                    {
122                        my_errmsg = "GTA component types differ";
123                        throw std::exception();
124                    }
125                }
126                if (dataType == GL_BYTE || dataType == GL_UNSIGNED_BYTE)
127                {
128                    internalFormat = hdr.components();
129                }
130                else
131                {
132                    internalFormat =
133                        hdr.components() == 1 ? GL_LUMINANCE32F_ARB :
134                        hdr.components() == 2 ? GL_LUMINANCE_ALPHA32F_ARB :
135                        hdr.components() == 3 ? GL_RGB32F_ARB :
136                        GL_RGBA32F_ARB;
137                }
138                imageData = new unsigned char[hdr.data_size()];
139                hdr.read_data(fin, imageData);
140            }
141            catch (std::exception& e)
142            {
143                delete[] imageData;
144                if (!(my_errmsg.empty()))
145                {
146                    OSG_WARN << my_errmsg << std::endl;
147                }
148                else
149                {
150                    OSG_WARN << e.what() << std::endl;
151                }
152                return ReadResult::ERROR_IN_READING_FILE;
153            }
154
155            osg::Image* pOsgImage = new osg::Image;
156            pOsgImage->setImage(s,t,r,
157                internalFormat,
158                pixelFormat,
159                dataType,
160                imageData,
161                osg::Image::USE_NEW_DELETE);
162            pOsgImage->setOrigin(osg::Image::TOP_LEFT);
163
164            return pOsgImage;
165        }
166
167        WriteResult local_writeImage(std::ostream& fout,const osg::Image& img,const osgDB::ReaderWriter::Options* options) const
168        {
169            std::string my_errmsg;
170            try
171            {
172                gta::header hdr;
173                gta::compression compression = gta::zlib;
174                if (options)
175                {
176                    std::istringstream iss(options->getOptionString());
177                    std::string opt;
178                    std::string compressionMethod;
179                    while (iss >> opt)
180                    {
181                        if (opt == "COMPRESSION")
182                        {
183                            iss >> compressionMethod;
184                        }
185                    };
186                    if (compressionMethod == "NONE")
187                        compression = gta::none;
188                    else if (compressionMethod == "ZLIB")
189                        compression = gta::zlib;
190                    else if (compressionMethod == "ZLIB1")
191                        compression = gta::zlib1;
192                    else if (compressionMethod == "ZLIB2")
193                        compression = gta::zlib2;
194                    else if (compressionMethod == "ZLIB3")
195                        compression = gta::zlib3;
196                    else if (compressionMethod == "ZLIB4")
197                        compression = gta::zlib4;
198                    else if (compressionMethod == "ZLIB5")
199                        compression = gta::zlib5;
200                    else if (compressionMethod == "ZLIB6")
201                        compression = gta::zlib6;
202                    else if (compressionMethod == "ZLIB7")
203                        compression = gta::zlib7;
204                    else if (compressionMethod == "ZLIB8")
205                        compression = gta::zlib8;
206                    else if (compressionMethod == "ZLIB9")
207                        compression = gta::zlib9;
208                    else if (compressionMethod == "BZIP2")
209                        compression = gta::bzip2;
210                    else if (compressionMethod == "XZ")
211                        compression = gta::xz;
212                }
213                hdr.set_compression(compression);
214                if (img.s() > 0 && img.t() <= 1 && img.r() <= 1)
215                {
216                    hdr.set_dimensions(img.s());
217                }
218                else if (img.s() > 0 && img.t() > 1 && img.r() <= 1)
219                {
220                    hdr.set_dimensions(img.s(), img.t());
221                }
222                else if (img.s() > 0 && img.t() > 1 && img.r() > 1)
223                {
224                    hdr.set_dimensions(img.s(), img.t(), img.r());
225                }
226                else
227                {
228                    my_errmsg = "Image has unsupported dimensions";
229                    throw std::exception();
230                }
231                gta::type type;
232                switch (img.getDataType())
233                {
234                case GL_BYTE:
235                    type = gta::int8;
236                    break;
237                case GL_UNSIGNED_BYTE:
238                    type = gta::uint8;
239                    break;
240                case GL_SHORT:
241                    type = gta::int16;
242                    break;
243                case GL_UNSIGNED_SHORT:
244                    type = gta::uint16;
245                    break;
246                case GL_INT:
247                    type = gta::int32;
248                    break;
249                case GL_UNSIGNED_INT:
250                    type = gta::uint32;
251                    break;
252                case GL_FLOAT:
253                    type = gta::float32;
254                    break;
255                default:
256                    my_errmsg = "Image has unsupported data type";
257                    throw std::exception();
258                }
259                switch (img.getPixelFormat())
260                {
261                case 1:
262                case GL_DEPTH_COMPONENT:
263                case GL_LUMINANCE:
264                case GL_ALPHA:
265                    hdr.set_components(type);
266                    break;
267                case 2:
268                case GL_LUMINANCE_ALPHA:
269                    hdr.set_components(type, type);
270                    break;
271                case 3:
272                case GL_RGB:
273                    hdr.set_components(type, type, type);
274                    break;
275                case 4:
276                case GL_RGBA:
277                    hdr.set_components(type, type, type, type);
278                    break;
279                default:
280                    my_errmsg = "Image has unsupported pixel format";
281                    throw std::exception();
282                }
283                if (img.getPacking() != 1)
284                {
285                    my_errmsg = "Image has unsupported packing";
286                    throw std::exception();
287                }
288                hdr.write_to(fout);
289#if 0   /* Does not seem to be necessary */
290                if (img.t() > 1 && img.getOrigin() == osg::Image::BOTTOM_LEFT)
291                {
292                    int depth = (img.r() >= 1 ? img.r() : 1);
293                    const unsigned char* data = static_cast<const unsigned char*>(img.getDataPointer());
294                    size_t row_size = hdr.element_size() * img.s();
295                    gta::io_state io_state;
296                    for (int k = 0; k < depth; k++)
297                    {
298                        const unsigned char* slice = data + k * (row_size * img.t());
299                        for (int j = 0; j < img.t(); j++)
300                        {
301                            const unsigned char* p = slice + (img.t() - 1 - j) * row_size;
302                            hdr.write_elements(io_state, fout, img.s(), p);
303                        }
304                    }
305                }
306                else
307                {
308                    hdr.write_data(fout, img.getDataPointer());
309                }
310#endif
311                hdr.write_data(fout, img.getDataPointer());
312            }
313            catch (std::exception& e)
314            {
315                if (!(my_errmsg.empty()))
316                {
317                    OSG_WARN << my_errmsg << std::endl;
318                }
319                else
320                {
321                    OSG_WARN << e.what() << std::endl;
322                }
323                return WriteResult::ERROR_IN_WRITING_FILE;
324            }
325
326            return WriteResult::FILE_SAVED;
327        }
328
329        virtual ReadResult readObject(std::istream& fin,const osgDB::ReaderWriter::Options* options =NULL) const
330        {
331            return readImage(fin, options);
332        }
333
334        virtual ReadResult readObject(const std::string& file, const osgDB::ReaderWriter::Options* options =NULL) const
335        {
336            return readImage(file, options);
337        }
338
339        virtual ReadResult readImage(std::istream& fin,const osgDB::ReaderWriter::Options* options =NULL) const
340        {
341            return local_readImage(fin, options);
342        }
343
344        virtual ReadResult readImage(const std::string& file, const osgDB::ReaderWriter::Options* options) const
345        {
346            std::string ext = osgDB::getLowerCaseFileExtension(file);
347            if (!acceptsExtension(ext)) return ReadResult::FILE_NOT_HANDLED;
348
349            std::string fileName = osgDB::findDataFile( file, options );
350            if (fileName.empty()) return ReadResult::FILE_NOT_FOUND;
351
352            osgDB::ifstream istream(fileName.c_str(), std::ios::in | std::ios::binary);
353            if(!istream) return ReadResult::FILE_NOT_HANDLED;
354            ReadResult rr = local_readImage(istream, options);
355            if(rr.validImage()) rr.getImage()->setFileName(file);
356            return rr;
357        }
358
359        virtual WriteResult writeImage(const osg::Image& img,std::ostream& fout,const osgDB::ReaderWriter::Options* options) const
360        {
361            return local_writeImage(fout,img,options);
362        }
363
364        virtual WriteResult writeImage(const osg::Image &img,const std::string& fileName, const osgDB::ReaderWriter::Options *options) const
365        {
366            std::string ext = osgDB::getFileExtension(fileName);
367            if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED;
368
369            osgDB::ofstream fout(fileName.c_str(), std::ios::out | std::ios::binary);
370            if(!fout) return WriteResult::ERROR_IN_WRITING_FILE;
371
372            return writeImage(img,fout,options);
373        }
374};
375
376// now register with Registry to instantiate the above
377// reader/writer.
378REGISTER_OSGPLUGIN(gta, ReaderWriterGTA)
Note: See TracBrowser for help on using the browser.