2 /* pngvalid.c - validate libpng by constructing then reading png files.
4 * Last changed in libpng 1.5.1 [February 3, 2011]
5 * Copyright (c) 2011 Glenn Randers-Pehrson
6 * Written by John Cunningham Bowler
8 * This code is released under the libpng license.
9 * For conditions of distribution and use, see the disclaimer
10 * and license in png.h
13 * This is a C program that is intended to be linked against libpng. It
14 * generates bitmaps internally, stores them as PNG files (using the
15 * sequential write code) then reads them back (using the sequential
16 * read code) and validates that the result has the correct data.
18 * The program can be modified and extended to test the correctness of
19 * transformations performed by libpng.
23 #if PNG_LIBPNG_VER < 10500
24 /* This delibarately lacks the PNG_CONST. */
25 typedef png_byte
*png_const_bytep
;
27 /* This is copied from 1.5.1 png.h: */
28 #define PNG_INTERLACE_ADAM7_PASSES 7
29 #define PNG_PASS_START_ROW(pass) (((1U&~(pass))<<(3-((pass)>>1)))&7)
30 #define PNG_PASS_START_COL(pass) (((1U& (pass))<<(3-(((pass)+1)>>1)))&7)
31 #define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3)
32 #define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3)
33 #define PNG_PASS_ROWS(height, pass) (((height)+(((1<<PNG_PASS_ROW_SHIFT(pass))\
34 -1)-PNG_PASS_START_ROW(pass)))>>PNG_PASS_ROW_SHIFT(pass))
35 #define PNG_PASS_COLS(width, pass) (((width)+(((1<<PNG_PASS_COL_SHIFT(pass))\
36 -1)-PNG_PASS_START_COL(pass)))>>PNG_PASS_COL_SHIFT(pass))
37 #define PNG_ROW_FROM_PASS_ROW(yIn, pass) \
38 (((yIn)<<PNG_PASS_ROW_SHIFT(pass))+PNG_PASS_START_ROW(pass))
39 #define PNG_COL_FROM_PASS_COL(xIn, pass) \
40 (((xIn)<<PNG_PASS_COL_SHIFT(pass))+PNG_PASS_START_COL(pass))
41 #define PNG_PASS_MASK(pass,off) ( \
42 ((0x110145AFU>>(((7-(off))-(pass))<<2)) & 0xFU) | \
43 ((0x01145AF0U>>(((7-(off))-(pass))<<2)) & 0xF0U))
44 #define PNG_ROW_IN_INTERLACE_PASS(y, pass) \
45 ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1)
46 #define PNG_COL_IN_INTERLACE_PASS(x, pass) \
47 ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1)
49 /* These are needed too for the defualt build: */
50 #define PNG_WRITE_16BIT_SUPPORTED
51 #define PNG_READ_16BIT_SUPPORTED
54 #include "zlib.h" /* For crc32 */
56 #include <float.h> /* For floating point constants */
57 #include <stdlib.h> /* For malloc */
58 #include <string.h> /* For memcpy, memset */
59 #include <math.h> /* For floor */
61 /* Unused formal parameter errors are removed using the following macro which is
62 * expected to have no bad effects on performance.
65 # if defined(__GNUC__) || defined(_MSC_VER)
66 # define UNUSED(param) (void)param;
68 # define UNUSED(param)
72 /***************************** EXCEPTION HANDLING *****************************/
73 #include "contrib/visupng/cexcept.h"
75 define_exception_type(struct png_store
*);
77 /* The following are macros to reduce typing everywhere where the well known
78 * name 'the_exception_context' must be defined.
80 #define anon_context(ps) struct exception_context *the_exception_context = \
81 &(ps)->exception_context
82 #define context(ps,fault) anon_context(ps); png_store *fault
84 /******************************* UTILITIES ************************************/
85 /* Error handling is particularly problematic in production code - error
86 * handlers often themselves have bugs which lead to programs that detect
87 * minor errors crashing. The following functions deal with one very
88 * common class of errors in error handlers - attempting to format error or
89 * warning messages into buffers that are too small.
91 static size_t safecat(char *buffer
, size_t bufsize
, size_t pos
,
94 while (pos
< bufsize
&& cat
!= NULL
&& *cat
!= 0)
95 buffer
[pos
++] = *cat
++;
104 static size_t safecatn(char *buffer
, size_t bufsize
, size_t pos
, int n
)
107 sprintf(number
, "%d", n
);
108 return safecat(buffer
, bufsize
, pos
, number
);
111 static size_t safecatd(char *buffer
, size_t bufsize
, size_t pos
, double d
,
115 sprintf(number
, "%.*f", precision
, d
);
116 return safecat(buffer
, bufsize
, pos
, number
);
119 static PNG_CONST
char invalid
[] = "invalid";
120 static PNG_CONST
char sep
[] = ": ";
122 /* NOTE: this is indexed by ln2(bit_depth)! */
123 static PNG_CONST
char *bit_depths
[8] =
125 "1", "2", "4", "8", "16", invalid
, invalid
, invalid
128 static PNG_CONST
char *colour_types
[8] =
130 "greyscale", invalid
, "truecolour", "indexed-colour",
131 "greyscale with alpha", invalid
, "truecolour with alpha", invalid
134 /* To get log-bit-depth from bit depth, returns 0 to 7 (7 on error). */
136 log2depth(png_byte bit_depth
)
160 /* A numeric ID based on PNG file characteristics. The 'do_interlace' field
161 * simply records whether pngvalid did the interlace itself or whether it
162 * was done by libpng. Width and height must be less than 256.
164 #define FILEID(col, depth, interlace, width, height, do_interlace) \
165 ((png_uint_32)((col) + ((depth)<<3) + ((interlace)<<8) + \
166 (((do_interlace)!=0)<<15) + ((width)<<16) + ((height)<<24)))
168 #define COL_FROM_ID(id) ((png_byte)((id)& 0x7U))
169 #define DEPTH_FROM_ID(id) ((png_byte)(((id) >> 3) & 0x1fU))
170 #define INTERLACE_FROM_ID(id) ((int)(((id) >> 8) & 0x3))
171 #define DO_INTERLACE_FROM_ID(id) ((int)(((id)>>15) & 1))
172 #define WIDTH_FROM_ID(id) (((id)>>16) & 0xff)
173 #define HEIGHT_FROM_ID(id) (((id)>>24) & 0xff)
175 /* Utility to construct a standard name for a standard image. */
177 standard_name(char *buffer
, size_t bufsize
, size_t pos
, png_byte colour_type
,
178 int log_bit_depth
, int interlace_type
, png_uint_32 w
, png_uint_32 h
,
181 pos
= safecat(buffer
, bufsize
, pos
, colour_types
[colour_type
]);
182 pos
= safecat(buffer
, bufsize
, pos
, " ");
183 pos
= safecat(buffer
, bufsize
, pos
, bit_depths
[log_bit_depth
]);
184 pos
= safecat(buffer
, bufsize
, pos
, " bit ");
186 if (interlace_type
!= PNG_INTERLACE_NONE
)
187 pos
= safecat(buffer
, bufsize
, pos
, "interlaced");
189 pos
= safecat(buffer
, bufsize
, pos
, "(pngvalid)");
191 pos
= safecat(buffer
, bufsize
, pos
, "(libpng)");
194 pos
= safecat(buffer
, bufsize
, pos
, " ");
195 pos
= safecatn(buffer
, bufsize
, pos
, w
);
196 pos
= safecat(buffer
, bufsize
, pos
, "x");
197 pos
= safecatn(buffer
, bufsize
, pos
, h
);
204 standard_name_from_id(char *buffer
, size_t bufsize
, size_t pos
, png_uint_32 id
)
206 return standard_name(buffer
, bufsize
, pos
, COL_FROM_ID(id
),
207 log2depth(DEPTH_FROM_ID(id
)), INTERLACE_FROM_ID(id
),
208 WIDTH_FROM_ID(id
), HEIGHT_FROM_ID(id
), DO_INTERLACE_FROM_ID(id
));
211 /* Convenience API and defines to list valid formats. Note that 16 bit read and
212 * write support is required to do 16 bit read tests (we must be able to make a
213 * 16 bit image to test!)
215 #ifdef PNG_WRITE_16BIT_SUPPORTED
216 # define WRITE_BDHI 4
217 # ifdef PNG_READ_16BIT_SUPPORTED
222 # define WRITE_BDHI 3
229 next_format(png_bytep colour_type
, png_bytep bit_depth
)
233 *colour_type
= 0, *bit_depth
= 1;
237 *bit_depth
= (png_byte
)(*bit_depth
<< 1);
239 /* Palette images are restricted to 8 bit depth */
242 || (*colour_type
!= 3 && *bit_depth
<= 16)
247 /* Move to the next color type, or return 0 at the end. */
248 switch (*colour_type
)
276 sample(png_const_bytep row
, png_byte colour_type
, png_byte bit_depth
,
277 png_uint_32 x
, unsigned int sample_index
)
279 png_uint_32 bit_index
, result
;
281 /* Find a sample index for the desired sample: */
285 if ((colour_type
& 1) == 0) /* !palette */
291 bit_index
+= x
; /* Alpha channel */
293 if (colour_type
& (2+4))
294 bit_index
+= sample_index
* bit_depth
; /* Multiple channels: select one */
297 /* Return the sample from the row as an integer. */
298 row
+= bit_index
>> 3;
304 else if (bit_depth
> 8)
305 return (result
<< 8) + *++row
;
307 /* Less than 8 bits per sample. */
309 return (result
>> (8-bit_index
-bit_depth
)) & ((1U<<bit_depth
)-1);
312 /* Copy a single pixel, of a given size, from one buffer to another -
313 * while this is basically bit addressed there is an implicit assumption
314 * that pixels 8 or more bits in size are byte aligned and that pixels
315 * do not otherwise cross byte boundaries. (This is, so far as I know,
316 * universally true in bitmap computer graphics. [JCB 20101212])
318 * NOTE: The to and from buffers may be the same.
321 pixel_copy(png_bytep toBuffer
, png_uint_32 toIndex
,
322 png_const_bytep fromBuffer
, png_uint_32 fromIndex
, unsigned int pixelSize
)
324 /* Assume we can multiply by 'size' without overflow because we are
325 * just working in a single buffer.
327 toIndex
*= pixelSize
;
328 fromIndex
*= pixelSize
;
329 if (pixelSize
< 8) /* Sub-byte */
331 /* Mask to select the location of the copied pixel: */
332 unsigned int destMask
= ((1U<<pixelSize
)-1) << (8-pixelSize
-(toIndex
&7));
333 /* The following read the entire pixels and clears the extra: */
334 unsigned int destByte
= toBuffer
[toIndex
>> 3] & ~destMask
;
335 unsigned int sourceByte
= fromBuffer
[fromIndex
>> 3];
337 /* Don't rely on << or >> supporting '0' here, just in case: */
339 if (fromIndex
> 0) sourceByte
<<= fromIndex
;
340 if ((toIndex
& 7) > 0) sourceByte
>>= toIndex
& 7;
342 toBuffer
[toIndex
>> 3] = (png_byte
)(destByte
| (sourceByte
& destMask
));
344 else /* One or more bytes */
345 memmove(toBuffer
+(toIndex
>>3), fromBuffer
+(fromIndex
>>3), pixelSize
>>3);
348 /* Compare pixels - they are assumed to start at the first byte in the
352 pixel_cmp(png_const_bytep pa
, png_const_bytep pb
, png_uint_32 bit_width
)
354 if (memcmp(pa
, pb
, bit_width
>>3) == 0)
358 if ((bit_width
& 7) == 0) return 0;
360 /* Ok, any differences? */
361 p
= pa
[bit_width
>> 3];
362 p
^= pb
[bit_width
>> 3];
364 if (p
== 0) return 0;
366 /* There are, but they may not be significant, remove the bits
367 * after the end (the low order bits in PNG.)
372 if (p
== 0) return 0;
375 return 1; /* Different */
378 /*************************** BASIC PNG FILE WRITING ***************************/
379 /* A png_store takes data from the sequential writer or provides data
380 * to the sequential reader. It can also store the result of a PNG
381 * write for later retrieval.
383 #define STORE_BUFFER_SIZE 500 /* arbitrary */
384 typedef struct png_store_buffer
386 struct png_store_buffer
* prev
; /* NOTE: stored in reverse order */
387 png_byte buffer
[STORE_BUFFER_SIZE
];
390 #define FILE_NAME_SIZE 64
392 typedef struct png_store_file
394 struct png_store_file
* next
; /* as many as you like... */
395 char name
[FILE_NAME_SIZE
];
396 png_uint_32 id
; /* must be correct (see FILEID) */
397 png_size_t datacount
; /* In this (the last) buffer */
398 png_store_buffer data
; /* Last buffer in file */
401 /* The following is a pool of memory allocated by a single libpng read or write
404 typedef struct store_pool
406 struct png_store
*store
; /* Back pointer */
407 struct store_memory
*list
; /* List of allocated memory */
408 png_byte mark
[4]; /* Before and after data */
410 /* Statistics for this run. */
411 png_alloc_size_t max
; /* Maximum single allocation */
412 png_alloc_size_t current
; /* Current allocation */
413 png_alloc_size_t limit
; /* Highest current allocation */
414 png_alloc_size_t total
; /* Total allocation */
416 /* Overall statistics (retained across successive runs). */
417 png_alloc_size_t max_max
;
418 png_alloc_size_t max_limit
;
419 png_alloc_size_t max_total
;
422 typedef struct png_store
424 /* For cexcept.h exception handling - simply store one of these;
425 * the context is a self pointer but it may point to a different
426 * png_store (in fact it never does in this program.)
428 struct exception_context
431 unsigned int verbose
:1;
432 unsigned int treat_warnings_as_errors
:1;
433 unsigned int expect_error
:1;
434 unsigned int expect_warning
:1;
435 unsigned int saw_warning
:1;
436 unsigned int speed
:1;
437 unsigned int progressive
:1; /* use progressive read */
438 unsigned int validated
:1; /* used as a temporary flag */
441 char test
[128]; /* Name of test */
445 png_structp pread
; /* Used to read a saved file */
447 png_store_file
* current
; /* Set when reading */
448 png_store_buffer
* next
; /* Set when reading */
449 png_size_t readpos
; /* Position in *next */
450 png_byte
* image
; /* Buffer for reading interlaced images */
451 size_t cb_image
; /* Size of this buffer */
452 store_pool read_memory_pool
;
455 png_store_file
* saved
;
456 png_structp pwrite
; /* Used when writing a new file */
458 png_size_t writepos
; /* Position in .new */
459 char wname
[FILE_NAME_SIZE
];
460 png_store_buffer
new; /* The end of the new PNG file being written. */
461 store_pool write_memory_pool
;
464 /* Initialization and cleanup */
466 store_pool_mark(png_byte
*mark
)
468 /* Generate a new mark. This uses a boring repeatable algorithm and it is
469 * implemented here so that it gives the same set of numbers on every
470 * architecture. It's a linear congruential generator (Knuth or Sedgewick
471 * "Algorithms") but it comes from the 'feedback taps' table in Horowitz and
472 * Hill, "The Art of Electronics".
474 static png_uint_32 u0
= 0x12345678, u1
= 1;
476 /* There are thirty three bits, the next bit in the sequence is bit-33 XOR
477 * bit-20. The top 1 bit is in u1, the bottom 32 are in u0.
482 /* First generate 8 new bits then shift them in at the end. */
483 png_uint_32 u
= ((u0
>> (20-8)) ^ ((u1
<< 7) | (u0
>> (32-7)))) & 0xff;
488 *mark
++ = (png_byte
)u
;
492 /* Use this for random 32 bit values, this function makes sure the result is
504 store_pool_mark(mark
);
505 result
= png_get_uint_32(mark
);
513 store_pool_init(png_store
*ps
, store_pool
*pool
)
515 memset(pool
, 0, sizeof *pool
);
519 pool
->max
= pool
->current
= pool
->limit
= pool
->total
= 0;
520 pool
->max_max
= pool
->max_limit
= pool
->max_total
= 0;
521 store_pool_mark(pool
->mark
);
525 store_init(png_store
* ps
)
527 memset(ps
, 0, sizeof *ps
);
528 init_exception_context(&ps
->exception_context
);
529 store_pool_init(ps
, &ps
->read_memory_pool
);
530 store_pool_init(ps
, &ps
->write_memory_pool
);
532 ps
->treat_warnings_as_errors
= 0;
533 ps
->expect_error
= 0;
534 ps
->expect_warning
= 0;
539 ps
->nerrors
= ps
->nwarnings
= 0;
542 ps
->saved
= ps
->current
= NULL
;
553 /* This somewhat odd function is used when reading an image to ensure that the
554 * buffer is big enough - this is why a png_structp is available.
557 store_ensure_image(png_store
*ps
, png_structp pp
, size_t cb
)
559 if (ps
->cb_image
< cb
)
561 if (ps
->image
!= NULL
)
567 /* The buffer is deliberately mis-aligned. */
568 ps
->image
= malloc(cb
+1);
569 if (ps
->image
== NULL
)
570 png_error(pp
, "OOM allocating image buffer");
576 /* And, for error checking, the whole buffer is set to '1' - this
577 * matches what happens with the 'size' test images on write and also
578 * matches the unused bits in the test rows.
580 memset(ps
->image
, 0xff, cb
);
584 store_freebuffer(png_store_buffer
* psb
)
588 store_freebuffer(psb
->prev
);
595 store_freenew(png_store
*ps
)
597 store_freebuffer(&ps
->new);
602 store_storenew(png_store
*ps
)
604 png_store_buffer
*pb
;
606 if (ps
->writepos
!= STORE_BUFFER_SIZE
)
607 png_error(ps
->pwrite
, "invalid store call");
609 pb
= malloc(sizeof *pb
);
612 png_error(ps
->pwrite
, "store new: OOM");
620 store_freefile(png_store_file
**ppf
)
624 store_freefile(&(*ppf
)->next
);
626 store_freebuffer(&(*ppf
)->data
);
627 (*ppf
)->datacount
= 0;
633 /* Main interface to file storeage, after writing a new PNG file (see the API
634 * below) call store_storefile to store the result with the given name and id.
637 store_storefile(png_store
*ps
, png_uint_32 id
)
639 png_store_file
*pf
= malloc(sizeof *pf
);
641 png_error(ps
->pwrite
, "storefile: OOM");
642 safecat(pf
->name
, sizeof pf
->name
, 0, ps
->wname
);
645 pf
->datacount
= ps
->writepos
;
650 pf
->next
= ps
->saved
;
654 /* Generate an error message (in the given buffer) */
656 store_message(png_store
*ps
, png_structp pp
, char *buffer
, size_t bufsize
,
657 size_t pos
, PNG_CONST
char *msg
)
659 if (pp
!= NULL
&& pp
== ps
->pread
)
662 pos
= safecat(buffer
, bufsize
, pos
, "read: ");
664 if (ps
->current
!= NULL
)
666 pos
= safecat(buffer
, bufsize
, pos
, ps
->current
->name
);
667 pos
= safecat(buffer
, bufsize
, pos
, sep
);
671 else if (pp
!= NULL
&& pp
== ps
->pwrite
)
674 pos
= safecat(buffer
, bufsize
, pos
, "write: ");
675 pos
= safecat(buffer
, bufsize
, pos
, ps
->wname
);
676 pos
= safecat(buffer
, bufsize
, pos
, sep
);
681 /* Neither reading nor writing (or a memory error in struct delete) */
682 pos
= safecat(buffer
, bufsize
, pos
, "pngvalid: ");
685 if (ps
->test
[0] != 0)
687 pos
= safecat(buffer
, bufsize
, pos
, ps
->test
);
688 pos
= safecat(buffer
, bufsize
, pos
, sep
);
690 pos
= safecat(buffer
, bufsize
, pos
, msg
);
694 /* Log an error or warning - the relevant count is always incremented. */
696 store_log(png_store
* ps
, png_structp pp
, png_const_charp message
, int is_error
)
698 /* The warning is copied to the error buffer if there are no errors and it is
699 * the first warning. The error is copied to the error buffer if it is the
700 * first error (overwriting any prior warnings).
702 if (is_error
? (ps
->nerrors
)++ == 0 :
703 (ps
->nwarnings
)++ == 0 && ps
->nerrors
== 0)
704 store_message(ps
, pp
, ps
->error
, sizeof ps
->error
, 0, message
);
712 pos
= safecat(buffer
, sizeof buffer
, 0, "error: ");
714 pos
= safecat(buffer
, sizeof buffer
, 0, "warning: ");
716 store_message(ps
, pp
, buffer
, sizeof buffer
, pos
, message
);
717 fputs(buffer
, stderr
);
722 /* Functions to use as PNG callbacks. */
724 store_error(png_structp pp
, png_const_charp message
) /* PNG_NORETURN */
726 png_store
*ps
= png_get_error_ptr(pp
);
728 if (!ps
->expect_error
)
729 store_log(ps
, pp
, message
, 1 /* error */);
731 /* And finally throw an exception. */
733 struct exception_context
*the_exception_context
= &ps
->exception_context
;
739 store_warning(png_structp pp
, png_const_charp message
)
741 png_store
*ps
= png_get_error_ptr(pp
);
743 if (!ps
->expect_warning
)
744 store_log(ps
, pp
, message
, 0 /* warning */);
750 store_write(png_structp pp
, png_bytep pb
, png_size_t st
)
752 png_store
*ps
= png_get_io_ptr(pp
);
754 if (ps
->pwrite
!= pp
)
755 png_error(pp
, "store state damaged");
761 if (ps
->writepos
>= STORE_BUFFER_SIZE
)
766 if (cb
> STORE_BUFFER_SIZE
- ps
->writepos
)
767 cb
= STORE_BUFFER_SIZE
- ps
->writepos
;
769 memcpy(ps
->new.buffer
+ ps
->writepos
, pb
, cb
);
777 store_flush(png_structp pp
)
779 UNUSED(pp
) /*DOES NOTHING*/
783 store_read_buffer_size(png_store
*ps
)
785 /* Return the bytes available for read in the current buffer. */
786 if (ps
->next
!= &ps
->current
->data
)
787 return STORE_BUFFER_SIZE
;
789 return ps
->current
->datacount
;
792 /* Return total bytes available for read. */
794 store_read_buffer_avail(png_store
*ps
)
796 if (ps
->current
!= NULL
&& ps
->next
!= NULL
)
798 png_store_buffer
*next
= &ps
->current
->data
;
799 size_t cbAvail
= ps
->current
->datacount
;
801 while (next
!= ps
->next
&& next
!= NULL
)
804 cbAvail
+= STORE_BUFFER_SIZE
;
807 if (next
!= ps
->next
)
808 png_error(ps
->pread
, "buffer read error");
810 if (cbAvail
> ps
->readpos
)
811 return cbAvail
- ps
->readpos
;
818 store_read_buffer_next(png_store
*ps
)
820 png_store_buffer
*pbOld
= ps
->next
;
821 png_store_buffer
*pbNew
= &ps
->current
->data
;
824 while (pbNew
!= NULL
&& pbNew
->prev
!= pbOld
)
834 png_error(ps
->pread
, "buffer lost");
837 return 0; /* EOF or error */
840 /* Need separate implementation and callback to allow use of the same code
841 * during progressive read, where the io_ptr is set internally by libpng.
844 store_read_imp(png_store
*ps
, png_bytep pb
, png_size_t st
)
846 if (ps
->current
== NULL
|| ps
->next
== NULL
)
847 png_error(ps
->pread
, "store state damaged");
851 size_t cbAvail
= store_read_buffer_size(ps
) - ps
->readpos
;
855 if (cbAvail
> st
) cbAvail
= st
;
856 memcpy(pb
, ps
->next
->buffer
+ ps
->readpos
, cbAvail
);
859 ps
->readpos
+= cbAvail
;
862 else if (!store_read_buffer_next(ps
))
863 png_error(ps
->pread
, "read beyond end of file");
868 store_read(png_structp pp
, png_bytep pb
, png_size_t st
)
870 png_store
*ps
= png_get_io_ptr(pp
);
872 if (ps
== NULL
|| ps
->pread
!= pp
)
873 png_error(pp
, "bad store read call");
875 store_read_imp(ps
, pb
, st
);
879 store_progressive_read(png_store
*ps
, png_structp pp
, png_infop pi
)
881 /* Notice that a call to store_read will cause this function to fail because
882 * readpos will be set.
884 if (ps
->pread
!= pp
|| ps
->current
== NULL
|| ps
->next
== NULL
)
885 png_error(pp
, "store state damaged (progressive)");
889 if (ps
->readpos
!= 0)
890 png_error(pp
, "store_read called during progressive read");
892 png_process_data(pp
, pi
, ps
->next
->buffer
, store_read_buffer_size(ps
));
894 while (store_read_buffer_next(ps
));
897 /***************************** MEMORY MANAGEMENT*** ***************************/
898 /* A store_memory is simply the header for an allocated block of memory. The
899 * pointer returned to libpng is just after the end of the header block, the
900 * allocated memory is followed by a second copy of the 'mark'.
902 typedef struct store_memory
904 store_pool
*pool
; /* Originating pool */
905 struct store_memory
*next
; /* Singly linked list */
906 png_alloc_size_t size
; /* Size of memory allocated */
907 png_byte mark
[4]; /* ID marker */
910 /* Handle a fatal error in memory allocation. This calls png_error if the
911 * libpng struct is non-NULL, else it outputs a message and returns. This means
912 * that a memory problem while libpng is running will abort (png_error) the
913 * handling of particular file while one in cleanup (after the destroy of the
914 * struct has returned) will simply keep going and free (or attempt to free)
918 store_pool_error(png_store
*ps
, png_structp pp
, PNG_CONST
char *msg
)
923 /* Else we have to do it ourselves. png_error eventually calls store_log,
924 * above. store_log accepts a NULL png_structp - it just changes what gets
925 * output by store_message.
927 store_log(ps
, pp
, msg
, 1 /* error */);
931 store_memory_free(png_structp pp
, store_pool
*pool
, store_memory
*memory
)
933 /* Note that pp may be NULL (see store_pool_delete below), the caller has
934 * found 'memory' in pool->list *and* unlinked this entry, so this is a valid
935 * pointer (for sure), but the contents may have been trashed.
937 if (memory
->pool
!= pool
)
938 store_pool_error(pool
->store
, pp
, "memory corrupted (pool)");
940 else if (memcmp(memory
->mark
, pool
->mark
, sizeof memory
->mark
) != 0)
941 store_pool_error(pool
->store
, pp
, "memory corrupted (start)");
943 /* It should be safe to read the size field now. */
946 png_alloc_size_t cb
= memory
->size
;
949 store_pool_error(pool
->store
, pp
, "memory corrupted (size)");
951 else if (memcmp((png_bytep
)(memory
+1)+cb
, pool
->mark
, sizeof pool
->mark
)
953 store_pool_error(pool
->store
, pp
, "memory corrupted (end)");
955 /* Finally give the library a chance to find problems too: */
965 store_pool_delete(png_store
*ps
, store_pool
*pool
)
967 if (pool
->list
!= NULL
)
969 fprintf(stderr
, "%s: %s %s: memory lost (list follows):\n", ps
->test
,
970 pool
== &ps
->read_memory_pool
? "read" : "write",
971 pool
== &ps
->read_memory_pool
? (ps
->current
!= NULL
?
972 ps
->current
->name
: "unknown file") : ps
->wname
);
977 store_memory
*next
= pool
->list
;
978 pool
->list
= next
->next
;
981 fprintf(stderr
, "\t%lu bytes @ %p\n",
982 (unsigned long)next
->size
, next
+1);
983 /* The NULL means this will always return, even if the memory is
986 store_memory_free(NULL
, pool
, next
);
988 while (pool
->list
!= NULL
);
991 /* And reset the other fields too for the next time. */
992 if (pool
->max
> pool
->max_max
) pool
->max_max
= pool
->max
;
994 if (pool
->current
!= 0) /* unexpected internal error */
995 fprintf(stderr
, "%s: %s %s: memory counter mismatch (internal error)\n",
996 ps
->test
, pool
== &ps
->read_memory_pool
? "read" : "write",
997 pool
== &ps
->read_memory_pool
? (ps
->current
!= NULL
?
998 ps
->current
->name
: "unknown file") : ps
->wname
);
1001 if (pool
->limit
> pool
->max_limit
)
1002 pool
->max_limit
= pool
->limit
;
1006 if (pool
->total
> pool
->max_total
)
1007 pool
->max_total
= pool
->total
;
1011 /* Get a new mark too. */
1012 store_pool_mark(pool
->mark
);
1015 /* The memory callbacks: */
1017 store_malloc(png_structp pp
, png_alloc_size_t cb
)
1019 store_pool
*pool
= png_get_mem_ptr(pp
);
1020 store_memory
*new = malloc(cb
+ (sizeof *new) + (sizeof pool
->mark
));
1027 pool
->current
+= cb
;
1029 if (pool
->current
> pool
->limit
)
1030 pool
->limit
= pool
->current
;
1035 memcpy(new->mark
, pool
->mark
, sizeof new->mark
);
1036 memcpy((png_byte
*)(new+1) + cb
, pool
->mark
, sizeof pool
->mark
);
1038 new->next
= pool
->list
;
1044 store_pool_error(pool
->store
, pp
, "out of memory");
1050 store_free(png_structp pp
, png_voidp memory
)
1052 store_pool
*pool
= png_get_mem_ptr(pp
);
1053 store_memory
*this = memory
, **test
;
1055 /* First check that this 'memory' really is valid memory - it must be in the
1056 * pool list. If it is, use the shared memory_free function to free it.
1059 for (test
= &pool
->list
; *test
!= this; test
= &(*test
)->next
)
1063 store_pool_error(pool
->store
, pp
, "bad pointer to free");
1068 /* Unlink this entry, *test == this. */
1071 store_memory_free(pp
, pool
, this);
1074 /* Setup functions. */
1075 /* Cleanup when aborting a write or after storing the new file. */
1077 store_write_reset(png_store
*ps
)
1079 if (ps
->pwrite
!= NULL
)
1084 png_destroy_write_struct(&ps
->pwrite
, &ps
->piwrite
);
1088 /* memory corruption: continue. */
1095 /* And make sure that all the memory has been freed - this will output
1096 * spurious errors in the case of memory corruption above, but this is safe.
1098 store_pool_delete(ps
, &ps
->write_memory_pool
);
1103 /* The following is the main write function, it returns a png_struct and,
1104 * optionally, a png_info suitable for writiing a new PNG file. Use
1105 * store_storefile above to record this file after it has been written. The
1106 * returned libpng structures as destroyed by store_write_reset above.
1109 set_store_for_write(png_store
*ps
, png_infopp ppi
,
1110 PNG_CONST
char * volatile name
)
1116 if (ps
->pwrite
!= NULL
)
1117 png_error(ps
->pwrite
, "write store already in use");
1119 store_write_reset(ps
);
1120 safecat(ps
->wname
, sizeof ps
->wname
, 0, name
);
1122 /* Don't do the slow memory checks if doing a speed test. */
1124 ps
->pwrite
= png_create_write_struct(PNG_LIBPNG_VER_STRING
,
1125 ps
, store_error
, store_warning
);
1128 ps
->pwrite
= png_create_write_struct_2(PNG_LIBPNG_VER_STRING
,
1129 ps
, store_error
, store_warning
, &ps
->write_memory_pool
,
1130 store_malloc
, store_free
);
1132 png_set_write_fn(ps
->pwrite
, ps
, store_write
, store_flush
);
1135 *ppi
= ps
->piwrite
= png_create_info_struct(ps
->pwrite
);
1144 /* Cleanup when finished reading (either due to error or in the success case).
1147 store_read_reset(png_store
*ps
)
1149 if (ps
->pread
!= NULL
)
1154 png_destroy_read_struct(&ps
->pread
, &ps
->piread
, NULL
);
1158 /* error already output: continue */
1165 /* Always do this to be safe. */
1166 store_pool_delete(ps
, &ps
->read_memory_pool
);
1175 store_read_set(png_store
*ps
, png_uint_32 id
)
1177 png_store_file
*pf
= ps
->saved
;
1185 store_read_buffer_next(ps
);
1194 char msg
[FILE_NAME_SIZE
+64];
1196 pos
= standard_name_from_id(msg
, sizeof msg
, 0, id
);
1197 pos
= safecat(msg
, sizeof msg
, pos
, ": file not found");
1198 png_error(ps
->pread
, msg
);
1202 /* The main interface for reading a saved file - pass the id number of the file
1203 * to retrieve. Ids must be unique or the earlier file will be hidden. The API
1204 * returns a png_struct and, optionally, a png_info. Both of these will be
1205 * destroyed by store_read_reset above.
1208 set_store_for_read(png_store
*ps
, png_infopp ppi
, png_uint_32 id
,
1209 PNG_CONST
char *name
)
1211 /* Set the name for png_error */
1212 safecat(ps
->test
, sizeof ps
->test
, 0, name
);
1214 if (ps
->pread
!= NULL
)
1215 png_error(ps
->pread
, "read store already in use");
1217 store_read_reset(ps
);
1219 /* Both the create APIs can return NULL if used in their default mode
1220 * (because there is no other way of handling an error because the jmp_buf
1221 * by default is stored in png_struct and that has not been allocated!)
1222 * However, given that store_error works correctly in these circumstances
1223 * we don't ever expect NULL in this program.
1226 ps
->pread
= png_create_read_struct(PNG_LIBPNG_VER_STRING
, ps
,
1227 store_error
, store_warning
);
1230 ps
->pread
= png_create_read_struct_2(PNG_LIBPNG_VER_STRING
, ps
,
1231 store_error
, store_warning
, &ps
->read_memory_pool
, store_malloc
,
1234 if (ps
->pread
== NULL
)
1236 struct exception_context
*the_exception_context
= &ps
->exception_context
;
1238 store_log(ps
, NULL
, "png_create_read_struct returned NULL (unexpected)",
1244 store_read_set(ps
, id
);
1247 *ppi
= ps
->piread
= png_create_info_struct(ps
->pread
);
1252 /* The overall cleanup of a store simply calls the above then removes all the
1253 * saved files. This does not delete the store itself.
1256 store_delete(png_store
*ps
)
1258 store_write_reset(ps
);
1259 store_read_reset(ps
);
1260 store_freefile(&ps
->saved
);
1262 if (ps
->image
!= NULL
)
1270 /*********************** PNG FILE MODIFICATION ON READ ************************/
1271 /* Files may be modified on read. The following structure contains a complete
1272 * png_store together with extra members to handle modification and a special
1273 * read callback for libpng. To use this the 'modifications' field must be set
1274 * to a list of png_modification structures that actually perform the
1275 * modification, otherwise a png_modifier is functionally equivalent to a
1276 * png_store. There is a special read function, set_modifier_for_read, which
1277 * replaces set_store_for_read.
1279 typedef struct png_modifier
1281 png_store
this; /* I am a png_store */
1282 struct png_modification
*modifications
; /* Changes to make */
1286 modifier_start
, /* Initial value */
1287 modifier_signature
, /* Have a signature */
1288 modifier_IHDR
/* Have an IHDR */
1289 } state
; /* My state */
1291 /* Information from IHDR: */
1292 png_byte bit_depth
; /* From IHDR */
1293 png_byte colour_type
; /* From IHDR */
1295 /* While handling PLTE, IDAT and IEND these chunks may be pended to allow
1296 * other chunks to be inserted.
1298 png_uint_32 pending_len
;
1299 png_uint_32 pending_chunk
;
1303 unsigned int ngammas
;
1305 /* Lowest sbit to test (libpng fails for sbit < 8) */
1308 /* Error control - these are the limits on errors accepted by the gamma tests
1311 double maxout8
; /* Maximum output value error */
1312 double maxabs8
; /* Absolute sample error 0..1 */
1313 double maxpc8
; /* Percentage sample error 0..100% */
1314 double maxout16
; /* Maximum output value error */
1315 double maxabs16
; /* Absolute sample error 0..1 */
1316 double maxpc16
; /* Percentage sample error 0..100% */
1318 /* Logged 8 and 16 bit errors ('output' values): */
1319 double error_gray_2
;
1320 double error_gray_4
;
1321 double error_gray_8
;
1322 double error_gray_16
;
1323 double error_color_8
;
1324 double error_color_16
;
1327 /* Whether or not to interlace. */
1328 int interlace_type
:9; /* int, but must store '1' */
1330 /* Run the standard tests? */
1331 unsigned int test_standard
:1;
1333 /* Run the odd-sized image and interlace read/write tests? */
1334 unsigned int test_size
:1;
1336 /* Run tests on reading with a combiniation of transforms, */
1337 unsigned int test_transform
:1;
1339 /* When to use the use_input_precision option: */
1340 unsigned int use_input_precision
:1;
1341 unsigned int use_input_precision_sbit
:1;
1342 unsigned int use_input_precision_16to8
:1;
1344 /* Which gamma tests to run: */
1345 unsigned int test_gamma_threshold
:1;
1346 unsigned int test_gamma_transform
:1; /* main tests */
1347 unsigned int test_gamma_sbit
:1;
1348 unsigned int test_gamma_strip16
:1;
1350 unsigned int log
:1; /* Log max error */
1352 /* Buffer information, the buffer size limits the size of the chunks that can
1353 * be modified - they must fit (including header and CRC) into the buffer!
1355 size_t flush
; /* Count of bytes to flush */
1356 size_t buffer_count
; /* Bytes in buffer */
1357 size_t buffer_position
; /* Position in buffer */
1358 png_byte buffer
[1024];
1361 static double abserr(png_modifier
*pm
, png_byte bit_depth
)
1363 return bit_depth
== 16 ? pm
->maxabs16
: pm
->maxabs8
;
1366 static double pcerr(png_modifier
*pm
, png_byte bit_depth
)
1368 return (bit_depth
== 16 ? pm
->maxpc16
: pm
->maxpc8
) * .01;
1371 static double outerr(png_modifier
*pm
, png_byte bit_depth
)
1373 /* There is a serious error in the 2 and 4 bit grayscale transform because
1374 * the gamma table value (8 bits) is simply shifted, not rounded, so the
1375 * error in 4 bit greyscale gamma is up to the value below. This is a hack
1376 * to allow pngvalid to succeed:
1384 if (bit_depth
== 16)
1385 return pm
->maxout16
;
1390 /* This returns true if the test should be stopped now because it has already
1391 * failed and it is running silently.
1393 static int fail(png_modifier
*pm
)
1395 return !pm
->log
&& !pm
->this.verbose
&& (pm
->this.nerrors
> 0 ||
1396 (pm
->this.treat_warnings_as_errors
&& pm
->this.nwarnings
> 0));
1400 modifier_init(png_modifier
*pm
)
1402 memset(pm
, 0, sizeof *pm
);
1403 store_init(&pm
->this);
1404 pm
->modifications
= NULL
;
1405 pm
->state
= modifier_start
;
1407 pm
->maxout8
= pm
->maxpc8
= pm
->maxabs8
= 0;
1408 pm
->maxout16
= pm
->maxpc16
= pm
->maxabs16
= 0;
1409 pm
->error_gray_2
= pm
->error_gray_4
= pm
->error_gray_8
= 0;
1410 pm
->error_gray_16
= pm
->error_color_8
= pm
->error_color_16
= 0;
1411 pm
->interlace_type
= PNG_INTERLACE_NONE
;
1412 pm
->test_standard
= 0;
1414 pm
->test_transform
= 0;
1415 pm
->use_input_precision
= 0;
1416 pm
->use_input_precision_sbit
= 0;
1417 pm
->use_input_precision_16to8
= 0;
1418 pm
->test_gamma_threshold
= 0;
1419 pm
->test_gamma_transform
= 0;
1420 pm
->test_gamma_sbit
= 0;
1421 pm
->test_gamma_strip16
= 0;
1424 /* Rely on the memset for all the other fields - there are no pointers */
1427 /* One modification structure must be provided for each chunk to be modified (in
1428 * fact more than one can be provided if multiple separate changes are desired
1429 * for a single chunk.) Modifications include adding a new chunk when a
1430 * suitable chunk does not exist.
1432 * The caller of modify_fn will reset the CRC of the chunk and record 'modified'
1433 * or 'added' as appropriate if the modify_fn returns 1 (true). If the
1434 * modify_fn is NULL the chunk is simply removed.
1436 typedef struct png_modification
1438 struct png_modification
*next
;
1441 /* If the following is NULL all matching chunks will be removed: */
1442 int (*modify_fn
)(struct png_modifier
*pm
,
1443 struct png_modification
*me
, int add
);
1445 /* If the following is set to PLTE, IDAT or IEND and the chunk has not been
1446 * found and modified (and there is a modify_fn) the modify_fn will be called
1447 * to add the chunk before the relevant chunk.
1450 unsigned int modified
:1; /* Chunk was modified */
1451 unsigned int added
:1; /* Chunk was added */
1452 unsigned int removed
:1; /* Chunk was removed */
1455 static void modification_reset(png_modification
*pmm
)
1462 modification_reset(pmm
->next
);
1467 modification_init(png_modification
*pmm
)
1469 memset(pmm
, 0, sizeof *pmm
);
1472 pmm
->modify_fn
= NULL
;
1474 modification_reset(pmm
);
1478 modifier_reset(png_modifier
*pm
)
1480 store_read_reset(&pm
->this);
1481 pm
->modifications
= NULL
;
1482 pm
->state
= modifier_start
;
1483 pm
->bit_depth
= pm
->colour_type
= 0;
1484 pm
->pending_len
= pm
->pending_chunk
= 0;
1485 pm
->flush
= pm
->buffer_count
= pm
->buffer_position
= 0;
1488 /* Convenience macros. */
1489 #define CHUNK(a,b,c,d) (((a)<<24)+((b)<<16)+((c)<<8)+(d))
1490 #define CHUNK_IHDR CHUNK(73,72,68,82)
1491 #define CHUNK_PLTE CHUNK(80,76,84,69)
1492 #define CHUNK_IDAT CHUNK(73,68,65,84)
1493 #define CHUNK_IEND CHUNK(73,69,78,68)
1494 #define CHUNK_cHRM CHUNK(99,72,82,77)
1495 #define CHUNK_gAMA CHUNK(103,65,77,65)
1496 #define CHUNK_sBIT CHUNK(115,66,73,84)
1497 #define CHUNK_sRGB CHUNK(115,82,71,66)
1499 /* The guts of modification are performed during a read. */
1501 modifier_crc(png_bytep buffer
)
1503 /* Recalculate the chunk CRC - a complete chunk must be in
1504 * the buffer, at the start.
1506 uInt datalen
= png_get_uint_32(buffer
);
1507 png_save_uint_32(buffer
+datalen
+8, crc32(0L, buffer
+4, datalen
+4));
1511 modifier_setbuffer(png_modifier
*pm
)
1513 modifier_crc(pm
->buffer
);
1514 pm
->buffer_count
= png_get_uint_32(pm
->buffer
)+12;
1515 pm
->buffer_position
= 0;
1518 /* Separate the callback into the actual implementation (which is passed the
1519 * png_modifier explicitly) and the callback, which gets the modifier from the
1523 modifier_read_imp(png_modifier
*pm
, png_bytep pb
, png_size_t st
)
1528 png_uint_32 len
, chunk
;
1529 png_modification
*mod
;
1531 if (pm
->buffer_position
>= pm
->buffer_count
) switch (pm
->state
)
1533 static png_byte sign
[8] = { 137, 80, 78, 71, 13, 10, 26, 10 };
1534 case modifier_start
:
1535 store_read_imp(&pm
->this, pm
->buffer
, 8); /* size of signature. */
1536 pm
->buffer_count
= 8;
1537 pm
->buffer_position
= 0;
1539 if (memcmp(pm
->buffer
, sign
, 8) != 0)
1540 png_error(pm
->this.pread
, "invalid PNG file signature");
1541 pm
->state
= modifier_signature
;
1544 case modifier_signature
:
1545 store_read_imp(&pm
->this, pm
->buffer
, 13+12); /* size of IHDR */
1546 pm
->buffer_count
= 13+12;
1547 pm
->buffer_position
= 0;
1549 if (png_get_uint_32(pm
->buffer
) != 13 ||
1550 png_get_uint_32(pm
->buffer
+4) != CHUNK_IHDR
)
1551 png_error(pm
->this.pread
, "invalid IHDR");
1553 /* Check the list of modifiers for modifications to the IHDR. */
1554 mod
= pm
->modifications
;
1557 if (mod
->chunk
== CHUNK_IHDR
&& mod
->modify_fn
&&
1558 (*mod
->modify_fn
)(pm
, mod
, 0))
1561 modifier_setbuffer(pm
);
1564 /* Ignore removal or add if IHDR! */
1568 /* Cache information from the IHDR (the modified one.) */
1569 pm
->bit_depth
= pm
->buffer
[8+8];
1570 pm
->colour_type
= pm
->buffer
[8+8+1];
1572 pm
->state
= modifier_IHDR
;
1578 /* Read a new chunk and process it until we see PLTE, IDAT or
1579 * IEND. 'flush' indicates that there is still some data to
1580 * output from the preceding chunk.
1582 if ((cb
= pm
->flush
) > 0)
1584 if (cb
> st
) cb
= st
;
1586 store_read_imp(&pm
->this, pb
, cb
);
1589 if (st
<= 0) return;
1592 /* No more bytes to flush, read a header, or handle a pending
1595 if (pm
->pending_chunk
!= 0)
1597 png_save_uint_32(pm
->buffer
, pm
->pending_len
);
1598 png_save_uint_32(pm
->buffer
+4, pm
->pending_chunk
);
1599 pm
->pending_len
= 0;
1600 pm
->pending_chunk
= 0;
1603 store_read_imp(&pm
->this, pm
->buffer
, 8);
1605 pm
->buffer_count
= 8;
1606 pm
->buffer_position
= 0;
1608 /* Check for something to modify or a terminator chunk. */
1609 len
= png_get_uint_32(pm
->buffer
);
1610 chunk
= png_get_uint_32(pm
->buffer
+4);
1612 /* Terminators first, they may have to be delayed for added
1615 if (chunk
== CHUNK_PLTE
|| chunk
== CHUNK_IDAT
||
1616 chunk
== CHUNK_IEND
)
1618 mod
= pm
->modifications
;
1622 if ((mod
->add
== chunk
||
1623 (mod
->add
== CHUNK_PLTE
&& chunk
== CHUNK_IDAT
)) &&
1624 mod
->modify_fn
!= NULL
&& !mod
->modified
&& !mod
->added
)
1626 /* Regardless of what the modify function does do not run
1631 if ((*mod
->modify_fn
)(pm
, mod
, 1 /*add*/))
1633 /* Reset the CRC on a new chunk */
1634 if (pm
->buffer_count
> 0)
1635 modifier_setbuffer(pm
);
1639 pm
->buffer_position
= 0;
1643 /* The buffer has been filled with something (we assume)
1644 * so output this. Pend the current chunk.
1646 pm
->pending_len
= len
;
1647 pm
->pending_chunk
= chunk
;
1648 break; /* out of while */
1655 /* Don't do any further processing if the buffer was modified -
1656 * otherwise the code will end up modifying a chunk that was
1660 break; /* out of switch */
1663 /* If we get to here then this chunk may need to be modified. To
1664 * do this it must be less than 1024 bytes in total size, otherwise
1665 * it just gets flushed.
1667 if (len
+12 <= sizeof pm
->buffer
)
1669 store_read_imp(&pm
->this, pm
->buffer
+pm
->buffer_count
,
1670 len
+12-pm
->buffer_count
);
1671 pm
->buffer_count
= len
+12;
1673 /* Check for a modification, else leave it be. */
1674 mod
= pm
->modifications
;
1677 if (mod
->chunk
== chunk
)
1679 if (mod
->modify_fn
== NULL
)
1681 /* Remove this chunk */
1682 pm
->buffer_count
= pm
->buffer_position
= 0;
1684 break; /* Terminate the while loop */
1687 else if ((*mod
->modify_fn
)(pm
, mod
, 0))
1690 /* The chunk may have been removed: */
1691 if (pm
->buffer_count
== 0)
1693 pm
->buffer_position
= 0;
1696 modifier_setbuffer(pm
);
1705 pm
->flush
= len
+12 - pm
->buffer_count
; /* data + crc */
1707 /* Take the data from the buffer (if there is any). */
1711 /* Here to read from the modifier buffer (not directly from
1712 * the store, as in the flush case above.)
1714 cb
= pm
->buffer_count
- pm
->buffer_position
;
1719 memcpy(pb
, pm
->buffer
+ pm
->buffer_position
, cb
);
1722 pm
->buffer_position
+= cb
;
1728 modifier_read(png_structp pp
, png_bytep pb
, png_size_t st
)
1730 png_modifier
*pm
= png_get_io_ptr(pp
);
1732 if (pm
== NULL
|| pm
->this.pread
!= pp
)
1733 png_error(pp
, "bad modifier_read call");
1735 modifier_read_imp(pm
, pb
, st
);
1738 /* Like store_progressive_read but the data is getting changed as we go so we
1739 * need a local buffer.
1742 modifier_progressive_read(png_modifier
*pm
, png_structp pp
, png_infop pi
)
1744 if (pm
->this.pread
!= pp
|| pm
->this.current
== NULL
||
1745 pm
->this.next
== NULL
)
1746 png_error(pp
, "store state damaged (progressive)");
1748 /* This is another Horowitz and Hill random noise generator. In this case
1749 * the aim is to stress the progressive reader with truely horrible variable
1750 * buffer sizes in the range 1..500, so a sequence of 9 bit random numbers
1751 * is generated. We could probably just count from 1 to 32767 and get as
1756 static png_uint_32 noise
= 1;
1757 png_size_t cb
, cbAvail
;
1758 png_byte buffer
[512];
1760 /* Generate 15 more bits of stuff: */
1761 noise
= (noise
<< 9) | ((noise
^ (noise
>> (9-5))) & 0x1ff);
1764 /* Check that this number of bytes are available (in the current buffer.)
1765 * (This doesn't quite work - the modifier might delete a chunk; unlikely
1766 * but possible, it doesn't happen at present because the modifier only
1767 * adds chunks to standard images.)
1769 cbAvail
= store_read_buffer_avail(&pm
->this);
1770 if (pm
->buffer_count
> pm
->buffer_position
)
1771 cbAvail
+= pm
->buffer_count
- pm
->buffer_position
;
1775 /* Check for EOF: */
1782 modifier_read_imp(pm
, buffer
, cb
);
1783 png_process_data(pp
, pi
, buffer
, cb
);
1786 /* Check the invariants at the end (if this fails it's a problem in this
1789 if (pm
->buffer_count
> pm
->buffer_position
||
1790 pm
->this.next
!= &pm
->this.current
->data
||
1791 pm
->this.readpos
< pm
->this.current
->datacount
)
1792 png_error(pp
, "progressive read implementation error");
1795 /* Set up a modifier. */
1797 set_modifier_for_read(png_modifier
*pm
, png_infopp ppi
, png_uint_32 id
,
1798 PNG_CONST
char *name
)
1800 /* Do this first so that the modifier fields are cleared even if an error
1801 * happens allocating the png_struct. No allocation is done here so no
1802 * cleanup is required.
1804 pm
->state
= modifier_start
;
1806 pm
->colour_type
= 255;
1808 pm
->pending_len
= 0;
1809 pm
->pending_chunk
= 0;
1811 pm
->buffer_count
= 0;
1812 pm
->buffer_position
= 0;
1814 return set_store_for_read(&pm
->this, ppi
, id
, name
);
1817 /***************************** STANDARD PNG FILES *****************************/
1818 /* Standard files - write and save standard files. */
1819 /* There are two basic forms of standard images. Those which attempt to have
1820 * all the possible pixel values (not possible for 16bpp images, but a range of
1821 * values are produced) and those which have a range of image sizes. The former
1822 * are used for testing transforms, in particular gamma correction and bit
1823 * reduction and increase. The latter are reserved for testing the behavior of
1824 * libpng with respect to 'odd' image sizes - particularly small images where
1825 * rows become 1 byte and interlace passes disappear.
1827 * The first, most useful, set are the 'transform' images, the second set of
1828 * small images are the 'size' images.
1830 * The transform files are constructed with rows which fit into a 1024 byte row
1831 * buffer. This makes allocation easier below. Further regardless of the file
1832 * format every row has 128 pixels (giving 1024 bytes for 64bpp formats).
1834 * Files are stored with no gAMA or sBIT chunks, with a PLTE only when needed
1835 * and with an ID derived from the colour type, bit depth and interlace type
1836 * as above (FILEID). The width (128) and height (variable) are not stored in
1837 * the FILEID - instead the fields are set to 0, indicating a transform file.
1839 * The size files ar constructed with rows a maximum of 128 bytes wide, allowing
1840 * a maximum width of 16 pixels (for the 64bpp case.) They also have a maximum
1841 * height of 16 rows. The width and height are stored in the FILEID and, being
1842 * non-zero, indicate a size file.
1845 /* The number of passes is related to the interlace type. There wass no libpng
1846 * API to determine this prior to 1.5, so we need an inquiry function:
1849 npasses_from_interlace_type(png_structp pp
, int interlace_type
)
1851 switch (interlace_type
)
1854 png_error(pp
, "invalid interlace type");
1856 case PNG_INTERLACE_NONE
:
1859 case PNG_INTERLACE_ADAM7
:
1860 return PNG_INTERLACE_ADAM7_PASSES
;
1865 bit_size(png_structp pp
, png_byte colour_type
, png_byte bit_depth
)
1867 switch (colour_type
)
1869 case 0: return bit_depth
;
1871 case 2: return 3*bit_depth
;
1873 case 3: return bit_depth
;
1875 case 4: return 2*bit_depth
;
1877 case 6: return 4*bit_depth
;
1879 default: png_error(pp
, "invalid color type");
1883 #define TRANSFORM_WIDTH 128U
1884 #define TRANSFORM_ROWMAX (TRANSFORM_WIDTH*8U)
1885 #define SIZE_ROWMAX (16*8U) /* 16 pixels, max 8 bytes each - 128 bytes */
1886 #define STANDARD_ROWMAX TRANSFORM_ROWMAX /* The larger of the two */
1888 /* So the maximum image sizes are as follows. A 'transform' image may require
1889 * more than 65535 bytes. The size images are a maximum of 2046 bytes.
1891 #define TRANSFORM_IMAGEMAX (TRANSFORM_ROWMAX * (png_uint_32)2048)
1892 #define SIZE_IMAGEMAX (SIZE_ROWMAX * 16U)
1895 transform_rowsize(png_structp pp
, png_byte colour_type
, png_byte bit_depth
)
1897 return (TRANSFORM_WIDTH
* bit_size(pp
, colour_type
, bit_depth
)) / 8;
1900 /* transform_width(pp, colour_type, bit_depth) current returns the same number
1901 * every time, so just use a macro:
1903 #define transform_width(pp, colour_type, bit_depth) TRANSFORM_WIDTH
1906 transform_height(png_structp pp
, png_byte colour_type
, png_byte bit_depth
)
1908 switch (bit_size(pp
, colour_type
, bit_depth
))
1913 return 1; /* Total of 128 pixels */
1916 return 2; /* Total of 256 pixels/bytes */
1919 return 512; /* Total of 65536 pixels */
1923 return 512; /* 65536 pixels */
1927 return 2048;/* 4 x 65536 pixels. */
1930 return 0; /* Error, will be caught later */
1934 /* The following can only be defined here, now we have the definitions
1935 * of the transform image sizes.
1938 standard_width(png_structp pp
, png_uint_32 id
)
1940 png_uint_32 width
= WIDTH_FROM_ID(id
);
1944 width
= transform_width(pp
, COL_FROM_ID(id
), DEPTH_FROM_ID(id
));
1950 standard_height(png_structp pp
, png_uint_32 id
)
1952 png_uint_32 height
= HEIGHT_FROM_ID(id
);
1955 height
= transform_height(pp
, COL_FROM_ID(id
), DEPTH_FROM_ID(id
));
1961 standard_rowsize(png_structp pp
, png_uint_32 id
)
1963 png_uint_32 width
= standard_width(pp
, id
);
1965 /* This won't overflow: */
1966 width
*= bit_size(pp
, COL_FROM_ID(id
), DEPTH_FROM_ID(id
));
1967 return (width
+ 7) / 8;
1971 transform_row(png_structp pp
, png_byte buffer
[TRANSFORM_ROWMAX
],
1972 png_byte colour_type
, png_byte bit_depth
, png_uint_32 y
)
1974 png_uint_32 v
= y
<< 7;
1977 switch (bit_size(pp
, colour_type
, bit_depth
))
1980 while (i
<128/8) buffer
[i
] = v
& 0xff, v
+= 17, ++i
;
1984 while (i
<128/4) buffer
[i
] = v
& 0xff, v
+= 33, ++i
;
1988 while (i
<128/2) buffer
[i
] = v
& 0xff, v
+= 65, ++i
;
1992 /* 256 bytes total, 128 bytes in each row set as follows: */
1993 while (i
<128) buffer
[i
] = v
& 0xff, ++v
, ++i
;
1997 /* Generate all 65536 pixel values in order, which includes the 8 bit
1998 * GA case as well as the 16 bit G case.
2001 buffer
[2*i
] = (v
>>8) & 0xff, buffer
[2*i
+1] = v
& 0xff, ++v
, ++i
;
2006 /* 65535 pixels, but rotate the values. */
2009 /* Three bytes per pixel, r, g, b, make b by r^g */
2010 buffer
[3*i
+0] = (v
>> 8) & 0xff;
2011 buffer
[3*i
+1] = v
& 0xff;
2012 buffer
[3*i
+2] = ((v
>> 8) ^ v
) & 0xff;
2020 /* 65535 pixels, r, g, b, a; just replicate */
2023 buffer
[4*i
+0] = (v
>> 8) & 0xff;
2024 buffer
[4*i
+1] = v
& 0xff;
2025 buffer
[4*i
+2] = (v
>> 8) & 0xff;
2026 buffer
[4*i
+3] = v
& 0xff;
2034 /* y is maximum 2047, giving 4x65536 pixels, make 'r' increase by 1 at
2035 * each pixel, g increase by 257 (0x101) and 'b' by 0x1111:
2039 png_uint_32 t
= v
++;
2040 buffer
[6*i
+0] = (t
>> 8) & 0xff;
2041 buffer
[6*i
+1] = t
& 0xff;
2043 buffer
[6*i
+2] = (t
>> 8) & 0xff;
2044 buffer
[6*i
+3] = t
& 0xff;
2046 buffer
[6*i
+4] = (t
>> 8) & 0xff;
2047 buffer
[6*i
+5] = t
& 0xff;
2054 /* As above in the 32 bit case. */
2057 png_uint_32 t
= v
++;
2058 buffer
[8*i
+0] = (t
>> 8) & 0xff;
2059 buffer
[8*i
+1] = t
& 0xff;
2060 buffer
[8*i
+4] = (t
>> 8) & 0xff;
2061 buffer
[8*i
+5] = t
& 0xff;
2063 buffer
[8*i
+2] = (t
>> 8) & 0xff;
2064 buffer
[8*i
+3] = t
& 0xff;
2065 buffer
[8*i
+6] = (t
>> 8) & 0xff;
2066 buffer
[8*i
+7] = t
& 0xff;
2075 png_error(pp
, "internal error");
2078 /* This is just to do the right cast - could be changed to a function to check
2079 * 'bd' but there isn't much point.
2081 #define DEPTH(bd) ((png_byte)(1U << (bd)))
2083 /* Make a standardized image given a an image colour type, bit depth and
2084 * interlace type. The standard images have a very restricted range of
2085 * rows and heights and are used for testing transforms rather than image
2086 * layout details. See make_size_images below for a way to make images
2087 * that test odd sizes along with the libpng interlace handling.
2090 make_transform_image(png_store
* PNG_CONST ps
, png_byte PNG_CONST colour_type
,
2091 png_byte PNG_CONST bit_depth
, int interlace_type
, png_const_charp name
)
2098 png_structp pp
= set_store_for_write(ps
, &pi
, name
);
2101 /* In the event of a problem return control to the Catch statement below
2102 * to do the clean up - it is not possible to 'return' directly from a Try
2108 h
= transform_height(pp
, colour_type
, bit_depth
);
2110 png_set_IHDR(pp
, pi
, transform_width(pp
, colour_type
, bit_depth
), h
,
2111 bit_depth
, colour_type
, interlace_type
,
2112 PNG_COMPRESSION_TYPE_BASE
, PNG_FILTER_TYPE_BASE
);
2114 if (colour_type
== 3) /* palette */
2120 pal
[i
].red
= pal
[i
].green
= pal
[i
].blue
= (png_byte
)i
;
2123 png_set_PLTE(pp
, pi
, pal
, 256);
2126 png_write_info(pp
, pi
);
2128 if (png_get_rowbytes(pp
, pi
) !=
2129 transform_rowsize(pp
, colour_type
, bit_depth
))
2130 png_error(pp
, "row size incorrect");
2134 /* Somewhat confusingly this must be called *after* png_write_info
2135 * because if it is called before, the information in *pp has not been
2136 * updated to reflect the interlaced image.
2138 int npasses
= png_set_interlace_handling(pp
);
2141 if (npasses
!= npasses_from_interlace_type(pp
, interlace_type
))
2142 png_error(pp
, "write: png_set_interlace_handling failed");
2144 for (pass
=0; pass
<npasses
; ++pass
)
2150 png_byte buffer
[TRANSFORM_ROWMAX
];
2152 transform_row(pp
, buffer
, colour_type
, bit_depth
, y
);
2153 png_write_row(pp
, buffer
);
2158 png_write_end(pp
, pi
);
2160 /* And store this under the appropriate id, then clean up. */
2161 store_storefile(ps
, FILEID(colour_type
, bit_depth
, interlace_type
,
2164 store_write_reset(ps
);
2169 /* Use the png_store returned by the exception. This may help the compiler
2170 * because 'ps' is not used in this branch of the setjmp. Note that fault
2171 * and ps will always be the same value.
2173 store_write_reset(fault
);
2178 make_standard(png_store
* PNG_CONST ps
, png_byte PNG_CONST colour_type
, int bdlo
,
2181 for (; bdlo
<= bdhi
; ++bdlo
)
2185 for (interlace_type
= PNG_INTERLACE_NONE
;
2186 interlace_type
< PNG_INTERLACE_LAST
; ++interlace_type
)
2188 char name
[FILE_NAME_SIZE
];
2190 standard_name(name
, sizeof name
, 0, colour_type
, bdlo
, interlace_type
,
2192 make_transform_image(ps
, colour_type
, DEPTH(bdlo
), interlace_type
,
2199 make_transform_images(png_store
*ps
)
2201 /* This is in case of errors. */
2202 safecat(ps
->test
, sizeof ps
->test
, 0, "make standard images");
2204 /* Arguments are colour_type, low bit depth, high bit depth
2206 make_standard(ps
, 0, 0, WRITE_BDHI
);
2207 make_standard(ps
, 2, 3, WRITE_BDHI
);
2208 make_standard(ps
, 3, 0, 3 /*palette: max 8 bits*/);
2209 make_standard(ps
, 4, 3, WRITE_BDHI
);
2210 make_standard(ps
, 6, 3, WRITE_BDHI
);
2213 /* The following two routines use the PNG interlace support macros from
2214 * png.h to interlace or deinterlace rows.
2217 interlace_row(png_bytep buffer
, png_const_bytep imageRow
,
2218 unsigned int pixel_size
, png_uint_32 w
, int pass
)
2220 png_uint_32 xin
, xout
, xstep
;
2222 /* Note that this can, trivially, be optimized to a memcpy on pass 7, the
2223 * code is presented this way to make it easier to understand. In practice
2224 * consult the code in the libpng source to see other ways of doing this.
2226 xin
= PNG_PASS_START_COL(pass
);
2227 xstep
= 1U<<PNG_PASS_COL_SHIFT(pass
);
2229 for (xout
=0; xin
<w
; xin
+=xstep
)
2231 pixel_copy(buffer
, xout
, imageRow
, xin
, pixel_size
);
2237 deinterlace_row(png_bytep buffer
, png_const_bytep row
,
2238 unsigned int pixel_size
, png_uint_32 w
, int pass
)
2240 /* The inverse of the above, 'row' is part of row 'y' of the output image,
2241 * in 'buffer'. The image is 'w' wide and this is pass 'pass', distribute
2242 * the pixels of row into buffer and return the number written (to allow
2243 * this to be checked).
2245 png_uint_32 xin
, xout
, xstep
;
2247 xout
= PNG_PASS_START_COL(pass
);
2248 xstep
= 1U<<PNG_PASS_COL_SHIFT(pass
);
2250 for (xin
=0; xout
<w
; xout
+=xstep
)
2252 pixel_copy(buffer
, xout
, row
, xin
, pixel_size
);
2257 /* Build a single row for the 'size' test images, this fills in only the
2258 * first bit_width bits of the sample row.
2261 size_row(png_byte buffer
[SIZE_ROWMAX
], png_uint_32 bit_width
, png_uint_32 y
)
2263 /* height is in the range 1 to 16, so: */
2264 y
= ((y
& 1) << 7) + ((y
& 2) << 6) + ((y
& 4) << 5) + ((y
& 8) << 4);
2265 /* the following ensures bits are set in small images: */
2268 while (bit_width
>= 8)
2269 *buffer
++ = (png_byte
)y
++, bit_width
-= 8;
2271 /* There may be up to 7 remaining bits, these go in the most significant
2276 png_uint_32 mask
= (1U<<(8-bit_width
))-1;
2277 *buffer
= (png_byte
)((*buffer
& mask
) | (y
& ~mask
));
2282 make_size_image(png_store
* PNG_CONST ps
, png_byte PNG_CONST colour_type
,
2283 png_byte PNG_CONST bit_depth
, int PNG_CONST interlace_type
,
2284 png_uint_32 PNG_CONST w
, png_uint_32 PNG_CONST h
,
2285 int PNG_CONST do_interlace
)
2293 unsigned int pixel_size
;
2295 /* Make a name and get an appropriate id for the store: */
2296 char name
[FILE_NAME_SIZE
];
2297 PNG_CONST png_uint_32 id
= FILEID(colour_type
, bit_depth
, interlace_type
,
2298 w
, h
, do_interlace
);
2300 standard_name_from_id(name
, sizeof name
, 0, id
);
2301 pp
= set_store_for_write(ps
, &pi
, name
);
2303 /* In the event of a problem return control to the Catch statement below
2304 * to do the clean up - it is not possible to 'return' directly from a Try
2310 png_set_IHDR(pp
, pi
, w
, h
, bit_depth
, colour_type
, interlace_type
,
2311 PNG_COMPRESSION_TYPE_BASE
, PNG_FILTER_TYPE_BASE
);
2313 /* Same palette as make_transform_image - I don' think there is any
2314 * benefit from using a different one (JB 20101211)
2316 if (colour_type
== 3) /* palette */
2322 pal
[i
].red
= pal
[i
].green
= pal
[i
].blue
= (png_byte
)i
;
2325 png_set_PLTE(pp
, pi
, pal
, 256);
2328 png_write_info(pp
, pi
);
2330 /* Calculate the bit size, divide by 8 to get the byte size - this won't
2331 * overflow because we know the w values are all small enough even for
2332 * a system where 'unsigned int' is only 16 bits.
2334 pixel_size
= bit_size(pp
, colour_type
, bit_depth
);
2335 if (png_get_rowbytes(pp
, pi
) != ((w
* pixel_size
) + 7) / 8)
2336 png_error(pp
, "row size incorrect");
2340 int npasses
= npasses_from_interlace_type(pp
, interlace_type
);
2343 png_byte image
[16][SIZE_ROWMAX
];
2345 /* To help consistent error detection make the parts of this buffer
2346 * that aren't set below all '1':
2348 memset(image
, 0xff, sizeof image
);
2350 if (!do_interlace
&& npasses
!= png_set_interlace_handling(pp
))
2351 png_error(pp
, "write: png_set_interlace_handling failed");
2353 /* Prepare the whole image first to avoid making it 7 times: */
2355 size_row(image
[y
], w
* pixel_size
, y
);
2357 for (pass
=0; pass
<npasses
; ++pass
)
2359 /* The following two are for checking the macros: */
2360 PNG_CONST png_uint_32 wPass
= PNG_PASS_COLS(w
, pass
);
2362 /* If do_interlace is set we don't call png_write_row for every
2363 * row because some of them are empty. In fact, for a 1x1 image,
2364 * most of them are empty!
2368 png_const_bytep row
= image
[y
];
2369 png_byte tempRow
[SIZE_ROWMAX
];
2371 /* If do_interlace *and* the image is interlaced we
2372 * need a reduced interlace row, this may be reduced
2375 if (do_interlace
&& interlace_type
== PNG_INTERLACE_ADAM7
)
2377 /* The row must not be written if it doesn't exist, notice
2378 * that there are two conditions here, either the row isn't
2379 * ever in the pass or the row would be but isn't wide
2380 * enough to contribute any pixels. In fact the wPass test
2381 * can be used to skip the whole y loop in this case.
2383 if (PNG_ROW_IN_INTERLACE_PASS(y
, pass
) && wPass
> 0)
2385 /* Set to all 1's for error detection (libpng tends to
2386 * set unset things to 0).
2388 memset(tempRow
, 0xff, sizeof tempRow
);
2389 interlace_row(tempRow
, row
, pixel_size
, w
, pass
);
2396 /* Only get to here if the row has some pixels in it. */
2397 png_write_row(pp
, row
);
2402 png_write_end(pp
, pi
);
2404 /* And store this under the appropriate id, then clean up. */
2405 store_storefile(ps
, id
);
2407 store_write_reset(ps
);
2412 /* Use the png_store returned by the exception. This may help the compiler
2413 * because 'ps' is not used in this branch of the setjmp. Note that fault
2414 * and ps will always be the same value.
2416 store_write_reset(fault
);
2421 make_size(png_store
* PNG_CONST ps
, png_byte PNG_CONST colour_type
, int bdlo
,
2424 for (; bdlo
<= bdhi
; ++bdlo
)
2428 for (width
= 1; width
<= 16; ++width
)
2432 for (height
= 1; height
<= 16; ++height
)
2434 /* The four combinations of DIY interlace and interlace or not -
2435 * no interlace + DIY should be identical to no interlace with
2438 make_size_image(ps
, colour_type
, DEPTH(bdlo
), PNG_INTERLACE_NONE
,
2440 make_size_image(ps
, colour_type
, DEPTH(bdlo
), PNG_INTERLACE_NONE
,
2442 make_size_image(ps
, colour_type
, DEPTH(bdlo
), PNG_INTERLACE_ADAM7
,
2444 make_size_image(ps
, colour_type
, DEPTH(bdlo
), PNG_INTERLACE_ADAM7
,
2452 make_size_images(png_store
*ps
)
2454 /* This is in case of errors. */
2455 safecat(ps
->test
, sizeof ps
->test
, 0, "make size images");
2457 /* Arguments are colour_type, low bit depth, high bit depth
2459 make_size(ps
, 0, 0, WRITE_BDHI
);
2460 make_size(ps
, 2, 3, WRITE_BDHI
);
2461 make_size(ps
, 3, 0, 3 /*palette: max 8 bits*/);
2462 make_size(ps
, 4, 3, WRITE_BDHI
);
2463 make_size(ps
, 6, 3, WRITE_BDHI
);
2466 /* Return a row based on image id and 'y' for checking: */
2468 standard_row(png_structp pp
, png_byte std
[STANDARD_ROWMAX
], png_uint_32 id
,
2471 if (WIDTH_FROM_ID(id
) == 0)
2472 transform_row(pp
, std
, COL_FROM_ID(id
), DEPTH_FROM_ID(id
), y
);
2474 size_row(std
, WIDTH_FROM_ID(id
) * bit_size(pp
, COL_FROM_ID(id
),
2475 DEPTH_FROM_ID(id
)), y
);
2478 /* Tests - individual test cases */
2479 /* Like 'make_standard' but errors are deliberately introduced into the calls
2480 * to ensure that they get detected - it should not be possible to write an
2481 * invalid image with libpng!
2484 sBIT0_error_fn(png_structp pp
, png_infop pi
)
2486 /* 0 is invalid... */
2488 bad
.red
= bad
.green
= bad
.blue
= bad
.gray
= bad
.alpha
= 0;
2489 png_set_sBIT(pp
, pi
, &bad
);
2493 sBIT_error_fn(png_structp pp
, png_infop pi
)
2498 if (png_get_color_type(pp
, pi
) == PNG_COLOR_TYPE_PALETTE
)
2502 bit_depth
= png_get_bit_depth(pp
, pi
);
2504 /* Now we know the bit depth we can easily generate an invalid sBIT entry */
2505 bad
.red
= bad
.green
= bad
.blue
= bad
.gray
= bad
.alpha
=
2506 (png_byte
)(bit_depth
+1);
2507 png_set_sBIT(pp
, pi
, &bad
);
2510 static PNG_CONST
struct
2512 void (*fn
)(png_structp
, png_infop
);
2513 PNG_CONST
char *msg
;
2514 unsigned int warning
:1; /* the error is a warning... */
2517 { sBIT0_error_fn
, "sBIT(0): failed to detect error", 1 },
2518 { sBIT_error_fn
, "sBIT(too big): failed to detect error", 1 },
2522 make_error(png_store
* volatile ps
, png_byte PNG_CONST colour_type
,
2523 png_byte bit_depth
, int interlace_type
, int test
, png_const_charp name
)
2532 pp
= set_store_for_write(ps
, &pi
, name
);
2537 png_set_IHDR(pp
, pi
, transform_width(pp
, colour_type
, bit_depth
),
2538 transform_height(pp
, colour_type
, bit_depth
), bit_depth
, colour_type
,
2539 interlace_type
, PNG_COMPRESSION_TYPE_BASE
, PNG_FILTER_TYPE_BASE
);
2541 if (colour_type
== 3) /* palette */
2547 pal
[i
].red
= pal
[i
].green
= pal
[i
].blue
= (png_byte
)i
;
2550 png_set_PLTE(pp
, pi
, pal
, 256);
2553 /* Time for a few errors, these are in various optional chunks, the
2554 * standard tests test the standard chunks pretty well.
2556 # define exception__prev exception_prev_1
2557 # define exception__env exception_env_1
2560 /* Expect this to throw: */
2561 ps
->expect_error
= !error_test
[test
].warning
;
2562 ps
->expect_warning
= error_test
[test
].warning
;
2563 ps
->saw_warning
= 0;
2564 error_test
[test
].fn(pp
, pi
);
2566 /* Normally the error is only detected here: */
2567 png_write_info(pp
, pi
);
2569 /* And handle the case where it was only a warning: */
2570 if (ps
->expect_warning
&& ps
->saw_warning
)
2573 /* If we get here there is a problem, we have success - no error or
2574 * no warning - when we shouldn't have success. Log an error.
2576 store_log(ps
, pp
, error_test
[test
].msg
, 1 /*error*/);
2580 ps
= fault
; /* expected exit, make sure ps is not clobbered */
2581 #undef exception__prev
2582 #undef exception__env
2584 /* And clear these flags */
2585 ps
->expect_error
= 0;
2586 ps
->expect_warning
= 0;
2588 /* Now write the whole image, just to make sure that the detected, or
2589 * undetected, errro has not created problems inside libpng.
2591 if (png_get_rowbytes(pp
, pi
) !=
2592 transform_rowsize(pp
, colour_type
, bit_depth
))
2593 png_error(pp
, "row size incorrect");
2597 png_uint_32 h
= transform_height(pp
, colour_type
, bit_depth
);
2598 int npasses
= png_set_interlace_handling(pp
);
2601 if (npasses
!= npasses_from_interlace_type(pp
, interlace_type
))
2602 png_error(pp
, "write: png_set_interlace_handling failed");
2604 for (pass
=0; pass
<npasses
; ++pass
)
2610 png_byte buffer
[TRANSFORM_ROWMAX
];
2612 transform_row(pp
, buffer
, colour_type
, bit_depth
, y
);
2613 png_write_row(pp
, buffer
);
2618 png_write_end(pp
, pi
);
2620 /* The following deletes the file that was just written. */
2621 store_write_reset(ps
);
2626 store_write_reset(fault
);
2631 make_errors(png_modifier
* PNG_CONST pm
, png_byte PNG_CONST colour_type
,
2632 int bdlo
, int PNG_CONST bdhi
)
2634 for (; bdlo
<= bdhi
; ++bdlo
)
2638 for (interlace_type
= PNG_INTERLACE_NONE
;
2639 interlace_type
< PNG_INTERLACE_LAST
; ++interlace_type
)
2642 char name
[FILE_NAME_SIZE
];
2644 standard_name(name
, sizeof name
, 0, colour_type
, bdlo
, interlace_type
,
2647 for (test
=0; test
<(sizeof error_test
)/(sizeof error_test
[0]); ++test
)
2649 make_error(&pm
->this, colour_type
, DEPTH(bdlo
), interlace_type
,
2658 return 1; /* keep going */
2662 perform_error_test(png_modifier
*pm
)
2664 /* Need to do this here because we just write in this test. */
2665 safecat(pm
->this.test
, sizeof pm
->this.test
, 0, "error test");
2667 if (!make_errors(pm
, 0, 0, WRITE_BDHI
))
2670 if (!make_errors(pm
, 2, 3, WRITE_BDHI
))
2673 if (!make_errors(pm
, 3, 0, 3))
2676 if (!make_errors(pm
, 4, 3, WRITE_BDHI
))
2679 if (!make_errors(pm
, 6, 3, WRITE_BDHI
))
2683 /* Because we want to use the same code in both the progressive reader and the
2684 * sequential reader it is necessary to deal with the fact that the progressive
2685 * reader callbacks only have one parameter (png_get_progressive_ptr()), so this
2686 * must contain all the test parameters and all the local variables directly
2687 * accessible to the sequential reader implementation.
2689 * The technique adopted is to reinvent part of what Dijkstra termed a
2690 * 'display'; an array of pointers to the stack frames of enclosing functions so
2691 * that a nested function definition can access the local (C auto) variables of
2692 * the functions that contain its definition. In fact C provides the first
2693 * pointer (the local variables - the stack frame pointer) and the last (the
2694 * global variables - the BCPL global vector typically implemented as global
2695 * addresses), this code requires one more pointer to make the display - the
2696 * local variables (and function call parameters) of the function that actually
2697 * invokes either the progressive or sequential reader.
2699 * Perhaps confusingly this technique is confounded with classes - the
2700 * 'standard_display' defined here is sub-classed as the 'gamma_display' below.
2701 * A gamma_display is a standard_display, taking advantage of the ANSI-C
2702 * requirement that the pointer to the first member of a structure must be the
2703 * same as the pointer to the structure. This allows us to reuse standard_
2704 * functions in the gamma test code; something that could not be done with
2707 typedef struct standard_palette_entry
/* pngvalid format palette! */
2713 } standard_palette
[256];
2715 typedef struct standard_display
2717 png_store
* ps
; /* Test parameters (passed to the function) */
2718 png_byte colour_type
;
2720 png_byte red_sBIT
; /* Input data sBIT values. */
2721 png_byte green_sBIT
;
2723 png_byte alpha_sBIT
;
2725 png_uint_32 id
; /* Calculated file ID */
2726 png_uint_32 w
; /* Width of image */
2727 png_uint_32 h
; /* Height of image */
2728 int npasses
; /* Number of interlaced passes */
2729 png_uint_32 pixel_size
; /* Width of one pixel in bits */
2730 png_uint_32 bit_width
; /* Width of output row in bits */
2731 size_t cbRow
; /* Bytes in a row of the output image */
2732 int do_interlace
; /* Do interlacing internally */
2733 int is_transparent
; /* Transparecy information was present. */
2739 } transparent
; /* The transparent color, if set. */
2745 standard_display_init(standard_display
*dp
, png_store
* ps
, png_uint_32 id
,
2749 dp
->colour_type
= COL_FROM_ID(id
);
2750 dp
->bit_depth
= DEPTH_FROM_ID(id
);
2751 dp
->alpha_sBIT
= dp
->blue_sBIT
= dp
->green_sBIT
= dp
->alpha_sBIT
=
2753 dp
->interlace_type
= INTERLACE_FROM_ID(id
);
2755 /* All the rest are filled in after the read_info: */
2762 dp
->do_interlace
= do_interlace
;
2763 dp
->is_transparent
= 0;
2764 /* Preset the transparent color to black: */
2765 memset(&dp
->transparent
, 0, sizeof dp
->transparent
);
2766 /* Preset the palette to full intensity/opaque througout: */
2767 memset(dp
->palette
, 0xff, sizeof dp
->palette
);
2771 /* Call this only if the colour type is 3 - PNG_COLOR_TYPE_PALETTE - otherwise
2772 * it will png_error out. The API returns true if tRNS information was
2776 standard_palette_init(standard_palette palette
, png_structp pp
, png_infop pi
)
2779 png_bytep trans_alpha
;
2784 if (png_get_PLTE(pp
, pi
, &pal
, &num
) & PNG_INFO_PLTE
)
2788 for (i
=0; i
<num
; ++i
)
2790 palette
[i
].red
= pal
[i
].red
;
2791 palette
[i
].green
= pal
[i
].green
;
2792 palette
[i
].blue
= pal
[i
].blue
;
2795 /* Mark the remainder of the entries with a flag value: */
2797 palette
[i
].red
= palette
[i
].green
= palette
[i
].blue
= 126;
2800 else /* !png_get_PLTE */
2801 png_error(pp
, "validate: missing PLTE with color type 3");
2805 if (png_get_tRNS(pp
, pi
, &trans_alpha
, &num
, 0) & PNG_INFO_tRNS
)
2809 /* Any of these are crash-worthy - given the implementation of
2810 * png_get_tRNS up to 1.5 an app won't crash if it just checks the
2811 * result above and fails to check that the variables it passed have
2812 * actually been filled in! Note that if the app were to pass the
2813 * last, png_color_16p, variable too it couldn't rely on this.
2815 if (trans_alpha
== 0 || num
<= 0 || num
> 256)
2816 png_error(pp
, "validate: unexpected png_get_tRNS (palette) result");
2818 for (i
=0; i
<num
; ++i
)
2819 palette
[i
].alpha
= trans_alpha
[i
];
2822 palette
[i
].alpha
= 255;
2824 return 1; /* transparency */
2829 /* No transparency - just set the alpha channel to opaque. */
2832 for (i
=0; i
<256; ++i
)
2833 palette
[i
].alpha
= 255;
2835 return 0; /* no transparency */
2839 /* By passing a 'standard_display' the progressive callbacks can be used
2840 * directly by the sequential code, the functions suffixed "_imp" are the
2841 * implementations, the functions without the suffix are the callbacks.
2843 * The code for the info callback is split into two because this callback calls
2844 * png_read_update_info or png_start_read_image and what gets called depends on
2845 * whether the info needs updating (we want to test both calls in pngvalid.)
2848 standard_info_part1(standard_display
*dp
, png_structp pp
, png_infop pi
)
2850 if (png_get_bit_depth(pp
, pi
) != dp
->bit_depth
)
2851 png_error(pp
, "validate: bit depth changed");
2853 if (png_get_color_type(pp
, pi
) != dp
->colour_type
)
2854 png_error(pp
, "validate: color type changed");
2856 if (png_get_filter_type(pp
, pi
) != PNG_FILTER_TYPE_BASE
)
2857 png_error(pp
, "validate: filter type changed");
2859 if (png_get_interlace_type(pp
, pi
) != dp
->interlace_type
)
2860 png_error(pp
, "validate: interlacing changed");
2862 if (png_get_compression_type(pp
, pi
) != PNG_COMPRESSION_TYPE_BASE
)
2863 png_error(pp
, "validate: compression type changed");
2865 dp
->w
= png_get_image_width(pp
, pi
);
2867 if (dp
->w
!= standard_width(pp
, dp
->id
))
2868 png_error(pp
, "validate: image width changed");
2870 dp
->h
= png_get_image_height(pp
, pi
);
2872 if (dp
->h
!= standard_height(pp
, dp
->id
))
2873 png_error(pp
, "validate: image height changed");
2875 /* Record (but don't check at present) the input sBIT according to the colour
2879 png_color_8p sBIT
= 0;
2881 if (png_get_sBIT(pp
, pi
, &sBIT
) & PNG_INFO_sBIT
)
2883 int sBIT_invalid
= 0;
2886 png_error(pp
, "validate: unexpected png_get_sBIT result");
2888 if (dp
->colour_type
& PNG_COLOR_MASK_COLOR
)
2890 if (sBIT
->red
== 0 || sBIT
->red
> dp
->bit_depth
)
2893 dp
->red_sBIT
= sBIT
->red
;
2895 if (sBIT
->green
== 0 || sBIT
->green
> dp
->bit_depth
)
2898 dp
->green_sBIT
= sBIT
->green
;
2900 if (sBIT
->blue
== 0 || sBIT
->blue
> dp
->bit_depth
)
2903 dp
->blue_sBIT
= sBIT
->blue
;
2908 if (sBIT
->gray
== 0 || sBIT
->gray
> dp
->bit_depth
)
2911 dp
->blue_sBIT
= dp
->green_sBIT
= dp
->red_sBIT
= sBIT
->gray
;
2914 /* All 8 bits in tRNS for a palette image are significant - see the
2917 if (dp
->colour_type
& PNG_COLOR_MASK_ALPHA
)
2919 if (sBIT
->alpha
== 0 || sBIT
->alpha
> dp
->bit_depth
)
2922 dp
->alpha_sBIT
= sBIT
->alpha
;
2926 png_error(pp
, "validate: sBIT value out of range");
2930 /* Important: this is validating the value *before* any transforms have been
2931 * put in place. It doesn't matter for the standard tests, where there are
2932 * no transforms, but it does for other tests where rowbytes may change after
2933 * png_read_update_info.
2935 if (png_get_rowbytes(pp
, pi
) != standard_rowsize(pp
, dp
->id
))
2936 png_error(pp
, "validate: row size changed");
2938 /* The palette is never read for non-palette images, even though it is valid
2939 * - this could be changed.
2941 if (dp
->colour_type
== 3) /* palette */
2945 dp
->is_transparent
= standard_palette_init(dp
->palette
, pp
, pi
);
2947 /* And validate the result. */
2948 for (i
=0; i
<256; ++i
)
2949 if (dp
->palette
[i
].red
!= i
|| dp
->palette
[i
].green
!= i
||
2950 dp
->palette
[i
].blue
!= i
)
2951 png_error(pp
, "validate: color type 3 PLTE chunk changed");
2954 /* In any case always check for a tranparent color: */
2956 png_color_16p trans_color
= 0;
2958 if (png_get_tRNS(pp
, pi
, 0, 0, &trans_color
) & PNG_INFO_tRNS
)
2960 if (trans_color
== 0)
2961 png_error(pp
, "validate: unexpected png_get_tRNS (color) result");
2963 switch (dp
->colour_type
)
2966 dp
->transparent
.red
= dp
->transparent
.green
= dp
->transparent
.blue
=
2968 dp
->is_transparent
= 1;
2972 dp
->transparent
.red
= trans_color
->red
;
2973 dp
->transparent
.green
= trans_color
->green
;
2974 dp
->transparent
.blue
= trans_color
->blue
;
2975 dp
->is_transparent
= 1;
2979 /* Not expected because it should result in the array case
2982 png_error(pp
, "validate: unexpected png_get_tRNS result");
2986 png_error(pp
, "validate: invalid tRNS chunk with alpha image");
2991 /* Read the number of passes - expected to match the value used when
2992 * creating the image (interlaced or not). This has the side effect of
2993 * turning on interlace handling (if do_interlace is not set.)
2995 dp
->npasses
= npasses_from_interlace_type(pp
, dp
->interlace_type
);
2996 if (!dp
->do_interlace
&& dp
->npasses
!= png_set_interlace_handling(pp
))
2997 png_error(pp
, "validate: file changed interlace type");
2999 /* Caller calls png_read_update_info or png_start_read_image now, then calls
3004 /* This must be called *after* the png_read_update_info call to get the correct
3005 * 'rowbytes' value, otherwise png_get_rowbytes will refer to the untransformed
3009 standard_info_part2(standard_display
*dp
, png_structp pp
, png_infop pi
,
3012 /* Record cbRow now that it can be found. */
3013 dp
->pixel_size
= bit_size(pp
, png_get_color_type(pp
, pi
),
3014 png_get_bit_depth(pp
, pi
));
3015 dp
->bit_width
= png_get_image_width(pp
, pi
) * dp
->pixel_size
;
3016 dp
->cbRow
= png_get_rowbytes(pp
, pi
);
3018 /* Validate the rowbytes here again. */
3019 if (dp
->cbRow
!= (dp
->bit_width
+7)/8)
3020 png_error(pp
, "bad png_get_rowbytes calculation");
3022 /* Then ensure there is enough space for the output image(s). */
3023 store_ensure_image(dp
->ps
, pp
, nImages
* dp
->cbRow
* dp
->h
);
3027 standard_info_imp(standard_display
*dp
, png_structp pp
, png_infop pi
,
3030 /* Note that the validation routine has the side effect of turning on
3031 * interlace handling in the subsequent code.
3033 standard_info_part1(dp
, pp
, pi
);
3035 /* And the info callback has to call this (or png_read_update_info - see
3036 * below in the png_modifier code for that variant.
3038 png_start_read_image(pp
);
3040 /* Validate the height, width and rowbytes plus ensure that sufficient buffer
3041 * exists for decoding the image.
3043 standard_info_part2(dp
, pp
, pi
, nImages
);
3047 standard_info(png_structp pp
, png_infop pi
)
3049 standard_display
*dp
= png_get_progressive_ptr(pp
);
3051 /* Call with nImages==1 because the progressive reader can only produce one
3054 standard_info_imp(dp
, pp
, pi
, 1 /*only one image*/);
3058 progressive_row(png_structp pp
, png_bytep new_row
, png_uint_32 y
, int pass
)
3060 PNG_CONST standard_display
*dp
= png_get_progressive_ptr(pp
);
3062 /* When handling interlacing some rows will be absent in each pass, the
3063 * callback still gets called, but with a NULL pointer. This is checked
3064 * in the 'else' clause below. We need our own 'cbRow', but we can't call
3065 * png_get_rowbytes because we got no info structure.
3067 if (new_row
!= NULL
)
3071 /* In the case where the reader doesn't do the interlace it gives
3072 * us the y in the sub-image:
3074 if (dp
->do_interlace
&& dp
->interlace_type
== PNG_INTERLACE_ADAM7
)
3075 y
= PNG_ROW_FROM_PASS_ROW(y
, pass
);
3077 /* Validate this just in case. */
3079 png_error(pp
, "invalid y to progressive row callback");
3081 row
= dp
->ps
->image
+ y
* dp
->cbRow
;
3083 /* Combine the new row into the old: */
3084 if (dp
->do_interlace
)
3086 if (dp
->interlace_type
== PNG_INTERLACE_ADAM7
)
3087 deinterlace_row(row
, new_row
, dp
->pixel_size
, dp
->w
, pass
);
3089 memcpy(row
, new_row
, dp
->cbRow
);
3092 png_progressive_combine_row(pp
, row
, new_row
);
3093 } else if (dp
->interlace_type
== PNG_INTERLACE_ADAM7
&&
3094 PNG_ROW_IN_INTERLACE_PASS(y
, pass
) &&
3095 PNG_PASS_COLS(dp
->w
, pass
) > 0)
3096 png_error(pp
, "missing row in progressive de-interlacing");
3100 sequential_row(standard_display
*dp
, png_structp pp
, png_infop pi
,
3101 PNG_CONST png_bytep pImage
, PNG_CONST png_bytep pDisplay
)
3103 PNG_CONST
int npasses
= dp
->npasses
;
3104 PNG_CONST
int do_interlace
= dp
->do_interlace
&&
3105 dp
->interlace_type
== PNG_INTERLACE_ADAM7
;
3106 PNG_CONST png_uint_32 height
= standard_height(pp
, dp
->id
);
3107 PNG_CONST png_uint_32 width
= standard_width(pp
, dp
->id
);
3108 PNG_CONST
size_t cbRow
= dp
->cbRow
;
3111 for (pass
=0; pass
<npasses
; ++pass
)
3114 png_uint_32 wPass
= PNG_PASS_COLS(width
, pass
);
3115 png_bytep pRow1
= pImage
;
3116 png_bytep pRow2
= pDisplay
;
3118 for (y
=0; y
<height
; ++y
)
3122 /* wPass may be zero or this row may not be in this pass.
3123 * png_read_row must not be called in either case.
3125 if (wPass
> 0 && PNG_ROW_IN_INTERLACE_PASS(y
, pass
))
3127 /* Read the row into a pair of temporary buffers, then do the
3128 * merge here into the output rows.
3130 png_byte row
[STANDARD_ROWMAX
], display
[STANDARD_ROWMAX
];
3132 /* The following aids (to some extent) error detection - we can
3133 * see where png_read_row wrote. Use opposite values in row and
3134 * display to make this easier.
3136 memset(row
, 0xff, sizeof row
);
3137 memset(display
, 0, sizeof display
);
3139 png_read_row(pp
, row
, display
);
3142 deinterlace_row(pRow1
, row
, dp
->pixel_size
, dp
->w
, pass
);
3145 deinterlace_row(pRow2
, display
, dp
->pixel_size
, dp
->w
, pass
);
3149 png_read_row(pp
, pRow1
, pRow2
);
3159 /* And finish the read operation (only really necessary if the caller wants
3160 * to find additional data in png_info from chunks after the last IDAT.)
3162 png_read_end(pp
, pi
);
3166 standard_row_validate(standard_display
*dp
, png_structp pp
, png_const_bytep row
,
3167 png_const_bytep display
, png_uint_32 y
)
3169 png_byte std
[STANDARD_ROWMAX
];
3171 memset(std
, 0xff, sizeof std
);
3172 standard_row(pp
, std
, dp
->id
, y
);
3174 /* At the end both the 'row' and 'display' arrays should end up identical.
3175 * In earlier passes 'row' will be partially filled in, with only the pixels
3176 * that have been read so far, but 'display' will have those pixels
3177 * replicated to fill the unread pixels while reading an interlaced image.
3178 * The side effect inside the libpng sequential reader is that the 'row'
3179 * array retains the correct values for unwritten pixels within the row
3180 * bytes, while the 'display' array gets bits off the end of the image (in
3181 * the last byte) trashed. Unfortunately in the progressive reader the
3182 * row bytes are always trashed, so we always do a pixel_cmp here even though
3183 * a memcmp of all cbRow bytes will succeed for the sequential reader.
3185 if (row
!= NULL
&& pixel_cmp(std
, row
, dp
->bit_width
) != 0)
3188 sprintf(msg
, "PNG image row %d changed", y
);
3192 /* In this case use pixel_cmp because we need to compare a partial
3193 * byte at the end of the row if the row is not an exact multiple
3196 if (display
!= NULL
&& pixel_cmp(std
, display
, dp
->bit_width
) != 0)
3199 sprintf(msg
, "display row %d changed", y
);
3205 standard_image_validate(standard_display
*dp
, png_structp pp
,
3206 png_const_bytep pImage
, png_const_bytep pDisplay
)
3210 for (y
=0; y
<dp
->h
; ++y
)
3212 standard_row_validate(dp
, pp
, pImage
, pDisplay
, y
);
3215 pImage
+= dp
->cbRow
;
3217 if (pDisplay
!= NULL
)
3218 pDisplay
+= dp
->cbRow
;
3221 /* This avoids false positives if the validation code is never called! */
3222 dp
->ps
->validated
= 1;
3226 standard_end(png_structp pp
, png_infop pi
)
3228 standard_display
*dp
= png_get_progressive_ptr(pp
);
3232 /* Validate the image - progressive reading only produces one variant for
3233 * interlaced images.
3235 standard_image_validate(dp
, pp
, dp
->ps
->image
, NULL
);
3238 /* A single test run checking the standard image to ensure it is not damaged. */
3240 standard_test(png_store
* PNG_CONST psIn
, png_uint_32 PNG_CONST id
,
3244 context(psIn
, fault
);
3246 /* Set up the display (stack frame) variables from the arguments to the
3247 * function and initialize the locals that are filled in later.
3249 standard_display_init(&d
, psIn
, id
, do_interlace
);
3251 /* Everything is protected by a Try/Catch. The functions called also
3252 * typically have local Try/Catch blocks.
3259 /* Get a png_struct for reading the image. This will throw an error if it
3260 * fails, so we don't need to check the result.
3262 pp
= set_store_for_read(d
.ps
, &pi
, d
.id
,
3263 d
.do_interlace
? (d
.ps
->progressive
?
3264 "pngvalid progressive deinterlacer" :
3265 "pngvalid sequential deinterlacer") : (d
.ps
->progressive
?
3266 "progressive reader" : "sequential reader"));
3268 /* Introduce the correct read function. */
3269 if (d
.ps
->progressive
)
3271 png_set_progressive_read_fn(pp
, &d
, standard_info
, progressive_row
,
3274 /* Now feed data into the reader until we reach the end: */
3275 store_progressive_read(d
.ps
, pp
, pi
);
3279 /* Note that this takes the store, not the display. */
3280 png_set_read_fn(pp
, d
.ps
, store_read
);
3282 /* Check the header values: */
3283 png_read_info(pp
, pi
);
3285 /* The code tests both versions of the images that the sequential
3286 * reader can produce.
3288 standard_info_imp(&d
, pp
, pi
, 2 /*images*/);
3290 /* Need the total bytes in the image below; we can't get to this point
3291 * unless the PNG file values have been checked against the expected
3295 PNG_CONST png_bytep pImage
= d
.ps
->image
;
3296 PNG_CONST png_bytep pDisplay
= pImage
+ d
.cbRow
* d
.h
;
3298 sequential_row(&d
, pp
, pi
, pImage
, pDisplay
);
3300 /* After the last pass loop over the rows again to check that the
3303 standard_image_validate(&d
, pp
, pImage
, pDisplay
);
3307 /* Check for validation. */
3308 if (!d
.ps
->validated
)
3309 png_error(pp
, "image read failed silently");
3311 /* Successful completion. */
3315 d
.ps
= fault
; /* make sure this hasn't been clobbered. */
3317 /* In either case clean up the store. */
3318 store_read_reset(d
.ps
);
3322 test_standard(png_modifier
* PNG_CONST pm
, png_byte PNG_CONST colour_type
,
3323 int bdlo
, int PNG_CONST bdhi
)
3325 for (; bdlo
<= bdhi
; ++bdlo
)
3329 for (interlace_type
= PNG_INTERLACE_NONE
;
3330 interlace_type
< PNG_INTERLACE_LAST
; ++interlace_type
)
3332 standard_test(&pm
->this, FILEID(colour_type
, DEPTH(bdlo
),
3333 interlace_type
, 0, 0, 0), 0/*do_interlace*/);
3340 return 1; /* keep going */
3344 perform_standard_test(png_modifier
*pm
)
3346 /* Test each colour type over the valid range of bit depths (expressed as
3347 * log2(bit_depth) in turn, stop as soon as any error is detected.
3349 if (!test_standard(pm
, 0, 0, READ_BDHI
))
3352 if (!test_standard(pm
, 2, 3, READ_BDHI
))
3355 if (!test_standard(pm
, 3, 0, 3))
3358 if (!test_standard(pm
, 4, 3, READ_BDHI
))
3361 if (!test_standard(pm
, 6, 3, READ_BDHI
))
3366 /********************************** SIZE TESTS ********************************/
3368 test_size(png_modifier
* PNG_CONST pm
, png_byte PNG_CONST colour_type
,
3369 int bdlo
, int PNG_CONST bdhi
)
3371 /* Run the tests on each combination.
3373 * NOTE: on my 32 bit x86 each of the following blocks takes
3374 * a total of 3.5 seconds if done across every combo of bit depth
3375 * width and height. This is a waste of time in practice, hence the
3376 * hinc and winc stuff:
3378 static PNG_CONST png_byte hinc
[] = {1, 3, 11, 1, 5};
3379 static PNG_CONST png_byte winc
[] = {1, 9, 5, 7, 1};
3380 for (; bdlo
<= bdhi
; ++bdlo
)
3384 for (h
=1; h
<=16; h
+=hinc
[bdlo
]) for (w
=1; w
<=16; w
+=winc
[bdlo
])
3386 /* First test all the 'size' images against the sequential
3387 * reader using libpng to deinterlace (where required.) This
3388 * validates the write side of libpng. There are four possibilities
3391 standard_test(&pm
->this, FILEID(colour_type
, DEPTH(bdlo
),
3392 PNG_INTERLACE_NONE
, w
, h
, 0), 0/*do_interlace*/);
3397 standard_test(&pm
->this, FILEID(colour_type
, DEPTH(bdlo
),
3398 PNG_INTERLACE_NONE
, w
, h
, 1), 0/*do_interlace*/);
3403 standard_test(&pm
->this, FILEID(colour_type
, DEPTH(bdlo
),
3404 PNG_INTERLACE_ADAM7
, w
, h
, 0), 0/*do_interlace*/);
3409 standard_test(&pm
->this, FILEID(colour_type
, DEPTH(bdlo
),
3410 PNG_INTERLACE_ADAM7
, w
, h
, 1), 0/*do_interlace*/);
3415 /* Now validate the interlaced read side - do_interlace true,
3416 * in the progressive case this does actually make a difference
3417 * to the code used in the non-interlaced case too.
3419 standard_test(&pm
->this, FILEID(colour_type
, DEPTH(bdlo
),
3420 PNG_INTERLACE_NONE
, w
, h
, 0), 1/*do_interlace*/);
3425 standard_test(&pm
->this, FILEID(colour_type
, DEPTH(bdlo
),
3426 PNG_INTERLACE_ADAM7
, w
, h
, 0), 1/*do_interlace*/);
3433 return 1; /* keep going */
3437 perform_size_test(png_modifier
*pm
)
3439 /* Test each colour type over the valid range of bit depths (expressed as
3440 * log2(bit_depth) in turn, stop as soon as any error is detected.
3442 if (!test_size(pm
, 0, 0, READ_BDHI
))
3445 if (!test_size(pm
, 2, 3, READ_BDHI
))
3448 /* For the moment don't do the palette test - it's a waste of time when
3449 * compared to the greyscale test.
3452 if (!test_size(pm
, 3, 0, 3))
3456 if (!test_size(pm
, 4, 3, READ_BDHI
))
3459 if (!test_size(pm
, 6, 3, READ_BDHI
))
3464 /******************************* TRANSFORM TESTS ******************************/
3465 /* A set of tests to validate libpng image transforms. The possibilities here
3466 * are legion because the transforms can be combined in a combinatorial
3467 * fashion. To deal with this some measure of restraint is required, otherwise
3468 * the tests would take forever.
3470 typedef struct image_pixel
3472 /* A local (pngvalid) representation of a PNG pixel, in all its
3475 unsigned int red
, green
, blue
, alpha
; /* For non-palette images. */
3476 unsigned int palette_index
; /* For a palette image. */
3477 png_byte colour_type
; /* As in the spec. */
3478 png_byte bit_depth
; /* Defines bit size in row */
3479 png_byte sample_depth
; /* Scale of samples */
3480 int have_tRNS
; /* tRNS chunk may need processing */
3482 /* For checking the code calculates double precision floating point values
3483 * along with an error value, accumulated from the transforms. Because an
3484 * sBIT setting allows larger error bounds (indeed, by the spec, apparently
3485 * up to just less than +/-1 in the scaled value) the *lowest* sBIT for each
3486 * channel is stored. This sBIT value is folded in to the stored error value
3487 * at the end of the application of the transforms to the pixel.
3489 double redf
, greenf
, bluef
, alphaf
;
3490 double rede
, greene
, bluee
, alphae
;
3491 png_byte red_sBIT
, green_sBIT
, blue_sBIT
, alpha_sBIT
;
3494 /* Shared utility function, see below. */
3496 image_pixel_setf(image_pixel
*this, unsigned int max
)
3498 this->redf
= this->red
/ (double)max
;
3499 this->greenf
= this->green
/ (double)max
;
3500 this->bluef
= this->blue
/ (double)max
;
3501 this->alphaf
= this->alpha
/ (double)max
;
3503 if (this->red
< max
)
3504 this->rede
= this->redf
* DBL_EPSILON
;
3507 if (this->green
< max
)
3508 this->greene
= this->greenf
* DBL_EPSILON
;
3511 if (this->blue
< max
)
3512 this->bluee
= this->bluef
* DBL_EPSILON
;
3515 if (this->alpha
< max
)
3516 this->alphae
= this->alphaf
* DBL_EPSILON
;
3521 /* Initialize the structure for the next pixel - call this before doing any
3522 * transforms and call it for each pixel since all the fields may need to be
3526 image_pixel_init(image_pixel
*this, png_const_bytep row
, png_byte colour_type
,
3527 png_byte bit_depth
, png_uint_32 x
, standard_palette palette
)
3529 PNG_CONST png_byte sample_depth
= (png_byte
)(colour_type
==
3530 PNG_COLOR_TYPE_PALETTE
? 8 : bit_depth
);
3531 PNG_CONST
unsigned int max
= (1U<<sample_depth
)-1;
3533 /* Initially just set everything to the same number and the alpha to opaque.
3534 * Note that this currently assumes a simple palette where entry x has colour
3537 this->palette_index
= this->red
= this->green
= this->blue
=
3538 sample(row
, colour_type
, bit_depth
, x
, 0);
3540 this->red_sBIT
= this->green_sBIT
= this->blue_sBIT
= this->alpha_sBIT
=
3543 /* Then override as appropriate: */
3544 if (colour_type
== 3) /* palette */
3546 /* This permits the caller to default to the sample value. */
3549 PNG_CONST
unsigned int i
= this->palette_index
;
3551 this->red
= palette
[i
].red
;
3552 this->green
= palette
[i
].green
;
3553 this->blue
= palette
[i
].blue
;
3554 this->alpha
= palette
[i
].alpha
;
3558 else /* not palette */
3562 if (colour_type
& 2)
3564 this->green
= sample(row
, colour_type
, bit_depth
, x
, 1);
3565 this->blue
= sample(row
, colour_type
, bit_depth
, x
, 2);
3568 if (colour_type
& 4)
3569 this->alpha
= sample(row
, colour_type
, bit_depth
, x
, ++i
);
3572 /* Calculate the scaled values, these are simply the values divided by
3573 * 'max' and the error is initialized to the double precision epsilon value
3574 * from the header file.
3576 image_pixel_setf(this, max
);
3578 /* Store the input information for use in the transforms - these will
3579 * modify the information.
3581 this->colour_type
= colour_type
;
3582 this->bit_depth
= bit_depth
;
3583 this->sample_depth
= sample_depth
;
3584 this->have_tRNS
= 0;
3587 /* Convert a palette image to an rgb image. This necessarily converts the tRNS
3588 * chunk at the same time, because the tRNS will be in palette form.
3591 image_pixel_convert_PLTE(image_pixel
*this, const standard_display
*display
)
3593 if (this->colour_type
== PNG_COLOR_TYPE_PALETTE
)
3595 PNG_CONST
unsigned int i
= this->palette_index
;
3597 this->bit_depth
= this->sample_depth
;
3598 this->red
= display
->palette
[i
].red
;
3599 this->green
= display
->palette
[i
].green
;
3600 this->blue
= display
->palette
[i
].blue
;
3601 this->red_sBIT
= display
->red_sBIT
;
3602 this->green_sBIT
= display
->green_sBIT
;
3603 this->blue_sBIT
= display
->blue_sBIT
;
3605 if (this->have_tRNS
)
3607 this->alpha
= display
->palette
[i
].alpha
;
3608 this->colour_type
= PNG_COLOR_TYPE_RGB_ALPHA
;
3609 this->have_tRNS
= 0;
3614 this->colour_type
= PNG_COLOR_TYPE_RGB
;
3616 this->alpha_sBIT
= 8;
3618 /* And regenerate the scaled values and all the errors, which are now set
3619 * back to the initial values.
3621 image_pixel_setf(this, 255);
3625 /* Add an alpha channel, this will glom in the tRNS information because tRNS is
3626 * not valid in an alpha image. The bit depth will invariably be set to at
3627 * least 8. Palette images will be converted to alpha (using the above API).
3630 image_pixel_add_alpha(image_pixel
*this, const standard_display
*display
)
3632 if (this->colour_type
== PNG_COLOR_TYPE_PALETTE
)
3633 image_pixel_convert_PLTE(this, display
);
3635 if ((this->colour_type
& PNG_COLOR_MASK_ALPHA
) == 0)
3637 if (this->colour_type
== PNG_COLOR_TYPE_GRAY
)
3639 if (this->bit_depth
< 8)
3640 this->bit_depth
= 8;
3642 if (this->have_tRNS
)
3644 this->have_tRNS
= 0;
3646 /* Check the input, original, channel value here against the
3647 * original tRNS gray chunk valie.
3649 if (this->red
== display
->transparent
.red
)
3657 this->colour_type
= PNG_COLOR_TYPE_GRAY_ALPHA
;
3660 else if (this->colour_type
== PNG_COLOR_TYPE_RGB
)
3662 if (this->have_tRNS
)
3664 this->have_tRNS
= 0;
3666 /* Again, check the exact input values, not the current transformed
3669 if (this->red
== display
->transparent
.red
&&
3670 this->green
== display
->transparent
.green
&&
3671 this->blue
== display
->transparent
.blue
)
3676 this->colour_type
= PNG_COLOR_TYPE_RGB_ALPHA
;
3680 /* The error in the alpha is zero and the sBIT value comes from the
3681 * original sBIT data (actually it will always be the original bit depth).
3684 this->alpha_sBIT
= display
->alpha_sBIT
;
3688 struct transform_display
;
3689 typedef struct image_transform
3691 /* The name of this transform: a string. */
3692 PNG_CONST
char *name
;
3694 /* Each transform can be disabled from the command line: */
3697 /* The global list of transforms; read only. */
3698 struct image_transform
*PNG_CONST list
;
3700 /* The global count of the number of times this transform has been set on an
3703 unsigned int global_use
;
3705 /* The local count of the number of times this transform has been set. */
3706 unsigned int local_use
;
3708 /* The next transform in the list, each transform must call its own next
3709 * transform after it has processed the pixel successfully.
3711 PNG_CONST
struct image_transform
*next
;
3713 /* A single transform for the image, expressed as a series of function
3714 * callbacks and some space for values.
3716 * First a callback to set the transform on the current png_read_struct:
3718 void (*set
)(PNG_CONST
struct image_transform
*this,
3719 struct transform_display
*that
, png_structp pp
, png_infop pi
);
3721 /* Then a transform that takes an input pixel in one PNG format or another
3722 * and modifies it by a pngvalid implementation of the transform (thus
3723 * duplicating the libpng intent without, we hope, duplicating the bugs
3724 * in the libpng implementation!) The png_structp is solely to allow error
3725 * reporting via png_error and png_warning.
3727 void (*mod
)(PNG_CONST
struct image_transform
*this, image_pixel
*that
,
3728 png_structp pp
, PNG_CONST
struct transform_display
*display
);
3730 /* Add this transform to the list and return true if the transform is
3731 * meaningful for this colour type and bit depth - if false then the
3732 * transform should have no effect on the image so there's not a lot of
3735 int (*add
)(struct image_transform
*this,
3736 PNG_CONST
struct image_transform
**that
, png_byte colour_type
,
3737 png_byte bit_depth
);
3740 typedef struct transform_display
3742 standard_display
this;
3746 PNG_CONST image_transform
* transform_list
;
3748 /* Local variables */
3749 png_byte output_colour_type
;
3750 png_byte output_bit_depth
;
3751 } transform_display
;
3753 /* Two functions to end the list: */
3755 image_transform_set_end(PNG_CONST image_transform
*this,
3756 transform_display
*that
, png_structp pp
, png_infop pi
)
3764 /* At the end of the list recalculate the output image pixel value from the
3765 * double precision values set up by the preceding 'mod' calls:
3768 sample_scale(double sample_value
, unsigned int scale
)
3770 sample_value
= floor(sample_value
* scale
+ .5);
3772 /* Return NaN as 0: */
3773 if (!(sample_value
> 0))
3775 else if (sample_value
> scale
)
3776 sample_value
= scale
;
3778 return (unsigned int)sample_value
;
3782 image_transform_mod_end(PNG_CONST image_transform
*this, image_pixel
*that
,
3783 png_structp pp
, PNG_CONST transform_display
*display
)
3785 PNG_CONST
unsigned int scale
= (1U<<that
->sample_depth
)-1;
3791 /* At the end recalculate the digitized red green and blue values according
3792 * to the current sample_depth of the pixel.
3794 * The sample value is simply scaled to the maximum, checking for over
3795 * and underflow (which can both happen for some image transforms,
3796 * including simple size scaling, though libpng doesn't do that at present.
3798 that
->red
= sample_scale(that
->redf
, scale
);
3800 /* The error value is increased, at the end, according to the lowest sBIT
3801 * value seen. Common sense tells us that the intermediate integer
3802 * representations are no more accurate than +/- 0.5 in the integral values,
3803 * the sBIT allows the implementation to be worse than this. In addition the
3804 * PNG specification actually permits any error within the range (-1..+1),
3805 * but that is ignored here. Instead the final digitized value is compared,
3806 * below to the digitized value of the error limits - this has the net effect
3807 * of allowing (almost) +/-1 in the output value. It's difficult to see how
3808 * any algorithm that digitizes intermediate results can be more accurate.
3810 that
->rede
+= 1./(2*((1U<<that
->red_sBIT
)-1));
3812 if (that
->colour_type
& PNG_COLOR_MASK_COLOR
)
3814 that
->green
= sample_scale(that
->greenf
, scale
);
3815 that
->blue
= sample_scale(that
->bluef
, scale
);
3816 that
->greene
+= 1./(2*((1U<<that
->green_sBIT
)-1));
3817 that
->bluee
+= 1./(2*((1U<<that
->blue_sBIT
)-1));
3821 that
->blue
= that
->green
= that
->red
;
3822 that
->bluef
= that
->greenf
= that
->redf
;
3823 that
->bluee
= that
->greene
= that
->rede
;
3826 if ((that
->colour_type
& PNG_COLOR_MASK_ALPHA
) ||
3827 that
->colour_type
== PNG_COLOR_TYPE_PALETTE
)
3829 that
->alpha
= sample_scale(that
->alphaf
, scale
);
3830 that
->alphae
+= 1./(2*((1U<<that
->alpha_sBIT
)-1));
3834 that
->alpha
= scale
; /* opaque */
3835 that
->alpha
= 1; /* Override this. */
3836 that
->alphae
= 0; /* It's exact ;-) */
3840 /* Static 'end' structure: */
3841 static image_transform image_transform_end
=
3849 image_transform_set_end
,
3850 image_transform_mod_end
,
3851 0 /* never called, I want it to crash if it is! */
3854 /* Reader callbacks and implementations, where they differ from the standard
3858 transform_display_init(transform_display
*dp
, png_modifier
*pm
, png_uint_32 id
,
3859 PNG_CONST image_transform
*transform_list
)
3861 /* Standard fields */
3862 standard_display_init(&dp
->this, &pm
->this, id
, 0/*do_interlace*/);
3864 /* Parameter fields */
3866 dp
->transform_list
= transform_list
;
3868 /* Local variable fields */
3869 dp
->output_colour_type
= 255; /* invalid */
3870 dp
->output_bit_depth
= 255; /* invalid */
3874 transform_info_imp(transform_display
*dp
, png_structp pp
, png_infop pi
)
3876 /* Reuse the standard stuff as appropriate. */
3877 standard_info_part1(&dp
->this, pp
, pi
);
3879 /* Now set the list of transforms. */
3880 dp
->transform_list
->set(dp
->transform_list
, dp
, pp
, pi
);
3882 /* Update the info structure for these transforms: */
3883 png_read_update_info(pp
, pi
);
3885 /* And get the output information into the standard_display */
3886 standard_info_part2(&dp
->this, pp
, pi
, 1/*images*/);
3888 /* Plus the extra stuff we need for the transform tests: */
3889 dp
->output_colour_type
= png_get_color_type(pp
, pi
);
3890 dp
->output_bit_depth
= png_get_bit_depth(pp
, pi
);
3892 /* Validate the combination of colour type and bit depth that we are getting
3893 * out of libpng; the semantics of something not in the PNG spec are, at
3896 switch (dp
->output_colour_type
)
3898 case PNG_COLOR_TYPE_PALETTE
:
3899 if (dp
->output_bit_depth
> 8) goto error
;
3901 case PNG_COLOR_TYPE_GRAY
:
3902 if (dp
->output_bit_depth
== 1 || dp
->output_bit_depth
== 2 ||
3903 dp
->output_bit_depth
== 4)
3907 if (dp
->output_bit_depth
== 8 || dp
->output_bit_depth
== 16)
3915 pos
= safecat(message
, sizeof message
, 0,
3916 "invalid final bit depth: colour type(");
3917 pos
= safecatn(message
, sizeof message
, pos
, dp
->output_colour_type
);
3918 pos
= safecat(message
, sizeof message
, pos
, ") with bit depth: ");
3919 pos
= safecatn(message
, sizeof message
, pos
, dp
->output_bit_depth
);
3921 png_error(pp
, message
);
3925 /* Use a test pixel to check that the output agrees with what we expect -
3926 * this avoids running the whole test if the output is unexpected.
3929 image_pixel test_pixel
;
3931 memset(&test_pixel
, 0, sizeof test_pixel
);
3932 test_pixel
.colour_type
= dp
->this.colour_type
; /* input */
3933 test_pixel
.bit_depth
= dp
->this.bit_depth
;
3934 if (test_pixel
.colour_type
== PNG_COLOR_TYPE_PALETTE
)
3935 test_pixel
.sample_depth
= 8;
3937 test_pixel
.sample_depth
= test_pixel
.bit_depth
;
3938 /* Don't need sBIT here */
3939 test_pixel
.have_tRNS
= dp
->this.is_transparent
;
3941 dp
->transform_list
->mod(dp
->transform_list
, &test_pixel
, pp
, dp
);
3943 if (test_pixel
.colour_type
!= dp
->output_colour_type
)
3946 size_t pos
= safecat(message
, sizeof message
, 0, "colour type ");
3948 pos
= safecatn(message
, sizeof message
, pos
, dp
->output_colour_type
);
3949 pos
= safecat(message
, sizeof message
, pos
, " expected ");
3950 pos
= safecatn(message
, sizeof message
, pos
, test_pixel
.colour_type
);
3952 png_error(pp
, message
);
3955 if (test_pixel
.bit_depth
!= dp
->output_bit_depth
)
3958 size_t pos
= safecat(message
, sizeof message
, 0, "bit depth ");
3960 pos
= safecatn(message
, sizeof message
, pos
, dp
->output_bit_depth
);
3961 pos
= safecat(message
, sizeof message
, pos
, " expected ");
3962 pos
= safecatn(message
, sizeof message
, pos
, test_pixel
.bit_depth
);
3964 png_error(pp
, message
);
3967 /* If both bit depth and colour type are correct check the sample depth.
3968 * I believe these are both internal errors.
3970 if (test_pixel
.colour_type
== PNG_COLOR_TYPE_PALETTE
)
3972 if (test_pixel
.sample_depth
!= 8) /* oops - internal error! */
3973 png_error(pp
, "pngvalid: internal: palette sample depth not 8");
3975 else if (test_pixel
.sample_depth
!= dp
->output_bit_depth
)
3978 size_t pos
= safecat(message
, sizeof message
, 0,
3979 "internal: sample depth ");
3981 pos
= safecatn(message
, sizeof message
, pos
, dp
->output_bit_depth
);
3982 pos
= safecat(message
, sizeof message
, pos
, " expected ");
3983 pos
= safecatn(message
, sizeof message
, pos
, test_pixel
.sample_depth
);
3985 png_error(pp
, message
);
3991 transform_info(png_structp pp
, png_infop pi
)
3993 transform_info_imp(png_get_progressive_ptr(pp
), pp
, pi
);
3997 transform_range_check(png_structp pp
, unsigned int r
, unsigned int g
,
3998 unsigned int b
, unsigned int a
, unsigned int in_digitized
, double in
,
3999 unsigned int out
, png_byte sample_depth
, double err
, PNG_CONST
char *name
)
4001 /* Compare the scaled, digitzed, values of our local calculation (in+-err)
4002 * with the digitized values libpng produced; 'sample_depth' is the actual
4003 * digitization depth of the libpng output colors (the bit depth except for
4004 * palette images where it is always 8.)
4006 unsigned int max
= (1U<<sample_depth
)-1;
4007 double in_min
= ceil((in
-err
)*max
- .5);
4008 double in_max
= floor((in
+err
)*max
+ .5);
4009 if (!(out
>= in_min
&& out
<= in_max
))
4014 pos
= safecat(message
, sizeof message
, 0, name
);
4015 pos
= safecat(message
, sizeof message
, pos
, " output value error: rgba(");
4016 pos
= safecatn(message
, sizeof message
, pos
, r
);
4017 pos
= safecat(message
, sizeof message
, pos
, ",");
4018 pos
= safecatn(message
, sizeof message
, pos
, g
);
4019 pos
= safecat(message
, sizeof message
, pos
, ",");
4020 pos
= safecatn(message
, sizeof message
, pos
, b
);
4021 pos
= safecat(message
, sizeof message
, pos
, ",");
4022 pos
= safecatn(message
, sizeof message
, pos
, a
);
4023 pos
= safecat(message
, sizeof message
, pos
, "): ");
4024 pos
= safecatn(message
, sizeof message
, pos
, out
);
4025 pos
= safecat(message
, sizeof message
, pos
, " expected: ");
4026 pos
= safecatn(message
, sizeof message
, pos
, in_digitized
);
4027 pos
= safecat(message
, sizeof message
, pos
, " (");
4028 pos
= safecatd(message
, sizeof message
, pos
, (in
-err
)*max
, 3);
4029 pos
= safecat(message
, sizeof message
, pos
, "..");
4030 pos
= safecatd(message
, sizeof message
, pos
, (in
+err
)*max
, 3);
4031 pos
= safecat(message
, sizeof message
, pos
, ")");
4033 png_error(pp
, message
);
4038 transform_image_validate(transform_display
*dp
, png_structp pp
, png_infop pi
,
4039 png_const_bytep pRow
)
4041 /* Constants for the loop below: */
4042 PNG_CONST png_byte in_ct
= dp
->this.colour_type
;
4043 PNG_CONST png_byte in_bd
= dp
->this.bit_depth
;
4044 PNG_CONST png_uint_32 w
= dp
->this.w
;
4045 PNG_CONST png_uint_32 h
= dp
->this.h
;
4046 PNG_CONST
size_t cbRow
= dp
->this.cbRow
;
4047 PNG_CONST png_byte out_ct
= dp
->output_colour_type
;
4048 PNG_CONST png_byte out_bd
= dp
->output_bit_depth
;
4049 PNG_CONST png_byte sample_depth
= (png_byte
)(out_ct
==
4050 PNG_COLOR_TYPE_PALETTE
? 8 : out_bd
);
4051 PNG_CONST png_byte red_sBIT
= dp
->this.red_sBIT
;
4052 PNG_CONST png_byte green_sBIT
= dp
->this.green_sBIT
;
4053 PNG_CONST png_byte blue_sBIT
= dp
->this.blue_sBIT
;
4054 PNG_CONST png_byte alpha_sBIT
= dp
->this.alpha_sBIT
;
4055 PNG_CONST
int have_tRNS
= dp
->this.is_transparent
;
4057 standard_palette out_palette
;
4062 /* Read the palette corresponding to the output if the output colour type
4063 * indicates a palette, othewise set out_palette to garbage.
4065 if (out_ct
== PNG_COLOR_TYPE_PALETTE
)
4066 (void)standard_palette_init(out_palette
, pp
, pi
);
4068 memset(out_palette
, 0x5e, sizeof out_palette
);
4070 for (y
=0; y
<h
; ++y
, pRow
+= cbRow
)
4074 /* The original, standard, row pre-transforms. */
4075 png_byte std
[STANDARD_ROWMAX
];
4077 transform_row(pp
, std
, in_ct
, in_bd
, y
);
4079 /* Go through each original pixel transforming it and comparing with what
4080 * libpng did to the same pixel.
4084 image_pixel in_pixel
, out_pixel
;
4085 unsigned int r
, g
, b
, a
;
4087 /* Find out what we think the pixel should be: */
4088 image_pixel_init(&in_pixel
, std
, in_ct
, in_bd
, x
, dp
->this.palette
);
4090 in_pixel
.red_sBIT
= red_sBIT
;
4091 in_pixel
.green_sBIT
= green_sBIT
;
4092 in_pixel
.blue_sBIT
= blue_sBIT
;
4093 in_pixel
.alpha_sBIT
= alpha_sBIT
;
4094 in_pixel
.have_tRNS
= have_tRNS
;
4096 /* For error detection, below. */
4102 dp
->transform_list
->mod(dp
->transform_list
, &in_pixel
, pp
, dp
);
4104 /* Read the output pixel and compare it to what we got, we don't
4105 * use the error field here, so no need to update sBIT.
4107 image_pixel_init(&out_pixel
, pRow
, out_ct
, out_bd
, x
, out_palette
);
4109 /* We don't expect changes to the index here even if the bit depth is
4112 if (in_ct
== PNG_COLOR_TYPE_PALETTE
&&
4113 out_ct
== PNG_COLOR_TYPE_PALETTE
)
4115 if (in_pixel
.palette_index
!= out_pixel
.palette_index
)
4116 png_error(pp
, "unexpected transformed palette index");
4119 /* Check the colours for palette images too - in fact the palette could
4120 * be separately verified itself in most cases.
4122 if (in_pixel
.red
!= out_pixel
.red
)
4123 transform_range_check(pp
, r
, g
, b
, a
, in_pixel
.red
, in_pixel
.redf
,
4124 out_pixel
.red
, sample_depth
, in_pixel
.rede
, "red/gray");
4126 if ((out_ct
& PNG_COLOR_MASK_COLOR
) != 0 &&
4127 in_pixel
.green
!= out_pixel
.green
)
4128 transform_range_check(pp
, r
, g
, b
, a
, in_pixel
.green
,
4129 in_pixel
.greenf
, out_pixel
.green
, sample_depth
, in_pixel
.greene
,
4132 if ((out_ct
& PNG_COLOR_MASK_COLOR
) != 0 &&
4133 in_pixel
.blue
!= out_pixel
.blue
)
4134 transform_range_check(pp
, r
, g
, b
, a
, in_pixel
.blue
, in_pixel
.bluef
,
4135 out_pixel
.blue
, sample_depth
, in_pixel
.bluee
, "blue");
4137 if ((out_ct
& PNG_COLOR_MASK_ALPHA
) != 0 &&
4138 in_pixel
.alpha
!= out_pixel
.alpha
)
4139 transform_range_check(pp
, r
, g
, b
, a
, in_pixel
.alpha
,
4140 in_pixel
.alphaf
, out_pixel
.alpha
, sample_depth
, in_pixel
.alphae
,
4142 } /* pixel (x) loop */
4143 } /* row (y) loop */
4145 /* Record that something was actually checked to avoid a false positive. */
4146 dp
->this.ps
->validated
= 1;
4150 transform_end(png_structp pp
, png_infop pi
)
4152 transform_display
*dp
= png_get_progressive_ptr(pp
);
4154 transform_image_validate(dp
, pp
, pi
, dp
->this.ps
->image
);
4157 /* A single test run. */
4159 transform_test(png_modifier
*pmIn
, PNG_CONST png_uint_32 idIn
,
4160 PNG_CONST image_transform
* transform_listIn
, PNG_CONST
char *name
)
4162 transform_display d
;
4163 context(&pmIn
->this, fault
);
4165 transform_display_init(&d
, pmIn
, idIn
, transform_listIn
);
4172 /* Get a png_struct for writing the image. */
4173 pp
= set_modifier_for_read(d
.pm
, &pi
, d
.this.id
, name
);
4176 /* Logging (debugging only) */
4180 (void)store_message(&d
.pm
->this, pp
, buffer
, sizeof buffer
, 0,
4183 fprintf(stderr
, "%s\n", buffer
);
4187 /* Introduce the correct read function. */
4188 if (d
.pm
->this.progressive
)
4190 /* Share the row function with the standard implementation. */
4191 png_set_progressive_read_fn(pp
, &d
, transform_info
, progressive_row
,
4194 /* Now feed data into the reader until we reach the end: */
4195 modifier_progressive_read(d
.pm
, pp
, pi
);
4199 /* modifier_read expects a png_modifier* */
4200 png_set_read_fn(pp
, d
.pm
, modifier_read
);
4202 /* Check the header values: */
4203 png_read_info(pp
, pi
);
4205 /* Process the 'info' requirements. Only one image is generated */
4206 transform_info_imp(&d
, pp
, pi
);
4208 sequential_row(&d
.this, pp
, pi
, NULL
, d
.this.ps
->image
);
4210 transform_image_validate(&d
, pp
, pi
, d
.this.ps
->image
);
4213 modifier_reset(d
.pm
);
4217 modifier_reset((png_modifier
*)fault
);
4220 /* The transforms: */
4221 #define ITSTRUCT(name) image_transform_##name
4222 #define IT(name,prev)\
4223 static image_transform ITSTRUCT(name) =\
4227 &ITSTRUCT(prev), /*list*/\
4231 image_transform_png_set_##name##_set,\
4232 image_transform_png_set_##name##_mod,\
4233 image_transform_png_set_##name##_add\
4238 image_transform_default_add(image_transform
*this,
4239 PNG_CONST image_transform
**that
, png_byte colour_type
, png_byte bit_depth
)
4250 /* png_set_palette_to_rgb */
4252 image_transform_png_set_palette_to_rgb_set(PNG_CONST image_transform
*this,
4253 transform_display
*that
, png_structp pp
, png_infop pi
)
4255 png_set_palette_to_rgb(pp
);
4256 this->next
->set(this->next
, that
, pp
, pi
);
4260 image_transform_png_set_palette_to_rgb_mod(PNG_CONST image_transform
*this,
4261 image_pixel
*that
, png_structp pp
, PNG_CONST transform_display
*display
)
4263 if (that
->colour_type
== PNG_COLOR_TYPE_PALETTE
)
4264 image_pixel_convert_PLTE(that
, &display
->this);
4266 this->next
->mod(this->next
, that
, pp
, display
);
4270 image_transform_png_set_palette_to_rgb_add(image_transform
*this,
4271 PNG_CONST image_transform
**that
, png_byte colour_type
, png_byte bit_depth
)
4278 return colour_type
== PNG_COLOR_TYPE_PALETTE
;
4281 IT(palette_to_rgb
, end
);
4284 /* png_set_tRNS_to_alpha */
4286 image_transform_png_set_tRNS_to_alpha_set(PNG_CONST image_transform
*this,
4287 transform_display
*that
, png_structp pp
, png_infop pi
)
4289 png_set_tRNS_to_alpha(pp
);
4290 this->next
->set(this->next
, that
, pp
, pi
);
4294 image_transform_png_set_tRNS_to_alpha_mod(PNG_CONST image_transform
*this,
4295 image_pixel
*that
, png_structp pp
, PNG_CONST transform_display
*display
)
4297 /* LIBPNG BUG: this always forces palette images to RGB. */
4298 if (that
->colour_type
== PNG_COLOR_TYPE_PALETTE
)
4299 image_pixel_convert_PLTE(that
, &display
->this);
4301 /* This effectively does an 'expand' only if there is some transparency to
4302 * covert to an alpha channel.
4304 if (that
->have_tRNS
)
4305 image_pixel_add_alpha(that
, &display
->this);
4307 /* LIBPNG BUG: otherwise libpng still expands to 8 bits! */
4310 if (that
->bit_depth
< 8)
4312 if (that
->sample_depth
< 8)
4313 that
->sample_depth
= 8;
4316 this->next
->mod(this->next
, that
, pp
, display
);
4320 image_transform_png_set_tRNS_to_alpha_add(image_transform
*this,
4321 PNG_CONST image_transform
**that
, png_byte colour_type
, png_byte bit_depth
)
4328 /* We don't know yet whether there will be a tRNS chunk, but we know that
4329 * this transformation should do nothing if there already is an alpha
4332 return (colour_type
& PNG_COLOR_MASK_ALPHA
) == 0;
4335 IT(tRNS_to_alpha
,palette_to_rgb
);
4337 /* png_set_gray_to_rgb */
4339 image_transform_png_set_gray_to_rgb_set(PNG_CONST image_transform
*this,
4340 transform_display
*that
, png_structp pp
, png_infop pi
)
4342 png_set_gray_to_rgb(pp
);
4343 this->next
->set(this->next
, that
, pp
, pi
);
4347 image_transform_png_set_gray_to_rgb_mod(PNG_CONST image_transform
*this,
4348 image_pixel
*that
, png_structp pp
, PNG_CONST transform_display
*display
)
4350 /* NOTE: we can actually pend the tRNS processing at this point because we
4351 * can correctly recognize the original pixel value even though we have
4352 * mapped the one gray channel to the three RGB ones, but in fact libpng
4353 * doesn't do this, so we don't either.
4355 if ((that
->colour_type
& PNG_COLOR_MASK_COLOR
) == 0 && that
->have_tRNS
)
4356 image_pixel_add_alpha(that
, &display
->this);
4358 /* Simply expand the bit depth and alter the colour type as required. */
4359 if (that
->colour_type
== PNG_COLOR_TYPE_GRAY
)
4361 /* RGB images have a bit depth at least equal to '8' */
4362 if (that
->bit_depth
< 8)
4363 that
->sample_depth
= that
->bit_depth
= 8;
4365 /* And just changing the colour type works here because the green and blue
4366 * channels are being maintained in lock-step with the red/gray:
4368 that
->colour_type
= PNG_COLOR_TYPE_RGB
;
4371 else if (that
->colour_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
4372 that
->colour_type
= PNG_COLOR_TYPE_RGB_ALPHA
;
4374 this->next
->mod(this->next
, that
, pp
, display
);
4378 image_transform_png_set_gray_to_rgb_add(image_transform
*this,
4379 PNG_CONST image_transform
**that
, png_byte colour_type
, png_byte bit_depth
)
4386 return (colour_type
& PNG_COLOR_MASK_COLOR
) == 0;
4389 IT(gray_to_rgb
,tRNS_to_alpha
);
4391 /* png_set_expand */
4393 image_transform_png_set_expand_set(PNG_CONST image_transform
*this,
4394 transform_display
*that
, png_structp pp
, png_infop pi
)
4397 this->next
->set(this->next
, that
, pp
, pi
);
4401 image_transform_png_set_expand_mod(PNG_CONST image_transform
*this,
4402 image_pixel
*that
, png_structp pp
, PNG_CONST transform_display
*display
)
4404 /* The general expand case depends on what the colour type is: */
4405 if (that
->colour_type
== PNG_COLOR_TYPE_PALETTE
)
4406 image_pixel_convert_PLTE(that
, &display
->this);
4407 else if (that
->bit_depth
< 8) /* grayscale */
4408 that
->sample_depth
= that
->bit_depth
= 8;
4410 if (that
->have_tRNS
)
4411 image_pixel_add_alpha(that
, &display
->this);
4413 this->next
->mod(this->next
, that
, pp
, display
);
4417 image_transform_png_set_expand_add(image_transform
*this,
4418 PNG_CONST image_transform
**that
, png_byte colour_type
, png_byte bit_depth
)
4425 /* 'expand' should do nothing for RGBA or GA input - no tRNS and the bit
4426 * depth is at least 8 already.
4428 return (colour_type
& PNG_COLOR_MASK_ALPHA
) == 0;
4431 IT(expand
,gray_to_rgb
);
4433 /* png_set_expand_gray_1_2_4_to_8
4434 * LIBPNG BUG: this just does an 'expand'
4437 image_transform_png_set_expand_gray_1_2_4_to_8_set(
4438 PNG_CONST image_transform
*this, transform_display
*that
, png_structp pp
,
4441 png_set_expand_gray_1_2_4_to_8(pp
);
4442 this->next
->set(this->next
, that
, pp
, pi
);
4446 image_transform_png_set_expand_gray_1_2_4_to_8_mod(
4447 PNG_CONST image_transform
*this, image_pixel
*that
, png_structp pp
,
4448 PNG_CONST transform_display
*display
)
4450 image_transform_png_set_expand_mod(this, that
, pp
, display
);
4454 image_transform_png_set_expand_gray_1_2_4_to_8_add(image_transform
*this,
4455 PNG_CONST image_transform
**that
, png_byte colour_type
, png_byte bit_depth
)
4457 return image_transform_png_set_expand_add(this, that
, colour_type
,
4461 IT(expand_gray_1_2_4_to_8
, expand
);
4463 /* png_set_strip_16 */
4465 image_transform_png_set_strip_16_set(PNG_CONST image_transform
*this,
4466 transform_display
*that
, png_structp pp
, png_infop pi
)
4468 png_set_strip_16(pp
);
4469 this->next
->set(this->next
, that
, pp
, pi
);
4473 image_transform_png_set_strip_16_mod(PNG_CONST image_transform
*this,
4474 image_pixel
*that
, png_structp pp
, PNG_CONST transform_display
*display
)
4476 if (that
->bit_depth
== 16)
4478 that
->sample_depth
= that
->bit_depth
= 8;
4479 if (that
->red_sBIT
> 8) that
->red_sBIT
= 8;
4480 if (that
->green_sBIT
> 8) that
->green_sBIT
= 8;
4481 if (that
->blue_sBIT
> 8) that
->blue_sBIT
= 8;
4482 if (that
->alpha_sBIT
> 8) that
->alpha_sBIT
= 8;
4484 # ifndef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED
4485 /* The strip 16 algoirithm drops the low 8 bits rather than calculating
4486 * 1/257, so we need to adjust the permitted errors appropriately:
4489 PNG_CONST
double d
= (255-128.5)/65535;
4498 this->next
->mod(this->next
, that
, pp
, display
);
4502 image_transform_png_set_strip_16_add(image_transform
*this,
4503 PNG_CONST image_transform
**that
, png_byte colour_type
, png_byte bit_depth
)
4510 return bit_depth
> 8;
4513 IT(strip_16
, expand_gray_1_2_4_to_8
);
4515 /* png_set_strip_alpha */
4517 image_transform_png_set_strip_alpha_set(PNG_CONST image_transform
*this,
4518 transform_display
*that
, png_structp pp
, png_infop pi
)
4520 png_set_strip_alpha(pp
);
4521 this->next
->set(this->next
, that
, pp
, pi
);
4525 image_transform_png_set_strip_alpha_mod(PNG_CONST image_transform
*this,
4526 image_pixel
*that
, png_structp pp
, PNG_CONST transform_display
*display
)
4528 if (that
->colour_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
4529 that
->colour_type
= PNG_COLOR_TYPE_GRAY
;
4530 else if (that
->colour_type
== PNG_COLOR_TYPE_RGB_ALPHA
)
4531 that
->colour_type
= PNG_COLOR_TYPE_RGB
;
4533 that
->have_tRNS
= 0;
4537 this->next
->mod(this->next
, that
, pp
, display
);
4541 image_transform_png_set_strip_alpha_add(image_transform
*this,
4542 PNG_CONST image_transform
**that
, png_byte colour_type
, png_byte bit_depth
)
4549 return (colour_type
& PNG_COLOR_MASK_ALPHA
) != 0;
4552 IT(strip_alpha
,strip_16
);
4554 /* png_set_rgb_to_gray(png_structp, int err_action, double red, double green)
4555 * png_set_rgb_to_gray_fixed(png_structp, int err_action, png_fixed_point red,
4556 * png_fixed_point green)
4557 * png_get_rgb_to_gray_status
4559 * At present the APIs are simply tested using the 16.16 fixed point conversion
4560 * values known to be used inside libpng:
4566 * NOTE: this currently ignores the gamma because no gamma is being set, the
4567 * tests on gamma need to happen in the gamma test set.
4570 image_transform_png_set_rgb_to_gray_set(PNG_CONST image_transform
*this,
4571 transform_display
*that
, png_structp pp
, png_infop pi
)
4573 PNG_CONST
int error_action
= 1; /* no error, no defines in png.h */
4575 # ifdef PNG_FLOATING_POINT_SUPPORTED
4576 png_set_rgb_to_gray(pp
, error_action
, -1, -1);
4578 png_set_rgb_to_gray_fixed(pp
, error_action
, -1, -1);
4581 this->next
->set(this->next
, that
, pp
, pi
);
4585 image_transform_png_set_rgb_to_gray_mod(PNG_CONST image_transform
*this,
4586 image_pixel
*that
, png_structp pp
, PNG_CONST transform_display
*display
)
4588 if ((that
->colour_type
& PNG_COLOR_MASK_COLOR
) != 0)
4590 if (that
->colour_type
== PNG_COLOR_TYPE_PALETTE
)
4591 image_pixel_convert_PLTE(that
, &display
->this);
4593 /* Image now has RGB channels... */
4594 that
->bluef
= that
->greenf
= that
->redf
= (that
->redf
* 6968 +
4595 that
->greenf
* 23434 + that
->bluef
* 2366) / 32768;
4596 that
->bluee
= that
->greene
= that
->rede
= (that
->rede
* 6968 +
4597 that
->greene
* 23434 + that
->bluee
* 2366) / 32768 *
4598 (1 + DBL_EPSILON
* 6);
4600 /* The sBIT is the minium of the three colour channel sBITs. */
4601 if (that
->red_sBIT
> that
->green_sBIT
)
4602 that
->red_sBIT
= that
->green_sBIT
;
4603 if (that
->red_sBIT
> that
->blue_sBIT
)
4604 that
->red_sBIT
= that
->blue_sBIT
;
4605 that
->blue_sBIT
= that
->green_sBIT
= that
->red_sBIT
;
4607 /* And zap the colour bit in the type: */
4608 if (that
->colour_type
== PNG_COLOR_TYPE_RGB
)
4609 that
->colour_type
= PNG_COLOR_TYPE_GRAY
;
4610 else if (that
->colour_type
== PNG_COLOR_TYPE_RGB_ALPHA
)
4611 that
->colour_type
= PNG_COLOR_TYPE_GRAY_ALPHA
;
4614 this->next
->mod(this->next
, that
, pp
, display
);
4618 image_transform_png_set_rgb_to_gray_add(image_transform
*this,
4619 PNG_CONST image_transform
**that
, png_byte colour_type
, png_byte bit_depth
)
4626 return (colour_type
& PNG_COLOR_MASK_COLOR
) != 0;
4629 IT(rgb_to_gray
,strip_alpha
);
4631 /* png_set_background(png_structp, png_const_color_16p background_color,
4632 * int background_gamma_code, int need_expand, double background_gamma)
4633 * png_set_background_fixed(png_structp, png_const_color_16p background_color,
4634 * int background_gamma_code, int need_expand,
4635 * png_fixed_point background_gamma)
4637 * As with rgb_to_gray this ignores the gamma.
4640 image_transform_png_set_background_set(PNG_CONST image_transform
*this,
4641 transform_display
*that
, png_structp pp
, png_infop pi
)
4645 /* Since we don't know the output bit depth at this point we must use the
4646 * input values and ask libpng to expand the chunk as required.
4648 back
.index
= 255; /* Should not be used */
4649 back
.gray
= back
.blue
= back
.green
= back
.red
=
4650 (png_uint_16
)((1U << that
->this.bit_depth
) >> 1);
4652 # ifdef PNG_FLOATING_POINT_SUPPORTED
4653 png_set_background(pp
, &back
, PNG_BACKGROUND_GAMMA_FILE
, 1, 0);
4655 png_set_background_fixed(pp
, &back
, PNG_BACKGROUND_GAMMA_FILE
, 1, 0);
4658 this->next
->set(this->next
, that
, pp
, pi
);
4662 image_transform_png_set_background_mod(PNG_CONST image_transform
*this,
4663 image_pixel
*that
, png_structp pp
, PNG_CONST transform_display
*display
)
4665 /* Check for tRNS first: */
4666 if (that
->have_tRNS
&& that
->colour_type
!= PNG_COLOR_TYPE_PALETTE
)
4667 image_pixel_add_alpha(that
, &display
->this);
4669 /* This is only necessary if the alpha value is less than 1. */
4670 if (that
->alphaf
< 1)
4672 /* Repeat the calculation above and scale the result: */
4673 unsigned int tmp
= (1U << display
->this.bit_depth
);
4674 double component
= (tmp
>> 1)/(double)(tmp
-1);
4676 /* Now we do the background calculation without any gamma correction. */
4677 if (that
->alphaf
<= 0)
4679 that
->bluef
= that
->greenf
= that
->redf
= component
;
4680 that
->bluee
= that
->greene
= that
->rede
= component
* DBL_EPSILON
;
4681 that
->blue_sBIT
= that
->green_sBIT
= that
->red_sBIT
= that
->bit_depth
;
4686 component
*= 1-that
->alphaf
;
4687 that
->redf
= that
->redf
* that
->alphaf
+ component
;
4688 that
->rede
= that
->rede
* that
->alphaf
+ that
->redf
* 3 * DBL_EPSILON
;
4689 that
->greenf
= that
->greenf
* that
->alphaf
+ component
;
4690 that
->greene
= that
->greene
* that
->alphaf
+ that
->greenf
* 3 *
4692 that
->bluef
= that
->bluef
* that
->alphaf
+ component
;
4693 that
->bluee
= that
->bluee
* that
->alphaf
+ that
->bluef
* 3 *
4697 /* Remove the alpha type and set the alpha. */
4701 if (that
->colour_type
== PNG_COLOR_TYPE_RGB_ALPHA
)
4702 that
->colour_type
= PNG_COLOR_TYPE_RGB
;
4703 else if (that
->colour_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
4704 that
->colour_type
= PNG_COLOR_TYPE_GRAY
;
4707 this->next
->mod(this->next
, that
, pp
, display
);
4710 #define image_transform_png_set_background_add image_transform_default_add
4712 IT(background
,rgb_to_gray
);
4714 static image_transform
*PNG_CONST image_transform_first
= &ITSTRUCT(background
);
4717 transform_enable(PNG_CONST
char *name
)
4719 /* Everything starts out enabled, so if we see an 'enable' disabled
4720 * everything else the first time round.
4722 static int all_disabled
= 0;
4724 image_transform
*list
= image_transform_first
;
4726 while (list
!= &image_transform_end
)
4728 if (strcmp(list
->name
, name
) == 0)
4733 else if (!all_disabled
)
4743 fprintf(stderr
, "pngvalid: --transform-enable=%s: unknown transform\n",
4750 transform_disable(PNG_CONST
char *name
)
4752 image_transform
*list
= image_transform_first
;
4754 while (list
!= &image_transform_end
)
4756 if (strcmp(list
->name
, name
) == 0)
4765 fprintf(stderr
, "pngvalid: --transform-disable=%s: unknown transform\n",
4771 image_transform_reset_count(void)
4773 image_transform
*next
= image_transform_first
;
4776 while (next
!= &image_transform_end
)
4778 next
->local_use
= 0;
4784 /* This can only happen if we every have more than 32 transforms (excluding
4785 * the end) in the list.
4787 if (count
> 32) abort();
4791 image_transform_test_counter(png_uint_32 counter
, unsigned int max
)
4793 /* Test the list to see if there is any point contining, given a current
4794 * counter and a 'max' value.
4796 image_transform
*next
= image_transform_first
;
4798 while (next
!= &image_transform_end
)
4800 /* For max 0 or 1 continue until the counter overflows: */
4803 /* Continue if any entry hasn't reacked the max. */
4804 if (max
> 1 && next
->local_use
< max
)
4809 return max
<= 1 && counter
== 0;
4813 image_transform_add(PNG_CONST image_transform
**this, unsigned int max
,
4814 png_uint_32 counter
, char *name
, size_t sizeof_name
, size_t *pos
,
4815 png_byte colour_type
, png_byte bit_depth
)
4817 for (;;) /* until we manage to add something */
4820 image_transform
*list
;
4822 /* Find the next counter value, if the counter is zero this is the start
4823 * of the list. This routine always returns the current counter (not the
4824 * next) so it returns 0 at the end and expects 0 at the beginning.
4826 if (counter
== 0) /* first time */
4828 image_transform_reset_count();
4832 counter
= random_32();
4834 else /* advance the counter */
4838 case 0: ++counter
; break;
4839 case 1: counter
<<= 1; break;
4840 default: counter
= random_32(); break;
4844 /* Now add all these items, if possible */
4845 *this = &image_transform_end
;
4846 list
= image_transform_first
;
4849 /* Go through the whole list adding anything that the counter selects: */
4850 while (list
!= &image_transform_end
)
4852 if ((counter
& mask
) != 0 && list
->enable
&&
4853 (max
== 0 || list
->local_use
< max
))
4855 /* Candidate to add: */
4856 if (list
->add(list
, this, colour_type
, bit_depth
) || max
== 0)
4858 /* Added, so add to the name too. */
4859 *pos
= safecat(name
, sizeof_name
, *pos
, " +");
4860 *pos
= safecat(name
, sizeof_name
, *pos
, list
->name
);
4865 /* Not useful and max>0, so remvoe it from *this: */
4869 /* And, since we know it isn't useful, stop it being added again
4872 list
->local_use
= max
;
4880 /* Now if anything was added we have something to do. */
4881 if (*this != &image_transform_end
)
4884 /* Nothing added, but was there anything in there to add? */
4885 if (!image_transform_test_counter(counter
, max
))
4890 #ifdef THIS_IS_THE_PROFORMA
4892 image_transform_png_set_@
_set(PNG_CONST image_transform
*this,
4893 transform_display
*that
, png_structp pp
, png_infop pi
)
4896 this->next
->set(this->next
, that
, pp
, pi
);
4900 image_transform_png_set_@
_mod(PNG_CONST image_transform
*this,
4901 image_pixel
*that
, png_structp pp
, PNG_CONST transform_display
*display
)
4903 this->next
->mod(this->next
, that
, pp
, display
);
4907 image_transform_png_set_@
_add(image_transform
*this,
4908 PNG_CONST image_transform
**that
, char *name
, size_t sizeof_name
,
4909 size_t *pos
, png_byte colour_type
, png_byte bit_depth
)
4914 *pos
= safecat(name
, sizeof_name
, *pos
, " +@");
4922 /* png_set_quantize(png_structp, png_colorp palette, int num_palette,
4923 * int maximum_colors, png_const_uint_16p histogram, int full_quantize)
4925 * Very difficult to validate this!
4929 /* The data layout transforms are handled by swapping our own channel data,
4930 * necessarily these need to happen at the end of the transform list because the
4931 * semantic of the channels changes after these are executed. Some of these,
4932 * like set_shift and set_packing, can't be done at present because they change
4933 * the layout of the data at the sub-sample level so sample() won't get the
4936 /* png_set_invert_alpha */
4942 /* png_set_swap_alpha */
4948 /* png_set_filler, (png_structp png_ptr, png_uint_32 filler, int flags)); */
4951 /* png_set_add_alpha, (png_structp png_ptr, png_uint_32 filler, int flags)); */
4954 /* png_set_packing */
4957 /* png_set_packswap */
4960 /* png_set_invert_mono */
4963 /* png_set_shift(png_structp, png_const_color_8p true_bits) */
4967 test_transform(png_modifier
* PNG_CONST pm
, png_byte PNG_CONST colour_type
,
4968 int bdlo
, int PNG_CONST bdhi
, png_uint_32 max
)
4970 for (; bdlo
<= bdhi
; ++bdlo
)
4972 PNG_CONST png_byte bit_depth
= DEPTH(bdlo
);
4973 png_uint_32 counter
= 0;
4977 base_pos
= safecat(name
, sizeof name
, 0, "transform:");
4981 size_t pos
= base_pos
;
4982 PNG_CONST image_transform
*list
= 0;
4984 counter
= image_transform_add(&list
, max
, counter
, name
, sizeof name
,
4985 &pos
, colour_type
, bit_depth
);
4990 /* The command line can change this to checking interlaced images. */
4991 transform_test(pm
, FILEID(colour_type
, bit_depth
, pm
->interlace_type
,
4992 0, 0, 0), list
, name
);
4999 return 1; /* keep going */
5003 perform_transform_test(png_modifier
*pm
)
5005 /* Test each colour type over the valid range of bit depths (expressed as
5006 * log2(bit_depth) in turn, stop as soon as any error is detected.
5008 if (!test_transform(pm
, 0, 0, READ_BDHI
, 1))
5011 if (!test_transform(pm
, 2, 3, READ_BDHI
, 1))
5014 if (!test_transform(pm
, 3, 0, 3, 1))
5017 if (!test_transform(pm
, 4, 3, READ_BDHI
, 1))
5020 if (!test_transform(pm
, 6, 3, READ_BDHI
, 1))
5025 /********************************* GAMMA TESTS ********************************/
5026 /* Gamma test images. */
5027 typedef struct gamma_modification
5029 png_modification
this;
5030 png_fixed_point gamma
;
5031 } gamma_modification
;
5034 gamma_modify(png_modifier
*pm
, png_modification
*me
, int add
)
5037 /* This simply dumps the given gamma value into the buffer. */
5038 png_save_uint_32(pm
->buffer
, 4);
5039 png_save_uint_32(pm
->buffer
+4, CHUNK_gAMA
);
5040 png_save_uint_32(pm
->buffer
+8, ((gamma_modification
*)me
)->gamma
);
5045 gamma_modification_init(gamma_modification
*me
, png_modifier
*pm
, double gammad
)
5049 modification_init(&me
->this);
5050 me
->this.chunk
= CHUNK_gAMA
;
5051 me
->this.modify_fn
= gamma_modify
;
5052 me
->this.add
= CHUNK_PLTE
;
5053 g
= floor(gammad
* 100000 + .5);
5054 me
->gamma
= (png_fixed_point
)g
;
5055 me
->this.next
= pm
->modifications
;
5056 pm
->modifications
= &me
->this;
5059 typedef struct srgb_modification
5061 png_modification
this;
5063 } srgb_modification
;
5066 srgb_modify(png_modifier
*pm
, png_modification
*me
, int add
)
5069 /* As above, ignore add and just make a new chunk */
5070 png_save_uint_32(pm
->buffer
, 1);
5071 png_save_uint_32(pm
->buffer
+4, CHUNK_sRGB
);
5072 pm
->buffer
[8] = ((srgb_modification
*)me
)->intent
;
5077 srgb_modification_init(srgb_modification
*me
, png_modifier
*pm
, png_byte intent
)
5079 modification_init(&me
->this);
5080 me
->this.chunk
= CHUNK_sBIT
;
5082 if (intent
<= 3) /* if valid, else *delete* sRGB chunks */
5084 me
->this.modify_fn
= srgb_modify
;
5085 me
->this.add
= CHUNK_PLTE
;
5086 me
->intent
= intent
;
5091 me
->this.modify_fn
= 0;
5096 me
->this.next
= pm
->modifications
;
5097 pm
->modifications
= &me
->this;
5100 typedef struct sbit_modification
5102 png_modification
this;
5104 } sbit_modification
;
5107 sbit_modify(png_modifier
*pm
, png_modification
*me
, int add
)
5109 png_byte sbit
= ((sbit_modification
*)me
)->sbit
;
5110 if (pm
->bit_depth
> sbit
)
5113 switch (pm
->colour_type
)
5133 png_error(pm
->this.pread
,
5134 "unexpected colour type in sBIT modification");
5137 png_save_uint_32(pm
->buffer
, cb
);
5138 png_save_uint_32(pm
->buffer
+4, CHUNK_sBIT
);
5141 (pm
->buffer
+8)[--cb
] = sbit
;
5147 /* Remove the sBIT chunk */
5148 pm
->buffer_count
= pm
->buffer_position
= 0;
5152 return 0; /* do nothing */
5156 sbit_modification_init(sbit_modification
*me
, png_modifier
*pm
, png_byte sbit
)
5158 modification_init(&me
->this);
5159 me
->this.chunk
= CHUNK_sBIT
;
5160 me
->this.modify_fn
= sbit_modify
;
5161 me
->this.add
= CHUNK_PLTE
;
5163 me
->this.next
= pm
->modifications
;
5164 pm
->modifications
= &me
->this;
5167 /* Reader callbacks and implementations, where they differ from the standard
5170 typedef struct gamma_display
5172 standard_display
this;
5177 double screen_gamma
;
5180 PNG_CONST
char* name
;
5182 int use_input_precision
;
5185 /* Local variables */
5192 gamma_display_init(gamma_display
*dp
, png_modifier
*pm
, png_uint_32 id
,
5193 double file_gamma
, double screen_gamma
, png_byte sbit
, int threshold_test
,
5194 int speed
, int use_input_precision
, int strip16
)
5196 /* Standard fields */
5197 standard_display_init(&dp
->this, &pm
->this, id
, 0/*do_interlace*/);
5199 /* Parameter fields */
5201 dp
->file_gamma
= file_gamma
;
5202 dp
->screen_gamma
= screen_gamma
;
5204 dp
->threshold_test
= threshold_test
;
5206 dp
->use_input_precision
= use_input_precision
;
5207 dp
->strip16
= strip16
;
5209 /* Local variable fields */
5210 dp
->maxerrout
= dp
->maxerrpc
= dp
->maxerrabs
= 0;
5214 gamma_info_imp(gamma_display
*dp
, png_structp pp
, png_infop pi
)
5216 /* Reuse the standard stuff as appropriate. */
5217 standard_info_part1(&dp
->this, pp
, pi
);
5219 /* If requested strip 16 to 8 bits - this is handled automagically below
5220 * because the output bit depth is read from the library. Note that there
5221 * are interactions with sBIT but, internally, libpng makes sbit at most
5222 * PNG_MAX_GAMMA_8 when doing the following.
5225 # ifdef PNG_READ_16_TO_8_SUPPORTED
5226 png_set_strip_16(pp
);
5228 png_error(pp
, "strip16 (16 to 8 bit conversion) not supported");
5231 png_read_update_info(pp
, pi
);
5233 /* Now we may get a different cbRow: */
5234 standard_info_part2(&dp
->this, pp
, pi
, 1 /*images*/);
5238 gamma_info(png_structp pp
, png_infop pi
)
5240 gamma_info_imp(png_get_progressive_ptr(pp
), pp
, pi
);
5244 gamma_image_validate(gamma_display
*dp
, png_structp pp
, png_infop pi
,
5245 png_const_bytep pRow
)
5247 /* Get some constants derived from the input and output file formats: */
5248 PNG_CONST png_byte sbit
= dp
->sbit
;
5249 PNG_CONST
double file_gamma
= dp
->file_gamma
;
5250 PNG_CONST
double screen_gamma
= dp
->screen_gamma
;
5251 PNG_CONST
int use_input_precision
= dp
->use_input_precision
;
5252 PNG_CONST
int speed
= dp
->speed
;
5253 PNG_CONST png_byte in_ct
= dp
->this.colour_type
;
5254 PNG_CONST png_byte in_bd
= dp
->this.bit_depth
;
5255 PNG_CONST png_uint_32 w
= dp
->this.w
;
5256 PNG_CONST png_uint_32 h
= dp
->this.h
;
5257 PNG_CONST
size_t cbRow
= dp
->this.cbRow
;
5258 PNG_CONST png_byte out_ct
= png_get_color_type(pp
, pi
);
5259 PNG_CONST png_byte out_bd
= png_get_bit_depth(pp
, pi
);
5260 PNG_CONST
unsigned int outmax
= (1U<<out_bd
)-1;
5261 PNG_CONST
double maxabs
= abserr(dp
->pm
, out_bd
);
5262 PNG_CONST
double maxout
= outerr(dp
->pm
, out_bd
);
5263 PNG_CONST
double maxpc
= pcerr(dp
->pm
, out_bd
);
5265 /* There are three sources of error, firstly the quantization in the
5266 * file encoding, determined by sbit and/or the file depth, secondly
5267 * the output (screen) gamma and thirdly the output file encoding.
5269 * Since this API receives the screen and file gamma in double
5270 * precision it is possible to calculate an exact answer given an input
5271 * pixel value. Therefore we assume that the *input* value is exact -
5272 * sample/maxsample - calculate the corresponding gamma corrected
5273 * output to the limits of double precision arithmetic and compare with
5274 * what libpng returns.
5276 * Since the library must quantize the output to 8 or 16 bits there is
5277 * a fundamental limit on the accuracy of the output of +/-.5 - this
5278 * quantization limit is included in addition to the other limits
5279 * specified by the paramaters to the API. (Effectively, add .5
5282 * The behavior of the 'sbit' paramter is defined by section 12.5
5283 * (sample depth scaling) of the PNG spec. That section forces the
5284 * decoder to assume that the PNG values have been scaled if sBIT is
5287 * png-sample = floor( input-sample * (max-out/max-in) + .5);
5289 * This means that only a subset of the possible PNG values should
5290 * appear in the input. However, the spec allows the encoder to use a
5291 * variety of approximations to the above and doesn't require any
5292 * restriction of the values produced.
5294 * Nevertheless the spec requires that the upper 'sBIT' bits of the
5295 * value stored in a PNG file be the original sample bits.
5296 * Consequently the code below simply scales the top sbit bits by
5297 * (1<<sbit)-1 to obtain an original sample value.
5299 * Because there is limited precision in the input it is arguable that
5300 * an acceptable result is any valid result from input-.5 to input+.5.
5301 * The basic tests below do not do this, however if
5302 * 'use_input_precision' is set a subsequent test is performed below.
5304 PNG_CONST
int processing
= (fabs(screen_gamma
*file_gamma
-1) >=
5305 PNG_GAMMA_THRESHOLD
&& !dp
->threshold_test
&& !speed
&& in_ct
!= 3) ||
5308 PNG_CONST
unsigned int samples_per_pixel
= (out_ct
& 2U) ? 3U : 1U;
5310 PNG_CONST
double gamma_correction
= 1/(file_gamma
*screen_gamma
);/* Overall */
5312 double maxerrout
= 0, maxerrabs
= 0, maxerrpc
= 0;
5315 for (y
=0; y
<h
; ++y
, pRow
+= cbRow
)
5318 png_byte std
[STANDARD_ROWMAX
];
5320 transform_row(pp
, std
, in_ct
, in_bd
, y
);
5324 for (x
=0; x
<w
; ++x
) for (s
=0; s
<samples_per_pixel
; ++s
)
5326 /* Input sample values: */
5327 PNG_CONST
unsigned int
5328 id
= sample(std
, in_ct
, in_bd
, x
, s
);
5330 PNG_CONST
unsigned int
5331 od
= sample(pRow
, out_ct
, out_bd
, x
, s
);
5333 PNG_CONST
unsigned int
5334 isbit
= id
>> (in_bd
-sbit
);
5336 double i
, input_sample
, encoded_sample
, output
;
5337 double encoded_error
, error
;
5338 double es_lo
, es_hi
;
5340 /* First check on the 'perfect' result obtained from the
5341 * digitized input value, id, and compare this against the
5342 * actual digitized result, 'od'. 'i' is the input result
5343 * in the range 0..1:
5345 * NOTE: sBIT should be taken into account here but isn't,
5346 * as described above.
5348 i
= isbit
; i
/= (1U<<sbit
)-1;
5350 /* Then get the gamma corrected version of 'i' and compare
5351 * to 'od', any error less than .5 is insignificant - just
5352 * quantization of the output value to the nearest digital
5353 * value (nevertheless the error is still recorded - it's
5356 encoded_sample
= pow(i
, gamma_correction
) * outmax
;
5357 encoded_error
= fabs(od
-encoded_sample
);
5359 if (encoded_error
> maxerrout
)
5360 maxerrout
= encoded_error
;
5362 if (encoded_error
< .5+maxout
)
5365 /* There may be an error, so calculate the actual sample
5366 * values - unencoded light intensity values. Note that
5367 * in practice these are not unencoded because they
5368 * include a 'viewing correction' to decrease or
5369 * (normally) increase the perceptual contrast of the
5370 * image. There's nothing we can do about this - we don't
5371 * know what it is - so assume the unencoded value is
5372 * perceptually linear.
5374 input_sample
= pow(i
, 1/file_gamma
); /* In range 0..1 */
5377 output
= pow(output
, screen_gamma
);
5379 /* Now we have the numbers for real errors, both absolute
5380 * values as as a percentage of the correct value (output):
5382 error
= fabs(input_sample
-output
);
5384 if (error
> maxerrabs
)
5387 /* The following is an attempt to ignore the tendency of
5388 * quantization to dominate the percentage errors for low
5389 * output sample values:
5391 if (input_sample
*maxpc
> .5+maxabs
)
5393 double percentage_error
= error
/input_sample
;
5394 if (percentage_error
> maxerrpc
) maxerrpc
= percentage_error
;
5397 /* Now calculate the digitization limits for
5398 * 'encoded_sample' using the 'max' values. Note that
5399 * maxout is in the encoded space but maxpc and maxabs are
5400 * in linear light space.
5402 * First find the maximum error in linear light space,
5406 double tmp
= input_sample
* maxpc
;
5407 if (tmp
< maxabs
) tmp
= maxabs
;
5409 /* Low bound - the minimum of the three: */
5410 es_lo
= encoded_sample
- maxout
;
5412 if (es_lo
> 0 && input_sample
-tmp
> 0)
5414 double low_value
= outmax
* pow(input_sample
-tmp
,
5416 if (low_value
< es_lo
) es_lo
= low_value
;
5422 es_hi
= encoded_sample
+ maxout
;
5424 if (es_hi
< outmax
&& input_sample
+tmp
< 1)
5426 double high_value
= outmax
* pow(input_sample
+tmp
,
5428 if (high_value
> es_hi
) es_hi
= high_value
;
5435 /* The primary test is that the final encoded value
5436 * returned by the library should be between the two limits
5437 * (inclusive) that were calculated above. At this point
5438 * quantization of the output must be taken into account.
5440 if (od
+.5 < es_lo
|| od
-.5 > es_hi
)
5442 /* There has been an error in processing. */
5443 double is_lo
, is_hi
;
5445 if (use_input_precision
)
5447 /* Ok, something is wrong - this actually happens in
5448 * current libpng sbit processing. Assume that the
5449 * input value (id, adjusted for sbit) can be
5450 * anywhere between value-.5 and value+.5 - quite a
5451 * large range if sbit is low.
5453 double tmp
= (isbit
- .5)/((1U<<sbit
)-1);
5457 is_lo
= outmax
* pow(tmp
, gamma_correction
) - maxout
;
5458 if (is_lo
< 0) is_lo
= 0;
5464 tmp
= (isbit
+ .5)/((1U<<sbit
)-1);
5468 is_hi
= outmax
* pow(tmp
, gamma_correction
) + maxout
;
5469 if (is_hi
> outmax
) is_hi
= outmax
;
5475 if (!(od
+.5 < is_lo
|| od
-.5 > is_hi
))
5479 is_lo
= es_lo
, is_hi
= es_hi
;
5485 "error: %.3f; %u{%u;%u} -> %u not %.2f (%.1f-%.1f)",
5486 od
-encoded_sample
, id
, sbit
, isbit
, od
,
5487 encoded_sample
, is_lo
, is_hi
);
5489 png_warning(pp
, msg
);
5495 else if (!speed
&& memcmp(std
, pRow
, cbRow
) != 0)
5499 /* No transform is expected on the threshold tests. */
5500 sprintf(msg
, "gamma: below threshold row %d changed", y
);
5504 } /* row (y) loop */
5506 dp
->maxerrout
= maxerrout
;
5507 dp
->maxerrabs
= maxerrabs
;
5508 dp
->maxerrpc
= maxerrpc
;
5509 dp
->this.ps
->validated
= 1;
5513 gamma_end(png_structp pp
, png_infop pi
)
5515 gamma_display
*dp
= png_get_progressive_ptr(pp
);
5517 gamma_image_validate(dp
, pp
, pi
, dp
->this.ps
->image
);
5520 /* A single test run checking a gamma transformation.
5522 * maxabs: maximum absolute error as a fraction
5523 * maxout: maximum output error in the output units
5524 * maxpc: maximum percentage error (as a percentage)
5527 gamma_test(png_modifier
*pmIn
, PNG_CONST png_byte colour_typeIn
,
5528 PNG_CONST png_byte bit_depthIn
, PNG_CONST
int interlace_typeIn
,
5529 PNG_CONST
double file_gammaIn
, PNG_CONST
double screen_gammaIn
,
5530 PNG_CONST png_byte sbitIn
, PNG_CONST
int threshold_testIn
,
5531 PNG_CONST
char *name
, PNG_CONST
int speedIn
,
5532 PNG_CONST
int use_input_precisionIn
, PNG_CONST
int strip16In
)
5535 context(&pmIn
->this, fault
);
5537 gamma_display_init(&d
, pmIn
, FILEID(colour_typeIn
, bit_depthIn
,
5538 interlace_typeIn
, 0, 0, 0), file_gammaIn
, screen_gammaIn
, sbitIn
,
5539 threshold_testIn
, speedIn
, use_input_precisionIn
, strip16In
);
5545 gamma_modification gamma_mod
;
5546 srgb_modification srgb_mod
;
5547 sbit_modification sbit_mod
;
5549 /* Make an appropriate modifier to set the PNG file gamma to the
5550 * given gamma value and the sBIT chunk to the given precision.
5552 d
.pm
->modifications
= NULL
;
5553 gamma_modification_init(&gamma_mod
, d
.pm
, d
.file_gamma
);
5554 srgb_modification_init(&srgb_mod
, d
.pm
, 127 /*delete*/);
5555 sbit_modification_init(&sbit_mod
, d
.pm
, d
.sbit
);
5557 modification_reset(d
.pm
->modifications
);
5559 /* Get a png_struct for writing the image. */
5560 pp
= set_modifier_for_read(d
.pm
, &pi
, d
.this.id
, name
);
5562 /* Set up gamma processing. */
5563 #ifdef PNG_FLOATING_POINT_SUPPORTED
5564 png_set_gamma(pp
, d
.screen_gamma
, d
.file_gamma
);
5567 png_fixed_point s
= floor(d
.screen_gamma
*100000+.5);
5568 png_fixed_point f
= floor(d
.file_gamma
*100000+.5);
5569 png_set_gamma_fixed(pp
, s
, f
);
5573 /* Introduce the correct read function. */
5574 if (d
.pm
->this.progressive
)
5576 /* Share the row function with the standard implementation. */
5577 png_set_progressive_read_fn(pp
, &d
, gamma_info
, progressive_row
,
5580 /* Now feed data into the reader until we reach the end: */
5581 modifier_progressive_read(d
.pm
, pp
, pi
);
5585 /* modifier_read expects a png_modifier* */
5586 png_set_read_fn(pp
, d
.pm
, modifier_read
);
5588 /* Check the header values: */
5589 png_read_info(pp
, pi
);
5591 /* Process the 'info' requirements. Only one image is generated */
5592 gamma_info_imp(&d
, pp
, pi
);
5594 sequential_row(&d
.this, pp
, pi
, NULL
, d
.this.ps
->image
);
5596 gamma_image_validate(&d
, pp
, pi
, d
.this.ps
->image
);
5599 modifier_reset(d
.pm
);
5601 if (d
.pm
->log
&& !d
.threshold_test
&& !d
.speed
)
5602 fprintf(stderr
, "%d bit %s %s: max error %f (%.2g, %2g%%)\n",
5603 d
.this.bit_depth
, colour_types
[d
.this.colour_type
], d
.name
,
5604 d
.maxerrout
, d
.maxerrabs
, 100*d
.maxerrpc
);
5606 /* Log the summary values too. */
5607 if (d
.this.colour_type
== 0 || d
.this.colour_type
== 4)
5609 switch (d
.this.bit_depth
)
5615 if (d
.maxerrout
> d
.pm
->error_gray_2
)
5616 d
.pm
->error_gray_2
= d
.maxerrout
;
5621 if (d
.maxerrout
> d
.pm
->error_gray_4
)
5622 d
.pm
->error_gray_4
= d
.maxerrout
;
5627 if (d
.maxerrout
> d
.pm
->error_gray_8
)
5628 d
.pm
->error_gray_8
= d
.maxerrout
;
5633 if (d
.maxerrout
> d
.pm
->error_gray_16
)
5634 d
.pm
->error_gray_16
= d
.maxerrout
;
5639 png_error(pp
, "bad bit depth (internal: 1)");
5643 else if (d
.this.colour_type
== 2 || d
.this.colour_type
== 6)
5645 switch (d
.this.bit_depth
)
5649 if (d
.maxerrout
> d
.pm
->error_color_8
)
5650 d
.pm
->error_color_8
= d
.maxerrout
;
5656 if (d
.maxerrout
> d
.pm
->error_color_16
)
5657 d
.pm
->error_color_16
= d
.maxerrout
;
5662 png_error(pp
, "bad bit depth (internal: 2)");
5668 modifier_reset((png_modifier
*)fault
);
5671 static void gamma_threshold_test(png_modifier
*pm
, png_byte colour_type
,
5672 png_byte bit_depth
, int interlace_type
, double file_gamma
,
5673 double screen_gamma
)
5677 pos
= safecat(name
, sizeof name
, pos
, "threshold ");
5678 pos
= safecatd(name
, sizeof name
, pos
, file_gamma
, 3);
5679 pos
= safecat(name
, sizeof name
, pos
, "/");
5680 pos
= safecatd(name
, sizeof name
, pos
, screen_gamma
, 3);
5682 (void)gamma_test(pm
, colour_type
, bit_depth
, interlace_type
, file_gamma
,
5683 screen_gamma
, bit_depth
, 1, name
, 0 /*speed*/, 0 /*no input precision*/,
5688 perform_gamma_threshold_tests(png_modifier
*pm
)
5690 png_byte colour_type
= 0;
5691 png_byte bit_depth
= 0;
5693 while (next_format(&colour_type
, &bit_depth
))
5695 double test_gamma
= 1.0;
5696 while (test_gamma
>= .4)
5698 /* There's little point testing the interlacing vs non-interlacing,
5699 * but this can be set from the command line.
5701 gamma_threshold_test(pm
, colour_type
, bit_depth
, pm
->interlace_type
,
5702 test_gamma
, 1/test_gamma
);
5706 /* And a special test for sRGB */
5707 gamma_threshold_test(pm
, colour_type
, bit_depth
, pm
->interlace_type
,
5715 static void gamma_transform_test(png_modifier
*pm
,
5716 PNG_CONST png_byte colour_type
, PNG_CONST png_byte bit_depth
,
5717 PNG_CONST
int interlace_type
, PNG_CONST
double file_gamma
,
5718 PNG_CONST
double screen_gamma
, PNG_CONST png_byte sbit
, PNG_CONST
int speed
,
5719 PNG_CONST
int use_input_precision
, PNG_CONST
int strip16
)
5724 if (sbit
!= bit_depth
)
5726 pos
= safecat(name
, sizeof name
, pos
, "sbit(");
5727 pos
= safecatn(name
, sizeof name
, pos
, sbit
);
5728 pos
= safecat(name
, sizeof name
, pos
, ") ");
5732 pos
= safecat(name
, sizeof name
, pos
, "gamma ");
5735 pos
= safecat(name
, sizeof name
, pos
, "16to8 ");
5737 pos
= safecatd(name
, sizeof name
, pos
, file_gamma
, 3);
5738 pos
= safecat(name
, sizeof name
, pos
, "->");
5739 pos
= safecatd(name
, sizeof name
, pos
, screen_gamma
, 3);
5741 gamma_test(pm
, colour_type
, bit_depth
, interlace_type
, file_gamma
,
5742 screen_gamma
, sbit
, 0, name
, speed
, use_input_precision
, strip16
);
5745 static void perform_gamma_transform_tests(png_modifier
*pm
, int speed
)
5747 png_byte colour_type
= 0;
5748 png_byte bit_depth
= 0;
5750 /* Ignore palette images - the gamma correction happens on the palette entry,
5751 * haven't got the tests for this yet.
5753 while (next_format(&colour_type
, &bit_depth
)) if (colour_type
!= 3)
5757 for (i
=0; i
<pm
->ngammas
; ++i
) for (j
=0; j
<pm
->ngammas
; ++j
) if (i
!= j
)
5759 gamma_transform_test(pm
, colour_type
, bit_depth
, pm
->interlace_type
,
5760 1/pm
->gammas
[i
], pm
->gammas
[j
], bit_depth
, speed
,
5761 pm
->use_input_precision
, 0 /*do not strip16*/);
5769 static void perform_gamma_sbit_tests(png_modifier
*pm
, int speed
)
5773 /* The only interesting cases are colour and grayscale, alpha is ignored here
5774 * for overall speed. Only bit depths 8 and 16 are tested.
5776 for (sbit
=pm
->sbitlow
; sbit
<(1<<READ_BDHI
); ++sbit
)
5780 for (i
=0; i
<pm
->ngammas
; ++i
)
5782 for (j
=0; j
<pm
->ngammas
; ++j
)
5788 gamma_transform_test(pm
, 0, 8, pm
->interlace_type
,
5789 1/pm
->gammas
[i
], pm
->gammas
[j
], sbit
, speed
,
5790 pm
->use_input_precision_sbit
, 0 /*strip16*/);
5795 gamma_transform_test(pm
, 2, 8, pm
->interlace_type
,
5796 1/pm
->gammas
[i
], pm
->gammas
[j
], sbit
, speed
,
5797 pm
->use_input_precision_sbit
, 0 /*strip16*/);
5804 gamma_transform_test(pm
, 0, 16, pm
->interlace_type
,
5805 1/pm
->gammas
[i
], pm
->gammas
[j
], sbit
, speed
,
5806 pm
->use_input_precision_sbit
, 0 /*strip16*/);
5811 gamma_transform_test(pm
, 2, 16, pm
->interlace_type
,
5812 1/pm
->gammas
[i
], pm
->gammas
[j
], sbit
, speed
,
5813 pm
->use_input_precision_sbit
, 0 /*strip16*/);
5824 /* Note that this requires a 16 bit source image but produces 8 bit output, so
5825 * we only need the 16bit write support.
5827 #ifdef PNG_READ_16_TO_8_SUPPORTED
5828 static void perform_gamma_strip16_tests(png_modifier
*pm
, int speed
)
5830 # ifndef PNG_MAX_GAMMA_8
5831 # define PNG_MAX_GAMMA_8 11
5833 /* Include the alpha cases here. Note that sbit matches the internal value
5834 * used by the library - otherwise we will get spurious errors from the
5835 * internal sbit style approximation.
5837 * The threshold test is here because otherwise the 16 to 8 conversion will
5838 * proceed *without* gamma correction, and the tests above will fail (but not
5839 * by much) - this could be fixed, it only appears with the -g option.
5842 for (i
=0; i
<pm
->ngammas
; ++i
)
5844 for (j
=0; j
<pm
->ngammas
; ++j
)
5847 fabs(pm
->gammas
[j
]/pm
->gammas
[i
]-1) >= PNG_GAMMA_THRESHOLD
)
5849 gamma_transform_test(pm
, 0, 16, pm
->interlace_type
, 1/pm
->gammas
[i
],
5850 pm
->gammas
[j
], PNG_MAX_GAMMA_8
, speed
,
5851 pm
->use_input_precision_16to8
, 1 /*strip16*/);
5856 gamma_transform_test(pm
, 2, 16, pm
->interlace_type
, 1/pm
->gammas
[i
],
5857 pm
->gammas
[j
], PNG_MAX_GAMMA_8
, speed
,
5858 pm
->use_input_precision_16to8
, 1 /*strip16*/);
5863 gamma_transform_test(pm
, 4, 16, pm
->interlace_type
, 1/pm
->gammas
[i
],
5864 pm
->gammas
[j
], PNG_MAX_GAMMA_8
, speed
,
5865 pm
->use_input_precision_16to8
, 1 /*strip16*/);
5870 gamma_transform_test(pm
, 6, 16, pm
->interlace_type
, 1/pm
->gammas
[i
],
5871 pm
->gammas
[j
], PNG_MAX_GAMMA_8
, speed
,
5872 pm
->use_input_precision_16to8
, 1 /*strip16*/);
5880 #endif /* 16 to 8 bit conversion */
5883 perform_gamma_test(png_modifier
*pm
, int speed
, int summary
)
5885 /* First some arbitrary no-transform tests: */
5886 if (!speed
&& pm
->test_gamma_threshold
)
5888 perform_gamma_threshold_tests(pm
);
5894 /* Now some real transforms. */
5895 if (pm
->test_gamma_transform
)
5897 perform_gamma_transform_tests(pm
, speed
);
5901 printf("Gamma correction error summary\n\n");
5902 printf("The printed value is the maximum error in the pixel values\n");
5903 printf("calculated by the libpng gamma correction code. The error\n");
5904 printf("is calculated as the difference between the output pixel\n");
5905 printf("value (always an integer) and the ideal value from the\n");
5906 printf("libpng specification (typically not an integer).\n\n");
5908 printf("Expect this value to be less than .5 for 8 bit formats,\n");
5909 printf("less than 1 for formats with fewer than 8 bits and a small\n");
5910 printf("number (typically less than 5) for the 16 bit formats.\n");
5911 printf("For performance reasons the value for 16 bit formats\n");
5912 printf("increases when the image file includes an sBIT chunk.\n\n");
5914 printf(" 2 bit gray: %.5f\n", pm
->error_gray_2
);
5915 printf(" 4 bit gray: %.5f\n", pm
->error_gray_4
);
5916 printf(" 8 bit gray: %.5f\n", pm
->error_gray_8
);
5917 printf(" 8 bit color: %.5f\n", pm
->error_color_8
);
5919 printf(" 16 bit gray: %.5f\n", pm
->error_gray_16
);
5920 printf(" 16 bit color: %.5f\n", pm
->error_color_16
);
5925 /* The sbit tests produce much larger errors: */
5926 if (pm
->test_gamma_sbit
)
5928 pm
->error_gray_2
= pm
->error_gray_4
= pm
->error_gray_8
=
5929 pm
->error_gray_16
= pm
->error_color_8
= pm
->error_color_16
= 0;
5930 perform_gamma_sbit_tests(pm
, speed
);
5934 printf("Gamma correction with sBIT:\n");
5936 if (pm
->sbitlow
< 8U)
5938 printf(" 2 bit gray: %.5f\n", pm
->error_gray_2
);
5939 printf(" 4 bit gray: %.5f\n", pm
->error_gray_4
);
5940 printf(" 8 bit gray: %.5f\n", pm
->error_gray_8
);
5941 printf(" 8 bit color: %.5f\n", pm
->error_color_8
);
5945 printf(" 16 bit gray: %.5f\n", pm
->error_gray_16
);
5946 printf(" 16 bit color: %.5f\n", pm
->error_color_16
);
5951 #ifdef PNG_READ_16_TO_8_SUPPORTED
5952 if (pm
->test_gamma_strip16
)
5954 /* The 16 to 8 bit strip operations: */
5955 pm
->error_gray_2
= pm
->error_gray_4
= pm
->error_gray_8
=
5956 pm
->error_gray_16
= pm
->error_color_8
= pm
->error_color_16
= 0;
5957 perform_gamma_strip16_tests(pm
, speed
);
5961 printf("Gamma correction with 16 to 8 bit reduction:\n");
5962 printf(" 16 bit gray: %.5f\n", pm
->error_gray_16
);
5963 printf(" 16 bit color: %.5f\n", pm
->error_color_16
);
5969 /* INTERLACE MACRO VALIDATION */
5970 /* This is copied verbatim from the specification, it is simply the pass
5971 * number in which each pixel in each 8x8 tile appears. The array must
5972 * be indexed adam7[y][x] and notice that the pass numbers are based at
5973 * 1, not 0 - the base libpng uses.
5976 png_byte adam7
[8][8] =
5978 { 1,6,4,6,2,6,4,6 },
5979 { 7,7,7,7,7,7,7,7 },
5980 { 5,6,5,6,5,6,5,6 },
5981 { 7,7,7,7,7,7,7,7 },
5982 { 3,6,4,6,3,6,4,6 },
5983 { 7,7,7,7,7,7,7,7 },
5984 { 5,6,5,6,5,6,5,6 },
5988 /* This routine validates all the interlace support macros in png.h for
5989 * a variety of valid PNG widths and heights. It uses a number of similarly
5990 * named internal routines that feed off the above array.
5993 png_pass_start_row(int pass
)
5997 for (y
=0; y
<8; ++y
) for (x
=0; x
<8; ++x
) if (adam7
[y
][x
] == pass
)
6003 png_pass_start_col(int pass
)
6007 for (x
=0; x
<8; ++x
) for (y
=0; y
<8; ++y
) if (adam7
[y
][x
] == pass
)
6013 png_pass_row_shift(int pass
)
6015 int x
, y
, base
=(-1), inc
=8;
6017 for (y
=0; y
<8; ++y
) for (x
=0; x
<8; ++x
) if (adam7
[y
][x
] == pass
)
6023 else if (inc
== y
-base
)
6026 inc
= y
-base
, base
=y
;
6027 else if (inc
!= y
-base
)
6028 return 0xff; /* error - more than one 'inc' value! */
6031 if (base
== (-1)) return 0xfe; /* error - no row in pass! */
6033 /* The shift is always 1, 2 or 3 - no pass has all the rows! */
6042 /* error - unrecognized 'inc' */
6043 return (inc
<< 8) + 0xfd;
6047 png_pass_col_shift(int pass
)
6049 int x
, y
, base
=(-1), inc
=8;
6051 for (x
=0; x
<8; ++x
) for (y
=0; y
<8; ++y
) if (adam7
[y
][x
] == pass
)
6057 else if (inc
== x
-base
)
6060 inc
= x
-base
, base
=x
;
6061 else if (inc
!= x
-base
)
6062 return 0xff; /* error - more than one 'inc' value! */
6065 if (base
== (-1)) return 0xfe; /* error - no row in pass! */
6067 /* The shift is always 1, 2 or 3 - no pass has all the rows! */
6070 case 1: return 0; /* pass 7 has all the columns */
6077 /* error - unrecognized 'inc' */
6078 return (inc
<< 8) + 0xfd;
6082 png_row_from_pass_row(png_uint_32 yIn
, int pass
)
6084 /* By examination of the array: */
6087 case 0: return yIn
* 8;
6088 case 1: return yIn
* 8;
6089 case 2: return yIn
* 8 + 4;
6090 case 3: return yIn
* 4;
6091 case 4: return yIn
* 4 + 2;
6092 case 5: return yIn
* 2;
6093 case 6: return yIn
* 2 + 1;
6097 return 0xff; /* bad pass number */
6101 png_col_from_pass_col(png_uint_32 xIn
, int pass
)
6103 /* By examination of the array: */
6106 case 0: return xIn
* 8;
6107 case 1: return xIn
* 8 + 4;
6108 case 2: return xIn
* 4;
6109 case 3: return xIn
* 4 + 2;
6110 case 4: return xIn
* 2;
6111 case 5: return xIn
* 2 + 1;
6116 return 0xff; /* bad pass number */
6120 png_row_in_interlace_pass(png_uint_32 y
, int pass
)
6122 /* Is row 'y' in pass 'pass'? */
6126 for (x
=0; x
<8; ++x
) if (adam7
[y
][x
] == pass
)
6133 png_col_in_interlace_pass(png_uint_32 x
, int pass
)
6135 /* Is column 'x' in pass 'pass'? */
6139 for (y
=0; y
<8; ++y
) if (adam7
[y
][x
] == pass
)
6146 png_pass_rows(png_uint_32 height
, int pass
)
6148 png_uint_32 tiles
= height
>>3;
6149 png_uint_32 rows
= 0;
6154 for (y
=0; y
<8; ++y
) for (x
=0; x
<8; ++x
) if (adam7
[y
][x
] == pass
)
6157 if (y
< height
) ++rows
;
6158 break; /* i.e. break the 'x', column, loop. */
6165 png_pass_cols(png_uint_32 width
, int pass
)
6167 png_uint_32 tiles
= width
>>3;
6168 png_uint_32 cols
= 0;
6173 for (x
=0; x
<8; ++x
) for (y
=0; y
<8; ++y
) if (adam7
[y
][x
] == pass
)
6176 if (x
< width
) ++cols
;
6177 break; /* i.e. break the 'y', row, loop. */
6184 perform_interlace_macro_validation(void)
6186 /* The macros to validate, first those that depend only on pass:
6188 * PNG_PASS_START_ROW(pass)
6189 * PNG_PASS_START_COL(pass)
6190 * PNG_PASS_ROW_SHIFT(pass)
6191 * PNG_PASS_COL_SHIFT(pass)
6195 for (pass
=0; pass
<7; ++pass
)
6197 png_uint_32 m
, f
, v
;
6199 m
= PNG_PASS_START_ROW(pass
);
6200 f
= png_pass_start_row(pass
);
6203 fprintf(stderr
, "PNG_PASS_START_ROW(%d) = %u != %x\n", pass
, m
, f
);
6207 m
= PNG_PASS_START_COL(pass
);
6208 f
= png_pass_start_col(pass
);
6211 fprintf(stderr
, "PNG_PASS_START_COL(%d) = %u != %x\n", pass
, m
, f
);
6215 m
= PNG_PASS_ROW_SHIFT(pass
);
6216 f
= png_pass_row_shift(pass
);
6219 fprintf(stderr
, "PNG_PASS_ROW_SHIFT(%d) = %u != %x\n", pass
, m
, f
);
6223 m
= PNG_PASS_COL_SHIFT(pass
);
6224 f
= png_pass_col_shift(pass
);
6227 fprintf(stderr
, "PNG_PASS_COL_SHIFT(%d) = %u != %x\n", pass
, m
, f
);
6231 /* Macros that depend on the image or sub-image height too:
6233 * PNG_PASS_ROWS(height, pass)
6234 * PNG_PASS_COLS(width, pass)
6235 * PNG_ROW_FROM_PASS_ROW(yIn, pass)
6236 * PNG_COL_FROM_PASS_COL(xIn, pass)
6237 * PNG_ROW_IN_INTERLACE_PASS(y, pass)
6238 * PNG_COL_IN_INTERLACE_PASS(x, pass)
6242 /* First the base 0 stuff: */
6243 m
= PNG_ROW_FROM_PASS_ROW(v
, pass
);
6244 f
= png_row_from_pass_row(v
, pass
);
6247 fprintf(stderr
, "PNG_ROW_FROM_PASS_ROW(%u, %d) = %u != %x\n",
6252 m
= PNG_COL_FROM_PASS_COL(v
, pass
);
6253 f
= png_col_from_pass_col(v
, pass
);
6256 fprintf(stderr
, "PNG_COL_FROM_PASS_COL(%u, %d) = %u != %x\n",
6261 m
= PNG_ROW_IN_INTERLACE_PASS(v
, pass
);
6262 f
= png_row_in_interlace_pass(v
, pass
);
6265 fprintf(stderr
, "PNG_ROW_IN_INTERLACE_PASS(%u, %d) = %u != %x\n",
6270 m
= PNG_COL_IN_INTERLACE_PASS(v
, pass
);
6271 f
= png_col_in_interlace_pass(v
, pass
);
6274 fprintf(stderr
, "PNG_COL_IN_INTERLACE_PASS(%u, %d) = %u != %x\n",
6279 /* Then the base 1 stuff: */
6281 m
= PNG_PASS_ROWS(v
, pass
);
6282 f
= png_pass_rows(v
, pass
);
6285 fprintf(stderr
, "PNG_PASS_ROWS(%u, %d) = %u != %x\n",
6290 m
= PNG_PASS_COLS(v
, pass
);
6291 f
= png_pass_cols(v
, pass
);
6294 fprintf(stderr
, "PNG_PASS_COLS(%u, %d) = %u != %x\n",
6299 /* Move to the next v - the stepping algorithm starts skipping
6300 * values above 1024.
6304 if (v
== PNG_UINT_31_MAX
)
6308 if (v
>= PNG_UINT_31_MAX
)
6309 v
= PNG_UINT_31_MAX
-1;
6316 int main(int argc
, PNG_CONST
char **argv
)
6318 volatile int summary
= 1; /* Print the error summary at the end */
6320 /* Create the given output file on success: */
6321 PNG_CONST
char *volatile touch
= NULL
;
6323 /* This is an array of standard gamma values (believe it or not I've seen
6324 * every one of these mentioned somewhere.)
6326 * In the following list the most useful values are first!
6329 gammas
[]={2.2, 1.0, 2.2/1.45, 1.8, 1.5, 2.4, 2.5, 2.62, 2.9};
6332 context(&pm
.this, fault
);
6336 /* Preallocate the image buffer, because we know how big it needs to be,
6337 * note that, for testing purposes, it is deliberately mis-aligned.
6339 pm
.this.image
= malloc(2*TRANSFORM_IMAGEMAX
+1);
6341 if (pm
.this.image
!= NULL
)
6343 /* Ignore OOM at this point - the 'ensure' routine above will allocate
6344 * the array appropriately.
6347 pm
.this.cb_image
= 2*TRANSFORM_IMAGEMAX
;
6350 /* Default to error on warning: */
6351 pm
.this.treat_warnings_as_errors
= 1;
6353 /* Store the test gammas */
6355 pm
.ngammas
= 0; /* default to off */
6356 pm
.sbitlow
= 8U; /* because libpng doesn't do sBIT below 8! */
6357 pm
.use_input_precision_16to8
= 1U; /* Because of the way libpng does it */
6359 /* Some default values (set the behavior for 'make check' here).
6360 * These values simply control the maximum error permitted in the gamma
6361 * transformations. The practial limits for human perception are described
6362 * below (the setting for maxpc16), however for 8 bit encodings it isn't
6363 * possible to meet the accepted capabilities of human vision - i.e. 8 bit
6364 * images can never be good enough, regardless of encoding.
6366 pm
.maxout8
= .1; /* Arithmetic error in *encoded* value */
6367 pm
.maxabs8
= .00005; /* 1/20000 */
6368 pm
.maxpc8
= .499; /* I.e., .499% fractional error */
6369 pm
.maxout16
= .499; /* Error in *encoded* value */
6370 pm
.maxabs16
= .00005;/* 1/20000 */
6372 /* NOTE: this is a reasonable perceptual limit. We assume that humans can
6373 * perceive light level differences of 1% over a 100:1 range, so we need to
6374 * maintain 1 in 10000 accuracy (in linear light space), which is what the
6375 * following guarantees. It also allows significantly higher errors at
6376 * higher 16 bit values, which is important for performance. The actual
6377 * maximum 16 bit error is about +/-1.9 in the fixed point implementation but
6378 * this is only allowed for values >38149 by the following:
6380 pm
.maxpc16
= .005; /* I.e., 1/200% - 1/20000 */
6382 /* Now parse the command line options. */
6385 if (strcmp(*++argv
, "-v") == 0)
6386 pm
.this.verbose
= 1;
6388 else if (strcmp(*argv
, "-l") == 0)
6391 else if (strcmp(*argv
, "-q") == 0)
6392 summary
= pm
.this.verbose
= pm
.log
= 0;
6394 else if (strcmp(*argv
, "-w") == 0)
6395 pm
.this.treat_warnings_as_errors
= 0;
6397 else if (strcmp(*argv
, "--speed") == 0)
6398 pm
.this.speed
= 1, pm
.ngammas
= (sizeof gammas
)/(sizeof gammas
[0]),
6399 pm
.test_standard
= 0;
6401 else if (strcmp(*argv
, "--size") == 0)
6404 else if (strcmp(*argv
, "--nosize") == 0)
6407 else if (strcmp(*argv
, "--standard") == 0)
6408 pm
.test_standard
= 1;
6410 else if (strcmp(*argv
, "--nostandard") == 0)
6411 pm
.test_standard
= 0;
6413 else if (strcmp(*argv
, "--transform") == 0)
6414 pm
.test_transform
= 1;
6416 else if (strcmp(*argv
, "--notransform") == 0)
6417 pm
.test_transform
= 0;
6419 else if (strncmp(*argv
, "--transform-disable=",
6420 sizeof "--transform-disable") == 0)
6422 pm
.test_transform
= 1;
6423 transform_disable(*argv
+ sizeof "--transform-disable");
6426 else if (strncmp(*argv
, "--transform-enable=",
6427 sizeof "--transform-enable") == 0)
6429 pm
.test_transform
= 1;
6430 transform_enable(*argv
+ sizeof "--transform-enable");
6433 else if (strcmp(*argv
, "--gamma") == 0)
6435 /* Just do two gamma tests here (2.2 and linear) for speed: */
6437 pm
.test_gamma_threshold
= 1;
6438 pm
.test_gamma_transform
= 1;
6439 pm
.test_gamma_sbit
= 1;
6440 pm
.test_gamma_strip16
= 1;
6443 else if (strcmp(*argv
, "--nogamma") == 0)
6446 else if (strcmp(*argv
, "--gamma-threshold") == 0)
6447 pm
.ngammas
= 2U, pm
.test_gamma_threshold
= 1;
6449 else if (strcmp(*argv
, "--nogamma-threshold") == 0)
6450 pm
.test_gamma_threshold
= 0;
6452 else if (strcmp(*argv
, "--gamma-transform") == 0)
6453 pm
.ngammas
= 2U, pm
.test_gamma_transform
= 1;
6455 else if (strcmp(*argv
, "--nogamma-transform") == 0)
6456 pm
.test_gamma_transform
= 0;
6458 else if (strcmp(*argv
, "--gamma-sbit") == 0)
6459 pm
.ngammas
= 2U, pm
.test_gamma_sbit
= 1;
6461 else if (strcmp(*argv
, "--nogamma-sbit") == 0)
6462 pm
.test_gamma_sbit
= 0;
6464 else if (strcmp(*argv
, "--gamma-16-to-8") == 0)
6465 pm
.ngammas
= 2U, pm
.test_gamma_strip16
= 1;
6467 else if (strcmp(*argv
, "--nogamma-16-to-8") == 0)
6468 pm
.test_gamma_strip16
= 0;
6470 else if (strcmp(*argv
, "--all-gammas") == 0)
6471 pm
.ngammas
= (sizeof gammas
)/(sizeof gammas
[0]);
6473 else if (strcmp(*argv
, "--progressive-read") == 0)
6474 pm
.this.progressive
= 1;
6476 else if (strcmp(*argv
, "--interlace") == 0)
6477 pm
.interlace_type
= PNG_INTERLACE_ADAM7
;
6479 else if (argc
>= 1 && strcmp(*argv
, "--sbitlow") == 0)
6480 --argc
, pm
.sbitlow
= (png_byte
)atoi(*++argv
);
6482 else if (argc
>= 1 && strcmp(*argv
, "--touch") == 0)
6483 --argc
, touch
= *++argv
;
6485 else if (argc
>= 1 && strncmp(*argv
, "--max", 4) == 0)
6489 if (strcmp(4+*argv
, "abs8") == 0)
6490 pm
.maxabs8
= atof(*++argv
);
6492 else if (strcmp(4+*argv
, "abs16") == 0)
6493 pm
.maxabs16
= atof(*++argv
);
6495 else if (strcmp(4+*argv
, "out8") == 0)
6496 pm
.maxout8
= atof(*++argv
);
6498 else if (strcmp(4+*argv
, "out16") == 0)
6499 pm
.maxout16
= atof(*++argv
);
6501 else if (strcmp(4+*argv
, "pc8") == 0)
6502 pm
.maxpc8
= atof(*++argv
);
6504 else if (strcmp(4+*argv
, "pc16") == 0)
6505 pm
.maxpc16
= atof(*++argv
);
6509 fprintf(stderr
, "pngvalid: %s: unknown 'max' option\n", *argv
);
6516 fprintf(stderr
, "pngvalid: %s: unknown argument\n", *argv
);
6521 /* If pngvalid is run with no arguments default to a reasonable set of the
6524 if (pm
.test_standard
== 0 && pm
.test_size
== 0 && pm
.test_transform
== 0 &&
6527 pm
.test_standard
= 1;
6529 pm
.test_transform
= 1;
6533 if (pm
.ngammas
> 0 &&
6534 pm
.test_gamma_threshold
== 0 && pm
.test_gamma_transform
== 0 &&
6535 pm
.test_gamma_sbit
== 0 && pm
.test_gamma_strip16
== 0)
6537 pm
.test_gamma_threshold
= 1;
6538 pm
.test_gamma_transform
= 1;
6539 pm
.test_gamma_sbit
= 1;
6540 pm
.test_gamma_strip16
= 1;
6543 else if (pm
.ngammas
== 0)
6545 /* Nothing to test so turn everything off: */
6546 pm
.test_gamma_threshold
= 0;
6547 pm
.test_gamma_transform
= 0;
6548 pm
.test_gamma_sbit
= 0;
6549 pm
.test_gamma_strip16
= 0;
6554 /* Make useful base images */
6555 make_transform_images(&pm
.this);
6557 /* Perform the standard and gamma tests. */
6558 if (pm
.test_standard
)
6560 perform_interlace_macro_validation();
6561 perform_standard_test(&pm
);
6562 perform_error_test(&pm
);
6565 /* Various oddly sized images: */
6568 make_size_images(&pm
.this);
6569 perform_size_test(&pm
);
6572 /* Combinatorial transforms: */
6573 if (pm
.test_transform
)
6574 perform_transform_test(&pm
);
6577 perform_gamma_test(&pm
, pm
.this.speed
!= 0,
6578 summary
&& !pm
.this.speed
);
6583 fprintf(stderr
, "pngvalid: test aborted (probably failed in cleanup)\n");
6584 if (!pm
.this.verbose
)
6586 if (pm
.this.error
[0] != 0)
6587 fprintf(stderr
, "pngvalid: first error: %s\n", pm
.this.error
);
6589 fprintf(stderr
, "pngvalid: run with -v to see what happened\n");
6594 if (summary
&& !pm
.this.speed
)
6596 printf("Results using %s point arithmetic %s\n",
6597 #if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || PNG_LIBPNG_VER < 10500
6602 (pm
.this.nerrors
|| (pm
.this.treat_warnings_as_errors
&&
6603 pm
.this.nwarnings
)) ? "(errors)" : (pm
.this.nwarnings
?
6604 "(warnings)" : "(no errors or warnings)")
6606 printf("Allocated memory statistics (in bytes):\n"
6607 "\tread %lu maximum single, %lu peak, %lu total\n"
6608 "\twrite %lu maximum single, %lu peak, %lu total\n",
6609 (unsigned long)pm
.this.read_memory_pool
.max_max
,
6610 (unsigned long)pm
.this.read_memory_pool
.max_limit
,
6611 (unsigned long)pm
.this.read_memory_pool
.max_total
,
6612 (unsigned long)pm
.this.write_memory_pool
.max_max
,
6613 (unsigned long)pm
.this.write_memory_pool
.max_limit
,
6614 (unsigned long)pm
.this.write_memory_pool
.max_total
);
6617 /* Do this here to provoke memory corruption errors in memory not directly
6618 * allocated by libpng - not a complete test, but better than nothing.
6620 store_delete(&pm
.this);
6622 /* Error exit if there are any errors, and maybe if there are any
6625 if (pm
.this.nerrors
|| (pm
.this.treat_warnings_as_errors
&&
6628 if (!pm
.this.verbose
)
6629 fprintf(stderr
, "pngvalid: %s\n", pm
.this.error
);
6631 fprintf(stderr
, "pngvalid: %d errors, %d warnings\n", pm
.this.nerrors
,
6640 FILE *fsuccess
= fopen(touch
, "wt");
6642 if (fsuccess
!= NULL
)
6645 fprintf(fsuccess
, "PNG validation succeeded\n");
6647 error
= ferror(fsuccess
);
6649 if (fclose(fsuccess
) || error
)
6651 fprintf(stderr
, "%s: write failed\n", touch
);