This repository has been archived on 2023-11-11. You can view files and clone it, but cannot push or open issues or pull requests.
libpng/pngrutil.c

3184 lines
90 KiB
C
Raw Normal View History

2006-03-04 22:50:47 +00:00
1997-05-16 07:46:07 +00:00
/* pngrutil.c - utilities to read a PNG file
1998-01-01 13:13:13 +00:00
*
2008-04-30 10:23:42 +00:00
* Last changed in libpng 1.2.27 [April 29, 2008]
1998-01-01 13:13:13 +00:00
* For conditions of distribution and use, see copyright notice in png.h
2008-01-09 16:58:36 +00:00
* Copyright (c) 1998-2008 Glenn Randers-Pehrson
2000-06-04 19:29:29 +00:00
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
1998-01-01 13:13:13 +00:00
*
1998-05-21 14:27:50 +00:00
* This file contains routines that are only called from within
1998-01-01 13:13:13 +00:00
* libpng itself during the course of reading an image.
*/
1995-07-20 07:43:20 +00:00
#define PNG_INTERNAL
#include "png.h"
2006-02-21 04:09:05 +00:00
#if defined(PNG_READ_SUPPORTED)
2007-08-10 20:49:26 +00:00
#if defined(_WIN32_WCE) && (_WIN32_WCE<0x500)
# define WIN32_WCE_OLD
#endif
2006-11-20 13:55:23 +00:00
#ifdef PNG_FLOATING_POINT_SUPPORTED
2007-08-10 20:49:26 +00:00
# if defined(WIN32_WCE_OLD)
2000-07-08 18:19:41 +00:00
/* strtod() function is not supported on WindowsCE */
2007-05-18 18:40:59 +00:00
__inline double png_strtod(png_structp png_ptr, PNG_CONST char *nptr, char **endptr)
2000-07-08 18:19:41 +00:00
{
double result = 0;
int len;
wchar_t *str, *end;
len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0);
2006-11-20 13:55:23 +00:00
str = (wchar_t *)png_malloc(png_ptr, len * sizeof(wchar_t));
2000-07-08 18:19:41 +00:00
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);
2001-05-07 19:52:45 +00:00
*endptr = (char *)nptr + (png_strlen(nptr) - len + 1);
2007-07-17 02:44:06 +00:00
png_free(png_ptr, str);
2000-07-08 18:19:41 +00:00
}
return result;
}
2006-11-20 13:55:23 +00:00
# else
# define png_strtod(p,a,b) strtod(a,b)
2000-07-08 18:19:41 +00:00
# endif
#endif
2006-02-21 04:09:05 +00:00
png_uint_32 PNGAPI
2004-07-28 13:20:44 +00:00
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)
2006-03-02 13:23:18 +00:00
png_error(png_ptr, "PNG unsigned integer out of range.");
2004-07-28 13:20:44 +00:00
return (i);
}
1997-05-16 07:46:07 +00:00
#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED
1998-05-21 14:27:50 +00:00
/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
2006-02-21 04:09:05 +00:00
png_uint_32 PNGAPI
1995-12-19 09:22:19 +00:00
png_get_uint_32(png_bytep buf)
1995-07-20 07:43:20 +00:00
{
1998-05-02 17:52:25 +00:00
png_uint_32 i = ((png_uint_32)(*buf) << 24) +
1995-07-20 07:43:20 +00:00
((png_uint_32)(*(buf + 1)) << 16) +
((png_uint_32)(*(buf + 2)) << 8) +
(png_uint_32)(*(buf + 3));
1998-02-01 02:07:59 +00:00
return (i);
1995-07-20 07:43:20 +00:00
}
1998-05-21 14:27:50 +00:00
/* Grab a signed 32-bit integer from a buffer in big-endian format. The
1997-05-16 07:46:07 +00:00
* 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. */
2006-02-21 04:09:05 +00:00
png_int_32 PNGAPI
1997-05-16 07:46:07 +00:00
png_get_int_32(png_bytep buf)
{
1998-05-02 17:52:25 +00:00
png_int_32 i = ((png_int_32)(*buf) << 24) +
1997-05-16 07:46:07 +00:00
((png_int_32)(*(buf + 1)) << 16) +
((png_int_32)(*(buf + 2)) << 8) +
(png_int_32)(*(buf + 3));
1998-02-01 02:07:59 +00:00
return (i);
1997-05-16 07:46:07 +00:00
}
1998-05-21 14:27:50 +00:00
/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
2006-02-21 04:09:05 +00:00
png_uint_16 PNGAPI
1995-12-19 09:22:19 +00:00
png_get_uint_16(png_bytep buf)
1995-07-20 07:43:20 +00:00
{
1998-05-02 17:52:25 +00:00
png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) +
1996-01-26 07:38:47 +00:00
(png_uint_16)(*(buf + 1)));
1995-07-20 07:43:20 +00:00
1998-02-01 02:07:59 +00:00
return (i);
1995-07-20 07:43:20 +00:00
}
1997-05-16 07:46:07 +00:00
#endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */
1995-07-20 07:43:20 +00:00
1997-01-17 07:34:35 +00:00
/* Read data, and (optionally) run it through the CRC. */
2000-05-06 19:09:57 +00:00
void /* PRIVATE */
1997-05-16 07:46:07 +00:00
png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
1995-07-20 07:43:20 +00:00
{
2006-11-13 20:14:21 +00:00
if(png_ptr == NULL) return;
1995-12-19 09:22:19 +00:00
png_read_data(png_ptr, buf, length);
1997-05-16 07:46:07 +00:00
png_calculate_crc(png_ptr, buf, length);
1995-07-20 07:43:20 +00:00
}
1997-01-17 07:34:35 +00:00
/* 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
1997-05-16 07:46:07 +00:00
things up, we may calculate the CRC on the data and print a message.
Returns '1' if there was a CRC error, '0' otherwise. */
2000-05-06 19:09:57 +00:00
int /* PRIVATE */
1997-01-17 07:34:35 +00:00
png_crc_finish(png_structp png_ptr, png_uint_32 skip)
1995-07-20 07:43:20 +00:00
{
1998-05-02 17:52:25 +00:00
png_size_t i;
png_size_t istop = png_ptr->zbuf_size;
1995-07-20 07:43:20 +00:00
1998-05-09 15:02:29 +00:00
for (i = (png_size_t)skip; i > istop; i -= istop)
1997-01-17 07:34:35 +00:00
{
1997-05-16 07:46:07 +00:00
png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
1995-07-20 07:43:20 +00:00
}
if (i)
{
1998-05-02 17:52:25 +00:00
png_crc_read(png_ptr, png_ptr->zbuf, i);
1997-01-17 07:34:35 +00:00
}
1997-05-16 07:46:07 +00:00
if (png_crc_error(png_ptr))
1997-01-17 07:34:35 +00:00
{
2000-02-05 05:40:16 +00:00
if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */
1997-01-17 07:34:35 +00:00
!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
(!(png_ptr->chunk_name[0] & 0x20) && /* Critical */
2000-02-05 05:40:16 +00:00
(png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)))
1997-01-17 07:34:35 +00:00
{
1998-01-04 04:40:55 +00:00
png_chunk_warning(png_ptr, "CRC error");
1997-01-17 07:34:35 +00:00
}
else
{
1998-01-04 04:40:55 +00:00
png_chunk_error(png_ptr, "CRC error");
1997-01-17 07:34:35 +00:00
}
1998-02-01 02:07:59 +00:00
return (1);
1995-07-20 07:43:20 +00:00
}
1997-01-17 07:34:35 +00:00
1998-02-01 02:07:59 +00:00
return (0);
1995-07-20 07:43:20 +00:00
}
1998-01-17 04:06:18 +00:00
/* Compare the CRC stored in the PNG file with that calculated by libpng from
1997-01-17 07:34:35 +00:00
the data it has read thus far. */
2000-05-06 19:09:57 +00:00
int /* PRIVATE */
1997-01-17 07:34:35 +00:00
png_crc_error(png_structp png_ptr)
{
png_byte crc_bytes[4];
png_uint_32 crc;
1997-05-16 07:46:07 +00:00
int need_crc = 1;
1997-01-17 07:34:35 +00:00
1997-05-16 07:46:07 +00:00
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;
}
1997-01-17 07:34:35 +00:00
1997-05-16 07:46:07 +00:00
png_read_data(png_ptr, crc_bytes, 4);
1997-01-17 07:34:35 +00:00
1997-05-16 07:46:07 +00:00
if (need_crc)
{
crc = png_get_uint_32(crc_bytes);
1998-02-01 02:07:59 +00:00
return ((int)(crc != png_ptr->crc));
1997-05-16 07:46:07 +00:00
}
else
1998-02-01 02:07:59 +00:00
return (0);
1997-01-17 07:34:35 +00:00
}
1999-12-10 15:43:02 +00:00
#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \
2000-04-14 19:20:47 +00:00
defined(PNG_READ_iCCP_SUPPORTED)
1999-12-10 15:43:02 +00:00
/*
* 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).
*/
2000-05-06 19:09:57 +00:00
png_charp /* PRIVATE */
png_decompress_chunk(png_structp png_ptr, int comp_type,
1999-12-10 15:43:02 +00:00
png_charp chunkdata, png_size_t chunklength,
2000-04-02 03:10:05 +00:00
png_size_t prefix_size, png_size_t *newlength)
1999-12-10 15:43:02 +00:00
{
2007-05-18 18:40:59 +00:00
static PNG_CONST char msg[] = "Error decoding compressed text";
2004-07-18 03:45:44 +00:00
png_charp text;
2000-03-21 11:13:06 +00:00
png_size_t text_size;
1999-12-10 15:43:02 +00:00
2000-12-28 13:50:05 +00:00
if (comp_type == PNG_COMPRESSION_TYPE_BASE)
1999-12-10 15:43:02 +00:00
{
2000-06-04 19:29:29 +00:00
int ret = Z_OK;
1999-12-10 15:43:02 +00:00
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)
{
2000-06-04 19:29:29 +00:00
ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
1999-12-10 15:43:02 +00:00
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)
{
2004-07-28 13:20:44 +00:00
text_size = prefix_size + png_sizeof(msg) + 1;
2002-05-25 16:12:10 +00:00
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");
}
2001-04-20 15:32:10 +00:00
png_memcpy(text, chunkdata, prefix_size);
1999-12-10 15:43:02 +00:00
}
2001-04-20 15:32:10 +00:00
text[text_size - 1] = 0x00;
1999-12-10 15:43:02 +00:00
2001-04-20 15:32:10 +00:00
/* Copy what we can of the error message into the text chunk */
text_size = (png_size_t)(chunklength - (text - chunkdata) - 1);
2004-07-28 13:20:44 +00:00
text_size = png_sizeof(msg) > text_size ? text_size :
png_sizeof(msg);
2008-01-22 03:07:36 +00:00
png_memcpy(text + prefix_size, msg, text_size);
1999-12-10 15:43:02 +00:00
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;
2002-05-25 16:12:10 +00:00
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.");
}
2001-04-20 15:32:10 +00:00
png_memcpy(text + prefix_size, png_ptr->zbuf,
2001-05-07 19:52:45 +00:00
text_size - prefix_size);
2001-04-20 15:32:10 +00:00
png_memcpy(text, chunkdata, prefix_size);
*(text + text_size) = 0x00;
1999-12-10 15:43:02 +00:00
}
else
{
png_charp tmp;
tmp = text;
2002-05-25 16:12:10 +00:00
text = (png_charp)png_malloc_warn(png_ptr,
(png_uint_32)(text_size +
1999-12-10 15:43:02 +00:00
png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1));
2002-05-25 16:12:10 +00:00
if (text == NULL)
{
png_free(png_ptr, tmp);
png_free(png_ptr, chunkdata);
png_error(png_ptr,"Not enough memory to decompress chunk..");
}
1999-12-10 15:43:02 +00:00
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;
}
}
}
2000-06-04 19:29:29 +00:00
if (ret != Z_STREAM_END)
2000-06-24 12:42:42 +00:00
{
2000-07-08 18:19:41 +00:00
#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
2006-06-27 20:23:00 +00:00
char umsg[52];
2000-06-24 12:42:42 +00:00
2000-07-08 18:19:41 +00:00
if (ret == Z_BUF_ERROR)
2007-05-21 02:40:52 +00:00
png_snprintf(umsg, 52,
"Buffer error in compressed datastream in %s chunk",
2000-07-08 18:19:41 +00:00
png_ptr->chunk_name);
else if (ret == Z_DATA_ERROR)
2007-05-21 02:40:52 +00:00
png_snprintf(umsg, 52,
"Data error in compressed datastream in %s chunk",
2000-07-08 18:19:41 +00:00
png_ptr->chunk_name);
else
2007-05-21 02:40:52 +00:00
png_snprintf(umsg, 52,
"Incomplete compressed datastream in %s chunk",
2000-07-08 18:19:41 +00:00
png_ptr->chunk_name);
2000-06-24 12:42:42 +00:00
png_warning(png_ptr, umsg);
#else
2000-06-04 19:29:29 +00:00
png_warning(png_ptr,
2000-06-24 12:42:42 +00:00
"Incomplete compressed datastream in chunk other than IDAT");
#endif
2001-01-12 21:13:06 +00:00
text_size=prefix_size;
if (text == NULL)
{
2002-05-25 16:12:10 +00:00
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.");
}
2001-04-20 15:32:10 +00:00
png_memcpy(text, chunkdata, prefix_size);
2001-01-12 21:13:06 +00:00
}
2001-04-20 15:32:10 +00:00
*(text + text_size) = 0x00;
2000-06-24 12:42:42 +00:00
}
1999-12-10 15:43:02 +00:00
inflateReset(&png_ptr->zstream);
png_ptr->zstream.avail_in = 0;
png_free(png_ptr, chunkdata);
chunkdata = text;
2000-04-02 03:10:05 +00:00
*newlength=text_size;
1999-12-10 15:43:02 +00:00
}
2000-12-28 13:50:05 +00:00
else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
1999-12-10 15:43:02 +00:00
{
2000-07-08 18:19:41 +00:00
#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
1999-12-10 15:43:02 +00:00
char umsg[50];
2007-05-21 02:40:52 +00:00
png_snprintf(umsg, 50,
"Unknown zTXt compression type %d", comp_type);
1999-12-10 15:43:02 +00:00
png_warning(png_ptr, umsg);
#else
png_warning(png_ptr, "Unknown zTXt compression type");
#endif
2000-12-23 20:27:39 +00:00
*(chunkdata + prefix_size) = 0x00;
*newlength=prefix_size;
1999-12-10 15:43:02 +00:00
}
return chunkdata;
}
#endif
1997-01-17 07:34:35 +00:00
1995-07-20 07:43:20 +00:00
/* read and check the IDHR chunk */
2000-05-06 19:09:57 +00:00
void /* PRIVATE */
1997-01-17 07:34:35 +00:00
png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1995-07-20 07:43:20 +00:00
{
png_byte buf[13];
png_uint_32 width, height;
int bit_depth, color_type, compression_type, filter_type;
int interlace_type;
1997-05-16 07:46:07 +00:00
png_debug(1, "in png_handle_IHDR\n");
2000-03-21 11:13:06 +00:00
if (png_ptr->mode & PNG_HAVE_IHDR)
1996-06-05 20:50:50 +00:00
png_error(png_ptr, "Out of place IHDR");
1995-07-20 07:43:20 +00:00
/* check the length */
if (length != 13)
1995-12-19 09:22:19 +00:00
png_error(png_ptr, "Invalid IHDR chunk");
1995-07-20 07:43:20 +00:00
1997-01-17 07:34:35 +00:00
png_ptr->mode |= PNG_HAVE_IHDR;
1995-07-20 07:43:20 +00:00
png_crc_read(png_ptr, buf, 13);
1997-01-17 07:34:35 +00:00
png_crc_finish(png_ptr, 0);
1995-07-20 07:43:20 +00:00
2004-07-28 13:20:44 +00:00
width = png_get_uint_31(png_ptr, buf);
height = png_get_uint_31(png_ptr, buf + 4);
1995-07-20 07:43:20 +00:00
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;
1996-01-26 07:38:47 +00:00
png_ptr->bit_depth = (png_byte)bit_depth;
png_ptr->interlaced = (png_byte)interlace_type;
png_ptr->color_type = (png_byte)color_type;
2001-05-18 09:54:50 +00:00
#if defined(PNG_MNG_FEATURES_SUPPORTED)
2000-12-15 14:54:42 +00:00
png_ptr->filter_type = (png_byte)filter_type;
2001-05-18 09:54:50 +00:00
#endif
2004-07-18 03:45:44 +00:00
png_ptr->compression_type = (png_byte)compression_type;
1995-07-20 07:43:20 +00:00
/* find number of channels */
switch (png_ptr->color_type)
{
1997-05-16 07:46:07 +00:00
case PNG_COLOR_TYPE_GRAY:
case PNG_COLOR_TYPE_PALETTE:
1995-07-20 07:43:20 +00:00
png_ptr->channels = 1;
break;
1997-05-16 07:46:07 +00:00
case PNG_COLOR_TYPE_RGB:
1995-07-20 07:43:20 +00:00
png_ptr->channels = 3;
break;
1997-05-16 07:46:07 +00:00
case PNG_COLOR_TYPE_GRAY_ALPHA:
1995-07-20 07:43:20 +00:00
png_ptr->channels = 2;
break;
1997-05-16 07:46:07 +00:00
case PNG_COLOR_TYPE_RGB_ALPHA:
1995-07-20 07:43:20 +00:00
png_ptr->channels = 4;
break;
}
1997-01-17 07:34:35 +00:00
1995-07-20 07:43:20 +00:00
/* set up other useful info */
1996-01-26 07:38:47 +00:00
png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
1998-02-07 16:20:57 +00:00
png_ptr->channels);
2004-08-04 11:34:52 +00:00
png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->width);
1997-05-16 07:46:07 +00:00
png_debug1(3,"bit_depth = %d\n", png_ptr->bit_depth);
png_debug1(3,"channels = %d\n", png_ptr->channels);
2000-07-17 11:17:09 +00:00
png_debug1(3,"rowbytes = %lu\n", png_ptr->rowbytes);
1997-05-16 07:46:07 +00:00
png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
color_type, interlace_type, compression_type, filter_type);
1995-07-20 07:43:20 +00:00
}
/* read and check the palette */
2000-05-06 19:09:57 +00:00
void /* PRIVATE */
1997-01-17 07:34:35 +00:00
png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1995-07-20 07:43:20 +00:00
{
2000-12-28 13:50:05 +00:00
png_color palette[PNG_MAX_PALETTE_LENGTH];
1997-01-17 07:34:35 +00:00
int num, i;
2000-06-04 19:29:29 +00:00
#ifndef PNG_NO_POINTER_INDEXING
png_colorp pal_ptr;
#endif
1995-07-20 07:43:20 +00:00
1997-05-16 07:46:07 +00:00
png_debug(1, "in png_handle_PLTE\n");
1996-06-05 20:50:50 +00:00
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before PLTE");
1997-01-17 07:34:35 +00:00
else if (png_ptr->mode & PNG_HAVE_IDAT)
{
png_warning(png_ptr, "Invalid PLTE after IDAT");
png_crc_finish(png_ptr, length);
return;
}
1996-06-05 20:50:50 +00:00
else if (png_ptr->mode & PNG_HAVE_PLTE)
1997-01-17 07:34:35 +00:00
png_error(png_ptr, "Duplicate PLTE chunk");
png_ptr->mode |= PNG_HAVE_PLTE;
1996-06-05 20:50:50 +00:00
2001-05-07 19:52:45 +00:00
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;
}
1996-06-05 20:50:50 +00:00
#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
{
1997-01-17 07:34:35 +00:00
png_crc_finish(png_ptr, length);
1996-06-05 20:50:50 +00:00
return;
}
#endif
2000-12-28 13:50:05 +00:00
if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
1996-06-05 20:50:50 +00:00
{
if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
{
png_warning(png_ptr, "Invalid palette chunk");
1997-01-17 07:34:35 +00:00
png_crc_finish(png_ptr, length);
1996-06-05 20:50:50 +00:00
return;
}
else
{
png_error(png_ptr, "Invalid palette chunk");
}
}
1995-07-20 07:43:20 +00:00
num = (int)length / 3;
2000-04-10 00:06:13 +00:00
2000-06-04 19:29:29 +00:00
#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
1996-01-26 07:38:47 +00:00
for (i = 0; i < num; i++)
1995-07-20 07:43:20 +00:00
{
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];
}
2000-06-04 19:29:29 +00:00
#endif
1997-01-17 07:34:35 +00:00
/* 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. */
1998-01-31 03:45:12 +00:00
#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
1997-01-17 07:34:35 +00:00
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1998-01-31 03:45:12 +00:00
#endif
1997-01-17 07:34:35 +00:00
{
1997-05-16 07:46:07 +00:00
png_crc_finish(png_ptr, 0);
1997-01-17 07:34:35 +00:00
}
1998-01-31 03:45:12 +00:00
#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
1997-01-17 07:34:35 +00:00
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)
{
1998-01-04 04:40:55 +00:00
png_chunk_error(png_ptr, "CRC error");
1997-01-17 07:34:35 +00:00
}
else
{
1998-01-04 04:40:55 +00:00
png_chunk_warning(png_ptr, "CRC error");
1997-01-17 07:34:35 +00:00
return;
}
}
1997-05-16 07:46:07 +00:00
/* Otherwise, we (optionally) emit a warning and use the chunk. */
1997-01-17 07:34:35 +00:00
else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
{
1998-01-04 04:40:55 +00:00
png_chunk_warning(png_ptr, "CRC error");
1997-01-17 07:34:35 +00:00
}
}
1998-01-31 03:45:12 +00:00
#endif
2000-04-10 00:06:13 +00:00
1997-05-16 07:46:07 +00:00
png_set_PLTE(png_ptr, info_ptr, palette, num);
1998-04-21 20:03:57 +00:00
2000-05-01 14:31:54 +00:00
#if defined(PNG_READ_tRNS_SUPPORTED)
1998-04-21 20:03:57 +00:00
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{
2000-02-05 05:40:16 +00:00
if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
1998-04-21 20:03:57 +00:00
{
2000-04-10 00:06:13 +00:00
if (png_ptr->num_trans > (png_uint_16)num)
1998-04-21 20:03:57 +00:00
{
png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
2000-04-10 00:06:13 +00:00
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;
1998-04-21 20:03:57 +00:00
}
}
}
#endif
1997-01-17 07:34:35 +00:00
}
1996-06-05 20:50:50 +00:00
2000-05-06 19:09:57 +00:00
void /* PRIVATE */
1997-01-17 07:34:35 +00:00
png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
{
1997-05-16 07:46:07 +00:00
png_debug(1, "in png_handle_IEND\n");
1997-01-17 07:34:35 +00:00
if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
{
png_error(png_ptr, "No image in file");
}
2000-02-05 05:40:16 +00:00
png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
1997-01-17 07:34:35 +00:00
if (length != 0)
{
png_warning(png_ptr, "Incorrect IEND chunk length");
}
1997-05-16 07:46:07 +00:00
png_crc_finish(png_ptr, length);
2004-08-04 11:34:52 +00:00
2007-05-21 18:27:47 +00:00
info_ptr =info_ptr; /* quiet compiler warnings about unused info_ptr */
1995-07-20 07:43:20 +00:00
}
1995-09-26 10:22:39 +00:00
#if defined(PNG_READ_gAMA_SUPPORTED)
2000-05-06 19:09:57 +00:00
void /* PRIVATE */
1997-01-17 07:34:35 +00:00
png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1995-07-20 07:43:20 +00:00
{
2000-02-05 05:40:16 +00:00
png_fixed_point igamma;
1999-12-10 15:43:02 +00:00
#ifdef PNG_FLOATING_POINT_SUPPORTED
1997-05-16 07:46:07 +00:00
float file_gamma;
1999-12-10 15:43:02 +00:00
#endif
1995-07-20 07:43:20 +00:00
png_byte buf[4];
1997-05-16 07:46:07 +00:00
png_debug(1, "in png_handle_gAMA\n");
1996-06-05 20:50:50 +00:00
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before gAMA");
1997-01-17 07:34:35 +00:00
else if (png_ptr->mode & PNG_HAVE_IDAT)
{
png_warning(png_ptr, "Invalid gAMA after IDAT");
png_crc_finish(png_ptr, length);
return;
}
1996-06-05 20:50:50 +00:00
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");
1998-01-08 02:54:20 +00:00
2004-08-04 11:34:52 +00:00
if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
1998-01-08 02:54:20 +00:00
#if defined(PNG_READ_sRGB_SUPPORTED)
&& !(info_ptr->valid & PNG_INFO_sRGB)
#endif
)
1997-01-17 07:34:35 +00:00
{
png_warning(png_ptr, "Duplicate gAMA chunk");
png_crc_finish(png_ptr, length);
return;
}
1996-06-05 20:50:50 +00:00
1995-07-20 07:43:20 +00:00
if (length != 4)
{
1996-01-10 08:56:49 +00:00
png_warning(png_ptr, "Incorrect gAMA chunk length");
1997-01-17 07:34:35 +00:00
png_crc_finish(png_ptr, length);
1995-07-20 07:43:20 +00:00
return;
}
png_crc_read(png_ptr, buf, 4);
1997-01-17 07:34:35 +00:00
if (png_crc_finish(png_ptr, 0))
return;
2000-02-05 05:40:16 +00:00
igamma = (png_fixed_point)png_get_uint_32(buf);
1995-07-20 07:43:20 +00:00
/* check for zero gamma */
1997-05-16 07:46:07 +00:00
if (igamma == 0)
2001-05-07 19:52:45 +00:00
{
png_warning(png_ptr,
"Ignoring gAMA chunk with gamma=0");
return;
}
1995-07-20 07:43:20 +00:00
1998-01-01 13:13:13 +00:00
#if defined(PNG_READ_sRGB_SUPPORTED)
2006-03-10 16:19:04 +00:00
if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
2004-08-10 02:50:32 +00:00
if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
1998-01-01 13:13:13 +00:00
{
png_warning(png_ptr,
"Ignoring incorrect gAMA value when sRGB is also present");
2000-07-08 18:19:41 +00:00
#ifndef PNG_NO_CONSOLE_IO
2000-02-05 05:40:16 +00:00
fprintf(stderr, "gamma = (%d/100000)\n", (int)igamma);
1998-01-08 02:54:20 +00:00
#endif
1998-01-01 13:13:13 +00:00
return;
}
#endif /* PNG_READ_sRGB_SUPPORTED */
1999-12-10 15:43:02 +00:00
#ifdef PNG_FLOATING_POINT_SUPPORTED
1998-03-08 01:45:37 +00:00
file_gamma = (float)igamma / (float)100000.0;
2000-02-05 05:40:16 +00:00
# ifdef PNG_READ_GAMMA_SUPPORTED
png_ptr->gamma = file_gamma;
# endif
png_set_gAMA(png_ptr, info_ptr, file_gamma);
1999-12-10 15:43:02 +00:00
#endif
#ifdef PNG_FIXED_POINT_SUPPORTED
png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
#endif
1995-07-20 07:43:20 +00:00
}
1995-09-26 10:22:39 +00:00
#endif
1995-07-20 07:43:20 +00:00
1995-09-26 10:22:39 +00:00
#if defined(PNG_READ_sBIT_SUPPORTED)
2000-05-06 19:09:57 +00:00
void /* PRIVATE */
1997-01-17 07:34:35 +00:00
png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1995-07-20 07:43:20 +00:00
{
1997-05-16 07:46:07 +00:00
png_size_t truelen;
1996-01-26 07:38:47 +00:00
png_byte buf[4];
1996-01-10 08:56:49 +00:00
1997-05-16 07:46:07 +00:00
png_debug(1, "in png_handle_sBIT\n");
1996-01-10 08:56:49 +00:00
buf[0] = buf[1] = buf[2] = buf[3] = 0;
1995-07-20 07:43:20 +00:00
1996-06-05 20:50:50 +00:00
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before sBIT");
1997-01-17 07:34:35 +00:00
else if (png_ptr->mode & PNG_HAVE_IDAT)
{
png_warning(png_ptr, "Invalid sBIT after IDAT");
png_crc_finish(png_ptr, length);
return;
}
1996-06-05 20:50:50 +00:00
else if (png_ptr->mode & PNG_HAVE_PLTE)
1998-01-01 13:13:13 +00:00
{
1996-06-05 20:50:50 +00:00
/* Should be an error, but we can cope with it */
png_warning(png_ptr, "Out of place sBIT chunk");
1998-01-01 13:13:13 +00:00
}
2004-08-04 11:34:52 +00:00
if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
1997-01-17 07:34:35 +00:00
{
png_warning(png_ptr, "Duplicate sBIT chunk");
png_crc_finish(png_ptr, length);
return;
}
1996-06-05 20:50:50 +00:00
1995-07-20 07:43:20 +00:00
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1997-01-17 07:34:35 +00:00
truelen = 3;
1995-07-20 07:43:20 +00:00
else
1997-05-16 07:46:07 +00:00
truelen = (png_size_t)png_ptr->channels;
1995-07-20 07:43:20 +00:00
2004-07-28 13:20:44 +00:00
if (length != truelen || length > 4)
1995-07-20 07:43:20 +00:00
{
1996-01-10 08:56:49 +00:00
png_warning(png_ptr, "Incorrect sBIT chunk length");
1997-01-17 07:34:35 +00:00
png_crc_finish(png_ptr, length);
1996-01-26 07:38:47 +00:00
return;
1995-07-20 07:43:20 +00:00
}
1997-05-16 07:46:07 +00:00
png_crc_read(png_ptr, buf, truelen);
1997-01-17 07:34:35 +00:00
if (png_crc_finish(png_ptr, 0))
return;
1995-07-20 07:43:20 +00:00
if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
{
1995-12-19 09:22:19 +00:00
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];
1995-11-28 17:22:13 +00:00
}
else
{
1996-01-26 07:38:47 +00:00
png_ptr->sig_bit.gray = buf[0];
1998-12-29 17:47:59 +00:00
png_ptr->sig_bit.red = buf[0];
png_ptr->sig_bit.green = buf[0];
png_ptr->sig_bit.blue = buf[0];
1995-12-19 09:22:19 +00:00
png_ptr->sig_bit.alpha = buf[1];
1995-11-28 17:22:13 +00:00
}
1997-05-16 07:46:07 +00:00
png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
1995-07-20 07:43:20 +00:00
}
1995-09-26 10:22:39 +00:00
#endif
1995-07-20 07:43:20 +00:00
1995-09-26 10:22:39 +00:00
#if defined(PNG_READ_cHRM_SUPPORTED)
2000-05-06 19:09:57 +00:00
void /* PRIVATE */
1997-01-17 07:34:35 +00:00
png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1995-07-20 07:43:20 +00:00
{
2006-06-05 16:47:25 +00:00
png_byte buf[4];
1999-12-10 15:43:02 +00:00
#ifdef PNG_FLOATING_POINT_SUPPORTED
1995-07-20 07:43:20 +00:00
float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
1999-12-10 15:43:02 +00:00
#endif
2000-02-05 05:40:16 +00:00
png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
1999-12-10 15:43:02 +00:00
int_y_green, int_x_blue, int_y_blue;
1995-07-20 07:43:20 +00:00
2002-02-22 05:14:23 +00:00
png_uint_32 uint_x, uint_y;
1997-05-16 07:46:07 +00:00
png_debug(1, "in png_handle_cHRM\n");
1996-06-05 20:50:50 +00:00
if (!(png_ptr->mode & PNG_HAVE_IHDR))
2000-02-05 05:40:16 +00:00
png_error(png_ptr, "Missing IHDR before cHRM");
1997-01-17 07:34:35 +00:00
else if (png_ptr->mode & PNG_HAVE_IDAT)
{
png_warning(png_ptr, "Invalid cHRM after IDAT");
png_crc_finish(png_ptr, length);
return;
}
1996-06-05 20:50:50 +00:00
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");
1998-01-08 02:54:20 +00:00
2004-08-04 11:34:52 +00:00
if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
1998-01-08 02:54:20 +00:00
#if defined(PNG_READ_sRGB_SUPPORTED)
&& !(info_ptr->valid & PNG_INFO_sRGB)
#endif
)
1997-01-17 07:34:35 +00:00
{
png_warning(png_ptr, "Duplicate cHRM chunk");
png_crc_finish(png_ptr, length);
return;
}
1996-06-05 20:50:50 +00:00
1995-07-20 07:43:20 +00:00
if (length != 32)
{
1996-01-10 08:56:49 +00:00
png_warning(png_ptr, "Incorrect cHRM chunk length");
1997-01-17 07:34:35 +00:00
png_crc_finish(png_ptr, length);
1996-01-26 07:38:47 +00:00
return;
1995-07-20 07:43:20 +00:00
}
2006-06-05 16:47:25 +00:00
png_crc_read(png_ptr, buf, 4);
uint_x = png_get_uint_32(buf);
2006-06-05 16:47:25 +00:00
png_crc_read(png_ptr, buf, 4);
uint_y = png_get_uint_32(buf);
2002-02-22 05:14:23 +00:00
if (uint_x > 80000L || uint_y > 80000L ||
uint_x + uint_y > 100000L)
1997-01-17 07:34:35 +00:00
{
png_warning(png_ptr, "Invalid cHRM white point");
2006-06-05 16:47:25 +00:00
png_crc_finish(png_ptr, 24);
1997-01-17 07:34:35 +00:00
return;
}
2002-02-22 05:14:23 +00:00
int_x_white = (png_fixed_point)uint_x;
int_y_white = (png_fixed_point)uint_y;
1995-07-20 07:43:20 +00:00
2006-06-05 16:47:25 +00:00
png_crc_read(png_ptr, buf, 4);
uint_x = png_get_uint_32(buf);
png_crc_read(png_ptr, buf, 4);
uint_y = png_get_uint_32(buf);
2006-02-22 15:19:25 +00:00
if (uint_x + uint_y > 100000L)
1997-01-17 07:34:35 +00:00
{
png_warning(png_ptr, "Invalid cHRM red point");
2006-06-05 16:47:25 +00:00
png_crc_finish(png_ptr, 16);
1997-01-17 07:34:35 +00:00
return;
}
2002-02-22 05:14:23 +00:00
int_x_red = (png_fixed_point)uint_x;
int_y_red = (png_fixed_point)uint_y;
1995-07-20 07:43:20 +00:00
2006-06-05 16:47:25 +00:00
png_crc_read(png_ptr, buf, 4);
uint_x = png_get_uint_32(buf);
png_crc_read(png_ptr, buf, 4);
uint_y = png_get_uint_32(buf);
2006-02-22 15:19:25 +00:00
if (uint_x + uint_y > 100000L)
1997-01-17 07:34:35 +00:00
{
png_warning(png_ptr, "Invalid cHRM green point");
2006-06-05 16:47:25 +00:00
png_crc_finish(png_ptr, 8);
1997-01-17 07:34:35 +00:00
return;
}
2002-02-22 05:14:23 +00:00
int_x_green = (png_fixed_point)uint_x;
int_y_green = (png_fixed_point)uint_y;
1995-07-20 07:43:20 +00:00
2006-06-05 16:47:25 +00:00
png_crc_read(png_ptr, buf, 4);
uint_x = png_get_uint_32(buf);
png_crc_read(png_ptr, buf, 4);
uint_y = png_get_uint_32(buf);
2006-02-22 15:19:25 +00:00
if (uint_x + uint_y > 100000L)
1997-01-17 07:34:35 +00:00
{
png_warning(png_ptr, "Invalid cHRM blue point");
2006-06-05 16:47:25 +00:00
png_crc_finish(png_ptr, 0);
1997-01-17 07:34:35 +00:00
return;
}
2002-02-22 05:14:23 +00:00
int_x_blue = (png_fixed_point)uint_x;
int_y_blue = (png_fixed_point)uint_y;
1999-12-10 15:43:02 +00:00
#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
1995-07-20 07:43:20 +00:00
1998-01-01 13:13:13 +00:00
#if defined(PNG_READ_sRGB_SUPPORTED)
if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB))
1998-01-01 13:13:13 +00:00
{
2004-08-10 02:50:32 +00:00
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))
1998-01-04 04:40:55 +00:00
{
png_warning(png_ptr,
"Ignoring incorrect cHRM value when sRGB is also present");
2000-07-08 18:19:41 +00:00
#ifndef PNG_NO_CONSOLE_IO
1999-12-10 15:43:02 +00:00
#ifdef PNG_FLOATING_POINT_SUPPORTED
1998-01-08 02:54:20 +00:00
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);
1999-12-10 15:43:02 +00:00
#else
2000-02-05 05:40:16 +00:00
fprintf(stderr,"wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
1999-12-10 15:43:02 +00:00
int_x_white, int_y_white, int_x_red, int_y_red);
2000-02-05 05:40:16 +00:00
fprintf(stderr,"gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
1999-12-10 15:43:02 +00:00
int_x_green, int_y_green, int_x_blue, int_y_blue);
1998-01-08 02:54:20 +00:00
#endif
2000-07-08 18:19:41 +00:00
#endif /* PNG_NO_CONSOLE_IO */
1998-01-04 04:40:55 +00:00
}
2006-06-05 16:47:25 +00:00
png_crc_finish(png_ptr, 0);
1998-01-01 13:13:13 +00:00
return;
}
#endif /* PNG_READ_sRGB_SUPPORTED */
1999-12-10 15:43:02 +00:00
#ifdef PNG_FLOATING_POINT_SUPPORTED
1997-05-16 07:46:07 +00:00
png_set_cHRM(png_ptr, info_ptr,
1996-01-26 07:38:47 +00:00
white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
1999-12-10 15:43:02 +00:00
#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
2006-06-05 16:47:25 +00:00
if (png_crc_finish(png_ptr, 0))
return;
1995-07-20 07:43:20 +00:00
}
1995-09-26 10:22:39 +00:00
#endif
1995-07-20 07:43:20 +00:00
1998-01-01 13:13:13 +00:00
#if defined(PNG_READ_sRGB_SUPPORTED)
2000-05-06 19:09:57 +00:00
void /* PRIVATE */
1998-01-01 13:13:13 +00:00
png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
{
1998-01-17 04:06:18 +00:00
int intent;
1998-01-01 13:13:13 +00:00
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");
1998-01-08 02:54:20 +00:00
2004-08-04 11:34:52 +00:00
if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
1998-01-01 13:13:13 +00:00
{
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 */
1998-01-31 03:45:12 +00:00
if (intent >= PNG_sRGB_INTENT_LAST)
1998-01-01 13:13:13 +00:00
{
png_warning(png_ptr, "Unknown sRGB intent");
return;
}
1998-01-31 03:45:12 +00:00
#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
2006-03-10 16:19:04 +00:00
if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA))
2000-02-05 05:40:16 +00:00
{
2004-07-18 03:45:44 +00:00
png_fixed_point igamma;
2000-02-05 05:40:16 +00:00
#ifdef PNG_FIXED_POINT_SUPPORTED
2004-07-18 03:45:44 +00:00
igamma=info_ptr->int_gamma;
1999-12-10 15:43:02 +00:00
#else
2000-02-05 05:40:16 +00:00
# ifdef PNG_FLOATING_POINT_SUPPORTED
2004-07-18 03:45:44 +00:00
igamma=(png_fixed_point)(info_ptr->gamma * 100000.);
1999-12-10 15:43:02 +00:00
# endif
#endif
2004-08-10 02:50:32 +00:00
if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
1998-01-08 02:54:20 +00:00
{
png_warning(png_ptr,
"Ignoring incorrect gAMA value when sRGB is also present");
2000-07-08 18:19:41 +00:00
#ifndef PNG_NO_CONSOLE_IO
2000-02-05 05:40:16 +00:00
# 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
1998-01-08 02:54:20 +00:00
#endif
}
2000-02-05 05:40:16 +00:00
}
1998-01-08 02:54:20 +00:00
#endif /* PNG_READ_gAMA_SUPPORTED */
#ifdef PNG_READ_cHRM_SUPPORTED
2000-05-01 14:31:54 +00:00
#ifdef PNG_FIXED_POINT_SUPPORTED
2006-03-10 16:19:04 +00:00
if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
2004-08-10 02:50:32 +00:00
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))
1998-01-08 02:54:20 +00:00
{
png_warning(png_ptr,
"Ignoring incorrect cHRM value when sRGB is also present");
}
2000-05-01 14:31:54 +00:00
#endif /* PNG_FIXED_POINT_SUPPORTED */
1998-01-08 02:54:20 +00:00
#endif /* PNG_READ_cHRM_SUPPORTED */
1998-01-01 13:13:13 +00:00
1998-01-08 02:54:20 +00:00
png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
1998-01-01 13:13:13 +00:00
}
1998-01-08 02:54:20 +00:00
#endif /* PNG_READ_sRGB_SUPPORTED */
1999-12-10 15:43:02 +00:00
#if defined(PNG_READ_iCCP_SUPPORTED)
2000-05-06 19:09:57 +00:00
void /* PRIVATE */
1999-12-10 15:43:02 +00:00
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;
2002-02-22 05:14:23 +00:00
png_bytep pC;
1999-12-10 15:43:02 +00:00
png_charp profile;
png_uint_32 skip = 0;
2004-07-18 03:45:44 +00:00
png_uint_32 profile_size, profile_length;
2000-04-02 03:10:05 +00:00
png_size_t slength, prefix_length, data_length;
1999-12-10 15:43:02 +00:00
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");
2004-08-04 11:34:52 +00:00
if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
1999-12-10 15:43:02 +00:00
{
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;
2001-04-20 15:32:10 +00:00
png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
1999-12-10 15:43:02 +00:00
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 */ ;
2000-06-04 19:29:29 +00:00
1999-12-10 15:43:02 +00:00
++profile;
2000-06-04 19:29:29 +00:00
/* there should be at least one zero (the compression type byte)
1999-12-10 15:43:02 +00:00
following the separator, and we should be on it */
2007-07-19 01:05:37 +00:00
if ( profile >= chunkdata + slength - 1)
1999-12-10 15:43:02 +00:00
{
png_free(png_ptr, chunkdata);
2000-11-10 18:26:19 +00:00
png_warning(png_ptr, "Malformed iCCP chunk");
2000-04-14 19:20:47 +00:00
return;
1999-12-10 15:43:02 +00:00
}
2000-06-04 19:29:29 +00:00
/* compression_type should always be zero */
1999-12-10 15:43:02 +00:00
compression_type = *profile++;
2000-11-10 18:26:19 +00:00
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) */
}
1999-12-10 15:43:02 +00:00
prefix_length = profile - chunkdata;
chunkdata = png_decompress_chunk(png_ptr, compression_type, chunkdata,
2000-04-02 03:10:05 +00:00
slength, prefix_length, &data_length);
1999-12-10 15:43:02 +00:00
2000-11-10 18:26:19 +00:00
profile_length = data_length - prefix_length;
2001-01-12 21:13:06 +00:00
2001-12-04 12:30:43 +00:00
if ( prefix_length > data_length || profile_length < 4)
2001-06-23 13:03:17 +00:00
{
png_free(png_ptr, chunkdata);
png_warning(png_ptr, "Profile size field missing from iCCP chunk");
return;
}
2001-01-12 21:13:06 +00:00
/* Check the profile_size recorded in the first 32 bits of the ICC profile */
2002-02-22 05:14:23 +00:00
pC = (png_bytep)(chunkdata+prefix_length);
profile_size = ((*(pC ))<<24) |
((*(pC+1))<<16) |
((*(pC+2))<< 8) |
((*(pC+3)) );
2000-11-10 18:26:19 +00:00
if(profile_size < profile_length)
profile_length = profile_size;
if(profile_size > profile_length)
{
2001-06-23 13:03:17 +00:00
png_free(png_ptr, chunkdata);
2006-03-02 13:23:18 +00:00
png_warning(png_ptr, "Ignoring truncated iCCP profile.");
2000-11-10 18:26:19 +00:00
return;
}
1999-12-10 15:43:02 +00:00
png_set_iCCP(png_ptr, info_ptr, chunkdata, compression_type,
2000-12-28 13:50:05 +00:00
chunkdata + prefix_length, profile_length);
1999-12-10 15:43:02 +00:00
png_free(png_ptr, chunkdata);
}
#endif /* PNG_READ_iCCP_SUPPORTED */
#if defined(PNG_READ_sPLT_SUPPORTED)
2000-05-06 19:09:57 +00:00
void /* PRIVATE */
1999-12-10 15:43:02 +00:00
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;
2000-03-21 11:13:06 +00:00
png_sPLT_t new_palette;
2000-06-04 19:29:29 +00:00
#ifdef PNG_NO_POINTER_INDEXING
png_sPLT_entryp pp;
#endif
1999-12-10 15:43:02 +00:00
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);
2001-04-20 15:32:10 +00:00
slength = (png_size_t)length;
2001-05-07 19:52:45 +00:00
png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
1999-12-10 15:43:02 +00:00
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 */
2007-07-19 01:05:37 +00:00
if (entry_start > chunkdata + slength - 2)
1999-12-10 15:43:02 +00:00
{
png_free(png_ptr, chunkdata);
2000-04-14 19:20:47 +00:00
png_warning(png_ptr, "malformed sPLT chunk");
return;
1999-12-10 15:43:02 +00:00
}
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);
2001-05-07 19:52:45 +00:00
png_warning(png_ptr, "sPLT chunk has bad length");
return;
1999-12-10 15:43:02 +00:00
}
2006-02-21 04:09:05 +00:00
new_palette.nentries = (png_int_32) ( data_length / entry_size);
2004-08-04 11:34:52 +00:00
if ((png_uint_32) new_palette.nentries > (png_uint_32) (PNG_SIZE_MAX /
png_sizeof(png_sPLT_entry)))
2004-07-28 13:20:44 +00:00
{
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;
}
1999-12-10 15:43:02 +00:00
2000-06-04 19:29:29 +00:00
#ifndef PNG_NO_POINTER_INDEXING
1999-12-10 15:43:02 +00:00
for (i = 0; i < new_palette.nentries; i++)
{
2000-03-21 11:13:06 +00:00
png_sPLT_entryp pp = new_palette.entries + i;
1999-12-10 15:43:02 +00:00
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;
}
2000-06-04 19:29:29 +00:00
#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
1999-12-10 15:43:02 +00:00
/* discard all chunk data except the name and stash that */
new_palette.name = (png_charp)chunkdata;
2000-02-18 19:48:52 +00:00
png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
1999-12-10 15:43:02 +00:00
png_free(png_ptr, chunkdata);
png_free(png_ptr, new_palette.entries);
}
#endif /* PNG_READ_sPLT_SUPPORTED */
1995-09-26 10:22:39 +00:00
#if defined(PNG_READ_tRNS_SUPPORTED)
2000-05-06 19:09:57 +00:00
void /* PRIVATE */
1997-01-17 07:34:35 +00:00
png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1995-07-20 07:43:20 +00:00
{
2002-06-20 11:54:34 +00:00
png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
2000-12-28 13:50:05 +00:00
1997-05-16 07:46:07 +00:00
png_debug(1, "in png_handle_tRNS\n");
1996-06-05 20:50:50 +00:00
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before tRNS");
1997-01-17 07:34:35 +00:00
else if (png_ptr->mode & PNG_HAVE_IDAT)
{
png_warning(png_ptr, "Invalid tRNS after IDAT");
png_crc_finish(png_ptr, length);
return;
}
2000-02-05 05:40:16 +00:00
else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
1997-01-17 07:34:35 +00:00
{
1998-02-09 02:56:40 +00:00
png_warning(png_ptr, "Duplicate tRNS chunk");
1997-01-17 07:34:35 +00:00
png_crc_finish(png_ptr, length);
return;
}
1996-06-05 20:50:50 +00:00
2004-08-04 11:34:52 +00:00
if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
1995-07-20 07:43:20 +00:00
{
2004-08-04 11:34:52 +00:00
png_byte buf[2];
if (length != 2)
1995-07-20 07:43:20 +00:00
{
1996-01-10 08:56:49 +00:00
png_warning(png_ptr, "Incorrect tRNS chunk length");
1997-01-17 07:34:35 +00:00
png_crc_finish(png_ptr, length);
1995-07-20 07:43:20 +00:00
return;
}
2004-08-04 11:34:52 +00:00
png_crc_read(png_ptr, buf, 2);
png_ptr->num_trans = 1;
2008-04-12 11:59:47 +00:00
png_ptr->trans_values.gray = png_get_uint_16(buf);
1995-07-20 07:43:20 +00:00
}
else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
{
png_byte buf[6];
if (length != 6)
{
1996-01-10 08:56:49 +00:00
png_warning(png_ptr, "Incorrect tRNS chunk length");
1997-01-17 07:34:35 +00:00
png_crc_finish(png_ptr, length);
1995-07-20 07:43:20 +00:00
return;
}
1997-05-16 07:46:07 +00:00
png_crc_read(png_ptr, buf, (png_size_t)length);
1998-01-01 13:13:13 +00:00
png_ptr->num_trans = 1;
2008-04-12 11:59:47 +00:00
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);
1995-07-20 07:43:20 +00:00
}
2004-08-04 11:34:52 +00:00
else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1995-07-20 07:43:20 +00:00
{
2004-08-04 11:34:52 +00:00
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)
1995-07-20 07:43:20 +00:00
{
1996-01-10 08:56:49 +00:00
png_warning(png_ptr, "Incorrect tRNS chunk length");
1997-01-17 07:34:35 +00:00
png_crc_finish(png_ptr, length);
1996-01-26 07:38:47 +00:00
return;
}
2004-08-04 11:34:52 +00:00
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;
1996-01-26 07:38:47 +00:00
}
else
1996-06-05 20:50:50 +00:00
{
png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
1997-01-17 07:34:35 +00:00
png_crc_finish(png_ptr, length);
1996-06-05 20:50:50 +00:00
return;
}
1995-07-20 07:43:20 +00:00
1997-01-17 07:34:35 +00:00
if (png_crc_finish(png_ptr, 0))
2007-05-14 19:27:48 +00:00
{
png_ptr->num_trans = 0;
1997-01-17 07:34:35 +00:00
return;
2007-05-14 19:27:48 +00:00
}
1997-01-17 07:34:35 +00:00
2000-12-28 13:50:05 +00:00
png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
1995-07-20 07:43:20 +00:00
&(png_ptr->trans_values));
}
1995-09-26 10:22:39 +00:00
#endif
1995-07-20 07:43:20 +00:00
1995-09-26 10:22:39 +00:00
#if defined(PNG_READ_bKGD_SUPPORTED)
2000-05-06 19:09:57 +00:00
void /* PRIVATE */
1997-01-17 07:34:35 +00:00
png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1995-07-20 07:43:20 +00:00
{
1997-05-16 07:46:07 +00:00
png_size_t truelen;
1995-07-20 07:43:20 +00:00
png_byte buf[6];
1997-05-16 07:46:07 +00:00
png_debug(1, "in png_handle_bKGD\n");
1996-06-05 20:50:50 +00:00
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before bKGD");
1997-01-17 07:34:35 +00:00
else if (png_ptr->mode & PNG_HAVE_IDAT)
{
png_warning(png_ptr, "Invalid bKGD after IDAT");
png_crc_finish(png_ptr, length);
return;
}
1996-06-05 20:50:50 +00:00
else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
!(png_ptr->mode & PNG_HAVE_PLTE))
{
png_warning(png_ptr, "Missing PLTE before bKGD");
1997-01-17 07:34:35 +00:00
png_crc_finish(png_ptr, length);
return;
}
2000-02-05 05:40:16 +00:00
else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
1997-01-17 07:34:35 +00:00
{
png_warning(png_ptr, "Duplicate bKGD chunk");
png_crc_finish(png_ptr, length);
1996-06-05 20:50:50 +00:00
return;
}
1995-07-20 07:43:20 +00:00
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;
1997-01-17 07:34:35 +00:00
if (length != truelen)
1995-07-20 07:43:20 +00:00
{
1996-01-26 07:38:47 +00:00
png_warning(png_ptr, "Incorrect bKGD chunk length");
1997-01-17 07:34:35 +00:00
png_crc_finish(png_ptr, length);
1995-07-20 07:43:20 +00:00
return;
}
1997-05-16 07:46:07 +00:00
png_crc_read(png_ptr, buf, truelen);
1997-01-17 07:34:35 +00:00
if (png_crc_finish(png_ptr, 0))
return;
1996-06-05 20:50:50 +00:00
/* 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
1997-01-17 07:34:35 +00:00
* from the info_ptr struct. */
1995-07-20 07:43:20 +00:00
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1996-06-05 20:50:50 +00:00
{
1995-07-20 07:43:20 +00:00
png_ptr->background.index = buf[0];
2008-02-06 16:32:29 +00:00
if (info_ptr && info_ptr->num_palette)
1999-09-17 17:27:26 +00:00
{
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;
}
1996-06-05 20:50:50 +00:00
}
1997-05-16 07:46:07 +00:00
else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
1996-06-05 20:50:50 +00:00
{
png_ptr->background.red =
png_ptr->background.green =
png_ptr->background.blue =
1995-07-20 07:43:20 +00:00
png_ptr->background.gray = png_get_uint_16(buf);
1996-06-05 20:50:50 +00:00
}
1995-07-20 07:43:20 +00:00
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);
}
1997-05-16 07:46:07 +00:00
png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
1995-07-20 07:43:20 +00:00
}
1995-09-26 10:22:39 +00:00
#endif
1995-07-20 07:43:20 +00:00
1995-09-26 10:22:39 +00:00
#if defined(PNG_READ_hIST_SUPPORTED)
2000-05-06 19:09:57 +00:00
void /* PRIVATE */
1997-01-17 07:34:35 +00:00
png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1995-07-20 07:43:20 +00:00
{
2004-07-28 13:20:44 +00:00
unsigned int num, i;
2002-06-20 11:54:34 +00:00
png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
1995-07-20 07:43:20 +00:00
1997-05-16 07:46:07 +00:00
png_debug(1, "in png_handle_hIST\n");
1996-06-05 20:50:50 +00:00
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before hIST");
1997-01-17 07:34:35 +00:00
else if (png_ptr->mode & PNG_HAVE_IDAT)
{
png_warning(png_ptr, "Invalid hIST after IDAT");
png_crc_finish(png_ptr, length);
return;
}
1996-06-05 20:50:50 +00:00
else if (!(png_ptr->mode & PNG_HAVE_PLTE))
{
png_warning(png_ptr, "Missing PLTE before hIST");
1997-01-17 07:34:35 +00:00
png_crc_finish(png_ptr, length);
return;
}
2000-02-05 05:40:16 +00:00
else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
1997-01-17 07:34:35 +00:00
{
png_warning(png_ptr, "Duplicate hIST chunk");
png_crc_finish(png_ptr, length);
1996-06-05 20:50:50 +00:00
return;
}
2004-07-28 13:20:44 +00:00
num = length / 2 ;
2004-08-04 11:34:52 +00:00
if (num != (unsigned int) png_ptr->num_palette || num >
(unsigned int) PNG_MAX_PALETTE_LENGTH)
1996-01-26 07:38:47 +00:00
{
png_warning(png_ptr, "Incorrect hIST chunk length");
1997-01-17 07:34:35 +00:00
png_crc_finish(png_ptr, length);
1996-01-26 07:38:47 +00:00
return;
}
1995-07-20 07:43:20 +00:00
1996-01-26 07:38:47 +00:00
for (i = 0; i < num; i++)
1995-07-20 07:43:20 +00:00
{
png_byte buf[2];
png_crc_read(png_ptr, buf, 2);
2000-12-28 13:50:05 +00:00
readbuf[i] = png_get_uint_16(buf);
1995-07-20 07:43:20 +00:00
}
1997-01-17 07:34:35 +00:00
if (png_crc_finish(png_ptr, 0))
return;
2000-12-28 13:50:05 +00:00
png_set_hIST(png_ptr, info_ptr, readbuf);
1995-07-20 07:43:20 +00:00
}
1995-09-26 10:22:39 +00:00
#endif
1995-07-20 07:43:20 +00:00
1995-09-26 10:22:39 +00:00
#if defined(PNG_READ_pHYs_SUPPORTED)
2000-05-06 19:09:57 +00:00
void /* PRIVATE */
1997-01-17 07:34:35 +00:00
png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1995-07-20 07:43:20 +00:00
{
png_byte buf[9];
png_uint_32 res_x, res_y;
int unit_type;
1997-05-16 07:46:07 +00:00
png_debug(1, "in png_handle_pHYs\n");
1996-06-05 20:50:50 +00:00
if (!(png_ptr->mode & PNG_HAVE_IHDR))
2000-05-29 13:58:03 +00:00
png_error(png_ptr, "Missing IHDR before pHYs");
1997-01-17 07:34:35 +00:00
else if (png_ptr->mode & PNG_HAVE_IDAT)
{
2000-05-29 13:58:03 +00:00
png_warning(png_ptr, "Invalid pHYs after IDAT");
1997-01-17 07:34:35 +00:00
png_crc_finish(png_ptr, length);
return;
}
2000-02-05 05:40:16 +00:00
else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
1997-01-17 07:34:35 +00:00
{
2000-05-29 13:58:03 +00:00
png_warning(png_ptr, "Duplicate pHYs chunk");
1997-01-17 07:34:35 +00:00
png_crc_finish(png_ptr, length);
return;
}
1996-06-05 20:50:50 +00:00
1995-07-20 07:43:20 +00:00
if (length != 9)
{
1996-01-26 07:38:47 +00:00
png_warning(png_ptr, "Incorrect pHYs chunk length");
1997-01-17 07:34:35 +00:00
png_crc_finish(png_ptr, length);
1995-07-20 07:43:20 +00:00
return;
1996-01-26 07:38:47 +00:00
}
1995-07-20 07:43:20 +00:00
png_crc_read(png_ptr, buf, 9);
1997-01-17 07:34:35 +00:00
if (png_crc_finish(png_ptr, 0))
return;
1995-07-20 07:43:20 +00:00
res_x = png_get_uint_32(buf);
res_y = png_get_uint_32(buf + 4);
unit_type = buf[8];
1997-05-16 07:46:07 +00:00
png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
1995-07-20 07:43:20 +00:00
}
1995-09-26 10:22:39 +00:00
#endif
1995-07-20 07:43:20 +00:00
1995-09-26 10:22:39 +00:00
#if defined(PNG_READ_oFFs_SUPPORTED)
2000-05-06 19:09:57 +00:00
void /* PRIVATE */
1997-01-17 07:34:35 +00:00
png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1995-07-20 07:43:20 +00:00
{
png_byte buf[9];
1999-12-10 15:43:02 +00:00
png_int_32 offset_x, offset_y;
1995-07-20 07:43:20 +00:00
int unit_type;
1997-05-16 07:46:07 +00:00
png_debug(1, "in png_handle_oFFs\n");
1996-06-05 20:50:50 +00:00
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before oFFs");
1997-01-17 07:34:35 +00:00
else if (png_ptr->mode & PNG_HAVE_IDAT)
{
png_warning(png_ptr, "Invalid oFFs after IDAT");
png_crc_finish(png_ptr, length);
return;
}
2000-02-05 05:40:16 +00:00
else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
1997-01-17 07:34:35 +00:00
{
png_warning(png_ptr, "Duplicate oFFs chunk");
png_crc_finish(png_ptr, length);
return;
}
1996-06-05 20:50:50 +00:00
1995-07-20 07:43:20 +00:00
if (length != 9)
{
1996-01-26 07:38:47 +00:00
png_warning(png_ptr, "Incorrect oFFs chunk length");
1997-01-17 07:34:35 +00:00
png_crc_finish(png_ptr, length);
1995-07-20 07:43:20 +00:00
return;
}
1996-01-26 07:38:47 +00:00
png_crc_read(png_ptr, buf, 9);
1997-01-17 07:34:35 +00:00
if (png_crc_finish(png_ptr, 0))
return;
1995-07-20 07:43:20 +00:00
1999-12-10 15:43:02 +00:00
offset_x = png_get_int_32(buf);
offset_y = png_get_int_32(buf + 4);
1995-07-20 07:43:20 +00:00
unit_type = buf[8];
1997-05-16 07:46:07 +00:00
png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
}
#endif
#if defined(PNG_READ_pCAL_SUPPORTED)
2000-07-11 12:12:36 +00:00
/* read the pCAL chunk (described in the PNG Extensions document) */
2000-05-06 19:09:57 +00:00
void /* PRIVATE */
1997-05-16 07:46:07 +00:00
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;
1998-02-09 02:56:40 +00:00
png_size_t slength;
1997-05-16 07:46:07 +00:00
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;
}
2000-02-05 05:40:16 +00:00
else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
1997-05-16 07:46:07 +00:00
{
png_warning(png_ptr, "Duplicate pCAL chunk");
png_crc_finish(png_ptr, length);
return;
}
2000-07-17 11:17:09 +00:00
png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)\n",
1997-05-16 07:46:07 +00:00
length + 1);
2002-05-25 16:12:10 +00:00
purpose = (png_charp)png_malloc_warn(png_ptr, length + 1);
if (purpose == NULL)
{
png_warning(png_ptr, "No memory for pCAL purpose.");
return;
}
1998-02-09 02:56:40 +00:00
slength = (png_size_t)length;
png_crc_read(png_ptr, (png_bytep)purpose, slength);
1997-05-16 07:46:07 +00:00
if (png_crc_finish(png_ptr, 0))
{
png_free(png_ptr, purpose);
return;
}
1998-02-09 02:56:40 +00:00
purpose[slength] = 0x00; /* null terminate the last string */
1997-05-16 07:46:07 +00:00
png_debug(3, "Finding end of pCAL purpose string\n");
1998-04-21 20:03:57 +00:00
for (buf = purpose; *buf; buf++)
1998-03-13 13:39:39 +00:00
/* empty loop */ ;
1997-05-16 07:46:07 +00:00
1998-02-09 02:56:40 +00:00
endptr = purpose + slength;
1997-05-16 07:46:07 +00:00
/* 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");
}
1998-04-21 20:03:57 +00:00
for (buf = units; *buf; buf++)
1998-03-16 00:20:23 +00:00
/* Empty loop to move past the units string. */ ;
1997-05-16 07:46:07 +00:00
png_debug(3, "Allocating pCAL parameters array\n");
2002-05-25 16:12:10 +00:00
params = (png_charpp)png_malloc_warn(png_ptr, (png_uint_32)(nparams
2004-07-28 13:20:44 +00:00
*png_sizeof(png_charp))) ;
2002-05-25 16:12:10 +00:00
if (params == NULL)
{
png_free(png_ptr, purpose);
png_warning(png_ptr, "No memory for pCAL params.");
return;
}
1997-05-16 07:46:07 +00:00
/* Get pointers to the start of each parameter string. */
1998-02-07 16:20:57 +00:00
for (i = 0; i < (int)nparams; i++)
1997-05-16 07:46:07 +00:00
{
buf++; /* Skip the null string terminator from previous parameter. */
png_debug1(3, "Reading pCAL parameter %d\n", i);
2007-09-26 00:44:08 +00:00
for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++)
1998-03-16 00:20:23 +00:00
/* Empty loop to move past each parameter string */ ;
1997-05-16 07:46:07 +00:00
/* 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);
1995-07-20 07:43:20 +00:00
}
1995-09-26 10:22:39 +00:00
#endif
1995-07-20 07:43:20 +00:00
1999-12-10 15:43:02 +00:00
#if defined(PNG_READ_sCAL_SUPPORTED)
/* read the sCAL chunk */
2000-05-06 19:09:57 +00:00
void /* PRIVATE */
1999-12-10 15:43:02 +00:00
png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
{
2000-02-05 05:40:16 +00:00
png_charp buffer, ep;
1999-12-10 15:43:02 +00:00
#ifdef PNG_FLOATING_POINT_SUPPORTED
2000-03-21 11:13:06 +00:00
double width, height;
1999-12-10 15:43:02 +00:00
png_charp vp;
2000-02-05 05:40:16 +00:00
#else
#ifdef PNG_FIXED_POINT_SUPPORTED
png_charp swidth, sheight;
#endif
1999-12-10 15:43:02 +00:00
#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;
}
2000-02-05 05:40:16 +00:00
else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
1999-12-10 15:43:02 +00:00
{
png_warning(png_ptr, "Duplicate sCAL chunk");
png_crc_finish(png_ptr, length);
return;
}
2000-07-17 11:17:09 +00:00
png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)\n",
1999-12-10 15:43:02 +00:00
length + 1);
2002-05-25 16:12:10 +00:00
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;
}
1999-12-10 15:43:02 +00:00
slength = (png_size_t)length;
2000-02-05 05:40:16 +00:00
png_crc_read(png_ptr, (png_bytep)buffer, slength);
1999-12-10 15:43:02 +00:00
if (png_crc_finish(png_ptr, 0))
{
2000-02-05 05:40:16 +00:00
png_free(png_ptr, buffer);
1999-12-10 15:43:02 +00:00
return;
}
2000-02-05 05:40:16 +00:00
buffer[slength] = 0x00; /* null terminate the last string */
1999-12-10 15:43:02 +00:00
2000-02-05 05:40:16 +00:00
ep = buffer + 1; /* skip unit byte */
1999-12-10 15:43:02 +00:00
#ifdef PNG_FLOATING_POINT_SUPPORTED
2006-11-20 13:55:23 +00:00
width = png_strtod(png_ptr, ep, &vp);
1999-12-10 15:43:02 +00:00
if (*vp)
2000-04-14 19:20:47 +00:00
{
png_warning(png_ptr, "malformed width string in sCAL chunk");
return;
}
2000-02-05 05:40:16 +00:00
#else
#ifdef PNG_FIXED_POINT_SUPPORTED
2002-05-25 16:12:10 +00:00
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;
}
2001-05-07 19:52:45 +00:00
png_memcpy(swidth, ep, (png_size_t)png_strlen(ep));
2000-02-05 05:40:16 +00:00
#endif
#endif
1999-12-10 15:43:02 +00:00
2000-02-05 05:40:16 +00:00
for (ep = buffer; *ep; ep++)
1999-12-10 15:43:02 +00:00
/* empty loop */ ;
ep++;
2007-09-27 00:34:29 +00:00
if (buffer + slength < ep)
{
png_warning(png_ptr, "Truncated sCAL chunk");
#if defined(PNG_FIXED_POINT_SUPPORTED) && \
!defined(PNG_FLOATING_POINT_SUPPORTED)
png_free(png_ptr, swidth);
#endif
png_free(png_ptr, buffer);
return;
}
1999-12-10 15:43:02 +00:00
#ifdef PNG_FLOATING_POINT_SUPPORTED
2006-11-20 13:55:23 +00:00
height = png_strtod(png_ptr, ep, &vp);
1999-12-10 15:43:02 +00:00
if (*vp)
2000-04-14 19:20:47 +00:00
{
png_warning(png_ptr, "malformed height string in sCAL chunk");
return;
}
2000-02-05 05:40:16 +00:00
#else
#ifdef PNG_FIXED_POINT_SUPPORTED
2002-05-25 16:12:10 +00:00
sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
2008-01-22 03:07:36 +00:00
if (sheight == NULL)
2002-05-25 16:12:10 +00:00
{
png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
return;
}
2001-05-07 19:52:45 +00:00
png_memcpy(sheight, ep, (png_size_t)png_strlen(ep));
2000-02-05 05:40:16 +00:00
#endif
#endif
1999-12-10 15:43:02 +00:00
2000-02-05 05:40:16 +00:00
if (buffer + slength < ep
1999-12-10 15:43:02 +00:00
#ifdef PNG_FLOATING_POINT_SUPPORTED
|| width <= 0. || height <= 0.
#endif
)
{
png_warning(png_ptr, "Invalid sCAL data");
2000-02-05 05:40:16 +00:00
png_free(png_ptr, buffer);
#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1999-12-10 15:43:02 +00:00
png_free(png_ptr, swidth);
png_free(png_ptr, sheight);
2000-02-05 05:40:16 +00:00
#endif
1999-12-10 15:43:02 +00:00
return;
}
#ifdef PNG_FLOATING_POINT_SUPPORTED
2000-02-05 05:40:16 +00:00
png_set_sCAL(png_ptr, info_ptr, buffer[0], width, height);
#else
1999-12-10 15:43:02 +00:00
#ifdef PNG_FIXED_POINT_SUPPORTED
2000-02-05 05:40:16 +00:00
png_set_sCAL_s(png_ptr, info_ptr, buffer[0], swidth, sheight);
#endif
1999-12-10 15:43:02 +00:00
#endif
2000-02-05 05:40:16 +00:00
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
1999-12-10 15:43:02 +00:00
}
#endif
1995-09-26 10:22:39 +00:00
#if defined(PNG_READ_tIME_SUPPORTED)
2000-05-06 19:09:57 +00:00
void /* PRIVATE */
1997-01-17 07:34:35 +00:00
png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1995-07-20 07:43:20 +00:00
{
png_byte buf[7];
png_time mod_time;
1997-05-16 07:46:07 +00:00
png_debug(1, "in png_handle_tIME\n");
1996-06-05 20:50:50 +00:00
if (!(png_ptr->mode & PNG_HAVE_IHDR))
1997-01-17 07:34:35 +00:00
png_error(png_ptr, "Out of place tIME chunk");
2000-02-05 05:40:16 +00:00
else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
1997-01-17 07:34:35 +00:00
{
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;
1996-06-05 20:50:50 +00:00
1995-07-20 07:43:20 +00:00
if (length != 7)
{
1996-01-26 07:38:47 +00:00
png_warning(png_ptr, "Incorrect tIME chunk length");
1997-01-17 07:34:35 +00:00
png_crc_finish(png_ptr, length);
1995-07-20 07:43:20 +00:00
return;
}
png_crc_read(png_ptr, buf, 7);
1997-01-17 07:34:35 +00:00
if (png_crc_finish(png_ptr, 0))
return;
1995-07-20 07:43:20 +00:00
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];
1996-01-26 07:38:47 +00:00
mod_time.year = png_get_uint_16(buf);
1995-07-20 07:43:20 +00:00
1997-05-16 07:46:07 +00:00
png_set_tIME(png_ptr, info_ptr, &mod_time);
1995-07-20 07:43:20 +00:00
}
1995-09-26 10:22:39 +00:00
#endif
1995-07-20 07:43:20 +00:00
1995-09-26 10:22:39 +00:00
#if defined(PNG_READ_tEXt_SUPPORTED)
1997-05-16 07:46:07 +00:00
/* Note: this does not properly handle chunks that are > 64K under DOS */
2000-05-06 19:09:57 +00:00
void /* PRIVATE */
1997-01-17 07:34:35 +00:00
png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1995-07-20 07:43:20 +00:00
{
1997-05-16 07:46:07 +00:00
png_textp text_ptr;
1996-01-26 07:38:47 +00:00
png_charp key;
1995-12-19 09:22:19 +00:00
png_charp text;
1997-05-16 07:46:07 +00:00
png_uint_32 skip = 0;
1998-02-09 02:56:40 +00:00
png_size_t slength;
2002-05-25 16:12:10 +00:00
int ret;
1997-05-16 07:46:07 +00:00
png_debug(1, "in png_handle_tEXt\n");
1995-07-20 07:43:20 +00:00
1996-06-05 20:50:50 +00:00
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before tEXt");
1997-01-17 07:34:35 +00:00
if (png_ptr->mode & PNG_HAVE_IDAT)
png_ptr->mode |= PNG_AFTER_IDAT;
1997-05-16 07:46:07 +00:00
#ifdef PNG_MAX_MALLOC_64K
1998-01-01 13:13:13 +00:00
if (length > (png_uint_32)65535L)
1997-05-16 07:46:07 +00:00
{
png_warning(png_ptr, "tEXt chunk too large to fit in memory");
1998-01-01 13:13:13 +00:00
skip = length - (png_uint_32)65535L;
length = (png_uint_32)65535L;
1997-05-16 07:46:07 +00:00
}
#endif
2002-05-25 16:12:10 +00:00
key = (png_charp)png_malloc_warn(png_ptr, length + 1);
if (key == NULL)
{
png_warning(png_ptr, "No memory to process text chunk.");
return;
}
1998-02-09 02:56:40 +00:00
slength = (png_size_t)length;
2001-04-20 15:32:10 +00:00
png_crc_read(png_ptr, (png_bytep)key, slength);
1997-05-16 07:46:07 +00:00
if (png_crc_finish(png_ptr, skip))
1997-01-17 07:34:35 +00:00
{
png_free(png_ptr, key);
return;
}
1998-02-09 02:56:40 +00:00
key[slength] = 0x00;
1995-07-20 07:43:20 +00:00
for (text = key; *text; text++)
1997-05-16 07:46:07 +00:00
/* empty loop to find end of key */ ;
1995-07-20 07:43:20 +00:00
1998-02-09 02:56:40 +00:00
if (text != key + slength)
1995-07-20 07:43:20 +00:00
text++;
2004-07-28 13:20:44 +00:00
text_ptr = (png_textp)png_malloc_warn(png_ptr,
(png_uint_32)png_sizeof(png_text));
2002-05-25 16:12:10 +00:00
if (text_ptr == NULL)
{
png_warning(png_ptr, "Not enough memory to process text chunk.");
png_free(png_ptr, key);
return;
}
1997-05-16 07:46:07 +00:00
text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
text_ptr->key = key;
2000-05-06 19:09:57 +00:00
#ifdef PNG_iTXt_SUPPORTED
2000-02-05 05:40:16 +00:00
text_ptr->lang = NULL;
text_ptr->lang_key = NULL;
2000-05-06 19:09:57 +00:00
text_ptr->itxt_length = 0;
#endif
1997-05-16 07:46:07 +00:00
text_ptr->text = text;
2000-02-05 05:40:16 +00:00
text_ptr->text_length = png_strlen(text);
1997-05-16 07:46:07 +00:00
2002-05-25 16:12:10 +00:00
ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
1997-05-16 07:46:07 +00:00
2001-04-15 01:15:41 +00:00
png_free(png_ptr, key);
2001-04-20 15:32:10 +00:00
png_free(png_ptr, text_ptr);
2002-05-25 16:12:10 +00:00
if (ret)
png_warning(png_ptr, "Insufficient memory to process text chunk.");
1995-07-20 07:43:20 +00:00
}
1995-09-26 10:22:39 +00:00
#endif
1995-07-20 07:43:20 +00:00
1995-09-26 10:22:39 +00:00
#if defined(PNG_READ_zTXt_SUPPORTED)
1997-05-16 07:46:07 +00:00
/* note: this does not correctly handle chunks that are > 64K under DOS */
2000-05-06 19:09:57 +00:00
void /* PRIVATE */
1997-01-17 07:34:35 +00:00
png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1995-07-20 07:43:20 +00:00
{
1997-05-16 07:46:07 +00:00
png_textp text_ptr;
1999-12-10 15:43:02 +00:00
png_charp chunkdata;
1995-12-19 09:22:19 +00:00
png_charp text;
2000-03-21 11:13:06 +00:00
int comp_type;
2002-05-25 16:12:10 +00:00
int ret;
2000-04-02 03:10:05 +00:00
png_size_t slength, prefix_len, data_len;
1997-05-16 07:46:07 +00:00
png_debug(1, "in png_handle_zTXt\n");
1996-06-05 20:50:50 +00:00
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before zTXt");
1997-01-17 07:34:35 +00:00
if (png_ptr->mode & PNG_HAVE_IDAT)
png_ptr->mode |= PNG_AFTER_IDAT;
1997-05-16 07:46:07 +00:00
#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. */
1998-01-01 13:13:13 +00:00
if (length > (png_uint_32)65535L)
1997-05-16 07:46:07 +00:00
{
png_warning(png_ptr,"zTXt chunk too large to fit in memory");
png_crc_finish(png_ptr, length);
return;
}
#endif
2002-05-25 16:12:10 +00:00
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;
2001-04-20 15:32:10 +00:00
png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
1997-01-17 07:34:35 +00:00
if (png_crc_finish(png_ptr, 0))
{
1999-12-10 15:43:02 +00:00
png_free(png_ptr, chunkdata);
1997-01-17 07:34:35 +00:00
return;
}
1999-12-10 15:43:02 +00:00
chunkdata[slength] = 0x00;
1995-07-20 07:43:20 +00:00
1999-12-10 15:43:02 +00:00
for (text = chunkdata; *text; text++)
1995-07-20 07:43:20 +00:00
/* empty loop */ ;
1999-12-10 15:43:02 +00:00
/* zTXt must have some text after the chunkdataword */
2007-09-26 00:44:08 +00:00
if (text >= chunkdata + slength - 2)
1995-07-20 07:43:20 +00:00
{
2007-07-19 01:05:37 +00:00
png_warning(png_ptr, "Truncated zTXt chunk");
png_free(png_ptr, chunkdata);
return;
1995-07-20 07:43:20 +00:00
}
1999-12-10 15:43:02 +00:00
else
1996-06-05 20:50:50 +00:00
{
1999-12-10 15:43:02 +00:00
comp_type = *(++text);
2000-12-23 20:27:39 +00:00
if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
{
png_warning(png_ptr, "Unknown compression type in zTXt chunk");
comp_type = PNG_TEXT_COMPRESSION_zTXt;
}
2000-02-05 05:40:16 +00:00
text++; /* skip the compression_method byte */
1999-12-10 15:43:02 +00:00
}
prefix_len = text - chunkdata;
1995-07-20 07:43:20 +00:00
1999-12-10 15:43:02 +00:00
chunkdata = (png_charp)png_decompress_chunk(png_ptr, comp_type, chunkdata,
2000-04-02 03:10:05 +00:00
(png_size_t)length, prefix_len, &data_len);
1995-07-20 07:43:20 +00:00
2004-07-28 13:20:44 +00:00
text_ptr = (png_textp)png_malloc_warn(png_ptr,
(png_uint_32)png_sizeof(png_text));
2002-05-25 16:12:10 +00:00
if (text_ptr == NULL)
{
png_warning(png_ptr,"Not enough memory to process zTXt chunk.");
png_free(png_ptr, chunkdata);
return;
}
2001-04-20 15:32:10 +00:00
text_ptr->compression = comp_type;
text_ptr->key = chunkdata;
2000-05-06 19:09:57 +00:00
#ifdef PNG_iTXt_SUPPORTED
2001-04-20 15:32:10 +00:00
text_ptr->lang = NULL;
text_ptr->lang_key = NULL;
text_ptr->itxt_length = 0;
2000-05-06 19:09:57 +00:00
#endif
2001-04-20 15:32:10 +00:00
text_ptr->text = chunkdata + prefix_len;
text_ptr->text_length = data_len;
1995-07-20 07:43:20 +00:00
2002-05-25 16:12:10 +00:00
ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
1996-06-05 20:50:50 +00:00
2001-04-20 15:32:10 +00:00
png_free(png_ptr, text_ptr);
1999-12-10 15:43:02 +00:00
png_free(png_ptr, chunkdata);
2002-05-25 16:12:10 +00:00
if (ret)
png_error(png_ptr, "Insufficient memory to store zTXt chunk.");
1999-12-10 15:43:02 +00:00
}
#endif
1996-06-05 20:50:50 +00:00
1999-12-10 15:43:02 +00:00
#if defined(PNG_READ_iTXt_SUPPORTED)
/* note: this does not correctly handle chunks that are > 64K under DOS */
2000-05-06 19:09:57 +00:00
void /* PRIVATE */
1999-12-10 15:43:02 +00:00
png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
{
png_textp text_ptr;
png_charp chunkdata;
2000-02-05 05:40:16 +00:00
png_charp key, lang, text, lang_key;
2000-03-21 11:13:06 +00:00
int comp_flag;
2000-02-05 05:40:16 +00:00
int comp_type = 0;
2002-05-25 16:12:10 +00:00
int ret;
2000-04-02 03:10:05 +00:00
png_size_t slength, prefix_len, data_len;
1996-06-05 20:50:50 +00:00
1999-12-10 15:43:02 +00:00
png_debug(1, "in png_handle_iTXt\n");
1996-06-05 20:50:50 +00:00
1999-12-10 15:43:02 +00:00
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before iTXt");
1995-07-20 07:43:20 +00:00
1999-12-10 15:43:02 +00:00
if (png_ptr->mode & PNG_HAVE_IDAT)
png_ptr->mode |= PNG_AFTER_IDAT;
1995-07-20 07:43:20 +00:00
1999-12-10 15:43:02 +00:00
#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;
1995-07-20 07:43:20 +00:00
}
1999-12-10 15:43:02 +00:00
#endif
2002-05-25 16:12:10 +00:00
chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
if (chunkdata == NULL)
{
png_warning(png_ptr, "No memory to process iTXt chunk.");
return;
}
2001-04-20 15:32:10 +00:00
slength = (png_size_t)length;
png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
1999-12-10 15:43:02 +00:00
if (png_crc_finish(png_ptr, 0))
1997-05-16 07:46:07 +00:00
{
1999-12-10 15:43:02 +00:00
png_free(png_ptr, chunkdata);
return;
}
1997-05-16 07:46:07 +00:00
1999-12-10 15:43:02 +00:00
chunkdata[slength] = 0x00;
1997-05-16 07:46:07 +00:00
1999-12-10 15:43:02 +00:00
for (lang = chunkdata; *lang; lang++)
/* empty loop */ ;
lang++; /* skip NUL separator */
2000-02-05 05:40:16 +00:00
/* iTXt must have a language tag (possibly empty), two compression bytes,
translated keyword (possibly empty), and possibly some text after the
keyword */
2007-07-19 01:05:37 +00:00
if (lang >= chunkdata + slength - 3)
1999-12-10 15:43:02 +00:00
{
2007-07-19 01:05:37 +00:00
png_warning(png_ptr, "Truncated iTXt chunk");
png_free(png_ptr, chunkdata);
return;
1997-05-16 07:46:07 +00:00
}
1999-12-10 15:43:02 +00:00
else
{
comp_flag = *lang++;
comp_type = *lang++;
}
2000-02-05 05:40:16 +00:00
for (lang_key = lang; *lang_key; lang_key++)
/* empty loop */ ;
lang_key++; /* skip NUL separator */
2007-09-27 00:34:29 +00:00
if (lang_key >= chunkdata + slength)
{
png_warning(png_ptr, "Truncated iTXt chunk");
png_free(png_ptr, chunkdata);
return;
}
2000-02-05 05:40:16 +00:00
for (text = lang_key; *text; text++)
1999-12-10 15:43:02 +00:00
/* empty loop */ ;
text++; /* skip NUL separator */
2007-07-19 01:05:37 +00:00
if (text >= chunkdata + slength)
{
png_warning(png_ptr, "Malformed iTXt chunk");
png_free(png_ptr, chunkdata);
return;
}
1999-12-10 15:43:02 +00:00
prefix_len = text - chunkdata;
2000-02-05 05:40:16 +00:00
key=chunkdata;
1999-12-10 15:43:02 +00:00
if (comp_flag)
chunkdata = png_decompress_chunk(png_ptr, comp_type, chunkdata,
2000-04-02 03:10:05 +00:00
(size_t)length, prefix_len, &data_len);
else
data_len=png_strlen(chunkdata + prefix_len);
2004-07-28 13:20:44 +00:00
text_ptr = (png_textp)png_malloc_warn(png_ptr,
(png_uint_32)png_sizeof(png_text));
2002-05-25 16:12:10 +00:00
if (text_ptr == NULL)
{
png_warning(png_ptr,"Not enough memory to process iTXt chunk.");
png_free(png_ptr, chunkdata);
return;
}
2001-04-20 15:32:10 +00:00
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;
1995-07-20 07:43:20 +00:00
2002-05-25 16:12:10 +00:00
ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
1997-05-16 07:46:07 +00:00
2001-04-20 15:32:10 +00:00
png_free(png_ptr, text_ptr);
1999-12-10 15:43:02 +00:00
png_free(png_ptr, chunkdata);
2002-05-25 16:12:10 +00:00
if (ret)
png_error(png_ptr, "Insufficient memory to store iTXt chunk.");
1999-12-10 15:43:02 +00:00
}
#endif
1997-01-17 07:34:35 +00:00
/* 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
1999-12-10 15:43:02 +00:00
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. */
2000-05-06 19:09:57 +00:00
void /* PRIVATE */
1997-01-17 07:34:35 +00:00
png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
{
1999-12-10 15:43:02 +00:00
png_uint_32 skip = 0;
1997-05-16 07:46:07 +00:00
png_debug(1, "in png_handle_unknown\n");
1999-12-10 15:43:02 +00:00
if (png_ptr->mode & PNG_HAVE_IDAT)
2000-02-05 05:40:16 +00:00
{
#ifdef PNG_USE_LOCAL_ARRAYS
2007-05-21 18:27:47 +00:00
PNG_CONST PNG_IDAT;
2000-02-05 05:40:16 +00:00
#endif
if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* not an IDAT */
png_ptr->mode |= PNG_AFTER_IDAT;
}
1999-12-10 15:43:02 +00:00
1997-01-17 07:34:35 +00:00
png_check_chunk_name(png_ptr, png_ptr->chunk_name);
if (!(png_ptr->chunk_name[0] & 0x20))
{
2000-05-01 14:31:54 +00:00
#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
2000-02-05 05:40:16 +00:00
if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
2004-08-08 02:42:49 +00:00
PNG_HANDLE_CHUNK_ALWAYS
2000-02-05 05:40:16 +00:00
#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2001-05-07 19:52:45 +00:00
&& png_ptr->read_user_chunk_fn == NULL
2000-02-05 05:40:16 +00:00
#endif
)
2000-05-01 14:31:54 +00:00
#endif
2000-02-05 05:40:16 +00:00
png_chunk_error(png_ptr, "unknown critical chunk");
1997-01-17 07:34:35 +00:00
}
1999-12-10 15:43:02 +00:00
#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
2006-02-21 04:09:05 +00:00
if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) ||
(png_ptr->read_user_chunk_fn != NULL))
1999-12-10 15:43:02 +00:00
{
#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
2007-10-16 19:27:46 +00:00
png_memcpy((png_charp)png_ptr->unknown_chunk.name,
(png_charp)png_ptr->chunk_name,
png_sizeof(png_ptr->unknown_chunk.name));
png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1] = '\0';
2007-05-09 13:56:59 +00:00
png_ptr->unknown_chunk.size = (png_size_t)length;
2008-04-12 11:59:47 +00:00
if (length == 0)
png_ptr->unknown_chunk.data = NULL;
else
{
png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length);
png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length);
}
2000-02-05 05:40:16 +00:00
#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2001-05-07 19:52:45 +00:00
if(png_ptr->read_user_chunk_fn != NULL)
2000-02-05 05:40:16 +00:00
{
/* callback to user unknown chunk handler */
2007-05-09 13:56:59 +00:00
int ret;
ret = (*(png_ptr->read_user_chunk_fn))
(png_ptr, &png_ptr->unknown_chunk);
if (ret < 0)
png_chunk_error(png_ptr, "error in user chunk");
if (ret == 0)
2000-02-05 05:40:16 +00:00
{
if (!(png_ptr->chunk_name[0] & 0x20))
if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
2004-08-08 02:42:49 +00:00
PNG_HANDLE_CHUNK_ALWAYS)
2000-02-05 05:40:16 +00:00
png_chunk_error(png_ptr, "unknown critical chunk");
2007-05-12 04:12:12 +00:00
png_set_unknown_chunks(png_ptr, info_ptr,
&png_ptr->unknown_chunk, 1);
2000-02-05 05:40:16 +00:00
}
}
2008-01-09 16:58:36 +00:00
else
2007-05-12 04:12:12 +00:00
#endif
2008-04-14 14:26:03 +00:00
png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
png_free(png_ptr, png_ptr->unknown_chunk.data);
png_ptr->unknown_chunk.data = NULL;
1999-12-10 15:43:02 +00:00
}
else
#endif
2000-02-05 05:40:16 +00:00
skip = length;
1998-02-09 02:56:40 +00:00
1999-12-10 15:43:02 +00:00
png_crc_finish(png_ptr, skip);
2000-02-05 05:40:16 +00:00
#if !defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2007-05-18 18:40:59 +00:00
info_ptr = info_ptr; /* quiet compiler warnings about unused info_ptr */
2000-02-05 05:40:16 +00:00
#endif
1997-01-17 07:34:35 +00:00
}
/* This function is called to verify that a chunk name is valid.
This function can't have the "critical chunk check" incorporated
1997-05-16 07:46:07 +00:00
into it, since in the future we will need to be able to call user
1997-01-17 07:34:35 +00:00
functions to handle unknown critical chunks after we check that
the chunk name itself is valid. */
1997-05-16 07:46:07 +00:00
2004-07-18 03:45:44 +00:00
#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
1997-05-16 07:46:07 +00:00
2000-05-06 19:09:57 +00:00
void /* PRIVATE */
1997-01-17 07:34:35 +00:00
png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
{
1997-05-16 07:46:07 +00:00
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]))
1997-01-17 07:34:35 +00:00
{
1998-01-04 04:40:55 +00:00
png_chunk_error(png_ptr, "invalid chunk type");
1997-01-17 07:34:35 +00:00
}
}
1998-06-14 19:43:31 +00:00
/* Combines the row recently read in with the existing pixels in the
row. This routine takes care of alpha and transparency if requested.
1995-07-20 07:43:20 +00:00
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
1998-06-14 19:43:31 +00:00
bits are needed. A one indicates the pixel is to be combined,
1995-07-20 07:43:20 +00:00
a zero indicates the pixel is to be skipped. This is in addition
to any alpha or transparency value associated with the pixel. If
1997-01-17 07:34:35 +00:00
you want all pixels to be combined, pass 0xff (255) in mask. */
2007-06-23 02:40:24 +00:00
2000-05-06 19:09:57 +00:00
void /* PRIVATE */
2001-01-12 21:13:06 +00:00
png_combine_row(png_structp png_ptr, png_bytep row, int mask)
1995-07-20 07:43:20 +00:00
{
2007-09-01 20:12:50 +00:00
png_debug(1,"in png_combine_row\n");
1995-07-20 07:43:20 +00:00
if (mask == 0xff)
{
1995-09-26 10:22:39 +00:00
png_memcpy(row, png_ptr->row_buf + 1,
2004-08-04 11:34:52 +00:00
PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width));
1995-07-20 07:43:20 +00:00
}
else
{
switch (png_ptr->row_info.pixel_depth)
{
case 1:
{
1998-05-02 17:52:25 +00:00
png_bytep sp = png_ptr->row_buf + 1;
png_bytep dp = row;
2004-11-28 00:22:29 +00:00
int s_inc, s_start, s_end;
int m = 0x80;
int shift;
1998-05-02 17:52:25 +00:00
png_uint_32 i;
2004-11-28 00:22:29 +00:00
png_uint_32 row_width = png_ptr->width;
1995-07-20 07:43:20 +00:00
1997-05-16 07:46:07 +00:00
#if defined(PNG_READ_PACKSWAP_SUPPORTED)
if (png_ptr->transformations & PNG_PACKSWAP)
2004-11-28 00:22:29 +00:00
{
s_start = 0;
s_end = 7;
s_inc = 1;
}
else
1997-05-16 07:46:07 +00:00
#endif
{
2004-11-28 00:22:29 +00:00
s_start = 7;
s_end = 0;
s_inc = -1;
1997-05-16 07:46:07 +00:00
}
2004-11-28 00:22:29 +00:00
shift = s_start;
for (i = 0; i < row_width; i++)
1995-07-20 07:43:20 +00:00
{
2004-11-28 00:22:29 +00:00
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;
1995-07-20 07:43:20 +00:00
}
break;
}
case 2:
{
1998-05-02 17:52:25 +00:00
png_bytep sp = png_ptr->row_buf + 1;
png_bytep dp = row;
2004-11-28 00:22:29 +00:00
int s_start, s_end, s_inc;
2004-11-24 13:50:16 +00:00
int m = 0x80;
2004-11-28 00:22:29 +00:00
int shift;
png_uint_32 i;
png_uint_32 row_width = png_ptr->width;
int value;
1995-07-20 07:43:20 +00:00
1997-05-16 07:46:07 +00:00
#if defined(PNG_READ_PACKSWAP_SUPPORTED)
if (png_ptr->transformations & PNG_PACKSWAP)
{
2004-11-28 00:22:29 +00:00
s_start = 0;
s_end = 6;
s_inc = 2;
1997-05-16 07:46:07 +00:00
}
2004-11-28 00:22:29 +00:00
else
#endif
1997-05-16 07:46:07 +00:00
{
2004-11-28 00:22:29 +00:00
s_start = 6;
s_end = 0;
s_inc = -2;
1997-05-16 07:46:07 +00:00
}
2004-11-28 00:22:29 +00:00
shift = s_start;
for (i = 0; i < row_width; i++)
1995-07-20 07:43:20 +00:00
{
2004-11-28 00:22:29 +00:00
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;
1995-07-20 07:43:20 +00:00
}
break;
}
case 4:
{
1998-05-02 17:52:25 +00:00
png_bytep sp = png_ptr->row_buf + 1;
png_bytep dp = row;
2004-11-28 00:22:29 +00:00
int s_start, s_end, s_inc;
2004-11-24 13:50:16 +00:00
int m = 0x80;
2004-11-28 00:22:29 +00:00
int shift;
png_uint_32 i;
png_uint_32 row_width = png_ptr->width;
int value;
1995-07-20 07:43:20 +00:00
1997-05-16 07:46:07 +00:00
#if defined(PNG_READ_PACKSWAP_SUPPORTED)
if (png_ptr->transformations & PNG_PACKSWAP)
{
2004-11-28 00:22:29 +00:00
s_start = 0;
s_end = 4;
s_inc = 4;
1997-05-16 07:46:07 +00:00
}
2004-11-28 00:22:29 +00:00
else
#endif
1997-05-16 07:46:07 +00:00
{
2004-11-28 00:22:29 +00:00
s_start = 4;
s_end = 0;
s_inc = -4;
1997-05-16 07:46:07 +00:00
}
2004-11-28 00:22:29 +00:00
shift = s_start;
for (i = 0; i < row_width; i++)
1995-07-20 07:43:20 +00:00
{
2004-11-28 00:22:29 +00:00
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;
1995-07-20 07:43:20 +00:00
}
break;
}
default:
{
1998-05-02 17:52:25 +00:00
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;
2004-11-28 00:22:29 +00:00
png_uint_32 row_width = png_ptr->width;
png_byte m = 0x80;
1998-05-02 17:52:25 +00:00
2004-11-28 00:22:29 +00:00
for (i = 0; i < row_width; i++)
1995-07-20 07:43:20 +00:00
{
2004-11-28 00:22:29 +00:00
if (m & mask)
{
png_memcpy(dp, sp, pixel_bytes);
}
sp += pixel_bytes;
dp += pixel_bytes;
if (m == 1)
m = 0x80;
else
m >>= 1;
1995-07-20 07:43:20 +00:00
}
break;
}
}
}
}
2001-01-12 21:13:06 +00:00
#ifdef PNG_READ_INTERLACING_SUPPORTED
2001-05-07 19:52:45 +00:00
/* 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)
*/
2000-05-06 19:09:57 +00:00
void /* PRIVATE */
2001-01-12 21:13:06 +00:00
png_do_read_interlace(png_structp png_ptr)
1995-07-20 07:43:20 +00:00
{
2001-01-12 21:13:06 +00:00
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;
1999-11-29 05:32:18 +00:00
#ifdef PNG_USE_LOCAL_ARRAYS
1999-11-27 16:22:33 +00:00
/* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* offset to next interlace block */
2007-05-18 18:40:59 +00:00
PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
1999-11-29 05:32:18 +00:00
#endif
1999-12-10 15:43:02 +00:00
2007-09-01 20:12:50 +00:00
png_debug(1,"in png_do_read_interlace\n");
2004-11-28 00:22:29 +00:00
if (row != NULL && row_info != NULL)
1995-07-20 07:43:20 +00:00
{
2004-11-28 00:22:29 +00:00
png_uint_32 final_width;
final_width = row_info->width * png_pass_inc[pass];
1995-07-20 07:43:20 +00:00
switch (row_info->pixel_depth)
{
case 1:
{
1998-05-02 17:52:25 +00:00
png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
2004-11-28 00:22:29 +00:00
int sshift, dshift;
int s_start, s_end, s_inc;
int jstop = png_pass_inc[pass];
png_byte v;
1995-07-20 07:43:20 +00:00
png_uint_32 i;
2004-11-28 00:22:29 +00:00
int j;
1995-07-20 07:43:20 +00:00
1997-05-16 07:46:07 +00:00
#if defined(PNG_READ_PACKSWAP_SUPPORTED)
if (transformations & PNG_PACKSWAP)
{
2004-11-28 00:22:29 +00:00
sshift = (int)((row_info->width + 7) & 0x07);
dshift = (int)((final_width + 7) & 0x07);
s_start = 7;
s_end = 0;
s_inc = -1;
1997-05-16 07:46:07 +00:00
}
2004-11-28 00:22:29 +00:00
else
1997-05-16 07:46:07 +00:00
#endif
1995-07-20 07:43:20 +00:00
{
2004-11-28 00:22:29 +00:00
sshift = 7 - (int)((row_info->width + 7) & 0x07);
dshift = 7 - (int)((final_width + 7) & 0x07);
s_start = 0;
s_end = 7;
s_inc = 1;
}
2004-11-24 13:50:16 +00:00
2004-11-28 00:22:29 +00:00
for (i = 0; i < row_info->width; i++)
{
v = (png_byte)((*sp >> sshift) & 0x01);
for (j = 0; j < jstop; j++)
1995-07-20 07:43:20 +00:00
{
2004-11-28 00:22:29 +00:00
*dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
*dp |= (png_byte)(v << dshift);
if (dshift == s_end)
{
dshift = s_start;
dp--;
}
else
dshift += s_inc;
1995-07-20 07:43:20 +00:00
}
2004-11-28 00:22:29 +00:00
if (sshift == s_end)
1995-07-20 07:43:20 +00:00
{
2004-11-28 00:22:29 +00:00
sshift = s_start;
1995-07-20 07:43:20 +00:00
sp--;
}
2004-11-28 00:22:29 +00:00
else
sshift += s_inc;
1995-07-20 07:43:20 +00:00
}
break;
}
case 2:
{
2004-11-28 00:22:29 +00:00
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];
1997-05-16 07:46:07 +00:00
png_uint_32 i;
1995-07-20 07:43:20 +00:00
1997-05-16 07:46:07 +00:00
#if defined(PNG_READ_PACKSWAP_SUPPORTED)
if (transformations & PNG_PACKSWAP)
{
2004-11-28 00:22:29 +00:00
sshift = (int)(((row_info->width + 3) & 0x03) << 1);
dshift = (int)(((final_width + 3) & 0x03) << 1);
s_start = 6;
s_end = 0;
s_inc = -2;
1997-05-16 07:46:07 +00:00
}
2004-11-28 00:22:29 +00:00
else
1997-05-16 07:46:07 +00:00
#endif
2004-11-28 00:22:29 +00:00
{
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;
}
1997-05-16 07:46:07 +00:00
2004-11-28 00:22:29 +00:00
for (i = 0; i < row_info->width; i++)
1995-07-20 07:43:20 +00:00
{
2004-11-28 00:22:29 +00:00
png_byte v;
int j;
1997-05-16 07:46:07 +00:00
2004-11-28 00:22:29 +00:00
v = (png_byte)((*sp >> sshift) & 0x03);
for (j = 0; j < jstop; j++)
1995-07-20 07:43:20 +00:00
{
2004-11-28 00:22:29 +00:00
*dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
*dp |= (png_byte)(v << dshift);
if (dshift == s_end)
{
dshift = s_start;
dp--;
}
else
dshift += s_inc;
1995-07-20 07:43:20 +00:00
}
2004-11-28 00:22:29 +00:00
if (sshift == s_end)
1995-07-20 07:43:20 +00:00
{
2004-11-28 00:22:29 +00:00
sshift = s_start;
1995-07-20 07:43:20 +00:00
sp--;
}
2004-11-28 00:22:29 +00:00
else
sshift += s_inc;
1995-07-20 07:43:20 +00:00
}
break;
}
case 4:
{
1998-05-02 17:52:25 +00:00
png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
2004-11-28 00:22:29 +00:00
int sshift, dshift;
int s_start, s_end, s_inc;
1995-07-20 07:43:20 +00:00
png_uint_32 i;
2004-11-28 00:22:29 +00:00
int jstop = png_pass_inc[pass];
1995-07-20 07:43:20 +00:00
1997-05-16 07:46:07 +00:00
#if defined(PNG_READ_PACKSWAP_SUPPORTED)
if (transformations & PNG_PACKSWAP)
{
2004-11-28 00:22:29 +00:00
sshift = (int)(((row_info->width + 1) & 0x01) << 2);
dshift = (int)(((final_width + 1) & 0x01) << 2);
s_start = 4;
s_end = 0;
s_inc = -4;
1997-05-16 07:46:07 +00:00
}
2004-11-28 00:22:29 +00:00
else
1997-05-16 07:46:07 +00:00
#endif
{
2004-11-28 00:22:29 +00:00
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;
}
1997-05-16 07:46:07 +00:00
2004-11-28 00:22:29 +00:00
for (i = 0; i < row_info->width; i++)
{
png_byte v = (png_byte)((*sp >> sshift) & 0xf);
int j;
1997-05-16 07:46:07 +00:00
2004-11-28 00:22:29 +00:00
for (j = 0; j < jstop; j++)
1995-07-20 07:43:20 +00:00
{
2004-11-28 00:22:29 +00:00
*dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
*dp |= (png_byte)(v << dshift);
if (dshift == s_end)
{
dshift = s_start;
dp--;
}
else
dshift += s_inc;
1995-07-20 07:43:20 +00:00
}
2004-11-28 00:22:29 +00:00
if (sshift == s_end)
1995-07-20 07:43:20 +00:00
{
2004-11-28 00:22:29 +00:00
sshift = s_start;
1995-07-20 07:43:20 +00:00
sp--;
}
2004-11-28 00:22:29 +00:00
else
sshift += s_inc;
1995-07-20 07:43:20 +00:00
}
break;
}
default:
{
1998-05-02 17:52:25 +00:00
png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes;
2004-11-28 00:22:29 +00:00
png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
int jstop = png_pass_inc[pass];
1997-05-16 07:46:07 +00:00
png_uint_32 i;
1995-07-20 07:43:20 +00:00
2004-11-28 00:22:29 +00:00
for (i = 0; i < row_info->width; i++)
1995-07-20 07:43:20 +00:00
{
2004-11-28 00:22:29 +00:00
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;
1995-07-20 07:43:20 +00:00
}
break;
}
}
row_info->width = final_width;
2004-08-04 11:34:52 +00:00
row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,final_width);
1995-07-20 07:43:20 +00:00
}
2000-05-29 13:58:03 +00:00
#if !defined(PNG_READ_PACKSWAP_SUPPORTED)
2007-05-18 18:40:59 +00:00
transformations = transformations; /* silence compiler warning */
2000-05-29 13:58:03 +00:00
#endif
1995-07-20 07:43:20 +00:00
}
2001-01-12 21:13:06 +00:00
#endif /* PNG_READ_INTERLACING_SUPPORTED */
1995-07-20 07:43:20 +00:00
2000-05-06 19:09:57 +00:00
void /* PRIVATE */
2001-01-12 21:13:06 +00:00
png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
1998-04-21 20:03:57 +00:00
png_bytep prev_row, int filter)
{
2007-09-01 20:12:50 +00:00
png_debug(1, "in png_read_filter_row\n");
2000-07-17 11:17:09 +00:00
png_debug2(2,"row = %lu, filter = %d\n", png_ptr->row_number, filter);
1998-04-21 20:03:57 +00:00
switch (filter)
{
case PNG_FILTER_VALUE_NONE:
break;
case PNG_FILTER_VALUE_SUB:
{
1998-05-02 17:52:25 +00:00
png_uint_32 i;
png_uint_32 istop = row_info->rowbytes;
1999-10-01 19:22:25 +00:00
png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
1998-05-02 17:52:25 +00:00
png_bytep rp = row + bpp;
png_bytep lp = row;
1998-04-21 20:03:57 +00:00
1998-05-02 17:52:25 +00:00
for (i = bpp; i < istop; i++)
1998-04-21 20:03:57 +00:00
{
1998-05-21 14:27:50 +00:00
*rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
rp++;
1998-04-21 20:03:57 +00:00
}
break;
}
case PNG_FILTER_VALUE_UP:
{
1998-05-02 17:52:25 +00:00
png_uint_32 i;
png_uint_32 istop = row_info->rowbytes;
png_bytep rp = row;
png_bytep pp = prev_row;
1998-04-21 20:03:57 +00:00
1998-05-02 17:52:25 +00:00
for (i = 0; i < istop; i++)
1998-04-21 20:03:57 +00:00
{
1998-05-21 14:27:50 +00:00
*rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
rp++;
1998-04-21 20:03:57 +00:00
}
break;
}
case PNG_FILTER_VALUE_AVG:
{
1998-05-02 17:52:25 +00:00
png_uint_32 i;
png_bytep rp = row;
png_bytep pp = prev_row;
png_bytep lp = row;
1999-10-01 19:22:25 +00:00
png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
1998-05-21 14:27:50 +00:00
png_uint_32 istop = row_info->rowbytes - bpp;
1998-04-21 20:03:57 +00:00
1998-05-02 17:52:25 +00:00
for (i = 0; i < bpp; i++)
1998-04-21 20:03:57 +00:00
{
1998-05-21 14:27:50 +00:00
*rp = (png_byte)(((int)(*rp) +
1999-10-01 19:22:25 +00:00
((int)(*pp++) / 2 )) & 0xff);
1998-05-21 14:27:50 +00:00
rp++;
1998-04-21 20:03:57 +00:00
}
1998-12-29 17:47:59 +00:00
1998-05-21 14:27:50 +00:00
for (i = 0; i < istop; i++)
1998-04-21 20:03:57 +00:00
{
1998-05-21 14:27:50 +00:00
*rp = (png_byte)(((int)(*rp) +
1999-10-01 19:22:25 +00:00
(int)(*pp++ + *lp++) / 2 ) & 0xff);
1998-05-21 14:27:50 +00:00
rp++;
1998-04-21 20:03:57 +00:00
}
break;
}
case PNG_FILTER_VALUE_PAETH:
{
1998-05-02 17:52:25 +00:00
png_uint_32 i;
png_bytep rp = row;
png_bytep pp = prev_row;
png_bytep lp = row;
png_bytep cp = prev_row;
1999-10-01 19:22:25 +00:00
png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
1998-05-21 14:27:50 +00:00
png_uint_32 istop=row_info->rowbytes - bpp;
1998-05-02 17:52:25 +00:00
for (i = 0; i < bpp; i++)
1998-04-21 20:03:57 +00:00
{
1998-05-21 14:27:50 +00:00
*rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
rp++;
1998-04-21 20:03:57 +00:00
}
1998-05-21 14:27:50 +00:00
for (i = 0; i < istop; i++) /* use leftover rp,pp */
1998-04-21 20:03:57 +00:00
{
int a, b, c, pa, pb, pc, p;
1998-05-02 17:52:25 +00:00
a = *lp++;
b = *pp++;
c = *cp++;
p = b - c;
pc = a - c;
1998-04-21 20:03:57 +00:00
#ifdef PNG_USE_ABS
1998-05-02 17:52:25 +00:00
pa = abs(p);
pb = abs(pc);
pc = abs(p + pc);
1998-04-21 20:03:57 +00:00
#else
1998-05-02 17:52:25 +00:00
pa = p < 0 ? -p : p;
pb = pc < 0 ? -pc : pc;
pc = (p + pc) < 0 ? -(p + pc) : p + pc;
1998-04-21 20:03:57 +00:00
#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;
1998-05-21 14:27:50 +00:00
*rp = (png_byte)(((int)(*rp) + p) & 0xff);
rp++;
1998-04-21 20:03:57 +00:00
}
break;
}
default:
1998-12-29 17:47:59 +00:00
png_warning(png_ptr, "Ignoring bad adaptive filter type");
*row=0;
1998-04-21 20:03:57 +00:00
break;
}
}
1995-07-20 07:43:20 +00:00
2000-05-06 19:09:57 +00:00
void /* PRIVATE */
1995-12-19 09:22:19 +00:00
png_read_finish_row(png_structp png_ptr)
1995-07-20 07:43:20 +00:00
{
1999-11-29 05:32:18 +00:00
#ifdef PNG_USE_LOCAL_ARRAYS
2008-03-26 14:53:56 +00:00
#ifdef PNG_READ_INTERLACING_SUPPORTED
1999-11-27 16:22:33 +00:00
/* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
1999-12-10 15:43:02 +00:00
1999-11-27 16:22:33 +00:00
/* start of interlace block */
2007-05-18 18:40:59 +00:00
PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
1999-12-10 15:43:02 +00:00
1999-11-27 16:22:33 +00:00
/* offset to next interlace block */
2007-05-18 18:40:59 +00:00
PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
1999-12-10 15:43:02 +00:00
1999-11-27 16:22:33 +00:00
/* start of interlace block in the y direction */
2007-05-18 18:40:59 +00:00
PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
1999-12-10 15:43:02 +00:00
1999-11-27 16:22:33 +00:00
/* offset to next interlace block in the y direction */
2007-05-18 18:40:59 +00:00
PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
2008-03-26 14:53:56 +00:00
#endif /* PNG_READ_INTERLACING_SUPPORTED */
1999-11-29 05:32:18 +00:00
#endif
1999-12-10 15:43:02 +00:00
1997-05-16 07:46:07 +00:00
png_debug(1, "in png_read_finish_row\n");
1995-07-20 07:43:20 +00:00
png_ptr->row_number++;
if (png_ptr->row_number < png_ptr->num_rows)
return;
2008-03-26 14:53:56 +00:00
#ifdef PNG_READ_INTERLACING_SUPPORTED
1995-07-20 07:43:20 +00:00
if (png_ptr->interlaced)
{
png_ptr->row_number = 0;
2007-06-15 15:13:25 +00:00
png_memset_check(png_ptr, png_ptr->prev_row, 0,
png_ptr->rowbytes + 1);
1995-07-20 07:43:20 +00:00
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];
2004-08-04 11:34:52 +00:00
png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,
png_ptr->iwidth) + 1;
1998-02-07 16:20:57 +00:00
1995-07-20 07:43:20 +00:00
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;
}
1998-06-14 19:43:31 +00:00
else /* if (png_ptr->transformations & PNG_INTERLACE) */
1995-09-26 10:22:39 +00:00
break;
1995-07-20 07:43:20 +00:00
} while (png_ptr->iwidth == 0);
if (png_ptr->pass < 7)
return;
}
2008-03-26 14:53:56 +00:00
#endif /* PNG_READ_INTERLACING_SUPPORTED */
1995-07-20 07:43:20 +00:00
1996-06-05 20:50:50 +00:00
if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
1995-07-20 07:43:20 +00:00
{
1999-11-29 05:32:18 +00:00
#ifdef PNG_USE_LOCAL_ARRAYS
2007-05-21 18:27:47 +00:00
PNG_CONST PNG_IDAT;
1999-11-29 05:32:18 +00:00
#endif
1995-07-20 07:43:20 +00:00
char extra;
int ret;
1997-01-17 07:34:35 +00:00
png_ptr->zstream.next_out = (Byte *)&extra;
png_ptr->zstream.avail_out = (uInt)1;
1998-03-07 20:33:00 +00:00
for(;;)
1995-07-20 07:43:20 +00:00
{
1997-01-17 07:34:35 +00:00
if (!(png_ptr->zstream.avail_in))
1995-07-20 07:43:20 +00:00
{
while (!png_ptr->idat_size)
{
1997-01-17 07:34:35 +00:00
png_byte chunk_length[4];
1995-07-20 07:43:20 +00:00
1997-01-17 07:34:35 +00:00
png_crc_finish(png_ptr, 0);
1995-07-20 07:43:20 +00:00
1997-01-17 07:34:35 +00:00
png_read_data(png_ptr, chunk_length, 4);
2004-07-28 13:20:44 +00:00
png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length);
1997-01-17 07:34:35 +00:00
png_reset_crc(png_ptr);
png_crc_read(png_ptr, png_ptr->chunk_name, 4);
2007-09-18 17:44:25 +00:00
if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
1995-12-19 09:22:19 +00:00
png_error(png_ptr, "Not enough image data");
1995-07-20 07:43:20 +00:00
}
1997-01-17 07:34:35 +00:00
png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
png_ptr->zstream.next_in = png_ptr->zbuf;
1995-07-20 07:43:20 +00:00
if (png_ptr->zbuf_size > png_ptr->idat_size)
1997-01-17 07:34:35 +00:00
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;
1995-07-20 07:43:20 +00:00
}
1997-01-17 07:34:35 +00:00
ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
1995-07-20 07:43:20 +00:00
if (ret == Z_STREAM_END)
{
1997-01-17 07:34:35 +00:00
if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
1995-07-20 07:43:20 +00:00
png_ptr->idat_size)
2002-08-06 23:06:11 +00:00
png_warning(png_ptr, "Extra compressed data");
1997-01-17 07:34:35 +00:00
png_ptr->mode |= PNG_AFTER_IDAT;
png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
1995-07-20 07:43:20 +00:00
break;
}
if (ret != Z_OK)
1997-01-17 07:34:35 +00:00
png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
1996-06-05 20:50:50 +00:00
"Decompression Error");
1995-07-20 07:43:20 +00:00
1997-01-17 07:34:35 +00:00
if (!(png_ptr->zstream.avail_out))
2002-08-06 23:06:11 +00:00
{
png_warning(png_ptr, "Extra compressed data.");
png_ptr->mode |= PNG_AFTER_IDAT;
png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
break;
}
1995-07-20 07:43:20 +00:00
1998-03-07 20:33:00 +00:00
}
1997-01-17 07:34:35 +00:00
png_ptr->zstream.avail_out = 0;
1995-07-20 07:43:20 +00:00
}
1997-01-17 07:34:35 +00:00
if (png_ptr->idat_size || png_ptr->zstream.avail_in)
2002-08-06 23:06:11 +00:00
png_warning(png_ptr, "Extra compression data");
1995-07-20 07:43:20 +00:00
1997-01-17 07:34:35 +00:00
inflateReset(&png_ptr->zstream);
1995-07-20 07:43:20 +00:00
1997-01-17 07:34:35 +00:00
png_ptr->mode |= PNG_AFTER_IDAT;
1995-07-20 07:43:20 +00:00
}
2000-05-06 19:09:57 +00:00
void /* PRIVATE */
1995-12-19 09:22:19 +00:00
png_read_start_row(png_structp png_ptr)
1995-07-20 07:43:20 +00:00
{
1999-11-29 05:32:18 +00:00
#ifdef PNG_USE_LOCAL_ARRAYS
2008-03-26 14:53:56 +00:00
#ifdef PNG_READ_INTERLACING_SUPPORTED
1999-11-27 16:22:33 +00:00
/* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
1999-12-10 15:43:02 +00:00
1999-11-27 16:22:33 +00:00
/* start of interlace block */
2007-05-18 18:40:59 +00:00
PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
1999-12-10 15:43:02 +00:00
1999-11-27 16:22:33 +00:00
/* offset to next interlace block */
2007-05-18 18:40:59 +00:00
PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
1999-12-10 15:43:02 +00:00
1999-11-27 16:22:33 +00:00
/* start of interlace block in the y direction */
2007-05-18 18:40:59 +00:00
PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
1999-12-10 15:43:02 +00:00
1999-11-27 16:22:33 +00:00
/* offset to next interlace block in the y direction */
2007-05-18 18:40:59 +00:00
PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
2008-03-26 14:53:56 +00:00
#endif
1999-11-29 05:32:18 +00:00
#endif
1999-12-10 15:43:02 +00:00
1995-07-20 07:43:20 +00:00
int max_pixel_depth;
1998-05-09 15:02:29 +00:00
png_uint_32 row_bytes;
1995-07-20 07:43:20 +00:00
1997-05-16 07:46:07 +00:00
png_debug(1, "in png_read_start_row\n");
1997-01-17 07:34:35 +00:00
png_ptr->zstream.avail_in = 0;
1995-07-20 07:43:20 +00:00
png_init_read_transformations(png_ptr);
2008-03-26 14:53:56 +00:00
#ifdef PNG_READ_INTERLACING_SUPPORTED
1995-07-20 07:43:20 +00:00
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];
1998-02-07 16:20:57 +00:00
2004-08-04 11:34:52 +00:00
row_bytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->iwidth) + 1;
1998-05-09 15:02:29 +00:00
png_ptr->irowbytes = (png_size_t)row_bytes;
if((png_uint_32)png_ptr->irowbytes != row_bytes)
1998-02-07 16:20:57 +00:00
png_error(png_ptr, "Rowbytes overflow in png_read_start_row");
1995-07-20 07:43:20 +00:00
}
else
2008-03-26 14:53:56 +00:00
#endif /* PNG_READ_INTERLACING_SUPPORTED */
1995-07-20 07:43:20 +00:00
{
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;
1995-09-26 10:22:39 +00:00
#if defined(PNG_READ_PACK_SUPPORTED)
1995-07-20 07:43:20 +00:00
if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
max_pixel_depth = 8;
1995-09-26 10:22:39 +00:00
#endif
1995-07-20 07:43:20 +00:00
1996-06-05 20:50:50 +00:00
#if defined(PNG_READ_EXPAND_SUPPORTED)
if (png_ptr->transformations & PNG_EXPAND)
1995-07-20 07:43:20 +00:00
{
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;
}
}
}
1995-09-26 10:22:39 +00:00
#endif
1995-07-20 07:43:20 +00:00
1995-09-26 10:22:39 +00:00
#if defined(PNG_READ_FILLER_SUPPORTED)
if (png_ptr->transformations & (PNG_FILLER))
1995-07-20 07:43:20 +00:00
{
1998-05-09 15:02:29 +00:00
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
max_pixel_depth = 32;
else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
1998-04-21 20:03:57 +00:00
{
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;
}
1995-07-20 07:43:20 +00:00
}
1995-09-26 10:22:39 +00:00
#endif
1995-07-20 07:43:20 +00:00
1995-09-26 10:22:39 +00:00
#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1995-07-20 07:43:20 +00:00
if (png_ptr->transformations & PNG_GRAY_TO_RGB)
{
1998-12-29 17:47:59 +00:00
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)
1995-07-20 07:43:20 +00:00
{
if (max_pixel_depth <= 16)
max_pixel_depth = 32;
1998-12-29 17:47:59 +00:00
else
1995-07-20 07:43:20 +00:00
max_pixel_depth = 64;
}
else
{
if (max_pixel_depth <= 8)
2000-02-18 19:48:52 +00:00
{
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;
1998-12-29 17:47:59 +00:00
else
1995-07-20 07:43:20 +00:00
max_pixel_depth = 48;
}
}
1995-09-26 10:22:39 +00:00
#endif
1995-07-20 07:43:20 +00:00
2000-05-01 14:31:54 +00:00
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
1999-10-01 19:22:25 +00:00
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
1995-07-20 07:43:20 +00:00
/* align the width on the next larger 8 pixels. Mainly used
for interlacing */
1998-05-09 15:02:29 +00:00
row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
1995-07-20 07:43:20 +00:00
/* calculate the maximum bytes needed, adding a byte and a pixel
1998-04-21 20:03:57 +00:00
for safety's sake */
2004-08-04 11:34:52 +00:00
row_bytes = PNG_ROWBYTES(max_pixel_depth,row_bytes) +
1995-07-20 07:43:20 +00:00
1 + ((max_pixel_depth + 7) >> 3);
#ifdef PNG_MAX_MALLOC_64K
1998-05-09 15:02:29 +00:00
if (row_bytes > (png_uint_32)65536L)
1996-06-05 20:50:50 +00:00
png_error(png_ptr, "This image requires a row greater than 64KB");
1995-07-20 07:43:20 +00:00
#endif
2008-03-18 23:38:07 +00:00
2008-03-20 00:26:22 +00:00
if(row_bytes + 64 > png_ptr->old_big_row_buf_size)
{
2008-04-14 14:26:03 +00:00
png_free(png_ptr,png_ptr->big_row_buf);
2008-03-20 00:26:22 +00:00
png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes+64);
png_ptr->row_buf = png_ptr->big_row_buf+32;
png_ptr->old_big_row_buf_size = row_bytes+64;
}
1995-07-20 07:43:20 +00:00
#ifdef PNG_MAX_MALLOC_64K
1998-01-01 13:13:13 +00:00
if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L)
1996-06-05 20:50:50 +00:00
png_error(png_ptr, "This image requires a row greater than 64KB");
1995-07-20 07:43:20 +00:00
#endif
2006-11-08 02:09:46 +00:00
if ((png_uint_32)png_ptr->rowbytes > (png_uint_32)(PNG_SIZE_MAX - 1))
2004-07-28 13:20:44 +00:00
png_error(png_ptr, "Row has too many bytes to allocate in memory.");
2008-03-20 00:26:22 +00:00
if(png_ptr->rowbytes+1 > png_ptr->old_prev_row_size)
{
2008-04-14 14:26:03 +00:00
png_free(png_ptr,png_ptr->prev_row);
2008-03-20 00:26:22 +00:00
png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
png_ptr->rowbytes + 1));
png_ptr->old_prev_row_size = png_ptr->rowbytes+1;
}
1997-05-16 07:46:07 +00:00
1998-02-09 02:56:40 +00:00
png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
1995-07-20 07:43:20 +00:00
2000-07-17 11:17:09 +00:00
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);
1995-07-20 07:43:20 +00:00
1996-06-05 20:50:50 +00:00
png_ptr->flags |= PNG_FLAG_ROW_INIT;
1995-07-20 07:43:20 +00:00
}
2006-02-21 04:09:05 +00:00
#endif /* PNG_READ_SUPPORTED */