-Index: pngread.c
-===================================================================
---- pngread.c
-+++ pngread.c
-@@ -413,6 +413,11 @@
- #if defined(PNG_READ_zTXt_SUPPORTED)
- PNG_CONST PNG_zTXt;
- #endif
-+#if defined(PNG_READ_APNG_SUPPORTED)
-+ PNG_CONST PNG_acTL;
-+ PNG_CONST PNG_fcTL;
-+ PNG_CONST PNG_fdAT;
-+#endif
- #endif /* PNG_USE_LOCAL_ARRAYS */
- png_uint_32 length = png_read_chunk_header(png_ptr);
- PNG_CONST png_bytep chunk_name = png_ptr->chunk_name;
-@@ -457,6 +462,9 @@
- !(png_ptr->mode & PNG_HAVE_PLTE))
- png_error(png_ptr, "Missing PLTE before IDAT");
-
-+#if defined(PNG_READ_APNG_SUPPORTED)
-+ png_have_info(png_ptr, info_ptr);
-+#endif
- png_ptr->idat_size = length;
- png_ptr->mode |= PNG_HAVE_IDAT;
- break;
-@@ -529,12 +537,97 @@
- else if (!png_memcmp(chunk_name, png_iTXt, 4))
- png_handle_iTXt(png_ptr, info_ptr, length);
- #endif
-+#if defined(PNG_READ_APNG_SUPPORTED)
-+ else if (!png_memcmp(chunk_name, png_acTL, 4))
-+ png_handle_acTL(png_ptr, info_ptr, length);
-+ else if (!png_memcmp(chunk_name, png_fcTL, 4))
-+ png_handle_fcTL(png_ptr, info_ptr, length);
-+ else if (!png_memcmp(chunk_name, png_fdAT, 4))
-+ png_handle_fdAT(png_ptr, info_ptr, length);
-+#endif
- else
- png_handle_unknown(png_ptr, info_ptr, length);
- }
- }
- #endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */
-
-+#if defined(PNG_READ_APNG_SUPPORTED)
-+void PNGAPI
-+png_read_frame_head(png_structp png_ptr, png_infop info_ptr)
-+{
-+ png_byte have_chunk_after_DAT; /* after IDAT or after fdAT */
-+
-+ png_debug(0, "Reading frame head");
-+
-+ if (!(png_ptr->mode & PNG_HAVE_acTL))
-+ png_error(png_ptr, "attempt to png_read_frame_head() but "
-+ "no acTL present");
-+
-+ /* do nothing for the main IDAT */
-+ if (png_ptr->num_frames_read == 0)
-+ return;
-+
-+ png_crc_finish(png_ptr, 0); /* CRC from last IDAT or fdAT chunk */
-+
-+ png_read_reset(png_ptr);
-+ png_ptr->mode &= ~PNG_HAVE_fcTL;
-+
-+ have_chunk_after_DAT = 0;
-+ for (;;)
-+ {
-+#ifdef PNG_USE_LOCAL_ARRAYS
-+ PNG_IDAT;
-+ PNG_fdAT;
-+ PNG_fcTL;
-+#endif
-+ png_byte chunk_length[4];
-+ png_uint_32 length;
-+
-+ png_read_data(png_ptr, chunk_length, 4);
-+ length = 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_IDAT, 4))
-+ {
-+ /* discard trailing IDATs for the first frame */
-+ if (have_chunk_after_DAT || png_ptr->num_frames_read > 1)
-+ png_error(png_ptr, "png_read_frame_head(): out of place IDAT");
-+ png_crc_finish(png_ptr, length);
-+ }
-+ else if (!png_memcmp(png_ptr->chunk_name, png_fcTL, 4))
-+ {
-+ png_handle_fcTL(png_ptr, info_ptr, length);
-+ have_chunk_after_DAT = 1;
-+ }
-+ else if (!png_memcmp(png_ptr->chunk_name, png_fdAT, 4))
-+ {
-+ png_ensure_sequence_number(png_ptr, length);
-+
-+ /* discard trailing fdATs for frames other than the first */
-+ if (!have_chunk_after_DAT && png_ptr->num_frames_read > 1)
-+ png_crc_finish(png_ptr, length - 4);
-+ else if(png_ptr->mode & PNG_HAVE_fcTL)
-+ {
-+ png_ptr->idat_size = length - 4;
-+ png_ptr->mode |= PNG_HAVE_IDAT;
-+
-+ break;
-+ }
-+ else
-+ png_error(png_ptr, "png_read_frame_head(): out of place fdAT");
-+ }
-+ else
-+ {
-+ png_warning(png_ptr, "Skipped (ignored) a chunk "
-+ "between APNG chunks");
-+ png_crc_finish(png_ptr, length);
-+ }
-+ }
-+}
-+#endif /* PNG_READ_APNG_SUPPORTED */
-+
- /* Optional call to update the users info_ptr structure */
- void PNGAPI
- png_read_update_info(png_structp png_ptr, png_infop info_ptr)
-@@ -573,6 +666,10 @@
- {
- #ifdef PNG_USE_LOCAL_ARRAYS
- PNG_CONST PNG_IDAT;
-+#if defined(PNG_READ_APNG_SUPPORTED)
-+ PNG_CONST PNG_fdAT;
-+ PNG_CONST PNG_IEND;
-+#endif
- PNG_CONST int png_pass_dsp_mask[7] = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55,
- 0xff};
- PNG_CONST int png_pass_mask[7] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff};
-@@ -703,13 +800,39 @@
- {
- if (!(png_ptr->zstream.avail_in))
- {
-- while (!png_ptr->idat_size)
-+ png_uint_32 bytes_to_skip = 0;
-+
-+ while (!png_ptr->idat_size || bytes_to_skip != 0)
- {
-- png_crc_finish(png_ptr, 0);
-+ png_crc_finish(png_ptr, bytes_to_skip);
-+ bytes_to_skip = 0;
-
- png_ptr->idat_size = png_read_chunk_header(png_ptr);
-+#if defined(PNG_READ_APNG_SUPPORTED)
-+ if (png_ptr->num_frames_read == 0)
-+ {
-+#endif
- if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
- png_error(png_ptr, "Not enough image data");
-+#if defined(PNG_READ_APNG_SUPPORTED)
-+ }
-+ else
-+ {
-+ if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
-+ png_error(png_ptr, "Not enough image data");
-+ if (png_memcmp(png_ptr->chunk_name, png_fdAT, 4))
-+ {
-+ png_warning(png_ptr, "Skipped (ignored) a chunk "
-+ "between APNG chunks");
-+ bytes_to_skip = png_ptr->idat_size;
-+ continue;
-+ }
-+
-+ png_ensure_sequence_number(png_ptr, png_ptr->idat_size);
-+
-+ png_ptr->idat_size -= 4;
-+ }
-+#endif
- }
- png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
- png_ptr->zstream.next_in = png_ptr->zbuf;
-@@ -727,6 +850,9 @@
- png_error(png_ptr, "Extra compressed data");
- png_ptr->mode |= PNG_AFTER_IDAT;
- png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
-+#if defined(PNG_READ_APNG_SUPPORTED)
-+ png_ptr->num_frames_read++;
-+#endif
- break;
- }
- if (ret != Z_OK)
-@@ -981,6 +1107,11 @@
- #if defined(PNG_READ_zTXt_SUPPORTED)
- PNG_CONST PNG_zTXt;
- #endif
-+#if defined(PNG_READ_APNG_SUPPORTED)
-+ PNG_CONST PNG_acTL;
-+ PNG_CONST PNG_fcTL;
-+ PNG_CONST PNG_fdAT;
-+#endif
- #endif /* PNG_USE_LOCAL_ARRAYS */
- png_uint_32 length = png_read_chunk_header(png_ptr);
- PNG_CONST png_bytep chunk_name = png_ptr->chunk_name;
-@@ -1081,6 +1212,14 @@
- else if (!png_memcmp(chunk_name, png_iTXt, 4))
- png_handle_iTXt(png_ptr, info_ptr, length);
- #endif
-+#if defined(PNG_READ_APNG_SUPPORTED)
-+ else if (!png_memcmp(chunk_name, png_acTL, 4))
-+ png_handle_acTL(png_ptr, info_ptr, length);
-+ else if (!png_memcmp(chunk_name, png_fcTL, 4))
-+ png_handle_fcTL(png_ptr, info_ptr, length);
-+ else if (!png_memcmp(chunk_name, png_fdAT, 4))
-+ png_handle_fdAT(png_ptr, info_ptr, length);
-+#endif
- else
- png_handle_unknown(png_ptr, info_ptr, length);
- } while (!(png_ptr->mode & PNG_HAVE_IEND));
-Index: pngget.c
-===================================================================
---- pngget.c
-+++ pngget.c
-@@ -839,6 +839,167 @@
- }
- #endif
-
-+#ifdef PNG_APNG_SUPPORTED
-+png_uint_32 PNGAPI
-+png_get_acTL(png_structp png_ptr, png_infop info_ptr,
-+ png_uint_32 *num_frames, png_uint_32 *num_plays)
-+{
-+ png_debug1(1, "in %s retrieval function", "acTL");
-+
-+ if (png_ptr != NULL && info_ptr != NULL &&
-+ (info_ptr->valid & PNG_INFO_acTL) &&
-+ num_frames != NULL && num_plays != NULL)
-+ {
-+ *num_frames = info_ptr->num_frames;
-+ *num_plays = info_ptr->num_plays;
-+ return (1);
-+ }
-+
-+ return (0);
-+}
-+
-+png_uint_32 PNGAPI
-+png_get_num_frames(png_structp png_ptr, png_infop info_ptr)
-+{
-+ png_debug(1, "in png_get_num_frames()");
-+
-+ if (png_ptr != NULL && info_ptr != NULL)
-+ return (info_ptr->num_frames);
-+ return (0);
-+}
-+
-+png_uint_32 PNGAPI
-+png_get_num_plays(png_structp png_ptr, png_infop info_ptr)
-+{
-+ png_debug(1, "in png_get_num_plays()");
-+
-+ if (png_ptr != NULL && info_ptr != NULL)
-+ return (info_ptr->num_plays);
-+ return (0);
-+}
-+
-+png_uint_32 PNGAPI
-+png_get_next_frame_fcTL(png_structp png_ptr, png_infop info_ptr,
-+ png_uint_32 *width, png_uint_32 *height,
-+ png_uint_32 *x_offset, png_uint_32 *y_offset,
-+ png_uint_16 *delay_num, png_uint_16 *delay_den,
-+ png_byte *dispose_op, png_byte *blend_op)
-+{
-+ png_debug1(1, "in %s retrieval function", "fcTL");
-+
-+ if (png_ptr != NULL && info_ptr != NULL &&
-+ (info_ptr->valid & PNG_INFO_fcTL) &&
-+ width != NULL && height != NULL &&
-+ x_offset != NULL && x_offset != NULL &&
-+ delay_num != NULL && delay_den != NULL &&
-+ dispose_op != NULL && blend_op != NULL)
-+ {
-+ *width = info_ptr->next_frame_width;
-+ *height = info_ptr->next_frame_height;
-+ *x_offset = info_ptr->next_frame_x_offset;
-+ *y_offset = info_ptr->next_frame_y_offset;
-+ *delay_num = info_ptr->next_frame_delay_num;
-+ *delay_den = info_ptr->next_frame_delay_den;
-+ *dispose_op = info_ptr->next_frame_dispose_op;
-+ *blend_op = info_ptr->next_frame_blend_op;
-+ return (1);
-+ }
-+
-+ return (0);
-+}
-+
-+png_uint_32 PNGAPI
-+png_get_next_frame_width(png_structp png_ptr, png_infop info_ptr)
-+{
-+ png_debug(1, "in png_get_next_frame_width()");
-+
-+ if (png_ptr != NULL && info_ptr != NULL)
-+ return (info_ptr->next_frame_width);
-+ return (0);
-+}
-+
-+png_uint_32 PNGAPI
-+png_get_next_frame_height(png_structp png_ptr, png_infop info_ptr)
-+{
-+ png_debug(1, "in png_get_next_frame_height()");
-+
-+ if (png_ptr != NULL && info_ptr != NULL)
-+ return (info_ptr->next_frame_height);
-+ return (0);
-+}
-+
-+png_uint_32 PNGAPI
-+png_get_next_frame_x_offset(png_structp png_ptr, png_infop info_ptr)
-+{
-+ png_debug(1, "in png_get_next_frame_x_offset()");
-+
-+ if (png_ptr != NULL && info_ptr != NULL)
-+ return (info_ptr->next_frame_x_offset);
-+ return (0);
-+}
-+
-+png_uint_32 PNGAPI
-+png_get_next_frame_y_offset(png_structp png_ptr, png_infop info_ptr)
-+{
-+ png_debug(1, "in png_get_next_frame_y_offset()");
-+
-+ if (png_ptr != NULL && info_ptr != NULL)
-+ return (info_ptr->next_frame_y_offset);
-+ return (0);
-+}
-+
-+png_uint_16 PNGAPI
-+png_get_next_frame_delay_num(png_structp png_ptr, png_infop info_ptr)
-+{
-+ png_debug(1, "in png_get_next_frame_delay_num()");
-+
-+ if (png_ptr != NULL && info_ptr != NULL)
-+ return (info_ptr->next_frame_delay_num);
-+ return (0);
-+}
-+
-+png_uint_16 PNGAPI
-+png_get_next_frame_delay_den(png_structp png_ptr, png_infop info_ptr)
-+{
-+ png_debug(1, "in png_get_next_frame_delay_den()");
-+
-+ if (png_ptr != NULL && info_ptr != NULL)
-+ return (info_ptr->next_frame_delay_den);
-+ return (0);
-+}
-+
-+png_byte PNGAPI
-+png_get_next_frame_dispose_op(png_structp png_ptr, png_infop info_ptr)
-+{
-+ png_debug(1, "in png_get_next_frame_dispose_op()");
-+
-+ if (png_ptr != NULL && info_ptr != NULL)
-+ return (info_ptr->next_frame_dispose_op);
-+ return (0);
-+}
-+
-+png_byte PNGAPI
-+png_get_next_frame_blend_op(png_structp png_ptr, png_infop info_ptr)
-+{
-+ png_debug(1, "in png_get_next_frame_blend_op()");
-+
-+ if (png_ptr != NULL && info_ptr != NULL)
-+ return (info_ptr->next_frame_blend_op);
-+ return (0);
-+}
-+
-+png_byte PNGAPI
-+png_get_first_frame_is_hidden(png_structp png_ptr, png_infop info_ptr)
-+{
-+ png_debug(1, "in png_first_frame_is_hidden()");
-+
-+ if (png_ptr != NULL)
-+ return (png_byte)(png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN);
-+
-+ return 0;
-+}
-+#endif /* PNG_APNG_SUPPORTED */
-+
- #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
- png_uint_32 PNGAPI
- png_get_unknown_chunks(png_structp png_ptr, png_infop info_ptr,
-Index: png.c
-===================================================================
---- png.c
-+++ png.c
-@@ -54,6 +54,11 @@