pngset.c 38.4 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.25 [February 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 18

#define PNG_INTERNAL
#include "png.h"

19 20
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)

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

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

34 35
#if defined(PNG_cHRM_SUPPORTED)
#ifdef PNG_FLOATING_POINT_SUPPORTED
36
void PNGAPI
A
Andreas Dilger 已提交
37 38 39 40 41
png_set_cHRM(png_structp png_ptr, png_infop info_ptr,
   double white_x, double white_y, double red_x, double red_y,
   double green_x, double green_y, double blue_x, double blue_y)
{
   png_debug1(1, "in %s storage function\n", "cHRM");
42
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
43
      return;
44 45 46 47 48 49 50
   if (!(white_x || white_y || red_x || red_y || green_x || green_y ||
       blue_x || blue_y))
   {
      png_warning(png_ptr,
        "Ignoring attempt to set all-zero chromaticity values");
      return;
   }
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
   if (white_x < 0.0 || white_y < 0.0 ||
         red_x < 0.0 ||   red_y < 0.0 ||
       green_x < 0.0 || green_y < 0.0 ||
        blue_x < 0.0 ||  blue_y < 0.0)
   {
      png_warning(png_ptr,
        "Ignoring attempt to set negative chromaticity value");
      return;
   }
   if (white_x > 21474.83 || white_y > 21474.83 ||
         red_x > 21474.83 ||   red_y > 21474.83 ||
       green_x > 21474.83 || green_y > 21474.83 ||
        blue_x > 21474.83 ||  blue_y > 21474.83)
   {
      png_warning(png_ptr,
        "Ignoring attempt to set chromaticity value exceeding 21474.83");
      return;
   }

A
Andreas Dilger 已提交
70 71 72 73 74 75 76 77
   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;
78 79 80
#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);
81 82
   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);
83 84
   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);
85 86
   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);
87
#endif
A
Andreas Dilger 已提交
88 89 90
   info_ptr->valid |= PNG_INFO_cHRM;
}
#endif
91
#ifdef PNG_FIXED_POINT_SUPPORTED
92
void PNGAPI
93
png_set_cHRM_fixed(png_structp png_ptr, png_infop info_ptr,
94 95 96
   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)
97 98 99 100
{
   png_debug1(1, "in %s storage function\n", "cHRM");
   if (png_ptr == NULL || info_ptr == NULL)
      return;
A
Andreas Dilger 已提交
101

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

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

164 165 166 167 168 169 170 171 172
   /* Check for overflow */
   if (file_gamma > 21474.83)
   {
      png_warning(png_ptr, "Limiting gamma to 21474.83");
      gamma=21474.83;
   }
   else
      gamma=file_gamma;
   info_ptr->gamma = (float)gamma;
173
#ifdef PNG_FIXED_POINT_SUPPORTED
174
   info_ptr->int_gamma = (int)(gamma*100000.+.5);
175 176
#endif
   info_ptr->valid |= PNG_INFO_gAMA;
177
   if(gamma == 0.0)
178
      png_warning(png_ptr, "Setting gamma=0");
179 180
}
#endif
181
void PNGAPI
182 183
png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point
   int_gamma)
184
{
185 186
   png_fixed_point gamma;

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

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

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

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

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

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

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

261
void PNGAPI
A
Andreas Dilger 已提交
262 263 264 265 266 267
png_set_IHDR(png_structp png_ptr, png_infop info_ptr,
   png_uint_32 width, png_uint_32 height, int bit_depth,
   int color_type, int interlace_type, int compression_type,
   int filter_type)
{
   png_debug1(1, "in %s storage function\n", "IHDR");
268
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
269 270
      return;

271 272 273
   /* check for width and height valid values */
   if (width == 0 || height == 0)
      png_error(png_ptr, "Image width or height is zero in IHDR");
274 275 276 277 278 279 280
#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
281
   if (width > PNG_UINT_31_MAX || height > PNG_UINT_31_MAX)
282
      png_error(png_ptr, "Invalid image size in IHDR");
283 284 285 286 287 288 289
   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");
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322

   /* check other values */
   if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 &&
      bit_depth != 8 && bit_depth != 16)
      png_error(png_ptr, "Invalid bit depth in IHDR");

   if (color_type < 0 || color_type == 1 ||
      color_type == 5 || color_type > 6)
      png_error(png_ptr, "Invalid color type in IHDR");

   if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) ||
       ((color_type == PNG_COLOR_TYPE_RGB ||
         color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
         color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8))
      png_error(png_ptr, "Invalid color type/bit depth combination in IHDR");

   if (interlace_type >= PNG_INTERLACE_LAST)
      png_error(png_ptr, "Unknown interlace method in IHDR");

   if (compression_type != PNG_COMPRESSION_TYPE_BASE)
      png_error(png_ptr, "Unknown compression method in IHDR");

#if defined(PNG_MNG_FEATURES_SUPPORTED)
   /* Accept filter_method 64 (intrapixel differencing) only if
    * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
    * 2. Libpng did not read a PNG signature (this filter_method is only
    *    used in PNG datastreams that are embedded in MNG datastreams) and
    * 3. The application called png_permit_mng_features with a mask that
    *    included PNG_FLAG_MNG_FILTER_64 and
    * 4. The filter_method is 64 and
    * 5. The color_type is RGB or RGBA
    */
   if((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&png_ptr->mng_features_permitted)
323
      png_warning(png_ptr,"MNG features are not allowed in a PNG datastream");
324 325 326 327 328
   if(filter_type != PNG_FILTER_TYPE_BASE)
   {
     if(!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
        (filter_type == PNG_INTRAPIXEL_DIFFERENCING) &&
        ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&
329
        (color_type == PNG_COLOR_TYPE_RGB ||
330 331 332 333 334 335 336 337 338 339
         color_type == PNG_COLOR_TYPE_RGB_ALPHA)))
        png_error(png_ptr, "Unknown filter method in IHDR");
     if(png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)
        png_warning(png_ptr, "Invalid filter method in IHDR");
   }
#else
   if(filter_type != PNG_FILTER_TYPE_BASE)
      png_error(png_ptr, "Unknown filter method in IHDR");
#endif

A
Andreas Dilger 已提交
340 341 342 343 344 345 346
   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;
347 348 349
   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 已提交
350 351 352 353 354 355
      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);
356

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

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

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

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

   length = png_strlen(purpose) + 1;
399
   png_debug1(3, "allocating purpose for info (%lu bytes)\n", length);
400 401 402 403 404 405
   info_ptr->pcal_purpose = (png_charp)png_malloc_warn(png_ptr, length);
   if (info_ptr->pcal_purpose == NULL)
     {
       png_warning(png_ptr, "Insufficient memory for pCAL purpose.");
       return;
     }
406
   png_memcpy(info_ptr->pcal_purpose, purpose, (png_size_t)length);
A
Andreas Dilger 已提交
407 408 409 410 411 412 413 414

   png_debug(3, "storing X0, X1, type, and nparams in info\n");
   info_ptr->pcal_X0 = X0;
   info_ptr->pcal_X1 = X1;
   info_ptr->pcal_type = (png_byte)type;
   info_ptr->pcal_nparams = (png_byte)nparams;

   length = png_strlen(units) + 1;
415
   png_debug1(3, "allocating units for info (%lu bytes)\n", length);
416 417 418 419 420 421
   info_ptr->pcal_units = (png_charp)png_malloc_warn(png_ptr, length);
   if (info_ptr->pcal_units == NULL)
     {
       png_warning(png_ptr, "Insufficient memory for pCAL units.");
       return;
     }
422
   png_memcpy(info_ptr->pcal_units, units, (png_size_t)length);
A
Andreas Dilger 已提交
423

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

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

   for (i = 0; i < nparams; i++)
   {
      length = png_strlen(params[i]) + 1;
437
      png_debug2(3, "allocating parameter %d for info (%lu bytes)\n", i, length);
438 439 440 441 442 443
      info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length);
      if (info_ptr->pcal_params[i] == NULL)
        {
          png_warning(png_ptr, "Insufficient memory for pCAL parameter.");
          return;
        }
444
      png_memcpy(info_ptr->pcal_params[i], params[i], (png_size_t)length);
A
Andreas Dilger 已提交
445 446 447
   }

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

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

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

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

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

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

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

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

#if defined(PNG_pHYs_SUPPORTED)
516
void PNGAPI
A
Andreas Dilger 已提交
517 518 519 520
png_set_pHYs(png_structp png_ptr, png_infop info_ptr,
   png_uint_32 res_x, png_uint_32 res_y, int unit_type)
{
   png_debug1(1, "in %s storage function\n", "pHYs");
521
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
522 523 524 525 526 527 528 529 530
      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

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

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

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

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

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

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

580
#if defined(PNG_sBIT_SUPPORTED)
581
void PNGAPI
A
Andreas Dilger 已提交
582 583 584 585
png_set_sBIT(png_structp png_ptr, png_infop info_ptr,
   png_color_8p sig_bit)
{
   png_debug1(1, "in %s storage function\n", "sBIT");
586
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
587 588
      return;

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

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

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

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

   png_set_sRGB(png_ptr, info_ptr, intent);

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

644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659
#if defined(PNG_cHRM_SUPPORTED)
#ifdef PNG_FIXED_POINT_SUPPORTED
   int_white_x = 31270L;
   int_white_y = 32900L;
   int_red_x   = 64000L;
   int_red_y   = 33000L;
   int_green_x = 30000L;
   int_green_y = 60000L;
   int_blue_x  = 15000L;
   int_blue_y  =  6000L;

   png_set_cHRM_fixed(png_ptr, info_ptr,
      int_white_x, int_white_y, int_red_x, int_red_y, int_green_x, int_green_y,
      int_blue_x, int_blue_y);
#endif
#ifdef PNG_FLOATING_POINT_SUPPORTED
660 661 662 663 664 665 666 667
   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;
668 669 670

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

676 677

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

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

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

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

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

#if defined(PNG_TEXT_SUPPORTED)
724
void PNGAPI
A
Andreas Dilger 已提交
725 726
png_set_text(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr,
   int num_text)
727 728 729 730 731 732 733 734 735 736
{
   int ret;
   ret=png_set_text_2(png_ptr, info_ptr, text_ptr, num_text);
   if (ret)
     png_error(png_ptr, "Insufficient memory to store text");
}

int /* PRIVATE */
png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr,
   int num_text)
A
Andreas Dilger 已提交
737 738 739 740
{
   int i;

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

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

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

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

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

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

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

837
      textp->key = (png_charp)png_malloc_warn(png_ptr,
838
         (png_uint_32)(key_len + text_length + lang_len + lang_key_len + 4));
839 840
      if (textp->key == NULL)
        return(1);
841 842 843
      png_debug2(2, "Allocated %lu bytes at %x in png_set_text\n",
         (png_uint_32)(key_len + lang_len + lang_key_len + text_length + 4),
         (int)textp->key);
844 845

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

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

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

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

908
#if defined(PNG_tRNS_SUPPORTED)
909
void PNGAPI
A
Andreas Dilger 已提交
910 911 912 913
png_set_tRNS(png_structp png_ptr, png_infop info_ptr,
   png_bytep trans, int num_trans, png_color_16p trans_values)
{
   png_debug1(1, "in %s storage function\n", "tRNS");
914
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
915 916 917
      return;

   if (trans != NULL)
918 919
   {
       /*
920 921 922 923
        * 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.
        */
924 925 926
#ifdef PNG_FREE_ME_SUPPORTED
       png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
#endif
927
       /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */
928
       png_ptr->trans = info_ptr->trans = (png_bytep)png_malloc(png_ptr,
929 930 931
           (png_uint_32)PNG_MAX_PALETTE_LENGTH);
       if (num_trans <= PNG_MAX_PALETTE_LENGTH)
         png_memcpy(info_ptr->trans, trans, (png_size_t)num_trans);
932 933 934 935 936 937
#ifdef PNG_FREE_ME_SUPPORTED
       info_ptr->free_me |= PNG_FREE_TRNS;
#else
       png_ptr->flags |= PNG_FLAG_FREE_TRNS;
#endif
   }
A
Andreas Dilger 已提交
938 939 940 941

   if (trans_values != NULL)
   {
      png_memcpy(&(info_ptr->trans_values), trans_values,
942
         png_sizeof(png_color_16));
943 944
      if (num_trans == 0)
        num_trans = 1;
A
Andreas Dilger 已提交
945 946 947 948 949 950
   }
   info_ptr->num_trans = (png_uint_16)num_trans;
   info_ptr->valid |= PNG_INFO_tRNS;
}
#endif

951
#if defined(PNG_sPLT_SUPPORTED)
952
void PNGAPI
953
png_set_sPLT(png_structp png_ptr,
954
             png_infop info_ptr, png_sPLT_tp entries, int nentries)
955
{
956
    png_sPLT_tp np;
957 958
    int i;

959 960 961
    if (png_ptr == NULL || info_ptr == NULL)
       return;

962
    np = (png_sPLT_tp)png_malloc_warn(png_ptr,
963
        (info_ptr->splt_palettes_num + nentries) * png_sizeof(png_sPLT_t));
964 965
    if (np == NULL)
    {
966
      png_warning(png_ptr, "No memory for sPLT palettes.");
967 968
      return;
    }
969

970
    png_memcpy(np, info_ptr->splt_palettes,
971
           info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t));
972
    png_free(png_ptr, info_ptr->splt_palettes);
973
    info_ptr->splt_palettes=NULL;
974 975 976

    for (i = 0; i < nentries; i++)
    {
977 978
        png_sPLT_tp to = np + info_ptr->splt_palettes_num + i;
        png_sPLT_tp from = entries + i;
979
        png_uint_32 length;
980

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

    info_ptr->splt_palettes = np;
    info_ptr->splt_palettes_num += nentries;
1008
    info_ptr->valid |= PNG_INFO_sPLT;
1009
#ifdef PNG_FREE_ME_SUPPORTED
1010
    info_ptr->free_me |= PNG_FREE_SPLT;
1011
#endif
1012 1013 1014
}
#endif /* PNG_sPLT_SUPPORTED */

1015
#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
1016
void PNGAPI
1017
png_set_unknown_chunks(png_structp png_ptr,
1018
   png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns)
1019 1020 1021 1022
{
    png_unknown_chunkp np;
    int i;

1023 1024 1025
    if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0)
        return;

1026
    np = (png_unknown_chunkp)png_malloc_warn(png_ptr,
1027
        (info_ptr->unknown_chunks_num + num_unknowns) *
1028
        png_sizeof(png_unknown_chunk));
1029 1030
    if (np == NULL)
    {
1031 1032
       png_warning(png_ptr,
          "Out of memory while processing unknown chunk.");
1033 1034
       return;
    }
1035

1036
    png_memcpy(np, info_ptr->unknown_chunks,
1037
           info_ptr->unknown_chunks_num * png_sizeof(png_unknown_chunk));
1038
    png_free(png_ptr, info_ptr->unknown_chunks);
1039
    info_ptr->unknown_chunks=NULL;
1040

1041
    for (i = 0; i < num_unknowns; i++)
1042 1043 1044 1045
    {
        png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i;
        png_unknown_chunkp from = unknowns + i;

1046 1047 1048
        png_memcpy((png_charp)to->name, 
                   (png_charp)from->name, 
                   png_sizeof(from->name));
1049
        to->name[png_sizeof(to->name)-1] = '\0';
1050

1051
        to->data = (png_bytep)png_malloc_warn(png_ptr, from->size);
1052
        if (to->data == NULL)
1053
        {
1054 1055
           png_warning(png_ptr,
              "Out of memory while processing unknown chunk.");
1056
        }
1057 1058
        else
        {
1059 1060
           png_memcpy(to->data, from->data, from->size);
           to->size = from->size;
1061

1062 1063
           /* note our location in the read or write sequence */
           to->location = (png_byte)(png_ptr->mode & 0xff);
1064
        }
1065 1066 1067
    }

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

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

#if defined(PNG_MNG_FEATURES_SUPPORTED)
png_uint_32 PNGAPI
png_permit_mng_features (png_structp png_ptr, png_uint_32 mng_features)
{
   png_debug(1, "in png_permit_mng_features\n");
   if (png_ptr == NULL)
      return (png_uint_32)0;
   png_ptr->mng_features_permitted =
     (png_byte)(mng_features & PNG_ALL_MNG_FEATURES);
   return (png_uint_32)png_ptr->mng_features_permitted;
1111 1112
}
#endif
1113

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

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

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

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

1179 1180 1181
   if (png_ptr == NULL || info_ptr == NULL)
      return;

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

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

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

1212

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

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

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

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