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