Imported from pngcrush-1.6.5.tar

This commit is contained in:
Glenn Randers-Pehrson
2008-05-10 08:58:19 -05:00
parent ea25b6b078
commit 8f3268f4af
40 changed files with 2279 additions and 10821 deletions

View File

@@ -1,9 +1,9 @@
/* pngrutil.c - utilities to read a PNG file
*
* Last changed in libpng 1.2.11 June 4, 2006
* Last changed in libpng 1.2.27 [April 29, 2008]
* For conditions of distribution and use, see copyright notice in png.h
* Copyright (c) 1998-2006 Glenn Randers-Pehrson
* Copyright (c) 1998-2008 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -16,27 +16,33 @@
#if defined(PNG_READ_SUPPORTED)
#if defined(_WIN32_WCE)
#if defined(_WIN32_WCE) && (_WIN32_WCE<0x500)
# define WIN32_WCE_OLD
#endif
#ifdef PNG_FLOATING_POINT_SUPPORTED
# if defined(WIN32_WCE_OLD)
/* strtod() function is not supported on WindowsCE */
# ifdef PNG_FLOATING_POINT_SUPPORTED
__inline double strtod(const char *nptr, char **endptr)
__inline double png_strtod(png_structp png_ptr, PNG_CONST char *nptr, char **endptr)
{
double result = 0;
int len;
wchar_t *str, *end;
len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0);
str = (wchar_t *)malloc(len * sizeof(wchar_t));
str = (wchar_t *)png_malloc(png_ptr, len * sizeof(wchar_t));
if ( NULL != str )
{
MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len);
result = wcstod(str, &end);
len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL);
*endptr = (char *)nptr + (png_strlen(nptr) - len + 1);
free(str);
png_free(png_ptr, str);
}
return result;
}
# else
# define png_strtod(p,a,b) strtod(a,b)
# endif
#endif
@@ -90,6 +96,7 @@ png_get_uint_16(png_bytep buf)
void /* PRIVATE */
png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
{
if(png_ptr == NULL) return;
png_read_data(png_ptr, buf, length);
png_calculate_crc(png_ptr, buf, length);
}
@@ -178,7 +185,7 @@ png_decompress_chunk(png_structp png_ptr, int comp_type,
png_charp chunkdata, png_size_t chunklength,
png_size_t prefix_size, png_size_t *newlength)
{
static char msg[] = "Error decoding compressed text";
static PNG_CONST char msg[] = "Error decoding compressed text";
png_charp text;
png_size_t text_size;
@@ -223,7 +230,7 @@ png_decompress_chunk(png_structp png_ptr, int comp_type,
text_size = (png_size_t)(chunklength - (text - chunkdata) - 1);
text_size = png_sizeof(msg) > text_size ? text_size :
png_sizeof(msg);
png_memcpy(text + prefix_size, msg, text_size + 1);
png_memcpy(text + prefix_size, msg, text_size);
break;
}
if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END)
@@ -276,16 +283,19 @@ png_decompress_chunk(png_structp png_ptr, int comp_type,
if (ret != Z_STREAM_END)
{
#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
char umsg[50];
char umsg[52];
if (ret == Z_BUF_ERROR)
sprintf(umsg,"Buffer error in compressed datastream in %s chunk",
png_snprintf(umsg, 52,
"Buffer error in compressed datastream in %s chunk",
png_ptr->chunk_name);
else if (ret == Z_DATA_ERROR)
sprintf(umsg,"Data error in compressed datastream in %s chunk",
png_snprintf(umsg, 52,
"Data error in compressed datastream in %s chunk",
png_ptr->chunk_name);
else
sprintf(umsg,"Incomplete compressed datastream in %s chunk",
png_snprintf(umsg, 52,
"Incomplete compressed datastream in %s chunk",
png_ptr->chunk_name);
png_warning(png_ptr, umsg);
#else
@@ -318,7 +328,8 @@ png_decompress_chunk(png_structp png_ptr, int comp_type,
#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
char umsg[50];
sprintf(umsg, "Unknown zTXt compression type %d", comp_type);
png_snprintf(umsg, 50,
"Unknown zTXt compression type %d", comp_type);
png_warning(png_ptr, umsg);
#else
png_warning(png_ptr, "Unknown zTXt compression type");
@@ -560,8 +571,7 @@ png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
}
png_crc_finish(png_ptr, length);
if (&info_ptr == NULL) /* quiet compiler warnings about unused info_ptr */
return;
info_ptr =info_ptr; /* quiet compiler warnings about unused info_ptr */
}
#if defined(PNG_READ_gAMA_SUPPORTED)
@@ -1034,7 +1044,7 @@ png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
/* there should be at least one zero (the compression type byte)
following the separator, and we should be on it */
if ( profile >= chunkdata + slength)
if ( profile >= chunkdata + slength - 1)
{
png_free(png_ptr, chunkdata);
png_warning(png_ptr, "Malformed iCCP chunk");
@@ -1138,7 +1148,7 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
++entry_start;
/* a sample depth should follow the separator, and we should be on it */
if (entry_start > chunkdata + slength)
if (entry_start > chunkdata + slength - 2)
{
png_free(png_ptr, chunkdata);
png_warning(png_ptr, "malformed sPLT chunk");
@@ -1311,7 +1321,10 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
}
if (png_crc_finish(png_ptr, 0))
{
png_ptr->num_trans = 0;
return;
}
png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
&(png_ptr->trans_values));
@@ -1374,7 +1387,7 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{
png_ptr->background.index = buf[0];
if(info_ptr->num_palette)
if (info_ptr && info_ptr->num_palette)
{
if(buf[0] > info_ptr->num_palette)
{
@@ -1654,7 +1667,7 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
buf++; /* Skip the null string terminator from previous parameter. */
png_debug1(3, "Reading pCAL parameter %d\n", i);
for (params[i] = buf; *buf != 0x00 && buf <= endptr; buf++)
for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++)
/* Empty loop to move past each parameter string */ ;
/* Make sure we haven't run out of data yet */
@@ -1730,7 +1743,7 @@ png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
ep = buffer + 1; /* skip unit byte */
#ifdef PNG_FLOATING_POINT_SUPPORTED
width = strtod(ep, &vp);
width = png_strtod(png_ptr, ep, &vp);
if (*vp)
{
png_warning(png_ptr, "malformed width string in sCAL chunk");
@@ -1752,8 +1765,19 @@ png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
/* empty loop */ ;
ep++;
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;
}
#ifdef PNG_FLOATING_POINT_SUPPORTED
height = strtod(ep, &vp);
height = png_strtod(png_ptr, ep, &vp);
if (*vp)
{
png_warning(png_ptr, "malformed height string in sCAL chunk");
@@ -1762,7 +1786,7 @@ png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#else
#ifdef PNG_FIXED_POINT_SUPPORTED
sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
if (swidth == NULL)
if (sheight == NULL)
{
png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
return;
@@ -1975,10 +1999,11 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
/* empty loop */ ;
/* zTXt must have some text after the chunkdataword */
if (text == chunkdata + slength)
if (text >= chunkdata + slength - 2)
{
comp_type = PNG_TEXT_COMPRESSION_NONE;
png_warning(png_ptr, "Zero length zTXt chunk");
png_warning(png_ptr, "Truncated zTXt chunk");
png_free(png_ptr, chunkdata);
return;
}
else
{
@@ -2078,10 +2103,11 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
translated keyword (possibly empty), and possibly some text after the
keyword */
if (lang >= chunkdata + slength)
if (lang >= chunkdata + slength - 3)
{
comp_flag = PNG_TEXT_COMPRESSION_NONE;
png_warning(png_ptr, "Zero length iTXt chunk");
png_warning(png_ptr, "Truncated iTXt chunk");
png_free(png_ptr, chunkdata);
return;
}
else
{
@@ -2093,9 +2119,22 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
/* empty loop */ ;
lang_key++; /* skip NUL separator */
if (lang_key >= chunkdata + slength)
{
png_warning(png_ptr, "Truncated iTXt chunk");
png_free(png_ptr, chunkdata);
return;
}
for (text = lang_key; *text; text++)
/* empty loop */ ;
text++; /* skip NUL separator */
if (text >= chunkdata + slength)
{
png_warning(png_ptr, "Malformed iTXt chunk");
png_free(png_ptr, chunkdata);
return;
}
prefix_len = text - chunkdata;
@@ -2145,7 +2184,7 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
if (png_ptr->mode & PNG_HAVE_IDAT)
{
#ifdef PNG_USE_LOCAL_ARRAYS
PNG_IDAT;
PNG_CONST PNG_IDAT;
#endif
if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* not an IDAT */
png_ptr->mode |= PNG_AFTER_IDAT;
@@ -2170,8 +2209,6 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) ||
(png_ptr->read_user_chunk_fn != NULL))
{
png_unknown_chunk chunk;
#ifdef PNG_MAX_MALLOC_64K
if (length > (png_uint_32)65535L)
{
@@ -2180,30 +2217,42 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
length = (png_uint_32)65535L;
}
#endif
png_strcpy((png_charp)chunk.name, (png_charp)png_ptr->chunk_name);
chunk.data = (png_bytep)png_malloc(png_ptr, length);
chunk.size = (png_size_t)length;
png_crc_read(png_ptr, (png_bytep)chunk.data, length);
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';
png_ptr->unknown_chunk.size = (png_size_t)length;
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);
}
#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
if(png_ptr->read_user_chunk_fn != NULL)
{
/* callback to user unknown chunk handler */
if ((*(png_ptr->read_user_chunk_fn)) (png_ptr, &chunk) <= 0)
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)
{
if (!(png_ptr->chunk_name[0] & 0x20))
if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
PNG_HANDLE_CHUNK_ALWAYS)
{
png_free(png_ptr, chunk.data);
png_chunk_error(png_ptr, "unknown critical chunk");
}
png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
png_set_unknown_chunks(png_ptr, info_ptr,
&png_ptr->unknown_chunk, 1);
}
}
else
#endif
png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
png_free(png_ptr, chunk.data);
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;
}
else
#endif
@@ -2212,8 +2261,7 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_crc_finish(png_ptr, skip);
#if !defined(PNG_READ_USER_CHUNKS_SUPPORTED)
if (&info_ptr == NULL) /* quiet compiler warnings about unused info_ptr */
return;
info_ptr = info_ptr; /* quiet compiler warnings about unused info_ptr */
#endif
}
@@ -2246,7 +2294,7 @@ png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
a zero indicates the pixel is to be skipped. This is in addition
to any alpha or transparency value associated with the pixel. If
you want all pixels to be combined, pass 0xff (255) in mask. */
#ifndef PNG_HAVE_ASSEMBLER_COMBINE_ROW
void /* PRIVATE */
png_combine_row(png_structp png_ptr, png_bytep row, int mask)
{
@@ -2447,10 +2495,8 @@ png_combine_row(png_structp png_ptr, png_bytep row, int mask)
}
}
}
#endif /* !PNG_HAVE_ASSEMBLER_COMBINE_ROW */
#ifdef PNG_READ_INTERLACING_SUPPORTED
#ifndef PNG_HAVE_ASSEMBLER_READ_INTERLACE /* else in pngvcrd.c, pnggccrd.c */
/* 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)
@@ -2465,10 +2511,10 @@ png_do_read_interlace(png_structp png_ptr)
#ifdef PNG_USE_LOCAL_ARRAYS
/* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* offset to next interlace block */
const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
#endif
png_debug(1,"in png_do_read_interlace (stock C version)\n");
png_debug(1,"in png_do_read_interlace\n");
if (row != NULL && row_info != NULL)
{
png_uint_32 final_width;
@@ -2672,14 +2718,11 @@ png_do_read_interlace(png_structp png_ptr)
row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,final_width);
}
#if !defined(PNG_READ_PACKSWAP_SUPPORTED)
if (&transformations == NULL) /* silence compiler warning */
return;
transformations = transformations; /* silence compiler warning */
#endif
}
#endif /* !PNG_HAVE_ASSEMBLER_READ_INTERLACE */
#endif /* PNG_READ_INTERLACING_SUPPORTED */
#ifndef PNG_HAVE_ASSEMBLER_READ_FILTER_ROW
void /* PRIVATE */
png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
png_bytep prev_row, int filter)
@@ -2802,25 +2845,26 @@ png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
break;
}
}
#endif /* !PNG_HAVE_ASSEMBLER_READ_FILTER_ROW */
void /* PRIVATE */
png_read_finish_row(png_structp png_ptr)
{
#ifdef PNG_USE_LOCAL_ARRAYS
#ifdef PNG_READ_INTERLACING_SUPPORTED
/* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* start of interlace block */
const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
/* offset to next interlace block */
const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
/* start of interlace block in the y direction */
const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
/* offset to next interlace block in the y direction */
const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
#endif /* PNG_READ_INTERLACING_SUPPORTED */
#endif
png_debug(1, "in png_read_finish_row\n");
@@ -2828,10 +2872,12 @@ png_read_finish_row(png_structp png_ptr)
if (png_ptr->row_number < png_ptr->num_rows)
return;
#ifdef PNG_READ_INTERLACING_SUPPORTED
if (png_ptr->interlaced)
{
png_ptr->row_number = 0;
png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
png_memset_check(png_ptr, png_ptr->prev_row, 0,
png_ptr->rowbytes + 1);
do
{
png_ptr->pass++;
@@ -2861,11 +2907,12 @@ png_read_finish_row(png_structp png_ptr)
if (png_ptr->pass < 7)
return;
}
#endif /* PNG_READ_INTERLACING_SUPPORTED */
if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
{
#ifdef PNG_USE_LOCAL_ARRAYS
PNG_IDAT;
PNG_CONST PNG_IDAT;
#endif
char extra;
int ret;
@@ -2886,7 +2933,7 @@ png_read_finish_row(png_structp png_ptr)
png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length);
png_reset_crc(png_ptr);
png_crc_read(png_ptr, png_ptr->chunk_name, 4);
if (png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4))
if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
png_error(png_ptr, "Not enough image data");
}
@@ -2935,19 +2982,21 @@ void /* PRIVATE */
png_read_start_row(png_structp png_ptr)
{
#ifdef PNG_USE_LOCAL_ARRAYS
#ifdef PNG_READ_INTERLACING_SUPPORTED
/* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* start of interlace block */
const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
/* offset to next interlace block */
const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
/* start of interlace block in the y direction */
const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
/* offset to next interlace block in the y direction */
const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
#endif
#endif
int max_pixel_depth;
@@ -2956,6 +3005,7 @@ png_read_start_row(png_structp png_ptr)
png_debug(1, "in png_read_start_row\n");
png_ptr->zstream.avail_in = 0;
png_init_read_transformations(png_ptr);
#ifdef PNG_READ_INTERLACING_SUPPORTED
if (png_ptr->interlaced)
{
if (!(png_ptr->transformations & PNG_INTERLACE))
@@ -2976,6 +3026,7 @@ png_read_start_row(png_structp png_ptr)
png_error(png_ptr, "Rowbytes overflow in png_read_start_row");
}
else
#endif /* PNG_READ_INTERLACING_SUPPORTED */
{
png_ptr->num_rows = png_ptr->height;
png_ptr->iwidth = png_ptr->width;
@@ -3094,20 +3145,29 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
if (row_bytes > (png_uint_32)65536L)
png_error(png_ptr, "This image requires a row greater than 64KB");
#endif
png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes+64);
png_ptr->row_buf = png_ptr->big_row_buf+32;
#if defined(PNG_DEBUG) && defined(PNG_USE_PNGGCCRD)
png_ptr->row_buf_size = row_bytes;
#endif
if(row_bytes + 64 > png_ptr->old_big_row_buf_size)
{
png_free(png_ptr,png_ptr->big_row_buf);
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;
}
#ifdef PNG_MAX_MALLOC_64K
if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L)
png_error(png_ptr, "This image requires a row greater than 64KB");
#endif
if ((png_uint_32)png_ptr->rowbytes > PNG_SIZE_MAX - 1)
if ((png_uint_32)png_ptr->rowbytes > (png_uint_32)(PNG_SIZE_MAX - 1))
png_error(png_ptr, "Row has too many bytes to allocate in memory.");
png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
png_ptr->rowbytes + 1));
if(png_ptr->rowbytes+1 > png_ptr->old_prev_row_size)
{
png_free(png_ptr,png_ptr->prev_row);
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;
}
png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);