Back to index

tetex-bin  3.0
pngtest.c
Go to the documentation of this file.
00001 
00002 /* pngtest.c - a simple test program to test libpng
00003  *
00004  * libpng 1.2.8 - December 3, 2004
00005  * For conditions of distribution and use, see copyright notice in png.h
00006  * Copyright (c) 1998-2004 Glenn Randers-Pehrson
00007  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
00008  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
00009  *
00010  * This program reads in a PNG image, writes it out again, and then
00011  * compares the two files.  If the files are identical, this shows that
00012  * the basic chunk handling, filtering, and (de)compression code is working
00013  * properly.  It does not currently test all of the transforms, although
00014  * it probably should.
00015  *
00016  * The program will report "FAIL" in certain legitimate cases:
00017  * 1) when the compression level or filter selection method is changed.
00018  * 2) when the maximum IDAT size (PNG_ZBUF_SIZE in pngconf.h) is not 8192.
00019  * 3) unknown unsafe-to-copy ancillary chunks or unknown critical chunks
00020  *    exist in the input file.
00021  * 4) others not listed here...
00022  * In these cases, it is best to check with another tool such as "pngcheck"
00023  * to see what the differences between the two files are.
00024  *
00025  * If a filename is given on the command-line, then this file is used
00026  * for the input, rather than the default "pngtest.png".  This allows
00027  * testing a wide variety of files easily.  You can also test a number
00028  * of files at once by typing "pngtest -m file1.png file2.png ..."
00029  */
00030 
00031 #include "png.h"
00032 
00033 #if defined(_WIN32_WCE)
00034 #  if _WIN32_WCE < 211
00035      __error__ (f|w)printf functions are not supported on old WindowsCE.;
00036 #  endif
00037 #  include <windows.h>
00038 #  include <stdlib.h>
00039 #  define READFILE(file, data, length, check) \
00040      if (ReadFile(file, data, length, &check,NULL)) check = 0
00041 #  define WRITEFILE(file, data, length, check)) \
00042      if (WriteFile(file, data, length, &check, NULL)) check = 0
00043 #  define FCLOSE(file) CloseHandle(file)
00044 #else
00045 #  include <stdio.h>
00046 #  include <stdlib.h>
00047 #  include <assert.h>
00048 #  define READFILE(file, data, length, check) \
00049      check=(png_size_t)fread(data,(png_size_t)1,length,file)
00050 #  define WRITEFILE(file, data, length, check) \
00051      check=(png_size_t)fwrite(data,(png_size_t)1, length, file)
00052 #  define FCLOSE(file) fclose(file)
00053 #endif
00054 
00055 #if defined(PNG_NO_STDIO)
00056 #  if defined(_WIN32_WCE)
00057      typedef HANDLE                png_FILE_p;
00058 #  else
00059      typedef FILE                * png_FILE_p;
00060 #  endif
00061 #endif
00062 
00063 /* Makes pngtest verbose so we can find problems (needs to be before png.h) */
00064 #ifndef PNG_DEBUG
00065 #  define PNG_DEBUG 0
00066 #endif
00067 
00068 #if !PNG_DEBUG
00069 #  define SINGLE_ROWBUF_ALLOC  /* makes buffer overruns easier to nail */
00070 #endif
00071 
00072 /* Turn on CPU timing
00073 #define PNGTEST_TIMING
00074 */
00075 
00076 #ifdef PNG_NO_FLOATING_POINT_SUPPORTED
00077 #undef PNGTEST_TIMING
00078 #endif
00079 
00080 #ifdef PNGTEST_TIMING
00081 static float t_start, t_stop, t_decode, t_encode, t_misc;
00082 #include <time.h>
00083 #endif
00084 
00085 /* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */
00086 #ifndef png_jmpbuf
00087 #  define png_jmpbuf(png_ptr) png_ptr->jmpbuf
00088 #endif
00089 
00090 #ifdef PNGTEST_TIMING
00091 static float t_start, t_stop, t_decode, t_encode, t_misc;
00092 #if !defined(PNG_tIME_SUPPORTED)
00093 #include <time.h>
00094 #endif
00095 #endif
00096 
00097 #if defined(PNG_TIME_RFC1123_SUPPORTED)
00098 static int tIME_chunk_present=0;
00099 static char tIME_string[30] = "no tIME chunk present in file";
00100 #endif
00101 
00102 static int verbose = 0;
00103 
00104 int test_one_file PNGARG((PNG_CONST char *inname, PNG_CONST char *outname));
00105 
00106 #ifdef __TURBOC__
00107 #include <mem.h>
00108 #endif
00109 
00110 /* defined so I can write to a file on gui/windowing platforms */
00111 /*  #define STDERR stderr  */
00112 #define STDERR stdout   /* for DOS */
00113 
00114 /* example of using row callbacks to make a simple progress meter */
00115 static int status_pass=1;
00116 static int status_dots_requested=0;
00117 static int status_dots=1;
00118 
00119 void
00120 #ifdef PNG_1_0_X
00121 PNGAPI
00122 #endif
00123 read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass);
00124 void
00125 #ifdef PNG_1_0_X
00126 PNGAPI
00127 #endif
00128 read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass)
00129 {
00130     if(png_ptr == NULL || row_number > PNG_UINT_31_MAX) return;
00131     if(status_pass != pass)
00132     {
00133        fprintf(stdout,"\n Pass %d: ",pass);
00134        status_pass = pass;
00135        status_dots = 31;
00136     }
00137     status_dots--;
00138     if(status_dots == 0)
00139     {
00140        fprintf(stdout, "\n         ");
00141        status_dots=30;
00142     }
00143     fprintf(stdout, "r");
00144 }
00145 
00146 void
00147 #ifdef PNG_1_0_X
00148 PNGAPI
00149 #endif
00150 write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass);
00151 void
00152 #ifdef PNG_1_0_X
00153 PNGAPI
00154 #endif
00155 write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass)
00156 {
00157     if(png_ptr == NULL || row_number > PNG_UINT_31_MAX || pass > 7) return;
00158     fprintf(stdout, "w");
00159 }
00160 
00161 
00162 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
00163 /* Example of using user transform callback (we don't transform anything,
00164    but merely examine the row filters.  We set this to 256 rather than
00165    5 in case illegal filter values are present.) */
00166 static png_uint_32 filters_used[256];
00167 void
00168 #ifdef PNG_1_0_X
00169 PNGAPI
00170 #endif
00171 count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data);
00172 void
00173 #ifdef PNG_1_0_X
00174 PNGAPI
00175 #endif
00176 count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data)
00177 {
00178     if(png_ptr != NULL && row_info != NULL)
00179       ++filters_used[*(data-1)];
00180 }
00181 #endif
00182 
00183 #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
00184 /* example of using user transform callback (we don't transform anything,
00185    but merely count the zero samples) */
00186 
00187 static png_uint_32 zero_samples;
00188 
00189 void
00190 #ifdef PNG_1_0_X
00191 PNGAPI
00192 #endif
00193 count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data);
00194 void
00195 #ifdef PNG_1_0_X
00196 PNGAPI
00197 #endif
00198 count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data)
00199 {
00200    png_bytep dp = data;
00201    if(png_ptr == NULL)return;
00202 
00203    /* contents of row_info:
00204     *  png_uint_32 width      width of row
00205     *  png_uint_32 rowbytes   number of bytes in row
00206     *  png_byte color_type    color type of pixels
00207     *  png_byte bit_depth     bit depth of samples
00208     *  png_byte channels      number of channels (1-4)
00209     *  png_byte pixel_depth   bits per pixel (depth*channels)
00210     */
00211 
00212 
00213     /* counts the number of zero samples (or zero pixels if color_type is 3 */
00214 
00215     if(row_info->color_type == 0 || row_info->color_type == 3)
00216     {
00217        int pos=0;
00218        png_uint_32 n, nstop;
00219        for (n=0, nstop=row_info->width; n<nstop; n++)
00220        {
00221           if(row_info->bit_depth == 1)
00222           {
00223              if(((*dp << pos++ ) & 0x80) == 0) zero_samples++;
00224              if(pos == 8)
00225              {
00226                 pos = 0;
00227                 dp++;
00228              }
00229           }
00230           if(row_info->bit_depth == 2)
00231           {
00232              if(((*dp << (pos+=2)) & 0xc0) == 0) zero_samples++;
00233              if(pos == 8)
00234              {
00235                 pos = 0;
00236                 dp++;
00237              }
00238           }
00239           if(row_info->bit_depth == 4)
00240           {
00241              if(((*dp << (pos+=4)) & 0xf0) == 0) zero_samples++;
00242              if(pos == 8)
00243              {
00244                 pos = 0;
00245                 dp++;
00246              }
00247           }
00248           if(row_info->bit_depth == 8)
00249              if(*dp++ == 0) zero_samples++;
00250           if(row_info->bit_depth == 16)
00251           {
00252              if((*dp | *(dp+1)) == 0) zero_samples++;
00253              dp+=2;
00254           }
00255        }
00256     }
00257     else /* other color types */
00258     {
00259        png_uint_32 n, nstop;
00260        int channel;
00261        int color_channels = row_info->channels;
00262        if(row_info->color_type > 3)color_channels--;
00263 
00264        for (n=0, nstop=row_info->width; n<nstop; n++)
00265        {
00266           for (channel = 0; channel < color_channels; channel++)
00267           {
00268              if(row_info->bit_depth == 8)
00269                 if(*dp++ == 0) zero_samples++;
00270              if(row_info->bit_depth == 16)
00271              {
00272                 if((*dp | *(dp+1)) == 0) zero_samples++;
00273                 dp+=2;
00274              }
00275           }
00276           if(row_info->color_type > 3)
00277           {
00278              dp++;
00279              if(row_info->bit_depth == 16)dp++;
00280           }
00281        }
00282     }
00283 }
00284 #endif /* PNG_WRITE_USER_TRANSFORM_SUPPORTED */
00285 
00286 static int wrote_question = 0;
00287 
00288 #if defined(PNG_NO_STDIO)
00289 /* START of code to validate stdio-free compilation */
00290 /* These copies of the default read/write functions come from pngrio.c and */
00291 /* pngwio.c.  They allow "don't include stdio" testing of the library. */
00292 /* This is the function that does the actual reading of data.  If you are
00293    not reading from a standard C stream, you should create a replacement
00294    read_data function and use it at run time with png_set_read_fn(), rather
00295    than changing the library. */
00296 
00297 #ifndef USE_FAR_KEYWORD
00298 static void
00299 pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
00300 {
00301    png_size_t check;
00302 
00303    /* fread() returns 0 on error, so it is OK to store this in a png_size_t
00304     * instead of an int, which is what fread() actually returns.
00305     */
00306    READFILE((png_FILE_p)png_ptr->io_ptr, data, length, check);
00307 
00308    if (check != length)
00309    {
00310       png_error(png_ptr, "Read Error!");
00311    }
00312 }
00313 #else
00314 /* this is the model-independent version. Since the standard I/O library
00315    can't handle far buffers in the medium and small models, we have to copy
00316    the data.
00317 */
00318 
00319 #define NEAR_BUF_SIZE 1024
00320 #define MIN(a,b) (a <= b ? a : b)
00321 
00322 static void
00323 pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
00324 {
00325    int check;
00326    png_byte *n_data;
00327    png_FILE_p io_ptr;
00328 
00329    /* Check if data really is near. If so, use usual code. */
00330    n_data = (png_byte *)CVT_PTR_NOCHECK(data);
00331    io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
00332    if ((png_bytep)n_data == data)
00333    {
00334       READFILE(io_ptr, n_data, length, check);
00335    }
00336    else
00337    {
00338       png_byte buf[NEAR_BUF_SIZE];
00339       png_size_t read, remaining, err;
00340       check = 0;
00341       remaining = length;
00342       do
00343       {
00344          read = MIN(NEAR_BUF_SIZE, remaining);
00345          READFILE(io_ptr, buf, 1, err);
00346          png_memcpy(data, buf, read); /* copy far buffer to near buffer */
00347          if(err != read)
00348             break;
00349          else
00350             check += err;
00351          data += read;
00352          remaining -= read;
00353       }
00354       while (remaining != 0);
00355    }
00356    if (check != length)
00357    {
00358       png_error(png_ptr, "read Error");
00359    }
00360 }
00361 #endif /* USE_FAR_KEYWORD */
00362 
00363 #if defined(PNG_WRITE_FLUSH_SUPPORTED)
00364 static void
00365 pngtest_flush(png_structp png_ptr)
00366 {
00367 #if !defined(_WIN32_WCE)
00368    png_FILE_p io_ptr;
00369    io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr));
00370    if (io_ptr != NULL)
00371       fflush(io_ptr);
00372 #endif
00373 }
00374 #endif
00375 
00376 /* This is the function that does the actual writing of data.  If you are
00377    not writing to a standard C stream, you should create a replacement
00378    write_data function and use it at run time with png_set_write_fn(), rather
00379    than changing the library. */
00380 #ifndef USE_FAR_KEYWORD
00381 static void
00382 pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
00383 {
00384    png_uint_32 check;
00385 
00386    WRITEFILE((png_FILE_p)png_ptr->io_ptr,  data, length, check);
00387    if (check != length)
00388    {
00389       png_error(png_ptr, "Write Error");
00390    }
00391 }
00392 #else
00393 /* this is the model-independent version. Since the standard I/O library
00394    can't handle far buffers in the medium and small models, we have to copy
00395    the data.
00396 */
00397 
00398 #define NEAR_BUF_SIZE 1024
00399 #define MIN(a,b) (a <= b ? a : b)
00400 
00401 static void
00402 pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
00403 {
00404    png_uint_32 check;
00405    png_byte *near_data;  /* Needs to be "png_byte *" instead of "png_bytep" */
00406    png_FILE_p io_ptr;
00407 
00408    /* Check if data really is near. If so, use usual code. */
00409    near_data = (png_byte *)CVT_PTR_NOCHECK(data);
00410    io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
00411    if ((png_bytep)near_data == data)
00412    {
00413       WRITEFILE(io_ptr, near_data, length, check);
00414    }
00415    else
00416    {
00417       png_byte buf[NEAR_BUF_SIZE];
00418       png_size_t written, remaining, err;
00419       check = 0;
00420       remaining = length;
00421       do
00422       {
00423          written = MIN(NEAR_BUF_SIZE, remaining);
00424          png_memcpy(buf, data, written); /* copy far buffer to near buffer */
00425          WRITEFILE(io_ptr, buf, written, err);
00426          if (err != written)
00427             break;
00428          else
00429             check += err;
00430          data += written;
00431          remaining -= written;
00432       }
00433       while (remaining != 0);
00434    }
00435    if (check != length)
00436    {
00437       png_error(png_ptr, "Write Error");
00438    }
00439 }
00440 
00441 #endif /* USE_FAR_KEYWORD */
00442 
00443 /* This function is called when there is a warning, but the library thinks
00444  * it can continue anyway.  Replacement functions don't have to do anything
00445  * here if you don't want to.  In the default configuration, png_ptr is
00446  * not used, but it is passed in case it may be useful.
00447  */
00448 static void
00449 pngtest_warning(png_structp png_ptr, png_const_charp message)
00450 {
00451    PNG_CONST char *name = "UNKNOWN (ERROR!)";
00452    if (png_ptr != NULL && png_ptr->error_ptr != NULL)
00453       name = png_ptr->error_ptr;
00454    fprintf(STDERR, "%s: libpng warning: %s\n", name, message);
00455 }
00456 
00457 /* This is the default error handling function.  Note that replacements for
00458  * this function MUST NOT RETURN, or the program will likely crash.  This
00459  * function is used by default, or if the program supplies NULL for the
00460  * error function pointer in png_set_error_fn().
00461  */
00462 static void
00463 pngtest_error(png_structp png_ptr, png_const_charp message)
00464 {
00465    pngtest_warning(png_ptr, message);
00466    /* We can return because png_error calls the default handler, which is
00467     * actually OK in this case. */
00468 }
00469 #endif /* PNG_NO_STDIO */
00470 /* END of code to validate stdio-free compilation */
00471 
00472 /* START of code to validate memory allocation and deallocation */
00473 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
00474 
00475 /* Allocate memory.  For reasonable files, size should never exceed
00476    64K.  However, zlib may allocate more then 64K if you don't tell
00477    it not to.  See zconf.h and png.h for more information.  zlib does
00478    need to allocate exactly 64K, so whatever you call here must
00479    have the ability to do that.
00480 
00481    This piece of code can be compiled to validate max 64K allocations
00482    by setting MAXSEG_64K in zlib zconf.h *or* PNG_MAX_MALLOC_64K. */
00483 typedef struct memory_information
00484 {
00485    png_uint_32               size;
00486    png_voidp                 pointer;
00487    struct memory_information FAR *next;
00488 } memory_information;
00489 typedef memory_information FAR *memory_infop;
00490 
00491 static memory_infop pinformation = NULL;
00492 static int current_allocation = 0;
00493 static int maximum_allocation = 0;
00494 static int total_allocation = 0;
00495 static int num_allocations = 0;
00496 
00497 png_voidp png_debug_malloc PNGARG((png_structp png_ptr, png_uint_32 size));
00498 void png_debug_free PNGARG((png_structp png_ptr, png_voidp ptr));
00499 
00500 png_voidp
00501 png_debug_malloc(png_structp png_ptr, png_uint_32 size)
00502 {
00503 
00504    /* png_malloc has already tested for NULL; png_create_struct calls
00505       png_debug_malloc directly, with png_ptr == NULL which is OK */
00506 
00507    if (size == 0)
00508       return (NULL);
00509 
00510    /* This calls the library allocator twice, once to get the requested
00511       buffer and once to get a new free list entry. */
00512    {
00513       /* Disable malloc_fn and free_fn */
00514       memory_infop pinfo;
00515       png_set_mem_fn(png_ptr, NULL, NULL, NULL);
00516       pinfo = (memory_infop)png_malloc(png_ptr,
00517          (png_uint_32)png_sizeof (*pinfo));
00518       pinfo->size = size;
00519       current_allocation += size;
00520       total_allocation += size;
00521       num_allocations ++;
00522       if (current_allocation > maximum_allocation)
00523          maximum_allocation = current_allocation;
00524       pinfo->pointer = (png_voidp)png_malloc(png_ptr, size);
00525       /* Restore malloc_fn and free_fn */
00526       png_set_mem_fn(png_ptr, png_voidp_NULL, (png_malloc_ptr)png_debug_malloc,
00527          (png_free_ptr)png_debug_free);
00528       if (size != 0 && pinfo->pointer == NULL)
00529       {
00530          current_allocation -= size;
00531          total_allocation -= size;
00532          png_error(png_ptr,
00533            "out of memory in pngtest->png_debug_malloc.");
00534       }
00535       pinfo->next = pinformation;
00536       pinformation = pinfo;
00537       /* Make sure the caller isn't assuming zeroed memory. */
00538       png_memset(pinfo->pointer, 0xdd, pinfo->size);
00539       if(verbose)
00540          printf("png_malloc %lu bytes at %x\n",size,pinfo->pointer);
00541       assert(pinfo->size != 12345678);
00542       return (png_voidp)(pinfo->pointer);
00543    }
00544 }
00545 
00546 /* Free a pointer.  It is removed from the list at the same time. */
00547 void
00548 png_debug_free(png_structp png_ptr, png_voidp ptr)
00549 {
00550    if (png_ptr == NULL)
00551       fprintf(STDERR, "NULL pointer to png_debug_free.\n");
00552    if (ptr == 0)
00553    {
00554 #if 0 /* This happens all the time. */
00555       fprintf(STDERR, "WARNING: freeing NULL pointer\n");
00556 #endif
00557       return;
00558    }
00559 
00560    /* Unlink the element from the list. */
00561    {
00562       memory_infop FAR *ppinfo = &pinformation;
00563       for (;;)
00564       {
00565          memory_infop pinfo = *ppinfo;
00566          if (pinfo->pointer == ptr)
00567          {
00568             *ppinfo = pinfo->next;
00569             current_allocation -= pinfo->size;
00570             if (current_allocation < 0)
00571                fprintf(STDERR, "Duplicate free of memory\n");
00572             /* We must free the list element too, but first kill
00573                the memory that is to be freed. */
00574             png_memset(ptr, 0x55, pinfo->size);
00575             png_free_default(png_ptr, pinfo);
00576             pinfo=NULL;
00577             break;
00578          }
00579          if (pinfo->next == NULL)
00580          {
00581             fprintf(STDERR, "Pointer %x not found\n", (unsigned int)ptr);
00582             break;
00583          }
00584          ppinfo = &pinfo->next;
00585       }
00586    }
00587 
00588    /* Finally free the data. */
00589    if(verbose)
00590       printf("Freeing %x\n",ptr);
00591    png_free_default(png_ptr, ptr);
00592    ptr=NULL;
00593 }
00594 #endif /* PNG_USER_MEM_SUPPORTED && PNG_DEBUG */
00595 /* END of code to test memory allocation/deallocation */
00596 
00597 /* Test one file */
00598 int
00599 test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
00600 {
00601    static png_FILE_p fpin;
00602    static png_FILE_p fpout;  /* "static" prevents setjmp corruption */
00603    png_structp read_ptr;
00604    png_infop read_info_ptr, end_info_ptr;
00605 #ifdef PNG_WRITE_SUPPORTED
00606    png_structp write_ptr;
00607    png_infop write_info_ptr;
00608    png_infop write_end_info_ptr;
00609 #else
00610    png_structp write_ptr = NULL;
00611    png_infop write_info_ptr = NULL;
00612    png_infop write_end_info_ptr = NULL;
00613 #endif
00614    png_bytep row_buf;
00615    png_uint_32 y;
00616    png_uint_32 width, height;
00617    int num_pass, pass;
00618    int bit_depth, color_type;
00619 #ifdef PNG_SETJMP_SUPPORTED
00620 #ifdef USE_FAR_KEYWORD
00621    jmp_buf jmpbuf;
00622 #endif
00623 #endif
00624 
00625 #if defined(_WIN32_WCE)
00626    TCHAR path[MAX_PATH];
00627 #endif
00628    char inbuf[256], outbuf[256];
00629 
00630    row_buf = NULL;
00631 
00632 #if defined(_WIN32_WCE)
00633    MultiByteToWideChar(CP_ACP, 0, inname, -1, path, MAX_PATH);
00634    if ((fpin = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
00635 #else
00636    if ((fpin = fopen(inname, "rb")) == NULL)
00637 #endif
00638    {
00639       fprintf(STDERR, "Could not find input file %s\n", inname);
00640       return (1);
00641    }
00642 
00643 #if defined(_WIN32_WCE)
00644    MultiByteToWideChar(CP_ACP, 0, outname, -1, path, MAX_PATH);
00645    if ((fpout = CreateFile(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL)) == INVALID_HANDLE_VALUE)
00646 #else
00647    if ((fpout = fopen(outname, "wb")) == NULL)
00648 #endif
00649    {
00650       fprintf(STDERR, "Could not open output file %s\n", outname);
00651       FCLOSE(fpin);
00652       return (1);
00653    }
00654 
00655    png_debug(0, "Allocating read and write structures\n");
00656 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
00657    read_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, png_voidp_NULL,
00658       png_error_ptr_NULL, png_error_ptr_NULL, png_voidp_NULL,
00659       (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free);
00660 #else
00661    read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL,
00662       png_error_ptr_NULL, png_error_ptr_NULL);
00663 #endif
00664 #if defined(PNG_NO_STDIO)
00665    png_set_error_fn(read_ptr, (png_voidp)inname, pngtest_error,
00666        pngtest_warning);
00667 #endif
00668 #ifdef PNG_WRITE_SUPPORTED
00669 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
00670    write_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, png_voidp_NULL,
00671       png_error_ptr_NULL, png_error_ptr_NULL, png_voidp_NULL,
00672       (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free);
00673 #else
00674    write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL,
00675       png_error_ptr_NULL, png_error_ptr_NULL);
00676 #endif
00677 #if defined(PNG_NO_STDIO)
00678    png_set_error_fn(write_ptr, (png_voidp)inname, pngtest_error,
00679        pngtest_warning);
00680 #endif
00681 #endif
00682    png_debug(0, "Allocating read_info, write_info and end_info structures\n");
00683    read_info_ptr = png_create_info_struct(read_ptr);
00684    end_info_ptr = png_create_info_struct(read_ptr);
00685 #ifdef PNG_WRITE_SUPPORTED
00686    write_info_ptr = png_create_info_struct(write_ptr);
00687    write_end_info_ptr = png_create_info_struct(write_ptr);
00688 #endif
00689 
00690 #ifdef PNG_SETJMP_SUPPORTED
00691    png_debug(0, "Setting jmpbuf for read struct\n");
00692 #ifdef USE_FAR_KEYWORD
00693    if (setjmp(jmpbuf))
00694 #else
00695    if (setjmp(png_jmpbuf(read_ptr)))
00696 #endif
00697    {
00698       fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname);
00699       if (row_buf)
00700          png_free(read_ptr, row_buf);
00701       png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
00702 #ifdef PNG_WRITE_SUPPORTED
00703       png_destroy_info_struct(write_ptr, &write_end_info_ptr);
00704       png_destroy_write_struct(&write_ptr, &write_info_ptr);
00705 #endif
00706       FCLOSE(fpin);
00707       FCLOSE(fpout);
00708       return (1);
00709    }
00710 #ifdef USE_FAR_KEYWORD
00711    png_memcpy(png_jmpbuf(read_ptr),jmpbuf,png_sizeof(jmp_buf));
00712 #endif
00713 
00714 #ifdef PNG_WRITE_SUPPORTED
00715    png_debug(0, "Setting jmpbuf for write struct\n");
00716 #ifdef USE_FAR_KEYWORD
00717    if (setjmp(jmpbuf))
00718 #else
00719    if (setjmp(png_jmpbuf(write_ptr)))
00720 #endif
00721    {
00722       fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname);
00723       png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
00724       png_destroy_info_struct(write_ptr, &write_end_info_ptr);
00725 #ifdef PNG_WRITE_SUPPORTED
00726       png_destroy_write_struct(&write_ptr, &write_info_ptr);
00727 #endif
00728       FCLOSE(fpin);
00729       FCLOSE(fpout);
00730       return (1);
00731    }
00732 #ifdef USE_FAR_KEYWORD
00733    png_memcpy(png_jmpbuf(write_ptr),jmpbuf,png_sizeof(jmp_buf));
00734 #endif
00735 #endif
00736 #endif
00737 
00738    png_debug(0, "Initializing input and output streams\n");
00739 #if !defined(PNG_NO_STDIO)
00740    png_init_io(read_ptr, fpin);
00741 #  ifdef PNG_WRITE_SUPPORTED
00742    png_init_io(write_ptr, fpout);
00743 #  endif
00744 #else
00745    png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data);
00746 #  ifdef PNG_WRITE_SUPPORTED
00747    png_set_write_fn(write_ptr, (png_voidp)fpout,  pngtest_write_data,
00748 #    if defined(PNG_WRITE_FLUSH_SUPPORTED)
00749       pngtest_flush);
00750 #    else
00751       NULL);
00752 #    endif
00753 #  endif
00754 #endif
00755    if(status_dots_requested == 1)
00756    {
00757 #ifdef PNG_WRITE_SUPPORTED
00758       png_set_write_status_fn(write_ptr, write_row_callback);
00759 #endif
00760       png_set_read_status_fn(read_ptr, read_row_callback);
00761    }
00762    else
00763    {
00764 #ifdef PNG_WRITE_SUPPORTED
00765       png_set_write_status_fn(write_ptr, png_write_status_ptr_NULL);
00766 #endif
00767       png_set_read_status_fn(read_ptr, png_read_status_ptr_NULL);
00768    }
00769 
00770 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
00771    {
00772      int i;
00773      for(i=0; i<256; i++)
00774         filters_used[i]=0;
00775      png_set_read_user_transform_fn(read_ptr, count_filters);
00776    }
00777 #endif
00778 #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
00779    zero_samples=0;
00780    png_set_write_user_transform_fn(write_ptr, count_zero_samples);
00781 #endif
00782 
00783 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
00784 #  ifndef PNG_HANDLE_CHUNK_ALWAYS
00785 #    define PNG_HANDLE_CHUNK_ALWAYS       3
00786 #  endif
00787    png_set_keep_unknown_chunks(read_ptr, PNG_HANDLE_CHUNK_ALWAYS,
00788       png_bytep_NULL, 0);
00789 #endif
00790 #if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
00791 #  ifndef PNG_HANDLE_CHUNK_IF_SAFE
00792 #    define PNG_HANDLE_CHUNK_IF_SAFE      2
00793 #  endif
00794    png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_IF_SAFE,
00795       png_bytep_NULL, 0);
00796 #endif
00797 
00798    png_debug(0, "Reading info struct\n");
00799    png_read_info(read_ptr, read_info_ptr);
00800 
00801    png_debug(0, "Transferring info struct\n");
00802    {
00803       int interlace_type, compression_type, filter_type;
00804 
00805       if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth,
00806           &color_type, &interlace_type, &compression_type, &filter_type))
00807       {
00808          png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth,
00809 #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
00810             color_type, interlace_type, compression_type, filter_type);
00811 #else
00812             color_type, PNG_INTERLACE_NONE, compression_type, filter_type);
00813 #endif
00814       }
00815    }
00816 #if defined(PNG_FIXED_POINT_SUPPORTED)
00817 #if defined(PNG_cHRM_SUPPORTED)
00818    {
00819       png_fixed_point white_x, white_y, red_x, red_y, green_x, green_y, blue_x,
00820          blue_y;
00821       if (png_get_cHRM_fixed(read_ptr, read_info_ptr, &white_x, &white_y, &red_x,
00822          &red_y, &green_x, &green_y, &blue_x, &blue_y))
00823       {
00824          png_set_cHRM_fixed(write_ptr, write_info_ptr, white_x, white_y, red_x,
00825             red_y, green_x, green_y, blue_x, blue_y);
00826       }
00827    }
00828 #endif
00829 #if defined(PNG_gAMA_SUPPORTED)
00830    {
00831       png_fixed_point gamma;
00832 
00833       if (png_get_gAMA_fixed(read_ptr, read_info_ptr, &gamma))
00834       {
00835          png_set_gAMA_fixed(write_ptr, write_info_ptr, gamma);
00836       }
00837    }
00838 #endif
00839 #else /* Use floating point versions */
00840 #if defined(PNG_FLOATING_POINT_SUPPORTED)
00841 #if defined(PNG_cHRM_SUPPORTED)
00842    {
00843       double white_x, white_y, red_x, red_y, green_x, green_y, blue_x,
00844          blue_y;
00845       if (png_get_cHRM(read_ptr, read_info_ptr, &white_x, &white_y, &red_x,
00846          &red_y, &green_x, &green_y, &blue_x, &blue_y))
00847       {
00848          png_set_cHRM(write_ptr, write_info_ptr, white_x, white_y, red_x,
00849             red_y, green_x, green_y, blue_x, blue_y);
00850       }
00851    }
00852 #endif
00853 #if defined(PNG_gAMA_SUPPORTED)
00854    {
00855       double gamma;
00856 
00857       if (png_get_gAMA(read_ptr, read_info_ptr, &gamma))
00858       {
00859          png_set_gAMA(write_ptr, write_info_ptr, gamma);
00860       }
00861    }
00862 #endif
00863 #endif /* floating point */
00864 #endif /* fixed point */
00865 #if defined(PNG_iCCP_SUPPORTED)
00866    {
00867       png_charp name;
00868       png_charp profile;
00869       png_uint_32 proflen;
00870       int compression_type;
00871 
00872       if (png_get_iCCP(read_ptr, read_info_ptr, &name, &compression_type,
00873                       &profile, &proflen))
00874       {
00875          png_set_iCCP(write_ptr, write_info_ptr, name, compression_type,
00876                       profile, proflen);
00877       }
00878    }
00879 #endif
00880 #if defined(PNG_sRGB_SUPPORTED)
00881    {
00882       int intent;
00883 
00884       if (png_get_sRGB(read_ptr, read_info_ptr, &intent))
00885       {
00886          png_set_sRGB(write_ptr, write_info_ptr, intent);
00887       }
00888    }
00889 #endif
00890    {
00891       png_colorp palette;
00892       int num_palette;
00893 
00894       if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette))
00895       {
00896          png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette);
00897       }
00898    }
00899 #if defined(PNG_bKGD_SUPPORTED)
00900    {
00901       png_color_16p background;
00902 
00903       if (png_get_bKGD(read_ptr, read_info_ptr, &background))
00904       {
00905          png_set_bKGD(write_ptr, write_info_ptr, background);
00906       }
00907    }
00908 #endif
00909 #if defined(PNG_hIST_SUPPORTED)
00910    {
00911       png_uint_16p hist;
00912 
00913       if (png_get_hIST(read_ptr, read_info_ptr, &hist))
00914       {
00915          png_set_hIST(write_ptr, write_info_ptr, hist);
00916       }
00917    }
00918 #endif
00919 #if defined(PNG_oFFs_SUPPORTED)
00920    {
00921       png_int_32 offset_x, offset_y;
00922       int unit_type;
00923 
00924       if (png_get_oFFs(read_ptr, read_info_ptr,&offset_x,&offset_y,&unit_type))
00925       {
00926          png_set_oFFs(write_ptr, write_info_ptr, offset_x, offset_y, unit_type);
00927       }
00928    }
00929 #endif
00930 #if defined(PNG_pCAL_SUPPORTED)
00931    {
00932       png_charp purpose, units;
00933       png_charpp params;
00934       png_int_32 X0, X1;
00935       int type, nparams;
00936 
00937       if (png_get_pCAL(read_ptr, read_info_ptr, &purpose, &X0, &X1, &type,
00938          &nparams, &units, &params))
00939       {
00940          png_set_pCAL(write_ptr, write_info_ptr, purpose, X0, X1, type,
00941             nparams, units, params);
00942       }
00943    }
00944 #endif
00945 #if defined(PNG_pHYs_SUPPORTED)
00946    {
00947       png_uint_32 res_x, res_y;
00948       int unit_type;
00949 
00950       if (png_get_pHYs(read_ptr, read_info_ptr, &res_x, &res_y, &unit_type))
00951       {
00952          png_set_pHYs(write_ptr, write_info_ptr, res_x, res_y, unit_type);
00953       }
00954    }
00955 #endif
00956 #if defined(PNG_sBIT_SUPPORTED)
00957    {
00958       png_color_8p sig_bit;
00959 
00960       if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit))
00961       {
00962          png_set_sBIT(write_ptr, write_info_ptr, sig_bit);
00963       }
00964    }
00965 #endif
00966 #if defined(PNG_sCAL_SUPPORTED)
00967 #ifdef PNG_FLOATING_POINT_SUPPORTED
00968    {
00969       int unit;
00970       double scal_width, scal_height;
00971 
00972       if (png_get_sCAL(read_ptr, read_info_ptr, &unit, &scal_width,
00973          &scal_height))
00974       {
00975          png_set_sCAL(write_ptr, write_info_ptr, unit, scal_width, scal_height);
00976       }
00977    }
00978 #else
00979 #ifdef PNG_FIXED_POINT_SUPPORTED
00980    {
00981       int unit;
00982       png_charp scal_width, scal_height;
00983 
00984       if (png_get_sCAL_s(read_ptr, read_info_ptr, &unit, &scal_width,
00985           &scal_height))
00986       {
00987          png_set_sCAL_s(write_ptr, write_info_ptr, unit, scal_width, scal_height);
00988       }
00989    }
00990 #endif
00991 #endif
00992 #endif
00993 #if defined(PNG_TEXT_SUPPORTED)
00994    {
00995       png_textp text_ptr;
00996       int num_text;
00997 
00998       if (png_get_text(read_ptr, read_info_ptr, &text_ptr, &num_text) > 0)
00999       {
01000          png_debug1(0, "Handling %d iTXt/tEXt/zTXt chunks\n", num_text);
01001          png_set_text(write_ptr, write_info_ptr, text_ptr, num_text);
01002       }
01003    }
01004 #endif
01005 #if defined(PNG_tIME_SUPPORTED)
01006    {
01007       png_timep mod_time;
01008 
01009       if (png_get_tIME(read_ptr, read_info_ptr, &mod_time))
01010       {
01011          png_set_tIME(write_ptr, write_info_ptr, mod_time);
01012 #if defined(PNG_TIME_RFC1123_SUPPORTED)
01013          /* we have to use png_strcpy instead of "=" because the string
01014             pointed to by png_convert_to_rfc1123() gets free'ed before
01015             we use it */
01016          png_strcpy(tIME_string,png_convert_to_rfc1123(read_ptr, mod_time));
01017          tIME_chunk_present++;
01018 #endif /* PNG_TIME_RFC1123_SUPPORTED */
01019       }
01020    }
01021 #endif
01022 #if defined(PNG_tRNS_SUPPORTED)
01023    {
01024       png_bytep trans;
01025       int num_trans;
01026       png_color_16p trans_values;
01027 
01028       if (png_get_tRNS(read_ptr, read_info_ptr, &trans, &num_trans,
01029          &trans_values))
01030       {
01031          png_set_tRNS(write_ptr, write_info_ptr, trans, num_trans,
01032             trans_values);
01033       }
01034    }
01035 #endif
01036 #if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
01037    {
01038       png_unknown_chunkp unknowns;
01039       int num_unknowns = (int)png_get_unknown_chunks(read_ptr, read_info_ptr,
01040          &unknowns);
01041       if (num_unknowns)
01042       {
01043          png_size_t i;
01044          png_set_unknown_chunks(write_ptr, write_info_ptr, unknowns,
01045            num_unknowns);
01046          /* copy the locations from the read_info_ptr.  The automatically
01047             generated locations in write_info_ptr are wrong because we
01048             haven't written anything yet */
01049          for (i = 0; i < (png_size_t)num_unknowns; i++)
01050            png_set_unknown_chunk_location(write_ptr, write_info_ptr, i,
01051              unknowns[i].location);
01052       }
01053    }
01054 #endif
01055 
01056 #ifdef PNG_WRITE_SUPPORTED
01057    png_debug(0, "\nWriting info struct\n");
01058 
01059 /* If we wanted, we could write info in two steps:
01060    png_write_info_before_PLTE(write_ptr, write_info_ptr);
01061  */
01062    png_write_info(write_ptr, write_info_ptr);
01063 #endif
01064 
01065 #ifdef SINGLE_ROWBUF_ALLOC
01066    png_debug(0, "\nAllocating row buffer...");
01067    row_buf = (png_bytep)png_malloc(read_ptr,
01068       png_get_rowbytes(read_ptr, read_info_ptr));
01069    png_debug1(0, "0x%08lx\n\n", (unsigned long)row_buf);
01070 #endif /* SINGLE_ROWBUF_ALLOC */
01071    png_debug(0, "Writing row data\n");
01072 
01073 #if defined(PNG_READ_INTERLACING_SUPPORTED) || \
01074   defined(PNG_WRITE_INTERLACING_SUPPORTED)
01075    num_pass = png_set_interlace_handling(read_ptr);
01076 #  ifdef PNG_WRITE_SUPPORTED
01077    png_set_interlace_handling(write_ptr);
01078 #  endif
01079 #else
01080    num_pass=1;
01081 #endif
01082 
01083 #ifdef PNGTEST_TIMING
01084    t_stop = (float)clock();
01085    t_misc += (t_stop - t_start);
01086    t_start = t_stop;
01087 #endif
01088    for (pass = 0; pass < num_pass; pass++)
01089    {
01090       png_debug1(0, "Writing row data for pass %d\n",pass);
01091       for (y = 0; y < height; y++)
01092       {
01093 #ifndef SINGLE_ROWBUF_ALLOC
01094          png_debug2(0, "\nAllocating row buffer (pass %d, y = %ld)...", pass,y);
01095          row_buf = (png_bytep)png_malloc(read_ptr,
01096             png_get_rowbytes(read_ptr, read_info_ptr));
01097          png_debug2(0, "0x%08lx (%ld bytes)\n", (unsigned long)row_buf,
01098             png_get_rowbytes(read_ptr, read_info_ptr));
01099 #endif /* !SINGLE_ROWBUF_ALLOC */
01100          png_read_rows(read_ptr, (png_bytepp)&row_buf, png_bytepp_NULL, 1);
01101 
01102 #ifdef PNG_WRITE_SUPPORTED
01103 #ifdef PNGTEST_TIMING
01104          t_stop = (float)clock();
01105          t_decode += (t_stop - t_start);
01106          t_start = t_stop;
01107 #endif
01108          png_write_rows(write_ptr, (png_bytepp)&row_buf, 1);
01109 #ifdef PNGTEST_TIMING
01110          t_stop = (float)clock();
01111          t_encode += (t_stop - t_start);
01112          t_start = t_stop;
01113 #endif
01114 #endif /* PNG_WRITE_SUPPORTED */
01115 
01116 #ifndef SINGLE_ROWBUF_ALLOC
01117          png_debug2(0, "Freeing row buffer (pass %d, y = %ld)\n\n", pass, y);
01118          png_free(read_ptr, row_buf);
01119 #endif /* !SINGLE_ROWBUF_ALLOC */
01120       }
01121    }
01122 
01123 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
01124    png_free_data(read_ptr, read_info_ptr, PNG_FREE_UNKN, -1);
01125 #endif
01126 #if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
01127    png_free_data(write_ptr, write_info_ptr, PNG_FREE_UNKN, -1);
01128 #endif
01129 
01130    png_debug(0, "Reading and writing end_info data\n");
01131 
01132    png_read_end(read_ptr, end_info_ptr);
01133 #if defined(PNG_TEXT_SUPPORTED)
01134    {
01135       png_textp text_ptr;
01136       int num_text;
01137 
01138       if (png_get_text(read_ptr, end_info_ptr, &text_ptr, &num_text) > 0)
01139       {
01140          png_debug1(0, "Handling %d iTXt/tEXt/zTXt chunks\n", num_text);
01141          png_set_text(write_ptr, write_end_info_ptr, text_ptr, num_text);
01142       }
01143    }
01144 #endif
01145 #if defined(PNG_tIME_SUPPORTED)
01146    {
01147       png_timep mod_time;
01148 
01149       if (png_get_tIME(read_ptr, end_info_ptr, &mod_time))
01150       {
01151          png_set_tIME(write_ptr, write_end_info_ptr, mod_time);
01152 #if defined(PNG_TIME_RFC1123_SUPPORTED)
01153          /* we have to use png_strcpy instead of "=" because the string
01154             pointed to by png_convert_to_rfc1123() gets free'ed before
01155             we use it */
01156          png_strcpy(tIME_string,png_convert_to_rfc1123(read_ptr, mod_time));
01157          tIME_chunk_present++;
01158 #endif /* PNG_TIME_RFC1123_SUPPORTED */
01159       }
01160    }
01161 #endif
01162 #if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
01163    {
01164       png_unknown_chunkp unknowns;
01165       int num_unknowns;
01166       num_unknowns = (int)png_get_unknown_chunks(read_ptr, end_info_ptr,
01167          &unknowns);
01168       if (num_unknowns)
01169       {
01170          png_size_t i;
01171          png_set_unknown_chunks(write_ptr, write_end_info_ptr, unknowns,
01172            num_unknowns);
01173          /* copy the locations from the read_info_ptr.  The automatically
01174             generated locations in write_end_info_ptr are wrong because we
01175             haven't written the end_info yet */
01176          for (i = 0; i < (png_size_t)num_unknowns; i++)
01177            png_set_unknown_chunk_location(write_ptr, write_end_info_ptr, i,
01178              unknowns[i].location);
01179       }
01180    }
01181 #endif
01182 #ifdef PNG_WRITE_SUPPORTED
01183    png_write_end(write_ptr, write_end_info_ptr);
01184 #endif
01185 
01186 #ifdef PNG_EASY_ACCESS_SUPPORTED
01187    if(verbose)
01188    {
01189       png_uint_32 iwidth, iheight;
01190       iwidth = png_get_image_width(write_ptr, write_info_ptr);
01191       iheight = png_get_image_height(write_ptr, write_info_ptr);
01192       fprintf(STDERR, "Image width = %lu, height = %lu\n",
01193          iwidth, iheight);
01194    }
01195 #endif
01196 
01197    png_debug(0, "Destroying data structs\n");
01198 #ifdef SINGLE_ROWBUF_ALLOC
01199    png_debug(1, "destroying row_buf for read_ptr\n");
01200    png_free(read_ptr, row_buf);
01201    row_buf=NULL;
01202 #endif /* SINGLE_ROWBUF_ALLOC */
01203    png_debug(1, "destroying read_ptr, read_info_ptr, end_info_ptr\n");
01204    png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
01205 #ifdef PNG_WRITE_SUPPORTED
01206    png_debug(1, "destroying write_end_info_ptr\n");
01207    png_destroy_info_struct(write_ptr, &write_end_info_ptr);
01208    png_debug(1, "destroying write_ptr, write_info_ptr\n");
01209    png_destroy_write_struct(&write_ptr, &write_info_ptr);
01210 #endif
01211    png_debug(0, "Destruction complete.\n");
01212 
01213    FCLOSE(fpin);
01214    FCLOSE(fpout);
01215 
01216    png_debug(0, "Opening files for comparison\n");
01217 #if defined(_WIN32_WCE)
01218    MultiByteToWideChar(CP_ACP, 0, inname, -1, path, MAX_PATH);
01219    if ((fpin = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
01220 #else
01221    if ((fpin = fopen(inname, "rb")) == NULL)
01222 #endif
01223    {
01224       fprintf(STDERR, "Could not find file %s\n", inname);
01225       return (1);
01226    }
01227 
01228 #if defined(_WIN32_WCE)
01229    MultiByteToWideChar(CP_ACP, 0, outname, -1, path, MAX_PATH);
01230    if ((fpout = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
01231 #else
01232    if ((fpout = fopen(outname, "rb")) == NULL)
01233 #endif
01234    {
01235       fprintf(STDERR, "Could not find file %s\n", outname);
01236       FCLOSE(fpin);
01237       return (1);
01238    }
01239 
01240    for(;;)
01241    {
01242       png_size_t num_in, num_out;
01243 
01244       READFILE(fpin, inbuf, 1, num_in);
01245       READFILE(fpout, outbuf, 1, num_out);
01246 
01247       if (num_in != num_out)
01248       {
01249          fprintf(STDERR, "\nFiles %s and %s are of a different size\n",
01250                  inname, outname);
01251          if(wrote_question == 0)
01252          {
01253             fprintf(STDERR,
01254          "   Was %s written with the same maximum IDAT chunk size (%d bytes),",
01255               inname,PNG_ZBUF_SIZE);
01256             fprintf(STDERR,
01257               "\n   filtering heuristic (libpng default), compression");
01258             fprintf(STDERR,
01259               " level (zlib default),\n   and zlib version (%s)?\n\n",
01260               ZLIB_VERSION);
01261             wrote_question=1;
01262          }
01263          FCLOSE(fpin);
01264          FCLOSE(fpout);
01265          return (0);
01266       }
01267 
01268       if (!num_in)
01269          break;
01270 
01271       if (png_memcmp(inbuf, outbuf, num_in))
01272       {
01273          fprintf(STDERR, "\nFiles %s and %s are different\n", inname, outname);
01274          if(wrote_question == 0)
01275          {
01276             fprintf(STDERR,
01277          "   Was %s written with the same maximum IDAT chunk size (%d bytes),",
01278                  inname,PNG_ZBUF_SIZE);
01279             fprintf(STDERR,
01280               "\n   filtering heuristic (libpng default), compression");
01281             fprintf(STDERR,
01282               " level (zlib default),\n   and zlib version (%s)?\n\n",
01283               ZLIB_VERSION);
01284             wrote_question=1;
01285          }
01286          FCLOSE(fpin);
01287          FCLOSE(fpout);
01288          return (0);
01289       }
01290    }
01291 
01292    FCLOSE(fpin);
01293    FCLOSE(fpout);
01294 
01295    return (0);
01296 }
01297 
01298 /* input and output filenames */
01299 #ifdef RISCOS
01300 static PNG_CONST char *inname = "pngtest/png";
01301 static PNG_CONST char *outname = "pngout/png";
01302 #else
01303 static PNG_CONST char *inname = "pngtest.png";
01304 static PNG_CONST char *outname = "pngout.png";
01305 #endif
01306 
01307 int
01308 main(int argc, char *argv[])
01309 {
01310    int multiple = 0;
01311    int ierror = 0;
01312 
01313    fprintf(STDERR, "Testing libpng version %s\n", PNG_LIBPNG_VER_STRING);
01314    fprintf(STDERR, "   with zlib   version %s\n", ZLIB_VERSION);
01315    fprintf(STDERR,"%s",png_get_copyright(NULL));
01316    /* Show the version of libpng used in building the library */
01317    fprintf(STDERR," library (%lu):%s", png_access_version_number(),
01318       png_get_header_version(NULL));
01319    /* Show the version of libpng used in building the application */
01320    fprintf(STDERR," pngtest (%lu):%s", (unsigned long)PNG_LIBPNG_VER,
01321       PNG_HEADER_VERSION_STRING);
01322    fprintf(STDERR," png_sizeof(png_struct)=%ld, png_sizeof(png_info)=%ld\n",
01323                     (long)png_sizeof(png_struct), (long)png_sizeof(png_info));
01324 
01325    /* Do some consistency checking on the memory allocation settings, I'm
01326       not sure this matters, but it is nice to know, the first of these
01327       tests should be impossible because of the way the macros are set
01328       in pngconf.h */
01329 #if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K)
01330       fprintf(STDERR, " NOTE: Zlib compiled for max 64k, libpng not\n");
01331 #endif
01332    /* I think the following can happen. */
01333 #if !defined(MAXSEG_64K) && defined(PNG_MAX_MALLOC_64K)
01334       fprintf(STDERR, " NOTE: libpng compiled for max 64k, zlib not\n");
01335 #endif
01336 
01337    if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING))
01338    {
01339       fprintf(STDERR,
01340          "Warning: versions are different between png.h and png.c\n");
01341       fprintf(STDERR, "  png.h version: %s\n", PNG_LIBPNG_VER_STRING);
01342       fprintf(STDERR, "  png.c version: %s\n\n", png_libpng_ver);
01343       ++ierror;
01344    }
01345 
01346    if (argc > 1)
01347    {
01348       if (strcmp(argv[1], "-m") == 0)
01349       {
01350          multiple = 1;
01351          status_dots_requested = 0;
01352       }
01353       else if (strcmp(argv[1], "-mv") == 0 ||
01354                strcmp(argv[1], "-vm") == 0 )
01355       {
01356          multiple = 1;
01357          verbose = 1;
01358          status_dots_requested = 1;
01359       }
01360       else if (strcmp(argv[1], "-v") == 0)
01361       {
01362          verbose = 1;
01363          status_dots_requested = 1;
01364          inname = argv[2];
01365       }
01366       else
01367       {
01368          inname = argv[1];
01369          status_dots_requested = 0;
01370       }
01371    }
01372 
01373    if (!multiple && argc == 3+verbose)
01374      outname = argv[2+verbose];
01375 
01376    if ((!multiple && argc > 3+verbose) || (multiple && argc < 2))
01377    {
01378      fprintf(STDERR,
01379        "usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n",
01380         argv[0], argv[0]);
01381      fprintf(STDERR,
01382        "  reads/writes one PNG file (without -m) or multiple files (-m)\n");
01383      fprintf(STDERR,
01384        "  with -m %s is used as a temporary file\n", outname);
01385      exit(1);
01386    }
01387 
01388    if (multiple)
01389    {
01390       int i;
01391 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
01392       int allocation_now = current_allocation;
01393 #endif
01394       for (i=2; i<argc; ++i)
01395       {
01396 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
01397          int k;
01398 #endif
01399          int kerror;
01400          fprintf(STDERR, "Testing %s:",argv[i]);
01401          kerror = test_one_file(argv[i], outname);
01402          if (kerror == 0)
01403          {
01404 #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
01405             fprintf(STDERR, "\n PASS (%lu zero samples)\n",zero_samples);
01406 #else
01407             fprintf(STDERR, " PASS\n");
01408 #endif
01409 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
01410             for (k=0; k<256; k++)
01411                if(filters_used[k])
01412                   fprintf(STDERR, " Filter %d was used %lu times\n",
01413                      k,filters_used[k]);
01414 #endif
01415 #if defined(PNG_TIME_RFC1123_SUPPORTED)
01416          if(tIME_chunk_present != 0)
01417             fprintf(STDERR, " tIME = %s\n",tIME_string);
01418          tIME_chunk_present = 0;
01419 #endif /* PNG_TIME_RFC1123_SUPPORTED */
01420          }
01421          else
01422          {
01423             fprintf(STDERR, " FAIL\n");
01424             ierror += kerror;
01425          }
01426 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
01427          if (allocation_now != current_allocation)
01428             fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n",
01429                current_allocation-allocation_now);
01430          if (current_allocation != 0)
01431          {
01432             memory_infop pinfo = pinformation;
01433 
01434             fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n",
01435                current_allocation);
01436             while (pinfo != NULL)
01437             {
01438                fprintf(STDERR, " %lu bytes at %x\n", pinfo->size, 
01439                  (unsigned int) pinfo->pointer);
01440                pinfo = pinfo->next;
01441             }
01442          }
01443 #endif
01444       }
01445 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
01446          fprintf(STDERR, " Current memory allocation: %10d bytes\n",
01447             current_allocation);
01448          fprintf(STDERR, " Maximum memory allocation: %10d bytes\n",
01449             maximum_allocation);
01450          fprintf(STDERR, " Total   memory allocation: %10d bytes\n",
01451             total_allocation);
01452          fprintf(STDERR, "     Number of allocations: %10d\n",
01453             num_allocations);
01454 #endif
01455    }
01456    else
01457    {
01458       int i;
01459       for (i=0; i<3; ++i)
01460       {
01461          int kerror;
01462 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
01463          int allocation_now = current_allocation;
01464 #endif
01465          if (i == 1) status_dots_requested = 1;
01466          else if(verbose == 0)status_dots_requested = 0;
01467          if (i == 0 || verbose == 1 || ierror != 0)
01468             fprintf(STDERR, "Testing %s:",inname);
01469          kerror = test_one_file(inname, outname);
01470          if(kerror == 0)
01471          {
01472             if(verbose == 1 || i == 2)
01473             {
01474 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
01475                 int k;
01476 #endif
01477 #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
01478                 fprintf(STDERR, "\n PASS (%lu zero samples)\n",zero_samples);
01479 #else
01480                 fprintf(STDERR, " PASS\n");
01481 #endif
01482 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
01483                 for (k=0; k<256; k++)
01484                    if(filters_used[k])
01485                       fprintf(STDERR, " Filter %d was used %lu times\n",
01486                          k,filters_used[k]);
01487 #endif
01488 #if defined(PNG_TIME_RFC1123_SUPPORTED)
01489              if(tIME_chunk_present != 0)
01490                 fprintf(STDERR, " tIME = %s\n",tIME_string);
01491 #endif /* PNG_TIME_RFC1123_SUPPORTED */
01492             }
01493          }
01494          else
01495          {
01496             if(verbose == 0 && i != 2)
01497                fprintf(STDERR, "Testing %s:",inname);
01498             fprintf(STDERR, " FAIL\n");
01499             ierror += kerror;
01500          }
01501 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
01502          if (allocation_now != current_allocation)
01503              fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n",
01504                current_allocation-allocation_now);
01505          if (current_allocation != 0)
01506          {
01507              memory_infop pinfo = pinformation;
01508 
01509              fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n",
01510                 current_allocation);
01511              while (pinfo != NULL)
01512              {
01513                 fprintf(STDERR," %lu bytes at %x\n",
01514                    pinfo->size, (unsigned int)pinfo->pointer);
01515                 pinfo = pinfo->next;
01516              }
01517           }
01518 #endif
01519        }
01520 #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
01521        fprintf(STDERR, " Current memory allocation: %10d bytes\n",
01522           current_allocation);
01523        fprintf(STDERR, " Maximum memory allocation: %10d bytes\n",
01524           maximum_allocation);
01525        fprintf(STDERR, " Total   memory allocation: %10d bytes\n",
01526           total_allocation);
01527        fprintf(STDERR, "     Number of allocations: %10d\n",
01528             num_allocations);
01529 #endif
01530    }
01531 
01532 #ifdef PNGTEST_TIMING
01533    t_stop = (float)clock();
01534    t_misc += (t_stop - t_start);
01535    t_start = t_stop;
01536    fprintf(STDERR," CPU time used = %.3f seconds",
01537       (t_misc+t_decode+t_encode)/(float)CLOCKS_PER_SEC);
01538    fprintf(STDERR," (decoding %.3f,\n",
01539       t_decode/(float)CLOCKS_PER_SEC);
01540    fprintf(STDERR,"        encoding %.3f ,",
01541       t_encode/(float)CLOCKS_PER_SEC);
01542    fprintf(STDERR," other %.3f seconds)\n\n",
01543       t_misc/(float)CLOCKS_PER_SEC);
01544 #endif
01545 
01546    if (ierror == 0)
01547       fprintf(STDERR, "libpng passes test\n");
01548    else
01549       fprintf(STDERR, "libpng FAILS test\n");
01550    return (int)(ierror != 0);
01551 }
01552 
01553 /* Generate a compiler error if there is an old png.h in the search path. */
01554 typedef version_1_2_8 your_png_h_is_not_version_1_2_8;