- Main Page
- Data Structures
- Files

- File List

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

    00001 //-----------------------------------------------------------------------------
    00002 //
    00003 // ImageLib Sources
    00004 // Copyright (C) 2000-2008 by Denton Woods
    00005 // Last modified: 12/14/2008
    00006 //
    00007 // Filename: src-IL/src/il_png.c
    00008 //
    00009 // Description: Portable network graphics file (.png) functions
    00010 //
    00011 // 20040223 XIX : now may spit out pngs with a transparent index, this is mostly a hack
    00012 // but the proper way of doing it would be to change the pal stuff to think in argb rather than rgb
    00013 // which is something of a bigger job.
    00014 //
    00015 //-----------------------------------------------------------------------------
    00016
    00017 // Most of the comments are left in this file from libpng's excellent example.c
    00018
    00019 #include "il_internal.h"
    00020 #ifndef IL_NO_PNG
    00021 #include <png.h>
    00022 #include "il_manip.h"
    00023 #include <stdlib.h>
    00024 #if PNG_LIBPNG_VER < 10200
    00025         #warning DevIL was designed with libpng 1.2.0 or higher in mind.  Consider upgrading at www.libpng.org.
    00026 #endif
    00027
    00028 #if (defined(_WIN32) || defined(_WIN64)) && defined(IL_USE_PRAGMA_LIBS)
    00029         #if defined(_MSC_VER) || defined(__BORLANDC__)
    00030                 #ifndef _DEBUG
    00031                         #pragma comment(lib, "libpng.lib")
    00032                         #pragma comment(lib, "zlib.lib")
    00033                 #else
    00034                         #pragma comment(lib, "libpng-d.lib")
    00035                         #pragma comment(lib, "zlib-d.lib")
    00036                 #endif
    00037         #endif
    00038 #endif
    00039
    00040
    00041 ILboolean       iIsValidPng(void);
    00042 ILboolean       iLoadPngInternal(void);
    00043 ILboolean       iSavePngInternal(void);
    00044
    00045 ILint           readpng_init(void);
    00046 ILboolean       readpng_get_image(ILdouble display_exponent);
    00047 void            readpng_cleanup(void);
    00048
    00049 png_structp png_ptr = NULL;
    00050 png_infop   info_ptr = NULL;
    00051 ILint           png_color_type;
    00052
    00053 #define GAMMA_CORRECTION 1.0  // Doesn't seem to be doing anything...
    00054
    00055
    00056 ILboolean ilIsValidPng(ILconst_string FileName)
    00057 {
    00058         ILHANDLE        PngFile;
    00059         ILboolean       bPng = IL_FALSE;
    00060
    00061         if (!iCheckExtension(FileName, IL_TEXT("png"))) {
    00062                 ilSetError(IL_INVALID_EXTENSION);
    00063                 return bPng;
    00064         }
    00065
    00066         PngFile = iopenr(FileName);
    00067         if (PngFile == NULL) {
    00068                 ilSetError(IL_COULD_NOT_OPEN_FILE);
    00069                 return bPng;
    00070         }
    00071
    00072         bPng = ilIsValidPngF(PngFile);
    00073         icloser(PngFile);
    00074
    00075         return bPng;
    00076 }
    00077
    00078
    00079 ILboolean ilIsValidPngF(ILHANDLE File)
    00080 {
    00081         ILuint          FirstPos;
    00082         ILboolean       bRet;
    00083
    00084         iSetInputFile(File);
    00085         FirstPos = itell();
    00086         bRet = iIsValidPng();
    00087         iseek(FirstPos, IL_SEEK_SET);
    00088
    00089         return bRet;
    00090 }
    00091
    00092
    00093 ILboolean ilIsValidPngL(const void *Lump, ILuint Size)
    00094 {
    00095         iSetInputLump(Lump, Size);
    00096         return iIsValidPng();
    00097 }
    00098
    00099
    00100 ILboolean iIsValidPng()
    00101 {
    00102         ILubyte         Signature[8];
    00103         ILint           Read;
    00104
    00105         Read = iread(Signature, 1, 8);
    00106         iseek(-Read, IL_SEEK_CUR);
    00107
    00108         return png_check_sig(Signature, 8);
    00109 }
    00110
    00111
    00112 // Reads a file
    00113 ILboolean ilLoadPng(ILconst_string FileName)
    00114 {
    00115         ILHANDLE        PngFile;
    00116         ILboolean       bPng = IL_FALSE;
    00117
    00118         PngFile = iopenr(FileName);
    00119         if (PngFile == NULL) {
    00120                 ilSetError(IL_COULD_NOT_OPEN_FILE);
    00121                 return bPng;
    00122         }
    00123
    00124         bPng = ilLoadPngF(PngFile);
    00125         icloser(PngFile);
    00126
    00127         return bPng;
    00128 }
    00129
    00130
    00131 // Reads an already-opened file
    00132 ILboolean ilLoadPngF(ILHANDLE File)
    00133 {
    00134         ILuint          FirstPos;
    00135         ILboolean       bRet;
    00136
    00137         iSetInputFile(File);
    00138         FirstPos = itell();
    00139         bRet = iLoadPngInternal();
    00140         iseek(FirstPos, IL_SEEK_SET);
    00141
    00142         return bRet;
    00143 }
    00144
    00145
    00146 // Reads from a memory "lump"
    00147 ILboolean ilLoadPngL(const void *Lump, ILuint Size)
    00148 {
    00149         iSetInputLump(Lump, Size);
    00150         return iLoadPngInternal();
    00151 }
    00152
    00153
    00154 ILboolean iLoadPngInternal()
    00155 {
    00156         png_ptr = NULL;
    00157         info_ptr = NULL;
    00158
    00159         if (iCurImage == NULL) {
    00160                 ilSetError(IL_ILLEGAL_OPERATION);
    00161                 return IL_FALSE;
    00162         }
    00163         if (!iIsValidPng()) {
    00164                 ilSetError(IL_INVALID_VALUE);
    00165                 return IL_FALSE;
    00166         }
    00167
    00168         if (readpng_init())
    00169                 return IL_FALSE;
    00170         if (!readpng_get_image(GAMMA_CORRECTION))
    00171                 return IL_FALSE;
    00172
    00173         readpng_cleanup();
    00174
    00175         ilFixImage();
    00176
    00177         return IL_TRUE;
    00178 }
    00179
    00180
    00181 static void png_read(png_structp png_ptr, png_bytep data, png_size_t length)
    00182 {
    00183         (void)png_ptr;
    00184         iread(data, 1, (ILuint)length);
    00185         return;
    00186 }
    00187
    00188
    00189 static void png_error_func(png_structp png_ptr, png_const_charp message)
    00190 {
    00191         ilSetError(IL_LIB_PNG_ERROR);
    00192
    00193         /*
    00194           changed 20040224
    00195           From the libpng docs:
    00196           "Errors handled through png_error() are fatal, meaning that png_error()
    00197            should never return to its caller. Currently, this is handled via
    00198            setjmp() and longjmp()"
    00199         */
    00200         //return;
    00201         longjmp(png_jmpbuf(png_ptr), 1);
    00202 }
    00203
    00204 static void png_warn_func(png_structp png_ptr, png_const_charp message)
    00205 {
    00206         return;
    00207 }
    00208
    00209
    00210 ILint readpng_init()
    00211 {
    00212         png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, png_error_func, png_warn_func);
    00213         if (!png_ptr)
    00214                 return 4;       /* out of memory */
    00215
    00216         info_ptr = png_create_info_struct(png_ptr);
    00217         if (!info_ptr) {
    00218                 png_destroy_read_struct(&png_ptr, NULL, NULL);
    00219                 return 4;       /* out of memory */
    00220         }
    00221
    00222
    00223         /* we could create a second info struct here (end_info), but it's only
    00224          * useful if we want to keep pre- and post-IDAT chunk info separated
    00225          * (mainly for PNG-aware image editors and converters) */
    00226
    00227
    00228         /* setjmp() must be called in every function that calls a PNG-reading
    00229          * libpng function */
    00230
    00231         if (setjmp(png_jmpbuf(png_ptr))) {
    00232                 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    00233                 return 2;
    00234         }
    00235
    00236
    00237         png_set_read_fn(png_ptr, NULL, png_read);
    00238         png_set_error_fn(png_ptr, NULL, png_error_func, png_warn_func);
    00239
    00240 //      png_set_sig_bytes(png_ptr, 8);  /* we already read the 8 signature bytes */
    00241
    00242         png_read_info(png_ptr, info_ptr);  /* read all PNG info up to image data */
    00243
    00244
    00245         /* alternatively, could make separate calls to png_get_image_width(),
    00246          * etc., but want bit_depth and png_color_type for later [don't care about
    00247          * compression_type and filter_type => NULLs] */
    00248
    00249         /* OK, that's all we need for now; return happy */
    00250
    00251         return 0;
    00252 }
    00253
    00254
    00255 /* display_exponent == LUT_exponent * CRT_exponent */
    00256
    00257 ILboolean readpng_get_image(ILdouble display_exponent)
    00258 {
    00259         png_bytepp      row_pointers = NULL;
    00260         png_uint_32 width, height; // Changed the type to fix AMD64 bit problems, thanks to Eric Werness
    00261         ILdouble        screen_gamma = 1.0;
    00262         ILuint          i, channels;
    00263         ILenum          format;
    00264         png_colorp      palette;
    00265         ILint           num_palette, j, bit_depth;
    00266 #if _WIN32 || DJGPP
    00267         ILdouble image_gamma;
    00268 #endif
    00269
    00270         /* setjmp() must be called in every function that calls a PNG-reading
    00271          * libpng function */
    00272
    00273         if (setjmp(png_jmpbuf(png_ptr))) {
    00274                 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    00275                 return IL_FALSE;
    00276         }
    00277
    00278         png_get_IHDR(png_ptr, info_ptr, (png_uint_32*)&width, (png_uint_32*)&height,
    00279                      &bit_depth, &png_color_type, NULL, NULL, NULL);
    00280
    00281         // Expand low-bit-depth grayscale images to 8 bits
    00282         if (png_color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
    00283                 png_set_gray_1_2_4_to_8(png_ptr);
    00284         }
    00285
    00286         // Expand RGB images with transparency to full alpha channels
    00287         //      so the data will be available as RGBA quartets.
    00288         // But don't expand paletted images, since we want alpha palettes!
    00289         if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) && !(png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE)))
    00290                 png_set_tRNS_to_alpha(png_ptr);
    00291
    00292         //refresh information (added 20040224)
    00293         png_get_IHDR(png_ptr, info_ptr, (png_uint_32*)&width, (png_uint_32*)&height,
    00294                      &bit_depth, &png_color_type, NULL, NULL, NULL);
    00295
    00296         if (bit_depth < 8) {    // Expanded earlier for grayscale, now take care of palette and rgb
    00297                 bit_depth = 8;
    00298                 png_set_packing(png_ptr);
    00299         }
    00300
    00301         // Perform gamma correction.
    00302         // @TODO:  Determine if we should call png_set_gamma if image_gamma is 1.0.
    00303 #if _WIN32 || DJGPP
    00304         screen_gamma = 2.2;
    00305         if (png_get_gAMA(png_ptr, info_ptr, &image_gamma))
    00306                 png_set_gamma(png_ptr, screen_gamma, image_gamma);
    00307 #else
    00308         screen_gamma = screen_gamma;
    00309 #endif
    00310
    00311         //fix endianess
    00312 #ifdef __LITTLE_ENDIAN__
    00313         if (bit_depth == 16)
    00314                 png_set_swap(png_ptr);
    00315 #endif
    00316
    00317
    00318         png_read_update_info(png_ptr, info_ptr);
    00319         channels = (ILint)png_get_channels(png_ptr, info_ptr);
    00320         //added 20040224: update png_color_type so that it has the correct value
    00321         //in iLoadPngInternal (globals rule...)
    00322         png_color_type = png_get_color_type(png_ptr, info_ptr);
    00323
    00324         //determine internal format
    00325         switch(png_color_type)
    00326         {
    00327                 case PNG_COLOR_TYPE_PALETTE:
    00328                         format = IL_COLOUR_INDEX;
    00329                         break;
    00330                 case PNG_COLOR_TYPE_GRAY:
    00331                         format = IL_LUMINANCE;
    00332                         break;
    00333                 case PNG_COLOR_TYPE_GRAY_ALPHA:
    00334                         format = IL_LUMINANCE_ALPHA;
    00335                         break;
    00336                 case PNG_COLOR_TYPE_RGB:
    00337                         format = IL_RGB;
    00338                         break;
    00339                 case PNG_COLOR_TYPE_RGB_ALPHA:
    00340                         format = IL_RGBA;
    00341                         break;
    00342                 default:
    00343                         ilSetError(IL_ILLEGAL_FILE_VALUE);
    00344                         png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    00345                         return IL_FALSE;
    00346         }
    00347
    00348         if (!ilTexImage(width, height, 1, (ILubyte)channels, format, ilGetTypeBpc((ILubyte)(bit_depth >> 3)), NULL)) {
    00349                 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    00350                 return IL_FALSE;
    00351         }
    00352         iCurImage->Origin = IL_ORIGIN_UPPER_LEFT;
    00353
    00354         //copy palette
    00355         if (format == IL_COLOUR_INDEX) {
    00356                 int chans;
    00357                 png_bytep trans = NULL;
    00358                 int  num_trans = -1;
    00359                 if (!png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)) {
    00360                         ilSetError(IL_ILLEGAL_FILE_VALUE);
    00361                         png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    00362                         return IL_FALSE;
    00363                 }
    00364
    00365                 chans = 3;
    00366                 iCurImage->Pal.PalType = IL_PAL_RGB24;
    00367
    00368                 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
    00369                         png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL);
    00370                         iCurImage->Pal.PalType = IL_PAL_RGBA32;
    00371                         chans = 4;
    00372                 }
    00373
    00374                 iCurImage->Pal.PalSize = num_palette * chans;
    00375
    00376                 iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize);
    00377
    00378                 for (j = 0; j < num_palette; ++j) {
    00379                         iCurImage->Pal.Palette[chans*j + 0] = palette[j].red;
    00380                         iCurImage->Pal.Palette[chans*j + 1] = palette[j].green;
    00381                         iCurImage->Pal.Palette[chans*j + 2] = palette[j].blue;
    00382                         if (trans!=NULL) {
    00383                                 if (j<num_trans)
    00384                                         iCurImage->Pal.Palette[chans*j + 3] = trans[j];
    00385                                 else
    00386                                         iCurImage->Pal.Palette[chans*j + 3] = 255;
    00387                         }
    00388                 }
    00389         }
    00390
    00391         //allocate row pointers
    00392         if ((row_pointers = (png_bytepp)ialloc(height * sizeof(png_bytep))) == NULL) {
    00393                 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    00394                 return IL_FALSE;
    00395         }
    00396
    00397
    00398         // Set the individual row_pointers to point at the correct offsets */
    00399         for (i = 0; i < height; i++)
    00400                 row_pointers[i] = iCurImage->Data + i * iCurImage->Bps;
    00401
    00402
    00403         // Now we can go ahead and just read the whole image
    00404         png_read_image(png_ptr, row_pointers);
    00405
    00406
    00407         /* and we're done!      (png_read_end() can be omitted if no processing of
    00408          * post-IDAT text/time/etc. is desired) */
    00409         //png_read_end(png_ptr, NULL);
    00410         ifree(row_pointers);
    00411
    00412         return IL_TRUE;
    00413 }
    00414
    00415
    00416 void readpng_cleanup()
    00417 {
    00418         if (png_ptr && info_ptr) {
    00419                 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    00420                 png_ptr = NULL;
    00421                 info_ptr = NULL;
    00422         }
    00423 }
    00424
    00425
    00427 ILboolean ilSavePng(const ILstring FileName)
    00428 {
    00429         ILHANDLE        PngFile;
    00430         ILuint          PngSize;
    00431
    00432         if (ilGetBoolean(IL_FILE_MODE) == IL_FALSE) {
    00433                 if (iFileExists(FileName)) {
    00434                         ilSetError(IL_FILE_ALREADY_EXISTS);
    00435                         return IL_FALSE;
    00436                 }
    00437         }
    00438
    00439         PngFile = iopenw(FileName);
    00440         if (PngFile == NULL) {
    00441                 ilSetError(IL_COULD_NOT_OPEN_FILE);
    00442                 return IL_FALSE;
    00443         }
    00444
    00445         PngSize = ilSavePngF(PngFile);
    00446         iclosew(PngFile);
    00447
    00448         if (PngSize == 0)
    00449                 return IL_FALSE;
    00450         return IL_TRUE;
    00451 }
    00452
    00453
    00455 ILuint ilSavePngF(ILHANDLE File)
    00456 {
    00457         ILuint Pos;
    00458         iSetOutputFile(File);
    00459         Pos = itellw();
    00460         if (iSavePngInternal() == IL_FALSE)
    00461                 return 0;  // Error occurred
    00462         return itellw() - Pos;  // Return the number of bytes written.
    00463 }
    00464
    00465
    00467 ILuint ilSavePngL(void *Lump, ILuint Size)
    00468 {
    00469         ILuint Pos = itellw();
    00470         iSetOutputLump(Lump, Size);
    00471         if (iSavePngInternal() == IL_FALSE)
    00472                 return 0;  // Error occurred
    00473         return itellw() - Pos;  // Return the number of bytes written.
    00474 }
    00475
    00476
    00477 void png_write(png_structp png_ptr, png_bytep data, png_size_t length)
    00478 {
    00479         (void)png_ptr;
    00480         iwrite(data, 1, (ILuint)length);
    00481         return;
    00482 }
    00483
    00484 void flush_data(png_structp png_ptr)
    00485 {
    00486         return;
    00487 }
    00488
    00489
    00490 // Internal function used to save the Png.
    00491 ILboolean iSavePngInternal()
    00492 {
    00493         png_structp png_ptr;
    00494         png_infop       info_ptr;
    00495         png_text        text[4];
    00496         ILenum          PngType;
    00497         ILuint          BitDepth, i, j;
    00498         ILubyte         **RowPtr = NULL;
    00499         ILimage         *Temp = NULL;
    00500         ILpal           *TempPal = NULL;
    00501
    00502 //XIX alpha
    00503         ILubyte         transpart[1];
    00504         ILint           trans;
    00505
    00506         if (iCurImage == NULL) {
    00507                 ilSetError(IL_ILLEGAL_OPERATION);
    00508                 return IL_FALSE;
    00509         }
    00510
    00511         /* Create and initialize the png_struct with the desired error handler
    00512         * functions.  If you want to use the default stderr and longjump method,
    00513         * you can supply NULL for the last three parameters.  We also check that
    00514         * the library version is compatible with the one used at compile time,
    00515         * in case we are using dynamically linked libraries.  REQUIRED.
    00516         */
    00517         png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, png_error_func, png_warn_func);
    00518         if (png_ptr == NULL) {
    00519                 ilSetError(IL_LIB_PNG_ERROR);
    00520                 return IL_FALSE;
    00521         }
    00522
    00523         // Allocate/initialize the image information data.      REQUIRED
    00524         info_ptr = png_create_info_struct(png_ptr);
    00525         if (info_ptr == NULL) {
    00526                 ilSetError(IL_LIB_PNG_ERROR);
    00527                 goto error_label;
    00528         }
    00529
    00530         /*// Set error handling.  REQUIRED if you aren't supplying your own
    00531         //      error handling functions in the png_create_write_struct() call.
    00532         if (setjmp(png_jmpbuf(png_ptr))) {
    00533                 // If we get here, we had a problem reading the file
    00534                 png_destroy_write_struct(&png_ptr, &info_ptr);
    00535                 ilSetError(IL_LIB_PNG_ERROR);
    00536                 return IL_FALSE;
    00537         }*/
    00538
    00539 //      png_init_io(png_ptr, PngFile);
    00540         png_set_write_fn(png_ptr, NULL, png_write, flush_data);
    00541
    00542         switch (iCurImage->Type)
    00543         {
    00544                 case IL_BYTE:
    00545                 case IL_UNSIGNED_BYTE:
    00546                         Temp = iCurImage;
    00547                         BitDepth = 8;
    00548                         break;
    00549                 case IL_SHORT:
    00550                 case IL_UNSIGNED_SHORT:
    00551                         Temp = iCurImage;
    00552                         BitDepth = 16;
    00553                         break;
    00554                 case IL_INT:
    00555                 case IL_UNSIGNED_INT:
    00556                         Temp = iConvertImage(iCurImage, iCurImage->Format, IL_UNSIGNED_SHORT);
    00557                         if (Temp == NULL) {
    00558                                 png_destroy_write_struct(&png_ptr, &info_ptr);
    00559                                 return IL_FALSE;
    00560                         }
    00561                         BitDepth = 16;
    00562                         break;
    00563                 default:
    00564                         ilSetError(IL_INTERNAL_ERROR);
    00565                         goto error_label;
    00566         }
    00567
    00568         switch (iCurImage->Format)
    00569         {
    00570                 case IL_COLOUR_INDEX:
    00571                         PngType = PNG_COLOR_TYPE_PALETTE;
    00572                         break;
    00573                 case IL_LUMINANCE:
    00574                         PngType = PNG_COLOR_TYPE_GRAY;
    00575                         break;
    00576                 case IL_LUMINANCE_ALPHA: //added 20050328
    00577                         PngType = PNG_COLOR_TYPE_GRAY_ALPHA;
    00578                         break;
    00579                 case IL_RGB:
    00580                 case IL_BGR:
    00581                         PngType = PNG_COLOR_TYPE_RGB;
    00582                         break;
    00583                 case IL_RGBA:
    00584                 case IL_BGRA:
    00585                         PngType = PNG_COLOR_TYPE_RGB_ALPHA;
    00586                         break;
    00587                 default:
    00588                         ilSetError(IL_INTERNAL_ERROR);
    00589                         goto error_label;
    00590         }
    00591
    00592         // Set the image information here.      Width and height are up to 2^31,
    00593         //      bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
    00594         //      the png_color_type selected. png_color_type is one of PNG_COLOR_TYPE_GRAY,
    00595         //      PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
    00596         //      or PNG_COLOR_TYPE_RGB_ALPHA.  interlace is either PNG_INTERLACE_NONE or
    00597         //      PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
    00598         //      currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
    00599         if (iGetInt(IL_PNG_INTERLACE) == IL_TRUE) {
    00600                 png_set_IHDR(png_ptr, info_ptr, iCurImage->Width, iCurImage->Height, BitDepth, PngType,
    00601                         PNG_INTERLACE_ADAM7, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
    00602         }
    00603         else {
    00604                 png_set_IHDR(png_ptr, info_ptr, iCurImage->Width, iCurImage->Height, BitDepth, PngType,
    00605                         PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
    00606         }
    00607
    00608         if (iCurImage->Format == IL_COLOUR_INDEX) {
    00609                 // set the palette if there is one.  REQUIRED for indexed-color images.
    00610                 TempPal = iConvertPal(&iCurImage->Pal, IL_PAL_RGB24);
    00611                 png_set_PLTE(png_ptr, info_ptr, (png_colorp)TempPal->Palette,
    00612                         ilGetInteger(IL_PALETTE_NUM_COLS));
    00613
    00614 //XIX alpha
    00615                 trans=iGetInt(IL_PNG_ALPHA_INDEX);
    00616                 if ( trans>=0)
    00617                 {
    00618                         transpart[0]=(ILubyte)trans;
    00619                         png_set_tRNS(png_ptr, info_ptr, transpart, 1, 0);
    00620                 }
    00621         }
    00622
    00623         /*
    00624         // optional significant bit chunk
    00625         // if we are dealing with a grayscale image then
    00626         sig_bit.gray = true_bit_depth;
    00627         // otherwise, if we are dealing with a color image then
    00628         sig_bit.red = true_red_bit_depth;
    00629         sig_bit.green = true_green_bit_depth;
    00630         sig_bit.blue = true_blue_bit_depth;
    00631         // if the image has an alpha channel then
    00632         sig_bit.alpha = true_alpha_bit_depth;
    00633         png_set_sBIT(png_ptr, info_ptr, sig_bit);*/
    00634
    00635
    00636         /* Optional gamma chunk is strongly suggested if you have any guess
    00637         * as to the correct gamma of the image.
    00638         */
    00639         //png_set_gAMA(png_ptr, info_ptr, gamma);
    00640
    00641         // Optionally write comments into the image.
    00642         imemclear(text, sizeof(png_text) * 4);
    00643         text[0].key = "Generated by";
    00644         text[0].text = "Generated by the Developer's Image Library (DevIL)";
    00645         text[0].compression = PNG_TEXT_COMPRESSION_NONE;
    00646         text[1].key = "Author";
    00647         text[1].text = (char*)iGetString(IL_PNG_AUTHNAME_STRING);  // Will not actually be modified!
    00648         text[1].compression = PNG_TEXT_COMPRESSION_NONE;
    00649         text[2].key = "Description";
    00650         text[2].text = iGetString(IL_PNG_DESCRIPTION_STRING);
    00651         text[2].compression = PNG_TEXT_COMPRESSION_NONE;
    00652         text[3].key = "Title";
    00653         text[3].text = iGetString(IL_PNG_TITLE_STRING);
    00654         text[3].compression = PNG_TEXT_COMPRESSION_NONE;
    00655         png_set_text(png_ptr, info_ptr, text, 3);
    00656
    00657         // Write the file header information.  REQUIRED.
    00658         png_write_info(png_ptr, info_ptr);
    00659
    00660         // Free up our user-defined text.
    00661         if (text[1].text)
    00662                 ifree(text[1].text);
    00663         if (text[2].text)
    00664                 ifree(text[2].text);
    00665         if (text[3].text)
    00666                 ifree(text[3].text);
    00667
    00668         /* Shift the pixels up to a legal bit depth and fill in
    00669         * as appropriate to correctly scale the image.
    00670         */
    00671         //png_set_shift(png_ptr, &sig_bit);
    00672
    00673         /* pack pixels into bytes */
    00674         //png_set_packing(png_ptr);
    00675
    00676         // swap location of alpha bytes from ARGB to RGBA
    00677         //png_set_swap_alpha(png_ptr);
    00678
    00679         // flip BGR pixels to RGB
    00680         if (iCurImage->Format == IL_BGR || iCurImage->Format == IL_BGRA)
    00681                 png_set_bgr(png_ptr);
    00682
    00683         // swap bytes of 16-bit files to most significant byte first
    00684         #ifdef  __LITTLE_ENDIAN__
    00685         png_set_swap(png_ptr);
    00686         #endif//__LITTLE_ENDIAN__
    00687
    00688         RowPtr = (ILubyte**)ialloc(iCurImage->Height * sizeof(ILubyte*));
    00689         if (RowPtr == NULL)
    00690                 goto error_label;
    00691         if (iCurImage->Origin == IL_ORIGIN_UPPER_LEFT) {
    00692                 for (i = 0; i < iCurImage->Height; i++) {
    00693                         RowPtr[i] = Temp->Data + i * Temp->Bps;
    00694                 }
    00695         }
    00696         else {
    00697                 j = iCurImage->Height - 1;
    00698                 for (i = 0; i < iCurImage->Height; i++, j--) {
    00699                         RowPtr[i] = Temp->Data + j * Temp->Bps;
    00700                 }
    00701         }
    00702
    00703         // Writes the image.
    00704         png_write_image(png_ptr, RowPtr);
    00705
    00706         // It is REQUIRED to call this to finish writing the rest of the file
    00707         png_write_end(png_ptr, info_ptr);
    00708
    00709         // clean up after the write, and ifree any memory allocated
    00710         png_destroy_write_struct(&png_ptr, &info_ptr);
    00711
    00712         ifree(RowPtr);
    00713
    00714         if (Temp != iCurImage)
    00715                 ilCloseImage(Temp);
    00716         ilClosePal(TempPal);
    00717
    00718         return IL_TRUE;
    00719
    00720 error_label:
    00721         png_destroy_write_struct(&png_ptr, &info_ptr);
    00722         ifree(RowPtr);
    00723         if (Temp != iCurImage)
    00724                 ilCloseImage(Temp);
    00725         ilClosePal(TempPal);
    00726         return IL_FALSE;
    00727 }
    00728
    00729
    00730 #endif//IL_NO_PNG