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

/* pngset.c - storage of image information into info struct
3
 *
4
 * Last changed in libpng 1.2.30 [August 15, 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 24
png_set_bKGD(png_structp png_ptr, png_infop info_ptr, png_color_16p background)
{
   png_debug1(1, "in %s storage function\n", "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 40
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");
41
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
42
      return;
43 44 45 46 47 48 49
   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;
   }
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
   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 已提交
69 70 71 72 73 74 75 76
   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;
77 78 79
#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);
80 81
   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);
82 83
   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);
84 85
   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);
86
#endif
A
Andreas Dilger 已提交
87 88 89
   info_ptr->valid |= PNG_INFO_cHRM;
}
#endif
90
#ifdef PNG_FIXED_POINT_SUPPORTED
91
void PNGAPI
92
png_set_cHRM_fixed(png_structp png_ptr, png_infop info_ptr,
93 94 95
   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)
96 97 98 99
{
   png_debug1(1, "in %s storage function\n", "cHRM");
   if (png_ptr == NULL || info_ptr == NULL)
      return;
A
Andreas Dilger 已提交
100

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

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

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

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

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

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

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

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

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

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

260
void PNGAPI
A
Andreas Dilger 已提交
261 262 263 264 265 266
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");
267
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
268 269
      return;

270 271 272
   /* check for width and height valid values */
   if (width == 0 || height == 0)
      png_error(png_ptr, "Image width or height is zero in IHDR");
273 274 275 276 277 278 279
#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
280
   if (width > PNG_UINT_31_MAX || height > PNG_UINT_31_MAX)
281
      png_error(png_ptr, "Invalid image size in IHDR");
282 283 284 285 286 287 288
   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");
289 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

   /* 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
    */
321
   if ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&png_ptr->mng_features_permitted)
322
      png_warning(png_ptr, "MNG features are not allowed in a PNG datastream");
323
   if (filter_type != PNG_FILTER_TYPE_BASE)
324
   {
325
     if (!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
326 327
        (filter_type == PNG_INTRAPIXEL_DIFFERENCING) &&
        ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&
328
        (color_type == PNG_COLOR_TYPE_RGB ||
329 330
         color_type == PNG_COLOR_TYPE_RGB_ALPHA)))
        png_error(png_ptr, "Unknown filter method in IHDR");
331
     if (png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)
332 333 334
        png_warning(png_ptr, "Invalid filter method in IHDR");
   }
#else
335
   if (filter_type != PNG_FILTER_TYPE_BASE)
336 337 338
      png_error(png_ptr, "Unknown filter method in IHDR");
#endif

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

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

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

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

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

   length = png_strlen(purpose) + 1;
398 399
   png_debug1(3, "allocating purpose for info (%lu bytes)\n",
     (unsigned long)length);
400 401
   info_ptr->pcal_purpose = (png_charp)png_malloc_warn(png_ptr, length);
   if (info_ptr->pcal_purpose == NULL)
402
   {
403
       png_warning(png_ptr, "Insufficient memory for pCAL purpose.");
404 405
      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 416
   png_debug1(3, "allocating units for info (%lu bytes)\n",
     (unsigned long)length);
417 418
   info_ptr->pcal_units = (png_charp)png_malloc_warn(png_ptr, length);
   if (info_ptr->pcal_units == NULL)
419
   {
420
       png_warning(png_ptr, "Insufficient memory for pCAL units.");
421 422
      return;
   }
423
   png_memcpy(info_ptr->pcal_units, units, (png_size_t)length);
A
Andreas Dilger 已提交
424

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

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

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

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

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

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

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

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

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

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

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

#if defined(PNG_pHYs_SUPPORTED)
521
void PNGAPI
A
Andreas Dilger 已提交
522 523 524 525
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");
526
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
527 528 529 530 531 532 533 534 535
      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

536
void PNGAPI
A
Andreas Dilger 已提交
537 538 539
png_set_PLTE(png_structp png_ptr, png_infop info_ptr,
   png_colorp palette, int num_palette)
{
540

A
Andreas Dilger 已提交
541
   png_debug1(1, "in %s storage function\n", "PLTE");
542
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
543 544
      return;

545 546 547 548 549 550 551 552 553 554 555
   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;
       }
     }

556 557 558 559 560 561 562 563
   /*
    * 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
564

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

582
   info_ptr->valid |= PNG_INFO_PLTE;
A
Andreas Dilger 已提交
583 584
}

585
#if defined(PNG_sBIT_SUPPORTED)
586
void PNGAPI
A
Andreas Dilger 已提交
587 588 589 590
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");
591
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
592 593
      return;

594
   png_memcpy(&(info_ptr->sig_bit), sig_bit, png_sizeof(png_color_8));
A
Andreas Dilger 已提交
595 596 597 598
   info_ptr->valid |= PNG_INFO_sBIT;
}
#endif

599
#if defined(PNG_sRGB_SUPPORTED)
600
void PNGAPI
601
png_set_sRGB(png_structp png_ptr, png_infop info_ptr, int intent)
602 603
{
   png_debug1(1, "in %s storage function\n", "sRGB");
604
   if (png_ptr == NULL || info_ptr == NULL)
605 606
      return;

607
   info_ptr->srgb_intent = (png_byte)intent;
608 609
   info_ptr->valid |= PNG_INFO_sRGB;
}
610

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

   png_set_sRGB(png_ptr, info_ptr, intent);

638 639
#if defined(PNG_gAMA_SUPPORTED)
#ifdef PNG_FLOATING_POINT_SUPPORTED
640
   file_gamma = (float).45455;
641 642
   png_set_gAMA(png_ptr, info_ptr, file_gamma);
#endif
643 644 645 646 647
#ifdef PNG_FIXED_POINT_SUPPORTED
   int_file_gamma = 45455L;
   png_set_gAMA_fixed(png_ptr, info_ptr, int_file_gamma);
#endif
#endif
648

649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664
#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
665 666 667 668 669 670 671 672
   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;
673 674 675

   png_set_cHRM(png_ptr, info_ptr,
      white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
676
#endif
677 678 679 680
#endif
}
#endif

681 682

#if defined(PNG_iCCP_SUPPORTED)
683
void PNGAPI
684 685
png_set_iCCP(png_structp png_ptr, png_infop info_ptr,
             png_charp name, int compression_type,
686
             png_charp profile, png_uint_32 proflen)
687
{
688 689
   png_charp new_iccp_name;
   png_charp new_iccp_profile;
690
   png_uint_32 length;
691

692 693 694 695
   png_debug1(1, "in %s storage function\n", "iCCP");
   if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL)
      return;

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

714
   png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0);
715

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

#if defined(PNG_TEXT_SUPPORTED)
730
void PNGAPI
A
Andreas Dilger 已提交
731 732
png_set_text(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr,
   int num_text)
733 734
{
   int ret;
735
   ret = png_set_text_2(png_ptr, info_ptr, text_ptr, num_text);
736 737 738 739 740 741 742
   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 已提交
743 744 745 746
{
   int i;

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

749
   if (png_ptr == NULL || info_ptr == NULL || num_text == 0)
750
      return(0);
A
Andreas Dilger 已提交
751 752 753 754 755 756 757 758 759 760 761 762 763 764

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

797
      if (text_ptr[i].key == NULL)
798 799
          continue;

800 801
      key_len = png_strlen(text_ptr[i].key);

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

827
      if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0')
A
Andreas Dilger 已提交
828
      {
829
         text_length = 0;
830
#ifdef PNG_iTXt_SUPPORTED
831
         if (text_ptr[i].compression > 0)
832 833
            textp->compression = PNG_ITXT_COMPRESSION_NONE;
         else
834
#endif
835
            textp->compression = PNG_TEXT_COMPRESSION_NONE;
A
Andreas Dilger 已提交
836 837 838
      }
      else
      {
839
         text_length = png_strlen(text_ptr[i].text);
A
Andreas Dilger 已提交
840 841
         textp->compression = text_ptr[i].compression;
      }
842

843
      textp->key = (png_charp)png_malloc_warn(png_ptr,
844 845
         (png_uint_32)
         (key_len + text_length + lang_len + lang_key_len + 4));
846 847
      if (textp->key == NULL)
        return(1);
848
      png_debug2(2, "Allocated %lu bytes at %x in png_set_text\n",
849 850
         (png_uint_32)
         (key_len + lang_len + lang_key_len + text_length + 4),
851
         (int)textp->key);
852 853

      png_memcpy(textp->key, text_ptr[i].key,
854
         (png_size_t)(key_len));
855
      *(textp->key + key_len) = '\0';
856
#ifdef PNG_iTXt_SUPPORTED
857 858
      if (text_ptr[i].compression > 0)
      {
859
         textp->lang = textp->key + key_len + 1;
860
         png_memcpy(textp->lang, text_ptr[i].lang, lang_len);
861
         *(textp->lang + lang_len) = '\0';
862
         textp->lang_key = textp->lang + lang_len + 1;
863
         png_memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len);
864
         *(textp->lang_key + lang_key_len) = '\0';
865
         textp->text = textp->lang_key + lang_key_len + 1;
866 867
      }
      else
868
#endif
869
      {
870
#ifdef PNG_iTXt_SUPPORTED
871 872
         textp->lang=NULL;
         textp->lang_key=NULL;
873
#endif
874
         textp->text = textp->key + key_len + 1;
875
      }
876
      if (text_length)
877
         png_memcpy(textp->text, text_ptr[i].text,
878
            (png_size_t)(text_length));
879
      *(textp->text + text_length) = '\0';
880

881
#ifdef PNG_iTXt_SUPPORTED
882
      if (textp->compression > 0)
883 884 885 886 887
      {
         textp->text_length = 0;
         textp->itxt_length = text_length;
      }
      else
888
#endif
889 890
      {
         textp->text_length = text_length;
891
#ifdef PNG_iTXt_SUPPORTED
892
         textp->itxt_length = 0;
893
#endif
894
      }
A
Andreas Dilger 已提交
895 896 897
      info_ptr->num_text++;
      png_debug1(3, "transferred text chunk %d\n", info_ptr->num_text);
   }
898
   return(0);
A
Andreas Dilger 已提交
899 900 901
}
#endif

902
#if defined(PNG_tIME_SUPPORTED)
903
void PNGAPI
A
Andreas Dilger 已提交
904 905 906
png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_timep mod_time)
{
   png_debug1(1, "in %s storage function\n", "tIME");
907
   if (png_ptr == NULL || info_ptr == NULL ||
908
       (png_ptr->mode & PNG_WROTE_tIME))
A
Andreas Dilger 已提交
909 910
      return;

911
   png_memcpy(&(info_ptr->mod_time), mod_time, png_sizeof(png_time));
A
Andreas Dilger 已提交
912 913 914 915
   info_ptr->valid |= PNG_INFO_tIME;
}
#endif

916
#if defined(PNG_tRNS_SUPPORTED)
917
void PNGAPI
A
Andreas Dilger 已提交
918 919 920 921
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");
922
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
923 924 925
      return;

   if (trans != NULL)
926 927
   {
       /*
928 929 930 931
        * 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.
        */
932

933 934 935 936
#ifdef PNG_FREE_ME_SUPPORTED
       png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
#endif

937
       /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */
938
       png_ptr->trans = info_ptr->trans = (png_bytep)png_malloc(png_ptr,
939
           (png_uint_32)PNG_MAX_PALETTE_LENGTH);
940
       if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH)
941
         png_memcpy(info_ptr->trans, trans, (png_size_t)num_trans);
942
   }
A
Andreas Dilger 已提交
943 944 945

   if (trans_values != NULL)
   {
946 947 948 949 950 951 952
      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)))
953 954
        png_warning(png_ptr,
           "tRNS chunk has out-of-range samples for bit_depth");
A
Andreas Dilger 已提交
955
      png_memcpy(&(info_ptr->trans_values), trans_values,
956
         png_sizeof(png_color_16));
957 958
      if (num_trans == 0)
        num_trans = 1;
A
Andreas Dilger 已提交
959
   }
960

A
Andreas Dilger 已提交
961
   info_ptr->num_trans = (png_uint_16)num_trans;
962 963 964 965 966 967 968 969 970
   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 已提交
971 972 973
}
#endif

974
#if defined(PNG_sPLT_SUPPORTED)
975
void PNGAPI
976
png_set_sPLT(png_structp png_ptr,
977
             png_infop info_ptr, png_sPLT_tp entries, int nentries)
978 979 980 981 982 983 984
/*
 *  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.
 */
985
{
986
    png_sPLT_tp np;
987 988
    int i;

989 990 991
    if (png_ptr == NULL || info_ptr == NULL)
       return;

992
    np = (png_sPLT_tp)png_malloc_warn(png_ptr,
993 994
        (info_ptr->splt_palettes_num + nentries) *
        (png_uint_32)png_sizeof(png_sPLT_t));
995 996
    if (np == NULL)
    {
997
      png_warning(png_ptr, "No memory for sPLT palettes.");
998 999
      return;
    }
1000

1001
    png_memcpy(np, info_ptr->splt_palettes,
1002
           info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t));
1003
    png_free(png_ptr, info_ptr->splt_palettes);
1004
    info_ptr->splt_palettes=NULL;
1005 1006 1007

    for (i = 0; i < nentries; i++)
    {
1008 1009
        png_sPLT_tp to = np + info_ptr->splt_palettes_num + i;
        png_sPLT_tp from = entries + i;
1010
        png_uint_32 length;
1011

1012 1013
        length = png_strlen(from->name) + 1;
        to->name = (png_charp)png_malloc_warn(png_ptr, length);
1014 1015 1016 1017
        if (to->name == NULL)
        {
           png_warning(png_ptr,
             "Out of memory while processing sPLT chunk");
1018
           continue;
1019
        }
1020
        png_memcpy(to->name, from->name, length);
1021
        to->entries = (png_sPLT_entryp)png_malloc_warn(png_ptr,
1022
            (png_uint_32)(from->nentries * png_sizeof(png_sPLT_entry)));
1023 1024 1025 1026
        if (to->entries == NULL)
        {
           png_warning(png_ptr,
             "Out of memory while processing sPLT chunk");
1027
           png_free(png_ptr, to->name);
1028
           to->name = NULL;
1029
           continue;
1030
        }
1031 1032
        png_memcpy(to->entries, from->entries,
            from->nentries * png_sizeof(png_sPLT_entry));
1033 1034
        to->nentries = from->nentries;
        to->depth = from->depth;
1035 1036 1037 1038
    }

    info_ptr->splt_palettes = np;
    info_ptr->splt_palettes_num += nentries;
1039
    info_ptr->valid |= PNG_INFO_sPLT;
1040
#ifdef PNG_FREE_ME_SUPPORTED
1041
    info_ptr->free_me |= PNG_FREE_SPLT;
1042
#endif
1043 1044 1045
}
#endif /* PNG_sPLT_SUPPORTED */

1046
#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
1047
void PNGAPI
1048
png_set_unknown_chunks(png_structp png_ptr,
1049
   png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns)
1050 1051 1052 1053
{
    png_unknown_chunkp np;
    int i;

1054 1055 1056
    if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0)
        return;

1057
    np = (png_unknown_chunkp)png_malloc_warn(png_ptr,
1058 1059
        (png_uint_32)((info_ptr->unknown_chunks_num + num_unknowns) *
        png_sizeof(png_unknown_chunk)));
1060 1061
    if (np == NULL)
    {
1062 1063
       png_warning(png_ptr,
          "Out of memory while processing unknown chunk.");
1064 1065
       return;
    }
1066

1067
    png_memcpy(np, info_ptr->unknown_chunks,
1068
           info_ptr->unknown_chunks_num * png_sizeof(png_unknown_chunk));
1069
    png_free(png_ptr, info_ptr->unknown_chunks);
1070
    info_ptr->unknown_chunks=NULL;
1071

1072
    for (i = 0; i < num_unknowns; i++)
1073
    {
1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088
       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
       {
1089 1090
          to->data = (png_bytep)png_malloc_warn(png_ptr,
            (png_uint_32)from->size);
1091 1092 1093
          if (to->data == NULL)
          {
             png_warning(png_ptr,
1094
              "Out of memory while processing unknown chunk.");
1095
             to->size = 0;
1096 1097 1098 1099
          }
          else
             png_memcpy(to->data, from->data, from->size);
       }
1100 1101 1102
    }

    info_ptr->unknown_chunks = np;
1103
    info_ptr->unknown_chunks_num += num_unknowns;
1104
#ifdef PNG_FREE_ME_SUPPORTED
1105
    info_ptr->free_me |= PNG_FREE_UNKN;
1106
#endif
1107
}
1108
void PNGAPI
1109 1110 1111
png_set_unknown_chunk_location(png_structp png_ptr, png_infop info_ptr,
   int chunk, int location)
{
1112
   if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 && chunk <
1113 1114 1115
         (int)info_ptr->unknown_chunks_num)
      info_ptr->unknown_chunks[chunk].location = (png_byte)location;
}
1116 1117
#endif

1118
#if defined(PNG_1_0_X) || defined(PNG_1_2_X)
1119 1120
#if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \
    defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED)
1121
void PNGAPI
1122 1123
png_permit_empty_plte (png_structp png_ptr, int empty_plte_permitted)
{
1124
   /* This function is deprecated in favor of png_permit_mng_features()
1125
      and will be removed from libpng-1.3.0 */
1126
   png_debug(1, "in png_permit_empty_plte, DEPRECATED.\n");
1127 1128
   if (png_ptr == NULL)
      return;
1129
   png_ptr->mng_features_permitted = (png_byte)
1130
     ((png_ptr->mng_features_permitted & (~PNG_FLAG_MNG_EMPTY_PLTE)) |
1131 1132 1133
     ((empty_plte_permitted & PNG_FLAG_MNG_EMPTY_PLTE)));
}
#endif
1134
#endif
1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145

#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;
1146 1147
}
#endif
1148

1149
#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
1150
void PNGAPI
1151 1152 1153 1154 1155
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;
1156 1157
    if (png_ptr == NULL)
       return;
1158 1159
    if (num_chunks == 0)
    {
1160
      if (keep == PNG_HANDLE_CHUNK_ALWAYS || keep == PNG_HANDLE_CHUNK_IF_SAFE)
1161 1162 1163
        png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
      else
        png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
1164

1165
      if (keep == PNG_HANDLE_CHUNK_ALWAYS)
1166 1167 1168 1169 1170 1171 1172
        png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS;
      else
        png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS;
      return;
    }
    if (chunk_list == NULL)
      return;
1173
    old_num_chunks = png_ptr->num_chunk_list;
1174
    new_list=(png_bytep)png_malloc(png_ptr,
1175 1176 1177
       (png_uint_32)
       (5*(num_chunks + old_num_chunks)));
    if (png_ptr->chunk_list != NULL)
1178
    {
1179 1180
       png_memcpy(new_list, png_ptr->chunk_list,
          (png_size_t)(5*old_num_chunks));
1181
       png_free(png_ptr, png_ptr->chunk_list);
1182
       png_ptr->chunk_list=NULL;
1183
    }
1184
    png_memcpy(new_list + 5*old_num_chunks, chunk_list,
1185
       (png_size_t)(5*num_chunks));
1186
    for (p = new_list + 5*old_num_chunks + 4, i = 0; i<num_chunks; i++, p += 5)
1187
       *p=(png_byte)keep;
1188 1189
    png_ptr->num_chunk_list = old_num_chunks + num_chunks;
    png_ptr->chunk_list = new_list;
1190
#ifdef PNG_FREE_ME_SUPPORTED
1191
    png_ptr->free_me |= PNG_FREE_LIST;
1192
#endif
1193 1194
}
#endif
1195

1196
#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
1197
void PNGAPI
1198 1199 1200 1201
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");
1202 1203
   if (png_ptr == NULL)
      return;
1204 1205 1206 1207
   png_ptr->read_user_chunk_fn = read_user_chunk_fn;
   png_ptr->user_chunk_ptr = user_chunk_ptr;
}
#endif
1208

1209
#if defined(PNG_INFO_IMAGE_SUPPORTED)
1210
void PNGAPI
1211 1212 1213
png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers)
{
   png_debug1(1, "in %s storage function\n", "rows");
1214

1215 1216 1217
   if (png_ptr == NULL || info_ptr == NULL)
      return;

1218
   if (info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers))
1219
      png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
1220
   info_ptr->row_pointers = row_pointers;
1221
   if (row_pointers)
1222
      info_ptr->valid |= PNG_INFO_IDAT;
1223 1224 1225
}
#endif

1226
#ifdef PNG_WRITE_SUPPORTED
1227
void PNGAPI
1228 1229
png_set_compression_buffer_size(png_structp png_ptr,
    png_uint_32 size)
1230
{
1231 1232
    if (png_ptr == NULL)
       return;
1233
    png_free(png_ptr, png_ptr->zbuf);
1234 1235 1236 1237 1238
    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;
}
1239
#endif
1240 1241 1242 1243 1244

void PNGAPI
png_set_invalid(png_structp png_ptr, png_infop info_ptr, int mask)
{
   if (png_ptr && info_ptr)
1245
      info_ptr->valid &= ~mask;
1246
}
1247

1248

1249
#ifndef PNG_1_0_X
1250
#ifdef PNG_ASSEMBLER_CODE_SUPPORTED
1251
/* function was added to libpng 1.2.0 and should always exist by default */
1252 1253 1254
void PNGAPI
png_set_asm_flags (png_structp png_ptr, png_uint_32 asm_flags)
{
1255 1256 1257
/* 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;
1258
    asm_flags = asm_flags; /* Quiet the compiler */
1259
}
1260 1261 1262 1263 1264 1265 1266

/* 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)
{
1267
/* Obsolete as of libpng-1.2.20 and will be removed from libpng-1.4.0 */
1268 1269
    if (png_ptr == NULL)
       return;
1270 1271 1272
    /* Quiet the compiler */
    mmx_bitdepth_threshold = mmx_bitdepth_threshold;
    mmx_rowbytes_threshold = mmx_rowbytes_threshold;
1273
}
1274
#endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */
1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285

#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.
     */
1286
    if (png_ptr == NULL) return;
1287 1288 1289 1290 1291
    png_ptr->user_width_max = user_width_max;
    png_ptr->user_height_max = user_height_max;
}
#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */

1292
#endif /* ?PNG_1_0_X */
1293
#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */