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

/* pngset.c - storage of image information into info struct
3
 *
4
 * libpng 1.0.11beta3 - April 15, 2001
5
 * For conditions of distribution and use, see copyright notice in png.h
6
 * Copyright (c) 1998-2001 Glenn Randers-Pehrson
7 8
 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
9 10 11 12 13 14
 *
 * The functions here are used during reads to store data from the file
 * into the info struct, and during writes to store application data
 * into the info struct for writing into the file.  This abstracts the
 * info struct and allows us to change the structure in the future.
 */
A
Andreas Dilger 已提交
15 16 17 18

#define PNG_INTERNAL
#include "png.h"

19
#if defined(PNG_bKGD_SUPPORTED)
20
void PNGAPI
A
Andreas Dilger 已提交
21 22 23
png_set_bKGD(png_structp png_ptr, png_infop info_ptr, png_color_16p background)
{
   png_debug1(1, "in %s storage function\n", "bKGD");
24
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
25 26 27 28 29 30 31
      return;

   png_memcpy(&(info_ptr->background), background, sizeof(png_color_16));
   info_ptr->valid |= PNG_INFO_bKGD;
}
#endif

32 33
#if defined(PNG_cHRM_SUPPORTED)
#ifdef PNG_FLOATING_POINT_SUPPORTED
34
void PNGAPI
A
Andreas Dilger 已提交
35 36 37 38 39
png_set_cHRM(png_structp png_ptr, png_infop info_ptr,
   double white_x, double white_y, double red_x, double red_y,
   double green_x, double green_y, double blue_x, double blue_y)
{
   png_debug1(1, "in %s storage function\n", "cHRM");
40
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
41 42 43 44 45 46 47 48 49 50
      return;

   info_ptr->x_white = (float)white_x;
   info_ptr->y_white = (float)white_y;
   info_ptr->x_red   = (float)red_x;
   info_ptr->y_red   = (float)red_y;
   info_ptr->x_green = (float)green_x;
   info_ptr->y_green = (float)green_y;
   info_ptr->x_blue  = (float)blue_x;
   info_ptr->y_blue  = (float)blue_y;
51 52 53 54 55 56 57 58 59 60
#ifdef PNG_FIXED_POINT_SUPPORTED
   info_ptr->int_x_white = (png_fixed_point)(white_x*100000.+0.5);
   info_ptr->int_y_white = (png_fixed_point)(white_y*100000.+0.5);
   info_ptr->int_x_red   = (png_fixed_point)(red_x*100000.+0.5);
   info_ptr->int_y_red   = (png_fixed_point)(red_y*100000.+0.5);
   info_ptr->int_x_green = (png_fixed_point)(green_x*100000.+0.5);
   info_ptr->int_y_green = (png_fixed_point)(green_y*100000.+0.5);
   info_ptr->int_x_blue  = (png_fixed_point)(blue_x*100000.+0.5);
   info_ptr->int_y_blue  = (png_fixed_point)(blue_y*100000.+0.5);
#endif
A
Andreas Dilger 已提交
61 62 63
   info_ptr->valid |= PNG_INFO_cHRM;
}
#endif
64
#ifdef PNG_FIXED_POINT_SUPPORTED
65
void PNGAPI
66
png_set_cHRM_fixed(png_structp png_ptr, png_infop info_ptr,
67 68 69
   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)
70 71 72 73
{
   png_debug1(1, "in %s storage function\n", "cHRM");
   if (png_ptr == NULL || info_ptr == NULL)
      return;
A
Andreas Dilger 已提交
74

75 76 77 78 79 80 81 82
   info_ptr->int_x_white = white_x;
   info_ptr->int_y_white = white_y;
   info_ptr->int_x_red   = red_x;
   info_ptr->int_y_red   = red_y;
   info_ptr->int_x_green = green_x;
   info_ptr->int_y_green = green_y;
   info_ptr->int_x_blue  = blue_x;
   info_ptr->int_y_blue  = blue_y;
83 84 85 86 87 88 89 90 91 92
#ifdef PNG_FLOATING_POINT_SUPPORTED
   info_ptr->x_white = (float)(white_x/100000.);
   info_ptr->y_white = (float)(white_y/100000.);
   info_ptr->x_red   = (float)(red_x/100000.);
   info_ptr->y_red   = (float)(red_y/100000.);
   info_ptr->x_green = (float)(green_x/100000.);
   info_ptr->y_green = (float)(green_y/100000.);
   info_ptr->x_blue  = (float)(blue_x/100000.);
   info_ptr->y_blue  = (float)(blue_y/100000.);
#endif
93 94 95 96 97 98 99
   info_ptr->valid |= PNG_INFO_cHRM;
}
#endif
#endif

#if defined(PNG_gAMA_SUPPORTED)
#ifdef PNG_FLOATING_POINT_SUPPORTED
100
void PNGAPI
A
Andreas Dilger 已提交
101 102 103
png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma)
{
   png_debug1(1, "in %s storage function\n", "gAMA");
104
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
105 106 107
      return;

   info_ptr->gamma = (float)file_gamma;
108 109 110 111
#ifdef PNG_FIXED_POINT_SUPPORTED
   info_ptr->int_gamma = (int)(file_gamma*100000.+.5);
#endif
   info_ptr->valid |= PNG_INFO_gAMA;
112 113
   if(file_gamma == 0.0)
      png_warning(png_ptr, "Setting gamma=0");
114 115
}
#endif
116
void PNGAPI
117 118
png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point
   int_gamma)
119 120 121 122 123 124
{
   png_debug1(1, "in %s storage function\n", "gAMA");
   if (png_ptr == NULL || info_ptr == NULL)
      return;

#ifdef PNG_FLOATING_POINT_SUPPORTED
125
   info_ptr->gamma = (float)(int_gamma/100000.);
126
#endif
127
#ifdef PNG_FIXED_POINT_SUPPORTED
128
   info_ptr->int_gamma = int_gamma;
129
#endif
A
Andreas Dilger 已提交
130
   info_ptr->valid |= PNG_INFO_gAMA;
131 132
   if(int_gamma == 0)
      png_warning(png_ptr, "Setting gamma=0");
A
Andreas Dilger 已提交
133
}
134
#endif
A
Andreas Dilger 已提交
135

136
#if defined(PNG_hIST_SUPPORTED)
137
void PNGAPI
A
Andreas Dilger 已提交
138 139
png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p hist)
{
140 141
   int	i;

A
Andreas Dilger 已提交
142
   png_debug1(1, "in %s storage function\n", "hIST");
143
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
144
      return;
145
   if (info_ptr->num_palette == 0)
146
   {
147
       png_warning(png_ptr,
148 149 150
          "Palette size 0, hIST allocation skipped.");
       return;
   }
151 152 153 154 155 156

#ifdef PNG_FREE_ME_SUPPORTED
   png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0);
#endif
   png_ptr->hist = (png_uint_16p)png_malloc(png_ptr,
      (png_uint_32)(info_ptr->num_palette * sizeof (png_uint_16)));
157 158 159 160 161
   if (png_ptr->hist == (png_uint_16p)NULL)
   {
      png_warning (png_ptr, "Could not allocate memory for histogram");
      return;
   }
A
Andreas Dilger 已提交
162

163 164 165
   for (i = 0; i < info_ptr->num_palette; i++)
       png_ptr->hist[i] = hist[i];
   info_ptr->hist = png_ptr->hist;
A
Andreas Dilger 已提交
166
   info_ptr->valid |= PNG_INFO_hIST;
167 168 169 170 171 172

#ifdef PNG_FREE_ME_SUPPORTED
   info_ptr->free_me |= PNG_FREE_HIST;
#else
   png_ptr->flags |= PNG_FLAG_FREE_HIST;
#endif
A
Andreas Dilger 已提交
173 174 175
}
#endif

176
void PNGAPI
A
Andreas Dilger 已提交
177 178 179 180 181
png_set_IHDR(png_structp png_ptr, png_infop info_ptr,
   png_uint_32 width, png_uint_32 height, int bit_depth,
   int color_type, int interlace_type, int compression_type,
   int filter_type)
{
182
   int rowbytes_per_pixel;
A
Andreas Dilger 已提交
183
   png_debug1(1, "in %s storage function\n", "IHDR");
184
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
185 186
      return;

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 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
   /* check for width and height valid values */
   if (width == 0 || height == 0)
      png_error(png_ptr, "Image width or height is zero in IHDR");
   if (width > PNG_MAX_UINT || height > PNG_MAX_UINT)
      png_error(png_ptr, "Invalid image size in IHDR");

   /* check other values */
   if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 &&
      bit_depth != 8 && bit_depth != 16)
      png_error(png_ptr, "Invalid bit depth in IHDR");

   if (color_type < 0 || color_type == 1 ||
      color_type == 5 || color_type > 6)
      png_error(png_ptr, "Invalid color type in IHDR");

   if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) ||
       ((color_type == PNG_COLOR_TYPE_RGB ||
         color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
         color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8))
      png_error(png_ptr, "Invalid color type/bit depth combination in IHDR");

   if (interlace_type >= PNG_INTERLACE_LAST)
      png_error(png_ptr, "Unknown interlace method in IHDR");

   if (compression_type != PNG_COMPRESSION_TYPE_BASE)
      png_error(png_ptr, "Unknown compression method in IHDR");

#if defined(PNG_MNG_FEATURES_SUPPORTED)
   /* Accept filter_method 64 (intrapixel differencing) only if
    * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
    * 2. Libpng did not read a PNG signature (this filter_method is only
    *    used in PNG datastreams that are embedded in MNG datastreams) and
    * 3. The application called png_permit_mng_features with a mask that
    *    included PNG_FLAG_MNG_FILTER_64 and
    * 4. The filter_method is 64 and
    * 5. The color_type is RGB or RGBA
    */
   if((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&png_ptr->mng_features_permitted)
      png_warning(png_ptr,"MNG features are not allowed in a PNG datastream\n");
   if(filter_type != PNG_FILTER_TYPE_BASE)
   {
     if(!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
        (filter_type == PNG_INTRAPIXEL_DIFFERENCING) &&
        ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&
        (color_type == PNG_COLOR_TYPE_RGB || 
         color_type == PNG_COLOR_TYPE_RGB_ALPHA)))
        png_error(png_ptr, "Unknown filter method in IHDR");
     if(png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)
        png_warning(png_ptr, "Invalid filter method in IHDR");
   }
#else
   if(filter_type != PNG_FILTER_TYPE_BASE)
      png_error(png_ptr, "Unknown filter method in IHDR");
#endif

A
Andreas Dilger 已提交
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
   info_ptr->width = width;
   info_ptr->height = height;
   info_ptr->bit_depth = (png_byte)bit_depth;
   info_ptr->color_type =(png_byte) color_type;
   info_ptr->compression_type = (png_byte)compression_type;
   info_ptr->filter_type = (png_byte)filter_type;
   info_ptr->interlace_type = (png_byte)interlace_type;
   if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
      info_ptr->channels = 1;
   else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
      info_ptr->channels = 3;
   else
      info_ptr->channels = 1;
   if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
      info_ptr->channels++;
   info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth);
258 259 260

   /* check for overflow */
   rowbytes_per_pixel = (info_ptr->pixel_depth + 7) >> 3;
261
   if (( width > PNG_MAX_UINT/rowbytes_per_pixel))
262 263 264 265 266
   {
      png_warning(png_ptr,
         "Width too large to process image data; rowbytes will overflow.");
      info_ptr->rowbytes = (png_size_t)0;
   }
267 268
   else
      info_ptr->rowbytes = (info_ptr->width * info_ptr->pixel_depth + 7) >> 3;
A
Andreas Dilger 已提交
269 270
}

271
#if defined(PNG_oFFs_SUPPORTED)
272
void PNGAPI
A
Andreas Dilger 已提交
273
png_set_oFFs(png_structp png_ptr, png_infop info_ptr,
274
   png_int_32 offset_x, png_int_32 offset_y, int unit_type)
A
Andreas Dilger 已提交
275 276
{
   png_debug1(1, "in %s storage function\n", "oFFs");
277
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
278 279 280 281 282 283 284 285 286
      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

287
#if defined(PNG_pCAL_SUPPORTED)
288
void PNGAPI
A
Andreas Dilger 已提交
289 290 291 292
png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
   png_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams,
   png_charp units, png_charpp params)
{
293
   png_uint_32 length;
294
   int i;
A
Andreas Dilger 已提交
295 296

   png_debug1(1, "in %s storage function\n", "pCAL");
297
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
298 299 300
      return;

   length = png_strlen(purpose) + 1;
301
   png_debug1(3, "allocating purpose for info (%lu bytes)\n", length);
A
Andreas Dilger 已提交
302
   info_ptr->pcal_purpose = (png_charp)png_malloc(png_ptr, length);
303 304 305 306 307
   if (info_ptr->pcal_purpose == (png_charp)NULL)
   {
      png_warning (png_ptr, "Could not allocate memory for pCAL");
      return;
   }
308
   png_memcpy(info_ptr->pcal_purpose, purpose, (png_size_t)length);
A
Andreas Dilger 已提交
309 310 311 312 313 314 315 316

   png_debug(3, "storing X0, X1, type, and nparams in info\n");
   info_ptr->pcal_X0 = X0;
   info_ptr->pcal_X1 = X1;
   info_ptr->pcal_type = (png_byte)type;
   info_ptr->pcal_nparams = (png_byte)nparams;

   length = png_strlen(units) + 1;
317
   png_debug1(3, "allocating units for info (%lu bytes)\n", length);
A
Andreas Dilger 已提交
318
   info_ptr->pcal_units = (png_charp)png_malloc(png_ptr, length);
319 320 321 322 323 324
   if (info_ptr->pcal_units == (png_charp)NULL)
   {
      png_free (png_ptr, info_ptr->pcal_purpose);
      png_warning (png_ptr, "Could not allocate memory for pCAL units");
      return;
   }
325
   png_memcpy(info_ptr->pcal_units, units, (png_size_t)length);
A
Andreas Dilger 已提交
326 327

   info_ptr->pcal_params = (png_charpp)png_malloc(png_ptr,
328
      (png_uint_32)((nparams + 1) * sizeof(png_charp)));
329 330 331 332 333 334 335 336
   if (info_ptr->pcal_params == (png_charpp)NULL)
   {
      png_free (png_ptr, info_ptr->pcal_purpose);
      png_free (png_ptr, info_ptr->pcal_units);
      png_warning (png_ptr, "Could not allocate memory for pCAL params");
      return;
   }

A
Andreas Dilger 已提交
337 338 339 340 341
   info_ptr->pcal_params[nparams] = NULL;

   for (i = 0; i < nparams; i++)
   {
      length = png_strlen(params[i]) + 1;
342
      png_debug2(3, "allocating parameter %d for info (%lu bytes)\n", i, length);
A
Andreas Dilger 已提交
343
      info_ptr->pcal_params[i] = (png_charp)png_malloc(png_ptr, length);
344 345 346 347 348 349 350
      if (info_ptr->pcal_params[i] == (png_charp)NULL)
      {
         nparams=i;
         png_warning (png_ptr, "Could not allocate memory for pCAL params");
      }
      else
         png_memcpy(info_ptr->pcal_params[i], params[i], (png_size_t)length);
A
Andreas Dilger 已提交
351 352 353
   }

   info_ptr->valid |= PNG_INFO_pCAL;
354 355 356
#ifdef PNG_FREE_ME_SUPPORTED
   info_ptr->free_me |= PNG_FREE_PCAL;
#endif
A
Andreas Dilger 已提交
357 358 359
}
#endif

360 361
#if defined(PNG_READ_sCAL_SUPPORTED) || defined(PNG_WRITE_sCAL_SUPPORTED)
#ifdef PNG_FLOATING_POINT_SUPPORTED
362
void PNGAPI
363
png_set_sCAL(png_structp png_ptr, png_infop info_ptr,
364
             int unit, double width, double height)
365 366 367 368 369
{
   png_debug1(1, "in %s storage function\n", "sCAL");
   if (png_ptr == NULL || info_ptr == NULL)
      return;

370
   info_ptr->scal_unit = (png_byte)unit;
371 372 373 374 375
   info_ptr->scal_pixel_width = width;
   info_ptr->scal_pixel_height = height;

   info_ptr->valid |= PNG_INFO_sCAL;
}
376 377
#else
#ifdef PNG_FIXED_POINT_SUPPORTED
378
void PNGAPI
379
png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr,
380
             int unit, png_charp swidth, png_charp sheight)
381 382 383 384 385 386 387
{
   png_uint_32 length;

   png_debug1(1, "in %s storage function\n", "sCAL");
   if (png_ptr == NULL || info_ptr == NULL)
      return;

388
   info_ptr->scal_unit = (png_byte)unit;
389 390 391 392

   length = png_strlen(swidth) + 1;
   png_debug1(3, "allocating unit for info (%d bytes)\n", length);
   info_ptr->scal_s_width = (png_charp)png_malloc(png_ptr, length);
393 394
   if (info_ptr->scal_s_width != (png_charp)NULL)
      png_memcpy(info_ptr->scal_s_width, swidth, (png_size_t)length);
395 396 397

   length = png_strlen(sheight) + 1;
   png_debug1(3, "allocating unit for info (%d bytes)\n", length);
398 399 400
   info_ptr->scal_s_height = (png_charp)png_malloc(png_ptr, length);
   if (info_ptr->scal_s_height != (png_charp)NULL)
      png_memcpy(info_ptr->scal_s_height, sheight, (png_size_t)length);
401 402

   info_ptr->valid |= PNG_INFO_sCAL;
403 404 405
#ifdef PNG_FREE_ME_SUPPORTED
   info_ptr->free_me |= PNG_FREE_SCAL;
#endif
406 407
}
#endif
408 409
#endif
#endif
410 411

#if defined(PNG_pHYs_SUPPORTED)
412
void PNGAPI
A
Andreas Dilger 已提交
413 414 415 416
png_set_pHYs(png_structp png_ptr, png_infop info_ptr,
   png_uint_32 res_x, png_uint_32 res_y, int unit_type)
{
   png_debug1(1, "in %s storage function\n", "pHYs");
417
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
418 419 420 421 422 423 424 425 426
      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

427
void PNGAPI
A
Andreas Dilger 已提交
428 429 430
png_set_PLTE(png_structp png_ptr, png_infop info_ptr,
   png_colorp palette, int num_palette)
{
431

A
Andreas Dilger 已提交
432
   png_debug1(1, "in %s storage function\n", "PLTE");
433
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
434 435
      return;

436 437 438 439 440 441 442 443 444 445
   /*
    * It may not actually be necessary to set png_ptr->palette here;
    * we do it for backward compatibility with the way the png_handle_tRNS
    * function used to do the allocation.
    */
#ifdef PNG_FREE_ME_SUPPORTED
   png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0);
#endif
   png_ptr->palette = (png_colorp)png_zalloc(png_ptr, (uInt)num_palette,
      sizeof (png_color));
446 447 448 449 450
   if (png_ptr->palette == (png_colorp)NULL)
   {
      png_warning(png_ptr, "Unable to allocate palette");
      return;
   }
451
   png_memcpy(png_ptr->palette, palette, num_palette * sizeof (png_color));
452 453 454 455 456 457 458 459
   info_ptr->palette = png_ptr->palette;
   info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette;

#ifdef PNG_FREE_ME_SUPPORTED
   info_ptr->free_me |= PNG_FREE_PLTE;
#else
   png_ptr->flags |= PNG_FLAG_FREE_PLTE;
#endif
460

461
   info_ptr->valid |= PNG_INFO_PLTE;
A
Andreas Dilger 已提交
462 463
}

464
#if defined(PNG_sBIT_SUPPORTED)
465
void PNGAPI
A
Andreas Dilger 已提交
466 467 468 469
png_set_sBIT(png_structp png_ptr, png_infop info_ptr,
   png_color_8p sig_bit)
{
   png_debug1(1, "in %s storage function\n", "sBIT");
470
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
471 472 473 474 475 476 477
      return;

   png_memcpy(&(info_ptr->sig_bit), sig_bit, sizeof (png_color_8));
   info_ptr->valid |= PNG_INFO_sBIT;
}
#endif

478
#if defined(PNG_sRGB_SUPPORTED)
479
void PNGAPI
480
png_set_sRGB(png_structp png_ptr, png_infop info_ptr, int intent)
481 482
{
   png_debug1(1, "in %s storage function\n", "sRGB");
483
   if (png_ptr == NULL || info_ptr == NULL)
484 485
      return;

486
   info_ptr->srgb_intent = (png_byte)intent;
487 488
   info_ptr->valid |= PNG_INFO_sRGB;
}
489

490
void PNGAPI
491
png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr,
492
   int intent)
493
{
494 495
#if defined(PNG_gAMA_SUPPORTED)
#ifdef PNG_FLOATING_POINT_SUPPORTED
496 497
   float file_gamma;
#endif
498
#ifdef PNG_FIXED_POINT_SUPPORTED
499
   png_fixed_point int_file_gamma;
500 501 502 503
#endif
#endif
#if defined(PNG_cHRM_SUPPORTED)
#ifdef PNG_FLOATING_POINT_SUPPORTED
504
   float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
505 506
#endif
#ifdef PNG_FIXED_POINT_SUPPORTED
507
   png_fixed_point int_white_x, int_white_y, int_red_x, int_red_y, int_green_x,
508 509
      int_green_y, int_blue_x, int_blue_y;
#endif
510 511
#endif
   png_debug1(1, "in %s storage function\n", "sRGB_gAMA_and_cHRM");
512
   if (png_ptr == NULL || info_ptr == NULL)
513 514 515 516
      return;

   png_set_sRGB(png_ptr, info_ptr, intent);

517 518
#if defined(PNG_gAMA_SUPPORTED)
#ifdef PNG_FLOATING_POINT_SUPPORTED
519
   file_gamma = (float).45455;
520 521
   png_set_gAMA(png_ptr, info_ptr, file_gamma);
#endif
522 523 524 525 526
#ifdef PNG_FIXED_POINT_SUPPORTED
   int_file_gamma = 45455L;
   png_set_gAMA_fixed(png_ptr, info_ptr, int_file_gamma);
#endif
#endif
527

528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543
#if defined(PNG_cHRM_SUPPORTED)
#ifdef PNG_FIXED_POINT_SUPPORTED
   int_white_x = 31270L;
   int_white_y = 32900L;
   int_red_x   = 64000L;
   int_red_y   = 33000L;
   int_green_x = 30000L;
   int_green_y = 60000L;
   int_blue_x  = 15000L;
   int_blue_y  =  6000L;

   png_set_cHRM_fixed(png_ptr, info_ptr,
      int_white_x, int_white_y, int_red_x, int_red_y, int_green_x, int_green_y,
      int_blue_x, int_blue_y);
#endif
#ifdef PNG_FLOATING_POINT_SUPPORTED
544 545 546 547 548 549 550 551
   white_x = (float).3127;
   white_y = (float).3290;
   red_x   = (float).64;
   red_y   = (float).33;
   green_x = (float).30;
   green_y = (float).60;
   blue_x  = (float).15;
   blue_y  = (float).06;
552 553 554

   png_set_cHRM(png_ptr, info_ptr,
      white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
555
#endif
556 557 558 559
#endif
}
#endif

560 561

#if defined(PNG_iCCP_SUPPORTED)
562
void PNGAPI
563 564
png_set_iCCP(png_structp png_ptr, png_infop info_ptr,
             png_charp name, int compression_type,
565
             png_charp profile, png_uint_32 proflen)
566
{
567 568 569
   png_charp new_iccp_name;
   png_charp new_iccp_profile;

570 571 572 573
   png_debug1(1, "in %s storage function\n", "iCCP");
   if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL)
      return;

574
   new_iccp_name = (png_charp)png_malloc(png_ptr, png_strlen(name)+1);
575 576 577 578 579
   if (new_iccp_name == (png_charp)NULL) 
   {
     png_warning (png_ptr, "Could not allocate memory for ICC profile name");
     return;
   }
580
   png_strcpy(new_iccp_name, name);
581
   new_iccp_profile = (png_charp)png_malloc(png_ptr, proflen);
582 583 584 585 586 587
   if (new_iccp_profile == (png_charp)NULL) 
   {
     png_warning (png_ptr, "Could not allocate memory for ICC profile");
     png_free (png_ptr, new_iccp_name);
     return;
   }
588 589
   png_memcpy(new_iccp_profile, profile, (png_size_t)proflen);

590
   png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0);
591

592
   info_ptr->iccp_proflen = proflen;
593 594
   info_ptr->iccp_name = new_iccp_name;
   info_ptr->iccp_profile = new_iccp_profile;
595
   /* Compression is always zero but is here so the API and info structure
596
    * does not have to change if we introduce multiple compression types */
597
   info_ptr->iccp_compression = (png_byte)compression_type;
598
#ifdef PNG_FREE_ME_SUPPORTED
599
   info_ptr->free_me |= PNG_FREE_ICCP;
600
#endif
601 602 603 604 605
   info_ptr->valid |= PNG_INFO_iCCP;
}
#endif

#if defined(PNG_TEXT_SUPPORTED)
606
void PNGAPI
A
Andreas Dilger 已提交
607 608 609 610 611 612
png_set_text(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr,
   int num_text)
{
   int i;

   png_debug1(1, "in %s storage function\n", (png_ptr->chunk_name[0] == '\0' ?
613
      "text" : (png_const_charp)png_ptr->chunk_name));
A
Andreas Dilger 已提交
614

615
   if (png_ptr == NULL || info_ptr == NULL || num_text == 0)
A
Andreas Dilger 已提交
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631
      return;

   /* Make sure we have enough space in the "text" array in info_struct
    * to hold all of the incoming text_ptr objects.
    */
   if (info_ptr->num_text + num_text > info_ptr->max_text)
   {
      if (info_ptr->text != NULL)
      {
         png_textp old_text;
         int old_max;

         old_max = info_ptr->max_text;
         info_ptr->max_text = info_ptr->num_text + num_text + 8;
         old_text = info_ptr->text;
         info_ptr->text = (png_textp)png_malloc(png_ptr,
632
            (png_uint_32)(info_ptr->max_text * sizeof (png_text)));
633 634 635 636 637 638
         if (info_ptr->text == (png_textp)NULL)
         {
            png_warning (png_ptr, "Could not allocate memory for text");
            info_ptr->text = old_text;
            return;
         }
639 640
         png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max *
            sizeof(png_text)));
A
Andreas Dilger 已提交
641 642 643 644 645 646 647
         png_free(png_ptr, old_text);
      }
      else
      {
         info_ptr->max_text = num_text + 8;
         info_ptr->num_text = 0;
         info_ptr->text = (png_textp)png_malloc(png_ptr,
648
            (png_uint_32)(info_ptr->max_text * sizeof (png_text)));
649 650 651 652 653
         if (info_ptr->text == (png_textp)NULL)
         {
            png_warning (png_ptr, "Could not allocate memory for text");
            return;
         }
654 655 656
#ifdef PNG_FREE_ME_SUPPORTED
         info_ptr->free_me |= PNG_FREE_TEXT;
#endif
A
Andreas Dilger 已提交
657 658 659 660 661 662
      }
      png_debug1(3, "allocated %d entries for info_ptr->text\n",
         info_ptr->max_text);
   }
   for (i = 0; i < num_text; i++)
   {
663 664
      png_size_t text_length,key_len;
      png_size_t lang_len,lang_key_len;
A
Andreas Dilger 已提交
665 666
      png_textp textp = &(info_ptr->text[info_ptr->num_text]);

667
      if (text_ptr[i].key == (png_charp)NULL)
668 669
          continue;

670 671
      key_len = png_strlen(text_ptr[i].key);

672 673 674 675 676 677
      if(text_ptr[i].compression <= 0)
      {
        lang_len = 0;
        lang_key_len = 0;
      }
      else
678
#ifdef PNG_iTXt_SUPPORTED
679 680
      {
        /* set iTXt data */
681 682 683 684 685 686 687 688
        if (text_ptr[i].key != (png_charp)NULL)
          lang_len = png_strlen(text_ptr[i].lang);
        else
          lang_len = 0;
        if (text_ptr[i].lang_key != (png_charp)NULL)
          lang_key_len = png_strlen(text_ptr[i].lang_key);
        else
          lang_key_len = 0;
689
      }
690 691 692 693 694 695
#else
      {
        png_warning(png_ptr, "iTXt chunk not supported.");
        continue;
      }
#endif
A
Andreas Dilger 已提交
696

697
      if (text_ptr[i].text == (png_charp)NULL || text_ptr[i].text[0] == '\0')
A
Andreas Dilger 已提交
698
      {
699
         text_length = 0;
700
#ifdef PNG_iTXt_SUPPORTED
701 702 703
         if(text_ptr[i].compression > 0)
            textp->compression = PNG_ITXT_COMPRESSION_NONE;
         else
704
#endif
705
            textp->compression = PNG_TEXT_COMPRESSION_NONE;
A
Andreas Dilger 已提交
706 707 708
      }
      else
      {
709
         text_length = png_strlen(text_ptr[i].text);
A
Andreas Dilger 已提交
710 711
         textp->compression = text_ptr[i].compression;
      }
712 713

      textp->key = (png_charp)png_malloc(png_ptr,
714
         (png_uint_32)(key_len + text_length + lang_len + lang_key_len + 4));
715 716 717 718 719
      if (textp->key == (png_charp)NULL)
      {
         png_warning (png_ptr, "Could not allocate memory for text pointer");
         return;
      }
720
      png_debug2(2, "Allocated %d bytes at %x in png_set_text\n",
721
         key_len + lang_len + lang_key_len + text_length + 4, (int)textp->key);
722 723

      png_memcpy(textp->key, text_ptr[i].key,
724 725
         (png_size_t)(key_len));
      *(textp->key+key_len) = '\0';
726
#ifdef PNG_iTXt_SUPPORTED
727 728 729 730 731 732 733 734 735 736 737
      if (text_ptr[i].compression > 0)
      {
         textp->lang=textp->key + key_len + 1;
         png_memcpy(textp->lang, text_ptr[i].lang, lang_len);
         *(textp->lang+lang_len) = '\0';
         textp->lang_key=textp->lang + lang_len + 1;
         png_memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len);
         *(textp->lang_key+lang_key_len) = '\0';
         textp->text=textp->lang_key + lang_key_len + 1;
      }
      else
738
#endif
739
      {
740
#ifdef PNG_iTXt_SUPPORTED
741 742
         textp->lang=(png_charp)NULL;
         textp->lang_key=(png_charp)NULL;
743
#endif
744 745 746
         textp->text=textp->key + key_len + 1;
      }
      if(text_length)
747
         png_memcpy(textp->text, text_ptr[i].text,
748
            (png_size_t)(text_length));
749
      *(textp->text+text_length) = '\0';
750

751
#ifdef PNG_iTXt_SUPPORTED
752 753 754 755 756 757
      if(textp->compression > 0)
      {
         textp->text_length = 0;
         textp->itxt_length = text_length;
      }
      else
758
#endif
759 760
      {
         textp->text_length = text_length;
761
#ifdef PNG_iTXt_SUPPORTED
762
         textp->itxt_length = 0;
763
#endif
764
      }
765
      info_ptr->text[info_ptr->num_text]= *textp;
A
Andreas Dilger 已提交
766 767 768 769 770 771
      info_ptr->num_text++;
      png_debug1(3, "transferred text chunk %d\n", info_ptr->num_text);
   }
}
#endif

772
#if defined(PNG_tIME_SUPPORTED)
773
void PNGAPI
A
Andreas Dilger 已提交
774 775 776
png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_timep mod_time)
{
   png_debug1(1, "in %s storage function\n", "tIME");
777
   if (png_ptr == NULL || info_ptr == NULL ||
778
       (png_ptr->mode & PNG_WROTE_tIME))
A
Andreas Dilger 已提交
779 780 781 782 783 784 785
      return;

   png_memcpy(&(info_ptr->mod_time), mod_time, sizeof (png_time));
   info_ptr->valid |= PNG_INFO_tIME;
}
#endif

786
#if defined(PNG_tRNS_SUPPORTED)
787
void PNGAPI
A
Andreas Dilger 已提交
788 789 790 791
png_set_tRNS(png_structp png_ptr, png_infop info_ptr,
   png_bytep trans, int num_trans, png_color_16p trans_values)
{
   png_debug1(1, "in %s storage function\n", "tRNS");
792
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
793 794 795
      return;

   if (trans != NULL)
796 797 798 799 800 801 802 803 804
   {
       /*
	* It may not actually be necessary to set png_ptr->trans here;
	* we do it for backward compatibility with the way the png_handle_tRNS
	* function used to do the allocation.
	*/
#ifdef PNG_FREE_ME_SUPPORTED
       png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
#endif
805 806
       png_ptr->trans = info_ptr->trans = (png_bytep)png_malloc(png_ptr,
           num_trans);
807 808 809 810 811
       if (png_ptr->trans == (png_bytep)NULL)
       {
          png_warning (png_ptr, "Could not allocate memory for tRNS array");
          return;
       }
812
       png_memcpy(info_ptr->trans, trans, num_trans);
813 814 815 816 817 818
#ifdef PNG_FREE_ME_SUPPORTED
       info_ptr->free_me |= PNG_FREE_TRNS;
#else
       png_ptr->flags |= PNG_FLAG_FREE_TRNS;
#endif
   }
A
Andreas Dilger 已提交
819 820 821 822 823

   if (trans_values != NULL)
   {
      png_memcpy(&(info_ptr->trans_values), trans_values,
         sizeof(png_color_16));
824 825
      if (num_trans == 0)
        num_trans = 1;
A
Andreas Dilger 已提交
826 827 828 829 830 831
   }
   info_ptr->num_trans = (png_uint_16)num_trans;
   info_ptr->valid |= PNG_INFO_tRNS;
}
#endif

832
#if defined(PNG_sPLT_SUPPORTED)
833
void PNGAPI
834
png_set_sPLT(png_structp png_ptr,
835
             png_infop info_ptr, png_sPLT_tp entries, int nentries)
836
{
837
    png_sPLT_tp np;
838 839
    int i;

840 841
    np = (png_sPLT_tp)png_malloc(png_ptr,
        (info_ptr->splt_palettes_num + nentries) * sizeof(png_sPLT_t));
842 843 844 845 846
    if (np == (png_sPLT_tp)NULL)
    {
       png_warning (png_ptr, "Could not allocate memory for sPLT");
       return;
    }
847

848
    png_memcpy(np, info_ptr->splt_palettes,
849
           info_ptr->splt_palettes_num * sizeof(png_sPLT_t));
850
    png_free(png_ptr, info_ptr->splt_palettes);
851
    info_ptr->splt_palettes=NULL;
852 853 854

    for (i = 0; i < nentries; i++)
    {
855 856
        png_sPLT_tp to = np + info_ptr->splt_palettes_num + i;
        png_sPLT_tp from = entries + i;
857 858

        to->name = (png_charp)png_malloc(png_ptr,
859
            png_strlen(from->name) + 1);
860
        png_strcpy(to->name, from->name);
861
        to->entries = (png_sPLT_entryp)png_malloc(png_ptr,
862 863 864 865 866 867 868 869 870
            from->nentries * sizeof(png_sPLT_t));
        if (to->entries == (png_sPLT_entryp)NULL)
        {
           png_warning(png_ptr, "Could not allocate memory for sPLT entry");
           nentries=i;
        }
        else
        {
          png_memcpy(to->entries, from->entries,
871
               from->nentries * sizeof(png_sPLT_t));
872 873 874
          to->nentries = from->nentries;
          to->depth = from->depth;
        }
875 876 877 878
    }

    info_ptr->splt_palettes = np;
    info_ptr->splt_palettes_num += nentries;
879
    info_ptr->valid |= PNG_INFO_sPLT;
880
#ifdef PNG_FREE_ME_SUPPORTED
881
    info_ptr->free_me |= PNG_FREE_SPLT;
882
#endif
883 884 885
}
#endif /* PNG_sPLT_SUPPORTED */

886
#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
887
void PNGAPI
888
png_set_unknown_chunks(png_structp png_ptr,
889
   png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns)
890 891 892 893
{
    png_unknown_chunkp np;
    int i;

894 895 896
    if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0)
        return;

897
    np = (png_unknown_chunkp)png_malloc(png_ptr,
898 899
        (info_ptr->unknown_chunks_num + num_unknowns) *
        sizeof(png_unknown_chunk));
900 901 902 903 904
    if (np == (png_unknown_chunkp)NULL)
    {
       png_warning (png_ptr, "Could not allocate memory for unknown chunk");
       return;
    }
905

906
    png_memcpy(np, info_ptr->unknown_chunks,
907 908
           info_ptr->unknown_chunks_num * sizeof(png_unknown_chunk));
    png_free(png_ptr, info_ptr->unknown_chunks);
909
    info_ptr->unknown_chunks=NULL;
910

911
    for (i = 0; i < num_unknowns; i++)
912 913 914 915
    {
        png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i;
        png_unknown_chunkp from = unknowns + i;

916
        png_strcpy((png_charp)to->name, (png_charp)from->name);
917
        to->data = (png_bytep)png_malloc(png_ptr, from->size);
918 919 920 921 922 923 924 925 926
        if (to->data == (png_bytep)NULL)
        {
           png_warning(png_ptr, "Could not allocate memory for unknown entry");
           num_unknowns=i;
        }
        else
        {
          png_memcpy(to->data, from->data, from->size);
          to->size = from->size;
927

928 929 930
          /* note our location in the read or write sequence */
          to->location = (png_byte)(png_ptr->mode & 0xff);
        }
931 932 933
    }

    info_ptr->unknown_chunks = np;
934
    info_ptr->unknown_chunks_num += num_unknowns;
935
#ifdef PNG_FREE_ME_SUPPORTED
936
    info_ptr->free_me |= PNG_FREE_UNKN;
937
#endif
938
}
939
void PNGAPI
940 941 942
png_set_unknown_chunk_location(png_structp png_ptr, png_infop info_ptr,
   int chunk, int location)
{
943
   if(png_ptr != NULL && info_ptr != NULL && chunk >= 0 && chunk <
944 945 946
         (int)info_ptr->unknown_chunks_num)
      info_ptr->unknown_chunks[chunk].location = (png_byte)location;
}
947 948
#endif

949 950
#if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \
    defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED)
951
void PNGAPI
952 953
png_permit_empty_plte (png_structp png_ptr, int empty_plte_permitted)
{
954 955 956
   /* This function is deprecated in favor of png_permit_mng_features()
      and will be removed from libpng-2.0.0 */
   png_debug(1, "in png_permit_empty_plte, DEPRECATED.\n");
957 958
   if (png_ptr == NULL)
      return;
959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974
   png_ptr->mng_features_permitted = (png_byte)
     ((png_ptr->mng_features_permitted & (~(PNG_FLAG_MNG_EMPTY_PLTE))) |
     ((empty_plte_permitted & PNG_FLAG_MNG_EMPTY_PLTE)));
}
#endif

#if defined(PNG_MNG_FEATURES_SUPPORTED)
png_uint_32 PNGAPI
png_permit_mng_features (png_structp png_ptr, png_uint_32 mng_features)
{
   png_debug(1, "in png_permit_mng_features\n");
   if (png_ptr == NULL)
      return (png_uint_32)0;
   png_ptr->mng_features_permitted =
     (png_byte)(mng_features & PNG_ALL_MNG_FEATURES);
   return (png_uint_32)png_ptr->mng_features_permitted;
975 976
}
#endif
977

978
#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
979
void PNGAPI
980 981 982 983 984 985 986 987 988 989 990
png_set_keep_unknown_chunks(png_structp png_ptr, int keep, png_bytep
   chunk_list, int num_chunks)
{
    png_bytep new_list, p;
    int i, old_num_chunks;
    if (num_chunks == 0)
    {
      if(keep == HANDLE_CHUNK_ALWAYS || keep == HANDLE_CHUNK_IF_SAFE)
        png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
      else
        png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
991

992 993 994 995 996 997 998 999 1000
      if(keep == HANDLE_CHUNK_ALWAYS)
        png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS;
      else
        png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS;
      return;
    }
    if (chunk_list == NULL)
      return;
    old_num_chunks=png_ptr->num_chunk_list;
1001
    new_list=(png_bytep)png_malloc(png_ptr,5*(num_chunks+old_num_chunks));
1002 1003 1004
    if(png_ptr->chunk_list != (png_bytep)NULL)
    {
       png_memcpy(new_list, png_ptr->chunk_list, 5*old_num_chunks);
1005
       png_free(png_ptr, png_ptr->chunk_list);
1006
       png_ptr->chunk_list=NULL;
1007 1008 1009 1010 1011 1012
    }
    png_memcpy(new_list+5*old_num_chunks, chunk_list, 5*num_chunks);
    for (p=new_list+5*old_num_chunks+4, i=0; i<num_chunks; i++, p+=5)
       *p=(png_byte)keep;
    png_ptr->num_chunk_list=old_num_chunks+num_chunks;
    png_ptr->chunk_list=new_list;
1013
#ifdef PNG_FREE_ME_SUPPORTED
1014
    png_ptr->free_me |= PNG_FREE_LIST;
1015
#endif
1016 1017
}
#endif
1018

1019
#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
1020
void PNGAPI
1021 1022 1023 1024 1025 1026 1027 1028
png_set_read_user_chunk_fn(png_structp png_ptr, png_voidp user_chunk_ptr,
   png_user_chunk_ptr read_user_chunk_fn)
{
   png_debug(1, "in png_set_read_user_chunk_fn\n");
   png_ptr->read_user_chunk_fn = read_user_chunk_fn;
   png_ptr->user_chunk_ptr = user_chunk_ptr;
}
#endif
1029

1030
#if defined(PNG_INFO_IMAGE_SUPPORTED)
1031
void PNGAPI
1032 1033 1034
png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers)
{
   png_debug1(1, "in %s storage function\n", "rows");
1035

1036 1037 1038
   if (png_ptr == NULL || info_ptr == NULL)
      return;

1039
   if(info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers))
1040
      png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
1041 1042 1043
   info_ptr->row_pointers = row_pointers;
   if(row_pointers)
      info_ptr->valid |= PNG_INFO_IDAT;
1044 1045 1046
}
#endif

1047
void PNGAPI
1048 1049 1050 1051 1052 1053
png_set_compression_buffer_size(png_structp png_ptr, png_uint_32 size)
{
    if(png_ptr->zbuf)
       png_free(png_ptr, png_ptr->zbuf);
    png_ptr->zbuf_size = (png_size_t)size;
    png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, size);
1054 1055
    if(!png_ptr->zbuf)
       png_error(png_ptr,"Unable to malloc zbuf");
1056 1057 1058
    png_ptr->zstream.next_out = png_ptr->zbuf;
    png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
}
1059 1060 1061 1062 1063 1064 1065

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