2 /* pngtest.c - a simple test program to test libpng
5 * For conditions of distribution and use, see copyright notice in png.h
6 * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
7 * Copyright (c) 1996, 1997 Andreas Dilger
8 * Copyright (c) 1998, Glenn Randers-Pehrson
11 * This program reads in a PNG image, writes it out again, and then
12 * compares the two files. If the files are identical, this shows that
13 * the basic chunk handling, filtering, and (de)compression code is working
14 * properly. It does not currently test all of the transforms, although
17 * The program will fail in certain legitimate cases:
18 * 1) when the compression level or filter selection method is changed.
19 * 2) when the chunk size is smaller than 8K.
20 * 3) unknown ancillary chunks 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 images 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.
33 /* Makes pngtest verbose so we can find problems (needs to be before png.h) */
40 int test_one_file
PNGARG((PNG_CONST
char *inname
, PNG_CONST
char *outname
));
46 /* defined so I can write to a file on gui/windowing platforms */
47 /* #define STDERR stderr */
48 #define STDERR stdout /* for DOS */
50 /* example of using row callbacks to make a simple progress meter */
51 static int status_pass
=1;
52 static int status_dots_requested
=0;
53 static int status_dots
=1;
56 read_row_callback(png_structp png_ptr
, png_uint_32 row_number
, int pass
)
58 if(png_ptr
== NULL
|| row_number
> 0x3fffffffL
) return;
59 if(status_pass
!= pass
)
61 fprintf(stdout
,"\n Pass %d: ",pass
);
68 fprintf(stdout
, "\n ");
75 write_row_callback(png_structp png_ptr
, png_uint_32 row_number
, int pass
)
77 if(png_ptr
== NULL
|| row_number
> 0x3fffffffL
|| pass
> 7) return;
82 #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
83 /* example of using user transform callback (we don't transform anything,
84 but merely count the black pixels) */
86 static png_uint_32 black_pixels
;
89 count_black_pixels(png_structp png_ptr
, png_row_infop row_info
, png_bytep data
)
92 if(png_ptr
== NULL
)return;
94 /* contents of row_info:
95 * png_uint_32 width width of row
96 * png_uint_32 rowbytes number of bytes in row
97 * png_byte color_type color type of pixels
98 * png_byte bit_depth bit depth of samples
99 * png_byte channels number of channels (1-4)
100 * png_byte pixel_depth bits per pixel (depth*channels)
103 /* counts the number of black pixels (or zero pixels if color_type is 3 */
105 if(row_info
->color_type
== 0 || row_info
->color_type
== 3)
109 for (n
=0; n
<row_info
->width
; n
++)
111 if(row_info
->bit_depth
== 1)
112 if(((*dp
<< pos
++ )& 0x80) == 0) black_pixels
++;
118 if(row_info
->bit_depth
== 2)
119 if(((*dp
<< (pos
+=2))& 0xc0) == 0) black_pixels
++;
125 if(row_info
->bit_depth
== 4)
126 if(((*dp
<< (pos
+=4))& 0xf0) == 0) black_pixels
++;
132 if(row_info
->bit_depth
== 8)
133 if(*dp
++ == 0) black_pixels
++;
134 if(row_info
->bit_depth
== 16)
136 if((*dp
| *(dp
+1)) == 0) black_pixels
++;
141 else /* other color types */
145 int color_channels
= row_info
->channels
;
146 if(row_info
->color_type
> 3)color_channels
--;
148 for (n
=0; n
<row_info
->width
; n
++)
150 for (channel
= 0; channel
< color_channels
; channel
++)
152 if(row_info
->bit_depth
== 8)
153 if(*dp
++ == 0) black_pixels
++;
154 if(row_info
->bit_depth
== 16)
156 if((*dp
| *(dp
+1)) == 0) black_pixels
++;
160 if(row_info
->color_type
> 3)
163 if(row_info
->bit_depth
== 16)dp
++;
168 #endif /* PNG_WRITE_USER_TRANSFORM_SUPPORTED */
170 static int verbose
= 0;
171 static int wrote_question
= 0;
173 #if defined(PNG_NO_STDIO)
174 /* START of code to validate stdio-free compilation */
175 /* These copies of the default read/write functions come from pngrio.c and */
176 /* pngwio.c. They allow "don't include stdio" testing of the library. */
177 /* This is the function which does the actual reading of data. If you are
178 not reading from a standard C stream, you should create a replacement
179 read_data function and use it at run time with png_set_read_fn(), rather
180 than changing the library. */
181 #ifndef USE_FAR_KEYWORD
183 png_default_read_data(png_structp png_ptr
, png_bytep data
, png_size_t length
)
187 /* fread() returns 0 on error, so it is OK to store this in a png_size_t
188 * instead of an int, which is what fread() actually returns.
190 check
= (png_size_t
)fread(data
, (png_size_t
)1, length
,
191 (FILE *)png_ptr
->io_ptr
);
195 png_error(png_ptr
, "Read Error");
199 /* this is the model-independent version. Since the standard I/O library
200 can't handle far buffers in the medium and small models, we have to copy
204 #define NEAR_BUF_SIZE 1024
205 #define MIN(a,b) (a <= b ? a : b)
208 png_default_read_data(png_structp png_ptr
, png_bytep data
, png_size_t length
)
214 /* Check if data really is near. If so, use usual code. */
215 n_data
= (png_byte
*)CVT_PTR_NOCHECK(data
);
216 io_ptr
= (FILE *)CVT_PTR(png_ptr
->io_ptr
);
217 if ((png_bytep
)n_data
== data
)
219 check
= fread(n_data
, 1, length
, io_ptr
);
223 png_byte buf
[NEAR_BUF_SIZE
];
224 png_size_t read
, remaining
, err
;
229 read
= MIN(NEAR_BUF_SIZE
, remaining
);
230 err
= fread(buf
, (png_size_t
)1, read
, io_ptr
);
231 png_memcpy(data
, buf
, read
); /* copy far buffer to near buffer */
239 while (remaining
!= 0);
243 png_error(png_ptr
, "read Error");
246 #endif /* USE_FAR_KEYWORD */
248 #if defined(PNG_WRITE_FLUSH_SUPPORTED)
250 png_default_flush(png_structp png_ptr
)
253 io_ptr
= (FILE *)CVT_PTR((png_ptr
->io_ptr
));
259 /* This is the function which does the actual writing of data. If you are
260 not writing to a standard C stream, you should create a replacement
261 write_data function and use it at run time with png_set_write_fn(), rather
262 than changing the library. */
263 #ifndef USE_FAR_KEYWORD
265 png_default_write_data(png_structp png_ptr
, png_bytep data
, png_size_t length
)
269 check
= fwrite(data
, 1, length
, (FILE *)(png_ptr
->io_ptr
));
272 png_error(png_ptr
, "Write Error");
276 /* this is the model-independent version. Since the standard I/O library
277 can't handle far buffers in the medium and small models, we have to copy
281 #define NEAR_BUF_SIZE 1024
282 #define MIN(a,b) (a <= b ? a : b)
285 png_default_write_data(png_structp png_ptr
, png_bytep data
, png_size_t length
)
288 png_byte
*near_data
; /* Needs to be "png_byte *" instead of "png_bytep" */
291 /* Check if data really is near. If so, use usual code. */
292 near_data
= (png_byte
*)CVT_PTR_NOCHECK(data
);
293 io_ptr
= (FILE *)CVT_PTR(png_ptr
->io_ptr
);
294 if ((png_bytep
)near_data
== data
)
296 check
= fwrite(near_data
, 1, length
, io_ptr
);
300 png_byte buf
[NEAR_BUF_SIZE
];
301 png_size_t written
, remaining
, err
;
306 written
= MIN(NEAR_BUF_SIZE
, remaining
);
307 png_memcpy(buf
, data
, written
); /* copy far buffer to near buffer */
308 err
= fwrite(buf
, 1, written
, io_ptr
);
314 remaining
-= written
;
316 while (remaining
!= 0);
320 png_error(png_ptr
, "Write Error");
324 #endif /* USE_FAR_KEYWORD */
326 /* This function is called when there is a warning, but the library thinks
327 * it can continue anyway. Replacement functions don't have to do anything
328 * here if you don't want to. In the default configuration, png_ptr is
329 * not used, but it is passed in case it may be useful.
332 png_default_warning(png_structp png_ptr
, png_const_charp message
)
334 PNG_CONST
char *name
= "UNKNOWN (ERROR!)";
335 if (png_ptr
!= NULL
&& png_ptr
->error_ptr
!= NULL
)
336 name
= png_ptr
->error_ptr
;
337 fprintf(STDERR
, "%s: libpng warning: %s\n", name
, message
);
340 /* This is the default error handling function. Note that replacements for
341 * this function MUST NOT RETURN, or the program will likely crash. This
342 * function is used by default, or if the program supplies NULL for the
343 * error function pointer in png_set_error_fn().
346 png_default_error(png_structp png_ptr
, png_const_charp message
)
348 png_default_warning(png_ptr
, message
);
349 /* We can return because png_error calls the default handler which is
350 * actually ok in this case. */
352 #endif /* PNG_NO_STDIO */
353 /* END of code to validate stdio-free compilation */
355 /* START of code to validate memory allocation and deallocation */
356 #ifdef PNGTEST_MEMORY_DEBUG
357 /* Borland DOS special memory handler */
358 #if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
359 ERROR
- memory debugging is
not supported on
this platform
362 /* Allocate memory. For reasonable files, size should never exceed
363 64K. However, zlib may allocate more then 64K if you don't tell
364 it not to. See zconf.h and png.h for more information. zlib does
365 need to allocate exactly 64K, so whatever you call here must
366 have the ability to do that.
368 This piece of code can be compiled to validate max 64K allocations
369 by setting MAXSEG_64K in zlib zconf.h *or* PNG_MAX_MALLOC_64K. */
370 typedef struct memory_information
{
373 struct memory_information FAR
*next
;
374 } memory_information
;
375 typedef memory_information FAR
*memory_infop
;
377 static memory_infop pinformation
= NULL
;
378 static int current_allocation
= 0;
379 static int maximum_allocation
= 0;
381 extern PNG_EXPORT(png_voidp
,png_debug_malloc
) PNGARG((png_structp png_ptr
,
383 extern PNG_EXPORT(void,png_debug_free
) PNGARG((png_structp png_ptr
,
387 png_malloc(png_structp png_ptr
, png_uint_32 size
) {
388 if (png_ptr
== NULL
) {
389 fprintf(STDERR
, "NULL pointer to memory allocator\n");
393 return (png_voidp
)(NULL
);
395 /* This calls the library allocator twice, once to get the requested
396 buffer and once to get a new free list entry. */
398 memory_infop pinfo
= png_debug_malloc(png_ptr
, sizeof *pinfo
);
400 current_allocation
+= size
;
401 if (current_allocation
> maximum_allocation
)
402 maximum_allocation
= current_allocation
;
403 pinfo
->pointer
= png_debug_malloc(png_ptr
, size
);
404 pinfo
->next
= pinformation
;
405 pinformation
= pinfo
;
406 /* Make sure the caller isn't assuming zeroed memory. */
407 png_memset(pinfo
->pointer
, 0xdd, pinfo
->size
);
408 return (png_voidp
)(pinfo
->pointer
);
412 /* Free a pointer. It is removed from the list at the same time. */
414 png_free(png_structp png_ptr
, png_voidp ptr
)
417 fprintf(STDERR
, "NULL pointer to memory allocator\n");
419 #if 0 /* This happens all the time. */
420 fprintf(STDERR
, "WARNING: freeing NULL pointer\n");
425 /* Unlink the element from the list. */
427 memory_infop FAR
*ppinfo
= &pinformation
;
429 memory_infop pinfo
= *ppinfo
;
430 if (pinfo
->pointer
== ptr
) {
431 *ppinfo
= pinfo
->next
;
432 current_allocation
-= pinfo
->size
;
433 if (current_allocation
< 0)
434 fprintf(STDERR
, "Duplicate free of memory\n");
435 /* We must free the list element too, but first kill
436 the memory which is to be freed. */
437 memset(ptr
, 0x55, pinfo
->size
);
438 png_debug_free(png_ptr
, pinfo
);
441 if (pinfo
->next
== NULL
) {
442 fprintf(STDERR
, "Pointer %x not found\n", ptr
);
445 ppinfo
= &pinfo
->next
;
449 /* Finally free the data. */
450 png_debug_free(png_ptr
, ptr
);
452 #endif /* Not Borland DOS special memory handler */
454 /* END of code to test memory allocation/deallocation */
458 test_one_file(PNG_CONST
char *inname
, PNG_CONST
char *outname
)
460 static FILE *fpin
, *fpout
; /* "static" prevents setjmp corruption */
461 png_structp read_ptr
, write_ptr
;
462 png_infop read_info_ptr
, write_info_ptr
, end_info_ptr
;
465 png_uint_32 width
, height
;
467 int bit_depth
, color_type
;
468 #ifdef USE_FAR_KEYWORD
472 char inbuf
[256], outbuf
[256];
474 row_buf
= (png_bytep
)NULL
;
476 if ((fpin
= fopen(inname
, "rb")) == NULL
)
478 fprintf(STDERR
, "Could not find input file %s\n", inname
);
482 if ((fpout
= fopen(outname
, "wb")) == NULL
)
484 fprintf(STDERR
, "Could not open output file %s\n", outname
);
489 png_debug(0, "Allocating read and write structures\n");
490 read_ptr
= png_create_read_struct(PNG_LIBPNG_VER_STRING
, (png_voidp
)NULL
,
491 (png_error_ptr
)NULL
, (png_error_ptr
)NULL
);
492 #if defined(PNG_NO_STDIO)
493 png_set_error_fn(read_ptr
, (png_voidp
)inname
, png_default_error
,
494 png_default_warning
);
496 write_ptr
= png_create_write_struct(PNG_LIBPNG_VER_STRING
, (png_voidp
)NULL
,
497 (png_error_ptr
)NULL
, (png_error_ptr
)NULL
);
498 #if defined(PNG_NO_STDIO)
499 png_set_error_fn(write_ptr
, (png_voidp
)inname
, png_default_error
,
500 png_default_warning
);
502 png_debug(0, "Allocating read_info, write_info and end_info structures\n");
503 read_info_ptr
= png_create_info_struct(read_ptr
);
504 write_info_ptr
= png_create_info_struct(write_ptr
);
505 end_info_ptr
= png_create_info_struct(read_ptr
);
507 png_debug(0, "Setting jmpbuf for read struct\n");
508 #ifdef USE_FAR_KEYWORD
511 if (setjmp(read_ptr
->jmpbuf
))
514 fprintf(STDERR
, "%s -> %s: libpng read error\n", inname
, outname
);
515 png_destroy_read_struct(&read_ptr
, &read_info_ptr
, &end_info_ptr
);
516 png_destroy_write_struct(&write_ptr
, &write_info_ptr
);
522 png_debug(0, "Setting jmpbuf for write struct\n");
523 #ifdef USE_FAR_KEYWORD
524 png_memcpy(read_ptr
->jmpbuf
,jmpbuf
,sizeof(jmp_buf));
527 if (setjmp(write_ptr
->jmpbuf
))
530 fprintf(STDERR
, "%s -> %s: libpng write error\n", inname
, outname
);
531 png_destroy_read_struct(&read_ptr
, &read_info_ptr
, &end_info_ptr
);
532 png_destroy_write_struct(&write_ptr
, &write_info_ptr
);
538 #ifdef USE_FAR_KEYWORD
539 png_memcpy(write_ptr
->jmpbuf
,jmpbuf
,sizeof(jmp_buf));
541 png_debug(0, "Initializing input and output streams\n");
542 #if !defined(PNG_NO_STDIO)
543 png_init_io(read_ptr
, fpin
);
544 png_init_io(write_ptr
, fpout
);
546 png_set_read_fn(read_ptr
, (png_voidp
)fpin
, png_default_read_data
);
547 png_set_write_fn(write_ptr
, (png_voidp
)fpout
, png_default_write_data
,
548 #if defined(PNG_WRITE_FLUSH_SUPPORTED)
554 if(status_dots_requested
== 1)
556 png_set_write_status_fn(write_ptr
, write_row_callback
);
557 png_set_read_status_fn(read_ptr
, read_row_callback
);
561 png_set_write_status_fn(write_ptr
, NULL
);
562 png_set_read_status_fn(read_ptr
, NULL
);
565 # if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
567 png_set_write_user_transform_fn(write_ptr
, count_black_pixels
);
570 png_debug(0, "Reading info struct\n");
571 png_read_info(read_ptr
, read_info_ptr
);
573 png_debug(0, "Transferring info struct\n");
575 int interlace_type
, compression_type
, filter_type
;
577 if (png_get_IHDR(read_ptr
, read_info_ptr
, &width
, &height
, &bit_depth
,
578 &color_type
, &interlace_type
, &compression_type
, &filter_type
))
580 png_set_IHDR(write_ptr
, write_info_ptr
, width
, height
, bit_depth
,
581 #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
582 color_type
, interlace_type
, compression_type
, filter_type
);
584 color_type
, PNG_INTERLACE_NONE
, compression_type
, filter_type
);
588 #if defined(PNG_READ_bKGD_SUPPORTED) && defined(PNG_WRITE_bKGD_SUPPORTED)
590 png_color_16p background
;
592 if (png_get_bKGD(read_ptr
, read_info_ptr
, &background
))
594 png_set_bKGD(write_ptr
, write_info_ptr
, background
);
598 #if defined(PNG_READ_cHRM_SUPPORTED) && defined(PNG_WRITE_cHRM_SUPPORTED)
600 double white_x
, white_y
, red_x
, red_y
, green_x
, green_y
, blue_x
, blue_y
;
602 if (png_get_cHRM(read_ptr
, read_info_ptr
, &white_x
, &white_y
, &red_x
,
603 &red_y
, &green_x
, &green_y
, &blue_x
, &blue_y
))
605 png_set_cHRM(write_ptr
, write_info_ptr
, white_x
, white_y
, red_x
,
606 red_y
, green_x
, green_y
, blue_x
, blue_y
);
610 #if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_WRITE_gAMA_SUPPORTED)
614 if (png_get_gAMA(read_ptr
, read_info_ptr
, &gamma
))
616 png_set_gAMA(write_ptr
, write_info_ptr
, gamma
);
620 #if defined(PNG_READ_sRGB_SUPPORTED) && defined(PNG_WRITE_sRGB_SUPPORTED)
624 if (png_get_sRGB(read_ptr
, read_info_ptr
, &intent
))
626 png_set_sRGB(write_ptr
, write_info_ptr
, intent
);
630 #if defined(PNG_READ_hIST_SUPPORTED) && defined(PNG_WRITE_hIST_SUPPORTED)
634 if (png_get_hIST(read_ptr
, read_info_ptr
, &hist
))
636 png_set_hIST(write_ptr
, write_info_ptr
, hist
);
640 #if defined(PNG_READ_oFFs_SUPPORTED) && defined(PNG_WRITE_oFFs_SUPPORTED)
642 png_uint_32 offset_x
, offset_y
;
645 if (png_get_oFFs(read_ptr
, read_info_ptr
,&offset_x
,&offset_y
,&unit_type
))
647 png_set_oFFs(write_ptr
, write_info_ptr
, offset_x
, offset_y
, unit_type
);
651 #if defined(PNG_READ_pCAL_SUPPORTED) && defined(PNG_WRITE_pCAL_SUPPORTED)
653 png_charp purpose
, units
;
658 if (png_get_pCAL(read_ptr
, read_info_ptr
, &purpose
, &X0
, &X1
, &type
,
659 &nparams
, &units
, ¶ms
))
661 png_set_pCAL(write_ptr
, write_info_ptr
, purpose
, X0
, X1
, type
,
662 nparams
, units
, params
);
666 #if defined(PNG_READ_pHYs_SUPPORTED) && defined(PNG_WRITE_pHYs_SUPPORTED)
668 png_uint_32 res_x
, res_y
;
671 if (png_get_pHYs(read_ptr
, read_info_ptr
, &res_x
, &res_y
, &unit_type
))
673 png_set_pHYs(write_ptr
, write_info_ptr
, res_x
, res_y
, unit_type
);
681 if (png_get_PLTE(read_ptr
, read_info_ptr
, &palette
, &num_palette
))
683 png_set_PLTE(write_ptr
, write_info_ptr
, palette
, num_palette
);
686 #if defined(PNG_READ_sBIT_SUPPORTED) && defined(PNG_WRITE_sBIT_SUPPORTED)
688 png_color_8p sig_bit
;
690 if (png_get_sBIT(read_ptr
, read_info_ptr
, &sig_bit
))
692 png_set_sBIT(write_ptr
, write_info_ptr
, sig_bit
);
696 #if (defined(PNG_READ_tEXt_SUPPORTED) && defined(PNG_WRITE_tEXt_SUPPORTED)) || \
697 (defined(PNG_READ_zTXt_SUPPORTED) && defined(PNG_WRITE_zTXt_SUPPORTED))
702 if (png_get_text(read_ptr
, read_info_ptr
, &text_ptr
, &num_text
) > 0)
704 png_debug1(0, "Handling %d tEXt/zTXt chunks\n", num_text
);
705 png_set_text(write_ptr
, write_info_ptr
, text_ptr
, num_text
);
709 #if defined(PNG_READ_tIME_SUPPORTED) && defined(PNG_WRITE_tIME_SUPPORTED)
713 if (png_get_tIME(read_ptr
, read_info_ptr
, &mod_time
))
715 png_set_tIME(write_ptr
, write_info_ptr
, mod_time
);
719 #if defined(PNG_READ_tRNS_SUPPORTED) && defined(PNG_WRITE_tRNS_SUPPORTED)
723 png_color_16p trans_values
;
725 if (png_get_tRNS(read_ptr
, read_info_ptr
, &trans
, &num_trans
,
728 png_set_tRNS(write_ptr
, write_info_ptr
, trans
, num_trans
,
734 png_debug(0, "\nWriting info struct\n");
735 png_write_info(write_ptr
, write_info_ptr
);
737 png_debug(0, "\nAllocating row buffer \n");
738 row_buf
= (png_bytep
)png_malloc(read_ptr
,
739 png_get_rowbytes(read_ptr
, read_info_ptr
));
742 fprintf(STDERR
, "No memory to allocate row buffer\n");
743 png_destroy_read_struct(&read_ptr
, &read_info_ptr
, (png_infopp
)NULL
);
744 png_destroy_write_struct(&write_ptr
, &write_info_ptr
);
749 png_debug(0, "Writing row data\n");
751 num_pass
= png_set_interlace_handling(read_ptr
);
752 png_set_interlace_handling(write_ptr
);
754 for (pass
= 0; pass
< num_pass
; pass
++)
756 png_debug1(0, "Writing row data for pass %d\n",pass
);
757 for (y
= 0; y
< height
; y
++)
759 png_read_rows(read_ptr
, (png_bytepp
)&row_buf
, (png_bytepp
)NULL
, 1);
760 png_write_rows(write_ptr
, (png_bytepp
)&row_buf
, 1);
764 png_debug(0, "Reading and writing end_info data\n");
765 png_read_end(read_ptr
, end_info_ptr
);
766 png_write_end(write_ptr
, end_info_ptr
);
768 #ifdef PNG_EASY_ACCESS_SUPPORTED
771 png_uint_32 iwidth
, iheight
;
772 iwidth
= png_get_image_width(write_ptr
, write_info_ptr
);
773 iheight
= png_get_image_height(write_ptr
, write_info_ptr
);
774 fprintf(STDERR
, "Image width = %lu, height = %lu\n",
779 png_debug(0, "Destroying data structs\n");
780 png_free(read_ptr
, row_buf
);
781 png_destroy_read_struct(&read_ptr
, &read_info_ptr
, &end_info_ptr
);
782 png_destroy_write_struct(&write_ptr
, &write_info_ptr
);
787 png_debug(0, "Opening files for comparison\n");
788 if ((fpin
= fopen(inname
, "rb")) == NULL
)
790 fprintf(STDERR
, "Could not find file %s\n", inname
);
794 if ((fpout
= fopen(outname
, "rb")) == NULL
)
796 fprintf(STDERR
, "Could not find file %s\n", outname
);
803 png_size_t num_in
, num_out
;
805 num_in
= fread(inbuf
, 1, 1, fpin
);
806 num_out
= fread(outbuf
, 1, 1, fpout
);
808 if (num_in
!= num_out
)
810 fprintf(STDERR
, "Files %s and %s are of a different size\n",
812 if(wrote_question
== 0)
815 " Was %s written with the same chunk size (8k),",inname
);
817 " filtering\n heuristic (libpng default), compression");
819 " level (zlib default)\n and zlib version (%s)?\n\n",
831 if (png_memcmp(inbuf
, outbuf
, num_in
))
833 fprintf(STDERR
, "Files %s and %s are different\n", inname
, outname
);
834 if(wrote_question
== 0)
837 " Was %s written with the same chunk size (8k),",inname
);
839 " filtering\n heuristic (libpng default), compression");
841 " level (zlib default)\n and zlib version (%s)?\n\n",
857 /* input and output filenames */
859 PNG_CONST
char *inname
= "pngtest/png";
860 PNG_CONST
char *outname
= "pngout/png";
862 static PNG_CONST
char *inname
= "pngtest.png";
863 static PNG_CONST
char *outname
= "pngout.png";
867 main(int argc
, char *argv
[])
872 fprintf(STDERR
, "Testing libpng version %s\n", PNG_LIBPNG_VER_STRING
);
873 fprintf(STDERR
, " with zlib version %s\n", ZLIB_VERSION
);
875 /* Do some consistency checking on the memory allocation settings, I'm
876 not sure this matters, but it is nice to know, the first of these
877 tests should be impossible because of the way the macros are set
879 #if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K)
880 fprintf(STDERR
, " NOTE: Zlib compiled for max 64k, libpng not\n");
882 /* I think the following can happen. */
883 #if !defined(MAXSEG_64K) && defined(PNG_MAX_MALLOC_64K)
884 fprintf(STDERR
, " NOTE: libpng compiled for max 64k, zlib not\n");
887 if (strcmp(png_libpng_ver
, PNG_LIBPNG_VER_STRING
))
890 "Warning: versions are different between png.h and png.c\n");
891 fprintf(STDERR
, " png.h version: %s\n", PNG_LIBPNG_VER_STRING
);
892 fprintf(STDERR
, " png.c version: %s\n\n", png_libpng_ver
);
898 if (strcmp(argv
[1], "-m") == 0)
901 status_dots_requested
= 0;
903 else if (strcmp(argv
[1], "-mv") == 0 ||
904 strcmp(argv
[1], "-vm") == 0 )
908 status_dots_requested
= 1;
910 else if (strcmp(argv
[1], "-v") == 0)
913 status_dots_requested
= 1;
919 status_dots_requested
= 0;
923 if (!multiple
&& argc
== 3+verbose
)
924 outname
= argv
[2+verbose
];
926 if ((!multiple
&& argc
> 3+verbose
) || (multiple
&& argc
< 2))
929 "usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n",
932 " reads/writes one PNG file (without -m) or multiple files (-m)\n");
934 " with -m %s is used as a temporary file\n", outname
);
941 #ifdef PNGTEST_MEMORY_DEBUG
942 int allocation_now
= current_allocation
;
944 for (i
=2; i
<argc
; ++i
)
947 fprintf(STDERR
, "Testing %s:",argv
[i
]);
948 kerror
= test_one_file(argv
[i
], outname
);
950 #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
951 fprintf(STDERR
, " PASS (%lu black pixels)\n",black_pixels
);
953 fprintf(STDERR
, " PASS\n");
956 fprintf(STDERR
, " FAIL\n");
959 #ifdef PNGTEST_MEMORY_DEBUG
960 if (allocation_now
!= current_allocation
)
961 fprintf(STDERR
, "MEMORY ERROR: %d bytes lost\n",
962 current_allocation
-allocation_now
);
963 if (current_allocation
!= 0) {
964 memory_infop pinfo
= pinformation
;
966 fprintf(STDERR
, "MEMORY ERROR: %d bytes still allocated\n",
968 while (pinfo
!= NULL
) {
969 fprintf(STDERR
, " %d bytes at %x\n", pinfo
->size
, pinfo
->pointer
);
975 #ifdef PNGTEST_MEMORY_DEBUG
976 fprintf(STDERR
, "Maximum memory allocation: %d bytes\n",
983 for (i
=0; i
<3; ++i
) {
985 #ifdef PNGTEST_MEMORY_DEBUG
986 int allocation_now
= current_allocation
;
988 if (i
== 1) status_dots_requested
= 1;
989 else if(verbose
== 0)status_dots_requested
= 0;
990 if (i
== 0 || verbose
== 1 || ierror
!= 0)
991 fprintf(STDERR
, "Testing %s:",inname
);
992 kerror
= test_one_file(inname
, outname
);
995 if(verbose
== 1 || i
== 2)
996 #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
997 fprintf(STDERR
, " PASS (%lu black pixels)\n",black_pixels
);
999 fprintf(STDERR
, " PASS\n");
1004 if(verbose
== 0 && i
!= 2)
1005 fprintf(STDERR
, "Testing %s:",inname
);
1006 fprintf(STDERR
, " FAIL\n");
1009 #ifdef PNGTEST_MEMORY_DEBUG
1010 if (allocation_now
!= current_allocation
)
1011 fprintf(STDERR
, "MEMORY ERROR: %d bytes lost\n",
1012 current_allocation
-allocation_now
);
1013 if (current_allocation
!= 0) {
1014 memory_infop pinfo
= pinformation
;
1016 fprintf(STDERR
, "MEMORY ERROR: %d bytes still allocated\n",
1017 current_allocation
);
1018 while (pinfo
!= NULL
) {
1019 fprintf(STDERR
, " %d bytes at %x\n", pinfo
->size
, pinfo
->pointer
);
1020 pinfo
= pinfo
->next
;
1025 #ifdef PNGTEST_MEMORY_DEBUG
1026 fprintf(STDERR
, "Maximum memory allocation: %d bytes\n",
1027 maximum_allocation
);
1032 fprintf(STDERR
, "libpng passes test\n");
1034 fprintf(STDERR
, "libpng FAILS test\n");
1035 return (int)(ierror
!= 0);