apps/png/libpng/pngrutil.c

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

Generated on Fri Nov 28 00:06:22 2008 for elphel by  doxygen 1.5.1