pngset.c 36.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
    png_free(png_ptr, png_ptr->zbuf);
1235

1236 1237
    if (size > ZLIB_IO_MAX)
    {
1238 1239 1240
       png_warning(png_ptr, "Attempt to set buffer size beyond max ignored");
       png_ptr->zbuf_size = ZLIB_IO_MAX;
       size = ZLIB_IO_MAX; /* must fit */
1241
    }
1242

1243
    else
1244
       png_ptr->zbuf_size = (uInt)size;
1245

1246
    png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, size);
1247

1248 1249 1250
    /* The following ensures a relatively safe failure if this gets called while
     * the buffer is actually in use.
     */
1251
    png_ptr->zstream.next_out = png_ptr->zbuf;
1252 1253
    png_ptr->zstream.avail_out = 0;
    png_ptr->zstream.avail_in = 0;
1254
}
1255 1256

void PNGAPI
1257
png_set_invalid(png_const_structrp png_ptr, png_inforp info_ptr, int mask)
1258 1259
{
   if (png_ptr && info_ptr)
1260
      info_ptr->valid &= ~mask;
1261
}
1262

1263

1264
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
1265
/* This function was added to libpng 1.2.6 */
1266
void PNGAPI
1267
png_set_user_limits (png_structrp png_ptr, png_uint_32 user_width_max,
1268 1269
    png_uint_32 user_height_max)
{
1270 1271 1272 1273 1274 1275
   /* 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;
1276

1277 1278
   png_ptr->user_width_max = user_width_max;
   png_ptr->user_height_max = user_height_max;
1279
}
1280

1281
/* This function was added to libpng 1.4.0 */
1282
void PNGAPI
1283
png_set_chunk_cache_max (png_structrp png_ptr, png_uint_32 user_chunk_cache_max)
1284
{
1285 1286 1287 1288 1289 1290
    if (png_ptr)
       png_ptr->user_chunk_cache_max = user_chunk_cache_max;
}

/* This function was added to libpng 1.4.1 */
void PNGAPI
1291
png_set_chunk_malloc_max (png_structrp png_ptr,
1292
    png_alloc_size_t user_chunk_malloc_max)
1293
{
1294 1295
   if (png_ptr)
      png_ptr->user_chunk_malloc_max = user_chunk_malloc_max;
1296
}
1297 1298
#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */

1299

1300
#ifdef PNG_BENIGN_ERRORS_SUPPORTED
1301
void PNGAPI
1302
png_set_benign_errors(png_structrp png_ptr, int allowed)
1303
{
1304
   png_debug(1, "in png_set_benign_errors");
1305

1306
   if (allowed)
1307
      png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN;
1308

1309
   else
1310
      png_ptr->flags &= ~PNG_FLAG_BENIGN_ERRORS_WARN;
1311 1312
}
#endif /* PNG_BENIGN_ERRORS_SUPPORTED */
1313
#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */