root/OpenSceneGraph/trunk/src/osgPlugins/hdr/ReaderWriterHDR.cpp @ 13041

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

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2*
3* Copyright (C) 2004 Mekensleep
4*
5*    Mekensleep
6*    24 rue vieille du temple
7*    75004 Paris
8*       licensing@mekensleep.com
9*
10* This library is free software; you can redistribute it and/or
11* modify it under the terms of the GNU Lesser General Public
12* License as published by the Free Software Foundation; either
13* version 2.1 of the License, or (at your option) any later version.
14*
15* This library is distributed in the hope that it will be useful,
16* but WITHOUT ANY WARRANTY; without even the implied warranty of
17* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18* Lesser General Public License for more details.
19*
20* You should have received a copy of the GNU Lesser General Public
21* License along with this library; if not, write to the Free Software
22* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
23*
24* Author:
25*  Igor Kravtchenko <igor@obraz.net>
26*
27*/
28
29#include <osg/Image>
30#include <osg/Notify>
31#include <osg/Geode>
32#include <osg/GL>
33
34#include <osgDB/Registry>
35#include <osgDB/FileNameUtils>
36#include <osgDB/FileUtils>
37#include <osgDB/fstream>
38
39#include <stdio.h>
40#include <assert.h>
41#include <string.h>
42#include <stdlib.h>
43#include <sstream>
44
45#include "hdrloader.h"
46#include "hdrwriter.h"
47
48#ifndef GL_RGBA8
49    #define GL_RGBA8 0x8058
50#endif
51
52#ifndef GL_RGB8
53    #define GL_RGB8 0x8051
54#endif
55
56
57class ReaderWriterHDR : public osgDB::ReaderWriter
58{
59public:
60    ReaderWriterHDR()
61    {
62        supportsExtension("hdr","High Dynamic Range image format");
63        supportsOption("RGBMUL","");
64        supportsOption("RGB8","");
65        supportsOption("RAW","");
66        supportsOption("YFLIP","");
67        supportsOption("NO_YFLIP","");
68    }
69    virtual const char* className() { return "HDR Image Reader"; }
70
71    virtual ReadResult readImage(const std::string &_file, const osgDB::ReaderWriter::Options *_opts) const
72    {
73        std::string filepath = osgDB::findDataFile(_file, _opts);
74        if (filepath.empty())
75            return ReadResult::FILE_NOT_FOUND;
76
77        if (!HDRLoader::isHDRFile(filepath.c_str()))
78            return ReadResult::FILE_NOT_HANDLED;
79
80        float mul = 1.0f;
81        bool bYFlip = false;
82        bool convertToRGB8 = false;
83        bool rawRGBE = false;
84        if(_opts)
85        {
86            std::istringstream iss(_opts->getOptionString());
87            std::string opt;
88            while (iss >> opt)
89            {
90                if(opt == "RGBMUL")
91                {
92                    iss >> mul;
93                }
94                else if(opt == "RGB8")
95                {
96                    convertToRGB8 = true;
97                }
98                /* RAW: store the RGBE values into a Image, to use this option you
99                 * need to decode the RGBE value in the fragment shader. Follow
100                 * the cube map glsl decoder:
101                 *
102                 * vec4 textureCubeRGBE( uniform samplerCube sampler, vec3 coords )
103                 * {
104                 *     ivec4 rgbe = textureCube( sampler, coords ) * 255. + 0.5;
105                 *     float e = rgbe.a - ( 128 + 8 );
106                 *     return vec4( rgbe.rgb * exp2( e ), 1.0 );
107                 * }
108                 *
109                 */
110                else if(opt == "RAW")
111                {
112                    rawRGBE = true;
113                }
114                else if(opt == "YFLIP")
115                {
116                    bYFlip = true; // Image is flipped later if required
117                }
118            }
119        }
120
121        HDRLoaderResult res;
122        bool ret = HDRLoader::load(filepath.c_str(), rawRGBE, res);
123        if (!ret)
124            return ReadResult::ERROR_IN_READING_FILE;
125
126        // create the osg::Image to fill in.
127        osg::Image *img = new osg::Image;
128
129        // copy across the raw data into the osg::Image
130        if (convertToRGB8)
131        {
132            int nbPixs = res.width * res.height;
133            int nbElements = nbPixs * 3;
134            unsigned char *rgb = new unsigned char[ nbElements ];
135            unsigned char *tt = rgb;
136            float *cols = res.cols;
137
138            for (int i = 0; i < nbElements; i++) {
139                float element = *cols++;
140                element *= mul;
141                if (element < 0) element = 0;
142                else if (element > 1) element = 1;
143                int intElement = (int) (element * 255.0f);
144                *tt++ = intElement;
145            }
146
147            delete [] res.cols;
148
149            int pixelFormat = GL_RGB;
150            int dataType = GL_UNSIGNED_BYTE;
151
152            img->setFileName(filepath.c_str());
153            img->setImage(  res.width, res.height, 1,
154                            3, // Why this value are here?
155                            pixelFormat,
156                            dataType,
157                            (unsigned char*) rgb,
158                            osg::Image::USE_NEW_DELETE);
159        }
160        else
161        {
162            int internalFormat;
163            int pixelFormat;
164            int dataType = GL_FLOAT;
165
166            if (rawRGBE)
167            {
168                internalFormat = GL_RGBA8;
169                pixelFormat = GL_RGBA;
170            } else {
171                internalFormat = GL_RGB32F_ARB;
172                pixelFormat = GL_RGB;
173            }
174
175            img->setFileName(filepath.c_str());
176            img->setImage(  res.width, res.height, 1,
177                            internalFormat,
178                            pixelFormat,
179                            dataType,
180                            (unsigned char*) res.cols,
181                            osg::Image::USE_NEW_DELETE);
182        }
183
184        // Y flip
185        if(bYFlip==true) img->flipVertical();
186
187        return img;
188    }
189
190
191    // Additional write methods
192    virtual WriteResult writeImage(const osg::Image &image,const std::string& file, const osgDB::ReaderWriter::Options* options) const
193    {
194        std::string ext = osgDB::getFileExtension(file);
195        if (!acceptsExtension(ext)) return WriteResult::FILE_NOT_HANDLED;
196
197        osgDB::ofstream fout(file.c_str(), std::ios::out | std::ios::binary);
198        if(!fout) return WriteResult::ERROR_IN_WRITING_FILE;
199
200        return writeImage(image,fout,options);
201    }
202
203    virtual WriteResult writeImage(const osg::Image& image,std::ostream& fout,const Options* options) const
204    {
205
206        bool bYFlip = true;        // Whether to flip the vertical
207        bool rawRGBE = false;    // Whether to write as raw RGBE
208
209        if(options)
210        {
211            std::istringstream iss(options->getOptionString());
212            std::string opt;
213            while (iss >> opt)
214            {
215                if (opt=="NO_YFLIP")
216                {
217                    // We want to YFLIP because although the file format specification
218                    // dictates that +Y M +X N is a valid resolution line, no software (including
219                    // HDRShop!) actually recognises it; hence everything tends to be written upside down
220                    // So we flip the image first...
221                    bYFlip = false;
222                }
223                else if(opt=="RAW")
224                {
225                    rawRGBE = true;
226                }
227                /* The following are left out for the moment as
228                   we don't really do anything with them in OSG
229                else if(opt=="GAMMA")
230                {
231                   iss >> gamma;
232                }
233                else if(opt=="EXPOSURE")
234                {
235                    iss >> exposure;
236                }
237                */
238
239            }
240        }
241
242        // Reject unhandled image formats
243        if(rawRGBE==false)
244        {
245            if(image.getInternalTextureFormat()!=GL_RGB32F_ARB)    // We only handle RGB (no alpha) with 32F formats
246            {
247                return WriteResult::FILE_NOT_HANDLED;
248            }
249        }
250        else    // Outputting raw RGBE (as interpreted by a shader, for example)
251        {
252            if(image.getInternalTextureFormat()!=GL_RGBA8) // We need 8 bit bytes including alpha (E)
253            {
254                return WriteResult::FILE_NOT_HANDLED;
255            }
256        }
257
258        // Get a temporary copy to flip if we need to
259        osg::ref_ptr<osg::Image> source = new osg::Image(image,osg::CopyOp::DEEP_COPY_ALL);
260
261        if(bYFlip==true) source->flipVertical();
262
263        bool success;
264        success = HDRWriter::writeHeader(source.get(),fout);
265        if(!success)
266        {
267            source = 0;    // delete the temporary image
268            return WriteResult::ERROR_IN_WRITING_FILE;    // early out
269        }
270
271        success = HDRWriter::writeRLE(source.get(), fout);
272
273        source = 0; // delete the temporary image
274        return (success)? WriteResult::FILE_SAVED : WriteResult::ERROR_IN_WRITING_FILE;
275    }
276};
277
278// now register with Registry to instantiate the above
279// reader/writer.
280REGISTER_OSGPLUGIN(hdr, ReaderWriterHDR)
Note: See TracBrowser for help on using the browser.