pngset.c 51.5 KB
Newer Older
D
duke 已提交
1 2 3 4 5
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
6
 * published by the Free Software Foundation.  Oracle designates this
D
duke 已提交
7
 * particular file as subject to the "Classpath" exception as provided
8
 * by Oracle in the LICENSE file that accompanied this code.
D
duke 已提交
9 10 11 12 13 14 15 16 17 18 19
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
20 21 22
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
D
duke 已提交
23 24 25 26 27 28 29 30 31
 */

/* pngset.c - storage of image information into info struct
 *
 * This file is available under and governed by the GNU General Public
 * License version 2 only, as published by the Free Software Foundation.
 * However, the following notice accompanied the original version of this
 * file and, per its terms, should not be removed:
 *
S
serb 已提交
32
 * Copyright (c) 2018 Cosmin Truta
P
prr 已提交
33
 * Copyright (c) 1998-2018 Glenn Randers-Pehrson
S
serb 已提交
34 35
 * Copyright (c) 1996-1997 Andreas Dilger
 * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
D
duke 已提交
36
 *
B
bae 已提交
37 38 39 40
 * This code is released under the libpng license.
 * For conditions of distribution and use, see the disclaimer
 * and license in png.h
 *
D
duke 已提交
41 42 43 44 45 46
 * 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.
 */

B
bae 已提交
47
#include "pngpriv.h"
D
duke 已提交
48 49 50

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

B
bae 已提交
51
#ifdef PNG_bKGD_SUPPORTED
D
duke 已提交
52
void PNGAPI
53
png_set_bKGD(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
54
    png_const_color_16p background)
D
duke 已提交
55
{
B
bae 已提交
56 57
   png_debug1(1, "in %s storage function", "bKGD");

58
   if (png_ptr == NULL || info_ptr == NULL || background == NULL)
D
duke 已提交
59 60
      return;

61
   info_ptr->background = *background;
D
duke 已提交
62 63 64 65
   info_ptr->valid |= PNG_INFO_bKGD;
}
#endif

B
bae 已提交
66 67
#ifdef PNG_cHRM_SUPPORTED
void PNGFAPI
68
png_set_cHRM_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
69 70 71
    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)
D
duke 已提交
72
{
73 74
   png_xy xy;

B
bae 已提交
75 76
   png_debug1(1, "in %s storage function", "cHRM fixed");

D
duke 已提交
77 78 79
   if (png_ptr == NULL || info_ptr == NULL)
      return;

80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
   xy.redx = red_x;
   xy.redy = red_y;
   xy.greenx = green_x;
   xy.greeny = green_y;
   xy.bluex = blue_x;
   xy.bluey = blue_y;
   xy.whitex = white_x;
   xy.whitey = white_y;

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

   png_colorspace_sync_info(png_ptr, info_ptr);
}

void PNGFAPI
png_set_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_inforp 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_debug1(1, "in %s storage function", "cHRM XYZ fixed");

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

   XYZ.red_X = int_red_X;
   XYZ.red_Y = int_red_Y;
   XYZ.red_Z = int_red_Z;
   XYZ.green_X = int_green_X;
   XYZ.green_Y = int_green_Y;
   XYZ.green_Z = int_green_Z;
   XYZ.blue_X = int_blue_X;
   XYZ.blue_Y = int_blue_Y;
   XYZ.blue_Z = int_blue_Z;

   if (png_colorspace_set_endpoints(png_ptr, &info_ptr->colorspace,
       &XYZ, 2) != 0)
      info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM;

   png_colorspace_sync_info(png_ptr, info_ptr);
D
duke 已提交
126 127
}

B
bae 已提交
128
#  ifdef PNG_FLOATING_POINT_SUPPORTED
D
duke 已提交
129
void PNGAPI
130
png_set_cHRM(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
131 132
    double white_x, double white_y, double red_x, double red_y,
    double green_x, double green_y, double blue_x, double blue_y)
D
duke 已提交
133
{
B
bae 已提交
134
   png_set_cHRM_fixed(png_ptr, info_ptr,
P
prr 已提交
135 136 137 138 139 140 141 142
       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"));
D
duke 已提交
143
}
B
bae 已提交
144

145 146 147 148 149 150
void PNGAPI
png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp 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,
P
prr 已提交
151 152 153 154 155 156 157 158 159
       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 Green X"),
       png_fixed(png_ptr, green_Y, "cHRM Green Y"),
       png_fixed(png_ptr, green_Z, "cHRM Green Z"),
       png_fixed(png_ptr, blue_X, "cHRM Blue X"),
       png_fixed(png_ptr, blue_Y, "cHRM Blue Y"),
       png_fixed(png_ptr, blue_Z, "cHRM Blue Z"));
160 161 162 163
}
#  endif /* FLOATING_POINT */

#endif /* cHRM */
B
bae 已提交
164

P
prr 已提交
165 166 167
#ifdef PNG_eXIf_SUPPORTED
void PNGAPI
png_set_eXIf(png_const_structrp png_ptr, png_inforp info_ptr,
S
serb 已提交
168
    png_bytep eXIf_buf)
P
prr 已提交
169 170 171 172 173 174 175 176
{
  png_warning(png_ptr, "png_set_eXIf does not work; use png_set_eXIf_1");
  PNG_UNUSED(info_ptr)
  PNG_UNUSED(eXIf_buf)
}

void PNGAPI
png_set_eXIf_1(png_const_structrp png_ptr, png_inforp info_ptr,
S
serb 已提交
177
    png_uint_32 num_exif, png_bytep eXIf_buf)
P
prr 已提交
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
{
   int i;

   png_debug1(1, "in %s storage function", "eXIf");

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

   if (info_ptr->exif)
   {
      png_free(png_ptr, info_ptr->exif);
      info_ptr->exif = NULL;
   }

   info_ptr->num_exif = num_exif;

   info_ptr->exif = png_voidcast(png_bytep, png_malloc_warn(png_ptr,
       info_ptr->num_exif));

   if (info_ptr->exif == NULL)
   {
      png_warning(png_ptr, "Insufficient memory for eXIf chunk data");
      return;
   }

   info_ptr->free_me |= PNG_FREE_EXIF;

   for (i = 0; i < (int) info_ptr->num_exif; i++)
      info_ptr->exif[i] = eXIf_buf[i];

   info_ptr->valid |= PNG_INFO_eXIf;
}
#endif /* eXIf */

B
bae 已提交
212 213
#ifdef PNG_gAMA_SUPPORTED
void PNGFAPI
214 215
png_set_gAMA_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
    png_fixed_point file_gamma)
D
duke 已提交
216
{
B
bae 已提交
217
   png_debug1(1, "in %s storage function", "gAMA");
D
duke 已提交
218 219 220 221

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

222 223
   png_colorspace_set_gamma(png_ptr, &info_ptr->colorspace, file_gamma);
   png_colorspace_sync_info(png_ptr, info_ptr);
D
duke 已提交
224
}
B
bae 已提交
225 226 227

#  ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
228
png_set_gAMA(png_const_structrp png_ptr, png_inforp info_ptr, double file_gamma)
B
bae 已提交
229 230 231 232 233
{
   png_set_gAMA_fixed(png_ptr, info_ptr, png_fixed(png_ptr, file_gamma,
       "png_set_gAMA"));
}
#  endif
D
duke 已提交
234 235
#endif

B
bae 已提交
236
#ifdef PNG_hIST_SUPPORTED
D
duke 已提交
237
void PNGAPI
238 239
png_set_hIST(png_const_structrp png_ptr, png_inforp info_ptr,
    png_const_uint_16p hist)
D
duke 已提交
240 241 242
{
   int i;

B
bae 已提交
243 244
   png_debug1(1, "in %s storage function", "hIST");

D
duke 已提交
245 246
   if (png_ptr == NULL || info_ptr == NULL)
      return;
B
bae 已提交
247 248

   if (info_ptr->num_palette == 0 || info_ptr->num_palette
D
duke 已提交
249 250
       > PNG_MAX_PALETTE_LENGTH)
   {
B
bae 已提交
251 252 253 254
      png_warning(png_ptr,
          "Invalid palette size, hIST allocation skipped");

      return;
D
duke 已提交
255 256 257
   }

   png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0);
B
bae 已提交
258 259 260 261

   /* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in
    * version 1.2.1
    */
262 263
   info_ptr->hist = png_voidcast(png_uint_16p, png_malloc_warn(png_ptr,
       PNG_MAX_PALETTE_LENGTH * (sizeof (png_uint_16))));
B
bae 已提交
264

265
   if (info_ptr->hist == NULL)
B
bae 已提交
266 267
   {
      png_warning(png_ptr, "Insufficient memory for hIST chunk data");
268

B
bae 已提交
269 270
      return;
   }
D
duke 已提交
271

272 273
   info_ptr->free_me |= PNG_FREE_HIST;

D
duke 已提交
274
   for (i = 0; i < info_ptr->num_palette; i++)
275
      info_ptr->hist[i] = hist[i];
B
bae 已提交
276

D
duke 已提交
277 278 279 280 281
   info_ptr->valid |= PNG_INFO_hIST;
}
#endif

void PNGAPI
282
png_set_IHDR(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
283 284 285
    png_uint_32 width, png_uint_32 height, int bit_depth,
    int color_type, int interlace_type, int compression_type,
    int filter_type)
D
duke 已提交
286
{
B
bae 已提交
287 288
   png_debug1(1, "in %s storage function", "IHDR");

D
duke 已提交
289 290 291 292 293 294
   if (png_ptr == NULL || info_ptr == NULL)
      return;

   info_ptr->width = width;
   info_ptr->height = height;
   info_ptr->bit_depth = (png_byte)bit_depth;
B
bae 已提交
295
   info_ptr->color_type = (png_byte)color_type;
D
duke 已提交
296 297 298
   info_ptr->compression_type = (png_byte)compression_type;
   info_ptr->filter_type = (png_byte)filter_type;
   info_ptr->interlace_type = (png_byte)interlace_type;
B
bae 已提交
299 300 301 302 303

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

D
duke 已提交
304 305
   if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
      info_ptr->channels = 1;
B
bae 已提交
306

307
   else if ((info_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
D
duke 已提交
308
      info_ptr->channels = 3;
B
bae 已提交
309

D
duke 已提交
310 311
   else
      info_ptr->channels = 1;
B
bae 已提交
312

313
   if ((info_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)
D
duke 已提交
314
      info_ptr->channels++;
B
bae 已提交
315

D
duke 已提交
316 317
   info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth);

318
   info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width);
D
duke 已提交
319 320
}

B
bae 已提交
321
#ifdef PNG_oFFs_SUPPORTED
D
duke 已提交
322
void PNGAPI
323
png_set_oFFs(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
324
    png_int_32 offset_x, png_int_32 offset_y, int unit_type)
D
duke 已提交
325
{
B
bae 已提交
326 327
   png_debug1(1, "in %s storage function", "oFFs");

D
duke 已提交
328 329 330 331 332 333 334 335 336 337
   if (png_ptr == NULL || info_ptr == NULL)
      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

B
bae 已提交
338
#ifdef PNG_pCAL_SUPPORTED
D
duke 已提交
339
void PNGAPI
340
png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
341 342
    png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type,
    int nparams, png_const_charp units, png_charpp params)
D
duke 已提交
343
{
P
prr 已提交
344
   size_t length;
D
duke 已提交
345 346
   int i;

B
bae 已提交
347 348
   png_debug1(1, "in %s storage function", "pCAL");

349 350
   if (png_ptr == NULL || info_ptr == NULL || purpose == NULL || units == NULL
       || (nparams > 0 && params == NULL))
D
duke 已提交
351 352
      return;

353
   length = strlen(purpose) + 1;
B
bae 已提交
354 355 356 357 358 359 360
   png_debug1(3, "allocating purpose for info (%lu bytes)",
       (unsigned long)length);

   /* TODO: validate format of calibration name and unit name */

   /* Check that the type matches the specification. */
   if (type < 0 || type > 3)
P
prr 已提交
361 362 363 364 365
   {
      png_chunk_report(png_ptr, "Invalid pCAL equation type",
            PNG_CHUNK_WRITE_ERROR);
      return;
   }
B
bae 已提交
366

367
   if (nparams < 0 || nparams > 255)
P
prr 已提交
368 369 370 371 372
   {
      png_chunk_report(png_ptr, "Invalid pCAL parameter count",
            PNG_CHUNK_WRITE_ERROR);
      return;
   }
373

B
bae 已提交
374 375
   /* Validate params[nparams] */
   for (i=0; i<nparams; ++i)
376 377 378
   {
      if (params[i] == NULL ||
          !png_check_fp_string(params[i], strlen(params[i])))
P
prr 已提交
379 380 381 382 383
      {
         png_chunk_report(png_ptr, "Invalid format for pCAL parameter",
               PNG_CHUNK_WRITE_ERROR);
         return;
      }
384
   }
B
bae 已提交
385

386 387
   info_ptr->pcal_purpose = png_voidcast(png_charp,
       png_malloc_warn(png_ptr, length));
B
bae 已提交
388

D
duke 已提交
389
   if (info_ptr->pcal_purpose == NULL)
B
bae 已提交
390
   {
P
prr 已提交
391 392
      png_chunk_report(png_ptr, "Insufficient memory for pCAL purpose",
            PNG_CHUNK_WRITE_ERROR);
B
bae 已提交
393 394 395
      return;
   }

396
   memcpy(info_ptr->pcal_purpose, purpose, length);
D
duke 已提交
397

B
bae 已提交
398
   png_debug(3, "storing X0, X1, type, and nparams in info");
D
duke 已提交
399 400 401 402 403
   info_ptr->pcal_X0 = X0;
   info_ptr->pcal_X1 = X1;
   info_ptr->pcal_type = (png_byte)type;
   info_ptr->pcal_nparams = (png_byte)nparams;

404
   length = strlen(units) + 1;
B
bae 已提交
405
   png_debug1(3, "allocating units for info (%lu bytes)",
P
prr 已提交
406
       (unsigned long)length);
B
bae 已提交
407

408
   info_ptr->pcal_units = png_voidcast(png_charp,
P
prr 已提交
409
       png_malloc_warn(png_ptr, length));
B
bae 已提交
410

D
duke 已提交
411
   if (info_ptr->pcal_units == NULL)
B
bae 已提交
412 413
   {
      png_warning(png_ptr, "Insufficient memory for pCAL units");
414

B
bae 已提交
415 416 417
      return;
   }

418
   memcpy(info_ptr->pcal_units, units, length);
D
duke 已提交
419

420
   info_ptr->pcal_params = png_voidcast(png_charpp, png_malloc_warn(png_ptr,
P
prr 已提交
421
       (size_t)(((unsigned int)nparams + 1) * (sizeof (png_charp)))));
B
bae 已提交
422

D
duke 已提交
423
   if (info_ptr->pcal_params == NULL)
B
bae 已提交
424 425
   {
      png_warning(png_ptr, "Insufficient memory for pCAL params");
426

B
bae 已提交
427 428
      return;
   }
D
duke 已提交
429

P
prr 已提交
430 431
   memset(info_ptr->pcal_params, 0, ((unsigned int)nparams + 1) *
       (sizeof (png_charp)));
D
duke 已提交
432 433 434

   for (i = 0; i < nparams; i++)
   {
435
      length = strlen(params[i]) + 1;
B
bae 已提交
436 437 438
      png_debug2(3, "allocating parameter %d for info (%lu bytes)", i,
          (unsigned long)length);

D
duke 已提交
439
      info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length);
B
bae 已提交
440

D
duke 已提交
441
      if (info_ptr->pcal_params[i] == NULL)
B
bae 已提交
442 443
      {
         png_warning(png_ptr, "Insufficient memory for pCAL parameter");
444

B
bae 已提交
445 446 447
         return;
      }

448
      memcpy(info_ptr->pcal_params[i], params[i], length);
D
duke 已提交
449 450 451 452 453 454 455
   }

   info_ptr->valid |= PNG_INFO_pCAL;
   info_ptr->free_me |= PNG_FREE_PCAL;
}
#endif

B
bae 已提交
456
#ifdef PNG_sCAL_SUPPORTED
D
duke 已提交
457
void PNGAPI
458
png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
459
    int unit, png_const_charp swidth, png_const_charp sheight)
D
duke 已提交
460
{
P
prr 已提交
461
   size_t lengthw = 0, lengthh = 0;
B
bae 已提交
462 463 464

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

D
duke 已提交
465 466 467
   if (png_ptr == NULL || info_ptr == NULL)
      return;

B
bae 已提交
468 469 470 471 472
   /* 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");
D
duke 已提交
473

474
   if (swidth == NULL || (lengthw = strlen(swidth)) == 0 ||
B
bae 已提交
475 476
       swidth[0] == 45 /* '-' */ || !png_check_fp_string(swidth, lengthw))
      png_error(png_ptr, "Invalid sCAL width");
D
duke 已提交
477

478
   if (sheight == NULL || (lengthh = strlen(sheight)) == 0 ||
B
bae 已提交
479 480
       sheight[0] == 45 /* '-' */ || !png_check_fp_string(sheight, lengthh))
      png_error(png_ptr, "Invalid sCAL height");
D
duke 已提交
481 482 483

   info_ptr->scal_unit = (png_byte)unit;

B
bae 已提交
484 485 486 487
   ++lengthw;

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

488
   info_ptr->scal_s_width = png_voidcast(png_charp,
P
prr 已提交
489
       png_malloc_warn(png_ptr, lengthw));
B
bae 已提交
490

D
duke 已提交
491 492
   if (info_ptr->scal_s_width == NULL)
   {
B
bae 已提交
493
      png_warning(png_ptr, "Memory allocation failed while processing sCAL");
494

B
bae 已提交
495
      return;
D
duke 已提交
496 497
   }

498
   memcpy(info_ptr->scal_s_width, swidth, lengthw);
B
bae 已提交
499 500 501 502 503

   ++lengthh;

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

504
   info_ptr->scal_s_height = png_voidcast(png_charp,
P
prr 已提交
505
       png_malloc_warn(png_ptr, lengthh));
B
bae 已提交
506

D
duke 已提交
507 508 509
   if (info_ptr->scal_s_height == NULL)
   {
      png_free (png_ptr, info_ptr->scal_s_width);
B
bae 已提交
510 511 512
      info_ptr->scal_s_width = NULL;

      png_warning(png_ptr, "Memory allocation failed while processing sCAL");
513

B
bae 已提交
514
      return;
D
duke 已提交
515
   }
B
bae 已提交
516

517
   memcpy(info_ptr->scal_s_height, sheight, lengthh);
D
duke 已提交
518 519 520 521

   info_ptr->valid |= PNG_INFO_sCAL;
   info_ptr->free_me |= PNG_FREE_SCAL;
}
B
bae 已提交
522 523 524

#  ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
525 526
png_set_sCAL(png_const_structrp png_ptr, png_inforp info_ptr, int unit,
    double width, double height)
B
bae 已提交
527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542
{
   png_debug1(1, "in %s storage function", "sCAL");

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

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

   else
   {
      /* Convert 'width' and 'height' to ASCII. */
      char swidth[PNG_sCAL_MAX_DIGITS+1];
      char sheight[PNG_sCAL_MAX_DIGITS+1];

543
      png_ascii_from_fp(png_ptr, swidth, (sizeof swidth), width,
P
prr 已提交
544
          PNG_sCAL_PRECISION);
545
      png_ascii_from_fp(png_ptr, sheight, (sizeof sheight), height,
P
prr 已提交
546
          PNG_sCAL_PRECISION);
B
bae 已提交
547 548 549 550 551 552 553 554

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

#  ifdef PNG_FIXED_POINT_SUPPORTED
void PNGAPI
555
png_set_sCAL_fixed(png_const_structrp png_ptr, png_inforp info_ptr, int unit,
B
bae 已提交
556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572
    png_fixed_point width, png_fixed_point height)
{
   png_debug1(1, "in %s storage function", "sCAL");

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

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

   else
   {
      /* Convert 'width' and 'height' to ASCII. */
      char swidth[PNG_sCAL_MAX_DIGITS+1];
      char sheight[PNG_sCAL_MAX_DIGITS+1];

573 574
      png_ascii_from_fixed(png_ptr, swidth, (sizeof swidth), width);
      png_ascii_from_fixed(png_ptr, sheight, (sizeof sheight), height);
B
bae 已提交
575 576 577 578 579

      png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight);
   }
}
#  endif
D
duke 已提交
580 581
#endif

B
bae 已提交
582
#ifdef PNG_pHYs_SUPPORTED
D
duke 已提交
583
void PNGAPI
584
png_set_pHYs(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
585
    png_uint_32 res_x, png_uint_32 res_y, int unit_type)
D
duke 已提交
586
{
B
bae 已提交
587 588
   png_debug1(1, "in %s storage function", "pHYs");

D
duke 已提交
589 590 591 592 593 594 595 596 597 598 599
   if (png_ptr == NULL || info_ptr == NULL)
      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

void PNGAPI
600
png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
601
    png_const_colorp palette, int num_palette)
D
duke 已提交
602 603
{

604 605
   png_uint_32 max_palette_length;

B
bae 已提交
606 607
   png_debug1(1, "in %s storage function", "PLTE");

D
duke 已提交
608 609 610
   if (png_ptr == NULL || info_ptr == NULL)
      return;

611 612 613 614
   max_palette_length = (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ?
      (1 << info_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH;

   if (num_palette < 0 || num_palette > (int) max_palette_length)
B
bae 已提交
615 616
   {
      if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
D
duke 已提交
617
         png_error(png_ptr, "Invalid palette length");
B
bae 已提交
618 619 620

      else
      {
D
duke 已提交
621
         png_warning(png_ptr, "Invalid palette length");
622

D
duke 已提交
623
         return;
B
bae 已提交
624 625
      }
   }
D
duke 已提交
626

S
serb 已提交
627 628 629 630 631 632 633 634 635 636
   if ((num_palette > 0 && palette == NULL) ||
      (num_palette == 0
#        ifdef PNG_MNG_FEATURES_SUPPORTED
            && (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0
#        endif
      ))
   {
      png_error(png_ptr, "Invalid palette");
   }

B
bae 已提交
637
   /* It may not actually be necessary to set png_ptr->palette here;
D
duke 已提交
638 639
    * we do it for backward compatibility with the way the png_handle_tRNS
    * function used to do the allocation.
640 641 642
    *
    * 1.6.0: the above statement appears to be incorrect; something has to set
    * the palette inside png_struct on read.
D
duke 已提交
643 644 645 646
    */
   png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0);

   /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead
647 648
    * of num_palette entries, in case of an invalid PNG file or incorrect
    * call to png_set_PLTE() with too-large sample values.
B
bae 已提交
649
    */
650 651
   png_ptr->palette = png_voidcast(png_colorp, png_calloc(png_ptr,
       PNG_MAX_PALETTE_LENGTH * (sizeof (png_color))));
B
bae 已提交
652

653
   if (num_palette > 0)
P
prr 已提交
654 655
      memcpy(png_ptr->palette, palette, (unsigned int)num_palette *
          (sizeof (png_color)));
D
duke 已提交
656 657 658 659 660 661 662 663
   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;

   info_ptr->valid |= PNG_INFO_PLTE;
}

B
bae 已提交
664
#ifdef PNG_sBIT_SUPPORTED
D
duke 已提交
665
void PNGAPI
666
png_set_sBIT(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
667
    png_const_color_8p sig_bit)
D
duke 已提交
668
{
B
bae 已提交
669 670
   png_debug1(1, "in %s storage function", "sBIT");

671
   if (png_ptr == NULL || info_ptr == NULL || sig_bit == NULL)
D
duke 已提交
672 673
      return;

674
   info_ptr->sig_bit = *sig_bit;
D
duke 已提交
675 676 677 678
   info_ptr->valid |= PNG_INFO_sBIT;
}
#endif

B
bae 已提交
679
#ifdef PNG_sRGB_SUPPORTED
D
duke 已提交
680
void PNGAPI
681
png_set_sRGB(png_const_structrp png_ptr, png_inforp info_ptr, int srgb_intent)
D
duke 已提交
682
{
B
bae 已提交
683 684
   png_debug1(1, "in %s storage function", "sRGB");

D
duke 已提交
685 686 687
   if (png_ptr == NULL || info_ptr == NULL)
      return;

688 689
   (void)png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace, srgb_intent);
   png_colorspace_sync_info(png_ptr, info_ptr);
D
duke 已提交
690 691 692
}

void PNGAPI
693
png_set_sRGB_gAMA_and_cHRM(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
694
    int srgb_intent)
D
duke 已提交
695
{
B
bae 已提交
696 697
   png_debug1(1, "in %s storage function", "sRGB_gAMA_and_cHRM");

D
duke 已提交
698 699 700
   if (png_ptr == NULL || info_ptr == NULL)
      return;

701 702 703 704 705 706 707
   if (png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace,
       srgb_intent) != 0)
   {
      /* This causes the gAMA and cHRM to be written too */
      info_ptr->colorspace.flags |=
         PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM;
   }
D
duke 已提交
708

709
   png_colorspace_sync_info(png_ptr, info_ptr);
D
duke 已提交
710
}
B
bae 已提交
711
#endif /* sRGB */
D
duke 已提交
712 713


B
bae 已提交
714
#ifdef PNG_iCCP_SUPPORTED
D
duke 已提交
715
void PNGAPI
716
png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
717 718
    png_const_charp name, int compression_type,
    png_const_bytep profile, png_uint_32 proflen)
D
duke 已提交
719 720
{
   png_charp new_iccp_name;
B
bae 已提交
721
   png_bytep new_iccp_profile;
P
prr 已提交
722
   size_t length;
B
bae 已提交
723 724

   png_debug1(1, "in %s storage function", "iCCP");
D
duke 已提交
725 726 727 728

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

729 730 731 732 733 734 735 736 737 738 739
   if (compression_type != PNG_COMPRESSION_TYPE_BASE)
      png_app_error(png_ptr, "Invalid iCCP compression method");

   /* Set the colorspace first because this validates the profile; do not
    * override previously set app cHRM or gAMA here (because likely as not the
    * application knows better than libpng what the correct values are.)  Pass
    * the info_ptr color_type field to png_colorspace_set_ICC because in the
    * write case it has not yet been stored in png_ptr.
    */
   {
      int result = png_colorspace_set_ICC(png_ptr, &info_ptr->colorspace, name,
P
prr 已提交
740
          proflen, profile, info_ptr->color_type);
741 742 743 744 745 746 747 748 749 750 751 752 753 754

      png_colorspace_sync_info(png_ptr, info_ptr);

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

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

   length = strlen(name)+1;
   new_iccp_name = png_voidcast(png_charp, png_malloc_warn(png_ptr, length));
B
bae 已提交
755

D
duke 已提交
756 757
   if (new_iccp_name == NULL)
   {
758 759
      png_benign_error(png_ptr, "Insufficient memory to process iCCP chunk");

D
duke 已提交
760 761
      return;
   }
B
bae 已提交
762

763 764
   memcpy(new_iccp_name, name, length);
   new_iccp_profile = png_voidcast(png_bytep,
P
prr 已提交
765
       png_malloc_warn(png_ptr, proflen));
B
bae 已提交
766

D
duke 已提交
767 768
   if (new_iccp_profile == NULL)
   {
769 770
      png_free(png_ptr, new_iccp_name);
      png_benign_error(png_ptr,
B
bae 已提交
771
          "Insufficient memory to process iCCP profile");
772

D
duke 已提交
773 774
      return;
   }
B
bae 已提交
775

776
   memcpy(new_iccp_profile, profile, proflen);
D
duke 已提交
777 778 779 780 781 782 783 784 785 786 787

   png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0);

   info_ptr->iccp_proflen = proflen;
   info_ptr->iccp_name = new_iccp_name;
   info_ptr->iccp_profile = new_iccp_profile;
   info_ptr->free_me |= PNG_FREE_ICCP;
   info_ptr->valid |= PNG_INFO_iCCP;
}
#endif

B
bae 已提交
788
#ifdef PNG_TEXT_SUPPORTED
D
duke 已提交
789
void PNGAPI
790 791
png_set_text(png_const_structrp png_ptr, png_inforp info_ptr,
    png_const_textp text_ptr, int num_text)
D
duke 已提交
792 793
{
   int ret;
B
bae 已提交
794 795
   ret = png_set_text_2(png_ptr, info_ptr, text_ptr, num_text);

796
   if (ret != 0)
B
bae 已提交
797
      png_error(png_ptr, "Insufficient memory to store text");
D
duke 已提交
798 799 800
}

int /* PRIVATE */
801
png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
802
    png_const_textp text_ptr, int num_text)
D
duke 已提交
803 804 805
{
   int i;

806 807
   png_debug1(1, "in %lx storage function", png_ptr == NULL ? 0xabadca11U :
      (unsigned long)png_ptr->chunk_name);
D
duke 已提交
808

809
   if (png_ptr == NULL || info_ptr == NULL || num_text <= 0 || text_ptr == NULL)
D
duke 已提交
810 811 812
      return(0);

   /* Make sure we have enough space in the "text" array in info_struct
813 814 815
    * to hold all of the incoming text_ptr objects.  This compare can't overflow
    * because max_text >= num_text (anyway, subtract of two positive integers
    * can't overflow in any case.)
D
duke 已提交
816
    */
817
   if (num_text > info_ptr->max_text - info_ptr->num_text)
D
duke 已提交
818
   {
819 820 821
      int old_num_text = info_ptr->num_text;
      int max_text;
      png_textp new_text = NULL;
B
bae 已提交
822

823 824 825 826 827
      /* Calculate an appropriate max_text, checking for overflow. */
      max_text = old_num_text;
      if (num_text <= INT_MAX - max_text)
      {
         max_text += num_text;
B
bae 已提交
828

829 830 831
         /* Round up to a multiple of 8 */
         if (max_text < INT_MAX-8)
            max_text = (max_text + 8) & ~0x7;
A
azvegint 已提交
832

833 834 835 836 837 838 839
         else
            max_text = INT_MAX;

         /* Now allocate a new array and copy the old members in; this does all
          * the overflow checks.
          */
         new_text = png_voidcast(png_textp,png_realloc_array(png_ptr,
P
prr 已提交
840 841
             info_ptr->text, old_num_text, max_text-old_num_text,
             sizeof *new_text));
D
duke 已提交
842
      }
B
bae 已提交
843

844
      if (new_text == NULL)
D
duke 已提交
845
      {
846
         png_chunk_report(png_ptr, "too many text chunks",
P
prr 已提交
847
             PNG_CHUNK_WRITE_ERROR);
848 849

         return 1;
D
duke 已提交
850
      }
B
bae 已提交
851

852 853 854 855 856 857 858 859
      png_free(png_ptr, info_ptr->text);

      info_ptr->text = new_text;
      info_ptr->free_me |= PNG_FREE_TEXT;
      info_ptr->max_text = max_text;
      /* num_text is adjusted below as the entries are copied in */

      png_debug1(3, "allocated %d entries for info_ptr->text", max_text);
D
duke 已提交
860
   }
861

D
duke 已提交
862 863
   for (i = 0; i < num_text; i++)
   {
864 865
      size_t text_length, key_len;
      size_t lang_len, lang_key_len;
D
duke 已提交
866 867 868 869 870
      png_textp textp = &(info_ptr->text[info_ptr->num_text]);

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

B
bae 已提交
871 872 873
      if (text_ptr[i].compression < PNG_TEXT_COMPRESSION_NONE ||
          text_ptr[i].compression >= PNG_TEXT_COMPRESSION_LAST)
      {
874
         png_chunk_report(png_ptr, "text compression mode is out of range",
P
prr 已提交
875
             PNG_CHUNK_WRITE_ERROR);
B
bae 已提交
876 877 878
         continue;
      }

879
      key_len = strlen(text_ptr[i].key);
D
duke 已提交
880

B
bae 已提交
881
      if (text_ptr[i].compression <= 0)
D
duke 已提交
882
      {
B
bae 已提交
883 884
         lang_len = 0;
         lang_key_len = 0;
D
duke 已提交
885
      }
B
bae 已提交
886

D
duke 已提交
887
      else
B
bae 已提交
888
#  ifdef PNG_iTXt_SUPPORTED
D
duke 已提交
889
      {
B
bae 已提交
890 891 892
         /* Set iTXt data */

         if (text_ptr[i].lang != NULL)
893
            lang_len = strlen(text_ptr[i].lang);
B
bae 已提交
894 895 896 897 898

         else
            lang_len = 0;

         if (text_ptr[i].lang_key != NULL)
899
            lang_key_len = strlen(text_ptr[i].lang_key);
B
bae 已提交
900 901 902

         else
            lang_key_len = 0;
D
duke 已提交
903
      }
904
#  else /* iTXt */
D
duke 已提交
905
      {
906
         png_chunk_report(png_ptr, "iTXt chunk not supported",
P
prr 已提交
907
             PNG_CHUNK_WRITE_ERROR);
B
bae 已提交
908
         continue;
D
duke 已提交
909
      }
B
bae 已提交
910
#  endif
D
duke 已提交
911 912 913 914

      if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0')
      {
         text_length = 0;
B
bae 已提交
915 916
#  ifdef PNG_iTXt_SUPPORTED
         if (text_ptr[i].compression > 0)
D
duke 已提交
917
            textp->compression = PNG_ITXT_COMPRESSION_NONE;
B
bae 已提交
918

D
duke 已提交
919
         else
B
bae 已提交
920
#  endif
D
duke 已提交
921 922
            textp->compression = PNG_TEXT_COMPRESSION_NONE;
      }
B
bae 已提交
923

D
duke 已提交
924 925
      else
      {
926
         text_length = strlen(text_ptr[i].text);
D
duke 已提交
927 928 929
         textp->compression = text_ptr[i].compression;
      }

930 931
      textp->key = png_voidcast(png_charp,png_malloc_base(png_ptr,
          key_len + text_length + lang_len + lang_key_len + 4));
B
bae 已提交
932

D
duke 已提交
933
      if (textp->key == NULL)
934 935
      {
         png_chunk_report(png_ptr, "text chunk: out of memory",
P
prr 已提交
936
             PNG_CHUNK_WRITE_ERROR);
937 938 939

         return 1;
      }
B
bae 已提交
940 941 942 943 944 945

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

946
      memcpy(textp->key, text_ptr[i].key, key_len);
B
bae 已提交
947 948
      *(textp->key + key_len) = '\0';

D
duke 已提交
949 950
      if (text_ptr[i].compression > 0)
      {
B
bae 已提交
951
         textp->lang = textp->key + key_len + 1;
952
         memcpy(textp->lang, text_ptr[i].lang, lang_len);
B
bae 已提交
953 954
         *(textp->lang + lang_len) = '\0';
         textp->lang_key = textp->lang + lang_len + 1;
955
         memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len);
B
bae 已提交
956 957
         *(textp->lang_key + lang_key_len) = '\0';
         textp->text = textp->lang_key + lang_key_len + 1;
D
duke 已提交
958
      }
B
bae 已提交
959

D
duke 已提交
960 961 962 963
      else
      {
         textp->lang=NULL;
         textp->lang_key=NULL;
B
bae 已提交
964
         textp->text = textp->key + key_len + 1;
D
duke 已提交
965
      }
B
bae 已提交
966

967 968
      if (text_length != 0)
         memcpy(textp->text, text_ptr[i].text, text_length);
D
duke 已提交
969

B
bae 已提交
970 971 972 973
      *(textp->text + text_length) = '\0';

#  ifdef PNG_iTXt_SUPPORTED
      if (textp->compression > 0)
D
duke 已提交
974 975 976 977
      {
         textp->text_length = 0;
         textp->itxt_length = text_length;
      }
B
bae 已提交
978

D
duke 已提交
979
      else
B
bae 已提交
980
#  endif
D
duke 已提交
981 982 983 984
      {
         textp->text_length = text_length;
         textp->itxt_length = 0;
      }
B
bae 已提交
985

D
duke 已提交
986
      info_ptr->num_text++;
B
bae 已提交
987
      png_debug1(3, "transferred text chunk %d", info_ptr->num_text);
D
duke 已提交
988
   }
989

D
duke 已提交
990 991 992 993
   return(0);
}
#endif

B
bae 已提交
994
#ifdef PNG_tIME_SUPPORTED
D
duke 已提交
995
void PNGAPI
996 997
png_set_tIME(png_const_structrp png_ptr, png_inforp info_ptr,
    png_const_timep mod_time)
D
duke 已提交
998
{
B
bae 已提交
999 1000
   png_debug1(1, "in %s storage function", "tIME");

1001 1002
   if (png_ptr == NULL || info_ptr == NULL || mod_time == NULL ||
       (png_ptr->mode & PNG_WROTE_tIME) != 0)
D
duke 已提交
1003 1004
      return;

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

   info_ptr->mod_time = *mod_time;
D
duke 已提交
1016 1017 1018 1019
   info_ptr->valid |= PNG_INFO_tIME;
}
#endif

B
bae 已提交
1020
#ifdef PNG_tRNS_SUPPORTED
D
duke 已提交
1021
void PNGAPI
1022
png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
1023
    png_const_bytep trans_alpha, int num_trans, png_const_color_16p trans_color)
D
duke 已提交
1024
{
B
bae 已提交
1025 1026
   png_debug1(1, "in %s storage function", "tRNS");

D
duke 已提交
1027
   if (png_ptr == NULL || info_ptr == NULL)
1028

D
duke 已提交
1029 1030
      return;

B
bae 已提交
1031
   if (trans_alpha != NULL)
D
duke 已提交
1032
   {
B
bae 已提交
1033
       /* It may not actually be necessary to set png_ptr->trans_alpha here;
D
duke 已提交
1034 1035
        * we do it for backward compatibility with the way the png_handle_tRNS
        * function used to do the allocation.
1036 1037 1038 1039
        *
        * 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).
D
duke 已提交
1040
        */
B
bae 已提交
1041

D
duke 已提交
1042
       png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
B
bae 已提交
1043 1044

       if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH)
1045 1046 1047
       {
         /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */
          info_ptr->trans_alpha = png_voidcast(png_bytep,
P
prr 已提交
1048
              png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH));
P
prr 已提交
1049
          memcpy(info_ptr->trans_alpha, trans_alpha, (size_t)num_trans);
1050 1051
       }
       png_ptr->trans_alpha = info_ptr->trans_alpha;
D
duke 已提交
1052 1053
   }

B
bae 已提交
1054
   if (trans_color != NULL)
D
duke 已提交
1055
   {
1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067
#ifdef PNG_WARNINGS_SUPPORTED
      if (info_ptr->bit_depth < 16)
      {
         int sample_max = (1 << info_ptr->bit_depth) - 1;

         if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY &&
             trans_color->gray > sample_max) ||
             (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
             (trans_color->red > sample_max ||
             trans_color->green > sample_max ||
             trans_color->blue > sample_max)))
            png_warning(png_ptr,
P
prr 已提交
1068
                "tRNS chunk has out-of-range samples for bit_depth");
1069 1070
      }
#endif
B
bae 已提交
1071

1072
      info_ptr->trans_color = *trans_color;
B
bae 已提交
1073

D
duke 已提交
1074
      if (num_trans == 0)
B
bae 已提交
1075
         num_trans = 1;
D
duke 已提交
1076
   }
B
bae 已提交
1077

D
duke 已提交
1078
   info_ptr->num_trans = (png_uint_16)num_trans;
B
bae 已提交
1079 1080 1081 1082 1083 1084

   if (num_trans != 0)
   {
      info_ptr->valid |= PNG_INFO_tRNS;
      info_ptr->free_me |= PNG_FREE_TRNS;
   }
D
duke 已提交
1085 1086 1087
}
#endif

B
bae 已提交
1088
#ifdef PNG_sPLT_SUPPORTED
D
duke 已提交
1089
void PNGAPI
1090 1091
png_set_sPLT(png_const_structrp png_ptr,
    png_inforp info_ptr, png_const_sPLT_tp entries, int nentries)
B
bae 已提交
1092 1093 1094 1095 1096 1097 1098 1099
/*
 *  entries        - array of png_sPLT_t structures
 *                   to be added to the list of palettes
 *                   in the info structure.
 *
 *  nentries       - number of palette structures to be
 *                   added.
 */
D
duke 已提交
1100
{
B
bae 已提交
1101
   png_sPLT_tp np;
D
duke 已提交
1102

1103
   if (png_ptr == NULL || info_ptr == NULL || nentries <= 0 || entries == NULL)
B
bae 已提交
1104
      return;
D
duke 已提交
1105

1106 1107 1108 1109
   /* Use the internal realloc function, which checks for all the possible
    * overflows.  Notice that the parameters are (int) and (size_t)
    */
   np = png_voidcast(png_sPLT_tp,png_realloc_array(png_ptr,
P
prr 已提交
1110 1111
       info_ptr->splt_palettes, info_ptr->splt_palettes_num, nentries,
       sizeof *np));
B
bae 已提交
1112 1113 1114

   if (np == NULL)
   {
1115 1116 1117
      /* Out of memory or too many chunks */
      png_chunk_report(png_ptr, "too many sPLT chunks", PNG_CHUNK_WRITE_ERROR);

D
duke 已提交
1118
      return;
B
bae 已提交
1119
   }
D
duke 已提交
1120

A
azvegint 已提交
1121
   png_free(png_ptr, info_ptr->splt_palettes);
1122 1123
   info_ptr->splt_palettes = np;
   info_ptr->free_me |= PNG_FREE_SPLT;
B
bae 已提交
1124

1125
   np += info_ptr->splt_palettes_num;
A
azvegint 已提交
1126

1127 1128
   do
   {
P
prr 已提交
1129
      size_t length;
B
bae 已提交
1130

1131 1132
      /* Skip invalid input entries */
      if (entries->name == NULL || entries->entries == NULL)
B
bae 已提交
1133
      {
1134 1135 1136
         /* png_handle_sPLT doesn't do this, so this is an app error */
         png_app_error(png_ptr, "png_set_sPLT: invalid sPLT");
         /* Just skip the invalid entry */
B
bae 已提交
1137 1138 1139
         continue;
      }

1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158
      np->depth = entries->depth;

      /* In the event of out-of-memory just return - there's no point keeping
       * on trying to add sPLT chunks.
       */
      length = strlen(entries->name) + 1;
      np->name = png_voidcast(png_charp, png_malloc_base(png_ptr, length));

      if (np->name == NULL)
         break;

      memcpy(np->name, entries->name, length);

      /* IMPORTANT: we have memory now that won't get freed if something else
       * goes wrong; this code must free it.  png_malloc_array produces no
       * warnings; use a png_chunk_report (below) if there is an error.
       */
      np->entries = png_voidcast(png_sPLT_entryp, png_malloc_array(png_ptr,
          entries->nentries, sizeof (png_sPLT_entry)));
B
bae 已提交
1159

1160
      if (np->entries == NULL)
B
bae 已提交
1161
      {
1162 1163 1164
         png_free(png_ptr, np->name);
         np->name = NULL;
         break;
B
bae 已提交
1165 1166
      }

1167 1168 1169 1170 1171
      np->nentries = entries->nentries;
      /* This multiply can't overflow because png_malloc_array has already
       * checked it when doing the allocation.
       */
      memcpy(np->entries, entries->entries,
P
prr 已提交
1172
          (unsigned int)entries->nentries * sizeof (png_sPLT_entry));
1173 1174 1175 1176 1177 1178 1179

      /* Note that 'continue' skips the advance of the out pointer and out
       * count, so an invalid entry is not added.
       */
      info_ptr->valid |= PNG_INFO_sPLT;
      ++(info_ptr->splt_palettes_num);
      ++np;
P
prr 已提交
1180
      ++entries;
1181
   }
P
prr 已提交
1182
   while (--nentries);
1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193

   if (nentries > 0)
      png_chunk_report(png_ptr, "sPLT out of memory", PNG_CHUNK_WRITE_ERROR);
}
#endif /* sPLT */

#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
static png_byte
check_location(png_const_structrp png_ptr, int location)
{
   location &= (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT);
B
bae 已提交
1194

1195 1196 1197 1198 1199 1200 1201 1202
   /* New in 1.6.0; copy the location and check it.  This is an API
    * change; previously the app had to use the
    * png_set_unknown_chunk_location API below for each chunk.
    */
   if (location == 0 && (png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
   {
      /* Write struct, so unknown chunks come from the app */
      png_app_warning(png_ptr,
P
prr 已提交
1203
          "png_set_unknown_chunks now expects a valid location");
1204 1205
      /* Use the old behavior */
      location = (png_byte)(png_ptr->mode &
P
prr 已提交
1206
          (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT));
B
bae 已提交
1207 1208
   }

1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224
   /* This need not be an internal error - if the app calls
    * png_set_unknown_chunks on a read pointer it must get the location right.
    */
   if (location == 0)
      png_error(png_ptr, "invalid location in png_set_unknown_chunks");

   /* Now reduce the location to the top-most set bit by removing each least
    * significant bit in turn.
    */
   while (location != (location & -location))
      location &= ~(location & -location);

   /* The cast is safe because 'location' is a bit mask and only the low four
    * bits are significant.
    */
   return (png_byte)location;
D
duke 已提交
1225 1226 1227
}

void PNGAPI
1228
png_set_unknown_chunks(png_const_structrp png_ptr,
P
prr 已提交
1229
    png_inforp info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns)
D
duke 已提交
1230
{
B
bae 已提交
1231 1232
   png_unknown_chunkp np;

1233 1234
   if (png_ptr == NULL || info_ptr == NULL || num_unknowns <= 0 ||
       unknowns == NULL)
B
bae 已提交
1235
      return;
D
duke 已提交
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
   /* Check for the failure cases where support has been disabled at compile
    * time.  This code is hardly ever compiled - it's here because
    * STORE_UNKNOWN_CHUNKS is set by both read and write code (compiling in this
    * code) but may be meaningless if the read or write handling of unknown
    * chunks is not compiled in.
    */
#  if !defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) && \
      defined(PNG_READ_SUPPORTED)
      if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
      {
         png_app_error(png_ptr, "no unknown chunk support on read");

         return;
      }
#  endif
#  if !defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) && \
      defined(PNG_WRITE_SUPPORTED)
      if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
      {
         png_app_error(png_ptr, "no unknown chunk support on write");

         return;
      }
#  endif

   /* Prior to 1.6.0 this code used png_malloc_warn; however, this meant that
    * unknown critical chunks could be lost with just a warning resulting in
    * undefined behavior.  Now png_chunk_report is used to provide behavior
    * appropriate to read or write.
    */
   np = png_voidcast(png_unknown_chunkp, png_realloc_array(png_ptr,
P
prr 已提交
1268 1269
       info_ptr->unknown_chunks, info_ptr->unknown_chunks_num, num_unknowns,
       sizeof *np));
D
duke 已提交
1270

B
bae 已提交
1271 1272
   if (np == NULL)
   {
1273
      png_chunk_report(png_ptr, "too many unknown chunks",
P
prr 已提交
1274
          PNG_CHUNK_WRITE_ERROR);
1275

B
bae 已提交
1276 1277
      return;
   }
D
duke 已提交
1278

A
azvegint 已提交
1279
   png_free(png_ptr, info_ptr->unknown_chunks);
1280 1281
   info_ptr->unknown_chunks = np; /* safe because it is initialized */
   info_ptr->free_me |= PNG_FREE_UNKN;
B
bae 已提交
1282

1283
   np += info_ptr->unknown_chunks_num;
A
azvegint 已提交
1284

1285 1286 1287 1288 1289 1290 1291 1292
   /* Increment unknown_chunks_num each time round the loop to protect the
    * just-allocated chunk data.
    */
   for (; num_unknowns > 0; --num_unknowns, ++unknowns)
   {
      memcpy(np->name, unknowns->name, (sizeof np->name));
      np->name[(sizeof np->name)-1] = '\0';
      np->location = check_location(png_ptr, unknowns->location);
A
azvegint 已提交
1293

1294 1295 1296 1297 1298
      if (unknowns->size == 0)
      {
         np->data = NULL;
         np->size = 0;
      }
B
bae 已提交
1299 1300 1301

      else
      {
1302
         np->data = png_voidcast(png_bytep,
P
prr 已提交
1303
             png_malloc_base(png_ptr, unknowns->size));
B
bae 已提交
1304

1305
         if (np->data == NULL)
B
bae 已提交
1306
         {
1307
            png_chunk_report(png_ptr, "unknown chunk: out of memory",
P
prr 已提交
1308
                PNG_CHUNK_WRITE_ERROR);
1309 1310
            /* But just skip storing the unknown chunk */
            continue;
B
bae 已提交
1311 1312
         }

1313 1314
         memcpy(np->data, unknowns->data, unknowns->size);
         np->size = unknowns->size;
B
bae 已提交
1315
      }
A
azvegint 已提交
1316

1317 1318 1319 1320 1321 1322 1323
      /* These increments are skipped on out-of-memory for the data - the
       * unknown chunk entry gets overwritten if the png_chunk_report returns.
       * This is correct in the read case (the chunk is just dropped.)
       */
      ++np;
      ++(info_ptr->unknown_chunks_num);
   }
D
duke 已提交
1324
}
B
bae 已提交
1325

D
duke 已提交
1326
void PNGAPI
1327
png_set_unknown_chunk_location(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
1328
    int chunk, int location)
D
duke 已提交
1329
{
1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341
   /* This API is pretty pointless in 1.6.0 because the location can be set
    * before the call to png_set_unknown_chunks.
    *
    * TODO: add a png_app_warning in 1.7
    */
   if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 &&
      chunk < info_ptr->unknown_chunks_num)
   {
      if ((location & (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT)) == 0)
      {
         png_app_error(png_ptr, "invalid unknown chunk location");
         /* Fake out the pre 1.6.0 behavior: */
P
prr 已提交
1342
         if (((unsigned int)location & PNG_HAVE_IDAT) != 0) /* undocumented! */
1343 1344 1345 1346 1347
            location = PNG_AFTER_IDAT;

         else
            location = PNG_HAVE_IHDR; /* also undocumented */
      }
D
duke 已提交
1348

1349 1350 1351 1352 1353
      info_ptr->unknown_chunks[chunk].location =
         check_location(png_ptr, location);
   }
}
#endif /* STORE_UNKNOWN_CHUNKS */
D
duke 已提交
1354

B
bae 已提交
1355
#ifdef PNG_MNG_FEATURES_SUPPORTED
D
duke 已提交
1356
png_uint_32 PNGAPI
1357
png_permit_mng_features (png_structrp png_ptr, png_uint_32 mng_features)
D
duke 已提交
1358
{
B
bae 已提交
1359 1360
   png_debug(1, "in png_permit_mng_features");

D
duke 已提交
1361
   if (png_ptr == NULL)
1362
      return 0;
B
bae 已提交
1363

1364
   png_ptr->mng_features_permitted = mng_features & PNG_ALL_MNG_FEATURES;
B
bae 已提交
1365

1366
   return png_ptr->mng_features_permitted;
D
duke 已提交
1367 1368 1369
}
#endif

B
bae 已提交
1370
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398
static unsigned int
add_one_chunk(png_bytep list, unsigned int count, png_const_bytep add, int keep)
{
   unsigned int i;

   /* Utility function: update the 'keep' state of a chunk if it is already in
    * the list, otherwise add it to the list.
    */
   for (i=0; i<count; ++i, list += 5)
   {
      if (memcmp(list, add, 4) == 0)
      {
         list[4] = (png_byte)keep;

         return count;
      }
   }

   if (keep != PNG_HANDLE_CHUNK_AS_DEFAULT)
   {
      ++count;
      memcpy(list, add, 4);
      list[4] = (png_byte)keep;
   }

   return count;
}

D
duke 已提交
1399
void PNGAPI
1400 1401
png_set_keep_unknown_chunks(png_structrp png_ptr, int keep,
    png_const_bytep chunk_list, int num_chunks_in)
D
duke 已提交
1402
{
1403 1404 1405
   png_bytep new_list;
   unsigned int num_chunks, old_num_chunks;

B
bae 已提交
1406 1407 1408
   if (png_ptr == NULL)
      return;

1409
   if (keep < 0 || keep >= PNG_HANDLE_CHUNK_LAST)
B
bae 已提交
1410
   {
1411
      png_app_error(png_ptr, "png_set_keep_unknown_chunks: invalid keep");
B
bae 已提交
1412

1413 1414
      return;
   }
B
bae 已提交
1415

1416 1417 1418
   if (num_chunks_in <= 0)
   {
      png_ptr->unknown_default = keep;
A
azvegint 已提交
1419

1420 1421 1422 1423
      /* '0' means just set the flags, so stop here */
      if (num_chunks_in == 0)
        return;
   }
A
azvegint 已提交
1424

1425 1426 1427 1428 1429
   if (num_chunks_in < 0)
   {
      /* Ignore all unknown chunks and all chunks recognized by
       * libpng except for IHDR, PLTE, tRNS, IDAT, and IEND
       */
S
serb 已提交
1430
      static const png_byte chunks_to_ignore[] = {
1431 1432
         98,  75,  71,  68, '\0',  /* bKGD */
         99,  72,  82,  77, '\0',  /* cHRM */
P
prr 已提交
1433
        101,  88,  73, 102, '\0',  /* eXIf */
1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452
        103,  65,  77,  65, '\0',  /* gAMA */
        104,  73,  83,  84, '\0',  /* hIST */
        105,  67,  67,  80, '\0',  /* iCCP */
        105,  84,  88, 116, '\0',  /* iTXt */
        111,  70,  70, 115, '\0',  /* oFFs */
        112,  67,  65,  76, '\0',  /* pCAL */
        112,  72,  89, 115, '\0',  /* pHYs */
        115,  66,  73,  84, '\0',  /* sBIT */
        115,  67,  65,  76, '\0',  /* sCAL */
        115,  80,  76,  84, '\0',  /* sPLT */
        115,  84,  69,  82, '\0',  /* sTER */
        115,  82,  71,  66, '\0',  /* sRGB */
        116,  69,  88, 116, '\0',  /* tEXt */
        116,  73,  77,  69, '\0',  /* tIME */
        122,  84,  88, 116, '\0'   /* zTXt */
      };

      chunk_list = chunks_to_ignore;
      num_chunks = (unsigned int)/*SAFE*/(sizeof chunks_to_ignore)/5U;
A
azvegint 已提交
1453
   }
B
bae 已提交
1454

1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466
   else /* num_chunks_in > 0 */
   {
      if (chunk_list == NULL)
      {
         /* Prior to 1.6.0 this was silently ignored, now it is an app_error
          * which can be switched off.
          */
         png_app_error(png_ptr, "png_set_keep_unknown_chunks: no chunk list");

         return;
      }

P
prr 已提交
1467
      num_chunks = (unsigned int)num_chunks_in;
1468
   }
A
azvegint 已提交
1469

A
azvegint 已提交
1470
   old_num_chunks = png_ptr->num_chunk_list;
1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490
   if (png_ptr->chunk_list == NULL)
      old_num_chunks = 0;

   /* Since num_chunks is always restricted to UINT_MAX/5 this can't overflow.
    */
   if (num_chunks + old_num_chunks > UINT_MAX/5)
   {
      png_app_error(png_ptr, "png_set_keep_unknown_chunks: too many chunks");

      return;
   }

   /* If these chunks are being reset to the default then no more memory is
    * required because add_one_chunk above doesn't extend the list if the 'keep'
    * parameter is the default.
    */
   if (keep != 0)
   {
      new_list = png_voidcast(png_bytep, png_malloc(png_ptr,
          5 * (num_chunks + old_num_chunks)));
B
bae 已提交
1491

1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507
      if (old_num_chunks > 0)
         memcpy(new_list, png_ptr->chunk_list, 5*old_num_chunks);
   }

   else if (old_num_chunks > 0)
      new_list = png_ptr->chunk_list;

   else
      new_list = NULL;

   /* Add the new chunks together with each one's handling code.  If the chunk
    * already exists the code is updated, otherwise the chunk is added to the
    * end.  (In libpng 1.6.0 order no longer matters because this code enforces
    * the earlier convention that the last setting is the one that is used.)
    */
   if (new_list != NULL)
B
bae 已提交
1508
   {
1509 1510 1511 1512 1513 1514 1515
      png_const_bytep inlist;
      png_bytep outlist;
      unsigned int i;

      for (i=0; i<num_chunks; ++i)
      {
         old_num_chunks = add_one_chunk(new_list, old_num_chunks,
P
prr 已提交
1516
             chunk_list+5*i, keep);
1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539
      }

      /* Now remove any spurious 'default' entries. */
      num_chunks = 0;
      for (i=0, inlist=outlist=new_list; i<old_num_chunks; ++i, inlist += 5)
      {
         if (inlist[4])
         {
            if (outlist != inlist)
               memcpy(outlist, inlist, 5);
            outlist += 5;
            ++num_chunks;
         }
      }

      /* This means the application has removed all the specialized handling. */
      if (num_chunks == 0)
      {
         if (png_ptr->chunk_list != new_list)
            png_free(png_ptr, new_list);

         new_list = NULL;
      }
B
bae 已提交
1540 1541
   }

1542 1543 1544 1545
   else
      num_chunks = 0;

   png_ptr->num_chunk_list = num_chunks;
B
bae 已提交
1546

1547 1548 1549 1550
   if (png_ptr->chunk_list != new_list)
   {
      if (png_ptr->chunk_list != NULL)
         png_free(png_ptr, png_ptr->chunk_list);
B
bae 已提交
1551

1552 1553
      png_ptr->chunk_list = new_list;
   }
D
duke 已提交
1554 1555 1556
}
#endif

B
bae 已提交
1557
#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
D
duke 已提交
1558
void PNGAPI
1559
png_set_read_user_chunk_fn(png_structrp png_ptr, png_voidp user_chunk_ptr,
B
bae 已提交
1560
    png_user_chunk_ptr read_user_chunk_fn)
D
duke 已提交
1561
{
B
bae 已提交
1562 1563
   png_debug(1, "in png_set_read_user_chunk_fn");

D
duke 已提交
1564 1565
   if (png_ptr == NULL)
      return;
B
bae 已提交
1566

D
duke 已提交
1567 1568 1569 1570 1571
   png_ptr->read_user_chunk_fn = read_user_chunk_fn;
   png_ptr->user_chunk_ptr = user_chunk_ptr;
}
#endif

B
bae 已提交
1572
#ifdef PNG_INFO_IMAGE_SUPPORTED
D
duke 已提交
1573
void PNGAPI
1574 1575
png_set_rows(png_const_structrp png_ptr, png_inforp info_ptr,
    png_bytepp row_pointers)
D
duke 已提交
1576
{
B
bae 已提交
1577
   png_debug1(1, "in %s storage function", "rows");
D
duke 已提交
1578 1579 1580 1581

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

1582 1583
   if (info_ptr->row_pointers != NULL &&
       (info_ptr->row_pointers != row_pointers))
D
duke 已提交
1584
      png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
B
bae 已提交
1585

D
duke 已提交
1586
   info_ptr->row_pointers = row_pointers;
B
bae 已提交
1587

1588
   if (row_pointers != NULL)
D
duke 已提交
1589 1590 1591 1592 1593
      info_ptr->valid |= PNG_INFO_IDAT;
}
#endif

void PNGAPI
P
prr 已提交
1594
png_set_compression_buffer_size(png_structrp png_ptr, size_t size)
D
duke 已提交
1595
{
P
prr 已提交
1596 1597
   if (png_ptr == NULL)
      return;
B
bae 已提交
1598

P
prr 已提交
1599 1600
   if (size == 0 || size > PNG_UINT_31_MAX)
      png_error(png_ptr, "invalid compression buffer size");
B
bae 已提交
1601

1602
#  ifdef PNG_SEQUENTIAL_READ_SUPPORTED
P
prr 已提交
1603 1604 1605 1606 1607
   if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
   {
      png_ptr->IDAT_read_size = (png_uint_32)size; /* checked above */
      return;
   }
1608 1609 1610
#  endif

#  ifdef PNG_WRITE_SUPPORTED
P
prr 已提交
1611 1612 1613
   if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
   {
      if (png_ptr->zowner != 0)
1614
      {
P
prr 已提交
1615 1616
         png_warning(png_ptr,
             "Compression buffer size cannot be changed because it is in use");
1617

P
prr 已提交
1618 1619
         return;
      }
B
bae 已提交
1620

1621
#ifndef __COVERITY__
P
prr 已提交
1622 1623 1624 1625 1626 1627 1628 1629 1630
      /* Some compilers complain that this is always false.  However, it
       * can be true when integer overflow happens.
       */
      if (size > ZLIB_IO_MAX)
      {
         png_warning(png_ptr,
             "Compression buffer size limited to system maximum");
         size = ZLIB_IO_MAX; /* must fit */
      }
1631
#endif
B
bae 已提交
1632

P
prr 已提交
1633 1634 1635 1636 1637 1638 1639
      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");
1640

P
prr 已提交
1641 1642
         return;
      }
B
bae 已提交
1643

P
prr 已提交
1644 1645 1646 1647
      if (png_ptr->zbuffer_size != size)
      {
         png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list);
         png_ptr->zbuffer_size = (uInt)size;
1648
      }
P
prr 已提交
1649
   }
1650
#  endif
D
duke 已提交
1651 1652 1653
}

void PNGAPI
1654
png_set_invalid(png_const_structrp png_ptr, png_inforp info_ptr, int mask)
D
duke 已提交
1655
{
1656
   if (png_ptr != NULL && info_ptr != NULL)
P
prr 已提交
1657
      info_ptr->valid &= (unsigned int)(~mask);
D
duke 已提交
1658 1659 1660
}


B
bae 已提交
1661 1662
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
/* This function was added to libpng 1.2.6 */
D
duke 已提交
1663
void PNGAPI
1664
png_set_user_limits (png_structrp png_ptr, png_uint_32 user_width_max,
B
bae 已提交
1665
    png_uint_32 user_height_max)
D
duke 已提交
1666
{
B
bae 已提交
1667 1668
   /* Images with dimensions larger than these limits will be
    * rejected by png_set_IHDR().  To accept any PNG datastream
1669
    * regardless of dimensions, set both limits to 0x7fffffff.
B
bae 已提交
1670 1671 1672
    */
   if (png_ptr == NULL)
      return;
D
duke 已提交
1673

B
bae 已提交
1674 1675
   png_ptr->user_width_max = user_width_max;
   png_ptr->user_height_max = user_height_max;
D
duke 已提交
1676 1677
}

B
bae 已提交
1678
/* This function was added to libpng 1.4.0 */
D
duke 已提交
1679
void PNGAPI
1680
png_set_chunk_cache_max (png_structrp png_ptr, png_uint_32 user_chunk_cache_max)
D
duke 已提交
1681
{
1682 1683
   if (png_ptr != NULL)
      png_ptr->user_chunk_cache_max = user_chunk_cache_max;
D
duke 已提交
1684 1685
}

B
bae 已提交
1686
/* This function was added to libpng 1.4.1 */
D
duke 已提交
1687
void PNGAPI
1688
png_set_chunk_malloc_max (png_structrp png_ptr,
B
bae 已提交
1689
    png_alloc_size_t user_chunk_malloc_max)
D
duke 已提交
1690
{
1691
   if (png_ptr != NULL)
B
bae 已提交
1692
      png_ptr->user_chunk_malloc_max = user_chunk_malloc_max;
D
duke 已提交
1693
}
1694
#endif /* ?SET_USER_LIMITS */
D
duke 已提交
1695

B
bae 已提交
1696 1697 1698

#ifdef PNG_BENIGN_ERRORS_SUPPORTED
void PNGAPI
1699
png_set_benign_errors(png_structrp png_ptr, int allowed)
B
bae 已提交
1700 1701 1702
{
   png_debug(1, "in png_set_benign_errors");

1703 1704 1705 1706 1707 1708 1709 1710 1711
   /* If allowed is 1, png_benign_error() is treated as a warning.
    *
    * If allowed is 0, png_benign_error() is treated as an error (which
    * is the default behavior if png_set_benign_errors() is not called).
    */

   if (allowed != 0)
      png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN |
         PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN;
B
bae 已提交
1712 1713

   else
1714 1715
      png_ptr->flags &= ~(PNG_FLAG_BENIGN_ERRORS_WARN |
         PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN);
B
bae 已提交
1716
}
1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739
#endif /* BENIGN_ERRORS */

#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
   /* Whether to report invalid palette index; added at libng-1.5.10.
    * It is possible for an indexed (color-type==3) PNG file to contain
    * pixels with invalid (out-of-range) indexes if the PLTE chunk has
    * fewer entries than the image's bit-depth would allow. We recover
    * from this gracefully by filling any incomplete palette with zeros
    * (opaque black).  By default, when this occurs libpng will issue
    * a benign error.  This API can be used to override that behavior.
    */
void PNGAPI
png_set_check_for_invalid_index(png_structrp png_ptr, int allowed)
{
   png_debug(1, "in png_set_check_for_invalid_index");

   if (allowed > 0)
      png_ptr->num_palette_max = 0;

   else
      png_ptr->num_palette_max = -1;
}
#endif
1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755

#if defined(PNG_TEXT_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) || \
    defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED)
/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
 * and if invalid, correct the keyword rather than discarding the entire
 * chunk.  The PNG 1.0 specification requires keywords 1-79 characters in
 * length, forbids leading or trailing whitespace, multiple internal spaces,
 * and the non-break space (0x80) from ISO 8859-1.  Returns keyword length.
 *
 * The 'new_key' buffer must be 80 characters in size (for the keyword plus a
 * trailing '\0').  If this routine returns 0 then there was no keyword, or a
 * valid one could not be generated, and the caller must png_error.
 */
png_uint_32 /* PRIVATE */
png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key)
{
P
prr 已提交
1756
#ifdef PNG_WARNINGS_SUPPORTED
1757
   png_const_charp orig_key = key;
P
prr 已提交
1758
#endif
1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775
   png_uint_32 key_len = 0;
   int bad_character = 0;
   int space = 1;

   png_debug(1, "in png_check_keyword");

   if (key == NULL)
   {
      *new_key = 0;
      return 0;
   }

   while (*key && key_len < 79)
   {
      png_byte ch = (png_byte)*key++;

      if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/))
P
prr 已提交
1776 1777 1778
      {
         *new_key++ = ch; ++key_len; space = 0;
      }
1779 1780 1781 1782 1783 1784

      else if (space == 0)
      {
         /* A space or an invalid character when one wasn't seen immediately
          * before; output just a space.
          */
P
prr 已提交
1785
         *new_key++ = 32; ++key_len; space = 1;
1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797

         /* If the character was not a space then it is invalid. */
         if (ch != 32)
            bad_character = ch;
      }

      else if (bad_character == 0)
         bad_character = ch; /* just skip it, record the first error */
   }

   if (key_len > 0 && space != 0) /* trailing space */
   {
P
prr 已提交
1798
      --key_len; --new_key;
1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822
      if (bad_character == 0)
         bad_character = 32;
   }

   /* Terminate the keyword */
   *new_key = 0;

   if (key_len == 0)
      return 0;

#ifdef PNG_WARNINGS_SUPPORTED
   /* Try to only output one warning per keyword: */
   if (*key != 0) /* keyword too long */
      png_warning(png_ptr, "keyword truncated");

   else if (bad_character != 0)
   {
      PNG_WARNING_PARAMETERS(p)

      png_warning_parameter(p, 1, orig_key);
      png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_02x, bad_character);

      png_formatted_warning(png_ptr, p, "keyword \"@1\": bad character '0x@2'");
   }
P
prr 已提交
1823 1824 1825
#else /* !WARNINGS */
   PNG_UNUSED(png_ptr)
#endif /* !WARNINGS */
1826 1827 1828 1829

   return key_len;
}
#endif /* TEXT || pCAL || iCCP || sPLT */
1830
#endif /* READ || WRITE */