Back to index

lightning-sunbird  0.9+nobinonly
pngrutil.c
Go to the documentation of this file.
00001 /* pngrutil.c - utilities to read a PNG file
00002  *
00003  * libpng version 1.2.7 - September 12, 2004
00004  * For conditions of distribution and use, see copyright notice in png.h
00005  * Copyright (c) 1998-2004 Glenn Randers-Pehrson
00006  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
00007  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
00008  *
00009  * This file contains routines that are only called from within
00010  * libpng itself during the course of reading an image.
00011  */
00012 
00013 #define PNG_INTERNAL
00014 #include "png.h"
00015 
00016 #if defined(_WIN32_WCE)
00017 /* strtod() function is not supported on WindowsCE */
00018 #  ifdef PNG_FLOATING_POINT_SUPPORTED
00019 __inline double strtod(const char *nptr, char **endptr)
00020 {
00021    double result = 0;
00022    int len;
00023    wchar_t *str, *end;
00024 
00025    len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0);
00026    str = (wchar_t *)malloc(len * sizeof(wchar_t));
00027    if ( NULL != str )
00028    {
00029       MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len);
00030       result = wcstod(str, &end);
00031       len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL);
00032       *endptr = (char *)nptr + (png_strlen(nptr) - len + 1);
00033       free(str);
00034    }
00035    return result;
00036 }
00037 #  endif
00038 #endif
00039 
00040 png_uint_32 /* PRIVATE */
00041 png_get_uint_31(png_structp png_ptr, png_bytep buf)
00042 {
00043    png_uint_32 i = png_get_uint_32(buf);
00044    if (i > PNG_UINT_31_MAX)
00045      png_error(png_ptr, "PNG unsigned integer out of range.\n");
00046    return (i);
00047 }
00048 #ifndef PNG_READ_BIG_ENDIAN_SUPPORTED
00049 /* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
00050 png_uint_32 /* PRIVATE */
00051 png_get_uint_32(png_bytep buf)
00052 {
00053    png_uint_32 i = ((png_uint_32)(*buf) << 24) +
00054       ((png_uint_32)(*(buf + 1)) << 16) +
00055       ((png_uint_32)(*(buf + 2)) << 8) +
00056       (png_uint_32)(*(buf + 3));
00057 
00058    return (i);
00059 }
00060 
00061 #if defined(PNG_READ_pCAL_SUPPORTED) || defined(PNG_READ_oFFs_SUPPORTED)
00062 /* Grab a signed 32-bit integer from a buffer in big-endian format.  The
00063  * data is stored in the PNG file in two's complement format, and it is
00064  * assumed that the machine format for signed integers is the same. */
00065 png_int_32 /* PRIVATE */
00066 png_get_int_32(png_bytep buf)
00067 {
00068    png_int_32 i = ((png_int_32)(*buf) << 24) +
00069       ((png_int_32)(*(buf + 1)) << 16) +
00070       ((png_int_32)(*(buf + 2)) << 8) +
00071       (png_int_32)(*(buf + 3));
00072 
00073    return (i);
00074 }
00075 #endif /* PNG_READ_pCAL_SUPPORTED */
00076 
00077 /* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
00078 png_uint_16 /* PRIVATE */
00079 png_get_uint_16(png_bytep buf)
00080 {
00081    png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) +
00082       (png_uint_16)(*(buf + 1)));
00083 
00084    return (i);
00085 }
00086 #endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */
00087 
00088 /* Read data, and (optionally) run it through the CRC. */
00089 void /* PRIVATE */
00090 png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
00091 {
00092    png_read_data(png_ptr, buf, length);
00093    png_calculate_crc(png_ptr, buf, length);
00094 }
00095 
00096 /* Optionally skip data and then check the CRC.  Depending on whether we
00097    are reading a ancillary or critical chunk, and how the program has set
00098    things up, we may calculate the CRC on the data and print a message.
00099    Returns '1' if there was a CRC error, '0' otherwise. */
00100 int /* PRIVATE */
00101 png_crc_finish(png_structp png_ptr, png_uint_32 skip)
00102 {
00103    png_size_t i;
00104    png_size_t istop = png_ptr->zbuf_size;
00105 
00106    for (i = (png_size_t)skip; i > istop; i -= istop)
00107    {
00108       png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
00109    }
00110    if (i)
00111    {
00112       png_crc_read(png_ptr, png_ptr->zbuf, i);
00113    }
00114 
00115    if (png_crc_error(png_ptr))
00116    {
00117       if (((png_ptr->chunk_name[0] & 0x20) &&                /* Ancillary */
00118            !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
00119           (!(png_ptr->chunk_name[0] & 0x20) &&             /* Critical  */
00120           (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)))
00121       {
00122          png_chunk_warning(png_ptr, "CRC error");
00123       }
00124       else
00125       {
00126          png_chunk_error(png_ptr, "CRC error");
00127       }
00128       return (1);
00129    }
00130 
00131    return (0);
00132 }
00133 
00134 /* Compare the CRC stored in the PNG file with that calculated by libpng from
00135    the data it has read thus far. */
00136 int /* PRIVATE */
00137 png_crc_error(png_structp png_ptr)
00138 {
00139    png_byte crc_bytes[4];
00140    png_uint_32 crc;
00141    int need_crc = 1;
00142 
00143    if (png_ptr->chunk_name[0] & 0x20)                     /* ancillary */
00144    {
00145       if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
00146           (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
00147          need_crc = 0;
00148    }
00149    else                                                    /* critical */
00150    {
00151       if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
00152          need_crc = 0;
00153    }
00154 
00155    png_read_data(png_ptr, crc_bytes, 4);
00156 
00157    if (need_crc)
00158    {
00159       crc = png_get_uint_32(crc_bytes);
00160       return ((int)(crc != png_ptr->crc));
00161    }
00162    else
00163       return (0);
00164 }
00165 
00166 #if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \
00167     defined(PNG_READ_iCCP_SUPPORTED)
00168 /*
00169  * Decompress trailing data in a chunk.  The assumption is that chunkdata
00170  * points at an allocated area holding the contents of a chunk with a
00171  * trailing compressed part.  What we get back is an allocated area
00172  * holding the original prefix part and an uncompressed version of the
00173  * trailing part (the malloc area passed in is freed).
00174  */
00175 png_charp /* PRIVATE */
00176 png_decompress_chunk(png_structp png_ptr, int comp_type,
00177                               png_charp chunkdata, png_size_t chunklength,
00178                               png_size_t prefix_size, png_size_t *newlength)
00179 {
00180    static char msg[] = "Error decoding compressed text";
00181    png_charp text;
00182    png_size_t text_size;
00183 
00184    if (comp_type == PNG_COMPRESSION_TYPE_BASE)
00185    {
00186       int ret = Z_OK;
00187       png_ptr->zstream.next_in = (png_bytep)(chunkdata + prefix_size);
00188       png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size);
00189       png_ptr->zstream.next_out = png_ptr->zbuf;
00190       png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
00191 
00192       text_size = 0;
00193       text = NULL;
00194 
00195       while (png_ptr->zstream.avail_in)
00196       {
00197          ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
00198          if (ret != Z_OK && ret != Z_STREAM_END)
00199          {
00200             if (png_ptr->zstream.msg != NULL)
00201                png_warning(png_ptr, png_ptr->zstream.msg);
00202             else
00203                png_warning(png_ptr, msg);
00204             inflateReset(&png_ptr->zstream);
00205             png_ptr->zstream.avail_in = 0;
00206 
00207             if (text ==  NULL)
00208             {
00209                text_size = prefix_size + png_sizeof(msg) + 1;
00210                text = (png_charp)png_malloc_warn(png_ptr, text_size);
00211                if (text ==  NULL)
00212                  {
00213                     png_free(png_ptr,chunkdata);
00214                     png_error(png_ptr,"Not enough memory to decompress chunk");
00215                  }
00216                png_memcpy(text, chunkdata, prefix_size);
00217             }
00218 
00219             text[text_size - 1] = 0x00;
00220 
00221             /* Copy what we can of the error message into the text chunk */
00222             text_size = (png_size_t)(chunklength - (text - chunkdata) - 1);
00223             text_size = png_sizeof(msg) > text_size ? text_size :
00224                png_sizeof(msg);
00225             png_memcpy(text + prefix_size, msg, text_size + 1);
00226             break;
00227          }
00228          if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END)
00229          {
00230             if (text == NULL)
00231             {
00232                text_size = prefix_size +
00233                    png_ptr->zbuf_size - png_ptr->zstream.avail_out;
00234                text = (png_charp)png_malloc_warn(png_ptr, text_size + 1);
00235                if (text ==  NULL)
00236                  {
00237                     png_free(png_ptr,chunkdata);
00238                     png_error(png_ptr,"Not enough memory to decompress chunk.");
00239                  }
00240                png_memcpy(text + prefix_size, png_ptr->zbuf,
00241                     text_size - prefix_size);
00242                png_memcpy(text, chunkdata, prefix_size);
00243                *(text + text_size) = 0x00;
00244             }
00245             else
00246             {
00247                png_charp tmp;
00248 
00249                tmp = text;
00250                text = (png_charp)png_malloc_warn(png_ptr,
00251                   (png_uint_32)(text_size +
00252                   png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1));
00253                if (text == NULL)
00254                {
00255                   png_free(png_ptr, tmp);
00256                   png_free(png_ptr, chunkdata);
00257                   png_error(png_ptr,"Not enough memory to decompress chunk..");
00258                }
00259                png_memcpy(text, tmp, text_size);
00260                png_free(png_ptr, tmp);
00261                png_memcpy(text + text_size, png_ptr->zbuf,
00262                   (png_ptr->zbuf_size - png_ptr->zstream.avail_out));
00263                text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
00264                *(text + text_size) = 0x00;
00265             }
00266             if (ret == Z_STREAM_END)
00267                break;
00268             else
00269             {
00270                png_ptr->zstream.next_out = png_ptr->zbuf;
00271                png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
00272             }
00273          }
00274       }
00275       if (ret != Z_STREAM_END)
00276       {
00277 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
00278          char umsg[52];
00279 
00280          if (ret == Z_BUF_ERROR)
00281             sprintf(umsg,"Buffer error in compressed datastream in %s chunk",
00282                 png_ptr->chunk_name);
00283          else if (ret == Z_DATA_ERROR)
00284             sprintf(umsg,"Data error in compressed datastream in %s chunk",
00285                 png_ptr->chunk_name);
00286          else
00287             sprintf(umsg,"Incomplete compressed datastream in %s chunk",
00288                 png_ptr->chunk_name);
00289          png_warning(png_ptr, umsg);
00290 #else
00291          png_warning(png_ptr,
00292             "Incomplete compressed datastream in chunk other than IDAT");
00293 #endif
00294          text_size=prefix_size;
00295          if (text ==  NULL)
00296          {
00297             text = (png_charp)png_malloc_warn(png_ptr, text_size+1);
00298             if (text == NULL)
00299               {
00300                 png_free(png_ptr, chunkdata);
00301                 png_error(png_ptr,"Not enough memory for text.");
00302               }
00303             png_memcpy(text, chunkdata, prefix_size);
00304          }
00305          *(text + text_size) = 0x00;
00306       }
00307 
00308       inflateReset(&png_ptr->zstream);
00309       png_ptr->zstream.avail_in = 0;
00310 
00311       png_free(png_ptr, chunkdata);
00312       chunkdata = text;
00313       *newlength=text_size;
00314    }
00315    else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
00316    {
00317 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
00318       char umsg[50];
00319 
00320       sprintf(umsg, "Unknown zTXt compression type %d", comp_type);
00321       png_warning(png_ptr, umsg);
00322 #else
00323       png_warning(png_ptr, "Unknown zTXt compression type");
00324 #endif
00325 
00326       *(chunkdata + prefix_size) = 0x00;
00327       *newlength=prefix_size;
00328    }
00329 
00330    return chunkdata;
00331 }
00332 #endif
00333 
00334 /* read and check the IDHR chunk */
00335 void /* PRIVATE */
00336 png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
00337 {
00338    png_byte buf[13];
00339    png_uint_32 width, height;
00340    int bit_depth, color_type, compression_type, filter_type;
00341    int interlace_type;
00342 
00343    png_debug(1, "in png_handle_IHDR\n");
00344 
00345    if (png_ptr->mode & PNG_HAVE_IHDR)
00346       png_error(png_ptr, "Out of place IHDR");
00347 
00348    /* check the length */
00349    if (length != 13)
00350       png_error(png_ptr, "Invalid IHDR chunk");
00351 
00352    png_ptr->mode |= PNG_HAVE_IHDR;
00353 
00354    png_crc_read(png_ptr, buf, 13);
00355    png_crc_finish(png_ptr, 0);
00356 
00357    width = png_get_uint_31(png_ptr, buf);
00358    height = png_get_uint_31(png_ptr, buf + 4);
00359    bit_depth = buf[8];
00360    color_type = buf[9];
00361    compression_type = buf[10];
00362    filter_type = buf[11];
00363    interlace_type = buf[12];
00364 
00365    /* set internal variables */
00366    png_ptr->width = width;
00367    png_ptr->height = height;
00368    png_ptr->bit_depth = (png_byte)bit_depth;
00369    png_ptr->interlaced = (png_byte)interlace_type;
00370    png_ptr->color_type = (png_byte)color_type;
00371 #if defined(PNG_MNG_FEATURES_SUPPORTED)
00372    png_ptr->filter_type = (png_byte)filter_type;
00373 #endif
00374    png_ptr->compression_type = (png_byte)compression_type;
00375 
00376    /* find number of channels */
00377    switch (png_ptr->color_type)
00378    {
00379       case PNG_COLOR_TYPE_GRAY:
00380       case PNG_COLOR_TYPE_PALETTE:
00381          png_ptr->channels = 1;
00382          break;
00383       case PNG_COLOR_TYPE_RGB:
00384          png_ptr->channels = 3;
00385          break;
00386       case PNG_COLOR_TYPE_GRAY_ALPHA:
00387          png_ptr->channels = 2;
00388          break;
00389       case PNG_COLOR_TYPE_RGB_ALPHA:
00390          png_ptr->channels = 4;
00391          break;
00392    }
00393 
00394    /* set up other useful info */
00395    png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
00396    png_ptr->channels);
00397    png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->width);
00398    png_debug1(3,"bit_depth = %d\n", png_ptr->bit_depth);
00399    png_debug1(3,"channels = %d\n", png_ptr->channels);
00400    png_debug1(3,"rowbytes = %lu\n", png_ptr->rowbytes);
00401    png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
00402       color_type, interlace_type, compression_type, filter_type);
00403 }
00404 
00405 /* read and check the palette */
00406 void /* PRIVATE */
00407 png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
00408 {
00409    png_color palette[PNG_MAX_PALETTE_LENGTH];
00410    int num, i;
00411 #ifndef PNG_NO_POINTER_INDEXING
00412    png_colorp pal_ptr;
00413 #endif
00414 
00415    png_debug(1, "in png_handle_PLTE\n");
00416 
00417    if (!(png_ptr->mode & PNG_HAVE_IHDR))
00418       png_error(png_ptr, "Missing IHDR before PLTE");
00419    else if (png_ptr->mode & PNG_HAVE_IDAT)
00420    {
00421       png_warning(png_ptr, "Invalid PLTE after IDAT");
00422       png_crc_finish(png_ptr, length);
00423       return;
00424    }
00425    else if (png_ptr->mode & PNG_HAVE_PLTE)
00426       png_error(png_ptr, "Duplicate PLTE chunk");
00427 
00428    png_ptr->mode |= PNG_HAVE_PLTE;
00429 
00430    if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
00431    {
00432       png_warning(png_ptr,
00433         "Ignoring PLTE chunk in grayscale PNG");
00434       png_crc_finish(png_ptr, length);
00435       return;
00436    }
00437 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
00438    if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
00439    {
00440       png_crc_finish(png_ptr, length);
00441       return;
00442    }
00443 #endif
00444 
00445    if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
00446    {
00447       if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
00448       {
00449          png_warning(png_ptr, "Invalid palette chunk");
00450          png_crc_finish(png_ptr, length);
00451          return;
00452       }
00453       else
00454       {
00455          png_error(png_ptr, "Invalid palette chunk");
00456       }
00457    }
00458 
00459    num = (int)length / 3;
00460 
00461 #ifndef PNG_NO_POINTER_INDEXING
00462    for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
00463    {
00464       png_byte buf[3];
00465 
00466       png_crc_read(png_ptr, buf, 3);
00467       pal_ptr->red = buf[0];
00468       pal_ptr->green = buf[1];
00469       pal_ptr->blue = buf[2];
00470    }
00471 #else
00472    for (i = 0; i < num; i++)
00473    {
00474       png_byte buf[3];
00475 
00476       png_crc_read(png_ptr, buf, 3);
00477       /* don't depend upon png_color being any order */
00478       palette[i].red = buf[0];
00479       palette[i].green = buf[1];
00480       palette[i].blue = buf[2];
00481    }
00482 #endif
00483 
00484    /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
00485       whatever the normal CRC configuration tells us.  However, if we
00486       have an RGB image, the PLTE can be considered ancillary, so
00487       we will act as though it is. */
00488 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
00489    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
00490 #endif
00491    {
00492       png_crc_finish(png_ptr, 0);
00493    }
00494 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
00495    else if (png_crc_error(png_ptr))  /* Only if we have a CRC error */
00496    {
00497       /* If we don't want to use the data from an ancillary chunk,
00498          we have two options: an error abort, or a warning and we
00499          ignore the data in this chunk (which should be OK, since
00500          it's considered ancillary for a RGB or RGBA image). */
00501       if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
00502       {
00503          if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
00504          {
00505             png_chunk_error(png_ptr, "CRC error");
00506          }
00507          else
00508          {
00509             png_chunk_warning(png_ptr, "CRC error");
00510             return;
00511          }
00512       }
00513       /* Otherwise, we (optionally) emit a warning and use the chunk. */
00514       else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
00515       {
00516          png_chunk_warning(png_ptr, "CRC error");
00517       }
00518    }
00519 #endif
00520 
00521    png_set_PLTE(png_ptr, info_ptr, palette, num);
00522 
00523 #if defined(PNG_READ_tRNS_SUPPORTED)
00524    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
00525    {
00526       if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
00527       {
00528          if (png_ptr->num_trans > (png_uint_16)num)
00529          {
00530             png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
00531             png_ptr->num_trans = (png_uint_16)num;
00532          }
00533          if (info_ptr->num_trans > (png_uint_16)num)
00534          {
00535             png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
00536             info_ptr->num_trans = (png_uint_16)num;
00537          }
00538       }
00539    }
00540 #endif
00541 
00542 }
00543 
00544 void /* PRIVATE */
00545 png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
00546 {
00547    png_debug(1, "in png_handle_IEND\n");
00548 
00549    if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
00550    {
00551       png_error(png_ptr, "No image in file");
00552    }
00553 
00554    png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
00555 
00556    if (length != 0)
00557    {
00558       png_warning(png_ptr, "Incorrect IEND chunk length");
00559    }
00560    png_crc_finish(png_ptr, length);
00561 
00562    if (&info_ptr == NULL) /* quiet compiler warnings about unused info_ptr */
00563       return;
00564 }
00565 
00566 #if defined(PNG_READ_gAMA_SUPPORTED)
00567 void /* PRIVATE */
00568 png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
00569 {
00570    png_fixed_point igamma;
00571 #ifdef PNG_FLOATING_POINT_SUPPORTED
00572    float file_gamma;
00573 #endif
00574    png_byte buf[4];
00575 
00576    png_debug(1, "in png_handle_gAMA\n");
00577 
00578    if (!(png_ptr->mode & PNG_HAVE_IHDR))
00579       png_error(png_ptr, "Missing IHDR before gAMA");
00580    else if (png_ptr->mode & PNG_HAVE_IDAT)
00581    {
00582       png_warning(png_ptr, "Invalid gAMA after IDAT");
00583       png_crc_finish(png_ptr, length);
00584       return;
00585    }
00586    else if (png_ptr->mode & PNG_HAVE_PLTE)
00587       /* Should be an error, but we can cope with it */
00588       png_warning(png_ptr, "Out of place gAMA chunk");
00589 
00590    if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
00591 #if defined(PNG_READ_sRGB_SUPPORTED)
00592       && !(info_ptr->valid & PNG_INFO_sRGB)
00593 #endif
00594       )
00595    {
00596       png_warning(png_ptr, "Duplicate gAMA chunk");
00597       png_crc_finish(png_ptr, length);
00598       return;
00599    }
00600 
00601    if (length != 4)
00602    {
00603       png_warning(png_ptr, "Incorrect gAMA chunk length");
00604       png_crc_finish(png_ptr, length);
00605       return;
00606    }
00607 
00608    png_crc_read(png_ptr, buf, 4);
00609    if (png_crc_finish(png_ptr, 0))
00610       return;
00611 
00612    igamma = (png_fixed_point)png_get_uint_32(buf);
00613    /* check for zero gamma */
00614    if (igamma == 0)
00615       {
00616          png_warning(png_ptr,
00617            "Ignoring gAMA chunk with gamma=0");
00618          return;
00619       }
00620 
00621 #if defined(PNG_READ_sRGB_SUPPORTED)
00622    if (info_ptr->valid & PNG_INFO_sRGB)
00623       if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
00624       {
00625          png_warning(png_ptr,
00626            "Ignoring incorrect gAMA value when sRGB is also present");
00627 #ifndef PNG_NO_CONSOLE_IO
00628          fprintf(stderr, "gamma = (%d/100000)\n", (int)igamma);
00629 #endif
00630          return;
00631       }
00632 #endif /* PNG_READ_sRGB_SUPPORTED */
00633 
00634 #ifdef PNG_FLOATING_POINT_SUPPORTED
00635    file_gamma = (float)igamma / (float)100000.0;
00636 #  ifdef PNG_READ_GAMMA_SUPPORTED
00637      png_ptr->gamma = file_gamma;
00638 #  endif
00639      png_set_gAMA(png_ptr, info_ptr, file_gamma);
00640 #endif
00641 #ifdef PNG_FIXED_POINT_SUPPORTED
00642    png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
00643 #endif
00644 }
00645 #endif
00646 
00647 #if defined(PNG_READ_sBIT_SUPPORTED)
00648 void /* PRIVATE */
00649 png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
00650 {
00651    png_size_t truelen;
00652    png_byte buf[4];
00653 
00654    png_debug(1, "in png_handle_sBIT\n");
00655 
00656    buf[0] = buf[1] = buf[2] = buf[3] = 0;
00657 
00658    if (!(png_ptr->mode & PNG_HAVE_IHDR))
00659       png_error(png_ptr, "Missing IHDR before sBIT");
00660    else if (png_ptr->mode & PNG_HAVE_IDAT)
00661    {
00662       png_warning(png_ptr, "Invalid sBIT after IDAT");
00663       png_crc_finish(png_ptr, length);
00664       return;
00665    }
00666    else if (png_ptr->mode & PNG_HAVE_PLTE)
00667    {
00668       /* Should be an error, but we can cope with it */
00669       png_warning(png_ptr, "Out of place sBIT chunk");
00670    }
00671    if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
00672    {
00673       png_warning(png_ptr, "Duplicate sBIT chunk");
00674       png_crc_finish(png_ptr, length);
00675       return;
00676    }
00677 
00678    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
00679       truelen = 3;
00680    else
00681       truelen = (png_size_t)png_ptr->channels;
00682 
00683    if (length != truelen || length > 4)
00684    {
00685       png_warning(png_ptr, "Incorrect sBIT chunk length");
00686       png_crc_finish(png_ptr, length);
00687       return;
00688    }
00689 
00690    png_crc_read(png_ptr, buf, truelen);
00691    if (png_crc_finish(png_ptr, 0))
00692       return;
00693 
00694    if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
00695    {
00696       png_ptr->sig_bit.red = buf[0];
00697       png_ptr->sig_bit.green = buf[1];
00698       png_ptr->sig_bit.blue = buf[2];
00699       png_ptr->sig_bit.alpha = buf[3];
00700    }
00701    else
00702    {
00703       png_ptr->sig_bit.gray = buf[0];
00704       png_ptr->sig_bit.red = buf[0];
00705       png_ptr->sig_bit.green = buf[0];
00706       png_ptr->sig_bit.blue = buf[0];
00707       png_ptr->sig_bit.alpha = buf[1];
00708    }
00709    png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
00710 }
00711 #endif
00712 
00713 #if defined(PNG_READ_cHRM_SUPPORTED)
00714 void /* PRIVATE */
00715 png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
00716 {
00717    png_byte buf[4];
00718 #ifdef PNG_FLOATING_POINT_SUPPORTED
00719    float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
00720 #endif
00721    png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
00722       int_y_green, int_x_blue, int_y_blue;
00723 
00724    png_uint_32 uint_x, uint_y;
00725 
00726    png_debug(1, "in png_handle_cHRM\n");
00727 
00728    if (!(png_ptr->mode & PNG_HAVE_IHDR))
00729       png_error(png_ptr, "Missing IHDR before cHRM");
00730    else if (png_ptr->mode & PNG_HAVE_IDAT)
00731    {
00732       png_warning(png_ptr, "Invalid cHRM after IDAT");
00733       png_crc_finish(png_ptr, length);
00734       return;
00735    }
00736    else if (png_ptr->mode & PNG_HAVE_PLTE)
00737       /* Should be an error, but we can cope with it */
00738       png_warning(png_ptr, "Missing PLTE before cHRM");
00739 
00740    if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
00741 #if defined(PNG_READ_sRGB_SUPPORTED)
00742       && !(info_ptr->valid & PNG_INFO_sRGB)
00743 #endif
00744       )
00745    {
00746       png_warning(png_ptr, "Duplicate cHRM chunk");
00747       png_crc_finish(png_ptr, length);
00748       return;
00749    }
00750 
00751    if (length != 32)
00752    {
00753       png_warning(png_ptr, "Incorrect cHRM chunk length");
00754       png_crc_finish(png_ptr, length);
00755       return;
00756    }
00757 
00758    png_crc_read(png_ptr, buf, 4);
00759    uint_x = png_get_uint_32(buf);
00760 
00761    png_crc_read(png_ptr, buf, 4);
00762    uint_y = png_get_uint_32(buf);
00763 
00764    if (uint_x > 80000L || uint_y > 80000L ||
00765       uint_x + uint_y > 100000L)
00766    {
00767       png_warning(png_ptr, "Invalid cHRM white point");
00768       png_crc_finish(png_ptr, 24);
00769       return;
00770    }
00771    int_x_white = (png_fixed_point)uint_x;
00772    int_y_white = (png_fixed_point)uint_y;
00773 
00774    png_crc_read(png_ptr, buf, 4);
00775    uint_x = png_get_uint_32(buf);
00776 
00777    png_crc_read(png_ptr, buf, 4);
00778    uint_y = png_get_uint_32(buf);
00779 
00780    if (uint_x > 80000L || uint_y > 80000L ||
00781       uint_x + uint_y > 100000L)
00782    {
00783       png_warning(png_ptr, "Invalid cHRM red point");
00784       png_crc_finish(png_ptr, 16);
00785       return;
00786    }
00787    int_x_red = (png_fixed_point)uint_x;
00788    int_y_red = (png_fixed_point)uint_y;
00789 
00790    png_crc_read(png_ptr, buf, 4);
00791    uint_x = png_get_uint_32(buf);
00792 
00793    png_crc_read(png_ptr, buf, 4);
00794    uint_y = png_get_uint_32(buf);
00795 
00796    if (uint_x > 80000L || uint_y > 80000L ||
00797       uint_x + uint_y > 100000L)
00798    {
00799       png_warning(png_ptr, "Invalid cHRM green point");
00800       png_crc_finish(png_ptr, 8);
00801       return;
00802    }
00803    int_x_green = (png_fixed_point)uint_x;
00804    int_y_green = (png_fixed_point)uint_y;
00805 
00806    png_crc_read(png_ptr, buf, 4);
00807    uint_x = png_get_uint_32(buf);
00808 
00809    png_crc_read(png_ptr, buf, 4);
00810    uint_y = png_get_uint_32(buf);
00811 
00812    if (uint_x > 80000L || uint_y > 80000L ||
00813       uint_x + uint_y > 100000L)
00814    {
00815       png_warning(png_ptr, "Invalid cHRM blue point");
00816       png_crc_finish(png_ptr, 0);
00817       return;
00818    }
00819    int_x_blue = (png_fixed_point)uint_x;
00820    int_y_blue = (png_fixed_point)uint_y;
00821 
00822 #ifdef PNG_FLOATING_POINT_SUPPORTED
00823    white_x = (float)int_x_white / (float)100000.0;
00824    white_y = (float)int_y_white / (float)100000.0;
00825    red_x   = (float)int_x_red   / (float)100000.0;
00826    red_y   = (float)int_y_red   / (float)100000.0;
00827    green_x = (float)int_x_green / (float)100000.0;
00828    green_y = (float)int_y_green / (float)100000.0;
00829    blue_x  = (float)int_x_blue  / (float)100000.0;
00830    blue_y  = (float)int_y_blue  / (float)100000.0;
00831 #endif
00832 
00833 #if defined(PNG_READ_sRGB_SUPPORTED)
00834    if (info_ptr->valid & PNG_INFO_sRGB)
00835       {
00836       if (PNG_OUT_OF_RANGE(int_x_white, 31270,  1000) ||
00837           PNG_OUT_OF_RANGE(int_y_white, 32900,  1000) ||
00838           PNG_OUT_OF_RANGE(int_x_red,   64000L, 1000) ||
00839           PNG_OUT_OF_RANGE(int_y_red,   33000,  1000) ||
00840           PNG_OUT_OF_RANGE(int_x_green, 30000,  1000) ||
00841           PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) ||
00842           PNG_OUT_OF_RANGE(int_x_blue,  15000,  1000) ||
00843           PNG_OUT_OF_RANGE(int_y_blue,   6000,  1000))
00844          {
00845 
00846             png_warning(png_ptr,
00847               "Ignoring incorrect cHRM value when sRGB is also present");
00848 #ifndef PNG_NO_CONSOLE_IO
00849 #ifdef PNG_FLOATING_POINT_SUPPORTED
00850             fprintf(stderr,"wx=%f, wy=%f, rx=%f, ry=%f\n",
00851                white_x, white_y, red_x, red_y);
00852             fprintf(stderr,"gx=%f, gy=%f, bx=%f, by=%f\n",
00853                green_x, green_y, blue_x, blue_y);
00854 #else
00855             fprintf(stderr,"wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
00856                int_x_white, int_y_white, int_x_red, int_y_red);
00857             fprintf(stderr,"gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
00858                int_x_green, int_y_green, int_x_blue, int_y_blue);
00859 #endif
00860 #endif /* PNG_NO_CONSOLE_IO */
00861          }
00862          png_crc_finish(png_ptr, 0);
00863          return;
00864       }
00865 #endif /* PNG_READ_sRGB_SUPPORTED */
00866 
00867 #ifdef PNG_FLOATING_POINT_SUPPORTED
00868    png_set_cHRM(png_ptr, info_ptr,
00869       white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
00870 #endif
00871 #ifdef PNG_FIXED_POINT_SUPPORTED
00872    png_set_cHRM_fixed(png_ptr, info_ptr,
00873       int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
00874       int_y_green, int_x_blue, int_y_blue);
00875 #endif
00876    if (png_crc_finish(png_ptr, 0))
00877       return;
00878 }
00879 #endif
00880 
00881 #if defined(PNG_READ_sRGB_SUPPORTED)
00882 void /* PRIVATE */
00883 png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
00884 {
00885    int intent;
00886    png_byte buf[1];
00887 
00888    png_debug(1, "in png_handle_sRGB\n");
00889 
00890    if (!(png_ptr->mode & PNG_HAVE_IHDR))
00891       png_error(png_ptr, "Missing IHDR before sRGB");
00892    else if (png_ptr->mode & PNG_HAVE_IDAT)
00893    {
00894       png_warning(png_ptr, "Invalid sRGB after IDAT");
00895       png_crc_finish(png_ptr, length);
00896       return;
00897    }
00898    else if (png_ptr->mode & PNG_HAVE_PLTE)
00899       /* Should be an error, but we can cope with it */
00900       png_warning(png_ptr, "Out of place sRGB chunk");
00901 
00902    if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
00903    {
00904       png_warning(png_ptr, "Duplicate sRGB chunk");
00905       png_crc_finish(png_ptr, length);
00906       return;
00907    }
00908 
00909    if (length != 1)
00910    {
00911       png_warning(png_ptr, "Incorrect sRGB chunk length");
00912       png_crc_finish(png_ptr, length);
00913       return;
00914    }
00915 
00916    png_crc_read(png_ptr, buf, 1);
00917    if (png_crc_finish(png_ptr, 0))
00918       return;
00919 
00920    intent = buf[0];
00921    /* check for bad intent */
00922    if (intent >= PNG_sRGB_INTENT_LAST)
00923    {
00924       png_warning(png_ptr, "Unknown sRGB intent");
00925       return;
00926    }
00927 
00928 #if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
00929    if ((info_ptr->valid & PNG_INFO_gAMA))
00930    {
00931    png_fixed_point igamma;
00932 #ifdef PNG_FIXED_POINT_SUPPORTED
00933       igamma=info_ptr->int_gamma;
00934 #else
00935 #  ifdef PNG_FLOATING_POINT_SUPPORTED
00936       igamma=(png_fixed_point)(info_ptr->gamma * 100000.);
00937 #  endif
00938 #endif
00939       if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
00940       {
00941          png_warning(png_ptr,
00942            "Ignoring incorrect gAMA value when sRGB is also present");
00943 #ifndef PNG_NO_CONSOLE_IO
00944 #  ifdef PNG_FIXED_POINT_SUPPORTED
00945          fprintf(stderr,"incorrect gamma=(%d/100000)\n",(int)png_ptr->int_gamma);
00946 #  else
00947 #    ifdef PNG_FLOATING_POINT_SUPPORTED
00948          fprintf(stderr,"incorrect gamma=%f\n",png_ptr->gamma);
00949 #    endif
00950 #  endif
00951 #endif
00952       }
00953    }
00954 #endif /* PNG_READ_gAMA_SUPPORTED */
00955 
00956 #ifdef PNG_READ_cHRM_SUPPORTED
00957 #ifdef PNG_FIXED_POINT_SUPPORTED
00958    if (info_ptr->valid & PNG_INFO_cHRM)
00959       if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270,  1000) ||
00960           PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900,  1000) ||
00961           PNG_OUT_OF_RANGE(info_ptr->int_x_red,   64000L, 1000) ||
00962           PNG_OUT_OF_RANGE(info_ptr->int_y_red,   33000,  1000) ||
00963           PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000,  1000) ||
00964           PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) ||
00965           PNG_OUT_OF_RANGE(info_ptr->int_x_blue,  15000,  1000) ||
00966           PNG_OUT_OF_RANGE(info_ptr->int_y_blue,   6000,  1000))
00967          {
00968             png_warning(png_ptr,
00969               "Ignoring incorrect cHRM value when sRGB is also present");
00970          }
00971 #endif /* PNG_FIXED_POINT_SUPPORTED */
00972 #endif /* PNG_READ_cHRM_SUPPORTED */
00973 
00974    png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
00975 }
00976 #endif /* PNG_READ_sRGB_SUPPORTED */
00977 
00978 #if defined(PNG_READ_iCCP_SUPPORTED)
00979 void /* PRIVATE */
00980 png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
00981 /* Note: this does not properly handle chunks that are > 64K under DOS */
00982 {
00983    png_charp chunkdata;
00984    png_byte compression_type;
00985    png_bytep pC;
00986    png_charp profile;
00987    png_uint_32 skip = 0;
00988    png_uint_32 profile_size, profile_length;
00989    png_size_t slength, prefix_length, data_length;
00990 
00991    png_debug(1, "in png_handle_iCCP\n");
00992 
00993    if (!(png_ptr->mode & PNG_HAVE_IHDR))
00994       png_error(png_ptr, "Missing IHDR before iCCP");
00995    else if (png_ptr->mode & PNG_HAVE_IDAT)
00996    {
00997       png_warning(png_ptr, "Invalid iCCP after IDAT");
00998       png_crc_finish(png_ptr, length);
00999       return;
01000    }
01001    else if (png_ptr->mode & PNG_HAVE_PLTE)
01002       /* Should be an error, but we can cope with it */
01003       png_warning(png_ptr, "Out of place iCCP chunk");
01004 
01005    if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
01006    {
01007       png_warning(png_ptr, "Duplicate iCCP chunk");
01008       png_crc_finish(png_ptr, length);
01009       return;
01010    }
01011 
01012 #ifdef PNG_MAX_MALLOC_64K
01013    if (length > (png_uint_32)65535L)
01014    {
01015       png_warning(png_ptr, "iCCP chunk too large to fit in memory");
01016       skip = length - (png_uint_32)65535L;
01017       length = (png_uint_32)65535L;
01018    }
01019 #endif
01020 
01021    chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
01022    slength = (png_size_t)length;
01023    png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
01024 
01025    if (png_crc_finish(png_ptr, skip))
01026    {
01027       png_free(png_ptr, chunkdata);
01028       return;
01029    }
01030 
01031    chunkdata[slength] = 0x00;
01032 
01033    for (profile = chunkdata; *profile; profile++)
01034       /* empty loop to find end of name */ ;
01035 
01036    ++profile;
01037 
01038    /* there should be at least one zero (the compression type byte)
01039       following the separator, and we should be on it  */
01040    if ( profile >= chunkdata + slength)
01041    {
01042       png_free(png_ptr, chunkdata);
01043       png_warning(png_ptr, "Malformed iCCP chunk");
01044       return;
01045    }
01046 
01047    /* compression_type should always be zero */
01048    compression_type = *profile++;
01049    if (compression_type)
01050    {
01051       png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
01052       compression_type=0x00;  /* Reset it to zero (libpng-1.0.6 through 1.0.8
01053                                  wrote nonzero) */
01054    }
01055 
01056    prefix_length = profile - chunkdata;
01057    chunkdata = png_decompress_chunk(png_ptr, compression_type, chunkdata,
01058                                     slength, prefix_length, &data_length);
01059 
01060    profile_length = data_length - prefix_length;
01061 
01062    if ( prefix_length > data_length || profile_length < 4)
01063    {
01064       png_free(png_ptr, chunkdata);
01065       png_warning(png_ptr, "Profile size field missing from iCCP chunk");
01066       return;
01067    }
01068 
01069    /* Check the profile_size recorded in the first 32 bits of the ICC profile */
01070    pC = (png_bytep)(chunkdata+prefix_length);
01071    profile_size = ((*(pC  ))<<24) |
01072                   ((*(pC+1))<<16) |
01073                   ((*(pC+2))<< 8) |
01074                   ((*(pC+3))    );
01075 
01076    if(profile_size < profile_length)
01077       profile_length = profile_size;
01078 
01079    if(profile_size > profile_length)
01080    {
01081       png_free(png_ptr, chunkdata);
01082       png_warning(png_ptr, "Ignoring truncated iCCP profile.\n");
01083       return;
01084    }
01085 
01086    png_set_iCCP(png_ptr, info_ptr, chunkdata, compression_type,
01087                 chunkdata + prefix_length, profile_length);
01088    png_free(png_ptr, chunkdata);
01089 }
01090 #endif /* PNG_READ_iCCP_SUPPORTED */
01091 
01092 #if defined(PNG_READ_sPLT_SUPPORTED)
01093 void /* PRIVATE */
01094 png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
01095 /* Note: this does not properly handle chunks that are > 64K under DOS */
01096 {
01097    png_bytep chunkdata;
01098    png_bytep entry_start;
01099    png_sPLT_t new_palette;
01100 #ifdef PNG_NO_POINTER_INDEXING
01101    png_sPLT_entryp pp;
01102 #endif
01103    int data_length, entry_size, i;
01104    png_uint_32 skip = 0;
01105    png_size_t slength;
01106 
01107    png_debug(1, "in png_handle_sPLT\n");
01108 
01109    if (!(png_ptr->mode & PNG_HAVE_IHDR))
01110       png_error(png_ptr, "Missing IHDR before sPLT");
01111    else if (png_ptr->mode & PNG_HAVE_IDAT)
01112    {
01113       png_warning(png_ptr, "Invalid sPLT after IDAT");
01114       png_crc_finish(png_ptr, length);
01115       return;
01116    }
01117 
01118 #ifdef PNG_MAX_MALLOC_64K
01119    if (length > (png_uint_32)65535L)
01120    {
01121       png_warning(png_ptr, "sPLT chunk too large to fit in memory");
01122       skip = length - (png_uint_32)65535L;
01123       length = (png_uint_32)65535L;
01124    }
01125 #endif
01126 
01127    chunkdata = (png_bytep)png_malloc(png_ptr, length + 1);
01128    slength = (png_size_t)length;
01129    png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
01130 
01131    if (png_crc_finish(png_ptr, skip))
01132    {
01133       png_free(png_ptr, chunkdata);
01134       return;
01135    }
01136 
01137    chunkdata[slength] = 0x00;
01138 
01139    for (entry_start = chunkdata; *entry_start; entry_start++)
01140       /* empty loop to find end of name */ ;
01141    ++entry_start;
01142 
01143    /* a sample depth should follow the separator, and we should be on it  */
01144    if (entry_start > chunkdata + slength)
01145    {
01146       png_free(png_ptr, chunkdata);
01147       png_warning(png_ptr, "malformed sPLT chunk");
01148       return;
01149    }
01150 
01151    new_palette.depth = *entry_start++;
01152    entry_size = (new_palette.depth == 8 ? 6 : 10);
01153    data_length = (slength - (entry_start - chunkdata));
01154 
01155    /* integrity-check the data length */
01156    if (data_length % entry_size)
01157    {
01158       png_free(png_ptr, chunkdata);
01159       png_warning(png_ptr, "sPLT chunk has bad length");
01160       return;
01161    }
01162 
01163    new_palette.nentries = (png_uint_32) (data_length / entry_size);
01164    if ((png_uint_32) new_palette.nentries > (png_uint_32) (PNG_SIZE_MAX /
01165        png_sizeof(png_sPLT_entry)))
01166    {
01167        png_warning(png_ptr, "sPLT chunk too long");
01168        return;
01169    }
01170    new_palette.entries = (png_sPLT_entryp)png_malloc_warn(
01171        png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry));
01172    if (new_palette.entries == NULL)
01173    {
01174        png_warning(png_ptr, "sPLT chunk requires too much memory");
01175        return;
01176    }
01177 
01178 #ifndef PNG_NO_POINTER_INDEXING
01179    for (i = 0; i < new_palette.nentries; i++)
01180    {
01181       png_sPLT_entryp pp = new_palette.entries + i;
01182 
01183       if (new_palette.depth == 8)
01184       {
01185           pp->red = *entry_start++;
01186           pp->green = *entry_start++;
01187           pp->blue = *entry_start++;
01188           pp->alpha = *entry_start++;
01189       }
01190       else
01191       {
01192           pp->red   = png_get_uint_16(entry_start); entry_start += 2;
01193           pp->green = png_get_uint_16(entry_start); entry_start += 2;
01194           pp->blue  = png_get_uint_16(entry_start); entry_start += 2;
01195           pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
01196       }
01197       pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
01198    }
01199 #else
01200    pp = new_palette.entries;
01201    for (i = 0; i < new_palette.nentries; i++)
01202    {
01203 
01204       if (new_palette.depth == 8)
01205       {
01206           pp[i].red   = *entry_start++;
01207           pp[i].green = *entry_start++;
01208           pp[i].blue  = *entry_start++;
01209           pp[i].alpha = *entry_start++;
01210       }
01211       else
01212       {
01213           pp[i].red   = png_get_uint_16(entry_start); entry_start += 2;
01214           pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
01215           pp[i].blue  = png_get_uint_16(entry_start); entry_start += 2;
01216           pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
01217       }
01218       pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
01219    }
01220 #endif
01221 
01222    /* discard all chunk data except the name and stash that */
01223    new_palette.name = (png_charp)chunkdata;
01224 
01225    png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
01226 
01227    png_free(png_ptr, chunkdata);
01228    png_free(png_ptr, new_palette.entries);
01229 }
01230 #endif /* PNG_READ_sPLT_SUPPORTED */
01231 
01232 #if defined(PNG_READ_tRNS_SUPPORTED)
01233 void /* PRIVATE */
01234 png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
01235 {
01236    png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
01237 
01238    png_debug(1, "in png_handle_tRNS\n");
01239 
01240    if (!(png_ptr->mode & PNG_HAVE_IHDR))
01241       png_error(png_ptr, "Missing IHDR before tRNS");
01242    else if (png_ptr->mode & PNG_HAVE_IDAT)
01243    {
01244       png_warning(png_ptr, "Invalid tRNS after IDAT");
01245       png_crc_finish(png_ptr, length);
01246       return;
01247    }
01248    else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
01249    {
01250       png_warning(png_ptr, "Duplicate tRNS chunk");
01251       png_crc_finish(png_ptr, length);
01252       return;
01253    }
01254 
01255    if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
01256    {
01257       png_byte buf[2];
01258 
01259       if (length != 2)
01260       {
01261          png_warning(png_ptr, "Incorrect tRNS chunk length");
01262          png_crc_finish(png_ptr, length);
01263          return;
01264       }
01265 
01266       png_crc_read(png_ptr, buf, 2);
01267       png_ptr->num_trans = 1;
01268       png_ptr->trans_values.gray = png_get_uint_16(buf);
01269    }
01270    else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
01271    {
01272       png_byte buf[6];
01273 
01274       if (length != 6)
01275       {
01276          png_warning(png_ptr, "Incorrect tRNS chunk length");
01277          png_crc_finish(png_ptr, length);
01278          return;
01279       }
01280       png_crc_read(png_ptr, buf, (png_size_t)length);
01281       png_ptr->num_trans = 1;
01282       png_ptr->trans_values.red = png_get_uint_16(buf);
01283       png_ptr->trans_values.green = png_get_uint_16(buf + 2);
01284       png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
01285    }
01286    else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
01287    {
01288       if (!(png_ptr->mode & PNG_HAVE_PLTE))
01289       {
01290          /* Should be an error, but we can cope with it. */
01291          png_warning(png_ptr, "Missing PLTE before tRNS");
01292       }
01293       if (length > (png_uint_32)png_ptr->num_palette ||
01294           length > PNG_MAX_PALETTE_LENGTH)
01295       {
01296          png_warning(png_ptr, "Incorrect tRNS chunk length");
01297          png_crc_finish(png_ptr, length);
01298          return;
01299       }
01300       if (length == 0)
01301       {
01302          png_warning(png_ptr, "Zero length tRNS chunk");
01303          png_crc_finish(png_ptr, length);
01304          return;
01305       }
01306       png_crc_read(png_ptr, readbuf, (png_size_t)length);
01307       png_ptr->num_trans = (png_uint_16)length;
01308    }
01309    else
01310    {
01311       png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
01312       png_crc_finish(png_ptr, length);
01313       return;
01314    }
01315 
01316    if (png_crc_finish(png_ptr, 0))
01317    {
01318       png_ptr->num_trans = 0;
01319       return;
01320    }
01321 
01322    png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
01323       &(png_ptr->trans_values));
01324 }
01325 #endif
01326 
01327 #if defined(PNG_READ_bKGD_SUPPORTED)
01328 void /* PRIVATE */
01329 png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
01330 {
01331    png_size_t truelen;
01332    png_byte buf[6];
01333 
01334    png_debug(1, "in png_handle_bKGD\n");
01335 
01336    if (!(png_ptr->mode & PNG_HAVE_IHDR))
01337       png_error(png_ptr, "Missing IHDR before bKGD");
01338    else if (png_ptr->mode & PNG_HAVE_IDAT)
01339    {
01340       png_warning(png_ptr, "Invalid bKGD after IDAT");
01341       png_crc_finish(png_ptr, length);
01342       return;
01343    }
01344    else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
01345             !(png_ptr->mode & PNG_HAVE_PLTE))
01346    {
01347       png_warning(png_ptr, "Missing PLTE before bKGD");
01348       png_crc_finish(png_ptr, length);
01349       return;
01350    }
01351    else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
01352    {
01353       png_warning(png_ptr, "Duplicate bKGD chunk");
01354       png_crc_finish(png_ptr, length);
01355       return;
01356    }
01357 
01358    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
01359       truelen = 1;
01360    else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
01361       truelen = 6;
01362    else
01363       truelen = 2;
01364 
01365    if (length != truelen)
01366    {
01367       png_warning(png_ptr, "Incorrect bKGD chunk length");
01368       png_crc_finish(png_ptr, length);
01369       return;
01370    }
01371 
01372    png_crc_read(png_ptr, buf, truelen);
01373    if (png_crc_finish(png_ptr, 0))
01374       return;
01375 
01376    /* We convert the index value into RGB components so that we can allow
01377     * arbitrary RGB values for background when we have transparency, and
01378     * so it is easy to determine the RGB values of the background color
01379     * from the info_ptr struct. */
01380    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
01381    {
01382       png_ptr->background.index = buf[0];
01383       if(info_ptr->num_palette)
01384       {
01385           if(buf[0] > info_ptr->num_palette)
01386           {
01387              png_warning(png_ptr, "Incorrect bKGD chunk index value");
01388              return;
01389           }
01390           png_ptr->background.red =
01391              (png_uint_16)png_ptr->palette[buf[0]].red;
01392           png_ptr->background.green =
01393              (png_uint_16)png_ptr->palette[buf[0]].green;
01394           png_ptr->background.blue =
01395              (png_uint_16)png_ptr->palette[buf[0]].blue;
01396       }
01397    }
01398    else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
01399    {
01400       png_ptr->background.red =
01401       png_ptr->background.green =
01402       png_ptr->background.blue =
01403       png_ptr->background.gray = png_get_uint_16(buf);
01404    }
01405    else
01406    {
01407       png_ptr->background.red = png_get_uint_16(buf);
01408       png_ptr->background.green = png_get_uint_16(buf + 2);
01409       png_ptr->background.blue = png_get_uint_16(buf + 4);
01410    }
01411 
01412    png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
01413 }
01414 #endif
01415 
01416 #if defined(PNG_READ_hIST_SUPPORTED)
01417 void /* PRIVATE */
01418 png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
01419 {
01420    unsigned int num, i;
01421    png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
01422 
01423    png_debug(1, "in png_handle_hIST\n");
01424 
01425    if (!(png_ptr->mode & PNG_HAVE_IHDR))
01426       png_error(png_ptr, "Missing IHDR before hIST");
01427    else if (png_ptr->mode & PNG_HAVE_IDAT)
01428    {
01429       png_warning(png_ptr, "Invalid hIST after IDAT");
01430       png_crc_finish(png_ptr, length);
01431       return;
01432    }
01433    else if (!(png_ptr->mode & PNG_HAVE_PLTE))
01434    {
01435       png_warning(png_ptr, "Missing PLTE before hIST");
01436       png_crc_finish(png_ptr, length);
01437       return;
01438    }
01439    else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
01440    {
01441       png_warning(png_ptr, "Duplicate hIST chunk");
01442       png_crc_finish(png_ptr, length);
01443       return;
01444    }
01445 
01446    num = length / 2 ;
01447    if (num != (unsigned int) png_ptr->num_palette || num >
01448       (unsigned int) PNG_MAX_PALETTE_LENGTH)
01449    {
01450       png_warning(png_ptr, "Incorrect hIST chunk length");
01451       png_crc_finish(png_ptr, length);
01452       return;
01453    }
01454 
01455    for (i = 0; i < num; i++)
01456    {
01457       png_byte buf[2];
01458 
01459       png_crc_read(png_ptr, buf, 2);
01460       readbuf[i] = png_get_uint_16(buf);
01461    }
01462 
01463    if (png_crc_finish(png_ptr, 0))
01464       return;
01465 
01466    png_set_hIST(png_ptr, info_ptr, readbuf);
01467 }
01468 #endif
01469 
01470 #if defined(PNG_READ_pHYs_SUPPORTED)
01471 void /* PRIVATE */
01472 png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
01473 {
01474    png_byte buf[9];
01475    png_uint_32 res_x, res_y;
01476    int unit_type;
01477 
01478    png_debug(1, "in png_handle_pHYs\n");
01479 
01480    if (!(png_ptr->mode & PNG_HAVE_IHDR))
01481       png_error(png_ptr, "Missing IHDR before pHYs");
01482    else if (png_ptr->mode & PNG_HAVE_IDAT)
01483    {
01484       png_warning(png_ptr, "Invalid pHYs after IDAT");
01485       png_crc_finish(png_ptr, length);
01486       return;
01487    }
01488    else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
01489    {
01490       png_warning(png_ptr, "Duplicate pHYs chunk");
01491       png_crc_finish(png_ptr, length);
01492       return;
01493    }
01494 
01495    if (length != 9)
01496    {
01497       png_warning(png_ptr, "Incorrect pHYs chunk length");
01498       png_crc_finish(png_ptr, length);
01499       return;
01500    }
01501 
01502    png_crc_read(png_ptr, buf, 9);
01503    if (png_crc_finish(png_ptr, 0))
01504       return;
01505 
01506    res_x = png_get_uint_32(buf);
01507    res_y = png_get_uint_32(buf + 4);
01508    unit_type = buf[8];
01509    png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
01510 }
01511 #endif
01512 
01513 #if defined(PNG_READ_oFFs_SUPPORTED)
01514 void /* PRIVATE */
01515 png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
01516 {
01517    png_byte buf[9];
01518    png_int_32 offset_x, offset_y;
01519    int unit_type;
01520 
01521    png_debug(1, "in png_handle_oFFs\n");
01522 
01523    if (!(png_ptr->mode & PNG_HAVE_IHDR))
01524       png_error(png_ptr, "Missing IHDR before oFFs");
01525    else if (png_ptr->mode & PNG_HAVE_IDAT)
01526    {
01527       png_warning(png_ptr, "Invalid oFFs after IDAT");
01528       png_crc_finish(png_ptr, length);
01529       return;
01530    }
01531    else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
01532    {
01533       png_warning(png_ptr, "Duplicate oFFs chunk");
01534       png_crc_finish(png_ptr, length);
01535       return;
01536    }
01537 
01538    if (length != 9)
01539    {
01540       png_warning(png_ptr, "Incorrect oFFs chunk length");
01541       png_crc_finish(png_ptr, length);
01542       return;
01543    }
01544 
01545    png_crc_read(png_ptr, buf, 9);
01546    if (png_crc_finish(png_ptr, 0))
01547       return;
01548 
01549    offset_x = png_get_int_32(buf);
01550    offset_y = png_get_int_32(buf + 4);
01551    unit_type = buf[8];
01552    png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
01553 }
01554 #endif
01555 
01556 #if defined(PNG_READ_pCAL_SUPPORTED)
01557 /* read the pCAL chunk (described in the PNG Extensions document) */
01558 void /* PRIVATE */
01559 png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
01560 {
01561    png_charp purpose;
01562    png_int_32 X0, X1;
01563    png_byte type, nparams;
01564    png_charp buf, units, endptr;
01565    png_charpp params;
01566    png_size_t slength;
01567    int i;
01568 
01569    png_debug(1, "in png_handle_pCAL\n");
01570 
01571    if (!(png_ptr->mode & PNG_HAVE_IHDR))
01572       png_error(png_ptr, "Missing IHDR before pCAL");
01573    else if (png_ptr->mode & PNG_HAVE_IDAT)
01574    {
01575       png_warning(png_ptr, "Invalid pCAL after IDAT");
01576       png_crc_finish(png_ptr, length);
01577       return;
01578    }
01579    else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
01580    {
01581       png_warning(png_ptr, "Duplicate pCAL chunk");
01582       png_crc_finish(png_ptr, length);
01583       return;
01584    }
01585 
01586    png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)\n",
01587       length + 1);
01588    purpose = (png_charp)png_malloc_warn(png_ptr, length + 1);
01589    if (purpose == NULL)
01590      {
01591        png_warning(png_ptr, "No memory for pCAL purpose.");
01592        return;
01593      }
01594    slength = (png_size_t)length;
01595    png_crc_read(png_ptr, (png_bytep)purpose, slength);
01596 
01597    if (png_crc_finish(png_ptr, 0))
01598    {
01599       png_free(png_ptr, purpose);
01600       return;
01601    }
01602 
01603    purpose[slength] = 0x00; /* null terminate the last string */
01604 
01605    png_debug(3, "Finding end of pCAL purpose string\n");
01606    for (buf = purpose; *buf; buf++)
01607       /* empty loop */ ;
01608 
01609    endptr = purpose + slength;
01610 
01611    /* We need to have at least 12 bytes after the purpose string
01612       in order to get the parameter information. */
01613    if (endptr <= buf + 12)
01614    {
01615       png_warning(png_ptr, "Invalid pCAL data");
01616       png_free(png_ptr, purpose);
01617       return;
01618    }
01619 
01620    png_debug(3, "Reading pCAL X0, X1, type, nparams, and units\n");
01621    X0 = png_get_int_32((png_bytep)buf+1);
01622    X1 = png_get_int_32((png_bytep)buf+5);
01623    type = buf[9];
01624    nparams = buf[10];
01625    units = buf + 11;
01626 
01627    png_debug(3, "Checking pCAL equation type and number of parameters\n");
01628    /* Check that we have the right number of parameters for known
01629       equation types. */
01630    if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
01631        (type == PNG_EQUATION_BASE_E && nparams != 3) ||
01632        (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
01633        (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
01634    {
01635       png_warning(png_ptr, "Invalid pCAL parameters for equation type");
01636       png_free(png_ptr, purpose);
01637       return;
01638    }
01639    else if (type >= PNG_EQUATION_LAST)
01640    {
01641       png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
01642    }
01643 
01644    for (buf = units; *buf; buf++)
01645       /* Empty loop to move past the units string. */ ;
01646 
01647    png_debug(3, "Allocating pCAL parameters array\n");
01648    params = (png_charpp)png_malloc_warn(png_ptr, (png_uint_32)(nparams
01649       *png_sizeof(png_charp))) ;
01650    if (params == NULL)
01651      {
01652        png_free(png_ptr, purpose);
01653        png_warning(png_ptr, "No memory for pCAL params.");
01654        return;
01655      }
01656 
01657    /* Get pointers to the start of each parameter string. */
01658    for (i = 0; i < (int)nparams; i++)
01659    {
01660       buf++; /* Skip the null string terminator from previous parameter. */
01661 
01662       png_debug1(3, "Reading pCAL parameter %d\n", i);
01663       for (params[i] = buf; *buf != 0x00 && buf <= endptr; buf++)
01664          /* Empty loop to move past each parameter string */ ;
01665 
01666       /* Make sure we haven't run out of data yet */
01667       if (buf > endptr)
01668       {
01669          png_warning(png_ptr, "Invalid pCAL data");
01670          png_free(png_ptr, purpose);
01671          png_free(png_ptr, params);
01672          return;
01673       }
01674    }
01675 
01676    png_set_pCAL(png_ptr, info_ptr, purpose, X0, X1, type, nparams,
01677       units, params);
01678 
01679    png_free(png_ptr, purpose);
01680    png_free(png_ptr, params);
01681 }
01682 #endif
01683 
01684 #if defined(PNG_READ_sCAL_SUPPORTED)
01685 /* read the sCAL chunk */
01686 void /* PRIVATE */
01687 png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
01688 {
01689    png_charp buffer, ep;
01690 #ifdef PNG_FLOATING_POINT_SUPPORTED
01691    double width, height;
01692    png_charp vp;
01693 #else
01694 #ifdef PNG_FIXED_POINT_SUPPORTED
01695    png_charp swidth, sheight;
01696 #endif
01697 #endif
01698    png_size_t slength;
01699 
01700    png_debug(1, "in png_handle_sCAL\n");
01701 
01702    if (!(png_ptr->mode & PNG_HAVE_IHDR))
01703       png_error(png_ptr, "Missing IHDR before sCAL");
01704    else if (png_ptr->mode & PNG_HAVE_IDAT)
01705    {
01706       png_warning(png_ptr, "Invalid sCAL after IDAT");
01707       png_crc_finish(png_ptr, length);
01708       return;
01709    }
01710    else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
01711    {
01712       png_warning(png_ptr, "Duplicate sCAL chunk");
01713       png_crc_finish(png_ptr, length);
01714       return;
01715    }
01716 
01717    png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)\n",
01718       length + 1);
01719    buffer = (png_charp)png_malloc_warn(png_ptr, length + 1);
01720    if (buffer == NULL)
01721      {
01722        png_warning(png_ptr, "Out of memory while processing sCAL chunk");
01723        return;
01724      }
01725    slength = (png_size_t)length;
01726    png_crc_read(png_ptr, (png_bytep)buffer, slength);
01727 
01728    if (png_crc_finish(png_ptr, 0))
01729    {
01730       png_free(png_ptr, buffer);
01731       return;
01732    }
01733 
01734    buffer[slength] = 0x00; /* null terminate the last string */
01735 
01736    ep = buffer + 1;        /* skip unit byte */
01737 
01738 #ifdef PNG_FLOATING_POINT_SUPPORTED
01739    width = strtod(ep, &vp);
01740    if (*vp)
01741    {
01742        png_warning(png_ptr, "malformed width string in sCAL chunk");
01743        return;
01744    }
01745 #else
01746 #ifdef PNG_FIXED_POINT_SUPPORTED
01747    swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
01748    if (swidth == NULL)
01749      {
01750        png_warning(png_ptr, "Out of memory while processing sCAL chunk width");
01751        return;
01752      }
01753    png_memcpy(swidth, ep, (png_size_t)png_strlen(ep));
01754 #endif
01755 #endif
01756 
01757    for (ep = buffer; *ep; ep++)
01758       /* empty loop */ ;
01759    ep++;
01760 
01761 #ifdef PNG_FLOATING_POINT_SUPPORTED
01762    height = strtod(ep, &vp);
01763    if (*vp)
01764    {
01765        png_warning(png_ptr, "malformed height string in sCAL chunk");
01766        return;
01767    }
01768 #else
01769 #ifdef PNG_FIXED_POINT_SUPPORTED
01770    sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
01771    if (swidth == NULL)
01772      {
01773        png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
01774        return;
01775      }
01776    png_memcpy(sheight, ep, (png_size_t)png_strlen(ep));
01777 #endif
01778 #endif
01779 
01780    if (buffer + slength < ep
01781 #ifdef PNG_FLOATING_POINT_SUPPORTED
01782       || width <= 0. || height <= 0.
01783 #endif
01784       )
01785    {
01786       png_warning(png_ptr, "Invalid sCAL data");
01787       png_free(png_ptr, buffer);
01788 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
01789       png_free(png_ptr, swidth);
01790       png_free(png_ptr, sheight);
01791 #endif
01792       return;
01793    }
01794 
01795 
01796 #ifdef PNG_FLOATING_POINT_SUPPORTED
01797    png_set_sCAL(png_ptr, info_ptr, buffer[0], width, height);
01798 #else
01799 #ifdef PNG_FIXED_POINT_SUPPORTED
01800    png_set_sCAL_s(png_ptr, info_ptr, buffer[0], swidth, sheight);
01801 #endif
01802 #endif
01803 
01804    png_free(png_ptr, buffer);
01805 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
01806    png_free(png_ptr, swidth);
01807    png_free(png_ptr, sheight);
01808 #endif
01809 }
01810 #endif
01811 
01812 #if defined(PNG_READ_tIME_SUPPORTED)
01813 void /* PRIVATE */
01814 png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
01815 {
01816    png_byte buf[7];
01817    png_time mod_time;
01818 
01819    png_debug(1, "in png_handle_tIME\n");
01820 
01821    if (!(png_ptr->mode & PNG_HAVE_IHDR))
01822       png_error(png_ptr, "Out of place tIME chunk");
01823    else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
01824    {
01825       png_warning(png_ptr, "Duplicate tIME chunk");
01826       png_crc_finish(png_ptr, length);
01827       return;
01828    }
01829 
01830    if (png_ptr->mode & PNG_HAVE_IDAT)
01831       png_ptr->mode |= PNG_AFTER_IDAT;
01832 
01833    if (length != 7)
01834    {
01835       png_warning(png_ptr, "Incorrect tIME chunk length");
01836       png_crc_finish(png_ptr, length);
01837       return;
01838    }
01839 
01840    png_crc_read(png_ptr, buf, 7);
01841    if (png_crc_finish(png_ptr, 0))
01842       return;
01843 
01844    mod_time.second = buf[6];
01845    mod_time.minute = buf[5];
01846    mod_time.hour = buf[4];
01847    mod_time.day = buf[3];
01848    mod_time.month = buf[2];
01849    mod_time.year = png_get_uint_16(buf);
01850 
01851    png_set_tIME(png_ptr, info_ptr, &mod_time);
01852 }
01853 #endif
01854 
01855 #if defined(PNG_READ_tEXt_SUPPORTED)
01856 /* Note: this does not properly handle chunks that are > 64K under DOS */
01857 void /* PRIVATE */
01858 png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
01859 {
01860    png_textp text_ptr;
01861    png_charp key;
01862    png_charp text;
01863    png_uint_32 skip = 0;
01864    png_size_t slength;
01865    int ret;
01866 
01867    png_debug(1, "in png_handle_tEXt\n");
01868 
01869    if (!(png_ptr->mode & PNG_HAVE_IHDR))
01870       png_error(png_ptr, "Missing IHDR before tEXt");
01871 
01872    if (png_ptr->mode & PNG_HAVE_IDAT)
01873       png_ptr->mode |= PNG_AFTER_IDAT;
01874 
01875 #ifdef PNG_MAX_MALLOC_64K
01876    if (length > (png_uint_32)65535L)
01877    {
01878       png_warning(png_ptr, "tEXt chunk too large to fit in memory");
01879       skip = length - (png_uint_32)65535L;
01880       length = (png_uint_32)65535L;
01881    }
01882 #endif
01883 
01884    key = (png_charp)png_malloc_warn(png_ptr, length + 1);
01885    if (key == NULL)
01886    {
01887      png_warning(png_ptr, "No memory to process text chunk.");
01888      return;
01889    }
01890    slength = (png_size_t)length;
01891    png_crc_read(png_ptr, (png_bytep)key, slength);
01892 
01893    if (png_crc_finish(png_ptr, skip))
01894    {
01895       png_free(png_ptr, key);
01896       return;
01897    }
01898 
01899    key[slength] = 0x00;
01900 
01901    for (text = key; *text; text++)
01902       /* empty loop to find end of key */ ;
01903 
01904    if (text != key + slength)
01905       text++;
01906 
01907    text_ptr = (png_textp)png_malloc_warn(png_ptr,
01908       (png_uint_32)png_sizeof(png_text));
01909    if (text_ptr == NULL)
01910    {
01911      png_warning(png_ptr, "Not enough memory to process text chunk.");
01912      png_free(png_ptr, key);
01913      return;
01914    }
01915    text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
01916    text_ptr->key = key;
01917 #ifdef PNG_iTXt_SUPPORTED
01918    text_ptr->lang = NULL;
01919    text_ptr->lang_key = NULL;
01920    text_ptr->itxt_length = 0;
01921 #endif
01922    text_ptr->text = text;
01923    text_ptr->text_length = png_strlen(text);
01924 
01925    ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
01926 
01927    png_free(png_ptr, key);
01928    png_free(png_ptr, text_ptr);
01929    if (ret)
01930      png_warning(png_ptr, "Insufficient memory to process text chunk.");
01931 }
01932 #endif
01933 
01934 #if defined(PNG_READ_zTXt_SUPPORTED)
01935 /* note: this does not correctly handle chunks that are > 64K under DOS */
01936 void /* PRIVATE */
01937 png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
01938 {
01939    png_textp text_ptr;
01940    png_charp chunkdata;
01941    png_charp text;
01942    int comp_type;
01943    int ret;
01944    png_size_t slength, prefix_len, data_len;
01945 
01946    png_debug(1, "in png_handle_zTXt\n");
01947    if (!(png_ptr->mode & PNG_HAVE_IHDR))
01948       png_error(png_ptr, "Missing IHDR before zTXt");
01949 
01950    if (png_ptr->mode & PNG_HAVE_IDAT)
01951       png_ptr->mode |= PNG_AFTER_IDAT;
01952 
01953 #ifdef PNG_MAX_MALLOC_64K
01954    /* We will no doubt have problems with chunks even half this size, but
01955       there is no hard and fast rule to tell us where to stop. */
01956    if (length > (png_uint_32)65535L)
01957    {
01958      png_warning(png_ptr,"zTXt chunk too large to fit in memory");
01959      png_crc_finish(png_ptr, length);
01960      return;
01961    }
01962 #endif
01963 
01964    chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
01965    if (chunkdata == NULL)
01966    {
01967      png_warning(png_ptr,"Out of memory processing zTXt chunk.");
01968      return;
01969    }
01970    slength = (png_size_t)length;
01971    png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
01972    if (png_crc_finish(png_ptr, 0))
01973    {
01974       png_free(png_ptr, chunkdata);
01975       return;
01976    }
01977 
01978    chunkdata[slength] = 0x00;
01979 
01980    for (text = chunkdata; *text; text++)
01981       /* empty loop */ ;
01982 
01983    /* zTXt must have some text after the chunkdataword */
01984    if (text == chunkdata + slength)
01985    {
01986       comp_type = PNG_TEXT_COMPRESSION_NONE;
01987       png_warning(png_ptr, "Zero length zTXt chunk");
01988    }
01989    else
01990    {
01991        comp_type = *(++text);
01992        if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
01993        {
01994           png_warning(png_ptr, "Unknown compression type in zTXt chunk");
01995           comp_type = PNG_TEXT_COMPRESSION_zTXt;
01996        }
01997        text++;        /* skip the compression_method byte */
01998    }
01999    prefix_len = text - chunkdata;
02000 
02001    chunkdata = (png_charp)png_decompress_chunk(png_ptr, comp_type, chunkdata,
02002                                     (png_size_t)length, prefix_len, &data_len);
02003 
02004    text_ptr = (png_textp)png_malloc_warn(png_ptr,
02005      (png_uint_32)png_sizeof(png_text));
02006    if (text_ptr == NULL)
02007    {
02008      png_warning(png_ptr,"Not enough memory to process zTXt chunk.");
02009      png_free(png_ptr, chunkdata);
02010      return;
02011    }
02012    text_ptr->compression = comp_type;
02013    text_ptr->key = chunkdata;
02014 #ifdef PNG_iTXt_SUPPORTED
02015    text_ptr->lang = NULL;
02016    text_ptr->lang_key = NULL;
02017    text_ptr->itxt_length = 0;
02018 #endif
02019    text_ptr->text = chunkdata + prefix_len;
02020    text_ptr->text_length = data_len;
02021 
02022    ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
02023 
02024    png_free(png_ptr, text_ptr);
02025    png_free(png_ptr, chunkdata);
02026    if (ret)
02027      png_error(png_ptr, "Insufficient memory to store zTXt chunk.");
02028 }
02029 #endif
02030 
02031 #if defined(PNG_READ_iTXt_SUPPORTED)
02032 /* note: this does not correctly handle chunks that are > 64K under DOS */
02033 void /* PRIVATE */
02034 png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
02035 {
02036    png_textp text_ptr;
02037    png_charp chunkdata;
02038    png_charp key, lang, text, lang_key;
02039    int comp_flag;
02040    int comp_type = 0;
02041    int ret;
02042    png_size_t slength, prefix_len, data_len;
02043 
02044    png_debug(1, "in png_handle_iTXt\n");
02045 
02046    if (!(png_ptr->mode & PNG_HAVE_IHDR))
02047       png_error(png_ptr, "Missing IHDR before iTXt");
02048 
02049    if (png_ptr->mode & PNG_HAVE_IDAT)
02050       png_ptr->mode |= PNG_AFTER_IDAT;
02051 
02052 #ifdef PNG_MAX_MALLOC_64K
02053    /* We will no doubt have problems with chunks even half this size, but
02054       there is no hard and fast rule to tell us where to stop. */
02055    if (length > (png_uint_32)65535L)
02056    {
02057      png_warning(png_ptr,"iTXt chunk too large to fit in memory");
02058      png_crc_finish(png_ptr, length);
02059      return;
02060    }
02061 #endif
02062 
02063    chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
02064    if (chunkdata == NULL)
02065    {
02066      png_warning(png_ptr, "No memory to process iTXt chunk.");
02067      return;
02068    }
02069    slength = (png_size_t)length;
02070    png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
02071    if (png_crc_finish(png_ptr, 0))
02072    {
02073       png_free(png_ptr, chunkdata);
02074       return;
02075    }
02076 
02077    chunkdata[slength] = 0x00;
02078 
02079    for (lang = chunkdata; *lang; lang++)
02080       /* empty loop */ ;
02081    lang++;        /* skip NUL separator */
02082 
02083    /* iTXt must have a language tag (possibly empty), two compression bytes,
02084       translated keyword (possibly empty), and possibly some text after the
02085       keyword */
02086 
02087    if (lang >= chunkdata + slength)
02088    {
02089       comp_flag = PNG_TEXT_COMPRESSION_NONE;
02090       png_warning(png_ptr, "Zero length iTXt chunk");
02091    }
02092    else
02093    {
02094        comp_flag = *lang++;
02095        comp_type = *lang++;
02096    }
02097 
02098    for (lang_key = lang; *lang_key; lang_key++)
02099       /* empty loop */ ;
02100    lang_key++;        /* skip NUL separator */
02101 
02102    for (text = lang_key; *text; text++)
02103       /* empty loop */ ;
02104    text++;        /* skip NUL separator */
02105 
02106    prefix_len = text - chunkdata;
02107 
02108    key=chunkdata;
02109    if (comp_flag)
02110        chunkdata = png_decompress_chunk(png_ptr, comp_type, chunkdata,
02111           (size_t)length, prefix_len, &data_len);
02112    else
02113        data_len=png_strlen(chunkdata + prefix_len);
02114    text_ptr = (png_textp)png_malloc_warn(png_ptr,
02115       (png_uint_32)png_sizeof(png_text));
02116    if (text_ptr == NULL)
02117    {
02118      png_warning(png_ptr,"Not enough memory to process iTXt chunk.");
02119      png_free(png_ptr, chunkdata);
02120      return;
02121    }
02122    text_ptr->compression = (int)comp_flag + 1;
02123    text_ptr->lang_key = chunkdata+(lang_key-key);
02124    text_ptr->lang = chunkdata+(lang-key);
02125    text_ptr->itxt_length = data_len;
02126    text_ptr->text_length = 0;
02127    text_ptr->key = chunkdata;
02128    text_ptr->text = chunkdata + prefix_len;
02129 
02130    ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
02131 
02132    png_free(png_ptr, text_ptr);
02133    png_free(png_ptr, chunkdata);
02134    if (ret)
02135      png_error(png_ptr, "Insufficient memory to store iTXt chunk.");
02136 }
02137 #endif
02138 
02139 /* This function is called when we haven't found a handler for a
02140    chunk.  If there isn't a problem with the chunk itself (ie bad
02141    chunk name, CRC, or a critical chunk), the chunk is silently ignored
02142    -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
02143    case it will be saved away to be written out later. */
02144 void /* PRIVATE */
02145 png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
02146 {
02147    png_uint_32 skip = 0;
02148 
02149    png_debug(1, "in png_handle_unknown\n");
02150 
02151    if (png_ptr->mode & PNG_HAVE_IDAT)
02152    {
02153 #ifdef PNG_USE_LOCAL_ARRAYS
02154       PNG_IDAT;
02155 #endif
02156       if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))  /* not an IDAT */
02157          png_ptr->mode |= PNG_AFTER_IDAT;
02158    }
02159 
02160    png_check_chunk_name(png_ptr, png_ptr->chunk_name);
02161 
02162    if (!(png_ptr->chunk_name[0] & 0x20))
02163    {
02164 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
02165       if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
02166            PNG_HANDLE_CHUNK_ALWAYS
02167 #if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
02168            && png_ptr->read_user_chunk_fn == NULL
02169 #endif
02170         )
02171 #endif
02172           png_chunk_error(png_ptr, "unknown critical chunk");
02173    }
02174 
02175 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
02176    if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
02177    {
02178        png_unknown_chunk chunk;
02179 
02180 #ifdef PNG_MAX_MALLOC_64K
02181        if (length > (png_uint_32)65535L)
02182        {
02183            png_warning(png_ptr, "unknown chunk too large to fit in memory");
02184            skip = length - (png_uint_32)65535L;
02185            length = (png_uint_32)65535L;
02186        }
02187 #endif
02188        png_strcpy((png_charp)chunk.name, (png_charp)png_ptr->chunk_name);
02189        chunk.data = (png_bytep)png_malloc(png_ptr, length);
02190        chunk.size = (png_size_t)length;
02191        png_crc_read(png_ptr, (png_bytep)chunk.data, length);
02192 #if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
02193        if(png_ptr->read_user_chunk_fn != NULL)
02194        {
02195           /* callback to user unknown chunk handler */
02196           if ((*(png_ptr->read_user_chunk_fn)) (png_ptr, &chunk) <= 0)
02197           {
02198              if (!(png_ptr->chunk_name[0] & 0x20))
02199                 if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
02200                      PNG_HANDLE_CHUNK_ALWAYS)
02201                  {
02202                    png_free(png_ptr, chunk.data);
02203                    png_chunk_error(png_ptr, "unknown critical chunk");
02204                  }
02205              png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
02206           }
02207        }
02208        else
02209 #endif
02210           png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
02211        png_free(png_ptr, chunk.data);
02212    }
02213    else
02214 #endif
02215       skip = length;
02216 
02217    png_crc_finish(png_ptr, skip);
02218 
02219 #if !defined(PNG_READ_USER_CHUNKS_SUPPORTED)
02220    if (&info_ptr == NULL) /* quiet compiler warnings about unused info_ptr */
02221       return;
02222 #endif
02223 }
02224 
02225 /* This function is called to verify that a chunk name is valid.
02226    This function can't have the "critical chunk check" incorporated
02227    into it, since in the future we will need to be able to call user
02228    functions to handle unknown critical chunks after we check that
02229    the chunk name itself is valid. */
02230 
02231 #define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
02232 
02233 void /* PRIVATE */
02234 png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
02235 {
02236    png_debug(1, "in png_check_chunk_name\n");
02237    if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
02238        isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
02239    {
02240       png_chunk_error(png_ptr, "invalid chunk type");
02241    }
02242 }
02243 
02244 /* Combines the row recently read in with the existing pixels in the
02245    row.  This routine takes care of alpha and transparency if requested.
02246    This routine also handles the two methods of progressive display
02247    of interlaced images, depending on the mask value.
02248    The mask value describes which pixels are to be combined with
02249    the row.  The pattern always repeats every 8 pixels, so just 8
02250    bits are needed.  A one indicates the pixel is to be combined,
02251    a zero indicates the pixel is to be skipped.  This is in addition
02252    to any alpha or transparency value associated with the pixel.  If
02253    you want all pixels to be combined, pass 0xff (255) in mask.  */
02254 #ifndef PNG_HAVE_ASSEMBLER_COMBINE_ROW
02255 void /* PRIVATE */
02256 png_combine_row(png_structp png_ptr, png_bytep row, int mask)
02257 {
02258    png_debug(1,"in png_combine_row\n");
02259    if (mask == 0xff)
02260    {
02261       png_memcpy(row, png_ptr->row_buf + 1,
02262          PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width));
02263    }
02264    else
02265    {
02266       switch (png_ptr->row_info.pixel_depth)
02267       {
02268          case 1:
02269          {
02270             png_bytep sp = png_ptr->row_buf + 1;
02271             png_bytep dp = row;
02272             int s_inc, s_start, s_end;
02273             int m = 0x80;
02274             int shift;
02275             png_uint_32 i;
02276             png_uint_32 row_width = png_ptr->width;
02277 
02278 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
02279             if (png_ptr->transformations & PNG_PACKSWAP)
02280             {
02281                 s_start = 0;
02282                 s_end = 7;
02283                 s_inc = 1;
02284             }
02285             else
02286 #endif
02287             {
02288                 s_start = 7;
02289                 s_end = 0;
02290                 s_inc = -1;
02291             }
02292 
02293             shift = s_start;
02294 
02295             for (i = 0; i < row_width; i++)
02296             {
02297                if (m & mask)
02298                {
02299                   int value;
02300 
02301                   value = (*sp >> shift) & 0x01;
02302                   *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
02303                   *dp |= (png_byte)(value << shift);
02304                }
02305 
02306                if (shift == s_end)
02307                {
02308                   shift = s_start;
02309                   sp++;
02310                   dp++;
02311                }
02312                else
02313                   shift += s_inc;
02314 
02315                if (m == 1)
02316                   m = 0x80;
02317                else
02318                   m >>= 1;
02319             }
02320             break;
02321          }
02322          case 2:
02323          {
02324             png_bytep sp = png_ptr->row_buf + 1;
02325             png_bytep dp = row;
02326             int s_start, s_end, s_inc;
02327             int m = 0x80;
02328             int shift;
02329             png_uint_32 i;
02330             png_uint_32 row_width = png_ptr->width;
02331             int value;
02332 
02333 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
02334             if (png_ptr->transformations & PNG_PACKSWAP)
02335             {
02336                s_start = 0;
02337                s_end = 6;
02338                s_inc = 2;
02339             }
02340             else
02341 #endif
02342             {
02343                s_start = 6;
02344                s_end = 0;
02345                s_inc = -2;
02346             }
02347 
02348             shift = s_start;
02349 
02350             for (i = 0; i < row_width; i++)
02351             {
02352                if (m & mask)
02353                {
02354                   value = (*sp >> shift) & 0x03;
02355                   *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
02356                   *dp |= (png_byte)(value << shift);
02357                }
02358 
02359                if (shift == s_end)
02360                {
02361                   shift = s_start;
02362                   sp++;
02363                   dp++;
02364                }
02365                else
02366                   shift += s_inc;
02367                if (m == 1)
02368                   m = 0x80;
02369                else
02370                   m >>= 1;
02371             }
02372             break;
02373          }
02374          case 4:
02375          {
02376             png_bytep sp = png_ptr->row_buf + 1;
02377             png_bytep dp = row;
02378             int s_start, s_end, s_inc;
02379             int m = 0x80;
02380             int shift;
02381             png_uint_32 i;
02382             png_uint_32 row_width = png_ptr->width;
02383             int value;
02384 
02385 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
02386             if (png_ptr->transformations & PNG_PACKSWAP)
02387             {
02388                s_start = 0;
02389                s_end = 4;
02390                s_inc = 4;
02391             }
02392             else
02393 #endif
02394             {
02395                s_start = 4;
02396                s_end = 0;
02397                s_inc = -4;
02398             }
02399             shift = s_start;
02400 
02401             for (i = 0; i < row_width; i++)
02402             {
02403                if (m & mask)
02404                {
02405                   value = (*sp >> shift) & 0xf;
02406                   *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
02407                   *dp |= (png_byte)(value << shift);
02408                }
02409 
02410                if (shift == s_end)
02411                {
02412                   shift = s_start;
02413                   sp++;
02414                   dp++;
02415                }
02416                else
02417                   shift += s_inc;
02418                if (m == 1)
02419                   m = 0x80;
02420                else
02421                   m >>= 1;
02422             }
02423             break;
02424          }
02425          default:
02426          {
02427             png_bytep sp = png_ptr->row_buf + 1;
02428             png_bytep dp = row;
02429             png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
02430             png_uint_32 i;
02431             png_uint_32 row_width = png_ptr->width;
02432             png_byte m = 0x80;
02433 
02434 
02435             for (i = 0; i < row_width; i++)
02436             {
02437                if (m & mask)
02438                {
02439                   png_memcpy(dp, sp, pixel_bytes);
02440                }
02441 
02442                sp += pixel_bytes;
02443                dp += pixel_bytes;
02444 
02445                if (m == 1)
02446                   m = 0x80;
02447                else
02448                   m >>= 1;
02449             }
02450             break;
02451          }
02452       }
02453    }
02454 }
02455 #endif /* !PNG_HAVE_ASSEMBLER_COMBINE_ROW */
02456 
02457 #ifdef PNG_READ_INTERLACING_SUPPORTED
02458 #ifndef PNG_HAVE_ASSEMBLER_READ_INTERLACE   /* else in pngvcrd.c, pnggccrd.c */
02459 /* OLD pre-1.0.9 interface:
02460 void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
02461    png_uint_32 transformations)
02462  */
02463 void /* PRIVATE */
02464 png_do_read_interlace(png_structp png_ptr)
02465 {
02466    png_row_infop row_info = &(png_ptr->row_info);
02467    png_bytep row = png_ptr->row_buf + 1;
02468    int pass = png_ptr->pass;
02469    png_uint_32 transformations = png_ptr->transformations;
02470 #ifdef PNG_USE_LOCAL_ARRAYS
02471    /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
02472    /* offset to next interlace block */
02473    const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
02474 #endif
02475 
02476    png_debug(1,"in png_do_read_interlace (stock C version)\n");
02477    if (row != NULL && row_info != NULL)
02478    {
02479       png_uint_32 final_width;
02480 
02481       final_width = row_info->width * png_pass_inc[pass];
02482 
02483       switch (row_info->pixel_depth)
02484       {
02485          case 1:
02486          {
02487             png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
02488             png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
02489             int sshift, dshift;
02490             int s_start, s_end, s_inc;
02491             int jstop = png_pass_inc[pass];
02492             png_byte v;
02493             png_uint_32 i;
02494             int j;
02495 
02496 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
02497             if (transformations & PNG_PACKSWAP)
02498             {
02499                 sshift = (int)((row_info->width + 7) & 0x07);
02500                 dshift = (int)((final_width + 7) & 0x07);
02501                 s_start = 7;
02502                 s_end = 0;
02503                 s_inc = -1;
02504             }
02505             else
02506 #endif
02507             {
02508                 sshift = 7 - (int)((row_info->width + 7) & 0x07);
02509                 dshift = 7 - (int)((final_width + 7) & 0x07);
02510                 s_start = 0;
02511                 s_end = 7;
02512                 s_inc = 1;
02513             }
02514 
02515             for (i = 0; i < row_info->width; i++)
02516             {
02517                v = (png_byte)((*sp >> sshift) & 0x01);
02518                for (j = 0; j < jstop; j++)
02519                {
02520                   *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
02521                   *dp |= (png_byte)(v << dshift);
02522                   if (dshift == s_end)
02523                   {
02524                      dshift = s_start;
02525                      dp--;
02526                   }
02527                   else
02528                      dshift += s_inc;
02529                }
02530                if (sshift == s_end)
02531                {
02532                   sshift = s_start;
02533                   sp--;
02534                }
02535                else
02536                   sshift += s_inc;
02537             }
02538             break;
02539          }
02540          case 2:
02541          {
02542             png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
02543             png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
02544             int sshift, dshift;
02545             int s_start, s_end, s_inc;
02546             int jstop = png_pass_inc[pass];
02547             png_uint_32 i;
02548 
02549 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
02550             if (transformations & PNG_PACKSWAP)
02551             {
02552                sshift = (int)(((row_info->width + 3) & 0x03) << 1);
02553                dshift = (int)(((final_width + 3) & 0x03) << 1);
02554                s_start = 6;
02555                s_end = 0;
02556                s_inc = -2;
02557             }
02558             else
02559 #endif
02560             {
02561                sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
02562                dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
02563                s_start = 0;
02564                s_end = 6;
02565                s_inc = 2;
02566             }
02567 
02568             for (i = 0; i < row_info->width; i++)
02569             {
02570                png_byte v;
02571                int j;
02572 
02573                v = (png_byte)((*sp >> sshift) & 0x03);
02574                for (j = 0; j < jstop; j++)
02575                {
02576                   *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
02577                   *dp |= (png_byte)(v << dshift);
02578                   if (dshift == s_end)
02579                   {
02580                      dshift = s_start;
02581                      dp--;
02582                   }
02583                   else
02584                      dshift += s_inc;
02585                }
02586                if (sshift == s_end)
02587                {
02588                   sshift = s_start;
02589                   sp--;
02590                }
02591                else
02592                   sshift += s_inc;
02593             }
02594             break;
02595          }
02596          case 4:
02597          {
02598             png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
02599             png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
02600             int sshift, dshift;
02601             int s_start, s_end, s_inc;
02602             png_uint_32 i;
02603             int jstop = png_pass_inc[pass];
02604 
02605 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
02606             if (transformations & PNG_PACKSWAP)
02607             {
02608                sshift = (int)(((row_info->width + 1) & 0x01) << 2);
02609                dshift = (int)(((final_width + 1) & 0x01) << 2);
02610                s_start = 4;
02611                s_end = 0;
02612                s_inc = -4;
02613             }
02614             else
02615 #endif
02616             {
02617                sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
02618                dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
02619                s_start = 0;
02620                s_end = 4;
02621                s_inc = 4;
02622             }
02623 
02624             for (i = 0; i < row_info->width; i++)
02625             {
02626                png_byte v = (png_byte)((*sp >> sshift) & 0xf);
02627                int j;
02628 
02629                for (j = 0; j < jstop; j++)
02630                {
02631                   *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
02632                   *dp |= (png_byte)(v << dshift);
02633                   if (dshift == s_end)
02634                   {
02635                      dshift = s_start;
02636                      dp--;
02637                   }
02638                   else
02639                      dshift += s_inc;
02640                }
02641                if (sshift == s_end)
02642                {
02643                   sshift = s_start;
02644                   sp--;
02645                }
02646                else
02647                   sshift += s_inc;
02648             }
02649             break;
02650          }
02651          default:
02652          {
02653             png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
02654             png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes;
02655             png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
02656 
02657             int jstop = png_pass_inc[pass];
02658             png_uint_32 i;
02659 
02660             for (i = 0; i < row_info->width; i++)
02661             {
02662                png_byte v[8];
02663                int j;
02664 
02665                png_memcpy(v, sp, pixel_bytes);
02666                for (j = 0; j < jstop; j++)
02667                {
02668                   png_memcpy(dp, v, pixel_bytes);
02669                   dp -= pixel_bytes;
02670                }
02671                sp -= pixel_bytes;
02672             }
02673             break;
02674          }
02675       }
02676       row_info->width = final_width;
02677       row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,final_width);
02678    }
02679 #if !defined(PNG_READ_PACKSWAP_SUPPORTED)
02680    if (&transformations == NULL) /* silence compiler warning */
02681       return;
02682 #endif
02683 }
02684 #endif /* !PNG_HAVE_ASSEMBLER_READ_INTERLACE */
02685 #endif /* PNG_READ_INTERLACING_SUPPORTED */
02686 
02687 #ifndef PNG_HAVE_ASSEMBLER_READ_FILTER_ROW
02688 void /* PRIVATE */
02689 png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
02690    png_bytep prev_row, int filter)
02691 {
02692    png_debug(1, "in png_read_filter_row\n");
02693    png_debug2(2,"row = %lu, filter = %d\n", png_ptr->row_number, filter);
02694    switch (filter)
02695    {
02696       case PNG_FILTER_VALUE_NONE:
02697          break;
02698       case PNG_FILTER_VALUE_SUB:
02699       {
02700          png_uint_32 i;
02701          png_uint_32 istop = row_info->rowbytes;
02702          png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
02703          png_bytep rp = row + bpp;
02704          png_bytep lp = row;
02705 
02706          for (i = bpp; i < istop; i++)
02707          {
02708             *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
02709             rp++;
02710          }
02711          break;
02712       }
02713       case PNG_FILTER_VALUE_UP:
02714       {
02715          png_uint_32 i;
02716          png_uint_32 istop = row_info->rowbytes;
02717          png_bytep rp = row;
02718          png_bytep pp = prev_row;
02719 
02720          for (i = 0; i < istop; i++)
02721          {
02722             *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
02723             rp++;
02724          }
02725          break;
02726       }
02727       case PNG_FILTER_VALUE_AVG:
02728       {
02729          png_uint_32 i;
02730          png_bytep rp = row;
02731          png_bytep pp = prev_row;
02732          png_bytep lp = row;
02733          png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
02734          png_uint_32 istop = row_info->rowbytes - bpp;
02735 
02736          for (i = 0; i < bpp; i++)
02737          {
02738             *rp = (png_byte)(((int)(*rp) +
02739                ((int)(*pp++) / 2 )) & 0xff);
02740             rp++;
02741          }
02742 
02743          for (i = 0; i < istop; i++)
02744          {
02745             *rp = (png_byte)(((int)(*rp) +
02746                (int)(*pp++ + *lp++) / 2 ) & 0xff);
02747             rp++;
02748          }
02749          break;
02750       }
02751       case PNG_FILTER_VALUE_PAETH:
02752       {
02753          png_uint_32 i;
02754          png_bytep rp = row;
02755          png_bytep pp = prev_row;
02756          png_bytep lp = row;
02757          png_bytep cp = prev_row;
02758          png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
02759          png_uint_32 istop=row_info->rowbytes - bpp;
02760 
02761          for (i = 0; i < bpp; i++)
02762          {
02763             *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
02764             rp++;
02765          }
02766 
02767          for (i = 0; i < istop; i++)   /* use leftover rp,pp */
02768          {
02769             int a, b, c, pa, pb, pc, p;
02770 
02771             a = *lp++;
02772             b = *pp++;
02773             c = *cp++;
02774 
02775             p = b - c;
02776             pc = a - c;
02777 
02778 #ifdef PNG_USE_ABS
02779             pa = abs(p);
02780             pb = abs(pc);
02781             pc = abs(p + pc);
02782 #else
02783             pa = p < 0 ? -p : p;
02784             pb = pc < 0 ? -pc : pc;
02785             pc = (p + pc) < 0 ? -(p + pc) : p + pc;
02786 #endif
02787 
02788             /*
02789                if (pa <= pb && pa <= pc)
02790                   p = a;
02791                else if (pb <= pc)
02792                   p = b;
02793                else
02794                   p = c;
02795              */
02796 
02797             p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
02798 
02799             *rp = (png_byte)(((int)(*rp) + p) & 0xff);
02800             rp++;
02801          }
02802          break;
02803       }
02804       default:
02805          png_warning(png_ptr, "Ignoring bad adaptive filter type");
02806          *row=0;
02807          break;
02808    }
02809 }
02810 #endif /* !PNG_HAVE_ASSEMBLER_READ_FILTER_ROW */
02811 
02812 void /* PRIVATE */
02813 png_read_finish_row(png_structp png_ptr)
02814 {
02815 #ifdef PNG_USE_LOCAL_ARRAYS
02816    /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
02817 
02818    /* start of interlace block */
02819    const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
02820 
02821    /* offset to next interlace block */
02822    const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
02823 
02824    /* start of interlace block in the y direction */
02825    const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
02826 
02827    /* offset to next interlace block in the y direction */
02828    const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
02829 #endif
02830 
02831    png_debug(1, "in png_read_finish_row\n");
02832    png_ptr->row_number++;
02833    if (png_ptr->row_number < png_ptr->num_rows)
02834       return;
02835 
02836    if (png_ptr->interlaced)
02837    {
02838       png_ptr->row_number = 0;
02839       png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
02840       do
02841       {
02842          png_ptr->pass++;
02843          if (png_ptr->pass >= 7)
02844             break;
02845          png_ptr->iwidth = (png_ptr->width +
02846             png_pass_inc[png_ptr->pass] - 1 -
02847             png_pass_start[png_ptr->pass]) /
02848             png_pass_inc[png_ptr->pass];
02849 
02850          png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,
02851             png_ptr->iwidth) + 1;
02852 
02853          if (!(png_ptr->transformations & PNG_INTERLACE))
02854          {
02855             png_ptr->num_rows = (png_ptr->height +
02856                png_pass_yinc[png_ptr->pass] - 1 -
02857                png_pass_ystart[png_ptr->pass]) /
02858                png_pass_yinc[png_ptr->pass];
02859             if (!(png_ptr->num_rows))
02860                continue;
02861          }
02862          else  /* if (png_ptr->transformations & PNG_INTERLACE) */
02863             break;
02864       } while (png_ptr->iwidth == 0);
02865 
02866       if (png_ptr->pass < 7)
02867          return;
02868    }
02869 
02870    if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
02871    {
02872 #ifdef PNG_USE_LOCAL_ARRAYS
02873       PNG_IDAT;
02874 #endif
02875       char extra;
02876       int ret;
02877 
02878       png_ptr->zstream.next_out = (Byte *)&extra;
02879       png_ptr->zstream.avail_out = (uInt)1;
02880       for(;;)
02881       {
02882          if (!(png_ptr->zstream.avail_in))
02883          {
02884             while (!png_ptr->idat_size)
02885             {
02886                png_byte chunk_length[4];
02887 
02888                png_crc_finish(png_ptr, 0);
02889 
02890                png_read_data(png_ptr, chunk_length, 4);
02891                png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length);
02892                png_reset_crc(png_ptr);
02893                png_crc_read(png_ptr, png_ptr->chunk_name, 4);
02894                if (png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4))
02895                   png_error(png_ptr, "Not enough image data");
02896 
02897             }
02898             png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
02899             png_ptr->zstream.next_in = png_ptr->zbuf;
02900             if (png_ptr->zbuf_size > png_ptr->idat_size)
02901                png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
02902             png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
02903             png_ptr->idat_size -= png_ptr->zstream.avail_in;
02904          }
02905          ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
02906          if (ret == Z_STREAM_END)
02907          {
02908             if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
02909                png_ptr->idat_size)
02910                png_warning(png_ptr, "Extra compressed data");
02911             png_ptr->mode |= PNG_AFTER_IDAT;
02912             png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
02913             break;
02914          }
02915          if (ret != Z_OK)
02916             png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
02917                       "Decompression Error");
02918 
02919          if (!(png_ptr->zstream.avail_out))
02920          {
02921             png_warning(png_ptr, "Extra compressed data.");
02922             png_ptr->mode |= PNG_AFTER_IDAT;
02923             png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
02924             break;
02925          }
02926 
02927       }
02928       png_ptr->zstream.avail_out = 0;
02929    }
02930 
02931    if (png_ptr->idat_size || png_ptr->zstream.avail_in)
02932       png_warning(png_ptr, "Extra compression data");
02933 
02934    inflateReset(&png_ptr->zstream);
02935 
02936    png_ptr->mode |= PNG_AFTER_IDAT;
02937 }
02938 
02939 void /* PRIVATE */
02940 png_read_start_row(png_structp png_ptr)
02941 {
02942 #ifdef PNG_USE_LOCAL_ARRAYS
02943    /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
02944 
02945    /* start of interlace block */
02946    const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
02947 
02948    /* offset to next interlace block */
02949    const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
02950 
02951    /* start of interlace block in the y direction */
02952    const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
02953 
02954    /* offset to next interlace block in the y direction */
02955    const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
02956 #endif
02957 
02958    int max_pixel_depth;
02959    png_uint_32 row_bytes;
02960 
02961    png_debug(1, "in png_read_start_row\n");
02962    png_ptr->zstream.avail_in = 0;
02963    png_init_read_transformations(png_ptr);
02964    if (png_ptr->interlaced)
02965    {
02966       if (!(png_ptr->transformations & PNG_INTERLACE))
02967          png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
02968             png_pass_ystart[0]) / png_pass_yinc[0];
02969       else
02970          png_ptr->num_rows = png_ptr->height;
02971 
02972       png_ptr->iwidth = (png_ptr->width +
02973          png_pass_inc[png_ptr->pass] - 1 -
02974          png_pass_start[png_ptr->pass]) /
02975          png_pass_inc[png_ptr->pass];
02976 
02977          row_bytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->iwidth) + 1;
02978 
02979          png_ptr->irowbytes = (png_size_t)row_bytes;
02980          if((png_uint_32)png_ptr->irowbytes != row_bytes)
02981             png_error(png_ptr, "Rowbytes overflow in png_read_start_row");
02982    }
02983    else
02984    {
02985       png_ptr->num_rows = png_ptr->height;
02986       png_ptr->iwidth = png_ptr->width;
02987       png_ptr->irowbytes = png_ptr->rowbytes + 1;
02988    }
02989    max_pixel_depth = png_ptr->pixel_depth;
02990 
02991 #if defined(PNG_READ_PACK_SUPPORTED)
02992    if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
02993       max_pixel_depth = 8;
02994 #endif
02995 
02996 #if defined(PNG_READ_EXPAND_SUPPORTED)
02997    if (png_ptr->transformations & PNG_EXPAND)
02998    {
02999       if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
03000       {
03001          if (png_ptr->num_trans)
03002             max_pixel_depth = 32;
03003          else
03004             max_pixel_depth = 24;
03005       }
03006       else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
03007       {
03008          if (max_pixel_depth < 8)
03009             max_pixel_depth = 8;
03010          if (png_ptr->num_trans)
03011             max_pixel_depth *= 2;
03012       }
03013       else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
03014       {
03015          if (png_ptr->num_trans)
03016          {
03017             max_pixel_depth *= 4;
03018             max_pixel_depth /= 3;
03019          }
03020       }
03021    }
03022 #endif
03023 
03024 #if defined(PNG_READ_FILLER_SUPPORTED)
03025    if (png_ptr->transformations & (PNG_FILLER))
03026    {
03027       if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
03028          max_pixel_depth = 32;
03029       else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
03030       {
03031          if (max_pixel_depth <= 8)
03032             max_pixel_depth = 16;
03033          else
03034             max_pixel_depth = 32;
03035       }
03036       else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
03037       {
03038          if (max_pixel_depth <= 32)
03039             max_pixel_depth = 32;
03040          else
03041             max_pixel_depth = 64;
03042       }
03043    }
03044 #endif
03045 
03046 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
03047    if (png_ptr->transformations & PNG_GRAY_TO_RGB)
03048    {
03049       if (
03050 #if defined(PNG_READ_EXPAND_SUPPORTED)
03051         (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
03052 #endif
03053 #if defined(PNG_READ_FILLER_SUPPORTED)
03054         (png_ptr->transformations & (PNG_FILLER)) ||
03055 #endif
03056         png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
03057       {
03058          if (max_pixel_depth <= 16)
03059             max_pixel_depth = 32;
03060          else
03061             max_pixel_depth = 64;
03062       }
03063       else
03064       {
03065          if (max_pixel_depth <= 8)
03066            {
03067              if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
03068                max_pixel_depth = 32;
03069              else
03070                max_pixel_depth = 24;
03071            }
03072          else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
03073             max_pixel_depth = 64;
03074          else
03075             max_pixel_depth = 48;
03076       }
03077    }
03078 #endif
03079 
03080 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
03081 defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
03082    if(png_ptr->transformations & PNG_USER_TRANSFORM)
03083      {
03084        int user_pixel_depth=png_ptr->user_transform_depth*
03085          png_ptr->user_transform_channels;
03086        if(user_pixel_depth > max_pixel_depth)
03087          max_pixel_depth=user_pixel_depth;
03088      }
03089 #endif
03090 
03091    /* align the width on the next larger 8 pixels.  Mainly used
03092       for interlacing */
03093    row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
03094    /* calculate the maximum bytes needed, adding a byte and a pixel
03095       for safety's sake */
03096    row_bytes = PNG_ROWBYTES(max_pixel_depth,row_bytes) +
03097       1 + ((max_pixel_depth + 7) >> 3);
03098 #ifdef PNG_MAX_MALLOC_64K
03099    if (row_bytes > (png_uint_32)65536L)
03100       png_error(png_ptr, "This image requires a row greater than 64KB");
03101 #endif
03102    png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes+64);
03103    png_ptr->row_buf = png_ptr->big_row_buf+32;
03104 #if defined(PNG_DEBUG) && defined(PNG_USE_PNGGCCRD)
03105    png_ptr->row_buf_size = row_bytes;
03106 #endif
03107 
03108 #ifdef PNG_MAX_MALLOC_64K
03109    if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L)
03110       png_error(png_ptr, "This image requires a row greater than 64KB");
03111 #endif
03112    if ((png_uint_32)png_ptr->rowbytes + 1 > PNG_SIZE_MAX)
03113       png_error(png_ptr, "Row has too many bytes to allocate in memory.");
03114    png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
03115       png_ptr->rowbytes + 1));
03116 
03117    png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
03118 
03119    png_debug1(3, "width = %lu,\n", png_ptr->width);
03120    png_debug1(3, "height = %lu,\n", png_ptr->height);
03121    png_debug1(3, "iwidth = %lu,\n", png_ptr->iwidth);
03122    png_debug1(3, "num_rows = %lu\n", png_ptr->num_rows);
03123    png_debug1(3, "rowbytes = %lu,\n", png_ptr->rowbytes);
03124    png_debug1(3, "irowbytes = %lu,\n", png_ptr->irowbytes);
03125 
03126    png_ptr->flags |= PNG_FLAG_ROW_INIT;
03127 }