pngset.c 38.9 KB
Newer Older
A
Andreas Dilger 已提交
1 2

/* pngset.c - storage of image information into info struct
3
 *
4
 * libpng 1.2.9beta3 - February 24, 2006
5
 * For conditions of distribution and use, see copyright notice in png.h
6
 * Copyright (c) 1998-2006 Glenn Randers-Pehrson
7 8
 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
9 10 11 12 13 14
 *
 * The functions here are used during reads to store data from the file
 * into the info struct, and during writes to store application data
 * into the info struct for writing into the file.  This abstracts the
 * info struct and allows us to change the structure in the future.
 */
A
Andreas Dilger 已提交
15 16 17 18

#define PNG_INTERNAL
#include "png.h"

19 20
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)

21
#if defined(PNG_bKGD_SUPPORTED)
22
void PNGAPI
A
Andreas Dilger 已提交
23 24 25
png_set_bKGD(png_structp png_ptr, png_infop info_ptr, png_color_16p background)
{
   png_debug1(1, "in %s storage function\n", "bKGD");
26
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
27 28
      return;

29
   png_memcpy(&(info_ptr->background), background, png_sizeof(png_color_16));
A
Andreas Dilger 已提交
30 31 32 33
   info_ptr->valid |= PNG_INFO_bKGD;
}
#endif

34 35
#if defined(PNG_cHRM_SUPPORTED)
#ifdef PNG_FLOATING_POINT_SUPPORTED
36
void PNGAPI
A
Andreas Dilger 已提交
37 38 39 40 41
png_set_cHRM(png_structp png_ptr, png_infop info_ptr,
   double white_x, double white_y, double red_x, double red_y,
   double green_x, double green_y, double blue_x, double blue_y)
{
   png_debug1(1, "in %s storage function\n", "cHRM");
42
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
43 44
      return;

45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
   if (white_x < 0.0 || white_y < 0.0 ||
         red_x < 0.0 ||   red_y < 0.0 ||
       green_x < 0.0 || green_y < 0.0 ||
        blue_x < 0.0 ||  blue_y < 0.0)
   {
      png_warning(png_ptr,
        "Ignoring attempt to set negative chromaticity value");
      return;
   }
   if (white_x > 21474.83 || white_y > 21474.83 ||
         red_x > 21474.83 ||   red_y > 21474.83 ||
       green_x > 21474.83 || green_y > 21474.83 ||
        blue_x > 21474.83 ||  blue_y > 21474.83)
   {
      png_warning(png_ptr,
        "Ignoring attempt to set chromaticity value exceeding 21474.83");
      return;
   }

A
Andreas Dilger 已提交
64 65 66 67 68 69 70 71
   info_ptr->x_white = (float)white_x;
   info_ptr->y_white = (float)white_y;
   info_ptr->x_red   = (float)red_x;
   info_ptr->y_red   = (float)red_y;
   info_ptr->x_green = (float)green_x;
   info_ptr->y_green = (float)green_y;
   info_ptr->x_blue  = (float)blue_x;
   info_ptr->y_blue  = (float)blue_y;
72 73 74
#ifdef PNG_FIXED_POINT_SUPPORTED
   info_ptr->int_x_white = (png_fixed_point)(white_x*100000.+0.5);
   info_ptr->int_y_white = (png_fixed_point)(white_y*100000.+0.5);
75 76
   info_ptr->int_x_red   = (png_fixed_point)(  red_x*100000.+0.5);
   info_ptr->int_y_red   = (png_fixed_point)(  red_y*100000.+0.5);
77 78
   info_ptr->int_x_green = (png_fixed_point)(green_x*100000.+0.5);
   info_ptr->int_y_green = (png_fixed_point)(green_y*100000.+0.5);
79 80
   info_ptr->int_x_blue  = (png_fixed_point)( blue_x*100000.+0.5);
   info_ptr->int_y_blue  = (png_fixed_point)( blue_y*100000.+0.5);
81
#endif
A
Andreas Dilger 已提交
82 83 84
   info_ptr->valid |= PNG_INFO_cHRM;
}
#endif
85
#ifdef PNG_FIXED_POINT_SUPPORTED
86
void PNGAPI
87
png_set_cHRM_fixed(png_structp png_ptr, png_infop info_ptr,
88 89 90
   png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x,
   png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y,
   png_fixed_point blue_x, png_fixed_point blue_y)
91 92 93 94
{
   png_debug1(1, "in %s storage function\n", "cHRM");
   if (png_ptr == NULL || info_ptr == NULL)
      return;
A
Andreas Dilger 已提交
95

96 97 98 99 100 101 102 103 104
   if (white_x < 0 || white_y < 0 ||
         red_x < 0 ||   red_y < 0 ||
       green_x < 0 || green_y < 0 ||
        blue_x < 0 ||  blue_y < 0)
   {
      png_warning(png_ptr,
        "Ignoring attempt to set negative chromaticity value");
      return;
   }
105
#ifdef PNG_FLOATING_POINT_SUPPORTED
106 107 108 109 110 111 112 113
   if (white_x > (double) PNG_UINT_31_MAX ||
       white_y > (double) PNG_UINT_31_MAX ||
         red_x > (double) PNG_UINT_31_MAX ||
         red_y > (double) PNG_UINT_31_MAX ||
       green_x > (double) PNG_UINT_31_MAX ||
       green_y > (double) PNG_UINT_31_MAX ||
        blue_x > (double) PNG_UINT_31_MAX ||
        blue_y > (double) PNG_UINT_31_MAX)
114 115 116 117 118 119 120 121 122 123
#else
   if (white_x > (png_fixed_point) PNG_UINT_31_MAX/100000L ||
       white_y > (png_fixed_point) PNG_UINT_31_MAX/100000L ||
         red_x > (png_fixed_point) PNG_UINT_31_MAX/100000L ||
         red_y > (png_fixed_point) PNG_UINT_31_MAX/100000L ||
       green_x > (png_fixed_point) PNG_UINT_31_MAX/100000L ||
       green_y > (png_fixed_point) PNG_UINT_31_MAX/100000L ||
        blue_x > (png_fixed_point) PNG_UINT_31_MAX/100000L ||
        blue_y > (png_fixed_point) PNG_UINT_31_MAX/100000L)
#endif
124 125 126 127 128
   {
      png_warning(png_ptr,
        "Ignoring attempt to set chromaticity value exceeding 21474.83");
      return;
   }
129 130 131 132 133 134 135 136
   info_ptr->int_x_white = white_x;
   info_ptr->int_y_white = white_y;
   info_ptr->int_x_red   = red_x;
   info_ptr->int_y_red   = red_y;
   info_ptr->int_x_green = green_x;
   info_ptr->int_y_green = green_y;
   info_ptr->int_x_blue  = blue_x;
   info_ptr->int_y_blue  = blue_y;
137 138 139
#ifdef PNG_FLOATING_POINT_SUPPORTED
   info_ptr->x_white = (float)(white_x/100000.);
   info_ptr->y_white = (float)(white_y/100000.);
140 141
   info_ptr->x_red   = (float)(  red_x/100000.);
   info_ptr->y_red   = (float)(  red_y/100000.);
142 143
   info_ptr->x_green = (float)(green_x/100000.);
   info_ptr->y_green = (float)(green_y/100000.);
144 145
   info_ptr->x_blue  = (float)( blue_x/100000.);
   info_ptr->y_blue  = (float)( blue_y/100000.);
146
#endif
147 148 149 150 151 152 153
   info_ptr->valid |= PNG_INFO_cHRM;
}
#endif
#endif

#if defined(PNG_gAMA_SUPPORTED)
#ifdef PNG_FLOATING_POINT_SUPPORTED
154
void PNGAPI
A
Andreas Dilger 已提交
155 156
png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma)
{
157
   double gamma;
A
Andreas Dilger 已提交
158
   png_debug1(1, "in %s storage function\n", "gAMA");
159
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
160 161
      return;

162 163 164 165 166 167 168 169 170
   /* Check for overflow */
   if (file_gamma > 21474.83)
   {
      png_warning(png_ptr, "Limiting gamma to 21474.83");
      gamma=21474.83;
   }
   else
      gamma=file_gamma;
   info_ptr->gamma = (float)gamma;
171
#ifdef PNG_FIXED_POINT_SUPPORTED
172
   info_ptr->int_gamma = (int)(gamma*100000.+.5);
173 174
#endif
   info_ptr->valid |= PNG_INFO_gAMA;
175
   if(gamma == 0.0)
176
      png_warning(png_ptr, "Setting gamma=0");
177 178
}
#endif
179
void PNGAPI
180 181
png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point
   int_gamma)
182
{
183 184
   png_fixed_point gamma;

185 186 187 188
   png_debug1(1, "in %s storage function\n", "gAMA");
   if (png_ptr == NULL || info_ptr == NULL)
      return;

189
   if (int_gamma > (png_fixed_point) PNG_UINT_31_MAX)
190 191
   {
     png_warning(png_ptr, "Limiting gamma to 21474.83");
192
     gamma=PNG_UINT_31_MAX;
193 194 195 196 197 198 199 200 201 202 203
   }
   else
   {
     if (int_gamma < 0)
     {
       png_warning(png_ptr, "Setting negative gamma to zero");
       gamma=0;
     }
     else
       gamma=int_gamma;
   }
204
#ifdef PNG_FLOATING_POINT_SUPPORTED
205
   info_ptr->gamma = (float)(gamma/100000.);
206
#endif
207
#ifdef PNG_FIXED_POINT_SUPPORTED
208
   info_ptr->int_gamma = gamma;
209
#endif
A
Andreas Dilger 已提交
210
   info_ptr->valid |= PNG_INFO_gAMA;
211
   if(gamma == 0)
212
      png_warning(png_ptr, "Setting gamma=0");
A
Andreas Dilger 已提交
213
}
214
#endif
A
Andreas Dilger 已提交
215

216
#if defined(PNG_hIST_SUPPORTED)
217
void PNGAPI
A
Andreas Dilger 已提交
218 219
png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p hist)
{
220
   int i;
221

A
Andreas Dilger 已提交
222
   png_debug1(1, "in %s storage function\n", "hIST");
223
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
224
      return;
225 226
   if (info_ptr->num_palette <= 0 || info_ptr->num_palette
       > PNG_MAX_PALETTE_LENGTH)
227
   {
228
       png_warning(png_ptr,
229
          "Invalid palette size, hIST allocation skipped.");
230 231
       return;
   }
232 233 234 235

#ifdef PNG_FREE_ME_SUPPORTED
   png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0);
#endif
236 237
   /* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in version
      1.2.1 */
238
   png_ptr->hist = (png_uint_16p)png_malloc_warn(png_ptr,
239
      (png_uint_32)(PNG_MAX_PALETTE_LENGTH * png_sizeof (png_uint_16)));
240 241 242 243 244
   if (png_ptr->hist == NULL)
     {
       png_warning(png_ptr, "Insufficient memory for hIST chunk data.");
       return;
     }
A
Andreas Dilger 已提交
245

246 247 248
   for (i = 0; i < info_ptr->num_palette; i++)
       png_ptr->hist[i] = hist[i];
   info_ptr->hist = png_ptr->hist;
A
Andreas Dilger 已提交
249
   info_ptr->valid |= PNG_INFO_hIST;
250 251 252 253 254 255

#ifdef PNG_FREE_ME_SUPPORTED
   info_ptr->free_me |= PNG_FREE_HIST;
#else
   png_ptr->flags |= PNG_FLAG_FREE_HIST;
#endif
A
Andreas Dilger 已提交
256 257 258
}
#endif

259
void PNGAPI
A
Andreas Dilger 已提交
260 261 262 263 264 265
png_set_IHDR(png_structp png_ptr, png_infop info_ptr,
   png_uint_32 width, png_uint_32 height, int bit_depth,
   int color_type, int interlace_type, int compression_type,
   int filter_type)
{
   png_debug1(1, "in %s storage function\n", "IHDR");
266
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
267 268
      return;

269 270 271
   /* check for width and height valid values */
   if (width == 0 || height == 0)
      png_error(png_ptr, "Image width or height is zero in IHDR");
272 273 274 275 276 277 278
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
   if (width > png_ptr->user_width_max || height > png_ptr->user_height_max)
      png_error(png_ptr, "image size exceeds user limits in IHDR");
#else
   if (width > PNG_USER_WIDTH_MAX || height > PNG_USER_HEIGHT_MAX)
      png_error(png_ptr, "image size exceeds user limits in IHDR");
#endif
279
   if (width > PNG_UINT_31_MAX || height > PNG_UINT_31_MAX)
280
      png_error(png_ptr, "Invalid image size in IHDR");
281 282 283 284 285 286 287
   if ( width > (PNG_UINT_32_MAX
                 >> 3)      /* 8-byte RGBA pixels */
                 - 64       /* bigrowbuf hack */
                 - 1        /* filter byte */
                 - 7*8      /* rounding of width to multiple of 8 pixels */
                 - 8)       /* extra max_pixel_depth pad */
      png_warning(png_ptr, "Width is too large for libpng to process pixels");
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337

   /* check other values */
   if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 &&
      bit_depth != 8 && bit_depth != 16)
      png_error(png_ptr, "Invalid bit depth in IHDR");

   if (color_type < 0 || color_type == 1 ||
      color_type == 5 || color_type > 6)
      png_error(png_ptr, "Invalid color type in IHDR");

   if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) ||
       ((color_type == PNG_COLOR_TYPE_RGB ||
         color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
         color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8))
      png_error(png_ptr, "Invalid color type/bit depth combination in IHDR");

   if (interlace_type >= PNG_INTERLACE_LAST)
      png_error(png_ptr, "Unknown interlace method in IHDR");

   if (compression_type != PNG_COMPRESSION_TYPE_BASE)
      png_error(png_ptr, "Unknown compression method in IHDR");

#if defined(PNG_MNG_FEATURES_SUPPORTED)
   /* Accept filter_method 64 (intrapixel differencing) only if
    * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
    * 2. Libpng did not read a PNG signature (this filter_method is only
    *    used in PNG datastreams that are embedded in MNG datastreams) and
    * 3. The application called png_permit_mng_features with a mask that
    *    included PNG_FLAG_MNG_FILTER_64 and
    * 4. The filter_method is 64 and
    * 5. The color_type is RGB or RGBA
    */
   if((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&png_ptr->mng_features_permitted)
      png_warning(png_ptr,"MNG features are not allowed in a PNG datastream\n");
   if(filter_type != PNG_FILTER_TYPE_BASE)
   {
     if(!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
        (filter_type == PNG_INTRAPIXEL_DIFFERENCING) &&
        ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&
        (color_type == PNG_COLOR_TYPE_RGB || 
         color_type == PNG_COLOR_TYPE_RGB_ALPHA)))
        png_error(png_ptr, "Unknown filter method in IHDR");
     if(png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)
        png_warning(png_ptr, "Invalid filter method in IHDR");
   }
#else
   if(filter_type != PNG_FILTER_TYPE_BASE)
      png_error(png_ptr, "Unknown filter method in IHDR");
#endif

A
Andreas Dilger 已提交
338 339 340 341 342 343 344
   info_ptr->width = width;
   info_ptr->height = height;
   info_ptr->bit_depth = (png_byte)bit_depth;
   info_ptr->color_type =(png_byte) color_type;
   info_ptr->compression_type = (png_byte)compression_type;
   info_ptr->filter_type = (png_byte)filter_type;
   info_ptr->interlace_type = (png_byte)interlace_type;
345 346 347
   if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
      info_ptr->channels = 1;
   else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
A
Andreas Dilger 已提交
348 349 350 351 352 353
      info_ptr->channels = 3;
   else
      info_ptr->channels = 1;
   if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
      info_ptr->channels++;
   info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth);
354

355 356 357 358 359 360 361
   /* check for potential overflow */
   if ( width > (PNG_UINT_32_MAX
                 >> 3)      /* 8-byte RGBA pixels */
                 - 64       /* bigrowbuf hack */
                 - 1        /* filter byte */
                 - 7*8      /* rounding of width to multiple of 8 pixels */
                 - 8)       /* extra max_pixel_depth pad */
362
      info_ptr->rowbytes = (png_size_t)0;
363
   else
364
      info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth,width);
A
Andreas Dilger 已提交
365 366
}

367
#if defined(PNG_oFFs_SUPPORTED)
368
void PNGAPI
A
Andreas Dilger 已提交
369
png_set_oFFs(png_structp png_ptr, png_infop info_ptr,
370
   png_int_32 offset_x, png_int_32 offset_y, int unit_type)
A
Andreas Dilger 已提交
371 372
{
   png_debug1(1, "in %s storage function\n", "oFFs");
373
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
374 375 376 377 378 379 380 381 382
      return;

   info_ptr->x_offset = offset_x;
   info_ptr->y_offset = offset_y;
   info_ptr->offset_unit_type = (png_byte)unit_type;
   info_ptr->valid |= PNG_INFO_oFFs;
}
#endif

383
#if defined(PNG_pCAL_SUPPORTED)
384
void PNGAPI
A
Andreas Dilger 已提交
385 386 387 388
png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
   png_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams,
   png_charp units, png_charpp params)
{
389
   png_uint_32 length;
390
   int i;
A
Andreas Dilger 已提交
391 392

   png_debug1(1, "in %s storage function\n", "pCAL");
393
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
394 395 396
      return;

   length = png_strlen(purpose) + 1;
397
   png_debug1(3, "allocating purpose for info (%lu bytes)\n", length);
398 399 400 401 402 403
   info_ptr->pcal_purpose = (png_charp)png_malloc_warn(png_ptr, length);
   if (info_ptr->pcal_purpose == NULL)
     {
       png_warning(png_ptr, "Insufficient memory for pCAL purpose.");
       return;
     }
404
   png_memcpy(info_ptr->pcal_purpose, purpose, (png_size_t)length);
A
Andreas Dilger 已提交
405 406 407 408 409 410 411 412

   png_debug(3, "storing X0, X1, type, and nparams in info\n");
   info_ptr->pcal_X0 = X0;
   info_ptr->pcal_X1 = X1;
   info_ptr->pcal_type = (png_byte)type;
   info_ptr->pcal_nparams = (png_byte)nparams;

   length = png_strlen(units) + 1;
413
   png_debug1(3, "allocating units for info (%lu bytes)\n", length);
414 415 416 417 418 419
   info_ptr->pcal_units = (png_charp)png_malloc_warn(png_ptr, length);
   if (info_ptr->pcal_units == NULL)
     {
       png_warning(png_ptr, "Insufficient memory for pCAL units.");
       return;
     }
420
   png_memcpy(info_ptr->pcal_units, units, (png_size_t)length);
A
Andreas Dilger 已提交
421

422
   info_ptr->pcal_params = (png_charpp)png_malloc_warn(png_ptr,
423
      (png_uint_32)((nparams + 1) * png_sizeof(png_charp)));
424 425 426 427 428
   if (info_ptr->pcal_params == NULL)
     {
       png_warning(png_ptr, "Insufficient memory for pCAL params.");
       return;
     }
429

A
Andreas Dilger 已提交
430 431 432 433 434
   info_ptr->pcal_params[nparams] = NULL;

   for (i = 0; i < nparams; i++)
   {
      length = png_strlen(params[i]) + 1;
435
      png_debug2(3, "allocating parameter %d for info (%lu bytes)\n", i, length);
436 437 438 439 440 441
      info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length);
      if (info_ptr->pcal_params[i] == NULL)
        {
          png_warning(png_ptr, "Insufficient memory for pCAL parameter.");
          return;
        }
442
      png_memcpy(info_ptr->pcal_params[i], params[i], (png_size_t)length);
A
Andreas Dilger 已提交
443 444 445
   }

   info_ptr->valid |= PNG_INFO_pCAL;
446 447 448
#ifdef PNG_FREE_ME_SUPPORTED
   info_ptr->free_me |= PNG_FREE_PCAL;
#endif
A
Andreas Dilger 已提交
449 450 451
}
#endif

452 453
#if defined(PNG_READ_sCAL_SUPPORTED) || defined(PNG_WRITE_sCAL_SUPPORTED)
#ifdef PNG_FLOATING_POINT_SUPPORTED
454
void PNGAPI
455
png_set_sCAL(png_structp png_ptr, png_infop info_ptr,
456
             int unit, double width, double height)
457 458 459 460 461
{
   png_debug1(1, "in %s storage function\n", "sCAL");
   if (png_ptr == NULL || info_ptr == NULL)
      return;

462
   info_ptr->scal_unit = (png_byte)unit;
463 464 465 466 467
   info_ptr->scal_pixel_width = width;
   info_ptr->scal_pixel_height = height;

   info_ptr->valid |= PNG_INFO_sCAL;
}
468 469
#else
#ifdef PNG_FIXED_POINT_SUPPORTED
470
void PNGAPI
471
png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr,
472
             int unit, png_charp swidth, png_charp sheight)
473 474 475 476 477 478 479
{
   png_uint_32 length;

   png_debug1(1, "in %s storage function\n", "sCAL");
   if (png_ptr == NULL || info_ptr == NULL)
      return;

480
   info_ptr->scal_unit = (png_byte)unit;
481 482 483

   length = png_strlen(swidth) + 1;
   png_debug1(3, "allocating unit for info (%d bytes)\n", length);
484 485 486 487 488
   info_ptr->scal_s_width = (png_charp)png_malloc_warn(png_ptr, length);
   if (info_ptr->scal_s_width == NULL)
   {
      png_warning(png_ptr, "Memory allocation failed while processing sCAL.");
   }
489
   png_memcpy(info_ptr->scal_s_width, swidth, (png_size_t)length);
490 491 492

   length = png_strlen(sheight) + 1;
   png_debug1(3, "allocating unit for info (%d bytes)\n", length);
493 494 495 496 497 498
   info_ptr->scal_s_height = (png_charp)png_malloc_warn(png_ptr, length);
   if (info_ptr->scal_s_height == NULL)
   {
      png_free (png_ptr, info_ptr->scal_s_width);
      png_warning(png_ptr, "Memory allocation failed while processing sCAL.");
   }
499
   png_memcpy(info_ptr->scal_s_height, sheight, (png_size_t)length);
500 501

   info_ptr->valid |= PNG_INFO_sCAL;
502 503 504
#ifdef PNG_FREE_ME_SUPPORTED
   info_ptr->free_me |= PNG_FREE_SCAL;
#endif
505 506
}
#endif
507 508
#endif
#endif
509 510

#if defined(PNG_pHYs_SUPPORTED)
511
void PNGAPI
A
Andreas Dilger 已提交
512 513 514 515
png_set_pHYs(png_structp png_ptr, png_infop info_ptr,
   png_uint_32 res_x, png_uint_32 res_y, int unit_type)
{
   png_debug1(1, "in %s storage function\n", "pHYs");
516
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
517 518 519 520 521 522 523 524 525
      return;

   info_ptr->x_pixels_per_unit = res_x;
   info_ptr->y_pixels_per_unit = res_y;
   info_ptr->phys_unit_type = (png_byte)unit_type;
   info_ptr->valid |= PNG_INFO_pHYs;
}
#endif

526
void PNGAPI
A
Andreas Dilger 已提交
527 528 529
png_set_PLTE(png_structp png_ptr, png_infop info_ptr,
   png_colorp palette, int num_palette)
{
530

A
Andreas Dilger 已提交
531
   png_debug1(1, "in %s storage function\n", "PLTE");
532
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
533 534
      return;

535 536 537 538 539 540 541 542 543 544 545
   if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH)
     {
       if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
         png_error(png_ptr, "Invalid palette length");
       else
       {
         png_warning(png_ptr, "Invalid palette length");
         return;
       }
     }

546 547 548 549 550 551 552 553
   /*
    * It may not actually be necessary to set png_ptr->palette here;
    * we do it for backward compatibility with the way the png_handle_tRNS
    * function used to do the allocation.
    */
#ifdef PNG_FREE_ME_SUPPORTED
   png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0);
#endif
554

555 556
   /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead
      of num_palette entries,
557
      in case of an invalid PNG file that has too-large sample values. */
558
   png_ptr->palette = (png_colorp)png_malloc(png_ptr,
559 560 561
      PNG_MAX_PALETTE_LENGTH * png_sizeof(png_color));
   png_memset(png_ptr->palette, 0, PNG_MAX_PALETTE_LENGTH *
      png_sizeof(png_color));
562
   png_memcpy(png_ptr->palette, palette, num_palette * png_sizeof (png_color));
563 564 565 566 567 568 569 570
   info_ptr->palette = png_ptr->palette;
   info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette;

#ifdef PNG_FREE_ME_SUPPORTED
   info_ptr->free_me |= PNG_FREE_PLTE;
#else
   png_ptr->flags |= PNG_FLAG_FREE_PLTE;
#endif
571

572
   info_ptr->valid |= PNG_INFO_PLTE;
A
Andreas Dilger 已提交
573 574
}

575
#if defined(PNG_sBIT_SUPPORTED)
576
void PNGAPI
A
Andreas Dilger 已提交
577 578 579 580
png_set_sBIT(png_structp png_ptr, png_infop info_ptr,
   png_color_8p sig_bit)
{
   png_debug1(1, "in %s storage function\n", "sBIT");
581
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
582 583
      return;

584
   png_memcpy(&(info_ptr->sig_bit), sig_bit, png_sizeof (png_color_8));
A
Andreas Dilger 已提交
585 586 587 588
   info_ptr->valid |= PNG_INFO_sBIT;
}
#endif

589
#if defined(PNG_sRGB_SUPPORTED)
590
void PNGAPI
591
png_set_sRGB(png_structp png_ptr, png_infop info_ptr, int intent)
592 593
{
   png_debug1(1, "in %s storage function\n", "sRGB");
594
   if (png_ptr == NULL || info_ptr == NULL)
595 596
      return;

597
   info_ptr->srgb_intent = (png_byte)intent;
598 599
   info_ptr->valid |= PNG_INFO_sRGB;
}
600

601
void PNGAPI
602
png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr,
603
   int intent)
604
{
605 606
#if defined(PNG_gAMA_SUPPORTED)
#ifdef PNG_FLOATING_POINT_SUPPORTED
607 608
   float file_gamma;
#endif
609
#ifdef PNG_FIXED_POINT_SUPPORTED
610
   png_fixed_point int_file_gamma;
611 612 613 614
#endif
#endif
#if defined(PNG_cHRM_SUPPORTED)
#ifdef PNG_FLOATING_POINT_SUPPORTED
615
   float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
616 617
#endif
#ifdef PNG_FIXED_POINT_SUPPORTED
618
   png_fixed_point int_white_x, int_white_y, int_red_x, int_red_y, int_green_x,
619 620
      int_green_y, int_blue_x, int_blue_y;
#endif
621 622
#endif
   png_debug1(1, "in %s storage function\n", "sRGB_gAMA_and_cHRM");
623
   if (png_ptr == NULL || info_ptr == NULL)
624 625 626 627
      return;

   png_set_sRGB(png_ptr, info_ptr, intent);

628 629
#if defined(PNG_gAMA_SUPPORTED)
#ifdef PNG_FLOATING_POINT_SUPPORTED
630
   file_gamma = (float).45455;
631 632
   png_set_gAMA(png_ptr, info_ptr, file_gamma);
#endif
633 634 635 636 637
#ifdef PNG_FIXED_POINT_SUPPORTED
   int_file_gamma = 45455L;
   png_set_gAMA_fixed(png_ptr, info_ptr, int_file_gamma);
#endif
#endif
638

639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654
#if defined(PNG_cHRM_SUPPORTED)
#ifdef PNG_FIXED_POINT_SUPPORTED
   int_white_x = 31270L;
   int_white_y = 32900L;
   int_red_x   = 64000L;
   int_red_y   = 33000L;
   int_green_x = 30000L;
   int_green_y = 60000L;
   int_blue_x  = 15000L;
   int_blue_y  =  6000L;

   png_set_cHRM_fixed(png_ptr, info_ptr,
      int_white_x, int_white_y, int_red_x, int_red_y, int_green_x, int_green_y,
      int_blue_x, int_blue_y);
#endif
#ifdef PNG_FLOATING_POINT_SUPPORTED
655 656 657 658 659 660 661 662
   white_x = (float).3127;
   white_y = (float).3290;
   red_x   = (float).64;
   red_y   = (float).33;
   green_x = (float).30;
   green_y = (float).60;
   blue_x  = (float).15;
   blue_y  = (float).06;
663 664 665

   png_set_cHRM(png_ptr, info_ptr,
      white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
666
#endif
667 668 669 670
#endif
}
#endif

671 672

#if defined(PNG_iCCP_SUPPORTED)
673
void PNGAPI
674 675
png_set_iCCP(png_structp png_ptr, png_infop info_ptr,
             png_charp name, int compression_type,
676
             png_charp profile, png_uint_32 proflen)
677
{
678 679 680
   png_charp new_iccp_name;
   png_charp new_iccp_profile;

681 682 683 684
   png_debug1(1, "in %s storage function\n", "iCCP");
   if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL)
      return;

685 686 687 688 689 690
   new_iccp_name = (png_charp)png_malloc_warn(png_ptr, png_strlen(name)+1);
   if (new_iccp_name == NULL)
   {
      png_warning(png_ptr, "Insufficient memory to process iCCP chunk.");
      return;
   }
691
   png_strcpy(new_iccp_name, name);
692 693 694 695 696 697 698
   new_iccp_profile = (png_charp)png_malloc_warn(png_ptr, proflen);
   if (new_iccp_profile == NULL)
   {
      png_free (png_ptr, new_iccp_name);
      png_warning(png_ptr, "Insufficient memory to process iCCP profile.");
      return;
   }
699 700
   png_memcpy(new_iccp_profile, profile, (png_size_t)proflen);

701
   png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0);
702

703
   info_ptr->iccp_proflen = proflen;
704 705
   info_ptr->iccp_name = new_iccp_name;
   info_ptr->iccp_profile = new_iccp_profile;
706
   /* Compression is always zero but is here so the API and info structure
707
    * does not have to change if we introduce multiple compression types */
708
   info_ptr->iccp_compression = (png_byte)compression_type;
709
#ifdef PNG_FREE_ME_SUPPORTED
710
   info_ptr->free_me |= PNG_FREE_ICCP;
711
#endif
712 713 714 715 716
   info_ptr->valid |= PNG_INFO_iCCP;
}
#endif

#if defined(PNG_TEXT_SUPPORTED)
717
void PNGAPI
A
Andreas Dilger 已提交
718 719
png_set_text(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr,
   int num_text)
720 721 722 723 724 725 726 727 728 729
{
   int ret;
   ret=png_set_text_2(png_ptr, info_ptr, text_ptr, num_text);
   if (ret)
     png_error(png_ptr, "Insufficient memory to store text");
}

int /* PRIVATE */
png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr,
   int num_text)
A
Andreas Dilger 已提交
730 731 732 733
{
   int i;

   png_debug1(1, "in %s storage function\n", (png_ptr->chunk_name[0] == '\0' ?
734
      "text" : (png_const_charp)png_ptr->chunk_name));
A
Andreas Dilger 已提交
735

736
   if (png_ptr == NULL || info_ptr == NULL || num_text == 0)
737
      return(0);
A
Andreas Dilger 已提交
738 739 740 741 742 743 744 745 746 747 748 749 750 751

   /* Make sure we have enough space in the "text" array in info_struct
    * to hold all of the incoming text_ptr objects.
    */
   if (info_ptr->num_text + num_text > info_ptr->max_text)
   {
      if (info_ptr->text != NULL)
      {
         png_textp old_text;
         int old_max;

         old_max = info_ptr->max_text;
         info_ptr->max_text = info_ptr->num_text + num_text + 8;
         old_text = info_ptr->text;
752
         info_ptr->text = (png_textp)png_malloc_warn(png_ptr,
753
            (png_uint_32)(info_ptr->max_text * png_sizeof (png_text)));
754 755 756 757 758
         if (info_ptr->text == NULL)
           {
             png_free(png_ptr, old_text);
             return(1);
           }
759
         png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max *
760
            png_sizeof(png_text)));
A
Andreas Dilger 已提交
761 762 763 764 765 766
         png_free(png_ptr, old_text);
      }
      else
      {
         info_ptr->max_text = num_text + 8;
         info_ptr->num_text = 0;
767
         info_ptr->text = (png_textp)png_malloc_warn(png_ptr,
768
            (png_uint_32)(info_ptr->max_text * png_sizeof (png_text)));
769 770
         if (info_ptr->text == NULL)
           return(1);
771 772 773
#ifdef PNG_FREE_ME_SUPPORTED
         info_ptr->free_me |= PNG_FREE_TEXT;
#endif
A
Andreas Dilger 已提交
774 775 776 777 778 779
      }
      png_debug1(3, "allocated %d entries for info_ptr->text\n",
         info_ptr->max_text);
   }
   for (i = 0; i < num_text; i++)
   {
780 781
      png_size_t text_length,key_len;
      png_size_t lang_len,lang_key_len;
A
Andreas Dilger 已提交
782 783
      png_textp textp = &(info_ptr->text[info_ptr->num_text]);

784
      if (text_ptr[i].key == NULL)
785 786
          continue;

787 788
      key_len = png_strlen(text_ptr[i].key);

789 790 791 792 793 794
      if(text_ptr[i].compression <= 0)
      {
        lang_len = 0;
        lang_key_len = 0;
      }
      else
795
#ifdef PNG_iTXt_SUPPORTED
796 797
      {
        /* set iTXt data */
798
        if (text_ptr[i].lang != NULL)
799 800 801
          lang_len = png_strlen(text_ptr[i].lang);
        else
          lang_len = 0;
802
        if (text_ptr[i].lang_key != NULL)
803 804 805
          lang_key_len = png_strlen(text_ptr[i].lang_key);
        else
          lang_key_len = 0;
806
      }
807 808 809 810 811 812
#else
      {
        png_warning(png_ptr, "iTXt chunk not supported.");
        continue;
      }
#endif
A
Andreas Dilger 已提交
813

814
      if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0')
A
Andreas Dilger 已提交
815
      {
816
         text_length = 0;
817
#ifdef PNG_iTXt_SUPPORTED
818 819 820
         if(text_ptr[i].compression > 0)
            textp->compression = PNG_ITXT_COMPRESSION_NONE;
         else
821
#endif
822
            textp->compression = PNG_TEXT_COMPRESSION_NONE;
A
Andreas Dilger 已提交
823 824 825
      }
      else
      {
826
         text_length = png_strlen(text_ptr[i].text);
A
Andreas Dilger 已提交
827 828
         textp->compression = text_ptr[i].compression;
      }
829

830
      textp->key = (png_charp)png_malloc_warn(png_ptr,
831
         (png_uint_32)(key_len + text_length + lang_len + lang_key_len + 4));
832 833
      if (textp->key == NULL)
        return(1);
834 835 836
      png_debug2(2, "Allocated %lu bytes at %x in png_set_text\n",
         (png_uint_32)(key_len + lang_len + lang_key_len + text_length + 4),
         (int)textp->key);
837 838

      png_memcpy(textp->key, text_ptr[i].key,
839 840
         (png_size_t)(key_len));
      *(textp->key+key_len) = '\0';
841
#ifdef PNG_iTXt_SUPPORTED
842 843 844 845 846 847 848 849 850 851 852
      if (text_ptr[i].compression > 0)
      {
         textp->lang=textp->key + key_len + 1;
         png_memcpy(textp->lang, text_ptr[i].lang, lang_len);
         *(textp->lang+lang_len) = '\0';
         textp->lang_key=textp->lang + lang_len + 1;
         png_memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len);
         *(textp->lang_key+lang_key_len) = '\0';
         textp->text=textp->lang_key + lang_key_len + 1;
      }
      else
853
#endif
854
      {
855
#ifdef PNG_iTXt_SUPPORTED
856 857
         textp->lang=NULL;
         textp->lang_key=NULL;
858
#endif
859 860 861
         textp->text=textp->key + key_len + 1;
      }
      if(text_length)
862
         png_memcpy(textp->text, text_ptr[i].text,
863
            (png_size_t)(text_length));
864
      *(textp->text+text_length) = '\0';
865

866
#ifdef PNG_iTXt_SUPPORTED
867 868 869 870 871 872
      if(textp->compression > 0)
      {
         textp->text_length = 0;
         textp->itxt_length = text_length;
      }
      else
873
#endif
874 875
      {
         textp->text_length = text_length;
876
#ifdef PNG_iTXt_SUPPORTED
877
         textp->itxt_length = 0;
878
#endif
879
      }
880
      info_ptr->text[info_ptr->num_text]= *textp;
A
Andreas Dilger 已提交
881 882 883
      info_ptr->num_text++;
      png_debug1(3, "transferred text chunk %d\n", info_ptr->num_text);
   }
884
   return(0);
A
Andreas Dilger 已提交
885 886 887
}
#endif

888
#if defined(PNG_tIME_SUPPORTED)
889
void PNGAPI
A
Andreas Dilger 已提交
890 891 892
png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_timep mod_time)
{
   png_debug1(1, "in %s storage function\n", "tIME");
893
   if (png_ptr == NULL || info_ptr == NULL ||
894
       (png_ptr->mode & PNG_WROTE_tIME))
A
Andreas Dilger 已提交
895 896
      return;

897
   png_memcpy(&(info_ptr->mod_time), mod_time, png_sizeof (png_time));
A
Andreas Dilger 已提交
898 899 900 901
   info_ptr->valid |= PNG_INFO_tIME;
}
#endif

902
#if defined(PNG_tRNS_SUPPORTED)
903
void PNGAPI
A
Andreas Dilger 已提交
904 905 906 907
png_set_tRNS(png_structp png_ptr, png_infop info_ptr,
   png_bytep trans, int num_trans, png_color_16p trans_values)
{
   png_debug1(1, "in %s storage function\n", "tRNS");
908
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
909 910 911
      return;

   if (trans != NULL)
912 913
   {
       /*
914 915 916 917
        * It may not actually be necessary to set png_ptr->trans here;
        * we do it for backward compatibility with the way the png_handle_tRNS
        * function used to do the allocation.
        */
918 919 920
#ifdef PNG_FREE_ME_SUPPORTED
       png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
#endif
921
       /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */
922
       png_ptr->trans = info_ptr->trans = (png_bytep)png_malloc(png_ptr,
923 924 925
           (png_uint_32)PNG_MAX_PALETTE_LENGTH);
       if (num_trans <= PNG_MAX_PALETTE_LENGTH)
         png_memcpy(info_ptr->trans, trans, (png_size_t)num_trans);
926 927 928 929 930 931
#ifdef PNG_FREE_ME_SUPPORTED
       info_ptr->free_me |= PNG_FREE_TRNS;
#else
       png_ptr->flags |= PNG_FLAG_FREE_TRNS;
#endif
   }
A
Andreas Dilger 已提交
932 933 934 935

   if (trans_values != NULL)
   {
      png_memcpy(&(info_ptr->trans_values), trans_values,
936
         png_sizeof(png_color_16));
937 938
      if (num_trans == 0)
        num_trans = 1;
A
Andreas Dilger 已提交
939 940 941 942 943 944
   }
   info_ptr->num_trans = (png_uint_16)num_trans;
   info_ptr->valid |= PNG_INFO_tRNS;
}
#endif

945
#if defined(PNG_sPLT_SUPPORTED)
946
void PNGAPI
947
png_set_sPLT(png_structp png_ptr,
948
             png_infop info_ptr, png_sPLT_tp entries, int nentries)
949
{
950
    png_sPLT_tp np;
951 952
    int i;

953
    np = (png_sPLT_tp)png_malloc_warn(png_ptr,
954
        (info_ptr->splt_palettes_num + nentries) * png_sizeof(png_sPLT_t));
955 956
    if (np == NULL)
    {
957
      png_warning(png_ptr, "No memory for sPLT palettes.");
958 959
      return;
    }
960

961
    png_memcpy(np, info_ptr->splt_palettes,
962
           info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t));
963
    png_free(png_ptr, info_ptr->splt_palettes);
964
    info_ptr->splt_palettes=NULL;
965 966 967

    for (i = 0; i < nentries; i++)
    {
968 969
        png_sPLT_tp to = np + info_ptr->splt_palettes_num + i;
        png_sPLT_tp from = entries + i;
970 971

        to->name = (png_charp)png_malloc(png_ptr,
972
            png_strlen(from->name) + 1);
973
        /* TODO: use png_malloc_warn */
974
        png_strcpy(to->name, from->name);
975
        to->entries = (png_sPLT_entryp)png_malloc(png_ptr,
976 977
            from->nentries * png_sizeof(png_sPLT_t));
        /* TODO: use png_malloc_warn */
978
        png_memcpy(to->entries, from->entries,
979
            from->nentries * png_sizeof(png_sPLT_t));
980 981
        to->nentries = from->nentries;
        to->depth = from->depth;
982 983 984 985
    }

    info_ptr->splt_palettes = np;
    info_ptr->splt_palettes_num += nentries;
986
    info_ptr->valid |= PNG_INFO_sPLT;
987
#ifdef PNG_FREE_ME_SUPPORTED
988
    info_ptr->free_me |= PNG_FREE_SPLT;
989
#endif
990 991 992
}
#endif /* PNG_sPLT_SUPPORTED */

993
#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
994
void PNGAPI
995
png_set_unknown_chunks(png_structp png_ptr,
996
   png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns)
997 998 999 1000
{
    png_unknown_chunkp np;
    int i;

1001 1002 1003
    if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0)
        return;

1004
    np = (png_unknown_chunkp)png_malloc_warn(png_ptr,
1005
        (info_ptr->unknown_chunks_num + num_unknowns) *
1006
        png_sizeof(png_unknown_chunk));
1007 1008 1009 1010 1011
    if (np == NULL)
    {
       png_warning(png_ptr, "Out of memory while processing unknown chunk.");
       return;
    }
1012

1013
    png_memcpy(np, info_ptr->unknown_chunks,
1014
           info_ptr->unknown_chunks_num * png_sizeof(png_unknown_chunk));
1015
    png_free(png_ptr, info_ptr->unknown_chunks);
1016
    info_ptr->unknown_chunks=NULL;
1017

1018
    for (i = 0; i < num_unknowns; i++)
1019 1020 1021 1022
    {
        png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i;
        png_unknown_chunkp from = unknowns + i;

1023 1024
        png_strncpy((png_charp)to->name, (png_charp)from->name, 5);
        to->data = (png_bytep)png_malloc_warn(png_ptr, from->size);
1025
        if (to->data == NULL)
1026 1027 1028
        {
           png_warning(png_ptr, "Out of memory processing unknown chunk.");
        }
1029 1030
        else
        {
1031 1032
           png_memcpy(to->data, from->data, from->size);
           to->size = from->size;
1033

1034 1035
           /* note our location in the read or write sequence */
           to->location = (png_byte)(png_ptr->mode & 0xff);
1036
        }
1037 1038 1039
    }

    info_ptr->unknown_chunks = np;
1040
    info_ptr->unknown_chunks_num += num_unknowns;
1041
#ifdef PNG_FREE_ME_SUPPORTED
1042
    info_ptr->free_me |= PNG_FREE_UNKN;
1043
#endif
1044
}
1045
void PNGAPI
1046 1047 1048
png_set_unknown_chunk_location(png_structp png_ptr, png_infop info_ptr,
   int chunk, int location)
{
1049
   if(png_ptr != NULL && info_ptr != NULL && chunk >= 0 && chunk <
1050 1051 1052
         (int)info_ptr->unknown_chunks_num)
      info_ptr->unknown_chunks[chunk].location = (png_byte)location;
}
1053 1054
#endif

1055 1056
#if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \
    defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED)
1057
void PNGAPI
1058 1059
png_permit_empty_plte (png_structp png_ptr, int empty_plte_permitted)
{
1060 1061 1062
   /* This function is deprecated in favor of png_permit_mng_features()
      and will be removed from libpng-2.0.0 */
   png_debug(1, "in png_permit_empty_plte, DEPRECATED.\n");
1063 1064
   if (png_ptr == NULL)
      return;
1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080
   png_ptr->mng_features_permitted = (png_byte)
     ((png_ptr->mng_features_permitted & (~(PNG_FLAG_MNG_EMPTY_PLTE))) |
     ((empty_plte_permitted & PNG_FLAG_MNG_EMPTY_PLTE)));
}
#endif

#if defined(PNG_MNG_FEATURES_SUPPORTED)
png_uint_32 PNGAPI
png_permit_mng_features (png_structp png_ptr, png_uint_32 mng_features)
{
   png_debug(1, "in png_permit_mng_features\n");
   if (png_ptr == NULL)
      return (png_uint_32)0;
   png_ptr->mng_features_permitted =
     (png_byte)(mng_features & PNG_ALL_MNG_FEATURES);
   return (png_uint_32)png_ptr->mng_features_permitted;
1081 1082
}
#endif
1083

1084
#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
1085
void PNGAPI
1086 1087 1088 1089 1090 1091 1092
png_set_keep_unknown_chunks(png_structp png_ptr, int keep, png_bytep
   chunk_list, int num_chunks)
{
    png_bytep new_list, p;
    int i, old_num_chunks;
    if (num_chunks == 0)
    {
1093
      if(keep == PNG_HANDLE_CHUNK_ALWAYS || keep == PNG_HANDLE_CHUNK_IF_SAFE)
1094 1095 1096
        png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
      else
        png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
1097

1098
      if(keep == PNG_HANDLE_CHUNK_ALWAYS)
1099 1100 1101 1102 1103 1104 1105 1106
        png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS;
      else
        png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS;
      return;
    }
    if (chunk_list == NULL)
      return;
    old_num_chunks=png_ptr->num_chunk_list;
1107 1108
    new_list=(png_bytep)png_malloc(png_ptr,
       (png_uint_32)(5*(num_chunks+old_num_chunks)));
1109
    if(png_ptr->chunk_list != NULL)
1110
    {
1111 1112
       png_memcpy(new_list, png_ptr->chunk_list,
          (png_size_t)(5*old_num_chunks));
1113
       png_free(png_ptr, png_ptr->chunk_list);
1114
       png_ptr->chunk_list=NULL;
1115
    }
1116 1117
    png_memcpy(new_list+5*old_num_chunks, chunk_list,
       (png_size_t)(5*num_chunks));
1118 1119 1120 1121
    for (p=new_list+5*old_num_chunks+4, i=0; i<num_chunks; i++, p+=5)
       *p=(png_byte)keep;
    png_ptr->num_chunk_list=old_num_chunks+num_chunks;
    png_ptr->chunk_list=new_list;
1122
#ifdef PNG_FREE_ME_SUPPORTED
1123
    png_ptr->free_me |= PNG_FREE_LIST;
1124
#endif
1125 1126
}
#endif
1127

1128
#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
1129
void PNGAPI
1130 1131 1132 1133 1134 1135 1136 1137
png_set_read_user_chunk_fn(png_structp png_ptr, png_voidp user_chunk_ptr,
   png_user_chunk_ptr read_user_chunk_fn)
{
   png_debug(1, "in png_set_read_user_chunk_fn\n");
   png_ptr->read_user_chunk_fn = read_user_chunk_fn;
   png_ptr->user_chunk_ptr = user_chunk_ptr;
}
#endif
1138

1139
#if defined(PNG_INFO_IMAGE_SUPPORTED)
1140
void PNGAPI
1141 1142 1143
png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers)
{
   png_debug1(1, "in %s storage function\n", "rows");
1144

1145 1146 1147
   if (png_ptr == NULL || info_ptr == NULL)
      return;

1148
   if(info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers))
1149
      png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
1150 1151 1152
   info_ptr->row_pointers = row_pointers;
   if(row_pointers)
      info_ptr->valid |= PNG_INFO_IDAT;
1153 1154 1155
}
#endif

1156
#ifdef PNG_WRITE_SUPPORTED
1157
void PNGAPI
1158 1159 1160 1161 1162 1163 1164 1165 1166
png_set_compression_buffer_size(png_structp png_ptr, png_uint_32 size)
{
    if(png_ptr->zbuf)
       png_free(png_ptr, png_ptr->zbuf);
    png_ptr->zbuf_size = (png_size_t)size;
    png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, size);
    png_ptr->zstream.next_out = png_ptr->zbuf;
    png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
}
1167
#endif
1168 1169 1170 1171 1172 1173 1174

void PNGAPI
png_set_invalid(png_structp png_ptr, png_infop info_ptr, int mask)
{
   if (png_ptr && info_ptr)
      info_ptr->valid &= ~(mask);
}
1175

1176

1177
#ifndef PNG_1_0_X
1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215
#ifdef PNG_ASSEMBLER_CODE_SUPPORTED
/* this function was added to libpng 1.2.0 and should always exist by default */
void PNGAPI
png_set_asm_flags (png_structp png_ptr, png_uint_32 asm_flags)
{
    png_uint_32 settable_asm_flags;
    png_uint_32 settable_mmx_flags;

    settable_mmx_flags =
#ifdef PNG_HAVE_ASSEMBLER_COMBINE_ROW
                         PNG_ASM_FLAG_MMX_READ_COMBINE_ROW  |
#endif
#ifdef PNG_HAVE_ASSEMBLER_READ_INTERLACE
                         PNG_ASM_FLAG_MMX_READ_INTERLACE    |
#endif
#ifdef PNG_HAVE_ASSEMBLER_READ_FILTER_ROW
                         PNG_ASM_FLAG_MMX_READ_FILTER_SUB   |
                         PNG_ASM_FLAG_MMX_READ_FILTER_UP    |
                         PNG_ASM_FLAG_MMX_READ_FILTER_AVG   |
                         PNG_ASM_FLAG_MMX_READ_FILTER_PAETH |
#endif
                         0;

    /* could be some non-MMX ones in the future, but not currently: */
    settable_asm_flags = settable_mmx_flags;

    if (!(png_ptr->asm_flags & PNG_ASM_FLAG_MMX_SUPPORT_COMPILED) ||
        !(png_ptr->asm_flags & PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU))
    {
        /* clear all MMX flags if MMX isn't supported */
        settable_asm_flags &= ~settable_mmx_flags;
        png_ptr->asm_flags &= ~settable_mmx_flags;
    }

    /* we're replacing the settable bits with those passed in by the user,
     * so first zero them out of the master copy, then logical-OR in the
     * allowed subset that was requested */

1216 1217
    png_ptr->asm_flags &= ~settable_asm_flags;               /* zero them */
    png_ptr->asm_flags |= (asm_flags & settable_asm_flags);  /* set them */
1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231
}
#endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */

#ifdef PNG_ASSEMBLER_CODE_SUPPORTED
/* this function was added to libpng 1.2.0 */
void PNGAPI
png_set_mmx_thresholds (png_structp png_ptr,
                        png_byte mmx_bitdepth_threshold,
                        png_uint_32 mmx_rowbytes_threshold)
{
    png_ptr->mmx_bitdepth_threshold = mmx_bitdepth_threshold;
    png_ptr->mmx_rowbytes_threshold = mmx_rowbytes_threshold;
}
#endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */
1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247

#ifdef PNG_SET_USER_LIMITS_SUPPORTED
/* this function was added to libpng 1.2.6 */
void PNGAPI
png_set_user_limits (png_structp png_ptr, png_uint_32 user_width_max,
    png_uint_32 user_height_max)
{
    /* Images with dimensions larger than these limits will be
     * rejected by png_set_IHDR().  To accept any PNG datastream
     * regardless of dimensions, set both limits to 0x7ffffffL.
     */
    png_ptr->user_width_max = user_width_max;
    png_ptr->user_height_max = user_height_max;
}
#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */

1248
#endif /* ?PNG_1_0_X */
1249
#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */