- Main Page
- Data Structures
- Files

- File List

# E:/DevIL/src-IL/src/il_hdr.c

    00001 //-----------------------------------------------------------------------------
    00002 //
    00003 // ImageLib Sources
    00004 // Copyright (C) 2000-2008 by Denton Woods (this file by thakis / Denton)
    00005 // Last modified: 12/14/2008
    00006 //
    00007 // Filename: src-IL/src/il_hdr.c
    00008 //
    00009 // Description: Reads/writes a RADIANCE High Dynamic Range Image
    00010 //
    00011 //-----------------------------------------------------------------------------
    00012
    00013
    00014 #include "il_internal.h"
    00015 #ifndef IL_NO_HDR
    00016 #include "il_hdr.h"
    00017 #include "il_endian.h"
    00018
    00019
    00021 ILboolean ilIsValidHdr(ILconst_string FileName)
    00022 {
    00023         ILHANDLE        HdrFile;
    00024         ILboolean       bHdr = IL_FALSE;
    00025
    00026         if (!iCheckExtension(FileName, IL_TEXT("hdr"))) {
    00027                 ilSetError(IL_INVALID_EXTENSION);
    00028                 return bHdr;
    00029         }
    00030
    00031         HdrFile = iopenr(FileName);
    00032         if (HdrFile == NULL) {
    00033                 ilSetError(IL_COULD_NOT_OPEN_FILE);
    00034                 return bHdr;
    00035         }
    00036
    00037         bHdr = ilIsValidHdrF(HdrFile);
    00038         icloser(HdrFile);
    00039
    00040         return bHdr;
    00041 }
    00042
    00043
    00045 ILboolean ilIsValidHdrF(ILHANDLE File)
    00046 {
    00047         ILuint          FirstPos;
    00048         ILboolean       bRet;
    00049
    00050         iSetInputFile(File);
    00051         FirstPos = itell();
    00052         bRet = iIsValidHdr();
    00053         iseek(FirstPos, IL_SEEK_SET);
    00054
    00055         return bRet;
    00056 }
    00057
    00058
    00060 ILboolean ilIsValidHdrL(const void *Lump, ILuint Size)
    00061 {
    00062         iSetInputLump(Lump, Size);
    00063         return iIsValidHdr();
    00064 }
    00065
    00066
    00067 // Internal function used to get the .hdr header from the current file.
    00068 ILboolean iGetHdrHead(HDRHEADER *Header)
    00069 {
    00070         ILboolean done = IL_FALSE;
    00071         char a, b;
    00072         char x[3], y[3]; //changed 20050217: added space for the '\0' char
    00073         char buff[81]; // 01-19-2009: Added space for the '\0'.
    00074         ILuint count = 0;
    00075
    00076         iread(Header->Signature, 1, 10);
    00077
    00078         //skip lines until an empty line is found.
    00079         //this marks the end of header information,
    00080         //the next line contains the image's dimension.
    00081
    00082         //TODO: read header contents into variables
    00083         //(EXPOSURE, orientation, xyz correction, ...)
    00084
    00085         if (iread(&a, 1, 1) != 1)
    00086                 return IL_FALSE;
    00087
    00088         while (!done) {
    00089                 if (iread(&b, 1, 1) != 1)
    00090                         return IL_FALSE;
    00091                 if (b == '\n' && a == '\n')
    00092                         done = IL_TRUE;
    00093                 else
    00094                         a = b;
    00095         }
    00096
    00097         //read dimensions (note that this assumes a somewhat valid image)
    00098         if (iread(&a, 1, 1) != 1)
    00099                 return IL_FALSE;
    00100         while (a != '\n') {
    00101                 if (count >= 80) {  // Line shouldn't be this long at all.
    00102                         ilSetError(IL_INVALID_FILE_HEADER);
    00103                         return IL_FALSE;
    00104                 }
    00105                 buff[count] = a;
    00106                 if (iread(&a, 1, 1) != 1)
    00107                         return IL_FALSE;
    00108                 ++count;
    00109         }
    00110         buff[count] = '\0';
    00111
    00112         //note that this is not the 100% correct way to load hdr images:
    00113         //in a perfect world we would check if there's a +/- X/Y in front
    00114         //of width and heigth and mirror + rotate the image after decoding
    00115         //according to that. But HDRShop doesn't do that either (and that's
    00116         //my reference program :) ) and it's just a rotate and a mirror,
    00117         //nothing that really changes the appearance of the loaded image...
    00118         //(The code as it is now assumes that y contains "-Y" and x contains
    00119         //"+X" after the following line)
    00120
    00121         // The 2 has to be in the %s format specifier to prevent buffer overruns.
    00122         sscanf(buff, "%2s %d %2s %d", y, &Header->Height, x, &Header->Width);
    00123
    00124         return IL_TRUE;
    00125 }
    00126
    00127
    00128 // Internal function to get the header and check it.
    00129 ILboolean iIsValidHdr()
    00130 {
    00131         char    Head[10];
    00132         ILint   Read;
    00133
    00134         Read = iread(Head, 1, 10);
    00135         iseek(-Read, IL_SEEK_CUR);  // Go ahead and restore to previous state
    00136         if (Read != 10)
    00137                 return IL_FALSE;
    00138
    00139         return
    00140                 strnicmp(Head, "#?RADIANCE", 10) == 0
    00141                 || strnicmp(Head, "#?RGBE", 6) == 0;
    00142 }
    00143
    00144
    00145 // Internal function used to check if the HEADER is a valid .hdr header.
    00146 ILboolean iCheckHdr(HDRHEADER *Header)
    00147 {
    00148         return
    00149                 strnicmp(Header->Signature, "#?RADIANCE", 10) == 0
    00150                 || strnicmp(Header->Signature, "#?RGBE", 6) == 0;
    00151 }
    00152
    00153
    00155 ILboolean ilLoadHdr(ILconst_string FileName)
    00156 {
    00157         ILHANDLE        HdrFile;
    00158         ILboolean       bHdr = IL_FALSE;
    00159
    00160         HdrFile = iopenr(FileName);
    00161         if (HdrFile == NULL) {
    00162                 ilSetError(IL_COULD_NOT_OPEN_FILE);
    00163                 return bHdr;
    00164         }
    00165
    00166         bHdr = ilLoadHdrF(HdrFile);
    00167         icloser(HdrFile);
    00168
    00169         return bHdr;
    00170 }
    00171
    00172
    00174 ILboolean ilLoadHdrF(ILHANDLE File)
    00175 {
    00176         ILuint          FirstPos;
    00177         ILboolean       bRet;
    00178
    00179         iSetInputFile(File);
    00180         FirstPos = itell();
    00181         bRet = iLoadHdrInternal();
    00182         iseek(FirstPos, IL_SEEK_SET);
    00183
    00184         return bRet;
    00185 }
    00186
    00187
    00189 ILboolean ilLoadHdrL(const void *Lump, ILuint Size)
    00190 {
    00191         iSetInputLump(Lump, Size);
    00192         return iLoadHdrInternal();
    00193 }
    00194
    00195
    00196 // Internal function used to load the .hdr.
    00197 ILboolean iLoadHdrInternal()
    00198 {
    00199         HDRHEADER       Header;
    00200         ILfloat *data;
    00201         ILubyte *scanline;
    00202         ILuint i, j, e, r, g, b;
    00203
    00204         if (iCurImage == NULL) {
    00205                 ilSetError(IL_ILLEGAL_OPERATION);
    00206                 return IL_FALSE;
    00207         }
    00208
    00209         if (!iGetHdrHead(&Header)) {
    00210                 ilSetError(IL_INVALID_FILE_HEADER);
    00211                 return IL_FALSE;
    00212         }
    00213         if (!iCheckHdr(&Header)) {
    00214                 //iseek(-(ILint)sizeof(HDRHEAD), IL_SEEK_CUR);
    00215                 ilSetError(IL_INVALID_FILE_HEADER);
    00216                 return IL_FALSE;
    00217         }
    00218
    00219         // Update the current image with the new dimensions
    00220         if (!ilTexImage(Header.Width, Header.Height, 1, 3, IL_RGB, IL_FLOAT, NULL)) {
    00221                 return IL_FALSE;
    00222         }
    00223         iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
    00224
    00225         //read image data
    00226         if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST)
    00227                 iPreCache(iCurImage->Width / 8 * iCurImage->Height);
    00228
    00229         data = (ILfloat*)iCurImage->Data;
    00230         scanline = (ILubyte*)ialloc(Header.Width*4);
    00231         for (i = 0; i < Header.Height; ++i) {
    00232                 ReadScanline(scanline, Header.Width);
    00233
    00234                 //convert hdrs internal format to floats
    00235                 for (j = 0; j < 4*Header.Width; j += 4) {
    00236                         ILuint *ee;
    00237                         ILfloat t, *ff;
    00238                         e = scanline[j + 3];
    00239                         r = scanline[j + 0];
    00240                         g = scanline[j + 1];
    00241                         b = scanline[j + 2];
    00242
    00243                         //t = (float)pow(2.f, ((ILint)e) - 128);
    00244                         if (e != 0)
    00245                                 e = (e - 1) << 23;
    00246
    00247                         // All this just to avoid stric-aliasing warnings...
    00248                         // was: t = *(ILfloat*)&e
    00249                         ee = &e;
    00250                         ff = (ILfloat*)ee;
    00251                         t = *ff;
    00252
    00253                         data[0] = (r/255.0f)*t;
    00254                         data[1] = (g/255.0f)*t;
    00255                         data[2] = (b/255.0f)*t;
    00256                         data += 3;
    00257                 }
    00258         }
    00259         iUnCache();
    00260         ifree(scanline);
    00261
    00262         return ilFixImage();
    00263 }
    00264
    00265 void ReadScanline(ILubyte *scanline, ILuint w) {
    00266         ILubyte *runner;
    00267         ILuint r, g, b, e, read, shift;
    00268
    00269         r = igetc();
    00270         g = igetc();
    00271         b = igetc();
    00272         e = igetc();
    00273
    00274         //check if the scanline is in the new format
    00275         //if so, e, r, g, g are stored separated and are
    00276         //rle-compressed independently.
    00277         if (r == 2 && g == 2) {
    00278                 ILuint length = (b << 8) | e;
    00279                 ILuint j, t, k;
    00280                 if (length > w)
    00281                         length = w; //fix broken files
    00282                 for (k = 0; k < 4; ++k) {
    00283                         runner = scanline + k;
    00284                         j = 0;
    00285                         while (j < length) {
    00286                                 t = igetc();
    00287                                 if (t > 128) { //Run?
    00288                                         ILubyte val = igetc();
    00289                                         t &= 127;
    00290                                         //copy current byte
    00291                                         while (t > 0 && j < length) {
    00292                                                 *runner = val;
    00293                                                 runner += 4;
    00294                                                 --t;
    00295                                                 ++j;
    00296                                         }
    00297                                 }
    00298                                 else { //No Run.
    00299                                         //read new bytes
    00300                                         while (t > 0 && j < length) {
    00301                                                 *runner = igetc();
    00302                                                 runner += 4;
    00303                                                 --t;
    00304                                                 ++j;
    00305                                         }
    00306                                 }
    00307                         }
    00308                 }
    00309                 return; //done decoding a scanline in separated format
    00310         }
    00311
    00312         //if we come here, we are dealing with old-style scanlines
    00313         shift = 0;
    00314         read = 0;
    00315         runner = scanline;
    00316         while (read < w) {
    00317                 if (read != 0) {
    00318                         r = igetc();
    00319                         g = igetc();
    00320                         b = igetc();
    00321                         e = igetc();
    00322                 }
    00323
    00324                 //if all three mantissas are 1, then this is a rle
    00325                 //count dword
    00326                 if (r == 1 && g == 1 && b == 1) {
    00327                         ILuint length = e;
    00328                         ILuint j;
    00329                         for (j = length << shift; j > 0 && read < w; --j) {
    00330                                 memcpy(runner, runner - 4, 4);
    00331                                 runner += 4;
    00332                                 ++read;
    00333                         }
    00334                         //if more than one rle count dword is read
    00335                         //consecutively, they are higher order bytes
    00336                         //of the first read value. shift keeps track of
    00337                         //that.
    00338                         shift += 8;
    00339                 }
    00340                 else {
    00341                         runner[0] = r;
    00342                         runner[1] = g;
    00343                         runner[2] = b;
    00344                         runner[3] = e;
    00345
    00346                         shift = 0;
    00347                         runner += 4;
    00348                         ++read;
    00349                 }
    00350         }
    00351 }
    00352
    00353
    00354
    00356 ILboolean ilSaveHdr(const ILstring FileName)
    00357 {
    00358         ILHANDLE        HdrFile;
    00359         ILuint          HdrSize;
    00360
    00361         if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) {
    00362                 if (iFileExists(FileName)) {
    00363                         ilSetError(IL_FILE_ALREADY_EXISTS);
    00364                         return IL_FALSE;
    00365                 }
    00366         }
    00367
    00368         HdrFile = iopenw(FileName);
    00369         if (HdrFile == NULL) {
    00370                 ilSetError(IL_COULD_NOT_OPEN_FILE);
    00371                 return IL_FALSE;
    00372         }
    00373
    00374         HdrSize = ilSaveHdrF(HdrFile);
    00375         iclosew(HdrFile);
    00376
    00377         if (HdrSize == 0)
    00378                 return IL_FALSE;
    00379         return IL_TRUE;
    00380 }
    00381
    00382
    00384 ILuint ilSaveHdrF(ILHANDLE File)
    00385 {
    00386         ILuint Pos;
    00387         iSetOutputFile(File);
    00388         Pos = itellw();
    00389         if (iSaveHdrInternal() == IL_FALSE)
    00390                 return 0;  // Error occurred
    00391         return itellw() - Pos;  // Return the number of bytes written.
    00392 }
    00393
    00394
    00396 ILuint ilSaveHdrL(void *Lump, ILuint Size)
    00397 {
    00398         ILuint Pos = itellw();
    00399         iSetOutputLump(Lump, Size);
    00400         if (iSaveHdrInternal() == IL_FALSE)
    00401                 return 0;  // Error occurred
    00402         return itellw() - Pos;  // Return the number of bytes written.
    00403 }
    00404
    00405
    00406 //
    00407 // Much of the saving code is based on the code by Bruce Walter,
    00408 //  available at http://www.graphics.cornell.edu/online/formats/rgbe/.
    00409 //
    00410 // The actual source code file is
    00411 //  http://www.graphics.cornell.edu/online/formats/rgbe/rgbe.c
    00412 //
    00413
    00414
    00415 /* standard conversion from float pixels to rgbe pixels */
    00416 /* note: you can remove the "inline"s if your compiler complains about it */
    00417 //static INLINE void
    00418 static void
    00419 float2rgbe(unsigned char rgbe[4], float red, float green, float blue)
    00420 {
    00421   float v;
    00422   int e;
    00423
    00424   v = red;
    00425   if (green > v) v = green;
    00426   if (blue > v) v = blue;
    00427   if (v < 1e-32) {
    00428     rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
    00429   }
    00430   else {
    00431     v = (float)(frexp(v,&e) * 256.0/v);
    00432     rgbe[0] = (unsigned char) (red * v);
    00433     rgbe[1] = (unsigned char) (green * v);
    00434     rgbe[2] = (unsigned char) (blue * v);
    00435     rgbe[3] = (unsigned char) (e + 128);
    00436   }
    00437 }
    00438
    00439
    00440 typedef struct {
    00441   ILuint        valid;            /* indicate which fields are valid */
    00442   ILbyte        programtype[16]; /* listed at beginning of file to identify it
    00443                          * after "#?".  defaults to "RGBE" */
    00444   ILfloat       gamma;          /* image has already been gamma corrected with
    00445                          * given gamma.  defaults to 1.0 (no correction) */
    00446   ILfloat       exposure;       /* a value of 1.0 in an image corresponds to
    00447                          * <exposure> watts/steradian/m^2.
    00448                          * defaults to 1.0 */
    00449 } rgbe_header_info;
    00450
    00451 /* flags indicating which fields in an rgbe_header_info are valid */
    00452 #define RGBE_VALID_PROGRAMTYPE 0x01
    00453 #define RGBE_VALID_GAMMA       0x02
    00454 #define RGBE_VALID_EXPOSURE    0x04
    00455
    00456 /* offsets to red, green, and blue components in a data (float) pixel */
    00457 #define RGBE_DATA_RED    0
    00458 #define RGBE_DATA_GREEN  1
    00459 #define RGBE_DATA_BLUE   2
    00460 /* number of floats per pixel */
    00461 #define RGBE_DATA_SIZE   3
    00462
    00463
    00464 /* default minimal header. modify if you want more information in header */
    00465 ILboolean RGBE_WriteHeader(ILuint width, ILuint height, rgbe_header_info *info)
    00466 {
    00467         char *programtype = "RGBE";
    00468
    00469         if (info && (info->valid & RGBE_VALID_PROGRAMTYPE))
    00470                 programtype = info->programtype;
    00471         if (ilprintf("#?%s\n",programtype) < 0)
    00472                 return IL_FALSE;
    00473         /* The #? is to identify file type, the programtype is optional. */
    00474         if (info && (info->valid & RGBE_VALID_GAMMA)) {
    00475                 if (ilprintf("GAMMA=%g\n",info->gamma) < 0)
    00476                   return IL_FALSE;
    00477         }
    00478         if (info && (info->valid & RGBE_VALID_EXPOSURE)) {
    00479                 if (ilprintf("EXPOSURE=%g\n",info->exposure) < 0)
    00480                   return IL_FALSE;
    00481         }
    00482         if (ilprintf("FORMAT=32-bit_rle_rgbe\n\n") < 0)
    00483                 return IL_FALSE;
    00484         if (ilprintf("-Y %d +X %d\n", height, width) < 0)
    00485                 return IL_FALSE;
    00486         return IL_TRUE;
    00487 }
    00488
    00489
    00490 /* simple write routine that does not use run length encoding */
    00491 /* These routines can be made faster by allocating a larger buffer and
    00492    fread-ing and iwrite-ing the data in larger chunks */
    00493 int RGBE_WritePixels(float *data, int numpixels)
    00494 {
    00495         unsigned char rgbe[4];
    00496
    00497         while (numpixels-- > 0) {
    00498                 float2rgbe(rgbe,data[RGBE_DATA_RED],data[RGBE_DATA_GREEN],data[RGBE_DATA_BLUE]);
    00499                 data += RGBE_DATA_SIZE;
    00500                 if (iwrite(rgbe, sizeof(rgbe), 1) < 1)
    00501                         return IL_FALSE;
    00502         }
    00503         return IL_TRUE;
    00504 }
    00505
    00506
    00507 /* The code below is only needed for the run-length encoded files. */
    00508 /* Run length encoding adds considerable complexity but does */
    00509 /* save some space.  For each scanline, each channel (r,g,b,e) is */
    00510 /* encoded separately for better compression. */
    00511
    00512 ILboolean RGBE_WriteBytes_RLE(ILubyte *data, ILuint numbytes)
    00513 {
    00514 #define MINRUNLENGTH 4
    00515         ILuint  cur, beg_run, run_count, old_run_count, nonrun_count;
    00516         ILubyte buf[2];
    00517
    00518         cur = 0;
    00519         while (cur < numbytes) {
    00520                 beg_run = cur;
    00521                 /* find next run of length at least 4 if one exists */
    00522                 run_count = old_run_count = 0;
    00523                 while((run_count < MINRUNLENGTH) && (beg_run < numbytes)) {
    00524                         beg_run += run_count;
    00525                         old_run_count = run_count;
    00526                         run_count = 1;
    00527                         // 01-25-2009: Moved test for beg_run + run_count first so that it is
    00528                         //  tested first.  This keeps it from going out of bounds by 1.
    00529                         while((beg_run + run_count < numbytes) && (run_count < 127) &&
    00530                                 (data[beg_run] == data[beg_run + run_count]))
    00531                         run_count++;
    00532                 }
    00533                 /* if data before next big run is a short run then write it as such */
    00534                 if ((old_run_count > 1)&&(old_run_count == beg_run - cur)) {
    00535                         buf[0] = 128 + old_run_count;   /*write short run*/
    00536                         buf[1] = data[cur];
    00537                         if (iwrite(buf,sizeof(buf[0])*2,1) < 1)
    00538                                 return IL_FALSE;
    00539                         cur = beg_run;
    00540                 }
    00541                 /* write out bytes until we reach the start of the next run */
    00542                 while(cur < beg_run) {
    00543                         nonrun_count = beg_run - cur;
    00544                         if (nonrun_count > 128)
    00545                                 nonrun_count = 128;
    00546                         buf[0] = nonrun_count;
    00547                         if (iwrite(buf,sizeof(buf[0]),1) < 1)
    00548                                 return IL_FALSE;
    00549                         if (iwrite(&data[cur],sizeof(data[0])*nonrun_count,1) < 1)
    00550                                 return IL_FALSE;
    00551                         cur += nonrun_count;
    00552                 }
    00553                 /* write out next run if one was found */
    00554                 if (run_count >= MINRUNLENGTH) {
    00555                         buf[0] = 128 + run_count;
    00556                         buf[1] = data[beg_run];
    00557                         if (iwrite(buf,sizeof(buf[0])*2,1) < 1)
    00558                                 return IL_FALSE;
    00559                         cur += run_count;
    00560                 }
    00561         }
    00562         return IL_TRUE;
    00563 #undef MINRUNLENGTH
    00564 }
    00565
    00566
    00567 // Internal function used to save the Hdr.
    00568 ILboolean iSaveHdrInternal()
    00569 {
    00570         ILimage *TempImage;
    00571         rgbe_header_info stHeader;
    00572         unsigned char rgbe[4];
    00573         ILubyte         *buffer;
    00574         ILfloat         *data;
    00575         ILuint          i;
    00576         ILboolean       bRet;
    00577
    00578         if (iCurImage == NULL) {
    00579                 ilSetError(IL_ILLEGAL_OPERATION);
    00580                 return IL_FALSE;
    00581         }
    00582
    00583         stHeader.exposure = 0;
    00584         stHeader.gamma = 0;
    00585         stHeader.programtype[0] = 0;
    00586         stHeader.valid = 0;
    00587
    00588         if (iCurImage->Format != IL_UNSIGNED_BYTE) {
    00589                 TempImage = iConvertImage(iCurImage, IL_RGB, IL_FLOAT);
    00590                 if (TempImage == NULL)
    00591                         return IL_FALSE;
    00592         }
    00593         else
    00594                 TempImage = iCurImage;
    00595
    00596         if (!RGBE_WriteHeader(TempImage->Width, TempImage->Height, &stHeader))
    00597                 return IL_FALSE;
    00598
    00599         if (TempImage->Origin == IL_ORIGIN_LOWER_LEFT)
    00600                 iFlipBuffer(TempImage->Data, TempImage->Depth, TempImage->Bps, TempImage->Height);
    00601         data = (ILfloat*)TempImage->Data;
    00602
    00603         if ((TempImage->Width < 8)||(TempImage->Width > 0x7fff)) {
    00604                 /* run length encoding is not allowed so write flat*/
    00605                 bRet = RGBE_WritePixels(data,TempImage->Width*TempImage->Height);
    00606                 if (iCurImage != TempImage)
    00607                         ilCloseImage(TempImage);
    00608                 return bRet;
    00609         }
    00610         buffer = (ILubyte*)ialloc(sizeof(ILubyte)*4*TempImage->Width);
    00611         if (buffer == NULL) {
    00612                 /* no buffer space so write flat */
    00613                 bRet = RGBE_WritePixels(data,TempImage->Width*TempImage->Height);
    00614                 if (iCurImage != TempImage)
    00615                         ilCloseImage(TempImage);
    00616                 return bRet;
    00617         }
    00618
    00619         while(TempImage->Height-- > 0) {
    00620                 rgbe[0] = 2;
    00621                 rgbe[1] = 2;
    00622                 rgbe[2] = TempImage->Width >> 8;
    00623                 rgbe[3] = TempImage->Width & 0xFF;
    00624                 if (iwrite(rgbe, sizeof(rgbe), 1) < 1) {
    00625                         free(buffer);
    00626                         if (iCurImage != TempImage)
    00627                                 ilCloseImage(TempImage);
    00628                         return IL_FALSE;
    00629                 }
    00630
    00631                 for(i=0;i<TempImage->Width;i++) {
    00632                         float2rgbe(rgbe,data[RGBE_DATA_RED],data[RGBE_DATA_GREEN],data[RGBE_DATA_BLUE]);
    00633                         buffer[i] = rgbe[0];
    00634                         buffer[i+TempImage->Width] = rgbe[1];
    00635                         buffer[i+2*TempImage->Width] = rgbe[2];
    00636                         buffer[i+3*TempImage->Width] = rgbe[3];
    00637                         data += RGBE_DATA_SIZE;
    00638                 }
    00639                 /* write out each of the four channels separately run length encoded */
    00640                 /* first red, then green, then blue, then exponent */
    00641                 for(i=0;i<4;i++) {
    00642                         if (RGBE_WriteBytes_RLE(&buffer[i*TempImage->Width],TempImage->Width) != IL_TRUE) {
    00643                                 ifree(buffer);
    00644                                 if (iCurImage != TempImage)
    00645                                         ilCloseImage(TempImage);
    00646                                 return IL_FALSE;
    00647                         }
    00648                 }
    00649         }
    00650         ifree(buffer);
    00651
    00652         if (iCurImage != TempImage)
    00653                 ilCloseImage(TempImage);
    00654         return IL_TRUE;
    00655 }
    00656
    00657
    00658 #endif//IL_NO_HDR