pngset.c 38.3 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.37 [June 4, 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 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
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 78 79 80
#if !defined(PNG_NO_CHECK_cHRM)
   if (png_check_cHRM_fixed(png_ptr,
      white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y))
#endif
81
   {
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
      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;
#ifdef  PNG_FLOATING_POINT_SUPPORTED
      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.);
99
#endif
100
      info_ptr->valid |= PNG_INFO_cHRM;
101
   }
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 146
      png_warning(png_ptr, "Limiting gamma to 21474.83");
      png_gamma=PNG_UINT_31_MAX;
147 148 149
   }
   else
   {
150 151 152 153 154 155 156
      if (int_gamma < 0)
      {
         png_warning(png_ptr, "Setting negative gamma to zero");
         png_gamma = 0;
      }
      else
         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 183 184
      png_warning(png_ptr,
         "Invalid palette size, hIST allocation skipped.");
      return;
185
   }
186 187 188 189

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

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

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

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

224
   /* Check for width and height valid values */
225 226
   if (width == 0 || height == 0)
      png_error(png_ptr, "Image width or height is zero in IHDR");
227 228 229 230 231 232 233
#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
234
   if (width > PNG_UINT_31_MAX || height > PNG_UINT_31_MAX)
235
      png_error(png_ptr, "Invalid image size in IHDR");
236 237 238 239 240 241 242
   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");
243

244
   /* Check other values */
245 246 247 248 249
   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 ||
250
       color_type == 5 || color_type > 6)
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
      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
    */
275
   if ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&png_ptr->mng_features_permitted)
276
      png_warning(png_ptr, "MNG features are not allowed in a PNG datastream");
277
   if (filter_type != PNG_FILTER_TYPE_BASE)
278
   {
279
     if (!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
280 281 282
         (filter_type == PNG_INTRAPIXEL_DIFFERENCING) &&
         ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&
         (color_type == PNG_COLOR_TYPE_RGB ||
283 284
         color_type == PNG_COLOR_TYPE_RGB_ALPHA)))
        png_error(png_ptr, "Unknown filter method in IHDR");
285
     if (png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)
286 287 288
        png_warning(png_ptr, "Invalid filter method in IHDR");
   }
#else
289
   if (filter_type != PNG_FILTER_TYPE_BASE)
290 291 292
      png_error(png_ptr, "Unknown filter method in IHDR");
#endif

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

499
   if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH)
500 501
   {
      if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
502
         png_error(png_ptr, "Invalid palette length");
503 504
      else
      {
505 506
         png_warning(png_ptr, "Invalid palette length");
         return;
507 508
      }
   }
509

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

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

537
   info_ptr->valid |= PNG_INFO_PLTE;
A
Andreas Dilger 已提交
538 539
}

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

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

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

562
   info_ptr->srgb_intent = (png_byte)intent;
563 564
   info_ptr->valid |= PNG_INFO_sRGB;
}
565

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

   png_set_sRGB(png_ptr, info_ptr, intent);

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

602 603 604 605 606 607 608 609 610 611 612
#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
613 614 615 616 617 618 619 620
   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;
621
#endif
622

623 624
#if !defined(PNG_NO_CHECK_cHRM)
   if (png_check_cHRM_fixed(png_ptr,
625 626
       int_white_x, int_white_y, int_red_x, int_red_y, int_green_x,
       int_green_y, int_blue_x, int_blue_y))
627
#endif
628 629
   {
#ifdef PNG_FIXED_POINT_SUPPORTED
630 631 632
      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);
633
#endif
634 635
#ifdef PNG_FLOATING_POINT_SUPPORTED
      png_set_cHRM(png_ptr, info_ptr,
636
          white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
637 638 639
#endif
   }
#endif /* cHRM */
640
}
641
#endif /* sRGB */
642

643 644

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

654
   png_debug1(1, "in %s storage function", "iCCP");
655 656 657
   if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL)
      return;

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

676
   png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0);
677

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

#if defined(PNG_TEXT_SUPPORTED)
692
void PNGAPI
A
Andreas Dilger 已提交
693
png_set_text(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr,
694
             int num_text)
695 696
{
   int ret;
697
   ret = png_set_text_2(png_ptr, info_ptr, text_ptr, num_text);
698
   if (ret)
699
      png_error(png_ptr, "Insufficient memory to store text");
700 701 702 703
}

int /* PRIVATE */
png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr,
704
               int num_text)
A
Andreas Dilger 已提交
705 706 707
{
   int i;

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

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

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

759
      if (text_ptr[i].key == NULL)
760 761
          continue;

762 763
      key_len = png_strlen(text_ptr[i].key);

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

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

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

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

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

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

872
   png_memcpy(&(info_ptr->mod_time), mod_time, png_sizeof(png_time));
A
Andreas Dilger 已提交
873 874 875 876
   info_ptr->valid |= PNG_INFO_tIME;
}
#endif

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

   if (trans != NULL)
887 888
   {
       /*
889 890 891 892
        * 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.
        */
893

894 895 896 897
#ifdef PNG_FREE_ME_SUPPORTED
       png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
#endif

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

   if (trans_values != NULL)
   {
907 908 909 910 911 912 913
      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)))
914 915
         png_warning(png_ptr,
            "tRNS chunk has out-of-range samples for bit_depth");
A
Andreas Dilger 已提交
916
      png_memcpy(&(info_ptr->trans_values), trans_values,
917
         png_sizeof(png_color_16));
918
      if (num_trans == 0)
919
         num_trans = 1;
A
Andreas Dilger 已提交
920
   }
921

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

935
#if defined(PNG_sPLT_SUPPORTED)
936
void PNGAPI
937
png_set_sPLT(png_structp png_ptr,
938
             png_infop info_ptr, png_sPLT_tp entries, int nentries)
939 940 941 942 943 944 945
/*
 *  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.
 */
946
{
947 948
   png_sPLT_tp np;
   int i;
949

950 951
   if (png_ptr == NULL || info_ptr == NULL)
      return;
952

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

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

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

973
      length = png_strlen(from->name) + 1;
974
        to->name = (png_charp)png_malloc_warn(png_ptr, length);
975 976 977 978 979 980 981 982
      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,
983
            (png_uint_32)(from->nentries * png_sizeof(png_sPLT_entry)));
984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000
      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;
      }
      png_memcpy(to->entries, from->entries,
          from->nentries * png_sizeof(png_sPLT_entry));
      to->nentries = from->nentries;
      to->depth = from->depth;
   }

   info_ptr->splt_palettes = np;
   info_ptr->splt_palettes_num += nentries;
   info_ptr->valid |= PNG_INFO_sPLT;
1001
#ifdef PNG_FREE_ME_SUPPORTED
1002
   info_ptr->free_me |= PNG_FREE_SPLT;
1003
#endif
1004 1005 1006
}
#endif /* PNG_sPLT_SUPPORTED */

1007
#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
1008
void PNGAPI
1009
png_set_unknown_chunks(png_structp png_ptr,
1010
   png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns)
1011
{
1012 1013 1014 1015
   png_unknown_chunkp np;
   int i;

   if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0)
1016
       return;
1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 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 1064

   np = (png_unknown_chunkp)png_malloc_warn(png_ptr,
       (png_uint_32)((info_ptr->unknown_chunks_num + num_unknowns) *
       png_sizeof(png_unknown_chunk)));
   if (np == NULL)
   {
      png_warning(png_ptr,
         "Out of memory while processing unknown chunk.");
      return;
   }

   png_memcpy(np, info_ptr->unknown_chunks,
          info_ptr->unknown_chunks_num * png_sizeof(png_unknown_chunk));
   png_free(png_ptr, info_ptr->unknown_chunks);
   info_ptr->unknown_chunks=NULL;

   for (i = 0; i < num_unknowns; i++)
   {
      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_uint_32)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);
      }
   }

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

1079
#if defined(PNG_1_0_X) || defined(PNG_1_2_X)
1080 1081
#if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \
    defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED)
1082
void PNGAPI
1083 1084
png_permit_empty_plte (png_structp png_ptr, int empty_plte_permitted)
{
1085
   /* This function is deprecated in favor of png_permit_mng_features()
1086
      and will be removed from libpng-1.3.0 */
1087
   png_debug(1, "in png_permit_empty_plte, DEPRECATED.");
1088 1089
   if (png_ptr == NULL)
      return;
1090
   png_ptr->mng_features_permitted = (png_byte)
1091
     ((png_ptr->mng_features_permitted & (~PNG_FLAG_MNG_EMPTY_PLTE)) |
1092 1093 1094
     ((empty_plte_permitted & PNG_FLAG_MNG_EMPTY_PLTE)));
}
#endif
1095
#endif
1096 1097 1098 1099 1100

#if defined(PNG_MNG_FEATURES_SUPPORTED)
png_uint_32 PNGAPI
png_permit_mng_features (png_structp png_ptr, png_uint_32 mng_features)
{
1101
   png_debug(1, "in png_permit_mng_features");
1102 1103 1104 1105 1106
   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;
1107 1108
}
#endif
1109

1110
#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
1111
void PNGAPI
1112 1113 1114
png_set_keep_unknown_chunks(png_structp png_ptr, int keep, png_bytep
   chunk_list, int num_chunks)
{
1115 1116 1117 1118 1119 1120
   png_bytep new_list, p;
   int i, old_num_chunks;
   if (png_ptr == NULL)
      return;
   if (num_chunks == 0)
   {
1121
      if (keep == PNG_HANDLE_CHUNK_ALWAYS || keep == PNG_HANDLE_CHUNK_IF_SAFE)
1122
         png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
1123
      else
1124
         png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
1125

1126
      if (keep == PNG_HANDLE_CHUNK_ALWAYS)
1127
         png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS;
1128
      else
1129
         png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS;
1130
      return;
1131 1132
   }
   if (chunk_list == NULL)
1133
      return;
1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150
   old_num_chunks = png_ptr->num_chunk_list;
   new_list=(png_bytep)png_malloc(png_ptr,
      (png_uint_32)
      (5*(num_chunks + old_num_chunks)));
   if (png_ptr->chunk_list != NULL)
   {
      png_memcpy(new_list, png_ptr->chunk_list,
         (png_size_t)(5*old_num_chunks));
      png_free(png_ptr, png_ptr->chunk_list);
      png_ptr->chunk_list=NULL;
   }
   png_memcpy(new_list + 5*old_num_chunks, chunk_list,
      (png_size_t)(5*num_chunks));
   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;
1151
#ifdef PNG_FREE_ME_SUPPORTED
1152
   png_ptr->free_me |= PNG_FREE_LIST;
1153
#endif
1154 1155
}
#endif
1156

1157
#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
1158
void PNGAPI
1159 1160 1161
png_set_read_user_chunk_fn(png_structp png_ptr, png_voidp user_chunk_ptr,
   png_user_chunk_ptr read_user_chunk_fn)
{
1162
   png_debug(1, "in png_set_read_user_chunk_fn");
1163 1164
   if (png_ptr == NULL)
      return;
1165 1166 1167 1168
   png_ptr->read_user_chunk_fn = read_user_chunk_fn;
   png_ptr->user_chunk_ptr = user_chunk_ptr;
}
#endif
1169

1170
#if defined(PNG_INFO_IMAGE_SUPPORTED)
1171
void PNGAPI
1172 1173
png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers)
{
1174
   png_debug1(1, "in %s storage function", "rows");
1175

1176 1177 1178
   if (png_ptr == NULL || info_ptr == NULL)
      return;

1179
   if (info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers))
1180
      png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
1181
   info_ptr->row_pointers = row_pointers;
1182
   if (row_pointers)
1183
      info_ptr->valid |= PNG_INFO_IDAT;
1184 1185 1186
}
#endif

1187
#ifdef PNG_WRITE_SUPPORTED
1188
void PNGAPI
1189 1190
png_set_compression_buffer_size(png_structp png_ptr,
    png_uint_32 size)
1191
{
1192 1193
    if (png_ptr == NULL)
       return;
1194
    png_free(png_ptr, png_ptr->zbuf);
1195 1196 1197 1198 1199
    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;
}
1200
#endif
1201 1202 1203 1204 1205

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

1209

1210
#ifndef PNG_1_0_X
1211
#ifdef PNG_ASSEMBLER_CODE_SUPPORTED
1212
/* Function was added to libpng 1.2.0 and should always exist by default */
1213 1214 1215
void PNGAPI
png_set_asm_flags (png_structp png_ptr, png_uint_32 asm_flags)
{
1216 1217 1218
/* 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;
1219
    asm_flags = asm_flags; /* Quiet the compiler */
1220
}
1221

1222
/* This function was added to libpng 1.2.0 */
1223 1224 1225 1226 1227
void PNGAPI
png_set_mmx_thresholds (png_structp png_ptr,
                        png_byte mmx_bitdepth_threshold,
                        png_uint_32 mmx_rowbytes_threshold)
{
1228
/* Obsolete as of libpng-1.2.20 and will be removed from libpng-1.4.0 */
1229 1230
    if (png_ptr == NULL)
       return;
1231 1232 1233
    /* Quiet the compiler */
    mmx_bitdepth_threshold = mmx_bitdepth_threshold;
    mmx_rowbytes_threshold = mmx_rowbytes_threshold;
1234
}
1235
#endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */
1236 1237

#ifdef PNG_SET_USER_LIMITS_SUPPORTED
1238
/* This function was added to libpng 1.2.6 */
1239 1240 1241 1242
void PNGAPI
png_set_user_limits (png_structp png_ptr, png_uint_32 user_width_max,
    png_uint_32 user_height_max)
{
1243 1244 1245 1246 1247 1248 1249 1250
   /* 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.
    */
   if (png_ptr == NULL)
      return;
   png_ptr->user_width_max = user_width_max;
   png_ptr->user_height_max = user_height_max;
1251 1252 1253
}
#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */

1254
#endif /* ?PNG_1_0_X */
1255
#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */