- Main Page
- Data Structures
- Files

- File List

# E:/DevIL/src-IL/src/il_exr.cpp

    00001 //-----------------------------------------------------------------------------
    00002 //
    00003 // ImageLib Sources
    00004 // Copyright (C) 2000-2009 by Denton Woods
    00005 // Last modified: 01/04/2009
    00006 //
    00007 // Filename: src-IL/src/il_exr.cpp
    00008 //
    00009 // Description: Reads from an OpenEXR (.exr) file using the OpenEXR library.
    00010 //
    00011 //-----------------------------------------------------------------------------
    00012
    00013
    00014 #include "il_internal.h"
    00015 #ifndef IL_NO_EXR
    00016
    00017 #ifndef HAVE_CONFIG_H // We are probably on a Windows box .
    00018 //#define OPENEXR_DLL
    00019 #define HALF_EXPORTS
    00020 #endif //HAVE_CONFIG_H
    00021
    00022 #include "il_exr.h"
    00023 #include <ImfRgba.h>
    00024 #include <ImfArray.h>
    00025 #include <ImfRgbaFile.h>
    00026 //#include <ImfTiledRgbaFile.h>
    00027 //#include <ImfInputFile.h>
    00028 //#include <ImfTiledInputFile.h>
    00029 //#include <ImfPreviewImage.h>
    00030 //#include <ImfChannelList.h>
    00031
    00032
    00033
    00034 #if (defined(_WIN32) || defined(_WIN64)) && defined(IL_USE_PRAGMA_LIBS)
    00035         #if defined(_MSC_VER) || defined(__BORLANDC__)
    00036                 #ifndef _DEBUG
    00037                         #pragma comment(lib, "openexr.lib")
    00038                 #else
    00039                         #pragma comment(lib, "openexr-d.lib")
    00040                 #endif
    00041         #endif
    00042 #endif
    00043
    00044
    00046 ILboolean ilIsValidExr(ILconst_string FileName)
    00047 {
    00048         ILHANDLE        ExrFile;
    00049         ILboolean       bExr = IL_FALSE;
    00050
    00051         if (!iCheckExtension(FileName, IL_TEXT("exr"))) {
    00052                 ilSetError(IL_INVALID_EXTENSION);
    00053                 return bExr;
    00054         }
    00055
    00056         ExrFile = iopenr(FileName);
    00057         if (ExrFile == NULL) {
    00058                 ilSetError(IL_COULD_NOT_OPEN_FILE);
    00059                 return bExr;
    00060         }
    00061
    00062         bExr = ilIsValidExrF(ExrFile);
    00063         icloser(ExrFile);
    00064
    00065         return bExr;
    00066 }
    00067
    00068
    00070 ILboolean ilIsValidExrF(ILHANDLE File)
    00071 {
    00072         ILuint          FirstPos;
    00073         ILboolean       bRet;
    00074
    00075         iSetInputFile(File);
    00076         FirstPos = itell();
    00077         bRet = iIsValidExr();
    00078         iseek(FirstPos, IL_SEEK_SET);
    00079
    00080         return bRet;
    00081 }
    00082
    00083
    00085 ILboolean ilIsValidExrL(const void *Lump, ILuint Size)
    00086 {
    00087         iSetInputLump(Lump, Size);
    00088         return iIsValidExr();
    00089 }
    00090
    00091
    00092 // Internal function used to get the EXR header from the current file.
    00093 ILboolean iGetExrHead(EXRHEAD *Header)
    00094 {
    00095         Header->MagicNumber = GetLittleUInt();
    00096         Header->Version = GetLittleUInt();
    00097
    00098         return IL_TRUE;
    00099 }
    00100
    00101
    00102 // Internal function to get the header and check it.
    00103 ILboolean iIsValidExr()
    00104 {
    00105         EXRHEAD Head;
    00106
    00107         if (!iGetExrHead(&Head))
    00108                 return IL_FALSE;
    00109         iseek(-8, IL_SEEK_CUR);
    00110
    00111         return iCheckExr(&Head);
    00112 }
    00113
    00114
    00115 // Internal function used to check if the HEADER is a valid EXR header.
    00116 ILboolean iCheckExr(EXRHEAD *Header)
    00117 {
    00118         // The file magic number (signature) is 0x76, 0x2f, 0x31, 0x01
    00119         if (Header->MagicNumber != 0x01312F76)
    00120                 return IL_FALSE;
    00121         // The only valid version so far is version 2.  The upper value has
    00122         //  to do with tiling.
    00123         if (Header->Version != 0x002 && Header->Version != 0x202)
    00124                 return IL_FALSE;
    00125
    00126         return IL_TRUE;
    00127 }
    00128
    00129
    00130 // Nothing to do here in the constructor.
    00131 ilIStream::ilIStream() : Imf::IStream("N/A")
    00132 {
    00133         return;
    00134 }
    00135
    00136
    00137 bool ilIStream::read(char c[], int n)
    00138 {
    00139         if (iread(c, 1, n) != n)
    00140                 return false;
    00141         return true;
    00142 }
    00143
    00144
    00145 //@TODO: Make this work with 64-bit values.
    00146 Imf::Int64 ilIStream::tellg()
    00147 {
    00148         Imf::Int64 Pos;
    00149
    00150         // itell only returns a 32-bit value!
    00151         Pos = itell();
    00152
    00153         return Pos;
    00154 }
    00155
    00156
    00157 // Note that there is no return value here, even though there probably should be.
    00158 //@TODO: Make this work with 64-bit values.
    00159 void ilIStream::seekg(Imf::Int64 Pos)
    00160 {
    00161         // iseek only uses a 32-bit value!
    00162         iseek((ILint)Pos, IL_SEEK_SET);  // I am assuming this is seeking from the beginning.
    00163         return;
    00164 }
    00165
    00166
    00167 void ilIStream::clear()
    00168 {
    00169         return;
    00170 }
    00171
    00172
    00174 ILboolean ilLoadExr(ILconst_string FileName)
    00175 {
    00176         ILHANDLE        ExrFile;
    00177         ILboolean       bExr = IL_FALSE;
    00178
    00179         ExrFile = iopenr(FileName);
    00180         if (ExrFile == NULL) {
    00181                 ilSetError(IL_COULD_NOT_OPEN_FILE);
    00182                 return bExr;
    00183         }
    00184
    00185         bExr = ilLoadExrF(ExrFile);
    00186         icloser(ExrFile);
    00187
    00188         return bExr;
    00189 }
    00190
    00191
    00193 ILboolean ilLoadExrF(ILHANDLE File)
    00194 {
    00195         ILuint          FirstPos;
    00196         ILboolean       bRet;
    00197
    00198         iSetInputFile(File);
    00199         FirstPos = itell();
    00200         bRet = iLoadExrInternal();
    00201         iseek(FirstPos, IL_SEEK_SET);
    00202
    00203         return bRet;
    00204 }
    00205
    00206
    00208 ILboolean ilLoadExrL(const void *Lump, ILuint Size)
    00209 {
    00210         iSetInputLump(Lump, Size);
    00211         return iLoadExrInternal();
    00212 }
    00213
    00214
    00215 using namespace Imath;
    00216 using namespace Imf;
    00217 using namespace std;
    00218
    00219
    00220 ILboolean iLoadExrInternal()
    00221 {
    00222         Array<Rgba> pixels;
    00223         Box2i dataWindow;
    00224         float pixelAspectRatio;
    00225         ILfloat *FloatData;
    00226
    00227         ilIStream File;
    00228         RgbaInputFile in(File);
    00229
    00230         Rgba a;
    00231     dataWindow = in.dataWindow();
    00232     pixelAspectRatio = in.pixelAspectRatio();
    00233
    00234     int dw, dh, dx, dy;
    00235
    00236         dw = dataWindow.max.x - dataWindow.min.x + 1;
    00237     dh = dataWindow.max.y - dataWindow.min.y + 1;
    00238     dx = dataWindow.min.x;
    00239     dy = dataWindow.min.y;
    00240
    00241     pixels.resizeErase (dw * dh);
    00242         in.setFrameBuffer (pixels - dx - dy * dw, 1, dw);
    00243
    00244         try
    00245     {
    00246                 in.readPixels (dataWindow.min.y, dataWindow.max.y);
    00247     }
    00248     catch (const exception &e)
    00249     {
    00250         // If some of the pixels in the file cannot be read,
    00251         // print an error message, and return a partial image
    00252         // to the caller.
    00253                 ilSetError(IL_LIB_EXR_ERROR);  // Could I use something a bit more descriptive based on e?
    00254                 e;  // Prevent the compiler from yelling at us about this being unused.
    00255                 return IL_FALSE;
    00256     }
    00257
    00258         //if (ilTexImage(dw, dh, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL) == IL_FALSE)
    00259         //if (ilTexImage(dw, dh, 1, 4, IL_RGBA, IL_UNSIGNED_SHORT, NULL) == IL_FALSE)
    00260         if (ilTexImage(dw, dh, 1, 4, IL_RGBA, IL_FLOAT, NULL) == IL_FALSE)
    00261                 return IL_FALSE;
    00262
    00263         // Determine where the origin is in the original file.
    00264         if (in.lineOrder() == INCREASING_Y)
    00265                 iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
    00266         else
    00267                 iCurImage->Origin = IL_ORIGIN_LOWER_LEFT;
    00268
    00269         // Better to access FloatData instead of recasting everytime.
    00270         FloatData = (ILfloat*)iCurImage->Data;
    00271
    00272         for (int i = 0; i < dw * dh; i++)
    00273         {
    00274                 // Too much data lost
    00275                 //iCurImage->Data[i * 4 + 0] = (ILubyte)(pixels[i].r.bits() >> 8);
    00276                 //iCurImage->Data[i * 4 + 1] = (ILubyte)(pixels[i].g.bits() >> 8);
    00277                 //iCurImage->Data[i * 4 + 2] = (ILubyte)(pixels[i].b.bits() >> 8);
    00278                 //iCurImage->Data[i * 4 + 3] = (ILubyte)(pixels[i].a.bits() >> 8);
    00279
    00280                 // The images look kind of washed out with this.
    00281                 //((ILshort*)(iCurImage->Data))[i * 4 + 0] = pixels[i].r.bits();
    00282                 //((ILshort*)(iCurImage->Data))[i * 4 + 1] = pixels[i].g.bits();
    00283                 //((ILshort*)(iCurImage->Data))[i * 4 + 2] = pixels[i].b.bits();
    00284                 //((ILshort*)(iCurImage->Data))[i * 4 + 3] = pixels[i].a.bits();
    00285
    00286                 // This gives the best results, since no data is lost.
    00287                 FloatData[i * 4]     = pixels[i].r;
    00288                 FloatData[i * 4 + 1] = pixels[i].g;
    00289                 FloatData[i * 4 + 2] = pixels[i].b;
    00290                 FloatData[i * 4 + 3] = pixels[i].a;
    00291         }
    00292
    00293         // Converts the image to predefined type, format and/or origin if needed.
    00294         ilFixImage();
    00295
    00296         return IL_TRUE;
    00297 }
    00298
    00299
    00300
    00301 // Nothing to do here in the constructor.
    00302 ilOStream::ilOStream() : Imf::OStream("N/A")
    00303 {
    00304         return;
    00305 }
    00306
    00307 void ilOStream::write(const char c[], int n)
    00308 {
    00309         iwrite(c, 1, n);  //@TODO: Throw an exception here.
    00310         return;
    00311 }
    00312
    00313 //@TODO: Make this work with 64-bit values.
    00314 Imf::Int64 ilOStream::tellp()
    00315 {
    00316         Imf::Int64 Pos;
    00317
    00318         // itellw only returns a 32-bit value!
    00319         Pos = itellw();
    00320
    00321         return Pos;
    00322 }
    00323
    00324 // Note that there is no return value here, even though there probably should be.
    00325 //@TODO: Make this work with 64-bit values.
    00326 void ilOStream::seekp(Imf::Int64 Pos)
    00327 {
    00328         // iseekw only uses a 32-bit value!
    00329         iseekw((ILint)Pos, IL_SEEK_SET);  // I am assuming this is seeking from the beginning.
    00330         return;
    00331 }
    00332
    00333
    00335 ILboolean ilSaveExr(const ILstring FileName)
    00336 {
    00337         ILHANDLE        ExrFile;
    00338         ILuint          ExrSize;
    00339
    00340         if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) {
    00341                 if (iFileExists(FileName)) {
    00342                         ilSetError(IL_FILE_ALREADY_EXISTS);
    00343                         return IL_FALSE;
    00344                 }
    00345         }
    00346
    00347         ExrFile = iopenw(FileName);
    00348         if (ExrFile == NULL) {
    00349                 ilSetError(IL_COULD_NOT_OPEN_FILE);
    00350                 return IL_FALSE;
    00351         }
    00352
    00353         ExrSize = ilSaveExrF(ExrFile);
    00354         iclosew(ExrFile);
    00355
    00356         if (ExrSize == 0)
    00357                 return IL_FALSE;
    00358         return IL_TRUE;
    00359 }
    00360
    00361
    00363 ILuint ilSaveExrF(ILHANDLE File)
    00364 {
    00365         ILuint Pos;
    00366         iSetOutputFile(File);
    00367         Pos = itellw();
    00368         if (iSaveExrInternal() == IL_FALSE)
    00369                 return 0;  // Error occurred
    00370         return itellw() - Pos;  // Return the number of bytes written.
    00371 }
    00372
    00373
    00375 ILuint ilSaveExrL(void *Lump, ILuint Size)
    00376 {
    00377         ILuint Pos = itellw();
    00378         iSetOutputLump(Lump, Size);
    00379         if (iSaveExrInternal() == IL_FALSE)
    00380                 return 0;  // Error occurred
    00381         return itellw() - Pos;  // Return the number of bytes written.
    00382 }
    00383
    00384
    00385 ILboolean iSaveExrInternal()
    00386 {
    00387         Imath::Box2i DataWindow(Imath::V2i(0, 0), Imath::V2i(iCurImage->Width-1, iCurImage->Height-1));
    00388         Imf::LineOrder Order;
    00389         if (iCurImage->Origin == IL_ORIGIN_LOWER_LEFT)
    00390                 Order = DECREASING_Y;
    00391         else
    00392                 Order = INCREASING_Y;
    00393         Imf::Header Head(iCurImage->Width, iCurImage->Height, DataWindow, 1, Imath::V2f (0, 0), 1, Order);
    00394
    00395         ilOStream File;
    00396         Imf::RgbaOutputFile Out(File, Head);
    00397         ILimage *TempImage = iCurImage;
    00398
    00399         //@TODO: Can we always assume that Rgba is packed the same?
    00400         Rgba *HalfData = (Rgba*)ialloc(TempImage->Width * TempImage->Height * sizeof(Rgba));
    00401         if (HalfData == NULL)
    00402                 return IL_FALSE;
    00403
    00404         if (iCurImage->Format != IL_RGBA || iCurImage->Type != IL_FLOAT) {
    00405                 TempImage = iConvertImage(iCurImage, IL_RGBA, IL_FLOAT);
    00406                 if (TempImage == NULL) {
    00407                         ifree(HalfData);
    00408                         return IL_FALSE;
    00409                 }
    00410         }
    00411
    00412         ILuint Offset = 0;
    00413         ILfloat *FloatPtr = (ILfloat*)TempImage->Data;
    00414         for (unsigned int y = 0; y < TempImage->Height; y++) {
    00415                 for (unsigned int x = 0; x < TempImage->Width; x++) {
    00416                         HalfData[y * TempImage->Width + x].r = FloatPtr[Offset];
    00417                         HalfData[y * TempImage->Width + x].g = FloatPtr[Offset + 1];
    00418                         HalfData[y * TempImage->Width + x].b = FloatPtr[Offset + 2];
    00419                         HalfData[y * TempImage->Width + x].a = FloatPtr[Offset + 3];
    00420                         Offset += 4;  // 4 floats
    00421                 }
    00422         }
    00423
    00424         Out.setFrameBuffer(HalfData, 1, TempImage->Width);
    00425         Out.writePixels(TempImage->Height);  //@TODO: Do each scanline separately to keep from using so much memory.
    00426
    00427         // Free our half data.
    00428         ifree(HalfData);
    00429         // Destroy our temporary image if we used one.
    00430         if (TempImage != iCurImage)
    00431                 ilCloseImage(TempImage);
    00432
    00433         return IL_TRUE;
    00434 }
    00435
    00436
    00437 #endif //IL_NO_EXR