pngset.c 38.2 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.34 [December 18, 2008]
5
 * For conditions of distribution and use, see copyright notice in png.h
6
 * Copyright (c) 1998-2008 Glenn Randers-Pehrson
7 8
 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
9 10 11 12 13 14
 *
 * The functions here are used during reads to store data from the file
 * into the info struct, and during writes to store application data
 * into the info struct for writing into the file.  This abstracts the
 * info struct and allows us to change the structure in the future.
 */
A
Andreas Dilger 已提交
15 16 17

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

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

76 77 78 79
#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
80
   {
81 82 83 84 85 86 87 88
     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;
89
#ifdef PNG_FLOATING_POINT_SUPPORTED
90 91 92 93 94 95 96 97 98 99 100
     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;
   }
101
}
102 103
#endif /* PNG_FIXED_POINT_SUPPORTED */
#endif /* PNG_cHRM_SUPPORTED */
104 105 106

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

A
Andreas Dilger 已提交
385 386 387 388 389
   info_ptr->pcal_params[nparams] = NULL;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

   png_set_sRGB(png_ptr, info_ptr, intent);

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

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

620 621 622 623
#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))
624
#endif
625 626 627 628 629
   {
#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);
630
#endif
631 632 633 634 635 636
#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 */
637 638 639
}
#endif

640 641

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

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

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

673
   png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0);
674

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

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

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

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

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

756
      if (text_ptr[i].key == NULL)
757 758
          continue;

759 760
      key_len = png_strlen(text_ptr[i].key);

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

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

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

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

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

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

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

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

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

892 893 894 895
#ifdef PNG_FREE_ME_SUPPORTED
       png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
#endif

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

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

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

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

948 949 950
    if (png_ptr == NULL || info_ptr == NULL)
       return;

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

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

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

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

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

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

1013 1014 1015
    if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0)
        return;

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

1026
    png_memcpy(np, info_ptr->unknown_chunks,
1027
           info_ptr->unknown_chunks_num * png_sizeof(png_unknown_chunk));
1028
    png_free(png_ptr, info_ptr->unknown_chunks);
1029
    info_ptr->unknown_chunks=NULL;
1030

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

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

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

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

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

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

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

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

1174 1175 1176
   if (png_ptr == NULL || info_ptr == NULL)
      return;

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

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

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

1207

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

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

#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.
     */
1245
    if (png_ptr == NULL) return;
1246 1247 1248 1249 1250
    png_ptr->user_width_max = user_width_max;
    png_ptr->user_height_max = user_height_max;
}
#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */

1251
#endif /* ?PNG_1_0_X */
1252
#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */