Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
96 giacomo 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
79
static 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
91
static 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)
98
static int tIME_chunk_present=0;
99
static char tIME_string[30] = "no tIME chunk present in file";
100
#endif
101
 
102
static int verbose = 0;
103
 
104
int 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 */
115
static int status_pass=1;
116
static int status_dots_requested=0;
117
static int status_dots=1;
118
 
119
void
120
#ifdef PNG_1_0_X
121
PNGAPI
122
#endif
123
read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass);
124
void
125
#ifdef PNG_1_0_X
126
PNGAPI
127
#endif
128
read_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
       cprintf("\n Pass %d: ",pass);
134
       status_pass = pass;
135
       status_dots = 31;
136
    }
137
    status_dots--;
138
    if(status_dots == 0)
139
    {
140
       cprintf("\n         ");
141
       status_dots=30;
142
    }
143
    cprintf("r");
144
}
145
 
146
void
147
#ifdef PNG_1_0_X
148
PNGAPI
149
#endif
150
write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass);
151
void
152
#ifdef PNG_1_0_X
153
PNGAPI
154
#endif
155
write_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
    cprintf("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.) */
166
static png_uint_32 filters_used[256];
167
void
168
#ifdef PNG_1_0_X
169
PNGAPI
170
#endif
171
count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data);
172
void
173
#ifdef PNG_1_0_X
174
PNGAPI
175
#endif
176
count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data)
177
{
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
 
187
static png_uint_32 zero_samples;
188
 
189
void
190
#ifdef PNG_1_0_X
191
PNGAPI
192
#endif
193
count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data);
194
void
195
#ifdef PNG_1_0_X
196
PNGAPI
197
#endif
198
count_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
 
286
static 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
298
static void
299
pngtest_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
 
322
static void
323
pngtest_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)
364
static void
365
pngtest_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
381
static void
382
pngtest_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
 
401
static void
402
pngtest_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
 */
448
static void
449
pngtest_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
   cprintf("%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
 */
462
static void
463
pngtest_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. */
483
typedef struct memory_information
484
{
485
   png_uint_32               size;
486
   png_voidp                 pointer;
487
   struct memory_information FAR *next;
488
} memory_information;
489
typedef memory_information FAR *memory_infop;
490
 
491
static memory_infop pinformation = NULL;
492
static int current_allocation = 0;
493
static int maximum_allocation = 0;
494
static int total_allocation = 0;
495
static int num_allocations = 0;
496
 
497
png_voidp png_debug_malloc PNGARG((png_structp png_ptr, png_uint_32 size));
498
void png_debug_free PNGARG((png_structp png_ptr, png_voidp ptr));
499
 
500
png_voidp
501
png_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. */
536
void
537
png_debug_free(png_structp png_ptr, png_voidp ptr)
538
{
539
   if (png_ptr == NULL)
540
      cprintf("NULL pointer to png_debug_free.\n");
541
   if (ptr == 0)
542
   {
543
#if 0 /* This happens all the time. */
544
      cprintf("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
               cprintf("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
            cprintf("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
      cprintf("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 */
589
int
590
test_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
      cprintf("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
      cprintf("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
      cprintf("%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
      cprintf("%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
      cprintf("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
      cprintf("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
      cprintf("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
         cprintf("\nFiles %s and %s are of a different size\n",
1237
                 inname, outname);
1238
         if(wrote_question == 0)
1239
         {
1240
            cprintf("   Was %s written with the same maximum IDAT chunk size (%d bytes),",
1241
              inname,PNG_ZBUF_SIZE);
1242
            cprintf("\n   filtering heuristic (libpng default), compression");
1243
            cprintf(" level (zlib default),\n   and zlib version (%s)?\n\n",
1244
              ZLIB_VERSION);
1245
            wrote_question=1;
1246
         }
1247
         FCLOSE(fpin);
1248
         FCLOSE(fpout);
1249
         return (0);
1250
      }
1251
 
1252
      if (!num_in)
1253
         break;
1254
 
1255
      if (png_memcmp(inbuf, outbuf, num_in))
1256
      {
1257
         cprintf("\nFiles %s and %s are different\n", inname, outname);
1258
         if(wrote_question == 0)
1259
         {
1260
            cprintf("   Was %s written with the same maximum IDAT chunk size (%d bytes),",
1261
                 inname,PNG_ZBUF_SIZE);
1262
            cprintf("\n   filtering heuristic (libpng default), compression");
1263
            cprintf(" level (zlib default),\n   and zlib version (%s)?\n\n",
1264
              ZLIB_VERSION);
1265
            wrote_question=1;
1266
         }
1267
         FCLOSE(fpin);
1268
         FCLOSE(fpout);
1269
         return (0);
1270
      }
1271
   }
1272
 
1273
   FCLOSE(fpin);
1274
   FCLOSE(fpout);
1275
 
1276
   return (0);
1277
}
1278
 
1279
/* input and output filenames */
1280
#ifdef RISCOS
1281
static PNG_CONST char *inname = "pngtest/png";
1282
static PNG_CONST char *outname = "pngout/png";
1283
#else
1284
static PNG_CONST char *inname = "pngtest.png";
1285
static PNG_CONST char *outname = "pngout.png";
1286
#endif
1287
 
1288
int
1289
main(int argc, char *argv[])
1290
{
1291
   int multiple = 0;
1292
   int ierror = 0;
1293
 
1294
   cprintf("Testing libpng version %s\n", PNG_LIBPNG_VER_STRING);
1295
   cprintf("   with zlib   version %s\n", ZLIB_VERSION);
1296
   cprintf("%s",png_get_copyright(NULL));
1297
   /* Show the version of libpng used in building the library */
1298
   cprintf(" library (%lu):%s", png_access_version_number(),
1299
      png_get_header_version(NULL));
1300
   /* Show the version of libpng used in building the application */
1301
   cprintf(" pngtest (%lu):%s", (unsigned long)PNG_LIBPNG_VER,
1302
      PNG_HEADER_VERSION_STRING);
1303
   cprintf(" sizeof(png_struct)=%ld, sizeof(png_info)=%ld\n",
1304
                    (long)sizeof(png_struct), (long)sizeof(png_info));
1305
 
1306
   /* Do some consistency checking on the memory allocation settings, I'm
1307
      not sure this matters, but it is nice to know, the first of these
1308
      tests should be impossible because of the way the macros are set
1309
      in pngconf.h */
1310
#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K)
1311
      cprintf(" NOTE: Zlib compiled for max 64k, libpng not\n");
1312
#endif
1313
   /* I think the following can happen. */
1314
#if !defined(MAXSEG_64K) && defined(PNG_MAX_MALLOC_64K)
1315
      cprintf(" NOTE: libpng compiled for max 64k, zlib not\n");
1316
#endif
1317
 
1318
   if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING))
1319
   {
1320
      cprintf("Warning: versions are different between png.h and png.c\n");
1321
      cprintf("  png.h version: %s\n", PNG_LIBPNG_VER_STRING);
1322
      cprintf("  png.c version: %s\n\n", png_libpng_ver);
1323
      ++ierror;
1324
   }
1325
 
1326
   if (argc > 1)
1327
   {
1328
      if (strcmp(argv[1], "-m") == 0)
1329
      {
1330
         multiple = 1;
1331
         status_dots_requested = 0;
1332
      }
1333
      else if (strcmp(argv[1], "-mv") == 0 ||
1334
               strcmp(argv[1], "-vm") == 0 )
1335
      {
1336
         multiple = 1;
1337
         verbose = 1;
1338
         status_dots_requested = 1;
1339
      }
1340
      else if (strcmp(argv[1], "-v") == 0)
1341
      {
1342
         verbose = 1;
1343
         status_dots_requested = 1;
1344
         inname = argv[2];
1345
      }
1346
      else
1347
      {
1348
         inname = argv[1];
1349
         status_dots_requested = 0;
1350
      }
1351
   }
1352
 
1353
   if (!multiple && argc == 3+verbose)
1354
     outname = argv[2+verbose];
1355
 
1356
   if ((!multiple && argc > 3+verbose) || (multiple && argc < 2))
1357
   {
1358
     cprintf("usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n",
1359
        argv[0], argv[0]);
1360
     cprintf("  reads/writes one PNG file (without -m) or multiple files (-m)\n");
1361
     cprintf("  with -m %s is used as a temporary file\n", outname);
1362
     exit(1);
1363
   }
1364
 
1365
   if (multiple)
1366
   {
1367
      int i;
1368
#ifdef PNG_USER_MEM_SUPPORTED
1369
      int allocation_now = current_allocation;
1370
#endif
1371
      for (i=2; i<argc; ++i)
1372
      {
1373
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1374
         int k;
1375
#endif
1376
         int kerror;
1377
         cprintf("Testing %s:",argv[i]);
1378
         kerror = test_one_file(argv[i], outname);
1379
         if (kerror == 0)
1380
         {
1381
#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
1382
            cprintf("\n PASS (%lu zero samples)\n",zero_samples);
1383
#else
1384
            cprintf(" PASS\n");
1385
#endif
1386
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1387
            for (k=0; k<256; k++)
1388
               if(filters_used[k])
1389
                  cprintf(" Filter %d was used %lu times\n",
1390
                     k,filters_used[k]);
1391
#endif
1392
#if defined(PNG_TIME_RFC1123_SUPPORTED)
1393
         if(tIME_chunk_present != 0)
1394
            cprintf(" tIME = %s\n",tIME_string);
1395
         tIME_chunk_present = 0;
1396
#endif /* PNG_TIME_RFC1123_SUPPORTED */
1397
         }
1398
         else
1399
         {
1400
            cprintf(" FAIL\n");
1401
            ierror += kerror;
1402
         }
1403
#ifdef PNG_USER_MEM_SUPPORTED
1404
         if (allocation_now != current_allocation)
1405
            cprintf("MEMORY ERROR: %d bytes lost\n",
1406
               current_allocation-allocation_now);
1407
         if (current_allocation != 0)
1408
         {
1409
            memory_infop pinfo = pinformation;
1410
 
1411
            cprintf("MEMORY ERROR: %d bytes still allocated\n",
1412
               current_allocation);
1413
            while (pinfo != NULL)
1414
            {
1415
               cprintf(" %lu bytes at %x\n", pinfo->size,
1416
                 (unsigned int) pinfo->pointer);
1417
               pinfo = pinfo->next;
1418
            }
1419
         }
1420
#endif
1421
      }
1422
#ifdef PNG_USER_MEM_SUPPORTED
1423
         cprintf(" Current memory allocation: %10d bytes\n",
1424
            current_allocation);
1425
         cprintf(" Maximum memory allocation: %10d bytes\n",
1426
            maximum_allocation);
1427
         cprintf(" Total   memory allocation: %10d bytes\n",
1428
            total_allocation);
1429
         cprintf("     Number of allocations: %10d\n",
1430
            num_allocations);
1431
#endif
1432
   }
1433
   else
1434
   {
1435
      int i;
1436
      for (i=0; i<3; ++i)
1437
      {
1438
         int kerror;
1439
#ifdef PNG_USER_MEM_SUPPORTED
1440
         int allocation_now = current_allocation;
1441
#endif
1442
         if (i == 1) status_dots_requested = 1;
1443
         else if(verbose == 0)status_dots_requested = 0;
1444
         if (i == 0 || verbose == 1 || ierror != 0)
1445
            cprintf("Testing %s:",inname);
1446
         kerror = test_one_file(inname, outname);
1447
         if(kerror == 0)
1448
         {
1449
            if(verbose == 1 || i == 2)
1450
            {
1451
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1452
                int k;
1453
#endif
1454
#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
1455
                cprintf("\n PASS (%lu zero samples)\n",zero_samples);
1456
#else
1457
                cprintf(" PASS\n");
1458
#endif
1459
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1460
                for (k=0; k<256; k++)
1461
                   if(filters_used[k])
1462
                      cprintf(" Filter %d was used %lu times\n",
1463
                         k,filters_used[k]);
1464
#endif
1465
#if defined(PNG_TIME_RFC1123_SUPPORTED)
1466
             if(tIME_chunk_present != 0)
1467
                cprintf(" tIME = %s\n",tIME_string);
1468
#endif /* PNG_TIME_RFC1123_SUPPORTED */
1469
            }
1470
         }
1471
         else
1472
         {
1473
            if(verbose == 0 && i != 2)
1474
               cprintf("Testing %s:",inname);
1475
            cprintf(" FAIL\n");
1476
            ierror += kerror;
1477
         }
1478
#ifdef PNG_USER_MEM_SUPPORTED
1479
         if (allocation_now != current_allocation)
1480
             cprintf("MEMORY ERROR: %d bytes lost\n",
1481
               current_allocation-allocation_now);
1482
         if (current_allocation != 0)
1483
         {
1484
             memory_infop pinfo = pinformation;
1485
 
1486
             cprintf("MEMORY ERROR: %d bytes still allocated\n",
1487
                current_allocation);
1488
             while (pinfo != NULL)
1489
             {
1490
                cprintf(" %lu bytes at %x\n",
1491
                   pinfo->size, (unsigned int)pinfo->pointer);
1492
                pinfo = pinfo->next;
1493
             }
1494
          }
1495
#endif
1496
       }
1497
#ifdef PNG_USER_MEM_SUPPORTED
1498
       cprintf(" Current memory allocation: %10d bytes\n",
1499
          current_allocation);
1500
       cprintf(" Maximum memory allocation: %10d bytes\n",
1501
          maximum_allocation);
1502
       cprintf(" Total   memory allocation: %10d bytes\n",
1503
          total_allocation);
1504
       cprintf("     Number of allocations: %10d\n",
1505
            num_allocations);
1506
#endif
1507
   }
1508
 
1509
#ifdef PNGTEST_TIMING
1510
   t_stop = (float)clock();
1511
   t_misc += (t_stop - t_start);
1512
   t_start = t_stop;
1513
   cprintf(" CPU time used = %.3f seconds",
1514
      (t_misc+t_decode+t_encode)/(float)CLOCKS_PER_SEC);
1515
   cprintf(" (decoding %.3f,\n",
1516
      t_decode/(float)CLOCKS_PER_SEC);
1517
   cprintf("        encoding %.3f ,",
1518
      t_encode/(float)CLOCKS_PER_SEC);
1519
   cprintf(" other %.3f seconds)\n\n",
1520
      t_misc/(float)CLOCKS_PER_SEC);
1521
#endif
1522
 
1523
   if (ierror == 0)
1524
      cprintf("libpng passes test\n");
1525
   else
1526
      cprintf("libpng FAILS test\n");
1527
   return (int)(ierror != 0);
1528
}
1529
 
1530
/* Generate a compiler error if there is an old png.h in the search path. */
1531
typedef version_1_2_5 your_png_h_is_not_version_1_2_5;