~ppsspp/ppsspp/ppsspp_1.3.0

« back to all changes in this revision

Viewing changes to ext/native/ext/libpng/pngtest.c

  • Committer: Sérgio Benjamim
  • Date: 2017-01-02 00:12:05 UTC
  • Revision ID: sergio_br2@yahoo.com.br-20170102001205-cxbta9za203nmjwm
1.3.0 source (from ppsspp_1.3.0-r160.p5.l1762.a165.t83~56~ubuntu16.04.1.tar.xz).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/* pngtest.c - a simple test program to test libpng
 
3
 *
 
4
 * Last changed in libpng 1.5.25 [December 3, 2015]
 
5
 * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
 
6
 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
 
7
 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
 
8
 *
 
9
 * This code is released under the libpng license.
 
10
 * For conditions of distribution and use, see the disclaimer
 
11
 * and license in png.h
 
12
 *
 
13
 * This program reads in a PNG image, writes it out again, and then
 
14
 * compares the two files.  If the files are identical, this shows that
 
15
 * the basic chunk handling, filtering, and (de)compression code is working
 
16
 * properly.  It does not currently test all of the transforms, although
 
17
 * it probably should.
 
18
 *
 
19
 * The program will report "FAIL" in certain legitimate cases:
 
20
 * 1) when the compression level or filter selection method is changed.
 
21
 * 2) when the maximum IDAT size (PNG_ZBUF_SIZE in pngconf.h) is not 8192.
 
22
 * 3) unknown unsafe-to-copy ancillary chunks or unknown critical chunks
 
23
 *    exist in the input file.
 
24
 * 4) others not listed here...
 
25
 * In these cases, it is best to check with another tool such as "pngcheck"
 
26
 * to see what the differences between the two files are.
 
27
 *
 
28
 * If a filename is given on the command-line, then this file is used
 
29
 * for the input, rather than the default "pngtest.png".  This allows
 
30
 * testing a wide variety of files easily.  You can also test a number
 
31
 * of files at once by typing "pngtest -m file1.png file2.png ..."
 
32
 */
 
33
 
 
34
#define _POSIX_SOURCE 1
 
35
 
 
36
#include <stdio.h>
 
37
#include <stdlib.h>
 
38
#include <string.h>
 
39
 
 
40
/* Defined so I can write to a file on gui/windowing platforms */
 
41
/*  #define STDERR stderr  */
 
42
#define STDERR stdout   /* For DOS */
 
43
 
 
44
#include "png.h"
 
45
 
 
46
/* 1.6.1 added support for the configure test harness, which uses 77 to indicate
 
47
 * a skipped test, in earlier versions we need to succeed on a skipped test, so:
 
48
 */
 
49
#if PNG_LIBPNG_VER >= 10601 && defined(HAVE_CONFIG_H)
 
50
#  define SKIP 77
 
51
#else
 
52
#  define SKIP 0
 
53
#endif
 
54
 
 
55
/* Known chunks that exist in pngtest.png must be supported or pngtest will fail
 
56
 * simply as a result of re-ordering them.  This may be fixed in 1.7
 
57
 *
 
58
 * pngtest allocates a single row buffer for each row and overwrites it,
 
59
 * therefore if the write side doesn't support the writing of interlaced images
 
60
 * nothing can be done for an interlaced image (and the code below will fail
 
61
 * horribly trying to write extra data after writing garbage).
 
62
 */
 
63
#if defined PNG_READ_SUPPORTED && /* else nothing can be done */\
 
64
   defined PNG_READ_bKGD_SUPPORTED &&\
 
65
   defined PNG_READ_cHRM_SUPPORTED &&\
 
66
   defined PNG_READ_gAMA_SUPPORTED &&\
 
67
   defined PNG_READ_oFFs_SUPPORTED &&\
 
68
   defined PNG_READ_pCAL_SUPPORTED &&\
 
69
   defined PNG_READ_pHYs_SUPPORTED &&\
 
70
   defined PNG_READ_sBIT_SUPPORTED &&\
 
71
   defined PNG_READ_sCAL_SUPPORTED &&\
 
72
   defined PNG_READ_sRGB_SUPPORTED &&\
 
73
   defined PNG_READ_sPLT_SUPPORTED &&\
 
74
   defined PNG_READ_tEXt_SUPPORTED &&\
 
75
   defined PNG_READ_tIME_SUPPORTED &&\
 
76
   defined PNG_READ_zTXt_SUPPORTED &&\
 
77
   (defined PNG_WRITE_INTERLACING_SUPPORTED || PNG_LIBPNG_VER >= 10700)
 
78
 
 
79
#ifdef PNG_ZLIB_HEADER
 
80
#  include PNG_ZLIB_HEADER /* defined by pnglibconf.h from 1.7 */
 
81
#else
 
82
#  include "zlib.h"
 
83
#endif
 
84
 
 
85
/* Copied from pngpriv.h but only used in error messages below. */
 
86
#ifndef PNG_ZBUF_SIZE
 
87
#  define PNG_ZBUF_SIZE 8192
 
88
#endif
 
89
#define FCLOSE(file) fclose(file)
 
90
 
 
91
#ifndef PNG_STDIO_SUPPORTED
 
92
typedef FILE                * png_FILE_p;
 
93
#endif
 
94
 
 
95
/* Makes pngtest verbose so we can find problems. */
 
96
#ifndef PNG_DEBUG
 
97
#  define PNG_DEBUG 0
 
98
#endif
 
99
 
 
100
#if PNG_DEBUG > 1
 
101
#  define pngtest_debug(m)        ((void)fprintf(stderr, m "\n"))
 
102
#  define pngtest_debug1(m,p1)    ((void)fprintf(stderr, m "\n", p1))
 
103
#  define pngtest_debug2(m,p1,p2) ((void)fprintf(stderr, m "\n", p1, p2))
 
104
#else
 
105
#  define pngtest_debug(m)        ((void)0)
 
106
#  define pngtest_debug1(m,p1)    ((void)0)
 
107
#  define pngtest_debug2(m,p1,p2) ((void)0)
 
108
#endif
 
109
 
 
110
#if !PNG_DEBUG
 
111
#  define SINGLE_ROWBUF_ALLOC  /* Makes buffer overruns easier to nail */
 
112
#endif
 
113
 
 
114
#ifndef PNG_UNUSED
 
115
#  define PNG_UNUSED(param) (void)param;
 
116
#endif
 
117
 
 
118
/* Turn on CPU timing
 
119
#define PNGTEST_TIMING
 
120
*/
 
121
 
 
122
#ifndef PNG_FLOATING_POINT_SUPPORTED
 
123
#undef PNGTEST_TIMING
 
124
#endif
 
125
 
 
126
#ifdef PNGTEST_TIMING
 
127
static float t_start, t_stop, t_decode, t_encode, t_misc;
 
128
#include <time.h>
 
129
#endif
 
130
 
 
131
#ifdef PNG_TIME_RFC1123_SUPPORTED
 
132
#define PNG_tIME_STRING_LENGTH 29
 
133
static int tIME_chunk_present = 0;
 
134
static char tIME_string[PNG_tIME_STRING_LENGTH] = "tIME chunk is not present";
 
135
 
 
136
#if PNG_LIBPNG_VER < 10619
 
137
#define png_convert_to_rfc1123_buffer(ts, t) tIME_to_str(read_ptr, ts, t)
 
138
 
 
139
static int
 
140
tIME_to_str(png_structp png_ptr, png_charp ts, png_const_timep t)
 
141
{
 
142
    png_const_charp str = png_convert_to_rfc1123(png_ptr, t);
 
143
 
 
144
    if (str == NULL)
 
145
        return 0;
 
146
 
 
147
    strcpy(ts, str);
 
148
    return 1;
 
149
}
 
150
#endif /* older libpng */
 
151
#endif
 
152
 
 
153
static int verbose = 0;
 
154
static int strict = 0;
 
155
static int relaxed = 0;
 
156
static int unsupported_chunks = 0; /* chunk unsupported by libpng in input */
 
157
static int error_count = 0; /* count calls to png_error */
 
158
static int warning_count = 0; /* count calls to png_warning */
 
159
 
 
160
/* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */
 
161
#ifndef png_jmpbuf
 
162
#  define png_jmpbuf(png_ptr) png_ptr->jmpbuf
 
163
#endif
 
164
 
 
165
/* Defines for unknown chunk handling if required. */
 
166
#ifndef PNG_HANDLE_CHUNK_ALWAYS
 
167
#  define PNG_HANDLE_CHUNK_ALWAYS       3
 
168
#endif
 
169
#ifndef PNG_HANDLE_CHUNK_IF_SAFE
 
170
#  define PNG_HANDLE_CHUNK_IF_SAFE      2
 
171
#endif
 
172
 
 
173
/* Utility to save typing/errors, the argument must be a name */
 
174
#define MEMZERO(var) ((void)memset(&var, 0, sizeof var))
 
175
 
 
176
/* Example of using row callbacks to make a simple progress meter */
 
177
static int status_pass = 1;
 
178
static int status_dots_requested = 0;
 
179
static int status_dots = 1;
 
180
 
 
181
static void PNGCBAPI
 
182
read_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass)
 
183
{
 
184
   if (png_ptr == NULL || row_number > PNG_UINT_31_MAX)
 
185
      return;
 
186
 
 
187
   if (status_pass != pass)
 
188
   {
 
189
      fprintf(stdout, "\n Pass %d: ", pass);
 
190
      status_pass = pass;
 
191
      status_dots = 31;
 
192
   }
 
193
 
 
194
   status_dots--;
 
195
 
 
196
   if (status_dots == 0)
 
197
   {
 
198
      fprintf(stdout, "\n         ");
 
199
      status_dots=30;
 
200
   }
 
201
 
 
202
   fprintf(stdout, "r");
 
203
}
 
204
 
 
205
#ifdef PNG_WRITE_SUPPORTED
 
206
static void PNGCBAPI
 
207
write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass)
 
208
{
 
209
   if (png_ptr == NULL || row_number > PNG_UINT_31_MAX || pass > 7)
 
210
      return;
 
211
 
 
212
   fprintf(stdout, "w");
 
213
}
 
214
#endif
 
215
 
 
216
 
 
217
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
 
218
/* Example of using a user transform callback (doesn't do anything at present).
 
219
 */
 
220
static void PNGCBAPI
 
221
read_user_callback(png_structp png_ptr, png_row_infop row_info, png_bytep data)
 
222
{
 
223
   PNG_UNUSED(png_ptr)
 
224
   PNG_UNUSED(row_info)
 
225
   PNG_UNUSED(data)
 
226
}
 
227
#endif
 
228
 
 
229
#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
 
230
/* Example of using user transform callback (we don't transform anything,
 
231
 * but merely count the zero samples)
 
232
 */
 
233
 
 
234
static png_uint_32 zero_samples;
 
235
 
 
236
static void PNGCBAPI
 
237
count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data)
 
238
{
 
239
   png_bytep dp = data;
 
240
   if (png_ptr == NULL)
 
241
      return;
 
242
 
 
243
   /* Contents of row_info:
 
244
    *  png_uint_32 width      width of row
 
245
    *  png_uint_32 rowbytes   number of bytes in row
 
246
    *  png_byte color_type    color type of pixels
 
247
    *  png_byte bit_depth     bit depth of samples
 
248
    *  png_byte channels      number of channels (1-4)
 
249
    *  png_byte pixel_depth   bits per pixel (depth*channels)
 
250
    */
 
251
 
 
252
    /* Counts the number of zero samples (or zero pixels if color_type is 3 */
 
253
 
 
254
    if (row_info->color_type == 0 || row_info->color_type == 3)
 
255
    {
 
256
       int pos = 0;
 
257
       png_uint_32 n, nstop;
 
258
 
 
259
       for (n = 0, nstop=row_info->width; n<nstop; n++)
 
260
       {
 
261
          if (row_info->bit_depth == 1)
 
262
          {
 
263
             if (((*dp << pos++ ) & 0x80) == 0)
 
264
                zero_samples++;
 
265
 
 
266
             if (pos == 8)
 
267
             {
 
268
                pos = 0;
 
269
                dp++;
 
270
             }
 
271
          }
 
272
 
 
273
          if (row_info->bit_depth == 2)
 
274
          {
 
275
             if (((*dp << (pos+=2)) & 0xc0) == 0)
 
276
                zero_samples++;
 
277
 
 
278
             if (pos == 8)
 
279
             {
 
280
                pos = 0;
 
281
                dp++;
 
282
             }
 
283
          }
 
284
 
 
285
          if (row_info->bit_depth == 4)
 
286
          {
 
287
             if (((*dp << (pos+=4)) & 0xf0) == 0)
 
288
                zero_samples++;
 
289
 
 
290
             if (pos == 8)
 
291
             {
 
292
                pos = 0;
 
293
                dp++;
 
294
             }
 
295
          }
 
296
 
 
297
          if (row_info->bit_depth == 8)
 
298
             if (*dp++ == 0)
 
299
                zero_samples++;
 
300
 
 
301
          if (row_info->bit_depth == 16)
 
302
          {
 
303
             if ((*dp | *(dp+1)) == 0)
 
304
                zero_samples++;
 
305
             dp+=2;
 
306
          }
 
307
       }
 
308
    }
 
309
    else /* Other color types */
 
310
    {
 
311
       png_uint_32 n, nstop;
 
312
       int channel;
 
313
       int color_channels = row_info->channels;
 
314
       if (row_info->color_type > 3)
 
315
          color_channels--;
 
316
 
 
317
       for (n = 0, nstop=row_info->width; n<nstop; n++)
 
318
       {
 
319
          for (channel = 0; channel < color_channels; channel++)
 
320
          {
 
321
             if (row_info->bit_depth == 8)
 
322
                if (*dp++ == 0)
 
323
                   zero_samples++;
 
324
 
 
325
             if (row_info->bit_depth == 16)
 
326
             {
 
327
                if ((*dp | *(dp+1)) == 0)
 
328
                   zero_samples++;
 
329
 
 
330
                dp+=2;
 
331
             }
 
332
          }
 
333
          if (row_info->color_type > 3)
 
334
          {
 
335
             dp++;
 
336
             if (row_info->bit_depth == 16)
 
337
                dp++;
 
338
          }
 
339
       }
 
340
    }
 
341
}
 
342
#endif /* WRITE_USER_TRANSFORM */
 
343
 
 
344
#ifndef PNG_STDIO_SUPPORTED
 
345
/* START of code to validate stdio-free compilation */
 
346
/* These copies of the default read/write functions come from pngrio.c and
 
347
 * pngwio.c.  They allow "don't include stdio" testing of the library.
 
348
 * This is the function that does the actual reading of data.  If you are
 
349
 * not reading from a standard C stream, you should create a replacement
 
350
 * read_data function and use it at run time with png_set_read_fn(), rather
 
351
 * than changing the library.
 
352
 */
 
353
 
 
354
#ifdef PNG_IO_STATE_SUPPORTED
 
355
void
 
356
pngtest_check_io_state(png_structp png_ptr, png_size_t data_length,
 
357
   png_uint_32 io_op);
 
358
void
 
359
pngtest_check_io_state(png_structp png_ptr, png_size_t data_length,
 
360
   png_uint_32 io_op)
 
361
{
 
362
   png_uint_32 io_state = png_get_io_state(png_ptr);
 
363
   int err = 0;
 
364
 
 
365
   /* Check if the current operation (reading / writing) is as expected. */
 
366
   if ((io_state & PNG_IO_MASK_OP) != io_op)
 
367
      png_error(png_ptr, "Incorrect operation in I/O state");
 
368
 
 
369
   /* Check if the buffer size specific to the current location
 
370
    * (file signature / header / data / crc) is as expected.
 
371
    */
 
372
   switch (io_state & PNG_IO_MASK_LOC)
 
373
   {
 
374
   case PNG_IO_SIGNATURE:
 
375
      if (data_length > 8)
 
376
         err = 1;
 
377
      break;
 
378
   case PNG_IO_CHUNK_HDR:
 
379
      if (data_length != 8)
 
380
         err = 1;
 
381
      break;
 
382
   case PNG_IO_CHUNK_DATA:
 
383
      break;  /* no restrictions here */
 
384
   case PNG_IO_CHUNK_CRC:
 
385
      if (data_length != 4)
 
386
         err = 1;
 
387
      break;
 
388
   default:
 
389
      err = 1;  /* uninitialized */
 
390
   }
 
391
   if (err != 0)
 
392
      png_error(png_ptr, "Bad I/O state or buffer size");
 
393
}
 
394
#endif
 
395
 
 
396
static void PNGCBAPI
 
397
pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
 
398
{
 
399
   png_size_t check = 0;
 
400
   png_voidp io_ptr;
 
401
 
 
402
   /* fread() returns 0 on error, so it is OK to store this in a png_size_t
 
403
    * instead of an int, which is what fread() actually returns.
 
404
    */
 
405
   io_ptr = png_get_io_ptr(png_ptr);
 
406
   if (io_ptr != NULL)
 
407
   {
 
408
      check = fread(data, 1, length, (png_FILE_p)io_ptr);
 
409
   }
 
410
 
 
411
   if (check != length)
 
412
   {
 
413
      png_error(png_ptr, "Read Error");
 
414
   }
 
415
 
 
416
#ifdef PNG_IO_STATE_SUPPORTED
 
417
   pngtest_check_io_state(png_ptr, length, PNG_IO_READING);
 
418
#endif
 
419
}
 
420
 
 
421
#ifdef PNG_WRITE_FLUSH_SUPPORTED
 
422
static void PNGCBAPI
 
423
pngtest_flush(png_structp png_ptr)
 
424
{
 
425
   /* Do nothing; fflush() is said to be just a waste of energy. */
 
426
   PNG_UNUSED(png_ptr)   /* Stifle compiler warning */
 
427
}
 
428
#endif
 
429
 
 
430
/* This is the function that does the actual writing of data.  If you are
 
431
 * not writing to a standard C stream, you should create a replacement
 
432
 * write_data function and use it at run time with png_set_write_fn(), rather
 
433
 * than changing the library.
 
434
 */
 
435
static void PNGCBAPI
 
436
pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
 
437
{
 
438
   png_size_t check;
 
439
 
 
440
   check = fwrite(data, 1, length, (png_FILE_p)png_get_io_ptr(png_ptr));
 
441
 
 
442
   if (check != length)
 
443
   {
 
444
      png_error(png_ptr, "Write Error");
 
445
   }
 
446
 
 
447
#ifdef PNG_IO_STATE_SUPPORTED
 
448
   pngtest_check_io_state(png_ptr, length, PNG_IO_WRITING);
 
449
#endif
 
450
}
 
451
#endif /* !STDIO */
 
452
 
 
453
/* This function is called when there is a warning, but the library thinks
 
454
 * it can continue anyway.  Replacement functions don't have to do anything
 
455
 * here if you don't want to.  In the default configuration, png_ptr is
 
456
 * not used, but it is passed in case it may be useful.
 
457
 */
 
458
typedef struct
 
459
{
 
460
   PNG_CONST char *file_name;
 
461
}  pngtest_error_parameters;
 
462
 
 
463
static void PNGCBAPI
 
464
pngtest_warning(png_structp png_ptr, png_const_charp message)
 
465
{
 
466
   PNG_CONST char *name = "UNKNOWN (ERROR!)";
 
467
   pngtest_error_parameters *test =
 
468
      (pngtest_error_parameters*)png_get_error_ptr(png_ptr);
 
469
 
 
470
   ++warning_count;
 
471
 
 
472
   if (test != NULL && test->file_name != NULL)
 
473
      name = test->file_name;
 
474
 
 
475
   fprintf(STDERR, "%s: libpng warning: %s\n", name, message);
 
476
}
 
477
 
 
478
/* This is the default error handling function.  Note that replacements for
 
479
 * this function MUST NOT RETURN, or the program will likely crash.  This
 
480
 * function is used by default, or if the program supplies NULL for the
 
481
 * error function pointer in png_set_error_fn().
 
482
 */
 
483
static void PNGCBAPI
 
484
pngtest_error(png_structp png_ptr, png_const_charp message)
 
485
{
 
486
   ++error_count;
 
487
 
 
488
   pngtest_warning(png_ptr, message);
 
489
   /* We can return because png_error calls the default handler, which is
 
490
    * actually OK in this case.
 
491
    */
 
492
}
 
493
 
 
494
/* END of code to validate stdio-free compilation */
 
495
 
 
496
/* START of code to validate memory allocation and deallocation */
 
497
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
 
498
 
 
499
/* Allocate memory.  For reasonable files, size should never exceed
 
500
 * 64K.  However, zlib may allocate more than 64K if you don't tell
 
501
 * it not to.  See zconf.h and png.h for more information.  zlib does
 
502
 * need to allocate exactly 64K, so whatever you call here must
 
503
 * have the ability to do that.
 
504
 *
 
505
 * This piece of code can be compiled to validate max 64K allocations
 
506
 * by setting MAXSEG_64K in zlib zconf.h *or* PNG_MAX_MALLOC_64K.
 
507
 */
 
508
typedef struct memory_information
 
509
{
 
510
   png_alloc_size_t          size;
 
511
   png_voidp                 pointer;
 
512
   struct memory_information *next;
 
513
} memory_information;
 
514
typedef memory_information *memory_infop;
 
515
 
 
516
static memory_infop pinformation = NULL;
 
517
static int current_allocation = 0;
 
518
static int maximum_allocation = 0;
 
519
static int total_allocation = 0;
 
520
static int num_allocations = 0;
 
521
 
 
522
png_voidp PNGCBAPI png_debug_malloc PNGARG((png_structp png_ptr,
 
523
    png_alloc_size_t size));
 
524
void PNGCBAPI png_debug_free PNGARG((png_structp png_ptr, png_voidp ptr));
 
525
 
 
526
png_voidp
 
527
PNGCBAPI png_debug_malloc(png_structp png_ptr, png_alloc_size_t size)
 
528
{
 
529
 
 
530
   /* png_malloc has already tested for NULL; png_create_struct calls
 
531
    * png_debug_malloc directly, with png_ptr == NULL which is OK
 
532
    */
 
533
 
 
534
   if (size == 0)
 
535
      return (NULL);
 
536
 
 
537
   /* This calls the library allocator twice, once to get the requested
 
538
      buffer and once to get a new free list entry. */
 
539
   {
 
540
      /* Disable malloc_fn and free_fn */
 
541
      memory_infop pinfo;
 
542
      png_set_mem_fn(png_ptr, NULL, NULL, NULL);
 
543
      pinfo = (memory_infop)png_malloc(png_ptr,
 
544
         (sizeof *pinfo));
 
545
      pinfo->size = size;
 
546
      current_allocation += size;
 
547
      total_allocation += size;
 
548
      num_allocations ++;
 
549
 
 
550
      if (current_allocation > maximum_allocation)
 
551
         maximum_allocation = current_allocation;
 
552
 
 
553
      pinfo->pointer = png_malloc(png_ptr, size);
 
554
      /* Restore malloc_fn and free_fn */
 
555
 
 
556
      png_set_mem_fn(png_ptr,
 
557
          NULL, png_debug_malloc, png_debug_free);
 
558
 
 
559
      if (size != 0 && pinfo->pointer == NULL)
 
560
      {
 
561
         current_allocation -= size;
 
562
         total_allocation -= size;
 
563
         png_error(png_ptr,
 
564
           "out of memory in pngtest->png_debug_malloc");
 
565
      }
 
566
 
 
567
      pinfo->next = pinformation;
 
568
      pinformation = pinfo;
 
569
      /* Make sure the caller isn't assuming zeroed memory. */
 
570
      memset(pinfo->pointer, 0xdd, pinfo->size);
 
571
 
 
572
      if (verbose != 0)
 
573
         printf("png_malloc %lu bytes at %p\n", (unsigned long)size,
 
574
            pinfo->pointer);
 
575
 
 
576
      return (png_voidp)(pinfo->pointer);
 
577
   }
 
578
}
 
579
 
 
580
/* Free a pointer.  It is removed from the list at the same time. */
 
581
void PNGCBAPI
 
582
png_debug_free(png_structp png_ptr, png_voidp ptr)
 
583
{
 
584
   if (png_ptr == NULL)
 
585
      fprintf(STDERR, "NULL pointer to png_debug_free.\n");
 
586
 
 
587
   if (ptr == 0)
 
588
   {
 
589
#if 0 /* This happens all the time. */
 
590
      fprintf(STDERR, "WARNING: freeing NULL pointer\n");
 
591
#endif
 
592
      return;
 
593
   }
 
594
 
 
595
   /* Unlink the element from the list. */
 
596
   if (pinformation != NULL)
 
597
   {
 
598
      memory_infop *ppinfo = &pinformation;
 
599
 
 
600
      for (;;)
 
601
      {
 
602
         memory_infop pinfo = *ppinfo;
 
603
 
 
604
         if (pinfo->pointer == ptr)
 
605
         {
 
606
            *ppinfo = pinfo->next;
 
607
            current_allocation -= pinfo->size;
 
608
            if (current_allocation < 0)
 
609
               fprintf(STDERR, "Duplicate free of memory\n");
 
610
            /* We must free the list element too, but first kill
 
611
               the memory that is to be freed. */
 
612
            memset(ptr, 0x55, pinfo->size);
 
613
            free(pinfo);
 
614
            pinfo = NULL;
 
615
            break;
 
616
         }
 
617
 
 
618
         if (pinfo->next == NULL)
 
619
         {
 
620
            fprintf(STDERR, "Pointer %p not found\n", ptr);
 
621
            break;
 
622
         }
 
623
 
 
624
         ppinfo = &pinfo->next;
 
625
      }
 
626
   }
 
627
 
 
628
   /* Finally free the data. */
 
629
   if (verbose != 0)
 
630
      printf("Freeing %p\n", ptr);
 
631
 
 
632
   if (ptr != NULL)
 
633
      free(ptr);
 
634
   ptr = NULL;
 
635
}
 
636
#endif /* USER_MEM && DEBUG */
 
637
/* END of code to test memory allocation/deallocation */
 
638
 
 
639
 
 
640
#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
 
641
/* Demonstration of user chunk support of the sTER and vpAg chunks */
 
642
 
 
643
/* (sTER is a public chunk not yet known by libpng.  vpAg is a private
 
644
chunk used in ImageMagick to store "virtual page" size).  */
 
645
 
 
646
static struct user_chunk_data
 
647
{
 
648
   png_const_infop info_ptr;
 
649
   png_uint_32     vpAg_width, vpAg_height;
 
650
   png_byte        vpAg_units;
 
651
   png_byte        sTER_mode;
 
652
   int             location[2];
 
653
}
 
654
user_chunk_data;
 
655
 
 
656
/* Used for location and order; zero means nothing. */
 
657
#define have_sTER   0x01
 
658
#define have_vpAg   0x02
 
659
#define before_PLTE 0x10
 
660
#define before_IDAT 0x20
 
661
#define after_IDAT  0x40
 
662
 
 
663
static void
 
664
init_callback_info(png_const_infop info_ptr)
 
665
{
 
666
   MEMZERO(user_chunk_data);
 
667
   user_chunk_data.info_ptr = info_ptr;
 
668
}
 
669
 
 
670
static int
 
671
set_location(png_structp png_ptr, struct user_chunk_data *data, int what)
 
672
{
 
673
   int location;
 
674
 
 
675
   if ((data->location[0] & what) != 0 || (data->location[1] & what) != 0)
 
676
      return 0; /* already have one of these */
 
677
 
 
678
   /* Find where we are (the code below zeroes info_ptr to indicate that the
 
679
    * chunks before the first IDAT have been read.)
 
680
    */
 
681
   if (data->info_ptr == NULL) /* after IDAT */
 
682
      location = what | after_IDAT;
 
683
 
 
684
   else if (png_get_valid(png_ptr, data->info_ptr, PNG_INFO_PLTE) != 0)
 
685
      location = what | before_IDAT;
 
686
 
 
687
   else
 
688
      location = what | before_PLTE;
 
689
 
 
690
   if (data->location[0] == 0)
 
691
      data->location[0] = location;
 
692
 
 
693
   else
 
694
      data->location[1] = location;
 
695
 
 
696
   return 1; /* handled */
 
697
}
 
698
 
 
699
static int PNGCBAPI
 
700
read_user_chunk_callback(png_struct *png_ptr, png_unknown_chunkp chunk)
 
701
{
 
702
   struct user_chunk_data *my_user_chunk_data =
 
703
      (struct user_chunk_data*)png_get_user_chunk_ptr(png_ptr);
 
704
 
 
705
   if (my_user_chunk_data == NULL)
 
706
      png_error(png_ptr, "lost user chunk pointer");
 
707
 
 
708
   /* Return one of the following:
 
709
    *    return (-n);  chunk had an error
 
710
    *    return (0);  did not recognize
 
711
    *    return (n);  success
 
712
    *
 
713
    * The unknown chunk structure contains the chunk data:
 
714
    * png_byte name[5];
 
715
    * png_byte *data;
 
716
    * png_size_t size;
 
717
    *
 
718
    * Note that libpng has already taken care of the CRC handling.
 
719
    */
 
720
 
 
721
   if (chunk->name[0] == 115 && chunk->name[1] ==  84 &&     /* s  T */
 
722
       chunk->name[2] ==  69 && chunk->name[3] ==  82)       /* E  R */
 
723
      {
 
724
         /* Found sTER chunk */
 
725
         if (chunk->size != 1)
 
726
            return (-1); /* Error return */
 
727
 
 
728
         if (chunk->data[0] != 0 && chunk->data[0] != 1)
 
729
            return (-1);  /* Invalid mode */
 
730
 
 
731
         if (set_location(png_ptr, my_user_chunk_data, have_sTER) != 0)
 
732
         {
 
733
            my_user_chunk_data->sTER_mode=chunk->data[0];
 
734
            return (1);
 
735
         }
 
736
 
 
737
         else
 
738
            return (0); /* duplicate sTER - give it to libpng */
 
739
      }
 
740
 
 
741
   if (chunk->name[0] != 118 || chunk->name[1] != 112 ||    /* v  p */
 
742
       chunk->name[2] !=  65 || chunk->name[3] != 103)      /* A  g */
 
743
      return (0); /* Did not recognize */
 
744
 
 
745
   /* Found ImageMagick vpAg chunk */
 
746
 
 
747
   if (chunk->size != 9)
 
748
      return (-1); /* Error return */
 
749
 
 
750
   if (set_location(png_ptr, my_user_chunk_data, have_vpAg) == 0)
 
751
      return (0);  /* duplicate vpAg */
 
752
 
 
753
   my_user_chunk_data->vpAg_width = png_get_uint_31(png_ptr, chunk->data);
 
754
   my_user_chunk_data->vpAg_height = png_get_uint_31(png_ptr, chunk->data + 4);
 
755
   my_user_chunk_data->vpAg_units = chunk->data[8];
 
756
 
 
757
   return (1);
 
758
}
 
759
 
 
760
#ifdef PNG_WRITE_SUPPORTED
 
761
static void
 
762
write_sTER_chunk(png_structp write_ptr)
 
763
{
 
764
   png_byte sTER[5] = {115,  84,  69,  82, '\0'};
 
765
 
 
766
   if (verbose != 0)
 
767
      fprintf(STDERR, "\n stereo mode = %d\n", user_chunk_data.sTER_mode);
 
768
 
 
769
   png_write_chunk(write_ptr, sTER, &user_chunk_data.sTER_mode, 1);
 
770
}
 
771
 
 
772
static void
 
773
write_vpAg_chunk(png_structp write_ptr)
 
774
{
 
775
   png_byte vpAg[5] = {118, 112,  65, 103, '\0'};
 
776
 
 
777
   png_byte vpag_chunk_data[9];
 
778
 
 
779
   if (verbose != 0)
 
780
      fprintf(STDERR, " vpAg = %lu x %lu, units = %d\n",
 
781
        (unsigned long)user_chunk_data.vpAg_width,
 
782
        (unsigned long)user_chunk_data.vpAg_height,
 
783
        user_chunk_data.vpAg_units);
 
784
 
 
785
   png_save_uint_32(vpag_chunk_data, user_chunk_data.vpAg_width);
 
786
   png_save_uint_32(vpag_chunk_data + 4, user_chunk_data.vpAg_height);
 
787
   vpag_chunk_data[8] = user_chunk_data.vpAg_units;
 
788
   png_write_chunk(write_ptr, vpAg, vpag_chunk_data, 9);
 
789
}
 
790
 
 
791
static void
 
792
write_chunks(png_structp write_ptr, int location)
 
793
{
 
794
   int i;
 
795
 
 
796
   /* Notice that this preserves the original chunk order, however chunks
 
797
    * intercepted by the callback will be written *after* chunks passed to
 
798
    * libpng.  This will actually reverse a pair of sTER chunks or a pair of
 
799
    * vpAg chunks, resulting in an error later.  This is not worth worrying
 
800
    * about - the chunks should not be duplicated!
 
801
    */
 
802
   for (i=0; i<2; ++i)
 
803
   {
 
804
      if (user_chunk_data.location[i] == (location | have_sTER))
 
805
         write_sTER_chunk(write_ptr);
 
806
 
 
807
      else if (user_chunk_data.location[i] == (location | have_vpAg))
 
808
         write_vpAg_chunk(write_ptr);
 
809
   }
 
810
}
 
811
#endif /* WRITE */
 
812
#else /* !READ_USER_CHUNKS */
 
813
#  define write_chunks(pp,loc) ((void)0)
 
814
#endif
 
815
/* END of code to demonstrate user chunk support */
 
816
 
 
817
/* START of code to check that libpng has the required text support; this only
 
818
 * checks for the write support because if read support is missing the chunk
 
819
 * will simply not be reported back to pngtest.
 
820
 */
 
821
#ifdef PNG_TEXT_SUPPORTED
 
822
static void
 
823
pngtest_check_text_support(png_structp png_ptr, png_textp text_ptr,
 
824
   int num_text)
 
825
{
 
826
   while (num_text > 0)
 
827
   {
 
828
      switch (text_ptr[--num_text].compression)
 
829
      {
 
830
         case PNG_TEXT_COMPRESSION_NONE:
 
831
            break;
 
832
 
 
833
         case PNG_TEXT_COMPRESSION_zTXt:
 
834
#           ifndef PNG_WRITE_zTXt_SUPPORTED
 
835
               ++unsupported_chunks;
 
836
               /* In libpng 1.7 this now does an app-error, so stop it: */
 
837
               text_ptr[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
 
838
#           endif
 
839
            break;
 
840
 
 
841
         case PNG_ITXT_COMPRESSION_NONE:
 
842
         case PNG_ITXT_COMPRESSION_zTXt:
 
843
#           ifndef PNG_WRITE_iTXt_SUPPORTED
 
844
               ++unsupported_chunks;
 
845
               text_ptr[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
 
846
#           endif
 
847
            break;
 
848
 
 
849
         default:
 
850
            /* This is an error */
 
851
            png_error(png_ptr, "invalid text chunk compression field");
 
852
            break;
 
853
      }
 
854
   }
 
855
}
 
856
#endif
 
857
/* END of code to check that libpng has the required text support */
 
858
 
 
859
/* Test one file */
 
860
static int
 
861
test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
 
862
{
 
863
   static png_FILE_p fpin;
 
864
   static png_FILE_p fpout;  /* "static" prevents setjmp corruption */
 
865
   pngtest_error_parameters error_parameters;
 
866
   png_structp read_ptr;
 
867
   png_infop read_info_ptr, end_info_ptr;
 
868
#ifdef PNG_WRITE_SUPPORTED
 
869
   png_structp write_ptr;
 
870
   png_infop write_info_ptr;
 
871
   png_infop write_end_info_ptr;
 
872
#ifdef PNG_WRITE_FILTER_SUPPORTED
 
873
   int interlace_preserved = 1;
 
874
#endif /* WRITE_FILTER */
 
875
#else /* !WRITE */
 
876
   png_structp write_ptr = NULL;
 
877
   png_infop write_info_ptr = NULL;
 
878
   png_infop write_end_info_ptr = NULL;
 
879
#endif /* !WRITE */
 
880
   png_bytep row_buf;
 
881
   png_uint_32 y;
 
882
   png_uint_32 width, height;
 
883
   volatile int num_passes;
 
884
   int pass;
 
885
   int bit_depth, color_type;
 
886
 
 
887
   row_buf = NULL;
 
888
   error_parameters.file_name = inname;
 
889
 
 
890
   if ((fpin = fopen(inname, "rb")) == NULL)
 
891
   {
 
892
      fprintf(STDERR, "Could not find input file %s\n", inname);
 
893
      return (1);
 
894
   }
 
895
 
 
896
   if ((fpout = fopen(outname, "wb")) == NULL)
 
897
   {
 
898
      fprintf(STDERR, "Could not open output file %s\n", outname);
 
899
      FCLOSE(fpin);
 
900
      return (1);
 
901
   }
 
902
 
 
903
   pngtest_debug("Allocating read and write structures");
 
904
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
 
905
   read_ptr =
 
906
      png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL,
 
907
      NULL, NULL, NULL, png_debug_malloc, png_debug_free);
 
908
#else
 
909
   read_ptr =
 
910
      png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
 
911
#endif
 
912
   png_set_error_fn(read_ptr, &error_parameters, pngtest_error,
 
913
      pngtest_warning);
 
914
 
 
915
#ifdef PNG_WRITE_SUPPORTED
 
916
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
 
917
   write_ptr =
 
918
      png_create_write_struct_2(PNG_LIBPNG_VER_STRING, NULL,
 
919
      NULL, NULL, NULL, png_debug_malloc, png_debug_free);
 
920
#else
 
921
   write_ptr =
 
922
      png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
 
923
#endif
 
924
   png_set_error_fn(write_ptr, &error_parameters, pngtest_error,
 
925
      pngtest_warning);
 
926
#endif
 
927
   pngtest_debug("Allocating read_info, write_info and end_info structures");
 
928
   read_info_ptr = png_create_info_struct(read_ptr);
 
929
   end_info_ptr = png_create_info_struct(read_ptr);
 
930
#ifdef PNG_WRITE_SUPPORTED
 
931
   write_info_ptr = png_create_info_struct(write_ptr);
 
932
   write_end_info_ptr = png_create_info_struct(write_ptr);
 
933
#endif
 
934
 
 
935
#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
 
936
   init_callback_info(read_info_ptr);
 
937
   png_set_read_user_chunk_fn(read_ptr, &user_chunk_data,
 
938
     read_user_chunk_callback);
 
939
#endif
 
940
 
 
941
#ifdef PNG_SETJMP_SUPPORTED
 
942
   pngtest_debug("Setting jmpbuf for read struct");
 
943
   if (setjmp(png_jmpbuf(read_ptr)))
 
944
   {
 
945
      fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname);
 
946
      png_free(read_ptr, row_buf);
 
947
      row_buf = NULL;
 
948
      png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
 
949
#ifdef PNG_WRITE_SUPPORTED
 
950
      png_destroy_info_struct(write_ptr, &write_end_info_ptr);
 
951
      png_destroy_write_struct(&write_ptr, &write_info_ptr);
 
952
#endif
 
953
      FCLOSE(fpin);
 
954
      FCLOSE(fpout);
 
955
      return (1);
 
956
   }
 
957
 
 
958
#ifdef PNG_WRITE_SUPPORTED
 
959
   pngtest_debug("Setting jmpbuf for write struct");
 
960
 
 
961
   if (setjmp(png_jmpbuf(write_ptr)))
 
962
   {
 
963
      fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname);
 
964
      png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
 
965
      png_destroy_info_struct(write_ptr, &write_end_info_ptr);
 
966
#ifdef PNG_WRITE_SUPPORTED
 
967
      png_destroy_write_struct(&write_ptr, &write_info_ptr);
 
968
#endif
 
969
      FCLOSE(fpin);
 
970
      FCLOSE(fpout);
 
971
      return (1);
 
972
   }
 
973
#endif
 
974
#endif
 
975
 
 
976
   if (strict != 0)
 
977
   {
 
978
      /* Treat png_benign_error() as errors on read */
 
979
      png_set_benign_errors(read_ptr, 0);
 
980
 
 
981
#ifdef PNG_WRITE_SUPPORTED
 
982
      /* Treat them as errors on write */
 
983
      png_set_benign_errors(write_ptr, 0);
 
984
#endif
 
985
 
 
986
      /* if strict is not set, then app warnings and errors are treated as
 
987
       * warnings in release builds, but not in unstable builds; this can be
 
988
       * changed with '--relaxed'.
 
989
       */
 
990
   }
 
991
 
 
992
   else if (relaxed != 0)
 
993
   {
 
994
      /* Allow application (pngtest) errors and warnings to pass */
 
995
      png_set_benign_errors(read_ptr, 1);
 
996
 
 
997
#ifdef PNG_WRITE_SUPPORTED
 
998
      png_set_benign_errors(write_ptr, 1);
 
999
#endif
 
1000
   }
 
1001
 
 
1002
   pngtest_debug("Initializing input and output streams");
 
1003
#ifdef PNG_STDIO_SUPPORTED
 
1004
   png_init_io(read_ptr, fpin);
 
1005
#  ifdef PNG_WRITE_SUPPORTED
 
1006
   png_init_io(write_ptr, fpout);
 
1007
#  endif
 
1008
#else
 
1009
   png_set_read_fn(read_ptr, (png_voidp)fpin, pngtest_read_data);
 
1010
#  ifdef PNG_WRITE_SUPPORTED
 
1011
   png_set_write_fn(write_ptr, (png_voidp)fpout,  pngtest_write_data,
 
1012
#    ifdef PNG_WRITE_FLUSH_SUPPORTED
 
1013
      pngtest_flush);
 
1014
#    else
 
1015
      NULL);
 
1016
#    endif
 
1017
#  endif
 
1018
#endif
 
1019
 
 
1020
   if (status_dots_requested == 1)
 
1021
   {
 
1022
#ifdef PNG_WRITE_SUPPORTED
 
1023
      png_set_write_status_fn(write_ptr, write_row_callback);
 
1024
#endif
 
1025
      png_set_read_status_fn(read_ptr, read_row_callback);
 
1026
   }
 
1027
 
 
1028
   else
 
1029
   {
 
1030
#ifdef PNG_WRITE_SUPPORTED
 
1031
      png_set_write_status_fn(write_ptr, NULL);
 
1032
#endif
 
1033
      png_set_read_status_fn(read_ptr, NULL);
 
1034
   }
 
1035
 
 
1036
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
 
1037
   png_set_read_user_transform_fn(read_ptr, read_user_callback);
 
1038
#endif
 
1039
#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
 
1040
   zero_samples = 0;
 
1041
   png_set_write_user_transform_fn(write_ptr, count_zero_samples);
 
1042
#endif
 
1043
 
 
1044
#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
 
1045
   /* Preserve all the unknown chunks, if possible.  If this is disabled then,
 
1046
    * even if the png_{get,set}_unknown_chunks stuff is enabled, we can't use
 
1047
    * libpng to *save* the unknown chunks on read (because we can't switch the
 
1048
    * save option on!)
 
1049
    *
 
1050
    * Notice that if SET_UNKNOWN_CHUNKS is *not* supported read will discard all
 
1051
    * unknown chunks and write will write them all.
 
1052
    */
 
1053
#ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
 
1054
   png_set_keep_unknown_chunks(read_ptr, PNG_HANDLE_CHUNK_ALWAYS,
 
1055
      NULL, 0);
 
1056
#endif
 
1057
#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
 
1058
   png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_ALWAYS,
 
1059
      NULL, 0);
 
1060
#endif
 
1061
#endif
 
1062
 
 
1063
   pngtest_debug("Reading info struct");
 
1064
   png_read_info(read_ptr, read_info_ptr);
 
1065
 
 
1066
#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
 
1067
   /* This is a bit of a hack; there is no obvious way in the callback function
 
1068
    * to determine that the chunks before the first IDAT have been read, so
 
1069
    * remove the info_ptr (which is only used to determine position relative to
 
1070
    * PLTE) here to indicate that we are after the IDAT.
 
1071
    */
 
1072
   user_chunk_data.info_ptr = NULL;
 
1073
#endif
 
1074
 
 
1075
   pngtest_debug("Transferring info struct");
 
1076
   {
 
1077
      int interlace_type, compression_type, filter_type;
 
1078
 
 
1079
      if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth,
 
1080
          &color_type, &interlace_type, &compression_type, &filter_type) != 0)
 
1081
      {
 
1082
         png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth,
 
1083
            color_type, interlace_type, compression_type, filter_type);
 
1084
         /* num_passes may not be available below if interlace support is not
 
1085
          * provided by libpng for both read and write.
 
1086
          */
 
1087
         switch (interlace_type)
 
1088
         {
 
1089
            case PNG_INTERLACE_NONE:
 
1090
               num_passes = 1;
 
1091
               break;
 
1092
 
 
1093
            case PNG_INTERLACE_ADAM7:
 
1094
               num_passes = 7;
 
1095
               break;
 
1096
 
 
1097
            default:
 
1098
               png_error(read_ptr, "invalid interlace type");
 
1099
               /*NOT REACHED*/
 
1100
         }
 
1101
      }
 
1102
 
 
1103
      else
 
1104
         png_error(read_ptr, "png_get_IHDR failed");
 
1105
   }
 
1106
#ifdef PNG_FIXED_POINT_SUPPORTED
 
1107
#ifdef PNG_cHRM_SUPPORTED
 
1108
   {
 
1109
      png_fixed_point white_x, white_y, red_x, red_y, green_x, green_y, blue_x,
 
1110
         blue_y;
 
1111
 
 
1112
      if (png_get_cHRM_fixed(read_ptr, read_info_ptr, &white_x, &white_y,
 
1113
         &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y) != 0)
 
1114
      {
 
1115
         png_set_cHRM_fixed(write_ptr, write_info_ptr, white_x, white_y, red_x,
 
1116
            red_y, green_x, green_y, blue_x, blue_y);
 
1117
      }
 
1118
   }
 
1119
#endif
 
1120
#ifdef PNG_gAMA_SUPPORTED
 
1121
   {
 
1122
      png_fixed_point gamma;
 
1123
 
 
1124
      if (png_get_gAMA_fixed(read_ptr, read_info_ptr, &gamma) != 0)
 
1125
         png_set_gAMA_fixed(write_ptr, write_info_ptr, gamma);
 
1126
   }
 
1127
#endif
 
1128
#else /* Use floating point versions */
 
1129
#ifdef PNG_FLOATING_POINT_SUPPORTED
 
1130
#ifdef PNG_cHRM_SUPPORTED
 
1131
   {
 
1132
      double white_x, white_y, red_x, red_y, green_x, green_y, blue_x,
 
1133
         blue_y;
 
1134
 
 
1135
      if (png_get_cHRM(read_ptr, read_info_ptr, &white_x, &white_y, &red_x,
 
1136
         &red_y, &green_x, &green_y, &blue_x, &blue_y) != 0)
 
1137
      {
 
1138
         png_set_cHRM(write_ptr, write_info_ptr, white_x, white_y, red_x,
 
1139
            red_y, green_x, green_y, blue_x, blue_y);
 
1140
      }
 
1141
   }
 
1142
#endif
 
1143
#ifdef PNG_gAMA_SUPPORTED
 
1144
   {
 
1145
      double gamma;
 
1146
 
 
1147
      if (png_get_gAMA(read_ptr, read_info_ptr, &gamma) != 0)
 
1148
         png_set_gAMA(write_ptr, write_info_ptr, gamma);
 
1149
   }
 
1150
#endif
 
1151
#endif /* Floating point */
 
1152
#endif /* Fixed point */
 
1153
#ifdef PNG_iCCP_SUPPORTED
 
1154
   {
 
1155
      png_charp name;
 
1156
      png_bytep profile;
 
1157
      png_uint_32 proflen;
 
1158
      int compression_type;
 
1159
 
 
1160
      if (png_get_iCCP(read_ptr, read_info_ptr, &name, &compression_type,
 
1161
                      &profile, &proflen) != 0)
 
1162
      {
 
1163
         png_set_iCCP(write_ptr, write_info_ptr, name, compression_type,
 
1164
                      profile, proflen);
 
1165
      }
 
1166
   }
 
1167
#endif
 
1168
#ifdef PNG_sRGB_SUPPORTED
 
1169
   {
 
1170
      int intent;
 
1171
 
 
1172
      if (png_get_sRGB(read_ptr, read_info_ptr, &intent) != 0)
 
1173
         png_set_sRGB(write_ptr, write_info_ptr, intent);
 
1174
   }
 
1175
#endif
 
1176
   {
 
1177
      png_colorp palette;
 
1178
      int num_palette;
 
1179
 
 
1180
      if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette) != 0)
 
1181
         png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette);
 
1182
   }
 
1183
#ifdef PNG_bKGD_SUPPORTED
 
1184
   {
 
1185
      png_color_16p background;
 
1186
 
 
1187
      if (png_get_bKGD(read_ptr, read_info_ptr, &background) != 0)
 
1188
      {
 
1189
         png_set_bKGD(write_ptr, write_info_ptr, background);
 
1190
      }
 
1191
   }
 
1192
#endif
 
1193
#ifdef PNG_hIST_SUPPORTED
 
1194
   {
 
1195
      png_uint_16p hist;
 
1196
 
 
1197
      if (png_get_hIST(read_ptr, read_info_ptr, &hist) != 0)
 
1198
         png_set_hIST(write_ptr, write_info_ptr, hist);
 
1199
   }
 
1200
#endif
 
1201
#ifdef PNG_oFFs_SUPPORTED
 
1202
   {
 
1203
      png_int_32 offset_x, offset_y;
 
1204
      int unit_type;
 
1205
 
 
1206
      if (png_get_oFFs(read_ptr, read_info_ptr, &offset_x, &offset_y,
 
1207
          &unit_type) != 0)
 
1208
      {
 
1209
         png_set_oFFs(write_ptr, write_info_ptr, offset_x, offset_y, unit_type);
 
1210
      }
 
1211
   }
 
1212
#endif
 
1213
#ifdef PNG_pCAL_SUPPORTED
 
1214
   {
 
1215
      png_charp purpose, units;
 
1216
      png_charpp params;
 
1217
      png_int_32 X0, X1;
 
1218
      int type, nparams;
 
1219
 
 
1220
      if (png_get_pCAL(read_ptr, read_info_ptr, &purpose, &X0, &X1, &type,
 
1221
         &nparams, &units, &params) != 0)
 
1222
      {
 
1223
         png_set_pCAL(write_ptr, write_info_ptr, purpose, X0, X1, type,
 
1224
            nparams, units, params);
 
1225
      }
 
1226
   }
 
1227
#endif
 
1228
#ifdef PNG_pHYs_SUPPORTED
 
1229
   {
 
1230
      png_uint_32 res_x, res_y;
 
1231
      int unit_type;
 
1232
 
 
1233
      if (png_get_pHYs(read_ptr, read_info_ptr, &res_x, &res_y,
 
1234
          &unit_type) != 0)
 
1235
         png_set_pHYs(write_ptr, write_info_ptr, res_x, res_y, unit_type);
 
1236
   }
 
1237
#endif
 
1238
#ifdef PNG_sBIT_SUPPORTED
 
1239
   {
 
1240
      png_color_8p sig_bit;
 
1241
 
 
1242
      if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit) != 0)
 
1243
         png_set_sBIT(write_ptr, write_info_ptr, sig_bit);
 
1244
   }
 
1245
#endif
 
1246
#ifdef PNG_sCAL_SUPPORTED
 
1247
#if defined(PNG_FLOATING_POINT_SUPPORTED) && \
 
1248
   defined(PNG_FLOATING_ARITHMETIC_SUPPORTED)
 
1249
   {
 
1250
      int unit;
 
1251
      double scal_width, scal_height;
 
1252
 
 
1253
      if (png_get_sCAL(read_ptr, read_info_ptr, &unit, &scal_width,
 
1254
         &scal_height) != 0)
 
1255
      {
 
1256
         png_set_sCAL(write_ptr, write_info_ptr, unit, scal_width, scal_height);
 
1257
      }
 
1258
   }
 
1259
#else
 
1260
#ifdef PNG_FIXED_POINT_SUPPORTED
 
1261
   {
 
1262
      int unit;
 
1263
      png_charp scal_width, scal_height;
 
1264
 
 
1265
      if (png_get_sCAL_s(read_ptr, read_info_ptr, &unit, &scal_width,
 
1266
          &scal_height) != 0)
 
1267
      {
 
1268
         png_set_sCAL_s(write_ptr, write_info_ptr, unit, scal_width,
 
1269
             scal_height);
 
1270
      }
 
1271
   }
 
1272
#endif
 
1273
#endif
 
1274
#endif
 
1275
 
 
1276
#ifdef PNG_sPLT_SUPPORTED
 
1277
   {
 
1278
       png_sPLT_tp entries;
 
1279
 
 
1280
       int num_entries = (int) png_get_sPLT(read_ptr, read_info_ptr, &entries);
 
1281
       if (num_entries)
 
1282
       {
 
1283
           png_set_sPLT(write_ptr, write_info_ptr, entries, num_entries);
 
1284
       }
 
1285
   }
 
1286
#endif
 
1287
 
 
1288
#ifdef PNG_TEXT_SUPPORTED
 
1289
   {
 
1290
      png_textp text_ptr;
 
1291
      int num_text;
 
1292
 
 
1293
      if (png_get_text(read_ptr, read_info_ptr, &text_ptr, &num_text) > 0)
 
1294
      {
 
1295
         pngtest_debug1("Handling %d iTXt/tEXt/zTXt chunks", num_text);
 
1296
 
 
1297
         pngtest_check_text_support(read_ptr, text_ptr, num_text);
 
1298
 
 
1299
         if (verbose != 0)
 
1300
         {
 
1301
            int i;
 
1302
 
 
1303
            printf("\n");
 
1304
            for (i=0; i<num_text; i++)
 
1305
            {
 
1306
               printf("   Text compression[%d]=%d\n",
 
1307
                     i, text_ptr[i].compression);
 
1308
            }
 
1309
         }
 
1310
 
 
1311
         png_set_text(write_ptr, write_info_ptr, text_ptr, num_text);
 
1312
      }
 
1313
   }
 
1314
#endif
 
1315
#ifdef PNG_tIME_SUPPORTED
 
1316
   {
 
1317
      png_timep mod_time;
 
1318
 
 
1319
      if (png_get_tIME(read_ptr, read_info_ptr, &mod_time) != 0)
 
1320
      {
 
1321
         png_set_tIME(write_ptr, write_info_ptr, mod_time);
 
1322
#ifdef PNG_TIME_RFC1123_SUPPORTED
 
1323
         if (png_convert_to_rfc1123_buffer(tIME_string, mod_time) != 0)
 
1324
            tIME_string[(sizeof tIME_string) - 1] = '\0';
 
1325
 
 
1326
         else
 
1327
         {
 
1328
            strncpy(tIME_string, "*** invalid time ***", (sizeof tIME_string));
 
1329
            tIME_string[(sizeof tIME_string) - 1] = '\0';
 
1330
         }
 
1331
 
 
1332
         tIME_chunk_present++;
 
1333
#endif /* TIME_RFC1123 */
 
1334
      }
 
1335
   }
 
1336
#endif
 
1337
#ifdef PNG_tRNS_SUPPORTED
 
1338
   {
 
1339
      png_bytep trans_alpha;
 
1340
      int num_trans;
 
1341
      png_color_16p trans_color;
 
1342
 
 
1343
      if (png_get_tRNS(read_ptr, read_info_ptr, &trans_alpha, &num_trans,
 
1344
         &trans_color) != 0)
 
1345
      {
 
1346
         int sample_max = (1 << bit_depth);
 
1347
         /* libpng doesn't reject a tRNS chunk with out-of-range samples */
 
1348
         if (!((color_type == PNG_COLOR_TYPE_GRAY &&
 
1349
             (int)trans_color->gray > sample_max) ||
 
1350
             (color_type == PNG_COLOR_TYPE_RGB &&
 
1351
             ((int)trans_color->red > sample_max ||
 
1352
             (int)trans_color->green > sample_max ||
 
1353
             (int)trans_color->blue > sample_max))))
 
1354
            png_set_tRNS(write_ptr, write_info_ptr, trans_alpha, num_trans,
 
1355
               trans_color);
 
1356
      }
 
1357
   }
 
1358
#endif
 
1359
#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
 
1360
   {
 
1361
      png_unknown_chunkp unknowns;
 
1362
      int num_unknowns = png_get_unknown_chunks(read_ptr, read_info_ptr,
 
1363
         &unknowns);
 
1364
 
 
1365
      if (num_unknowns != 0)
 
1366
      {
 
1367
         png_set_unknown_chunks(write_ptr, write_info_ptr, unknowns,
 
1368
           num_unknowns);
 
1369
#if PNG_LIBPNG_VER < 10600
 
1370
         /* Copy the locations from the read_info_ptr.  The automatically
 
1371
          * generated locations in write_end_info_ptr are wrong prior to 1.6.0
 
1372
          * because they are reset from the write pointer (removed in 1.6.0).
 
1373
          */
 
1374
         {
 
1375
            int i;
 
1376
            for (i = 0; i < num_unknowns; i++)
 
1377
              png_set_unknown_chunk_location(write_ptr, write_info_ptr, i,
 
1378
                unknowns[i].location);
 
1379
         }
 
1380
#endif
 
1381
      }
 
1382
   }
 
1383
#endif
 
1384
 
 
1385
#ifdef PNG_WRITE_SUPPORTED
 
1386
   pngtest_debug("Writing info struct");
 
1387
 
 
1388
   /* Write the info in two steps so that if we write the 'unknown' chunks here
 
1389
    * they go to the correct place.
 
1390
    */
 
1391
   png_write_info_before_PLTE(write_ptr, write_info_ptr);
 
1392
 
 
1393
   write_chunks(write_ptr, before_PLTE); /* before PLTE */
 
1394
 
 
1395
   png_write_info(write_ptr, write_info_ptr);
 
1396
 
 
1397
   write_chunks(write_ptr, before_IDAT); /* after PLTE */
 
1398
#endif
 
1399
 
 
1400
#ifdef SINGLE_ROWBUF_ALLOC
 
1401
   pngtest_debug("Allocating row buffer...");
 
1402
   row_buf = (png_bytep)png_malloc(read_ptr,
 
1403
      png_get_rowbytes(read_ptr, read_info_ptr));
 
1404
 
 
1405
   pngtest_debug1("\t0x%08lx", (unsigned long)row_buf);
 
1406
#endif /* SINGLE_ROWBUF_ALLOC */
 
1407
   pngtest_debug("Writing row data");
 
1408
 
 
1409
#if defined(PNG_READ_INTERLACING_SUPPORTED) &&\
 
1410
   defined(PNG_WRITE_INTERLACING_SUPPORTED)
 
1411
   /* Both must be defined for libpng to be able to handle the interlace,
 
1412
    * otherwise it gets handled below by simply reading and writing the passes
 
1413
    * directly.
 
1414
    */
 
1415
   if (png_set_interlace_handling(read_ptr) != num_passes)
 
1416
      png_error(write_ptr,
 
1417
            "png_set_interlace_handling(read): wrong pass count ");
 
1418
   if (png_set_interlace_handling(write_ptr) != num_passes)
 
1419
      png_error(write_ptr,
 
1420
            "png_set_interlace_handling(write): wrong pass count ");
 
1421
#else /* png_set_interlace_handling not called on either read or write */
 
1422
#  define calc_pass_height
 
1423
#endif /* not using libpng interlace handling */
 
1424
 
 
1425
#ifdef PNGTEST_TIMING
 
1426
   t_stop = (float)clock();
 
1427
   t_misc += (t_stop - t_start);
 
1428
   t_start = t_stop;
 
1429
#endif
 
1430
   for (pass = 0; pass < num_passes; pass++)
 
1431
   {
 
1432
#     ifdef calc_pass_height
 
1433
         png_uint_32 pass_height;
 
1434
 
 
1435
         if (num_passes == 7) /* interlaced */
 
1436
         {
 
1437
            if (PNG_PASS_COLS(width, pass) > 0)
 
1438
               pass_height = PNG_PASS_ROWS(height, pass);
 
1439
 
 
1440
            else
 
1441
               pass_height = 0;
 
1442
         }
 
1443
 
 
1444
         else /* not interlaced */
 
1445
            pass_height = height;
 
1446
#     else
 
1447
#        define pass_height height
 
1448
#     endif
 
1449
 
 
1450
      pngtest_debug1("Writing row data for pass %d", pass);
 
1451
      for (y = 0; y < pass_height; y++)
 
1452
      {
 
1453
#ifndef SINGLE_ROWBUF_ALLOC
 
1454
         pngtest_debug2("Allocating row buffer (pass %d, y = %u)...", pass, y);
 
1455
 
 
1456
         row_buf = (png_bytep)png_malloc(read_ptr,
 
1457
            png_get_rowbytes(read_ptr, read_info_ptr));
 
1458
 
 
1459
         pngtest_debug2("\t0x%08lx (%lu bytes)", (unsigned long)row_buf,
 
1460
            (unsigned long)png_get_rowbytes(read_ptr, read_info_ptr));
 
1461
 
 
1462
#endif /* !SINGLE_ROWBUF_ALLOC */
 
1463
         png_read_rows(read_ptr, (png_bytepp)&row_buf, NULL, 1);
 
1464
 
 
1465
#ifdef PNG_WRITE_SUPPORTED
 
1466
#ifdef PNGTEST_TIMING
 
1467
         t_stop = (float)clock();
 
1468
         t_decode += (t_stop - t_start);
 
1469
         t_start = t_stop;
 
1470
#endif
 
1471
         png_write_rows(write_ptr, (png_bytepp)&row_buf, 1);
 
1472
#ifdef PNGTEST_TIMING
 
1473
         t_stop = (float)clock();
 
1474
         t_encode += (t_stop - t_start);
 
1475
         t_start = t_stop;
 
1476
#endif
 
1477
#endif /* WRITE */
 
1478
 
 
1479
#ifndef SINGLE_ROWBUF_ALLOC
 
1480
         pngtest_debug2("Freeing row buffer (pass %d, y = %u)", pass, y);
 
1481
         png_free(read_ptr, row_buf);
 
1482
         row_buf = NULL;
 
1483
#endif /* !SINGLE_ROWBUF_ALLOC */
 
1484
      }
 
1485
   }
 
1486
 
 
1487
#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
 
1488
#  ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
 
1489
      png_free_data(read_ptr, read_info_ptr, PNG_FREE_UNKN, -1);
 
1490
#  endif
 
1491
#  ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
 
1492
      png_free_data(write_ptr, write_info_ptr, PNG_FREE_UNKN, -1);
 
1493
#  endif
 
1494
#endif
 
1495
 
 
1496
   pngtest_debug("Reading and writing end_info data");
 
1497
 
 
1498
   png_read_end(read_ptr, end_info_ptr);
 
1499
#ifdef PNG_TEXT_SUPPORTED
 
1500
   {
 
1501
      png_textp text_ptr;
 
1502
      int num_text;
 
1503
 
 
1504
      if (png_get_text(read_ptr, end_info_ptr, &text_ptr, &num_text) > 0)
 
1505
      {
 
1506
         pngtest_debug1("Handling %d iTXt/tEXt/zTXt chunks", num_text);
 
1507
 
 
1508
         pngtest_check_text_support(read_ptr, text_ptr, num_text);
 
1509
 
 
1510
         if (verbose != 0)
 
1511
         {
 
1512
            int i;
 
1513
 
 
1514
            printf("\n");
 
1515
            for (i=0; i<num_text; i++)
 
1516
            {
 
1517
               printf("   Text compression[%d]=%d\n",
 
1518
                     i, text_ptr[i].compression);
 
1519
            }
 
1520
         }
 
1521
 
 
1522
         png_set_text(write_ptr, write_end_info_ptr, text_ptr, num_text);
 
1523
      }
 
1524
   }
 
1525
#endif
 
1526
#ifdef PNG_tIME_SUPPORTED
 
1527
   {
 
1528
      png_timep mod_time;
 
1529
 
 
1530
      if (png_get_tIME(read_ptr, end_info_ptr, &mod_time) != 0)
 
1531
      {
 
1532
         png_set_tIME(write_ptr, write_end_info_ptr, mod_time);
 
1533
#ifdef PNG_TIME_RFC1123_SUPPORTED
 
1534
         if (png_convert_to_rfc1123_buffer(tIME_string, mod_time) != 0)
 
1535
            tIME_string[(sizeof tIME_string) - 1] = '\0';
 
1536
 
 
1537
         else
 
1538
         {
 
1539
            strncpy(tIME_string, "*** invalid time ***", sizeof tIME_string);
 
1540
            tIME_string[(sizeof tIME_string)-1] = '\0';
 
1541
         }
 
1542
 
 
1543
         tIME_chunk_present++;
 
1544
#endif /* TIME_RFC1123 */
 
1545
      }
 
1546
   }
 
1547
#endif
 
1548
#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
 
1549
   {
 
1550
      png_unknown_chunkp unknowns;
 
1551
      int num_unknowns = png_get_unknown_chunks(read_ptr, end_info_ptr,
 
1552
         &unknowns);
 
1553
 
 
1554
      if (num_unknowns != 0)
 
1555
      {
 
1556
         png_set_unknown_chunks(write_ptr, write_end_info_ptr, unknowns,
 
1557
           num_unknowns);
 
1558
#if PNG_LIBPNG_VER < 10600
 
1559
         /* Copy the locations from the read_info_ptr.  The automatically
 
1560
          * generated locations in write_end_info_ptr are wrong prior to 1.6.0
 
1561
          * because they are reset from the write pointer (removed in 1.6.0).
 
1562
          */
 
1563
         {
 
1564
            int i;
 
1565
            for (i = 0; i < num_unknowns; i++)
 
1566
              png_set_unknown_chunk_location(write_ptr, write_end_info_ptr, i,
 
1567
                unknowns[i].location);
 
1568
         }
 
1569
#endif
 
1570
      }
 
1571
   }
 
1572
#endif
 
1573
 
 
1574
#ifdef PNG_WRITE_SUPPORTED
 
1575
#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
 
1576
   /* Normally one would use Z_DEFAULT_STRATEGY for text compression.
 
1577
    * This is here just to make pngtest replicate the results from libpng
 
1578
    * versions prior to 1.5.4, and to test this new API.
 
1579
    */
 
1580
   png_set_text_compression_strategy(write_ptr, Z_FILTERED);
 
1581
#endif
 
1582
 
 
1583
   /* When the unknown vpAg/sTER chunks are written by pngtest the only way to
 
1584
    * do it is to write them *before* calling png_write_end.  When unknown
 
1585
    * chunks are written by libpng, however, they are written just before IEND.
 
1586
    * There seems to be no way round this, however vpAg/sTER are not expected
 
1587
    * after IDAT.
 
1588
    */
 
1589
   write_chunks(write_ptr, after_IDAT);
 
1590
 
 
1591
   png_write_end(write_ptr, write_end_info_ptr);
 
1592
#endif
 
1593
 
 
1594
#ifdef PNG_EASY_ACCESS_SUPPORTED
 
1595
   if (verbose != 0)
 
1596
   {
 
1597
      png_uint_32 iwidth, iheight;
 
1598
      iwidth = png_get_image_width(write_ptr, write_info_ptr);
 
1599
      iheight = png_get_image_height(write_ptr, write_info_ptr);
 
1600
      fprintf(STDERR, "\n Image width = %lu, height = %lu\n",
 
1601
         (unsigned long)iwidth, (unsigned long)iheight);
 
1602
   }
 
1603
#endif
 
1604
 
 
1605
   pngtest_debug("Destroying data structs");
 
1606
#ifdef SINGLE_ROWBUF_ALLOC
 
1607
   pngtest_debug("destroying row_buf for read_ptr");
 
1608
   png_free(read_ptr, row_buf);
 
1609
   row_buf = NULL;
 
1610
#endif /* SINGLE_ROWBUF_ALLOC */
 
1611
   pngtest_debug("destroying read_ptr, read_info_ptr, end_info_ptr");
 
1612
   png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
 
1613
#ifdef PNG_WRITE_SUPPORTED
 
1614
   pngtest_debug("destroying write_end_info_ptr");
 
1615
   png_destroy_info_struct(write_ptr, &write_end_info_ptr);
 
1616
   pngtest_debug("destroying write_ptr, write_info_ptr");
 
1617
   png_destroy_write_struct(&write_ptr, &write_info_ptr);
 
1618
#endif
 
1619
   pngtest_debug("Destruction complete.");
 
1620
 
 
1621
   FCLOSE(fpin);
 
1622
   FCLOSE(fpout);
 
1623
 
 
1624
   /* Summarize any warnings or errors and in 'strict' mode fail the test.
 
1625
    * Unsupported chunks can result in warnings, in that case ignore the strict
 
1626
    * setting, otherwise fail the test on warnings as well as errors.
 
1627
    */
 
1628
   if (error_count > 0)
 
1629
   {
 
1630
      /* We don't really expect to get here because of the setjmp handling
 
1631
       * above, but this is safe.
 
1632
       */
 
1633
      fprintf(STDERR, "\n  %s: %d libpng errors found (%d warnings)",
 
1634
         inname, error_count, warning_count);
 
1635
 
 
1636
      if (strict != 0)
 
1637
         return (1);
 
1638
   }
 
1639
 
 
1640
#  ifdef PNG_WRITE_SUPPORTED
 
1641
      /* If there is no write support nothing was written! */
 
1642
      else if (unsupported_chunks > 0)
 
1643
      {
 
1644
         fprintf(STDERR, "\n  %s: unsupported chunks (%d)%s",
 
1645
            inname, unsupported_chunks, strict ? ": IGNORED --strict!" : "");
 
1646
      }
 
1647
#  endif
 
1648
 
 
1649
   else if (warning_count > 0)
 
1650
   {
 
1651
      fprintf(STDERR, "\n  %s: %d libpng warnings found",
 
1652
         inname, warning_count);
 
1653
 
 
1654
      if (strict != 0)
 
1655
         return (1);
 
1656
   }
 
1657
 
 
1658
   pngtest_debug("Opening files for comparison");
 
1659
   if ((fpin = fopen(inname, "rb")) == NULL)
 
1660
   {
 
1661
      fprintf(STDERR, "Could not find file %s\n", inname);
 
1662
      return (1);
 
1663
   }
 
1664
 
 
1665
   if ((fpout = fopen(outname, "rb")) == NULL)
 
1666
   {
 
1667
      fprintf(STDERR, "Could not find file %s\n", outname);
 
1668
      FCLOSE(fpin);
 
1669
      return (1);
 
1670
   }
 
1671
 
 
1672
#if defined (PNG_WRITE_SUPPORTED) /* else nothing was written */ &&\
 
1673
    defined (PNG_WRITE_FILTER_SUPPORTED)
 
1674
   if (interlace_preserved != 0) /* else the files will be changed */
 
1675
   {
 
1676
      for (;;)
 
1677
      {
 
1678
         static int wrote_question = 0;
 
1679
         png_size_t num_in, num_out;
 
1680
         char inbuf[256], outbuf[256];
 
1681
 
 
1682
         num_in = fread(inbuf, 1, sizeof inbuf, fpin);
 
1683
         num_out = fread(outbuf, 1, sizeof outbuf, fpout);
 
1684
 
 
1685
         if (num_in != num_out)
 
1686
         {
 
1687
            fprintf(STDERR, "\nFiles %s and %s are of a different size\n",
 
1688
                    inname, outname);
 
1689
 
 
1690
            if (wrote_question == 0 && unsupported_chunks == 0)
 
1691
            {
 
1692
               fprintf(STDERR,
 
1693
         "   Was %s written with the same maximum IDAT chunk size (%d bytes),",
 
1694
                 inname, PNG_ZBUF_SIZE);
 
1695
               fprintf(STDERR,
 
1696
                 "\n   filtering heuristic (libpng default), compression");
 
1697
               fprintf(STDERR,
 
1698
                 " level (zlib default),\n   and zlib version (%s)?\n\n",
 
1699
                 ZLIB_VERSION);
 
1700
               wrote_question = 1;
 
1701
            }
 
1702
 
 
1703
            FCLOSE(fpin);
 
1704
            FCLOSE(fpout);
 
1705
 
 
1706
            if (strict != 0 && unsupported_chunks == 0)
 
1707
              return (1);
 
1708
 
 
1709
            else
 
1710
              return (0);
 
1711
         }
 
1712
 
 
1713
         if (num_in == 0)
 
1714
            break;
 
1715
 
 
1716
         if (memcmp(inbuf, outbuf, num_in))
 
1717
         {
 
1718
            fprintf(STDERR, "\nFiles %s and %s are different\n", inname,
 
1719
               outname);
 
1720
 
 
1721
            if (wrote_question == 0 && unsupported_chunks == 0)
 
1722
            {
 
1723
               fprintf(STDERR,
 
1724
         "   Was %s written with the same maximum IDAT chunk size (%d bytes),",
 
1725
                    inname, PNG_ZBUF_SIZE);
 
1726
               fprintf(STDERR,
 
1727
                 "\n   filtering heuristic (libpng default), compression");
 
1728
               fprintf(STDERR,
 
1729
                 " level (zlib default),\n   and zlib version (%s)?\n\n",
 
1730
                 ZLIB_VERSION);
 
1731
               wrote_question = 1;
 
1732
            }
 
1733
 
 
1734
            FCLOSE(fpin);
 
1735
            FCLOSE(fpout);
 
1736
 
 
1737
            /* NOTE: the unsupported_chunks escape is permitted here because
 
1738
             * unsupported text chunk compression will result in the compression
 
1739
             * mode being changed (to NONE) yet, in the test case, the result
 
1740
             * can be exactly the same size!
 
1741
             */
 
1742
            if (strict != 0 && unsupported_chunks == 0)
 
1743
              return (1);
 
1744
 
 
1745
            else
 
1746
              return (0);
 
1747
         }
 
1748
      }
 
1749
   }
 
1750
#endif /* WRITE && WRITE_FILTER */
 
1751
 
 
1752
   FCLOSE(fpin);
 
1753
   FCLOSE(fpout);
 
1754
 
 
1755
   return (0);
 
1756
}
 
1757
 
 
1758
/* Input and output filenames */
 
1759
#ifdef RISCOS
 
1760
static PNG_CONST char *inname = "pngtest/png";
 
1761
static PNG_CONST char *outname = "pngout/png";
 
1762
#else
 
1763
static PNG_CONST char *inname = "pngtest.png";
 
1764
static PNG_CONST char *outname = "pngout.png";
 
1765
#endif
 
1766
 
 
1767
int
 
1768
main(int argc, char *argv[])
 
1769
{
 
1770
   int multiple = 0;
 
1771
   int ierror = 0;
 
1772
 
 
1773
   png_structp dummy_ptr;
 
1774
 
 
1775
   fprintf(STDERR, "\n Testing libpng version %s\n", PNG_LIBPNG_VER_STRING);
 
1776
   fprintf(STDERR, "   with zlib   version %s\n", ZLIB_VERSION);
 
1777
   fprintf(STDERR, "%s", png_get_copyright(NULL));
 
1778
   /* Show the version of libpng used in building the library */
 
1779
   fprintf(STDERR, " library (%lu):%s",
 
1780
      (unsigned long)png_access_version_number(),
 
1781
      png_get_header_version(NULL));
 
1782
 
 
1783
   /* Show the version of libpng used in building the application */
 
1784
   fprintf(STDERR, " pngtest (%lu):%s", (unsigned long)PNG_LIBPNG_VER,
 
1785
      PNG_HEADER_VERSION_STRING);
 
1786
 
 
1787
   /* Do some consistency checking on the memory allocation settings, I'm
 
1788
    * not sure this matters, but it is nice to know, the first of these
 
1789
    * tests should be impossible because of the way the macros are set
 
1790
    * in pngconf.h
 
1791
    */
 
1792
#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K)
 
1793
      fprintf(STDERR, " NOTE: Zlib compiled for max 64k, libpng not\n");
 
1794
#endif
 
1795
   /* I think the following can happen. */
 
1796
#if !defined(MAXSEG_64K) && defined(PNG_MAX_MALLOC_64K)
 
1797
      fprintf(STDERR, " NOTE: libpng compiled for max 64k, zlib not\n");
 
1798
#endif
 
1799
 
 
1800
   if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING))
 
1801
   {
 
1802
      fprintf(STDERR,
 
1803
         "Warning: versions are different between png.h and png.c\n");
 
1804
      fprintf(STDERR, "  png.h version: %s\n", PNG_LIBPNG_VER_STRING);
 
1805
      fprintf(STDERR, "  png.c version: %s\n\n", png_libpng_ver);
 
1806
      ++ierror;
 
1807
   }
 
1808
 
 
1809
   if (argc > 1)
 
1810
   {
 
1811
      if (strcmp(argv[1], "-m") == 0)
 
1812
      {
 
1813
         multiple = 1;
 
1814
         status_dots_requested = 0;
 
1815
      }
 
1816
 
 
1817
      else if (strcmp(argv[1], "-mv") == 0 ||
 
1818
               strcmp(argv[1], "-vm") == 0 )
 
1819
      {
 
1820
         multiple = 1;
 
1821
         verbose = 1;
 
1822
         status_dots_requested = 1;
 
1823
      }
 
1824
 
 
1825
      else if (strcmp(argv[1], "-v") == 0)
 
1826
      {
 
1827
         verbose = 1;
 
1828
         status_dots_requested = 1;
 
1829
         inname = argv[2];
 
1830
      }
 
1831
 
 
1832
      else if (strcmp(argv[1], "--strict") == 0)
 
1833
      {
 
1834
         status_dots_requested = 0;
 
1835
         verbose = 1;
 
1836
         inname = argv[2];
 
1837
         strict++;
 
1838
         relaxed = 0;
 
1839
      }
 
1840
 
 
1841
      else if (strcmp(argv[1], "--relaxed") == 0)
 
1842
      {
 
1843
         status_dots_requested = 0;
 
1844
         verbose = 1;
 
1845
         inname = argv[2];
 
1846
         strict = 0;
 
1847
         relaxed++;
 
1848
      }
 
1849
 
 
1850
      else
 
1851
      {
 
1852
         inname = argv[1];
 
1853
         status_dots_requested = 0;
 
1854
      }
 
1855
   }
 
1856
 
 
1857
   if (multiple == 0 && argc == 3 + verbose)
 
1858
     outname = argv[2 + verbose];
 
1859
 
 
1860
   if ((multiple == 0 && argc > 3 + verbose) ||
 
1861
       (multiple != 0 && argc < 2))
 
1862
   {
 
1863
     fprintf(STDERR,
 
1864
       "usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n",
 
1865
        argv[0], argv[0]);
 
1866
     fprintf(STDERR,
 
1867
       "  reads/writes one PNG file (without -m) or multiple files (-m)\n");
 
1868
     fprintf(STDERR,
 
1869
       "  with -m %s is used as a temporary file\n", outname);
 
1870
     exit(1);
 
1871
   }
 
1872
 
 
1873
   if (multiple != 0)
 
1874
   {
 
1875
      int i;
 
1876
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
 
1877
      int allocation_now = current_allocation;
 
1878
#endif
 
1879
      for (i=2; i<argc; ++i)
 
1880
      {
 
1881
         int kerror;
 
1882
         fprintf(STDERR, "\n Testing %s:", argv[i]);
 
1883
#if PNG_DEBUG > 0
 
1884
         fprintf(STDERR, "\n");
 
1885
#endif
 
1886
         kerror = test_one_file(argv[i], outname);
 
1887
         if (kerror == 0)
 
1888
         {
 
1889
#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
 
1890
            fprintf(STDERR, "\n PASS (%lu zero samples)\n",
 
1891
               (unsigned long)zero_samples);
 
1892
#else
 
1893
            fprintf(STDERR, " PASS\n");
 
1894
#endif
 
1895
#ifdef PNG_TIME_RFC1123_SUPPORTED
 
1896
            if (tIME_chunk_present != 0)
 
1897
               fprintf(STDERR, " tIME = %s\n", tIME_string);
 
1898
 
 
1899
            tIME_chunk_present = 0;
 
1900
#endif /* TIME_RFC1123 */
 
1901
         }
 
1902
 
 
1903
         else
 
1904
         {
 
1905
            fprintf(STDERR, " FAIL\n");
 
1906
            ierror += kerror;
 
1907
         }
 
1908
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
 
1909
         if (allocation_now != current_allocation)
 
1910
            fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n",
 
1911
               current_allocation - allocation_now);
 
1912
 
 
1913
         if (current_allocation != 0)
 
1914
         {
 
1915
            memory_infop pinfo = pinformation;
 
1916
 
 
1917
            fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n",
 
1918
               current_allocation);
 
1919
 
 
1920
            while (pinfo != NULL)
 
1921
            {
 
1922
               fprintf(STDERR, " %lu bytes at %p\n",
 
1923
                 (unsigned long)pinfo->size,
 
1924
                 pinfo->pointer);
 
1925
               pinfo = pinfo->next;
 
1926
            }
 
1927
         }
 
1928
#endif
 
1929
      }
 
1930
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
 
1931
         fprintf(STDERR, " Current memory allocation: %10d bytes\n",
 
1932
            current_allocation);
 
1933
         fprintf(STDERR, " Maximum memory allocation: %10d bytes\n",
 
1934
            maximum_allocation);
 
1935
         fprintf(STDERR, " Total   memory allocation: %10d bytes\n",
 
1936
            total_allocation);
 
1937
         fprintf(STDERR, "     Number of allocations: %10d\n",
 
1938
            num_allocations);
 
1939
#endif
 
1940
   }
 
1941
 
 
1942
   else
 
1943
   {
 
1944
      int i;
 
1945
      for (i = 0; i<3; ++i)
 
1946
      {
 
1947
         int kerror;
 
1948
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
 
1949
         int allocation_now = current_allocation;
 
1950
#endif
 
1951
         if (i == 1)
 
1952
            status_dots_requested = 1;
 
1953
 
 
1954
         else if (verbose == 0)
 
1955
            status_dots_requested = 0;
 
1956
 
 
1957
         if (i == 0 || verbose == 1 || ierror != 0)
 
1958
         {
 
1959
            fprintf(STDERR, "\n Testing %s:", inname);
 
1960
#if PNG_DEBUG > 0
 
1961
            fprintf(STDERR, "\n");
 
1962
#endif
 
1963
         }
 
1964
 
 
1965
         kerror = test_one_file(inname, outname);
 
1966
 
 
1967
         if (kerror == 0)
 
1968
         {
 
1969
            if (verbose == 1 || i == 2)
 
1970
            {
 
1971
#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
 
1972
                fprintf(STDERR, "\n PASS (%lu zero samples)\n",
 
1973
                   (unsigned long)zero_samples);
 
1974
#else
 
1975
                fprintf(STDERR, " PASS\n");
 
1976
#endif
 
1977
#ifdef PNG_TIME_RFC1123_SUPPORTED
 
1978
             if (tIME_chunk_present != 0)
 
1979
                fprintf(STDERR, " tIME = %s\n", tIME_string);
 
1980
#endif /* TIME_RFC1123 */
 
1981
            }
 
1982
         }
 
1983
 
 
1984
         else
 
1985
         {
 
1986
            if (verbose == 0 && i != 2)
 
1987
            {
 
1988
               fprintf(STDERR, "\n Testing %s:", inname);
 
1989
#if PNG_DEBUG > 0
 
1990
               fprintf(STDERR, "\n");
 
1991
#endif
 
1992
            }
 
1993
 
 
1994
            fprintf(STDERR, " FAIL\n");
 
1995
            ierror += kerror;
 
1996
         }
 
1997
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
 
1998
         if (allocation_now != current_allocation)
 
1999
             fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n",
 
2000
               current_allocation - allocation_now);
 
2001
 
 
2002
         if (current_allocation != 0)
 
2003
         {
 
2004
             memory_infop pinfo = pinformation;
 
2005
 
 
2006
             fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n",
 
2007
                current_allocation);
 
2008
 
 
2009
             while (pinfo != NULL)
 
2010
             {
 
2011
                fprintf(STDERR, " %lu bytes at %p\n",
 
2012
                   (unsigned long)pinfo->size, pinfo->pointer);
 
2013
                pinfo = pinfo->next;
 
2014
             }
 
2015
          }
 
2016
#endif
 
2017
       }
 
2018
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
 
2019
       fprintf(STDERR, " Current memory allocation: %10d bytes\n",
 
2020
          current_allocation);
 
2021
       fprintf(STDERR, " Maximum memory allocation: %10d bytes\n",
 
2022
          maximum_allocation);
 
2023
       fprintf(STDERR, " Total   memory allocation: %10d bytes\n",
 
2024
          total_allocation);
 
2025
       fprintf(STDERR, "     Number of allocations: %10d\n",
 
2026
            num_allocations);
 
2027
#endif
 
2028
   }
 
2029
 
 
2030
#ifdef PNGTEST_TIMING
 
2031
   t_stop = (float)clock();
 
2032
   t_misc += (t_stop - t_start);
 
2033
   t_start = t_stop;
 
2034
   fprintf(STDERR, " CPU time used = %.3f seconds",
 
2035
      (t_misc+t_decode+t_encode)/(float)CLOCKS_PER_SEC);
 
2036
   fprintf(STDERR, " (decoding %.3f,\n",
 
2037
      t_decode/(float)CLOCKS_PER_SEC);
 
2038
   fprintf(STDERR, "        encoding %.3f ,",
 
2039
      t_encode/(float)CLOCKS_PER_SEC);
 
2040
   fprintf(STDERR, " other %.3f seconds)\n\n",
 
2041
      t_misc/(float)CLOCKS_PER_SEC);
 
2042
#endif
 
2043
 
 
2044
   if (ierror == 0)
 
2045
      fprintf(STDERR, " libpng passes test\n");
 
2046
 
 
2047
   else
 
2048
      fprintf(STDERR, " libpng FAILS test\n");
 
2049
 
 
2050
   dummy_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
 
2051
   fprintf(STDERR, " Default limits:\n");
 
2052
   fprintf(STDERR, "  width_max  = %lu\n",
 
2053
      (unsigned long) png_get_user_width_max(dummy_ptr));
 
2054
   fprintf(STDERR, "  height_max = %lu\n",
 
2055
      (unsigned long) png_get_user_height_max(dummy_ptr));
 
2056
   if (png_get_chunk_cache_max(dummy_ptr) == 0)
 
2057
      fprintf(STDERR, "  cache_max  = unlimited\n");
 
2058
   else
 
2059
      fprintf(STDERR, "  cache_max  = %lu\n",
 
2060
         (unsigned long) png_get_chunk_cache_max(dummy_ptr));
 
2061
   if (png_get_chunk_malloc_max(dummy_ptr) == 0)
 
2062
      fprintf(STDERR, "  malloc_max = unlimited\n");
 
2063
   else
 
2064
      fprintf(STDERR, "  malloc_max = %lu\n",
 
2065
         (unsigned long) png_get_chunk_malloc_max(dummy_ptr));
 
2066
   png_destroy_read_struct(&dummy_ptr, NULL, NULL);
 
2067
 
 
2068
   return (int)(ierror != 0);
 
2069
}
 
2070
#else
 
2071
int
 
2072
main(void)
 
2073
{
 
2074
   fprintf(STDERR,
 
2075
      " test ignored because libpng was not built with read support\n");
 
2076
   /* And skip this test */
 
2077
   return SKIP;
 
2078
}
 
2079
#endif
 
2080
 
 
2081
/* Generate a compiler error if there is an old png.h in the search path. */
 
2082
typedef png_libpng_version_1_6_22 Your_png_h_is_not_version_1_6_22;