Blame pngrutil.c

Packit 0ba690
Packit 0ba690
/* pngrutil.c - utilities to read a PNG file
Packit 0ba690
 *
Packit 0ba690
 * Last changed in libpng 1.2.55 [December 6, 2015]
Packit 0ba690
 * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
Packit 0ba690
 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
Packit 0ba690
 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
Packit 0ba690
 *
Packit 0ba690
 * This code is released under the libpng license.
Packit 0ba690
 * For conditions of distribution and use, see the disclaimer
Packit 0ba690
 * and license in png.h
Packit 0ba690
 *
Packit 0ba690
 * This file contains routines that are only called from within
Packit 0ba690
 * libpng itself during the course of reading an image.
Packit 0ba690
 */
Packit 0ba690
Packit 0ba690
#define PNG_INTERNAL
Packit 0ba690
#define PNG_NO_PEDANTIC_WARNINGS
Packit 0ba690
#include "png.h"
Packit 0ba690
#ifdef PNG_READ_SUPPORTED
Packit 0ba690
Packit 0ba690
#if defined(_WIN32_WCE) && (_WIN32_WCE<0x500)
Packit 0ba690
#  define WIN32_WCE_OLD
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
#ifdef PNG_FLOATING_POINT_SUPPORTED
Packit 0ba690
#  ifdef WIN32_WCE_OLD
Packit 0ba690
/* The strtod() function is not supported on WindowsCE */
Packit 0ba690
__inline double png_strtod(png_structp png_ptr, PNG_CONST char *nptr,
Packit 0ba690
    char **endptr)
Packit 0ba690
{
Packit 0ba690
   double result = 0;
Packit 0ba690
   int len;
Packit 0ba690
   wchar_t *str, *end;
Packit 0ba690
Packit 0ba690
   len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0);
Packit 0ba690
   str = (wchar_t *)png_malloc(png_ptr, len * png_sizeof(wchar_t));
Packit 0ba690
   if ( NULL != str )
Packit 0ba690
   {
Packit 0ba690
      MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len);
Packit 0ba690
      result = wcstod(str, &end;;
Packit 0ba690
      len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL);
Packit 0ba690
      *endptr = (char *)nptr + (png_strlen(nptr) - len + 1);
Packit 0ba690
      png_free(png_ptr, str);
Packit 0ba690
   }
Packit 0ba690
   return result;
Packit 0ba690
}
Packit 0ba690
#  else
Packit 0ba690
#    define png_strtod(p,a,b) strtod(a,b)
Packit 0ba690
#  endif
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
png_uint_32 PNGAPI
Packit 0ba690
png_get_uint_31(png_structp png_ptr, png_bytep buf)
Packit 0ba690
{
Packit 0ba690
#ifdef PNG_READ_BIG_ENDIAN_SUPPORTED
Packit 0ba690
   png_uint_32 i = png_get_uint_32(buf);
Packit 0ba690
#else
Packit 0ba690
   /* Avoid an extra function call by inlining the result. */
Packit 0ba690
   png_uint_32 i = ((png_uint_32)((*(buf    )) & 0xff) << 24) +
Packit 0ba690
                   ((png_uint_32)((*(buf + 1)) & 0xff) << 16) +
Packit 0ba690
                   ((png_uint_32)((*(buf + 2)) & 0xff) <<  8) +
Packit 0ba690
                   ((png_uint_32)((*(buf + 3)) & 0xff)      );
Packit 0ba690
#endif
Packit 0ba690
   if (i > PNG_UINT_31_MAX)
Packit 0ba690
      png_error(png_ptr, "PNG unsigned integer out of range.");
Packit 0ba690
   return (i);
Packit 0ba690
}
Packit 0ba690
#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED
Packit 0ba690
/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
Packit 0ba690
png_uint_32 PNGAPI
Packit 0ba690
png_get_uint_32(png_bytep buf)
Packit 0ba690
{
Packit 0ba690
   png_uint_32 i = ((png_uint_32)((*(buf    )) & 0xff) << 24) +
Packit 0ba690
                   ((png_uint_32)((*(buf + 1)) & 0xff) << 16) +
Packit 0ba690
                   ((png_uint_32)((*(buf + 2)) & 0xff) <<  8) +
Packit 0ba690
                   ((png_uint_32)((*(buf + 3)) & 0xff)      );
Packit 0ba690
Packit 0ba690
   return (i);
Packit 0ba690
}
Packit 0ba690
Packit 0ba690
/* Grab a signed 32-bit integer from a buffer in big-endian format.  The
Packit 0ba690
 * data is stored in the PNG file in two's complement format, and it is
Packit 0ba690
 * assumed that the machine format for signed integers is the same.
Packit 0ba690
 */
Packit 0ba690
png_int_32 PNGAPI
Packit 0ba690
png_get_int_32(png_bytep buf)
Packit 0ba690
{
Packit 0ba690
   png_int_32 i = ((png_int_32)((*(buf    )) & 0xff) << 24) +
Packit 0ba690
                  ((png_int_32)((*(buf + 1)) & 0xff) << 16) +
Packit 0ba690
                  ((png_int_32)((*(buf + 2)) & 0xff) <<  8) +
Packit 0ba690
                  ((png_int_32)((*(buf + 3)) & 0xff)      );
Packit 0ba690
Packit 0ba690
   return (i);
Packit 0ba690
}
Packit 0ba690
Packit 0ba690
/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
Packit 0ba690
png_uint_16 PNGAPI
Packit 0ba690
png_get_uint_16(png_bytep buf)
Packit 0ba690
{
Packit 0ba690
   png_uint_16 i = ((png_uint_16)((*(buf     )) & 0xff) << 8) +
Packit 0ba690
                   ((png_uint_16)((*(buf +  1)) & 0xff)     );
Packit 0ba690
Packit 0ba690
   return (i);
Packit 0ba690
}
Packit 0ba690
#endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */
Packit 0ba690
Packit 0ba690
/* Read the chunk header (length + type name).
Packit 0ba690
 * Put the type name into png_ptr->chunk_name, and return the length.
Packit 0ba690
 */
Packit 0ba690
png_uint_32 /* PRIVATE */
Packit 0ba690
png_read_chunk_header(png_structp png_ptr)
Packit 0ba690
{
Packit 0ba690
   png_byte buf[8];
Packit 0ba690
   png_uint_32 length;
Packit 0ba690
Packit 0ba690
   /* Read the length and the chunk name */
Packit 0ba690
   png_read_data(png_ptr, buf, 8);
Packit 0ba690
   length = png_get_uint_31(png_ptr, buf);
Packit 0ba690
Packit 0ba690
   /* Put the chunk name into png_ptr->chunk_name */
Packit 0ba690
   png_memcpy(png_ptr->chunk_name, buf + 4, 4);
Packit 0ba690
Packit 0ba690
   png_debug2(0, "Reading %s chunk, length = %lu",
Packit 0ba690
      png_ptr->chunk_name, length);
Packit 0ba690
Packit 0ba690
   /* Reset the crc and run it over the chunk name */
Packit 0ba690
   png_reset_crc(png_ptr);
Packit 0ba690
   png_calculate_crc(png_ptr, png_ptr->chunk_name, 4);
Packit 0ba690
Packit 0ba690
   /* Check to see if chunk name is valid */
Packit 0ba690
   png_check_chunk_name(png_ptr, png_ptr->chunk_name);
Packit 0ba690
Packit 0ba690
   return length;
Packit 0ba690
}
Packit 0ba690
Packit 0ba690
/* Read data, and (optionally) run it through the CRC. */
Packit 0ba690
void /* PRIVATE */
Packit 0ba690
png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
Packit 0ba690
{
Packit 0ba690
   if (png_ptr == NULL)
Packit 0ba690
      return;
Packit 0ba690
   png_read_data(png_ptr, buf, length);
Packit 0ba690
   png_calculate_crc(png_ptr, buf, length);
Packit 0ba690
}
Packit 0ba690
Packit 0ba690
/* Optionally skip data and then check the CRC.  Depending on whether we
Packit 0ba690
 * are reading a ancillary or critical chunk, and how the program has set
Packit 0ba690
 * things up, we may calculate the CRC on the data and print a message.
Packit 0ba690
 * Returns '1' if there was a CRC error, '0' otherwise.
Packit 0ba690
 */
Packit 0ba690
int /* PRIVATE */
Packit 0ba690
png_crc_finish(png_structp png_ptr, png_uint_32 skip)
Packit 0ba690
{
Packit 0ba690
   png_size_t i;
Packit 0ba690
   png_size_t istop = png_ptr->zbuf_size;
Packit 0ba690
Packit 0ba690
   for (i = (png_size_t)skip; i > istop; i -= istop)
Packit 0ba690
   {
Packit 0ba690
      png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
Packit 0ba690
   }
Packit 0ba690
   if (i)
Packit 0ba690
   {
Packit 0ba690
      png_crc_read(png_ptr, png_ptr->zbuf, i);
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   if (png_crc_error(png_ptr))
Packit 0ba690
   {
Packit 0ba690
      if (((png_ptr->chunk_name[0] & 0x20) &&                /* Ancillary */
Packit 0ba690
          !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
Packit 0ba690
          (!(png_ptr->chunk_name[0] & 0x20) &&             /* Critical  */
Packit 0ba690
          (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)))
Packit 0ba690
      {
Packit 0ba690
         png_chunk_warning(png_ptr, "CRC error");
Packit 0ba690
      }
Packit 0ba690
      else
Packit 0ba690
      {
Packit 0ba690
         png_chunk_error(png_ptr, "CRC error");
Packit 0ba690
      }
Packit 0ba690
      return (1);
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   return (0);
Packit 0ba690
}
Packit 0ba690
Packit 0ba690
/* Compare the CRC stored in the PNG file with that calculated by libpng from
Packit 0ba690
 * the data it has read thus far.
Packit 0ba690
 */
Packit 0ba690
int /* PRIVATE */
Packit 0ba690
png_crc_error(png_structp png_ptr)
Packit 0ba690
{
Packit 0ba690
   png_byte crc_bytes[4];
Packit 0ba690
   png_uint_32 crc;
Packit 0ba690
   int need_crc = 1;
Packit 0ba690
Packit 0ba690
   if (png_ptr->chunk_name[0] & 0x20)                     /* ancillary */
Packit 0ba690
   {
Packit 0ba690
      if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
Packit 0ba690
          (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
Packit 0ba690
         need_crc = 0;
Packit 0ba690
   }
Packit 0ba690
   else                                                    /* critical */
Packit 0ba690
   {
Packit 0ba690
      if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
Packit 0ba690
         need_crc = 0;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   png_read_data(png_ptr, crc_bytes, 4);
Packit 0ba690
Packit 0ba690
   if (need_crc)
Packit 0ba690
   {
Packit 0ba690
      crc = png_get_uint_32(crc_bytes);
Packit 0ba690
      return ((int)(crc != png_ptr->crc));
Packit 0ba690
   }
Packit 0ba690
   else
Packit 0ba690
      return (0);
Packit 0ba690
}
Packit 0ba690
Packit 0ba690
#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \
Packit 0ba690
    defined(PNG_READ_iCCP_SUPPORTED)
Packit 0ba690
static png_size_t
Packit 0ba690
png_inflate(png_structp png_ptr, const png_byte *data, png_size_t size,
Packit 0ba690
        png_bytep output, png_size_t output_size)
Packit 0ba690
{
Packit 0ba690
   png_size_t count = 0;
Packit 0ba690
Packit 0ba690
   png_ptr->zstream.next_in = (png_bytep)data; /* const_cast: VALID */
Packit 0ba690
   png_ptr->zstream.avail_in = size;
Packit 0ba690
Packit 0ba690
   while (1)
Packit 0ba690
   {
Packit 0ba690
      int ret, avail;
Packit 0ba690
Packit 0ba690
      /* Reset the output buffer each time round - we empty it
Packit 0ba690
       * after every inflate call.
Packit 0ba690
       */
Packit 0ba690
      png_ptr->zstream.next_out = png_ptr->zbuf;
Packit 0ba690
      png_ptr->zstream.avail_out = png_ptr->zbuf_size;
Packit 0ba690
Packit 0ba690
      ret = inflate(&png_ptr->zstream, Z_NO_FLUSH);
Packit 0ba690
      avail = png_ptr->zbuf_size - png_ptr->zstream.avail_out;
Packit 0ba690
Packit 0ba690
      /* First copy/count any new output - but only if we didn't
Packit 0ba690
       * get an error code.
Packit 0ba690
       */
Packit 0ba690
      if ((ret == Z_OK || ret == Z_STREAM_END) && avail > 0)
Packit 0ba690
      {
Packit 0ba690
         if (output != 0 && output_size > count)
Packit 0ba690
         {
Packit 0ba690
            png_size_t copy = output_size - count;
Packit 0ba690
            if ((png_size_t) avail < copy) copy = (png_size_t) avail;
Packit 0ba690
            png_memcpy(output + count, png_ptr->zbuf, copy);
Packit 0ba690
         }
Packit 0ba690
         count += avail;
Packit 0ba690
      }
Packit 0ba690
Packit 0ba690
      if (ret == Z_OK)
Packit 0ba690
         continue;
Packit 0ba690
Packit 0ba690
      /* Termination conditions - always reset the zstream, it
Packit 0ba690
       * must be left in inflateInit state.
Packit 0ba690
       */
Packit 0ba690
      png_ptr->zstream.avail_in = 0;
Packit 0ba690
      inflateReset(&png_ptr->zstream);
Packit 0ba690
Packit 0ba690
      if (ret == Z_STREAM_END)
Packit 0ba690
         return count; /* NOTE: may be zero. */
Packit 0ba690
Packit 0ba690
      /* Now handle the error codes - the API always returns 0
Packit 0ba690
       * and the error message is dumped into the uncompressed
Packit 0ba690
       * buffer if available.
Packit 0ba690
       */
Packit 0ba690
      {
Packit 0ba690
         PNG_CONST char *msg;
Packit 0ba690
         if (png_ptr->zstream.msg != 0)
Packit 0ba690
            msg = png_ptr->zstream.msg;
Packit 0ba690
         else
Packit 0ba690
         {
Packit 0ba690
#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
Packit 0ba690
            char umsg[52];
Packit 0ba690
Packit 0ba690
            switch (ret)
Packit 0ba690
            {
Packit 0ba690
               case Z_BUF_ERROR:
Packit 0ba690
                  msg = "Buffer error in compressed datastream in %s chunk";
Packit 0ba690
                  break;
Packit 0ba690
               case Z_DATA_ERROR:
Packit 0ba690
                  msg = "Data error in compressed datastream in %s chunk";
Packit 0ba690
                  break;
Packit 0ba690
               default:
Packit 0ba690
                  msg = "Incomplete compressed datastream in %s chunk";
Packit 0ba690
                  break;
Packit 0ba690
            }
Packit 0ba690
Packit 0ba690
            png_snprintf(umsg, sizeof umsg, msg, png_ptr->chunk_name);
Packit 0ba690
            msg = umsg;
Packit 0ba690
            png_warning(png_ptr, msg);
Packit 0ba690
#else
Packit 0ba690
            msg = "Damaged compressed datastream in chunk other than IDAT";
Packit 0ba690
#endif
Packit 0ba690
         }
Packit 0ba690
Packit 0ba690
#ifndef PNG_STDIO_SUPPORTED
Packit 0ba690
         png_warning(png_ptr, msg);
Packit 0ba690
#endif
Packit 0ba690
      }
Packit 0ba690
Packit 0ba690
      /* 0 means an error - notice that this code simple ignores
Packit 0ba690
       * zero length compressed chunks as a result.
Packit 0ba690
       */
Packit 0ba690
      return 0;
Packit 0ba690
   }
Packit 0ba690
}
Packit 0ba690
Packit 0ba690
/*
Packit 0ba690
 * Decompress trailing data in a chunk.  The assumption is that chunkdata
Packit 0ba690
 * points at an allocated area holding the contents of a chunk with a
Packit 0ba690
 * trailing compressed part.  What we get back is an allocated area
Packit 0ba690
 * holding the original prefix part and an uncompressed version of the
Packit 0ba690
 * trailing part (the malloc area passed in is freed).
Packit 0ba690
 */
Packit 0ba690
void /* PRIVATE */
Packit 0ba690
png_decompress_chunk(png_structp png_ptr, int comp_type,
Packit 0ba690
    png_size_t chunklength,
Packit 0ba690
    png_size_t prefix_size, png_size_t *newlength)
Packit 0ba690
{
Packit 0ba690
   /* The caller should guarantee this */
Packit 0ba690
   if (prefix_size > chunklength)
Packit 0ba690
   {
Packit 0ba690
      /* The recovery is to delete the chunk. */
Packit 0ba690
      png_warning(png_ptr, "invalid chunklength");
Packit 0ba690
      prefix_size = 0; /* To delete everything */
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   else if (comp_type == PNG_COMPRESSION_TYPE_BASE)
Packit 0ba690
   {
Packit 0ba690
      png_size_t expanded_size = png_inflate(png_ptr,
Packit 0ba690
                (png_bytep)(png_ptr->chunkdata + prefix_size),
Packit 0ba690
                chunklength - prefix_size,
Packit 0ba690
                0/*output*/, 0/*output size*/);
Packit 0ba690
Packit 0ba690
      /* Now check the limits on this chunk - if the limit fails the
Packit 0ba690
       * compressed data will be removed, the prefix will remain.
Packit 0ba690
       */
Packit 0ba690
      if (prefix_size >= (~(png_size_t)0) - 1 ||
Packit 0ba690
         expanded_size >= (~(png_size_t)0) - 1 - prefix_size
Packit 0ba690
#ifdef PNG_USER_CHUNK_MALLOC_MAX
Packit 0ba690
         || ((PNG_USER_CHUNK_MALLOC_MAX > 0) &&
Packit 0ba690
          prefix_size + expanded_size >= PNG_USER_CHUNK_MALLOC_MAX - 1)
Packit 0ba690
#endif
Packit 0ba690
          )
Packit 0ba690
         png_warning(png_ptr, "Exceeded size limit while expanding chunk");
Packit 0ba690
Packit 0ba690
      /* If the size is zero either there was an error and a message
Packit 0ba690
       * has already been output (warning) or the size really is zero
Packit 0ba690
       * and we have nothing to do - the code will exit through the
Packit 0ba690
       * error case below.
Packit 0ba690
       */
Packit 0ba690
      else if (expanded_size > 0)
Packit 0ba690
      {
Packit 0ba690
         /* Success (maybe) - really uncompress the chunk. */
Packit 0ba690
         png_size_t new_size = 0;
Packit 0ba690
Packit 0ba690
         png_charp text = png_malloc_warn(png_ptr,
Packit 0ba690
             prefix_size + expanded_size + 1);
Packit 0ba690
Packit 0ba690
         if (text != NULL)
Packit 0ba690
         {
Packit 0ba690
            png_memcpy(text, png_ptr->chunkdata, prefix_size);
Packit 0ba690
            new_size = png_inflate(png_ptr,
Packit 0ba690
                (png_bytep)(png_ptr->chunkdata + prefix_size),
Packit 0ba690
                chunklength - prefix_size,
Packit 0ba690
                (png_bytep)(text + prefix_size), expanded_size);
Packit 0ba690
            text[prefix_size + expanded_size] = 0; /* just in case */
Packit 0ba690
Packit 0ba690
            if (new_size == expanded_size)
Packit 0ba690
            {
Packit 0ba690
               png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
               png_ptr->chunkdata = text;
Packit 0ba690
               *newlength = prefix_size + expanded_size;
Packit 0ba690
               return; /* The success return! */
Packit 0ba690
            }
Packit 0ba690
Packit 0ba690
            png_warning(png_ptr, "png_inflate logic error");
Packit 0ba690
            png_free(png_ptr, text);
Packit 0ba690
         }
Packit 0ba690
         else
Packit 0ba690
          png_warning(png_ptr, "Not enough memory to decompress chunk.");
Packit 0ba690
      }
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
Packit 0ba690
   {
Packit 0ba690
#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
Packit 0ba690
      char umsg[50];
Packit 0ba690
Packit 0ba690
      png_snprintf(umsg, sizeof umsg, "Unknown zTXt compression type %d",
Packit 0ba690
          comp_type);
Packit 0ba690
      png_warning(png_ptr, umsg);
Packit 0ba690
#else
Packit 0ba690
      png_warning(png_ptr, "Unknown zTXt compression type");
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
      /* The recovery is to simply drop the data. */
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   /* Generic error return - leave the prefix, delete the compressed
Packit 0ba690
    * data, reallocate the chunkdata to remove the potentially large
Packit 0ba690
    * amount of compressed data.
Packit 0ba690
    */
Packit 0ba690
   {
Packit 0ba690
      png_charp text = png_malloc_warn(png_ptr, prefix_size + 1);
Packit 0ba690
      if (text != NULL)
Packit 0ba690
      {
Packit 0ba690
         if (prefix_size > 0)
Packit 0ba690
            png_memcpy(text, png_ptr->chunkdata, prefix_size);
Packit 0ba690
         png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
         png_ptr->chunkdata = text;
Packit 0ba690
Packit 0ba690
         /* This is an extra zero in the 'uncompressed' part. */
Packit 0ba690
         *(png_ptr->chunkdata + prefix_size) = 0x00;
Packit 0ba690
      }
Packit 0ba690
      /* Ignore a malloc error here - it is safe. */
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   *newlength = prefix_size;
Packit 0ba690
}
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
/* Read and check the IDHR chunk */
Packit 0ba690
void /* PRIVATE */
Packit 0ba690
png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Packit 0ba690
{
Packit 0ba690
   png_byte buf[13];
Packit 0ba690
   png_uint_32 width, height;
Packit 0ba690
   int bit_depth, color_type, compression_type, filter_type;
Packit 0ba690
   int interlace_type;
Packit 0ba690
Packit 0ba690
   png_debug(1, "in png_handle_IHDR");
Packit 0ba690
Packit 0ba690
   if (png_ptr->mode & PNG_HAVE_IHDR)
Packit 0ba690
      png_error(png_ptr, "Out of place IHDR");
Packit 0ba690
Packit 0ba690
   /* Check the length */
Packit 0ba690
   if (length != 13)
Packit 0ba690
      png_error(png_ptr, "Invalid IHDR chunk");
Packit 0ba690
Packit 0ba690
   png_ptr->mode |= PNG_HAVE_IHDR;
Packit 0ba690
Packit 0ba690
   png_crc_read(png_ptr, buf, 13);
Packit 0ba690
   png_crc_finish(png_ptr, 0);
Packit 0ba690
Packit 0ba690
   width = png_get_uint_31(png_ptr, buf);
Packit 0ba690
   height = png_get_uint_31(png_ptr, buf + 4);
Packit 0ba690
   bit_depth = buf[8];
Packit 0ba690
   color_type = buf[9];
Packit 0ba690
   compression_type = buf[10];
Packit 0ba690
   filter_type = buf[11];
Packit 0ba690
   interlace_type = buf[12];
Packit 0ba690
Packit 0ba690
   /* Set internal variables */
Packit 0ba690
   png_ptr->width = width;
Packit 0ba690
   png_ptr->height = height;
Packit 0ba690
   png_ptr->bit_depth = (png_byte)bit_depth;
Packit 0ba690
   png_ptr->interlaced = (png_byte)interlace_type;
Packit 0ba690
   png_ptr->color_type = (png_byte)color_type;
Packit 0ba690
#ifdef PNG_MNG_FEATURES_SUPPORTED
Packit 0ba690
   png_ptr->filter_type = (png_byte)filter_type;
Packit 0ba690
#endif
Packit 0ba690
   png_ptr->compression_type = (png_byte)compression_type;
Packit 0ba690
Packit 0ba690
   /* Find number of channels */
Packit 0ba690
   switch (png_ptr->color_type)
Packit 0ba690
   {
Packit 0ba690
      case PNG_COLOR_TYPE_GRAY:
Packit 0ba690
      case PNG_COLOR_TYPE_PALETTE:
Packit 0ba690
         png_ptr->channels = 1;
Packit 0ba690
         break;
Packit 0ba690
Packit 0ba690
      case PNG_COLOR_TYPE_RGB:
Packit 0ba690
         png_ptr->channels = 3;
Packit 0ba690
         break;
Packit 0ba690
Packit 0ba690
      case PNG_COLOR_TYPE_GRAY_ALPHA:
Packit 0ba690
         png_ptr->channels = 2;
Packit 0ba690
         break;
Packit 0ba690
Packit 0ba690
      case PNG_COLOR_TYPE_RGB_ALPHA:
Packit 0ba690
         png_ptr->channels = 4;
Packit 0ba690
         break;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   /* Set up other useful info */
Packit 0ba690
   png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
Packit 0ba690
   png_ptr->channels);
Packit 0ba690
   png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width);
Packit 0ba690
   png_debug1(3, "bit_depth = %d", png_ptr->bit_depth);
Packit 0ba690
   png_debug1(3, "channels = %d", png_ptr->channels);
Packit 0ba690
   png_debug1(3, "rowbytes = %lu", png_ptr->rowbytes);
Packit 0ba690
   png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
Packit 0ba690
      color_type, interlace_type, compression_type, filter_type);
Packit 0ba690
}
Packit 0ba690
Packit 0ba690
/* Read and check the palette */
Packit 0ba690
void /* PRIVATE */
Packit 0ba690
png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Packit 0ba690
{
Packit 0ba690
   png_color palette[PNG_MAX_PALETTE_LENGTH];
Packit 0ba690
   int max_palette_length, num, i;
Packit 0ba690
#ifdef PNG_POINTER_INDEXING_SUPPORTED
Packit 0ba690
   png_colorp pal_ptr;
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
   png_debug(1, "in png_handle_PLTE");
Packit 0ba690
Packit 0ba690
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
Packit 0ba690
      png_error(png_ptr, "Missing IHDR before PLTE");
Packit 0ba690
Packit 0ba690
   else if (png_ptr->mode & PNG_HAVE_IDAT)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Invalid PLTE after IDAT");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   else if (png_ptr->mode & PNG_HAVE_PLTE)
Packit 0ba690
      png_error(png_ptr, "Duplicate PLTE chunk");
Packit 0ba690
Packit 0ba690
   png_ptr->mode |= PNG_HAVE_PLTE;
Packit 0ba690
Packit 0ba690
   if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr,
Packit 0ba690
        "Ignoring PLTE chunk in grayscale PNG");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
#ifndef PNG_READ_OPT_PLTE_SUPPORTED
Packit 0ba690
   if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
Packit 0ba690
   {
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
   if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
Packit 0ba690
   {
Packit 0ba690
      if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
Packit 0ba690
      {
Packit 0ba690
         png_warning(png_ptr, "Invalid palette chunk");
Packit 0ba690
         png_crc_finish(png_ptr, length);
Packit 0ba690
         return;
Packit 0ba690
      }
Packit 0ba690
Packit 0ba690
      else
Packit 0ba690
      {
Packit 0ba690
         png_error(png_ptr, "Invalid palette chunk");
Packit 0ba690
      }
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   /* The cast is safe because 'length' is less than 3*PNG_MAX_PALETTE_LENGTH */
Packit 0ba690
   num = (int)length / 3;
Packit 0ba690
Packit 0ba690
   /* If the palette has 256 or fewer entries but is too large for the bit
Packit 0ba690
    * depth, we don't issue an error, to preserve the behavior of previous
Packit 0ba690
    * libpng versions. We silently truncate the unused extra palette entries
Packit 0ba690
    * here.
Packit 0ba690
    */
Packit 0ba690
   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Packit 0ba690
      max_palette_length = (1 << png_ptr->bit_depth);
Packit 0ba690
   else
Packit 0ba690
      max_palette_length = PNG_MAX_PALETTE_LENGTH;
Packit 0ba690
Packit 0ba690
   if (num > max_palette_length)
Packit 0ba690
      num = max_palette_length;
Packit 0ba690
Packit 0ba690
#ifdef PNG_POINTER_INDEXING_SUPPORTED
Packit 0ba690
   for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
Packit 0ba690
   {
Packit 0ba690
      png_byte buf[3];
Packit 0ba690
Packit 0ba690
      png_crc_read(png_ptr, buf, 3);
Packit 0ba690
      pal_ptr->red = buf[0];
Packit 0ba690
      pal_ptr->green = buf[1];
Packit 0ba690
      pal_ptr->blue = buf[2];
Packit 0ba690
   }
Packit 0ba690
#else
Packit 0ba690
   for (i = 0; i < num; i++)
Packit 0ba690
   {
Packit 0ba690
      png_byte buf[3];
Packit 0ba690
Packit 0ba690
      png_crc_read(png_ptr, buf, 3);
Packit 0ba690
      /* Don't depend upon png_color being any order */
Packit 0ba690
      palette[i].red = buf[0];
Packit 0ba690
      palette[i].green = buf[1];
Packit 0ba690
      palette[i].blue = buf[2];
Packit 0ba690
   }
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
   /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
Packit 0ba690
    * whatever the normal CRC configuration tells us.  However, if we
Packit 0ba690
    * have an RGB image, the PLTE can be considered ancillary, so
Packit 0ba690
    * we will act as though it is.
Packit 0ba690
    */
Packit 0ba690
#ifndef PNG_READ_OPT_PLTE_SUPPORTED
Packit 0ba690
   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Packit 0ba690
#endif
Packit 0ba690
   {
Packit 0ba690
      png_crc_finish(png_ptr, (int) length - num * 3);
Packit 0ba690
   }
Packit 0ba690
#ifndef PNG_READ_OPT_PLTE_SUPPORTED
Packit 0ba690
   else if (png_crc_error(png_ptr))  /* Only if we have a CRC error */
Packit 0ba690
   {
Packit 0ba690
      /* If we don't want to use the data from an ancillary chunk,
Packit 0ba690
         we have two options: an error abort, or a warning and we
Packit 0ba690
         ignore the data in this chunk (which should be OK, since
Packit 0ba690
         it's considered ancillary for a RGB or RGBA image). */
Packit 0ba690
      if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
Packit 0ba690
      {
Packit 0ba690
         if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
Packit 0ba690
         {
Packit 0ba690
            png_chunk_error(png_ptr, "CRC error");
Packit 0ba690
         }
Packit 0ba690
         else
Packit 0ba690
         {
Packit 0ba690
            png_chunk_warning(png_ptr, "CRC error");
Packit 0ba690
            return;
Packit 0ba690
         }
Packit 0ba690
      }
Packit 0ba690
      /* Otherwise, we (optionally) emit a warning and use the chunk. */
Packit 0ba690
      else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
Packit 0ba690
      {
Packit 0ba690
         png_chunk_warning(png_ptr, "CRC error");
Packit 0ba690
      }
Packit 0ba690
   }
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
   png_set_PLTE(png_ptr, info_ptr, palette, num);
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_tRNS_SUPPORTED
Packit 0ba690
   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Packit 0ba690
   {
Packit 0ba690
      if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
Packit 0ba690
      {
Packit 0ba690
         if (png_ptr->num_trans > (png_uint_16)num)
Packit 0ba690
         {
Packit 0ba690
            png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
Packit 0ba690
            png_ptr->num_trans = (png_uint_16)num;
Packit 0ba690
         }
Packit 0ba690
         if (info_ptr->num_trans > (png_uint_16)num)
Packit 0ba690
         {
Packit 0ba690
            png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
Packit 0ba690
            info_ptr->num_trans = (png_uint_16)num;
Packit 0ba690
         }
Packit 0ba690
      }
Packit 0ba690
   }
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
}
Packit 0ba690
Packit 0ba690
void /* PRIVATE */
Packit 0ba690
png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Packit 0ba690
{
Packit 0ba690
   png_debug(1, "in png_handle_IEND");
Packit 0ba690
Packit 0ba690
   if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
Packit 0ba690
   {
Packit 0ba690
      png_error(png_ptr, "No image in file");
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
Packit 0ba690
Packit 0ba690
   if (length != 0)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Incorrect IEND chunk length");
Packit 0ba690
   }
Packit 0ba690
   png_crc_finish(png_ptr, length);
Packit 0ba690
Packit 0ba690
   PNG_UNUSED(info_ptr) /* Quiet compiler warnings about unused info_ptr */
Packit 0ba690
}
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_gAMA_SUPPORTED
Packit 0ba690
void /* PRIVATE */
Packit 0ba690
png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Packit 0ba690
{
Packit 0ba690
   png_fixed_point igamma;
Packit 0ba690
#ifdef PNG_FLOATING_POINT_SUPPORTED
Packit 0ba690
   float file_gamma;
Packit 0ba690
#endif
Packit 0ba690
   png_byte buf[4];
Packit 0ba690
Packit 0ba690
   png_debug(1, "in png_handle_gAMA");
Packit 0ba690
Packit 0ba690
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
Packit 0ba690
      png_error(png_ptr, "Missing IHDR before gAMA");
Packit 0ba690
   else if (png_ptr->mode & PNG_HAVE_IDAT)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Invalid gAMA after IDAT");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
   else if (png_ptr->mode & PNG_HAVE_PLTE)
Packit 0ba690
      /* Should be an error, but we can cope with it */
Packit 0ba690
      png_warning(png_ptr, "Out of place gAMA chunk");
Packit 0ba690
Packit 0ba690
   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
Packit 0ba690
#ifdef PNG_READ_sRGB_SUPPORTED
Packit 0ba690
      && !(info_ptr->valid & PNG_INFO_sRGB)
Packit 0ba690
#endif
Packit 0ba690
      )
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Duplicate gAMA chunk");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   if (length != 4)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Incorrect gAMA chunk length");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   png_crc_read(png_ptr, buf, 4);
Packit 0ba690
   if (png_crc_finish(png_ptr, 0))
Packit 0ba690
      return;
Packit 0ba690
Packit 0ba690
   igamma = (png_fixed_point)png_get_uint_32(buf);
Packit 0ba690
   /* Check for zero gamma */
Packit 0ba690
   if (igamma == 0)
Packit 0ba690
      {
Packit 0ba690
         png_warning(png_ptr,
Packit 0ba690
           "Ignoring gAMA chunk with gamma=0");
Packit 0ba690
         return;
Packit 0ba690
      }
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_sRGB_SUPPORTED
Packit 0ba690
   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
Packit 0ba690
      if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
Packit 0ba690
      {
Packit 0ba690
         png_warning(png_ptr,
Packit 0ba690
           "Ignoring incorrect gAMA value when sRGB is also present");
Packit 0ba690
#ifdef PNG_CONSOLE_IO_SUPPORTED
Packit 0ba690
         fprintf(stderr, "gamma = (%d/100000)", (int)igamma);
Packit 0ba690
#endif
Packit 0ba690
         return;
Packit 0ba690
      }
Packit 0ba690
#endif /* PNG_READ_sRGB_SUPPORTED */
Packit 0ba690
Packit 0ba690
#ifdef PNG_FLOATING_POINT_SUPPORTED
Packit 0ba690
   file_gamma = (float)igamma / (float)100000.0;
Packit 0ba690
#  ifdef PNG_READ_GAMMA_SUPPORTED
Packit 0ba690
     png_ptr->gamma = file_gamma;
Packit 0ba690
#  endif
Packit 0ba690
     png_set_gAMA(png_ptr, info_ptr, file_gamma);
Packit 0ba690
#endif
Packit 0ba690
#ifdef PNG_FIXED_POINT_SUPPORTED
Packit 0ba690
   png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
Packit 0ba690
#endif
Packit 0ba690
}
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_sBIT_SUPPORTED
Packit 0ba690
void /* PRIVATE */
Packit 0ba690
png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Packit 0ba690
{
Packit 0ba690
   png_size_t truelen;
Packit 0ba690
   png_byte buf[4];
Packit 0ba690
Packit 0ba690
   png_debug(1, "in png_handle_sBIT");
Packit 0ba690
Packit 0ba690
   buf[0] = buf[1] = buf[2] = buf[3] = 0;
Packit 0ba690
Packit 0ba690
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
Packit 0ba690
      png_error(png_ptr, "Missing IHDR before sBIT");
Packit 0ba690
   else if (png_ptr->mode & PNG_HAVE_IDAT)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Invalid sBIT after IDAT");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
   else if (png_ptr->mode & PNG_HAVE_PLTE)
Packit 0ba690
   {
Packit 0ba690
      /* Should be an error, but we can cope with it */
Packit 0ba690
      png_warning(png_ptr, "Out of place sBIT chunk");
Packit 0ba690
   }
Packit 0ba690
   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Duplicate sBIT chunk");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Packit 0ba690
      truelen = 3;
Packit 0ba690
   else
Packit 0ba690
      truelen = (png_size_t)png_ptr->channels;
Packit 0ba690
Packit 0ba690
   if (length != truelen || length > 4)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Incorrect sBIT chunk length");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   png_crc_read(png_ptr, buf, truelen);
Packit 0ba690
   if (png_crc_finish(png_ptr, 0))
Packit 0ba690
      return;
Packit 0ba690
Packit 0ba690
   if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
Packit 0ba690
   {
Packit 0ba690
      png_ptr->sig_bit.red = buf[0];
Packit 0ba690
      png_ptr->sig_bit.green = buf[1];
Packit 0ba690
      png_ptr->sig_bit.blue = buf[2];
Packit 0ba690
      png_ptr->sig_bit.alpha = buf[3];
Packit 0ba690
   }
Packit 0ba690
   else
Packit 0ba690
   {
Packit 0ba690
      png_ptr->sig_bit.gray = buf[0];
Packit 0ba690
      png_ptr->sig_bit.red = buf[0];
Packit 0ba690
      png_ptr->sig_bit.green = buf[0];
Packit 0ba690
      png_ptr->sig_bit.blue = buf[0];
Packit 0ba690
      png_ptr->sig_bit.alpha = buf[1];
Packit 0ba690
   }
Packit 0ba690
   png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
Packit 0ba690
}
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_cHRM_SUPPORTED
Packit 0ba690
void /* PRIVATE */
Packit 0ba690
png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Packit 0ba690
{
Packit 0ba690
   png_byte buf[32];
Packit 0ba690
#ifdef PNG_FLOATING_POINT_SUPPORTED
Packit 0ba690
   float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
Packit 0ba690
#endif
Packit 0ba690
   png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
Packit 0ba690
      int_y_green, int_x_blue, int_y_blue;
Packit 0ba690
Packit 0ba690
   png_uint_32 uint_x, uint_y;
Packit 0ba690
Packit 0ba690
   png_debug(1, "in png_handle_cHRM");
Packit 0ba690
Packit 0ba690
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
Packit 0ba690
      png_error(png_ptr, "Missing IHDR before cHRM");
Packit 0ba690
   else if (png_ptr->mode & PNG_HAVE_IDAT)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Invalid cHRM after IDAT");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
   else if (png_ptr->mode & PNG_HAVE_PLTE)
Packit 0ba690
      /* Should be an error, but we can cope with it */
Packit 0ba690
      png_warning(png_ptr, "Missing PLTE before cHRM");
Packit 0ba690
Packit 0ba690
   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
Packit 0ba690
#ifdef PNG_READ_sRGB_SUPPORTED
Packit 0ba690
      && !(info_ptr->valid & PNG_INFO_sRGB)
Packit 0ba690
#endif
Packit 0ba690
      )
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Duplicate cHRM chunk");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   if (length != 32)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Incorrect cHRM chunk length");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   png_crc_read(png_ptr, buf, 32);
Packit 0ba690
   if (png_crc_finish(png_ptr, 0))
Packit 0ba690
      return;
Packit 0ba690
Packit 0ba690
   uint_x = png_get_uint_32(buf);
Packit 0ba690
   uint_y = png_get_uint_32(buf + 4);
Packit 0ba690
   int_x_white = (png_fixed_point)uint_x;
Packit 0ba690
   int_y_white = (png_fixed_point)uint_y;
Packit 0ba690
Packit 0ba690
   uint_x = png_get_uint_32(buf + 8);
Packit 0ba690
   uint_y = png_get_uint_32(buf + 12);
Packit 0ba690
   int_x_red = (png_fixed_point)uint_x;
Packit 0ba690
   int_y_red = (png_fixed_point)uint_y;
Packit 0ba690
Packit 0ba690
   uint_x = png_get_uint_32(buf + 16);
Packit 0ba690
   uint_y = png_get_uint_32(buf + 20);
Packit 0ba690
   int_x_green = (png_fixed_point)uint_x;
Packit 0ba690
   int_y_green = (png_fixed_point)uint_y;
Packit 0ba690
Packit 0ba690
   uint_x = png_get_uint_32(buf + 24);
Packit 0ba690
   uint_y = png_get_uint_32(buf + 28);
Packit 0ba690
   int_x_blue = (png_fixed_point)uint_x;
Packit 0ba690
   int_y_blue = (png_fixed_point)uint_y;
Packit 0ba690
Packit 0ba690
#ifdef PNG_FLOATING_POINT_SUPPORTED
Packit 0ba690
   white_x = (float)int_x_white / (float)100000.0;
Packit 0ba690
   white_y = (float)int_y_white / (float)100000.0;
Packit 0ba690
   red_x   = (float)int_x_red   / (float)100000.0;
Packit 0ba690
   red_y   = (float)int_y_red   / (float)100000.0;
Packit 0ba690
   green_x = (float)int_x_green / (float)100000.0;
Packit 0ba690
   green_y = (float)int_y_green / (float)100000.0;
Packit 0ba690
   blue_x  = (float)int_x_blue  / (float)100000.0;
Packit 0ba690
   blue_y  = (float)int_y_blue  / (float)100000.0;
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_sRGB_SUPPORTED
Packit 0ba690
   if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB))
Packit 0ba690
      {
Packit 0ba690
      if (PNG_OUT_OF_RANGE(int_x_white, 31270,  1000) ||
Packit 0ba690
          PNG_OUT_OF_RANGE(int_y_white, 32900,  1000) ||
Packit 0ba690
          PNG_OUT_OF_RANGE(int_x_red,   64000L, 1000) ||
Packit 0ba690
          PNG_OUT_OF_RANGE(int_y_red,   33000,  1000) ||
Packit 0ba690
          PNG_OUT_OF_RANGE(int_x_green, 30000,  1000) ||
Packit 0ba690
          PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) ||
Packit 0ba690
          PNG_OUT_OF_RANGE(int_x_blue,  15000,  1000) ||
Packit 0ba690
          PNG_OUT_OF_RANGE(int_y_blue,   6000,  1000))
Packit 0ba690
         {
Packit 0ba690
            png_warning(png_ptr,
Packit 0ba690
              "Ignoring incorrect cHRM value when sRGB is also present");
Packit 0ba690
#ifdef PNG_CONSOLE_IO_SUPPORTED
Packit 0ba690
#ifdef PNG_FLOATING_POINT_SUPPORTED
Packit 0ba690
            fprintf(stderr, "wx=%f, wy=%f, rx=%f, ry=%f\n",
Packit 0ba690
               white_x, white_y, red_x, red_y);
Packit 0ba690
            fprintf(stderr, "gx=%f, gy=%f, bx=%f, by=%f\n",
Packit 0ba690
               green_x, green_y, blue_x, blue_y);
Packit 0ba690
#else
Packit 0ba690
            fprintf(stderr, "wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
Packit 0ba690
               (long)int_x_white, (long)int_y_white,
Packit 0ba690
               (long)int_x_red, (long)int_y_red);
Packit 0ba690
            fprintf(stderr, "gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
Packit 0ba690
               (long)int_x_green, (long)int_y_green,
Packit 0ba690
               (long)int_x_blue, (long)int_y_blue);
Packit 0ba690
#endif
Packit 0ba690
#endif /* PNG_CONSOLE_IO_SUPPORTED */
Packit 0ba690
         }
Packit 0ba690
         return;
Packit 0ba690
      }
Packit 0ba690
#endif /* PNG_READ_sRGB_SUPPORTED */
Packit 0ba690
Packit 0ba690
#ifdef PNG_FLOATING_POINT_SUPPORTED
Packit 0ba690
   png_set_cHRM(png_ptr, info_ptr,
Packit 0ba690
      white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
Packit 0ba690
#endif
Packit 0ba690
#ifdef PNG_FIXED_POINT_SUPPORTED
Packit 0ba690
   png_set_cHRM_fixed(png_ptr, info_ptr,
Packit 0ba690
      int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
Packit 0ba690
      int_y_green, int_x_blue, int_y_blue);
Packit 0ba690
#endif
Packit 0ba690
}
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_sRGB_SUPPORTED
Packit 0ba690
void /* PRIVATE */
Packit 0ba690
png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Packit 0ba690
{
Packit 0ba690
   int intent;
Packit 0ba690
   png_byte buf[1];
Packit 0ba690
Packit 0ba690
   png_debug(1, "in png_handle_sRGB");
Packit 0ba690
Packit 0ba690
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
Packit 0ba690
      png_error(png_ptr, "Missing IHDR before sRGB");
Packit 0ba690
   else if (png_ptr->mode & PNG_HAVE_IDAT)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Invalid sRGB after IDAT");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
   else if (png_ptr->mode & PNG_HAVE_PLTE)
Packit 0ba690
      /* Should be an error, but we can cope with it */
Packit 0ba690
      png_warning(png_ptr, "Out of place sRGB chunk");
Packit 0ba690
Packit 0ba690
   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Duplicate sRGB chunk");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   if (length != 1)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Incorrect sRGB chunk length");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   png_crc_read(png_ptr, buf, 1);
Packit 0ba690
   if (png_crc_finish(png_ptr, 0))
Packit 0ba690
      return;
Packit 0ba690
Packit 0ba690
   intent = buf[0];
Packit 0ba690
   /* Check for bad intent */
Packit 0ba690
   if (intent >= PNG_sRGB_INTENT_LAST)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Unknown sRGB intent");
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
Packit 0ba690
   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA))
Packit 0ba690
   {
Packit 0ba690
   png_fixed_point igamma;
Packit 0ba690
#ifdef PNG_FIXED_POINT_SUPPORTED
Packit 0ba690
      igamma=info_ptr->int_gamma;
Packit 0ba690
#else
Packit 0ba690
#  ifdef PNG_FLOATING_POINT_SUPPORTED
Packit 0ba690
      igamma=(png_fixed_point)(info_ptr->gamma * 100000.);
Packit 0ba690
#  endif
Packit 0ba690
#endif
Packit 0ba690
      if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
Packit 0ba690
      {
Packit 0ba690
         png_warning(png_ptr,
Packit 0ba690
           "Ignoring incorrect gAMA value when sRGB is also present");
Packit 0ba690
#ifdef PNG_CONSOLE_IO_SUPPORTED
Packit 0ba690
#  ifdef PNG_FIXED_POINT_SUPPORTED
Packit 0ba690
         fprintf(stderr, "incorrect gamma=(%d/100000)\n",
Packit 0ba690
            (int)png_ptr->int_gamma);
Packit 0ba690
#  else
Packit 0ba690
#    ifdef PNG_FLOATING_POINT_SUPPORTED
Packit 0ba690
         fprintf(stderr, "incorrect gamma=%f\n", png_ptr->gamma);
Packit 0ba690
#    endif
Packit 0ba690
#  endif
Packit 0ba690
#endif
Packit 0ba690
      }
Packit 0ba690
   }
Packit 0ba690
#endif /* PNG_READ_gAMA_SUPPORTED */
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_cHRM_SUPPORTED
Packit 0ba690
#ifdef PNG_FIXED_POINT_SUPPORTED
Packit 0ba690
   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
Packit 0ba690
      if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270,  1000) ||
Packit 0ba690
          PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900,  1000) ||
Packit 0ba690
          PNG_OUT_OF_RANGE(info_ptr->int_x_red,   64000L, 1000) ||
Packit 0ba690
          PNG_OUT_OF_RANGE(info_ptr->int_y_red,   33000,  1000) ||
Packit 0ba690
          PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000,  1000) ||
Packit 0ba690
          PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) ||
Packit 0ba690
          PNG_OUT_OF_RANGE(info_ptr->int_x_blue,  15000,  1000) ||
Packit 0ba690
          PNG_OUT_OF_RANGE(info_ptr->int_y_blue,   6000,  1000))
Packit 0ba690
         {
Packit 0ba690
            png_warning(png_ptr,
Packit 0ba690
              "Ignoring incorrect cHRM value when sRGB is also present");
Packit 0ba690
         }
Packit 0ba690
#endif /* PNG_FIXED_POINT_SUPPORTED */
Packit 0ba690
#endif /* PNG_READ_cHRM_SUPPORTED */
Packit 0ba690
Packit 0ba690
   png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
Packit 0ba690
}
Packit 0ba690
#endif /* PNG_READ_sRGB_SUPPORTED */
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_iCCP_SUPPORTED
Packit 0ba690
void /* PRIVATE */
Packit 0ba690
png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Packit 0ba690
/* Note: this does not properly handle chunks that are > 64K under DOS */
Packit 0ba690
{
Packit 0ba690
   png_byte compression_type;
Packit 0ba690
   png_bytep pC;
Packit 0ba690
   png_charp profile;
Packit 0ba690
   png_uint_32 skip = 0;
Packit 0ba690
   png_uint_32 profile_size, profile_length;
Packit 0ba690
   png_size_t slength, prefix_length, data_length;
Packit 0ba690
Packit 0ba690
   png_debug(1, "in png_handle_iCCP");
Packit 0ba690
Packit 0ba690
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
Packit 0ba690
      png_error(png_ptr, "Missing IHDR before iCCP");
Packit 0ba690
   else if (png_ptr->mode & PNG_HAVE_IDAT)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Invalid iCCP after IDAT");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
   else if (png_ptr->mode & PNG_HAVE_PLTE)
Packit 0ba690
      /* Should be an error, but we can cope with it */
Packit 0ba690
      png_warning(png_ptr, "Out of place iCCP chunk");
Packit 0ba690
Packit 0ba690
   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Duplicate iCCP chunk");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
#ifdef PNG_MAX_MALLOC_64K
Packit 0ba690
   if (length > (png_uint_32)65535L)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "iCCP chunk too large to fit in memory");
Packit 0ba690
      skip = length - (png_uint_32)65535L;
Packit 0ba690
      length = (png_uint_32)65535L;
Packit 0ba690
   }
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
   png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
   png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
Packit 0ba690
   slength = (png_size_t)length;
Packit 0ba690
   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
Packit 0ba690
Packit 0ba690
   if (png_crc_finish(png_ptr, skip))
Packit 0ba690
   {
Packit 0ba690
      png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
      png_ptr->chunkdata = NULL;
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   png_ptr->chunkdata[slength] = 0x00;
Packit 0ba690
Packit 0ba690
   for (profile = png_ptr->chunkdata; *profile; profile++)
Packit 0ba690
      /* Empty loop to find end of name */ ;
Packit 0ba690
Packit 0ba690
   ++profile;
Packit 0ba690
Packit 0ba690
   /* There should be at least one zero (the compression type byte)
Packit 0ba690
    * following the separator, and we should be on it
Packit 0ba690
    */
Packit 0ba690
   if (slength < 1U ||  profile >= png_ptr->chunkdata + slength - 1U)
Packit 0ba690
   {
Packit 0ba690
      png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
      png_ptr->chunkdata = NULL;
Packit 0ba690
      png_warning(png_ptr, "Malformed iCCP chunk");
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   /* Compression_type should always be zero */
Packit 0ba690
   compression_type = *profile++;
Packit 0ba690
   if (compression_type)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
Packit 0ba690
      compression_type = 0x00;  /* Reset it to zero (libpng-1.0.6 through 1.0.8
Packit 0ba690
                                 wrote nonzero) */
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   prefix_length = profile - png_ptr->chunkdata;
Packit 0ba690
   png_decompress_chunk(png_ptr, compression_type,
Packit 0ba690
     slength, prefix_length, &data_length);
Packit 0ba690
Packit 0ba690
   profile_length = data_length - prefix_length;
Packit 0ba690
Packit 0ba690
   if ( prefix_length > data_length || profile_length < 4)
Packit 0ba690
   {
Packit 0ba690
      png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
      png_ptr->chunkdata = NULL;
Packit 0ba690
      png_warning(png_ptr, "Profile size field missing from iCCP chunk");
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   /* Check the profile_size recorded in the first 32 bits of the ICC profile */
Packit 0ba690
   pC = (png_bytep)(png_ptr->chunkdata + prefix_length);
Packit 0ba690
   profile_size = ((png_uint_32) (*(pC    )<<24)) |
Packit 0ba690
                  ((png_uint_32) (*(pC + 1)<<16)) |
Packit 0ba690
                  ((png_uint_32) (*(pC + 2)<< 8)) |
Packit 0ba690
                  ((png_uint_32) (*(pC + 3)    ));
Packit 0ba690
Packit 0ba690
   if (profile_size < profile_length)
Packit 0ba690
      profile_length = profile_size;
Packit 0ba690
Packit 0ba690
   if (profile_size > profile_length)
Packit 0ba690
   {
Packit 0ba690
      png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
      png_ptr->chunkdata = NULL;
Packit 0ba690
      png_warning(png_ptr, "Ignoring truncated iCCP profile.");
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata,
Packit 0ba690
     compression_type, png_ptr->chunkdata + prefix_length, profile_length);
Packit 0ba690
   png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
   png_ptr->chunkdata = NULL;
Packit 0ba690
}
Packit 0ba690
#endif /* PNG_READ_iCCP_SUPPORTED */
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_sPLT_SUPPORTED
Packit 0ba690
void /* PRIVATE */
Packit 0ba690
png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Packit 0ba690
/* Note: this does not properly handle chunks that are > 64K under DOS */
Packit 0ba690
{
Packit 0ba690
   png_bytep entry_start;
Packit 0ba690
   png_sPLT_t new_palette;
Packit 0ba690
#ifdef PNG_POINTER_INDEXING_SUPPORTED
Packit 0ba690
   png_sPLT_entryp pp;
Packit 0ba690
#endif
Packit 0ba690
   int data_length, entry_size, i;
Packit 0ba690
   png_uint_32 skip = 0;
Packit 0ba690
   png_size_t slength;
Packit 0ba690
Packit 0ba690
   png_debug(1, "in png_handle_sPLT");
Packit 0ba690
Packit 0ba690
#ifdef PNG_USER_LIMITS_SUPPORTED
Packit 0ba690
Packit 0ba690
   if (png_ptr->user_chunk_cache_max != 0)
Packit 0ba690
   {
Packit 0ba690
      if (png_ptr->user_chunk_cache_max == 1)
Packit 0ba690
      {
Packit 0ba690
         png_crc_finish(png_ptr, length);
Packit 0ba690
         return;
Packit 0ba690
      }
Packit 0ba690
      if (--png_ptr->user_chunk_cache_max == 1)
Packit 0ba690
      {
Packit 0ba690
         png_warning(png_ptr, "No space in chunk cache for sPLT");
Packit 0ba690
         png_crc_finish(png_ptr, length);
Packit 0ba690
         return;
Packit 0ba690
      }
Packit 0ba690
   }
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
Packit 0ba690
      png_error(png_ptr, "Missing IHDR before sPLT");
Packit 0ba690
   else if (png_ptr->mode & PNG_HAVE_IDAT)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Invalid sPLT after IDAT");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
#ifdef PNG_MAX_MALLOC_64K
Packit 0ba690
   if (length > (png_uint_32)65535L)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "sPLT chunk too large to fit in memory");
Packit 0ba690
      skip = length - (png_uint_32)65535L;
Packit 0ba690
      length = (png_uint_32)65535L;
Packit 0ba690
   }
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
   png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
   png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
Packit 0ba690
   slength = (png_size_t)length;
Packit 0ba690
   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
Packit 0ba690
Packit 0ba690
   if (png_crc_finish(png_ptr, skip))
Packit 0ba690
   {
Packit 0ba690
      png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
      png_ptr->chunkdata = NULL;
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   png_ptr->chunkdata[slength] = 0x00;
Packit 0ba690
Packit 0ba690
   for (entry_start = (png_bytep)png_ptr->chunkdata; *entry_start;
Packit 0ba690
       entry_start++)
Packit 0ba690
      /* Empty loop to find end of name */ ;
Packit 0ba690
   ++entry_start;
Packit 0ba690
Packit 0ba690
   /* A sample depth should follow the separator, and we should be on it  */
Packit 0ba690
   if (slength < 2U ||
Packit 0ba690
       entry_start > (png_bytep)png_ptr->chunkdata + slength - 2U)
Packit 0ba690
   {
Packit 0ba690
      png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
      png_ptr->chunkdata = NULL;
Packit 0ba690
      png_warning(png_ptr, "malformed sPLT chunk");
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   new_palette.depth = *entry_start++;
Packit 0ba690
   entry_size = (new_palette.depth == 8 ? 6 : 10);
Packit 0ba690
   data_length = (slength - (entry_start - (png_bytep)png_ptr->chunkdata));
Packit 0ba690
Packit 0ba690
   /* Integrity-check the data length */
Packit 0ba690
   if (data_length % entry_size)
Packit 0ba690
   {
Packit 0ba690
      png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
      png_ptr->chunkdata = NULL;
Packit 0ba690
      png_warning(png_ptr, "sPLT chunk has bad length");
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   new_palette.nentries = (png_int_32) ( data_length / entry_size);
Packit 0ba690
   if ((png_uint_32) new_palette.nentries >
Packit 0ba690
       (png_uint_32) (PNG_SIZE_MAX / png_sizeof(png_sPLT_entry)))
Packit 0ba690
   {
Packit 0ba690
       png_warning(png_ptr, "sPLT chunk too long");
Packit 0ba690
       return;
Packit 0ba690
   }
Packit 0ba690
   new_palette.entries = (png_sPLT_entryp)png_malloc_warn(
Packit 0ba690
       png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry));
Packit 0ba690
   if (new_palette.entries == NULL)
Packit 0ba690
   {
Packit 0ba690
       png_warning(png_ptr, "sPLT chunk requires too much memory");
Packit 0ba690
       return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
#ifdef PNG_POINTER_INDEXING_SUPPORTED
Packit 0ba690
   for (i = 0; i < new_palette.nentries; i++)
Packit 0ba690
   {
Packit 0ba690
      pp = new_palette.entries + i;
Packit 0ba690
Packit 0ba690
      if (new_palette.depth == 8)
Packit 0ba690
      {
Packit 0ba690
          pp->red = *entry_start++;
Packit 0ba690
          pp->green = *entry_start++;
Packit 0ba690
          pp->blue = *entry_start++;
Packit 0ba690
          pp->alpha = *entry_start++;
Packit 0ba690
      }
Packit 0ba690
      else
Packit 0ba690
      {
Packit 0ba690
          pp->red   = png_get_uint_16(entry_start); entry_start += 2;
Packit 0ba690
          pp->green = png_get_uint_16(entry_start); entry_start += 2;
Packit 0ba690
          pp->blue  = png_get_uint_16(entry_start); entry_start += 2;
Packit 0ba690
          pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
Packit 0ba690
      }
Packit 0ba690
      pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
Packit 0ba690
   }
Packit 0ba690
#else
Packit 0ba690
   pp = new_palette.entries;
Packit 0ba690
   for (i = 0; i < new_palette.nentries; i++)
Packit 0ba690
   {
Packit 0ba690
Packit 0ba690
      if (new_palette.depth == 8)
Packit 0ba690
      {
Packit 0ba690
          pp[i].red   = *entry_start++;
Packit 0ba690
          pp[i].green = *entry_start++;
Packit 0ba690
          pp[i].blue  = *entry_start++;
Packit 0ba690
          pp[i].alpha = *entry_start++;
Packit 0ba690
      }
Packit 0ba690
      else
Packit 0ba690
      {
Packit 0ba690
          pp[i].red   = png_get_uint_16(entry_start); entry_start += 2;
Packit 0ba690
          pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
Packit 0ba690
          pp[i].blue  = png_get_uint_16(entry_start); entry_start += 2;
Packit 0ba690
          pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
Packit 0ba690
      }
Packit 0ba690
      pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
Packit 0ba690
   }
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
   /* Discard all chunk data except the name and stash that */
Packit 0ba690
   new_palette.name = png_ptr->chunkdata;
Packit 0ba690
Packit 0ba690
   png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
Packit 0ba690
Packit 0ba690
   png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
   png_ptr->chunkdata = NULL;
Packit 0ba690
   png_free(png_ptr, new_palette.entries);
Packit 0ba690
}
Packit 0ba690
#endif /* PNG_READ_sPLT_SUPPORTED */
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_tRNS_SUPPORTED
Packit 0ba690
void /* PRIVATE */
Packit 0ba690
png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Packit 0ba690
{
Packit 0ba690
   png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
Packit 0ba690
Packit 0ba690
   png_debug(1, "in png_handle_tRNS");
Packit 0ba690
Packit 0ba690
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
Packit 0ba690
      png_error(png_ptr, "Missing IHDR before tRNS");
Packit 0ba690
   else if (png_ptr->mode & PNG_HAVE_IDAT)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Invalid tRNS after IDAT");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Duplicate tRNS chunk");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
Packit 0ba690
   {
Packit 0ba690
      png_byte buf[2];
Packit 0ba690
Packit 0ba690
      if (length != 2)
Packit 0ba690
      {
Packit 0ba690
         png_warning(png_ptr, "Incorrect tRNS chunk length");
Packit 0ba690
         png_crc_finish(png_ptr, length);
Packit 0ba690
         return;
Packit 0ba690
      }
Packit 0ba690
Packit 0ba690
      png_crc_read(png_ptr, buf, 2);
Packit 0ba690
      png_ptr->num_trans = 1;
Packit 0ba690
      png_ptr->trans_values.gray = png_get_uint_16(buf);
Packit 0ba690
   }
Packit 0ba690
   else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
Packit 0ba690
   {
Packit 0ba690
      png_byte buf[6];
Packit 0ba690
Packit 0ba690
      if (length != 6)
Packit 0ba690
      {
Packit 0ba690
         png_warning(png_ptr, "Incorrect tRNS chunk length");
Packit 0ba690
         png_crc_finish(png_ptr, length);
Packit 0ba690
         return;
Packit 0ba690
      }
Packit 0ba690
      png_crc_read(png_ptr, buf, (png_size_t)length);
Packit 0ba690
      png_ptr->num_trans = 1;
Packit 0ba690
      png_ptr->trans_values.red = png_get_uint_16(buf);
Packit 0ba690
      png_ptr->trans_values.green = png_get_uint_16(buf + 2);
Packit 0ba690
      png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
Packit 0ba690
   }
Packit 0ba690
   else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Packit 0ba690
   {
Packit 0ba690
      if (!(png_ptr->mode & PNG_HAVE_PLTE))
Packit 0ba690
      {
Packit 0ba690
         /* Should be an error, but we can cope with it. */
Packit 0ba690
         png_warning(png_ptr, "Missing PLTE before tRNS");
Packit 0ba690
      }
Packit 0ba690
      if (length > (png_uint_32)png_ptr->num_palette ||
Packit 0ba690
          length > PNG_MAX_PALETTE_LENGTH)
Packit 0ba690
      {
Packit 0ba690
         png_warning(png_ptr, "Incorrect tRNS chunk length");
Packit 0ba690
         png_crc_finish(png_ptr, length);
Packit 0ba690
         return;
Packit 0ba690
      }
Packit 0ba690
      if (length == 0)
Packit 0ba690
      {
Packit 0ba690
         png_warning(png_ptr, "Zero length tRNS chunk");
Packit 0ba690
         png_crc_finish(png_ptr, length);
Packit 0ba690
         return;
Packit 0ba690
      }
Packit 0ba690
      png_crc_read(png_ptr, readbuf, (png_size_t)length);
Packit 0ba690
      png_ptr->num_trans = (png_uint_16)length;
Packit 0ba690
   }
Packit 0ba690
   else
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   if (png_crc_finish(png_ptr, 0))
Packit 0ba690
   {
Packit 0ba690
      png_ptr->num_trans = 0;
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
Packit 0ba690
      &(png_ptr->trans_values));
Packit 0ba690
}
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_bKGD_SUPPORTED
Packit 0ba690
void /* PRIVATE */
Packit 0ba690
png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Packit 0ba690
{
Packit 0ba690
   png_size_t truelen;
Packit 0ba690
   png_byte buf[6];
Packit 0ba690
Packit 0ba690
   png_debug(1, "in png_handle_bKGD");
Packit 0ba690
Packit 0ba690
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
Packit 0ba690
      png_error(png_ptr, "Missing IHDR before bKGD");
Packit 0ba690
   else if (png_ptr->mode & PNG_HAVE_IDAT)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Invalid bKGD after IDAT");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
   else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
Packit 0ba690
            !(png_ptr->mode & PNG_HAVE_PLTE))
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Missing PLTE before bKGD");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Duplicate bKGD chunk");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Packit 0ba690
      truelen = 1;
Packit 0ba690
   else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
Packit 0ba690
      truelen = 6;
Packit 0ba690
   else
Packit 0ba690
      truelen = 2;
Packit 0ba690
Packit 0ba690
   if (length != truelen)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Incorrect bKGD chunk length");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   png_crc_read(png_ptr, buf, truelen);
Packit 0ba690
   if (png_crc_finish(png_ptr, 0))
Packit 0ba690
      return;
Packit 0ba690
Packit 0ba690
   /* We convert the index value into RGB components so that we can allow
Packit 0ba690
    * arbitrary RGB values for background when we have transparency, and
Packit 0ba690
    * so it is easy to determine the RGB values of the background color
Packit 0ba690
    * from the info_ptr struct. */
Packit 0ba690
   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Packit 0ba690
   {
Packit 0ba690
      png_ptr->background.index = buf[0];
Packit 0ba690
      if (info_ptr && info_ptr->num_palette)
Packit 0ba690
      {
Packit 0ba690
          if (buf[0] >= info_ptr->num_palette)
Packit 0ba690
          {
Packit 0ba690
             png_warning(png_ptr, "Incorrect bKGD chunk index value");
Packit 0ba690
             return;
Packit 0ba690
          }
Packit 0ba690
          png_ptr->background.red =
Packit 0ba690
             (png_uint_16)png_ptr->palette[buf[0]].red;
Packit 0ba690
          png_ptr->background.green =
Packit 0ba690
             (png_uint_16)png_ptr->palette[buf[0]].green;
Packit 0ba690
          png_ptr->background.blue =
Packit 0ba690
             (png_uint_16)png_ptr->palette[buf[0]].blue;
Packit 0ba690
      }
Packit 0ba690
   }
Packit 0ba690
   else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
Packit 0ba690
   {
Packit 0ba690
      png_ptr->background.red =
Packit 0ba690
      png_ptr->background.green =
Packit 0ba690
      png_ptr->background.blue =
Packit 0ba690
      png_ptr->background.gray = png_get_uint_16(buf);
Packit 0ba690
   }
Packit 0ba690
   else
Packit 0ba690
   {
Packit 0ba690
      png_ptr->background.red = png_get_uint_16(buf);
Packit 0ba690
      png_ptr->background.green = png_get_uint_16(buf + 2);
Packit 0ba690
      png_ptr->background.blue = png_get_uint_16(buf + 4);
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
Packit 0ba690
}
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_hIST_SUPPORTED
Packit 0ba690
void /* PRIVATE */
Packit 0ba690
png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Packit 0ba690
{
Packit 0ba690
   unsigned int num, i;
Packit 0ba690
   png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
Packit 0ba690
Packit 0ba690
   png_debug(1, "in png_handle_hIST");
Packit 0ba690
Packit 0ba690
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
Packit 0ba690
      png_error(png_ptr, "Missing IHDR before hIST");
Packit 0ba690
   else if (png_ptr->mode & PNG_HAVE_IDAT)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Invalid hIST after IDAT");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
   else if (!(png_ptr->mode & PNG_HAVE_PLTE))
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Missing PLTE before hIST");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Duplicate hIST chunk");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   if (length > 2*PNG_MAX_PALETTE_LENGTH ||
Packit 0ba690
       length != (unsigned int) (2*png_ptr->num_palette))
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Incorrect hIST chunk length");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   num = length / 2 ;
Packit 0ba690
Packit 0ba690
   for (i = 0; i < num; i++)
Packit 0ba690
   {
Packit 0ba690
      png_byte buf[2];
Packit 0ba690
Packit 0ba690
      png_crc_read(png_ptr, buf, 2);
Packit 0ba690
      readbuf[i] = png_get_uint_16(buf);
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   if (png_crc_finish(png_ptr, 0))
Packit 0ba690
      return;
Packit 0ba690
Packit 0ba690
   png_set_hIST(png_ptr, info_ptr, readbuf);
Packit 0ba690
}
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_pHYs_SUPPORTED
Packit 0ba690
void /* PRIVATE */
Packit 0ba690
png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Packit 0ba690
{
Packit 0ba690
   png_byte buf[9];
Packit 0ba690
   png_uint_32 res_x, res_y;
Packit 0ba690
   int unit_type;
Packit 0ba690
Packit 0ba690
   png_debug(1, "in png_handle_pHYs");
Packit 0ba690
Packit 0ba690
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
Packit 0ba690
      png_error(png_ptr, "Missing IHDR before pHYs");
Packit 0ba690
   else if (png_ptr->mode & PNG_HAVE_IDAT)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Invalid pHYs after IDAT");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Duplicate pHYs chunk");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   if (length != 9)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Incorrect pHYs chunk length");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   png_crc_read(png_ptr, buf, 9);
Packit 0ba690
   if (png_crc_finish(png_ptr, 0))
Packit 0ba690
      return;
Packit 0ba690
Packit 0ba690
   res_x = png_get_uint_32(buf);
Packit 0ba690
   res_y = png_get_uint_32(buf + 4);
Packit 0ba690
   unit_type = buf[8];
Packit 0ba690
   png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
Packit 0ba690
}
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_oFFs_SUPPORTED
Packit 0ba690
void /* PRIVATE */
Packit 0ba690
png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Packit 0ba690
{
Packit 0ba690
   png_byte buf[9];
Packit 0ba690
   png_int_32 offset_x, offset_y;
Packit 0ba690
   int unit_type;
Packit 0ba690
Packit 0ba690
   png_debug(1, "in png_handle_oFFs");
Packit 0ba690
Packit 0ba690
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
Packit 0ba690
      png_error(png_ptr, "Missing IHDR before oFFs");
Packit 0ba690
   else if (png_ptr->mode & PNG_HAVE_IDAT)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Invalid oFFs after IDAT");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Duplicate oFFs chunk");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   if (length != 9)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Incorrect oFFs chunk length");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   png_crc_read(png_ptr, buf, 9);
Packit 0ba690
   if (png_crc_finish(png_ptr, 0))
Packit 0ba690
      return;
Packit 0ba690
Packit 0ba690
   offset_x = png_get_int_32(buf);
Packit 0ba690
   offset_y = png_get_int_32(buf + 4);
Packit 0ba690
   unit_type = buf[8];
Packit 0ba690
   png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
Packit 0ba690
}
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_pCAL_SUPPORTED
Packit 0ba690
/* Read the pCAL chunk (described in the PNG Extensions document) */
Packit 0ba690
void /* PRIVATE */
Packit 0ba690
png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Packit 0ba690
{
Packit 0ba690
   png_int_32 X0, X1;
Packit 0ba690
   png_byte type, nparams;
Packit 0ba690
   png_charp buf, units, endptr;
Packit 0ba690
   png_charpp params;
Packit 0ba690
   png_size_t slength;
Packit 0ba690
   int i;
Packit 0ba690
Packit 0ba690
   png_debug(1, "in png_handle_pCAL");
Packit 0ba690
Packit 0ba690
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
Packit 0ba690
      png_error(png_ptr, "Missing IHDR before pCAL");
Packit 0ba690
   else if (png_ptr->mode & PNG_HAVE_IDAT)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Invalid pCAL after IDAT");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Duplicate pCAL chunk");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)",
Packit 0ba690
      length + 1);
Packit 0ba690
   png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
   png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
Packit 0ba690
   if (png_ptr->chunkdata == NULL)
Packit 0ba690
     {
Packit 0ba690
       png_warning(png_ptr, "No memory for pCAL purpose.");
Packit 0ba690
       return;
Packit 0ba690
     }
Packit 0ba690
   slength = (png_size_t)length;
Packit 0ba690
   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
Packit 0ba690
Packit 0ba690
   if (png_crc_finish(png_ptr, 0))
Packit 0ba690
   {
Packit 0ba690
      png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
      png_ptr->chunkdata = NULL;
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
Packit 0ba690
Packit 0ba690
   png_debug(3, "Finding end of pCAL purpose string");
Packit 0ba690
   for (buf = png_ptr->chunkdata; *buf; buf++)
Packit 0ba690
      /* Empty loop */ ;
Packit 0ba690
Packit 0ba690
   endptr = png_ptr->chunkdata + slength;
Packit 0ba690
Packit 0ba690
   /* We need to have at least 12 bytes after the purpose string
Packit 0ba690
      in order to get the parameter information. */
Packit 0ba690
   if (slength < 12U || endptr - buf <= 12)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Invalid pCAL data");
Packit 0ba690
      png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
      png_ptr->chunkdata = NULL;
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   png_debug(3, "Reading pCAL X0, X1, type, nparams, and units");
Packit 0ba690
   X0 = png_get_int_32((png_bytep)buf+1);
Packit 0ba690
   X1 = png_get_int_32((png_bytep)buf+5);
Packit 0ba690
   type = buf[9];
Packit 0ba690
   nparams = buf[10];
Packit 0ba690
   units = buf + 11;
Packit 0ba690
Packit 0ba690
   png_debug(3, "Checking pCAL equation type and number of parameters");
Packit 0ba690
   /* Check that we have the right number of parameters for known
Packit 0ba690
      equation types. */
Packit 0ba690
   if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
Packit 0ba690
       (type == PNG_EQUATION_BASE_E && nparams != 3) ||
Packit 0ba690
       (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
Packit 0ba690
       (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Invalid pCAL parameters for equation type");
Packit 0ba690
      png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
      png_ptr->chunkdata = NULL;
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
   else if (type >= PNG_EQUATION_LAST)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   for (buf = units; *buf; buf++)
Packit 0ba690
      /* Empty loop to move past the units string. */ ;
Packit 0ba690
Packit 0ba690
   png_debug(3, "Allocating pCAL parameters array");
Packit 0ba690
   params = (png_charpp)png_malloc_warn(png_ptr,
Packit 0ba690
      (png_uint_32)(nparams * png_sizeof(png_charp))) ;
Packit 0ba690
   if (params == NULL)
Packit 0ba690
     {
Packit 0ba690
       png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
       png_ptr->chunkdata = NULL;
Packit 0ba690
       png_warning(png_ptr, "No memory for pCAL params.");
Packit 0ba690
       return;
Packit 0ba690
     }
Packit 0ba690
Packit 0ba690
   /* Get pointers to the start of each parameter string. */
Packit 0ba690
   for (i = 0; i < (int)nparams; i++)
Packit 0ba690
   {
Packit 0ba690
      buf++; /* Skip the null string terminator from previous parameter. */
Packit 0ba690
Packit 0ba690
      png_debug1(3, "Reading pCAL parameter %d", i);
Packit 0ba690
      for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++)
Packit 0ba690
         /* Empty loop to move past each parameter string */ ;
Packit 0ba690
Packit 0ba690
      /* Make sure we haven't run out of data yet */
Packit 0ba690
      if (buf > endptr)
Packit 0ba690
      {
Packit 0ba690
         png_warning(png_ptr, "Invalid pCAL data");
Packit 0ba690
         png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
         png_ptr->chunkdata = NULL;
Packit 0ba690
         png_free(png_ptr, params);
Packit 0ba690
         return;
Packit 0ba690
      }
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   png_set_pCAL(png_ptr, info_ptr, png_ptr->chunkdata, X0, X1, type, nparams,
Packit 0ba690
      units, params);
Packit 0ba690
Packit 0ba690
   png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
   png_ptr->chunkdata = NULL;
Packit 0ba690
   png_free(png_ptr, params);
Packit 0ba690
}
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_sCAL_SUPPORTED
Packit 0ba690
/* Read the sCAL chunk */
Packit 0ba690
void /* PRIVATE */
Packit 0ba690
png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Packit 0ba690
{
Packit 0ba690
   png_charp ep;
Packit 0ba690
#ifdef PNG_FLOATING_POINT_SUPPORTED
Packit 0ba690
   double width, height;
Packit 0ba690
   png_charp vp;
Packit 0ba690
#else
Packit 0ba690
#ifdef PNG_FIXED_POINT_SUPPORTED
Packit 0ba690
   png_charp swidth, sheight;
Packit 0ba690
#endif
Packit 0ba690
#endif
Packit 0ba690
   png_size_t slength;
Packit 0ba690
Packit 0ba690
   png_debug(1, "in png_handle_sCAL");
Packit 0ba690
Packit 0ba690
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
Packit 0ba690
      png_error(png_ptr, "Missing IHDR before sCAL");
Packit 0ba690
   else if (png_ptr->mode & PNG_HAVE_IDAT)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Invalid sCAL after IDAT");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Duplicate sCAL chunk");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   /* Need unit type, width, \0, height: minimum 4 bytes */
Packit 0ba690
   else if (length < 4)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "sCAL chunk too short");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)",
Packit 0ba690
      length + 1);
Packit 0ba690
   png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
Packit 0ba690
   if (png_ptr->chunkdata == NULL)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Out of memory while processing sCAL chunk");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
   slength = (png_size_t)length;
Packit 0ba690
   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
Packit 0ba690
Packit 0ba690
   if (png_crc_finish(png_ptr, 0))
Packit 0ba690
   {
Packit 0ba690
      png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
      png_ptr->chunkdata = NULL;
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
Packit 0ba690
Packit 0ba690
   ep = png_ptr->chunkdata + 1;        /* Skip unit byte */
Packit 0ba690
Packit 0ba690
#ifdef PNG_FLOATING_POINT_SUPPORTED
Packit 0ba690
   width = png_strtod(png_ptr, ep, &vp);
Packit 0ba690
   if (*vp)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "malformed width string in sCAL chunk");
Packit 0ba690
      png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
      png_ptr->chunkdata = NULL;
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
#else
Packit 0ba690
#ifdef PNG_FIXED_POINT_SUPPORTED
Packit 0ba690
   swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
Packit 0ba690
   if (swidth == NULL)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Out of memory while processing sCAL chunk width");
Packit 0ba690
      png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
      png_ptr->chunkdata = NULL;
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
   png_memcpy(swidth, ep, (png_size_t)png_strlen(ep) + 1);
Packit 0ba690
#endif
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
   for (ep = png_ptr->chunkdata + 1; *ep; ep++)
Packit 0ba690
      /* Empty loop */ ;
Packit 0ba690
   ep++;
Packit 0ba690
Packit 0ba690
   if (png_ptr->chunkdata + slength < ep)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Truncated sCAL chunk");
Packit 0ba690
#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
Packit 0ba690
      png_free(png_ptr, swidth);
Packit 0ba690
#endif
Packit 0ba690
      png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
      png_ptr->chunkdata = NULL;
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
#ifdef PNG_FLOATING_POINT_SUPPORTED
Packit 0ba690
   height = png_strtod(png_ptr, ep, &vp);
Packit 0ba690
   if (*vp)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "malformed height string in sCAL chunk");
Packit 0ba690
      png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
      png_ptr->chunkdata = NULL;
Packit 0ba690
#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
Packit 0ba690
      png_free(png_ptr, swidth);
Packit 0ba690
#endif
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
#else
Packit 0ba690
#ifdef PNG_FIXED_POINT_SUPPORTED
Packit 0ba690
   sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
Packit 0ba690
   if (sheight == NULL)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
Packit 0ba690
      png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
      png_ptr->chunkdata = NULL;
Packit 0ba690
#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
Packit 0ba690
      png_free(png_ptr, swidth);
Packit 0ba690
#endif
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
   png_memcpy(sheight, ep, (png_size_t)png_strlen(ep) + 1);
Packit 0ba690
#endif
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
   if (png_ptr->chunkdata + slength < ep
Packit 0ba690
#ifdef PNG_FLOATING_POINT_SUPPORTED
Packit 0ba690
      || width <= 0. || height <= 0.
Packit 0ba690
#endif
Packit 0ba690
      )
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Invalid sCAL data");
Packit 0ba690
      png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
      png_ptr->chunkdata = NULL;
Packit 0ba690
#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
Packit 0ba690
      png_free(png_ptr, swidth);
Packit 0ba690
      png_free(png_ptr, sheight);
Packit 0ba690
#endif
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
Packit 0ba690
#ifdef PNG_FLOATING_POINT_SUPPORTED
Packit 0ba690
   png_set_sCAL(png_ptr, info_ptr, png_ptr->chunkdata[0], width, height);
Packit 0ba690
#else
Packit 0ba690
#ifdef PNG_FIXED_POINT_SUPPORTED
Packit 0ba690
   png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], swidth, sheight);
Packit 0ba690
#endif
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
   png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
   png_ptr->chunkdata = NULL;
Packit 0ba690
#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
Packit 0ba690
   png_free(png_ptr, swidth);
Packit 0ba690
   png_free(png_ptr, sheight);
Packit 0ba690
#endif
Packit 0ba690
}
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_tIME_SUPPORTED
Packit 0ba690
void /* PRIVATE */
Packit 0ba690
png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Packit 0ba690
{
Packit 0ba690
   png_byte buf[7];
Packit 0ba690
   png_time mod_time;
Packit 0ba690
Packit 0ba690
   png_debug(1, "in png_handle_tIME");
Packit 0ba690
Packit 0ba690
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
Packit 0ba690
      png_error(png_ptr, "Out of place tIME chunk");
Packit 0ba690
   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Duplicate tIME chunk");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   if (png_ptr->mode & PNG_HAVE_IDAT)
Packit 0ba690
      png_ptr->mode |= PNG_AFTER_IDAT;
Packit 0ba690
Packit 0ba690
   if (length != 7)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Incorrect tIME chunk length");
Packit 0ba690
      png_crc_finish(png_ptr, length);
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   png_crc_read(png_ptr, buf, 7);
Packit 0ba690
   if (png_crc_finish(png_ptr, 0))
Packit 0ba690
      return;
Packit 0ba690
Packit 0ba690
   mod_time.second = buf[6];
Packit 0ba690
   mod_time.minute = buf[5];
Packit 0ba690
   mod_time.hour = buf[4];
Packit 0ba690
   mod_time.day = buf[3];
Packit 0ba690
   mod_time.month = buf[2];
Packit 0ba690
   mod_time.year = png_get_uint_16(buf);
Packit 0ba690
Packit 0ba690
   png_set_tIME(png_ptr, info_ptr, &mod_time);
Packit 0ba690
}
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_tEXt_SUPPORTED
Packit 0ba690
/* Note: this does not properly handle chunks that are > 64K under DOS */
Packit 0ba690
void /* PRIVATE */
Packit 0ba690
png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Packit 0ba690
{
Packit 0ba690
   png_textp text_ptr;
Packit 0ba690
   png_charp key;
Packit 0ba690
   png_charp text;
Packit 0ba690
   png_uint_32 skip = 0;
Packit 0ba690
   png_size_t slength;
Packit 0ba690
   int ret;
Packit 0ba690
Packit 0ba690
   png_debug(1, "in png_handle_tEXt");
Packit 0ba690
Packit 0ba690
#ifdef PNG_USER_LIMITS_SUPPORTED
Packit 0ba690
   if (png_ptr->user_chunk_cache_max != 0)
Packit 0ba690
   {
Packit 0ba690
      if (png_ptr->user_chunk_cache_max == 1)
Packit 0ba690
      {
Packit 0ba690
         png_crc_finish(png_ptr, length);
Packit 0ba690
         return;
Packit 0ba690
      }
Packit 0ba690
      if (--png_ptr->user_chunk_cache_max == 1)
Packit 0ba690
      {
Packit 0ba690
         png_warning(png_ptr, "No space in chunk cache for tEXt");
Packit 0ba690
         png_crc_finish(png_ptr, length);
Packit 0ba690
         return;
Packit 0ba690
      }
Packit 0ba690
   }
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
Packit 0ba690
      png_error(png_ptr, "Missing IHDR before tEXt");
Packit 0ba690
Packit 0ba690
   if (png_ptr->mode & PNG_HAVE_IDAT)
Packit 0ba690
      png_ptr->mode |= PNG_AFTER_IDAT;
Packit 0ba690
Packit 0ba690
#ifdef PNG_MAX_MALLOC_64K
Packit 0ba690
   if (length > (png_uint_32)65535L)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "tEXt chunk too large to fit in memory");
Packit 0ba690
      skip = length - (png_uint_32)65535L;
Packit 0ba690
      length = (png_uint_32)65535L;
Packit 0ba690
   }
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
   png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
Packit 0ba690
   png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
Packit 0ba690
   if (png_ptr->chunkdata == NULL)
Packit 0ba690
   {
Packit 0ba690
     png_warning(png_ptr, "No memory to process text chunk.");
Packit 0ba690
     return;
Packit 0ba690
   }
Packit 0ba690
   slength = (png_size_t)length;
Packit 0ba690
   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
Packit 0ba690
Packit 0ba690
   if (png_crc_finish(png_ptr, skip))
Packit 0ba690
   {
Packit 0ba690
      png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
      png_ptr->chunkdata = NULL;
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   key = png_ptr->chunkdata;
Packit 0ba690
Packit 0ba690
   key[slength] = 0x00;
Packit 0ba690
Packit 0ba690
   for (text = key; *text; text++)
Packit 0ba690
      /* Empty loop to find end of key */ ;
Packit 0ba690
Packit 0ba690
   if (text != key + slength)
Packit 0ba690
      text++;
Packit 0ba690
Packit 0ba690
   text_ptr = (png_textp)png_malloc_warn(png_ptr,
Packit 0ba690
      (png_uint_32)png_sizeof(png_text));
Packit 0ba690
   if (text_ptr == NULL)
Packit 0ba690
   {
Packit 0ba690
     png_warning(png_ptr, "Not enough memory to process text chunk.");
Packit 0ba690
     png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
     png_ptr->chunkdata = NULL;
Packit 0ba690
     return;
Packit 0ba690
   }
Packit 0ba690
   text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
Packit 0ba690
   text_ptr->key = key;
Packit 0ba690
#ifdef PNG_iTXt_SUPPORTED
Packit 0ba690
   text_ptr->lang = NULL;
Packit 0ba690
   text_ptr->lang_key = NULL;
Packit 0ba690
   text_ptr->itxt_length = 0;
Packit 0ba690
#endif
Packit 0ba690
   text_ptr->text = text;
Packit 0ba690
   text_ptr->text_length = png_strlen(text);
Packit 0ba690
Packit 0ba690
   ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
Packit 0ba690
Packit 0ba690
   png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
   png_ptr->chunkdata = NULL;
Packit 0ba690
   png_free(png_ptr, text_ptr);
Packit 0ba690
   if (ret)
Packit 0ba690
     png_warning(png_ptr, "Insufficient memory to process text chunk.");
Packit 0ba690
}
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_zTXt_SUPPORTED
Packit 0ba690
/* Note: this does not correctly handle chunks that are > 64K under DOS */
Packit 0ba690
void /* PRIVATE */
Packit 0ba690
png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Packit 0ba690
{
Packit 0ba690
   png_textp text_ptr;
Packit 0ba690
   png_charp text;
Packit 0ba690
   int comp_type;
Packit 0ba690
   int ret;
Packit 0ba690
   png_size_t slength, prefix_len, data_len;
Packit 0ba690
Packit 0ba690
   png_debug(1, "in png_handle_zTXt");
Packit 0ba690
Packit 0ba690
#ifdef PNG_USER_LIMITS_SUPPORTED
Packit 0ba690
   if (png_ptr->user_chunk_cache_max != 0)
Packit 0ba690
   {
Packit 0ba690
      if (png_ptr->user_chunk_cache_max == 1)
Packit 0ba690
      {
Packit 0ba690
         png_crc_finish(png_ptr, length);
Packit 0ba690
         return;
Packit 0ba690
      }
Packit 0ba690
      if (--png_ptr->user_chunk_cache_max == 1)
Packit 0ba690
      {
Packit 0ba690
         png_warning(png_ptr, "No space in chunk cache for zTXt");
Packit 0ba690
         png_crc_finish(png_ptr, length);
Packit 0ba690
         return;
Packit 0ba690
      }
Packit 0ba690
   }
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
Packit 0ba690
      png_error(png_ptr, "Missing IHDR before zTXt");
Packit 0ba690
Packit 0ba690
   if (png_ptr->mode & PNG_HAVE_IDAT)
Packit 0ba690
      png_ptr->mode |= PNG_AFTER_IDAT;
Packit 0ba690
Packit 0ba690
#ifdef PNG_MAX_MALLOC_64K
Packit 0ba690
   /* We will no doubt have problems with chunks even half this size, but
Packit 0ba690
      there is no hard and fast rule to tell us where to stop. */
Packit 0ba690
   if (length > (png_uint_32)65535L)
Packit 0ba690
   {
Packit 0ba690
     png_warning(png_ptr, "zTXt chunk too large to fit in memory");
Packit 0ba690
     png_crc_finish(png_ptr, length);
Packit 0ba690
     return;
Packit 0ba690
   }
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
   png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
   png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
Packit 0ba690
   if (png_ptr->chunkdata == NULL)
Packit 0ba690
   {
Packit 0ba690
     png_warning(png_ptr, "Out of memory processing zTXt chunk.");
Packit 0ba690
     return;
Packit 0ba690
   }
Packit 0ba690
   slength = (png_size_t)length;
Packit 0ba690
   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
Packit 0ba690
   if (png_crc_finish(png_ptr, 0))
Packit 0ba690
   {
Packit 0ba690
      png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
      png_ptr->chunkdata = NULL;
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   png_ptr->chunkdata[slength] = 0x00;
Packit 0ba690
Packit 0ba690
   for (text = png_ptr->chunkdata; *text; text++)
Packit 0ba690
      /* Empty loop */ ;
Packit 0ba690
Packit 0ba690
   /* zTXt must have some text after the chunkdataword */
Packit 0ba690
   if (slength < 2U || text >= png_ptr->chunkdata + slength - 2U)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Truncated zTXt chunk");
Packit 0ba690
      png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
      png_ptr->chunkdata = NULL;
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
   else
Packit 0ba690
   {
Packit 0ba690
       comp_type = *(++text);
Packit 0ba690
       if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
Packit 0ba690
       {
Packit 0ba690
          png_warning(png_ptr, "Unknown compression type in zTXt chunk");
Packit 0ba690
          comp_type = PNG_TEXT_COMPRESSION_zTXt;
Packit 0ba690
       }
Packit 0ba690
       text++;        /* Skip the compression_method byte */
Packit 0ba690
   }
Packit 0ba690
   prefix_len = text - png_ptr->chunkdata;
Packit 0ba690
Packit 0ba690
   png_decompress_chunk(png_ptr, comp_type,
Packit 0ba690
     (png_size_t)length, prefix_len, &data_len);
Packit 0ba690
Packit 0ba690
   text_ptr = (png_textp)png_malloc_warn(png_ptr,
Packit 0ba690
      (png_uint_32)png_sizeof(png_text));
Packit 0ba690
   if (text_ptr == NULL)
Packit 0ba690
   {
Packit 0ba690
     png_warning(png_ptr, "Not enough memory to process zTXt chunk.");
Packit 0ba690
     png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
     png_ptr->chunkdata = NULL;
Packit 0ba690
     return;
Packit 0ba690
   }
Packit 0ba690
   text_ptr->compression = comp_type;
Packit 0ba690
   text_ptr->key = png_ptr->chunkdata;
Packit 0ba690
#ifdef PNG_iTXt_SUPPORTED
Packit 0ba690
   text_ptr->lang = NULL;
Packit 0ba690
   text_ptr->lang_key = NULL;
Packit 0ba690
   text_ptr->itxt_length = 0;
Packit 0ba690
#endif
Packit 0ba690
   text_ptr->text = png_ptr->chunkdata + prefix_len;
Packit 0ba690
   text_ptr->text_length = data_len;
Packit 0ba690
Packit 0ba690
   ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
Packit 0ba690
Packit 0ba690
   png_free(png_ptr, text_ptr);
Packit 0ba690
   png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
   png_ptr->chunkdata = NULL;
Packit 0ba690
   if (ret)
Packit 0ba690
     png_error(png_ptr, "Insufficient memory to store zTXt chunk.");
Packit 0ba690
}
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_iTXt_SUPPORTED
Packit 0ba690
/* Note: this does not correctly handle chunks that are > 64K under DOS */
Packit 0ba690
void /* PRIVATE */
Packit 0ba690
png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Packit 0ba690
{
Packit 0ba690
   png_textp text_ptr;
Packit 0ba690
   png_charp key, lang, text, lang_key;
Packit 0ba690
   int comp_flag;
Packit 0ba690
   int comp_type = 0;
Packit 0ba690
   int ret;
Packit 0ba690
   png_size_t slength, prefix_len, data_len;
Packit 0ba690
Packit 0ba690
   png_debug(1, "in png_handle_iTXt");
Packit 0ba690
Packit 0ba690
#ifdef PNG_USER_LIMITS_SUPPORTED
Packit 0ba690
   if (png_ptr->user_chunk_cache_max != 0)
Packit 0ba690
   {
Packit 0ba690
      if (png_ptr->user_chunk_cache_max == 1)
Packit 0ba690
      {
Packit 0ba690
         png_crc_finish(png_ptr, length);
Packit 0ba690
         return;
Packit 0ba690
      }
Packit 0ba690
      if (--png_ptr->user_chunk_cache_max == 1)
Packit 0ba690
      {
Packit 0ba690
         png_warning(png_ptr, "No space in chunk cache for iTXt");
Packit 0ba690
         png_crc_finish(png_ptr, length);
Packit 0ba690
         return;
Packit 0ba690
      }
Packit 0ba690
   }
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
Packit 0ba690
      png_error(png_ptr, "Missing IHDR before iTXt");
Packit 0ba690
Packit 0ba690
   if (png_ptr->mode & PNG_HAVE_IDAT)
Packit 0ba690
      png_ptr->mode |= PNG_AFTER_IDAT;
Packit 0ba690
Packit 0ba690
#ifdef PNG_MAX_MALLOC_64K
Packit 0ba690
   /* We will no doubt have problems with chunks even half this size, but
Packit 0ba690
      there is no hard and fast rule to tell us where to stop. */
Packit 0ba690
   if (length > (png_uint_32)65535L)
Packit 0ba690
   {
Packit 0ba690
     png_warning(png_ptr, "iTXt chunk too large to fit in memory");
Packit 0ba690
     png_crc_finish(png_ptr, length);
Packit 0ba690
     return;
Packit 0ba690
   }
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
   png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
   png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
Packit 0ba690
   if (png_ptr->chunkdata == NULL)
Packit 0ba690
   {
Packit 0ba690
     png_warning(png_ptr, "No memory to process iTXt chunk.");
Packit 0ba690
     return;
Packit 0ba690
   }
Packit 0ba690
   slength = (png_size_t)length;
Packit 0ba690
   png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
Packit 0ba690
   if (png_crc_finish(png_ptr, 0))
Packit 0ba690
   {
Packit 0ba690
      png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
      png_ptr->chunkdata = NULL;
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   png_ptr->chunkdata[slength] = 0x00;
Packit 0ba690
Packit 0ba690
   for (lang = png_ptr->chunkdata; *lang; lang++)
Packit 0ba690
      /* Empty loop */ ;
Packit 0ba690
   lang++;        /* Skip NUL separator */
Packit 0ba690
Packit 0ba690
   /* iTXt must have a language tag (possibly empty), two compression bytes,
Packit 0ba690
    * translated keyword (possibly empty), and possibly some text after the
Packit 0ba690
    * keyword
Packit 0ba690
    */
Packit 0ba690
Packit 0ba690
   if (slength < 3U || lang >= png_ptr->chunkdata + slength - 3U)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Truncated iTXt chunk");
Packit 0ba690
      png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
      png_ptr->chunkdata = NULL;
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
   else
Packit 0ba690
   {
Packit 0ba690
       comp_flag = *lang++;
Packit 0ba690
       comp_type = *lang++;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   for (lang_key = lang; *lang_key; lang_key++)
Packit 0ba690
      /* Empty loop */ ;
Packit 0ba690
   lang_key++;        /* Skip NUL separator */
Packit 0ba690
Packit 0ba690
   if (lang_key >= png_ptr->chunkdata + slength)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Truncated iTXt chunk");
Packit 0ba690
      png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
      png_ptr->chunkdata = NULL;
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   for (text = lang_key; *text; text++)
Packit 0ba690
      /* Empty loop */ ;
Packit 0ba690
   text++;        /* Skip NUL separator */
Packit 0ba690
   if (text >= png_ptr->chunkdata + slength)
Packit 0ba690
   {
Packit 0ba690
      png_warning(png_ptr, "Malformed iTXt chunk");
Packit 0ba690
      png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
      png_ptr->chunkdata = NULL;
Packit 0ba690
      return;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   prefix_len = text - png_ptr->chunkdata;
Packit 0ba690
Packit 0ba690
   key=png_ptr->chunkdata;
Packit 0ba690
   if (comp_flag)
Packit 0ba690
       png_decompress_chunk(png_ptr, comp_type,
Packit 0ba690
         (size_t)length, prefix_len, &data_len);
Packit 0ba690
   else
Packit 0ba690
       data_len = png_strlen(png_ptr->chunkdata + prefix_len);
Packit 0ba690
   text_ptr = (png_textp)png_malloc_warn(png_ptr,
Packit 0ba690
      (png_uint_32)png_sizeof(png_text));
Packit 0ba690
   if (text_ptr == NULL)
Packit 0ba690
   {
Packit 0ba690
     png_warning(png_ptr, "Not enough memory to process iTXt chunk.");
Packit 0ba690
     png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
     png_ptr->chunkdata = NULL;
Packit 0ba690
     return;
Packit 0ba690
   }
Packit 0ba690
   text_ptr->compression = (int)comp_flag + 1;
Packit 0ba690
   text_ptr->lang_key = png_ptr->chunkdata + (lang_key - key);
Packit 0ba690
   text_ptr->lang = png_ptr->chunkdata + (lang - key);
Packit 0ba690
   text_ptr->itxt_length = data_len;
Packit 0ba690
   text_ptr->text_length = 0;
Packit 0ba690
   text_ptr->key = png_ptr->chunkdata;
Packit 0ba690
   text_ptr->text = png_ptr->chunkdata + prefix_len;
Packit 0ba690
Packit 0ba690
   ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
Packit 0ba690
Packit 0ba690
   png_free(png_ptr, text_ptr);
Packit 0ba690
   png_free(png_ptr, png_ptr->chunkdata);
Packit 0ba690
   png_ptr->chunkdata = NULL;
Packit 0ba690
   if (ret)
Packit 0ba690
     png_error(png_ptr, "Insufficient memory to store iTXt chunk.");
Packit 0ba690
}
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
/* This function is called when we haven't found a handler for a
Packit 0ba690
   chunk.  If there isn't a problem with the chunk itself (ie bad
Packit 0ba690
   chunk name, CRC, or a critical chunk), the chunk is silently ignored
Packit 0ba690
   -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
Packit 0ba690
   case it will be saved away to be written out later. */
Packit 0ba690
void /* PRIVATE */
Packit 0ba690
png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Packit 0ba690
{
Packit 0ba690
   png_uint_32 skip = 0;
Packit 0ba690
Packit 0ba690
   png_debug(1, "in png_handle_unknown");
Packit 0ba690
Packit 0ba690
#ifdef PNG_USER_LIMITS_SUPPORTED
Packit 0ba690
   if (png_ptr->user_chunk_cache_max != 0)
Packit 0ba690
   {
Packit 0ba690
      if (png_ptr->user_chunk_cache_max == 1)
Packit 0ba690
      {
Packit 0ba690
         png_crc_finish(png_ptr, length);
Packit 0ba690
         return;
Packit 0ba690
      }
Packit 0ba690
      if (--png_ptr->user_chunk_cache_max == 1)
Packit 0ba690
      {
Packit 0ba690
         png_warning(png_ptr, "No space in chunk cache for unknown chunk");
Packit 0ba690
         png_crc_finish(png_ptr, length);
Packit 0ba690
         return;
Packit 0ba690
      }
Packit 0ba690
   }
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
   if (png_ptr->mode & PNG_HAVE_IDAT)
Packit 0ba690
   {
Packit 0ba690
#ifdef PNG_USE_LOCAL_ARRAYS
Packit 0ba690
      PNG_CONST PNG_IDAT;
Packit 0ba690
#endif
Packit 0ba690
      if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))  /* Not an IDAT */
Packit 0ba690
         png_ptr->mode |= PNG_AFTER_IDAT;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   if (!(png_ptr->chunk_name[0] & 0x20))
Packit 0ba690
   {
Packit 0ba690
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
Packit 0ba690
      if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
Packit 0ba690
           PNG_HANDLE_CHUNK_ALWAYS
Packit 0ba690
#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
Packit 0ba690
           && png_ptr->read_user_chunk_fn == NULL
Packit 0ba690
#endif
Packit 0ba690
        )
Packit 0ba690
#endif
Packit 0ba690
          png_chunk_error(png_ptr, "unknown critical chunk");
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
Packit 0ba690
   if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
Packit 0ba690
#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
Packit 0ba690
       || (png_ptr->read_user_chunk_fn != NULL)
Packit 0ba690
#endif
Packit 0ba690
        )
Packit 0ba690
   {
Packit 0ba690
#ifdef PNG_MAX_MALLOC_64K
Packit 0ba690
       if (length > (png_uint_32)65535L)
Packit 0ba690
       {
Packit 0ba690
           png_warning(png_ptr, "unknown chunk too large to fit in memory");
Packit 0ba690
           skip = length - (png_uint_32)65535L;
Packit 0ba690
           length = (png_uint_32)65535L;
Packit 0ba690
       }
Packit 0ba690
#endif
Packit 0ba690
       png_memcpy((png_charp)png_ptr->unknown_chunk.name,
Packit 0ba690
                  (png_charp)png_ptr->chunk_name,
Packit 0ba690
                  png_sizeof(png_ptr->unknown_chunk.name));
Packit 0ba690
       png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1]
Packit 0ba690
           = '\0';
Packit 0ba690
       png_ptr->unknown_chunk.size = (png_size_t)length;
Packit 0ba690
       if (length == 0)
Packit 0ba690
         png_ptr->unknown_chunk.data = NULL;
Packit 0ba690
       else
Packit 0ba690
       {
Packit 0ba690
         png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length);
Packit 0ba690
         png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length);
Packit 0ba690
       }
Packit 0ba690
#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
Packit 0ba690
       if (png_ptr->read_user_chunk_fn != NULL)
Packit 0ba690
       {
Packit 0ba690
          /* Callback to user unknown chunk handler */
Packit 0ba690
          int ret;
Packit 0ba690
          ret = (*(png_ptr->read_user_chunk_fn))
Packit 0ba690
            (png_ptr, &png_ptr->unknown_chunk);
Packit 0ba690
          if (ret < 0)
Packit 0ba690
             png_chunk_error(png_ptr, "error in user chunk");
Packit 0ba690
          if (ret == 0)
Packit 0ba690
          {
Packit 0ba690
             if (!(png_ptr->chunk_name[0] & 0x20))
Packit 0ba690
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
Packit 0ba690
                if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
Packit 0ba690
                     PNG_HANDLE_CHUNK_ALWAYS)
Packit 0ba690
#endif
Packit 0ba690
                   png_chunk_error(png_ptr, "unknown critical chunk");
Packit 0ba690
             png_set_unknown_chunks(png_ptr, info_ptr,
Packit 0ba690
               &png_ptr->unknown_chunk, 1);
Packit 0ba690
          }
Packit 0ba690
       }
Packit 0ba690
       else
Packit 0ba690
#endif
Packit 0ba690
       png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
Packit 0ba690
       png_free(png_ptr, png_ptr->unknown_chunk.data);
Packit 0ba690
       png_ptr->unknown_chunk.data = NULL;
Packit 0ba690
   }
Packit 0ba690
   else
Packit 0ba690
#endif
Packit 0ba690
      skip = length;
Packit 0ba690
Packit 0ba690
   png_crc_finish(png_ptr, skip);
Packit 0ba690
Packit 0ba690
#ifndef PNG_READ_USER_CHUNKS_SUPPORTED
Packit 0ba690
   PNG_UNUSED(info_ptr) /* Quiet compiler warnings about unused info_ptr */
Packit 0ba690
#endif
Packit 0ba690
}
Packit 0ba690
Packit 0ba690
/* This function is called to verify that a chunk name is valid.
Packit 0ba690
   This function can't have the "critical chunk check" incorporated
Packit 0ba690
   into it, since in the future we will need to be able to call user
Packit 0ba690
   functions to handle unknown critical chunks after we check that
Packit 0ba690
   the chunk name itself is valid. */
Packit 0ba690
Packit 0ba690
#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
Packit 0ba690
Packit 0ba690
void /* PRIVATE */
Packit 0ba690
png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
Packit 0ba690
{
Packit 0ba690
   png_debug(1, "in png_check_chunk_name");
Packit 0ba690
   if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
Packit 0ba690
       isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
Packit 0ba690
   {
Packit 0ba690
      png_chunk_error(png_ptr, "invalid chunk type");
Packit 0ba690
   }
Packit 0ba690
}
Packit 0ba690
Packit 0ba690
/* Combines the row recently read in with the existing pixels in the
Packit 0ba690
   row.  This routine takes care of alpha and transparency if requested.
Packit 0ba690
   This routine also handles the two methods of progressive display
Packit 0ba690
   of interlaced images, depending on the mask value.
Packit 0ba690
   The mask value describes which pixels are to be combined with
Packit 0ba690
   the row.  The pattern always repeats every 8 pixels, so just 8
Packit 0ba690
   bits are needed.  A one indicates the pixel is to be combined,
Packit 0ba690
   a zero indicates the pixel is to be skipped.  This is in addition
Packit 0ba690
   to any alpha or transparency value associated with the pixel.  If
Packit 0ba690
   you want all pixels to be combined, pass 0xff (255) in mask.  */
Packit 0ba690
Packit 0ba690
void /* PRIVATE */
Packit 0ba690
png_combine_row(png_structp png_ptr, png_bytep row, int mask)
Packit 0ba690
{
Packit 0ba690
   png_debug(1, "in png_combine_row");
Packit 0ba690
   if (mask == 0xff)
Packit 0ba690
   {
Packit 0ba690
      png_memcpy(row, png_ptr->row_buf + 1,
Packit 0ba690
         PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width));
Packit 0ba690
   }
Packit 0ba690
   else
Packit 0ba690
   {
Packit 0ba690
      switch (png_ptr->row_info.pixel_depth)
Packit 0ba690
      {
Packit 0ba690
         case 1:
Packit 0ba690
         {
Packit 0ba690
            png_bytep sp = png_ptr->row_buf + 1;
Packit 0ba690
            png_bytep dp = row;
Packit 0ba690
            int s_inc, s_start, s_end;
Packit 0ba690
            int m = 0x80;
Packit 0ba690
            int shift;
Packit 0ba690
            png_uint_32 i;
Packit 0ba690
            png_uint_32 row_width = png_ptr->width;
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_PACKSWAP_SUPPORTED
Packit 0ba690
            if (png_ptr->transformations & PNG_PACKSWAP)
Packit 0ba690
            {
Packit 0ba690
                s_start = 0;
Packit 0ba690
                s_end = 7;
Packit 0ba690
                s_inc = 1;
Packit 0ba690
            }
Packit 0ba690
            else
Packit 0ba690
#endif
Packit 0ba690
            {
Packit 0ba690
                s_start = 7;
Packit 0ba690
                s_end = 0;
Packit 0ba690
                s_inc = -1;
Packit 0ba690
            }
Packit 0ba690
Packit 0ba690
            shift = s_start;
Packit 0ba690
Packit 0ba690
            for (i = 0; i < row_width; i++)
Packit 0ba690
            {
Packit 0ba690
               if (m & mask)
Packit 0ba690
               {
Packit 0ba690
                  int value;
Packit 0ba690
Packit 0ba690
                  value = (*sp >> shift) & 0x01;
Packit 0ba690
                  *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
Packit 0ba690
                  *dp |= (png_byte)(value << shift);
Packit 0ba690
               }
Packit 0ba690
Packit 0ba690
               if (shift == s_end)
Packit 0ba690
               {
Packit 0ba690
                  shift = s_start;
Packit 0ba690
                  sp++;
Packit 0ba690
                  dp++;
Packit 0ba690
               }
Packit 0ba690
               else
Packit 0ba690
                  shift += s_inc;
Packit 0ba690
Packit 0ba690
               if (m == 1)
Packit 0ba690
                  m = 0x80;
Packit 0ba690
               else
Packit 0ba690
                  m >>= 1;
Packit 0ba690
            }
Packit 0ba690
            break;
Packit 0ba690
         }
Packit 0ba690
         case 2:
Packit 0ba690
         {
Packit 0ba690
            png_bytep sp = png_ptr->row_buf + 1;
Packit 0ba690
            png_bytep dp = row;
Packit 0ba690
            int s_start, s_end, s_inc;
Packit 0ba690
            int m = 0x80;
Packit 0ba690
            int shift;
Packit 0ba690
            png_uint_32 i;
Packit 0ba690
            png_uint_32 row_width = png_ptr->width;
Packit 0ba690
            int value;
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_PACKSWAP_SUPPORTED
Packit 0ba690
            if (png_ptr->transformations & PNG_PACKSWAP)
Packit 0ba690
            {
Packit 0ba690
               s_start = 0;
Packit 0ba690
               s_end = 6;
Packit 0ba690
               s_inc = 2;
Packit 0ba690
            }
Packit 0ba690
            else
Packit 0ba690
#endif
Packit 0ba690
            {
Packit 0ba690
               s_start = 6;
Packit 0ba690
               s_end = 0;
Packit 0ba690
               s_inc = -2;
Packit 0ba690
            }
Packit 0ba690
Packit 0ba690
            shift = s_start;
Packit 0ba690
Packit 0ba690
            for (i = 0; i < row_width; i++)
Packit 0ba690
            {
Packit 0ba690
               if (m & mask)
Packit 0ba690
               {
Packit 0ba690
                  value = (*sp >> shift) & 0x03;
Packit 0ba690
                  *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
Packit 0ba690
                  *dp |= (png_byte)(value << shift);
Packit 0ba690
               }
Packit 0ba690
Packit 0ba690
               if (shift == s_end)
Packit 0ba690
               {
Packit 0ba690
                  shift = s_start;
Packit 0ba690
                  sp++;
Packit 0ba690
                  dp++;
Packit 0ba690
               }
Packit 0ba690
               else
Packit 0ba690
                  shift += s_inc;
Packit 0ba690
               if (m == 1)
Packit 0ba690
                  m = 0x80;
Packit 0ba690
               else
Packit 0ba690
                  m >>= 1;
Packit 0ba690
            }
Packit 0ba690
            break;
Packit 0ba690
         }
Packit 0ba690
         case 4:
Packit 0ba690
         {
Packit 0ba690
            png_bytep sp = png_ptr->row_buf + 1;
Packit 0ba690
            png_bytep dp = row;
Packit 0ba690
            int s_start, s_end, s_inc;
Packit 0ba690
            int m = 0x80;
Packit 0ba690
            int shift;
Packit 0ba690
            png_uint_32 i;
Packit 0ba690
            png_uint_32 row_width = png_ptr->width;
Packit 0ba690
            int value;
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_PACKSWAP_SUPPORTED
Packit 0ba690
            if (png_ptr->transformations & PNG_PACKSWAP)
Packit 0ba690
            {
Packit 0ba690
               s_start = 0;
Packit 0ba690
               s_end = 4;
Packit 0ba690
               s_inc = 4;
Packit 0ba690
            }
Packit 0ba690
            else
Packit 0ba690
#endif
Packit 0ba690
            {
Packit 0ba690
               s_start = 4;
Packit 0ba690
               s_end = 0;
Packit 0ba690
               s_inc = -4;
Packit 0ba690
            }
Packit 0ba690
            shift = s_start;
Packit 0ba690
Packit 0ba690
            for (i = 0; i < row_width; i++)
Packit 0ba690
            {
Packit 0ba690
               if (m & mask)
Packit 0ba690
               {
Packit 0ba690
                  value = (*sp >> shift) & 0xf;
Packit 0ba690
                  *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
Packit 0ba690
                  *dp |= (png_byte)(value << shift);
Packit 0ba690
               }
Packit 0ba690
Packit 0ba690
               if (shift == s_end)
Packit 0ba690
               {
Packit 0ba690
                  shift = s_start;
Packit 0ba690
                  sp++;
Packit 0ba690
                  dp++;
Packit 0ba690
               }
Packit 0ba690
               else
Packit 0ba690
                  shift += s_inc;
Packit 0ba690
               if (m == 1)
Packit 0ba690
                  m = 0x80;
Packit 0ba690
               else
Packit 0ba690
                  m >>= 1;
Packit 0ba690
            }
Packit 0ba690
            break;
Packit 0ba690
         }
Packit 0ba690
         default:
Packit 0ba690
         {
Packit 0ba690
            png_bytep sp = png_ptr->row_buf + 1;
Packit 0ba690
            png_bytep dp = row;
Packit 0ba690
            png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
Packit 0ba690
            png_uint_32 i;
Packit 0ba690
            png_uint_32 row_width = png_ptr->width;
Packit 0ba690
            png_byte m = 0x80;
Packit 0ba690
Packit 0ba690
Packit 0ba690
            for (i = 0; i < row_width; i++)
Packit 0ba690
            {
Packit 0ba690
               if (m & mask)
Packit 0ba690
               {
Packit 0ba690
                  png_memcpy(dp, sp, pixel_bytes);
Packit 0ba690
               }
Packit 0ba690
Packit 0ba690
               sp += pixel_bytes;
Packit 0ba690
               dp += pixel_bytes;
Packit 0ba690
Packit 0ba690
               if (m == 1)
Packit 0ba690
                  m = 0x80;
Packit 0ba690
               else
Packit 0ba690
                  m >>= 1;
Packit 0ba690
            }
Packit 0ba690
            break;
Packit 0ba690
         }
Packit 0ba690
      }
Packit 0ba690
   }
Packit 0ba690
}
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_INTERLACING_SUPPORTED
Packit 0ba690
/* OLD pre-1.0.9 interface:
Packit 0ba690
void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
Packit 0ba690
   png_uint_32 transformations)
Packit 0ba690
 */
Packit 0ba690
void /* PRIVATE */
Packit 0ba690
png_do_read_interlace(png_structp png_ptr)
Packit 0ba690
{
Packit 0ba690
   png_row_infop row_info = &(png_ptr->row_info);
Packit 0ba690
   png_bytep row = png_ptr->row_buf + 1;
Packit 0ba690
   int pass = png_ptr->pass;
Packit 0ba690
   png_uint_32 transformations = png_ptr->transformations;
Packit 0ba690
   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
Packit 0ba690
   /* Offset to next interlace block */
Packit 0ba690
#ifndef PNG_USE_GLOBAL_ARRAYS
Packit 0ba690
   PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
   png_debug(1, "in png_do_read_interlace");
Packit 0ba690
   if (row != NULL && row_info != NULL)
Packit 0ba690
   {
Packit 0ba690
      png_uint_32 final_width;
Packit 0ba690
Packit 0ba690
      final_width = row_info->width * png_pass_inc[pass];
Packit 0ba690
Packit 0ba690
      switch (row_info->pixel_depth)
Packit 0ba690
      {
Packit 0ba690
         case 1:
Packit 0ba690
         {
Packit 0ba690
            png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
Packit 0ba690
            png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
Packit 0ba690
            int sshift, dshift;
Packit 0ba690
            int s_start, s_end, s_inc;
Packit 0ba690
            int jstop = png_pass_inc[pass];
Packit 0ba690
            png_byte v;
Packit 0ba690
            png_uint_32 i;
Packit 0ba690
            int j;
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_PACKSWAP_SUPPORTED
Packit 0ba690
            if (transformations & PNG_PACKSWAP)
Packit 0ba690
            {
Packit 0ba690
                sshift = (int)((row_info->width + 7) & 0x07);
Packit 0ba690
                dshift = (int)((final_width + 7) & 0x07);
Packit 0ba690
                s_start = 7;
Packit 0ba690
                s_end = 0;
Packit 0ba690
                s_inc = -1;
Packit 0ba690
            }
Packit 0ba690
            else
Packit 0ba690
#endif
Packit 0ba690
            {
Packit 0ba690
                sshift = 7 - (int)((row_info->width + 7) & 0x07);
Packit 0ba690
                dshift = 7 - (int)((final_width + 7) & 0x07);
Packit 0ba690
                s_start = 0;
Packit 0ba690
                s_end = 7;
Packit 0ba690
                s_inc = 1;
Packit 0ba690
            }
Packit 0ba690
Packit 0ba690
            for (i = 0; i < row_info->width; i++)
Packit 0ba690
            {
Packit 0ba690
               v = (png_byte)((*sp >> sshift) & 0x01);
Packit 0ba690
               for (j = 0; j < jstop; j++)
Packit 0ba690
               {
Packit 0ba690
                  *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
Packit 0ba690
                  *dp |= (png_byte)(v << dshift);
Packit 0ba690
                  if (dshift == s_end)
Packit 0ba690
                  {
Packit 0ba690
                     dshift = s_start;
Packit 0ba690
                     dp--;
Packit 0ba690
                  }
Packit 0ba690
                  else
Packit 0ba690
                     dshift += s_inc;
Packit 0ba690
               }
Packit 0ba690
               if (sshift == s_end)
Packit 0ba690
               {
Packit 0ba690
                  sshift = s_start;
Packit 0ba690
                  sp--;
Packit 0ba690
               }
Packit 0ba690
               else
Packit 0ba690
                  sshift += s_inc;
Packit 0ba690
            }
Packit 0ba690
            break;
Packit 0ba690
         }
Packit 0ba690
         case 2:
Packit 0ba690
         {
Packit 0ba690
            png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
Packit 0ba690
            png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
Packit 0ba690
            int sshift, dshift;
Packit 0ba690
            int s_start, s_end, s_inc;
Packit 0ba690
            int jstop = png_pass_inc[pass];
Packit 0ba690
            png_uint_32 i;
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_PACKSWAP_SUPPORTED
Packit 0ba690
            if (transformations & PNG_PACKSWAP)
Packit 0ba690
            {
Packit 0ba690
               sshift = (int)(((row_info->width + 3) & 0x03) << 1);
Packit 0ba690
               dshift = (int)(((final_width + 3) & 0x03) << 1);
Packit 0ba690
               s_start = 6;
Packit 0ba690
               s_end = 0;
Packit 0ba690
               s_inc = -2;
Packit 0ba690
            }
Packit 0ba690
            else
Packit 0ba690
#endif
Packit 0ba690
            {
Packit 0ba690
               sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
Packit 0ba690
               dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
Packit 0ba690
               s_start = 0;
Packit 0ba690
               s_end = 6;
Packit 0ba690
               s_inc = 2;
Packit 0ba690
            }
Packit 0ba690
Packit 0ba690
            for (i = 0; i < row_info->width; i++)
Packit 0ba690
            {
Packit 0ba690
               png_byte v;
Packit 0ba690
               int j;
Packit 0ba690
Packit 0ba690
               v = (png_byte)((*sp >> sshift) & 0x03);
Packit 0ba690
               for (j = 0; j < jstop; j++)
Packit 0ba690
               {
Packit 0ba690
                  *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
Packit 0ba690
                  *dp |= (png_byte)(v << dshift);
Packit 0ba690
                  if (dshift == s_end)
Packit 0ba690
                  {
Packit 0ba690
                     dshift = s_start;
Packit 0ba690
                     dp--;
Packit 0ba690
                  }
Packit 0ba690
                  else
Packit 0ba690
                     dshift += s_inc;
Packit 0ba690
               }
Packit 0ba690
               if (sshift == s_end)
Packit 0ba690
               {
Packit 0ba690
                  sshift = s_start;
Packit 0ba690
                  sp--;
Packit 0ba690
               }
Packit 0ba690
               else
Packit 0ba690
                  sshift += s_inc;
Packit 0ba690
            }
Packit 0ba690
            break;
Packit 0ba690
         }
Packit 0ba690
         case 4:
Packit 0ba690
         {
Packit 0ba690
            png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
Packit 0ba690
            png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
Packit 0ba690
            int sshift, dshift;
Packit 0ba690
            int s_start, s_end, s_inc;
Packit 0ba690
            png_uint_32 i;
Packit 0ba690
            int jstop = png_pass_inc[pass];
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_PACKSWAP_SUPPORTED
Packit 0ba690
            if (transformations & PNG_PACKSWAP)
Packit 0ba690
            {
Packit 0ba690
               sshift = (int)(((row_info->width + 1) & 0x01) << 2);
Packit 0ba690
               dshift = (int)(((final_width + 1) & 0x01) << 2);
Packit 0ba690
               s_start = 4;
Packit 0ba690
               s_end = 0;
Packit 0ba690
               s_inc = -4;
Packit 0ba690
            }
Packit 0ba690
            else
Packit 0ba690
#endif
Packit 0ba690
            {
Packit 0ba690
               sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
Packit 0ba690
               dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
Packit 0ba690
               s_start = 0;
Packit 0ba690
               s_end = 4;
Packit 0ba690
               s_inc = 4;
Packit 0ba690
            }
Packit 0ba690
Packit 0ba690
            for (i = 0; i < row_info->width; i++)
Packit 0ba690
            {
Packit 0ba690
               png_byte v = (png_byte)((*sp >> sshift) & 0xf);
Packit 0ba690
               int j;
Packit 0ba690
Packit 0ba690
               for (j = 0; j < jstop; j++)
Packit 0ba690
               {
Packit 0ba690
                  *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
Packit 0ba690
                  *dp |= (png_byte)(v << dshift);
Packit 0ba690
                  if (dshift == s_end)
Packit 0ba690
                  {
Packit 0ba690
                     dshift = s_start;
Packit 0ba690
                     dp--;
Packit 0ba690
                  }
Packit 0ba690
                  else
Packit 0ba690
                     dshift += s_inc;
Packit 0ba690
               }
Packit 0ba690
               if (sshift == s_end)
Packit 0ba690
               {
Packit 0ba690
                  sshift = s_start;
Packit 0ba690
                  sp--;
Packit 0ba690
               }
Packit 0ba690
               else
Packit 0ba690
                  sshift += s_inc;
Packit 0ba690
            }
Packit 0ba690
            break;
Packit 0ba690
         }
Packit 0ba690
         default:
Packit 0ba690
         {
Packit 0ba690
            png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
Packit 0ba690
            png_bytep sp = row + (png_size_t)(row_info->width - 1)
Packit 0ba690
                * pixel_bytes;
Packit 0ba690
            png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
Packit 0ba690
Packit 0ba690
            int jstop = png_pass_inc[pass];
Packit 0ba690
            png_uint_32 i;
Packit 0ba690
Packit 0ba690
            for (i = 0; i < row_info->width; i++)
Packit 0ba690
            {
Packit 0ba690
               png_byte v[8];
Packit 0ba690
               int j;
Packit 0ba690
Packit 0ba690
               png_memcpy(v, sp, pixel_bytes);
Packit 0ba690
               for (j = 0; j < jstop; j++)
Packit 0ba690
               {
Packit 0ba690
                  png_memcpy(dp, v, pixel_bytes);
Packit 0ba690
                  dp -= pixel_bytes;
Packit 0ba690
               }
Packit 0ba690
               sp -= pixel_bytes;
Packit 0ba690
            }
Packit 0ba690
            break;
Packit 0ba690
         }
Packit 0ba690
      }
Packit 0ba690
      row_info->width = final_width;
Packit 0ba690
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width);
Packit 0ba690
   }
Packit 0ba690
#ifndef PNG_READ_PACKSWAP_SUPPORTED
Packit 0ba690
   PNG_UNUSED(transformations) /* Silence compiler warning */
Packit 0ba690
#endif
Packit 0ba690
}
Packit 0ba690
#endif /* PNG_READ_INTERLACING_SUPPORTED */
Packit 0ba690
Packit 0ba690
void /* PRIVATE */
Packit 0ba690
png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
Packit 0ba690
   png_bytep prev_row, int filter)
Packit 0ba690
{
Packit 0ba690
   png_debug(1, "in png_read_filter_row");
Packit 0ba690
   png_debug2(2, "row = %lu, filter = %d", png_ptr->row_number, filter);
Packit 0ba690
   switch (filter)
Packit 0ba690
   {
Packit 0ba690
      case PNG_FILTER_VALUE_NONE:
Packit 0ba690
         break;
Packit 0ba690
      case PNG_FILTER_VALUE_SUB:
Packit 0ba690
      {
Packit 0ba690
         png_uint_32 i;
Packit 0ba690
         png_uint_32 istop = row_info->rowbytes;
Packit 0ba690
         png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
Packit 0ba690
         png_bytep rp = row + bpp;
Packit 0ba690
         png_bytep lp = row;
Packit 0ba690
Packit 0ba690
         for (i = bpp; i < istop; i++)
Packit 0ba690
         {
Packit 0ba690
            *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
Packit 0ba690
            rp++;
Packit 0ba690
         }
Packit 0ba690
         break;
Packit 0ba690
      }
Packit 0ba690
      case PNG_FILTER_VALUE_UP:
Packit 0ba690
      {
Packit 0ba690
         png_uint_32 i;
Packit 0ba690
         png_uint_32 istop = row_info->rowbytes;
Packit 0ba690
         png_bytep rp = row;
Packit 0ba690
         png_bytep pp = prev_row;
Packit 0ba690
Packit 0ba690
         for (i = 0; i < istop; i++)
Packit 0ba690
         {
Packit 0ba690
            *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
Packit 0ba690
            rp++;
Packit 0ba690
         }
Packit 0ba690
         break;
Packit 0ba690
      }
Packit 0ba690
      case PNG_FILTER_VALUE_AVG:
Packit 0ba690
      {
Packit 0ba690
         png_uint_32 i;
Packit 0ba690
         png_bytep rp = row;
Packit 0ba690
         png_bytep pp = prev_row;
Packit 0ba690
         png_bytep lp = row;
Packit 0ba690
         png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
Packit 0ba690
         png_uint_32 istop = row_info->rowbytes - bpp;
Packit 0ba690
Packit 0ba690
         for (i = 0; i < bpp; i++)
Packit 0ba690
         {
Packit 0ba690
            *rp = (png_byte)(((int)(*rp) +
Packit 0ba690
               ((int)(*pp++) / 2 )) & 0xff);
Packit 0ba690
            rp++;
Packit 0ba690
         }
Packit 0ba690
Packit 0ba690
         for (i = 0; i < istop; i++)
Packit 0ba690
         {
Packit 0ba690
            *rp = (png_byte)(((int)(*rp) +
Packit 0ba690
               (int)(*pp++ + *lp++) / 2 ) & 0xff);
Packit 0ba690
            rp++;
Packit 0ba690
         }
Packit 0ba690
         break;
Packit 0ba690
      }
Packit 0ba690
      case PNG_FILTER_VALUE_PAETH:
Packit 0ba690
      {
Packit 0ba690
         png_uint_32 i;
Packit 0ba690
         png_bytep rp = row;
Packit 0ba690
         png_bytep pp = prev_row;
Packit 0ba690
         png_bytep lp = row;
Packit 0ba690
         png_bytep cp = prev_row;
Packit 0ba690
         png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
Packit 0ba690
         png_uint_32 istop=row_info->rowbytes - bpp;
Packit 0ba690
Packit 0ba690
         for (i = 0; i < bpp; i++)
Packit 0ba690
         {
Packit 0ba690
            *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
Packit 0ba690
            rp++;
Packit 0ba690
         }
Packit 0ba690
Packit 0ba690
         for (i = 0; i < istop; i++)   /* Use leftover rp,pp */
Packit 0ba690
         {
Packit 0ba690
            int a, b, c, pa, pb, pc, p;
Packit 0ba690
Packit 0ba690
            a = *lp++;
Packit 0ba690
            b = *pp++;
Packit 0ba690
            c = *cp++;
Packit 0ba690
Packit 0ba690
            p = b - c;
Packit 0ba690
            pc = a - c;
Packit 0ba690
Packit 0ba690
#ifdef PNG_USE_ABS
Packit 0ba690
            pa = abs(p);
Packit 0ba690
            pb = abs(pc);
Packit 0ba690
            pc = abs(p + pc);
Packit 0ba690
#else
Packit 0ba690
            pa = p < 0 ? -p : p;
Packit 0ba690
            pb = pc < 0 ? -pc : pc;
Packit 0ba690
            pc = (p + pc) < 0 ? -(p + pc) : p + pc;
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
            /*
Packit 0ba690
               if (pa <= pb && pa <= pc)
Packit 0ba690
                  p = a;
Packit 0ba690
               else if (pb <= pc)
Packit 0ba690
                  p = b;
Packit 0ba690
               else
Packit 0ba690
                  p = c;
Packit 0ba690
             */
Packit 0ba690
Packit 0ba690
            p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c;
Packit 0ba690
Packit 0ba690
            *rp = (png_byte)(((int)(*rp) + p) & 0xff);
Packit 0ba690
            rp++;
Packit 0ba690
         }
Packit 0ba690
         break;
Packit 0ba690
      }
Packit 0ba690
      default:
Packit 0ba690
         png_warning(png_ptr, "Ignoring bad adaptive filter type");
Packit 0ba690
         *row = 0;
Packit 0ba690
         break;
Packit 0ba690
   }
Packit 0ba690
}
Packit 0ba690
Packit 0ba690
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
Packit 0ba690
void /* PRIVATE */
Packit 0ba690
png_read_finish_row(png_structp png_ptr)
Packit 0ba690
{
Packit 0ba690
#ifdef PNG_READ_INTERLACING_SUPPORTED
Packit 0ba690
#ifndef PNG_USE_GLOBAL_ARRAYS
Packit 0ba690
   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
Packit 0ba690
Packit 0ba690
   /* Start of interlace block */
Packit 0ba690
   PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
Packit 0ba690
Packit 0ba690
   /* Offset to next interlace block */
Packit 0ba690
   PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
Packit 0ba690
Packit 0ba690
   /* Start of interlace block in the y direction */
Packit 0ba690
   PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
Packit 0ba690
Packit 0ba690
   /* Offset to next interlace block in the y direction */
Packit 0ba690
   PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
Packit 0ba690
#endif
Packit 0ba690
#endif /* PNG_READ_INTERLACING_SUPPORTED */
Packit 0ba690
Packit 0ba690
   png_debug(1, "in png_read_finish_row");
Packit 0ba690
   png_ptr->row_number++;
Packit 0ba690
   if (png_ptr->row_number < png_ptr->num_rows)
Packit 0ba690
      return;
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_INTERLACING_SUPPORTED
Packit 0ba690
   if (png_ptr->interlaced)
Packit 0ba690
   {
Packit 0ba690
      png_ptr->row_number = 0;
Packit 0ba690
      png_memset_check(png_ptr, png_ptr->prev_row, 0,
Packit 0ba690
         png_ptr->rowbytes + 1);
Packit 0ba690
      do
Packit 0ba690
      {
Packit 0ba690
         png_ptr->pass++;
Packit 0ba690
         if (png_ptr->pass >= 7)
Packit 0ba690
            break;
Packit 0ba690
         png_ptr->iwidth = (png_ptr->width +
Packit 0ba690
            png_pass_inc[png_ptr->pass] - 1 -
Packit 0ba690
            png_pass_start[png_ptr->pass]) /
Packit 0ba690
            png_pass_inc[png_ptr->pass];
Packit 0ba690
Packit 0ba690
         if (!(png_ptr->transformations & PNG_INTERLACE))
Packit 0ba690
         {
Packit 0ba690
            png_ptr->num_rows = (png_ptr->height +
Packit 0ba690
               png_pass_yinc[png_ptr->pass] - 1 -
Packit 0ba690
               png_pass_ystart[png_ptr->pass]) /
Packit 0ba690
               png_pass_yinc[png_ptr->pass];
Packit 0ba690
            if (!(png_ptr->num_rows))
Packit 0ba690
               continue;
Packit 0ba690
         }
Packit 0ba690
         else  /* if (png_ptr->transformations & PNG_INTERLACE) */
Packit 0ba690
            break;
Packit 0ba690
      } while (png_ptr->iwidth == 0);
Packit 0ba690
Packit 0ba690
      if (png_ptr->pass < 7)
Packit 0ba690
         return;
Packit 0ba690
   }
Packit 0ba690
#endif /* PNG_READ_INTERLACING_SUPPORTED */
Packit 0ba690
Packit 0ba690
   if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
Packit 0ba690
   {
Packit 0ba690
#ifdef PNG_USE_LOCAL_ARRAYS
Packit 0ba690
      PNG_CONST PNG_IDAT;
Packit 0ba690
#endif
Packit 0ba690
      char extra;
Packit 0ba690
      int ret;
Packit 0ba690
Packit 0ba690
      png_ptr->zstream.next_out = (Byte *)&extra;
Packit 0ba690
      png_ptr->zstream.avail_out = (uInt)1;
Packit 0ba690
      for (;;)
Packit 0ba690
      {
Packit 0ba690
         if (!(png_ptr->zstream.avail_in))
Packit 0ba690
         {
Packit 0ba690
            while (!png_ptr->idat_size)
Packit 0ba690
            {
Packit 0ba690
               png_byte chunk_length[4];
Packit 0ba690
Packit 0ba690
               png_crc_finish(png_ptr, 0);
Packit 0ba690
Packit 0ba690
               png_read_data(png_ptr, chunk_length, 4);
Packit 0ba690
               png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length);
Packit 0ba690
               png_reset_crc(png_ptr);
Packit 0ba690
               png_crc_read(png_ptr, png_ptr->chunk_name, 4);
Packit 0ba690
               if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
Packit 0ba690
                  png_error(png_ptr, "Not enough image data");
Packit 0ba690
Packit 0ba690
            }
Packit 0ba690
            png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
Packit 0ba690
            png_ptr->zstream.next_in = png_ptr->zbuf;
Packit 0ba690
            if (png_ptr->zbuf_size > png_ptr->idat_size)
Packit 0ba690
               png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
Packit 0ba690
            png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
Packit 0ba690
            png_ptr->idat_size -= png_ptr->zstream.avail_in;
Packit 0ba690
         }
Packit 0ba690
         ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
Packit 0ba690
         if (ret == Z_STREAM_END)
Packit 0ba690
         {
Packit 0ba690
            if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
Packit 0ba690
               png_ptr->idat_size)
Packit 0ba690
               png_warning(png_ptr, "Extra compressed data.");
Packit 0ba690
            png_ptr->mode |= PNG_AFTER_IDAT;
Packit 0ba690
            png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
Packit 0ba690
            break;
Packit 0ba690
         }
Packit 0ba690
         if (ret != Z_OK)
Packit 0ba690
            png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
Packit 0ba690
                      "Decompression Error");
Packit 0ba690
Packit 0ba690
         if (!(png_ptr->zstream.avail_out))
Packit 0ba690
         {
Packit 0ba690
            png_warning(png_ptr, "Extra compressed data.");
Packit 0ba690
            png_ptr->mode |= PNG_AFTER_IDAT;
Packit 0ba690
            png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
Packit 0ba690
            break;
Packit 0ba690
         }
Packit 0ba690
Packit 0ba690
      }
Packit 0ba690
      png_ptr->zstream.avail_out = 0;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   if (png_ptr->idat_size || png_ptr->zstream.avail_in)
Packit 0ba690
      png_warning(png_ptr, "Extra compression data.");
Packit 0ba690
Packit 0ba690
   inflateReset(&png_ptr->zstream);
Packit 0ba690
Packit 0ba690
   png_ptr->mode |= PNG_AFTER_IDAT;
Packit 0ba690
}
Packit 0ba690
#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
Packit 0ba690
Packit 0ba690
void /* PRIVATE */
Packit 0ba690
png_read_start_row(png_structp png_ptr)
Packit 0ba690
{
Packit 0ba690
#ifdef PNG_READ_INTERLACING_SUPPORTED
Packit 0ba690
#ifndef PNG_USE_GLOBAL_ARRAYS
Packit 0ba690
   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
Packit 0ba690
Packit 0ba690
   /* Start of interlace block */
Packit 0ba690
   PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
Packit 0ba690
Packit 0ba690
   /* Offset to next interlace block */
Packit 0ba690
   PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
Packit 0ba690
Packit 0ba690
   /* Start of interlace block in the y direction */
Packit 0ba690
   PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
Packit 0ba690
Packit 0ba690
   /* Offset to next interlace block in the y direction */
Packit 0ba690
   PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
Packit 0ba690
#endif
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
   int max_pixel_depth;
Packit 0ba690
   png_size_t row_bytes;
Packit 0ba690
Packit 0ba690
   png_debug(1, "in png_read_start_row");
Packit 0ba690
   png_ptr->zstream.avail_in = 0;
Packit 0ba690
   png_init_read_transformations(png_ptr);
Packit 0ba690
#ifdef PNG_READ_INTERLACING_SUPPORTED
Packit 0ba690
   if (png_ptr->interlaced)
Packit 0ba690
   {
Packit 0ba690
      if (!(png_ptr->transformations & PNG_INTERLACE))
Packit 0ba690
         png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
Packit 0ba690
            png_pass_ystart[0]) / png_pass_yinc[0];
Packit 0ba690
      else
Packit 0ba690
         png_ptr->num_rows = png_ptr->height;
Packit 0ba690
Packit 0ba690
      png_ptr->iwidth = (png_ptr->width +
Packit 0ba690
         png_pass_inc[png_ptr->pass] - 1 -
Packit 0ba690
         png_pass_start[png_ptr->pass]) /
Packit 0ba690
         png_pass_inc[png_ptr->pass];
Packit 0ba690
   }
Packit 0ba690
   else
Packit 0ba690
#endif /* PNG_READ_INTERLACING_SUPPORTED */
Packit 0ba690
   {
Packit 0ba690
      png_ptr->num_rows = png_ptr->height;
Packit 0ba690
      png_ptr->iwidth = png_ptr->width;
Packit 0ba690
   }
Packit 0ba690
   max_pixel_depth = png_ptr->pixel_depth;
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_PACK_SUPPORTED
Packit 0ba690
   if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
Packit 0ba690
      max_pixel_depth = 8;
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_EXPAND_SUPPORTED
Packit 0ba690
   if (png_ptr->transformations & PNG_EXPAND)
Packit 0ba690
   {
Packit 0ba690
      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Packit 0ba690
      {
Packit 0ba690
         if (png_ptr->num_trans)
Packit 0ba690
            max_pixel_depth = 32;
Packit 0ba690
         else
Packit 0ba690
            max_pixel_depth = 24;
Packit 0ba690
      }
Packit 0ba690
      else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
Packit 0ba690
      {
Packit 0ba690
         if (max_pixel_depth < 8)
Packit 0ba690
            max_pixel_depth = 8;
Packit 0ba690
         if (png_ptr->num_trans)
Packit 0ba690
            max_pixel_depth *= 2;
Packit 0ba690
      }
Packit 0ba690
      else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
Packit 0ba690
      {
Packit 0ba690
         if (png_ptr->num_trans)
Packit 0ba690
         {
Packit 0ba690
            max_pixel_depth *= 4;
Packit 0ba690
            max_pixel_depth /= 3;
Packit 0ba690
         }
Packit 0ba690
      }
Packit 0ba690
   }
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_FILLER_SUPPORTED
Packit 0ba690
   if (png_ptr->transformations & (PNG_FILLER))
Packit 0ba690
   {
Packit 0ba690
      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Packit 0ba690
         max_pixel_depth = 32;
Packit 0ba690
      else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
Packit 0ba690
      {
Packit 0ba690
         if (max_pixel_depth <= 8)
Packit 0ba690
            max_pixel_depth = 16;
Packit 0ba690
         else
Packit 0ba690
            max_pixel_depth = 32;
Packit 0ba690
      }
Packit 0ba690
      else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
Packit 0ba690
      {
Packit 0ba690
         if (max_pixel_depth <= 32)
Packit 0ba690
            max_pixel_depth = 32;
Packit 0ba690
         else
Packit 0ba690
            max_pixel_depth = 64;
Packit 0ba690
      }
Packit 0ba690
   }
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
Packit 0ba690
   if (png_ptr->transformations & PNG_GRAY_TO_RGB)
Packit 0ba690
   {
Packit 0ba690
      if (
Packit 0ba690
#ifdef PNG_READ_EXPAND_SUPPORTED
Packit 0ba690
        (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
Packit 0ba690
#endif
Packit 0ba690
#ifdef PNG_READ_FILLER_SUPPORTED
Packit 0ba690
        (png_ptr->transformations & (PNG_FILLER)) ||
Packit 0ba690
#endif
Packit 0ba690
        png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
Packit 0ba690
      {
Packit 0ba690
         if (max_pixel_depth <= 16)
Packit 0ba690
            max_pixel_depth = 32;
Packit 0ba690
         else
Packit 0ba690
            max_pixel_depth = 64;
Packit 0ba690
      }
Packit 0ba690
      else
Packit 0ba690
      {
Packit 0ba690
         if (max_pixel_depth <= 8)
Packit 0ba690
           {
Packit 0ba690
             if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
Packit 0ba690
               max_pixel_depth = 32;
Packit 0ba690
             else
Packit 0ba690
               max_pixel_depth = 24;
Packit 0ba690
           }
Packit 0ba690
         else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
Packit 0ba690
            max_pixel_depth = 64;
Packit 0ba690
         else
Packit 0ba690
            max_pixel_depth = 48;
Packit 0ba690
      }
Packit 0ba690
   }
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
Packit 0ba690
defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
Packit 0ba690
   if (png_ptr->transformations & PNG_USER_TRANSFORM)
Packit 0ba690
     {
Packit 0ba690
       int user_pixel_depth = png_ptr->user_transform_depth*
Packit 0ba690
         png_ptr->user_transform_channels;
Packit 0ba690
       if (user_pixel_depth > max_pixel_depth)
Packit 0ba690
         max_pixel_depth=user_pixel_depth;
Packit 0ba690
     }
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
   /* Align the width on the next larger 8 pixels.  Mainly used
Packit 0ba690
    * for interlacing
Packit 0ba690
    */
Packit 0ba690
   row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
Packit 0ba690
   /* Calculate the maximum bytes needed, adding a byte and a pixel
Packit 0ba690
    * for safety's sake
Packit 0ba690
    */
Packit 0ba690
   row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) +
Packit 0ba690
      1 + ((max_pixel_depth + 7) >> 3);
Packit 0ba690
#ifdef PNG_MAX_MALLOC_64K
Packit 0ba690
   if (row_bytes > (png_uint_32)65536L)
Packit 0ba690
      png_error(png_ptr, "This image requires a row greater than 64KB");
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
   if (row_bytes + 64 > png_ptr->old_big_row_buf_size)
Packit 0ba690
   {
Packit 0ba690
     png_free(png_ptr, png_ptr->big_row_buf);
Packit 0ba690
     if (png_ptr->interlaced)
Packit 0ba690
        png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr,
Packit 0ba690
            row_bytes + 64);
Packit 0ba690
     else
Packit 0ba690
        png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr,
Packit 0ba690
            row_bytes + 64);
Packit 0ba690
     png_ptr->old_big_row_buf_size = row_bytes + 64;
Packit 0ba690
Packit 0ba690
     /* Use 32 bytes of padding before and after row_buf. */
Packit 0ba690
     png_ptr->row_buf = png_ptr->big_row_buf + 32;
Packit 0ba690
     png_ptr->old_big_row_buf_size = row_bytes + 64;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
#ifdef PNG_MAX_MALLOC_64K
Packit 0ba690
   if ((png_uint_32)row_bytes + 1 > (png_uint_32)65536L)
Packit 0ba690
      png_error(png_ptr, "This image requires a row greater than 64KB");
Packit 0ba690
#endif
Packit 0ba690
   if ((png_uint_32)row_bytes > (png_uint_32)(PNG_SIZE_MAX - 1))
Packit 0ba690
      png_error(png_ptr, "Row has too many bytes to allocate in memory.");
Packit 0ba690
Packit 0ba690
   if (row_bytes + 1 > png_ptr->old_prev_row_size)
Packit 0ba690
   {
Packit 0ba690
      png_free(png_ptr, png_ptr->prev_row);
Packit 0ba690
      png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
Packit 0ba690
        row_bytes + 1));
Packit 0ba690
      png_memset_check(png_ptr, png_ptr->prev_row, 0, row_bytes + 1);
Packit 0ba690
      png_ptr->old_prev_row_size = row_bytes + 1;
Packit 0ba690
   }
Packit 0ba690
Packit 0ba690
   png_ptr->rowbytes = row_bytes;
Packit 0ba690
Packit 0ba690
   png_debug1(3, "width = %lu,", png_ptr->width);
Packit 0ba690
   png_debug1(3, "height = %lu,", png_ptr->height);
Packit 0ba690
   png_debug1(3, "iwidth = %lu,", png_ptr->iwidth);
Packit 0ba690
   png_debug1(3, "num_rows = %lu,", png_ptr->num_rows);
Packit 0ba690
   png_debug1(3, "rowbytes = %lu,", png_ptr->rowbytes);
Packit 0ba690
   png_debug1(3, "irowbytes = %lu",
Packit 0ba690
       PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1);
Packit 0ba690
Packit 0ba690
   png_ptr->flags |= PNG_FLAG_ROW_INIT;
Packit 0ba690
}
Packit 0ba690
#endif /* PNG_READ_SUPPORTED */