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

/* pngset.c - storage of image information into info struct
3
 *
4
 * Last changed in libpng 1.2.30 [July 6, 2008]
5
 * For conditions of distribution and use, see copyright notice in png.h
6
 * Copyright (c) 1998-2008 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

#define PNG_INTERNAL
#include "png.h"
18 19
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)

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

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

33 34
#if defined(PNG_cHRM_SUPPORTED)
#ifdef PNG_FLOATING_POINT_SUPPORTED
35
void PNGAPI
A
Andreas Dilger 已提交
36 37 38 39 40
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");
41
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
42
      return;
43 44 45 46 47 48 49
   if (!(white_x || white_y || red_x || red_y || green_x || green_y ||
       blue_x || blue_y))
   {
      png_warning(png_ptr,
        "Ignoring attempt to set all-zero chromaticity values");
      return;
   }
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
   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 已提交
69 70 71 72 73 74 75 76
   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;
77 78 79
#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);
80 81
   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);
82 83
   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);
84 85
   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);
86
#endif
A
Andreas Dilger 已提交
87 88 89
   info_ptr->valid |= PNG_INFO_cHRM;
}
#endif
90
#ifdef PNG_FIXED_POINT_SUPPORTED
91
void PNGAPI
92
png_set_cHRM_fixed(png_structp png_ptr, png_infop info_ptr,
93 94 95
   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)
96 97 98 99
{
   png_debug1(1, "in %s storage function\n", "cHRM");
   if (png_ptr == NULL || info_ptr == NULL)
      return;
A
Andreas Dilger 已提交
100

101 102 103 104 105 106 107
   if (!(white_x || white_y || red_x || red_y || green_x || green_y ||
       blue_x || blue_y))
   {
      png_warning(png_ptr,
        "Ignoring attempt to set all-zero chromaticity values");
      return;
   }
108 109 110 111 112 113 114 115 116
   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;
   }
117 118 119 120 121 122 123 124
   if (white_x > (png_fixed_point) PNG_UINT_31_MAX ||
       white_y > (png_fixed_point) PNG_UINT_31_MAX ||
         red_x > (png_fixed_point) PNG_UINT_31_MAX ||
         red_y > (png_fixed_point) PNG_UINT_31_MAX ||
       green_x > (png_fixed_point) PNG_UINT_31_MAX ||
       green_y > (png_fixed_point) PNG_UINT_31_MAX ||
        blue_x > (png_fixed_point) PNG_UINT_31_MAX ||
        blue_y > (png_fixed_point) PNG_UINT_31_MAX )
125 126 127 128 129
   {
      png_warning(png_ptr,
        "Ignoring attempt to set chromaticity value exceeding 21474.83");
      return;
   }
130 131 132 133 134 135 136 137
   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;
138 139 140
#ifdef PNG_FLOATING_POINT_SUPPORTED
   info_ptr->x_white = (float)(white_x/100000.);
   info_ptr->y_white = (float)(white_y/100000.);
141 142
   info_ptr->x_red   = (float)(  red_x/100000.);
   info_ptr->y_red   = (float)(  red_y/100000.);
143 144
   info_ptr->x_green = (float)(green_x/100000.);
   info_ptr->y_green = (float)(green_y/100000.);
145 146
   info_ptr->x_blue  = (float)( blue_x/100000.);
   info_ptr->y_blue  = (float)( blue_y/100000.);
147
#endif
148 149 150 151 152 153 154
   info_ptr->valid |= PNG_INFO_cHRM;
}
#endif
#endif

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

163 164 165 166 167 168 169 170 171
   /* 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;
172
#ifdef PNG_FIXED_POINT_SUPPORTED
173
   info_ptr->int_gamma = (int)(gamma*100000.+.5);
174 175
#endif
   info_ptr->valid |= PNG_INFO_gAMA;
176
   if(gamma == 0.0)
177
      png_warning(png_ptr, "Setting gamma=0");
178 179
}
#endif
180
void PNGAPI
181 182
png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point
   int_gamma)
183
{
184 185
   png_fixed_point gamma;

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

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

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

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

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

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

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

260
void PNGAPI
A
Andreas Dilger 已提交
261 262 263 264 265 266
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");
267
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
268 269
      return;

270 271 272
   /* check for width and height valid values */
   if (width == 0 || height == 0)
      png_error(png_ptr, "Image width or height is zero in IHDR");
273 274 275 276 277 278 279
#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
280
   if (width > PNG_UINT_31_MAX || height > PNG_UINT_31_MAX)
281
      png_error(png_ptr, "Invalid image size in IHDR");
282 283 284 285 286 287 288
   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");
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

   /* 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)
322
      png_warning(png_ptr, "MNG features are not allowed in a PNG datastream");
323 324 325 326 327
   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) &&
328
        (color_type == PNG_COLOR_TYPE_RGB ||
329 330 331 332 333 334 335 336 337 338
         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 已提交
339 340 341 342 343 344 345
   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;
346 347 348
   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 已提交
349 350 351 352 353 354
      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);
355

356
   /* check for potential overflow */
357
   if (width > (PNG_UINT_32_MAX
358 359 360 361 362
                 >> 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 */
363
      info_ptr->rowbytes = (png_size_t)0;
364
   else
365
      info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width);
A
Andreas Dilger 已提交
366 367
}

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

384
#if defined(PNG_pCAL_SUPPORTED)
385
void PNGAPI
A
Andreas Dilger 已提交
386 387 388 389
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)
{
390
   png_uint_32 length;
391
   int i;
A
Andreas Dilger 已提交
392 393

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

   length = png_strlen(purpose) + 1;
398
   png_debug1(3, "allocating purpose for info (%lu bytes)\n", length);
399 400 401 402 403 404
   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;
     }
405
   png_memcpy(info_ptr->pcal_purpose, purpose, (png_size_t)length);
A
Andreas Dilger 已提交
406 407 408 409 410 411 412 413

   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;
414
   png_debug1(3, "allocating units for info (%lu bytes)\n", length);
415 416 417 418 419 420
   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;
     }
421
   png_memcpy(info_ptr->pcal_units, units, (png_size_t)length);
A
Andreas Dilger 已提交
422

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

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

   for (i = 0; i < nparams; i++)
   {
      length = png_strlen(params[i]) + 1;
436
      png_debug2(3, "allocating parameter %d for info (%lu bytes)\n", i, length);
437 438 439 440 441 442
      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;
        }
443
      png_memcpy(info_ptr->pcal_params[i], params[i], (png_size_t)length);
A
Andreas Dilger 已提交
444 445 446
   }

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

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

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

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

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

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

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

   length = png_strlen(sheight) + 1;
   png_debug1(3, "allocating unit for info (%d bytes)\n", length);
496 497 498 499
   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);
500 501
      png_warning(png_ptr,
       "Memory allocation failed while processing sCAL.");
502
      return;
503
   }
504
   png_memcpy(info_ptr->scal_s_height, sheight, (png_size_t)length);
505
   info_ptr->valid |= PNG_INFO_sCAL;
506 507 508
#ifdef PNG_FREE_ME_SUPPORTED
   info_ptr->free_me |= PNG_FREE_SCAL;
#endif
509 510
}
#endif
511 512
#endif
#endif
513 514

#if defined(PNG_pHYs_SUPPORTED)
515
void PNGAPI
A
Andreas Dilger 已提交
516 517 518 519
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");
520
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
521 522 523 524 525 526 527 528 529
      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

530
void PNGAPI
A
Andreas Dilger 已提交
531 532 533
png_set_PLTE(png_structp png_ptr, png_infop info_ptr,
   png_colorp palette, int num_palette)
{
534

A
Andreas Dilger 已提交
535
   png_debug1(1, "in %s storage function\n", "PLTE");
536
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
537 538
      return;

539 540 541 542 543 544 545 546 547 548 549
   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;
       }
     }

550 551 552 553 554 555 556 557
   /*
    * 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
558

559 560
   /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead
      of num_palette entries,
561
      in case of an invalid PNG file that has too-large sample values. */
562
   png_ptr->palette = (png_colorp)png_malloc(png_ptr,
563 564 565
      PNG_MAX_PALETTE_LENGTH * png_sizeof(png_color));
   png_memset(png_ptr->palette, 0, PNG_MAX_PALETTE_LENGTH *
      png_sizeof(png_color));
566
   png_memcpy(png_ptr->palette, palette, num_palette * png_sizeof(png_color));
567 568 569 570 571 572 573 574
   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
575

576
   info_ptr->valid |= PNG_INFO_PLTE;
A
Andreas Dilger 已提交
577 578
}

579
#if defined(PNG_sBIT_SUPPORTED)
580
void PNGAPI
A
Andreas Dilger 已提交
581 582 583 584
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");
585
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
586 587
      return;

588
   png_memcpy(&(info_ptr->sig_bit), sig_bit, png_sizeof(png_color_8));
A
Andreas Dilger 已提交
589 590 591 592
   info_ptr->valid |= PNG_INFO_sBIT;
}
#endif

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

601
   info_ptr->srgb_intent = (png_byte)intent;
602 603
   info_ptr->valid |= PNG_INFO_sRGB;
}
604

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

   png_set_sRGB(png_ptr, info_ptr, intent);

632 633
#if defined(PNG_gAMA_SUPPORTED)
#ifdef PNG_FLOATING_POINT_SUPPORTED
634
   file_gamma = (float).45455;
635 636
   png_set_gAMA(png_ptr, info_ptr, file_gamma);
#endif
637 638 639 640 641
#ifdef PNG_FIXED_POINT_SUPPORTED
   int_file_gamma = 45455L;
   png_set_gAMA_fixed(png_ptr, info_ptr, int_file_gamma);
#endif
#endif
642

643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658
#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
659 660 661 662 663 664 665 666
   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;
667 668 669

   png_set_cHRM(png_ptr, info_ptr,
      white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
670
#endif
671 672 673 674
#endif
}
#endif

675 676

#if defined(PNG_iCCP_SUPPORTED)
677
void PNGAPI
678 679
png_set_iCCP(png_structp png_ptr, png_infop info_ptr,
             png_charp name, int compression_type,
680
             png_charp profile, png_uint_32 proflen)
681
{
682 683
   png_charp new_iccp_name;
   png_charp new_iccp_profile;
684
   png_uint_32 length;
685

686 687 688 689
   png_debug1(1, "in %s storage function\n", "iCCP");
   if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL)
      return;

690 691
   length = png_strlen(name)+1;
   new_iccp_name = (png_charp)png_malloc_warn(png_ptr, length);
692 693 694 695 696
   if (new_iccp_name == NULL)
   {
      png_warning(png_ptr, "Insufficient memory to process iCCP chunk.");
      return;
   }
697
   png_memcpy(new_iccp_name, name, length);
698 699 700 701 702 703 704
   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;
   }
705 706
   png_memcpy(new_iccp_profile, profile, (png_size_t)proflen);

707
   png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0);
708

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

#if defined(PNG_TEXT_SUPPORTED)
723
void PNGAPI
A
Andreas Dilger 已提交
724 725
png_set_text(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr,
   int num_text)
726 727 728 729 730 731 732 733 734 735
{
   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 已提交
736 737 738 739
{
   int i;

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

742
   if (png_ptr == NULL || info_ptr == NULL || num_text == 0)
743
      return(0);
A
Andreas Dilger 已提交
744 745 746 747 748 749 750 751 752 753 754 755 756 757

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

790
      if (text_ptr[i].key == NULL)
791 792
          continue;

793 794
      key_len = png_strlen(text_ptr[i].key);

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

820
      if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0')
A
Andreas Dilger 已提交
821
      {
822
         text_length = 0;
823
#ifdef PNG_iTXt_SUPPORTED
824 825 826
         if(text_ptr[i].compression > 0)
            textp->compression = PNG_ITXT_COMPRESSION_NONE;
         else
827
#endif
828
            textp->compression = PNG_TEXT_COMPRESSION_NONE;
A
Andreas Dilger 已提交
829 830 831
      }
      else
      {
832
         text_length = png_strlen(text_ptr[i].text);
A
Andreas Dilger 已提交
833 834
         textp->compression = text_ptr[i].compression;
      }
835

836
      textp->key = (png_charp)png_malloc_warn(png_ptr,
837
         (png_uint_32)(key_len + text_length + lang_len + lang_key_len + 4));
838 839
      if (textp->key == NULL)
        return(1);
840 841 842
      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);
843 844

      png_memcpy(textp->key, text_ptr[i].key,
845 846
         (png_size_t)(key_len));
      *(textp->key+key_len) = '\0';
847
#ifdef PNG_iTXt_SUPPORTED
848 849 850 851 852 853 854 855 856 857 858
      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
859
#endif
860
      {
861
#ifdef PNG_iTXt_SUPPORTED
862 863
         textp->lang=NULL;
         textp->lang_key=NULL;
864
#endif
865 866 867
         textp->text=textp->key + key_len + 1;
      }
      if(text_length)
868
         png_memcpy(textp->text, text_ptr[i].text,
869
            (png_size_t)(text_length));
870
      *(textp->text+text_length) = '\0';
871

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

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

902
   png_memcpy(&(info_ptr->mod_time), mod_time, png_sizeof(png_time));
A
Andreas Dilger 已提交
903 904 905 906
   info_ptr->valid |= PNG_INFO_tIME;
}
#endif

907
#if defined(PNG_tRNS_SUPPORTED)
908
void PNGAPI
A
Andreas Dilger 已提交
909 910 911 912
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");
913
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
914 915
      return;

916 917
   png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);

A
Andreas Dilger 已提交
918
   if (trans != NULL)
919 920
   {
       /*
921 922 923 924
        * 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.
        */
925

926
       /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */
927
       png_ptr->trans = info_ptr->trans = (png_bytep)png_malloc(png_ptr,
928
           (png_uint_32)PNG_MAX_PALETTE_LENGTH);
929
       if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH)
930
         png_memcpy(info_ptr->trans, trans, (png_size_t)num_trans);
931
   }
A
Andreas Dilger 已提交
932 933 934

   if (trans_values != NULL)
   {
935 936 937 938 939 940 941
      int sample_max = (1 << info_ptr->bit_depth);
      if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY &&
          (int)trans_values->gray > sample_max) ||
          (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
          ((int)trans_values->red > sample_max ||
          (int)trans_values->green > sample_max ||
          (int)trans_values->blue > sample_max)))
942 943
        png_warning(png_ptr,
           "tRNS chunk has out-of-range samples for bit_depth");
A
Andreas Dilger 已提交
944
      png_memcpy(&(info_ptr->trans_values), trans_values,
945
         png_sizeof(png_color_16));
946 947
      if (num_trans == 0)
        num_trans = 1;
A
Andreas Dilger 已提交
948
   }
949

A
Andreas Dilger 已提交
950
   info_ptr->num_trans = (png_uint_16)num_trans;
951 952 953 954 955 956 957 958 959
   if (num_trans != 0)
   {
      info_ptr->valid |= PNG_INFO_tRNS;
#ifdef PNG_FREE_ME_SUPPORTED
      info_ptr->free_me |= PNG_FREE_TRNS;
#else
      png_ptr->flags |= PNG_FLAG_FREE_TRNS;
#endif
   }
A
Andreas Dilger 已提交
960 961 962
}
#endif

963
#if defined(PNG_sPLT_SUPPORTED)
964
void PNGAPI
965
png_set_sPLT(png_structp png_ptr,
966
             png_infop info_ptr, png_sPLT_tp entries, int nentries)
967
{
968
    png_sPLT_tp np;
969 970
    int i;

971 972 973
    if (png_ptr == NULL || info_ptr == NULL)
       return;

974
    np = (png_sPLT_tp)png_malloc_warn(png_ptr,
975
        (info_ptr->splt_palettes_num + nentries) * png_sizeof(png_sPLT_t));
976 977
    if (np == NULL)
    {
978
      png_warning(png_ptr, "No memory for sPLT palettes.");
979 980
      return;
    }
981

982
    png_memcpy(np, info_ptr->splt_palettes,
983
           info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t));
984
    png_free(png_ptr, info_ptr->splt_palettes);
985
    info_ptr->splt_palettes=NULL;
986 987 988

    for (i = 0; i < nentries; i++)
    {
989 990
        png_sPLT_tp to = np + info_ptr->splt_palettes_num + i;
        png_sPLT_tp from = entries + i;
991
        png_uint_32 length;
992

993 994
        length = png_strlen(from->name) + 1;
        to->name = (png_charp)png_malloc_warn(png_ptr, length);
995 996 997 998
        if (to->name == NULL)
        {
           png_warning(png_ptr,
             "Out of memory while processing sPLT chunk");
999
           continue;
1000
        }
1001
        png_memcpy(to->name, from->name, length);
1002
        to->entries = (png_sPLT_entryp)png_malloc_warn(png_ptr,
1003
            from->nentries * png_sizeof(png_sPLT_entry));
1004 1005 1006 1007
        if (to->entries == NULL)
        {
           png_warning(png_ptr,
             "Out of memory while processing sPLT chunk");
1008
           png_free(png_ptr, to->name);
1009
           to->name = NULL;
1010
           continue;
1011
        }
1012 1013
        png_memcpy(to->entries, from->entries,
            from->nentries * png_sizeof(png_sPLT_entry));
1014 1015
        to->nentries = from->nentries;
        to->depth = from->depth;
1016 1017 1018 1019
    }

    info_ptr->splt_palettes = np;
    info_ptr->splt_palettes_num += nentries;
1020
    info_ptr->valid |= PNG_INFO_sPLT;
1021
#ifdef PNG_FREE_ME_SUPPORTED
1022
    info_ptr->free_me |= PNG_FREE_SPLT;
1023
#endif
1024 1025 1026
}
#endif /* PNG_sPLT_SUPPORTED */

1027
#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
1028
void PNGAPI
1029
png_set_unknown_chunks(png_structp png_ptr,
1030
   png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns)
1031 1032 1033 1034
{
    png_unknown_chunkp np;
    int i;

1035 1036 1037
    if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0)
        return;

1038
    np = (png_unknown_chunkp)png_malloc_warn(png_ptr,
1039
        (info_ptr->unknown_chunks_num + num_unknowns) *
1040
        png_sizeof(png_unknown_chunk));
1041 1042
    if (np == NULL)
    {
1043 1044
       png_warning(png_ptr,
          "Out of memory while processing unknown chunk.");
1045 1046
       return;
    }
1047

1048
    png_memcpy(np, info_ptr->unknown_chunks,
1049
           info_ptr->unknown_chunks_num * png_sizeof(png_unknown_chunk));
1050
    png_free(png_ptr, info_ptr->unknown_chunks);
1051
    info_ptr->unknown_chunks=NULL;
1052

1053
    for (i = 0; i < num_unknowns; i++)
1054
    {
1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073
       png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i;
       png_unknown_chunkp from = unknowns + i;

       png_memcpy((png_charp)to->name, 
                  (png_charp)from->name, 
                  png_sizeof(from->name));
       to->name[png_sizeof(to->name)-1] = '\0';
       to->size = from->size;
       /* note our location in the read or write sequence */
       to->location = (png_byte)(png_ptr->mode & 0xff);

       if (from->size == 0)
          to->data=NULL;
       else
       {
          to->data = (png_bytep)png_malloc_warn(png_ptr, from->size);
          if (to->data == NULL)
          {
             png_warning(png_ptr,
1074
              "Out of memory while processing unknown chunk.");
1075 1076 1077 1078 1079
             to->size=0;
          }
          else
             png_memcpy(to->data, from->data, from->size);
       }
1080 1081 1082
    }

    info_ptr->unknown_chunks = np;
1083
    info_ptr->unknown_chunks_num += num_unknowns;
1084
#ifdef PNG_FREE_ME_SUPPORTED
1085
    info_ptr->free_me |= PNG_FREE_UNKN;
1086
#endif
1087
}
1088
void PNGAPI
1089 1090 1091
png_set_unknown_chunk_location(png_structp png_ptr, png_infop info_ptr,
   int chunk, int location)
{
1092
   if(png_ptr != NULL && info_ptr != NULL && chunk >= 0 && chunk <
1093 1094 1095
         (int)info_ptr->unknown_chunks_num)
      info_ptr->unknown_chunks[chunk].location = (png_byte)location;
}
1096 1097
#endif

1098
#if defined(PNG_1_0_X) || defined(PNG_1_2_X)
1099 1100
#if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \
    defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED)
1101
void PNGAPI
1102 1103
png_permit_empty_plte (png_structp png_ptr, int empty_plte_permitted)
{
1104
   /* This function is deprecated in favor of png_permit_mng_features()
1105
      and will be removed from libpng-1.3.0 */
1106
   png_debug(1, "in png_permit_empty_plte, DEPRECATED.\n");
1107 1108
   if (png_ptr == NULL)
      return;
1109
   png_ptr->mng_features_permitted = (png_byte)
1110
     ((png_ptr->mng_features_permitted & (~PNG_FLAG_MNG_EMPTY_PLTE)) |
1111 1112 1113
     ((empty_plte_permitted & PNG_FLAG_MNG_EMPTY_PLTE)));
}
#endif
1114
#endif
1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125

#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;
1126 1127
}
#endif
1128

1129
#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
1130
void PNGAPI
1131 1132 1133 1134 1135
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;
1136 1137
    if (png_ptr == NULL)
       return;
1138 1139
    if (num_chunks == 0)
    {
1140
      if(keep == PNG_HANDLE_CHUNK_ALWAYS || keep == PNG_HANDLE_CHUNK_IF_SAFE)
1141 1142 1143
        png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
      else
        png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
1144

1145
      if(keep == PNG_HANDLE_CHUNK_ALWAYS)
1146 1147 1148 1149 1150 1151 1152 1153
        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;
1154 1155
    new_list=(png_bytep)png_malloc(png_ptr,
       (png_uint_32)(5*(num_chunks+old_num_chunks)));
1156
    if(png_ptr->chunk_list != NULL)
1157
    {
1158 1159
       png_memcpy(new_list, png_ptr->chunk_list,
          (png_size_t)(5*old_num_chunks));
1160
       png_free(png_ptr, png_ptr->chunk_list);
1161
       png_ptr->chunk_list=NULL;
1162
    }
1163 1164
    png_memcpy(new_list+5*old_num_chunks, chunk_list,
       (png_size_t)(5*num_chunks));
1165 1166 1167 1168
    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;
1169
#ifdef PNG_FREE_ME_SUPPORTED
1170
    png_ptr->free_me |= PNG_FREE_LIST;
1171
#endif
1172 1173
}
#endif
1174

1175
#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
1176
void PNGAPI
1177 1178 1179 1180
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");
1181 1182
   if (png_ptr == NULL)
      return;
1183 1184 1185 1186
   png_ptr->read_user_chunk_fn = read_user_chunk_fn;
   png_ptr->user_chunk_ptr = user_chunk_ptr;
}
#endif
1187

1188
#if defined(PNG_INFO_IMAGE_SUPPORTED)
1189
void PNGAPI
1190 1191 1192
png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers)
{
   png_debug1(1, "in %s storage function\n", "rows");
1193

1194 1195 1196
   if (png_ptr == NULL || info_ptr == NULL)
      return;

1197
   if(info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers))
1198
      png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
1199 1200 1201
   info_ptr->row_pointers = row_pointers;
   if(row_pointers)
      info_ptr->valid |= PNG_INFO_IDAT;
1202 1203 1204
}
#endif

1205
#ifdef PNG_WRITE_SUPPORTED
1206
void PNGAPI
1207 1208
png_set_compression_buffer_size(png_structp png_ptr, png_uint_32 size)
{
1209 1210
    if (png_ptr == NULL)
       return;
1211
    png_free(png_ptr, png_ptr->zbuf);
1212 1213 1214 1215 1216
    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;
}
1217
#endif
1218 1219 1220 1221 1222

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

1226

1227
#ifndef PNG_1_0_X
1228
#ifdef PNG_ASSEMBLER_CODE_SUPPORTED
1229
/* function was added to libpng 1.2.0 and should always exist by default */
1230 1231 1232
void PNGAPI
png_set_asm_flags (png_structp png_ptr, png_uint_32 asm_flags)
{
1233 1234 1235
/* Obsolete as of libpng-1.2.20 and will be removed from libpng-1.4.0 */
    if (png_ptr != NULL)
    png_ptr->asm_flags = 0;
1236
}
1237 1238 1239 1240 1241 1242 1243

/* 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)
{
1244
/* Obsolete as of libpng-1.2.20 and will be removed from libpng-1.4.0 */
1245 1246
    if (png_ptr == NULL)
       return;
1247
}
1248
#endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */
1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259

#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.
     */
1260
    if(png_ptr == NULL) return;
1261 1262 1263 1264 1265
    png_ptr->user_width_max = user_width_max;
    png_ptr->user_height_max = user_height_max;
}
#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */

1266
#endif /* ?PNG_1_0_X */
1267
#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */