pngset.c 50.2 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:
 *
32 33
 * Last changed in libpng 1.6.23 [June 9, 2016]
 * Copyright (c) 1998-2016 Glenn Randers-Pehrson
D
duke 已提交
34 35 36
 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
 *
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 135 136 137 138 139 140 141 142
   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"));
D
duke 已提交
143
}
B
bae 已提交
144

145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
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,
      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"));
}
#  endif /* FLOATING_POINT */

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

#ifdef PNG_gAMA_SUPPORTED
void PNGFAPI
167 168
png_set_gAMA_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
    png_fixed_point file_gamma)
D
duke 已提交
169
{
B
bae 已提交
170
   png_debug1(1, "in %s storage function", "gAMA");
D
duke 已提交
171 172 173 174

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

175 176
   png_colorspace_set_gamma(png_ptr, &info_ptr->colorspace, file_gamma);
   png_colorspace_sync_info(png_ptr, info_ptr);
D
duke 已提交
177
}
B
bae 已提交
178 179 180

#  ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
181
png_set_gAMA(png_const_structrp png_ptr, png_inforp info_ptr, double file_gamma)
B
bae 已提交
182 183 184 185 186
{
   png_set_gAMA_fixed(png_ptr, info_ptr, png_fixed(png_ptr, file_gamma,
       "png_set_gAMA"));
}
#  endif
D
duke 已提交
187 188
#endif

B
bae 已提交
189
#ifdef PNG_hIST_SUPPORTED
D
duke 已提交
190
void PNGAPI
191 192
png_set_hIST(png_const_structrp png_ptr, png_inforp info_ptr,
    png_const_uint_16p hist)
D
duke 已提交
193 194 195
{
   int i;

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

D
duke 已提交
198 199
   if (png_ptr == NULL || info_ptr == NULL)
      return;
B
bae 已提交
200 201

   if (info_ptr->num_palette == 0 || info_ptr->num_palette
D
duke 已提交
202 203
       > PNG_MAX_PALETTE_LENGTH)
   {
B
bae 已提交
204 205 206 207
      png_warning(png_ptr,
          "Invalid palette size, hIST allocation skipped");

      return;
D
duke 已提交
208 209 210
   }

   png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0);
B
bae 已提交
211 212 213 214

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

218
   if (info_ptr->hist == NULL)
B
bae 已提交
219 220
   {
      png_warning(png_ptr, "Insufficient memory for hIST chunk data");
221

B
bae 已提交
222 223
      return;
   }
D
duke 已提交
224

225 226
   info_ptr->free_me |= PNG_FREE_HIST;

D
duke 已提交
227
   for (i = 0; i < info_ptr->num_palette; i++)
228
      info_ptr->hist[i] = hist[i];
B
bae 已提交
229

D
duke 已提交
230 231 232 233 234
   info_ptr->valid |= PNG_INFO_hIST;
}
#endif

void PNGAPI
235
png_set_IHDR(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
236 237 238
    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 已提交
239
{
B
bae 已提交
240 241
   png_debug1(1, "in %s storage function", "IHDR");

D
duke 已提交
242 243 244 245 246 247
   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 已提交
248
   info_ptr->color_type = (png_byte)color_type;
D
duke 已提交
249 250 251
   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 已提交
252 253 254 255 256

   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 已提交
257 258
   if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
      info_ptr->channels = 1;
B
bae 已提交
259

260
   else if ((info_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
D
duke 已提交
261
      info_ptr->channels = 3;
B
bae 已提交
262

D
duke 已提交
263 264
   else
      info_ptr->channels = 1;
B
bae 已提交
265

266
   if ((info_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)
D
duke 已提交
267
      info_ptr->channels++;
B
bae 已提交
268

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

271
   info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width);
D
duke 已提交
272 273
}

B
bae 已提交
274
#ifdef PNG_oFFs_SUPPORTED
D
duke 已提交
275
void PNGAPI
276
png_set_oFFs(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
277
    png_int_32 offset_x, png_int_32 offset_y, int unit_type)
D
duke 已提交
278
{
B
bae 已提交
279 280
   png_debug1(1, "in %s storage function", "oFFs");

D
duke 已提交
281 282 283 284 285 286 287 288 289 290
   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 已提交
291
#ifdef PNG_pCAL_SUPPORTED
D
duke 已提交
292
void PNGAPI
293
png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
294 295
    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 已提交
296
{
B
bae 已提交
297
   png_size_t length;
D
duke 已提交
298 299
   int i;

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

302 303
   if (png_ptr == NULL || info_ptr == NULL || purpose == NULL || units == NULL
       || (nparams > 0 && params == NULL))
D
duke 已提交
304 305
      return;

306
   length = strlen(purpose) + 1;
B
bae 已提交
307 308 309 310 311 312 313 314 315
   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)
      png_error(png_ptr, "Invalid pCAL equation type");

316 317 318
   if (nparams < 0 || nparams > 255)
      png_error(png_ptr, "Invalid pCAL parameter count");

B
bae 已提交
319 320
   /* Validate params[nparams] */
   for (i=0; i<nparams; ++i)
321 322 323
   {
      if (params[i] == NULL ||
          !png_check_fp_string(params[i], strlen(params[i])))
B
bae 已提交
324
         png_error(png_ptr, "Invalid format for pCAL parameter");
325
   }
B
bae 已提交
326

327 328
   info_ptr->pcal_purpose = png_voidcast(png_charp,
       png_malloc_warn(png_ptr, length));
B
bae 已提交
329

D
duke 已提交
330
   if (info_ptr->pcal_purpose == NULL)
B
bae 已提交
331 332
   {
      png_warning(png_ptr, "Insufficient memory for pCAL purpose");
333

B
bae 已提交
334 335 336
      return;
   }

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

B
bae 已提交
339
   png_debug(3, "storing X0, X1, type, and nparams in info");
D
duke 已提交
340 341 342 343 344
   info_ptr->pcal_X0 = X0;
   info_ptr->pcal_X1 = X1;
   info_ptr->pcal_type = (png_byte)type;
   info_ptr->pcal_nparams = (png_byte)nparams;

345
   length = strlen(units) + 1;
B
bae 已提交
346 347 348
   png_debug1(3, "allocating units for info (%lu bytes)",
     (unsigned long)length);

349 350
   info_ptr->pcal_units = png_voidcast(png_charp,
      png_malloc_warn(png_ptr, length));
B
bae 已提交
351

D
duke 已提交
352
   if (info_ptr->pcal_units == NULL)
B
bae 已提交
353 354
   {
      png_warning(png_ptr, "Insufficient memory for pCAL units");
355

B
bae 已提交
356 357 358
      return;
   }

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

361 362
   info_ptr->pcal_params = png_voidcast(png_charpp, png_malloc_warn(png_ptr,
       (png_size_t)((nparams + 1) * (sizeof (png_charp)))));
B
bae 已提交
363

D
duke 已提交
364
   if (info_ptr->pcal_params == NULL)
B
bae 已提交
365 366
   {
      png_warning(png_ptr, "Insufficient memory for pCAL params");
367

B
bae 已提交
368 369
      return;
   }
D
duke 已提交
370

371
   memset(info_ptr->pcal_params, 0, (nparams + 1) * (sizeof (png_charp)));
D
duke 已提交
372 373 374

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

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

D
duke 已提交
381
      if (info_ptr->pcal_params[i] == NULL)
B
bae 已提交
382 383
      {
         png_warning(png_ptr, "Insufficient memory for pCAL parameter");
384

B
bae 已提交
385 386 387
         return;
      }

388
      memcpy(info_ptr->pcal_params[i], params[i], length);
D
duke 已提交
389 390 391 392 393 394 395
   }

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

B
bae 已提交
396
#ifdef PNG_sCAL_SUPPORTED
D
duke 已提交
397
void PNGAPI
398
png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
399
    int unit, png_const_charp swidth, png_const_charp sheight)
D
duke 已提交
400
{
B
bae 已提交
401 402 403 404
   png_size_t lengthw = 0, lengthh = 0;

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

D
duke 已提交
405 406 407
   if (png_ptr == NULL || info_ptr == NULL)
      return;

B
bae 已提交
408 409 410 411 412
   /* 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 已提交
413

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

418
   if (sheight == NULL || (lengthh = strlen(sheight)) == 0 ||
B
bae 已提交
419 420
       sheight[0] == 45 /* '-' */ || !png_check_fp_string(sheight, lengthh))
      png_error(png_ptr, "Invalid sCAL height");
D
duke 已提交
421 422 423

   info_ptr->scal_unit = (png_byte)unit;

B
bae 已提交
424 425 426 427
   ++lengthw;

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

428 429
   info_ptr->scal_s_width = png_voidcast(png_charp,
      png_malloc_warn(png_ptr, lengthw));
B
bae 已提交
430

D
duke 已提交
431 432
   if (info_ptr->scal_s_width == NULL)
   {
B
bae 已提交
433
      png_warning(png_ptr, "Memory allocation failed while processing sCAL");
434

B
bae 已提交
435
      return;
D
duke 已提交
436 437
   }

438
   memcpy(info_ptr->scal_s_width, swidth, lengthw);
B
bae 已提交
439 440 441 442 443

   ++lengthh;

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

444 445
   info_ptr->scal_s_height = png_voidcast(png_charp,
      png_malloc_warn(png_ptr, lengthh));
B
bae 已提交
446

D
duke 已提交
447 448 449
   if (info_ptr->scal_s_height == NULL)
   {
      png_free (png_ptr, info_ptr->scal_s_width);
B
bae 已提交
450 451 452
      info_ptr->scal_s_width = NULL;

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

B
bae 已提交
454
      return;
D
duke 已提交
455
   }
B
bae 已提交
456

457
   memcpy(info_ptr->scal_s_height, sheight, lengthh);
D
duke 已提交
458 459 460 461

   info_ptr->valid |= PNG_INFO_sCAL;
   info_ptr->free_me |= PNG_FREE_SCAL;
}
B
bae 已提交
462 463 464

#  ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
465 466
png_set_sCAL(png_const_structrp png_ptr, png_inforp info_ptr, int unit,
    double width, double height)
B
bae 已提交
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482
{
   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];

483
      png_ascii_from_fp(png_ptr, swidth, (sizeof swidth), width,
B
bae 已提交
484
         PNG_sCAL_PRECISION);
485
      png_ascii_from_fp(png_ptr, sheight, (sizeof sheight), height,
B
bae 已提交
486 487 488 489 490 491 492 493 494
         PNG_sCAL_PRECISION);

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

#  ifdef PNG_FIXED_POINT_SUPPORTED
void PNGAPI
495
png_set_sCAL_fixed(png_const_structrp png_ptr, png_inforp info_ptr, int unit,
B
bae 已提交
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512
    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];

513 514
      png_ascii_from_fixed(png_ptr, swidth, (sizeof swidth), width);
      png_ascii_from_fixed(png_ptr, sheight, (sizeof sheight), height);
B
bae 已提交
515 516 517 518 519

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

B
bae 已提交
522
#ifdef PNG_pHYs_SUPPORTED
D
duke 已提交
523
void PNGAPI
524
png_set_pHYs(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
525
    png_uint_32 res_x, png_uint_32 res_y, int unit_type)
D
duke 已提交
526
{
B
bae 已提交
527 528
   png_debug1(1, "in %s storage function", "pHYs");

D
duke 已提交
529 530 531 532 533 534 535 536 537 538 539
   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
540
png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
541
    png_const_colorp palette, int num_palette)
D
duke 已提交
542 543
{

544 545
   png_uint_32 max_palette_length;

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

D
duke 已提交
548 549 550
   if (png_ptr == NULL || info_ptr == NULL)
      return;

551 552 553 554
   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 已提交
555 556
   {
      if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
D
duke 已提交
557
         png_error(png_ptr, "Invalid palette length");
B
bae 已提交
558 559 560

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

D
duke 已提交
563
         return;
B
bae 已提交
564 565
      }
   }
D
duke 已提交
566

S
serb 已提交
567 568 569 570 571 572 573 574 575 576
   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 已提交
577
   /* It may not actually be necessary to set png_ptr->palette here;
D
duke 已提交
578 579
    * we do it for backward compatibility with the way the png_handle_tRNS
    * function used to do the allocation.
580 581 582
    *
    * 1.6.0: the above statement appears to be incorrect; something has to set
    * the palette inside png_struct on read.
D
duke 已提交
583 584 585 586
    */
   png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0);

   /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead
587 588
    * 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 已提交
589
    */
590 591
   png_ptr->palette = png_voidcast(png_colorp, png_calloc(png_ptr,
       PNG_MAX_PALETTE_LENGTH * (sizeof (png_color))));
B
bae 已提交
592

593 594
   if (num_palette > 0)
      memcpy(png_ptr->palette, palette, num_palette * (sizeof (png_color)));
D
duke 已提交
595 596 597 598 599 600 601 602
   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 已提交
603
#ifdef PNG_sBIT_SUPPORTED
D
duke 已提交
604
void PNGAPI
605
png_set_sBIT(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
606
    png_const_color_8p sig_bit)
D
duke 已提交
607
{
B
bae 已提交
608 609
   png_debug1(1, "in %s storage function", "sBIT");

610
   if (png_ptr == NULL || info_ptr == NULL || sig_bit == NULL)
D
duke 已提交
611 612
      return;

613
   info_ptr->sig_bit = *sig_bit;
D
duke 已提交
614 615 616 617
   info_ptr->valid |= PNG_INFO_sBIT;
}
#endif

B
bae 已提交
618
#ifdef PNG_sRGB_SUPPORTED
D
duke 已提交
619
void PNGAPI
620
png_set_sRGB(png_const_structrp png_ptr, png_inforp info_ptr, int srgb_intent)
D
duke 已提交
621
{
B
bae 已提交
622 623
   png_debug1(1, "in %s storage function", "sRGB");

D
duke 已提交
624 625 626
   if (png_ptr == NULL || info_ptr == NULL)
      return;

627 628
   (void)png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace, srgb_intent);
   png_colorspace_sync_info(png_ptr, info_ptr);
D
duke 已提交
629 630 631
}

void PNGAPI
632
png_set_sRGB_gAMA_and_cHRM(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
633
    int srgb_intent)
D
duke 已提交
634
{
B
bae 已提交
635 636
   png_debug1(1, "in %s storage function", "sRGB_gAMA_and_cHRM");

D
duke 已提交
637 638 639
   if (png_ptr == NULL || info_ptr == NULL)
      return;

640 641 642 643 644 645 646
   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 已提交
647

648
   png_colorspace_sync_info(png_ptr, info_ptr);
D
duke 已提交
649
}
B
bae 已提交
650
#endif /* sRGB */
D
duke 已提交
651 652


B
bae 已提交
653
#ifdef PNG_iCCP_SUPPORTED
D
duke 已提交
654
void PNGAPI
655
png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
656 657
    png_const_charp name, int compression_type,
    png_const_bytep profile, png_uint_32 proflen)
D
duke 已提交
658 659
{
   png_charp new_iccp_name;
B
bae 已提交
660
   png_bytep new_iccp_profile;
661
   png_size_t length;
B
bae 已提交
662 663

   png_debug1(1, "in %s storage function", "iCCP");
D
duke 已提交
664 665 666 667

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

668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693
   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,
         proflen, profile, info_ptr->color_type);

      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 已提交
694

D
duke 已提交
695 696
   if (new_iccp_name == NULL)
   {
697 698
      png_benign_error(png_ptr, "Insufficient memory to process iCCP chunk");

D
duke 已提交
699 700
      return;
   }
B
bae 已提交
701

702 703 704
   memcpy(new_iccp_name, name, length);
   new_iccp_profile = png_voidcast(png_bytep,
      png_malloc_warn(png_ptr, proflen));
B
bae 已提交
705

D
duke 已提交
706 707
   if (new_iccp_profile == NULL)
   {
708 709
      png_free(png_ptr, new_iccp_name);
      png_benign_error(png_ptr,
B
bae 已提交
710
          "Insufficient memory to process iCCP profile");
711

D
duke 已提交
712 713
      return;
   }
B
bae 已提交
714

715
   memcpy(new_iccp_profile, profile, proflen);
D
duke 已提交
716 717 718 719 720 721 722 723 724 725 726

   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 已提交
727
#ifdef PNG_TEXT_SUPPORTED
D
duke 已提交
728
void PNGAPI
729 730
png_set_text(png_const_structrp png_ptr, png_inforp info_ptr,
    png_const_textp text_ptr, int num_text)
D
duke 已提交
731 732
{
   int ret;
B
bae 已提交
733 734
   ret = png_set_text_2(png_ptr, info_ptr, text_ptr, num_text);

735
   if (ret != 0)
B
bae 已提交
736
      png_error(png_ptr, "Insufficient memory to store text");
D
duke 已提交
737 738 739
}

int /* PRIVATE */
740
png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
741
    png_const_textp text_ptr, int num_text)
D
duke 已提交
742 743 744
{
   int i;

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

748
   if (png_ptr == NULL || info_ptr == NULL || num_text <= 0 || text_ptr == NULL)
D
duke 已提交
749 750 751
      return(0);

   /* Make sure we have enough space in the "text" array in info_struct
752 753 754
    * 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 已提交
755
    */
756
   if (num_text > info_ptr->max_text - info_ptr->num_text)
D
duke 已提交
757
   {
758 759 760
      int old_num_text = info_ptr->num_text;
      int max_text;
      png_textp new_text = NULL;
B
bae 已提交
761

762 763 764 765 766
      /* 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 已提交
767

768 769 770
         /* Round up to a multiple of 8 */
         if (max_text < INT_MAX-8)
            max_text = (max_text + 8) & ~0x7;
A
azvegint 已提交
771

772 773 774 775 776 777 778 779 780
         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,
            info_ptr->text, old_num_text, max_text-old_num_text,
            sizeof *new_text));
D
duke 已提交
781
      }
B
bae 已提交
782

783
      if (new_text == NULL)
D
duke 已提交
784
      {
785 786 787 788
         png_chunk_report(png_ptr, "too many text chunks",
            PNG_CHUNK_WRITE_ERROR);

         return 1;
D
duke 已提交
789
      }
B
bae 已提交
790

791 792 793 794 795 796 797 798
      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 已提交
799
   }
800

D
duke 已提交
801 802
   for (i = 0; i < num_text; i++)
   {
803 804
      size_t text_length, key_len;
      size_t lang_len, lang_key_len;
D
duke 已提交
805 806 807 808 809
      png_textp textp = &(info_ptr->text[info_ptr->num_text]);

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

B
bae 已提交
810 811 812
      if (text_ptr[i].compression < PNG_TEXT_COMPRESSION_NONE ||
          text_ptr[i].compression >= PNG_TEXT_COMPRESSION_LAST)
      {
813 814
         png_chunk_report(png_ptr, "text compression mode is out of range",
            PNG_CHUNK_WRITE_ERROR);
B
bae 已提交
815 816 817
         continue;
      }

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

B
bae 已提交
820
      if (text_ptr[i].compression <= 0)
D
duke 已提交
821
      {
B
bae 已提交
822 823
         lang_len = 0;
         lang_key_len = 0;
D
duke 已提交
824
      }
B
bae 已提交
825

D
duke 已提交
826
      else
B
bae 已提交
827
#  ifdef PNG_iTXt_SUPPORTED
D
duke 已提交
828
      {
B
bae 已提交
829 830 831
         /* Set iTXt data */

         if (text_ptr[i].lang != NULL)
832
            lang_len = strlen(text_ptr[i].lang);
B
bae 已提交
833 834 835 836 837

         else
            lang_len = 0;

         if (text_ptr[i].lang_key != NULL)
838
            lang_key_len = strlen(text_ptr[i].lang_key);
B
bae 已提交
839 840 841

         else
            lang_key_len = 0;
D
duke 已提交
842
      }
843
#  else /* iTXt */
D
duke 已提交
844
      {
845 846
         png_chunk_report(png_ptr, "iTXt chunk not supported",
            PNG_CHUNK_WRITE_ERROR);
B
bae 已提交
847
         continue;
D
duke 已提交
848
      }
B
bae 已提交
849
#  endif
D
duke 已提交
850 851 852 853

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

D
duke 已提交
858
         else
B
bae 已提交
859
#  endif
D
duke 已提交
860 861
            textp->compression = PNG_TEXT_COMPRESSION_NONE;
      }
B
bae 已提交
862

D
duke 已提交
863 864
      else
      {
865
         text_length = strlen(text_ptr[i].text);
D
duke 已提交
866 867 868
         textp->compression = text_ptr[i].compression;
      }

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

D
duke 已提交
872
      if (textp->key == NULL)
873 874 875 876 877 878
      {
         png_chunk_report(png_ptr, "text chunk: out of memory",
               PNG_CHUNK_WRITE_ERROR);

         return 1;
      }
B
bae 已提交
879 880 881 882 883 884

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

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

D
duke 已提交
888 889
      if (text_ptr[i].compression > 0)
      {
B
bae 已提交
890
         textp->lang = textp->key + key_len + 1;
891
         memcpy(textp->lang, text_ptr[i].lang, lang_len);
B
bae 已提交
892 893
         *(textp->lang + lang_len) = '\0';
         textp->lang_key = textp->lang + lang_len + 1;
894
         memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len);
B
bae 已提交
895 896
         *(textp->lang_key + lang_key_len) = '\0';
         textp->text = textp->lang_key + lang_key_len + 1;
D
duke 已提交
897
      }
B
bae 已提交
898

D
duke 已提交
899 900 901 902
      else
      {
         textp->lang=NULL;
         textp->lang_key=NULL;
B
bae 已提交
903
         textp->text = textp->key + key_len + 1;
D
duke 已提交
904
      }
B
bae 已提交
905

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

B
bae 已提交
909 910 911 912
      *(textp->text + text_length) = '\0';

#  ifdef PNG_iTXt_SUPPORTED
      if (textp->compression > 0)
D
duke 已提交
913 914 915 916
      {
         textp->text_length = 0;
         textp->itxt_length = text_length;
      }
B
bae 已提交
917

D
duke 已提交
918
      else
B
bae 已提交
919
#  endif
D
duke 已提交
920 921 922 923
      {
         textp->text_length = text_length;
         textp->itxt_length = 0;
      }
B
bae 已提交
924

D
duke 已提交
925
      info_ptr->num_text++;
B
bae 已提交
926
      png_debug1(3, "transferred text chunk %d", info_ptr->num_text);
D
duke 已提交
927
   }
928

D
duke 已提交
929 930 931 932
   return(0);
}
#endif

B
bae 已提交
933
#ifdef PNG_tIME_SUPPORTED
D
duke 已提交
934
void PNGAPI
935 936
png_set_tIME(png_const_structrp png_ptr, png_inforp info_ptr,
    png_const_timep mod_time)
D
duke 已提交
937
{
B
bae 已提交
938 939
   png_debug1(1, "in %s storage function", "tIME");

940 941
   if (png_ptr == NULL || info_ptr == NULL || mod_time == NULL ||
       (png_ptr->mode & PNG_WROTE_tIME) != 0)
D
duke 已提交
942 943
      return;

944 945 946 947 948 949 950 951 952 953 954
   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 已提交
955 956 957 958
   info_ptr->valid |= PNG_INFO_tIME;
}
#endif

B
bae 已提交
959
#ifdef PNG_tRNS_SUPPORTED
D
duke 已提交
960
void PNGAPI
961
png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
962
    png_const_bytep trans_alpha, int num_trans, png_const_color_16p trans_color)
D
duke 已提交
963
{
B
bae 已提交
964 965
   png_debug1(1, "in %s storage function", "tRNS");

D
duke 已提交
966
   if (png_ptr == NULL || info_ptr == NULL)
967

D
duke 已提交
968 969
      return;

B
bae 已提交
970
   if (trans_alpha != NULL)
D
duke 已提交
971
   {
B
bae 已提交
972
       /* It may not actually be necessary to set png_ptr->trans_alpha here;
D
duke 已提交
973 974
        * we do it for backward compatibility with the way the png_handle_tRNS
        * function used to do the allocation.
975 976 977 978
        *
        * 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 已提交
979
        */
B
bae 已提交
980

D
duke 已提交
981
       png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
B
bae 已提交
982 983

       if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH)
984 985 986 987
       {
         /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */
          info_ptr->trans_alpha = png_voidcast(png_bytep,
             png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH));
988
          memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans);
989 990
       }
       png_ptr->trans_alpha = info_ptr->trans_alpha;
D
duke 已提交
991 992
   }

B
bae 已提交
993
   if (trans_color != NULL)
D
duke 已提交
994
   {
995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009
#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,
               "tRNS chunk has out-of-range samples for bit_depth");
      }
#endif
B
bae 已提交
1010

1011
      info_ptr->trans_color = *trans_color;
B
bae 已提交
1012

D
duke 已提交
1013
      if (num_trans == 0)
B
bae 已提交
1014
         num_trans = 1;
D
duke 已提交
1015
   }
B
bae 已提交
1016

D
duke 已提交
1017
   info_ptr->num_trans = (png_uint_16)num_trans;
B
bae 已提交
1018 1019 1020 1021 1022 1023

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

B
bae 已提交
1027
#ifdef PNG_sPLT_SUPPORTED
D
duke 已提交
1028
void PNGAPI
1029 1030
png_set_sPLT(png_const_structrp png_ptr,
    png_inforp info_ptr, png_const_sPLT_tp entries, int nentries)
B
bae 已提交
1031 1032 1033 1034 1035 1036 1037 1038
/*
 *  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 已提交
1039
{
B
bae 已提交
1040
   png_sPLT_tp np;
D
duke 已提交
1041

1042
   if (png_ptr == NULL || info_ptr == NULL || nentries <= 0 || entries == NULL)
B
bae 已提交
1043
      return;
D
duke 已提交
1044

1045 1046 1047 1048 1049 1050
   /* 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,
      info_ptr->splt_palettes, info_ptr->splt_palettes_num, nentries,
      sizeof *np));
B
bae 已提交
1051 1052 1053

   if (np == NULL)
   {
1054 1055 1056
      /* Out of memory or too many chunks */
      png_chunk_report(png_ptr, "too many sPLT chunks", PNG_CHUNK_WRITE_ERROR);

D
duke 已提交
1057
      return;
B
bae 已提交
1058
   }
D
duke 已提交
1059

A
azvegint 已提交
1060
   png_free(png_ptr, info_ptr->splt_palettes);
1061 1062
   info_ptr->splt_palettes = np;
   info_ptr->free_me |= PNG_FREE_SPLT;
B
bae 已提交
1063

1064
   np += info_ptr->splt_palettes_num;
A
azvegint 已提交
1065

1066 1067 1068
   do
   {
      png_size_t length;
B
bae 已提交
1069

1070 1071
      /* Skip invalid input entries */
      if (entries->name == NULL || entries->entries == NULL)
B
bae 已提交
1072
      {
1073 1074 1075
         /* 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 已提交
1076 1077 1078
         continue;
      }

1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097
      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 已提交
1098

1099
      if (np->entries == NULL)
B
bae 已提交
1100
      {
1101 1102 1103
         png_free(png_ptr, np->name);
         np->name = NULL;
         break;
B
bae 已提交
1104 1105
      }

1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131
      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,
         entries->nentries * sizeof (png_sPLT_entry));

      /* 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;
   }
   while (++entries, --nentries);

   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 已提交
1132

1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144
   /* 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,
         "png_set_unknown_chunks now expects a valid location");
      /* Use the old behavior */
      location = (png_byte)(png_ptr->mode &
         (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT));
B
bae 已提交
1145 1146
   }

1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162
   /* 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 已提交
1163 1164 1165
}

void PNGAPI
1166 1167
png_set_unknown_chunks(png_const_structrp png_ptr,
   png_inforp info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns)
D
duke 已提交
1168
{
B
bae 已提交
1169 1170
   png_unknown_chunkp np;

1171 1172
   if (png_ptr == NULL || info_ptr == NULL || num_unknowns <= 0 ||
       unknowns == NULL)
B
bae 已提交
1173
      return;
D
duke 已提交
1174

1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207
   /* 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,
         info_ptr->unknown_chunks, info_ptr->unknown_chunks_num, num_unknowns,
         sizeof *np));
D
duke 已提交
1208

B
bae 已提交
1209 1210
   if (np == NULL)
   {
1211 1212 1213
      png_chunk_report(png_ptr, "too many unknown chunks",
         PNG_CHUNK_WRITE_ERROR);

B
bae 已提交
1214 1215
      return;
   }
D
duke 已提交
1216

A
azvegint 已提交
1217
   png_free(png_ptr, info_ptr->unknown_chunks);
1218 1219
   info_ptr->unknown_chunks = np; /* safe because it is initialized */
   info_ptr->free_me |= PNG_FREE_UNKN;
B
bae 已提交
1220

1221
   np += info_ptr->unknown_chunks_num;
A
azvegint 已提交
1222

1223 1224 1225 1226 1227 1228 1229 1230
   /* 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 已提交
1231

1232 1233 1234 1235 1236
      if (unknowns->size == 0)
      {
         np->data = NULL;
         np->size = 0;
      }
B
bae 已提交
1237 1238 1239

      else
      {
1240 1241
         np->data = png_voidcast(png_bytep,
            png_malloc_base(png_ptr, unknowns->size));
B
bae 已提交
1242

1243
         if (np->data == NULL)
B
bae 已提交
1244
         {
1245 1246 1247 1248
            png_chunk_report(png_ptr, "unknown chunk: out of memory",
               PNG_CHUNK_WRITE_ERROR);
            /* But just skip storing the unknown chunk */
            continue;
B
bae 已提交
1249 1250
         }

1251 1252
         memcpy(np->data, unknowns->data, unknowns->size);
         np->size = unknowns->size;
B
bae 已提交
1253
      }
A
azvegint 已提交
1254

1255 1256 1257 1258 1259 1260 1261
      /* 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 已提交
1262
}
B
bae 已提交
1263

D
duke 已提交
1264
void PNGAPI
1265
png_set_unknown_chunk_location(png_const_structrp png_ptr, png_inforp info_ptr,
B
bae 已提交
1266
    int chunk, int location)
D
duke 已提交
1267
{
1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285
   /* 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: */
         if ((location & PNG_HAVE_IDAT) != 0) /* undocumented! */
            location = PNG_AFTER_IDAT;

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

1287 1288 1289 1290 1291
      info_ptr->unknown_chunks[chunk].location =
         check_location(png_ptr, location);
   }
}
#endif /* STORE_UNKNOWN_CHUNKS */
D
duke 已提交
1292

B
bae 已提交
1293
#ifdef PNG_MNG_FEATURES_SUPPORTED
D
duke 已提交
1294
png_uint_32 PNGAPI
1295
png_permit_mng_features (png_structrp png_ptr, png_uint_32 mng_features)
D
duke 已提交
1296
{
B
bae 已提交
1297 1298
   png_debug(1, "in png_permit_mng_features");

D
duke 已提交
1299
   if (png_ptr == NULL)
1300
      return 0;
B
bae 已提交
1301

1302
   png_ptr->mng_features_permitted = mng_features & PNG_ALL_MNG_FEATURES;
B
bae 已提交
1303

1304
   return png_ptr->mng_features_permitted;
D
duke 已提交
1305 1306 1307
}
#endif

B
bae 已提交
1308
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336
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 已提交
1337
void PNGAPI
1338 1339
png_set_keep_unknown_chunks(png_structrp png_ptr, int keep,
    png_const_bytep chunk_list, int num_chunks_in)
D
duke 已提交
1340
{
1341 1342 1343
   png_bytep new_list;
   unsigned int num_chunks, old_num_chunks;

B
bae 已提交
1344 1345 1346
   if (png_ptr == NULL)
      return;

1347
   if (keep < 0 || keep >= PNG_HANDLE_CHUNK_LAST)
B
bae 已提交
1348
   {
1349
      png_app_error(png_ptr, "png_set_keep_unknown_chunks: invalid keep");
B
bae 已提交
1350

1351 1352
      return;
   }
B
bae 已提交
1353

1354 1355 1356
   if (num_chunks_in <= 0)
   {
      png_ptr->unknown_default = keep;
A
azvegint 已提交
1357

1358 1359 1360 1361
      /* '0' means just set the flags, so stop here */
      if (num_chunks_in == 0)
        return;
   }
A
azvegint 已提交
1362

1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389
   if (num_chunks_in < 0)
   {
      /* Ignore all unknown chunks and all chunks recognized by
       * libpng except for IHDR, PLTE, tRNS, IDAT, and IEND
       */
      static PNG_CONST png_byte chunks_to_ignore[] = {
         98,  75,  71,  68, '\0',  /* bKGD */
         99,  72,  82,  77, '\0',  /* cHRM */
        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 已提交
1390
   }
B
bae 已提交
1391

1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405
   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;
      }

      num_chunks = num_chunks_in;
   }
A
azvegint 已提交
1406

A
azvegint 已提交
1407
   old_num_chunks = png_ptr->num_chunk_list;
1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427
   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 已提交
1428

1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444
      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 已提交
1445
   {
1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476
      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,
            chunk_list+5*i, keep);
      }

      /* 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 已提交
1477 1478
   }

1479 1480 1481 1482
   else
      num_chunks = 0;

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

1484 1485 1486 1487
   if (png_ptr->chunk_list != new_list)
   {
      if (png_ptr->chunk_list != NULL)
         png_free(png_ptr, png_ptr->chunk_list);
B
bae 已提交
1488

1489 1490
      png_ptr->chunk_list = new_list;
   }
D
duke 已提交
1491 1492 1493
}
#endif

B
bae 已提交
1494
#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
D
duke 已提交
1495
void PNGAPI
1496
png_set_read_user_chunk_fn(png_structrp png_ptr, png_voidp user_chunk_ptr,
B
bae 已提交
1497
    png_user_chunk_ptr read_user_chunk_fn)
D
duke 已提交
1498
{
B
bae 已提交
1499 1500
   png_debug(1, "in png_set_read_user_chunk_fn");

D
duke 已提交
1501 1502
   if (png_ptr == NULL)
      return;
B
bae 已提交
1503

D
duke 已提交
1504 1505 1506 1507 1508
   png_ptr->read_user_chunk_fn = read_user_chunk_fn;
   png_ptr->user_chunk_ptr = user_chunk_ptr;
}
#endif

B
bae 已提交
1509
#ifdef PNG_INFO_IMAGE_SUPPORTED
D
duke 已提交
1510
void PNGAPI
1511 1512
png_set_rows(png_const_structrp png_ptr, png_inforp info_ptr,
    png_bytepp row_pointers)
D
duke 已提交
1513
{
B
bae 已提交
1514
   png_debug1(1, "in %s storage function", "rows");
D
duke 已提交
1515 1516 1517 1518

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

1519 1520
   if (info_ptr->row_pointers != NULL &&
       (info_ptr->row_pointers != row_pointers))
D
duke 已提交
1521
      png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
B
bae 已提交
1522

D
duke 已提交
1523
   info_ptr->row_pointers = row_pointers;
B
bae 已提交
1524

1525
   if (row_pointers != NULL)
D
duke 已提交
1526 1527 1528 1529 1530
      info_ptr->valid |= PNG_INFO_IDAT;
}
#endif

void PNGAPI
1531
png_set_compression_buffer_size(png_structrp png_ptr, png_size_t size)
D
duke 已提交
1532 1533 1534
{
    if (png_ptr == NULL)
       return;
B
bae 已提交
1535

1536 1537
    if (size == 0 || size > PNG_UINT_31_MAX)
       png_error(png_ptr, "invalid compression buffer size");
B
bae 已提交
1538

1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556
#  ifdef PNG_SEQUENTIAL_READ_SUPPORTED
      if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
      {
         png_ptr->IDAT_read_size = (png_uint_32)size; /* checked above */
         return;
      }
#  endif

#  ifdef PNG_WRITE_SUPPORTED
      if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
      {
         if (png_ptr->zowner != 0)
         {
            png_warning(png_ptr,
              "Compression buffer size cannot be changed because it is in use");

            return;
         }
B
bae 已提交
1557

1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568
#ifndef __COVERITY__
         /* 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 */
         }
#endif
B
bae 已提交
1569

1570 1571 1572 1573 1574 1575 1576 1577 1578 1579
         if (size < 6)
         {
            /* Deflate will potentially go into an infinite loop on a SYNC_FLUSH
             * if this is permitted.
             */
            png_warning(png_ptr,
               "Compression buffer size cannot be reduced below 6");

            return;
         }
B
bae 已提交
1580

1581 1582 1583 1584 1585 1586 1587
         if (png_ptr->zbuffer_size != size)
         {
            png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list);
            png_ptr->zbuffer_size = (uInt)size;
         }
      }
#  endif
D
duke 已提交
1588 1589 1590
}

void PNGAPI
1591
png_set_invalid(png_const_structrp png_ptr, png_inforp info_ptr, int mask)
D
duke 已提交
1592
{
1593
   if (png_ptr != NULL && info_ptr != NULL)
B
bae 已提交
1594
      info_ptr->valid &= ~mask;
D
duke 已提交
1595 1596 1597
}


B
bae 已提交
1598 1599
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
/* This function was added to libpng 1.2.6 */
D
duke 已提交
1600
void PNGAPI
1601
png_set_user_limits (png_structrp png_ptr, png_uint_32 user_width_max,
B
bae 已提交
1602
    png_uint_32 user_height_max)
D
duke 已提交
1603
{
B
bae 已提交
1604 1605
   /* Images with dimensions larger than these limits will be
    * rejected by png_set_IHDR().  To accept any PNG datastream
1606
    * regardless of dimensions, set both limits to 0x7fffffff.
B
bae 已提交
1607 1608 1609
    */
   if (png_ptr == NULL)
      return;
D
duke 已提交
1610

B
bae 已提交
1611 1612
   png_ptr->user_width_max = user_width_max;
   png_ptr->user_height_max = user_height_max;
D
duke 已提交
1613 1614
}

B
bae 已提交
1615
/* This function was added to libpng 1.4.0 */
D
duke 已提交
1616
void PNGAPI
1617
png_set_chunk_cache_max (png_structrp png_ptr, png_uint_32 user_chunk_cache_max)
D
duke 已提交
1618
{
1619 1620
   if (png_ptr != NULL)
      png_ptr->user_chunk_cache_max = user_chunk_cache_max;
D
duke 已提交
1621 1622
}

B
bae 已提交
1623
/* This function was added to libpng 1.4.1 */
D
duke 已提交
1624
void PNGAPI
1625
png_set_chunk_malloc_max (png_structrp png_ptr,
B
bae 已提交
1626
    png_alloc_size_t user_chunk_malloc_max)
D
duke 已提交
1627
{
1628
   if (png_ptr != NULL)
B
bae 已提交
1629
      png_ptr->user_chunk_malloc_max = user_chunk_malloc_max;
D
duke 已提交
1630
}
1631
#endif /* ?SET_USER_LIMITS */
D
duke 已提交
1632

B
bae 已提交
1633 1634 1635

#ifdef PNG_BENIGN_ERRORS_SUPPORTED
void PNGAPI
1636
png_set_benign_errors(png_structrp png_ptr, int allowed)
B
bae 已提交
1637 1638 1639
{
   png_debug(1, "in png_set_benign_errors");

1640 1641 1642 1643 1644 1645 1646 1647 1648
   /* 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 已提交
1649 1650

   else
1651 1652
      png_ptr->flags &= ~(PNG_FLAG_BENIGN_ERRORS_WARN |
         PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN);
B
bae 已提交
1653
}
1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676
#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
1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760

#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)
{
   png_const_charp orig_key = key;
   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*/))
         *new_key++ = ch, ++key_len, space = 0;

      else if (space == 0)
      {
         /* A space or an invalid character when one wasn't seen immediately
          * before; output just a space.
          */
         *new_key++ = 32, ++key_len, space = 1;

         /* 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 */
   {
      --key_len, --new_key;
      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'");
   }
#endif /* WARNINGS */

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