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