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