ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

pngrutil.c
Go to the documentation of this file.
00001 
00002 /* pngrutil.c - utilities to read a PNG file
00003  *
00004  * Last changed in libpng 1.5.9 [February 18, 2012]
00005  * Copyright (c) 1998-2012 Glenn Randers-Pehrson
00006  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
00007  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
00008  *
00009  * This code is released under the libpng license.
00010  * For conditions of distribution and use, see the disclaimer
00011  * and license in png.h
00012  *
00013  * This file contains routines that are only called from within
00014  * libpng itself during the course of reading an image.
00015  */
00016 
00017 #include "pngpriv.h"
00018 
00019 #ifdef PNG_READ_SUPPORTED
00020 
00021 #define png_strtod(p,a,b) strtod(a,b)
00022 
00023 png_uint_32 PNGAPI
00024 png_get_uint_31(png_structp png_ptr, png_const_bytep buf)
00025 {
00026    png_uint_32 uval = png_get_uint_32(buf);
00027 
00028    if (uval > PNG_UINT_31_MAX)
00029       png_error(png_ptr, "PNG unsigned integer out of range");
00030 
00031    return (uval);
00032 }
00033 
00034 #if defined(PNG_READ_gAMA_SUPPORTED) || defined(PNG_READ_cHRM_SUPPORTED)
00035 /* The following is a variation on the above for use with the fixed
00036  * point values used for gAMA and cHRM.  Instead of png_error it
00037  * issues a warning and returns (-1) - an invalid value because both
00038  * gAMA and cHRM use *unsigned* integers for fixed point values.
00039  */
00040 #define PNG_FIXED_ERROR (-1)
00041 
00042 static png_fixed_point /* PRIVATE */
00043 png_get_fixed_point(png_structp png_ptr, png_const_bytep buf)
00044 {
00045    png_uint_32 uval = png_get_uint_32(buf);
00046 
00047    if (uval <= PNG_UINT_31_MAX)
00048       return (png_fixed_point)uval; /* known to be in range */
00049 
00050    /* The caller can turn off the warning by passing NULL. */
00051    if (png_ptr != NULL)
00052       png_warning(png_ptr, "PNG fixed point integer out of range");
00053 
00054    return PNG_FIXED_ERROR;
00055 }
00056 #endif
00057 
00058 #ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED
00059 /* NOTE: the read macros will obscure these definitions, so that if
00060  * PNG_USE_READ_MACROS is set the library will not use them internally,
00061  * but the APIs will still be available externally.
00062  *
00063  * The parentheses around "PNGAPI function_name" in the following three
00064  * functions are necessary because they allow the macros to co-exist with
00065  * these (unused but exported) functions.
00066  */
00067 
00068 /* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
00069 png_uint_32 (PNGAPI
00070 png_get_uint_32)(png_const_bytep buf)
00071 {
00072    png_uint_32 uval =
00073        ((png_uint_32)(*(buf    )) << 24) +
00074        ((png_uint_32)(*(buf + 1)) << 16) +
00075        ((png_uint_32)(*(buf + 2)) <<  8) +
00076        ((png_uint_32)(*(buf + 3))      ) ;
00077 
00078    return uval;
00079 }
00080 
00081 /* Grab a signed 32-bit integer from a buffer in big-endian format.  The
00082  * data is stored in the PNG file in two's complement format and there
00083  * is no guarantee that a 'png_int_32' is exactly 32 bits, therefore
00084  * the following code does a two's complement to native conversion.
00085  */
00086 png_int_32 (PNGAPI
00087 png_get_int_32)(png_const_bytep buf)
00088 {
00089    png_uint_32 uval = png_get_uint_32(buf);
00090    if ((uval & 0x80000000) == 0) /* non-negative */
00091       return uval;
00092 
00093    uval = (uval ^ 0xffffffff) + 1;  /* 2's complement: -x = ~x+1 */
00094    return -(png_int_32)uval;
00095 }
00096 
00097 /* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
00098 png_uint_16 (PNGAPI
00099 png_get_uint_16)(png_const_bytep buf)
00100 {
00101    /* ANSI-C requires an int value to accomodate at least 16 bits so this
00102     * works and allows the compiler not to worry about possible narrowing
00103     * on 32 bit systems.  (Pre-ANSI systems did not make integers smaller
00104     * than 16 bits either.)
00105     */
00106    unsigned int val =
00107        ((unsigned int)(*buf) << 8) +
00108        ((unsigned int)(*(buf + 1)));
00109 
00110    return (png_uint_16)val;
00111 }
00112 
00113 #endif /* PNG_READ_INT_FUNCTIONS_SUPPORTED */
00114 
00115 /* Read and check the PNG file signature */
00116 void /* PRIVATE */
00117 png_read_sig(png_structp png_ptr, png_infop info_ptr)
00118 {
00119    png_size_t num_checked, num_to_check;
00120 
00121    /* Exit if the user application does not expect a signature. */
00122    if (png_ptr->sig_bytes >= 8)
00123       return;
00124 
00125    num_checked = png_ptr->sig_bytes;
00126    num_to_check = 8 - num_checked;
00127 
00128 #ifdef PNG_IO_STATE_SUPPORTED
00129    png_ptr->io_state = PNG_IO_READING | PNG_IO_SIGNATURE;
00130 #endif
00131 
00132    /* The signature must be serialized in a single I/O call. */
00133    png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check);
00134    png_ptr->sig_bytes = 8;
00135 
00136    if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
00137    {
00138       if (num_checked < 4 &&
00139           png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
00140          png_error(png_ptr, "Not a PNG file");
00141       else
00142          png_error(png_ptr, "PNG file corrupted by ASCII conversion");
00143    }
00144    if (num_checked < 3)
00145       png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE;
00146 }
00147 
00148 /* Read the chunk header (length + type name).
00149  * Put the type name into png_ptr->chunk_name, and return the length.
00150  */
00151 png_uint_32 /* PRIVATE */
00152 png_read_chunk_header(png_structp png_ptr)
00153 {
00154    png_byte buf[8];
00155    png_uint_32 length;
00156 
00157 #ifdef PNG_IO_STATE_SUPPORTED
00158    png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_HDR;
00159 #endif
00160 
00161    /* Read the length and the chunk name.
00162     * This must be performed in a single I/O call.
00163     */
00164    png_read_data(png_ptr, buf, 8);
00165    length = png_get_uint_31(png_ptr, buf);
00166 
00167    /* Put the chunk name into png_ptr->chunk_name. */
00168    png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(buf+4);
00169 
00170    png_debug2(0, "Reading %lx chunk, length = %lu",
00171        (unsigned long)png_ptr->chunk_name, (unsigned long)length);
00172 
00173    /* Reset the crc and run it over the chunk name. */
00174    png_reset_crc(png_ptr);
00175    png_calculate_crc(png_ptr, buf + 4, 4);
00176 
00177    /* Check to see if chunk name is valid. */
00178    png_check_chunk_name(png_ptr, png_ptr->chunk_name);
00179 
00180 #ifdef PNG_IO_STATE_SUPPORTED
00181    png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_DATA;
00182 #endif
00183 
00184    return length;
00185 }
00186 
00187 /* Read data, and (optionally) run it through the CRC. */
00188 void /* PRIVATE */
00189 png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
00190 {
00191    if (png_ptr == NULL)
00192       return;
00193 
00194    png_read_data(png_ptr, buf, length);
00195    png_calculate_crc(png_ptr, buf, length);
00196 }
00197 
00198 /* Optionally skip data and then check the CRC.  Depending on whether we
00199  * are reading a ancillary or critical chunk, and how the program has set
00200  * things up, we may calculate the CRC on the data and print a message.
00201  * Returns '1' if there was a CRC error, '0' otherwise.
00202  */
00203 int /* PRIVATE */
00204 png_crc_finish(png_structp png_ptr, png_uint_32 skip)
00205 {
00206    png_size_t i;
00207    png_size_t istop = png_ptr->zbuf_size;
00208 
00209    for (i = (png_size_t)skip; i > istop; i -= istop)
00210    {
00211       png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
00212    }
00213 
00214    if (i)
00215    {
00216       png_crc_read(png_ptr, png_ptr->zbuf, i);
00217    }
00218 
00219    if (png_crc_error(png_ptr))
00220    {
00221       if (PNG_CHUNK_ANCILLIARY(png_ptr->chunk_name) ?
00222           !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) :
00223           (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE))
00224       {
00225          png_chunk_warning(png_ptr, "CRC error");
00226       }
00227 
00228       else
00229       {
00230          png_chunk_benign_error(png_ptr, "CRC error");
00231          return (0);
00232       }
00233 
00234       return (1);
00235    }
00236 
00237    return (0);
00238 }
00239 
00240 /* Compare the CRC stored in the PNG file with that calculated by libpng from
00241  * the data it has read thus far.
00242  */
00243 int /* PRIVATE */
00244 png_crc_error(png_structp png_ptr)
00245 {
00246    png_byte crc_bytes[4];
00247    png_uint_32 crc;
00248    int need_crc = 1;
00249 
00250    if (PNG_CHUNK_ANCILLIARY(png_ptr->chunk_name))
00251    {
00252       if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
00253           (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
00254          need_crc = 0;
00255    }
00256 
00257    else /* critical */
00258    {
00259       if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
00260          need_crc = 0;
00261    }
00262 
00263 #ifdef PNG_IO_STATE_SUPPORTED
00264    png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_CRC;
00265 #endif
00266 
00267    /* The chunk CRC must be serialized in a single I/O call. */
00268    png_read_data(png_ptr, crc_bytes, 4);
00269 
00270    if (need_crc)
00271    {
00272       crc = png_get_uint_32(crc_bytes);
00273       return ((int)(crc != png_ptr->crc));
00274    }
00275 
00276    else
00277       return (0);
00278 }
00279 
00280 #ifdef PNG_READ_COMPRESSED_TEXT_SUPPORTED
00281 static png_size_t
00282 png_inflate(png_structp png_ptr, png_bytep data, png_size_t size,
00283     png_bytep output, png_size_t output_size)
00284 {
00285    png_size_t count = 0;
00286 
00287    /* zlib can't necessarily handle more than 65535 bytes at once (i.e. it can't
00288     * even necessarily handle 65536 bytes) because the type uInt is "16 bits or
00289     * more".  Consequently it is necessary to chunk the input to zlib.  This
00290     * code uses ZLIB_IO_MAX, from pngpriv.h, as the maximum (the maximum value
00291     * that can be stored in a uInt.)  It is possible to set ZLIB_IO_MAX to a
00292     * lower value in pngpriv.h and this may sometimes have a performance
00293     * advantage, because it forces access of the input data to be separated from
00294     * at least some of the use by some period of time.
00295     */
00296    png_ptr->zstream.next_in = data;
00297    /* avail_in is set below from 'size' */
00298    png_ptr->zstream.avail_in = 0;
00299 
00300    while (1)
00301    {
00302       int ret, avail;
00303 
00304       /* The setting of 'avail_in' used to be outside the loop; by setting it
00305        * inside it is possible to chunk the input to zlib and simply rely on
00306        * zlib to advance the 'next_in' pointer.  This allows arbitrary amounts o
00307        * data to be passed through zlib at the unavoidable cost of requiring a
00308        * window save (memcpy of up to 32768 output bytes) every ZLIB_IO_MAX
00309        * input bytes.
00310        */
00311       if (png_ptr->zstream.avail_in == 0 && size > 0)
00312       {
00313          if (size <= ZLIB_IO_MAX)
00314          {
00315             /* The value is less than ZLIB_IO_MAX so the cast is safe: */
00316             png_ptr->zstream.avail_in = (uInt)size;
00317             size = 0;
00318          }
00319 
00320          else
00321          {
00322             png_ptr->zstream.avail_in = ZLIB_IO_MAX;
00323             size -= ZLIB_IO_MAX;
00324          }
00325       }
00326 
00327       /* Reset the output buffer each time round - we empty it
00328        * after every inflate call.
00329        */
00330       png_ptr->zstream.next_out = png_ptr->zbuf;
00331       png_ptr->zstream.avail_out = png_ptr->zbuf_size;
00332 
00333       ret = inflate(&png_ptr->zstream, Z_NO_FLUSH);
00334       avail = png_ptr->zbuf_size - png_ptr->zstream.avail_out;
00335 
00336       /* First copy/count any new output - but only if we didn't
00337        * get an error code.
00338        */
00339       if ((ret == Z_OK || ret == Z_STREAM_END) && avail > 0)
00340       {
00341          png_size_t space = avail; /* > 0, see above */
00342 
00343          if (output != 0 && output_size > count)
00344          {
00345             png_size_t copy = output_size - count;
00346 
00347             if (space < copy)
00348                copy = space;
00349 
00350             png_memcpy(output + count, png_ptr->zbuf, copy);
00351          }
00352          count += space;
00353       }
00354 
00355       if (ret == Z_OK)
00356          continue;
00357 
00358       /* Termination conditions - always reset the zstream, it
00359        * must be left in inflateInit state.
00360        */
00361       png_ptr->zstream.avail_in = 0;
00362       inflateReset(&png_ptr->zstream);
00363 
00364       if (ret == Z_STREAM_END)
00365          return count; /* NOTE: may be zero. */
00366 
00367       /* Now handle the error codes - the API always returns 0
00368        * and the error message is dumped into the uncompressed
00369        * buffer if available.
00370        */
00371 #     ifdef PNG_WARNINGS_SUPPORTED
00372       {
00373          png_const_charp msg;
00374 
00375          if (png_ptr->zstream.msg != 0)
00376             msg = png_ptr->zstream.msg;
00377 
00378          else switch (ret)
00379          {
00380             case Z_BUF_ERROR:
00381                msg = "Buffer error in compressed datastream";
00382                break;
00383 
00384             case Z_DATA_ERROR:
00385                msg = "Data error in compressed datastream";
00386                break;
00387 
00388             default:
00389                msg = "Incomplete compressed datastream";
00390                break;
00391          }
00392 
00393          png_chunk_warning(png_ptr, msg);
00394       }
00395 #     endif
00396 
00397       /* 0 means an error - notice that this code simply ignores
00398        * zero length compressed chunks as a result.
00399        */
00400       return 0;
00401    }
00402 }
00403 
00404 /*
00405  * Decompress trailing data in a chunk.  The assumption is that chunkdata
00406  * points at an allocated area holding the contents of a chunk with a
00407  * trailing compressed part.  What we get back is an allocated area
00408  * holding the original prefix part and an uncompressed version of the
00409  * trailing part (the malloc area passed in is freed).
00410  */
00411 void /* PRIVATE */
00412 png_decompress_chunk(png_structp png_ptr, int comp_type,
00413     png_size_t chunklength,
00414     png_size_t prefix_size, png_size_t *newlength)
00415 {
00416    /* The caller should guarantee this */
00417    if (prefix_size > chunklength)
00418    {
00419       /* The recovery is to delete the chunk. */
00420       png_warning(png_ptr, "invalid chunklength");
00421       prefix_size = 0; /* To delete everything */
00422    }
00423 
00424    else if (comp_type == PNG_COMPRESSION_TYPE_BASE)
00425    {
00426       png_size_t expanded_size = png_inflate(png_ptr,
00427           (png_bytep)(png_ptr->chunkdata + prefix_size),
00428           chunklength - prefix_size,
00429           0,            /* output */
00430           0);           /* output size */
00431 
00432       /* Now check the limits on this chunk - if the limit fails the
00433        * compressed data will be removed, the prefix will remain.
00434        */
00435       if (prefix_size >= (~(png_size_t)0) - 1 ||
00436          expanded_size >= (~(png_size_t)0) - 1 - prefix_size
00437 #ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
00438          || (png_ptr->user_chunk_malloc_max &&
00439           (prefix_size + expanded_size >= png_ptr->user_chunk_malloc_max - 1))
00440 #else
00441 #  ifdef PNG_USER_CHUNK_MALLOC_MAX
00442          || ((PNG_USER_CHUNK_MALLOC_MAX > 0) &&
00443           prefix_size + expanded_size >= PNG_USER_CHUNK_MALLOC_MAX - 1)
00444 #  endif
00445 #endif
00446          )
00447          png_warning(png_ptr, "Exceeded size limit while expanding chunk");
00448 
00449       /* If the size is zero either there was an error and a message
00450        * has already been output (warning) or the size really is zero
00451        * and we have nothing to do - the code will exit through the
00452        * error case below.
00453        */
00454       else if (expanded_size > 0)
00455       {
00456          /* Success (maybe) - really uncompress the chunk. */
00457          png_size_t new_size = 0;
00458          png_charp text = (png_charp)png_malloc_warn(png_ptr,
00459              prefix_size + expanded_size + 1);
00460 
00461          if (text != NULL)
00462          {
00463             png_memcpy(text, png_ptr->chunkdata, prefix_size);
00464             new_size = png_inflate(png_ptr,
00465                 (png_bytep)(png_ptr->chunkdata + prefix_size),
00466                 chunklength - prefix_size,
00467                 (png_bytep)(text + prefix_size), expanded_size);
00468             text[prefix_size + expanded_size] = 0; /* just in case */
00469 
00470             if (new_size == expanded_size)
00471             {
00472                png_free(png_ptr, png_ptr->chunkdata);
00473                png_ptr->chunkdata = text;
00474                *newlength = prefix_size + expanded_size;
00475                return; /* The success return! */
00476             }
00477 
00478             png_warning(png_ptr, "png_inflate logic error");
00479             png_free(png_ptr, text);
00480          }
00481 
00482          else
00483             png_warning(png_ptr, "Not enough memory to decompress chunk");
00484       }
00485    }
00486 
00487    else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
00488    {
00489       PNG_WARNING_PARAMETERS(p)
00490       png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_d, comp_type);
00491       png_formatted_warning(png_ptr, p, "Unknown compression type @1");
00492 
00493       /* The recovery is to simply drop the data. */
00494    }
00495 
00496    /* Generic error return - leave the prefix, delete the compressed
00497     * data, reallocate the chunkdata to remove the potentially large
00498     * amount of compressed data.
00499     */
00500    {
00501       png_charp text = (png_charp)png_malloc_warn(png_ptr, prefix_size + 1);
00502 
00503       if (text != NULL)
00504       {
00505          if (prefix_size > 0)
00506             png_memcpy(text, png_ptr->chunkdata, prefix_size);
00507 
00508          png_free(png_ptr, png_ptr->chunkdata);
00509          png_ptr->chunkdata = text;
00510 
00511          /* This is an extra zero in the 'uncompressed' part. */
00512          *(png_ptr->chunkdata + prefix_size) = 0x00;
00513       }
00514       /* Ignore a malloc error here - it is safe. */
00515    }
00516 
00517    *newlength = prefix_size;
00518 }
00519 #endif /* PNG_READ_COMPRESSED_TEXT_SUPPORTED */
00520 
00521 /* Read and check the IDHR chunk */
00522 void /* PRIVATE */
00523 png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
00524 {
00525    png_byte buf[13];
00526    png_uint_32 width, height;
00527    int bit_depth, color_type, compression_type, filter_type;
00528    int interlace_type;
00529 
00530    png_debug(1, "in png_handle_IHDR");
00531 
00532    if (png_ptr->mode & PNG_HAVE_IHDR)
00533       png_error(png_ptr, "Out of place IHDR");
00534 
00535    /* Check the length */
00536    if (length != 13)
00537       png_error(png_ptr, "Invalid IHDR chunk");
00538 
00539    png_ptr->mode |= PNG_HAVE_IHDR;
00540 
00541    png_crc_read(png_ptr, buf, 13);
00542    png_crc_finish(png_ptr, 0);
00543 
00544    width = png_get_uint_31(png_ptr, buf);
00545    height = png_get_uint_31(png_ptr, buf + 4);
00546    bit_depth = buf[8];
00547    color_type = buf[9];
00548    compression_type = buf[10];
00549    filter_type = buf[11];
00550    interlace_type = buf[12];
00551 
00552    /* Set internal variables */
00553    png_ptr->width = width;
00554    png_ptr->height = height;
00555    png_ptr->bit_depth = (png_byte)bit_depth;
00556    png_ptr->interlaced = (png_byte)interlace_type;
00557    png_ptr->color_type = (png_byte)color_type;
00558 #ifdef PNG_MNG_FEATURES_SUPPORTED
00559    png_ptr->filter_type = (png_byte)filter_type;
00560 #endif
00561    png_ptr->compression_type = (png_byte)compression_type;
00562 
00563    /* Find number of channels */
00564    switch (png_ptr->color_type)
00565    {
00566       default: /* invalid, png_set_IHDR calls png_error */
00567       case PNG_COLOR_TYPE_GRAY:
00568       case PNG_COLOR_TYPE_PALETTE:
00569          png_ptr->channels = 1;
00570          break;
00571 
00572       case PNG_COLOR_TYPE_RGB:
00573          png_ptr->channels = 3;
00574          break;
00575 
00576       case PNG_COLOR_TYPE_GRAY_ALPHA:
00577          png_ptr->channels = 2;
00578          break;
00579 
00580       case PNG_COLOR_TYPE_RGB_ALPHA:
00581          png_ptr->channels = 4;
00582          break;
00583    }
00584 
00585    /* Set up other useful info */
00586    png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
00587    png_ptr->channels);
00588    png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width);
00589    png_debug1(3, "bit_depth = %d", png_ptr->bit_depth);
00590    png_debug1(3, "channels = %d", png_ptr->channels);
00591    png_debug1(3, "rowbytes = %lu", (unsigned long)png_ptr->rowbytes);
00592    png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
00593        color_type, interlace_type, compression_type, filter_type);
00594 }
00595 
00596 /* Read and check the palette */
00597 void /* PRIVATE */
00598 png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
00599 {
00600    png_color palette[PNG_MAX_PALETTE_LENGTH];
00601    int num, i;
00602 #ifdef PNG_POINTER_INDEXING_SUPPORTED
00603    png_colorp pal_ptr;
00604 #endif
00605 
00606    png_debug(1, "in png_handle_PLTE");
00607 
00608    if (!(png_ptr->mode & PNG_HAVE_IHDR))
00609       png_error(png_ptr, "Missing IHDR before PLTE");
00610 
00611    else if (png_ptr->mode & PNG_HAVE_IDAT)
00612    {
00613       png_warning(png_ptr, "Invalid PLTE after IDAT");
00614       png_crc_finish(png_ptr, length);
00615       return;
00616    }
00617 
00618    else if (png_ptr->mode & PNG_HAVE_PLTE)
00619       png_error(png_ptr, "Duplicate PLTE chunk");
00620 
00621    png_ptr->mode |= PNG_HAVE_PLTE;
00622 
00623    if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
00624    {
00625       png_warning(png_ptr,
00626           "Ignoring PLTE chunk in grayscale PNG");
00627       png_crc_finish(png_ptr, length);
00628       return;
00629    }
00630 
00631 #ifndef PNG_READ_OPT_PLTE_SUPPORTED
00632    if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
00633    {
00634       png_crc_finish(png_ptr, length);
00635       return;
00636    }
00637 #endif
00638 
00639    if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
00640    {
00641       if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
00642       {
00643          png_warning(png_ptr, "Invalid palette chunk");
00644          png_crc_finish(png_ptr, length);
00645          return;
00646       }
00647 
00648       else
00649       {
00650          png_error(png_ptr, "Invalid palette chunk");
00651       }
00652    }
00653 
00654    num = (int)length / 3;
00655 
00656 #ifdef PNG_POINTER_INDEXING_SUPPORTED
00657    for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
00658    {
00659       png_byte buf[3];
00660 
00661       png_crc_read(png_ptr, buf, 3);
00662       pal_ptr->red = buf[0];
00663       pal_ptr->green = buf[1];
00664       pal_ptr->blue = buf[2];
00665    }
00666 #else
00667    for (i = 0; i < num; i++)
00668    {
00669       png_byte buf[3];
00670 
00671       png_crc_read(png_ptr, buf, 3);
00672       /* Don't depend upon png_color being any order */
00673       palette[i].red = buf[0];
00674       palette[i].green = buf[1];
00675       palette[i].blue = buf[2];
00676    }
00677 #endif
00678 
00679    /* If we actually need the PLTE chunk (ie for a paletted image), we do
00680     * whatever the normal CRC configuration tells us.  However, if we
00681     * have an RGB image, the PLTE can be considered ancillary, so
00682     * we will act as though it is.
00683     */
00684 #ifndef PNG_READ_OPT_PLTE_SUPPORTED
00685    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
00686 #endif
00687    {
00688       png_crc_finish(png_ptr, 0);
00689    }
00690 
00691 #ifndef PNG_READ_OPT_PLTE_SUPPORTED
00692    else if (png_crc_error(png_ptr))  /* Only if we have a CRC error */
00693    {
00694       /* If we don't want to use the data from an ancillary chunk,
00695        * we have two options: an error abort, or a warning and we
00696        * ignore the data in this chunk (which should be OK, since
00697        * it's considered ancillary for a RGB or RGBA image).
00698        */
00699       if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
00700       {
00701          if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
00702          {
00703             png_chunk_benign_error(png_ptr, "CRC error");
00704          }
00705 
00706          else
00707          {
00708             png_chunk_warning(png_ptr, "CRC error");
00709             return;
00710          }
00711       }
00712 
00713       /* Otherwise, we (optionally) emit a warning and use the chunk. */
00714       else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
00715       {
00716          png_chunk_warning(png_ptr, "CRC error");
00717       }
00718    }
00719 #endif
00720 
00721    png_set_PLTE(png_ptr, info_ptr, palette, num);
00722 
00723 #ifdef PNG_READ_tRNS_SUPPORTED
00724    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
00725    {
00726       if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
00727       {
00728          if (png_ptr->num_trans > (png_uint_16)num)
00729          {
00730             png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
00731             png_ptr->num_trans = (png_uint_16)num;
00732          }
00733 
00734          if (info_ptr->num_trans > (png_uint_16)num)
00735          {
00736             png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
00737             info_ptr->num_trans = (png_uint_16)num;
00738          }
00739       }
00740    }
00741 #endif
00742 
00743 }
00744 
00745 void /* PRIVATE */
00746 png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
00747 {
00748    png_debug(1, "in png_handle_IEND");
00749 
00750    if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
00751    {
00752       png_error(png_ptr, "No image in file");
00753    }
00754 
00755    png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
00756 
00757    if (length != 0)
00758    {
00759       png_warning(png_ptr, "Incorrect IEND chunk length");
00760    }
00761 
00762    png_crc_finish(png_ptr, length);
00763 
00764    PNG_UNUSED(info_ptr) /* Quiet compiler warnings about unused info_ptr */
00765 }
00766 
00767 #ifdef PNG_READ_gAMA_SUPPORTED
00768 void /* PRIVATE */
00769 png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
00770 {
00771    png_fixed_point igamma;
00772    png_byte buf[4];
00773 
00774    png_debug(1, "in png_handle_gAMA");
00775 
00776    if (!(png_ptr->mode & PNG_HAVE_IHDR))
00777       png_error(png_ptr, "Missing IHDR before gAMA");
00778 
00779    else if (png_ptr->mode & PNG_HAVE_IDAT)
00780    {
00781       png_warning(png_ptr, "Invalid gAMA after IDAT");
00782       png_crc_finish(png_ptr, length);
00783       return;
00784    }
00785 
00786    else if (png_ptr->mode & PNG_HAVE_PLTE)
00787       /* Should be an error, but we can cope with it */
00788       png_warning(png_ptr, "Out of place gAMA chunk");
00789 
00790    if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
00791 #ifdef PNG_READ_sRGB_SUPPORTED
00792        && !(info_ptr->valid & PNG_INFO_sRGB)
00793 #endif
00794        )
00795    {
00796       png_warning(png_ptr, "Duplicate gAMA chunk");
00797       png_crc_finish(png_ptr, length);
00798       return;
00799    }
00800 
00801    if (length != 4)
00802    {
00803       png_warning(png_ptr, "Incorrect gAMA chunk length");
00804       png_crc_finish(png_ptr, length);
00805       return;
00806    }
00807 
00808    png_crc_read(png_ptr, buf, 4);
00809 
00810    if (png_crc_finish(png_ptr, 0))
00811       return;
00812 
00813    igamma = png_get_fixed_point(NULL, buf);
00814 
00815    /* Check for zero gamma or an error. */
00816    if (igamma <= 0)
00817    {
00818       png_warning(png_ptr,
00819           "Ignoring gAMA chunk with out of range gamma");
00820 
00821       return;
00822    }
00823 
00824 #  ifdef PNG_READ_sRGB_SUPPORTED
00825    if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
00826    {
00827       if (PNG_OUT_OF_RANGE(igamma, 45500, 500))
00828       {
00829          PNG_WARNING_PARAMETERS(p)
00830          png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_fixed, igamma);
00831          png_formatted_warning(png_ptr, p,
00832              "Ignoring incorrect gAMA value @1 when sRGB is also present");
00833          return;
00834       }
00835    }
00836 #  endif /* PNG_READ_sRGB_SUPPORTED */
00837 
00838 #  ifdef PNG_READ_GAMMA_SUPPORTED
00839    /* Gamma correction on read is supported. */
00840    png_ptr->gamma = igamma;
00841 #  endif
00842    /* And set the 'info' structure members. */
00843    png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
00844 }
00845 #endif
00846 
00847 #ifdef PNG_READ_sBIT_SUPPORTED
00848 void /* PRIVATE */
00849 png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
00850 {
00851    png_size_t truelen;
00852    png_byte buf[4];
00853 
00854    png_debug(1, "in png_handle_sBIT");
00855 
00856    buf[0] = buf[1] = buf[2] = buf[3] = 0;
00857 
00858    if (!(png_ptr->mode & PNG_HAVE_IHDR))
00859       png_error(png_ptr, "Missing IHDR before sBIT");
00860 
00861    else if (png_ptr->mode & PNG_HAVE_IDAT)
00862    {
00863       png_warning(png_ptr, "Invalid sBIT after IDAT");
00864       png_crc_finish(png_ptr, length);
00865       return;
00866    }
00867 
00868    else if (png_ptr->mode & PNG_HAVE_PLTE)
00869    {
00870       /* Should be an error, but we can cope with it */
00871       png_warning(png_ptr, "Out of place sBIT chunk");
00872    }
00873 
00874    if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
00875    {
00876       png_warning(png_ptr, "Duplicate sBIT chunk");
00877       png_crc_finish(png_ptr, length);
00878       return;
00879    }
00880 
00881    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
00882       truelen = 3;
00883 
00884    else
00885       truelen = (png_size_t)png_ptr->channels;
00886 
00887    if (length != truelen || length > 4)
00888    {
00889       png_warning(png_ptr, "Incorrect sBIT chunk length");
00890       png_crc_finish(png_ptr, length);
00891       return;
00892    }
00893 
00894    png_crc_read(png_ptr, buf, truelen);
00895 
00896    if (png_crc_finish(png_ptr, 0))
00897       return;
00898 
00899    if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
00900    {
00901       png_ptr->sig_bit.red = buf[0];
00902       png_ptr->sig_bit.green = buf[1];
00903       png_ptr->sig_bit.blue = buf[2];
00904       png_ptr->sig_bit.alpha = buf[3];
00905    }
00906 
00907    else
00908    {
00909       png_ptr->sig_bit.gray = buf[0];
00910       png_ptr->sig_bit.red = buf[0];
00911       png_ptr->sig_bit.green = buf[0];
00912       png_ptr->sig_bit.blue = buf[0];
00913       png_ptr->sig_bit.alpha = buf[1];
00914    }
00915 
00916    png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
00917 }
00918 #endif
00919 
00920 #ifdef PNG_READ_cHRM_SUPPORTED
00921 void /* PRIVATE */
00922 png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
00923 {
00924    png_byte buf[32];
00925    png_fixed_point x_white, y_white, x_red, y_red, x_green, y_green, x_blue,
00926       y_blue;
00927 
00928    png_debug(1, "in png_handle_cHRM");
00929 
00930    if (!(png_ptr->mode & PNG_HAVE_IHDR))
00931       png_error(png_ptr, "Missing IHDR before cHRM");
00932 
00933    else if (png_ptr->mode & PNG_HAVE_IDAT)
00934    {
00935       png_warning(png_ptr, "Invalid cHRM after IDAT");
00936       png_crc_finish(png_ptr, length);
00937       return;
00938    }
00939 
00940    else if (png_ptr->mode & PNG_HAVE_PLTE)
00941       /* Should be an error, but we can cope with it */
00942       png_warning(png_ptr, "Out of place cHRM chunk");
00943 
00944    if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
00945 #  ifdef PNG_READ_sRGB_SUPPORTED
00946        && !(info_ptr->valid & PNG_INFO_sRGB)
00947 #  endif
00948       )
00949    {
00950       png_warning(png_ptr, "Duplicate cHRM chunk");
00951       png_crc_finish(png_ptr, length);
00952       return;
00953    }
00954 
00955    if (length != 32)
00956    {
00957       png_warning(png_ptr, "Incorrect cHRM chunk length");
00958       png_crc_finish(png_ptr, length);
00959       return;
00960    }
00961 
00962    png_crc_read(png_ptr, buf, 32);
00963 
00964    if (png_crc_finish(png_ptr, 0))
00965       return;
00966 
00967    x_white = png_get_fixed_point(NULL, buf);
00968    y_white = png_get_fixed_point(NULL, buf + 4);
00969    x_red   = png_get_fixed_point(NULL, buf + 8);
00970    y_red   = png_get_fixed_point(NULL, buf + 12);
00971    x_green = png_get_fixed_point(NULL, buf + 16);
00972    y_green = png_get_fixed_point(NULL, buf + 20);
00973    x_blue  = png_get_fixed_point(NULL, buf + 24);
00974    y_blue  = png_get_fixed_point(NULL, buf + 28);
00975 
00976    if (x_white == PNG_FIXED_ERROR ||
00977        y_white == PNG_FIXED_ERROR ||
00978        x_red   == PNG_FIXED_ERROR ||
00979        y_red   == PNG_FIXED_ERROR ||
00980        x_green == PNG_FIXED_ERROR ||
00981        y_green == PNG_FIXED_ERROR ||
00982        x_blue  == PNG_FIXED_ERROR ||
00983        y_blue  == PNG_FIXED_ERROR)
00984    {
00985       png_warning(png_ptr, "Ignoring cHRM chunk with negative chromaticities");
00986       return;
00987    }
00988 
00989 #ifdef PNG_READ_sRGB_SUPPORTED
00990    if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB))
00991    {
00992       if (PNG_OUT_OF_RANGE(x_white, 31270,  1000) ||
00993           PNG_OUT_OF_RANGE(y_white, 32900,  1000) ||
00994           PNG_OUT_OF_RANGE(x_red,   64000,  1000) ||
00995           PNG_OUT_OF_RANGE(y_red,   33000,  1000) ||
00996           PNG_OUT_OF_RANGE(x_green, 30000,  1000) ||
00997           PNG_OUT_OF_RANGE(y_green, 60000,  1000) ||
00998           PNG_OUT_OF_RANGE(x_blue,  15000,  1000) ||
00999           PNG_OUT_OF_RANGE(y_blue,   6000,  1000))
01000       {
01001          PNG_WARNING_PARAMETERS(p)
01002 
01003          png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_fixed, x_white);
01004          png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_fixed, y_white);
01005          png_warning_parameter_signed(p, 3, PNG_NUMBER_FORMAT_fixed, x_red);
01006          png_warning_parameter_signed(p, 4, PNG_NUMBER_FORMAT_fixed, y_red);
01007          png_warning_parameter_signed(p, 5, PNG_NUMBER_FORMAT_fixed, x_green);
01008          png_warning_parameter_signed(p, 6, PNG_NUMBER_FORMAT_fixed, y_green);
01009          png_warning_parameter_signed(p, 7, PNG_NUMBER_FORMAT_fixed, x_blue);
01010          png_warning_parameter_signed(p, 8, PNG_NUMBER_FORMAT_fixed, y_blue);
01011 
01012          png_formatted_warning(png_ptr, p,
01013              "Ignoring incorrect cHRM white(@1,@2) r(@3,@4)g(@5,@6)b(@7,@8) "
01014              "when sRGB is also present");
01015       }
01016       return;
01017    }
01018 #endif /* PNG_READ_sRGB_SUPPORTED */
01019 
01020 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
01021    /* Store the _white values as default coefficients for the rgb to gray
01022     * operation if it is supported.  Check if the transform is already set to
01023     * avoid destroying the transform values.
01024     */
01025    if (!png_ptr->rgb_to_gray_coefficients_set)
01026    {
01027       /* png_set_background has not been called and we haven't seen an sRGB
01028        * chunk yet.  Find the XYZ of the three end points.
01029        */
01030       png_XYZ XYZ;
01031       png_xy xy;
01032 
01033       xy.redx = x_red;
01034       xy.redy = y_red;
01035       xy.greenx = x_green;
01036       xy.greeny = y_green;
01037       xy.bluex = x_blue;
01038       xy.bluey = y_blue;
01039       xy.whitex = x_white;
01040       xy.whitey = y_white;
01041 
01042       if (png_XYZ_from_xy_checked(png_ptr, &XYZ, xy))
01043       {
01044          /* The success case, because XYZ_from_xy normalises to a reference
01045           * white Y of 1.0 we just need to scale the numbers.  This should
01046           * always work just fine. It is an internal error if this overflows.
01047           */
01048          {
01049             png_fixed_point r, g, b;
01050             if (png_muldiv(&r, XYZ.redY, 32768, PNG_FP_1) &&
01051                r >= 0 && r <= 32768 &&
01052                png_muldiv(&g, XYZ.greenY, 32768, PNG_FP_1) &&
01053                g >= 0 && g <= 32768 &&
01054                png_muldiv(&b, XYZ.blueY, 32768, PNG_FP_1) &&
01055                b >= 0 && b <= 32768 &&
01056                r+g+b <= 32769)
01057             {
01058                /* We allow 0 coefficients here.  r+g+b may be 32769 if two or
01059                 * all of the coefficients were rounded up.  Handle this by
01060                 * reducing the *largest* coefficient by 1; this matches the
01061                 * approach used for the default coefficients in pngrtran.c
01062                 */
01063                int add = 0;
01064 
01065                if (r+g+b > 32768)
01066                   add = -1;
01067                else if (r+g+b < 32768)
01068                   add = 1;
01069 
01070                if (add != 0)
01071                {
01072                   if (g >= r && g >= b)
01073                      g += add;
01074                   else if (r >= g && r >= b)
01075                      r += add;
01076                   else
01077                      b += add;
01078                }
01079 
01080                /* Check for an internal error. */
01081                if (r+g+b != 32768)
01082                   png_error(png_ptr,
01083                      "internal error handling cHRM coefficients");
01084 
01085                png_ptr->rgb_to_gray_red_coeff   = (png_uint_16)r;
01086                png_ptr->rgb_to_gray_green_coeff = (png_uint_16)g;
01087             }
01088 
01089             /* This is a png_error at present even though it could be ignored -
01090              * it should never happen, but it is important that if it does, the
01091              * bug is fixed.
01092              */
01093             else
01094                png_error(png_ptr, "internal error handling cHRM->XYZ");
01095          }
01096       }
01097    }
01098 #endif
01099 
01100    png_set_cHRM_fixed(png_ptr, info_ptr, x_white, y_white, x_red, y_red,
01101       x_green, y_green, x_blue, y_blue);
01102 }
01103 #endif
01104 
01105 #ifdef PNG_READ_sRGB_SUPPORTED
01106 void /* PRIVATE */
01107 png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
01108 {
01109    int intent;
01110    png_byte buf[1];
01111 
01112    png_debug(1, "in png_handle_sRGB");
01113 
01114    if (!(png_ptr->mode & PNG_HAVE_IHDR))
01115       png_error(png_ptr, "Missing IHDR before sRGB");
01116 
01117    else if (png_ptr->mode & PNG_HAVE_IDAT)
01118    {
01119       png_warning(png_ptr, "Invalid sRGB after IDAT");
01120       png_crc_finish(png_ptr, length);
01121       return;
01122    }
01123 
01124    else if (png_ptr->mode & PNG_HAVE_PLTE)
01125       /* Should be an error, but we can cope with it */
01126       png_warning(png_ptr, "Out of place sRGB chunk");
01127 
01128    if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
01129    {
01130       png_warning(png_ptr, "Duplicate sRGB chunk");
01131       png_crc_finish(png_ptr, length);
01132       return;
01133    }
01134 
01135    if (length != 1)
01136    {
01137       png_warning(png_ptr, "Incorrect sRGB chunk length");
01138       png_crc_finish(png_ptr, length);
01139       return;
01140    }
01141 
01142    png_crc_read(png_ptr, buf, 1);
01143 
01144    if (png_crc_finish(png_ptr, 0))
01145       return;
01146 
01147    intent = buf[0];
01148 
01149    /* Check for bad intent */
01150    if (intent >= PNG_sRGB_INTENT_LAST)
01151    {
01152       png_warning(png_ptr, "Unknown sRGB intent");
01153       return;
01154    }
01155 
01156 #if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
01157    if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA))
01158    {
01159       if (PNG_OUT_OF_RANGE(info_ptr->gamma, 45500, 500))
01160       {
01161          PNG_WARNING_PARAMETERS(p)
01162 
01163          png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_fixed,
01164             info_ptr->gamma);
01165 
01166          png_formatted_warning(png_ptr, p,
01167              "Ignoring incorrect gAMA value @1 when sRGB is also present");
01168       }
01169    }
01170 #endif /* PNG_READ_gAMA_SUPPORTED */
01171 
01172 #ifdef PNG_READ_cHRM_SUPPORTED
01173    if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
01174       if (PNG_OUT_OF_RANGE(info_ptr->x_white, 31270,  1000) ||
01175           PNG_OUT_OF_RANGE(info_ptr->y_white, 32900,  1000) ||
01176           PNG_OUT_OF_RANGE(info_ptr->x_red,   64000,  1000) ||
01177           PNG_OUT_OF_RANGE(info_ptr->y_red,   33000,  1000) ||
01178           PNG_OUT_OF_RANGE(info_ptr->x_green, 30000,  1000) ||
01179           PNG_OUT_OF_RANGE(info_ptr->y_green, 60000,  1000) ||
01180           PNG_OUT_OF_RANGE(info_ptr->x_blue,  15000,  1000) ||
01181           PNG_OUT_OF_RANGE(info_ptr->y_blue,   6000,  1000))
01182       {
01183          png_warning(png_ptr,
01184              "Ignoring incorrect cHRM value when sRGB is also present");
01185       }
01186 #endif /* PNG_READ_cHRM_SUPPORTED */
01187 
01188    /* This is recorded for use when handling the cHRM chunk above.  An sRGB
01189     * chunk unconditionally overwrites the coefficients for grayscale conversion
01190     * too.
01191     */
01192    png_ptr->is_sRGB = 1;
01193 
01194 #  ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
01195       /* Don't overwrite user supplied values: */
01196       if (!png_ptr->rgb_to_gray_coefficients_set)
01197       {
01198          /* These numbers come from the sRGB specification (or, since one has to
01199           * pay much money to get a copy, the wikipedia sRGB page) the
01200           * chromaticity values quoted have been inverted to get the reverse
01201           * transformation from RGB to XYZ and the 'Y' coefficients scaled by
01202           * 32768 (then rounded).
01203           *
01204           * sRGB and ITU Rec-709 both truncate the values for the D65 white
01205           * point to four digits and, even though it actually stores five
01206           * digits, the PNG spec gives the truncated value.
01207           *
01208           * This means that when the chromaticities are converted back to XYZ
01209           * end points we end up with (6968,23435,2366), which, as described in
01210           * pngrtran.c, would overflow.  If the five digit precision and up is
01211           * used we get, instead:
01212           *
01213           *    6968*R + 23435*G + 2365*B
01214           *
01215           * (Notice that this rounds the blue coefficient down, rather than the
01216           * choice used in pngrtran.c which is to round the green one down.)
01217           */
01218          png_ptr->rgb_to_gray_red_coeff   =  6968; /* 0.212639005871510 */
01219          png_ptr->rgb_to_gray_green_coeff = 23434; /* 0.715168678767756 */
01220          /* png_ptr->rgb_to_gray_blue_coeff  =  2366; 0.072192315360734 */
01221 
01222          /* The following keeps the cHRM chunk from destroying the
01223           * coefficients again in the event that it follows the sRGB chunk.
01224           */
01225          png_ptr->rgb_to_gray_coefficients_set = 1;
01226       }
01227 #  endif
01228 
01229    png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
01230 }
01231 #endif /* PNG_READ_sRGB_SUPPORTED */
01232 
01233 #ifdef PNG_READ_iCCP_SUPPORTED
01234 void /* PRIVATE */
01235 png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
01236 /* Note: this does not properly handle chunks that are > 64K under DOS */
01237 {
01238    png_byte compression_type;
01239    png_bytep pC;
01240    png_charp profile;
01241    png_uint_32 skip = 0;
01242    png_uint_32 profile_size;
01243    png_alloc_size_t profile_length;
01244    png_size_t slength, prefix_length, data_length;
01245 
01246    png_debug(1, "in png_handle_iCCP");
01247 
01248    if (!(png_ptr->mode & PNG_HAVE_IHDR))
01249       png_error(png_ptr, "Missing IHDR before iCCP");
01250 
01251    else if (png_ptr->mode & PNG_HAVE_IDAT)
01252    {
01253       png_warning(png_ptr, "Invalid iCCP after IDAT");
01254       png_crc_finish(png_ptr, length);
01255       return;
01256    }
01257 
01258    else if (png_ptr->mode & PNG_HAVE_PLTE)
01259       /* Should be an error, but we can cope with it */
01260       png_warning(png_ptr, "Out of place iCCP chunk");
01261 
01262    if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
01263    {
01264       png_warning(png_ptr, "Duplicate iCCP chunk");
01265       png_crc_finish(png_ptr, length);
01266       return;
01267    }
01268 
01269 #ifdef PNG_MAX_MALLOC_64K
01270    if (length > (png_uint_32)65535L)
01271    {
01272       png_warning(png_ptr, "iCCP chunk too large to fit in memory");
01273       skip = length - (png_uint_32)65535L;
01274       length = (png_uint_32)65535L;
01275    }
01276 #endif
01277 
01278    png_free(png_ptr, png_ptr->chunkdata);
01279    png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
01280    slength = length;
01281    png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
01282 
01283    if (png_crc_finish(png_ptr, skip))
01284    {
01285       png_free(png_ptr, png_ptr->chunkdata);
01286       png_ptr->chunkdata = NULL;
01287       return;
01288    }
01289 
01290    png_ptr->chunkdata[slength] = 0x00;
01291 
01292    for (profile = png_ptr->chunkdata; *profile; profile++)
01293       /* Empty loop to find end of name */ ;
01294 
01295    ++profile;
01296 
01297    /* There should be at least one zero (the compression type byte)
01298     * following the separator, and we should be on it
01299     */
01300    if (profile >= png_ptr->chunkdata + slength - 1)
01301    {
01302       png_free(png_ptr, png_ptr->chunkdata);
01303       png_ptr->chunkdata = NULL;
01304       png_warning(png_ptr, "Malformed iCCP chunk");
01305       return;
01306    }
01307 
01308    /* Compression_type should always be zero */
01309    compression_type = *profile++;
01310 
01311    if (compression_type)
01312    {
01313       png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
01314       compression_type = 0x00;  /* Reset it to zero (libpng-1.0.6 through 1.0.8
01315                                  wrote nonzero) */
01316    }
01317 
01318    prefix_length = profile - png_ptr->chunkdata;
01319    png_decompress_chunk(png_ptr, compression_type,
01320        slength, prefix_length, &data_length);
01321 
01322    profile_length = data_length - prefix_length;
01323 
01324    if (prefix_length > data_length || profile_length < 4)
01325    {
01326       png_free(png_ptr, png_ptr->chunkdata);
01327       png_ptr->chunkdata = NULL;
01328       png_warning(png_ptr, "Profile size field missing from iCCP chunk");
01329       return;
01330    }
01331 
01332    /* Check the profile_size recorded in the first 32 bits of the ICC profile */
01333    pC = (png_bytep)(png_ptr->chunkdata + prefix_length);
01334    profile_size = ((*(pC    )) << 24) |
01335                   ((*(pC + 1)) << 16) |
01336                   ((*(pC + 2)) <<  8) |
01337                   ((*(pC + 3))      );
01338 
01339    /* NOTE: the following guarantees that 'profile_length' fits into 32 bits,
01340     * because profile_size is a 32 bit value.
01341     */
01342    if (profile_size < profile_length)
01343       profile_length = profile_size;
01344 
01345    /* And the following guarantees that profile_size == profile_length. */
01346    if (profile_size > profile_length)
01347    {
01348       PNG_WARNING_PARAMETERS(p)
01349 
01350       png_free(png_ptr, png_ptr->chunkdata);
01351       png_ptr->chunkdata = NULL;
01352 
01353       png_warning_parameter_unsigned(p, 1, PNG_NUMBER_FORMAT_u, profile_size);
01354       png_warning_parameter_unsigned(p, 2, PNG_NUMBER_FORMAT_u, profile_length);
01355       png_formatted_warning(png_ptr, p,
01356          "Ignoring iCCP chunk with declared size = @1 and actual length = @2");
01357       return;
01358    }
01359 
01360    png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata,
01361        compression_type, (png_bytep)png_ptr->chunkdata + prefix_length,
01362        profile_size);
01363    png_free(png_ptr, png_ptr->chunkdata);
01364    png_ptr->chunkdata = NULL;
01365 }
01366 #endif /* PNG_READ_iCCP_SUPPORTED */
01367 
01368 #ifdef PNG_READ_sPLT_SUPPORTED
01369 void /* PRIVATE */
01370 png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
01371 /* Note: this does not properly handle chunks that are > 64K under DOS */
01372 {
01373    png_bytep entry_start;
01374    png_sPLT_t new_palette;
01375    png_sPLT_entryp pp;
01376    png_uint_32 data_length;
01377    int entry_size, i;
01378    png_uint_32 skip = 0;
01379    png_size_t slength;
01380    png_uint_32 dl;
01381    png_size_t max_dl;
01382 
01383    png_debug(1, "in png_handle_sPLT");
01384 
01385 #ifdef PNG_USER_LIMITS_SUPPORTED
01386 
01387    if (png_ptr->user_chunk_cache_max != 0)
01388    {
01389       if (png_ptr->user_chunk_cache_max == 1)
01390       {
01391          png_crc_finish(png_ptr, length);
01392          return;
01393       }
01394 
01395       if (--png_ptr->user_chunk_cache_max == 1)
01396       {
01397          png_warning(png_ptr, "No space in chunk cache for sPLT");
01398          png_crc_finish(png_ptr, length);
01399          return;
01400       }
01401    }
01402 #endif
01403 
01404    if (!(png_ptr->mode & PNG_HAVE_IHDR))
01405       png_error(png_ptr, "Missing IHDR before sPLT");
01406 
01407    else if (png_ptr->mode & PNG_HAVE_IDAT)
01408    {
01409       png_warning(png_ptr, "Invalid sPLT after IDAT");
01410       png_crc_finish(png_ptr, length);
01411       return;
01412    }
01413 
01414 #ifdef PNG_MAX_MALLOC_64K
01415    if (length > (png_uint_32)65535L)
01416    {
01417       png_warning(png_ptr, "sPLT chunk too large to fit in memory");
01418       skip = length - (png_uint_32)65535L;
01419       length = (png_uint_32)65535L;
01420    }
01421 #endif
01422 
01423    png_free(png_ptr, png_ptr->chunkdata);
01424    png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
01425 
01426    /* WARNING: this may break if size_t is less than 32 bits; it is assumed
01427     * that the PNG_MAX_MALLOC_64K test is enabled in this case, but this is a
01428     * potential breakage point if the types in pngconf.h aren't exactly right.
01429     */
01430    slength = length;
01431    png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
01432 
01433    if (png_crc_finish(png_ptr, skip))
01434    {
01435       png_free(png_ptr, png_ptr->chunkdata);
01436       png_ptr->chunkdata = NULL;
01437       return;
01438    }
01439 
01440    png_ptr->chunkdata[slength] = 0x00;
01441 
01442    for (entry_start = (png_bytep)png_ptr->chunkdata; *entry_start;
01443        entry_start++)
01444       /* Empty loop to find end of name */ ;
01445 
01446    ++entry_start;
01447 
01448    /* A sample depth should follow the separator, and we should be on it  */
01449    if (entry_start > (png_bytep)png_ptr->chunkdata + slength - 2)
01450    {
01451       png_free(png_ptr, png_ptr->chunkdata);
01452       png_ptr->chunkdata = NULL;
01453       png_warning(png_ptr, "malformed sPLT chunk");
01454       return;
01455    }
01456 
01457    new_palette.depth = *entry_start++;
01458    entry_size = (new_palette.depth == 8 ? 6 : 10);
01459    /* This must fit in a png_uint_32 because it is derived from the original
01460     * chunk data length (and use 'length', not 'slength' here for clarity -
01461     * they are guaranteed to be the same, see the tests above.)
01462     */
01463    data_length = length - (png_uint_32)(entry_start -
01464       (png_bytep)png_ptr->chunkdata);
01465 
01466    /* Integrity-check the data length */
01467    if (data_length % entry_size)
01468    {
01469       png_free(png_ptr, png_ptr->chunkdata);
01470       png_ptr->chunkdata = NULL;
01471       png_warning(png_ptr, "sPLT chunk has bad length");
01472       return;
01473    }
01474 
01475    dl = (png_int_32)(data_length / entry_size);
01476    max_dl = PNG_SIZE_MAX / png_sizeof(png_sPLT_entry);
01477 
01478    if (dl > max_dl)
01479    {
01480        png_warning(png_ptr, "sPLT chunk too long");
01481        return;
01482    }
01483 
01484    new_palette.nentries = (png_int_32)(data_length / entry_size);
01485 
01486    new_palette.entries = (png_sPLT_entryp)png_malloc_warn(
01487        png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry));
01488 
01489    if (new_palette.entries == NULL)
01490    {
01491        png_warning(png_ptr, "sPLT chunk requires too much memory");
01492        return;
01493    }
01494 
01495 #ifdef PNG_POINTER_INDEXING_SUPPORTED
01496    for (i = 0; i < new_palette.nentries; i++)
01497    {
01498       pp = new_palette.entries + i;
01499 
01500       if (new_palette.depth == 8)
01501       {
01502          pp->red = *entry_start++;
01503          pp->green = *entry_start++;
01504          pp->blue = *entry_start++;
01505          pp->alpha = *entry_start++;
01506       }
01507 
01508       else
01509       {
01510          pp->red   = png_get_uint_16(entry_start); entry_start += 2;
01511          pp->green = png_get_uint_16(entry_start); entry_start += 2;
01512          pp->blue  = png_get_uint_16(entry_start); entry_start += 2;
01513          pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
01514       }
01515 
01516       pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
01517    }
01518 #else
01519    pp = new_palette.entries;
01520 
01521    for (i = 0; i < new_palette.nentries; i++)
01522    {
01523 
01524       if (new_palette.depth == 8)
01525       {
01526          pp[i].red   = *entry_start++;
01527          pp[i].green = *entry_start++;
01528          pp[i].blue  = *entry_start++;
01529          pp[i].alpha = *entry_start++;
01530       }
01531 
01532       else
01533       {
01534          pp[i].red   = png_get_uint_16(entry_start); entry_start += 2;
01535          pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
01536          pp[i].blue  = png_get_uint_16(entry_start); entry_start += 2;
01537          pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
01538       }
01539 
01540       pp[i].frequency = png_get_uint_16(entry_start); entry_start += 2;
01541    }
01542 #endif
01543 
01544    /* Discard all chunk data except the name and stash that */
01545    new_palette.name = png_ptr->chunkdata;
01546 
01547    png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
01548 
01549    png_free(png_ptr, png_ptr->chunkdata);
01550    png_ptr->chunkdata = NULL;
01551    png_free(png_ptr, new_palette.entries);
01552 }
01553 #endif /* PNG_READ_sPLT_SUPPORTED */
01554 
01555 #ifdef PNG_READ_tRNS_SUPPORTED
01556 void /* PRIVATE */
01557 png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
01558 {
01559    png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
01560 
01561    png_debug(1, "in png_handle_tRNS");
01562 
01563    if (!(png_ptr->mode & PNG_HAVE_IHDR))
01564       png_error(png_ptr, "Missing IHDR before tRNS");
01565 
01566    else if (png_ptr->mode & PNG_HAVE_IDAT)
01567    {
01568       png_warning(png_ptr, "Invalid tRNS after IDAT");
01569       png_crc_finish(png_ptr, length);
01570       return;
01571    }
01572 
01573    else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
01574    {
01575       png_warning(png_ptr, "Duplicate tRNS chunk");
01576       png_crc_finish(png_ptr, length);
01577       return;
01578    }
01579 
01580    if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
01581    {
01582       png_byte buf[2];
01583 
01584       if (length != 2)
01585       {
01586          png_warning(png_ptr, "Incorrect tRNS chunk length");
01587          png_crc_finish(png_ptr, length);
01588          return;
01589       }
01590 
01591       png_crc_read(png_ptr, buf, 2);
01592       png_ptr->num_trans = 1;
01593       png_ptr->trans_color.gray = png_get_uint_16(buf);
01594    }
01595 
01596    else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
01597    {
01598       png_byte buf[6];
01599 
01600       if (length != 6)
01601       {
01602          png_warning(png_ptr, "Incorrect tRNS chunk length");
01603          png_crc_finish(png_ptr, length);
01604          return;
01605       }
01606 
01607       png_crc_read(png_ptr, buf, (png_size_t)length);
01608       png_ptr->num_trans = 1;
01609       png_ptr->trans_color.red = png_get_uint_16(buf);
01610       png_ptr->trans_color.green = png_get_uint_16(buf + 2);
01611       png_ptr->trans_color.blue = png_get_uint_16(buf + 4);
01612    }
01613 
01614    else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
01615    {
01616       if (!(png_ptr->mode & PNG_HAVE_PLTE))
01617       {
01618          /* Should be an error, but we can cope with it. */
01619          png_warning(png_ptr, "Missing PLTE before tRNS");
01620       }
01621 
01622       if (length > (png_uint_32)png_ptr->num_palette ||
01623           length > PNG_MAX_PALETTE_LENGTH)
01624       {
01625          png_warning(png_ptr, "Incorrect tRNS chunk length");
01626          png_crc_finish(png_ptr, length);
01627          return;
01628       }
01629 
01630       if (length == 0)
01631       {
01632          png_warning(png_ptr, "Zero length tRNS chunk");
01633          png_crc_finish(png_ptr, length);
01634          return;
01635       }
01636 
01637       png_crc_read(png_ptr, readbuf, (png_size_t)length);
01638       png_ptr->num_trans = (png_uint_16)length;
01639    }
01640 
01641    else
01642    {
01643       png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
01644       png_crc_finish(png_ptr, length);
01645       return;
01646    }
01647 
01648    if (png_crc_finish(png_ptr, 0))
01649    {
01650       png_ptr->num_trans = 0;
01651       return;
01652    }
01653 
01654    png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
01655        &(png_ptr->trans_color));
01656 }
01657 #endif
01658 
01659 #ifdef PNG_READ_bKGD_SUPPORTED
01660 void /* PRIVATE */
01661 png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
01662 {
01663    png_size_t truelen;
01664    png_byte buf[6];
01665    png_color_16 background;
01666 
01667    png_debug(1, "in png_handle_bKGD");
01668 
01669    if (!(png_ptr->mode & PNG_HAVE_IHDR))
01670       png_error(png_ptr, "Missing IHDR before bKGD");
01671 
01672    else if (png_ptr->mode & PNG_HAVE_IDAT)
01673    {
01674       png_warning(png_ptr, "Invalid bKGD after IDAT");
01675       png_crc_finish(png_ptr, length);
01676       return;
01677    }
01678 
01679    else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
01680        !(png_ptr->mode & PNG_HAVE_PLTE))
01681    {
01682       png_warning(png_ptr, "Missing PLTE before bKGD");
01683       png_crc_finish(png_ptr, length);
01684       return;
01685    }
01686 
01687    else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
01688    {
01689       png_warning(png_ptr, "Duplicate bKGD chunk");
01690       png_crc_finish(png_ptr, length);
01691       return;
01692    }
01693 
01694    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
01695       truelen = 1;
01696 
01697    else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
01698       truelen = 6;
01699 
01700    else
01701       truelen = 2;
01702 
01703    if (length != truelen)
01704    {
01705       png_warning(png_ptr, "Incorrect bKGD chunk length");
01706       png_crc_finish(png_ptr, length);
01707       return;
01708    }
01709 
01710    png_crc_read(png_ptr, buf, truelen);
01711 
01712    if (png_crc_finish(png_ptr, 0))
01713       return;
01714 
01715    /* We convert the index value into RGB components so that we can allow
01716     * arbitrary RGB values for background when we have transparency, and
01717     * so it is easy to determine the RGB values of the background color
01718     * from the info_ptr struct.
01719     */
01720    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
01721    {
01722       background.index = buf[0];
01723 
01724       if (info_ptr && info_ptr->num_palette)
01725       {
01726          if (buf[0] >= info_ptr->num_palette)
01727          {
01728             png_warning(png_ptr, "Incorrect bKGD chunk index value");
01729             return;
01730          }
01731 
01732          background.red = (png_uint_16)png_ptr->palette[buf[0]].red;
01733          background.green = (png_uint_16)png_ptr->palette[buf[0]].green;
01734          background.blue = (png_uint_16)png_ptr->palette[buf[0]].blue;
01735       }
01736 
01737       else
01738          background.red = background.green = background.blue = 0;
01739 
01740       background.gray = 0;
01741    }
01742 
01743    else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
01744    {
01745       background.index = 0;
01746       background.red =
01747       background.green =
01748       background.blue =
01749       background.gray = png_get_uint_16(buf);
01750    }
01751 
01752    else
01753    {
01754       background.index = 0;
01755       background.red = png_get_uint_16(buf);
01756       background.green = png_get_uint_16(buf + 2);
01757       background.blue = png_get_uint_16(buf + 4);
01758       background.gray = 0;
01759    }
01760 
01761    png_set_bKGD(png_ptr, info_ptr, &background);
01762 }
01763 #endif
01764 
01765 #ifdef PNG_READ_hIST_SUPPORTED
01766 void /* PRIVATE */
01767 png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
01768 {
01769    unsigned int num, i;
01770    png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
01771 
01772    png_debug(1, "in png_handle_hIST");
01773 
01774    if (!(png_ptr->mode & PNG_HAVE_IHDR))
01775       png_error(png_ptr, "Missing IHDR before hIST");
01776 
01777    else if (png_ptr->mode & PNG_HAVE_IDAT)
01778    {
01779       png_warning(png_ptr, "Invalid hIST after IDAT");
01780       png_crc_finish(png_ptr, length);
01781       return;
01782    }
01783 
01784    else if (!(png_ptr->mode & PNG_HAVE_PLTE))
01785    {
01786       png_warning(png_ptr, "Missing PLTE before hIST");
01787       png_crc_finish(png_ptr, length);
01788       return;
01789    }
01790 
01791    else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
01792    {
01793       png_warning(png_ptr, "Duplicate hIST chunk");
01794       png_crc_finish(png_ptr, length);
01795       return;
01796    }
01797 
01798    num = length / 2 ;
01799 
01800    if (num != (unsigned int)png_ptr->num_palette || num >
01801        (unsigned int)PNG_MAX_PALETTE_LENGTH)
01802    {
01803       png_warning(png_ptr, "Incorrect hIST chunk length");
01804       png_crc_finish(png_ptr, length);
01805       return;
01806    }
01807 
01808    for (i = 0; i < num; i++)
01809    {
01810       png_byte buf[2];
01811 
01812       png_crc_read(png_ptr, buf, 2);
01813       readbuf[i] = png_get_uint_16(buf);
01814    }
01815 
01816    if (png_crc_finish(png_ptr, 0))
01817       return;
01818 
01819    png_set_hIST(png_ptr, info_ptr, readbuf);
01820 }
01821 #endif
01822 
01823 #ifdef PNG_READ_pHYs_SUPPORTED
01824 void /* PRIVATE */
01825 png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
01826 {
01827    png_byte buf[9];
01828    png_uint_32 res_x, res_y;
01829    int unit_type;
01830 
01831    png_debug(1, "in png_handle_pHYs");
01832 
01833    if (!(png_ptr->mode & PNG_HAVE_IHDR))
01834       png_error(png_ptr, "Missing IHDR before pHYs");
01835 
01836    else if (png_ptr->mode & PNG_HAVE_IDAT)
01837    {
01838       png_warning(png_ptr, "Invalid pHYs after IDAT");
01839       png_crc_finish(png_ptr, length);
01840       return;
01841    }
01842 
01843    else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
01844    {
01845       png_warning(png_ptr, "Duplicate pHYs chunk");
01846       png_crc_finish(png_ptr, length);
01847       return;
01848    }
01849 
01850    if (length != 9)
01851    {
01852       png_warning(png_ptr, "Incorrect pHYs chunk length");
01853       png_crc_finish(png_ptr, length);
01854       return;
01855    }
01856 
01857    png_crc_read(png_ptr, buf, 9);
01858 
01859    if (png_crc_finish(png_ptr, 0))
01860       return;
01861 
01862    res_x = png_get_uint_32(buf);
01863    res_y = png_get_uint_32(buf + 4);
01864    unit_type = buf[8];
01865    png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
01866 }
01867 #endif
01868 
01869 #ifdef PNG_READ_oFFs_SUPPORTED
01870 void /* PRIVATE */
01871 png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
01872 {
01873    png_byte buf[9];
01874    png_int_32 offset_x, offset_y;
01875    int unit_type;
01876 
01877    png_debug(1, "in png_handle_oFFs");
01878 
01879    if (!(png_ptr->mode & PNG_HAVE_IHDR))
01880       png_error(png_ptr, "Missing IHDR before oFFs");
01881 
01882    else if (png_ptr->mode & PNG_HAVE_IDAT)
01883    {
01884       png_warning(png_ptr, "Invalid oFFs after IDAT");
01885       png_crc_finish(png_ptr, length);
01886       return;
01887    }
01888 
01889    else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
01890    {
01891       png_warning(png_ptr, "Duplicate oFFs chunk");
01892       png_crc_finish(png_ptr, length);
01893       return;
01894    }
01895 
01896    if (length != 9)
01897    {
01898       png_warning(png_ptr, "Incorrect oFFs chunk length");
01899       png_crc_finish(png_ptr, length);
01900       return;
01901    }
01902 
01903    png_crc_read(png_ptr, buf, 9);
01904 
01905    if (png_crc_finish(png_ptr, 0))
01906       return;
01907 
01908    offset_x = png_get_int_32(buf);
01909    offset_y = png_get_int_32(buf + 4);
01910    unit_type = buf[8];
01911    png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
01912 }
01913 #endif
01914 
01915 #ifdef PNG_READ_pCAL_SUPPORTED
01916 /* Read the pCAL chunk (described in the PNG Extensions document) */
01917 void /* PRIVATE */
01918 png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
01919 {
01920    png_int_32 X0, X1;
01921    png_byte type, nparams;
01922    png_charp buf, units, endptr;
01923    png_charpp params;
01924    png_size_t slength;
01925    int i;
01926 
01927    png_debug(1, "in png_handle_pCAL");
01928 
01929    if (!(png_ptr->mode & PNG_HAVE_IHDR))
01930       png_error(png_ptr, "Missing IHDR before pCAL");
01931 
01932    else if (png_ptr->mode & PNG_HAVE_IDAT)
01933    {
01934       png_warning(png_ptr, "Invalid pCAL after IDAT");
01935       png_crc_finish(png_ptr, length);
01936       return;
01937    }
01938 
01939    else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
01940    {
01941       png_warning(png_ptr, "Duplicate pCAL chunk");
01942       png_crc_finish(png_ptr, length);
01943       return;
01944    }
01945 
01946    png_debug1(2, "Allocating and reading pCAL chunk data (%u bytes)",
01947        length + 1);
01948    png_free(png_ptr, png_ptr->chunkdata);
01949    png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
01950 
01951    if (png_ptr->chunkdata == NULL)
01952    {
01953       png_warning(png_ptr, "No memory for pCAL purpose");
01954       return;
01955    }
01956 
01957    slength = length;
01958    png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
01959 
01960    if (png_crc_finish(png_ptr, 0))
01961    {
01962       png_free(png_ptr, png_ptr->chunkdata);
01963       png_ptr->chunkdata = NULL;
01964       return;
01965    }
01966 
01967    png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
01968 
01969    png_debug(3, "Finding end of pCAL purpose string");
01970    for (buf = png_ptr->chunkdata; *buf; buf++)
01971       /* Empty loop */ ;
01972 
01973    endptr = png_ptr->chunkdata + slength;
01974 
01975    /* We need to have at least 12 bytes after the purpose string
01976     * in order to get the parameter information.
01977     */
01978    if (endptr <= buf + 12)
01979    {
01980       png_warning(png_ptr, "Invalid pCAL data");
01981       png_free(png_ptr, png_ptr->chunkdata);
01982       png_ptr->chunkdata = NULL;
01983       return;
01984    }
01985 
01986    png_debug(3, "Reading pCAL X0, X1, type, nparams, and units");
01987    X0 = png_get_int_32((png_bytep)buf+1);
01988    X1 = png_get_int_32((png_bytep)buf+5);
01989    type = buf[9];
01990    nparams = buf[10];
01991    units = buf + 11;
01992 
01993    png_debug(3, "Checking pCAL equation type and number of parameters");
01994    /* Check that we have the right number of parameters for known
01995     * equation types.
01996     */
01997    if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
01998        (type == PNG_EQUATION_BASE_E && nparams != 3) ||
01999        (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
02000        (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
02001    {
02002       png_warning(png_ptr, "Invalid pCAL parameters for equation type");
02003       png_free(png_ptr, png_ptr->chunkdata);
02004       png_ptr->chunkdata = NULL;
02005       return;
02006    }
02007 
02008    else if (type >= PNG_EQUATION_LAST)
02009    {
02010       png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
02011    }
02012 
02013    for (buf = units; *buf; buf++)
02014       /* Empty loop to move past the units string. */ ;
02015 
02016    png_debug(3, "Allocating pCAL parameters array");
02017 
02018    params = (png_charpp)png_malloc_warn(png_ptr,
02019        (png_size_t)(nparams * png_sizeof(png_charp)));
02020 
02021    if (params == NULL)
02022    {
02023       png_free(png_ptr, png_ptr->chunkdata);
02024       png_ptr->chunkdata = NULL;
02025       png_warning(png_ptr, "No memory for pCAL params");
02026       return;
02027    }
02028 
02029    /* Get pointers to the start of each parameter string. */
02030    for (i = 0; i < (int)nparams; i++)
02031    {
02032       buf++; /* Skip the null string terminator from previous parameter. */
02033 
02034       png_debug1(3, "Reading pCAL parameter %d", i);
02035 
02036       for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++)
02037          /* Empty loop to move past each parameter string */ ;
02038 
02039       /* Make sure we haven't run out of data yet */
02040       if (buf > endptr)
02041       {
02042          png_warning(png_ptr, "Invalid pCAL data");
02043          png_free(png_ptr, png_ptr->chunkdata);
02044          png_ptr->chunkdata = NULL;
02045          png_free(png_ptr, params);
02046          return;
02047       }
02048    }
02049 
02050    png_set_pCAL(png_ptr, info_ptr, png_ptr->chunkdata, X0, X1, type, nparams,
02051       units, params);
02052 
02053    png_free(png_ptr, png_ptr->chunkdata);
02054    png_ptr->chunkdata = NULL;
02055    png_free(png_ptr, params);
02056 }
02057 #endif
02058 
02059 #ifdef PNG_READ_sCAL_SUPPORTED
02060 /* Read the sCAL chunk */
02061 void /* PRIVATE */
02062 png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
02063 {
02064    png_size_t slength, i;
02065    int state;
02066 
02067    png_debug(1, "in png_handle_sCAL");
02068 
02069    if (!(png_ptr->mode & PNG_HAVE_IHDR))
02070       png_error(png_ptr, "Missing IHDR before sCAL");
02071 
02072    else if (png_ptr->mode & PNG_HAVE_IDAT)
02073    {
02074       png_warning(png_ptr, "Invalid sCAL after IDAT");
02075       png_crc_finish(png_ptr, length);
02076       return;
02077    }
02078 
02079    else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
02080    {
02081       png_warning(png_ptr, "Duplicate sCAL chunk");
02082       png_crc_finish(png_ptr, length);
02083       return;
02084    }
02085 
02086    /* Need unit type, width, \0, height: minimum 4 bytes */
02087    else if (length < 4)
02088    {
02089       png_warning(png_ptr, "sCAL chunk too short");
02090       png_crc_finish(png_ptr, length);
02091       return;
02092    }
02093 
02094    png_debug1(2, "Allocating and reading sCAL chunk data (%u bytes)",
02095       length + 1);
02096 
02097    png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
02098 
02099    if (png_ptr->chunkdata == NULL)
02100    {
02101       png_warning(png_ptr, "Out of memory while processing sCAL chunk");
02102       png_crc_finish(png_ptr, length);
02103       return;
02104    }
02105 
02106    slength = length;
02107    png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
02108    png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
02109 
02110    if (png_crc_finish(png_ptr, 0))
02111    {
02112       png_free(png_ptr, png_ptr->chunkdata);
02113       png_ptr->chunkdata = NULL;
02114       return;
02115    }
02116 
02117    /* Validate the unit. */
02118    if (png_ptr->chunkdata[0] != 1 && png_ptr->chunkdata[0] != 2)
02119    {
02120       png_warning(png_ptr, "Invalid sCAL ignored: invalid unit");
02121       png_free(png_ptr, png_ptr->chunkdata);
02122       png_ptr->chunkdata = NULL;
02123       return;
02124    }
02125 
02126    /* Validate the ASCII numbers, need two ASCII numbers separated by
02127     * a '\0' and they need to fit exactly in the chunk data.
02128     */
02129    i = 1;
02130    state = 0;
02131 
02132    if (!png_check_fp_number(png_ptr->chunkdata, slength, &state, &i) ||
02133        i >= slength || png_ptr->chunkdata[i++] != 0)
02134       png_warning(png_ptr, "Invalid sCAL chunk ignored: bad width format");
02135 
02136    else if (!PNG_FP_IS_POSITIVE(state))
02137       png_warning(png_ptr, "Invalid sCAL chunk ignored: non-positive width");
02138 
02139    else
02140    {
02141       png_size_t heighti = i;
02142 
02143       state = 0;
02144       if (!png_check_fp_number(png_ptr->chunkdata, slength, &state, &i) ||
02145           i != slength)
02146          png_warning(png_ptr, "Invalid sCAL chunk ignored: bad height format");
02147 
02148       else if (!PNG_FP_IS_POSITIVE(state))
02149          png_warning(png_ptr,
02150             "Invalid sCAL chunk ignored: non-positive height");
02151 
02152       else
02153          /* This is the (only) success case. */
02154          png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0],
02155             png_ptr->chunkdata+1, png_ptr->chunkdata+heighti);
02156    }
02157 
02158    /* Clean up - just free the temporarily allocated buffer. */
02159    png_free(png_ptr, png_ptr->chunkdata);
02160    png_ptr->chunkdata = NULL;
02161 }
02162 #endif
02163 
02164 #ifdef PNG_READ_tIME_SUPPORTED
02165 void /* PRIVATE */
02166 png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
02167 {
02168    png_byte buf[7];
02169    png_time mod_time;
02170 
02171    png_debug(1, "in png_handle_tIME");
02172 
02173    if (!(png_ptr->mode & PNG_HAVE_IHDR))
02174       png_error(png_ptr, "Out of place tIME chunk");
02175 
02176    else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
02177    {
02178       png_warning(png_ptr, "Duplicate tIME chunk");
02179       png_crc_finish(png_ptr, length);
02180       return;
02181    }
02182 
02183    if (png_ptr->mode & PNG_HAVE_IDAT)
02184       png_ptr->mode |= PNG_AFTER_IDAT;
02185 
02186    if (length != 7)
02187    {
02188       png_warning(png_ptr, "Incorrect tIME chunk length");
02189       png_crc_finish(png_ptr, length);
02190       return;
02191    }
02192 
02193    png_crc_read(png_ptr, buf, 7);
02194 
02195    if (png_crc_finish(png_ptr, 0))
02196       return;
02197 
02198    mod_time.second = buf[6];
02199    mod_time.minute = buf[5];
02200    mod_time.hour = buf[4];
02201    mod_time.day = buf[3];
02202    mod_time.month = buf[2];
02203    mod_time.year = png_get_uint_16(buf);
02204 
02205    png_set_tIME(png_ptr, info_ptr, &mod_time);
02206 }
02207 #endif
02208 
02209 #ifdef PNG_READ_tEXt_SUPPORTED
02210 /* Note: this does not properly handle chunks that are > 64K under DOS */
02211 void /* PRIVATE */
02212 png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
02213 {
02214    png_textp text_ptr;
02215    png_charp key;
02216    png_charp text;
02217    png_uint_32 skip = 0;
02218    png_size_t slength;
02219    int ret;
02220 
02221    png_debug(1, "in png_handle_tEXt");
02222 
02223 #ifdef PNG_USER_LIMITS_SUPPORTED
02224    if (png_ptr->user_chunk_cache_max != 0)
02225    {
02226       if (png_ptr->user_chunk_cache_max == 1)
02227       {
02228          png_crc_finish(png_ptr, length);
02229          return;
02230       }
02231 
02232       if (--png_ptr->user_chunk_cache_max == 1)
02233       {
02234          png_warning(png_ptr, "No space in chunk cache for tEXt");
02235          png_crc_finish(png_ptr, length);
02236          return;
02237       }
02238    }
02239 #endif
02240 
02241    if (!(png_ptr->mode & PNG_HAVE_IHDR))
02242       png_error(png_ptr, "Missing IHDR before tEXt");
02243 
02244    if (png_ptr->mode & PNG_HAVE_IDAT)
02245       png_ptr->mode |= PNG_AFTER_IDAT;
02246 
02247 #ifdef PNG_MAX_MALLOC_64K
02248    if (length > (png_uint_32)65535L)
02249    {
02250       png_warning(png_ptr, "tEXt chunk too large to fit in memory");
02251       skip = length - (png_uint_32)65535L;
02252       length = (png_uint_32)65535L;
02253    }
02254 #endif
02255 
02256    png_free(png_ptr, png_ptr->chunkdata);
02257 
02258    png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
02259 
02260    if (png_ptr->chunkdata == NULL)
02261    {
02262      png_warning(png_ptr, "No memory to process text chunk");
02263      return;
02264    }
02265 
02266    slength = length;
02267    png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
02268 
02269    if (png_crc_finish(png_ptr, skip))
02270    {
02271       png_free(png_ptr, png_ptr->chunkdata);
02272       png_ptr->chunkdata = NULL;
02273       return;
02274    }
02275 
02276    key = png_ptr->chunkdata;
02277 
02278    key[slength] = 0x00;
02279 
02280    for (text = key; *text; text++)
02281       /* Empty loop to find end of key */ ;
02282 
02283    if (text != key + slength)
02284       text++;
02285 
02286    text_ptr = (png_textp)png_malloc_warn(png_ptr,
02287        png_sizeof(png_text));
02288 
02289    if (text_ptr == NULL)
02290    {
02291       png_warning(png_ptr, "Not enough memory to process text chunk");
02292       png_free(png_ptr, png_ptr->chunkdata);
02293       png_ptr->chunkdata = NULL;
02294       return;
02295    }
02296 
02297    text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
02298    text_ptr->key = key;
02299    text_ptr->lang = NULL;
02300    text_ptr->lang_key = NULL;
02301    text_ptr->itxt_length = 0;
02302    text_ptr->text = text;
02303    text_ptr->text_length = png_strlen(text);
02304 
02305    ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
02306 
02307    png_free(png_ptr, png_ptr->chunkdata);
02308    png_ptr->chunkdata = NULL;
02309    png_free(png_ptr, text_ptr);
02310 
02311    if (ret)
02312       png_warning(png_ptr, "Insufficient memory to process text chunk");
02313 }
02314 #endif
02315 
02316 #ifdef PNG_READ_zTXt_SUPPORTED
02317 /* Note: this does not correctly handle chunks that are > 64K under DOS */
02318 void /* PRIVATE */
02319 png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
02320 {
02321    png_textp text_ptr;
02322    png_charp text;
02323    int comp_type;
02324    int ret;
02325    png_size_t slength, prefix_len, data_len;
02326 
02327    png_debug(1, "in png_handle_zTXt");
02328 
02329 #ifdef PNG_USER_LIMITS_SUPPORTED
02330    if (png_ptr->user_chunk_cache_max != 0)
02331    {
02332       if (png_ptr->user_chunk_cache_max == 1)
02333       {
02334          png_crc_finish(png_ptr, length);
02335          return;
02336       }
02337 
02338       if (--png_ptr->user_chunk_cache_max == 1)
02339       {
02340          png_warning(png_ptr, "No space in chunk cache for zTXt");
02341          png_crc_finish(png_ptr, length);
02342          return;
02343       }
02344    }
02345 #endif
02346 
02347    if (!(png_ptr->mode & PNG_HAVE_IHDR))
02348       png_error(png_ptr, "Missing IHDR before zTXt");
02349 
02350    if (png_ptr->mode & PNG_HAVE_IDAT)
02351       png_ptr->mode |= PNG_AFTER_IDAT;
02352 
02353 #ifdef PNG_MAX_MALLOC_64K
02354    /* We will no doubt have problems with chunks even half this size, but
02355     * there is no hard and fast rule to tell us where to stop.
02356     */
02357    if (length > (png_uint_32)65535L)
02358    {
02359       png_warning(png_ptr, "zTXt chunk too large to fit in memory");
02360       png_crc_finish(png_ptr, length);
02361       return;
02362    }
02363 #endif
02364 
02365    png_free(png_ptr, png_ptr->chunkdata);
02366    png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
02367 
02368    if (png_ptr->chunkdata == NULL)
02369    {
02370       png_warning(png_ptr, "Out of memory processing zTXt chunk");
02371       return;
02372    }
02373 
02374    slength = length;
02375    png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
02376 
02377    if (png_crc_finish(png_ptr, 0))
02378    {
02379       png_free(png_ptr, png_ptr->chunkdata);
02380       png_ptr->chunkdata = NULL;
02381       return;
02382    }
02383 
02384    png_ptr->chunkdata[slength] = 0x00;
02385 
02386    for (text = png_ptr->chunkdata; *text; text++)
02387       /* Empty loop */ ;
02388 
02389    /* zTXt must have some text after the chunkdataword */
02390    if (text >= png_ptr->chunkdata + slength - 2)
02391    {
02392       png_warning(png_ptr, "Truncated zTXt chunk");
02393       png_free(png_ptr, png_ptr->chunkdata);
02394       png_ptr->chunkdata = NULL;
02395       return;
02396    }
02397 
02398    else
02399    {
02400        comp_type = *(++text);
02401 
02402        if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
02403        {
02404           png_warning(png_ptr, "Unknown compression type in zTXt chunk");
02405           comp_type = PNG_TEXT_COMPRESSION_zTXt;
02406        }
02407 
02408        text++;        /* Skip the compression_method byte */
02409    }
02410 
02411    prefix_len = text - png_ptr->chunkdata;
02412 
02413    png_decompress_chunk(png_ptr, comp_type,
02414        (png_size_t)length, prefix_len, &data_len);
02415 
02416    text_ptr = (png_textp)png_malloc_warn(png_ptr,
02417        png_sizeof(png_text));
02418 
02419    if (text_ptr == NULL)
02420    {
02421       png_warning(png_ptr, "Not enough memory to process zTXt chunk");
02422       png_free(png_ptr, png_ptr->chunkdata);
02423       png_ptr->chunkdata = NULL;
02424       return;
02425    }
02426 
02427    text_ptr->compression = comp_type;
02428    text_ptr->key = png_ptr->chunkdata;
02429    text_ptr->lang = NULL;
02430    text_ptr->lang_key = NULL;
02431    text_ptr->itxt_length = 0;
02432    text_ptr->text = png_ptr->chunkdata + prefix_len;
02433    text_ptr->text_length = data_len;
02434 
02435    ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
02436 
02437    png_free(png_ptr, text_ptr);
02438    png_free(png_ptr, png_ptr->chunkdata);
02439    png_ptr->chunkdata = NULL;
02440 
02441    if (ret)
02442       png_error(png_ptr, "Insufficient memory to store zTXt chunk");
02443 }
02444 #endif
02445 
02446 #ifdef PNG_READ_iTXt_SUPPORTED
02447 /* Note: this does not correctly handle chunks that are > 64K under DOS */
02448 void /* PRIVATE */
02449 png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
02450 {
02451    png_textp text_ptr;
02452    png_charp key, lang, text, lang_key;
02453    int comp_flag;
02454    int comp_type = 0;
02455    int ret;
02456    png_size_t slength, prefix_len, data_len;
02457 
02458    png_debug(1, "in png_handle_iTXt");
02459 
02460 #ifdef PNG_USER_LIMITS_SUPPORTED
02461    if (png_ptr->user_chunk_cache_max != 0)
02462    {
02463       if (png_ptr->user_chunk_cache_max == 1)
02464       {
02465          png_crc_finish(png_ptr, length);
02466          return;
02467       }
02468 
02469       if (--png_ptr->user_chunk_cache_max == 1)
02470       {
02471          png_warning(png_ptr, "No space in chunk cache for iTXt");
02472          png_crc_finish(png_ptr, length);
02473          return;
02474       }
02475    }
02476 #endif
02477 
02478    if (!(png_ptr->mode & PNG_HAVE_IHDR))
02479       png_error(png_ptr, "Missing IHDR before iTXt");
02480 
02481    if (png_ptr->mode & PNG_HAVE_IDAT)
02482       png_ptr->mode |= PNG_AFTER_IDAT;
02483 
02484 #ifdef PNG_MAX_MALLOC_64K
02485    /* We will no doubt have problems with chunks even half this size, but
02486     * there is no hard and fast rule to tell us where to stop.
02487     */
02488    if (length > (png_uint_32)65535L)
02489    {
02490       png_warning(png_ptr, "iTXt chunk too large to fit in memory");
02491       png_crc_finish(png_ptr, length);
02492       return;
02493    }
02494 #endif
02495 
02496    png_free(png_ptr, png_ptr->chunkdata);
02497    png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
02498 
02499    if (png_ptr->chunkdata == NULL)
02500    {
02501       png_warning(png_ptr, "No memory to process iTXt chunk");
02502       return;
02503    }
02504 
02505    slength = length;
02506    png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
02507 
02508    if (png_crc_finish(png_ptr, 0))
02509    {
02510       png_free(png_ptr, png_ptr->chunkdata);
02511       png_ptr->chunkdata = NULL;
02512       return;
02513    }
02514 
02515    png_ptr->chunkdata[slength] = 0x00;
02516 
02517    for (lang = png_ptr->chunkdata; *lang; lang++)
02518       /* Empty loop */ ;
02519 
02520    lang++;        /* Skip NUL separator */
02521 
02522    /* iTXt must have a language tag (possibly empty), two compression bytes,
02523     * translated keyword (possibly empty), and possibly some text after the
02524     * keyword
02525     */
02526 
02527    if (lang >= png_ptr->chunkdata + slength - 3)
02528    {
02529       png_warning(png_ptr, "Truncated iTXt chunk");
02530       png_free(png_ptr, png_ptr->chunkdata);
02531       png_ptr->chunkdata = NULL;
02532       return;
02533    }
02534 
02535    else
02536    {
02537       comp_flag = *lang++;
02538       comp_type = *lang++;
02539    }
02540 
02541    if (comp_type || (comp_flag && comp_flag != PNG_TEXT_COMPRESSION_zTXt))
02542    {
02543       png_warning(png_ptr, "Unknown iTXt compression type or method");
02544       png_free(png_ptr, png_ptr->chunkdata);
02545       png_ptr->chunkdata = NULL;
02546       return;
02547    }
02548 
02549    for (lang_key = lang; *lang_key; lang_key++)
02550       /* Empty loop */ ;
02551 
02552    lang_key++;        /* Skip NUL separator */
02553 
02554    if (lang_key >= png_ptr->chunkdata + slength)
02555    {
02556       png_warning(png_ptr, "Truncated iTXt chunk");
02557       png_free(png_ptr, png_ptr->chunkdata);
02558       png_ptr->chunkdata = NULL;
02559       return;
02560    }
02561 
02562    for (text = lang_key; *text; text++)
02563       /* Empty loop */ ;
02564 
02565    text++;        /* Skip NUL separator */
02566 
02567    if (text >= png_ptr->chunkdata + slength)
02568    {
02569       png_warning(png_ptr, "Malformed iTXt chunk");
02570       png_free(png_ptr, png_ptr->chunkdata);
02571       png_ptr->chunkdata = NULL;
02572       return;
02573    }
02574 
02575    prefix_len = text - png_ptr->chunkdata;
02576 
02577    key=png_ptr->chunkdata;
02578 
02579    if (comp_flag)
02580       png_decompress_chunk(png_ptr, comp_type,
02581           (size_t)length, prefix_len, &data_len);
02582 
02583    else
02584       data_len = png_strlen(png_ptr->chunkdata + prefix_len);
02585 
02586    text_ptr = (png_textp)png_malloc_warn(png_ptr,
02587        png_sizeof(png_text));
02588 
02589    if (text_ptr == NULL)
02590    {
02591       png_warning(png_ptr, "Not enough memory to process iTXt chunk");
02592       png_free(png_ptr, png_ptr->chunkdata);
02593       png_ptr->chunkdata = NULL;
02594       return;
02595    }
02596 
02597    text_ptr->compression = (int)comp_flag + 1;
02598    text_ptr->lang_key = png_ptr->chunkdata + (lang_key - key);
02599    text_ptr->lang = png_ptr->chunkdata + (lang - key);
02600    text_ptr->itxt_length = data_len;
02601    text_ptr->text_length = 0;
02602    text_ptr->key = png_ptr->chunkdata;
02603    text_ptr->text = png_ptr->chunkdata + prefix_len;
02604 
02605    ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
02606 
02607    png_free(png_ptr, text_ptr);
02608    png_free(png_ptr, png_ptr->chunkdata);
02609    png_ptr->chunkdata = NULL;
02610 
02611    if (ret)
02612       png_error(png_ptr, "Insufficient memory to store iTXt chunk");
02613 }
02614 #endif
02615 
02616 /* This function is called when we haven't found a handler for a
02617  * chunk.  If there isn't a problem with the chunk itself (ie bad
02618  * chunk name, CRC, or a critical chunk), the chunk is silently ignored
02619  * -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
02620  * case it will be saved away to be written out later.
02621  */
02622 void /* PRIVATE */
02623 png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
02624 {
02625    png_uint_32 skip = 0;
02626 
02627    png_debug(1, "in png_handle_unknown");
02628 
02629 #ifdef PNG_USER_LIMITS_SUPPORTED
02630    if (png_ptr->user_chunk_cache_max != 0)
02631    {
02632       if (png_ptr->user_chunk_cache_max == 1)
02633       {
02634          png_crc_finish(png_ptr, length);
02635          return;
02636       }
02637 
02638       if (--png_ptr->user_chunk_cache_max == 1)
02639       {
02640          png_warning(png_ptr, "No space in chunk cache for unknown chunk");
02641          png_crc_finish(png_ptr, length);
02642          return;
02643       }
02644    }
02645 #endif
02646 
02647    if (png_ptr->mode & PNG_HAVE_IDAT)
02648    {
02649       if (png_ptr->chunk_name != png_IDAT)
02650          png_ptr->mode |= PNG_AFTER_IDAT;
02651    }
02652 
02653    if (PNG_CHUNK_CRITICAL(png_ptr->chunk_name))
02654    {
02655 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
02656       if (png_chunk_unknown_handling(png_ptr, png_ptr->chunk_name) !=
02657           PNG_HANDLE_CHUNK_ALWAYS
02658 #ifdef PNG_READ_USER_CHUNKS_SUPPORTED
02659           && png_ptr->read_user_chunk_fn == NULL
02660 #endif
02661           )
02662 #endif
02663          png_chunk_error(png_ptr, "unknown critical chunk");
02664    }
02665 
02666 #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
02667    if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
02668 #ifdef PNG_READ_USER_CHUNKS_SUPPORTED
02669        || (png_ptr->read_user_chunk_fn != NULL)
02670 #endif
02671        )
02672    {
02673 #ifdef PNG_MAX_MALLOC_64K
02674       if (length > 65535)
02675       {
02676          png_warning(png_ptr, "unknown chunk too large to fit in memory");
02677          skip = length - 65535;
02678          length = 65535;
02679       }
02680 #endif
02681 
02682       /* TODO: this code is very close to the unknown handling in pngpread.c,
02683        * maybe it can be put into a common utility routine?
02684        * png_struct::unknown_chunk is just used as a temporary variable, along
02685        * with the data into which the chunk is read.  These can be eliminated.
02686        */
02687       PNG_CSTRING_FROM_CHUNK(png_ptr->unknown_chunk.name, png_ptr->chunk_name);
02688       png_ptr->unknown_chunk.size = (png_size_t)length;
02689 
02690       if (length == 0)
02691          png_ptr->unknown_chunk.data = NULL;
02692 
02693       else
02694       {
02695          png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length);
02696          png_crc_read(png_ptr, png_ptr->unknown_chunk.data, length);
02697       }
02698 
02699 #ifdef PNG_READ_USER_CHUNKS_SUPPORTED
02700       if (png_ptr->read_user_chunk_fn != NULL)
02701       {
02702          /* Callback to user unknown chunk handler */
02703          int ret;
02704 
02705          ret = (*(png_ptr->read_user_chunk_fn))
02706              (png_ptr, &png_ptr->unknown_chunk);
02707 
02708          if (ret < 0)
02709             png_chunk_error(png_ptr, "error in user chunk");
02710 
02711          if (ret == 0)
02712          {
02713             if (PNG_CHUNK_CRITICAL(png_ptr->chunk_name))
02714             {
02715 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
02716                if (png_chunk_unknown_handling(png_ptr, png_ptr->chunk_name) !=
02717                    PNG_HANDLE_CHUNK_ALWAYS)
02718 #endif
02719                   png_chunk_error(png_ptr, "unknown critical chunk");
02720             }
02721 
02722             png_set_unknown_chunks(png_ptr, info_ptr,
02723                 &png_ptr->unknown_chunk, 1);
02724          }
02725       }
02726 
02727       else
02728 #endif
02729          png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
02730 
02731       png_free(png_ptr, png_ptr->unknown_chunk.data);
02732       png_ptr->unknown_chunk.data = NULL;
02733    }
02734 
02735    else
02736 #endif
02737       skip = length;
02738 
02739    png_crc_finish(png_ptr, skip);
02740 
02741 #ifndef PNG_READ_USER_CHUNKS_SUPPORTED
02742    PNG_UNUSED(info_ptr) /* Quiet compiler warnings about unused info_ptr */
02743 #endif
02744 }
02745 
02746 /* This function is called to verify that a chunk name is valid.
02747  * This function can't have the "critical chunk check" incorporated
02748  * into it, since in the future we will need to be able to call user
02749  * functions to handle unknown critical chunks after we check that
02750  * the chunk name itself is valid.
02751  */
02752 
02753 /* Bit hacking: the test for an invalid byte in the 4 byte chunk name is:
02754  *
02755  * ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
02756  */
02757 
02758 void /* PRIVATE */
02759 png_check_chunk_name(png_structp png_ptr, png_uint_32 chunk_name)
02760 {
02761    int i;
02762 
02763    png_debug(1, "in png_check_chunk_name");
02764 
02765    for (i=1; i<=4; ++i)
02766    {
02767       int c = chunk_name & 0xff;
02768 
02769       if (c < 65 || c > 122 || (c > 90 && c < 97))
02770          png_chunk_error(png_ptr, "invalid chunk type");
02771 
02772       chunk_name >>= 8;
02773    }
02774 }
02775 
02776 /* Combines the row recently read in with the existing pixels in the row.  This
02777  * routine takes care of alpha and transparency if requested.  This routine also
02778  * handles the two methods of progressive display of interlaced images,
02779  * depending on the 'display' value; if 'display' is true then the whole row
02780  * (dp) is filled from the start by replicating the available pixels.  If
02781  * 'display' is false only those pixels present in the pass are filled in.
02782  */
02783 void /* PRIVATE */
02784 png_combine_row(png_structp png_ptr, png_bytep dp, int display)
02785 {
02786    unsigned int pixel_depth = png_ptr->transformed_pixel_depth;
02787    png_const_bytep sp = png_ptr->row_buf + 1;
02788    png_uint_32 row_width = png_ptr->width;
02789    unsigned int pass = png_ptr->pass;
02790    png_bytep end_ptr = 0;
02791    png_byte end_byte = 0;
02792    unsigned int end_mask;
02793 
02794    png_debug(1, "in png_combine_row");
02795 
02796    /* Added in 1.5.6: it should not be possible to enter this routine until at
02797     * least one row has been read from the PNG data and transformed.
02798     */
02799    if (pixel_depth == 0)
02800       png_error(png_ptr, "internal row logic error");
02801 
02802    /* Added in 1.5.4: the pixel depth should match the information returned by
02803     * any call to png_read_update_info at this point.  Do not continue if we got
02804     * this wrong.
02805     */
02806    if (png_ptr->info_rowbytes != 0 && png_ptr->info_rowbytes !=
02807           PNG_ROWBYTES(pixel_depth, row_width))
02808       png_error(png_ptr, "internal row size calculation error");
02809 
02810    /* Don't expect this to ever happen: */
02811    if (row_width == 0)
02812       png_error(png_ptr, "internal row width error");
02813 
02814    /* Preserve the last byte in cases where only part of it will be overwritten,
02815     * the multiply below may overflow, we don't care because ANSI-C guarantees
02816     * we get the low bits.
02817     */
02818    end_mask = (pixel_depth * row_width) & 7;
02819    if (end_mask != 0)
02820    {
02821       /* end_ptr == NULL is a flag to say do nothing */
02822       end_ptr = dp + PNG_ROWBYTES(pixel_depth, row_width) - 1;
02823       end_byte = *end_ptr;
02824 #     ifdef PNG_READ_PACKSWAP_SUPPORTED
02825          if (png_ptr->transformations & PNG_PACKSWAP) /* little-endian byte */
02826             end_mask = 0xff << end_mask;
02827 
02828          else /* big-endian byte */
02829 #     endif
02830          end_mask = 0xff >> end_mask;
02831       /* end_mask is now the bits to *keep* from the destination row */
02832    }
02833 
02834    /* For non-interlaced images this reduces to a png_memcpy(). A png_memcpy()
02835     * will also happen if interlacing isn't supported or if the application
02836     * does not call png_set_interlace_handling().  In the latter cases the
02837     * caller just gets a sequence of the unexpanded rows from each interlace
02838     * pass.
02839     */
02840 #ifdef PNG_READ_INTERLACING_SUPPORTED
02841    if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE) &&
02842       pass < 6 && (display == 0 ||
02843       /* The following copies everything for 'display' on passes 0, 2 and 4. */
02844       (display == 1 && (pass & 1) != 0)))
02845    {
02846       /* Narrow images may have no bits in a pass; the caller should handle
02847        * this, but this test is cheap:
02848        */
02849       if (row_width <= PNG_PASS_START_COL(pass))
02850          return;
02851 
02852       if (pixel_depth < 8)
02853       {
02854          /* For pixel depths up to 4 bpp the 8-pixel mask can be expanded to fit
02855           * into 32 bits, then a single loop over the bytes using the four byte
02856           * values in the 32-bit mask can be used.  For the 'display' option the
02857           * expanded mask may also not require any masking within a byte.  To
02858           * make this work the PACKSWAP option must be taken into account - it
02859           * simply requires the pixels to be reversed in each byte.
02860           *
02861           * The 'regular' case requires a mask for each of the first 6 passes,
02862           * the 'display' case does a copy for the even passes in the range
02863           * 0..6.  This has already been handled in the test above.
02864           *
02865           * The masks are arranged as four bytes with the first byte to use in
02866           * the lowest bits (little-endian) regardless of the order (PACKSWAP or
02867           * not) of the pixels in each byte.
02868           *
02869           * NOTE: the whole of this logic depends on the caller of this function
02870           * only calling it on rows appropriate to the pass.  This function only
02871           * understands the 'x' logic; the 'y' logic is handled by the caller.
02872           *
02873           * The following defines allow generation of compile time constant bit
02874           * masks for each pixel depth and each possibility of swapped or not
02875           * swapped bytes.  Pass 'p' is in the range 0..6; 'x', a pixel index,
02876           * is in the range 0..7; and the result is 1 if the pixel is to be
02877           * copied in the pass, 0 if not.  'S' is for the sparkle method, 'B'
02878           * for the block method.
02879           *
02880           * With some compilers a compile time expression of the general form:
02881           *
02882           *    (shift >= 32) ? (a >> (shift-32)) : (b >> shift)
02883           *
02884           * Produces warnings with values of 'shift' in the range 33 to 63
02885           * because the right hand side of the ?: expression is evaluated by
02886           * the compiler even though it isn't used.  Microsoft Visual C (various
02887           * versions) and the Intel C compiler are known to do this.  To avoid
02888           * this the following macros are used in 1.5.6.  This is a temporary
02889           * solution to avoid destabilizing the code during the release process.
02890           */
02891 #        if PNG_USE_COMPILE_TIME_MASKS
02892 #           define PNG_LSR(x,s) ((x)>>((s) & 0x1f))
02893 #           define PNG_LSL(x,s) ((x)<<((s) & 0x1f))
02894 #        else
02895 #           define PNG_LSR(x,s) ((x)>>(s))
02896 #           define PNG_LSL(x,s) ((x)<<(s))
02897 #        endif
02898 #        define S_COPY(p,x) (((p)<4 ? PNG_LSR(0x80088822,(3-(p))*8+(7-(x))) :\
02899            PNG_LSR(0xaa55ff00,(7-(p))*8+(7-(x)))) & 1)
02900 #        define B_COPY(p,x) (((p)<4 ? PNG_LSR(0xff0fff33,(3-(p))*8+(7-(x))) :\
02901            PNG_LSR(0xff55ff00,(7-(p))*8+(7-(x)))) & 1)
02902 
02903          /* Return a mask for pass 'p' pixel 'x' at depth 'd'.  The mask is
02904           * little endian - the first pixel is at bit 0 - however the extra
02905           * parameter 's' can be set to cause the mask position to be swapped
02906           * within each byte, to match the PNG format.  This is done by XOR of
02907           * the shift with 7, 6 or 4 for bit depths 1, 2 and 4.
02908           */
02909 #        define PIXEL_MASK(p,x,d,s) \
02910             (PNG_LSL(((PNG_LSL(1U,(d)))-1),(((x)*(d))^((s)?8-(d):0))))
02911 
02912          /* Hence generate the appropriate 'block' or 'sparkle' pixel copy mask.
02913           */
02914 #        define S_MASKx(p,x,d,s) (S_COPY(p,x)?PIXEL_MASK(p,x,d,s):0)
02915 #        define B_MASKx(p,x,d,s) (B_COPY(p,x)?PIXEL_MASK(p,x,d,s):0)
02916 
02917          /* Combine 8 of these to get the full mask.  For the 1-bpp and 2-bpp
02918           * cases the result needs replicating, for the 4-bpp case the above
02919           * generates a full 32 bits.
02920           */
02921 #        define MASK_EXPAND(m,d) ((m)*((d)==1?0x01010101:((d)==2?0x00010001:1)))
02922 
02923 #        define S_MASK(p,d,s) MASK_EXPAND(S_MASKx(p,0,d,s) + S_MASKx(p,1,d,s) +\
02924             S_MASKx(p,2,d,s) + S_MASKx(p,3,d,s) + S_MASKx(p,4,d,s) +\
02925             S_MASKx(p,5,d,s) + S_MASKx(p,6,d,s) + S_MASKx(p,7,d,s), d)
02926 
02927 #        define B_MASK(p,d,s) MASK_EXPAND(B_MASKx(p,0,d,s) + B_MASKx(p,1,d,s) +\
02928             B_MASKx(p,2,d,s) + B_MASKx(p,3,d,s) + B_MASKx(p,4,d,s) +\
02929             B_MASKx(p,5,d,s) + B_MASKx(p,6,d,s) + B_MASKx(p,7,d,s), d)
02930 
02931 #if PNG_USE_COMPILE_TIME_MASKS
02932          /* Utility macros to construct all the masks for a depth/swap
02933           * combination.  The 's' parameter says whether the format is PNG
02934           * (big endian bytes) or not.  Only the three odd-numbered passes are
02935           * required for the display/block algorithm.
02936           */
02937 #        define S_MASKS(d,s) { S_MASK(0,d,s), S_MASK(1,d,s), S_MASK(2,d,s),\
02938             S_MASK(3,d,s), S_MASK(4,d,s), S_MASK(5,d,s) }
02939 
02940 #        define B_MASKS(d,s) { B_MASK(1,d,s), S_MASK(3,d,s), S_MASK(5,d,s) }
02941 
02942 #        define DEPTH_INDEX(d) ((d)==1?0:((d)==2?1:2))
02943 
02944          /* Hence the pre-compiled masks indexed by PACKSWAP (or not), depth and
02945           * then pass:
02946           */
02947          static PNG_CONST png_uint_32 row_mask[2/*PACKSWAP*/][3/*depth*/][6] =
02948          {
02949             /* Little-endian byte masks for PACKSWAP */
02950             { S_MASKS(1,0), S_MASKS(2,0), S_MASKS(4,0) },
02951             /* Normal (big-endian byte) masks - PNG format */
02952             { S_MASKS(1,1), S_MASKS(2,1), S_MASKS(4,1) }
02953          };
02954 
02955          /* display_mask has only three entries for the odd passes, so index by
02956           * pass>>1.
02957           */
02958          static PNG_CONST png_uint_32 display_mask[2][3][3] =
02959          {
02960             /* Little-endian byte masks for PACKSWAP */
02961             { B_MASKS(1,0), B_MASKS(2,0), B_MASKS(4,0) },
02962             /* Normal (big-endian byte) masks - PNG format */
02963             { B_MASKS(1,1), B_MASKS(2,1), B_MASKS(4,1) }
02964          };
02965 
02966 #        define MASK(pass,depth,display,png)\
02967             ((display)?display_mask[png][DEPTH_INDEX(depth)][pass>>1]:\
02968                row_mask[png][DEPTH_INDEX(depth)][pass])
02969 
02970 #else /* !PNG_USE_COMPILE_TIME_MASKS */
02971          /* This is the runtime alternative: it seems unlikely that this will
02972           * ever be either smaller or faster than the compile time approach.
02973           */
02974 #        define MASK(pass,depth,display,png)\
02975             ((display)?B_MASK(pass,depth,png):S_MASK(pass,depth,png))
02976 #endif /* !PNG_USE_COMPILE_TIME_MASKS */
02977 
02978          /* Use the appropriate mask to copy the required bits.  In some cases
02979           * the byte mask will be 0 or 0xff, optimize these cases.  row_width is
02980           * the number of pixels, but the code copies bytes, so it is necessary
02981           * to special case the end.
02982           */
02983          png_uint_32 pixels_per_byte = 8 / pixel_depth;
02984          png_uint_32 mask;
02985 
02986 #        ifdef PNG_READ_PACKSWAP_SUPPORTED
02987             if (png_ptr->transformations & PNG_PACKSWAP)
02988                mask = MASK(pass, pixel_depth, display, 0);
02989 
02990             else
02991 #        endif
02992             mask = MASK(pass, pixel_depth, display, 1);
02993 
02994          for (;;)
02995          {
02996             png_uint_32 m;
02997 
02998             /* It doesn't matter in the following if png_uint_32 has more than
02999              * 32 bits because the high bits always match those in m<<24; it is,
03000              * however, essential to use OR here, not +, because of this.
03001              */
03002             m = mask;
03003             mask = (m >> 8) | (m << 24); /* rotate right to good compilers */
03004             m &= 0xff;
03005 
03006             if (m != 0) /* something to copy */
03007             {
03008                if (m != 0xff)
03009                   *dp = (png_byte)((*dp & ~m) | (*sp & m));
03010                else
03011                   *dp = *sp;
03012             }
03013 
03014             /* NOTE: this may overwrite the last byte with garbage if the image
03015              * is not an exact number of bytes wide; libpng has always done
03016              * this.
03017              */
03018             if (row_width <= pixels_per_byte)
03019                break; /* May need to restore part of the last byte */
03020 
03021             row_width -= pixels_per_byte;
03022             ++dp;
03023             ++sp;
03024          }
03025       }
03026 
03027       else /* pixel_depth >= 8 */
03028       {
03029          unsigned int bytes_to_copy, bytes_to_jump;
03030 
03031          /* Validate the depth - it must be a multiple of 8 */
03032          if (pixel_depth & 7)
03033             png_error(png_ptr, "invalid user transform pixel depth");
03034 
03035          pixel_depth >>= 3; /* now in bytes */
03036          row_width *= pixel_depth;
03037 
03038          /* Regardless of pass number the Adam 7 interlace always results in a
03039           * fixed number of pixels to copy then to skip.  There may be a
03040           * different number of pixels to skip at the start though.
03041           */
03042          {
03043             unsigned int offset = PNG_PASS_START_COL(pass) * pixel_depth;
03044 
03045             row_width -= offset;
03046             dp += offset;
03047             sp += offset;
03048          }
03049 
03050          /* Work out the bytes to copy. */
03051          if (display)
03052          {
03053             /* When doing the 'block' algorithm the pixel in the pass gets
03054              * replicated to adjacent pixels.  This is why the even (0,2,4,6)
03055              * passes are skipped above - the entire expanded row is copied.
03056              */
03057             bytes_to_copy = (1<<((6-pass)>>1)) * pixel_depth;
03058 
03059             /* But don't allow this number to exceed the actual row width. */
03060             if (bytes_to_copy > row_width)
03061                bytes_to_copy = row_width;
03062          }
03063 
03064          else /* normal row; Adam7 only ever gives us one pixel to copy. */
03065             bytes_to_copy = pixel_depth;
03066 
03067          /* In Adam7 there is a constant offset between where the pixels go. */
03068          bytes_to_jump = PNG_PASS_COL_OFFSET(pass) * pixel_depth;
03069 
03070          /* And simply copy these bytes.  Some optimization is possible here,
03071           * depending on the value of 'bytes_to_copy'.  Special case the low
03072           * byte counts, which we know to be frequent.
03073           *
03074           * Notice that these cases all 'return' rather than 'break' - this
03075           * avoids an unnecessary test on whether to restore the last byte
03076           * below.
03077           */
03078          switch (bytes_to_copy)
03079          {
03080             case 1:
03081                for (;;)
03082                {
03083                   *dp = *sp;
03084 
03085                   if (row_width <= bytes_to_jump)
03086                      return;
03087 
03088                   dp += bytes_to_jump;
03089                   sp += bytes_to_jump;
03090                   row_width -= bytes_to_jump;
03091                }
03092 
03093             case 2:
03094                /* There is a possibility of a partial copy at the end here; this
03095                 * slows the code down somewhat.
03096                 */
03097                do
03098                {
03099                   dp[0] = sp[0], dp[1] = sp[1];
03100 
03101                   if (row_width <= bytes_to_jump)
03102                      return;
03103 
03104                   sp += bytes_to_jump;
03105                   dp += bytes_to_jump;
03106                   row_width -= bytes_to_jump;
03107                }
03108                while (row_width > 1);
03109 
03110                /* And there can only be one byte left at this point: */
03111                *dp = *sp;
03112                return;
03113 
03114             case 3:
03115                /* This can only be the RGB case, so each copy is exactly one
03116                 * pixel and it is not necessary to check for a partial copy.
03117                 */
03118                for(;;)
03119                {
03120                   dp[0] = sp[0], dp[1] = sp[1], dp[2] = sp[2];
03121 
03122                   if (row_width <= bytes_to_jump)
03123                      return;
03124 
03125                   sp += bytes_to_jump;
03126                   dp += bytes_to_jump;
03127                   row_width -= bytes_to_jump;
03128                }
03129 
03130             default:
03131 #if PNG_ALIGN_TYPE != PNG_ALIGN_NONE
03132                /* Check for double byte alignment and, if possible, use a
03133                 * 16-bit copy.  Don't attempt this for narrow images - ones that
03134                 * are less than an interlace panel wide.  Don't attempt it for
03135                 * wide bytes_to_copy either - use the png_memcpy there.
03136                 */
03137                if (bytes_to_copy < 16 /*else use png_memcpy*/ &&
03138                   png_isaligned(dp, png_uint_16) &&
03139                   png_isaligned(sp, png_uint_16) &&
03140                   bytes_to_copy % sizeof (png_uint_16) == 0 &&
03141                   bytes_to_jump % sizeof (png_uint_16) == 0)
03142                {
03143                   /* Everything is aligned for png_uint_16 copies, but try for
03144                    * png_uint_32 first.
03145                    */
03146                   if (png_isaligned(dp, png_uint_32) &&
03147                      png_isaligned(sp, png_uint_32) &&
03148                      bytes_to_copy % sizeof (png_uint_32) == 0 &&
03149                      bytes_to_jump % sizeof (png_uint_32) == 0)
03150                   {
03151                      png_uint_32p dp32 = (png_uint_32p)dp;
03152                      png_const_uint_32p sp32 = (png_const_uint_32p)sp;
03153                      unsigned int skip = (bytes_to_jump-bytes_to_copy) /
03154                         sizeof (png_uint_32);
03155 
03156                      do
03157                      {
03158                         size_t c = bytes_to_copy;
03159                         do
03160                         {
03161                            *dp32++ = *sp32++;
03162                            c -= sizeof (png_uint_32);
03163                         }
03164                         while (c > 0);
03165 
03166                         if (row_width <= bytes_to_jump)
03167                            return;
03168 
03169                         dp32 += skip;
03170                         sp32 += skip;
03171                         row_width -= bytes_to_jump;
03172                      }
03173                      while (bytes_to_copy <= row_width);
03174 
03175                      /* Get to here when the row_width truncates the final copy.
03176                       * There will be 1-3 bytes left to copy, so don't try the
03177                       * 16-bit loop below.
03178                       */
03179                      dp = (png_bytep)dp32;
03180                      sp = (png_const_bytep)sp32;
03181                      do
03182                         *dp++ = *sp++;
03183                      while (--row_width > 0);
03184                      return;
03185                   }
03186 
03187                   /* Else do it in 16-bit quantities, but only if the size is
03188                    * not too large.
03189                    */
03190                   else
03191                   {
03192                      png_uint_16p dp16 = (png_uint_16p)dp;
03193                      png_const_uint_16p sp16 = (png_const_uint_16p)sp;
03194                      unsigned int skip = (bytes_to_jump-bytes_to_copy) /
03195                         sizeof (png_uint_16);
03196 
03197                      do
03198                      {
03199                         size_t c = bytes_to_copy;
03200                         do
03201                         {
03202                            *dp16++ = *sp16++;
03203                            c -= sizeof (png_uint_16);
03204                         }
03205                         while (c > 0);
03206 
03207                         if (row_width <= bytes_to_jump)
03208                            return;
03209 
03210                         dp16 += skip;
03211                         sp16 += skip;
03212                         row_width -= bytes_to_jump;
03213                      }
03214                      while (bytes_to_copy <= row_width);
03215 
03216                      /* End of row - 1 byte left, bytes_to_copy > row_width: */
03217                      dp = (png_bytep)dp16;
03218                      sp = (png_const_bytep)sp16;
03219                      do
03220                         *dp++ = *sp++;
03221                      while (--row_width > 0);
03222                      return;
03223                   }
03224                }
03225 #endif /* PNG_ALIGN_ code */
03226 
03227                /* The true default - use a png_memcpy: */
03228                for (;;)
03229                {
03230                   png_memcpy(dp, sp, bytes_to_copy);
03231 
03232                   if (row_width <= bytes_to_jump)
03233                      return;
03234 
03235                   sp += bytes_to_jump;
03236                   dp += bytes_to_jump;
03237                   row_width -= bytes_to_jump;
03238                   if (bytes_to_copy > row_width)
03239                      bytes_to_copy = row_width;
03240                }
03241          }
03242 
03243          /* NOT REACHED*/
03244       } /* pixel_depth >= 8 */
03245 
03246       /* Here if pixel_depth < 8 to check 'end_ptr' below. */
03247    }
03248    else
03249 #endif
03250 
03251    /* If here then the switch above wasn't used so just png_memcpy the whole row
03252     * from the temporary row buffer (notice that this overwrites the end of the
03253     * destination row if it is a partial byte.)
03254     */
03255    png_memcpy(dp, sp, PNG_ROWBYTES(pixel_depth, row_width));
03256 
03257    /* Restore the overwritten bits from the last byte if necessary. */
03258    if (end_ptr != NULL)
03259       *end_ptr = (png_byte)((end_byte & end_mask) | (*end_ptr & ~end_mask));
03260 }
03261 
03262 #ifdef PNG_READ_INTERLACING_SUPPORTED
03263 void /* PRIVATE */
03264 png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
03265    png_uint_32 transformations /* Because these may affect the byte layout */)
03266 {
03267    /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
03268    /* Offset to next interlace block */
03269    static PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
03270 
03271    png_debug(1, "in png_do_read_interlace");
03272    if (row != NULL && row_info != NULL)
03273    {
03274       png_uint_32 final_width;
03275 
03276       final_width = row_info->width * png_pass_inc[pass];
03277 
03278       switch (row_info->pixel_depth)
03279       {
03280          case 1:
03281          {
03282             png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
03283             png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
03284             int sshift, dshift;
03285             int s_start, s_end, s_inc;
03286             int jstop = png_pass_inc[pass];
03287             png_byte v;
03288             png_uint_32 i;
03289             int j;
03290 
03291 #ifdef PNG_READ_PACKSWAP_SUPPORTED
03292             if (transformations & PNG_PACKSWAP)
03293             {
03294                 sshift = (int)((row_info->width + 7) & 0x07);
03295                 dshift = (int)((final_width + 7) & 0x07);
03296                 s_start = 7;
03297                 s_end = 0;
03298                 s_inc = -1;
03299             }
03300 
03301             else
03302 #endif
03303             {
03304                 sshift = 7 - (int)((row_info->width + 7) & 0x07);
03305                 dshift = 7 - (int)((final_width + 7) & 0x07);
03306                 s_start = 0;
03307                 s_end = 7;
03308                 s_inc = 1;
03309             }
03310 
03311             for (i = 0; i < row_info->width; i++)
03312             {
03313                v = (png_byte)((*sp >> sshift) & 0x01);
03314                for (j = 0; j < jstop; j++)
03315                {
03316                   *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
03317                   *dp |= (png_byte)(v << dshift);
03318 
03319                   if (dshift == s_end)
03320                   {
03321                      dshift = s_start;
03322                      dp--;
03323                   }
03324 
03325                   else
03326                      dshift += s_inc;
03327                }
03328 
03329                if (sshift == s_end)
03330                {
03331                   sshift = s_start;
03332                   sp--;
03333                }
03334 
03335                else
03336                   sshift += s_inc;
03337             }
03338             break;
03339          }
03340 
03341          case 2:
03342          {
03343             png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
03344             png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
03345             int sshift, dshift;
03346             int s_start, s_end, s_inc;
03347             int jstop = png_pass_inc[pass];
03348             png_uint_32 i;
03349 
03350 #ifdef PNG_READ_PACKSWAP_SUPPORTED
03351             if (transformations & PNG_PACKSWAP)
03352             {
03353                sshift = (int)(((row_info->width + 3) & 0x03) << 1);
03354                dshift = (int)(((final_width + 3) & 0x03) << 1);
03355                s_start = 6;
03356                s_end = 0;
03357                s_inc = -2;
03358             }
03359 
03360             else
03361 #endif
03362             {
03363                sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
03364                dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
03365                s_start = 0;
03366                s_end = 6;
03367                s_inc = 2;
03368             }
03369 
03370             for (i = 0; i < row_info->width; i++)
03371             {
03372                png_byte v;
03373                int j;
03374 
03375                v = (png_byte)((*sp >> sshift) & 0x03);
03376                for (j = 0; j < jstop; j++)
03377                {
03378                   *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
03379                   *dp |= (png_byte)(v << dshift);
03380 
03381                   if (dshift == s_end)
03382                   {
03383                      dshift = s_start;
03384                      dp--;
03385                   }
03386 
03387                   else
03388                      dshift += s_inc;
03389                }
03390 
03391                if (sshift == s_end)
03392                {
03393                   sshift = s_start;
03394                   sp--;
03395                }
03396 
03397                else
03398                   sshift += s_inc;
03399             }
03400             break;
03401          }
03402 
03403          case 4:
03404          {
03405             png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
03406             png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
03407             int sshift, dshift;
03408             int s_start, s_end, s_inc;
03409             png_uint_32 i;
03410             int jstop = png_pass_inc[pass];
03411 
03412 #ifdef PNG_READ_PACKSWAP_SUPPORTED
03413             if (transformations & PNG_PACKSWAP)
03414             {
03415                sshift = (int)(((row_info->width + 1) & 0x01) << 2);
03416                dshift = (int)(((final_width + 1) & 0x01) << 2);
03417                s_start = 4;
03418                s_end = 0;
03419                s_inc = -4;
03420             }
03421 
03422             else
03423 #endif
03424             {
03425                sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
03426                dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
03427                s_start = 0;
03428                s_end = 4;
03429                s_inc = 4;
03430             }
03431 
03432             for (i = 0; i < row_info->width; i++)
03433             {
03434                png_byte v = (png_byte)((*sp >> sshift) & 0x0f);
03435                int j;
03436 
03437                for (j = 0; j < jstop; j++)
03438                {
03439                   *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
03440                   *dp |= (png_byte)(v << dshift);
03441 
03442                   if (dshift == s_end)
03443                   {
03444                      dshift = s_start;
03445                      dp--;
03446                   }
03447 
03448                   else
03449                      dshift += s_inc;
03450                }
03451 
03452                if (sshift == s_end)
03453                {
03454                   sshift = s_start;
03455                   sp--;
03456                }
03457 
03458                else
03459                   sshift += s_inc;
03460             }
03461             break;
03462          }
03463 
03464          default:
03465          {
03466             png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
03467 
03468             png_bytep sp = row + (png_size_t)(row_info->width - 1)
03469                 * pixel_bytes;
03470 
03471             png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
03472 
03473             int jstop = png_pass_inc[pass];
03474             png_uint_32 i;
03475 
03476             for (i = 0; i < row_info->width; i++)
03477             {
03478                png_byte v[8];
03479                int j;
03480 
03481                png_memcpy(v, sp, pixel_bytes);
03482 
03483                for (j = 0; j < jstop; j++)
03484                {
03485                   png_memcpy(dp, v, pixel_bytes);
03486                   dp -= pixel_bytes;
03487                }
03488 
03489                sp -= pixel_bytes;
03490             }
03491             break;
03492          }
03493       }
03494 
03495       row_info->width = final_width;
03496       row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width);
03497    }
03498 #ifndef PNG_READ_PACKSWAP_SUPPORTED
03499    PNG_UNUSED(transformations)  /* Silence compiler warning */
03500 #endif
03501 }
03502 #endif /* PNG_READ_INTERLACING_SUPPORTED */
03503 
03504 static void
03505 png_read_filter_row_sub(png_row_infop row_info, png_bytep row,
03506    png_const_bytep prev_row)
03507 {
03508    png_size_t i;
03509    png_size_t istop = row_info->rowbytes;
03510    unsigned int bpp = (row_info->pixel_depth + 7) >> 3;
03511    png_bytep rp = row + bpp;
03512 
03513    PNG_UNUSED(prev_row)
03514 
03515    for (i = bpp; i < istop; i++)
03516    {
03517       *rp = (png_byte)(((int)(*rp) + (int)(*(rp-bpp))) & 0xff);
03518       rp++;
03519    }
03520 }
03521 
03522 static void
03523 png_read_filter_row_up(png_row_infop row_info, png_bytep row,
03524    png_const_bytep prev_row)
03525 {
03526    png_size_t i;
03527    png_size_t istop = row_info->rowbytes;
03528    png_bytep rp = row;
03529    png_const_bytep pp = prev_row;
03530 
03531    for (i = 0; i < istop; i++)
03532    {
03533       *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
03534       rp++;
03535    }
03536 }
03537 
03538 static void
03539 png_read_filter_row_avg(png_row_infop row_info, png_bytep row,
03540    png_const_bytep prev_row)
03541 {
03542    png_size_t i;
03543    png_bytep rp = row;
03544    png_const_bytep pp = prev_row;
03545    unsigned int bpp = (row_info->pixel_depth + 7) >> 3;
03546    png_size_t istop = row_info->rowbytes - bpp;
03547 
03548    for (i = 0; i < bpp; i++)
03549    {
03550       *rp = (png_byte)(((int)(*rp) +
03551          ((int)(*pp++) / 2 )) & 0xff);
03552 
03553       rp++;
03554    }
03555 
03556    for (i = 0; i < istop; i++)
03557    {
03558       *rp = (png_byte)(((int)(*rp) +
03559          (int)(*pp++ + *(rp-bpp)) / 2 ) & 0xff);
03560 
03561       rp++;
03562    }
03563 }
03564 
03565 static void
03566 png_read_filter_row_paeth_1byte_pixel(png_row_infop row_info, png_bytep row,
03567    png_const_bytep prev_row)
03568 {
03569    png_bytep rp_end = row + row_info->rowbytes;
03570    int a, c;
03571 
03572    /* First pixel/byte */
03573    c = *prev_row++;
03574    a = *row + c;
03575    *row++ = (png_byte)a;
03576 
03577    /* Remainder */
03578    while (row < rp_end)
03579    {
03580       int b, pa, pb, pc, p;
03581 
03582       a &= 0xff; /* From previous iteration or start */
03583       b = *prev_row++;
03584 
03585       p = b - c;
03586       pc = a - c;
03587 
03588 #     ifdef PNG_USE_ABS
03589          pa = abs(p);
03590          pb = abs(pc);
03591          pc = abs(p + pc);
03592 #     else
03593          pa = p < 0 ? -p : p;
03594          pb = pc < 0 ? -pc : pc;
03595          pc = (p + pc) < 0 ? -(p + pc) : p + pc;
03596 #     endif
03597 
03598       /* Find the best predictor, the least of pa, pb, pc favoring the earlier
03599        * ones in the case of a tie.
03600        */
03601       if (pb < pa) pa = pb, a = b;
03602       if (pc < pa) a = c;
03603 
03604       /* Calculate the current pixel in a, and move the previous row pixel to c
03605        * for the next time round the loop
03606        */
03607       c = b;
03608       a += *row;
03609       *row++ = (png_byte)a;
03610    }
03611 }
03612 
03613 static void
03614 png_read_filter_row_paeth_multibyte_pixel(png_row_infop row_info, png_bytep row,
03615    png_const_bytep prev_row)
03616 {
03617    int bpp = (row_info->pixel_depth + 7) >> 3;
03618    png_bytep rp_end = row + bpp;
03619 
03620    /* Process the first pixel in the row completely (this is the same as 'up'
03621     * because there is only one candidate predictor for the first row).
03622     */
03623    while (row < rp_end)
03624    {
03625       int a = *row + *prev_row++;
03626       *row++ = (png_byte)a;
03627    }
03628 
03629    /* Remainder */
03630    rp_end += row_info->rowbytes - bpp;
03631 
03632    while (row < rp_end)
03633    {
03634       int a, b, c, pa, pb, pc, p;
03635 
03636       c = *(prev_row - bpp);
03637       a = *(row - bpp);
03638       b = *prev_row++;
03639 
03640       p = b - c;
03641       pc = a - c;
03642 
03643 #     ifdef PNG_USE_ABS
03644          pa = abs(p);
03645          pb = abs(pc);
03646          pc = abs(p + pc);
03647 #     else
03648          pa = p < 0 ? -p : p;
03649          pb = pc < 0 ? -pc : pc;
03650          pc = (p + pc) < 0 ? -(p + pc) : p + pc;
03651 #     endif
03652 
03653       if (pb < pa) pa = pb, a = b;
03654       if (pc < pa) a = c;
03655 
03656       c = b;
03657       a += *row;
03658       *row++ = (png_byte)a;
03659    }
03660 }
03661 
03662 #ifdef PNG_ARM_NEON
03663 
03664 #ifdef __linux__
03665 #include <stdio.h>
03666 #include <elf.h>
03667 #include <asm/hwcap.h>
03668 
03669 static int png_have_hwcap(unsigned cap)
03670 {
03671    FILE *f = fopen("/proc/self/auxv", "r");
03672    Elf32_auxv_t aux;
03673    int have_cap = 0;
03674 
03675    if (!f)
03676       return 0;
03677 
03678    while (fread(&aux, sizeof(aux), 1, f) > 0)
03679    {
03680       if (aux.a_type == AT_HWCAP &&
03681           aux.a_un.a_val & cap)
03682       {
03683          have_cap = 1;
03684          break;
03685       }
03686    }
03687 
03688    fclose(f);
03689 
03690    return have_cap;
03691 }
03692 #endif /* __linux__ */
03693 
03694 static void
03695 png_init_filter_functions_neon(png_structp pp, unsigned int bpp)
03696 {
03697 #ifdef __linux__
03698    if (!png_have_hwcap(HWCAP_NEON))
03699       return;
03700 #endif
03701 
03702    pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_neon;
03703 
03704    if (bpp == 3)
03705    {
03706       pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_neon;
03707       pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_neon;
03708       pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = 
03709          png_read_filter_row_paeth3_neon;
03710    }
03711 
03712    else if (bpp == 4)
03713    {
03714       pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_neon;
03715       pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_neon;
03716       pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
03717           png_read_filter_row_paeth4_neon;
03718    }
03719 }
03720 #endif /* PNG_ARM_NEON */
03721 
03722 static void
03723 png_init_filter_functions(png_structp pp)
03724 {
03725    unsigned int bpp = (pp->pixel_depth + 7) >> 3;
03726 
03727    pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub;
03728    pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up;
03729    pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg;
03730    if (bpp == 1)
03731       pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
03732          png_read_filter_row_paeth_1byte_pixel;
03733    else
03734       pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
03735          png_read_filter_row_paeth_multibyte_pixel;
03736 
03737 #ifdef PNG_ARM_NEON
03738    png_init_filter_functions_neon(pp, bpp);
03739 #endif
03740 }
03741 
03742 void /* PRIVATE */
03743 png_read_filter_row(png_structp pp, png_row_infop row_info, png_bytep row,
03744    png_const_bytep prev_row, int filter)
03745 {
03746    if (pp->read_filter[0] == NULL)
03747       png_init_filter_functions(pp);
03748    if (filter > PNG_FILTER_VALUE_NONE && filter < PNG_FILTER_VALUE_LAST)
03749       pp->read_filter[filter-1](row_info, row, prev_row);
03750 }
03751 
03752 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED
03753 void /* PRIVATE */
03754 png_read_finish_row(png_structp png_ptr)
03755 {
03756 #ifdef PNG_READ_INTERLACING_SUPPORTED
03757    /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
03758 
03759    /* Start of interlace block */
03760    static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
03761 
03762    /* Offset to next interlace block */
03763    static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
03764 
03765    /* Start of interlace block in the y direction */
03766    static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
03767 
03768    /* Offset to next interlace block in the y direction */
03769    static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
03770 #endif /* PNG_READ_INTERLACING_SUPPORTED */
03771 
03772    png_debug(1, "in png_read_finish_row");
03773    png_ptr->row_number++;
03774    if (png_ptr->row_number < png_ptr->num_rows)
03775       return;
03776 
03777 #ifdef PNG_READ_INTERLACING_SUPPORTED
03778    if (png_ptr->interlaced)
03779    {
03780       png_ptr->row_number = 0;
03781 
03782       /* TO DO: don't do this if prev_row isn't needed (requires
03783        * read-ahead of the next row's filter byte.
03784        */
03785       png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
03786 
03787       do
03788       {
03789          png_ptr->pass++;
03790 
03791          if (png_ptr->pass >= 7)
03792             break;
03793 
03794          png_ptr->iwidth = (png_ptr->width +
03795             png_pass_inc[png_ptr->pass] - 1 -
03796             png_pass_start[png_ptr->pass]) /
03797             png_pass_inc[png_ptr->pass];
03798 
03799          if (!(png_ptr->transformations & PNG_INTERLACE))
03800          {
03801             png_ptr->num_rows = (png_ptr->height +
03802                 png_pass_yinc[png_ptr->pass] - 1 -
03803                 png_pass_ystart[png_ptr->pass]) /
03804                 png_pass_yinc[png_ptr->pass];
03805          }
03806 
03807          else  /* if (png_ptr->transformations & PNG_INTERLACE) */
03808             break; /* libpng deinterlacing sees every row */
03809 
03810       } while (png_ptr->num_rows == 0 || png_ptr->iwidth == 0);
03811 
03812       if (png_ptr->pass < 7)
03813          return;
03814    }
03815 #endif /* PNG_READ_INTERLACING_SUPPORTED */
03816 
03817    if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
03818    {
03819       char extra;
03820       int ret;
03821 
03822       png_ptr->zstream.next_out = (Byte *)&extra;
03823       png_ptr->zstream.avail_out = (uInt)1;
03824 
03825       for (;;)
03826       {
03827          if (!(png_ptr->zstream.avail_in))
03828          {
03829             while (!png_ptr->idat_size)
03830             {
03831                png_crc_finish(png_ptr, 0);
03832                png_ptr->idat_size = png_read_chunk_header(png_ptr);
03833                if (png_ptr->chunk_name != png_IDAT)
03834                   png_error(png_ptr, "Not enough image data");
03835             }
03836 
03837             png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
03838             png_ptr->zstream.next_in = png_ptr->zbuf;
03839 
03840             if (png_ptr->zbuf_size > png_ptr->idat_size)
03841                png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
03842 
03843             png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
03844             png_ptr->idat_size -= png_ptr->zstream.avail_in;
03845          }
03846 
03847          ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
03848 
03849          if (ret == Z_STREAM_END)
03850          {
03851             if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
03852                 png_ptr->idat_size)
03853                png_warning(png_ptr, "Extra compressed data");
03854 
03855             png_ptr->mode |= PNG_AFTER_IDAT;
03856             png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
03857             break;
03858          }
03859 
03860          if (ret != Z_OK)
03861             png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
03862                 "Decompression Error");
03863 
03864          if (!(png_ptr->zstream.avail_out))
03865          {
03866             png_warning(png_ptr, "Extra compressed data");
03867             png_ptr->mode |= PNG_AFTER_IDAT;
03868             png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
03869             break;
03870          }
03871 
03872       }
03873       png_ptr->zstream.avail_out = 0;
03874    }
03875 
03876    if (png_ptr->idat_size || png_ptr->zstream.avail_in)
03877       png_warning(png_ptr, "Extra compression data");
03878 
03879    inflateReset(&png_ptr->zstream);
03880 
03881    png_ptr->mode |= PNG_AFTER_IDAT;
03882 }
03883 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
03884 
03885 void /* PRIVATE */
03886 png_read_start_row(png_structp png_ptr)
03887 {
03888 #ifdef PNG_READ_INTERLACING_SUPPORTED
03889    /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
03890 
03891    /* Start of interlace block */
03892    static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
03893 
03894    /* Offset to next interlace block */
03895    static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
03896 
03897    /* Start of interlace block in the y direction */
03898    static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
03899 
03900    /* Offset to next interlace block in the y direction */
03901    static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
03902 #endif
03903 
03904    int max_pixel_depth;
03905    png_size_t row_bytes;
03906 
03907    png_debug(1, "in png_read_start_row");
03908    png_ptr->zstream.avail_in = 0;
03909 #ifdef PNG_READ_TRANSFORMS_SUPPORTED
03910    png_init_read_transformations(png_ptr);
03911 #endif
03912 #ifdef PNG_READ_INTERLACING_SUPPORTED
03913    if (png_ptr->interlaced)
03914    {
03915       if (!(png_ptr->transformations & PNG_INTERLACE))
03916          png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
03917              png_pass_ystart[0]) / png_pass_yinc[0];
03918 
03919       else
03920          png_ptr->num_rows = png_ptr->height;
03921 
03922       png_ptr->iwidth = (png_ptr->width +
03923           png_pass_inc[png_ptr->pass] - 1 -
03924           png_pass_start[png_ptr->pass]) /
03925           png_pass_inc[png_ptr->pass];
03926    }
03927 
03928    else
03929 #endif /* PNG_READ_INTERLACING_SUPPORTED */
03930    {
03931       png_ptr->num_rows = png_ptr->height;
03932       png_ptr->iwidth = png_ptr->width;
03933    }
03934 
03935    max_pixel_depth = png_ptr->pixel_depth;
03936 
03937    /* WARNING: * png_read_transform_info (pngrtran.c) performs a simpliar set of
03938     * calculations to calculate the final pixel depth, then
03939     * png_do_read_transforms actually does the transforms.  This means that the
03940     * code which effectively calculates this value is actually repeated in three
03941     * separate places.  They must all match.  Innocent changes to the order of
03942     * transformations can and will break libpng in a way that causes memory
03943     * overwrites.
03944     *
03945     * TODO: fix this.
03946     */
03947 #ifdef PNG_READ_PACK_SUPPORTED
03948    if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
03949       max_pixel_depth = 8;
03950 #endif
03951 
03952 #ifdef PNG_READ_EXPAND_SUPPORTED
03953    if (png_ptr->transformations & PNG_EXPAND)
03954    {
03955       if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
03956       {
03957          if (png_ptr->num_trans)
03958             max_pixel_depth = 32;
03959 
03960          else
03961             max_pixel_depth = 24;
03962       }
03963 
03964       else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
03965       {
03966          if (max_pixel_depth < 8)
03967             max_pixel_depth = 8;
03968 
03969          if (png_ptr->num_trans)
03970             max_pixel_depth *= 2;
03971       }
03972 
03973       else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
03974       {
03975          if (png_ptr->num_trans)
03976          {
03977             max_pixel_depth *= 4;
03978             max_pixel_depth /= 3;
03979          }
03980       }
03981    }
03982 #endif
03983 
03984 #ifdef PNG_READ_EXPAND_16_SUPPORTED
03985    if (png_ptr->transformations & PNG_EXPAND_16)
03986    {
03987 #     ifdef PNG_READ_EXPAND_SUPPORTED
03988          /* In fact it is an error if it isn't supported, but checking is
03989           * the safe way.
03990           */
03991          if (png_ptr->transformations & PNG_EXPAND)
03992          {
03993             if (png_ptr->bit_depth < 16)
03994                max_pixel_depth *= 2;
03995          }
03996          else
03997 #     endif
03998          png_ptr->transformations &= ~PNG_EXPAND_16;
03999    }
04000 #endif
04001 
04002 #ifdef PNG_READ_FILLER_SUPPORTED
04003    if (png_ptr->transformations & (PNG_FILLER))
04004    {
04005       if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
04006       {
04007          if (max_pixel_depth <= 8)
04008             max_pixel_depth = 16;
04009 
04010          else
04011             max_pixel_depth = 32;
04012       }
04013 
04014       else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB ||
04015          png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
04016       {
04017          if (max_pixel_depth <= 32)
04018             max_pixel_depth = 32;
04019 
04020          else
04021             max_pixel_depth = 64;
04022       }
04023    }
04024 #endif
04025 
04026 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
04027    if (png_ptr->transformations & PNG_GRAY_TO_RGB)
04028    {
04029       if (
04030 #ifdef PNG_READ_EXPAND_SUPPORTED
04031           (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
04032 #endif
04033 #ifdef PNG_READ_FILLER_SUPPORTED
04034           (png_ptr->transformations & (PNG_FILLER)) ||
04035 #endif
04036           png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
04037       {
04038          if (max_pixel_depth <= 16)
04039             max_pixel_depth = 32;
04040 
04041          else
04042             max_pixel_depth = 64;
04043       }
04044 
04045       else
04046       {
04047          if (max_pixel_depth <= 8)
04048          {
04049             if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
04050                max_pixel_depth = 32;
04051 
04052             else
04053                max_pixel_depth = 24;
04054          }
04055 
04056          else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
04057             max_pixel_depth = 64;
04058 
04059          else
04060             max_pixel_depth = 48;
04061       }
04062    }
04063 #endif
04064 
04065 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
04066 defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
04067    if (png_ptr->transformations & PNG_USER_TRANSFORM)
04068    {
04069       int user_pixel_depth = png_ptr->user_transform_depth *
04070          png_ptr->user_transform_channels;
04071 
04072       if (user_pixel_depth > max_pixel_depth)
04073          max_pixel_depth = user_pixel_depth;
04074    }
04075 #endif
04076 
04077    /* This value is stored in png_struct and double checked in the row read
04078     * code.
04079     */
04080    png_ptr->maximum_pixel_depth = (png_byte)max_pixel_depth;
04081    png_ptr->transformed_pixel_depth = 0; /* calculated on demand */
04082 
04083    /* Align the width on the next larger 8 pixels.  Mainly used
04084     * for interlacing
04085     */
04086    row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
04087    /* Calculate the maximum bytes needed, adding a byte and a pixel
04088     * for safety's sake
04089     */
04090    row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) +
04091        1 + ((max_pixel_depth + 7) >> 3);
04092 
04093 #ifdef PNG_MAX_MALLOC_64K
04094    if (row_bytes > (png_uint_32)65536L)
04095       png_error(png_ptr, "This image requires a row greater than 64KB");
04096 #endif
04097 
04098    if (row_bytes + 48 > png_ptr->old_big_row_buf_size)
04099    {
04100      png_free(png_ptr, png_ptr->big_row_buf);
04101      png_free(png_ptr, png_ptr->big_prev_row);
04102 
04103      if (png_ptr->interlaced)
04104         png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr,
04105             row_bytes + 48);
04106 
04107      else
04108         png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes + 48);
04109 
04110      png_ptr->big_prev_row = (png_bytep)png_malloc(png_ptr, row_bytes + 48);
04111 
04112 #ifdef PNG_ALIGNED_MEMORY_SUPPORTED
04113      /* Use 16-byte aligned memory for row_buf with at least 16 bytes
04114       * of padding before and after row_buf; treat prev_row similarly.
04115       * NOTE: the alignment is to the start of the pixels, one beyond the start
04116       * of the buffer, because of the filter byte.  Prior to libpng 1.5.6 this
04117       * was incorrect; the filter byte was aligned, which had the exact
04118       * opposite effect of that intended.
04119       */
04120      {
04121         png_bytep temp = png_ptr->big_row_buf + 32;
04122         int extra = (int)((temp - (png_bytep)0) & 0x0f);
04123         png_ptr->row_buf = temp - extra - 1/*filter byte*/;
04124 
04125         temp = png_ptr->big_prev_row + 32;
04126         extra = (int)((temp - (png_bytep)0) & 0x0f);
04127         png_ptr->prev_row = temp - extra - 1/*filter byte*/;
04128      }
04129 
04130 #else
04131      /* Use 31 bytes of padding before and 17 bytes after row_buf. */
04132      png_ptr->row_buf = png_ptr->big_row_buf + 31;
04133      png_ptr->prev_row = png_ptr->big_prev_row + 31;
04134 #endif
04135      png_ptr->old_big_row_buf_size = row_bytes + 48;
04136    }
04137 
04138 #ifdef PNG_MAX_MALLOC_64K
04139    if (png_ptr->rowbytes > 65535)
04140       png_error(png_ptr, "This image requires a row greater than 64KB");
04141 
04142 #endif
04143    if (png_ptr->rowbytes > (PNG_SIZE_MAX - 1))
04144       png_error(png_ptr, "Row has too many bytes to allocate in memory");
04145 
04146    png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
04147 
04148    png_debug1(3, "width = %u,", png_ptr->width);
04149    png_debug1(3, "height = %u,", png_ptr->height);
04150    png_debug1(3, "iwidth = %u,", png_ptr->iwidth);
04151    png_debug1(3, "num_rows = %u,", png_ptr->num_rows);
04152    png_debug1(3, "rowbytes = %lu,", (unsigned long)png_ptr->rowbytes);
04153    png_debug1(3, "irowbytes = %lu",
04154        (unsigned long)PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1);
04155 
04156    png_ptr->flags |= PNG_FLAG_ROW_INIT;
04157 }
04158 #endif /* PNG_READ_SUPPORTED */

Generated on Sun May 27 2012 04:19:31 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.