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

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

#include "png.h"
17
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
18
#include "pngpriv.h"
19

20
#if defined(PNG_bKGD_SUPPORTED)
21
void PNGAPI
A
Andreas Dilger 已提交
22 23
png_set_bKGD(png_structp png_ptr, png_infop info_ptr, png_color_16p background)
{
24
   png_debug1(1, "in %s storage function", "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
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)
{
40
   png_debug1(1, "in %s storage function", "cHRM");
41
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
42
      return;
43

A
Andreas Dilger 已提交
44 45 46 47 48 49 50 51
   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;
52 53 54
#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);
55 56
   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);
57 58
   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);
59 60
   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);
61
#endif
A
Andreas Dilger 已提交
62 63
   info_ptr->valid |= PNG_INFO_cHRM;
}
64 65
#endif /* PNG_FLOATING_POINT_SUPPORTED */

66
#ifdef PNG_FIXED_POINT_SUPPORTED
67
void PNGAPI
68
png_set_cHRM_fixed(png_structp png_ptr, png_infop info_ptr,
69 70 71
   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)
72
{
73
   png_debug1(1, "in %s storage function", "cHRM fixed");
74 75
   if (png_ptr == NULL || info_ptr == NULL)
      return;
A
Andreas Dilger 已提交
76

77
#if !defined(PNG_NO_CHECK_cHRM)
78 79
   if (png_check_cHRM_fixed(png_ptr,
      white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y))
80
#endif
81
   {
82 83 84 85 86 87 88 89
     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;
90
#ifdef PNG_FLOATING_POINT_SUPPORTED
91 92 93 94 95 96 97 98 99 100 101
     info_ptr->x_white = (float)(white_x/100000.);
     info_ptr->y_white = (float)(white_y/100000.);
     info_ptr->x_red   = (float)(  red_x/100000.);
     info_ptr->y_red   = (float)(  red_y/100000.);
     info_ptr->x_green = (float)(green_x/100000.);
     info_ptr->y_green = (float)(green_y/100000.);
     info_ptr->x_blue  = (float)( blue_x/100000.);
     info_ptr->y_blue  = (float)( blue_y/100000.);
#endif
     info_ptr->valid |= PNG_INFO_cHRM;
   }
102
}
103 104
#endif /* PNG_FIXED_POINT_SUPPORTED */
#endif /* PNG_cHRM_SUPPORTED */
105 106 107

#if defined(PNG_gAMA_SUPPORTED)
#ifdef PNG_FLOATING_POINT_SUPPORTED
108
void PNGAPI
A
Andreas Dilger 已提交
109 110
png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma)
{
111
   double png_gamma;
112
   png_debug1(1, "in %s storage function", "gAMA");
113
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
114 115
      return;

116 117 118 119
   /* Check for overflow */
   if (file_gamma > 21474.83)
   {
      png_warning(png_ptr, "Limiting gamma to 21474.83");
120
      png_gamma=21474.83;
121 122
   }
   else
123 124
      png_gamma = file_gamma;
   info_ptr->gamma = (float)png_gamma;
125
#ifdef PNG_FIXED_POINT_SUPPORTED
126
   info_ptr->int_gamma = (int)(png_gamma*100000.+.5);
127 128
#endif
   info_ptr->valid |= PNG_INFO_gAMA;
129
   if (png_gamma == 0.0)
130
      png_warning(png_ptr, "Setting gamma=0");
131 132
}
#endif
133
void PNGAPI
134 135
png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point
   int_gamma)
136
{
137
   png_fixed_point png_gamma;
138

139
   png_debug1(1, "in %s storage function", "gAMA");
140 141 142
   if (png_ptr == NULL || info_ptr == NULL)
      return;

143
   if (int_gamma > (png_fixed_point) PNG_UINT_31_MAX)
144 145
   {
     png_warning(png_ptr, "Limiting gamma to 21474.83");
146
     png_gamma=PNG_UINT_31_MAX;
147 148 149 150 151 152
   }
   else
   {
     if (int_gamma < 0)
     {
       png_warning(png_ptr, "Setting negative gamma to zero");
153
       png_gamma = 0;
154 155
     }
     else
156
       png_gamma = int_gamma;
157
   }
158
#ifdef PNG_FLOATING_POINT_SUPPORTED
159
   info_ptr->gamma = (float)(png_gamma/100000.);
160
#endif
161
#ifdef PNG_FIXED_POINT_SUPPORTED
162
   info_ptr->int_gamma = png_gamma;
163
#endif
A
Andreas Dilger 已提交
164
   info_ptr->valid |= PNG_INFO_gAMA;
165
   if (png_gamma == 0)
166
      png_warning(png_ptr, "Setting gamma=0");
A
Andreas Dilger 已提交
167
}
168
#endif
A
Andreas Dilger 已提交
169

170
#if defined(PNG_hIST_SUPPORTED)
171
void PNGAPI
A
Andreas Dilger 已提交
172 173
png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p hist)
{
174
   int i;
175

176
   png_debug1(1, "in %s storage function", "hIST");
177
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
178
      return;
179
   if (info_ptr->num_palette == 0 || info_ptr->num_palette
180
       > PNG_MAX_PALETTE_LENGTH)
181
   {
182
       png_warning(png_ptr,
183
          "Invalid palette size, hIST allocation skipped");
184 185
       return;
   }
186 187 188 189

#ifdef PNG_FREE_ME_SUPPORTED
   png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0);
#endif
190 191
   /* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in version
      1.2.1 */
192
   png_ptr->hist = (png_uint_16p)png_malloc_warn(png_ptr,
193
      PNG_MAX_PALETTE_LENGTH * png_sizeof(png_uint_16));
194 195
   if (png_ptr->hist == NULL)
     {
196
       png_warning(png_ptr, "Insufficient memory for hIST chunk data");
197 198
       return;
     }
A
Andreas Dilger 已提交
199

200 201 202
   for (i = 0; i < info_ptr->num_palette; i++)
       png_ptr->hist[i] = hist[i];
   info_ptr->hist = png_ptr->hist;
A
Andreas Dilger 已提交
203
   info_ptr->valid |= PNG_INFO_hIST;
204 205 206 207 208 209

#ifdef PNG_FREE_ME_SUPPORTED
   info_ptr->free_me |= PNG_FREE_HIST;
#else
   png_ptr->flags |= PNG_FLAG_FREE_HIST;
#endif
A
Andreas Dilger 已提交
210 211 212
}
#endif

213
void PNGAPI
A
Andreas Dilger 已提交
214 215 216 217 218
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)
{
219
   png_debug1(1, "in %s storage function", "IHDR");
220
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
221 222
      return;

223 224 225
   /* check for width and height valid values */
   if (width == 0 || height == 0)
      png_error(png_ptr, "Image width or height is zero in IHDR");
226 227 228 229 230 231 232
#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
233
   if (width > PNG_UINT_31_MAX || height > PNG_UINT_31_MAX)
234
      png_error(png_ptr, "Invalid image size in IHDR");
235 236 237 238 239 240 241
   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");
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273

   /* 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
    */
274 275 276
   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");
   if (filter_type != PNG_FILTER_TYPE_BASE)
277
   {
278
     if (!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
279 280
        (filter_type == PNG_INTRAPIXEL_DIFFERENCING) &&
        ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&
281
        (color_type == PNG_COLOR_TYPE_RGB ||
282 283
         color_type == PNG_COLOR_TYPE_RGB_ALPHA)))
        png_error(png_ptr, "Unknown filter method in IHDR");
284
     if (png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)
285 286 287
        png_warning(png_ptr, "Invalid filter method in IHDR");
   }
#else
288
   if (filter_type != PNG_FILTER_TYPE_BASE)
289 290 291
      png_error(png_ptr, "Unknown filter method in IHDR");
#endif

A
Andreas Dilger 已提交
292 293 294 295 296 297 298
   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;
299 300 301
   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 已提交
302 303 304 305 306 307
      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);
308

309
   /* check for potential overflow */
310
   if (width > (PNG_UINT_32_MAX
311 312 313 314 315
                 >> 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 */
316
      info_ptr->rowbytes = 0;
317
   else
318
      info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width);
A
Andreas Dilger 已提交
319 320
}

321
#if defined(PNG_oFFs_SUPPORTED)
322
void PNGAPI
A
Andreas Dilger 已提交
323
png_set_oFFs(png_structp png_ptr, png_infop info_ptr,
324
   png_int_32 offset_x, png_int_32 offset_y, int unit_type)
A
Andreas Dilger 已提交
325
{
326
   png_debug1(1, "in %s storage function", "oFFs");
327
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
328 329 330 331 332 333 334 335 336
      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

337
#if defined(PNG_pCAL_SUPPORTED)
338
void PNGAPI
A
Andreas Dilger 已提交
339 340 341 342
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)
{
343
   png_size_t length;
344
   int i;
A
Andreas Dilger 已提交
345

346
   png_debug1(1, "in %s storage function", "pCAL");
347
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
348 349 350
      return;

   length = png_strlen(purpose) + 1;
351
   png_debug1(3, "allocating purpose for info (%lu bytes)",
352
     (unsigned long)length);
353 354
   info_ptr->pcal_purpose = (png_charp)png_malloc_warn(png_ptr, length);
   if (info_ptr->pcal_purpose == NULL)
355
   {
356
       png_warning(png_ptr, "Insufficient memory for pCAL purpose");
357 358 359
      return;
   }
   png_memcpy(info_ptr->pcal_purpose, purpose, length);
A
Andreas Dilger 已提交
360

361
   png_debug(3, "storing X0, X1, type, and nparams in info");
A
Andreas Dilger 已提交
362 363 364 365 366 367
   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;
368
   png_debug1(3, "allocating units for info (%lu bytes)",
369
     (unsigned long)length);
370 371
   info_ptr->pcal_units = (png_charp)png_malloc_warn(png_ptr, length);
   if (info_ptr->pcal_units == NULL)
372
   {
373
       png_warning(png_ptr, "Insufficient memory for pCAL units");
374 375 376
      return;
   }
   png_memcpy(info_ptr->pcal_units, units, length);
A
Andreas Dilger 已提交
377

378
   info_ptr->pcal_params = (png_charpp)png_malloc_warn(png_ptr,
379
      (png_size_t)((nparams + 1) * png_sizeof(png_charp)));
380
   if (info_ptr->pcal_params == NULL)
381
   {
382
       png_warning(png_ptr, "Insufficient memory for pCAL params");
383 384
      return;
   }
385

386
   png_memset(info_ptr->pcal_params, 0, (nparams + 1) * png_sizeof(png_charp));
A
Andreas Dilger 已提交
387 388 389 390

   for (i = 0; i < nparams; i++)
   {
      length = png_strlen(params[i]) + 1;
391
      png_debug2(3, "allocating parameter %d for info (%lu bytes)", i,
392
        (unsigned long)length);
393 394
      info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length);
      if (info_ptr->pcal_params[i] == NULL)
395
      {
396 397
          png_warning(png_ptr, "Insufficient memory for pCAL parameter");
          return;
398 399
      }
      png_memcpy(info_ptr->pcal_params[i], params[i], length);
A
Andreas Dilger 已提交
400 401 402
   }

   info_ptr->valid |= PNG_INFO_pCAL;
403 404 405
#ifdef PNG_FREE_ME_SUPPORTED
   info_ptr->free_me |= PNG_FREE_PCAL;
#endif
A
Andreas Dilger 已提交
406 407 408
}
#endif

409 410
#if defined(PNG_READ_sCAL_SUPPORTED) || defined(PNG_WRITE_sCAL_SUPPORTED)
#ifdef PNG_FLOATING_POINT_SUPPORTED
411
void PNGAPI
412
png_set_sCAL(png_structp png_ptr, png_infop info_ptr,
413
             int unit, double width, double height)
414
{
415
   png_debug1(1, "in %s storage function", "sCAL");
416 417 418
   if (png_ptr == NULL || info_ptr == NULL)
      return;

419
   info_ptr->scal_unit = (png_byte)unit;
420 421 422 423 424
   info_ptr->scal_pixel_width = width;
   info_ptr->scal_pixel_height = height;

   info_ptr->valid |= PNG_INFO_sCAL;
}
425 426
#else
#ifdef PNG_FIXED_POINT_SUPPORTED
427
void PNGAPI
428
png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr,
429
             int unit, png_charp swidth, png_charp sheight)
430
{
431
   png_size_t length;
432

433
   png_debug1(1, "in %s storage function", "sCAL");
434 435 436
   if (png_ptr == NULL || info_ptr == NULL)
      return;

437
   info_ptr->scal_unit = (png_byte)unit;
438 439

   length = png_strlen(swidth) + 1;
440
   png_debug1(3, "allocating unit for info (%u bytes)",
441
      (unsigned int)length);
442 443 444
   info_ptr->scal_s_width = (png_charp)png_malloc_warn(png_ptr, length);
   if (info_ptr->scal_s_width == NULL)
   {
445 446 447
      png_warning(png_ptr,
       "Memory allocation failed while processing sCAL");
      return;
448
   }
449
   png_memcpy(info_ptr->scal_s_width, swidth, length);
450 451

   length = png_strlen(sheight) + 1;
452
   png_debug1(3, "allocating unit for info (%u bytes)",
453
      (unsigned int)length);
454 455 456 457
   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);
458
      info_ptr->scal_s_width = NULL;
459 460 461
      png_warning(png_ptr,
       "Memory allocation failed while processing sCAL");
      return;
462
   }
463
   png_memcpy(info_ptr->scal_s_height, sheight, length);
464
   info_ptr->valid |= PNG_INFO_sCAL;
465 466 467
#ifdef PNG_FREE_ME_SUPPORTED
   info_ptr->free_me |= PNG_FREE_SCAL;
#endif
468 469
}
#endif
470 471
#endif
#endif
472 473

#if defined(PNG_pHYs_SUPPORTED)
474
void PNGAPI
A
Andreas Dilger 已提交
475 476 477
png_set_pHYs(png_structp png_ptr, png_infop info_ptr,
   png_uint_32 res_x, png_uint_32 res_y, int unit_type)
{
478
   png_debug1(1, "in %s storage function", "pHYs");
479
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
480 481 482 483 484 485 486 487 488
      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

489
void PNGAPI
A
Andreas Dilger 已提交
490 491 492
png_set_PLTE(png_structp png_ptr, png_infop info_ptr,
   png_colorp palette, int num_palette)
{
493

494
   png_debug1(1, "in %s storage function", "PLTE");
495
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
496 497
      return;

498 499 500 501 502 503 504 505 506 507 508
   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;
       }
     }

509 510 511 512 513 514 515 516
   /*
    * 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
517

518 519
   /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead
      of num_palette entries,
520
      in case of an invalid PNG file that has too-large sample values. */
521
#ifdef PNG_CALLOC_SUPPORTED
522
   png_ptr->palette = (png_colorp)png_calloc(png_ptr,
523
      PNG_MAX_PALETTE_LENGTH * png_sizeof(png_color));
524 525 526 527 528 529
#else
   png_ptr->palette = (png_colorp)png_malloc(png_ptr,
      PNG_MAX_PALETTE_LENGTH * png_sizeof(png_color));
   png_memset(png_ptr->palette, 0, PNG_MAX_PALETTE_LENGTH *
      png_sizeof(png_color));
#endif
530
   png_memcpy(png_ptr->palette, palette, num_palette * png_sizeof(png_color));
531 532 533 534 535 536 537 538
   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
539

540
   info_ptr->valid |= PNG_INFO_PLTE;
A
Andreas Dilger 已提交
541 542
}

543
#if defined(PNG_sBIT_SUPPORTED)
544
void PNGAPI
A
Andreas Dilger 已提交
545 546 547
png_set_sBIT(png_structp png_ptr, png_infop info_ptr,
   png_color_8p sig_bit)
{
548
   png_debug1(1, "in %s storage function", "sBIT");
549
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
550 551
      return;

552
   png_memcpy(&(info_ptr->sig_bit), sig_bit, png_sizeof(png_color_8));
A
Andreas Dilger 已提交
553 554 555 556
   info_ptr->valid |= PNG_INFO_sBIT;
}
#endif

557
#if defined(PNG_sRGB_SUPPORTED)
558
void PNGAPI
559
png_set_sRGB(png_structp png_ptr, png_infop info_ptr, int intent)
560
{
561
   png_debug1(1, "in %s storage function", "sRGB");
562
   if (png_ptr == NULL || info_ptr == NULL)
563 564
      return;

565
   info_ptr->srgb_intent = (png_byte)intent;
566 567
   info_ptr->valid |= PNG_INFO_sRGB;
}
568

569
void PNGAPI
570
png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr,
571
   int intent)
572
{
573 574
#if defined(PNG_gAMA_SUPPORTED)
#ifdef PNG_FLOATING_POINT_SUPPORTED
575 576
   float file_gamma;
#endif
577
#ifdef PNG_FIXED_POINT_SUPPORTED
578
   png_fixed_point int_file_gamma;
579 580 581 582
#endif
#endif
#if defined(PNG_cHRM_SUPPORTED)
#ifdef PNG_FLOATING_POINT_SUPPORTED
583
   float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
584
#endif
585
   png_fixed_point int_white_x, int_white_y, int_red_x, int_red_y, int_green_x,
586
      int_green_y, int_blue_x, int_blue_y;
587
#endif
588
   png_debug1(1, "in %s storage function", "sRGB_gAMA_and_cHRM");
589
   if (png_ptr == NULL || info_ptr == NULL)
590 591 592 593
      return;

   png_set_sRGB(png_ptr, info_ptr, intent);

594 595
#if defined(PNG_gAMA_SUPPORTED)
#ifdef PNG_FLOATING_POINT_SUPPORTED
596
   file_gamma = (float).45455;
597 598
   png_set_gAMA(png_ptr, info_ptr, file_gamma);
#endif
599 600 601 602 603
#ifdef PNG_FIXED_POINT_SUPPORTED
   int_file_gamma = 45455L;
   png_set_gAMA_fixed(png_ptr, info_ptr, int_file_gamma);
#endif
#endif
604

605 606 607 608 609 610 611 612 613 614 615
#if defined(PNG_cHRM_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;

#ifdef PNG_FLOATING_POINT_SUPPORTED
616 617 618 619 620 621 622 623
   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;
624
#endif
625

626
#if !defined(PNG_NO_CHECK_cHRM)
627 628 629
   if (png_check_cHRM_fixed(png_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))
630
#endif
631 632 633 634 635 636 637
   {
#ifdef PNG_FIXED_POINT_SUPPORTED
     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
638 639
      png_set_cHRM(png_ptr, info_ptr,
         white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
640
#endif
641 642
   }
#endif /* cHRM */
643
}
644
#endif /* sRGB */
645

646 647

#if defined(PNG_iCCP_SUPPORTED)
648
void PNGAPI
649 650
png_set_iCCP(png_structp png_ptr, png_infop info_ptr,
             png_charp name, int compression_type,
651
             png_charp profile, png_uint_32 proflen)
652
{
653 654
   png_charp new_iccp_name;
   png_charp new_iccp_profile;
655
   png_uint_32 length;
656

657
   png_debug1(1, "in %s storage function", "iCCP");
658 659 660
   if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL)
      return;

661 662
   length = png_strlen(name)+1;
   new_iccp_name = (png_charp)png_malloc_warn(png_ptr, length);
663 664
   if (new_iccp_name == NULL)
   {
665
      png_warning(png_ptr, "Insufficient memory to process iCCP chunk");
666 667
      return;
   }
668
   png_memcpy(new_iccp_name, name, length);
669 670 671 672
   new_iccp_profile = (png_charp)png_malloc_warn(png_ptr, proflen);
   if (new_iccp_profile == NULL)
   {
      png_free (png_ptr, new_iccp_name);
673 674
      png_warning(png_ptr,
      "Insufficient memory to process iCCP profile");
675 676
      return;
   }
677 678
   png_memcpy(new_iccp_profile, profile, (png_size_t)proflen);

679
   png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0);
680

681
   info_ptr->iccp_proflen = proflen;
682 683
   info_ptr->iccp_name = new_iccp_name;
   info_ptr->iccp_profile = new_iccp_profile;
684
   /* Compression is always zero but is here so the API and info structure
685
    * does not have to change if we introduce multiple compression types */
686
   info_ptr->iccp_compression = (png_byte)compression_type;
687
#ifdef PNG_FREE_ME_SUPPORTED
688
   info_ptr->free_me |= PNG_FREE_ICCP;
689
#endif
690 691 692 693 694
   info_ptr->valid |= PNG_INFO_iCCP;
}
#endif

#if defined(PNG_TEXT_SUPPORTED)
695
void PNGAPI
A
Andreas Dilger 已提交
696 697
png_set_text(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr,
   int num_text)
698 699
{
   int ret;
700
   ret = png_set_text_2(png_ptr, info_ptr, text_ptr, num_text);
701 702 703 704 705 706 707
   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 已提交
708 709 710
{
   int i;

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

714
   if (png_ptr == NULL || info_ptr == NULL || num_text == 0)
715
      return(0);
A
Andreas Dilger 已提交
716 717 718 719 720 721 722 723 724 725 726 727 728 729

   /* 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;
730
         info_ptr->text = (png_textp)png_malloc_warn(png_ptr,
731
            (png_size_t)(info_ptr->max_text * png_sizeof(png_text)));
732 733 734 735 736
         if (info_ptr->text == NULL)
           {
             png_free(png_ptr, old_text);
             return(1);
           }
737
         png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max *
738
            png_sizeof(png_text)));
A
Andreas Dilger 已提交
739 740 741 742 743 744
         png_free(png_ptr, old_text);
      }
      else
      {
         info_ptr->max_text = num_text + 8;
         info_ptr->num_text = 0;
745
         info_ptr->text = (png_textp)png_malloc_warn(png_ptr,
746
            (png_size_t)(info_ptr->max_text * png_sizeof(png_text)));
747 748
         if (info_ptr->text == NULL)
           return(1);
749 750 751
#ifdef PNG_FREE_ME_SUPPORTED
         info_ptr->free_me |= PNG_FREE_TEXT;
#endif
A
Andreas Dilger 已提交
752
      }
753
      png_debug1(3, "allocated %d entries for info_ptr->text",
A
Andreas Dilger 已提交
754 755 756 757
         info_ptr->max_text);
   }
   for (i = 0; i < num_text; i++)
   {
758 759
      png_size_t text_length, key_len;
      png_size_t lang_len, lang_key_len;
A
Andreas Dilger 已提交
760 761
      png_textp textp = &(info_ptr->text[info_ptr->num_text]);

762
      if (text_ptr[i].key == NULL)
763 764
          continue;

765 766
      key_len = png_strlen(text_ptr[i].key);

767
      if (text_ptr[i].compression <= 0)
768 769 770 771 772
      {
        lang_len = 0;
        lang_key_len = 0;
      }
      else
773
#ifdef PNG_iTXt_SUPPORTED
774 775
      {
        /* set iTXt data */
776
        if (text_ptr[i].lang != NULL)
777 778 779
          lang_len = png_strlen(text_ptr[i].lang);
        else
          lang_len = 0;
780
        if (text_ptr[i].lang_key != NULL)
781 782 783
          lang_key_len = png_strlen(text_ptr[i].lang_key);
        else
          lang_key_len = 0;
784
      }
785 786
#else
      {
787
        png_warning(png_ptr, "iTXt chunk not supported");
788 789 790
        continue;
      }
#endif
A
Andreas Dilger 已提交
791

792
      if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0')
A
Andreas Dilger 已提交
793
      {
794
         text_length = 0;
795
#ifdef PNG_iTXt_SUPPORTED
796
         if (text_ptr[i].compression > 0)
797 798
            textp->compression = PNG_ITXT_COMPRESSION_NONE;
         else
799
#endif
800
            textp->compression = PNG_TEXT_COMPRESSION_NONE;
A
Andreas Dilger 已提交
801 802 803
      }
      else
      {
804
         text_length = png_strlen(text_ptr[i].text);
A
Andreas Dilger 已提交
805 806
         textp->compression = text_ptr[i].compression;
      }
807

808
      textp->key = (png_charp)png_malloc_warn(png_ptr,
809 810
         (png_size_t)
         (key_len + text_length + lang_len + lang_key_len + 4));
811 812
      if (textp->key == NULL)
        return(1);
813
      png_debug2(2, "Allocated %lu bytes at %x in png_set_text",
814 815
         (unsigned long)(png_uint_32)
         (key_len + lang_len + lang_key_len + text_length + 4),
816
         (int)textp->key);
817 818

      png_memcpy(textp->key, text_ptr[i].key,
819
         (png_size_t)(key_len));
820
      *(textp->key + key_len) = '\0';
821
#ifdef PNG_iTXt_SUPPORTED
822 823
      if (text_ptr[i].compression > 0)
      {
824
         textp->lang = textp->key + key_len + 1;
825
         png_memcpy(textp->lang, text_ptr[i].lang, lang_len);
826
         *(textp->lang + lang_len) = '\0';
827
         textp->lang_key = textp->lang + lang_len + 1;
828
         png_memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len);
829
         *(textp->lang_key + lang_key_len) = '\0';
830
         textp->text = textp->lang_key + lang_key_len + 1;
831 832
      }
      else
833
#endif
834
      {
835
#ifdef PNG_iTXt_SUPPORTED
836 837
         textp->lang=NULL;
         textp->lang_key=NULL;
838
#endif
839
         textp->text = textp->key + key_len + 1;
840
      }
841
      if (text_length)
842
         png_memcpy(textp->text, text_ptr[i].text,
843
            (png_size_t)(text_length));
844
      *(textp->text + text_length) = '\0';
845

846
#ifdef PNG_iTXt_SUPPORTED
847
      if (textp->compression > 0)
848 849 850 851 852
      {
         textp->text_length = 0;
         textp->itxt_length = text_length;
      }
      else
853
#endif
854 855
      {
         textp->text_length = text_length;
856
#ifdef PNG_iTXt_SUPPORTED
857
         textp->itxt_length = 0;
858
#endif
859
      }
A
Andreas Dilger 已提交
860
      info_ptr->num_text++;
861
      png_debug1(3, "transferred text chunk %d", info_ptr->num_text);
A
Andreas Dilger 已提交
862
   }
863
   return(0);
A
Andreas Dilger 已提交
864 865 866
}
#endif

867
#if defined(PNG_tIME_SUPPORTED)
868
void PNGAPI
A
Andreas Dilger 已提交
869 870
png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_timep mod_time)
{
871
   png_debug1(1, "in %s storage function", "tIME");
872
   if (png_ptr == NULL || info_ptr == NULL ||
873
       (png_ptr->mode & PNG_WROTE_tIME))
A
Andreas Dilger 已提交
874 875
      return;

876
   png_memcpy(&(info_ptr->mod_time), mod_time, png_sizeof(png_time));
A
Andreas Dilger 已提交
877 878 879 880
   info_ptr->valid |= PNG_INFO_tIME;
}
#endif

881
#if defined(PNG_tRNS_SUPPORTED)
882
void PNGAPI
A
Andreas Dilger 已提交
883
png_set_tRNS(png_structp png_ptr, png_infop info_ptr,
884
   png_bytep trans, int num_trans, png_color_16p trans_color)
A
Andreas Dilger 已提交
885
{
886
   png_debug1(1, "in %s storage function", "tRNS");
887
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
888 889 890
      return;

   if (trans != NULL)
891 892
   {
       /*
893 894 895 896
        * 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.
        */
897

898 899 900
#ifdef PNG_FREE_ME_SUPPORTED
       png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
#endif
901

902
       /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */
903
       png_ptr->trans = info_ptr->trans = (png_bytep)png_malloc(png_ptr,
904 905
           (png_size_t)PNG_MAX_PALETTE_LENGTH);
       if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH)
906
         png_memcpy(info_ptr->trans, trans, (png_size_t)num_trans);
907
   }
A
Andreas Dilger 已提交
908

909
   if (trans_color != NULL)
A
Andreas Dilger 已提交
910
   {
911 912
      int sample_max = (1 << info_ptr->bit_depth);
      if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY &&
913
          (int)trans_color->gray > sample_max) ||
914
          (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
915 916 917
          ((int)trans_color->red > sample_max ||
          (int)trans_color->green > sample_max ||
          (int)trans_color->blue > sample_max)))
918 919
        png_warning(png_ptr,
           "tRNS chunk has out-of-range samples for bit_depth");
920
      png_memcpy(&(info_ptr->trans_color), trans_color,
921
         png_sizeof(png_color_16));
922 923
      if (num_trans == 0)
        num_trans = 1;
A
Andreas Dilger 已提交
924
   }
925

A
Andreas Dilger 已提交
926
   info_ptr->num_trans = (png_uint_16)num_trans;
927 928 929 930 931 932 933 934 935
   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 已提交
936 937 938
}
#endif

939
#if defined(PNG_sPLT_SUPPORTED)
940
void PNGAPI
941
png_set_sPLT(png_structp png_ptr,
942
             png_infop info_ptr, png_sPLT_tp entries, int nentries)
943 944 945 946 947 948 949
/*
 *  entries        - array of png_sPLT_t structures
 *                   to be added to the list of palettes
 *                   in the info structure.
 *  nentries       - number of palette structures to be
 *                   added.
 */
950
{
951
    png_sPLT_tp np;
952 953
    int i;

954 955 956
    if (png_ptr == NULL || info_ptr == NULL)
       return;

957
    np = (png_sPLT_tp)png_malloc_warn(png_ptr,
958 959
        (info_ptr->splt_palettes_num + nentries) *
        (png_size_t)png_sizeof(png_sPLT_t));
960 961
    if (np == NULL)
    {
962
      png_warning(png_ptr, "No memory for sPLT palettes");
963 964
      return;
    }
965

966
    png_memcpy(np, info_ptr->splt_palettes,
967
           info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t));
968
    png_free(png_ptr, info_ptr->splt_palettes);
969
    info_ptr->splt_palettes=NULL;
970 971 972

    for (i = 0; i < nentries; i++)
    {
973 974
        png_sPLT_tp to = np + info_ptr->splt_palettes_num + i;
        png_sPLT_tp from = entries + i;
975
        png_uint_32 length;
976

977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995
        length = png_strlen(from->name) + 1;
        to->name = (png_charp)png_malloc_warn(png_ptr, (png_size_t)length);
        if (to->name == NULL)
        {
           png_warning(png_ptr,
             "Out of memory while processing sPLT chunk");
           continue;
        }
        png_memcpy(to->name, from->name, length);
        to->entries = (png_sPLT_entryp)png_malloc_warn(png_ptr,
            (png_size_t)(from->nentries * png_sizeof(png_sPLT_entry)));
        if (to->entries == NULL)
        {
           png_warning(png_ptr,
             "Out of memory while processing sPLT chunk");
           png_free(png_ptr, to->name);
           to->name = NULL;
           continue;
        }
996
        png_memcpy(to->entries, from->entries,
997
            from->nentries * png_sizeof(png_sPLT_entry));
998 999
        to->nentries = from->nentries;
        to->depth = from->depth;
1000 1001 1002 1003
    }

    info_ptr->splt_palettes = np;
    info_ptr->splt_palettes_num += nentries;
1004
    info_ptr->valid |= PNG_INFO_sPLT;
1005
#ifdef PNG_FREE_ME_SUPPORTED
1006
    info_ptr->free_me |= PNG_FREE_SPLT;
1007
#endif
1008 1009 1010
}
#endif /* PNG_sPLT_SUPPORTED */

1011
#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
1012
void PNGAPI
1013
png_set_unknown_chunks(png_structp png_ptr,
1014
   png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns)
1015 1016 1017 1018
{
    png_unknown_chunkp np;
    int i;

1019 1020 1021
    if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0)
        return;

1022
    np = (png_unknown_chunkp)png_malloc_warn(png_ptr,
1023 1024
        (png_size_t)((info_ptr->unknown_chunks_num + num_unknowns) *
        png_sizeof(png_unknown_chunk)));
1025 1026
    if (np == NULL)
    {
1027 1028
       png_warning(png_ptr,
          "Out of memory while processing unknown chunk");
1029 1030
       return;
    }
1031

1032
    png_memcpy(np, info_ptr->unknown_chunks,
1033
           info_ptr->unknown_chunks_num * png_sizeof(png_unknown_chunk));
1034 1035
    png_free(png_ptr, info_ptr->unknown_chunks);

1036
    for (i = 0; i < num_unknowns; i++)
1037
    {
1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063
       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,
            (png_size_t)from->size);
          if (to->data == NULL)
          {
             png_warning(png_ptr,
              "Out of memory while processing unknown chunk");
             to->size = 0;
          }
          else
             png_memcpy(to->data, from->data, from->size);
       }
1064 1065 1066
    }

    info_ptr->unknown_chunks = np;
1067
    info_ptr->unknown_chunks_num += num_unknowns;
1068
#ifdef PNG_FREE_ME_SUPPORTED
1069
    info_ptr->free_me |= PNG_FREE_UNKN;
1070
#endif
1071
}
1072
void PNGAPI
1073 1074 1075
png_set_unknown_chunk_location(png_structp png_ptr, png_infop info_ptr,
   int chunk, int location)
{
1076
   if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 && chunk <
1077 1078 1079
         (int)info_ptr->unknown_chunks_num)
      info_ptr->unknown_chunks[chunk].location = (png_byte)location;
}
1080 1081
#endif

1082

1083 1084 1085 1086
#if defined(PNG_MNG_FEATURES_SUPPORTED)
png_uint_32 PNGAPI
png_permit_mng_features (png_structp png_ptr, png_uint_32 mng_features)
{
1087
   png_debug(1, "in png_permit_mng_features");
1088 1089 1090 1091 1092
   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;
1093 1094
}
#endif
1095

1096
#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
1097
void PNGAPI
1098 1099 1100 1101 1102
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;
1103 1104
    if (png_ptr == NULL)
       return;
1105 1106
    if (num_chunks == 0)
    {
1107
      if (keep == PNG_HANDLE_CHUNK_ALWAYS || keep == PNG_HANDLE_CHUNK_IF_SAFE)
1108 1109 1110
        png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
      else
        png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
1111

1112
      if (keep == PNG_HANDLE_CHUNK_ALWAYS)
1113 1114 1115 1116 1117 1118 1119
        png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS;
      else
        png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS;
      return;
    }
    if (chunk_list == NULL)
      return;
1120
    old_num_chunks = png_ptr->num_chunk_list;
1121
    new_list=(png_bytep)png_malloc(png_ptr,
1122 1123 1124
       (png_size_t)
       (5*(num_chunks + old_num_chunks)));
    if (png_ptr->chunk_list != NULL)
1125
    {
1126 1127
       png_memcpy(new_list, png_ptr->chunk_list,
          (png_size_t)(5*old_num_chunks));
1128
       png_free(png_ptr, png_ptr->chunk_list);
1129
       png_ptr->chunk_list=NULL;
1130
    }
1131
    png_memcpy(new_list + 5*old_num_chunks, chunk_list,
1132
       (png_size_t)(5*num_chunks));
1133
    for (p = new_list + 5*old_num_chunks + 4, i = 0; i<num_chunks; i++, p += 5)
1134
       *p=(png_byte)keep;
1135 1136
    png_ptr->num_chunk_list = old_num_chunks + num_chunks;
    png_ptr->chunk_list = new_list;
1137
#ifdef PNG_FREE_ME_SUPPORTED
1138
    png_ptr->free_me |= PNG_FREE_LIST;
1139
#endif
1140 1141
}
#endif
1142

1143
#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
1144
void PNGAPI
1145 1146 1147
png_set_read_user_chunk_fn(png_structp png_ptr, png_voidp user_chunk_ptr,
   png_user_chunk_ptr read_user_chunk_fn)
{
1148
   png_debug(1, "in png_set_read_user_chunk_fn");
1149 1150
   if (png_ptr == NULL)
      return;
1151 1152 1153 1154
   png_ptr->read_user_chunk_fn = read_user_chunk_fn;
   png_ptr->user_chunk_ptr = user_chunk_ptr;
}
#endif
1155

1156
#if defined(PNG_INFO_IMAGE_SUPPORTED)
1157
void PNGAPI
1158 1159
png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers)
{
1160
   png_debug1(1, "in %s storage function", "rows");
1161

1162 1163 1164
   if (png_ptr == NULL || info_ptr == NULL)
      return;

1165
   if (info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers))
1166
      png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
1167
   info_ptr->row_pointers = row_pointers;
1168
   if (row_pointers)
1169
      info_ptr->valid |= PNG_INFO_IDAT;
1170 1171 1172
}
#endif

1173
#ifdef PNG_WRITE_SUPPORTED
1174
void PNGAPI
1175 1176
png_set_compression_buffer_size(png_structp png_ptr,
    png_size_t size)
1177
{
1178 1179
    if (png_ptr == NULL)
       return;
1180
    png_free(png_ptr, png_ptr->zbuf);
1181
    png_ptr->zbuf_size = size;
1182 1183 1184 1185
    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;
}
1186
#endif
1187 1188 1189 1190 1191

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

1195

1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206

#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.
     */
1207
    if (png_ptr == NULL) return;
1208 1209 1210
    png_ptr->user_width_max = user_width_max;
    png_ptr->user_height_max = user_height_max;
}
1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222
/* this function was added to libpng 1.4.0 */
void PNGAPI
png_set_chunk_cache_max (png_structp png_ptr,
   png_uint_32 user_chunk_cache_max)
{
    if (png_ptr == NULL) return;
    png_ptr->user_chunk_cache_max = user_chunk_cache_max;
    if (user_chunk_cache_max == 0x7fffffffL)  /* Unlimited */
      png_ptr->user_chunk_cache_max = 0;
    else
      png_ptr->user_chunk_cache_max = user_chunk_cache_max + 1;
}
1223 1224
#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */

1225 1226 1227 1228 1229

#if defined(PNG_BENIGN_ERRORS_SUPPORTED)
void PNGAPI
png_set_benign_errors(png_structp png_ptr, int allowed)
{
1230
   png_debug(1, "in png_set_benign_errors");
1231 1232 1233 1234 1235 1236
   if (allowed)
     png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN;
   else
     png_ptr->flags &= ~PNG_FLAG_BENIGN_ERRORS_WARN;
}
#endif /* PNG_BENIGN_ERRORS_SUPPORTED */
1237
#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */