]> git.lizzy.rs Git - irrlicht.git/blob - source/Irrlicht/libpng/pngtest.c
Merging r6145 through r6171 from trunk to ogl-es branch
[irrlicht.git] / source / Irrlicht / libpng / pngtest.c
1 \r
2 /* pngtest.c - a simple test program to test libpng\r
3  *\r
4  * Copyright (c) 2018-2019 Cosmin Truta\r
5  * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson\r
6  * Copyright (c) 1996-1997 Andreas Dilger\r
7  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.\r
8  *\r
9  * This code is released under the libpng license.\r
10  * For conditions of distribution and use, see the disclaimer\r
11  * and license in png.h\r
12  *\r
13  * This program reads in a PNG image, writes it out again, and then\r
14  * compares the two files.  If the files are identical, this shows that\r
15  * the basic chunk handling, filtering, and (de)compression code is working\r
16  * properly.  It does not currently test all of the transforms, although\r
17  * it probably should.\r
18  *\r
19  * The program will report "FAIL" in certain legitimate cases:\r
20  * 1) when the compression level or filter selection method is changed.\r
21  * 2) when the maximum IDAT size (PNG_ZBUF_SIZE in pngconf.h) is not 8192.\r
22  * 3) unknown unsafe-to-copy ancillary chunks or unknown critical chunks\r
23  *    exist in the input file.\r
24  * 4) others not listed here...\r
25  * In these cases, it is best to check with another tool such as "pngcheck"\r
26  * to see what the differences between the two files are.\r
27  *\r
28  * If a filename is given on the command-line, then this file is used\r
29  * for the input, rather than the default "pngtest.png".  This allows\r
30  * testing a wide variety of files easily.  You can also test a number\r
31  * of files at once by typing "pngtest -m file1.png file2.png ..."\r
32  */\r
33 \r
34 #define _POSIX_SOURCE 1\r
35 \r
36 #include <stdio.h>\r
37 #include <stdlib.h>\r
38 #include <string.h>\r
39 \r
40 /* Defined so I can write to a file on gui/windowing platforms */\r
41 /*  #define STDERR stderr  */\r
42 #define STDERR stdout   /* For DOS */\r
43 \r
44 #include "png.h"\r
45 \r
46 /* Known chunks that exist in pngtest.png must be supported or pngtest will fail\r
47  * simply as a result of re-ordering them.  This may be fixed in 1.7\r
48  *\r
49  * pngtest allocates a single row buffer for each row and overwrites it,\r
50  * therefore if the write side doesn't support the writing of interlaced images\r
51  * nothing can be done for an interlaced image (and the code below will fail\r
52  * horribly trying to write extra data after writing garbage).\r
53  */\r
54 #if defined PNG_READ_SUPPORTED && /* else nothing can be done */\\r
55    defined PNG_READ_bKGD_SUPPORTED &&\\r
56    defined PNG_READ_cHRM_SUPPORTED &&\\r
57    defined PNG_READ_gAMA_SUPPORTED &&\\r
58    defined PNG_READ_oFFs_SUPPORTED &&\\r
59    defined PNG_READ_pCAL_SUPPORTED &&\\r
60    defined PNG_READ_pHYs_SUPPORTED &&\\r
61    defined PNG_READ_sBIT_SUPPORTED &&\\r
62    defined PNG_READ_sCAL_SUPPORTED &&\\r
63    defined PNG_READ_sRGB_SUPPORTED &&\\r
64    defined PNG_READ_sPLT_SUPPORTED &&\\r
65    defined PNG_READ_tEXt_SUPPORTED &&\\r
66    defined PNG_READ_tIME_SUPPORTED &&\\r
67    defined PNG_READ_zTXt_SUPPORTED &&\\r
68    (defined PNG_WRITE_INTERLACING_SUPPORTED || PNG_LIBPNG_VER >= 10700)\r
69 \r
70 #ifdef PNG_ZLIB_HEADER\r
71 #  include PNG_ZLIB_HEADER /* defined by pnglibconf.h from 1.7 */\r
72 #else\r
73 #  include "zlib.h"\r
74 #endif\r
75 \r
76 /* Copied from pngpriv.h but only used in error messages below. */\r
77 #ifndef PNG_ZBUF_SIZE\r
78 #  define PNG_ZBUF_SIZE 8192\r
79 #endif\r
80 #define FCLOSE(file) fclose(file)\r
81 \r
82 #ifndef PNG_STDIO_SUPPORTED\r
83 typedef FILE                * png_FILE_p;\r
84 #endif\r
85 \r
86 /* Makes pngtest verbose so we can find problems. */\r
87 #ifndef PNG_DEBUG\r
88 #  define PNG_DEBUG 0\r
89 #endif\r
90 \r
91 #if PNG_DEBUG > 1\r
92 #  define pngtest_debug(m)        ((void)fprintf(stderr, m "\n"))\r
93 #  define pngtest_debug1(m,p1)    ((void)fprintf(stderr, m "\n", p1))\r
94 #  define pngtest_debug2(m,p1,p2) ((void)fprintf(stderr, m "\n", p1, p2))\r
95 #else\r
96 #  define pngtest_debug(m)        ((void)0)\r
97 #  define pngtest_debug1(m,p1)    ((void)0)\r
98 #  define pngtest_debug2(m,p1,p2) ((void)0)\r
99 #endif\r
100 \r
101 #if !PNG_DEBUG\r
102 #  define SINGLE_ROWBUF_ALLOC  /* Makes buffer overruns easier to nail */\r
103 #endif\r
104 \r
105 #ifndef PNG_UNUSED\r
106 #  define PNG_UNUSED(param) (void)param;\r
107 #endif\r
108 \r
109 /* Turn on CPU timing\r
110 #define PNGTEST_TIMING\r
111 */\r
112 \r
113 #ifndef PNG_FLOATING_POINT_SUPPORTED\r
114 #undef PNGTEST_TIMING\r
115 #endif\r
116 \r
117 #ifdef PNGTEST_TIMING\r
118 static float t_start, t_stop, t_decode, t_encode, t_misc;\r
119 #include <time.h>\r
120 #endif\r
121 \r
122 #ifdef PNG_TIME_RFC1123_SUPPORTED\r
123 #define PNG_tIME_STRING_LENGTH 29\r
124 static int tIME_chunk_present = 0;\r
125 static char tIME_string[PNG_tIME_STRING_LENGTH] = "tIME chunk is not present";\r
126 \r
127 #if PNG_LIBPNG_VER < 10619\r
128 #define png_convert_to_rfc1123_buffer(ts, t) tIME_to_str(read_ptr, ts, t)\r
129 \r
130 static int\r
131 tIME_to_str(png_structp png_ptr, png_charp ts, png_const_timep t)\r
132 {\r
133    png_const_charp str = png_convert_to_rfc1123(png_ptr, t);\r
134 \r
135    if (str == NULL)\r
136        return 0;\r
137 \r
138    strcpy(ts, str);\r
139    return 1;\r
140 }\r
141 #endif /* older libpng */\r
142 #endif\r
143 \r
144 static int verbose = 0;\r
145 static int strict = 0;\r
146 static int relaxed = 0;\r
147 static int xfail = 0;\r
148 static int unsupported_chunks = 0; /* chunk unsupported by libpng in input */\r
149 static int error_count = 0; /* count calls to png_error */\r
150 static int warning_count = 0; /* count calls to png_warning */\r
151 \r
152 /* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */\r
153 #ifndef png_jmpbuf\r
154 #  define png_jmpbuf(png_ptr) png_ptr->jmpbuf\r
155 #endif\r
156 \r
157 /* Defines for unknown chunk handling if required. */\r
158 #ifndef PNG_HANDLE_CHUNK_ALWAYS\r
159 #  define PNG_HANDLE_CHUNK_ALWAYS       3\r
160 #endif\r
161 #ifndef PNG_HANDLE_CHUNK_IF_SAFE\r
162 #  define PNG_HANDLE_CHUNK_IF_SAFE      2\r
163 #endif\r
164 \r
165 /* Utility to save typing/errors, the argument must be a name */\r
166 #define MEMZERO(var) ((void)memset(&var, 0, sizeof var))\r
167 \r
168 /* Example of using row callbacks to make a simple progress meter */\r
169 static int status_pass = 1;\r
170 static int status_dots_requested = 0;\r
171 static int status_dots = 1;\r
172 \r
173 static void PNGCBAPI\r
174 read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass)\r
175 {\r
176    if (png_ptr == NULL || row_number > PNG_UINT_31_MAX)\r
177       return;\r
178 \r
179    if (status_pass != pass)\r
180    {\r
181       fprintf(stdout, "\n Pass %d: ", pass);\r
182       status_pass = pass;\r
183       status_dots = 31;\r
184    }\r
185 \r
186    status_dots--;\r
187 \r
188    if (status_dots == 0)\r
189    {\r
190       fprintf(stdout, "\n         ");\r
191       status_dots=30;\r
192    }\r
193 \r
194    fprintf(stdout, "r");\r
195 }\r
196 \r
197 #ifdef PNG_WRITE_SUPPORTED\r
198 static void PNGCBAPI\r
199 write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass)\r
200 {\r
201    if (png_ptr == NULL || row_number > PNG_UINT_31_MAX || pass > 7)\r
202       return;\r
203 \r
204    fprintf(stdout, "w");\r
205 }\r
206 #endif\r
207 \r
208 \r
209 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED\r
210 /* Example of using a user transform callback (doesn't do anything at present).\r
211  */\r
212 static void PNGCBAPI\r
213 read_user_callback(png_structp png_ptr, png_row_infop row_info, png_bytep data)\r
214 {\r
215    PNG_UNUSED(png_ptr)\r
216    PNG_UNUSED(row_info)\r
217    PNG_UNUSED(data)\r
218 }\r
219 #endif\r
220 \r
221 #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED\r
222 /* Example of using user transform callback (we don't transform anything,\r
223  * but merely count the zero samples)\r
224  */\r
225 \r
226 static png_uint_32 zero_samples;\r
227 \r
228 static void PNGCBAPI\r
229 count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data)\r
230 {\r
231    png_bytep dp = data;\r
232    if (png_ptr == NULL)\r
233       return;\r
234 \r
235    /* Contents of row_info:\r
236     *  png_uint_32 width      width of row\r
237     *  png_uint_32 rowbytes   number of bytes in row\r
238     *  png_byte color_type    color type of pixels\r
239     *  png_byte bit_depth     bit depth of samples\r
240     *  png_byte channels      number of channels (1-4)\r
241     *  png_byte pixel_depth   bits per pixel (depth*channels)\r
242     */\r
243 \r
244    /* Counts the number of zero samples (or zero pixels if color_type is 3 */\r
245 \r
246    if (row_info->color_type == 0 || row_info->color_type == 3)\r
247    {\r
248       int pos = 0;\r
249       png_uint_32 n, nstop;\r
250 \r
251       for (n = 0, nstop=row_info->width; n<nstop; n++)\r
252       {\r
253          if (row_info->bit_depth == 1)\r
254          {\r
255             if (((*dp << pos++ ) & 0x80) == 0)\r
256                zero_samples++;\r
257 \r
258             if (pos == 8)\r
259             {\r
260                pos = 0;\r
261                dp++;\r
262             }\r
263          }\r
264 \r
265          if (row_info->bit_depth == 2)\r
266          {\r
267             if (((*dp << (pos+=2)) & 0xc0) == 0)\r
268                zero_samples++;\r
269 \r
270             if (pos == 8)\r
271             {\r
272                pos = 0;\r
273                dp++;\r
274             }\r
275          }\r
276 \r
277          if (row_info->bit_depth == 4)\r
278          {\r
279             if (((*dp << (pos+=4)) & 0xf0) == 0)\r
280                zero_samples++;\r
281 \r
282             if (pos == 8)\r
283             {\r
284                pos = 0;\r
285                dp++;\r
286             }\r
287          }\r
288 \r
289          if (row_info->bit_depth == 8)\r
290             if (*dp++ == 0)\r
291                zero_samples++;\r
292 \r
293          if (row_info->bit_depth == 16)\r
294          {\r
295             if ((*dp | *(dp+1)) == 0)\r
296                zero_samples++;\r
297             dp+=2;\r
298          }\r
299       }\r
300    }\r
301    else /* Other color types */\r
302    {\r
303       png_uint_32 n, nstop;\r
304       int channel;\r
305       int color_channels = row_info->channels;\r
306       if (row_info->color_type > 3)\r
307          color_channels--;\r
308 \r
309       for (n = 0, nstop=row_info->width; n<nstop; n++)\r
310       {\r
311          for (channel = 0; channel < color_channels; channel++)\r
312          {\r
313             if (row_info->bit_depth == 8)\r
314                if (*dp++ == 0)\r
315                   zero_samples++;\r
316 \r
317             if (row_info->bit_depth == 16)\r
318             {\r
319                if ((*dp | *(dp+1)) == 0)\r
320                   zero_samples++;\r
321 \r
322                dp+=2;\r
323             }\r
324          }\r
325          if (row_info->color_type > 3)\r
326          {\r
327             dp++;\r
328             if (row_info->bit_depth == 16)\r
329                dp++;\r
330          }\r
331       }\r
332    }\r
333 }\r
334 #endif /* WRITE_USER_TRANSFORM */\r
335 \r
336 #ifndef PNG_STDIO_SUPPORTED\r
337 /* START of code to validate stdio-free compilation */\r
338 /* These copies of the default read/write functions come from pngrio.c and\r
339  * pngwio.c.  They allow "don't include stdio" testing of the library.\r
340  * This is the function that does the actual reading of data.  If you are\r
341  * not reading from a standard C stream, you should create a replacement\r
342  * read_data function and use it at run time with png_set_read_fn(), rather\r
343  * than changing the library.\r
344  */\r
345 \r
346 #ifdef PNG_IO_STATE_SUPPORTED\r
347 void\r
348 pngtest_check_io_state(png_structp png_ptr, size_t data_length,\r
349     png_uint_32 io_op);\r
350 void\r
351 pngtest_check_io_state(png_structp png_ptr, size_t data_length,\r
352     png_uint_32 io_op)\r
353 {\r
354    png_uint_32 io_state = png_get_io_state(png_ptr);\r
355    int err = 0;\r
356 \r
357    /* Check if the current operation (reading / writing) is as expected. */\r
358    if ((io_state & PNG_IO_MASK_OP) != io_op)\r
359       png_error(png_ptr, "Incorrect operation in I/O state");\r
360 \r
361    /* Check if the buffer size specific to the current location\r
362     * (file signature / header / data / crc) is as expected.\r
363     */\r
364    switch (io_state & PNG_IO_MASK_LOC)\r
365    {\r
366    case PNG_IO_SIGNATURE:\r
367       if (data_length > 8)\r
368          err = 1;\r
369       break;\r
370    case PNG_IO_CHUNK_HDR:\r
371       if (data_length != 8)\r
372          err = 1;\r
373       break;\r
374    case PNG_IO_CHUNK_DATA:\r
375       break;  /* no restrictions here */\r
376    case PNG_IO_CHUNK_CRC:\r
377       if (data_length != 4)\r
378          err = 1;\r
379       break;\r
380    default:\r
381       err = 1;  /* uninitialized */\r
382    }\r
383    if (err != 0)\r
384       png_error(png_ptr, "Bad I/O state or buffer size");\r
385 }\r
386 #endif\r
387 \r
388 static void PNGCBAPI\r
389 pngtest_read_data(png_structp png_ptr, png_bytep data, size_t length)\r
390 {\r
391    size_t check = 0;\r
392    png_voidp io_ptr;\r
393 \r
394    /* fread() returns 0 on error, so it is OK to store this in a size_t\r
395     * instead of an int, which is what fread() actually returns.\r
396     */\r
397    io_ptr = png_get_io_ptr(png_ptr);\r
398    if (io_ptr != NULL)\r
399    {\r
400       check = fread(data, 1, length, (png_FILE_p)io_ptr);\r
401    }\r
402 \r
403    if (check != length)\r
404    {\r
405       png_error(png_ptr, "Read Error");\r
406    }\r
407 \r
408 #ifdef PNG_IO_STATE_SUPPORTED\r
409    pngtest_check_io_state(png_ptr, length, PNG_IO_READING);\r
410 #endif\r
411 }\r
412 \r
413 #ifdef PNG_WRITE_FLUSH_SUPPORTED\r
414 static void PNGCBAPI\r
415 pngtest_flush(png_structp png_ptr)\r
416 {\r
417    /* Do nothing; fflush() is said to be just a waste of energy. */\r
418    PNG_UNUSED(png_ptr)   /* Stifle compiler warning */\r
419 }\r
420 #endif\r
421 \r
422 /* This is the function that does the actual writing of data.  If you are\r
423  * not writing to a standard C stream, you should create a replacement\r
424  * write_data function and use it at run time with png_set_write_fn(), rather\r
425  * than changing the library.\r
426  */\r
427 static void PNGCBAPI\r
428 pngtest_write_data(png_structp png_ptr, png_bytep data, size_t length)\r
429 {\r
430    size_t check;\r
431 \r
432    check = fwrite(data, 1, length, (png_FILE_p)png_get_io_ptr(png_ptr));\r
433 \r
434    if (check != length)\r
435    {\r
436       png_error(png_ptr, "Write Error");\r
437    }\r
438 \r
439 #ifdef PNG_IO_STATE_SUPPORTED\r
440    pngtest_check_io_state(png_ptr, length, PNG_IO_WRITING);\r
441 #endif\r
442 }\r
443 #endif /* !STDIO */\r
444 \r
445 /* This function is called when there is a warning, but the library thinks\r
446  * it can continue anyway.  Replacement functions don't have to do anything\r
447  * here if you don't want to.  In the default configuration, png_ptr is\r
448  * not used, but it is passed in case it may be useful.\r
449  */\r
450 typedef struct\r
451 {\r
452    const char *file_name;\r
453 }  pngtest_error_parameters;\r
454 \r
455 static void PNGCBAPI\r
456 pngtest_warning(png_structp png_ptr, png_const_charp message)\r
457 {\r
458    const char *name = "UNKNOWN (ERROR!)";\r
459    pngtest_error_parameters *test =\r
460       (pngtest_error_parameters*)png_get_error_ptr(png_ptr);\r
461 \r
462    ++warning_count;\r
463 \r
464    if (test != NULL && test->file_name != NULL)\r
465       name = test->file_name;\r
466 \r
467    fprintf(STDERR, "\n%s: libpng warning: %s\n", name, message);\r
468 }\r
469 \r
470 /* This is the default error handling function.  Note that replacements for\r
471  * this function MUST NOT RETURN, or the program will likely crash.  This\r
472  * function is used by default, or if the program supplies NULL for the\r
473  * error function pointer in png_set_error_fn().\r
474  */\r
475 static void PNGCBAPI\r
476 pngtest_error(png_structp png_ptr, png_const_charp message)\r
477 {\r
478    ++error_count;\r
479 \r
480    pngtest_warning(png_ptr, message);\r
481    /* We can return because png_error calls the default handler, which is\r
482     * actually OK in this case.\r
483     */\r
484 }\r
485 \r
486 /* END of code to validate stdio-free compilation */\r
487 \r
488 /* START of code to validate memory allocation and deallocation */\r
489 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG\r
490 \r
491 /* Allocate memory.  For reasonable files, size should never exceed\r
492  * 64K.  However, zlib may allocate more than 64K if you don't tell\r
493  * it not to.  See zconf.h and png.h for more information.  zlib does\r
494  * need to allocate exactly 64K, so whatever you call here must\r
495  * have the ability to do that.\r
496  *\r
497  * This piece of code can be compiled to validate max 64K allocations\r
498  * by setting MAXSEG_64K in zlib zconf.h *or* PNG_MAX_MALLOC_64K.\r
499  */\r
500 typedef struct memory_information\r
501 {\r
502    png_alloc_size_t          size;\r
503    png_voidp                 pointer;\r
504    struct memory_information *next;\r
505 } memory_information;\r
506 typedef memory_information *memory_infop;\r
507 \r
508 static memory_infop pinformation = NULL;\r
509 static int current_allocation = 0;\r
510 static int maximum_allocation = 0;\r
511 static int total_allocation = 0;\r
512 static int num_allocations = 0;\r
513 \r
514 png_voidp PNGCBAPI png_debug_malloc PNGARG((png_structp png_ptr,\r
515     png_alloc_size_t size));\r
516 void PNGCBAPI png_debug_free PNGARG((png_structp png_ptr, png_voidp ptr));\r
517 \r
518 png_voidp\r
519 PNGCBAPI png_debug_malloc(png_structp png_ptr, png_alloc_size_t size)\r
520 {\r
521 \r
522    /* png_malloc has already tested for NULL; png_create_struct calls\r
523     * png_debug_malloc directly, with png_ptr == NULL which is OK\r
524     */\r
525 \r
526    if (size == 0)\r
527       return (NULL);\r
528 \r
529    /* This calls the library allocator twice, once to get the requested\r
530       buffer and once to get a new free list entry. */\r
531    {\r
532       /* Disable malloc_fn and free_fn */\r
533       memory_infop pinfo;\r
534       png_set_mem_fn(png_ptr, NULL, NULL, NULL);\r
535       pinfo = (memory_infop)png_malloc(png_ptr,\r
536           (sizeof *pinfo));\r
537       pinfo->size = size;\r
538       current_allocation += size;\r
539       total_allocation += size;\r
540       num_allocations ++;\r
541 \r
542       if (current_allocation > maximum_allocation)\r
543          maximum_allocation = current_allocation;\r
544 \r
545       pinfo->pointer = png_malloc(png_ptr, size);\r
546       /* Restore malloc_fn and free_fn */\r
547 \r
548       png_set_mem_fn(png_ptr,\r
549           NULL, png_debug_malloc, png_debug_free);\r
550 \r
551       if (size != 0 && pinfo->pointer == NULL)\r
552       {\r
553          current_allocation -= size;\r
554          total_allocation -= size;\r
555          png_error(png_ptr,\r
556            "out of memory in pngtest->png_debug_malloc");\r
557       }\r
558 \r
559       pinfo->next = pinformation;\r
560       pinformation = pinfo;\r
561       /* Make sure the caller isn't assuming zeroed memory. */\r
562       memset(pinfo->pointer, 0xdd, pinfo->size);\r
563 \r
564       if (verbose != 0)\r
565          printf("png_malloc %lu bytes at %p\n", (unsigned long)size,\r
566              pinfo->pointer);\r
567 \r
568       return (png_voidp)(pinfo->pointer);\r
569    }\r
570 }\r
571 \r
572 /* Free a pointer.  It is removed from the list at the same time. */\r
573 void PNGCBAPI\r
574 png_debug_free(png_structp png_ptr, png_voidp ptr)\r
575 {\r
576    if (png_ptr == NULL)\r
577       fprintf(STDERR, "NULL pointer to png_debug_free.\n");\r
578 \r
579    if (ptr == 0)\r
580    {\r
581 #if 0 /* This happens all the time. */\r
582       fprintf(STDERR, "WARNING: freeing NULL pointer\n");\r
583 #endif\r
584       return;\r
585    }\r
586 \r
587    /* Unlink the element from the list. */\r
588    if (pinformation != NULL)\r
589    {\r
590       memory_infop *ppinfo = &pinformation;\r
591 \r
592       for (;;)\r
593       {\r
594          memory_infop pinfo = *ppinfo;\r
595 \r
596          if (pinfo->pointer == ptr)\r
597          {\r
598             *ppinfo = pinfo->next;\r
599             current_allocation -= pinfo->size;\r
600             if (current_allocation < 0)\r
601                fprintf(STDERR, "Duplicate free of memory\n");\r
602             /* We must free the list element too, but first kill\r
603                the memory that is to be freed. */\r
604             memset(ptr, 0x55, pinfo->size);\r
605             free(pinfo);\r
606             pinfo = NULL;\r
607             break;\r
608          }\r
609 \r
610          if (pinfo->next == NULL)\r
611          {\r
612             fprintf(STDERR, "Pointer %p not found\n", ptr);\r
613             break;\r
614          }\r
615 \r
616          ppinfo = &pinfo->next;\r
617       }\r
618    }\r
619 \r
620    /* Finally free the data. */\r
621    if (verbose != 0)\r
622       printf("Freeing %p\n", ptr);\r
623 \r
624    if (ptr != NULL)\r
625       free(ptr);\r
626    ptr = NULL;\r
627 }\r
628 #endif /* USER_MEM && DEBUG */\r
629 /* END of code to test memory allocation/deallocation */\r
630 \r
631 \r
632 #ifdef PNG_READ_USER_CHUNKS_SUPPORTED\r
633 /* Demonstration of user chunk support of the sTER and vpAg chunks */\r
634 \r
635 /* (sTER is a public chunk not yet known by libpng.  vpAg is a private\r
636 chunk used in ImageMagick to store "virtual page" size).  */\r
637 \r
638 static struct user_chunk_data\r
639 {\r
640    png_const_infop info_ptr;\r
641    png_uint_32     vpAg_width, vpAg_height;\r
642    png_byte        vpAg_units;\r
643    png_byte        sTER_mode;\r
644    int             location[2];\r
645 }\r
646 user_chunk_data;\r
647 \r
648 /* Used for location and order; zero means nothing. */\r
649 #define have_sTER   0x01\r
650 #define have_vpAg   0x02\r
651 #define before_PLTE 0x10\r
652 #define before_IDAT 0x20\r
653 #define after_IDAT  0x40\r
654 \r
655 static void\r
656 init_callback_info(png_const_infop info_ptr)\r
657 {\r
658    MEMZERO(user_chunk_data);\r
659    user_chunk_data.info_ptr = info_ptr;\r
660 }\r
661 \r
662 static int\r
663 set_location(png_structp png_ptr, struct user_chunk_data *data, int what)\r
664 {\r
665    int location;\r
666 \r
667    if ((data->location[0] & what) != 0 || (data->location[1] & what) != 0)\r
668       return 0; /* already have one of these */\r
669 \r
670    /* Find where we are (the code below zeroes info_ptr to indicate that the\r
671     * chunks before the first IDAT have been read.)\r
672     */\r
673    if (data->info_ptr == NULL) /* after IDAT */\r
674       location = what | after_IDAT;\r
675 \r
676    else if (png_get_valid(png_ptr, data->info_ptr, PNG_INFO_PLTE) != 0)\r
677       location = what | before_IDAT;\r
678 \r
679    else\r
680       location = what | before_PLTE;\r
681 \r
682    if (data->location[0] == 0)\r
683       data->location[0] = location;\r
684 \r
685    else\r
686       data->location[1] = location;\r
687 \r
688    return 1; /* handled */\r
689 }\r
690 \r
691 static int PNGCBAPI\r
692 read_user_chunk_callback(png_struct *png_ptr, png_unknown_chunkp chunk)\r
693 {\r
694    struct user_chunk_data *my_user_chunk_data =\r
695       (struct user_chunk_data*)png_get_user_chunk_ptr(png_ptr);\r
696 \r
697    if (my_user_chunk_data == NULL)\r
698       png_error(png_ptr, "lost user chunk pointer");\r
699 \r
700    /* Return one of the following:\r
701     *    return (-n);  chunk had an error\r
702     *    return (0);  did not recognize\r
703     *    return (n);  success\r
704     *\r
705     * The unknown chunk structure contains the chunk data:\r
706     * png_byte name[5];\r
707     * png_byte *data;\r
708     * size_t size;\r
709     *\r
710     * Note that libpng has already taken care of the CRC handling.\r
711     */\r
712 \r
713    if (chunk->name[0] == 115 && chunk->name[1] ==  84 &&     /* s  T */\r
714        chunk->name[2] ==  69 && chunk->name[3] ==  82)       /* E  R */\r
715       {\r
716          /* Found sTER chunk */\r
717          if (chunk->size != 1)\r
718             return (-1); /* Error return */\r
719 \r
720          if (chunk->data[0] != 0 && chunk->data[0] != 1)\r
721             return (-1);  /* Invalid mode */\r
722 \r
723          if (set_location(png_ptr, my_user_chunk_data, have_sTER) != 0)\r
724          {\r
725             my_user_chunk_data->sTER_mode=chunk->data[0];\r
726             return (1);\r
727          }\r
728 \r
729          else\r
730             return (0); /* duplicate sTER - give it to libpng */\r
731       }\r
732 \r
733    if (chunk->name[0] != 118 || chunk->name[1] != 112 ||    /* v  p */\r
734        chunk->name[2] !=  65 || chunk->name[3] != 103)      /* A  g */\r
735       return (0); /* Did not recognize */\r
736 \r
737    /* Found ImageMagick vpAg chunk */\r
738 \r
739    if (chunk->size != 9)\r
740       return (-1); /* Error return */\r
741 \r
742    if (set_location(png_ptr, my_user_chunk_data, have_vpAg) == 0)\r
743       return (0);  /* duplicate vpAg */\r
744 \r
745    my_user_chunk_data->vpAg_width = png_get_uint_31(png_ptr, chunk->data);\r
746    my_user_chunk_data->vpAg_height = png_get_uint_31(png_ptr, chunk->data + 4);\r
747    my_user_chunk_data->vpAg_units = chunk->data[8];\r
748 \r
749    return (1);\r
750 }\r
751 \r
752 #ifdef PNG_WRITE_SUPPORTED\r
753 static void\r
754 write_sTER_chunk(png_structp write_ptr)\r
755 {\r
756    png_byte sTER[5] = {115,  84,  69,  82, '\0'};\r
757 \r
758    if (verbose != 0)\r
759       fprintf(STDERR, "\n stereo mode = %d\n", user_chunk_data.sTER_mode);\r
760 \r
761    png_write_chunk(write_ptr, sTER, &user_chunk_data.sTER_mode, 1);\r
762 }\r
763 \r
764 static void\r
765 write_vpAg_chunk(png_structp write_ptr)\r
766 {\r
767    png_byte vpAg[5] = {118, 112,  65, 103, '\0'};\r
768 \r
769    png_byte vpag_chunk_data[9];\r
770 \r
771    if (verbose != 0)\r
772       fprintf(STDERR, " vpAg = %lu x %lu, units = %d\n",\r
773           (unsigned long)user_chunk_data.vpAg_width,\r
774           (unsigned long)user_chunk_data.vpAg_height,\r
775           user_chunk_data.vpAg_units);\r
776 \r
777    png_save_uint_32(vpag_chunk_data, user_chunk_data.vpAg_width);\r
778    png_save_uint_32(vpag_chunk_data + 4, user_chunk_data.vpAg_height);\r
779    vpag_chunk_data[8] = user_chunk_data.vpAg_units;\r
780    png_write_chunk(write_ptr, vpAg, vpag_chunk_data, 9);\r
781 }\r
782 \r
783 static void\r
784 write_chunks(png_structp write_ptr, int location)\r
785 {\r
786    int i;\r
787 \r
788    /* Notice that this preserves the original chunk order, however chunks\r
789     * intercepted by the callback will be written *after* chunks passed to\r
790     * libpng.  This will actually reverse a pair of sTER chunks or a pair of\r
791     * vpAg chunks, resulting in an error later.  This is not worth worrying\r
792     * about - the chunks should not be duplicated!\r
793     */\r
794    for (i=0; i<2; ++i)\r
795    {\r
796       if (user_chunk_data.location[i] == (location | have_sTER))\r
797          write_sTER_chunk(write_ptr);\r
798 \r
799       else if (user_chunk_data.location[i] == (location | have_vpAg))\r
800          write_vpAg_chunk(write_ptr);\r
801    }\r
802 }\r
803 #endif /* WRITE */\r
804 #else /* !READ_USER_CHUNKS */\r
805 #  define write_chunks(pp,loc) ((void)0)\r
806 #endif\r
807 /* END of code to demonstrate user chunk support */\r
808 \r
809 /* START of code to check that libpng has the required text support; this only\r
810  * checks for the write support because if read support is missing the chunk\r
811  * will simply not be reported back to pngtest.\r
812  */\r
813 #ifdef PNG_TEXT_SUPPORTED\r
814 static void\r
815 pngtest_check_text_support(png_structp png_ptr, png_textp text_ptr,\r
816     int num_text)\r
817 {\r
818    while (num_text > 0)\r
819    {\r
820       switch (text_ptr[--num_text].compression)\r
821       {\r
822          case PNG_TEXT_COMPRESSION_NONE:\r
823             break;\r
824 \r
825          case PNG_TEXT_COMPRESSION_zTXt:\r
826 #           ifndef PNG_WRITE_zTXt_SUPPORTED\r
827                ++unsupported_chunks;\r
828                /* In libpng 1.7 this now does an app-error, so stop it: */\r
829                text_ptr[num_text].compression = PNG_TEXT_COMPRESSION_NONE;\r
830 #           endif\r
831             break;\r
832 \r
833          case PNG_ITXT_COMPRESSION_NONE:\r
834          case PNG_ITXT_COMPRESSION_zTXt:\r
835 #           ifndef PNG_WRITE_iTXt_SUPPORTED\r
836                ++unsupported_chunks;\r
837                text_ptr[num_text].compression = PNG_TEXT_COMPRESSION_NONE;\r
838 #           endif\r
839             break;\r
840 \r
841          default:\r
842             /* This is an error */\r
843             png_error(png_ptr, "invalid text chunk compression field");\r
844             break;\r
845       }\r
846    }\r
847 }\r
848 #endif\r
849 /* END of code to check that libpng has the required text support */\r
850 \r
851 /* Test one file */\r
852 static int\r
853 test_one_file(const char *inname, const char *outname)\r
854 {\r
855    static png_FILE_p fpin;\r
856    static png_FILE_p fpout;  /* "static" prevents setjmp corruption */\r
857    pngtest_error_parameters error_parameters;\r
858    png_structp read_ptr;\r
859    png_infop read_info_ptr, end_info_ptr;\r
860 #ifdef PNG_WRITE_SUPPORTED\r
861    png_structp write_ptr;\r
862    png_infop write_info_ptr;\r
863    png_infop write_end_info_ptr;\r
864 #ifdef PNG_WRITE_FILTER_SUPPORTED\r
865    int interlace_preserved = 1;\r
866 #endif /* WRITE_FILTER */\r
867 #else /* !WRITE */\r
868    png_structp write_ptr = NULL;\r
869    png_infop write_info_ptr = NULL;\r
870    png_infop write_end_info_ptr = NULL;\r
871 #endif /* !WRITE */\r
872    png_bytep row_buf;\r
873    png_uint_32 y;\r
874    png_uint_32 width, height;\r
875    volatile int num_passes;\r
876    int pass;\r
877    int bit_depth, color_type;\r
878 \r
879    row_buf = NULL;\r
880    error_parameters.file_name = inname;\r
881 \r
882    if ((fpin = fopen(inname, "rb")) == NULL)\r
883    {\r
884       fprintf(STDERR, "Could not find input file %s\n", inname);\r
885       return (1);\r
886    }\r
887 \r
888    if ((fpout = fopen(outname, "wb")) == NULL)\r
889    {\r
890       fprintf(STDERR, "Could not open output file %s\n", outname);\r
891       FCLOSE(fpin);\r
892       return (1);\r
893    }\r
894 \r
895    pngtest_debug("Allocating read and write structures");\r
896 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG\r
897    read_ptr =\r
898        png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL,\r
899        NULL, NULL, NULL, png_debug_malloc, png_debug_free);\r
900 #else\r
901    read_ptr =\r
902        png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);\r
903 #endif\r
904    png_set_error_fn(read_ptr, &error_parameters, pngtest_error,\r
905        pngtest_warning);\r
906 \r
907 #ifdef PNG_WRITE_SUPPORTED\r
908 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG\r
909    write_ptr =\r
910        png_create_write_struct_2(PNG_LIBPNG_VER_STRING, NULL,\r
911        NULL, NULL, NULL, png_debug_malloc, png_debug_free);\r
912 #else\r
913    write_ptr =\r
914        png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);\r
915 #endif\r
916    png_set_error_fn(write_ptr, &error_parameters, pngtest_error,\r
917        pngtest_warning);\r
918 #endif\r
919    pngtest_debug("Allocating read_info, write_info and end_info structures");\r
920    read_info_ptr = png_create_info_struct(read_ptr);\r
921    end_info_ptr = png_create_info_struct(read_ptr);\r
922 #ifdef PNG_WRITE_SUPPORTED\r
923    write_info_ptr = png_create_info_struct(write_ptr);\r
924    write_end_info_ptr = png_create_info_struct(write_ptr);\r
925 #endif\r
926 \r
927 #ifdef PNG_READ_USER_CHUNKS_SUPPORTED\r
928    init_callback_info(read_info_ptr);\r
929    png_set_read_user_chunk_fn(read_ptr, &user_chunk_data,\r
930        read_user_chunk_callback);\r
931 #endif\r
932 \r
933 #ifdef PNG_SETJMP_SUPPORTED\r
934    pngtest_debug("Setting jmpbuf for read struct");\r
935    if (setjmp(png_jmpbuf(read_ptr)))\r
936    {\r
937       fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname);\r
938       png_free(read_ptr, row_buf);\r
939       row_buf = NULL;\r
940       if (verbose != 0)\r
941         fprintf(STDERR, "   destroy read structs\n");\r
942       png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);\r
943 #ifdef PNG_WRITE_SUPPORTED\r
944       if (verbose != 0)\r
945         fprintf(STDERR, "   destroy write structs\n");\r
946       png_destroy_info_struct(write_ptr, &write_end_info_ptr);\r
947       png_destroy_write_struct(&write_ptr, &write_info_ptr);\r
948 #endif\r
949       FCLOSE(fpin);\r
950       FCLOSE(fpout);\r
951       return (1);\r
952    }\r
953 \r
954 #ifdef PNG_WRITE_SUPPORTED\r
955    pngtest_debug("Setting jmpbuf for write struct");\r
956 \r
957    if (setjmp(png_jmpbuf(write_ptr)))\r
958    {\r
959       fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname);\r
960       png_free(read_ptr, row_buf);\r
961       row_buf = NULL;\r
962       if (verbose != 0)\r
963         fprintf(STDERR, "   destroying read structs\n");\r
964       png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);\r
965       if (verbose != 0)\r
966         fprintf(STDERR, "   destroying write structs\n");\r
967       png_destroy_info_struct(write_ptr, &write_end_info_ptr);\r
968       png_destroy_write_struct(&write_ptr, &write_info_ptr);\r
969       FCLOSE(fpin);\r
970       FCLOSE(fpout);\r
971       return (1);\r
972    }\r
973 #endif\r
974 #endif\r
975 \r
976 #ifdef PNG_BENIGN_ERRORS_SUPPORTED\r
977    if (strict != 0)\r
978    {\r
979       /* Treat png_benign_error() as errors on read */\r
980       png_set_benign_errors(read_ptr, 0);\r
981 \r
982 # ifdef PNG_WRITE_SUPPORTED\r
983       /* Treat them as errors on write */\r
984       png_set_benign_errors(write_ptr, 0);\r
985 # endif\r
986 \r
987       /* if strict is not set, then app warnings and errors are treated as\r
988        * warnings in release builds, but not in unstable builds; this can be\r
989        * changed with '--relaxed'.\r
990        */\r
991    }\r
992 \r
993    else if (relaxed != 0)\r
994    {\r
995       /* Allow application (pngtest) errors and warnings to pass */\r
996       png_set_benign_errors(read_ptr, 1);\r
997 \r
998       /* Turn off CRC checking while reading */\r
999       png_set_crc_action(read_ptr, PNG_CRC_QUIET_USE, PNG_CRC_QUIET_USE);\r
1000 \r
1001 #ifdef PNG_IGNORE_ADLER32\r
1002       /* Turn off ADLER32 checking while reading */\r
1003       png_set_option(read_ptr, PNG_IGNORE_ADLER32, PNG_OPTION_ON);\r
1004 #endif\r
1005 \r
1006 # ifdef PNG_WRITE_SUPPORTED\r
1007       png_set_benign_errors(write_ptr, 1);\r
1008 # endif\r
1009 \r
1010    }\r
1011 #endif /* BENIGN_ERRORS */\r
1012 \r
1013    pngtest_debug("Initializing input and output streams");\r
1014 #ifdef PNG_STDIO_SUPPORTED\r
1015    png_init_io(read_ptr, fpin);\r
1016 #  ifdef PNG_WRITE_SUPPORTED\r
1017    png_init_io(write_ptr, fpout);\r
1018 #  endif\r
1019 #else\r
1020    png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data);\r
1021 #  ifdef PNG_WRITE_SUPPORTED\r
1022    png_set_write_fn(write_ptr, (png_voidp)fpout,  pngtest_write_data,\r
1023 #    ifdef PNG_WRITE_FLUSH_SUPPORTED\r
1024        pngtest_flush);\r
1025 #    else\r
1026        NULL);\r
1027 #    endif\r
1028 #  endif\r
1029 #endif\r
1030 \r
1031    if (status_dots_requested == 1)\r
1032    {\r
1033 #ifdef PNG_WRITE_SUPPORTED\r
1034       png_set_write_status_fn(write_ptr, write_row_callback);\r
1035 #endif\r
1036       png_set_read_status_fn(read_ptr, read_row_callback);\r
1037    }\r
1038 \r
1039    else\r
1040    {\r
1041 #ifdef PNG_WRITE_SUPPORTED\r
1042       png_set_write_status_fn(write_ptr, NULL);\r
1043 #endif\r
1044       png_set_read_status_fn(read_ptr, NULL);\r
1045    }\r
1046 \r
1047 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED\r
1048    png_set_read_user_transform_fn(read_ptr, read_user_callback);\r
1049 #endif\r
1050 #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED\r
1051    zero_samples = 0;\r
1052    png_set_write_user_transform_fn(write_ptr, count_zero_samples);\r
1053 #endif\r
1054 \r
1055 #ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED\r
1056    /* Preserve all the unknown chunks, if possible.  If this is disabled then,\r
1057     * even if the png_{get,set}_unknown_chunks stuff is enabled, we can't use\r
1058     * libpng to *save* the unknown chunks on read (because we can't switch the\r
1059     * save option on!)\r
1060     *\r
1061     * Notice that if SET_UNKNOWN_CHUNKS is *not* supported read will discard all\r
1062     * unknown chunks and write will write them all.\r
1063     */\r
1064 #ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED\r
1065    png_set_keep_unknown_chunks(read_ptr, PNG_HANDLE_CHUNK_ALWAYS,\r
1066        NULL, 0);\r
1067 #endif\r
1068 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED\r
1069    png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_ALWAYS,\r
1070        NULL, 0);\r
1071 #endif\r
1072 #endif\r
1073 \r
1074    pngtest_debug("Reading info struct");\r
1075    png_read_info(read_ptr, read_info_ptr);\r
1076 \r
1077 #ifdef PNG_READ_USER_CHUNKS_SUPPORTED\r
1078    /* This is a bit of a hack; there is no obvious way in the callback function\r
1079     * to determine that the chunks before the first IDAT have been read, so\r
1080     * remove the info_ptr (which is only used to determine position relative to\r
1081     * PLTE) here to indicate that we are after the IDAT.\r
1082     */\r
1083    user_chunk_data.info_ptr = NULL;\r
1084 #endif\r
1085 \r
1086    pngtest_debug("Transferring info struct");\r
1087    {\r
1088       int interlace_type, compression_type, filter_type;\r
1089 \r
1090       if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth,\r
1091           &color_type, &interlace_type, &compression_type, &filter_type) != 0)\r
1092       {\r
1093          png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth,\r
1094              color_type, interlace_type, compression_type, filter_type);\r
1095          /* num_passes may not be available below if interlace support is not\r
1096           * provided by libpng for both read and write.\r
1097           */\r
1098          switch (interlace_type)\r
1099          {\r
1100             case PNG_INTERLACE_NONE:\r
1101                num_passes = 1;\r
1102                break;\r
1103 \r
1104             case PNG_INTERLACE_ADAM7:\r
1105                num_passes = 7;\r
1106                break;\r
1107 \r
1108             default:\r
1109                png_error(read_ptr, "invalid interlace type");\r
1110                /*NOT REACHED*/\r
1111          }\r
1112       }\r
1113 \r
1114       else\r
1115          png_error(read_ptr, "png_get_IHDR failed");\r
1116    }\r
1117 #ifdef PNG_FIXED_POINT_SUPPORTED\r
1118 #ifdef PNG_cHRM_SUPPORTED\r
1119    {\r
1120       png_fixed_point white_x, white_y, red_x, red_y, green_x, green_y, blue_x,\r
1121           blue_y;\r
1122 \r
1123       if (png_get_cHRM_fixed(read_ptr, read_info_ptr, &white_x, &white_y,\r
1124           &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y) != 0)\r
1125       {\r
1126          png_set_cHRM_fixed(write_ptr, write_info_ptr, white_x, white_y, red_x,\r
1127              red_y, green_x, green_y, blue_x, blue_y);\r
1128       }\r
1129    }\r
1130 #endif\r
1131 #ifdef PNG_gAMA_SUPPORTED\r
1132    {\r
1133       png_fixed_point gamma;\r
1134 \r
1135       if (png_get_gAMA_fixed(read_ptr, read_info_ptr, &gamma) != 0)\r
1136          png_set_gAMA_fixed(write_ptr, write_info_ptr, gamma);\r
1137    }\r
1138 #endif\r
1139 #else /* Use floating point versions */\r
1140 #ifdef PNG_FLOATING_POINT_SUPPORTED\r
1141 #ifdef PNG_cHRM_SUPPORTED\r
1142    {\r
1143       double white_x, white_y, red_x, red_y, green_x, green_y, blue_x,\r
1144           blue_y;\r
1145 \r
1146       if (png_get_cHRM(read_ptr, read_info_ptr, &white_x, &white_y, &red_x,\r
1147           &red_y, &green_x, &green_y, &blue_x, &blue_y) != 0)\r
1148       {\r
1149          png_set_cHRM(write_ptr, write_info_ptr, white_x, white_y, red_x,\r
1150              red_y, green_x, green_y, blue_x, blue_y);\r
1151       }\r
1152    }\r
1153 #endif\r
1154 #ifdef PNG_gAMA_SUPPORTED\r
1155    {\r
1156       double gamma;\r
1157 \r
1158       if (png_get_gAMA(read_ptr, read_info_ptr, &gamma) != 0)\r
1159          png_set_gAMA(write_ptr, write_info_ptr, gamma);\r
1160    }\r
1161 #endif\r
1162 #endif /* Floating point */\r
1163 #endif /* Fixed point */\r
1164 #ifdef PNG_iCCP_SUPPORTED\r
1165    {\r
1166       png_charp name;\r
1167       png_bytep profile;\r
1168       png_uint_32 proflen;\r
1169       int compression_type;\r
1170 \r
1171       if (png_get_iCCP(read_ptr, read_info_ptr, &name, &compression_type,\r
1172           &profile, &proflen) != 0)\r
1173       {\r
1174          png_set_iCCP(write_ptr, write_info_ptr, name, compression_type,\r
1175              profile, proflen);\r
1176       }\r
1177    }\r
1178 #endif\r
1179 #ifdef PNG_sRGB_SUPPORTED\r
1180    {\r
1181       int intent;\r
1182 \r
1183       if (png_get_sRGB(read_ptr, read_info_ptr, &intent) != 0)\r
1184          png_set_sRGB(write_ptr, write_info_ptr, intent);\r
1185    }\r
1186 #endif\r
1187    {\r
1188       png_colorp palette;\r
1189       int num_palette;\r
1190 \r
1191       if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette) != 0)\r
1192          png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette);\r
1193    }\r
1194 #ifdef PNG_bKGD_SUPPORTED\r
1195    {\r
1196       png_color_16p background;\r
1197 \r
1198       if (png_get_bKGD(read_ptr, read_info_ptr, &background) != 0)\r
1199       {\r
1200          png_set_bKGD(write_ptr, write_info_ptr, background);\r
1201       }\r
1202    }\r
1203 #endif\r
1204 #ifdef PNG_READ_eXIf_SUPPORTED\r
1205    {\r
1206       png_bytep exif=NULL;\r
1207       png_uint_32 exif_length;\r
1208 \r
1209       if (png_get_eXIf_1(read_ptr, read_info_ptr, &exif_length, &exif) != 0)\r
1210       {\r
1211          if (exif_length > 1)\r
1212             fprintf(STDERR," eXIf type %c%c, %lu bytes\n",exif[0],exif[1],\r
1213                (unsigned long)exif_length);\r
1214 # ifdef PNG_WRITE_eXIf_SUPPORTED\r
1215          png_set_eXIf_1(write_ptr, write_info_ptr, exif_length, exif);\r
1216 # endif\r
1217       }\r
1218    }\r
1219 #endif\r
1220 #ifdef PNG_hIST_SUPPORTED\r
1221    {\r
1222       png_uint_16p hist;\r
1223 \r
1224       if (png_get_hIST(read_ptr, read_info_ptr, &hist) != 0)\r
1225          png_set_hIST(write_ptr, write_info_ptr, hist);\r
1226    }\r
1227 #endif\r
1228 #ifdef PNG_oFFs_SUPPORTED\r
1229    {\r
1230       png_int_32 offset_x, offset_y;\r
1231       int unit_type;\r
1232 \r
1233       if (png_get_oFFs(read_ptr, read_info_ptr, &offset_x, &offset_y,\r
1234           &unit_type) != 0)\r
1235       {\r
1236          png_set_oFFs(write_ptr, write_info_ptr, offset_x, offset_y, unit_type);\r
1237       }\r
1238    }\r
1239 #endif\r
1240 #ifdef PNG_pCAL_SUPPORTED\r
1241    {\r
1242       png_charp purpose, units;\r
1243       png_charpp params;\r
1244       png_int_32 X0, X1;\r
1245       int type, nparams;\r
1246 \r
1247       if (png_get_pCAL(read_ptr, read_info_ptr, &purpose, &X0, &X1, &type,\r
1248           &nparams, &units, &params) != 0)\r
1249       {\r
1250          png_set_pCAL(write_ptr, write_info_ptr, purpose, X0, X1, type,\r
1251              nparams, units, params);\r
1252       }\r
1253    }\r
1254 #endif\r
1255 #ifdef PNG_pHYs_SUPPORTED\r
1256    {\r
1257       png_uint_32 res_x, res_y;\r
1258       int unit_type;\r
1259 \r
1260       if (png_get_pHYs(read_ptr, read_info_ptr, &res_x, &res_y,\r
1261           &unit_type) != 0)\r
1262          png_set_pHYs(write_ptr, write_info_ptr, res_x, res_y, unit_type);\r
1263    }\r
1264 #endif\r
1265 #ifdef PNG_sBIT_SUPPORTED\r
1266    {\r
1267       png_color_8p sig_bit;\r
1268 \r
1269       if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit) != 0)\r
1270          png_set_sBIT(write_ptr, write_info_ptr, sig_bit);\r
1271    }\r
1272 #endif\r
1273 #ifdef PNG_sCAL_SUPPORTED\r
1274 #if defined(PNG_FLOATING_POINT_SUPPORTED) && \\r
1275    defined(PNG_FLOATING_ARITHMETIC_SUPPORTED)\r
1276    {\r
1277       int unit;\r
1278       double scal_width, scal_height;\r
1279 \r
1280       if (png_get_sCAL(read_ptr, read_info_ptr, &unit, &scal_width,\r
1281           &scal_height) != 0)\r
1282       {\r
1283          png_set_sCAL(write_ptr, write_info_ptr, unit, scal_width, scal_height);\r
1284       }\r
1285    }\r
1286 #else\r
1287 #ifdef PNG_FIXED_POINT_SUPPORTED\r
1288    {\r
1289       int unit;\r
1290       png_charp scal_width, scal_height;\r
1291 \r
1292       if (png_get_sCAL_s(read_ptr, read_info_ptr, &unit, &scal_width,\r
1293            &scal_height) != 0)\r
1294       {\r
1295          png_set_sCAL_s(write_ptr, write_info_ptr, unit, scal_width,\r
1296              scal_height);\r
1297       }\r
1298    }\r
1299 #endif\r
1300 #endif\r
1301 #endif\r
1302 \r
1303 #ifdef PNG_sPLT_SUPPORTED\r
1304    {\r
1305        png_sPLT_tp entries;\r
1306 \r
1307        int num_entries = (int) png_get_sPLT(read_ptr, read_info_ptr, &entries);\r
1308        if (num_entries)\r
1309        {\r
1310            png_set_sPLT(write_ptr, write_info_ptr, entries, num_entries);\r
1311        }\r
1312    }\r
1313 #endif\r
1314 \r
1315 #ifdef PNG_TEXT_SUPPORTED\r
1316    {\r
1317       png_textp text_ptr;\r
1318       int num_text;\r
1319 \r
1320       if (png_get_text(read_ptr, read_info_ptr, &text_ptr, &num_text) > 0)\r
1321       {\r
1322          pngtest_debug1("Handling %d iTXt/tEXt/zTXt chunks", num_text);\r
1323 \r
1324          pngtest_check_text_support(read_ptr, text_ptr, num_text);\r
1325 \r
1326          if (verbose != 0)\r
1327          {\r
1328             int i;\r
1329 \r
1330             fprintf(STDERR,"\n");\r
1331             for (i=0; i<num_text; i++)\r
1332             {\r
1333                fprintf(STDERR,"   Text compression[%d]=%d\n",\r
1334                    i, text_ptr[i].compression);\r
1335             }\r
1336          }\r
1337 \r
1338          png_set_text(write_ptr, write_info_ptr, text_ptr, num_text);\r
1339       }\r
1340    }\r
1341 #endif\r
1342 #ifdef PNG_tIME_SUPPORTED\r
1343    {\r
1344       png_timep mod_time;\r
1345 \r
1346       if (png_get_tIME(read_ptr, read_info_ptr, &mod_time) != 0)\r
1347       {\r
1348          png_set_tIME(write_ptr, write_info_ptr, mod_time);\r
1349 #ifdef PNG_TIME_RFC1123_SUPPORTED\r
1350          if (png_convert_to_rfc1123_buffer(tIME_string, mod_time) != 0)\r
1351             tIME_string[(sizeof tIME_string) - 1] = '\0';\r
1352 \r
1353          else\r
1354          {\r
1355             strncpy(tIME_string, "*** invalid time ***", (sizeof tIME_string));\r
1356             tIME_string[(sizeof tIME_string) - 1] = '\0';\r
1357          }\r
1358 \r
1359          tIME_chunk_present++;\r
1360 #endif /* TIME_RFC1123 */\r
1361       }\r
1362    }\r
1363 #endif\r
1364 #ifdef PNG_tRNS_SUPPORTED\r
1365    {\r
1366       png_bytep trans_alpha;\r
1367       int num_trans;\r
1368       png_color_16p trans_color;\r
1369 \r
1370       if (png_get_tRNS(read_ptr, read_info_ptr, &trans_alpha, &num_trans,\r
1371           &trans_color) != 0)\r
1372       {\r
1373          int sample_max = (1 << bit_depth);\r
1374          /* libpng doesn't reject a tRNS chunk with out-of-range samples */\r
1375          if (!((color_type == PNG_COLOR_TYPE_GRAY &&\r
1376              (int)trans_color->gray > sample_max) ||\r
1377              (color_type == PNG_COLOR_TYPE_RGB &&\r
1378              ((int)trans_color->red > sample_max ||\r
1379              (int)trans_color->green > sample_max ||\r
1380              (int)trans_color->blue > sample_max))))\r
1381             png_set_tRNS(write_ptr, write_info_ptr, trans_alpha, num_trans,\r
1382                trans_color);\r
1383       }\r
1384    }\r
1385 #endif\r
1386 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED\r
1387    {\r
1388       png_unknown_chunkp unknowns;\r
1389       int num_unknowns = png_get_unknown_chunks(read_ptr, read_info_ptr,\r
1390           &unknowns);\r
1391 \r
1392       if (num_unknowns != 0)\r
1393       {\r
1394          png_set_unknown_chunks(write_ptr, write_info_ptr, unknowns,\r
1395              num_unknowns);\r
1396 #if PNG_LIBPNG_VER < 10600\r
1397          /* Copy the locations from the read_info_ptr.  The automatically\r
1398           * generated locations in write_end_info_ptr are wrong prior to 1.6.0\r
1399           * because they are reset from the write pointer (removed in 1.6.0).\r
1400           */\r
1401          {\r
1402             int i;\r
1403             for (i = 0; i < num_unknowns; i++)\r
1404               png_set_unknown_chunk_location(write_ptr, write_info_ptr, i,\r
1405                   unknowns[i].location);\r
1406          }\r
1407 #endif\r
1408       }\r
1409    }\r
1410 #endif\r
1411 \r
1412 #ifdef PNG_WRITE_SUPPORTED\r
1413    pngtest_debug("Writing info struct");\r
1414 \r
1415    /* Write the info in two steps so that if we write the 'unknown' chunks here\r
1416     * they go to the correct place.\r
1417     */\r
1418    png_write_info_before_PLTE(write_ptr, write_info_ptr);\r
1419 \r
1420    write_chunks(write_ptr, before_PLTE); /* before PLTE */\r
1421 \r
1422    png_write_info(write_ptr, write_info_ptr);\r
1423 \r
1424    write_chunks(write_ptr, before_IDAT); /* after PLTE */\r
1425 \r
1426    png_write_info(write_ptr, write_end_info_ptr);\r
1427 \r
1428    write_chunks(write_ptr, after_IDAT); /* after IDAT */\r
1429 \r
1430 #ifdef PNG_COMPRESSION_COMPAT\r
1431    /* Test the 'compatibility' setting here, if it is available. */\r
1432    png_set_compression(write_ptr, PNG_COMPRESSION_COMPAT);\r
1433 #endif\r
1434 #endif\r
1435 \r
1436 #ifdef SINGLE_ROWBUF_ALLOC\r
1437    pngtest_debug("Allocating row buffer...");\r
1438    row_buf = (png_bytep)png_malloc(read_ptr,\r
1439        png_get_rowbytes(read_ptr, read_info_ptr));\r
1440 \r
1441    pngtest_debug1("\t%p", row_buf);\r
1442 #endif /* SINGLE_ROWBUF_ALLOC */\r
1443    pngtest_debug("Writing row data");\r
1444 \r
1445 #if defined(PNG_READ_INTERLACING_SUPPORTED) &&\\r
1446    defined(PNG_WRITE_INTERLACING_SUPPORTED)\r
1447    /* Both must be defined for libpng to be able to handle the interlace,\r
1448     * otherwise it gets handled below by simply reading and writing the passes\r
1449     * directly.\r
1450     */\r
1451    if (png_set_interlace_handling(read_ptr) != num_passes)\r
1452       png_error(write_ptr,\r
1453           "png_set_interlace_handling(read): wrong pass count ");\r
1454    if (png_set_interlace_handling(write_ptr) != num_passes)\r
1455       png_error(write_ptr,\r
1456           "png_set_interlace_handling(write): wrong pass count ");\r
1457 #else /* png_set_interlace_handling not called on either read or write */\r
1458 #  define calc_pass_height\r
1459 #endif /* not using libpng interlace handling */\r
1460 \r
1461 #ifdef PNGTEST_TIMING\r
1462    t_stop = (float)clock();\r
1463    t_misc += (t_stop - t_start);\r
1464    t_start = t_stop;\r
1465 #endif\r
1466    for (pass = 0; pass < num_passes; pass++)\r
1467    {\r
1468 #     ifdef calc_pass_height\r
1469          png_uint_32 pass_height;\r
1470 \r
1471          if (num_passes == 7) /* interlaced */\r
1472          {\r
1473             if (PNG_PASS_COLS(width, pass) > 0)\r
1474                pass_height = PNG_PASS_ROWS(height, pass);\r
1475 \r
1476             else\r
1477                pass_height = 0;\r
1478          }\r
1479 \r
1480          else /* not interlaced */\r
1481             pass_height = height;\r
1482 #     else\r
1483 #        define pass_height height\r
1484 #     endif\r
1485 \r
1486       pngtest_debug1("Writing row data for pass %d", pass);\r
1487       for (y = 0; y < pass_height; y++)\r
1488       {\r
1489 #ifndef SINGLE_ROWBUF_ALLOC\r
1490          pngtest_debug2("Allocating row buffer (pass %d, y = %u)...", pass, y);\r
1491 \r
1492          row_buf = (png_bytep)png_malloc(read_ptr,\r
1493              png_get_rowbytes(read_ptr, read_info_ptr));\r
1494 \r
1495          pngtest_debug2("\t%p (%lu bytes)", row_buf,\r
1496              (unsigned long)png_get_rowbytes(read_ptr, read_info_ptr));\r
1497 \r
1498 #endif /* !SINGLE_ROWBUF_ALLOC */\r
1499          png_read_rows(read_ptr, (png_bytepp)&row_buf, NULL, 1);\r
1500 \r
1501 #ifdef PNG_WRITE_SUPPORTED\r
1502 #ifdef PNGTEST_TIMING\r
1503          t_stop = (float)clock();\r
1504          t_decode += (t_stop - t_start);\r
1505          t_start = t_stop;\r
1506 #endif\r
1507          png_write_rows(write_ptr, (png_bytepp)&row_buf, 1);\r
1508 #ifdef PNGTEST_TIMING\r
1509          t_stop = (float)clock();\r
1510          t_encode += (t_stop - t_start);\r
1511          t_start = t_stop;\r
1512 #endif\r
1513 #endif /* WRITE */\r
1514 \r
1515 #ifndef SINGLE_ROWBUF_ALLOC\r
1516          pngtest_debug2("Freeing row buffer (pass %d, y = %u)", pass, y);\r
1517          png_free(read_ptr, row_buf);\r
1518          row_buf = NULL;\r
1519 #endif /* !SINGLE_ROWBUF_ALLOC */\r
1520       }\r
1521    }\r
1522 \r
1523 #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED\r
1524 #  ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED\r
1525       png_free_data(read_ptr, read_info_ptr, PNG_FREE_UNKN, -1);\r
1526 #  endif\r
1527 #  ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED\r
1528       png_free_data(write_ptr, write_info_ptr, PNG_FREE_UNKN, -1);\r
1529 #  endif\r
1530 #endif\r
1531 \r
1532    pngtest_debug("Reading and writing end_info data");\r
1533 \r
1534    png_read_end(read_ptr, end_info_ptr);\r
1535 #ifdef PNG_TEXT_SUPPORTED\r
1536    {\r
1537       png_textp text_ptr;\r
1538       int num_text;\r
1539 \r
1540       if (png_get_text(read_ptr, end_info_ptr, &text_ptr, &num_text) > 0)\r
1541       {\r
1542          pngtest_debug1("Handling %d iTXt/tEXt/zTXt chunks", num_text);\r
1543 \r
1544          pngtest_check_text_support(read_ptr, text_ptr, num_text);\r
1545 \r
1546          if (verbose != 0)\r
1547          {\r
1548             int i;\r
1549 \r
1550             fprintf(STDERR,"\n");\r
1551             for (i=0; i<num_text; i++)\r
1552             {\r
1553                fprintf(STDERR,"   Text compression[%d]=%d\n",\r
1554                    i, text_ptr[i].compression);\r
1555             }\r
1556          }\r
1557 \r
1558          png_set_text(write_ptr, write_end_info_ptr, text_ptr, num_text);\r
1559       }\r
1560    }\r
1561 #endif\r
1562 #ifdef PNG_READ_eXIf_SUPPORTED\r
1563    {\r
1564       png_bytep exif=NULL;\r
1565       png_uint_32 exif_length;\r
1566 \r
1567       if (png_get_eXIf_1(read_ptr, end_info_ptr, &exif_length, &exif) != 0)\r
1568       {\r
1569          if (exif_length > 1)\r
1570             fprintf(STDERR," eXIf type %c%c, %lu bytes\n",exif[0],exif[1],\r
1571                (unsigned long)exif_length);\r
1572 # ifdef PNG_WRITE_eXIf_SUPPORTED\r
1573          png_set_eXIf_1(write_ptr, write_end_info_ptr, exif_length, exif);\r
1574 # endif\r
1575       }\r
1576    }\r
1577 #endif\r
1578 #ifdef PNG_tIME_SUPPORTED\r
1579    {\r
1580       png_timep mod_time;\r
1581 \r
1582       if (png_get_tIME(read_ptr, end_info_ptr, &mod_time) != 0)\r
1583       {\r
1584          png_set_tIME(write_ptr, write_end_info_ptr, mod_time);\r
1585 #ifdef PNG_TIME_RFC1123_SUPPORTED\r
1586          if (png_convert_to_rfc1123_buffer(tIME_string, mod_time) != 0)\r
1587             tIME_string[(sizeof tIME_string) - 1] = '\0';\r
1588 \r
1589          else\r
1590          {\r
1591             strncpy(tIME_string, "*** invalid time ***", sizeof tIME_string);\r
1592             tIME_string[(sizeof tIME_string)-1] = '\0';\r
1593          }\r
1594 \r
1595          tIME_chunk_present++;\r
1596 #endif /* TIME_RFC1123 */\r
1597       }\r
1598    }\r
1599 #endif\r
1600 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED\r
1601    {\r
1602       png_unknown_chunkp unknowns;\r
1603       int num_unknowns = png_get_unknown_chunks(read_ptr, end_info_ptr,\r
1604           &unknowns);\r
1605 \r
1606       if (num_unknowns != 0)\r
1607       {\r
1608          png_set_unknown_chunks(write_ptr, write_end_info_ptr, unknowns,\r
1609              num_unknowns);\r
1610 #if PNG_LIBPNG_VER < 10600\r
1611          /* Copy the locations from the read_info_ptr.  The automatically\r
1612           * generated locations in write_end_info_ptr are wrong prior to 1.6.0\r
1613           * because they are reset from the write pointer (removed in 1.6.0).\r
1614           */\r
1615          {\r
1616             int i;\r
1617             for (i = 0; i < num_unknowns; i++)\r
1618               png_set_unknown_chunk_location(write_ptr, write_end_info_ptr, i,\r
1619                   unknowns[i].location);\r
1620          }\r
1621 #endif\r
1622       }\r
1623    }\r
1624 #endif\r
1625 \r
1626 #ifdef PNG_WRITE_SUPPORTED\r
1627 #ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED\r
1628    /* Normally one would use Z_DEFAULT_STRATEGY for text compression.\r
1629     * This is here just to make pngtest replicate the results from libpng\r
1630     * versions prior to 1.5.4, and to test this new API.\r
1631     */\r
1632    png_set_text_compression_strategy(write_ptr, Z_FILTERED);\r
1633 #endif\r
1634 \r
1635    /* When the unknown vpAg/sTER chunks are written by pngtest the only way to\r
1636     * do it is to write them *before* calling png_write_end.  When unknown\r
1637     * chunks are written by libpng, however, they are written just before IEND.\r
1638     * There seems to be no way round this, however vpAg/sTER are not expected\r
1639     * after IDAT.\r
1640     */\r
1641    write_chunks(write_ptr, after_IDAT);\r
1642 \r
1643    png_write_end(write_ptr, write_end_info_ptr);\r
1644 #endif\r
1645 \r
1646 #ifdef PNG_EASY_ACCESS_SUPPORTED\r
1647    if (verbose != 0)\r
1648    {\r
1649       png_uint_32 iwidth, iheight;\r
1650       iwidth = png_get_image_width(write_ptr, write_info_ptr);\r
1651       iheight = png_get_image_height(write_ptr, write_info_ptr);\r
1652       fprintf(STDERR, "\n Image width = %lu, height = %lu\n",\r
1653           (unsigned long)iwidth, (unsigned long)iheight);\r
1654    }\r
1655 #endif\r
1656 \r
1657    pngtest_debug("Destroying data structs");\r
1658 #ifdef SINGLE_ROWBUF_ALLOC\r
1659    pngtest_debug("destroying row_buf for read_ptr");\r
1660    png_free(read_ptr, row_buf);\r
1661    row_buf = NULL;\r
1662 #endif /* SINGLE_ROWBUF_ALLOC */\r
1663    pngtest_debug("destroying read_ptr, read_info_ptr, end_info_ptr");\r
1664    png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);\r
1665 #ifdef PNG_WRITE_SUPPORTED\r
1666    pngtest_debug("destroying write_end_info_ptr");\r
1667    png_destroy_info_struct(write_ptr, &write_end_info_ptr);\r
1668    pngtest_debug("destroying write_ptr, write_info_ptr");\r
1669    png_destroy_write_struct(&write_ptr, &write_info_ptr);\r
1670 #endif\r
1671    pngtest_debug("Destruction complete.");\r
1672 \r
1673    FCLOSE(fpin);\r
1674    FCLOSE(fpout);\r
1675 \r
1676    /* Summarize any warnings or errors and in 'strict' mode fail the test.\r
1677     * Unsupported chunks can result in warnings, in that case ignore the strict\r
1678     * setting, otherwise fail the test on warnings as well as errors.\r
1679     */\r
1680    if (error_count > 0)\r
1681    {\r
1682       /* We don't really expect to get here because of the setjmp handling\r
1683        * above, but this is safe.\r
1684        */\r
1685       fprintf(STDERR, "\n  %s: %d libpng errors found (%d warnings)",\r
1686           inname, error_count, warning_count);\r
1687 \r
1688       if (strict != 0)\r
1689          return (1);\r
1690    }\r
1691 \r
1692 #  ifdef PNG_WRITE_SUPPORTED\r
1693       /* If there is no write support nothing was written! */\r
1694       else if (unsupported_chunks > 0)\r
1695       {\r
1696          fprintf(STDERR, "\n  %s: unsupported chunks (%d)%s",\r
1697              inname, unsupported_chunks, strict ? ": IGNORED --strict!" : "");\r
1698       }\r
1699 #  endif\r
1700 \r
1701    else if (warning_count > 0)\r
1702    {\r
1703       fprintf(STDERR, "\n  %s: %d libpng warnings found",\r
1704           inname, warning_count);\r
1705 \r
1706       if (strict != 0)\r
1707          return (1);\r
1708    }\r
1709 \r
1710    pngtest_debug("Opening files for comparison");\r
1711    if ((fpin = fopen(inname, "rb")) == NULL)\r
1712    {\r
1713       fprintf(STDERR, "Could not find file %s\n", inname);\r
1714       return (1);\r
1715    }\r
1716 \r
1717    if ((fpout = fopen(outname, "rb")) == NULL)\r
1718    {\r
1719       fprintf(STDERR, "Could not find file %s\n", outname);\r
1720       FCLOSE(fpin);\r
1721       return (1);\r
1722    }\r
1723 \r
1724 #if defined (PNG_WRITE_SUPPORTED) /* else nothing was written */ &&\\r
1725     defined (PNG_WRITE_FILTER_SUPPORTED)\r
1726    if (interlace_preserved != 0) /* else the files will be changed */\r
1727    {\r
1728       for (;;)\r
1729       {\r
1730          static int wrote_question = 0;\r
1731          size_t num_in, num_out;\r
1732          char inbuf[256], outbuf[256];\r
1733 \r
1734          num_in = fread(inbuf, 1, sizeof inbuf, fpin);\r
1735          num_out = fread(outbuf, 1, sizeof outbuf, fpout);\r
1736 \r
1737          if (num_in != num_out)\r
1738          {\r
1739             fprintf(STDERR, "\nFiles %s and %s are of a different size\n",\r
1740                 inname, outname);\r
1741 \r
1742             if (wrote_question == 0 && unsupported_chunks == 0)\r
1743             {\r
1744                fprintf(STDERR,\r
1745                    "   Was %s written with the same maximum IDAT"\r
1746                    " chunk size (%d bytes),",\r
1747                    inname, PNG_ZBUF_SIZE);\r
1748                fprintf(STDERR,\r
1749                    "\n   filtering heuristic (libpng default), compression");\r
1750                fprintf(STDERR,\r
1751                    " level (zlib default),\n   and zlib version (%s)?\n\n",\r
1752                    ZLIB_VERSION);\r
1753                wrote_question = 1;\r
1754             }\r
1755 \r
1756             FCLOSE(fpin);\r
1757             FCLOSE(fpout);\r
1758 \r
1759             if (strict != 0 && unsupported_chunks == 0)\r
1760               return (1);\r
1761 \r
1762             else\r
1763               return (0);\r
1764          }\r
1765 \r
1766          if (num_in == 0)\r
1767             break;\r
1768 \r
1769          if (memcmp(inbuf, outbuf, num_in))\r
1770          {\r
1771             fprintf(STDERR, "\nFiles %s and %s are different\n", inname,\r
1772                 outname);\r
1773 \r
1774             if (wrote_question == 0 && unsupported_chunks == 0)\r
1775             {\r
1776                fprintf(STDERR,\r
1777                    "   Was %s written with the same maximum"\r
1778                    " IDAT chunk size (%d bytes),",\r
1779                     inname, PNG_ZBUF_SIZE);\r
1780                fprintf(STDERR,\r
1781                    "\n   filtering heuristic (libpng default), compression");\r
1782                fprintf(STDERR,\r
1783                    " level (zlib default),\n   and zlib version (%s)?\n\n",\r
1784                  ZLIB_VERSION);\r
1785                wrote_question = 1;\r
1786             }\r
1787 \r
1788             FCLOSE(fpin);\r
1789             FCLOSE(fpout);\r
1790 \r
1791             /* NOTE: the unsupported_chunks escape is permitted here because\r
1792              * unsupported text chunk compression will result in the compression\r
1793              * mode being changed (to NONE) yet, in the test case, the result\r
1794              * can be exactly the same size!\r
1795              */\r
1796             if (strict != 0 && unsupported_chunks == 0)\r
1797               return (1);\r
1798 \r
1799             else\r
1800               return (0);\r
1801          }\r
1802       }\r
1803    }\r
1804 #endif /* WRITE && WRITE_FILTER */\r
1805 \r
1806    FCLOSE(fpin);\r
1807    FCLOSE(fpout);\r
1808 \r
1809    return (0);\r
1810 }\r
1811 \r
1812 /* Input and output filenames */\r
1813 #ifdef RISCOS\r
1814 static const char *inname = "pngtest/png";\r
1815 static const char *outname = "pngout/png";\r
1816 #else\r
1817 static const char *inname = "pngtest.png";\r
1818 static const char *outname = "pngout.png";\r
1819 #endif\r
1820 \r
1821 int\r
1822 main(int argc, char *argv[])\r
1823 {\r
1824    int multiple = 0;\r
1825    int ierror = 0;\r
1826 \r
1827    png_structp dummy_ptr;\r
1828 \r
1829    fprintf(STDERR, "\n Testing libpng version %s\n", PNG_LIBPNG_VER_STRING);\r
1830    fprintf(STDERR, "   with zlib   version %s\n", ZLIB_VERSION);\r
1831    fprintf(STDERR, "%s", png_get_copyright(NULL));\r
1832    /* Show the version of libpng used in building the library */\r
1833    fprintf(STDERR, " library (%lu):%s",\r
1834        (unsigned long)png_access_version_number(),\r
1835        png_get_header_version(NULL));\r
1836 \r
1837    /* Show the version of libpng used in building the application */\r
1838    fprintf(STDERR, " pngtest (%lu):%s", (unsigned long)PNG_LIBPNG_VER,\r
1839        PNG_HEADER_VERSION_STRING);\r
1840 \r
1841    /* Do some consistency checking on the memory allocation settings, I'm\r
1842     * not sure this matters, but it is nice to know, the first of these\r
1843     * tests should be impossible because of the way the macros are set\r
1844     * in pngconf.h\r
1845     */\r
1846 #if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K)\r
1847       fprintf(STDERR, " NOTE: Zlib compiled for max 64k, libpng not\n");\r
1848 #endif\r
1849    /* I think the following can happen. */\r
1850 #if !defined(MAXSEG_64K) && defined(PNG_MAX_MALLOC_64K)\r
1851       fprintf(STDERR, " NOTE: libpng compiled for max 64k, zlib not\n");\r
1852 #endif\r
1853 \r
1854    if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING))\r
1855    {\r
1856       fprintf(STDERR,\r
1857           "Warning: versions are different between png.h and png.c\n");\r
1858       fprintf(STDERR, "  png.h version: %s\n", PNG_LIBPNG_VER_STRING);\r
1859       fprintf(STDERR, "  png.c version: %s\n\n", png_libpng_ver);\r
1860       ++ierror;\r
1861    }\r
1862 \r
1863    if (argc > 1)\r
1864    {\r
1865       if (strcmp(argv[1], "-m") == 0)\r
1866       {\r
1867          multiple = 1;\r
1868          status_dots_requested = 0;\r
1869       }\r
1870 \r
1871       else if (strcmp(argv[1], "-mv") == 0 ||\r
1872                strcmp(argv[1], "-vm") == 0 )\r
1873       {\r
1874          multiple = 1;\r
1875          verbose = 1;\r
1876          status_dots_requested = 1;\r
1877       }\r
1878 \r
1879       else if (strcmp(argv[1], "-v") == 0)\r
1880       {\r
1881          verbose = 1;\r
1882          status_dots_requested = 1;\r
1883          inname = argv[2];\r
1884       }\r
1885 \r
1886       else if (strcmp(argv[1], "--strict") == 0)\r
1887       {\r
1888          status_dots_requested = 0;\r
1889          verbose = 1;\r
1890          inname = argv[2];\r
1891          strict++;\r
1892          relaxed = 0;\r
1893          multiple=1;\r
1894       }\r
1895 \r
1896       else if (strcmp(argv[1], "--relaxed") == 0)\r
1897       {\r
1898          status_dots_requested = 0;\r
1899          verbose = 1;\r
1900          inname = argv[2];\r
1901          strict = 0;\r
1902          relaxed++;\r
1903          multiple=1;\r
1904       }\r
1905       else if (strcmp(argv[1], "--xfail") == 0)\r
1906       {\r
1907          status_dots_requested = 0;\r
1908          verbose = 1;\r
1909          inname = argv[2];\r
1910          strict = 0;\r
1911          xfail++;\r
1912          relaxed++;\r
1913          multiple=1;\r
1914       }\r
1915 \r
1916       else\r
1917       {\r
1918          inname = argv[1];\r
1919          status_dots_requested = 0;\r
1920       }\r
1921    }\r
1922 \r
1923    if (multiple == 0 && argc == 3 + verbose)\r
1924       outname = argv[2 + verbose];\r
1925 \r
1926    if ((multiple == 0 && argc > 3 + verbose) ||\r
1927        (multiple != 0 && argc < 2))\r
1928    {\r
1929       fprintf(STDERR,\r
1930           "usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n",\r
1931           argv[0], argv[0]);\r
1932       fprintf(STDERR,\r
1933           "  reads/writes one PNG file (without -m) or multiple files (-m)\n");\r
1934       fprintf(STDERR,\r
1935           "  with -m %s is used as a temporary file\n", outname);\r
1936       exit(1);\r
1937    }\r
1938 \r
1939    if (multiple != 0)\r
1940    {\r
1941       int i;\r
1942 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG\r
1943       int allocation_now = current_allocation;\r
1944 #endif\r
1945       for (i=2; i<argc; ++i)\r
1946       {\r
1947          int kerror;\r
1948          fprintf(STDERR, "\n Testing %s:", argv[i]);\r
1949 #if PNG_DEBUG > 0\r
1950          fprintf(STDERR, "\n");\r
1951 #endif\r
1952          kerror = test_one_file(argv[i], outname);\r
1953          if (kerror == 0)\r
1954          {\r
1955 #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED\r
1956             fprintf(STDERR, "\n PASS (%lu zero samples)\n",\r
1957                 (unsigned long)zero_samples);\r
1958 #else\r
1959             fprintf(STDERR, " PASS\n");\r
1960 #endif\r
1961 #ifdef PNG_TIME_RFC1123_SUPPORTED\r
1962             if (tIME_chunk_present != 0)\r
1963                fprintf(STDERR, " tIME = %s\n", tIME_string);\r
1964 \r
1965             tIME_chunk_present = 0;\r
1966 #endif /* TIME_RFC1123 */\r
1967          }\r
1968 \r
1969          else\r
1970          {\r
1971             if (xfail)\r
1972               fprintf(STDERR, " XFAIL\n");\r
1973             else\r
1974             {\r
1975               fprintf(STDERR, " FAIL\n");\r
1976               ierror += kerror;\r
1977             }\r
1978          }\r
1979 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG\r
1980          if (allocation_now != current_allocation)\r
1981             fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n",\r
1982                 current_allocation - allocation_now);\r
1983 \r
1984          if (current_allocation != 0)\r
1985          {\r
1986             memory_infop pinfo = pinformation;\r
1987 \r
1988             fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n",\r
1989                 current_allocation);\r
1990 \r
1991             while (pinfo != NULL)\r
1992             {\r
1993                fprintf(STDERR, " %lu bytes at %p\n",\r
1994                    (unsigned long)pinfo->size,\r
1995                    pinfo->pointer);\r
1996                pinfo = pinfo->next;\r
1997             }\r
1998          }\r
1999 #endif\r
2000       }\r
2001 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG\r
2002          fprintf(STDERR, " Current memory allocation: %10d bytes\n",\r
2003              current_allocation);\r
2004          fprintf(STDERR, " Maximum memory allocation: %10d bytes\n",\r
2005              maximum_allocation);\r
2006          fprintf(STDERR, " Total   memory allocation: %10d bytes\n",\r
2007              total_allocation);\r
2008          fprintf(STDERR, "     Number of allocations: %10d\n",\r
2009              num_allocations);\r
2010 #endif\r
2011    }\r
2012 \r
2013    else\r
2014    {\r
2015       int i;\r
2016       for (i = 0; i<3; ++i)\r
2017       {\r
2018          int kerror;\r
2019 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG\r
2020          int allocation_now = current_allocation;\r
2021 #endif\r
2022          if (i == 1)\r
2023             status_dots_requested = 1;\r
2024 \r
2025          else if (verbose == 0)\r
2026             status_dots_requested = 0;\r
2027 \r
2028          if (i == 0 || verbose == 1 || ierror != 0)\r
2029          {\r
2030             fprintf(STDERR, "\n Testing %s:", inname);\r
2031 #if PNG_DEBUG > 0\r
2032             fprintf(STDERR, "\n");\r
2033 #endif\r
2034          }\r
2035 \r
2036          kerror = test_one_file(inname, outname);\r
2037 \r
2038          if (kerror == 0)\r
2039          {\r
2040             if (verbose == 1 || i == 2)\r
2041             {\r
2042 #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED\r
2043                 fprintf(STDERR, "\n PASS (%lu zero samples)\n",\r
2044                     (unsigned long)zero_samples);\r
2045 #else\r
2046                 fprintf(STDERR, " PASS\n");\r
2047 #endif\r
2048 #ifdef PNG_TIME_RFC1123_SUPPORTED\r
2049              if (tIME_chunk_present != 0)\r
2050                 fprintf(STDERR, " tIME = %s\n", tIME_string);\r
2051 #endif /* TIME_RFC1123 */\r
2052             }\r
2053          }\r
2054 \r
2055          else\r
2056          {\r
2057             if (verbose == 0 && i != 2)\r
2058             {\r
2059                fprintf(STDERR, "\n Testing %s:", inname);\r
2060 #if PNG_DEBUG > 0\r
2061                fprintf(STDERR, "\n");\r
2062 #endif\r
2063             }\r
2064 \r
2065             if (xfail)\r
2066               fprintf(STDERR, " XFAIL\n");\r
2067             else\r
2068             {\r
2069               fprintf(STDERR, " FAIL\n");\r
2070               ierror += kerror;\r
2071             }\r
2072          }\r
2073 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG\r
2074          if (allocation_now != current_allocation)\r
2075              fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n",\r
2076                  current_allocation - allocation_now);\r
2077 \r
2078          if (current_allocation != 0)\r
2079          {\r
2080              memory_infop pinfo = pinformation;\r
2081 \r
2082              fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n",\r
2083                  current_allocation);\r
2084 \r
2085              while (pinfo != NULL)\r
2086              {\r
2087                 fprintf(STDERR, " %lu bytes at %p\n",\r
2088                     (unsigned long)pinfo->size, pinfo->pointer);\r
2089                 pinfo = pinfo->next;\r
2090              }\r
2091           }\r
2092 #endif\r
2093        }\r
2094 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG\r
2095        fprintf(STDERR, " Current memory allocation: %10d bytes\n",\r
2096            current_allocation);\r
2097        fprintf(STDERR, " Maximum memory allocation: %10d bytes\n",\r
2098            maximum_allocation);\r
2099        fprintf(STDERR, " Total   memory allocation: %10d bytes\n",\r
2100            total_allocation);\r
2101        fprintf(STDERR, "     Number of allocations: %10d\n",\r
2102            num_allocations);\r
2103 #endif\r
2104    }\r
2105 \r
2106 #ifdef PNGTEST_TIMING\r
2107    t_stop = (float)clock();\r
2108    t_misc += (t_stop - t_start);\r
2109    t_start = t_stop;\r
2110    fprintf(STDERR, " CPU time used = %.3f seconds",\r
2111        (t_misc+t_decode+t_encode)/(float)CLOCKS_PER_SEC);\r
2112    fprintf(STDERR, " (decoding %.3f,\n",\r
2113        t_decode/(float)CLOCKS_PER_SEC);\r
2114    fprintf(STDERR, "        encoding %.3f ,",\r
2115        t_encode/(float)CLOCKS_PER_SEC);\r
2116    fprintf(STDERR, " other %.3f seconds)\n\n",\r
2117        t_misc/(float)CLOCKS_PER_SEC);\r
2118 #endif\r
2119 \r
2120    if (ierror == 0)\r
2121       fprintf(STDERR, " libpng passes test\n");\r
2122 \r
2123    else\r
2124       fprintf(STDERR, " libpng FAILS test\n");\r
2125 \r
2126    dummy_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);\r
2127    fprintf(STDERR, " Default limits:\n");\r
2128    fprintf(STDERR, "  width_max  = %lu\n",\r
2129        (unsigned long) png_get_user_width_max(dummy_ptr));\r
2130    fprintf(STDERR, "  height_max = %lu\n",\r
2131        (unsigned long) png_get_user_height_max(dummy_ptr));\r
2132    if (png_get_chunk_cache_max(dummy_ptr) == 0)\r
2133       fprintf(STDERR, "  cache_max  = unlimited\n");\r
2134    else\r
2135       fprintf(STDERR, "  cache_max  = %lu\n",\r
2136           (unsigned long) png_get_chunk_cache_max(dummy_ptr));\r
2137    if (png_get_chunk_malloc_max(dummy_ptr) == 0)\r
2138       fprintf(STDERR, "  malloc_max = unlimited\n");\r
2139    else\r
2140       fprintf(STDERR, "  malloc_max = %lu\n",\r
2141           (unsigned long) png_get_chunk_malloc_max(dummy_ptr));\r
2142    png_destroy_read_struct(&dummy_ptr, NULL, NULL);\r
2143 \r
2144    return (int)(ierror != 0);\r
2145 }\r
2146 #else\r
2147 int\r
2148 main(void)\r
2149 {\r
2150    fprintf(STDERR,\r
2151        " test ignored because libpng was not built with read support\n");\r
2152    /* And skip this test */\r
2153    return PNG_LIBPNG_VER < 10600 ? 0 : 77;\r
2154 }\r
2155 #endif\r
2156 \r
2157 /* Generate a compiler error if there is an old png.h in the search path. */\r
2158 typedef png_libpng_version_1_6_37 Your_png_h_is_not_version_1_6_37;\r