Back to index

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