VirtualBox

source: vbox/trunk/src/libs/libpng-1.6.43/pngtest.c

Last change on this file was 105469, checked in by vboxsync, 3 months ago

libpng-1.6.43: Applied and adjusted our libpng changes to 1.6.43. bugref:8515

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette