Back to index

plt-scheme  4.2.1
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.5 - October 3, 2002
00005  * For conditions of distribution and use, see copyright notice in png.h
00006  * Copyright (c) 1998-2002 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 #if defined(_WIN32_WCE)
00032 #  if _WIN32_WCE < 211
00033      __error__ (f|w)printf functions are not supported on old WindowsCE.;
00034 #  endif
00035 #  include <windows.h>
00036 #  include <stdlib.h>
00037 #  define READFILE(file, data, length, check) \
00038      if (ReadFile(file, data, length, &check,NULL)) check = 0
00039 #  define WRITEFILE(file, data, length, check)) \
00040      if (WriteFile(file, data, length, &check, NULL)) check = 0
00041 #  define FCLOSE(file) CloseHandle(file)
00042 #else
00043 #  include <stdio.h>
00044 #  include <stdlib.h>
00045 #  include <assert.h>
00046 #  define READFILE(file, data, length, check) \
00047      check=(png_size_t)fread(data,(png_size_t)1,length,file)
00048 #  define WRITEFILE(file, data, length, check) \
00049      check=(png_size_t)fwrite(data,(png_size_t)1, length, file)
00050 #  define FCLOSE(file) fclose(file)
00051 #endif
00052 
00053 #if defined(PNG_NO_STDIO)
00054 #  if defined(_WIN32_WCE)
00055      typedef HANDLE                png_FILE_p;
00056 #  else
00057      typedef FILE                * png_FILE_p;
00058 #  endif
00059 #endif
00060 
00061 /* Makes pngtest verbose so we can find problems (needs to be before png.h) */
00062 #ifndef PNG_DEBUG
00063 #  define PNG_DEBUG 0
00064 #endif
00065 
00066 #if !PNG_DEBUG
00067 #  define SINGLE_ROWBUF_ALLOC  /* makes buffer overruns easier to nail */
00068 #endif
00069 
00070 /* Turn on CPU timing
00071 #define PNGTEST_TIMING
00072 */
00073 
00074 #ifdef PNG_NO_FLOATING_POINT_SUPPORTED
00075 #undef PNGTEST_TIMING
00076 #endif
00077 
00078 #ifdef PNGTEST_TIMING
00079 static float t_start, t_stop, t_decode, t_encode, t_misc;
00080 #include <time.h>
00081 #endif
00082 
00083 #include "png.h"
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_MAX_UINT) 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_MAX_UINT || 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 #ifdef PNG_USER_MEM_SUPPORTED
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       memory_infop pinfo = (memory_infop)png_malloc_default(png_ptr,
00514          (png_uint_32)sizeof *pinfo);
00515       pinfo->size = size;
00516       current_allocation += size;
00517       total_allocation += size;
00518       num_allocations ++;
00519       if (current_allocation > maximum_allocation)
00520          maximum_allocation = current_allocation;
00521       pinfo->pointer = (png_voidp)png_malloc_default(png_ptr, size);
00522       pinfo->next = pinformation;
00523       pinformation = pinfo;
00524       /* Make sure the caller isn't assuming zeroed memory. */
00525       png_memset(pinfo->pointer, 0xdd, pinfo->size);
00526 #if PNG_DEBUG
00527       if(verbose)
00528          printf("png_malloc %lu bytes at %x\n",size,pinfo->pointer);
00529 #endif
00530       assert(pinfo->size != 12345678);
00531       return (png_voidp)(pinfo->pointer);
00532    }
00533 }
00534 
00535 /* Free a pointer.  It is removed from the list at the same time. */
00536 void
00537 png_debug_free(png_structp png_ptr, png_voidp ptr)
00538 {
00539    if (png_ptr == NULL)
00540       fprintf(STDERR, "NULL pointer to png_debug_free.\n");
00541    if (ptr == 0)
00542    {
00543 #if 0 /* This happens all the time. */
00544       fprintf(STDERR, "WARNING: freeing NULL pointer\n");
00545 #endif
00546       return;
00547    }
00548 
00549    /* Unlink the element from the list. */
00550    {
00551       memory_infop FAR *ppinfo = &pinformation;
00552       for (;;)
00553       {
00554          memory_infop pinfo = *ppinfo;
00555          if (pinfo->pointer == ptr)
00556          {
00557             *ppinfo = pinfo->next;
00558             current_allocation -= pinfo->size;
00559             if (current_allocation < 0)
00560                fprintf(STDERR, "Duplicate free of memory\n");
00561             /* We must free the list element too, but first kill
00562                the memory that is to be freed. */
00563             png_memset(ptr, 0x55, pinfo->size);
00564             png_free_default(png_ptr, pinfo);
00565             pinfo=NULL;
00566             break;
00567          }
00568          if (pinfo->next == NULL)
00569          {
00570             fprintf(STDERR, "Pointer %x not found\n", (unsigned int)ptr);
00571             break;
00572          }
00573          ppinfo = &pinfo->next;
00574       }
00575    }
00576 
00577    /* Finally free the data. */
00578 #if PNG_DEBUG
00579    if(verbose)
00580       printf("Freeing %x\n",ptr);
00581 #endif
00582    png_free_default(png_ptr, ptr);
00583    ptr=NULL;
00584 }
00585 #endif /* PNG_USER_MEM_SUPPORTED */
00586 /* END of code to test memory allocation/deallocation */
00587 
00588 /* Test one file */
00589 int
00590 test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
00591 {
00592    static png_FILE_p fpin;
00593    static png_FILE_p fpout;  /* "static" prevents setjmp corruption */
00594    png_structp read_ptr;
00595    png_infop read_info_ptr, end_info_ptr;
00596 #ifdef PNG_WRITE_SUPPORTED
00597    png_structp write_ptr;
00598    png_infop write_info_ptr;
00599    png_infop write_end_info_ptr;
00600 #else
00601    png_structp write_ptr = NULL;
00602    png_infop write_info_ptr = NULL;
00603    png_infop write_end_info_ptr = NULL;
00604 #endif
00605    png_bytep row_buf;
00606    png_uint_32 y;
00607    png_uint_32 width, height;
00608    int num_pass, pass;
00609    int bit_depth, color_type;
00610 #ifdef PNG_SETJMP_SUPPORTED
00611 #ifdef USE_FAR_KEYWORD
00612    jmp_buf jmpbuf;
00613 #endif
00614 #endif
00615 
00616 #if defined(_WIN32_WCE)
00617    TCHAR path[MAX_PATH];
00618 #endif
00619    char inbuf[256], outbuf[256];
00620 
00621    row_buf = NULL;
00622 
00623 #if defined(_WIN32_WCE)
00624    MultiByteToWideChar(CP_ACP, 0, inname, -1, path, MAX_PATH);
00625    if ((fpin = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
00626 #else
00627    if ((fpin = fopen(inname, "rb")) == NULL)
00628 #endif
00629    {
00630       fprintf(STDERR, "Could not find input file %s\n", inname);
00631       return (1);
00632    }
00633 
00634 #if defined(_WIN32_WCE)
00635    MultiByteToWideChar(CP_ACP, 0, outname, -1, path, MAX_PATH);
00636    if ((fpout = CreateFile(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL)) == INVALID_HANDLE_VALUE)
00637 #else
00638    if ((fpout = fopen(outname, "wb")) == NULL)
00639 #endif
00640    {
00641       fprintf(STDERR, "Could not open output file %s\n", outname);
00642       FCLOSE(fpin);
00643       return (1);
00644    }
00645 
00646    png_debug(0, "Allocating read and write structures\n");
00647 #ifdef PNG_USER_MEM_SUPPORTED
00648    read_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, png_voidp_NULL,
00649       png_error_ptr_NULL, png_error_ptr_NULL, png_voidp_NULL,
00650       (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free);
00651 #else
00652    read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL,
00653       png_error_ptr_NULL, png_error_ptr_NULL);
00654 #endif
00655 #if defined(PNG_NO_STDIO)
00656    png_set_error_fn(read_ptr, (png_voidp)inname, pngtest_error,
00657        pngtest_warning);
00658 #endif
00659 #ifdef PNG_WRITE_SUPPORTED
00660 #ifdef PNG_USER_MEM_SUPPORTED
00661    write_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, png_voidp_NULL,
00662       png_error_ptr_NULL, png_error_ptr_NULL, png_voidp_NULL,
00663       (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free);
00664 #else
00665    write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL,
00666       png_error_ptr_NULL, png_error_ptr_NULL);
00667 #endif
00668 #if defined(PNG_NO_STDIO)
00669    png_set_error_fn(write_ptr, (png_voidp)inname, pngtest_error,
00670        pngtest_warning);
00671 #endif
00672 #endif
00673    png_debug(0, "Allocating read_info, write_info and end_info structures\n");
00674    read_info_ptr = png_create_info_struct(read_ptr);
00675    end_info_ptr = png_create_info_struct(read_ptr);
00676 #ifdef PNG_WRITE_SUPPORTED
00677    write_info_ptr = png_create_info_struct(write_ptr);
00678    write_end_info_ptr = png_create_info_struct(write_ptr);
00679 #endif
00680 
00681 #ifdef PNG_SETJMP_SUPPORTED
00682    png_debug(0, "Setting jmpbuf for read struct\n");
00683 #ifdef USE_FAR_KEYWORD
00684    if (setjmp(jmpbuf))
00685 #else
00686    if (setjmp(png_jmpbuf(read_ptr)))
00687 #endif
00688    {
00689       fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname);
00690       if (row_buf)
00691          png_free(read_ptr, row_buf);
00692       png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
00693 #ifdef PNG_WRITE_SUPPORTED
00694       png_destroy_info_struct(write_ptr, &write_end_info_ptr);
00695       png_destroy_write_struct(&write_ptr, &write_info_ptr);
00696 #endif
00697       FCLOSE(fpin);
00698       FCLOSE(fpout);
00699       return (1);
00700    }
00701 #ifdef USE_FAR_KEYWORD
00702    png_memcpy(png_jmpbuf(read_ptr),jmpbuf,sizeof(jmp_buf));
00703 #endif
00704 
00705 #ifdef PNG_WRITE_SUPPORTED
00706    png_debug(0, "Setting jmpbuf for write struct\n");
00707 #ifdef USE_FAR_KEYWORD
00708    if (setjmp(jmpbuf))
00709 #else
00710    if (setjmp(png_jmpbuf(write_ptr)))
00711 #endif
00712    {
00713       fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname);
00714       png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
00715       png_destroy_info_struct(write_ptr, &write_end_info_ptr);
00716 #ifdef PNG_WRITE_SUPPORTED
00717       png_destroy_write_struct(&write_ptr, &write_info_ptr);
00718 #endif
00719       FCLOSE(fpin);
00720       FCLOSE(fpout);
00721       return (1);
00722    }
00723 #ifdef USE_FAR_KEYWORD
00724    png_memcpy(png_jmpbuf(write_ptr),jmpbuf,sizeof(jmp_buf));
00725 #endif
00726 #endif
00727 #endif
00728 
00729    png_debug(0, "Initializing input and output streams\n");
00730 #if !defined(PNG_NO_STDIO)
00731    png_init_io(read_ptr, fpin);
00732 #  ifdef PNG_WRITE_SUPPORTED
00733    png_init_io(write_ptr, fpout);
00734 #  endif
00735 #else
00736    png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data);
00737 #  ifdef PNG_WRITE_SUPPORTED
00738    png_set_write_fn(write_ptr, (png_voidp)fpout,  pngtest_write_data,
00739 #    if defined(PNG_WRITE_FLUSH_SUPPORTED)
00740       pngtest_flush);
00741 #    else
00742       NULL);
00743 #    endif
00744 #  endif
00745 #endif
00746    if(status_dots_requested == 1)
00747    {
00748 #ifdef PNG_WRITE_SUPPORTED
00749       png_set_write_status_fn(write_ptr, write_row_callback);
00750 #endif
00751       png_set_read_status_fn(read_ptr, read_row_callback);
00752    }
00753    else
00754    {
00755 #ifdef PNG_WRITE_SUPPORTED
00756       png_set_write_status_fn(write_ptr, png_write_status_ptr_NULL);
00757 #endif
00758       png_set_read_status_fn(read_ptr, png_read_status_ptr_NULL);
00759    }
00760 
00761 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
00762    {
00763      int i;
00764      for(i=0; i<256; i++)
00765         filters_used[i]=0;
00766      png_set_read_user_transform_fn(read_ptr, count_filters);
00767    }
00768 #endif
00769 #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
00770    zero_samples=0;
00771    png_set_write_user_transform_fn(write_ptr, count_zero_samples);
00772 #endif
00773 
00774 #define HANDLE_CHUNK_IF_SAFE      2
00775 #define HANDLE_CHUNK_ALWAYS       3
00776 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
00777    png_set_keep_unknown_chunks(read_ptr, HANDLE_CHUNK_ALWAYS,
00778       png_bytep_NULL, 0);
00779 #endif
00780 #if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
00781    png_set_keep_unknown_chunks(write_ptr, HANDLE_CHUNK_IF_SAFE,
00782       png_bytep_NULL, 0);
00783 #endif
00784 
00785    png_debug(0, "Reading info struct\n");
00786    png_read_info(read_ptr, read_info_ptr);
00787 
00788    png_debug(0, "Transferring info struct\n");
00789    {
00790       int interlace_type, compression_type, filter_type;
00791 
00792       if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth,
00793           &color_type, &interlace_type, &compression_type, &filter_type))
00794       {
00795          png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth,
00796 #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
00797             color_type, interlace_type, compression_type, filter_type);
00798 #else
00799             color_type, PNG_INTERLACE_NONE, compression_type, filter_type);
00800 #endif
00801       }
00802    }
00803 #if defined(PNG_FIXED_POINT_SUPPORTED)
00804 #if defined(PNG_cHRM_SUPPORTED)
00805    {
00806       png_fixed_point white_x, white_y, red_x, red_y, green_x, green_y, blue_x,
00807          blue_y;
00808       if (png_get_cHRM_fixed(read_ptr, read_info_ptr, &white_x, &white_y, &red_x,
00809          &red_y, &green_x, &green_y, &blue_x, &blue_y))
00810       {
00811          png_set_cHRM_fixed(write_ptr, write_info_ptr, white_x, white_y, red_x,
00812             red_y, green_x, green_y, blue_x, blue_y);
00813       }
00814    }
00815 #endif
00816 #if defined(PNG_gAMA_SUPPORTED)
00817    {
00818       png_fixed_point gamma;
00819 
00820       if (png_get_gAMA_fixed(read_ptr, read_info_ptr, &gamma))
00821       {
00822          png_set_gAMA_fixed(write_ptr, write_info_ptr, gamma);
00823       }
00824    }
00825 #endif
00826 #else /* Use floating point versions */
00827 #if defined(PNG_FLOATING_POINT_SUPPORTED)
00828 #if defined(PNG_cHRM_SUPPORTED)
00829    {
00830       double white_x, white_y, red_x, red_y, green_x, green_y, blue_x,
00831          blue_y;
00832       if (png_get_cHRM(read_ptr, read_info_ptr, &white_x, &white_y, &red_x,
00833          &red_y, &green_x, &green_y, &blue_x, &blue_y))
00834       {
00835          png_set_cHRM(write_ptr, write_info_ptr, white_x, white_y, red_x,
00836             red_y, green_x, green_y, blue_x, blue_y);
00837       }
00838    }
00839 #endif
00840 #if defined(PNG_gAMA_SUPPORTED)
00841    {
00842       double gamma;
00843 
00844       if (png_get_gAMA(read_ptr, read_info_ptr, &gamma))
00845       {
00846          png_set_gAMA(write_ptr, write_info_ptr, gamma);
00847       }
00848    }
00849 #endif
00850 #endif /* floating point */
00851 #endif /* fixed point */
00852 #if defined(PNG_iCCP_SUPPORTED)
00853    {
00854       png_charp name;
00855       png_charp profile;
00856       png_uint_32 proflen;
00857       int compression_type;
00858 
00859       if (png_get_iCCP(read_ptr, read_info_ptr, &name, &compression_type,
00860                       &profile, &proflen))
00861       {
00862          png_set_iCCP(write_ptr, write_info_ptr, name, compression_type,
00863                       profile, proflen);
00864       }
00865    }
00866 #endif
00867 #if defined(PNG_sRGB_SUPPORTED)
00868    {
00869       int intent;
00870 
00871       if (png_get_sRGB(read_ptr, read_info_ptr, &intent))
00872       {
00873          png_set_sRGB(write_ptr, write_info_ptr, intent);
00874       }
00875    }
00876 #endif
00877    {
00878       png_colorp palette;
00879       int num_palette;
00880 
00881       if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette))
00882       {
00883          png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette);
00884       }
00885    }
00886 #if defined(PNG_bKGD_SUPPORTED)
00887    {
00888       png_color_16p background;
00889 
00890       if (png_get_bKGD(read_ptr, read_info_ptr, &background))
00891       {
00892          png_set_bKGD(write_ptr, write_info_ptr, background);
00893       }
00894    }
00895 #endif
00896 #if defined(PNG_hIST_SUPPORTED)
00897    {
00898       png_uint_16p hist;
00899 
00900       if (png_get_hIST(read_ptr, read_info_ptr, &hist))
00901       {
00902          png_set_hIST(write_ptr, write_info_ptr, hist);
00903       }
00904    }
00905 #endif
00906 #if defined(PNG_oFFs_SUPPORTED)
00907    {
00908       png_int_32 offset_x, offset_y;
00909       int unit_type;
00910 
00911       if (png_get_oFFs(read_ptr, read_info_ptr,&offset_x,&offset_y,&unit_type))
00912       {
00913          png_set_oFFs(write_ptr, write_info_ptr, offset_x, offset_y, unit_type);
00914       }
00915    }
00916 #endif
00917 #if defined(PNG_pCAL_SUPPORTED)
00918    {
00919       png_charp purpose, units;
00920       png_charpp params;
00921       png_int_32 X0, X1;
00922       int type, nparams;
00923 
00924       if (png_get_pCAL(read_ptr, read_info_ptr, &purpose, &X0, &X1, &type,
00925          &nparams, &units, &params))
00926       {
00927          png_set_pCAL(write_ptr, write_info_ptr, purpose, X0, X1, type,
00928             nparams, units, params);
00929       }
00930    }
00931 #endif
00932 #if defined(PNG_pHYs_SUPPORTED)
00933    {
00934       png_uint_32 res_x, res_y;
00935       int unit_type;
00936 
00937       if (png_get_pHYs(read_ptr, read_info_ptr, &res_x, &res_y, &unit_type))
00938       {
00939          png_set_pHYs(write_ptr, write_info_ptr, res_x, res_y, unit_type);
00940       }
00941    }
00942 #endif
00943 #if defined(PNG_sBIT_SUPPORTED)
00944    {
00945       png_color_8p sig_bit;
00946 
00947       if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit))
00948       {
00949          png_set_sBIT(write_ptr, write_info_ptr, sig_bit);
00950       }
00951    }
00952 #endif
00953 #if defined(PNG_sCAL_SUPPORTED)
00954 #ifdef PNG_FLOATING_POINT_SUPPORTED
00955    {
00956       int unit;
00957       double scal_width, scal_height;
00958 
00959       if (png_get_sCAL(read_ptr, read_info_ptr, &unit, &scal_width,
00960          &scal_height))
00961       {
00962          png_set_sCAL(write_ptr, write_info_ptr, unit, scal_width, scal_height);
00963       }
00964    }
00965 #else
00966 #ifdef PNG_FIXED_POINT_SUPPORTED
00967    {
00968       int unit;
00969       png_charp scal_width, scal_height;
00970 
00971       if (png_get_sCAL_s(read_ptr, read_info_ptr, &unit, &scal_width,
00972           &scal_height))
00973       {
00974          png_set_sCAL_s(write_ptr, write_info_ptr, unit, scal_width, scal_height);
00975       }
00976    }
00977 #endif
00978 #endif
00979 #endif
00980 #if defined(PNG_TEXT_SUPPORTED)
00981    {
00982       png_textp text_ptr;
00983       int num_text;
00984 
00985       if (png_get_text(read_ptr, read_info_ptr, &text_ptr, &num_text) > 0)
00986       {
00987          png_debug1(0, "Handling %d iTXt/tEXt/zTXt chunks\n", num_text);
00988          png_set_text(write_ptr, write_info_ptr, text_ptr, num_text);
00989       }
00990    }
00991 #endif
00992 #if defined(PNG_tIME_SUPPORTED)
00993    {
00994       png_timep mod_time;
00995 
00996       if (png_get_tIME(read_ptr, read_info_ptr, &mod_time))
00997       {
00998          png_set_tIME(write_ptr, write_info_ptr, mod_time);
00999 #if defined(PNG_TIME_RFC1123_SUPPORTED)
01000          /* we have to use png_strcpy instead of "=" because the string
01001             pointed to by png_convert_to_rfc1123() gets free'ed before
01002             we use it */
01003          png_strcpy(tIME_string,png_convert_to_rfc1123(read_ptr, mod_time));
01004          tIME_chunk_present++;
01005 #endif /* PNG_TIME_RFC1123_SUPPORTED */
01006       }
01007    }
01008 #endif
01009 #if defined(PNG_tRNS_SUPPORTED)
01010    {
01011       png_bytep trans;
01012       int num_trans;
01013       png_color_16p trans_values;
01014 
01015       if (png_get_tRNS(read_ptr, read_info_ptr, &trans, &num_trans,
01016          &trans_values))
01017       {
01018          png_set_tRNS(write_ptr, write_info_ptr, trans, num_trans,
01019             trans_values);
01020       }
01021    }
01022 #endif
01023 #if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
01024    {
01025       png_unknown_chunkp unknowns;
01026       int num_unknowns = (int)png_get_unknown_chunks(read_ptr, read_info_ptr,
01027          &unknowns);
01028       if (num_unknowns)
01029       {
01030          png_size_t i;
01031          png_set_unknown_chunks(write_ptr, write_info_ptr, unknowns,
01032            num_unknowns);
01033          /* copy the locations from the read_info_ptr.  The automatically
01034             generated locations in write_info_ptr are wrong because we
01035             haven't written anything yet */
01036          for (i = 0; i < (png_size_t)num_unknowns; i++)
01037            png_set_unknown_chunk_location(write_ptr, write_info_ptr, i,
01038              unknowns[i].location);
01039       }
01040    }
01041 #endif
01042 
01043 #ifdef PNG_WRITE_SUPPORTED
01044    png_debug(0, "\nWriting info struct\n");
01045 
01046 /* If we wanted, we could write info in two steps:
01047    png_write_info_before_PLTE(write_ptr, write_info_ptr);
01048  */
01049    png_write_info(write_ptr, write_info_ptr);
01050 #endif
01051 
01052 #ifdef SINGLE_ROWBUF_ALLOC
01053    png_debug(0, "\nAllocating row buffer...");
01054    row_buf = (png_bytep)png_malloc(read_ptr,
01055       png_get_rowbytes(read_ptr, read_info_ptr));
01056    png_debug1(0, "0x%08lx\n\n", (unsigned long)row_buf);
01057 #endif /* SINGLE_ROWBUF_ALLOC */
01058    png_debug(0, "Writing row data\n");
01059 
01060 #if defined(PNG_READ_INTERLACING_SUPPORTED) || \
01061   defined(PNG_WRITE_INTERLACING_SUPPORTED)
01062    num_pass = png_set_interlace_handling(read_ptr);
01063 #  ifdef PNG_WRITE_SUPPORTED
01064    png_set_interlace_handling(write_ptr);
01065 #  endif
01066 #else
01067    num_pass=1;
01068 #endif
01069 
01070 #ifdef PNGTEST_TIMING
01071    t_stop = (float)clock();
01072    t_misc += (t_stop - t_start);
01073    t_start = t_stop;
01074 #endif
01075    for (pass = 0; pass < num_pass; pass++)
01076    {
01077       png_debug1(0, "Writing row data for pass %d\n",pass);
01078       for (y = 0; y < height; y++)
01079       {
01080 #ifndef SINGLE_ROWBUF_ALLOC
01081          png_debug2(0, "\nAllocating row buffer (pass %d, y = %ld)...", pass,y);
01082          row_buf = (png_bytep)png_malloc(read_ptr,
01083             png_get_rowbytes(read_ptr, read_info_ptr));
01084          png_debug2(0, "0x%08lx (%ld bytes)\n", (unsigned long)row_buf,
01085             png_get_rowbytes(read_ptr, read_info_ptr));
01086 #endif /* !SINGLE_ROWBUF_ALLOC */
01087          png_read_rows(read_ptr, (png_bytepp)&row_buf, png_bytepp_NULL, 1);
01088 
01089 #ifdef PNG_WRITE_SUPPORTED
01090 #ifdef PNGTEST_TIMING
01091          t_stop = (float)clock();
01092          t_decode += (t_stop - t_start);
01093          t_start = t_stop;
01094 #endif
01095          png_write_rows(write_ptr, (png_bytepp)&row_buf, 1);
01096 #ifdef PNGTEST_TIMING
01097          t_stop = (float)clock();
01098          t_encode += (t_stop - t_start);
01099          t_start = t_stop;
01100 #endif
01101 #endif /* PNG_WRITE_SUPPORTED */
01102 
01103 #ifndef SINGLE_ROWBUF_ALLOC
01104          png_debug2(0, "Freeing row buffer (pass %d, y = %ld)\n\n", pass, y);
01105          png_free(read_ptr, row_buf);
01106 #endif /* !SINGLE_ROWBUF_ALLOC */
01107       }
01108    }
01109 
01110 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
01111    png_free_data(read_ptr, read_info_ptr, PNG_FREE_UNKN, -1);
01112 #endif
01113 #if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
01114    png_free_data(write_ptr, write_info_ptr, PNG_FREE_UNKN, -1);
01115 #endif
01116 
01117    png_debug(0, "Reading and writing end_info data\n");
01118 
01119    png_read_end(read_ptr, end_info_ptr);
01120 #if defined(PNG_TEXT_SUPPORTED)
01121    {
01122       png_textp text_ptr;
01123       int num_text;
01124 
01125       if (png_get_text(read_ptr, end_info_ptr, &text_ptr, &num_text) > 0)
01126       {
01127          png_debug1(0, "Handling %d iTXt/tEXt/zTXt chunks\n", num_text);
01128          png_set_text(write_ptr, write_end_info_ptr, text_ptr, num_text);
01129       }
01130    }
01131 #endif
01132 #if defined(PNG_tIME_SUPPORTED)
01133    {
01134       png_timep mod_time;
01135 
01136       if (png_get_tIME(read_ptr, end_info_ptr, &mod_time))
01137       {
01138          png_set_tIME(write_ptr, write_end_info_ptr, mod_time);
01139 #if defined(PNG_TIME_RFC1123_SUPPORTED)
01140          /* we have to use png_strcpy instead of "=" because the string
01141             pointed to by png_convert_to_rfc1123() gets free'ed before
01142             we use it */
01143          png_strcpy(tIME_string,png_convert_to_rfc1123(read_ptr, mod_time));
01144          tIME_chunk_present++;
01145 #endif /* PNG_TIME_RFC1123_SUPPORTED */
01146       }
01147    }
01148 #endif
01149 #if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
01150    {
01151       png_unknown_chunkp unknowns;
01152       int num_unknowns;
01153       num_unknowns = (int)png_get_unknown_chunks(read_ptr, end_info_ptr,
01154          &unknowns);
01155       if (num_unknowns)
01156       {
01157          png_size_t i;
01158          png_set_unknown_chunks(write_ptr, write_end_info_ptr, unknowns,
01159            num_unknowns);
01160          /* copy the locations from the read_info_ptr.  The automatically
01161             generated locations in write_end_info_ptr are wrong because we
01162             haven't written the end_info yet */
01163          for (i = 0; i < (png_size_t)num_unknowns; i++)
01164            png_set_unknown_chunk_location(write_ptr, write_end_info_ptr, i,
01165              unknowns[i].location);
01166       }
01167    }
01168 #endif
01169 #ifdef PNG_WRITE_SUPPORTED
01170    png_write_end(write_ptr, write_end_info_ptr);
01171 #endif
01172 
01173 #ifdef PNG_EASY_ACCESS_SUPPORTED
01174    if(verbose)
01175    {
01176       png_uint_32 iwidth, iheight;
01177       iwidth = png_get_image_width(write_ptr, write_info_ptr);
01178       iheight = png_get_image_height(write_ptr, write_info_ptr);
01179       fprintf(STDERR, "Image width = %lu, height = %lu\n",
01180          iwidth, iheight);
01181    }
01182 #endif
01183 
01184    png_debug(0, "Destroying data structs\n");
01185 #ifdef SINGLE_ROWBUF_ALLOC
01186    png_debug(1, "destroying row_buf for read_ptr\n");
01187    png_free(read_ptr, row_buf);
01188    row_buf=NULL;
01189 #endif /* SINGLE_ROWBUF_ALLOC */
01190    png_debug(1, "destroying read_ptr, read_info_ptr, end_info_ptr\n");
01191    png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
01192 #ifdef PNG_WRITE_SUPPORTED
01193    png_debug(1, "destroying write_end_info_ptr\n");
01194    png_destroy_info_struct(write_ptr, &write_end_info_ptr);
01195    png_debug(1, "destroying write_ptr, write_info_ptr\n");
01196    png_destroy_write_struct(&write_ptr, &write_info_ptr);
01197 #endif
01198    png_debug(0, "Destruction complete.\n");
01199 
01200    FCLOSE(fpin);
01201    FCLOSE(fpout);
01202 
01203    png_debug(0, "Opening files for comparison\n");
01204 #if defined(_WIN32_WCE)
01205    MultiByteToWideChar(CP_ACP, 0, inname, -1, path, MAX_PATH);
01206    if ((fpin = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
01207 #else
01208    if ((fpin = fopen(inname, "rb")) == NULL)
01209 #endif
01210    {
01211       fprintf(STDERR, "Could not find file %s\n", inname);
01212       return (1);
01213    }
01214 
01215 #if defined(_WIN32_WCE)
01216    MultiByteToWideChar(CP_ACP, 0, outname, -1, path, MAX_PATH);
01217    if ((fpout = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
01218 #else
01219    if ((fpout = fopen(outname, "rb")) == NULL)
01220 #endif
01221    {
01222       fprintf(STDERR, "Could not find file %s\n", outname);
01223       FCLOSE(fpin);
01224       return (1);
01225    }
01226 
01227    for(;;)
01228    {
01229       png_size_t num_in, num_out;
01230 
01231       READFILE(fpin, inbuf, 1, num_in);
01232       READFILE(fpout, outbuf, 1, num_out);
01233 
01234       if (num_in != num_out)
01235       {
01236          fprintf(STDERR, "\nFiles %s and %s are of a different size\n",
01237                  inname, outname);
01238          if(wrote_question == 0)
01239          {
01240             fprintf(STDERR,
01241          "   Was %s written with the same maximum IDAT chunk size (%d bytes),",
01242               inname,PNG_ZBUF_SIZE);
01243             fprintf(STDERR,
01244               "\n   filtering heuristic (libpng default), compression");
01245             fprintf(STDERR,
01246               " level (zlib default),\n   and zlib version (%s)?\n\n",
01247               ZLIB_VERSION);
01248             wrote_question=1;
01249          }
01250          FCLOSE(fpin);
01251          FCLOSE(fpout);
01252          return (0);
01253       }
01254 
01255       if (!num_in)
01256          break;
01257 
01258       if (png_memcmp(inbuf, outbuf, num_in))
01259       {
01260          fprintf(STDERR, "\nFiles %s and %s are different\n", inname, outname);
01261          if(wrote_question == 0)
01262          {
01263             fprintf(STDERR,
01264          "   Was %s written with the same maximum IDAT chunk size (%d bytes),",
01265                  inname,PNG_ZBUF_SIZE);
01266             fprintf(STDERR,
01267               "\n   filtering heuristic (libpng default), compression");
01268             fprintf(STDERR,
01269               " level (zlib default),\n   and zlib version (%s)?\n\n",
01270               ZLIB_VERSION);
01271             wrote_question=1;
01272          }
01273          FCLOSE(fpin);
01274          FCLOSE(fpout);
01275          return (0);
01276       }
01277    }
01278 
01279    FCLOSE(fpin);
01280    FCLOSE(fpout);
01281 
01282    return (0);
01283 }
01284 
01285 /* input and output filenames */
01286 #ifdef RISCOS
01287 static PNG_CONST char *inname = "pngtest/png";
01288 static PNG_CONST char *outname = "pngout/png";
01289 #else
01290 static PNG_CONST char *inname = "pngtest.png";
01291 static PNG_CONST char *outname = "pngout.png";
01292 #endif
01293 
01294 int
01295 main(int argc, char *argv[])
01296 {
01297    int multiple = 0;
01298    int ierror = 0;
01299 
01300    fprintf(STDERR, "Testing libpng version %s\n", PNG_LIBPNG_VER_STRING);
01301    fprintf(STDERR, "   with zlib   version %s\n", ZLIB_VERSION);
01302    fprintf(STDERR,"%s",png_get_copyright(NULL));
01303    /* Show the version of libpng used in building the library */
01304    fprintf(STDERR," library (%lu):%s", png_access_version_number(),
01305       png_get_header_version(NULL));
01306    /* Show the version of libpng used in building the application */
01307    fprintf(STDERR," pngtest (%lu):%s", (unsigned long)PNG_LIBPNG_VER,
01308       PNG_HEADER_VERSION_STRING);
01309    fprintf(STDERR," sizeof(png_struct)=%ld, sizeof(png_info)=%ld\n",
01310                     (long)sizeof(png_struct), (long)sizeof(png_info));
01311 
01312    /* Do some consistency checking on the memory allocation settings, I'm
01313       not sure this matters, but it is nice to know, the first of these
01314       tests should be impossible because of the way the macros are set
01315       in pngconf.h */
01316 #if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K)
01317       fprintf(STDERR, " NOTE: Zlib compiled for max 64k, libpng not\n");
01318 #endif
01319    /* I think the following can happen. */
01320 #if !defined(MAXSEG_64K) && defined(PNG_MAX_MALLOC_64K)
01321       fprintf(STDERR, " NOTE: libpng compiled for max 64k, zlib not\n");
01322 #endif
01323 
01324    if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING))
01325    {
01326       fprintf(STDERR,
01327          "Warning: versions are different between png.h and png.c\n");
01328       fprintf(STDERR, "  png.h version: %s\n", PNG_LIBPNG_VER_STRING);
01329       fprintf(STDERR, "  png.c version: %s\n\n", png_libpng_ver);
01330       ++ierror;
01331    }
01332 
01333    if (argc > 1)
01334    {
01335       if (strcmp(argv[1], "-m") == 0)
01336       {
01337          multiple = 1;
01338          status_dots_requested = 0;
01339       }
01340       else if (strcmp(argv[1], "-mv") == 0 ||
01341                strcmp(argv[1], "-vm") == 0 )
01342       {
01343          multiple = 1;
01344          verbose = 1;
01345          status_dots_requested = 1;
01346       }
01347       else if (strcmp(argv[1], "-v") == 0)
01348       {
01349          verbose = 1;
01350          status_dots_requested = 1;
01351          inname = argv[2];
01352       }
01353       else
01354       {
01355          inname = argv[1];
01356          status_dots_requested = 0;
01357       }
01358    }
01359 
01360    if (!multiple && argc == 3+verbose)
01361      outname = argv[2+verbose];
01362 
01363    if ((!multiple && argc > 3+verbose) || (multiple && argc < 2))
01364    {
01365      fprintf(STDERR,
01366        "usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n",
01367         argv[0], argv[0]);
01368      fprintf(STDERR,
01369        "  reads/writes one PNG file (without -m) or multiple files (-m)\n");
01370      fprintf(STDERR,
01371        "  with -m %s is used as a temporary file\n", outname);
01372      exit(1);
01373    }
01374 
01375    if (multiple)
01376    {
01377       int i;
01378 #ifdef PNG_USER_MEM_SUPPORTED
01379       int allocation_now = current_allocation;
01380 #endif
01381       for (i=2; i<argc; ++i)
01382       {
01383 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
01384          int k;
01385 #endif
01386          int kerror;
01387          fprintf(STDERR, "Testing %s:",argv[i]);
01388          kerror = test_one_file(argv[i], outname);
01389          if (kerror == 0)
01390          {
01391 #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
01392             fprintf(STDERR, "\n PASS (%lu zero samples)\n",zero_samples);
01393 #else
01394             fprintf(STDERR, " PASS\n");
01395 #endif
01396 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
01397             for (k=0; k<256; k++)
01398                if(filters_used[k])
01399                   fprintf(STDERR, " Filter %d was used %lu times\n",
01400                      k,filters_used[k]);
01401 #endif
01402 #if defined(PNG_TIME_RFC1123_SUPPORTED)
01403          if(tIME_chunk_present != 0)
01404             fprintf(STDERR, " tIME = %s\n",tIME_string);
01405          tIME_chunk_present = 0;
01406 #endif /* PNG_TIME_RFC1123_SUPPORTED */
01407          }
01408          else
01409          {
01410             fprintf(STDERR, " FAIL\n");
01411             ierror += kerror;
01412          }
01413 #ifdef PNG_USER_MEM_SUPPORTED
01414          if (allocation_now != current_allocation)
01415             fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n",
01416                current_allocation-allocation_now);
01417          if (current_allocation != 0)
01418          {
01419             memory_infop pinfo = pinformation;
01420 
01421             fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n",
01422                current_allocation);
01423             while (pinfo != NULL)
01424             {
01425                fprintf(STDERR, " %lu bytes at %x\n", pinfo->size, 
01426                  (unsigned int) pinfo->pointer);
01427                pinfo = pinfo->next;
01428             }
01429          }
01430 #endif
01431       }
01432 #ifdef PNG_USER_MEM_SUPPORTED
01433          fprintf(STDERR, " Current memory allocation: %10d bytes\n",
01434             current_allocation);
01435          fprintf(STDERR, " Maximum memory allocation: %10d bytes\n",
01436             maximum_allocation);
01437          fprintf(STDERR, " Total   memory allocation: %10d bytes\n",
01438             total_allocation);
01439          fprintf(STDERR, "     Number of allocations: %10d\n",
01440             num_allocations);
01441 #endif
01442    }
01443    else
01444    {
01445       int i;
01446       for (i=0; i<3; ++i)
01447       {
01448          int kerror;
01449 #ifdef PNG_USER_MEM_SUPPORTED
01450          int allocation_now = current_allocation;
01451 #endif
01452          if (i == 1) status_dots_requested = 1;
01453          else if(verbose == 0)status_dots_requested = 0;
01454          if (i == 0 || verbose == 1 || ierror != 0)
01455             fprintf(STDERR, "Testing %s:",inname);
01456          kerror = test_one_file(inname, outname);
01457          if(kerror == 0)
01458          {
01459             if(verbose == 1 || i == 2)
01460             {
01461 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
01462                 int k;
01463 #endif
01464 #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
01465                 fprintf(STDERR, "\n PASS (%lu zero samples)\n",zero_samples);
01466 #else
01467                 fprintf(STDERR, " PASS\n");
01468 #endif
01469 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
01470                 for (k=0; k<256; k++)
01471                    if(filters_used[k])
01472                       fprintf(STDERR, " Filter %d was used %lu times\n",
01473                          k,filters_used[k]);
01474 #endif
01475 #if defined(PNG_TIME_RFC1123_SUPPORTED)
01476              if(tIME_chunk_present != 0)
01477                 fprintf(STDERR, " tIME = %s\n",tIME_string);
01478 #endif /* PNG_TIME_RFC1123_SUPPORTED */
01479             }
01480          }
01481          else
01482          {
01483             if(verbose == 0 && i != 2)
01484                fprintf(STDERR, "Testing %s:",inname);
01485             fprintf(STDERR, " FAIL\n");
01486             ierror += kerror;
01487          }
01488 #ifdef PNG_USER_MEM_SUPPORTED
01489          if (allocation_now != current_allocation)
01490              fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n",
01491                current_allocation-allocation_now);
01492          if (current_allocation != 0)
01493          {
01494              memory_infop pinfo = pinformation;
01495 
01496              fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n",
01497                 current_allocation);
01498              while (pinfo != NULL)
01499              {
01500                 fprintf(STDERR," %lu bytes at %x\n",
01501                    pinfo->size, (unsigned int)pinfo->pointer);
01502                 pinfo = pinfo->next;
01503              }
01504           }
01505 #endif
01506        }
01507 #ifdef PNG_USER_MEM_SUPPORTED
01508        fprintf(STDERR, " Current memory allocation: %10d bytes\n",
01509           current_allocation);
01510        fprintf(STDERR, " Maximum memory allocation: %10d bytes\n",
01511           maximum_allocation);
01512        fprintf(STDERR, " Total   memory allocation: %10d bytes\n",
01513           total_allocation);
01514        fprintf(STDERR, "     Number of allocations: %10d\n",
01515             num_allocations);
01516 #endif
01517    }
01518 
01519 #ifdef PNGTEST_TIMING
01520    t_stop = (float)clock();
01521    t_misc += (t_stop - t_start);
01522    t_start = t_stop;
01523    fprintf(STDERR," CPU time used = %.3f seconds",
01524       (t_misc+t_decode+t_encode)/(float)CLOCKS_PER_SEC);
01525    fprintf(STDERR," (decoding %.3f,\n",
01526       t_decode/(float)CLOCKS_PER_SEC);
01527    fprintf(STDERR,"        encoding %.3f ,",
01528       t_encode/(float)CLOCKS_PER_SEC);
01529    fprintf(STDERR," other %.3f seconds)\n\n",
01530       t_misc/(float)CLOCKS_PER_SEC);
01531 #endif
01532 
01533    if (ierror == 0)
01534       fprintf(STDERR, "libpng passes test\n");
01535    else
01536       fprintf(STDERR, "libpng FAILS test\n");
01537    return (int)(ierror != 0);
01538 }
01539 
01540 /* Generate a compiler error if there is an old png.h in the search path. */
01541 typedef version_1_2_5 your_png_h_is_not_version_1_2_5;