00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #include <stdlib.h>
00044 #include <stdio.h>
00045 #include <math.h>
00046 #include <memory.h>
00047
00048 #include <OSGConfig.h>
00049
00050 #include <iostream>
00051 #include <fstream>
00052 #include <errno.h>
00053
00054 #ifdef _WIN32
00055 #ifdef min
00056 #undef min
00057 #endif
00058 #ifdef max
00059 #undef max
00060 #endif
00061 #endif
00062
00063 #ifdef OSG_WITH_IMF
00064 #include <OpenEXR/Iex.h>
00065 #include <OpenEXR/ImathBox.h>
00066 #include <OpenEXR/ImfIO.h>
00067 #include <OpenEXR/ImfHeader.h>
00068 #include <OpenEXR/ImfVersion.h>
00069 #include <OpenEXR/ImfArray.h>
00070 #include <OpenEXR/ImfRgba.h>
00071 #include <OpenEXR/ImfRgbaFile.h>
00072 #include <OpenEXR/ImfStandardAttributes.h>
00073 #endif
00074
00075 #include <OSGLog.h>
00076 #include <OSGImageFileHandler.h>
00077 #include <OSGPathHandler.h>
00078 #include <OSGFileSystem.h>
00079
00080 #include "OSGEXRImageFileType.h"
00081
00082 OSG_USING_NAMESPACE
00083
00084
00095
00096
00097
00098
00099
00100 static const Char8 *suffixArray[] =
00101 {
00102 "exr"
00103 };
00104
00105 EXRImageFileType EXRImageFileType::_the( "image/x-exr",
00106 suffixArray, sizeof(suffixArray),
00107 OSG_READ_SUPPORTED |
00108 OSG_WRITE_SUPPORTED );
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 #ifdef OSG_WITH_IMF
00121
00122
00126 class StdIStream : public Imf::IStream
00127 {
00128 public:
00133 StdIStream(std::istream &is, const char fileName[]);
00134 virtual ~StdIStream();
00135
00136 virtual bool read(char c[], int n);
00137 virtual Imf::Int64 tellg();
00138 virtual void seekg(Imf::Int64 pos);
00139 virtual void clear();
00140
00141 private:
00142 bool checkError();
00143
00144 std::istream *_is;
00145 };
00146
00147
00151 class StdOStream : public Imf::OStream
00152 {
00153 public:
00158 StdOStream(std::ostream &os, const char fileName[]);
00159 virtual ~StdOStream();
00160
00161 virtual void write(const char c[], int n);
00162 virtual Imf::Int64 tellp();
00163 virtual void seekp(Imf::Int64 pos);
00164
00165 private:
00166 void checkError();
00167
00168 std::ostream *_os;
00169 };
00170
00171
00172 StdIStream::StdIStream(std::istream &is, const char fileName[]) :
00173 Imf::IStream(fileName), _is(&is) { }
00174
00175 StdIStream::~StdIStream() { }
00176
00177 bool StdIStream::read(char c[], int n)
00178 {
00179 if (!*_is)
00180 throw Iex::InputExc("Unexpected end of file.");
00181
00182 errno = 0;
00183 _is->read(c, n);
00184
00185 return checkError();
00186 }
00187
00188 Imf::Int64 StdIStream::tellg()
00189 {
00190 return std::streamoff(_is->tellg());
00191 }
00192
00193 void StdIStream::seekg(Imf::Int64 pos)
00194 {
00195 _is->seekg(pos);
00196 checkError();
00197 }
00198
00199 void StdIStream::clear()
00200 {
00201 _is->clear();
00202 }
00203
00204 bool StdIStream::checkError()
00205 {
00206 if (!*_is)
00207 {
00208 if (errno)
00209 Iex::throwErrnoExc();
00210
00211 _is->clear(std::ios_base::goodbit);
00212 return false;
00213 }
00214 return true;
00215 }
00216
00217
00218 StdOStream::StdOStream(std::ostream &os, const char fileName[]) :
00219 Imf::OStream(fileName), _os(&os) { }
00220
00221 StdOStream::~StdOStream() { }
00222
00223 void StdOStream::write(const char c[], int n)
00224 {
00225 errno = 0;
00226 _os->write(c, n);
00227 checkError();
00228 }
00229
00230 Imf::Int64 StdOStream::tellp()
00231 {
00232 return std::streamoff(_os->tellp());
00233 }
00234
00235 void StdOStream::seekp(Imf::Int64 pos)
00236 {
00237 _os->seekp(pos);
00238 checkError();
00239 }
00240
00241 void StdOStream::checkError()
00242 {
00243 if (!*_os)
00244 {
00245 if (errno)
00246 Iex::throwErrnoExc();
00247 throw Iex::ErrnoExc ("Write failed.");
00248 }
00249 }
00250
00251 #endif //OSG_WITH_IMF
00252
00253
00257 EXRImageFileType& EXRImageFileType::the (void)
00258 {
00259 return _the;
00260 }
00261
00262
00263
00264
00265
00266
00271 bool EXRImageFileType::read(ImagePtr &image, std::istream &is, const std::string &mimetype)
00272 {
00273 #ifdef OSG_WITH_IMF
00274 if (!is.good())
00275 return false;
00276
00277 const char *dummy = "";
00278 StdIStream file(is, dummy);
00279
00280 Imf::Int64 pos = file.tellg();
00281
00282 bool check = isOpenExrFile(is);
00283
00284 file.seekg(pos);
00285
00286 if (!check)
00287 {
00288 FFATAL(( "Wrong format, no %s image given!\n",
00289 mimetype.c_str() ));
00290 return false;
00291 }
00292
00293
00294
00295 try
00296 {
00297 Int32 width, height, numImg = 1;
00298 Imf::RgbaInputFile stream(file);
00299
00300 Imath::Box2i dw = stream.dataWindow();
00301 Imf::Array2D<Imf::Rgba> pixels;
00302
00303 const Imf::Header &header = stream.header();
00304 const Imf::LineOrder &order = header.lineOrder();
00305
00306 const Imf::EnvmapAttribute *envmap =
00307 header.findTypedAttribute<Imf::EnvmapAttribute>("envmap");
00308
00309 width = dw.max.x - dw.min.x + 1;
00310 height = dw.max.y - dw.min.y + 1;
00311
00312 pixels.resizeErase(height, width);
00313
00314 if (envmap && envmap->value() == Imf::ENVMAP_CUBE)
00315 {
00316 numImg = 6;
00317 height /= numImg;
00318
00319 if (width != height)
00320 {
00321 FFATAL(( "Cubemaps must have squared size, but w=%d and h=%d!\n",
00322 width, height ));
00323 return false;
00324 }
00325 }
00326
00327 stream.setFrameBuffer(&pixels[0][0] - dw.min.x - dw.min.y * width, 1, width);
00328 stream.readPixels(dw.min.y, dw.max.y);
00329
00330 image->set( Image::OSG_RGBA_PF, width, height, 1, 1, 1, 0, 0,
00331 Image::OSG_FLOAT16_IMAGEDATA, true, numImg );
00332 image->clearHalf();
00333
00334 Real16 *data = (Real16*)(image->getData());
00335
00336 for (Int32 side=numImg-1; side >=0; side--)
00337 {
00338 Int32 i, j, size = side * width * height * 4;
00339
00340 for (Int32 y=side*height; y<(side+1)*height; y++)
00341 {
00342 for (Int32 x=0; x<width; x++)
00343 {
00344 if (numImg == 1 || side == 2 || side == 3)
00345 {
00346 i = (2 * side + 1) * height - (y + 1);
00347 j = x;
00348 }
00349 else
00350 {
00351 i = y;
00352 j = width - x - 1;
00353 }
00354
00355 *(data + size++) = (Real16)pixels[i][j].r;
00356 *(data + size++) = (Real16)pixels[i][j].g;
00357 *(data + size++) = (Real16)pixels[i][j].b;
00358 *(data + size++) = (Real16)pixels[i][j].a;
00359 }
00360 }
00361 }
00362
00363 return true;
00364 }
00365 catch(std::exception &e)
00366 {
00367 FFATAL(( "Error while trying to read OpenEXR Image from stream: %s\n",
00368 e.what() ));
00369 return false;
00370 }
00371
00372 #else
00373 SWARNING << getMimeType()
00374 << " read is not compiled into the current binary "
00375 << std::endl;
00376 return false;
00377 #endif
00378 }
00379
00380
00385 bool EXRImageFileType::write(const ImagePtr &image, std::ostream &os, const std::string &mimetype)
00386 {
00387 #ifdef OSG_WITH_IMF
00388 if (!os.good())
00389 return false;
00390
00391 if(image->getDataType() != Image::OSG_FLOAT16_IMAGEDATA)
00392 {
00393 FWARNING(("EXRImageFileType::write: Image has non float data type!\n"));
00394 return false;
00395 }
00396 if (image->getSideCount() == 6)
00397 {
00398 FWARNING(("EXRImageFileType::write: NYI for cubemaps\n"));
00399 return false;
00400 }
00401
00402 try
00403 {
00404 Int32 width = image->getWidth();
00405 Int32 height = image->getHeight();
00406
00407 const char *dummy = "";
00408 StdOStream file(os, dummy);
00409 Imf::Header header(width, height);
00410
00411 Imf::RgbaOutputFile stream(file, header, Imf::WRITE_RGBA);
00412
00413 Imf::Rgba *pixels = new Imf::Rgba[width * height];
00414
00415 Real16 *data = ((Real16*)(image->getData()));
00416 Int32 size = width * height * 4;
00417
00418 for (Int32 y=0; y<height; y++)
00419 {
00420 for (Int32 x=width-1; x>=0; x--)
00421 {
00422 pixels[width * y + x].a = *(data + --size);
00423 pixels[width * y + x].b = *(data + --size);
00424 pixels[width * y + x].g = *(data + --size);
00425 pixels[width * y + x].r = *(data + --size);
00426 }
00427 }
00428
00429 stream.setFrameBuffer(pixels, 1, (int)width);
00430 stream.writePixels(height);
00431
00432 delete [] pixels;
00433
00434 return true;
00435 }
00436 catch(std::exception &e)
00437 {
00438 FFATAL(( "Error while trying to write OpenEXR Image from stream: %s\n",
00439 e.what() ));
00440 return false;
00441 }
00442
00443 #else
00444 SWARNING << getMimeType()
00445 << " write is not compiled into the current binary "
00446 << std::endl;
00447 return false;
00448 #endif
00449 }
00450
00451
00456 UInt64 EXRImageFileType::restoreData( ImagePtr &image,
00457 const UChar8 *buffer,
00458 Int32 OSG_CHECK_ARG(memSize) )
00459 {
00460 image->setData(buffer);
00461
00462 return image->getSize();
00463 }
00464
00465
00470 UInt64 EXRImageFileType::storeData(const ImagePtr &image,
00471 UChar8 *buffer,
00472 Int32 OSG_CHECK_ARG(memSize))
00473 {
00474 UInt32 dataSize = image->getSize();
00475 const UChar8 *src = image->getData();
00476
00477 if ( dataSize && src && buffer )
00478 memcpy( buffer, src, dataSize);
00479
00480 return dataSize;
00481 }
00482
00483
00487 EXRImageFileType::EXRImageFileType ( const Char8 *mimeType,
00488 const Char8 *suffixArray[],
00489 UInt16 suffixByteCount,
00490 UInt32 flags )
00491 : ImageFileType ( mimeType, suffixArray, suffixByteCount, flags )
00492 {
00493 FINFO(( "EXRImageFileType: %s\n", mimeType));
00494
00495
00496
00497 }
00498
00499
00503 EXRImageFileType::~EXRImageFileType(void)
00504 {
00505 }
00506
00507
00511 bool EXRImageFileType::isOpenExrFile(std::istream &is)
00512 {
00513 #ifdef OSG_WITH_IMF
00514 char bytes[4];
00515
00516 is.read(bytes, sizeof(bytes));
00517
00518 return !!is && Imf::isImfMagic(bytes);
00519
00520 #else
00521 return false;
00522 #endif
00523 }