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


openhrp3
Author(s): AIST, General Robotix Inc., Nakamura Lab of Dept. of Mechano Informatics at University of Tokyo
autogenerated on Thu Apr 11 2019 03:30:18