2 /* pngtest.c - a simple test program to test libpng
4 * libpng 1.0.3 -January 14, 1999
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, 1999 Glenn Randers-Pehrson
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
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 chunk size is not 8K.
19 * 3) unknown ancillary chunks exist in the input file.
20 * 4) others not listed here...
21 * In these cases, it is best to check with another tool such as "pngcheck"
22 * to see what the differences between the two images are.
24 * If a filename is given on the command-line, then this file is used
25 * for the input, rather than the default "pngtest.png". This allows
26 * testing a wide variety of files easily. You can also test a number
27 * of files at once by typing "pngtest -m file1.png file2.png ..."
33 /* Makes pngtest verbose so we can find problems (needs to be before png.h) */
40 #if defined(PNG_TIME_RFC1123_SUPPORTED)
41 static int tIME_chunk_present
=0;
42 static char tIME_string
[30] = "no tIME chunk present in file";
43 #endif /* PNG_TIME_RFC1123_SUPPORTED */
45 int test_one_file
PNGARG((PNG_CONST
char *inname
, PNG_CONST
char *outname
));
51 /* defined so I can write to a file on gui/windowing platforms */
52 /* #define STDERR stderr */
53 #define STDERR stdout /* for DOS */
55 /* example of using row callbacks to make a simple progress meter */
56 static int status_pass
=1;
57 static int status_dots_requested
=0;
58 static int status_dots
=1;
61 read_row_callback(png_structp png_ptr
, png_uint_32 row_number
, int pass
)
63 if(png_ptr
== NULL
|| row_number
> 0x3fffffffL
) return;
64 if(status_pass
!= pass
)
66 fprintf(stdout
,"\n Pass %d: ",pass
);
73 fprintf(stdout
, "\n ");
80 write_row_callback(png_structp png_ptr
, png_uint_32 row_number
, int pass
)
82 if(png_ptr
== NULL
|| row_number
> 0x3fffffffL
|| pass
> 7) return;
87 #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
88 /* example of using user transform callback (we don't transform anything,
89 but merely count the zero samples) */
91 static png_uint_32 zero_samples
;
94 count_zero_samples(png_structp png_ptr
, png_row_infop row_info
, png_bytep data
)
97 if(png_ptr
== NULL
)return;
99 /* contents of row_info:
100 * png_uint_32 width width of row
101 * png_uint_32 rowbytes number of bytes in row
102 * png_byte color_type color type of pixels
103 * png_byte bit_depth bit depth of samples
104 * png_byte channels number of channels (1-4)
105 * png_byte pixel_depth bits per pixel (depth*channels)
108 /* counts the number of zero samples (or zero pixels if color_type is 3 */
110 if(row_info
->color_type
== 0 || row_info
->color_type
== 3)
113 png_uint_32 n
, nstop
;
114 for (n
=0, nstop
=row_info
->width
; n
<nstop
; n
++)
116 if(row_info
->bit_depth
== 1)
118 if(((*dp
<< pos
++ )& 0x80) == 0) zero_samples
++;
125 if(row_info
->bit_depth
== 2)
127 if(((*dp
<< (pos
+=2))& 0xc0) == 0) zero_samples
++;
134 if(row_info
->bit_depth
== 4)
136 if(((*dp
<< (pos
+=4))& 0xf0) == 0) zero_samples
++;
143 if(row_info
->bit_depth
== 8)
144 if(*dp
++ == 0) zero_samples
++;
145 if(row_info
->bit_depth
== 16)
147 if((*dp
| *(dp
+1)) == 0) zero_samples
++;
152 else /* other color types */
154 png_uint_32 n
, nstop
;
156 int color_channels
= row_info
->channels
;
157 if(row_info
->color_type
> 3)color_channels
--;
159 for (n
=0, nstop
=row_info
->width
; n
<nstop
; n
++)
161 for (channel
= 0; channel
< color_channels
; channel
++)
163 if(row_info
->bit_depth
== 8)
164 if(*dp
++ == 0) zero_samples
++;
165 if(row_info
->bit_depth
== 16)
167 if((*dp
| *(dp
+1)) == 0) zero_samples
++;
171 if(row_info
->color_type
> 3)
174 if(row_info
->bit_depth
== 16)dp
++;
179 #endif /* PNG_WRITE_USER_TRANSFORM_SUPPORTED */
181 static int verbose
= 0;
182 static int wrote_question
= 0;
184 #if defined(PNG_NO_STDIO)
185 /* START of code to validate stdio-free compilation */
186 /* These copies of the default read/write functions come from pngrio.c and */
187 /* pngwio.c. They allow "don't include stdio" testing of the library. */
188 /* This is the function that does the actual reading of data. If you are
189 not reading from a standard C stream, you should create a replacement
190 read_data function and use it at run time with png_set_read_fn(), rather
191 than changing the library. */
192 #ifndef USE_FAR_KEYWORD
194 png_default_read_data(png_structp png_ptr
, png_bytep data
, png_size_t length
)
198 /* fread() returns 0 on error, so it is OK to store this in a png_size_t
199 * instead of an int, which is what fread() actually returns.
201 check
= (png_size_t
)fread(data
, (png_size_t
)1, length
,
202 (FILE *)png_ptr
->io_ptr
);
206 png_error(png_ptr
, "Read Error");
210 /* this is the model-independent version. Since the standard I/O library
211 can't handle far buffers in the medium and small models, we have to copy
215 #define NEAR_BUF_SIZE 1024
216 #define MIN(a,b) (a <= b ? a : b)
219 png_default_read_data(png_structp png_ptr
, png_bytep data
, png_size_t length
)
225 /* Check if data really is near. If so, use usual code. */
226 n_data
= (png_byte
*)CVT_PTR_NOCHECK(data
);
227 io_ptr
= (FILE *)CVT_PTR(png_ptr
->io_ptr
);
228 if ((png_bytep
)n_data
== data
)
230 check
= fread(n_data
, 1, length
, io_ptr
);
234 png_byte buf
[NEAR_BUF_SIZE
];
235 png_size_t read
, remaining
, err
;
240 read
= MIN(NEAR_BUF_SIZE
, remaining
);
241 err
= fread(buf
, (png_size_t
)1, read
, io_ptr
);
242 png_memcpy(data
, buf
, read
); /* copy far buffer to near buffer */
250 while (remaining
!= 0);
254 png_error(png_ptr
, "read Error");
257 #endif /* USE_FAR_KEYWORD */
259 #if defined(PNG_WRITE_FLUSH_SUPPORTED)
261 png_default_flush(png_structp png_ptr
)
264 io_ptr
= (FILE *)CVT_PTR((png_ptr
->io_ptr
));
270 /* This is the function that does the actual writing of data. If you are
271 not writing to a standard C stream, you should create a replacement
272 write_data function and use it at run time with png_set_write_fn(), rather
273 than changing the library. */
274 #ifndef USE_FAR_KEYWORD
276 png_default_write_data(png_structp png_ptr
, png_bytep data
, png_size_t length
)
280 check
= fwrite(data
, 1, length
, (FILE *)(png_ptr
->io_ptr
));
283 png_error(png_ptr
, "Write Error");
287 /* this is the model-independent version. Since the standard I/O library
288 can't handle far buffers in the medium and small models, we have to copy
292 #define NEAR_BUF_SIZE 1024
293 #define MIN(a,b) (a <= b ? a : b)
296 png_default_write_data(png_structp png_ptr
, png_bytep data
, png_size_t length
)
299 png_byte
*near_data
; /* Needs to be "png_byte *" instead of "png_bytep" */
302 /* Check if data really is near. If so, use usual code. */
303 near_data
= (png_byte
*)CVT_PTR_NOCHECK(data
);
304 io_ptr
= (FILE *)CVT_PTR(png_ptr
->io_ptr
);
305 if ((png_bytep
)near_data
== data
)
307 check
= fwrite(near_data
, 1, length
, io_ptr
);
311 png_byte buf
[NEAR_BUF_SIZE
];
312 png_size_t written
, remaining
, err
;
317 written
= MIN(NEAR_BUF_SIZE
, remaining
);
318 png_memcpy(buf
, data
, written
); /* copy far buffer to near buffer */
319 err
= fwrite(buf
, 1, written
, io_ptr
);
325 remaining
-= written
;
327 while (remaining
!= 0);
331 png_error(png_ptr
, "Write Error");
335 #endif /* USE_FAR_KEYWORD */
337 /* This function is called when there is a warning, but the library thinks
338 * it can continue anyway. Replacement functions don't have to do anything
339 * here if you don't want to. In the default configuration, png_ptr is
340 * not used, but it is passed in case it may be useful.
343 png_default_warning(png_structp png_ptr
, png_const_charp message
)
345 PNG_CONST
char *name
= "UNKNOWN (ERROR!)";
346 if (png_ptr
!= NULL
&& png_ptr
->error_ptr
!= NULL
)
347 name
= png_ptr
->error_ptr
;
348 fprintf(STDERR
, "%s: libpng warning: %s\n", name
, message
);
351 /* This is the default error handling function. Note that replacements for
352 * this function MUST NOT RETURN, or the program will likely crash. This
353 * function is used by default, or if the program supplies NULL for the
354 * error function pointer in png_set_error_fn().
357 png_default_error(png_structp png_ptr
, png_const_charp message
)
359 png_default_warning(png_ptr
, message
);
360 /* We can return because png_error calls the default handler, which is
361 * actually OK in this case. */
363 #endif /* PNG_NO_STDIO */
364 /* END of code to validate stdio-free compilation */
366 /* START of code to validate memory allocation and deallocation */
367 #ifdef PNG_USER_MEM_SUPPORTED
369 /* Allocate memory. For reasonable files, size should never exceed
370 64K. However, zlib may allocate more then 64K if you don't tell
371 it not to. See zconf.h and png.h for more information. zlib does
372 need to allocate exactly 64K, so whatever you call here must
373 have the ability to do that.
375 This piece of code can be compiled to validate max 64K allocations
376 by setting MAXSEG_64K in zlib zconf.h *or* PNG_MAX_MALLOC_64K. */
377 typedef struct memory_information
{
380 struct memory_information FAR
*next
;
381 } memory_information
;
382 typedef memory_information FAR
*memory_infop
;
384 static memory_infop pinformation
= NULL
;
385 static int current_allocation
= 0;
386 static int maximum_allocation
= 0;
388 extern PNG_EXPORT(png_voidp
,png_debug_malloc
) PNGARG((png_structp png_ptr
,
390 extern PNG_EXPORT(void,png_debug_free
) PNGARG((png_structp png_ptr
,
394 png_debug_malloc(png_structp png_ptr
, png_uint_32 size
) {
396 /* png_malloc has already tested for NULL; png_create_struct calls
397 png_debug_malloc directly, with png_ptr == NULL which is OK */
400 return (png_voidp
)(NULL
);
402 /* This calls the library allocator twice, once to get the requested
403 buffer and once to get a new free list entry. */
405 memory_infop pinfo
= png_malloc_default(png_ptr
, sizeof *pinfo
);
407 current_allocation
+= size
;
408 if (current_allocation
> maximum_allocation
)
409 maximum_allocation
= current_allocation
;
410 pinfo
->pointer
= png_malloc_default(png_ptr
, size
);
411 pinfo
->next
= pinformation
;
412 pinformation
= pinfo
;
413 /* Make sure the caller isn't assuming zeroed memory. */
414 png_memset(pinfo
->pointer
, 0xdd, pinfo
->size
);
415 return (png_voidp
)(pinfo
->pointer
);
419 /* Free a pointer. It is removed from the list at the same time. */
421 png_debug_free(png_structp png_ptr
, png_voidp ptr
)
424 fprintf(STDERR
, "NULL pointer to png_debug_free.\n");
426 #if 0 /* This happens all the time. */
427 fprintf(STDERR
, "WARNING: freeing NULL pointer\n");
432 /* Unlink the element from the list. */
434 memory_infop FAR
*ppinfo
= &pinformation
;
436 memory_infop pinfo
= *ppinfo
;
437 if (pinfo
->pointer
== ptr
) {
438 *ppinfo
= pinfo
->next
;
439 current_allocation
-= pinfo
->size
;
440 if (current_allocation
< 0)
441 fprintf(STDERR
, "Duplicate free of memory\n");
442 /* We must free the list element too, but first kill
443 the memory that is to be freed. */
444 memset(ptr
, 0x55, pinfo
->size
);
445 png_free_default(png_ptr
, pinfo
);
448 if (pinfo
->next
== NULL
) {
449 fprintf(STDERR
, "Pointer %x not found\n", ptr
);
452 ppinfo
= &pinfo
->next
;
456 /* Finally free the data. */
457 png_free_default(png_ptr
, ptr
);
459 #endif /* PNG_USER_MEM_SUPPORTED */
460 /* END of code to test memory allocation/deallocation */
464 test_one_file(PNG_CONST
char *inname
, PNG_CONST
char *outname
)
466 static FILE *fpin
, *fpout
; /* "static" prevents setjmp corruption */
467 png_structp read_ptr
, write_ptr
;
468 png_infop read_info_ptr
, write_info_ptr
, end_info_ptr
;
471 png_uint_32 width
, height
;
473 int bit_depth
, color_type
;
474 #ifdef USE_FAR_KEYWORD
478 char inbuf
[256], outbuf
[256];
480 row_buf
= (png_bytep
)NULL
;
482 if ((fpin
= fopen(inname
, "rb")) == NULL
)
484 fprintf(STDERR
, "Could not find input file %s\n", inname
);
488 if ((fpout
= fopen(outname
, "wb")) == NULL
)
490 fprintf(STDERR
, "Could not open output file %s\n", outname
);
495 png_debug(0, "Allocating read and write structures\n");
496 #ifdef PNG_USER_MEM_SUPPORTED
497 read_ptr
= png_create_read_struct_2(PNG_LIBPNG_VER_STRING
, (png_voidp
)NULL
,
498 (png_error_ptr
)NULL
, (png_error_ptr
)NULL
, (png_voidp
)NULL
,
499 (png_malloc_ptr
)png_debug_malloc
, (png_free_ptr
)png_debug_free
);
501 read_ptr
= png_create_read_struct(PNG_LIBPNG_VER_STRING
, (png_voidp
)NULL
,
502 (png_error_ptr
)NULL
, (png_error_ptr
)NULL
);
504 #if defined(PNG_NO_STDIO)
505 png_set_error_fn(read_ptr
, (png_voidp
)inname
, png_default_error
,
506 png_default_warning
);
508 #ifdef PNG_USER_MEM_SUPPORTED
509 write_ptr
= png_create_write_struct_2(PNG_LIBPNG_VER_STRING
, (png_voidp
)NULL
,
510 (png_error_ptr
)NULL
, (png_error_ptr
)NULL
, (png_voidp
)NULL
,
511 (png_malloc_ptr
)png_debug_malloc
, (png_free_ptr
)png_debug_free
);
513 write_ptr
= png_create_write_struct(PNG_LIBPNG_VER_STRING
, (png_voidp
)NULL
,
514 (png_error_ptr
)NULL
, (png_error_ptr
)NULL
);
516 #if defined(PNG_NO_STDIO)
517 png_set_error_fn(write_ptr
, (png_voidp
)inname
, png_default_error
,
518 png_default_warning
);
520 png_debug(0, "Allocating read_info, write_info and end_info structures\n");
521 read_info_ptr
= png_create_info_struct(read_ptr
);
522 write_info_ptr
= png_create_info_struct(write_ptr
);
523 end_info_ptr
= png_create_info_struct(read_ptr
);
524 #ifdef PNG_USER_MEM_SUPPORTED
527 png_debug(0, "Setting jmpbuf for read struct\n");
528 #ifdef USE_FAR_KEYWORD
531 if (setjmp(read_ptr
->jmpbuf
))
534 fprintf(STDERR
, "%s -> %s: libpng read error\n", inname
, outname
);
535 png_destroy_read_struct(&read_ptr
, &read_info_ptr
, &end_info_ptr
);
536 png_destroy_write_struct(&write_ptr
, &write_info_ptr
);
541 #ifdef USE_FAR_KEYWORD
542 png_memcpy(read_ptr
->jmpbuf
,jmpbuf
,sizeof(jmp_buf));
545 png_debug(0, "Setting jmpbuf for write struct\n");
546 #ifdef USE_FAR_KEYWORD
549 if (setjmp(write_ptr
->jmpbuf
))
552 fprintf(STDERR
, "%s -> %s: libpng write error\n", inname
, outname
);
553 png_destroy_read_struct(&read_ptr
, &read_info_ptr
, &end_info_ptr
);
554 png_destroy_write_struct(&write_ptr
, &write_info_ptr
);
559 #ifdef USE_FAR_KEYWORD
560 png_memcpy(write_ptr
->jmpbuf
,jmpbuf
,sizeof(jmp_buf));
563 png_debug(0, "Initializing input and output streams\n");
564 #if !defined(PNG_NO_STDIO)
565 png_init_io(read_ptr
, fpin
);
566 png_init_io(write_ptr
, fpout
);
568 png_set_read_fn(read_ptr
, (png_voidp
)fpin
, png_default_read_data
);
569 png_set_write_fn(write_ptr
, (png_voidp
)fpout
, png_default_write_data
,
570 #if defined(PNG_WRITE_FLUSH_SUPPORTED)
576 if(status_dots_requested
== 1)
578 png_set_write_status_fn(write_ptr
, write_row_callback
);
579 png_set_read_status_fn(read_ptr
, read_row_callback
);
583 png_set_write_status_fn(write_ptr
, NULL
);
584 png_set_read_status_fn(read_ptr
, NULL
);
587 # if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
589 png_set_write_user_transform_fn(write_ptr
, count_zero_samples
);
592 png_debug(0, "Reading info struct\n");
593 png_read_info(read_ptr
, read_info_ptr
);
595 png_debug(0, "Transferring info struct\n");
597 int interlace_type
, compression_type
, filter_type
;
599 if (png_get_IHDR(read_ptr
, read_info_ptr
, &width
, &height
, &bit_depth
,
600 &color_type
, &interlace_type
, &compression_type
, &filter_type
))
602 png_set_IHDR(write_ptr
, write_info_ptr
, width
, height
, bit_depth
,
603 #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
604 color_type
, interlace_type
, compression_type
, filter_type
);
606 color_type
, PNG_INTERLACE_NONE
, compression_type
, filter_type
);
610 #if defined(PNG_READ_bKGD_SUPPORTED) && defined(PNG_WRITE_bKGD_SUPPORTED)
612 png_color_16p background
;
614 if (png_get_bKGD(read_ptr
, read_info_ptr
, &background
))
616 png_set_bKGD(write_ptr
, write_info_ptr
, background
);
620 #if defined(PNG_READ_cHRM_SUPPORTED) && defined(PNG_WRITE_cHRM_SUPPORTED)
622 double white_x
, white_y
, red_x
, red_y
, green_x
, green_y
, blue_x
, blue_y
;
624 if (png_get_cHRM(read_ptr
, read_info_ptr
, &white_x
, &white_y
, &red_x
,
625 &red_y
, &green_x
, &green_y
, &blue_x
, &blue_y
))
627 png_set_cHRM(write_ptr
, write_info_ptr
, white_x
, white_y
, red_x
,
628 red_y
, green_x
, green_y
, blue_x
, blue_y
);
632 #if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_WRITE_gAMA_SUPPORTED)
636 if (png_get_gAMA(read_ptr
, read_info_ptr
, &gamma
))
638 png_set_gAMA(write_ptr
, write_info_ptr
, gamma
);
642 #if defined(PNG_READ_sRGB_SUPPORTED) && defined(PNG_WRITE_sRGB_SUPPORTED)
646 if (png_get_sRGB(read_ptr
, read_info_ptr
, &intent
))
648 png_set_sRGB(write_ptr
, write_info_ptr
, intent
);
652 #if defined(PNG_READ_hIST_SUPPORTED) && defined(PNG_WRITE_hIST_SUPPORTED)
656 if (png_get_hIST(read_ptr
, read_info_ptr
, &hist
))
658 png_set_hIST(write_ptr
, write_info_ptr
, hist
);
662 #if defined(PNG_READ_oFFs_SUPPORTED) && defined(PNG_WRITE_oFFs_SUPPORTED)
664 png_uint_32 offset_x
, offset_y
;
667 if (png_get_oFFs(read_ptr
, read_info_ptr
,&offset_x
,&offset_y
,&unit_type
))
669 png_set_oFFs(write_ptr
, write_info_ptr
, offset_x
, offset_y
, unit_type
);
673 #if defined(PNG_READ_pCAL_SUPPORTED) && defined(PNG_WRITE_pCAL_SUPPORTED)
675 png_charp purpose
, units
;
680 if (png_get_pCAL(read_ptr
, read_info_ptr
, &purpose
, &X0
, &X1
, &type
,
681 &nparams
, &units
, ¶ms
))
683 png_set_pCAL(write_ptr
, write_info_ptr
, purpose
, X0
, X1
, type
,
684 nparams
, units
, params
);
688 #if defined(PNG_READ_pHYs_SUPPORTED) && defined(PNG_WRITE_pHYs_SUPPORTED)
690 png_uint_32 res_x
, res_y
;
693 if (png_get_pHYs(read_ptr
, read_info_ptr
, &res_x
, &res_y
, &unit_type
))
695 png_set_pHYs(write_ptr
, write_info_ptr
, res_x
, res_y
, unit_type
);
703 if (png_get_PLTE(read_ptr
, read_info_ptr
, &palette
, &num_palette
))
705 png_set_PLTE(write_ptr
, write_info_ptr
, palette
, num_palette
);
708 #if defined(PNG_READ_sBIT_SUPPORTED) && defined(PNG_WRITE_sBIT_SUPPORTED)
710 png_color_8p sig_bit
;
712 if (png_get_sBIT(read_ptr
, read_info_ptr
, &sig_bit
))
714 png_set_sBIT(write_ptr
, write_info_ptr
, sig_bit
);
718 #if (defined(PNG_READ_tEXt_SUPPORTED) && defined(PNG_WRITE_tEXt_SUPPORTED)) || \
719 (defined(PNG_READ_zTXt_SUPPORTED) && defined(PNG_WRITE_zTXt_SUPPORTED))
724 if (png_get_text(read_ptr
, read_info_ptr
, &text_ptr
, &num_text
) > 0)
726 png_debug1(0, "Handling %d tEXt/zTXt chunks\n", num_text
);
727 png_set_text(write_ptr
, write_info_ptr
, text_ptr
, num_text
);
731 #if defined(PNG_READ_tIME_SUPPORTED) && defined(PNG_WRITE_tIME_SUPPORTED)
735 if (png_get_tIME(read_ptr
, read_info_ptr
, &mod_time
))
737 png_set_tIME(write_ptr
, write_info_ptr
, mod_time
);
738 #if defined(PNG_TIME_RFC1123_SUPPORTED)
739 /* we have to use png_strcpy instead of "=" because the string
740 pointed to by png_convert_to_rfc1123() gets free'ed before
742 png_strcpy(tIME_string
,png_convert_to_rfc1123(read_ptr
, mod_time
));
743 tIME_chunk_present
++;
744 #endif /* PNG_TIME_RFC1123_SUPPORTED */
748 #if defined(PNG_READ_tRNS_SUPPORTED) && defined(PNG_WRITE_tRNS_SUPPORTED)
752 png_color_16p trans_values
;
754 if (png_get_tRNS(read_ptr
, read_info_ptr
, &trans
, &num_trans
,
757 png_set_tRNS(write_ptr
, write_info_ptr
, trans
, num_trans
,
763 png_debug(0, "\nWriting info struct\n");
764 png_write_info(write_ptr
, write_info_ptr
);
766 png_debug(0, "\nAllocating row buffer \n");
767 row_buf
= (png_bytep
)png_malloc(read_ptr
,
768 png_get_rowbytes(read_ptr
, read_info_ptr
));
771 fprintf(STDERR
, "No memory to allocate row buffer\n");
772 png_destroy_read_struct(&read_ptr
, &read_info_ptr
, (png_infopp
)NULL
);
773 png_destroy_write_struct(&write_ptr
, &write_info_ptr
);
778 png_debug(0, "Writing row data\n");
780 num_pass
= png_set_interlace_handling(read_ptr
);
781 png_set_interlace_handling(write_ptr
);
783 for (pass
= 0; pass
< num_pass
; pass
++)
785 png_debug1(0, "Writing row data for pass %d\n",pass
);
786 for (y
= 0; y
< height
; y
++)
788 png_read_rows(read_ptr
, (png_bytepp
)&row_buf
, (png_bytepp
)NULL
, 1);
789 png_write_rows(write_ptr
, (png_bytepp
)&row_buf
, 1);
793 png_debug(0, "Reading and writing end_info data\n");
794 png_read_end(read_ptr
, end_info_ptr
);
795 png_write_end(write_ptr
, end_info_ptr
);
797 #ifdef PNG_EASY_ACCESS_SUPPORTED
800 png_uint_32 iwidth
, iheight
;
801 iwidth
= png_get_image_width(write_ptr
, write_info_ptr
);
802 iheight
= png_get_image_height(write_ptr
, write_info_ptr
);
803 fprintf(STDERR
, "Image width = %lu, height = %lu\n",
808 png_debug(0, "Destroying data structs\n");
809 png_free(read_ptr
, row_buf
);
810 png_destroy_read_struct(&read_ptr
, &read_info_ptr
, &end_info_ptr
);
811 png_destroy_write_struct(&write_ptr
, &write_info_ptr
);
816 png_debug(0, "Opening files for comparison\n");
817 if ((fpin
= fopen(inname
, "rb")) == NULL
)
819 fprintf(STDERR
, "Could not find file %s\n", inname
);
823 if ((fpout
= fopen(outname
, "rb")) == NULL
)
825 fprintf(STDERR
, "Could not find file %s\n", outname
);
832 png_size_t num_in
, num_out
;
834 num_in
= fread(inbuf
, 1, 1, fpin
);
835 num_out
= fread(outbuf
, 1, 1, fpout
);
837 if (num_in
!= num_out
)
839 fprintf(STDERR
, "Files %s and %s are of a different size\n",
841 if(wrote_question
== 0)
844 " Was %s written with the same chunk size (8k),",inname
);
846 " filtering\n heuristic (libpng default), compression");
848 " level (zlib default)\n and zlib version (%s)?\n\n",
860 if (png_memcmp(inbuf
, outbuf
, num_in
))
862 fprintf(STDERR
, "Files %s and %s are different\n", inname
, outname
);
863 if(wrote_question
== 0)
866 " Was %s written with the same chunk size (8k),",inname
);
868 " filtering\n heuristic (libpng default), compression");
870 " level (zlib default)\n and zlib version (%s)?\n\n",
886 /* input and output filenames */
888 PNG_CONST
char *inname
= "pngtest/png";
889 PNG_CONST
char *outname
= "pngout/png";
891 static PNG_CONST
char *inname
= "pngtest.png";
892 static PNG_CONST
char *outname
= "pngout.png";
896 main(int argc
, char *argv
[])
901 fprintf(STDERR
, "Testing libpng version %s\n", PNG_LIBPNG_VER_STRING
);
902 fprintf(STDERR
, " with zlib version %s\n", ZLIB_VERSION
);
903 fprintf(STDERR
,"%s",png_get_copyright(NULL
));
905 /* Do some consistency checking on the memory allocation settings, I'm
906 not sure this matters, but it is nice to know, the first of these
907 tests should be impossible because of the way the macros are set
909 #if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K)
910 fprintf(STDERR
, " NOTE: Zlib compiled for max 64k, libpng not\n");
912 /* I think the following can happen. */
913 #if !defined(MAXSEG_64K) && defined(PNG_MAX_MALLOC_64K)
914 fprintf(STDERR
, " NOTE: libpng compiled for max 64k, zlib not\n");
917 if (strcmp(png_libpng_ver
, PNG_LIBPNG_VER_STRING
))
920 "Warning: versions are different between png.h and png.c\n");
921 fprintf(STDERR
, " png.h version: %s\n", PNG_LIBPNG_VER_STRING
);
922 fprintf(STDERR
, " png.c version: %s\n\n", png_libpng_ver
);
928 if (strcmp(argv
[1], "-m") == 0)
931 status_dots_requested
= 0;
933 else if (strcmp(argv
[1], "-mv") == 0 ||
934 strcmp(argv
[1], "-vm") == 0 )
938 status_dots_requested
= 1;
940 else if (strcmp(argv
[1], "-v") == 0)
943 status_dots_requested
= 1;
949 status_dots_requested
= 0;
953 if (!multiple
&& argc
== 3+verbose
)
954 outname
= argv
[2+verbose
];
956 if ((!multiple
&& argc
> 3+verbose
) || (multiple
&& argc
< 2))
959 "usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n",
962 " reads/writes one PNG file (without -m) or multiple files (-m)\n");
964 " with -m %s is used as a temporary file\n", outname
);
971 #ifdef PNG_USER_MEM_SUPPORTED
972 int allocation_now
= current_allocation
;
974 for (i
=2; i
<argc
; ++i
)
977 fprintf(STDERR
, "Testing %s:",argv
[i
]);
978 kerror
= test_one_file(argv
[i
], outname
);
981 #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
982 fprintf(STDERR
, " PASS (%lu zero samples)\n",zero_samples
);
984 fprintf(STDERR
, " PASS\n");
986 #if defined(PNG_TIME_RFC1123_SUPPORTED)
987 if(tIME_chunk_present
!= 0)
988 fprintf(STDERR
, " tIME = %s\n",tIME_string
);
989 tIME_chunk_present
= 0;
990 #endif /* PNG_TIME_RFC1123_SUPPORTED */
994 fprintf(STDERR
, " FAIL\n");
997 #ifdef PNG_USER_MEM_SUPPORTED
998 if (allocation_now
!= current_allocation
)
999 fprintf(STDERR
, "MEMORY ERROR: %d bytes lost\n",
1000 current_allocation
-allocation_now
);
1001 if (current_allocation
!= 0) {
1002 memory_infop pinfo
= pinformation
;
1004 fprintf(STDERR
, "MEMORY ERROR: %d bytes still allocated\n",
1005 current_allocation
);
1006 while (pinfo
!= NULL
) {
1007 fprintf(STDERR
, " %d bytes at %x\n", pinfo
->size
, pinfo
->pointer
);
1008 pinfo
= pinfo
->next
;
1013 #ifdef PNG_USER_MEM_SUPPORTED
1014 fprintf(STDERR
, "Maximum memory allocation: %d bytes\n",
1015 maximum_allocation
);
1021 for (i
=0; i
<3; ++i
) {
1023 #ifdef PNG_USER_MEM_SUPPORTED
1024 int allocation_now
= current_allocation
;
1026 if (i
== 1) status_dots_requested
= 1;
1027 else if(verbose
== 0)status_dots_requested
= 0;
1028 if (i
== 0 || verbose
== 1 || ierror
!= 0)
1029 fprintf(STDERR
, "Testing %s:",inname
);
1030 kerror
= test_one_file(inname
, outname
);
1033 if(verbose
== 1 || i
== 2)
1035 #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
1036 fprintf(STDERR
, " PASS (%lu zero samples)\n",zero_samples
);
1038 fprintf(STDERR
, " PASS\n");
1040 #if defined(PNG_TIME_RFC1123_SUPPORTED)
1041 if(tIME_chunk_present
!= 0)
1042 fprintf(STDERR
, " tIME = %s\n",tIME_string
);
1043 #endif /* PNG_TIME_RFC1123_SUPPORTED */
1048 if(verbose
== 0 && i
!= 2)
1049 fprintf(STDERR
, "Testing %s:",inname
);
1050 fprintf(STDERR
, " FAIL\n");
1053 #ifdef PNG_USER_MEM_SUPPORTED
1054 if (allocation_now
!= current_allocation
)
1055 fprintf(STDERR
, "MEMORY ERROR: %d bytes lost\n",
1056 current_allocation
-allocation_now
);
1057 if (current_allocation
!= 0) {
1058 memory_infop pinfo
= pinformation
;
1060 fprintf(STDERR
, "MEMORY ERROR: %d bytes still allocated\n",
1061 current_allocation
);
1062 while (pinfo
!= NULL
) {
1063 fprintf(STDERR
, " %d bytes at %x\n", pinfo
->size
, pinfo
->pointer
);
1064 pinfo
= pinfo
->next
;
1069 #ifdef PNG_USER_MEM_SUPPORTED
1070 fprintf(STDERR
, "Maximum memory allocation: %d bytes\n",
1071 maximum_allocation
);
1076 fprintf(STDERR
, "libpng passes test\n");
1078 fprintf(STDERR
, "libpng FAILS test\n");
1079 return (int)(ierror
!= 0);