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