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