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