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