]> git.pld-linux.org Git - packages/libpng.git/blame - libpng-apng.patch
- up to 1.4.1
[packages/libpng.git] / libpng-apng.patch
CommitLineData
b0807320
ER
1Index: pngread.c
2===================================================================
3--- pngread.c
4+++ pngread.c
9089cb0c 5@@ -300,6 +300,11 @@
b0807320 6 #ifdef PNG_READ_zTXt_SUPPORTED
00bce163 7 PNG_zTXt;
259182b6 8 #endif
b0807320 9+#ifdef PNG_READ_APNG_SUPPORTED
00bce163
AM
10+ PNG_acTL;
11+ PNG_fcTL;
12+ PNG_fdAT;
92006fdd 13+#endif
b0807320
ER
14 png_uint_32 length = png_read_chunk_header(png_ptr);
15 PNG_CONST png_bytep chunk_name = png_ptr->chunk_name;
00bce163 16
9089cb0c 17@@ -343,6 +348,9 @@
b0807320
ER
18 !(png_ptr->mode & PNG_HAVE_PLTE))
19 png_error(png_ptr, "Missing PLTE before IDAT");
259182b6 20
b0807320
ER
21+#ifdef PNG_READ_APNG_SUPPORTED
22+ png_have_info(png_ptr, info_ptr);
259182b6 23+#endif
b0807320
ER
24 png_ptr->idat_size = length;
25 png_ptr->mode |= PNG_HAVE_IDAT;
26 break;
9089cb0c 27@@ -415,12 +423,95 @@
b0807320
ER
28 else if (!png_memcmp(chunk_name, png_iTXt, 4))
29 png_handle_iTXt(png_ptr, info_ptr, length);
6df9a45f 30 #endif
92006fdd 31+#ifdef PNG_READ_APNG_SUPPORTED
b0807320
ER
32+ else if (!png_memcmp(chunk_name, png_acTL, 4))
33+ png_handle_acTL(png_ptr, info_ptr, length);
34+ else if (!png_memcmp(chunk_name, png_fcTL, 4))
35+ png_handle_fcTL(png_ptr, info_ptr, length);
36+ else if (!png_memcmp(chunk_name, png_fdAT, 4))
37+ png_handle_fdAT(png_ptr, info_ptr, length);
259182b6 38+#endif
b0807320
ER
39 else
40 png_handle_unknown(png_ptr, info_ptr, length);
41 }
42 }
43 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
44
45+#ifdef PNG_READ_APNG_SUPPORTED
46+void PNGAPI
47+png_read_frame_head(png_structp png_ptr, png_infop info_ptr)
48+{
49+ png_byte have_chunk_after_DAT; /* after IDAT or after fdAT */
50+
51+ png_debug(0, "Reading frame head");
52+
53+ if (!(png_ptr->mode & PNG_HAVE_acTL))
54+ png_error(png_ptr, "attempt to png_read_frame_head() but "
55+ "no acTL present");
56+
57+ /* do nothing for the main IDAT */
58+ if (png_ptr->num_frames_read == 0)
59+ return;
60+
61+ png_crc_finish(png_ptr, 0); /* CRC from last IDAT or fdAT chunk */
62+
63+ png_read_reset(png_ptr);
64+ png_ptr->mode &= ~PNG_HAVE_fcTL;
65+
66+ have_chunk_after_DAT = 0;
67+ for (;;)
68+ {
b0807320
ER
69+ PNG_IDAT;
70+ PNG_fdAT;
71+ PNG_fcTL;
b0807320
ER
72+ png_byte chunk_length[4];
73+ png_uint_32 length;
74+
75+ png_read_data(png_ptr, chunk_length, 4);
76+ length = png_get_uint_31(png_ptr, chunk_length);
77+
78+ png_reset_crc(png_ptr);
79+ png_crc_read(png_ptr, png_ptr->chunk_name, 4);
80+
81+ if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
82+ {
83+ /* discard trailing IDATs for the first frame */
84+ if (have_chunk_after_DAT || png_ptr->num_frames_read > 1)
85+ png_error(png_ptr, "png_read_frame_head(): out of place IDAT");
86+ png_crc_finish(png_ptr, length);
87+ }
88+ else if (!png_memcmp(png_ptr->chunk_name, png_fcTL, 4))
89+ {
90+ png_handle_fcTL(png_ptr, info_ptr, length);
91+ have_chunk_after_DAT = 1;
92+ }
93+ else if (!png_memcmp(png_ptr->chunk_name, png_fdAT, 4))
94+ {
95+ png_ensure_sequence_number(png_ptr, length);
96+
97+ /* discard trailing fdATs for frames other than the first */
98+ if (!have_chunk_after_DAT && png_ptr->num_frames_read > 1)
99+ png_crc_finish(png_ptr, length - 4);
100+ else if(png_ptr->mode & PNG_HAVE_fcTL)
101+ {
102+ png_ptr->idat_size = length - 4;
103+ png_ptr->mode |= PNG_HAVE_IDAT;
104+
105+ break;
106+ }
107+ else
108+ png_error(png_ptr, "png_read_frame_head(): out of place fdAT");
109+ }
110+ else
111+ {
112+ png_warning(png_ptr, "Skipped (ignored) a chunk "
113+ "between APNG chunks");
114+ png_crc_finish(png_ptr, length);
115+ }
116+ }
117+}
118+#endif /* PNG_READ_APNG_SUPPORTED */
259182b6 119+
b0807320
ER
120 /* Optional call to update the users info_ptr structure */
121 void PNGAPI
122 png_read_update_info(png_structp png_ptr, png_infop info_ptr)
9089cb0c 123@@ -461,6 +552,10 @@
b0807320
ER
124 png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
125 {
00bce163 126 PNG_IDAT;
b0807320 127+#ifdef PNG_READ_APNG_SUPPORTED
00bce163
AM
128+ PNG_fdAT;
129+ PNG_IEND;
259182b6 130+#endif
b0807320
ER
131 PNG_CONST int png_pass_dsp_mask[7] = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55,
132 0xff};
133 PNG_CONST int png_pass_mask[7] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff};
9089cb0c 134@@ -596,13 +691,39 @@
b0807320
ER
135 {
136 if (!(png_ptr->zstream.avail_in))
137 {
138- while (!png_ptr->idat_size)
139+ png_uint_32 bytes_to_skip = 0;
140+
141+ while (!png_ptr->idat_size || bytes_to_skip != 0)
142 {
143- png_crc_finish(png_ptr, 0);
144+ png_crc_finish(png_ptr, bytes_to_skip);
145+ bytes_to_skip = 0;
259182b6 146
b0807320
ER
147 png_ptr->idat_size = png_read_chunk_header(png_ptr);
148+#ifdef PNG_READ_APNG_SUPPORTED
149+ if (png_ptr->num_frames_read == 0)
150+ {
259182b6 151+#endif
b0807320
ER
152 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
153 png_error(png_ptr, "Not enough image data");
92006fdd 154+#ifdef PNG_READ_APNG_SUPPORTED
b0807320
ER
155+ }
156+ else
157+ {
158+ if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
159+ png_error(png_ptr, "Not enough image data");
160+ if (png_memcmp(png_ptr->chunk_name, png_fdAT, 4))
161+ {
162+ png_warning(png_ptr, "Skipped (ignored) a chunk "
163+ "between APNG chunks");
164+ bytes_to_skip = png_ptr->idat_size;
165+ continue;
166+ }
167+
168+ png_ensure_sequence_number(png_ptr, png_ptr->idat_size);
169+
170+ png_ptr->idat_size -= 4;
171+ }
259182b6 172+#endif
b0807320
ER
173 }
174 png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
175 png_ptr->zstream.next_in = png_ptr->zbuf;
9089cb0c 176@@ -620,6 +741,9 @@
00bce163 177 png_benign_error(png_ptr, "Extra compressed data");
b0807320
ER
178 png_ptr->mode |= PNG_AFTER_IDAT;
179 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
92006fdd 180+#ifdef PNG_READ_APNG_SUPPORTED
b0807320 181+ png_ptr->num_frames_read++;
580fd6fc 182+#endif
b0807320
ER
183 break;
184 }
185 if (ret != Z_OK)
9089cb0c 186@@ -875,6 +999,11 @@
b0807320 187 #ifdef PNG_READ_zTXt_SUPPORTED
00bce163 188 PNG_zTXt;
580fd6fc 189 #endif
580fd6fc 190+#ifdef PNG_READ_APNG_SUPPORTED
00bce163
AM
191+ PNG_acTL;
192+ PNG_fcTL;
193+ PNG_fdAT;
580fd6fc 194+#endif
b0807320
ER
195 png_uint_32 length = png_read_chunk_header(png_ptr);
196 PNG_CONST png_bytep chunk_name = png_ptr->chunk_name;
00bce163 197
9089cb0c 198@@ -974,6 +1103,14 @@
b0807320
ER
199 else if (!png_memcmp(chunk_name, png_iTXt, 4))
200 png_handle_iTXt(png_ptr, info_ptr, length);
580fd6fc 201 #endif
580fd6fc 202+#ifdef PNG_READ_APNG_SUPPORTED
b0807320
ER
203+ else if (!png_memcmp(chunk_name, png_acTL, 4))
204+ png_handle_acTL(png_ptr, info_ptr, length);
205+ else if (!png_memcmp(chunk_name, png_fcTL, 4))
206+ png_handle_fcTL(png_ptr, info_ptr, length);
207+ else if (!png_memcmp(chunk_name, png_fdAT, 4))
208+ png_handle_fdAT(png_ptr, info_ptr, length);
e4744232 209+#endif
b0807320
ER
210 else
211 png_handle_unknown(png_ptr, info_ptr, length);
212 } while (!(png_ptr->mode & PNG_HAVE_IEND));
213Index: pngget.c
214===================================================================
215--- pngget.c
216+++ pngget.c
580fd6fc
TP
217@@ -842,6 +842,167 @@
218 }
219 #endif
92006fdd 220
580fd6fc
TP
221+#ifdef PNG_APNG_SUPPORTED
222+png_uint_32 PNGAPI
223+png_get_acTL(png_structp png_ptr, png_infop info_ptr,
224+ png_uint_32 *num_frames, png_uint_32 *num_plays)
225+{
226+ png_debug1(1, "in %s retrieval function", "acTL");
227+
228+ if (png_ptr != NULL && info_ptr != NULL &&
229+ (info_ptr->valid & PNG_INFO_acTL) &&
230+ num_frames != NULL && num_plays != NULL)
231+ {
232+ *num_frames = info_ptr->num_frames;
233+ *num_plays = info_ptr->num_plays;
234+ return (1);
235+ }
236+
237+ return (0);
238+}
239+
240+png_uint_32 PNGAPI
241+png_get_num_frames(png_structp png_ptr, png_infop info_ptr)
242+{
243+ png_debug(1, "in png_get_num_frames()");
244+
245+ if (png_ptr != NULL && info_ptr != NULL)
246+ return (info_ptr->num_frames);
247+ return (0);
248+}
249+
250+png_uint_32 PNGAPI
251+png_get_num_plays(png_structp png_ptr, png_infop info_ptr)
252+{
253+ png_debug(1, "in png_get_num_plays()");
254+
255+ if (png_ptr != NULL && info_ptr != NULL)
256+ return (info_ptr->num_plays);
257+ return (0);
258+}
259+
260+png_uint_32 PNGAPI
261+png_get_next_frame_fcTL(png_structp png_ptr, png_infop info_ptr,
262+ png_uint_32 *width, png_uint_32 *height,
263+ png_uint_32 *x_offset, png_uint_32 *y_offset,
264+ png_uint_16 *delay_num, png_uint_16 *delay_den,
265+ png_byte *dispose_op, png_byte *blend_op)
266+{
267+ png_debug1(1, "in %s retrieval function", "fcTL");
268+
269+ if (png_ptr != NULL && info_ptr != NULL &&
270+ (info_ptr->valid & PNG_INFO_fcTL) &&
271+ width != NULL && height != NULL &&
272+ x_offset != NULL && x_offset != NULL &&
273+ delay_num != NULL && delay_den != NULL &&
00bce163 274+ dispose_op != NULL && blend_op != NULL)
580fd6fc
TP
275+ {
276+ *width = info_ptr->next_frame_width;
277+ *height = info_ptr->next_frame_height;
278+ *x_offset = info_ptr->next_frame_x_offset;
279+ *y_offset = info_ptr->next_frame_y_offset;
280+ *delay_num = info_ptr->next_frame_delay_num;
281+ *delay_den = info_ptr->next_frame_delay_den;
282+ *dispose_op = info_ptr->next_frame_dispose_op;
283+ *blend_op = info_ptr->next_frame_blend_op;
284+ return (1);
285+ }
286+
287+ return (0);
288+}
289+
290+png_uint_32 PNGAPI
291+png_get_next_frame_width(png_structp png_ptr, png_infop info_ptr)
292+{
293+ png_debug(1, "in png_get_next_frame_width()");
294+
295+ if (png_ptr != NULL && info_ptr != NULL)
296+ return (info_ptr->next_frame_width);
297+ return (0);
298+}
299+
300+png_uint_32 PNGAPI
301+png_get_next_frame_height(png_structp png_ptr, png_infop info_ptr)
302+{
303+ png_debug(1, "in png_get_next_frame_height()");
304+
305+ if (png_ptr != NULL && info_ptr != NULL)
306+ return (info_ptr->next_frame_height);
307+ return (0);
308+}
309+
310+png_uint_32 PNGAPI
311+png_get_next_frame_x_offset(png_structp png_ptr, png_infop info_ptr)
312+{
313+ png_debug(1, "in png_get_next_frame_x_offset()");
314+
315+ if (png_ptr != NULL && info_ptr != NULL)
316+ return (info_ptr->next_frame_x_offset);
317+ return (0);
318+}
319+
320+png_uint_32 PNGAPI
321+png_get_next_frame_y_offset(png_structp png_ptr, png_infop info_ptr)
322+{
323+ png_debug(1, "in png_get_next_frame_y_offset()");
324+
325+ if (png_ptr != NULL && info_ptr != NULL)
326+ return (info_ptr->next_frame_y_offset);
327+ return (0);
328+}
329+
330+png_uint_16 PNGAPI
331+png_get_next_frame_delay_num(png_structp png_ptr, png_infop info_ptr)
332+{
333+ png_debug(1, "in png_get_next_frame_delay_num()");
334+
335+ if (png_ptr != NULL && info_ptr != NULL)
336+ return (info_ptr->next_frame_delay_num);
337+ return (0);
338+}
339+
340+png_uint_16 PNGAPI
341+png_get_next_frame_delay_den(png_structp png_ptr, png_infop info_ptr)
342+{
343+ png_debug(1, "in png_get_next_frame_delay_den()");
344+
345+ if (png_ptr != NULL && info_ptr != NULL)
346+ return (info_ptr->next_frame_delay_den);
347+ return (0);
348+}
349+
350+png_byte PNGAPI
351+png_get_next_frame_dispose_op(png_structp png_ptr, png_infop info_ptr)
352+{
353+ png_debug(1, "in png_get_next_frame_dispose_op()");
354+
355+ if (png_ptr != NULL && info_ptr != NULL)
356+ return (info_ptr->next_frame_dispose_op);
357+ return (0);
358+}
359+
360+png_byte PNGAPI
361+png_get_next_frame_blend_op(png_structp png_ptr, png_infop info_ptr)
362+{
363+ png_debug(1, "in png_get_next_frame_blend_op()");
364+
365+ if (png_ptr != NULL && info_ptr != NULL)
366+ return (info_ptr->next_frame_blend_op);
367+ return (0);
368+}
369+
370+png_byte PNGAPI
371+png_get_first_frame_is_hidden(png_structp png_ptr, png_infop info_ptr)
372+{
373+ png_debug(1, "in png_first_frame_is_hidden()");
374+
375+ if (png_ptr != NULL)
376+ return (png_byte)(png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN);
377+
378+ return 0;
379+}
380+#endif /* PNG_APNG_SUPPORTED */
381+
382 #ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
383 png_uint_32 PNGAPI
384 png_get_unknown_chunks(png_structp png_ptr, png_infop info_ptr,
b0807320
ER
385Index: png.h
386===================================================================
387--- png.h
388+++ png.h
9089cb0c 389@@ -888,6 +888,19 @@
b0807320 390 png_fixed_point int_y_blue PNG_DEPSTRUCT;
259182b6 391 #endif
b0807320
ER
392
393+#ifdef PNG_APNG_SUPPORTED
394+ png_uint_32 num_frames; /* including default image */
395+ png_uint_32 num_plays;
396+ png_uint_32 next_frame_width;
397+ png_uint_32 next_frame_height;
398+ png_uint_32 next_frame_x_offset;
399+ png_uint_32 next_frame_y_offset;
400+ png_uint_16 next_frame_delay_num;
401+ png_uint_16 next_frame_delay_den;
402+ png_byte next_frame_dispose_op;
403+ png_byte next_frame_blend_op;
259182b6 404+#endif
b0807320
ER
405+
406 } png_info;
580fd6fc 407
b0807320 408 typedef png_info FAR * png_infop;
9089cb0c 409@@ -985,6 +998,10 @@
b0807320
ER
410 #define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */
411 #define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */
412 #define PNG_INFO_IDAT 0x8000L /* ESR, 1.0.6 */
413+#ifdef PNG_APNG_SUPPORTED
414+#define PNG_INFO_acTL 0x10000L
415+#define PNG_INFO_fcTL 0x20000L
416+#endif
417
418 /* This is used for the transformation routines, as some of them
419 * change these values for the row. It also should enable using
9089cb0c 420@@ -1026,6 +1043,10 @@
b0807320
ER
421 typedef void (PNGAPI *png_progressive_end_ptr) PNGARG((png_structp, png_infop));
422 typedef void (PNGAPI *png_progressive_row_ptr) PNGARG((png_structp, png_bytep,
423 png_uint_32, int));
424+#ifdef PNG_APNG_SUPPORTED
425+typedef void (PNGAPI *png_progressive_frame_ptr) PNGARG((png_structp,
426+ png_uint_32));
427+#endif
428 #endif
429
430 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
9089cb0c 431@@ -1445,6 +1466,39 @@
00bce163 432 png_uint_32 user_chunk_cache_max PNG_DEPSTRUCT;
b0807320 433 #endif
6df9a45f 434
b0807320
ER
435+#ifdef PNG_APNG_SUPPORTED
436+ png_uint_32 apng_flags;
437+ png_uint_32 next_seq_num; /* next fcTL/fdAT chunk sequence number */
438+ png_uint_32 first_frame_width;
439+ png_uint_32 first_frame_height;
440+
580fd6fc 441+#ifdef PNG_READ_APNG_SUPPORTED
b0807320
ER
442+ png_uint_32 num_frames_read; /* incremented after all image data of */
443+ /* a frame is read */
444+#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
445+ png_progressive_frame_ptr frame_info_fn; /* frame info read callback */
446+ png_progressive_frame_ptr frame_end_fn; /* frame data read callback */
447+#endif
448+#endif
449+
450+#ifdef PNG_WRITE_APNG_SUPPORTED
451+ png_uint_32 num_frames_to_write;
452+ png_uint_32 num_frames_written;
453+#endif
454+
455+/* For png_struct.apng_flags: */
456+#define PNG_FIRST_FRAME_HIDDEN 0x0001
457+
458+/* dispose_op flags from inside fcTL */
459+#define PNG_DISPOSE_OP_NONE 0x00
460+#define PNG_DISPOSE_OP_BACKGROUND 0x01
461+#define PNG_DISPOSE_OP_PREVIOUS 0x02
462+
463+/* blend_op flags from inside fcTL */
464+#define PNG_BLEND_OP_SOURCE 0x00
465+#define PNG_BLEND_OP_OVER 0x01
466+#endif /* PNG_APNG_SUPPORTED */
467+
468 /* New member added in libpng-1.0.25 and 1.2.17 */
469 #ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
470 /* Storage for unknown chunk that the library doesn't recognize. */
9089cb0c 471@@ -1773,6 +1827,18 @@
b0807320
ER
472 extern PNG_EXPORT(void,png_write_image) PNGARG((png_structp png_ptr,
473 png_bytepp image));
474
475+#ifdef PNG_WRITE_APNG_SUPPORTED
476+extern PNG_EXPORT (void,png_write_frame_head) PNGARG((png_structp png_ptr,
477+ png_infop png_info, png_bytepp row_pointers,
478+ png_uint_32 width, png_uint_32 height,
00bce163 479+ png_uint_32 x_offset, png_uint_32 y_offset,
b0807320
ER
480+ png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
481+ png_byte blend_op));
482+
483+extern PNG_EXPORT (void,png_write_frame_tail) PNGARG((png_structp png_ptr,
484+ png_infop png_info));
485+#endif
00bce163
AM
486+
487 /* Write the end of the PNG file. */
b0807320
ER
488 extern PNG_EXPORT(void,png_write_end) PNGARG((png_structp png_ptr,
489 png_infop info_ptr));
9089cb0c 490@@ -2017,6 +2083,11 @@
b0807320
ER
491 png_voidp progressive_ptr,
492 png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,
493 png_progressive_end_ptr end_fn));
494+#ifdef PNG_READ_APNG_SUPPORTED
495+extern PNG_EXPORT(void,png_set_progressive_frame_fn) PNGARG((png_structp png_ptr,
496+ png_progressive_frame_ptr frame_info_fn,
497+ png_progressive_frame_ptr frame_end_fn));
498+#endif
499
500 /* Returns the user pointer associated with the push read functions */
501 extern PNG_EXPORT(png_voidp,png_get_progressive_ptr)
9089cb0c 502@@ -2443,6 +2514,53 @@
b0807320
ER
503 #endif
504 #endif /* PNG_sCAL_SUPPORTED || PNG_WRITE_sCAL_SUPPORTED */
505
506+#ifdef PNG_APNG_SUPPORTED
507+extern PNG_EXPORT(png_uint_32,png_get_acTL) PNGARG((png_structp png_ptr,
508+ png_infop info_ptr, png_uint_32 *num_frames, png_uint_32 *num_plays));
509+extern PNG_EXPORT(png_uint_32,png_set_acTL) PNGARG((png_structp png_ptr,
510+ png_infop info_ptr, png_uint_32 num_frames, png_uint_32 num_plays));
511+extern PNG_EXPORT(png_uint_32,png_get_num_frames) PNGARG((png_structp png_ptr,
512+ png_infop info_ptr));
513+extern PNG_EXPORT(png_uint_32,png_get_num_plays)
514+ PNGARG((png_structp png_ptr, png_infop info_ptr));
515+
516+extern PNG_EXPORT(png_uint_32,png_get_next_frame_fcTL)
517+ PNGARG((png_structp png_ptr, png_infop info_ptr, png_uint_32 *width,
518+ png_uint_32 *height, png_uint_32 *x_offset, png_uint_32 *y_offset,
519+ png_uint_16 *delay_num, png_uint_16 *delay_den, png_byte *dispose_op,
520+ png_byte *blend_op));
521+extern PNG_EXPORT(png_uint_32,png_set_next_frame_fcTL)
522+ PNGARG((png_structp png_ptr, png_infop info_ptr, png_uint_32 width,
523+ png_uint_32 height, png_uint_32 x_offset, png_uint_32 y_offset,
524+ png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
525+ png_byte blend_op));
b0807320
ER
526+extern PNG_EXPORT(png_uint_32,png_get_next_frame_width)
527+ PNGARG((png_structp png_ptr, png_infop info_ptr));
528+extern PNG_EXPORT(png_uint_32,png_get_next_frame_height)
529+ PNGARG((png_structp png_ptr, png_infop info_ptr));
530+extern PNG_EXPORT(png_uint_32,png_get_next_frame_x_offset)
531+ PNGARG((png_structp png_ptr, png_infop info_ptr));
532+extern PNG_EXPORT(png_uint_32,png_get_next_frame_y_offset)
533+ PNGARG((png_structp png_ptr, png_infop info_ptr));
534+extern PNG_EXPORT(png_uint_16,png_get_next_frame_delay_num)
535+ PNGARG((png_structp png_ptr, png_infop info_ptr));
536+extern PNG_EXPORT(png_uint_16,png_get_next_frame_delay_den)
537+ PNGARG((png_structp png_ptr, png_infop info_ptr));
538+extern PNG_EXPORT(png_byte,png_get_next_frame_dispose_op)
539+ PNGARG((png_structp png_ptr, png_infop info_ptr));
540+extern PNG_EXPORT(png_byte,png_get_next_frame_blend_op)
541+ PNGARG((png_structp png_ptr, png_infop info_ptr));
542+extern PNG_EXPORT(png_byte,png_get_first_frame_is_hidden)
543+ PNGARG((png_structp png_ptr, png_infop info_ptr));
544+extern PNG_EXPORT(png_uint_32,png_set_first_frame_is_hidden)
545+ PNGARG((png_structp png_ptr, png_infop info_ptr, png_byte is_hidden));
546+#endif /* PNG_APNG_SUPPORTED */
547+
548+#ifdef PNG_READ_APNG_SUPPORTED
549+extern PNG_EXPORT(void,png_read_frame_head) PNGARG((png_structp png_ptr,
550+ png_infop info_ptr));
551+#endif
552+
553 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
554 /* Provide a list of chunks and how they are to be handled, if the built-in
555 handling or default unknown chunk handling is not desired. Any chunks not
00bce163
AM
556Index: pngpriv.h
557===================================================================
558--- pngpriv.h
559+++ pngpriv.h
560@@ -98,6 +98,10 @@
b0807320
ER
561 #define PNG_BACKGROUND_IS_GRAY 0x800
562 #define PNG_HAVE_PNG_SIGNATURE 0x1000
563 #define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */
564+#ifdef PNG_APNG_SUPPORTED
565+#define PNG_HAVE_acTL 0x4000
566+#define PNG_HAVE_fcTL 0x8000L
567+#endif
568
569 /* Flags for the transformations the PNG library does on the image data */
00bce163
AM
570 #define PNG_BGR 0x0001
571@@ -231,6 +235,11 @@
572 #define PNG_tIME PNG_CONST png_byte png_tIME[5] = {116, 73, 77, 69, '\0'}
573 #define PNG_tRNS PNG_CONST png_byte png_tRNS[5] = {116, 82, 78, 83, '\0'}
574 #define PNG_zTXt PNG_CONST png_byte png_zTXt[5] = {122, 84, 88, 116, '\0'}
b0807320 575+#ifdef PNG_APNG_SUPPORTED
00bce163
AM
576+#define PNG_acTL PNG_CONST png_byte png_acTL[5] = { 97, 99, 84, 76, '\0'}
577+#define PNG_fcTL PNG_CONST png_byte png_fcTL[5] = {102, 99, 84, 76, '\0'}
578+#define PNG_fdAT PNG_CONST png_byte png_fdAT[5] = {102, 100, 65, 84, '\0'}
b0807320
ER
579+#endif
580
b0807320 581
00bce163
AM
582 /* Inhibit C++ name-mangling for libpng functions but not for system calls. */
583@@ -468,6 +477,17 @@
b0807320
ER
584 #endif
585 #endif
586
587+#ifdef PNG_WRITE_APNG_SUPPORTED
588+PNG_EXTERN void png_write_acTL PNGARG((png_structp png_ptr,
589+ png_uint_32 num_frames, png_uint_32 num_plays));
590+
591+PNG_EXTERN void png_write_fcTL PNGARG((png_structp png_ptr,
592+ png_uint_32 width, png_uint_32 height,
593+ png_uint_32 x_offset, png_uint_32 y_offset,
594+ png_uint_16 delay_num, png_uint_16 delay_den,
595+ png_byte dispose_op, png_byte blend_op));
596+#endif
597+
598 /* Called when finished processing a row of data */
00bce163 599 PNG_EXTERN void png_write_finish_row PNGARG((png_structp png_ptr));
b0807320 600
00bce163 601@@ -520,6 +540,20 @@
b0807320 602 PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr,
00bce163 603 png_infop info_ptr));
b0807320
ER
604
605+#ifdef PNG_READ_APNG_SUPPORTED
606+/* Private, reset some things to become ready for reading next frame */
607+PNG_EXTERN void png_read_reset PNGARG((png_structp png_ptr));
608+PNG_EXTERN void png_read_reinit PNGARG((png_structp png_ptr,
609+ png_infop info_ptr));
610+PNG_EXTERN void png_progressive_read_reset PNGARG((png_structp png_ptr));
611+#endif
612+#ifdef PNG_WRITE_APNG_SUPPORTED
613+/* Private, reset some things to become ready for writing next frame */
614+PNG_EXTERN void png_write_reset PNGARG((png_structp png_ptr));
615+PNG_EXTERN void png_write_reinit PNGARG((png_structp png_ptr,
616+ png_infop info_ptr, png_uint_32 width, png_uint_32 height));
617+#endif
618+
619 /* These are the functions that do the transformations */
620 #ifdef PNG_READ_FILLER_SUPPORTED
621 PNG_EXTERN void png_do_read_filler PNGARG((png_row_infop row_info,
9089cb0c 622@@ -736,6 +770,25 @@
00bce163 623 png_uint_32 length));
b0807320
ER
624 #endif
625
626+#ifdef PNG_READ_APNG_SUPPORTED
627+PNG_EXTERN void png_handle_acTL PNGARG((png_structp png_ptr, png_infop info_ptr,
628+ png_uint_32 length));
629+PNG_EXTERN void png_handle_fcTL PNGARG((png_structp png_ptr, png_infop info_ptr,
630+ png_uint_32 length));
631+PNG_EXTERN void png_have_info PNGARG((png_structp png_ptr, png_infop info_ptr));
632+PNG_EXTERN void png_handle_fdAT PNGARG((png_structp png_ptr, png_infop info_ptr,
633+ png_uint_32 length));
634+PNG_EXTERN void png_ensure_sequence_number PNGARG((png_structp png_ptr,
635+ png_uint_32 length));
636+#endif
9089cb0c
AM
637+#ifdef PNG_APNG_SUPPORTED
638+PNG_EXTERN void png_ensure_fcTL_is_valid PNGARG((png_structp png_ptr,
639+ png_uint_32 width, png_uint_32 height,
640+ png_uint_32 x_offset, png_uint_32 y_offset,
641+ png_uint_16 delay_num, png_uint_16 delay_den,
642+ png_byte dispose_op, png_byte blend_op));
643+#endif
b0807320
ER
644+
645 PNG_EXTERN void png_handle_unknown PNGARG((png_structp png_ptr,
00bce163 646 png_infop info_ptr, png_uint_32 length));
b0807320
ER
647
648Index: pngwrite.c
649===================================================================
650--- pngwrite.c
651+++ pngwrite.c
9089cb0c 652@@ -57,6 +57,10 @@
b0807320
ER
653 /* The rest of these check to see if the valid field has the appropriate
654 * flag set, and if it does, writes the chunk.
655 */
656+#ifdef PNG_WRITE_APNG_SUPPORTED
657+ if (info_ptr->valid & PNG_INFO_acTL)
658+ png_write_acTL(png_ptr, info_ptr->num_frames, info_ptr->num_plays);
659+#endif
660 #ifdef PNG_WRITE_gAMA_SUPPORTED
661 if (info_ptr->valid & PNG_INFO_gAMA)
662 {
9089cb0c 663@@ -319,6 +323,10 @@
b0807320
ER
664 return;
665 if (!(png_ptr->mode & PNG_HAVE_IDAT))
666 png_error(png_ptr, "No IDATs written into file");
667+#ifdef PNG_WRITE_APNG_SUPPORTED
668+ if (png_ptr->num_frames_written != png_ptr->num_frames_to_write)
669+ png_error(png_ptr, "Not enough frames written");
670+#endif
671
672 /* See if user wants us to write information chunks */
673 if (info_ptr != NULL)
9089cb0c 674@@ -1454,4 +1462,39 @@
b0807320
ER
675 params = params;
676 }
677 #endif
678+
679+#ifdef PNG_WRITE_APNG_SUPPORTED
680+void PNGAPI
681+png_write_frame_head(png_structp png_ptr, png_infop info_ptr,
682+ png_bytepp row_pointers, png_uint_32 width, png_uint_32 height,
683+ png_uint_32 x_offset, png_uint_32 y_offset,
684+ png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
685+ png_byte blend_op)
686+{
687+ png_debug(1, "in png_write_frame_head");
688+
689+ /* there is a chance this has been set after png_write_info was called,
690+ * so it would be set but not written. is there a way to be sure? */
691+ if (!(info_ptr->valid & PNG_INFO_acTL))
692+ png_error(png_ptr, "png_write_frame_head(): acTL not set");
693+
694+ png_write_reset(png_ptr);
695+
696+ png_write_reinit(png_ptr, info_ptr, width, height);
697+
698+ if ( !(png_ptr->num_frames_written == 0 &&
699+ (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN) ) )
700+ png_write_fcTL(png_ptr, width, height, x_offset, y_offset,
701+ delay_num, delay_den, dispose_op, blend_op);
702+}
703+
704+void PNGAPI
705+png_write_frame_tail(png_structp png_ptr, png_infop png_info)
706+{
707+ png_debug(1, "in png_write_frame_tail");
708+
709+ png_ptr->num_frames_written++;
710+}
711+#endif /* PNG_WRITE_APNG_SUPPORTED */
712+
713 #endif /* PNG_WRITE_SUPPORTED */
714Index: pngconf.h
715===================================================================
716--- pngconf.h
717+++ pngconf.h
9089cb0c 718@@ -869,6 +869,10 @@
00bce163
AM
719 # define PNG_READ_tRNS_SUPPORTED
720 # define PNG_tRNS_SUPPORTED
b0807320
ER
721 #endif
722+#ifndef PNG_NO_READ_APNG
723+# define PNG_READ_APNG_SUPPORTED
724+# define PNG_APNG_SUPPORTED
725+#endif
00bce163
AM
726 #ifndef PNG_NO_READ_zTXt
727 # define PNG_READ_zTXt_SUPPORTED
728 # define PNG_zTXt_SUPPORTED
9089cb0c 729@@ -1028,6 +1032,14 @@
b0807320
ER
730 # define PNG_TEXT_SUPPORTED
731 # endif
732 #endif
733+#ifndef PNG_NO_WRITE_APNG
734+# ifndef PNG_WRITE_APNG_SUPPORTED
735+# define PNG_WRITE_APNG_SUPPORTED
736+# endif
737+# ifndef PNG_APNG_SUPPORTED
738+# define PNG_APNG_SUPPORTED
739+# endif
740+#endif
741
742 #ifdef PNG_WRITE_tIME_SUPPORTED
743 # ifndef PNG_NO_CONVERT_tIME
744Index: pngpread.c
745===================================================================
746--- pngpread.c
747+++ pngpread.c
00bce163 748@@ -205,6 +205,11 @@
b0807320 749 #ifdef PNG_READ_zTXt_SUPPORTED
00bce163 750 PNG_zTXt;
b0807320
ER
751 #endif
752+#ifdef PNG_READ_APNG_SUPPORTED
00bce163
AM
753+ PNG_acTL;
754+ PNG_fcTL;
755+ PNG_fdAT;
b0807320 756+#endif
b0807320
ER
757
758 /* First we make sure we have enough data for the 4 byte chunk name
00bce163
AM
759 * and the 4 byte chunk length before proceeding with decoding the
760@@ -230,6 +235,103 @@
b0807320
ER
761 png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
762 }
763
764+#ifdef PNG_READ_APNG_SUPPORTED
765+ if (png_ptr->num_frames_read > 0 &&
766+ png_ptr->num_frames_read < info_ptr->num_frames)
767+ {
768+ if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
769+ {
770+ /* Discard trailing IDATs for the first frame */
771+ if (png_ptr->mode & PNG_HAVE_fcTL || png_ptr->num_frames_read > 1)
772+ png_error(png_ptr, "out of place IDAT");
773+
774+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
775+ {
776+ png_push_save_buffer(png_ptr);
777+ return;
778+ }
779+ png_push_crc_skip(png_ptr, png_ptr->push_length);
780+ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
781+ return;
782+ }
783+ else if (!png_memcmp(png_ptr->chunk_name, png_fdAT, 4))
784+ {
785+ if (png_ptr->buffer_size < 4)
259182b6
ER
786+ {
787+ png_push_save_buffer(png_ptr);
788+ return;
789+ }
790+ png_ensure_sequence_number(png_ptr, 4);
791+
792+ if (!(png_ptr->mode & PNG_HAVE_fcTL))
793+ {
92006fdd 794+ /* Discard trailing fdATs for frames other than the first */
259182b6
ER
795+ if (png_ptr->num_frames_read < 2)
796+ png_error(png_ptr, "out of place fdAT");
797+
798+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
799+ {
800+ png_push_save_buffer(png_ptr);
801+ return;
802+ }
803+ png_push_crc_skip(png_ptr, png_ptr->push_length);
804+ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
805+ return;
806+ }
807+ else
808+ {
809+ /* frame data follows */
810+ png_ptr->idat_size = png_ptr->push_length - 4;
811+ png_ptr->mode |= PNG_HAVE_IDAT;
812+ png_ptr->process_mode = PNG_READ_IDAT_MODE;
813+
814+ return;
815+ }
816+ }
817+ else if(!png_memcmp(png_ptr->chunk_name, png_fcTL, 4))
818+ {
819+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
820+ {
821+ png_push_save_buffer(png_ptr);
822+ return;
823+ }
824+
825+ png_read_reset(png_ptr);
826+ png_ptr->mode &= ~PNG_HAVE_fcTL;
827+
828+ png_handle_fcTL(png_ptr, info_ptr, png_ptr->push_length);
829+
830+ if (!(png_ptr->mode & PNG_HAVE_fcTL))
831+ png_error(png_ptr, "missing required fcTL chunk");
832+
833+ png_read_reinit(png_ptr, info_ptr);
834+ png_progressive_read_reset(png_ptr);
835+
836+ if (png_ptr->frame_info_fn != NULL)
837+ (*(png_ptr->frame_info_fn))(png_ptr, png_ptr->num_frames_read);
838+
839+ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
840+
841+ return;
842+ }
843+ else
844+ {
845+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
846+ {
847+ png_push_save_buffer(png_ptr);
848+ return;
849+ }
850+ png_warning(png_ptr, "Skipped (ignored) a chunk "
851+ "between APNG chunks");
852+ png_push_crc_skip(png_ptr, png_ptr->push_length);
853+ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
854+ return;
855+ }
856+
857+ return;
858+ }
859+#endif /* PNG_READ_APNG_SUPPORTED */
b0807320 860+
259182b6 861 if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
6df9a45f 862 if (png_ptr->mode & PNG_AFTER_IDAT)
259182b6 863 png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
00bce163
AM
864@@ -325,6 +427,9 @@
865 png_benign_error(png_ptr, "Too many IDATs found");
259182b6
ER
866 }
867
580fd6fc 868+#ifdef PNG_READ_APNG_SUPPORTED
259182b6
ER
869+ png_have_info(png_ptr, info_ptr);
870+#endif
871 png_ptr->idat_size = png_ptr->push_length;
872 png_ptr->mode |= PNG_HAVE_IDAT;
873 png_ptr->process_mode = PNG_READ_IDAT_MODE;
9089cb0c 874@@ -557,6 +662,38 @@
259182b6 875 }
6df9a45f 876
259182b6 877 #endif
580fd6fc 878+#ifdef PNG_READ_APNG_SUPPORTED
259182b6
ER
879+ else if (!png_memcmp(png_ptr->chunk_name, png_acTL, 4))
880+ {
881+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
882+ {
883+ png_push_save_buffer(png_ptr);
884+ return;
885+ }
92006fdd 886+
259182b6
ER
887+ png_handle_acTL(png_ptr, info_ptr, png_ptr->push_length);
888+ }
889+ else if (!png_memcmp(png_ptr->chunk_name, png_fcTL, 4))
890+ {
891+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
892+ {
893+ png_push_save_buffer(png_ptr);
894+ return;
895+ }
92006fdd 896+
259182b6
ER
897+ png_handle_fcTL(png_ptr, info_ptr, png_ptr->push_length);
898+ }
899+ else if (!png_memcmp(png_ptr->chunk_name, png_fdAT, 4))
900+ {
901+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
902+ {
903+ png_push_save_buffer(png_ptr);
904+ return;
905+ }
92006fdd 906+
259182b6
ER
907+ png_handle_fdAT(png_ptr, info_ptr, png_ptr->push_length);
908+ }
909+#endif /* PNG_READ_APNG_SUPPORTED */
910 else
911 {
912 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
9089cb0c 913@@ -736,11 +873,15 @@
259182b6
ER
914 png_push_read_IDAT(png_structp png_ptr)
915 {
00bce163 916 PNG_IDAT;
580fd6fc 917+#ifdef PNG_READ_APNG_SUPPORTED
259182b6
ER
918+ PNG_fdAT;
919+ PNG_IEND;
259182b6
ER
920+#endif
921 if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER))
922 {
923 png_byte chunk_length[4];
924
925- if (png_ptr->buffer_size < 8)
926+ if (png_ptr->buffer_size < 12)
927 {
928 png_push_save_buffer(png_ptr);
929 return;
9089cb0c 930@@ -752,15 +893,62 @@
259182b6
ER
931 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
932 png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
933
b0807320 934- if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
580fd6fc 935+#ifdef PNG_READ_APNG_SUPPORTED
00bce163 936+ if (png_memcmp(png_ptr->chunk_name, png_fdAT, 4)
b0807320
ER
937+ && png_ptr->num_frames_read > 0)
938+ {
939+ if (png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)
940+ {
941+ png_ptr->process_mode = PNG_READ_CHUNK_MODE;
942+ if (png_ptr->frame_end_fn != NULL)
943+ (*(png_ptr->frame_end_fn))(png_ptr, png_ptr->num_frames_read);
944+ png_ptr->num_frames_read++;
945+ return;
946+ }
947+ else
948+ {
949+ if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
580fd6fc 950+ png_error(png_ptr, "Not enough image data");
b0807320
ER
951+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
952+ {
953+ png_push_save_buffer(png_ptr);
954+ return;
955+ }
956+ png_warning(png_ptr, "Skipping (ignoring) a chunk between "
957+ "APNG chunks");
958+ png_crc_finish(png_ptr, png_ptr->push_length);
959+ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
960+ return;
961+ }
962+ }
963+ else
964+#endif
965+ if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)
580fd6fc 966+#ifdef PNG_READ_APNG_SUPPORTED
b0807320 967+ && (png_ptr->num_frames_read == 0)
580fd6fc 968+#endif
b0807320
ER
969+ )
970 {
971 png_ptr->process_mode = PNG_READ_CHUNK_MODE;
972 if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
973 png_error(png_ptr, "Not enough compressed data");
580fd6fc 974+#ifdef PNG_READ_APNG_SUPPORTED
b0807320
ER
975+ if (png_ptr->frame_end_fn != NULL)
976+ (*(png_ptr->frame_end_fn))(png_ptr, png_ptr->num_frames_read);
580fd6fc
TP
977+ png_ptr->num_frames_read++;
978+#endif
b0807320 979 return;
580fd6fc 980 }
b0807320
ER
981
982 png_ptr->idat_size = png_ptr->push_length;
983+
580fd6fc 984+#ifdef PNG_READ_APNG_SUPPORTED
b0807320
ER
985+ if (png_ptr->num_frames_read > 0)
986+ {
987+ png_ensure_sequence_number(png_ptr, 4);
988+ png_ptr->idat_size -= 4;
989+ }
580fd6fc 990+#endif
b0807320
ER
991 }
992 if (png_ptr->idat_size && png_ptr->save_buffer_size)
993 {
9089cb0c 994@@ -1716,6 +1904,17 @@
b0807320
ER
995 png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
996 }
997
580fd6fc 998+#ifdef PNG_READ_APNG_SUPPORTED
b0807320
ER
999+void PNGAPI
1000+png_set_progressive_frame_fn(png_structp png_ptr,
1001+ png_progressive_frame_ptr frame_info_fn,
1002+ png_progressive_frame_ptr frame_end_fn)
1003+{
1004+ png_ptr->frame_info_fn = frame_info_fn;
1005+ png_ptr->frame_end_fn = frame_end_fn;
1006+}
580fd6fc 1007+#endif
b0807320
ER
1008+
1009 png_voidp PNGAPI
1010 png_get_progressive_ptr(png_structp png_ptr)
1011 {
1012Index: pngset.c
1013===================================================================
1014--- pngset.c
1015+++ pngset.c
00bce163
AM
1016@@ -260,6 +260,11 @@
1017 info_ptr->rowbytes = 0;
b0807320
ER
1018 else
1019 info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width);
1020+
1021+#ifdef PNG_APNG_SUPPORTED
1022+ /* for non-animated png. this may be overritten from an acTL chunk later */
1023+ info_ptr->num_frames = 1;
1024+#endif
1025 }
1026
1027 #ifdef PNG_oFFs_SUPPORTED
00bce163 1028@@ -932,6 +937,142 @@
b0807320
ER
1029 }
1030 #endif /* PNG_sPLT_SUPPORTED */
1031
1032+#ifdef PNG_APNG_SUPPORTED
1033+png_uint_32 PNGAPI
1034+png_set_acTL(png_structp png_ptr, png_infop info_ptr,
1035+ png_uint_32 num_frames, png_uint_32 num_plays)
1036+{
1037+ png_debug1(1, "in %s storage function", "acTL");
1038+
1039+ if (png_ptr == NULL || info_ptr == NULL)
1040+ {
1041+ png_warning(png_ptr,
1042+ "Call to png_set_acTL() with NULL png_ptr "
1043+ "or info_ptr ignored");
1044+ return (0);
1045+ }
1046+ if (num_frames == 0)
1047+ {
1048+ png_warning(png_ptr,
1049+ "Ignoring attempt to set acTL with num_frames zero");
1050+ return (0);
1051+ }
1052+ if (num_frames > PNG_UINT_31_MAX)
1053+ {
1054+ png_warning(png_ptr,
1055+ "Ignoring attempt to set acTL with num_frames > 2^31-1");
1056+ return (0);
1057+ }
1058+ if (num_plays > PNG_UINT_31_MAX)
1059+ {
1060+ png_warning(png_ptr,
1061+ "Ignoring attempt to set acTL with num_plays "
1062+ "> 2^31-1");
1063+ return (0);
1064+ }
1065+
1066+ info_ptr->num_frames = num_frames;
1067+ info_ptr->num_plays = num_plays;
1068+
1069+ info_ptr->valid |= PNG_INFO_acTL;
1070+
1071+ return (1);
1072+}
1073+
1074+/* delay_num and delay_den can hold any 16-bit values including zero */
1075+png_uint_32 PNGAPI
1076+png_set_next_frame_fcTL(png_structp png_ptr, png_infop info_ptr,
1077+ png_uint_32 width, png_uint_32 height,
1078+ png_uint_32 x_offset, png_uint_32 y_offset,
1079+ png_uint_16 delay_num, png_uint_16 delay_den,
1080+ png_byte dispose_op, png_byte blend_op)
1081+{
1082+ png_debug1(1, "in %s storage function", "fcTL");
1083+
1084+ if (png_ptr == NULL || info_ptr == NULL)
1085+ {
1086+ png_warning(png_ptr,
1087+ "Call to png_set_fcTL() with NULL png_ptr or info_ptr "
1088+ "ignored");
1089+ return (0);
1090+ }
1091+
1092+ png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset,
1093+ delay_num, delay_den, dispose_op, blend_op);
1094+
1095+ if (blend_op == PNG_BLEND_OP_OVER)
1096+ {
1097+ if (!(png_ptr->color_type & PNG_COLOR_MASK_ALPHA) &&
1098+ !(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)))
1099+ {
1100+ png_warning(png_ptr, "PNG_BLEND_OP_OVER is meaningless "
1101+ "and wasteful for opaque images, ignored");
1102+ blend_op = PNG_BLEND_OP_SOURCE;
1103+ }
1104+ }
1105+
1106+ info_ptr->next_frame_width = width;
1107+ info_ptr->next_frame_height = height;
1108+ info_ptr->next_frame_x_offset = x_offset;
1109+ info_ptr->next_frame_y_offset = y_offset;
1110+ info_ptr->next_frame_delay_num = delay_num;
1111+ info_ptr->next_frame_delay_den = delay_den;
1112+ info_ptr->next_frame_dispose_op = dispose_op;
1113+ info_ptr->next_frame_blend_op = blend_op;
1114+
1115+ info_ptr->valid |= PNG_INFO_fcTL;
1116+
1117+ return (1);
1118+}
1119+
1120+void /* PRIVATE */
1121+png_ensure_fcTL_is_valid(png_structp png_ptr,
1122+ png_uint_32 width, png_uint_32 height,
1123+ png_uint_32 x_offset, png_uint_32 y_offset,
1124+ png_uint_16 delay_num, png_uint_16 delay_den,
1125+ png_byte dispose_op, png_byte blend_op)
1126+{
1127+ if (width + x_offset > png_ptr->first_frame_width ||
1128+ height + y_offset > png_ptr->first_frame_height)
1129+ png_error(png_ptr, "dimensions of a frame are greater than"
1130+ "the ones in IHDR");
1131+ if (width > PNG_UINT_31_MAX)
1132+ png_error(png_ptr, "invalid width in fcTL (> 2^31-1)");
1133+ if (height > PNG_UINT_31_MAX)
1134+ png_error(png_ptr, "invalid height in fcTL (> 2^31-1)");
1135+ if (x_offset > PNG_UINT_31_MAX)
1136+ png_error(png_ptr, "invalid x_offset in fcTL (> 2^31-1)");
1137+ if (y_offset > PNG_UINT_31_MAX)
1138+ png_error(png_ptr, "invalid y_offset in fcTL (> 2^31-1)");
1139+
1140+ if (dispose_op != PNG_DISPOSE_OP_NONE &&
00bce163
AM
1141+ dispose_op != PNG_DISPOSE_OP_BACKGROUND &&
1142+ dispose_op != PNG_DISPOSE_OP_PREVIOUS)
b0807320
ER
1143+ png_error(png_ptr, "invalid dispose_op in fcTL");
1144+
1145+ if (blend_op != PNG_BLEND_OP_SOURCE &&
00bce163 1146+ blend_op != PNG_BLEND_OP_OVER)
b0807320
ER
1147+ png_error(png_ptr, "invalid blend_op in fcTL");
1148+}
1149+
1150+png_uint_32 PNGAPI
1151+png_set_first_frame_is_hidden(png_structp png_ptr, png_infop info_ptr,
1152+ png_byte is_hidden)
1153+{
1154+ png_debug(1, "in png_first_frame_is_hidden()");
1155+
1156+ if (png_ptr == NULL)
1157+ return 0;
1158+
1159+ if(is_hidden)
1160+ png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN;
1161+ else
1162+ png_ptr->apng_flags &= ~PNG_FIRST_FRAME_HIDDEN;
1163+
1164+ return 1;
1165+}
1166+#endif /* PNG_APNG_SUPPORTED */
1167+
00bce163 1168 #ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
b0807320
ER
1169 void PNGAPI
1170 png_set_unknown_chunks(png_structp png_ptr,
1171Index: pngrutil.c
1172===================================================================
1173--- pngrutil.c
1174+++ pngrutil.c
9089cb0c 1175@@ -434,6 +434,11 @@
259182b6
ER
1176 filter_type = buf[11];
1177 interlace_type = buf[12];
1178
580fd6fc 1179+#ifdef PNG_READ_APNG_SUPPORTED
259182b6
ER
1180+ png_ptr->first_frame_width = width;
1181+ png_ptr->first_frame_height = height;
1182+#endif
1183+
6df9a45f 1184 /* Set internal variables */
259182b6
ER
1185 png_ptr->width = width;
1186 png_ptr->height = height;
9089cb0c 1187@@ -2318,6 +2323,168 @@
259182b6
ER
1188 }
1189 #endif
1190
580fd6fc 1191+#ifdef PNG_READ_APNG_SUPPORTED
259182b6
ER
1192+void /* PRIVATE */
1193+png_handle_acTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1194+{
1195+ png_byte data[8];
1196+ png_uint_32 num_frames;
1197+ png_uint_32 num_plays;
1198+ png_uint_32 didSet;
1199+
6df9a45f 1200+ png_debug(1, "in png_handle_acTL");
259182b6
ER
1201+
1202+ if (!(png_ptr->mode & PNG_HAVE_IHDR))
1203+ {
1204+ png_error(png_ptr, "Missing IHDR before acTL");
1205+ }
1206+ else if (png_ptr->mode & PNG_HAVE_IDAT)
1207+ {
1208+ png_warning(png_ptr, "Invalid acTL after IDAT skipped");
1209+ png_crc_finish(png_ptr, length);
1210+ return;
1211+ }
1212+ else if (png_ptr->mode & PNG_HAVE_acTL)
1213+ {
1214+ png_warning(png_ptr, "Duplicate acTL skipped");
1215+ png_crc_finish(png_ptr, length);
1216+ return;
1217+ }
1218+ else if (length != 8)
1219+ {
1220+ png_warning(png_ptr, "acTL with invalid length skipped");
1221+ png_crc_finish(png_ptr, length);
1222+ return;
1223+ }
1224+
1225+ png_crc_read(png_ptr, data, 8);
1226+ png_crc_finish(png_ptr, 0);
1227+
1228+ num_frames = png_get_uint_31(png_ptr, data);
1229+ num_plays = png_get_uint_31(png_ptr, data + 4);
1230+
1231+ /* the set function will do error checking on num_frames */
1232+ didSet = png_set_acTL(png_ptr, info_ptr, num_frames, num_plays);
1233+ if(didSet)
1234+ png_ptr->mode |= PNG_HAVE_acTL;
1235+}
1236+
1237+void /* PRIVATE */
1238+png_handle_fcTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1239+{
1240+ png_byte data[22];
1241+ png_uint_32 width;
1242+ png_uint_32 height;
1243+ png_uint_32 x_offset;
1244+ png_uint_32 y_offset;
1245+ png_uint_16 delay_num;
1246+ png_uint_16 delay_den;
1247+ png_byte dispose_op;
1248+ png_byte blend_op;
1249+
6df9a45f 1250+ png_debug(1, "in png_handle_fcTL");
259182b6 1251+
9089cb0c
AM
1252+ png_ensure_sequence_number(png_ptr, length);
1253+
259182b6
ER
1254+ if (!(png_ptr->mode & PNG_HAVE_IHDR))
1255+ {
1256+ png_error(png_ptr, "Missing IHDR before fcTL");
1257+ }
1258+ else if (png_ptr->mode & PNG_HAVE_IDAT)
1259+ {
1260+ /* for any frames other then the first this message may be misleading,
1261+ * but correct. PNG_HAVE_IDAT is unset before the frame head is read
1262+ * i can't think of a better message */
1263+ png_warning(png_ptr, "Invalid fcTL after IDAT skipped");
9089cb0c 1264+ png_crc_finish(png_ptr, length-4);
259182b6
ER
1265+ return;
1266+ }
1267+ else if (png_ptr->mode & PNG_HAVE_fcTL)
1268+ {
1269+ png_warning(png_ptr, "Duplicate fcTL within one frame skipped");
9089cb0c 1270+ png_crc_finish(png_ptr, length-4);
259182b6
ER
1271+ return;
1272+ }
1273+ else if (length != 26)
1274+ {
1275+ png_warning(png_ptr, "fcTL with invalid length skipped");
9089cb0c 1276+ png_crc_finish(png_ptr, length-4);
259182b6
ER
1277+ return;
1278+ }
1279+
259182b6
ER
1280+ png_crc_read(png_ptr, data, 22);
1281+ png_crc_finish(png_ptr, 0);
1282+
1283+ width = png_get_uint_31(png_ptr, data);
1284+ height = png_get_uint_31(png_ptr, data + 4);
1285+ x_offset = png_get_uint_31(png_ptr, data + 8);
1286+ y_offset = png_get_uint_31(png_ptr, data + 12);
1287+ delay_num = png_get_uint_16(data + 16);
1288+ delay_den = png_get_uint_16(data + 18);
1289+ dispose_op = data[20];
1290+ blend_op = data[21];
1291+
1292+ if (png_ptr->num_frames_read == 0 && (x_offset != 0 || y_offset != 0))
1293+ png_error(png_ptr, "fcTL for the first frame must have zero offset");
1294+ if (png_ptr->num_frames_read == 0 &&
1295+ (width != info_ptr->width || height != info_ptr->height))
1296+ png_error(png_ptr, "size in first frame's fcTL must match "
1297+ "the size in IHDR");
1298+
1299+ /* the set function will do more error checking */
1300+ png_set_next_frame_fcTL(png_ptr, info_ptr, width, height,
1301+ x_offset, y_offset, delay_num, delay_den,
1302+ dispose_op, blend_op);
1303+
1304+ png_read_reinit(png_ptr, info_ptr);
1305+
1306+ png_ptr->mode |= PNG_HAVE_fcTL;
1307+}
1308+
1309+void /* PRIVATE */
b0807320 1310+png_have_info(png_structp png_ptr, png_infop info_ptr)
259182b6 1311+{
b0807320
ER
1312+ if((info_ptr->valid & PNG_INFO_acTL) && !(info_ptr->valid & PNG_INFO_fcTL))
1313+ {
1314+ png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN;
1315+ info_ptr->num_frames++;
1316+ }
1317+}
580fd6fc 1318+
b0807320
ER
1319+void /* PRIVATE */
1320+png_handle_fdAT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1321+{
1322+ png_ensure_sequence_number(png_ptr, length);
1323+
1324+ /* This function is only called from png_read_end(), png_read_info(),
1325+ * and png_push_read_chunk() which means that:
1326+ * - the user doesn't want to read this frame
1327+ * - or this is an out-of-place fdAT
1328+ * in either case it is safe to ignore the chunk with a warning */
1329+ png_warning(png_ptr, "ignoring fdAT chunk");
1330+ png_crc_finish(png_ptr, length - 4);
259182b6
ER
1331+}
1332+
b0807320
ER
1333+void /* PRIVATE */
1334+png_ensure_sequence_number(png_structp png_ptr, png_uint_32 length)
259182b6 1335+{
b0807320
ER
1336+ png_byte data[4];
1337+ png_uint_32 sequence_number;
259182b6 1338+
b0807320
ER
1339+ if (length < 4)
1340+ png_error(png_ptr, "invalid fcTL or fdAT chunk found");
259182b6 1341+
b0807320
ER
1342+ png_crc_read(png_ptr, data, 4);
1343+ sequence_number = png_get_uint_31(png_ptr, data);
259182b6 1344+
b0807320
ER
1345+ if (sequence_number != png_ptr->next_seq_num)
1346+ png_error(png_ptr, "fcTL or fdAT chunk with out-of-order sequence "
1347+ "number found");
1348+
1349+ png_ptr->next_seq_num++;
259182b6 1350+}
b0807320 1351+#endif /* PNG_READ_APNG_SUPPORTED */
259182b6 1352+
b0807320
ER
1353 /* This function is called when we haven't found a handler for a
1354 chunk. If there isn't a problem with the chunk itself (ie bad
1355 chunk name, CRC, or a critical chunk), the chunk is silently ignored
9089cb0c 1356@@ -3353,4 +3520,73 @@
580fd6fc 1357
b0807320 1358 png_ptr->flags |= PNG_FLAG_ROW_INIT;
580fd6fc 1359 }
259182b6 1360+
b0807320
ER
1361+#ifdef PNG_READ_APNG_SUPPORTED
1362+/* This function is to be called after the main IDAT set has been read and
1363+ * before a new IDAT is read. It resets some parts of png_ptr
1364+ * to make them usable by the read functions again */
1365+void /* PRIVATE */
1366+png_read_reset(png_structp png_ptr)
259182b6 1367+{
b0807320
ER
1368+ png_ptr->mode &= ~PNG_HAVE_IDAT;
1369+ png_ptr->mode &= ~PNG_AFTER_IDAT;
1370+ png_ptr->row_number = 0;
1371+ png_ptr->pass = 0;
1372+ png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
259182b6
ER
1373+}
1374+
b0807320
ER
1375+void /* PRIVATE */
1376+png_read_reinit(png_structp png_ptr, png_infop info_ptr)
259182b6 1377+{
b0807320
ER
1378+ png_ptr->width = info_ptr->next_frame_width;
1379+ png_ptr->height = info_ptr->next_frame_height;
1380+ png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->width);
1381+ if (png_ptr->prev_row)
00bce163 1382+ png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
259182b6 1383+}
580fd6fc 1384+
b0807320
ER
1385+/* same as png_read_reset() but for the progressive reader */
1386+void /* PRIVATE */
1387+png_progressive_read_reset(png_structp png_ptr)
1388+{
b0807320
ER
1389+ /* start of interlace block */
1390+ const int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
1391+
1392+ /* offset to next interlace block */
1393+ const int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
1394+
1395+ /* start of interlace block in the y direction */
1396+ const int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
1397+
1398+ /* offset to next interlace block in the y direction */
1399+ const int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
b0807320
ER
1400+
1401+ if (png_ptr->interlaced)
1402+ {
1403+ if (!(png_ptr->transformations & PNG_INTERLACE))
1404+ png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
1405+ png_pass_ystart[0]) / png_pass_yinc[0];
1406+ else
1407+ png_ptr->num_rows = png_ptr->height;
1408+
1409+ png_ptr->iwidth = (png_ptr->width +
1410+ png_pass_inc[png_ptr->pass] - 1 -
1411+ png_pass_start[png_ptr->pass]) /
1412+ png_pass_inc[png_ptr->pass];
b0807320
ER
1413+ }
1414+ else
1415+ {
1416+ png_ptr->num_rows = png_ptr->height;
1417+ png_ptr->iwidth = png_ptr->width;
b0807320 1418+ }
b0807320
ER
1419+ png_ptr->flags &= ~PNG_FLAG_ZLIB_FINISHED;
1420+ if (inflateReset(&(png_ptr->zstream)) != Z_OK)
1421+ png_error(png_ptr, "inflateReset failed");
1422+ png_ptr->zstream.avail_in = 0;
1423+ png_ptr->zstream.next_in = 0;
1424+ png_ptr->zstream.next_out = png_ptr->row_buf;
9089cb0c
AM
1425+ png_ptr->zstream.avail_out = (uInt)PNG_ROWBYTES(png_ptr->pixel_depth,
1426+ png_ptr->iwidth) + 1;
b0807320
ER
1427+}
1428+#endif /* PNG_READ_APNG_SUPPORTED */
1429 #endif /* PNG_READ_SUPPORTED */
1430Index: pngwutil.c
1431===================================================================
1432--- pngwutil.c
1433+++ pngwutil.c
9089cb0c 1434@@ -539,6 +539,11 @@
6df9a45f 1435 /* Write the chunk */
c501f448 1436 png_write_chunk(png_ptr, (png_bytep)png_IHDR, buf, (png_size_t)13);
259182b6 1437
580fd6fc 1438+#ifdef PNG_WRITE_APNG_SUPPORTED
259182b6
ER
1439+ png_ptr->first_frame_width = width;
1440+ png_ptr->first_frame_height = height;
1441+#endif
1442+
6df9a45f 1443 /* Initialize zlib with PNG info */
259182b6
ER
1444 png_ptr->zstream.zalloc = png_zalloc;
1445 png_ptr->zstream.zfree = png_zfree;
9089cb0c 1446@@ -661,6 +666,9 @@
00bce163 1447 png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length)
259182b6 1448 {
259182b6 1449 PNG_IDAT;
580fd6fc 1450+#ifdef PNG_WRITE_APNG_SUPPORTED
259182b6 1451+ PNG_fdAT;
259182b6 1452+#endif
259182b6 1453
92006fdd 1454 png_debug(1, "in png_write_IDAT");
00bce163 1455
9089cb0c 1456@@ -705,7 +713,28 @@
259182b6
ER
1457 "Invalid zlib compression method or flags in IDAT");
1458 }
1459
580fd6fc 1460+#ifdef PNG_WRITE_APNG_SUPPORTED
259182b6
ER
1461+ if(png_ptr->num_frames_written == 0)
1462+#endif
b0807320 1463 png_write_chunk(png_ptr, (png_bytep)png_IDAT, data, length);
580fd6fc 1464+#ifdef PNG_WRITE_APNG_SUPPORTED
259182b6
ER
1465+ else
1466+ {
1467+ png_byte buf[4];
1468+
1469+ png_write_chunk_start(png_ptr, (png_bytep)png_fdAT, 4 + length);
1470+
1471+ png_save_uint_32(buf, png_ptr->next_seq_num);
1472+ png_write_chunk_data(png_ptr, buf, 4);
1473+
1474+ png_write_chunk_data(png_ptr, data, length);
1475+
1476+ png_write_chunk_end(png_ptr);
1477+
1478+ png_ptr->next_seq_num++;
1479+ }
1480+#endif
1481+
1482 png_ptr->mode |= PNG_HAVE_IDAT;
1483 }
1484
9089cb0c 1485@@ -1712,6 +1741,66 @@
259182b6
ER
1486 }
1487 #endif
1488
580fd6fc 1489+#ifdef PNG_WRITE_APNG_SUPPORTED
259182b6
ER
1490+void /* PRIVATE */
1491+png_write_acTL(png_structp png_ptr,
1492+ png_uint_32 num_frames, png_uint_32 num_plays)
1493+{
259182b6 1494+ PNG_acTL;
259182b6
ER
1495+ png_byte data[16];
1496+
6df9a45f 1497+ png_debug(1, "in png_write_acTL");
259182b6
ER
1498+
1499+ png_ptr->num_frames_to_write = num_frames;
1500+
1501+ if (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN)
1502+ num_frames--;
1503+
1504+ png_save_uint_32(data, num_frames);
1505+ png_save_uint_32(data + 4, num_plays);
1506+
1507+ png_write_chunk(png_ptr, (png_bytep)png_acTL, data, (png_size_t)8);
1508+}
1509+
1510+void /* PRIVATE */
1511+png_write_fcTL(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
1512+ png_uint_32 x_offset, png_uint_32 y_offset,
1513+ png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
1514+ png_byte blend_op)
1515+{
259182b6 1516+ PNG_fcTL;
259182b6
ER
1517+ png_byte data[26];
1518+
6df9a45f 1519+ png_debug(1, "in png_write_fcTL");
259182b6
ER
1520+
1521+ if (png_ptr->num_frames_written == 0 && (x_offset != 0 || y_offset != 0))
6df9a45f 1522+ png_error(png_ptr, "x and/or y offset for the first frame aren't 0");
259182b6
ER
1523+ if (png_ptr->num_frames_written == 0 &&
1524+ (width != png_ptr->first_frame_width ||
1525+ height != png_ptr->first_frame_height))
1526+ png_error(png_ptr, "width and/or height in the first frame's fcTL "
6df9a45f 1527+ "don't match the ones in IHDR");
259182b6
ER
1528+
1529+ /* more error checking */
1530+ png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset,
1531+ delay_num, delay_den, dispose_op, blend_op);
1532+
1533+ png_save_uint_32(data, png_ptr->next_seq_num);
1534+ png_save_uint_32(data + 4, width);
1535+ png_save_uint_32(data + 8, height);
1536+ png_save_uint_32(data + 12, x_offset);
1537+ png_save_uint_32(data + 16, y_offset);
1538+ png_save_uint_16(data + 20, delay_num);
1539+ png_save_uint_16(data + 22, delay_den);
1540+ data[24] = dispose_op;
1541+ data[25] = blend_op;
1542+
1543+ png_write_chunk(png_ptr, (png_bytep)png_fcTL, data, (png_size_t)26);
1544+
1545+ png_ptr->next_seq_num++;
1546+}
1547+#endif /* PNG_WRITE_APNG_SUPPORTED */
1548+
6df9a45f 1549 /* Initializes the row writing capability of libpng */
259182b6
ER
1550 void /* PRIVATE */
1551 png_write_start_row(png_structp png_ptr)
9089cb0c 1552@@ -2113,8 +2202,8 @@
b0807320
ER
1553 #ifndef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
1554 if (png_ptr->row_number == 0 && filter_to_do == PNG_ALL_FILTERS)
1555 {
1556- /* These will never be selected so we need not test them. */
1557- filter_to_do &= ~(PNG_FILTER_UP | PNG_FILTER_PAETH);
1558+ /* These use previous row */
1559+ filter_to_do &= ~(PNG_FILTER_UP | PNG_FILTER_AVG | PNG_FILTER_PAETH);
1560 }
1561 #endif
1562
9089cb0c 1563@@ -2783,4 +2872,39 @@
259182b6
ER
1564 }
1565 #endif
1566 }
1567+
580fd6fc 1568+#ifdef PNG_WRITE_APNG_SUPPORTED
259182b6
ER
1569+void /* PRIVATE */
1570+png_write_reset(png_structp png_ptr)
1571+{
1572+ png_ptr->row_number = 0;
1573+ png_ptr->pass = 0;
1574+ png_ptr->mode &= ~PNG_HAVE_IDAT;
1575+}
1576+
1577+void /* PRIVATE */
1578+png_write_reinit(png_structp png_ptr, png_infop info_ptr,
1579+ png_uint_32 width, png_uint_32 height)
1580+{
1581+ if (png_ptr->num_frames_written == 0 &&
1582+ (width != png_ptr->first_frame_width ||
1583+ height != png_ptr->first_frame_height))
1584+ png_error(png_ptr, "width and/or height in the first frame's fcTL "
6df9a45f 1585+ "don't match the ones in IHDR");
259182b6
ER
1586+ if (width > png_ptr->first_frame_width ||
1587+ height > png_ptr->first_frame_height)
1588+ png_error(png_ptr, "width and/or height for a frame greater than"
1589+ "the ones in IHDR");
1590+
1591+ png_set_IHDR(png_ptr, info_ptr, width, height,
1592+ info_ptr->bit_depth, info_ptr->color_type,
1593+ info_ptr->interlace_type, info_ptr->compression_type,
1594+ info_ptr->filter_type);
1595+
1596+ png_ptr->width = width;
1597+ png_ptr->height = height;
1598+ png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width);
1599+ png_ptr->usr_width = png_ptr->width;
1600+}
1601+#endif
1602 #endif /* PNG_WRITE_SUPPORTED */
b0807320
ER
1603Index: pngrtran.c
1604===================================================================
1605--- pngrtran.c
1606+++ pngrtran.c
9089cb0c 1607@@ -1325,7 +1325,7 @@
b0807320
ER
1608 * pixels. This check added to libpng-1.2.19
1609 */
1610 #if (PNG_WARN_UNINITIALIZED_ROW==1)
1611- png_error(png_ptr, "Uninitialized row");
1612+ png_warning(png_ptr, "Uninitialized row");
1613 #else
1614 png_warning(png_ptr, "Uninitialized row");
1615 #endif
This page took 0.268039 seconds and 4 git commands to generate.