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