diff options
author | Waldemar Brodkorb <wbx@uclibc-ng.org> | 2016-10-01 21:41:34 +0200 |
---|---|---|
committer | Waldemar Brodkorb <wbx@uclibc-ng.org> | 2016-10-29 07:53:40 +0200 |
commit | a4071e7324833a7556d5125d7874bf340d5827a7 (patch) | |
tree | 88f6e894800e30a0807294f38cb6dfb7f34cbd8d /package/libpng | |
parent | 443fb793aab5aa894bcd5fde604bd143c1d88fcc (diff) |
libpng: fix APNG patch
Diffstat (limited to 'package/libpng')
-rw-r--r-- | package/libpng/patches/libpng-1.6.22-apng.patch | 960 |
1 files changed, 473 insertions, 487 deletions
diff --git a/package/libpng/patches/libpng-1.6.22-apng.patch b/package/libpng/patches/libpng-1.6.22-apng.patch index 66440b70f..24cc9aa9a 100644 --- a/package/libpng/patches/libpng-1.6.22-apng.patch +++ b/package/libpng/patches/libpng-1.6.22-apng.patch @@ -1,7 +1,6 @@ -Index: LICENSE -=================================================================== ---- LICENSE -+++ LICENSE +diff -Nur libpng-1.6.22.orig/LICENSE libpng-1.6.22/LICENSE +--- libpng-1.6.22.orig/LICENSE 2016-05-26 05:41:45.000000000 +0200 ++++ libpng-1.6.22/LICENSE 2016-10-01 00:22:37.029393861 +0200 @@ -8,6 +8,12 @@ If you modify libpng you may insert additional notices immediately following this sentence. @@ -15,115 +14,38 @@ Index: LICENSE This code is released under the libpng license. libpng versions 1.0.7, July 1, 2000 through 1.6.22, May 26, 2016 are -Index: pngread.c -=================================================================== ---- pngread.c -+++ pngread.c -@@ -158,6 +158,9 @@ - - else if (chunk_name == png_IDAT) - { -+#ifdef PNG_READ_APNG_SUPPORTED -+ png_have_info(png_ptr, info_ptr); -+#endif - png_ptr->idat_size = length; - break; - } -@@ -247,6 +250,17 @@ - png_handle_iTXt(png_ptr, info_ptr, length); +diff -Nur libpng-1.6.22.orig/png.c libpng-1.6.22/png.c +--- libpng-1.6.22.orig/png.c 2016-05-26 05:41:45.000000000 +0200 ++++ libpng-1.6.22/png.c 2016-10-01 00:22:37.029393861 +0200 +@@ -775,17 +775,21 @@ + #else + # ifdef __STDC__ + return PNG_STRING_NEWLINE \ +- "libpng version 1.6.22 - May 26, 2016" PNG_STRING_NEWLINE \ ++ "libpng version 1.6.22+apng - May 26, 2016" PNG_STRING_NEWLINE \ + "Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson" \ + PNG_STRING_NEWLINE \ + "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ + "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \ +- PNG_STRING_NEWLINE; ++ PNG_STRING_NEWLINE \ ++ "Portions Copyright (c) 2006-2007 Andrew Smith" PNG_STRING_NEWLINE \ ++ "Portions Copyright (c) 2008-2016 Max Stepin" PNG_STRING_NEWLINE ; + # else +- return "libpng version 1.6.22 - May 26, 2016\ ++ return "libpng version 1.6.22+apng - May 26, 2016\ + Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson\ + Copyright (c) 1996-1997 Andreas Dilger\ +- Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc."; ++ Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.\ ++ Portions Copyright (c) 2006-2007 Andrew Smith\ ++ Portions Copyright (c) 2008-2016 Max Stepin"; + # endif #endif - -+#ifdef PNG_READ_APNG_SUPPORTED -+ else if (chunk_name == png_acTL) -+ png_handle_acTL(png_ptr, info_ptr, length); -+ -+ else if (chunk_name == png_fcTL) -+ png_handle_fcTL(png_ptr, info_ptr, length); -+ -+ else if (chunk_name == png_fdAT) -+ png_handle_fdAT(png_ptr, info_ptr, length); -+#endif -+ - else - png_handle_unknown(png_ptr, info_ptr, length, - PNG_HANDLE_CHUNK_AS_DEFAULT); -@@ -254,6 +268,72 @@ } - #endif /* SEQUENTIAL_READ */ - -+#ifdef 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) == 0) -+ 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_read_reset(png_ptr); -+ png_ptr->flags &= ~PNG_FLAG_ROW_INIT; -+ png_ptr->mode &= ~PNG_HAVE_fcTL; -+ -+ have_chunk_after_DAT = 0; -+ for (;;) -+ { -+ png_uint_32 length = png_read_chunk_header(png_ptr); -+ -+ if (png_ptr->chunk_name == png_IDAT) -+ { -+ /* discard trailing IDATs for the first frame */ -+ if (have_chunk_after_DAT != 0 || 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_ptr->chunk_name == png_fcTL) -+ { -+ png_handle_fcTL(png_ptr, info_ptr, length); -+ have_chunk_after_DAT = 1; -+ } -+ -+ else if (png_ptr->chunk_name == png_fdAT) -+ { -+ png_ensure_sequence_number(png_ptr, length); -+ -+ /* discard trailing fdATs for frames other than the first */ -+ if (have_chunk_after_DAT == 0 && 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 /* READ_APNG */ -+ - /* Optional call to update the users info_ptr structure */ - void PNGAPI - png_read_update_info(png_structrp png_ptr, png_inforp info_ptr) -Index: pngget.c -=================================================================== ---- pngget.c -+++ pngget.c +diff -Nur libpng-1.6.22.orig/pngget.c libpng-1.6.22/pngget.c +--- libpng-1.6.22.orig/pngget.c 2016-05-26 05:41:45.000000000 +0200 ++++ libpng-1.6.22/pngget.c 2016-10-01 00:22:37.029393861 +0200 @@ -1216,4 +1216,166 @@ # endif #endif @@ -291,40 +213,9 @@ Index: pngget.c +} +#endif /* APNG */ #endif /* READ || WRITE */ -Index: png.c -=================================================================== ---- png.c -+++ png.c -@@ -775,17 +775,21 @@ - #else - # ifdef __STDC__ - return PNG_STRING_NEWLINE \ -- "libpng version 1.6.22 - May 26, 2016" PNG_STRING_NEWLINE \ -+ "libpng version 1.6.22+apng - May 26, 2016" PNG_STRING_NEWLINE \ - "Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson" \ - PNG_STRING_NEWLINE \ - "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ - "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \ -- PNG_STRING_NEWLINE; -+ PNG_STRING_NEWLINE \ -+ "Portions Copyright (c) 2006-2007 Andrew Smith" PNG_STRING_NEWLINE \ -+ "Portions Copyright (c) 2008-2016 Max Stepin" PNG_STRING_NEWLINE ; - # else -- return "libpng version 1.6.22 - May 26, 2016\ -+ return "libpng version 1.6.22+apng - May 26, 2016\ - Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson\ - Copyright (c) 1996-1997 Andreas Dilger\ -- Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc."; -+ Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.\ -+ Portions Copyright (c) 2006-2007 Andrew Smith\ -+ Portions Copyright (c) 2008-2016 Max Stepin"; - # endif - #endif - } -Index: png.h -=================================================================== ---- png.h -+++ png.h +diff -Nur libpng-1.6.22.orig/png.h libpng-1.6.22/png.h +--- libpng-1.6.22.orig/png.h 2016-05-26 05:41:45.000000000 +0200 ++++ libpng-1.6.22/png.h 2016-10-01 00:22:37.029393861 +0200 @@ -23,6 +23,12 @@ * If you modify libpng you may insert additional notices immediately following * this sentence. @@ -489,92 +380,9 @@ Index: png.h #endif #ifdef __cplusplus -Index: pngpriv.h -=================================================================== ---- pngpriv.h -+++ pngpriv.h -@@ -537,6 +537,10 @@ - #define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */ - /* 0x4000 (unused) */ - #define PNG_IS_READ_STRUCT 0x8000 /* Else is a write struct */ -+#ifdef PNG_APNG_SUPPORTED -+#define PNG_HAVE_acTL 0x10000 -+#define PNG_HAVE_fcTL 0x20000 -+#endif - - /* Flags for the transformations the PNG library does on the image data */ - #define PNG_BGR 0x0001 -@@ -754,6 +758,16 @@ - #define png_tRNS PNG_U32(116, 82, 78, 83) - #define png_zTXt PNG_U32(122, 84, 88, 116) - -+#ifdef PNG_APNG_SUPPORTED -+#define png_acTL PNG_U32( 97, 99, 84, 76) -+#define png_fcTL PNG_U32(102, 99, 84, 76) -+#define png_fdAT PNG_U32(102, 100, 65, 84) -+ -+/* For png_struct.apng_flags: */ -+#define PNG_FIRST_FRAME_HIDDEN 0x0001 -+#define PNG_APNG_APP 0x0002 -+#endif -+ - /* The following will work on (signed char*) strings, whereas the get_uint_32 - * macro will fail on top-bit-set values because of the sign extension. - */ -@@ -1441,6 +1455,49 @@ - - #endif /* PROGRESSIVE_READ */ - -+#ifdef PNG_APNG_SUPPORTED -+PNG_INTERNAL_FUNCTION(void,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),PNG_EMPTY); -+ -+#ifdef PNG_READ_APNG_SUPPORTED -+PNG_INTERNAL_FUNCTION(void,png_handle_acTL,(png_structp png_ptr, -+ png_infop info_ptr, png_uint_32 length),PNG_EMPTY); -+PNG_INTERNAL_FUNCTION(void,png_handle_fcTL,(png_structp png_ptr, -+ png_infop info_ptr, png_uint_32 length),PNG_EMPTY); -+PNG_INTERNAL_FUNCTION(void,png_handle_fdAT,(png_structp png_ptr, -+ png_infop info_ptr, png_uint_32 length),PNG_EMPTY); -+PNG_INTERNAL_FUNCTION(void,png_have_info,(png_structp png_ptr, -+ png_infop info_ptr),PNG_EMPTY); -+PNG_INTERNAL_FUNCTION(void,png_ensure_sequence_number,(png_structp png_ptr, -+ png_uint_32 length),PNG_EMPTY); -+PNG_INTERNAL_FUNCTION(void,png_read_reset,(png_structp png_ptr),PNG_EMPTY); -+PNG_INTERNAL_FUNCTION(void,png_read_reinit,(png_structp png_ptr, -+ png_infop info_ptr),PNG_EMPTY); -+#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -+PNG_INTERNAL_FUNCTION(void,png_progressive_read_reset,(png_structp png_ptr), -+ PNG_EMPTY); -+#endif /* PROGRESSIVE_READ */ -+#endif /* READ_APNG */ -+ -+#ifdef PNG_WRITE_APNG_SUPPORTED -+PNG_INTERNAL_FUNCTION(void,png_write_acTL,(png_structp png_ptr, -+ png_uint_32 num_frames, png_uint_32 num_plays),PNG_EMPTY); -+PNG_INTERNAL_FUNCTION(void,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),PNG_EMPTY); -+PNG_INTERNAL_FUNCTION(void,png_write_fdAT,(png_structp png_ptr, -+ png_const_bytep data, png_size_t length),PNG_EMPTY); -+PNG_INTERNAL_FUNCTION(void,png_write_reset,(png_structp png_ptr),PNG_EMPTY); -+PNG_INTERNAL_FUNCTION(void,png_write_reinit,(png_structp png_ptr, -+ png_infop info_ptr, png_uint_32 width, png_uint_32 height),PNG_EMPTY); -+#endif /* WRITE_APNG */ -+#endif /* APNG */ -+ - /* Added at libpng version 1.6.0 */ - #ifdef PNG_GAMMA_SUPPORTED - PNG_INTERNAL_FUNCTION(void,png_colorspace_set_gamma,(png_const_structrp png_ptr, -Index: pnginfo.h -=================================================================== ---- pnginfo.h -+++ pnginfo.h +diff -Nur libpng-1.6.22.orig/pnginfo.h libpng-1.6.22/pnginfo.h +--- libpng-1.6.22.orig/pnginfo.h 2016-05-26 05:41:45.000000000 +0200 ++++ libpng-1.6.22/pnginfo.h 2016-10-01 00:22:37.033394016 +0200 @@ -255,5 +255,18 @@ png_bytepp row_pointers; /* the image bits */ #endif @@ -594,112 +402,9 @@ Index: pnginfo.h + }; #endif /* PNGINFO_H */ -Index: pngstruct.h -=================================================================== ---- pngstruct.h -+++ pngstruct.h -@@ -403,6 +403,27 @@ - png_byte filter_type; - #endif - -+#ifdef 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; -+ -+#ifdef 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 -+ -+#ifdef PNG_WRITE_APNG_SUPPORTED -+ png_uint_32 num_frames_to_write; -+ png_uint_32 num_frames_written; -+#endif -+#endif /* APNG */ -+ - /* New members added in libpng-1.2.0 */ - - /* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */ -Index: pngwrite.c -=================================================================== ---- pngwrite.c -+++ pngwrite.c -@@ -128,6 +128,10 @@ - * the application continues writing the PNG. So check the 'invalid' - * flag here too. - */ -+#ifdef PNG_WRITE_APNG_SUPPORTED -+ if ((info_ptr->valid & PNG_INFO_acTL) != 0) -+ png_write_acTL(png_ptr, info_ptr->num_frames, info_ptr->num_plays); -+#endif - #ifdef PNG_GAMMA_SUPPORTED - # ifdef PNG_WRITE_gAMA_SUPPORTED - if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 && -@@ -360,6 +364,11 @@ - if ((png_ptr->mode & PNG_HAVE_IDAT) == 0) - png_error(png_ptr, "No IDATs written into file"); - -+#ifdef 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 -+ - #ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED - if (png_ptr->num_palette_max > png_ptr->num_palette) - png_benign_error(png_ptr, "Wrote palette index exceeding num_palette"); -@@ -2380,4 +2389,42 @@ - } - #endif /* SIMPLIFIED_WRITE_STDIO */ - #endif /* SIMPLIFIED_WRITE */ -+ -+#ifdef 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"); -+ -+ /* 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) == 0) -+ 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->apng_flags & PNG_FIRST_FRAME_HIDDEN) == 0 || -+ png_ptr->num_frames_written != 0) -+ png_write_fcTL(png_ptr, width, height, x_offset, y_offset, -+ delay_num, delay_den, dispose_op, blend_op); -+ -+ PNG_UNUSED(row_pointers) -+} -+ -+void PNGAPI -+png_write_frame_tail(png_structp png_ptr, png_infop info_ptr) -+{ -+ png_debug(1, "in png_write_frame_tail"); -+ -+ png_ptr->num_frames_written++; -+ -+ PNG_UNUSED(info_ptr) -+} -+#endif /* WRITE_APNG */ - #endif /* WRITE */ -Index: pngpread.c -=================================================================== ---- pngpread.c -+++ pngpread.c +diff -Nur libpng-1.6.22.orig/pngpread.c libpng-1.6.22/pngpread.c +--- libpng-1.6.22.orig/pngpread.c 2016-05-26 05:41:45.000000000 +0200 ++++ libpng-1.6.22/pngpread.c 2016-10-01 00:22:37.033394016 +0200 @@ -194,6 +194,89 @@ chunk_name = png_ptr->chunk_name; @@ -930,173 +635,194 @@ Index: pngpread.c png_voidp PNGAPI png_get_progressive_ptr(png_const_structrp png_ptr) { -Index: pngset.c -=================================================================== ---- pngset.c -+++ pngset.c -@@ -241,6 +241,11 @@ - info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth); - - info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width); -+ +diff -Nur libpng-1.6.22.orig/pngpriv.h libpng-1.6.22/pngpriv.h +--- libpng-1.6.22.orig/pngpriv.h 2016-05-26 05:41:45.000000000 +0200 ++++ libpng-1.6.22/pngpriv.h 2016-10-01 00:22:37.033394016 +0200 +@@ -537,6 +537,10 @@ + #define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */ + /* 0x4000 (unused) */ + #define PNG_IS_READ_STRUCT 0x8000 /* Else is a write struct */ +#ifdef PNG_APNG_SUPPORTED -+ /* for non-animated png. this may be overwritten from an acTL chunk later */ -+ info_ptr->num_frames = 1; ++#define PNG_HAVE_acTL 0x10000 ++#define PNG_HAVE_fcTL 0x20000 +#endif - } - #ifdef PNG_oFFs_SUPPORTED -@@ -1094,6 +1099,146 @@ - } - #endif /* sPLT */ + /* Flags for the transformations the PNG library does on the image data */ + #define PNG_BGR 0x0001 +@@ -754,6 +758,16 @@ + #define png_tRNS PNG_U32(116, 82, 78, 83) + #define png_zTXt PNG_U32(122, 84, 88, 116) +#ifdef 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", "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; ++#define png_acTL PNG_U32( 97, 99, 84, 76) ++#define png_fcTL PNG_U32(102, 99, 84, 76) ++#define png_fdAT PNG_U32(102, 100, 65, 84) + -+ info_ptr->valid |= PNG_INFO_acTL; ++/* For png_struct.apng_flags: */ ++#define PNG_FIRST_FRAME_HIDDEN 0x0001 ++#define PNG_APNG_APP 0x0002 ++#endif + -+ return (1); -+} + /* The following will work on (signed char*) strings, whereas the get_uint_32 + * macro will fail on top-bit-set values because of the sign extension. + */ +@@ -1441,6 +1455,49 @@ + + #endif /* PROGRESSIVE_READ */ + ++#ifdef PNG_APNG_SUPPORTED ++PNG_INTERNAL_FUNCTION(void,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),PNG_EMPTY); + -+/* 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", "fcTL"); ++#ifdef PNG_READ_APNG_SUPPORTED ++PNG_INTERNAL_FUNCTION(void,png_handle_acTL,(png_structp png_ptr, ++ png_infop info_ptr, png_uint_32 length),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_handle_fcTL,(png_structp png_ptr, ++ png_infop info_ptr, png_uint_32 length),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_handle_fdAT,(png_structp png_ptr, ++ png_infop info_ptr, png_uint_32 length),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_have_info,(png_structp png_ptr, ++ png_infop info_ptr),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_ensure_sequence_number,(png_structp png_ptr, ++ png_uint_32 length),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_read_reset,(png_structp png_ptr),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_read_reinit,(png_structp png_ptr, ++ png_infop info_ptr),PNG_EMPTY); ++#ifdef PNG_PROGRESSIVE_READ_SUPPORTED ++PNG_INTERNAL_FUNCTION(void,png_progressive_read_reset,(png_structp png_ptr), ++ PNG_EMPTY); ++#endif /* PROGRESSIVE_READ */ ++#endif /* READ_APNG */ + -+ 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); -+ } ++#ifdef PNG_WRITE_APNG_SUPPORTED ++PNG_INTERNAL_FUNCTION(void,png_write_acTL,(png_structp png_ptr, ++ png_uint_32 num_frames, png_uint_32 num_plays),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,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),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_write_fdAT,(png_structp png_ptr, ++ png_const_bytep data, png_size_t length),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_write_reset,(png_structp png_ptr),PNG_EMPTY); ++PNG_INTERNAL_FUNCTION(void,png_write_reinit,(png_structp png_ptr, ++ png_infop info_ptr, png_uint_32 width, png_uint_32 height),PNG_EMPTY); ++#endif /* WRITE_APNG */ ++#endif /* APNG */ + -+ png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset, -+ delay_num, delay_den, dispose_op, blend_op); + /* Added at libpng version 1.6.0 */ + #ifdef PNG_GAMMA_SUPPORTED + PNG_INTERNAL_FUNCTION(void,png_colorspace_set_gamma,(png_const_structrp png_ptr, +diff -Nur libpng-1.6.22.orig/pngread.c libpng-1.6.22/pngread.c +--- libpng-1.6.22.orig/pngread.c 2016-05-26 05:41:46.000000000 +0200 ++++ libpng-1.6.22/pngread.c 2016-10-01 00:22:37.029393861 +0200 +@@ -158,6 +158,9 @@ + + else if (chunk_name == png_IDAT) + { ++#ifdef PNG_READ_APNG_SUPPORTED ++ png_have_info(png_ptr, info_ptr); ++#endif + png_ptr->idat_size = length; + break; + } +@@ -247,6 +250,17 @@ + png_handle_iTXt(png_ptr, info_ptr, length); + #endif + ++#ifdef PNG_READ_APNG_SUPPORTED ++ else if (chunk_name == png_acTL) ++ png_handle_acTL(png_ptr, info_ptr, length); + -+ if (blend_op == PNG_BLEND_OP_OVER) -+ { -+ if ((png_ptr->color_type & PNG_COLOR_MASK_ALPHA) == 0 && -+ png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) == 0) -+ { -+ png_warning(png_ptr, "PNG_BLEND_OP_OVER is meaningless " -+ "and wasteful for opaque images, ignored"); -+ blend_op = PNG_BLEND_OP_SOURCE; -+ } -+ } ++ else if (chunk_name == png_fcTL) ++ png_handle_fcTL(png_ptr, info_ptr, length); + -+ 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; ++ else if (chunk_name == png_fdAT) ++ png_handle_fdAT(png_ptr, info_ptr, length); ++#endif + -+ info_ptr->valid |= PNG_INFO_fcTL; + else + png_handle_unknown(png_ptr, info_ptr, length, + PNG_HANDLE_CHUNK_AS_DEFAULT); +@@ -254,6 +268,72 @@ + } + #endif /* SEQUENTIAL_READ */ + ++#ifdef 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 */ + -+ return (1); -+} ++ png_debug(0, "Reading frame head"); + -+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 > 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 (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 ((png_ptr->mode & PNG_HAVE_acTL) == 0) ++ png_error(png_ptr, "attempt to png_read_frame_head() but " ++ "no acTL present"); + -+ 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"); ++ /* do nothing for the main IDAT */ ++ if (png_ptr->num_frames_read == 0) ++ return; + -+ if (blend_op != PNG_BLEND_OP_SOURCE && -+ blend_op != PNG_BLEND_OP_OVER) -+ png_error(png_ptr, "invalid blend_op in fcTL"); ++ png_read_reset(png_ptr); ++ png_ptr->flags &= ~PNG_FLAG_ROW_INIT; ++ png_ptr->mode &= ~PNG_HAVE_fcTL; + -+ PNG_UNUSED(delay_num) -+ PNG_UNUSED(delay_den) -+} ++ have_chunk_after_DAT = 0; ++ for (;;) ++ { ++ png_uint_32 length = png_read_chunk_header(png_ptr); + -+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()"); ++ if (png_ptr->chunk_name == png_IDAT) ++ { ++ /* discard trailing IDATs for the first frame */ ++ if (have_chunk_after_DAT != 0 || png_ptr->num_frames_read > 1) ++ png_error(png_ptr, "png_read_frame_head(): out of place IDAT"); ++ png_crc_finish(png_ptr, length); ++ } + -+ if (png_ptr == NULL) -+ return 0; ++ else if (png_ptr->chunk_name == png_fcTL) ++ { ++ png_handle_fcTL(png_ptr, info_ptr, length); ++ have_chunk_after_DAT = 1; ++ } + -+ if (is_hidden != 0) -+ png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN; -+ else -+ png_ptr->apng_flags &= ~PNG_FIRST_FRAME_HIDDEN; ++ else if (png_ptr->chunk_name == png_fdAT) ++ { ++ png_ensure_sequence_number(png_ptr, length); + -+ PNG_UNUSED(info_ptr) ++ /* discard trailing fdATs for frames other than the first */ ++ if (have_chunk_after_DAT == 0 && 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; + -+ return 1; ++ 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 /* APNG */ ++#endif /* READ_APNG */ + - #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED - static png_byte - check_location(png_const_structrp png_ptr, int location) -Index: pngrutil.c -=================================================================== ---- pngrutil.c -+++ pngrutil.c + /* Optional call to update the users info_ptr structure */ + void PNGAPI + png_read_update_info(png_structrp png_ptr, png_inforp info_ptr) +diff -Nur libpng-1.6.22.orig/pngrutil.c libpng-1.6.22/pngrutil.c +--- libpng-1.6.22.orig/pngrutil.c 2016-05-26 05:41:46.000000000 +0200 ++++ libpng-1.6.22/pngrutil.c 2016-10-01 00:22:37.033394016 +0200 @@ -855,6 +855,11 @@ filter_type = buf[11]; interlace_type = buf[12]; @@ -1428,10 +1154,271 @@ Index: pngrutil.c +#endif /* PROGRESSIVE_READ */ +#endif /* READ_APNG */ #endif /* READ */ -Index: pngwutil.c -=================================================================== ---- pngwutil.c -+++ pngwutil.c +diff -Nur libpng-1.6.22.orig/pngset.c libpng-1.6.22/pngset.c +--- libpng-1.6.22.orig/pngset.c 2016-05-26 05:41:46.000000000 +0200 ++++ libpng-1.6.22/pngset.c 2016-10-01 00:22:37.033394016 +0200 +@@ -241,6 +241,11 @@ + info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth); + + info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width); ++ ++#ifdef PNG_APNG_SUPPORTED ++ /* for non-animated png. this may be overwritten from an acTL chunk later */ ++ info_ptr->num_frames = 1; ++#endif + } + + #ifdef PNG_oFFs_SUPPORTED +@@ -1094,6 +1099,146 @@ + } + #endif /* sPLT */ + ++#ifdef 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", "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", "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); ++ ++ if (blend_op == PNG_BLEND_OP_OVER) ++ { ++ if ((png_ptr->color_type & PNG_COLOR_MASK_ALPHA) == 0 && ++ png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) == 0) ++ { ++ png_warning(png_ptr, "PNG_BLEND_OP_OVER is meaningless " ++ "and wasteful for opaque images, ignored"); ++ blend_op = PNG_BLEND_OP_SOURCE; ++ } ++ } ++ ++ 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 > 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 (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 (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"); ++ ++ PNG_UNUSED(delay_num) ++ PNG_UNUSED(delay_den) ++} ++ ++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()"); ++ ++ if (png_ptr == NULL) ++ return 0; ++ ++ if (is_hidden != 0) ++ png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN; ++ else ++ png_ptr->apng_flags &= ~PNG_FIRST_FRAME_HIDDEN; ++ ++ PNG_UNUSED(info_ptr) ++ ++ return 1; ++} ++#endif /* APNG */ ++ + #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED + static png_byte + check_location(png_const_structrp png_ptr, int location) +diff -Nur libpng-1.6.22.orig/pngstruct.h libpng-1.6.22/pngstruct.h +--- libpng-1.6.22.orig/pngstruct.h 2016-05-26 05:41:45.000000000 +0200 ++++ libpng-1.6.22/pngstruct.h 2016-10-01 00:22:37.033394016 +0200 +@@ -403,6 +403,27 @@ + png_byte filter_type; + #endif + ++#ifdef 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; ++ ++#ifdef 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 ++ ++#ifdef PNG_WRITE_APNG_SUPPORTED ++ png_uint_32 num_frames_to_write; ++ png_uint_32 num_frames_written; ++#endif ++#endif /* APNG */ ++ + /* New members added in libpng-1.2.0 */ + + /* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */ +diff -Nur libpng-1.6.22.orig/pngwrite.c libpng-1.6.22/pngwrite.c +--- libpng-1.6.22.orig/pngwrite.c 2016-05-26 05:41:46.000000000 +0200 ++++ libpng-1.6.22/pngwrite.c 2016-10-01 00:22:37.033394016 +0200 +@@ -128,6 +128,10 @@ + * the application continues writing the PNG. So check the 'invalid' + * flag here too. + */ ++#ifdef PNG_WRITE_APNG_SUPPORTED ++ if ((info_ptr->valid & PNG_INFO_acTL) != 0) ++ png_write_acTL(png_ptr, info_ptr->num_frames, info_ptr->num_plays); ++#endif + #ifdef PNG_GAMMA_SUPPORTED + # ifdef PNG_WRITE_gAMA_SUPPORTED + if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 && +@@ -360,6 +364,11 @@ + if ((png_ptr->mode & PNG_HAVE_IDAT) == 0) + png_error(png_ptr, "No IDATs written into file"); + ++#ifdef 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 ++ + #ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED + if (png_ptr->num_palette_max > png_ptr->num_palette) + png_benign_error(png_ptr, "Wrote palette index exceeding num_palette"); +@@ -2380,4 +2389,42 @@ + } + #endif /* SIMPLIFIED_WRITE_STDIO */ + #endif /* SIMPLIFIED_WRITE */ ++ ++#ifdef 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"); ++ ++ /* 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) == 0) ++ 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->apng_flags & PNG_FIRST_FRAME_HIDDEN) == 0 || ++ png_ptr->num_frames_written != 0) ++ png_write_fcTL(png_ptr, width, height, x_offset, y_offset, ++ delay_num, delay_den, dispose_op, blend_op); ++ ++ PNG_UNUSED(row_pointers) ++} ++ ++void PNGAPI ++png_write_frame_tail(png_structp png_ptr, png_infop info_ptr) ++{ ++ png_debug(1, "in png_write_frame_tail"); ++ ++ png_ptr->num_frames_written++; ++ ++ PNG_UNUSED(info_ptr) ++} ++#endif /* WRITE_APNG */ + #endif /* WRITE */ +diff -Nur libpng-1.6.22.orig/pngwutil.c libpng-1.6.22/pngwutil.c +--- libpng-1.6.22.orig/pngwutil.c 2016-05-26 05:41:46.000000000 +0200 ++++ libpng-1.6.22/pngwutil.c 2016-10-01 00:22:37.033394016 +0200 @@ -817,6 +817,11 @@ /* Write the chunk */ png_write_complete_chunk(png_ptr, png_IHDR, buf, (png_size_t)13); @@ -1599,10 +1586,9 @@ Index: pngwutil.c +} +#endif /* WRITE_APNG */ #endif /* WRITE */ -Index: scripts/symbols.def -=================================================================== ---- scripts/symbols.def -+++ scripts/symbols.def +diff -Nur libpng-1.6.22.orig/scripts/symbols.def libpng-1.6.22/scripts/symbols.def +--- libpng-1.6.22.orig/scripts/symbols.def 2016-05-26 05:41:46.000000000 +0200 ++++ libpng-1.6.22/scripts/symbols.def 2016-10-01 00:22:37.033394016 +0200 @@ -250,3 +250,23 @@ png_get_palette_max @243 png_set_option @244 |