/* pngwutil.c - utilities to write a PNG file
*
- * libpng 1.2.4 - July 8, 2002
+ * libpng version 1.2.7 - September 12, 2004
* For conditions of distribution and use, see copyright notice in png.h
- * Copyright (c) 1998-2002 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2004 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.)
*/
old_ptr = comp->output_ptr;
comp->output_ptr = (png_charpp)png_malloc(png_ptr,
- (png_uint_32)(comp->max_output_ptr * sizeof (png_charpp)));
+ (png_uint_32)(comp->max_output_ptr *
+ png_sizeof (png_charpp)));
png_memcpy(comp->output_ptr, old_ptr, old_max
- * sizeof (png_charp));
+ * png_sizeof (png_charp));
png_free(png_ptr, old_ptr);
}
else
comp->output_ptr = (png_charpp)png_malloc(png_ptr,
- (png_uint_32)(comp->max_output_ptr * sizeof (png_charp)));
+ (png_uint_32)(comp->max_output_ptr *
+ png_sizeof (png_charp)));
}
/* save the data */
old_ptr = comp->output_ptr;
/* This could be optimized to realloc() */
comp->output_ptr = (png_charpp)png_malloc(png_ptr,
- (png_uint_32)(comp->max_output_ptr * sizeof (png_charpp)));
+ (png_uint_32)(comp->max_output_ptr *
+ png_sizeof (png_charpp)));
png_memcpy(comp->output_ptr, old_ptr,
- old_max * sizeof (png_charp));
+ old_max * png_sizeof (png_charp));
png_free(png_ptr, old_ptr);
}
else
comp->output_ptr = (png_charpp)png_malloc(png_ptr,
- (png_uint_32)(comp->max_output_ptr * sizeof (png_charp)));
+ (png_uint_32)(comp->max_output_ptr *
+ png_sizeof (png_charp)));
}
/* save off the data */
#if defined(PNG_MNG_FEATURES_SUPPORTED)
png_ptr->filter_type = (png_byte)filter_type;
#endif
+ png_ptr->compression_type = (png_byte)compression_type;
png_ptr->width = width;
png_ptr->height = height;
png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels);
- png_ptr->rowbytes = ((width * (png_size_t)png_ptr->pixel_depth + 7) >> 3);
+ png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width);
/* set the usr info, so any transformations can modify it */
png_ptr->usr_width = png_ptr->width;
png_ptr->usr_bit_depth = png_ptr->bit_depth;
PNG_IDAT;
#endif
png_debug(1, "in png_write_IDAT\n");
+
+ /* Optimize the CMF field in the zlib stream. */
+ /* This hack of the zlib stream is compliant to the stream specification. */
+ if (!(png_ptr->mode & PNG_HAVE_IDAT) &&
+ png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
+ {
+ unsigned int z_cmf = data[0]; /* zlib compression method and flags */
+ if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70)
+ {
+ /* Avoid memory underflows and multiplication overflows. */
+ /* The conditions below are practically always satisfied;
+ however, they still must be checked. */
+ if (length >= 2 &&
+ png_ptr->height < 16384 && png_ptr->width < 16384)
+ {
+ png_uint_32 uncompressed_idat_size = png_ptr->height *
+ ((png_ptr->width *
+ png_ptr->channels * png_ptr->bit_depth + 15) >> 3);
+ unsigned int z_cinfo = z_cmf >> 4;
+ unsigned int half_z_window_size = 1 << (z_cinfo + 7);
+ while (uncompressed_idat_size <= half_z_window_size &&
+ half_z_window_size >= 256)
+ {
+ z_cinfo--;
+ half_z_window_size >>= 1;
+ }
+ z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4);
+ if (data[0] != (png_byte)z_cmf)
+ {
+ data[0] = (png_byte)z_cmf;
+ data[1] &= 0xe0;
+ data[1] += (png_byte)(0x1f - ((z_cmf << 8) + data[1]) % 0x1f);
+ }
+ }
+ }
+ else
+ png_error(png_ptr,
+ "Invalid zlib compression method or flags in IDAT");
+ }
+
png_write_chunk(png_ptr, (png_bytep)png_IDAT, data, length);
png_ptr->mode |= PNG_HAVE_IDAT;
}
png_debug1(2, "Keyword to be checked is '%s'\n", key);
- *new_key = (png_charp)png_malloc(png_ptr, (png_uint_32)(key_len + 2));
+ *new_key = (png_charp)png_malloc_warn(png_ptr, (png_uint_32)(key_len + 2));
+ if (*new_key == NULL)
+ {
+ png_warning(png_ptr, "Out of memory while procesing keyword");
+ return ((png_size_t)0);
+ }
/* Replace non-printing characters with a blank and print a warning */
for (kp = key, dp = *new_key; *kp != '\0'; kp++, dp++)
{
png_warning(png_ptr, "Empty language field in iTXt chunk");
new_lang = NULL;
- lang_len = 0;
+ lang_len = 0;
}
if (lang_key == NULL)
total_len = purpose_len + units_len + 10;
params_len = (png_uint_32p)png_malloc(png_ptr, (png_uint_32)(nparams
- *sizeof(png_uint_32)));
+ *png_sizeof(png_uint_32)));
/* Find the length of each parameter, making sure we don't count the
null terminator for the last parameter. */
#endif
png_size_t total_len;
char wbuf[32], hbuf[32];
+ png_byte bunit = unit;
png_debug(1, "in png_write_sCAL\n");
png_debug1(3, "sCAL total length = %d\n", (int)total_len);
png_write_chunk_start(png_ptr, (png_bytep)png_sCAL, (png_uint_32)total_len);
- png_write_chunk_data(png_ptr, (png_bytep)&unit, 1);
+ png_write_chunk_data(png_ptr, (png_bytep)&bunit, 1);
png_write_chunk_data(png_ptr, (png_bytep)wbuf, png_strlen(wbuf)+1);
png_write_chunk_data(png_ptr, (png_bytep)hbuf, png_strlen(hbuf));
#endif
png_size_t total_len;
char wbuf[32], hbuf[32];
+ png_byte bunit = unit;
png_debug(1, "in png_write_sCAL_s\n");
png_debug1(3, "sCAL total length = %d\n", total_len);
png_write_chunk_start(png_ptr, (png_bytep)png_sCAL, (png_uint_32)total_len);
- png_write_chunk_data(png_ptr, (png_bytep)&unit, 1);
+ png_write_chunk_data(png_ptr, (png_bytep)&bunit, 1);
png_write_chunk_data(png_ptr, (png_bytep)wbuf, png_strlen(wbuf)+1);
png_write_chunk_data(png_ptr, (png_bytep)hbuf, png_strlen(hbuf));
png_size_t buf_size;
png_debug(1, "in png_write_start_row\n");
- buf_size = (png_size_t)(((png_ptr->width * png_ptr->usr_channels *
- png_ptr->usr_bit_depth + 7) >> 3) + 1);
+ buf_size = (png_size_t)(PNG_ROWBYTES(
+ png_ptr->usr_channels*png_ptr->usr_bit_depth,png_ptr->width)+1);
/* set up row buffer */
png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, (png_uint_32)buf_size);
{
if (png_ptr->prev_row != NULL)
png_memset(png_ptr->prev_row, 0,
- (png_size_t) (((png_uint_32)png_ptr->usr_channels *
- (png_uint_32)png_ptr->usr_bit_depth *
- png_ptr->width + 7) >> 3) + 1);
+ (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels*
+ png_ptr->usr_bit_depth,png_ptr->width))+1);
return;
}
}
png_pass_inc[pass] - 1 -
png_pass_start[pass]) /
png_pass_inc[pass];
- row_info->rowbytes = ((row_info->width *
- row_info->pixel_depth + 7) >> 3);
+ row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
+ row_info->width);
}
}
#endif
png_debug(1, "in png_write_find_filter\n");
/* find out how many bytes offset each pixel is */
- bpp = (row_info->pixel_depth + 7) / 8;
+ bpp = (row_info->pixel_depth + 7) >> 3;
prev_row = png_ptr->prev_row;
best_row = row_buf = png_ptr->row_buf;
sum += (v < 128) ? v : 256 - v;
}
- for (lp = row_buf + 1; i < row_info->rowbytes;
+ for (lp = row_buf + 1; i < row_bytes;
i++, rp++, lp++, dp++)
{
v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);