pngset.c 37.7 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
   png_debug1(1, "in %s storage function", "cHRM fixed");
46

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

50
#  ifdef PNG_CHECK_cHRM_SUPPORTED
51
   if (png_check_cHRM_fixed(png_ptr,
52
       white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y))
53
#  endif
54
   {
G
[devel]  
Glenn Randers-Pehrson 已提交
55 56 57 58 59 60 61 62
      info_ptr->x_white = white_x;
      info_ptr->y_white = white_y;
      info_ptr->x_red   = red_x;
      info_ptr->y_red   = red_y;
      info_ptr->x_green = green_x;
      info_ptr->y_green = green_y;
      info_ptr->x_blue  = blue_x;
      info_ptr->y_blue  = blue_y;
63
      info_ptr->valid |= PNG_INFO_cHRM;
64
   }
65 66
}

67
void PNGFAPI
68
png_set_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
    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_xy xy;

   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;

   if (png_xy_from_XYZ(&xy, XYZ))
      png_error(png_ptr, "XYZ values out of representable range");

   png_set_cHRM_fixed(png_ptr, info_ptr, xy.whitex, xy.whitey, xy.redx, xy.redy,
      xy.greenx, xy.greeny, xy.bluex, xy.bluey);
}

100
#  ifdef PNG_FLOATING_POINT_SUPPORTED
101
void PNGAPI
102
png_set_cHRM(png_const_structrp png_ptr, png_inforp info_ptr,
G
[devel]  
Glenn Randers-Pehrson 已提交
103 104
    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 已提交
105
{
G
[devel]  
Glenn Randers-Pehrson 已提交
106 107 108 109 110 111 112 113 114 115
   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"));
}
116 117

void PNGAPI
118
png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp info_ptr, double red_X,
119 120 121 122 123 124 125 126 127 128 129 130 131 132
    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"));
}
133
#  endif /* PNG_FLOATING_POINT_SUPPORTED */
134

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

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

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

147 148 149 150 151
   /* 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
152
    * 6250.0, which are truly ridiculous gammma values (and will produce
153
    * displays that are all black or all white.)
G
[devel]  
Glenn Randers-Pehrson 已提交
154
    */
155 156
   if (file_gamma < 16 || file_gamma > 625000000)
      png_warning(png_ptr, "Out of range gamma value ignored");
157

158 159
   else
   {
160
      info_ptr->gamma = file_gamma;
G
[devel]  
Glenn Randers-Pehrson 已提交
161
      info_ptr->valid |= PNG_INFO_gAMA;
162
   }
G
[devel]  
Glenn Randers-Pehrson 已提交
163
}
164

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

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

182
   png_debug1(1, "in %s storage function", "hIST");
183

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

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

193
      return;
194
   }
195 196

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

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

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

210 211
   info_ptr->free_me |= PNG_FREE_HIST;

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

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

219
void PNGAPI
220
png_set_IHDR(png_const_structrp png_ptr, png_inforp info_ptr,
221 222 223
    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 已提交
224
{
225
   png_debug1(1, "in %s storage function", "IHDR");
226

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

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

   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);

242 243
   if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
      info_ptr->channels = 1;
244

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

A
Andreas Dilger 已提交
248 249
   else
      info_ptr->channels = 1;
250

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

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

256
   /* Check for potential overflow */
257 258 259 260 261 262
   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 */
263
      info_ptr->rowbytes = 0;
264
   else
265
      info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width);
A
Andreas Dilger 已提交
266 267
}

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

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

285
#ifdef PNG_pCAL_SUPPORTED
286
void PNGAPI
287
png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr,
288 289
    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 已提交
290
{
291
   png_size_t length;
292
   int i;
A
Andreas Dilger 已提交
293

294
   png_debug1(1, "in %s storage function", "pCAL");
295

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

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

G
[devel]  
Glenn Randers-Pehrson 已提交
304 305 306 307 308 309
   /* 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");

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

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

319 320
   info_ptr->pcal_purpose = png_voidcast(png_charp,
      png_malloc_warn(png_ptr, length));
321

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

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

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

340 341
   info_ptr->pcal_units = png_voidcast(png_charp,
      png_malloc_warn(png_ptr, length));
342

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

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

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

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

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

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

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

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

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

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

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

391
   png_debug1(1, "in %s storage function", "sCAL");
392

393 394 395
   if (png_ptr == NULL || info_ptr == NULL)
      return;

G
[devel]  
Glenn Randers-Pehrson 已提交
396 397 398 399 400 401
   /* 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");

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

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

410
   info_ptr->scal_unit = (png_byte)unit;
411

G
[devel]  
Glenn Randers-Pehrson 已提交
412
   ++lengthw;
413

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

416 417
   info_ptr->scal_s_width = png_voidcast(png_charp,
      png_malloc_warn(png_ptr, lengthw));
418

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

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

G
[devel]  
Glenn Randers-Pehrson 已提交
427
   ++lengthh;
428

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

431 432
   info_ptr->scal_s_height = png_voidcast(png_charp,
      png_malloc_warn(png_ptr, lengthh));
433

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

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

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

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

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

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

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

G
[devel]  
Glenn Randers-Pehrson 已提交
463 464 465 466 467 468 469 470 471 472 473 474 475 476
   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);
   }
}
477
#  endif
478

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

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

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

493 494 495 496 497 498 499 500 501 502 503 504
   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);
   }
}
505
#  endif
506
#endif
507

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

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

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

530
   png_debug1(1, "in %s storage function", "PLTE");
531

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

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

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

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

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

563
   png_memcpy(png_ptr->palette, palette, num_palette * png_sizeof(png_color));
564 565 566 567
   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;
568

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

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

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

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

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

593
   if (png_ptr == NULL || info_ptr == NULL)
594 595
      return;

596
   info_ptr->srgb_intent = (png_byte)srgb_intent;
597 598
   info_ptr->valid |= PNG_INFO_sRGB;
}
599

600
void PNGAPI
601
png_set_sRGB_gAMA_and_cHRM(png_const_structrp png_ptr, png_inforp info_ptr,
602
    int srgb_intent)
603
{
604
   png_debug1(1, "in %s storage function", "sRGB_gAMA_and_cHRM");
605

606
   if (png_ptr == NULL || info_ptr == NULL)
607 608
      return;

609
   png_set_sRGB(png_ptr, info_ptr, srgb_intent);
610

611
#  ifdef PNG_gAMA_SUPPORTED
612
   png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE);
613
#  endif
614

615
#  ifdef PNG_cHRM_SUPPORTED
616
   png_set_cHRM_fixed(png_ptr, info_ptr,
617
      /* color      x       y */
618 619 620 621
      /* white */ 31270, 32900,
      /* red   */ 64000, 33000,
      /* green */ 30000, 60000,
      /* blue  */ 15000,  6000
622
   );
623
#  endif /* cHRM */
624
}
625
#endif /* sRGB */
626

627

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

638
   png_debug1(1, "in %s storage function", "iCCP");
639

640 641 642
   if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL)
      return;

643
   length = png_strlen(name)+1;
644
   new_iccp_name = png_voidcast(png_charp, png_malloc_warn(png_ptr, length));
645

646 647
   if (new_iccp_name == NULL)
   {
648
      png_warning(png_ptr, "Insufficient memory to process iCCP chunk");
649 650
      return;
   }
651

652
   png_memcpy(new_iccp_name, name, length);
653 654
   new_iccp_profile = png_voidcast(png_bytep,
      png_malloc_warn(png_ptr, proflen));
655

656 657 658
   if (new_iccp_profile == NULL)
   {
      png_free (png_ptr, new_iccp_name);
659
      png_warning(png_ptr,
660
          "Insufficient memory to process iCCP profile");
661 662
      return;
   }
663

664
   png_memcpy(new_iccp_profile, profile, proflen);
665

666
   png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0);
667

668
   info_ptr->iccp_proflen = proflen;
669 670
   info_ptr->iccp_name = new_iccp_name;
   info_ptr->iccp_profile = new_iccp_profile;
671
   /* Compression is always zero but is here so the API and info structure
672 673
    * does not have to change if we introduce multiple compression types
    */
674
   info_ptr->iccp_compression = (png_byte)compression_type;
675
   info_ptr->free_me |= PNG_FREE_ICCP;
676 677 678 679
   info_ptr->valid |= PNG_INFO_iCCP;
}
#endif

680
#ifdef PNG_TEXT_SUPPORTED
681
void PNGAPI
682 683
png_set_text(png_const_structrp png_ptr, png_inforp info_ptr,
    png_const_textp text_ptr, int num_text)
684 685
{
   int ret;
686
   ret = png_set_text_2(png_ptr, info_ptr, text_ptr, num_text);
687

688
   if (ret)
689
      png_error(png_ptr, "Insufficient memory to store text");
690 691 692
}

int /* PRIVATE */
693
png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr,
694
    png_const_textp text_ptr, int num_text)
A
Andreas Dilger 已提交
695 696 697
{
   int i;

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

701
   if (png_ptr == NULL || info_ptr == NULL || num_text == 0)
702
      return(0);
A
Andreas Dilger 已提交
703 704 705 706 707 708 709 710 711 712 713 714 715 716

   /* 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;
717
         info_ptr->text = (png_textp)png_malloc_warn(png_ptr,
718
            (png_size_t)(info_ptr->max_text * png_sizeof(png_text)));
719

720
         if (info_ptr->text == NULL)
721 722 723 724
         {
            png_free(png_ptr, old_text);
            return(1);
         }
725

726
         png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max *
727
             png_sizeof(png_text)));
A
Andreas Dilger 已提交
728 729
         png_free(png_ptr, old_text);
      }
730

A
Andreas Dilger 已提交
731 732 733 734
      else
      {
         info_ptr->max_text = num_text + 8;
         info_ptr->num_text = 0;
735
         info_ptr->text = (png_textp)png_malloc_warn(png_ptr,
736
             (png_size_t)(info_ptr->max_text * png_sizeof(png_text)));
737
         if (info_ptr->text == NULL)
738
            return(1);
739
         info_ptr->free_me |= PNG_FREE_TEXT;
A
Andreas Dilger 已提交
740
      }
741

742
      png_debug1(3, "allocated %d entries for info_ptr->text",
743
          info_ptr->max_text);
A
Andreas Dilger 已提交
744 745 746
   }
   for (i = 0; i < num_text; i++)
   {
747 748
      png_size_t text_length, key_len;
      png_size_t lang_len, lang_key_len;
A
Andreas Dilger 已提交
749 750
      png_textp textp = &(info_ptr->text[info_ptr->num_text]);

751
      if (text_ptr[i].key == NULL)
752 753
          continue;

754 755
      if (text_ptr[i].compression < PNG_TEXT_COMPRESSION_NONE ||
          text_ptr[i].compression >= PNG_TEXT_COMPRESSION_LAST)
756 757 758 759 760
      {
         png_warning(png_ptr, "text compression mode is out of range");
         continue;
      }

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

763
      if (text_ptr[i].compression <= 0)
764
      {
765 766
         lang_len = 0;
         lang_key_len = 0;
767
      }
768

769
      else
770
#  ifdef PNG_iTXt_SUPPORTED
771
      {
772
         /* Set iTXt data */
773

774 775
         if (text_ptr[i].lang != NULL)
            lang_len = png_strlen(text_ptr[i].lang);
776

777 778
         else
            lang_len = 0;
779

780 781
         if (text_ptr[i].lang_key != NULL)
            lang_key_len = png_strlen(text_ptr[i].lang_key);
782

783 784
         else
            lang_key_len = 0;
785
      }
786
#  else /* PNG_iTXt_SUPPORTED */
787
      {
788 789
         png_warning(png_ptr, "iTXt chunk not supported");
         continue;
790
      }
791
#  endif
A
Andreas Dilger 已提交
792

793
      if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0')
A
Andreas Dilger 已提交
794
      {
795
         text_length = 0;
796
#  ifdef PNG_iTXt_SUPPORTED
797
         if (text_ptr[i].compression > 0)
798
            textp->compression = PNG_ITXT_COMPRESSION_NONE;
799

800
         else
801
#  endif
802
            textp->compression = PNG_TEXT_COMPRESSION_NONE;
A
Andreas Dilger 已提交
803
      }
804

A
Andreas Dilger 已提交
805 806
      else
      {
807
         text_length = png_strlen(text_ptr[i].text);
A
Andreas Dilger 已提交
808 809
         textp->compression = text_ptr[i].compression;
      }
810

811
      textp->key = (png_charp)png_malloc_warn(png_ptr,
812 813
          (png_size_t)
          (key_len + text_length + lang_len + lang_key_len + 4));
814

815
      if (textp->key == NULL)
816
         return(1);
817

818
      png_debug2(2, "Allocated %lu bytes at %p in png_set_text",
819 820
          (unsigned long)(png_uint_32)
          (key_len + lang_len + lang_key_len + text_length + 4),
821
          textp->key);
822

823
      png_memcpy(textp->key, text_ptr[i].key,(png_size_t)(key_len));
824
      *(textp->key + key_len) = '\0';
825

826 827
      if (text_ptr[i].compression > 0)
      {
828
         textp->lang = textp->key + key_len + 1;
829
         png_memcpy(textp->lang, text_ptr[i].lang, lang_len);
830
         *(textp->lang + lang_len) = '\0';
831
         textp->lang_key = textp->lang + lang_len + 1;
832
         png_memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len);
833
         *(textp->lang_key + lang_key_len) = '\0';
834
         textp->text = textp->lang_key + lang_key_len + 1;
835
      }
836

837 838
      else
      {
839 840
         textp->lang=NULL;
         textp->lang_key=NULL;
841
         textp->text = textp->key + key_len + 1;
842
      }
843

844
      if (text_length)
845
         png_memcpy(textp->text, text_ptr[i].text,
846
             (png_size_t)(text_length));
847

848
      *(textp->text + text_length) = '\0';
849

850
#  ifdef PNG_iTXt_SUPPORTED
851
      if (textp->compression > 0)
852 853 854 855
      {
         textp->text_length = 0;
         textp->itxt_length = text_length;
      }
856

857
      else
858
#  endif
859 860 861 862
      {
         textp->text_length = text_length;
         textp->itxt_length = 0;
      }
863

A
Andreas Dilger 已提交
864
      info_ptr->num_text++;
865
      png_debug1(3, "transferred text chunk %d", info_ptr->num_text);
A
Andreas Dilger 已提交
866
   }
867
   return(0);
A
Andreas Dilger 已提交
868 869 870
}
#endif

871
#ifdef PNG_tIME_SUPPORTED
872
void PNGAPI
873 874
png_set_tIME(png_const_structrp png_ptr, png_inforp info_ptr,
    png_const_timep mod_time)
A
Andreas Dilger 已提交
875
{
876
   png_debug1(1, "in %s storage function", "tIME");
877

878
   if (png_ptr == NULL || info_ptr == NULL || mod_time == NULL ||
879
       (png_ptr->mode & PNG_WROTE_tIME))
A
Andreas Dilger 已提交
880 881
      return;

882 883 884 885 886 887 888 889 890
   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;
   }

891
   info_ptr->mod_time = *mod_time;
A
Andreas Dilger 已提交
892 893 894 895
   info_ptr->valid |= PNG_INFO_tIME;
}
#endif

896
#ifdef PNG_tRNS_SUPPORTED
897
void PNGAPI
898
png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr,
899
    png_const_bytep trans_alpha, int num_trans, png_const_color_16p trans_color)
A
Andreas Dilger 已提交
900
{
901
   png_debug1(1, "in %s storage function", "tRNS");
902

903
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
904 905
      return;

906
   if (trans_alpha != NULL)
907
   {
908
       /* It may not actually be necessary to set png_ptr->trans_alpha here;
909 910
        * we do it for backward compatibility with the way the png_handle_tRNS
        * function used to do the allocation.
911 912 913 914
        *
        * 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).
915
        */
916

917
       png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
918

919
       /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */
920 921
       png_ptr->trans_alpha = info_ptr->trans_alpha = png_voidcast(png_bytep,
         png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH));
922

923
       if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH)
924
          png_memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans);
925
   }
A
Andreas Dilger 已提交
926

927
   if (trans_color != NULL)
A
Andreas Dilger 已提交
928
   {
929
      int sample_max = (1 << info_ptr->bit_depth);
930

931
      if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY &&
932
          trans_color->gray > sample_max) ||
933
          (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
934 935 936
          (trans_color->red > sample_max ||
          trans_color->green > sample_max ||
          trans_color->blue > sample_max)))
937 938
         png_warning(png_ptr,
            "tRNS chunk has out-of-range samples for bit_depth");
939

940
      info_ptr->trans_color = *trans_color;
941

942
      if (num_trans == 0)
943
         num_trans = 1;
A
Andreas Dilger 已提交
944
   }
945

A
Andreas Dilger 已提交
946
   info_ptr->num_trans = (png_uint_16)num_trans;
947

948 949 950 951 952
   if (num_trans != 0)
   {
      info_ptr->valid |= PNG_INFO_tRNS;
      info_ptr->free_me |= PNG_FREE_TRNS;
   }
A
Andreas Dilger 已提交
953 954 955
}
#endif

956
#ifdef PNG_sPLT_SUPPORTED
957
void PNGAPI
958
png_set_sPLT(png_const_structrp png_ptr,
959
    png_inforp info_ptr, png_const_sPLT_tp entries, int nentries)
960 961 962 963
/*
 *  entries        - array of png_sPLT_t structures
 *                   to be added to the list of palettes
 *                   in the info structure.
964
 *
965 966 967
 *  nentries       - number of palette structures to be
 *                   added.
 */
968
{
969 970
   png_sPLT_tp np;
   int i;
971

972 973
   if (png_ptr == NULL || info_ptr == NULL || nentries <= 0 ||
      entries == NULL)
974
      return;
975

976 977
   np = png_voidcast(png_sPLT_tp, png_malloc_warn(png_ptr,
       (info_ptr->splt_palettes_num + nentries) * png_sizeof(png_sPLT_t)));
978

979 980
   if (np == NULL)
   {
981
      png_warning(png_ptr, "No memory for sPLT palettes");
982
      return;
983
   }
984

985
   png_memcpy(np, info_ptr->splt_palettes,
986
       info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t));
987

988 989
   png_free(png_ptr, info_ptr->splt_palettes);
   info_ptr->splt_palettes=NULL;
990

991 992 993
   /* TODO: fix this, it apparently leaves NULL entries in the event of OOM
    * below.
    */
994 995 996
   for (i = 0; i < nentries; i++)
   {
      png_sPLT_tp to = np + info_ptr->splt_palettes_num + i;
997
      png_const_sPLT_tp from = entries + i;
998
      png_size_t length;
999

1000 1001 1002 1003 1004 1005 1006 1007 1008
      /* 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;

1009
      length = png_strlen(from->name) + 1;
1010
      to->name = png_voidcast(png_charp, png_malloc_warn(png_ptr, length));
1011

1012 1013 1014
      if (to->name == NULL)
      {
         png_warning(png_ptr,
1015
             "Out of memory while processing sPLT chunk");
1016 1017
         continue;
      }
1018

1019
      png_memcpy(to->name, from->name, length);
1020 1021
      to->entries = png_voidcast(png_sPLT_entryp, png_malloc_warn(png_ptr,
          from->nentries * png_sizeof(png_sPLT_entry)));
1022

1023 1024
      if (to->entries == NULL)
      {
1025
         png_warning(png_ptr, "Out of memory while processing sPLT chunk");
1026 1027 1028 1029
         png_free(png_ptr, to->name);
         to->name = NULL;
         continue;
      }
1030

1031 1032
      png_memcpy(to->entries, from->entries,
          from->nentries * png_sizeof(png_sPLT_entry));
1033

1034 1035 1036 1037 1038 1039 1040 1041
      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;
1042 1043 1044
}
#endif /* PNG_sPLT_SUPPORTED */

1045
#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
1046
void PNGAPI
1047
png_set_unknown_chunks(png_const_structrp png_ptr,
1048
   png_inforp info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns)
1049
{
1050 1051 1052 1053
   png_unknown_chunkp np;
   int i;

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

1056
   np = png_voidcast(png_unknown_chunkp, png_malloc_warn(png_ptr,
1057
       (png_size_t)(info_ptr->unknown_chunks_num + num_unknowns) *
1058
       png_sizeof(png_unknown_chunk)));
1059

1060 1061 1062
   if (np == NULL)
   {
      png_warning(png_ptr,
1063
          "Out of memory while processing unknown chunk");
1064 1065 1066 1067
      return;
   }

   png_memcpy(np, info_ptr->unknown_chunks,
1068 1069
       (png_size_t)info_ptr->unknown_chunks_num *
       png_sizeof(png_unknown_chunk));
1070

1071
   png_free(png_ptr, info_ptr->unknown_chunks);
1072
   info_ptr->unknown_chunks = NULL;
1073 1074 1075 1076

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

1079
      png_memcpy(to->name, from->name, png_sizeof(from->name));
1080 1081
      to->name[png_sizeof(to->name)-1] = '\0';
      to->size = from->size;
1082

1083
      /* Note our location in the read or write sequence */
1084 1085 1086 1087
      to->location = (png_byte)(png_ptr->mode & 0xff);

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

1089 1090 1091
      else
      {
         to->data = (png_bytep)png_malloc_warn(png_ptr,
1092
             (png_size_t)from->size);
1093

1094 1095 1096
         if (to->data == NULL)
         {
            png_warning(png_ptr,
1097
                "Out of memory while processing unknown chunk");
1098 1099
            to->size = 0;
         }
1100

1101 1102 1103 1104 1105 1106 1107 1108
         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;
1109
}
1110

1111
void PNGAPI
1112
png_set_unknown_chunk_location(png_const_structrp png_ptr, png_inforp info_ptr,
1113
    int chunk, int location)
1114
{
1115
   if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 && chunk <
1116
       info_ptr->unknown_chunks_num)
1117 1118
      info_ptr->unknown_chunks[chunk].location = (png_byte)location;
}
1119 1120
#endif

1121

1122
#ifdef PNG_MNG_FEATURES_SUPPORTED
1123
png_uint_32 PNGAPI
1124
png_permit_mng_features (png_structrp png_ptr, png_uint_32 mng_features)
1125
{
1126
   png_debug(1, "in png_permit_mng_features");
1127

1128
   if (png_ptr == NULL)
1129
      return 0;
1130

1131
   png_ptr->mng_features_permitted = mng_features & PNG_ALL_MNG_FEATURES;
1132

1133
   return png_ptr->mng_features_permitted;
1134 1135
}
#endif
1136

1137
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
1138
void PNGAPI
1139
png_set_keep_unknown_chunks(png_structrp png_ptr, int keep,
1140
    png_const_bytep chunk_list, int num_chunksIn)
1141
{
1142
   png_bytep new_list, p;
1143
   unsigned int i, num_chunks, old_num_chunks;
1144 1145
   if (png_ptr == NULL)
      return;
1146

1147
   if (num_chunksIn <= 0)
1148
   {
1149
      if (keep == PNG_HANDLE_CHUNK_ALWAYS || keep == PNG_HANDLE_CHUNK_IF_SAFE)
1150
         png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
1151

1152
      else
1153
         png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
1154

1155
      if (keep == PNG_HANDLE_CHUNK_ALWAYS)
1156
         png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS;
1157

1158
      else
1159
         png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS;
1160

1161
      return;
1162
   }
1163

1164
   if (chunk_list == NULL)
1165
      return;
1166

1167 1168 1169
   /* The argument is >0 */
   num_chunks = (unsigned int)num_chunksIn;

1170
   old_num_chunks = png_ptr->num_chunk_list;
1171 1172
   new_list = png_voidcast(png_bytep, png_malloc(png_ptr,
       5 * (num_chunks + old_num_chunks)));
1173

1174 1175
   if (png_ptr->chunk_list != NULL)
   {
1176
      png_memcpy(new_list, png_ptr->chunk_list, 5*old_num_chunks);
1177 1178 1179
      png_free(png_ptr, png_ptr->chunk_list);
      png_ptr->chunk_list=NULL;
   }
1180

1181 1182
   png_memcpy(new_list + 5*old_num_chunks, chunk_list,
      5*(unsigned int)num_chunks);
1183

1184 1185
   for (p = new_list + 5*old_num_chunks + 4, i = 0; i<num_chunks; i++, p += 5)
      *p=(png_byte)keep;
1186

1187 1188 1189
   png_ptr->num_chunk_list = old_num_chunks + num_chunks;
   png_ptr->chunk_list = new_list;
   png_ptr->free_me |= PNG_FREE_LIST;
1190 1191
}
#endif
1192

1193
#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
1194
void PNGAPI
1195
png_set_read_user_chunk_fn(png_structrp png_ptr, png_voidp user_chunk_ptr,
1196
    png_user_chunk_ptr read_user_chunk_fn)
1197
{
1198
   png_debug(1, "in png_set_read_user_chunk_fn");
1199

1200 1201
   if (png_ptr == NULL)
      return;
1202

1203 1204 1205 1206
   png_ptr->read_user_chunk_fn = read_user_chunk_fn;
   png_ptr->user_chunk_ptr = user_chunk_ptr;
}
#endif
1207

1208
#ifdef PNG_INFO_IMAGE_SUPPORTED
1209
void PNGAPI
1210 1211
png_set_rows(png_const_structrp png_ptr, png_inforp info_ptr,
    png_bytepp row_pointers)
1212
{
1213
   png_debug1(1, "in %s storage function", "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

1221
   info_ptr->row_pointers = row_pointers;
1222

1223
   if (row_pointers)
1224
      info_ptr->valid |= PNG_INFO_IDAT;
1225 1226 1227
}
#endif

1228
void PNGAPI
1229
png_set_compression_buffer_size(png_structrp png_ptr, png_size_t size)
1230
{
1231 1232
    if (png_ptr == NULL)
       return;
1233

1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278
    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
1279
}
1280 1281

void PNGAPI
1282
png_set_invalid(png_const_structrp png_ptr, png_inforp info_ptr, int mask)
1283 1284
{
   if (png_ptr && info_ptr)
1285
      info_ptr->valid &= ~mask;
1286
}
1287

1288

1289
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
1290
/* This function was added to libpng 1.2.6 */
1291
void PNGAPI
1292
png_set_user_limits (png_structrp png_ptr, png_uint_32 user_width_max,
1293 1294
    png_uint_32 user_height_max)
{
1295 1296 1297 1298 1299 1300
   /* 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;
1301

1302 1303
   png_ptr->user_width_max = user_width_max;
   png_ptr->user_height_max = user_height_max;
1304
}
1305

1306
/* This function was added to libpng 1.4.0 */
1307
void PNGAPI
1308
png_set_chunk_cache_max (png_structrp png_ptr, png_uint_32 user_chunk_cache_max)
1309
{
1310 1311 1312 1313 1314 1315
    if (png_ptr)
       png_ptr->user_chunk_cache_max = user_chunk_cache_max;
}

/* This function was added to libpng 1.4.1 */
void PNGAPI
1316
png_set_chunk_malloc_max (png_structrp png_ptr,
1317
    png_alloc_size_t user_chunk_malloc_max)
1318
{
1319 1320
   if (png_ptr)
      png_ptr->user_chunk_malloc_max = user_chunk_malloc_max;
1321
}
1322 1323
#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */

1324

1325
#ifdef PNG_BENIGN_ERRORS_SUPPORTED
1326
void PNGAPI
1327
png_set_benign_errors(png_structrp png_ptr, int allowed)
1328
{
1329
   png_debug(1, "in png_set_benign_errors");
1330

1331
   if (allowed)
1332
      png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN;
1333

1334
   else
1335
      png_ptr->flags &= ~PNG_FLAG_BENIGN_ERRORS_WARN;
1336 1337
}
#endif /* PNG_BENIGN_ERRORS_SUPPORTED */
1338 1339 1340 1341 1342 1343 1344 1345

#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
   /* 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");

1346
   if (allowed > 0)
1347 1348 1349 1350 1351 1352 1353
      png_ptr->num_palette_max = 0;

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

1354
#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */