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

/* pngset.c - storage of image information into info struct
3
 *
4
 * libpng 1.2.0beta2 - May 7, 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)));
A
Andreas Dilger 已提交
157

158 159 160
   for (i = 0; i < info_ptr->num_palette; i++)
       png_ptr->hist[i] = hist[i];
   info_ptr->hist = png_ptr->hist;
A
Andreas Dilger 已提交
161
   info_ptr->valid |= PNG_INFO_hIST;
162 163 164 165 166 167

#ifdef PNG_FREE_ME_SUPPORTED
   info_ptr->free_me |= PNG_FREE_HIST;
#else
   png_ptr->flags |= PNG_FLAG_FREE_HIST;
#endif
A
Andreas Dilger 已提交
168 169 170
}
#endif

171
void PNGAPI
A
Andreas Dilger 已提交
172 173 174 175 176
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)
{
177
   int rowbytes_per_pixel;
A
Andreas Dilger 已提交
178
   png_debug1(1, "in %s storage function\n", "IHDR");
179
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
180 181
      return;

182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 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
   /* 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 已提交
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
   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);
253 254 255

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

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

282
#if defined(PNG_pCAL_SUPPORTED)
283
void PNGAPI
A
Andreas Dilger 已提交
284 285 286 287
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)
{
288
   png_uint_32 length;
289
   int i;
A
Andreas Dilger 已提交
290 291

   png_debug1(1, "in %s storage function\n", "pCAL");
292
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
293 294 295
      return;

   length = png_strlen(purpose) + 1;
296
   png_debug1(3, "allocating purpose for info (%lu bytes)\n", length);
A
Andreas Dilger 已提交
297
   info_ptr->pcal_purpose = (png_charp)png_malloc(png_ptr, length);
298
   png_memcpy(info_ptr->pcal_purpose, purpose, (png_size_t)length);
A
Andreas Dilger 已提交
299 300 301 302 303 304 305 306

   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;
307
   png_debug1(3, "allocating units for info (%lu bytes)\n", length);
A
Andreas Dilger 已提交
308
   info_ptr->pcal_units = (png_charp)png_malloc(png_ptr, length);
309
   png_memcpy(info_ptr->pcal_units, units, (png_size_t)length);
A
Andreas Dilger 已提交
310 311

   info_ptr->pcal_params = (png_charpp)png_malloc(png_ptr,
312
      (png_uint_32)((nparams + 1) * sizeof(png_charp)));
313

A
Andreas Dilger 已提交
314 315 316 317 318
   info_ptr->pcal_params[nparams] = NULL;

   for (i = 0; i < nparams; i++)
   {
      length = png_strlen(params[i]) + 1;
319
      png_debug2(3, "allocating parameter %d for info (%lu bytes)\n", i, length);
A
Andreas Dilger 已提交
320
      info_ptr->pcal_params[i] = (png_charp)png_malloc(png_ptr, length);
321
      png_memcpy(info_ptr->pcal_params[i], params[i], (png_size_t)length);
A
Andreas Dilger 已提交
322 323 324
   }

   info_ptr->valid |= PNG_INFO_pCAL;
325 326 327
#ifdef PNG_FREE_ME_SUPPORTED
   info_ptr->free_me |= PNG_FREE_PCAL;
#endif
A
Andreas Dilger 已提交
328 329 330
}
#endif

331 332
#if defined(PNG_READ_sCAL_SUPPORTED) || defined(PNG_WRITE_sCAL_SUPPORTED)
#ifdef PNG_FLOATING_POINT_SUPPORTED
333
void PNGAPI
334
png_set_sCAL(png_structp png_ptr, png_infop info_ptr,
335
             int unit, double width, double height)
336 337 338 339 340
{
   png_debug1(1, "in %s storage function\n", "sCAL");
   if (png_ptr == NULL || info_ptr == NULL)
      return;

341
   info_ptr->scal_unit = (png_byte)unit;
342 343 344 345 346
   info_ptr->scal_pixel_width = width;
   info_ptr->scal_pixel_height = height;

   info_ptr->valid |= PNG_INFO_sCAL;
}
347 348
#else
#ifdef PNG_FIXED_POINT_SUPPORTED
349
void PNGAPI
350
png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr,
351
             int unit, png_charp swidth, png_charp sheight)
352 353 354 355 356 357 358
{
   png_uint_32 length;

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

359
   info_ptr->scal_unit = (png_byte)unit;
360 361 362 363

   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);
364
   png_memcpy(info_ptr->scal_s_width, swidth, (png_size_t)length);
365 366 367

   length = png_strlen(sheight) + 1;
   png_debug1(3, "allocating unit for info (%d bytes)\n", length);
368
   info_ptr->scal_s_height = (png_charp)png_malloc(png_ptr, length);
369
   png_memcpy(info_ptr->scal_s_height, sheight, (png_size_t)length);
370 371

   info_ptr->valid |= PNG_INFO_sCAL;
372 373 374
#ifdef PNG_FREE_ME_SUPPORTED
   info_ptr->free_me |= PNG_FREE_SCAL;
#endif
375 376
}
#endif
377 378
#endif
#endif
379 380

#if defined(PNG_pHYs_SUPPORTED)
381
void PNGAPI
A
Andreas Dilger 已提交
382 383 384 385
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");
386
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
387 388 389 390 391 392 393 394 395
      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

396
void PNGAPI
A
Andreas Dilger 已提交
397 398 399
png_set_PLTE(png_structp png_ptr, png_infop info_ptr,
   png_colorp palette, int num_palette)
{
400

A
Andreas Dilger 已提交
401
   png_debug1(1, "in %s storage function\n", "PLTE");
402
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
403 404
      return;

405 406 407 408 409 410 411 412 413 414
   /*
    * 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));
415
   png_memcpy(png_ptr->palette, palette, num_palette * sizeof (png_color));
416 417 418 419 420 421 422 423
   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
424

425
   info_ptr->valid |= PNG_INFO_PLTE;
A
Andreas Dilger 已提交
426 427
}

428
#if defined(PNG_sBIT_SUPPORTED)
429
void PNGAPI
A
Andreas Dilger 已提交
430 431 432 433
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");
434
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
435 436 437 438 439 440 441
      return;

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

442
#if defined(PNG_sRGB_SUPPORTED)
443
void PNGAPI
444
png_set_sRGB(png_structp png_ptr, png_infop info_ptr, int intent)
445 446
{
   png_debug1(1, "in %s storage function\n", "sRGB");
447
   if (png_ptr == NULL || info_ptr == NULL)
448 449
      return;

450
   info_ptr->srgb_intent = (png_byte)intent;
451 452
   info_ptr->valid |= PNG_INFO_sRGB;
}
453

454
void PNGAPI
455
png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr,
456
   int intent)
457
{
458 459
#if defined(PNG_gAMA_SUPPORTED)
#ifdef PNG_FLOATING_POINT_SUPPORTED
460 461
   float file_gamma;
#endif
462
#ifdef PNG_FIXED_POINT_SUPPORTED
463
   png_fixed_point int_file_gamma;
464 465 466 467
#endif
#endif
#if defined(PNG_cHRM_SUPPORTED)
#ifdef PNG_FLOATING_POINT_SUPPORTED
468
   float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
469 470
#endif
#ifdef PNG_FIXED_POINT_SUPPORTED
471
   png_fixed_point int_white_x, int_white_y, int_red_x, int_red_y, int_green_x,
472 473
      int_green_y, int_blue_x, int_blue_y;
#endif
474 475
#endif
   png_debug1(1, "in %s storage function\n", "sRGB_gAMA_and_cHRM");
476
   if (png_ptr == NULL || info_ptr == NULL)
477 478 479 480
      return;

   png_set_sRGB(png_ptr, info_ptr, intent);

481 482
#if defined(PNG_gAMA_SUPPORTED)
#ifdef PNG_FLOATING_POINT_SUPPORTED
483
   file_gamma = (float).45455;
484 485
   png_set_gAMA(png_ptr, info_ptr, file_gamma);
#endif
486 487 488 489 490
#ifdef PNG_FIXED_POINT_SUPPORTED
   int_file_gamma = 45455L;
   png_set_gAMA_fixed(png_ptr, info_ptr, int_file_gamma);
#endif
#endif
491

492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
#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
508 509 510 511 512 513 514 515
   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;
516 517 518

   png_set_cHRM(png_ptr, info_ptr,
      white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
519
#endif
520 521 522 523
#endif
}
#endif

524 525

#if defined(PNG_iCCP_SUPPORTED)
526
void PNGAPI
527 528
png_set_iCCP(png_structp png_ptr, png_infop info_ptr,
             png_charp name, int compression_type,
529
             png_charp profile, png_uint_32 proflen)
530
{
531 532 533
   png_charp new_iccp_name;
   png_charp new_iccp_profile;

534 535 536 537
   png_debug1(1, "in %s storage function\n", "iCCP");
   if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL)
      return;

538 539 540
   new_iccp_name = (png_charp)png_malloc(png_ptr, png_strlen(name)+1);
   png_strcpy(new_iccp_name, name);
   new_iccp_profile = (png_charp)png_malloc(png_ptr, proflen);
541 542
   png_memcpy(new_iccp_profile, profile, (png_size_t)proflen);

543
   png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0);
544

545
   info_ptr->iccp_proflen = proflen;
546 547
   info_ptr->iccp_name = new_iccp_name;
   info_ptr->iccp_profile = new_iccp_profile;
548
   /* Compression is always zero but is here so the API and info structure
549
    * does not have to change if we introduce multiple compression types */
550
   info_ptr->iccp_compression = (png_byte)compression_type;
551
#ifdef PNG_FREE_ME_SUPPORTED
552
   info_ptr->free_me |= PNG_FREE_ICCP;
553
#endif
554 555 556 557 558
   info_ptr->valid |= PNG_INFO_iCCP;
}
#endif

#if defined(PNG_TEXT_SUPPORTED)
559
void PNGAPI
A
Andreas Dilger 已提交
560 561 562 563 564 565
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' ?
566
      "text" : (png_const_charp)png_ptr->chunk_name));
A
Andreas Dilger 已提交
567

568
   if (png_ptr == NULL || info_ptr == NULL || num_text == 0)
A
Andreas Dilger 已提交
569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584
      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,
585
            (png_uint_32)(info_ptr->max_text * sizeof (png_text)));
586 587
         png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max *
            sizeof(png_text)));
A
Andreas Dilger 已提交
588 589 590 591 592 593 594
         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,
595
            (png_uint_32)(info_ptr->max_text * sizeof (png_text)));
596 597 598
#ifdef PNG_FREE_ME_SUPPORTED
         info_ptr->free_me |= PNG_FREE_TEXT;
#endif
A
Andreas Dilger 已提交
599 600 601 602 603 604
      }
      png_debug1(3, "allocated %d entries for info_ptr->text\n",
         info_ptr->max_text);
   }
   for (i = 0; i < num_text; i++)
   {
605 606
      png_size_t text_length,key_len;
      png_size_t lang_len,lang_key_len;
A
Andreas Dilger 已提交
607 608
      png_textp textp = &(info_ptr->text[info_ptr->num_text]);

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

612 613
      key_len = png_strlen(text_ptr[i].key);

614 615 616 617 618 619
      if(text_ptr[i].compression <= 0)
      {
        lang_len = 0;
        lang_key_len = 0;
      }
      else
620
#ifdef PNG_iTXt_SUPPORTED
621 622
      {
        /* set iTXt data */
623
        if (text_ptr[i].key != NULL)
624 625 626
          lang_len = png_strlen(text_ptr[i].lang);
        else
          lang_len = 0;
627
        if (text_ptr[i].lang_key != NULL)
628 629 630
          lang_key_len = png_strlen(text_ptr[i].lang_key);
        else
          lang_key_len = 0;
631
      }
632 633 634 635 636 637
#else
      {
        png_warning(png_ptr, "iTXt chunk not supported.");
        continue;
      }
#endif
A
Andreas Dilger 已提交
638

639
      if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0')
A
Andreas Dilger 已提交
640
      {
641
         text_length = 0;
642
#ifdef PNG_iTXt_SUPPORTED
643 644 645
         if(text_ptr[i].compression > 0)
            textp->compression = PNG_ITXT_COMPRESSION_NONE;
         else
646
#endif
647
            textp->compression = PNG_TEXT_COMPRESSION_NONE;
A
Andreas Dilger 已提交
648 649 650
      }
      else
      {
651
         text_length = png_strlen(text_ptr[i].text);
A
Andreas Dilger 已提交
652 653
         textp->compression = text_ptr[i].compression;
      }
654 655

      textp->key = (png_charp)png_malloc(png_ptr,
656
         (png_uint_32)(key_len + text_length + lang_len + lang_key_len + 4));
657 658
      png_debug2(2, "Allocated %d bytes at %x in png_set_text\n",
         key_len + lang_len + lang_key_len + text_length + 4, (int)textp->key);
659 660

      png_memcpy(textp->key, text_ptr[i].key,
661 662
         (png_size_t)(key_len));
      *(textp->key+key_len) = '\0';
663
#ifdef PNG_iTXt_SUPPORTED
664 665 666 667 668 669 670 671 672 673 674
      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
675
#endif
676
      {
677
#ifdef PNG_iTXt_SUPPORTED
678 679
         textp->lang=(png_charp)NULL;
         textp->lang_key=(png_charp)NULL;
680
#endif
681 682 683
         textp->text=textp->key + key_len + 1;
      }
      if(text_length)
684
         png_memcpy(textp->text, text_ptr[i].text,
685
            (png_size_t)(text_length));
686
      *(textp->text+text_length) = '\0';
687

688
#ifdef PNG_iTXt_SUPPORTED
689 690 691 692 693 694
      if(textp->compression > 0)
      {
         textp->text_length = 0;
         textp->itxt_length = text_length;
      }
      else
695
#endif
696 697
      {
         textp->text_length = text_length;
698
#ifdef PNG_iTXt_SUPPORTED
699
         textp->itxt_length = 0;
700
#endif
701
      }
702
      info_ptr->text[info_ptr->num_text]= *textp;
A
Andreas Dilger 已提交
703 704 705 706 707 708
      info_ptr->num_text++;
      png_debug1(3, "transferred text chunk %d\n", info_ptr->num_text);
   }
}
#endif

709
#if defined(PNG_tIME_SUPPORTED)
710
void PNGAPI
A
Andreas Dilger 已提交
711 712 713
png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_timep mod_time)
{
   png_debug1(1, "in %s storage function\n", "tIME");
714
   if (png_ptr == NULL || info_ptr == NULL ||
715
       (png_ptr->mode & PNG_WROTE_tIME))
A
Andreas Dilger 已提交
716 717 718 719 720 721 722
      return;

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

723
#if defined(PNG_tRNS_SUPPORTED)
724
void PNGAPI
A
Andreas Dilger 已提交
725 726 727 728
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");
729
   if (png_ptr == NULL || info_ptr == NULL)
A
Andreas Dilger 已提交
730 731 732
      return;

   if (trans != NULL)
733 734 735 736 737 738 739 740 741
   {
       /*
	* 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
742 743 744
       png_ptr->trans = info_ptr->trans = (png_bytep)png_malloc(png_ptr,
           num_trans);
       png_memcpy(info_ptr->trans, trans, num_trans);
745 746 747 748 749 750
#ifdef PNG_FREE_ME_SUPPORTED
       info_ptr->free_me |= PNG_FREE_TRNS;
#else
       png_ptr->flags |= PNG_FLAG_FREE_TRNS;
#endif
   }
A
Andreas Dilger 已提交
751 752 753 754 755

   if (trans_values != NULL)
   {
      png_memcpy(&(info_ptr->trans_values), trans_values,
         sizeof(png_color_16));
756 757
      if (num_trans == 0)
        num_trans = 1;
A
Andreas Dilger 已提交
758 759 760 761 762 763
   }
   info_ptr->num_trans = (png_uint_16)num_trans;
   info_ptr->valid |= PNG_INFO_tRNS;
}
#endif

764
#if defined(PNG_sPLT_SUPPORTED)
765
void PNGAPI
766
png_set_sPLT(png_structp png_ptr,
767
             png_infop info_ptr, png_sPLT_tp entries, int nentries)
768
{
769
    png_sPLT_tp np;
770 771
    int i;

772 773
    np = (png_sPLT_tp)png_malloc(png_ptr,
        (info_ptr->splt_palettes_num + nentries) * sizeof(png_sPLT_t));
774

775
    png_memcpy(np, info_ptr->splt_palettes,
776
           info_ptr->splt_palettes_num * sizeof(png_sPLT_t));
777
    png_free(png_ptr, info_ptr->splt_palettes);
778
    info_ptr->splt_palettes=NULL;
779 780 781

    for (i = 0; i < nentries; i++)
    {
782 783
        png_sPLT_tp to = np + info_ptr->splt_palettes_num + i;
        png_sPLT_tp from = entries + i;
784 785

        to->name = (png_charp)png_malloc(png_ptr,
786
            png_strlen(from->name) + 1);
787
        png_strcpy(to->name, from->name);
788
        to->entries = (png_sPLT_entryp)png_malloc(png_ptr,
789
            from->nentries * sizeof(png_sPLT_t));
790
        png_memcpy(to->entries, from->entries,
791
            from->nentries * sizeof(png_sPLT_t));
792 793
        to->nentries = from->nentries;
        to->depth = from->depth;
794 795 796 797
    }

    info_ptr->splt_palettes = np;
    info_ptr->splt_palettes_num += nentries;
798
    info_ptr->valid |= PNG_INFO_sPLT;
799
#ifdef PNG_FREE_ME_SUPPORTED
800
    info_ptr->free_me |= PNG_FREE_SPLT;
801
#endif
802 803 804
}
#endif /* PNG_sPLT_SUPPORTED */

805
#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
806
void PNGAPI
807
png_set_unknown_chunks(png_structp png_ptr,
808
   png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns)
809 810 811 812
{
    png_unknown_chunkp np;
    int i;

813 814 815
    if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0)
        return;

816
    np = (png_unknown_chunkp)png_malloc(png_ptr,
817 818
        (info_ptr->unknown_chunks_num + num_unknowns) *
        sizeof(png_unknown_chunk));
819

820
    png_memcpy(np, info_ptr->unknown_chunks,
821 822
           info_ptr->unknown_chunks_num * sizeof(png_unknown_chunk));
    png_free(png_ptr, info_ptr->unknown_chunks);
823
    info_ptr->unknown_chunks=NULL;
824

825
    for (i = 0; i < num_unknowns; i++)
826 827 828 829
    {
        png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i;
        png_unknown_chunkp from = unknowns + i;

830
        png_strcpy((png_charp)to->name, (png_charp)from->name);
831
        to->data = (png_bytep)png_malloc(png_ptr, from->size);
832 833
        png_memcpy(to->data, from->data, from->size);
        to->size = from->size;
834

835 836
        /* note our location in the read or write sequence */
        to->location = (png_byte)(png_ptr->mode & 0xff);
837 838 839
    }

    info_ptr->unknown_chunks = np;
840
    info_ptr->unknown_chunks_num += num_unknowns;
841
#ifdef PNG_FREE_ME_SUPPORTED
842
    info_ptr->free_me |= PNG_FREE_UNKN;
843
#endif
844
}
845
void PNGAPI
846 847 848
png_set_unknown_chunk_location(png_structp png_ptr, png_infop info_ptr,
   int chunk, int location)
{
849
   if(png_ptr != NULL && info_ptr != NULL && chunk >= 0 && chunk <
850 851 852
         (int)info_ptr->unknown_chunks_num)
      info_ptr->unknown_chunks[chunk].location = (png_byte)location;
}
853 854
#endif

855 856
#if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \
    defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED)
857
void PNGAPI
858 859
png_permit_empty_plte (png_structp png_ptr, int empty_plte_permitted)
{
860 861 862
   /* 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");
863 864
   if (png_ptr == NULL)
      return;
865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880
   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;
881 882
}
#endif
883

884
#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
885
void PNGAPI
886 887 888 889 890 891 892 893 894 895 896
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;
897

898 899 900 901 902 903 904 905 906
      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;
907 908
    new_list=(png_bytep)png_malloc(png_ptr,5*(num_chunks+old_num_chunks));
    if(png_ptr->chunk_list != NULL)
909 910
    {
       png_memcpy(new_list, png_ptr->chunk_list, 5*old_num_chunks);
911
       png_free(png_ptr, png_ptr->chunk_list);
912
       png_ptr->chunk_list=NULL;
913 914 915 916 917 918
    }
    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;
919
#ifdef PNG_FREE_ME_SUPPORTED
920
    png_ptr->free_me |= PNG_FREE_LIST;
921
#endif
922 923
}
#endif
924

925
#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
926
void PNGAPI
927 928 929 930 931 932 933 934
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
935

936
#if defined(PNG_INFO_IMAGE_SUPPORTED)
937
void PNGAPI
938 939 940
png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers)
{
   png_debug1(1, "in %s storage function\n", "rows");
941

942 943 944
   if (png_ptr == NULL || info_ptr == NULL)
      return;

945
   if(info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers))
946
      png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
947 948 949
   info_ptr->row_pointers = row_pointers;
   if(row_pointers)
      info_ptr->valid |= PNG_INFO_IDAT;
950 951 952
}
#endif

953
void PNGAPI
954 955 956 957 958 959 960 961 962
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);
    png_ptr->zstream.next_out = png_ptr->zbuf;
    png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
}
963 964 965 966 967 968 969

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

971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025

#ifdef PNG_ASSEMBLER_CODE_SUPPORTED
/* this function was added to libpng 1.2.0 and should always exist by default */
void PNGAPI
png_set_asm_flags (png_structp png_ptr, png_uint_32 asm_flags)
{
    png_uint_32 settable_asm_flags;
    png_uint_32 settable_mmx_flags;

    settable_mmx_flags =
#ifdef PNG_HAVE_ASSEMBLER_COMBINE_ROW
                         PNG_ASM_FLAG_MMX_READ_COMBINE_ROW  |
#endif
#ifdef PNG_HAVE_ASSEMBLER_READ_INTERLACE
                         PNG_ASM_FLAG_MMX_READ_INTERLACE    |
#endif
#ifdef PNG_HAVE_ASSEMBLER_READ_FILTER_ROW
                         PNG_ASM_FLAG_MMX_READ_FILTER_SUB   |
                         PNG_ASM_FLAG_MMX_READ_FILTER_UP    |
                         PNG_ASM_FLAG_MMX_READ_FILTER_AVG   |
                         PNG_ASM_FLAG_MMX_READ_FILTER_PAETH |
#endif
                         0;

    /* could be some non-MMX ones in the future, but not currently: */
    settable_asm_flags = settable_mmx_flags;

    if (!(png_ptr->asm_flags & PNG_ASM_FLAG_MMX_SUPPORT_COMPILED) ||
        !(png_ptr->asm_flags & PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU))
    {
        /* clear all MMX flags if MMX isn't supported */
        settable_asm_flags &= ~settable_mmx_flags;
        png_ptr->asm_flags &= ~settable_mmx_flags;
    }

    /* we're replacing the settable bits with those passed in by the user,
     * so first zero them out of the master copy, then logical-OR in the
     * allowed subset that was requested */

    png_ptr->asm_flags &= ~settable_asm_flags;			/* zero them */
    png_ptr->asm_flags |= (asm_flags & settable_asm_flags);	/* set them */
}
#endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */

#ifdef PNG_ASSEMBLER_CODE_SUPPORTED
/* this function was added to libpng 1.2.0 */
void PNGAPI
png_set_mmx_thresholds (png_structp png_ptr,
                        png_byte mmx_bitdepth_threshold,
                        png_uint_32 mmx_rowbytes_threshold)
{
    png_ptr->mmx_bitdepth_threshold = mmx_bitdepth_threshold;
    png_ptr->mmx_rowbytes_threshold = mmx_rowbytes_threshold;
}
#endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */