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.35 [February 14, 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
     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 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 120 121 122
   /* Check for overflow */
   if (file_gamma > 21474.83)
   {
      png_warning(png_ptr, "Limiting gamma to 21474.83");
      gamma=21474.83;
   }
   else
123
      gamma = file_gamma;
124
   info_ptr->gamma = (float)gamma;
125
#ifdef PNG_FIXED_POINT_SUPPORTED
126
   info_ptr->int_gamma = (int)(gamma*100000.+.5);
127 128
#endif
   info_ptr->valid |= PNG_INFO_gAMA;
129
   if (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 138
   png_fixed_point gamma;

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
     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
       gamma = 0;
154 155
     }
     else
156
       gamma = int_gamma;
157
   }
158
#ifdef PNG_FLOATING_POINT_SUPPORTED
159
   info_ptr->gamma = (float)(gamma/100000.);
160
#endif
161
#ifdef PNG_FIXED_POINT_SUPPORTED
162
   info_ptr->int_gamma = gamma;
163
#endif
A
Andreas Dilger 已提交
164
   info_ptr->valid |= PNG_INFO_gAMA;
165
   if (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_uint_32)(PNG_MAX_PALETTE_LENGTH * png_sizeof(png_uint_16)));
194 195 196 197 198
   if (png_ptr->hist == NULL)
     {
       png_warning(png_ptr, "Insufficient memory for hIST chunk data.");
       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
   if ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&png_ptr->mng_features_permitted)
275
      png_warning(png_ptr, "MNG features are not allowed in a PNG datastream");
276
   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 = (png_size_t)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_uint_32 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
      return;
   }
359
   png_memcpy(info_ptr->pcal_purpose, purpose, (png_size_t)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
      return;
   }
376
   png_memcpy(info_ptr->pcal_units, units, (png_size_t)length);
A
Andreas Dilger 已提交
377

378
   info_ptr->pcal_params = (png_charpp)png_malloc_warn(png_ptr,
379
      (png_uint_32)((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 387 388
#ifdef PNG_FREE_ME_SUPPORTED
   info_ptr->free_me |= PNG_FREE_PCAL;
#endif
389

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

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

   info_ptr->valid |= PNG_INFO_pCAL;
}
#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 500 501 502 503 504 505 506 507 508 509
   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;
       }
     }

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

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

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

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

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

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

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

   png_set_sRGB(png_ptr, info_ptr, intent);

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

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

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

642 643

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

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

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

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

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

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

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

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

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

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

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

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

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

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

      png_memcpy(textp->key, text_ptr[i].key,
815
         (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 919
      if (num_trans == 0)
        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
    png_sPLT_tp np;
948 949
    int i;

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

953
    np = (png_sPLT_tp)png_malloc_warn(png_ptr,
954 955
        (info_ptr->splt_palettes_num + nentries) *
        (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
    png_memcpy(np, info_ptr->splt_palettes,
963
           info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t));
964

965
    png_free(png_ptr, info_ptr->splt_palettes);
966
    info_ptr->splt_palettes=NULL;
967 968 969

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

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

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

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

1016 1017 1018
    if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0)
        return;

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

1029
    png_memcpy(np, info_ptr->unknown_chunks,
1030
           info_ptr->unknown_chunks_num * png_sizeof(png_unknown_chunk));
1031
    png_free(png_ptr, info_ptr->unknown_chunks);
1032
    info_ptr->unknown_chunks=NULL;
1033

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

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

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

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

1111
#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
1112
void PNGAPI
1113 1114 1115 1116 1117
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;
1118 1119
    if (png_ptr == NULL)
       return;
1120 1121
    if (num_chunks == 0)
    {
1122
      if (keep == PNG_HANDLE_CHUNK_ALWAYS || keep == PNG_HANDLE_CHUNK_IF_SAFE)
1123 1124 1125
        png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
      else
        png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
1126

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

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

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

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

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

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

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

1210

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

/* 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)
{
1229
/* Obsolete as of libpng-1.2.20 and will be removed from libpng-1.4.0 */
1230 1231
    if (png_ptr == NULL)
       return;
1232 1233 1234
    /* Quiet the compiler */
    mmx_bitdepth_threshold = mmx_bitdepth_threshold;
    mmx_rowbytes_threshold = mmx_rowbytes_threshold;
1235
}
1236
#endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */
1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247

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

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