]> git.pld-linux.org Git - packages/libpng.git/blame - libpng-apng.patch
- rel 1
[packages/libpng.git] / libpng-apng.patch
CommitLineData
b0807320
ER
1Index: pngread.c
2===================================================================
3--- pngread.c
4+++ pngread.c
00bce163 5@@ -292,6 +292,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
AM
16
17@@ -335,6 +340,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;
00bce163 27@@ -407,12 +415,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)
00bce163 123@@ -453,6 +544,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};
00bce163 134@@ -585,13 +680,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;
00bce163
AM
176@@ -609,6 +730,9 @@
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)
00bce163 186@@ -864,6 +988,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
AM
197
198@@ -963,6 +1092,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
00bce163 389@@ -861,6 +861,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;
00bce163 409@@ -958,6 +971,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
00bce163 420@@ -998,6 +1015,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) || \
00bce163
AM
431@@ -1320,6 +1341,39 @@
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. */
00bce163 471@@ -1648,6 +1702,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));
00bce163 490@@ -1891,6 +1957,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)
00bce163 502@@ -2317,6 +2388,59 @@
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));
526+extern PNG_EXPORT(void,png_ensure_fcTL_is_valid)
527+ PNGARG((png_structp png_ptr,
528+ png_uint_32 width, png_uint_32 height,
529+ png_uint_32 x_offset, png_uint_32 y_offset,
530+ png_uint_16 delay_num, png_uint_16 delay_den,
531+ png_byte dispose_op, png_byte blend_op));
532+extern PNG_EXPORT(png_uint_32,png_get_next_frame_width)
533+ PNGARG((png_structp png_ptr, png_infop info_ptr));
534+extern PNG_EXPORT(png_uint_32,png_get_next_frame_height)
535+ PNGARG((png_structp png_ptr, png_infop info_ptr));
536+extern PNG_EXPORT(png_uint_32,png_get_next_frame_x_offset)
537+ PNGARG((png_structp png_ptr, png_infop info_ptr));
538+extern PNG_EXPORT(png_uint_32,png_get_next_frame_y_offset)
539+ PNGARG((png_structp png_ptr, png_infop info_ptr));
540+extern PNG_EXPORT(png_uint_16,png_get_next_frame_delay_num)
541+ PNGARG((png_structp png_ptr, png_infop info_ptr));
542+extern PNG_EXPORT(png_uint_16,png_get_next_frame_delay_den)
543+ PNGARG((png_structp png_ptr, png_infop info_ptr));
544+extern PNG_EXPORT(png_byte,png_get_next_frame_dispose_op)
545+ PNGARG((png_structp png_ptr, png_infop info_ptr));
546+extern PNG_EXPORT(png_byte,png_get_next_frame_blend_op)
547+ PNGARG((png_structp png_ptr, png_infop info_ptr));
548+extern PNG_EXPORT(png_byte,png_get_first_frame_is_hidden)
549+ PNGARG((png_structp png_ptr, png_infop info_ptr));
550+extern PNG_EXPORT(png_uint_32,png_set_first_frame_is_hidden)
551+ PNGARG((png_structp png_ptr, png_infop info_ptr, png_byte is_hidden));
552+#endif /* PNG_APNG_SUPPORTED */
553+
554+#ifdef PNG_READ_APNG_SUPPORTED
555+extern PNG_EXPORT(void,png_read_frame_head) PNGARG((png_structp png_ptr,
556+ png_infop info_ptr));
557+#endif
558+
559 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
560 /* Provide a list of chunks and how they are to be handled, if the built-in
561 handling or default unknown chunk handling is not desired. Any chunks not
00bce163
AM
562Index: pngpriv.h
563===================================================================
564--- pngpriv.h
565+++ pngpriv.h
566@@ -98,6 +98,10 @@
b0807320
ER
567 #define PNG_BACKGROUND_IS_GRAY 0x800
568 #define PNG_HAVE_PNG_SIGNATURE 0x1000
569 #define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */
570+#ifdef PNG_APNG_SUPPORTED
571+#define PNG_HAVE_acTL 0x4000
572+#define PNG_HAVE_fcTL 0x8000L
573+#endif
574
575 /* Flags for the transformations the PNG library does on the image data */
00bce163
AM
576 #define PNG_BGR 0x0001
577@@ -231,6 +235,11 @@
578 #define PNG_tIME PNG_CONST png_byte png_tIME[5] = {116, 73, 77, 69, '\0'}
579 #define PNG_tRNS PNG_CONST png_byte png_tRNS[5] = {116, 82, 78, 83, '\0'}
580 #define PNG_zTXt PNG_CONST png_byte png_zTXt[5] = {122, 84, 88, 116, '\0'}
b0807320 581+#ifdef PNG_APNG_SUPPORTED
00bce163
AM
582+#define PNG_acTL PNG_CONST png_byte png_acTL[5] = { 97, 99, 84, 76, '\0'}
583+#define PNG_fcTL PNG_CONST png_byte png_fcTL[5] = {102, 99, 84, 76, '\0'}
584+#define PNG_fdAT PNG_CONST png_byte png_fdAT[5] = {102, 100, 65, 84, '\0'}
b0807320
ER
585+#endif
586
b0807320 587
00bce163
AM
588 /* Inhibit C++ name-mangling for libpng functions but not for system calls. */
589@@ -468,6 +477,17 @@
b0807320
ER
590 #endif
591 #endif
592
593+#ifdef PNG_WRITE_APNG_SUPPORTED
594+PNG_EXTERN void png_write_acTL PNGARG((png_structp png_ptr,
595+ png_uint_32 num_frames, png_uint_32 num_plays));
596+
597+PNG_EXTERN void png_write_fcTL PNGARG((png_structp png_ptr,
598+ png_uint_32 width, png_uint_32 height,
599+ png_uint_32 x_offset, png_uint_32 y_offset,
600+ png_uint_16 delay_num, png_uint_16 delay_den,
601+ png_byte dispose_op, png_byte blend_op));
602+#endif
603+
604 /* Called when finished processing a row of data */
00bce163 605 PNG_EXTERN void png_write_finish_row PNGARG((png_structp png_ptr));
b0807320 606
00bce163 607@@ -520,6 +540,20 @@
b0807320 608 PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr,
00bce163 609 png_infop info_ptr));
b0807320
ER
610
611+#ifdef PNG_READ_APNG_SUPPORTED
612+/* Private, reset some things to become ready for reading next frame */
613+PNG_EXTERN void png_read_reset PNGARG((png_structp png_ptr));
614+PNG_EXTERN void png_read_reinit PNGARG((png_structp png_ptr,
615+ png_infop info_ptr));
616+PNG_EXTERN void png_progressive_read_reset PNGARG((png_structp png_ptr));
617+#endif
618+#ifdef PNG_WRITE_APNG_SUPPORTED
619+/* Private, reset some things to become ready for writing next frame */
620+PNG_EXTERN void png_write_reset PNGARG((png_structp png_ptr));
621+PNG_EXTERN void png_write_reinit PNGARG((png_structp png_ptr,
622+ png_infop info_ptr, png_uint_32 width, png_uint_32 height));
623+#endif
624+
625 /* These are the functions that do the transformations */
626 #ifdef PNG_READ_FILLER_SUPPORTED
627 PNG_EXTERN void png_do_read_filler PNGARG((png_row_infop row_info,
00bce163
AM
628@@ -735,6 +769,18 @@
629 png_uint_32 length));
b0807320
ER
630 #endif
631
632+#ifdef PNG_READ_APNG_SUPPORTED
633+PNG_EXTERN void png_handle_acTL PNGARG((png_structp png_ptr, png_infop info_ptr,
634+ png_uint_32 length));
635+PNG_EXTERN void png_handle_fcTL PNGARG((png_structp png_ptr, png_infop info_ptr,
636+ png_uint_32 length));
637+PNG_EXTERN void png_have_info PNGARG((png_structp png_ptr, png_infop info_ptr));
638+PNG_EXTERN void png_handle_fdAT PNGARG((png_structp png_ptr, png_infop info_ptr,
639+ png_uint_32 length));
640+PNG_EXTERN void png_ensure_sequence_number PNGARG((png_structp png_ptr,
641+ png_uint_32 length));
642+#endif
643+
644 PNG_EXTERN void png_handle_unknown PNGARG((png_structp png_ptr,
00bce163 645 png_infop info_ptr, png_uint_32 length));
b0807320
ER
646
647Index: pngwrite.c
648===================================================================
649--- pngwrite.c
650+++ pngwrite.c
651@@ -56,6 +56,10 @@
652 /* The rest of these check to see if the valid field has the appropriate
653 * flag set, and if it does, writes the chunk.
654 */
655+#ifdef PNG_WRITE_APNG_SUPPORTED
656+ if (info_ptr->valid & PNG_INFO_acTL)
657+ png_write_acTL(png_ptr, info_ptr->num_frames, info_ptr->num_plays);
658+#endif
659 #ifdef PNG_WRITE_gAMA_SUPPORTED
660 if (info_ptr->valid & PNG_INFO_gAMA)
661 {
662@@ -318,6 +322,10 @@
663 return;
664 if (!(png_ptr->mode & PNG_HAVE_IDAT))
665 png_error(png_ptr, "No IDATs written into file");
666+#ifdef PNG_WRITE_APNG_SUPPORTED
667+ if (png_ptr->num_frames_written != png_ptr->num_frames_to_write)
668+ png_error(png_ptr, "Not enough frames written");
669+#endif
670
671 /* See if user wants us to write information chunks */
672 if (info_ptr != NULL)
00bce163 673@@ -1451,4 +1459,39 @@
b0807320
ER
674 params = params;
675 }
676 #endif
677+
678+#ifdef PNG_WRITE_APNG_SUPPORTED
679+void PNGAPI
680+png_write_frame_head(png_structp png_ptr, png_infop info_ptr,
681+ png_bytepp row_pointers, png_uint_32 width, png_uint_32 height,
682+ png_uint_32 x_offset, png_uint_32 y_offset,
683+ png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
684+ png_byte blend_op)
685+{
686+ png_debug(1, "in png_write_frame_head");
687+
688+ /* there is a chance this has been set after png_write_info was called,
689+ * so it would be set but not written. is there a way to be sure? */
690+ if (!(info_ptr->valid & PNG_INFO_acTL))
691+ png_error(png_ptr, "png_write_frame_head(): acTL not set");
692+
693+ png_write_reset(png_ptr);
694+
695+ png_write_reinit(png_ptr, info_ptr, width, height);
696+
697+ if ( !(png_ptr->num_frames_written == 0 &&
698+ (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN) ) )
699+ png_write_fcTL(png_ptr, width, height, x_offset, y_offset,
700+ delay_num, delay_den, dispose_op, blend_op);
701+}
702+
703+void PNGAPI
704+png_write_frame_tail(png_structp png_ptr, png_infop png_info)
705+{
706+ png_debug(1, "in png_write_frame_tail");
707+
708+ png_ptr->num_frames_written++;
709+}
710+#endif /* PNG_WRITE_APNG_SUPPORTED */
711+
712 #endif /* PNG_WRITE_SUPPORTED */
713Index: pngconf.h
714===================================================================
715--- pngconf.h
716+++ pngconf.h
00bce163
AM
717@@ -845,6 +845,10 @@
718 # define PNG_READ_tRNS_SUPPORTED
719 # define PNG_tRNS_SUPPORTED
b0807320
ER
720 #endif
721+#ifndef PNG_NO_READ_APNG
722+# define PNG_READ_APNG_SUPPORTED
723+# define PNG_APNG_SUPPORTED
724+#endif
00bce163
AM
725 #ifndef PNG_NO_READ_zTXt
726 # define PNG_READ_zTXt_SUPPORTED
727 # define PNG_zTXt_SUPPORTED
728@@ -1002,6 +1006,14 @@
b0807320
ER
729 # define PNG_TEXT_SUPPORTED
730 # endif
731 #endif
732+#ifndef PNG_NO_WRITE_APNG
733+# ifndef PNG_WRITE_APNG_SUPPORTED
734+# define PNG_WRITE_APNG_SUPPORTED
735+# endif
736+# ifndef PNG_APNG_SUPPORTED
737+# define PNG_APNG_SUPPORTED
738+# endif
739+#endif
740
741 #ifdef PNG_WRITE_tIME_SUPPORTED
742 # ifndef PNG_NO_CONVERT_tIME
743Index: pngpread.c
744===================================================================
745--- pngpread.c
746+++ pngpread.c
00bce163 747@@ -205,6 +205,11 @@
b0807320 748 #ifdef PNG_READ_zTXt_SUPPORTED
00bce163 749 PNG_zTXt;
b0807320
ER
750 #endif
751+#ifdef PNG_READ_APNG_SUPPORTED
00bce163
AM
752+ PNG_acTL;
753+ PNG_fcTL;
754+ PNG_fdAT;
b0807320 755+#endif
b0807320
ER
756
757 /* First we make sure we have enough data for the 4 byte chunk name
00bce163
AM
758 * and the 4 byte chunk length before proceeding with decoding the
759@@ -230,6 +235,103 @@
b0807320
ER
760 png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
761 }
762
763+#ifdef PNG_READ_APNG_SUPPORTED
764+ if (png_ptr->num_frames_read > 0 &&
765+ png_ptr->num_frames_read < info_ptr->num_frames)
766+ {
767+ if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
768+ {
769+ /* Discard trailing IDATs for the first frame */
770+ if (png_ptr->mode & PNG_HAVE_fcTL || png_ptr->num_frames_read > 1)
771+ png_error(png_ptr, "out of place IDAT");
772+
773+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
774+ {
775+ png_push_save_buffer(png_ptr);
776+ return;
777+ }
778+ png_push_crc_skip(png_ptr, png_ptr->push_length);
779+ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
780+ return;
781+ }
782+ else if (!png_memcmp(png_ptr->chunk_name, png_fdAT, 4))
783+ {
784+ if (png_ptr->buffer_size < 4)
259182b6
ER
785+ {
786+ png_push_save_buffer(png_ptr);
787+ return;
788+ }
789+ png_ensure_sequence_number(png_ptr, 4);
790+
791+ if (!(png_ptr->mode & PNG_HAVE_fcTL))
792+ {
92006fdd 793+ /* Discard trailing fdATs for frames other than the first */
259182b6
ER
794+ if (png_ptr->num_frames_read < 2)
795+ png_error(png_ptr, "out of place fdAT");
796+
797+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
798+ {
799+ png_push_save_buffer(png_ptr);
800+ return;
801+ }
802+ png_push_crc_skip(png_ptr, png_ptr->push_length);
803+ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
804+ return;
805+ }
806+ else
807+ {
808+ /* frame data follows */
809+ png_ptr->idat_size = png_ptr->push_length - 4;
810+ png_ptr->mode |= PNG_HAVE_IDAT;
811+ png_ptr->process_mode = PNG_READ_IDAT_MODE;
812+
813+ return;
814+ }
815+ }
816+ else if(!png_memcmp(png_ptr->chunk_name, png_fcTL, 4))
817+ {
818+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
819+ {
820+ png_push_save_buffer(png_ptr);
821+ return;
822+ }
823+
824+ png_read_reset(png_ptr);
825+ png_ptr->mode &= ~PNG_HAVE_fcTL;
826+
827+ png_handle_fcTL(png_ptr, info_ptr, png_ptr->push_length);
828+
829+ if (!(png_ptr->mode & PNG_HAVE_fcTL))
830+ png_error(png_ptr, "missing required fcTL chunk");
831+
832+ png_read_reinit(png_ptr, info_ptr);
833+ png_progressive_read_reset(png_ptr);
834+
835+ if (png_ptr->frame_info_fn != NULL)
836+ (*(png_ptr->frame_info_fn))(png_ptr, png_ptr->num_frames_read);
837+
838+ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
839+
840+ return;
841+ }
842+ else
843+ {
844+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
845+ {
846+ png_push_save_buffer(png_ptr);
847+ return;
848+ }
849+ png_warning(png_ptr, "Skipped (ignored) a chunk "
850+ "between APNG chunks");
851+ png_push_crc_skip(png_ptr, png_ptr->push_length);
852+ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
853+ return;
854+ }
855+
856+ return;
857+ }
858+#endif /* PNG_READ_APNG_SUPPORTED */
b0807320 859+
259182b6 860 if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
6df9a45f 861 if (png_ptr->mode & PNG_AFTER_IDAT)
259182b6 862 png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
00bce163
AM
863@@ -325,6 +427,9 @@
864 png_benign_error(png_ptr, "Too many IDATs found");
259182b6
ER
865 }
866
580fd6fc 867+#ifdef PNG_READ_APNG_SUPPORTED
259182b6
ER
868+ png_have_info(png_ptr, info_ptr);
869+#endif
870 png_ptr->idat_size = png_ptr->push_length;
871 png_ptr->mode |= PNG_HAVE_IDAT;
872 png_ptr->process_mode = PNG_READ_IDAT_MODE;
00bce163 873@@ -555,6 +660,38 @@
259182b6 874 }
6df9a45f 875
259182b6 876 #endif
580fd6fc 877+#ifdef PNG_READ_APNG_SUPPORTED
259182b6
ER
878+ else if (!png_memcmp(png_ptr->chunk_name, png_acTL, 4))
879+ {
880+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
881+ {
882+ png_push_save_buffer(png_ptr);
883+ return;
884+ }
92006fdd 885+
259182b6
ER
886+ png_handle_acTL(png_ptr, info_ptr, png_ptr->push_length);
887+ }
888+ else if (!png_memcmp(png_ptr->chunk_name, png_fcTL, 4))
889+ {
890+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
891+ {
892+ png_push_save_buffer(png_ptr);
893+ return;
894+ }
92006fdd 895+
259182b6
ER
896+ png_handle_fcTL(png_ptr, info_ptr, png_ptr->push_length);
897+ }
898+ else if (!png_memcmp(png_ptr->chunk_name, png_fdAT, 4))
899+ {
900+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
901+ {
902+ png_push_save_buffer(png_ptr);
903+ return;
904+ }
92006fdd 905+
259182b6
ER
906+ png_handle_fdAT(png_ptr, info_ptr, png_ptr->push_length);
907+ }
908+#endif /* PNG_READ_APNG_SUPPORTED */
909 else
910 {
911 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
00bce163 912@@ -729,11 +866,15 @@
259182b6
ER
913 png_push_read_IDAT(png_structp png_ptr)
914 {
00bce163 915 PNG_IDAT;
580fd6fc 916+#ifdef PNG_READ_APNG_SUPPORTED
259182b6
ER
917+ PNG_fdAT;
918+ PNG_IEND;
259182b6
ER
919+#endif
920 if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER))
921 {
922 png_byte chunk_length[4];
923
924- if (png_ptr->buffer_size < 8)
925+ if (png_ptr->buffer_size < 12)
926 {
927 png_push_save_buffer(png_ptr);
928 return;
00bce163 929@@ -745,15 +886,62 @@
259182b6
ER
930 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
931 png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
932
b0807320 933- if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
580fd6fc 934+#ifdef PNG_READ_APNG_SUPPORTED
00bce163 935+ if (png_memcmp(png_ptr->chunk_name, png_fdAT, 4)
b0807320
ER
936+ && png_ptr->num_frames_read > 0)
937+ {
938+ if (png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)
939+ {
940+ png_ptr->process_mode = PNG_READ_CHUNK_MODE;
941+ if (png_ptr->frame_end_fn != NULL)
942+ (*(png_ptr->frame_end_fn))(png_ptr, png_ptr->num_frames_read);
943+ png_ptr->num_frames_read++;
944+ return;
945+ }
946+ else
947+ {
948+ if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
580fd6fc 949+ png_error(png_ptr, "Not enough image data");
b0807320
ER
950+ if (png_ptr->push_length + 4 > png_ptr->buffer_size)
951+ {
952+ png_push_save_buffer(png_ptr);
953+ return;
954+ }
955+ png_warning(png_ptr, "Skipping (ignoring) a chunk between "
956+ "APNG chunks");
957+ png_crc_finish(png_ptr, png_ptr->push_length);
958+ png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
959+ return;
960+ }
961+ }
962+ else
963+#endif
964+ if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)
580fd6fc 965+#ifdef PNG_READ_APNG_SUPPORTED
b0807320 966+ && (png_ptr->num_frames_read == 0)
580fd6fc 967+#endif
b0807320
ER
968+ )
969 {
970 png_ptr->process_mode = PNG_READ_CHUNK_MODE;
971 if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
972 png_error(png_ptr, "Not enough compressed data");
580fd6fc 973+#ifdef PNG_READ_APNG_SUPPORTED
b0807320
ER
974+ if (png_ptr->frame_end_fn != NULL)
975+ (*(png_ptr->frame_end_fn))(png_ptr, png_ptr->num_frames_read);
580fd6fc
TP
976+ png_ptr->num_frames_read++;
977+#endif
b0807320 978 return;
580fd6fc 979 }
b0807320
ER
980
981 png_ptr->idat_size = png_ptr->push_length;
982+
580fd6fc 983+#ifdef PNG_READ_APNG_SUPPORTED
b0807320
ER
984+ if (png_ptr->num_frames_read > 0)
985+ {
986+ png_ensure_sequence_number(png_ptr, 4);
987+ png_ptr->idat_size -= 4;
988+ }
580fd6fc 989+#endif
b0807320
ER
990 }
991 if (png_ptr->idat_size && png_ptr->save_buffer_size)
992 {
00bce163 993@@ -1710,6 +1898,17 @@
b0807320
ER
994 png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
995 }
996
580fd6fc 997+#ifdef PNG_READ_APNG_SUPPORTED
b0807320
ER
998+void PNGAPI
999+png_set_progressive_frame_fn(png_structp png_ptr,
1000+ png_progressive_frame_ptr frame_info_fn,
1001+ png_progressive_frame_ptr frame_end_fn)
1002+{
1003+ png_ptr->frame_info_fn = frame_info_fn;
1004+ png_ptr->frame_end_fn = frame_end_fn;
1005+}
580fd6fc 1006+#endif
b0807320
ER
1007+
1008 png_voidp PNGAPI
1009 png_get_progressive_ptr(png_structp png_ptr)
1010 {
1011Index: pngset.c
1012===================================================================
1013--- pngset.c
1014+++ pngset.c
00bce163
AM
1015@@ -260,6 +260,11 @@
1016 info_ptr->rowbytes = 0;
b0807320
ER
1017 else
1018 info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width);
1019+
1020+#ifdef PNG_APNG_SUPPORTED
1021+ /* for non-animated png. this may be overritten from an acTL chunk later */
1022+ info_ptr->num_frames = 1;
1023+#endif
1024 }
1025
1026 #ifdef PNG_oFFs_SUPPORTED
00bce163 1027@@ -932,6 +937,142 @@
b0807320
ER
1028 }
1029 #endif /* PNG_sPLT_SUPPORTED */
1030
1031+#ifdef PNG_APNG_SUPPORTED
1032+png_uint_32 PNGAPI
1033+png_set_acTL(png_structp png_ptr, png_infop info_ptr,
1034+ png_uint_32 num_frames, png_uint_32 num_plays)
1035+{
1036+ png_debug1(1, "in %s storage function", "acTL");
1037+
1038+ if (png_ptr == NULL || info_ptr == NULL)
1039+ {
1040+ png_warning(png_ptr,
1041+ "Call to png_set_acTL() with NULL png_ptr "
1042+ "or info_ptr ignored");
1043+ return (0);
1044+ }
1045+ if (num_frames == 0)
1046+ {
1047+ png_warning(png_ptr,
1048+ "Ignoring attempt to set acTL with num_frames zero");
1049+ return (0);
1050+ }
1051+ if (num_frames > PNG_UINT_31_MAX)
1052+ {
1053+ png_warning(png_ptr,
1054+ "Ignoring attempt to set acTL with num_frames > 2^31-1");
1055+ return (0);
1056+ }
1057+ if (num_plays > PNG_UINT_31_MAX)
1058+ {
1059+ png_warning(png_ptr,
1060+ "Ignoring attempt to set acTL with num_plays "
1061+ "> 2^31-1");
1062+ return (0);
1063+ }
1064+
1065+ info_ptr->num_frames = num_frames;
1066+ info_ptr->num_plays = num_plays;
1067+
1068+ info_ptr->valid |= PNG_INFO_acTL;
1069+
1070+ return (1);
1071+}
1072+
1073+/* delay_num and delay_den can hold any 16-bit values including zero */
1074+png_uint_32 PNGAPI
1075+png_set_next_frame_fcTL(png_structp png_ptr, png_infop info_ptr,
1076+ png_uint_32 width, png_uint_32 height,
1077+ png_uint_32 x_offset, png_uint_32 y_offset,
1078+ png_uint_16 delay_num, png_uint_16 delay_den,
1079+ png_byte dispose_op, png_byte blend_op)
1080+{
1081+ png_debug1(1, "in %s storage function", "fcTL");
1082+
1083+ if (png_ptr == NULL || info_ptr == NULL)
1084+ {
1085+ png_warning(png_ptr,
1086+ "Call to png_set_fcTL() with NULL png_ptr or info_ptr "
1087+ "ignored");
1088+ return (0);
1089+ }
1090+
1091+ png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset,
1092+ delay_num, delay_den, dispose_op, blend_op);
1093+
1094+ if (blend_op == PNG_BLEND_OP_OVER)
1095+ {
1096+ if (!(png_ptr->color_type & PNG_COLOR_MASK_ALPHA) &&
1097+ !(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)))
1098+ {
1099+ png_warning(png_ptr, "PNG_BLEND_OP_OVER is meaningless "
1100+ "and wasteful for opaque images, ignored");
1101+ blend_op = PNG_BLEND_OP_SOURCE;
1102+ }
1103+ }
1104+
1105+ info_ptr->next_frame_width = width;
1106+ info_ptr->next_frame_height = height;
1107+ info_ptr->next_frame_x_offset = x_offset;
1108+ info_ptr->next_frame_y_offset = y_offset;
1109+ info_ptr->next_frame_delay_num = delay_num;
1110+ info_ptr->next_frame_delay_den = delay_den;
1111+ info_ptr->next_frame_dispose_op = dispose_op;
1112+ info_ptr->next_frame_blend_op = blend_op;
1113+
1114+ info_ptr->valid |= PNG_INFO_fcTL;
1115+
1116+ return (1);
1117+}
1118+
1119+void /* PRIVATE */
1120+png_ensure_fcTL_is_valid(png_structp png_ptr,
1121+ png_uint_32 width, png_uint_32 height,
1122+ png_uint_32 x_offset, png_uint_32 y_offset,
1123+ png_uint_16 delay_num, png_uint_16 delay_den,
1124+ png_byte dispose_op, png_byte blend_op)
1125+{
1126+ if (width + x_offset > png_ptr->first_frame_width ||
1127+ height + y_offset > png_ptr->first_frame_height)
1128+ png_error(png_ptr, "dimensions of a frame are greater than"
1129+ "the ones in IHDR");
1130+ if (width > PNG_UINT_31_MAX)
1131+ png_error(png_ptr, "invalid width in fcTL (> 2^31-1)");
1132+ if (height > PNG_UINT_31_MAX)
1133+ png_error(png_ptr, "invalid height in fcTL (> 2^31-1)");
1134+ if (x_offset > PNG_UINT_31_MAX)
1135+ png_error(png_ptr, "invalid x_offset in fcTL (> 2^31-1)");
1136+ if (y_offset > PNG_UINT_31_MAX)
1137+ png_error(png_ptr, "invalid y_offset in fcTL (> 2^31-1)");
1138+
1139+ if (dispose_op != PNG_DISPOSE_OP_NONE &&
00bce163
AM
1140+ dispose_op != PNG_DISPOSE_OP_BACKGROUND &&
1141+ dispose_op != PNG_DISPOSE_OP_PREVIOUS)
b0807320
ER
1142+ png_error(png_ptr, "invalid dispose_op in fcTL");
1143+
1144+ if (blend_op != PNG_BLEND_OP_SOURCE &&
00bce163 1145+ blend_op != PNG_BLEND_OP_OVER)
b0807320
ER
1146+ png_error(png_ptr, "invalid blend_op in fcTL");
1147+}
1148+
1149+png_uint_32 PNGAPI
1150+png_set_first_frame_is_hidden(png_structp png_ptr, png_infop info_ptr,
1151+ png_byte is_hidden)
1152+{
1153+ png_debug(1, "in png_first_frame_is_hidden()");
1154+
1155+ if (png_ptr == NULL)
1156+ return 0;
1157+
1158+ if(is_hidden)
1159+ png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN;
1160+ else
1161+ png_ptr->apng_flags &= ~PNG_FIRST_FRAME_HIDDEN;
1162+
1163+ return 1;
1164+}
1165+#endif /* PNG_APNG_SUPPORTED */
1166+
00bce163 1167 #ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
b0807320
ER
1168 void PNGAPI
1169 png_set_unknown_chunks(png_structp png_ptr,
1170Index: pngrutil.c
1171===================================================================
1172--- pngrutil.c
1173+++ pngrutil.c
00bce163 1174@@ -423,6 +423,11 @@
259182b6
ER
1175 filter_type = buf[11];
1176 interlace_type = buf[12];
1177
580fd6fc 1178+#ifdef PNG_READ_APNG_SUPPORTED
259182b6
ER
1179+ png_ptr->first_frame_width = width;
1180+ png_ptr->first_frame_height = height;
1181+#endif
1182+
6df9a45f 1183 /* Set internal variables */
259182b6
ER
1184 png_ptr->width = width;
1185 png_ptr->height = height;
00bce163 1186@@ -2294,6 +2299,168 @@
259182b6
ER
1187 }
1188 #endif
1189
580fd6fc 1190+#ifdef PNG_READ_APNG_SUPPORTED
259182b6
ER
1191+void /* PRIVATE */
1192+png_handle_acTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1193+{
1194+ png_byte data[8];
1195+ png_uint_32 num_frames;
1196+ png_uint_32 num_plays;
1197+ png_uint_32 didSet;
1198+
6df9a45f 1199+ png_debug(1, "in png_handle_acTL");
259182b6
ER
1200+
1201+ if (!(png_ptr->mode & PNG_HAVE_IHDR))
1202+ {
1203+ png_error(png_ptr, "Missing IHDR before acTL");
1204+ }
1205+ else if (png_ptr->mode & PNG_HAVE_IDAT)
1206+ {
1207+ png_warning(png_ptr, "Invalid acTL after IDAT skipped");
1208+ png_crc_finish(png_ptr, length);
1209+ return;
1210+ }
1211+ else if (png_ptr->mode & PNG_HAVE_acTL)
1212+ {
1213+ png_warning(png_ptr, "Duplicate acTL skipped");
1214+ png_crc_finish(png_ptr, length);
1215+ return;
1216+ }
1217+ else if (length != 8)
1218+ {
1219+ png_warning(png_ptr, "acTL with invalid length skipped");
1220+ png_crc_finish(png_ptr, length);
1221+ return;
1222+ }
1223+
1224+ png_crc_read(png_ptr, data, 8);
1225+ png_crc_finish(png_ptr, 0);
1226+
1227+ num_frames = png_get_uint_31(png_ptr, data);
1228+ num_plays = png_get_uint_31(png_ptr, data + 4);
1229+
1230+ /* the set function will do error checking on num_frames */
1231+ didSet = png_set_acTL(png_ptr, info_ptr, num_frames, num_plays);
1232+ if(didSet)
1233+ png_ptr->mode |= PNG_HAVE_acTL;
1234+}
1235+
1236+void /* PRIVATE */
1237+png_handle_fcTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1238+{
1239+ png_byte data[22];
1240+ png_uint_32 width;
1241+ png_uint_32 height;
1242+ png_uint_32 x_offset;
1243+ png_uint_32 y_offset;
1244+ png_uint_16 delay_num;
1245+ png_uint_16 delay_den;
1246+ png_byte dispose_op;
1247+ png_byte blend_op;
1248+
6df9a45f 1249+ png_debug(1, "in png_handle_fcTL");
259182b6
ER
1250+
1251+ if (!(png_ptr->mode & PNG_HAVE_IHDR))
1252+ {
1253+ png_error(png_ptr, "Missing IHDR before fcTL");
1254+ }
1255+ else if (png_ptr->mode & PNG_HAVE_IDAT)
1256+ {
1257+ /* for any frames other then the first this message may be misleading,
1258+ * but correct. PNG_HAVE_IDAT is unset before the frame head is read
1259+ * i can't think of a better message */
1260+ png_warning(png_ptr, "Invalid fcTL after IDAT skipped");
1261+ png_crc_finish(png_ptr, length);
1262+ return;
1263+ }
1264+ else if (png_ptr->mode & PNG_HAVE_fcTL)
1265+ {
1266+ png_warning(png_ptr, "Duplicate fcTL within one frame skipped");
1267+ png_crc_finish(png_ptr, length);
1268+ return;
1269+ }
1270+ else if (length != 26)
1271+ {
1272+ png_warning(png_ptr, "fcTL with invalid length skipped");
1273+ png_crc_finish(png_ptr, length);
1274+ return;
1275+ }
1276+
1277+ png_ensure_sequence_number(png_ptr, length);
1278+
1279+ png_crc_read(png_ptr, data, 22);
1280+ png_crc_finish(png_ptr, 0);
1281+
1282+ width = png_get_uint_31(png_ptr, data);
1283+ height = png_get_uint_31(png_ptr, data + 4);
1284+ x_offset = png_get_uint_31(png_ptr, data + 8);
1285+ y_offset = png_get_uint_31(png_ptr, data + 12);
1286+ delay_num = png_get_uint_16(data + 16);
1287+ delay_den = png_get_uint_16(data + 18);
1288+ dispose_op = data[20];
1289+ blend_op = data[21];
1290+
1291+ if (png_ptr->num_frames_read == 0 && (x_offset != 0 || y_offset != 0))
1292+ png_error(png_ptr, "fcTL for the first frame must have zero offset");
1293+ if (png_ptr->num_frames_read == 0 &&
1294+ (width != info_ptr->width || height != info_ptr->height))
1295+ png_error(png_ptr, "size in first frame's fcTL must match "
1296+ "the size in IHDR");
1297+
1298+ /* the set function will do more error checking */
1299+ png_set_next_frame_fcTL(png_ptr, info_ptr, width, height,
1300+ x_offset, y_offset, delay_num, delay_den,
1301+ dispose_op, blend_op);
1302+
1303+ png_read_reinit(png_ptr, info_ptr);
1304+
1305+ png_ptr->mode |= PNG_HAVE_fcTL;
1306+}
1307+
1308+void /* PRIVATE */
b0807320 1309+png_have_info(png_structp png_ptr, png_infop info_ptr)
259182b6 1310+{
b0807320
ER
1311+ if((info_ptr->valid & PNG_INFO_acTL) && !(info_ptr->valid & PNG_INFO_fcTL))
1312+ {
1313+ png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN;
1314+ info_ptr->num_frames++;
1315+ }
1316+}
580fd6fc 1317+
b0807320
ER
1318+void /* PRIVATE */
1319+png_handle_fdAT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1320+{
1321+ png_ensure_sequence_number(png_ptr, length);
1322+
1323+ /* This function is only called from png_read_end(), png_read_info(),
1324+ * and png_push_read_chunk() which means that:
1325+ * - the user doesn't want to read this frame
1326+ * - or this is an out-of-place fdAT
1327+ * in either case it is safe to ignore the chunk with a warning */
1328+ png_warning(png_ptr, "ignoring fdAT chunk");
1329+ png_crc_finish(png_ptr, length - 4);
259182b6
ER
1330+}
1331+
b0807320
ER
1332+void /* PRIVATE */
1333+png_ensure_sequence_number(png_structp png_ptr, png_uint_32 length)
259182b6 1334+{
b0807320
ER
1335+ png_byte data[4];
1336+ png_uint_32 sequence_number;
259182b6 1337+
b0807320
ER
1338+ if (length < 4)
1339+ png_error(png_ptr, "invalid fcTL or fdAT chunk found");
259182b6 1340+
b0807320
ER
1341+ png_crc_read(png_ptr, data, 4);
1342+ sequence_number = png_get_uint_31(png_ptr, data);
259182b6 1343+
b0807320
ER
1344+ if (sequence_number != png_ptr->next_seq_num)
1345+ png_error(png_ptr, "fcTL or fdAT chunk with out-of-order sequence "
1346+ "number found");
1347+
1348+ png_ptr->next_seq_num++;
259182b6 1349+}
b0807320 1350+#endif /* PNG_READ_APNG_SUPPORTED */
259182b6 1351+
b0807320
ER
1352 /* This function is called when we haven't found a handler for a
1353 chunk. If there isn't a problem with the chunk itself (ie bad
1354 chunk name, CRC, or a critical chunk), the chunk is silently ignored
00bce163 1355@@ -3333,4 +3500,82 @@
580fd6fc 1356
b0807320 1357 png_ptr->flags |= PNG_FLAG_ROW_INIT;
580fd6fc 1358 }
259182b6 1359+
b0807320
ER
1360+#ifdef PNG_READ_APNG_SUPPORTED
1361+/* This function is to be called after the main IDAT set has been read and
1362+ * before a new IDAT is read. It resets some parts of png_ptr
1363+ * to make them usable by the read functions again */
1364+void /* PRIVATE */
1365+png_read_reset(png_structp png_ptr)
259182b6 1366+{
b0807320
ER
1367+ png_ptr->mode &= ~PNG_HAVE_IDAT;
1368+ png_ptr->mode &= ~PNG_AFTER_IDAT;
1369+ png_ptr->row_number = 0;
1370+ png_ptr->pass = 0;
1371+ png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
259182b6
ER
1372+}
1373+
b0807320
ER
1374+void /* PRIVATE */
1375+png_read_reinit(png_structp png_ptr, png_infop info_ptr)
259182b6 1376+{
b0807320
ER
1377+ png_ptr->width = info_ptr->next_frame_width;
1378+ png_ptr->height = info_ptr->next_frame_height;
1379+ png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->width);
1380+ if (png_ptr->prev_row)
00bce163 1381+ png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
259182b6 1382+}
580fd6fc 1383+
b0807320
ER
1384+/* same as png_read_reset() but for the progressive reader */
1385+void /* PRIVATE */
1386+png_progressive_read_reset(png_structp png_ptr)
1387+{
b0807320
ER
1388+ /* start of interlace block */
1389+ const int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
1390+
1391+ /* offset to next interlace block */
1392+ const int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
1393+
1394+ /* start of interlace block in the y direction */
1395+ const int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
1396+
1397+ /* offset to next interlace block in the y direction */
1398+ const int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
b0807320
ER
1399+ png_uint_32 row_bytes;
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];
1413+
1414+ row_bytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->iwidth) + 1;
1415+
1416+ png_ptr->irowbytes = (png_size_t)row_bytes;
1417+ if((png_uint_32)png_ptr->irowbytes != row_bytes)
1418+ png_error(png_ptr, "png_progressive_read_reset(): Rowbytes "
1419+ "overflow");
1420+ }
1421+ else
1422+ {
1423+ png_ptr->num_rows = png_ptr->height;
1424+ png_ptr->iwidth = png_ptr->width;
1425+ png_ptr->irowbytes = png_ptr->rowbytes + 1;
1426+ }
1427+
1428+ png_ptr->flags &= ~PNG_FLAG_ZLIB_FINISHED;
1429+ if (inflateReset(&(png_ptr->zstream)) != Z_OK)
1430+ png_error(png_ptr, "inflateReset failed");
1431+ png_ptr->zstream.avail_in = 0;
1432+ png_ptr->zstream.next_in = 0;
1433+ png_ptr->zstream.next_out = png_ptr->row_buf;
1434+ png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;
1435+}
1436+#endif /* PNG_READ_APNG_SUPPORTED */
1437 #endif /* PNG_READ_SUPPORTED */
1438Index: pngwutil.c
1439===================================================================
1440--- pngwutil.c
1441+++ pngwutil.c
00bce163 1442@@ -538,6 +538,11 @@
6df9a45f 1443 /* Write the chunk */
c501f448 1444 png_write_chunk(png_ptr, (png_bytep)png_IHDR, buf, (png_size_t)13);
259182b6 1445
580fd6fc 1446+#ifdef PNG_WRITE_APNG_SUPPORTED
259182b6
ER
1447+ png_ptr->first_frame_width = width;
1448+ png_ptr->first_frame_height = height;
1449+#endif
1450+
6df9a45f 1451 /* Initialize zlib with PNG info */
259182b6
ER
1452 png_ptr->zstream.zalloc = png_zalloc;
1453 png_ptr->zstream.zfree = png_zfree;
00bce163
AM
1454@@ -658,6 +663,9 @@
1455 png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length)
259182b6 1456 {
259182b6 1457 PNG_IDAT;
580fd6fc 1458+#ifdef PNG_WRITE_APNG_SUPPORTED
259182b6 1459+ PNG_fdAT;
259182b6 1460+#endif
259182b6 1461
92006fdd 1462 png_debug(1, "in png_write_IDAT");
00bce163
AM
1463
1464@@ -702,7 +710,28 @@
259182b6
ER
1465 "Invalid zlib compression method or flags in IDAT");
1466 }
1467
580fd6fc 1468+#ifdef PNG_WRITE_APNG_SUPPORTED
259182b6
ER
1469+ if(png_ptr->num_frames_written == 0)
1470+#endif
b0807320 1471 png_write_chunk(png_ptr, (png_bytep)png_IDAT, data, length);
580fd6fc 1472+#ifdef PNG_WRITE_APNG_SUPPORTED
259182b6
ER
1473+ else
1474+ {
1475+ png_byte buf[4];
1476+
1477+ png_write_chunk_start(png_ptr, (png_bytep)png_fdAT, 4 + length);
1478+
1479+ png_save_uint_32(buf, png_ptr->next_seq_num);
1480+ png_write_chunk_data(png_ptr, buf, 4);
1481+
1482+ png_write_chunk_data(png_ptr, data, length);
1483+
1484+ png_write_chunk_end(png_ptr);
1485+
1486+ png_ptr->next_seq_num++;
1487+ }
1488+#endif
1489+
1490 png_ptr->mode |= PNG_HAVE_IDAT;
1491 }
1492
00bce163 1493@@ -1709,6 +1738,66 @@
259182b6
ER
1494 }
1495 #endif
1496
580fd6fc 1497+#ifdef PNG_WRITE_APNG_SUPPORTED
259182b6
ER
1498+void /* PRIVATE */
1499+png_write_acTL(png_structp png_ptr,
1500+ png_uint_32 num_frames, png_uint_32 num_plays)
1501+{
259182b6 1502+ PNG_acTL;
259182b6
ER
1503+ png_byte data[16];
1504+
6df9a45f 1505+ png_debug(1, "in png_write_acTL");
259182b6
ER
1506+
1507+ png_ptr->num_frames_to_write = num_frames;
1508+
1509+ if (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN)
1510+ num_frames--;
1511+
1512+ png_save_uint_32(data, num_frames);
1513+ png_save_uint_32(data + 4, num_plays);
1514+
1515+ png_write_chunk(png_ptr, (png_bytep)png_acTL, data, (png_size_t)8);
1516+}
1517+
1518+void /* PRIVATE */
1519+png_write_fcTL(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
1520+ png_uint_32 x_offset, png_uint_32 y_offset,
1521+ png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
1522+ png_byte blend_op)
1523+{
259182b6 1524+ PNG_fcTL;
259182b6
ER
1525+ png_byte data[26];
1526+
6df9a45f 1527+ png_debug(1, "in png_write_fcTL");
259182b6
ER
1528+
1529+ if (png_ptr->num_frames_written == 0 && (x_offset != 0 || y_offset != 0))
6df9a45f 1530+ png_error(png_ptr, "x and/or y offset for the first frame aren't 0");
259182b6
ER
1531+ if (png_ptr->num_frames_written == 0 &&
1532+ (width != png_ptr->first_frame_width ||
1533+ height != png_ptr->first_frame_height))
1534+ png_error(png_ptr, "width and/or height in the first frame's fcTL "
6df9a45f 1535+ "don't match the ones in IHDR");
259182b6
ER
1536+
1537+ /* more error checking */
1538+ png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset,
1539+ delay_num, delay_den, dispose_op, blend_op);
1540+
1541+ png_save_uint_32(data, png_ptr->next_seq_num);
1542+ png_save_uint_32(data + 4, width);
1543+ png_save_uint_32(data + 8, height);
1544+ png_save_uint_32(data + 12, x_offset);
1545+ png_save_uint_32(data + 16, y_offset);
1546+ png_save_uint_16(data + 20, delay_num);
1547+ png_save_uint_16(data + 22, delay_den);
1548+ data[24] = dispose_op;
1549+ data[25] = blend_op;
1550+
1551+ png_write_chunk(png_ptr, (png_bytep)png_fcTL, data, (png_size_t)26);
1552+
1553+ png_ptr->next_seq_num++;
1554+}
1555+#endif /* PNG_WRITE_APNG_SUPPORTED */
1556+
6df9a45f 1557 /* Initializes the row writing capability of libpng */
259182b6
ER
1558 void /* PRIVATE */
1559 png_write_start_row(png_structp png_ptr)
00bce163 1560@@ -2110,8 +2199,8 @@
b0807320
ER
1561 #ifndef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
1562 if (png_ptr->row_number == 0 && filter_to_do == PNG_ALL_FILTERS)
1563 {
1564- /* These will never be selected so we need not test them. */
1565- filter_to_do &= ~(PNG_FILTER_UP | PNG_FILTER_PAETH);
1566+ /* These use previous row */
1567+ filter_to_do &= ~(PNG_FILTER_UP | PNG_FILTER_AVG | PNG_FILTER_PAETH);
1568 }
1569 #endif
1570
00bce163 1571@@ -2780,4 +2869,39 @@
259182b6
ER
1572 }
1573 #endif
1574 }
1575+
580fd6fc 1576+#ifdef PNG_WRITE_APNG_SUPPORTED
259182b6
ER
1577+void /* PRIVATE */
1578+png_write_reset(png_structp png_ptr)
1579+{
1580+ png_ptr->row_number = 0;
1581+ png_ptr->pass = 0;
1582+ png_ptr->mode &= ~PNG_HAVE_IDAT;
1583+}
1584+
1585+void /* PRIVATE */
1586+png_write_reinit(png_structp png_ptr, png_infop info_ptr,
1587+ png_uint_32 width, png_uint_32 height)
1588+{
1589+ if (png_ptr->num_frames_written == 0 &&
1590+ (width != png_ptr->first_frame_width ||
1591+ height != png_ptr->first_frame_height))
1592+ png_error(png_ptr, "width and/or height in the first frame's fcTL "
6df9a45f 1593+ "don't match the ones in IHDR");
259182b6
ER
1594+ if (width > png_ptr->first_frame_width ||
1595+ height > png_ptr->first_frame_height)
1596+ png_error(png_ptr, "width and/or height for a frame greater than"
1597+ "the ones in IHDR");
1598+
1599+ png_set_IHDR(png_ptr, info_ptr, width, height,
1600+ info_ptr->bit_depth, info_ptr->color_type,
1601+ info_ptr->interlace_type, info_ptr->compression_type,
1602+ info_ptr->filter_type);
1603+
1604+ png_ptr->width = width;
1605+ png_ptr->height = height;
1606+ png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width);
1607+ png_ptr->usr_width = png_ptr->width;
1608+}
1609+#endif
1610 #endif /* PNG_WRITE_SUPPORTED */
b0807320
ER
1611Index: pngrtran.c
1612===================================================================
1613--- pngrtran.c
1614+++ pngrtran.c
00bce163 1615@@ -1320,7 +1320,7 @@
b0807320
ER
1616 * pixels. This check added to libpng-1.2.19
1617 */
1618 #if (PNG_WARN_UNINITIALIZED_ROW==1)
1619- png_error(png_ptr, "Uninitialized row");
1620+ png_warning(png_ptr, "Uninitialized row");
1621 #else
1622 png_warning(png_ptr, "Uninitialized row");
1623 #endif
This page took 0.562168 seconds and 4 git commands to generate.