pngrutil.c

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

Generated on Tue Jul 5 14:13:31 2011 for ROOT_528-00b_version by  doxygen 1.5.1