1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2000-2002 by the OpenSG Forum *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
37 \*---------------------------------------------------------------------------*/
39 //-------------------------------
41 //-------------------------------
48 #include "OSGConfig.h"
54 #include "OSGImageFileHandler.h"
55 #include "OSGPathHandler.h"
56 #include "OSGFileSystem.h"
58 #include "OSGHDRImageFileType.h"
60 // Static Class Varible implementations:
61 static const OSG::Char8
*suffixArray
[] =
68 #define MINELEN 8 // minimum scanline length for encoding
69 #define MAXELEN 0x7fff // maximum scanline length for encoding
70 #define MINRUN 4 // minimum run length
77 // copy source -> dest
78 #define copy_rgbe(c1, c2) (c2[RED]=c1[RED],c2[GRN]=c1[GRN],c2[BLU]=c1[BLU],c2[EXP]=c1[EXP])
80 /*! \class HDRImageFileType
82 Image File Type to read/write and store/restore Image objects as
85 All the type specific code is included in the class. Does
86 not depend on external libs.
90 /*****************************
92 *****************************/
94 HDRImageFileType
HDRImageFileType::_the("image/x-hdr",
95 suffixArray
, sizeof(suffixArray
),
97 OSG_WRITE_SUPPORTED
);
100 /*****************************
102 *****************************/
105 /********************************
107 *******************************/
110 /*******************************
112 *******************************/
114 //-------------------------------------------------------------------------
116 Tries to fill the image object with the data read from
117 the given input stream. Returns true on success.
120 bool HDRImageFileType::read( Image
*image
,
122 const std::string
&mimetype
)
126 if (!checkHDR(is
, width
, height
))
128 FWARNING(("No valid RADIANCE picture format\n"));
132 bool use16BitFloat
= false;
134 if(this->hasOption("use16BitFloat") == true)
136 this->getOptionAs("use16BitFloat", use16BitFloat
);
139 image
->set(Image::OSG_RGB_PF
,
143 (use16BitFloat
== true) ?
144 Image::OSG_FLOAT16_IMAGEDATA
: Image::OSG_FLOAT32_IMAGEDATA
);
146 if(!image
->isValid())
153 Real16
*data
= reinterpret_cast<Real16
*>(image
->editData());
155 return radiance2fp(is
, data
, width
, height
);
159 Real32
*data
= reinterpret_cast<Real32
*>(image
->editData());
161 return radiance2fp(is
, data
, width
, height
);
165 //-------------------------------------------------------------------------
167 Tries to write the image object to the given output stream.
168 Returns true on success.
171 bool HDRImageFileType::write(const Image
*image
,
173 const std::string
&mimetype
)
175 if( (image
->getDataType() != Image::OSG_FLOAT32_IMAGEDATA
) &&
176 (image
->getDataType() != Image::OSG_FLOAT16_IMAGEDATA
) )
178 FWARNING(("HDRImageFileType::write: Image has non float data "
186 int width
= image
->getWidth();
187 int height
= image
->getHeight();
189 os
<< "#?RADIANCE" << std::endl
;
190 os
<< "# Written with OpenSG" << std::endl
;
191 os
<< "FORMAT=32-bit_rle_rgbe" << std::endl
;
192 os
<< "EXPOSURE=" << 1.0f
<< std::endl
<< std::endl
;
193 os
<< "-Y " << height
<< " +X " << width
<< std::endl
;
195 RGBE
*rgbe_scan
= new RGBE
[width
];
197 if( image
->getDataType() == Image::OSG_FLOAT32_IMAGEDATA
)
199 const Real32
*data
= reinterpret_cast<const Real32
*>(image
->getData());
202 for(int y
=height
-1;y
>=0;y
--)
205 &data
[y
* width
* 3],
215 else // OSG_FLOAT16_IMAGEDATA
217 const Real16
*data
= reinterpret_cast<const Real16
*>(image
->getData());
220 for(int y
=height
-1;y
>=0;y
--)
223 &data
[y
* width
* 3],
238 //-------------------------------------------------------------------------
240 Tries to restore the image data from the given memblock.
241 Returns the amount of data read.
244 UInt64
HDRImageFileType::restoreData( Image
*image
,
245 const UChar8
*buffer
,
248 image
->setData(buffer
);
250 return image
->getSize();
253 //-------------------------------------------------------------------------
255 Tries to store the image data to the given memblock.
256 Returns the amount of data written.
259 UInt64
HDRImageFileType::storeData(const Image
*image
,
261 Int32
OSG_CHECK_ARG(memSize
)) const
263 UInt32 dataSize
= image
->getSize();
265 const UChar8
*src
= image
->getData();
267 if(dataSize
&& src
&& buffer
)
268 memcpy(buffer
, src
, dataSize
);
274 //-------------------------------------------------------------------------
276 Constructor used for the singleton object
279 HDRImageFileType::HDRImageFileType(const Char8
*mimeType
,
280 const Char8
*suffixArray
[],
281 UInt16 suffixByteCount
,
290 //-------------------------------------------------------------------------
295 HDRImageFileType::~HDRImageFileType(void)
299 // check header and get resolution (streaming type)
300 bool HDRImageFileType::checkHDR(std::istream
&is
, int &width
, int &height
)
302 char cs
[256], st1
[80], st2
[80];
307 while (!is
.eof() && !resok
)
311 if (strstr(cs
, "32-bit_rle_rgbe"))
314 if (HDRok
&& (cs
[0] == '\r' || cs
[0] == '\n' || cs
[0] == '\0'))
316 // empty line found, next is resolution info, format: -Y N +X N
317 // directly followed by data
320 i
= sscanf(cs
, "%79s %d %79s %d", st1
, &height
, st2
, &width
);
328 // convert radiance hdr to float image (streaming type)
329 bool HDRImageFileType::radiance2fp(std::istream
&is
,
335 RGBE
*sline
= new RGBE
[width
];
340 for(y
=height
-1;y
>=0;y
--)
343 if (!freadcolrs(is
, sline
, width
))
345 Real16
*fcol
= &data
[yx
* 3];
346 for (x
=0;x
<width
;x
++)
348 RGBE2Half(sline
[x
], fcol
);
358 // convert radiance hdr to float image (streaming type)
359 bool HDRImageFileType::radiance2fp(std::istream
&is
,
365 RGBE
*sline
= new RGBE
[width
];
370 for(y
=height
-1;y
>=0;y
--)
373 if (!freadcolrs(is
, sline
, width
))
375 Real32
*fcol
= &data
[yx
* 3];
376 for (x
=0;x
<width
;x
++)
378 RGBE2Float(sline
[x
], fcol
);
388 // read and decode a rgbe scanline (streaming type)
389 bool HDRImageFileType::freadcolrs(std::istream
&is
, RGBE
*scan
, int width
)
391 int i
,j
,code
,val
,size
;
394 if ((width
< MINELEN
) | (width
> MAXELEN
))
396 FWARNING(("Sorry, format probably too old\n"));
400 byte
= static_cast<unsigned char>(is
.get());
404 byte
= static_cast<unsigned char>(is
.get());
407 byte
= static_cast<unsigned char>(is
.get());
410 size
= (int(scan
[0][BLU
])) << 8;
413 if ( (size
| i
) != width
)
431 scan
[j
++][i
] = static_cast<unsigned char>(val
);
436 scan
[j
++][i
] = is
.get();
441 return is
.eof() ? false : true;
445 //rgbe -> float color
446 void HDRImageFileType::RGBE2Float(RGBE rgbe
, Real32
*fcol
)
450 *(fcol
+ RED
) = *(fcol
+ GRN
) = *(fcol
+ BLU
) = 0;
454 Real32 f
= ldexp(1., rgbe
[EXP
]-(COLXS
+8));
455 *(fcol
+ RED
) = (rgbe
[RED
]+.5)*f
;
456 *(fcol
+ GRN
) = (rgbe
[GRN
]+.5)*f
;
457 *(fcol
+ BLU
) = (rgbe
[BLU
]+.5)*f
;
461 void HDRImageFileType::RGBE2Half(RGBE rgbe
, Real16
*fcol
)
465 *(fcol
+ RED
) = *(fcol
+ GRN
) = *(fcol
+ BLU
) = 0;
469 Real32 f
= ldexp(1., rgbe
[EXP
]-(COLXS
+8));
471 *(fcol
+ RED
) = Real16( ( rgbe
[RED
]+.5) * f
);
472 *(fcol
+ GRN
) = Real16( ( rgbe
[GRN
]+.5) * f
);
473 *(fcol
+ BLU
) = Real16( ( rgbe
[BLU
]+.5) * f
);
477 int HDRImageFileType::fwritecolrs(std:: ostream
&os
,
484 for (int i
=0;i
<width
;i
++)
486 float2RGBE(scan
, rgbe_scan
[i
]);
490 return fwriteRGBE(os
, rgbe_scan
, width
, height
);
493 int HDRImageFileType::fwritecolrs(std:: ostream
&os
,
500 for(int i
=0;i
<width
;i
++)
502 half2RGBE(scan
, rgbe_scan
[i
]);
506 return fwriteRGBE(os
, rgbe_scan
, width
, height
);
509 int HDRImageFileType::fwriteRGBE(std::ostream
&os
,
514 int i
, j
, beg
, c2
, cnt
=0;
516 if ((width
< MINELEN
) | (width
> MAXELEN
))
518 // OOBs, write out flat
519 os
.write(reinterpret_cast<char *>(rgbe_scan
), width
);
524 os
<< static_cast<unsigned char>(2);
525 os
<< static_cast<unsigned char>(2);
526 os
<< static_cast<unsigned char>(width
>>8);
527 os
<< static_cast<unsigned char>(width
&255);
529 // put components seperately
532 for (j
=0;j
<width
;j
+=cnt
)
535 for (beg
=j
;beg
<width
;beg
+=cnt
)
540 (rgbe_scan
[beg
+cnt
][i
]==rgbe_scan
[beg
][i
]);
547 if (((beg
-j
)>1) && ((beg
-j
) < MINRUN
))
550 while (rgbe_scan
[c2
++][i
] == rgbe_scan
[j
][i
])
555 os
<< static_cast<unsigned char>(128+beg
-j
);
556 os
<< static_cast<unsigned char>(rgbe_scan
[j
][i
]);
565 if ((c2
= beg
-j
) > 128)
567 os
<< static_cast<unsigned char>(c2
);
570 os
<< rgbe_scan
[j
++][i
];
575 os
<< static_cast<unsigned char>(128+cnt
);
576 os
<< rgbe_scan
[beg
][i
];
584 return (os
.fail() ? -1 : 0);
587 //float color -> rgbe
588 void HDRImageFileType::float2RGBE(const Real32
*fcol
, RGBE rgbe
)
590 Real32 d
= (*(fcol
+ RED
) > *(fcol
+ GRN
)) ? *(fcol
+ RED
) : *(fcol
+ GRN
);
592 if(*(fcol
+ BLU
) > d
)
598 rgbe
[RED
] = rgbe
[GRN
] = rgbe
[BLU
] = rgbe
[EXP
] = 0;
603 d
= frexp(d
, &e
) * 256.f
/ d
;
604 rgbe
[RED
] = static_cast<unsigned char>(*(fcol
+ RED
) * d
);
605 rgbe
[GRN
] = static_cast<unsigned char>(*(fcol
+ GRN
) * d
);
606 rgbe
[BLU
] = static_cast<unsigned char>(*(fcol
+ BLU
) * d
);
607 rgbe
[EXP
] = static_cast<unsigned char>(e
+ COLXS
);
612 void HDRImageFileType::half2RGBE(const Real16
*fcol
, RGBE rgbe
)
614 Real32 d
= (*(fcol
+ RED
) > *(fcol
+ GRN
)) ? *(fcol
+ RED
) : *(fcol
+ GRN
);
616 if(*(fcol
+ BLU
) > d
)
622 rgbe
[RED
] = rgbe
[GRN
] = rgbe
[BLU
] = rgbe
[EXP
] = 0;
627 d
= frexp(d
, &e
) * 256.f
/ d
;
628 rgbe
[RED
] = static_cast<unsigned char>(*(fcol
+ RED
) * d
);
629 rgbe
[GRN
] = static_cast<unsigned char>(*(fcol
+ GRN
) * d
);
630 rgbe
[BLU
] = static_cast<unsigned char>(*(fcol
+ BLU
) * d
);
631 rgbe
[EXP
] = static_cast<unsigned char>(e
+ COLXS
);