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