1 2 /* pngwrite.c - general routines to write a PNG file 3 * 4 * Last changed in libpng 1.6.19 [November 12, 2015] 5 * Copyright (c) 1998-2002,2004,2006-2015 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 14 #include "pngpriv.h" 15 #ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED 16 # include <errno.h> 17 #endif /* SIMPLIFIED_WRITE_STDIO */ 18 19 #ifdef PNG_WRITE_SUPPORTED 20 21 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED 22 /* Write out all the unknown chunks for the current given location */ 23 static void 24 write_unknown_chunks(png_structrp png_ptr, png_const_inforp info_ptr, 25 unsigned int where) 26 { 27 if (info_ptr->unknown_chunks_num != 0) 28 { 29 png_const_unknown_chunkp up; 30 31 png_debug(5, "writing extra chunks"); 32 33 for (up = info_ptr->unknown_chunks; 34 up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; 35 ++up) 36 if ((up->location & where) != 0) 37 { 38 /* If per-chunk unknown chunk handling is enabled use it, otherwise 39 * just write the chunks the application has set. 40 */ 41 #ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED 42 int keep = png_handle_as_unknown(png_ptr, up->name); 43 44 /* NOTE: this code is radically different from the read side in the 45 * matter of handling an ancillary unknown chunk. In the read side 46 * the default behavior is to discard it, in the code below the default 47 * behavior is to write it. Critical chunks are, however, only 48 * written if explicitly listed or if the default is set to write all 49 * unknown chunks. 50 * 51 * The default handling is also slightly weird - it is not possible to 52 * stop the writing of all unsafe-to-copy chunks! 53 * 54 * TODO: REVIEW: this would seem to be a bug. 55 */ 56 if (keep != PNG_HANDLE_CHUNK_NEVER && 57 ((up->name[3] & 0x20) /* safe-to-copy overrides everything */ || 58 keep == PNG_HANDLE_CHUNK_ALWAYS || 59 (keep == PNG_HANDLE_CHUNK_AS_DEFAULT && 60 png_ptr->unknown_default == PNG_HANDLE_CHUNK_ALWAYS))) 61 #endif 62 { 63 /* TODO: review, what is wrong with a zero length unknown chunk? */ 64 if (up->size == 0) 65 png_warning(png_ptr, "Writing zero-length unknown chunk"); 66 67 png_write_chunk(png_ptr, up->name, up->data, up->size); 68 } 69 } 70 } 71 } 72 #endif /* WRITE_UNKNOWN_CHUNKS */ 73 74 /* Writes all the PNG information. This is the suggested way to use the 75 * library. If you have a new chunk to add, make a function to write it, 76 * and put it in the correct location here. If you want the chunk written 77 * after the image data, put it in png_write_end(). I strongly encourage 78 * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing 79 * the chunk, as that will keep the code from breaking if you want to just 80 * write a plain PNG file. If you have long comments, I suggest writing 81 * them in png_write_end(), and compressing them. 82 */ 83 void PNGAPI 84 png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr) 85 { 86 png_debug(1, "in png_write_info_before_PLTE"); 87 88 if (png_ptr == NULL || info_ptr == NULL) 89 return; 90 91 if ((png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE) == 0) 92 { 93 /* Write PNG signature */ 94 png_write_sig(png_ptr); 95 96 #ifdef PNG_MNG_FEATURES_SUPPORTED 97 if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) != 0 && \ 98 png_ptr->mng_features_permitted != 0) 99 { 100 png_warning(png_ptr, 101 "MNG features are not allowed in a PNG datastream"); 102 png_ptr->mng_features_permitted = 0; 103 } 104 #endif 105 106 /* Write IHDR information. */ 107 png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height, 108 info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type, 109 info_ptr->filter_type, 110 #ifdef PNG_WRITE_INTERLACING_SUPPORTED 111 info_ptr->interlace_type 112 #else 113 0 114 #endif 115 ); 116 117 /* The rest of these check to see if the valid field has the appropriate 118 * flag set, and if it does, writes the chunk. 119 * 120 * 1.6.0: COLORSPACE support controls the writing of these chunks too, and 121 * the chunks will be written if the WRITE routine is there and 122 * information * is available in the COLORSPACE. (See 123 * png_colorspace_sync_info in png.c for where the valid flags get set.) 124 * 125 * Under certain circumstances the colorspace can be invalidated without 126 * syncing the info_struct 'valid' flags; this happens if libpng detects 127 * an error and calls png_error while the color space is being set, yet 128 * the application continues writing the PNG. So check the 'invalid' 129 * flag here too. 130 */ 131 #ifdef PNG_GAMMA_SUPPORTED 132 # ifdef PNG_WRITE_gAMA_SUPPORTED 133 if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 && 134 (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_gAMA) != 0 && 135 (info_ptr->valid & PNG_INFO_gAMA) != 0) 136 png_write_gAMA_fixed(png_ptr, info_ptr->colorspace.gamma); 137 # endif 138 #endif 139 140 #ifdef PNG_COLORSPACE_SUPPORTED 141 /* Write only one of sRGB or an ICC profile. If a profile was supplied 142 * and it matches one of the known sRGB ones issue a warning. 143 */ 144 # ifdef PNG_WRITE_iCCP_SUPPORTED 145 if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 && 146 (info_ptr->valid & PNG_INFO_iCCP) != 0) 147 { 148 # ifdef PNG_WRITE_sRGB_SUPPORTED 149 if ((info_ptr->valid & PNG_INFO_sRGB) != 0) 150 png_app_warning(png_ptr, 151 "profile matches sRGB but writing iCCP instead"); 152 # endif 153 154 png_write_iCCP(png_ptr, info_ptr->iccp_name, 155 info_ptr->iccp_profile); 156 } 157 # ifdef PNG_WRITE_sRGB_SUPPORTED 158 else 159 # endif 160 # endif 161 162 # ifdef PNG_WRITE_sRGB_SUPPORTED 163 if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 && 164 (info_ptr->valid & PNG_INFO_sRGB) != 0) 165 png_write_sRGB(png_ptr, info_ptr->colorspace.rendering_intent); 166 # endif /* WRITE_sRGB */ 167 #endif /* COLORSPACE */ 168 169 #ifdef PNG_WRITE_sBIT_SUPPORTED 170 if ((info_ptr->valid & PNG_INFO_sBIT) != 0) 171 png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type); 172 #endif 173 174 #ifdef PNG_COLORSPACE_SUPPORTED 175 # ifdef PNG_WRITE_cHRM_SUPPORTED 176 if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 && 177 (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_cHRM) != 0 && 178 (info_ptr->valid & PNG_INFO_cHRM) != 0) 179 png_write_cHRM_fixed(png_ptr, &info_ptr->colorspace.end_points_xy); 180 # endif 181 #endif 182 183 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED 184 write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_IHDR); 185 #endif 186 187 png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE; 188 } 189 } 190 191 void PNGAPI 192 png_write_info(png_structrp png_ptr, png_const_inforp info_ptr) 193 { 194 #if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) 195 int i; 196 #endif 197 198 png_debug(1, "in png_write_info"); 199 200 if (png_ptr == NULL || info_ptr == NULL) 201 return; 202 203 png_write_info_before_PLTE(png_ptr, info_ptr); 204 205 if ((info_ptr->valid & PNG_INFO_PLTE) != 0) 206 png_write_PLTE(png_ptr, info_ptr->palette, 207 (png_uint_32)info_ptr->num_palette); 208 209 else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 210 png_error(png_ptr, "Valid palette required for paletted images"); 211 212 #ifdef PNG_WRITE_tRNS_SUPPORTED 213 if ((info_ptr->valid & PNG_INFO_tRNS) !=0) 214 { 215 #ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED 216 /* Invert the alpha channel (in tRNS) */ 217 if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0 && 218 info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 219 { 220 int j, jend; 221 222 jend = info_ptr->num_trans; 223 if (jend > PNG_MAX_PALETTE_LENGTH) 224 jend = PNG_MAX_PALETTE_LENGTH; 225 226 for (j = 0; j<jend; ++j) 227 info_ptr->trans_alpha[j] = 228 (png_byte)(255 - info_ptr->trans_alpha[j]); 229 } 230 #endif 231 png_write_tRNS(png_ptr, info_ptr->trans_alpha, &(info_ptr->trans_color), 232 info_ptr->num_trans, info_ptr->color_type); 233 } 234 #endif 235 #ifdef PNG_WRITE_bKGD_SUPPORTED 236 if ((info_ptr->valid & PNG_INFO_bKGD) != 0) 237 png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type); 238 #endif 239 240 #ifdef PNG_WRITE_hIST_SUPPORTED 241 if ((info_ptr->valid & PNG_INFO_hIST) != 0) 242 png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette); 243 #endif 244 245 #ifdef PNG_WRITE_oFFs_SUPPORTED 246 if ((info_ptr->valid & PNG_INFO_oFFs) != 0) 247 png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset, 248 info_ptr->offset_unit_type); 249 #endif 250 251 #ifdef PNG_WRITE_pCAL_SUPPORTED 252 if ((info_ptr->valid & PNG_INFO_pCAL) != 0) 253 png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0, 254 info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams, 255 info_ptr->pcal_units, info_ptr->pcal_params); 256 #endif 257 258 #ifdef PNG_WRITE_sCAL_SUPPORTED 259 if ((info_ptr->valid & PNG_INFO_sCAL) != 0) 260 png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit, 261 info_ptr->scal_s_width, info_ptr->scal_s_height); 262 #endif /* sCAL */ 263 264 #ifdef PNG_WRITE_pHYs_SUPPORTED 265 if ((info_ptr->valid & PNG_INFO_pHYs) != 0) 266 png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit, 267 info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type); 268 #endif /* pHYs */ 269 270 #ifdef PNG_WRITE_tIME_SUPPORTED 271 if ((info_ptr->valid & PNG_INFO_tIME) != 0) 272 { 273 png_write_tIME(png_ptr, &(info_ptr->mod_time)); 274 png_ptr->mode |= PNG_WROTE_tIME; 275 } 276 #endif /* tIME */ 277 278 #ifdef PNG_WRITE_sPLT_SUPPORTED 279 if ((info_ptr->valid & PNG_INFO_sPLT) != 0) 280 for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) 281 png_write_sPLT(png_ptr, info_ptr->splt_palettes + i); 282 #endif /* sPLT */ 283 284 #ifdef PNG_WRITE_TEXT_SUPPORTED 285 /* Check to see if we need to write text chunks */ 286 for (i = 0; i < info_ptr->num_text; i++) 287 { 288 png_debug2(2, "Writing header text chunk %d, type %d", i, 289 info_ptr->text[i].compression); 290 /* An internationalized chunk? */ 291 if (info_ptr->text[i].compression > 0) 292 { 293 #ifdef PNG_WRITE_iTXt_SUPPORTED 294 /* Write international chunk */ 295 png_write_iTXt(png_ptr, 296 info_ptr->text[i].compression, 297 info_ptr->text[i].key, 298 info_ptr->text[i].lang, 299 info_ptr->text[i].lang_key, 300 info_ptr->text[i].text); 301 /* Mark this chunk as written */ 302 if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) 303 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; 304 else 305 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; 306 #else 307 png_warning(png_ptr, "Unable to write international text"); 308 #endif 309 } 310 311 /* If we want a compressed text chunk */ 312 else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt) 313 { 314 #ifdef PNG_WRITE_zTXt_SUPPORTED 315 /* Write compressed chunk */ 316 png_write_zTXt(png_ptr, info_ptr->text[i].key, 317 info_ptr->text[i].text, info_ptr->text[i].compression); 318 /* Mark this chunk as written */ 319 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; 320 #else 321 png_warning(png_ptr, "Unable to write compressed text"); 322 #endif 323 } 324 325 else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) 326 { 327 #ifdef PNG_WRITE_tEXt_SUPPORTED 328 /* Write uncompressed chunk */ 329 png_write_tEXt(png_ptr, info_ptr->text[i].key, 330 info_ptr->text[i].text, 331 0); 332 /* Mark this chunk as written */ 333 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; 334 #else 335 /* Can't get here */ 336 png_warning(png_ptr, "Unable to write uncompressed text"); 337 #endif 338 } 339 } 340 #endif /* tEXt */ 341 342 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED 343 write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_PLTE); 344 #endif 345 } 346 347 /* Writes the end of the PNG file. If you don't want to write comments or 348 * time information, you can pass NULL for info. If you already wrote these 349 * in png_write_info(), do not write them again here. If you have long 350 * comments, I suggest writing them here, and compressing them. 351 */ 352 void PNGAPI 353 png_write_end(png_structrp png_ptr, png_inforp info_ptr) 354 { 355 png_debug(1, "in png_write_end"); 356 357 if (png_ptr == NULL) 358 return; 359 360 if ((png_ptr->mode & PNG_HAVE_IDAT) == 0) 361 png_error(png_ptr, "No IDATs written into file"); 362 363 #ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED 364 if (png_ptr->num_palette_max > png_ptr->num_palette) 365 png_benign_error(png_ptr, "Wrote palette index exceeding num_palette"); 366 #endif 367 368 /* See if user wants us to write information chunks */ 369 if (info_ptr != NULL) 370 { 371 #ifdef PNG_WRITE_TEXT_SUPPORTED 372 int i; /* local index variable */ 373 #endif 374 #ifdef PNG_WRITE_tIME_SUPPORTED 375 /* Check to see if user has supplied a time chunk */ 376 if ((info_ptr->valid & PNG_INFO_tIME) != 0 && 377 (png_ptr->mode & PNG_WROTE_tIME) == 0) 378 png_write_tIME(png_ptr, &(info_ptr->mod_time)); 379 380 #endif 381 #ifdef PNG_WRITE_TEXT_SUPPORTED 382 /* Loop through comment chunks */ 383 for (i = 0; i < info_ptr->num_text; i++) 384 { 385 png_debug2(2, "Writing trailer text chunk %d, type %d", i, 386 info_ptr->text[i].compression); 387 /* An internationalized chunk? */ 388 if (info_ptr->text[i].compression > 0) 389 { 390 #ifdef PNG_WRITE_iTXt_SUPPORTED 391 /* Write international chunk */ 392 png_write_iTXt(png_ptr, 393 info_ptr->text[i].compression, 394 info_ptr->text[i].key, 395 info_ptr->text[i].lang, 396 info_ptr->text[i].lang_key, 397 info_ptr->text[i].text); 398 /* Mark this chunk as written */ 399 if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) 400 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; 401 else 402 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; 403 #else 404 png_warning(png_ptr, "Unable to write international text"); 405 #endif 406 } 407 408 else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt) 409 { 410 #ifdef PNG_WRITE_zTXt_SUPPORTED 411 /* Write compressed chunk */ 412 png_write_zTXt(png_ptr, info_ptr->text[i].key, 413 info_ptr->text[i].text, info_ptr->text[i].compression); 414 /* Mark this chunk as written */ 415 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; 416 #else 417 png_warning(png_ptr, "Unable to write compressed text"); 418 #endif 419 } 420 421 else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) 422 { 423 #ifdef PNG_WRITE_tEXt_SUPPORTED 424 /* Write uncompressed chunk */ 425 png_write_tEXt(png_ptr, info_ptr->text[i].key, 426 info_ptr->text[i].text, 0); 427 /* Mark this chunk as written */ 428 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; 429 #else 430 png_warning(png_ptr, "Unable to write uncompressed text"); 431 #endif 432 } 433 } 434 #endif 435 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED 436 write_unknown_chunks(png_ptr, info_ptr, PNG_AFTER_IDAT); 437 #endif 438 } 439 440 png_ptr->mode |= PNG_AFTER_IDAT; 441 442 /* Write end of PNG file */ 443 png_write_IEND(png_ptr); 444 445 /* This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03, 446 * and restored again in libpng-1.2.30, may cause some applications that 447 * do not set png_ptr->output_flush_fn to crash. If your application 448 * experiences a problem, please try building libpng with 449 * PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to 450 * png-mng-implement at lists.sf.net . 451 */ 452 #ifdef PNG_WRITE_FLUSH_SUPPORTED 453 # ifdef PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED 454 png_flush(png_ptr); 455 # endif 456 #endif 457 } 458 459 #ifdef PNG_CONVERT_tIME_SUPPORTED 460 void PNGAPI 461 png_convert_from_struct_tm(png_timep ptime, PNG_CONST struct tm * ttime) 462 { 463 png_debug(1, "in png_convert_from_struct_tm"); 464 465 ptime->year = (png_uint_16)(1900 + ttime->tm_year); 466 ptime->month = (png_byte)(ttime->tm_mon + 1); 467 ptime->day = (png_byte)ttime->tm_mday; 468 ptime->hour = (png_byte)ttime->tm_hour; 469 ptime->minute = (png_byte)ttime->tm_min; 470 ptime->second = (png_byte)ttime->tm_sec; 471 } 472 473 void PNGAPI 474 png_convert_from_time_t(png_timep ptime, time_t ttime) 475 { 476 struct tm *tbuf; 477 478 png_debug(1, "in png_convert_from_time_t"); 479 480 tbuf = gmtime(&ttime); 481 png_convert_from_struct_tm(ptime, tbuf); 482 } 483 #endif 484 485 /* Initialize png_ptr structure, and allocate any memory needed */ 486 PNG_FUNCTION(png_structp,PNGAPI 487 png_create_write_struct,(png_const_charp user_png_ver, png_voidp error_ptr, 488 png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED) 489 { 490 #ifndef PNG_USER_MEM_SUPPORTED 491 png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr, 492 error_fn, warn_fn, NULL, NULL, NULL); 493 #else 494 return png_create_write_struct_2(user_png_ver, error_ptr, error_fn, 495 warn_fn, NULL, NULL, NULL); 496 } 497 498 /* Alternate initialize png_ptr structure, and allocate any memory needed */ 499 PNG_FUNCTION(png_structp,PNGAPI 500 png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, 501 png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, 502 png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED) 503 { 504 png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr, 505 error_fn, warn_fn, mem_ptr, malloc_fn, free_fn); 506 #endif /* USER_MEM */ 507 if (png_ptr != NULL) 508 { 509 /* Set the zlib control values to defaults; they can be overridden by the 510 * application after the struct has been created. 511 */ 512 png_ptr->zbuffer_size = PNG_ZBUF_SIZE; 513 514 /* The 'zlib_strategy' setting is irrelevant because png_default_claim in 515 * pngwutil.c defaults it according to whether or not filters will be 516 * used, and ignores this setting. 517 */ 518 png_ptr->zlib_strategy = PNG_Z_DEFAULT_STRATEGY; 519 png_ptr->zlib_level = PNG_Z_DEFAULT_COMPRESSION; 520 png_ptr->zlib_mem_level = 8; 521 png_ptr->zlib_window_bits = 15; 522 png_ptr->zlib_method = 8; 523 524 #ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED 525 png_ptr->zlib_text_strategy = PNG_TEXT_Z_DEFAULT_STRATEGY; 526 png_ptr->zlib_text_level = PNG_TEXT_Z_DEFAULT_COMPRESSION; 527 png_ptr->zlib_text_mem_level = 8; 528 png_ptr->zlib_text_window_bits = 15; 529 png_ptr->zlib_text_method = 8; 530 #endif /* WRITE_COMPRESSED_TEXT */ 531 532 /* This is a highly dubious configuration option; by default it is off, 533 * but it may be appropriate for private builds that are testing 534 * extensions not conformant to the current specification, or of 535 * applications that must not fail to write at all costs! 536 */ 537 #ifdef PNG_BENIGN_WRITE_ERRORS_SUPPORTED 538 /* In stable builds only warn if an application error can be completely 539 * handled. 540 */ 541 png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN; 542 #endif 543 544 /* App warnings are warnings in release (or release candidate) builds but 545 * are errors during development. 546 */ 547 #if PNG_RELEASE_BUILD 548 png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN; 549 #endif 550 551 /* TODO: delay this, it can be done in png_init_io() (if the app doesn't 552 * do it itself) avoiding setting the default function if it is not 553 * required. 554 */ 555 png_set_write_fn(png_ptr, NULL, NULL, NULL); 556 } 557 558 return png_ptr; 559 } 560 561 562 /* Write a few rows of image data. If the image is interlaced, 563 * either you will have to write the 7 sub images, or, if you 564 * have called png_set_interlace_handling(), you will have to 565 * "write" the image seven times. 566 */ 567 void PNGAPI 568 png_write_rows(png_structrp png_ptr, png_bytepp row, 569 png_uint_32 num_rows) 570 { 571 png_uint_32 i; /* row counter */ 572 png_bytepp rp; /* row pointer */ 573 574 png_debug(1, "in png_write_rows"); 575 576 if (png_ptr == NULL) 577 return; 578 579 /* Loop through the rows */ 580 for (i = 0, rp = row; i < num_rows; i++, rp++) 581 { 582 png_write_row(png_ptr, *rp); 583 } 584 } 585 586 /* Write the image. You only need to call this function once, even 587 * if you are writing an interlaced image. 588 */ 589 void PNGAPI 590 png_write_image(png_structrp png_ptr, png_bytepp image) 591 { 592 png_uint_32 i; /* row index */ 593 int pass, num_pass; /* pass variables */ 594 png_bytepp rp; /* points to current row */ 595 596 if (png_ptr == NULL) 597 return; 598 599 png_debug(1, "in png_write_image"); 600 601 #ifdef PNG_WRITE_INTERLACING_SUPPORTED 602 /* Initialize interlace handling. If image is not interlaced, 603 * this will set pass to 1 604 */ 605 num_pass = png_set_interlace_handling(png_ptr); 606 #else 607 num_pass = 1; 608 #endif 609 /* Loop through passes */ 610 for (pass = 0; pass < num_pass; pass++) 611 { 612 /* Loop through image */ 613 for (i = 0, rp = image; i < png_ptr->height; i++, rp++) 614 { 615 png_write_row(png_ptr, *rp); 616 } 617 } 618 } 619 620 #ifdef PNG_MNG_FEATURES_SUPPORTED 621 /* Performs intrapixel differencing */ 622 static void 623 png_do_write_intrapixel(png_row_infop row_info, png_bytep row) 624 { 625 png_debug(1, "in png_do_write_intrapixel"); 626 627 if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0) 628 { 629 int bytes_per_pixel; 630 png_uint_32 row_width = row_info->width; 631 if (row_info->bit_depth == 8) 632 { 633 png_bytep rp; 634 png_uint_32 i; 635 636 if (row_info->color_type == PNG_COLOR_TYPE_RGB) 637 bytes_per_pixel = 3; 638 639 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 640 bytes_per_pixel = 4; 641 642 else 643 return; 644 645 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) 646 { 647 *(rp) = (png_byte)(*rp - *(rp + 1)); 648 *(rp + 2) = (png_byte)(*(rp + 2) - *(rp + 1)); 649 } 650 } 651 652 #ifdef PNG_WRITE_16BIT_SUPPORTED 653 else if (row_info->bit_depth == 16) 654 { 655 png_bytep rp; 656 png_uint_32 i; 657 658 if (row_info->color_type == PNG_COLOR_TYPE_RGB) 659 bytes_per_pixel = 6; 660 661 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 662 bytes_per_pixel = 8; 663 664 else 665 return; 666 667 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) 668 { 669 png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1); 670 png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); 671 png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); 672 png_uint_32 red = (png_uint_32)((s0 - s1) & 0xffffL); 673 png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL); 674 *(rp ) = (png_byte)(red >> 8); 675 *(rp + 1) = (png_byte)red; 676 *(rp + 4) = (png_byte)(blue >> 8); 677 *(rp + 5) = (png_byte)blue; 678 } 679 } 680 #endif /* WRITE_16BIT */ 681 } 682 } 683 #endif /* MNG_FEATURES */ 684 685 /* Called by user to write a row of image data */ 686 void PNGAPI 687 png_write_row(png_structrp png_ptr, png_const_bytep row) 688 { 689 /* 1.5.6: moved from png_struct to be a local structure: */ 690 png_row_info row_info; 691 692 if (png_ptr == NULL) 693 return; 694 695 png_debug2(1, "in png_write_row (row %u, pass %d)", 696 png_ptr->row_number, png_ptr->pass); 697 698 /* Initialize transformations and other stuff if first time */ 699 if (png_ptr->row_number == 0 && png_ptr->pass == 0) 700 { 701 /* Make sure we wrote the header info */ 702 if ((png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE) == 0) 703 png_error(png_ptr, 704 "png_write_info was never called before png_write_row"); 705 706 /* Check for transforms that have been set but were defined out */ 707 #if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED) 708 if ((png_ptr->transformations & PNG_INVERT_MONO) != 0) 709 png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined"); 710 #endif 711 712 #if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED) 713 if ((png_ptr->transformations & PNG_FILLER) != 0) 714 png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined"); 715 #endif 716 #if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \ 717 defined(PNG_READ_PACKSWAP_SUPPORTED) 718 if ((png_ptr->transformations & PNG_PACKSWAP) != 0) 719 png_warning(png_ptr, 720 "PNG_WRITE_PACKSWAP_SUPPORTED is not defined"); 721 #endif 722 723 #if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED) 724 if ((png_ptr->transformations & PNG_PACK) != 0) 725 png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined"); 726 #endif 727 728 #if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED) 729 if ((png_ptr->transformations & PNG_SHIFT) != 0) 730 png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined"); 731 #endif 732 733 #if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED) 734 if ((png_ptr->transformations & PNG_BGR) != 0) 735 png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined"); 736 #endif 737 738 #if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED) 739 if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0) 740 png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined"); 741 #endif 742 743 png_write_start_row(png_ptr); 744 } 745 746 #ifdef PNG_WRITE_INTERLACING_SUPPORTED 747 /* If interlaced and not interested in row, return */ 748 if (png_ptr->interlaced != 0 && 749 (png_ptr->transformations & PNG_INTERLACE) != 0) 750 { 751 switch (png_ptr->pass) 752 { 753 case 0: 754 if ((png_ptr->row_number & 0x07) != 0) 755 { 756 png_write_finish_row(png_ptr); 757 return; 758 } 759 break; 760 761 case 1: 762 if ((png_ptr->row_number & 0x07) != 0 || png_ptr->width < 5) 763 { 764 png_write_finish_row(png_ptr); 765 return; 766 } 767 break; 768 769 case 2: 770 if ((png_ptr->row_number & 0x07) != 4) 771 { 772 png_write_finish_row(png_ptr); 773 return; 774 } 775 break; 776 777 case 3: 778 if ((png_ptr->row_number & 0x03) != 0 || png_ptr->width < 3) 779 { 780 png_write_finish_row(png_ptr); 781 return; 782 } 783 break; 784 785 case 4: 786 if ((png_ptr->row_number & 0x03) != 2) 787 { 788 png_write_finish_row(png_ptr); 789 return; 790 } 791 break; 792 793 case 5: 794 if ((png_ptr->row_number & 0x01) != 0 || png_ptr->width < 2) 795 { 796 png_write_finish_row(png_ptr); 797 return; 798 } 799 break; 800 801 case 6: 802 if ((png_ptr->row_number & 0x01) == 0) 803 { 804 png_write_finish_row(png_ptr); 805 return; 806 } 807 break; 808 809 default: /* error: ignore it */ 810 break; 811 } 812 } 813 #endif 814 815 /* Set up row info for transformations */ 816 row_info.color_type = png_ptr->color_type; 817 row_info.width = png_ptr->usr_width; 818 row_info.channels = png_ptr->usr_channels; 819 row_info.bit_depth = png_ptr->usr_bit_depth; 820 row_info.pixel_depth = (png_byte)(row_info.bit_depth * row_info.channels); 821 row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width); 822 823 png_debug1(3, "row_info->color_type = %d", row_info.color_type); 824 png_debug1(3, "row_info->width = %u", row_info.width); 825 png_debug1(3, "row_info->channels = %d", row_info.channels); 826 png_debug1(3, "row_info->bit_depth = %d", row_info.bit_depth); 827 png_debug1(3, "row_info->pixel_depth = %d", row_info.pixel_depth); 828 png_debug1(3, "row_info->rowbytes = %lu", (unsigned long)row_info.rowbytes); 829 830 /* Copy user's row into buffer, leaving room for filter byte. */ 831 memcpy(png_ptr->row_buf + 1, row, row_info.rowbytes); 832 833 #ifdef PNG_WRITE_INTERLACING_SUPPORTED 834 /* Handle interlacing */ 835 if (png_ptr->interlaced && png_ptr->pass < 6 && 836 (png_ptr->transformations & PNG_INTERLACE) != 0) 837 { 838 png_do_write_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass); 839 /* This should always get caught above, but still ... */ 840 if (row_info.width == 0) 841 { 842 png_write_finish_row(png_ptr); 843 return; 844 } 845 } 846 #endif 847 848 #ifdef PNG_WRITE_TRANSFORMS_SUPPORTED 849 /* Handle other transformations */ 850 if (png_ptr->transformations != 0) 851 png_do_write_transformations(png_ptr, &row_info); 852 #endif 853 854 /* At this point the row_info pixel depth must match the 'transformed' depth, 855 * which is also the output depth. 856 */ 857 if (row_info.pixel_depth != png_ptr->pixel_depth || 858 row_info.pixel_depth != png_ptr->transformed_pixel_depth) 859 png_error(png_ptr, "internal write transform logic error"); 860 861 #ifdef PNG_MNG_FEATURES_SUPPORTED 862 /* Write filter_method 64 (intrapixel differencing) only if 863 * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and 864 * 2. Libpng did not write a PNG signature (this filter_method is only 865 * used in PNG datastreams that are embedded in MNG datastreams) and 866 * 3. The application called png_permit_mng_features with a mask that 867 * included PNG_FLAG_MNG_FILTER_64 and 868 * 4. The filter_method is 64 and 869 * 5. The color_type is RGB or RGBA 870 */ 871 if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 && 872 (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) 873 { 874 /* Intrapixel differencing */ 875 png_do_write_intrapixel(&row_info, png_ptr->row_buf + 1); 876 } 877 #endif 878 879 /* Added at libpng-1.5.10 */ 880 #ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED 881 /* Check for out-of-range palette index */ 882 if (row_info.color_type == PNG_COLOR_TYPE_PALETTE && 883 png_ptr->num_palette_max >= 0) 884 png_do_check_palette_indexes(png_ptr, &row_info); 885 #endif 886 887 /* Find a filter if necessary, filter the row and write it out. */ 888 png_write_find_filter(png_ptr, &row_info); 889 890 if (png_ptr->write_row_fn != NULL) 891 (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); 892 } 893 894 #ifdef PNG_WRITE_FLUSH_SUPPORTED 895 /* Set the automatic flush interval or 0 to turn flushing off */ 896 void PNGAPI 897 png_set_flush(png_structrp png_ptr, int nrows) 898 { 899 png_debug(1, "in png_set_flush"); 900 901 if (png_ptr == NULL) 902 return; 903 904 png_ptr->flush_dist = (nrows < 0 ? 0 : nrows); 905 } 906 907 /* Flush the current output buffers now */ 908 void PNGAPI 909 png_write_flush(png_structrp png_ptr) 910 { 911 png_debug(1, "in png_write_flush"); 912 913 if (png_ptr == NULL) 914 return; 915 916 /* We have already written out all of the data */ 917 if (png_ptr->row_number >= png_ptr->num_rows) 918 return; 919 920 png_compress_IDAT(png_ptr, NULL, 0, Z_SYNC_FLUSH); 921 png_ptr->flush_rows = 0; 922 png_flush(png_ptr); 923 } 924 #endif /* WRITE_FLUSH */ 925 926 /* Free any memory used in png_ptr struct without freeing the struct itself. */ 927 static void 928 png_write_destroy(png_structrp png_ptr) 929 { 930 png_debug(1, "in png_write_destroy"); 931 932 /* Free any memory zlib uses */ 933 if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0) 934 deflateEnd(&png_ptr->zstream); 935 936 /* Free our memory. png_free checks NULL for us. */ 937 png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list); 938 png_free(png_ptr, png_ptr->row_buf); 939 png_ptr->row_buf = NULL; 940 #ifdef PNG_WRITE_FILTER_SUPPORTED 941 png_free(png_ptr, png_ptr->prev_row); 942 png_free(png_ptr, png_ptr->try_row); 943 png_free(png_ptr, png_ptr->tst_row); 944 png_ptr->prev_row = NULL; 945 png_ptr->try_row = NULL; 946 png_ptr->tst_row = NULL; 947 #endif 948 949 #ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED 950 png_free(png_ptr, png_ptr->chunk_list); 951 png_ptr->chunk_list = NULL; 952 #endif 953 954 /* The error handling and memory handling information is left intact at this 955 * point: the jmp_buf may still have to be freed. See png_destroy_png_struct 956 * for how this happens. 957 */ 958 } 959 960 /* Free all memory used by the write. 961 * In libpng 1.6.0 this API changed quietly to no longer accept a NULL value for 962 * *png_ptr_ptr. Prior to 1.6.0 it would accept such a value and it would free 963 * the passed in info_structs but it would quietly fail to free any of the data 964 * inside them. In 1.6.0 it quietly does nothing (it has to be quiet because it 965 * has no png_ptr.) 966 */ 967 void PNGAPI 968 png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr) 969 { 970 png_debug(1, "in png_destroy_write_struct"); 971 972 if (png_ptr_ptr != NULL) 973 { 974 png_structrp png_ptr = *png_ptr_ptr; 975 976 if (png_ptr != NULL) /* added in libpng 1.6.0 */ 977 { 978 png_destroy_info_struct(png_ptr, info_ptr_ptr); 979 980 *png_ptr_ptr = NULL; 981 png_write_destroy(png_ptr); 982 png_destroy_png_struct(png_ptr); 983 } 984 } 985 } 986 987 /* Allow the application to select one or more row filters to use. */ 988 void PNGAPI 989 png_set_filter(png_structrp png_ptr, int method, int filters) 990 { 991 png_debug(1, "in png_set_filter"); 992 993 if (png_ptr == NULL) 994 return; 995 996 #ifdef PNG_MNG_FEATURES_SUPPORTED 997 if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 && 998 (method == PNG_INTRAPIXEL_DIFFERENCING)) 999 method = PNG_FILTER_TYPE_BASE; 1000 1001 #endif 1002 if (method == PNG_FILTER_TYPE_BASE) 1003 { 1004 switch (filters & (PNG_ALL_FILTERS | 0x07)) 1005 { 1006 #ifdef PNG_WRITE_FILTER_SUPPORTED 1007 case 5: 1008 case 6: 1009 case 7: png_app_error(png_ptr, "Unknown row filter for method 0"); 1010 /* FALL THROUGH */ 1011 #endif /* WRITE_FILTER */ 1012 case PNG_FILTER_VALUE_NONE: 1013 png_ptr->do_filter = PNG_FILTER_NONE; break; 1014 1015 #ifdef PNG_WRITE_FILTER_SUPPORTED 1016 case PNG_FILTER_VALUE_SUB: 1017 png_ptr->do_filter = PNG_FILTER_SUB; break; 1018 1019 case PNG_FILTER_VALUE_UP: 1020 png_ptr->do_filter = PNG_FILTER_UP; break; 1021 1022 case PNG_FILTER_VALUE_AVG: 1023 png_ptr->do_filter = PNG_FILTER_AVG; break; 1024 1025 case PNG_FILTER_VALUE_PAETH: 1026 png_ptr->do_filter = PNG_FILTER_PAETH; break; 1027 1028 default: 1029 png_ptr->do_filter = (png_byte)filters; break; 1030 #else 1031 default: 1032 png_app_error(png_ptr, "Unknown row filter for method 0"); 1033 #endif /* WRITE_FILTER */ 1034 } 1035 1036 #ifdef PNG_WRITE_FILTER_SUPPORTED 1037 /* If we have allocated the row_buf, this means we have already started 1038 * with the image and we should have allocated all of the filter buffers 1039 * that have been selected. If prev_row isn't already allocated, then 1040 * it is too late to start using the filters that need it, since we 1041 * will be missing the data in the previous row. If an application 1042 * wants to start and stop using particular filters during compression, 1043 * it should start out with all of the filters, and then remove them 1044 * or add them back after the start of compression. 1045 * 1046 * NOTE: this is a nasty constraint on the code, because it means that the 1047 * prev_row buffer must be maintained even if there are currently no 1048 * 'prev_row' requiring filters active. 1049 */ 1050 if (png_ptr->row_buf != NULL) 1051 { 1052 int num_filters; 1053 png_alloc_size_t buf_size; 1054 1055 /* Repeat the checks in png_write_start_row; 1 pixel high or wide 1056 * images cannot benefit from certain filters. If this isn't done here 1057 * the check below will fire on 1 pixel high images. 1058 */ 1059 if (png_ptr->height == 1) 1060 filters &= ~(PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH); 1061 1062 if (png_ptr->width == 1) 1063 filters &= ~(PNG_FILTER_SUB|PNG_FILTER_AVG|PNG_FILTER_PAETH); 1064 1065 if ((filters & (PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH)) != 0 1066 && png_ptr->prev_row == NULL) 1067 { 1068 /* This is the error case, however it is benign - the previous row 1069 * is not available so the filter can't be used. Just warn here. 1070 */ 1071 png_app_warning(png_ptr, 1072 "png_set_filter: UP/AVG/PAETH cannot be added after start"); 1073 filters &= ~(PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH); 1074 } 1075 1076 num_filters = 0; 1077 1078 if (filters & PNG_FILTER_SUB) 1079 num_filters++; 1080 1081 if (filters & PNG_FILTER_UP) 1082 num_filters++; 1083 1084 if (filters & PNG_FILTER_AVG) 1085 num_filters++; 1086 1087 if (filters & PNG_FILTER_PAETH) 1088 num_filters++; 1089 1090 /* Allocate needed row buffers if they have not already been 1091 * allocated. 1092 */ 1093 buf_size = PNG_ROWBYTES(png_ptr->usr_channels * png_ptr->usr_bit_depth, 1094 png_ptr->width) + 1; 1095 1096 if (png_ptr->try_row == NULL) 1097 png_ptr->try_row = png_voidcast(png_bytep, 1098 png_malloc(png_ptr, buf_size)); 1099 1100 if (num_filters > 1) 1101 { 1102 if (png_ptr->tst_row == NULL) 1103 png_ptr->tst_row = png_voidcast(png_bytep, 1104 png_malloc(png_ptr, buf_size)); 1105 } 1106 } 1107 png_ptr->do_filter = (png_byte)filters; 1108 #endif 1109 } 1110 else 1111 png_error(png_ptr, "Unknown custom filter method"); 1112 } 1113 1114 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* DEPRECATED */ 1115 /* Provide floating and fixed point APIs */ 1116 #ifdef PNG_FLOATING_POINT_SUPPORTED 1117 void PNGAPI 1118 png_set_filter_heuristics(png_structrp png_ptr, int heuristic_method, 1119 int num_weights, png_const_doublep filter_weights, 1120 png_const_doublep filter_costs) 1121 { 1122 PNG_UNUSED(png_ptr) 1123 PNG_UNUSED(heuristic_method) 1124 PNG_UNUSED(num_weights) 1125 PNG_UNUSED(filter_weights) 1126 PNG_UNUSED(filter_costs) 1127 } 1128 #endif /* FLOATING_POINT */ 1129 1130 #ifdef PNG_FIXED_POINT_SUPPORTED 1131 void PNGAPI 1132 png_set_filter_heuristics_fixed(png_structrp png_ptr, int heuristic_method, 1133 int num_weights, png_const_fixed_point_p filter_weights, 1134 png_const_fixed_point_p filter_costs) 1135 { 1136 PNG_UNUSED(png_ptr) 1137 PNG_UNUSED(heuristic_method) 1138 PNG_UNUSED(num_weights) 1139 PNG_UNUSED(filter_weights) 1140 PNG_UNUSED(filter_costs) 1141 } 1142 #endif /* FIXED_POINT */ 1143 #endif /* WRITE_WEIGHTED_FILTER */ 1144 1145 #ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED 1146 void PNGAPI 1147 png_set_compression_level(png_structrp png_ptr, int level) 1148 { 1149 png_debug(1, "in png_set_compression_level"); 1150 1151 if (png_ptr == NULL) 1152 return; 1153 1154 png_ptr->zlib_level = level; 1155 } 1156 1157 void PNGAPI 1158 png_set_compression_mem_level(png_structrp png_ptr, int mem_level) 1159 { 1160 png_debug(1, "in png_set_compression_mem_level"); 1161 1162 if (png_ptr == NULL) 1163 return; 1164 1165 png_ptr->zlib_mem_level = mem_level; 1166 } 1167 1168 void PNGAPI 1169 png_set_compression_strategy(png_structrp png_ptr, int strategy) 1170 { 1171 png_debug(1, "in png_set_compression_strategy"); 1172 1173 if (png_ptr == NULL) 1174 return; 1175 1176 /* The flag setting here prevents the libpng dynamic selection of strategy. 1177 */ 1178 png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY; 1179 png_ptr->zlib_strategy = strategy; 1180 } 1181 1182 /* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a 1183 * smaller value of window_bits if it can do so safely. 1184 */ 1185 void PNGAPI 1186 png_set_compression_window_bits(png_structrp png_ptr, int window_bits) 1187 { 1188 if (png_ptr == NULL) 1189 return; 1190 1191 /* Prior to 1.6.0 this would warn but then set the window_bits value. This 1192 * meant that negative window bits values could be selected that would cause 1193 * libpng to write a non-standard PNG file with raw deflate or gzip 1194 * compressed IDAT or ancillary chunks. Such files can be read and there is 1195 * no warning on read, so this seems like a very bad idea. 1196 */ 1197 if (window_bits > 15) 1198 { 1199 png_warning(png_ptr, "Only compression windows <= 32k supported by PNG"); 1200 window_bits = 15; 1201 } 1202 1203 else if (window_bits < 8) 1204 { 1205 png_warning(png_ptr, "Only compression windows >= 256 supported by PNG"); 1206 window_bits = 8; 1207 } 1208 1209 png_ptr->zlib_window_bits = window_bits; 1210 } 1211 1212 void PNGAPI 1213 png_set_compression_method(png_structrp png_ptr, int method) 1214 { 1215 png_debug(1, "in png_set_compression_method"); 1216 1217 if (png_ptr == NULL) 1218 return; 1219 1220 /* This would produce an invalid PNG file if it worked, but it doesn't and 1221 * deflate will fault it, so it is harmless to just warn here. 1222 */ 1223 if (method != 8) 1224 png_warning(png_ptr, "Only compression method 8 is supported by PNG"); 1225 1226 png_ptr->zlib_method = method; 1227 } 1228 #endif /* WRITE_CUSTOMIZE_COMPRESSION */ 1229 1230 /* The following were added to libpng-1.5.4 */ 1231 #ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED 1232 void PNGAPI 1233 png_set_text_compression_level(png_structrp png_ptr, int level) 1234 { 1235 png_debug(1, "in png_set_text_compression_level"); 1236 1237 if (png_ptr == NULL) 1238 return; 1239 1240 png_ptr->zlib_text_level = level; 1241 } 1242 1243 void PNGAPI 1244 png_set_text_compression_mem_level(png_structrp png_ptr, int mem_level) 1245 { 1246 png_debug(1, "in png_set_text_compression_mem_level"); 1247 1248 if (png_ptr == NULL) 1249 return; 1250 1251 png_ptr->zlib_text_mem_level = mem_level; 1252 } 1253 1254 void PNGAPI 1255 png_set_text_compression_strategy(png_structrp png_ptr, int strategy) 1256 { 1257 png_debug(1, "in png_set_text_compression_strategy"); 1258 1259 if (png_ptr == NULL) 1260 return; 1261 1262 png_ptr->zlib_text_strategy = strategy; 1263 } 1264 1265 /* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a 1266 * smaller value of window_bits if it can do so safely. 1267 */ 1268 void PNGAPI 1269 png_set_text_compression_window_bits(png_structrp png_ptr, int window_bits) 1270 { 1271 if (png_ptr == NULL) 1272 return; 1273 1274 if (window_bits > 15) 1275 { 1276 png_warning(png_ptr, "Only compression windows <= 32k supported by PNG"); 1277 window_bits = 15; 1278 } 1279 1280 else if (window_bits < 8) 1281 { 1282 png_warning(png_ptr, "Only compression windows >= 256 supported by PNG"); 1283 window_bits = 8; 1284 } 1285 1286 png_ptr->zlib_text_window_bits = window_bits; 1287 } 1288 1289 void PNGAPI 1290 png_set_text_compression_method(png_structrp png_ptr, int method) 1291 { 1292 png_debug(1, "in png_set_text_compression_method"); 1293 1294 if (png_ptr == NULL) 1295 return; 1296 1297 if (method != 8) 1298 png_warning(png_ptr, "Only compression method 8 is supported by PNG"); 1299 1300 png_ptr->zlib_text_method = method; 1301 } 1302 #endif /* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */ 1303 /* end of API added to libpng-1.5.4 */ 1304 1305 void PNGAPI 1306 png_set_write_status_fn(png_structrp png_ptr, png_write_status_ptr write_row_fn) 1307 { 1308 if (png_ptr == NULL) 1309 return; 1310 1311 png_ptr->write_row_fn = write_row_fn; 1312 } 1313 1314 #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED 1315 void PNGAPI 1316 png_set_write_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr 1317 write_user_transform_fn) 1318 { 1319 png_debug(1, "in png_set_write_user_transform_fn"); 1320 1321 if (png_ptr == NULL) 1322 return; 1323 1324 png_ptr->transformations |= PNG_USER_TRANSFORM; 1325 png_ptr->write_user_transform_fn = write_user_transform_fn; 1326 } 1327 #endif 1328 1329 1330 #ifdef PNG_INFO_IMAGE_SUPPORTED 1331 void PNGAPI 1332 png_write_png(png_structrp png_ptr, png_inforp info_ptr, 1333 int transforms, voidp params) 1334 { 1335 if (png_ptr == NULL || info_ptr == NULL) 1336 return; 1337 1338 if ((info_ptr->valid & PNG_INFO_IDAT) == 0) 1339 { 1340 png_app_error(png_ptr, "no rows for png_write_image to write"); 1341 return; 1342 } 1343 1344 /* Write the file header information. */ 1345 png_write_info(png_ptr, info_ptr); 1346 1347 /* ------ these transformations don't touch the info structure ------- */ 1348 1349 /* Invert monochrome pixels */ 1350 if ((transforms & PNG_TRANSFORM_INVERT_MONO) != 0) 1351 #ifdef PNG_WRITE_INVERT_SUPPORTED 1352 png_set_invert_mono(png_ptr); 1353 #else 1354 png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_MONO not supported"); 1355 #endif 1356 1357 /* Shift the pixels up to a legal bit depth and fill in 1358 * as appropriate to correctly scale the image. 1359 */ 1360 if ((transforms & PNG_TRANSFORM_SHIFT) != 0) 1361 #ifdef PNG_WRITE_SHIFT_SUPPORTED 1362 if ((info_ptr->valid & PNG_INFO_sBIT) != 0) 1363 png_set_shift(png_ptr, &info_ptr->sig_bit); 1364 #else 1365 png_app_error(png_ptr, "PNG_TRANSFORM_SHIFT not supported"); 1366 #endif 1367 1368 /* Pack pixels into bytes */ 1369 if ((transforms & PNG_TRANSFORM_PACKING) != 0) 1370 #ifdef PNG_WRITE_PACK_SUPPORTED 1371 png_set_packing(png_ptr); 1372 #else 1373 png_app_error(png_ptr, "PNG_TRANSFORM_PACKING not supported"); 1374 #endif 1375 1376 /* Swap location of alpha bytes from ARGB to RGBA */ 1377 if ((transforms & PNG_TRANSFORM_SWAP_ALPHA) != 0) 1378 #ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED 1379 png_set_swap_alpha(png_ptr); 1380 #else 1381 png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ALPHA not supported"); 1382 #endif 1383 1384 /* Remove a filler (X) from XRGB/RGBX/AG/GA into to convert it into 1385 * RGB, note that the code expects the input color type to be G or RGB; no 1386 * alpha channel. 1387 */ 1388 if ((transforms & (PNG_TRANSFORM_STRIP_FILLER_AFTER| 1389 PNG_TRANSFORM_STRIP_FILLER_BEFORE)) != 0) 1390 { 1391 #ifdef PNG_WRITE_FILLER_SUPPORTED 1392 if ((transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER) != 0) 1393 { 1394 if ((transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) != 0) 1395 png_app_error(png_ptr, 1396 "PNG_TRANSFORM_STRIP_FILLER: BEFORE+AFTER not supported"); 1397 1398 /* Continue if ignored - this is the pre-1.6.10 behavior */ 1399 png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); 1400 } 1401 1402 else if ((transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) != 0) 1403 png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); 1404 #else 1405 png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_FILLER not supported"); 1406 #endif 1407 } 1408 1409 /* Flip BGR pixels to RGB */ 1410 if ((transforms & PNG_TRANSFORM_BGR) != 0) 1411 #ifdef PNG_WRITE_BGR_SUPPORTED 1412 png_set_bgr(png_ptr); 1413 #else 1414 png_app_error(png_ptr, "PNG_TRANSFORM_BGR not supported"); 1415 #endif 1416 1417 /* Swap bytes of 16-bit files to most significant byte first */ 1418 if ((transforms & PNG_TRANSFORM_SWAP_ENDIAN) != 0) 1419 #ifdef PNG_WRITE_SWAP_SUPPORTED 1420 png_set_swap(png_ptr); 1421 #else 1422 png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ENDIAN not supported"); 1423 #endif 1424 1425 /* Swap bits of 1-bit, 2-bit, 4-bit packed pixel formats */ 1426 if ((transforms & PNG_TRANSFORM_PACKSWAP) != 0) 1427 #ifdef PNG_WRITE_PACKSWAP_SUPPORTED 1428 png_set_packswap(png_ptr); 1429 #else 1430 png_app_error(png_ptr, "PNG_TRANSFORM_PACKSWAP not supported"); 1431 #endif 1432 1433 /* Invert the alpha channel from opacity to transparency */ 1434 if ((transforms & PNG_TRANSFORM_INVERT_ALPHA) != 0) 1435 #ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED 1436 png_set_invert_alpha(png_ptr); 1437 #else 1438 png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_ALPHA not supported"); 1439 #endif 1440 1441 /* ----------------------- end of transformations ------------------- */ 1442 1443 /* Write the bits */ 1444 png_write_image(png_ptr, info_ptr->row_pointers); 1445 1446 /* It is REQUIRED to call this to finish writing the rest of the file */ 1447 png_write_end(png_ptr, info_ptr); 1448 1449 PNG_UNUSED(params) 1450 } 1451 #endif 1452 1453 1454 #ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED 1455 /* Initialize the write structure - general purpose utility. */ 1456 static int 1457 png_image_write_init(png_imagep image) 1458 { 1459 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, image, 1460 png_safe_error, png_safe_warning); 1461 1462 if (png_ptr != NULL) 1463 { 1464 png_infop info_ptr = png_create_info_struct(png_ptr); 1465 1466 if (info_ptr != NULL) 1467 { 1468 png_controlp control = png_voidcast(png_controlp, 1469 png_malloc_warn(png_ptr, (sizeof *control))); 1470 1471 if (control != NULL) 1472 { 1473 memset(control, 0, (sizeof *control)); 1474 1475 control->png_ptr = png_ptr; 1476 control->info_ptr = info_ptr; 1477 control->for_write = 1; 1478 1479 image->opaque = control; 1480 return 1; 1481 } 1482 1483 /* Error clean up */ 1484 png_destroy_info_struct(png_ptr, &info_ptr); 1485 } 1486 1487 png_destroy_write_struct(&png_ptr, NULL); 1488 } 1489 1490 return png_image_error(image, "png_image_write_: out of memory"); 1491 } 1492 1493 /* Arguments to png_image_write_main: */ 1494 typedef struct 1495 { 1496 /* Arguments: */ 1497 png_imagep image; 1498 png_const_voidp buffer; 1499 png_int_32 row_stride; 1500 png_const_voidp colormap; 1501 int convert_to_8bit; 1502 /* Local variables: */ 1503 png_const_voidp first_row; 1504 ptrdiff_t row_bytes; 1505 png_voidp local_row; 1506 /* Byte count for memory writing */ 1507 png_bytep memory; 1508 png_alloc_size_t memory_bytes; /* not used for STDIO */ 1509 png_alloc_size_t output_bytes; /* running total */ 1510 } png_image_write_control; 1511 1512 /* Write png_uint_16 input to a 16-bit PNG; the png_ptr has already been set to 1513 * do any necessary byte swapping. The component order is defined by the 1514 * png_image format value. 1515 */ 1516 static int 1517 png_write_image_16bit(png_voidp argument) 1518 { 1519 png_image_write_control *display = png_voidcast(png_image_write_control*, 1520 argument); 1521 png_imagep image = display->image; 1522 png_structrp png_ptr = image->opaque->png_ptr; 1523 1524 png_const_uint_16p input_row = png_voidcast(png_const_uint_16p, 1525 display->first_row); 1526 png_uint_16p output_row = png_voidcast(png_uint_16p, display->local_row); 1527 png_uint_16p row_end; 1528 const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1; 1529 int aindex = 0; 1530 png_uint_32 y = image->height; 1531 1532 if ((image->format & PNG_FORMAT_FLAG_ALPHA) != 0) 1533 { 1534 # ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED 1535 if ((image->format & PNG_FORMAT_FLAG_AFIRST) != 0) 1536 { 1537 aindex = -1; 1538 ++input_row; /* To point to the first component */ 1539 ++output_row; 1540 } 1541 else 1542 aindex = channels; 1543 # else 1544 aindex = channels; 1545 # endif 1546 } 1547 1548 else 1549 png_error(png_ptr, "png_write_image: internal call error"); 1550 1551 /* Work out the output row end and count over this, note that the increment 1552 * above to 'row' means that row_end can actually be beyond the end of the 1553 * row; this is correct. 1554 */ 1555 row_end = output_row + image->width * (channels+1); 1556 1557 while (y-- > 0) 1558 { 1559 png_const_uint_16p in_ptr = input_row; 1560 png_uint_16p out_ptr = output_row; 1561 1562 while (out_ptr < row_end) 1563 { 1564 const png_uint_16 alpha = in_ptr[aindex]; 1565 png_uint_32 reciprocal = 0; 1566 int c; 1567 1568 out_ptr[aindex] = alpha; 1569 1570 /* Calculate a reciprocal. The correct calculation is simply 1571 * component/alpha*65535 << 15. (I.e. 15 bits of precision); this 1572 * allows correct rounding by adding .5 before the shift. 'reciprocal' 1573 * is only initialized when required. 1574 */ 1575 if (alpha > 0 && alpha < 65535) 1576 reciprocal = ((0xffff<<15)+(alpha>>1))/alpha; 1577 1578 c = channels; 1579 do /* always at least one channel */ 1580 { 1581 png_uint_16 component = *in_ptr++; 1582 1583 /* The following gives 65535 for an alpha of 0, which is fine, 1584 * otherwise if 0/0 is represented as some other value there is more 1585 * likely to be a discontinuity which will probably damage 1586 * compression when moving from a fully transparent area to a 1587 * nearly transparent one. (The assumption here is that opaque 1588 * areas tend not to be 0 intensity.) 1589 */ 1590 if (component >= alpha) 1591 component = 65535; 1592 1593 /* component<alpha, so component/alpha is less than one and 1594 * component*reciprocal is less than 2^31. 1595 */ 1596 else if (component > 0 && alpha < 65535) 1597 { 1598 png_uint_32 calc = component * reciprocal; 1599 calc += 16384; /* round to nearest */ 1600 component = (png_uint_16)(calc >> 15); 1601 } 1602 1603 *out_ptr++ = component; 1604 } 1605 while (--c > 0); 1606 1607 /* Skip to next component (skip the intervening alpha channel) */ 1608 ++in_ptr; 1609 ++out_ptr; 1610 } 1611 1612 png_write_row(png_ptr, png_voidcast(png_const_bytep, display->local_row)); 1613 input_row += display->row_bytes/(sizeof (png_uint_16)); 1614 } 1615 1616 return 1; 1617 } 1618 1619 /* Given 16-bit input (1 to 4 channels) write 8-bit output. If an alpha channel 1620 * is present it must be removed from the components, the components are then 1621 * written in sRGB encoding. No components are added or removed. 1622 * 1623 * Calculate an alpha reciprocal to reverse pre-multiplication. As above the 1624 * calculation can be done to 15 bits of accuracy; however, the output needs to 1625 * be scaled in the range 0..255*65535, so include that scaling here. 1626 */ 1627 # define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+(alpha>>1))/alpha) 1628 1629 static png_byte 1630 png_unpremultiply(png_uint_32 component, png_uint_32 alpha, 1631 png_uint_32 reciprocal/*from the above macro*/) 1632 { 1633 /* The following gives 1.0 for an alpha of 0, which is fine, otherwise if 0/0 1634 * is represented as some other value there is more likely to be a 1635 * discontinuity which will probably damage compression when moving from a 1636 * fully transparent area to a nearly transparent one. (The assumption here 1637 * is that opaque areas tend not to be 0 intensity.) 1638 * 1639 * There is a rounding problem here; if alpha is less than 128 it will end up 1640 * as 0 when scaled to 8 bits. To avoid introducing spurious colors into the 1641 * output change for this too. 1642 */ 1643 if (component >= alpha || alpha < 128) 1644 return 255; 1645 1646 /* component<alpha, so component/alpha is less than one and 1647 * component*reciprocal is less than 2^31. 1648 */ 1649 else if (component > 0) 1650 { 1651 /* The test is that alpha/257 (rounded) is less than 255, the first value 1652 * that becomes 255 is 65407. 1653 * NOTE: this must agree with the PNG_DIV257 macro (which must, therefore, 1654 * be exact!) [Could also test reciprocal != 0] 1655 */ 1656 if (alpha < 65407) 1657 { 1658 component *= reciprocal; 1659 component += 64; /* round to nearest */ 1660 component >>= 7; 1661 } 1662 1663 else 1664 component *= 255; 1665 1666 /* Convert the component to sRGB. */ 1667 return (png_byte)PNG_sRGB_FROM_LINEAR(component); 1668 } 1669 1670 else 1671 return 0; 1672 } 1673 1674 static int 1675 png_write_image_8bit(png_voidp argument) 1676 { 1677 png_image_write_control *display = png_voidcast(png_image_write_control*, 1678 argument); 1679 png_imagep image = display->image; 1680 png_structrp png_ptr = image->opaque->png_ptr; 1681 1682 png_const_uint_16p input_row = png_voidcast(png_const_uint_16p, 1683 display->first_row); 1684 png_bytep output_row = png_voidcast(png_bytep, display->local_row); 1685 png_uint_32 y = image->height; 1686 const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1; 1687 1688 if ((image->format & PNG_FORMAT_FLAG_ALPHA) != 0) 1689 { 1690 png_bytep row_end; 1691 int aindex; 1692 1693 # ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED 1694 if ((image->format & PNG_FORMAT_FLAG_AFIRST) != 0) 1695 { 1696 aindex = -1; 1697 ++input_row; /* To point to the first component */ 1698 ++output_row; 1699 } 1700 1701 else 1702 # endif 1703 aindex = channels; 1704 1705 /* Use row_end in place of a loop counter: */ 1706 row_end = output_row + image->width * (channels+1); 1707 1708 while (y-- > 0) 1709 { 1710 png_const_uint_16p in_ptr = input_row; 1711 png_bytep out_ptr = output_row; 1712 1713 while (out_ptr < row_end) 1714 { 1715 png_uint_16 alpha = in_ptr[aindex]; 1716 png_byte alphabyte = (png_byte)PNG_DIV257(alpha); 1717 png_uint_32 reciprocal = 0; 1718 int c; 1719 1720 /* Scale and write the alpha channel. */ 1721 out_ptr[aindex] = alphabyte; 1722 1723 if (alphabyte > 0 && alphabyte < 255) 1724 reciprocal = UNP_RECIPROCAL(alpha); 1725 1726 c = channels; 1727 do /* always at least one channel */ 1728 *out_ptr++ = png_unpremultiply(*in_ptr++, alpha, reciprocal); 1729 while (--c > 0); 1730 1731 /* Skip to next component (skip the intervening alpha channel) */ 1732 ++in_ptr; 1733 ++out_ptr; 1734 } /* while out_ptr < row_end */ 1735 1736 png_write_row(png_ptr, png_voidcast(png_const_bytep, 1737 display->local_row)); 1738 input_row += display->row_bytes/(sizeof (png_uint_16)); 1739 } /* while y */ 1740 } 1741 1742 else 1743 { 1744 /* No alpha channel, so the row_end really is the end of the row and it 1745 * is sufficient to loop over the components one by one. 1746 */ 1747 png_bytep row_end = output_row + image->width * channels; 1748 1749 while (y-- > 0) 1750 { 1751 png_const_uint_16p in_ptr = input_row; 1752 png_bytep out_ptr = output_row; 1753 1754 while (out_ptr < row_end) 1755 { 1756 png_uint_32 component = *in_ptr++; 1757 1758 component *= 255; 1759 *out_ptr++ = (png_byte)PNG_sRGB_FROM_LINEAR(component); 1760 } 1761 1762 png_write_row(png_ptr, output_row); 1763 input_row += display->row_bytes/(sizeof (png_uint_16)); 1764 } 1765 } 1766 1767 return 1; 1768 } 1769 1770 static void 1771 png_image_set_PLTE(png_image_write_control *display) 1772 { 1773 const png_imagep image = display->image; 1774 const void *cmap = display->colormap; 1775 const int entries = image->colormap_entries > 256 ? 256 : 1776 (int)image->colormap_entries; 1777 1778 /* NOTE: the caller must check for cmap != NULL and entries != 0 */ 1779 const png_uint_32 format = image->format; 1780 const int channels = PNG_IMAGE_SAMPLE_CHANNELS(format); 1781 1782 # if defined(PNG_FORMAT_BGR_SUPPORTED) &&\ 1783 defined(PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED) 1784 const int afirst = (format & PNG_FORMAT_FLAG_AFIRST) != 0 && 1785 (format & PNG_FORMAT_FLAG_ALPHA) != 0; 1786 # else 1787 # define afirst 0 1788 # endif 1789 1790 # ifdef PNG_FORMAT_BGR_SUPPORTED 1791 const int bgr = (format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0; 1792 # else 1793 # define bgr 0 1794 # endif 1795 1796 int i, num_trans; 1797 png_color palette[256]; 1798 png_byte tRNS[256]; 1799 1800 memset(tRNS, 255, (sizeof tRNS)); 1801 memset(palette, 0, (sizeof palette)); 1802 1803 for (i=num_trans=0; i<entries; ++i) 1804 { 1805 /* This gets automatically converted to sRGB with reversal of the 1806 * pre-multiplication if the color-map has an alpha channel. 1807 */ 1808 if ((format & PNG_FORMAT_FLAG_LINEAR) != 0) 1809 { 1810 png_const_uint_16p entry = png_voidcast(png_const_uint_16p, cmap); 1811 1812 entry += i * channels; 1813 1814 if ((channels & 1) != 0) /* no alpha */ 1815 { 1816 if (channels >= 3) /* RGB */ 1817 { 1818 palette[i].blue = (png_byte)PNG_sRGB_FROM_LINEAR(255 * 1819 entry[(2 ^ bgr)]); 1820 palette[i].green = (png_byte)PNG_sRGB_FROM_LINEAR(255 * 1821 entry[1]); 1822 palette[i].red = (png_byte)PNG_sRGB_FROM_LINEAR(255 * 1823 entry[bgr]); 1824 } 1825 1826 else /* Gray */ 1827 palette[i].blue = palette[i].red = palette[i].green = 1828 (png_byte)PNG_sRGB_FROM_LINEAR(255 * *entry); 1829 } 1830 1831 else /* alpha */ 1832 { 1833 png_uint_16 alpha = entry[afirst ? 0 : channels-1]; 1834 png_byte alphabyte = (png_byte)PNG_DIV257(alpha); 1835 png_uint_32 reciprocal = 0; 1836 1837 /* Calculate a reciprocal, as in the png_write_image_8bit code above 1838 * this is designed to produce a value scaled to 255*65535 when 1839 * divided by 128 (i.e. asr 7). 1840 */ 1841 if (alphabyte > 0 && alphabyte < 255) 1842 reciprocal = (((0xffff*0xff)<<7)+(alpha>>1))/alpha; 1843 1844 tRNS[i] = alphabyte; 1845 if (alphabyte < 255) 1846 num_trans = i+1; 1847 1848 if (channels >= 3) /* RGB */ 1849 { 1850 palette[i].blue = png_unpremultiply(entry[afirst + (2 ^ bgr)], 1851 alpha, reciprocal); 1852 palette[i].green = png_unpremultiply(entry[afirst + 1], alpha, 1853 reciprocal); 1854 palette[i].red = png_unpremultiply(entry[afirst + bgr], alpha, 1855 reciprocal); 1856 } 1857 1858 else /* gray */ 1859 palette[i].blue = palette[i].red = palette[i].green = 1860 png_unpremultiply(entry[afirst], alpha, reciprocal); 1861 } 1862 } 1863 1864 else /* Color-map has sRGB values */ 1865 { 1866 png_const_bytep entry = png_voidcast(png_const_bytep, cmap); 1867 1868 entry += i * channels; 1869 1870 switch (channels) 1871 { 1872 case 4: 1873 tRNS[i] = entry[afirst ? 0 : 3]; 1874 if (tRNS[i] < 255) 1875 num_trans = i+1; 1876 /* FALL THROUGH */ 1877 case 3: 1878 palette[i].blue = entry[afirst + (2 ^ bgr)]; 1879 palette[i].green = entry[afirst + 1]; 1880 palette[i].red = entry[afirst + bgr]; 1881 break; 1882 1883 case 2: 1884 tRNS[i] = entry[1 ^ afirst]; 1885 if (tRNS[i] < 255) 1886 num_trans = i+1; 1887 /* FALL THROUGH */ 1888 case 1: 1889 palette[i].blue = palette[i].red = palette[i].green = 1890 entry[afirst]; 1891 break; 1892 1893 default: 1894 break; 1895 } 1896 } 1897 } 1898 1899 # ifdef afirst 1900 # undef afirst 1901 # endif 1902 # ifdef bgr 1903 # undef bgr 1904 # endif 1905 1906 png_set_PLTE(image->opaque->png_ptr, image->opaque->info_ptr, palette, 1907 entries); 1908 1909 if (num_trans > 0) 1910 png_set_tRNS(image->opaque->png_ptr, image->opaque->info_ptr, tRNS, 1911 num_trans, NULL); 1912 1913 image->colormap_entries = entries; 1914 } 1915 1916 static int 1917 png_image_write_main(png_voidp argument) 1918 { 1919 png_image_write_control *display = png_voidcast(png_image_write_control*, 1920 argument); 1921 png_imagep image = display->image; 1922 png_structrp png_ptr = image->opaque->png_ptr; 1923 png_inforp info_ptr = image->opaque->info_ptr; 1924 png_uint_32 format = image->format; 1925 1926 /* The following four ints are actually booleans */ 1927 int colormap = (format & PNG_FORMAT_FLAG_COLORMAP); 1928 int linear = !colormap && (format & PNG_FORMAT_FLAG_LINEAR); /* input */ 1929 int alpha = !colormap && (format & PNG_FORMAT_FLAG_ALPHA); 1930 int write_16bit = linear && !colormap && (display->convert_to_8bit == 0); 1931 1932 # ifdef PNG_BENIGN_ERRORS_SUPPORTED 1933 /* Make sure we error out on any bad situation */ 1934 png_set_benign_errors(png_ptr, 0/*error*/); 1935 # endif 1936 1937 /* Default the 'row_stride' parameter if required, also check the row stride 1938 * and total image size to ensure that they are within the system limits. 1939 */ 1940 { 1941 const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format); 1942 1943 if (image->width <= 0x7FFFFFFFU/channels) /* no overflow */ 1944 { 1945 png_uint_32 check; 1946 const png_uint_32 png_row_stride = image->width * channels; 1947 1948 if (display->row_stride == 0) 1949 display->row_stride = (png_int_32)/*SAFE*/png_row_stride; 1950 1951 if (display->row_stride < 0) 1952 check = -display->row_stride; 1953 1954 else 1955 check = display->row_stride; 1956 1957 if (check >= png_row_stride) 1958 { 1959 /* Now check for overflow of the image buffer calculation; this 1960 * limits the whole image size to 32 bits for API compatibility with 1961 * the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro. 1962 */ 1963 if (image->height > 0xFFFFFFFF/png_row_stride) 1964 png_error(image->opaque->png_ptr, "memory image too large"); 1965 } 1966 1967 else 1968 png_error(image->opaque->png_ptr, "supplied row stride too small"); 1969 } 1970 1971 else 1972 png_error(image->opaque->png_ptr, "image row stride too large"); 1973 } 1974 1975 /* Set the required transforms then write the rows in the correct order. */ 1976 if ((format & PNG_FORMAT_FLAG_COLORMAP) != 0) 1977 { 1978 if (display->colormap != NULL && image->colormap_entries > 0) 1979 { 1980 png_uint_32 entries = image->colormap_entries; 1981 1982 png_set_IHDR(png_ptr, info_ptr, image->width, image->height, 1983 entries > 16 ? 8 : (entries > 4 ? 4 : (entries > 2 ? 2 : 1)), 1984 PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, 1985 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); 1986 1987 png_image_set_PLTE(display); 1988 } 1989 1990 else 1991 png_error(image->opaque->png_ptr, 1992 "no color-map for color-mapped image"); 1993 } 1994 1995 else 1996 png_set_IHDR(png_ptr, info_ptr, image->width, image->height, 1997 write_16bit ? 16 : 8, 1998 ((format & PNG_FORMAT_FLAG_COLOR) ? PNG_COLOR_MASK_COLOR : 0) + 1999 ((format & PNG_FORMAT_FLAG_ALPHA) ? PNG_COLOR_MASK_ALPHA : 0), 2000 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); 2001 2002 /* Counter-intuitively the data transformations must be called *after* 2003 * png_write_info, not before as in the read code, but the 'set' functions 2004 * must still be called before. Just set the color space information, never 2005 * write an interlaced image. 2006 */ 2007 2008 if (write_16bit != 0) 2009 { 2010 /* The gamma here is 1.0 (linear) and the cHRM chunk matches sRGB. */ 2011 png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_LINEAR); 2012 2013 if ((image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB) == 0) 2014 png_set_cHRM_fixed(png_ptr, info_ptr, 2015 /* color x y */ 2016 /* white */ 31270, 32900, 2017 /* red */ 64000, 33000, 2018 /* green */ 30000, 60000, 2019 /* blue */ 15000, 6000 2020 ); 2021 } 2022 2023 else if ((image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB) == 0) 2024 png_set_sRGB(png_ptr, info_ptr, PNG_sRGB_INTENT_PERCEPTUAL); 2025 2026 /* Else writing an 8-bit file and the *colors* aren't sRGB, but the 8-bit 2027 * space must still be gamma encoded. 2028 */ 2029 else 2030 png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE); 2031 2032 /* Write the file header. */ 2033 png_write_info(png_ptr, info_ptr); 2034 2035 /* Now set up the data transformations (*after* the header is written), 2036 * remove the handled transformations from the 'format' flags for checking. 2037 * 2038 * First check for a little endian system if writing 16-bit files. 2039 */ 2040 if (write_16bit != 0) 2041 { 2042 PNG_CONST png_uint_16 le = 0x0001; 2043 2044 if ((*(png_const_bytep) & le) != 0) 2045 png_set_swap(png_ptr); 2046 } 2047 2048 # ifdef PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED 2049 if ((format & PNG_FORMAT_FLAG_BGR) != 0) 2050 { 2051 if (colormap == 0 && (format & PNG_FORMAT_FLAG_COLOR) != 0) 2052 png_set_bgr(png_ptr); 2053 format &= ~PNG_FORMAT_FLAG_BGR; 2054 } 2055 # endif 2056 2057 # ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED 2058 if ((format & PNG_FORMAT_FLAG_AFIRST) != 0) 2059 { 2060 if (colormap == 0 && (format & PNG_FORMAT_FLAG_ALPHA) != 0) 2061 png_set_swap_alpha(png_ptr); 2062 format &= ~PNG_FORMAT_FLAG_AFIRST; 2063 } 2064 # endif 2065 2066 /* If there are 16 or fewer color-map entries we wrote a lower bit depth 2067 * above, but the application data is still byte packed. 2068 */ 2069 if (colormap != 0 && image->colormap_entries <= 16) 2070 png_set_packing(png_ptr); 2071 2072 /* That should have handled all (both) the transforms. */ 2073 if ((format & ~(png_uint_32)(PNG_FORMAT_FLAG_COLOR | PNG_FORMAT_FLAG_LINEAR | 2074 PNG_FORMAT_FLAG_ALPHA | PNG_FORMAT_FLAG_COLORMAP)) != 0) 2075 png_error(png_ptr, "png_write_image: unsupported transformation"); 2076 2077 { 2078 png_const_bytep row = png_voidcast(png_const_bytep, display->buffer); 2079 ptrdiff_t row_bytes = display->row_stride; 2080 2081 if (linear != 0) 2082 row_bytes *= (sizeof (png_uint_16)); 2083 2084 if (row_bytes < 0) 2085 row += (image->height-1) * (-row_bytes); 2086 2087 display->first_row = row; 2088 display->row_bytes = row_bytes; 2089 } 2090 2091 /* Apply 'fast' options if the flag is set. */ 2092 if ((image->flags & PNG_IMAGE_FLAG_FAST) != 0) 2093 { 2094 png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_NO_FILTERS); 2095 /* NOTE: determined by experiment using pngstest, this reflects some 2096 * balance between the time to write the image once and the time to read 2097 * it about 50 times. The speed-up in pngstest was about 10-20% of the 2098 * total (user) time on a heavily loaded system. 2099 */ 2100 # ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED 2101 png_set_compression_level(png_ptr, 3); 2102 # endif 2103 } 2104 2105 /* Check for the cases that currently require a pre-transform on the row 2106 * before it is written. This only applies when the input is 16-bit and 2107 * either there is an alpha channel or it is converted to 8-bit. 2108 */ 2109 if ((linear != 0 && alpha != 0 ) || 2110 (colormap == 0 && display->convert_to_8bit != 0)) 2111 { 2112 png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr, 2113 png_get_rowbytes(png_ptr, info_ptr))); 2114 int result; 2115 2116 display->local_row = row; 2117 if (write_16bit != 0) 2118 result = png_safe_execute(image, png_write_image_16bit, display); 2119 else 2120 result = png_safe_execute(image, png_write_image_8bit, display); 2121 display->local_row = NULL; 2122 2123 png_free(png_ptr, row); 2124 2125 /* Skip the 'write_end' on error: */ 2126 if (result == 0) 2127 return 0; 2128 } 2129 2130 /* Otherwise this is the case where the input is in a format currently 2131 * supported by the rest of the libpng write code; call it directly. 2132 */ 2133 else 2134 { 2135 png_const_bytep row = png_voidcast(png_const_bytep, display->first_row); 2136 ptrdiff_t row_bytes = display->row_bytes; 2137 png_uint_32 y = image->height; 2138 2139 while (y-- > 0) 2140 { 2141 png_write_row(png_ptr, row); 2142 row += row_bytes; 2143 } 2144 } 2145 2146 png_write_end(png_ptr, info_ptr); 2147 return 1; 2148 } 2149 2150 2151 static void (PNGCBAPI 2152 image_memory_write)(png_structp png_ptr, png_bytep/*const*/ data, 2153 png_size_t size) 2154 { 2155 png_image_write_control *display = png_voidcast(png_image_write_control*, 2156 png_ptr->io_ptr/*backdoor: png_get_io_ptr(png_ptr)*/); 2157 const png_alloc_size_t ob = display->output_bytes; 2158 2159 /* Check for overflow; this should never happen: */ 2160 if (size <= ((png_alloc_size_t)-1) - ob) 2161 { 2162 /* I don't think libpng ever does this, but just in case: */ 2163 if (size > 0) 2164 { 2165 if (display->memory_bytes >= ob+size) /* writing */ 2166 memcpy(display->memory+ob, data, size); 2167 2168 /* Always update the size: */ 2169 display->output_bytes = ob+size; 2170 } 2171 } 2172 2173 else 2174 png_error(png_ptr, "png_image_write_to_memory: PNG too big"); 2175 } 2176 2177 static void (PNGCBAPI 2178 image_memory_flush)(png_structp png_ptr) 2179 { 2180 PNG_UNUSED(png_ptr) 2181 } 2182 2183 static int 2184 png_image_write_memory(png_voidp argument) 2185 { 2186 png_image_write_control *display = png_voidcast(png_image_write_control*, 2187 argument); 2188 2189 /* The rest of the memory-specific init and write_main in an error protected 2190 * environment. This case needs to use callbacks for the write operations 2191 * since libpng has no built in support for writing to memory. 2192 */ 2193 png_set_write_fn(display->image->opaque->png_ptr, display/*io_ptr*/, 2194 image_memory_write, image_memory_flush); 2195 2196 return png_image_write_main(display); 2197 } 2198 2199 int PNGAPI 2200 png_image_write_to_memory(png_imagep image, void *memory, 2201 png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8bit, 2202 const void *buffer, png_int_32 row_stride, const void *colormap) 2203 { 2204 /* Write the image to the given buffer, or count the bytes if it is NULL */ 2205 if (image != NULL && image->version == PNG_IMAGE_VERSION) 2206 { 2207 if (memory_bytes != NULL && buffer != NULL) 2208 { 2209 /* This is to give the caller an easier error detection in the NULL 2210 * case and guard against uninitialized variable problems: 2211 */ 2212 if (memory == NULL) 2213 *memory_bytes = 0; 2214 2215 if (png_image_write_init(image) != 0) 2216 { 2217 png_image_write_control display; 2218 int result; 2219 2220 memset(&display, 0, (sizeof display)); 2221 display.image = image; 2222 display.buffer = buffer; 2223 display.row_stride = row_stride; 2224 display.colormap = colormap; 2225 display.convert_to_8bit = convert_to_8bit; 2226 display.memory = png_voidcast(png_bytep, memory); 2227 display.memory_bytes = *memory_bytes; 2228 display.output_bytes = 0; 2229 2230 result = png_safe_execute(image, png_image_write_memory, &display); 2231 png_image_free(image); 2232 2233 /* write_memory returns true even if we ran out of buffer. */ 2234 if (result) 2235 { 2236 /* On out-of-buffer this function returns '0' but still updates 2237 * memory_bytes: 2238 */ 2239 if (memory != NULL && display.output_bytes > *memory_bytes) 2240 result = 0; 2241 2242 *memory_bytes = display.output_bytes; 2243 } 2244 2245 return result; 2246 } 2247 2248 else 2249 return 0; 2250 } 2251 2252 else 2253 return png_image_error(image, 2254 "png_image_write_to_memory: invalid argument"); 2255 } 2256 2257 else if (image != NULL) 2258 return png_image_error(image, 2259 "png_image_write_to_memory: incorrect PNG_IMAGE_VERSION"); 2260 2261 else 2262 return 0; 2263 } 2264 2265 #ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED 2266 int PNGAPI 2267 png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit, 2268 const void *buffer, png_int_32 row_stride, const void *colormap) 2269 { 2270 /* Write the image to the given (FILE*). */ 2271 if (image != NULL && image->version == PNG_IMAGE_VERSION) 2272 { 2273 if (file != NULL && buffer != NULL) 2274 { 2275 if (png_image_write_init(image) != 0) 2276 { 2277 png_image_write_control display; 2278 int result; 2279 2280 /* This is slightly evil, but png_init_io doesn't do anything other 2281 * than this and we haven't changed the standard IO functions so 2282 * this saves a 'safe' function. 2283 */ 2284 image->opaque->png_ptr->io_ptr = file; 2285 2286 memset(&display, 0, (sizeof display)); 2287 display.image = image; 2288 display.buffer = buffer; 2289 display.row_stride = row_stride; 2290 display.colormap = colormap; 2291 display.convert_to_8bit = convert_to_8bit; 2292 2293 result = png_safe_execute(image, png_image_write_main, &display); 2294 png_image_free(image); 2295 return result; 2296 } 2297 2298 else 2299 return 0; 2300 } 2301 2302 else 2303 return png_image_error(image, 2304 "png_image_write_to_stdio: invalid argument"); 2305 } 2306 2307 else if (image != NULL) 2308 return png_image_error(image, 2309 "png_image_write_to_stdio: incorrect PNG_IMAGE_VERSION"); 2310 2311 else 2312 return 0; 2313 } 2314 2315 int PNGAPI 2316 png_image_write_to_file(png_imagep image, const char *file_name, 2317 int convert_to_8bit, const void *buffer, png_int_32 row_stride, 2318 const void *colormap) 2319 { 2320 /* Write the image to the named file. */ 2321 if (image != NULL && image->version == PNG_IMAGE_VERSION) 2322 { 2323 if (file_name != NULL && buffer != NULL) 2324 { 2325 FILE *fp = fopen(file_name, "wb"); 2326 2327 if (fp != NULL) 2328 { 2329 if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer, 2330 row_stride, colormap) != 0) 2331 { 2332 int error; /* from fflush/fclose */ 2333 2334 /* Make sure the file is flushed correctly. */ 2335 if (fflush(fp) == 0 && ferror(fp) == 0) 2336 { 2337 if (fclose(fp) == 0) 2338 return 1; 2339 2340 error = errno; /* from fclose */ 2341 } 2342 2343 else 2344 { 2345 error = errno; /* from fflush or ferror */ 2346 (void)fclose(fp); 2347 } 2348 2349 (void)remove(file_name); 2350 /* The image has already been cleaned up; this is just used to 2351 * set the error (because the original write succeeded). 2352 */ 2353 return png_image_error(image, strerror(error)); 2354 } 2355 2356 else 2357 { 2358 /* Clean up: just the opened file. */ 2359 (void)fclose(fp); 2360 (void)remove(file_name); 2361 return 0; 2362 } 2363 } 2364 2365 else 2366 return png_image_error(image, strerror(errno)); 2367 } 2368 2369 else 2370 return png_image_error(image, 2371 "png_image_write_to_file: invalid argument"); 2372 } 2373 2374 else if (image != NULL) 2375 return png_image_error(image, 2376 "png_image_write_to_file: incorrect PNG_IMAGE_VERSION"); 2377 2378 else 2379 return 0; 2380 } 2381 #endif /* SIMPLIFIED_WRITE_STDIO */ 2382 #endif /* SIMPLIFIED_WRITE */ 2383 #endif /* WRITE */ 2384