1 :
2 : /* pngset.c - storage of image information into info struct
3 : *
4 : * Last changed in libpng 1.5.7 [December 15, 2011]
5 : * Copyright (c) 1998-2011 Glenn Randers-Pehrson
6 : * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
7 : * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
8 : *
9 : * This code is released under the libpng license.
10 : * For conditions of distribution and use, see the disclaimer
11 : * and license in png.h
12 : *
13 : * The functions here are used during reads to store data from the file
14 : * into the info struct, and during writes to store application data
15 : * into the info struct for writing into the file. This abstracts the
16 : * info struct and allows us to change the structure in the future.
17 : */
18 :
19 : #include "pngpriv.h"
20 :
21 : #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
22 :
23 : #ifdef PNG_bKGD_SUPPORTED
24 : void PNGAPI
25 : png_set_bKGD(png_structp png_ptr, png_infop info_ptr,
26 : png_const_color_16p background)
27 : {
28 : png_debug1(1, "in %s storage function", "bKGD");
29 :
30 : if (png_ptr == NULL || info_ptr == NULL)
31 : return;
32 :
33 : png_memcpy(&(info_ptr->background), background, png_sizeof(png_color_16));
34 : info_ptr->valid |= PNG_INFO_bKGD;
35 : }
36 : #endif
37 :
38 : #ifdef PNG_cHRM_SUPPORTED
39 : void PNGFAPI
40 0 : png_set_cHRM_fixed(png_structp png_ptr, png_infop info_ptr,
41 : png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x,
42 : png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y,
43 : png_fixed_point blue_x, png_fixed_point blue_y)
44 : {
45 : png_debug1(1, "in %s storage function", "cHRM fixed");
46 :
47 0 : if (png_ptr == NULL || info_ptr == NULL)
48 0 : return;
49 :
50 : # ifdef PNG_CHECK_cHRM_SUPPORTED
51 0 : if (png_check_cHRM_fixed(png_ptr,
52 : white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y))
53 : # endif
54 : {
55 0 : info_ptr->x_white = white_x;
56 0 : info_ptr->y_white = white_y;
57 0 : info_ptr->x_red = red_x;
58 0 : info_ptr->y_red = red_y;
59 0 : info_ptr->x_green = green_x;
60 0 : info_ptr->y_green = green_y;
61 0 : info_ptr->x_blue = blue_x;
62 0 : info_ptr->y_blue = blue_y;
63 0 : info_ptr->valid |= PNG_INFO_cHRM;
64 : }
65 : }
66 :
67 : void PNGFAPI
68 0 : png_set_cHRM_XYZ_fixed(png_structp png_ptr, png_infop info_ptr,
69 : png_fixed_point int_red_X, png_fixed_point int_red_Y,
70 : png_fixed_point int_red_Z, png_fixed_point int_green_X,
71 : png_fixed_point int_green_Y, png_fixed_point int_green_Z,
72 : png_fixed_point int_blue_X, png_fixed_point int_blue_Y,
73 : png_fixed_point int_blue_Z)
74 : {
75 : png_XYZ XYZ;
76 : png_xy xy;
77 :
78 : png_debug1(1, "in %s storage function", "cHRM XYZ fixed");
79 :
80 0 : if (png_ptr == NULL || info_ptr == NULL)
81 0 : return;
82 :
83 0 : XYZ.redX = int_red_X;
84 0 : XYZ.redY = int_red_Y;
85 0 : XYZ.redZ = int_red_Z;
86 0 : XYZ.greenX = int_green_X;
87 0 : XYZ.greenY = int_green_Y;
88 0 : XYZ.greenZ = int_green_Z;
89 0 : XYZ.blueX = int_blue_X;
90 0 : XYZ.blueY = int_blue_Y;
91 0 : XYZ.blueZ = int_blue_Z;
92 :
93 0 : if (png_xy_from_XYZ(&xy, XYZ))
94 0 : png_error(png_ptr, "XYZ values out of representable range");
95 :
96 0 : png_set_cHRM_fixed(png_ptr, info_ptr, xy.whitex, xy.whitey, xy.redx, xy.redy,
97 : xy.greenx, xy.greeny, xy.bluex, xy.bluey);
98 : }
99 :
100 : # ifdef PNG_FLOATING_POINT_SUPPORTED
101 : void PNGAPI
102 0 : png_set_cHRM(png_structp png_ptr, png_infop info_ptr,
103 : double white_x, double white_y, double red_x, double red_y,
104 : double green_x, double green_y, double blue_x, double blue_y)
105 : {
106 0 : png_set_cHRM_fixed(png_ptr, info_ptr,
107 : png_fixed(png_ptr, white_x, "cHRM White X"),
108 : png_fixed(png_ptr, white_y, "cHRM White Y"),
109 : png_fixed(png_ptr, red_x, "cHRM Red X"),
110 : png_fixed(png_ptr, red_y, "cHRM Red Y"),
111 : png_fixed(png_ptr, green_x, "cHRM Green X"),
112 : png_fixed(png_ptr, green_y, "cHRM Green Y"),
113 : png_fixed(png_ptr, blue_x, "cHRM Blue X"),
114 : png_fixed(png_ptr, blue_y, "cHRM Blue Y"));
115 0 : }
116 :
117 : void PNGAPI
118 0 : png_set_cHRM_XYZ(png_structp png_ptr, png_infop info_ptr, double red_X,
119 : double red_Y, double red_Z, double green_X, double green_Y, double green_Z,
120 : double blue_X, double blue_Y, double blue_Z)
121 : {
122 0 : png_set_cHRM_XYZ_fixed(png_ptr, info_ptr,
123 : png_fixed(png_ptr, red_X, "cHRM Red X"),
124 : png_fixed(png_ptr, red_Y, "cHRM Red Y"),
125 : png_fixed(png_ptr, red_Z, "cHRM Red Z"),
126 : png_fixed(png_ptr, green_X, "cHRM Red X"),
127 : png_fixed(png_ptr, green_Y, "cHRM Red Y"),
128 : png_fixed(png_ptr, green_Z, "cHRM Red Z"),
129 : png_fixed(png_ptr, blue_X, "cHRM Red X"),
130 : png_fixed(png_ptr, blue_Y, "cHRM Red Y"),
131 : png_fixed(png_ptr, blue_Z, "cHRM Red Z"));
132 0 : }
133 : # endif /* PNG_FLOATING_POINT_SUPPORTED */
134 :
135 : #endif /* PNG_cHRM_SUPPORTED */
136 :
137 : #ifdef PNG_gAMA_SUPPORTED
138 : void PNGFAPI
139 1 : png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point
140 : file_gamma)
141 : {
142 : png_debug1(1, "in %s storage function", "gAMA");
143 :
144 1 : if (png_ptr == NULL || info_ptr == NULL)
145 0 : return;
146 :
147 : /* Changed in libpng-1.5.4 to limit the values to ensure overflow can't
148 : * occur. Since the fixed point representation is assymetrical it is
149 : * possible for 1/gamma to overflow the limit of 21474 and this means the
150 : * gamma value must be at least 5/100000 and hence at most 20000.0. For
151 : * safety the limits here are a little narrower. The values are 0.00016 to
152 : * 6250.0, which are truly ridiculous gammma values (and will produce
153 : * displays that are all black or all white.)
154 : */
155 1 : if (file_gamma < 16 || file_gamma > 625000000)
156 : png_warning(png_ptr, "Out of range gamma value ignored");
157 :
158 : else
159 : {
160 1 : info_ptr->gamma = file_gamma;
161 1 : info_ptr->valid |= PNG_INFO_gAMA;
162 : }
163 : }
164 :
165 : # ifdef PNG_FLOATING_POINT_SUPPORTED
166 : void PNGAPI
167 0 : png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma)
168 : {
169 0 : png_set_gAMA_fixed(png_ptr, info_ptr, png_fixed(png_ptr, file_gamma,
170 : "png_set_gAMA"));
171 0 : }
172 : # endif
173 : #endif
174 :
175 : #ifdef PNG_hIST_SUPPORTED
176 : void PNGAPI
177 : png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_const_uint_16p hist)
178 : {
179 : int i;
180 :
181 : png_debug1(1, "in %s storage function", "hIST");
182 :
183 : if (png_ptr == NULL || info_ptr == NULL)
184 : return;
185 :
186 : if (info_ptr->num_palette == 0 || info_ptr->num_palette
187 : > PNG_MAX_PALETTE_LENGTH)
188 : {
189 : png_warning(png_ptr,
190 : "Invalid palette size, hIST allocation skipped");
191 :
192 : return;
193 : }
194 :
195 : png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0);
196 :
197 : /* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in
198 : * version 1.2.1
199 : */
200 : png_ptr->hist = (png_uint_16p)png_malloc_warn(png_ptr,
201 : PNG_MAX_PALETTE_LENGTH * png_sizeof(png_uint_16));
202 :
203 : if (png_ptr->hist == NULL)
204 : {
205 : png_warning(png_ptr, "Insufficient memory for hIST chunk data");
206 : return;
207 : }
208 :
209 : for (i = 0; i < info_ptr->num_palette; i++)
210 : png_ptr->hist[i] = hist[i];
211 :
212 : info_ptr->hist = png_ptr->hist;
213 : info_ptr->valid |= PNG_INFO_hIST;
214 : info_ptr->free_me |= PNG_FREE_HIST;
215 : }
216 : #endif
217 :
218 : void PNGAPI
219 49 : png_set_IHDR(png_structp png_ptr, png_infop info_ptr,
220 : png_uint_32 width, png_uint_32 height, int bit_depth,
221 : int color_type, int interlace_type, int compression_type,
222 : int filter_type)
223 : {
224 : png_debug1(1, "in %s storage function", "IHDR");
225 :
226 49 : if (png_ptr == NULL || info_ptr == NULL)
227 0 : return;
228 :
229 49 : info_ptr->width = width;
230 49 : info_ptr->height = height;
231 49 : info_ptr->bit_depth = (png_byte)bit_depth;
232 49 : info_ptr->color_type = (png_byte)color_type;
233 49 : info_ptr->compression_type = (png_byte)compression_type;
234 49 : info_ptr->filter_type = (png_byte)filter_type;
235 49 : info_ptr->interlace_type = (png_byte)interlace_type;
236 :
237 245 : png_check_IHDR (png_ptr, info_ptr->width, info_ptr->height,
238 147 : info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type,
239 98 : info_ptr->compression_type, info_ptr->filter_type);
240 :
241 49 : if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
242 0 : info_ptr->channels = 1;
243 :
244 49 : else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
245 49 : info_ptr->channels = 3;
246 :
247 : else
248 0 : info_ptr->channels = 1;
249 :
250 49 : if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
251 38 : info_ptr->channels++;
252 :
253 49 : info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth);
254 :
255 : /* Check for potential overflow */
256 49 : if (width >
257 : (PNG_UINT_32_MAX >> 3) /* 8-byte RRGGBBAA pixels */
258 : - 48 /* bigrowbuf hack */
259 : - 1 /* filter byte */
260 : - 7*8 /* rounding of width to multiple of 8 pixels */
261 : - 8) /* extra max_pixel_depth pad */
262 0 : info_ptr->rowbytes = 0;
263 : else
264 49 : info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width);
265 :
266 : #ifdef PNG_APNG_SUPPORTED
267 : /* for non-animated png. this may be overwritten from an acTL chunk later */
268 49 : info_ptr->num_frames = 1;
269 : #endif
270 : }
271 :
272 : #ifdef PNG_oFFs_SUPPORTED
273 : void PNGAPI
274 : png_set_oFFs(png_structp png_ptr, png_infop info_ptr,
275 : png_int_32 offset_x, png_int_32 offset_y, int unit_type)
276 : {
277 : png_debug1(1, "in %s storage function", "oFFs");
278 :
279 : if (png_ptr == NULL || info_ptr == NULL)
280 : return;
281 :
282 : info_ptr->x_offset = offset_x;
283 : info_ptr->y_offset = offset_y;
284 : info_ptr->offset_unit_type = (png_byte)unit_type;
285 : info_ptr->valid |= PNG_INFO_oFFs;
286 : }
287 : #endif
288 :
289 : #ifdef PNG_pCAL_SUPPORTED
290 : void PNGAPI
291 : png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
292 : png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type,
293 : int nparams, png_const_charp units, png_charpp params)
294 : {
295 : png_size_t length;
296 : int i;
297 :
298 : png_debug1(1, "in %s storage function", "pCAL");
299 :
300 : if (png_ptr == NULL || info_ptr == NULL)
301 : return;
302 :
303 : length = png_strlen(purpose) + 1;
304 : png_debug1(3, "allocating purpose for info (%lu bytes)",
305 : (unsigned long)length);
306 :
307 : /* TODO: validate format of calibration name and unit name */
308 :
309 : /* Check that the type matches the specification. */
310 : if (type < 0 || type > 3)
311 : png_error(png_ptr, "Invalid pCAL equation type");
312 :
313 : /* Validate params[nparams] */
314 : for (i=0; i<nparams; ++i)
315 : if (!png_check_fp_string(params[i], png_strlen(params[i])))
316 : png_error(png_ptr, "Invalid format for pCAL parameter");
317 :
318 : info_ptr->pcal_purpose = (png_charp)png_malloc_warn(png_ptr, length);
319 :
320 : if (info_ptr->pcal_purpose == NULL)
321 : {
322 : png_warning(png_ptr, "Insufficient memory for pCAL purpose");
323 : return;
324 : }
325 :
326 : png_memcpy(info_ptr->pcal_purpose, purpose, length);
327 :
328 : png_debug(3, "storing X0, X1, type, and nparams in info");
329 : info_ptr->pcal_X0 = X0;
330 : info_ptr->pcal_X1 = X1;
331 : info_ptr->pcal_type = (png_byte)type;
332 : info_ptr->pcal_nparams = (png_byte)nparams;
333 :
334 : length = png_strlen(units) + 1;
335 : png_debug1(3, "allocating units for info (%lu bytes)",
336 : (unsigned long)length);
337 :
338 : info_ptr->pcal_units = (png_charp)png_malloc_warn(png_ptr, length);
339 :
340 : if (info_ptr->pcal_units == NULL)
341 : {
342 : png_warning(png_ptr, "Insufficient memory for pCAL units");
343 : return;
344 : }
345 :
346 : png_memcpy(info_ptr->pcal_units, units, length);
347 :
348 : info_ptr->pcal_params = (png_charpp)png_malloc_warn(png_ptr,
349 : (png_size_t)((nparams + 1) * png_sizeof(png_charp)));
350 :
351 : if (info_ptr->pcal_params == NULL)
352 : {
353 : png_warning(png_ptr, "Insufficient memory for pCAL params");
354 : return;
355 : }
356 :
357 : png_memset(info_ptr->pcal_params, 0, (nparams + 1) * png_sizeof(png_charp));
358 :
359 : for (i = 0; i < nparams; i++)
360 : {
361 : length = png_strlen(params[i]) + 1;
362 : png_debug2(3, "allocating parameter %d for info (%lu bytes)", i,
363 : (unsigned long)length);
364 :
365 : info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length);
366 :
367 : if (info_ptr->pcal_params[i] == NULL)
368 : {
369 : png_warning(png_ptr, "Insufficient memory for pCAL parameter");
370 : return;
371 : }
372 :
373 : png_memcpy(info_ptr->pcal_params[i], params[i], length);
374 : }
375 :
376 : info_ptr->valid |= PNG_INFO_pCAL;
377 : info_ptr->free_me |= PNG_FREE_PCAL;
378 : }
379 : #endif
380 :
381 : #ifdef PNG_sCAL_SUPPORTED
382 : void PNGAPI
383 : png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr,
384 : int unit, png_const_charp swidth, png_const_charp sheight)
385 : {
386 : png_size_t lengthw = 0, lengthh = 0;
387 :
388 : png_debug1(1, "in %s storage function", "sCAL");
389 :
390 : if (png_ptr == NULL || info_ptr == NULL)
391 : return;
392 :
393 : /* Double check the unit (should never get here with an invalid
394 : * unit unless this is an API call.)
395 : */
396 : if (unit != 1 && unit != 2)
397 : png_error(png_ptr, "Invalid sCAL unit");
398 :
399 : if (swidth == NULL || (lengthw = png_strlen(swidth)) == 0 ||
400 : swidth[0] == 45 /* '-' */ || !png_check_fp_string(swidth, lengthw))
401 : png_error(png_ptr, "Invalid sCAL width");
402 :
403 : if (sheight == NULL || (lengthh = png_strlen(sheight)) == 0 ||
404 : sheight[0] == 45 /* '-' */ || !png_check_fp_string(sheight, lengthh))
405 : png_error(png_ptr, "Invalid sCAL height");
406 :
407 : info_ptr->scal_unit = (png_byte)unit;
408 :
409 : ++lengthw;
410 :
411 : png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthw);
412 :
413 : info_ptr->scal_s_width = (png_charp)png_malloc_warn(png_ptr, lengthw);
414 :
415 : if (info_ptr->scal_s_width == NULL)
416 : {
417 : png_warning(png_ptr, "Memory allocation failed while processing sCAL");
418 : return;
419 : }
420 :
421 : png_memcpy(info_ptr->scal_s_width, swidth, lengthw);
422 :
423 : ++lengthh;
424 :
425 : png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthh);
426 :
427 : info_ptr->scal_s_height = (png_charp)png_malloc_warn(png_ptr, lengthh);
428 :
429 : if (info_ptr->scal_s_height == NULL)
430 : {
431 : png_free (png_ptr, info_ptr->scal_s_width);
432 : info_ptr->scal_s_width = NULL;
433 :
434 : png_warning(png_ptr, "Memory allocation failed while processing sCAL");
435 : return;
436 : }
437 :
438 : png_memcpy(info_ptr->scal_s_height, sheight, lengthh);
439 :
440 : info_ptr->valid |= PNG_INFO_sCAL;
441 : info_ptr->free_me |= PNG_FREE_SCAL;
442 : }
443 :
444 : # ifdef PNG_FLOATING_POINT_SUPPORTED
445 : void PNGAPI
446 : png_set_sCAL(png_structp png_ptr, png_infop info_ptr, int unit, double width,
447 : double height)
448 : {
449 : png_debug1(1, "in %s storage function", "sCAL");
450 :
451 : /* Check the arguments. */
452 : if (width <= 0)
453 : png_warning(png_ptr, "Invalid sCAL width ignored");
454 :
455 : else if (height <= 0)
456 : png_warning(png_ptr, "Invalid sCAL height ignored");
457 :
458 : else
459 : {
460 : /* Convert 'width' and 'height' to ASCII. */
461 : char swidth[PNG_sCAL_MAX_DIGITS+1];
462 : char sheight[PNG_sCAL_MAX_DIGITS+1];
463 :
464 : png_ascii_from_fp(png_ptr, swidth, sizeof swidth, width,
465 : PNG_sCAL_PRECISION);
466 : png_ascii_from_fp(png_ptr, sheight, sizeof sheight, height,
467 : PNG_sCAL_PRECISION);
468 :
469 : png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight);
470 : }
471 : }
472 : # endif
473 :
474 : # ifdef PNG_FIXED_POINT_SUPPORTED
475 : void PNGAPI
476 : png_set_sCAL_fixed(png_structp png_ptr, png_infop info_ptr, int unit,
477 : png_fixed_point width, png_fixed_point height)
478 : {
479 : png_debug1(1, "in %s storage function", "sCAL");
480 :
481 : /* Check the arguments. */
482 : if (width <= 0)
483 : png_warning(png_ptr, "Invalid sCAL width ignored");
484 :
485 : else if (height <= 0)
486 : png_warning(png_ptr, "Invalid sCAL height ignored");
487 :
488 : else
489 : {
490 : /* Convert 'width' and 'height' to ASCII. */
491 : char swidth[PNG_sCAL_MAX_DIGITS+1];
492 : char sheight[PNG_sCAL_MAX_DIGITS+1];
493 :
494 : png_ascii_from_fixed(png_ptr, swidth, sizeof swidth, width);
495 : png_ascii_from_fixed(png_ptr, sheight, sizeof sheight, height);
496 :
497 : png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight);
498 : }
499 : }
500 : # endif
501 : #endif
502 :
503 : #ifdef PNG_pHYs_SUPPORTED
504 : void PNGAPI
505 : png_set_pHYs(png_structp png_ptr, png_infop info_ptr,
506 : png_uint_32 res_x, png_uint_32 res_y, int unit_type)
507 : {
508 : png_debug1(1, "in %s storage function", "pHYs");
509 :
510 : if (png_ptr == NULL || info_ptr == NULL)
511 : return;
512 :
513 : info_ptr->x_pixels_per_unit = res_x;
514 : info_ptr->y_pixels_per_unit = res_y;
515 : info_ptr->phys_unit_type = (png_byte)unit_type;
516 : info_ptr->valid |= PNG_INFO_pHYs;
517 : }
518 : #endif
519 :
520 : void PNGAPI
521 0 : png_set_PLTE(png_structp png_ptr, png_infop info_ptr,
522 : png_const_colorp palette, int num_palette)
523 : {
524 :
525 : png_debug1(1, "in %s storage function", "PLTE");
526 :
527 0 : if (png_ptr == NULL || info_ptr == NULL)
528 0 : return;
529 :
530 0 : if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH)
531 : {
532 0 : if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
533 0 : png_error(png_ptr, "Invalid palette length");
534 :
535 : else
536 : {
537 : png_warning(png_ptr, "Invalid palette length");
538 0 : return;
539 : }
540 : }
541 :
542 : /* It may not actually be necessary to set png_ptr->palette here;
543 : * we do it for backward compatibility with the way the png_handle_tRNS
544 : * function used to do the allocation.
545 : */
546 0 : png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0);
547 :
548 : /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead
549 : * of num_palette entries, in case of an invalid PNG file that has
550 : * too-large sample values.
551 : */
552 0 : png_ptr->palette = (png_colorp)png_calloc(png_ptr,
553 : PNG_MAX_PALETTE_LENGTH * png_sizeof(png_color));
554 :
555 0 : png_memcpy(png_ptr->palette, palette, num_palette * png_sizeof(png_color));
556 0 : info_ptr->palette = png_ptr->palette;
557 0 : info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette;
558 :
559 0 : info_ptr->free_me |= PNG_FREE_PLTE;
560 :
561 0 : info_ptr->valid |= PNG_INFO_PLTE;
562 : }
563 :
564 : #ifdef PNG_sBIT_SUPPORTED
565 : void PNGAPI
566 : png_set_sBIT(png_structp png_ptr, png_infop info_ptr,
567 : png_const_color_8p sig_bit)
568 : {
569 : png_debug1(1, "in %s storage function", "sBIT");
570 :
571 : if (png_ptr == NULL || info_ptr == NULL)
572 : return;
573 :
574 : png_memcpy(&(info_ptr->sig_bit), sig_bit, png_sizeof(png_color_8));
575 : info_ptr->valid |= PNG_INFO_sBIT;
576 : }
577 : #endif
578 :
579 : #ifdef PNG_sRGB_SUPPORTED
580 : void PNGAPI
581 0 : png_set_sRGB(png_structp png_ptr, png_infop info_ptr, int srgb_intent)
582 : {
583 : png_debug1(1, "in %s storage function", "sRGB");
584 :
585 0 : if (png_ptr == NULL || info_ptr == NULL)
586 0 : return;
587 :
588 0 : info_ptr->srgb_intent = (png_byte)srgb_intent;
589 0 : info_ptr->valid |= PNG_INFO_sRGB;
590 : }
591 :
592 : void PNGAPI
593 0 : png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr,
594 : int srgb_intent)
595 : {
596 : png_debug1(1, "in %s storage function", "sRGB_gAMA_and_cHRM");
597 :
598 0 : if (png_ptr == NULL || info_ptr == NULL)
599 0 : return;
600 :
601 0 : png_set_sRGB(png_ptr, info_ptr, srgb_intent);
602 :
603 : # ifdef PNG_gAMA_SUPPORTED
604 0 : png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE);
605 : # endif
606 :
607 : # ifdef PNG_cHRM_SUPPORTED
608 0 : png_set_cHRM_fixed(png_ptr, info_ptr,
609 : /* color x y */
610 : /* white */ 31270, 32900,
611 : /* red */ 64000, 33000,
612 : /* green */ 30000, 60000,
613 : /* blue */ 15000, 6000
614 : );
615 : # endif /* cHRM */
616 : }
617 : #endif /* sRGB */
618 :
619 :
620 : #ifdef PNG_iCCP_SUPPORTED
621 : void PNGAPI
622 0 : png_set_iCCP(png_structp png_ptr, png_infop info_ptr,
623 : png_const_charp name, int compression_type,
624 : png_const_bytep profile, png_uint_32 proflen)
625 : {
626 : png_charp new_iccp_name;
627 : png_bytep new_iccp_profile;
628 : png_size_t length;
629 :
630 : png_debug1(1, "in %s storage function", "iCCP");
631 :
632 0 : if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL)
633 0 : return;
634 :
635 0 : length = png_strlen(name)+1;
636 0 : new_iccp_name = (png_charp)png_malloc_warn(png_ptr, length);
637 :
638 0 : if (new_iccp_name == NULL)
639 : {
640 : png_warning(png_ptr, "Insufficient memory to process iCCP chunk");
641 0 : return;
642 : }
643 :
644 0 : png_memcpy(new_iccp_name, name, length);
645 0 : new_iccp_profile = (png_bytep)png_malloc_warn(png_ptr, proflen);
646 :
647 0 : if (new_iccp_profile == NULL)
648 : {
649 0 : png_free (png_ptr, new_iccp_name);
650 : png_warning(png_ptr,
651 : "Insufficient memory to process iCCP profile");
652 0 : return;
653 : }
654 :
655 0 : png_memcpy(new_iccp_profile, profile, (png_size_t)proflen);
656 :
657 0 : png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0);
658 :
659 0 : info_ptr->iccp_proflen = proflen;
660 0 : info_ptr->iccp_name = new_iccp_name;
661 0 : info_ptr->iccp_profile = new_iccp_profile;
662 : /* Compression is always zero but is here so the API and info structure
663 : * does not have to change if we introduce multiple compression types
664 : */
665 0 : info_ptr->iccp_compression = (png_byte)compression_type;
666 0 : info_ptr->free_me |= PNG_FREE_ICCP;
667 0 : info_ptr->valid |= PNG_INFO_iCCP;
668 : }
669 : #endif
670 :
671 : #ifdef PNG_TEXT_SUPPORTED
672 : void PNGAPI
673 0 : png_set_text(png_structp png_ptr, png_infop info_ptr, png_const_textp text_ptr,
674 : int num_text)
675 : {
676 : int ret;
677 0 : ret = png_set_text_2(png_ptr, info_ptr, text_ptr, num_text);
678 :
679 0 : if (ret)
680 0 : png_error(png_ptr, "Insufficient memory to store text");
681 0 : }
682 :
683 : int /* PRIVATE */
684 0 : png_set_text_2(png_structp png_ptr, png_infop info_ptr,
685 : png_const_textp text_ptr, int num_text)
686 : {
687 : int i;
688 :
689 : png_debug1(1, "in %lx storage function", png_ptr == NULL ? "unexpected" :
690 : (unsigned long)png_ptr->chunk_name);
691 :
692 0 : if (png_ptr == NULL || info_ptr == NULL || num_text == 0)
693 0 : return(0);
694 :
695 : /* Make sure we have enough space in the "text" array in info_struct
696 : * to hold all of the incoming text_ptr objects.
697 : */
698 0 : if (info_ptr->num_text + num_text > info_ptr->max_text)
699 : {
700 0 : if (info_ptr->text != NULL)
701 : {
702 : png_textp old_text;
703 : int old_max;
704 :
705 0 : old_max = info_ptr->max_text;
706 0 : info_ptr->max_text = info_ptr->num_text + num_text + 8;
707 0 : old_text = info_ptr->text;
708 0 : info_ptr->text = (png_textp)png_malloc_warn(png_ptr,
709 0 : (png_size_t)(info_ptr->max_text * png_sizeof(png_text)));
710 :
711 0 : if (info_ptr->text == NULL)
712 : {
713 0 : png_free(png_ptr, old_text);
714 0 : return(1);
715 : }
716 :
717 0 : png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max *
718 : png_sizeof(png_text)));
719 0 : png_free(png_ptr, old_text);
720 : }
721 :
722 : else
723 : {
724 0 : info_ptr->max_text = num_text + 8;
725 0 : info_ptr->num_text = 0;
726 0 : info_ptr->text = (png_textp)png_malloc_warn(png_ptr,
727 0 : (png_size_t)(info_ptr->max_text * png_sizeof(png_text)));
728 0 : if (info_ptr->text == NULL)
729 0 : return(1);
730 0 : info_ptr->free_me |= PNG_FREE_TEXT;
731 : }
732 :
733 : png_debug1(3, "allocated %d entries for info_ptr->text",
734 : info_ptr->max_text);
735 : }
736 0 : for (i = 0; i < num_text; i++)
737 : {
738 : png_size_t text_length, key_len;
739 : png_size_t lang_len, lang_key_len;
740 0 : png_textp textp = &(info_ptr->text[info_ptr->num_text]);
741 :
742 0 : if (text_ptr[i].key == NULL)
743 0 : continue;
744 :
745 0 : if (text_ptr[i].compression < PNG_TEXT_COMPRESSION_NONE ||
746 0 : text_ptr[i].compression >= PNG_TEXT_COMPRESSION_LAST)
747 : {
748 : png_warning(png_ptr, "text compression mode is out of range");
749 0 : continue;
750 : }
751 :
752 0 : key_len = png_strlen(text_ptr[i].key);
753 :
754 0 : if (text_ptr[i].compression <= 0)
755 : {
756 0 : lang_len = 0;
757 0 : lang_key_len = 0;
758 : }
759 :
760 : else
761 : # ifdef PNG_iTXt_SUPPORTED
762 : {
763 : /* Set iTXt data */
764 :
765 : if (text_ptr[i].lang != NULL)
766 : lang_len = png_strlen(text_ptr[i].lang);
767 :
768 : else
769 : lang_len = 0;
770 :
771 : if (text_ptr[i].lang_key != NULL)
772 : lang_key_len = png_strlen(text_ptr[i].lang_key);
773 :
774 : else
775 : lang_key_len = 0;
776 : }
777 : # else /* PNG_iTXt_SUPPORTED */
778 : {
779 : png_warning(png_ptr, "iTXt chunk not supported");
780 0 : continue;
781 : }
782 : # endif
783 :
784 0 : if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0')
785 : {
786 0 : text_length = 0;
787 : # ifdef PNG_iTXt_SUPPORTED
788 : if (text_ptr[i].compression > 0)
789 : textp->compression = PNG_ITXT_COMPRESSION_NONE;
790 :
791 : else
792 : # endif
793 0 : textp->compression = PNG_TEXT_COMPRESSION_NONE;
794 : }
795 :
796 : else
797 : {
798 0 : text_length = png_strlen(text_ptr[i].text);
799 0 : textp->compression = text_ptr[i].compression;
800 : }
801 :
802 0 : textp->key = (png_charp)png_malloc_warn(png_ptr,
803 : (png_size_t)
804 0 : (key_len + text_length + lang_len + lang_key_len + 4));
805 :
806 0 : if (textp->key == NULL)
807 0 : return(1);
808 :
809 : png_debug2(2, "Allocated %lu bytes at %p in png_set_text",
810 : (unsigned long)(png_uint_32)
811 : (key_len + lang_len + lang_key_len + text_length + 4),
812 : textp->key);
813 :
814 0 : png_memcpy(textp->key, text_ptr[i].key,(png_size_t)(key_len));
815 0 : *(textp->key + key_len) = '\0';
816 :
817 0 : if (text_ptr[i].compression > 0)
818 : {
819 0 : textp->lang = textp->key + key_len + 1;
820 0 : png_memcpy(textp->lang, text_ptr[i].lang, lang_len);
821 0 : *(textp->lang + lang_len) = '\0';
822 0 : textp->lang_key = textp->lang + lang_len + 1;
823 0 : png_memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len);
824 0 : *(textp->lang_key + lang_key_len) = '\0';
825 0 : textp->text = textp->lang_key + lang_key_len + 1;
826 : }
827 :
828 : else
829 : {
830 0 : textp->lang=NULL;
831 0 : textp->lang_key=NULL;
832 0 : textp->text = textp->key + key_len + 1;
833 : }
834 :
835 0 : if (text_length)
836 0 : png_memcpy(textp->text, text_ptr[i].text,
837 : (png_size_t)(text_length));
838 :
839 0 : *(textp->text + text_length) = '\0';
840 :
841 : # ifdef PNG_iTXt_SUPPORTED
842 : if (textp->compression > 0)
843 : {
844 : textp->text_length = 0;
845 : textp->itxt_length = text_length;
846 : }
847 :
848 : else
849 : # endif
850 : {
851 0 : textp->text_length = text_length;
852 0 : textp->itxt_length = 0;
853 : }
854 :
855 0 : info_ptr->num_text++;
856 : png_debug1(3, "transferred text chunk %d", info_ptr->num_text);
857 : }
858 0 : return(0);
859 : }
860 : #endif
861 :
862 : #ifdef PNG_tIME_SUPPORTED
863 : void PNGAPI
864 : png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_const_timep mod_time)
865 : {
866 : png_debug1(1, "in %s storage function", "tIME");
867 :
868 : if (png_ptr == NULL || info_ptr == NULL ||
869 : (png_ptr->mode & PNG_WROTE_tIME))
870 : return;
871 :
872 : if (mod_time->month == 0 || mod_time->month > 12 ||
873 : mod_time->day == 0 || mod_time->day > 31 ||
874 : mod_time->hour > 23 || mod_time->minute > 59 ||
875 : mod_time->second > 60)
876 : {
877 : png_warning(png_ptr, "Ignoring invalid time value");
878 : return;
879 : }
880 :
881 : png_memcpy(&(info_ptr->mod_time), mod_time, png_sizeof(png_time));
882 : info_ptr->valid |= PNG_INFO_tIME;
883 : }
884 : #endif
885 :
886 : #ifdef PNG_tRNS_SUPPORTED
887 : void PNGAPI
888 0 : png_set_tRNS(png_structp png_ptr, png_infop info_ptr,
889 : png_const_bytep trans_alpha, int num_trans, png_const_color_16p trans_color)
890 : {
891 : png_debug1(1, "in %s storage function", "tRNS");
892 :
893 0 : if (png_ptr == NULL || info_ptr == NULL)
894 0 : return;
895 :
896 0 : if (trans_alpha != NULL)
897 : {
898 : /* It may not actually be necessary to set png_ptr->trans_alpha here;
899 : * we do it for backward compatibility with the way the png_handle_tRNS
900 : * function used to do the allocation.
901 : */
902 :
903 0 : png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
904 :
905 : /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */
906 0 : png_ptr->trans_alpha = info_ptr->trans_alpha =
907 0 : (png_bytep)png_malloc(png_ptr, (png_size_t)PNG_MAX_PALETTE_LENGTH);
908 :
909 0 : if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH)
910 0 : png_memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans);
911 : }
912 :
913 0 : if (trans_color != NULL)
914 : {
915 0 : int sample_max = (1 << info_ptr->bit_depth);
916 :
917 0 : if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY &&
918 0 : (int)trans_color->gray > sample_max) ||
919 : (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
920 : ((int)trans_color->red > sample_max ||
921 : (int)trans_color->green > sample_max ||
922 : (int)trans_color->blue > sample_max)))
923 : png_warning(png_ptr,
924 : "tRNS chunk has out-of-range samples for bit_depth");
925 :
926 0 : png_memcpy(&(info_ptr->trans_color), trans_color,
927 : png_sizeof(png_color_16));
928 :
929 0 : if (num_trans == 0)
930 0 : num_trans = 1;
931 : }
932 :
933 0 : info_ptr->num_trans = (png_uint_16)num_trans;
934 :
935 0 : if (num_trans != 0)
936 : {
937 0 : info_ptr->valid |= PNG_INFO_tRNS;
938 0 : info_ptr->free_me |= PNG_FREE_TRNS;
939 : }
940 : }
941 : #endif
942 :
943 : #ifdef PNG_sPLT_SUPPORTED
944 : void PNGAPI
945 : png_set_sPLT(png_structp png_ptr,
946 : png_infop info_ptr, png_const_sPLT_tp entries, int nentries)
947 : /*
948 : * entries - array of png_sPLT_t structures
949 : * to be added to the list of palettes
950 : * in the info structure.
951 : *
952 : * nentries - number of palette structures to be
953 : * added.
954 : */
955 : {
956 : png_sPLT_tp np;
957 : int i;
958 :
959 : if (png_ptr == NULL || info_ptr == NULL)
960 : return;
961 :
962 : np = (png_sPLT_tp)png_malloc_warn(png_ptr,
963 : (info_ptr->splt_palettes_num + nentries) *
964 : (png_size_t)png_sizeof(png_sPLT_t));
965 :
966 : if (np == NULL)
967 : {
968 : png_warning(png_ptr, "No memory for sPLT palettes");
969 : return;
970 : }
971 :
972 : png_memcpy(np, info_ptr->splt_palettes,
973 : info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t));
974 :
975 : png_free(png_ptr, info_ptr->splt_palettes);
976 : info_ptr->splt_palettes=NULL;
977 :
978 : for (i = 0; i < nentries; i++)
979 : {
980 : png_sPLT_tp to = np + info_ptr->splt_palettes_num + i;
981 : png_const_sPLT_tp from = entries + i;
982 : png_size_t length;
983 :
984 : length = png_strlen(from->name) + 1;
985 : to->name = (png_charp)png_malloc_warn(png_ptr, length);
986 :
987 : if (to->name == NULL)
988 : {
989 : png_warning(png_ptr,
990 : "Out of memory while processing sPLT chunk");
991 : continue;
992 : }
993 :
994 : png_memcpy(to->name, from->name, length);
995 : to->entries = (png_sPLT_entryp)png_malloc_warn(png_ptr,
996 : from->nentries * png_sizeof(png_sPLT_entry));
997 :
998 : if (to->entries == NULL)
999 : {
1000 : png_warning(png_ptr,
1001 : "Out of memory while processing sPLT chunk");
1002 : png_free(png_ptr, to->name);
1003 : to->name = NULL;
1004 : continue;
1005 : }
1006 :
1007 : png_memcpy(to->entries, from->entries,
1008 : from->nentries * png_sizeof(png_sPLT_entry));
1009 :
1010 : to->nentries = from->nentries;
1011 : to->depth = from->depth;
1012 : }
1013 :
1014 : info_ptr->splt_palettes = np;
1015 : info_ptr->splt_palettes_num += nentries;
1016 : info_ptr->valid |= PNG_INFO_sPLT;
1017 : info_ptr->free_me |= PNG_FREE_SPLT;
1018 : }
1019 : #endif /* PNG_sPLT_SUPPORTED */
1020 :
1021 : #ifdef PNG_APNG_SUPPORTED
1022 : png_uint_32 PNGAPI
1023 6 : png_set_acTL(png_structp png_ptr, png_infop info_ptr,
1024 : png_uint_32 num_frames, png_uint_32 num_plays)
1025 : {
1026 : png_debug1(1, "in %s storage function", "acTL");
1027 :
1028 6 : if (png_ptr == NULL || info_ptr == NULL)
1029 : {
1030 : png_warning(png_ptr,
1031 : "Call to png_set_acTL() with NULL png_ptr "
1032 : "or info_ptr ignored");
1033 0 : return (0);
1034 : }
1035 6 : if (num_frames == 0)
1036 : {
1037 : png_warning(png_ptr,
1038 : "Ignoring attempt to set acTL with num_frames zero");
1039 0 : return (0);
1040 : }
1041 6 : if (num_frames > PNG_UINT_31_MAX)
1042 : {
1043 : png_warning(png_ptr,
1044 : "Ignoring attempt to set acTL with num_frames > 2^31-1");
1045 0 : return (0);
1046 : }
1047 6 : if (num_plays > PNG_UINT_31_MAX)
1048 : {
1049 : png_warning(png_ptr,
1050 : "Ignoring attempt to set acTL with num_plays "
1051 : "> 2^31-1");
1052 0 : return (0);
1053 : }
1054 :
1055 6 : info_ptr->num_frames = num_frames;
1056 6 : info_ptr->num_plays = num_plays;
1057 :
1058 6 : info_ptr->valid |= PNG_INFO_acTL;
1059 :
1060 6 : return (1);
1061 : }
1062 :
1063 : /* delay_num and delay_den can hold any 16-bit values including zero */
1064 : png_uint_32 PNGAPI
1065 0 : png_set_next_frame_fcTL(png_structp png_ptr, png_infop info_ptr,
1066 : png_uint_32 width, png_uint_32 height,
1067 : png_uint_32 x_offset, png_uint_32 y_offset,
1068 : png_uint_16 delay_num, png_uint_16 delay_den,
1069 : png_byte dispose_op, png_byte blend_op)
1070 : {
1071 : png_debug1(1, "in %s storage function", "fcTL");
1072 :
1073 0 : if (png_ptr == NULL || info_ptr == NULL)
1074 : {
1075 : png_warning(png_ptr,
1076 : "Call to png_set_fcTL() with NULL png_ptr or info_ptr "
1077 : "ignored");
1078 0 : return (0);
1079 : }
1080 :
1081 0 : png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset,
1082 : delay_num, delay_den, dispose_op, blend_op);
1083 :
1084 0 : if (blend_op == PNG_BLEND_OP_OVER)
1085 : {
1086 0 : if (!(png_ptr->color_type & PNG_COLOR_MASK_ALPHA) &&
1087 0 : !(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)))
1088 : {
1089 : png_warning(png_ptr, "PNG_BLEND_OP_OVER is meaningless "
1090 : "and wasteful for opaque images, ignored");
1091 0 : blend_op = PNG_BLEND_OP_SOURCE;
1092 : }
1093 : }
1094 :
1095 0 : info_ptr->next_frame_width = width;
1096 0 : info_ptr->next_frame_height = height;
1097 0 : info_ptr->next_frame_x_offset = x_offset;
1098 0 : info_ptr->next_frame_y_offset = y_offset;
1099 0 : info_ptr->next_frame_delay_num = delay_num;
1100 0 : info_ptr->next_frame_delay_den = delay_den;
1101 0 : info_ptr->next_frame_dispose_op = dispose_op;
1102 0 : info_ptr->next_frame_blend_op = blend_op;
1103 :
1104 0 : info_ptr->valid |= PNG_INFO_fcTL;
1105 :
1106 0 : return (1);
1107 : }
1108 :
1109 : void /* PRIVATE */
1110 18 : png_ensure_fcTL_is_valid(png_structp png_ptr,
1111 : png_uint_32 width, png_uint_32 height,
1112 : png_uint_32 x_offset, png_uint_32 y_offset,
1113 : png_uint_16 delay_num, png_uint_16 delay_den,
1114 : png_byte dispose_op, png_byte blend_op)
1115 : {
1116 36 : if (width + x_offset > png_ptr->first_frame_width ||
1117 18 : height + y_offset > png_ptr->first_frame_height)
1118 0 : png_error(png_ptr, "dimensions of a frame are greater than"
1119 : "the ones in IHDR");
1120 18 : if (width > PNG_UINT_31_MAX)
1121 0 : png_error(png_ptr, "invalid width in fcTL (> 2^31-1)");
1122 18 : if (height > PNG_UINT_31_MAX)
1123 0 : png_error(png_ptr, "invalid height in fcTL (> 2^31-1)");
1124 18 : if (x_offset > PNG_UINT_31_MAX)
1125 0 : png_error(png_ptr, "invalid x_offset in fcTL (> 2^31-1)");
1126 18 : if (y_offset > PNG_UINT_31_MAX)
1127 0 : png_error(png_ptr, "invalid y_offset in fcTL (> 2^31-1)");
1128 :
1129 18 : if (dispose_op != PNG_DISPOSE_OP_NONE &&
1130 0 : dispose_op != PNG_DISPOSE_OP_BACKGROUND &&
1131 : dispose_op != PNG_DISPOSE_OP_PREVIOUS)
1132 0 : png_error(png_ptr, "invalid dispose_op in fcTL");
1133 :
1134 18 : if (blend_op != PNG_BLEND_OP_SOURCE &&
1135 : blend_op != PNG_BLEND_OP_OVER)
1136 0 : png_error(png_ptr, "invalid blend_op in fcTL");
1137 :
1138 : PNG_UNUSED(delay_num)
1139 : PNG_UNUSED(delay_den)
1140 18 : }
1141 :
1142 : png_uint_32 PNGAPI
1143 6 : png_set_first_frame_is_hidden(png_structp png_ptr, png_infop info_ptr,
1144 : png_byte is_hidden)
1145 : {
1146 : png_debug(1, "in png_first_frame_is_hidden()");
1147 :
1148 6 : if (png_ptr == NULL)
1149 0 : return 0;
1150 :
1151 6 : if (is_hidden)
1152 1 : png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN;
1153 : else
1154 5 : png_ptr->apng_flags &= ~PNG_FIRST_FRAME_HIDDEN;
1155 :
1156 : PNG_UNUSED(info_ptr)
1157 :
1158 6 : return 1;
1159 : }
1160 : #endif /* PNG_APNG_SUPPORTED */
1161 :
1162 : #ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
1163 : void PNGAPI
1164 : png_set_unknown_chunks(png_structp png_ptr,
1165 : png_infop info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns)
1166 : {
1167 : png_unknown_chunkp np;
1168 : int i;
1169 :
1170 : if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0)
1171 : return;
1172 :
1173 : np = (png_unknown_chunkp)png_malloc_warn(png_ptr,
1174 : (png_size_t)(info_ptr->unknown_chunks_num + num_unknowns) *
1175 : png_sizeof(png_unknown_chunk));
1176 :
1177 : if (np == NULL)
1178 : {
1179 : png_warning(png_ptr,
1180 : "Out of memory while processing unknown chunk");
1181 : return;
1182 : }
1183 :
1184 : png_memcpy(np, info_ptr->unknown_chunks,
1185 : (png_size_t)info_ptr->unknown_chunks_num *
1186 : png_sizeof(png_unknown_chunk));
1187 :
1188 : png_free(png_ptr, info_ptr->unknown_chunks);
1189 : info_ptr->unknown_chunks = NULL;
1190 :
1191 : for (i = 0; i < num_unknowns; i++)
1192 : {
1193 : png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i;
1194 : png_const_unknown_chunkp from = unknowns + i;
1195 :
1196 : png_memcpy(to->name, from->name, png_sizeof(from->name));
1197 : to->name[png_sizeof(to->name)-1] = '\0';
1198 : to->size = from->size;
1199 :
1200 : /* Note our location in the read or write sequence */
1201 : to->location = (png_byte)(png_ptr->mode & 0xff);
1202 :
1203 : if (from->size == 0)
1204 : to->data=NULL;
1205 :
1206 : else
1207 : {
1208 : to->data = (png_bytep)png_malloc_warn(png_ptr,
1209 : (png_size_t)from->size);
1210 :
1211 : if (to->data == NULL)
1212 : {
1213 : png_warning(png_ptr,
1214 : "Out of memory while processing unknown chunk");
1215 : to->size = 0;
1216 : }
1217 :
1218 : else
1219 : png_memcpy(to->data, from->data, from->size);
1220 : }
1221 : }
1222 :
1223 : info_ptr->unknown_chunks = np;
1224 : info_ptr->unknown_chunks_num += num_unknowns;
1225 : info_ptr->free_me |= PNG_FREE_UNKN;
1226 : }
1227 :
1228 : void PNGAPI
1229 : png_set_unknown_chunk_location(png_structp png_ptr, png_infop info_ptr,
1230 : int chunk, int location)
1231 : {
1232 : if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 && chunk <
1233 : info_ptr->unknown_chunks_num)
1234 : info_ptr->unknown_chunks[chunk].location = (png_byte)location;
1235 : }
1236 : #endif
1237 :
1238 :
1239 : #ifdef PNG_MNG_FEATURES_SUPPORTED
1240 : png_uint_32 PNGAPI
1241 : png_permit_mng_features (png_structp png_ptr, png_uint_32 mng_features)
1242 : {
1243 : png_debug(1, "in png_permit_mng_features");
1244 :
1245 : if (png_ptr == NULL)
1246 : return (png_uint_32)0;
1247 :
1248 : png_ptr->mng_features_permitted =
1249 : (png_byte)(mng_features & PNG_ALL_MNG_FEATURES);
1250 :
1251 : return (png_uint_32)png_ptr->mng_features_permitted;
1252 : }
1253 : #endif
1254 :
1255 : #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
1256 : void PNGAPI
1257 : png_set_keep_unknown_chunks(png_structp png_ptr, int keep, png_const_bytep
1258 : chunk_list, int num_chunks)
1259 : {
1260 : png_bytep new_list, p;
1261 : int i, old_num_chunks;
1262 : if (png_ptr == NULL)
1263 : return;
1264 :
1265 : if (num_chunks == 0)
1266 : {
1267 : if (keep == PNG_HANDLE_CHUNK_ALWAYS || keep == PNG_HANDLE_CHUNK_IF_SAFE)
1268 : png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
1269 :
1270 : else
1271 : png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
1272 :
1273 : if (keep == PNG_HANDLE_CHUNK_ALWAYS)
1274 : png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS;
1275 :
1276 : else
1277 : png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS;
1278 :
1279 : return;
1280 : }
1281 :
1282 : if (chunk_list == NULL)
1283 : return;
1284 :
1285 : old_num_chunks = png_ptr->num_chunk_list;
1286 : new_list=(png_bytep)png_malloc(png_ptr,
1287 : (png_size_t)(5*(num_chunks + old_num_chunks)));
1288 :
1289 : if (png_ptr->chunk_list != NULL)
1290 : {
1291 : png_memcpy(new_list, png_ptr->chunk_list,
1292 : (png_size_t)(5*old_num_chunks));
1293 : png_free(png_ptr, png_ptr->chunk_list);
1294 : png_ptr->chunk_list=NULL;
1295 : }
1296 :
1297 : png_memcpy(new_list + 5*old_num_chunks, chunk_list,
1298 : (png_size_t)(5*num_chunks));
1299 :
1300 : for (p = new_list + 5*old_num_chunks + 4, i = 0; i<num_chunks; i++, p += 5)
1301 : *p=(png_byte)keep;
1302 :
1303 : png_ptr->num_chunk_list = old_num_chunks + num_chunks;
1304 : png_ptr->chunk_list = new_list;
1305 : png_ptr->free_me |= PNG_FREE_LIST;
1306 : }
1307 : #endif
1308 :
1309 : #ifdef PNG_READ_USER_CHUNKS_SUPPORTED
1310 : void PNGAPI
1311 : png_set_read_user_chunk_fn(png_structp png_ptr, png_voidp user_chunk_ptr,
1312 : png_user_chunk_ptr read_user_chunk_fn)
1313 : {
1314 : png_debug(1, "in png_set_read_user_chunk_fn");
1315 :
1316 : if (png_ptr == NULL)
1317 : return;
1318 :
1319 : png_ptr->read_user_chunk_fn = read_user_chunk_fn;
1320 : png_ptr->user_chunk_ptr = user_chunk_ptr;
1321 : }
1322 : #endif
1323 :
1324 : #ifdef PNG_INFO_IMAGE_SUPPORTED
1325 : void PNGAPI
1326 : png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers)
1327 : {
1328 : png_debug1(1, "in %s storage function", "rows");
1329 :
1330 : if (png_ptr == NULL || info_ptr == NULL)
1331 : return;
1332 :
1333 : if (info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers))
1334 : png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
1335 :
1336 : info_ptr->row_pointers = row_pointers;
1337 :
1338 : if (row_pointers)
1339 : info_ptr->valid |= PNG_INFO_IDAT;
1340 : }
1341 : #endif
1342 :
1343 : void PNGAPI
1344 0 : png_set_compression_buffer_size(png_structp png_ptr, png_size_t size)
1345 : {
1346 0 : if (png_ptr == NULL)
1347 0 : return;
1348 :
1349 0 : png_free(png_ptr, png_ptr->zbuf);
1350 :
1351 : if (size > ZLIB_IO_MAX)
1352 : {
1353 : png_warning(png_ptr, "Attempt to set buffer size beyond max ignored");
1354 : png_ptr->zbuf_size = ZLIB_IO_MAX;
1355 : size = ZLIB_IO_MAX; /* must fit */
1356 : }
1357 :
1358 : else
1359 0 : png_ptr->zbuf_size = (uInt)size;
1360 :
1361 0 : png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, size);
1362 :
1363 : /* The following ensures a relatively safe failure if this gets called while
1364 : * the buffer is actually in use.
1365 : */
1366 0 : png_ptr->zstream.next_out = png_ptr->zbuf;
1367 0 : png_ptr->zstream.avail_out = 0;
1368 0 : png_ptr->zstream.avail_in = 0;
1369 : }
1370 :
1371 : void PNGAPI
1372 0 : png_set_invalid(png_structp png_ptr, png_infop info_ptr, int mask)
1373 : {
1374 0 : if (png_ptr && info_ptr)
1375 0 : info_ptr->valid &= ~mask;
1376 0 : }
1377 :
1378 :
1379 :
1380 : #ifdef PNG_SET_USER_LIMITS_SUPPORTED
1381 : /* This function was added to libpng 1.2.6 */
1382 : void PNGAPI
1383 : png_set_user_limits (png_structp png_ptr, png_uint_32 user_width_max,
1384 : png_uint_32 user_height_max)
1385 : {
1386 : /* Images with dimensions larger than these limits will be
1387 : * rejected by png_set_IHDR(). To accept any PNG datastream
1388 : * regardless of dimensions, set both limits to 0x7ffffffL.
1389 : */
1390 : if (png_ptr == NULL)
1391 : return;
1392 :
1393 : png_ptr->user_width_max = user_width_max;
1394 : png_ptr->user_height_max = user_height_max;
1395 : }
1396 :
1397 : /* This function was added to libpng 1.4.0 */
1398 : void PNGAPI
1399 : png_set_chunk_cache_max (png_structp png_ptr,
1400 : png_uint_32 user_chunk_cache_max)
1401 : {
1402 : if (png_ptr)
1403 : png_ptr->user_chunk_cache_max = user_chunk_cache_max;
1404 : }
1405 :
1406 : /* This function was added to libpng 1.4.1 */
1407 : void PNGAPI
1408 : png_set_chunk_malloc_max (png_structp png_ptr,
1409 : png_alloc_size_t user_chunk_malloc_max)
1410 : {
1411 : if (png_ptr)
1412 : png_ptr->user_chunk_malloc_max = user_chunk_malloc_max;
1413 : }
1414 : #endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */
1415 :
1416 :
1417 : #ifdef PNG_BENIGN_ERRORS_SUPPORTED
1418 : void PNGAPI
1419 : png_set_benign_errors(png_structp png_ptr, int allowed)
1420 : {
1421 : png_debug(1, "in png_set_benign_errors");
1422 :
1423 : if (allowed)
1424 : png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN;
1425 :
1426 : else
1427 : png_ptr->flags &= ~PNG_FLAG_BENIGN_ERRORS_WARN;
1428 : }
1429 : #endif /* PNG_BENIGN_ERRORS_SUPPORTED */
1430 : #endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
|