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.6.25 [September 1, 2016]
      5  * Copyright (c) 1998-2002,2004,2006-2016 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 png_alloc_size_t current_allocation = 0;
    518 static png_alloc_size_t maximum_allocation = 0;
    519 static png_alloc_size_t total_allocation = 0;
    520 static png_alloc_size_t 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             if (current_allocation < pinfo->size)
    608                fprintf(STDERR, "Duplicate free of memory\n");
    609             else
    610                current_allocation -= pinfo->size;
    611             /* We must free the list element too, but first kill
    612                the memory that is to be freed. */
    613             memset(ptr, 0x55, pinfo->size);
    614             free(pinfo);
    615             pinfo = NULL;
    616             break;
    617          }
    618 
    619          if (pinfo->next == NULL)
    620          {
    621             fprintf(STDERR, "Pointer %p not found\n", ptr);
    622             break;
    623          }
    624 
    625          ppinfo = &pinfo->next;
    626       }
    627    }
    628 
    629    /* Finally free the data. */
    630    if (verbose != 0)
    631       printf("Freeing %p\n", ptr);
    632 
    633    if (ptr != NULL)
    634       free(ptr);
    635    ptr = NULL;
    636 }
    637 #endif /* USER_MEM && DEBUG */
    638 /* END of code to test memory allocation/deallocation */
    639 
    640 
    641 #ifdef PNG_READ_USER_CHUNKS_SUPPORTED
    642 /* Demonstration of user chunk support of the sTER and vpAg chunks */
    643 
    644 /* (sTER is a public chunk not yet known by libpng.  vpAg is a private
    645 chunk used in ImageMagick to store "virtual page" size).  */
    646 
    647 static struct user_chunk_data
    648 {
    649    png_const_infop info_ptr;
    650    png_uint_32     vpAg_width, vpAg_height;
    651    png_byte        vpAg_units;
    652    png_byte        sTER_mode;
    653    int             location[2];
    654 }
    655 user_chunk_data;
    656 
    657 /* Used for location and order; zero means nothing. */
    658 #define have_sTER   0x01
    659 #define have_vpAg   0x02
    660 #define before_PLTE 0x10
    661 #define before_IDAT 0x20
    662 #define after_IDAT  0x40
    663 
    664 static void
    665 init_callback_info(png_const_infop info_ptr)
    666 {
    667    MEMZERO(user_chunk_data);
    668    user_chunk_data.info_ptr = info_ptr;
    669 }
    670 
    671 static int
    672 set_location(png_structp png_ptr, struct user_chunk_data *data, int what)
    673 {
    674    int location;
    675 
    676    if ((data->location[0] & what) != 0 || (data->location[1] & what) != 0)
    677       return 0; /* already have one of these */
    678 
    679    /* Find where we are (the code below zeroes info_ptr to indicate that the
    680     * chunks before the first IDAT have been read.)
    681     */
    682    if (data->info_ptr == NULL) /* after IDAT */
    683       location = what | after_IDAT;
    684 
    685    else if (png_get_valid(png_ptr, data->info_ptr, PNG_INFO_PLTE) != 0)
    686       location = what | before_IDAT;
    687 
    688    else
    689       location = what | before_PLTE;
    690 
    691    if (data->location[0] == 0)
    692       data->location[0] = location;
    693 
    694    else
    695       data->location[1] = location;
    696 
    697    return 1; /* handled */
    698 }
    699 
    700 static int PNGCBAPI
    701 read_user_chunk_callback(png_struct *png_ptr, png_unknown_chunkp chunk)
    702 {
    703    struct user_chunk_data *my_user_chunk_data =
    704       (struct user_chunk_data*)png_get_user_chunk_ptr(png_ptr);
    705 
    706    if (my_user_chunk_data == NULL)
    707       png_error(png_ptr, "lost user chunk pointer");
    708 
    709    /* Return one of the following:
    710     *    return (-n);  chunk had an error
    711     *    return (0);  did not recognize
    712     *    return (n);  success
    713     *
    714     * The unknown chunk structure contains the chunk data:
    715     * png_byte name[5];
    716     * png_byte *data;
    717     * png_size_t size;
    718     *
    719     * Note that libpng has already taken care of the CRC handling.
    720     */
    721 
    722    if (chunk->name[0] == 115 && chunk->name[1] ==  84 &&     /* s  T */
    723        chunk->name[2] ==  69 && chunk->name[3] ==  82)       /* E  R */
    724       {
    725          /* Found sTER chunk */
    726          if (chunk->size != 1)
    727             return (-1); /* Error return */
    728 
    729          if (chunk->data[0] != 0 && chunk->data[0] != 1)
    730             return (-1);  /* Invalid mode */
    731 
    732          if (set_location(png_ptr, my_user_chunk_data, have_sTER) != 0)
    733          {
    734             my_user_chunk_data->sTER_mode=chunk->data[0];
    735             return (1);
    736          }
    737 
    738          else
    739             return (0); /* duplicate sTER - give it to libpng */
    740       }
    741 
    742    if (chunk->name[0] != 118 || chunk->name[1] != 112 ||    /* v  p */
    743        chunk->name[2] !=  65 || chunk->name[3] != 103)      /* A  g */
    744       return (0); /* Did not recognize */
    745 
    746    /* Found ImageMagick vpAg chunk */
    747 
    748    if (chunk->size != 9)
    749       return (-1); /* Error return */
    750 
    751    if (set_location(png_ptr, my_user_chunk_data, have_vpAg) == 0)
    752       return (0);  /* duplicate vpAg */
    753 
    754    my_user_chunk_data->vpAg_width = png_get_uint_31(png_ptr, chunk->data);
    755    my_user_chunk_data->vpAg_height = png_get_uint_31(png_ptr, chunk->data + 4);
    756    my_user_chunk_data->vpAg_units = chunk->data[8];
    757 
    758    return (1);
    759 }
    760 
    761 #ifdef PNG_WRITE_SUPPORTED
    762 static void
    763 write_sTER_chunk(png_structp write_ptr)
    764 {
    765    png_byte sTER[5] = {115,  84,  69,  82, '\0'};
    766 
    767    if (verbose != 0)
    768       fprintf(STDERR, "\n stereo mode = %d\n", user_chunk_data.sTER_mode);
    769 
    770    png_write_chunk(write_ptr, sTER, &user_chunk_data.sTER_mode, 1);
    771 }
    772 
    773 static void
    774 write_vpAg_chunk(png_structp write_ptr)
    775 {
    776    png_byte vpAg[5] = {118, 112,  65, 103, '\0'};
    777 
    778    png_byte vpag_chunk_data[9];
    779 
    780    if (verbose != 0)
    781       fprintf(STDERR, " vpAg = %lu x %lu, units = %d\n",
    782           (unsigned long)user_chunk_data.vpAg_width,
    783           (unsigned long)user_chunk_data.vpAg_height,
    784           user_chunk_data.vpAg_units);
    785 
    786    png_save_uint_32(vpag_chunk_data, user_chunk_data.vpAg_width);
    787    png_save_uint_32(vpag_chunk_data + 4, user_chunk_data.vpAg_height);
    788    vpag_chunk_data[8] = user_chunk_data.vpAg_units;
    789    png_write_chunk(write_ptr, vpAg, vpag_chunk_data, 9);
    790 }
    791 
    792 static void
    793 write_chunks(png_structp write_ptr, int location)
    794 {
    795    int i;
    796 
    797    /* Notice that this preserves the original chunk order, however chunks
    798     * intercepted by the callback will be written *after* chunks passed to
    799     * libpng.  This will actually reverse a pair of sTER chunks or a pair of
    800     * vpAg chunks, resulting in an error later.  This is not worth worrying
    801     * about - the chunks should not be duplicated!
    802     */
    803    for (i=0; i<2; ++i)
    804    {
    805       if (user_chunk_data.location[i] == (location | have_sTER))
    806          write_sTER_chunk(write_ptr);
    807 
    808       else if (user_chunk_data.location[i] == (location | have_vpAg))
    809          write_vpAg_chunk(write_ptr);
    810    }
    811 }
    812 #endif /* WRITE */
    813 #else /* !READ_USER_CHUNKS */
    814 #  define write_chunks(pp,loc) ((void)0)
    815 #endif
    816 /* END of code to demonstrate user chunk support */
    817 
    818 /* START of code to check that libpng has the required text support; this only
    819  * checks for the write support because if read support is missing the chunk
    820  * will simply not be reported back to pngtest.
    821  */
    822 #ifdef PNG_TEXT_SUPPORTED
    823 static void
    824 pngtest_check_text_support(png_structp png_ptr, png_textp text_ptr,
    825     int num_text)
    826 {
    827    while (num_text > 0)
    828    {
    829       switch (text_ptr[--num_text].compression)
    830       {
    831          case PNG_TEXT_COMPRESSION_NONE:
    832             break;
    833 
    834          case PNG_TEXT_COMPRESSION_zTXt:
    835 #           ifndef PNG_WRITE_zTXt_SUPPORTED
    836                ++unsupported_chunks;
    837                /* In libpng 1.7 this now does an app-error, so stop it: */
    838                text_ptr[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
    839 #           endif
    840             break;
    841 
    842          case PNG_ITXT_COMPRESSION_NONE:
    843          case PNG_ITXT_COMPRESSION_zTXt:
    844 #           ifndef PNG_WRITE_iTXt_SUPPORTED
    845                ++unsupported_chunks;
    846                text_ptr[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
    847 #           endif
    848             break;
    849 
    850          default:
    851             /* This is an error */
    852             png_error(png_ptr, "invalid text chunk compression field");
    853             break;
    854       }
    855    }
    856 }
    857 #endif
    858 /* END of code to check that libpng has the required text support */
    859 
    860 /* Test one file */
    861 static int
    862 test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
    863 {
    864    static png_FILE_p fpin;
    865    static png_FILE_p fpout;  /* "static" prevents setjmp corruption */
    866    pngtest_error_parameters error_parameters;
    867    png_structp read_ptr;
    868    png_infop read_info_ptr, end_info_ptr;
    869 #ifdef PNG_WRITE_SUPPORTED
    870    png_structp write_ptr;
    871    png_infop write_info_ptr;
    872    png_infop write_end_info_ptr;
    873 #ifdef PNG_WRITE_FILTER_SUPPORTED
    874    int interlace_preserved = 1;
    875 #endif /* WRITE_FILTER */
    876 #else /* !WRITE */
    877    png_structp write_ptr = NULL;
    878    png_infop write_info_ptr = NULL;
    879    png_infop write_end_info_ptr = NULL;
    880 #endif /* !WRITE */
    881    png_bytep row_buf;
    882    png_uint_32 y;
    883    png_uint_32 width, height;
    884    volatile int num_passes;
    885    int pass;
    886    int bit_depth, color_type;
    887 
    888    row_buf = NULL;
    889    error_parameters.file_name = inname;
    890 
    891    if ((fpin = fopen(inname, "rb")) == NULL)
    892    {
    893       fprintf(STDERR, "Could not find input file %s\n", inname);
    894       return (1);
    895    }
    896 
    897    if ((fpout = fopen(outname, "wb")) == NULL)
    898    {
    899       fprintf(STDERR, "Could not open output file %s\n", outname);
    900       FCLOSE(fpin);
    901       return (1);
    902    }
    903 
    904    pngtest_debug("Allocating read and write structures");
    905 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
    906    read_ptr =
    907        png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL,
    908        NULL, NULL, NULL, png_debug_malloc, png_debug_free);
    909 #else
    910    read_ptr =
    911        png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    912 #endif
    913    png_set_error_fn(read_ptr, &error_parameters, pngtest_error,
    914        pngtest_warning);
    915 
    916 #ifdef PNG_WRITE_SUPPORTED
    917 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
    918    write_ptr =
    919        png_create_write_struct_2(PNG_LIBPNG_VER_STRING, NULL,
    920        NULL, NULL, NULL, png_debug_malloc, png_debug_free);
    921 #else
    922    write_ptr =
    923        png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    924 #endif
    925    png_set_error_fn(write_ptr, &error_parameters, pngtest_error,
    926        pngtest_warning);
    927 #endif
    928    pngtest_debug("Allocating read_info, write_info and end_info structures");
    929    read_info_ptr = png_create_info_struct(read_ptr);
    930    end_info_ptr = png_create_info_struct(read_ptr);
    931 #ifdef PNG_WRITE_SUPPORTED
    932    write_info_ptr = png_create_info_struct(write_ptr);
    933    write_end_info_ptr = png_create_info_struct(write_ptr);
    934 #endif
    935 
    936 #ifdef PNG_READ_USER_CHUNKS_SUPPORTED
    937    init_callback_info(read_info_ptr);
    938    png_set_read_user_chunk_fn(read_ptr, &user_chunk_data,
    939        read_user_chunk_callback);
    940 #endif
    941 
    942 #ifdef PNG_SET_USER_LIMITS_SUPPORTED
    943 #  ifdef CHUNK_LIMIT /* from the build, for testing */
    944       png_set_chunk_malloc_max(read_ptr, CHUNK_LIMIT);
    945 #  endif /* CHUNK_LIMIT */
    946 #endif
    947 
    948 #ifdef PNG_SETJMP_SUPPORTED
    949    pngtest_debug("Setting jmpbuf for read struct");
    950    if (setjmp(png_jmpbuf(read_ptr)))
    951    {
    952       fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname);
    953       png_free(read_ptr, row_buf);
    954       row_buf = NULL;
    955       png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
    956 #ifdef PNG_WRITE_SUPPORTED
    957       png_destroy_info_struct(write_ptr, &write_end_info_ptr);
    958       png_destroy_write_struct(&write_ptr, &write_info_ptr);
    959 #endif
    960       FCLOSE(fpin);
    961       FCLOSE(fpout);
    962       return (1);
    963    }
    964 
    965 #ifdef PNG_WRITE_SUPPORTED
    966    pngtest_debug("Setting jmpbuf for write struct");
    967 
    968    if (setjmp(png_jmpbuf(write_ptr)))
    969    {
    970       fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname);
    971       png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
    972       png_destroy_info_struct(write_ptr, &write_end_info_ptr);
    973 #ifdef PNG_WRITE_SUPPORTED
    974       png_destroy_write_struct(&write_ptr, &write_info_ptr);
    975 #endif
    976       FCLOSE(fpin);
    977       FCLOSE(fpout);
    978       return (1);
    979    }
    980 #endif
    981 #endif
    982 
    983    if (strict != 0)
    984    {
    985       /* Treat png_benign_error() as errors on read */
    986       png_set_benign_errors(read_ptr, 0);
    987 
    988 #ifdef PNG_WRITE_SUPPORTED
    989       /* Treat them as errors on write */
    990       png_set_benign_errors(write_ptr, 0);
    991 #endif
    992 
    993       /* if strict is not set, then app warnings and errors are treated as
    994        * warnings in release builds, but not in unstable builds; this can be
    995        * changed with '--relaxed'.
    996        */
    997    }
    998 
    999    else if (relaxed != 0)
   1000    {
   1001       /* Allow application (pngtest) errors and warnings to pass */
   1002       png_set_benign_errors(read_ptr, 1);
   1003 
   1004 #ifdef PNG_WRITE_SUPPORTED
   1005       png_set_benign_errors(write_ptr, 1);
   1006 #endif
   1007    }
   1008 
   1009    pngtest_debug("Initializing input and output streams");
   1010 #ifdef PNG_STDIO_SUPPORTED
   1011    png_init_io(read_ptr, fpin);
   1012 #  ifdef PNG_WRITE_SUPPORTED
   1013    png_init_io(write_ptr, fpout);
   1014 #  endif
   1015 #else
   1016    png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data);
   1017 #  ifdef PNG_WRITE_SUPPORTED
   1018    png_set_write_fn(write_ptr, (png_voidp)fpout,  pngtest_write_data,
   1019 #    ifdef PNG_WRITE_FLUSH_SUPPORTED
   1020        pngtest_flush);
   1021 #    else
   1022        NULL);
   1023 #    endif
   1024 #  endif
   1025 #endif
   1026 
   1027    if (status_dots_requested == 1)
   1028    {
   1029 #ifdef PNG_WRITE_SUPPORTED
   1030       png_set_write_status_fn(write_ptr, write_row_callback);
   1031 #endif
   1032       png_set_read_status_fn(read_ptr, read_row_callback);
   1033    }
   1034 
   1035    else
   1036    {
   1037 #ifdef PNG_WRITE_SUPPORTED
   1038       png_set_write_status_fn(write_ptr, NULL);
   1039 #endif
   1040       png_set_read_status_fn(read_ptr, NULL);
   1041    }
   1042 
   1043 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
   1044    png_set_read_user_transform_fn(read_ptr, read_user_callback);
   1045 #endif
   1046 #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
   1047    zero_samples = 0;
   1048    png_set_write_user_transform_fn(write_ptr, count_zero_samples);
   1049 #endif
   1050 
   1051 #ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
   1052    /* Preserve all the unknown chunks, if possible.  If this is disabled then,
   1053     * even if the png_{get,set}_unknown_chunks stuff is enabled, we can't use
   1054     * libpng to *save* the unknown chunks on read (because we can't switch the
   1055     * save option on!)
   1056     *
   1057     * Notice that if SET_UNKNOWN_CHUNKS is *not* supported read will discard all
   1058     * unknown chunks and write will write them all.
   1059     */
   1060 #ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
   1061    png_set_keep_unknown_chunks(read_ptr, PNG_HANDLE_CHUNK_ALWAYS,
   1062        NULL, 0);
   1063 #endif
   1064 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
   1065    png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_ALWAYS,
   1066        NULL, 0);
   1067 #endif
   1068 #endif
   1069 
   1070    pngtest_debug("Reading info struct");
   1071    png_read_info(read_ptr, read_info_ptr);
   1072 
   1073 #ifdef PNG_READ_USER_CHUNKS_SUPPORTED
   1074    /* This is a bit of a hack; there is no obvious way in the callback function
   1075     * to determine that the chunks before the first IDAT have been read, so
   1076     * remove the info_ptr (which is only used to determine position relative to
   1077     * PLTE) here to indicate that we are after the IDAT.
   1078     */
   1079    user_chunk_data.info_ptr = NULL;
   1080 #endif
   1081 
   1082    pngtest_debug("Transferring info struct");
   1083    {
   1084       int interlace_type, compression_type, filter_type;
   1085 
   1086       if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth,
   1087           &color_type, &interlace_type, &compression_type, &filter_type) != 0)
   1088       {
   1089          png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth,
   1090              color_type, interlace_type, compression_type, filter_type);
   1091          /* num_passes may not be available below if interlace support is not
   1092           * provided by libpng for both read and write.
   1093           */
   1094          switch (interlace_type)
   1095          {
   1096             case PNG_INTERLACE_NONE:
   1097                num_passes = 1;
   1098                break;
   1099 
   1100             case PNG_INTERLACE_ADAM7:
   1101                num_passes = 7;
   1102                break;
   1103 
   1104             default:
   1105                png_error(read_ptr, "invalid interlace type");
   1106                /*NOT REACHED*/
   1107          }
   1108       }
   1109 
   1110       else
   1111          png_error(read_ptr, "png_get_IHDR failed");
   1112    }
   1113 #ifdef PNG_FIXED_POINT_SUPPORTED
   1114 #ifdef PNG_cHRM_SUPPORTED
   1115    {
   1116       png_fixed_point white_x, white_y, red_x, red_y, green_x, green_y, blue_x,
   1117           blue_y;
   1118 
   1119       if (png_get_cHRM_fixed(read_ptr, read_info_ptr, &white_x, &white_y,
   1120           &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y) != 0)
   1121       {
   1122          png_set_cHRM_fixed(write_ptr, write_info_ptr, white_x, white_y, red_x,
   1123              red_y, green_x, green_y, blue_x, blue_y);
   1124       }
   1125    }
   1126 #endif
   1127 #ifdef PNG_gAMA_SUPPORTED
   1128    {
   1129       png_fixed_point gamma;
   1130 
   1131       if (png_get_gAMA_fixed(read_ptr, read_info_ptr, &gamma) != 0)
   1132          png_set_gAMA_fixed(write_ptr, write_info_ptr, gamma);
   1133    }
   1134 #endif
   1135 #else /* Use floating point versions */
   1136 #ifdef PNG_FLOATING_POINT_SUPPORTED
   1137 #ifdef PNG_cHRM_SUPPORTED
   1138    {
   1139       double white_x, white_y, red_x, red_y, green_x, green_y, blue_x,
   1140           blue_y;
   1141 
   1142       if (png_get_cHRM(read_ptr, read_info_ptr, &white_x, &white_y, &red_x,
   1143           &red_y, &green_x, &green_y, &blue_x, &blue_y) != 0)
   1144       {
   1145          png_set_cHRM(write_ptr, write_info_ptr, white_x, white_y, red_x,
   1146              red_y, green_x, green_y, blue_x, blue_y);
   1147       }
   1148    }
   1149 #endif
   1150 #ifdef PNG_gAMA_SUPPORTED
   1151    {
   1152       double gamma;
   1153 
   1154       if (png_get_gAMA(read_ptr, read_info_ptr, &gamma) != 0)
   1155          png_set_gAMA(write_ptr, write_info_ptr, gamma);
   1156    }
   1157 #endif
   1158 #endif /* Floating point */
   1159 #endif /* Fixed point */
   1160 #ifdef PNG_iCCP_SUPPORTED
   1161    {
   1162       png_charp name;
   1163       png_bytep profile;
   1164       png_uint_32 proflen;
   1165       int compression_type;
   1166 
   1167       if (png_get_iCCP(read_ptr, read_info_ptr, &name, &compression_type,
   1168           &profile, &proflen) != 0)
   1169       {
   1170          png_set_iCCP(write_ptr, write_info_ptr, name, compression_type,
   1171              profile, proflen);
   1172       }
   1173    }
   1174 #endif
   1175 #ifdef PNG_sRGB_SUPPORTED
   1176    {
   1177       int intent;
   1178 
   1179       if (png_get_sRGB(read_ptr, read_info_ptr, &intent) != 0)
   1180          png_set_sRGB(write_ptr, write_info_ptr, intent);
   1181    }
   1182 #endif
   1183    {
   1184       png_colorp palette;
   1185       int num_palette;
   1186 
   1187       if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette) != 0)
   1188          png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette);
   1189    }
   1190 #ifdef PNG_bKGD_SUPPORTED
   1191    {
   1192       png_color_16p background;
   1193 
   1194       if (png_get_bKGD(read_ptr, read_info_ptr, &background) != 0)
   1195       {
   1196          png_set_bKGD(write_ptr, write_info_ptr, background);
   1197       }
   1198    }
   1199 #endif
   1200 #ifdef PNG_hIST_SUPPORTED
   1201    {
   1202       png_uint_16p hist;
   1203 
   1204       if (png_get_hIST(read_ptr, read_info_ptr, &hist) != 0)
   1205          png_set_hIST(write_ptr, write_info_ptr, hist);
   1206    }
   1207 #endif
   1208 #ifdef PNG_oFFs_SUPPORTED
   1209    {
   1210       png_int_32 offset_x, offset_y;
   1211       int unit_type;
   1212 
   1213       if (png_get_oFFs(read_ptr, read_info_ptr, &offset_x, &offset_y,
   1214           &unit_type) != 0)
   1215       {
   1216          png_set_oFFs(write_ptr, write_info_ptr, offset_x, offset_y, unit_type);
   1217       }
   1218    }
   1219 #endif
   1220 #ifdef PNG_pCAL_SUPPORTED
   1221    {
   1222       png_charp purpose, units;
   1223       png_charpp params;
   1224       png_int_32 X0, X1;
   1225       int type, nparams;
   1226 
   1227       if (png_get_pCAL(read_ptr, read_info_ptr, &purpose, &X0, &X1, &type,
   1228           &nparams, &units, &params) != 0)
   1229       {
   1230          png_set_pCAL(write_ptr, write_info_ptr, purpose, X0, X1, type,
   1231              nparams, units, params);
   1232       }
   1233    }
   1234 #endif
   1235 #ifdef PNG_pHYs_SUPPORTED
   1236    {
   1237       png_uint_32 res_x, res_y;
   1238       int unit_type;
   1239 
   1240       if (png_get_pHYs(read_ptr, read_info_ptr, &res_x, &res_y,
   1241           &unit_type) != 0)
   1242          png_set_pHYs(write_ptr, write_info_ptr, res_x, res_y, unit_type);
   1243    }
   1244 #endif
   1245 #ifdef PNG_sBIT_SUPPORTED
   1246    {
   1247       png_color_8p sig_bit;
   1248 
   1249       if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit) != 0)
   1250          png_set_sBIT(write_ptr, write_info_ptr, sig_bit);
   1251    }
   1252 #endif
   1253 #ifdef PNG_sCAL_SUPPORTED
   1254 #if defined(PNG_FLOATING_POINT_SUPPORTED) && \
   1255    defined(PNG_FLOATING_ARITHMETIC_SUPPORTED)
   1256    {
   1257       int unit;
   1258       double scal_width, scal_height;
   1259 
   1260       if (png_get_sCAL(read_ptr, read_info_ptr, &unit, &scal_width,
   1261           &scal_height) != 0)
   1262       {
   1263          png_set_sCAL(write_ptr, write_info_ptr, unit, scal_width, scal_height);
   1264       }
   1265    }
   1266 #else
   1267 #ifdef PNG_FIXED_POINT_SUPPORTED
   1268    {
   1269       int unit;
   1270       png_charp scal_width, scal_height;
   1271 
   1272       if (png_get_sCAL_s(read_ptr, read_info_ptr, &unit, &scal_width,
   1273            &scal_height) != 0)
   1274       {
   1275          png_set_sCAL_s(write_ptr, write_info_ptr, unit, scal_width,
   1276              scal_height);
   1277       }
   1278    }
   1279 #endif
   1280 #endif
   1281 #endif
   1282 
   1283 #ifdef PNG_sPLT_SUPPORTED
   1284    {
   1285        png_sPLT_tp entries;
   1286 
   1287        int num_entries = (int) png_get_sPLT(read_ptr, read_info_ptr, &entries);
   1288        if (num_entries)
   1289        {
   1290            png_set_sPLT(write_ptr, write_info_ptr, entries, num_entries);
   1291        }
   1292    }
   1293 #endif
   1294 
   1295 #ifdef PNG_TEXT_SUPPORTED
   1296    {
   1297       png_textp text_ptr;
   1298       int num_text;
   1299 
   1300       if (png_get_text(read_ptr, read_info_ptr, &text_ptr, &num_text) > 0)
   1301       {
   1302          pngtest_debug1("Handling %d iTXt/tEXt/zTXt chunks", num_text);
   1303 
   1304          pngtest_check_text_support(read_ptr, text_ptr, num_text);
   1305 
   1306          if (verbose != 0)
   1307          {
   1308             int i;
   1309 
   1310             printf("\n");
   1311             for (i=0; i<num_text; i++)
   1312             {
   1313                printf("   Text compression[%d]=%d\n",
   1314                    i, text_ptr[i].compression);
   1315             }
   1316          }
   1317 
   1318          png_set_text(write_ptr, write_info_ptr, text_ptr, num_text);
   1319       }
   1320    }
   1321 #endif
   1322 #ifdef PNG_tIME_SUPPORTED
   1323    {
   1324       png_timep mod_time;
   1325 
   1326       if (png_get_tIME(read_ptr, read_info_ptr, &mod_time) != 0)
   1327       {
   1328          png_set_tIME(write_ptr, write_info_ptr, mod_time);
   1329 #ifdef PNG_TIME_RFC1123_SUPPORTED
   1330          if (png_convert_to_rfc1123_buffer(tIME_string, mod_time) != 0)
   1331             tIME_string[(sizeof tIME_string) - 1] = '\0';
   1332 
   1333          else
   1334          {
   1335             strncpy(tIME_string, "*** invalid time ***", (sizeof tIME_string));
   1336             tIME_string[(sizeof tIME_string) - 1] = '\0';
   1337          }
   1338 
   1339          tIME_chunk_present++;
   1340 #endif /* TIME_RFC1123 */
   1341       }
   1342    }
   1343 #endif
   1344 #ifdef PNG_tRNS_SUPPORTED
   1345    {
   1346       png_bytep trans_alpha;
   1347       int num_trans;
   1348       png_color_16p trans_color;
   1349 
   1350       if (png_get_tRNS(read_ptr, read_info_ptr, &trans_alpha, &num_trans,
   1351           &trans_color) != 0)
   1352       {
   1353          int sample_max = (1 << bit_depth);
   1354          /* libpng doesn't reject a tRNS chunk with out-of-range samples */
   1355          if (!((color_type == PNG_COLOR_TYPE_GRAY &&
   1356              (int)trans_color->gray > sample_max) ||
   1357              (color_type == PNG_COLOR_TYPE_RGB &&
   1358              ((int)trans_color->red > sample_max ||
   1359              (int)trans_color->green > sample_max ||
   1360              (int)trans_color->blue > sample_max))))
   1361             png_set_tRNS(write_ptr, write_info_ptr, trans_alpha, num_trans,
   1362                trans_color);
   1363       }
   1364    }
   1365 #endif
   1366 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
   1367    {
   1368       png_unknown_chunkp unknowns;
   1369       int num_unknowns = png_get_unknown_chunks(read_ptr, read_info_ptr,
   1370           &unknowns);
   1371 
   1372       if (num_unknowns != 0)
   1373       {
   1374          png_set_unknown_chunks(write_ptr, write_info_ptr, unknowns,
   1375              num_unknowns);
   1376 #if PNG_LIBPNG_VER < 10600
   1377          /* Copy the locations from the read_info_ptr.  The automatically
   1378           * generated locations in write_end_info_ptr are wrong prior to 1.6.0
   1379           * because they are reset from the write pointer (removed in 1.6.0).
   1380           */
   1381          {
   1382             int i;
   1383             for (i = 0; i < num_unknowns; i++)
   1384               png_set_unknown_chunk_location(write_ptr, write_info_ptr, i,
   1385                   unknowns[i].location);
   1386          }
   1387 #endif
   1388       }
   1389    }
   1390 #endif
   1391 
   1392 #ifdef PNG_WRITE_SUPPORTED
   1393    pngtest_debug("Writing info struct");
   1394 
   1395    /* Write the info in two steps so that if we write the 'unknown' chunks here
   1396     * they go to the correct place.
   1397     */
   1398    png_write_info_before_PLTE(write_ptr, write_info_ptr);
   1399 
   1400    write_chunks(write_ptr, before_PLTE); /* before PLTE */
   1401 
   1402    png_write_info(write_ptr, write_info_ptr);
   1403 
   1404    write_chunks(write_ptr, before_IDAT); /* after PLTE */
   1405 #endif
   1406 
   1407 #ifdef SINGLE_ROWBUF_ALLOC
   1408    pngtest_debug("Allocating row buffer...");
   1409    row_buf = (png_bytep)png_malloc(read_ptr,
   1410        png_get_rowbytes(read_ptr, read_info_ptr));
   1411 
   1412    pngtest_debug1("\t0x%08lx", (unsigned long)row_buf);
   1413 #endif /* SINGLE_ROWBUF_ALLOC */
   1414    pngtest_debug("Writing row data");
   1415 
   1416 #if defined(PNG_READ_INTERLACING_SUPPORTED) &&\
   1417    defined(PNG_WRITE_INTERLACING_SUPPORTED)
   1418    /* Both must be defined for libpng to be able to handle the interlace,
   1419     * otherwise it gets handled below by simply reading and writing the passes
   1420     * directly.
   1421     */
   1422    if (png_set_interlace_handling(read_ptr) != num_passes)
   1423       png_error(write_ptr,
   1424           "png_set_interlace_handling(read): wrong pass count ");
   1425    if (png_set_interlace_handling(write_ptr) != num_passes)
   1426       png_error(write_ptr,
   1427           "png_set_interlace_handling(write): wrong pass count ");
   1428 #else /* png_set_interlace_handling not called on either read or write */
   1429 #  define calc_pass_height
   1430 #endif /* not using libpng interlace handling */
   1431 
   1432 #ifdef PNGTEST_TIMING
   1433    t_stop = (float)clock();
   1434    t_misc += (t_stop - t_start);
   1435    t_start = t_stop;
   1436 #endif
   1437    for (pass = 0; pass < num_passes; pass++)
   1438    {
   1439 #     ifdef calc_pass_height
   1440          png_uint_32 pass_height;
   1441 
   1442          if (num_passes == 7) /* interlaced */
   1443          {
   1444             if (PNG_PASS_COLS(width, pass) > 0)
   1445                pass_height = PNG_PASS_ROWS(height, pass);
   1446 
   1447             else
   1448                pass_height = 0;
   1449          }
   1450 
   1451          else /* not interlaced */
   1452             pass_height = height;
   1453 #     else
   1454 #        define pass_height height
   1455 #     endif
   1456 
   1457       pngtest_debug1("Writing row data for pass %d", pass);
   1458       for (y = 0; y < pass_height; y++)
   1459       {
   1460 #ifndef SINGLE_ROWBUF_ALLOC
   1461          pngtest_debug2("Allocating row buffer (pass %d, y = %u)...", pass, y);
   1462 
   1463          row_buf = (png_bytep)png_malloc(read_ptr,
   1464              png_get_rowbytes(read_ptr, read_info_ptr));
   1465 
   1466          pngtest_debug2("\t0x%08lx (%lu bytes)", (unsigned long)row_buf,
   1467              (unsigned long)png_get_rowbytes(read_ptr, read_info_ptr));
   1468 
   1469 #endif /* !SINGLE_ROWBUF_ALLOC */
   1470          png_read_rows(read_ptr, (png_bytepp)&row_buf, NULL, 1);
   1471 
   1472 #ifdef PNG_WRITE_SUPPORTED
   1473 #ifdef PNGTEST_TIMING
   1474          t_stop = (float)clock();
   1475          t_decode += (t_stop - t_start);
   1476          t_start = t_stop;
   1477 #endif
   1478          png_write_rows(write_ptr, (png_bytepp)&row_buf, 1);
   1479 #ifdef PNGTEST_TIMING
   1480          t_stop = (float)clock();
   1481          t_encode += (t_stop - t_start);
   1482          t_start = t_stop;
   1483 #endif
   1484 #endif /* WRITE */
   1485 
   1486 #ifndef SINGLE_ROWBUF_ALLOC
   1487          pngtest_debug2("Freeing row buffer (pass %d, y = %u)", pass, y);
   1488          png_free(read_ptr, row_buf);
   1489          row_buf = NULL;
   1490 #endif /* !SINGLE_ROWBUF_ALLOC */
   1491       }
   1492    }
   1493 
   1494 #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
   1495 #  ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
   1496       png_free_data(read_ptr, read_info_ptr, PNG_FREE_UNKN, -1);
   1497 #  endif
   1498 #  ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
   1499       png_free_data(write_ptr, write_info_ptr, PNG_FREE_UNKN, -1);
   1500 #  endif
   1501 #endif
   1502 
   1503    pngtest_debug("Reading and writing end_info data");
   1504 
   1505    png_read_end(read_ptr, end_info_ptr);
   1506 #ifdef PNG_TEXT_SUPPORTED
   1507    {
   1508       png_textp text_ptr;
   1509       int num_text;
   1510 
   1511       if (png_get_text(read_ptr, end_info_ptr, &text_ptr, &num_text) > 0)
   1512       {
   1513          pngtest_debug1("Handling %d iTXt/tEXt/zTXt chunks", num_text);
   1514 
   1515          pngtest_check_text_support(read_ptr, text_ptr, num_text);
   1516 
   1517          if (verbose != 0)
   1518          {
   1519             int i;
   1520 
   1521             printf("\n");
   1522             for (i=0; i<num_text; i++)
   1523             {
   1524                printf("   Text compression[%d]=%d\n",
   1525                    i, text_ptr[i].compression);
   1526             }
   1527          }
   1528 
   1529          png_set_text(write_ptr, write_end_info_ptr, text_ptr, num_text);
   1530       }
   1531    }
   1532 #endif
   1533 #ifdef PNG_tIME_SUPPORTED
   1534    {
   1535       png_timep mod_time;
   1536 
   1537       if (png_get_tIME(read_ptr, end_info_ptr, &mod_time) != 0)
   1538       {
   1539          png_set_tIME(write_ptr, write_end_info_ptr, mod_time);
   1540 #ifdef PNG_TIME_RFC1123_SUPPORTED
   1541          if (png_convert_to_rfc1123_buffer(tIME_string, mod_time) != 0)
   1542             tIME_string[(sizeof tIME_string) - 1] = '\0';
   1543 
   1544          else
   1545          {
   1546             strncpy(tIME_string, "*** invalid time ***", sizeof tIME_string);
   1547             tIME_string[(sizeof tIME_string)-1] = '\0';
   1548          }
   1549 
   1550          tIME_chunk_present++;
   1551 #endif /* TIME_RFC1123 */
   1552       }
   1553    }
   1554 #endif
   1555 #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
   1556    {
   1557       png_unknown_chunkp unknowns;
   1558       int num_unknowns = png_get_unknown_chunks(read_ptr, end_info_ptr,
   1559           &unknowns);
   1560 
   1561       if (num_unknowns != 0)
   1562       {
   1563          png_set_unknown_chunks(write_ptr, write_end_info_ptr, unknowns,
   1564              num_unknowns);
   1565 #if PNG_LIBPNG_VER < 10600
   1566          /* Copy the locations from the read_info_ptr.  The automatically
   1567           * generated locations in write_end_info_ptr are wrong prior to 1.6.0
   1568           * because they are reset from the write pointer (removed in 1.6.0).
   1569           */
   1570          {
   1571             int i;
   1572             for (i = 0; i < num_unknowns; i++)
   1573               png_set_unknown_chunk_location(write_ptr, write_end_info_ptr, i,
   1574                   unknowns[i].location);
   1575          }
   1576 #endif
   1577       }
   1578    }
   1579 #endif
   1580 
   1581 #ifdef PNG_WRITE_SUPPORTED
   1582 #ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
   1583    /* Normally one would use Z_DEFAULT_STRATEGY for text compression.
   1584     * This is here just to make pngtest replicate the results from libpng
   1585     * versions prior to 1.5.4, and to test this new API.
   1586     */
   1587    png_set_text_compression_strategy(write_ptr, Z_FILTERED);
   1588 #endif
   1589 
   1590    /* When the unknown vpAg/sTER chunks are written by pngtest the only way to
   1591     * do it is to write them *before* calling png_write_end.  When unknown
   1592     * chunks are written by libpng, however, they are written just before IEND.
   1593     * There seems to be no way round this, however vpAg/sTER are not expected
   1594     * after IDAT.
   1595     */
   1596    write_chunks(write_ptr, after_IDAT);
   1597 
   1598    png_write_end(write_ptr, write_end_info_ptr);
   1599 #endif
   1600 
   1601 #ifdef PNG_EASY_ACCESS_SUPPORTED
   1602    if (verbose != 0)
   1603    {
   1604       png_uint_32 iwidth, iheight;
   1605       iwidth = png_get_image_width(write_ptr, write_info_ptr);
   1606       iheight = png_get_image_height(write_ptr, write_info_ptr);
   1607       fprintf(STDERR, "\n Image width = %lu, height = %lu\n",
   1608           (unsigned long)iwidth, (unsigned long)iheight);
   1609    }
   1610 #endif
   1611 
   1612    pngtest_debug("Destroying data structs");
   1613 #ifdef SINGLE_ROWBUF_ALLOC
   1614    pngtest_debug("destroying row_buf for read_ptr");
   1615    png_free(read_ptr, row_buf);
   1616    row_buf = NULL;
   1617 #endif /* SINGLE_ROWBUF_ALLOC */
   1618    pngtest_debug("destroying read_ptr, read_info_ptr, end_info_ptr");
   1619    png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
   1620 #ifdef PNG_WRITE_SUPPORTED
   1621    pngtest_debug("destroying write_end_info_ptr");
   1622    png_destroy_info_struct(write_ptr, &write_end_info_ptr);
   1623    pngtest_debug("destroying write_ptr, write_info_ptr");
   1624    png_destroy_write_struct(&write_ptr, &write_info_ptr);
   1625 #endif
   1626    pngtest_debug("Destruction complete.");
   1627 
   1628    FCLOSE(fpin);
   1629    FCLOSE(fpout);
   1630 
   1631    /* Summarize any warnings or errors and in 'strict' mode fail the test.
   1632     * Unsupported chunks can result in warnings, in that case ignore the strict
   1633     * setting, otherwise fail the test on warnings as well as errors.
   1634     */
   1635    if (error_count > 0)
   1636    {
   1637       /* We don't really expect to get here because of the setjmp handling
   1638        * above, but this is safe.
   1639        */
   1640       fprintf(STDERR, "\n  %s: %d libpng errors found (%d warnings)",
   1641           inname, error_count, warning_count);
   1642 
   1643       if (strict != 0)
   1644          return (1);
   1645    }
   1646 
   1647 #  ifdef PNG_WRITE_SUPPORTED
   1648       /* If there is no write support nothing was written! */
   1649       else if (unsupported_chunks > 0)
   1650       {
   1651          fprintf(STDERR, "\n  %s: unsupported chunks (%d)%s",
   1652              inname, unsupported_chunks, strict ? ": IGNORED --strict!" : "");
   1653       }
   1654 #  endif
   1655 
   1656    else if (warning_count > 0)
   1657    {
   1658       fprintf(STDERR, "\n  %s: %d libpng warnings found",
   1659           inname, warning_count);
   1660 
   1661       if (strict != 0)
   1662          return (1);
   1663    }
   1664 
   1665    pngtest_debug("Opening files for comparison");
   1666    if ((fpin = fopen(inname, "rb")) == NULL)
   1667    {
   1668       fprintf(STDERR, "Could not find file %s\n", inname);
   1669       return (1);
   1670    }
   1671 
   1672    if ((fpout = fopen(outname, "rb")) == NULL)
   1673    {
   1674       fprintf(STDERR, "Could not find file %s\n", outname);
   1675       FCLOSE(fpin);
   1676       return (1);
   1677    }
   1678 
   1679 #if defined (PNG_WRITE_SUPPORTED) /* else nothing was written */ &&\
   1680     defined (PNG_WRITE_FILTER_SUPPORTED)
   1681    if (interlace_preserved != 0) /* else the files will be changed */
   1682    {
   1683       for (;;)
   1684       {
   1685          static int wrote_question = 0;
   1686          png_size_t num_in, num_out;
   1687          char inbuf[256], outbuf[256];
   1688 
   1689          num_in = fread(inbuf, 1, sizeof inbuf, fpin);
   1690          num_out = fread(outbuf, 1, sizeof outbuf, fpout);
   1691 
   1692          if (num_in != num_out)
   1693          {
   1694             fprintf(STDERR, "\nFiles %s and %s are of a different size\n",
   1695                 inname, outname);
   1696 
   1697             if (wrote_question == 0 && unsupported_chunks == 0)
   1698             {
   1699                fprintf(STDERR,
   1700                    "   Was %s written with the same maximum IDAT"
   1701                    " chunk size (%d bytes),",
   1702                    inname, PNG_ZBUF_SIZE);
   1703                fprintf(STDERR,
   1704                    "\n   filtering heuristic (libpng default), compression");
   1705                fprintf(STDERR,
   1706                    " level (zlib default),\n   and zlib version (%s)?\n\n",
   1707                    ZLIB_VERSION);
   1708                wrote_question = 1;
   1709             }
   1710 
   1711             FCLOSE(fpin);
   1712             FCLOSE(fpout);
   1713 
   1714             if (strict != 0 && unsupported_chunks == 0)
   1715               return (1);
   1716 
   1717             else
   1718               return (0);
   1719          }
   1720 
   1721          if (num_in == 0)
   1722             break;
   1723 
   1724          if (memcmp(inbuf, outbuf, num_in))
   1725          {
   1726             fprintf(STDERR, "\nFiles %s and %s are different\n", inname,
   1727                 outname);
   1728 
   1729             if (wrote_question == 0 && unsupported_chunks == 0)
   1730             {
   1731                fprintf(STDERR,
   1732                    "   Was %s written with the same maximum"
   1733                    " IDAT chunk size (%d bytes),",
   1734                     inname, PNG_ZBUF_SIZE);
   1735                fprintf(STDERR,
   1736                    "\n   filtering heuristic (libpng default), compression");
   1737                fprintf(STDERR,
   1738                    " level (zlib default),\n   and zlib version (%s)?\n\n",
   1739                  ZLIB_VERSION);
   1740                wrote_question = 1;
   1741             }
   1742 
   1743             FCLOSE(fpin);
   1744             FCLOSE(fpout);
   1745 
   1746             /* NOTE: the unsupported_chunks escape is permitted here because
   1747              * unsupported text chunk compression will result in the compression
   1748              * mode being changed (to NONE) yet, in the test case, the result
   1749              * can be exactly the same size!
   1750              */
   1751             if (strict != 0 && unsupported_chunks == 0)
   1752               return (1);
   1753 
   1754             else
   1755               return (0);
   1756          }
   1757       }
   1758    }
   1759 #endif /* WRITE && WRITE_FILTER */
   1760 
   1761    FCLOSE(fpin);
   1762    FCLOSE(fpout);
   1763 
   1764    return (0);
   1765 }
   1766 
   1767 /* Input and output filenames */
   1768 #ifdef RISCOS
   1769 static PNG_CONST char *inname = "pngtest/png";
   1770 static PNG_CONST char *outname = "pngout/png";
   1771 #else
   1772 static PNG_CONST char *inname = "pngtest.png";
   1773 static PNG_CONST char *outname = "pngout.png";
   1774 #endif
   1775 
   1776 int
   1777 main(int argc, char *argv[])
   1778 {
   1779    int multiple = 0;
   1780    int ierror = 0;
   1781 
   1782    png_structp dummy_ptr;
   1783 
   1784    fprintf(STDERR, "\n Testing libpng version %s\n", PNG_LIBPNG_VER_STRING);
   1785    fprintf(STDERR, "   with zlib   version %s\n", ZLIB_VERSION);
   1786    fprintf(STDERR, "%s", png_get_copyright(NULL));
   1787    /* Show the version of libpng used in building the library */
   1788    fprintf(STDERR, " library (%lu):%s",
   1789        (unsigned long)png_access_version_number(),
   1790        png_get_header_version(NULL));
   1791 
   1792    /* Show the version of libpng used in building the application */
   1793    fprintf(STDERR, " pngtest (%lu):%s", (unsigned long)PNG_LIBPNG_VER,
   1794        PNG_HEADER_VERSION_STRING);
   1795 
   1796    /* Do some consistency checking on the memory allocation settings, I'm
   1797     * not sure this matters, but it is nice to know, the first of these
   1798     * tests should be impossible because of the way the macros are set
   1799     * in pngconf.h
   1800     */
   1801 #if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K)
   1802       fprintf(STDERR, " NOTE: Zlib compiled for max 64k, libpng not\n");
   1803 #endif
   1804    /* I think the following can happen. */
   1805 #if !defined(MAXSEG_64K) && defined(PNG_MAX_MALLOC_64K)
   1806       fprintf(STDERR, " NOTE: libpng compiled for max 64k, zlib not\n");
   1807 #endif
   1808 
   1809    if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING))
   1810    {
   1811       fprintf(STDERR,
   1812           "Warning: versions are different between png.h and png.c\n");
   1813       fprintf(STDERR, "  png.h version: %s\n", PNG_LIBPNG_VER_STRING);
   1814       fprintf(STDERR, "  png.c version: %s\n\n", png_libpng_ver);
   1815       ++ierror;
   1816    }
   1817 
   1818    if (argc > 1)
   1819    {
   1820       if (strcmp(argv[1], "-m") == 0)
   1821       {
   1822          multiple = 1;
   1823          status_dots_requested = 0;
   1824       }
   1825 
   1826       else if (strcmp(argv[1], "-mv") == 0 ||
   1827                strcmp(argv[1], "-vm") == 0 )
   1828       {
   1829          multiple = 1;
   1830          verbose = 1;
   1831          status_dots_requested = 1;
   1832       }
   1833 
   1834       else if (strcmp(argv[1], "-v") == 0)
   1835       {
   1836          verbose = 1;
   1837          status_dots_requested = 1;
   1838          inname = argv[2];
   1839       }
   1840 
   1841       else if (strcmp(argv[1], "--strict") == 0)
   1842       {
   1843          status_dots_requested = 0;
   1844          verbose = 1;
   1845          inname = argv[2];
   1846          strict++;
   1847          relaxed = 0;
   1848       }
   1849 
   1850       else if (strcmp(argv[1], "--relaxed") == 0)
   1851       {
   1852          status_dots_requested = 0;
   1853          verbose = 1;
   1854          inname = argv[2];
   1855          strict = 0;
   1856          relaxed++;
   1857       }
   1858 
   1859       else
   1860       {
   1861          inname = argv[1];
   1862          status_dots_requested = 0;
   1863       }
   1864    }
   1865 
   1866    if (multiple == 0 && argc == 3 + verbose)
   1867       outname = argv[2 + verbose];
   1868 
   1869    if ((multiple == 0 && argc > 3 + verbose) ||
   1870        (multiple != 0 && argc < 2))
   1871    {
   1872       fprintf(STDERR,
   1873           "usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n",
   1874           argv[0], argv[0]);
   1875       fprintf(STDERR,
   1876           "  reads/writes one PNG file (without -m) or multiple files (-m)\n");
   1877       fprintf(STDERR,
   1878           "  with -m %s is used as a temporary file\n", outname);
   1879       exit(1);
   1880    }
   1881 
   1882    if (multiple != 0)
   1883    {
   1884       int i;
   1885 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
   1886       png_alloc_size_t allocation_now = current_allocation;
   1887 #endif
   1888       for (i=2; i<argc; ++i)
   1889       {
   1890          int kerror;
   1891          fprintf(STDERR, "\n Testing %s:", argv[i]);
   1892 #if PNG_DEBUG > 0
   1893          fprintf(STDERR, "\n");
   1894 #endif
   1895          kerror = test_one_file(argv[i], outname);
   1896          if (kerror == 0)
   1897          {
   1898 #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
   1899             fprintf(STDERR, "\n PASS (%lu zero samples)\n",
   1900                 (unsigned long)zero_samples);
   1901 #else
   1902             fprintf(STDERR, " PASS\n");
   1903 #endif
   1904 #ifdef PNG_TIME_RFC1123_SUPPORTED
   1905             if (tIME_chunk_present != 0)
   1906                fprintf(STDERR, " tIME = %s\n", tIME_string);
   1907 
   1908             tIME_chunk_present = 0;
   1909 #endif /* TIME_RFC1123 */
   1910          }
   1911 
   1912          else
   1913          {
   1914             fprintf(STDERR, " FAIL\n");
   1915             ierror += kerror;
   1916          }
   1917 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
   1918          if (allocation_now != current_allocation)
   1919             fprintf(STDERR, "MEMORY ERROR: %lu bytes lost\n",
   1920                 (unsigned long)(current_allocation - allocation_now));
   1921 
   1922          if (current_allocation != 0)
   1923          {
   1924             memory_infop pinfo = pinformation;
   1925 
   1926             fprintf(STDERR, "MEMORY ERROR: %lu bytes still allocated\n",
   1927                 (unsigned long)current_allocation);
   1928 
   1929             while (pinfo != NULL)
   1930             {
   1931                fprintf(STDERR, " %lu bytes at %p\n",
   1932                    (unsigned long)pinfo->size,
   1933                    pinfo->pointer);
   1934                pinfo = pinfo->next;
   1935             }
   1936          }
   1937 #endif
   1938       }
   1939 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
   1940          fprintf(STDERR, " Current memory allocation: %20lu bytes\n",
   1941              (unsigned long)current_allocation);
   1942          fprintf(STDERR, " Maximum memory allocation: %20lu bytes\n",
   1943              (unsigned long) maximum_allocation);
   1944          fprintf(STDERR, " Total   memory allocation: %20lu bytes\n",
   1945              (unsigned long)total_allocation);
   1946          fprintf(STDERR, "     Number of allocations: %20lu\n",
   1947              (unsigned long)num_allocations);
   1948 #endif
   1949    }
   1950 
   1951    else
   1952    {
   1953       int i;
   1954       for (i = 0; i<3; ++i)
   1955       {
   1956          int kerror;
   1957 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
   1958          png_alloc_size_t allocation_now = current_allocation;
   1959 #endif
   1960          if (i == 1)
   1961             status_dots_requested = 1;
   1962 
   1963          else if (verbose == 0)
   1964             status_dots_requested = 0;
   1965 
   1966          if (i == 0 || verbose == 1 || ierror != 0)
   1967          {
   1968             fprintf(STDERR, "\n Testing %s:", inname);
   1969 #if PNG_DEBUG > 0
   1970             fprintf(STDERR, "\n");
   1971 #endif
   1972          }
   1973 
   1974          kerror = test_one_file(inname, outname);
   1975 
   1976          if (kerror == 0)
   1977          {
   1978             if (verbose == 1 || i == 2)
   1979             {
   1980 #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
   1981                 fprintf(STDERR, "\n PASS (%lu zero samples)\n",
   1982                     (unsigned long)zero_samples);
   1983 #else
   1984                 fprintf(STDERR, " PASS\n");
   1985 #endif
   1986 #ifdef PNG_TIME_RFC1123_SUPPORTED
   1987              if (tIME_chunk_present != 0)
   1988                 fprintf(STDERR, " tIME = %s\n", tIME_string);
   1989 #endif /* TIME_RFC1123 */
   1990             }
   1991          }
   1992 
   1993          else
   1994          {
   1995             if (verbose == 0 && i != 2)
   1996             {
   1997                fprintf(STDERR, "\n Testing %s:", inname);
   1998 #if PNG_DEBUG > 0
   1999                fprintf(STDERR, "\n");
   2000 #endif
   2001             }
   2002 
   2003             fprintf(STDERR, " FAIL\n");
   2004             ierror += kerror;
   2005          }
   2006 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
   2007          if (allocation_now != current_allocation)
   2008              fprintf(STDERR, "MEMORY ERROR: %lu bytes lost\n",
   2009                  (unsigned long)(current_allocation - allocation_now));
   2010 
   2011          if (current_allocation != 0)
   2012          {
   2013              memory_infop pinfo = pinformation;
   2014 
   2015              fprintf(STDERR, "MEMORY ERROR: %lu bytes still allocated\n",
   2016                  (unsigned long)current_allocation);
   2017 
   2018              while (pinfo != NULL)
   2019              {
   2020                 fprintf(STDERR, " %lu bytes at %p\n",
   2021                     (unsigned long)pinfo->size, pinfo->pointer);
   2022                 pinfo = pinfo->next;
   2023              }
   2024           }
   2025 #endif
   2026        }
   2027 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
   2028        fprintf(STDERR, " Current memory allocation: %20lu bytes\n",
   2029            (unsigned long)current_allocation);
   2030        fprintf(STDERR, " Maximum memory allocation: %20lu bytes\n",
   2031            (unsigned long)maximum_allocation);
   2032        fprintf(STDERR, " Total   memory allocation: %20lu bytes\n",
   2033            (unsigned long)total_allocation);
   2034        fprintf(STDERR, "     Number of allocations: %20lu\n",
   2035            (unsigned long)num_allocations);
   2036 #endif
   2037    }
   2038 
   2039 #ifdef PNGTEST_TIMING
   2040    t_stop = (float)clock();
   2041    t_misc += (t_stop - t_start);
   2042    t_start = t_stop;
   2043    fprintf(STDERR, " CPU time used = %.3f seconds",
   2044        (t_misc+t_decode+t_encode)/(float)CLOCKS_PER_SEC);
   2045    fprintf(STDERR, " (decoding %.3f,\n",
   2046        t_decode/(float)CLOCKS_PER_SEC);
   2047    fprintf(STDERR, "        encoding %.3f ,",
   2048        t_encode/(float)CLOCKS_PER_SEC);
   2049    fprintf(STDERR, " other %.3f seconds)\n\n",
   2050        t_misc/(float)CLOCKS_PER_SEC);
   2051 #endif
   2052 
   2053    if (ierror == 0)
   2054       fprintf(STDERR, " libpng passes test\n");
   2055 
   2056    else
   2057       fprintf(STDERR, " libpng FAILS test\n");
   2058 
   2059    dummy_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
   2060    fprintf(STDERR, " Default limits:\n");
   2061    fprintf(STDERR, "  width_max  = %lu\n",
   2062        (unsigned long) png_get_user_width_max(dummy_ptr));
   2063    fprintf(STDERR, "  height_max = %lu\n",
   2064        (unsigned long) png_get_user_height_max(dummy_ptr));
   2065    if (png_get_chunk_cache_max(dummy_ptr) == 0)
   2066       fprintf(STDERR, "  cache_max  = unlimited\n");
   2067    else
   2068       fprintf(STDERR, "  cache_max  = %lu\n",
   2069           (unsigned long) png_get_chunk_cache_max(dummy_ptr));
   2070    if (png_get_chunk_malloc_max(dummy_ptr) == 0)
   2071       fprintf(STDERR, "  malloc_max = unlimited\n");
   2072    else
   2073       fprintf(STDERR, "  malloc_max = %lu\n",
   2074           (unsigned long) png_get_chunk_malloc_max(dummy_ptr));
   2075    png_destroy_read_struct(&dummy_ptr, NULL, NULL);
   2076 
   2077    return (int)(ierror != 0);
   2078 }
   2079 #else
   2080 int
   2081 main(void)
   2082 {
   2083    fprintf(STDERR,
   2084        " test ignored because libpng was not built with read support\n");
   2085    /* And skip this test */
   2086    return SKIP;
   2087 }
   2088 #endif
   2089 
   2090 /* Generate a compiler error if there is an old png.h in the search path. */
   2091 typedef png_libpng_version_1_6_25 Your_png_h_is_not_version_1_6_25;
   2092