/* pngread.c - read a PNG file
*
- * libpng 1.0.1
+ * libpng 1.0.3 - January 14, 1999
* For conditions of distribution and use, see copyright notice in png.h
* Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
* Copyright (c) 1996, 1997 Andreas Dilger
- * Copyright (c) 1998, Glenn Randers-Pehrson
- * March 15, 1998
+ * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
*
* This file contains routines that an application calls directly to
* read a PNG file or stream.
/* Create a PNG structure for reading, and allocate any memory needed. */
png_structp
-png_create_read_struct(png_const_charp user_png_ver, voidp error_ptr,
+png_create_read_struct(png_const_charp user_png_ver, png_voidp error_ptr,
png_error_ptr error_fn, png_error_ptr warn_fn)
{
+
+#ifdef PNG_USER_MEM_SUPPORTED
+ return (png_create_read_struct_2(user_png_ver, error_ptr, error_fn,
+ warn_fn, NULL, NULL, NULL));
+}
+
+/* Alternate create PNG structure for reading, and allocate any memory needed. */
+png_structp
+png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
+ png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
+ png_malloc_ptr malloc_fn, png_free_ptr free_fn)
+{
+#endif /* PNG_USER_MEM_SUPPORTED */
+
png_structp png_ptr;
#ifdef USE_FAR_KEYWORD
jmp_buf jmpbuf;
#endif
png_debug(1, "in png_create_read_struct\n");
+#ifdef PNG_USER_MEM_SUPPORTED
+ if ((png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,
+ (png_malloc_ptr)malloc_fn)) == NULL)
+#else
if ((png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG)) == NULL)
+#endif
{
return (png_structp)NULL;
}
#ifdef USE_FAR_KEYWORD
png_memcpy(png_ptr->jmpbuf,jmpbuf,sizeof(jmp_buf));
#endif
+
+#ifdef PNG_USER_MEM_SUPPORTED
+ png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn);
+#endif /* PNG_USER_MEM_SUPPORTED */
+
png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
/* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
}
/* Initialize PNG structure for reading, and allocate any memory needed.
- This interface is depreciated in favour of the png_create_read_struct(),
+ This interface is deprecated in favour of the png_create_read_struct(),
and it will eventually disappear. */
void
png_read_init(png_structp png_ptr)
/* Read the information before the actual image data. This has been
* changed in v0.90 to allow reading a file that already has the magic
* bytes read from the stream. You can tell libpng how many bytes have
- * been read from the beginning of the stream (up to the maxumum of 8)
+ * been read from the beginning of the stream (up to the maximum of 8)
* via png_set_sig_bytes(), and we will only check the remaining bytes
* here. The application can then have access to the signature bytes we
* read if it is determined that this isn't a valid PNG file.
/* Initialize palette, background, etc, after transformations
* are set, but before any reading takes place. This allows
- * the user to obtail a gamma corrected palette, for example.
+ * the user to obtain a gamma-corrected palette, for example.
* If the user doesn't call this, we will do it ourselves.
*/
void
/* save jump buffer and error functions */
if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
png_read_start_row(png_ptr);
+ if (png_ptr->row_number == 0 && png_ptr->pass == 0)
+ {
+ /* check for transforms that have been set but were defined out */
+#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED)
+ if (png_ptr->transformations & PNG_INVERT_MONO)
+ png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined.");
+#endif
+#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED)
+ if (png_ptr->transformations & PNG_FILLER)
+ png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined.");
+#endif
+#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && !defined(PNG_READ_PACKSWAP_SUPPORTED)
+ if (png_ptr->transformations & PNG_PACKSWAP)
+ png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined.");
+#endif
+#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED)
+ if (png_ptr->transformations & PNG_PACK)
+ png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined.");
+#endif
+#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED)
+ if (png_ptr->transformations & PNG_SHIFT)
+ png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined.");
+#endif
+#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED)
+ if (png_ptr->transformations & PNG_BGR)
+ png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined.");
+#endif
+#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED)
+ if (png_ptr->transformations & PNG_SWAP_BYTES)
+ png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined.");
+#endif
+ }
#if defined(PNG_READ_INTERLACING_SUPPORTED)
/* if interlaced and we do not need a new row, combine row and return */
/* Read one or more rows of image data. If the image is interlaced,
* and png_set_interlace_handling() has been called, the rows need to
* contain the contents of the rows from the previous pass. If the
- * image has alpha or transparency, and png_handle_alpha() has been
+ * image has alpha or transparency, and png_handle_alpha()[*] has been
* called, the rows contents must be initialized to the contents of the
* screen.
- *
+ *
* "row" holds the actual image, and pixels are placed in it
* as they arrive. If the image is displayed after each pass, it will
* appear to "sparkle" in. "display_row" can be used to display a
* also, but you may. If the image is not interlaced, or if you have
* not called png_set_interlace_handling(), the display_row buffer will
* be ignored, so pass NULL to it.
+ *
+ * [*] png_handle_alpha() does not exist yet, as of libpng version 1.0.3.
*/
void
/* save jump buffer and error functions */
rp = row;
dp = display_row;
- for (i = 0; i < num_rows; i++)
- {
- png_bytep rptr;
- png_bytep dptr;
+ if (rp != NULL && dp != NULL)
+ for (i = 0; i < num_rows; i++)
+ {
+ png_bytep rptr = *rp++;
+ png_bytep dptr = *dp++;
- if (rp != NULL)
- rptr = *rp;
- else
- rptr = NULL;
- if (dp != NULL)
- dptr = *dp;
- else
- dptr = NULL;
- png_read_row(png_ptr, rptr, dptr);
- if (row != NULL)
+ png_read_row(png_ptr, rptr, dptr);
+ }
+ else if(rp != NULL)
+ for (i = 0; i < num_rows; i++)
+ {
+ png_bytep rptr = *rp;
+ png_read_row(png_ptr, rptr, NULL);
rp++;
- if (display_row != NULL)
+ }
+ else if(dp != NULL)
+ for (i = 0; i < num_rows; i++)
+ {
+ png_bytep dptr = *dp;
+ png_read_row(png_ptr, NULL, dptr);
dp++;
- }
+ }
}
/* Read the entire image. If the image has an alpha channel or a tRNS
- * chunk, and you have called png_handle_alpha(), you will need to
+ * chunk, and you have called png_handle_alpha()[*], you will need to
* initialize the image to the current image that PNG will be overlaying.
* We set the num_rows again here, in case it was incorrectly set in
* png_read_start_row() by a call to png_read_update_info() or
* prior to either of these functions like it should have been. You can
* only call this function once. If you desire to have an image for
* each pass of a interlaced image, use png_read_rows() instead.
+ *
+ * [*] png_handle_alpha() does not exist yet, as of libpng version 1.0.3.
*/
void
png_read_image(png_structp png_ptr, png_bytepp image)
{
- png_uint_32 i;
+ png_uint_32 i,image_height;
int pass, j;
png_bytepp rp;
/* save jump buffer and error functions */
pass = png_set_interlace_handling(png_ptr);
- png_ptr->num_rows = png_ptr->height; /* Make sure this is set correctly */
+ image_height=png_ptr->height;
+ png_ptr->num_rows = image_height; /* Make sure this is set correctly */
for (j = 0; j < pass; j++)
{
rp = image;
- for (i = 0; i < png_ptr->height; i++)
+ for (i = 0; i < image_height; i++)
{
png_read_row(png_ptr, *rp, NULL);
rp++;
{
png_structp png_ptr = NULL;
png_infop info_ptr = NULL, end_info_ptr = NULL;
+#ifdef PNG_USER_MEM_SUPPORTED
+ png_free_ptr free_fn = NULL;
+#endif /* PNG_USER_MEM_SUPPORTED */
png_debug(1, "in png_destroy_read_struct\n");
/* save jump buffer and error functions */
if (end_info_ptr_ptr != NULL)
end_info_ptr = *end_info_ptr_ptr;
+#ifdef PNG_USER_MEM_SUPPORTED
+ free_fn = png_ptr->free_fn;
+#endif
+
png_read_destroy(png_ptr, info_ptr, end_info_ptr);
if (info_ptr != NULL)
#if defined(PNG_READ_tEXt_SUPPORTED) || defined(PNG_READ_zTXt_SUPPORTED)
png_free(png_ptr, info_ptr->text);
#endif
+
+#ifdef PNG_USER_MEM_SUPPORTED
+ png_destroy_struct_2((png_voidp)info_ptr, free_fn);
+#else
png_destroy_struct((png_voidp)info_ptr);
+#endif
*info_ptr_ptr = (png_infop)NULL;
}
#if defined(PNG_READ_tEXt_SUPPORTED) || defined(PNG_READ_zTXt_SUPPORTED)
png_free(png_ptr, end_info_ptr->text);
#endif
+#ifdef PNG_USER_MEM_SUPPORTED
+ png_destroy_struct_2((png_voidp)end_info_ptr, free_fn);
+#else
png_destroy_struct((png_voidp)end_info_ptr);
+#endif
*end_info_ptr_ptr = (png_infop)NULL;
}
if (png_ptr != NULL)
{
+#ifdef PNG_USER_MEM_SUPPORTED
+ png_destroy_struct_2((png_voidp)png_ptr, free_fn);
+#else
png_destroy_struct((png_voidp)png_ptr);
+#endif
*png_ptr_ptr = (png_structp)NULL;
}
}
png_error_ptr error_fn;
png_error_ptr warning_fn;
png_voidp error_ptr;
+#ifdef PNG_USER_MEM_SUPPORTED
+ png_free_ptr free_fn;
+#endif
png_debug(1, "in png_read_destroy\n");
/* save jump buffer and error functions */
if (png_ptr->gamma_16_table != NULL)
{
int i;
- for (i = 0; i < (1 << (8 - png_ptr->gamma_shift)); i++)
+ int istop = (1 << (8 - png_ptr->gamma_shift));
+ for (i = 0; i < istop; i++)
{
png_free(png_ptr, png_ptr->gamma_16_table[i]);
}
+ png_free(png_ptr, png_ptr->gamma_16_table);
}
-#endif
#if defined(PNG_READ_BACKGROUND_SUPPORTED)
- png_free(png_ptr, png_ptr->gamma_16_table);
if (png_ptr->gamma_16_from_1 != NULL)
{
int i;
- for (i = 0; i < (1 << (8 - png_ptr->gamma_shift)); i++)
+ int istop = (1 << (8 - png_ptr->gamma_shift));
+ for (i = 0; i < istop; i++)
{
png_free(png_ptr, png_ptr->gamma_16_from_1[i]);
}
- }
png_free(png_ptr, png_ptr->gamma_16_from_1);
+ }
if (png_ptr->gamma_16_to_1 != NULL)
{
int i;
- for (i = 0; i < (1 << (8 - png_ptr->gamma_shift)); i++)
+ int istop = (1 << (8 - png_ptr->gamma_shift));
+ for (i = 0; i < istop; i++)
{
png_free(png_ptr, png_ptr->gamma_16_to_1[i]);
}
- }
png_free(png_ptr, png_ptr->gamma_16_to_1);
+ }
#endif
+#endif
+#if defined(PNG_TIME_RFC1123_SUPPORTED)
+ png_free(png_ptr, png_ptr->time_buffer);
+#endif /* PNG_TIME_RFC1123_SUPPORTED */
inflateEnd(&png_ptr->zstream);
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
error_fn = png_ptr->error_fn;
warning_fn = png_ptr->warning_fn;
error_ptr = png_ptr->error_ptr;
+#ifdef PNG_USER_MEM_SUPPORTED
+ free_fn = png_ptr->free_fn;
+#endif
png_memset(png_ptr, 0, sizeof (png_struct));
png_ptr->error_fn = error_fn;
png_ptr->warning_fn = warning_fn;
png_ptr->error_ptr = error_ptr;
+#ifdef PNG_USER_MEM_SUPPORTED
+ png_ptr->free_fn = free_fn;
+#endif
png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
}