ALT Linux Bugzilla
– Attachment 3126 Details for
Bug 18152
Add APNG support
New bug
|
Search
|
[?]
|
Help
Register
|
Log In
[x]
|
Forgot Password
Login:
[x]
|
EN
|
RU
[patch]
http://www.linuxfromscratch.org/patches/blfs/svn/libpng-1.2.33-apng-1.patch
libpng-1.2.33-apng-1.patch (text/plain), 54.93 KB, created by
Alexey Gladkov
on 2008-12-09 10:29:16 MSK
(
hide
)
Description:
http://www.linuxfromscratch.org/patches/blfs/svn/libpng-1.2.33-apng-1.patch
Filename:
MIME Type:
Creator:
Alexey Gladkov
Created:
2008-12-09 10:29:16 MSK
Size:
54.93 KB
patch
obsolete
>Submitted By: Ken Moffat <ken at linuxfromscratch dot org> >Date: 2008-11-08 >Initial Package Version: 1.2.10 >Upstream Status: Rejected >Origin: Andrew Smith, updated for 1.2.31 by Jens Ornot, taken from cblfs. >Description: APNG is an extension of the [PNG][pngspec] format, adding support for animated images. > It is intended to be a replacement for simple animated images > that have traditionally used the [GIF][gifspec] format, > while adding support for 24-bit images and 8-bit transparency. > APNG is a simpler alternative to MNG, > providing a spec suitable for the most common usage of animated images on the Internet. > > APNG is backwards-compatible with PNG; > any PNG decoder should be able to ignore the APNG-specific chunks and display a single image. > >diff -ruN libpng-1.2.31/pngread.c.orig libpng-1.2.31/pngread.c >--- libpng-1.2.31/pngread.c.orig 2008-08-23 21:44:39.000000000 +0200 >+++ libpng-1.2.31/pngread.c 2008-08-23 21:48:13.000000000 +0200 >@@ -407,6 +407,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; >@@ -451,6 +456,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; >@@ -523,12 +531,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(png_ptr->chunk_name, png_acTL, 4)) >+ png_handle_acTL(png_ptr, info_ptr, length); >+ else if (!png_memcmp(png_ptr->chunk_name, png_fcTL, 4)) >+ png_handle_fcTL(png_ptr, info_ptr, length); >+ else if (!png_memcmp(png_ptr->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\n"); >+ >+ 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) >@@ -565,6 +658,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}; >@@ -694,13 +791,40 @@ > { > 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; >@@ -718,6 +842,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) >@@ -969,6 +1096,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; >@@ -1069,6 +1201,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(png_ptr->chunk_name, png_acTL, 4)) >+ png_handle_acTL(png_ptr, info_ptr, length); >+ else if (!png_memcmp(png_ptr->chunk_name, png_fcTL, 4)) >+ png_handle_fcTL(png_ptr, info_ptr, length); >+ else if (!png_memcmp(png_ptr->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)); >diff -ruN libpng-1.2.31/pngget.c.orig libpng-1.2.31/pngget.c >--- libpng-1.2.31/pngget.c.orig 2008-08-23 21:44:56.000000000 +0200 >+++ libpng-1.2.31/pngget.c 2008-08-23 21:48:13.000000000 +0200 >@@ -796,6 +796,167 @@ > } > #endif > >+#if defined(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\n", "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()\n"); >+ >+ 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()\n"); >+ >+ 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\n", "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()\n"); >+ >+ 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()\n"); >+ >+ 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()\n"); >+ >+ 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()\n"); >+ >+ 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()\n"); >+ >+ 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()\n"); >+ >+ 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()\n"); >+ >+ 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()\n"); >+ >+ 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()\n"); >+ >+ 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, >diff -ruN libpng-1.2.31/png.c.orig libpng-1.2.31/png.c >--- libpng-1.2.31/png.c.orig 2008-08-23 21:45:13.000000000 +0200 >+++ libpng-1.2.31/png.c 2008-08-23 21:48:13.000000000 +0200 >@@ -51,6 +51,9 @@ > PNG_tIME; > PNG_tRNS; > PNG_zTXt; >+PNG_acTL; >+PNG_fcTL; >+PNG_fdAT; > > #ifdef PNG_READ_SUPPORTED > /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ >diff -ruN libpng-1.2.31/png.h.orig libpng-1.2.31/png.h >--- libpng-1.2.31/png.h.orig 2008-08-23 21:45:34.000000000 +0200 >+++ libpng-1.2.31/png.h 2008-08-23 21:48:13.000000000 +0200 >@@ -974,6 +974,19 @@ > png_fixed_point int_y_blue; > #endif > >+#if defined(PNG_APNG_SUPPORTED) >+ png_uint_32 num_frames; /* including default image */ >+ png_uint_32 num_plays; >+ png_uint_32 next_frame_width; >+ png_uint_32 next_frame_height; >+ png_uint_32 next_frame_x_offset; >+ png_uint_32 next_frame_y_offset; >+ png_uint_16 next_frame_delay_num; >+ png_uint_16 next_frame_delay_den; >+ png_byte next_frame_dispose_op; >+ png_byte next_frame_blend_op; >+#endif >+ > } png_info; > > typedef png_info FAR * png_infop; >@@ -1075,6 +1088,8 @@ > #define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */ > #define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */ > #define PNG_INFO_IDAT 0x8000L /* ESR, 1.0.6 */ >+#define PNG_INFO_acTL 0x10000L >+#define PNG_INFO_fcTL 0x20000L > > /* This is used for the transformation routines, as some of them > * change these values for the row. It also should enable using >@@ -1115,6 +1130,10 @@ > typedef void (PNGAPI *png_progressive_end_ptr) PNGARG((png_structp, png_infop)); > typedef void (PNGAPI *png_progressive_row_ptr) PNGARG((png_structp, png_bytep, > png_uint_32, int)); >+#if defined(PNG_APNG_SUPPORTED) >+typedef void (PNGAPI *png_progressive_frame_ptr) PNGARG((png_structp, >+ png_uint_32)); >+#endif > #endif > > #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ >@@ -1446,6 +1465,39 @@ > png_uint_32 user_height_max; > #endif > >+#if defined(PNG_APNG_SUPPORTED) >+ png_uint_32 apng_flags; >+ png_uint_32 next_seq_num; /* next fcTL/fdAT chunk sequence number */ >+ png_uint_32 first_frame_width; >+ png_uint_32 first_frame_height; >+ >+#if defined(PNG_READ_APNG_SUPPORTED) >+ png_uint_32 num_frames_read; /* incremented after all image data of */ >+ /* a frame is read */ >+#ifdef PNG_PROGRESSIVE_READ_SUPPORTED >+ png_progressive_frame_ptr frame_info_fn; /* frame info read callback */ >+ png_progressive_frame_ptr frame_end_fn; /* frame data read callback */ >+#endif >+#endif >+ >+#if defined(PNG_WRITE_APNG_SUPPORTED) >+ png_uint_32 num_frames_to_write; >+ png_uint_32 num_frames_written; >+#endif >+#endif >+ >+/* For png_struct.apng_flags: */ >+#define PNG_FIRST_FRAME_HIDDEN 0x0001 >+ >+/* dispose_op flags from inside fcTL */ >+#define PNG_DISPOSE_OP_NONE 0x00 >+#define PNG_DISPOSE_OP_BACKGROUND 0x01 >+#define PNG_DISPOSE_OP_PREVIOUS 0x02 >+ >+/* blend_op flags from inside fcTL */ >+#define PNG_BLEND_OP_SOURCE 0x00 >+#define PNG_BLEND_OP_OVER 0x01 >+ > /* New member added in libpng-1.0.25 and 1.2.17 */ > #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) > /* storage for unknown chunk that the library doesn't recognize. */ >@@ -1779,6 +1831,18 @@ > extern PNG_EXPORT(void,png_write_image) PNGARG((png_structp png_ptr, > png_bytepp image)); > >+#if defined(PNG_WRITE_APNG_SUPPORTED) >+extern PNG_EXPORT (void,png_write_frame_head) PNGARG((png_structp png_ptr, >+ png_infop png_info, png_bytepp row_pointers, >+ 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)); >+ >+extern PNG_EXPORT (void,png_write_frame_tail) PNGARG((png_structp png_ptr, >+ png_infop png_info)); >+#endif >+ > /* writes the end of the PNG file. */ > extern PNG_EXPORT(void,png_write_end) PNGARG((png_structp png_ptr, > png_infop info_ptr)); >@@ -2027,6 +2091,11 @@ > png_voidp progressive_ptr, > png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, > png_progressive_end_ptr end_fn)); >+#if defined(PNG_READ_APNG_SUPPORTED) >+extern PNG_EXPORT(void,png_set_progressive_frame_fn) PNGARG((png_structp png_ptr, >+ png_progressive_frame_ptr frame_info_fn, >+ png_progressive_frame_ptr frame_end_fn)); >+#endif > > /* returns the user pointer associated with the push read functions */ > extern PNG_EXPORT(png_voidp,png_get_progressive_ptr) >@@ -2464,6 +2533,59 @@ > #endif > #endif /* PNG_sCAL_SUPPORTED || PNG_WRITE_sCAL_SUPPORTED */ > >+#if defined(PNG_APNG_SUPPORTED) >+extern PNG_EXPORT(png_uint_32,png_get_acTL) PNGARG((png_structp png_ptr, >+ png_infop info_ptr, png_uint_32 *num_frames, png_uint_32 *num_plays)); >+extern PNG_EXPORT(png_uint_32,png_set_acTL) PNGARG((png_structp png_ptr, >+ png_infop info_ptr, png_uint_32 num_frames, png_uint_32 num_plays)); >+extern PNG_EXPORT(png_uint_32,png_get_num_frames) PNGARG((png_structp png_ptr, >+ png_infop info_ptr)); >+extern PNG_EXPORT(png_uint_32,png_get_num_plays) >+ PNGARG((png_structp png_ptr, png_infop info_ptr)); >+ >+extern PNG_EXPORT(png_uint_32,png_get_next_frame_fcTL) >+ PNGARG((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)); >+extern PNG_EXPORT(png_uint_32,png_set_next_frame_fcTL) >+ PNGARG((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)); >+extern PNG_EXPORT(void,png_ensure_fcTL_is_valid) >+ PNGARG((png_structp png_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)); >+extern PNG_EXPORT(png_uint_32,png_get_next_frame_width) >+ PNGARG((png_structp png_ptr, png_infop info_ptr)); >+extern PNG_EXPORT(png_uint_32,png_get_next_frame_height) >+ PNGARG((png_structp png_ptr, png_infop info_ptr)); >+extern PNG_EXPORT(png_uint_32,png_get_next_frame_x_offset) >+ PNGARG((png_structp png_ptr, png_infop info_ptr)); >+extern PNG_EXPORT(png_uint_32,png_get_next_frame_y_offset) >+ PNGARG((png_structp png_ptr, png_infop info_ptr)); >+extern PNG_EXPORT(png_uint_16,png_get_next_frame_delay_num) >+ PNGARG((png_structp png_ptr, png_infop info_ptr)); >+extern PNG_EXPORT(png_uint_16,png_get_next_frame_delay_den) >+ PNGARG((png_structp png_ptr, png_infop info_ptr)); >+extern PNG_EXPORT(png_byte,png_get_next_frame_dispose_op) >+ PNGARG((png_structp png_ptr, png_infop info_ptr)); >+extern PNG_EXPORT(png_byte,png_get_next_frame_blend_op) >+ PNGARG((png_structp png_ptr, png_infop info_ptr)); >+extern PNG_EXPORT(png_byte,png_get_first_frame_is_hidden) >+ PNGARG((png_structp png_ptr, png_infop info_ptr)); >+extern PNG_EXPORT(png_uint_32,png_set_first_frame_is_hidden) >+ PNGARG((png_structp png_ptr, png_infop info_ptr, png_byte is_hidden)); >+#endif /* PNG_APNG_SUPPORTED */ >+ >+#if defined(PNG_READ_APNG_SUPPORTED) >+extern PNG_EXPORT(void,png_read_frame_head) PNGARG((png_structp png_ptr, >+ png_infop info_ptr)); >+#endif >+ > #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) > /* provide a list of chunks and how they are to be handled, if the built-in > handling or default unknown chunk handling is not desired. Any chunks not >@@ -2771,6 +2893,8 @@ > #define PNG_BACKGROUND_IS_GRAY 0x800 > #define PNG_HAVE_PNG_SIGNATURE 0x1000 > #define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */ >+#define PNG_HAVE_acTL 0x4000 >+#define PNG_HAVE_fcTL 0x8000L > > /* flags for the transformations the PNG library does on the image data */ > #define PNG_BGR 0x0001 >@@ -2911,6 +3035,9 @@ > #define PNG_tIME png_byte png_tIME[5] = {116, 73, 77, 69, '\0'} > #define PNG_tRNS png_byte png_tRNS[5] = {116, 82, 78, 83, '\0'} > #define PNG_zTXt png_byte png_zTXt[5] = {122, 84, 88, 116, '\0'} >+#define PNG_acTL png_byte png_acTL[5] = { 97, 99, 84, 76, '\0'} >+#define PNG_fcTL png_byte png_fcTL[5] = {102, 99, 84, 76, '\0'} >+#define PNG_fdAT png_byte png_fdAT[5] = {102, 100, 65, 84, '\0'} > > #ifdef PNG_USE_GLOBAL_ARRAYS > PNG_EXPORT_VAR (png_byte FARDATA) png_IHDR[5]; >@@ -2934,6 +3061,9 @@ > PNG_EXPORT_VAR (png_byte FARDATA) png_tIME[5]; > PNG_EXPORT_VAR (png_byte FARDATA) png_tRNS[5]; > PNG_EXPORT_VAR (png_byte FARDATA) png_zTXt[5]; >+PNG_EXPORT_VAR (png_byte FARDATA) png_acTL[5]; >+PNG_EXPORT_VAR (png_byte FARDATA) png_fcTL[5]; >+PNG_EXPORT_VAR (png_byte FARDATA) png_fdAT[5]; > #endif /* PNG_USE_GLOBAL_ARRAYS */ > > #if defined(PNG_1_0_X) || defined (PNG_1_2_X) >@@ -3208,6 +3338,17 @@ > #endif > #endif > >+#if defined(PNG_WRITE_APNG_SUPPORTED) >+PNG_EXTERN void png_write_acTL PNGARG((png_structp png_ptr, >+ png_uint_32 num_frames, png_uint_32 num_plays)); >+ >+PNG_EXTERN void png_write_fcTL PNGARG((png_structp png_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)); >+#endif >+ > /* Called when finished processing a row of data */ > PNG_EXTERN void png_write_finish_row PNGARG((png_structp png_ptr)); > >@@ -3259,6 +3400,20 @@ > PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr, > png_infop info_ptr)); > >+#if defined(PNG_READ_APNG_SUPPORTED) >+/* private, reset some things to become ready for reading next frame */ >+PNG_EXTERN void png_read_reset PNGARG((png_structp png_ptr)); >+PNG_EXTERN void png_read_reinit PNGARG((png_structp png_ptr, >+ png_infop info_ptr)); >+PNG_EXTERN void png_progressive_read_reset PNGARG((png_structp png_ptr)); >+#endif >+#if defined(PNG_WRITE_APNG_SUPPORTED) >+/* private, reset some things to become ready for writing next frame */ >+PNG_EXTERN void png_write_reset PNGARG((png_structp png_ptr)); >+PNG_EXTERN void png_write_reinit PNGARG((png_structp png_ptr, >+ png_infop info_ptr, png_uint_32 width, png_uint_32 height)); >+#endif >+ > /* these are the functions that do the transformations */ > #if defined(PNG_READ_FILLER_SUPPORTED) > PNG_EXTERN void png_do_read_filler PNGARG((png_row_infop row_info, >@@ -3474,6 +3629,18 @@ > png_uint_32 length)); > #endif > >+#if defined(PNG_READ_APNG_SUPPORTED) >+PNG_EXTERN void png_handle_acTL PNGARG((png_structp png_ptr, png_infop info_ptr, >+ png_uint_32 length)); >+PNG_EXTERN void png_handle_fcTL PNGARG((png_structp png_ptr, png_infop info_ptr, >+ png_uint_32 length)); >+PNG_EXTERN void png_have_info PNGARG((png_structp png_ptr, png_infop info_ptr)); >+PNG_EXTERN void png_handle_fdAT PNGARG((png_structp png_ptr, png_infop info_ptr, >+ png_uint_32 length)); >+PNG_EXTERN void png_ensure_sequence_number PNGARG((png_structp png_ptr, >+ png_uint_32 length)); >+#endif >+ > PNG_EXTERN void png_handle_unknown PNGARG((png_structp png_ptr, > png_infop info_ptr, png_uint_32 length)); > >diff -ruN libpng-1.2.31/pngwrite.c.orig libpng-1.2.31/pngwrite.c >--- libpng-1.2.31/pngwrite.c.orig 2008-08-23 21:45:53.000000000 +0200 >+++ libpng-1.2.31/pngwrite.c 2008-08-23 21:48:13.000000000 +0200 >@@ -263,6 +263,10 @@ > } > } > #endif >+#if defined(PNG_WRITE_APNG_SUPPORTED) >+ if (info_ptr->valid & PNG_INFO_acTL) >+ png_write_acTL(png_ptr, info_ptr->num_frames, info_ptr->num_plays); >+#endif > #if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) > if (info_ptr->unknown_chunks_num) > { >@@ -301,6 +305,10 @@ > return; > if (!(png_ptr->mode & PNG_HAVE_IDAT)) > png_error(png_ptr, "No IDATs written into file"); >+#if defined(PNG_WRITE_APNG_SUPPORTED) >+ if (png_ptr->num_frames_written != png_ptr->num_frames_to_write) >+ png_error(png_ptr, "Not enough frames written"); >+#endif > > /* see if user wants us to write information chunks */ > if (info_ptr != NULL) >@@ -1544,4 +1552,39 @@ > params = params; > } > #endif >+ >+#if defined(PNG_WRITE_APNG_SUPPORTED) >+void PNGAPI >+png_write_frame_head(png_structp png_ptr, png_infop info_ptr, >+ png_bytepp row_pointers, 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_debug(1, "in png_write_frame_head\n"); >+ >+ /* there is a chance this has been set after png_write_info was called, >+ * so it would be set but not written. is there a way to be sure? */ >+ if (!(info_ptr->valid & PNG_INFO_acTL)) >+ png_error(png_ptr, "png_write_frame_head(): acTL not set"); >+ >+ png_write_reset(png_ptr); >+ >+ png_write_reinit(png_ptr, info_ptr, width, height); >+ >+ if ( !(png_ptr->num_frames_written == 0 && >+ (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN) ) ) >+ png_write_fcTL(png_ptr, width, height, x_offset, y_offset, >+ delay_num, delay_den, dispose_op, blend_op); >+} >+ >+void PNGAPI >+png_write_frame_tail(png_structp png_ptr, png_infop png_info) >+{ >+ png_debug(1, "in png_write_frame_tail\n"); >+ >+ png_ptr->num_frames_written++; >+} >+#endif /* PNG_WRITE_APNG_SUPPORTED */ >+ > #endif /* PNG_WRITE_SUPPORTED */ >diff -ruN libpng-1.2.31/pngconf.h.orig libpng-1.2.31/pngconf.h >--- libpng-1.2.31/pngconf.h.orig 2008-08-23 21:46:06.000000000 +0200 >+++ libpng-1.2.31/pngconf.h 2008-08-23 21:48:13.000000000 +0200 >@@ -925,6 +925,10 @@ > # define PNG_READ_zTXt_SUPPORTED > # define PNG_zTXt_SUPPORTED > #endif >+#ifndef PNG_NO_READ_APNG >+# define PNG_READ_APNG_SUPPORTED >+# define PNG_APNG_SUPPORTED >+#endif > #ifndef PNG_NO_READ_UNKNOWN_CHUNKS > # define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED > # ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED >@@ -1067,6 +1071,12 @@ > # define PNG_zTXt_SUPPORTED > # endif > #endif >+#ifndef PNG_NO_WRITE_APNG >+# define PNG_WRITE_APNG_SUPPORTED >+# ifndef PNG_APNG_SUPPORTED >+# define PNG_APNG_SUPPORTED >+# endif >+#endif > #ifndef PNG_NO_WRITE_UNKNOWN_CHUNKS > # define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED > # ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED >diff -ruN libpng-1.2.31/pngpread.c.orig libpng-1.2.31/pngpread.c >--- libpng-1.2.31/pngpread.c.orig 2008-08-23 21:46:24.000000000 +0200 >+++ libpng-1.2.31/pngpread.c 2008-08-23 21:48:13.000000000 +0200 >@@ -191,6 +191,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 */ > /* First we make sure we have enough data for the 4 byte chunk name > * and the 4 byte chunk length before proceeding with decoding the >@@ -215,7 +220,104 @@ > png_check_chunk_name(png_ptr, png_ptr->chunk_name); > png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; > } >- >+ >+#if defined(PNG_READ_APNG_SUPPORTED) >+ if (png_ptr->num_frames_read > 0 && >+ png_ptr->num_frames_read < info_ptr->num_frames) >+ { >+ if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) >+ { >+ /* discard trailing IDATs for the first frame */ >+ if (png_ptr->mode & PNG_HAVE_fcTL || png_ptr->num_frames_read > 1) >+ png_error(png_ptr, "out of place IDAT"); >+ >+ if (png_ptr->push_length + 4 > png_ptr->buffer_size) >+ { >+ png_push_save_buffer(png_ptr); >+ return; >+ } >+ png_push_crc_skip(png_ptr, png_ptr->push_length); >+ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; >+ return; >+ } >+ else if (!png_memcmp(png_ptr->chunk_name, png_fdAT, 4)) >+ { >+ if (png_ptr->buffer_size < 4) >+ { >+ png_push_save_buffer(png_ptr); >+ return; >+ } >+ png_ensure_sequence_number(png_ptr, 4); >+ >+ if (!(png_ptr->mode & PNG_HAVE_fcTL)) >+ { >+ /* discard trailing fdATs for frames other than the first */ >+ if (png_ptr->num_frames_read < 2) >+ png_error(png_ptr, "out of place fdAT"); >+ >+ if (png_ptr->push_length + 4 > png_ptr->buffer_size) >+ { >+ png_push_save_buffer(png_ptr); >+ return; >+ } >+ png_push_crc_skip(png_ptr, png_ptr->push_length); >+ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; >+ return; >+ } >+ else >+ { >+ /* frame data follows */ >+ png_ptr->idat_size = png_ptr->push_length - 4; >+ png_ptr->mode |= PNG_HAVE_IDAT; >+ png_ptr->process_mode = PNG_READ_IDAT_MODE; >+ >+ return; >+ } >+ } >+ else if(!png_memcmp(png_ptr->chunk_name, png_fcTL, 4)) >+ { >+ if (png_ptr->push_length + 4 > png_ptr->buffer_size) >+ { >+ png_push_save_buffer(png_ptr); >+ return; >+ } >+ >+ png_read_reset(png_ptr); >+ png_ptr->mode &= ~PNG_HAVE_fcTL; >+ >+ png_handle_fcTL(png_ptr, info_ptr, png_ptr->push_length); >+ >+ if (!(png_ptr->mode & PNG_HAVE_fcTL)) >+ png_error(png_ptr, "missing required fcTL chunk"); >+ >+ png_read_reinit(png_ptr, info_ptr); >+ png_progressive_read_reset(png_ptr); >+ >+ if (png_ptr->frame_info_fn != NULL) >+ (*(png_ptr->frame_info_fn))(png_ptr, png_ptr->num_frames_read); >+ >+ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; >+ >+ return; >+ } >+ else >+ { >+ if (png_ptr->push_length + 4 > png_ptr->buffer_size) >+ { >+ png_push_save_buffer(png_ptr); >+ return; >+ } >+ png_warning(png_ptr, "Skipped (ignored) a chunk " >+ "between APNG chunks"); >+ png_push_crc_skip(png_ptr, png_ptr->push_length); >+ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; >+ return; >+ } >+ >+ return; >+ } >+#endif /* PNG_READ_APNG_SUPPORTED */ >+ > if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) > if (png_ptr->mode & PNG_AFTER_IDAT) > png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; >@@ -297,6 +399,9 @@ > png_error(png_ptr, "Too many IDAT's found"); > } > >+#if defined(PNG_READ_APNG_SUPPORTED) >+ png_have_info(png_ptr, info_ptr); >+#endif > png_ptr->idat_size = png_ptr->push_length; > png_ptr->mode |= PNG_HAVE_IDAT; > png_ptr->process_mode = PNG_READ_IDAT_MODE; >@@ -492,6 +597,35 @@ > png_push_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length); > } > #endif >+#if defined(PNG_READ_APNG_SUPPORTED) >+ else if (!png_memcmp(png_ptr->chunk_name, png_acTL, 4)) >+ { >+ if (png_ptr->push_length + 4 > png_ptr->buffer_size) >+ { >+ png_push_save_buffer(png_ptr); >+ return; >+ } >+ png_handle_acTL(png_ptr, info_ptr, png_ptr->push_length); >+ } >+ else if (!png_memcmp(png_ptr->chunk_name, png_fcTL, 4)) >+ { >+ if (png_ptr->push_length + 4 > png_ptr->buffer_size) >+ { >+ png_push_save_buffer(png_ptr); >+ return; >+ } >+ png_handle_fcTL(png_ptr, info_ptr, png_ptr->push_length); >+ } >+ else if (!png_memcmp(png_ptr->chunk_name, png_fdAT, 4)) >+ { >+ if (png_ptr->push_length + 4 > png_ptr->buffer_size) >+ { >+ png_push_save_buffer(png_ptr); >+ return; >+ } >+ png_handle_fdAT(png_ptr, info_ptr, png_ptr->push_length); >+ } >+#endif /* PNG_READ_APNG_SUPPORTED */ > else > { > if (png_ptr->push_length + 4 > png_ptr->buffer_size) >@@ -662,13 +796,17 @@ > png_push_read_IDAT(png_structp png_ptr) > { > #ifdef PNG_USE_LOCAL_ARRAYS >- PNG_CONST PNG_IDAT; >+ PNG_IDAT; >+#if defined(PNG_READ_APNG_SUPPORTED) >+ PNG_fdAT; >+ PNG_IEND; >+#endif > #endif > if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) > { > png_byte chunk_length[4]; > >- if (png_ptr->buffer_size < 8) >+ if (png_ptr->buffer_size < 12) > { > png_push_save_buffer(png_ptr); > return; >@@ -680,15 +818,59 @@ > png_crc_read(png_ptr, png_ptr->chunk_name, 4); > png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; > >- if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) >+#if defined(PNG_READ_APNG_SUPPORTED) >+ if (png_memcmp(png_ptr->chunk_name, (png_bytep)png_fdAT, 4) >+ && png_ptr->num_frames_read > 0) >+ { >+ if (png_ptr->flags & PNG_FLAG_ZLIB_FINISHED) >+ { >+ png_ptr->process_mode = PNG_READ_CHUNK_MODE; >+ if (png_ptr->frame_end_fn != NULL) >+ (*(png_ptr->frame_end_fn))(png_ptr, png_ptr->num_frames_read); >+ png_ptr->num_frames_read++; >+ return; >+ } >+ else >+ { >+ if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) >+ png_error(png_ptr, "Not enough image data"); >+ if (png_ptr->push_length + 4 > png_ptr->buffer_size) >+ { >+ png_push_save_buffer(png_ptr); >+ return; >+ } >+ png_warning(png_ptr, "Skipping (ignoring) a chunk between " >+ "APNG chunks"); >+ png_crc_finish(png_ptr, png_ptr->push_length); >+ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; >+ return; >+ } >+ } >+ else >+#endif >+ if ( png_memcmp(png_ptr->chunk_name, png_IDAT, 4) >+ && (png_ptr->num_frames_read == 0) ) > { > png_ptr->process_mode = PNG_READ_CHUNK_MODE; > if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) > png_error(png_ptr, "Not enough compressed data"); >+#if defined(PNG_READ_APNG_SUPPORTED) >+ if (png_ptr->frame_end_fn != NULL) >+ (*(png_ptr->frame_end_fn))(png_ptr, png_ptr->num_frames_read); >+ png_ptr->num_frames_read++; >+#endif > return; > } > > png_ptr->idat_size = png_ptr->push_length; >+ >+#if defined(PNG_READ_APNG_SUPPORTED) >+ if(png_ptr->num_frames_read > 0) >+ { >+ png_ensure_sequence_number(png_ptr, 4); >+ png_ptr->idat_size -= 4; >+ } >+#endif > } > if (png_ptr->idat_size && png_ptr->save_buffer_size) > { >@@ -1585,6 +1767,17 @@ > png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer); > } > >+#if defined(PNG_READ_APNG_SUPPORTED) >+void PNGAPI >+png_set_progressive_frame_fn(png_structp png_ptr, >+ png_progressive_frame_ptr frame_info_fn, >+ png_progressive_frame_ptr frame_end_fn) >+{ >+ png_ptr->frame_info_fn = frame_info_fn; >+ png_ptr->frame_end_fn = frame_end_fn; >+} >+#endif >+ > png_voidp PNGAPI > png_get_progressive_ptr(png_structp png_ptr) > { >diff -ruN libpng-1.2.31/pngset.c.orig libpng-1.2.31/pngset.c >--- libpng-1.2.31/pngset.c.orig 2008-08-23 21:46:38.000000000 +0200 >+++ libpng-1.2.31/pngset.c 2008-08-23 21:48:13.000000000 +0200 >@@ -363,6 +363,11 @@ > info_ptr->rowbytes = (png_size_t)0; > else > info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width); >+ >+#if defined(PNG_APNG_SUPPORTED) >+ /* for non-animated png. this may be overritten from an acTL chunk later */ >+ info_ptr->num_frames = 1; >+#endif > } > > #if defined(PNG_oFFs_SUPPORTED) >@@ -1043,6 +1048,141 @@ > } > #endif /* PNG_sPLT_SUPPORTED */ > >+#if defined(PNG_APNG_SUPPORTED) >+png_uint_32 PNGAPI >+png_set_acTL(png_structp png_ptr, png_infop info_ptr, >+ png_uint_32 num_frames, png_uint_32 num_plays) >+{ >+ png_debug1(1, "in %s storage function\n", "acTL"); >+ >+ if (png_ptr == NULL || info_ptr == NULL) >+ { >+ png_warning(png_ptr, >+ "Call to png_set_acTL() with NULL png_ptr " >+ "or info_ptr ignored"); >+ return (0); >+ } >+ if (num_frames == 0) >+ { >+ png_warning(png_ptr, >+ "Ignoring attempt to set acTL with num_frames zero"); >+ return (0); >+ } >+ if (num_frames > PNG_UINT_31_MAX) >+ { >+ png_warning(png_ptr, >+ "Ignoring attempt to set acTL with num_frames > 2^31-1"); >+ return (0); >+ } >+ if (num_plays > PNG_UINT_31_MAX) >+ { >+ png_warning(png_ptr, >+ "Ignoring attempt to set acTL with num_plays " >+ "> 2^31-1"); >+ return (0); >+ } >+ >+ info_ptr->num_frames = num_frames; >+ info_ptr->num_plays = num_plays; >+ >+ info_ptr->valid |= PNG_INFO_acTL; >+ >+ return (1); >+} >+ >+/* delay_num and delay_den can hold any 16-bit values including zero */ >+png_uint_32 PNGAPI >+png_set_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 storage function\n", "fcTL"); >+ >+ if (png_ptr == NULL || info_ptr == NULL) >+ { >+ png_warning(png_ptr, >+ "Call to png_set_fcTL() with NULL png_ptr or info_ptr " >+ "ignored"); >+ return (0); >+ } >+ >+ png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset, >+ delay_num, delay_den, dispose_op, blend_op); >+ >+ info_ptr->next_frame_width = width; >+ info_ptr->next_frame_height = height; >+ info_ptr->next_frame_x_offset = x_offset; >+ info_ptr->next_frame_y_offset = y_offset; >+ info_ptr->next_frame_delay_num = delay_num; >+ info_ptr->next_frame_delay_den = delay_den; >+ info_ptr->next_frame_dispose_op = dispose_op; >+ info_ptr->next_frame_blend_op = blend_op; >+ >+ info_ptr->valid |= PNG_INFO_fcTL; >+ >+ return (1); >+} >+ >+void /* PRIVATE */ >+png_ensure_fcTL_is_valid(png_structp png_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) >+{ >+ if (width + x_offset > png_ptr->first_frame_width || >+ height + y_offset > png_ptr->first_frame_height) >+ png_error(png_ptr, "dimensions of a frame are greater than" >+ "the ones in IHDR"); >+ if (width > PNG_UINT_31_MAX) >+ png_error(png_ptr, "invalid width in fcTL (> 2^31-1)"); >+ if (height > PNG_UINT_31_MAX) >+ png_error(png_ptr, "invalid height in fcTL (> 2^31-1)"); >+ if (x_offset > PNG_UINT_31_MAX) >+ png_error(png_ptr, "invalid x_offset in fcTL (> 2^31-1)"); >+ if (y_offset > PNG_UINT_31_MAX) >+ png_error(png_ptr, "invalid y_offset in fcTL (> 2^31-1)"); >+ >+ if (dispose_op != PNG_DISPOSE_OP_NONE && >+ dispose_op != PNG_DISPOSE_OP_BACKGROUND && >+ dispose_op != PNG_DISPOSE_OP_PREVIOUS) >+ png_error(png_ptr, "invalid dispose_op in fcTL"); >+ >+ if (blend_op != PNG_BLEND_OP_SOURCE && >+ blend_op != PNG_BLEND_OP_OVER) >+ png_error(png_ptr, "invalid blend_op in fcTL"); >+ >+ if (blend_op == PNG_BLEND_OP_OVER) { >+ if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) >+ png_error(png_ptr, "PNG_BLEND_OP_OVER is not valid for " >+ "color type 'greyscale without alpha'"); >+ else if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) && >+ !(png_ptr->color_type & PNG_COLOR_MASK_ALPHA)) >+ png_error(png_ptr, "PNG_BLEND_OP_OVER is not valid for " >+ "color type 'truecolor without alpha'"); >+ } >+} >+ >+png_uint_32 PNGAPI >+png_set_first_frame_is_hidden(png_structp png_ptr, png_infop info_ptr, >+ png_byte is_hidden) >+{ >+ png_debug(1, "in png_first_frame_is_hidden()\n"); >+ >+ if (png_ptr == NULL) >+ return 0; >+ >+ if(is_hidden) >+ png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN; >+ else >+ png_ptr->apng_flags &= ~PNG_FIRST_FRAME_HIDDEN; >+ >+ return 1; >+} >+#endif /* PNG_APNG_SUPPORTED */ >+ > #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) > void PNGAPI > png_set_unknown_chunks(png_structp png_ptr, >diff -ruN libpng-1.2.31/pngrutil.c.orig libpng-1.2.31/pngrutil.c >--- libpng-1.2.31/pngrutil.c.orig 2008-08-23 21:46:55.000000000 +0200 >+++ libpng-1.2.31/pngrutil.c 2008-08-23 21:48:13.000000000 +0200 >@@ -414,6 +414,11 @@ > filter_type = buf[11]; > interlace_type = buf[12]; > >+#if defined(PNG_READ_APNG_SUPPORTED) >+ png_ptr->first_frame_width = width; >+ png_ptr->first_frame_height = height; >+#endif >+ > /* set internal variables */ > png_ptr->width = width; > png_ptr->height = height; >@@ -2220,6 +2225,168 @@ > } > #endif > >+#if defined(PNG_READ_APNG_SUPPORTED) >+void /* PRIVATE */ >+png_handle_acTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) >+{ >+ png_byte data[8]; >+ png_uint_32 num_frames; >+ png_uint_32 num_plays; >+ png_uint_32 didSet; >+ >+ png_debug(1, "in png_handle_acTL\n"); >+ >+ if (!(png_ptr->mode & PNG_HAVE_IHDR)) >+ { >+ png_error(png_ptr, "Missing IHDR before acTL"); >+ } >+ else if (png_ptr->mode & PNG_HAVE_IDAT) >+ { >+ png_warning(png_ptr, "Invalid acTL after IDAT skipped"); >+ png_crc_finish(png_ptr, length); >+ return; >+ } >+ else if (png_ptr->mode & PNG_HAVE_acTL) >+ { >+ png_warning(png_ptr, "Duplicate acTL skipped"); >+ png_crc_finish(png_ptr, length); >+ return; >+ } >+ else if (length != 8) >+ { >+ png_warning(png_ptr, "acTL with invalid length skipped"); >+ png_crc_finish(png_ptr, length); >+ return; >+ } >+ >+ png_crc_read(png_ptr, data, 8); >+ png_crc_finish(png_ptr, 0); >+ >+ num_frames = png_get_uint_31(png_ptr, data); >+ num_plays = png_get_uint_31(png_ptr, data + 4); >+ >+ /* the set function will do error checking on num_frames */ >+ didSet = png_set_acTL(png_ptr, info_ptr, num_frames, num_plays); >+ if(didSet) >+ png_ptr->mode |= PNG_HAVE_acTL; >+} >+ >+void /* PRIVATE */ >+png_handle_fcTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) >+{ >+ png_byte data[22]; >+ 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_debug(1, "in png_handle_fcTL\n"); >+ >+ if (!(png_ptr->mode & PNG_HAVE_IHDR)) >+ { >+ png_error(png_ptr, "Missing IHDR before fcTL"); >+ } >+ else if (png_ptr->mode & PNG_HAVE_IDAT) >+ { >+ /* for any frames other then the first this message may be misleading, >+ * but correct. PNG_HAVE_IDAT is unset before the frame head is read >+ * i can't think of a better message */ >+ png_warning(png_ptr, "Invalid fcTL after IDAT skipped"); >+ png_crc_finish(png_ptr, length); >+ return; >+ } >+ else if (png_ptr->mode & PNG_HAVE_fcTL) >+ { >+ png_warning(png_ptr, "Duplicate fcTL within one frame skipped"); >+ png_crc_finish(png_ptr, length); >+ return; >+ } >+ else if (length != 26) >+ { >+ png_warning(png_ptr, "fcTL with invalid length skipped"); >+ png_crc_finish(png_ptr, length); >+ return; >+ } >+ >+ png_ensure_sequence_number(png_ptr, length); >+ >+ png_crc_read(png_ptr, data, 22); >+ png_crc_finish(png_ptr, 0); >+ >+ width = png_get_uint_31(png_ptr, data); >+ height = png_get_uint_31(png_ptr, data + 4); >+ x_offset = png_get_uint_31(png_ptr, data + 8); >+ y_offset = png_get_uint_31(png_ptr, data + 12); >+ delay_num = png_get_uint_16(data + 16); >+ delay_den = png_get_uint_16(data + 18); >+ dispose_op = data[20]; >+ blend_op = data[21]; >+ >+ if (png_ptr->num_frames_read == 0 && (x_offset != 0 || y_offset != 0)) >+ png_error(png_ptr, "fcTL for the first frame must have zero offset"); >+ if (png_ptr->num_frames_read == 0 && >+ (width != info_ptr->width || height != info_ptr->height)) >+ png_error(png_ptr, "size in first frame's fcTL must match " >+ "the size in IHDR"); >+ >+ /* the set function will do more error checking */ >+ png_set_next_frame_fcTL(png_ptr, info_ptr, width, height, >+ x_offset, y_offset, delay_num, delay_den, >+ dispose_op, blend_op); >+ >+ png_read_reinit(png_ptr, info_ptr); >+ >+ png_ptr->mode |= PNG_HAVE_fcTL; >+} >+ >+void /* PRIVATE */ >+png_have_info(png_structp png_ptr, png_infop info_ptr) >+{ >+ if((info_ptr->valid & PNG_INFO_acTL) && !(info_ptr->valid & PNG_INFO_fcTL)) >+ { >+ png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN; >+ info_ptr->num_frames++; >+ } >+} >+ >+void /* PRIVATE */ >+png_handle_fdAT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) >+{ >+ png_ensure_sequence_number(png_ptr, length); >+ >+ /* This function is only called from png_read_end(), png_read_info(), >+ * and png_push_read_chunk() which means that: >+ * - the user doesn't want to read this frame >+ * - or this is an out-of-place fdAT >+ * in either case it is safe to ignore the chunk with a warning */ >+ png_warning(png_ptr, "ignoring fdAT chunk"); >+ png_crc_finish(png_ptr, length - 4); >+} >+ >+void /* PRIVATE */ >+png_ensure_sequence_number(png_structp png_ptr, png_uint_32 length) >+{ >+ png_byte data[4]; >+ png_uint_32 sequence_number; >+ >+ if (length < 4) >+ png_error(png_ptr, "invalid fcTL or fdAT chunk found"); >+ >+ png_crc_read(png_ptr, data, 4); >+ sequence_number = png_get_uint_31(png_ptr, data); >+ >+ if (sequence_number != png_ptr->next_seq_num) >+ png_error(png_ptr, "fcTL or fdAT chunk with out-of-order sequence " >+ "number found"); >+ >+ png_ptr->next_seq_num++; >+} >+#endif /* PNG_READ_APNG_SUPPORTED */ >+ > /* 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 > chunk name, CRC, or a critical chunk), the chunk is silently ignored >@@ -3195,8 +3362,10 @@ > 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; >+ if (png_ptr->big_row_buf == NULL) >+ png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes+64); >+ if (png_ptr->row_buf == NULL) >+ png_ptr->row_buf = png_ptr->big_row_buf+32; > png_ptr->old_big_row_buf_size = row_bytes+64; > } > >@@ -3226,4 +3395,82 @@ > > png_ptr->flags |= PNG_FLAG_ROW_INIT; > } >+ >+#if defined(PNG_READ_APNG_SUPPORTED) >+/* This function is to be called after the main IDAT set has been read and >+ * before a new IDAT is read. It resets some parts of png_ptr >+ * to make them usable by the read functions again */ >+void /* PRIVATE */ >+png_read_reset(png_structp png_ptr) >+{ >+ png_ptr->mode &= ~PNG_HAVE_IDAT; >+ png_ptr->mode &= ~PNG_AFTER_IDAT; >+ png_ptr->row_number = 0; >+ png_ptr->pass = 0; >+ png_ptr->flags &= ~PNG_FLAG_ROW_INIT; >+} >+ >+void /* PRIVATE */ >+png_read_reinit(png_structp png_ptr, png_infop info_ptr) >+{ >+ png_ptr->width = info_ptr->next_frame_width; >+ png_ptr->height = info_ptr->next_frame_height; >+ png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->width); >+} >+ >+/* same as png_read_reset() but for the progressive reader */ >+void /* PRIVATE */ >+png_progressive_read_reset(png_structp png_ptr) >+{ >+#ifdef PNG_USE_LOCAL_ARRAYS >+ /* start of interlace block */ >+ const int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; >+ >+ /* offset to next interlace block */ >+ const int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; >+ >+ /* start of interlace block in the y direction */ >+ const int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; >+ >+ /* offset to next interlace block in the y direction */ >+ const int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; >+#endif >+ png_uint_32 row_bytes; >+ >+ 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]; >+ >+ row_bytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->iwidth) + 1; >+ >+ png_ptr->irowbytes = (png_size_t)row_bytes; >+ if((png_uint_32)png_ptr->irowbytes != row_bytes) >+ png_error(png_ptr, "png_progressive_read_reset(): Rowbytes " >+ "overflow"); >+ } >+ else >+ { >+ png_ptr->num_rows = png_ptr->height; >+ png_ptr->iwidth = png_ptr->width; >+ png_ptr->irowbytes = png_ptr->rowbytes + 1; >+ } >+ >+ png_ptr->flags &= ~PNG_FLAG_ZLIB_FINISHED; >+ if (inflateReset(&(png_ptr->zstream)) != Z_OK) >+ png_error(png_ptr, "inflateReset failed"); >+ png_ptr->zstream.avail_in = 0; >+ png_ptr->zstream.next_in = 0; >+ png_ptr->zstream.next_out = png_ptr->row_buf; >+ png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes; >+} >+#endif /* PNG_READ_APNG_SUPPORTED */ > #endif /* PNG_READ_SUPPORTED */ >diff -ruN libpng-1.2.31/pngwutil.c.orig libpng-1.2.31/pngwutil.c >--- libpng-1.2.31/pngwutil.c.orig 2008-08-23 21:47:06.000000000 +0200 >+++ libpng-1.2.31/pngwutil.c 2008-08-23 21:48:13.000000000 +0200 >@@ -506,6 +506,11 @@ > /* write the chunk */ > png_write_chunk(png_ptr, (png_bytep)png_IHDR, buf, (png_size_t)13); > >+#if defined(PNG_WRITE_APNG_SUPPORTED) >+ png_ptr->first_frame_width = width; >+ png_ptr->first_frame_height = height; >+#endif >+ > /* initialize zlib with PNG info */ > png_ptr->zstream.zalloc = png_zalloc; > png_ptr->zstream.zfree = png_zfree; >@@ -628,6 +633,9 @@ > { > #ifdef PNG_USE_LOCAL_ARRAYS > PNG_IDAT; >+#if defined(PNG_WRITE_APNG_SUPPORTED) >+ PNG_fdAT; >+#endif > #endif > png_debug(1, "in png_write_IDAT\n"); > >@@ -670,7 +678,28 @@ > "Invalid zlib compression method or flags in IDAT"); > } > >- png_write_chunk(png_ptr, (png_bytep)png_IDAT, data, length); >+#if defined(PNG_WRITE_APNG_SUPPORTED) >+ if(png_ptr->num_frames_written == 0) >+#endif >+ png_write_chunk(png_ptr, (png_bytep)png_IDAT, data, length); >+#if defined(PNG_WRITE_APNG_SUPPORTED) >+ else >+ { >+ png_byte buf[4]; >+ >+ png_write_chunk_start(png_ptr, (png_bytep)png_fdAT, 4 + length); >+ >+ png_save_uint_32(buf, png_ptr->next_seq_num); >+ png_write_chunk_data(png_ptr, buf, 4); >+ >+ png_write_chunk_data(png_ptr, data, length); >+ >+ png_write_chunk_end(png_ptr); >+ >+ png_ptr->next_seq_num++; >+ } >+#endif >+ > png_ptr->mode |= PNG_HAVE_IDAT; > } > >@@ -1755,6 +1784,70 @@ > } > #endif > >+#if defined(PNG_WRITE_APNG_SUPPORTED) >+void /* PRIVATE */ >+png_write_acTL(png_structp png_ptr, >+ png_uint_32 num_frames, png_uint_32 num_plays) >+{ >+#ifdef PNG_USE_LOCAL_ARRAYS >+ PNG_acTL; >+#endif >+ png_byte data[16]; >+ >+ png_debug(1, "in png_write_acTL\n"); >+ >+ png_ptr->num_frames_to_write = num_frames; >+ >+ if (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN) >+ num_frames--; >+ >+ png_save_uint_32(data, num_frames); >+ png_save_uint_32(data + 4, num_plays); >+ >+ png_write_chunk(png_ptr, (png_bytep)png_acTL, data, (png_size_t)8); >+} >+ >+void /* PRIVATE */ >+png_write_fcTL(png_structp png_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) >+{ >+#ifdef PNG_USE_LOCAL_ARRAYS >+ PNG_fcTL; >+#endif >+ png_byte data[26]; >+ >+ png_debug(1, "in png_write_fcTL\n"); >+ >+ if (png_ptr->num_frames_written == 0 && (x_offset != 0 || y_offset != 0)) >+ png_error(png_ptr, "x and/or y offset for the first frame aren't 0\n"); >+ if (png_ptr->num_frames_written == 0 && >+ (width != png_ptr->first_frame_width || >+ height != png_ptr->first_frame_height)) >+ png_error(png_ptr, "width and/or height in the first frame's fcTL " >+ "don't match the ones in IHDR\n"); >+ >+ /* more error checking */ >+ png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset, >+ delay_num, delay_den, dispose_op, blend_op); >+ >+ png_save_uint_32(data, png_ptr->next_seq_num); >+ png_save_uint_32(data + 4, width); >+ png_save_uint_32(data + 8, height); >+ png_save_uint_32(data + 12, x_offset); >+ png_save_uint_32(data + 16, y_offset); >+ png_save_uint_16(data + 20, delay_num); >+ png_save_uint_16(data + 22, delay_den); >+ data[24] = dispose_op; >+ data[25] = blend_op; >+ >+ png_write_chunk(png_ptr, (png_bytep)png_fcTL, data, (png_size_t)26); >+ >+ png_ptr->next_seq_num++; >+} >+#endif /* PNG_WRITE_APNG_SUPPORTED */ >+ > /* initializes the row writing capability of libpng */ > void /* PRIVATE */ > png_write_start_row(png_structp png_ptr) >@@ -2824,4 +2917,39 @@ > } > #endif > } >+ >+#if defined(PNG_WRITE_APNG_SUPPORTED) >+void /* PRIVATE */ >+png_write_reset(png_structp png_ptr) >+{ >+ png_ptr->row_number = 0; >+ png_ptr->pass = 0; >+ png_ptr->mode &= ~PNG_HAVE_IDAT; >+} >+ >+void /* PRIVATE */ >+png_write_reinit(png_structp png_ptr, png_infop info_ptr, >+ png_uint_32 width, png_uint_32 height) >+{ >+ if (png_ptr->num_frames_written == 0 && >+ (width != png_ptr->first_frame_width || >+ height != png_ptr->first_frame_height)) >+ png_error(png_ptr, "width and/or height in the first frame's fcTL " >+ "don't match the ones in IHDR\n"); >+ if (width > png_ptr->first_frame_width || >+ height > png_ptr->first_frame_height) >+ png_error(png_ptr, "width and/or height for a frame greater than" >+ "the ones in IHDR"); >+ >+ png_set_IHDR(png_ptr, info_ptr, width, height, >+ info_ptr->bit_depth, info_ptr->color_type, >+ info_ptr->interlace_type, info_ptr->compression_type, >+ info_ptr->filter_type); >+ >+ png_ptr->width = width; >+ png_ptr->height = height; >+ png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width); >+ png_ptr->usr_width = png_ptr->width; >+} >+#endif > #endif /* PNG_WRITE_SUPPORTED */ >diff -ruN libpng-1.2.31/pngrtran.c.orig libpng-1.2.31/pngrtran.c >--- libpng-1.2.31/pngrtran.c.orig 2008-08-23 21:47:30.000000000 +0200 >+++ libpng-1.2.31/pngrtran.c 2008-08-23 21:48:13.000000000 +0200 >@@ -1288,7 +1288,7 @@ > * or png_read_update_info() after setting transforms that expand > * pixels. This check added to libpng-1.2.19 */ > #if (PNG_WARN_UNINITIALIZED_ROW==1) >- png_error(png_ptr, "Uninitialized row"); >+ png_warning(png_ptr, "Uninitialized row"); > #else > png_warning(png_ptr, "Uninitialized row"); > #endif
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 18152
: 3126