- Main Page
- Data Structures
- Files

- File List

# E:/DevIL/src-IL/src/il_icon.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_icon.c
    00008 //
    00009 // Description: Reads from a Windows icon (.ico) file.
    00010 //
    00011 //-----------------------------------------------------------------------------
    00012
    00013
    00014 #include "il_internal.h"
    00015 #ifndef IL_NO_ICO
    00016 #include "il_icon.h"
    00017 #ifndef IL_NO_PNG
    00018         #include <png.h>
    00019 #endif
    00020
    00022 ILboolean ilLoadIcon(ILconst_string FileName)
    00023 {
    00024         ILHANDLE        IconFile;
    00025         ILboolean       bIcon = IL_FALSE;
    00026
    00027         IconFile = iopenr(FileName);
    00028         if (IconFile == NULL) {
    00029                 ilSetError(IL_COULD_NOT_OPEN_FILE);
    00030                 return bIcon;
    00031         }
    00032
    00033         bIcon = ilLoadIconF(IconFile);
    00034         icloser(IconFile);
    00035
    00036         return bIcon;
    00037 }
    00038
    00039
    00041 ILboolean ilLoadIconF(ILHANDLE File)
    00042 {
    00043         ILuint          FirstPos;
    00044         ILboolean       bRet;
    00045
    00046         iSetInputFile(File);
    00047         FirstPos = itell();
    00048         bRet = iLoadIconInternal();
    00049         iseek(FirstPos, IL_SEEK_SET);
    00050
    00051         return bRet;
    00052 }
    00053
    00054
    00056 ILboolean ilLoadIconL(const void *Lump, ILuint Size)
    00057 {
    00058         iSetInputLump(Lump, Size);
    00059         return iLoadIconInternal();
    00060 }
    00061
    00062
    00063 // Internal function used to load the icon.
    00064 ILboolean iLoadIconInternal()
    00065 {
    00066         ICODIR          IconDir;
    00067         ICODIRENTRY     *DirEntries = NULL;
    00068         ICOIMAGE        *IconImages = NULL;
    00069         ILimage         *Image = NULL;
    00070         ILint           i;
    00071         ILuint          Size, PadSize, ANDPadSize, j, k, l, m, x, w, CurAndByte, AndBytes;
    00072         ILboolean       BaseCreated = IL_FALSE;
    00073         ILubyte         PNGTest[3];
    00074
    00075         if (iCurImage == NULL) {
    00076                 ilSetError(IL_ILLEGAL_OPERATION);
    00077                 return IL_FALSE;
    00078         }
    00079
    00080         IconDir.Reserved = GetLittleShort();
    00081         IconDir.Type = GetLittleShort();
    00082         IconDir.Count = GetLittleShort();
    00083
    00084         if (ieof())
    00085                 goto file_read_error;
    00086
    00087         DirEntries = (ICODIRENTRY*)ialloc(sizeof(ICODIRENTRY) * IconDir.Count);
    00088         IconImages = (ICOIMAGE*)ialloc(sizeof(ICOIMAGE) * IconDir.Count);
    00089         if (DirEntries == NULL || IconImages == NULL) {
    00090                 ifree(DirEntries);
    00091                 ifree(IconImages);
    00092                 return IL_FALSE;
    00093         }
    00094
    00095         // Make it easier for file_read_error.
    00096         for (i = 0; i < IconDir.Count; i++)
    00097                 imemclear(&IconImages[i], sizeof(ICOIMAGE));
    00098
    00099         for (i = 0; i < IconDir.Count; ++i) {
    00100                 DirEntries[i].Width = (ILubyte)igetc();
    00101                 DirEntries[i].Height = (ILubyte)igetc();
    00102                 DirEntries[i].NumColours = (ILubyte)igetc();
    00103                 DirEntries[i].Reserved = (ILubyte)igetc();
    00104                 DirEntries[i].Planes = GetLittleShort();
    00105                 DirEntries[i].Bpp = GetLittleShort();
    00106                 DirEntries[i].SizeOfData = GetLittleUInt();
    00107                 DirEntries[i].Offset = GetLittleUInt();
    00108
    00109                 if (ieof())
    00110                         goto file_read_error;
    00111         }
    00112
    00113         for (i = 0; i < IconDir.Count; i++) {
    00114                 iseek(DirEntries[i].Offset, IL_SEEK_SET);
    00115
    00116                 // 08-22-2008: Adding test for compressed PNG data
    00117                 igetc(); // Skip the first character...seems to vary.
    00118                 iread(PNGTest, 3, 1);
    00119                 if (!strnicmp((char*)PNGTest, "PNG", 3))  // Characters 'P', 'N', 'G' for PNG header
    00120                 {
    00121 #ifdef IL_NO_PNG
    00122                         ilSetError(IL_FORMAT_NOT_SUPPORTED);  // Cannot handle these without libpng.
    00123                         goto file_read_error;
    00124 #else
    00125                         iseek(DirEntries[i].Offset, IL_SEEK_SET);
    00126                         if (!iLoadIconPNG(&IconImages[i]))
    00127                                 goto file_read_error;
    00128 #endif
    00129                 }
    00130                 else
    00131                 {
    00132                         // Need to go back the 4 bytes that were just read.
    00133                         iseek(DirEntries[i].Offset, IL_SEEK_SET);
    00134
    00135                         IconImages[i].Head.Size = GetLittleInt();
    00136                         IconImages[i].Head.Width = GetLittleInt();
    00137                         IconImages[i].Head.Height = GetLittleInt();
    00138                         IconImages[i].Head.Planes = GetLittleShort();
    00139                         IconImages[i].Head.BitCount = GetLittleShort();
    00140                         IconImages[i].Head.Compression = GetLittleInt();
    00141                         IconImages[i].Head.SizeImage = GetLittleInt();
    00142                         IconImages[i].Head.XPixPerMeter = GetLittleInt();
    00143                         IconImages[i].Head.YPixPerMeter = GetLittleInt();
    00144                         IconImages[i].Head.ColourUsed = GetLittleInt();
    00145                         IconImages[i].Head.ColourImportant = GetLittleInt();
    00146
    00147                         if (ieof())
    00148                                 goto file_read_error;
    00149
    00150                         if (IconImages[i].Head.BitCount < 8) {
    00151                                 if (IconImages[i].Head.ColourUsed == 0) {
    00152                                         switch (IconImages[i].Head.BitCount)
    00153                                         {
    00154                                                 case 1:
    00155                                                         IconImages[i].Head.ColourUsed = 2;
    00156                                                         break;
    00157                                                 case 4:
    00158                                                         IconImages[i].Head.ColourUsed = 16;
    00159                                                         break;
    00160                                         }
    00161                                 }
    00162                                 IconImages[i].Pal = (ILubyte*)ialloc(IconImages[i].Head.ColourUsed * 4);
    00163                                 if (IconImages[i].Pal == NULL)
    00164                                         goto file_read_error;  // @TODO: Rename the label.
    00165                                 if (iread(IconImages[i].Pal, IconImages[i].Head.ColourUsed * 4, 1) != 1)
    00166                                         goto file_read_error;
    00167                         }
    00168                         else if (IconImages[i].Head.BitCount == 8) {
    00169                                 IconImages[i].Pal = (ILubyte*)ialloc(256 * 4);
    00170                                 if (IconImages[i].Pal == NULL)
    00171                                         goto file_read_error;
    00172                                 if (iread(IconImages[i].Pal, 1, 256 * 4) != 256*4)
    00173                                         goto file_read_error;
    00174                         }
    00175                         else {
    00176                                 IconImages[i].Pal = NULL;
    00177                         }
    00178
    00179                         PadSize = (4 - ((IconImages[i].Head.Width*IconImages[i].Head.BitCount + 7) / 8) % 4) % 4;  // Has to be DWORD-aligned.
    00180                         ANDPadSize = (4 - ((IconImages[i].Head.Width + 7) / 8) % 4) % 4;  // AND is 1 bit/pixel
    00181                         Size = ((IconImages[i].Head.Width*IconImages[i].Head.BitCount + 7) / 8 + PadSize)
    00182                                                                 * (IconImages[i].Head.Height / 2);
    00183
    00184
    00185                         IconImages[i].Data = (ILubyte*)ialloc(Size);
    00186                         if (IconImages[i].Data == NULL)
    00187                                 goto file_read_error;
    00188                         if (iread(IconImages[i].Data, 1, Size) != Size)
    00189                                 goto file_read_error;
    00190
    00191                         Size = (((IconImages[i].Head.Width + 7) /8) + ANDPadSize) * (IconImages[i].Head.Height / 2);
    00192                         IconImages[i].AND = (ILubyte*)ialloc(Size);
    00193                         if (IconImages[i].AND == NULL)
    00194                                 goto file_read_error;
    00195                         if (iread(IconImages[i].AND, 1, Size) != Size)
    00196                                 goto file_read_error;
    00197                 }
    00198         }
    00199
    00200
    00201         for (i = 0; i < IconDir.Count; i++) {
    00202                 if (IconImages[i].Head.BitCount != 1 && IconImages[i].Head.BitCount != 4 &&
    00203                         IconImages[i].Head.BitCount != 8 && IconImages[i].Head.BitCount != 24 &&
    00204
    00205                         IconImages[i].Head.BitCount != 32)
    00206                         continue;
    00207
    00208                 if (!BaseCreated) {
    00209                         if (IconImages[i].Head.Size == 0)  // PNG compressed icon
    00210                                 ilTexImage(IconImages[i].Head.Width, IconImages[i].Head.Height, 1, 4, IL_BGRA, IL_UNSIGNED_BYTE, NULL);
    00211                         else
    00212                                 ilTexImage(IconImages[i].Head.Width, IconImages[i].Head.Height / 2, 1, 4, IL_BGRA, IL_UNSIGNED_BYTE, NULL);
    00213                         iCurImage->Origin = IL_ORIGIN_LOWER_LEFT;
    00214                         Image = iCurImage;
    00215                         BaseCreated = IL_TRUE;
    00216                 }
    00217                 else {
    00218                         if (IconImages[i].Head.Size == 0)  // PNG compressed icon
    00219                                 Image->Next = ilNewImage(IconImages[i].Head.Width, IconImages[i].Head.Height, 1, 4, 1);
    00220                         else
    00221                                 Image->Next = ilNewImage(IconImages[i].Head.Width, IconImages[i].Head.Height / 2, 1, 4, 1);
    00222                         Image = Image->Next;
    00223                         Image->Format = IL_BGRA;
    00224                 }
    00225                 Image->Type = IL_UNSIGNED_BYTE;
    00226
    00227                 j = 0;  k = 0;  l = 128;  CurAndByte = 0; x = 0;
    00228
    00229                 w = IconImages[i].Head.Width;
    00230                 PadSize = (4 - ((w*IconImages[i].Head.BitCount + 7) / 8) % 4) % 4;  // Has to be DWORD-aligned.
    00231
    00232                 ANDPadSize = (4 - ((w + 7) / 8) % 4) % 4;  // AND is 1 bit/pixel
    00233                 AndBytes = (w + 7) / 8;
    00234
    00235                 if (IconImages[i].Head.BitCount == 1) {
    00236                         for (; j < Image->SizeOfData; k++) {
    00237                                 for (m = 128; m && x < w; m >>= 1) {
    00238                                         Image->Data[j] = IconImages[i].Pal[!!(IconImages[i].Data[k] & m) * 4];
    00239                                         Image->Data[j+1] = IconImages[i].Pal[!!(IconImages[i].Data[k] & m) * 4 + 1];
    00240                                         Image->Data[j+2] = IconImages[i].Pal[!!(IconImages[i].Data[k] & m) * 4 + 2];
    00241                                         Image->Data[j+3] = (IconImages[i].AND[CurAndByte] & l) != 0 ? 0 : 255;
    00242                                         j += 4;
    00243                                         l >>= 1;
    00244
    00245                                         ++x;
    00246                                 }
    00247                                 if (l == 0 || x == w) {
    00248                                         l = 128;
    00249                                         CurAndByte++;
    00250                                         if (x == w) {
    00251                                                 CurAndByte += ANDPadSize;
    00252                                                 k += PadSize;
    00253                                                 x = 0;
    00254                                         }
    00255
    00256                                 }
    00257                         }
    00258                 }
    00259                 else if (IconImages[i].Head.BitCount == 4) {
    00260                         for (; j < Image->SizeOfData; j += 8, k++) {
    00261                                 Image->Data[j] = IconImages[i].Pal[((IconImages[i].Data[k] & 0xF0) >> 4) * 4];
    00262                                 Image->Data[j+1] = IconImages[i].Pal[((IconImages[i].Data[k] & 0xF0) >> 4) * 4 + 1];
    00263                                 Image->Data[j+2] = IconImages[i].Pal[((IconImages[i].Data[k] & 0xF0) >> 4) * 4 + 2];
    00264                                 Image->Data[j+3] = (IconImages[i].AND[CurAndByte] & l) != 0 ? 0 : 255;
    00265                                 l >>= 1;
    00266
    00267                                 ++x;
    00268
    00269                                 if(x < w) {
    00270                                         Image->Data[j+4] = IconImages[i].Pal[(IconImages[i].Data[k] & 0x0F) * 4];
    00271                                         Image->Data[j+5] = IconImages[i].Pal[(IconImages[i].Data[k] & 0x0F) * 4 + 1];
    00272                                         Image->Data[j+6] = IconImages[i].Pal[(IconImages[i].Data[k] & 0x0F) * 4 + 2];
    00273                                         Image->Data[j+7] = (IconImages[i].AND[CurAndByte] & l) != 0 ? 0 : 255;
    00274                                         l >>= 1;
    00275
    00276                                         ++x;
    00277
    00278                                 }
    00279
    00280                                 else
    00281
    00282                                         j -= 4;
    00283
    00284
    00285                                 if (l == 0 || x == w) {
    00286                                         l = 128;
    00287                                         CurAndByte++;
    00288                                         if (x == w) {
    00289                                                 CurAndByte += ANDPadSize;
    00290
    00291                                                 k += PadSize;
    00292                                                 x = 0;
    00293                                         }
    00294                                 }
    00295                         }
    00296                 }
    00297                 else if (IconImages[i].Head.BitCount == 8) {
    00298                         for (; j < Image->SizeOfData; j += 4, k++) {
    00299                                 Image->Data[j] = IconImages[i].Pal[IconImages[i].Data[k] * 4];
    00300                                 Image->Data[j+1] = IconImages[i].Pal[IconImages[i].Data[k] * 4 + 1];
    00301                                 Image->Data[j+2] = IconImages[i].Pal[IconImages[i].Data[k] * 4 + 2];
    00302                                 if (IconImages[i].AND == NULL)  // PNG Palette
    00303                                 {
    00304                                         Image->Data[j+3] = IconImages[i].Pal[IconImages[i].Data[k] * 4 + 3];
    00305                                 }
    00306                                 else
    00307                                 {
    00308                                         Image->Data[j+3] = (IconImages[i].AND[CurAndByte] & l) != 0 ? 0 : 255;
    00309                                 }
    00310                                 l >>= 1;
    00311
    00312                                 ++x;
    00313                                 if (l == 0 || x == w) {
    00314                                         l = 128;
    00315                                         CurAndByte++;
    00316                                         if (x == w) {
    00317                                                 CurAndByte += ANDPadSize;
    00318
    00319                                                 k += PadSize;
    00320                                                 x = 0;
    00321                                         }
    00322                                 }
    00323                         }
    00324                 }
    00325                 else if (IconImages[i].Head.BitCount == 24) {
    00326                         for (; j < Image->SizeOfData; j += 4, k += 3) {
    00327                                 Image->Data[j] = IconImages[i].Data[k];
    00328                                 Image->Data[j+1] = IconImages[i].Data[k+1];
    00329                                 Image->Data[j+2] = IconImages[i].Data[k+2];
    00330                                 Image->Data[j+3] = (IconImages[i].AND[CurAndByte] & l) != 0 ? 0 : 255;
    00331                                 l >>= 1;
    00332
    00333                                 ++x;
    00334                                 if (l == 0 || x == w) {
    00335                                         l = 128;
    00336                                         CurAndByte++;
    00337                                         if (x == w) {
    00338                                                 CurAndByte += ANDPadSize;
    00339
    00340                                                 k += PadSize;
    00341                                                 x = 0;
    00342                                         }
    00343                                 }
    00344                         }
    00345                 }
    00346
    00347                 else if (IconImages[i].Head.BitCount == 32) {
    00348                         for (; j < Image->SizeOfData; j += 4, k += 4) {
    00349                                 Image->Data[j] = IconImages[i].Data[k];
    00350                                 Image->Data[j+1] = IconImages[i].Data[k+1];
    00351                                 Image->Data[j+2] = IconImages[i].Data[k+2];
    00352
    00353                                 //If the icon has 4 channels, use 4th channel for alpha...
    00354                                 //(for Windows XP style icons with true alpha channel
    00355                                 Image->Data[j+3] = IconImages[i].Data[k+3];
    00356                         }
    00357                 }
    00358         }
    00359
    00360
    00361         for (i = 0; i < IconDir.Count; i++) {
    00362                 ifree(IconImages[i].Pal);
    00363                 ifree(IconImages[i].Data);
    00364                 ifree(IconImages[i].AND);
    00365         }
    00366         ifree(IconImages);
    00367         ifree(DirEntries);
    00368
    00369         ilFixImage();
    00370
    00371         return IL_TRUE;
    00372
    00373 file_read_error:
    00374         if (IconImages) {
    00375                 for (i = 0; i < IconDir.Count; i++) {
    00376                         if (IconImages[i].Pal)
    00377                                 ifree(IconImages[i].Pal);
    00378                         if (IconImages[i].Data)
    00379                                 ifree(IconImages[i].Data);
    00380                         if (IconImages[i].AND)
    00381                                 ifree(IconImages[i].AND);
    00382                 }
    00383                 ifree(IconImages);
    00384         }
    00385         if (DirEntries)
    00386                 ifree(DirEntries);
    00387         return IL_FALSE;
    00388 }
    00389
    00390
    00391 #ifndef IL_NO_PNG
    00392 // 08-22-2008: Copying a lot of this over from il_png.c for the moment.
    00393 // @TODO: Make .ico and .png use the same functions.
    00394 png_structp ico_png_ptr = NULL;
    00395 png_infop   ico_info_ptr = NULL;
    00396 ILint           ico_color_type;
    00397
    00398 #define GAMMA_CORRECTION 1.0  // Doesn't seem to be doing anything...
    00399
    00400 ILint ico_readpng_init();
    00401 ILboolean ico_readpng_get_image(ICOIMAGE *Icon, ILdouble display_exponent);
    00402 void ico_readpng_cleanup();
    00403 #endif
    00404
    00405 ILboolean iLoadIconPNG(ICOIMAGE *Icon)
    00406 {
    00407 #ifndef IL_NO_PNG
    00408         ILint init;
    00409         init = ico_readpng_init();
    00410         if (init)
    00411                 return IL_FALSE;
    00412         if (!ico_readpng_get_image(Icon, GAMMA_CORRECTION))
    00413                 return IL_FALSE;
    00414
    00415         ico_readpng_cleanup();
    00416         Icon->Head.Size = 0;    // Easiest way to tell that this is a PNG.
    00417                                                         // In the normal routine, it will not be 0.
    00418
    00419         return IL_TRUE;
    00420 #else
    00421         Icon;
    00422         return IL_FALSE;
    00423 #endif
    00424 }
    00425
    00426 #ifndef IL_NO_PNG
    00427 static void ico_png_read(png_structp png_ptr, png_bytep data, png_size_t length)
    00428 {
    00429         (void)png_ptr;
    00430         iread(data, 1, (ILuint)length);
    00431         return;
    00432 }
    00433
    00434
    00435 static void ico_png_error_func(png_structp png_ptr, png_const_charp message)
    00436 {
    00437         message;
    00438         ilSetError(IL_LIB_PNG_ERROR);
    00439
    00440         /*
    00441           changed 20040224
    00442           From the libpng docs:
    00443           "Errors handled through png_error() are fatal, meaning that png_error()
    00444            should never return to its caller. Currently, this is handled via
    00445            setjmp() and longjmp()"
    00446         */
    00447         //return;
    00448         longjmp(png_jmpbuf(png_ptr), 1);
    00449 }
    00450
    00451 static void ico_png_warn_func(png_structp png_ptr, png_const_charp message)
    00452 {
    00453         png_ptr; message;
    00454         return;
    00455 }
    00456
    00457
    00458 ILint ico_readpng_init()
    00459 {
    00460         ico_png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, ico_png_error_func, ico_png_warn_func);
    00461         if (!ico_png_ptr)
    00462                 return 4;       /* out of memory */
    00463
    00464         ico_info_ptr = png_create_info_struct(ico_png_ptr);
    00465         if (!ico_info_ptr) {
    00466                 png_destroy_read_struct(&ico_png_ptr, NULL, NULL);
    00467                 return 4;       /* out of memory */
    00468         }
    00469
    00470
    00471         /* we could create a second info struct here (end_info), but it's only
    00472          * useful if we want to keep pre- and post-IDAT chunk info separated
    00473          * (mainly for PNG-aware image editors and converters) */
    00474
    00475
    00476         /* setjmp() must be called in every function that calls a PNG-reading
    00477          * libpng function */
    00478
    00479         if (setjmp(png_jmpbuf(ico_png_ptr))) {
    00480                 png_destroy_read_struct(&ico_png_ptr, &ico_info_ptr, NULL);
    00481                 return 2;
    00482         }
    00483
    00484
    00485         png_set_read_fn(ico_png_ptr, NULL, ico_png_read);
    00486         png_set_error_fn(ico_png_ptr, NULL, ico_png_error_func, ico_png_warn_func);
    00487
    00488 //      png_set_sig_bytes(ico_png_ptr, 8);      /* we already read the 8 signature bytes */
    00489
    00490         png_read_info(ico_png_ptr, ico_info_ptr);  /* read all PNG info up to image data */
    00491
    00492         /* alternatively, could make separate calls to png_get_image_width(),
    00493          * etc., but want bit_depth and ico_color_type for later [don't care about
    00494          * compression_type and filter_type => NULLs] */
    00495
    00496         /* OK, that's all we need for now; return happy */
    00497
    00498         return 0;
    00499 }
    00500
    00501
    00502 ILboolean ico_readpng_get_image(ICOIMAGE *Icon, ILdouble display_exponent)
    00503 {
    00504         png_bytepp      row_pointers = NULL;
    00505         png_uint_32 width, height; // Changed the type to fix AMD64 bit problems, thanks to Eric Werness
    00506         ILdouble        screen_gamma = 1.0;
    00507         ILuint          i, channels;
    00508         ILenum          format;
    00509         png_colorp      palette;
    00510         ILint           num_palette, j, bit_depth;
    00511 #if _WIN32 || DJGPP
    00512         ILdouble image_gamma;
    00513 #endif
    00514
    00515         display_exponent;
    00516
    00517         /* setjmp() must be called in every function that calls a PNG-reading
    00518          * libpng function */
    00519
    00520         if (setjmp(png_jmpbuf(ico_png_ptr))) {
    00521                 png_destroy_read_struct(&ico_png_ptr, &ico_info_ptr, NULL);
    00522                 return IL_FALSE;
    00523         }
    00524
    00525         png_get_IHDR(ico_png_ptr, ico_info_ptr, (png_uint_32*)&width, (png_uint_32*)&height,
    00526                      &bit_depth, &ico_color_type, NULL, NULL, NULL);
    00527
    00528         // Expand low-bit-depth grayscale images to 8 bits
    00529         if (ico_color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
    00530                 png_set_gray_1_2_4_to_8(ico_png_ptr);
    00531         }
    00532
    00533         // Expand RGB images with transparency to full alpha channels
    00534         //      so the data will be available as RGBA quartets.
    00535         // But don't expand paletted images, since we want alpha palettes!
    00536         if (png_get_valid(ico_png_ptr, ico_info_ptr, PNG_INFO_tRNS) && !(png_get_valid(ico_png_ptr, ico_info_ptr, PNG_INFO_PLTE)))
    00537                 png_set_tRNS_to_alpha(ico_png_ptr);
    00538
    00539         //refresh information (added 20040224)
    00540         png_get_IHDR(ico_png_ptr, ico_info_ptr, (png_uint_32*)&width, (png_uint_32*)&height,
    00541                      &bit_depth, &ico_color_type, NULL, NULL, NULL);
    00542
    00543         if (bit_depth < 8) {    // Expanded earlier for grayscale, now take care of palette and rgb
    00544                 bit_depth = 8;
    00545                 png_set_packing(ico_png_ptr);
    00546         }
    00547
    00548         // Perform gamma correction.
    00549         // @TODO:  Determine if we should call png_set_gamma if image_gamma is 1.0.
    00550 #if _WIN32 || DJGPP
    00551         screen_gamma = 2.2;
    00552         if (png_get_gAMA(ico_png_ptr, ico_info_ptr, &image_gamma))
    00553                 png_set_gamma(ico_png_ptr, screen_gamma, image_gamma);
    00554 #else
    00555         screen_gamma = screen_gamma;
    00556 #endif
    00557
    00558         //fix endianess
    00559 #ifdef __LITTLE_ENDIAN__
    00560         if (bit_depth == 16)
    00561                 png_set_swap(ico_png_ptr);
    00562 #endif
    00563
    00564
    00565         png_read_update_info(ico_png_ptr, ico_info_ptr);
    00566         channels = (ILint)png_get_channels(ico_png_ptr, ico_info_ptr);
    00567         // added 20040224: update ico_color_type so that it has the correct value
    00568         // in iLoadPngInternal (globals rule...)
    00569         ico_color_type = png_get_color_type(ico_png_ptr, ico_info_ptr);
    00570
    00571         // Determine internal format
    00572         switch (ico_color_type)
    00573         {
    00574                 case PNG_COLOR_TYPE_PALETTE:
    00575                         Icon->Head.BitCount = 8;
    00576                         format = IL_COLOUR_INDEX;
    00577                         break;
    00578                 case PNG_COLOR_TYPE_RGB:
    00579                         Icon->Head.BitCount = 24;
    00580                         format = IL_RGB;
    00581                         break;
    00582                 case PNG_COLOR_TYPE_RGB_ALPHA:
    00583                         Icon->Head.BitCount = 32;
    00584                         format = IL_RGBA;
    00585                         break;
    00586                 default:
    00587                         ilSetError(IL_ILLEGAL_FILE_VALUE);
    00588                         png_destroy_read_struct(&ico_png_ptr, &ico_info_ptr, NULL);
    00589                         return IL_FALSE;
    00590         }
    00591
    00592         if (ico_color_type & PNG_COLOR_MASK_COLOR)
    00593                 png_set_bgr(ico_png_ptr);
    00594
    00595         Icon->Head.Width = width;
    00596         Icon->Head.Height = height;
    00597         Icon->Data = ialloc(width * height * Icon->Head.BitCount / 8);
    00598         if (Icon->Data == NULL)
    00599         {
    00600                 png_destroy_read_struct(&ico_png_ptr, &ico_info_ptr, NULL);
    00601                 return IL_FALSE;
    00602         }
    00603
    00604         // Copy Palette
    00605         if (format == IL_COLOUR_INDEX)
    00606         {
    00607                 int chans;
    00608                 png_bytep trans = NULL;
    00609                 int num_trans = -1;
    00610                 if (!png_get_PLTE(ico_png_ptr, ico_info_ptr, &palette, &num_palette)) {
    00611                         ilSetError(IL_ILLEGAL_FILE_VALUE);
    00612                         png_destroy_read_struct(&ico_png_ptr, &ico_info_ptr, NULL);
    00613                         return IL_FALSE;
    00614                 }
    00615
    00616                 chans = 4;
    00617
    00618                 if (png_get_valid(ico_png_ptr, ico_info_ptr, PNG_INFO_tRNS)) {
    00619                         png_get_tRNS(ico_png_ptr, ico_info_ptr, &trans, &num_trans, NULL);
    00620                 }
    00621
    00622 // @TODO: We may need to keep track of the size of the palette.
    00623                 Icon->Pal = (ILubyte*)ialloc(num_palette * chans);
    00624
    00625                 for (j = 0; j < num_palette; ++j) {
    00626                         Icon->Pal[chans*j + 0] = palette[j].blue;
    00627                         Icon->Pal[chans*j + 1] = palette[j].green;
    00628                         Icon->Pal[chans*j + 2] = palette[j].red;
    00629                         if (trans != NULL) {
    00630                                 if (j < num_trans)
    00631                                         Icon->Pal[chans*j + 3] = trans[j];
    00632                                 else
    00633                                         Icon->Pal[chans*j + 3] = 255;
    00634                         }
    00635                 }
    00636
    00637                 Icon->AND = NULL;  // Transparency information is obtained from libpng.
    00638         }
    00639
    00640         //allocate row pointers
    00641         if ((row_pointers = (png_bytepp)ialloc(height * sizeof(png_bytep))) == NULL) {
    00642                 png_destroy_read_struct(&ico_png_ptr, &ico_info_ptr, NULL);
    00643                 return IL_FALSE;
    00644         }
    00645
    00646
    00647         // Set the individual row_pointers to point at the correct offsets
    00648         // Needs to be flipped
    00649         for (i = 0; i < height; i++)
    00650                 row_pointers[height - i - 1] = Icon->Data + i * width * Icon->Head.BitCount / 8;
    00651                 //row_pointers[i] = Icon->Data + i * width * Icon->Head.BitCount / 8;
    00652
    00653
    00654         // Now we can go ahead and just read the whole image
    00655         png_read_image(ico_png_ptr, row_pointers);
    00656
    00657         /* and we're done!      (png_read_end() can be omitted if no processing of
    00658          * post-IDAT text/time/etc. is desired) */
    00659         //png_read_end(ico_png_ptr, NULL);
    00660         ifree(row_pointers);
    00661
    00662         return IL_TRUE;
    00663 }
    00664
    00665
    00666 void ico_readpng_cleanup()
    00667 {
    00668         if (ico_png_ptr && ico_info_ptr) {
    00669                 png_destroy_read_struct(&ico_png_ptr, &ico_info_ptr, NULL);
    00670                 ico_png_ptr = NULL;
    00671                 ico_info_ptr = NULL;
    00672         }
    00673 }
    00674 #endif//IL_NO_PNG
    00675
    00676 #endif//IL_NO_ICO