- Main Page
- Data Structures
- Files

- File List

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

    00001
    00002 #include "il_internal.h"
    00003 #ifndef IL_NO_SGI
    00004 #include "il_sgi.h"
    00005 #include "il_manip.h"
    00006 #include <limits.h>
    00007
    00008 static char *FName = NULL;
    00009
    00010 /*----------------------------------------------------------------------------*/
    00011
    00013 ILboolean ilIsValidSgi(ILconst_string FileName)
    00014 {
    00015         ILHANDLE        SgiFile;
    00016         ILboolean       bSgi = IL_FALSE;
    00017
    00018         if (!iCheckExtension(FileName, IL_TEXT("sgi"))) {
    00019                 ilSetError(IL_INVALID_EXTENSION);
    00020                 return bSgi;
    00021         }
    00022
    00023         FName = (char*)FileName;
    00024
    00025         SgiFile = iopenr(FileName);
    00026         if (SgiFile == NULL) {
    00027                 ilSetError(IL_COULD_NOT_OPEN_FILE);
    00028                 return bSgi;
    00029         }
    00030
    00031         bSgi = ilIsValidSgiF(SgiFile);
    00032         icloser(SgiFile);
    00033
    00034         return bSgi;
    00035 }
    00036
    00037 /*----------------------------------------------------------------------------*/
    00038
    00040 ILboolean ilIsValidSgiF(ILHANDLE File)
    00041 {
    00042         ILuint          FirstPos;
    00043         ILboolean       bRet;
    00044
    00045         iSetInputFile(File);
    00046         FirstPos = itell();
    00047         bRet = iIsValidSgi();
    00048         iseek(FirstPos, IL_SEEK_SET);
    00049
    00050         return bRet;
    00051 }
    00052
    00053 /*----------------------------------------------------------------------------*/
    00054
    00056 ILboolean ilIsValidSgiL(const void *Lump, ILuint Size)
    00057 {
    00058         FName = NULL;
    00059         iSetInputLump(Lump, Size);
    00060         return iIsValidSgi();
    00061 }
    00062
    00063 /*----------------------------------------------------------------------------*/
    00064
    00065 // Internal function used to get the .sgi header from the current file.
    00066 ILboolean iGetSgiHead(iSgiHeader *Header)
    00067 {
    00068         Header->MagicNum = GetBigUShort();
    00069         Header->Storage = (ILbyte)igetc();
    00070         Header->Bpc = (ILbyte)igetc();
    00071         Header->Dim = GetBigUShort();
    00072         Header->XSize = GetBigUShort();
    00073         Header->YSize = GetBigUShort();
    00074         Header->ZSize = GetBigUShort();
    00075         Header->PixMin = GetBigInt();
    00076         Header->PixMax = GetBigInt();
    00077         Header->Dummy1 = GetBigInt();
    00078         iread(Header->Name, 1, 80);
    00079         Header->ColMap = GetBigInt();
    00080         iread(Header->Dummy, 1, 404);
    00081
    00082         return IL_TRUE;
    00083 }
    00084
    00085 /*----------------------------------------------------------------------------*/
    00086
    00087 /* Internal function to get the header and check it. */
    00088 ILboolean iIsValidSgi()
    00089 {
    00090         iSgiHeader      Head;
    00091
    00092         if (!iGetSgiHead(&Head))
    00093                 return IL_FALSE;
    00094         iseek(-(ILint)sizeof(iSgiHeader), IL_SEEK_CUR);  // Go ahead and restore to previous state
    00095
    00096         return iCheckSgi(&Head);
    00097 }
    00098
    00099 /*----------------------------------------------------------------------------*/
    00100
    00101 /* Internal function used to check if the HEADER is a valid .sgi header. */
    00102 ILboolean iCheckSgi(iSgiHeader *Header)
    00103 {
    00104         if (Header->MagicNum != SGI_MAGICNUM)
    00105                 return IL_FALSE;
    00106         if (Header->Storage != SGI_RLE && Header->Storage != SGI_VERBATIM)
    00107                 return IL_FALSE;
    00108         if (Header->Bpc == 0 || Header->Dim == 0)
    00109                 return IL_FALSE;
    00110         if (Header->XSize == 0 || Header->YSize == 0 || Header->ZSize == 0)
    00111                 return IL_FALSE;
    00112
    00113         return IL_TRUE;
    00114 }
    00115
    00116 /*----------------------------------------------------------------------------*/
    00117
    00119 ILboolean ilLoadSgi(ILconst_string FileName)
    00120 {
    00121         ILHANDLE        SgiFile;
    00122         ILboolean       bSgi = IL_FALSE;
    00123
    00124         SgiFile = iopenr(FileName);
    00125         if (SgiFile == NULL) {
    00126                 ilSetError(IL_COULD_NOT_OPEN_FILE);
    00127                 return bSgi;
    00128         }
    00129
    00130         bSgi = ilLoadSgiF(SgiFile);
    00131         icloser(SgiFile);
    00132
    00133         return bSgi;
    00134 }
    00135
    00136 /*----------------------------------------------------------------------------*/
    00137
    00139 ILboolean ilLoadSgiF(ILHANDLE File)
    00140 {
    00141         ILuint          FirstPos;
    00142         ILboolean       bRet;
    00143
    00144         iSetInputFile(File);
    00145         FirstPos = itell();
    00146         bRet = iLoadSgiInternal();
    00147         iseek(FirstPos, IL_SEEK_SET);
    00148
    00149         return bRet;
    00150 }
    00151
    00152 /*----------------------------------------------------------------------------*/
    00153
    00155 ILboolean ilLoadSgiL(const void *Lump, ILuint Size)
    00156 {
    00157         iSetInputLump(Lump, Size);
    00158         return iLoadSgiInternal();
    00159 }
    00160
    00161 /*----------------------------------------------------------------------------*/
    00162
    00163 /* Internal function used to load the SGI image */
    00164 ILboolean iLoadSgiInternal()
    00165 {
    00166         iSgiHeader      Header;
    00167         ILboolean       bSgi;
    00168
    00169         if (iCurImage == NULL) {
    00170                 ilSetError(IL_ILLEGAL_OPERATION);
    00171                 return IL_FALSE;
    00172         }
    00173
    00174         if (!iGetSgiHead(&Header))
    00175                 return IL_FALSE;
    00176         if (!iCheckSgi(&Header)) {
    00177                 ilSetError(IL_INVALID_FILE_HEADER);
    00178                 return IL_FALSE;
    00179         }
    00180
    00181         // Bugfix for #1060946.
    00182         //  The ZSize should never really be 2 by the specifications.  Some
    00183         //  application is outputting these, and it looks like the ZSize
    00184         //  should really be 1.
    00185         if (Header.ZSize == 2)
    00186                 Header.ZSize = 1;
    00187
    00188         if (Header.Storage == SGI_RLE) {  // RLE
    00189                 bSgi = iReadRleSgi(&Header);
    00190         }
    00191         else {  // Non-RLE  //(Header.Storage == SGI_VERBATIM)
    00192                 bSgi = iReadNonRleSgi(&Header);
    00193         }
    00194
    00195         ilFixImage();
    00196
    00197         return bSgi;
    00198 }
    00199
    00200 /*----------------------------------------------------------------------------*/
    00201
    00202 ILboolean iReadRleSgi(iSgiHeader *Head)
    00203 {
    00204         #ifdef __LITTLE_ENDIAN__
    00205         ILuint ixTable;
    00206         #endif
    00207         ILuint          ChanInt = 0;
    00208         ILuint          ixPlane, ixHeight,ixPixel, RleOff, RleLen;
    00209         ILuint          *OffTable=NULL, *LenTable=NULL, TableSize, Cur;
    00210         ILubyte         **TempData=NULL;
    00211
    00212         if (!iNewSgi(Head))
    00213                 return IL_FALSE;
    00214
    00215         TableSize = Head->YSize * Head->ZSize;
    00216         OffTable = (ILuint*)ialloc(TableSize * sizeof(ILuint));
    00217         LenTable = (ILuint*)ialloc(TableSize * sizeof(ILuint));
    00218         if (OffTable == NULL || LenTable == NULL)
    00219                 goto cleanup_error;
    00220         if (iread(OffTable, TableSize * sizeof(ILuint), 1) != 1)
    00221                 goto cleanup_error;
    00222         if (iread(LenTable, TableSize * sizeof(ILuint), 1) != 1)
    00223                 goto cleanup_error;
    00224
    00225 #ifdef __LITTLE_ENDIAN__
    00226         // Fix the offset/len table (it's big endian format)
    00227         for (ixTable = 0; ixTable < TableSize; ixTable++) {
    00228                 iSwapUInt(OffTable + ixTable);
    00229                 iSwapUInt(LenTable + ixTable);
    00230         }
    00231 #endif //__LITTLE_ENDIAN__
    00232
    00233         // We have to create a temporary buffer for the image, because SGI
    00234         //      images are plane-separated.
    00235         TempData = (ILubyte**)ialloc(Head->ZSize * sizeof(ILubyte*));
    00236         if (TempData == NULL)
    00237                 goto cleanup_error;
    00238         imemclear(TempData, Head->ZSize * sizeof(ILubyte*));  // Just in case ialloc fails then cleanup_error.
    00239         for (ixPlane = 0; ixPlane < Head->ZSize; ixPlane++) {
    00240                 TempData[ixPlane] = (ILubyte*)ialloc(Head->XSize * Head->YSize * Head->Bpc);
    00241                 if (TempData[ixPlane] == NULL)
    00242                         goto cleanup_error;
    00243         }
    00244
    00245         // Read the Planes into the temporary memory
    00246         for (ixPlane = 0; ixPlane < Head->ZSize; ixPlane++) {
    00247                 for (ixHeight = 0, Cur = 0;     ixHeight < Head->YSize;
    00248                         ixHeight++, Cur += Head->XSize * Head->Bpc) {
    00249
    00250                         RleOff = OffTable[ixHeight + ixPlane * Head->YSize];
    00251                         RleLen = LenTable[ixHeight + ixPlane * Head->YSize];
    00252
    00253                         // Seeks to the offset table position
    00254                         iseek(RleOff, IL_SEEK_SET);
    00255                         if (iGetScanLine((TempData[ixPlane]) + (ixHeight * Head->XSize * Head->Bpc),
    00256                                 Head, RleLen) != Head->XSize * Head->Bpc) {
    00257                                         ilSetError(IL_ILLEGAL_FILE_VALUE);
    00258                                         goto cleanup_error;
    00259                         }
    00260                 }
    00261         }
    00262
    00263         // DW: Removed on 05/25/2002.
    00264         /*// Check if an alphaplane exists and invert it
    00265         if (Head->ZSize == 4) {
    00266                 for (ixPixel=0; (ILint)ixPixel<Head->XSize * Head->YSize; ixPixel++) {
    00267                         TempData[3][ixPixel] = TempData[3][ixPixel] ^ 255;
    00268                 }
    00269         }*/
    00270
    00271         // Assemble the image from its planes
    00272         for (ixPixel = 0; ixPixel < iCurImage->SizeOfData;
    00273                 ixPixel += Head->ZSize * Head->Bpc, ChanInt += Head->Bpc) {
    00274                 for (ixPlane = 0; (ILint)ixPlane < Head->ZSize * Head->Bpc;     ixPlane += Head->Bpc) {
    00275                         iCurImage->Data[ixPixel + ixPlane] = TempData[ixPlane][ChanInt];
    00276                         if (Head->Bpc == 2)
    00277                                 iCurImage->Data[ixPixel + ixPlane + 1] = TempData[ixPlane][ChanInt + 1];
    00278                 }
    00279         }
    00280
    00281         #ifdef __LITTLE_ENDIAN__
    00282         if (Head->Bpc == 2)
    00283                 sgiSwitchData(iCurImage->Data, iCurImage->SizeOfData);
    00284         #endif
    00285
    00286         ifree(OffTable);
    00287         ifree(LenTable);
    00288
    00289         for (ixPlane = 0; ixPlane < Head->ZSize; ixPlane++) {
    00290                 ifree(TempData[ixPlane]);
    00291         }
    00292         ifree(TempData);
    00293
    00294         return IL_TRUE;
    00295
    00296 cleanup_error:
    00297         ifree(OffTable);
    00298         ifree(LenTable);
    00299         if (TempData) {
    00300                 for (ixPlane = 0; ixPlane < Head->ZSize; ixPlane++) {
    00301                         ifree(TempData[ixPlane]);
    00302                 }
    00303                 ifree(TempData);
    00304         }
    00305
    00306         return IL_FALSE;
    00307 }
    00308
    00309 /*----------------------------------------------------------------------------*/
    00310
    00311 ILint iGetScanLine(ILubyte *ScanLine, iSgiHeader *Head, ILuint Length)
    00312 {
    00313         ILushort Pixel, Count;  // For current pixel
    00314         ILuint   BppRead = 0, CurPos = 0, Bps = Head->XSize * Head->Bpc;
    00315
    00316         while (BppRead < Length && CurPos < Bps)
    00317         {
    00318                 Pixel = 0;
    00319                 if (iread(&Pixel, Head->Bpc, 1) != 1)
    00320                         return -1;
    00321
    00322 #ifndef __LITTLE_ENDIAN__
    00323                 iSwapUShort(&Pixel);
    00324 #endif
    00325
    00326                 if (!(Count = (Pixel & 0x7f)))  // If 0, line ends
    00327                         return CurPos;
    00328                 if (Pixel & 0x80) {  // If top bit set, then it is a "run"
    00329                         if (iread(ScanLine, Head->Bpc, Count) != Count)
    00330                                 return -1;
    00331                         BppRead += Head->Bpc * Count + Head->Bpc;
    00332                         ScanLine += Head->Bpc * Count;
    00333                         CurPos += Head->Bpc * Count;
    00334                 }
    00335                 else {
    00336                         if (iread(&Pixel, Head->Bpc, 1) != 1)
    00337                                 return -1;
    00338 #ifndef __LITTLE_ENDIAN__
    00339                         iSwapUShort(&Pixel);
    00340 #endif
    00341                         if (Head->Bpc == 1) {
    00342                                 while (Count--) {
    00343                                         *ScanLine = (ILubyte)Pixel;
    00344                                         ScanLine++;
    00345                                         CurPos++;
    00346                                 }
    00347                         }
    00348                         else {
    00349                                 while (Count--) {
    00350                                         *(ILushort*)ScanLine = Pixel;
    00351                                         ScanLine += 2;
    00352                                         CurPos += 2;
    00353                                 }
    00354                         }
    00355                         BppRead += Head->Bpc + Head->Bpc;
    00356                 }
    00357         }
    00358
    00359         return CurPos;
    00360 }
    00361
    00362
    00363 /*----------------------------------------------------------------------------*/
    00364
    00365 // Much easier to read - just assemble from planes, no decompression
    00366 ILboolean iReadNonRleSgi(iSgiHeader *Head)
    00367 {
    00368         ILuint          i, c;
    00369         // ILint                ChanInt = 0; Unused
    00370         ILint           ChanSize;
    00371         ILboolean       Cache = IL_FALSE;
    00372
    00373         if (!iNewSgi(Head)) {
    00374                 return IL_FALSE;
    00375         }
    00376
    00377         if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST) {
    00378                 Cache = IL_TRUE;
    00379                 ChanSize = Head->XSize * Head->YSize * Head->Bpc;
    00380                 iPreCache(ChanSize);
    00381         }
    00382
    00383         for (c = 0; c < iCurImage->Bpp; c++) {
    00384                 for (i = c; i < iCurImage->SizeOfData; i += iCurImage->Bpp) {
    00385                         if (iread(iCurImage->Data + i, 1, 1) != 1) {
    00386                                 if (Cache)
    00387                                         iUnCache();
    00388                                 return IL_FALSE;
    00389                         }
    00390                 }
    00391         }
    00392
    00393         if (Cache)
    00394                 iUnCache();
    00395
    00396         return IL_TRUE;
    00397 }
    00398
    00399 /*----------------------------------------------------------------------------*/
    00400
    00401 void sgiSwitchData(ILubyte *Data, ILuint SizeOfData)
    00402 {
    00403         ILubyte Temp;
    00404         ILuint  i;
    00405         #ifdef ALTIVEC_GCC
    00406                 i = 0;
    00407                 union {
    00408                         vector unsigned char vec;
    00409                         vector unsigned int load;
    00410                 }inversion_vector;
    00411
    00412                 inversion_vector.load  = (vector unsigned int)\
    00413                         {0x01000302,0x05040706,0x09080B0A,0x0D0C0F0E};
    00414                 while( i <= SizeOfData-16 ) {
    00415                         vector unsigned char data = vec_ld(i,Data);
    00416                         vec_perm(data,data,inversion_vector.vec);
    00417                         vec_st(data,i,Data);
    00418                         i+=16;
    00419                 }
    00420                 SizeOfData -= i;
    00421         #endif
    00422         for (i = 0; i < SizeOfData; i += 2) {
    00423                 Temp = Data[i];
    00424                 Data[i] = Data[i+1];
    00425                 Data[i+1] = Temp;
    00426         }
    00427         return;
    00428 }
    00429
    00430 /*----------------------------------------------------------------------------*/
    00431
    00432 // Just an internal convenience function for reading SGI files
    00433 ILboolean iNewSgi(iSgiHeader *Head)
    00434 {
    00435         if (!ilTexImage(Head->XSize, Head->YSize, Head->Bpc, (ILubyte)Head->ZSize, 0, IL_UNSIGNED_BYTE, NULL)) {
    00436                 return IL_FALSE;
    00437         }
    00438         iCurImage->Origin = IL_ORIGIN_LOWER_LEFT;
    00439
    00440         switch (Head->ZSize)
    00441         {
    00442                 case 1:
    00443                         iCurImage->Format = IL_LUMINANCE;
    00444                         break;
    00445                 /*case 2:
    00446                         iCurImage->Format = IL_LUMINANCE_ALPHA;
    00447                         break;*/
    00448                 case 3:
    00449                         iCurImage->Format = IL_RGB;
    00450                         break;
    00451                 case 4:
    00452                         iCurImage->Format = IL_RGBA;
    00453                         break;
    00454                 default:
    00455                         ilSetError(IL_ILLEGAL_FILE_VALUE);
    00456                         return IL_FALSE;
    00457         }
    00458
    00459         switch (Head->Bpc)
    00460         {
    00461                 case 1:
    00462                         if (Head->PixMin < 0)
    00463                                 iCurImage->Type = IL_BYTE;
    00464                         else
    00465                                 iCurImage->Type = IL_UNSIGNED_BYTE;
    00466                         break;
    00467                 case 2:
    00468                         if (Head->PixMin < 0)
    00469                                 iCurImage->Type = IL_SHORT;
    00470                         else
    00471                                 iCurImage->Type = IL_UNSIGNED_SHORT;
    00472                         break;
    00473                 default:
    00474                         ilSetError(IL_ILLEGAL_FILE_VALUE);
    00475                         return IL_FALSE;
    00476         }
    00477
    00478         iCurImage->Origin = IL_ORIGIN_LOWER_LEFT;
    00479
    00480         return IL_TRUE;
    00481 }
    00482
    00483 /*----------------------------------------------------------------------------*/
    00484
    00486 ILboolean ilSaveSgi(const ILstring FileName)
    00487 {
    00488         ILHANDLE        SgiFile;
    00489         ILuint          SgiSize;
    00490
    00491         if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) {
    00492                 if (iFileExists(FileName)) {
    00493                         ilSetError(IL_FILE_ALREADY_EXISTS);
    00494                         return IL_FALSE;
    00495                 }
    00496         }
    00497
    00498         SgiFile = iopenw(FileName);
    00499         if (SgiFile == NULL) {
    00500                 ilSetError(IL_COULD_NOT_OPEN_FILE);
    00501                 return IL_FALSE;
    00502         }
    00503
    00504         SgiSize = ilSaveSgiF(SgiFile);
    00505         iclosew(SgiFile);
    00506
    00507         if (SgiSize == 0)
    00508                 return IL_FALSE;
    00509         return IL_TRUE;
    00510 }
    00511
    00512
    00514 ILuint ilSaveSgiF(ILHANDLE File)
    00515 {
    00516         ILuint Pos;
    00517         iSetOutputFile(File);
    00518         Pos = itellw();
    00519         if (iSaveSgiInternal() == IL_FALSE)
    00520                 return 0;  // Error occurred
    00521         return itellw() - Pos;  // Return the number of bytes written.
    00522 }
    00523
    00524
    00526 ILuint ilSaveSgiL(void *Lump, ILuint Size)
    00527 {
    00528         ILuint Pos = itellw();
    00529         iSetOutputLump(Lump, Size);
    00530         if (iSaveSgiInternal() == IL_FALSE)
    00531                 return 0;  // Error occurred
    00532         return itellw() - Pos;  // Return the number of bytes written.
    00533 }
    00534
    00535
    00536 ILenum DetermineSgiType(ILenum Type)
    00537 {
    00538         if (Type > IL_UNSIGNED_SHORT) {
    00539                 if (iCurImage->Type == IL_INT)
    00540                         return IL_SHORT;
    00541                 return IL_UNSIGNED_SHORT;
    00542         }
    00543         return Type;
    00544 }
    00545
    00546 /*----------------------------------------------------------------------------*/
    00547
    00548 // Rle does NOT work yet.
    00549
    00550 // Internal function used to save the Sgi.
    00551 ILboolean iSaveSgiInternal()
    00552 {
    00553         ILuint          i, c;
    00554         ILboolean       Compress;
    00555         ILimage         *Temp = iCurImage;
    00556         ILubyte         *TempData;
    00557
    00558         if (iCurImage == NULL) {
    00559                 ilSetError(IL_ILLEGAL_OPERATION);
    00560                 return IL_FALSE;
    00561         }
    00562
    00563         if (iCurImage->Format != IL_LUMINANCE
    00564             //while the sgi spec doesn't directly forbid rgb files with 2
    00565             //channels, they are quite uncommon and most apps don't support
    00566             //them. so convert lum_a images to rgba before writing.
    00567             //&& iCurImage->Format != IL_LUMINANCE_ALPHA
    00568             && iCurImage->Format != IL_RGB
    00569             && iCurImage->Format != IL_RGBA) {
    00570                 if (iCurImage->Format == IL_BGRA || iCurImage->Format == IL_LUMINANCE_ALPHA)
    00571                         Temp = iConvertImage(iCurImage, IL_RGBA, DetermineSgiType(iCurImage->Type));
    00572                 else
    00573                         Temp = iConvertImage(iCurImage, IL_RGB, DetermineSgiType(iCurImage->Type));
    00574         }
    00575         else if (iCurImage->Type > IL_UNSIGNED_SHORT) {
    00576                 Temp = iConvertImage(iCurImage, iCurImage->Format, DetermineSgiType(iCurImage->Type));
    00577         }
    00578
    00579         //compression of images with 2 bytes per channel doesn't work yet
    00580         Compress = iGetInt(IL_SGI_RLE) && Temp->Bpc == 1;
    00581
    00582         if (Temp == NULL)
    00583                 return IL_FALSE;
    00584
    00585         SaveBigUShort(SGI_MAGICNUM);  // 'Magic' number
    00586         if (Compress)
    00587                 iputc(1);
    00588         else
    00589                 iputc(0);
    00590
    00591         if (Temp->Type == IL_UNSIGNED_BYTE)
    00592                 iputc(1);
    00593         else if (Temp->Type == IL_UNSIGNED_SHORT)
    00594                 iputc(2);
    00595         // Need to error here if not one of the two...
    00596
    00597         if (Temp->Format == IL_LUMINANCE || Temp->Format == IL_COLOUR_INDEX)
    00598                 SaveBigUShort(2);
    00599         else
    00600                 SaveBigUShort(3);
    00601
    00602         SaveBigUShort((ILushort)Temp->Width);
    00603         SaveBigUShort((ILushort)Temp->Height);
    00604         SaveBigUShort((ILushort)Temp->Bpp);
    00605
    00606         switch (Temp->Type)
    00607         {
    00608                 case IL_BYTE:
    00609                         SaveBigInt(SCHAR_MIN);  // Minimum pixel value
    00610                         SaveBigInt(SCHAR_MAX);  // Maximum pixel value
    00611                         break;
    00612                 case IL_UNSIGNED_BYTE:
    00613                         SaveBigInt(0);                  // Minimum pixel value
    00614                         SaveBigInt(UCHAR_MAX);  // Maximum pixel value
    00615                         break;
    00616                 case IL_SHORT:
    00617                         SaveBigInt(SHRT_MIN);   // Minimum pixel value
    00618                         SaveBigInt(SHRT_MAX);   // Maximum pixel value
    00619                         break;
    00620                 case IL_UNSIGNED_SHORT:
    00621                         SaveBigInt(0);                  // Minimum pixel value
    00622                         SaveBigInt(USHRT_MAX);  // Maximum pixel value
    00623                         break;
    00624         }
    00625
    00626         SaveBigInt(0);  // Dummy value
    00627
    00628         if (FName) {
    00629                 c = ilCharStrLen(FName);
    00630                 c = c < 79 ? 79 : c;
    00631                 iwrite(FName, 1, c);
    00632                 c = 80 - c;
    00633                 for (i = 0; i < c; i++) {
    00634                         iputc(0);
    00635                 }
    00636         }
    00637         else {
    00638                 for (i = 0; i < 80; i++) {
    00639                         iputc(0);
    00640                 }
    00641         }
    00642
    00643         SaveBigUInt(0);  // Colormap
    00644
    00645         // Padding
    00646         for (i = 0; i < 101; i++) {
    00647                 SaveLittleInt(0);
    00648         }
    00649
    00650
    00651         if (iCurImage->Origin == IL_ORIGIN_UPPER_LEFT) {
    00652                 TempData = iGetFlipped(Temp);
    00653                 if (TempData == NULL) {
    00654                         if (Temp!= iCurImage)
    00655                                 ilCloseImage(Temp);
    00656                         return IL_FALSE;
    00657                 }
    00658         }
    00659         else {
    00660                 TempData = Temp->Data;
    00661         }
    00662
    00663
    00664         if (!Compress) {
    00665                 for (c = 0; c < Temp->Bpp; c++) {
    00666                         for (i = c; i < Temp->SizeOfData; i += Temp->Bpp) {
    00667                                 iputc(TempData[i]);  // Have to save each colour plane separately.
    00668                         }
    00669                 }
    00670         }
    00671         else {
    00672                 iSaveRleSgi(TempData, Temp->Width, Temp->Height, Temp->Bpp, Temp->Bps);
    00673         }
    00674
    00675
    00676         if (TempData != Temp->Data)
    00677                 ifree(TempData);
    00678         if (Temp != iCurImage)
    00679                 ilCloseImage(Temp);
    00680
    00681         return IL_TRUE;
    00682 }
    00683
    00684 /*----------------------------------------------------------------------------*/
    00685
    00686 ILboolean iSaveRleSgi(ILubyte *Data, ILuint w, ILuint h, ILuint numChannels,
    00687                 ILuint bps)
    00688 {
    00689         //works only for sgi files with only 1 bpc
    00690
    00691         ILuint  c, i, y, j;
    00692         ILubyte *ScanLine = NULL, *CompLine = NULL;
    00693         ILuint  *StartTable = NULL, *LenTable = NULL;
    00694         ILuint  TableOff, DataOff = 0;
    00695
    00696         ScanLine = (ILubyte*)ialloc(w);
    00697         CompLine = (ILubyte*)ialloc(w * 2 + 1);  // Absolute worst case.
    00698         StartTable = (ILuint*)ialloc(h * numChannels * sizeof(ILuint));
    00699         LenTable = (ILuint*)icalloc(h * numChannels, sizeof(ILuint));
    00700         if (!ScanLine || !CompLine || !StartTable || !LenTable) {
    00701                 ifree(ScanLine);
    00702                 ifree(CompLine);
    00703                 ifree(StartTable);
    00704                 ifree(LenTable);
    00705                 return IL_FALSE;
    00706         }
    00707
    00708         // These just contain dummy values at this point.
    00709         TableOff = itellw();
    00710         iwrite(StartTable, sizeof(ILuint), h * numChannels);
    00711         iwrite(LenTable, sizeof(ILuint), h * numChannels);
    00712
    00713         DataOff = itellw();
    00714         for (c = 0; c < numChannels; c++) {
    00715                 for (y = 0; y < h; y++) {
    00716                         i = y * bps + c;
    00717                         for (j = 0; j < w; j++, i += numChannels) {
    00718                                 ScanLine[j] = Data[i];
    00719                         }
    00720
    00721                         ilRleCompressLine(ScanLine, w, 1, CompLine, LenTable + h * c + y, IL_SGICOMP);
    00722                         iwrite(CompLine, 1, *(LenTable + h * c + y));
    00723                 }
    00724         }
    00725
    00726         iseekw(TableOff, IL_SEEK_SET);
    00727
    00728         j = h * numChannels;
    00729         for (y = 0; y < j; y++) {
    00730                 StartTable[y] = DataOff;
    00731                 DataOff += LenTable[y];
    00732 #ifdef __LITTLE_ENDIAN__
    00733                 iSwapUInt(&StartTable[y]);
    00734                 iSwapUInt(&LenTable[y]);
    00735 #endif
    00736         }
    00737
    00738         iwrite(StartTable, sizeof(ILuint), h * numChannels);
    00739         iwrite(LenTable, sizeof(ILuint), h * numChannels);
    00740
    00741         ifree(ScanLine);
    00742         ifree(CompLine);
    00743         ifree(StartTable);
    00744         ifree(LenTable);
    00745
    00746         return IL_TRUE;
    00747 }
    00748
    00749 /*----------------------------------------------------------------------------*/
    00750
    00751 #endif//IL_NO_SGI