1 2 /* pngtest.c - a simple test program to test libpng 3 * 4 * Last changed in libpng 1.2.43 [February 25, 2010] 5 * Copyright (c) 1998-2010 Glenn Randers-Pehrson 6 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) 7 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) 8 * 9 * This code is released under the libpng license. 10 * For conditions of distribution and use, see the disclaimer 11 * and license in png.h 12 * 13 * This program reads in a PNG image, writes it out again, and then 14 * compares the two files. If the files are identical, this shows that 15 * the basic chunk handling, filtering, and (de)compression code is working 16 * properly. It does not currently test all of the transforms, although 17 * it probably should. 18 * 19 * The program will report "FAIL" in certain legitimate cases: 20 * 1) when the compression level or filter selection method is changed. 21 * 2) when the maximum IDAT size (PNG_ZBUF_SIZE in pngconf.h) is not 8192. 22 * 3) unknown unsafe-to-copy ancillary chunks or unknown critical chunks 23 * exist in the input file. 24 * 4) others not listed here... 25 * In these cases, it is best to check with another tool such as "pngcheck" 26 * to see what the differences between the two files are. 27 * 28 * If a filename is given on the command-line, then this file is used 29 * for the input, rather than the default "pngtest.png". This allows 30 * testing a wide variety of files easily. You can also test a number 31 * of files at once by typing "pngtest -m file1.png file2.png ..." 32 */ 33 34 #define PNG_PEDANTIC_WARNINGS 35 #include "png.h" 36 37 #ifdef _WIN32_WCE 38 # if _WIN32_WCE < 211 39 __error__ (f|w)printf functions are not supported on old WindowsCE.; 40 # endif 41 # include <windows.h> 42 # include <stdlib.h> 43 # define READFILE(file, data, length, check) \ 44 if (ReadFile(file, data, length, &check, NULL)) check = 0 45 # define WRITEFILE(file, data, length, check)) \ 46 if (WriteFile(file, data, length, &check, NULL)) check = 0 47 # define FCLOSE(file) CloseHandle(file) 48 #else 49 # include <stdio.h> 50 # include <stdlib.h> 51 # define READFILE(file, data, length, check) \ 52 check=(png_size_t)fread(data, (png_size_t)1, length, file) 53 # define WRITEFILE(file, data, length, check) \ 54 check=(png_size_t)fwrite(data, (png_size_t)1, length, file) 55 # define FCLOSE(file) fclose(file) 56 #endif 57 58 #ifndef PNG_STDIO_SUPPORTED 59 # ifdef _WIN32_WCE 60 typedef HANDLE png_FILE_p; 61 # else 62 typedef FILE * png_FILE_p; 63 # endif 64 #endif 65 66 /* Makes pngtest verbose so we can find problems (needs to be before png.h) */ 67 #ifndef PNG_DEBUG 68 # define PNG_DEBUG 0 69 #endif 70 71 #if !PNG_DEBUG 72 # define SINGLE_ROWBUF_ALLOC /* Makes buffer overruns easier to nail */ 73 #endif 74 75 /* Turn on CPU timing 76 #define PNGTEST_TIMING 77 */ 78 79 #ifndef PNG_FLOATING_POINT_SUPPORTED 80 #undef PNGTEST_TIMING 81 #endif 82 83 #ifdef PNGTEST_TIMING 84 static float t_start, t_stop, t_decode, t_encode, t_misc; 85 #include <time.h> 86 #endif 87 88 #ifdef PNG_TIME_RFC1123_SUPPORTED 89 #define PNG_tIME_STRING_LENGTH 29 90 static int tIME_chunk_present = 0; 91 static char tIME_string[PNG_tIME_STRING_LENGTH] = "tIME chunk is not present"; 92 #endif 93 94 static int verbose = 0; 95 96 int test_one_file PNGARG((PNG_CONST char *inname, PNG_CONST char *outname)); 97 98 #ifdef __TURBOC__ 99 #include <mem.h> 100 #endif 101 102 /* Defined so I can write to a file on gui/windowing platforms */ 103 /* #define STDERR stderr */ 104 #define STDERR stdout /* For DOS */ 105 106 /* In case a system header (e.g., on AIX) defined jmpbuf */ 107 #ifdef jmpbuf 108 # undef jmpbuf 109 #endif 110 111 /* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */ 112 #ifndef png_jmpbuf 113 # define png_jmpbuf(png_ptr) png_ptr->jmpbuf 114 #endif 115 116 /* Example of using row callbacks to make a simple progress meter */ 117 static int status_pass = 1; 118 static int status_dots_requested = 0; 119 static int status_dots = 1; 120 121 void 122 #ifdef PNG_1_0_X 123 PNGAPI 124 #endif 125 read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass); 126 void 127 #ifdef PNG_1_0_X 128 PNGAPI 129 #endif 130 read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) 131 { 132 if (png_ptr == NULL || row_number > PNG_UINT_31_MAX) 133 return; 134 if (status_pass != pass) 135 { 136 fprintf(stdout, "\n Pass %d: ", pass); 137 status_pass = pass; 138 status_dots = 31; 139 } 140 status_dots--; 141 if (status_dots == 0) 142 { 143 fprintf(stdout, "\n "); 144 status_dots=30; 145 } 146 fprintf(stdout, "r"); 147 } 148 149 void 150 #ifdef PNG_1_0_X 151 PNGAPI 152 #endif 153 write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass); 154 void 155 #ifdef PNG_1_0_X 156 PNGAPI 157 #endif 158 write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass) 159 { 160 if (png_ptr == NULL || row_number > PNG_UINT_31_MAX || pass > 7) 161 return; 162 fprintf(stdout, "w"); 163 } 164 165 166 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED 167 /* Example of using user transform callback (we don't transform anything, 168 * but merely examine the row filters. We set this to 256 rather than 169 * 5 in case illegal filter values are present.) 170 */ 171 static png_uint_32 filters_used[256]; 172 void 173 #ifdef PNG_1_0_X 174 PNGAPI 175 #endif 176 count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data); 177 void 178 #ifdef PNG_1_0_X 179 PNGAPI 180 #endif 181 count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data) 182 { 183 if (png_ptr != NULL && row_info != NULL) 184 ++filters_used[*(data - 1)]; 185 } 186 #endif 187 188 #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED 189 /* Example of using user transform callback (we don't transform anything, 190 * but merely count the zero samples) 191 */ 192 193 static png_uint_32 zero_samples; 194 195 void 196 #ifdef PNG_1_0_X 197 PNGAPI 198 #endif 199 count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data); 200 void 201 #ifdef PNG_1_0_X 202 PNGAPI 203 #endif 204 count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data) 205 { 206 png_bytep dp = data; 207 if (png_ptr == NULL)return; 208 209 /* Contents of row_info: 210 * png_uint_32 width width of row 211 * png_uint_32 rowbytes number of bytes in row 212 * png_byte color_type color type of pixels 213 * png_byte bit_depth bit depth of samples 214 * png_byte channels number of channels (1-4) 215 * png_byte pixel_depth bits per pixel (depth*channels) 216 */ 217 218 /* Counts the number of zero samples (or zero pixels if color_type is 3 */ 219 220 if (row_info->color_type == 0 || row_info->color_type == 3) 221 { 222 int pos = 0; 223 png_uint_32 n, nstop; 224 for (n = 0, nstop=row_info->width; n<nstop; n++) 225 { 226 if (row_info->bit_depth == 1) 227 { 228 if (((*dp << pos++ ) & 0x80) == 0) 229 zero_samples++; 230 if (pos == 8) 231 { 232 pos = 0; 233 dp++; 234 } 235 } 236 if (row_info->bit_depth == 2) 237 { 238 if (((*dp << (pos+=2)) & 0xc0) == 0) 239 zero_samples++; 240 if (pos == 8) 241 { 242 pos = 0; 243 dp++; 244 } 245 } 246 if (row_info->bit_depth == 4) 247 { 248 if (((*dp << (pos+=4)) & 0xf0) == 0) 249 zero_samples++; 250 if (pos == 8) 251 { 252 pos = 0; 253 dp++; 254 } 255 } 256 if (row_info->bit_depth == 8) 257 if (*dp++ == 0) 258 zero_samples++; 259 if (row_info->bit_depth == 16) 260 { 261 if ((*dp | *(dp+1)) == 0) 262 zero_samples++; 263 dp+=2; 264 } 265 } 266 } 267 else /* Other color types */ 268 { 269 png_uint_32 n, nstop; 270 int channel; 271 int color_channels = row_info->channels; 272 if (row_info->color_type > 3)color_channels--; 273 274 for (n = 0, nstop=row_info->width; n<nstop; n++) 275 { 276 for (channel = 0; channel < color_channels; channel++) 277 { 278 if (row_info->bit_depth == 8) 279 if (*dp++ == 0) 280 zero_samples++; 281 if (row_info->bit_depth == 16) 282 { 283 if ((*dp | *(dp+1)) == 0) 284 zero_samples++; 285 dp+=2; 286 } 287 } 288 if (row_info->color_type > 3) 289 { 290 dp++; 291 if (row_info->bit_depth == 16) 292 dp++; 293 } 294 } 295 } 296 } 297 #endif /* PNG_WRITE_USER_TRANSFORM_SUPPORTED */ 298 299 static int wrote_question = 0; 300 301 #ifndef PNG_STDIO_SUPPORTED 302 /* START of code to validate stdio-free compilation */ 303 /* These copies of the default read/write functions come from pngrio.c and 304 * pngwio.c. They allow "don't include stdio" testing of the library. 305 * This is the function that does the actual reading of data. If you are 306 * not reading from a standard C stream, you should create a replacement 307 * read_data function and use it at run time with png_set_read_fn(), rather 308 * than changing the library. 309 */ 310 311 #ifndef USE_FAR_KEYWORD 312 static void 313 pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) 314 { 315 png_size_t check = 0; 316 png_voidp io_ptr; 317 318 /* fread() returns 0 on error, so it is OK to store this in a png_size_t 319 * instead of an int, which is what fread() actually returns. 320 */ 321 io_ptr = png_get_io_ptr(png_ptr); 322 if (io_ptr != NULL) 323 { 324 READFILE((png_FILE_p)io_ptr, data, length, check); 325 } 326 327 if (check != length) 328 { 329 png_error(png_ptr, "Read Error!"); 330 } 331 } 332 #else 333 /* This is the model-independent version. Since the standard I/O library 334 can't handle far buffers in the medium and small models, we have to copy 335 the data. 336 */ 337 338 #define NEAR_BUF_SIZE 1024 339 #define MIN(a,b) (a <= b ? a : b) 340 341 static void 342 pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) 343 { 344 int check; 345 png_byte *n_data; 346 png_FILE_p io_ptr; 347 348 /* Check if data really is near. If so, use usual code. */ 349 n_data = (png_byte *)CVT_PTR_NOCHECK(data); 350 io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); 351 if ((png_bytep)n_data == data) 352 { 353 READFILE(io_ptr, n_data, length, check); 354 } 355 else 356 { 357 png_byte buf[NEAR_BUF_SIZE]; 358 png_size_t read, remaining, err; 359 check = 0; 360 remaining = length; 361 do 362 { 363 read = MIN(NEAR_BUF_SIZE, remaining); 364 READFILE(io_ptr, buf, 1, err); 365 png_memcpy(data, buf, read); /* Copy far buffer to near buffer */ 366 if (err != read) 367 break; 368 else 369 check += err; 370 data += read; 371 remaining -= read; 372 } 373 while (remaining != 0); 374 } 375 if (check != length) 376 png_error(png_ptr, "read Error"); 377 } 378 #endif /* USE_FAR_KEYWORD */ 379 380 #ifdef PNG_WRITE_FLUSH_SUPPORTED 381 static void 382 pngtest_flush(png_structp png_ptr) 383 { 384 /* Do nothing; fflush() is said to be just a waste of energy. */ 385 png_ptr = png_ptr; /* Stifle compiler warning */ 386 } 387 #endif 388 389 /* This is the function that does the actual writing of data. If you are 390 * not writing to a standard C stream, you should create a replacement 391 * write_data function and use it at run time with png_set_write_fn(), rather 392 * than changing the library. 393 */ 394 #ifndef USE_FAR_KEYWORD 395 static void 396 pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) 397 { 398 png_uint_32 check; 399 400 WRITEFILE((png_FILE_p)png_ptr->io_ptr, data, length, check); 401 if (check != length) 402 { 403 png_error(png_ptr, "Write Error"); 404 } 405 } 406 #else 407 /* This is the model-independent version. Since the standard I/O library 408 can't handle far buffers in the medium and small models, we have to copy 409 the data. 410 */ 411 412 #define NEAR_BUF_SIZE 1024 413 #define MIN(a,b) (a <= b ? a : b) 414 415 static void 416 pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) 417 { 418 png_uint_32 check; 419 png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */ 420 png_FILE_p io_ptr; 421 422 /* Check if data really is near. If so, use usual code. */ 423 near_data = (png_byte *)CVT_PTR_NOCHECK(data); 424 io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr); 425 if ((png_bytep)near_data == data) 426 { 427 WRITEFILE(io_ptr, near_data, length, check); 428 } 429 else 430 { 431 png_byte buf[NEAR_BUF_SIZE]; 432 png_size_t written, remaining, err; 433 check = 0; 434 remaining = length; 435 do 436 { 437 written = MIN(NEAR_BUF_SIZE, remaining); 438 png_memcpy(buf, data, written); /* Copy far buffer to near buffer */ 439 WRITEFILE(io_ptr, buf, written, err); 440 if (err != written) 441 break; 442 else 443 check += err; 444 data += written; 445 remaining -= written; 446 } 447 while (remaining != 0); 448 } 449 if (check != length) 450 { 451 png_error(png_ptr, "Write Error"); 452 } 453 } 454 #endif /* USE_FAR_KEYWORD */ 455 456 /* This function is called when there is a warning, but the library thinks 457 * it can continue anyway. Replacement functions don't have to do anything 458 * here if you don't want to. In the default configuration, png_ptr is 459 * not used, but it is passed in case it may be useful. 460 */ 461 static void 462 pngtest_warning(png_structp png_ptr, png_const_charp message) 463 { 464 PNG_CONST char *name = "UNKNOWN (ERROR!)"; 465 char *test; 466 test = png_get_error_ptr(png_ptr); 467 if (test == NULL) 468 fprintf(STDERR, "%s: libpng warning: %s\n", name, message); 469 else 470 fprintf(STDERR, "%s: libpng warning: %s\n", test, message); 471 } 472 473 /* This is the default error handling function. Note that replacements for 474 * this function MUST NOT RETURN, or the program will likely crash. This 475 * function is used by default, or if the program supplies NULL for the 476 * error function pointer in png_set_error_fn(). 477 */ 478 static void 479 pngtest_error(png_structp png_ptr, png_const_charp message) 480 { 481 pngtest_warning(png_ptr, message); 482 /* We can return because png_error calls the default handler, which is 483 * actually OK in this case. 484 */ 485 } 486 #endif /* !PNG_STDIO_SUPPORTED */ 487 /* END of code to validate stdio-free compilation */ 488 489 /* START of code to validate memory allocation and deallocation */ 490 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG 491 492 /* Allocate memory. For reasonable files, size should never exceed 493 * 64K. However, zlib may allocate more then 64K if you don't tell 494 * it not to. See zconf.h and png.h for more information. zlib does 495 * need to allocate exactly 64K, so whatever you call here must 496 * have the ability to do that. 497 * 498 * This piece of code can be compiled to validate max 64K allocations 499 * by setting MAXSEG_64K in zlib zconf.h *or* PNG_MAX_MALLOC_64K. 500 */ 501 typedef struct memory_information 502 { 503 png_uint_32 size; 504 png_voidp pointer; 505 struct memory_information FAR *next; 506 } memory_information; 507 typedef memory_information FAR *memory_infop; 508 509 static memory_infop pinformation = NULL; 510 static int current_allocation = 0; 511 static int maximum_allocation = 0; 512 static int total_allocation = 0; 513 static int num_allocations = 0; 514 515 png_voidp png_debug_malloc PNGARG((png_structp png_ptr, png_uint_32 size)); 516 void png_debug_free PNGARG((png_structp png_ptr, png_voidp ptr)); 517 518 png_voidp 519 png_debug_malloc(png_structp png_ptr, png_uint_32 size) 520 { 521 522 /* png_malloc has already tested for NULL; png_create_struct calls 523 * png_debug_malloc directly, with png_ptr == NULL which is OK 524 */ 525 526 if (size == 0) 527 return (NULL); 528 529 /* This calls the library allocator twice, once to get the requested 530 buffer and once to get a new free list entry. */ 531 { 532 /* Disable malloc_fn and free_fn */ 533 memory_infop pinfo; 534 png_set_mem_fn(png_ptr, NULL, NULL, NULL); 535 pinfo = (memory_infop)png_malloc(png_ptr, 536 (png_uint_32)png_sizeof(*pinfo)); 537 pinfo->size = size; 538 current_allocation += size; 539 total_allocation += size; 540 num_allocations ++; 541 if (current_allocation > maximum_allocation) 542 maximum_allocation = current_allocation; 543 pinfo->pointer = (png_voidp)png_malloc(png_ptr, size); 544 /* Restore malloc_fn and free_fn */ 545 png_set_mem_fn(png_ptr, 546 png_voidp_NULL, (png_malloc_ptr)png_debug_malloc, 547 (png_free_ptr)png_debug_free); 548 if (size != 0 && pinfo->pointer == NULL) 549 { 550 current_allocation -= size; 551 total_allocation -= size; 552 png_error(png_ptr, 553 "out of memory in pngtest->png_debug_malloc."); 554 } 555 pinfo->next = pinformation; 556 pinformation = pinfo; 557 /* Make sure the caller isn't assuming zeroed memory. */ 558 png_memset(pinfo->pointer, 0xdd, pinfo->size); 559 if (verbose) 560 printf("png_malloc %lu bytes at %x\n", (unsigned long)size, 561 pinfo->pointer); 562 return (png_voidp)(pinfo->pointer); 563 } 564 } 565 566 /* Free a pointer. It is removed from the list at the same time. */ 567 void 568 png_debug_free(png_structp png_ptr, png_voidp ptr) 569 { 570 if (png_ptr == NULL) 571 fprintf(STDERR, "NULL pointer to png_debug_free.\n"); 572 if (ptr == 0) 573 { 574 #if 0 /* This happens all the time. */ 575 fprintf(STDERR, "WARNING: freeing NULL pointer\n"); 576 #endif 577 return; 578 } 579 580 /* Unlink the element from the list. */ 581 { 582 memory_infop FAR *ppinfo = &pinformation; 583 for (;;) 584 { 585 memory_infop pinfo = *ppinfo; 586 if (pinfo->pointer == ptr) 587 { 588 *ppinfo = pinfo->next; 589 current_allocation -= pinfo->size; 590 if (current_allocation < 0) 591 fprintf(STDERR, "Duplicate free of memory\n"); 592 /* We must free the list element too, but first kill 593 the memory that is to be freed. */ 594 png_memset(ptr, 0x55, pinfo->size); 595 png_free_default(png_ptr, pinfo); 596 pinfo = NULL; 597 break; 598 } 599 if (pinfo->next == NULL) 600 { 601 fprintf(STDERR, "Pointer %x not found\n", (unsigned int)ptr); 602 break; 603 } 604 ppinfo = &pinfo->next; 605 } 606 } 607 608 /* Finally free the data. */ 609 if (verbose) 610 printf("Freeing %x\n", ptr); 611 png_free_default(png_ptr, ptr); 612 ptr = NULL; 613 } 614 #endif /* PNG_USER_MEM_SUPPORTED && PNG_DEBUG */ 615 /* END of code to test memory allocation/deallocation */ 616 617 618 /* Demonstration of user chunk support of the sTER and vpAg chunks */ 619 #ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED 620 621 /* (sTER is a public chunk not yet known by libpng. vpAg is a private 622 chunk used in ImageMagick to store "virtual page" size). */ 623 624 static png_uint_32 user_chunk_data[4]; 625 626 /* 0: sTER mode + 1 627 * 1: vpAg width 628 * 2: vpAg height 629 * 3: vpAg units 630 */ 631 632 static int read_user_chunk_callback(png_struct *png_ptr, 633 png_unknown_chunkp chunk) 634 { 635 png_uint_32 636 *my_user_chunk_data; 637 638 /* Return one of the following: 639 * return (-n); chunk had an error 640 * return (0); did not recognize 641 * return (n); success 642 * 643 * The unknown chunk structure contains the chunk data: 644 * png_byte name[5]; 645 * png_byte *data; 646 * png_size_t size; 647 * 648 * Note that libpng has already taken care of the CRC handling. 649 */ 650 651 if (chunk->name[0] == 115 && chunk->name[1] == 84 && /* s T */ 652 chunk->name[2] == 69 && chunk->name[3] == 82) /* E R */ 653 { 654 /* Found sTER chunk */ 655 if (chunk->size != 1) 656 return (-1); /* Error return */ 657 if (chunk->data[0] != 0 && chunk->data[0] != 1) 658 return (-1); /* Invalid mode */ 659 my_user_chunk_data=(png_uint_32 *) png_get_user_chunk_ptr(png_ptr); 660 my_user_chunk_data[0]=chunk->data[0]+1; 661 return (1); 662 } 663 664 if (chunk->name[0] != 118 || chunk->name[1] != 112 || /* v p */ 665 chunk->name[2] != 65 || chunk->name[3] != 103) /* A g */ 666 return (0); /* Did not recognize */ 667 668 /* Found ImageMagick vpAg chunk */ 669 670 if (chunk->size != 9) 671 return (-1); /* Error return */ 672 673 my_user_chunk_data=(png_uint_32 *) png_get_user_chunk_ptr(png_ptr); 674 675 my_user_chunk_data[1]=png_get_uint_31(png_ptr, chunk->data); 676 my_user_chunk_data[2]=png_get_uint_31(png_ptr, chunk->data + 4); 677 my_user_chunk_data[3]=(png_uint_32)chunk->data[8]; 678 679 return (1); 680 681 } 682 #endif 683 /* END of code to demonstrate user chunk support */ 684 685 /* Test one file */ 686 int 687 test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) 688 { 689 static png_FILE_p fpin; 690 static png_FILE_p fpout; /* "static" prevents setjmp corruption */ 691 png_structp read_ptr; 692 png_infop read_info_ptr, end_info_ptr; 693 #ifdef PNG_WRITE_SUPPORTED 694 png_structp write_ptr; 695 png_infop write_info_ptr; 696 png_infop write_end_info_ptr; 697 #else 698 png_structp write_ptr = NULL; 699 png_infop write_info_ptr = NULL; 700 png_infop write_end_info_ptr = NULL; 701 #endif 702 png_bytep row_buf; 703 png_uint_32 y; 704 png_uint_32 width, height; 705 int num_pass, pass; 706 int bit_depth, color_type; 707 #ifdef PNG_SETJMP_SUPPORTED 708 #ifdef USE_FAR_KEYWORD 709 jmp_buf jmpbuf; 710 #endif 711 #endif 712 713 #ifdef _WIN32_WCE 714 TCHAR path[MAX_PATH]; 715 #endif 716 char inbuf[256], outbuf[256]; 717 718 row_buf = NULL; 719 720 #ifdef _WIN32_WCE 721 MultiByteToWideChar(CP_ACP, 0, inname, -1, path, MAX_PATH); 722 if ((fpin = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 723 NULL)) == INVALID_HANDLE_VALUE) 724 #else 725 if ((fpin = fopen(inname, "rb")) == NULL) 726 #endif 727 { 728 fprintf(STDERR, "Could not find input file %s\n", inname); 729 return (1); 730 } 731 732 #ifdef _WIN32_WCE 733 MultiByteToWideChar(CP_ACP, 0, outname, -1, path, MAX_PATH); 734 if ((fpout = CreateFile(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 735 0, NULL)) == INVALID_HANDLE_VALUE) 736 #else 737 if ((fpout = fopen(outname, "wb")) == NULL) 738 #endif 739 { 740 fprintf(STDERR, "Could not open output file %s\n", outname); 741 FCLOSE(fpin); 742 return (1); 743 } 744 745 png_debug(0, "Allocating read and write structures"); 746 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG 747 read_ptr = 748 png_create_read_struct_2(PNG_LIBPNG_VER_STRING, png_voidp_NULL, 749 png_error_ptr_NULL, png_error_ptr_NULL, png_voidp_NULL, 750 (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free); 751 #else 752 read_ptr = 753 png_create_read_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL, 754 png_error_ptr_NULL, png_error_ptr_NULL); 755 #endif 756 #ifndef PNG_STDIO_SUPPORTED 757 png_set_error_fn(read_ptr, (png_voidp)inname, pngtest_error, 758 pngtest_warning); 759 #endif 760 761 #ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED 762 user_chunk_data[0] = 0; 763 user_chunk_data[1] = 0; 764 user_chunk_data[2] = 0; 765 user_chunk_data[3] = 0; 766 png_set_read_user_chunk_fn(read_ptr, user_chunk_data, 767 read_user_chunk_callback); 768 769 #endif 770 #ifdef PNG_WRITE_SUPPORTED 771 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG 772 write_ptr = 773 png_create_write_struct_2(PNG_LIBPNG_VER_STRING, png_voidp_NULL, 774 png_error_ptr_NULL, png_error_ptr_NULL, png_voidp_NULL, 775 (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free); 776 #else 777 write_ptr = 778 png_create_write_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL, 779 png_error_ptr_NULL, png_error_ptr_NULL); 780 #endif 781 #ifndef PNG_STDIO_SUPPORTED 782 png_set_error_fn(write_ptr, (png_voidp)inname, pngtest_error, 783 pngtest_warning); 784 #endif 785 #endif 786 png_debug(0, "Allocating read_info, write_info and end_info structures"); 787 read_info_ptr = png_create_info_struct(read_ptr); 788 end_info_ptr = png_create_info_struct(read_ptr); 789 #ifdef PNG_WRITE_SUPPORTED 790 write_info_ptr = png_create_info_struct(write_ptr); 791 write_end_info_ptr = png_create_info_struct(write_ptr); 792 #endif 793 794 #ifdef PNG_SETJMP_SUPPORTED 795 png_debug(0, "Setting jmpbuf for read struct"); 796 #ifdef USE_FAR_KEYWORD 797 if (setjmp(jmpbuf)) 798 #else 799 if (setjmp(png_jmpbuf(read_ptr))) 800 #endif 801 { 802 fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname); 803 png_free(read_ptr, row_buf); 804 row_buf = NULL; 805 png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); 806 #ifdef PNG_WRITE_SUPPORTED 807 png_destroy_info_struct(write_ptr, &write_end_info_ptr); 808 png_destroy_write_struct(&write_ptr, &write_info_ptr); 809 #endif 810 FCLOSE(fpin); 811 FCLOSE(fpout); 812 return (1); 813 } 814 #ifdef USE_FAR_KEYWORD 815 png_memcpy(png_jmpbuf(read_ptr), jmpbuf, png_sizeof(jmp_buf)); 816 #endif 817 818 #ifdef PNG_WRITE_SUPPORTED 819 png_debug(0, "Setting jmpbuf for write struct"); 820 #ifdef USE_FAR_KEYWORD 821 if (setjmp(jmpbuf)) 822 #else 823 if (setjmp(png_jmpbuf(write_ptr))) 824 #endif 825 { 826 fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname); 827 png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); 828 png_destroy_info_struct(write_ptr, &write_end_info_ptr); 829 #ifdef PNG_WRITE_SUPPORTED 830 png_destroy_write_struct(&write_ptr, &write_info_ptr); 831 #endif 832 FCLOSE(fpin); 833 FCLOSE(fpout); 834 return (1); 835 } 836 #ifdef USE_FAR_KEYWORD 837 png_memcpy(png_jmpbuf(write_ptr), jmpbuf, png_sizeof(jmp_buf)); 838 #endif 839 #endif 840 #endif 841 842 png_debug(0, "Initializing input and output streams"); 843 #ifdef PNG_STDIO_SUPPORTED 844 png_init_io(read_ptr, fpin); 845 # ifdef PNG_WRITE_SUPPORTED 846 png_init_io(write_ptr, fpout); 847 # endif 848 #else 849 png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data); 850 # ifdef PNG_WRITE_SUPPORTED 851 png_set_write_fn(write_ptr, (png_voidp)fpout, pngtest_write_data, 852 # ifdef PNG_WRITE_FLUSH_SUPPORTED 853 pngtest_flush); 854 # else 855 NULL); 856 # endif 857 # endif 858 #endif 859 if (status_dots_requested == 1) 860 { 861 #ifdef PNG_WRITE_SUPPORTED 862 png_set_write_status_fn(write_ptr, write_row_callback); 863 #endif 864 png_set_read_status_fn(read_ptr, read_row_callback); 865 } 866 else 867 { 868 #ifdef PNG_WRITE_SUPPORTED 869 png_set_write_status_fn(write_ptr, png_write_status_ptr_NULL); 870 #endif 871 png_set_read_status_fn(read_ptr, png_read_status_ptr_NULL); 872 } 873 874 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED 875 { 876 int i; 877 for (i = 0; i<256; i++) 878 filters_used[i] = 0; 879 png_set_read_user_transform_fn(read_ptr, count_filters); 880 } 881 #endif 882 #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED 883 zero_samples = 0; 884 png_set_write_user_transform_fn(write_ptr, count_zero_samples); 885 #endif 886 887 #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED 888 # ifndef PNG_HANDLE_CHUNK_ALWAYS 889 # define PNG_HANDLE_CHUNK_ALWAYS 3 890 # endif 891 png_set_keep_unknown_chunks(read_ptr, PNG_HANDLE_CHUNK_ALWAYS, 892 png_bytep_NULL, 0); 893 #endif 894 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED 895 # ifndef PNG_HANDLE_CHUNK_IF_SAFE 896 # define PNG_HANDLE_CHUNK_IF_SAFE 2 897 # endif 898 png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_IF_SAFE, 899 png_bytep_NULL, 0); 900 #endif 901 902 png_debug(0, "Reading info struct"); 903 png_read_info(read_ptr, read_info_ptr); 904 905 png_debug(0, "Transferring info struct"); 906 { 907 int interlace_type, compression_type, filter_type; 908 909 if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth, 910 &color_type, &interlace_type, &compression_type, &filter_type)) 911 { 912 png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth, 913 #ifdef PNG_WRITE_INTERLACING_SUPPORTED 914 color_type, interlace_type, compression_type, filter_type); 915 #else 916 color_type, PNG_INTERLACE_NONE, compression_type, filter_type); 917 #endif 918 } 919 } 920 #ifdef PNG_FIXED_POINT_SUPPORTED 921 #ifdef PNG_cHRM_SUPPORTED 922 { 923 png_fixed_point white_x, white_y, red_x, red_y, green_x, green_y, blue_x, 924 blue_y; 925 if (png_get_cHRM_fixed(read_ptr, read_info_ptr, &white_x, &white_y, 926 &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y)) 927 { 928 png_set_cHRM_fixed(write_ptr, write_info_ptr, white_x, white_y, red_x, 929 red_y, green_x, green_y, blue_x, blue_y); 930 } 931 } 932 #endif 933 #ifdef PNG_gAMA_SUPPORTED 934 { 935 png_fixed_point gamma; 936 937 if (png_get_gAMA_fixed(read_ptr, read_info_ptr, &gamma)) 938 png_set_gAMA_fixed(write_ptr, write_info_ptr, gamma); 939 } 940 #endif 941 #else /* Use floating point versions */ 942 #ifdef PNG_FLOATING_POINT_SUPPORTED 943 #ifdef PNG_cHRM_SUPPORTED 944 { 945 double white_x, white_y, red_x, red_y, green_x, green_y, blue_x, 946 blue_y; 947 if (png_get_cHRM(read_ptr, read_info_ptr, &white_x, &white_y, &red_x, 948 &red_y, &green_x, &green_y, &blue_x, &blue_y)) 949 { 950 png_set_cHRM(write_ptr, write_info_ptr, white_x, white_y, red_x, 951 red_y, green_x, green_y, blue_x, blue_y); 952 } 953 } 954 #endif 955 #ifdef PNG_gAMA_SUPPORTED 956 { 957 double gamma; 958 959 if (png_get_gAMA(read_ptr, read_info_ptr, &gamma)) 960 png_set_gAMA(write_ptr, write_info_ptr, gamma); 961 } 962 #endif 963 #endif /* Floating point */ 964 #endif /* Fixed point */ 965 #ifdef PNG_iCCP_SUPPORTED 966 { 967 png_charp name; 968 png_charp profile; 969 png_uint_32 proflen; 970 int compression_type; 971 972 if (png_get_iCCP(read_ptr, read_info_ptr, &name, &compression_type, 973 &profile, &proflen)) 974 { 975 png_set_iCCP(write_ptr, write_info_ptr, name, compression_type, 976 profile, proflen); 977 } 978 } 979 #endif 980 #ifdef PNG_sRGB_SUPPORTED 981 { 982 int intent; 983 984 if (png_get_sRGB(read_ptr, read_info_ptr, &intent)) 985 png_set_sRGB(write_ptr, write_info_ptr, intent); 986 } 987 #endif 988 { 989 png_colorp palette; 990 int num_palette; 991 992 if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette)) 993 png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette); 994 } 995 #ifdef PNG_bKGD_SUPPORTED 996 { 997 png_color_16p background; 998 999 if (png_get_bKGD(read_ptr, read_info_ptr, &background)) 1000 { 1001 png_set_bKGD(write_ptr, write_info_ptr, background); 1002 } 1003 } 1004 #endif 1005 #ifdef PNG_hIST_SUPPORTED 1006 { 1007 png_uint_16p hist; 1008 1009 if (png_get_hIST(read_ptr, read_info_ptr, &hist)) 1010 png_set_hIST(write_ptr, write_info_ptr, hist); 1011 } 1012 #endif 1013 #ifdef PNG_oFFs_SUPPORTED 1014 { 1015 png_int_32 offset_x, offset_y; 1016 int unit_type; 1017 1018 if (png_get_oFFs(read_ptr, read_info_ptr, &offset_x, &offset_y, 1019 &unit_type)) 1020 { 1021 png_set_oFFs(write_ptr, write_info_ptr, offset_x, offset_y, unit_type); 1022 } 1023 } 1024 #endif 1025 #ifdef PNG_pCAL_SUPPORTED 1026 { 1027 png_charp purpose, units; 1028 png_charpp params; 1029 png_int_32 X0, X1; 1030 int type, nparams; 1031 1032 if (png_get_pCAL(read_ptr, read_info_ptr, &purpose, &X0, &X1, &type, 1033 &nparams, &units, ¶ms)) 1034 { 1035 png_set_pCAL(write_ptr, write_info_ptr, purpose, X0, X1, type, 1036 nparams, units, params); 1037 } 1038 } 1039 #endif 1040 #ifdef PNG_pHYs_SUPPORTED 1041 { 1042 png_uint_32 res_x, res_y; 1043 int unit_type; 1044 1045 if (png_get_pHYs(read_ptr, read_info_ptr, &res_x, &res_y, &unit_type)) 1046 png_set_pHYs(write_ptr, write_info_ptr, res_x, res_y, unit_type); 1047 } 1048 #endif 1049 #ifdef PNG_sBIT_SUPPORTED 1050 { 1051 png_color_8p sig_bit; 1052 1053 if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit)) 1054 png_set_sBIT(write_ptr, write_info_ptr, sig_bit); 1055 } 1056 #endif 1057 #ifdef PNG_sCAL_SUPPORTED 1058 #ifdef PNG_FLOATING_POINT_SUPPORTED 1059 { 1060 int unit; 1061 double scal_width, scal_height; 1062 1063 if (png_get_sCAL(read_ptr, read_info_ptr, &unit, &scal_width, 1064 &scal_height)) 1065 { 1066 png_set_sCAL(write_ptr, write_info_ptr, unit, scal_width, scal_height); 1067 } 1068 } 1069 #else 1070 #ifdef PNG_FIXED_POINT_SUPPORTED 1071 { 1072 int unit; 1073 png_charp scal_width, scal_height; 1074 1075 if (png_get_sCAL_s(read_ptr, read_info_ptr, &unit, &scal_width, 1076 &scal_height)) 1077 { 1078 png_set_sCAL_s(write_ptr, write_info_ptr, unit, scal_width, 1079 scal_height); 1080 } 1081 } 1082 #endif 1083 #endif 1084 #endif 1085 #ifdef PNG_TEXT_SUPPORTED 1086 { 1087 png_textp text_ptr; 1088 int num_text; 1089 1090 if (png_get_text(read_ptr, read_info_ptr, &text_ptr, &num_text) > 0) 1091 { 1092 png_debug1(0, "Handling %d iTXt/tEXt/zTXt chunks", num_text); 1093 png_set_text(write_ptr, write_info_ptr, text_ptr, num_text); 1094 } 1095 } 1096 #endif 1097 #ifdef PNG_tIME_SUPPORTED 1098 { 1099 png_timep mod_time; 1100 1101 if (png_get_tIME(read_ptr, read_info_ptr, &mod_time)) 1102 { 1103 png_set_tIME(write_ptr, write_info_ptr, mod_time); 1104 #ifdef PNG_TIME_RFC1123_SUPPORTED 1105 /* We have to use png_memcpy instead of "=" because the string 1106 * pointed to by png_convert_to_rfc1123() gets free'ed before 1107 * we use it. 1108 */ 1109 png_memcpy(tIME_string, 1110 png_convert_to_rfc1123(read_ptr, mod_time), 1111 png_sizeof(tIME_string)); 1112 tIME_string[png_sizeof(tIME_string) - 1] = '\0'; 1113 tIME_chunk_present++; 1114 #endif /* PNG_TIME_RFC1123_SUPPORTED */ 1115 } 1116 } 1117 #endif 1118 #ifdef PNG_tRNS_SUPPORTED 1119 { 1120 png_bytep trans; 1121 int num_trans; 1122 png_color_16p trans_values; 1123 1124 if (png_get_tRNS(read_ptr, read_info_ptr, &trans, &num_trans, 1125 &trans_values)) 1126 { 1127 int sample_max = (1 << bit_depth); 1128 /* libpng doesn't reject a tRNS chunk with out-of-range samples */ 1129 if (!((color_type == PNG_COLOR_TYPE_GRAY && 1130 (int)trans_values->gray > sample_max) || 1131 (color_type == PNG_COLOR_TYPE_RGB && 1132 ((int)trans_values->red > sample_max || 1133 (int)trans_values->green > sample_max || 1134 (int)trans_values->blue > sample_max)))) 1135 png_set_tRNS(write_ptr, write_info_ptr, trans, num_trans, 1136 trans_values); 1137 } 1138 } 1139 #endif 1140 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED 1141 { 1142 png_unknown_chunkp unknowns; 1143 int num_unknowns = (int)png_get_unknown_chunks(read_ptr, read_info_ptr, 1144 &unknowns); 1145 if (num_unknowns) 1146 { 1147 png_size_t i; 1148 png_set_unknown_chunks(write_ptr, write_info_ptr, unknowns, 1149 num_unknowns); 1150 /* Copy the locations from the read_info_ptr. The automatically 1151 * generated locations in write_info_ptr are wrong because we 1152 * haven't written anything yet. 1153 */ 1154 for (i = 0; i < (png_size_t)num_unknowns; i++) 1155 png_set_unknown_chunk_location(write_ptr, write_info_ptr, i, 1156 unknowns[i].location); 1157 } 1158 } 1159 #endif 1160 1161 #ifdef PNG_WRITE_SUPPORTED 1162 png_debug(0, "Writing info struct"); 1163 1164 /* If we wanted, we could write info in two steps: 1165 * png_write_info_before_PLTE(write_ptr, write_info_ptr); 1166 */ 1167 png_write_info(write_ptr, write_info_ptr); 1168 1169 #ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED 1170 if (user_chunk_data[0] != 0) 1171 { 1172 png_byte png_sTER[5] = {115, 84, 69, 82, '\0'}; 1173 1174 unsigned char 1175 ster_chunk_data[1]; 1176 1177 if (verbose) 1178 fprintf(STDERR, "\n stereo mode = %lu\n", 1179 (unsigned long)(user_chunk_data[0] - 1)); 1180 ster_chunk_data[0]=(unsigned char)(user_chunk_data[0] - 1); 1181 png_write_chunk(write_ptr, png_sTER, ster_chunk_data, 1); 1182 } 1183 if (user_chunk_data[1] != 0 || user_chunk_data[2] != 0) 1184 { 1185 png_byte png_vpAg[5] = {118, 112, 65, 103, '\0'}; 1186 1187 unsigned char 1188 vpag_chunk_data[9]; 1189 1190 if (verbose) 1191 fprintf(STDERR, " vpAg = %lu x %lu, units = %lu\n", 1192 (unsigned long)user_chunk_data[1], 1193 (unsigned long)user_chunk_data[2], 1194 (unsigned long)user_chunk_data[3]); 1195 png_save_uint_32(vpag_chunk_data, user_chunk_data[1]); 1196 png_save_uint_32(vpag_chunk_data + 4, user_chunk_data[2]); 1197 vpag_chunk_data[8] = (unsigned char)(user_chunk_data[3] & 0xff); 1198 png_write_chunk(write_ptr, png_vpAg, vpag_chunk_data, 9); 1199 } 1200 1201 #endif 1202 #endif 1203 1204 #ifdef SINGLE_ROWBUF_ALLOC 1205 png_debug(0, "Allocating row buffer..."); 1206 row_buf = (png_bytep)png_malloc(read_ptr, 1207 png_get_rowbytes(read_ptr, read_info_ptr)); 1208 png_debug1(0, "0x%08lx", (unsigned long)row_buf); 1209 #endif /* SINGLE_ROWBUF_ALLOC */ 1210 png_debug(0, "Writing row data"); 1211 1212 #if defined(PNG_READ_INTERLACING_SUPPORTED) || \ 1213 defined(PNG_WRITE_INTERLACING_SUPPORTED) 1214 num_pass = png_set_interlace_handling(read_ptr); 1215 # ifdef PNG_WRITE_SUPPORTED 1216 png_set_interlace_handling(write_ptr); 1217 # endif 1218 #else 1219 num_pass = 1; 1220 #endif 1221 1222 #ifdef PNGTEST_TIMING 1223 t_stop = (float)clock(); 1224 t_misc += (t_stop - t_start); 1225 t_start = t_stop; 1226 #endif 1227 for (pass = 0; pass < num_pass; pass++) 1228 { 1229 png_debug1(0, "Writing row data for pass %d", pass); 1230 for (y = 0; y < height; y++) 1231 { 1232 #ifndef SINGLE_ROWBUF_ALLOC 1233 png_debug2(0, "Allocating row buffer (pass %d, y = %ld)...", pass, y); 1234 row_buf = (png_bytep)png_malloc(read_ptr, 1235 png_get_rowbytes(read_ptr, read_info_ptr)); 1236 png_debug2(0, "0x%08lx (%ld bytes)", (unsigned long)row_buf, 1237 png_get_rowbytes(read_ptr, read_info_ptr)); 1238 #endif /* !SINGLE_ROWBUF_ALLOC */ 1239 png_read_rows(read_ptr, (png_bytepp)&row_buf, png_bytepp_NULL, 1); 1240 1241 #ifdef PNG_WRITE_SUPPORTED 1242 #ifdef PNGTEST_TIMING 1243 t_stop = (float)clock(); 1244 t_decode += (t_stop - t_start); 1245 t_start = t_stop; 1246 #endif 1247 png_write_rows(write_ptr, (png_bytepp)&row_buf, 1); 1248 #ifdef PNGTEST_TIMING 1249 t_stop = (float)clock(); 1250 t_encode += (t_stop - t_start); 1251 t_start = t_stop; 1252 #endif 1253 #endif /* PNG_WRITE_SUPPORTED */ 1254 1255 #ifndef SINGLE_ROWBUF_ALLOC 1256 png_debug2(0, "Freeing row buffer (pass %d, y = %ld)", pass, y); 1257 png_free(read_ptr, row_buf); 1258 row_buf = NULL; 1259 #endif /* !SINGLE_ROWBUF_ALLOC */ 1260 } 1261 } 1262 1263 #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED 1264 png_free_data(read_ptr, read_info_ptr, PNG_FREE_UNKN, -1); 1265 #endif 1266 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED 1267 png_free_data(write_ptr, write_info_ptr, PNG_FREE_UNKN, -1); 1268 #endif 1269 1270 png_debug(0, "Reading and writing end_info data"); 1271 1272 png_read_end(read_ptr, end_info_ptr); 1273 #ifdef PNG_TEXT_SUPPORTED 1274 { 1275 png_textp text_ptr; 1276 int num_text; 1277 1278 if (png_get_text(read_ptr, end_info_ptr, &text_ptr, &num_text) > 0) 1279 { 1280 png_debug1(0, "Handling %d iTXt/tEXt/zTXt chunks", num_text); 1281 png_set_text(write_ptr, write_end_info_ptr, text_ptr, num_text); 1282 } 1283 } 1284 #endif 1285 #ifdef PNG_tIME_SUPPORTED 1286 { 1287 png_timep mod_time; 1288 1289 if (png_get_tIME(read_ptr, end_info_ptr, &mod_time)) 1290 { 1291 png_set_tIME(write_ptr, write_end_info_ptr, mod_time); 1292 #ifdef PNG_TIME_RFC1123_SUPPORTED 1293 /* We have to use png_memcpy instead of "=" because the string 1294 pointed to by png_convert_to_rfc1123() gets free'ed before 1295 we use it */ 1296 png_memcpy(tIME_string, 1297 png_convert_to_rfc1123(read_ptr, mod_time), 1298 png_sizeof(tIME_string)); 1299 tIME_string[png_sizeof(tIME_string) - 1] = '\0'; 1300 tIME_chunk_present++; 1301 #endif /* PNG_TIME_RFC1123_SUPPORTED */ 1302 } 1303 } 1304 #endif 1305 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED 1306 { 1307 png_unknown_chunkp unknowns; 1308 int num_unknowns; 1309 num_unknowns = (int)png_get_unknown_chunks(read_ptr, end_info_ptr, 1310 &unknowns); 1311 if (num_unknowns) 1312 { 1313 png_size_t i; 1314 png_set_unknown_chunks(write_ptr, write_end_info_ptr, unknowns, 1315 num_unknowns); 1316 /* Copy the locations from the read_info_ptr. The automatically 1317 * generated locations in write_end_info_ptr are wrong because we 1318 * haven't written the end_info yet. 1319 */ 1320 for (i = 0; i < (png_size_t)num_unknowns; i++) 1321 png_set_unknown_chunk_location(write_ptr, write_end_info_ptr, i, 1322 unknowns[i].location); 1323 } 1324 } 1325 #endif 1326 #ifdef PNG_WRITE_SUPPORTED 1327 png_write_end(write_ptr, write_end_info_ptr); 1328 #endif 1329 1330 #ifdef PNG_EASY_ACCESS_SUPPORTED 1331 if (verbose) 1332 { 1333 png_uint_32 iwidth, iheight; 1334 iwidth = png_get_image_width(write_ptr, write_info_ptr); 1335 iheight = png_get_image_height(write_ptr, write_info_ptr); 1336 fprintf(STDERR, "\n Image width = %lu, height = %lu\n", 1337 (unsigned long)iwidth, (unsigned long)iheight); 1338 } 1339 #endif 1340 1341 png_debug(0, "Destroying data structs"); 1342 #ifdef SINGLE_ROWBUF_ALLOC 1343 png_debug(1, "destroying row_buf for read_ptr"); 1344 png_free(read_ptr, row_buf); 1345 row_buf = NULL; 1346 #endif /* SINGLE_ROWBUF_ALLOC */ 1347 png_debug(1, "destroying read_ptr, read_info_ptr, end_info_ptr"); 1348 png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); 1349 #ifdef PNG_WRITE_SUPPORTED 1350 png_debug(1, "destroying write_end_info_ptr"); 1351 png_destroy_info_struct(write_ptr, &write_end_info_ptr); 1352 png_debug(1, "destroying write_ptr, write_info_ptr"); 1353 png_destroy_write_struct(&write_ptr, &write_info_ptr); 1354 #endif 1355 png_debug(0, "Destruction complete."); 1356 1357 FCLOSE(fpin); 1358 FCLOSE(fpout); 1359 1360 png_debug(0, "Opening files for comparison"); 1361 #ifdef _WIN32_WCE 1362 MultiByteToWideChar(CP_ACP, 0, inname, -1, path, MAX_PATH); 1363 if ((fpin = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 1364 0, NULL)) == INVALID_HANDLE_VALUE) 1365 #else 1366 if ((fpin = fopen(inname, "rb")) == NULL) 1367 #endif 1368 { 1369 fprintf(STDERR, "Could not find file %s\n", inname); 1370 return (1); 1371 } 1372 1373 #ifdef _WIN32_WCE 1374 MultiByteToWideChar(CP_ACP, 0, outname, -1, path, MAX_PATH); 1375 if ((fpout = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 1376 0, NULL)) == INVALID_HANDLE_VALUE) 1377 #else 1378 if ((fpout = fopen(outname, "rb")) == NULL) 1379 #endif 1380 { 1381 fprintf(STDERR, "Could not find file %s\n", outname); 1382 FCLOSE(fpin); 1383 return (1); 1384 } 1385 1386 for (;;) 1387 { 1388 png_size_t num_in, num_out; 1389 1390 READFILE(fpin, inbuf, 1, num_in); 1391 READFILE(fpout, outbuf, 1, num_out); 1392 1393 if (num_in != num_out) 1394 { 1395 fprintf(STDERR, "\nFiles %s and %s are of a different size\n", 1396 inname, outname); 1397 if (wrote_question == 0) 1398 { 1399 fprintf(STDERR, 1400 " Was %s written with the same maximum IDAT chunk size (%d bytes),", 1401 inname, PNG_ZBUF_SIZE); 1402 fprintf(STDERR, 1403 "\n filtering heuristic (libpng default), compression"); 1404 fprintf(STDERR, 1405 " level (zlib default),\n and zlib version (%s)?\n\n", 1406 ZLIB_VERSION); 1407 wrote_question = 1; 1408 } 1409 FCLOSE(fpin); 1410 FCLOSE(fpout); 1411 return (0); 1412 } 1413 1414 if (!num_in) 1415 break; 1416 1417 if (png_memcmp(inbuf, outbuf, num_in)) 1418 { 1419 fprintf(STDERR, "\nFiles %s and %s are different\n", inname, outname); 1420 if (wrote_question == 0) 1421 { 1422 fprintf(STDERR, 1423 " Was %s written with the same maximum IDAT chunk size (%d bytes),", 1424 inname, PNG_ZBUF_SIZE); 1425 fprintf(STDERR, 1426 "\n filtering heuristic (libpng default), compression"); 1427 fprintf(STDERR, 1428 " level (zlib default),\n and zlib version (%s)?\n\n", 1429 ZLIB_VERSION); 1430 wrote_question = 1; 1431 } 1432 FCLOSE(fpin); 1433 FCLOSE(fpout); 1434 return (0); 1435 } 1436 } 1437 1438 FCLOSE(fpin); 1439 FCLOSE(fpout); 1440 1441 return (0); 1442 } 1443 1444 /* Input and output filenames */ 1445 #ifdef RISCOS 1446 static PNG_CONST char *inname = "pngtest/png"; 1447 static PNG_CONST char *outname = "pngout/png"; 1448 #else 1449 static PNG_CONST char *inname = "pngtest.png"; 1450 static PNG_CONST char *outname = "pngout.png"; 1451 #endif 1452 1453 int 1454 main(int argc, char *argv[]) 1455 { 1456 int multiple = 0; 1457 int ierror = 0; 1458 1459 fprintf(STDERR, "\n Testing libpng version %s\n", PNG_LIBPNG_VER_STRING); 1460 fprintf(STDERR, " with zlib version %s\n", ZLIB_VERSION); 1461 fprintf(STDERR, "%s", png_get_copyright(NULL)); 1462 /* Show the version of libpng used in building the library */ 1463 fprintf(STDERR, " library (%lu):%s", 1464 (unsigned long)png_access_version_number(), 1465 png_get_header_version(NULL)); 1466 /* Show the version of libpng used in building the application */ 1467 fprintf(STDERR, " pngtest (%lu):%s", (unsigned long)PNG_LIBPNG_VER, 1468 PNG_HEADER_VERSION_STRING); 1469 fprintf(STDERR, " sizeof(png_struct)=%ld, sizeof(png_info)=%ld\n", 1470 (long)png_sizeof(png_struct), (long)png_sizeof(png_info)); 1471 1472 /* Do some consistency checking on the memory allocation settings, I'm 1473 * not sure this matters, but it is nice to know, the first of these 1474 * tests should be impossible because of the way the macros are set 1475 * in pngconf.h 1476 */ 1477 #if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) 1478 fprintf(STDERR, " NOTE: Zlib compiled for max 64k, libpng not\n"); 1479 #endif 1480 /* I think the following can happen. */ 1481 #if !defined(MAXSEG_64K) && defined(PNG_MAX_MALLOC_64K) 1482 fprintf(STDERR, " NOTE: libpng compiled for max 64k, zlib not\n"); 1483 #endif 1484 1485 if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING)) 1486 { 1487 fprintf(STDERR, 1488 "Warning: versions are different between png.h and png.c\n"); 1489 fprintf(STDERR, " png.h version: %s\n", PNG_LIBPNG_VER_STRING); 1490 fprintf(STDERR, " png.c version: %s\n\n", png_libpng_ver); 1491 ++ierror; 1492 } 1493 1494 if (argc > 1) 1495 { 1496 if (strcmp(argv[1], "-m") == 0) 1497 { 1498 multiple = 1; 1499 status_dots_requested = 0; 1500 } 1501 else if (strcmp(argv[1], "-mv") == 0 || 1502 strcmp(argv[1], "-vm") == 0 ) 1503 { 1504 multiple = 1; 1505 verbose = 1; 1506 status_dots_requested = 1; 1507 } 1508 else if (strcmp(argv[1], "-v") == 0) 1509 { 1510 verbose = 1; 1511 status_dots_requested = 1; 1512 inname = argv[2]; 1513 } 1514 else 1515 { 1516 inname = argv[1]; 1517 status_dots_requested = 0; 1518 } 1519 } 1520 1521 if (!multiple && argc == 3 + verbose) 1522 outname = argv[2 + verbose]; 1523 1524 if ((!multiple && argc > 3 + verbose) || (multiple && argc < 2)) 1525 { 1526 fprintf(STDERR, 1527 "usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n", 1528 argv[0], argv[0]); 1529 fprintf(STDERR, 1530 " reads/writes one PNG file (without -m) or multiple files (-m)\n"); 1531 fprintf(STDERR, 1532 " with -m %s is used as a temporary file\n", outname); 1533 exit(1); 1534 } 1535 1536 if (multiple) 1537 { 1538 int i; 1539 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG 1540 int allocation_now = current_allocation; 1541 #endif 1542 for (i=2; i<argc; ++i) 1543 { 1544 int kerror; 1545 fprintf(STDERR, "\n Testing %s:", argv[i]); 1546 kerror = test_one_file(argv[i], outname); 1547 if (kerror == 0) 1548 { 1549 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED 1550 int k; 1551 #endif 1552 #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED 1553 fprintf(STDERR, "\n PASS (%lu zero samples)\n", 1554 (unsigned long)zero_samples); 1555 #else 1556 fprintf(STDERR, " PASS\n"); 1557 #endif 1558 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED 1559 for (k = 0; k<256; k++) 1560 if (filters_used[k]) 1561 fprintf(STDERR, " Filter %d was used %lu times\n", 1562 k, (unsigned long)filters_used[k]); 1563 #endif 1564 #ifdef PNG_TIME_RFC1123_SUPPORTED 1565 if (tIME_chunk_present != 0) 1566 fprintf(STDERR, " tIME = %s\n", tIME_string); 1567 tIME_chunk_present = 0; 1568 #endif /* PNG_TIME_RFC1123_SUPPORTED */ 1569 } 1570 else 1571 { 1572 fprintf(STDERR, " FAIL\n"); 1573 ierror += kerror; 1574 } 1575 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG 1576 if (allocation_now != current_allocation) 1577 fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n", 1578 current_allocation - allocation_now); 1579 if (current_allocation != 0) 1580 { 1581 memory_infop pinfo = pinformation; 1582 1583 fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n", 1584 current_allocation); 1585 while (pinfo != NULL) 1586 { 1587 fprintf(STDERR, " %lu bytes at %x\n", 1588 (unsigned long)pinfo->size, 1589 (unsigned int) pinfo->pointer); 1590 pinfo = pinfo->next; 1591 } 1592 } 1593 #endif 1594 } 1595 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG 1596 fprintf(STDERR, " Current memory allocation: %10d bytes\n", 1597 current_allocation); 1598 fprintf(STDERR, " Maximum memory allocation: %10d bytes\n", 1599 maximum_allocation); 1600 fprintf(STDERR, " Total memory allocation: %10d bytes\n", 1601 total_allocation); 1602 fprintf(STDERR, " Number of allocations: %10d\n", 1603 num_allocations); 1604 #endif 1605 } 1606 else 1607 { 1608 int i; 1609 for (i = 0; i<3; ++i) 1610 { 1611 int kerror; 1612 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG 1613 int allocation_now = current_allocation; 1614 #endif 1615 if (i == 1) status_dots_requested = 1; 1616 else if (verbose == 0)status_dots_requested = 0; 1617 if (i == 0 || verbose == 1 || ierror != 0) 1618 fprintf(STDERR, "\n Testing %s:", inname); 1619 kerror = test_one_file(inname, outname); 1620 if (kerror == 0) 1621 { 1622 if (verbose == 1 || i == 2) 1623 { 1624 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED 1625 int k; 1626 #endif 1627 #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED 1628 fprintf(STDERR, "\n PASS (%lu zero samples)\n", 1629 (unsigned long)zero_samples); 1630 #else 1631 fprintf(STDERR, " PASS\n"); 1632 #endif 1633 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED 1634 for (k = 0; k<256; k++) 1635 if (filters_used[k]) 1636 fprintf(STDERR, " Filter %d was used %lu times\n", 1637 k, (unsigned long)filters_used[k]); 1638 #endif 1639 #ifdef PNG_TIME_RFC1123_SUPPORTED 1640 if (tIME_chunk_present != 0) 1641 fprintf(STDERR, " tIME = %s\n", tIME_string); 1642 #endif /* PNG_TIME_RFC1123_SUPPORTED */ 1643 } 1644 } 1645 else 1646 { 1647 if (verbose == 0 && i != 2) 1648 fprintf(STDERR, "\n Testing %s:", inname); 1649 fprintf(STDERR, " FAIL\n"); 1650 ierror += kerror; 1651 } 1652 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG 1653 if (allocation_now != current_allocation) 1654 fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n", 1655 current_allocation - allocation_now); 1656 if (current_allocation != 0) 1657 { 1658 memory_infop pinfo = pinformation; 1659 1660 fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n", 1661 current_allocation); 1662 while (pinfo != NULL) 1663 { 1664 fprintf(STDERR, " %lu bytes at %x\n", 1665 (unsigned long)pinfo->size, (unsigned int)pinfo->pointer); 1666 pinfo = pinfo->next; 1667 } 1668 } 1669 #endif 1670 } 1671 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG 1672 fprintf(STDERR, " Current memory allocation: %10d bytes\n", 1673 current_allocation); 1674 fprintf(STDERR, " Maximum memory allocation: %10d bytes\n", 1675 maximum_allocation); 1676 fprintf(STDERR, " Total memory allocation: %10d bytes\n", 1677 total_allocation); 1678 fprintf(STDERR, " Number of allocations: %10d\n", 1679 num_allocations); 1680 #endif 1681 } 1682 1683 #ifdef PNGTEST_TIMING 1684 t_stop = (float)clock(); 1685 t_misc += (t_stop - t_start); 1686 t_start = t_stop; 1687 fprintf(STDERR, " CPU time used = %.3f seconds", 1688 (t_misc+t_decode+t_encode)/(float)CLOCKS_PER_SEC); 1689 fprintf(STDERR, " (decoding %.3f,\n", 1690 t_decode/(float)CLOCKS_PER_SEC); 1691 fprintf(STDERR, " encoding %.3f ,", 1692 t_encode/(float)CLOCKS_PER_SEC); 1693 fprintf(STDERR, " other %.3f seconds)\n\n", 1694 t_misc/(float)CLOCKS_PER_SEC); 1695 #endif 1696 1697 if (ierror == 0) 1698 fprintf(STDERR, " libpng passes test\n"); 1699 else 1700 fprintf(STDERR, " libpng FAILS test\n"); 1701 return (int)(ierror != 0); 1702 } 1703 1704 /* Generate a compiler error if there is an old png.h in the search path. */ 1705 typedef version_1_2_46 your_png_h_is_not_version_1_2_46; 1706