initial import
[dosrtxon] / libs / imago / libpng / pngset.c
1 \r
2 /* pngset.c - storage of image information into info struct\r
3  *\r
4  * Last changed in libpng 1.2.30 [August 15, 2008]\r
5  * For conditions of distribution and use, see copyright notice in png.h\r
6  * Copyright (c) 1998-2008 Glenn Randers-Pehrson\r
7  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)\r
8  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)\r
9  *\r
10  * The functions here are used during reads to store data from the file\r
11  * into the info struct, and during writes to store application data\r
12  * into the info struct for writing into the file.  This abstracts the\r
13  * info struct and allows us to change the structure in the future.\r
14  */\r
15 \r
16 #define PNG_INTERNAL\r
17 #include "png.h"\r
18 #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)\r
19 \r
20 #if defined(PNG_bKGD_SUPPORTED)\r
21 void PNGAPI\r
22 png_set_bKGD(png_structp png_ptr, png_infop info_ptr, png_color_16p background)\r
23 {\r
24    png_debug1(1, "in %s storage function\n", "bKGD");\r
25    if (png_ptr == NULL || info_ptr == NULL)\r
26       return;\r
27 \r
28    png_memcpy(&(info_ptr->background), background, png_sizeof(png_color_16));\r
29    info_ptr->valid |= PNG_INFO_bKGD;\r
30 }\r
31 #endif\r
32 \r
33 #if defined(PNG_cHRM_SUPPORTED)\r
34 #ifdef PNG_FLOATING_POINT_SUPPORTED\r
35 void PNGAPI\r
36 png_set_cHRM(png_structp png_ptr, png_infop info_ptr,\r
37    double white_x, double white_y, double red_x, double red_y,\r
38    double green_x, double green_y, double blue_x, double blue_y)\r
39 {\r
40    png_debug1(1, "in %s storage function\n", "cHRM");\r
41    if (png_ptr == NULL || info_ptr == NULL)\r
42       return;\r
43    if (!(white_x || white_y || red_x || red_y || green_x || green_y ||\r
44        blue_x || blue_y))\r
45    {\r
46       png_warning(png_ptr,\r
47         "Ignoring attempt to set all-zero chromaticity values");\r
48       return;\r
49    }\r
50    if (white_x < 0.0 || white_y < 0.0 ||\r
51          red_x < 0.0 ||   red_y < 0.0 ||\r
52        green_x < 0.0 || green_y < 0.0 ||\r
53         blue_x < 0.0 ||  blue_y < 0.0)\r
54    {\r
55       png_warning(png_ptr,\r
56         "Ignoring attempt to set negative chromaticity value");\r
57       return;\r
58    }\r
59    if (white_x > 21474.83 || white_y > 21474.83 ||\r
60          red_x > 21474.83 ||   red_y > 21474.83 ||\r
61        green_x > 21474.83 || green_y > 21474.83 ||\r
62         blue_x > 21474.83 ||  blue_y > 21474.83)\r
63    {\r
64       png_warning(png_ptr,\r
65         "Ignoring attempt to set chromaticity value exceeding 21474.83");\r
66       return;\r
67    }\r
68 \r
69    info_ptr->x_white = (float)white_x;\r
70    info_ptr->y_white = (float)white_y;\r
71    info_ptr->x_red   = (float)red_x;\r
72    info_ptr->y_red   = (float)red_y;\r
73    info_ptr->x_green = (float)green_x;\r
74    info_ptr->y_green = (float)green_y;\r
75    info_ptr->x_blue  = (float)blue_x;\r
76    info_ptr->y_blue  = (float)blue_y;\r
77 #ifdef PNG_FIXED_POINT_SUPPORTED\r
78    info_ptr->int_x_white = (png_fixed_point)(white_x*100000.+0.5);\r
79    info_ptr->int_y_white = (png_fixed_point)(white_y*100000.+0.5);\r
80    info_ptr->int_x_red   = (png_fixed_point)(  red_x*100000.+0.5);\r
81    info_ptr->int_y_red   = (png_fixed_point)(  red_y*100000.+0.5);\r
82    info_ptr->int_x_green = (png_fixed_point)(green_x*100000.+0.5);\r
83    info_ptr->int_y_green = (png_fixed_point)(green_y*100000.+0.5);\r
84    info_ptr->int_x_blue  = (png_fixed_point)( blue_x*100000.+0.5);\r
85    info_ptr->int_y_blue  = (png_fixed_point)( blue_y*100000.+0.5);\r
86 #endif\r
87    info_ptr->valid |= PNG_INFO_cHRM;\r
88 }\r
89 #endif\r
90 #ifdef PNG_FIXED_POINT_SUPPORTED\r
91 void PNGAPI\r
92 png_set_cHRM_fixed(png_structp png_ptr, png_infop info_ptr,\r
93    png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x,\r
94    png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y,\r
95    png_fixed_point blue_x, png_fixed_point blue_y)\r
96 {\r
97    png_debug1(1, "in %s storage function\n", "cHRM");\r
98    if (png_ptr == NULL || info_ptr == NULL)\r
99       return;\r
100 \r
101    if (!(white_x || white_y || red_x || red_y || green_x || green_y ||\r
102        blue_x || blue_y))\r
103    {\r
104       png_warning(png_ptr,\r
105         "Ignoring attempt to set all-zero chromaticity values");\r
106       return;\r
107    }\r
108    if (white_x < 0 || white_y < 0 ||\r
109          red_x < 0 ||   red_y < 0 ||\r
110        green_x < 0 || green_y < 0 ||\r
111         blue_x < 0 ||  blue_y < 0)\r
112    {\r
113       png_warning(png_ptr,\r
114         "Ignoring attempt to set negative chromaticity value");\r
115       return;\r
116    }\r
117    if (white_x > (png_fixed_point) PNG_UINT_31_MAX ||\r
118        white_y > (png_fixed_point) PNG_UINT_31_MAX ||\r
119          red_x > (png_fixed_point) PNG_UINT_31_MAX ||\r
120          red_y > (png_fixed_point) PNG_UINT_31_MAX ||\r
121        green_x > (png_fixed_point) PNG_UINT_31_MAX ||\r
122        green_y > (png_fixed_point) PNG_UINT_31_MAX ||\r
123         blue_x > (png_fixed_point) PNG_UINT_31_MAX ||\r
124         blue_y > (png_fixed_point) PNG_UINT_31_MAX )\r
125    {\r
126       png_warning(png_ptr,\r
127         "Ignoring attempt to set chromaticity value exceeding 21474.83");\r
128       return;\r
129    }\r
130    info_ptr->int_x_white = white_x;\r
131    info_ptr->int_y_white = white_y;\r
132    info_ptr->int_x_red   = red_x;\r
133    info_ptr->int_y_red   = red_y;\r
134    info_ptr->int_x_green = green_x;\r
135    info_ptr->int_y_green = green_y;\r
136    info_ptr->int_x_blue  = blue_x;\r
137    info_ptr->int_y_blue  = blue_y;\r
138 #ifdef PNG_FLOATING_POINT_SUPPORTED\r
139    info_ptr->x_white = (float)(white_x/100000.);\r
140    info_ptr->y_white = (float)(white_y/100000.);\r
141    info_ptr->x_red   = (float)(  red_x/100000.);\r
142    info_ptr->y_red   = (float)(  red_y/100000.);\r
143    info_ptr->x_green = (float)(green_x/100000.);\r
144    info_ptr->y_green = (float)(green_y/100000.);\r
145    info_ptr->x_blue  = (float)( blue_x/100000.);\r
146    info_ptr->y_blue  = (float)( blue_y/100000.);\r
147 #endif\r
148    info_ptr->valid |= PNG_INFO_cHRM;\r
149 }\r
150 #endif\r
151 #endif\r
152 \r
153 #if defined(PNG_gAMA_SUPPORTED)\r
154 #ifdef PNG_FLOATING_POINT_SUPPORTED\r
155 void PNGAPI\r
156 png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma)\r
157 {\r
158    double gamma;\r
159    png_debug1(1, "in %s storage function\n", "gAMA");\r
160    if (png_ptr == NULL || info_ptr == NULL)\r
161       return;\r
162 \r
163    /* Check for overflow */\r
164    if (file_gamma > 21474.83)\r
165    {\r
166       png_warning(png_ptr, "Limiting gamma to 21474.83");\r
167       gamma=21474.83;\r
168    }\r
169    else\r
170       gamma = file_gamma;\r
171    info_ptr->gamma = (float)gamma;\r
172 #ifdef PNG_FIXED_POINT_SUPPORTED\r
173    info_ptr->int_gamma = (int)(gamma*100000.+.5);\r
174 #endif\r
175    info_ptr->valid |= PNG_INFO_gAMA;\r
176    if (gamma == 0.0)\r
177       png_warning(png_ptr, "Setting gamma=0");\r
178 }\r
179 #endif\r
180 void PNGAPI\r
181 png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point\r
182    int_gamma)\r
183 {\r
184    png_fixed_point gamma;\r
185 \r
186    png_debug1(1, "in %s storage function\n", "gAMA");\r
187    if (png_ptr == NULL || info_ptr == NULL)\r
188       return;\r
189 \r
190    if (int_gamma > (png_fixed_point) PNG_UINT_31_MAX)\r
191    {\r
192      png_warning(png_ptr, "Limiting gamma to 21474.83");\r
193      gamma=PNG_UINT_31_MAX;\r
194    }\r
195    else\r
196    {\r
197      if (int_gamma < 0)\r
198      {\r
199        png_warning(png_ptr, "Setting negative gamma to zero");\r
200        gamma = 0;\r
201      }\r
202      else\r
203        gamma = int_gamma;\r
204    }\r
205 #ifdef PNG_FLOATING_POINT_SUPPORTED\r
206    info_ptr->gamma = (float)(gamma/100000.);\r
207 #endif\r
208 #ifdef PNG_FIXED_POINT_SUPPORTED\r
209    info_ptr->int_gamma = gamma;\r
210 #endif\r
211    info_ptr->valid |= PNG_INFO_gAMA;\r
212    if (gamma == 0)\r
213       png_warning(png_ptr, "Setting gamma=0");\r
214 }\r
215 #endif\r
216 \r
217 #if defined(PNG_hIST_SUPPORTED)\r
218 void PNGAPI\r
219 png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p hist)\r
220 {\r
221    int i;\r
222 \r
223    png_debug1(1, "in %s storage function\n", "hIST");\r
224    if (png_ptr == NULL || info_ptr == NULL)\r
225       return;\r
226    if (info_ptr->num_palette == 0 || info_ptr->num_palette\r
227        > PNG_MAX_PALETTE_LENGTH)\r
228    {\r
229        png_warning(png_ptr,\r
230           "Invalid palette size, hIST allocation skipped.");\r
231        return;\r
232    }\r
233 \r
234 #ifdef PNG_FREE_ME_SUPPORTED\r
235    png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0);\r
236 #endif\r
237    /* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in version\r
238       1.2.1 */\r
239    png_ptr->hist = (png_uint_16p)png_malloc_warn(png_ptr,\r
240       (png_uint_32)(PNG_MAX_PALETTE_LENGTH * png_sizeof(png_uint_16)));\r
241    if (png_ptr->hist == NULL)\r
242      {\r
243        png_warning(png_ptr, "Insufficient memory for hIST chunk data.");\r
244        return;\r
245      }\r
246 \r
247    for (i = 0; i < info_ptr->num_palette; i++)\r
248        png_ptr->hist[i] = hist[i];\r
249    info_ptr->hist = png_ptr->hist;\r
250    info_ptr->valid |= PNG_INFO_hIST;\r
251 \r
252 #ifdef PNG_FREE_ME_SUPPORTED\r
253    info_ptr->free_me |= PNG_FREE_HIST;\r
254 #else\r
255    png_ptr->flags |= PNG_FLAG_FREE_HIST;\r
256 #endif\r
257 }\r
258 #endif\r
259 \r
260 void PNGAPI\r
261 png_set_IHDR(png_structp png_ptr, png_infop info_ptr,\r
262    png_uint_32 width, png_uint_32 height, int bit_depth,\r
263    int color_type, int interlace_type, int compression_type,\r
264    int filter_type)\r
265 {\r
266    png_debug1(1, "in %s storage function\n", "IHDR");\r
267    if (png_ptr == NULL || info_ptr == NULL)\r
268       return;\r
269 \r
270    /* check for width and height valid values */\r
271    if (width == 0 || height == 0)\r
272       png_error(png_ptr, "Image width or height is zero in IHDR");\r
273 #ifdef PNG_SET_USER_LIMITS_SUPPORTED\r
274    if (width > png_ptr->user_width_max || height > png_ptr->user_height_max)\r
275       png_error(png_ptr, "image size exceeds user limits in IHDR");\r
276 #else\r
277    if (width > PNG_USER_WIDTH_MAX || height > PNG_USER_HEIGHT_MAX)\r
278       png_error(png_ptr, "image size exceeds user limits in IHDR");\r
279 #endif\r
280    if (width > PNG_UINT_31_MAX || height > PNG_UINT_31_MAX)\r
281       png_error(png_ptr, "Invalid image size in IHDR");\r
282    if ( width > (PNG_UINT_32_MAX\r
283                  >> 3)      /* 8-byte RGBA pixels */\r
284                  - 64       /* bigrowbuf hack */\r
285                  - 1        /* filter byte */\r
286                  - 7*8      /* rounding of width to multiple of 8 pixels */\r
287                  - 8)       /* extra max_pixel_depth pad */\r
288       png_warning(png_ptr, "Width is too large for libpng to process pixels");\r
289 \r
290    /* check other values */\r
291    if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 &&\r
292       bit_depth != 8 && bit_depth != 16)\r
293       png_error(png_ptr, "Invalid bit depth in IHDR");\r
294 \r
295    if (color_type < 0 || color_type == 1 ||\r
296       color_type == 5 || color_type > 6)\r
297       png_error(png_ptr, "Invalid color type in IHDR");\r
298 \r
299    if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) ||\r
300        ((color_type == PNG_COLOR_TYPE_RGB ||\r
301          color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||\r
302          color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8))\r
303       png_error(png_ptr, "Invalid color type/bit depth combination in IHDR");\r
304 \r
305    if (interlace_type >= PNG_INTERLACE_LAST)\r
306       png_error(png_ptr, "Unknown interlace method in IHDR");\r
307 \r
308    if (compression_type != PNG_COMPRESSION_TYPE_BASE)\r
309       png_error(png_ptr, "Unknown compression method in IHDR");\r
310 \r
311 #if defined(PNG_MNG_FEATURES_SUPPORTED)\r
312    /* Accept filter_method 64 (intrapixel differencing) only if\r
313     * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and\r
314     * 2. Libpng did not read a PNG signature (this filter_method is only\r
315     *    used in PNG datastreams that are embedded in MNG datastreams) and\r
316     * 3. The application called png_permit_mng_features with a mask that\r
317     *    included PNG_FLAG_MNG_FILTER_64 and\r
318     * 4. The filter_method is 64 and\r
319     * 5. The color_type is RGB or RGBA\r
320     */\r
321    if ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&png_ptr->mng_features_permitted)\r
322       png_warning(png_ptr, "MNG features are not allowed in a PNG datastream");\r
323    if (filter_type != PNG_FILTER_TYPE_BASE)\r
324    {\r
325      if (!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&\r
326         (filter_type == PNG_INTRAPIXEL_DIFFERENCING) &&\r
327         ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&\r
328         (color_type == PNG_COLOR_TYPE_RGB ||\r
329          color_type == PNG_COLOR_TYPE_RGB_ALPHA)))\r
330         png_error(png_ptr, "Unknown filter method in IHDR");\r
331      if (png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)\r
332         png_warning(png_ptr, "Invalid filter method in IHDR");\r
333    }\r
334 #else\r
335    if (filter_type != PNG_FILTER_TYPE_BASE)\r
336       png_error(png_ptr, "Unknown filter method in IHDR");\r
337 #endif\r
338 \r
339    info_ptr->width = width;\r
340    info_ptr->height = height;\r
341    info_ptr->bit_depth = (png_byte)bit_depth;\r
342    info_ptr->color_type =(png_byte) color_type;\r
343    info_ptr->compression_type = (png_byte)compression_type;\r
344    info_ptr->filter_type = (png_byte)filter_type;\r
345    info_ptr->interlace_type = (png_byte)interlace_type;\r
346    if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)\r
347       info_ptr->channels = 1;\r
348    else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)\r
349       info_ptr->channels = 3;\r
350    else\r
351       info_ptr->channels = 1;\r
352    if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)\r
353       info_ptr->channels++;\r
354    info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth);\r
355 \r
356    /* check for potential overflow */\r
357    if (width > (PNG_UINT_32_MAX\r
358                  >> 3)      /* 8-byte RGBA pixels */\r
359                  - 64       /* bigrowbuf hack */\r
360                  - 1        /* filter byte */\r
361                  - 7*8      /* rounding of width to multiple of 8 pixels */\r
362                  - 8)       /* extra max_pixel_depth pad */\r
363       info_ptr->rowbytes = (png_size_t)0;\r
364    else\r
365       info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width);\r
366 }\r
367 \r
368 #if defined(PNG_oFFs_SUPPORTED)\r
369 void PNGAPI\r
370 png_set_oFFs(png_structp png_ptr, png_infop info_ptr,\r
371    png_int_32 offset_x, png_int_32 offset_y, int unit_type)\r
372 {\r
373    png_debug1(1, "in %s storage function\n", "oFFs");\r
374    if (png_ptr == NULL || info_ptr == NULL)\r
375       return;\r
376 \r
377    info_ptr->x_offset = offset_x;\r
378    info_ptr->y_offset = offset_y;\r
379    info_ptr->offset_unit_type = (png_byte)unit_type;\r
380    info_ptr->valid |= PNG_INFO_oFFs;\r
381 }\r
382 #endif\r
383 \r
384 #if defined(PNG_pCAL_SUPPORTED)\r
385 void PNGAPI\r
386 png_set_pCAL(png_structp png_ptr, png_infop info_ptr,\r
387    png_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams,\r
388    png_charp units, png_charpp params)\r
389 {\r
390    png_uint_32 length;\r
391    int i;\r
392 \r
393    png_debug1(1, "in %s storage function\n", "pCAL");\r
394    if (png_ptr == NULL || info_ptr == NULL)\r
395       return;\r
396 \r
397    length = png_strlen(purpose) + 1;\r
398    png_debug1(3, "allocating purpose for info (%lu bytes)\n",\r
399      (unsigned long)length);\r
400    info_ptr->pcal_purpose = (png_charp)png_malloc_warn(png_ptr, length);\r
401    if (info_ptr->pcal_purpose == NULL)\r
402    {\r
403        png_warning(png_ptr, "Insufficient memory for pCAL purpose.");\r
404       return;\r
405    }\r
406    png_memcpy(info_ptr->pcal_purpose, purpose, (png_size_t)length);\r
407 \r
408    png_debug(3, "storing X0, X1, type, and nparams in info\n");\r
409    info_ptr->pcal_X0 = X0;\r
410    info_ptr->pcal_X1 = X1;\r
411    info_ptr->pcal_type = (png_byte)type;\r
412    info_ptr->pcal_nparams = (png_byte)nparams;\r
413 \r
414    length = png_strlen(units) + 1;\r
415    png_debug1(3, "allocating units for info (%lu bytes)\n",\r
416      (unsigned long)length);\r
417    info_ptr->pcal_units = (png_charp)png_malloc_warn(png_ptr, length);\r
418    if (info_ptr->pcal_units == NULL)\r
419    {\r
420        png_warning(png_ptr, "Insufficient memory for pCAL units.");\r
421       return;\r
422    }\r
423    png_memcpy(info_ptr->pcal_units, units, (png_size_t)length);\r
424 \r
425    info_ptr->pcal_params = (png_charpp)png_malloc_warn(png_ptr,\r
426       (png_uint_32)((nparams + 1) * png_sizeof(png_charp)));\r
427    if (info_ptr->pcal_params == NULL)\r
428    {\r
429        png_warning(png_ptr, "Insufficient memory for pCAL params.");\r
430       return;\r
431    }\r
432 \r
433    info_ptr->pcal_params[nparams] = NULL;\r
434 \r
435    for (i = 0; i < nparams; i++)\r
436    {\r
437       length = png_strlen(params[i]) + 1;\r
438       png_debug2(3, "allocating parameter %d for info (%lu bytes)\n", i,\r
439         (unsigned long)length);\r
440       info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length);\r
441       if (info_ptr->pcal_params[i] == NULL)\r
442       {\r
443           png_warning(png_ptr, "Insufficient memory for pCAL parameter.");\r
444           return;\r
445       }\r
446       png_memcpy(info_ptr->pcal_params[i], params[i], (png_size_t)length);\r
447    }\r
448 \r
449    info_ptr->valid |= PNG_INFO_pCAL;\r
450 #ifdef PNG_FREE_ME_SUPPORTED\r
451    info_ptr->free_me |= PNG_FREE_PCAL;\r
452 #endif\r
453 }\r
454 #endif\r
455 \r
456 #if defined(PNG_READ_sCAL_SUPPORTED) || defined(PNG_WRITE_sCAL_SUPPORTED)\r
457 #ifdef PNG_FLOATING_POINT_SUPPORTED\r
458 void PNGAPI\r
459 png_set_sCAL(png_structp png_ptr, png_infop info_ptr,\r
460              int unit, double width, double height)\r
461 {\r
462    png_debug1(1, "in %s storage function\n", "sCAL");\r
463    if (png_ptr == NULL || info_ptr == NULL)\r
464       return;\r
465 \r
466    info_ptr->scal_unit = (png_byte)unit;\r
467    info_ptr->scal_pixel_width = width;\r
468    info_ptr->scal_pixel_height = height;\r
469 \r
470    info_ptr->valid |= PNG_INFO_sCAL;\r
471 }\r
472 #else\r
473 #ifdef PNG_FIXED_POINT_SUPPORTED\r
474 void PNGAPI\r
475 png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr,\r
476              int unit, png_charp swidth, png_charp sheight)\r
477 {\r
478    png_uint_32 length;\r
479 \r
480    png_debug1(1, "in %s storage function\n", "sCAL");\r
481    if (png_ptr == NULL || info_ptr == NULL)\r
482       return;\r
483 \r
484    info_ptr->scal_unit = (png_byte)unit;\r
485 \r
486    length = png_strlen(swidth) + 1;\r
487    png_debug1(3, "allocating unit for info (%u bytes)\n",\r
488       (unsigned int)length);\r
489    info_ptr->scal_s_width = (png_charp)png_malloc_warn(png_ptr, length);\r
490    if (info_ptr->scal_s_width == NULL)\r
491    {\r
492       png_warning(png_ptr,\r
493        "Memory allocation failed while processing sCAL.");\r
494       return;\r
495    }\r
496    png_memcpy(info_ptr->scal_s_width, swidth, (png_size_t)length);\r
497 \r
498    length = png_strlen(sheight) + 1;\r
499    png_debug1(3, "allocating unit for info (%u bytes)\n",\r
500       (unsigned int)length);\r
501    info_ptr->scal_s_height = (png_charp)png_malloc_warn(png_ptr, length);\r
502    if (info_ptr->scal_s_height == NULL)\r
503    {\r
504       png_free (png_ptr, info_ptr->scal_s_width);\r
505       info_ptr->scal_s_width = NULL;\r
506       png_warning(png_ptr,\r
507        "Memory allocation failed while processing sCAL.");\r
508       return;\r
509    }\r
510    png_memcpy(info_ptr->scal_s_height, sheight, (png_size_t)length);\r
511    info_ptr->valid |= PNG_INFO_sCAL;\r
512 #ifdef PNG_FREE_ME_SUPPORTED\r
513    info_ptr->free_me |= PNG_FREE_SCAL;\r
514 #endif\r
515 }\r
516 #endif\r
517 #endif\r
518 #endif\r
519 \r
520 #if defined(PNG_pHYs_SUPPORTED)\r
521 void PNGAPI\r
522 png_set_pHYs(png_structp png_ptr, png_infop info_ptr,\r
523    png_uint_32 res_x, png_uint_32 res_y, int unit_type)\r
524 {\r
525    png_debug1(1, "in %s storage function\n", "pHYs");\r
526    if (png_ptr == NULL || info_ptr == NULL)\r
527       return;\r
528 \r
529    info_ptr->x_pixels_per_unit = res_x;\r
530    info_ptr->y_pixels_per_unit = res_y;\r
531    info_ptr->phys_unit_type = (png_byte)unit_type;\r
532    info_ptr->valid |= PNG_INFO_pHYs;\r
533 }\r
534 #endif\r
535 \r
536 void PNGAPI\r
537 png_set_PLTE(png_structp png_ptr, png_infop info_ptr,\r
538    png_colorp palette, int num_palette)\r
539 {\r
540 \r
541    png_debug1(1, "in %s storage function\n", "PLTE");\r
542    if (png_ptr == NULL || info_ptr == NULL)\r
543       return;\r
544 \r
545    if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH)\r
546      {\r
547        if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)\r
548          png_error(png_ptr, "Invalid palette length");\r
549        else\r
550        {\r
551          png_warning(png_ptr, "Invalid palette length");\r
552          return;\r
553        }\r
554      }\r
555 \r
556    /*\r
557     * It may not actually be necessary to set png_ptr->palette here;\r
558     * we do it for backward compatibility with the way the png_handle_tRNS\r
559     * function used to do the allocation.\r
560     */\r
561 #ifdef PNG_FREE_ME_SUPPORTED\r
562    png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0);\r
563 #endif\r
564 \r
565    /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead\r
566       of num_palette entries,\r
567       in case of an invalid PNG file that has too-large sample values. */\r
568    png_ptr->palette = (png_colorp)png_malloc(png_ptr,\r
569       PNG_MAX_PALETTE_LENGTH * png_sizeof(png_color));\r
570    png_memset(png_ptr->palette, 0, PNG_MAX_PALETTE_LENGTH *\r
571       png_sizeof(png_color));\r
572    png_memcpy(png_ptr->palette, palette, num_palette * png_sizeof(png_color));\r
573    info_ptr->palette = png_ptr->palette;\r
574    info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette;\r
575 \r
576 #ifdef PNG_FREE_ME_SUPPORTED\r
577    info_ptr->free_me |= PNG_FREE_PLTE;\r
578 #else\r
579    png_ptr->flags |= PNG_FLAG_FREE_PLTE;\r
580 #endif\r
581 \r
582    info_ptr->valid |= PNG_INFO_PLTE;\r
583 }\r
584 \r
585 #if defined(PNG_sBIT_SUPPORTED)\r
586 void PNGAPI\r
587 png_set_sBIT(png_structp png_ptr, png_infop info_ptr,\r
588    png_color_8p sig_bit)\r
589 {\r
590    png_debug1(1, "in %s storage function\n", "sBIT");\r
591    if (png_ptr == NULL || info_ptr == NULL)\r
592       return;\r
593 \r
594    png_memcpy(&(info_ptr->sig_bit), sig_bit, png_sizeof(png_color_8));\r
595    info_ptr->valid |= PNG_INFO_sBIT;\r
596 }\r
597 #endif\r
598 \r
599 #if defined(PNG_sRGB_SUPPORTED)\r
600 void PNGAPI\r
601 png_set_sRGB(png_structp png_ptr, png_infop info_ptr, int intent)\r
602 {\r
603    png_debug1(1, "in %s storage function\n", "sRGB");\r
604    if (png_ptr == NULL || info_ptr == NULL)\r
605       return;\r
606 \r
607    info_ptr->srgb_intent = (png_byte)intent;\r
608    info_ptr->valid |= PNG_INFO_sRGB;\r
609 }\r
610 \r
611 void PNGAPI\r
612 png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr,\r
613    int intent)\r
614 {\r
615 #if defined(PNG_gAMA_SUPPORTED)\r
616 #ifdef PNG_FLOATING_POINT_SUPPORTED\r
617    float file_gamma;\r
618 #endif\r
619 #ifdef PNG_FIXED_POINT_SUPPORTED\r
620    png_fixed_point int_file_gamma;\r
621 #endif\r
622 #endif\r
623 #if defined(PNG_cHRM_SUPPORTED)\r
624 #ifdef PNG_FLOATING_POINT_SUPPORTED\r
625    float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;\r
626 #endif\r
627 #ifdef PNG_FIXED_POINT_SUPPORTED\r
628    png_fixed_point int_white_x, int_white_y, int_red_x, int_red_y, int_green_x,\r
629       int_green_y, int_blue_x, int_blue_y;\r
630 #endif\r
631 #endif\r
632    png_debug1(1, "in %s storage function\n", "sRGB_gAMA_and_cHRM");\r
633    if (png_ptr == NULL || info_ptr == NULL)\r
634       return;\r
635 \r
636    png_set_sRGB(png_ptr, info_ptr, intent);\r
637 \r
638 #if defined(PNG_gAMA_SUPPORTED)\r
639 #ifdef PNG_FLOATING_POINT_SUPPORTED\r
640    file_gamma = (float).45455;\r
641    png_set_gAMA(png_ptr, info_ptr, file_gamma);\r
642 #endif\r
643 #ifdef PNG_FIXED_POINT_SUPPORTED\r
644    int_file_gamma = 45455L;\r
645    png_set_gAMA_fixed(png_ptr, info_ptr, int_file_gamma);\r
646 #endif\r
647 #endif\r
648 \r
649 #if defined(PNG_cHRM_SUPPORTED)\r
650 #ifdef PNG_FIXED_POINT_SUPPORTED\r
651    int_white_x = 31270L;\r
652    int_white_y = 32900L;\r
653    int_red_x   = 64000L;\r
654    int_red_y   = 33000L;\r
655    int_green_x = 30000L;\r
656    int_green_y = 60000L;\r
657    int_blue_x  = 15000L;\r
658    int_blue_y  =  6000L;\r
659 \r
660    png_set_cHRM_fixed(png_ptr, info_ptr,\r
661       int_white_x, int_white_y, int_red_x, int_red_y, int_green_x, int_green_y,\r
662       int_blue_x, int_blue_y);\r
663 #endif\r
664 #ifdef PNG_FLOATING_POINT_SUPPORTED\r
665    white_x = (float).3127;\r
666    white_y = (float).3290;\r
667    red_x   = (float).64;\r
668    red_y   = (float).33;\r
669    green_x = (float).30;\r
670    green_y = (float).60;\r
671    blue_x  = (float).15;\r
672    blue_y  = (float).06;\r
673 \r
674    png_set_cHRM(png_ptr, info_ptr,\r
675       white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);\r
676 #endif\r
677 #endif\r
678 }\r
679 #endif\r
680 \r
681 \r
682 #if defined(PNG_iCCP_SUPPORTED)\r
683 void PNGAPI\r
684 png_set_iCCP(png_structp png_ptr, png_infop info_ptr,\r
685              png_charp name, int compression_type,\r
686              png_charp profile, png_uint_32 proflen)\r
687 {\r
688    png_charp new_iccp_name;\r
689    png_charp new_iccp_profile;\r
690    png_uint_32 length;\r
691 \r
692    png_debug1(1, "in %s storage function\n", "iCCP");\r
693    if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL)\r
694       return;\r
695 \r
696    length = png_strlen(name)+1;\r
697    new_iccp_name = (png_charp)png_malloc_warn(png_ptr, length);\r
698    if (new_iccp_name == NULL)\r
699    {\r
700       png_warning(png_ptr, "Insufficient memory to process iCCP chunk.");\r
701       return;\r
702    }\r
703    png_memcpy(new_iccp_name, name, length);\r
704    new_iccp_profile = (png_charp)png_malloc_warn(png_ptr, proflen);\r
705    if (new_iccp_profile == NULL)\r
706    {\r
707       png_free (png_ptr, new_iccp_name);\r
708       png_warning(png_ptr,\r
709       "Insufficient memory to process iCCP profile.");\r
710       return;\r
711    }\r
712    png_memcpy(new_iccp_profile, profile, (png_size_t)proflen);\r
713 \r
714    png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0);\r
715 \r
716    info_ptr->iccp_proflen = proflen;\r
717    info_ptr->iccp_name = new_iccp_name;\r
718    info_ptr->iccp_profile = new_iccp_profile;\r
719    /* Compression is always zero but is here so the API and info structure\r
720     * does not have to change if we introduce multiple compression types */\r
721    info_ptr->iccp_compression = (png_byte)compression_type;\r
722 #ifdef PNG_FREE_ME_SUPPORTED\r
723    info_ptr->free_me |= PNG_FREE_ICCP;\r
724 #endif\r
725    info_ptr->valid |= PNG_INFO_iCCP;\r
726 }\r
727 #endif\r
728 \r
729 #if defined(PNG_TEXT_SUPPORTED)\r
730 void PNGAPI\r
731 png_set_text(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr,\r
732    int num_text)\r
733 {\r
734    int ret;\r
735    ret = png_set_text_2(png_ptr, info_ptr, text_ptr, num_text);\r
736    if (ret)\r
737      png_error(png_ptr, "Insufficient memory to store text");\r
738 }\r
739 \r
740 int /* PRIVATE */\r
741 png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr,\r
742    int num_text)\r
743 {\r
744    int i;\r
745 \r
746    png_debug1(1, "in %s storage function\n", (png_ptr->chunk_name[0] == '\0' ?\r
747       "text" : (png_const_charp)png_ptr->chunk_name));\r
748 \r
749    if (png_ptr == NULL || info_ptr == NULL || num_text == 0)\r
750       return(0);\r
751 \r
752    /* Make sure we have enough space in the "text" array in info_struct\r
753     * to hold all of the incoming text_ptr objects.\r
754     */\r
755    if (info_ptr->num_text + num_text > info_ptr->max_text)\r
756    {\r
757       if (info_ptr->text != NULL)\r
758       {\r
759          png_textp old_text;\r
760          int old_max;\r
761 \r
762          old_max = info_ptr->max_text;\r
763          info_ptr->max_text = info_ptr->num_text + num_text + 8;\r
764          old_text = info_ptr->text;\r
765          info_ptr->text = (png_textp)png_malloc_warn(png_ptr,\r
766             (png_uint_32)(info_ptr->max_text * png_sizeof(png_text)));\r
767          if (info_ptr->text == NULL)\r
768            {\r
769              png_free(png_ptr, old_text);\r
770              return(1);\r
771            }\r
772          png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max *\r
773             png_sizeof(png_text)));\r
774          png_free(png_ptr, old_text);\r
775       }\r
776       else\r
777       {\r
778          info_ptr->max_text = num_text + 8;\r
779          info_ptr->num_text = 0;\r
780          info_ptr->text = (png_textp)png_malloc_warn(png_ptr,\r
781             (png_uint_32)(info_ptr->max_text * png_sizeof(png_text)));\r
782          if (info_ptr->text == NULL)\r
783            return(1);\r
784 #ifdef PNG_FREE_ME_SUPPORTED\r
785          info_ptr->free_me |= PNG_FREE_TEXT;\r
786 #endif\r
787       }\r
788       png_debug1(3, "allocated %d entries for info_ptr->text\n",\r
789          info_ptr->max_text);\r
790    }\r
791    for (i = 0; i < num_text; i++)\r
792    {\r
793       png_size_t text_length, key_len;\r
794       png_size_t lang_len, lang_key_len;\r
795       png_textp textp = &(info_ptr->text[info_ptr->num_text]);\r
796 \r
797       if (text_ptr[i].key == NULL)\r
798           continue;\r
799 \r
800       key_len = png_strlen(text_ptr[i].key);\r
801 \r
802       if (text_ptr[i].compression <= 0)\r
803       {\r
804         lang_len = 0;\r
805         lang_key_len = 0;\r
806       }\r
807       else\r
808 #ifdef PNG_iTXt_SUPPORTED\r
809       {\r
810         /* set iTXt data */\r
811         if (text_ptr[i].lang != NULL)\r
812           lang_len = png_strlen(text_ptr[i].lang);\r
813         else\r
814           lang_len = 0;\r
815         if (text_ptr[i].lang_key != NULL)\r
816           lang_key_len = png_strlen(text_ptr[i].lang_key);\r
817         else\r
818           lang_key_len = 0;\r
819       }\r
820 #else\r
821       {\r
822         png_warning(png_ptr, "iTXt chunk not supported.");\r
823         continue;\r
824       }\r
825 #endif\r
826 \r
827       if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0')\r
828       {\r
829          text_length = 0;\r
830 #ifdef PNG_iTXt_SUPPORTED\r
831          if (text_ptr[i].compression > 0)\r
832             textp->compression = PNG_ITXT_COMPRESSION_NONE;\r
833          else\r
834 #endif\r
835             textp->compression = PNG_TEXT_COMPRESSION_NONE;\r
836       }\r
837       else\r
838       {\r
839          text_length = png_strlen(text_ptr[i].text);\r
840          textp->compression = text_ptr[i].compression;\r
841       }\r
842 \r
843       textp->key = (png_charp)png_malloc_warn(png_ptr,\r
844          (png_uint_32)\r
845          (key_len + text_length + lang_len + lang_key_len + 4));\r
846       if (textp->key == NULL)\r
847         return(1);\r
848       png_debug2(2, "Allocated %lu bytes at %x in png_set_text\n",\r
849          (png_uint_32)\r
850          (key_len + lang_len + lang_key_len + text_length + 4),\r
851          (int)textp->key);\r
852 \r
853       png_memcpy(textp->key, text_ptr[i].key,\r
854          (png_size_t)(key_len));\r
855       *(textp->key + key_len) = '\0';\r
856 #ifdef PNG_iTXt_SUPPORTED\r
857       if (text_ptr[i].compression > 0)\r
858       {\r
859          textp->lang = textp->key + key_len + 1;\r
860          png_memcpy(textp->lang, text_ptr[i].lang, lang_len);\r
861          *(textp->lang + lang_len) = '\0';\r
862          textp->lang_key = textp->lang + lang_len + 1;\r
863          png_memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len);\r
864          *(textp->lang_key + lang_key_len) = '\0';\r
865          textp->text = textp->lang_key + lang_key_len + 1;\r
866       }\r
867       else\r
868 #endif\r
869       {\r
870 #ifdef PNG_iTXt_SUPPORTED\r
871          textp->lang=NULL;\r
872          textp->lang_key=NULL;\r
873 #endif\r
874          textp->text = textp->key + key_len + 1;\r
875       }\r
876       if (text_length)\r
877          png_memcpy(textp->text, text_ptr[i].text,\r
878             (png_size_t)(text_length));\r
879       *(textp->text + text_length) = '\0';\r
880 \r
881 #ifdef PNG_iTXt_SUPPORTED\r
882       if (textp->compression > 0)\r
883       {\r
884          textp->text_length = 0;\r
885          textp->itxt_length = text_length;\r
886       }\r
887       else\r
888 #endif\r
889       {\r
890          textp->text_length = text_length;\r
891 #ifdef PNG_iTXt_SUPPORTED\r
892          textp->itxt_length = 0;\r
893 #endif\r
894       }\r
895       info_ptr->num_text++;\r
896       png_debug1(3, "transferred text chunk %d\n", info_ptr->num_text);\r
897    }\r
898    return(0);\r
899 }\r
900 #endif\r
901 \r
902 #if defined(PNG_tIME_SUPPORTED)\r
903 void PNGAPI\r
904 png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_timep mod_time)\r
905 {\r
906    png_debug1(1, "in %s storage function\n", "tIME");\r
907    if (png_ptr == NULL || info_ptr == NULL ||\r
908        (png_ptr->mode & PNG_WROTE_tIME))\r
909       return;\r
910 \r
911    png_memcpy(&(info_ptr->mod_time), mod_time, png_sizeof(png_time));\r
912    info_ptr->valid |= PNG_INFO_tIME;\r
913 }\r
914 #endif\r
915 \r
916 #if defined(PNG_tRNS_SUPPORTED)\r
917 void PNGAPI\r
918 png_set_tRNS(png_structp png_ptr, png_infop info_ptr,\r
919    png_bytep trans, int num_trans, png_color_16p trans_values)\r
920 {\r
921    png_debug1(1, "in %s storage function\n", "tRNS");\r
922    if (png_ptr == NULL || info_ptr == NULL)\r
923       return;\r
924 \r
925    if (trans != NULL)\r
926    {\r
927        /*\r
928         * It may not actually be necessary to set png_ptr->trans here;\r
929         * we do it for backward compatibility with the way the png_handle_tRNS\r
930         * function used to do the allocation.\r
931         */\r
932 \r
933 #ifdef PNG_FREE_ME_SUPPORTED\r
934        png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);\r
935 #endif\r
936 \r
937        /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */\r
938        png_ptr->trans = info_ptr->trans = (png_bytep)png_malloc(png_ptr,\r
939            (png_uint_32)PNG_MAX_PALETTE_LENGTH);\r
940        if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH)\r
941          png_memcpy(info_ptr->trans, trans, (png_size_t)num_trans);\r
942    }\r
943 \r
944    if (trans_values != NULL)\r
945    {\r
946       int sample_max = (1 << info_ptr->bit_depth);\r
947       if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY &&\r
948           (int)trans_values->gray > sample_max) ||\r
949           (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&\r
950           ((int)trans_values->red > sample_max ||\r
951           (int)trans_values->green > sample_max ||\r
952           (int)trans_values->blue > sample_max)))\r
953         png_warning(png_ptr,\r
954            "tRNS chunk has out-of-range samples for bit_depth");\r
955       png_memcpy(&(info_ptr->trans_values), trans_values,\r
956          png_sizeof(png_color_16));\r
957       if (num_trans == 0)\r
958         num_trans = 1;\r
959    }\r
960 \r
961    info_ptr->num_trans = (png_uint_16)num_trans;\r
962    if (num_trans != 0)\r
963    {\r
964       info_ptr->valid |= PNG_INFO_tRNS;\r
965 #ifdef PNG_FREE_ME_SUPPORTED\r
966       info_ptr->free_me |= PNG_FREE_TRNS;\r
967 #else\r
968       png_ptr->flags |= PNG_FLAG_FREE_TRNS;\r
969 #endif\r
970    }\r
971 }\r
972 #endif\r
973 \r
974 #if defined(PNG_sPLT_SUPPORTED)\r
975 void PNGAPI\r
976 png_set_sPLT(png_structp png_ptr,\r
977              png_infop info_ptr, png_sPLT_tp entries, int nentries)\r
978 /*\r
979  *  entries        - array of png_sPLT_t structures\r
980  *                   to be added to the list of palettes\r
981  *                   in the info structure.\r
982  *  nentries       - number of palette structures to be\r
983  *                   added.\r
984  */\r
985 {\r
986     png_sPLT_tp np;\r
987     int i;\r
988 \r
989     if (png_ptr == NULL || info_ptr == NULL)\r
990        return;\r
991 \r
992     np = (png_sPLT_tp)png_malloc_warn(png_ptr,\r
993         (info_ptr->splt_palettes_num + nentries) *\r
994         (png_uint_32)png_sizeof(png_sPLT_t));\r
995     if (np == NULL)\r
996     {\r
997       png_warning(png_ptr, "No memory for sPLT palettes.");\r
998       return;\r
999     }\r
1000 \r
1001     png_memcpy(np, info_ptr->splt_palettes,\r
1002            info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t));\r
1003     png_free(png_ptr, info_ptr->splt_palettes);\r
1004     info_ptr->splt_palettes=NULL;\r
1005 \r
1006     for (i = 0; i < nentries; i++)\r
1007     {\r
1008         png_sPLT_tp to = np + info_ptr->splt_palettes_num + i;\r
1009         png_sPLT_tp from = entries + i;\r
1010         png_uint_32 length;\r
1011 \r
1012         length = png_strlen(from->name) + 1;\r
1013         to->name = (png_charp)png_malloc_warn(png_ptr, length);\r
1014         if (to->name == NULL)\r
1015         {\r
1016            png_warning(png_ptr,\r
1017              "Out of memory while processing sPLT chunk");\r
1018            continue;\r
1019         }\r
1020         png_memcpy(to->name, from->name, length);\r
1021         to->entries = (png_sPLT_entryp)png_malloc_warn(png_ptr,\r
1022             (png_uint_32)(from->nentries * png_sizeof(png_sPLT_entry)));\r
1023         if (to->entries == NULL)\r
1024         {\r
1025            png_warning(png_ptr,\r
1026              "Out of memory while processing sPLT chunk");\r
1027            png_free(png_ptr, to->name);\r
1028            to->name = NULL;\r
1029            continue;\r
1030         }\r
1031         png_memcpy(to->entries, from->entries,\r
1032             from->nentries * png_sizeof(png_sPLT_entry));\r
1033         to->nentries = from->nentries;\r
1034         to->depth = from->depth;\r
1035     }\r
1036 \r
1037     info_ptr->splt_palettes = np;\r
1038     info_ptr->splt_palettes_num += nentries;\r
1039     info_ptr->valid |= PNG_INFO_sPLT;\r
1040 #ifdef PNG_FREE_ME_SUPPORTED\r
1041     info_ptr->free_me |= PNG_FREE_SPLT;\r
1042 #endif\r
1043 }\r
1044 #endif /* PNG_sPLT_SUPPORTED */\r
1045 \r
1046 #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)\r
1047 void PNGAPI\r
1048 png_set_unknown_chunks(png_structp png_ptr,\r
1049    png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns)\r
1050 {\r
1051     png_unknown_chunkp np;\r
1052     int i;\r
1053 \r
1054     if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0)\r
1055         return;\r
1056 \r
1057     np = (png_unknown_chunkp)png_malloc_warn(png_ptr,\r
1058         (png_uint_32)((info_ptr->unknown_chunks_num + num_unknowns) *\r
1059         png_sizeof(png_unknown_chunk)));\r
1060     if (np == NULL)\r
1061     {\r
1062        png_warning(png_ptr,\r
1063           "Out of memory while processing unknown chunk.");\r
1064        return;\r
1065     }\r
1066 \r
1067     png_memcpy(np, info_ptr->unknown_chunks,\r
1068            info_ptr->unknown_chunks_num * png_sizeof(png_unknown_chunk));\r
1069     png_free(png_ptr, info_ptr->unknown_chunks);\r
1070     info_ptr->unknown_chunks=NULL;\r
1071 \r
1072     for (i = 0; i < num_unknowns; i++)\r
1073     {\r
1074        png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i;\r
1075        png_unknown_chunkp from = unknowns + i;\r
1076 \r
1077        png_memcpy((png_charp)to->name, \r
1078                   (png_charp)from->name, \r
1079                   png_sizeof(from->name));\r
1080        to->name[png_sizeof(to->name)-1] = '\0';\r
1081        to->size = from->size;\r
1082        /* note our location in the read or write sequence */\r
1083        to->location = (png_byte)(png_ptr->mode & 0xff);\r
1084 \r
1085        if (from->size == 0)\r
1086           to->data=NULL;\r
1087        else\r
1088        {\r
1089           to->data = (png_bytep)png_malloc_warn(png_ptr,\r
1090             (png_uint_32)from->size);\r
1091           if (to->data == NULL)\r
1092           {\r
1093              png_warning(png_ptr,\r
1094               "Out of memory while processing unknown chunk.");\r
1095              to->size = 0;\r
1096           }\r
1097           else\r
1098              png_memcpy(to->data, from->data, from->size);\r
1099        }\r
1100     }\r
1101 \r
1102     info_ptr->unknown_chunks = np;\r
1103     info_ptr->unknown_chunks_num += num_unknowns;\r
1104 #ifdef PNG_FREE_ME_SUPPORTED\r
1105     info_ptr->free_me |= PNG_FREE_UNKN;\r
1106 #endif\r
1107 }\r
1108 void PNGAPI\r
1109 png_set_unknown_chunk_location(png_structp png_ptr, png_infop info_ptr,\r
1110    int chunk, int location)\r
1111 {\r
1112    if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 && chunk <\r
1113          (int)info_ptr->unknown_chunks_num)\r
1114       info_ptr->unknown_chunks[chunk].location = (png_byte)location;\r
1115 }\r
1116 #endif\r
1117 \r
1118 #if defined(PNG_1_0_X) || defined(PNG_1_2_X)\r
1119 #if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \\r
1120     defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED)\r
1121 void PNGAPI\r
1122 png_permit_empty_plte (png_structp png_ptr, int empty_plte_permitted)\r
1123 {\r
1124    /* This function is deprecated in favor of png_permit_mng_features()\r
1125       and will be removed from libpng-1.3.0 */\r
1126    png_debug(1, "in png_permit_empty_plte, DEPRECATED.\n");\r
1127    if (png_ptr == NULL)\r
1128       return;\r
1129    png_ptr->mng_features_permitted = (png_byte)\r
1130      ((png_ptr->mng_features_permitted & (~PNG_FLAG_MNG_EMPTY_PLTE)) |\r
1131      ((empty_plte_permitted & PNG_FLAG_MNG_EMPTY_PLTE)));\r
1132 }\r
1133 #endif\r
1134 #endif\r
1135 \r
1136 #if defined(PNG_MNG_FEATURES_SUPPORTED)\r
1137 png_uint_32 PNGAPI\r
1138 png_permit_mng_features (png_structp png_ptr, png_uint_32 mng_features)\r
1139 {\r
1140    png_debug(1, "in png_permit_mng_features\n");\r
1141    if (png_ptr == NULL)\r
1142       return (png_uint_32)0;\r
1143    png_ptr->mng_features_permitted =\r
1144      (png_byte)(mng_features & PNG_ALL_MNG_FEATURES);\r
1145    return (png_uint_32)png_ptr->mng_features_permitted;\r
1146 }\r
1147 #endif\r
1148 \r
1149 #if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)\r
1150 void PNGAPI\r
1151 png_set_keep_unknown_chunks(png_structp png_ptr, int keep, png_bytep\r
1152    chunk_list, int num_chunks)\r
1153 {\r
1154     png_bytep new_list, p;\r
1155     int i, old_num_chunks;\r
1156     if (png_ptr == NULL)\r
1157        return;\r
1158     if (num_chunks == 0)\r
1159     {\r
1160       if (keep == PNG_HANDLE_CHUNK_ALWAYS || keep == PNG_HANDLE_CHUNK_IF_SAFE)\r
1161         png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS;\r
1162       else\r
1163         png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS;\r
1164 \r
1165       if (keep == PNG_HANDLE_CHUNK_ALWAYS)\r
1166         png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS;\r
1167       else\r
1168         png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS;\r
1169       return;\r
1170     }\r
1171     if (chunk_list == NULL)\r
1172       return;\r
1173     old_num_chunks = png_ptr->num_chunk_list;\r
1174     new_list=(png_bytep)png_malloc(png_ptr,\r
1175        (png_uint_32)\r
1176        (5*(num_chunks + old_num_chunks)));\r
1177     if (png_ptr->chunk_list != NULL)\r
1178     {\r
1179        png_memcpy(new_list, png_ptr->chunk_list,\r
1180           (png_size_t)(5*old_num_chunks));\r
1181        png_free(png_ptr, png_ptr->chunk_list);\r
1182        png_ptr->chunk_list=NULL;\r
1183     }\r
1184     png_memcpy(new_list + 5*old_num_chunks, chunk_list,\r
1185        (png_size_t)(5*num_chunks));\r
1186     for (p = new_list + 5*old_num_chunks + 4, i = 0; i<num_chunks; i++, p += 5)\r
1187        *p=(png_byte)keep;\r
1188     png_ptr->num_chunk_list = old_num_chunks + num_chunks;\r
1189     png_ptr->chunk_list = new_list;\r
1190 #ifdef PNG_FREE_ME_SUPPORTED\r
1191     png_ptr->free_me |= PNG_FREE_LIST;\r
1192 #endif\r
1193 }\r
1194 #endif\r
1195 \r
1196 #if defined(PNG_READ_USER_CHUNKS_SUPPORTED)\r
1197 void PNGAPI\r
1198 png_set_read_user_chunk_fn(png_structp png_ptr, png_voidp user_chunk_ptr,\r
1199    png_user_chunk_ptr read_user_chunk_fn)\r
1200 {\r
1201    png_debug(1, "in png_set_read_user_chunk_fn\n");\r
1202    if (png_ptr == NULL)\r
1203       return;\r
1204    png_ptr->read_user_chunk_fn = read_user_chunk_fn;\r
1205    png_ptr->user_chunk_ptr = user_chunk_ptr;\r
1206 }\r
1207 #endif\r
1208 \r
1209 #if defined(PNG_INFO_IMAGE_SUPPORTED)\r
1210 void PNGAPI\r
1211 png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers)\r
1212 {\r
1213    png_debug1(1, "in %s storage function\n", "rows");\r
1214 \r
1215    if (png_ptr == NULL || info_ptr == NULL)\r
1216       return;\r
1217 \r
1218    if (info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers))\r
1219       png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);\r
1220    info_ptr->row_pointers = row_pointers;\r
1221    if (row_pointers)\r
1222       info_ptr->valid |= PNG_INFO_IDAT;\r
1223 }\r
1224 #endif\r
1225 \r
1226 #ifdef PNG_WRITE_SUPPORTED\r
1227 void PNGAPI\r
1228 png_set_compression_buffer_size(png_structp png_ptr,\r
1229     png_uint_32 size)\r
1230 {\r
1231     if (png_ptr == NULL)\r
1232        return;\r
1233     png_free(png_ptr, png_ptr->zbuf);\r
1234     png_ptr->zbuf_size = (png_size_t)size;\r
1235     png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, size);\r
1236     png_ptr->zstream.next_out = png_ptr->zbuf;\r
1237     png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;\r
1238 }\r
1239 #endif\r
1240 \r
1241 void PNGAPI\r
1242 png_set_invalid(png_structp png_ptr, png_infop info_ptr, int mask)\r
1243 {\r
1244    if (png_ptr && info_ptr)\r
1245       info_ptr->valid &= ~mask;\r
1246 }\r
1247 \r
1248 \r
1249 #ifndef PNG_1_0_X\r
1250 #ifdef PNG_ASSEMBLER_CODE_SUPPORTED\r
1251 /* function was added to libpng 1.2.0 and should always exist by default */\r
1252 void PNGAPI\r
1253 png_set_asm_flags (png_structp png_ptr, png_uint_32 asm_flags)\r
1254 {\r
1255 /* Obsolete as of libpng-1.2.20 and will be removed from libpng-1.4.0 */\r
1256     if (png_ptr != NULL)\r
1257     png_ptr->asm_flags = 0;\r
1258     asm_flags = asm_flags; /* Quiet the compiler */\r
1259 }\r
1260 \r
1261 /* this function was added to libpng 1.2.0 */\r
1262 void PNGAPI\r
1263 png_set_mmx_thresholds (png_structp png_ptr,\r
1264                         png_byte mmx_bitdepth_threshold,\r
1265                         png_uint_32 mmx_rowbytes_threshold)\r
1266 {\r
1267 /* Obsolete as of libpng-1.2.20 and will be removed from libpng-1.4.0 */\r
1268     if (png_ptr == NULL)\r
1269        return;\r
1270     /* Quiet the compiler */\r
1271     mmx_bitdepth_threshold = mmx_bitdepth_threshold;\r
1272     mmx_rowbytes_threshold = mmx_rowbytes_threshold;\r
1273 }\r
1274 #endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */\r
1275 \r
1276 #ifdef PNG_SET_USER_LIMITS_SUPPORTED\r
1277 /* this function was added to libpng 1.2.6 */\r
1278 void PNGAPI\r
1279 png_set_user_limits (png_structp png_ptr, png_uint_32 user_width_max,\r
1280     png_uint_32 user_height_max)\r
1281 {\r
1282     /* Images with dimensions larger than these limits will be\r
1283      * rejected by png_set_IHDR().  To accept any PNG datastream\r
1284      * regardless of dimensions, set both limits to 0x7ffffffL.\r
1285      */\r
1286     if (png_ptr == NULL) return;\r
1287     png_ptr->user_width_max = user_width_max;\r
1288     png_ptr->user_height_max = user_height_max;\r
1289 }\r
1290 #endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */\r
1291 \r
1292 #endif /* ?PNG_1_0_X */\r
1293 #endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */\r