summaryrefslogtreecommitdiff
path: root/libpng/libpng-apng.patch
blob: f346d9f7c28803b2e11117891244f6b3db5eaceb (plain)
    1 diff -Naru libpng-1.6.34.org/png.h libpng-1.6.34/png.h
    2 --- libpng-1.6.34.org/png.h	2017-09-29 18:55:30.653711999 +0900
    3 +++ libpng-1.6.34/png.h	2017-09-29 18:56:30.306850103 +0900
    4 @@ -361,6 +361,10 @@
    5  #   include "pnglibconf.h"
    6  #endif
    7  
    8 +#define PNG_APNG_SUPPORTED
    9 +#define PNG_READ_APNG_SUPPORTED
   10 +#define PNG_WRITE_APNG_SUPPORTED
   11 +
   12  #ifndef PNG_VERSION_INFO_ONLY
   13  /* Machine specific configuration. */
   14  #  include "pngconf.h"
   15 @@ -456,6 +460,17 @@
   16   * See pngconf.h for base types that vary by machine/system
   17   */
   18  
   19 +#ifdef PNG_APNG_SUPPORTED
   20 +/* dispose_op flags from inside fcTL */
   21 +#define PNG_DISPOSE_OP_NONE        0x00U
   22 +#define PNG_DISPOSE_OP_BACKGROUND  0x01U
   23 +#define PNG_DISPOSE_OP_PREVIOUS    0x02U
   24 +
   25 +/* blend_op flags from inside fcTL */
   26 +#define PNG_BLEND_OP_SOURCE        0x00U
   27 +#define PNG_BLEND_OP_OVER          0x01U
   28 +#endif /* PNG_APNG_SUPPORTED */
   29 +
   30  /* This triggers a compiler error in png.c, if png.c and png.h
   31   * do not agree upon the version number.
   32   */
   33 @@ -777,6 +792,10 @@
   34  #define PNG_INFO_sCAL 0x4000U  /* ESR, 1.0.6 */
   35  #define PNG_INFO_IDAT 0x8000U  /* ESR, 1.0.6 */
   36  #define PNG_INFO_eXIf 0x10000U /* GR-P, 1.6.31 */
   37 +#ifdef PNG_APNG_SUPPORTED
   38 +#define PNG_INFO_acTL 0x20000U
   39 +#define PNG_INFO_fcTL 0x40000U
   40 +#endif
   41  
   42  /* This is used for the transformation routines, as some of them
   43   * change these values for the row.  It also should enable using
   44 @@ -814,6 +833,10 @@
   45  #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
   46  typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop));
   47  typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop));
   48 +#ifdef PNG_APNG_SUPPORTED
   49 +typedef PNG_CALLBACK(void, *png_progressive_frame_ptr, (png_structp,
   50 +    png_uint_32));
   51 +#endif
   52  
   53  /* The following callback receives png_uint_32 row_number, int pass for the
   54   * png_bytep data of the row.  When transforming an interlaced image the
   55 @@ -3257,6 +3280,74 @@
   56  /*******************************************************************************
   57   *  END OF HARDWARE AND SOFTWARE OPTIONS
   58   ******************************************************************************/
   59 +#ifdef PNG_APNG_SUPPORTED
   60 +PNG_EXPORT(250, png_uint_32, png_get_acTL, (png_structp png_ptr,
   61 +   png_infop info_ptr, png_uint_32 *num_frames, png_uint_32 *num_plays));
   62 +
   63 +PNG_EXPORT(251, png_uint_32, png_set_acTL, (png_structp png_ptr,
   64 +   png_infop info_ptr, png_uint_32 num_frames, png_uint_32 num_plays));
   65 +
   66 +PNG_EXPORT(252, png_uint_32, png_get_num_frames, (png_structp png_ptr,
   67 +   png_infop info_ptr));
   68 +
   69 +PNG_EXPORT(253, png_uint_32, png_get_num_plays, (png_structp png_ptr,
   70 +   png_infop info_ptr));
   71 +
   72 +PNG_EXPORT(254, png_uint_32, png_get_next_frame_fcTL,
   73 +   (png_structp png_ptr, png_infop info_ptr, png_uint_32 *width,
   74 +   png_uint_32 *height, png_uint_32 *x_offset, png_uint_32 *y_offset,
   75 +   png_uint_16 *delay_num, png_uint_16 *delay_den, png_byte *dispose_op,
   76 +   png_byte *blend_op));
   77 +
   78 +PNG_EXPORT(255, png_uint_32, png_set_next_frame_fcTL,
   79 +   (png_structp png_ptr, png_infop info_ptr, png_uint_32 width,
   80 +   png_uint_32 height, png_uint_32 x_offset, png_uint_32 y_offset,
   81 +   png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
   82 +   png_byte blend_op));
   83 +
   84 +PNG_EXPORT(256, png_uint_32, png_get_next_frame_width,
   85 +   (png_structp png_ptr, png_infop info_ptr));
   86 +PNG_EXPORT(257, png_uint_32, png_get_next_frame_height,
   87 +   (png_structp png_ptr, png_infop info_ptr));
   88 +PNG_EXPORT(258, png_uint_32, png_get_next_frame_x_offset,
   89 +   (png_structp png_ptr, png_infop info_ptr));
   90 +PNG_EXPORT(259, png_uint_32, png_get_next_frame_y_offset,
   91 +   (png_structp png_ptr, png_infop info_ptr));
   92 +PNG_EXPORT(260, png_uint_16, png_get_next_frame_delay_num,
   93 +   (png_structp png_ptr, png_infop info_ptr));
   94 +PNG_EXPORT(261, png_uint_16, png_get_next_frame_delay_den,
   95 +   (png_structp png_ptr, png_infop info_ptr));
   96 +PNG_EXPORT(262, png_byte, png_get_next_frame_dispose_op,
   97 +   (png_structp png_ptr, png_infop info_ptr));
   98 +PNG_EXPORT(263, png_byte, png_get_next_frame_blend_op,
   99 +   (png_structp png_ptr, png_infop info_ptr));
  100 +PNG_EXPORT(264, png_byte, png_get_first_frame_is_hidden,
  101 +   (png_structp png_ptr, png_infop info_ptr));
  102 +PNG_EXPORT(265, png_uint_32, png_set_first_frame_is_hidden,
  103 +   (png_structp png_ptr, png_infop info_ptr, png_byte is_hidden));
  104 +
  105 +#ifdef PNG_READ_APNG_SUPPORTED
  106 +PNG_EXPORT(266, void, png_read_frame_head, (png_structp png_ptr,
  107 +   png_infop info_ptr));
  108 +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
  109 +PNG_EXPORT(267, void, png_set_progressive_frame_fn, (png_structp png_ptr,
  110 +   png_progressive_frame_ptr frame_info_fn,
  111 +   png_progressive_frame_ptr frame_end_fn));
  112 +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
  113 +#endif /* PNG_READ_APNG_SUPPORTED */
  114 +
  115 +#ifdef PNG_WRITE_APNG_SUPPORTED
  116 +PNG_EXPORT(268, void, png_write_frame_head, (png_structp png_ptr,
  117 +   png_infop info_ptr, png_bytepp row_pointers,
  118 +   png_uint_32 width, png_uint_32 height,
  119 +   png_uint_32 x_offset, png_uint_32 y_offset,
  120 +   png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
  121 +   png_byte blend_op));
  122 +
  123 +PNG_EXPORT(269, void, png_write_frame_tail, (png_structp png_ptr,
  124 +   png_infop info_ptr));
  125 +#endif /* PNG_WRITE_APNG_SUPPORTED */
  126 +#endif /* PNG_APNG_SUPPORTED */
  127  
  128  /* Maintainer: Put new public prototypes here ^, in libpng.3, in project
  129   * defs, and in scripts/symbols.def.
  130 @@ -3266,7 +3357,11 @@
  131   * one to use is one more than this.)
  132   */
  133  #ifdef PNG_EXPORT_LAST_ORDINAL
  134 +#ifdef PNG_APNG_SUPPORTED
  135 +  PNG_EXPORT_LAST_ORDINAL(269);
  136 +#else
  137    PNG_EXPORT_LAST_ORDINAL(249);
  138 +#endif /* PNG_APNG_SUPPORTED */
  139  #endif
  140  
  141  #ifdef __cplusplus
  142 diff -Naru libpng-1.6.34.org/pngget.c libpng-1.6.34/pngget.c
  143 --- libpng-1.6.34.org/pngget.c	2017-09-29 18:53:22.698691668 +0900
  144 +++ libpng-1.6.34/pngget.c	2017-09-29 18:56:30.286848380 +0900
  145 @@ -1245,4 +1245,166 @@
  146  #  endif
  147  #endif
  148  
  149 +#ifdef PNG_APNG_SUPPORTED
  150 +png_uint_32 PNGAPI
  151 +png_get_acTL(png_structp png_ptr, png_infop info_ptr,
  152 +             png_uint_32 *num_frames, png_uint_32 *num_plays)
  153 +{
  154 +    png_debug1(1, "in %s retrieval function", "acTL");
  155 +
  156 +    if (png_ptr != NULL && info_ptr != NULL &&
  157 +        (info_ptr->valid & PNG_INFO_acTL) &&
  158 +        num_frames != NULL && num_plays != NULL)
  159 +    {
  160 +        *num_frames = info_ptr->num_frames;
  161 +        *num_plays = info_ptr->num_plays;
  162 +        return (1);
  163 +    }
  164 +
  165 +    return (0);
  166 +}
  167 +
  168 +png_uint_32 PNGAPI
  169 +png_get_num_frames(png_structp png_ptr, png_infop info_ptr)
  170 +{
  171 +    png_debug(1, "in png_get_num_frames()");
  172 +
  173 +    if (png_ptr != NULL && info_ptr != NULL)
  174 +        return (info_ptr->num_frames);
  175 +    return (0);
  176 +}
  177 +
  178 +png_uint_32 PNGAPI
  179 +png_get_num_plays(png_structp png_ptr, png_infop info_ptr)
  180 +{
  181 +    png_debug(1, "in png_get_num_plays()");
  182 +
  183 +    if (png_ptr != NULL && info_ptr != NULL)
  184 +        return (info_ptr->num_plays);
  185 +    return (0);
  186 +}
  187 +
  188 +png_uint_32 PNGAPI
  189 +png_get_next_frame_fcTL(png_structp png_ptr, png_infop info_ptr,
  190 +             png_uint_32 *width, png_uint_32 *height,
  191 +             png_uint_32 *x_offset, png_uint_32 *y_offset,
  192 +             png_uint_16 *delay_num, png_uint_16 *delay_den,
  193 +             png_byte *dispose_op, png_byte *blend_op)
  194 +{
  195 +    png_debug1(1, "in %s retrieval function", "fcTL");
  196 +
  197 +    if (png_ptr != NULL && info_ptr != NULL &&
  198 +        (info_ptr->valid & PNG_INFO_fcTL) &&
  199 +        width != NULL && height != NULL &&
  200 +        x_offset != NULL && y_offset != NULL &&
  201 +        delay_num != NULL && delay_den != NULL &&
  202 +        dispose_op != NULL && blend_op != NULL)
  203 +    {
  204 +        *width = info_ptr->next_frame_width;
  205 +        *height = info_ptr->next_frame_height;
  206 +        *x_offset = info_ptr->next_frame_x_offset;
  207 +        *y_offset = info_ptr->next_frame_y_offset;
  208 +        *delay_num = info_ptr->next_frame_delay_num;
  209 +        *delay_den = info_ptr->next_frame_delay_den;
  210 +        *dispose_op = info_ptr->next_frame_dispose_op;
  211 +        *blend_op = info_ptr->next_frame_blend_op;
  212 +        return (1);
  213 +    }
  214 +
  215 +    return (0);
  216 +}
  217 +
  218 +png_uint_32 PNGAPI
  219 +png_get_next_frame_width(png_structp png_ptr, png_infop info_ptr)
  220 +{
  221 +    png_debug(1, "in png_get_next_frame_width()");
  222 +
  223 +    if (png_ptr != NULL && info_ptr != NULL)
  224 +        return (info_ptr->next_frame_width);
  225 +    return (0);
  226 +}
  227 +
  228 +png_uint_32 PNGAPI
  229 +png_get_next_frame_height(png_structp png_ptr, png_infop info_ptr)
  230 +{
  231 +    png_debug(1, "in png_get_next_frame_height()");
  232 +
  233 +    if (png_ptr != NULL && info_ptr != NULL)
  234 +        return (info_ptr->next_frame_height);
  235 +    return (0);
  236 +}
  237 +
  238 +png_uint_32 PNGAPI
  239 +png_get_next_frame_x_offset(png_structp png_ptr, png_infop info_ptr)
  240 +{
  241 +    png_debug(1, "in png_get_next_frame_x_offset()");
  242 +
  243 +    if (png_ptr != NULL && info_ptr != NULL)
  244 +        return (info_ptr->next_frame_x_offset);
  245 +    return (0);
  246 +}
  247 +
  248 +png_uint_32 PNGAPI
  249 +png_get_next_frame_y_offset(png_structp png_ptr, png_infop info_ptr)
  250 +{
  251 +    png_debug(1, "in png_get_next_frame_y_offset()");
  252 +
  253 +    if (png_ptr != NULL && info_ptr != NULL)
  254 +        return (info_ptr->next_frame_y_offset);
  255 +    return (0);
  256 +}
  257 +
  258 +png_uint_16 PNGAPI
  259 +png_get_next_frame_delay_num(png_structp png_ptr, png_infop info_ptr)
  260 +{
  261 +    png_debug(1, "in png_get_next_frame_delay_num()");
  262 +
  263 +    if (png_ptr != NULL && info_ptr != NULL)
  264 +        return (info_ptr->next_frame_delay_num);
  265 +    return (0);
  266 +}
  267 +
  268 +png_uint_16 PNGAPI
  269 +png_get_next_frame_delay_den(png_structp png_ptr, png_infop info_ptr)
  270 +{
  271 +    png_debug(1, "in png_get_next_frame_delay_den()");
  272 +
  273 +    if (png_ptr != NULL && info_ptr != NULL)
  274 +        return (info_ptr->next_frame_delay_den);
  275 +    return (0);
  276 +}
  277 +
  278 +png_byte PNGAPI
  279 +png_get_next_frame_dispose_op(png_structp png_ptr, png_infop info_ptr)
  280 +{
  281 +    png_debug(1, "in png_get_next_frame_dispose_op()");
  282 +
  283 +    if (png_ptr != NULL && info_ptr != NULL)
  284 +        return (info_ptr->next_frame_dispose_op);
  285 +    return (0);
  286 +}
  287 +
  288 +png_byte PNGAPI
  289 +png_get_next_frame_blend_op(png_structp png_ptr, png_infop info_ptr)
  290 +{
  291 +    png_debug(1, "in png_get_next_frame_blend_op()");
  292 +
  293 +    if (png_ptr != NULL && info_ptr != NULL)
  294 +        return (info_ptr->next_frame_blend_op);
  295 +    return (0);
  296 +}
  297 +
  298 +png_byte PNGAPI
  299 +png_get_first_frame_is_hidden(png_structp png_ptr, png_infop info_ptr)
  300 +{
  301 +    png_debug(1, "in png_first_frame_is_hidden()");
  302 +
  303 +    if (png_ptr != NULL)
  304 +       return (png_byte)(png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN);
  305 +
  306 +    PNG_UNUSED(info_ptr)
  307 +
  308 +    return 0;
  309 +}
  310 +#endif /* PNG_APNG_SUPPORTED */
  311  #endif /* READ || WRITE */
  312 diff -Naru libpng-1.6.34.org/pnginfo.h libpng-1.6.34/pnginfo.h
  313 --- libpng-1.6.34.org/pnginfo.h	2017-09-29 18:53:22.698691668 +0900
  314 +++ libpng-1.6.34/pnginfo.h	2017-09-29 18:56:30.286848380 +0900
  315 @@ -263,5 +263,18 @@
  316     png_bytepp row_pointers;        /* the image bits */
  317  #endif
  318  
  319 +#ifdef PNG_APNG_SUPPORTED
  320 +   png_uint_32 num_frames; /* including default image */
  321 +   png_uint_32 num_plays;
  322 +   png_uint_32 next_frame_width;
  323 +   png_uint_32 next_frame_height;
  324 +   png_uint_32 next_frame_x_offset;
  325 +   png_uint_32 next_frame_y_offset;
  326 +   png_uint_16 next_frame_delay_num;
  327 +   png_uint_16 next_frame_delay_den;
  328 +   png_byte next_frame_dispose_op;
  329 +   png_byte next_frame_blend_op;
  330 +#endif
  331 +
  332  };
  333  #endif /* PNGINFO_H */
  334 diff -Naru libpng-1.6.34.org/pngpread.c libpng-1.6.34/pngpread.c
  335 --- libpng-1.6.34.org/pngpread.c	2017-09-29 18:53:22.698691668 +0900
  336 +++ libpng-1.6.34/pngpread.c	2017-09-29 18:56:30.286848380 +0900
  337 @@ -195,6 +195,106 @@
  338  
  339     chunk_name = png_ptr->chunk_name;
  340  
  341 +#ifdef PNG_READ_APNG_SUPPORTED
  342 +   if (png_ptr->num_frames_read > 0 &&
  343 +       png_ptr->num_frames_read < info_ptr->num_frames)
  344 +   {
  345 +      if (chunk_name == png_IDAT)
  346 +      {
  347 +         /* Discard trailing IDATs for the first frame */
  348 +         if (png_ptr->mode & PNG_HAVE_fcTL || png_ptr->num_frames_read > 1)
  349 +            png_error(png_ptr, "out of place IDAT");
  350 +
  351 +         if (png_ptr->push_length + 4 > png_ptr->buffer_size)
  352 +         {
  353 +            png_push_save_buffer(png_ptr);
  354 +            return;
  355 +         }
  356 +
  357 +         png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
  358 +         return;
  359 +      }
  360 +      else if (chunk_name == png_fdAT)
  361 +      {
  362 +         if (png_ptr->buffer_size < 4)
  363 +         {
  364 +            png_push_save_buffer(png_ptr);
  365 +            return;
  366 +         }
  367 +
  368 +         png_ensure_sequence_number(png_ptr, 4);
  369 +
  370 +         if (!(png_ptr->mode & PNG_HAVE_fcTL))
  371 +         {
  372 +            /* Discard trailing fdATs for frames other than the first */
  373 +            if (png_ptr->num_frames_read < 2)
  374 +               png_error(png_ptr, "out of place fdAT");
  375 +
  376 +            if (png_ptr->push_length + 4 > png_ptr->buffer_size)
  377 +            {
  378 +               png_push_save_buffer(png_ptr);
  379 +               return;
  380 +            }
  381 +
  382 +            png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
  383 +            return;
  384 +         }
  385 +
  386 +         else
  387 +         {
  388 +            /* frame data follows */
  389 +            png_ptr->idat_size = png_ptr->push_length - 4;
  390 +            png_ptr->mode |= PNG_HAVE_IDAT;
  391 +            png_ptr->process_mode = PNG_READ_IDAT_MODE;
  392 +
  393 +            return;
  394 +         }
  395 +      }
  396 +
  397 +      else if (chunk_name == png_fcTL)
  398 +      {
  399 +         if (png_ptr->push_length + 4 > png_ptr->buffer_size)
  400 +         {
  401 +            png_push_save_buffer(png_ptr);
  402 +            return;
  403 +         }
  404 +
  405 +         png_read_reset(png_ptr);
  406 +         png_ptr->mode &= ~PNG_HAVE_fcTL;
  407 +
  408 +         png_handle_fcTL(png_ptr, info_ptr, png_ptr->push_length);
  409 +
  410 +         if (!(png_ptr->mode & PNG_HAVE_fcTL))
  411 +            png_error(png_ptr, "missing required fcTL chunk");
  412 +
  413 +         png_read_reinit(png_ptr, info_ptr);
  414 +         png_progressive_read_reset(png_ptr);
  415 +
  416 +         if (png_ptr->frame_info_fn != NULL)
  417 +            (*(png_ptr->frame_info_fn))(png_ptr, png_ptr->num_frames_read);
  418 +
  419 +         png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
  420 +
  421 +         return;
  422 +      }
  423 +
  424 +      else
  425 +      {
  426 +         if (png_ptr->push_length + 4 > png_ptr->buffer_size)
  427 +         {
  428 +            png_push_save_buffer(png_ptr);
  429 +            return;
  430 +         }
  431 +         png_warning(png_ptr, "Skipped (ignored) a chunk "
  432 +                              "between APNG chunks");
  433 +         png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
  434 +         return;
  435 +      }
  436 +
  437 +      return;
  438 +   }
  439 +#endif /* PNG_READ_APNG_SUPPORTED */
  440 +
  441     if (chunk_name == png_IDAT)
  442     {
  443        if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
  444 @@ -261,6 +361,9 @@
  445  
  446     else if (chunk_name == png_IDAT)
  447     {
  448 +#ifdef PNG_READ_APNG_SUPPORTED
  449 +      png_have_info(png_ptr, info_ptr);
  450 +#endif
  451        png_ptr->idat_size = png_ptr->push_length;
  452        png_ptr->process_mode = PNG_READ_IDAT_MODE;
  453        png_push_have_info(png_ptr, info_ptr);
  454 @@ -406,6 +509,30 @@
  455        png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
  456     }
  457  #endif
  458 +#ifdef PNG_READ_APNG_SUPPORTED
  459 +   else if (chunk_name == png_acTL)
  460 +   {
  461 +      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
  462 +      {
  463 +         png_push_save_buffer(png_ptr);
  464 +         return;
  465 +      }
  466 +
  467 +      png_handle_acTL(png_ptr, info_ptr, png_ptr->push_length);
  468 +   }
  469 +
  470 +   else if (chunk_name == png_fcTL)
  471 +   {
  472 +      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
  473 +      {
  474 +         png_push_save_buffer(png_ptr);
  475 +         return;
  476 +      }
  477 +
  478 +      png_handle_fcTL(png_ptr, info_ptr, png_ptr->push_length);
  479 +   }
  480 +
  481 +#endif /* PNG_READ_APNG_SUPPORTED */
  482  
  483     else
  484     {
  485 @@ -539,7 +666,11 @@
  486        png_byte chunk_tag[4];
  487  
  488        /* TODO: this code can be commoned up with the same code in push_read */
  489 +#ifdef PNG_READ_APNG_SUPPORTED
  490 +      PNG_PUSH_SAVE_BUFFER_IF_LT(12)
  491 +#else
  492        PNG_PUSH_SAVE_BUFFER_IF_LT(8)
  493 +#endif
  494        png_push_fill_buffer(png_ptr, chunk_length, 4);
  495        png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
  496        png_reset_crc(png_ptr);
  497 @@ -547,17 +678,64 @@
  498        png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
  499        png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
  500  
  501 +#ifdef PNG_READ_APNG_SUPPORTED
  502 +      if (png_ptr->chunk_name != png_fdAT && png_ptr->num_frames_read > 0)
  503 +      {
  504 +          if (png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED)
  505 +          {
  506 +              png_ptr->process_mode = PNG_READ_CHUNK_MODE;
  507 +              if (png_ptr->frame_end_fn != NULL)
  508 +                 (*(png_ptr->frame_end_fn))(png_ptr, png_ptr->num_frames_read);
  509 +              png_ptr->num_frames_read++;
  510 +              return;
  511 +          }
  512 +          else
  513 +          {
  514 +              if (png_ptr->chunk_name == png_IEND)
  515 +                  png_error(png_ptr, "Not enough image data");
  516 +              if (png_ptr->push_length + 4 > png_ptr->buffer_size)
  517 +              {
  518 +                 png_push_save_buffer(png_ptr);
  519 +                 return;
  520 +              }
  521 +              png_warning(png_ptr, "Skipping (ignoring) a chunk between "
  522 +                                   "APNG chunks");
  523 +              png_crc_finish(png_ptr, png_ptr->push_length);
  524 +              png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
  525 +              return;
  526 +          }
  527 +      }
  528 +      else
  529 +#endif
  530 +#ifdef PNG_READ_APNG_SUPPORTED
  531 +      if (png_ptr->chunk_name != png_IDAT && png_ptr->num_frames_read == 0)
  532 +#else
  533        if (png_ptr->chunk_name != png_IDAT)
  534 +#endif
  535        {
  536           png_ptr->process_mode = PNG_READ_CHUNK_MODE;
  537  
  538           if ((png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0)
  539              png_error(png_ptr, "Not enough compressed data");
  540  
  541 +#ifdef PNG_READ_APNG_SUPPORTED
  542 +         if (png_ptr->frame_end_fn != NULL)
  543 +            (*(png_ptr->frame_end_fn))(png_ptr, png_ptr->num_frames_read);
  544 +         png_ptr->num_frames_read++;
  545 +#endif
  546 +
  547           return;
  548        }
  549  
  550        png_ptr->idat_size = png_ptr->push_length;
  551 +
  552 +#ifdef PNG_READ_APNG_SUPPORTED
  553 +      if (png_ptr->num_frames_read > 0)
  554 +      {
  555 +         png_ensure_sequence_number(png_ptr, 4);
  556 +         png_ptr->idat_size -= 4;
  557 +      }
  558 +#endif
  559     }
  560  
  561     if (png_ptr->idat_size != 0 && png_ptr->save_buffer_size != 0)
  562 @@ -631,6 +809,15 @@
  563     if (!(buffer_length > 0) || buffer == NULL)
  564        png_error(png_ptr, "No IDAT data (internal error)");
  565  
  566 +#ifdef PNG_READ_APNG_SUPPORTED
  567 +   /* If the app is not APNG-aware, decode only the first frame */
  568 +   if (!(png_ptr->apng_flags & PNG_APNG_APP) && png_ptr->num_frames_read > 0)
  569 +   {
  570 +     png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
  571 +     return;
  572 +   }
  573 +#endif
  574 +
  575     /* This routine must process all the data it has been given
  576      * before returning, calling the row callback as required to
  577      * handle the uncompressed results.
  578 @@ -1085,6 +1272,18 @@
  579     png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
  580  }
  581  
  582 +#ifdef PNG_READ_APNG_SUPPORTED
  583 +void PNGAPI
  584 +png_set_progressive_frame_fn(png_structp png_ptr,
  585 +   png_progressive_frame_ptr frame_info_fn,
  586 +   png_progressive_frame_ptr frame_end_fn)
  587 +{
  588 +   png_ptr->frame_info_fn = frame_info_fn;
  589 +   png_ptr->frame_end_fn = frame_end_fn;
  590 +   png_ptr->apng_flags |= PNG_APNG_APP;
  591 +}
  592 +#endif
  593 +
  594  png_voidp PNGAPI
  595  png_get_progressive_ptr(png_const_structrp png_ptr)
  596  {
  597 diff -Naru libpng-1.6.34.org/pngpriv.h libpng-1.6.34/pngpriv.h
  598 --- libpng-1.6.34.org/pngpriv.h	2017-09-29 18:53:22.699691754 +0900
  599 +++ libpng-1.6.34/pngpriv.h	2017-09-29 18:56:30.286848380 +0900
  600 @@ -628,6 +628,10 @@
  601  #define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000U /* Have another chunk after IDAT */
  602                     /*             0x4000U (unused) */
  603  #define PNG_IS_READ_STRUCT        0x8000U /* Else is a write struct */
  604 +#ifdef PNG_APNG_SUPPORTED
  605 +#define PNG_HAVE_acTL            0x10000U
  606 +#define PNG_HAVE_fcTL            0x20000U
  607 +#endif
  608  
  609  /* Flags for the transformations the PNG library does on the image data */
  610  #define PNG_BGR                 0x0001U
  611 @@ -864,6 +868,16 @@
  612  #define png_tRNS PNG_U32(116,  82,  78,  83)
  613  #define png_zTXt PNG_U32(122,  84,  88, 116)
  614  
  615 +#ifdef PNG_APNG_SUPPORTED
  616 +#define png_acTL PNG_U32( 97,  99,  84,  76)
  617 +#define png_fcTL PNG_U32(102,  99,  84,  76)
  618 +#define png_fdAT PNG_U32(102, 100,  65,  84)
  619 +
  620 +/* For png_struct.apng_flags: */
  621 +#define PNG_FIRST_FRAME_HIDDEN       0x0001U
  622 +#define PNG_APNG_APP                 0x0002U
  623 +#endif
  624 +
  625  /* The following will work on (signed char*) strings, whereas the get_uint_32
  626   * macro will fail on top-bit-set values because of the sign extension.
  627   */
  628 @@ -1635,6 +1649,47 @@
  629      */
  630  #endif
  631  
  632 +#ifdef PNG_APNG_SUPPORTED
  633 +PNG_INTERNAL_FUNCTION(void,png_ensure_fcTL_is_valid,(png_structp png_ptr,
  634 +   png_uint_32 width, png_uint_32 height,
  635 +   png_uint_32 x_offset, png_uint_32 y_offset,
  636 +   png_uint_16 delay_num, png_uint_16 delay_den,
  637 +   png_byte dispose_op, png_byte blend_op), PNG_EMPTY);
  638 +
  639 +#ifdef PNG_READ_APNG_SUPPORTED
  640 +PNG_INTERNAL_FUNCTION(void,png_handle_acTL,(png_structp png_ptr, png_infop info_ptr,
  641 +   png_uint_32 length),PNG_EMPTY);
  642 +PNG_INTERNAL_FUNCTION(void,png_handle_fcTL,(png_structp png_ptr, png_infop info_ptr,
  643 +   png_uint_32 length),PNG_EMPTY);
  644 +PNG_INTERNAL_FUNCTION(void,png_handle_fdAT,(png_structp png_ptr, png_infop info_ptr,
  645 +   png_uint_32 length),PNG_EMPTY);
  646 +PNG_INTERNAL_FUNCTION(void,png_have_info,(png_structp png_ptr, png_infop info_ptr),PNG_EMPTY);
  647 +PNG_INTERNAL_FUNCTION(void,png_ensure_sequence_number,(png_structp png_ptr,
  648 +   png_uint_32 length),PNG_EMPTY);
  649 +PNG_INTERNAL_FUNCTION(void,png_read_reset,(png_structp png_ptr),PNG_EMPTY);
  650 +PNG_INTERNAL_FUNCTION(void,png_read_reinit,(png_structp png_ptr,
  651 +   png_infop info_ptr),PNG_EMPTY);
  652 +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
  653 +PNG_INTERNAL_FUNCTION(void,png_progressive_read_reset,(png_structp png_ptr),PNG_EMPTY);
  654 +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
  655 +#endif /* PNG_READ_APNG_SUPPORTED */
  656 +
  657 +#ifdef PNG_WRITE_APNG_SUPPORTED
  658 +PNG_INTERNAL_FUNCTION(void,png_write_acTL,(png_structp png_ptr,
  659 +   png_uint_32 num_frames, png_uint_32 num_plays),PNG_EMPTY);
  660 +PNG_INTERNAL_FUNCTION(void,png_write_fcTL,(png_structp png_ptr,
  661 +   png_uint_32 width, png_uint_32 height,
  662 +   png_uint_32 x_offset, png_uint_32 y_offset,
  663 +   png_uint_16 delay_num, png_uint_16 delay_den,
  664 +   png_byte dispose_op, png_byte blend_op),PNG_EMPTY);
  665 +PNG_INTERNAL_FUNCTION(void,png_write_fdAT,(png_structp png_ptr,
  666 +   png_const_bytep data, png_size_t length),PNG_EMPTY);
  667 +PNG_INTERNAL_FUNCTION(void,png_write_reset,(png_structp png_ptr),PNG_EMPTY);
  668 +PNG_INTERNAL_FUNCTION(void,png_write_reinit,(png_structp png_ptr,
  669 +   png_infop info_ptr, png_uint_32 width, png_uint_32 height),PNG_EMPTY);
  670 +#endif /* PNG_WRITE_APNG_SUPPORTED */
  671 +#endif /* PNG_APNG_SUPPORTED */
  672 +
  673  /* Added at libpng version 1.4.0 */
  674  #ifdef PNG_COLORSPACE_SUPPORTED
  675  /* These internal functions are for maintaining the colorspace structure within
  676 diff -Naru libpng-1.6.34.org/pngread.c libpng-1.6.34/pngread.c
  677 --- libpng-1.6.34.org/pngread.c	2017-09-29 18:53:22.699691754 +0900
  678 +++ libpng-1.6.34/pngread.c	2017-09-29 18:56:30.286848380 +0900
  679 @@ -161,6 +161,9 @@
  680  
  681        else if (chunk_name == png_IDAT)
  682        {
  683 +#ifdef PNG_READ_APNG_SUPPORTED
  684 +         png_have_info(png_ptr, info_ptr);
  685 +#endif
  686           png_ptr->idat_size = length;
  687           break;
  688        }
  689 @@ -255,6 +258,17 @@
  690           png_handle_iTXt(png_ptr, info_ptr, length);
  691  #endif
  692  
  693 +#ifdef PNG_READ_APNG_SUPPORTED
  694 +      else if (chunk_name == png_acTL)
  695 +         png_handle_acTL(png_ptr, info_ptr, length);
  696 +
  697 +      else if (chunk_name == png_fcTL)
  698 +         png_handle_fcTL(png_ptr, info_ptr, length);
  699 +
  700 +      else if (chunk_name == png_fdAT)
  701 +         png_handle_fdAT(png_ptr, info_ptr, length);
  702 +#endif
  703 +
  704        else
  705           png_handle_unknown(png_ptr, info_ptr, length,
  706               PNG_HANDLE_CHUNK_AS_DEFAULT);
  707 @@ -262,6 +276,72 @@
  708  }
  709  #endif /* SEQUENTIAL_READ */
  710  
  711 +#ifdef PNG_READ_APNG_SUPPORTED
  712 +void PNGAPI
  713 +png_read_frame_head(png_structp png_ptr, png_infop info_ptr)
  714 +{
  715 +    png_byte have_chunk_after_DAT; /* after IDAT or after fdAT */
  716 +
  717 +    png_debug(0, "Reading frame head");
  718 +
  719 +    if (!(png_ptr->mode & PNG_HAVE_acTL))
  720 +        png_error(png_ptr, "attempt to png_read_frame_head() but "
  721 +                           "no acTL present");
  722 +
  723 +    /* do nothing for the main IDAT */
  724 +    if (png_ptr->num_frames_read == 0)
  725 +        return;
  726 +
  727 +    png_read_reset(png_ptr);
  728 +    png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
  729 +    png_ptr->mode &= ~PNG_HAVE_fcTL;
  730 +
  731 +    have_chunk_after_DAT = 0;
  732 +    for (;;)
  733 +    {
  734 +        png_uint_32 length = png_read_chunk_header(png_ptr);
  735 +
  736 +        if (png_ptr->chunk_name == png_IDAT)
  737 +        {
  738 +            /* discard trailing IDATs for the first frame */
  739 +            if (have_chunk_after_DAT || png_ptr->num_frames_read > 1)
  740 +                png_error(png_ptr, "png_read_frame_head(): out of place IDAT");
  741 +            png_crc_finish(png_ptr, length);
  742 +        }
  743 +
  744 +        else if (png_ptr->chunk_name == png_fcTL)
  745 +        {
  746 +            png_handle_fcTL(png_ptr, info_ptr, length);
  747 +            have_chunk_after_DAT = 1;
  748 +        }
  749 +
  750 +        else if (png_ptr->chunk_name == png_fdAT)
  751 +        {
  752 +            png_ensure_sequence_number(png_ptr, length);
  753 +
  754 +            /* discard trailing fdATs for frames other than the first */
  755 +            if (!have_chunk_after_DAT && png_ptr->num_frames_read > 1)
  756 +                png_crc_finish(png_ptr, length - 4);
  757 +            else if(png_ptr->mode & PNG_HAVE_fcTL)
  758 +            {
  759 +                png_ptr->idat_size = length - 4;
  760 +                png_ptr->mode |= PNG_HAVE_IDAT;
  761 +
  762 +                break;
  763 +            }
  764 +            else
  765 +                png_error(png_ptr, "png_read_frame_head(): out of place fdAT");
  766 +        }
  767 +        else
  768 +        {
  769 +            png_warning(png_ptr, "Skipped (ignored) a chunk "
  770 +                                 "between APNG chunks");
  771 +            png_crc_finish(png_ptr, length);
  772 +        }
  773 +    }
  774 +}
  775 +#endif /* PNG_READ_APNG_SUPPORTED */
  776 +
  777  /* Optional call to update the users info_ptr structure */
  778  void PNGAPI
  779  png_read_update_info(png_structrp png_ptr, png_inforp info_ptr)
  780 diff -Naru libpng-1.6.34.org/pngrutil.c libpng-1.6.34/pngrutil.c
  781 --- libpng-1.6.34.org/pngrutil.c	2017-09-29 18:53:22.701691926 +0900
  782 +++ libpng-1.6.34/pngrutil.c	2017-09-29 18:56:30.287848466 +0900
  783 @@ -865,6 +865,11 @@
  784     filter_type = buf[11];
  785     interlace_type = buf[12];
  786  
  787 +#ifdef PNG_READ_APNG_SUPPORTED
  788 +   png_ptr->first_frame_width = width;
  789 +   png_ptr->first_frame_height = height;
  790 +#endif
  791 +
  792     /* Set internal variables */
  793     png_ptr->width = width;
  794     png_ptr->height = height;
  795 @@ -2840,6 +2845,179 @@
  796  }
  797  #endif
  798  
  799 +#ifdef PNG_READ_APNG_SUPPORTED
  800 +void /* PRIVATE */
  801 +png_handle_acTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
  802 +{
  803 +    png_byte data[8];
  804 +    png_uint_32 num_frames;
  805 +    png_uint_32 num_plays;
  806 +    png_uint_32 didSet;
  807 +
  808 +    png_debug(1, "in png_handle_acTL");
  809 +
  810 +    if (!(png_ptr->mode & PNG_HAVE_IHDR))
  811 +    {
  812 +        png_error(png_ptr, "Missing IHDR before acTL");
  813 +    }
  814 +    else if (png_ptr->mode & PNG_HAVE_IDAT)
  815 +    {
  816 +        png_warning(png_ptr, "Invalid acTL after IDAT skipped");
  817 +        png_crc_finish(png_ptr, length);
  818 +        return;
  819 +    }
  820 +    else if (png_ptr->mode & PNG_HAVE_acTL)
  821 +    {
  822 +        png_warning(png_ptr, "Duplicate acTL skipped");
  823 +        png_crc_finish(png_ptr, length);
  824 +        return;
  825 +    }
  826 +    else if (length != 8)
  827 +    {
  828 +        png_warning(png_ptr, "acTL with invalid length skipped");
  829 +        png_crc_finish(png_ptr, length);
  830 +        return;
  831 +    }
  832 +
  833 +    png_crc_read(png_ptr, data, 8);
  834 +    png_crc_finish(png_ptr, 0);
  835 +
  836 +    num_frames = png_get_uint_31(png_ptr, data);
  837 +    num_plays = png_get_uint_31(png_ptr, data + 4);
  838 +
  839 +    /* the set function will do error checking on num_frames */
  840 +    didSet = png_set_acTL(png_ptr, info_ptr, num_frames, num_plays);
  841 +    if(didSet)
  842 +        png_ptr->mode |= PNG_HAVE_acTL;
  843 +}
  844 +
  845 +void /* PRIVATE */
  846 +png_handle_fcTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
  847 +{
  848 +    png_byte data[22];
  849 +    png_uint_32 width;
  850 +    png_uint_32 height;
  851 +    png_uint_32 x_offset;
  852 +    png_uint_32 y_offset;
  853 +    png_uint_16 delay_num;
  854 +    png_uint_16 delay_den;
  855 +    png_byte dispose_op;
  856 +    png_byte blend_op;
  857 +
  858 +    png_debug(1, "in png_handle_fcTL");
  859 +
  860 +    png_ensure_sequence_number(png_ptr, length);
  861 +
  862 +    if (!(png_ptr->mode & PNG_HAVE_IHDR))
  863 +    {
  864 +        png_error(png_ptr, "Missing IHDR before fcTL");
  865 +    }
  866 +    else if (png_ptr->mode & PNG_HAVE_IDAT)
  867 +    {
  868 +        /* for any frames other then the first this message may be misleading,
  869 +        * but correct. PNG_HAVE_IDAT is unset before the frame head is read
  870 +        * i can't think of a better message */
  871 +        png_warning(png_ptr, "Invalid fcTL after IDAT skipped");
  872 +        png_crc_finish(png_ptr, length-4);
  873 +        return;
  874 +    }
  875 +    else if (png_ptr->mode & PNG_HAVE_fcTL)
  876 +    {
  877 +        png_warning(png_ptr, "Duplicate fcTL within one frame skipped");
  878 +        png_crc_finish(png_ptr, length-4);
  879 +        return;
  880 +    }
  881 +    else if (length != 26)
  882 +    {
  883 +        png_warning(png_ptr, "fcTL with invalid length skipped");
  884 +        png_crc_finish(png_ptr, length-4);
  885 +        return;
  886 +    }
  887 +
  888 +    png_crc_read(png_ptr, data, 22);
  889 +    png_crc_finish(png_ptr, 0);
  890 +
  891 +    width = png_get_uint_31(png_ptr, data);
  892 +    height = png_get_uint_31(png_ptr, data + 4);
  893 +    x_offset = png_get_uint_31(png_ptr, data + 8);
  894 +    y_offset = png_get_uint_31(png_ptr, data + 12);
  895 +    delay_num = png_get_uint_16(data + 16);
  896 +    delay_den = png_get_uint_16(data + 18);
  897 +    dispose_op = data[20];
  898 +    blend_op = data[21];
  899 +
  900 +    if (png_ptr->num_frames_read == 0 && (x_offset != 0 || y_offset != 0))
  901 +    {
  902 +        png_warning(png_ptr, "fcTL for the first frame must have zero offset");
  903 +        return;
  904 +    }
  905 +
  906 +    if (info_ptr != NULL)
  907 +    {
  908 +        if (png_ptr->num_frames_read == 0 &&
  909 +            (width != info_ptr->width || height != info_ptr->height))
  910 +        {
  911 +            png_warning(png_ptr, "size in first frame's fcTL must match "
  912 +                               "the size in IHDR");
  913 +            return;
  914 +        }
  915 +
  916 +        /* The set function will do more error checking */
  917 +        png_set_next_frame_fcTL(png_ptr, info_ptr, width, height,
  918 +                                x_offset, y_offset, delay_num, delay_den,
  919 +                                dispose_op, blend_op);
  920 +
  921 +        png_read_reinit(png_ptr, info_ptr);
  922 +
  923 +        png_ptr->mode |= PNG_HAVE_fcTL;
  924 +    }
  925 +}
  926 +
  927 +void /* PRIVATE */
  928 +png_have_info(png_structp png_ptr, png_infop info_ptr)
  929 +{
  930 +    if((info_ptr->valid & PNG_INFO_acTL) && !(info_ptr->valid & PNG_INFO_fcTL))
  931 +    {
  932 +        png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN;
  933 +        info_ptr->num_frames++;
  934 +    }
  935 +}
  936 +
  937 +void /* PRIVATE */
  938 +png_handle_fdAT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
  939 +{
  940 +    png_ensure_sequence_number(png_ptr, length);
  941 +
  942 +    /* This function is only called from png_read_end(), png_read_info(),
  943 +    * and png_push_read_chunk() which means that:
  944 +    * - the user doesn't want to read this frame
  945 +    * - or this is an out-of-place fdAT
  946 +    * in either case it is safe to ignore the chunk with a warning */
  947 +    png_warning(png_ptr, "ignoring fdAT chunk");
  948 +    png_crc_finish(png_ptr, length - 4);
  949 +    PNG_UNUSED(info_ptr)
  950 +}
  951 +
  952 +void /* PRIVATE */
  953 +png_ensure_sequence_number(png_structp png_ptr, png_uint_32 length)
  954 +{
  955 +    png_byte data[4];
  956 +    png_uint_32 sequence_number;
  957 +
  958 +    if (length < 4)
  959 +        png_error(png_ptr, "invalid fcTL or fdAT chunk found");
  960 +
  961 +    png_crc_read(png_ptr, data, 4);
  962 +    sequence_number = png_get_uint_31(png_ptr, data);
  963 +
  964 +    if (sequence_number != png_ptr->next_seq_num)
  965 +        png_error(png_ptr, "fcTL or fdAT chunk with out-of-order sequence "
  966 +                           "number found");
  967 +
  968 +    png_ptr->next_seq_num++;
  969 +}
  970 +#endif /* PNG_READ_APNG_SUPPORTED */
  971 +
  972  #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
  973  /* Utility function for png_handle_unknown; set up png_ptr::unknown_chunk */
  974  static int
  975 @@ -4145,7 +4323,38 @@
  976        {
  977           uInt avail_in;
  978           png_bytep buffer;
  979 +#ifdef PNG_READ_APNG_SUPPORTED
  980 +         png_uint_32 bytes_to_skip = 0;
  981 +
  982 +         while (png_ptr->idat_size == 0 || bytes_to_skip != 0)
  983 +         {
  984 +            png_crc_finish(png_ptr, bytes_to_skip);
  985 +            bytes_to_skip = 0;
  986 +
  987 +            png_ptr->idat_size = png_read_chunk_header(png_ptr);
  988 +            if (png_ptr->num_frames_read == 0)
  989 +            {
  990 +               if (png_ptr->chunk_name != png_IDAT)
  991 +                  png_error(png_ptr, "Not enough image data");
  992 +            }
  993 +            else
  994 +            {
  995 +               if (png_ptr->chunk_name == png_IEND)
  996 +                  png_error(png_ptr, "Not enough image data");
  997 +               if (png_ptr->chunk_name != png_fdAT)
  998 +               {
  999 +                  png_warning(png_ptr, "Skipped (ignored) a chunk "
 1000 +                                       "between APNG chunks");
 1001 +                  bytes_to_skip = png_ptr->idat_size;
 1002 +                  continue;
 1003 +               }
 1004  
 1005 +               png_ensure_sequence_number(png_ptr, png_ptr->idat_size);
 1006 +
 1007 +               png_ptr->idat_size -= 4;
 1008 +            }
 1009 +         }
 1010 +#else
 1011           while (png_ptr->idat_size == 0)
 1012           {
 1013              png_crc_finish(png_ptr, 0);
 1014 @@ -4157,7 +4366,7 @@
 1015              if (png_ptr->chunk_name != png_IDAT)
 1016                 png_error(png_ptr, "Not enough image data");
 1017           }
 1018 -
 1019 +#endif /* PNG_READ_APNG_SUPPORTED */
 1020           avail_in = png_ptr->IDAT_read_size;
 1021  
 1022           if (avail_in > png_ptr->idat_size)
 1023 @@ -4220,6 +4429,9 @@
 1024  
 1025           png_ptr->mode |= PNG_AFTER_IDAT;
 1026           png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
 1027 +#ifdef PNG_READ_APNG_SUPPORTED
 1028 +         png_ptr->num_frames_read++;
 1029 +#endif
 1030  
 1031           if (png_ptr->zstream.avail_in > 0 || png_ptr->idat_size > 0)
 1032              png_chunk_benign_error(png_ptr, "Extra compressed data");
 1033 @@ -4658,4 +4870,80 @@
 1034  
 1035     png_ptr->flags |= PNG_FLAG_ROW_INIT;
 1036  }
 1037 +
 1038 +#ifdef PNG_READ_APNG_SUPPORTED
 1039 +/* This function is to be called after the main IDAT set has been read and
 1040 + * before a new IDAT is read. It resets some parts of png_ptr
 1041 + * to make them usable by the read functions again */
 1042 +void /* PRIVATE */
 1043 +png_read_reset(png_structp png_ptr)
 1044 +{
 1045 +    png_ptr->mode &= ~PNG_HAVE_IDAT;
 1046 +    png_ptr->mode &= ~PNG_AFTER_IDAT;
 1047 +    png_ptr->row_number = 0;
 1048 +    png_ptr->pass = 0;
 1049 +}
 1050 +
 1051 +void /* PRIVATE */
 1052 +png_read_reinit(png_structp png_ptr, png_infop info_ptr)
 1053 +{
 1054 +    png_ptr->width = info_ptr->next_frame_width;
 1055 +    png_ptr->height = info_ptr->next_frame_height;
 1056 +    png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->width);
 1057 +    png_ptr->info_rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth,
 1058 +        png_ptr->width);
 1059 +    if (png_ptr->prev_row)
 1060 +        memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
 1061 +}
 1062 +
 1063 +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
 1064 +/* same as png_read_reset() but for the progressive reader */
 1065 +void /* PRIVATE */
 1066 +png_progressive_read_reset(png_structp png_ptr)
 1067 +{
 1068 +#ifdef PNG_READ_INTERLACING_SUPPORTED
 1069 +   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
 1070 +
 1071 +   /* Start of interlace block */
 1072 +    const int png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
 1073 +
 1074 +    /* Offset to next interlace block */
 1075 +    const int png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
 1076 +
 1077 +    /* Start of interlace block in the y direction */
 1078 +    const int png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
 1079 +
 1080 +    /* Offset to next interlace block in the y direction */
 1081 +    const int png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
 1082 +
 1083 +    if (png_ptr->interlaced)
 1084 +    {
 1085 +        if (!(png_ptr->transformations & PNG_INTERLACE))
 1086 +            png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
 1087 +                                png_pass_ystart[0]) / png_pass_yinc[0];
 1088 +        else
 1089 +            png_ptr->num_rows = png_ptr->height;
 1090 +
 1091 +        png_ptr->iwidth = (png_ptr->width +
 1092 +                           png_pass_inc[png_ptr->pass] - 1 -
 1093 +                           png_pass_start[png_ptr->pass]) /
 1094 +                           png_pass_inc[png_ptr->pass];
 1095 +    }
 1096 +    else
 1097 +#endif /* PNG_READ_INTERLACING_SUPPORTED */
 1098 +    {
 1099 +        png_ptr->num_rows = png_ptr->height;
 1100 +        png_ptr->iwidth = png_ptr->width;
 1101 +    }
 1102 +    png_ptr->flags &= ~PNG_FLAG_ZSTREAM_ENDED;
 1103 +    if (inflateReset(&(png_ptr->zstream)) != Z_OK)
 1104 +        png_error(png_ptr, "inflateReset failed");
 1105 +    png_ptr->zstream.avail_in = 0;
 1106 +    png_ptr->zstream.next_in = 0;
 1107 +    png_ptr->zstream.next_out = png_ptr->row_buf;
 1108 +    png_ptr->zstream.avail_out = (uInt)PNG_ROWBYTES(png_ptr->pixel_depth,
 1109 +        png_ptr->iwidth) + 1;
 1110 +}
 1111 +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
 1112 +#endif /* PNG_READ_APNG_SUPPORTED */
 1113  #endif /* READ */
 1114 diff -Naru libpng-1.6.34.org/pngset.c libpng-1.6.34/pngset.c
 1115 --- libpng-1.6.34.org/pngset.c	2017-09-29 18:53:22.701691926 +0900
 1116 +++ libpng-1.6.34/pngset.c	2017-09-29 18:56:30.292848897 +0900
 1117 @@ -288,6 +288,11 @@
 1118     info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth);
 1119  
 1120     info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width);
 1121 +
 1122 +#ifdef PNG_APNG_SUPPORTED
 1123 +   /* for non-animated png. this may be overwritten from an acTL chunk later */
 1124 +   info_ptr->num_frames = 1;
 1125 +#endif
 1126  }
 1127  
 1128  #ifdef PNG_oFFs_SUPPORTED
 1129 @@ -1158,6 +1163,147 @@
 1130  }
 1131  #endif /* sPLT */
 1132  
 1133 +#ifdef PNG_APNG_SUPPORTED
 1134 +png_uint_32 PNGAPI
 1135 +png_set_acTL(png_structp png_ptr, png_infop info_ptr,
 1136 +    png_uint_32 num_frames, png_uint_32 num_plays)
 1137 +{
 1138 +    png_debug1(1, "in %s storage function", "acTL");
 1139 +
 1140 +    if (png_ptr == NULL || info_ptr == NULL)
 1141 +    {
 1142 +        png_warning(png_ptr,
 1143 +                    "Call to png_set_acTL() with NULL png_ptr "
 1144 +                    "or info_ptr ignored");
 1145 +        return (0);
 1146 +    }
 1147 +    if (num_frames == 0)
 1148 +    {
 1149 +        png_warning(png_ptr,
 1150 +                    "Ignoring attempt to set acTL with num_frames zero");
 1151 +        return (0);
 1152 +    }
 1153 +    if (num_frames > PNG_UINT_31_MAX)
 1154 +    {
 1155 +        png_warning(png_ptr,
 1156 +                    "Ignoring attempt to set acTL with num_frames > 2^31-1");
 1157 +        return (0);
 1158 +    }
 1159 +    if (num_plays > PNG_UINT_31_MAX)
 1160 +    {
 1161 +        png_warning(png_ptr,
 1162 +                    "Ignoring attempt to set acTL with num_plays "
 1163 +                    "> 2^31-1");
 1164 +        return (0);
 1165 +    }
 1166 +
 1167 +    info_ptr->num_frames = num_frames;
 1168 +    info_ptr->num_plays = num_plays;
 1169 +
 1170 +    info_ptr->valid |= PNG_INFO_acTL;
 1171 +
 1172 +    return (1);
 1173 +}
 1174 +
 1175 +/* delay_num and delay_den can hold any 16-bit values including zero */
 1176 +png_uint_32 PNGAPI
 1177 +png_set_next_frame_fcTL(png_structp png_ptr, png_infop info_ptr,
 1178 +    png_uint_32 width, png_uint_32 height,
 1179 +    png_uint_32 x_offset, png_uint_32 y_offset,
 1180 +    png_uint_16 delay_num, png_uint_16 delay_den,
 1181 +    png_byte dispose_op, png_byte blend_op)
 1182 +{
 1183 +    png_debug1(1, "in %s storage function", "fcTL");
 1184 +
 1185 +    if (png_ptr == NULL || info_ptr == NULL)
 1186 +    {
 1187 +        png_warning(png_ptr,
 1188 +                    "Call to png_set_fcTL() with NULL png_ptr or info_ptr "
 1189 +                    "ignored");
 1190 +        return (0);
 1191 +    }
 1192 +
 1193 +    png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset,
 1194 +                             delay_num, delay_den, dispose_op, blend_op);
 1195 +
 1196 +    if (blend_op == PNG_BLEND_OP_OVER)
 1197 +    {
 1198 +        if (!(png_ptr->color_type & PNG_COLOR_MASK_ALPHA) &&
 1199 +            !(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)))
 1200 +        {
 1201 +          png_warning(png_ptr, "PNG_BLEND_OP_OVER is meaningless "
 1202 +                               "and wasteful for opaque images, ignored");
 1203 +          blend_op = PNG_BLEND_OP_SOURCE;
 1204 +        }
 1205 +    }
 1206 +
 1207 +    info_ptr->next_frame_width = width;
 1208 +    info_ptr->next_frame_height = height;
 1209 +    info_ptr->next_frame_x_offset = x_offset;
 1210 +    info_ptr->next_frame_y_offset = y_offset;
 1211 +    info_ptr->next_frame_delay_num = delay_num;
 1212 +    info_ptr->next_frame_delay_den = delay_den;
 1213 +    info_ptr->next_frame_dispose_op = dispose_op;
 1214 +    info_ptr->next_frame_blend_op = blend_op;
 1215 +
 1216 +    info_ptr->valid |= PNG_INFO_fcTL;
 1217 +
 1218 +    return (1);
 1219 +}
 1220 +
 1221 +void /* PRIVATE */
 1222 +png_ensure_fcTL_is_valid(png_structp png_ptr,
 1223 +    png_uint_32 width, png_uint_32 height,
 1224 +    png_uint_32 x_offset, png_uint_32 y_offset,
 1225 +    png_uint_16 delay_num, png_uint_16 delay_den,
 1226 +    png_byte dispose_op, png_byte blend_op)
 1227 +{
 1228 +    if (width == 0 || width > PNG_UINT_31_MAX)
 1229 +        png_error(png_ptr, "invalid width in fcTL (> 2^31-1)");
 1230 +    if (height == 0 || height > PNG_UINT_31_MAX)
 1231 +        png_error(png_ptr, "invalid height in fcTL (> 2^31-1)");
 1232 +    if (x_offset > PNG_UINT_31_MAX)
 1233 +        png_error(png_ptr, "invalid x_offset in fcTL (> 2^31-1)");
 1234 +    if (y_offset > PNG_UINT_31_MAX)
 1235 +        png_error(png_ptr, "invalid y_offset in fcTL (> 2^31-1)");
 1236 +    if (width + x_offset > png_ptr->first_frame_width ||
 1237 +        height + y_offset > png_ptr->first_frame_height)
 1238 +        png_error(png_ptr, "dimensions of a frame are greater than"
 1239 +                           "the ones in IHDR");
 1240 +
 1241 +    if (dispose_op != PNG_DISPOSE_OP_NONE &&
 1242 +        dispose_op != PNG_DISPOSE_OP_BACKGROUND &&
 1243 +        dispose_op != PNG_DISPOSE_OP_PREVIOUS)
 1244 +        png_error(png_ptr, "invalid dispose_op in fcTL");
 1245 +
 1246 +    if (blend_op != PNG_BLEND_OP_SOURCE &&
 1247 +        blend_op != PNG_BLEND_OP_OVER)
 1248 +        png_error(png_ptr, "invalid blend_op in fcTL");
 1249 +
 1250 +    PNG_UNUSED(delay_num)
 1251 +    PNG_UNUSED(delay_den)
 1252 +}
 1253 +
 1254 +png_uint_32 PNGAPI
 1255 +png_set_first_frame_is_hidden(png_structp png_ptr, png_infop info_ptr,
 1256 +                              png_byte is_hidden)
 1257 +{
 1258 +    png_debug(1, "in png_first_frame_is_hidden()");
 1259 +
 1260 +    if (png_ptr == NULL)
 1261 +        return 0;
 1262 +
 1263 +    if (is_hidden)
 1264 +        png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN;
 1265 +    else
 1266 +        png_ptr->apng_flags &= ~PNG_FIRST_FRAME_HIDDEN;
 1267 +
 1268 +    PNG_UNUSED(info_ptr)
 1269 +
 1270 +    return 1;
 1271 +}
 1272 +#endif /* PNG_APNG_SUPPORTED */
 1273 +
 1274  #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
 1275  static png_byte
 1276  check_location(png_const_structrp png_ptr, int location)
 1277 diff -Naru libpng-1.6.34.org/pngstruct.h libpng-1.6.34/pngstruct.h
 1278 --- libpng-1.6.34.org/pngstruct.h	2017-09-29 18:53:22.701691926 +0900
 1279 +++ libpng-1.6.34/pngstruct.h	2017-09-29 18:56:30.287848466 +0900
 1280 @@ -403,6 +403,27 @@
 1281     png_byte filter_type;
 1282  #endif
 1283  
 1284 +#ifdef PNG_APNG_SUPPORTED
 1285 +   png_uint_32 apng_flags;
 1286 +   png_uint_32 next_seq_num;         /* next fcTL/fdAT chunk sequence number */
 1287 +   png_uint_32 first_frame_width;
 1288 +   png_uint_32 first_frame_height;
 1289 +
 1290 +#ifdef PNG_READ_APNG_SUPPORTED
 1291 +   png_uint_32 num_frames_read;      /* incremented after all image data of */
 1292 +                                     /* a frame is read */
 1293 +#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
 1294 +   png_progressive_frame_ptr frame_info_fn; /* frame info read callback */
 1295 +   png_progressive_frame_ptr frame_end_fn;  /* frame data read callback */
 1296 +#endif
 1297 +#endif
 1298 +
 1299 +#ifdef PNG_WRITE_APNG_SUPPORTED
 1300 +   png_uint_32 num_frames_to_write;
 1301 +   png_uint_32 num_frames_written;
 1302 +#endif
 1303 +#endif /* PNG_APNG_SUPPORTED */
 1304 +
 1305  /* New members added in libpng-1.2.0 */
 1306  
 1307  /* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */
 1308 diff -Naru libpng-1.6.34.org/pngtest.c libpng-1.6.34/pngtest.c
 1309 --- libpng-1.6.34.org/pngtest.c	2017-09-29 18:55:30.654712085 +0900
 1310 +++ libpng-1.6.34/pngtest.c	2017-09-29 18:56:30.287848466 +0900
 1311 @@ -875,6 +875,10 @@
 1312     volatile int num_passes;
 1313     int pass;
 1314     int bit_depth, color_type;
 1315 +#ifdef PNG_APNG_SUPPORTED
 1316 +   png_uint_32 num_frames;
 1317 +   png_uint_32 num_plays;
 1318 +#endif
 1319  
 1320     row_buf = NULL;
 1321     error_parameters.file_name = inname;
 1322 @@ -1381,6 +1385,22 @@
 1323        }
 1324     }
 1325  #endif
 1326 +
 1327 +#ifdef PNG_APNG_SUPPORTED
 1328 +   if (png_get_valid(read_ptr, read_info_ptr, PNG_INFO_acTL))
 1329 +   {
 1330 +      if (png_get_acTL(read_ptr, read_info_ptr, &num_frames, &num_plays))
 1331 +      {
 1332 +         png_byte is_hidden;
 1333 +         pngtest_debug2("Handling acTL chunks (frames %ld, plays %ld)",
 1334 +                    num_frames, num_plays);
 1335 +         png_set_acTL(write_ptr, write_info_ptr, num_frames, num_plays);
 1336 +         is_hidden = png_get_first_frame_is_hidden(read_ptr, read_info_ptr);
 1337 +         png_set_first_frame_is_hidden(write_ptr, write_info_ptr, is_hidden);
 1338 +      }
 1339 +   }
 1340 +#endif
 1341 +
 1342  #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
 1343     {
 1344        png_unknown_chunkp unknowns;
 1345 @@ -1461,6 +1481,110 @@
 1346     t_misc += (t_stop - t_start);
 1347     t_start = t_stop;
 1348  #endif
 1349 +#ifdef PNG_APNG_SUPPORTED
 1350 +   if (png_get_valid(read_ptr, read_info_ptr, PNG_INFO_acTL))
 1351 +   {
 1352 +      png_uint_32 frame;
 1353 +      for (frame = 0; frame < num_frames; frame++)
 1354 +      {
 1355 +         png_uint_32 frame_width;
 1356 +         png_uint_32 frame_height;
 1357 +         png_uint_32 x_offset;
 1358 +         png_uint_32 y_offset;
 1359 +         png_uint_16 delay_num;
 1360 +         png_uint_16 delay_den;
 1361 +         png_byte dispose_op;
 1362 +         png_byte blend_op;
 1363 +         png_read_frame_head(read_ptr, read_info_ptr);
 1364 +         if (png_get_valid(read_ptr, read_info_ptr, PNG_INFO_fcTL))
 1365 +         {
 1366 +            png_get_next_frame_fcTL(read_ptr, read_info_ptr,
 1367 +                                    &frame_width, &frame_height,
 1368 +                                    &x_offset, &y_offset,
 1369 +                                    &delay_num, &delay_den,
 1370 +                                    &dispose_op, &blend_op);
 1371 +         }
 1372 +         else
 1373 +         {
 1374 +            frame_width = width;
 1375 +            frame_height = height;
 1376 +            x_offset = 0;
 1377 +            y_offset = 0;
 1378 +            delay_num = 1;
 1379 +            delay_den = 1;
 1380 +            dispose_op = PNG_DISPOSE_OP_NONE;
 1381 +            blend_op = PNG_BLEND_OP_SOURCE;
 1382 +         }
 1383 +#ifdef PNG_WRITE_APNG_SUPPORTED
 1384 +         png_write_frame_head(write_ptr, write_info_ptr, (png_bytepp)&row_buf,
 1385 +                              frame_width, frame_height,
 1386 +                              x_offset, y_offset,
 1387 +                              delay_num, delay_den,
 1388 +                              dispose_op, blend_op);
 1389 +#endif
 1390 +         for (pass = 0; pass < num_passes; pass++)
 1391 +         {
 1392 +#           ifdef calc_pass_height
 1393 +               png_uint_32 pass_height;
 1394 +
 1395 +               if (num_passes == 7) /* interlaced */
 1396 +               {
 1397 +                  if (PNG_PASS_COLS(frame_width, pass) > 0)
 1398 +                     pass_height = PNG_PASS_ROWS(frame_height, pass);
 1399 +
 1400 +                  else
 1401 +                     pass_height = 0;
 1402 +               }
 1403 +
 1404 +               else /* not interlaced */
 1405 +                  pass_height = frame_height;
 1406 +#           else
 1407 +#              define pass_height frame_height
 1408 +#           endif
 1409 +
 1410 +            pngtest_debug1("Writing row data for pass %d", pass);
 1411 +            for (y = 0; y < pass_height; y++)
 1412 +            {
 1413 +#ifndef SINGLE_ROWBUF_ALLOC
 1414 +               pngtest_debug2("Allocating row buffer (pass %d, y = %u)...", pass, y);
 1415 +
 1416 +               row_buf = (png_bytep)png_malloc(read_ptr,
 1417 +                  png_get_rowbytes(read_ptr, read_info_ptr));
 1418 +
 1419 +               pngtest_debug2("\t0x%08lx (%lu bytes)", (unsigned long)row_buf,
 1420 +                  (unsigned long)png_get_rowbytes(read_ptr, read_info_ptr));
 1421 +
 1422 +#endif /* !SINGLE_ROWBUF_ALLOC */
 1423 +               png_read_rows(read_ptr, (png_bytepp)&row_buf, NULL, 1);
 1424 +
 1425 +#ifdef PNG_WRITE_SUPPORTED
 1426 +#ifdef PNGTEST_TIMING
 1427 +               t_stop = (float)clock();
 1428 +               t_decode += (t_stop - t_start);
 1429 +               t_start = t_stop;
 1430 +#endif
 1431 +               png_write_rows(write_ptr, (png_bytepp)&row_buf, 1);
 1432 +#ifdef PNGTEST_TIMING
 1433 +               t_stop = (float)clock();
 1434 +               t_encode += (t_stop - t_start);
 1435 +               t_start = t_stop;
 1436 +#endif
 1437 +#endif /* PNG_WRITE_SUPPORTED */
 1438 +
 1439 +#ifndef SINGLE_ROWBUF_ALLOC
 1440 +               pngtest_debug2("Freeing row buffer (pass %d, y = %u)", pass, y);
 1441 +               png_free(read_ptr, row_buf);
 1442 +               row_buf = NULL;
 1443 +#endif /* !SINGLE_ROWBUF_ALLOC */
 1444 +            }
 1445 +         }
 1446 +#ifdef PNG_WRITE_APNG_SUPPORTED
 1447 +         png_write_frame_tail(write_ptr, write_info_ptr);
 1448 +#endif
 1449 +      }
 1450 +   }
 1451 +   else
 1452 +#endif
 1453     for (pass = 0; pass < num_passes; pass++)
 1454     {
 1455  #     ifdef calc_pass_height
 1456 diff -Naru libpng-1.6.34.org/pngwrite.c libpng-1.6.34/pngwrite.c
 1457 --- libpng-1.6.34.org/pngwrite.c	2017-09-29 18:53:22.702692013 +0900
 1458 +++ libpng-1.6.34/pngwrite.c	2017-09-29 18:56:30.288848552 +0900
 1459 @@ -128,6 +128,10 @@
 1460         * the application continues writing the PNG.  So check the 'invalid'
 1461         * flag here too.
 1462         */
 1463 +#ifdef PNG_WRITE_APNG_SUPPORTED
 1464 +      if (info_ptr->valid & PNG_INFO_acTL)
 1465 +         png_write_acTL(png_ptr, info_ptr->num_frames, info_ptr->num_plays);
 1466 +#endif
 1467  #ifdef PNG_GAMMA_SUPPORTED
 1468  #  ifdef PNG_WRITE_gAMA_SUPPORTED
 1469        if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
 1470 @@ -370,6 +374,11 @@
 1471        png_benign_error(png_ptr, "Wrote palette index exceeding num_palette");
 1472  #endif
 1473  
 1474 +#ifdef PNG_WRITE_APNG_SUPPORTED
 1475 +   if (png_ptr->num_frames_written != png_ptr->num_frames_to_write)
 1476 +      png_error(png_ptr, "Not enough frames written");
 1477 +#endif
 1478 +
 1479     /* See if user wants us to write information chunks */
 1480     if (info_ptr != NULL)
 1481     {
 1482 @@ -1461,6 +1470,43 @@
 1483  }
 1484  #endif
 1485  
 1486 +#ifdef PNG_WRITE_APNG_SUPPORTED
 1487 +void PNGAPI
 1488 +png_write_frame_head(png_structp png_ptr, png_infop info_ptr,
 1489 +    png_bytepp row_pointers, png_uint_32 width, png_uint_32 height,
 1490 +    png_uint_32 x_offset, png_uint_32 y_offset,
 1491 +    png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
 1492 +    png_byte blend_op)
 1493 +{
 1494 +    png_debug(1, "in png_write_frame_head");
 1495 +
 1496 +    /* there is a chance this has been set after png_write_info was called,
 1497 +    * so it would be set but not written. is there a way to be sure? */
 1498 +    if (!(info_ptr->valid & PNG_INFO_acTL))
 1499 +        png_error(png_ptr, "png_write_frame_head(): acTL not set");
 1500 +
 1501 +    png_write_reset(png_ptr);
 1502 +
 1503 +    png_write_reinit(png_ptr, info_ptr, width, height);
 1504 +
 1505 +    if ( !(png_ptr->num_frames_written == 0 &&
 1506 +           (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN) ) )
 1507 +        png_write_fcTL(png_ptr, width, height, x_offset, y_offset,
 1508 +                       delay_num, delay_den, dispose_op, blend_op);
 1509 +
 1510 +    PNG_UNUSED(row_pointers)
 1511 +}
 1512 +
 1513 +void PNGAPI
 1514 +png_write_frame_tail(png_structp png_ptr, png_infop info_ptr)
 1515 +{
 1516 +    png_debug(1, "in png_write_frame_tail");
 1517 +
 1518 +    png_ptr->num_frames_written++;
 1519 +
 1520 +    PNG_UNUSED(info_ptr)
 1521 +}
 1522 +#endif /* PNG_WRITE_APNG_SUPPORTED */
 1523  
 1524  #ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
 1525  /* Initialize the write structure - general purpose utility. */
 1526 diff -Naru libpng-1.6.34.org/pngwutil.c libpng-1.6.34/pngwutil.c
 1527 --- libpng-1.6.34.org/pngwutil.c	2017-09-29 18:53:22.703692099 +0900
 1528 +++ libpng-1.6.34/pngwutil.c	2017-09-29 18:56:30.302849758 +0900
 1529 @@ -822,6 +822,11 @@
 1530     /* Write the chunk */
 1531     png_write_complete_chunk(png_ptr, png_IHDR, buf, (png_size_t)13);
 1532  
 1533 +#ifdef PNG_WRITE_APNG_SUPPORTED
 1534 +   png_ptr->first_frame_width = width;
 1535 +   png_ptr->first_frame_height = height;
 1536 +#endif
 1537 +
 1538     if ((png_ptr->do_filter) == PNG_NO_FILTERS)
 1539     {
 1540        if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
 1541 @@ -1003,8 +1008,17 @@
 1542                 optimize_cmf(data, png_image_size(png_ptr));
 1543  #endif
 1544  
 1545 -         if (size > 0)
 1546 -            png_write_complete_chunk(png_ptr, png_IDAT, data, size);
 1547 +            if (size > 0)
 1548 +#ifdef PNG_WRITE_APNG_SUPPORTED
 1549 +            {
 1550 +               if (png_ptr->num_frames_written == 0)
 1551 +#endif
 1552 +               png_write_complete_chunk(png_ptr, png_IDAT, data, size);
 1553 +#ifdef PNG_WRITE_APNG_SUPPORTED
 1554 +               else
 1555 +                  png_write_fdAT(png_ptr, data, size);
 1556 +            }
 1557 +#endif /* PNG_WRITE_APNG_SUPPORTED */
 1558           png_ptr->mode |= PNG_HAVE_IDAT;
 1559  
 1560           png_ptr->zstream.next_out = data;
 1561 @@ -1051,7 +1065,17 @@
 1562  #endif
 1563  
 1564           if (size > 0)
 1565 +#ifdef PNG_WRITE_APNG_SUPPORTED
 1566 +         {
 1567 +            if (png_ptr->num_frames_written == 0)
 1568 +#endif
 1569              png_write_complete_chunk(png_ptr, png_IDAT, data, size);
 1570 +#ifdef PNG_WRITE_APNG_SUPPORTED
 1571 +            else
 1572 +               png_write_fdAT(png_ptr, data, size);
 1573 +         }
 1574 +#endif /* PNG_WRITE_APNG_SUPPORTED */
 1575 +
 1576           png_ptr->zstream.avail_out = 0;
 1577           png_ptr->zstream.next_out = NULL;
 1578           png_ptr->mode |= PNG_HAVE_IDAT | PNG_AFTER_IDAT;
 1579 @@ -1887,6 +1911,82 @@
 1580  }
 1581  #endif
 1582  
 1583 +#ifdef PNG_WRITE_APNG_SUPPORTED
 1584 +void /* PRIVATE */
 1585 +png_write_acTL(png_structp png_ptr,
 1586 +    png_uint_32 num_frames, png_uint_32 num_plays)
 1587 +{
 1588 +    png_byte buf[8];
 1589 +
 1590 +    png_debug(1, "in png_write_acTL");
 1591 +
 1592 +    png_ptr->num_frames_to_write = num_frames;
 1593 +
 1594 +    if (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN)
 1595 +        num_frames--;
 1596 +
 1597 +    png_save_uint_32(buf, num_frames);
 1598 +    png_save_uint_32(buf + 4, num_plays);
 1599 +
 1600 +    png_write_complete_chunk(png_ptr, png_acTL, buf, (png_size_t)8);
 1601 +}
 1602 +
 1603 +void /* PRIVATE */
 1604 +png_write_fcTL(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
 1605 +    png_uint_32 x_offset, png_uint_32 y_offset,
 1606 +    png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
 1607 +    png_byte blend_op)
 1608 +{
 1609 +    png_byte buf[26];
 1610 +
 1611 +    png_debug(1, "in png_write_fcTL");
 1612 +
 1613 +    if (png_ptr->num_frames_written == 0 && (x_offset != 0 || y_offset != 0))
 1614 +        png_error(png_ptr, "x and/or y offset for the first frame aren't 0");
 1615 +    if (png_ptr->num_frames_written == 0 &&
 1616 +        (width != png_ptr->first_frame_width ||
 1617 +         height != png_ptr->first_frame_height))
 1618 +        png_error(png_ptr, "width and/or height in the first frame's fcTL "
 1619 +                           "don't match the ones in IHDR");
 1620 +
 1621 +    /* more error checking */
 1622 +    png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset,
 1623 +                             delay_num, delay_den, dispose_op, blend_op);
 1624 +
 1625 +    png_save_uint_32(buf, png_ptr->next_seq_num);
 1626 +    png_save_uint_32(buf + 4, width);
 1627 +    png_save_uint_32(buf + 8, height);
 1628 +    png_save_uint_32(buf + 12, x_offset);
 1629 +    png_save_uint_32(buf + 16, y_offset);
 1630 +    png_save_uint_16(buf + 20, delay_num);
 1631 +    png_save_uint_16(buf + 22, delay_den);
 1632 +    buf[24] = dispose_op;
 1633 +    buf[25] = blend_op;
 1634 +
 1635 +    png_write_complete_chunk(png_ptr, png_fcTL, buf, (png_size_t)26);
 1636 +
 1637 +    png_ptr->next_seq_num++;
 1638 +}
 1639 +
 1640 +void /* PRIVATE */
 1641 +png_write_fdAT(png_structp png_ptr,
 1642 +    png_const_bytep data, png_size_t length)
 1643 +{
 1644 +    png_byte buf[4];
 1645 +
 1646 +    png_write_chunk_header(png_ptr, png_fdAT, (png_uint_32)(4 + length));
 1647 +
 1648 +    png_save_uint_32(buf, png_ptr->next_seq_num);
 1649 +    png_write_chunk_data(png_ptr, buf, 4);
 1650 +
 1651 +    png_write_chunk_data(png_ptr, data, length);
 1652 +
 1653 +    png_write_chunk_end(png_ptr);
 1654 +
 1655 +    png_ptr->next_seq_num++;
 1656 +}
 1657 +#endif /* PNG_WRITE_APNG_SUPPORTED */
 1658 +
 1659  /* Initializes the row writing capability of libpng */
 1660  void /* PRIVATE */
 1661  png_write_start_row(png_structrp png_ptr)
 1662 @@ -2781,4 +2881,39 @@
 1663     }
 1664  #endif /* WRITE_FLUSH */
 1665  }
 1666 +
 1667 +#ifdef PNG_WRITE_APNG_SUPPORTED
 1668 +void /* PRIVATE */
 1669 +png_write_reset(png_structp png_ptr)
 1670 +{
 1671 +    png_ptr->row_number = 0;
 1672 +    png_ptr->pass = 0;
 1673 +    png_ptr->mode &= ~PNG_HAVE_IDAT;
 1674 +}
 1675 +
 1676 +void /* PRIVATE */
 1677 +png_write_reinit(png_structp png_ptr, png_infop info_ptr,
 1678 +                 png_uint_32 width, png_uint_32 height)
 1679 +{
 1680 +    if (png_ptr->num_frames_written == 0 &&
 1681 +        (width != png_ptr->first_frame_width ||
 1682 +         height != png_ptr->first_frame_height))
 1683 +        png_error(png_ptr, "width and/or height in the first frame's fcTL "
 1684 +                           "don't match the ones in IHDR");
 1685 +    if (width > png_ptr->first_frame_width ||
 1686 +        height > png_ptr->first_frame_height)
 1687 +        png_error(png_ptr, "width and/or height for a frame greater than"
 1688 +                           "the ones in IHDR");
 1689 +
 1690 +    png_set_IHDR(png_ptr, info_ptr, width, height,
 1691 +                 info_ptr->bit_depth, info_ptr->color_type,
 1692 +                 info_ptr->interlace_type, info_ptr->compression_type,
 1693 +                 info_ptr->filter_type);
 1694 +
 1695 +    png_ptr->width = width;
 1696 +    png_ptr->height = height;
 1697 +    png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width);
 1698 +    png_ptr->usr_width = png_ptr->width;
 1699 +}
 1700 +#endif /* PNG_WRITE_APNG_SUPPORTED */
 1701  #endif /* WRITE */
 1702 diff -Naru libpng-1.6.34.org/scripts/symbols.def libpng-1.6.34/scripts/symbols.def
 1703 --- libpng-1.6.34.org/scripts/symbols.def	2017-09-29 18:55:30.655712171 +0900
 1704 +++ libpng-1.6.34/scripts/symbols.def	2017-09-29 18:56:30.289848638 +0900
 1705 @@ -254,3 +254,23 @@
 1706   png_set_eXIf @247
 1707   png_get_eXIf_1 @248
 1708   png_set_eXIf_1 @249
 1709 + png_get_acTL @250
 1710 + png_set_acTL @251
 1711 + png_get_num_frames @252
 1712 + png_get_num_plays @253
 1713 + png_get_next_frame_fcTL @254
 1714 + png_set_next_frame_fcTL @255
 1715 + png_get_next_frame_width @256
 1716 + png_get_next_frame_height @257
 1717 + png_get_next_frame_x_offset @258
 1718 + png_get_next_frame_y_offset @259
 1719 + png_get_next_frame_delay_num @260
 1720 + png_get_next_frame_delay_den @261
 1721 + png_get_next_frame_dispose_op @262
 1722 + png_get_next_frame_blend_op @263
 1723 + png_get_first_frame_is_hidden @264
 1724 + png_set_first_frame_is_hidden @265
 1725 + png_read_frame_head @266
 1726 + png_set_progressive_frame_fn @267
 1727 + png_write_frame_head @268
 1728 + png_write_frame_tail @269

Generated by cgit