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