pngrutil.c 88.9 KB
Newer Older
1

A
Andreas Dilger 已提交
2
/* pngrutil.c - utilities to read a PNG file
3
 *
4
 * Last changed in libpng 1.2.9 March 20, 2006
5
 * For conditions of distribution and use, see copyright notice in png.h
6
 * Copyright (c) 1998-2006 Glenn Randers-Pehrson
7 8
 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
9
 *
10
 * This file contains routines that are only called from within
11 12
 * libpng itself during the course of reading an image.
 */
G
Guy Schalnat 已提交
13 14 15 16

#define PNG_INTERNAL
#include "png.h"

17 18
#if defined(PNG_READ_SUPPORTED)

19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
#if defined(_WIN32_WCE)
/* strtod() function is not supported on WindowsCE */
#  ifdef PNG_FLOATING_POINT_SUPPORTED
__inline double strtod(const char *nptr, char **endptr)
{
   double result = 0;
   int len;
   wchar_t *str, *end;

   len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0);
   str = (wchar_t *)malloc(len * sizeof(wchar_t));
   if ( NULL != str )
   {
      MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len);
      result = wcstod(str, &end);
      len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL);
35
      *endptr = (char *)nptr + (png_strlen(nptr) - len + 1);
36 37 38 39 40 41 42
      free(str);
   }
   return result;
}
#  endif
#endif

43
png_uint_32 PNGAPI
44 45 46 47
png_get_uint_31(png_structp png_ptr, png_bytep buf)
{
   png_uint_32 i = png_get_uint_32(buf);
   if (i > PNG_UINT_31_MAX)
48
     png_error(png_ptr, "PNG unsigned integer out of range.");
49 50
   return (i);
}
A
Andreas Dilger 已提交
51
#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED
52
/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
53
png_uint_32 PNGAPI
G
Guy Schalnat 已提交
54
png_get_uint_32(png_bytep buf)
G
Guy Schalnat 已提交
55
{
56
   png_uint_32 i = ((png_uint_32)(*buf) << 24) +
G
Guy Schalnat 已提交
57 58 59 60
      ((png_uint_32)(*(buf + 1)) << 16) +
      ((png_uint_32)(*(buf + 2)) << 8) +
      (png_uint_32)(*(buf + 3));

61
   return (i);
G
Guy Schalnat 已提交
62 63
}

64
/* Grab a signed 32-bit integer from a buffer in big-endian format.  The
A
Andreas Dilger 已提交
65 66
 * data is stored in the PNG file in two's complement format, and it is
 * assumed that the machine format for signed integers is the same. */
67
png_int_32 PNGAPI
A
Andreas Dilger 已提交
68 69
png_get_int_32(png_bytep buf)
{
70
   png_int_32 i = ((png_int_32)(*buf) << 24) +
A
Andreas Dilger 已提交
71 72 73 74
      ((png_int_32)(*(buf + 1)) << 16) +
      ((png_int_32)(*(buf + 2)) << 8) +
      (png_int_32)(*(buf + 3));

75
   return (i);
A
Andreas Dilger 已提交
76 77
}

78
/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
79
png_uint_16 PNGAPI
G
Guy Schalnat 已提交
80
png_get_uint_16(png_bytep buf)
G
Guy Schalnat 已提交
81
{
82
   png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) +
G
Guy Schalnat 已提交
83
      (png_uint_16)(*(buf + 1)));
G
Guy Schalnat 已提交
84

85
   return (i);
G
Guy Schalnat 已提交
86
}
A
Andreas Dilger 已提交
87
#endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */
G
Guy Schalnat 已提交
88

A
Andreas Dilger 已提交
89
/* Read data, and (optionally) run it through the CRC. */
90
void /* PRIVATE */
A
Andreas Dilger 已提交
91
png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
G
Guy Schalnat 已提交
92
{
G
Guy Schalnat 已提交
93
   png_read_data(png_ptr, buf, length);
A
Andreas Dilger 已提交
94
   png_calculate_crc(png_ptr, buf, length);
G
Guy Schalnat 已提交
95 96
}

A
Andreas Dilger 已提交
97 98
/* Optionally skip data and then check the CRC.  Depending on whether we
   are reading a ancillary or critical chunk, and how the program has set
A
Andreas Dilger 已提交
99 100
   things up, we may calculate the CRC on the data and print a message.
   Returns '1' if there was a CRC error, '0' otherwise. */
101
int /* PRIVATE */
A
Andreas Dilger 已提交
102
png_crc_finish(png_structp png_ptr, png_uint_32 skip)
G
Guy Schalnat 已提交
103
{
104 105
   png_size_t i;
   png_size_t istop = png_ptr->zbuf_size;
G
Guy Schalnat 已提交
106

107
   for (i = (png_size_t)skip; i > istop; i -= istop)
A
Andreas Dilger 已提交
108
   {
A
Andreas Dilger 已提交
109
      png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
G
Guy Schalnat 已提交
110 111 112
   }
   if (i)
   {
113
      png_crc_read(png_ptr, png_ptr->zbuf, i);
A
Andreas Dilger 已提交
114 115
   }

A
Andreas Dilger 已提交
116
   if (png_crc_error(png_ptr))
A
Andreas Dilger 已提交
117
   {
118
      if (((png_ptr->chunk_name[0] & 0x20) &&                /* Ancillary */
A
Andreas Dilger 已提交
119 120
           !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
          (!(png_ptr->chunk_name[0] & 0x20) &&             /* Critical  */
121
          (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)))
A
Andreas Dilger 已提交
122
      {
123
         png_chunk_warning(png_ptr, "CRC error");
A
Andreas Dilger 已提交
124 125 126
      }
      else
      {
127
         png_chunk_error(png_ptr, "CRC error");
A
Andreas Dilger 已提交
128
      }
129
      return (1);
G
Guy Schalnat 已提交
130
   }
A
Andreas Dilger 已提交
131

132
   return (0);
G
Guy Schalnat 已提交
133 134
}

135
/* Compare the CRC stored in the PNG file with that calculated by libpng from
A
Andreas Dilger 已提交
136
   the data it has read thus far. */
137
int /* PRIVATE */
A
Andreas Dilger 已提交
138 139 140 141
png_crc_error(png_structp png_ptr)
{
   png_byte crc_bytes[4];
   png_uint_32 crc;
A
Andreas Dilger 已提交
142
   int need_crc = 1;
A
Andreas Dilger 已提交
143

A
Andreas Dilger 已提交
144 145 146 147 148 149 150 151 152 153 154
   if (png_ptr->chunk_name[0] & 0x20)                     /* ancillary */
   {
      if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
          (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
         need_crc = 0;
   }
   else                                                    /* critical */
   {
      if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
         need_crc = 0;
   }
A
Andreas Dilger 已提交
155

A
Andreas Dilger 已提交
156
   png_read_data(png_ptr, crc_bytes, 4);
A
Andreas Dilger 已提交
157

A
Andreas Dilger 已提交
158 159 160
   if (need_crc)
   {
      crc = png_get_uint_32(crc_bytes);
161
      return ((int)(crc != png_ptr->crc));
A
Andreas Dilger 已提交
162 163
   }
   else
164
      return (0);
A
Andreas Dilger 已提交
165 166
}

167
#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \
168
    defined(PNG_READ_iCCP_SUPPORTED)
169 170 171 172 173 174 175
/*
 * Decompress trailing data in a chunk.  The assumption is that chunkdata
 * points at an allocated area holding the contents of a chunk with a
 * trailing compressed part.  What we get back is an allocated area
 * holding the original prefix part and an uncompressed version of the
 * trailing part (the malloc area passed in is freed).
 */
176 177
png_charp /* PRIVATE */
png_decompress_chunk(png_structp png_ptr, int comp_type,
178
                              png_charp chunkdata, png_size_t chunklength,
179
                              png_size_t prefix_size, png_size_t *newlength)
180 181
{
   static char msg[] = "Error decoding compressed text";
182
   png_charp text;
183
   png_size_t text_size;
184

185
   if (comp_type == PNG_COMPRESSION_TYPE_BASE)
186
   {
187
      int ret = Z_OK;
188 189 190 191 192 193 194 195 196 197
      png_ptr->zstream.next_in = (png_bytep)(chunkdata + prefix_size);
      png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size);
      png_ptr->zstream.next_out = png_ptr->zbuf;
      png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;

      text_size = 0;
      text = NULL;

      while (png_ptr->zstream.avail_in)
      {
198
         ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
199 200 201 202 203 204 205 206 207 208 209
         if (ret != Z_OK && ret != Z_STREAM_END)
         {
            if (png_ptr->zstream.msg != NULL)
               png_warning(png_ptr, png_ptr->zstream.msg);
            else
               png_warning(png_ptr, msg);
            inflateReset(&png_ptr->zstream);
            png_ptr->zstream.avail_in = 0;

            if (text ==  NULL)
            {
210
               text_size = prefix_size + png_sizeof(msg) + 1;
211 212 213 214 215 216
               text = (png_charp)png_malloc_warn(png_ptr, text_size);
               if (text ==  NULL)
                 {
                    png_free(png_ptr,chunkdata);
                    png_error(png_ptr,"Not enough memory to decompress chunk");
                 }
217
               png_memcpy(text, chunkdata, prefix_size);
218 219
            }

220
            text[text_size - 1] = 0x00;
221

222 223
            /* Copy what we can of the error message into the text chunk */
            text_size = (png_size_t)(chunklength - (text - chunkdata) - 1);
224 225
            text_size = png_sizeof(msg) > text_size ? text_size :
               png_sizeof(msg);
226
            png_memcpy(text + prefix_size, msg, text_size + 1);
227 228 229 230 231 232 233 234
            break;
         }
         if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END)
         {
            if (text == NULL)
            {
               text_size = prefix_size +
                   png_ptr->zbuf_size - png_ptr->zstream.avail_out;
235 236 237 238 239 240
               text = (png_charp)png_malloc_warn(png_ptr, text_size + 1);
               if (text ==  NULL)
                 {
                    png_free(png_ptr,chunkdata);
                    png_error(png_ptr,"Not enough memory to decompress chunk.");
                 }
241
               png_memcpy(text + prefix_size, png_ptr->zbuf,
242
                    text_size - prefix_size);
243 244
               png_memcpy(text, chunkdata, prefix_size);
               *(text + text_size) = 0x00;
245 246 247 248 249 250
            }
            else
            {
               png_charp tmp;

               tmp = text;
251 252
               text = (png_charp)png_malloc_warn(png_ptr,
                  (png_uint_32)(text_size +
253
                  png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1));
254 255 256 257 258 259
               if (text == NULL)
               {
                  png_free(png_ptr, tmp);
                  png_free(png_ptr, chunkdata);
                  png_error(png_ptr,"Not enough memory to decompress chunk..");
               }
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
               png_memcpy(text, tmp, text_size);
               png_free(png_ptr, tmp);
               png_memcpy(text + text_size, png_ptr->zbuf,
                  (png_ptr->zbuf_size - png_ptr->zstream.avail_out));
               text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
               *(text + text_size) = 0x00;
            }
            if (ret == Z_STREAM_END)
               break;
            else
            {
               png_ptr->zstream.next_out = png_ptr->zbuf;
               png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
            }
         }
      }
276
      if (ret != Z_STREAM_END)
277
      {
278
#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
279 280
         char umsg[50];

281 282 283 284 285 286 287 288 289
         if (ret == Z_BUF_ERROR)
            sprintf(umsg,"Buffer error in compressed datastream in %s chunk",
                png_ptr->chunk_name);
         else if (ret == Z_DATA_ERROR)
            sprintf(umsg,"Data error in compressed datastream in %s chunk",
                png_ptr->chunk_name);
         else
            sprintf(umsg,"Incomplete compressed datastream in %s chunk",
                png_ptr->chunk_name);
290 291
         png_warning(png_ptr, umsg);
#else
292
         png_warning(png_ptr,
293 294
            "Incomplete compressed datastream in chunk other than IDAT");
#endif
295 296 297
         text_size=prefix_size;
         if (text ==  NULL)
         {
298 299 300 301 302 303
            text = (png_charp)png_malloc_warn(png_ptr, text_size+1);
            if (text == NULL)
              {
                png_free(png_ptr, chunkdata);
                png_error(png_ptr,"Not enough memory for text.");
              }
304
            png_memcpy(text, chunkdata, prefix_size);
305
         }
306
         *(text + text_size) = 0x00;
307
      }
308 309 310 311 312 313

      inflateReset(&png_ptr->zstream);
      png_ptr->zstream.avail_in = 0;

      png_free(png_ptr, chunkdata);
      chunkdata = text;
314
      *newlength=text_size;
315
   }
316
   else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
317
   {
318
#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
319 320 321 322 323 324 325 326
      char umsg[50];

      sprintf(umsg, "Unknown zTXt compression type %d", comp_type);
      png_warning(png_ptr, umsg);
#else
      png_warning(png_ptr, "Unknown zTXt compression type");
#endif

327 328
      *(chunkdata + prefix_size) = 0x00;
      *newlength=prefix_size;
329 330 331 332 333
   }

   return chunkdata;
}
#endif
A
Andreas Dilger 已提交
334

G
Guy Schalnat 已提交
335
/* read and check the IDHR chunk */
336
void /* PRIVATE */
A
Andreas Dilger 已提交
337
png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
G
Guy Schalnat 已提交
338 339 340 341 342 343
{
   png_byte buf[13];
   png_uint_32 width, height;
   int bit_depth, color_type, compression_type, filter_type;
   int interlace_type;

A
Andreas Dilger 已提交
344 345
   png_debug(1, "in png_handle_IHDR\n");

346
   if (png_ptr->mode & PNG_HAVE_IHDR)
G
Guy Schalnat 已提交
347 348
      png_error(png_ptr, "Out of place IHDR");

G
Guy Schalnat 已提交
349 350
   /* check the length */
   if (length != 13)
G
Guy Schalnat 已提交
351
      png_error(png_ptr, "Invalid IHDR chunk");
G
Guy Schalnat 已提交
352

A
Andreas Dilger 已提交
353 354
   png_ptr->mode |= PNG_HAVE_IHDR;

G
Guy Schalnat 已提交
355
   png_crc_read(png_ptr, buf, 13);
A
Andreas Dilger 已提交
356
   png_crc_finish(png_ptr, 0);
G
Guy Schalnat 已提交
357

358 359
   width = png_get_uint_31(png_ptr, buf);
   height = png_get_uint_31(png_ptr, buf + 4);
G
Guy Schalnat 已提交
360 361 362 363 364 365 366 367 368
   bit_depth = buf[8];
   color_type = buf[9];
   compression_type = buf[10];
   filter_type = buf[11];
   interlace_type = buf[12];

   /* set internal variables */
   png_ptr->width = width;
   png_ptr->height = height;
G
Guy Schalnat 已提交
369 370 371
   png_ptr->bit_depth = (png_byte)bit_depth;
   png_ptr->interlaced = (png_byte)interlace_type;
   png_ptr->color_type = (png_byte)color_type;
372
#if defined(PNG_MNG_FEATURES_SUPPORTED)
373
   png_ptr->filter_type = (png_byte)filter_type;
374
#endif
375
   png_ptr->compression_type = (png_byte)compression_type;
G
Guy Schalnat 已提交
376 377 378 379

   /* find number of channels */
   switch (png_ptr->color_type)
   {
A
Andreas Dilger 已提交
380 381
      case PNG_COLOR_TYPE_GRAY:
      case PNG_COLOR_TYPE_PALETTE:
G
Guy Schalnat 已提交
382 383
         png_ptr->channels = 1;
         break;
A
Andreas Dilger 已提交
384
      case PNG_COLOR_TYPE_RGB:
G
Guy Schalnat 已提交
385 386
         png_ptr->channels = 3;
         break;
A
Andreas Dilger 已提交
387
      case PNG_COLOR_TYPE_GRAY_ALPHA:
G
Guy Schalnat 已提交
388 389
         png_ptr->channels = 2;
         break;
A
Andreas Dilger 已提交
390
      case PNG_COLOR_TYPE_RGB_ALPHA:
G
Guy Schalnat 已提交
391 392 393
         png_ptr->channels = 4;
         break;
   }
A
Andreas Dilger 已提交
394

G
Guy Schalnat 已提交
395
   /* set up other useful info */
G
Guy Schalnat 已提交
396
   png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
397
   png_ptr->channels);
398
   png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->width);
A
Andreas Dilger 已提交
399 400
   png_debug1(3,"bit_depth = %d\n", png_ptr->bit_depth);
   png_debug1(3,"channels = %d\n", png_ptr->channels);
401
   png_debug1(3,"rowbytes = %lu\n", png_ptr->rowbytes);
A
Andreas Dilger 已提交
402 403
   png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
      color_type, interlace_type, compression_type, filter_type);
G
Guy Schalnat 已提交
404 405 406
}

/* read and check the palette */
407
void /* PRIVATE */
A
Andreas Dilger 已提交
408
png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
G
Guy Schalnat 已提交
409
{
410
   png_color palette[PNG_MAX_PALETTE_LENGTH];
A
Andreas Dilger 已提交
411
   int num, i;
412 413 414
#ifndef PNG_NO_POINTER_INDEXING
   png_colorp pal_ptr;
#endif
G
Guy Schalnat 已提交
415

A
Andreas Dilger 已提交
416 417
   png_debug(1, "in png_handle_PLTE\n");

G
Guy Schalnat 已提交
418 419
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
      png_error(png_ptr, "Missing IHDR before PLTE");
A
Andreas Dilger 已提交
420 421 422 423 424 425
   else if (png_ptr->mode & PNG_HAVE_IDAT)
   {
      png_warning(png_ptr, "Invalid PLTE after IDAT");
      png_crc_finish(png_ptr, length);
      return;
   }
G
Guy Schalnat 已提交
426
   else if (png_ptr->mode & PNG_HAVE_PLTE)
A
Andreas Dilger 已提交
427 428 429
      png_error(png_ptr, "Duplicate PLTE chunk");

   png_ptr->mode |= PNG_HAVE_PLTE;
G
Guy Schalnat 已提交
430

431 432 433 434 435 436 437
   if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
   {
      png_warning(png_ptr,
        "Ignoring PLTE chunk in grayscale PNG");
      png_crc_finish(png_ptr, length);
      return;
   }
G
Guy Schalnat 已提交
438 439 440
#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
   if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
   {
A
Andreas Dilger 已提交
441
      png_crc_finish(png_ptr, length);
G
Guy Schalnat 已提交
442 443 444 445
      return;
   }
#endif

446
   if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
G
Guy Schalnat 已提交
447 448 449 450
   {
      if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
      {
         png_warning(png_ptr, "Invalid palette chunk");
A
Andreas Dilger 已提交
451
         png_crc_finish(png_ptr, length);
G
Guy Schalnat 已提交
452 453 454 455 456 457 458
         return;
      }
      else
      {
         png_error(png_ptr, "Invalid palette chunk");
      }
   }
G
Guy Schalnat 已提交
459 460

   num = (int)length / 3;
461

462 463 464 465 466 467 468 469 470 471 472
#ifndef PNG_NO_POINTER_INDEXING
   for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
   {
      png_byte buf[3];

      png_crc_read(png_ptr, buf, 3);
      pal_ptr->red = buf[0];
      pal_ptr->green = buf[1];
      pal_ptr->blue = buf[2];
   }
#else
G
Guy Schalnat 已提交
473
   for (i = 0; i < num; i++)
G
Guy Schalnat 已提交
474 475 476 477 478 479 480 481 482
   {
      png_byte buf[3];

      png_crc_read(png_ptr, buf, 3);
      /* don't depend upon png_color being any order */
      palette[i].red = buf[0];
      palette[i].green = buf[1];
      palette[i].blue = buf[2];
   }
483
#endif
A
Andreas Dilger 已提交
484 485 486 487 488

   /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
      whatever the normal CRC configuration tells us.  However, if we
      have an RGB image, the PLTE can be considered ancillary, so
      we will act as though it is. */
489
#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
A
Andreas Dilger 已提交
490
   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
491
#endif
A
Andreas Dilger 已提交
492
   {
A
Andreas Dilger 已提交
493
      png_crc_finish(png_ptr, 0);
A
Andreas Dilger 已提交
494
   }
495
#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
A
Andreas Dilger 已提交
496 497 498 499 500 501 502 503 504 505
   else if (png_crc_error(png_ptr))  /* Only if we have a CRC error */
   {
      /* If we don't want to use the data from an ancillary chunk,
         we have two options: an error abort, or a warning and we
         ignore the data in this chunk (which should be OK, since
         it's considered ancillary for a RGB or RGBA image). */
      if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
      {
         if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
         {
506
            png_chunk_error(png_ptr, "CRC error");
A
Andreas Dilger 已提交
507 508 509
         }
         else
         {
510
            png_chunk_warning(png_ptr, "CRC error");
A
Andreas Dilger 已提交
511 512 513
            return;
         }
      }
A
Andreas Dilger 已提交
514
      /* Otherwise, we (optionally) emit a warning and use the chunk. */
A
Andreas Dilger 已提交
515 516
      else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
      {
517
         png_chunk_warning(png_ptr, "CRC error");
A
Andreas Dilger 已提交
518 519
      }
   }
520
#endif
521

A
Andreas Dilger 已提交
522
   png_set_PLTE(png_ptr, info_ptr, palette, num);
523

524
#if defined(PNG_READ_tRNS_SUPPORTED)
525 526
   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
   {
527
      if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
528
      {
529
         if (png_ptr->num_trans > (png_uint_16)num)
530 531
         {
            png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
532 533 534 535 536 537
            png_ptr->num_trans = (png_uint_16)num;
         }
         if (info_ptr->num_trans > (png_uint_16)num)
         {
            png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
            info_ptr->num_trans = (png_uint_16)num;
538 539 540 541 542
         }
      }
   }
#endif

A
Andreas Dilger 已提交
543
}
G
Guy Schalnat 已提交
544

545
void /* PRIVATE */
A
Andreas Dilger 已提交
546 547
png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
{
A
Andreas Dilger 已提交
548 549
   png_debug(1, "in png_handle_IEND\n");

A
Andreas Dilger 已提交
550 551 552 553 554
   if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
   {
      png_error(png_ptr, "No image in file");
   }

555
   png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
A
Andreas Dilger 已提交
556 557 558 559 560

   if (length != 0)
   {
      png_warning(png_ptr, "Incorrect IEND chunk length");
   }
A
Andreas Dilger 已提交
561
   png_crc_finish(png_ptr, length);
562 563 564

   if (&info_ptr == NULL) /* quiet compiler warnings about unused info_ptr */
      return;
G
Guy Schalnat 已提交
565 566
}

G
Guy Schalnat 已提交
567
#if defined(PNG_READ_gAMA_SUPPORTED)
568
void /* PRIVATE */
A
Andreas Dilger 已提交
569
png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
G
Guy Schalnat 已提交
570
{
571
   png_fixed_point igamma;
572
#ifdef PNG_FLOATING_POINT_SUPPORTED
A
Andreas Dilger 已提交
573
   float file_gamma;
574
#endif
G
Guy Schalnat 已提交
575 576
   png_byte buf[4];

A
Andreas Dilger 已提交
577 578
   png_debug(1, "in png_handle_gAMA\n");

G
Guy Schalnat 已提交
579 580
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
      png_error(png_ptr, "Missing IHDR before gAMA");
A
Andreas Dilger 已提交
581 582 583 584 585 586
   else if (png_ptr->mode & PNG_HAVE_IDAT)
   {
      png_warning(png_ptr, "Invalid gAMA after IDAT");
      png_crc_finish(png_ptr, length);
      return;
   }
G
Guy Schalnat 已提交
587 588 589
   else if (png_ptr->mode & PNG_HAVE_PLTE)
      /* Should be an error, but we can cope with it */
      png_warning(png_ptr, "Out of place gAMA chunk");
590

591
   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
592 593 594 595
#if defined(PNG_READ_sRGB_SUPPORTED)
      && !(info_ptr->valid & PNG_INFO_sRGB)
#endif
      )
A
Andreas Dilger 已提交
596 597 598 599 600
   {
      png_warning(png_ptr, "Duplicate gAMA chunk");
      png_crc_finish(png_ptr, length);
      return;
   }
G
Guy Schalnat 已提交
601

G
Guy Schalnat 已提交
602 603
   if (length != 4)
   {
G
Guy Schalnat 已提交
604
      png_warning(png_ptr, "Incorrect gAMA chunk length");
A
Andreas Dilger 已提交
605
      png_crc_finish(png_ptr, length);
G
Guy Schalnat 已提交
606 607 608 609
      return;
   }

   png_crc_read(png_ptr, buf, 4);
A
Andreas Dilger 已提交
610 611 612
   if (png_crc_finish(png_ptr, 0))
      return;

613
   igamma = (png_fixed_point)png_get_uint_32(buf);
G
Guy Schalnat 已提交
614
   /* check for zero gamma */
A
Andreas Dilger 已提交
615
   if (igamma == 0)
616 617 618 619 620
      {
         png_warning(png_ptr,
           "Ignoring gAMA chunk with gamma=0");
         return;
      }
G
Guy Schalnat 已提交
621

622
#if defined(PNG_READ_sRGB_SUPPORTED)
623
   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
624
      if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
625 626 627
      {
         png_warning(png_ptr,
           "Ignoring incorrect gAMA value when sRGB is also present");
628
#ifndef PNG_NO_CONSOLE_IO
629
         fprintf(stderr, "gamma = (%d/100000)\n", (int)igamma);
630
#endif
631 632 633 634
         return;
      }
#endif /* PNG_READ_sRGB_SUPPORTED */

635
#ifdef PNG_FLOATING_POINT_SUPPORTED
636
   file_gamma = (float)igamma / (float)100000.0;
637 638 639 640
#  ifdef PNG_READ_GAMMA_SUPPORTED
     png_ptr->gamma = file_gamma;
#  endif
     png_set_gAMA(png_ptr, info_ptr, file_gamma);
641 642 643 644
#endif
#ifdef PNG_FIXED_POINT_SUPPORTED
   png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
#endif
G
Guy Schalnat 已提交
645
}
G
Guy Schalnat 已提交
646
#endif
G
Guy Schalnat 已提交
647

G
Guy Schalnat 已提交
648
#if defined(PNG_READ_sBIT_SUPPORTED)
649
void /* PRIVATE */
A
Andreas Dilger 已提交
650
png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
G
Guy Schalnat 已提交
651
{
A
Andreas Dilger 已提交
652
   png_size_t truelen;
G
Guy Schalnat 已提交
653
   png_byte buf[4];
G
Guy Schalnat 已提交
654

A
Andreas Dilger 已提交
655 656
   png_debug(1, "in png_handle_sBIT\n");

G
Guy Schalnat 已提交
657
   buf[0] = buf[1] = buf[2] = buf[3] = 0;
G
Guy Schalnat 已提交
658

G
Guy Schalnat 已提交
659 660
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
      png_error(png_ptr, "Missing IHDR before sBIT");
A
Andreas Dilger 已提交
661 662 663 664 665 666
   else if (png_ptr->mode & PNG_HAVE_IDAT)
   {
      png_warning(png_ptr, "Invalid sBIT after IDAT");
      png_crc_finish(png_ptr, length);
      return;
   }
G
Guy Schalnat 已提交
667
   else if (png_ptr->mode & PNG_HAVE_PLTE)
668
   {
G
Guy Schalnat 已提交
669 670
      /* Should be an error, but we can cope with it */
      png_warning(png_ptr, "Out of place sBIT chunk");
671
   }
672
   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
A
Andreas Dilger 已提交
673 674 675 676 677
   {
      png_warning(png_ptr, "Duplicate sBIT chunk");
      png_crc_finish(png_ptr, length);
      return;
   }
G
Guy Schalnat 已提交
678

G
Guy Schalnat 已提交
679
   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
A
Andreas Dilger 已提交
680
      truelen = 3;
G
Guy Schalnat 已提交
681
   else
A
Andreas Dilger 已提交
682
      truelen = (png_size_t)png_ptr->channels;
G
Guy Schalnat 已提交
683

684
   if (length != truelen || length > 4)
G
Guy Schalnat 已提交
685
   {
G
Guy Schalnat 已提交
686
      png_warning(png_ptr, "Incorrect sBIT chunk length");
A
Andreas Dilger 已提交
687
      png_crc_finish(png_ptr, length);
G
Guy Schalnat 已提交
688
      return;
G
Guy Schalnat 已提交
689 690
   }

A
Andreas Dilger 已提交
691
   png_crc_read(png_ptr, buf, truelen);
A
Andreas Dilger 已提交
692 693 694
   if (png_crc_finish(png_ptr, 0))
      return;

G
Guy Schalnat 已提交
695 696
   if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
   {
G
Guy Schalnat 已提交
697 698 699 700
      png_ptr->sig_bit.red = buf[0];
      png_ptr->sig_bit.green = buf[1];
      png_ptr->sig_bit.blue = buf[2];
      png_ptr->sig_bit.alpha = buf[3];
G
Guy Schalnat 已提交
701 702 703
   }
   else
   {
G
Guy Schalnat 已提交
704
      png_ptr->sig_bit.gray = buf[0];
705 706 707
      png_ptr->sig_bit.red = buf[0];
      png_ptr->sig_bit.green = buf[0];
      png_ptr->sig_bit.blue = buf[0];
G
Guy Schalnat 已提交
708
      png_ptr->sig_bit.alpha = buf[1];
G
Guy Schalnat 已提交
709
   }
A
Andreas Dilger 已提交
710
   png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
G
Guy Schalnat 已提交
711
}
G
Guy Schalnat 已提交
712
#endif
G
Guy Schalnat 已提交
713

G
Guy Schalnat 已提交
714
#if defined(PNG_READ_cHRM_SUPPORTED)
715
void /* PRIVATE */
A
Andreas Dilger 已提交
716
png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
G
Guy Schalnat 已提交
717 718
{
   png_byte buf[4];
719
#ifdef PNG_FLOATING_POINT_SUPPORTED
G
Guy Schalnat 已提交
720
   float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
721
#endif
722
   png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
723
      int_y_green, int_x_blue, int_y_blue;
G
Guy Schalnat 已提交
724

725 726
   png_uint_32 uint_x, uint_y;

A
Andreas Dilger 已提交
727 728
   png_debug(1, "in png_handle_cHRM\n");

G
Guy Schalnat 已提交
729
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
730
      png_error(png_ptr, "Missing IHDR before cHRM");
A
Andreas Dilger 已提交
731 732 733 734 735 736
   else if (png_ptr->mode & PNG_HAVE_IDAT)
   {
      png_warning(png_ptr, "Invalid cHRM after IDAT");
      png_crc_finish(png_ptr, length);
      return;
   }
G
Guy Schalnat 已提交
737 738 739
   else if (png_ptr->mode & PNG_HAVE_PLTE)
      /* Should be an error, but we can cope with it */
      png_warning(png_ptr, "Missing PLTE before cHRM");
740

741
   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
742 743 744 745
#if defined(PNG_READ_sRGB_SUPPORTED)
      && !(info_ptr->valid & PNG_INFO_sRGB)
#endif
      )
A
Andreas Dilger 已提交
746 747 748 749 750
   {
      png_warning(png_ptr, "Duplicate cHRM chunk");
      png_crc_finish(png_ptr, length);
      return;
   }
G
Guy Schalnat 已提交
751

G
Guy Schalnat 已提交
752 753
   if (length != 32)
   {
G
Guy Schalnat 已提交
754
      png_warning(png_ptr, "Incorrect cHRM chunk length");
A
Andreas Dilger 已提交
755
      png_crc_finish(png_ptr, length);
G
Guy Schalnat 已提交
756
      return;
G
Guy Schalnat 已提交
757 758 759
   }

   png_crc_read(png_ptr, buf, 4);
760
   uint_x = png_get_uint_32(buf);
G
Guy Schalnat 已提交
761 762

   png_crc_read(png_ptr, buf, 4);
763
   uint_y = png_get_uint_32(buf);
A
Andreas Dilger 已提交
764

765 766
   if (uint_x > 80000L || uint_y > 80000L ||
      uint_x + uint_y > 100000L)
A
Andreas Dilger 已提交
767 768 769 770 771
   {
      png_warning(png_ptr, "Invalid cHRM white point");
      png_crc_finish(png_ptr, 24);
      return;
   }
772 773
   int_x_white = (png_fixed_point)uint_x;
   int_y_white = (png_fixed_point)uint_y;
G
Guy Schalnat 已提交
774 775

   png_crc_read(png_ptr, buf, 4);
776
   uint_x = png_get_uint_32(buf);
G
Guy Schalnat 已提交
777 778

   png_crc_read(png_ptr, buf, 4);
779
   uint_y = png_get_uint_32(buf);
A
Andreas Dilger 已提交
780

781
   if (uint_x + uint_y > 100000L)
A
Andreas Dilger 已提交
782 783 784 785 786
   {
      png_warning(png_ptr, "Invalid cHRM red point");
      png_crc_finish(png_ptr, 16);
      return;
   }
787 788
   int_x_red = (png_fixed_point)uint_x;
   int_y_red = (png_fixed_point)uint_y;
G
Guy Schalnat 已提交
789 790

   png_crc_read(png_ptr, buf, 4);
791
   uint_x = png_get_uint_32(buf);
G
Guy Schalnat 已提交
792 793

   png_crc_read(png_ptr, buf, 4);
794
   uint_y = png_get_uint_32(buf);
A
Andreas Dilger 已提交
795

796
   if (uint_x + uint_y > 100000L)
A
Andreas Dilger 已提交
797 798 799 800 801
   {
      png_warning(png_ptr, "Invalid cHRM green point");
      png_crc_finish(png_ptr, 8);
      return;
   }
802 803
   int_x_green = (png_fixed_point)uint_x;
   int_y_green = (png_fixed_point)uint_y;
G
Guy Schalnat 已提交
804 805

   png_crc_read(png_ptr, buf, 4);
806
   uint_x = png_get_uint_32(buf);
G
Guy Schalnat 已提交
807 808

   png_crc_read(png_ptr, buf, 4);
809
   uint_y = png_get_uint_32(buf);
A
Andreas Dilger 已提交
810

811
   if (uint_x + uint_y > 100000L)
A
Andreas Dilger 已提交
812 813 814 815 816
   {
      png_warning(png_ptr, "Invalid cHRM blue point");
      png_crc_finish(png_ptr, 0);
      return;
   }
817 818 819
   int_x_blue = (png_fixed_point)uint_x;
   int_y_blue = (png_fixed_point)uint_y;

820 821 822 823 824 825 826 827 828 829
#ifdef PNG_FLOATING_POINT_SUPPORTED
   white_x = (float)int_x_white / (float)100000.0;
   white_y = (float)int_y_white / (float)100000.0;
   red_x   = (float)int_x_red   / (float)100000.0;
   red_y   = (float)int_y_red   / (float)100000.0;
   green_x = (float)int_x_green / (float)100000.0;
   green_y = (float)int_y_green / (float)100000.0;
   blue_x  = (float)int_x_blue  / (float)100000.0;
   blue_y  = (float)int_y_blue  / (float)100000.0;
#endif
G
Guy Schalnat 已提交
830

831
#if defined(PNG_READ_sRGB_SUPPORTED)
832
   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
833
      {
834 835 836 837 838 839 840 841
      if (PNG_OUT_OF_RANGE(int_x_white, 31270,  1000) ||
          PNG_OUT_OF_RANGE(int_y_white, 32900,  1000) ||
          PNG_OUT_OF_RANGE(int_x_red,   64000L, 1000) ||
          PNG_OUT_OF_RANGE(int_y_red,   33000,  1000) ||
          PNG_OUT_OF_RANGE(int_x_green, 30000,  1000) ||
          PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) ||
          PNG_OUT_OF_RANGE(int_x_blue,  15000,  1000) ||
          PNG_OUT_OF_RANGE(int_y_blue,   6000,  1000))
842
         {
843

844 845
            png_warning(png_ptr,
              "Ignoring incorrect cHRM value when sRGB is also present");
846
#ifndef PNG_NO_CONSOLE_IO
847
#ifdef PNG_FLOATING_POINT_SUPPORTED
848 849 850 851
            fprintf(stderr,"wx=%f, wy=%f, rx=%f, ry=%f\n",
               white_x, white_y, red_x, red_y);
            fprintf(stderr,"gx=%f, gy=%f, bx=%f, by=%f\n",
               green_x, green_y, blue_x, blue_y);
852
#else
853
            fprintf(stderr,"wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
854
               int_x_white, int_y_white, int_x_red, int_y_red);
855
            fprintf(stderr,"gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
856
               int_x_green, int_y_green, int_x_blue, int_y_blue);
857
#endif
858
#endif /* PNG_NO_CONSOLE_IO */
859
         }
860
         png_crc_finish(png_ptr, 0);
861 862 863 864
         return;
      }
#endif /* PNG_READ_sRGB_SUPPORTED */

865
#ifdef PNG_FLOATING_POINT_SUPPORTED
A
Andreas Dilger 已提交
866
   png_set_cHRM(png_ptr, info_ptr,
G
Guy Schalnat 已提交
867
      white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
868 869 870 871 872 873
#endif
#ifdef PNG_FIXED_POINT_SUPPORTED
   png_set_cHRM_fixed(png_ptr, info_ptr,
      int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
      int_y_green, int_x_blue, int_y_blue);
#endif
874 875
   if (png_crc_finish(png_ptr, 0))
      return;
G
Guy Schalnat 已提交
876
}
G
Guy Schalnat 已提交
877
#endif
G
Guy Schalnat 已提交
878

879
#if defined(PNG_READ_sRGB_SUPPORTED)
880
void /* PRIVATE */
881 882
png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
{
883
   int intent;
884 885 886 887 888 889 890 891 892 893 894 895 896 897 898
   png_byte buf[1];

   png_debug(1, "in png_handle_sRGB\n");

   if (!(png_ptr->mode & PNG_HAVE_IHDR))
      png_error(png_ptr, "Missing IHDR before sRGB");
   else if (png_ptr->mode & PNG_HAVE_IDAT)
   {
      png_warning(png_ptr, "Invalid sRGB after IDAT");
      png_crc_finish(png_ptr, length);
      return;
   }
   else if (png_ptr->mode & PNG_HAVE_PLTE)
      /* Should be an error, but we can cope with it */
      png_warning(png_ptr, "Out of place sRGB chunk");
899

900
   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919
   {
      png_warning(png_ptr, "Duplicate sRGB chunk");
      png_crc_finish(png_ptr, length);
      return;
   }

   if (length != 1)
   {
      png_warning(png_ptr, "Incorrect sRGB chunk length");
      png_crc_finish(png_ptr, length);
      return;
   }

   png_crc_read(png_ptr, buf, 1);
   if (png_crc_finish(png_ptr, 0))
      return;

   intent = buf[0];
   /* check for bad intent */
920
   if (intent >= PNG_sRGB_INTENT_LAST)
921 922 923 924 925
   {
      png_warning(png_ptr, "Unknown sRGB intent");
      return;
   }

926
#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
927
   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA))
928
   {
929
   png_fixed_point igamma;
930
#ifdef PNG_FIXED_POINT_SUPPORTED
931
      igamma=info_ptr->int_gamma;
932
#else
933
#  ifdef PNG_FLOATING_POINT_SUPPORTED
934
      igamma=(png_fixed_point)(info_ptr->gamma * 100000.);
935 936
#  endif
#endif
937
      if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
938 939 940
      {
         png_warning(png_ptr,
           "Ignoring incorrect gAMA value when sRGB is also present");
941
#ifndef PNG_NO_CONSOLE_IO
942 943 944 945 946 947 948
#  ifdef PNG_FIXED_POINT_SUPPORTED
         fprintf(stderr,"incorrect gamma=(%d/100000)\n",(int)png_ptr->int_gamma);
#  else
#    ifdef PNG_FLOATING_POINT_SUPPORTED
         fprintf(stderr,"incorrect gamma=%f\n",png_ptr->gamma);
#    endif
#  endif
949 950
#endif
      }
951
   }
952 953 954
#endif /* PNG_READ_gAMA_SUPPORTED */

#ifdef PNG_READ_cHRM_SUPPORTED
955
#ifdef PNG_FIXED_POINT_SUPPORTED
956
   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
957 958 959 960 961 962 963 964
      if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270,  1000) ||
          PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900,  1000) ||
          PNG_OUT_OF_RANGE(info_ptr->int_x_red,   64000L, 1000) ||
          PNG_OUT_OF_RANGE(info_ptr->int_y_red,   33000,  1000) ||
          PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000,  1000) ||
          PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) ||
          PNG_OUT_OF_RANGE(info_ptr->int_x_blue,  15000,  1000) ||
          PNG_OUT_OF_RANGE(info_ptr->int_y_blue,   6000,  1000))
965 966 967 968
         {
            png_warning(png_ptr,
              "Ignoring incorrect cHRM value when sRGB is also present");
         }
969
#endif /* PNG_FIXED_POINT_SUPPORTED */
970
#endif /* PNG_READ_cHRM_SUPPORTED */
971

972
   png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
973
}
974 975
#endif /* PNG_READ_sRGB_SUPPORTED */

976
#if defined(PNG_READ_iCCP_SUPPORTED)
977
void /* PRIVATE */
978 979 980 981 982
png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
/* Note: this does not properly handle chunks that are > 64K under DOS */
{
   png_charp chunkdata;
   png_byte compression_type;
983
   png_bytep pC;
984 985
   png_charp profile;
   png_uint_32 skip = 0;
986
   png_uint_32 profile_size, profile_length;
987
   png_size_t slength, prefix_length, data_length;
988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002

   png_debug(1, "in png_handle_iCCP\n");

   if (!(png_ptr->mode & PNG_HAVE_IHDR))
      png_error(png_ptr, "Missing IHDR before iCCP");
   else if (png_ptr->mode & PNG_HAVE_IDAT)
   {
      png_warning(png_ptr, "Invalid iCCP after IDAT");
      png_crc_finish(png_ptr, length);
      return;
   }
   else if (png_ptr->mode & PNG_HAVE_PLTE)
      /* Should be an error, but we can cope with it */
      png_warning(png_ptr, "Out of place iCCP chunk");

1003
   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020
   {
      png_warning(png_ptr, "Duplicate iCCP chunk");
      png_crc_finish(png_ptr, length);
      return;
   }

#ifdef PNG_MAX_MALLOC_64K
   if (length > (png_uint_32)65535L)
   {
      png_warning(png_ptr, "iCCP chunk too large to fit in memory");
      skip = length - (png_uint_32)65535L;
      length = (png_uint_32)65535L;
   }
#endif

   chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
   slength = (png_size_t)length;
1021
   png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032

   if (png_crc_finish(png_ptr, skip))
   {
      png_free(png_ptr, chunkdata);
      return;
   }

   chunkdata[slength] = 0x00;

   for (profile = chunkdata; *profile; profile++)
      /* empty loop to find end of name */ ;
1033

1034 1035
   ++profile;

1036
   /* there should be at least one zero (the compression type byte)
1037
      following the separator, and we should be on it  */
1038
   if ( profile >= chunkdata + slength)
1039 1040
   {
      png_free(png_ptr, chunkdata);
1041
      png_warning(png_ptr, "Malformed iCCP chunk");
1042
      return;
1043 1044
   }

1045
   /* compression_type should always be zero */
1046
   compression_type = *profile++;
1047 1048 1049 1050 1051 1052
   if (compression_type)
   {
      png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
      compression_type=0x00;  /* Reset it to zero (libpng-1.0.6 through 1.0.8
                                 wrote nonzero) */
   }
1053 1054 1055

   prefix_length = profile - chunkdata;
   chunkdata = png_decompress_chunk(png_ptr, compression_type, chunkdata,
1056
                                    slength, prefix_length, &data_length);
1057

1058
   profile_length = data_length - prefix_length;
1059

1060
   if ( prefix_length > data_length || profile_length < 4)
1061 1062 1063 1064 1065 1066
   {
      png_free(png_ptr, chunkdata);
      png_warning(png_ptr, "Profile size field missing from iCCP chunk");
      return;
   }

1067
   /* Check the profile_size recorded in the first 32 bits of the ICC profile */
1068 1069 1070 1071 1072
   pC = (png_bytep)(chunkdata+prefix_length);
   profile_size = ((*(pC  ))<<24) |
                  ((*(pC+1))<<16) |
                  ((*(pC+2))<< 8) |
                  ((*(pC+3))    );
1073 1074 1075 1076 1077 1078

   if(profile_size < profile_length)
      profile_length = profile_size;

   if(profile_size > profile_length)
   {
1079
      png_free(png_ptr, chunkdata);
1080
      png_warning(png_ptr, "Ignoring truncated iCCP profile.");
1081 1082 1083
      return;
   }

1084
   png_set_iCCP(png_ptr, info_ptr, chunkdata, compression_type,
1085
                chunkdata + prefix_length, profile_length);
1086 1087 1088 1089 1090
   png_free(png_ptr, chunkdata);
}
#endif /* PNG_READ_iCCP_SUPPORTED */

#if defined(PNG_READ_sPLT_SUPPORTED)
1091
void /* PRIVATE */
1092 1093 1094 1095 1096
png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
/* Note: this does not properly handle chunks that are > 64K under DOS */
{
   png_bytep chunkdata;
   png_bytep entry_start;
1097
   png_sPLT_t new_palette;
1098 1099 1100
#ifdef PNG_NO_POINTER_INDEXING
   png_sPLT_entryp pp;
#endif
1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125
   int data_length, entry_size, i;
   png_uint_32 skip = 0;
   png_size_t slength;

   png_debug(1, "in png_handle_sPLT\n");

   if (!(png_ptr->mode & PNG_HAVE_IHDR))
      png_error(png_ptr, "Missing IHDR before sPLT");
   else if (png_ptr->mode & PNG_HAVE_IDAT)
   {
      png_warning(png_ptr, "Invalid sPLT after IDAT");
      png_crc_finish(png_ptr, length);
      return;
   }

#ifdef PNG_MAX_MALLOC_64K
   if (length > (png_uint_32)65535L)
   {
      png_warning(png_ptr, "sPLT chunk too large to fit in memory");
      skip = length - (png_uint_32)65535L;
      length = (png_uint_32)65535L;
   }
#endif

   chunkdata = (png_bytep)png_malloc(png_ptr, length + 1);
1126
   slength = (png_size_t)length;
1127
   png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144

   if (png_crc_finish(png_ptr, skip))
   {
      png_free(png_ptr, chunkdata);
      return;
   }

   chunkdata[slength] = 0x00;

   for (entry_start = chunkdata; *entry_start; entry_start++)
      /* empty loop to find end of name */ ;
   ++entry_start;

   /* a sample depth should follow the separator, and we should be on it  */
   if (entry_start > chunkdata + slength)
   {
      png_free(png_ptr, chunkdata);
1145 1146
      png_warning(png_ptr, "malformed sPLT chunk");
      return;
1147 1148 1149 1150 1151 1152 1153 1154 1155 1156
   }

   new_palette.depth = *entry_start++;
   entry_size = (new_palette.depth == 8 ? 6 : 10);
   data_length = (slength - (entry_start - chunkdata));

   /* integrity-check the data length */
   if (data_length % entry_size)
   {
      png_free(png_ptr, chunkdata);
1157 1158
      png_warning(png_ptr, "sPLT chunk has bad length");
      return;
1159 1160
   }

1161
   new_palette.nentries = (png_int_32) ( data_length / entry_size);
1162 1163
   if ((png_uint_32) new_palette.nentries > (png_uint_32) (PNG_SIZE_MAX /
       png_sizeof(png_sPLT_entry)))
1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174
   {
       png_warning(png_ptr, "sPLT chunk too long");
       return;
   }
   new_palette.entries = (png_sPLT_entryp)png_malloc_warn(
       png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry));
   if (new_palette.entries == NULL)
   {
       png_warning(png_ptr, "sPLT chunk requires too much memory");
       return;
   }
1175

1176
#ifndef PNG_NO_POINTER_INDEXING
1177 1178
   for (i = 0; i < new_palette.nentries; i++)
   {
1179
      png_sPLT_entryp pp = new_palette.entries + i;
1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196

      if (new_palette.depth == 8)
      {
          pp->red = *entry_start++;
          pp->green = *entry_start++;
          pp->blue = *entry_start++;
          pp->alpha = *entry_start++;
      }
      else
      {
          pp->red   = png_get_uint_16(entry_start); entry_start += 2;
          pp->green = png_get_uint_16(entry_start); entry_start += 2;
          pp->blue  = png_get_uint_16(entry_start); entry_start += 2;
          pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
      }
      pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
   }
1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218
#else
   pp = new_palette.entries;
   for (i = 0; i < new_palette.nentries; i++)
   {

      if (new_palette.depth == 8)
      {
          pp[i].red   = *entry_start++;
          pp[i].green = *entry_start++;
          pp[i].blue  = *entry_start++;
          pp[i].alpha = *entry_start++;
      }
      else
      {
          pp[i].red   = png_get_uint_16(entry_start); entry_start += 2;
          pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
          pp[i].blue  = png_get_uint_16(entry_start); entry_start += 2;
          pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
      }
      pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
   }
#endif
1219 1220 1221 1222

   /* discard all chunk data except the name and stash that */
   new_palette.name = (png_charp)chunkdata;

1223
   png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
1224 1225 1226 1227 1228 1229

   png_free(png_ptr, chunkdata);
   png_free(png_ptr, new_palette.entries);
}
#endif /* PNG_READ_sPLT_SUPPORTED */

G
Guy Schalnat 已提交
1230
#if defined(PNG_READ_tRNS_SUPPORTED)
1231
void /* PRIVATE */
A
Andreas Dilger 已提交
1232
png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
G
Guy Schalnat 已提交
1233
{
1234
   png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
1235

A
Andreas Dilger 已提交
1236 1237
   png_debug(1, "in png_handle_tRNS\n");

G
Guy Schalnat 已提交
1238 1239
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
      png_error(png_ptr, "Missing IHDR before tRNS");
A
Andreas Dilger 已提交
1240 1241 1242 1243 1244 1245
   else if (png_ptr->mode & PNG_HAVE_IDAT)
   {
      png_warning(png_ptr, "Invalid tRNS after IDAT");
      png_crc_finish(png_ptr, length);
      return;
   }
1246
   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
A
Andreas Dilger 已提交
1247
   {
1248
      png_warning(png_ptr, "Duplicate tRNS chunk");
A
Andreas Dilger 已提交
1249 1250 1251
      png_crc_finish(png_ptr, length);
      return;
   }
G
Guy Schalnat 已提交
1252

1253
   if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
G
Guy Schalnat 已提交
1254
   {
1255 1256 1257
      png_byte buf[2];

      if (length != 2)
G
Guy Schalnat 已提交
1258
      {
G
Guy Schalnat 已提交
1259
         png_warning(png_ptr, "Incorrect tRNS chunk length");
A
Andreas Dilger 已提交
1260
         png_crc_finish(png_ptr, length);
G
Guy Schalnat 已提交
1261 1262 1263
         return;
      }

1264 1265 1266
      png_crc_read(png_ptr, buf, 2);
      png_ptr->num_trans = 1;
      png_ptr->trans_values.gray = png_get_uint_16(buf);
G
Guy Schalnat 已提交
1267 1268 1269 1270 1271 1272 1273
   }
   else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
   {
      png_byte buf[6];

      if (length != 6)
      {
G
Guy Schalnat 已提交
1274
         png_warning(png_ptr, "Incorrect tRNS chunk length");
A
Andreas Dilger 已提交
1275
         png_crc_finish(png_ptr, length);
G
Guy Schalnat 已提交
1276 1277
         return;
      }
A
Andreas Dilger 已提交
1278
      png_crc_read(png_ptr, buf, (png_size_t)length);
1279
      png_ptr->num_trans = 1;
G
Guy Schalnat 已提交
1280 1281 1282 1283
      png_ptr->trans_values.red = png_get_uint_16(buf);
      png_ptr->trans_values.green = png_get_uint_16(buf + 2);
      png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
   }
1284
   else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
1285
   {
1286 1287 1288 1289 1290 1291 1292
      if (!(png_ptr->mode & PNG_HAVE_PLTE))
      {
         /* Should be an error, but we can cope with it. */
         png_warning(png_ptr, "Missing PLTE before tRNS");
      }
      if (length > (png_uint_32)png_ptr->num_palette ||
          length > PNG_MAX_PALETTE_LENGTH)
G
Guy Schalnat 已提交
1293
      {
G
Guy Schalnat 已提交
1294
         png_warning(png_ptr, "Incorrect tRNS chunk length");
A
Andreas Dilger 已提交
1295
         png_crc_finish(png_ptr, length);
G
Guy Schalnat 已提交
1296 1297
         return;
      }
1298 1299 1300 1301 1302 1303 1304 1305
      if (length == 0)
      {
         png_warning(png_ptr, "Zero length tRNS chunk");
         png_crc_finish(png_ptr, length);
         return;
      }
      png_crc_read(png_ptr, readbuf, (png_size_t)length);
      png_ptr->num_trans = (png_uint_16)length;
G
Guy Schalnat 已提交
1306 1307
   }
   else
G
Guy Schalnat 已提交
1308 1309
   {
      png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
A
Andreas Dilger 已提交
1310
      png_crc_finish(png_ptr, length);
G
Guy Schalnat 已提交
1311 1312
      return;
   }
G
Guy Schalnat 已提交
1313

A
Andreas Dilger 已提交
1314 1315 1316
   if (png_crc_finish(png_ptr, 0))
      return;

1317
   png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
G
Guy Schalnat 已提交
1318 1319
      &(png_ptr->trans_values));
}
G
Guy Schalnat 已提交
1320
#endif
G
Guy Schalnat 已提交
1321

G
Guy Schalnat 已提交
1322
#if defined(PNG_READ_bKGD_SUPPORTED)
1323
void /* PRIVATE */
A
Andreas Dilger 已提交
1324
png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
G
Guy Schalnat 已提交
1325
{
A
Andreas Dilger 已提交
1326
   png_size_t truelen;
G
Guy Schalnat 已提交
1327 1328
   png_byte buf[6];

A
Andreas Dilger 已提交
1329 1330
   png_debug(1, "in png_handle_bKGD\n");

G
Guy Schalnat 已提交
1331 1332
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
      png_error(png_ptr, "Missing IHDR before bKGD");
A
Andreas Dilger 已提交
1333 1334 1335 1336 1337 1338
   else if (png_ptr->mode & PNG_HAVE_IDAT)
   {
      png_warning(png_ptr, "Invalid bKGD after IDAT");
      png_crc_finish(png_ptr, length);
      return;
   }
G
Guy Schalnat 已提交
1339 1340 1341 1342
   else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
            !(png_ptr->mode & PNG_HAVE_PLTE))
   {
      png_warning(png_ptr, "Missing PLTE before bKGD");
A
Andreas Dilger 已提交
1343 1344 1345
      png_crc_finish(png_ptr, length);
      return;
   }
1346
   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
A
Andreas Dilger 已提交
1347 1348 1349
   {
      png_warning(png_ptr, "Duplicate bKGD chunk");
      png_crc_finish(png_ptr, length);
G
Guy Schalnat 已提交
1350 1351 1352
      return;
   }

G
Guy Schalnat 已提交
1353 1354 1355 1356 1357 1358 1359
   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
      truelen = 1;
   else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
      truelen = 6;
   else
      truelen = 2;

A
Andreas Dilger 已提交
1360
   if (length != truelen)
G
Guy Schalnat 已提交
1361
   {
G
Guy Schalnat 已提交
1362
      png_warning(png_ptr, "Incorrect bKGD chunk length");
A
Andreas Dilger 已提交
1363
      png_crc_finish(png_ptr, length);
G
Guy Schalnat 已提交
1364 1365 1366
      return;
   }

A
Andreas Dilger 已提交
1367
   png_crc_read(png_ptr, buf, truelen);
A
Andreas Dilger 已提交
1368 1369 1370
   if (png_crc_finish(png_ptr, 0))
      return;

G
Guy Schalnat 已提交
1371 1372 1373
   /* We convert the index value into RGB components so that we can allow
    * arbitrary RGB values for background when we have transparency, and
    * so it is easy to determine the RGB values of the background color
A
Andreas Dilger 已提交
1374
    * from the info_ptr struct. */
G
Guy Schalnat 已提交
1375
   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
G
Guy Schalnat 已提交
1376
   {
G
Guy Schalnat 已提交
1377
      png_ptr->background.index = buf[0];
1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391
      if(info_ptr->num_palette)
      {
          if(buf[0] > info_ptr->num_palette)
          {
             png_warning(png_ptr, "Incorrect bKGD chunk index value");
             return;
          }
          png_ptr->background.red =
             (png_uint_16)png_ptr->palette[buf[0]].red;
          png_ptr->background.green =
             (png_uint_16)png_ptr->palette[buf[0]].green;
          png_ptr->background.blue =
             (png_uint_16)png_ptr->palette[buf[0]].blue;
      }
G
Guy Schalnat 已提交
1392
   }
A
Andreas Dilger 已提交
1393
   else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
G
Guy Schalnat 已提交
1394 1395 1396 1397
   {
      png_ptr->background.red =
      png_ptr->background.green =
      png_ptr->background.blue =
G
Guy Schalnat 已提交
1398
      png_ptr->background.gray = png_get_uint_16(buf);
G
Guy Schalnat 已提交
1399
   }
G
Guy Schalnat 已提交
1400 1401 1402 1403 1404 1405 1406
   else
   {
      png_ptr->background.red = png_get_uint_16(buf);
      png_ptr->background.green = png_get_uint_16(buf + 2);
      png_ptr->background.blue = png_get_uint_16(buf + 4);
   }

A
Andreas Dilger 已提交
1407
   png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
G
Guy Schalnat 已提交
1408
}
G
Guy Schalnat 已提交
1409
#endif
G
Guy Schalnat 已提交
1410

G
Guy Schalnat 已提交
1411
#if defined(PNG_READ_hIST_SUPPORTED)
1412
void /* PRIVATE */
A
Andreas Dilger 已提交
1413
png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
G
Guy Schalnat 已提交
1414
{
1415
   unsigned int num, i;
1416
   png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
G
Guy Schalnat 已提交
1417

A
Andreas Dilger 已提交
1418 1419
   png_debug(1, "in png_handle_hIST\n");

G
Guy Schalnat 已提交
1420 1421
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
      png_error(png_ptr, "Missing IHDR before hIST");
A
Andreas Dilger 已提交
1422 1423 1424 1425 1426 1427
   else if (png_ptr->mode & PNG_HAVE_IDAT)
   {
      png_warning(png_ptr, "Invalid hIST after IDAT");
      png_crc_finish(png_ptr, length);
      return;
   }
G
Guy Schalnat 已提交
1428 1429 1430
   else if (!(png_ptr->mode & PNG_HAVE_PLTE))
   {
      png_warning(png_ptr, "Missing PLTE before hIST");
A
Andreas Dilger 已提交
1431 1432 1433
      png_crc_finish(png_ptr, length);
      return;
   }
1434
   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
A
Andreas Dilger 已提交
1435 1436 1437
   {
      png_warning(png_ptr, "Duplicate hIST chunk");
      png_crc_finish(png_ptr, length);
G
Guy Schalnat 已提交
1438 1439 1440
      return;
   }

1441
   num = length / 2 ;
1442 1443
   if (num != (unsigned int) png_ptr->num_palette || num >
      (unsigned int) PNG_MAX_PALETTE_LENGTH)
G
Guy Schalnat 已提交
1444 1445
   {
      png_warning(png_ptr, "Incorrect hIST chunk length");
A
Andreas Dilger 已提交
1446
      png_crc_finish(png_ptr, length);
G
Guy Schalnat 已提交
1447 1448
      return;
   }
G
Guy Schalnat 已提交
1449

G
Guy Schalnat 已提交
1450
   for (i = 0; i < num; i++)
G
Guy Schalnat 已提交
1451 1452 1453 1454
   {
      png_byte buf[2];

      png_crc_read(png_ptr, buf, 2);
1455
      readbuf[i] = png_get_uint_16(buf);
G
Guy Schalnat 已提交
1456
   }
A
Andreas Dilger 已提交
1457 1458 1459 1460

   if (png_crc_finish(png_ptr, 0))
      return;

1461
   png_set_hIST(png_ptr, info_ptr, readbuf);
G
Guy Schalnat 已提交
1462
}
G
Guy Schalnat 已提交
1463
#endif
G
Guy Schalnat 已提交
1464

G
Guy Schalnat 已提交
1465
#if defined(PNG_READ_pHYs_SUPPORTED)
1466
void /* PRIVATE */
A
Andreas Dilger 已提交
1467
png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
G
Guy Schalnat 已提交
1468 1469 1470 1471 1472
{
   png_byte buf[9];
   png_uint_32 res_x, res_y;
   int unit_type;

A
Andreas Dilger 已提交
1473 1474
   png_debug(1, "in png_handle_pHYs\n");

G
Guy Schalnat 已提交
1475
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
1476
      png_error(png_ptr, "Missing IHDR before pHYs");
A
Andreas Dilger 已提交
1477 1478
   else if (png_ptr->mode & PNG_HAVE_IDAT)
   {
1479
      png_warning(png_ptr, "Invalid pHYs after IDAT");
A
Andreas Dilger 已提交
1480 1481 1482
      png_crc_finish(png_ptr, length);
      return;
   }
1483
   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
A
Andreas Dilger 已提交
1484
   {
1485
      png_warning(png_ptr, "Duplicate pHYs chunk");
A
Andreas Dilger 已提交
1486 1487 1488
      png_crc_finish(png_ptr, length);
      return;
   }
G
Guy Schalnat 已提交
1489

G
Guy Schalnat 已提交
1490 1491
   if (length != 9)
   {
G
Guy Schalnat 已提交
1492
      png_warning(png_ptr, "Incorrect pHYs chunk length");
A
Andreas Dilger 已提交
1493
      png_crc_finish(png_ptr, length);
G
Guy Schalnat 已提交
1494
      return;
G
Guy Schalnat 已提交
1495
   }
G
Guy Schalnat 已提交
1496 1497

   png_crc_read(png_ptr, buf, 9);
A
Andreas Dilger 已提交
1498 1499
   if (png_crc_finish(png_ptr, 0))
      return;
G
Guy Schalnat 已提交
1500 1501 1502 1503

   res_x = png_get_uint_32(buf);
   res_y = png_get_uint_32(buf + 4);
   unit_type = buf[8];
A
Andreas Dilger 已提交
1504
   png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
G
Guy Schalnat 已提交
1505
}
G
Guy Schalnat 已提交
1506
#endif
G
Guy Schalnat 已提交
1507

G
Guy Schalnat 已提交
1508
#if defined(PNG_READ_oFFs_SUPPORTED)
1509
void /* PRIVATE */
A
Andreas Dilger 已提交
1510
png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
G
Guy Schalnat 已提交
1511 1512
{
   png_byte buf[9];
1513
   png_int_32 offset_x, offset_y;
G
Guy Schalnat 已提交
1514 1515
   int unit_type;

A
Andreas Dilger 已提交
1516 1517
   png_debug(1, "in png_handle_oFFs\n");

G
Guy Schalnat 已提交
1518 1519
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
      png_error(png_ptr, "Missing IHDR before oFFs");
A
Andreas Dilger 已提交
1520 1521 1522 1523 1524 1525
   else if (png_ptr->mode & PNG_HAVE_IDAT)
   {
      png_warning(png_ptr, "Invalid oFFs after IDAT");
      png_crc_finish(png_ptr, length);
      return;
   }
1526
   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
A
Andreas Dilger 已提交
1527 1528 1529 1530 1531
   {
      png_warning(png_ptr, "Duplicate oFFs chunk");
      png_crc_finish(png_ptr, length);
      return;
   }
G
Guy Schalnat 已提交
1532

G
Guy Schalnat 已提交
1533 1534
   if (length != 9)
   {
G
Guy Schalnat 已提交
1535
      png_warning(png_ptr, "Incorrect oFFs chunk length");
A
Andreas Dilger 已提交
1536
      png_crc_finish(png_ptr, length);
G
Guy Schalnat 已提交
1537 1538 1539
      return;
   }

G
Guy Schalnat 已提交
1540
   png_crc_read(png_ptr, buf, 9);
A
Andreas Dilger 已提交
1541 1542
   if (png_crc_finish(png_ptr, 0))
      return;
G
Guy Schalnat 已提交
1543

1544 1545
   offset_x = png_get_int_32(buf);
   offset_y = png_get_int_32(buf + 4);
G
Guy Schalnat 已提交
1546
   unit_type = buf[8];
A
Andreas Dilger 已提交
1547 1548 1549 1550 1551
   png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
}
#endif

#if defined(PNG_READ_pCAL_SUPPORTED)
1552
/* read the pCAL chunk (described in the PNG Extensions document) */
1553
void /* PRIVATE */
A
Andreas Dilger 已提交
1554 1555 1556 1557 1558 1559 1560
png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
{
   png_charp purpose;
   png_int_32 X0, X1;
   png_byte type, nparams;
   png_charp buf, units, endptr;
   png_charpp params;
1561
   png_size_t slength;
A
Andreas Dilger 已提交
1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573
   int i;

   png_debug(1, "in png_handle_pCAL\n");

   if (!(png_ptr->mode & PNG_HAVE_IHDR))
      png_error(png_ptr, "Missing IHDR before pCAL");
   else if (png_ptr->mode & PNG_HAVE_IDAT)
   {
      png_warning(png_ptr, "Invalid pCAL after IDAT");
      png_crc_finish(png_ptr, length);
      return;
   }
1574
   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
A
Andreas Dilger 已提交
1575 1576 1577 1578 1579 1580
   {
      png_warning(png_ptr, "Duplicate pCAL chunk");
      png_crc_finish(png_ptr, length);
      return;
   }

1581
   png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)\n",
A
Andreas Dilger 已提交
1582
      length + 1);
1583 1584 1585 1586 1587 1588
   purpose = (png_charp)png_malloc_warn(png_ptr, length + 1);
   if (purpose == NULL)
     {
       png_warning(png_ptr, "No memory for pCAL purpose.");
       return;
     }
1589 1590
   slength = (png_size_t)length;
   png_crc_read(png_ptr, (png_bytep)purpose, slength);
A
Andreas Dilger 已提交
1591 1592 1593 1594 1595 1596 1597

   if (png_crc_finish(png_ptr, 0))
   {
      png_free(png_ptr, purpose);
      return;
   }

1598
   purpose[slength] = 0x00; /* null terminate the last string */
A
Andreas Dilger 已提交
1599 1600

   png_debug(3, "Finding end of pCAL purpose string\n");
1601
   for (buf = purpose; *buf; buf++)
1602
      /* empty loop */ ;
A
Andreas Dilger 已提交
1603

1604
   endptr = purpose + slength;
A
Andreas Dilger 已提交
1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638

   /* We need to have at least 12 bytes after the purpose string
      in order to get the parameter information. */
   if (endptr <= buf + 12)
   {
      png_warning(png_ptr, "Invalid pCAL data");
      png_free(png_ptr, purpose);
      return;
   }

   png_debug(3, "Reading pCAL X0, X1, type, nparams, and units\n");
   X0 = png_get_int_32((png_bytep)buf+1);
   X1 = png_get_int_32((png_bytep)buf+5);
   type = buf[9];
   nparams = buf[10];
   units = buf + 11;

   png_debug(3, "Checking pCAL equation type and number of parameters\n");
   /* Check that we have the right number of parameters for known
      equation types. */
   if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
       (type == PNG_EQUATION_BASE_E && nparams != 3) ||
       (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
       (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
   {
      png_warning(png_ptr, "Invalid pCAL parameters for equation type");
      png_free(png_ptr, purpose);
      return;
   }
   else if (type >= PNG_EQUATION_LAST)
   {
      png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
   }

1639
   for (buf = units; *buf; buf++)
1640
      /* Empty loop to move past the units string. */ ;
A
Andreas Dilger 已提交
1641 1642

   png_debug(3, "Allocating pCAL parameters array\n");
1643
   params = (png_charpp)png_malloc_warn(png_ptr, (png_uint_32)(nparams
1644
      *png_sizeof(png_charp))) ;
1645 1646 1647 1648 1649 1650
   if (params == NULL)
     {
       png_free(png_ptr, purpose);
       png_warning(png_ptr, "No memory for pCAL params.");
       return;
     }
A
Andreas Dilger 已提交
1651 1652

   /* Get pointers to the start of each parameter string. */
1653
   for (i = 0; i < (int)nparams; i++)
A
Andreas Dilger 已提交
1654 1655 1656 1657
   {
      buf++; /* Skip the null string terminator from previous parameter. */

      png_debug1(3, "Reading pCAL parameter %d\n", i);
1658
      for (params[i] = buf; *buf != 0x00 && buf <= endptr; buf++)
1659
         /* Empty loop to move past each parameter string */ ;
A
Andreas Dilger 已提交
1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675

      /* Make sure we haven't run out of data yet */
      if (buf > endptr)
      {
         png_warning(png_ptr, "Invalid pCAL data");
         png_free(png_ptr, purpose);
         png_free(png_ptr, params);
         return;
      }
   }

   png_set_pCAL(png_ptr, info_ptr, purpose, X0, X1, type, nparams,
      units, params);

   png_free(png_ptr, purpose);
   png_free(png_ptr, params);
G
Guy Schalnat 已提交
1676
}
G
Guy Schalnat 已提交
1677
#endif
G
Guy Schalnat 已提交
1678

1679 1680
#if defined(PNG_READ_sCAL_SUPPORTED)
/* read the sCAL chunk */
1681
void /* PRIVATE */
1682 1683
png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
{
1684
   png_charp buffer, ep;
1685
#ifdef PNG_FLOATING_POINT_SUPPORTED
1686
   double width, height;
1687
   png_charp vp;
1688 1689 1690 1691
#else
#ifdef PNG_FIXED_POINT_SUPPORTED
   png_charp swidth, sheight;
#endif
1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704
#endif
   png_size_t slength;

   png_debug(1, "in png_handle_sCAL\n");

   if (!(png_ptr->mode & PNG_HAVE_IHDR))
      png_error(png_ptr, "Missing IHDR before sCAL");
   else if (png_ptr->mode & PNG_HAVE_IDAT)
   {
      png_warning(png_ptr, "Invalid sCAL after IDAT");
      png_crc_finish(png_ptr, length);
      return;
   }
1705
   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
1706 1707 1708 1709 1710 1711
   {
      png_warning(png_ptr, "Duplicate sCAL chunk");
      png_crc_finish(png_ptr, length);
      return;
   }

1712
   png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)\n",
1713
      length + 1);
1714 1715 1716 1717 1718 1719
   buffer = (png_charp)png_malloc_warn(png_ptr, length + 1);
   if (buffer == NULL)
     {
       png_warning(png_ptr, "Out of memory while processing sCAL chunk");
       return;
     }
1720
   slength = (png_size_t)length;
1721
   png_crc_read(png_ptr, (png_bytep)buffer, slength);
1722 1723 1724

   if (png_crc_finish(png_ptr, 0))
   {
1725
      png_free(png_ptr, buffer);
1726 1727 1728
      return;
   }

1729
   buffer[slength] = 0x00; /* null terminate the last string */
1730

1731
   ep = buffer + 1;        /* skip unit byte */
1732 1733 1734 1735

#ifdef PNG_FLOATING_POINT_SUPPORTED
   width = strtod(ep, &vp);
   if (*vp)
1736 1737 1738 1739
   {
       png_warning(png_ptr, "malformed width string in sCAL chunk");
       return;
   }
1740 1741
#else
#ifdef PNG_FIXED_POINT_SUPPORTED
1742 1743 1744 1745 1746 1747
   swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
   if (swidth == NULL)
     {
       png_warning(png_ptr, "Out of memory while processing sCAL chunk width");
       return;
     }
1748
   png_memcpy(swidth, ep, (png_size_t)png_strlen(ep));
1749 1750
#endif
#endif
1751

1752
   for (ep = buffer; *ep; ep++)
1753 1754 1755 1756 1757 1758
      /* empty loop */ ;
   ep++;

#ifdef PNG_FLOATING_POINT_SUPPORTED
   height = strtod(ep, &vp);
   if (*vp)
1759 1760 1761 1762
   {
       png_warning(png_ptr, "malformed height string in sCAL chunk");
       return;
   }
1763 1764
#else
#ifdef PNG_FIXED_POINT_SUPPORTED
1765 1766 1767 1768 1769 1770
   sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
   if (swidth == NULL)
     {
       png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
       return;
     }
1771
   png_memcpy(sheight, ep, (png_size_t)png_strlen(ep));
1772 1773
#endif
#endif
1774

1775
   if (buffer + slength < ep
1776 1777 1778 1779 1780 1781
#ifdef PNG_FLOATING_POINT_SUPPORTED
      || width <= 0. || height <= 0.
#endif
      )
   {
      png_warning(png_ptr, "Invalid sCAL data");
1782 1783
      png_free(png_ptr, buffer);
#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1784 1785
      png_free(png_ptr, swidth);
      png_free(png_ptr, sheight);
1786
#endif
1787 1788 1789 1790 1791
      return;
   }


#ifdef PNG_FLOATING_POINT_SUPPORTED
1792 1793
   png_set_sCAL(png_ptr, info_ptr, buffer[0], width, height);
#else
1794
#ifdef PNG_FIXED_POINT_SUPPORTED
1795 1796
   png_set_sCAL_s(png_ptr, info_ptr, buffer[0], swidth, sheight);
#endif
1797 1798
#endif

1799 1800 1801 1802 1803
   png_free(png_ptr, buffer);
#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
   png_free(png_ptr, swidth);
   png_free(png_ptr, sheight);
#endif
1804 1805 1806
}
#endif

G
Guy Schalnat 已提交
1807
#if defined(PNG_READ_tIME_SUPPORTED)
1808
void /* PRIVATE */
A
Andreas Dilger 已提交
1809
png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
G
Guy Schalnat 已提交
1810 1811 1812 1813
{
   png_byte buf[7];
   png_time mod_time;

A
Andreas Dilger 已提交
1814 1815
   png_debug(1, "in png_handle_tIME\n");

G
Guy Schalnat 已提交
1816
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
A
Andreas Dilger 已提交
1817
      png_error(png_ptr, "Out of place tIME chunk");
1818
   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
A
Andreas Dilger 已提交
1819 1820 1821 1822 1823 1824 1825 1826
   {
      png_warning(png_ptr, "Duplicate tIME chunk");
      png_crc_finish(png_ptr, length);
      return;
   }

   if (png_ptr->mode & PNG_HAVE_IDAT)
      png_ptr->mode |= PNG_AFTER_IDAT;
G
Guy Schalnat 已提交
1827

G
Guy Schalnat 已提交
1828 1829
   if (length != 7)
   {
G
Guy Schalnat 已提交
1830
      png_warning(png_ptr, "Incorrect tIME chunk length");
A
Andreas Dilger 已提交
1831
      png_crc_finish(png_ptr, length);
G
Guy Schalnat 已提交
1832 1833 1834 1835
      return;
   }

   png_crc_read(png_ptr, buf, 7);
A
Andreas Dilger 已提交
1836 1837
   if (png_crc_finish(png_ptr, 0))
      return;
G
Guy Schalnat 已提交
1838 1839 1840 1841 1842 1843

   mod_time.second = buf[6];
   mod_time.minute = buf[5];
   mod_time.hour = buf[4];
   mod_time.day = buf[3];
   mod_time.month = buf[2];
G
Guy Schalnat 已提交
1844
   mod_time.year = png_get_uint_16(buf);
G
Guy Schalnat 已提交
1845

A
Andreas Dilger 已提交
1846
   png_set_tIME(png_ptr, info_ptr, &mod_time);
G
Guy Schalnat 已提交
1847
}
G
Guy Schalnat 已提交
1848
#endif
G
Guy Schalnat 已提交
1849

G
Guy Schalnat 已提交
1850
#if defined(PNG_READ_tEXt_SUPPORTED)
A
Andreas Dilger 已提交
1851
/* Note: this does not properly handle chunks that are > 64K under DOS */
1852
void /* PRIVATE */
A
Andreas Dilger 已提交
1853
png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
G
Guy Schalnat 已提交
1854
{
A
Andreas Dilger 已提交
1855
   png_textp text_ptr;
G
Guy Schalnat 已提交
1856
   png_charp key;
G
Guy Schalnat 已提交
1857
   png_charp text;
A
Andreas Dilger 已提交
1858
   png_uint_32 skip = 0;
1859
   png_size_t slength;
1860
   int ret;
A
Andreas Dilger 已提交
1861 1862

   png_debug(1, "in png_handle_tEXt\n");
G
Guy Schalnat 已提交
1863

G
Guy Schalnat 已提交
1864 1865 1866
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
      png_error(png_ptr, "Missing IHDR before tEXt");

A
Andreas Dilger 已提交
1867 1868 1869
   if (png_ptr->mode & PNG_HAVE_IDAT)
      png_ptr->mode |= PNG_AFTER_IDAT;

A
Andreas Dilger 已提交
1870
#ifdef PNG_MAX_MALLOC_64K
1871
   if (length > (png_uint_32)65535L)
A
Andreas Dilger 已提交
1872 1873
   {
      png_warning(png_ptr, "tEXt chunk too large to fit in memory");
1874 1875
      skip = length - (png_uint_32)65535L;
      length = (png_uint_32)65535L;
A
Andreas Dilger 已提交
1876 1877 1878
   }
#endif

1879 1880 1881 1882 1883 1884
   key = (png_charp)png_malloc_warn(png_ptr, length + 1);
   if (key == NULL)
   {
     png_warning(png_ptr, "No memory to process text chunk.");
     return;
   }
1885
   slength = (png_size_t)length;
1886
   png_crc_read(png_ptr, (png_bytep)key, slength);
A
Andreas Dilger 已提交
1887 1888

   if (png_crc_finish(png_ptr, skip))
A
Andreas Dilger 已提交
1889 1890 1891 1892 1893
   {
      png_free(png_ptr, key);
      return;
   }

1894
   key[slength] = 0x00;
G
Guy Schalnat 已提交
1895 1896

   for (text = key; *text; text++)
A
Andreas Dilger 已提交
1897
      /* empty loop to find end of key */ ;
G
Guy Schalnat 已提交
1898

1899
   if (text != key + slength)
G
Guy Schalnat 已提交
1900 1901
      text++;

1902 1903
   text_ptr = (png_textp)png_malloc_warn(png_ptr,
      (png_uint_32)png_sizeof(png_text));
1904 1905 1906 1907 1908 1909
   if (text_ptr == NULL)
   {
     png_warning(png_ptr, "Not enough memory to process text chunk.");
     png_free(png_ptr, key);
     return;
   }
A
Andreas Dilger 已提交
1910 1911
   text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
   text_ptr->key = key;
1912
#ifdef PNG_iTXt_SUPPORTED
1913 1914
   text_ptr->lang = NULL;
   text_ptr->lang_key = NULL;
1915 1916
   text_ptr->itxt_length = 0;
#endif
A
Andreas Dilger 已提交
1917
   text_ptr->text = text;
1918
   text_ptr->text_length = png_strlen(text);
A
Andreas Dilger 已提交
1919

1920
   ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
A
Andreas Dilger 已提交
1921

1922
   png_free(png_ptr, key);
1923
   png_free(png_ptr, text_ptr);
1924 1925
   if (ret)
     png_warning(png_ptr, "Insufficient memory to process text chunk.");
G
Guy Schalnat 已提交
1926
}
G
Guy Schalnat 已提交
1927
#endif
G
Guy Schalnat 已提交
1928

G
Guy Schalnat 已提交
1929
#if defined(PNG_READ_zTXt_SUPPORTED)
A
Andreas Dilger 已提交
1930
/* note: this does not correctly handle chunks that are > 64K under DOS */
1931
void /* PRIVATE */
A
Andreas Dilger 已提交
1932
png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
G
Guy Schalnat 已提交
1933
{
A
Andreas Dilger 已提交
1934
   png_textp text_ptr;
1935
   png_charp chunkdata;
G
Guy Schalnat 已提交
1936
   png_charp text;
1937
   int comp_type;
1938
   int ret;
1939
   png_size_t slength, prefix_len, data_len;
A
Andreas Dilger 已提交
1940 1941

   png_debug(1, "in png_handle_zTXt\n");
G
Guy Schalnat 已提交
1942 1943 1944
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
      png_error(png_ptr, "Missing IHDR before zTXt");

A
Andreas Dilger 已提交
1945 1946 1947
   if (png_ptr->mode & PNG_HAVE_IDAT)
      png_ptr->mode |= PNG_AFTER_IDAT;

A
Andreas Dilger 已提交
1948 1949 1950
#ifdef PNG_MAX_MALLOC_64K
   /* We will no doubt have problems with chunks even half this size, but
      there is no hard and fast rule to tell us where to stop. */
1951
   if (length > (png_uint_32)65535L)
A
Andreas Dilger 已提交
1952 1953 1954 1955 1956 1957 1958
   {
     png_warning(png_ptr,"zTXt chunk too large to fit in memory");
     png_crc_finish(png_ptr, length);
     return;
   }
#endif

1959 1960 1961 1962 1963 1964 1965
   chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
   if (chunkdata == NULL)
   {
     png_warning(png_ptr,"Out of memory processing zTXt chunk.");
     return;
   }
   slength = (png_size_t)length;
1966
   png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
A
Andreas Dilger 已提交
1967 1968
   if (png_crc_finish(png_ptr, 0))
   {
1969
      png_free(png_ptr, chunkdata);
A
Andreas Dilger 已提交
1970 1971 1972
      return;
   }

1973
   chunkdata[slength] = 0x00;
G
Guy Schalnat 已提交
1974

1975
   for (text = chunkdata; *text; text++)
G
Guy Schalnat 已提交
1976 1977
      /* empty loop */ ;

1978 1979
   /* zTXt must have some text after the chunkdataword */
   if (text == chunkdata + slength)
G
Guy Schalnat 已提交
1980
   {
1981
      comp_type = PNG_TEXT_COMPRESSION_NONE;
G
Guy Schalnat 已提交
1982
      png_warning(png_ptr, "Zero length zTXt chunk");
G
Guy Schalnat 已提交
1983
   }
1984
   else
G
Guy Schalnat 已提交
1985
   {
1986
       comp_type = *(++text);
1987 1988 1989 1990 1991
       if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
       {
          png_warning(png_ptr, "Unknown compression type in zTXt chunk");
          comp_type = PNG_TEXT_COMPRESSION_zTXt;
       }
1992
       text++;        /* skip the compression_method byte */
1993 1994
   }
   prefix_len = text - chunkdata;
G
Guy Schalnat 已提交
1995

1996
   chunkdata = (png_charp)png_decompress_chunk(png_ptr, comp_type, chunkdata,
1997
                                    (png_size_t)length, prefix_len, &data_len);
G
Guy Schalnat 已提交
1998

1999 2000
   text_ptr = (png_textp)png_malloc_warn(png_ptr,
     (png_uint_32)png_sizeof(png_text));
2001 2002 2003 2004 2005 2006
   if (text_ptr == NULL)
   {
     png_warning(png_ptr,"Not enough memory to process zTXt chunk.");
     png_free(png_ptr, chunkdata);
     return;
   }
2007 2008
   text_ptr->compression = comp_type;
   text_ptr->key = chunkdata;
2009
#ifdef PNG_iTXt_SUPPORTED
2010 2011 2012
   text_ptr->lang = NULL;
   text_ptr->lang_key = NULL;
   text_ptr->itxt_length = 0;
2013
#endif
2014 2015
   text_ptr->text = chunkdata + prefix_len;
   text_ptr->text_length = data_len;
G
Guy Schalnat 已提交
2016

2017
   ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
G
Guy Schalnat 已提交
2018

2019
   png_free(png_ptr, text_ptr);
2020
   png_free(png_ptr, chunkdata);
2021 2022
   if (ret)
     png_error(png_ptr, "Insufficient memory to store zTXt chunk.");
2023 2024
}
#endif
G
Guy Schalnat 已提交
2025

2026 2027
#if defined(PNG_READ_iTXt_SUPPORTED)
/* note: this does not correctly handle chunks that are > 64K under DOS */
2028
void /* PRIVATE */
2029 2030 2031 2032
png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
{
   png_textp text_ptr;
   png_charp chunkdata;
2033
   png_charp key, lang, text, lang_key;
2034
   int comp_flag;
2035
   int comp_type = 0;
2036
   int ret;
2037
   png_size_t slength, prefix_len, data_len;
G
Guy Schalnat 已提交
2038

2039
   png_debug(1, "in png_handle_iTXt\n");
G
Guy Schalnat 已提交
2040

2041 2042
   if (!(png_ptr->mode & PNG_HAVE_IHDR))
      png_error(png_ptr, "Missing IHDR before iTXt");
G
Guy Schalnat 已提交
2043

2044 2045
   if (png_ptr->mode & PNG_HAVE_IDAT)
      png_ptr->mode |= PNG_AFTER_IDAT;
G
Guy Schalnat 已提交
2046

2047 2048 2049 2050 2051 2052 2053 2054
#ifdef PNG_MAX_MALLOC_64K
   /* We will no doubt have problems with chunks even half this size, but
      there is no hard and fast rule to tell us where to stop. */
   if (length > (png_uint_32)65535L)
   {
     png_warning(png_ptr,"iTXt chunk too large to fit in memory");
     png_crc_finish(png_ptr, length);
     return;
G
Guy Schalnat 已提交
2055
   }
2056 2057
#endif

2058 2059 2060 2061 2062 2063
   chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
   if (chunkdata == NULL)
   {
     png_warning(png_ptr, "No memory to process iTXt chunk.");
     return;
   }
2064 2065
   slength = (png_size_t)length;
   png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
2066
   if (png_crc_finish(png_ptr, 0))
A
Andreas Dilger 已提交
2067
   {
2068 2069 2070
      png_free(png_ptr, chunkdata);
      return;
   }
A
Andreas Dilger 已提交
2071

2072
   chunkdata[slength] = 0x00;
A
Andreas Dilger 已提交
2073

2074 2075 2076 2077
   for (lang = chunkdata; *lang; lang++)
      /* empty loop */ ;
   lang++;        /* skip NUL separator */

2078 2079 2080 2081
   /* iTXt must have a language tag (possibly empty), two compression bytes,
      translated keyword (possibly empty), and possibly some text after the
      keyword */

2082 2083
   if (lang >= chunkdata + slength)
   {
2084
      comp_flag = PNG_TEXT_COMPRESSION_NONE;
2085
      png_warning(png_ptr, "Zero length iTXt chunk");
A
Andreas Dilger 已提交
2086
   }
2087 2088 2089 2090 2091 2092
   else
   {
       comp_flag = *lang++;
       comp_type = *lang++;
   }

2093 2094 2095 2096 2097
   for (lang_key = lang; *lang_key; lang_key++)
      /* empty loop */ ;
   lang_key++;        /* skip NUL separator */

   for (text = lang_key; *text; text++)
2098 2099 2100 2101 2102
      /* empty loop */ ;
   text++;        /* skip NUL separator */

   prefix_len = text - chunkdata;

2103
   key=chunkdata;
2104 2105
   if (comp_flag)
       chunkdata = png_decompress_chunk(png_ptr, comp_type, chunkdata,
2106 2107 2108
          (size_t)length, prefix_len, &data_len);
   else
       data_len=png_strlen(chunkdata + prefix_len);
2109 2110
   text_ptr = (png_textp)png_malloc_warn(png_ptr,
      (png_uint_32)png_sizeof(png_text));
2111 2112 2113 2114 2115 2116
   if (text_ptr == NULL)
   {
     png_warning(png_ptr,"Not enough memory to process iTXt chunk.");
     png_free(png_ptr, chunkdata);
     return;
   }
2117 2118 2119 2120 2121 2122 2123
   text_ptr->compression = (int)comp_flag + 1;
   text_ptr->lang_key = chunkdata+(lang_key-key);
   text_ptr->lang = chunkdata+(lang-key);
   text_ptr->itxt_length = data_len;
   text_ptr->text_length = 0;
   text_ptr->key = chunkdata;
   text_ptr->text = chunkdata + prefix_len;
G
Guy Schalnat 已提交
2124

2125
   ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
A
Andreas Dilger 已提交
2126

2127
   png_free(png_ptr, text_ptr);
2128
   png_free(png_ptr, chunkdata);
2129 2130
   if (ret)
     png_error(png_ptr, "Insufficient memory to store iTXt chunk.");
2131 2132 2133
}
#endif

A
Andreas Dilger 已提交
2134 2135
/* This function is called when we haven't found a handler for a
   chunk.  If there isn't a problem with the chunk itself (ie bad
2136 2137 2138
   chunk name, CRC, or a critical chunk), the chunk is silently ignored
   -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
   case it will be saved away to be written out later. */
2139
void /* PRIVATE */
A
Andreas Dilger 已提交
2140 2141
png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
{
2142 2143
   png_uint_32 skip = 0;

A
Andreas Dilger 已提交
2144 2145
   png_debug(1, "in png_handle_unknown\n");

2146
   if (png_ptr->mode & PNG_HAVE_IDAT)
2147 2148 2149 2150 2151 2152 2153
   {
#ifdef PNG_USE_LOCAL_ARRAYS
      PNG_IDAT;
#endif
      if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))  /* not an IDAT */
         png_ptr->mode |= PNG_AFTER_IDAT;
   }
2154

A
Andreas Dilger 已提交
2155 2156 2157 2158
   png_check_chunk_name(png_ptr, png_ptr->chunk_name);

   if (!(png_ptr->chunk_name[0] & 0x20))
   {
2159
#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
2160
      if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
2161
           PNG_HANDLE_CHUNK_ALWAYS
2162
#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2163
           && png_ptr->read_user_chunk_fn == NULL
2164 2165
#endif
        )
2166
#endif
2167
          png_chunk_error(png_ptr, "unknown critical chunk");
A
Andreas Dilger 已提交
2168 2169
   }

2170
#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
2171 2172
   if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) ||
       (png_ptr->read_user_chunk_fn != NULL))
2173 2174
   {
       png_unknown_chunk chunk;
A
Andreas Dilger 已提交
2175

2176 2177 2178 2179 2180 2181 2182 2183
#ifdef PNG_MAX_MALLOC_64K
       if (length > (png_uint_32)65535L)
       {
           png_warning(png_ptr, "unknown chunk too large to fit in memory");
           skip = length - (png_uint_32)65535L;
           length = (png_uint_32)65535L;
       }
#endif
2184
       png_strcpy((png_charp)chunk.name, (png_charp)png_ptr->chunk_name);
2185
       chunk.data = (png_bytep)png_malloc(png_ptr, length);
2186 2187
       chunk.size = (png_size_t)length;
       png_crc_read(png_ptr, (png_bytep)chunk.data, length);
2188
#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2189
       if(png_ptr->read_user_chunk_fn != NULL)
2190 2191 2192 2193 2194 2195
       {
          /* callback to user unknown chunk handler */
          if ((*(png_ptr->read_user_chunk_fn)) (png_ptr, &chunk) <= 0)
          {
             if (!(png_ptr->chunk_name[0] & 0x20))
                if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
2196
                     PNG_HANDLE_CHUNK_ALWAYS)
2197 2198
                 {
                   png_free(png_ptr, chunk.data);
2199
                   png_chunk_error(png_ptr, "unknown critical chunk");
2200
                 }
2201 2202 2203 2204 2205 2206
             png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
          }
       }
       else
#endif
          png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
2207 2208 2209 2210
       png_free(png_ptr, chunk.data);
   }
   else
#endif
2211
      skip = length;
2212

2213
   png_crc_finish(png_ptr, skip);
2214 2215

#if !defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2216 2217
   if (&info_ptr == NULL) /* quiet compiler warnings about unused info_ptr */
      return;
2218
#endif
A
Andreas Dilger 已提交
2219 2220 2221 2222
}

/* This function is called to verify that a chunk name is valid.
   This function can't have the "critical chunk check" incorporated
A
Andreas Dilger 已提交
2223
   into it, since in the future we will need to be able to call user
A
Andreas Dilger 已提交
2224 2225
   functions to handle unknown critical chunks after we check that
   the chunk name itself is valid. */
A
Andreas Dilger 已提交
2226

2227
#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
A
Andreas Dilger 已提交
2228

2229
void /* PRIVATE */
A
Andreas Dilger 已提交
2230 2231
png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
{
A
Andreas Dilger 已提交
2232 2233 2234
   png_debug(1, "in png_check_chunk_name\n");
   if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
       isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
A
Andreas Dilger 已提交
2235
   {
2236
      png_chunk_error(png_ptr, "invalid chunk type");
A
Andreas Dilger 已提交
2237 2238 2239
   }
}

2240 2241
/* Combines the row recently read in with the existing pixels in the
   row.  This routine takes care of alpha and transparency if requested.
G
Guy Schalnat 已提交
2242 2243 2244 2245
   This routine also handles the two methods of progressive display
   of interlaced images, depending on the mask value.
   The mask value describes which pixels are to be combined with
   the row.  The pattern always repeats every 8 pixels, so just 8
2246
   bits are needed.  A one indicates the pixel is to be combined,
G
Guy Schalnat 已提交
2247 2248
   a zero indicates the pixel is to be skipped.  This is in addition
   to any alpha or transparency value associated with the pixel.  If
A
Andreas Dilger 已提交
2249
   you want all pixels to be combined, pass 0xff (255) in mask.  */
2250
#ifndef PNG_HAVE_ASSEMBLER_COMBINE_ROW
2251
void /* PRIVATE */
2252
png_combine_row(png_structp png_ptr, png_bytep row, int mask)
G
Guy Schalnat 已提交
2253
{
A
Andreas Dilger 已提交
2254
   png_debug(1,"in png_combine_row\n");
G
Guy Schalnat 已提交
2255 2256
   if (mask == 0xff)
   {
G
Guy Schalnat 已提交
2257
      png_memcpy(row, png_ptr->row_buf + 1,
2258
         PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width));
G
Guy Schalnat 已提交
2259 2260 2261 2262 2263 2264 2265
   }
   else
   {
      switch (png_ptr->row_info.pixel_depth)
      {
         case 1:
         {
2266 2267
            png_bytep sp = png_ptr->row_buf + 1;
            png_bytep dp = row;
2268 2269 2270
            int s_inc, s_start, s_end;
            int m = 0x80;
            int shift;
2271
            png_uint_32 i;
2272
            png_uint_32 row_width = png_ptr->width;
G
Guy Schalnat 已提交
2273

A
Andreas Dilger 已提交
2274 2275
#if defined(PNG_READ_PACKSWAP_SUPPORTED)
            if (png_ptr->transformations & PNG_PACKSWAP)
2276 2277 2278 2279 2280 2281
            {
                s_start = 0;
                s_end = 7;
                s_inc = 1;
            }
            else
A
Andreas Dilger 已提交
2282 2283
#endif
            {
2284 2285 2286
                s_start = 7;
                s_end = 0;
                s_inc = -1;
A
Andreas Dilger 已提交
2287
            }
2288 2289 2290 2291

            shift = s_start;

            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2292
            {
2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314
               if (m & mask)
               {
                  int value;

                  value = (*sp >> shift) & 0x01;
                  *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
                  *dp |= (png_byte)(value << shift);
               }

               if (shift == s_end)
               {
                  shift = s_start;
                  sp++;
                  dp++;
               }
               else
                  shift += s_inc;

               if (m == 1)
                  m = 0x80;
               else
                  m >>= 1;
G
Guy Schalnat 已提交
2315 2316 2317 2318 2319
            }
            break;
         }
         case 2:
         {
2320 2321
            png_bytep sp = png_ptr->row_buf + 1;
            png_bytep dp = row;
2322
            int s_start, s_end, s_inc;
2323
            int m = 0x80;
2324 2325 2326 2327
            int shift;
            png_uint_32 i;
            png_uint_32 row_width = png_ptr->width;
            int value;
G
Guy Schalnat 已提交
2328

A
Andreas Dilger 已提交
2329 2330 2331
#if defined(PNG_READ_PACKSWAP_SUPPORTED)
            if (png_ptr->transformations & PNG_PACKSWAP)
            {
2332 2333 2334
               s_start = 0;
               s_end = 6;
               s_inc = 2;
A
Andreas Dilger 已提交
2335
            }
2336 2337
            else
#endif
A
Andreas Dilger 已提交
2338
            {
2339 2340 2341
               s_start = 6;
               s_end = 0;
               s_inc = -2;
A
Andreas Dilger 已提交
2342
            }
2343 2344 2345 2346

            shift = s_start;

            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2347
            {
2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366
               if (m & mask)
               {
                  value = (*sp >> shift) & 0x03;
                  *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
                  *dp |= (png_byte)(value << shift);
               }

               if (shift == s_end)
               {
                  shift = s_start;
                  sp++;
                  dp++;
               }
               else
                  shift += s_inc;
               if (m == 1)
                  m = 0x80;
               else
                  m >>= 1;
G
Guy Schalnat 已提交
2367 2368 2369 2370 2371
            }
            break;
         }
         case 4:
         {
2372 2373
            png_bytep sp = png_ptr->row_buf + 1;
            png_bytep dp = row;
2374
            int s_start, s_end, s_inc;
2375
            int m = 0x80;
2376 2377 2378 2379
            int shift;
            png_uint_32 i;
            png_uint_32 row_width = png_ptr->width;
            int value;
G
Guy Schalnat 已提交
2380

A
Andreas Dilger 已提交
2381 2382 2383
#if defined(PNG_READ_PACKSWAP_SUPPORTED)
            if (png_ptr->transformations & PNG_PACKSWAP)
            {
2384 2385 2386
               s_start = 0;
               s_end = 4;
               s_inc = 4;
A
Andreas Dilger 已提交
2387
            }
2388 2389
            else
#endif
A
Andreas Dilger 已提交
2390
            {
2391 2392 2393
               s_start = 4;
               s_end = 0;
               s_inc = -4;
A
Andreas Dilger 已提交
2394
            }
2395 2396 2397
            shift = s_start;

            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2398
            {
2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417
               if (m & mask)
               {
                  value = (*sp >> shift) & 0xf;
                  *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
                  *dp |= (png_byte)(value << shift);
               }

               if (shift == s_end)
               {
                  shift = s_start;
                  sp++;
                  dp++;
               }
               else
                  shift += s_inc;
               if (m == 1)
                  m = 0x80;
               else
                  m >>= 1;
G
Guy Schalnat 已提交
2418 2419 2420 2421 2422
            }
            break;
         }
         default:
         {
2423 2424 2425 2426
            png_bytep sp = png_ptr->row_buf + 1;
            png_bytep dp = row;
            png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
            png_uint_32 i;
2427 2428 2429
            png_uint_32 row_width = png_ptr->width;
            png_byte m = 0x80;

2430

2431
            for (i = 0; i < row_width; i++)
G
Guy Schalnat 已提交
2432
            {
2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444
               if (m & mask)
               {
                  png_memcpy(dp, sp, pixel_bytes);
               }

               sp += pixel_bytes;
               dp += pixel_bytes;

               if (m == 1)
                  m = 0x80;
               else
                  m >>= 1;
G
Guy Schalnat 已提交
2445 2446 2447 2448 2449 2450
            }
            break;
         }
      }
   }
}
2451
#endif /* !PNG_HAVE_ASSEMBLER_COMBINE_ROW */
G
Guy Schalnat 已提交
2452

2453 2454
#ifdef PNG_READ_INTERLACING_SUPPORTED
#ifndef PNG_HAVE_ASSEMBLER_READ_INTERLACE   /* else in pngvcrd.c, pnggccrd.c */
2455 2456 2457 2458
/* OLD pre-1.0.9 interface:
void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
   png_uint_32 transformations)
 */
2459
void /* PRIVATE */
2460
png_do_read_interlace(png_structp png_ptr)
G
Guy Schalnat 已提交
2461
{
2462 2463 2464 2465
   png_row_infop row_info = &(png_ptr->row_info);
   png_bytep row = png_ptr->row_buf + 1;
   int pass = png_ptr->pass;
   png_uint_32 transformations = png_ptr->transformations;
2466
#ifdef PNG_USE_LOCAL_ARRAYS
2467 2468 2469
   /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
   /* offset to next interlace block */
   const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2470
#endif
2471

2472
   png_debug(1,"in png_do_read_interlace (stock C version)\n");
2473
   if (row != NULL && row_info != NULL)
G
Guy Schalnat 已提交
2474
   {
2475 2476 2477
      png_uint_32 final_width;

      final_width = row_info->width * png_pass_inc[pass];
G
Guy Schalnat 已提交
2478 2479 2480 2481 2482

      switch (row_info->pixel_depth)
      {
         case 1:
         {
2483 2484
            png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
            png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
2485 2486 2487 2488
            int sshift, dshift;
            int s_start, s_end, s_inc;
            int jstop = png_pass_inc[pass];
            png_byte v;
G
Guy Schalnat 已提交
2489
            png_uint_32 i;
2490
            int j;
G
Guy Schalnat 已提交
2491

A
Andreas Dilger 已提交
2492 2493 2494
#if defined(PNG_READ_PACKSWAP_SUPPORTED)
            if (transformations & PNG_PACKSWAP)
            {
2495 2496 2497 2498 2499
                sshift = (int)((row_info->width + 7) & 0x07);
                dshift = (int)((final_width + 7) & 0x07);
                s_start = 7;
                s_end = 0;
                s_inc = -1;
A
Andreas Dilger 已提交
2500
            }
2501
            else
A
Andreas Dilger 已提交
2502
#endif
G
Guy Schalnat 已提交
2503
            {
2504 2505 2506 2507 2508 2509
                sshift = 7 - (int)((row_info->width + 7) & 0x07);
                dshift = 7 - (int)((final_width + 7) & 0x07);
                s_start = 0;
                s_end = 7;
                s_inc = 1;
            }
2510

2511 2512 2513 2514
            for (i = 0; i < row_info->width; i++)
            {
               v = (png_byte)((*sp >> sshift) & 0x01);
               for (j = 0; j < jstop; j++)
G
Guy Schalnat 已提交
2515
               {
2516 2517 2518 2519 2520 2521 2522 2523 2524
                  *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
                  *dp |= (png_byte)(v << dshift);
                  if (dshift == s_end)
                  {
                     dshift = s_start;
                     dp--;
                  }
                  else
                     dshift += s_inc;
G
Guy Schalnat 已提交
2525
               }
2526
               if (sshift == s_end)
G
Guy Schalnat 已提交
2527
               {
2528
                  sshift = s_start;
G
Guy Schalnat 已提交
2529 2530
                  sp--;
               }
2531 2532
               else
                  sshift += s_inc;
G
Guy Schalnat 已提交
2533 2534 2535 2536 2537
            }
            break;
         }
         case 2:
         {
2538 2539 2540 2541 2542
            png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
            png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
            int sshift, dshift;
            int s_start, s_end, s_inc;
            int jstop = png_pass_inc[pass];
A
Andreas Dilger 已提交
2543
            png_uint_32 i;
G
Guy Schalnat 已提交
2544

A
Andreas Dilger 已提交
2545 2546 2547
#if defined(PNG_READ_PACKSWAP_SUPPORTED)
            if (transformations & PNG_PACKSWAP)
            {
2548 2549 2550 2551 2552
               sshift = (int)(((row_info->width + 3) & 0x03) << 1);
               dshift = (int)(((final_width + 3) & 0x03) << 1);
               s_start = 6;
               s_end = 0;
               s_inc = -2;
A
Andreas Dilger 已提交
2553
            }
2554
            else
A
Andreas Dilger 已提交
2555
#endif
2556 2557 2558 2559 2560 2561 2562
            {
               sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
               dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
               s_start = 0;
               s_end = 6;
               s_inc = 2;
            }
A
Andreas Dilger 已提交
2563

2564
            for (i = 0; i < row_info->width; i++)
G
Guy Schalnat 已提交
2565
            {
2566 2567
               png_byte v;
               int j;
A
Andreas Dilger 已提交
2568

2569 2570
               v = (png_byte)((*sp >> sshift) & 0x03);
               for (j = 0; j < jstop; j++)
G
Guy Schalnat 已提交
2571
               {
2572 2573 2574 2575 2576 2577 2578 2579 2580
                  *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
                  *dp |= (png_byte)(v << dshift);
                  if (dshift == s_end)
                  {
                     dshift = s_start;
                     dp--;
                  }
                  else
                     dshift += s_inc;
G
Guy Schalnat 已提交
2581
               }
2582
               if (sshift == s_end)
G
Guy Schalnat 已提交
2583
               {
2584
                  sshift = s_start;
G
Guy Schalnat 已提交
2585 2586
                  sp--;
               }
2587 2588
               else
                  sshift += s_inc;
G
Guy Schalnat 已提交
2589 2590 2591 2592 2593
            }
            break;
         }
         case 4:
         {
2594 2595
            png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
            png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
2596 2597
            int sshift, dshift;
            int s_start, s_end, s_inc;
G
Guy Schalnat 已提交
2598
            png_uint_32 i;
2599
            int jstop = png_pass_inc[pass];
G
Guy Schalnat 已提交
2600

A
Andreas Dilger 已提交
2601 2602 2603
#if defined(PNG_READ_PACKSWAP_SUPPORTED)
            if (transformations & PNG_PACKSWAP)
            {
2604 2605 2606 2607 2608
               sshift = (int)(((row_info->width + 1) & 0x01) << 2);
               dshift = (int)(((final_width + 1) & 0x01) << 2);
               s_start = 4;
               s_end = 0;
               s_inc = -4;
A
Andreas Dilger 已提交
2609
            }
2610
            else
A
Andreas Dilger 已提交
2611 2612
#endif
            {
2613 2614 2615 2616 2617 2618
               sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
               dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
               s_start = 0;
               s_end = 4;
               s_inc = 4;
            }
A
Andreas Dilger 已提交
2619

2620 2621 2622 2623
            for (i = 0; i < row_info->width; i++)
            {
               png_byte v = (png_byte)((*sp >> sshift) & 0xf);
               int j;
A
Andreas Dilger 已提交
2624

2625
               for (j = 0; j < jstop; j++)
G
Guy Schalnat 已提交
2626
               {
2627 2628 2629 2630 2631 2632 2633 2634 2635
                  *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
                  *dp |= (png_byte)(v << dshift);
                  if (dshift == s_end)
                  {
                     dshift = s_start;
                     dp--;
                  }
                  else
                     dshift += s_inc;
G
Guy Schalnat 已提交
2636
               }
2637
               if (sshift == s_end)
G
Guy Schalnat 已提交
2638
               {
2639
                  sshift = s_start;
G
Guy Schalnat 已提交
2640 2641
                  sp--;
               }
2642 2643
               else
                  sshift += s_inc;
G
Guy Schalnat 已提交
2644 2645 2646 2647 2648
            }
            break;
         }
         default:
         {
2649 2650
            png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
            png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes;
2651 2652 2653
            png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;

            int jstop = png_pass_inc[pass];
A
Andreas Dilger 已提交
2654
            png_uint_32 i;
G
Guy Schalnat 已提交
2655

2656
            for (i = 0; i < row_info->width; i++)
G
Guy Schalnat 已提交
2657
            {
2658 2659 2660 2661 2662 2663 2664 2665 2666 2667
               png_byte v[8];
               int j;

               png_memcpy(v, sp, pixel_bytes);
               for (j = 0; j < jstop; j++)
               {
                  png_memcpy(dp, v, pixel_bytes);
                  dp -= pixel_bytes;
               }
               sp -= pixel_bytes;
G
Guy Schalnat 已提交
2668 2669 2670 2671 2672
            }
            break;
         }
      }
      row_info->width = final_width;
2673
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,final_width);
G
Guy Schalnat 已提交
2674
   }
2675
#if !defined(PNG_READ_PACKSWAP_SUPPORTED)
2676 2677
   if (&transformations == NULL) /* silence compiler warning */
      return;
2678
#endif
G
Guy Schalnat 已提交
2679
}
2680 2681
#endif /* !PNG_HAVE_ASSEMBLER_READ_INTERLACE */
#endif /* PNG_READ_INTERLACING_SUPPORTED */
G
Guy Schalnat 已提交
2682

2683
#ifndef PNG_HAVE_ASSEMBLER_READ_FILTER_ROW
2684
void /* PRIVATE */
2685
png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
2686 2687 2688
   png_bytep prev_row, int filter)
{
   png_debug(1, "in png_read_filter_row\n");
2689
   png_debug2(2,"row = %lu, filter = %d\n", png_ptr->row_number, filter);
2690 2691 2692 2693 2694 2695
   switch (filter)
   {
      case PNG_FILTER_VALUE_NONE:
         break;
      case PNG_FILTER_VALUE_SUB:
      {
2696 2697
         png_uint_32 i;
         png_uint_32 istop = row_info->rowbytes;
2698
         png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2699 2700
         png_bytep rp = row + bpp;
         png_bytep lp = row;
2701

2702
         for (i = bpp; i < istop; i++)
2703
         {
2704 2705
            *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
            rp++;
2706 2707 2708 2709 2710
         }
         break;
      }
      case PNG_FILTER_VALUE_UP:
      {
2711 2712 2713 2714
         png_uint_32 i;
         png_uint_32 istop = row_info->rowbytes;
         png_bytep rp = row;
         png_bytep pp = prev_row;
2715

2716
         for (i = 0; i < istop; i++)
2717
         {
2718 2719
            *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
            rp++;
2720 2721 2722 2723 2724
         }
         break;
      }
      case PNG_FILTER_VALUE_AVG:
      {
2725 2726 2727 2728
         png_uint_32 i;
         png_bytep rp = row;
         png_bytep pp = prev_row;
         png_bytep lp = row;
2729
         png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2730
         png_uint_32 istop = row_info->rowbytes - bpp;
2731

2732
         for (i = 0; i < bpp; i++)
2733
         {
2734
            *rp = (png_byte)(((int)(*rp) +
2735
               ((int)(*pp++) / 2 )) & 0xff);
2736
            rp++;
2737
         }
2738

2739
         for (i = 0; i < istop; i++)
2740
         {
2741
            *rp = (png_byte)(((int)(*rp) +
2742
               (int)(*pp++ + *lp++) / 2 ) & 0xff);
2743
            rp++;
2744 2745 2746 2747 2748
         }
         break;
      }
      case PNG_FILTER_VALUE_PAETH:
      {
2749 2750 2751 2752 2753
         png_uint_32 i;
         png_bytep rp = row;
         png_bytep pp = prev_row;
         png_bytep lp = row;
         png_bytep cp = prev_row;
2754
         png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2755
         png_uint_32 istop=row_info->rowbytes - bpp;
2756 2757

         for (i = 0; i < bpp; i++)
2758
         {
2759 2760
            *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
            rp++;
2761 2762
         }

2763
         for (i = 0; i < istop; i++)   /* use leftover rp,pp */
2764 2765 2766
         {
            int a, b, c, pa, pb, pc, p;

2767 2768 2769 2770 2771 2772
            a = *lp++;
            b = *pp++;
            c = *cp++;

            p = b - c;
            pc = a - c;
2773 2774

#ifdef PNG_USE_ABS
2775 2776 2777
            pa = abs(p);
            pb = abs(pc);
            pc = abs(p + pc);
2778
#else
2779 2780 2781
            pa = p < 0 ? -p : p;
            pb = pc < 0 ? -pc : pc;
            pc = (p + pc) < 0 ? -(p + pc) : p + pc;
2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794
#endif

            /*
               if (pa <= pb && pa <= pc)
                  p = a;
               else if (pb <= pc)
                  p = b;
               else
                  p = c;
             */

            p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;

2795 2796
            *rp = (png_byte)(((int)(*rp) + p) & 0xff);
            rp++;
2797 2798 2799 2800
         }
         break;
      }
      default:
2801 2802
         png_warning(png_ptr, "Ignoring bad adaptive filter type");
         *row=0;
2803 2804 2805
         break;
   }
}
2806
#endif /* !PNG_HAVE_ASSEMBLER_READ_FILTER_ROW */
G
Guy Schalnat 已提交
2807

2808
void /* PRIVATE */
G
Guy Schalnat 已提交
2809
png_read_finish_row(png_structp png_ptr)
G
Guy Schalnat 已提交
2810
{
2811
#ifdef PNG_USE_LOCAL_ARRAYS
2812
   /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2813

2814 2815
   /* start of interlace block */
   const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2816

2817 2818
   /* offset to next interlace block */
   const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2819

2820 2821
   /* start of interlace block in the y direction */
   const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
2822

2823 2824
   /* offset to next interlace block in the y direction */
   const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
2825
#endif
2826

A
Andreas Dilger 已提交
2827
   png_debug(1, "in png_read_finish_row\n");
G
Guy Schalnat 已提交
2828 2829 2830 2831 2832 2833 2834
   png_ptr->row_number++;
   if (png_ptr->row_number < png_ptr->num_rows)
      return;

   if (png_ptr->interlaced)
   {
      png_ptr->row_number = 0;
2835
      png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
G
Guy Schalnat 已提交
2836 2837 2838 2839 2840 2841 2842 2843 2844
      do
      {
         png_ptr->pass++;
         if (png_ptr->pass >= 7)
            break;
         png_ptr->iwidth = (png_ptr->width +
            png_pass_inc[png_ptr->pass] - 1 -
            png_pass_start[png_ptr->pass]) /
            png_pass_inc[png_ptr->pass];
2845 2846 2847

         png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,
            png_ptr->iwidth) + 1;
2848

G
Guy Schalnat 已提交
2849 2850 2851 2852 2853 2854 2855 2856 2857
         if (!(png_ptr->transformations & PNG_INTERLACE))
         {
            png_ptr->num_rows = (png_ptr->height +
               png_pass_yinc[png_ptr->pass] - 1 -
               png_pass_ystart[png_ptr->pass]) /
               png_pass_yinc[png_ptr->pass];
            if (!(png_ptr->num_rows))
               continue;
         }
2858
         else  /* if (png_ptr->transformations & PNG_INTERLACE) */
G
Guy Schalnat 已提交
2859
            break;
G
Guy Schalnat 已提交
2860 2861 2862 2863 2864 2865
      } while (png_ptr->iwidth == 0);

      if (png_ptr->pass < 7)
         return;
   }

G
Guy Schalnat 已提交
2866
   if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
G
Guy Schalnat 已提交
2867
   {
2868 2869 2870
#ifdef PNG_USE_LOCAL_ARRAYS
      PNG_IDAT;
#endif
G
Guy Schalnat 已提交
2871 2872 2873
      char extra;
      int ret;

A
Andreas Dilger 已提交
2874 2875
      png_ptr->zstream.next_out = (Byte *)&extra;
      png_ptr->zstream.avail_out = (uInt)1;
2876
      for(;;)
G
Guy Schalnat 已提交
2877
      {
A
Andreas Dilger 已提交
2878
         if (!(png_ptr->zstream.avail_in))
G
Guy Schalnat 已提交
2879 2880 2881
         {
            while (!png_ptr->idat_size)
            {
A
Andreas Dilger 已提交
2882
               png_byte chunk_length[4];
G
Guy Schalnat 已提交
2883

A
Andreas Dilger 已提交
2884
               png_crc_finish(png_ptr, 0);
G
Guy Schalnat 已提交
2885

A
Andreas Dilger 已提交
2886
               png_read_data(png_ptr, chunk_length, 4);
2887
               png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length);
A
Andreas Dilger 已提交
2888 2889
               png_reset_crc(png_ptr);
               png_crc_read(png_ptr, png_ptr->chunk_name, 4);
2890
               if (png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4))
G
Guy Schalnat 已提交
2891
                  png_error(png_ptr, "Not enough image data");
G
Guy Schalnat 已提交
2892 2893

            }
A
Andreas Dilger 已提交
2894 2895
            png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
            png_ptr->zstream.next_in = png_ptr->zbuf;
G
Guy Schalnat 已提交
2896
            if (png_ptr->zbuf_size > png_ptr->idat_size)
A
Andreas Dilger 已提交
2897 2898 2899
               png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
            png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
            png_ptr->idat_size -= png_ptr->zstream.avail_in;
G
Guy Schalnat 已提交
2900
         }
A
Andreas Dilger 已提交
2901
         ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
G
Guy Schalnat 已提交
2902 2903
         if (ret == Z_STREAM_END)
         {
A
Andreas Dilger 已提交
2904
            if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
G
Guy Schalnat 已提交
2905
               png_ptr->idat_size)
2906
               png_warning(png_ptr, "Extra compressed data");
A
Andreas Dilger 已提交
2907 2908
            png_ptr->mode |= PNG_AFTER_IDAT;
            png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
G
Guy Schalnat 已提交
2909 2910 2911
            break;
         }
         if (ret != Z_OK)
A
Andreas Dilger 已提交
2912
            png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
G
Guy Schalnat 已提交
2913
                      "Decompression Error");
G
Guy Schalnat 已提交
2914

A
Andreas Dilger 已提交
2915
         if (!(png_ptr->zstream.avail_out))
2916 2917 2918 2919 2920 2921
         {
            png_warning(png_ptr, "Extra compressed data.");
            png_ptr->mode |= PNG_AFTER_IDAT;
            png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
            break;
         }
G
Guy Schalnat 已提交
2922

2923
      }
A
Andreas Dilger 已提交
2924
      png_ptr->zstream.avail_out = 0;
G
Guy Schalnat 已提交
2925 2926
   }

A
Andreas Dilger 已提交
2927
   if (png_ptr->idat_size || png_ptr->zstream.avail_in)
2928
      png_warning(png_ptr, "Extra compression data");
G
Guy Schalnat 已提交
2929

A
Andreas Dilger 已提交
2930
   inflateReset(&png_ptr->zstream);
G
Guy Schalnat 已提交
2931

A
Andreas Dilger 已提交
2932
   png_ptr->mode |= PNG_AFTER_IDAT;
G
Guy Schalnat 已提交
2933 2934
}

2935
void /* PRIVATE */
G
Guy Schalnat 已提交
2936
png_read_start_row(png_structp png_ptr)
G
Guy Schalnat 已提交
2937
{
2938
#ifdef PNG_USE_LOCAL_ARRAYS
2939
   /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2940

2941 2942
   /* start of interlace block */
   const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2943

2944 2945
   /* offset to next interlace block */
   const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2946

2947 2948
   /* start of interlace block in the y direction */
   const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
2949

2950 2951
   /* offset to next interlace block in the y direction */
   const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
2952
#endif
2953

G
Guy Schalnat 已提交
2954
   int max_pixel_depth;
2955
   png_uint_32 row_bytes;
G
Guy Schalnat 已提交
2956

A
Andreas Dilger 已提交
2957
   png_debug(1, "in png_read_start_row\n");
A
Andreas Dilger 已提交
2958
   png_ptr->zstream.avail_in = 0;
G
Guy Schalnat 已提交
2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971
   png_init_read_transformations(png_ptr);
   if (png_ptr->interlaced)
   {
      if (!(png_ptr->transformations & PNG_INTERLACE))
         png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
            png_pass_ystart[0]) / png_pass_yinc[0];
      else
         png_ptr->num_rows = png_ptr->height;

      png_ptr->iwidth = (png_ptr->width +
         png_pass_inc[png_ptr->pass] - 1 -
         png_pass_start[png_ptr->pass]) /
         png_pass_inc[png_ptr->pass];
2972

2973 2974
         row_bytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->iwidth) + 1;

2975 2976
         png_ptr->irowbytes = (png_size_t)row_bytes;
         if((png_uint_32)png_ptr->irowbytes != row_bytes)
2977
            png_error(png_ptr, "Rowbytes overflow in png_read_start_row");
G
Guy Schalnat 已提交
2978 2979 2980 2981 2982 2983 2984 2985 2986
   }
   else
   {
      png_ptr->num_rows = png_ptr->height;
      png_ptr->iwidth = png_ptr->width;
      png_ptr->irowbytes = png_ptr->rowbytes + 1;
   }
   max_pixel_depth = png_ptr->pixel_depth;

G
Guy Schalnat 已提交
2987
#if defined(PNG_READ_PACK_SUPPORTED)
G
Guy Schalnat 已提交
2988 2989
   if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
      max_pixel_depth = 8;
G
Guy Schalnat 已提交
2990
#endif
G
Guy Schalnat 已提交
2991

G
Guy Schalnat 已提交
2992 2993
#if defined(PNG_READ_EXPAND_SUPPORTED)
   if (png_ptr->transformations & PNG_EXPAND)
G
Guy Schalnat 已提交
2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017
   {
      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
      {
         if (png_ptr->num_trans)
            max_pixel_depth = 32;
         else
            max_pixel_depth = 24;
      }
      else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
      {
         if (max_pixel_depth < 8)
            max_pixel_depth = 8;
         if (png_ptr->num_trans)
            max_pixel_depth *= 2;
      }
      else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
      {
         if (png_ptr->num_trans)
         {
            max_pixel_depth *= 4;
            max_pixel_depth /= 3;
         }
      }
   }
G
Guy Schalnat 已提交
3018
#endif
G
Guy Schalnat 已提交
3019

G
Guy Schalnat 已提交
3020 3021
#if defined(PNG_READ_FILLER_SUPPORTED)
   if (png_ptr->transformations & (PNG_FILLER))
G
Guy Schalnat 已提交
3022
   {
3023 3024 3025
      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
         max_pixel_depth = 32;
      else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038
      {
         if (max_pixel_depth <= 8)
            max_pixel_depth = 16;
         else
            max_pixel_depth = 32;
      }
      else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
      {
         if (max_pixel_depth <= 32)
            max_pixel_depth = 32;
         else
            max_pixel_depth = 64;
      }
G
Guy Schalnat 已提交
3039
   }
G
Guy Schalnat 已提交
3040
#endif
G
Guy Schalnat 已提交
3041

G
Guy Schalnat 已提交
3042
#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
G
Guy Schalnat 已提交
3043 3044
   if (png_ptr->transformations & PNG_GRAY_TO_RGB)
   {
3045 3046 3047 3048 3049 3050 3051 3052
      if (
#if defined(PNG_READ_EXPAND_SUPPORTED)
        (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
#endif
#if defined(PNG_READ_FILLER_SUPPORTED)
        (png_ptr->transformations & (PNG_FILLER)) ||
#endif
        png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
G
Guy Schalnat 已提交
3053 3054 3055
      {
         if (max_pixel_depth <= 16)
            max_pixel_depth = 32;
3056
         else
G
Guy Schalnat 已提交
3057 3058 3059 3060 3061
            max_pixel_depth = 64;
      }
      else
      {
         if (max_pixel_depth <= 8)
3062 3063 3064 3065 3066 3067 3068 3069
           {
             if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
               max_pixel_depth = 32;
             else
               max_pixel_depth = 24;
           }
         else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
            max_pixel_depth = 64;
3070
         else
G
Guy Schalnat 已提交
3071 3072 3073
            max_pixel_depth = 48;
      }
   }
G
Guy Schalnat 已提交
3074
#endif
G
Guy Schalnat 已提交
3075

3076 3077
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
3078 3079 3080 3081 3082 3083 3084 3085 3086
   if(png_ptr->transformations & PNG_USER_TRANSFORM)
     {
       int user_pixel_depth=png_ptr->user_transform_depth*
         png_ptr->user_transform_channels;
       if(user_pixel_depth > max_pixel_depth)
         max_pixel_depth=user_pixel_depth;
     }
#endif

G
Guy Schalnat 已提交
3087 3088
   /* align the width on the next larger 8 pixels.  Mainly used
      for interlacing */
3089
   row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
G
Guy Schalnat 已提交
3090
   /* calculate the maximum bytes needed, adding a byte and a pixel
3091
      for safety's sake */
3092
   row_bytes = PNG_ROWBYTES(max_pixel_depth,row_bytes) +
G
Guy Schalnat 已提交
3093 3094
      1 + ((max_pixel_depth + 7) >> 3);
#ifdef PNG_MAX_MALLOC_64K
3095
   if (row_bytes > (png_uint_32)65536L)
G
Guy Schalnat 已提交
3096
      png_error(png_ptr, "This image requires a row greater than 64KB");
G
Guy Schalnat 已提交
3097
#endif
3098 3099
   png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes+64);
   png_ptr->row_buf = png_ptr->big_row_buf+32;
3100
#if defined(PNG_DEBUG) && defined(PNG_USE_PNGGCCRD)
3101
   png_ptr->row_buf_size = row_bytes;
3102
#endif
G
Guy Schalnat 已提交
3103 3104

#ifdef PNG_MAX_MALLOC_64K
3105
   if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L)
G
Guy Schalnat 已提交
3106
      png_error(png_ptr, "This image requires a row greater than 64KB");
G
Guy Schalnat 已提交
3107
#endif
3108
   if ((png_uint_32)png_ptr->rowbytes > PNG_SIZE_MAX - 1)
3109
      png_error(png_ptr, "Row has too many bytes to allocate in memory.");
3110 3111
   png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
      png_ptr->rowbytes + 1));
A
Andreas Dilger 已提交
3112

3113
   png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
G
Guy Schalnat 已提交
3114

3115 3116 3117 3118 3119 3120
   png_debug1(3, "width = %lu,\n", png_ptr->width);
   png_debug1(3, "height = %lu,\n", png_ptr->height);
   png_debug1(3, "iwidth = %lu,\n", png_ptr->iwidth);
   png_debug1(3, "num_rows = %lu\n", png_ptr->num_rows);
   png_debug1(3, "rowbytes = %lu,\n", png_ptr->rowbytes);
   png_debug1(3, "irowbytes = %lu,\n", png_ptr->irowbytes);
G
Guy Schalnat 已提交
3121

G
Guy Schalnat 已提交
3122
   png_ptr->flags |= PNG_FLAG_ROW_INIT;
G
Guy Schalnat 已提交
3123
}
3124
#endif /* PNG_READ_SUPPORTED */