Commit | Line | Data |
---|---|---|
0a0f2c83 VM |
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 | |
7472392b | 7 | |
0a0f2c83 VM |
8 | +#define PNG_APNG_SUPPORTED |
9 | +#define PNG_READ_APNG_SUPPORTED | |
10 | +#define PNG_WRITE_APNG_SUPPORTED | |
7472392b | 11 | + |
0a0f2c83 VM |
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 | */ | |
7472392b | 18 | |
0a0f2c83 VM |
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 | |
7472392b | 24 | + |
0a0f2c83 VM |
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 */ | |
7472392b | 29 | + |
0a0f2c83 VM |
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 | |
7472392b | 40 | +#endif |
7472392b | 41 | |
0a0f2c83 VM |
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)); | |
7472392b | 62 | + |
0a0f2c83 VM |
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)); | |
7472392b | 65 | + |
0a0f2c83 VM |
66 | +PNG_EXPORT(252, png_uint_32, png_get_num_frames, (png_structp png_ptr, |
67 | + png_infop info_ptr)); | |
7472392b | 68 | + |
0a0f2c83 VM |
69 | +PNG_EXPORT(253, png_uint_32, png_get_num_plays, (png_structp png_ptr, |
70 | + png_infop info_ptr)); | |
7472392b | 71 | + |
0a0f2c83 VM |
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)); | |
7472392b | 77 | + |
0a0f2c83 VM |
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)); | |
7472392b | 83 | + |
0a0f2c83 VM |
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)); | |
7472392b | 104 | + |
0a0f2c83 VM |
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 */ | |
7472392b | 114 | + |
0a0f2c83 VM |
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)); | |
7472392b | 122 | + |
0a0f2c83 VM |
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 @@ | |
7472392b VM |
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 && | |
0a0f2c83 | 157 | + (info_ptr->valid & PNG_INFO_acTL) && |
7472392b VM |
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 && | |
0a0f2c83 | 198 | + (info_ptr->valid & PNG_INFO_fcTL) && |
7472392b VM |
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 | +} | |
0a0f2c83 | 310 | +#endif /* PNG_APNG_SUPPORTED */ |
7472392b | 311 | #endif /* READ || WRITE */ |
0a0f2c83 VM |
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 */ | |
7472392b VM |
317 | #endif |
318 | ||
7472392b | 319 | +#ifdef PNG_APNG_SUPPORTED |
0a0f2c83 VM |
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; | |
7472392b | 330 | +#endif |
0a0f2c83 VM |
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 @@ | |
7472392b | 338 | |
0a0f2c83 | 339 | chunk_name = png_ptr->chunk_name; |
7472392b | 340 | |
0a0f2c83 VM |
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"); | |
7472392b | 350 | + |
0a0f2c83 VM |
351 | + if (png_ptr->push_length + 4 > png_ptr->buffer_size) |
352 | + { | |
353 | + png_push_save_buffer(png_ptr); | |
354 | + return; | |
355 | + } | |
7472392b | 356 | + |
0a0f2c83 VM |
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 | + } | |
7472392b | 367 | + |
0a0f2c83 | 368 | + png_ensure_sequence_number(png_ptr, 4); |
7472392b | 369 | + |
0a0f2c83 VM |
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"); | |
7472392b | 375 | + |
0a0f2c83 VM |
376 | + if (png_ptr->push_length + 4 > png_ptr->buffer_size) |
377 | + { | |
378 | + png_push_save_buffer(png_ptr); | |
379 | + return; | |
380 | + } | |
7472392b | 381 | + |
7472392b | 382 | + png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; |
0a0f2c83 | 383 | + return; |
7472392b VM |
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; | |
0a0f2c83 VM |
392 | + |
393 | + return; | |
7472392b VM |
394 | + } |
395 | + } | |
396 | + | |
397 | + else if (chunk_name == png_fcTL) | |
398 | + { | |
0a0f2c83 VM |
399 | + if (png_ptr->push_length + 4 > png_ptr->buffer_size) |
400 | + { | |
401 | + png_push_save_buffer(png_ptr); | |
402 | + return; | |
403 | + } | |
404 | + | |
7472392b VM |
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 | + | |
0a0f2c83 | 410 | + if (!(png_ptr->mode & PNG_HAVE_fcTL)) |
7472392b VM |
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; | |
7472392b | 420 | + |
0a0f2c83 | 421 | + return; |
7472392b VM |
422 | + } |
423 | + | |
424 | + else | |
425 | + { | |
0a0f2c83 VM |
426 | + if (png_ptr->push_length + 4 > png_ptr->buffer_size) |
427 | + { | |
428 | + png_push_save_buffer(png_ptr); | |
429 | + return; | |
430 | + } | |
7472392b VM |
431 | + png_warning(png_ptr, "Skipped (ignored) a chunk " |
432 | + "between APNG chunks"); | |
7472392b | 433 | + png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; |
0a0f2c83 | 434 | + return; |
7472392b VM |
435 | + } |
436 | + | |
437 | + return; | |
438 | + } | |
0a0f2c83 | 439 | +#endif /* PNG_READ_APNG_SUPPORTED */ |
7472392b VM |
440 | + |
441 | if (chunk_name == png_IDAT) | |
442 | { | |
443 | if ((png_ptr->mode & PNG_AFTER_IDAT) != 0) | |
0a0f2c83 | 444 | @@ -261,6 +361,9 @@ |
7472392b VM |
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); | |
0a0f2c83 VM |
454 | @@ -406,6 +509,30 @@ |
455 | png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length); | |
7472392b VM |
456 | } |
457 | #endif | |
7472392b VM |
458 | +#ifdef PNG_READ_APNG_SUPPORTED |
459 | + else if (chunk_name == png_acTL) | |
460 | + { | |
0a0f2c83 VM |
461 | + if (png_ptr->push_length + 4 > png_ptr->buffer_size) |
462 | + { | |
463 | + png_push_save_buffer(png_ptr); | |
464 | + return; | |
465 | + } | |
466 | + | |
7472392b VM |
467 | + png_handle_acTL(png_ptr, info_ptr, png_ptr->push_length); |
468 | + } | |
469 | + | |
470 | + else if (chunk_name == png_fcTL) | |
471 | + { | |
0a0f2c83 VM |
472 | + if (png_ptr->push_length + 4 > png_ptr->buffer_size) |
473 | + { | |
474 | + png_push_save_buffer(png_ptr); | |
475 | + return; | |
476 | + } | |
477 | + | |
7472392b VM |
478 | + png_handle_fcTL(png_ptr, info_ptr, png_ptr->push_length); |
479 | + } | |
480 | + | |
0a0f2c83 VM |
481 | +#endif /* PNG_READ_APNG_SUPPORTED */ |
482 | ||
7472392b VM |
483 | else |
484 | { | |
0a0f2c83 | 485 | @@ -539,7 +666,11 @@ |
7472392b VM |
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); | |
0a0f2c83 | 497 | @@ -547,17 +678,64 @@ |
7472392b VM |
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 | + { | |
0a0f2c83 | 504 | + if (png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) |
7472392b VM |
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"); | |
0a0f2c83 VM |
516 | + if (png_ptr->push_length + 4 > png_ptr->buffer_size) |
517 | + { | |
518 | + png_push_save_buffer(png_ptr); | |
519 | + return; | |
520 | + } | |
7472392b VM |
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) | |
0a0f2c83 | 562 | @@ -631,6 +809,15 @@ |
7472392b VM |
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 */ | |
0a0f2c83 | 568 | + if (!(png_ptr->apng_flags & PNG_APNG_APP) && png_ptr->num_frames_read > 0) |
7472392b | 569 | + { |
0a0f2c83 VM |
570 | + png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED; |
571 | + return; | |
7472392b VM |
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. | |
0a0f2c83 | 578 | @@ -1085,6 +1272,18 @@ |
7472392b VM |
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 | { | |
0a0f2c83 VM |
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 */ | |
7472392b | 604 | +#ifdef PNG_APNG_SUPPORTED |
0a0f2c83 VM |
605 | +#define PNG_HAVE_acTL 0x10000U |
606 | +#define PNG_HAVE_fcTL 0x20000U | |
7472392b | 607 | +#endif |
7472392b | 608 | |
0a0f2c83 VM |
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) | |
7472392b VM |
614 | |
615 | +#ifdef PNG_APNG_SUPPORTED | |
0a0f2c83 VM |
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) | |
7472392b | 619 | + |
0a0f2c83 VM |
620 | +/* For png_struct.apng_flags: */ |
621 | +#define PNG_FIRST_FRAME_HIDDEN 0x0001U | |
622 | +#define PNG_APNG_APP 0x0002U | |
623 | +#endif | |
7472392b | 624 | + |
0a0f2c83 VM |
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); | |
7472392b | 638 | + |
0a0f2c83 VM |
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 */ | |
7472392b | 656 | + |
0a0f2c83 VM |
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); | |
7472392b | 696 | + |
0a0f2c83 VM |
697 | + else if (chunk_name == png_fcTL) |
698 | + png_handle_fcTL(png_ptr, info_ptr, length); | |
7472392b | 699 | + |
0a0f2c83 VM |
700 | + else if (chunk_name == png_fdAT) |
701 | + png_handle_fdAT(png_ptr, info_ptr, length); | |
702 | +#endif | |
7472392b | 703 | + |
0a0f2c83 VM |
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 */ | |
7472392b | 716 | + |
0a0f2c83 | 717 | + png_debug(0, "Reading frame head"); |
7472392b | 718 | + |
0a0f2c83 VM |
719 | + if (!(png_ptr->mode & PNG_HAVE_acTL)) |
720 | + png_error(png_ptr, "attempt to png_read_frame_head() but " | |
721 | + "no acTL present"); | |
7472392b | 722 | + |
0a0f2c83 VM |
723 | + /* do nothing for the main IDAT */ |
724 | + if (png_ptr->num_frames_read == 0) | |
725 | + return; | |
7472392b | 726 | + |
0a0f2c83 VM |
727 | + png_read_reset(png_ptr); |
728 | + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; | |
729 | + png_ptr->mode &= ~PNG_HAVE_fcTL; | |
7472392b | 730 | + |
0a0f2c83 VM |
731 | + have_chunk_after_DAT = 0; |
732 | + for (;;) | |
733 | + { | |
734 | + png_uint_32 length = png_read_chunk_header(png_ptr); | |
7472392b | 735 | + |
0a0f2c83 VM |
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 | + } | |
7472392b | 743 | + |
0a0f2c83 VM |
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 | + } | |
7472392b | 749 | + |
0a0f2c83 VM |
750 | + else if (png_ptr->chunk_name == png_fdAT) |
751 | + { | |
752 | + png_ensure_sequence_number(png_ptr, length); | |
7472392b | 753 | + |
0a0f2c83 VM |
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; | |
7472392b | 761 | + |
0a0f2c83 VM |
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 | + } | |
7472392b | 774 | +} |
0a0f2c83 | 775 | +#endif /* PNG_READ_APNG_SUPPORTED */ |
7472392b | 776 | + |
0a0f2c83 VM |
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 @@ | |
7472392b VM |
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; | |
0a0f2c83 | 795 | @@ -2840,6 +2845,179 @@ |
7472392b VM |
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 | + | |
0a0f2c83 | 810 | + if (!(png_ptr->mode & PNG_HAVE_IHDR)) |
7472392b VM |
811 | + { |
812 | + png_error(png_ptr, "Missing IHDR before acTL"); | |
813 | + } | |
0a0f2c83 | 814 | + else if (png_ptr->mode & PNG_HAVE_IDAT) |
7472392b VM |
815 | + { |
816 | + png_warning(png_ptr, "Invalid acTL after IDAT skipped"); | |
817 | + png_crc_finish(png_ptr, length); | |
818 | + return; | |
819 | + } | |
0a0f2c83 | 820 | + else if (png_ptr->mode & PNG_HAVE_acTL) |
7472392b VM |
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); | |
0a0f2c83 | 841 | + if(didSet) |
7472392b VM |
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 | + | |
0a0f2c83 | 862 | + if (!(png_ptr->mode & PNG_HAVE_IHDR)) |
7472392b VM |
863 | + { |
864 | + png_error(png_ptr, "Missing IHDR before fcTL"); | |
865 | + } | |
0a0f2c83 | 866 | + else if (png_ptr->mode & PNG_HAVE_IDAT) |
7472392b VM |
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 | + } | |
0a0f2c83 | 875 | + else if (png_ptr->mode & PNG_HAVE_fcTL) |
7472392b VM |
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 | +{ | |
0a0f2c83 | 930 | + if((info_ptr->valid & PNG_INFO_acTL) && !(info_ptr->valid & PNG_INFO_fcTL)) |
7472392b VM |
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 | +} | |
0a0f2c83 | 970 | +#endif /* PNG_READ_APNG_SUPPORTED */ |
7472392b VM |
971 | + |
972 | #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED | |
973 | /* Utility function for png_handle_unknown; set up png_ptr::unknown_chunk */ | |
974 | static int | |
0a0f2c83 VM |
975 | @@ -4145,7 +4323,38 @@ |
976 | { | |
7472392b VM |
977 | uInt avail_in; |
978 | png_bytep buffer; | |
7472392b VM |
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 | + } | |
0a0f2c83 | 1004 | |
7472392b VM |
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); | |
0a0f2c83 | 1014 | @@ -4157,7 +4366,7 @@ |
7472392b VM |
1015 | if (png_ptr->chunk_name != png_IDAT) |
1016 | png_error(png_ptr, "Not enough image data"); | |
1017 | } | |
0a0f2c83 VM |
1018 | - |
1019 | +#endif /* PNG_READ_APNG_SUPPORTED */ | |
7472392b VM |
1020 | avail_in = png_ptr->IDAT_read_size; |
1021 | ||
0a0f2c83 VM |
1022 | if (avail_in > png_ptr->idat_size) |
1023 | @@ -4220,6 +4429,9 @@ | |
7472392b VM |
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"); | |
0a0f2c83 | 1033 | @@ -4658,4 +4870,80 @@ |
7472392b VM |
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); | |
0a0f2c83 | 1059 | + if (png_ptr->prev_row) |
7472392b VM |
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 | |
0a0f2c83 | 1069 | + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ |
7472392b | 1070 | + |
0a0f2c83 VM |
1071 | + /* Start of interlace block */ |
1072 | + const int png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; | |
7472392b VM |
1073 | + |
1074 | + /* Offset to next interlace block */ | |
0a0f2c83 | 1075 | + const int png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; |
7472392b VM |
1076 | + |
1077 | + /* Start of interlace block in the y direction */ | |
0a0f2c83 | 1078 | + const int png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; |
7472392b VM |
1079 | + |
1080 | + /* Offset to next interlace block in the y direction */ | |
0a0f2c83 | 1081 | + const int png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; |
7472392b | 1082 | + |
0a0f2c83 | 1083 | + if (png_ptr->interlaced) |
7472392b | 1084 | + { |
0a0f2c83 | 1085 | + if (!(png_ptr->transformations & PNG_INTERLACE)) |
7472392b VM |
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 | |
0a0f2c83 | 1097 | +#endif /* PNG_READ_INTERLACING_SUPPORTED */ |
7472392b VM |
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 | +} | |
0a0f2c83 VM |
1111 | +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ |
1112 | +#endif /* PNG_READ_APNG_SUPPORTED */ | |
7472392b | 1113 | #endif /* READ */ |
0a0f2c83 VM |
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); | |
7472392b | 1119 | |
0a0f2c83 | 1120 | info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width); |
7472392b | 1121 | + |
0a0f2c83 VM |
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 | } | |
7472392b | 1127 | |
0a0f2c83 VM |
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 | + | |
7472392b | 1299 | +#ifdef PNG_WRITE_APNG_SUPPORTED |
0a0f2c83 VM |
1300 | + png_uint_32 num_frames_to_write; |
1301 | + png_uint_32 num_frames_written; | |
7472392b | 1302 | +#endif |
0a0f2c83 VM |
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 | + } | |
7472392b | 1383 | +#ifdef PNG_WRITE_APNG_SUPPORTED |
0a0f2c83 VM |
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 | + } | |
7472392b | 1445 | + } |
0a0f2c83 VM |
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 | |
7472392b | 1537 | + |
0a0f2c83 VM |
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 */ | |
7472392b VM |
1558 | png_ptr->mode |= PNG_HAVE_IDAT; |
1559 | ||
1560 | png_ptr->zstream.next_out = data; | |
0a0f2c83 | 1561 | @@ -1051,7 +1065,17 @@ |
7472392b VM |
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 | + } | |
0a0f2c83 | 1574 | +#endif /* PNG_WRITE_APNG_SUPPORTED */ |
7472392b VM |
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; | |
0a0f2c83 | 1579 | @@ -1887,6 +1911,82 @@ |
7472392b VM |
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 | + | |
0a0f2c83 | 1594 | + if (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN) |
7472392b VM |
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 | +} | |
0a0f2c83 | 1657 | +#endif /* PNG_WRITE_APNG_SUPPORTED */ |
7472392b VM |
1658 | + |
1659 | /* Initializes the row writing capability of libpng */ | |
1660 | void /* PRIVATE */ | |
1661 | png_write_start_row(png_structrp png_ptr) | |
0a0f2c83 | 1662 | @@ -2781,4 +2881,39 @@ |
7472392b VM |
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) | |
0a0f2c83 | 1687 | + png_error(png_ptr, "width and/or height for a frame greater than" |
7472392b VM |
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 | +} | |
0a0f2c83 | 1700 | +#endif /* PNG_WRITE_APNG_SUPPORTED */ |
7472392b | 1701 | #endif /* WRITE */ |
0a0f2c83 VM |
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 |