Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
 
2
/* pngtest.c - a simple test program to test libpng
3
 *
4
 * libpng 1.2.8 - December 3, 2004
5
 * For conditions of distribution and use, see copyright notice in png.h
6
 * Copyright (c) 1998-2004 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
#include "png.h"
32
 
33
#if defined(_WIN32_WCE)
34
#  if _WIN32_WCE < 211
35
     __error__ (f|w)printf functions are not supported on old WindowsCE.;
36
#  endif
37
#  include <windows.h>
38
#  include <stdlib.h>
39
#  define READFILE(file, data, length, check) \
40
     if (ReadFile(file, data, length, &check,NULL)) check = 0
41
#  define WRITEFILE(file, data, length, check)) \
42
     if (WriteFile(file, data, length, &check, NULL)) check = 0
43
#  define FCLOSE(file) CloseHandle(file)
44
#else
45
#  include <stdio.h>
46
#  include <stdlib.h>
47
#  include <assert.h>
48
#  define READFILE(file, data, length, check) \
49
     check=(png_size_t)fread(data,(png_size_t)1,length,file)
50
#  define WRITEFILE(file, data, length, check) \
51
     check=(png_size_t)fwrite(data,(png_size_t)1, length, file)
52
#  define FCLOSE(file) fclose(file)
53
#endif
54
 
55
#if defined(PNG_NO_STDIO)
56
#  if defined(_WIN32_WCE)
57
     typedef HANDLE                png_FILE_p;
58
#  else
59
     typedef FILE                * png_FILE_p;
60
#  endif
61
#endif
62
 
63
/* Makes pngtest verbose so we can find problems (needs to be before png.h) */
64
#ifndef PNG_DEBUG
65
#  define PNG_DEBUG 0
66
#endif
67
 
68
#if !PNG_DEBUG
69
#  define SINGLE_ROWBUF_ALLOC  /* makes buffer overruns easier to nail */
70
#endif
71
 
72
/* Turn on CPU timing
73
#define PNGTEST_TIMING
74
*/
75
 
76
#ifdef PNG_NO_FLOATING_POINT_SUPPORTED
77
#undef PNGTEST_TIMING
78
#endif
79
 
80
#ifdef PNGTEST_TIMING
81
static float t_start, t_stop, t_decode, t_encode, t_misc;
82
#include <time.h>
83
#endif
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_UINT_31_MAX) 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
 
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_UINT_31_MAX || 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.) */
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
   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
 */
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
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
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
      /* Disable malloc_fn and free_fn */
514
      memory_infop pinfo;
515
      png_set_mem_fn(png_ptr, NULL, NULL, NULL);
516
      pinfo = (memory_infop)png_malloc(png_ptr,
517
         (png_uint_32)png_sizeof (*pinfo));
518
      pinfo->size = size;
519
      current_allocation += size;
520
      total_allocation += size;
521
      num_allocations ++;
522
      if (current_allocation > maximum_allocation)
523
         maximum_allocation = current_allocation;
524
      pinfo->pointer = (png_voidp)png_malloc(png_ptr, size);
525
      /* Restore malloc_fn and free_fn */
526
      png_set_mem_fn(png_ptr, png_voidp_NULL, (png_malloc_ptr)png_debug_malloc,
527
         (png_free_ptr)png_debug_free);
528
      if (size != 0 && pinfo->pointer == NULL)
529
      {
530
         current_allocation -= size;
531
         total_allocation -= size;
532
         png_error(png_ptr,
533
           "out of memory in pngtest->png_debug_malloc.");
534
      }
535
      pinfo->next = pinformation;
536
      pinformation = pinfo;
537
      /* Make sure the caller isn't assuming zeroed memory. */
538
      png_memset(pinfo->pointer, 0xdd, pinfo->size);
539
      if(verbose)
540
         printf("png_malloc %lu bytes at %x\n",size,pinfo->pointer);
541
      assert(pinfo->size != 12345678);
542
      return (png_voidp)(pinfo->pointer);
543
   }
544
}
545
 
546
/* Free a pointer.  It is removed from the list at the same time. */
547
void
548
png_debug_free(png_structp png_ptr, png_voidp ptr)
549
{
550
   if (png_ptr == NULL)
551
      fprintf(STDERR, "NULL pointer to png_debug_free.\n");
552
   if (ptr == 0)
553
   {
554
#if 0 /* This happens all the time. */
555
      fprintf(STDERR, "WARNING: freeing NULL pointer\n");
556
#endif
557
      return;
558
   }
559
 
560
   /* Unlink the element from the list. */
561
   {
562
      memory_infop FAR *ppinfo = &pinformation;
563
      for (;;)
564
      {
565
         memory_infop pinfo = *ppinfo;
566
         if (pinfo->pointer == ptr)
567
         {
568
            *ppinfo = pinfo->next;
569
            current_allocation -= pinfo->size;
570
            if (current_allocation < 0)
571
               fprintf(STDERR, "Duplicate free of memory\n");
572
            /* We must free the list element too, but first kill
573
               the memory that is to be freed. */
574
            png_memset(ptr, 0x55, pinfo->size);
575
            png_free_default(png_ptr, pinfo);
576
            pinfo=NULL;
577
            break;
578
         }
579
         if (pinfo->next == NULL)
580
         {
581
            fprintf(STDERR, "Pointer %x not found\n", (unsigned int)ptr);
582
            break;
583
         }
584
         ppinfo = &pinfo->next;
585
      }
586
   }
587
 
588
   /* Finally free the data. */
589
   if(verbose)
590
      printf("Freeing %x\n",ptr);
591
   png_free_default(png_ptr, ptr);
592
   ptr=NULL;
593
}
594
#endif /* PNG_USER_MEM_SUPPORTED && PNG_DEBUG */
595
/* END of code to test memory allocation/deallocation */
596
 
597
/* Test one file */
598
int
599
test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
600
{
601
   static png_FILE_p fpin;
602
   static png_FILE_p fpout;  /* "static" prevents setjmp corruption */
603
   png_structp read_ptr;
604
   png_infop read_info_ptr, end_info_ptr;
605
#ifdef PNG_WRITE_SUPPORTED
606
   png_structp write_ptr;
607
   png_infop write_info_ptr;
608
   png_infop write_end_info_ptr;
609
#else
610
   png_structp write_ptr = NULL;
611
   png_infop write_info_ptr = NULL;
612
   png_infop write_end_info_ptr = NULL;
613
#endif
614
   png_bytep row_buf;
615
   png_uint_32 y;
616
   png_uint_32 width, height;
617
   int num_pass, pass;
618
   int bit_depth, color_type;
619
#ifdef PNG_SETJMP_SUPPORTED
620
#ifdef USE_FAR_KEYWORD
621
   jmp_buf jmpbuf;
622
#endif
623
#endif
624
 
625
#if defined(_WIN32_WCE)
626
   TCHAR path[MAX_PATH];
627
#endif
628
   char inbuf[256], outbuf[256];
629
 
630
   row_buf = NULL;
631
 
632
#if defined(_WIN32_WCE)
633
   MultiByteToWideChar(CP_ACP, 0, inname, -1, path, MAX_PATH);
634
   if ((fpin = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
635
#else
636
   if ((fpin = fopen(inname, "rb")) == NULL)
637
#endif
638
   {
639
      fprintf(STDERR, "Could not find input file %s\n", inname);
640
      return (1);
641
   }
642
 
643
#if defined(_WIN32_WCE)
644
   MultiByteToWideChar(CP_ACP, 0, outname, -1, path, MAX_PATH);
645
   if ((fpout = CreateFile(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL)) == INVALID_HANDLE_VALUE)
646
#else
647
   if ((fpout = fopen(outname, "wb")) == NULL)
648
#endif
649
   {
650
      fprintf(STDERR, "Could not open output file %s\n", outname);
651
      FCLOSE(fpin);
652
      return (1);
653
   }
654
 
655
   png_debug(0, "Allocating read and write structures\n");
656
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
657
   read_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, png_voidp_NULL,
658
      png_error_ptr_NULL, png_error_ptr_NULL, png_voidp_NULL,
659
      (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free);
660
#else
661
   read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL,
662
      png_error_ptr_NULL, png_error_ptr_NULL);
663
#endif
664
#if defined(PNG_NO_STDIO)
665
   png_set_error_fn(read_ptr, (png_voidp)inname, pngtest_error,
666
       pngtest_warning);
667
#endif
668
#ifdef PNG_WRITE_SUPPORTED
669
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
670
   write_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, png_voidp_NULL,
671
      png_error_ptr_NULL, png_error_ptr_NULL, png_voidp_NULL,
672
      (png_malloc_ptr)png_debug_malloc, (png_free_ptr)png_debug_free);
673
#else
674
   write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, png_voidp_NULL,
675
      png_error_ptr_NULL, png_error_ptr_NULL);
676
#endif
677
#if defined(PNG_NO_STDIO)
678
   png_set_error_fn(write_ptr, (png_voidp)inname, pngtest_error,
679
       pngtest_warning);
680
#endif
681
#endif
682
   png_debug(0, "Allocating read_info, write_info and end_info structures\n");
683
   read_info_ptr = png_create_info_struct(read_ptr);
684
   end_info_ptr = png_create_info_struct(read_ptr);
685
#ifdef PNG_WRITE_SUPPORTED
686
   write_info_ptr = png_create_info_struct(write_ptr);
687
   write_end_info_ptr = png_create_info_struct(write_ptr);
688
#endif
689
 
690
#ifdef PNG_SETJMP_SUPPORTED
691
   png_debug(0, "Setting jmpbuf for read struct\n");
692
#ifdef USE_FAR_KEYWORD
693
   if (setjmp(jmpbuf))
694
#else
695
   if (setjmp(png_jmpbuf(read_ptr)))
696
#endif
697
   {
698
      fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname);
699
      if (row_buf)
700
         png_free(read_ptr, row_buf);
701
      png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
702
#ifdef PNG_WRITE_SUPPORTED
703
      png_destroy_info_struct(write_ptr, &write_end_info_ptr);
704
      png_destroy_write_struct(&write_ptr, &write_info_ptr);
705
#endif
706
      FCLOSE(fpin);
707
      FCLOSE(fpout);
708
      return (1);
709
   }
710
#ifdef USE_FAR_KEYWORD
711
   png_memcpy(png_jmpbuf(read_ptr),jmpbuf,png_sizeof(jmp_buf));
712
#endif
713
 
714
#ifdef PNG_WRITE_SUPPORTED
715
   png_debug(0, "Setting jmpbuf for write struct\n");
716
#ifdef USE_FAR_KEYWORD
717
   if (setjmp(jmpbuf))
718
#else
719
   if (setjmp(png_jmpbuf(write_ptr)))
720
#endif
721
   {
722
      fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname);
723
      png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
724
      png_destroy_info_struct(write_ptr, &write_end_info_ptr);
725
#ifdef PNG_WRITE_SUPPORTED
726
      png_destroy_write_struct(&write_ptr, &write_info_ptr);
727
#endif
728
      FCLOSE(fpin);
729
      FCLOSE(fpout);
730
      return (1);
731
   }
732
#ifdef USE_FAR_KEYWORD
733
   png_memcpy(png_jmpbuf(write_ptr),jmpbuf,png_sizeof(jmp_buf));
734
#endif
735
#endif
736
#endif
737
 
738
   png_debug(0, "Initializing input and output streams\n");
739
#if !defined(PNG_NO_STDIO)
740
   png_init_io(read_ptr, fpin);
741
#  ifdef PNG_WRITE_SUPPORTED
742
   png_init_io(write_ptr, fpout);
743
#  endif
744
#else
745
   png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data);
746
#  ifdef PNG_WRITE_SUPPORTED
747
   png_set_write_fn(write_ptr, (png_voidp)fpout,  pngtest_write_data,
748
#    if defined(PNG_WRITE_FLUSH_SUPPORTED)
749
      pngtest_flush);
750
#    else
751
      NULL);
752
#    endif
753
#  endif
754
#endif
755
   if(status_dots_requested == 1)
756
   {
757
#ifdef PNG_WRITE_SUPPORTED
758
      png_set_write_status_fn(write_ptr, write_row_callback);
759
#endif
760
      png_set_read_status_fn(read_ptr, read_row_callback);
761
   }
762
   else
763
   {
764
#ifdef PNG_WRITE_SUPPORTED
765
      png_set_write_status_fn(write_ptr, png_write_status_ptr_NULL);
766
#endif
767
      png_set_read_status_fn(read_ptr, png_read_status_ptr_NULL);
768
   }
769
 
770
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
771
   {
772
     int i;
773
     for(i=0; i<256; i++)
774
        filters_used[i]=0;
775
     png_set_read_user_transform_fn(read_ptr, count_filters);
776
   }
777
#endif
778
#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
779
   zero_samples=0;
780
   png_set_write_user_transform_fn(write_ptr, count_zero_samples);
781
#endif
782
 
783
#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
784
#  ifndef PNG_HANDLE_CHUNK_ALWAYS
785
#    define PNG_HANDLE_CHUNK_ALWAYS       3
786
#  endif
787
   png_set_keep_unknown_chunks(read_ptr, PNG_HANDLE_CHUNK_ALWAYS,
788
      png_bytep_NULL, 0);
789
#endif
790
#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
791
#  ifndef PNG_HANDLE_CHUNK_IF_SAFE
792
#    define PNG_HANDLE_CHUNK_IF_SAFE      2
793
#  endif
794
   png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_IF_SAFE,
795
      png_bytep_NULL, 0);
796
#endif
797
 
798
   png_debug(0, "Reading info struct\n");
799
   png_read_info(read_ptr, read_info_ptr);
800
 
801
   png_debug(0, "Transferring info struct\n");
802
   {
803
      int interlace_type, compression_type, filter_type;
804
 
805
      if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth,
806
          &color_type, &interlace_type, &compression_type, &filter_type))
807
      {
808
         png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth,
809
#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
810
            color_type, interlace_type, compression_type, filter_type);
811
#else
812
            color_type, PNG_INTERLACE_NONE, compression_type, filter_type);
813
#endif
814
      }
815
   }
816
#if defined(PNG_FIXED_POINT_SUPPORTED)
817
#if defined(PNG_cHRM_SUPPORTED)
818
   {
819
      png_fixed_point white_x, white_y, red_x, red_y, green_x, green_y, blue_x,
820
         blue_y;
821
      if (png_get_cHRM_fixed(read_ptr, read_info_ptr, &white_x, &white_y, &red_x,
822
         &red_y, &green_x, &green_y, &blue_x, &blue_y))
823
      {
824
         png_set_cHRM_fixed(write_ptr, write_info_ptr, white_x, white_y, red_x,
825
            red_y, green_x, green_y, blue_x, blue_y);
826
      }
827
   }
828
#endif
829
#if defined(PNG_gAMA_SUPPORTED)
830
   {
831
      png_fixed_point gamma;
832
 
833
      if (png_get_gAMA_fixed(read_ptr, read_info_ptr, &gamma))
834
      {
835
         png_set_gAMA_fixed(write_ptr, write_info_ptr, gamma);
836
      }
837
   }
838
#endif
839
#else /* Use floating point versions */
840
#if defined(PNG_FLOATING_POINT_SUPPORTED)
841
#if defined(PNG_cHRM_SUPPORTED)
842
   {
843
      double white_x, white_y, red_x, red_y, green_x, green_y, blue_x,
844
         blue_y;
845
      if (png_get_cHRM(read_ptr, read_info_ptr, &white_x, &white_y, &red_x,
846
         &red_y, &green_x, &green_y, &blue_x, &blue_y))
847
      {
848
         png_set_cHRM(write_ptr, write_info_ptr, white_x, white_y, red_x,
849
            red_y, green_x, green_y, blue_x, blue_y);
850
      }
851
   }
852
#endif
853
#if defined(PNG_gAMA_SUPPORTED)
854
   {
855
      double gamma;
856
 
857
      if (png_get_gAMA(read_ptr, read_info_ptr, &gamma))
858
      {
859
         png_set_gAMA(write_ptr, write_info_ptr, gamma);
860
      }
861
   }
862
#endif
863
#endif /* floating point */
864
#endif /* fixed point */
865
#if defined(PNG_iCCP_SUPPORTED)
866
   {
867
      png_charp name;
868
      png_charp profile;
869
      png_uint_32 proflen;
870
      int compression_type;
871
 
872
      if (png_get_iCCP(read_ptr, read_info_ptr, &name, &compression_type,
873
                      &profile, &proflen))
874
      {
875
         png_set_iCCP(write_ptr, write_info_ptr, name, compression_type,
876
                      profile, proflen);
877
      }
878
   }
879
#endif
880
#if defined(PNG_sRGB_SUPPORTED)
881
   {
882
      int intent;
883
 
884
      if (png_get_sRGB(read_ptr, read_info_ptr, &intent))
885
      {
886
         png_set_sRGB(write_ptr, write_info_ptr, intent);
887
      }
888
   }
889
#endif
890
   {
891
      png_colorp palette;
892
      int num_palette;
893
 
894
      if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette))
895
      {
896
         png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette);
897
      }
898
   }
899
#if defined(PNG_bKGD_SUPPORTED)
900
   {
901
      png_color_16p background;
902
 
903
      if (png_get_bKGD(read_ptr, read_info_ptr, &background))
904
      {
905
         png_set_bKGD(write_ptr, write_info_ptr, background);
906
      }
907
   }
908
#endif
909
#if defined(PNG_hIST_SUPPORTED)
910
   {
911
      png_uint_16p hist;
912
 
913
      if (png_get_hIST(read_ptr, read_info_ptr, &hist))
914
      {
915
         png_set_hIST(write_ptr, write_info_ptr, hist);
916
      }
917
   }
918
#endif
919
#if defined(PNG_oFFs_SUPPORTED)
920
   {
921
      png_int_32 offset_x, offset_y;
922
      int unit_type;
923
 
924
      if (png_get_oFFs(read_ptr, read_info_ptr,&offset_x,&offset_y,&unit_type))
925
      {
926
         png_set_oFFs(write_ptr, write_info_ptr, offset_x, offset_y, unit_type);
927
      }
928
   }
929
#endif
930
#if defined(PNG_pCAL_SUPPORTED)
931
   {
932
      png_charp purpose, units;
933
      png_charpp params;
934
      png_int_32 X0, X1;
935
      int type, nparams;
936
 
937
      if (png_get_pCAL(read_ptr, read_info_ptr, &purpose, &X0, &X1, &type,
938
         &nparams, &units, &params))
939
      {
940
         png_set_pCAL(write_ptr, write_info_ptr, purpose, X0, X1, type,
941
            nparams, units, params);
942
      }
943
   }
944
#endif
945
#if defined(PNG_pHYs_SUPPORTED)
946
   {
947
      png_uint_32 res_x, res_y;
948
      int unit_type;
949
 
950
      if (png_get_pHYs(read_ptr, read_info_ptr, &res_x, &res_y, &unit_type))
951
      {
952
         png_set_pHYs(write_ptr, write_info_ptr, res_x, res_y, unit_type);
953
      }
954
   }
955
#endif
956
#if defined(PNG_sBIT_SUPPORTED)
957
   {
958
      png_color_8p sig_bit;
959
 
960
      if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit))
961
      {
962
         png_set_sBIT(write_ptr, write_info_ptr, sig_bit);
963
      }
964
   }
965
#endif
966
#if defined(PNG_sCAL_SUPPORTED)
967
#ifdef PNG_FLOATING_POINT_SUPPORTED
968
   {
969
      int unit;
970
      double scal_width, scal_height;
971
 
972
      if (png_get_sCAL(read_ptr, read_info_ptr, &unit, &scal_width,
973
         &scal_height))
974
      {
975
         png_set_sCAL(write_ptr, write_info_ptr, unit, scal_width, scal_height);
976
      }
977
   }
978
#else
979
#ifdef PNG_FIXED_POINT_SUPPORTED
980
   {
981
      int unit;
982
      png_charp scal_width, scal_height;
983
 
984
      if (png_get_sCAL_s(read_ptr, read_info_ptr, &unit, &scal_width,
985
          &scal_height))
986
      {
987
         png_set_sCAL_s(write_ptr, write_info_ptr, unit, scal_width, scal_height);
988
      }
989
   }
990
#endif
991
#endif
992
#endif
993
#if defined(PNG_TEXT_SUPPORTED)
994
   {
995
      png_textp text_ptr;
996
      int num_text;
997
 
998
      if (png_get_text(read_ptr, read_info_ptr, &text_ptr, &num_text) > 0)
999
      {
1000
         png_debug1(0, "Handling %d iTXt/tEXt/zTXt chunks\n", num_text);
1001
         png_set_text(write_ptr, write_info_ptr, text_ptr, num_text);
1002
      }
1003
   }
1004
#endif
1005
#if defined(PNG_tIME_SUPPORTED)
1006
   {
1007
      png_timep mod_time;
1008
 
1009
      if (png_get_tIME(read_ptr, read_info_ptr, &mod_time))
1010
      {
1011
         png_set_tIME(write_ptr, write_info_ptr, mod_time);
1012
#if defined(PNG_TIME_RFC1123_SUPPORTED)
1013
         /* we have to use png_strcpy instead of "=" because the string
1014
            pointed to by png_convert_to_rfc1123() gets free'ed before
1015
            we use it */
1016
         png_strcpy(tIME_string,png_convert_to_rfc1123(read_ptr, mod_time));
1017
         tIME_chunk_present++;
1018
#endif /* PNG_TIME_RFC1123_SUPPORTED */
1019
      }
1020
   }
1021
#endif
1022
#if defined(PNG_tRNS_SUPPORTED)
1023
   {
1024
      png_bytep trans;
1025
      int num_trans;
1026
      png_color_16p trans_values;
1027
 
1028
      if (png_get_tRNS(read_ptr, read_info_ptr, &trans, &num_trans,
1029
         &trans_values))
1030
      {
1031
         png_set_tRNS(write_ptr, write_info_ptr, trans, num_trans,
1032
            trans_values);
1033
      }
1034
   }
1035
#endif
1036
#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
1037
   {
1038
      png_unknown_chunkp unknowns;
1039
      int num_unknowns = (int)png_get_unknown_chunks(read_ptr, read_info_ptr,
1040
         &unknowns);
1041
      if (num_unknowns)
1042
      {
1043
         png_size_t i;
1044
         png_set_unknown_chunks(write_ptr, write_info_ptr, unknowns,
1045
           num_unknowns);
1046
         /* copy the locations from the read_info_ptr.  The automatically
1047
            generated locations in write_info_ptr are wrong because we
1048
            haven't written anything yet */
1049
         for (i = 0; i < (png_size_t)num_unknowns; i++)
1050
           png_set_unknown_chunk_location(write_ptr, write_info_ptr, i,
1051
             unknowns[i].location);
1052
      }
1053
   }
1054
#endif
1055
 
1056
#ifdef PNG_WRITE_SUPPORTED
1057
   png_debug(0, "\nWriting info struct\n");
1058
 
1059
/* If we wanted, we could write info in two steps:
1060
   png_write_info_before_PLTE(write_ptr, write_info_ptr);
1061
 */
1062
   png_write_info(write_ptr, write_info_ptr);
1063
#endif
1064
 
1065
#ifdef SINGLE_ROWBUF_ALLOC
1066
   png_debug(0, "\nAllocating row buffer...");
1067
   row_buf = (png_bytep)png_malloc(read_ptr,
1068
      png_get_rowbytes(read_ptr, read_info_ptr));
1069
   png_debug1(0, "0x%08lx\n\n", (unsigned long)row_buf);
1070
#endif /* SINGLE_ROWBUF_ALLOC */
1071
   png_debug(0, "Writing row data\n");
1072
 
1073
#if defined(PNG_READ_INTERLACING_SUPPORTED) || \
1074
  defined(PNG_WRITE_INTERLACING_SUPPORTED)
1075
   num_pass = png_set_interlace_handling(read_ptr);
1076
#  ifdef PNG_WRITE_SUPPORTED
1077
   png_set_interlace_handling(write_ptr);
1078
#  endif
1079
#else
1080
   num_pass=1;
1081
#endif
1082
 
1083
#ifdef PNGTEST_TIMING
1084
   t_stop = (float)clock();
1085
   t_misc += (t_stop - t_start);
1086
   t_start = t_stop;
1087
#endif
1088
   for (pass = 0; pass < num_pass; pass++)
1089
   {
1090
      png_debug1(0, "Writing row data for pass %d\n",pass);
1091
      for (y = 0; y < height; y++)
1092
      {
1093
#ifndef SINGLE_ROWBUF_ALLOC
1094
         png_debug2(0, "\nAllocating row buffer (pass %d, y = %ld)...", pass,y);
1095
         row_buf = (png_bytep)png_malloc(read_ptr,
1096
            png_get_rowbytes(read_ptr, read_info_ptr));
1097
         png_debug2(0, "0x%08lx (%ld bytes)\n", (unsigned long)row_buf,
1098
            png_get_rowbytes(read_ptr, read_info_ptr));
1099
#endif /* !SINGLE_ROWBUF_ALLOC */
1100
         png_read_rows(read_ptr, (png_bytepp)&row_buf, png_bytepp_NULL, 1);
1101
 
1102
#ifdef PNG_WRITE_SUPPORTED
1103
#ifdef PNGTEST_TIMING
1104
         t_stop = (float)clock();
1105
         t_decode += (t_stop - t_start);
1106
         t_start = t_stop;
1107
#endif
1108
         png_write_rows(write_ptr, (png_bytepp)&row_buf, 1);
1109
#ifdef PNGTEST_TIMING
1110
         t_stop = (float)clock();
1111
         t_encode += (t_stop - t_start);
1112
         t_start = t_stop;
1113
#endif
1114
#endif /* PNG_WRITE_SUPPORTED */
1115
 
1116
#ifndef SINGLE_ROWBUF_ALLOC
1117
         png_debug2(0, "Freeing row buffer (pass %d, y = %ld)\n\n", pass, y);
1118
         png_free(read_ptr, row_buf);
1119
#endif /* !SINGLE_ROWBUF_ALLOC */
1120
      }
1121
   }
1122
 
1123
#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
1124
   png_free_data(read_ptr, read_info_ptr, PNG_FREE_UNKN, -1);
1125
#endif
1126
#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
1127
   png_free_data(write_ptr, write_info_ptr, PNG_FREE_UNKN, -1);
1128
#endif
1129
 
1130
   png_debug(0, "Reading and writing end_info data\n");
1131
 
1132
   png_read_end(read_ptr, end_info_ptr);
1133
#if defined(PNG_TEXT_SUPPORTED)
1134
   {
1135
      png_textp text_ptr;
1136
      int num_text;
1137
 
1138
      if (png_get_text(read_ptr, end_info_ptr, &text_ptr, &num_text) > 0)
1139
      {
1140
         png_debug1(0, "Handling %d iTXt/tEXt/zTXt chunks\n", num_text);
1141
         png_set_text(write_ptr, write_end_info_ptr, text_ptr, num_text);
1142
      }
1143
   }
1144
#endif
1145
#if defined(PNG_tIME_SUPPORTED)
1146
   {
1147
      png_timep mod_time;
1148
 
1149
      if (png_get_tIME(read_ptr, end_info_ptr, &mod_time))
1150
      {
1151
         png_set_tIME(write_ptr, write_end_info_ptr, mod_time);
1152
#if defined(PNG_TIME_RFC1123_SUPPORTED)
1153
         /* we have to use png_strcpy instead of "=" because the string
1154
            pointed to by png_convert_to_rfc1123() gets free'ed before
1155
            we use it */
1156
         png_strcpy(tIME_string,png_convert_to_rfc1123(read_ptr, mod_time));
1157
         tIME_chunk_present++;
1158
#endif /* PNG_TIME_RFC1123_SUPPORTED */
1159
      }
1160
   }
1161
#endif
1162
#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
1163
   {
1164
      png_unknown_chunkp unknowns;
1165
      int num_unknowns;
1166
      num_unknowns = (int)png_get_unknown_chunks(read_ptr, end_info_ptr,
1167
         &unknowns);
1168
      if (num_unknowns)
1169
      {
1170
         png_size_t i;
1171
         png_set_unknown_chunks(write_ptr, write_end_info_ptr, unknowns,
1172
           num_unknowns);
1173
         /* copy the locations from the read_info_ptr.  The automatically
1174
            generated locations in write_end_info_ptr are wrong because we
1175
            haven't written the end_info yet */
1176
         for (i = 0; i < (png_size_t)num_unknowns; i++)
1177
           png_set_unknown_chunk_location(write_ptr, write_end_info_ptr, i,
1178
             unknowns[i].location);
1179
      }
1180
   }
1181
#endif
1182
#ifdef PNG_WRITE_SUPPORTED
1183
   png_write_end(write_ptr, write_end_info_ptr);
1184
#endif
1185
 
1186
#ifdef PNG_EASY_ACCESS_SUPPORTED
1187
   if(verbose)
1188
   {
1189
      png_uint_32 iwidth, iheight;
1190
      iwidth = png_get_image_width(write_ptr, write_info_ptr);
1191
      iheight = png_get_image_height(write_ptr, write_info_ptr);
1192
      fprintf(STDERR, "Image width = %lu, height = %lu\n",
1193
         iwidth, iheight);
1194
   }
1195
#endif
1196
 
1197
   png_debug(0, "Destroying data structs\n");
1198
#ifdef SINGLE_ROWBUF_ALLOC
1199
   png_debug(1, "destroying row_buf for read_ptr\n");
1200
   png_free(read_ptr, row_buf);
1201
   row_buf=NULL;
1202
#endif /* SINGLE_ROWBUF_ALLOC */
1203
   png_debug(1, "destroying read_ptr, read_info_ptr, end_info_ptr\n");
1204
   png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
1205
#ifdef PNG_WRITE_SUPPORTED
1206
   png_debug(1, "destroying write_end_info_ptr\n");
1207
   png_destroy_info_struct(write_ptr, &write_end_info_ptr);
1208
   png_debug(1, "destroying write_ptr, write_info_ptr\n");
1209
   png_destroy_write_struct(&write_ptr, &write_info_ptr);
1210
#endif
1211
   png_debug(0, "Destruction complete.\n");
1212
 
1213
   FCLOSE(fpin);
1214
   FCLOSE(fpout);
1215
 
1216
   png_debug(0, "Opening files for comparison\n");
1217
#if defined(_WIN32_WCE)
1218
   MultiByteToWideChar(CP_ACP, 0, inname, -1, path, MAX_PATH);
1219
   if ((fpin = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
1220
#else
1221
   if ((fpin = fopen(inname, "rb")) == NULL)
1222
#endif
1223
   {
1224
      fprintf(STDERR, "Could not find file %s\n", inname);
1225
      return (1);
1226
   }
1227
 
1228
#if defined(_WIN32_WCE)
1229
   MultiByteToWideChar(CP_ACP, 0, outname, -1, path, MAX_PATH);
1230
   if ((fpout = CreateFile(path, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
1231
#else
1232
   if ((fpout = fopen(outname, "rb")) == NULL)
1233
#endif
1234
   {
1235
      fprintf(STDERR, "Could not find file %s\n", outname);
1236
      FCLOSE(fpin);
1237
      return (1);
1238
   }
1239
 
1240
   for(;;)
1241
   {
1242
      png_size_t num_in, num_out;
1243
 
1244
      READFILE(fpin, inbuf, 1, num_in);
1245
      READFILE(fpout, outbuf, 1, num_out);
1246
 
1247
      if (num_in != num_out)
1248
      {
1249
         fprintf(STDERR, "\nFiles %s and %s are of a different size\n",
1250
                 inname, outname);
1251
         if(wrote_question == 0)
1252
         {
1253
            fprintf(STDERR,
1254
         "   Was %s written with the same maximum IDAT chunk size (%d bytes),",
1255
              inname,PNG_ZBUF_SIZE);
1256
            fprintf(STDERR,
1257
              "\n   filtering heuristic (libpng default), compression");
1258
            fprintf(STDERR,
1259
              " level (zlib default),\n   and zlib version (%s)?\n\n",
1260
              ZLIB_VERSION);
1261
            wrote_question=1;
1262
         }
1263
         FCLOSE(fpin);
1264
         FCLOSE(fpout);
1265
         return (0);
1266
      }
1267
 
1268
      if (!num_in)
1269
         break;
1270
 
1271
      if (png_memcmp(inbuf, outbuf, num_in))
1272
      {
1273
         fprintf(STDERR, "\nFiles %s and %s are different\n", inname, outname);
1274
         if(wrote_question == 0)
1275
         {
1276
            fprintf(STDERR,
1277
         "   Was %s written with the same maximum IDAT chunk size (%d bytes),",
1278
                 inname,PNG_ZBUF_SIZE);
1279
            fprintf(STDERR,
1280
              "\n   filtering heuristic (libpng default), compression");
1281
            fprintf(STDERR,
1282
              " level (zlib default),\n   and zlib version (%s)?\n\n",
1283
              ZLIB_VERSION);
1284
            wrote_question=1;
1285
         }
1286
         FCLOSE(fpin);
1287
         FCLOSE(fpout);
1288
         return (0);
1289
      }
1290
   }
1291
 
1292
   FCLOSE(fpin);
1293
   FCLOSE(fpout);
1294
 
1295
   return (0);
1296
}
1297
 
1298
/* input and output filenames */
1299
#ifdef RISCOS
1300
static PNG_CONST char *inname = "pngtest/png";
1301
static PNG_CONST char *outname = "pngout/png";
1302
#else
1303
static PNG_CONST char *inname = "pngtest.png";
1304
static PNG_CONST char *outname = "pngout.png";
1305
#endif
1306
 
1307
int
1308
main(int argc, char *argv[])
1309
{
1310
   int multiple = 0;
1311
   int ierror = 0;
1312
 
1313
   fprintf(STDERR, "Testing libpng version %s\n", PNG_LIBPNG_VER_STRING);
1314
   fprintf(STDERR, "   with zlib   version %s\n", ZLIB_VERSION);
1315
   fprintf(STDERR,"%s",png_get_copyright(NULL));
1316
   /* Show the version of libpng used in building the library */
1317
   fprintf(STDERR," library (%lu):%s", png_access_version_number(),
1318
      png_get_header_version(NULL));
1319
   /* Show the version of libpng used in building the application */
1320
   fprintf(STDERR," pngtest (%lu):%s", (unsigned long)PNG_LIBPNG_VER,
1321
      PNG_HEADER_VERSION_STRING);
1322
   fprintf(STDERR," png_sizeof(png_struct)=%ld, png_sizeof(png_info)=%ld\n",
1323
                    (long)png_sizeof(png_struct), (long)png_sizeof(png_info));
1324
 
1325
   /* Do some consistency checking on the memory allocation settings, I'm
1326
      not sure this matters, but it is nice to know, the first of these
1327
      tests should be impossible because of the way the macros are set
1328
      in pngconf.h */
1329
#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K)
1330
      fprintf(STDERR, " NOTE: Zlib compiled for max 64k, libpng not\n");
1331
#endif
1332
   /* I think the following can happen. */
1333
#if !defined(MAXSEG_64K) && defined(PNG_MAX_MALLOC_64K)
1334
      fprintf(STDERR, " NOTE: libpng compiled for max 64k, zlib not\n");
1335
#endif
1336
 
1337
   if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING))
1338
   {
1339
      fprintf(STDERR,
1340
         "Warning: versions are different between png.h and png.c\n");
1341
      fprintf(STDERR, "  png.h version: %s\n", PNG_LIBPNG_VER_STRING);
1342
      fprintf(STDERR, "  png.c version: %s\n\n", png_libpng_ver);
1343
      ++ierror;
1344
   }
1345
 
1346
   if (argc > 1)
1347
   {
1348
      if (strcmp(argv[1], "-m") == 0)
1349
      {
1350
         multiple = 1;
1351
         status_dots_requested = 0;
1352
      }
1353
      else if (strcmp(argv[1], "-mv") == 0 ||
1354
               strcmp(argv[1], "-vm") == 0 )
1355
      {
1356
         multiple = 1;
1357
         verbose = 1;
1358
         status_dots_requested = 1;
1359
      }
1360
      else if (strcmp(argv[1], "-v") == 0)
1361
      {
1362
         verbose = 1;
1363
         status_dots_requested = 1;
1364
         inname = argv[2];
1365
      }
1366
      else
1367
      {
1368
         inname = argv[1];
1369
         status_dots_requested = 0;
1370
      }
1371
   }
1372
 
1373
   if (!multiple && argc == 3+verbose)
1374
     outname = argv[2+verbose];
1375
 
1376
   if ((!multiple && argc > 3+verbose) || (multiple && argc < 2))
1377
   {
1378
     fprintf(STDERR,
1379
       "usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n",
1380
        argv[0], argv[0]);
1381
     fprintf(STDERR,
1382
       "  reads/writes one PNG file (without -m) or multiple files (-m)\n");
1383
     fprintf(STDERR,
1384
       "  with -m %s is used as a temporary file\n", outname);
1385
     exit(1);
1386
   }
1387
 
1388
   if (multiple)
1389
   {
1390
      int i;
1391
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
1392
      int allocation_now = current_allocation;
1393
#endif
1394
      for (i=2; i<argc; ++i)
1395
      {
1396
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1397
         int k;
1398
#endif
1399
         int kerror;
1400
         fprintf(STDERR, "Testing %s:",argv[i]);
1401
         kerror = test_one_file(argv[i], outname);
1402
         if (kerror == 0)
1403
         {
1404
#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
1405
            fprintf(STDERR, "\n PASS (%lu zero samples)\n",zero_samples);
1406
#else
1407
            fprintf(STDERR, " PASS\n");
1408
#endif
1409
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1410
            for (k=0; k<256; k++)
1411
               if(filters_used[k])
1412
                  fprintf(STDERR, " Filter %d was used %lu times\n",
1413
                     k,filters_used[k]);
1414
#endif
1415
#if defined(PNG_TIME_RFC1123_SUPPORTED)
1416
         if(tIME_chunk_present != 0)
1417
            fprintf(STDERR, " tIME = %s\n",tIME_string);
1418
         tIME_chunk_present = 0;
1419
#endif /* PNG_TIME_RFC1123_SUPPORTED */
1420
         }
1421
         else
1422
         {
1423
            fprintf(STDERR, " FAIL\n");
1424
            ierror += kerror;
1425
         }
1426
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
1427
         if (allocation_now != current_allocation)
1428
            fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n",
1429
               current_allocation-allocation_now);
1430
         if (current_allocation != 0)
1431
         {
1432
            memory_infop pinfo = pinformation;
1433
 
1434
            fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n",
1435
               current_allocation);
1436
            while (pinfo != NULL)
1437
            {
1438
               fprintf(STDERR, " %lu bytes at %x\n", pinfo->size, 
1439
                 (unsigned int) pinfo->pointer);
1440
               pinfo = pinfo->next;
1441
            }
1442
         }
1443
#endif
1444
      }
1445
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
1446
         fprintf(STDERR, " Current memory allocation: %10d bytes\n",
1447
            current_allocation);
1448
         fprintf(STDERR, " Maximum memory allocation: %10d bytes\n",
1449
            maximum_allocation);
1450
         fprintf(STDERR, " Total   memory allocation: %10d bytes\n",
1451
            total_allocation);
1452
         fprintf(STDERR, "     Number of allocations: %10d\n",
1453
            num_allocations);
1454
#endif
1455
   }
1456
   else
1457
   {
1458
      int i;
1459
      for (i=0; i<3; ++i)
1460
      {
1461
         int kerror;
1462
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
1463
         int allocation_now = current_allocation;
1464
#endif
1465
         if (i == 1) status_dots_requested = 1;
1466
         else if(verbose == 0)status_dots_requested = 0;
1467
         if (i == 0 || verbose == 1 || ierror != 0)
1468
            fprintf(STDERR, "Testing %s:",inname);
1469
         kerror = test_one_file(inname, outname);
1470
         if(kerror == 0)
1471
         {
1472
            if(verbose == 1 || i == 2)
1473
            {
1474
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1475
                int k;
1476
#endif
1477
#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
1478
                fprintf(STDERR, "\n PASS (%lu zero samples)\n",zero_samples);
1479
#else
1480
                fprintf(STDERR, " PASS\n");
1481
#endif
1482
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1483
                for (k=0; k<256; k++)
1484
                   if(filters_used[k])
1485
                      fprintf(STDERR, " Filter %d was used %lu times\n",
1486
                         k,filters_used[k]);
1487
#endif
1488
#if defined(PNG_TIME_RFC1123_SUPPORTED)
1489
             if(tIME_chunk_present != 0)
1490
                fprintf(STDERR, " tIME = %s\n",tIME_string);
1491
#endif /* PNG_TIME_RFC1123_SUPPORTED */
1492
            }
1493
         }
1494
         else
1495
         {
1496
            if(verbose == 0 && i != 2)
1497
               fprintf(STDERR, "Testing %s:",inname);
1498
            fprintf(STDERR, " FAIL\n");
1499
            ierror += kerror;
1500
         }
1501
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
1502
         if (allocation_now != current_allocation)
1503
             fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n",
1504
               current_allocation-allocation_now);
1505
         if (current_allocation != 0)
1506
         {
1507
             memory_infop pinfo = pinformation;
1508
 
1509
             fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n",
1510
                current_allocation);
1511
             while (pinfo != NULL)
1512
             {
1513
                fprintf(STDERR," %lu bytes at %x\n",
1514
                   pinfo->size, (unsigned int)pinfo->pointer);
1515
                pinfo = pinfo->next;
1516
             }
1517
          }
1518
#endif
1519
       }
1520
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
1521
       fprintf(STDERR, " Current memory allocation: %10d bytes\n",
1522
          current_allocation);
1523
       fprintf(STDERR, " Maximum memory allocation: %10d bytes\n",
1524
          maximum_allocation);
1525
       fprintf(STDERR, " Total   memory allocation: %10d bytes\n",
1526
          total_allocation);
1527
       fprintf(STDERR, "     Number of allocations: %10d\n",
1528
            num_allocations);
1529
#endif
1530
   }
1531
 
1532
#ifdef PNGTEST_TIMING
1533
   t_stop = (float)clock();
1534
   t_misc += (t_stop - t_start);
1535
   t_start = t_stop;
1536
   fprintf(STDERR," CPU time used = %.3f seconds",
1537
      (t_misc+t_decode+t_encode)/(float)CLOCKS_PER_SEC);
1538
   fprintf(STDERR," (decoding %.3f,\n",
1539
      t_decode/(float)CLOCKS_PER_SEC);
1540
   fprintf(STDERR,"        encoding %.3f ,",
1541
      t_encode/(float)CLOCKS_PER_SEC);
1542
   fprintf(STDERR," other %.3f seconds)\n\n",
1543
      t_misc/(float)CLOCKS_PER_SEC);
1544
#endif
1545
 
1546
   if (ierror == 0)
1547
      fprintf(STDERR, "libpng passes test\n");
1548
   else
1549
      fprintf(STDERR, "libpng FAILS test\n");
1550
   return (int)(ierror != 0);
1551
}
1552
 
1553
/* Generate a compiler error if there is an old png.h in the search path. */
1554
typedef version_1_2_8 your_png_h_is_not_version_1_2_8;