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


openhrp3
Author(s): AIST, General Robotix Inc., Nakamura Lab of Dept. of Mechano Informatics at University of Tokyo
autogenerated on Thu Apr 11 2019 03:30:18