- Main Page
- Data Structures
- Files

- File List

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

    00001 //-----------------------------------------------------------------------------
    00002 //
    00003 // ImageLib Sources
    00004 // Copyright (C) 2001-2009 by Denton Woods
    00005 // Last modified: 01/15/2009
    00006 //
    00007 // Filename: src-IL/src/il_icns.c
    00008 //
    00009 // Description: Reads from a Mac OS X icon (.icns) file.
    00010 //              Credit for the format of .icns files goes to
    00011 //              http://www.macdisk.com/maciconen.php3 and
    00012 //              http://ezix.org/project/wiki/MacOSXIcons
    00013 //
    00014 //-----------------------------------------------------------------------------
    00015
    00016 //@TODO: Put ilSetError calls in when errors occur.
    00017 //@TODO: Should we clear the alpha channel just in case there isn't one in the file?
    00018 //@TODO: Checks on iread
    00019
    00020 #include "il_internal.h"
    00021 #ifndef IL_NO_ICNS
    00022 #include "il_icns.h"
    00023
    00024 #ifndef IL_NO_JP2
    00025         #if defined(_WIN32) && defined(IL_USE_PRAGMA_LIBS)
    00026                 #if defined(_MSC_VER) || defined(__BORLANDC__)
    00027                         #ifndef _DEBUG
    00028                                 #pragma comment(lib, "libjasper.lib")
    00029                         #else
    00030                                 #pragma comment(lib, "libjasper-d.lib")
    00031                         #endif
    00032                 #endif
    00033         #endif
    00034 #endif//IL_NO_JP2
    00035
    00036
    00038 ILboolean ilIsValidIcns(ILconst_string FileName)
    00039 {
    00040         ILHANDLE        IcnsFile;
    00041         ILboolean       bIcns = IL_FALSE;
    00042
    00043         if (!iCheckExtension(FileName, IL_TEXT("icns"))) {
    00044                 ilSetError(IL_INVALID_EXTENSION);
    00045                 return bIcns;
    00046         }
    00047
    00048         IcnsFile = iopenr(FileName);
    00049         if (IcnsFile == NULL) {
    00050                 ilSetError(IL_COULD_NOT_OPEN_FILE);
    00051                 return bIcns;
    00052         }
    00053
    00054         bIcns = ilIsValidIcnsF(IcnsFile);
    00055         icloser(IcnsFile);
    00056
    00057         return bIcns;
    00058 }
    00059
    00060
    00062 ILboolean ilIsValidIcnsF(ILHANDLE File)
    00063 {
    00064         ILuint          FirstPos;
    00065         ILboolean       bRet;
    00066
    00067         iSetInputFile(File);
    00068         FirstPos = itell();
    00069         bRet = iIsValidIcns();
    00070         iseek(FirstPos, IL_SEEK_SET);
    00071
    00072         return bRet;
    00073 }
    00074
    00075
    00077 ILboolean ilIsValidIcnsL(const void *Lump, ILuint Size)
    00078 {
    00079         iSetInputLump(Lump, Size);
    00080         return iIsValidIcns();
    00081 }
    00082
    00083
    00084 // Internal function to get the header and check it.
    00085 ILboolean iIsValidIcns()
    00086 {
    00087         ICNSHEAD        Header;
    00088
    00089         iread(Header.Head, 1, 4);
    00090         iseek(-4, IL_SEEK_CUR);  // Go ahead and restore to previous state
    00091
    00092         if (strncmp(Header.Head, "icns", 4))  // First 4 bytes have to be 'icns'.
    00093                 return IL_FALSE;
    00094
    00095         return IL_TRUE;
    00096 }
    00097
    00098
    00100 ILboolean ilLoadIcns(ILconst_string FileName)
    00101 {
    00102         ILHANDLE        IcnsFile;
    00103         ILboolean       bIcns = IL_FALSE;
    00104
    00105         IcnsFile = iopenr(FileName);
    00106         if (IcnsFile == NULL) {
    00107                 ilSetError(IL_COULD_NOT_OPEN_FILE);
    00108                 return bIcns;
    00109         }
    00110
    00111         bIcns = ilLoadIcnsF(IcnsFile);
    00112         icloser(IcnsFile);
    00113
    00114         return bIcns;
    00115 }
    00116
    00117
    00119 ILboolean ilLoadIcnsF(ILHANDLE File)
    00120 {
    00121         ILuint          FirstPos;
    00122         ILboolean       bRet;
    00123
    00124         iSetInputFile(File);
    00125         FirstPos = itell();
    00126         bRet = iLoadIcnsInternal();
    00127         iseek(FirstPos, IL_SEEK_SET);
    00128
    00129         return bRet;
    00130 }
    00131
    00132
    00134 ILboolean ilLoadIcnsL(const void *Lump, ILuint Size)
    00135 {
    00136         iSetInputLump(Lump, Size);
    00137         return iLoadIcnsInternal();
    00138 }
    00139
    00140
    00141 // Internal function used to load the icon.
    00142 ILboolean iLoadIcnsInternal()
    00143 {
    00144         ICNSHEAD        Header;
    00145         ICNSDATA        Entry;
    00146         ILimage         *Image = NULL;
    00147         ILboolean       BaseCreated = IL_FALSE;
    00148
    00149
    00150         if (iCurImage == NULL)
    00151         {
    00152                 ilSetError(IL_ILLEGAL_OPERATION);
    00153                 return IL_FALSE;
    00154         }
    00155
    00156         iread(Header.Head, 4, 1);
    00157         Header.Size = GetBigInt();
    00158
    00159         if (strncmp(Header.Head, "icns", 4))  // First 4 bytes have to be 'icns'.
    00160                 return IL_FALSE;
    00161
    00162         while ((ILint)itell() < Header.Size && !ieof())
    00163         {
    00164                 iread(Entry.ID, 4, 1);
    00165                 Entry.Size = GetBigInt();
    00166
    00167                 if (!strncmp(Entry.ID, "it32", 4))  // 128x128 24-bit
    00168                 {
    00169                         if (iIcnsReadData(&BaseCreated, IL_FALSE, 128, &Entry, &Image) == IL_FALSE)
    00170                                 goto icns_error;
    00171                 }
    00172                 else if (!strncmp(Entry.ID, "t8mk", 4))  // 128x128 alpha mask
    00173                 {
    00174                         if (iIcnsReadData(&BaseCreated, IL_TRUE, 128, &Entry, &Image) == IL_FALSE)
    00175                                 goto icns_error;
    00176                 }
    00177                 else if (!strncmp(Entry.ID, "ih32", 4))  // 48x48 24-bit
    00178                 {
    00179                         if (iIcnsReadData(&BaseCreated, IL_FALSE, 48, &Entry, &Image) == IL_FALSE)
    00180                                 goto icns_error;
    00181                 }
    00182                 else if (!strncmp(Entry.ID, "h8mk", 4))  // 48x48 alpha mask
    00183                 {
    00184                         if (iIcnsReadData(&BaseCreated, IL_TRUE, 48, &Entry, &Image) == IL_FALSE)
    00185                                 goto icns_error;
    00186                 }
    00187                 else if (!strncmp(Entry.ID, "il32", 4))  // 32x32 24-bit
    00188                 {
    00189                         if (iIcnsReadData(&BaseCreated, IL_FALSE, 32, &Entry, &Image) == IL_FALSE)
    00190                                 goto icns_error;
    00191                 }
    00192                 else if (!strncmp(Entry.ID, "l8mk", 4))  // 32x32 alpha mask
    00193                 {
    00194                         if (iIcnsReadData(&BaseCreated, IL_TRUE, 32, &Entry, &Image) == IL_FALSE)
    00195                                 goto icns_error;
    00196                 }
    00197                 else if (!strncmp(Entry.ID, "is32", 4))  // 16x16 24-bit
    00198                 {
    00199                         if (iIcnsReadData(&BaseCreated, IL_FALSE, 16, &Entry, &Image) == IL_FALSE)
    00200                                 goto icns_error;
    00201                 }
    00202                 else if (!strncmp(Entry.ID, "s8mk", 4))  // 16x16 alpha mask
    00203                 {
    00204                         if (iIcnsReadData(&BaseCreated, IL_TRUE, 16, &Entry, &Image) == IL_FALSE)
    00205                                 goto icns_error;
    00206                 }
    00207 #ifndef IL_NO_JP2
    00208                 else if (!strncmp(Entry.ID, "ic09", 4))  // 512x512 JPEG2000 encoded - Uses JasPer
    00209                 {
    00210                         if (iIcnsReadData(&BaseCreated, IL_FALSE, 512, &Entry, &Image) == IL_FALSE)
    00211                                 goto icns_error;
    00212                 }
    00213                 else if (!strncmp(Entry.ID, "ic08", 4))  // 256x256 JPEG2000 encoded - Uses JasPer
    00214                 {
    00215                         if (iIcnsReadData(&BaseCreated, IL_FALSE, 256, &Entry, &Image) == IL_FALSE)
    00216                                 goto icns_error;
    00217                 }
    00218 #endif//IL_NO_JP2
    00219                 else  // Not a valid format or one that we can use
    00220                 {
    00221                         iseek(Entry.Size - 8, IL_SEEK_CUR);
    00222                 }
    00223         }
    00224
    00225         ilFixImage();
    00226
    00227         return IL_TRUE;
    00228
    00229 icns_error:
    00230         return IL_FALSE;
    00231 }
    00232
    00233 ILboolean iIcnsReadData(ILboolean *BaseCreated, ILboolean IsAlpha, ILint Width, ICNSDATA *Entry, ILimage **Image)
    00234 {
    00235         ILint           Position = 0, RLEPos = 0, Channel, i;
    00236         ILubyte         RLERead, *Data = NULL;
    00237         ILimage         *TempImage = NULL;
    00238         ILboolean       ImageAlreadyExists = IL_FALSE;
    00239
    00240         // The .icns format stores the alpha and RGB as two separate images, so this
    00241         //  checks to see if one exists for that particular size.  Unfortunately,
    00242         //      there is no guarantee that they are in any particular order.
    00243         if (*BaseCreated && iCurImage != NULL)
    00244         {
    00245                 TempImage = iCurImage;
    00246                 while (TempImage != NULL)
    00247                 {
    00248                         if ((ILuint)Width == TempImage->Width)
    00249                         {
    00250                                 ImageAlreadyExists = IL_TRUE;
    00251                                 break;
    00252                         }
    00253                         TempImage = TempImage->Next;
    00254                 }
    00255         }
    00256
    00257         Data = ialloc(Entry->Size - 8);
    00258         if (Data == NULL)
    00259                 return IL_FALSE;
    00260
    00261         if (!ImageAlreadyExists)
    00262         {
    00263                 if (!*BaseCreated)  // Create base image
    00264                 {
    00265                         ilTexImage(Width, Width, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL);
    00266                         iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
    00267                         *Image = iCurImage;
    00268                         *BaseCreated = IL_TRUE;
    00269                 }
    00270                 else  // Create next image in list
    00271                 {
    00272                         (*Image)->Next = ilNewImage(Width, Width, 1, 4, 1);
    00273                         *Image = (*Image)->Next;
    00274                         (*Image)->Format = IL_RGBA;
    00275                         (*Image)->Origin = IL_ORIGIN_UPPER_LEFT;
    00276                 }
    00277
    00278                 TempImage = *Image;
    00279         }
    00280
    00281         if (IsAlpha)  // Alpha is never compressed.
    00282         {
    00283                 iread(Data, Entry->Size - 8, 1);  // Size includes the header
    00284                 if (Entry->Size - 8 != Width * Width)
    00285                 {
    00286                         ifree(Data);
    00287                         return IL_FALSE;
    00288                 }
    00289
    00290                 for (i = 0; i < Width * Width; i++)
    00291                 {
    00292                         TempImage->Data[(i * 4) + 3] = Data[i];
    00293                 }
    00294         }
    00295         else if (Width == 256 || Width == 512)  // JPEG2000 encoded - uses JasPer
    00296         {
    00297 #ifndef IL_NO_JP2
    00298                 iread(Data, Entry->Size - 8, 1);  // Size includes the header
    00299                 if (ilLoadJp2LInternal(Data, Entry->Size - 8, TempImage) == IL_FALSE)
    00300                 {
    00301                         ifree(Data);
    00302                         ilSetError(IL_LIB_JP2_ERROR);
    00303                         return IL_TRUE;
    00304                 }
    00305 #else  // Cannot handle this size.
    00306                 ilSetError(IL_LIB_JP2_ERROR);  //@TODO: Handle this better...just skip the data.
    00307                 return IL_FALSE;
    00308 #endif//IL_NO_JP2
    00309         }
    00310         else  // RGB data
    00311         {
    00312                 iread(Data, Entry->Size - 8, 1);  // Size includes the header
    00313                 if (Width == 128)
    00314                         RLEPos += 4;  // There are an extra 4 bytes here of zeros.
    00315                 //@TODO: Should we check to make sure they are all 0?
    00316
    00317                 if (Entry->Size - 8 == Width * Width * 4) // Uncompressed
    00318                 {
    00319                         //memcpy(TempImage->Data, Data, Entry->Size);
    00320                         for (i = 0; i < Width * Width; i++, Position += 4)
    00321                         {
    00322                                 TempImage->Data[i * 4 + 0] = Data[Position+1];
    00323                                 TempImage->Data[i * 4 + 1] = Data[Position+2];
    00324                                 TempImage->Data[i * 4 + 2] = Data[Position+3];
    00325                         }
    00326                 }
    00327                 else  // RLE decoding
    00328                 {
    00329                         for (Channel = 0; Channel < 3; Channel++)
    00330                         {
    00331                                 Position = 0;
    00332                                 while (Position < Width * Width)
    00333                                 {
    00334                                         RLERead = Data[RLEPos];
    00335                                         RLEPos++;
    00336
    00337                                         if (RLERead >= 128)
    00338                                         {
    00339                                                 for (i = 0; i < RLERead - 125 && (Position + i) < Width * Width; i++)
    00340                                                 {
    00341                                                         TempImage->Data[Channel + (Position + i) * 4] = Data[RLEPos];
    00342                                                 }
    00343                                                 RLEPos++;
    00344                                                 Position += RLERead - 125;
    00345                                         }
    00346                                         else
    00347                                         {
    00348                                                 for (i = 0; i < RLERead + 1 && (Position + i) < Width * Width; i++)
    00349                                                 {
    00350                                                         TempImage->Data[Channel + (Position + i) * 4] = Data[RLEPos + i];
    00351                                                 }
    00352                                                 RLEPos += RLERead + 1;
    00353                                                 Position += RLERead + 1;
    00354                                         }
    00355                                 }
    00356                         }
    00357                 }
    00358         }
    00359
    00360         ifree(Data);
    00361         return IL_TRUE;
    00362 }
    00363
    00364 #endif//IL_NO_ICNS