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