fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
  SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation)  

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