source: trunk/third/libpng/pngtest.c @ 18166

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