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