1 2/* pngwutil.c - utilities to write a PNG file 3 * 4 * Last changed in libpng 1.4.1 [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 14#define PNG_NO_PEDANTIC_WARNINGS 15#include "png.h" 16#ifdef PNG_WRITE_SUPPORTED 17#include "pngpriv.h" 18 19/* Place a 32-bit number into a buffer in PNG byte order. We work 20 * with unsigned numbers for convenience, although one supported 21 * ancillary chunk uses signed (two's complement) numbers. 22 */ 23void PNGAPI 24png_save_uint_32(png_bytep buf, png_uint_32 i) 25{ 26 buf[0] = (png_byte)((i >> 24) & 0xff); 27 buf[1] = (png_byte)((i >> 16) & 0xff); 28 buf[2] = (png_byte)((i >> 8) & 0xff); 29 buf[3] = (png_byte)(i & 0xff); 30} 31 32#ifdef PNG_SAVE_INT_32_SUPPORTED 33/* The png_save_int_32 function assumes integers are stored in two's 34 * complement format. If this isn't the case, then this routine needs to 35 * be modified to write data in two's complement format. 36 */ 37void PNGAPI 38png_save_int_32(png_bytep buf, png_int_32 i) 39{ 40 buf[0] = (png_byte)((i >> 24) & 0xff); 41 buf[1] = (png_byte)((i >> 16) & 0xff); 42 buf[2] = (png_byte)((i >> 8) & 0xff); 43 buf[3] = (png_byte)(i & 0xff); 44} 45#endif 46 47/* Place a 16-bit number into a buffer in PNG byte order. 48 * The parameter is declared unsigned int, not png_uint_16, 49 * just to avoid potential problems on pre-ANSI C compilers. 50 */ 51void PNGAPI 52png_save_uint_16(png_bytep buf, unsigned int i) 53{ 54 buf[0] = (png_byte)((i >> 8) & 0xff); 55 buf[1] = (png_byte)(i & 0xff); 56} 57 58/* Simple function to write the signature. If we have already written 59 * the magic bytes of the signature, or more likely, the PNG stream is 60 * being embedded into another stream and doesn't need its own signature, 61 * we should call png_set_sig_bytes() to tell libpng how many of the 62 * bytes have already been written. 63 */ 64void PNGAPI 65png_write_sig(png_structp png_ptr) 66{ 67 png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; 68 69#ifdef PNG_IO_STATE_SUPPORTED 70 /* Inform the I/O callback that the signature is being written */ 71 png_ptr->io_state = PNG_IO_WRITING | PNG_IO_SIGNATURE; 72#endif 73 74 /* Write the rest of the 8 byte signature */ 75 png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes], 76 (png_size_t)(8 - png_ptr->sig_bytes)); 77 if (png_ptr->sig_bytes < 3) 78 png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; 79} 80 81/* Write a PNG chunk all at once. The type is an array of ASCII characters 82 * representing the chunk name. The array must be at least 4 bytes in 83 * length, and does not need to be null terminated. To be safe, pass the 84 * pre-defined chunk names here, and if you need a new one, define it 85 * where the others are defined. The length is the length of the data. 86 * All the data must be present. If that is not possible, use the 87 * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end() 88 * functions instead. 89 */ 90void PNGAPI 91png_write_chunk(png_structp png_ptr, png_bytep chunk_name, 92 png_bytep data, png_size_t length) 93{ 94 if (png_ptr == NULL) 95 return; 96 png_write_chunk_start(png_ptr, chunk_name, (png_uint_32)length); 97 png_write_chunk_data(png_ptr, data, (png_size_t)length); 98 png_write_chunk_end(png_ptr); 99} 100 101/* Write the start of a PNG chunk. The type is the chunk type. 102 * The total_length is the sum of the lengths of all the data you will be 103 * passing in png_write_chunk_data(). 104 */ 105void PNGAPI 106png_write_chunk_start(png_structp png_ptr, png_bytep chunk_name, 107 png_uint_32 length) 108{ 109 png_byte buf[8]; 110 111 png_debug2(0, "Writing %s chunk, length = %lu", chunk_name, 112 (unsigned long)length); 113 114 if (png_ptr == NULL) 115 return; 116 117#ifdef PNG_IO_STATE_SUPPORTED 118 /* Inform the I/O callback that the chunk header is being written. 119 * PNG_IO_CHUNK_HDR requires a single I/O call. 120 */ 121 png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_HDR; 122#endif 123 124 /* Write the length and the chunk name */ 125 png_save_uint_32(buf, length); 126 png_memcpy(buf + 4, chunk_name, 4); 127 png_write_data(png_ptr, buf, (png_size_t)8); 128 /* Put the chunk name into png_ptr->chunk_name */ 129 png_memcpy(png_ptr->chunk_name, chunk_name, 4); 130 /* Reset the crc and run it over the chunk name */ 131 png_reset_crc(png_ptr); 132 png_calculate_crc(png_ptr, chunk_name, 4); 133 134#ifdef PNG_IO_STATE_SUPPORTED 135 /* Inform the I/O callback that chunk data will (possibly) be written. 136 * PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls. 137 */ 138 png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_DATA; 139#endif 140} 141 142/* Write the data of a PNG chunk started with png_write_chunk_start(). 143 * Note that multiple calls to this function are allowed, and that the 144 * sum of the lengths from these calls *must* add up to the total_length 145 * given to png_write_chunk_start(). 146 */ 147void PNGAPI 148png_write_chunk_data(png_structp png_ptr, png_bytep data, png_size_t length) 149{ 150 /* Write the data, and run the CRC over it */ 151 if (png_ptr == NULL) 152 return; 153 if (data != NULL && length > 0) 154 { 155 png_write_data(png_ptr, data, length); 156 /* Update the CRC after writing the data, 157 * in case that the user I/O routine alters it. 158 */ 159 png_calculate_crc(png_ptr, data, length); 160 } 161} 162 163/* Finish a chunk started with png_write_chunk_start(). */ 164void PNGAPI 165png_write_chunk_end(png_structp png_ptr) 166{ 167 png_byte buf[4]; 168 169 if (png_ptr == NULL) return; 170 171#ifdef PNG_IO_STATE_SUPPORTED 172 /* Inform the I/O callback that the chunk CRC is being written. 173 * PNG_IO_CHUNK_CRC requires a single I/O function call. 174 */ 175 png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_CRC; 176#endif 177 178 /* Write the crc in a single operation */ 179 png_save_uint_32(buf, png_ptr->crc); 180 181 png_write_data(png_ptr, buf, (png_size_t)4); 182} 183 184#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_iCCP_SUPPORTED) 185/* This pair of functions encapsulates the operation of (a) compressing a 186 * text string, and (b) issuing it later as a series of chunk data writes. 187 * The compression_state structure is shared context for these functions 188 * set up by the caller in order to make the whole mess thread-safe. 189 */ 190 191typedef struct 192{ 193 char *input; /* The uncompressed input data */ 194 int input_len; /* Its length */ 195 int num_output_ptr; /* Number of output pointers used */ 196 int max_output_ptr; /* Size of output_ptr */ 197 png_charpp output_ptr; /* Array of pointers to output */ 198} compression_state; 199 200/* Compress given text into storage in the png_ptr structure */ 201static int /* PRIVATE */ 202png_text_compress(png_structp png_ptr, 203 png_charp text, png_size_t text_len, int compression, 204 compression_state *comp) 205{ 206 int ret; 207 208 comp->num_output_ptr = 0; 209 comp->max_output_ptr = 0; 210 comp->output_ptr = NULL; 211 comp->input = NULL; 212 comp->input_len = 0; 213 214 /* We may just want to pass the text right through */ 215 if (compression == PNG_TEXT_COMPRESSION_NONE) 216 { 217 comp->input = text; 218 comp->input_len = text_len; 219 return((int)text_len); 220 } 221 222 if (compression >= PNG_TEXT_COMPRESSION_LAST) 223 { 224#ifdef PNG_STDIO_SUPPORTED 225 char msg[50]; 226 png_snprintf(msg, 50, "Unknown compression type %d", compression); 227 png_warning(png_ptr, msg); 228#else 229 png_warning(png_ptr, "Unknown compression type"); 230#endif 231 } 232 233 /* We can't write the chunk until we find out how much data we have, 234 * which means we need to run the compressor first and save the 235 * output. This shouldn't be a problem, as the vast majority of 236 * comments should be reasonable, but we will set up an array of 237 * malloc'd pointers to be sure. 238 * 239 * If we knew the application was well behaved, we could simplify this 240 * greatly by assuming we can always malloc an output buffer large 241 * enough to hold the compressed text ((1001 * text_len / 1000) + 12) 242 * and malloc this directly. The only time this would be a bad idea is 243 * if we can't malloc more than 64K and we have 64K of random input 244 * data, or if the input string is incredibly large (although this 245 * wouldn't cause a failure, just a slowdown due to swapping). 246 */ 247 248 /* Set up the compression buffers */ 249 png_ptr->zstream.avail_in = (uInt)text_len; 250 png_ptr->zstream.next_in = (Bytef *)text; 251 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; 252 png_ptr->zstream.next_out = (Bytef *)png_ptr->zbuf; 253 254 /* This is the same compression loop as in png_write_row() */ 255 do 256 { 257 /* Compress the data */ 258 ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); 259 if (ret != Z_OK) 260 { 261 /* Error */ 262 if (png_ptr->zstream.msg != NULL) 263 png_error(png_ptr, png_ptr->zstream.msg); 264 else 265 png_error(png_ptr, "zlib error"); 266 } 267 /* Check to see if we need more room */ 268 if (!(png_ptr->zstream.avail_out)) 269 { 270 /* Make sure the output array has room */ 271 if (comp->num_output_ptr >= comp->max_output_ptr) 272 { 273 int old_max; 274 275 old_max = comp->max_output_ptr; 276 comp->max_output_ptr = comp->num_output_ptr + 4; 277 if (comp->output_ptr != NULL) 278 { 279 png_charpp old_ptr; 280 281 old_ptr = comp->output_ptr; 282 comp->output_ptr = (png_charpp)png_malloc(png_ptr, 283 (png_alloc_size_t) 284 (comp->max_output_ptr * png_sizeof(png_charpp))); 285 png_memcpy(comp->output_ptr, old_ptr, old_max 286 * png_sizeof(png_charp)); 287 png_free(png_ptr, old_ptr); 288 } 289 else 290 comp->output_ptr = (png_charpp)png_malloc(png_ptr, 291 (png_alloc_size_t) 292 (comp->max_output_ptr * png_sizeof(png_charp))); 293 } 294 295 /* Save the data */ 296 comp->output_ptr[comp->num_output_ptr] = 297 (png_charp)png_malloc(png_ptr, 298 (png_alloc_size_t)png_ptr->zbuf_size); 299 png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, 300 png_ptr->zbuf_size); 301 comp->num_output_ptr++; 302 303 /* and reset the buffer */ 304 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; 305 png_ptr->zstream.next_out = png_ptr->zbuf; 306 } 307 /* Continue until we don't have any more to compress */ 308 } while (png_ptr->zstream.avail_in); 309 310 /* Finish the compression */ 311 do 312 { 313 /* Tell zlib we are finished */ 314 ret = deflate(&png_ptr->zstream, Z_FINISH); 315 316 if (ret == Z_OK) 317 { 318 /* Check to see if we need more room */ 319 if (!(png_ptr->zstream.avail_out)) 320 { 321 /* Check to make sure our output array has room */ 322 if (comp->num_output_ptr >= comp->max_output_ptr) 323 { 324 int old_max; 325 326 old_max = comp->max_output_ptr; 327 comp->max_output_ptr = comp->num_output_ptr + 4; 328 if (comp->output_ptr != NULL) 329 { 330 png_charpp old_ptr; 331 332 old_ptr = comp->output_ptr; 333 /* This could be optimized to realloc() */ 334 comp->output_ptr = (png_charpp)png_malloc(png_ptr, 335 (png_alloc_size_t)(comp->max_output_ptr * 336 png_sizeof(png_charp))); 337 png_memcpy(comp->output_ptr, old_ptr, 338 old_max * png_sizeof(png_charp)); 339 png_free(png_ptr, old_ptr); 340 } 341 else 342 comp->output_ptr = (png_charpp)png_malloc(png_ptr, 343 (png_alloc_size_t)(comp->max_output_ptr * 344 png_sizeof(png_charp))); 345 } 346 347 /* Save the data */ 348 comp->output_ptr[comp->num_output_ptr] = 349 (png_charp)png_malloc(png_ptr, 350 (png_alloc_size_t)png_ptr->zbuf_size); 351 png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, 352 png_ptr->zbuf_size); 353 comp->num_output_ptr++; 354 355 /* and reset the buffer pointers */ 356 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; 357 png_ptr->zstream.next_out = png_ptr->zbuf; 358 } 359 } 360 else if (ret != Z_STREAM_END) 361 { 362 /* We got an error */ 363 if (png_ptr->zstream.msg != NULL) 364 png_error(png_ptr, png_ptr->zstream.msg); 365 else 366 png_error(png_ptr, "zlib error"); 367 } 368 } while (ret != Z_STREAM_END); 369 370 /* Text length is number of buffers plus last buffer */ 371 text_len = png_ptr->zbuf_size * comp->num_output_ptr; 372 if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) 373 text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out; 374 375 return((int)text_len); 376} 377 378/* Ship the compressed text out via chunk writes */ 379static void /* PRIVATE */ 380png_write_compressed_data_out(png_structp png_ptr, compression_state *comp) 381{ 382 int i; 383 384 /* Handle the no-compression case */ 385 if (comp->input) 386 { 387 png_write_chunk_data(png_ptr, (png_bytep)comp->input, 388 (png_size_t)comp->input_len); 389 return; 390 } 391 392 /* Write saved output buffers, if any */ 393 for (i = 0; i < comp->num_output_ptr; i++) 394 { 395 png_write_chunk_data(png_ptr, (png_bytep)comp->output_ptr[i], 396 (png_size_t)png_ptr->zbuf_size); 397 png_free(png_ptr, comp->output_ptr[i]); 398 } 399 if (comp->max_output_ptr != 0) 400 png_free(png_ptr, comp->output_ptr); 401 /* Write anything left in zbuf */ 402 if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size) 403 png_write_chunk_data(png_ptr, png_ptr->zbuf, 404 (png_size_t)(png_ptr->zbuf_size - png_ptr->zstream.avail_out)); 405 406 /* Reset zlib for another zTXt/iTXt or image data */ 407 deflateReset(&png_ptr->zstream); 408 png_ptr->zstream.data_type = Z_BINARY; 409} 410#endif 411 412/* Write the IHDR chunk, and update the png_struct with the necessary 413 * information. Note that the rest of this code depends upon this 414 * information being correct. 415 */ 416void /* PRIVATE */ 417png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height, 418 int bit_depth, int color_type, int compression_type, int filter_type, 419 int interlace_type) 420{ 421 PNG_IHDR; 422 int ret; 423 424 png_byte buf[13]; /* Buffer to store the IHDR info */ 425 426 png_debug(1, "in png_write_IHDR"); 427 428 /* Check that we have valid input data from the application info */ 429 switch (color_type) 430 { 431 case PNG_COLOR_TYPE_GRAY: 432 switch (bit_depth) 433 { 434 case 1: 435 case 2: 436 case 4: 437 case 8: 438 case 16: png_ptr->channels = 1; break; 439 default: png_error(png_ptr, 440 "Invalid bit depth for grayscale image"); 441 } 442 break; 443 case PNG_COLOR_TYPE_RGB: 444 if (bit_depth != 8 && bit_depth != 16) 445 png_error(png_ptr, "Invalid bit depth for RGB image"); 446 png_ptr->channels = 3; 447 break; 448 case PNG_COLOR_TYPE_PALETTE: 449 switch (bit_depth) 450 { 451 case 1: 452 case 2: 453 case 4: 454 case 8: png_ptr->channels = 1; break; 455 default: png_error(png_ptr, "Invalid bit depth for paletted image"); 456 } 457 break; 458 case PNG_COLOR_TYPE_GRAY_ALPHA: 459 if (bit_depth != 8 && bit_depth != 16) 460 png_error(png_ptr, "Invalid bit depth for grayscale+alpha image"); 461 png_ptr->channels = 2; 462 break; 463 case PNG_COLOR_TYPE_RGB_ALPHA: 464 if (bit_depth != 8 && bit_depth != 16) 465 png_error(png_ptr, "Invalid bit depth for RGBA image"); 466 png_ptr->channels = 4; 467 break; 468 default: 469 png_error(png_ptr, "Invalid image color type specified"); 470 } 471 472 if (compression_type != PNG_COMPRESSION_TYPE_BASE) 473 { 474 png_warning(png_ptr, "Invalid compression type specified"); 475 compression_type = PNG_COMPRESSION_TYPE_BASE; 476 } 477 478 /* Write filter_method 64 (intrapixel differencing) only if 479 * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and 480 * 2. Libpng did not write a PNG signature (this filter_method is only 481 * used in PNG datastreams that are embedded in MNG datastreams) and 482 * 3. The application called png_permit_mng_features with a mask that 483 * included PNG_FLAG_MNG_FILTER_64 and 484 * 4. The filter_method is 64 and 485 * 5. The color_type is RGB or RGBA 486 */ 487 if ( 488#ifdef PNG_MNG_FEATURES_SUPPORTED 489 !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && 490 ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) && 491 (color_type == PNG_COLOR_TYPE_RGB || 492 color_type == PNG_COLOR_TYPE_RGB_ALPHA) && 493 (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) && 494#endif 495 filter_type != PNG_FILTER_TYPE_BASE) 496 { 497 png_warning(png_ptr, "Invalid filter type specified"); 498 filter_type = PNG_FILTER_TYPE_BASE; 499 } 500 501#ifdef PNG_WRITE_INTERLACING_SUPPORTED 502 if (interlace_type != PNG_INTERLACE_NONE && 503 interlace_type != PNG_INTERLACE_ADAM7) 504 { 505 png_warning(png_ptr, "Invalid interlace type specified"); 506 interlace_type = PNG_INTERLACE_ADAM7; 507 } 508#else 509 interlace_type=PNG_INTERLACE_NONE; 510#endif 511 512 /* Save the relevent information */ 513 png_ptr->bit_depth = (png_byte)bit_depth; 514 png_ptr->color_type = (png_byte)color_type; 515 png_ptr->interlaced = (png_byte)interlace_type; 516#ifdef PNG_MNG_FEATURES_SUPPORTED 517 png_ptr->filter_type = (png_byte)filter_type; 518#endif 519 png_ptr->compression_type = (png_byte)compression_type; 520 png_ptr->width = width; 521 png_ptr->height = height; 522 523 png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels); 524 png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width); 525 /* Set the usr info, so any transformations can modify it */ 526 png_ptr->usr_width = png_ptr->width; 527 png_ptr->usr_bit_depth = png_ptr->bit_depth; 528 png_ptr->usr_channels = png_ptr->channels; 529 530 /* Pack the header information into the buffer */ 531 png_save_uint_32(buf, width); 532 png_save_uint_32(buf + 4, height); 533 buf[8] = (png_byte)bit_depth; 534 buf[9] = (png_byte)color_type; 535 buf[10] = (png_byte)compression_type; 536 buf[11] = (png_byte)filter_type; 537 buf[12] = (png_byte)interlace_type; 538 539 /* Write the chunk */ 540 png_write_chunk(png_ptr, (png_bytep)png_IHDR, buf, (png_size_t)13); 541 542 /* Initialize zlib with PNG info */ 543 png_ptr->zstream.zalloc = png_zalloc; 544 png_ptr->zstream.zfree = png_zfree; 545 png_ptr->zstream.opaque = (voidpf)png_ptr; 546 if (!(png_ptr->do_filter)) 547 { 548 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE || 549 png_ptr->bit_depth < 8) 550 png_ptr->do_filter = PNG_FILTER_NONE; 551 else 552 png_ptr->do_filter = PNG_ALL_FILTERS; 553 } 554 if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY)) 555 { 556 if (png_ptr->do_filter != PNG_FILTER_NONE) 557 png_ptr->zlib_strategy = Z_FILTERED; 558 else 559 png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY; 560 } 561 if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL)) 562 png_ptr->zlib_level = Z_DEFAULT_COMPRESSION; 563 if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL)) 564 png_ptr->zlib_mem_level = 8; 565 if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS)) 566 png_ptr->zlib_window_bits = 15; 567 if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD)) 568 png_ptr->zlib_method = 8; 569 ret = deflateInit2(&png_ptr->zstream, png_ptr->zlib_level, 570 png_ptr->zlib_method, png_ptr->zlib_window_bits, 571 png_ptr->zlib_mem_level, png_ptr->zlib_strategy); 572 if (ret != Z_OK) 573 { 574 if (ret == Z_VERSION_ERROR) png_error(png_ptr, 575 "zlib failed to initialize compressor -- version error"); 576 if (ret == Z_STREAM_ERROR) png_error(png_ptr, 577 "zlib failed to initialize compressor -- stream error"); 578 if (ret == Z_MEM_ERROR) png_error(png_ptr, 579 "zlib failed to initialize compressor -- mem error"); 580 png_error(png_ptr, "zlib failed to initialize compressor"); 581 } 582 png_ptr->zstream.next_out = png_ptr->zbuf; 583 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; 584 /* libpng is not interested in zstream.data_type */ 585 /* Set it to a predefined value, to avoid its evaluation inside zlib */ 586 png_ptr->zstream.data_type = Z_BINARY; 587 588 png_ptr->mode = PNG_HAVE_IHDR; 589} 590 591/* Write the palette. We are careful not to trust png_color to be in the 592 * correct order for PNG, so people can redefine it to any convenient 593 * structure. 594 */ 595void /* PRIVATE */ 596png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal) 597{ 598 PNG_PLTE; 599 png_uint_32 i; 600 png_colorp pal_ptr; 601 png_byte buf[3]; 602 603 png_debug(1, "in png_write_PLTE"); 604 605 if (( 606#ifdef PNG_MNG_FEATURES_SUPPORTED 607 !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) && 608#endif 609 num_pal == 0) || num_pal > 256) 610 { 611 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 612 { 613 png_error(png_ptr, "Invalid number of colors in palette"); 614 } 615 else 616 { 617 png_warning(png_ptr, "Invalid number of colors in palette"); 618 return; 619 } 620 } 621 622 if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) 623 { 624 png_warning(png_ptr, 625 "Ignoring request to write a PLTE chunk in grayscale PNG"); 626 return; 627 } 628 629 png_ptr->num_palette = (png_uint_16)num_pal; 630 png_debug1(3, "num_palette = %d", png_ptr->num_palette); 631 632 png_write_chunk_start(png_ptr, (png_bytep)png_PLTE, 633 (png_uint_32)(num_pal * 3)); 634#ifdef PNG_POINTER_INDEXING_SUPPORTED 635 for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++) 636 { 637 buf[0] = pal_ptr->red; 638 buf[1] = pal_ptr->green; 639 buf[2] = pal_ptr->blue; 640 png_write_chunk_data(png_ptr, buf, (png_size_t)3); 641 } 642#else 643 /* This is a little slower but some buggy compilers need to do this 644 * instead 645 */ 646 pal_ptr=palette; 647 for (i = 0; i < num_pal; i++) 648 { 649 buf[0] = pal_ptr[i].red; 650 buf[1] = pal_ptr[i].green; 651 buf[2] = pal_ptr[i].blue; 652 png_write_chunk_data(png_ptr, buf, (png_size_t)3); 653 } 654#endif 655 png_write_chunk_end(png_ptr); 656 png_ptr->mode |= PNG_HAVE_PLTE; 657} 658 659/* Write an IDAT chunk */ 660void /* PRIVATE */ 661png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length) 662{ 663 PNG_IDAT; 664 665 png_debug(1, "in png_write_IDAT"); 666 667 /* Optimize the CMF field in the zlib stream. */ 668 /* This hack of the zlib stream is compliant to the stream specification. */ 669 if (!(png_ptr->mode & PNG_HAVE_IDAT) && 670 png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) 671 { 672 unsigned int z_cmf = data[0]; /* zlib compression method and flags */ 673 if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70) 674 { 675 /* Avoid memory underflows and multiplication overflows. 676 * 677 * The conditions below are practically always satisfied; 678 * however, they still must be checked. 679 */ 680 if (length >= 2 && 681 png_ptr->height < 16384 && png_ptr->width < 16384) 682 { 683 png_uint_32 uncompressed_idat_size = png_ptr->height * 684 ((png_ptr->width * 685 png_ptr->channels * png_ptr->bit_depth + 15) >> 3); 686 unsigned int z_cinfo = z_cmf >> 4; 687 unsigned int half_z_window_size = 1 << (z_cinfo + 7); 688 while (uncompressed_idat_size <= half_z_window_size && 689 half_z_window_size >= 256) 690 { 691 z_cinfo--; 692 half_z_window_size >>= 1; 693 } 694 z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4); 695 if (data[0] != (png_byte)z_cmf) 696 { 697 data[0] = (png_byte)z_cmf; 698 data[1] &= 0xe0; 699 data[1] += (png_byte)(0x1f - ((z_cmf << 8) + data[1]) % 0x1f); 700 } 701 } 702 } 703 else 704 png_error(png_ptr, 705 "Invalid zlib compression method or flags in IDAT"); 706 } 707 708 png_write_chunk(png_ptr, (png_bytep)png_IDAT, data, length); 709 png_ptr->mode |= PNG_HAVE_IDAT; 710} 711 712/* Write an IEND chunk */ 713void /* PRIVATE */ 714png_write_IEND(png_structp png_ptr) 715{ 716 PNG_IEND; 717 718 png_debug(1, "in png_write_IEND"); 719 720 png_write_chunk(png_ptr, (png_bytep)png_IEND, NULL, 721 (png_size_t)0); 722 png_ptr->mode |= PNG_HAVE_IEND; 723} 724 725#ifdef PNG_WRITE_gAMA_SUPPORTED 726/* Write a gAMA chunk */ 727#ifdef PNG_FLOATING_POINT_SUPPORTED 728void /* PRIVATE */ 729png_write_gAMA(png_structp png_ptr, double file_gamma) 730{ 731 PNG_gAMA; 732 png_uint_32 igamma; 733 png_byte buf[4]; 734 735 png_debug(1, "in png_write_gAMA"); 736 737 /* file_gamma is saved in 1/100,000ths */ 738 igamma = (png_uint_32)(file_gamma * 100000.0 + 0.5); 739 png_save_uint_32(buf, igamma); 740 png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4); 741} 742#endif 743#ifdef PNG_FIXED_POINT_SUPPORTED 744void /* PRIVATE */ 745png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma) 746{ 747 PNG_gAMA; 748 png_byte buf[4]; 749 750 png_debug(1, "in png_write_gAMA"); 751 752 /* file_gamma is saved in 1/100,000ths */ 753 png_save_uint_32(buf, (png_uint_32)file_gamma); 754 png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4); 755} 756#endif 757#endif 758 759#ifdef PNG_WRITE_sRGB_SUPPORTED 760/* Write a sRGB chunk */ 761void /* PRIVATE */ 762png_write_sRGB(png_structp png_ptr, int srgb_intent) 763{ 764 PNG_sRGB; 765 png_byte buf[1]; 766 767 png_debug(1, "in png_write_sRGB"); 768 769 if (srgb_intent >= PNG_sRGB_INTENT_LAST) 770 png_warning(png_ptr, 771 "Invalid sRGB rendering intent specified"); 772 buf[0]=(png_byte)srgb_intent; 773 png_write_chunk(png_ptr, (png_bytep)png_sRGB, buf, (png_size_t)1); 774} 775#endif 776 777#ifdef PNG_WRITE_iCCP_SUPPORTED 778/* Write an iCCP chunk */ 779void /* PRIVATE */ 780png_write_iCCP(png_structp png_ptr, png_charp name, int compression_type, 781 png_charp profile, int profile_len) 782{ 783 PNG_iCCP; 784 png_size_t name_len; 785 png_charp new_name; 786 compression_state comp; 787 int embedded_profile_len = 0; 788 789 png_debug(1, "in png_write_iCCP"); 790 791 comp.num_output_ptr = 0; 792 comp.max_output_ptr = 0; 793 comp.output_ptr = NULL; 794 comp.input = NULL; 795 comp.input_len = 0; 796 797 if ((name_len = png_check_keyword(png_ptr, name, 798 &new_name)) == 0) 799 return; 800 801 if (compression_type != PNG_COMPRESSION_TYPE_BASE) 802 png_warning(png_ptr, "Unknown compression type in iCCP chunk"); 803 804 if (profile == NULL) 805 profile_len = 0; 806 807 if (profile_len > 3) 808 embedded_profile_len = 809 ((*( (png_bytep)profile ))<<24) | 810 ((*( (png_bytep)profile + 1))<<16) | 811 ((*( (png_bytep)profile + 2))<< 8) | 812 ((*( (png_bytep)profile + 3)) ); 813 814 if (embedded_profile_len < 0) 815 { 816 png_warning(png_ptr, 817 "Embedded profile length in iCCP chunk is negative"); 818 png_free(png_ptr, new_name); 819 return; 820 } 821 822 if (profile_len < embedded_profile_len) 823 { 824 png_warning(png_ptr, 825 "Embedded profile length too large in iCCP chunk"); 826 png_free(png_ptr, new_name); 827 return; 828 } 829 830 if (profile_len > embedded_profile_len) 831 { 832 png_warning(png_ptr, 833 "Truncating profile to actual length in iCCP chunk"); 834 profile_len = embedded_profile_len; 835 } 836 837 if (profile_len) 838 profile_len = png_text_compress(png_ptr, profile, 839 (png_size_t)profile_len, PNG_COMPRESSION_TYPE_BASE, &comp); 840 841 /* Make sure we include the NULL after the name and the compression type */ 842 png_write_chunk_start(png_ptr, (png_bytep)png_iCCP, 843 (png_uint_32)(name_len + profile_len + 2)); 844 new_name[name_len + 1] = 0x00; 845 png_write_chunk_data(png_ptr, (png_bytep)new_name, 846 (png_size_t)(name_len + 2)); 847 848 if (profile_len) 849 png_write_compressed_data_out(png_ptr, &comp); 850 851 png_write_chunk_end(png_ptr); 852 png_free(png_ptr, new_name); 853} 854#endif 855 856#ifdef PNG_WRITE_sPLT_SUPPORTED 857/* Write a sPLT chunk */ 858void /* PRIVATE */ 859png_write_sPLT(png_structp png_ptr, png_sPLT_tp spalette) 860{ 861 PNG_sPLT; 862 png_size_t name_len; 863 png_charp new_name; 864 png_byte entrybuf[10]; 865 png_size_t entry_size = (spalette->depth == 8 ? 6 : 10); 866 png_size_t palette_size = entry_size * spalette->nentries; 867 png_sPLT_entryp ep; 868#ifndef PNG_POINTER_INDEXING_SUPPORTED 869 int i; 870#endif 871 872 png_debug(1, "in png_write_sPLT"); 873 874 if ((name_len = png_check_keyword(png_ptr,spalette->name, &new_name))==0) 875 return; 876 877 /* Make sure we include the NULL after the name */ 878 png_write_chunk_start(png_ptr, (png_bytep)png_sPLT, 879 (png_uint_32)(name_len + 2 + palette_size)); 880 png_write_chunk_data(png_ptr, (png_bytep)new_name, 881 (png_size_t)(name_len + 1)); 882 png_write_chunk_data(png_ptr, (png_bytep)&spalette->depth, (png_size_t)1); 883 884 /* Loop through each palette entry, writing appropriately */ 885#ifdef PNG_POINTER_INDEXING_SUPPORTED 886 for (ep = spalette->entries; ep<spalette->entries + spalette->nentries; ep++) 887 { 888 if (spalette->depth == 8) 889 { 890 entrybuf[0] = (png_byte)ep->red; 891 entrybuf[1] = (png_byte)ep->green; 892 entrybuf[2] = (png_byte)ep->blue; 893 entrybuf[3] = (png_byte)ep->alpha; 894 png_save_uint_16(entrybuf + 4, ep->frequency); 895 } 896 else 897 { 898 png_save_uint_16(entrybuf + 0, ep->red); 899 png_save_uint_16(entrybuf + 2, ep->green); 900 png_save_uint_16(entrybuf + 4, ep->blue); 901 png_save_uint_16(entrybuf + 6, ep->alpha); 902 png_save_uint_16(entrybuf + 8, ep->frequency); 903 } 904 png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size); 905 } 906#else 907 ep=spalette->entries; 908 for (i=0; i>spalette->nentries; i++) 909 { 910 if (spalette->depth == 8) 911 { 912 entrybuf[0] = (png_byte)ep[i].red; 913 entrybuf[1] = (png_byte)ep[i].green; 914 entrybuf[2] = (png_byte)ep[i].blue; 915 entrybuf[3] = (png_byte)ep[i].alpha; 916 png_save_uint_16(entrybuf + 4, ep[i].frequency); 917 } 918 else 919 { 920 png_save_uint_16(entrybuf + 0, ep[i].red); 921 png_save_uint_16(entrybuf + 2, ep[i].green); 922 png_save_uint_16(entrybuf + 4, ep[i].blue); 923 png_save_uint_16(entrybuf + 6, ep[i].alpha); 924 png_save_uint_16(entrybuf + 8, ep[i].frequency); 925 } 926 png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size); 927 } 928#endif 929 930 png_write_chunk_end(png_ptr); 931 png_free(png_ptr, new_name); 932} 933#endif 934 935#ifdef PNG_WRITE_sBIT_SUPPORTED 936/* Write the sBIT chunk */ 937void /* PRIVATE */ 938png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type) 939{ 940 PNG_sBIT; 941 png_byte buf[4]; 942 png_size_t size; 943 944 png_debug(1, "in png_write_sBIT"); 945 946 /* Make sure we don't depend upon the order of PNG_COLOR_8 */ 947 if (color_type & PNG_COLOR_MASK_COLOR) 948 { 949 png_byte maxbits; 950 951 maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 : 952 png_ptr->usr_bit_depth); 953 if (sbit->red == 0 || sbit->red > maxbits || 954 sbit->green == 0 || sbit->green > maxbits || 955 sbit->blue == 0 || sbit->blue > maxbits) 956 { 957 png_warning(png_ptr, "Invalid sBIT depth specified"); 958 return; 959 } 960 buf[0] = sbit->red; 961 buf[1] = sbit->green; 962 buf[2] = sbit->blue; 963 size = 3; 964 } 965 else 966 { 967 if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth) 968 { 969 png_warning(png_ptr, "Invalid sBIT depth specified"); 970 return; 971 } 972 buf[0] = sbit->gray; 973 size = 1; 974 } 975 976 if (color_type & PNG_COLOR_MASK_ALPHA) 977 { 978 if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth) 979 { 980 png_warning(png_ptr, "Invalid sBIT depth specified"); 981 return; 982 } 983 buf[size++] = sbit->alpha; 984 } 985 986 png_write_chunk(png_ptr, (png_bytep)png_sBIT, buf, size); 987} 988#endif 989 990#ifdef PNG_WRITE_cHRM_SUPPORTED 991/* Write the cHRM chunk */ 992#ifdef PNG_FLOATING_POINT_SUPPORTED 993void /* PRIVATE */ 994png_write_cHRM(png_structp png_ptr, double white_x, double white_y, 995 double red_x, double red_y, double green_x, double green_y, 996 double blue_x, double blue_y) 997{ 998 PNG_cHRM; 999 png_byte buf[32]; 1000 1001 png_fixed_point int_white_x, int_white_y, int_red_x, int_red_y, 1002 int_green_x, int_green_y, int_blue_x, int_blue_y; 1003 1004 png_debug(1, "in png_write_cHRM"); 1005 1006 int_white_x = (png_uint_32)(white_x * 100000.0 + 0.5); 1007 int_white_y = (png_uint_32)(white_y * 100000.0 + 0.5); 1008 int_red_x = (png_uint_32)(red_x * 100000.0 + 0.5); 1009 int_red_y = (png_uint_32)(red_y * 100000.0 + 0.5); 1010 int_green_x = (png_uint_32)(green_x * 100000.0 + 0.5); 1011 int_green_y = (png_uint_32)(green_y * 100000.0 + 0.5); 1012 int_blue_x = (png_uint_32)(blue_x * 100000.0 + 0.5); 1013 int_blue_y = (png_uint_32)(blue_y * 100000.0 + 0.5); 1014 1015#ifdef PNG_CHECK_cHRM_SUPPORTED 1016 if (png_check_cHRM_fixed(png_ptr, int_white_x, int_white_y, 1017 int_red_x, int_red_y, int_green_x, int_green_y, int_blue_x, int_blue_y)) 1018#endif 1019 { 1020 /* Each value is saved in 1/100,000ths */ 1021 1022 png_save_uint_32(buf, int_white_x); 1023 png_save_uint_32(buf + 4, int_white_y); 1024 1025 png_save_uint_32(buf + 8, int_red_x); 1026 png_save_uint_32(buf + 12, int_red_y); 1027 1028 png_save_uint_32(buf + 16, int_green_x); 1029 png_save_uint_32(buf + 20, int_green_y); 1030 1031 png_save_uint_32(buf + 24, int_blue_x); 1032 png_save_uint_32(buf + 28, int_blue_y); 1033 1034 png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32); 1035 } 1036} 1037#endif 1038#ifdef PNG_FIXED_POINT_SUPPORTED 1039void /* PRIVATE */ 1040png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x, 1041 png_fixed_point white_y, png_fixed_point red_x, png_fixed_point red_y, 1042 png_fixed_point green_x, png_fixed_point green_y, png_fixed_point blue_x, 1043 png_fixed_point blue_y) 1044{ 1045 PNG_cHRM; 1046 png_byte buf[32]; 1047 1048 png_debug(1, "in png_write_cHRM"); 1049 1050 /* Each value is saved in 1/100,000ths */ 1051#ifdef PNG_CHECK_cHRM_SUPPORTED 1052 if (png_check_cHRM_fixed(png_ptr, white_x, white_y, red_x, red_y, 1053 green_x, green_y, blue_x, blue_y)) 1054#endif 1055 { 1056 png_save_uint_32(buf, (png_uint_32)white_x); 1057 png_save_uint_32(buf + 4, (png_uint_32)white_y); 1058 1059 png_save_uint_32(buf + 8, (png_uint_32)red_x); 1060 png_save_uint_32(buf + 12, (png_uint_32)red_y); 1061 1062 png_save_uint_32(buf + 16, (png_uint_32)green_x); 1063 png_save_uint_32(buf + 20, (png_uint_32)green_y); 1064 1065 png_save_uint_32(buf + 24, (png_uint_32)blue_x); 1066 png_save_uint_32(buf + 28, (png_uint_32)blue_y); 1067 1068 png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32); 1069 } 1070} 1071#endif 1072#endif 1073 1074#ifdef PNG_WRITE_tRNS_SUPPORTED 1075/* Write the tRNS chunk */ 1076void /* PRIVATE */ 1077png_write_tRNS(png_structp png_ptr, png_bytep trans_alpha, png_color_16p tran, 1078 int num_trans, int color_type) 1079{ 1080 PNG_tRNS; 1081 png_byte buf[6]; 1082 1083 png_debug(1, "in png_write_tRNS"); 1084 1085 if (color_type == PNG_COLOR_TYPE_PALETTE) 1086 { 1087 if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette) 1088 { 1089 png_warning(png_ptr, "Invalid number of transparent colors specified"); 1090 return; 1091 } 1092 /* Write the chunk out as it is */ 1093 png_write_chunk(png_ptr, (png_bytep)png_tRNS, trans_alpha, 1094 (png_size_t)num_trans); 1095 } 1096 else if (color_type == PNG_COLOR_TYPE_GRAY) 1097 { 1098 /* One 16 bit value */ 1099 if (tran->gray >= (1 << png_ptr->bit_depth)) 1100 { 1101 png_warning(png_ptr, 1102 "Ignoring attempt to write tRNS chunk out-of-range for bit_depth"); 1103 return; 1104 } 1105 png_save_uint_16(buf, tran->gray); 1106 png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)2); 1107 } 1108 else if (color_type == PNG_COLOR_TYPE_RGB) 1109 { 1110 /* Three 16 bit values */ 1111 png_save_uint_16(buf, tran->red); 1112 png_save_uint_16(buf + 2, tran->green); 1113 png_save_uint_16(buf + 4, tran->blue); 1114 if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) 1115 { 1116 png_warning(png_ptr, 1117 "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"); 1118 return; 1119 } 1120 png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)6); 1121 } 1122 else 1123 { 1124 png_warning(png_ptr, "Can't write tRNS with an alpha channel"); 1125 } 1126} 1127#endif 1128 1129#ifdef PNG_WRITE_bKGD_SUPPORTED 1130/* Write the background chunk */ 1131void /* PRIVATE */ 1132png_write_bKGD(png_structp png_ptr, png_color_16p back, int color_type) 1133{ 1134 PNG_bKGD; 1135 png_byte buf[6]; 1136 1137 png_debug(1, "in png_write_bKGD"); 1138 1139 if (color_type == PNG_COLOR_TYPE_PALETTE) 1140 { 1141 if ( 1142#ifdef PNG_MNG_FEATURES_SUPPORTED 1143 (png_ptr->num_palette || 1144 (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) && 1145#endif 1146 back->index >= png_ptr->num_palette) 1147 { 1148 png_warning(png_ptr, "Invalid background palette index"); 1149 return; 1150 } 1151 buf[0] = back->index; 1152 png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)1); 1153 } 1154 else if (color_type & PNG_COLOR_MASK_COLOR) 1155 { 1156 png_save_uint_16(buf, back->red); 1157 png_save_uint_16(buf + 2, back->green); 1158 png_save_uint_16(buf + 4, back->blue); 1159 if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) 1160 { 1161 png_warning(png_ptr, 1162 "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8"); 1163 return; 1164 } 1165 png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)6); 1166 } 1167 else 1168 { 1169 if (back->gray >= (1 << png_ptr->bit_depth)) 1170 { 1171 png_warning(png_ptr, 1172 "Ignoring attempt to write bKGD chunk out-of-range for bit_depth"); 1173 return; 1174 } 1175 png_save_uint_16(buf, back->gray); 1176 png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)2); 1177 } 1178} 1179#endif 1180 1181#ifdef PNG_WRITE_hIST_SUPPORTED 1182/* Write the histogram */ 1183void /* PRIVATE */ 1184png_write_hIST(png_structp png_ptr, png_uint_16p hist, int num_hist) 1185{ 1186 PNG_hIST; 1187 int i; 1188 png_byte buf[3]; 1189 1190 png_debug(1, "in png_write_hIST"); 1191 1192 if (num_hist > (int)png_ptr->num_palette) 1193 { 1194 png_debug2(3, "num_hist = %d, num_palette = %d", num_hist, 1195 png_ptr->num_palette); 1196 png_warning(png_ptr, "Invalid number of histogram entries specified"); 1197 return; 1198 } 1199 1200 png_write_chunk_start(png_ptr, (png_bytep)png_hIST, 1201 (png_uint_32)(num_hist * 2)); 1202 for (i = 0; i < num_hist; i++) 1203 { 1204 png_save_uint_16(buf, hist[i]); 1205 png_write_chunk_data(png_ptr, buf, (png_size_t)2); 1206 } 1207 png_write_chunk_end(png_ptr); 1208} 1209#endif 1210 1211#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ 1212 defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) 1213/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification, 1214 * and if invalid, correct the keyword rather than discarding the entire 1215 * chunk. The PNG 1.0 specification requires keywords 1-79 characters in 1216 * length, forbids leading or trailing whitespace, multiple internal spaces, 1217 * and the non-break space (0x80) from ISO 8859-1. Returns keyword length. 1218 * 1219 * The new_key is allocated to hold the corrected keyword and must be freed 1220 * by the calling routine. This avoids problems with trying to write to 1221 * static keywords without having to have duplicate copies of the strings. 1222 */ 1223png_size_t /* PRIVATE */ 1224png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key) 1225{ 1226 png_size_t key_len; 1227 png_charp kp, dp; 1228 int kflag; 1229 int kwarn=0; 1230 1231 png_debug(1, "in png_check_keyword"); 1232 1233 *new_key = NULL; 1234 1235 if (key == NULL || (key_len = png_strlen(key)) == 0) 1236 { 1237 png_warning(png_ptr, "zero length keyword"); 1238 return ((png_size_t)0); 1239 } 1240 1241 png_debug1(2, "Keyword to be checked is '%s'", key); 1242 1243 *new_key = (png_charp)png_malloc_warn(png_ptr, (png_uint_32)(key_len + 2)); 1244 if (*new_key == NULL) 1245 { 1246 png_warning(png_ptr, "Out of memory while procesing keyword"); 1247 return ((png_size_t)0); 1248 } 1249 1250 /* Replace non-printing characters with a blank and print a warning */ 1251 for (kp = key, dp = *new_key; *kp != '\0'; kp++, dp++) 1252 { 1253 if ((png_byte)*kp < 0x20 || 1254 ((png_byte)*kp > 0x7E && (png_byte)*kp < 0xA1)) 1255 { 1256#ifdef PNG_STDIO_SUPPORTED 1257 char msg[40]; 1258 1259 png_snprintf(msg, 40, 1260 "invalid keyword character 0x%02X", (png_byte)*kp); 1261 png_warning(png_ptr, msg); 1262#else 1263 png_warning(png_ptr, "invalid character in keyword"); 1264#endif 1265 *dp = ' '; 1266 } 1267 else 1268 { 1269 *dp = *kp; 1270 } 1271 } 1272 *dp = '\0'; 1273 1274 /* Remove any trailing white space. */ 1275 kp = *new_key + key_len - 1; 1276 if (*kp == ' ') 1277 { 1278 png_warning(png_ptr, "trailing spaces removed from keyword"); 1279 1280 while (*kp == ' ') 1281 { 1282 *(kp--) = '\0'; 1283 key_len--; 1284 } 1285 } 1286 1287 /* Remove any leading white space. */ 1288 kp = *new_key; 1289 if (*kp == ' ') 1290 { 1291 png_warning(png_ptr, "leading spaces removed from keyword"); 1292 1293 while (*kp == ' ') 1294 { 1295 kp++; 1296 key_len--; 1297 } 1298 } 1299 1300 png_debug1(2, "Checking for multiple internal spaces in '%s'", kp); 1301 1302 /* Remove multiple internal spaces. */ 1303 for (kflag = 0, dp = *new_key; *kp != '\0'; kp++) 1304 { 1305 if (*kp == ' ' && kflag == 0) 1306 { 1307 *(dp++) = *kp; 1308 kflag = 1; 1309 } 1310 else if (*kp == ' ') 1311 { 1312 key_len--; 1313 kwarn=1; 1314 } 1315 else 1316 { 1317 *(dp++) = *kp; 1318 kflag = 0; 1319 } 1320 } 1321 *dp = '\0'; 1322 if (kwarn) 1323 png_warning(png_ptr, "extra interior spaces removed from keyword"); 1324 1325 if (key_len == 0) 1326 { 1327 png_free(png_ptr, *new_key); 1328 png_warning(png_ptr, "Zero length keyword"); 1329 } 1330 1331 if (key_len > 79) 1332 { 1333 png_warning(png_ptr, "keyword length must be 1 - 79 characters"); 1334 (*new_key)[79] = '\0'; 1335 key_len = 79; 1336 } 1337 1338 return (key_len); 1339} 1340#endif 1341 1342#ifdef PNG_WRITE_tEXt_SUPPORTED 1343/* Write a tEXt chunk */ 1344void /* PRIVATE */ 1345png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text, 1346 png_size_t text_len) 1347{ 1348 PNG_tEXt; 1349 png_size_t key_len; 1350 png_charp new_key; 1351 1352 png_debug(1, "in png_write_tEXt"); 1353 1354 if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0) 1355 return; 1356 1357 if (text == NULL || *text == '\0') 1358 text_len = 0; 1359 else 1360 text_len = png_strlen(text); 1361 1362 /* Make sure we include the 0 after the key */ 1363 png_write_chunk_start(png_ptr, (png_bytep)png_tEXt, 1364 (png_uint_32)(key_len + text_len + 1)); 1365 /* 1366 * We leave it to the application to meet PNG-1.0 requirements on the 1367 * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of 1368 * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. 1369 * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. 1370 */ 1371 png_write_chunk_data(png_ptr, (png_bytep)new_key, 1372 (png_size_t)(key_len + 1)); 1373 if (text_len) 1374 png_write_chunk_data(png_ptr, (png_bytep)text, (png_size_t)text_len); 1375 1376 png_write_chunk_end(png_ptr); 1377 png_free(png_ptr, new_key); 1378} 1379#endif 1380 1381#ifdef PNG_WRITE_zTXt_SUPPORTED 1382/* Write a compressed text chunk */ 1383void /* PRIVATE */ 1384png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text, 1385 png_size_t text_len, int compression) 1386{ 1387 PNG_zTXt; 1388 png_size_t key_len; 1389 char buf[1]; 1390 png_charp new_key; 1391 compression_state comp; 1392 1393 png_debug(1, "in png_write_zTXt"); 1394 1395 comp.num_output_ptr = 0; 1396 comp.max_output_ptr = 0; 1397 comp.output_ptr = NULL; 1398 comp.input = NULL; 1399 comp.input_len = 0; 1400 1401 if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0) 1402 { 1403 png_free(png_ptr, new_key); 1404 return; 1405 } 1406 1407 if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE) 1408 { 1409 png_write_tEXt(png_ptr, new_key, text, (png_size_t)0); 1410 png_free(png_ptr, new_key); 1411 return; 1412 } 1413 1414 text_len = png_strlen(text); 1415 1416 /* Compute the compressed data; do it now for the length */ 1417 text_len = png_text_compress(png_ptr, text, text_len, compression, 1418 &comp); 1419 1420 /* Write start of chunk */ 1421 png_write_chunk_start(png_ptr, (png_bytep)png_zTXt, 1422 (png_uint_32)(key_len+text_len + 2)); 1423 /* Write key */ 1424 png_write_chunk_data(png_ptr, (png_bytep)new_key, 1425 (png_size_t)(key_len + 1)); 1426 png_free(png_ptr, new_key); 1427 1428 buf[0] = (png_byte)compression; 1429 /* Write compression */ 1430 png_write_chunk_data(png_ptr, (png_bytep)buf, (png_size_t)1); 1431 /* Write the compressed data */ 1432 png_write_compressed_data_out(png_ptr, &comp); 1433 1434 /* Close the chunk */ 1435 png_write_chunk_end(png_ptr); 1436} 1437#endif 1438 1439#ifdef PNG_WRITE_iTXt_SUPPORTED 1440/* Write an iTXt chunk */ 1441void /* PRIVATE */ 1442png_write_iTXt(png_structp png_ptr, int compression, png_charp key, 1443 png_charp lang, png_charp lang_key, png_charp text) 1444{ 1445 PNG_iTXt; 1446 png_size_t lang_len, key_len, lang_key_len, text_len; 1447 png_charp new_lang; 1448 png_charp new_key = NULL; 1449 png_byte cbuf[2]; 1450 compression_state comp; 1451 1452 png_debug(1, "in png_write_iTXt"); 1453 1454 comp.num_output_ptr = 0; 1455 comp.max_output_ptr = 0; 1456 comp.output_ptr = NULL; 1457 comp.input = NULL; 1458 1459 if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0) 1460 return; 1461 1462 if ((lang_len = png_check_keyword(png_ptr, lang, &new_lang))==0) 1463 { 1464 png_warning(png_ptr, "Empty language field in iTXt chunk"); 1465 new_lang = NULL; 1466 lang_len = 0; 1467 } 1468 1469 if (lang_key == NULL) 1470 lang_key_len = 0; 1471 else 1472 lang_key_len = png_strlen(lang_key); 1473 1474 if (text == NULL) 1475 text_len = 0; 1476 else 1477 text_len = png_strlen(text); 1478 1479 /* Compute the compressed data; do it now for the length */ 1480 text_len = png_text_compress(png_ptr, text, text_len, compression-2, 1481 &comp); 1482 1483 1484 /* Make sure we include the compression flag, the compression byte, 1485 * and the NULs after the key, lang, and lang_key parts */ 1486 1487 png_write_chunk_start(png_ptr, (png_bytep)png_iTXt, 1488 (png_uint_32)( 1489 5 /* comp byte, comp flag, terminators for key, lang and lang_key */ 1490 + key_len 1491 + lang_len 1492 + lang_key_len 1493 + text_len)); 1494 1495 /* We leave it to the application to meet PNG-1.0 requirements on the 1496 * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of 1497 * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. 1498 * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. 1499 */ 1500 png_write_chunk_data(png_ptr, (png_bytep)new_key, 1501 (png_size_t)(key_len + 1)); 1502 1503 /* Set the compression flag */ 1504 if (compression == PNG_ITXT_COMPRESSION_NONE || \ 1505 compression == PNG_TEXT_COMPRESSION_NONE) 1506 cbuf[0] = 0; 1507 else /* compression == PNG_ITXT_COMPRESSION_zTXt */ 1508 cbuf[0] = 1; 1509 /* Set the compression method */ 1510 cbuf[1] = 0; 1511 png_write_chunk_data(png_ptr, cbuf, (png_size_t)2); 1512 1513 cbuf[0] = 0; 1514 png_write_chunk_data(png_ptr, (new_lang ? (png_bytep)new_lang : cbuf), 1515 (png_size_t)(lang_len + 1)); 1516 png_write_chunk_data(png_ptr, (lang_key ? (png_bytep)lang_key : cbuf), 1517 (png_size_t)(lang_key_len + 1)); 1518 png_write_compressed_data_out(png_ptr, &comp); 1519 1520 png_write_chunk_end(png_ptr); 1521 png_free(png_ptr, new_key); 1522 png_free(png_ptr, new_lang); 1523} 1524#endif 1525 1526#ifdef PNG_WRITE_oFFs_SUPPORTED 1527/* Write the oFFs chunk */ 1528void /* PRIVATE */ 1529png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset, 1530 int unit_type) 1531{ 1532 PNG_oFFs; 1533 png_byte buf[9]; 1534 1535 png_debug(1, "in png_write_oFFs"); 1536 1537 if (unit_type >= PNG_OFFSET_LAST) 1538 png_warning(png_ptr, "Unrecognized unit type for oFFs chunk"); 1539 1540 png_save_int_32(buf, x_offset); 1541 png_save_int_32(buf + 4, y_offset); 1542 buf[8] = (png_byte)unit_type; 1543 1544 png_write_chunk(png_ptr, (png_bytep)png_oFFs, buf, (png_size_t)9); 1545} 1546#endif 1547#ifdef PNG_WRITE_pCAL_SUPPORTED 1548/* Write the pCAL chunk (described in the PNG extensions document) */ 1549void /* PRIVATE */ 1550png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0, 1551 png_int_32 X1, int type, int nparams, png_charp units, png_charpp params) 1552{ 1553 PNG_pCAL; 1554 png_size_t purpose_len, units_len, total_len; 1555 png_uint_32p params_len; 1556 png_byte buf[10]; 1557 png_charp new_purpose; 1558 int i; 1559 1560 png_debug1(1, "in png_write_pCAL (%d parameters)", nparams); 1561 1562 if (type >= PNG_EQUATION_LAST) 1563 png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); 1564 1565 purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1; 1566 png_debug1(3, "pCAL purpose length = %d", (int)purpose_len); 1567 units_len = png_strlen(units) + (nparams == 0 ? 0 : 1); 1568 png_debug1(3, "pCAL units length = %d", (int)units_len); 1569 total_len = purpose_len + units_len + 10; 1570 1571 params_len = (png_uint_32p)png_malloc(png_ptr, 1572 (png_alloc_size_t)(nparams * png_sizeof(png_uint_32))); 1573 1574 /* Find the length of each parameter, making sure we don't count the 1575 null terminator for the last parameter. */ 1576 for (i = 0; i < nparams; i++) 1577 { 1578 params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1); 1579 png_debug2(3, "pCAL parameter %d length = %lu", i, 1580 (unsigned long) params_len[i]); 1581 total_len += (png_size_t)params_len[i]; 1582 } 1583 1584 png_debug1(3, "pCAL total length = %d", (int)total_len); 1585 png_write_chunk_start(png_ptr, (png_bytep)png_pCAL, (png_uint_32)total_len); 1586 png_write_chunk_data(png_ptr, (png_bytep)new_purpose, 1587 (png_size_t)purpose_len); 1588 png_save_int_32(buf, X0); 1589 png_save_int_32(buf + 4, X1); 1590 buf[8] = (png_byte)type; 1591 buf[9] = (png_byte)nparams; 1592 png_write_chunk_data(png_ptr, buf, (png_size_t)10); 1593 png_write_chunk_data(png_ptr, (png_bytep)units, (png_size_t)units_len); 1594 1595 png_free(png_ptr, new_purpose); 1596 1597 for (i = 0; i < nparams; i++) 1598 { 1599 png_write_chunk_data(png_ptr, (png_bytep)params[i], 1600 (png_size_t)params_len[i]); 1601 } 1602 1603 png_free(png_ptr, params_len); 1604 png_write_chunk_end(png_ptr); 1605} 1606#endif 1607 1608#ifdef PNG_WRITE_sCAL_SUPPORTED 1609/* Write the sCAL chunk */ 1610#if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) 1611void /* PRIVATE */ 1612png_write_sCAL(png_structp png_ptr, int unit, double width, double height) 1613{ 1614 PNG_sCAL; 1615 char buf[64]; 1616 png_size_t total_len; 1617 1618 png_debug(1, "in png_write_sCAL"); 1619 1620 buf[0] = (char)unit; 1621 png_snprintf(buf + 1, 63, "%12.12e", width); 1622 total_len = 1 + png_strlen(buf + 1) + 1; 1623 png_snprintf(buf + total_len, 64-total_len, "%12.12e", height); 1624 total_len += png_strlen(buf + total_len); 1625 1626 png_debug1(3, "sCAL total length = %u", (unsigned int)total_len); 1627 png_write_chunk(png_ptr, (png_bytep)png_sCAL, (png_bytep)buf, total_len); 1628} 1629#else 1630#ifdef PNG_FIXED_POINT_SUPPORTED 1631void /* PRIVATE */ 1632png_write_sCAL_s(png_structp png_ptr, int unit, png_charp width, 1633 png_charp height) 1634{ 1635 PNG_sCAL; 1636 png_byte buf[64]; 1637 png_size_t wlen, hlen, total_len; 1638 1639 png_debug(1, "in png_write_sCAL_s"); 1640 1641 wlen = png_strlen(width); 1642 hlen = png_strlen(height); 1643 total_len = wlen + hlen + 2; 1644 if (total_len > 64) 1645 { 1646 png_warning(png_ptr, "Can't write sCAL (buffer too small)"); 1647 return; 1648 } 1649 1650 buf[0] = (png_byte)unit; 1651 png_memcpy(buf + 1, width, wlen + 1); /* Append the '\0' here */ 1652 png_memcpy(buf + wlen + 2, height, hlen); /* Do NOT append the '\0' here */ 1653 1654 png_debug1(3, "sCAL total length = %u", (unsigned int)total_len); 1655 png_write_chunk(png_ptr, (png_bytep)png_sCAL, buf, total_len); 1656} 1657#endif 1658#endif 1659#endif 1660 1661#ifdef PNG_WRITE_pHYs_SUPPORTED 1662/* Write the pHYs chunk */ 1663void /* PRIVATE */ 1664png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit, 1665 png_uint_32 y_pixels_per_unit, 1666 int unit_type) 1667{ 1668 PNG_pHYs; 1669 png_byte buf[9]; 1670 1671 png_debug(1, "in png_write_pHYs"); 1672 1673 if (unit_type >= PNG_RESOLUTION_LAST) 1674 png_warning(png_ptr, "Unrecognized unit type for pHYs chunk"); 1675 1676 png_save_uint_32(buf, x_pixels_per_unit); 1677 png_save_uint_32(buf + 4, y_pixels_per_unit); 1678 buf[8] = (png_byte)unit_type; 1679 1680 png_write_chunk(png_ptr, (png_bytep)png_pHYs, buf, (png_size_t)9); 1681} 1682#endif 1683 1684#ifdef PNG_WRITE_tIME_SUPPORTED 1685/* Write the tIME chunk. Use either png_convert_from_struct_tm() 1686 * or png_convert_from_time_t(), or fill in the structure yourself. 1687 */ 1688void /* PRIVATE */ 1689png_write_tIME(png_structp png_ptr, png_timep mod_time) 1690{ 1691 PNG_tIME; 1692 png_byte buf[7]; 1693 1694 png_debug(1, "in png_write_tIME"); 1695 1696 if (mod_time->month > 12 || mod_time->month < 1 || 1697 mod_time->day > 31 || mod_time->day < 1 || 1698 mod_time->hour > 23 || mod_time->second > 60) 1699 { 1700 png_warning(png_ptr, "Invalid time specified for tIME chunk"); 1701 return; 1702 } 1703 1704 png_save_uint_16(buf, mod_time->year); 1705 buf[2] = mod_time->month; 1706 buf[3] = mod_time->day; 1707 buf[4] = mod_time->hour; 1708 buf[5] = mod_time->minute; 1709 buf[6] = mod_time->second; 1710 1711 png_write_chunk(png_ptr, (png_bytep)png_tIME, buf, (png_size_t)7); 1712} 1713#endif 1714 1715/* Initializes the row writing capability of libpng */ 1716void /* PRIVATE */ 1717png_write_start_row(png_structp png_ptr) 1718{ 1719#ifdef PNG_WRITE_INTERLACING_SUPPORTED 1720 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ 1721 1722 /* Start of interlace block */ 1723 int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; 1724 1725 /* Offset to next interlace block */ 1726 int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; 1727 1728 /* Start of interlace block in the y direction */ 1729 int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; 1730 1731 /* Offset to next interlace block in the y direction */ 1732 int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; 1733#endif 1734 1735 png_size_t buf_size; 1736 1737 png_debug(1, "in png_write_start_row"); 1738 1739 buf_size = (png_size_t)(PNG_ROWBYTES( 1740 png_ptr->usr_channels*png_ptr->usr_bit_depth, png_ptr->width) + 1); 1741 1742 /* Set up row buffer */ 1743 png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, 1744 (png_alloc_size_t)buf_size); 1745 png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE; 1746 1747#ifdef PNG_WRITE_FILTER_SUPPORTED 1748 /* Set up filtering buffer, if using this filter */ 1749 if (png_ptr->do_filter & PNG_FILTER_SUB) 1750 { 1751 png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, 1752 (png_alloc_size_t)(png_ptr->rowbytes + 1)); 1753 png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; 1754 } 1755 1756 /* We only need to keep the previous row if we are using one of these. */ 1757 if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) 1758 { 1759 /* Set up previous row buffer */ 1760 png_ptr->prev_row = (png_bytep)png_calloc(png_ptr, 1761 (png_alloc_size_t)buf_size); 1762 1763 if (png_ptr->do_filter & PNG_FILTER_UP) 1764 { 1765 png_ptr->up_row = (png_bytep)png_malloc(png_ptr, 1766 (png_size_t)(png_ptr->rowbytes + 1)); 1767 png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; 1768 } 1769 1770 if (png_ptr->do_filter & PNG_FILTER_AVG) 1771 { 1772 png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, 1773 (png_alloc_size_t)(png_ptr->rowbytes + 1)); 1774 png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; 1775 } 1776 1777 if (png_ptr->do_filter & PNG_FILTER_PAETH) 1778 { 1779 png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, 1780 (png_size_t)(png_ptr->rowbytes + 1)); 1781 png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; 1782 } 1783 } 1784#endif /* PNG_WRITE_FILTER_SUPPORTED */ 1785 1786#ifdef PNG_WRITE_INTERLACING_SUPPORTED 1787 /* If interlaced, we need to set up width and height of pass */ 1788 if (png_ptr->interlaced) 1789 { 1790 if (!(png_ptr->transformations & PNG_INTERLACE)) 1791 { 1792 png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - 1793 png_pass_ystart[0]) / png_pass_yinc[0]; 1794 png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 - 1795 png_pass_start[0]) / png_pass_inc[0]; 1796 } 1797 else 1798 { 1799 png_ptr->num_rows = png_ptr->height; 1800 png_ptr->usr_width = png_ptr->width; 1801 } 1802 } 1803 else 1804#endif 1805 { 1806 png_ptr->num_rows = png_ptr->height; 1807 png_ptr->usr_width = png_ptr->width; 1808 } 1809 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; 1810 png_ptr->zstream.next_out = png_ptr->zbuf; 1811} 1812 1813/* Internal use only. Called when finished processing a row of data. */ 1814void /* PRIVATE */ 1815png_write_finish_row(png_structp png_ptr) 1816{ 1817#ifdef PNG_WRITE_INTERLACING_SUPPORTED 1818 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ 1819 1820 /* Start of interlace block */ 1821 int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; 1822 1823 /* Offset to next interlace block */ 1824 int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; 1825 1826 /* Start of interlace block in the y direction */ 1827 int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; 1828 1829 /* Offset to next interlace block in the y direction */ 1830 int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; 1831#endif 1832 1833 int ret; 1834 1835 png_debug(1, "in png_write_finish_row"); 1836 1837 /* Next row */ 1838 png_ptr->row_number++; 1839 1840 /* See if we are done */ 1841 if (png_ptr->row_number < png_ptr->num_rows) 1842 return; 1843 1844#ifdef PNG_WRITE_INTERLACING_SUPPORTED 1845 /* If interlaced, go to next pass */ 1846 if (png_ptr->interlaced) 1847 { 1848 png_ptr->row_number = 0; 1849 if (png_ptr->transformations & PNG_INTERLACE) 1850 { 1851 png_ptr->pass++; 1852 } 1853 else 1854 { 1855 /* Loop until we find a non-zero width or height pass */ 1856 do 1857 { 1858 png_ptr->pass++; 1859 if (png_ptr->pass >= 7) 1860 break; 1861 png_ptr->usr_width = (png_ptr->width + 1862 png_pass_inc[png_ptr->pass] - 1 - 1863 png_pass_start[png_ptr->pass]) / 1864 png_pass_inc[png_ptr->pass]; 1865 png_ptr->num_rows = (png_ptr->height + 1866 png_pass_yinc[png_ptr->pass] - 1 - 1867 png_pass_ystart[png_ptr->pass]) / 1868 png_pass_yinc[png_ptr->pass]; 1869 if (png_ptr->transformations & PNG_INTERLACE) 1870 break; 1871 } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0); 1872 1873 } 1874 1875 /* Reset the row above the image for the next pass */ 1876 if (png_ptr->pass < 7) 1877 { 1878 if (png_ptr->prev_row != NULL) 1879 png_memset(png_ptr->prev_row, 0, 1880 (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels* 1881 png_ptr->usr_bit_depth, png_ptr->width)) + 1); 1882 return; 1883 } 1884 } 1885#endif 1886 1887 /* If we get here, we've just written the last row, so we need 1888 to flush the compressor */ 1889 do 1890 { 1891 /* Tell the compressor we are done */ 1892 ret = deflate(&png_ptr->zstream, Z_FINISH); 1893 /* Check for an error */ 1894 if (ret == Z_OK) 1895 { 1896 /* Check to see if we need more room */ 1897 if (!(png_ptr->zstream.avail_out)) 1898 { 1899 png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); 1900 png_ptr->zstream.next_out = png_ptr->zbuf; 1901 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; 1902 } 1903 } 1904 else if (ret != Z_STREAM_END) 1905 { 1906 if (png_ptr->zstream.msg != NULL) 1907 png_error(png_ptr, png_ptr->zstream.msg); 1908 else 1909 png_error(png_ptr, "zlib error"); 1910 } 1911 } while (ret != Z_STREAM_END); 1912 1913 /* Write any extra space */ 1914 if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) 1915 { 1916 png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size - 1917 png_ptr->zstream.avail_out); 1918 } 1919 1920 deflateReset(&png_ptr->zstream); 1921 png_ptr->zstream.data_type = Z_BINARY; 1922} 1923 1924#ifdef PNG_WRITE_INTERLACING_SUPPORTED 1925/* Pick out the correct pixels for the interlace pass. 1926 * The basic idea here is to go through the row with a source 1927 * pointer and a destination pointer (sp and dp), and copy the 1928 * correct pixels for the pass. As the row gets compacted, 1929 * sp will always be >= dp, so we should never overwrite anything. 1930 * See the default: case for the easiest code to understand. 1931 */ 1932void /* PRIVATE */ 1933png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) 1934{ 1935 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ 1936 1937 /* Start of interlace block */ 1938 int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; 1939 1940 /* Offset to next interlace block */ 1941 int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; 1942 1943 png_debug(1, "in png_do_write_interlace"); 1944 1945 /* We don't have to do anything on the last pass (6) */ 1946 if (pass < 6) 1947 { 1948 /* Each pixel depth is handled separately */ 1949 switch (row_info->pixel_depth) 1950 { 1951 case 1: 1952 { 1953 png_bytep sp; 1954 png_bytep dp; 1955 int shift; 1956 int d; 1957 int value; 1958 png_uint_32 i; 1959 png_uint_32 row_width = row_info->width; 1960 1961 dp = row; 1962 d = 0; 1963 shift = 7; 1964 for (i = png_pass_start[pass]; i < row_width; 1965 i += png_pass_inc[pass]) 1966 { 1967 sp = row + (png_size_t)(i >> 3); 1968 value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01; 1969 d |= (value << shift); 1970 1971 if (shift == 0) 1972 { 1973 shift = 7; 1974 *dp++ = (png_byte)d; 1975 d = 0; 1976 } 1977 else 1978 shift--; 1979 1980 } 1981 if (shift != 7) 1982 *dp = (png_byte)d; 1983 break; 1984 } 1985 case 2: 1986 { 1987 png_bytep sp; 1988 png_bytep dp; 1989 int shift; 1990 int d; 1991 int value; 1992 png_uint_32 i; 1993 png_uint_32 row_width = row_info->width; 1994 1995 dp = row; 1996 shift = 6; 1997 d = 0; 1998 for (i = png_pass_start[pass]; i < row_width; 1999 i += png_pass_inc[pass]) 2000 { 2001 sp = row + (png_size_t)(i >> 2); 2002 value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03; 2003 d |= (value << shift); 2004 2005 if (shift == 0) 2006 { 2007 shift = 6; 2008 *dp++ = (png_byte)d; 2009 d = 0; 2010 } 2011 else 2012 shift -= 2; 2013 } 2014 if (shift != 6) 2015 *dp = (png_byte)d; 2016 break; 2017 } 2018 case 4: 2019 { 2020 png_bytep sp; 2021 png_bytep dp; 2022 int shift; 2023 int d; 2024 int value; 2025 png_uint_32 i; 2026 png_uint_32 row_width = row_info->width; 2027 2028 dp = row; 2029 shift = 4; 2030 d = 0; 2031 for (i = png_pass_start[pass]; i < row_width; 2032 i += png_pass_inc[pass]) 2033 { 2034 sp = row + (png_size_t)(i >> 1); 2035 value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f; 2036 d |= (value << shift); 2037 2038 if (shift == 0) 2039 { 2040 shift = 4; 2041 *dp++ = (png_byte)d; 2042 d = 0; 2043 } 2044 else 2045 shift -= 4; 2046 } 2047 if (shift != 4) 2048 *dp = (png_byte)d; 2049 break; 2050 } 2051 default: 2052 { 2053 png_bytep sp; 2054 png_bytep dp; 2055 png_uint_32 i; 2056 png_uint_32 row_width = row_info->width; 2057 png_size_t pixel_bytes; 2058 2059 /* Start at the beginning */ 2060 dp = row; 2061 /* Find out how many bytes each pixel takes up */ 2062 pixel_bytes = (row_info->pixel_depth >> 3); 2063 /* Loop through the row, only looking at the pixels that 2064 matter */ 2065 for (i = png_pass_start[pass]; i < row_width; 2066 i += png_pass_inc[pass]) 2067 { 2068 /* Find out where the original pixel is */ 2069 sp = row + (png_size_t)i * pixel_bytes; 2070 /* Move the pixel */ 2071 if (dp != sp) 2072 png_memcpy(dp, sp, pixel_bytes); 2073 /* Next pixel */ 2074 dp += pixel_bytes; 2075 } 2076 break; 2077 } 2078 } 2079 /* Set new row width */ 2080 row_info->width = (row_info->width + 2081 png_pass_inc[pass] - 1 - 2082 png_pass_start[pass]) / 2083 png_pass_inc[pass]; 2084 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, 2085 row_info->width); 2086 } 2087} 2088#endif 2089 2090/* This filters the row, chooses which filter to use, if it has not already 2091 * been specified by the application, and then writes the row out with the 2092 * chosen filter. 2093 */ 2094#define PNG_MAXSUM (((png_uint_32)(-1)) >> 1) 2095#define PNG_HISHIFT 10 2096#define PNG_LOMASK ((png_uint_32)0xffffL) 2097#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT)) 2098void /* PRIVATE */ 2099png_write_find_filter(png_structp png_ptr, png_row_infop row_info) 2100{ 2101 png_bytep best_row; 2102#ifdef PNG_WRITE_FILTER_SUPPORTED 2103 png_bytep prev_row, row_buf; 2104 png_uint_32 mins, bpp; 2105 png_byte filter_to_do = png_ptr->do_filter; 2106 png_uint_32 row_bytes = row_info->rowbytes; 2107#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 2108 int num_p_filters = (int)png_ptr->num_prev_filters; 2109#endif 2110 2111 png_debug(1, "in png_write_find_filter"); 2112 2113#ifndef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 2114 if (png_ptr->row_number == 0 && filter_to_do == PNG_ALL_FILTERS) 2115 { 2116 /* These will never be selected so we need not test them. */ 2117 filter_to_do &= ~(PNG_FILTER_UP | PNG_FILTER_PAETH); 2118 } 2119#endif 2120 2121 /* Find out how many bytes offset each pixel is */ 2122 bpp = (row_info->pixel_depth + 7) >> 3; 2123 2124 prev_row = png_ptr->prev_row; 2125#endif 2126 best_row = png_ptr->row_buf; 2127#ifdef PNG_WRITE_FILTER_SUPPORTED 2128 row_buf = best_row; 2129 mins = PNG_MAXSUM; 2130 2131 /* The prediction method we use is to find which method provides the 2132 * smallest value when summing the absolute values of the distances 2133 * from zero, using anything >= 128 as negative numbers. This is known 2134 * as the "minimum sum of absolute differences" heuristic. Other 2135 * heuristics are the "weighted minimum sum of absolute differences" 2136 * (experimental and can in theory improve compression), and the "zlib 2137 * predictive" method (not implemented yet), which does test compressions 2138 * of lines using different filter methods, and then chooses the 2139 * (series of) filter(s) that give minimum compressed data size (VERY 2140 * computationally expensive). 2141 * 2142 * GRR 980525: consider also 2143 * (1) minimum sum of absolute differences from running average (i.e., 2144 * keep running sum of non-absolute differences & count of bytes) 2145 * [track dispersion, too? restart average if dispersion too large?] 2146 * (1b) minimum sum of absolute differences from sliding average, probably 2147 * with window size <= deflate window (usually 32K) 2148 * (2) minimum sum of squared differences from zero or running average 2149 * (i.e., ~ root-mean-square approach) 2150 */ 2151 2152 2153 /* We don't need to test the 'no filter' case if this is the only filter 2154 * that has been chosen, as it doesn't actually do anything to the data. 2155 */ 2156 if ((filter_to_do & PNG_FILTER_NONE) && 2157 filter_to_do != PNG_FILTER_NONE) 2158 { 2159 png_bytep rp; 2160 png_uint_32 sum = 0; 2161 png_uint_32 i; 2162 int v; 2163 2164 for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) 2165 { 2166 v = *rp; 2167 sum += (v < 128) ? v : 256 - v; 2168 } 2169 2170#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 2171 if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) 2172 { 2173 png_uint_32 sumhi, sumlo; 2174 int j; 2175 sumlo = sum & PNG_LOMASK; 2176 sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */ 2177 2178 /* Reduce the sum if we match any of the previous rows */ 2179 for (j = 0; j < num_p_filters; j++) 2180 { 2181 if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) 2182 { 2183 sumlo = (sumlo * png_ptr->filter_weights[j]) >> 2184 PNG_WEIGHT_SHIFT; 2185 sumhi = (sumhi * png_ptr->filter_weights[j]) >> 2186 PNG_WEIGHT_SHIFT; 2187 } 2188 } 2189 2190 /* Factor in the cost of this filter (this is here for completeness, 2191 * but it makes no sense to have a "cost" for the NONE filter, as 2192 * it has the minimum possible computational cost - none). 2193 */ 2194 sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> 2195 PNG_COST_SHIFT; 2196 sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> 2197 PNG_COST_SHIFT; 2198 2199 if (sumhi > PNG_HIMASK) 2200 sum = PNG_MAXSUM; 2201 else 2202 sum = (sumhi << PNG_HISHIFT) + sumlo; 2203 } 2204#endif 2205 mins = sum; 2206 } 2207 2208 /* Sub filter */ 2209 if (filter_to_do == PNG_FILTER_SUB) 2210 /* It's the only filter so no testing is needed */ 2211 { 2212 png_bytep rp, lp, dp; 2213 png_uint_32 i; 2214 for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; 2215 i++, rp++, dp++) 2216 { 2217 *dp = *rp; 2218 } 2219 for (lp = row_buf + 1; i < row_bytes; 2220 i++, rp++, lp++, dp++) 2221 { 2222 *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); 2223 } 2224 best_row = png_ptr->sub_row; 2225 } 2226 2227 else if (filter_to_do & PNG_FILTER_SUB) 2228 { 2229 png_bytep rp, dp, lp; 2230 png_uint_32 sum = 0, lmins = mins; 2231 png_uint_32 i; 2232 int v; 2233 2234#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 2235 /* We temporarily increase the "minimum sum" by the factor we 2236 * would reduce the sum of this filter, so that we can do the 2237 * early exit comparison without scaling the sum each time. 2238 */ 2239 if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) 2240 { 2241 int j; 2242 png_uint_32 lmhi, lmlo; 2243 lmlo = lmins & PNG_LOMASK; 2244 lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; 2245 2246 for (j = 0; j < num_p_filters; j++) 2247 { 2248 if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) 2249 { 2250 lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> 2251 PNG_WEIGHT_SHIFT; 2252 lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> 2253 PNG_WEIGHT_SHIFT; 2254 } 2255 } 2256 2257 lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> 2258 PNG_COST_SHIFT; 2259 lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> 2260 PNG_COST_SHIFT; 2261 2262 if (lmhi > PNG_HIMASK) 2263 lmins = PNG_MAXSUM; 2264 else 2265 lmins = (lmhi << PNG_HISHIFT) + lmlo; 2266 } 2267#endif 2268 2269 for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; 2270 i++, rp++, dp++) 2271 { 2272 v = *dp = *rp; 2273 2274 sum += (v < 128) ? v : 256 - v; 2275 } 2276 for (lp = row_buf + 1; i < row_bytes; 2277 i++, rp++, lp++, dp++) 2278 { 2279 v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); 2280 2281 sum += (v < 128) ? v : 256 - v; 2282 2283 if (sum > lmins) /* We are already worse, don't continue. */ 2284 break; 2285 } 2286 2287#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 2288 if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) 2289 { 2290 int j; 2291 png_uint_32 sumhi, sumlo; 2292 sumlo = sum & PNG_LOMASK; 2293 sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; 2294 2295 for (j = 0; j < num_p_filters; j++) 2296 { 2297 if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) 2298 { 2299 sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >> 2300 PNG_WEIGHT_SHIFT; 2301 sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >> 2302 PNG_WEIGHT_SHIFT; 2303 } 2304 } 2305 2306 sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> 2307 PNG_COST_SHIFT; 2308 sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> 2309 PNG_COST_SHIFT; 2310 2311 if (sumhi > PNG_HIMASK) 2312 sum = PNG_MAXSUM; 2313 else 2314 sum = (sumhi << PNG_HISHIFT) + sumlo; 2315 } 2316#endif 2317 2318 if (sum < mins) 2319 { 2320 mins = sum; 2321 best_row = png_ptr->sub_row; 2322 } 2323 } 2324 2325 /* Up filter */ 2326 if (filter_to_do == PNG_FILTER_UP) 2327 { 2328 png_bytep rp, dp, pp; 2329 png_uint_32 i; 2330 2331 for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, 2332 pp = prev_row + 1; i < row_bytes; 2333 i++, rp++, pp++, dp++) 2334 { 2335 *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); 2336 } 2337 best_row = png_ptr->up_row; 2338 } 2339 2340 else if (filter_to_do & PNG_FILTER_UP) 2341 { 2342 png_bytep rp, dp, pp; 2343 png_uint_32 sum = 0, lmins = mins; 2344 png_uint_32 i; 2345 int v; 2346 2347 2348#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 2349 if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) 2350 { 2351 int j; 2352 png_uint_32 lmhi, lmlo; 2353 lmlo = lmins & PNG_LOMASK; 2354 lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; 2355 2356 for (j = 0; j < num_p_filters; j++) 2357 { 2358 if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) 2359 { 2360 lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> 2361 PNG_WEIGHT_SHIFT; 2362 lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> 2363 PNG_WEIGHT_SHIFT; 2364 } 2365 } 2366 2367 lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> 2368 PNG_COST_SHIFT; 2369 lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> 2370 PNG_COST_SHIFT; 2371 2372 if (lmhi > PNG_HIMASK) 2373 lmins = PNG_MAXSUM; 2374 else 2375 lmins = (lmhi << PNG_HISHIFT) + lmlo; 2376 } 2377#endif 2378 2379 for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, 2380 pp = prev_row + 1; i < row_bytes; i++) 2381 { 2382 v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); 2383 2384 sum += (v < 128) ? v : 256 - v; 2385 2386 if (sum > lmins) /* We are already worse, don't continue. */ 2387 break; 2388 } 2389 2390#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 2391 if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) 2392 { 2393 int j; 2394 png_uint_32 sumhi, sumlo; 2395 sumlo = sum & PNG_LOMASK; 2396 sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; 2397 2398 for (j = 0; j < num_p_filters; j++) 2399 { 2400 if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) 2401 { 2402 sumlo = (sumlo * png_ptr->filter_weights[j]) >> 2403 PNG_WEIGHT_SHIFT; 2404 sumhi = (sumhi * png_ptr->filter_weights[j]) >> 2405 PNG_WEIGHT_SHIFT; 2406 } 2407 } 2408 2409 sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> 2410 PNG_COST_SHIFT; 2411 sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> 2412 PNG_COST_SHIFT; 2413 2414 if (sumhi > PNG_HIMASK) 2415 sum = PNG_MAXSUM; 2416 else 2417 sum = (sumhi << PNG_HISHIFT) + sumlo; 2418 } 2419#endif 2420 2421 if (sum < mins) 2422 { 2423 mins = sum; 2424 best_row = png_ptr->up_row; 2425 } 2426 } 2427 2428 /* Avg filter */ 2429 if (filter_to_do == PNG_FILTER_AVG) 2430 { 2431 png_bytep rp, dp, pp, lp; 2432 png_uint_32 i; 2433 for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, 2434 pp = prev_row + 1; i < bpp; i++) 2435 { 2436 *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); 2437 } 2438 for (lp = row_buf + 1; i < row_bytes; i++) 2439 { 2440 *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) 2441 & 0xff); 2442 } 2443 best_row = png_ptr->avg_row; 2444 } 2445 2446 else if (filter_to_do & PNG_FILTER_AVG) 2447 { 2448 png_bytep rp, dp, pp, lp; 2449 png_uint_32 sum = 0, lmins = mins; 2450 png_uint_32 i; 2451 int v; 2452 2453#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 2454 if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) 2455 { 2456 int j; 2457 png_uint_32 lmhi, lmlo; 2458 lmlo = lmins & PNG_LOMASK; 2459 lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; 2460 2461 for (j = 0; j < num_p_filters; j++) 2462 { 2463 if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG) 2464 { 2465 lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> 2466 PNG_WEIGHT_SHIFT; 2467 lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> 2468 PNG_WEIGHT_SHIFT; 2469 } 2470 } 2471 2472 lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> 2473 PNG_COST_SHIFT; 2474 lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> 2475 PNG_COST_SHIFT; 2476 2477 if (lmhi > PNG_HIMASK) 2478 lmins = PNG_MAXSUM; 2479 else 2480 lmins = (lmhi << PNG_HISHIFT) + lmlo; 2481 } 2482#endif 2483 2484 for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, 2485 pp = prev_row + 1; i < bpp; i++) 2486 { 2487 v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); 2488 2489 sum += (v < 128) ? v : 256 - v; 2490 } 2491 for (lp = row_buf + 1; i < row_bytes; i++) 2492 { 2493 v = *dp++ = 2494 (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff); 2495 2496 sum += (v < 128) ? v : 256 - v; 2497 2498 if (sum > lmins) /* We are already worse, don't continue. */ 2499 break; 2500 } 2501 2502#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 2503 if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) 2504 { 2505 int j; 2506 png_uint_32 sumhi, sumlo; 2507 sumlo = sum & PNG_LOMASK; 2508 sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; 2509 2510 for (j = 0; j < num_p_filters; j++) 2511 { 2512 if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) 2513 { 2514 sumlo = (sumlo * png_ptr->filter_weights[j]) >> 2515 PNG_WEIGHT_SHIFT; 2516 sumhi = (sumhi * png_ptr->filter_weights[j]) >> 2517 PNG_WEIGHT_SHIFT; 2518 } 2519 } 2520 2521 sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> 2522 PNG_COST_SHIFT; 2523 sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> 2524 PNG_COST_SHIFT; 2525 2526 if (sumhi > PNG_HIMASK) 2527 sum = PNG_MAXSUM; 2528 else 2529 sum = (sumhi << PNG_HISHIFT) + sumlo; 2530 } 2531#endif 2532 2533 if (sum < mins) 2534 { 2535 mins = sum; 2536 best_row = png_ptr->avg_row; 2537 } 2538 } 2539 2540 /* Paeth filter */ 2541 if (filter_to_do == PNG_FILTER_PAETH) 2542 { 2543 png_bytep rp, dp, pp, cp, lp; 2544 png_uint_32 i; 2545 for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, 2546 pp = prev_row + 1; i < bpp; i++) 2547 { 2548 *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); 2549 } 2550 2551 for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) 2552 { 2553 int a, b, c, pa, pb, pc, p; 2554 2555 b = *pp++; 2556 c = *cp++; 2557 a = *lp++; 2558 2559 p = b - c; 2560 pc = a - c; 2561 2562#ifdef PNG_USE_ABS 2563 pa = abs(p); 2564 pb = abs(pc); 2565 pc = abs(p + pc); 2566#else 2567 pa = p < 0 ? -p : p; 2568 pb = pc < 0 ? -pc : pc; 2569 pc = (p + pc) < 0 ? -(p + pc) : p + pc; 2570#endif 2571 2572 p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; 2573 2574 *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); 2575 } 2576 best_row = png_ptr->paeth_row; 2577 } 2578 2579 else if (filter_to_do & PNG_FILTER_PAETH) 2580 { 2581 png_bytep rp, dp, pp, cp, lp; 2582 png_uint_32 sum = 0, lmins = mins; 2583 png_uint_32 i; 2584 int v; 2585 2586#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 2587 if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) 2588 { 2589 int j; 2590 png_uint_32 lmhi, lmlo; 2591 lmlo = lmins & PNG_LOMASK; 2592 lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; 2593 2594 for (j = 0; j < num_p_filters; j++) 2595 { 2596 if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) 2597 { 2598 lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> 2599 PNG_WEIGHT_SHIFT; 2600 lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> 2601 PNG_WEIGHT_SHIFT; 2602 } 2603 } 2604 2605 lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> 2606 PNG_COST_SHIFT; 2607 lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> 2608 PNG_COST_SHIFT; 2609 2610 if (lmhi > PNG_HIMASK) 2611 lmins = PNG_MAXSUM; 2612 else 2613 lmins = (lmhi << PNG_HISHIFT) + lmlo; 2614 } 2615#endif 2616 2617 for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, 2618 pp = prev_row + 1; i < bpp; i++) 2619 { 2620 v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); 2621 2622 sum += (v < 128) ? v : 256 - v; 2623 } 2624 2625 for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) 2626 { 2627 int a, b, c, pa, pb, pc, p; 2628 2629 b = *pp++; 2630 c = *cp++; 2631 a = *lp++; 2632 2633#ifndef PNG_SLOW_PAETH 2634 p = b - c; 2635 pc = a - c; 2636#ifdef PNG_USE_ABS 2637 pa = abs(p); 2638 pb = abs(pc); 2639 pc = abs(p + pc); 2640#else 2641 pa = p < 0 ? -p : p; 2642 pb = pc < 0 ? -pc : pc; 2643 pc = (p + pc) < 0 ? -(p + pc) : p + pc; 2644#endif 2645 p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; 2646#else /* PNG_SLOW_PAETH */ 2647 p = a + b - c; 2648 pa = abs(p - a); 2649 pb = abs(p - b); 2650 pc = abs(p - c); 2651 if (pa <= pb && pa <= pc) 2652 p = a; 2653 else if (pb <= pc) 2654 p = b; 2655 else 2656 p = c; 2657#endif /* PNG_SLOW_PAETH */ 2658 2659 v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); 2660 2661 sum += (v < 128) ? v : 256 - v; 2662 2663 if (sum > lmins) /* We are already worse, don't continue. */ 2664 break; 2665 } 2666 2667#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 2668 if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) 2669 { 2670 int j; 2671 png_uint_32 sumhi, sumlo; 2672 sumlo = sum & PNG_LOMASK; 2673 sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; 2674 2675 for (j = 0; j < num_p_filters; j++) 2676 { 2677 if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) 2678 { 2679 sumlo = (sumlo * png_ptr->filter_weights[j]) >> 2680 PNG_WEIGHT_SHIFT; 2681 sumhi = (sumhi * png_ptr->filter_weights[j]) >> 2682 PNG_WEIGHT_SHIFT; 2683 } 2684 } 2685 2686 sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> 2687 PNG_COST_SHIFT; 2688 sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> 2689 PNG_COST_SHIFT; 2690 2691 if (sumhi > PNG_HIMASK) 2692 sum = PNG_MAXSUM; 2693 else 2694 sum = (sumhi << PNG_HISHIFT) + sumlo; 2695 } 2696#endif 2697 2698 if (sum < mins) 2699 { 2700 best_row = png_ptr->paeth_row; 2701 } 2702 } 2703#endif /* PNG_WRITE_FILTER_SUPPORTED */ 2704 /* Do the actual writing of the filtered row data from the chosen filter. */ 2705 2706 png_write_filtered_row(png_ptr, best_row); 2707 2708#ifdef PNG_WRITE_FILTER_SUPPORTED 2709#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 2710 /* Save the type of filter we picked this time for future calculations */ 2711 if (png_ptr->num_prev_filters > 0) 2712 { 2713 int j; 2714 for (j = 1; j < num_p_filters; j++) 2715 { 2716 png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1]; 2717 } 2718 png_ptr->prev_filters[j] = best_row[0]; 2719 } 2720#endif 2721#endif /* PNG_WRITE_FILTER_SUPPORTED */ 2722} 2723 2724 2725/* Do the actual writing of a previously filtered row. */ 2726void /* PRIVATE */ 2727png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row) 2728{ 2729 png_debug(1, "in png_write_filtered_row"); 2730 2731 png_debug1(2, "filter = %d", filtered_row[0]); 2732 /* Set up the zlib input buffer */ 2733 2734 png_ptr->zstream.next_in = filtered_row; 2735 png_ptr->zstream.avail_in = (uInt)png_ptr->row_info.rowbytes + 1; 2736 /* Repeat until we have compressed all the data */ 2737 do 2738 { 2739 int ret; /* Return of zlib */ 2740 2741 /* Compress the data */ 2742 ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); 2743 /* Check for compression errors */ 2744 if (ret != Z_OK) 2745 { 2746 if (png_ptr->zstream.msg != NULL) 2747 png_error(png_ptr, png_ptr->zstream.msg); 2748 else 2749 png_error(png_ptr, "zlib error"); 2750 } 2751 2752 /* See if it is time to write another IDAT */ 2753 if (!(png_ptr->zstream.avail_out)) 2754 { 2755 /* Write the IDAT and reset the zlib output buffer */ 2756 png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); 2757 png_ptr->zstream.next_out = png_ptr->zbuf; 2758 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; 2759 } 2760 /* Repeat until all data has been compressed */ 2761 } while (png_ptr->zstream.avail_in); 2762 2763 /* Swap the current and previous rows */ 2764 if (png_ptr->prev_row != NULL) 2765 { 2766 png_bytep tptr; 2767 2768 tptr = png_ptr->prev_row; 2769 png_ptr->prev_row = png_ptr->row_buf; 2770 png_ptr->row_buf = tptr; 2771 } 2772 2773 /* Finish row - updates counters and flushes zlib if last row */ 2774 png_write_finish_row(png_ptr); 2775 2776#ifdef PNG_WRITE_FLUSH_SUPPORTED 2777 png_ptr->flush_rows++; 2778 2779 if (png_ptr->flush_dist > 0 && 2780 png_ptr->flush_rows >= png_ptr->flush_dist) 2781 { 2782 png_write_flush(png_ptr); 2783 } 2784#endif 2785} 2786#endif /* PNG_WRITE_SUPPORTED */ 2787