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

/* pngset.c - storage of image information into info struct
3
 *
4
 * Last changed in libpng 1.5.6 [November 3, 2011]
5
 * Copyright (c) 1998-2011 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 26
png_set_bKGD(png_structp png_ptr, png_infop info_ptr,
    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)
A
Andreas Dilger 已提交
31 32
      return;

33
   png_memcpy(&(info_ptr->background), background, png_sizeof(png_color_16));
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_structp png_ptr, png_infop 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 68 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
void PNGFAPI
png_set_cHRM_XYZ_fixed(png_structp png_ptr, png_infop info_ptr,
    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
G
[devel]  
Glenn Randers-Pehrson 已提交
102 103 104
png_set_cHRM(png_structp png_ptr, png_infop info_ptr,
    double white_x, double white_y, double red_x, double red_y,
    double green_x, double green_y, double blue_x, double blue_y)
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 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132

void PNGAPI
png_set_cHRM_XYZ(png_structp png_ptr, png_infop info_ptr, double red_X,
    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
png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point
140
    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 167 168 169
void PNGAPI
png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma)
{
   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
png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_const_uint_16p hist)
A
Andreas Dilger 已提交
178
{
179
   int i;
180

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

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

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

192
      return;
193
   }
194 195

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

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

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

209
   for (i = 0; i < info_ptr->num_palette; i++)
210
      png_ptr->hist[i] = hist[i];
211

212
   info_ptr->hist = png_ptr->hist;
A
Andreas Dilger 已提交
213
   info_ptr->valid |= PNG_INFO_hIST;
214
   info_ptr->free_me |= PNG_FREE_HIST;
A
Andreas Dilger 已提交
215 216 217
}
#endif

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

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

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

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

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

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

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

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

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

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

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

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

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

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

295
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
296 297 298
      return;

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

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

   /* Validate params[nparams] */
   for (i=0; i<nparams; ++i)
      if (!png_check_fp_string(params[i], png_strlen(params[i])))
         png_error(png_ptr, "Invalid format for pCAL parameter");

313
   info_ptr->pcal_purpose = (png_charp)png_malloc_warn(png_ptr, length);
314

315
   if (info_ptr->pcal_purpose == NULL)
316
   {
317
      png_warning(png_ptr, "Insufficient memory for pCAL purpose");
318 319
      return;
   }
320

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

323
   png_debug(3, "storing X0, X1, type, and nparams in info");
A
Andreas Dilger 已提交
324 325 326 327 328 329
   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;
330
   png_debug1(3, "allocating units for info (%lu bytes)",
331
     (unsigned long)length);
332

333
   info_ptr->pcal_units = (png_charp)png_malloc_warn(png_ptr, length);
334

335
   if (info_ptr->pcal_units == NULL)
336
   {
337
      png_warning(png_ptr, "Insufficient memory for pCAL units");
338 339
      return;
   }
340

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

343
   info_ptr->pcal_params = (png_charpp)png_malloc_warn(png_ptr,
344
       (png_size_t)((nparams + 1) * png_sizeof(png_charp)));
345

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

352
   png_memset(info_ptr->pcal_params, 0, (nparams + 1) * png_sizeof(png_charp));
A
Andreas Dilger 已提交
353 354 355 356

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

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

362
      if (info_ptr->pcal_params[i] == NULL)
363
      {
364 365
         png_warning(png_ptr, "Insufficient memory for pCAL parameter");
         return;
366
      }
367

368
      png_memcpy(info_ptr->pcal_params[i], params[i], length);
A
Andreas Dilger 已提交
369 370 371
   }

   info_ptr->valid |= PNG_INFO_pCAL;
372
   info_ptr->free_me |= PNG_FREE_PCAL;
A
Andreas Dilger 已提交
373 374 375
}
#endif

376
#ifdef PNG_sCAL_SUPPORTED
377
void PNGAPI
378
png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr,
379
    int unit, png_const_charp swidth, png_const_charp sheight)
380
{
381
   png_size_t lengthw = 0, lengthh = 0;
382

383
   png_debug1(1, "in %s storage function", "sCAL");
384

385 386 387
   if (png_ptr == NULL || info_ptr == NULL)
      return;

G
[devel]  
Glenn Randers-Pehrson 已提交
388 389 390 391 392 393
   /* 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");

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

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

402
   info_ptr->scal_unit = (png_byte)unit;
403

G
[devel]  
Glenn Randers-Pehrson 已提交
404
   ++lengthw;
405

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

G
[devel]  
Glenn Randers-Pehrson 已提交
408
   info_ptr->scal_s_width = (png_charp)png_malloc_warn(png_ptr, lengthw);
409

410 411
   if (info_ptr->scal_s_width == NULL)
   {
G
[devel]  
Glenn Randers-Pehrson 已提交
412
      png_warning(png_ptr, "Memory allocation failed while processing sCAL");
413
      return;
414
   }
415

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

G
[devel]  
Glenn Randers-Pehrson 已提交
418
   ++lengthh;
419

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

G
[devel]  
Glenn Randers-Pehrson 已提交
422
   info_ptr->scal_s_height = (png_charp)png_malloc_warn(png_ptr, lengthh);
423

424 425 426
   if (info_ptr->scal_s_height == NULL)
   {
      png_free (png_ptr, info_ptr->scal_s_width);
427
      info_ptr->scal_s_width = NULL;
428

G
[devel]  
Glenn Randers-Pehrson 已提交
429
      png_warning(png_ptr, "Memory allocation failed while processing sCAL");
430
      return;
431
   }
432

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

435
   info_ptr->valid |= PNG_INFO_sCAL;
436
   info_ptr->free_me |= PNG_FREE_SCAL;
437
}
G
[devel]  
Glenn Randers-Pehrson 已提交
438

439
#  ifdef PNG_FLOATING_POINT_SUPPORTED
G
[devel]  
Glenn Randers-Pehrson 已提交
440 441
void PNGAPI
png_set_sCAL(png_structp png_ptr, png_infop info_ptr, int unit, double width,
442
    double height)
G
[devel]  
Glenn Randers-Pehrson 已提交
443 444 445 446 447 448
{
   png_debug1(1, "in %s storage function", "sCAL");

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

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

G
[devel]  
Glenn Randers-Pehrson 已提交
453 454 455 456 457 458 459 460 461 462 463 464 465 466
   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);
   }
}
467
#  endif
468

469
#  ifdef PNG_FIXED_POINT_SUPPORTED
470 471
void PNGAPI
png_set_sCAL_fixed(png_structp png_ptr, png_infop info_ptr, int unit,
472
    png_fixed_point width, png_fixed_point height)
473 474 475 476 477 478
{
   png_debug1(1, "in %s storage function", "sCAL");

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

480 481
   else if (height <= 0)
      png_warning(png_ptr, "Invalid sCAL height ignored");
482

483 484 485 486 487 488 489 490 491 492 493 494
   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);
   }
}
495
#  endif
496
#endif
497

498
#ifdef PNG_pHYs_SUPPORTED
499
void PNGAPI
A
Andreas Dilger 已提交
500
png_set_pHYs(png_structp png_ptr, png_infop info_ptr,
501
    png_uint_32 res_x, png_uint_32 res_y, int unit_type)
A
Andreas Dilger 已提交
502
{
503
   png_debug1(1, "in %s storage function", "pHYs");
504

505
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
506 507 508 509 510 511 512 513 514
      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

515
void PNGAPI
A
Andreas Dilger 已提交
516
png_set_PLTE(png_structp png_ptr, png_infop info_ptr,
517
    png_const_colorp palette, int num_palette)
A
Andreas Dilger 已提交
518
{
519

520
   png_debug1(1, "in %s storage function", "PLTE");
521

522
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
523 524
      return;

525
   if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH)
526 527
   {
      if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
528
         png_error(png_ptr, "Invalid palette length");
529

530 531
      else
      {
532 533
         png_warning(png_ptr, "Invalid palette length");
         return;
534 535
      }
   }
536

537
   /* It may not actually be necessary to set png_ptr->palette here;
538 539 540 541
    * we do it for backward compatibility with the way the png_handle_tRNS
    * function used to do the allocation.
    */
   png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0);
542

543
   /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead
544 545 546
    * of num_palette entries, in case of an invalid PNG file that has
    * too-large sample values.
    */
547
   png_ptr->palette = (png_colorp)png_calloc(png_ptr,
548
       PNG_MAX_PALETTE_LENGTH * png_sizeof(png_color));
549

550
   png_memcpy(png_ptr->palette, palette, num_palette * png_sizeof(png_color));
551 552 553 554
   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;
555

556
   info_ptr->valid |= PNG_INFO_PLTE;
A
Andreas Dilger 已提交
557 558
}

559
#ifdef PNG_sBIT_SUPPORTED
560
void PNGAPI
A
Andreas Dilger 已提交
561
png_set_sBIT(png_structp png_ptr, png_infop info_ptr,
562
    png_const_color_8p sig_bit)
A
Andreas Dilger 已提交
563
{
564
   png_debug1(1, "in %s storage function", "sBIT");
565

566
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
567 568
      return;

569
   png_memcpy(&(info_ptr->sig_bit), sig_bit, png_sizeof(png_color_8));
A
Andreas Dilger 已提交
570 571 572 573
   info_ptr->valid |= PNG_INFO_sBIT;
}
#endif

574
#ifdef PNG_sRGB_SUPPORTED
575
void PNGAPI
576
png_set_sRGB(png_structp png_ptr, png_infop info_ptr, int srgb_intent)
577
{
578
   png_debug1(1, "in %s storage function", "sRGB");
579

580
   if (png_ptr == NULL || info_ptr == NULL)
581 582
      return;

583
   info_ptr->srgb_intent = (png_byte)srgb_intent;
584 585
   info_ptr->valid |= PNG_INFO_sRGB;
}
586

587
void PNGAPI
588
png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr,
589
    int srgb_intent)
590
{
591
   png_debug1(1, "in %s storage function", "sRGB_gAMA_and_cHRM");
592

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

596
   png_set_sRGB(png_ptr, info_ptr, srgb_intent);
597

598
#  ifdef PNG_gAMA_SUPPORTED
599
   png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE);
600
#  endif
601

602
#  ifdef PNG_cHRM_SUPPORTED
603
   png_set_cHRM_fixed(png_ptr, info_ptr,
604
      /* color      x       y */
605 606 607 608
      /* white */ 31270, 32900,
      /* red   */ 64000, 33000,
      /* green */ 30000, 60000,
      /* blue  */ 15000,  6000
609
   );
610
#  endif /* cHRM */
611
}
612
#endif /* sRGB */
613

614

615
#ifdef PNG_iCCP_SUPPORTED
616
void PNGAPI
617
png_set_iCCP(png_structp png_ptr, png_infop info_ptr,
618 619
    png_const_charp name, int compression_type,
    png_const_bytep profile, png_uint_32 proflen)
620
{
621
   png_charp new_iccp_name;
G
[devel]  
Glenn Randers-Pehrson 已提交
622
   png_bytep new_iccp_profile;
623
   png_size_t length;
624

625
   png_debug1(1, "in %s storage function", "iCCP");
626

627 628 629
   if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL)
      return;

630 631
   length = png_strlen(name)+1;
   new_iccp_name = (png_charp)png_malloc_warn(png_ptr, length);
632

633 634
   if (new_iccp_name == NULL)
   {
635
        png_warning(png_ptr, "Insufficient memory to process iCCP chunk");
636 637
      return;
   }
638

639
   png_memcpy(new_iccp_name, name, length);
G
[devel]  
Glenn Randers-Pehrson 已提交
640
   new_iccp_profile = (png_bytep)png_malloc_warn(png_ptr, proflen);
641

642 643 644
   if (new_iccp_profile == NULL)
   {
      png_free (png_ptr, new_iccp_name);
645
      png_warning(png_ptr,
646
          "Insufficient memory to process iCCP profile");
647 648
      return;
   }
649

650 651
   png_memcpy(new_iccp_profile, profile, (png_size_t)proflen);

652
   png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0);
653

654
   info_ptr->iccp_proflen = proflen;
655 656
   info_ptr->iccp_name = new_iccp_name;
   info_ptr->iccp_profile = new_iccp_profile;
657
   /* Compression is always zero but is here so the API and info structure
658 659
    * does not have to change if we introduce multiple compression types
    */
660
   info_ptr->iccp_compression = (png_byte)compression_type;
661
   info_ptr->free_me |= PNG_FREE_ICCP;
662 663 664 665
   info_ptr->valid |= PNG_INFO_iCCP;
}
#endif

666
#ifdef PNG_TEXT_SUPPORTED
667
void PNGAPI
668
png_set_text(png_structp png_ptr, png_infop info_ptr, png_const_textp text_ptr,
669
    int num_text)
670 671
{
   int ret;
672
   ret = png_set_text_2(png_ptr, info_ptr, text_ptr, num_text);
673

674
   if (ret)
675
      png_error(png_ptr, "Insufficient memory to store text");
676 677 678
}

int /* PRIVATE */
679 680
png_set_text_2(png_structp png_ptr, png_infop info_ptr,
    png_const_textp text_ptr, int num_text)
A
Andreas Dilger 已提交
681 682 683
{
   int i;

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

687
   if (png_ptr == NULL || info_ptr == NULL || num_text == 0)
688
      return(0);
A
Andreas Dilger 已提交
689 690 691 692 693 694 695 696 697 698 699 700 701 702

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

706
         if (info_ptr->text == NULL)
707 708 709 710
         {
            png_free(png_ptr, old_text);
            return(1);
         }
711

712
         png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max *
713
             png_sizeof(png_text)));
A
Andreas Dilger 已提交
714 715
         png_free(png_ptr, old_text);
      }
716

A
Andreas Dilger 已提交
717 718 719 720
      else
      {
         info_ptr->max_text = num_text + 8;
         info_ptr->num_text = 0;
721
         info_ptr->text = (png_textp)png_malloc_warn(png_ptr,
722
             (png_size_t)(info_ptr->max_text * png_sizeof(png_text)));
723
         if (info_ptr->text == NULL)
724
            return(1);
725
         info_ptr->free_me |= PNG_FREE_TEXT;
A
Andreas Dilger 已提交
726
      }
727

728
      png_debug1(3, "allocated %d entries for info_ptr->text",
729
          info_ptr->max_text);
A
Andreas Dilger 已提交
730 731 732
   }
   for (i = 0; i < num_text; i++)
   {
733 734
      png_size_t text_length, key_len;
      png_size_t lang_len, lang_key_len;
A
Andreas Dilger 已提交
735 736
      png_textp textp = &(info_ptr->text[info_ptr->num_text]);

737
      if (text_ptr[i].key == NULL)
738 739
          continue;

740 741
      if (text_ptr[i].compression < PNG_TEXT_COMPRESSION_NONE ||
          text_ptr[i].compression >= PNG_TEXT_COMPRESSION_LAST)
742 743 744 745 746
      {
         png_warning(png_ptr, "text compression mode is out of range");
         continue;
      }

747 748
      key_len = png_strlen(text_ptr[i].key);

749
      if (text_ptr[i].compression <= 0)
750
      {
751 752
         lang_len = 0;
         lang_key_len = 0;
753
      }
754

755
      else
756
#  ifdef PNG_iTXt_SUPPORTED
757
      {
758
         /* Set iTXt data */
759

760 761
         if (text_ptr[i].lang != NULL)
            lang_len = png_strlen(text_ptr[i].lang);
762

763 764
         else
            lang_len = 0;
765

766 767
         if (text_ptr[i].lang_key != NULL)
            lang_key_len = png_strlen(text_ptr[i].lang_key);
768

769 770
         else
            lang_key_len = 0;
771
      }
772
#  else /* PNG_iTXt_SUPPORTED */
773
      {
774 775
         png_warning(png_ptr, "iTXt chunk not supported");
         continue;
776
      }
777
#  endif
A
Andreas Dilger 已提交
778

779
      if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0')
A
Andreas Dilger 已提交
780
      {
781
         text_length = 0;
782
#  ifdef PNG_iTXt_SUPPORTED
783
         if (text_ptr[i].compression > 0)
784
            textp->compression = PNG_ITXT_COMPRESSION_NONE;
785

786
         else
787
#  endif
788
            textp->compression = PNG_TEXT_COMPRESSION_NONE;
A
Andreas Dilger 已提交
789
      }
790

A
Andreas Dilger 已提交
791 792
      else
      {
793
         text_length = png_strlen(text_ptr[i].text);
A
Andreas Dilger 已提交
794 795
         textp->compression = text_ptr[i].compression;
      }
796

797
      textp->key = (png_charp)png_malloc_warn(png_ptr,
798 799
          (png_size_t)
          (key_len + text_length + lang_len + lang_key_len + 4));
800

801
      if (textp->key == NULL)
802
         return(1);
803

804
      png_debug2(2, "Allocated %lu bytes at %p in png_set_text",
805 806
          (unsigned long)(png_uint_32)
          (key_len + lang_len + lang_key_len + text_length + 4),
807
          textp->key);
808

809
      png_memcpy(textp->key, text_ptr[i].key,(png_size_t)(key_len));
810
      *(textp->key + key_len) = '\0';
811

812 813
      if (text_ptr[i].compression > 0)
      {
814
         textp->lang = textp->key + key_len + 1;
815
         png_memcpy(textp->lang, text_ptr[i].lang, lang_len);
816
         *(textp->lang + lang_len) = '\0';
817
         textp->lang_key = textp->lang + lang_len + 1;
818
         png_memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len);
819
         *(textp->lang_key + lang_key_len) = '\0';
820
         textp->text = textp->lang_key + lang_key_len + 1;
821
      }
822

823 824
      else
      {
825 826
         textp->lang=NULL;
         textp->lang_key=NULL;
827
         textp->text = textp->key + key_len + 1;
828
      }
829

830
      if (text_length)
831
         png_memcpy(textp->text, text_ptr[i].text,
832
             (png_size_t)(text_length));
833

834
      *(textp->text + text_length) = '\0';
835

836
#  ifdef PNG_iTXt_SUPPORTED
837
      if (textp->compression > 0)
838 839 840 841
      {
         textp->text_length = 0;
         textp->itxt_length = text_length;
      }
842

843
      else
844
#  endif
845 846 847 848
      {
         textp->text_length = text_length;
         textp->itxt_length = 0;
      }
849

A
Andreas Dilger 已提交
850
      info_ptr->num_text++;
851
      png_debug1(3, "transferred text chunk %d", info_ptr->num_text);
A
Andreas Dilger 已提交
852
   }
853
   return(0);
A
Andreas Dilger 已提交
854 855 856
}
#endif

857
#ifdef PNG_tIME_SUPPORTED
858
void PNGAPI
859
png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_const_timep mod_time)
A
Andreas Dilger 已提交
860
{
861
   png_debug1(1, "in %s storage function", "tIME");
862

863
   if (png_ptr == NULL || info_ptr == NULL ||
864
       (png_ptr->mode & PNG_WROTE_tIME))
A
Andreas Dilger 已提交
865 866
      return;

867 868 869 870 871 872 873 874 875
   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;
   }

876
   png_memcpy(&(info_ptr->mod_time), mod_time, png_sizeof(png_time));
A
Andreas Dilger 已提交
877 878 879 880
   info_ptr->valid |= PNG_INFO_tIME;
}
#endif

881
#ifdef PNG_tRNS_SUPPORTED
882
void PNGAPI
A
Andreas Dilger 已提交
883
png_set_tRNS(png_structp png_ptr, png_infop info_ptr,
884
    png_const_bytep trans_alpha, int num_trans, png_const_color_16p trans_color)
A
Andreas Dilger 已提交
885
{
886
   png_debug1(1, "in %s storage function", "tRNS");
887

888
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
889 890
      return;

891
   if (trans_alpha != NULL)
892
   {
893
       /* It may not actually be necessary to set png_ptr->trans_alpha here;
894 895 896
        * we do it for backward compatibility with the way the png_handle_tRNS
        * function used to do the allocation.
        */
897

898
       png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
899

900
       /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */
G
[devel]  
Glenn Randers-Pehrson 已提交
901
       png_ptr->trans_alpha = info_ptr->trans_alpha =
902
           (png_bytep)png_malloc(png_ptr, (png_size_t)PNG_MAX_PALETTE_LENGTH);
903

904
       if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH)
905
          png_memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans);
906
   }
A
Andreas Dilger 已提交
907

908
   if (trans_color != NULL)
A
Andreas Dilger 已提交
909
   {
910
      int sample_max = (1 << info_ptr->bit_depth);
911

912
      if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY &&
913
          (int)trans_color->gray > sample_max) ||
914
          (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
915 916 917
          ((int)trans_color->red > sample_max ||
          (int)trans_color->green > sample_max ||
          (int)trans_color->blue > sample_max)))
918 919
         png_warning(png_ptr,
            "tRNS chunk has out-of-range samples for bit_depth");
920

G
[devel]  
Glenn Randers-Pehrson 已提交
921 922
      png_memcpy(&(info_ptr->trans_color), trans_color,
         png_sizeof(png_color_16));
923

924
      if (num_trans == 0)
925
         num_trans = 1;
A
Andreas Dilger 已提交
926
   }
927

A
Andreas Dilger 已提交
928
   info_ptr->num_trans = (png_uint_16)num_trans;
929

930 931 932 933 934
   if (num_trans != 0)
   {
      info_ptr->valid |= PNG_INFO_tRNS;
      info_ptr->free_me |= PNG_FREE_TRNS;
   }
A
Andreas Dilger 已提交
935 936 937
}
#endif

938
#ifdef PNG_sPLT_SUPPORTED
939
void PNGAPI
940
png_set_sPLT(png_structp png_ptr,
941
    png_infop info_ptr, png_const_sPLT_tp entries, int nentries)
942 943 944 945
/*
 *  entries        - array of png_sPLT_t structures
 *                   to be added to the list of palettes
 *                   in the info structure.
946
 *
947 948 949
 *  nentries       - number of palette structures to be
 *                   added.
 */
950
{
951 952
   png_sPLT_tp np;
   int i;
953

954 955
   if (png_ptr == NULL || info_ptr == NULL)
      return;
956

957 958
   np = (png_sPLT_tp)png_malloc_warn(png_ptr,
       (info_ptr->splt_palettes_num + nentries) *
959
       (png_size_t)png_sizeof(png_sPLT_t));
960

961 962
   if (np == NULL)
   {
963
      png_warning(png_ptr, "No memory for sPLT palettes");
964
      return;
965
   }
966

967
   png_memcpy(np, info_ptr->splt_palettes,
968
       info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t));
969

970 971
   png_free(png_ptr, info_ptr->splt_palettes);
   info_ptr->splt_palettes=NULL;
972

973 974 975
   for (i = 0; i < nentries; i++)
   {
      png_sPLT_tp to = np + info_ptr->splt_palettes_num + i;
976
      png_const_sPLT_tp from = entries + i;
977
      png_size_t length;
978

979
      length = png_strlen(from->name) + 1;
980
      to->name = (png_charp)png_malloc_warn(png_ptr, length);
981

982 983 984
      if (to->name == NULL)
      {
         png_warning(png_ptr,
985
             "Out of memory while processing sPLT chunk");
986 987
         continue;
      }
988

989 990
      png_memcpy(to->name, from->name, length);
      to->entries = (png_sPLT_entryp)png_malloc_warn(png_ptr,
991
          from->nentries * png_sizeof(png_sPLT_entry));
992

993 994 995
      if (to->entries == NULL)
      {
         png_warning(png_ptr,
996
             "Out of memory while processing sPLT chunk");
997 998 999 1000
         png_free(png_ptr, to->name);
         to->name = NULL;
         continue;
      }
1001

1002 1003
      png_memcpy(to->entries, from->entries,
          from->nentries * png_sizeof(png_sPLT_entry));
1004

1005 1006 1007 1008 1009 1010 1011 1012
      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;
1013 1014 1015
}
#endif /* PNG_sPLT_SUPPORTED */

1016
#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
1017
void PNGAPI
1018
png_set_unknown_chunks(png_structp png_ptr,
1019
   png_infop info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns)
1020
{
1021 1022 1023 1024
   png_unknown_chunkp np;
   int i;

   if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0)
1025
      return;
1026 1027

   np = (png_unknown_chunkp)png_malloc_warn(png_ptr,
1028 1029
       (png_size_t)(info_ptr->unknown_chunks_num + num_unknowns) *
       png_sizeof(png_unknown_chunk));
1030

1031 1032 1033
   if (np == NULL)
   {
      png_warning(png_ptr,
1034
          "Out of memory while processing unknown chunk");
1035 1036 1037 1038
      return;
   }

   png_memcpy(np, info_ptr->unknown_chunks,
1039 1040
       (png_size_t)info_ptr->unknown_chunks_num *
       png_sizeof(png_unknown_chunk));
1041

1042
   png_free(png_ptr, info_ptr->unknown_chunks);
1043
   info_ptr->unknown_chunks = NULL;
1044 1045 1046 1047

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

1050
      png_memcpy(to->name, from->name, png_sizeof(from->name));
1051 1052
      to->name[png_sizeof(to->name)-1] = '\0';
      to->size = from->size;
1053

1054
      /* Note our location in the read or write sequence */
1055 1056 1057 1058
      to->location = (png_byte)(png_ptr->mode & 0xff);

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

1060 1061 1062
      else
      {
         to->data = (png_bytep)png_malloc_warn(png_ptr,
1063
             (png_size_t)from->size);
1064

1065 1066 1067
         if (to->data == NULL)
         {
            png_warning(png_ptr,
1068
                "Out of memory while processing unknown chunk");
1069 1070
            to->size = 0;
         }
1071

1072 1073 1074 1075 1076 1077 1078 1079
         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;
1080
}
1081

1082
void PNGAPI
1083
png_set_unknown_chunk_location(png_structp png_ptr, png_infop info_ptr,
1084
    int chunk, int location)
1085
{
1086
   if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 && chunk <
1087
       info_ptr->unknown_chunks_num)
1088 1089
      info_ptr->unknown_chunks[chunk].location = (png_byte)location;
}
1090 1091
#endif

1092

1093
#ifdef PNG_MNG_FEATURES_SUPPORTED
1094 1095 1096
png_uint_32 PNGAPI
png_permit_mng_features (png_structp png_ptr, png_uint_32 mng_features)
{
1097
   png_debug(1, "in png_permit_mng_features");
1098

1099 1100
   if (png_ptr == NULL)
      return (png_uint_32)0;
1101

1102
   png_ptr->mng_features_permitted =
1103
       (png_byte)(mng_features & PNG_ALL_MNG_FEATURES);
1104

1105
   return (png_uint_32)png_ptr->mng_features_permitted;
1106 1107
}
#endif
1108

1109
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
1110
void PNGAPI
1111
png_set_keep_unknown_chunks(png_structp png_ptr, int keep, png_const_bytep
1112
    chunk_list, int num_chunks)
1113
{
1114 1115 1116 1117
   png_bytep new_list, p;
   int i, old_num_chunks;
   if (png_ptr == NULL)
      return;
1118

1119 1120
   if (num_chunks == 0)
   {
1121
      if (keep == PNG_HANDLE_CHUNK_ALWAYS || keep == PNG_HANDLE_CHUNK_IF_SAFE)
1122
         png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
1123

1124
      else
1125
         png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
1126

1127
      if (keep == PNG_HANDLE_CHUNK_ALWAYS)
1128
         png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS;
1129

1130
      else
1131
         png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS;
1132

1133
      return;
1134
   }
1135

1136
   if (chunk_list == NULL)
1137
      return;
1138

1139 1140
   old_num_chunks = png_ptr->num_chunk_list;
   new_list=(png_bytep)png_malloc(png_ptr,
1141
       (png_size_t)(5*(num_chunks + old_num_chunks)));
1142

1143 1144 1145
   if (png_ptr->chunk_list != NULL)
   {
      png_memcpy(new_list, png_ptr->chunk_list,
1146
          (png_size_t)(5*old_num_chunks));
1147 1148 1149
      png_free(png_ptr, png_ptr->chunk_list);
      png_ptr->chunk_list=NULL;
   }
1150

1151
   png_memcpy(new_list + 5*old_num_chunks, chunk_list,
1152
       (png_size_t)(5*num_chunks));
1153

1154 1155
   for (p = new_list + 5*old_num_chunks + 4, i = 0; i<num_chunks; i++, p += 5)
      *p=(png_byte)keep;
1156

1157 1158 1159
   png_ptr->num_chunk_list = old_num_chunks + num_chunks;
   png_ptr->chunk_list = new_list;
   png_ptr->free_me |= PNG_FREE_LIST;
1160 1161
}
#endif
1162

1163
#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
1164
void PNGAPI
1165
png_set_read_user_chunk_fn(png_structp png_ptr, png_voidp user_chunk_ptr,
1166
    png_user_chunk_ptr read_user_chunk_fn)
1167
{
1168
   png_debug(1, "in png_set_read_user_chunk_fn");
1169

1170 1171
   if (png_ptr == NULL)
      return;
1172

1173 1174 1175 1176
   png_ptr->read_user_chunk_fn = read_user_chunk_fn;
   png_ptr->user_chunk_ptr = user_chunk_ptr;
}
#endif
1177

1178
#ifdef PNG_INFO_IMAGE_SUPPORTED
1179
void PNGAPI
1180 1181
png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers)
{
1182
   png_debug1(1, "in %s storage function", "rows");
1183

1184 1185 1186
   if (png_ptr == NULL || info_ptr == NULL)
      return;

1187
   if (info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers))
1188
      png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
1189

1190
   info_ptr->row_pointers = row_pointers;
1191

1192
   if (row_pointers)
1193
      info_ptr->valid |= PNG_INFO_IDAT;
1194 1195 1196
}
#endif

1197
void PNGAPI
1198
png_set_compression_buffer_size(png_structp png_ptr, png_size_t size)
1199
{
1200 1201
    if (png_ptr == NULL)
       return;
1202

1203
    png_free(png_ptr, png_ptr->zbuf);
1204

1205 1206
    if (size > ZLIB_IO_MAX)
    {
1207 1208 1209
       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 */
1210
    }
1211

1212
    else
1213
       png_ptr->zbuf_size = (uInt)size;
1214

1215
    png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, size);
1216

1217 1218 1219
    /* The following ensures a relatively safe failure if this gets called while
     * the buffer is actually in use.
     */
1220
    png_ptr->zstream.next_out = png_ptr->zbuf;
1221 1222
    png_ptr->zstream.avail_out = 0;
    png_ptr->zstream.avail_in = 0;
1223
}
1224 1225 1226 1227 1228

void PNGAPI
png_set_invalid(png_structp png_ptr, png_infop info_ptr, int mask)
{
   if (png_ptr && info_ptr)
1229
      info_ptr->valid &= ~mask;
1230
}
1231

1232

1233 1234

#ifdef PNG_SET_USER_LIMITS_SUPPORTED
1235
/* This function was added to libpng 1.2.6 */
1236 1237 1238 1239
void PNGAPI
png_set_user_limits (png_structp png_ptr, png_uint_32 user_width_max,
    png_uint_32 user_height_max)
{
1240 1241 1242 1243 1244 1245
   /* 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;
1246

1247 1248
   png_ptr->user_width_max = user_width_max;
   png_ptr->user_height_max = user_height_max;
1249
}
1250

1251
/* This function was added to libpng 1.4.0 */
1252 1253 1254 1255
void PNGAPI
png_set_chunk_cache_max (png_structp png_ptr,
   png_uint_32 user_chunk_cache_max)
{
1256 1257 1258 1259 1260 1261 1262
    if (png_ptr)
       png_ptr->user_chunk_cache_max = user_chunk_cache_max;
}

/* This function was added to libpng 1.4.1 */
void PNGAPI
png_set_chunk_malloc_max (png_structp png_ptr,
1263
    png_alloc_size_t user_chunk_malloc_max)
1264
{
1265 1266
   if (png_ptr)
      png_ptr->user_chunk_malloc_max = user_chunk_malloc_max;
1267
}
1268 1269
#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */

1270

1271
#ifdef PNG_BENIGN_ERRORS_SUPPORTED
1272 1273 1274
void PNGAPI
png_set_benign_errors(png_structp png_ptr, int allowed)
{
1275
   png_debug(1, "in png_set_benign_errors");
1276

1277
   if (allowed)
1278
      png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN;
1279

1280
   else
1281
      png_ptr->flags &= ~PNG_FLAG_BENIGN_ERRORS_WARN;
1282 1283
}
#endif /* PNG_BENIGN_ERRORS_SUPPORTED */
1284
#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */