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

/* pngset.c - storage of image information into info struct
3
 *
4
 * Last changed in libpng 1.6.0 [(PENDING RELEASE)]
5
 * Copyright (c) 1998-2012 Glenn Randers-Pehrson
6 7
 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
8
 *
9
 * This code is released under the libpng license.
10
 * For conditions of distribution and use, see the disclaimer
11
 * and license in png.h
12
 *
13 14 15 16 17
 * 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 已提交
18

19
#include "pngpriv.h"
20

21 22
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)

23
#ifdef PNG_bKGD_SUPPORTED
24
void PNGAPI
25
png_set_bKGD(png_const_structrp png_ptr, png_inforp info_ptr,
26
    png_const_color_16p background)
A
Andreas Dilger 已提交
27
{
28
   png_debug1(1, "in %s storage function", "bKGD");
29

30
   if (png_ptr == NULL || info_ptr == NULL || background == NULL)
A
Andreas Dilger 已提交
31 32
      return;

33
   info_ptr->background = *background;
A
Andreas Dilger 已提交
34 35 36 37
   info_ptr->valid |= PNG_INFO_bKGD;
}
#endif

38
#ifdef PNG_cHRM_SUPPORTED
G
[devel]  
Glenn Randers-Pehrson 已提交
39
void PNGFAPI
40
png_set_cHRM_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
41 42 43
    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)
44
{
45 46
   png_xy xy;

47
   png_debug1(1, "in %s storage function", "cHRM fixed");
48

49 50
   if (png_ptr == NULL || info_ptr == NULL)
      return;
A
Andreas Dilger 已提交
51

52 53 54 55 56 57 58 59 60 61 62 63 64 65
   xy.redx = red_x;
   xy.redy = red_y;
   xy.greenx = green_x;
   xy.greeny = green_y;
   xy.bluex = blue_x;
   xy.bluey = blue_y;
   xy.whitex = white_x;
   xy.whitey = white_y;

   if (png_colorspace_set_chromaticities(png_ptr, &info_ptr->colorspace, &xy,
      2/* override with app values*/))
      info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM;

   png_colorspace_sync_info(png_ptr, info_ptr);
66 67
}

68
void PNGFAPI
69
png_set_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
    png_fixed_point int_red_X, png_fixed_point int_red_Y,
    png_fixed_point int_red_Z, png_fixed_point int_green_X,
    png_fixed_point int_green_Y, png_fixed_point int_green_Z,
    png_fixed_point int_blue_X, png_fixed_point int_blue_Y,
    png_fixed_point int_blue_Z)
{
   png_XYZ XYZ;

   png_debug1(1, "in %s storage function", "cHRM XYZ fixed");

   if (png_ptr == NULL || info_ptr == NULL)
      return;

   XYZ.redX = int_red_X;
   XYZ.redY = int_red_Y;
   XYZ.redZ = int_red_Z;
   XYZ.greenX = int_green_X;
   XYZ.greenY = int_green_Y;
   XYZ.greenZ = int_green_Z;
   XYZ.blueX = int_blue_X;
   XYZ.blueY = int_blue_Y;
   XYZ.blueZ = int_blue_Z;

93 94
   if (png_colorspace_set_endpoints(png_ptr, &info_ptr->colorspace, &XYZ, 2))
      info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM;
95

96
   png_colorspace_sync_info(png_ptr, info_ptr);
97 98
}

99
#  ifdef PNG_FLOATING_POINT_SUPPORTED
100
void PNGAPI
101
png_set_cHRM(png_const_structrp png_ptr, png_inforp info_ptr,
G
[devel]  
Glenn Randers-Pehrson 已提交
102 103
    double white_x, double white_y, double red_x, double red_y,
    double green_x, double green_y, double blue_x, double blue_y)
A
Andreas Dilger 已提交
104
{
G
[devel]  
Glenn Randers-Pehrson 已提交
105 106 107 108 109 110 111 112 113 114
   png_set_cHRM_fixed(png_ptr, info_ptr,
      png_fixed(png_ptr, white_x, "cHRM White X"),
      png_fixed(png_ptr, white_y, "cHRM White Y"),
      png_fixed(png_ptr, red_x, "cHRM Red X"),
      png_fixed(png_ptr, red_y, "cHRM Red Y"),
      png_fixed(png_ptr, green_x, "cHRM Green X"),
      png_fixed(png_ptr, green_y, "cHRM Green Y"),
      png_fixed(png_ptr, blue_x, "cHRM Blue X"),
      png_fixed(png_ptr, blue_y, "cHRM Blue Y"));
}
115 116

void PNGAPI
117
png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp info_ptr, double red_X,
118 119 120 121 122 123 124 125 126 127 128 129 130 131
    double red_Y, double red_Z, double green_X, double green_Y, double green_Z,
    double blue_X, double blue_Y, double blue_Z)
{
   png_set_cHRM_XYZ_fixed(png_ptr, info_ptr,
      png_fixed(png_ptr, red_X, "cHRM Red X"),
      png_fixed(png_ptr, red_Y, "cHRM Red Y"),
      png_fixed(png_ptr, red_Z, "cHRM Red Z"),
      png_fixed(png_ptr, green_X, "cHRM Red X"),
      png_fixed(png_ptr, green_Y, "cHRM Red Y"),
      png_fixed(png_ptr, green_Z, "cHRM Red Z"),
      png_fixed(png_ptr, blue_X, "cHRM Red X"),
      png_fixed(png_ptr, blue_Y, "cHRM Red Y"),
      png_fixed(png_ptr, blue_Z, "cHRM Red Z"));
}
132
#  endif /* PNG_FLOATING_POINT_SUPPORTED */
133

G
[devel]  
Glenn Randers-Pehrson 已提交
134
#endif /* PNG_cHRM_SUPPORTED */
135

G
[devel]  
Glenn Randers-Pehrson 已提交
136 137
#ifdef PNG_gAMA_SUPPORTED
void PNGFAPI
138 139
png_set_gAMA_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
    png_fixed_point file_gamma)
140
{
141
   png_debug1(1, "in %s storage function", "gAMA");
142

143 144 145
   if (png_ptr == NULL || info_ptr == NULL)
      return;

146 147 148 149 150
   /* Changed in libpng-1.5.4 to limit the values to ensure overflow can't
    * occur.  Since the fixed point representation is assymetrical it is
    * possible for 1/gamma to overflow the limit of 21474 and this means the
    * gamma value must be at least 5/100000 and hence at most 20000.0.  For
    * safety the limits here are a little narrower.  The values are 0.00016 to
151
    * 6250.0, which are truly ridiculous gammma values (and will produce
152
    * displays that are all black or all white.)
G
[devel]  
Glenn Randers-Pehrson 已提交
153
    */
154
   if (file_gamma < 16 || file_gamma > 625000000)
155
      png_app_error(png_ptr, "Out of range gamma value ignored");
156

157 158
   else
   {
159 160 161 162 163
      if (png_colorspace_set_gamma(png_ptr, &info_ptr->colorspace, file_gamma,
         2/* overrided with app value */))
         info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_gAMA;

      png_colorspace_sync_info(png_ptr, info_ptr);
164
   }
G
[devel]  
Glenn Randers-Pehrson 已提交
165
}
166

167
#  ifdef PNG_FLOATING_POINT_SUPPORTED
G
[devel]  
Glenn Randers-Pehrson 已提交
168
void PNGAPI
169
png_set_gAMA(png_const_structrp png_ptr, png_inforp info_ptr, double file_gamma)
G
[devel]  
Glenn Randers-Pehrson 已提交
170 171
{
   png_set_gAMA_fixed(png_ptr, info_ptr, png_fixed(png_ptr, file_gamma,
172
       "png_set_gAMA"));
A
Andreas Dilger 已提交
173
}
174
#  endif
175
#endif
A
Andreas Dilger 已提交
176

177
#ifdef PNG_hIST_SUPPORTED
178
void PNGAPI
179 180
png_set_hIST(png_const_structrp png_ptr, png_inforp info_ptr,
    png_const_uint_16p hist)
A
Andreas Dilger 已提交
181
{
182
   int i;
183

184
   png_debug1(1, "in %s storage function", "hIST");
185

186
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
187
      return;
188

189
   if (info_ptr->num_palette == 0 || info_ptr->num_palette
190
       > PNG_MAX_PALETTE_LENGTH)
191
   {
192
      png_warning(png_ptr,
193
          "Invalid palette size, hIST allocation skipped");
194

195
      return;
196
   }
197 198

   png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0);
199

200 201 202
   /* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in
    * version 1.2.1
    */
203 204
   info_ptr->hist = png_voidcast(png_uint_16p, png_malloc_warn(png_ptr,
       PNG_MAX_PALETTE_LENGTH * png_sizeof(png_uint_16)));
205

206
   if (info_ptr->hist == NULL)
207 208 209 210
   {
      png_warning(png_ptr, "Insufficient memory for hIST chunk data");
      return;
   }
A
Andreas Dilger 已提交
211

212 213
   info_ptr->free_me |= PNG_FREE_HIST;

214
   for (i = 0; i < info_ptr->num_palette; i++)
215
      info_ptr->hist[i] = hist[i];
216

A
Andreas Dilger 已提交
217 218 219 220
   info_ptr->valid |= PNG_INFO_hIST;
}
#endif

221
void PNGAPI
222
png_set_IHDR(png_const_structrp png_ptr, png_inforp info_ptr,
223 224 225
    png_uint_32 width, png_uint_32 height, int bit_depth,
    int color_type, int interlace_type, int compression_type,
    int filter_type)
A
Andreas Dilger 已提交
226
{
227
   png_debug1(1, "in %s storage function", "IHDR");
228

229
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
230 231 232 233 234
      return;

   info_ptr->width = width;
   info_ptr->height = height;
   info_ptr->bit_depth = (png_byte)bit_depth;
235
   info_ptr->color_type = (png_byte)color_type;
A
Andreas Dilger 已提交
236 237 238
   info_ptr->compression_type = (png_byte)compression_type;
   info_ptr->filter_type = (png_byte)filter_type;
   info_ptr->interlace_type = (png_byte)interlace_type;
239 240 241 242 243

   png_check_IHDR (png_ptr, info_ptr->width, info_ptr->height,
       info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type,
       info_ptr->compression_type, info_ptr->filter_type);

244 245
   if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
      info_ptr->channels = 1;
246

247
   else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
A
Andreas Dilger 已提交
248
      info_ptr->channels = 3;
249

A
Andreas Dilger 已提交
250 251
   else
      info_ptr->channels = 1;
252

A
Andreas Dilger 已提交
253 254
   if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
      info_ptr->channels++;
255

A
Andreas Dilger 已提交
256
   info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth);
257

258
   /* Check for potential overflow */
259 260 261 262 263 264
   if (width >
       (PNG_UINT_32_MAX >> 3)      /* 8-byte RRGGBBAA pixels */
       - 48       /* bigrowbuf hack */
       - 1        /* filter byte */
       - 7*8      /* rounding of width to multiple of 8 pixels */
       - 8)       /* extra max_pixel_depth pad */
265
      info_ptr->rowbytes = 0;
266
   else
267
      info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width);
A
Andreas Dilger 已提交
268 269
}

270
#ifdef PNG_oFFs_SUPPORTED
271
void PNGAPI
272
png_set_oFFs(png_const_structrp png_ptr, png_inforp info_ptr,
273
    png_int_32 offset_x, png_int_32 offset_y, int unit_type)
A
Andreas Dilger 已提交
274
{
275
   png_debug1(1, "in %s storage function", "oFFs");
276

277
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
278 279 280 281 282 283 284 285 286
      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

287
#ifdef PNG_pCAL_SUPPORTED
288
void PNGAPI
289
png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr,
290 291
    png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type,
    int nparams, png_const_charp units, png_charpp params)
A
Andreas Dilger 已提交
292
{
293
   png_size_t length;
294
   int i;
A
Andreas Dilger 已提交
295

296
   png_debug1(1, "in %s storage function", "pCAL");
297

298 299
   if (png_ptr == NULL || info_ptr == NULL || purpose == NULL || units == NULL
      || (nparams > 0 && params == NULL))
A
Andreas Dilger 已提交
300 301 302
      return;

   length = png_strlen(purpose) + 1;
303
   png_debug1(3, "allocating purpose for info (%lu bytes)",
304
       (unsigned long)length);
305

G
[devel]  
Glenn Randers-Pehrson 已提交
306 307 308 309 310 311
   /* TODO: validate format of calibration name and unit name */

   /* Check that the type matches the specification. */
   if (type < 0 || type > 3)
      png_error(png_ptr, "Invalid pCAL equation type");

312 313 314
   if (nparams < 0 || nparams > 255)
      png_error(png_ptr, "Invalid pCAL parameter count");

G
[devel]  
Glenn Randers-Pehrson 已提交
315 316
   /* Validate params[nparams] */
   for (i=0; i<nparams; ++i)
317 318
      if (params[i] == NULL ||
         !png_check_fp_string(params[i], png_strlen(params[i])))
G
[devel]  
Glenn Randers-Pehrson 已提交
319 320
         png_error(png_ptr, "Invalid format for pCAL parameter");

321 322
   info_ptr->pcal_purpose = png_voidcast(png_charp,
      png_malloc_warn(png_ptr, length));
323

324
   if (info_ptr->pcal_purpose == NULL)
325
   {
326
      png_warning(png_ptr, "Insufficient memory for pCAL purpose");
327 328
      return;
   }
329

330
   png_memcpy(info_ptr->pcal_purpose, purpose, length);
A
Andreas Dilger 已提交
331

332
   png_debug(3, "storing X0, X1, type, and nparams in info");
A
Andreas Dilger 已提交
333 334 335 336 337 338
   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;
339
   png_debug1(3, "allocating units for info (%lu bytes)",
340
     (unsigned long)length);
341

342 343
   info_ptr->pcal_units = png_voidcast(png_charp,
      png_malloc_warn(png_ptr, length));
344

345
   if (info_ptr->pcal_units == NULL)
346
   {
347
      png_warning(png_ptr, "Insufficient memory for pCAL units");
348 349
      return;
   }
350

351
   png_memcpy(info_ptr->pcal_units, units, length);
A
Andreas Dilger 已提交
352

353 354
   info_ptr->pcal_params = png_voidcast(png_charpp, png_malloc_warn(png_ptr,
       (png_size_t)((nparams + 1) * png_sizeof(png_charp))));
355

356
   if (info_ptr->pcal_params == NULL)
357
   {
358
      png_warning(png_ptr, "Insufficient memory for pCAL params");
359 360
      return;
   }
361

362
   png_memset(info_ptr->pcal_params, 0, (nparams + 1) * png_sizeof(png_charp));
A
Andreas Dilger 已提交
363 364 365 366

   for (i = 0; i < nparams; i++)
   {
      length = png_strlen(params[i]) + 1;
367
      png_debug2(3, "allocating parameter %d for info (%lu bytes)", i,
368
          (unsigned long)length);
369

370
      info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length);
371

372
      if (info_ptr->pcal_params[i] == NULL)
373
      {
374 375
         png_warning(png_ptr, "Insufficient memory for pCAL parameter");
         return;
376
      }
377

378
      png_memcpy(info_ptr->pcal_params[i], params[i], length);
A
Andreas Dilger 已提交
379 380 381
   }

   info_ptr->valid |= PNG_INFO_pCAL;
382
   info_ptr->free_me |= PNG_FREE_PCAL;
A
Andreas Dilger 已提交
383 384 385
}
#endif

386
#ifdef PNG_sCAL_SUPPORTED
387
void PNGAPI
388
png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr,
389
    int unit, png_const_charp swidth, png_const_charp sheight)
390
{
391
   png_size_t lengthw = 0, lengthh = 0;
392

393
   png_debug1(1, "in %s storage function", "sCAL");
394

395 396 397
   if (png_ptr == NULL || info_ptr == NULL)
      return;

G
[devel]  
Glenn Randers-Pehrson 已提交
398 399 400 401 402 403
   /* Double check the unit (should never get here with an invalid
    * unit unless this is an API call.)
    */
   if (unit != 1 && unit != 2)
      png_error(png_ptr, "Invalid sCAL unit");

404
   if (swidth == NULL || (lengthw = png_strlen(swidth)) == 0 ||
405
       swidth[0] == 45 /* '-' */ || !png_check_fp_string(swidth, lengthw))
G
[devel]  
Glenn Randers-Pehrson 已提交
406 407
      png_error(png_ptr, "Invalid sCAL width");

408
   if (sheight == NULL || (lengthh = png_strlen(sheight)) == 0 ||
409
       sheight[0] == 45 /* '-' */ || !png_check_fp_string(sheight, lengthh))
G
[devel]  
Glenn Randers-Pehrson 已提交
410 411
      png_error(png_ptr, "Invalid sCAL height");

412
   info_ptr->scal_unit = (png_byte)unit;
413

G
[devel]  
Glenn Randers-Pehrson 已提交
414
   ++lengthw;
415

416
   png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthw);
417

418 419
   info_ptr->scal_s_width = png_voidcast(png_charp,
      png_malloc_warn(png_ptr, lengthw));
420

421 422
   if (info_ptr->scal_s_width == NULL)
   {
G
[devel]  
Glenn Randers-Pehrson 已提交
423
      png_warning(png_ptr, "Memory allocation failed while processing sCAL");
424
      return;
425
   }
426

G
[devel]  
Glenn Randers-Pehrson 已提交
427
   png_memcpy(info_ptr->scal_s_width, swidth, lengthw);
428

G
[devel]  
Glenn Randers-Pehrson 已提交
429
   ++lengthh;
430

431
   png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthh);
432

433 434
   info_ptr->scal_s_height = png_voidcast(png_charp,
      png_malloc_warn(png_ptr, lengthh));
435

436 437 438
   if (info_ptr->scal_s_height == NULL)
   {
      png_free (png_ptr, info_ptr->scal_s_width);
439
      info_ptr->scal_s_width = NULL;
440

G
[devel]  
Glenn Randers-Pehrson 已提交
441
      png_warning(png_ptr, "Memory allocation failed while processing sCAL");
442
      return;
443
   }
444

G
[devel]  
Glenn Randers-Pehrson 已提交
445 446
   png_memcpy(info_ptr->scal_s_height, sheight, lengthh);

447
   info_ptr->valid |= PNG_INFO_sCAL;
448
   info_ptr->free_me |= PNG_FREE_SCAL;
449
}
G
[devel]  
Glenn Randers-Pehrson 已提交
450

451
#  ifdef PNG_FLOATING_POINT_SUPPORTED
G
[devel]  
Glenn Randers-Pehrson 已提交
452
void PNGAPI
453 454
png_set_sCAL(png_const_structrp png_ptr, png_inforp info_ptr, int unit,
    double width, double height)
G
[devel]  
Glenn Randers-Pehrson 已提交
455 456 457 458 459 460
{
   png_debug1(1, "in %s storage function", "sCAL");

   /* Check the arguments. */
   if (width <= 0)
      png_warning(png_ptr, "Invalid sCAL width ignored");
461

G
[devel]  
Glenn Randers-Pehrson 已提交
462 463
   else if (height <= 0)
      png_warning(png_ptr, "Invalid sCAL height ignored");
464

G
[devel]  
Glenn Randers-Pehrson 已提交
465 466 467 468 469 470 471 472 473 474 475 476 477 478
   else
   {
      /* Convert 'width' and 'height' to ASCII. */
      char swidth[PNG_sCAL_MAX_DIGITS+1];
      char sheight[PNG_sCAL_MAX_DIGITS+1];

      png_ascii_from_fp(png_ptr, swidth, sizeof swidth, width,
         PNG_sCAL_PRECISION);
      png_ascii_from_fp(png_ptr, sheight, sizeof sheight, height,
         PNG_sCAL_PRECISION);

      png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight);
   }
}
479
#  endif
480

481
#  ifdef PNG_FIXED_POINT_SUPPORTED
482
void PNGAPI
483
png_set_sCAL_fixed(png_const_structrp png_ptr, png_inforp info_ptr, int unit,
484
    png_fixed_point width, png_fixed_point height)
485 486 487 488 489 490
{
   png_debug1(1, "in %s storage function", "sCAL");

   /* Check the arguments. */
   if (width <= 0)
      png_warning(png_ptr, "Invalid sCAL width ignored");
491

492 493
   else if (height <= 0)
      png_warning(png_ptr, "Invalid sCAL height ignored");
494

495 496 497 498 499 500 501 502 503 504 505 506
   else
   {
      /* Convert 'width' and 'height' to ASCII. */
      char swidth[PNG_sCAL_MAX_DIGITS+1];
      char sheight[PNG_sCAL_MAX_DIGITS+1];

      png_ascii_from_fixed(png_ptr, swidth, sizeof swidth, width);
      png_ascii_from_fixed(png_ptr, sheight, sizeof sheight, height);

      png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight);
   }
}
507
#  endif
508
#endif
509

510
#ifdef PNG_pHYs_SUPPORTED
511
void PNGAPI
512
png_set_pHYs(png_const_structrp png_ptr, png_inforp info_ptr,
513
    png_uint_32 res_x, png_uint_32 res_y, int unit_type)
A
Andreas Dilger 已提交
514
{
515
   png_debug1(1, "in %s storage function", "pHYs");
516

517
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
518 519 520 521 522 523 524 525 526
      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

527
void PNGAPI
528
png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr,
529
    png_const_colorp palette, int num_palette)
A
Andreas Dilger 已提交
530
{
531

532
   png_debug1(1, "in %s storage function", "PLTE");
533

534
   if (png_ptr == NULL || info_ptr == NULL || palette == NULL)
A
Andreas Dilger 已提交
535 536
      return;

537
   if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH)
538 539
   {
      if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
540
         png_error(png_ptr, "Invalid palette length");
541

542 543
      else
      {
544 545
         png_warning(png_ptr, "Invalid palette length");
         return;
546 547
      }
   }
548

549
   /* It may not actually be necessary to set png_ptr->palette here;
550 551
    * we do it for backward compatibility with the way the png_handle_tRNS
    * function used to do the allocation.
552 553 554
    *
    * 1.6.0: the above statement appears to be incorrect; something has to set
    * the palette inside png_struct on read.
555 556
    */
   png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0);
557

558
   /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead
559 560 561
    * of num_palette entries, in case of an invalid PNG file that has
    * too-large sample values.
    */
562 563
   png_ptr->palette = png_voidcast(png_colorp, png_calloc(png_ptr,
       PNG_MAX_PALETTE_LENGTH * png_sizeof(png_color)));
564

565
   png_memcpy(png_ptr->palette, palette, num_palette * png_sizeof(png_color));
566 567 568 569
   info_ptr->palette = png_ptr->palette;
   info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette;

   info_ptr->free_me |= PNG_FREE_PLTE;
570

571
   info_ptr->valid |= PNG_INFO_PLTE;
A
Andreas Dilger 已提交
572 573
}

574
#ifdef PNG_sBIT_SUPPORTED
575
void PNGAPI
576
png_set_sBIT(png_const_structrp png_ptr, png_inforp info_ptr,
577
    png_const_color_8p sig_bit)
A
Andreas Dilger 已提交
578
{
579
   png_debug1(1, "in %s storage function", "sBIT");
580

581
   if (png_ptr == NULL || info_ptr == NULL || sig_bit == NULL)
A
Andreas Dilger 已提交
582 583
      return;

584
   info_ptr->sig_bit = *sig_bit;
A
Andreas Dilger 已提交
585 586 587 588
   info_ptr->valid |= PNG_INFO_sBIT;
}
#endif

589
#ifdef PNG_sRGB_SUPPORTED
590
void PNGAPI
591
png_set_sRGB(png_const_structrp png_ptr, png_inforp info_ptr, int srgb_intent)
592
{
593
   png_debug1(1, "in %s storage function", "sRGB");
594

595
   if (png_ptr == NULL || info_ptr == NULL)
596 597
      return;

598 599 600 601
   (void)png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace, srgb_intent,
      2/* app value overrides*/);

   png_colorspace_sync_info(png_ptr, info_ptr);
602
}
603

604
void PNGAPI
605
png_set_sRGB_gAMA_and_cHRM(png_const_structrp png_ptr, png_inforp info_ptr,
606
    int srgb_intent)
607
{
608
   png_debug1(1, "in %s storage function", "sRGB_gAMA_and_cHRM");
609

610
   if (png_ptr == NULL || info_ptr == NULL)
611 612
      return;

613 614 615 616 617 618 619
   if (png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace, srgb_intent,
      2/* app value overrides*/))
   {
      /* And cause the gAMA and cHRM to be written too */
      info_ptr->colorspace.flags |=
         PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM;
   }
620

621
   png_colorspace_sync_info(png_ptr, info_ptr);
622
}
623
#endif /* sRGB */
624

625

626
#ifdef PNG_iCCP_SUPPORTED
627
void PNGAPI
628
png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr,
629 630
    png_const_charp name, int compression_type,
    png_const_bytep profile, png_uint_32 proflen)
631
{
632
   png_charp new_iccp_name;
G
[devel]  
Glenn Randers-Pehrson 已提交
633
   png_bytep new_iccp_profile;
634
   png_size_t length;
635

636
   png_debug1(1, "in %s storage function", "iCCP");
637

638 639 640
   if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL)
      return;

641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662
   if (compression_type != PNG_COMPRESSION_TYPE_BASE)
      png_app_error(png_ptr, "Invalid iCCP compression method");

   /* Set the colorspace first because this validates the profile; do not
    * override previously set app cHRM or gAMA here (because likely as not the
    * application knows better than libpng what the correct values are.)
    */
   {
      int result = png_colorspace_set_ICC(png_ptr, &info_ptr->colorspace, name,
         proflen, profile, 0/* do *not* override the app cHRM or gAMA */);

      png_colorspace_sync_info(png_ptr, info_ptr);

      /* Don't do any of the copying if the profile was bad, or inconsistent. */
      if (!result)
         return;

      /* But do write the gAMA and cHRM chunks from the profile. */
      info_ptr->colorspace.flags |=
         PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM;
   }

663
   length = png_strlen(name)+1;
664
   new_iccp_name = png_voidcast(png_charp, png_malloc_warn(png_ptr, length));
665

666 667
   if (new_iccp_name == NULL)
   {
668
      png_benign_error(png_ptr, "Insufficient memory to process iCCP chunk");
669 670
      return;
   }
671

672
   png_memcpy(new_iccp_name, name, length);
673 674
   new_iccp_profile = png_voidcast(png_bytep,
      png_malloc_warn(png_ptr, proflen));
675

676 677
   if (new_iccp_profile == NULL)
   {
678 679
      png_free(png_ptr, new_iccp_name);
      png_benign_error(png_ptr,
680
          "Insufficient memory to process iCCP profile");
681 682
      return;
   }
683

684
   png_memcpy(new_iccp_profile, profile, proflen);
685

686
   png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0);
687

688
   info_ptr->iccp_proflen = proflen;
689 690
   info_ptr->iccp_name = new_iccp_name;
   info_ptr->iccp_profile = new_iccp_profile;
691
   info_ptr->free_me |= PNG_FREE_ICCP;
692 693 694 695
   info_ptr->valid |= PNG_INFO_iCCP;
}
#endif

696
#ifdef PNG_TEXT_SUPPORTED
697
void PNGAPI
698 699
png_set_text(png_const_structrp png_ptr, png_inforp info_ptr,
    png_const_textp text_ptr, int num_text)
700 701
{
   int ret;
702
   ret = png_set_text_2(png_ptr, info_ptr, text_ptr, num_text);
703

704
   if (ret)
705
      png_error(png_ptr, "Insufficient memory to store text");
706 707 708
}

int /* PRIVATE */
709
png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr,
710
    png_const_textp text_ptr, int num_text)
A
Andreas Dilger 已提交
711 712 713
{
   int i;

714 715
   png_debug1(1, "in %lx storage function", png_ptr == NULL ? "unexpected" :
      (unsigned long)png_ptr->chunk_name);
A
Andreas Dilger 已提交
716

717
   if (png_ptr == NULL || info_ptr == NULL || num_text == 0)
718
      return(0);
A
Andreas Dilger 已提交
719 720 721 722 723 724

   /* 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)
   {
725 726 727
      int old_max_text = info_ptr->max_text;
      int old_num_text = info_ptr->num_text;

A
Andreas Dilger 已提交
728 729 730 731 732 733
      if (info_ptr->text != NULL)
      {
         png_textp old_text;

         info_ptr->max_text = info_ptr->num_text + num_text + 8;
         old_text = info_ptr->text;
734

735
         info_ptr->text = (png_textp)png_malloc_warn(png_ptr,
736
            (png_size_t)(info_ptr->max_text * png_sizeof(png_text)));
737

738
         if (info_ptr->text == NULL)
739
         {
740 741 742
            /* Restore to previous condition */
            info_ptr->max_text = old_max_text;
            info_ptr->text = old_text;
743 744
            return(1);
         }
745

746
         png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max_text *
747
             png_sizeof(png_text)));
A
Andreas Dilger 已提交
748 749
         png_free(png_ptr, old_text);
      }
750

A
Andreas Dilger 已提交
751 752 753 754
      else
      {
         info_ptr->max_text = num_text + 8;
         info_ptr->num_text = 0;
755
         info_ptr->text = (png_textp)png_malloc_warn(png_ptr,
756
             (png_size_t)(info_ptr->max_text * png_sizeof(png_text)));
757
         if (info_ptr->text == NULL)
758 759 760 761
         {
            /* Restore to previous condition */
            info_ptr->num_text = old_num_text;
            info_ptr->max_text = old_max_text;
762
            return(1);
763
         }
764
         info_ptr->free_me |= PNG_FREE_TEXT;
A
Andreas Dilger 已提交
765
      }
766

767
      png_debug1(3, "allocated %d entries for info_ptr->text",
768
          info_ptr->max_text);
A
Andreas Dilger 已提交
769 770 771
   }
   for (i = 0; i < num_text; i++)
   {
772 773
      png_size_t text_length, key_len;
      png_size_t lang_len, lang_key_len;
A
Andreas Dilger 已提交
774 775
      png_textp textp = &(info_ptr->text[info_ptr->num_text]);

776
      if (text_ptr[i].key == NULL)
777 778
          continue;

779 780
      if (text_ptr[i].compression < PNG_TEXT_COMPRESSION_NONE ||
          text_ptr[i].compression >= PNG_TEXT_COMPRESSION_LAST)
781 782 783 784 785
      {
         png_warning(png_ptr, "text compression mode is out of range");
         continue;
      }

786 787
      key_len = png_strlen(text_ptr[i].key);

788
      if (text_ptr[i].compression <= 0)
789
      {
790 791
         lang_len = 0;
         lang_key_len = 0;
792
      }
793

794
      else
795
#  ifdef PNG_iTXt_SUPPORTED
796
      {
797
         /* Set iTXt data */
798

799 800
         if (text_ptr[i].lang != NULL)
            lang_len = png_strlen(text_ptr[i].lang);
801

802 803
         else
            lang_len = 0;
804

805 806
         if (text_ptr[i].lang_key != NULL)
            lang_key_len = png_strlen(text_ptr[i].lang_key);
807

808 809
         else
            lang_key_len = 0;
810
      }
811
#  else /* PNG_iTXt_SUPPORTED */
812
      {
813 814
         png_warning(png_ptr, "iTXt chunk not supported");
         continue;
815
      }
816
#  endif
A
Andreas Dilger 已提交
817

818
      if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0')
A
Andreas Dilger 已提交
819
      {
820
         text_length = 0;
821
#  ifdef PNG_iTXt_SUPPORTED
822
         if (text_ptr[i].compression > 0)
823
            textp->compression = PNG_ITXT_COMPRESSION_NONE;
824

825
         else
826
#  endif
827
            textp->compression = PNG_TEXT_COMPRESSION_NONE;
A
Andreas Dilger 已提交
828
      }
829

A
Andreas Dilger 已提交
830 831
      else
      {
832
         text_length = png_strlen(text_ptr[i].text);
A
Andreas Dilger 已提交
833 834
         textp->compression = text_ptr[i].compression;
      }
835

836
      textp->key = (png_charp)png_malloc_warn(png_ptr,
837 838
          (png_size_t)
          (key_len + text_length + lang_len + lang_key_len + 4));
839

840
      if (textp->key == NULL)
841
         return(1);
842

843
      png_debug2(2, "Allocated %lu bytes at %p in png_set_text",
844 845
          (unsigned long)(png_uint_32)
          (key_len + lang_len + lang_key_len + text_length + 4),
846
          textp->key);
847

848
      png_memcpy(textp->key, text_ptr[i].key,(png_size_t)(key_len));
849
      *(textp->key + key_len) = '\0';
850

851 852
      if (text_ptr[i].compression > 0)
      {
853
         textp->lang = textp->key + key_len + 1;
854
         png_memcpy(textp->lang, text_ptr[i].lang, lang_len);
855
         *(textp->lang + lang_len) = '\0';
856
         textp->lang_key = textp->lang + lang_len + 1;
857
         png_memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len);
858
         *(textp->lang_key + lang_key_len) = '\0';
859
         textp->text = textp->lang_key + lang_key_len + 1;
860
      }
861

862 863
      else
      {
864 865
         textp->lang=NULL;
         textp->lang_key=NULL;
866
         textp->text = textp->key + key_len + 1;
867
      }
868

869
      if (text_length)
870
         png_memcpy(textp->text, text_ptr[i].text,
871
             (png_size_t)(text_length));
872

873
      *(textp->text + text_length) = '\0';
874

875
#  ifdef PNG_iTXt_SUPPORTED
876
      if (textp->compression > 0)
877 878 879 880
      {
         textp->text_length = 0;
         textp->itxt_length = text_length;
      }
881

882
      else
883
#  endif
884 885 886 887
      {
         textp->text_length = text_length;
         textp->itxt_length = 0;
      }
888

A
Andreas Dilger 已提交
889
      info_ptr->num_text++;
890
      png_debug1(3, "transferred text chunk %d", info_ptr->num_text);
A
Andreas Dilger 已提交
891
   }
892
   return(0);
A
Andreas Dilger 已提交
893 894 895
}
#endif

896
#ifdef PNG_tIME_SUPPORTED
897
void PNGAPI
898 899
png_set_tIME(png_const_structrp png_ptr, png_inforp info_ptr,
    png_const_timep mod_time)
A
Andreas Dilger 已提交
900
{
901
   png_debug1(1, "in %s storage function", "tIME");
902

903
   if (png_ptr == NULL || info_ptr == NULL || mod_time == NULL ||
904
       (png_ptr->mode & PNG_WROTE_tIME))
A
Andreas Dilger 已提交
905 906
      return;

907 908 909 910 911 912 913 914 915
   if (mod_time->month == 0   || mod_time->month > 12  ||
       mod_time->day   == 0   || mod_time->day   > 31  ||
       mod_time->hour  > 23   || mod_time->minute > 59 ||
       mod_time->second > 60)
   {
      png_warning(png_ptr, "Ignoring invalid time value");
      return;
   }

916
   info_ptr->mod_time = *mod_time;
A
Andreas Dilger 已提交
917 918 919 920
   info_ptr->valid |= PNG_INFO_tIME;
}
#endif

921
#ifdef PNG_tRNS_SUPPORTED
922
void PNGAPI
923
png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr,
924
    png_const_bytep trans_alpha, int num_trans, png_const_color_16p trans_color)
A
Andreas Dilger 已提交
925
{
926
   png_debug1(1, "in %s storage function", "tRNS");
927

928
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
929 930
      return;

931
   if (trans_alpha != NULL)
932
   {
933
       /* It may not actually be necessary to set png_ptr->trans_alpha here;
934 935
        * we do it for backward compatibility with the way the png_handle_tRNS
        * function used to do the allocation.
936 937 938 939
        *
        * 1.6.0: The above statement is incorrect; png_handle_tRNS effectively
        * relies on png_set_tRNS storing the information in png_struct
        * (otherwise it won't be there for the code in pngrtran.c).
940
        */
941

942
       png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
943

944
       /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */
945 946
       png_ptr->trans_alpha = info_ptr->trans_alpha = png_voidcast(png_bytep,
         png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH));
947

948
       if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH)
949
          png_memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans);
950
   }
A
Andreas Dilger 已提交
951

952
   if (trans_color != NULL)
A
Andreas Dilger 已提交
953
   {
954
      int sample_max = (1 << info_ptr->bit_depth);
955

956
      if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY &&
957
          trans_color->gray > sample_max) ||
958
          (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
959 960 961
          (trans_color->red > sample_max ||
          trans_color->green > sample_max ||
          trans_color->blue > sample_max)))
962 963
         png_warning(png_ptr,
            "tRNS chunk has out-of-range samples for bit_depth");
964

965
      info_ptr->trans_color = *trans_color;
966

967
      if (num_trans == 0)
968
         num_trans = 1;
A
Andreas Dilger 已提交
969
   }
970

A
Andreas Dilger 已提交
971
   info_ptr->num_trans = (png_uint_16)num_trans;
972

973 974 975 976 977
   if (num_trans != 0)
   {
      info_ptr->valid |= PNG_INFO_tRNS;
      info_ptr->free_me |= PNG_FREE_TRNS;
   }
A
Andreas Dilger 已提交
978 979 980
}
#endif

981
#ifdef PNG_sPLT_SUPPORTED
982
void PNGAPI
983
png_set_sPLT(png_const_structrp png_ptr,
984
    png_inforp info_ptr, png_const_sPLT_tp entries, int nentries)
985 986 987 988
/*
 *  entries        - array of png_sPLT_t structures
 *                   to be added to the list of palettes
 *                   in the info structure.
989
 *
990 991 992
 *  nentries       - number of palette structures to be
 *                   added.
 */
993
{
994 995
   png_sPLT_tp np;
   int i;
996

997 998
   if (png_ptr == NULL || info_ptr == NULL || nentries <= 0 ||
      entries == NULL)
999
      return;
1000

1001 1002
   np = png_voidcast(png_sPLT_tp, png_malloc_warn(png_ptr,
       (info_ptr->splt_palettes_num + nentries) * png_sizeof(png_sPLT_t)));
1003

1004 1005
   if (np == NULL)
   {
1006
      png_warning(png_ptr, "No memory for sPLT palettes");
1007
      return;
1008
   }
1009

1010
   png_memcpy(np, info_ptr->splt_palettes,
1011
       info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t));
1012

1013 1014
   png_free(png_ptr, info_ptr->splt_palettes);
   info_ptr->splt_palettes=NULL;
1015

1016 1017 1018
   /* TODO: fix this, it apparently leaves NULL entries in the event of OOM
    * below.
    */
1019 1020 1021
   for (i = 0; i < nentries; i++)
   {
      png_sPLT_tp to = np + info_ptr->splt_palettes_num + i;
1022
      png_const_sPLT_tp from = entries + i;
1023
      png_size_t length;
1024

1025 1026 1027 1028 1029 1030 1031 1032 1033
      /* In event of error below the name and entries fields must be set to
       * NULL, otherwise libpng will crash later on while trying to free the
       * uninitialized pointers.
       */
      png_memset(to, 0, sizeof *to);

      if (from->name == NULL || from->entries == NULL)
         continue;

1034
      length = png_strlen(from->name) + 1;
1035
      to->name = png_voidcast(png_charp, png_malloc_warn(png_ptr, length));
1036

1037 1038 1039
      if (to->name == NULL)
      {
         png_warning(png_ptr,
1040
             "Out of memory while processing sPLT chunk");
1041 1042
         continue;
      }
1043

1044
      png_memcpy(to->name, from->name, length);
1045 1046
      to->entries = png_voidcast(png_sPLT_entryp, png_malloc_warn(png_ptr,
          from->nentries * png_sizeof(png_sPLT_entry)));
1047

1048 1049
      if (to->entries == NULL)
      {
1050
         png_warning(png_ptr, "Out of memory while processing sPLT chunk");
1051 1052 1053 1054
         png_free(png_ptr, to->name);
         to->name = NULL;
         continue;
      }
1055

1056 1057
      png_memcpy(to->entries, from->entries,
          from->nentries * png_sizeof(png_sPLT_entry));
1058

1059 1060 1061 1062 1063 1064 1065 1066
      to->nentries = from->nentries;
      to->depth = from->depth;
   }

   info_ptr->splt_palettes = np;
   info_ptr->splt_palettes_num += nentries;
   info_ptr->valid |= PNG_INFO_sPLT;
   info_ptr->free_me |= PNG_FREE_SPLT;
1067 1068 1069
}
#endif /* PNG_sPLT_SUPPORTED */

1070
#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
1071
void PNGAPI
1072
png_set_unknown_chunks(png_const_structrp png_ptr,
1073
   png_inforp info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns)
1074
{
1075 1076 1077 1078
   png_unknown_chunkp np;
   int i;

   if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0)
1079
      return;
1080

1081
   np = png_voidcast(png_unknown_chunkp, png_malloc_warn(png_ptr,
1082
       (png_size_t)(info_ptr->unknown_chunks_num + num_unknowns) *
1083
       png_sizeof(png_unknown_chunk)));
1084

1085 1086 1087
   if (np == NULL)
   {
      png_warning(png_ptr,
1088
          "Out of memory while processing unknown chunk");
1089 1090 1091 1092
      return;
   }

   png_memcpy(np, info_ptr->unknown_chunks,
1093 1094
       (png_size_t)info_ptr->unknown_chunks_num *
       png_sizeof(png_unknown_chunk));
1095

1096
   png_free(png_ptr, info_ptr->unknown_chunks);
1097
   info_ptr->unknown_chunks = NULL;
1098 1099 1100 1101

   for (i = 0; i < num_unknowns; i++)
   {
      png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i;
1102
      png_const_unknown_chunkp from = unknowns + i;
1103

1104
      png_memcpy(to->name, from->name, png_sizeof(from->name));
1105 1106
      to->name[png_sizeof(to->name)-1] = '\0';
      to->size = from->size;
1107

1108
      /* Note our location in the read or write sequence */
1109
      to->location = (png_byte)png_ptr->mode;
1110 1111 1112

      if (from->size == 0)
         to->data=NULL;
1113

1114 1115 1116
      else
      {
         to->data = (png_bytep)png_malloc_warn(png_ptr,
1117
             (png_size_t)from->size);
1118

1119 1120 1121
         if (to->data == NULL)
         {
            png_warning(png_ptr,
1122
                "Out of memory while processing unknown chunk");
1123 1124
            to->size = 0;
         }
1125

1126 1127 1128 1129 1130 1131 1132 1133
         else
            png_memcpy(to->data, from->data, from->size);
      }
   }

   info_ptr->unknown_chunks = np;
   info_ptr->unknown_chunks_num += num_unknowns;
   info_ptr->free_me |= PNG_FREE_UNKN;
1134
}
1135

1136
void PNGAPI
1137
png_set_unknown_chunk_location(png_const_structrp png_ptr, png_inforp info_ptr,
1138
    int chunk, int location)
1139
{
1140
   if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 && chunk <
1141
       info_ptr->unknown_chunks_num)
1142 1143
      info_ptr->unknown_chunks[chunk].location = (png_byte)location;
}
1144 1145
#endif

1146

1147
#ifdef PNG_MNG_FEATURES_SUPPORTED
1148
png_uint_32 PNGAPI
1149
png_permit_mng_features (png_structrp png_ptr, png_uint_32 mng_features)
1150
{
1151
   png_debug(1, "in png_permit_mng_features");
1152

1153
   if (png_ptr == NULL)
1154
      return 0;
1155

1156
   png_ptr->mng_features_permitted = mng_features & PNG_ALL_MNG_FEATURES;
1157

1158
   return png_ptr->mng_features_permitted;
1159 1160
}
#endif
1161

1162
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
1163
void PNGAPI
1164
png_set_keep_unknown_chunks(png_structrp png_ptr, int keep,
1165
    png_const_bytep chunk_list, int num_chunksIn)
1166
{
1167
   png_bytep new_list, p;
1168
   unsigned int i, num_chunks, old_num_chunks;
1169 1170
   if (png_ptr == NULL)
      return;
1171

1172
   if (num_chunksIn <= 0)
1173
   {
1174
      if (keep == PNG_HANDLE_CHUNK_ALWAYS || keep == PNG_HANDLE_CHUNK_IF_SAFE)
1175
         png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
1176

1177
      else
1178
         png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
1179

1180
      if (keep == PNG_HANDLE_CHUNK_ALWAYS)
1181
         png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS;
1182

1183
      else
1184
         png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS;
1185

1186
      return;
1187
   }
1188

1189
   if (chunk_list == NULL)
1190
      return;
1191

1192 1193 1194
   /* The argument is >0 */
   num_chunks = (unsigned int)num_chunksIn;

1195
   old_num_chunks = png_ptr->num_chunk_list;
1196 1197
   new_list = png_voidcast(png_bytep, png_malloc(png_ptr,
       5 * (num_chunks + old_num_chunks)));
1198

1199 1200
   if (png_ptr->chunk_list != NULL)
   {
1201
      png_memcpy(new_list, png_ptr->chunk_list, 5*old_num_chunks);
1202 1203 1204
      png_free(png_ptr, png_ptr->chunk_list);
      png_ptr->chunk_list=NULL;
   }
1205

1206 1207
   png_memcpy(new_list + 5*old_num_chunks, chunk_list,
      5*(unsigned int)num_chunks);
1208

1209 1210
   for (p = new_list + 5*old_num_chunks + 4, i = 0; i<num_chunks; i++, p += 5)
      *p=(png_byte)keep;
1211

1212 1213 1214
   png_ptr->num_chunk_list = old_num_chunks + num_chunks;
   png_ptr->chunk_list = new_list;
   png_ptr->free_me |= PNG_FREE_LIST;
1215 1216
}
#endif
1217

1218
#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
1219
void PNGAPI
1220
png_set_read_user_chunk_fn(png_structrp png_ptr, png_voidp user_chunk_ptr,
1221
    png_user_chunk_ptr read_user_chunk_fn)
1222
{
1223
   png_debug(1, "in png_set_read_user_chunk_fn");
1224

1225 1226
   if (png_ptr == NULL)
      return;
1227

1228 1229 1230 1231
   png_ptr->read_user_chunk_fn = read_user_chunk_fn;
   png_ptr->user_chunk_ptr = user_chunk_ptr;
}
#endif
1232

1233
#ifdef PNG_INFO_IMAGE_SUPPORTED
1234
void PNGAPI
1235 1236
png_set_rows(png_const_structrp png_ptr, png_inforp info_ptr,
    png_bytepp row_pointers)
1237
{
1238
   png_debug1(1, "in %s storage function", "rows");
1239

1240 1241 1242
   if (png_ptr == NULL || info_ptr == NULL)
      return;

1243
   if (info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers))
1244
      png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
1245

1246
   info_ptr->row_pointers = row_pointers;
1247

1248
   if (row_pointers)
1249
      info_ptr->valid |= PNG_INFO_IDAT;
1250 1251 1252
}
#endif

1253
void PNGAPI
1254
png_set_compression_buffer_size(png_structrp png_ptr, png_size_t size)
1255
{
1256 1257
    if (png_ptr == NULL)
       return;
1258

1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303
    if (size == 0 || size > PNG_UINT_31_MAX)
       png_error(png_ptr, "invalid compression buffer size");

#  ifdef PNG_SEQUENTIAL_READ_SUPPORTED
      if (png_ptr->mode & PNG_IS_READ_STRUCT)
      {
         png_ptr->IDAT_read_size = (png_uint_32)size; /* checked above */
         return;
      }
#  endif

#  ifdef PNG_WRITE_SUPPORTED
      if (!(png_ptr->mode & PNG_IS_READ_STRUCT))
      {
         if (png_ptr->zowner != 0)
         {
            png_warning(png_ptr,
              "Compression buffer size cannot be changed because it is in use");
            return;
         }
  
         if (size > ZLIB_IO_MAX)
         {
            png_warning(png_ptr,
               "Compression buffer size limited to system maximum");
            size = ZLIB_IO_MAX; /* must fit */
         }
  
         else if (size < 6)
         {
            /* Deflate will potentially go into an infinite loop on a SYNC_FLUSH
             * if this is permitted.
             */
            png_warning(png_ptr,
               "Compression buffer size cannot be reduced below 6");
            return;
         }
  
         if (png_ptr->zbuffer_size != size)
         {
            png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list);
            png_ptr->zbuffer_size = (uInt)size;
         }
      }
#  endif
1304
}
1305 1306

void PNGAPI
1307
png_set_invalid(png_const_structrp png_ptr, png_inforp info_ptr, int mask)
1308 1309
{
   if (png_ptr && info_ptr)
1310
      info_ptr->valid &= ~mask;
1311
}
1312

1313

1314
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
1315
/* This function was added to libpng 1.2.6 */
1316
void PNGAPI
1317
png_set_user_limits (png_structrp png_ptr, png_uint_32 user_width_max,
1318 1319
    png_uint_32 user_height_max)
{
1320 1321 1322 1323 1324 1325
   /* Images with dimensions larger than these limits will be
    * rejected by png_set_IHDR().  To accept any PNG datastream
    * regardless of dimensions, set both limits to 0x7ffffffL.
    */
   if (png_ptr == NULL)
      return;
1326

1327 1328
   png_ptr->user_width_max = user_width_max;
   png_ptr->user_height_max = user_height_max;
1329
}
1330

1331
/* This function was added to libpng 1.4.0 */
1332
void PNGAPI
1333
png_set_chunk_cache_max (png_structrp png_ptr, png_uint_32 user_chunk_cache_max)
1334
{
1335 1336 1337 1338 1339 1340
    if (png_ptr)
       png_ptr->user_chunk_cache_max = user_chunk_cache_max;
}

/* This function was added to libpng 1.4.1 */
void PNGAPI
1341
png_set_chunk_malloc_max (png_structrp png_ptr,
1342
    png_alloc_size_t user_chunk_malloc_max)
1343
{
1344 1345
   if (png_ptr)
      png_ptr->user_chunk_malloc_max = user_chunk_malloc_max;
1346
}
1347 1348
#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */

1349

1350
#ifdef PNG_BENIGN_ERRORS_SUPPORTED
1351
void PNGAPI
1352
png_set_benign_errors(png_structrp png_ptr, int allowed)
1353
{
1354
   png_debug(1, "in png_set_benign_errors");
1355

1356 1357 1358 1359 1360 1361
   /* If allowed is 1, png_benign_error() is treated as a warning.
    *
    * If allowed is 0, png_benign_error() is treated as an error (which
    * is the default behavior if png_set_benign_errors() is not called).
    */

1362
   if (allowed)
1363 1364
      png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN |
         PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN;
1365

1366
   else
1367 1368
      png_ptr->flags &= ~(PNG_FLAG_BENIGN_ERRORS_WARN |
         PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN);
1369 1370
}
#endif /* PNG_BENIGN_ERRORS_SUPPORTED */
1371

1372
#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
1373 1374 1375 1376 1377 1378
   /* Do not report invalid palette index; added at libng-1.5.10 */
void PNGAPI
png_set_check_for_invalid_index(png_structrp png_ptr, int allowed)
{
   png_debug(1, "in png_set_check_for_invalid_index");

1379
   if (allowed > 0)
1380 1381 1382 1383 1384 1385 1386
      png_ptr->num_palette_max = 0;

   else
      png_ptr->num_palette_max = -1;
}
#endif

1387
#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */