Home | History | Annotate | Download | only in libpng-1.2.19
      1 
      2 /* pngrutil.c - utilities to read a PNG file
      3  *
      4  * Last changed in libpng 1.2.19 August 18, 2007
      5  * For conditions of distribution and use, see copyright notice in png.h
      6  * Copyright (c) 1998-2007 Glenn Randers-Pehrson
      7  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
      8  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
      9  *
     10  * This file contains routines that are only called from within
     11  * libpng itself during the course of reading an image.
     12  */
     13 
     14 #define PNG_INTERNAL
     15 #include "png.h"
     16 
     17 #if defined(PNG_READ_SUPPORTED)
     18 
     19 #if defined(_WIN32_WCE) && (_WIN32_WCE<0x500)
     20 #  define WIN32_WCE_OLD
     21 #endif
     22 
     23 #ifdef PNG_FLOATING_POINT_SUPPORTED
     24 #  if defined(WIN32_WCE_OLD)
     25 /* strtod() function is not supported on WindowsCE */
     26 __inline double png_strtod(png_structp png_ptr, PNG_CONST char *nptr, char **endptr)
     27 {
     28    double result = 0;
     29    int len;
     30    wchar_t *str, *end;
     31 
     32    len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0);
     33    str = (wchar_t *)png_malloc(png_ptr, len * sizeof(wchar_t));
     34    if ( NULL != str )
     35    {
     36       MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len);
     37       result = wcstod(str, &end);
     38       len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL);
     39       *endptr = (char *)nptr + (png_strlen(nptr) - len + 1);
     40       png_free(png_ptr, str);
     41    }
     42    return result;
     43 }
     44 #  else
     45 #    define png_strtod(p,a,b) strtod(a,b)
     46 #  endif
     47 #endif
     48 
     49 png_uint_32 PNGAPI
     50 png_get_uint_31(png_structp png_ptr, png_bytep buf)
     51 {
     52    png_uint_32 i = png_get_uint_32(buf);
     53    if (i > PNG_UINT_31_MAX)
     54      png_error(png_ptr, "PNG unsigned integer out of range.");
     55    return (i);
     56 }
     57 #ifndef PNG_READ_BIG_ENDIAN_SUPPORTED
     58 /* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
     59 png_uint_32 PNGAPI
     60 png_get_uint_32(png_bytep buf)
     61 {
     62    png_uint_32 i = ((png_uint_32)(*buf) << 24) +
     63       ((png_uint_32)(*(buf + 1)) << 16) +
     64       ((png_uint_32)(*(buf + 2)) << 8) +
     65       (png_uint_32)(*(buf + 3));
     66 
     67    return (i);
     68 }
     69 
     70 /* Grab a signed 32-bit integer from a buffer in big-endian format.  The
     71  * data is stored in the PNG file in two's complement format, and it is
     72  * assumed that the machine format for signed integers is the same. */
     73 png_int_32 PNGAPI
     74 png_get_int_32(png_bytep buf)
     75 {
     76    png_int_32 i = ((png_int_32)(*buf) << 24) +
     77       ((png_int_32)(*(buf + 1)) << 16) +
     78       ((png_int_32)(*(buf + 2)) << 8) +
     79       (png_int_32)(*(buf + 3));
     80 
     81    return (i);
     82 }
     83 
     84 /* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
     85 png_uint_16 PNGAPI
     86 png_get_uint_16(png_bytep buf)
     87 {
     88    png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) +
     89       (png_uint_16)(*(buf + 1)));
     90 
     91    return (i);
     92 }
     93 #endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */
     94 
     95 /* Read data, and (optionally) run it through the CRC. */
     96 void /* PRIVATE */
     97 png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
     98 {
     99    if(png_ptr == NULL) return;
    100    png_read_data(png_ptr, buf, length);
    101    png_calculate_crc(png_ptr, buf, length);
    102 }
    103 
    104 /* Optionally skip data and then check the CRC.  Depending on whether we
    105    are reading a ancillary or critical chunk, and how the program has set
    106    things up, we may calculate the CRC on the data and print a message.
    107    Returns '1' if there was a CRC error, '0' otherwise. */
    108 int /* PRIVATE */
    109 png_crc_finish(png_structp png_ptr, png_uint_32 skip)
    110 {
    111    png_size_t i;
    112    png_size_t istop = png_ptr->zbuf_size;
    113 
    114    for (i = (png_size_t)skip; i > istop; i -= istop)
    115    {
    116       png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
    117    }
    118    if (i)
    119    {
    120       png_crc_read(png_ptr, png_ptr->zbuf, i);
    121    }
    122 
    123    if (png_crc_error(png_ptr))
    124    {
    125       if (((png_ptr->chunk_name[0] & 0x20) &&                /* Ancillary */
    126            !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
    127           (!(png_ptr->chunk_name[0] & 0x20) &&             /* Critical  */
    128           (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)))
    129       {
    130          png_chunk_warning(png_ptr, "CRC error");
    131       }
    132       else
    133       {
    134          png_chunk_error(png_ptr, "CRC error");
    135       }
    136       return (1);
    137    }
    138 
    139    return (0);
    140 }
    141 
    142 /* Compare the CRC stored in the PNG file with that calculated by libpng from
    143    the data it has read thus far. */
    144 int /* PRIVATE */
    145 png_crc_error(png_structp png_ptr)
    146 {
    147    png_byte crc_bytes[4];
    148    png_uint_32 crc;
    149    int need_crc = 1;
    150 
    151    if (png_ptr->chunk_name[0] & 0x20)                     /* ancillary */
    152    {
    153       if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
    154           (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
    155          need_crc = 0;
    156    }
    157    else                                                    /* critical */
    158    {
    159       if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
    160          need_crc = 0;
    161    }
    162 
    163    png_read_data(png_ptr, crc_bytes, 4);
    164 
    165    if (need_crc)
    166    {
    167       crc = png_get_uint_32(crc_bytes);
    168       return ((int)(crc != png_ptr->crc));
    169    }
    170    else
    171       return (0);
    172 }
    173 
    174 #if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \
    175     defined(PNG_READ_iCCP_SUPPORTED)
    176 /*
    177  * Decompress trailing data in a chunk.  The assumption is that chunkdata
    178  * points at an allocated area holding the contents of a chunk with a
    179  * trailing compressed part.  What we get back is an allocated area
    180  * holding the original prefix part and an uncompressed version of the
    181  * trailing part (the malloc area passed in is freed).
    182  */
    183 png_charp /* PRIVATE */
    184 png_decompress_chunk(png_structp png_ptr, int comp_type,
    185                               png_charp chunkdata, png_size_t chunklength,
    186                               png_size_t prefix_size, png_size_t *newlength)
    187 {
    188    static PNG_CONST char msg[] = "Error decoding compressed text";
    189    png_charp text;
    190    png_size_t text_size;
    191 
    192    if (comp_type == PNG_COMPRESSION_TYPE_BASE)
    193    {
    194       int ret = Z_OK;
    195       png_ptr->zstream.next_in = (png_bytep)(chunkdata + prefix_size);
    196       png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size);
    197       png_ptr->zstream.next_out = png_ptr->zbuf;
    198       png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
    199 
    200       text_size = 0;
    201       text = NULL;
    202 
    203       while (png_ptr->zstream.avail_in)
    204       {
    205          ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
    206          if (ret != Z_OK && ret != Z_STREAM_END)
    207          {
    208             if (png_ptr->zstream.msg != NULL)
    209                png_warning(png_ptr, png_ptr->zstream.msg);
    210             else
    211                png_warning(png_ptr, msg);
    212             inflateReset(&png_ptr->zstream);
    213             png_ptr->zstream.avail_in = 0;
    214 
    215             if (text ==  NULL)
    216             {
    217                text_size = prefix_size + png_sizeof(msg) + 1;
    218                text = (png_charp)png_malloc_warn(png_ptr, text_size);
    219                if (text ==  NULL)
    220                  {
    221                     png_free(png_ptr,chunkdata);
    222                     png_error(png_ptr,"Not enough memory to decompress chunk");
    223                  }
    224                png_memcpy(text, chunkdata, prefix_size);
    225             }
    226 
    227             text[text_size - 1] = 0x00;
    228 
    229             /* Copy what we can of the error message into the text chunk */
    230             text_size = (png_size_t)(chunklength - (text - chunkdata) - 1);
    231             text_size = png_sizeof(msg) > text_size ? text_size :
    232                png_sizeof(msg);
    233             png_memcpy(text + prefix_size, msg, text_size + 1);
    234             break;
    235          }
    236          if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END)
    237          {
    238             if (text == NULL)
    239             {
    240                text_size = prefix_size +
    241                    png_ptr->zbuf_size - png_ptr->zstream.avail_out;
    242                text = (png_charp)png_malloc_warn(png_ptr, text_size + 1);
    243                if (text ==  NULL)
    244                  {
    245                     png_free(png_ptr,chunkdata);
    246                     png_error(png_ptr,"Not enough memory to decompress chunk.");
    247                  }
    248                png_memcpy(text + prefix_size, png_ptr->zbuf,
    249                     text_size - prefix_size);
    250                png_memcpy(text, chunkdata, prefix_size);
    251                *(text + text_size) = 0x00;
    252             }
    253             else
    254             {
    255                png_charp tmp;
    256 
    257                tmp = text;
    258                text = (png_charp)png_malloc_warn(png_ptr,
    259                   (png_uint_32)(text_size +
    260                   png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1));
    261                if (text == NULL)
    262                {
    263                   png_free(png_ptr, tmp);
    264                   png_free(png_ptr, chunkdata);
    265                   png_error(png_ptr,"Not enough memory to decompress chunk..");
    266                }
    267                png_memcpy(text, tmp, text_size);
    268                png_free(png_ptr, tmp);
    269                png_memcpy(text + text_size, png_ptr->zbuf,
    270                   (png_ptr->zbuf_size - png_ptr->zstream.avail_out));
    271                text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
    272                *(text + text_size) = 0x00;
    273             }
    274             if (ret == Z_STREAM_END)
    275                break;
    276             else
    277             {
    278                png_ptr->zstream.next_out = png_ptr->zbuf;
    279                png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
    280             }
    281          }
    282       }
    283       if (ret != Z_STREAM_END)
    284       {
    285 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
    286          char umsg[52];
    287 
    288          if (ret == Z_BUF_ERROR)
    289             png_snprintf(umsg, 52,
    290                 "Buffer error in compressed datastream in %s chunk",
    291                 png_ptr->chunk_name);
    292          else if (ret == Z_DATA_ERROR)
    293             png_snprintf(umsg, 52,
    294                 "Data error in compressed datastream in %s chunk",
    295                 png_ptr->chunk_name);
    296          else
    297             png_snprintf(umsg, 52,
    298                 "Incomplete compressed datastream in %s chunk",
    299                 png_ptr->chunk_name);
    300          png_warning(png_ptr, umsg);
    301 #else
    302          png_warning(png_ptr,
    303             "Incomplete compressed datastream in chunk other than IDAT");
    304 #endif
    305          text_size=prefix_size;
    306          if (text ==  NULL)
    307          {
    308             text = (png_charp)png_malloc_warn(png_ptr, text_size+1);
    309             if (text == NULL)
    310               {
    311                 png_free(png_ptr, chunkdata);
    312                 png_error(png_ptr,"Not enough memory for text.");
    313               }
    314             png_memcpy(text, chunkdata, prefix_size);
    315          }
    316          *(text + text_size) = 0x00;
    317       }
    318 
    319       inflateReset(&png_ptr->zstream);
    320       png_ptr->zstream.avail_in = 0;
    321 
    322       png_free(png_ptr, chunkdata);
    323       chunkdata = text;
    324       *newlength=text_size;
    325    }
    326    else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
    327    {
    328 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
    329       char umsg[50];
    330 
    331       png_snprintf(umsg, 50,
    332          "Unknown zTXt compression type %d", comp_type);
    333       png_warning(png_ptr, umsg);
    334 #else
    335       png_warning(png_ptr, "Unknown zTXt compression type");
    336 #endif
    337 
    338       *(chunkdata + prefix_size) = 0x00;
    339       *newlength=prefix_size;
    340    }
    341 
    342    return chunkdata;
    343 }
    344 #endif
    345 
    346 /* read and check the IDHR chunk */
    347 void /* PRIVATE */
    348 png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    349 {
    350    png_byte buf[13];
    351    png_uint_32 width, height;
    352    int bit_depth, color_type, compression_type, filter_type;
    353    int interlace_type;
    354 
    355    png_debug(1, "in png_handle_IHDR\n");
    356 
    357    if (png_ptr->mode & PNG_HAVE_IHDR)
    358       png_error(png_ptr, "Out of place IHDR");
    359 
    360    /* check the length */
    361    if (length != 13)
    362       png_error(png_ptr, "Invalid IHDR chunk");
    363 
    364    png_ptr->mode |= PNG_HAVE_IHDR;
    365 
    366    png_crc_read(png_ptr, buf, 13);
    367    png_crc_finish(png_ptr, 0);
    368 
    369    width = png_get_uint_31(png_ptr, buf);
    370    height = png_get_uint_31(png_ptr, buf + 4);
    371    bit_depth = buf[8];
    372    color_type = buf[9];
    373    compression_type = buf[10];
    374    filter_type = buf[11];
    375    interlace_type = buf[12];
    376 
    377    /* set internal variables */
    378    png_ptr->width = width;
    379    png_ptr->height = height;
    380    png_ptr->bit_depth = (png_byte)bit_depth;
    381    png_ptr->interlaced = (png_byte)interlace_type;
    382    png_ptr->color_type = (png_byte)color_type;
    383 #if defined(PNG_MNG_FEATURES_SUPPORTED)
    384    png_ptr->filter_type = (png_byte)filter_type;
    385 #endif
    386    png_ptr->compression_type = (png_byte)compression_type;
    387 
    388    /* find number of channels */
    389    switch (png_ptr->color_type)
    390    {
    391       case PNG_COLOR_TYPE_GRAY:
    392       case PNG_COLOR_TYPE_PALETTE:
    393          png_ptr->channels = 1;
    394          break;
    395       case PNG_COLOR_TYPE_RGB:
    396          png_ptr->channels = 3;
    397          break;
    398       case PNG_COLOR_TYPE_GRAY_ALPHA:
    399          png_ptr->channels = 2;
    400          break;
    401       case PNG_COLOR_TYPE_RGB_ALPHA:
    402          png_ptr->channels = 4;
    403          break;
    404    }
    405 
    406    /* set up other useful info */
    407    png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
    408    png_ptr->channels);
    409    png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->width);
    410    png_debug1(3,"bit_depth = %d\n", png_ptr->bit_depth);
    411    png_debug1(3,"channels = %d\n", png_ptr->channels);
    412    png_debug1(3,"rowbytes = %lu\n", png_ptr->rowbytes);
    413    png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
    414       color_type, interlace_type, compression_type, filter_type);
    415 }
    416 
    417 /* read and check the palette */
    418 void /* PRIVATE */
    419 png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    420 {
    421    png_color palette[PNG_MAX_PALETTE_LENGTH];
    422    int num, i;
    423 #ifndef PNG_NO_POINTER_INDEXING
    424    png_colorp pal_ptr;
    425 #endif
    426 
    427    png_debug(1, "in png_handle_PLTE\n");
    428 
    429    if (!(png_ptr->mode & PNG_HAVE_IHDR))
    430       png_error(png_ptr, "Missing IHDR before PLTE");
    431    else if (png_ptr->mode & PNG_HAVE_IDAT)
    432    {
    433       png_warning(png_ptr, "Invalid PLTE after IDAT");
    434       png_crc_finish(png_ptr, length);
    435       return;
    436    }
    437    else if (png_ptr->mode & PNG_HAVE_PLTE)
    438       png_error(png_ptr, "Duplicate PLTE chunk");
    439 
    440    png_ptr->mode |= PNG_HAVE_PLTE;
    441 
    442    if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
    443    {
    444       png_warning(png_ptr,
    445         "Ignoring PLTE chunk in grayscale PNG");
    446       png_crc_finish(png_ptr, length);
    447       return;
    448    }
    449 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
    450    if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
    451    {
    452       png_crc_finish(png_ptr, length);
    453       return;
    454    }
    455 #endif
    456 
    457    if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
    458    {
    459       if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
    460       {
    461          png_warning(png_ptr, "Invalid palette chunk");
    462          png_crc_finish(png_ptr, length);
    463          return;
    464       }
    465       else
    466       {
    467          png_error(png_ptr, "Invalid palette chunk");
    468       }
    469    }
    470 
    471    num = (int)length / 3;
    472 
    473 #ifndef PNG_NO_POINTER_INDEXING
    474    for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
    475    {
    476       png_byte buf[3];
    477 
    478       png_crc_read(png_ptr, buf, 3);
    479       pal_ptr->red = buf[0];
    480       pal_ptr->green = buf[1];
    481       pal_ptr->blue = buf[2];
    482    }
    483 #else
    484    for (i = 0; i < num; i++)
    485    {
    486       png_byte buf[3];
    487 
    488       png_crc_read(png_ptr, buf, 3);
    489       /* don't depend upon png_color being any order */
    490       palette[i].red = buf[0];
    491       palette[i].green = buf[1];
    492       palette[i].blue = buf[2];
    493    }
    494 #endif
    495 
    496    /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
    497       whatever the normal CRC configuration tells us.  However, if we
    498       have an RGB image, the PLTE can be considered ancillary, so
    499       we will act as though it is. */
    500 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
    501    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
    502 #endif
    503    {
    504       png_crc_finish(png_ptr, 0);
    505    }
    506 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
    507    else if (png_crc_error(png_ptr))  /* Only if we have a CRC error */
    508    {
    509       /* If we don't want to use the data from an ancillary chunk,
    510          we have two options: an error abort, or a warning and we
    511          ignore the data in this chunk (which should be OK, since
    512          it's considered ancillary for a RGB or RGBA image). */
    513       if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
    514       {
    515          if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
    516          {
    517             png_chunk_error(png_ptr, "CRC error");
    518          }
    519          else
    520          {
    521             png_chunk_warning(png_ptr, "CRC error");
    522             return;
    523          }
    524       }
    525       /* Otherwise, we (optionally) emit a warning and use the chunk. */
    526       else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
    527       {
    528          png_chunk_warning(png_ptr, "CRC error");
    529       }
    530    }
    531 #endif
    532 
    533    png_set_PLTE(png_ptr, info_ptr, palette, num);
    534 
    535 #if defined(PNG_READ_tRNS_SUPPORTED)
    536    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
    537    {
    538       if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
    539       {
    540          if (png_ptr->num_trans > (png_uint_16)num)
    541          {
    542             png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
    543             png_ptr->num_trans = (png_uint_16)num;
    544          }
    545          if (info_ptr->num_trans > (png_uint_16)num)
    546          {
    547             png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
    548             info_ptr->num_trans = (png_uint_16)num;
    549          }
    550       }
    551    }
    552 #endif
    553 
    554 }
    555 
    556 void /* PRIVATE */
    557 png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    558 {
    559    png_debug(1, "in png_handle_IEND\n");
    560 
    561    if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
    562    {
    563       png_error(png_ptr, "No image in file");
    564    }
    565 
    566    png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
    567 
    568    if (length != 0)
    569    {
    570       png_warning(png_ptr, "Incorrect IEND chunk length");
    571    }
    572    png_crc_finish(png_ptr, length);
    573 
    574    info_ptr =info_ptr; /* quiet compiler warnings about unused info_ptr */
    575 }
    576 
    577 #if defined(PNG_READ_gAMA_SUPPORTED)
    578 void /* PRIVATE */
    579 png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    580 {
    581    png_fixed_point igamma;
    582 #ifdef PNG_FLOATING_POINT_SUPPORTED
    583    float file_gamma;
    584 #endif
    585    png_byte buf[4];
    586 
    587    png_debug(1, "in png_handle_gAMA\n");
    588 
    589    if (!(png_ptr->mode & PNG_HAVE_IHDR))
    590       png_error(png_ptr, "Missing IHDR before gAMA");
    591    else if (png_ptr->mode & PNG_HAVE_IDAT)
    592    {
    593       png_warning(png_ptr, "Invalid gAMA after IDAT");
    594       png_crc_finish(png_ptr, length);
    595       return;
    596    }
    597    else if (png_ptr->mode & PNG_HAVE_PLTE)
    598       /* Should be an error, but we can cope with it */
    599       png_warning(png_ptr, "Out of place gAMA chunk");
    600 
    601    if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
    602 #if defined(PNG_READ_sRGB_SUPPORTED)
    603       && !(info_ptr->valid & PNG_INFO_sRGB)
    604 #endif
    605       )
    606    {
    607       png_warning(png_ptr, "Duplicate gAMA chunk");
    608       png_crc_finish(png_ptr, length);
    609       return;
    610    }
    611 
    612    if (length != 4)
    613    {
    614       png_warning(png_ptr, "Incorrect gAMA chunk length");
    615       png_crc_finish(png_ptr, length);
    616       return;
    617    }
    618 
    619    png_crc_read(png_ptr, buf, 4);
    620    if (png_crc_finish(png_ptr, 0))
    621       return;
    622 
    623    igamma = (png_fixed_point)png_get_uint_32(buf);
    624    /* check for zero gamma */
    625    if (igamma == 0)
    626       {
    627          png_warning(png_ptr,
    628            "Ignoring gAMA chunk with gamma=0");
    629          return;
    630       }
    631 
    632 #if defined(PNG_READ_sRGB_SUPPORTED)
    633    if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
    634       if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
    635       {
    636          png_warning(png_ptr,
    637            "Ignoring incorrect gAMA value when sRGB is also present");
    638 #ifndef PNG_NO_CONSOLE_IO
    639          fprintf(stderr, "gamma = (%d/100000)\n", (int)igamma);
    640 #endif
    641          return;
    642       }
    643 #endif /* PNG_READ_sRGB_SUPPORTED */
    644 
    645 #ifdef PNG_FLOATING_POINT_SUPPORTED
    646    file_gamma = (float)igamma / (float)100000.0;
    647 #  ifdef PNG_READ_GAMMA_SUPPORTED
    648      png_ptr->gamma = file_gamma;
    649 #  endif
    650      png_set_gAMA(png_ptr, info_ptr, file_gamma);
    651 #endif
    652 #ifdef PNG_FIXED_POINT_SUPPORTED
    653    png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
    654 #endif
    655 }
    656 #endif
    657 
    658 #if defined(PNG_READ_sBIT_SUPPORTED)
    659 void /* PRIVATE */
    660 png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    661 {
    662    png_size_t truelen;
    663    png_byte buf[4];
    664 
    665    png_debug(1, "in png_handle_sBIT\n");
    666 
    667    buf[0] = buf[1] = buf[2] = buf[3] = 0;
    668 
    669    if (!(png_ptr->mode & PNG_HAVE_IHDR))
    670       png_error(png_ptr, "Missing IHDR before sBIT");
    671    else if (png_ptr->mode & PNG_HAVE_IDAT)
    672    {
    673       png_warning(png_ptr, "Invalid sBIT after IDAT");
    674       png_crc_finish(png_ptr, length);
    675       return;
    676    }
    677    else if (png_ptr->mode & PNG_HAVE_PLTE)
    678    {
    679       /* Should be an error, but we can cope with it */
    680       png_warning(png_ptr, "Out of place sBIT chunk");
    681    }
    682    if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
    683    {
    684       png_warning(png_ptr, "Duplicate sBIT chunk");
    685       png_crc_finish(png_ptr, length);
    686       return;
    687    }
    688 
    689    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
    690       truelen = 3;
    691    else
    692       truelen = (png_size_t)png_ptr->channels;
    693 
    694    if (length != truelen || length > 4)
    695    {
    696       png_warning(png_ptr, "Incorrect sBIT chunk length");
    697       png_crc_finish(png_ptr, length);
    698       return;
    699    }
    700 
    701    png_crc_read(png_ptr, buf, truelen);
    702    if (png_crc_finish(png_ptr, 0))
    703       return;
    704 
    705    if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
    706    {
    707       png_ptr->sig_bit.red = buf[0];
    708       png_ptr->sig_bit.green = buf[1];
    709       png_ptr->sig_bit.blue = buf[2];
    710       png_ptr->sig_bit.alpha = buf[3];
    711    }
    712    else
    713    {
    714       png_ptr->sig_bit.gray = buf[0];
    715       png_ptr->sig_bit.red = buf[0];
    716       png_ptr->sig_bit.green = buf[0];
    717       png_ptr->sig_bit.blue = buf[0];
    718       png_ptr->sig_bit.alpha = buf[1];
    719    }
    720    png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
    721 }
    722 #endif
    723 
    724 #if defined(PNG_READ_cHRM_SUPPORTED)
    725 void /* PRIVATE */
    726 png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    727 {
    728    png_byte buf[4];
    729 #ifdef PNG_FLOATING_POINT_SUPPORTED
    730    float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
    731 #endif
    732    png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
    733       int_y_green, int_x_blue, int_y_blue;
    734 
    735    png_uint_32 uint_x, uint_y;
    736 
    737    png_debug(1, "in png_handle_cHRM\n");
    738 
    739    if (!(png_ptr->mode & PNG_HAVE_IHDR))
    740       png_error(png_ptr, "Missing IHDR before cHRM");
    741    else if (png_ptr->mode & PNG_HAVE_IDAT)
    742    {
    743       png_warning(png_ptr, "Invalid cHRM after IDAT");
    744       png_crc_finish(png_ptr, length);
    745       return;
    746    }
    747    else if (png_ptr->mode & PNG_HAVE_PLTE)
    748       /* Should be an error, but we can cope with it */
    749       png_warning(png_ptr, "Missing PLTE before cHRM");
    750 
    751    if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
    752 #if defined(PNG_READ_sRGB_SUPPORTED)
    753       && !(info_ptr->valid & PNG_INFO_sRGB)
    754 #endif
    755       )
    756    {
    757       png_warning(png_ptr, "Duplicate cHRM chunk");
    758       png_crc_finish(png_ptr, length);
    759       return;
    760    }
    761 
    762    if (length != 32)
    763    {
    764       png_warning(png_ptr, "Incorrect cHRM chunk length");
    765       png_crc_finish(png_ptr, length);
    766       return;
    767    }
    768 
    769    png_crc_read(png_ptr, buf, 4);
    770    uint_x = png_get_uint_32(buf);
    771 
    772    png_crc_read(png_ptr, buf, 4);
    773    uint_y = png_get_uint_32(buf);
    774 
    775    if (uint_x > 80000L || uint_y > 80000L ||
    776       uint_x + uint_y > 100000L)
    777    {
    778       png_warning(png_ptr, "Invalid cHRM white point");
    779       png_crc_finish(png_ptr, 24);
    780       return;
    781    }
    782    int_x_white = (png_fixed_point)uint_x;
    783    int_y_white = (png_fixed_point)uint_y;
    784 
    785    png_crc_read(png_ptr, buf, 4);
    786    uint_x = png_get_uint_32(buf);
    787 
    788    png_crc_read(png_ptr, buf, 4);
    789    uint_y = png_get_uint_32(buf);
    790 
    791    if (uint_x + uint_y > 100000L)
    792    {
    793       png_warning(png_ptr, "Invalid cHRM red point");
    794       png_crc_finish(png_ptr, 16);
    795       return;
    796    }
    797    int_x_red = (png_fixed_point)uint_x;
    798    int_y_red = (png_fixed_point)uint_y;
    799 
    800    png_crc_read(png_ptr, buf, 4);
    801    uint_x = png_get_uint_32(buf);
    802 
    803    png_crc_read(png_ptr, buf, 4);
    804    uint_y = png_get_uint_32(buf);
    805 
    806    if (uint_x + uint_y > 100000L)
    807    {
    808       png_warning(png_ptr, "Invalid cHRM green point");
    809       png_crc_finish(png_ptr, 8);
    810       return;
    811    }
    812    int_x_green = (png_fixed_point)uint_x;
    813    int_y_green = (png_fixed_point)uint_y;
    814 
    815    png_crc_read(png_ptr, buf, 4);
    816    uint_x = png_get_uint_32(buf);
    817 
    818    png_crc_read(png_ptr, buf, 4);
    819    uint_y = png_get_uint_32(buf);
    820 
    821    if (uint_x + uint_y > 100000L)
    822    {
    823       png_warning(png_ptr, "Invalid cHRM blue point");
    824       png_crc_finish(png_ptr, 0);
    825       return;
    826    }
    827    int_x_blue = (png_fixed_point)uint_x;
    828    int_y_blue = (png_fixed_point)uint_y;
    829 
    830 #ifdef PNG_FLOATING_POINT_SUPPORTED
    831    white_x = (float)int_x_white / (float)100000.0;
    832    white_y = (float)int_y_white / (float)100000.0;
    833    red_x   = (float)int_x_red   / (float)100000.0;
    834    red_y   = (float)int_y_red   / (float)100000.0;
    835    green_x = (float)int_x_green / (float)100000.0;
    836    green_y = (float)int_y_green / (float)100000.0;
    837    blue_x  = (float)int_x_blue  / (float)100000.0;
    838    blue_y  = (float)int_y_blue  / (float)100000.0;
    839 #endif
    840 
    841 #if defined(PNG_READ_sRGB_SUPPORTED)
    842    if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB))
    843       {
    844       if (PNG_OUT_OF_RANGE(int_x_white, 31270,  1000) ||
    845           PNG_OUT_OF_RANGE(int_y_white, 32900,  1000) ||
    846           PNG_OUT_OF_RANGE(int_x_red,   64000L, 1000) ||
    847           PNG_OUT_OF_RANGE(int_y_red,   33000,  1000) ||
    848           PNG_OUT_OF_RANGE(int_x_green, 30000,  1000) ||
    849           PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) ||
    850           PNG_OUT_OF_RANGE(int_x_blue,  15000,  1000) ||
    851           PNG_OUT_OF_RANGE(int_y_blue,   6000,  1000))
    852          {
    853             png_warning(png_ptr,
    854               "Ignoring incorrect cHRM value when sRGB is also present");
    855 #ifndef PNG_NO_CONSOLE_IO
    856 #ifdef PNG_FLOATING_POINT_SUPPORTED
    857             fprintf(stderr,"wx=%f, wy=%f, rx=%f, ry=%f\n",
    858                white_x, white_y, red_x, red_y);
    859             fprintf(stderr,"gx=%f, gy=%f, bx=%f, by=%f\n",
    860                green_x, green_y, blue_x, blue_y);
    861 #else
    862             fprintf(stderr,"wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
    863                int_x_white, int_y_white, int_x_red, int_y_red);
    864             fprintf(stderr,"gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
    865                int_x_green, int_y_green, int_x_blue, int_y_blue);
    866 #endif
    867 #endif /* PNG_NO_CONSOLE_IO */
    868          }
    869          png_crc_finish(png_ptr, 0);
    870          return;
    871       }
    872 #endif /* PNG_READ_sRGB_SUPPORTED */
    873 
    874 #ifdef PNG_FLOATING_POINT_SUPPORTED
    875    png_set_cHRM(png_ptr, info_ptr,
    876       white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
    877 #endif
    878 #ifdef PNG_FIXED_POINT_SUPPORTED
    879    png_set_cHRM_fixed(png_ptr, info_ptr,
    880       int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
    881       int_y_green, int_x_blue, int_y_blue);
    882 #endif
    883    if (png_crc_finish(png_ptr, 0))
    884       return;
    885 }
    886 #endif
    887 
    888 #if defined(PNG_READ_sRGB_SUPPORTED)
    889 void /* PRIVATE */
    890 png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    891 {
    892    int intent;
    893    png_byte buf[1];
    894 
    895    png_debug(1, "in png_handle_sRGB\n");
    896 
    897    if (!(png_ptr->mode & PNG_HAVE_IHDR))
    898       png_error(png_ptr, "Missing IHDR before sRGB");
    899    else if (png_ptr->mode & PNG_HAVE_IDAT)
    900    {
    901       png_warning(png_ptr, "Invalid sRGB after IDAT");
    902       png_crc_finish(png_ptr, length);
    903       return;
    904    }
    905    else if (png_ptr->mode & PNG_HAVE_PLTE)
    906       /* Should be an error, but we can cope with it */
    907       png_warning(png_ptr, "Out of place sRGB chunk");
    908 
    909    if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
    910    {
    911       png_warning(png_ptr, "Duplicate sRGB chunk");
    912       png_crc_finish(png_ptr, length);
    913       return;
    914    }
    915 
    916    if (length != 1)
    917    {
    918       png_warning(png_ptr, "Incorrect sRGB chunk length");
    919       png_crc_finish(png_ptr, length);
    920       return;
    921    }
    922 
    923    png_crc_read(png_ptr, buf, 1);
    924    if (png_crc_finish(png_ptr, 0))
    925       return;
    926 
    927    intent = buf[0];
    928    /* check for bad intent */
    929    if (intent >= PNG_sRGB_INTENT_LAST)
    930    {
    931       png_warning(png_ptr, "Unknown sRGB intent");
    932       return;
    933    }
    934 
    935 #if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
    936    if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA))
    937    {
    938    png_fixed_point igamma;
    939 #ifdef PNG_FIXED_POINT_SUPPORTED
    940       igamma=info_ptr->int_gamma;
    941 #else
    942 #  ifdef PNG_FLOATING_POINT_SUPPORTED
    943       igamma=(png_fixed_point)(info_ptr->gamma * 100000.);
    944 #  endif
    945 #endif
    946       if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
    947       {
    948          png_warning(png_ptr,
    949            "Ignoring incorrect gAMA value when sRGB is also present");
    950 #ifndef PNG_NO_CONSOLE_IO
    951 #  ifdef PNG_FIXED_POINT_SUPPORTED
    952          fprintf(stderr,"incorrect gamma=(%d/100000)\n",(int)png_ptr->int_gamma);
    953 #  else
    954 #    ifdef PNG_FLOATING_POINT_SUPPORTED
    955          fprintf(stderr,"incorrect gamma=%f\n",png_ptr->gamma);
    956 #    endif
    957 #  endif
    958 #endif
    959       }
    960    }
    961 #endif /* PNG_READ_gAMA_SUPPORTED */
    962 
    963 #ifdef PNG_READ_cHRM_SUPPORTED
    964 #ifdef PNG_FIXED_POINT_SUPPORTED
    965    if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
    966       if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270,  1000) ||
    967           PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900,  1000) ||
    968           PNG_OUT_OF_RANGE(info_ptr->int_x_red,   64000L, 1000) ||
    969           PNG_OUT_OF_RANGE(info_ptr->int_y_red,   33000,  1000) ||
    970           PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000,  1000) ||
    971           PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) ||
    972           PNG_OUT_OF_RANGE(info_ptr->int_x_blue,  15000,  1000) ||
    973           PNG_OUT_OF_RANGE(info_ptr->int_y_blue,   6000,  1000))
    974          {
    975             png_warning(png_ptr,
    976               "Ignoring incorrect cHRM value when sRGB is also present");
    977          }
    978 #endif /* PNG_FIXED_POINT_SUPPORTED */
    979 #endif /* PNG_READ_cHRM_SUPPORTED */
    980 
    981    png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
    982 }
    983 #endif /* PNG_READ_sRGB_SUPPORTED */
    984 
    985 #if defined(PNG_READ_iCCP_SUPPORTED)
    986 void /* PRIVATE */
    987 png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
    988 /* Note: this does not properly handle chunks that are > 64K under DOS */
    989 {
    990    png_charp chunkdata;
    991    png_byte compression_type;
    992    png_bytep pC;
    993    png_charp profile;
    994    png_uint_32 skip = 0;
    995    png_uint_32 profile_size, profile_length;
    996    png_size_t slength, prefix_length, data_length;
    997 
    998    png_debug(1, "in png_handle_iCCP\n");
    999 
   1000    if (!(png_ptr->mode & PNG_HAVE_IHDR))
   1001       png_error(png_ptr, "Missing IHDR before iCCP");
   1002    else if (png_ptr->mode & PNG_HAVE_IDAT)
   1003    {
   1004       png_warning(png_ptr, "Invalid iCCP after IDAT");
   1005       png_crc_finish(png_ptr, length);
   1006       return;
   1007    }
   1008    else if (png_ptr->mode & PNG_HAVE_PLTE)
   1009       /* Should be an error, but we can cope with it */
   1010       png_warning(png_ptr, "Out of place iCCP chunk");
   1011 
   1012    if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
   1013    {
   1014       png_warning(png_ptr, "Duplicate iCCP chunk");
   1015       png_crc_finish(png_ptr, length);
   1016       return;
   1017    }
   1018 
   1019 #ifdef PNG_MAX_MALLOC_64K
   1020    if (length > (png_uint_32)65535L)
   1021    {
   1022       png_warning(png_ptr, "iCCP chunk too large to fit in memory");
   1023       skip = length - (png_uint_32)65535L;
   1024       length = (png_uint_32)65535L;
   1025    }
   1026 #endif
   1027 
   1028    chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
   1029    slength = (png_size_t)length;
   1030    png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
   1031 
   1032    if (png_crc_finish(png_ptr, skip))
   1033    {
   1034       png_free(png_ptr, chunkdata);
   1035       return;
   1036    }
   1037 
   1038    chunkdata[slength] = 0x00;
   1039 
   1040    for (profile = chunkdata; *profile; profile++)
   1041       /* empty loop to find end of name */ ;
   1042 
   1043    ++profile;
   1044 
   1045    /* there should be at least one zero (the compression type byte)
   1046       following the separator, and we should be on it  */
   1047    if ( profile >= chunkdata + slength - 1)
   1048    {
   1049       png_free(png_ptr, chunkdata);
   1050       png_warning(png_ptr, "Malformed iCCP chunk");
   1051       return;
   1052    }
   1053 
   1054    /* compression_type should always be zero */
   1055    compression_type = *profile++;
   1056    if (compression_type)
   1057    {
   1058       png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
   1059       compression_type=0x00;  /* Reset it to zero (libpng-1.0.6 through 1.0.8
   1060                                  wrote nonzero) */
   1061    }
   1062 
   1063    prefix_length = profile - chunkdata;
   1064    chunkdata = png_decompress_chunk(png_ptr, compression_type, chunkdata,
   1065                                     slength, prefix_length, &data_length);
   1066 
   1067    profile_length = data_length - prefix_length;
   1068 
   1069    if ( prefix_length > data_length || profile_length < 4)
   1070    {
   1071       png_free(png_ptr, chunkdata);
   1072       png_warning(png_ptr, "Profile size field missing from iCCP chunk");
   1073       return;
   1074    }
   1075 
   1076    /* Check the profile_size recorded in the first 32 bits of the ICC profile */
   1077    pC = (png_bytep)(chunkdata+prefix_length);
   1078    profile_size = ((*(pC  ))<<24) |
   1079                   ((*(pC+1))<<16) |
   1080                   ((*(pC+2))<< 8) |
   1081                   ((*(pC+3))    );
   1082 
   1083    if(profile_size < profile_length)
   1084       profile_length = profile_size;
   1085 
   1086    if(profile_size > profile_length)
   1087    {
   1088       png_free(png_ptr, chunkdata);
   1089       png_warning(png_ptr, "Ignoring truncated iCCP profile.");
   1090       return;
   1091    }
   1092 
   1093    png_set_iCCP(png_ptr, info_ptr, chunkdata, compression_type,
   1094                 chunkdata + prefix_length, profile_length);
   1095    png_free(png_ptr, chunkdata);
   1096 }
   1097 #endif /* PNG_READ_iCCP_SUPPORTED */
   1098 
   1099 #if defined(PNG_READ_sPLT_SUPPORTED)
   1100 void /* PRIVATE */
   1101 png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
   1102 /* Note: this does not properly handle chunks that are > 64K under DOS */
   1103 {
   1104    png_bytep chunkdata;
   1105    png_bytep entry_start;
   1106    png_sPLT_t new_palette;
   1107 #ifdef PNG_NO_POINTER_INDEXING
   1108    png_sPLT_entryp pp;
   1109 #endif
   1110    int data_length, entry_size, i;
   1111    png_uint_32 skip = 0;
   1112    png_size_t slength;
   1113 
   1114    png_debug(1, "in png_handle_sPLT\n");
   1115 
   1116    if (!(png_ptr->mode & PNG_HAVE_IHDR))
   1117       png_error(png_ptr, "Missing IHDR before sPLT");
   1118    else if (png_ptr->mode & PNG_HAVE_IDAT)
   1119    {
   1120       png_warning(png_ptr, "Invalid sPLT after IDAT");
   1121       png_crc_finish(png_ptr, length);
   1122       return;
   1123    }
   1124 
   1125 #ifdef PNG_MAX_MALLOC_64K
   1126    if (length > (png_uint_32)65535L)
   1127    {
   1128       png_warning(png_ptr, "sPLT chunk too large to fit in memory");
   1129       skip = length - (png_uint_32)65535L;
   1130       length = (png_uint_32)65535L;
   1131    }
   1132 #endif
   1133 
   1134    chunkdata = (png_bytep)png_malloc(png_ptr, length + 1);
   1135    slength = (png_size_t)length;
   1136    png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
   1137 
   1138    if (png_crc_finish(png_ptr, skip))
   1139    {
   1140       png_free(png_ptr, chunkdata);
   1141       return;
   1142    }
   1143 
   1144    chunkdata[slength] = 0x00;
   1145 
   1146    for (entry_start = chunkdata; *entry_start; entry_start++)
   1147       /* empty loop to find end of name */ ;
   1148    ++entry_start;
   1149 
   1150    /* a sample depth should follow the separator, and we should be on it  */
   1151    if (entry_start > chunkdata + slength - 2)
   1152    {
   1153       png_free(png_ptr, chunkdata);
   1154       png_warning(png_ptr, "malformed sPLT chunk");
   1155       return;
   1156    }
   1157 
   1158    new_palette.depth = *entry_start++;
   1159    entry_size = (new_palette.depth == 8 ? 6 : 10);
   1160    data_length = (slength - (entry_start - chunkdata));
   1161 
   1162    /* integrity-check the data length */
   1163    if (data_length % entry_size)
   1164    {
   1165       png_free(png_ptr, chunkdata);
   1166       png_warning(png_ptr, "sPLT chunk has bad length");
   1167       return;
   1168    }
   1169 
   1170    new_palette.nentries = (png_int_32) ( data_length / entry_size);
   1171    if ((png_uint_32) new_palette.nentries > (png_uint_32) (PNG_SIZE_MAX /
   1172        png_sizeof(png_sPLT_entry)))
   1173    {
   1174        png_warning(png_ptr, "sPLT chunk too long");
   1175        return;
   1176    }
   1177    new_palette.entries = (png_sPLT_entryp)png_malloc_warn(
   1178        png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry));
   1179    if (new_palette.entries == NULL)
   1180    {
   1181        png_warning(png_ptr, "sPLT chunk requires too much memory");
   1182        return;
   1183    }
   1184 
   1185 #ifndef PNG_NO_POINTER_INDEXING
   1186    for (i = 0; i < new_palette.nentries; i++)
   1187    {
   1188       png_sPLT_entryp pp = new_palette.entries + i;
   1189 
   1190       if (new_palette.depth == 8)
   1191       {
   1192           pp->red = *entry_start++;
   1193           pp->green = *entry_start++;
   1194           pp->blue = *entry_start++;
   1195           pp->alpha = *entry_start++;
   1196       }
   1197       else
   1198       {
   1199           pp->red   = png_get_uint_16(entry_start); entry_start += 2;
   1200           pp->green = png_get_uint_16(entry_start); entry_start += 2;
   1201           pp->blue  = png_get_uint_16(entry_start); entry_start += 2;
   1202           pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
   1203       }
   1204       pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
   1205    }
   1206 #else
   1207    pp = new_palette.entries;
   1208    for (i = 0; i < new_palette.nentries; i++)
   1209    {
   1210 
   1211       if (new_palette.depth == 8)
   1212       {
   1213           pp[i].red   = *entry_start++;
   1214           pp[i].green = *entry_start++;
   1215           pp[i].blue  = *entry_start++;
   1216           pp[i].alpha = *entry_start++;
   1217       }
   1218       else
   1219       {
   1220           pp[i].red   = png_get_uint_16(entry_start); entry_start += 2;
   1221           pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
   1222           pp[i].blue  = png_get_uint_16(entry_start); entry_start += 2;
   1223           pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
   1224       }
   1225       pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
   1226    }
   1227 #endif
   1228 
   1229    /* discard all chunk data except the name and stash that */
   1230    new_palette.name = (png_charp)chunkdata;
   1231 
   1232    png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
   1233 
   1234    png_free(png_ptr, chunkdata);
   1235    png_free(png_ptr, new_palette.entries);
   1236 }
   1237 #endif /* PNG_READ_sPLT_SUPPORTED */
   1238 
   1239 #if defined(PNG_READ_tRNS_SUPPORTED)
   1240 void /* PRIVATE */
   1241 png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
   1242 {
   1243    png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
   1244    int bit_mask;
   1245 
   1246    png_debug(1, "in png_handle_tRNS\n");
   1247 
   1248    /* For non-indexed color, mask off any bits in the tRNS value that
   1249     * exceed the bit depth.  Some creators were writing extra bits there.
   1250     * This is not needed for indexed color. */
   1251    bit_mask = (1 << png_ptr->bit_depth) - 1;
   1252 
   1253    if (!(png_ptr->mode & PNG_HAVE_IHDR))
   1254       png_error(png_ptr, "Missing IHDR before tRNS");
   1255    else if (png_ptr->mode & PNG_HAVE_IDAT)
   1256    {
   1257       png_warning(png_ptr, "Invalid tRNS after IDAT");
   1258       png_crc_finish(png_ptr, length);
   1259       return;
   1260    }
   1261    else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
   1262    {
   1263       png_warning(png_ptr, "Duplicate tRNS chunk");
   1264       png_crc_finish(png_ptr, length);
   1265       return;
   1266    }
   1267 
   1268    if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
   1269    {
   1270       png_byte buf[2];
   1271 
   1272       if (length != 2)
   1273       {
   1274          png_warning(png_ptr, "Incorrect tRNS chunk length");
   1275          png_crc_finish(png_ptr, length);
   1276          return;
   1277       }
   1278 
   1279       png_crc_read(png_ptr, buf, 2);
   1280       png_ptr->num_trans = 1;
   1281       png_ptr->trans_values.gray = png_get_uint_16(buf) & bit_mask;
   1282    }
   1283    else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
   1284    {
   1285       png_byte buf[6];
   1286 
   1287       if (length != 6)
   1288       {
   1289          png_warning(png_ptr, "Incorrect tRNS chunk length");
   1290          png_crc_finish(png_ptr, length);
   1291          return;
   1292       }
   1293       png_crc_read(png_ptr, buf, (png_size_t)length);
   1294       png_ptr->num_trans = 1;
   1295       png_ptr->trans_values.red = png_get_uint_16(buf) & bit_mask;
   1296       png_ptr->trans_values.green = png_get_uint_16(buf + 2) & bit_mask;
   1297       png_ptr->trans_values.blue = png_get_uint_16(buf + 4) & bit_mask;
   1298    }
   1299    else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
   1300    {
   1301       if (!(png_ptr->mode & PNG_HAVE_PLTE))
   1302       {
   1303          /* Should be an error, but we can cope with it. */
   1304          png_warning(png_ptr, "Missing PLTE before tRNS");
   1305       }
   1306       if (length > (png_uint_32)png_ptr->num_palette ||
   1307           length > PNG_MAX_PALETTE_LENGTH)
   1308       {
   1309          png_warning(png_ptr, "Incorrect tRNS chunk length");
   1310          png_crc_finish(png_ptr, length);
   1311          return;
   1312       }
   1313       if (length == 0)
   1314       {
   1315          png_warning(png_ptr, "Zero length tRNS chunk");
   1316          png_crc_finish(png_ptr, length);
   1317          return;
   1318       }
   1319       png_crc_read(png_ptr, readbuf, (png_size_t)length);
   1320       png_ptr->num_trans = (png_uint_16)length;
   1321    }
   1322    else
   1323    {
   1324       png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
   1325       png_crc_finish(png_ptr, length);
   1326       return;
   1327    }
   1328 
   1329    if (png_crc_finish(png_ptr, 0))
   1330    {
   1331       png_ptr->num_trans = 0;
   1332       return;
   1333    }
   1334 
   1335    png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
   1336       &(png_ptr->trans_values));
   1337 }
   1338 #endif
   1339 
   1340 #if defined(PNG_READ_bKGD_SUPPORTED)
   1341 void /* PRIVATE */
   1342 png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
   1343 {
   1344    png_size_t truelen;
   1345    png_byte buf[6];
   1346 
   1347    png_debug(1, "in png_handle_bKGD\n");
   1348 
   1349    if (!(png_ptr->mode & PNG_HAVE_IHDR))
   1350       png_error(png_ptr, "Missing IHDR before bKGD");
   1351    else if (png_ptr->mode & PNG_HAVE_IDAT)
   1352    {
   1353       png_warning(png_ptr, "Invalid bKGD after IDAT");
   1354       png_crc_finish(png_ptr, length);
   1355       return;
   1356    }
   1357    else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
   1358             !(png_ptr->mode & PNG_HAVE_PLTE))
   1359    {
   1360       png_warning(png_ptr, "Missing PLTE before bKGD");
   1361       png_crc_finish(png_ptr, length);
   1362       return;
   1363    }
   1364    else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
   1365    {
   1366       png_warning(png_ptr, "Duplicate bKGD chunk");
   1367       png_crc_finish(png_ptr, length);
   1368       return;
   1369    }
   1370 
   1371    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
   1372       truelen = 1;
   1373    else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
   1374       truelen = 6;
   1375    else
   1376       truelen = 2;
   1377 
   1378    if (length != truelen)
   1379    {
   1380       png_warning(png_ptr, "Incorrect bKGD chunk length");
   1381       png_crc_finish(png_ptr, length);
   1382       return;
   1383    }
   1384 
   1385    png_crc_read(png_ptr, buf, truelen);
   1386    if (png_crc_finish(png_ptr, 0))
   1387       return;
   1388 
   1389    /* We convert the index value into RGB components so that we can allow
   1390     * arbitrary RGB values for background when we have transparency, and
   1391     * so it is easy to determine the RGB values of the background color
   1392     * from the info_ptr struct. */
   1393    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
   1394    {
   1395       png_ptr->background.index = buf[0];
   1396       if(info_ptr->num_palette)
   1397       {
   1398           if(buf[0] > info_ptr->num_palette)
   1399           {
   1400              png_warning(png_ptr, "Incorrect bKGD chunk index value");
   1401              return;
   1402           }
   1403           png_ptr->background.red =
   1404              (png_uint_16)png_ptr->palette[buf[0]].red;
   1405           png_ptr->background.green =
   1406              (png_uint_16)png_ptr->palette[buf[0]].green;
   1407           png_ptr->background.blue =
   1408              (png_uint_16)png_ptr->palette[buf[0]].blue;
   1409       }
   1410    }
   1411    else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
   1412    {
   1413       png_ptr->background.red =
   1414       png_ptr->background.green =
   1415       png_ptr->background.blue =
   1416       png_ptr->background.gray = png_get_uint_16(buf);
   1417    }
   1418    else
   1419    {
   1420       png_ptr->background.red = png_get_uint_16(buf);
   1421       png_ptr->background.green = png_get_uint_16(buf + 2);
   1422       png_ptr->background.blue = png_get_uint_16(buf + 4);
   1423    }
   1424 
   1425    png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
   1426 }
   1427 #endif
   1428 
   1429 #if defined(PNG_READ_hIST_SUPPORTED)
   1430 void /* PRIVATE */
   1431 png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
   1432 {
   1433    unsigned int num, i;
   1434    png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
   1435 
   1436    png_debug(1, "in png_handle_hIST\n");
   1437 
   1438    if (!(png_ptr->mode & PNG_HAVE_IHDR))
   1439       png_error(png_ptr, "Missing IHDR before hIST");
   1440    else if (png_ptr->mode & PNG_HAVE_IDAT)
   1441    {
   1442       png_warning(png_ptr, "Invalid hIST after IDAT");
   1443       png_crc_finish(png_ptr, length);
   1444       return;
   1445    }
   1446    else if (!(png_ptr->mode & PNG_HAVE_PLTE))
   1447    {
   1448       png_warning(png_ptr, "Missing PLTE before hIST");
   1449       png_crc_finish(png_ptr, length);
   1450       return;
   1451    }
   1452    else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
   1453    {
   1454       png_warning(png_ptr, "Duplicate hIST chunk");
   1455       png_crc_finish(png_ptr, length);
   1456       return;
   1457    }
   1458 
   1459    num = length / 2 ;
   1460    if (num != (unsigned int) png_ptr->num_palette || num >
   1461       (unsigned int) PNG_MAX_PALETTE_LENGTH)
   1462    {
   1463       png_warning(png_ptr, "Incorrect hIST chunk length");
   1464       png_crc_finish(png_ptr, length);
   1465       return;
   1466    }
   1467 
   1468    for (i = 0; i < num; i++)
   1469    {
   1470       png_byte buf[2];
   1471 
   1472       png_crc_read(png_ptr, buf, 2);
   1473       readbuf[i] = png_get_uint_16(buf);
   1474    }
   1475 
   1476    if (png_crc_finish(png_ptr, 0))
   1477       return;
   1478 
   1479    png_set_hIST(png_ptr, info_ptr, readbuf);
   1480 }
   1481 #endif
   1482 
   1483 #if defined(PNG_READ_pHYs_SUPPORTED)
   1484 void /* PRIVATE */
   1485 png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
   1486 {
   1487    png_byte buf[9];
   1488    png_uint_32 res_x, res_y;
   1489    int unit_type;
   1490 
   1491    png_debug(1, "in png_handle_pHYs\n");
   1492 
   1493    if (!(png_ptr->mode & PNG_HAVE_IHDR))
   1494       png_error(png_ptr, "Missing IHDR before pHYs");
   1495    else if (png_ptr->mode & PNG_HAVE_IDAT)
   1496    {
   1497       png_warning(png_ptr, "Invalid pHYs after IDAT");
   1498       png_crc_finish(png_ptr, length);
   1499       return;
   1500    }
   1501    else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
   1502    {
   1503       png_warning(png_ptr, "Duplicate pHYs chunk");
   1504       png_crc_finish(png_ptr, length);
   1505       return;
   1506    }
   1507 
   1508    if (length != 9)
   1509    {
   1510       png_warning(png_ptr, "Incorrect pHYs chunk length");
   1511       png_crc_finish(png_ptr, length);
   1512       return;
   1513    }
   1514 
   1515    png_crc_read(png_ptr, buf, 9);
   1516    if (png_crc_finish(png_ptr, 0))
   1517       return;
   1518 
   1519    res_x = png_get_uint_32(buf);
   1520    res_y = png_get_uint_32(buf + 4);
   1521    unit_type = buf[8];
   1522    png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
   1523 }
   1524 #endif
   1525 
   1526 #if defined(PNG_READ_oFFs_SUPPORTED)
   1527 void /* PRIVATE */
   1528 png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
   1529 {
   1530    png_byte buf[9];
   1531    png_int_32 offset_x, offset_y;
   1532    int unit_type;
   1533 
   1534    png_debug(1, "in png_handle_oFFs\n");
   1535 
   1536    if (!(png_ptr->mode & PNG_HAVE_IHDR))
   1537       png_error(png_ptr, "Missing IHDR before oFFs");
   1538    else if (png_ptr->mode & PNG_HAVE_IDAT)
   1539    {
   1540       png_warning(png_ptr, "Invalid oFFs after IDAT");
   1541       png_crc_finish(png_ptr, length);
   1542       return;
   1543    }
   1544    else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
   1545    {
   1546       png_warning(png_ptr, "Duplicate oFFs chunk");
   1547       png_crc_finish(png_ptr, length);
   1548       return;
   1549    }
   1550 
   1551    if (length != 9)
   1552    {
   1553       png_warning(png_ptr, "Incorrect oFFs chunk length");
   1554       png_crc_finish(png_ptr, length);
   1555       return;
   1556    }
   1557 
   1558    png_crc_read(png_ptr, buf, 9);
   1559    if (png_crc_finish(png_ptr, 0))
   1560       return;
   1561 
   1562    offset_x = png_get_int_32(buf);
   1563    offset_y = png_get_int_32(buf + 4);
   1564    unit_type = buf[8];
   1565    png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
   1566 }
   1567 #endif
   1568 
   1569 #if defined(PNG_READ_pCAL_SUPPORTED)
   1570 /* read the pCAL chunk (described in the PNG Extensions document) */
   1571 void /* PRIVATE */
   1572 png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
   1573 {
   1574    png_charp purpose;
   1575    png_int_32 X0, X1;
   1576    png_byte type, nparams;
   1577    png_charp buf, units, endptr;
   1578    png_charpp params;
   1579    png_size_t slength;
   1580    int i;
   1581 
   1582    png_debug(1, "in png_handle_pCAL\n");
   1583 
   1584    if (!(png_ptr->mode & PNG_HAVE_IHDR))
   1585       png_error(png_ptr, "Missing IHDR before pCAL");
   1586    else if (png_ptr->mode & PNG_HAVE_IDAT)
   1587    {
   1588       png_warning(png_ptr, "Invalid pCAL after IDAT");
   1589       png_crc_finish(png_ptr, length);
   1590       return;
   1591    }
   1592    else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
   1593    {
   1594       png_warning(png_ptr, "Duplicate pCAL chunk");
   1595       png_crc_finish(png_ptr, length);
   1596       return;
   1597    }
   1598 
   1599    png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)\n",
   1600       length + 1);
   1601    purpose = (png_charp)png_malloc_warn(png_ptr, length + 1);
   1602    if (purpose == NULL)
   1603      {
   1604        png_warning(png_ptr, "No memory for pCAL purpose.");
   1605        return;
   1606      }
   1607    slength = (png_size_t)length;
   1608    png_crc_read(png_ptr, (png_bytep)purpose, slength);
   1609 
   1610    if (png_crc_finish(png_ptr, 0))
   1611    {
   1612       png_free(png_ptr, purpose);
   1613       return;
   1614    }
   1615 
   1616    purpose[slength] = 0x00; /* null terminate the last string */
   1617 
   1618    png_debug(3, "Finding end of pCAL purpose string\n");
   1619    for (buf = purpose; *buf; buf++)
   1620       /* empty loop */ ;
   1621 
   1622    endptr = purpose + slength;
   1623 
   1624    /* We need to have at least 12 bytes after the purpose string
   1625       in order to get the parameter information. */
   1626    if (endptr <= buf + 12)
   1627    {
   1628       png_warning(png_ptr, "Invalid pCAL data");
   1629       png_free(png_ptr, purpose);
   1630       return;
   1631    }
   1632 
   1633    png_debug(3, "Reading pCAL X0, X1, type, nparams, and units\n");
   1634    X0 = png_get_int_32((png_bytep)buf+1);
   1635    X1 = png_get_int_32((png_bytep)buf+5);
   1636    type = buf[9];
   1637    nparams = buf[10];
   1638    units = buf + 11;
   1639 
   1640    png_debug(3, "Checking pCAL equation type and number of parameters\n");
   1641    /* Check that we have the right number of parameters for known
   1642       equation types. */
   1643    if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
   1644        (type == PNG_EQUATION_BASE_E && nparams != 3) ||
   1645        (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
   1646        (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
   1647    {
   1648       png_warning(png_ptr, "Invalid pCAL parameters for equation type");
   1649       png_free(png_ptr, purpose);
   1650       return;
   1651    }
   1652    else if (type >= PNG_EQUATION_LAST)
   1653    {
   1654       png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
   1655    }
   1656 
   1657    for (buf = units; *buf; buf++)
   1658       /* Empty loop to move past the units string. */ ;
   1659 
   1660    png_debug(3, "Allocating pCAL parameters array\n");
   1661    params = (png_charpp)png_malloc_warn(png_ptr, (png_uint_32)(nparams
   1662       *png_sizeof(png_charp))) ;
   1663    if (params == NULL)
   1664      {
   1665        png_free(png_ptr, purpose);
   1666        png_warning(png_ptr, "No memory for pCAL params.");
   1667        return;
   1668      }
   1669 
   1670    /* Get pointers to the start of each parameter string. */
   1671    for (i = 0; i < (int)nparams; i++)
   1672    {
   1673       buf++; /* Skip the null string terminator from previous parameter. */
   1674 
   1675       png_debug1(3, "Reading pCAL parameter %d\n", i);
   1676       for (params[i] = buf; *buf != 0x00 && buf <= endptr; buf++)
   1677          /* Empty loop to move past each parameter string */ ;
   1678 
   1679       /* Make sure we haven't run out of data yet */
   1680       if (buf > endptr)
   1681       {
   1682          png_warning(png_ptr, "Invalid pCAL data");
   1683          png_free(png_ptr, purpose);
   1684          png_free(png_ptr, params);
   1685          return;
   1686       }
   1687    }
   1688 
   1689    png_set_pCAL(png_ptr, info_ptr, purpose, X0, X1, type, nparams,
   1690       units, params);
   1691 
   1692    png_free(png_ptr, purpose);
   1693    png_free(png_ptr, params);
   1694 }
   1695 #endif
   1696 
   1697 #if defined(PNG_READ_sCAL_SUPPORTED)
   1698 /* read the sCAL chunk */
   1699 void /* PRIVATE */
   1700 png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
   1701 {
   1702    png_charp buffer, ep;
   1703 #ifdef PNG_FLOATING_POINT_SUPPORTED
   1704    double width, height;
   1705    png_charp vp;
   1706 #else
   1707 #ifdef PNG_FIXED_POINT_SUPPORTED
   1708    png_charp swidth, sheight;
   1709 #endif
   1710 #endif
   1711    png_size_t slength;
   1712 
   1713    png_debug(1, "in png_handle_sCAL\n");
   1714 
   1715    if (!(png_ptr->mode & PNG_HAVE_IHDR))
   1716       png_error(png_ptr, "Missing IHDR before sCAL");
   1717    else if (png_ptr->mode & PNG_HAVE_IDAT)
   1718    {
   1719       png_warning(png_ptr, "Invalid sCAL after IDAT");
   1720       png_crc_finish(png_ptr, length);
   1721       return;
   1722    }
   1723    else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
   1724    {
   1725       png_warning(png_ptr, "Duplicate sCAL chunk");
   1726       png_crc_finish(png_ptr, length);
   1727       return;
   1728    }
   1729 
   1730    png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)\n",
   1731       length + 1);
   1732    buffer = (png_charp)png_malloc_warn(png_ptr, length + 1);
   1733    if (buffer == NULL)
   1734      {
   1735        png_warning(png_ptr, "Out of memory while processing sCAL chunk");
   1736        return;
   1737      }
   1738    slength = (png_size_t)length;
   1739    png_crc_read(png_ptr, (png_bytep)buffer, slength);
   1740 
   1741    if (png_crc_finish(png_ptr, 0))
   1742    {
   1743       png_free(png_ptr, buffer);
   1744       return;
   1745    }
   1746 
   1747    buffer[slength] = 0x00; /* null terminate the last string */
   1748 
   1749    ep = buffer + 1;        /* skip unit byte */
   1750 
   1751 #ifdef PNG_FLOATING_POINT_SUPPORTED
   1752    width = png_strtod(png_ptr, ep, &vp);
   1753    if (*vp)
   1754    {
   1755        png_warning(png_ptr, "malformed width string in sCAL chunk");
   1756        return;
   1757    }
   1758 #else
   1759 #ifdef PNG_FIXED_POINT_SUPPORTED
   1760    swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
   1761    if (swidth == NULL)
   1762      {
   1763        png_warning(png_ptr, "Out of memory while processing sCAL chunk width");
   1764        return;
   1765      }
   1766    png_memcpy(swidth, ep, (png_size_t)png_strlen(ep));
   1767 #endif
   1768 #endif
   1769 
   1770    for (ep = buffer; *ep; ep++)
   1771       /* empty loop */ ;
   1772    ep++;
   1773 
   1774 #ifdef PNG_FLOATING_POINT_SUPPORTED
   1775    height = png_strtod(png_ptr, ep, &vp);
   1776    if (*vp)
   1777    {
   1778        png_warning(png_ptr, "malformed height string in sCAL chunk");
   1779        return;
   1780    }
   1781 #else
   1782 #ifdef PNG_FIXED_POINT_SUPPORTED
   1783    sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
   1784    if (swidth == NULL)
   1785      {
   1786        png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
   1787        return;
   1788      }
   1789    png_memcpy(sheight, ep, (png_size_t)png_strlen(ep));
   1790 #endif
   1791 #endif
   1792 
   1793    if (buffer + slength < ep
   1794 #ifdef PNG_FLOATING_POINT_SUPPORTED
   1795       || width <= 0. || height <= 0.
   1796 #endif
   1797       )
   1798    {
   1799       png_warning(png_ptr, "Invalid sCAL data");
   1800       png_free(png_ptr, buffer);
   1801 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
   1802       png_free(png_ptr, swidth);
   1803       png_free(png_ptr, sheight);
   1804 #endif
   1805       return;
   1806    }
   1807 
   1808 
   1809 #ifdef PNG_FLOATING_POINT_SUPPORTED
   1810    png_set_sCAL(png_ptr, info_ptr, buffer[0], width, height);
   1811 #else
   1812 #ifdef PNG_FIXED_POINT_SUPPORTED
   1813    png_set_sCAL_s(png_ptr, info_ptr, buffer[0], swidth, sheight);
   1814 #endif
   1815 #endif
   1816 
   1817    png_free(png_ptr, buffer);
   1818 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
   1819    png_free(png_ptr, swidth);
   1820    png_free(png_ptr, sheight);
   1821 #endif
   1822 }
   1823 #endif
   1824 
   1825 #if defined(PNG_READ_tIME_SUPPORTED)
   1826 void /* PRIVATE */
   1827 png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
   1828 {
   1829    png_byte buf[7];
   1830    png_time mod_time;
   1831 
   1832    png_debug(1, "in png_handle_tIME\n");
   1833 
   1834    if (!(png_ptr->mode & PNG_HAVE_IHDR))
   1835       png_error(png_ptr, "Out of place tIME chunk");
   1836    else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
   1837    {
   1838       png_warning(png_ptr, "Duplicate tIME chunk");
   1839       png_crc_finish(png_ptr, length);
   1840       return;
   1841    }
   1842 
   1843    if (png_ptr->mode & PNG_HAVE_IDAT)
   1844       png_ptr->mode |= PNG_AFTER_IDAT;
   1845 
   1846    if (length != 7)
   1847    {
   1848       png_warning(png_ptr, "Incorrect tIME chunk length");
   1849       png_crc_finish(png_ptr, length);
   1850       return;
   1851    }
   1852 
   1853    png_crc_read(png_ptr, buf, 7);
   1854    if (png_crc_finish(png_ptr, 0))
   1855       return;
   1856 
   1857    mod_time.second = buf[6];
   1858    mod_time.minute = buf[5];
   1859    mod_time.hour = buf[4];
   1860    mod_time.day = buf[3];
   1861    mod_time.month = buf[2];
   1862    mod_time.year = png_get_uint_16(buf);
   1863 
   1864    png_set_tIME(png_ptr, info_ptr, &mod_time);
   1865 }
   1866 #endif
   1867 
   1868 #if defined(PNG_READ_tEXt_SUPPORTED)
   1869 /* Note: this does not properly handle chunks that are > 64K under DOS */
   1870 void /* PRIVATE */
   1871 png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
   1872 {
   1873    png_textp text_ptr;
   1874    png_charp key;
   1875    png_charp text;
   1876    png_uint_32 skip = 0;
   1877    png_size_t slength;
   1878    int ret;
   1879 
   1880    png_debug(1, "in png_handle_tEXt\n");
   1881 
   1882    if (!(png_ptr->mode & PNG_HAVE_IHDR))
   1883       png_error(png_ptr, "Missing IHDR before tEXt");
   1884 
   1885    if (png_ptr->mode & PNG_HAVE_IDAT)
   1886       png_ptr->mode |= PNG_AFTER_IDAT;
   1887 
   1888 #ifdef PNG_MAX_MALLOC_64K
   1889    if (length > (png_uint_32)65535L)
   1890    {
   1891       png_warning(png_ptr, "tEXt chunk too large to fit in memory");
   1892       skip = length - (png_uint_32)65535L;
   1893       length = (png_uint_32)65535L;
   1894    }
   1895 #endif
   1896 
   1897    key = (png_charp)png_malloc_warn(png_ptr, length + 1);
   1898    if (key == NULL)
   1899    {
   1900      png_warning(png_ptr, "No memory to process text chunk.");
   1901      return;
   1902    }
   1903    slength = (png_size_t)length;
   1904    png_crc_read(png_ptr, (png_bytep)key, slength);
   1905 
   1906    if (png_crc_finish(png_ptr, skip))
   1907    {
   1908       png_free(png_ptr, key);
   1909       return;
   1910    }
   1911 
   1912    key[slength] = 0x00;
   1913 
   1914    for (text = key; *text; text++)
   1915       /* empty loop to find end of key */ ;
   1916 
   1917    if (text != key + slength)
   1918       text++;
   1919 
   1920    text_ptr = (png_textp)png_malloc_warn(png_ptr,
   1921       (png_uint_32)png_sizeof(png_text));
   1922    if (text_ptr == NULL)
   1923    {
   1924      png_warning(png_ptr, "Not enough memory to process text chunk.");
   1925      png_free(png_ptr, key);
   1926      return;
   1927    }
   1928    text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
   1929    text_ptr->key = key;
   1930 #ifdef PNG_iTXt_SUPPORTED
   1931    text_ptr->lang = NULL;
   1932    text_ptr->lang_key = NULL;
   1933    text_ptr->itxt_length = 0;
   1934 #endif
   1935    text_ptr->text = text;
   1936    text_ptr->text_length = png_strlen(text);
   1937 
   1938    ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
   1939 
   1940    png_free(png_ptr, key);
   1941    png_free(png_ptr, text_ptr);
   1942    if (ret)
   1943      png_warning(png_ptr, "Insufficient memory to process text chunk.");
   1944 }
   1945 #endif
   1946 
   1947 #if defined(PNG_READ_zTXt_SUPPORTED)
   1948 /* note: this does not correctly handle chunks that are > 64K under DOS */
   1949 void /* PRIVATE */
   1950 png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
   1951 {
   1952    png_textp text_ptr;
   1953    png_charp chunkdata;
   1954    png_charp text;
   1955    int comp_type;
   1956    int ret;
   1957    png_size_t slength, prefix_len, data_len;
   1958 
   1959    png_debug(1, "in png_handle_zTXt\n");
   1960    if (!(png_ptr->mode & PNG_HAVE_IHDR))
   1961       png_error(png_ptr, "Missing IHDR before zTXt");
   1962 
   1963    if (png_ptr->mode & PNG_HAVE_IDAT)
   1964       png_ptr->mode |= PNG_AFTER_IDAT;
   1965 
   1966 #ifdef PNG_MAX_MALLOC_64K
   1967    /* We will no doubt have problems with chunks even half this size, but
   1968       there is no hard and fast rule to tell us where to stop. */
   1969    if (length > (png_uint_32)65535L)
   1970    {
   1971      png_warning(png_ptr,"zTXt chunk too large to fit in memory");
   1972      png_crc_finish(png_ptr, length);
   1973      return;
   1974    }
   1975 #endif
   1976 
   1977    chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
   1978    if (chunkdata == NULL)
   1979    {
   1980      png_warning(png_ptr,"Out of memory processing zTXt chunk.");
   1981      return;
   1982    }
   1983    slength = (png_size_t)length;
   1984    png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
   1985    if (png_crc_finish(png_ptr, 0))
   1986    {
   1987       png_free(png_ptr, chunkdata);
   1988       return;
   1989    }
   1990 
   1991    chunkdata[slength] = 0x00;
   1992 
   1993    for (text = chunkdata; *text; text++)
   1994       /* empty loop */ ;
   1995 
   1996    /* zTXt must have some text after the chunkdataword */
   1997    if (text == chunkdata + slength - 1)
   1998    {
   1999       png_warning(png_ptr, "Truncated zTXt chunk");
   2000       png_free(png_ptr, chunkdata);
   2001       return;
   2002    }
   2003    else
   2004    {
   2005        comp_type = *(++text);
   2006        if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
   2007        {
   2008           png_warning(png_ptr, "Unknown compression type in zTXt chunk");
   2009           comp_type = PNG_TEXT_COMPRESSION_zTXt;
   2010        }
   2011        text++;        /* skip the compression_method byte */
   2012    }
   2013    prefix_len = text - chunkdata;
   2014 
   2015    chunkdata = (png_charp)png_decompress_chunk(png_ptr, comp_type, chunkdata,
   2016                                     (png_size_t)length, prefix_len, &data_len);
   2017 
   2018    text_ptr = (png_textp)png_malloc_warn(png_ptr,
   2019      (png_uint_32)png_sizeof(png_text));
   2020    if (text_ptr == NULL)
   2021    {
   2022      png_warning(png_ptr,"Not enough memory to process zTXt chunk.");
   2023      png_free(png_ptr, chunkdata);
   2024      return;
   2025    }
   2026    text_ptr->compression = comp_type;
   2027    text_ptr->key = chunkdata;
   2028 #ifdef PNG_iTXt_SUPPORTED
   2029    text_ptr->lang = NULL;
   2030    text_ptr->lang_key = NULL;
   2031    text_ptr->itxt_length = 0;
   2032 #endif
   2033    text_ptr->text = chunkdata + prefix_len;
   2034    text_ptr->text_length = data_len;
   2035 
   2036    ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
   2037 
   2038    png_free(png_ptr, text_ptr);
   2039    png_free(png_ptr, chunkdata);
   2040    if (ret)
   2041      png_error(png_ptr, "Insufficient memory to store zTXt chunk.");
   2042 }
   2043 #endif
   2044 
   2045 #if defined(PNG_READ_iTXt_SUPPORTED)
   2046 /* note: this does not correctly handle chunks that are > 64K under DOS */
   2047 void /* PRIVATE */
   2048 png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
   2049 {
   2050    png_textp text_ptr;
   2051    png_charp chunkdata;
   2052    png_charp key, lang, text, lang_key;
   2053    int comp_flag;
   2054    int comp_type = 0;
   2055    int ret;
   2056    png_size_t slength, prefix_len, data_len;
   2057 
   2058    png_debug(1, "in png_handle_iTXt\n");
   2059 
   2060    if (!(png_ptr->mode & PNG_HAVE_IHDR))
   2061       png_error(png_ptr, "Missing IHDR before iTXt");
   2062 
   2063    if (png_ptr->mode & PNG_HAVE_IDAT)
   2064       png_ptr->mode |= PNG_AFTER_IDAT;
   2065 
   2066 #ifdef PNG_MAX_MALLOC_64K
   2067    /* We will no doubt have problems with chunks even half this size, but
   2068       there is no hard and fast rule to tell us where to stop. */
   2069    if (length > (png_uint_32)65535L)
   2070    {
   2071      png_warning(png_ptr,"iTXt chunk too large to fit in memory");
   2072      png_crc_finish(png_ptr, length);
   2073      return;
   2074    }
   2075 #endif
   2076 
   2077    chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
   2078    if (chunkdata == NULL)
   2079    {
   2080      png_warning(png_ptr, "No memory to process iTXt chunk.");
   2081      return;
   2082    }
   2083    slength = (png_size_t)length;
   2084    png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
   2085    if (png_crc_finish(png_ptr, 0))
   2086    {
   2087       png_free(png_ptr, chunkdata);
   2088       return;
   2089    }
   2090 
   2091    chunkdata[slength] = 0x00;
   2092 
   2093    for (lang = chunkdata; *lang; lang++)
   2094       /* empty loop */ ;
   2095    lang++;        /* skip NUL separator */
   2096 
   2097    /* iTXt must have a language tag (possibly empty), two compression bytes,
   2098       translated keyword (possibly empty), and possibly some text after the
   2099       keyword */
   2100 
   2101    if (lang >= chunkdata + slength - 3)
   2102    {
   2103       png_warning(png_ptr, "Truncated iTXt chunk");
   2104       png_free(png_ptr, chunkdata);
   2105       return;
   2106    }
   2107    else
   2108    {
   2109        comp_flag = *lang++;
   2110        comp_type = *lang++;
   2111    }
   2112 
   2113    for (lang_key = lang; *lang_key; lang_key++)
   2114       /* empty loop */ ;
   2115    lang_key++;        /* skip NUL separator */
   2116 
   2117    for (text = lang_key; *text; text++)
   2118       /* empty loop */ ;
   2119    text++;        /* skip NUL separator */
   2120    if (text >= chunkdata + slength)
   2121    {
   2122       png_warning(png_ptr, "Malformed iTXt chunk");
   2123       png_free(png_ptr, chunkdata);
   2124       return;
   2125    }
   2126 
   2127    prefix_len = text - chunkdata;
   2128 
   2129    key=chunkdata;
   2130    if (comp_flag)
   2131        chunkdata = png_decompress_chunk(png_ptr, comp_type, chunkdata,
   2132           (size_t)length, prefix_len, &data_len);
   2133    else
   2134        data_len=png_strlen(chunkdata + prefix_len);
   2135    text_ptr = (png_textp)png_malloc_warn(png_ptr,
   2136       (png_uint_32)png_sizeof(png_text));
   2137    if (text_ptr == NULL)
   2138    {
   2139      png_warning(png_ptr,"Not enough memory to process iTXt chunk.");
   2140      png_free(png_ptr, chunkdata);
   2141      return;
   2142    }
   2143    text_ptr->compression = (int)comp_flag + 1;
   2144    text_ptr->lang_key = chunkdata+(lang_key-key);
   2145    text_ptr->lang = chunkdata+(lang-key);
   2146    text_ptr->itxt_length = data_len;
   2147    text_ptr->text_length = 0;
   2148    text_ptr->key = chunkdata;
   2149    text_ptr->text = chunkdata + prefix_len;
   2150 
   2151    ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
   2152 
   2153    png_free(png_ptr, text_ptr);
   2154    png_free(png_ptr, chunkdata);
   2155    if (ret)
   2156      png_error(png_ptr, "Insufficient memory to store iTXt chunk.");
   2157 }
   2158 #endif
   2159 
   2160 /* This function is called when we haven't found a handler for a
   2161    chunk.  If there isn't a problem with the chunk itself (ie bad
   2162    chunk name, CRC, or a critical chunk), the chunk is silently ignored
   2163    -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
   2164    case it will be saved away to be written out later. */
   2165 void /* PRIVATE */
   2166 png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
   2167 {
   2168    png_uint_32 skip = 0;
   2169 
   2170    png_debug(1, "in png_handle_unknown\n");
   2171 
   2172    if (png_ptr->mode & PNG_HAVE_IDAT)
   2173    {
   2174 #ifdef PNG_USE_LOCAL_ARRAYS
   2175       PNG_CONST PNG_IDAT;
   2176 #endif
   2177       if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))  /* not an IDAT */
   2178          png_ptr->mode |= PNG_AFTER_IDAT;
   2179    }
   2180 
   2181    png_check_chunk_name(png_ptr, png_ptr->chunk_name);
   2182 
   2183    if (!(png_ptr->chunk_name[0] & 0x20))
   2184    {
   2185 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
   2186       if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
   2187            PNG_HANDLE_CHUNK_ALWAYS
   2188 #if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
   2189            && png_ptr->read_user_chunk_fn == NULL
   2190 #endif
   2191         )
   2192 #endif
   2193           png_chunk_error(png_ptr, "unknown critical chunk");
   2194    }
   2195 
   2196 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
   2197    if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) ||
   2198        (png_ptr->read_user_chunk_fn != NULL))
   2199    {
   2200 #ifdef PNG_MAX_MALLOC_64K
   2201        if (length > (png_uint_32)65535L)
   2202        {
   2203            png_warning(png_ptr, "unknown chunk too large to fit in memory");
   2204            skip = length - (png_uint_32)65535L;
   2205            length = (png_uint_32)65535L;
   2206        }
   2207 #endif
   2208        png_strncpy((png_charp)png_ptr->unknown_chunk.name,
   2209 	 (png_charp)png_ptr->chunk_name,
   2210          png_sizeof((png_charp)png_ptr->chunk_name));
   2211        png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length);
   2212        png_ptr->unknown_chunk.size = (png_size_t)length;
   2213        png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length);
   2214 #if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
   2215        if(png_ptr->read_user_chunk_fn != NULL)
   2216        {
   2217           /* callback to user unknown chunk handler */
   2218           int ret;
   2219           ret = (*(png_ptr->read_user_chunk_fn))
   2220             (png_ptr, &png_ptr->unknown_chunk);
   2221           if (ret < 0)
   2222              png_chunk_error(png_ptr, "error in user chunk");
   2223           if (ret == 0)
   2224           {
   2225              if (!(png_ptr->chunk_name[0] & 0x20))
   2226                 if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
   2227                      PNG_HANDLE_CHUNK_ALWAYS)
   2228                    png_chunk_error(png_ptr, "unknown critical chunk");
   2229              png_set_unknown_chunks(png_ptr, info_ptr,
   2230                &png_ptr->unknown_chunk, 1);
   2231           }
   2232        }
   2233 #else
   2234        png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
   2235 #endif
   2236        png_free(png_ptr, png_ptr->unknown_chunk.data);
   2237        png_ptr->unknown_chunk.data = NULL;
   2238    }
   2239    else
   2240 #endif
   2241       skip = length;
   2242 
   2243    png_crc_finish(png_ptr, skip);
   2244 
   2245 #if !defined(PNG_READ_USER_CHUNKS_SUPPORTED)
   2246    info_ptr = info_ptr; /* quiet compiler warnings about unused info_ptr */
   2247 #endif
   2248 }
   2249 
   2250 /* This function is called to verify that a chunk name is valid.
   2251    This function can't have the "critical chunk check" incorporated
   2252    into it, since in the future we will need to be able to call user
   2253    functions to handle unknown critical chunks after we check that
   2254    the chunk name itself is valid. */
   2255 
   2256 #define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
   2257 
   2258 void /* PRIVATE */
   2259 png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
   2260 {
   2261    png_debug(1, "in png_check_chunk_name\n");
   2262    if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
   2263        isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
   2264    {
   2265       png_chunk_error(png_ptr, "invalid chunk type");
   2266    }
   2267 }
   2268 
   2269 /* Combines the row recently read in with the existing pixels in the
   2270    row.  This routine takes care of alpha and transparency if requested.
   2271    This routine also handles the two methods of progressive display
   2272    of interlaced images, depending on the mask value.
   2273    The mask value describes which pixels are to be combined with
   2274    the row.  The pattern always repeats every 8 pixels, so just 8
   2275    bits are needed.  A one indicates the pixel is to be combined,
   2276    a zero indicates the pixel is to be skipped.  This is in addition
   2277    to any alpha or transparency value associated with the pixel.  If
   2278    you want all pixels to be combined, pass 0xff (255) in mask.  */
   2279 
   2280 /* Optimized C version of utilities to read a PNG file
   2281  *
   2282  * Based on code contributed by Nirav Chhatrapati, Intel Corp., 1998.
   2283  * Interface to libpng contributed by Gilles Vollant, 1999.
   2284  * GNU C port by Greg Roelofs, 1999-2001.
   2285  *
   2286  */
   2287 
   2288 #if defined(PNG_OPTIMIZED_CODE_SUPPORTED)
   2289 #if !defined(PNG_HAVE_MMX_COMBINE_ROW)
   2290 
   2291 /*===========================================================================*/
   2292 /*                                                                           */
   2293 /*                       P N G _ C O M B I N E _ R O W                       */
   2294 /*                                                                           */
   2295 /*===========================================================================*/
   2296 
   2297 
   2298 #define BPP2  2
   2299 #define BPP3  3 /* bytes per pixel (a.k.a. pixel_bytes) */
   2300 #define BPP4  4
   2301 #define BPP6  6 /* (defined only to help avoid cut-and-paste errors) */
   2302 #define BPP8  8
   2303 
   2304 /* Combines the row recently read in with the previous row.
   2305    This routine takes care of alpha and transparency if requested.
   2306    This routine also handles the two methods of progressive display
   2307    of interlaced images, depending on the mask value.
   2308    The mask value describes which pixels are to be combined with
   2309    the row.  The pattern always repeats every 8 pixels, so just 8
   2310    bits are needed.  A one indicates the pixel is to be combined; a
   2311    zero indicates the pixel is to be skipped.  This is in addition
   2312    to any alpha or transparency value associated with the pixel.
   2313    If you want all pixels to be combined, pass 0xff (255) in mask. */
   2314 
   2315 /* Use this routine for the x86 platform - it uses a faster MMX routine
   2316    if the machine supports MMX. */
   2317 
   2318 void /* PRIVATE */
   2319 png_combine_row(png_structp png_ptr, png_bytep row, int mask)
   2320 {
   2321 
   2322 #if defined(PNG_USE_LOCAL_ARRAYS)
   2323 static PNG_CONST int FARDATA png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
   2324 static PNG_CONST int FARDATA png_pass_inc[7]   = {8, 8, 4, 4, 2, 2, 1};
   2325 static PNG_CONST int FARDATA png_pass_width[7] = {8, 4, 4, 2, 2, 1, 1};
   2326 #endif
   2327 
   2328    png_debug(1, "in png_combine_row (pngrutil.c OPTIMIZED)\n");
   2329 
   2330    if (mask == 0xff)
   2331    {
   2332       png_debug(2,"mask == 0xff:  doing single png_memcpy()\n");
   2333       png_memcpy(row, png_ptr->row_buf + 1,
   2334        (png_size_t)PNG_ROWBYTES(png_ptr->row_info.pixel_depth,png_ptr->width));
   2335    }
   2336    else   /* (png_combine_row() is never called with mask == 0) */
   2337    {
   2338       switch (png_ptr->row_info.pixel_depth)
   2339       {
   2340          /* most common case:  combining 24-bit RGB */
   2341          case 24:       /* png_ptr->row_info.pixel_depth */
   2342          {
   2343             png_bytep srcptr;
   2344             png_bytep dstptr;
   2345 
   2346             {
   2347                register png_uint_32 i;
   2348                png_uint_32 initial_val = BPP3 * png_pass_start[png_ptr->pass];
   2349                  /* png.c:  png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; */
   2350                register int stride = BPP3 * png_pass_inc[png_ptr->pass];
   2351                  /* png.c:  png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; */
   2352                register int rep_bytes = BPP3 * png_pass_width[png_ptr->pass];
   2353                  /* png.c:  png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; */
   2354                png_uint_32 len = png_ptr->width &~7; /* reduce to mult of 8 */
   2355                int diff = (int) (png_ptr->width & 7); /* amount lost */
   2356                register png_uint_32 final_val = BPP3 * len;   /* GRR bugfix */
   2357 
   2358                srcptr = png_ptr->row_buf + 1 + initial_val;
   2359                dstptr = row + initial_val;
   2360 
   2361                for (i = initial_val; i < final_val; i += stride)
   2362                {
   2363                   png_memcpy(dstptr, srcptr, rep_bytes);
   2364                   srcptr += stride;
   2365                   dstptr += stride;
   2366                }
   2367                if (diff)  /* number of leftover pixels:  3 for pngtest */
   2368                {
   2369                   final_val += diff*BPP3;
   2370                   for (; i < final_val; i += stride)
   2371                   {
   2372                      if (rep_bytes > (int)(final_val-i))
   2373                         rep_bytes = (int)(final_val-i);
   2374                      png_memcpy(dstptr, srcptr, rep_bytes);
   2375                      srcptr += stride;
   2376                      dstptr += stride;
   2377                   }
   2378                }
   2379             } /* end of else (_mmx_supported) */
   2380 
   2381             break;
   2382          }       /* end 24 bpp */
   2383 
   2384          case 32:       /* png_ptr->row_info.pixel_depth */
   2385          {
   2386             png_bytep srcptr;
   2387             png_bytep dstptr;
   2388 
   2389             {
   2390                register png_uint_32 i;
   2391                png_uint_32 initial_val = BPP4 * png_pass_start[png_ptr->pass];
   2392                  /* png.c:  png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; */
   2393                register int stride = BPP4 * png_pass_inc[png_ptr->pass];
   2394                  /* png.c:  png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; */
   2395                register int rep_bytes = BPP4 * png_pass_width[png_ptr->pass];
   2396                  /* png.c:  png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; */
   2397                png_uint_32 len = png_ptr->width &~7; /* reduce to mult of 8 */
   2398                int diff = (int) (png_ptr->width & 7); /* amount lost */
   2399                register png_uint_32 final_val = BPP4 * len;   /* GRR bugfix */
   2400 
   2401                srcptr = png_ptr->row_buf + 1 + initial_val;
   2402                dstptr = row + initial_val;
   2403 
   2404                for (i = initial_val; i < final_val; i += stride)
   2405                {
   2406                   png_memcpy(dstptr, srcptr, rep_bytes);
   2407                   srcptr += stride;
   2408                   dstptr += stride;
   2409                }
   2410                if (diff)  /* number of leftover pixels:  3 for pngtest */
   2411                {
   2412                   final_val += diff*BPP4;
   2413                   for (; i < final_val; i += stride)
   2414                   {
   2415                      if (rep_bytes > (int)(final_val-i))
   2416                         rep_bytes = (int)(final_val-i);
   2417                      png_memcpy(dstptr, srcptr, rep_bytes);
   2418                      srcptr += stride;
   2419                      dstptr += stride;
   2420                   }
   2421                }
   2422             }
   2423 
   2424             break;
   2425          }       /* end 32 bpp */
   2426 
   2427          case 8:        /* png_ptr->row_info.pixel_depth */
   2428          {
   2429             png_bytep srcptr;
   2430             png_bytep dstptr;
   2431             {
   2432                register png_uint_32 i;
   2433                png_uint_32 initial_val = png_pass_start[png_ptr->pass];
   2434                  /* png.c:  png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; */
   2435                register int stride = png_pass_inc[png_ptr->pass];
   2436                  /* png.c:  png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; */
   2437                register int rep_bytes = png_pass_width[png_ptr->pass];
   2438                  /* png.c:  png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; */
   2439                png_uint_32 len = png_ptr->width &~7; /* reduce to mult of 8 */
   2440                int diff = (int) (png_ptr->width & 7); /* amount lost */
   2441                register png_uint_32 final_val = len;  /* GRR bugfix */
   2442 
   2443                srcptr = png_ptr->row_buf + 1 + initial_val;
   2444                dstptr = row + initial_val;
   2445 
   2446                for (i = initial_val; i < final_val; i += stride)
   2447                {
   2448                   png_memcpy(dstptr, srcptr, rep_bytes);
   2449                   srcptr += stride;
   2450                   dstptr += stride;
   2451                }
   2452                if (diff)  /* number of leftover pixels:  3 for pngtest */
   2453                {
   2454                   final_val += diff /* *BPP1 */ ;
   2455                   for (; i < final_val; i += stride)
   2456                   {
   2457                      if (rep_bytes > (int)(final_val-i))
   2458                         rep_bytes = (int)(final_val-i);
   2459                      png_memcpy(dstptr, srcptr, rep_bytes);
   2460                      srcptr += stride;
   2461                      dstptr += stride;
   2462                   }
   2463                }
   2464             }
   2465 
   2466             break;
   2467          }       /* end 8 bpp */
   2468 
   2469          case 1:        /* png_ptr->row_info.pixel_depth */
   2470          {
   2471             png_bytep sp;
   2472             png_bytep dp;
   2473             int s_inc, s_start, s_end;
   2474             int m;
   2475             int shift;
   2476             png_uint_32 i;
   2477 
   2478             sp = png_ptr->row_buf + 1;
   2479             dp = row;
   2480             m = 0x80;
   2481 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
   2482             if (png_ptr->transformations & PNG_PACKSWAP)
   2483             {
   2484                 s_start = 0;
   2485                 s_end = 7;
   2486                 s_inc = 1;
   2487             }
   2488             else
   2489 #endif
   2490             {
   2491                 s_start = 7;
   2492                 s_end = 0;
   2493                 s_inc = -1;
   2494             }
   2495 
   2496             shift = s_start;
   2497 
   2498             for (i = 0; i < png_ptr->width; i++)
   2499             {
   2500                if (m & mask)
   2501                {
   2502                   int value;
   2503 
   2504                   value = (*sp >> shift) & 0x1;
   2505                   *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
   2506                   *dp |= (png_byte)(value << shift);
   2507                }
   2508 
   2509                if (shift == s_end)
   2510                {
   2511                   shift = s_start;
   2512                   sp++;
   2513                   dp++;
   2514                }
   2515                else
   2516                   shift += s_inc;
   2517 
   2518                if (m == 1)
   2519                   m = 0x80;
   2520                else
   2521                   m >>= 1;
   2522             }
   2523             break;
   2524          }       /* end 1 bpp */
   2525 
   2526          case 2:        /* png_ptr->row_info.pixel_depth */
   2527          {
   2528             png_bytep sp;
   2529             png_bytep dp;
   2530             int s_start, s_end, s_inc;
   2531             int m;
   2532             int shift;
   2533             png_uint_32 i;
   2534             int value;
   2535 
   2536             sp = png_ptr->row_buf + 1;
   2537             dp = row;
   2538             m = 0x80;
   2539 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
   2540             if (png_ptr->transformations & PNG_PACKSWAP)
   2541             {
   2542                s_start = 0;
   2543                s_end = 6;
   2544                s_inc = 2;
   2545             }
   2546             else
   2547 #endif
   2548             {
   2549                s_start = 6;
   2550                s_end = 0;
   2551                s_inc = -2;
   2552             }
   2553 
   2554             shift = s_start;
   2555 
   2556             for (i = 0; i < png_ptr->width; i++)
   2557             {
   2558                if (m & mask)
   2559                {
   2560                   value = (*sp >> shift) & 0x3;
   2561                   *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
   2562                   *dp |= (png_byte)(value << shift);
   2563                }
   2564 
   2565                if (shift == s_end)
   2566                {
   2567                   shift = s_start;
   2568                   sp++;
   2569                   dp++;
   2570                }
   2571                else
   2572                   shift += s_inc;
   2573                if (m == 1)
   2574                   m = 0x80;
   2575                else
   2576                   m >>= 1;
   2577             }
   2578             break;
   2579          }       /* end 2 bpp */
   2580 
   2581          case 4:        /* png_ptr->row_info.pixel_depth */
   2582          {
   2583             png_bytep sp;
   2584             png_bytep dp;
   2585             int s_start, s_end, s_inc;
   2586             int m;
   2587             int shift;
   2588             png_uint_32 i;
   2589             int value;
   2590 
   2591             sp = png_ptr->row_buf + 1;
   2592             dp = row;
   2593             m = 0x80;
   2594 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
   2595             if (png_ptr->transformations & PNG_PACKSWAP)
   2596             {
   2597                s_start = 0;
   2598                s_end = 4;
   2599                s_inc = 4;
   2600             }
   2601             else
   2602 #endif
   2603             {
   2604                s_start = 4;
   2605                s_end = 0;
   2606                s_inc = -4;
   2607             }
   2608             shift = s_start;
   2609 
   2610             for (i = 0; i < png_ptr->width; i++)
   2611             {
   2612                if (m & mask)
   2613                {
   2614                   value = (*sp >> shift) & 0xf;
   2615                   *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
   2616                   *dp |= (png_byte)(value << shift);
   2617                }
   2618 
   2619                if (shift == s_end)
   2620                {
   2621                   shift = s_start;
   2622                   sp++;
   2623                   dp++;
   2624                }
   2625                else
   2626                   shift += s_inc;
   2627                if (m == 1)
   2628                   m = 0x80;
   2629                else
   2630                   m >>= 1;
   2631             }
   2632             break;
   2633          }       /* end 4 bpp */
   2634 
   2635          case 16:       /* png_ptr->row_info.pixel_depth */
   2636          {
   2637             png_bytep srcptr;
   2638             png_bytep dstptr;
   2639 
   2640             {
   2641                register png_uint_32 i;
   2642                png_uint_32 initial_val = BPP2 * png_pass_start[png_ptr->pass];
   2643                  /* png.c:  png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; */
   2644                register int stride = BPP2 * png_pass_inc[png_ptr->pass];
   2645                  /* png.c:  png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; */
   2646                register int rep_bytes = BPP2 * png_pass_width[png_ptr->pass];
   2647                  /* png.c:  png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; */
   2648                png_uint_32 len = png_ptr->width &~7;  /* reduce to mult of 8 */
   2649                int diff = (int) (png_ptr->width & 7); /* amount lost */
   2650                register png_uint_32 final_val = BPP2 * len;   /* GRR bugfix */
   2651 
   2652                srcptr = png_ptr->row_buf + 1 + initial_val;
   2653                dstptr = row + initial_val;
   2654 
   2655                for (i = initial_val; i < final_val; i += stride)
   2656                {
   2657                   png_memcpy(dstptr, srcptr, rep_bytes);
   2658                   srcptr += stride;
   2659                   dstptr += stride;
   2660                }
   2661                if (diff)  /* number of leftover pixels:  3 for pngtest */
   2662                {
   2663                   final_val += diff*BPP2;
   2664                   for (; i < final_val; i += stride)
   2665                   {
   2666                      if (rep_bytes > (int)(final_val-i))
   2667                         rep_bytes = (int)(final_val-i);
   2668                      png_memcpy(dstptr, srcptr, rep_bytes);
   2669                      srcptr += stride;
   2670                      dstptr += stride;
   2671                   }
   2672                }
   2673             } /* end of else (_mmx_supported) */
   2674 
   2675             break;
   2676          }       /* end 16 bpp */
   2677 
   2678 
   2679 
   2680          case 48:       /* png_ptr->row_info.pixel_depth */
   2681          {
   2682             png_bytep srcptr;
   2683             png_bytep dstptr;
   2684             {
   2685                register png_uint_32 i;
   2686                png_uint_32 initial_val = BPP6 * png_pass_start[png_ptr->pass];
   2687                  /* png.c:  png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; */
   2688                register int stride = BPP6 * png_pass_inc[png_ptr->pass];
   2689                  /* png.c:  png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; */
   2690                register int rep_bytes = BPP6 * png_pass_width[png_ptr->pass];
   2691                  /* png.c:  png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; */
   2692                png_uint_32 len = png_ptr->width &~7; /* reduce to mult of 8 */
   2693                int diff = (int) (png_ptr->width & 7); /* amount lost */
   2694                register png_uint_32 final_val = BPP6 * len;   /* GRR bugfix */
   2695 
   2696                srcptr = png_ptr->row_buf + 1 + initial_val;
   2697                dstptr = row + initial_val;
   2698 
   2699                for (i = initial_val; i < final_val; i += stride)
   2700                {
   2701                   png_memcpy(dstptr, srcptr, rep_bytes);
   2702                   srcptr += stride;
   2703                   dstptr += stride;
   2704                }
   2705                if (diff)  /* number of leftover pixels:  3 for pngtest */
   2706                {
   2707                   final_val += diff*BPP6;
   2708                   for (; i < final_val; i += stride)
   2709                   {
   2710                      if (rep_bytes > (int)(final_val-i))
   2711                         rep_bytes = (int)(final_val-i);
   2712                      png_memcpy(dstptr, srcptr, rep_bytes);
   2713                      srcptr += stride;
   2714                      dstptr += stride;
   2715                   }
   2716                }
   2717             }
   2718             break;
   2719          }       /* end 48 bpp */
   2720 
   2721          case 64:       /* png_ptr->row_info.pixel_depth */
   2722          {
   2723             png_bytep srcptr;
   2724             png_bytep dstptr;
   2725             register png_uint_32 i;
   2726             png_uint_32 initial_val = BPP8 * png_pass_start[png_ptr->pass];
   2727               /* png.c:  png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; */
   2728             register int stride = BPP8 * png_pass_inc[png_ptr->pass];
   2729               /* png.c:  png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; */
   2730             register int rep_bytes = BPP8 * png_pass_width[png_ptr->pass];
   2731               /* png.c:  png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; */
   2732             png_uint_32 len = png_ptr->width &~7;  /* reduce to mult of 8 */
   2733             int diff = (int) (png_ptr->width & 7); /* amount lost */
   2734             register png_uint_32 final_val = BPP8 * len;   /* GRR bugfix */
   2735 
   2736             srcptr = png_ptr->row_buf + 1 + initial_val;
   2737             dstptr = row + initial_val;
   2738 
   2739             for (i = initial_val; i < final_val; i += stride)
   2740             {
   2741                png_memcpy(dstptr, srcptr, rep_bytes);
   2742                srcptr += stride;
   2743                dstptr += stride;
   2744             }
   2745             if (diff)  /* number of leftover pixels:  3 for pngtest */
   2746             {
   2747                final_val += diff*BPP8;
   2748                for (; i < final_val; i += stride)
   2749                {
   2750                   if (rep_bytes > (int)(final_val-i))
   2751                      rep_bytes = (int)(final_val-i);
   2752                   png_memcpy(dstptr, srcptr, rep_bytes);
   2753                   srcptr += stride;
   2754                   dstptr += stride;
   2755                }
   2756             }
   2757 
   2758             break;
   2759          }       /* end 64 bpp */
   2760 
   2761          default: /* png_ptr->row_info.pixel_depth != 1,2,4,8,16,24,32,48,64 */
   2762          {
   2763             /* this should never happen */
   2764             png_warning(png_ptr, "Invalid row_info.pixel_depth in pngrutil");
   2765             break;
   2766          }
   2767       } /* end switch (png_ptr->row_info.pixel_depth) */
   2768 
   2769    } /* end if (non-trivial mask) */
   2770 
   2771 } /* end png_combine_row() */
   2772 #endif /* PNG_HAVE_MMX_COMBINE_ROW */
   2773 
   2774 
   2775 
   2776 /*===========================================================================*/
   2777 /*                                                                           */
   2778 /*                 P N G _ D O _ R E A D _ I N T E R L A C E                 */
   2779 /*                                                                           */
   2780 /*===========================================================================*/
   2781 
   2782 #if defined(PNG_READ_INTERLACING_SUPPORTED)
   2783 #if !defined(PNG_HAVE_MMX_READ_INTERLACE)
   2784 
   2785 /* png_do_read_interlace() is called after any 16-bit to 8-bit conversion
   2786  * has taken place.  [GRR: what other steps come before and/or after?]
   2787  */
   2788 
   2789 void /* PRIVATE */
   2790 png_do_read_interlace(png_structp png_ptr)
   2791 {
   2792 #if defined(PNG_USE_LOCAL_ARRAYS)
   2793 static PNG_CONST int FARDATA png_pass_inc[7]   = {8, 8, 4, 4, 2, 2, 1};
   2794 #endif
   2795    png_row_infop row_info = &(png_ptr->row_info);
   2796    png_bytep row = png_ptr->row_buf + 1;
   2797    int pass = png_ptr->pass;
   2798 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
   2799    png_uint_32 transformations = png_ptr->transformations;
   2800 #endif
   2801    png_debug(1,"in png_do_read_interlace (pngrutil.c OPTIMIZED)\n");
   2802 
   2803    if (row != NULL && row_info != NULL)
   2804    {
   2805       png_uint_32 final_width;
   2806 
   2807       final_width = row_info->width * png_pass_inc[pass];
   2808 
   2809       switch (row_info->pixel_depth)
   2810       {
   2811          case 1:
   2812          {
   2813             png_bytep sp, dp;
   2814             int sshift, dshift;
   2815             int s_start, s_end, s_inc;
   2816             png_byte v;
   2817             png_uint_32 i;
   2818             int j;
   2819 
   2820             sp = row + (png_size_t)((row_info->width - 1) >> 3);
   2821             dp = row + (png_size_t)((final_width - 1) >> 3);
   2822 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
   2823             if (transformations & PNG_PACKSWAP)
   2824             {
   2825                sshift = (int)((row_info->width + 7) & 7);
   2826                dshift = (int)((final_width + 7) & 7);
   2827                s_start = 7;
   2828                s_end = 0;
   2829                s_inc = -1;
   2830             }
   2831             else
   2832 #endif
   2833             {
   2834                sshift = 7 - (int)((row_info->width + 7) & 7);
   2835                dshift = 7 - (int)((final_width + 7) & 7);
   2836                s_start = 0;
   2837                s_end = 7;
   2838                s_inc = 1;
   2839             }
   2840 
   2841             for (i = row_info->width; i; i--)
   2842             {
   2843                v = (png_byte)((*sp >> sshift) & 0x1);
   2844                for (j = 0; j < png_pass_inc[pass]; j++)
   2845                {
   2846                   *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
   2847                   *dp |= (png_byte)(v << dshift);
   2848                   if (dshift == s_end)
   2849                   {
   2850                      dshift = s_start;
   2851                      dp--;
   2852                   }
   2853                   else
   2854                      dshift += s_inc;
   2855                }
   2856                if (sshift == s_end)
   2857                {
   2858                   sshift = s_start;
   2859                   sp--;
   2860                }
   2861                else
   2862                   sshift += s_inc;
   2863             }
   2864             break;
   2865          }
   2866 
   2867          case 2:
   2868          {
   2869             png_bytep sp, dp;
   2870             int sshift, dshift;
   2871             int s_start, s_end, s_inc;
   2872             png_uint_32 i;
   2873 
   2874             sp = row + (png_size_t)((row_info->width - 1) >> 2);
   2875             dp = row + (png_size_t)((final_width - 1) >> 2);
   2876 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
   2877             if (transformations & PNG_PACKSWAP)
   2878             {
   2879                sshift = (png_size_t)(((row_info->width + 3) & 3) << 1);
   2880                dshift = (png_size_t)(((final_width + 3) & 3) << 1);
   2881                s_start = 6;
   2882                s_end = 0;
   2883                s_inc = -2;
   2884             }
   2885             else
   2886 #endif
   2887             {
   2888                sshift = (png_size_t)((3 - ((row_info->width + 3) & 3)) << 1);
   2889                dshift = (png_size_t)((3 - ((final_width + 3) & 3)) << 1);
   2890                s_start = 0;
   2891                s_end = 6;
   2892                s_inc = 2;
   2893             }
   2894 
   2895             for (i = row_info->width; i; i--)
   2896             {
   2897                png_byte v;
   2898                int j;
   2899 
   2900                v = (png_byte)((*sp >> sshift) & 0x3);
   2901                for (j = 0; j < png_pass_inc[pass]; j++)
   2902                {
   2903                   *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
   2904                   *dp |= (png_byte)(v << dshift);
   2905                   if (dshift == s_end)
   2906                   {
   2907                      dshift = s_start;
   2908                      dp--;
   2909                   }
   2910                   else
   2911                      dshift += s_inc;
   2912                }
   2913                if (sshift == s_end)
   2914                {
   2915                   sshift = s_start;
   2916                   sp--;
   2917                }
   2918                else
   2919                   sshift += s_inc;
   2920             }
   2921             break;
   2922          }
   2923 
   2924          case 4:
   2925          {
   2926             png_bytep sp, dp;
   2927             int sshift, dshift;
   2928             int s_start, s_end, s_inc;
   2929             png_uint_32 i;
   2930 
   2931             sp = row + (png_size_t)((row_info->width - 1) >> 1);
   2932             dp = row + (png_size_t)((final_width - 1) >> 1);
   2933 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
   2934             if (transformations & PNG_PACKSWAP)
   2935             {
   2936                sshift = (png_size_t)(((row_info->width + 1) & 1) << 2);
   2937                dshift = (png_size_t)(((final_width + 1) & 1) << 2);
   2938                s_start = 4;
   2939                s_end = 0;
   2940                s_inc = -4;
   2941             }
   2942             else
   2943 #endif
   2944             {
   2945                sshift = (png_size_t)((1 - ((row_info->width + 1) & 1)) << 2);
   2946                dshift = (png_size_t)((1 - ((final_width + 1) & 1)) << 2);
   2947                s_start = 0;
   2948                s_end = 4;
   2949                s_inc = 4;
   2950             }
   2951 
   2952             for (i = row_info->width; i; i--)
   2953             {
   2954                png_byte v;
   2955                int j;
   2956 
   2957                v = (png_byte)((*sp >> sshift) & 0xf);
   2958                for (j = 0; j < png_pass_inc[pass]; j++)
   2959                {
   2960                   *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
   2961                   *dp |= (png_byte)(v << dshift);
   2962                   if (dshift == s_end)
   2963                   {
   2964                      dshift = s_start;
   2965                      dp--;
   2966                   }
   2967                   else
   2968                      dshift += s_inc;
   2969                }
   2970                if (sshift == s_end)
   2971                {
   2972                   sshift = s_start;
   2973                   sp--;
   2974                }
   2975                else
   2976                   sshift += s_inc;
   2977             }
   2978             break;
   2979          }
   2980 
   2981        /*====================================================================*/
   2982 
   2983          default: /* 8-bit or larger (this is where the routine is modified) */
   2984          {
   2985             png_bytep sptr, dp;
   2986             png_uint_32 i;
   2987             png_size_t pixel_bytes;
   2988             int width = (int)row_info->width;
   2989 
   2990             pixel_bytes = (row_info->pixel_depth >> 3);
   2991 
   2992             /* point sptr at the last pixel in the pre-expanded row: */
   2993             sptr = row + (width - 1) * pixel_bytes;
   2994 
   2995             /* point dp at the last pixel position in the expanded row: */
   2996             dp = row + (final_width - 1) * pixel_bytes;
   2997 
   2998             /* MMX not supported:  use modified C code - takes advantage
   2999              *   of inlining of png_memcpy for a constant */
   3000             /* GRR 19991007:  does it?  or should pixel_bytes in each
   3001              *   block be replaced with immediate value (e.g., 1)? */
   3002             /* GRR 19991017:  replaced with constants in each case */
   3003             {
   3004                if (pixel_bytes == 1)
   3005                {
   3006                   for (i = width; i; i--)
   3007                   {
   3008                      int j;
   3009                      for (j = 0; j < png_pass_inc[pass]; j++)
   3010                      {
   3011                         *dp-- = *sptr;
   3012                      }
   3013                      --sptr;
   3014                   }
   3015                }
   3016                else if (pixel_bytes == 3)
   3017                {
   3018                   for (i = width; i; i--)
   3019                   {
   3020                      png_byte v[8];
   3021                      int j;
   3022                      png_memcpy(v, sptr, 3);
   3023                      for (j = 0; j < png_pass_inc[pass]; j++)
   3024                      {
   3025                         png_memcpy(dp, v, 3);
   3026                         dp -= 3;
   3027                      }
   3028                      sptr -= 3;
   3029                   }
   3030                }
   3031                else if (pixel_bytes == 2)
   3032                {
   3033                   for (i = width; i; i--)
   3034                   {
   3035                      png_byte v[8];
   3036                      int j;
   3037                      png_memcpy(v, sptr, 2);
   3038                      for (j = 0; j < png_pass_inc[pass]; j++)
   3039                      {
   3040                         png_memcpy(dp, v, 2);
   3041                         dp -= 2;
   3042                      }
   3043                      sptr -= 2;
   3044                   }
   3045                }
   3046                else if (pixel_bytes == 4)
   3047                {
   3048                   for (i = width; i; i--)
   3049                   {
   3050                      png_byte v[8];
   3051                      int j;
   3052                      png_memcpy(v, sptr, 4);
   3053                      for (j = 0; j < png_pass_inc[pass]; j++)
   3054                      {
   3055 #if defined(PNG_DEBUG) && defined(PNG_1_0_X)
   3056                         if (dp < row || dp+3 > row+png_ptr->row_buf_size)
   3057                         {
   3058                            printf("dp out of bounds: row=%d, dp=%d, rp=%d\n",
   3059                              row, dp, row+png_ptr->row_buf_size);
   3060                            printf("row_buf=%d\n",png_ptr->row_buf_size);
   3061                         }
   3062 #endif
   3063                         png_memcpy(dp, v, 4);
   3064                         dp -= 4;
   3065                      }
   3066                      sptr -= 4;
   3067                   }
   3068                }
   3069                else if (pixel_bytes == 6)
   3070                {
   3071                   for (i = width; i; i--)
   3072                   {
   3073                      png_byte v[8];
   3074                      int j;
   3075                      png_memcpy(v, sptr, 6);
   3076                      for (j = 0; j < png_pass_inc[pass]; j++)
   3077                      {
   3078                         png_memcpy(dp, v, 6);
   3079                         dp -= 6;
   3080                      }
   3081                      sptr -= 6;
   3082                   }
   3083                }
   3084                else if (pixel_bytes == 8)
   3085                {
   3086                   for (i = width; i; i--)
   3087                   {
   3088                      png_byte v[8];
   3089                      int j;
   3090                      png_memcpy(v, sptr, 8);
   3091                      for (j = 0; j < png_pass_inc[pass]; j++)
   3092                      {
   3093                         png_memcpy(dp, v, 8);
   3094                         dp -= 8;
   3095                      }
   3096                      sptr -= 8;
   3097                   }
   3098                }
   3099                else     /* GRR:  should never be reached */
   3100                {
   3101                   for (i = width; i; i--)
   3102                   {
   3103                      png_byte v[8];
   3104                      int j;
   3105                      png_memcpy(v, sptr, pixel_bytes);
   3106                      for (j = 0; j < png_pass_inc[pass]; j++)
   3107                      {
   3108                         png_memcpy(dp, v, pixel_bytes);
   3109                         dp -= pixel_bytes;
   3110                      }
   3111                      sptr -= pixel_bytes;
   3112                   }
   3113                }
   3114 
   3115             }
   3116             break;
   3117          }
   3118       } /* end switch (row_info->pixel_depth) */
   3119 
   3120       row_info->width = final_width;
   3121 
   3122       row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,final_width);
   3123    }
   3124 
   3125 } /* end png_do_read_interlace() */
   3126 
   3127 #endif /* PNG_HAVE_MMX_READ_INTERLACE */
   3128 #endif /* PNG_READ_INTERLACING_SUPPORTED */
   3129 
   3130 
   3131 
   3132 #if !defined(PNG_HAVE_MMX_READ_FILTER_ROW)
   3133 /*===========================================================================*/
   3134 /*                                                                           */
   3135 /*                   P N G _ R E A D _ F I L T E R _ R O W                   */
   3136 /*                                                                           */
   3137 /*===========================================================================*/
   3138 
   3139 
   3140 /* Optimized png_read_filter_row routines */
   3141 
   3142 void /* PRIVATE */
   3143 png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep
   3144    row, png_bytep prev_row, int filter)
   3145 {
   3146 #if defined(PNG_DEBUG)
   3147    char filnm[10];
   3148 #endif
   3149 
   3150 
   3151 #if defined(PNG_DEBUG)
   3152    png_debug(1, "in png_read_filter_row (pngrutil.c OPTIMIZED)\n");
   3153    switch (filter)
   3154    {
   3155       case 0:
   3156          png_snprintf(filnm, 10, "none");
   3157          break;
   3158 
   3159       case 1:
   3160          png_snprintf(filnm, 10, "sub-%s",
   3161              "x86");
   3162          break;
   3163 
   3164       case 2:
   3165          png_snprintf(filnm, 10, "up-%s",
   3166              "x86");
   3167          break;
   3168 
   3169       case 3:
   3170          png_snprintf(filnm, 10, "avg-%s",
   3171              "x86");
   3172          break;
   3173 
   3174       case 4:
   3175          png_snprintf(filnm, 10, "Paeth-%s",
   3176              "x86");
   3177          break;
   3178 
   3179       default:
   3180          png_snprintf(filnm, 10, "unknown");
   3181          break;
   3182    }
   3183    png_debug2(0, "row_number=%5ld, %10s, ", png_ptr->row_number, filnm);
   3184    png_debug1(0, "row=0x%08lx, ", (unsigned long)row);
   3185    png_debug2(0, "pixdepth=%2d, bytes=%d, ", (int)row_info->pixel_depth,
   3186       (int)((row_info->pixel_depth + 7) >> 3));
   3187    png_debug1(0,"rowbytes=%8ld\n", row_info->rowbytes);
   3188 #endif /* PNG_DEBUG */
   3189 
   3190    switch (filter)
   3191    {
   3192       case PNG_FILTER_VALUE_NONE:
   3193          break;
   3194 
   3195       case PNG_FILTER_VALUE_SUB:
   3196          {
   3197             png_uint_32 i;
   3198             png_uint_32 istop = row_info->rowbytes;
   3199             png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
   3200             png_bytep rp = row + bpp;
   3201             png_bytep lp = row;
   3202 
   3203             for (i = bpp; i < istop; i++)
   3204             {
   3205                *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
   3206                rp++;
   3207             }
   3208          }
   3209          break;
   3210 
   3211       case PNG_FILTER_VALUE_UP:
   3212          {
   3213             png_uint_32 i;
   3214             png_uint_32 istop = row_info->rowbytes;
   3215             png_bytep rp = row;
   3216             png_bytep pp = prev_row;
   3217 
   3218             for (i = 0; i < istop; ++i)
   3219             {
   3220                *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
   3221                rp++;
   3222             }
   3223          }
   3224          break;
   3225 
   3226       case PNG_FILTER_VALUE_AVG:
   3227          {
   3228             png_uint_32 i;
   3229             png_bytep rp = row;
   3230             png_bytep pp = prev_row;
   3231             png_bytep lp = row;
   3232             png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
   3233             png_uint_32 istop = row_info->rowbytes - bpp;
   3234 
   3235             for (i = 0; i < bpp; i++)
   3236             {
   3237                *rp = (png_byte)(((int)(*rp) +
   3238                   ((int)(*pp++) >> 1)) & 0xff);
   3239                rp++;
   3240             }
   3241 
   3242             for (i = 0; i < istop; i++)
   3243             {
   3244                *rp = (png_byte)(((int)(*rp) +
   3245                   ((int)(*pp++ + *lp++) >> 1)) & 0xff);
   3246                rp++;
   3247             }
   3248          }
   3249          break;
   3250 
   3251       case PNG_FILTER_VALUE_PAETH:
   3252          {
   3253             png_uint_32 i;
   3254             png_bytep rp = row;
   3255             png_bytep pp = prev_row;
   3256             png_bytep lp = row;
   3257             png_bytep cp = prev_row;
   3258             png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
   3259             png_uint_32 istop = row_info->rowbytes - bpp;
   3260 
   3261             for (i = 0; i < bpp; i++)
   3262             {
   3263                *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
   3264                rp++;
   3265             }
   3266 
   3267             for (i = 0; i < istop; i++)   /* use leftover rp,pp */
   3268             {
   3269                int a, b, c, pa, pb, pc, p;
   3270 
   3271                a = *lp++;
   3272                b = *pp++;
   3273                c = *cp++;
   3274 
   3275                p = b - c;
   3276                pc = a - c;
   3277 
   3278 #if defined(PNG_USE_ABS)
   3279                pa = abs(p);
   3280                pb = abs(pc);
   3281                pc = abs(p + pc);
   3282 #else
   3283                pa = p < 0 ? -p : p;
   3284                pb = pc < 0 ? -pc : pc;
   3285                pc = (p + pc) < 0 ? -(p + pc) : p + pc;
   3286 #endif
   3287 
   3288                /*
   3289                   if (pa <= pb && pa <= pc)
   3290                      p = a;
   3291                   else if (pb <= pc)
   3292                      p = b;
   3293                   else
   3294                      p = c;
   3295                 */
   3296 
   3297                p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c;
   3298 
   3299                *rp = (png_byte)(((int)(*rp) + p) & 0xff);
   3300                rp++;
   3301             }
   3302          }
   3303          break;
   3304 
   3305       default:
   3306          png_warning(png_ptr, "Ignoring bad row-filter type");
   3307          *row=0;
   3308          break;
   3309    }
   3310 }
   3311 
   3312 #endif /* PNG_HAVE_MMX_READ_FILTER_ROW */
   3313 #endif /* PNG_OPTIMIZED_CODE_SUPPORTED */
   3314 
   3315 #if !defined(PNG_USE_PNGGCCRD) && !defined(PNG_USE_PNGVCRD)
   3316 #if !defined(PNG_OPTIMIZED_CODE_SUPPORTED)
   3317 /* Use the unoptimized original C code.  This might be removed from a future
   3318  * version of libpng if testing proves it to be worthless. */
   3319 void /* PRIVATE */
   3320 png_combine_row(png_structp png_ptr, png_bytep row, int mask)
   3321 {
   3322    png_debug(1,"in png_combine_row NOT OPTIMIZED\n");
   3323    if (mask == 0xff)
   3324    {
   3325       png_memcpy(row, png_ptr->row_buf + 1,
   3326          PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width));
   3327    }
   3328    else
   3329    {
   3330       switch (png_ptr->row_info.pixel_depth)
   3331       {
   3332          case 1:
   3333          {
   3334             png_bytep sp = png_ptr->row_buf + 1;
   3335             png_bytep dp = row;
   3336             int s_inc, s_start, s_end;
   3337             int m = 0x80;
   3338             int shift;
   3339             png_uint_32 i;
   3340             png_uint_32 row_width = png_ptr->width;
   3341 
   3342 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
   3343             if (png_ptr->transformations & PNG_PACKSWAP)
   3344             {
   3345                 s_start = 0;
   3346                 s_end = 7;
   3347                 s_inc = 1;
   3348             }
   3349             else
   3350 #endif
   3351             {
   3352                 s_start = 7;
   3353                 s_end = 0;
   3354                 s_inc = -1;
   3355             }
   3356 
   3357             shift = s_start;
   3358 
   3359             for (i = 0; i < row_width; i++)
   3360             {
   3361                if (m & mask)
   3362                {
   3363                   int value;
   3364 
   3365                   value = (*sp >> shift) & 0x01;
   3366                   *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
   3367                   *dp |= (png_byte)(value << shift);
   3368                }
   3369 
   3370                if (shift == s_end)
   3371                {
   3372                   shift = s_start;
   3373                   sp++;
   3374                   dp++;
   3375                }
   3376                else
   3377                   shift += s_inc;
   3378 
   3379                if (m == 1)
   3380                   m = 0x80;
   3381                else
   3382                   m >>= 1;
   3383             }
   3384             break;
   3385          }
   3386          case 2:
   3387          {
   3388             png_bytep sp = png_ptr->row_buf + 1;
   3389             png_bytep dp = row;
   3390             int s_start, s_end, s_inc;
   3391             int m = 0x80;
   3392             int shift;
   3393             png_uint_32 i;
   3394             png_uint_32 row_width = png_ptr->width;
   3395             int value;
   3396 
   3397 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
   3398             if (png_ptr->transformations & PNG_PACKSWAP)
   3399             {
   3400                s_start = 0;
   3401                s_end = 6;
   3402                s_inc = 2;
   3403             }
   3404             else
   3405 #endif
   3406             {
   3407                s_start = 6;
   3408                s_end = 0;
   3409                s_inc = -2;
   3410             }
   3411 
   3412             shift = s_start;
   3413 
   3414             for (i = 0; i < row_width; i++)
   3415             {
   3416                if (m & mask)
   3417                {
   3418                   value = (*sp >> shift) & 0x03;
   3419                   *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
   3420                   *dp |= (png_byte)(value << shift);
   3421                }
   3422 
   3423                if (shift == s_end)
   3424                {
   3425                   shift = s_start;
   3426                   sp++;
   3427                   dp++;
   3428                }
   3429                else
   3430                   shift += s_inc;
   3431                if (m == 1)
   3432                   m = 0x80;
   3433                else
   3434                   m >>= 1;
   3435             }
   3436             break;
   3437          }
   3438          case 4:
   3439          {
   3440             png_bytep sp = png_ptr->row_buf + 1;
   3441             png_bytep dp = row;
   3442             int s_start, s_end, s_inc;
   3443             int m = 0x80;
   3444             int shift;
   3445             png_uint_32 i;
   3446             png_uint_32 row_width = png_ptr->width;
   3447             int value;
   3448 
   3449 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
   3450             if (png_ptr->transformations & PNG_PACKSWAP)
   3451             {
   3452                s_start = 0;
   3453                s_end = 4;
   3454                s_inc = 4;
   3455             }
   3456             else
   3457 #endif
   3458             {
   3459                s_start = 4;
   3460                s_end = 0;
   3461                s_inc = -4;
   3462             }
   3463             shift = s_start;
   3464 
   3465             for (i = 0; i < row_width; i++)
   3466             {
   3467                if (m & mask)
   3468                {
   3469                   value = (*sp >> shift) & 0xf;
   3470                   *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
   3471                   *dp |= (png_byte)(value << shift);
   3472                }
   3473 
   3474                if (shift == s_end)
   3475                {
   3476                   shift = s_start;
   3477                   sp++;
   3478                   dp++;
   3479                }
   3480                else
   3481                   shift += s_inc;
   3482                if (m == 1)
   3483                   m = 0x80;
   3484                else
   3485                   m >>= 1;
   3486             }
   3487             break;
   3488          }
   3489          default:
   3490          {
   3491             png_bytep sp = png_ptr->row_buf + 1;
   3492             png_bytep dp = row;
   3493             png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
   3494             png_uint_32 i;
   3495             png_uint_32 row_width = png_ptr->width;
   3496             png_byte m = 0x80;
   3497 
   3498 
   3499             for (i = 0; i < row_width; i++)
   3500             {
   3501                if (m & mask)
   3502                {
   3503                   png_memcpy(dp, sp, pixel_bytes);
   3504                }
   3505 
   3506                sp += pixel_bytes;
   3507                dp += pixel_bytes;
   3508 
   3509                if (m == 1)
   3510                   m = 0x80;
   3511                else
   3512                   m >>= 1;
   3513             }
   3514             break;
   3515          }
   3516       }
   3517    }
   3518 }
   3519 
   3520 #ifdef PNG_READ_INTERLACING_SUPPORTED
   3521 /* OLD pre-1.0.9 interface:
   3522 void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
   3523    png_uint_32 transformations)
   3524  */
   3525 void /* PRIVATE */
   3526 png_do_read_interlace(png_structp png_ptr)
   3527 {
   3528    png_row_infop row_info = &(png_ptr->row_info);
   3529    png_bytep row = png_ptr->row_buf + 1;
   3530    int pass = png_ptr->pass;
   3531    png_uint_32 transformations = png_ptr->transformations;
   3532 #ifdef PNG_USE_LOCAL_ARRAYS
   3533    /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
   3534    /* offset to next interlace block */
   3535    PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
   3536 #endif
   3537 
   3538    png_debug(1,"in png_do_read_interlace (pngrutil.c NOT OPTIMIZED)\n");
   3539    if (row != NULL && row_info != NULL)
   3540    {
   3541       png_uint_32 final_width;
   3542 
   3543       final_width = row_info->width * png_pass_inc[pass];
   3544 
   3545       switch (row_info->pixel_depth)
   3546       {
   3547          case 1:
   3548          {
   3549             png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
   3550             png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
   3551             int sshift, dshift;
   3552             int s_start, s_end, s_inc;
   3553             int jstop = png_pass_inc[pass];
   3554             png_byte v;
   3555             png_uint_32 i;
   3556             int j;
   3557 
   3558 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
   3559             if (transformations & PNG_PACKSWAP)
   3560             {
   3561                 sshift = (int)((row_info->width + 7) & 0x07);
   3562                 dshift = (int)((final_width + 7) & 0x07);
   3563                 s_start = 7;
   3564                 s_end = 0;
   3565                 s_inc = -1;
   3566             }
   3567             else
   3568 #endif
   3569             {
   3570                 sshift = 7 - (int)((row_info->width + 7) & 0x07);
   3571                 dshift = 7 - (int)((final_width + 7) & 0x07);
   3572                 s_start = 0;
   3573                 s_end = 7;
   3574                 s_inc = 1;
   3575             }
   3576 
   3577             for (i = 0; i < row_info->width; i++)
   3578             {
   3579                v = (png_byte)((*sp >> sshift) & 0x01);
   3580                for (j = 0; j < jstop; j++)
   3581                {
   3582                   *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
   3583                   *dp |= (png_byte)(v << dshift);
   3584                   if (dshift == s_end)
   3585                   {
   3586                      dshift = s_start;
   3587                      dp--;
   3588                   }
   3589                   else
   3590                      dshift += s_inc;
   3591                }
   3592                if (sshift == s_end)
   3593                {
   3594                   sshift = s_start;
   3595                   sp--;
   3596                }
   3597                else
   3598                   sshift += s_inc;
   3599             }
   3600             break;
   3601          }
   3602          case 2:
   3603          {
   3604             png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
   3605             png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
   3606             int sshift, dshift;
   3607             int s_start, s_end, s_inc;
   3608             int jstop = png_pass_inc[pass];
   3609             png_uint_32 i;
   3610 
   3611 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
   3612             if (transformations & PNG_PACKSWAP)
   3613             {
   3614                sshift = (int)(((row_info->width + 3) & 0x03) << 1);
   3615                dshift = (int)(((final_width + 3) & 0x03) << 1);
   3616                s_start = 6;
   3617                s_end = 0;
   3618                s_inc = -2;
   3619             }
   3620             else
   3621 #endif
   3622             {
   3623                sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
   3624                dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
   3625                s_start = 0;
   3626                s_end = 6;
   3627                s_inc = 2;
   3628             }
   3629 
   3630             for (i = 0; i < row_info->width; i++)
   3631             {
   3632                png_byte v;
   3633                int j;
   3634 
   3635                v = (png_byte)((*sp >> sshift) & 0x03);
   3636                for (j = 0; j < jstop; j++)
   3637                {
   3638                   *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
   3639                   *dp |= (png_byte)(v << dshift);
   3640                   if (dshift == s_end)
   3641                   {
   3642                      dshift = s_start;
   3643                      dp--;
   3644                   }
   3645                   else
   3646                      dshift += s_inc;
   3647                }
   3648                if (sshift == s_end)
   3649                {
   3650                   sshift = s_start;
   3651                   sp--;
   3652                }
   3653                else
   3654                   sshift += s_inc;
   3655             }
   3656             break;
   3657          }
   3658          case 4:
   3659          {
   3660             png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
   3661             png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
   3662             int sshift, dshift;
   3663             int s_start, s_end, s_inc;
   3664             png_uint_32 i;
   3665             int jstop = png_pass_inc[pass];
   3666 
   3667 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
   3668             if (transformations & PNG_PACKSWAP)
   3669             {
   3670                sshift = (int)(((row_info->width + 1) & 0x01) << 2);
   3671                dshift = (int)(((final_width + 1) & 0x01) << 2);
   3672                s_start = 4;
   3673                s_end = 0;
   3674                s_inc = -4;
   3675             }
   3676             else
   3677 #endif
   3678             {
   3679                sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
   3680                dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
   3681                s_start = 0;
   3682                s_end = 4;
   3683                s_inc = 4;
   3684             }
   3685 
   3686             for (i = 0; i < row_info->width; i++)
   3687             {
   3688                png_byte v = (png_byte)((*sp >> sshift) & 0xf);
   3689                int j;
   3690 
   3691                for (j = 0; j < jstop; j++)
   3692                {
   3693                   *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
   3694                   *dp |= (png_byte)(v << dshift);
   3695                   if (dshift == s_end)
   3696                   {
   3697                      dshift = s_start;
   3698                      dp--;
   3699                   }
   3700                   else
   3701                      dshift += s_inc;
   3702                }
   3703                if (sshift == s_end)
   3704                {
   3705                   sshift = s_start;
   3706                   sp--;
   3707                }
   3708                else
   3709                   sshift += s_inc;
   3710             }
   3711             break;
   3712          }
   3713          default:
   3714          {
   3715             png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
   3716             png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes;
   3717             png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
   3718 
   3719             int jstop = png_pass_inc[pass];
   3720             png_uint_32 i;
   3721 
   3722             for (i = 0; i < row_info->width; i++)
   3723             {
   3724                png_byte v[8];
   3725                int j;
   3726 
   3727                png_memcpy(v, sp, pixel_bytes);
   3728                for (j = 0; j < jstop; j++)
   3729                {
   3730                   png_memcpy(dp, v, pixel_bytes);
   3731                   dp -= pixel_bytes;
   3732                }
   3733                sp -= pixel_bytes;
   3734             }
   3735             break;
   3736          }
   3737       }
   3738       row_info->width = final_width;
   3739       row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,final_width);
   3740    }
   3741 #if !defined(PNG_READ_PACKSWAP_SUPPORTED)
   3742    transformations = transformations; /* silence compiler warning */
   3743 #endif
   3744 }
   3745 #endif /* PNG_READ_INTERLACING_SUPPORTED */
   3746 
   3747 void /* PRIVATE */
   3748 png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
   3749    png_bytep prev_row, int filter)
   3750 {
   3751    png_debug(1, "in png_read_filter_row (NOT OPTIMIZED)\n");
   3752    png_debug2(2,"row = %lu, filter = %d\n", png_ptr->row_number, filter);
   3753    switch (filter)
   3754    {
   3755       case PNG_FILTER_VALUE_NONE:
   3756          break;
   3757       case PNG_FILTER_VALUE_SUB:
   3758       {
   3759          png_uint_32 i;
   3760          png_uint_32 istop = row_info->rowbytes;
   3761          png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
   3762          png_bytep rp = row + bpp;
   3763          png_bytep lp = row;
   3764 
   3765          for (i = bpp; i < istop; i++)
   3766          {
   3767             *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
   3768             rp++;
   3769          }
   3770          break;
   3771       }
   3772       case PNG_FILTER_VALUE_UP:
   3773       {
   3774          png_uint_32 i;
   3775          png_uint_32 istop = row_info->rowbytes;
   3776          png_bytep rp = row;
   3777          png_bytep pp = prev_row;
   3778 
   3779          for (i = 0; i < istop; i++)
   3780          {
   3781             *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
   3782             rp++;
   3783          }
   3784          break;
   3785       }
   3786       case PNG_FILTER_VALUE_AVG:
   3787       {
   3788          png_uint_32 i;
   3789          png_bytep rp = row;
   3790          png_bytep pp = prev_row;
   3791          png_bytep lp = row;
   3792          png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
   3793          png_uint_32 istop = row_info->rowbytes - bpp;
   3794 
   3795          for (i = 0; i < bpp; i++)
   3796          {
   3797             *rp = (png_byte)(((int)(*rp) +
   3798                ((int)(*pp++) / 2 )) & 0xff);
   3799             rp++;
   3800          }
   3801 
   3802          for (i = 0; i < istop; i++)
   3803          {
   3804             *rp = (png_byte)(((int)(*rp) +
   3805                (int)(*pp++ + *lp++) / 2 ) & 0xff);
   3806             rp++;
   3807          }
   3808          break;
   3809       }
   3810       case PNG_FILTER_VALUE_PAETH:
   3811       {
   3812          png_uint_32 i;
   3813          png_bytep rp = row;
   3814          png_bytep pp = prev_row;
   3815          png_bytep lp = row;
   3816          png_bytep cp = prev_row;
   3817          png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
   3818          png_uint_32 istop=row_info->rowbytes - bpp;
   3819 
   3820          for (i = 0; i < bpp; i++)
   3821          {
   3822             *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
   3823             rp++;
   3824          }
   3825 
   3826          for (i = 0; i < istop; i++)   /* use leftover rp,pp */
   3827          {
   3828             int a, b, c, pa, pb, pc, p;
   3829 
   3830             a = *lp++;
   3831             b = *pp++;
   3832             c = *cp++;
   3833 
   3834             p = b - c;
   3835             pc = a - c;
   3836 
   3837 #ifdef PNG_USE_ABS
   3838             pa = abs(p);
   3839             pb = abs(pc);
   3840             pc = abs(p + pc);
   3841 #else
   3842             pa = p < 0 ? -p : p;
   3843             pb = pc < 0 ? -pc : pc;
   3844             pc = (p + pc) < 0 ? -(p + pc) : p + pc;
   3845 #endif
   3846 
   3847             /*
   3848                if (pa <= pb && pa <= pc)
   3849                   p = a;
   3850                else if (pb <= pc)
   3851                   p = b;
   3852                else
   3853                   p = c;
   3854              */
   3855 
   3856             p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
   3857 
   3858             *rp = (png_byte)(((int)(*rp) + p) & 0xff);
   3859             rp++;
   3860          }
   3861          break;
   3862       }
   3863       default:
   3864          png_warning(png_ptr, "Ignoring bad adaptive filter type");
   3865          *row=0;
   3866          break;
   3867    }
   3868 }
   3869 #endif /* !PNG_OPTIMIZED_CODE_SUPPORTED */
   3870 #endif /* !PNG_USE_PNGGCCRD && !PNG_USE_PNGVCRD */
   3871 
   3872 void /* PRIVATE */
   3873 png_read_finish_row(png_structp png_ptr)
   3874 {
   3875 #ifdef PNG_USE_LOCAL_ARRAYS
   3876    /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
   3877 
   3878    /* start of interlace block */
   3879    PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
   3880 
   3881    /* offset to next interlace block */
   3882    PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
   3883 
   3884    /* start of interlace block in the y direction */
   3885    PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
   3886 
   3887    /* offset to next interlace block in the y direction */
   3888    PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
   3889 #endif
   3890 
   3891    png_debug(1, "in png_read_finish_row\n");
   3892    png_ptr->row_number++;
   3893    if (png_ptr->row_number < png_ptr->num_rows)
   3894       return;
   3895 
   3896    if (png_ptr->interlaced)
   3897    {
   3898       png_ptr->row_number = 0;
   3899       png_memset_check(png_ptr, png_ptr->prev_row, 0,
   3900          png_ptr->rowbytes + 1);
   3901       do
   3902       {
   3903          png_ptr->pass++;
   3904          if (png_ptr->pass >= 7)
   3905             break;
   3906          png_ptr->iwidth = (png_ptr->width +
   3907             png_pass_inc[png_ptr->pass] - 1 -
   3908             png_pass_start[png_ptr->pass]) /
   3909             png_pass_inc[png_ptr->pass];
   3910 
   3911          png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,
   3912             png_ptr->iwidth) + 1;
   3913 
   3914          if (!(png_ptr->transformations & PNG_INTERLACE))
   3915          {
   3916             png_ptr->num_rows = (png_ptr->height +
   3917                png_pass_yinc[png_ptr->pass] - 1 -
   3918                png_pass_ystart[png_ptr->pass]) /
   3919                png_pass_yinc[png_ptr->pass];
   3920             if (!(png_ptr->num_rows))
   3921                continue;
   3922          }
   3923          else  /* if (png_ptr->transformations & PNG_INTERLACE) */
   3924             break;
   3925       } while (png_ptr->iwidth == 0);
   3926 
   3927       if (png_ptr->pass < 7)
   3928          return;
   3929    }
   3930 
   3931    if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
   3932    {
   3933 #ifdef PNG_USE_LOCAL_ARRAYS
   3934       PNG_CONST PNG_IDAT;
   3935 #endif
   3936       char extra;
   3937       int ret;
   3938 
   3939       png_ptr->zstream.next_out = (Byte *)&extra;
   3940       png_ptr->zstream.avail_out = (uInt)1;
   3941       for(;;)
   3942       {
   3943          if (!(png_ptr->zstream.avail_in))
   3944          {
   3945             while (!png_ptr->idat_size)
   3946             {
   3947                png_byte chunk_length[4];
   3948 
   3949                png_crc_finish(png_ptr, 0);
   3950 
   3951                png_read_data(png_ptr, chunk_length, 4);
   3952                png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length);
   3953                png_reset_crc(png_ptr);
   3954                png_crc_read(png_ptr, png_ptr->chunk_name, 4);
   3955                if (png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4))
   3956                   png_error(png_ptr, "Not enough image data");
   3957 
   3958             }
   3959             png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
   3960             png_ptr->zstream.next_in = png_ptr->zbuf;
   3961             if (png_ptr->zbuf_size > png_ptr->idat_size)
   3962                png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
   3963             png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
   3964             png_ptr->idat_size -= png_ptr->zstream.avail_in;
   3965          }
   3966          ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
   3967          if (ret == Z_STREAM_END)
   3968          {
   3969             if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
   3970                png_ptr->idat_size)
   3971                png_warning(png_ptr, "Extra compressed data");
   3972             png_ptr->mode |= PNG_AFTER_IDAT;
   3973             png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
   3974             break;
   3975          }
   3976          if (ret != Z_OK)
   3977             png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
   3978                       "Decompression Error");
   3979 
   3980          if (!(png_ptr->zstream.avail_out))
   3981          {
   3982             png_warning(png_ptr, "Extra compressed data.");
   3983             png_ptr->mode |= PNG_AFTER_IDAT;
   3984             png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
   3985             break;
   3986          }
   3987 
   3988       }
   3989       png_ptr->zstream.avail_out = 0;
   3990    }
   3991 
   3992    if (png_ptr->idat_size || png_ptr->zstream.avail_in)
   3993       png_warning(png_ptr, "Extra compression data");
   3994 
   3995    inflateReset(&png_ptr->zstream);
   3996 
   3997    png_ptr->mode |= PNG_AFTER_IDAT;
   3998 }
   3999 
   4000 void /* PRIVATE */
   4001 png_read_start_row(png_structp png_ptr)
   4002 {
   4003 #ifdef PNG_USE_LOCAL_ARRAYS
   4004    /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
   4005 
   4006    /* start of interlace block */
   4007    PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
   4008 
   4009    /* offset to next interlace block */
   4010    PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
   4011 
   4012    /* start of interlace block in the y direction */
   4013    PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
   4014 
   4015    /* offset to next interlace block in the y direction */
   4016    PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
   4017 #endif
   4018 
   4019    int max_pixel_depth;
   4020    png_uint_32 row_bytes;
   4021 
   4022    png_debug(1, "in png_read_start_row\n");
   4023    png_ptr->zstream.avail_in = 0;
   4024    png_init_read_transformations(png_ptr);
   4025    if (png_ptr->interlaced)
   4026    {
   4027       if (!(png_ptr->transformations & PNG_INTERLACE))
   4028          png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
   4029             png_pass_ystart[0]) / png_pass_yinc[0];
   4030       else
   4031          png_ptr->num_rows = png_ptr->height;
   4032 
   4033       png_ptr->iwidth = (png_ptr->width +
   4034          png_pass_inc[png_ptr->pass] - 1 -
   4035          png_pass_start[png_ptr->pass]) /
   4036          png_pass_inc[png_ptr->pass];
   4037 
   4038          row_bytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->iwidth) + 1;
   4039 
   4040          png_ptr->irowbytes = (png_size_t)row_bytes;
   4041          if((png_uint_32)png_ptr->irowbytes != row_bytes)
   4042             png_error(png_ptr, "Rowbytes overflow in png_read_start_row");
   4043    }
   4044    else
   4045    {
   4046       png_ptr->num_rows = png_ptr->height;
   4047       png_ptr->iwidth = png_ptr->width;
   4048       png_ptr->irowbytes = png_ptr->rowbytes + 1;
   4049    }
   4050    max_pixel_depth = png_ptr->pixel_depth;
   4051 
   4052 #if defined(PNG_READ_PACK_SUPPORTED)
   4053    if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
   4054       max_pixel_depth = 8;
   4055 #endif
   4056 
   4057 #if defined(PNG_READ_EXPAND_SUPPORTED)
   4058    if (png_ptr->transformations & PNG_EXPAND)
   4059    {
   4060       if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
   4061       {
   4062          if (png_ptr->num_trans)
   4063             max_pixel_depth = 32;
   4064          else
   4065             max_pixel_depth = 24;
   4066       }
   4067       else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
   4068       {
   4069          if (max_pixel_depth < 8)
   4070             max_pixel_depth = 8;
   4071          if (png_ptr->num_trans)
   4072             max_pixel_depth *= 2;
   4073       }
   4074       else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
   4075       {
   4076          if (png_ptr->num_trans)
   4077          {
   4078             max_pixel_depth *= 4;
   4079             max_pixel_depth /= 3;
   4080          }
   4081       }
   4082    }
   4083 #endif
   4084 
   4085 #if defined(PNG_READ_FILLER_SUPPORTED)
   4086    if (png_ptr->transformations & (PNG_FILLER))
   4087    {
   4088       if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
   4089          max_pixel_depth = 32;
   4090       else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
   4091       {
   4092          if (max_pixel_depth <= 8)
   4093             max_pixel_depth = 16;
   4094          else
   4095             max_pixel_depth = 32;
   4096       }
   4097       else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
   4098       {
   4099          if (max_pixel_depth <= 32)
   4100             max_pixel_depth = 32;
   4101          else
   4102             max_pixel_depth = 64;
   4103       }
   4104    }
   4105 #endif
   4106 
   4107 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
   4108    if (png_ptr->transformations & PNG_GRAY_TO_RGB)
   4109    {
   4110       if (
   4111 #if defined(PNG_READ_EXPAND_SUPPORTED)
   4112         (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
   4113 #endif
   4114 #if defined(PNG_READ_FILLER_SUPPORTED)
   4115         (png_ptr->transformations & (PNG_FILLER)) ||
   4116 #endif
   4117         png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
   4118       {
   4119          if (max_pixel_depth <= 16)
   4120             max_pixel_depth = 32;
   4121          else
   4122             max_pixel_depth = 64;
   4123       }
   4124       else
   4125       {
   4126          if (max_pixel_depth <= 8)
   4127            {
   4128              if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
   4129                max_pixel_depth = 32;
   4130              else
   4131                max_pixel_depth = 24;
   4132            }
   4133          else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
   4134             max_pixel_depth = 64;
   4135          else
   4136             max_pixel_depth = 48;
   4137       }
   4138    }
   4139 #endif
   4140 
   4141 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
   4142 defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
   4143    if(png_ptr->transformations & PNG_USER_TRANSFORM)
   4144      {
   4145        int user_pixel_depth=png_ptr->user_transform_depth*
   4146          png_ptr->user_transform_channels;
   4147        if(user_pixel_depth > max_pixel_depth)
   4148          max_pixel_depth=user_pixel_depth;
   4149      }
   4150 #endif
   4151 
   4152    /* align the width on the next larger 8 pixels.  Mainly used
   4153       for interlacing */
   4154    row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
   4155    /* calculate the maximum bytes needed, adding a byte and a pixel
   4156       for safety's sake */
   4157    row_bytes = PNG_ROWBYTES(max_pixel_depth,row_bytes) +
   4158       1 + ((max_pixel_depth + 7) >> 3);
   4159 #ifdef PNG_MAX_MALLOC_64K
   4160    if (row_bytes > (png_uint_32)65536L)
   4161       png_error(png_ptr, "This image requires a row greater than 64KB");
   4162 #endif
   4163    png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes+64);
   4164    png_ptr->row_buf = png_ptr->big_row_buf+32;
   4165 #if defined(PNG_DEBUG) && defined(PNG_USE_PNGGCCRD) && defined(PNG_1_0_X)
   4166    png_ptr->row_buf_size = row_bytes;
   4167 #endif
   4168 
   4169 #ifdef PNG_MAX_MALLOC_64K
   4170    if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L)
   4171       png_error(png_ptr, "This image requires a row greater than 64KB");
   4172 #endif
   4173    if ((png_uint_32)png_ptr->rowbytes > (png_uint_32)(PNG_SIZE_MAX - 1))
   4174       png_error(png_ptr, "Row has too many bytes to allocate in memory.");
   4175    png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
   4176       png_ptr->rowbytes + 1));
   4177 
   4178    png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
   4179 
   4180    png_debug1(3, "width = %lu,\n", png_ptr->width);
   4181    png_debug1(3, "height = %lu,\n", png_ptr->height);
   4182    png_debug1(3, "iwidth = %lu,\n", png_ptr->iwidth);
   4183    png_debug1(3, "num_rows = %lu\n", png_ptr->num_rows);
   4184    png_debug1(3, "rowbytes = %lu,\n", png_ptr->rowbytes);
   4185    png_debug1(3, "irowbytes = %lu,\n", png_ptr->irowbytes);
   4186 
   4187    png_ptr->flags |= PNG_FLAG_ROW_INIT;
   4188 }
   4189 #endif /* PNG_READ_SUPPORTED */
   4190