1/* PDFlib GmbH cvsid: $Id: pngset.c 14574 2005-10-29 16:27:43Z bonefish $ */ 2 3/* pngset.c - storage of image information into info struct 4 * 5 * libpng 1.2.5 - October 3, 2002 6 * For conditions of distribution and use, see copyright notice in png.h 7 * Copyright (c) 1998-2002 Glenn Randers-Pehrson 8 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) 9 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) 10 * 11 * The functions here are used during reads to store data from the file 12 * into the info struct, and during writes to store application data 13 * into the info struct for writing into the file. This abstracts the 14 * info struct and allows us to change the structure in the future. 15 */ 16 17#define PNG_INTERNAL 18#include "png.h" 19 20#if defined(PNG_bKGD_SUPPORTED) 21void PNGAPI 22png_set_bKGD(png_structp png_ptr, png_infop info_ptr, png_color_16p background) 23{ 24 png_debug1(1, "in %s storage function\n", "bKGD"); 25 if (png_ptr == NULL || info_ptr == NULL) 26 return; 27 28 png_memcpy(&(info_ptr->background), background, sizeof(png_color_16)); 29 info_ptr->valid |= PNG_INFO_bKGD; 30} 31#endif 32 33#if defined(PNG_cHRM_SUPPORTED) 34#ifdef PNG_FLOATING_POINT_SUPPORTED 35void PNGAPI 36png_set_cHRM(png_structp png_ptr, png_infop info_ptr, 37 double white_x, double white_y, double red_x, double red_y, 38 double green_x, double green_y, double blue_x, double blue_y) 39{ 40 png_debug1(1, "in %s storage function\n", "cHRM"); 41 if (png_ptr == NULL || info_ptr == NULL) 42 return; 43 44 if (white_x < 0.0 || white_y < 0.0 || 45 red_x < 0.0 || red_y < 0.0 || 46 green_x < 0.0 || green_y < 0.0 || 47 blue_x < 0.0 || blue_y < 0.0) 48 { 49 png_warning(png_ptr, 50 "Ignoring attempt to set negative chromaticity value"); 51 return; 52 } 53 if (white_x > 21474.83 || white_y > 21474.83 || 54 red_x > 21474.83 || red_y > 21474.83 || 55 green_x > 21474.83 || green_y > 21474.83 || 56 blue_x > 21474.83 || blue_y > 21474.83) 57 { 58 png_warning(png_ptr, 59 "Ignoring attempt to set chromaticity value exceeding 21474.83"); 60 return; 61 } 62 63 info_ptr->x_white = (float)white_x; 64 info_ptr->y_white = (float)white_y; 65 info_ptr->x_red = (float)red_x; 66 info_ptr->y_red = (float)red_y; 67 info_ptr->x_green = (float)green_x; 68 info_ptr->y_green = (float)green_y; 69 info_ptr->x_blue = (float)blue_x; 70 info_ptr->y_blue = (float)blue_y; 71#ifdef PNG_FIXED_POINT_SUPPORTED 72 info_ptr->int_x_white = (png_fixed_point)(white_x*100000.+0.5); 73 info_ptr->int_y_white = (png_fixed_point)(white_y*100000.+0.5); 74 info_ptr->int_x_red = (png_fixed_point)( red_x*100000.+0.5); 75 info_ptr->int_y_red = (png_fixed_point)( red_y*100000.+0.5); 76 info_ptr->int_x_green = (png_fixed_point)(green_x*100000.+0.5); 77 info_ptr->int_y_green = (png_fixed_point)(green_y*100000.+0.5); 78 info_ptr->int_x_blue = (png_fixed_point)( blue_x*100000.+0.5); 79 info_ptr->int_y_blue = (png_fixed_point)( blue_y*100000.+0.5); 80#endif 81 info_ptr->valid |= PNG_INFO_cHRM; 82} 83#endif 84#ifdef PNG_FIXED_POINT_SUPPORTED 85void PNGAPI 86png_set_cHRM_fixed(png_structp png_ptr, png_infop info_ptr, 87 png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x, 88 png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y, 89 png_fixed_point blue_x, png_fixed_point blue_y) 90{ 91 png_debug1(1, "in %s storage function\n", "cHRM"); 92 if (png_ptr == NULL || info_ptr == NULL) 93 return; 94 95 if (white_x < 0 || white_y < 0 || 96 red_x < 0 || red_y < 0 || 97 green_x < 0 || green_y < 0 || 98 blue_x < 0 || blue_y < 0) 99 { 100 png_warning(png_ptr, 101 "Ignoring attempt to set negative chromaticity value"); 102 return; 103 } 104 if (white_x > (double) PNG_MAX_UINT || white_y > (double) PNG_MAX_UINT || 105 red_x > (double) PNG_MAX_UINT || red_y > (double) PNG_MAX_UINT || 106 green_x > (double) PNG_MAX_UINT || green_y > (double) PNG_MAX_UINT || 107 blue_x > (double) PNG_MAX_UINT || blue_y > (double) PNG_MAX_UINT) 108 { 109 png_warning(png_ptr, 110 "Ignoring attempt to set chromaticity value exceeding 21474.83"); 111 return; 112 } 113 info_ptr->int_x_white = white_x; 114 info_ptr->int_y_white = white_y; 115 info_ptr->int_x_red = red_x; 116 info_ptr->int_y_red = red_y; 117 info_ptr->int_x_green = green_x; 118 info_ptr->int_y_green = green_y; 119 info_ptr->int_x_blue = blue_x; 120 info_ptr->int_y_blue = blue_y; 121#ifdef PNG_FLOATING_POINT_SUPPORTED 122 info_ptr->x_white = (float)(white_x/100000.); 123 info_ptr->y_white = (float)(white_y/100000.); 124 info_ptr->x_red = (float)( red_x/100000.); 125 info_ptr->y_red = (float)( red_y/100000.); 126 info_ptr->x_green = (float)(green_x/100000.); 127 info_ptr->y_green = (float)(green_y/100000.); 128 info_ptr->x_blue = (float)( blue_x/100000.); 129 info_ptr->y_blue = (float)( blue_y/100000.); 130#endif 131 info_ptr->valid |= PNG_INFO_cHRM; 132} 133#endif 134#endif 135 136#if defined(PNG_gAMA_SUPPORTED) 137#ifdef PNG_FLOATING_POINT_SUPPORTED 138void PNGAPI 139png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma) 140{ 141 double tgamma; 142 png_debug1(1, "in %s storage function\n", "gAMA"); 143 if (png_ptr == NULL || info_ptr == NULL) 144 return; 145 146 /* Check for overflow */ 147 if (file_gamma > 21474.83) 148 { 149 png_warning(png_ptr, "Limiting gamma to 21474.83"); 150 tgamma=21474.83; 151 } 152 else 153 tgamma=file_gamma; 154 info_ptr->gamma = (float)tgamma; 155#ifdef PNG_FIXED_POINT_SUPPORTED 156 info_ptr->int_gamma = (int)(tgamma*100000.+.5); 157#endif 158 info_ptr->valid |= PNG_INFO_gAMA; 159 if(tgamma == 0.0) 160 png_warning(png_ptr, "Setting gamma=0"); 161} 162#endif 163void PNGAPI 164png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point 165 int_gamma) 166{ 167 png_fixed_point tgamma; 168 169 png_debug1(1, "in %s storage function\n", "gAMA"); 170 if (png_ptr == NULL || info_ptr == NULL) 171 return; 172 173 if (int_gamma > (png_fixed_point) PNG_MAX_UINT) 174 { 175 png_warning(png_ptr, "Limiting gamma to 21474.83"); 176 tgamma=PNG_MAX_UINT; 177 } 178 else 179 { 180 if (int_gamma < 0) 181 { 182 png_warning(png_ptr, "Setting negative gamma to zero"); 183 tgamma=0; 184 } 185 else 186 tgamma=int_gamma; 187 } 188#ifdef PNG_FLOATING_POINT_SUPPORTED 189 info_ptr->gamma = (float)(tgamma/100000.); 190#endif 191#ifdef PNG_FIXED_POINT_SUPPORTED 192 info_ptr->int_gamma = tgamma; 193#endif 194 info_ptr->valid |= PNG_INFO_gAMA; 195 if(tgamma == 0) 196 png_warning(png_ptr, "Setting gamma=0"); 197} 198#endif 199 200#if defined(PNG_hIST_SUPPORTED) 201void PNGAPI 202png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p hist) 203{ 204 int i; 205 206 png_debug1(1, "in %s storage function\n", "hIST"); 207 if (png_ptr == NULL || info_ptr == NULL) 208 return; 209 if (info_ptr->num_palette == 0) 210 { 211 png_warning(png_ptr, 212 "Palette size 0, hIST allocation skipped."); 213 return; 214 } 215 216#ifdef PNG_FREE_ME_SUPPORTED 217 png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0); 218#endif 219 /* Changed from info->num_palette to 256 in version 1.2.1 */ 220 png_ptr->hist = (png_uint_16p)png_malloc_warn(png_ptr, 221 (png_uint_32)(256 * sizeof (png_uint_16))); 222 if (png_ptr->hist == NULL) 223 { 224 png_warning(png_ptr, "Insufficient memory for hIST chunk data."); 225 return; 226 } 227 228 for (i = 0; i < info_ptr->num_palette; i++) 229 png_ptr->hist[i] = hist[i]; 230 info_ptr->hist = png_ptr->hist; 231 info_ptr->valid |= PNG_INFO_hIST; 232 233#ifdef PNG_FREE_ME_SUPPORTED 234 info_ptr->free_me |= PNG_FREE_HIST; 235#else 236 png_ptr->flags |= PNG_FLAG_FREE_HIST; 237#endif 238} 239#endif 240 241void PNGAPI 242png_set_IHDR(png_structp png_ptr, png_infop info_ptr, 243 png_uint_32 width, png_uint_32 height, int bit_depth, 244 int color_type, int interlace_type, int compression_type, 245 int filter_type) 246{ 247 int rowbytes_per_pixel; 248 png_debug1(1, "in %s storage function\n", "IHDR"); 249 if (png_ptr == NULL || info_ptr == NULL) 250 return; 251 252 /* check for width and height valid values */ 253 if (width == 0 || height == 0) 254 png_error(png_ptr, "Image width or height is zero in IHDR"); 255 if (width > PNG_MAX_UINT || height > PNG_MAX_UINT) 256 png_error(png_ptr, "Invalid image size in IHDR"); 257 258 /* check other values */ 259 if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 && 260 bit_depth != 8 && bit_depth != 16) 261 png_error(png_ptr, "Invalid bit depth in IHDR"); 262 263 if (color_type < 0 || color_type == 1 || 264 color_type == 5 || color_type > 6) 265 png_error(png_ptr, "Invalid color type in IHDR"); 266 267 if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) || 268 ((color_type == PNG_COLOR_TYPE_RGB || 269 color_type == PNG_COLOR_TYPE_GRAY_ALPHA || 270 color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8)) 271 png_error(png_ptr, "Invalid color type/bit depth combination in IHDR"); 272 273 if (interlace_type >= PNG_INTERLACE_LAST) 274 png_error(png_ptr, "Unknown interlace method in IHDR"); 275 276 if (compression_type != PNG_COMPRESSION_TYPE_BASE) 277 png_error(png_ptr, "Unknown compression method in IHDR"); 278 279#if defined(PNG_MNG_FEATURES_SUPPORTED) 280 /* Accept filter_method 64 (intrapixel differencing) only if 281 * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and 282 * 2. Libpng did not read a PNG signature (this filter_method is only 283 * used in PNG datastreams that are embedded in MNG datastreams) and 284 * 3. The application called png_permit_mng_features with a mask that 285 * included PNG_FLAG_MNG_FILTER_64 and 286 * 4. The filter_method is 64 and 287 * 5. The color_type is RGB or RGBA 288 */ 289 if((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&png_ptr->mng_features_permitted) 290 png_warning(png_ptr,"MNG features are not allowed in a PNG datastream\n"); 291 if(filter_type != PNG_FILTER_TYPE_BASE) 292 { 293 if(!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && 294 (filter_type == PNG_INTRAPIXEL_DIFFERENCING) && 295 ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) && 296 (color_type == PNG_COLOR_TYPE_RGB || 297 color_type == PNG_COLOR_TYPE_RGB_ALPHA))) 298 png_error(png_ptr, "Unknown filter method in IHDR"); 299 if(png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) 300 png_warning(png_ptr, "Invalid filter method in IHDR"); 301 } 302#else 303 if(filter_type != PNG_FILTER_TYPE_BASE) 304 png_error(png_ptr, "Unknown filter method in IHDR"); 305#endif 306 307 info_ptr->width = width; 308 info_ptr->height = height; 309 info_ptr->bit_depth = (png_byte)bit_depth; 310 info_ptr->color_type =(png_byte) color_type; 311 info_ptr->compression_type = (png_byte)compression_type; 312 info_ptr->filter_type = (png_byte)filter_type; 313 info_ptr->interlace_type = (png_byte)interlace_type; 314 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 315 info_ptr->channels = 1; 316 else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) 317 info_ptr->channels = 3; 318 else 319 info_ptr->channels = 1; 320 if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) 321 info_ptr->channels++; 322 info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth); 323 324 /* check for overflow */ 325 rowbytes_per_pixel = (info_ptr->pixel_depth + 7) >> 3; 326 if ( width > PNG_MAX_UINT/rowbytes_per_pixel - 64) 327 { 328 png_warning(png_ptr, 329 "Width too large to process image data; rowbytes will overflow."); 330 info_ptr->rowbytes = (png_size_t)0; 331 } 332 else 333 info_ptr->rowbytes = (info_ptr->width * info_ptr->pixel_depth + 7) >> 3; 334} 335 336#if defined(PNG_oFFs_SUPPORTED) 337void PNGAPI 338png_set_oFFs(png_structp png_ptr, png_infop info_ptr, 339 png_int_32 offset_x, png_int_32 offset_y, int unit_type) 340{ 341 png_debug1(1, "in %s storage function\n", "oFFs"); 342 if (png_ptr == NULL || info_ptr == NULL) 343 return; 344 345 info_ptr->x_offset = offset_x; 346 info_ptr->y_offset = offset_y; 347 info_ptr->offset_unit_type = (png_byte)unit_type; 348 info_ptr->valid |= PNG_INFO_oFFs; 349} 350#endif 351 352#if defined(PNG_pCAL_SUPPORTED) 353void PNGAPI 354png_set_pCAL(png_structp png_ptr, png_infop info_ptr, 355 png_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams, 356 png_charp units, png_charpp params) 357{ 358 png_uint_32 length; 359 int i; 360 361 png_debug1(1, "in %s storage function\n", "pCAL"); 362 if (png_ptr == NULL || info_ptr == NULL) 363 return; 364 365 length = png_strlen(purpose) + 1; 366 png_debug1(3, "allocating purpose for info (%lu bytes)\n", length); 367 info_ptr->pcal_purpose = (png_charp)png_malloc_warn(png_ptr, length); 368 if (info_ptr->pcal_purpose == NULL) 369 { 370 png_warning(png_ptr, "Insufficient memory for pCAL purpose."); 371 return; 372 } 373 png_memcpy(info_ptr->pcal_purpose, purpose, (png_size_t)length); 374 375 png_debug(3, "storing X0, X1, type, and nparams in info\n"); 376 info_ptr->pcal_X0 = X0; 377 info_ptr->pcal_X1 = X1; 378 info_ptr->pcal_type = (png_byte)type; 379 info_ptr->pcal_nparams = (png_byte)nparams; 380 381 length = png_strlen(units) + 1; 382 png_debug1(3, "allocating units for info (%lu bytes)\n", length); 383 info_ptr->pcal_units = (png_charp)png_malloc_warn(png_ptr, length); 384 if (info_ptr->pcal_units == NULL) 385 { 386 png_warning(png_ptr, "Insufficient memory for pCAL units."); 387 return; 388 } 389 png_memcpy(info_ptr->pcal_units, units, (png_size_t)length); 390 391 info_ptr->pcal_params = (png_charpp)png_malloc_warn(png_ptr, 392 (png_uint_32)((nparams + 1) * sizeof(png_charp))); 393 if (info_ptr->pcal_params == NULL) 394 { 395 png_warning(png_ptr, "Insufficient memory for pCAL params."); 396 return; 397 } 398 399 info_ptr->pcal_params[nparams] = NULL; 400 401 for (i = 0; i < nparams; i++) 402 { 403 length = png_strlen(params[i]) + 1; 404 png_debug2(3,"allocating parameter %d for info (%lu bytes)\n", i, length); 405 info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length); 406 if (info_ptr->pcal_params[i] == NULL) 407 { 408 png_warning(png_ptr, "Insufficient memory for pCAL parameter."); 409 return; 410 } 411 png_memcpy(info_ptr->pcal_params[i], params[i], (png_size_t)length); 412 } 413 414 info_ptr->valid |= PNG_INFO_pCAL; 415#ifdef PNG_FREE_ME_SUPPORTED 416 info_ptr->free_me |= PNG_FREE_PCAL; 417#endif 418} 419#endif 420 421#if defined(PNG_READ_sCAL_SUPPORTED) || defined(PNG_WRITE_sCAL_SUPPORTED) 422#ifdef PNG_FLOATING_POINT_SUPPORTED 423void PNGAPI 424png_set_sCAL(png_structp png_ptr, png_infop info_ptr, 425 int unit, double width, double height) 426{ 427 png_debug1(1, "in %s storage function\n", "sCAL"); 428 if (png_ptr == NULL || info_ptr == NULL) 429 return; 430 431 info_ptr->scal_unit = (png_byte)unit; 432 info_ptr->scal_pixel_width = width; 433 info_ptr->scal_pixel_height = height; 434 435 info_ptr->valid |= PNG_INFO_sCAL; 436} 437#else 438#ifdef PNG_FIXED_POINT_SUPPORTED 439void PNGAPI 440png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr, 441 int unit, png_charp swidth, png_charp sheight) 442{ 443 png_uint_32 length; 444 445 png_debug1(1, "in %s storage function\n", "sCAL"); 446 if (png_ptr == NULL || info_ptr == NULL) 447 return; 448 449 info_ptr->scal_unit = (png_byte)unit; 450 451 length = png_strlen(swidth) + 1; 452 png_debug1(3, "allocating unit for info (%d bytes)\n", length); 453 info_ptr->scal_s_width = (png_charp)png_malloc(png_ptr, length); 454 png_memcpy(info_ptr->scal_s_width, swidth, (png_size_t)length); 455 456 length = png_strlen(sheight) + 1; 457 png_debug1(3, "allocating unit for info (%d bytes)\n", length); 458 info_ptr->scal_s_height = (png_charp)png_malloc(png_ptr, length); 459 png_memcpy(info_ptr->scal_s_height, sheight, (png_size_t)length); 460 461 info_ptr->valid |= PNG_INFO_sCAL; 462#ifdef PNG_FREE_ME_SUPPORTED 463 info_ptr->free_me |= PNG_FREE_SCAL; 464#endif 465} 466#endif 467#endif 468#endif 469 470#if defined(PNG_pHYs_SUPPORTED) 471void PNGAPI 472png_set_pHYs(png_structp png_ptr, png_infop info_ptr, 473 png_uint_32 res_x, png_uint_32 res_y, int unit_type) 474{ 475 png_debug1(1, "in %s storage function\n", "pHYs"); 476 if (png_ptr == NULL || info_ptr == NULL) 477 return; 478 479 info_ptr->x_pixels_per_unit = res_x; 480 info_ptr->y_pixels_per_unit = res_y; 481 info_ptr->phys_unit_type = (png_byte)unit_type; 482 info_ptr->valid |= PNG_INFO_pHYs; 483} 484#endif 485 486void PNGAPI 487png_set_PLTE(png_structp png_ptr, png_infop info_ptr, 488 png_colorp palette, int num_palette) 489{ 490 491 png_debug1(1, "in %s storage function\n", "PLTE"); 492 if (png_ptr == NULL || info_ptr == NULL) 493 return; 494 495 /* 496 * It may not actually be necessary to set png_ptr->palette here; 497 * we do it for backward compatibility with the way the png_handle_tRNS 498 * function used to do the allocation. 499 */ 500#ifdef PNG_FREE_ME_SUPPORTED 501 png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0); 502#endif 503 /* Changed in libpng-1.2.1 to allocate 256 instead of num_palette entries, 504 in case of an invalid PNG file that has too-large sample values. */ 505 png_ptr->palette = (png_colorp)png_zalloc(png_ptr, (uInt)256, 506 sizeof (png_color)); 507 if (png_ptr->palette == NULL) 508 png_error(png_ptr, "Unable to malloc palette"); 509 png_memcpy(png_ptr->palette, palette, num_palette * sizeof (png_color)); 510 info_ptr->palette = png_ptr->palette; 511 info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette; 512 513#ifdef PNG_FREE_ME_SUPPORTED 514 info_ptr->free_me |= PNG_FREE_PLTE; 515#else 516 png_ptr->flags |= PNG_FLAG_FREE_PLTE; 517#endif 518 519 info_ptr->valid |= PNG_INFO_PLTE; 520} 521 522#if defined(PNG_sBIT_SUPPORTED) 523void PNGAPI 524png_set_sBIT(png_structp png_ptr, png_infop info_ptr, 525 png_color_8p sig_bit) 526{ 527 png_debug1(1, "in %s storage function\n", "sBIT"); 528 if (png_ptr == NULL || info_ptr == NULL) 529 return; 530 531 png_memcpy(&(info_ptr->sig_bit), sig_bit, sizeof (png_color_8)); 532 info_ptr->valid |= PNG_INFO_sBIT; 533} 534#endif 535 536#if defined(PNG_sRGB_SUPPORTED) 537void PNGAPI 538png_set_sRGB(png_structp png_ptr, png_infop info_ptr, int intent) 539{ 540 png_debug1(1, "in %s storage function\n", "sRGB"); 541 if (png_ptr == NULL || info_ptr == NULL) 542 return; 543 544 info_ptr->srgb_intent = (png_byte)intent; 545 info_ptr->valid |= PNG_INFO_sRGB; 546} 547 548void PNGAPI 549png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr, 550 int intent) 551{ 552#if defined(PNG_gAMA_SUPPORTED) 553#ifdef PNG_FLOATING_POINT_SUPPORTED 554 float file_gamma; 555#endif 556#ifdef PNG_FIXED_POINT_SUPPORTED 557 png_fixed_point int_file_gamma; 558#endif 559#endif 560#if defined(PNG_cHRM_SUPPORTED) 561#ifdef PNG_FLOATING_POINT_SUPPORTED 562 float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y; 563#endif 564#ifdef PNG_FIXED_POINT_SUPPORTED 565 png_fixed_point int_white_x, int_white_y, int_red_x, int_red_y, int_green_x, 566 int_green_y, int_blue_x, int_blue_y; 567#endif 568#endif 569 png_debug1(1, "in %s storage function\n", "sRGB_gAMA_and_cHRM"); 570 if (png_ptr == NULL || info_ptr == NULL) 571 return; 572 573 png_set_sRGB(png_ptr, info_ptr, intent); 574 575#if defined(PNG_gAMA_SUPPORTED) 576#ifdef PNG_FLOATING_POINT_SUPPORTED 577 file_gamma = (float).45455; 578 png_set_gAMA(png_ptr, info_ptr, file_gamma); 579#endif 580#ifdef PNG_FIXED_POINT_SUPPORTED 581 int_file_gamma = 45455L; 582 png_set_gAMA_fixed(png_ptr, info_ptr, int_file_gamma); 583#endif 584#endif 585 586#if defined(PNG_cHRM_SUPPORTED) 587#ifdef PNG_FIXED_POINT_SUPPORTED 588 int_white_x = 31270L; 589 int_white_y = 32900L; 590 int_red_x = 64000L; 591 int_red_y = 33000L; 592 int_green_x = 30000L; 593 int_green_y = 60000L; 594 int_blue_x = 15000L; 595 int_blue_y = 6000L; 596 597 png_set_cHRM_fixed(png_ptr, info_ptr, 598 int_white_x, int_white_y, int_red_x, int_red_y, int_green_x, int_green_y, 599 int_blue_x, int_blue_y); 600#endif 601#ifdef PNG_FLOATING_POINT_SUPPORTED 602 white_x = (float).3127; 603 white_y = (float).3290; 604 red_x = (float).64; 605 red_y = (float).33; 606 green_x = (float).30; 607 green_y = (float).60; 608 blue_x = (float).15; 609 blue_y = (float).06; 610 611 png_set_cHRM(png_ptr, info_ptr, 612 white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y); 613#endif 614#endif 615} 616#endif 617 618 619#if defined(PNG_iCCP_SUPPORTED) 620void PNGAPI 621png_set_iCCP(png_structp png_ptr, png_infop info_ptr, 622 png_charp name, int compression_type, 623 png_charp profile, png_uint_32 proflen) 624{ 625 png_charp new_iccp_name; 626 png_charp new_iccp_profile; 627 628 png_debug1(1, "in %s storage function\n", "iCCP"); 629 if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL) 630 return; 631 632 new_iccp_name = (png_charp)png_malloc(png_ptr, png_strlen(name)+1); 633 png_strcpy(new_iccp_name, name); 634 new_iccp_profile = (png_charp)png_malloc(png_ptr, proflen); 635 png_memcpy(new_iccp_profile, profile, (png_size_t)proflen); 636 637 png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0); 638 639 info_ptr->iccp_proflen = proflen; 640 info_ptr->iccp_name = new_iccp_name; 641 info_ptr->iccp_profile = new_iccp_profile; 642 /* Compression is always zero but is here so the API and info structure 643 * does not have to change if we introduce multiple compression types */ 644 info_ptr->iccp_compression = (png_byte)compression_type; 645#ifdef PNG_FREE_ME_SUPPORTED 646 info_ptr->free_me |= PNG_FREE_ICCP; 647#endif 648 info_ptr->valid |= PNG_INFO_iCCP; 649} 650#endif 651 652#if defined(PNG_TEXT_SUPPORTED) 653void PNGAPI 654png_set_text(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr, 655 int num_text) 656{ 657 int ret; 658 ret=png_set_text_2(png_ptr, info_ptr, text_ptr, num_text); 659 if (ret) 660 png_error(png_ptr, "Insufficient memory to store text"); 661} 662 663int /* PRIVATE */ 664png_set_text_2(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr, 665 int num_text) 666{ 667 int i; 668 669 png_debug1(1, "in %s storage function\n", (png_ptr->chunk_name[0] == '\0' ? 670 "text" : (png_const_charp)png_ptr->chunk_name)); 671 672 if (png_ptr == NULL || info_ptr == NULL || num_text == 0) 673 return(0); 674 675 /* Make sure we have enough space in the "text" array in info_struct 676 * to hold all of the incoming text_ptr objects. 677 */ 678 if (info_ptr->num_text + num_text > info_ptr->max_text) 679 { 680 if (info_ptr->text != NULL) 681 { 682 png_textp old_text; 683 int old_max; 684 685 old_max = info_ptr->max_text; 686 info_ptr->max_text = info_ptr->num_text + num_text + 8; 687 old_text = info_ptr->text; 688 info_ptr->text = (png_textp)png_malloc_warn(png_ptr, 689 (png_uint_32)(info_ptr->max_text * sizeof (png_text))); 690 if (info_ptr->text == NULL) 691 { 692 png_free(png_ptr, old_text); 693 return(1); 694 } 695 png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max * 696 sizeof(png_text))); 697 png_free(png_ptr, old_text); 698 } 699 else 700 { 701 info_ptr->max_text = num_text + 8; 702 info_ptr->num_text = 0; 703 info_ptr->text = (png_textp)png_malloc_warn(png_ptr, 704 (png_uint_32)(info_ptr->max_text * sizeof (png_text))); 705 if (info_ptr->text == NULL) 706 return(1); 707#ifdef PNG_FREE_ME_SUPPORTED 708 info_ptr->free_me |= PNG_FREE_TEXT; 709#endif 710 } 711 png_debug1(3, "allocated %d entries for info_ptr->text\n", 712 info_ptr->max_text); 713 } 714 for (i = 0; i < num_text; i++) 715 { 716 png_size_t text_length,key_len; 717 png_size_t lang_len,lang_key_len; 718 png_textp textp = &(info_ptr->text[info_ptr->num_text]); 719 720 if (text_ptr[i].key == NULL) 721 continue; 722 723 key_len = png_strlen(text_ptr[i].key); 724 725 if(text_ptr[i].compression <= 0) 726 { 727 lang_len = 0; 728 lang_key_len = 0; 729 } 730 else 731#ifdef PNG_iTXt_SUPPORTED 732 { 733 /* set iTXt data */ 734 if (text_ptr[i].lang != NULL) 735 lang_len = png_strlen(text_ptr[i].lang); 736 else 737 lang_len = 0; 738 if (text_ptr[i].lang_key != NULL) 739 lang_key_len = png_strlen(text_ptr[i].lang_key); 740 else 741 lang_key_len = 0; 742 } 743#else 744 { 745 png_warning(png_ptr, "iTXt chunk not supported."); 746 continue; 747 } 748#endif 749 750 if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0') 751 { 752 text_length = 0; 753#ifdef PNG_iTXt_SUPPORTED 754 if(text_ptr[i].compression > 0) 755 textp->compression = PNG_ITXT_COMPRESSION_NONE; 756 else 757#endif 758 textp->compression = PNG_TEXT_COMPRESSION_NONE; 759 } 760 else 761 { 762 text_length = png_strlen(text_ptr[i].text); 763 textp->compression = text_ptr[i].compression; 764 } 765 766 textp->key = (png_charp)png_malloc_warn(png_ptr, 767 (png_uint_32)(key_len + text_length + lang_len + lang_key_len + 4)); 768 if (textp->key == NULL) 769 return(1); 770 png_debug2(2, "Allocated %lu bytes at %x in png_set_text\n", 771 (png_uint_32)(key_len + lang_len + lang_key_len + text_length + 4), 772 (int)textp->key); 773 774 png_memcpy(textp->key, text_ptr[i].key, 775 (png_size_t)(key_len)); 776 *(textp->key+key_len) = '\0'; 777#ifdef PNG_iTXt_SUPPORTED 778 if (text_ptr[i].compression > 0) 779 { 780 textp->lang=textp->key + key_len + 1; 781 png_memcpy(textp->lang, text_ptr[i].lang, lang_len); 782 *(textp->lang+lang_len) = '\0'; 783 textp->lang_key=textp->lang + lang_len + 1; 784 png_memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len); 785 *(textp->lang_key+lang_key_len) = '\0'; 786 textp->text=textp->lang_key + lang_key_len + 1; 787 } 788 else 789#endif 790 { 791#ifdef PNG_iTXt_SUPPORTED 792 textp->lang=NULL; 793 textp->lang_key=NULL; 794#endif 795 textp->text=textp->key + key_len + 1; 796 } 797 if(text_length) 798 png_memcpy(textp->text, text_ptr[i].text, 799 (png_size_t)(text_length)); 800 *(textp->text+text_length) = '\0'; 801 802#ifdef PNG_iTXt_SUPPORTED 803 if(textp->compression > 0) 804 { 805 textp->text_length = 0; 806 textp->itxt_length = text_length; 807 } 808 else 809#endif 810 { 811 textp->text_length = text_length; 812#ifdef PNG_iTXt_SUPPORTED 813 textp->itxt_length = 0; 814#endif 815 } 816 info_ptr->text[info_ptr->num_text]= *textp; 817 info_ptr->num_text++; 818 png_debug1(3, "transferred text chunk %d\n", info_ptr->num_text); 819 } 820 return(0); 821} 822#endif 823 824#if defined(PNG_tIME_SUPPORTED) 825void PNGAPI 826png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_timep mod_time) 827{ 828 png_debug1(1, "in %s storage function\n", "tIME"); 829 if (png_ptr == NULL || info_ptr == NULL || 830 (png_ptr->mode & PNG_WROTE_tIME)) 831 return; 832 833 png_memcpy(&(info_ptr->mod_time), mod_time, sizeof (png_time)); 834 info_ptr->valid |= PNG_INFO_tIME; 835} 836#endif 837 838#if defined(PNG_tRNS_SUPPORTED) 839void PNGAPI 840png_set_tRNS(png_structp png_ptr, png_infop info_ptr, 841 png_bytep trans, int num_trans, png_color_16p trans_values) 842{ 843 png_debug1(1, "in %s storage function\n", "tRNS"); 844 if (png_ptr == NULL || info_ptr == NULL) 845 return; 846 847 if (trans != NULL) 848 { 849 /* 850 * It may not actually be necessary to set png_ptr->trans here; 851 * we do it for backward compatibility with the way the png_handle_tRNS 852 * function used to do the allocation. 853 */ 854#ifdef PNG_FREE_ME_SUPPORTED 855 png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0); 856#endif 857 /* Changed from num_trans to 256 in version 1.2.1 */ 858 png_ptr->trans = info_ptr->trans = (png_bytep)png_malloc(png_ptr, 859 (png_uint_32)256); 860 png_memcpy(info_ptr->trans, trans, (png_size_t)num_trans); 861#ifdef PNG_FREE_ME_SUPPORTED 862 info_ptr->free_me |= PNG_FREE_TRNS; 863#else 864 png_ptr->flags |= PNG_FLAG_FREE_TRNS; 865#endif 866 } 867 868 if (trans_values != NULL) 869 { 870 png_memcpy(&(info_ptr->trans_values), trans_values, 871 sizeof(png_color_16)); 872 if (num_trans == 0) 873 num_trans = 1; 874 } 875 info_ptr->num_trans = (png_uint_16)num_trans; 876 info_ptr->valid |= PNG_INFO_tRNS; 877} 878#endif 879 880#if defined(PNG_sPLT_SUPPORTED) 881void PNGAPI 882png_set_sPLT(png_structp png_ptr, 883 png_infop info_ptr, png_sPLT_tp entries, int nentries) 884{ 885 png_sPLT_tp np; 886 int i; 887 888 np = (png_sPLT_tp)png_malloc_warn(png_ptr, 889 (info_ptr->splt_palettes_num + nentries) * sizeof(png_sPLT_t)); 890 if (np == NULL) 891 { 892 png_warning(png_ptr, "No memory for sPLT palettes."); 893 return; 894 } 895 896 png_memcpy(np, info_ptr->splt_palettes, 897 info_ptr->splt_palettes_num * sizeof(png_sPLT_t)); 898 png_free(png_ptr, info_ptr->splt_palettes); 899 info_ptr->splt_palettes=NULL; 900 901 for (i = 0; i < nentries; i++) 902 { 903 png_sPLT_tp to = np + info_ptr->splt_palettes_num + i; 904 png_sPLT_tp from = entries + i; 905 906 to->name = (png_charp)png_malloc(png_ptr, 907 png_strlen(from->name) + 1); 908 png_strcpy(to->name, from->name); 909 to->entries = (png_sPLT_entryp)png_malloc(png_ptr, 910 from->nentries * sizeof(png_sPLT_t)); 911 png_memcpy(to->entries, from->entries, 912 from->nentries * sizeof(png_sPLT_t)); 913 to->nentries = from->nentries; 914 to->depth = from->depth; 915 } 916 917 info_ptr->splt_palettes = np; 918 info_ptr->splt_palettes_num += nentries; 919 info_ptr->valid |= PNG_INFO_sPLT; 920#ifdef PNG_FREE_ME_SUPPORTED 921 info_ptr->free_me |= PNG_FREE_SPLT; 922#endif 923} 924#endif /* PNG_sPLT_SUPPORTED */ 925 926#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) 927void PNGAPI 928png_set_unknown_chunks(png_structp png_ptr, 929 png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns) 930{ 931 png_unknown_chunkp np; 932 int i; 933 934 if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0) 935 return; 936 937 np = (png_unknown_chunkp)png_malloc_warn(png_ptr, 938 (info_ptr->unknown_chunks_num + num_unknowns) * 939 sizeof(png_unknown_chunk)); 940 if (np == NULL) 941 { 942 png_warning(png_ptr, "Out of memory while processing unknown chunk."); 943 return; 944 } 945 946 png_memcpy(np, info_ptr->unknown_chunks, 947 info_ptr->unknown_chunks_num * sizeof(png_unknown_chunk)); 948 png_free(png_ptr, info_ptr->unknown_chunks); 949 info_ptr->unknown_chunks=NULL; 950 951 for (i = 0; i < num_unknowns; i++) 952 { 953 png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i; 954 png_unknown_chunkp from = unknowns + i; 955 956 png_strcpy((png_charp)to->name, (png_charp)from->name); 957 to->data = (png_bytep)png_malloc(png_ptr, from->size); 958 if (to->data == NULL) 959 png_warning(png_ptr,"Out of memory while processing unknown chunk."); 960 else 961 { 962 png_memcpy(to->data, from->data, from->size); 963 to->size = from->size; 964 965 /* note our location in the read or write sequence */ 966 to->location = (png_byte)(png_ptr->mode & 0xff); 967 } 968 } 969 970 info_ptr->unknown_chunks = np; 971 info_ptr->unknown_chunks_num += num_unknowns; 972#ifdef PNG_FREE_ME_SUPPORTED 973 info_ptr->free_me |= PNG_FREE_UNKN; 974#endif 975} 976void PNGAPI 977png_set_unknown_chunk_location(png_structp png_ptr, png_infop info_ptr, 978 int chunk, int location) 979{ 980 if(png_ptr != NULL && info_ptr != NULL && chunk >= 0 && chunk < 981 (int)info_ptr->unknown_chunks_num) 982 info_ptr->unknown_chunks[chunk].location = (png_byte)location; 983} 984#endif 985 986#if defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ 987 defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) 988void PNGAPI 989png_permit_empty_plte (png_structp png_ptr, int empty_plte_permitted) 990{ 991 /* This function is deprecated in favor of png_permit_mng_features() 992 and will be removed from libpng-2.0.0 */ 993 png_debug(1, "in png_permit_empty_plte, DEPRECATED.\n"); 994 if (png_ptr == NULL) 995 return; 996 png_ptr->mng_features_permitted = (png_byte) 997 ((png_ptr->mng_features_permitted & (~(PNG_FLAG_MNG_EMPTY_PLTE))) | 998 ((empty_plte_permitted & PNG_FLAG_MNG_EMPTY_PLTE))); 999} 1000#endif 1001 1002#if defined(PNG_MNG_FEATURES_SUPPORTED) 1003png_uint_32 PNGAPI 1004png_permit_mng_features (png_structp png_ptr, png_uint_32 mng_features) 1005{ 1006 png_debug(1, "in png_permit_mng_features\n"); 1007 if (png_ptr == NULL) 1008 return (png_uint_32)0; 1009 png_ptr->mng_features_permitted = 1010 (png_byte)(mng_features & PNG_ALL_MNG_FEATURES); 1011 return (png_uint_32)png_ptr->mng_features_permitted; 1012} 1013#endif 1014 1015#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) 1016void PNGAPI 1017png_set_keep_unknown_chunks(png_structp png_ptr, int keep, png_bytep 1018 chunk_list, int num_chunks) 1019{ 1020 png_bytep new_list, p; 1021 int i, old_num_chunks; 1022 if (num_chunks == 0) 1023 { 1024 if(keep == HANDLE_CHUNK_ALWAYS || keep == HANDLE_CHUNK_IF_SAFE) 1025 png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS; 1026 else 1027 png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS; 1028 1029 if(keep == HANDLE_CHUNK_ALWAYS) 1030 png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS; 1031 else 1032 png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS; 1033 return; 1034 } 1035 if (chunk_list == NULL) 1036 return; 1037 old_num_chunks=png_ptr->num_chunk_list; 1038 new_list=(png_bytep)png_malloc(png_ptr, 1039 (png_uint_32)(5*(num_chunks+old_num_chunks))); 1040 if(png_ptr->chunk_list != NULL) 1041 { 1042 png_memcpy(new_list, png_ptr->chunk_list, 1043 (png_size_t)(5*old_num_chunks)); 1044 png_free(png_ptr, png_ptr->chunk_list); 1045 png_ptr->chunk_list=NULL; 1046 } 1047 png_memcpy(new_list+5*old_num_chunks, chunk_list, 1048 (png_size_t)(5*num_chunks)); 1049 for (p=new_list+5*old_num_chunks+4, i=0; i<num_chunks; i++, p+=5) 1050 *p=(png_byte)keep; 1051 png_ptr->num_chunk_list=old_num_chunks+num_chunks; 1052 png_ptr->chunk_list=new_list; 1053#ifdef PNG_FREE_ME_SUPPORTED 1054 png_ptr->free_me |= PNG_FREE_LIST; 1055#endif 1056} 1057#endif 1058 1059#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) 1060void PNGAPI 1061png_set_read_user_chunk_fn(png_structp png_ptr, png_voidp user_chunk_ptr, 1062 png_user_chunk_ptr read_user_chunk_fn) 1063{ 1064 png_debug(1, "in png_set_read_user_chunk_fn\n"); 1065 png_ptr->read_user_chunk_fn = read_user_chunk_fn; 1066 png_ptr->user_chunk_ptr = user_chunk_ptr; 1067} 1068#endif 1069 1070#if defined(PNG_INFO_IMAGE_SUPPORTED) 1071void PNGAPI 1072png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers) 1073{ 1074 png_debug1(1, "in %s storage function\n", "rows"); 1075 1076 if (png_ptr == NULL || info_ptr == NULL) 1077 return; 1078 1079 if(info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers)) 1080 png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); 1081 info_ptr->row_pointers = row_pointers; 1082 if(row_pointers) 1083 info_ptr->valid |= PNG_INFO_IDAT; 1084} 1085#endif 1086 1087void PNGAPI 1088png_set_compression_buffer_size(png_structp png_ptr, png_uint_32 size) 1089{ 1090 if(png_ptr->zbuf) 1091 png_free(png_ptr, png_ptr->zbuf); 1092 png_ptr->zbuf_size = (png_size_t)size; 1093 png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, size); 1094 png_ptr->zstream.next_out = png_ptr->zbuf; 1095 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; 1096} 1097 1098void PNGAPI 1099png_set_invalid(png_structp png_ptr, png_infop info_ptr, int mask) 1100{ 1101 if (png_ptr && info_ptr) 1102 info_ptr->valid &= ~(mask); 1103} 1104 1105 1106#ifndef PNG_1_0_X 1107#ifdef PNG_ASSEMBLER_CODE_SUPPORTED 1108/* this function was added to libpng 1.2.0 and should always exist by default */ 1109void PNGAPI 1110png_set_asm_flags (png_structp png_ptr, png_uint_32 asm_flags) 1111{ 1112 png_uint_32 settable_asm_flags; 1113 png_uint_32 settable_mmx_flags; 1114 1115 settable_mmx_flags = 1116#ifdef PNG_HAVE_ASSEMBLER_COMBINE_ROW 1117 PNG_ASM_FLAG_MMX_READ_COMBINE_ROW | 1118#endif 1119#ifdef PNG_HAVE_ASSEMBLER_READ_INTERLACE 1120 PNG_ASM_FLAG_MMX_READ_INTERLACE | 1121#endif 1122#ifdef PNG_HAVE_ASSEMBLER_READ_FILTER_ROW 1123 PNG_ASM_FLAG_MMX_READ_FILTER_SUB | 1124 PNG_ASM_FLAG_MMX_READ_FILTER_UP | 1125 PNG_ASM_FLAG_MMX_READ_FILTER_AVG | 1126 PNG_ASM_FLAG_MMX_READ_FILTER_PAETH | 1127#endif 1128 0; 1129 1130 /* could be some non-MMX ones in the future, but not currently: */ 1131 settable_asm_flags = settable_mmx_flags; 1132 1133 if (!(png_ptr->asm_flags & PNG_ASM_FLAG_MMX_SUPPORT_COMPILED) || 1134 !(png_ptr->asm_flags & PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU)) 1135 { 1136 /* clear all MMX flags if MMX isn't supported */ 1137 settable_asm_flags &= ~settable_mmx_flags; 1138 png_ptr->asm_flags &= ~settable_mmx_flags; 1139 } 1140 1141 /* we're replacing the settable bits with those passed in by the user, 1142 * so first zero them out of the master copy, then logical-OR in the 1143 * allowed subset that was requested */ 1144 1145 png_ptr->asm_flags &= ~settable_asm_flags; /* zero them */ 1146 png_ptr->asm_flags |= (asm_flags & settable_asm_flags); /* set them */ 1147} 1148#endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */ 1149 1150#ifdef PNG_ASSEMBLER_CODE_SUPPORTED 1151/* this function was added to libpng 1.2.0 */ 1152void PNGAPI 1153png_set_mmx_thresholds (png_structp png_ptr, 1154 png_byte mmx_bitdepth_threshold, 1155 png_uint_32 mmx_rowbytes_threshold) 1156{ 1157 png_ptr->mmx_bitdepth_threshold = mmx_bitdepth_threshold; 1158 png_ptr->mmx_rowbytes_threshold = mmx_rowbytes_threshold; 1159} 1160#endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */ 1161#endif /* ?PNG_1_0_X */ 1162