- Main Page
- Data Structures
- Files

- File List

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

    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_targa.c
    00008 //
    00009 // Description: Reads from and writes to a targa (.tga) file.
    00010 //
    00011 //-----------------------------------------------------------------------------
    00012
    00013
    00014 #include "il_internal.h"
    00015 #ifndef IL_NO_TGA
    00016 #include "il_targa.h"
    00017 //#include <time.h>  // for ilMakeString()
    00018 #include <string.h>
    00019 #include "il_manip.h"
    00020 #include "il_bits.h"
    00021
    00022 #ifdef DJGPP
    00023 #include <dos.h>
    00024 #endif
    00025
    00026
    00028 ILboolean ilIsValidTga(ILconst_string FileName)
    00029 {
    00030         ILHANDLE        TargaFile;
    00031         ILboolean       bTarga = IL_FALSE;
    00032
    00033         if (!iCheckExtension(FileName, IL_TEXT("tga")) &&
    00034                 !iCheckExtension(FileName, IL_TEXT("vda")) &&
    00035                 !iCheckExtension(FileName, IL_TEXT("icb")) &&
    00036                 !iCheckExtension(FileName, IL_TEXT("vst"))) {
    00037                 ilSetError(IL_INVALID_EXTENSION);
    00038                 return bTarga;
    00039         }
    00040
    00041         TargaFile = iopenr(FileName);
    00042         if (TargaFile == NULL) {
    00043                 ilSetError(IL_COULD_NOT_OPEN_FILE);
    00044                 return bTarga;
    00045         }
    00046
    00047         bTarga = ilIsValidTgaF(TargaFile);
    00048         icloser(TargaFile);
    00049
    00050         return bTarga;
    00051 }
    00052
    00053
    00055 ILboolean ilIsValidTgaF(ILHANDLE File)
    00056 {
    00057         ILuint          FirstPos;
    00058         ILboolean       bRet;
    00059
    00060         iSetInputFile(File);
    00061         FirstPos = itell();
    00062         bRet = iIsValidTarga();
    00063         iseek(FirstPos, IL_SEEK_SET);
    00064
    00065         return bRet;
    00066 }
    00067
    00068
    00070 ILboolean ilIsValidTgaL(const void *Lump, ILuint Size)
    00071 {
    00072         iSetInputLump(Lump, Size);
    00073         return iIsValidTarga();
    00074 }
    00075
    00076
    00077 // Internal function used to get the Targa header from the current file.
    00078 ILboolean iGetTgaHead(TARGAHEAD *Header)
    00079 {
    00080         Header->IDLen = (ILubyte)igetc();
    00081         Header->ColMapPresent = (ILubyte)igetc();
    00082         Header->ImageType = (ILubyte)igetc();
    00083         Header->FirstEntry = GetLittleShort();
    00084         Header->ColMapLen = GetLittleShort();
    00085         Header->ColMapEntSize = (ILubyte)igetc();
    00086
    00087         Header->OriginX = GetLittleShort();
    00088         Header->OriginY = GetLittleShort();
    00089         Header->Width = GetLittleUShort();
    00090         Header->Height = GetLittleUShort();
    00091         Header->Bpp = (ILubyte)igetc();
    00092         Header->ImageDesc = (ILubyte)igetc();
    00093
    00094         return IL_TRUE;
    00095 }
    00096
    00097
    00098 // Internal function to get the header and check it.
    00099 ILboolean iIsValidTarga()
    00100 {
    00101         TARGAHEAD       Head;
    00102
    00103         if (!iGetTgaHead(&Head))
    00104                 return IL_FALSE;
    00105         iseek(-(ILint)sizeof(TARGAHEAD), IL_SEEK_CUR);
    00106
    00107         return iCheckTarga(&Head);
    00108 }
    00109
    00110
    00111 // Internal function used to check if the HEADER is a valid Targa header.
    00112 ILboolean iCheckTarga(TARGAHEAD *Header)
    00113 {
    00114         if (Header->Width == 0 || Header->Height == 0)
    00115                 return IL_FALSE;
    00116         if (Header->Bpp != 8 && Header->Bpp != 15 && Header->Bpp != 16
    00117                 && Header->Bpp != 24 && Header->Bpp != 32)
    00118                 return IL_FALSE;
    00119         if (Header->ImageDesc & BIT_4)  // Supposed to be set to 0
    00120                 return IL_FALSE;
    00121
    00122         // check type (added 20040218)
    00123         if (Header->ImageType   != TGA_NO_DATA
    00124            && Header->ImageType != TGA_COLMAP_UNCOMP
    00125            && Header->ImageType != TGA_UNMAP_UNCOMP
    00126            && Header->ImageType != TGA_BW_UNCOMP
    00127            && Header->ImageType != TGA_COLMAP_COMP
    00128            && Header->ImageType != TGA_UNMAP_COMP
    00129            && Header->ImageType != TGA_BW_COMP)
    00130                 return IL_FALSE;
    00131
    00132         // Doesn't work well with the bitshift so change it.
    00133         if (Header->Bpp == 15)
    00134                 Header->Bpp = 16;
    00135
    00136         return IL_TRUE;
    00137 }
    00138
    00139
    00141 ILboolean ilLoadTarga(ILconst_string FileName)
    00142 {
    00143         ILHANDLE        TargaFile;
    00144         ILboolean       bTarga = IL_FALSE;
    00145
    00146         TargaFile = iopenr(FileName);
    00147         if (TargaFile == NULL) {
    00148                 ilSetError(IL_COULD_NOT_OPEN_FILE);
    00149                 return bTarga;
    00150         }
    00151
    00152         bTarga = ilLoadTargaF(TargaFile);
    00153         icloser(TargaFile);
    00154
    00155         return bTarga;
    00156 }
    00157
    00158
    00160 ILboolean ilLoadTargaF(ILHANDLE File)
    00161 {
    00162         ILuint          FirstPos;
    00163         ILboolean       bRet;
    00164
    00165         iSetInputFile(File);
    00166         FirstPos = itell();
    00167         bRet = iLoadTargaInternal();
    00168         iseek(FirstPos, IL_SEEK_SET);
    00169
    00170         return bRet;
    00171 }
    00172
    00173
    00175 ILboolean ilLoadTargaL(const void *Lump, ILuint Size)
    00176 {
    00177         iSetInputLump(Lump, Size);
    00178         return iLoadTargaInternal();
    00179 }
    00180
    00181
    00182 // Internal function used to load the Targa.
    00183 ILboolean iLoadTargaInternal()
    00184 {
    00185         TARGAHEAD       Header;
    00186         ILboolean       bTarga;
    00187         ILenum          iOrigin;
    00188
    00189         if (iCurImage == NULL) {
    00190                 ilSetError(IL_ILLEGAL_OPERATION);
    00191                 return IL_FALSE;
    00192         }
    00193
    00194         if (!iGetTgaHead(&Header))
    00195                 return IL_FALSE;
    00196         if (!iCheckTarga(&Header)) {
    00197                 ilSetError(IL_INVALID_FILE_HEADER);
    00198                 return IL_FALSE;
    00199         }
    00200
    00201         switch (Header.ImageType)
    00202         {
    00203                 case TGA_NO_DATA:
    00204                         ilSetError(IL_ILLEGAL_FILE_VALUE);
    00205                         return IL_FALSE;
    00206                 case TGA_COLMAP_UNCOMP:
    00207                 case TGA_COLMAP_COMP:
    00208                         bTarga = iReadColMapTga(&Header);
    00209                         break;
    00210                 case TGA_UNMAP_UNCOMP:
    00211                 case TGA_UNMAP_COMP:
    00212                         bTarga = iReadUnmapTga(&Header);
    00213                         break;
    00214                 case TGA_BW_UNCOMP:
    00215                 case TGA_BW_COMP:
    00216                         bTarga = iReadBwTga(&Header);
    00217                         break;
    00218                 default:
    00219                         ilSetError(IL_ILLEGAL_FILE_VALUE);
    00220                         return IL_FALSE;
    00221         }
    00222
    00223         // @JASON Extra Code to manipulate the image depending on
    00224         // the Image Descriptor's origin bits.
    00225         iOrigin = Header.ImageDesc & IMAGEDESC_ORIGIN_MASK;
    00226
    00227         switch (iOrigin)
    00228         {
    00229                 case IMAGEDESC_TOPLEFT:
    00230                         iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
    00231                         break;
    00232
    00233                 case IMAGEDESC_TOPRIGHT:
    00234                         iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
    00235                         iMirror();
    00236                         break;
    00237
    00238                 case IMAGEDESC_BOTLEFT:
    00239                         iCurImage->Origin = IL_ORIGIN_LOWER_LEFT;
    00240                         break;
    00241
    00242                 case IMAGEDESC_BOTRIGHT:
    00243                         iCurImage->Origin = IL_ORIGIN_LOWER_LEFT;
    00244                         iMirror();
    00245                         break;
    00246         }
    00247
    00248         ilFixImage();
    00249
    00250         return bTarga;
    00251 }
    00252
    00253
    00254 ILboolean iReadColMapTga(TARGAHEAD *Header)
    00255 {
    00256         char            ID[255];
    00257         ILuint          i;
    00258         ILushort        Pixel;
    00259
    00260         if (iread(ID, 1, Header->IDLen) != Header->IDLen)
    00261                 return IL_FALSE;
    00262
    00263         if (!ilTexImage(Header->Width, Header->Height, 1, (ILubyte)(Header->Bpp >> 3), 0, IL_UNSIGNED_BYTE, NULL)) {
    00264                 return IL_FALSE;
    00265         }
    00266         if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize)
    00267                 ifree(iCurImage->Pal.Palette);
    00268
    00269         iCurImage->Format = IL_COLOUR_INDEX;
    00270         iCurImage->Pal.PalSize = Header->ColMapLen * (Header->ColMapEntSize >> 3);
    00271
    00272         switch (Header->ColMapEntSize)
    00273         {
    00274                 case 16:
    00275                         iCurImage->Pal.PalType = IL_PAL_BGRA32;
    00276                         iCurImage->Pal.PalSize = Header->ColMapLen * 4;
    00277                         break;
    00278                 case 24:
    00279                         iCurImage->Pal.PalType = IL_PAL_BGR24;
    00280                         break;
    00281                 case 32:
    00282                         iCurImage->Pal.PalType = IL_PAL_BGRA32;
    00283                         break;
    00284                 default:
    00285                         // Should *never* reach here
    00286                         ilSetError(IL_ILLEGAL_FILE_VALUE);
    00287                         return IL_FALSE;
    00288         }
    00289
    00290         iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize);
    00291         if (iCurImage->Pal.Palette == NULL) {
    00292                 return IL_FALSE;
    00293         }
    00294
    00295         // Do we need to do something with FirstEntry?  Like maybe:
    00296         //      iread(Image->Pal + Targa->FirstEntry, 1, Image->Pal.PalSize);  ??
    00297         if (Header->ColMapEntSize != 16)
    00298         {
    00299                 if (iread(iCurImage->Pal.Palette, 1, iCurImage->Pal.PalSize) != iCurImage->Pal.PalSize)
    00300                         return IL_FALSE;
    00301         }
    00302         else {
    00303                 // 16 bit palette, so we have to break it up.
    00304                 for (i = 0; i < iCurImage->Pal.PalSize; i += 4)
    00305                 {
    00306                         Pixel = GetBigUShort();
    00307                         if (ieof())
    00308                                 return IL_FALSE;
    00309                         iCurImage->Pal.Palette[3] = (Pixel & 0x8000) >> 12;
    00310                         iCurImage->Pal.Palette[0] = (Pixel & 0xFC00) >> 7;
    00311                         iCurImage->Pal.Palette[1] = (Pixel & 0x03E0) >> 2;
    00312                         iCurImage->Pal.Palette[2] = (Pixel & 0x001F) << 3;
    00313                 }
    00314         }
    00315
    00316         if (Header->ImageType == TGA_COLMAP_COMP)
    00317         {
    00318                 if (!iUncompressTgaData(iCurImage))
    00319                 {
    00320                         return IL_FALSE;
    00321                 }
    00322         }
    00323         else
    00324         {
    00325                 if (iread(iCurImage->Data, 1, iCurImage->SizeOfData) != iCurImage->SizeOfData)
    00326                 {
    00327                         return IL_FALSE;
    00328                 }
    00329         }
    00330
    00331         return IL_TRUE;
    00332 }
    00333
    00334
    00335 ILboolean iReadUnmapTga(TARGAHEAD *Header)
    00336 {
    00337         ILubyte Bpp;
    00338         char    ID[255];
    00339
    00340         if (iread(ID, 1, Header->IDLen) != Header->IDLen)
    00341                 return IL_FALSE;
    00342
    00343         /*if (Header->Bpp == 16)
    00344                 Bpp = 3;
    00345         else*/
    00346         Bpp = (ILubyte)(Header->Bpp >> 3);
    00347
    00348         if (!ilTexImage(Header->Width, Header->Height, 1, Bpp, 0, IL_UNSIGNED_BYTE, NULL)) {
    00349                 return IL_FALSE;
    00350         }
    00351
    00352         switch (iCurImage->Bpp)
    00353         {
    00354                 case 1:
    00355                         iCurImage->Format = IL_COLOUR_INDEX;  // wtf?  How is this possible?
    00356                         break;
    00357                 case 2:  // 16-bit is not supported directly!
    00358                                  //iCurImage->Format = IL_RGB5_A1;
    00359                         /*iCurImage->Format = IL_RGBA;
    00360                         iCurImage->Type = IL_UNSIGNED_SHORT_5_5_5_1_EXT;*/
    00361                         //iCurImage->Type = IL_UNSIGNED_SHORT_5_6_5_REV;
    00362
    00363                         // Remove?
    00364                         //ilCloseImage(iCurImage);
    00365                         //ilSetError(IL_FORMAT_NOT_SUPPORTED);
    00366                         //return IL_FALSE;
    00367
    00368                         /*iCurImage->Bpp = 4;
    00369                         iCurImage->Format = IL_BGRA;
    00370                         iCurImage->Type = IL_UNSIGNED_SHORT_1_5_5_5_REV;*/
    00371
    00372                         iCurImage->Format = IL_BGR;
    00373
    00374                         break;
    00375                 case 3:
    00376                         iCurImage->Format = IL_BGR;
    00377                         break;
    00378                 case 4:
    00379                         iCurImage->Format = IL_BGRA;
    00380                         break;
    00381                 default:
    00382                         ilSetError(IL_INVALID_VALUE);
    00383                         return IL_FALSE;
    00384         }
    00385
    00386
    00387         // @TODO:  Determine this:
    00388         // We assume that no palette is present, but it's possible...
    00389         //      Should we mess with it or not?
    00390
    00391
    00392         if (Header->ImageType == TGA_UNMAP_COMP) {
    00393                 if (!iUncompressTgaData(iCurImage)) {
    00394                         return IL_FALSE;
    00395                 }
    00396         }
    00397         else {
    00398                 if (iread(iCurImage->Data, 1, iCurImage->SizeOfData) != iCurImage->SizeOfData) {
    00399                         return IL_FALSE;
    00400                 }
    00401         }
    00402
    00403         // Go ahead and expand it to 24-bit.
    00404         if (Header->Bpp == 16) {
    00405                 if (!i16BitTarga(iCurImage))
    00406                         return IL_FALSE;
    00407                 return IL_TRUE;
    00408         }
    00409
    00410         return IL_TRUE;
    00411 }
    00412
    00413
    00414 ILboolean iReadBwTga(TARGAHEAD *Header)
    00415 {
    00416         char ID[255];
    00417
    00418         if (iread(ID, 1, Header->IDLen) != Header->IDLen)
    00419                 return IL_FALSE;
    00420
    00421         // We assume that no palette is present, but it's possible...
    00422         //      Should we mess with it or not?
    00423
    00424         if (!ilTexImage(Header->Width, Header->Height, 1, (ILubyte)(Header->Bpp >> 3), IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL)) {
    00425                 return IL_FALSE;
    00426         }
    00427
    00428         if (Header->ImageType == TGA_BW_COMP) {
    00429                 if (!iUncompressTgaData(iCurImage)) {
    00430                         return IL_FALSE;
    00431                 }
    00432         }
    00433         else {
    00434                 if (iread(iCurImage->Data, 1, iCurImage->SizeOfData) != iCurImage->SizeOfData) {
    00435                         return IL_FALSE;
    00436                 }
    00437         }
    00438
    00439         return IL_TRUE;
    00440 }
    00441
    00442
    00443 ILboolean iUncompressTgaData(ILimage *Image)
    00444 {
    00445         ILuint  BytesRead = 0, Size, RunLen, i;
    00446         ILubyte Header, Color[4];
    00447         ILint   c;
    00448
    00449         Size = Image->Width * Image->Height * Image->Depth * Image->Bpp;
    00450
    00451         if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST)
    00452                 iPreCache(iCurImage->SizeOfData / 2);
    00453
    00454         while (BytesRead < Size) {
    00455                 Header = (ILubyte)igetc();
    00456                 if (Header & BIT_7) {
    00457                         ClearBits(Header, BIT_7);
    00458                         if (iread(Color, 1, Image->Bpp) != Image->Bpp) {
    00459                                 iUnCache();
    00460                                 return IL_FALSE;
    00461                         }
    00462                         RunLen = (Header+1) * Image->Bpp;
    00463                         for (i = 0; i < RunLen; i += Image->Bpp) {
    00464                                 for (c = 0; c < Image->Bpp; c++) {
    00465                                         Image->Data[BytesRead+i+c] = Color[c];
    00466                                 }
    00467                         }
    00468                         BytesRead += RunLen;
    00469                 }
    00470                 else {
    00471                         RunLen = (Header+1) * Image->Bpp;
    00472                         if (iread(Image->Data + BytesRead, 1, RunLen) != RunLen) {
    00473                                 iUnCache();
    00474                                 return IL_FALSE;
    00475                         }
    00476                         BytesRead += RunLen;
    00477                 }
    00478         }
    00479
    00480         iUnCache();
    00481
    00482         return IL_TRUE;
    00483 }
    00484
    00485
    00486 // Pretty damn unoptimized
    00487 ILboolean i16BitTarga(ILimage *Image)
    00488 {
    00489         ILushort        *Temp1;
    00490         ILubyte         *Data, *Temp2;
    00491         ILuint          x, PixSize = Image->Width * Image->Height;
    00492
    00493         Data = (ILubyte*)ialloc(Image->Width * Image->Height * 3);
    00494         Temp1 = (ILushort*)Image->Data;
    00495         Temp2 = Data;
    00496
    00497         if (Data == NULL)
    00498                 return IL_FALSE;
    00499
    00500         for (x = 0; x < PixSize; x++) {
    00501                 *Temp2++ = (*Temp1 & 0x001F) << 3;      // Blue
    00502                 *Temp2++ = (*Temp1 & 0x03E0) >> 2;      // Green
    00503                 *Temp2++ = (*Temp1 & 0x7C00) >> 7;      // Red
    00504
    00505                 Temp1++;
    00506
    00507
    00508                 /*s = *Temp;
    00509                 s = SwapShort(s);
    00510                 a = !!(s & BIT_15);
    00511
    00512                 s = s << 1;
    00513
    00514                 //if (a) {
    00515                 SetBits(s, BIT_0);
    00516                 //}
    00517
    00518                 //SetBits(s, BIT_15);
    00519
    00520                 *Temp++ = s;*/
    00521         }
    00522
    00523         if (!ilTexImage(Image->Width, Image->Height, 1, 3, IL_BGR, IL_UNSIGNED_BYTE, Data)) {
    00524                 ifree(Data);
    00525                 return IL_FALSE;
    00526         }
    00527
    00528         ifree(Data);
    00529
    00530         return IL_TRUE;
    00531 }
    00532
    00533
    00535 ILboolean ilSaveTarga(const ILstring FileName)
    00536 {
    00537         ILHANDLE        TargaFile;
    00538         ILuint          TargaSize;
    00539
    00540         if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) {
    00541                 if (iFileExists(FileName)) {
    00542                         ilSetError(IL_FILE_ALREADY_EXISTS);
    00543                         return IL_FALSE;
    00544                 }
    00545         }
    00546
    00547         TargaFile = iopenw(FileName);
    00548         if (TargaFile == NULL) {
    00549                 ilSetError(IL_COULD_NOT_OPEN_FILE);
    00550                 return IL_FALSE;
    00551         }
    00552
    00553         TargaSize = ilSaveTargaF(TargaFile);
    00554         iclosew(TargaFile);
    00555
    00556         if (TargaSize == 0)
    00557                 return IL_FALSE;
    00558         return IL_TRUE;
    00559 }
    00560
    00561
    00563 ILuint ilSaveTargaF(ILHANDLE File)
    00564 {
    00565         ILuint Pos;
    00566         iSetOutputFile(File);
    00567         Pos = itellw();
    00568         if (iSaveTargaInternal() == IL_FALSE)
    00569                 return 0;  // Error occurred
    00570         return itellw() - Pos;  // Return the number of bytes written.
    00571 }
    00572
    00573
    00575 ILuint ilSaveTargaL(void *Lump, ILuint Size)
    00576 {
    00577         ILuint Pos = itellw();
    00578         iSetOutputLump(Lump, Size);
    00579         if (iSaveTargaInternal() == IL_FALSE)
    00580                 return 0;  // Error occurred
    00581         return itellw() - Pos;  // Return the number of bytes written.
    00582 }
    00583
    00584
    00585 // Internal function used to save the Targa.
    00586 ILboolean iSaveTargaInternal()
    00587 {
    00588         const char      *ID = iGetString(IL_TGA_ID_STRING);
    00589         const char      *AuthName = iGetString(IL_TGA_AUTHNAME_STRING);
    00590         const char      *AuthComment = iGetString(IL_TGA_AUTHCOMMENT_STRING);
    00591         ILubyte         IDLen = 0, UsePal, Type, PalEntSize;
    00592         ILshort         ColMapStart = 0, PalSize;
    00593         ILubyte         Temp;
    00594         ILenum          Format;
    00595         ILboolean       Compress;
    00596         ILuint          RleLen;
    00597         ILubyte         *Rle;
    00598         ILpal           *TempPal = NULL;
    00599         ILimage         *TempImage = NULL;
    00600         ILuint          ExtOffset, i;
    00601         char            *Footer = "TRUEVISION-XFILE.\0";
    00602         char            *idString = "Developer's Image Library (DevIL)";
    00603         ILuint          Day, Month, Year, Hour, Minute, Second;
    00604         char            *TempData;
    00605
    00606         if (iCurImage == NULL) {
    00607                 ilSetError(IL_ILLEGAL_OPERATION);
    00608                 return IL_FALSE;
    00609         }
    00610
    00611         if (iGetInt(IL_TGA_RLE) == IL_TRUE)
    00612                 Compress = IL_TRUE;
    00613         else
    00614                 Compress = IL_FALSE;
    00615
    00616         if (ID)
    00617                 IDLen = (ILubyte)ilCharStrLen(ID);
    00618
    00619         if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize && iCurImage->Pal.PalType != IL_PAL_NONE)
    00620                 UsePal = IL_TRUE;
    00621         else
    00622                 UsePal = IL_FALSE;
    00623
    00624         iwrite(&IDLen, sizeof(ILubyte), 1);
    00625         iwrite(&UsePal, sizeof(ILubyte), 1);
    00626
    00627         Format = iCurImage->Format;
    00628         switch (Format) {
    00629                 case IL_COLOUR_INDEX:
    00630                         if (Compress)
    00631                                 Type = 9;
    00632                         else
    00633                                 Type = 1;
    00634                         break;
    00635                 case IL_BGR:
    00636                 case IL_BGRA:
    00637                         if (Compress)
    00638                                 Type = 10;
    00639                         else
    00640                                 Type = 2;
    00641                         break;
    00642                 case IL_RGB:
    00643                 case IL_RGBA:
    00644                         ilSwapColours();
    00645                         if (Compress)
    00646                                 Type = 10;
    00647                         else
    00648                                 Type = 2;
    00649                         break;
    00650                 case IL_LUMINANCE:
    00651                         if (Compress)
    00652                                 Type = 11;
    00653                         else
    00654                                 Type = 3;
    00655                         break;
    00656                 default:
    00657                         // Should convert the types here...
    00658                         ilSetError(IL_INVALID_VALUE);
    00659                         ifree(ID);
    00660                         ifree(AuthName);
    00661                         ifree(AuthComment);
    00662                         return IL_FALSE;
    00663         }
    00664
    00665         iwrite(&Type, sizeof(ILubyte), 1);
    00666         SaveLittleShort(ColMapStart);
    00667
    00668         switch (iCurImage->Pal.PalType)
    00669         {
    00670                 case IL_PAL_NONE:
    00671                         PalSize = 0;
    00672                         PalEntSize = 0;
    00673                         break;
    00674                 case IL_PAL_BGR24:
    00675                         PalSize = (ILshort)(iCurImage->Pal.PalSize / 3);
    00676                         PalEntSize = 24;
    00677                         TempPal = &iCurImage->Pal;
    00678                         break;
    00679
    00680                 case IL_PAL_RGB24:
    00681                 case IL_PAL_RGB32:
    00682                 case IL_PAL_RGBA32:
    00683                 case IL_PAL_BGR32:
    00684                 case IL_PAL_BGRA32:
    00685                         TempPal = iConvertPal(&iCurImage->Pal, IL_PAL_BGR24);
    00686                         if (TempPal == NULL)
    00687                                 return IL_FALSE;
    00688                                 PalSize = (ILshort)(TempPal->PalSize / 3);
    00689                         PalEntSize = 24;
    00690                         break;
    00691                 default:
    00692                         ilSetError(IL_INVALID_VALUE);
    00693                         ifree(ID);
    00694                         ifree(AuthName);
    00695                         ifree(AuthComment);
    00696                         PalSize = 0;
    00697                         PalEntSize = 0;
    00698                         return IL_FALSE;
    00699         }
    00700         SaveLittleShort(PalSize);
    00701         iwrite(&PalEntSize, sizeof(ILubyte), 1);
    00702
    00703         if (iCurImage->Bpc > 1) {
    00704                 TempImage = iConvertImage(iCurImage, iCurImage->Format, IL_UNSIGNED_BYTE);
    00705                 if (TempImage == NULL) {
    00706                         ifree(ID);
    00707                         ifree(AuthName);
    00708                         ifree(AuthComment);
    00709                         return IL_FALSE;
    00710                 }
    00711         }
    00712         else {
    00713                 TempImage = iCurImage;
    00714         }
    00715
    00716         if (TempImage->Origin != IL_ORIGIN_LOWER_LEFT)
    00717                 TempData = (char*)iGetFlipped(TempImage);
    00718         else
    00719                 TempData = (char*)TempImage->Data;
    00720
    00721         // Write out the origin stuff.
    00722         Temp = 0;
    00723         iwrite(&Temp, sizeof(ILshort), 1);
    00724         iwrite(&Temp, sizeof(ILshort), 1);
    00725
    00726         Temp = iCurImage->Bpp << 3;  // Changes to bits per pixel
    00727         SaveLittleUShort((ILushort)iCurImage->Width);
    00728         SaveLittleUShort((ILushort)iCurImage->Height);
    00729         iwrite(&Temp, sizeof(ILubyte), 1);
    00730
    00731         // Still don't know what exactly this is for...
    00732         Temp = 0;
    00733         iwrite(&Temp, sizeof(ILubyte), 1);
    00734         iwrite(ID, sizeof(char), IDLen);
    00735         ifree(ID);
    00736         //iwrite(ID, sizeof(ILbyte), IDLen - sizeof(ILuint));
    00737         //iwrite(&iCurImage->Depth, sizeof(ILuint), 1);
    00738
    00739         // Write out the colormap
    00740         if (UsePal)
    00741                 iwrite(TempPal->Palette, sizeof(ILubyte), TempPal->PalSize);
    00742         // else do nothing
    00743
    00744         if (!Compress)
    00745                 iwrite(TempData, sizeof(ILubyte), TempImage->SizeOfData);
    00746         else {
    00747                 Rle = (ILubyte*)ialloc(TempImage->SizeOfData + TempImage->SizeOfData / 2 + 1);  // max
    00748                 if (Rle == NULL) {
    00749                         ifree(AuthName);
    00750                         ifree(AuthComment);
    00751                         return IL_FALSE;
    00752                 }
    00753                 RleLen = ilRleCompress((unsigned char*)TempData, TempImage->Width, TempImage->Height,
    00754                                        TempImage->Depth, TempImage->Bpp, Rle, IL_TGACOMP, NULL);
    00755
    00756                 iwrite(Rle, 1, RleLen);
    00757                 ifree(Rle);
    00758         }
    00759
    00760         // Write the extension area.
    00761         ExtOffset = itellw();
    00762         SaveLittleUShort(495);  // Number of bytes in the extension area (TGA 2.0 spec)
    00763         iwrite(AuthName, 1, ilCharStrLen(AuthName));
    00764         ipad(41 - ilCharStrLen(AuthName));
    00765         iwrite(AuthComment, 1, ilCharStrLen(AuthComment));
    00766         ipad(324 - ilCharStrLen(AuthComment));
    00767         ifree(AuthName);
    00768         ifree(AuthComment);
    00769
    00770         // Write time/date
    00771         iGetDateTime(&Month, &Day, &Year, &Hour, &Minute, &Second);
    00772         SaveLittleUShort((ILushort)Month);
    00773         SaveLittleUShort((ILushort)Day);
    00774         SaveLittleUShort((ILushort)Year);
    00775         SaveLittleUShort((ILushort)Hour);
    00776         SaveLittleUShort((ILushort)Minute);
    00777         SaveLittleUShort((ILushort)Second);
    00778
    00779         for (i = 0; i < 6; i++) {  // Time created
    00780                 SaveLittleUShort(0);
    00781         }
    00782         for (i = 0; i < 41; i++) {      // Job name/ID
    00783                 iputc(0);
    00784         }
    00785         for (i = 0; i < 3; i++) {  // Job time
    00786                 SaveLittleUShort(0);
    00787         }
    00788
    00789         iwrite(idString, 1, ilCharStrLen(idString));    // Software ID
    00790         for (i = 0; i < 41 - ilCharStrLen(idString); i++) {
    00791                 iputc(0);
    00792         }
    00793         SaveLittleUShort(IL_VERSION);  // Software version
    00794         iputc(' ');  // Release letter (not beta anymore, so use a space)
    00795
    00796         SaveLittleUInt(0);      // Key colour
    00797         SaveLittleUInt(0);      // Pixel aspect ratio
    00798         SaveLittleUInt(0);      // Gamma correction offset
    00799         SaveLittleUInt(0);      // Colour correction offset
    00800         SaveLittleUInt(0);      // Postage stamp offset
    00801         SaveLittleUInt(0);      // Scan line offset
    00802         iputc(3);  // Attributes type
    00803
    00804         // Write the footer.
    00805         SaveLittleUInt(ExtOffset);      // No extension area
    00806         SaveLittleUInt(0);      // No developer directory
    00807         iwrite(Footer, 1, ilCharStrLen(Footer));
    00808
    00809         if (TempImage->Origin != IL_ORIGIN_LOWER_LEFT) {
    00810                 ifree(TempData);
    00811         }
    00812         if (Format == IL_RGB || Format == IL_RGBA) {
    00813                 ilSwapColours();
    00814         }
    00815
    00816         if (TempPal != &iCurImage->Pal && TempPal != NULL) {
    00817                 ifree(TempPal->Palette);
    00818                 ifree(TempPal);
    00819         }
    00820
    00821         if (TempImage != iCurImage)
    00822                 ilCloseImage(TempImage);
    00823
    00824         return IL_TRUE;
    00825 }
    00826
    00827
    00828 // Only to be called by ilDetermineSize.  Returns the buffer size needed to save the
    00829 //  current image as a Targa file.
    00830 ILuint iTargaSize(void)
    00831 {
    00832         ILuint  Size, Bpp;
    00833         ILubyte IDLen = 0;
    00834         const char      *ID = iGetString(IL_TGA_ID_STRING);
    00835         const char      *AuthName = iGetString(IL_TGA_AUTHNAME_STRING);
    00836         const char      *AuthComment = iGetString(IL_TGA_AUTHCOMMENT_STRING);
    00837
    00838         //@TODO: Support color indexed images.
    00839         if (iGetInt(IL_TGA_RLE) == IL_TRUE || iCurImage->Format == IL_COLOUR_INDEX) {
    00840                 // Use the slower method, since we are using compression.  We do a "fake" write.
    00841                 ilSaveTargaL(NULL, 0);
    00842         }
    00843
    00844         if (ID)
    00845                 IDLen = (ILubyte)ilCharStrLen(ID);
    00846
    00847         Size = 18 + IDLen;  // Header + ID
    00848
    00849         // Bpp may not be iCurImage->Bpp.
    00850         switch (iCurImage->Format)
    00851         {
    00852                 case IL_BGR:
    00853                 case IL_RGB:
    00854                         Bpp = 3;
    00855                         break;
    00856                 case IL_BGRA:
    00857                 case IL_RGBA:
    00858                         Bpp = 4;
    00859                         break;
    00860                 case IL_LUMINANCE:
    00861                         Bpp = 1;
    00862                         break;
    00863                 default:  //@TODO: Do not know what to do with the others yet.
    00864                         return 0;
    00865         }
    00866
    00867         Size += iCurImage->Width * iCurImage->Height * Bpp;
    00868         Size += 532;  // Size of the extension area
    00869
    00870         return Size;
    00871 }
    00872
    00873
    00874 /*// Makes a neat string to go into the id field of the .tga
    00875 void iMakeString(char *Str)
    00876 {
    00877         char            *PSG = "Generated by Developer's Image Library: ";
    00878         char            TimeStr[255];
    00879
    00880         time_t          Time;
    00881         struct tm       *CurTime;
    00882
    00883         time(&Time);
    00884 #ifdef _WIN32
    00885         _tzset();
    00886 #endif
    00887         CurTime = localtime(&Time);
    00888
    00889         strftime(TimeStr, 255 - ilCharStrLen(PSG), "%#c (%z)", CurTime);
    00890         //strftime(TimeStr, 255 - ilCharStrLen(PSG), "%C (%Z)", CurTime);
    00891         sprintf(Str, "%s%s", PSG, TimeStr);
    00892
    00893         return;
    00894 }*/
    00895
    00896
    00897 //changed name to iGetDateTime on 20031221 to fix bug 830196
    00898 void iGetDateTime(ILuint *Month, ILuint *Day, ILuint *Yr, ILuint *Hr, ILuint *Min, ILuint *Sec)
    00899 {
    00900 #ifdef DJGPP
    00901         struct date day;
    00902         struct time curtime;
    00903
    00904         gettime(&curtime);
    00905         getdate(&day);
    00906
    00907         *Month = day.da_mon;
    00908         *Day = day.da_day;
    00909         *Yr = day.da_year;
    00910
    00911         *Hr = curtime.ti_hour;
    00912         *Min = curtime.ti_min;
    00913         *Sec = curtime.ti_sec;
    00914
    00915         return;
    00916 #else
    00917
    00918 #ifdef _WIN32
    00919         SYSTEMTIME Time;
    00920
    00921         GetSystemTime(&Time);
    00922
    00923         *Month = Time.wMonth;
    00924         *Day = Time.wDay;
    00925         *Yr = Time.wYear;
    00926
    00927         *Hr = Time.wHour;
    00928         *Min = Time.wMinute;
    00929         *Sec = Time.wSecond;
    00930
    00931         return;
    00932 #else
    00933
    00934         *Month = 0;
    00935         *Day = 0;
    00936         *Yr = 0;
    00937
    00938         *Hr = 0;
    00939         *Min = 0;
    00940         *Sec = 0;
    00941
    00942         return;
    00943 #endif
    00944 #endif
    00945 }
    00946
    00947
    00948 #endif//IL_NO_TGA