2 /* pngvalid.c - validate libpng by constructing then reading png files.
4 * Last changed in libpng 1.5.6 [November 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.
22 #define _POSIX_SOURCE 1
25 #if PNG_LIBPNG_VER < 10500
26 /* This delibarately lacks the PNG_CONST. */
27 typedef png_byte
*png_const_bytep
;
29 /* This is copied from 1.5.1 png.h: */
30 #define PNG_INTERLACE_ADAM7_PASSES 7
31 #define PNG_PASS_START_ROW(pass) (((1U&~(pass))<<(3-((pass)>>1)))&7)
32 #define PNG_PASS_START_COL(pass) (((1U& (pass))<<(3-(((pass)+1)>>1)))&7)
33 #define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3)
34 #define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3)
35 #define PNG_PASS_ROWS(height, pass) (((height)+(((1<<PNG_PASS_ROW_SHIFT(pass))\
36 -1)-PNG_PASS_START_ROW(pass)))>>PNG_PASS_ROW_SHIFT(pass))
37 #define PNG_PASS_COLS(width, pass) (((width)+(((1<<PNG_PASS_COL_SHIFT(pass))\
38 -1)-PNG_PASS_START_COL(pass)))>>PNG_PASS_COL_SHIFT(pass))
39 #define PNG_ROW_FROM_PASS_ROW(yIn, pass) \
40 (((yIn)<<PNG_PASS_ROW_SHIFT(pass))+PNG_PASS_START_ROW(pass))
41 #define PNG_COL_FROM_PASS_COL(xIn, pass) \
42 (((xIn)<<PNG_PASS_COL_SHIFT(pass))+PNG_PASS_START_COL(pass))
43 #define PNG_PASS_MASK(pass,off) ( \
44 ((0x110145AFU>>(((7-(off))-(pass))<<2)) & 0xFU) | \
45 ((0x01145AF0U>>(((7-(off))-(pass))<<2)) & 0xF0U))
46 #define PNG_ROW_IN_INTERLACE_PASS(y, pass) \
47 ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1)
48 #define PNG_COL_IN_INTERLACE_PASS(x, pass) \
49 ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1)
51 /* These are needed too for the default build: */
52 #define PNG_WRITE_16BIT_SUPPORTED
53 #define PNG_READ_16BIT_SUPPORTED
55 /* This comes from pnglibconf.h afer 1.5: */
56 #define PNG_FP_1 100000
57 #define PNG_GAMMA_THRESHOLD_FIXED\
58 ((png_fixed_point)(PNG_GAMMA_THRESHOLD * PNG_FP_1))
61 #include "zlib.h" /* For crc32 */
63 #include <float.h> /* For floating point constants */
64 #include <stdlib.h> /* For malloc */
65 #include <string.h> /* For memcpy, memset */
66 #include <math.h> /* For floor */
68 /* Unused formal parameter errors are removed using the following macro which is
69 * expected to have no bad effects on performance.
72 # if defined(__GNUC__) || defined(_MSC_VER)
73 # define UNUSED(param) (void)param;
75 # define UNUSED(param)
79 /***************************** EXCEPTION HANDLING *****************************/
80 #include "contrib/visupng/cexcept.h"
83 # define this not_the_cpp_this
84 # define new not_the_cpp_new
85 # define voidcast(type, value) static_cast<type>(value)
87 # define voidcast(type, value) (value)
88 #endif /* __cplusplus */
91 define_exception_type(struct png_store
*);
93 /* The following are macros to reduce typing everywhere where the well known
94 * name 'the_exception_context' must be defined.
96 #define anon_context(ps) struct exception_context *the_exception_context = \
97 &(ps)->exception_context
98 #define context(ps,fault) anon_context(ps); png_store *fault
100 /******************************* UTILITIES ************************************/
101 /* Error handling is particularly problematic in production code - error
102 * handlers often themselves have bugs which lead to programs that detect
103 * minor errors crashing. The following functions deal with one very
104 * common class of errors in error handlers - attempting to format error or
105 * warning messages into buffers that are too small.
107 static size_t safecat(char *buffer
, size_t bufsize
, size_t pos
,
110 while (pos
< bufsize
&& cat
!= NULL
&& *cat
!= 0)
111 buffer
[pos
++] = *cat
++;
120 static size_t safecatn(char *buffer
, size_t bufsize
, size_t pos
, int n
)
123 sprintf(number
, "%d", n
);
124 return safecat(buffer
, bufsize
, pos
, number
);
127 #ifdef PNG_READ_TRANSFORMS_SUPPORTED
128 static size_t safecatd(char *buffer
, size_t bufsize
, size_t pos
, double d
,
132 sprintf(number
, "%.*f", precision
, d
);
133 return safecat(buffer
, bufsize
, pos
, number
);
137 static PNG_CONST
char invalid
[] = "invalid";
138 static PNG_CONST
char sep
[] = ": ";
140 static PNG_CONST
char *colour_types
[8] =
142 "grayscale", invalid
, "truecolour", "indexed-colour",
143 "grayscale with alpha", invalid
, "truecolour with alpha", invalid
146 /* Convert a double precision value to fixed point. */
147 static png_fixed_point
150 d
= floor(d
* PNG_FP_1
+ .5);
151 return (png_fixed_point
)d
;
154 /* Generate random bytes. This uses a boring repeatable algorithm and it
155 * is implemented here so that it gives the same set of numbers on every
156 * architecture. It's a linear congruential generator (Knuth or Sedgewick
157 * "Algorithms") but it comes from the 'feedback taps' table in Horowitz and
158 * Hill, "The Art of Electronics".
161 make_random_bytes(png_uint_32
* seed
, void* pv
, size_t size
)
163 png_uint_32 u0
= seed
[0], u1
= seed
[1];
164 png_bytep bytes
= voidcast(png_bytep
, pv
);
166 /* There are thirty three bits, the next bit in the sequence is bit-33 XOR
167 * bit-20. The top 1 bit is in u1, the bottom 32 are in u0.
170 for (i
=0; i
<size
; ++i
)
172 /* First generate 8 new bits then shift them in at the end. */
173 png_uint_32 u
= ((u0
>> (20-8)) ^ ((u1
<< 7) | (u0
>> (32-7)))) & 0xff;
178 *bytes
++ = (png_byte
)u
;
186 make_four_random_bytes(png_uint_32
* seed
, png_bytep bytes
)
188 make_random_bytes(seed
, bytes
, 4);
192 randomize(void *pv
, size_t size
)
194 static png_uint_32 random_seed
[2] = {0x56789abc, 0xd};
195 make_random_bytes(random_seed
, pv
, size
);
198 #define RANDOMIZE(this) randomize(&(this), sizeof (this))
201 random_mod(unsigned int max
)
207 return x
% max
; /* 0 .. max-1 */
220 /* A numeric ID based on PNG file characteristics. The 'do_interlace' field
221 * simply records whether pngvalid did the interlace itself or whether it
222 * was done by libpng. Width and height must be less than 256. 'palette' is an
223 * index of the palette to use for formats with a palette (0 otherwise.)
225 #define FILEID(col, depth, palette, interlace, width, height, do_interlace) \
226 ((png_uint_32)((col) + ((depth)<<3) + ((palette)<<8) + ((interlace)<<13) + \
227 (((do_interlace)!=0)<<15) + ((width)<<16) + ((height)<<24)))
229 #define COL_FROM_ID(id) ((png_byte)((id)& 0x7U))
230 #define DEPTH_FROM_ID(id) ((png_byte)(((id) >> 3) & 0x1fU))
231 #define PALETTE_FROM_ID(id) ((int)(((id) >> 8) & 0x1f))
232 #define INTERLACE_FROM_ID(id) ((int)(((id) >> 13) & 0x3))
233 #define DO_INTERLACE_FROM_ID(id) ((int)(((id)>>15) & 1))
234 #define WIDTH_FROM_ID(id) (((id)>>16) & 0xff)
235 #define HEIGHT_FROM_ID(id) (((id)>>24) & 0xff)
237 /* Utility to construct a standard name for a standard image. */
239 standard_name(char *buffer
, size_t bufsize
, size_t pos
, png_byte colour_type
,
240 int bit_depth
, int npalette
, int interlace_type
,
241 png_uint_32 w
, png_uint_32 h
, int do_interlace
)
243 pos
= safecat(buffer
, bufsize
, pos
, colour_types
[colour_type
]);
246 pos
= safecat(buffer
, bufsize
, pos
, "[");
247 pos
= safecatn(buffer
, bufsize
, pos
, npalette
);
248 pos
= safecat(buffer
, bufsize
, pos
, "]");
250 pos
= safecat(buffer
, bufsize
, pos
, " ");
251 pos
= safecatn(buffer
, bufsize
, pos
, bit_depth
);
252 pos
= safecat(buffer
, bufsize
, pos
, " bit");
254 if (interlace_type
!= PNG_INTERLACE_NONE
)
256 pos
= safecat(buffer
, bufsize
, pos
, " interlaced");
258 pos
= safecat(buffer
, bufsize
, pos
, "(pngvalid)");
260 pos
= safecat(buffer
, bufsize
, pos
, "(libpng)");
265 pos
= safecat(buffer
, bufsize
, pos
, " ");
266 pos
= safecatn(buffer
, bufsize
, pos
, w
);
267 pos
= safecat(buffer
, bufsize
, pos
, "x");
268 pos
= safecatn(buffer
, bufsize
, pos
, h
);
275 standard_name_from_id(char *buffer
, size_t bufsize
, size_t pos
, png_uint_32 id
)
277 return standard_name(buffer
, bufsize
, pos
, COL_FROM_ID(id
),
278 DEPTH_FROM_ID(id
), PALETTE_FROM_ID(id
), INTERLACE_FROM_ID(id
),
279 WIDTH_FROM_ID(id
), HEIGHT_FROM_ID(id
), DO_INTERLACE_FROM_ID(id
));
282 /* Convenience API and defines to list valid formats. Note that 16 bit read and
283 * write support is required to do 16 bit read tests (we must be able to make a
284 * 16 bit image to test!)
286 #ifdef PNG_WRITE_16BIT_SUPPORTED
287 # define WRITE_BDHI 4
288 # ifdef PNG_READ_16BIT_SUPPORTED
293 # define WRITE_BDHI 3
299 /* The following defines the number of different palettes to generate for
300 * each log bit depth of a colour type 3 standard image.
302 #define PALETTE_COUNT(bit_depth) ((bit_depth) > 4 ? 1 : 16)
305 next_format(png_bytep colour_type
, png_bytep bit_depth
, int* palette_number
)
309 *colour_type
= 0, *bit_depth
= 1, *palette_number
= 0;
313 if (*colour_type
== 3)
315 /* Add multiple palettes for colour type 3. */
316 if (++*palette_number
< PALETTE_COUNT(*bit_depth
))
322 *bit_depth
= (png_byte
)(*bit_depth
<< 1);
324 /* Palette images are restricted to 8 bit depth */
327 || (*colour_type
!= 3 && *bit_depth
<= 16)
332 /* Move to the next color type, or return 0 at the end. */
333 switch (*colour_type
)
360 #ifdef PNG_READ_TRANSFORMS_SUPPORTED
362 sample(png_const_bytep row
, png_byte colour_type
, png_byte bit_depth
,
363 png_uint_32 x
, unsigned int sample_index
)
365 png_uint_32 bit_index
, result
;
367 /* Find a sample index for the desired sample: */
371 if ((colour_type
& 1) == 0) /* !palette */
377 bit_index
+= x
; /* Alpha channel */
379 /* Multiple channels; select one: */
380 if (colour_type
& (2+4))
381 bit_index
+= sample_index
* bit_depth
;
384 /* Return the sample from the row as an integer. */
385 row
+= bit_index
>> 3;
391 else if (bit_depth
> 8)
392 return (result
<< 8) + *++row
;
394 /* Less than 8 bits per sample. */
396 return (result
>> (8-bit_index
-bit_depth
)) & ((1U<<bit_depth
)-1);
398 #endif /* PNG_READ_TRANSFORMS_SUPPORTED */
400 /* Copy a single pixel, of a given size, from one buffer to another -
401 * while this is basically bit addressed there is an implicit assumption
402 * that pixels 8 or more bits in size are byte aligned and that pixels
403 * do not otherwise cross byte boundaries. (This is, so far as I know,
404 * universally true in bitmap computer graphics. [JCB 20101212])
406 * NOTE: The to and from buffers may be the same.
409 pixel_copy(png_bytep toBuffer
, png_uint_32 toIndex
,
410 png_const_bytep fromBuffer
, png_uint_32 fromIndex
, unsigned int pixelSize
)
412 /* Assume we can multiply by 'size' without overflow because we are
413 * just working in a single buffer.
415 toIndex
*= pixelSize
;
416 fromIndex
*= pixelSize
;
417 if (pixelSize
< 8) /* Sub-byte */
419 /* Mask to select the location of the copied pixel: */
420 unsigned int destMask
= ((1U<<pixelSize
)-1) << (8-pixelSize
-(toIndex
&7));
421 /* The following read the entire pixels and clears the extra: */
422 unsigned int destByte
= toBuffer
[toIndex
>> 3] & ~destMask
;
423 unsigned int sourceByte
= fromBuffer
[fromIndex
>> 3];
425 /* Don't rely on << or >> supporting '0' here, just in case: */
427 if (fromIndex
> 0) sourceByte
<<= fromIndex
;
428 if ((toIndex
& 7) > 0) sourceByte
>>= toIndex
& 7;
430 toBuffer
[toIndex
>> 3] = (png_byte
)(destByte
| (sourceByte
& destMask
));
432 else /* One or more bytes */
433 memmove(toBuffer
+(toIndex
>>3), fromBuffer
+(fromIndex
>>3), pixelSize
>>3);
436 /* Copy a complete row of pixels, taking into account potential partial
440 row_copy(png_bytep toBuffer
, png_const_bytep fromBuffer
, unsigned int bitWidth
)
442 memcpy(toBuffer
, fromBuffer
, bitWidth
>> 3);
444 if ((bitWidth
& 7) != 0)
448 toBuffer
+= bitWidth
>> 3;
449 fromBuffer
+= bitWidth
>> 3;
450 /* The remaining bits are in the top of the byte, the mask is the bits to
453 mask
= 0xff >> (bitWidth
& 7);
454 *toBuffer
= (png_byte
)((*toBuffer
& mask
) | (*fromBuffer
& ~mask
));
458 /* Compare pixels - they are assumed to start at the first byte in the
462 pixel_cmp(png_const_bytep pa
, png_const_bytep pb
, png_uint_32 bit_width
)
464 #if PNG_LIBPNG_VER < 10506
465 if (memcmp(pa
, pb
, bit_width
>>3) == 0)
469 if ((bit_width
& 7) == 0) return 0;
471 /* Ok, any differences? */
472 p
= pa
[bit_width
>> 3];
473 p
^= pb
[bit_width
>> 3];
475 if (p
== 0) return 0;
477 /* There are, but they may not be significant, remove the bits
478 * after the end (the low order bits in PNG.)
483 if (p
== 0) return 0;
486 /* From libpng-1.5.6 the overwrite should be fixed, so compare the trailing
489 if (memcmp(pa
, pb
, (bit_width
+7)>>3) == 0)
493 /* Return the index of the changed byte. */
495 png_uint_32 where
= 0;
497 while (pa
[where
] == pb
[where
]) ++where
;
502 /*************************** BASIC PNG FILE WRITING ***************************/
503 /* A png_store takes data from the sequential writer or provides data
504 * to the sequential reader. It can also store the result of a PNG
505 * write for later retrieval.
507 #define STORE_BUFFER_SIZE 500 /* arbitrary */
508 typedef struct png_store_buffer
510 struct png_store_buffer
* prev
; /* NOTE: stored in reverse order */
511 png_byte buffer
[STORE_BUFFER_SIZE
];
514 #define FILE_NAME_SIZE 64
516 typedef struct store_palette_entry
/* record of a single palette entry */
522 } store_palette_entry
, store_palette
[256];
524 typedef struct png_store_file
526 struct png_store_file
* next
; /* as many as you like... */
527 char name
[FILE_NAME_SIZE
];
528 png_uint_32 id
; /* must be correct (see FILEID) */
529 png_size_t datacount
; /* In this (the last) buffer */
530 png_store_buffer data
; /* Last buffer in file */
531 int npalette
; /* Number of entries in palette */
532 store_palette_entry
* palette
; /* May be NULL */
535 /* The following is a pool of memory allocated by a single libpng read or write
538 typedef struct store_pool
540 struct png_store
*store
; /* Back pointer */
541 struct store_memory
*list
; /* List of allocated memory */
542 png_byte mark
[4]; /* Before and after data */
544 /* Statistics for this run. */
545 png_alloc_size_t max
; /* Maximum single allocation */
546 png_alloc_size_t current
; /* Current allocation */
547 png_alloc_size_t limit
; /* Highest current allocation */
548 png_alloc_size_t total
; /* Total allocation */
550 /* Overall statistics (retained across successive runs). */
551 png_alloc_size_t max_max
;
552 png_alloc_size_t max_limit
;
553 png_alloc_size_t max_total
;
556 typedef struct png_store
558 /* For cexcept.h exception handling - simply store one of these;
559 * the context is a self pointer but it may point to a different
560 * png_store (in fact it never does in this program.)
562 struct exception_context
565 unsigned int verbose
:1;
566 unsigned int treat_warnings_as_errors
:1;
567 unsigned int expect_error
:1;
568 unsigned int expect_warning
:1;
569 unsigned int saw_warning
:1;
570 unsigned int speed
:1;
571 unsigned int progressive
:1; /* use progressive read */
572 unsigned int validated
:1; /* used as a temporary flag */
575 char test
[128]; /* Name of test */
579 png_structp pread
; /* Used to read a saved file */
581 png_store_file
* current
; /* Set when reading */
582 png_store_buffer
* next
; /* Set when reading */
583 png_size_t readpos
; /* Position in *next */
584 png_byte
* image
; /* Buffer for reading interlaced images */
585 png_size_t cb_image
; /* Size of this buffer */
586 png_size_t cb_row
; /* Row size of the image(s) */
587 png_uint_32 image_h
; /* Number of rows in a single image */
588 store_pool read_memory_pool
;
591 png_store_file
* saved
;
592 png_structp pwrite
; /* Used when writing a new file */
594 png_size_t writepos
; /* Position in .new */
595 char wname
[FILE_NAME_SIZE
];
596 png_store_buffer
new; /* The end of the new PNG file being written. */
597 store_pool write_memory_pool
;
598 store_palette_entry
* palette
;
602 /* Initialization and cleanup */
604 store_pool_mark(png_bytep mark
)
606 static png_uint_32 store_seed
[2] = { 0x12345678, 1};
608 make_four_random_bytes(store_seed
, mark
);
611 /* Use this for random 32 bit values; this function makes sure the result is
623 store_pool_mark(mark
);
624 result
= png_get_uint_32(mark
);
632 store_pool_init(png_store
*ps
, store_pool
*pool
)
634 memset(pool
, 0, sizeof *pool
);
638 pool
->max
= pool
->current
= pool
->limit
= pool
->total
= 0;
639 pool
->max_max
= pool
->max_limit
= pool
->max_total
= 0;
640 store_pool_mark(pool
->mark
);
644 store_init(png_store
* ps
)
646 memset(ps
, 0, sizeof *ps
);
647 init_exception_context(&ps
->exception_context
);
648 store_pool_init(ps
, &ps
->read_memory_pool
);
649 store_pool_init(ps
, &ps
->write_memory_pool
);
651 ps
->treat_warnings_as_errors
= 0;
652 ps
->expect_error
= 0;
653 ps
->expect_warning
= 0;
658 ps
->nerrors
= ps
->nwarnings
= 0;
661 ps
->saved
= ps
->current
= NULL
;
677 store_freebuffer(png_store_buffer
* psb
)
681 store_freebuffer(psb
->prev
);
688 store_freenew(png_store
*ps
)
690 store_freebuffer(&ps
->new);
692 if (ps
->palette
!= NULL
)
701 store_storenew(png_store
*ps
)
703 png_store_buffer
*pb
;
705 if (ps
->writepos
!= STORE_BUFFER_SIZE
)
706 png_error(ps
->pwrite
, "invalid store call");
708 pb
= voidcast(png_store_buffer
*, malloc(sizeof *pb
));
711 png_error(ps
->pwrite
, "store new: OOM");
719 store_freefile(png_store_file
**ppf
)
723 store_freefile(&(*ppf
)->next
);
725 store_freebuffer(&(*ppf
)->data
);
726 (*ppf
)->datacount
= 0;
727 if ((*ppf
)->palette
!= NULL
)
729 free((*ppf
)->palette
);
730 (*ppf
)->palette
= NULL
;
731 (*ppf
)->npalette
= 0;
738 /* Main interface to file storeage, after writing a new PNG file (see the API
739 * below) call store_storefile to store the result with the given name and id.
742 store_storefile(png_store
*ps
, png_uint_32 id
)
744 png_store_file
*pf
= voidcast(png_store_file
*, malloc(sizeof *pf
));
746 png_error(ps
->pwrite
, "storefile: OOM");
747 safecat(pf
->name
, sizeof pf
->name
, 0, ps
->wname
);
750 pf
->datacount
= ps
->writepos
;
753 pf
->palette
= ps
->palette
;
754 pf
->npalette
= ps
->npalette
;
759 pf
->next
= ps
->saved
;
763 /* Generate an error message (in the given buffer) */
765 store_message(png_store
*ps
, png_structp pp
, char *buffer
, size_t bufsize
,
766 size_t pos
, PNG_CONST
char *msg
)
768 if (pp
!= NULL
&& pp
== ps
->pread
)
771 pos
= safecat(buffer
, bufsize
, pos
, "read: ");
773 if (ps
->current
!= NULL
)
775 pos
= safecat(buffer
, bufsize
, pos
, ps
->current
->name
);
776 pos
= safecat(buffer
, bufsize
, pos
, sep
);
780 else if (pp
!= NULL
&& pp
== ps
->pwrite
)
783 pos
= safecat(buffer
, bufsize
, pos
, "write: ");
784 pos
= safecat(buffer
, bufsize
, pos
, ps
->wname
);
785 pos
= safecat(buffer
, bufsize
, pos
, sep
);
790 /* Neither reading nor writing (or a memory error in struct delete) */
791 pos
= safecat(buffer
, bufsize
, pos
, "pngvalid: ");
794 if (ps
->test
[0] != 0)
796 pos
= safecat(buffer
, bufsize
, pos
, ps
->test
);
797 pos
= safecat(buffer
, bufsize
, pos
, sep
);
799 pos
= safecat(buffer
, bufsize
, pos
, msg
);
803 /* Verbose output to the error stream: */
805 store_verbose(png_store
*ps
, png_structp pp
, png_const_charp prefix
,
806 png_const_charp message
)
811 fputs(prefix
, stderr
);
813 (void)store_message(ps
, pp
, buffer
, sizeof buffer
, 0, message
);
814 fputs(buffer
, stderr
);
818 /* Log an error or warning - the relevant count is always incremented. */
820 store_log(png_store
* ps
, png_structp pp
, png_const_charp message
, int is_error
)
822 /* The warning is copied to the error buffer if there are no errors and it is
823 * the first warning. The error is copied to the error buffer if it is the
824 * first error (overwriting any prior warnings).
826 if (is_error
? (ps
->nerrors
)++ == 0 :
827 (ps
->nwarnings
)++ == 0 && ps
->nerrors
== 0)
828 store_message(ps
, pp
, ps
->error
, sizeof ps
->error
, 0, message
);
831 store_verbose(ps
, pp
, is_error
? "error: " : "warning: ", message
);
834 /* Functions to use as PNG callbacks. */
836 store_error(png_structp pp
, png_const_charp message
) /* PNG_NORETURN */
838 png_store
*ps
= voidcast(png_store
*, png_get_error_ptr(pp
));
840 if (!ps
->expect_error
)
841 store_log(ps
, pp
, message
, 1 /* error */);
843 /* And finally throw an exception. */
845 struct exception_context
*the_exception_context
= &ps
->exception_context
;
851 store_warning(png_structp pp
, png_const_charp message
)
853 png_store
*ps
= voidcast(png_store
*, png_get_error_ptr(pp
));
855 if (!ps
->expect_warning
)
856 store_log(ps
, pp
, message
, 0 /* warning */);
861 /* These somewhat odd functions are used when reading an image to ensure that
862 * the buffer is big enough, the png_structp is for errors.
864 /* Return a single row from the correct image. */
866 store_image_row(PNG_CONST png_store
* ps
, png_structp pp
, int nImage
,
869 png_size_t coffset
= (nImage
* ps
->image_h
+ y
) * (ps
->cb_row
+ 5) + 2;
871 if (ps
->image
== NULL
)
872 png_error(pp
, "no allocated image");
874 if (coffset
+ ps
->cb_row
+ 3 > ps
->cb_image
)
875 png_error(pp
, "image too small");
877 return ps
->image
+ coffset
;
881 store_image_free(png_store
*ps
, png_structp pp
)
883 if (ps
->image
!= NULL
)
885 png_bytep image
= ps
->image
;
887 if (image
[-1] != 0xed || image
[ps
->cb_image
] != 0xfe)
890 png_error(pp
, "png_store image overwrite (1)");
892 store_log(ps
, NULL
, "png_store image overwrite (2)", 1);
903 store_ensure_image(png_store
*ps
, png_structp pp
, int nImages
, png_size_t cbRow
,
906 png_size_t cb
= nImages
* cRows
* (cbRow
+ 5);
908 if (ps
->cb_image
< cb
)
912 store_image_free(ps
, pp
);
914 /* The buffer is deliberately mis-aligned. */
915 image
= voidcast(png_bytep
, malloc(cb
+2));
918 /* Called from the startup - ignore the error for the moment. */
922 png_error(pp
, "OOM allocating image buffer");
925 /* These magic tags are used to detect overwrites above. */
934 /* We have an adequate sized image; lay out the rows. There are 2 bytes at
935 * the start and three at the end of each (this ensures that the row
936 * alignment starts out odd - 2+1 and changes for larger images on each row.)
941 /* For error checking, the whole buffer is set to 10110010 (0xb2 - 178).
942 * This deliberately doesn't match the bits in the size test image which are
943 * outside the image; these are set to 0xff (all 1). To make the row
944 * comparison work in the 'size' test case the size rows are pre-initialized
945 * to the same value prior to calling 'standard_row'.
947 memset(ps
->image
, 178, cb
);
949 /* Then put in the marks. */
950 while (--nImages
>= 0)
954 for (y
=0; y
<cRows
; ++y
)
956 png_bytep row
= store_image_row(ps
, pp
, nImages
, y
);
969 store_image_check(PNG_CONST png_store
* ps
, png_structp pp
, int iImage
)
971 png_const_bytep image
= ps
->image
;
973 if (image
[-1] != 0xed || image
[ps
->cb_image
] != 0xfe)
974 png_error(pp
, "image overwrite");
977 png_size_t cbRow
= ps
->cb_row
;
978 png_uint_32 rows
= ps
->image_h
;
980 image
+= iImage
* (cbRow
+5) * ps
->image_h
;
982 image
+= 2; /* skip image first row markers */
986 if (image
[-2] != 190 || image
[-1] != 239)
987 png_error(pp
, "row start overwritten");
989 if (image
[cbRow
] != 222 || image
[cbRow
+1] != 173 ||
990 image
[cbRow
+2] != 17)
991 png_error(pp
, "row end overwritten");
999 store_write(png_structp pp
, png_bytep pb
, png_size_t st
)
1001 png_store
*ps
= voidcast(png_store
*, png_get_io_ptr(pp
));
1003 if (ps
->pwrite
!= pp
)
1004 png_error(pp
, "store state damaged");
1010 if (ps
->writepos
>= STORE_BUFFER_SIZE
)
1015 if (cb
> STORE_BUFFER_SIZE
- ps
->writepos
)
1016 cb
= STORE_BUFFER_SIZE
- ps
->writepos
;
1018 memcpy(ps
->new.buffer
+ ps
->writepos
, pb
, cb
);
1026 store_flush(png_structp pp
)
1028 UNUSED(pp
) /*DOES NOTHING*/
1032 store_read_buffer_size(png_store
*ps
)
1034 /* Return the bytes available for read in the current buffer. */
1035 if (ps
->next
!= &ps
->current
->data
)
1036 return STORE_BUFFER_SIZE
;
1038 return ps
->current
->datacount
;
1041 #ifdef PNG_READ_TRANSFORMS_SUPPORTED
1042 /* Return total bytes available for read. */
1044 store_read_buffer_avail(png_store
*ps
)
1046 if (ps
->current
!= NULL
&& ps
->next
!= NULL
)
1048 png_store_buffer
*next
= &ps
->current
->data
;
1049 size_t cbAvail
= ps
->current
->datacount
;
1051 while (next
!= ps
->next
&& next
!= NULL
)
1054 cbAvail
+= STORE_BUFFER_SIZE
;
1057 if (next
!= ps
->next
)
1058 png_error(ps
->pread
, "buffer read error");
1060 if (cbAvail
> ps
->readpos
)
1061 return cbAvail
- ps
->readpos
;
1069 store_read_buffer_next(png_store
*ps
)
1071 png_store_buffer
*pbOld
= ps
->next
;
1072 png_store_buffer
*pbNew
= &ps
->current
->data
;
1075 while (pbNew
!= NULL
&& pbNew
->prev
!= pbOld
)
1076 pbNew
= pbNew
->prev
;
1085 png_error(ps
->pread
, "buffer lost");
1088 return 0; /* EOF or error */
1091 /* Need separate implementation and callback to allow use of the same code
1092 * during progressive read, where the io_ptr is set internally by libpng.
1095 store_read_imp(png_store
*ps
, png_bytep pb
, png_size_t st
)
1097 if (ps
->current
== NULL
|| ps
->next
== NULL
)
1098 png_error(ps
->pread
, "store state damaged");
1102 size_t cbAvail
= store_read_buffer_size(ps
) - ps
->readpos
;
1106 if (cbAvail
> st
) cbAvail
= st
;
1107 memcpy(pb
, ps
->next
->buffer
+ ps
->readpos
, cbAvail
);
1110 ps
->readpos
+= cbAvail
;
1113 else if (!store_read_buffer_next(ps
))
1114 png_error(ps
->pread
, "read beyond end of file");
1119 store_read(png_structp pp
, png_bytep pb
, png_size_t st
)
1121 png_store
*ps
= voidcast(png_store
*, png_get_io_ptr(pp
));
1123 if (ps
== NULL
|| ps
->pread
!= pp
)
1124 png_error(pp
, "bad store read call");
1126 store_read_imp(ps
, pb
, st
);
1130 store_progressive_read(png_store
*ps
, png_structp pp
, png_infop pi
)
1132 /* Notice that a call to store_read will cause this function to fail because
1133 * readpos will be set.
1135 if (ps
->pread
!= pp
|| ps
->current
== NULL
|| ps
->next
== NULL
)
1136 png_error(pp
, "store state damaged (progressive)");
1140 if (ps
->readpos
!= 0)
1141 png_error(pp
, "store_read called during progressive read");
1143 png_process_data(pp
, pi
, ps
->next
->buffer
, store_read_buffer_size(ps
));
1145 while (store_read_buffer_next(ps
));
1148 /* The caller must fill this in: */
1149 static store_palette_entry
*
1150 store_write_palette(png_store
*ps
, int npalette
)
1152 if (ps
->pwrite
== NULL
)
1153 store_log(ps
, NULL
, "attempt to write palette without write stream", 1);
1155 if (ps
->palette
!= NULL
)
1156 png_error(ps
->pwrite
, "multiple store_write_palette calls");
1158 /* This function can only return NULL if called with '0'! */
1161 ps
->palette
= voidcast(store_palette_entry
*, malloc(npalette
*
1162 sizeof *ps
->palette
));
1164 if (ps
->palette
== NULL
)
1165 png_error(ps
->pwrite
, "store new palette: OOM");
1167 ps
->npalette
= npalette
;
1173 static store_palette_entry
*
1174 store_current_palette(png_store
*ps
, int *npalette
)
1176 /* This is an internal error (the call has been made outside a read
1179 if (ps
->current
== NULL
)
1180 store_log(ps
, ps
->pread
, "no current stream for palette", 1);
1182 /* The result may be null if there is no palette. */
1183 *npalette
= ps
->current
->npalette
;
1184 return ps
->current
->palette
;
1187 /***************************** MEMORY MANAGEMENT*** ***************************/
1188 /* A store_memory is simply the header for an allocated block of memory. The
1189 * pointer returned to libpng is just after the end of the header block, the
1190 * allocated memory is followed by a second copy of the 'mark'.
1192 typedef struct store_memory
1194 store_pool
*pool
; /* Originating pool */
1195 struct store_memory
*next
; /* Singly linked list */
1196 png_alloc_size_t size
; /* Size of memory allocated */
1197 png_byte mark
[4]; /* ID marker */
1200 /* Handle a fatal error in memory allocation. This calls png_error if the
1201 * libpng struct is non-NULL, else it outputs a message and returns. This means
1202 * that a memory problem while libpng is running will abort (png_error) the
1203 * handling of particular file while one in cleanup (after the destroy of the
1204 * struct has returned) will simply keep going and free (or attempt to free)
1208 store_pool_error(png_store
*ps
, png_structp pp
, PNG_CONST
char *msg
)
1213 /* Else we have to do it ourselves. png_error eventually calls store_log,
1214 * above. store_log accepts a NULL png_structp - it just changes what gets
1215 * output by store_message.
1217 store_log(ps
, pp
, msg
, 1 /* error */);
1221 store_memory_free(png_structp pp
, store_pool
*pool
, store_memory
*memory
)
1223 /* Note that pp may be NULL (see store_pool_delete below), the caller has
1224 * found 'memory' in pool->list *and* unlinked this entry, so this is a valid
1225 * pointer (for sure), but the contents may have been trashed.
1227 if (memory
->pool
!= pool
)
1228 store_pool_error(pool
->store
, pp
, "memory corrupted (pool)");
1230 else if (memcmp(memory
->mark
, pool
->mark
, sizeof memory
->mark
) != 0)
1231 store_pool_error(pool
->store
, pp
, "memory corrupted (start)");
1233 /* It should be safe to read the size field now. */
1236 png_alloc_size_t cb
= memory
->size
;
1239 store_pool_error(pool
->store
, pp
, "memory corrupted (size)");
1241 else if (memcmp((png_bytep
)(memory
+1)+cb
, pool
->mark
, sizeof pool
->mark
)
1243 store_pool_error(pool
->store
, pp
, "memory corrupted (end)");
1245 /* Finally give the library a chance to find problems too: */
1248 pool
->current
-= cb
;
1255 store_pool_delete(png_store
*ps
, store_pool
*pool
)
1257 if (pool
->list
!= NULL
)
1259 fprintf(stderr
, "%s: %s %s: memory lost (list follows):\n", ps
->test
,
1260 pool
== &ps
->read_memory_pool
? "read" : "write",
1261 pool
== &ps
->read_memory_pool
? (ps
->current
!= NULL
?
1262 ps
->current
->name
: "unknown file") : ps
->wname
);
1267 store_memory
*next
= pool
->list
;
1268 pool
->list
= next
->next
;
1271 fprintf(stderr
, "\t%lu bytes @ %p\n",
1272 (unsigned long)next
->size
, (PNG_CONST
void*)(next
+1));
1273 /* The NULL means this will always return, even if the memory is
1276 store_memory_free(NULL
, pool
, next
);
1278 while (pool
->list
!= NULL
);
1281 /* And reset the other fields too for the next time. */
1282 if (pool
->max
> pool
->max_max
) pool
->max_max
= pool
->max
;
1284 if (pool
->current
!= 0) /* unexpected internal error */
1285 fprintf(stderr
, "%s: %s %s: memory counter mismatch (internal error)\n",
1286 ps
->test
, pool
== &ps
->read_memory_pool
? "read" : "write",
1287 pool
== &ps
->read_memory_pool
? (ps
->current
!= NULL
?
1288 ps
->current
->name
: "unknown file") : ps
->wname
);
1291 if (pool
->limit
> pool
->max_limit
)
1292 pool
->max_limit
= pool
->limit
;
1296 if (pool
->total
> pool
->max_total
)
1297 pool
->max_total
= pool
->total
;
1301 /* Get a new mark too. */
1302 store_pool_mark(pool
->mark
);
1305 /* The memory callbacks: */
1307 store_malloc(png_structp pp
, png_alloc_size_t cb
)
1309 store_pool
*pool
= voidcast(store_pool
*, png_get_mem_ptr(pp
));
1310 store_memory
*new = voidcast(store_memory
*, malloc(cb
+ (sizeof *new) +
1311 (sizeof pool
->mark
)));
1318 pool
->current
+= cb
;
1320 if (pool
->current
> pool
->limit
)
1321 pool
->limit
= pool
->current
;
1326 memcpy(new->mark
, pool
->mark
, sizeof new->mark
);
1327 memcpy((png_byte
*)(new+1) + cb
, pool
->mark
, sizeof pool
->mark
);
1329 new->next
= pool
->list
;
1335 store_pool_error(pool
->store
, pp
, "out of memory");
1341 store_free(png_structp pp
, png_voidp memory
)
1343 store_pool
*pool
= voidcast(store_pool
*, png_get_mem_ptr(pp
));
1344 store_memory
*this = voidcast(store_memory
*, memory
), **test
;
1346 /* First check that this 'memory' really is valid memory - it must be in the
1347 * pool list. If it is, use the shared memory_free function to free it.
1350 for (test
= &pool
->list
; *test
!= this; test
= &(*test
)->next
)
1354 store_pool_error(pool
->store
, pp
, "bad pointer to free");
1359 /* Unlink this entry, *test == this. */
1362 store_memory_free(pp
, pool
, this);
1365 /* Setup functions. */
1366 /* Cleanup when aborting a write or after storing the new file. */
1368 store_write_reset(png_store
*ps
)
1370 if (ps
->pwrite
!= NULL
)
1375 png_destroy_write_struct(&ps
->pwrite
, &ps
->piwrite
);
1379 /* memory corruption: continue. */
1386 /* And make sure that all the memory has been freed - this will output
1387 * spurious errors in the case of memory corruption above, but this is safe.
1389 store_pool_delete(ps
, &ps
->write_memory_pool
);
1394 /* The following is the main write function, it returns a png_struct and,
1395 * optionally, a png_info suitable for writiing a new PNG file. Use
1396 * store_storefile above to record this file after it has been written. The
1397 * returned libpng structures as destroyed by store_write_reset above.
1400 set_store_for_write(png_store
*ps
, png_infopp ppi
,
1401 PNG_CONST
char * volatile name
)
1407 if (ps
->pwrite
!= NULL
)
1408 png_error(ps
->pwrite
, "write store already in use");
1410 store_write_reset(ps
);
1411 safecat(ps
->wname
, sizeof ps
->wname
, 0, name
);
1413 /* Don't do the slow memory checks if doing a speed test. */
1415 ps
->pwrite
= png_create_write_struct(PNG_LIBPNG_VER_STRING
,
1416 ps
, store_error
, store_warning
);
1419 ps
->pwrite
= png_create_write_struct_2(PNG_LIBPNG_VER_STRING
,
1420 ps
, store_error
, store_warning
, &ps
->write_memory_pool
,
1421 store_malloc
, store_free
);
1423 png_set_write_fn(ps
->pwrite
, ps
, store_write
, store_flush
);
1426 *ppi
= ps
->piwrite
= png_create_info_struct(ps
->pwrite
);
1435 /* Cleanup when finished reading (either due to error or in the success case).
1438 store_read_reset(png_store
*ps
)
1440 if (ps
->pread
!= NULL
)
1445 png_destroy_read_struct(&ps
->pread
, &ps
->piread
, NULL
);
1449 /* error already output: continue */
1456 /* Always do this to be safe. */
1457 store_pool_delete(ps
, &ps
->read_memory_pool
);
1466 store_read_set(png_store
*ps
, png_uint_32 id
)
1468 png_store_file
*pf
= ps
->saved
;
1476 store_read_buffer_next(ps
);
1485 char msg
[FILE_NAME_SIZE
+64];
1487 pos
= standard_name_from_id(msg
, sizeof msg
, 0, id
);
1488 pos
= safecat(msg
, sizeof msg
, pos
, ": file not found");
1489 png_error(ps
->pread
, msg
);
1493 /* The main interface for reading a saved file - pass the id number of the file
1494 * to retrieve. Ids must be unique or the earlier file will be hidden. The API
1495 * returns a png_struct and, optionally, a png_info. Both of these will be
1496 * destroyed by store_read_reset above.
1499 set_store_for_read(png_store
*ps
, png_infopp ppi
, png_uint_32 id
,
1500 PNG_CONST
char *name
)
1502 /* Set the name for png_error */
1503 safecat(ps
->test
, sizeof ps
->test
, 0, name
);
1505 if (ps
->pread
!= NULL
)
1506 png_error(ps
->pread
, "read store already in use");
1508 store_read_reset(ps
);
1510 /* Both the create APIs can return NULL if used in their default mode
1511 * (because there is no other way of handling an error because the jmp_buf
1512 * by default is stored in png_struct and that has not been allocated!)
1513 * However, given that store_error works correctly in these circumstances
1514 * we don't ever expect NULL in this program.
1517 ps
->pread
= png_create_read_struct(PNG_LIBPNG_VER_STRING
, ps
,
1518 store_error
, store_warning
);
1521 ps
->pread
= png_create_read_struct_2(PNG_LIBPNG_VER_STRING
, ps
,
1522 store_error
, store_warning
, &ps
->read_memory_pool
, store_malloc
,
1525 if (ps
->pread
== NULL
)
1527 struct exception_context
*the_exception_context
= &ps
->exception_context
;
1529 store_log(ps
, NULL
, "png_create_read_struct returned NULL (unexpected)",
1535 store_read_set(ps
, id
);
1538 *ppi
= ps
->piread
= png_create_info_struct(ps
->pread
);
1543 /* The overall cleanup of a store simply calls the above then removes all the
1544 * saved files. This does not delete the store itself.
1547 store_delete(png_store
*ps
)
1549 store_write_reset(ps
);
1550 store_read_reset(ps
);
1551 store_freefile(&ps
->saved
);
1552 store_image_free(ps
, NULL
);
1555 /*********************** PNG FILE MODIFICATION ON READ ************************/
1556 /* Files may be modified on read. The following structure contains a complete
1557 * png_store together with extra members to handle modification and a special
1558 * read callback for libpng. To use this the 'modifications' field must be set
1559 * to a list of png_modification structures that actually perform the
1560 * modification, otherwise a png_modifier is functionally equivalent to a
1561 * png_store. There is a special read function, set_modifier_for_read, which
1562 * replaces set_store_for_read.
1564 typedef enum modifier_state
1566 modifier_start
, /* Initial value */
1567 modifier_signature
, /* Have a signature */
1568 modifier_IHDR
/* Have an IHDR */
1571 typedef struct CIE_color
1573 /* A single CIE tristimulus value, representing the unique response of a
1574 * standard observer to a variety of light spectra. The observer recognizes
1575 * all spectra that produce this response as the same color, therefore this
1576 * is effectively a description of a color.
1582 chromaticity_x(CIE_color c
)
1584 return c
.X
/ (c
.X
+ c
.Y
+ c
.Z
);
1588 chromaticity_y(CIE_color c
)
1590 return c
.Y
/ (c
.X
+ c
.Y
+ c
.Z
);
1593 typedef struct color_encoding
1595 /* A description of an (R,G,B) encoding of color (as defined above); this
1596 * includes the actual colors of the (R,G,B) triples (1,0,0), (0,1,0) and
1597 * (0,0,1) plus an encoding value that is used to encode the linear
1598 * components R, G and B to give the actual values R^gamma, G^gamma and
1599 * B^gamma that are stored.
1601 double gamma
; /* Encoding (file) gamma of space */
1602 CIE_color red
, green
, blue
; /* End points */
1606 white_point(PNG_CONST color_encoding
*encoding
)
1610 white
.X
= encoding
->red
.X
+ encoding
->green
.X
+ encoding
->blue
.X
;
1611 white
.Y
= encoding
->red
.Y
+ encoding
->green
.Y
+ encoding
->blue
.Y
;
1612 white
.Z
= encoding
->red
.Z
+ encoding
->green
.Z
+ encoding
->blue
.Z
;
1618 normalize_color_encoding(color_encoding
*encoding
)
1620 PNG_CONST
double whiteY
= encoding
->red
.Y
+ encoding
->green
.Y
+
1625 encoding
->red
.X
/= whiteY
;
1626 encoding
->red
.Y
/= whiteY
;
1627 encoding
->red
.Z
/= whiteY
;
1628 encoding
->green
.X
/= whiteY
;
1629 encoding
->green
.Y
/= whiteY
;
1630 encoding
->green
.Z
/= whiteY
;
1631 encoding
->blue
.X
/= whiteY
;
1632 encoding
->blue
.Y
/= whiteY
;
1633 encoding
->blue
.Z
/= whiteY
;
1638 safecat_color_encoding(char *buffer
, size_t bufsize
, size_t pos
,
1639 PNG_CONST color_encoding
*e
, double encoding_gamma
)
1643 if (encoding_gamma
!= 0)
1644 pos
= safecat(buffer
, bufsize
, pos
, "(");
1645 pos
= safecat(buffer
, bufsize
, pos
, "R(");
1646 pos
= safecatd(buffer
, bufsize
, pos
, e
->red
.X
, 4);
1647 pos
= safecat(buffer
, bufsize
, pos
, ",");
1648 pos
= safecatd(buffer
, bufsize
, pos
, e
->red
.Y
, 4);
1649 pos
= safecat(buffer
, bufsize
, pos
, ",");
1650 pos
= safecatd(buffer
, bufsize
, pos
, e
->red
.Z
, 4);
1651 pos
= safecat(buffer
, bufsize
, pos
, "),G(");
1652 pos
= safecatd(buffer
, bufsize
, pos
, e
->green
.X
, 4);
1653 pos
= safecat(buffer
, bufsize
, pos
, ",");
1654 pos
= safecatd(buffer
, bufsize
, pos
, e
->green
.Y
, 4);
1655 pos
= safecat(buffer
, bufsize
, pos
, ",");
1656 pos
= safecatd(buffer
, bufsize
, pos
, e
->green
.Z
, 4);
1657 pos
= safecat(buffer
, bufsize
, pos
, "),B(");
1658 pos
= safecatd(buffer
, bufsize
, pos
, e
->blue
.X
, 4);
1659 pos
= safecat(buffer
, bufsize
, pos
, ",");
1660 pos
= safecatd(buffer
, bufsize
, pos
, e
->blue
.Y
, 4);
1661 pos
= safecat(buffer
, bufsize
, pos
, ",");
1662 pos
= safecatd(buffer
, bufsize
, pos
, e
->blue
.Z
, 4);
1663 pos
= safecat(buffer
, bufsize
, pos
, ")");
1664 if (encoding_gamma
!= 0)
1665 pos
= safecat(buffer
, bufsize
, pos
, ")");
1668 if (encoding_gamma
!= 0)
1670 pos
= safecat(buffer
, bufsize
, pos
, "^");
1671 pos
= safecatd(buffer
, bufsize
, pos
, encoding_gamma
, 5);
1677 typedef struct png_modifier
1679 png_store
this; /* I am a png_store */
1680 struct png_modification
*modifications
; /* Changes to make */
1682 modifier_state state
; /* My state */
1684 /* Information from IHDR: */
1685 png_byte bit_depth
; /* From IHDR */
1686 png_byte colour_type
; /* From IHDR */
1688 /* While handling PLTE, IDAT and IEND these chunks may be pended to allow
1689 * other chunks to be inserted.
1691 png_uint_32 pending_len
;
1692 png_uint_32 pending_chunk
;
1696 unsigned int ngammas
;
1697 unsigned int ngamma_tests
; /* Number of gamma tests to run*/
1698 double current_gamma
; /* 0 if not set */
1699 PNG_CONST color_encoding
*encodings
;
1700 unsigned int nencodings
;
1701 PNG_CONST color_encoding
*current_encoding
; /* If an encoding has been set */
1702 unsigned int encoding_counter
; /* For iteration */
1703 int encoding_ignored
; /* Something overwrote it */
1705 /* Control variables used to iterate through possible encodings, the
1706 * following must be set to 0 and tested by the function that uses the
1707 * png_modifier because the modifier only sets it to 1 (true.)
1709 unsigned int repeat
:1; /* Repeat this transform test. */
1710 unsigned int test_uses_encoding
:1;
1712 /* Lowest sbit to test (libpng fails for sbit < 8) */
1715 /* Error control - these are the limits on errors accepted by the gamma tests
1718 double maxout8
; /* Maximum output value error */
1719 double maxabs8
; /* Absolute sample error 0..1 */
1720 double maxcalc8
; /* Absolute sample error 0..1 */
1721 double maxpc8
; /* Percentage sample error 0..100% */
1722 double maxout16
; /* Maximum output value error */
1723 double maxabs16
; /* Absolute sample error 0..1 */
1724 double maxcalc16
;/* Absolute sample error 0..1 */
1725 double maxpc16
; /* Percentage sample error 0..100% */
1727 /* This is set by transforms that need to allow a higher limit, it is an
1728 * internal check on pngvalid to ensure that the calculated error limits are
1729 * not ridiculous; without this it is too easy to make a mistake in pngvalid
1730 * that allows any value through.
1732 double limit
; /* limit on error values, normally 4E-3 */
1734 /* Log limits - values above this are logged, but not necessarily
1737 double log8
; /* Absolute error in 8 bits to log */
1738 double log16
; /* Absolute error in 16 bits to log */
1740 /* Logged 8 and 16 bit errors ('output' values): */
1741 double error_gray_2
;
1742 double error_gray_4
;
1743 double error_gray_8
;
1744 double error_gray_16
;
1745 double error_color_8
;
1746 double error_color_16
;
1747 double error_indexed
;
1750 /* Whether to call png_read_update_info, not png_read_start_image, and how
1751 * many times to call it.
1753 int use_update_info
;
1755 /* Whether or not to interlace. */
1756 int interlace_type
:9; /* int, but must store '1' */
1758 /* Run the standard tests? */
1759 unsigned int test_standard
:1;
1761 /* Run the odd-sized image and interlace read/write tests? */
1762 unsigned int test_size
:1;
1764 /* Run tests on reading with a combiniation of transforms, */
1765 unsigned int test_transform
:1;
1767 /* When to use the use_input_precision option: */
1768 unsigned int use_input_precision
:1;
1769 unsigned int use_input_precision_sbit
:1;
1770 unsigned int use_input_precision_16to8
:1;
1772 /* If set assume that the calculation bit depth is set by the input
1773 * precision, not the output precision.
1775 unsigned int calculations_use_input_precision
:1;
1777 /* If set assume that the calculations are done in 16 bits even if both input
1778 * and output are 8 bit or less.
1780 unsigned int assume_16_bit_calculations
:1;
1782 /* Which gamma tests to run: */
1783 unsigned int test_gamma_threshold
:1;
1784 unsigned int test_gamma_transform
:1; /* main tests */
1785 unsigned int test_gamma_sbit
:1;
1786 unsigned int test_gamma_scale16
:1;
1787 unsigned int test_gamma_background
:1;
1788 unsigned int test_gamma_alpha_mode
:1;
1789 unsigned int test_gamma_expand16
:1;
1790 unsigned int test_exhaustive
:1;
1792 unsigned int log
:1; /* Log max error */
1794 /* Buffer information, the buffer size limits the size of the chunks that can
1795 * be modified - they must fit (including header and CRC) into the buffer!
1797 size_t flush
; /* Count of bytes to flush */
1798 size_t buffer_count
; /* Bytes in buffer */
1799 size_t buffer_position
; /* Position in buffer */
1800 png_byte buffer
[1024];
1803 /* This returns true if the test should be stopped now because it has already
1804 * failed and it is running silently.
1806 static int fail(png_modifier
*pm
)
1808 return !pm
->log
&& !pm
->this.verbose
&& (pm
->this.nerrors
> 0 ||
1809 (pm
->this.treat_warnings_as_errors
&& pm
->this.nwarnings
> 0));
1813 modifier_init(png_modifier
*pm
)
1815 memset(pm
, 0, sizeof *pm
);
1816 store_init(&pm
->this);
1817 pm
->modifications
= NULL
;
1818 pm
->state
= modifier_start
;
1821 pm
->ngamma_tests
= 0;
1823 pm
->current_gamma
= 0;
1826 pm
->current_encoding
= 0;
1827 pm
->encoding_counter
= 0;
1828 pm
->encoding_ignored
= 0;
1830 pm
->test_uses_encoding
= 0;
1831 pm
->maxout8
= pm
->maxpc8
= pm
->maxabs8
= pm
->maxcalc8
= 0;
1832 pm
->maxout16
= pm
->maxpc16
= pm
->maxabs16
= pm
->maxcalc16
= 0;
1834 pm
->log8
= pm
->log16
= 0; /* Means 'off' */
1835 pm
->error_gray_2
= pm
->error_gray_4
= pm
->error_gray_8
= 0;
1836 pm
->error_gray_16
= pm
->error_color_8
= pm
->error_color_16
= 0;
1837 pm
->error_indexed
= 0;
1838 pm
->use_update_info
= 0;
1839 pm
->interlace_type
= PNG_INTERLACE_NONE
;
1840 pm
->test_standard
= 0;
1842 pm
->test_transform
= 0;
1843 pm
->use_input_precision
= 0;
1844 pm
->use_input_precision_sbit
= 0;
1845 pm
->use_input_precision_16to8
= 0;
1846 pm
->calculations_use_input_precision
= 0;
1847 pm
->test_gamma_threshold
= 0;
1848 pm
->test_gamma_transform
= 0;
1849 pm
->test_gamma_sbit
= 0;
1850 pm
->test_gamma_scale16
= 0;
1851 pm
->test_gamma_background
= 0;
1852 pm
->test_gamma_alpha_mode
= 0;
1853 pm
->test_gamma_expand16
= 0;
1854 pm
->test_exhaustive
= 0;
1857 /* Rely on the memset for all the other fields - there are no pointers */
1860 #ifdef PNG_READ_TRANSFORMS_SUPPORTED
1861 /* If pm->calculations_use_input_precision is set then operations will happen
1862 * with only 8 bit precision unless both the input and output bit depth are 16.
1864 * If pm->assume_16_bit_calculations is set then even 8 bit calculations use 16
1865 * bit precision. This only affects those of the following limits that pertain
1866 * to a calculation - not a digitization operation - unless the following API is
1869 static double digitize(PNG_CONST png_modifier
*pm
, double value
,
1870 int sample_depth
, int do_round
)
1872 /* 'value' is in the range 0 to 1, the result is the same value rounded to a
1873 * multiple of the digitization factor - 8 or 16 bits depending on both the
1874 * sample depth and the 'assume' setting. Digitization is normally by
1875 * rounding and 'do_round' should be 1, if it is 0 the digitized value will
1878 PNG_CONST
unsigned int digitization_factor
=
1879 (pm
->assume_16_bit_calculations
|| sample_depth
== 16) ? 65535 : 255;
1881 /* Limiting the range is done as a convenience to the caller - it's easier to
1882 * do it once here than every time at the call site.
1886 else if (value
>= 1)
1889 value
*= digitization_factor
;
1890 if (do_round
) value
+= .5;
1891 return floor(value
)/digitization_factor
;
1894 static double abserr(PNG_CONST png_modifier
*pm
, int in_depth
, int out_depth
)
1896 /* Absolute error permitted in linear values - affected by the bit depth of
1899 if (pm
->assume_16_bit_calculations
|| (out_depth
== 16 && (in_depth
== 16 ||
1900 !pm
->calculations_use_input_precision
)))
1901 return pm
->maxabs16
;
1906 static double calcerr(PNG_CONST png_modifier
*pm
, int in_depth
, int out_depth
)
1908 /* Error in the linear composition arithmetic - only relevant when
1909 * composition actually happens (0 < alpha < 1).
1911 if (pm
->assume_16_bit_calculations
|| (out_depth
== 16 && (in_depth
== 16 ||
1912 !pm
->calculations_use_input_precision
)))
1913 return pm
->maxcalc16
;
1915 return pm
->maxcalc8
;
1918 static double pcerr(PNG_CONST png_modifier
*pm
, int in_depth
, int out_depth
)
1920 /* Percentage error permitted in the linear values. Note that the specified
1921 * value is a percentage but this routine returns a simple number.
1923 if (pm
->assume_16_bit_calculations
|| (out_depth
== 16 && (in_depth
== 16 ||
1924 !pm
->calculations_use_input_precision
)))
1925 return pm
->maxpc16
* .01;
1927 return pm
->maxpc8
* .01;
1930 /* Output error - the error in the encoded value. This is determined by the
1931 * digitization of the output so can be +/-0.5 in the actual output value. In
1932 * the expand_16 case with the current code in libpng the expand happens after
1933 * all the calculations are done in 8 bit arithmetic, so even though the output
1934 * depth is 16 the output error is determined by the 8 bit calculation.
1936 * This limit is not determined by the bit depth of internal calculations.
1938 * The specified parameter does *not* include the base .5 digitization error but
1941 static double outerr(PNG_CONST png_modifier
*pm
, int in_depth
, int out_depth
)
1943 /* There is a serious error in the 2 and 4 bit grayscale transform because
1944 * the gamma table value (8 bits) is simply shifted, not rounded, so the
1945 * error in 4 bit grayscale gamma is up to the value below. This is a hack
1946 * to allow pngvalid to succeed:
1948 * TODO: fix this in libpng
1956 if (out_depth
== 16 && (in_depth
== 16 ||
1957 !pm
->calculations_use_input_precision
))
1958 return pm
->maxout16
;
1960 /* This is the case where the value was calculated at 8-bit precision then
1961 * scaled to 16 bits.
1963 else if (out_depth
== 16)
1964 return pm
->maxout8
* 257;
1970 /* This does the same thing as the above however it returns the value to log,
1971 * rather than raising a warning. This is useful for debugging to track down
1972 * exactly what set of parameters cause high error values.
1974 static double outlog(PNG_CONST png_modifier
*pm
, int in_depth
, int out_depth
)
1976 /* The command line parameters are either 8 bit (0..255) or 16 bit (0..65535)
1977 * and so must be adjusted for low bit depth grayscale:
1981 if (pm
->log8
== 0) /* switched off */
1985 return pm
->log8
/ 255 * ((1<<out_depth
)-1);
1990 if (out_depth
== 16 && (in_depth
== 16 ||
1991 !pm
->calculations_use_input_precision
))
1999 /* This is the case where the value was calculated at 8-bit precision then
2000 * scaled to 16 bits.
2005 return pm
->log8
* 257;
2008 /* This complements the above by providing the appropriate quantization for the
2009 * final value. Normally this would just be quantization to an integral value,
2010 * but in the 8 bit calculation case it's actually quantization to a multiple of
2013 static int output_quantization_factor(PNG_CONST png_modifier
*pm
, int in_depth
,
2016 if (out_depth
== 16 && in_depth
!= 16
2017 && pm
->calculations_use_input_precision
)
2023 /* One modification structure must be provided for each chunk to be modified (in
2024 * fact more than one can be provided if multiple separate changes are desired
2025 * for a single chunk.) Modifications include adding a new chunk when a
2026 * suitable chunk does not exist.
2028 * The caller of modify_fn will reset the CRC of the chunk and record 'modified'
2029 * or 'added' as appropriate if the modify_fn returns 1 (true). If the
2030 * modify_fn is NULL the chunk is simply removed.
2032 typedef struct png_modification
2034 struct png_modification
*next
;
2037 /* If the following is NULL all matching chunks will be removed: */
2038 int (*modify_fn
)(struct png_modifier
*pm
,
2039 struct png_modification
*me
, int add
);
2041 /* If the following is set to PLTE, IDAT or IEND and the chunk has not been
2042 * found and modified (and there is a modify_fn) the modify_fn will be called
2043 * to add the chunk before the relevant chunk.
2046 unsigned int modified
:1; /* Chunk was modified */
2047 unsigned int added
:1; /* Chunk was added */
2048 unsigned int removed
:1; /* Chunk was removed */
2052 modification_reset(png_modification
*pmm
)
2059 modification_reset(pmm
->next
);
2064 modification_init(png_modification
*pmm
)
2066 memset(pmm
, 0, sizeof *pmm
);
2069 pmm
->modify_fn
= NULL
;
2071 modification_reset(pmm
);
2075 modifier_current_encoding(PNG_CONST png_modifier
*pm
, color_encoding
*ce
)
2077 if (pm
->current_encoding
!= 0)
2078 *ce
= *pm
->current_encoding
;
2081 memset(ce
, 0, sizeof *ce
);
2083 ce
->gamma
= pm
->current_gamma
;
2087 safecat_current_encoding(char *buffer
, size_t bufsize
, size_t pos
,
2088 PNG_CONST png_modifier
*pm
)
2090 pos
= safecat_color_encoding(buffer
, bufsize
, pos
, pm
->current_encoding
,
2093 if (pm
->encoding_ignored
)
2094 pos
= safecat(buffer
, bufsize
, pos
, "[overridden]");
2099 /* Iterate through the usefully testable color encodings. An encoding is one
2102 * 1) Nothing (no color space, no gamma).
2103 * 2) Just a gamma value from the gamma array (including 1.0)
2104 * 3) A color space from the encodings array with the corresponding gamma.
2105 * 4) The same, but with gamma 1.0 (only really useful with 16 bit calculations)
2107 * The iterator selects these in turn, the randomizer selects one at random,
2108 * which is used depends on the setting of the 'test_exhaustive' flag. Notice
2109 * that this function changes the colour space encoding so it must only be
2110 * called on completion of the previous test. This is what 'modifier_reset'
2113 * After the function has been called the 'repeat' flag will still be set; the
2114 * caller of modifier_reset must reset it at the start of each run of the test!
2117 modifier_total_encodings(PNG_CONST png_modifier
*pm
)
2119 return 1 + /* (1) nothing */
2120 pm
->ngammas
+ /* (2) gamma values to test */
2121 pm
->nencodings
+ /* (3) total number of encodings */
2122 /* The following test only works after the first time through the
2123 * png_modifier code because 'bit_depth' is set when the IHDR is read.
2124 * modifier_reset, below, preserves the setting until after it has called
2125 * the iterate function (also below.)
2127 * For this reason do not rely on this function outside a call to
2130 ((pm
->bit_depth
== 16 || pm
->assume_16_bit_calculations
) ?
2131 pm
->nencodings
: 0); /* (4) encodings with gamma == 1.0 */
2135 modifier_encoding_iterate(png_modifier
*pm
)
2137 if (!pm
->repeat
&& /* Else something needs the current encoding again. */
2138 pm
->test_uses_encoding
) /* Some transform is encoding dependent */
2140 if (pm
->test_exhaustive
)
2142 if (++pm
->encoding_counter
>= modifier_total_encodings(pm
))
2143 pm
->encoding_counter
= 0; /* This will stop the repeat */
2148 /* Not exhaustive - choose an encoding at random; generate a number in
2149 * the range 1..(max-1), so the result is always non-zero:
2151 if (pm
->encoding_counter
== 0)
2152 pm
->encoding_counter
= random_mod(modifier_total_encodings(pm
)-1)+1;
2154 pm
->encoding_counter
= 0;
2157 if (pm
->encoding_counter
> 0)
2161 else if (!pm
->repeat
)
2162 pm
->encoding_counter
= 0;
2166 modifier_reset(png_modifier
*pm
)
2168 store_read_reset(&pm
->this);
2170 pm
->pending_len
= pm
->pending_chunk
= 0;
2171 pm
->flush
= pm
->buffer_count
= pm
->buffer_position
= 0;
2172 pm
->modifications
= NULL
;
2173 pm
->state
= modifier_start
;
2174 modifier_encoding_iterate(pm
);
2175 /* The following must be set in the next run. In particular
2176 * test_uses_encodings must be set in the _ini function of each transform
2177 * that looks at the encodings. (Not the 'add' function!)
2179 pm
->test_uses_encoding
= 0;
2180 pm
->current_gamma
= 0;
2181 pm
->current_encoding
= 0;
2182 pm
->encoding_ignored
= 0;
2183 /* These only become value after IHDR is read: */
2184 pm
->bit_depth
= pm
->colour_type
= 0;
2187 /* The following must be called before anything else to get the encoding set up
2188 * on the modifier. In particular it must be called before the transform init
2189 * functions are called.
2192 modifier_set_encoding(png_modifier
*pm
)
2194 /* Set the encoding to the one specified by the current encoding counter,
2195 * first clear out all the settings - this corresponds to an encoding_counter
2198 pm
->current_gamma
= 0;
2199 pm
->current_encoding
= 0;
2200 pm
->encoding_ignored
= 0; /* not ignored yet - happens in _ini functions. */
2202 /* Now, if required, set the gamma and encoding fields. */
2203 if (pm
->encoding_counter
> 0)
2205 /* The gammas[] array is an array of screen gammas, not encoding gammas,
2206 * so we need the inverse:
2208 if (pm
->encoding_counter
<= pm
->ngammas
)
2209 pm
->current_gamma
= 1/pm
->gammas
[pm
->encoding_counter
-1];
2213 unsigned int i
= pm
->encoding_counter
- pm
->ngammas
;
2215 if (i
>= pm
->nencodings
)
2217 i
%= pm
->nencodings
;
2218 pm
->current_gamma
= 1; /* Linear, only in the 16 bit case */
2222 pm
->current_gamma
= pm
->encodings
[i
].gamma
;
2224 pm
->current_encoding
= pm
->encodings
+ i
;
2229 /* Enquiry functions to find out what is set. Notice that there is an implicit
2230 * assumption below that the first encoding in the list is the one for sRGB.
2233 modifier_color_encoding_is_sRGB(PNG_CONST png_modifier
*pm
)
2235 return pm
->current_encoding
!= 0 && pm
->current_encoding
== pm
->encodings
&&
2236 pm
->current_encoding
->gamma
== pm
->current_gamma
;
2240 modifier_color_encoding_is_set(PNG_CONST png_modifier
*pm
)
2242 return pm
->current_gamma
!= 0;
2245 /* Convenience macros. */
2246 #define CHUNK(a,b,c,d) (((a)<<24)+((b)<<16)+((c)<<8)+(d))
2247 #define CHUNK_IHDR CHUNK(73,72,68,82)
2248 #define CHUNK_PLTE CHUNK(80,76,84,69)
2249 #define CHUNK_IDAT CHUNK(73,68,65,84)
2250 #define CHUNK_IEND CHUNK(73,69,78,68)
2251 #define CHUNK_cHRM CHUNK(99,72,82,77)
2252 #define CHUNK_gAMA CHUNK(103,65,77,65)
2253 #define CHUNK_sBIT CHUNK(115,66,73,84)
2254 #define CHUNK_sRGB CHUNK(115,82,71,66)
2256 /* The guts of modification are performed during a read. */
2258 modifier_crc(png_bytep buffer
)
2260 /* Recalculate the chunk CRC - a complete chunk must be in
2261 * the buffer, at the start.
2263 uInt datalen
= png_get_uint_32(buffer
);
2264 uLong crc
= crc32(0, buffer
+4, datalen
+4);
2265 /* The cast to png_uint_32 is safe because a crc32 is always a 32 bit value.
2267 png_save_uint_32(buffer
+datalen
+8, (png_uint_32
)crc
);
2271 modifier_setbuffer(png_modifier
*pm
)
2273 modifier_crc(pm
->buffer
);
2274 pm
->buffer_count
= png_get_uint_32(pm
->buffer
)+12;
2275 pm
->buffer_position
= 0;
2278 /* Separate the callback into the actual implementation (which is passed the
2279 * png_modifier explicitly) and the callback, which gets the modifier from the
2283 modifier_read_imp(png_modifier
*pm
, png_bytep pb
, png_size_t st
)
2288 png_uint_32 len
, chunk
;
2289 png_modification
*mod
;
2291 if (pm
->buffer_position
>= pm
->buffer_count
) switch (pm
->state
)
2293 static png_byte sign
[8] = { 137, 80, 78, 71, 13, 10, 26, 10 };
2294 case modifier_start
:
2295 store_read_imp(&pm
->this, pm
->buffer
, 8); /* size of signature. */
2296 pm
->buffer_count
= 8;
2297 pm
->buffer_position
= 0;
2299 if (memcmp(pm
->buffer
, sign
, 8) != 0)
2300 png_error(pm
->this.pread
, "invalid PNG file signature");
2301 pm
->state
= modifier_signature
;
2304 case modifier_signature
:
2305 store_read_imp(&pm
->this, pm
->buffer
, 13+12); /* size of IHDR */
2306 pm
->buffer_count
= 13+12;
2307 pm
->buffer_position
= 0;
2309 if (png_get_uint_32(pm
->buffer
) != 13 ||
2310 png_get_uint_32(pm
->buffer
+4) != CHUNK_IHDR
)
2311 png_error(pm
->this.pread
, "invalid IHDR");
2313 /* Check the list of modifiers for modifications to the IHDR. */
2314 mod
= pm
->modifications
;
2317 if (mod
->chunk
== CHUNK_IHDR
&& mod
->modify_fn
&&
2318 (*mod
->modify_fn
)(pm
, mod
, 0))
2321 modifier_setbuffer(pm
);
2324 /* Ignore removal or add if IHDR! */
2328 /* Cache information from the IHDR (the modified one.) */
2329 pm
->bit_depth
= pm
->buffer
[8+8];
2330 pm
->colour_type
= pm
->buffer
[8+8+1];
2332 pm
->state
= modifier_IHDR
;
2338 /* Read a new chunk and process it until we see PLTE, IDAT or
2339 * IEND. 'flush' indicates that there is still some data to
2340 * output from the preceding chunk.
2342 if ((cb
= pm
->flush
) > 0)
2344 if (cb
> st
) cb
= st
;
2346 store_read_imp(&pm
->this, pb
, cb
);
2349 if (st
== 0) return;
2352 /* No more bytes to flush, read a header, or handle a pending
2355 if (pm
->pending_chunk
!= 0)
2357 png_save_uint_32(pm
->buffer
, pm
->pending_len
);
2358 png_save_uint_32(pm
->buffer
+4, pm
->pending_chunk
);
2359 pm
->pending_len
= 0;
2360 pm
->pending_chunk
= 0;
2363 store_read_imp(&pm
->this, pm
->buffer
, 8);
2365 pm
->buffer_count
= 8;
2366 pm
->buffer_position
= 0;
2368 /* Check for something to modify or a terminator chunk. */
2369 len
= png_get_uint_32(pm
->buffer
);
2370 chunk
= png_get_uint_32(pm
->buffer
+4);
2372 /* Terminators first, they may have to be delayed for added
2375 if (chunk
== CHUNK_PLTE
|| chunk
== CHUNK_IDAT
||
2376 chunk
== CHUNK_IEND
)
2378 mod
= pm
->modifications
;
2382 if ((mod
->add
== chunk
||
2383 (mod
->add
== CHUNK_PLTE
&& chunk
== CHUNK_IDAT
)) &&
2384 mod
->modify_fn
!= NULL
&& !mod
->modified
&& !mod
->added
)
2386 /* Regardless of what the modify function does do not run
2391 if ((*mod
->modify_fn
)(pm
, mod
, 1 /*add*/))
2393 /* Reset the CRC on a new chunk */
2394 if (pm
->buffer_count
> 0)
2395 modifier_setbuffer(pm
);
2399 pm
->buffer_position
= 0;
2403 /* The buffer has been filled with something (we assume)
2404 * so output this. Pend the current chunk.
2406 pm
->pending_len
= len
;
2407 pm
->pending_chunk
= chunk
;
2408 break; /* out of while */
2415 /* Don't do any further processing if the buffer was modified -
2416 * otherwise the code will end up modifying a chunk that was
2420 break; /* out of switch */
2423 /* If we get to here then this chunk may need to be modified. To
2424 * do this it must be less than 1024 bytes in total size, otherwise
2425 * it just gets flushed.
2427 if (len
+12 <= sizeof pm
->buffer
)
2429 store_read_imp(&pm
->this, pm
->buffer
+pm
->buffer_count
,
2430 len
+12-pm
->buffer_count
);
2431 pm
->buffer_count
= len
+12;
2433 /* Check for a modification, else leave it be. */
2434 mod
= pm
->modifications
;
2437 if (mod
->chunk
== chunk
)
2439 if (mod
->modify_fn
== NULL
)
2441 /* Remove this chunk */
2442 pm
->buffer_count
= pm
->buffer_position
= 0;
2444 break; /* Terminate the while loop */
2447 else if ((*mod
->modify_fn
)(pm
, mod
, 0))
2450 /* The chunk may have been removed: */
2451 if (pm
->buffer_count
== 0)
2453 pm
->buffer_position
= 0;
2456 modifier_setbuffer(pm
);
2465 pm
->flush
= len
+12 - pm
->buffer_count
; /* data + crc */
2467 /* Take the data from the buffer (if there is any). */
2471 /* Here to read from the modifier buffer (not directly from
2472 * the store, as in the flush case above.)
2474 cb
= pm
->buffer_count
- pm
->buffer_position
;
2479 memcpy(pb
, pm
->buffer
+ pm
->buffer_position
, cb
);
2482 pm
->buffer_position
+= cb
;
2488 modifier_read(png_structp pp
, png_bytep pb
, png_size_t st
)
2490 png_modifier
*pm
= voidcast(png_modifier
*, png_get_io_ptr(pp
));
2492 if (pm
== NULL
|| pm
->this.pread
!= pp
)
2493 png_error(pp
, "bad modifier_read call");
2495 modifier_read_imp(pm
, pb
, st
);
2498 /* Like store_progressive_read but the data is getting changed as we go so we
2499 * need a local buffer.
2502 modifier_progressive_read(png_modifier
*pm
, png_structp pp
, png_infop pi
)
2504 if (pm
->this.pread
!= pp
|| pm
->this.current
== NULL
||
2505 pm
->this.next
== NULL
)
2506 png_error(pp
, "store state damaged (progressive)");
2508 /* This is another Horowitz and Hill random noise generator. In this case
2509 * the aim is to stress the progressive reader with truly horrible variable
2510 * buffer sizes in the range 1..500, so a sequence of 9 bit random numbers
2511 * is generated. We could probably just count from 1 to 32767 and get as
2516 static png_uint_32 noise
= 1;
2517 png_size_t cb
, cbAvail
;
2518 png_byte buffer
[512];
2520 /* Generate 15 more bits of stuff: */
2521 noise
= (noise
<< 9) | ((noise
^ (noise
>> (9-5))) & 0x1ff);
2524 /* Check that this number of bytes are available (in the current buffer.)
2525 * (This doesn't quite work - the modifier might delete a chunk; unlikely
2526 * but possible, it doesn't happen at present because the modifier only
2527 * adds chunks to standard images.)
2529 cbAvail
= store_read_buffer_avail(&pm
->this);
2530 if (pm
->buffer_count
> pm
->buffer_position
)
2531 cbAvail
+= pm
->buffer_count
- pm
->buffer_position
;
2535 /* Check for EOF: */
2542 modifier_read_imp(pm
, buffer
, cb
);
2543 png_process_data(pp
, pi
, buffer
, cb
);
2546 /* Check the invariants at the end (if this fails it's a problem in this
2549 if (pm
->buffer_count
> pm
->buffer_position
||
2550 pm
->this.next
!= &pm
->this.current
->data
||
2551 pm
->this.readpos
< pm
->this.current
->datacount
)
2552 png_error(pp
, "progressive read implementation error");
2555 /* Set up a modifier. */
2557 set_modifier_for_read(png_modifier
*pm
, png_infopp ppi
, png_uint_32 id
,
2558 PNG_CONST
char *name
)
2560 /* Do this first so that the modifier fields are cleared even if an error
2561 * happens allocating the png_struct. No allocation is done here so no
2562 * cleanup is required.
2564 pm
->state
= modifier_start
;
2566 pm
->colour_type
= 255;
2568 pm
->pending_len
= 0;
2569 pm
->pending_chunk
= 0;
2571 pm
->buffer_count
= 0;
2572 pm
->buffer_position
= 0;
2574 return set_store_for_read(&pm
->this, ppi
, id
, name
);
2578 /******************************** MODIFICATIONS *******************************/
2579 /* Standard modifications to add chunks. These do not require the _SUPPORTED
2580 * macros because the chunks can be there regardless of whether this specific
2581 * libpng supports them.
2583 typedef struct gama_modification
2585 png_modification
this;
2586 png_fixed_point gamma
;
2587 } gama_modification
;
2590 gama_modify(png_modifier
*pm
, png_modification
*me
, int add
)
2593 /* This simply dumps the given gamma value into the buffer. */
2594 png_save_uint_32(pm
->buffer
, 4);
2595 png_save_uint_32(pm
->buffer
+4, CHUNK_gAMA
);
2596 png_save_uint_32(pm
->buffer
+8, ((gama_modification
*)me
)->gamma
);
2601 gama_modification_init(gama_modification
*me
, png_modifier
*pm
, double gammad
)
2605 modification_init(&me
->this);
2606 me
->this.chunk
= CHUNK_gAMA
;
2607 me
->this.modify_fn
= gama_modify
;
2608 me
->this.add
= CHUNK_PLTE
;
2610 me
->gamma
= (png_fixed_point
)g
;
2611 me
->this.next
= pm
->modifications
;
2612 pm
->modifications
= &me
->this;
2615 typedef struct chrm_modification
2617 png_modification
this;
2618 PNG_CONST color_encoding
*encoding
;
2619 png_fixed_point wx
, wy
, rx
, ry
, gx
, gy
, bx
, by
;
2620 } chrm_modification
;
2623 chrm_modify(png_modifier
*pm
, png_modification
*me
, int add
)
2626 /* As with gAMA this just adds the required cHRM chunk to the buffer. */
2627 png_save_uint_32(pm
->buffer
, 32);
2628 png_save_uint_32(pm
->buffer
+ 4, CHUNK_cHRM
);
2629 png_save_uint_32(pm
->buffer
+ 8, ((chrm_modification
*)me
)->wx
);
2630 png_save_uint_32(pm
->buffer
+12, ((chrm_modification
*)me
)->wy
);
2631 png_save_uint_32(pm
->buffer
+16, ((chrm_modification
*)me
)->rx
);
2632 png_save_uint_32(pm
->buffer
+20, ((chrm_modification
*)me
)->ry
);
2633 png_save_uint_32(pm
->buffer
+24, ((chrm_modification
*)me
)->gx
);
2634 png_save_uint_32(pm
->buffer
+28, ((chrm_modification
*)me
)->gy
);
2635 png_save_uint_32(pm
->buffer
+32, ((chrm_modification
*)me
)->bx
);
2636 png_save_uint_32(pm
->buffer
+36, ((chrm_modification
*)me
)->by
);
2641 chrm_modification_init(chrm_modification
*me
, png_modifier
*pm
,
2642 PNG_CONST color_encoding
*encoding
)
2644 CIE_color white
= white_point(encoding
);
2646 /* Original end points: */
2647 me
->encoding
= encoding
;
2649 /* Chromaticities (in fixed point): */
2650 me
->wx
= fix(chromaticity_x(white
));
2651 me
->wy
= fix(chromaticity_y(white
));
2653 me
->rx
= fix(chromaticity_x(encoding
->red
));
2654 me
->ry
= fix(chromaticity_y(encoding
->red
));
2655 me
->gx
= fix(chromaticity_x(encoding
->green
));
2656 me
->gy
= fix(chromaticity_y(encoding
->green
));
2657 me
->bx
= fix(chromaticity_x(encoding
->blue
));
2658 me
->by
= fix(chromaticity_y(encoding
->blue
));
2660 modification_init(&me
->this);
2661 me
->this.chunk
= CHUNK_cHRM
;
2662 me
->this.modify_fn
= chrm_modify
;
2663 me
->this.add
= CHUNK_PLTE
;
2664 me
->this.next
= pm
->modifications
;
2665 pm
->modifications
= &me
->this;
2668 typedef struct srgb_modification
2670 png_modification
this;
2672 } srgb_modification
;
2675 srgb_modify(png_modifier
*pm
, png_modification
*me
, int add
)
2678 /* As above, ignore add and just make a new chunk */
2679 png_save_uint_32(pm
->buffer
, 1);
2680 png_save_uint_32(pm
->buffer
+4, CHUNK_sRGB
);
2681 pm
->buffer
[8] = ((srgb_modification
*)me
)->intent
;
2686 srgb_modification_init(srgb_modification
*me
, png_modifier
*pm
, png_byte intent
)
2688 modification_init(&me
->this);
2689 me
->this.chunk
= CHUNK_sBIT
;
2691 if (intent
<= 3) /* if valid, else *delete* sRGB chunks */
2693 me
->this.modify_fn
= srgb_modify
;
2694 me
->this.add
= CHUNK_PLTE
;
2695 me
->intent
= intent
;
2700 me
->this.modify_fn
= 0;
2705 me
->this.next
= pm
->modifications
;
2706 pm
->modifications
= &me
->this;
2709 typedef struct sbit_modification
2711 png_modification
this;
2713 } sbit_modification
;
2716 sbit_modify(png_modifier
*pm
, png_modification
*me
, int add
)
2718 png_byte sbit
= ((sbit_modification
*)me
)->sbit
;
2719 if (pm
->bit_depth
> sbit
)
2722 switch (pm
->colour_type
)
2742 png_error(pm
->this.pread
,
2743 "unexpected colour type in sBIT modification");
2746 png_save_uint_32(pm
->buffer
, cb
);
2747 png_save_uint_32(pm
->buffer
+4, CHUNK_sBIT
);
2750 (pm
->buffer
+8)[--cb
] = sbit
;
2756 /* Remove the sBIT chunk */
2757 pm
->buffer_count
= pm
->buffer_position
= 0;
2761 return 0; /* do nothing */
2765 sbit_modification_init(sbit_modification
*me
, png_modifier
*pm
, png_byte sbit
)
2767 modification_init(&me
->this);
2768 me
->this.chunk
= CHUNK_sBIT
;
2769 me
->this.modify_fn
= sbit_modify
;
2770 me
->this.add
= CHUNK_PLTE
;
2772 me
->this.next
= pm
->modifications
;
2773 pm
->modifications
= &me
->this;
2775 #endif /* PNG_READ_TRANSFORMS_SUPPORTED */
2777 /***************************** STANDARD PNG FILES *****************************/
2778 /* Standard files - write and save standard files. */
2779 /* There are two basic forms of standard images. Those which attempt to have
2780 * all the possible pixel values (not possible for 16bpp images, but a range of
2781 * values are produced) and those which have a range of image sizes. The former
2782 * are used for testing transforms, in particular gamma correction and bit
2783 * reduction and increase. The latter are reserved for testing the behavior of
2784 * libpng with respect to 'odd' image sizes - particularly small images where
2785 * rows become 1 byte and interlace passes disappear.
2787 * The first, most useful, set are the 'transform' images, the second set of
2788 * small images are the 'size' images.
2790 * The transform files are constructed with rows which fit into a 1024 byte row
2791 * buffer. This makes allocation easier below. Further regardless of the file
2792 * format every row has 128 pixels (giving 1024 bytes for 64bpp formats).
2794 * Files are stored with no gAMA or sBIT chunks, with a PLTE only when needed
2795 * and with an ID derived from the colour type, bit depth and interlace type
2796 * as above (FILEID). The width (128) and height (variable) are not stored in
2797 * the FILEID - instead the fields are set to 0, indicating a transform file.
2799 * The size files ar constructed with rows a maximum of 128 bytes wide, allowing
2800 * a maximum width of 16 pixels (for the 64bpp case.) They also have a maximum
2801 * height of 16 rows. The width and height are stored in the FILEID and, being
2802 * non-zero, indicate a size file.
2804 * For palette image (colour type 3) multiple transform images are stored with
2805 * the same bit depth to allow testing of more colour combinations -
2806 * particularly important for testing the gamma code because libpng uses a
2807 * different code path for palette images. For size images a single palette is
2811 /* Make a 'standard' palette. Because there are only 256 entries in a palette
2812 * (maximum) this actually makes a random palette in the hope that enough tests
2813 * will catch enough errors. (Note that the same palette isn't produced every
2814 * time for the same test - it depends on what previous tests have been run -
2815 * but a given set of arguments to pngvalid will always produce the same palette
2816 * at the same test! This is why pseudo-random number generators are useful for
2819 * The store must be open for write when this is called, otherwise an internal
2820 * error will occur. This routine contains its own magic number seed, so the
2821 * palettes generated don't change if there are intervening errors (changing the
2822 * calls to the store_mark seed.)
2824 static store_palette_entry
*
2825 make_standard_palette(png_store
* ps
, int npalette
, int do_tRNS
)
2827 static png_uint_32 palette_seed
[2] = { 0x87654321, 9 };
2830 png_byte values
[256][4];
2832 /* Always put in black and white plus the six primary and secondary colors.
2836 values
[i
][1] = (i
&1) ? 255 : 0;
2837 values
[i
][2] = (i
&2) ? 255 : 0;
2838 values
[i
][3] = (i
&4) ? 255 : 0;
2841 /* Then add 62 grays (one quarter of the remaining 256 slots). */
2844 png_byte random_bytes
[4];
2847 need
[0] = 0; /*got black*/
2848 memset(need
+1, 1, (sizeof need
)-2); /*need these*/
2849 need
[255] = 0; /*but not white*/
2857 make_four_random_bytes(palette_seed
, random_bytes
);
2861 b
= random_bytes
[--j
];
2871 /* Finally add 192 colors at random - don't worry about matches to things we
2872 * already have, chance is less than 1/65536. Don't worry about grays,
2873 * chance is the same, so we get a duplicate or extra gray less than 1 time
2877 make_four_random_bytes(palette_seed
, values
[i
]);
2879 /* Fill in the alpha values in the first byte. Just use all possible values
2880 * (0..255) in an apparently random order:
2883 store_palette_entry
*palette
;
2884 png_byte selector
[4];
2886 make_four_random_bytes(palette_seed
, selector
);
2889 for (i
=0; i
<256; ++i
)
2890 values
[i
][0] = (png_byte
)(i
^ selector
[0]);
2893 for (i
=0; i
<256; ++i
)
2894 values
[i
][0] = 255; /* no transparency/tRNS chunk */
2896 /* 'values' contains 256 ARGB values, but we only need 'npalette'.
2897 * 'npalette' will always be a power of 2: 2, 4, 16 or 256. In the low
2898 * bit depth cases select colors at random, else it is difficult to have
2899 * a set of low bit depth palette test with any chance of a reasonable
2900 * range of colors. Do this by randomly permuting values into the low
2901 * 'npalette' entries using an XOR mask generated here. This also
2902 * permutes the npalette == 256 case in a potentially useful way (there is
2903 * no relationship between palette index and the color value therein!)
2905 palette
= store_write_palette(ps
, npalette
);
2907 for (i
=0; i
<npalette
; ++i
)
2909 palette
[i
].alpha
= values
[i
^ selector
[1]][0];
2910 palette
[i
].red
= values
[i
^ selector
[1]][1];
2911 palette
[i
].green
= values
[i
^ selector
[1]][2];
2912 palette
[i
].blue
= values
[i
^ selector
[1]][3];
2919 /* Initialize a standard palette on a write stream. The 'do_tRNS' argument
2920 * indicates whether or not to also set the tRNS chunk.
2923 init_standard_palette(png_store
*ps
, png_structp pp
, png_infop pi
, int npalette
,
2926 store_palette_entry
*ppal
= make_standard_palette(ps
, npalette
, do_tRNS
);
2930 png_color palette
[256];
2932 /* Set all entries to detect overread errors. */
2933 for (i
=0; i
<npalette
; ++i
)
2935 palette
[i
].red
= ppal
[i
].red
;
2936 palette
[i
].green
= ppal
[i
].green
;
2937 palette
[i
].blue
= ppal
[i
].blue
;
2940 /* Just in case fill in the rest with detectable values: */
2942 palette
[i
].red
= palette
[i
].green
= palette
[i
].blue
= 42;
2944 png_set_PLTE(pp
, pi
, palette
, npalette
);
2952 /* Set all the entries, but skip trailing opaque entries */
2953 for (i
=j
=0; i
<npalette
; ++i
)
2954 if ((tRNS
[i
] = ppal
[i
].alpha
) < 255)
2957 /* Fill in the remainder with a detectable value: */
2962 png_set_tRNS(pp
, pi
, tRNS
, j
, 0/*color*/);
2966 /* The number of passes is related to the interlace type. There was no libpng
2967 * API to determine this prior to 1.5, so we need an inquiry function:
2970 npasses_from_interlace_type(png_structp pp
, int interlace_type
)
2972 switch (interlace_type
)
2975 png_error(pp
, "invalid interlace type");
2977 case PNG_INTERLACE_NONE
:
2980 case PNG_INTERLACE_ADAM7
:
2981 return PNG_INTERLACE_ADAM7_PASSES
;
2986 bit_size(png_structp pp
, png_byte colour_type
, png_byte bit_depth
)
2988 switch (colour_type
)
2990 default: png_error(pp
, "invalid color type");
2992 case 0: return bit_depth
;
2994 case 2: return 3*bit_depth
;
2996 case 3: return bit_depth
;
2998 case 4: return 2*bit_depth
;
3000 case 6: return 4*bit_depth
;
3004 #define TRANSFORM_WIDTH 128U
3005 #define TRANSFORM_ROWMAX (TRANSFORM_WIDTH*8U)
3006 #define SIZE_ROWMAX (16*8U) /* 16 pixels, max 8 bytes each - 128 bytes */
3007 #define STANDARD_ROWMAX TRANSFORM_ROWMAX /* The larger of the two */
3008 #define SIZE_HEIGHTMAX 16 /* Maximum range of size images */
3011 transform_rowsize(png_structp pp
, png_byte colour_type
, png_byte bit_depth
)
3013 return (TRANSFORM_WIDTH
* bit_size(pp
, colour_type
, bit_depth
)) / 8;
3016 /* transform_width(pp, colour_type, bit_depth) current returns the same number
3017 * every time, so just use a macro:
3019 #define transform_width(pp, colour_type, bit_depth) TRANSFORM_WIDTH
3022 transform_height(png_structp pp
, png_byte colour_type
, png_byte bit_depth
)
3024 switch (bit_size(pp
, colour_type
, bit_depth
))
3029 return 1; /* Total of 128 pixels */
3032 return 2; /* Total of 256 pixels/bytes */
3035 return 512; /* Total of 65536 pixels */
3039 return 512; /* 65536 pixels */
3043 return 2048;/* 4 x 65536 pixels. */
3044 # define TRANSFORM_HEIGHTMAX 2048
3047 return 0; /* Error, will be caught later */
3051 /* The following can only be defined here, now we have the definitions
3052 * of the transform image sizes.
3055 standard_width(png_structp pp
, png_uint_32 id
)
3057 png_uint_32 width
= WIDTH_FROM_ID(id
);
3061 width
= transform_width(pp
, COL_FROM_ID(id
), DEPTH_FROM_ID(id
));
3067 standard_height(png_structp pp
, png_uint_32 id
)
3069 png_uint_32 height
= HEIGHT_FROM_ID(id
);
3072 height
= transform_height(pp
, COL_FROM_ID(id
), DEPTH_FROM_ID(id
));
3078 standard_rowsize(png_structp pp
, png_uint_32 id
)
3080 png_uint_32 width
= standard_width(pp
, id
);
3082 /* This won't overflow: */
3083 width
*= bit_size(pp
, COL_FROM_ID(id
), DEPTH_FROM_ID(id
));
3084 return (width
+ 7) / 8;
3088 transform_row(png_structp pp
, png_byte buffer
[TRANSFORM_ROWMAX
],
3089 png_byte colour_type
, png_byte bit_depth
, png_uint_32 y
)
3091 png_uint_32 v
= y
<< 7;
3094 switch (bit_size(pp
, colour_type
, bit_depth
))
3097 while (i
<128/8) buffer
[i
] = v
& 0xff, v
+= 17, ++i
;
3101 while (i
<128/4) buffer
[i
] = v
& 0xff, v
+= 33, ++i
;
3105 while (i
<128/2) buffer
[i
] = v
& 0xff, v
+= 65, ++i
;
3109 /* 256 bytes total, 128 bytes in each row set as follows: */
3110 while (i
<128) buffer
[i
] = v
& 0xff, ++v
, ++i
;
3114 /* Generate all 65536 pixel values in order, which includes the 8 bit
3115 * GA case as well as the 16 bit G case.
3118 buffer
[2*i
] = (v
>>8) & 0xff, buffer
[2*i
+1] = v
& 0xff, ++v
, ++i
;
3123 /* 65535 pixels, but rotate the values. */
3126 /* Three bytes per pixel, r, g, b, make b by r^g */
3127 buffer
[3*i
+0] = (v
>> 8) & 0xff;
3128 buffer
[3*i
+1] = v
& 0xff;
3129 buffer
[3*i
+2] = ((v
>> 8) ^ v
) & 0xff;
3137 /* 65535 pixels, r, g, b, a; just replicate */
3140 buffer
[4*i
+0] = (v
>> 8) & 0xff;
3141 buffer
[4*i
+1] = v
& 0xff;
3142 buffer
[4*i
+2] = (v
>> 8) & 0xff;
3143 buffer
[4*i
+3] = v
& 0xff;
3151 /* y is maximum 2047, giving 4x65536 pixels, make 'r' increase by 1 at
3152 * each pixel, g increase by 257 (0x101) and 'b' by 0x1111:
3156 png_uint_32 t
= v
++;
3157 buffer
[6*i
+0] = (t
>> 8) & 0xff;
3158 buffer
[6*i
+1] = t
& 0xff;
3160 buffer
[6*i
+2] = (t
>> 8) & 0xff;
3161 buffer
[6*i
+3] = t
& 0xff;
3163 buffer
[6*i
+4] = (t
>> 8) & 0xff;
3164 buffer
[6*i
+5] = t
& 0xff;
3171 /* As above in the 32 bit case. */
3174 png_uint_32 t
= v
++;
3175 buffer
[8*i
+0] = (t
>> 8) & 0xff;
3176 buffer
[8*i
+1] = t
& 0xff;
3177 buffer
[8*i
+4] = (t
>> 8) & 0xff;
3178 buffer
[8*i
+5] = t
& 0xff;
3180 buffer
[8*i
+2] = (t
>> 8) & 0xff;
3181 buffer
[8*i
+3] = t
& 0xff;
3182 buffer
[8*i
+6] = (t
>> 8) & 0xff;
3183 buffer
[8*i
+7] = t
& 0xff;
3192 png_error(pp
, "internal error");
3195 /* This is just to do the right cast - could be changed to a function to check
3196 * 'bd' but there isn't much point.
3198 #define DEPTH(bd) ((png_byte)(1U << (bd)))
3200 /* Make a standardized image given a an image colour type, bit depth and
3201 * interlace type. The standard images have a very restricted range of
3202 * rows and heights and are used for testing transforms rather than image
3203 * layout details. See make_size_images below for a way to make images
3204 * that test odd sizes along with the libpng interlace handling.
3207 make_transform_image(png_store
* PNG_CONST ps
, png_byte PNG_CONST colour_type
,
3208 png_byte PNG_CONST bit_depth
, int palette_number
, int interlace_type
,
3209 png_const_charp name
)
3216 png_structp pp
= set_store_for_write(ps
, &pi
, name
);
3219 /* In the event of a problem return control to the Catch statement below
3220 * to do the clean up - it is not possible to 'return' directly from a Try
3226 h
= transform_height(pp
, colour_type
, bit_depth
);
3228 png_set_IHDR(pp
, pi
, transform_width(pp
, colour_type
, bit_depth
), h
,
3229 bit_depth
, colour_type
, interlace_type
,
3230 PNG_COMPRESSION_TYPE_BASE
, PNG_FILTER_TYPE_BASE
);
3232 #ifdef PNG_TEXT_SUPPORTED
3234 static char key
[] = "image name"; /* must be writeable */
3237 char copy
[FILE_NAME_SIZE
];
3239 /* Use a compressed text string to test the correct interaction of text
3240 * compression and IDAT compression.
3242 text
.compression
= PNG_TEXT_COMPRESSION_zTXt
;
3244 /* Yuck: the text must be writable! */
3245 pos
= safecat(copy
, sizeof copy
, 0, ps
->wname
);
3247 text
.text_length
= pos
;
3248 text
.itxt_length
= 0;
3252 png_set_text(pp
, pi
, &text
, 1);
3256 if (colour_type
== 3) /* palette */
3257 init_standard_palette(ps
, pp
, pi
, 1U << bit_depth
, 1/*do tRNS*/);
3259 png_write_info(pp
, pi
);
3261 if (png_get_rowbytes(pp
, pi
) !=
3262 transform_rowsize(pp
, colour_type
, bit_depth
))
3263 png_error(pp
, "row size incorrect");
3267 /* Somewhat confusingly this must be called *after* png_write_info
3268 * because if it is called before, the information in *pp has not been
3269 * updated to reflect the interlaced image.
3271 int npasses
= png_set_interlace_handling(pp
);
3274 if (npasses
!= npasses_from_interlace_type(pp
, interlace_type
))
3275 png_error(pp
, "write: png_set_interlace_handling failed");
3277 for (pass
=0; pass
<npasses
; ++pass
)
3283 png_byte buffer
[TRANSFORM_ROWMAX
];
3285 transform_row(pp
, buffer
, colour_type
, bit_depth
, y
);
3286 png_write_row(pp
, buffer
);
3291 #ifdef PNG_TEXT_SUPPORTED
3293 static char key
[] = "end marker";
3294 static char comment
[] = "end";
3297 /* Use a compressed text string to test the correct interaction of text
3298 * compression and IDAT compression.
3300 text
.compression
= PNG_TEXT_COMPRESSION_zTXt
;
3302 text
.text
= comment
;
3303 text
.text_length
= (sizeof comment
)-1;
3304 text
.itxt_length
= 0;
3308 png_set_text(pp
, pi
, &text
, 1);
3312 png_write_end(pp
, pi
);
3314 /* And store this under the appropriate id, then clean up. */
3315 store_storefile(ps
, FILEID(colour_type
, bit_depth
, palette_number
,
3316 interlace_type
, 0, 0, 0));
3318 store_write_reset(ps
);
3323 /* Use the png_store returned by the exception. This may help the compiler
3324 * because 'ps' is not used in this branch of the setjmp. Note that fault
3325 * and ps will always be the same value.
3327 store_write_reset(fault
);
3332 make_transform_images(png_store
*ps
)
3334 png_byte colour_type
= 0;
3335 png_byte bit_depth
= 0;
3336 int palette_number
= 0;
3338 /* This is in case of errors. */
3339 safecat(ps
->test
, sizeof ps
->test
, 0, "make standard images");
3341 /* Use next_format to enumerate all the combinations we test, including
3342 * generating multiple low bit depth palette images.
3344 while (next_format(&colour_type
, &bit_depth
, &palette_number
))
3348 for (interlace_type
= PNG_INTERLACE_NONE
;
3349 interlace_type
< PNG_INTERLACE_LAST
; ++interlace_type
)
3351 char name
[FILE_NAME_SIZE
];
3353 standard_name(name
, sizeof name
, 0, colour_type
, bit_depth
,
3354 palette_number
, interlace_type
, 0, 0, 0);
3355 make_transform_image(ps
, colour_type
, bit_depth
, palette_number
,
3356 interlace_type
, name
);
3361 /* The following two routines use the PNG interlace support macros from
3362 * png.h to interlace or deinterlace rows.
3365 interlace_row(png_bytep buffer
, png_const_bytep imageRow
,
3366 unsigned int pixel_size
, png_uint_32 w
, int pass
)
3368 png_uint_32 xin
, xout
, xstep
;
3370 /* Note that this can, trivially, be optimized to a memcpy on pass 7, the
3371 * code is presented this way to make it easier to understand. In practice
3372 * consult the code in the libpng source to see other ways of doing this.
3374 xin
= PNG_PASS_START_COL(pass
);
3375 xstep
= 1U<<PNG_PASS_COL_SHIFT(pass
);
3377 for (xout
=0; xin
<w
; xin
+=xstep
)
3379 pixel_copy(buffer
, xout
, imageRow
, xin
, pixel_size
);
3385 deinterlace_row(png_bytep buffer
, png_const_bytep row
,
3386 unsigned int pixel_size
, png_uint_32 w
, int pass
)
3388 /* The inverse of the above, 'row' is part of row 'y' of the output image,
3389 * in 'buffer'. The image is 'w' wide and this is pass 'pass', distribute
3390 * the pixels of row into buffer and return the number written (to allow
3391 * this to be checked).
3393 png_uint_32 xin
, xout
, xstep
;
3395 xout
= PNG_PASS_START_COL(pass
);
3396 xstep
= 1U<<PNG_PASS_COL_SHIFT(pass
);
3398 for (xin
=0; xout
<w
; xout
+=xstep
)
3400 pixel_copy(buffer
, xout
, row
, xin
, pixel_size
);
3405 /* Build a single row for the 'size' test images; this fills in only the
3406 * first bit_width bits of the sample row.
3409 size_row(png_byte buffer
[SIZE_ROWMAX
], png_uint_32 bit_width
, png_uint_32 y
)
3411 /* height is in the range 1 to 16, so: */
3412 y
= ((y
& 1) << 7) + ((y
& 2) << 6) + ((y
& 4) << 5) + ((y
& 8) << 4);
3413 /* the following ensures bits are set in small images: */
3416 while (bit_width
>= 8)
3417 *buffer
++ = (png_byte
)y
++, bit_width
-= 8;
3419 /* There may be up to 7 remaining bits, these go in the most significant
3424 png_uint_32 mask
= (1U<<(8-bit_width
))-1;
3425 *buffer
= (png_byte
)((*buffer
& mask
) | (y
& ~mask
));
3430 make_size_image(png_store
* PNG_CONST ps
, png_byte PNG_CONST colour_type
,
3431 png_byte PNG_CONST bit_depth
, int PNG_CONST interlace_type
,
3432 png_uint_32 PNG_CONST w
, png_uint_32 PNG_CONST h
,
3433 int PNG_CONST do_interlace
)
3441 unsigned int pixel_size
;
3443 /* Make a name and get an appropriate id for the store: */
3444 char name
[FILE_NAME_SIZE
];
3445 PNG_CONST png_uint_32 id
= FILEID(colour_type
, bit_depth
, 0/*palette*/,
3446 interlace_type
, w
, h
, do_interlace
);
3448 standard_name_from_id(name
, sizeof name
, 0, id
);
3449 pp
= set_store_for_write(ps
, &pi
, name
);
3451 /* In the event of a problem return control to the Catch statement below
3452 * to do the clean up - it is not possible to 'return' directly from a Try
3458 png_set_IHDR(pp
, pi
, w
, h
, bit_depth
, colour_type
, interlace_type
,
3459 PNG_COMPRESSION_TYPE_BASE
, PNG_FILTER_TYPE_BASE
);
3461 if (colour_type
== 3) /* palette */
3462 init_standard_palette(ps
, pp
, pi
, 1U << bit_depth
, 0/*do tRNS*/);
3464 png_write_info(pp
, pi
);
3466 /* Calculate the bit size, divide by 8 to get the byte size - this won't
3467 * overflow because we know the w values are all small enough even for
3468 * a system where 'unsigned int' is only 16 bits.
3470 pixel_size
= bit_size(pp
, colour_type
, bit_depth
);
3471 if (png_get_rowbytes(pp
, pi
) != ((w
* pixel_size
) + 7) / 8)
3472 png_error(pp
, "row size incorrect");
3476 int npasses
= npasses_from_interlace_type(pp
, interlace_type
);
3479 png_byte image
[16][SIZE_ROWMAX
];
3481 /* To help consistent error detection make the parts of this buffer
3482 * that aren't set below all '1':
3484 memset(image
, 0xff, sizeof image
);
3486 if (!do_interlace
&& npasses
!= png_set_interlace_handling(pp
))
3487 png_error(pp
, "write: png_set_interlace_handling failed");
3489 /* Prepare the whole image first to avoid making it 7 times: */
3491 size_row(image
[y
], w
* pixel_size
, y
);
3493 for (pass
=0; pass
<npasses
; ++pass
)
3495 /* The following two are for checking the macros: */
3496 PNG_CONST png_uint_32 wPass
= PNG_PASS_COLS(w
, pass
);
3498 /* If do_interlace is set we don't call png_write_row for every
3499 * row because some of them are empty. In fact, for a 1x1 image,
3500 * most of them are empty!
3504 png_const_bytep row
= image
[y
];
3505 png_byte tempRow
[SIZE_ROWMAX
];
3507 /* If do_interlace *and* the image is interlaced we
3508 * need a reduced interlace row; this may be reduced
3511 if (do_interlace
&& interlace_type
== PNG_INTERLACE_ADAM7
)
3513 /* The row must not be written if it doesn't exist, notice
3514 * that there are two conditions here, either the row isn't
3515 * ever in the pass or the row would be but isn't wide
3516 * enough to contribute any pixels. In fact the wPass test
3517 * can be used to skip the whole y loop in this case.
3519 if (PNG_ROW_IN_INTERLACE_PASS(y
, pass
) && wPass
> 0)
3521 /* Set to all 1's for error detection (libpng tends to
3522 * set unset things to 0).
3524 memset(tempRow
, 0xff, sizeof tempRow
);
3525 interlace_row(tempRow
, row
, pixel_size
, w
, pass
);
3532 /* Only get to here if the row has some pixels in it. */
3533 png_write_row(pp
, row
);
3538 png_write_end(pp
, pi
);
3540 /* And store this under the appropriate id, then clean up. */
3541 store_storefile(ps
, id
);
3543 store_write_reset(ps
);
3548 /* Use the png_store returned by the exception. This may help the compiler
3549 * because 'ps' is not used in this branch of the setjmp. Note that fault
3550 * and ps will always be the same value.
3552 store_write_reset(fault
);
3557 make_size(png_store
* PNG_CONST ps
, png_byte PNG_CONST colour_type
, int bdlo
,
3560 for (; bdlo
<= bdhi
; ++bdlo
)
3564 for (width
= 1; width
<= 16; ++width
)
3568 for (height
= 1; height
<= 16; ++height
)
3570 /* The four combinations of DIY interlace and interlace or not -
3571 * no interlace + DIY should be identical to no interlace with
3574 make_size_image(ps
, colour_type
, DEPTH(bdlo
), PNG_INTERLACE_NONE
,
3576 make_size_image(ps
, colour_type
, DEPTH(bdlo
), PNG_INTERLACE_NONE
,
3578 make_size_image(ps
, colour_type
, DEPTH(bdlo
), PNG_INTERLACE_ADAM7
,
3580 make_size_image(ps
, colour_type
, DEPTH(bdlo
), PNG_INTERLACE_ADAM7
,
3588 make_size_images(png_store
*ps
)
3590 /* This is in case of errors. */
3591 safecat(ps
->test
, sizeof ps
->test
, 0, "make size images");
3593 /* Arguments are colour_type, low bit depth, high bit depth
3595 make_size(ps
, 0, 0, WRITE_BDHI
);
3596 make_size(ps
, 2, 3, WRITE_BDHI
);
3597 make_size(ps
, 3, 0, 3 /*palette: max 8 bits*/);
3598 make_size(ps
, 4, 3, WRITE_BDHI
);
3599 make_size(ps
, 6, 3, WRITE_BDHI
);
3602 /* Return a row based on image id and 'y' for checking: */
3604 standard_row(png_structp pp
, png_byte std
[STANDARD_ROWMAX
], png_uint_32 id
,
3607 if (WIDTH_FROM_ID(id
) == 0)
3608 transform_row(pp
, std
, COL_FROM_ID(id
), DEPTH_FROM_ID(id
), y
);
3610 size_row(std
, WIDTH_FROM_ID(id
) * bit_size(pp
, COL_FROM_ID(id
),
3611 DEPTH_FROM_ID(id
)), y
);
3614 /* Tests - individual test cases */
3615 /* Like 'make_standard' but errors are deliberately introduced into the calls
3616 * to ensure that they get detected - it should not be possible to write an
3617 * invalid image with libpng!
3619 #ifdef PNG_WARNINGS_SUPPORTED
3621 sBIT0_error_fn(png_structp pp
, png_infop pi
)
3623 /* 0 is invalid... */
3625 bad
.red
= bad
.green
= bad
.blue
= bad
.gray
= bad
.alpha
= 0;
3626 png_set_sBIT(pp
, pi
, &bad
);
3630 sBIT_error_fn(png_structp pp
, png_infop pi
)
3635 if (png_get_color_type(pp
, pi
) == PNG_COLOR_TYPE_PALETTE
)
3639 bit_depth
= png_get_bit_depth(pp
, pi
);
3641 /* Now we know the bit depth we can easily generate an invalid sBIT entry */
3642 bad
.red
= bad
.green
= bad
.blue
= bad
.gray
= bad
.alpha
=
3643 (png_byte
)(bit_depth
+1);
3644 png_set_sBIT(pp
, pi
, &bad
);
3647 static PNG_CONST
struct
3649 void (*fn
)(png_structp
, png_infop
);
3650 PNG_CONST
char *msg
;
3651 unsigned int warning
:1; /* the error is a warning... */
3654 /* no warnings makes these errors undetectable. */
3655 { sBIT0_error_fn
, "sBIT(0): failed to detect error", 1 },
3656 { sBIT_error_fn
, "sBIT(too big): failed to detect error", 1 },
3660 make_error(png_store
* volatile ps
, png_byte PNG_CONST colour_type
,
3661 png_byte bit_depth
, int interlace_type
, int test
, png_const_charp name
)
3670 pp
= set_store_for_write(ps
, &pi
, name
);
3675 png_set_IHDR(pp
, pi
, transform_width(pp
, colour_type
, bit_depth
),
3676 transform_height(pp
, colour_type
, bit_depth
), bit_depth
, colour_type
,
3677 interlace_type
, PNG_COMPRESSION_TYPE_BASE
, PNG_FILTER_TYPE_BASE
);
3679 if (colour_type
== 3) /* palette */
3680 init_standard_palette(ps
, pp
, pi
, 1U << bit_depth
, 0/*do tRNS*/);
3682 /* Time for a few errors; these are in various optional chunks, the
3683 * standard tests test the standard chunks pretty well.
3685 # define exception__prev exception_prev_1
3686 # define exception__env exception_env_1
3689 /* Expect this to throw: */
3690 ps
->expect_error
= !error_test
[test
].warning
;
3691 ps
->expect_warning
= error_test
[test
].warning
;
3692 ps
->saw_warning
= 0;
3693 error_test
[test
].fn(pp
, pi
);
3695 /* Normally the error is only detected here: */
3696 png_write_info(pp
, pi
);
3698 /* And handle the case where it was only a warning: */
3699 if (ps
->expect_warning
&& ps
->saw_warning
)
3702 /* If we get here there is a problem, we have success - no error or
3703 * no warning - when we shouldn't have success. Log an error.
3705 store_log(ps
, pp
, error_test
[test
].msg
, 1 /*error*/);
3709 ps
= fault
; /* expected exit, make sure ps is not clobbered */
3710 #undef exception__prev
3711 #undef exception__env
3713 /* And clear these flags */
3714 ps
->expect_error
= 0;
3715 ps
->expect_warning
= 0;
3717 /* Now write the whole image, just to make sure that the detected, or
3718 * undetected, errro has not created problems inside libpng.
3720 if (png_get_rowbytes(pp
, pi
) !=
3721 transform_rowsize(pp
, colour_type
, bit_depth
))
3722 png_error(pp
, "row size incorrect");
3726 png_uint_32 h
= transform_height(pp
, colour_type
, bit_depth
);
3727 int npasses
= png_set_interlace_handling(pp
);
3730 if (npasses
!= npasses_from_interlace_type(pp
, interlace_type
))
3731 png_error(pp
, "write: png_set_interlace_handling failed");
3733 for (pass
=0; pass
<npasses
; ++pass
)
3739 png_byte buffer
[TRANSFORM_ROWMAX
];
3741 transform_row(pp
, buffer
, colour_type
, bit_depth
, y
);
3742 png_write_row(pp
, buffer
);
3747 png_write_end(pp
, pi
);
3749 /* The following deletes the file that was just written. */
3750 store_write_reset(ps
);
3755 store_write_reset(fault
);
3760 make_errors(png_modifier
* PNG_CONST pm
, png_byte PNG_CONST colour_type
,
3761 int bdlo
, int PNG_CONST bdhi
)
3763 for (; bdlo
<= bdhi
; ++bdlo
)
3767 for (interlace_type
= PNG_INTERLACE_NONE
;
3768 interlace_type
< PNG_INTERLACE_LAST
; ++interlace_type
)
3771 char name
[FILE_NAME_SIZE
];
3773 standard_name(name
, sizeof name
, 0, colour_type
, 1<<bdlo
, 0,
3774 interlace_type
, 0, 0, 0);
3776 for (test
=0; test
<(sizeof error_test
)/(sizeof error_test
[0]); ++test
)
3778 make_error(&pm
->this, colour_type
, DEPTH(bdlo
), interlace_type
,
3787 return 1; /* keep going */
3792 perform_error_test(png_modifier
*pm
)
3794 #ifdef PNG_WARNINGS_SUPPORTED /* else there are no cases that work! */
3795 /* Need to do this here because we just write in this test. */
3796 safecat(pm
->this.test
, sizeof pm
->this.test
, 0, "error test");
3798 if (!make_errors(pm
, 0, 0, WRITE_BDHI
))
3801 if (!make_errors(pm
, 2, 3, WRITE_BDHI
))
3804 if (!make_errors(pm
, 3, 0, 3))
3807 if (!make_errors(pm
, 4, 3, WRITE_BDHI
))
3810 if (!make_errors(pm
, 6, 3, WRITE_BDHI
))
3817 /* This is just to validate the internal PNG formatting code - if this fails
3818 * then the warning messages the library outputs will probably be garbage.
3821 perform_formatting_test(png_store
*volatile ps
)
3823 #ifdef PNG_TIME_RFC1123_SUPPORTED
3824 /* The handle into the formatting code is the RFC1123 support; this test does
3825 * nothing if that is compiled out.
3831 png_const_charp correct
= "29 Aug 2079 13:53:60 +0000";
3832 png_const_charp result
;
3836 pp
= set_store_for_write(ps
, NULL
, "libpng formatting test");
3842 /* Arbitrary settings: */
3848 pt
.second
= 60; /* a leap second */
3850 result
= png_convert_to_rfc1123(pp
, &pt
);
3853 png_error(pp
, "png_convert_to_rfc1123 failed");
3855 if (strcmp(result
, correct
) != 0)
3860 pos
= safecat(msg
, sizeof msg
, pos
, "png_convert_to_rfc1123(");
3861 pos
= safecat(msg
, sizeof msg
, pos
, correct
);
3862 pos
= safecat(msg
, sizeof msg
, pos
, ") returned: '");
3863 pos
= safecat(msg
, sizeof msg
, pos
, result
);
3864 pos
= safecat(msg
, sizeof msg
, pos
, "'");
3869 store_write_reset(ps
);
3874 store_write_reset(fault
);
3881 /* Because we want to use the same code in both the progressive reader and the
3882 * sequential reader it is necessary to deal with the fact that the progressive
3883 * reader callbacks only have one parameter (png_get_progressive_ptr()), so this
3884 * must contain all the test parameters and all the local variables directly
3885 * accessible to the sequential reader implementation.
3887 * The technique adopted is to reinvent part of what Dijkstra termed a
3888 * 'display'; an array of pointers to the stack frames of enclosing functions so
3889 * that a nested function definition can access the local (C auto) variables of
3890 * the functions that contain its definition. In fact C provides the first
3891 * pointer (the local variables - the stack frame pointer) and the last (the
3892 * global variables - the BCPL global vector typically implemented as global
3893 * addresses), this code requires one more pointer to make the display - the
3894 * local variables (and function call parameters) of the function that actually
3895 * invokes either the progressive or sequential reader.
3897 * Perhaps confusingly this technique is confounded with classes - the
3898 * 'standard_display' defined here is sub-classed as the 'gamma_display' below.
3899 * A gamma_display is a standard_display, taking advantage of the ANSI-C
3900 * requirement that the pointer to the first member of a structure must be the
3901 * same as the pointer to the structure. This allows us to reuse standard_
3902 * functions in the gamma test code; something that could not be done with
3905 typedef struct standard_display
3907 png_store
* ps
; /* Test parameters (passed to the function) */
3908 png_byte colour_type
;
3910 png_byte red_sBIT
; /* Input data sBIT values. */
3911 png_byte green_sBIT
;
3913 png_byte alpha_sBIT
;
3915 png_uint_32 id
; /* Calculated file ID */
3916 png_uint_32 w
; /* Width of image */
3917 png_uint_32 h
; /* Height of image */
3918 int npasses
; /* Number of interlaced passes */
3919 png_uint_32 pixel_size
; /* Width of one pixel in bits */
3920 png_uint_32 bit_width
; /* Width of output row in bits */
3921 size_t cbRow
; /* Bytes in a row of the output image */
3922 int do_interlace
; /* Do interlacing internally */
3923 int is_transparent
; /* Transparency information was present. */
3924 int speed
; /* Doing a speed test */
3925 int use_update_info
;/* Call update_info, not start_image */
3931 } transparent
; /* The transparent color, if set. */
3932 int npalette
; /* Number of entries in the palette. */
3938 standard_display_init(standard_display
*dp
, png_store
* ps
, png_uint_32 id
,
3939 int do_interlace
, int use_update_info
)
3941 memset(dp
, 0, sizeof *dp
);
3944 dp
->colour_type
= COL_FROM_ID(id
);
3945 dp
->bit_depth
= DEPTH_FROM_ID(id
);
3946 if (dp
->colour_type
== 3)
3947 dp
->red_sBIT
= dp
->blue_sBIT
= dp
->green_sBIT
= dp
->alpha_sBIT
= 8;
3949 dp
->red_sBIT
= dp
->blue_sBIT
= dp
->green_sBIT
= dp
->alpha_sBIT
=
3951 dp
->interlace_type
= INTERLACE_FROM_ID(id
);
3953 /* All the rest are filled in after the read_info: */
3960 dp
->do_interlace
= do_interlace
;
3961 dp
->is_transparent
= 0;
3962 dp
->speed
= ps
->speed
;
3963 dp
->use_update_info
= use_update_info
;
3965 /* Preset the transparent color to black: */
3966 memset(&dp
->transparent
, 0, sizeof dp
->transparent
);
3967 /* Preset the palette to full intensity/opaque througout: */
3968 memset(dp
->palette
, 0xff, sizeof dp
->palette
);
3971 /* Initialize the palette fields - this must be done later because the palette
3972 * comes from the particular png_store_file that is selected.
3975 standard_palette_init(standard_display
*dp
)
3977 store_palette_entry
*palette
= store_current_palette(dp
->ps
, &dp
->npalette
);
3979 /* The remaining entries remain white/opaque. */
3980 if (dp
->npalette
> 0)
3982 int i
= dp
->npalette
;
3983 memcpy(dp
->palette
, palette
, i
* sizeof *palette
);
3985 /* Check for a non-opaque palette entry: */
3987 if (palette
[i
].alpha
< 255)
3991 /* GCC can't handle the more obviously optimizable version. */
3993 dp
->is_transparent
= 1;
3995 dp
->is_transparent
= 0;
3997 dp
->is_transparent
= (i
>= 0);
4002 /* Utility to read the palette from the PNG file and convert it into
4003 * store_palette format. This returns 1 if there is any transparency in the
4004 * palette (it does not check for a transparent colour in the non-palette case.)
4007 read_palette(store_palette palette
, int *npalette
, png_structp pp
, png_infop pi
)
4010 png_bytep trans_alpha
;
4016 if (png_get_PLTE(pp
, pi
, &pal
, npalette
) & PNG_INFO_PLTE
)
4020 if (i
<= 0 || i
> 256)
4021 png_error(pp
, "validate: invalid PLTE count");
4025 palette
[i
].red
= pal
[i
].red
;
4026 palette
[i
].green
= pal
[i
].green
;
4027 palette
[i
].blue
= pal
[i
].blue
;
4030 /* Mark the remainder of the entries with a flag value (other than
4031 * white/opaque which is the flag value stored above.)
4033 memset(palette
+ *npalette
, 126, (256-*npalette
) * sizeof *palette
);
4036 else /* !png_get_PLTE */
4038 if (*npalette
!= (-1))
4039 png_error(pp
, "validate: invalid PLTE result");
4040 /* But there is no palette, so record this: */
4042 memset(palette
, 113, sizeof palette
);
4046 num
= 2; /* force error below */
4047 if ((png_get_tRNS(pp
, pi
, &trans_alpha
, &num
, 0) & PNG_INFO_tRNS
) != 0 &&
4048 (trans_alpha
!= NULL
|| num
!= 1/*returns 1 for a transparent color*/) &&
4049 /* Oops, if a palette tRNS gets expanded png_read_update_info (at least so
4050 * far as 1.5.4) does not remove the trans_alpha pointer, only num_trans,
4051 * so in the above call we get a success, we get a pointer (who knows what
4052 * to) and we get num_trans == 0:
4054 !(trans_alpha
!= NULL
&& num
== 0)) /* TODO: fix this in libpng. */
4058 /* Any of these are crash-worthy - given the implementation of
4059 * png_get_tRNS up to 1.5 an app won't crash if it just checks the
4060 * result above and fails to check that the variables it passed have
4061 * actually been filled in! Note that if the app were to pass the
4062 * last, png_color_16p, variable too it couldn't rely on this.
4064 if (trans_alpha
== NULL
|| num
<= 0 || num
> 256 || num
> *npalette
)
4065 png_error(pp
, "validate: unexpected png_get_tRNS (palette) result");
4067 for (i
=0; i
<num
; ++i
)
4068 palette
[i
].alpha
= trans_alpha
[i
];
4070 for (num
=*npalette
; i
<num
; ++i
)
4071 palette
[i
].alpha
= 255;
4074 palette
[i
].alpha
= 33; /* flag value */
4076 return 1; /* transparency */
4081 /* No palette transparency - just set the alpha channel to opaque. */
4084 for (i
=0, num
=*npalette
; i
<num
; ++i
)
4085 palette
[i
].alpha
= 255;
4088 palette
[i
].alpha
= 55; /* flag value */
4090 return 0; /* no transparency */
4094 /* Utility to validate the palette if it should not have changed (the
4095 * non-transform case).
4098 standard_palette_validate(standard_display
*dp
, png_structp pp
, png_infop pi
)
4101 store_palette palette
;
4103 if (read_palette(palette
, &npalette
, pp
, pi
) != dp
->is_transparent
)
4104 png_error(pp
, "validate: palette transparency changed");
4106 if (npalette
!= dp
->npalette
)
4111 pos
= safecat(msg
, sizeof msg
, pos
, "validate: palette size changed: ");
4112 pos
= safecatn(msg
, sizeof msg
, pos
, dp
->npalette
);
4113 pos
= safecat(msg
, sizeof msg
, pos
, " -> ");
4114 pos
= safecatn(msg
, sizeof msg
, pos
, npalette
);
4119 int i
= npalette
; /* npalette is aliased */
4122 if (palette
[i
].red
!= dp
->palette
[i
].red
||
4123 palette
[i
].green
!= dp
->palette
[i
].green
||
4124 palette
[i
].blue
!= dp
->palette
[i
].blue
||
4125 palette
[i
].alpha
!= dp
->palette
[i
].alpha
)
4126 png_error(pp
, "validate: PLTE or tRNS chunk changed");
4130 /* By passing a 'standard_display' the progressive callbacks can be used
4131 * directly by the sequential code, the functions suffixed "_imp" are the
4132 * implementations, the functions without the suffix are the callbacks.
4134 * The code for the info callback is split into two because this callback calls
4135 * png_read_update_info or png_start_read_image and what gets called depends on
4136 * whether the info needs updating (we want to test both calls in pngvalid.)
4139 standard_info_part1(standard_display
*dp
, png_structp pp
, png_infop pi
)
4141 if (png_get_bit_depth(pp
, pi
) != dp
->bit_depth
)
4142 png_error(pp
, "validate: bit depth changed");
4144 if (png_get_color_type(pp
, pi
) != dp
->colour_type
)
4145 png_error(pp
, "validate: color type changed");
4147 if (png_get_filter_type(pp
, pi
) != PNG_FILTER_TYPE_BASE
)
4148 png_error(pp
, "validate: filter type changed");
4150 if (png_get_interlace_type(pp
, pi
) != dp
->interlace_type
)
4151 png_error(pp
, "validate: interlacing changed");
4153 if (png_get_compression_type(pp
, pi
) != PNG_COMPRESSION_TYPE_BASE
)
4154 png_error(pp
, "validate: compression type changed");
4156 dp
->w
= png_get_image_width(pp
, pi
);
4158 if (dp
->w
!= standard_width(pp
, dp
->id
))
4159 png_error(pp
, "validate: image width changed");
4161 dp
->h
= png_get_image_height(pp
, pi
);
4163 if (dp
->h
!= standard_height(pp
, dp
->id
))
4164 png_error(pp
, "validate: image height changed");
4166 /* Record (but don't check at present) the input sBIT according to the colour
4170 png_color_8p sBIT
= 0;
4172 if (png_get_sBIT(pp
, pi
, &sBIT
) & PNG_INFO_sBIT
)
4174 int sBIT_invalid
= 0;
4177 png_error(pp
, "validate: unexpected png_get_sBIT result");
4179 if (dp
->colour_type
& PNG_COLOR_MASK_COLOR
)
4181 if (sBIT
->red
== 0 || sBIT
->red
> dp
->bit_depth
)
4184 dp
->red_sBIT
= sBIT
->red
;
4186 if (sBIT
->green
== 0 || sBIT
->green
> dp
->bit_depth
)
4189 dp
->green_sBIT
= sBIT
->green
;
4191 if (sBIT
->blue
== 0 || sBIT
->blue
> dp
->bit_depth
)
4194 dp
->blue_sBIT
= sBIT
->blue
;
4199 if (sBIT
->gray
== 0 || sBIT
->gray
> dp
->bit_depth
)
4202 dp
->blue_sBIT
= dp
->green_sBIT
= dp
->red_sBIT
= sBIT
->gray
;
4205 /* All 8 bits in tRNS for a palette image are significant - see the
4208 if (dp
->colour_type
& PNG_COLOR_MASK_ALPHA
)
4210 if (sBIT
->alpha
== 0 || sBIT
->alpha
> dp
->bit_depth
)
4213 dp
->alpha_sBIT
= sBIT
->alpha
;
4217 png_error(pp
, "validate: sBIT value out of range");
4221 /* Important: this is validating the value *before* any transforms have been
4222 * put in place. It doesn't matter for the standard tests, where there are
4223 * no transforms, but it does for other tests where rowbytes may change after
4224 * png_read_update_info.
4226 if (png_get_rowbytes(pp
, pi
) != standard_rowsize(pp
, dp
->id
))
4227 png_error(pp
, "validate: row size changed");
4229 /* Validate the colour type 3 palette (this can be present on other color
4232 standard_palette_validate(dp
, pp
, pi
);
4234 /* In any case always check for a tranparent color (notice that the
4235 * colour type 3 case must not give a successful return on the get_tRNS call
4236 * with these arguments!)
4239 png_color_16p trans_color
= 0;
4241 if (png_get_tRNS(pp
, pi
, 0, 0, &trans_color
) & PNG_INFO_tRNS
)
4243 if (trans_color
== 0)
4244 png_error(pp
, "validate: unexpected png_get_tRNS (color) result");
4246 switch (dp
->colour_type
)
4249 dp
->transparent
.red
= dp
->transparent
.green
= dp
->transparent
.blue
=
4251 dp
->is_transparent
= 1;
4255 dp
->transparent
.red
= trans_color
->red
;
4256 dp
->transparent
.green
= trans_color
->green
;
4257 dp
->transparent
.blue
= trans_color
->blue
;
4258 dp
->is_transparent
= 1;
4262 /* Not expected because it should result in the array case
4265 png_error(pp
, "validate: unexpected png_get_tRNS result");
4269 png_error(pp
, "validate: invalid tRNS chunk with alpha image");
4274 /* Read the number of passes - expected to match the value used when
4275 * creating the image (interlaced or not). This has the side effect of
4276 * turning on interlace handling (if do_interlace is not set.)
4278 dp
->npasses
= npasses_from_interlace_type(pp
, dp
->interlace_type
);
4279 if (!dp
->do_interlace
&& dp
->npasses
!= png_set_interlace_handling(pp
))
4280 png_error(pp
, "validate: file changed interlace type");
4282 /* Caller calls png_read_update_info or png_start_read_image now, then calls
4287 /* This must be called *after* the png_read_update_info call to get the correct
4288 * 'rowbytes' value, otherwise png_get_rowbytes will refer to the untransformed
4292 standard_info_part2(standard_display
*dp
, png_structp pp
, png_infop pi
,
4295 /* Record cbRow now that it can be found. */
4296 dp
->pixel_size
= bit_size(pp
, png_get_color_type(pp
, pi
),
4297 png_get_bit_depth(pp
, pi
));
4298 dp
->bit_width
= png_get_image_width(pp
, pi
) * dp
->pixel_size
;
4299 dp
->cbRow
= png_get_rowbytes(pp
, pi
);
4301 /* Validate the rowbytes here again. */
4302 if (dp
->cbRow
!= (dp
->bit_width
+7)/8)
4303 png_error(pp
, "bad png_get_rowbytes calculation");
4305 /* Then ensure there is enough space for the output image(s). */
4306 store_ensure_image(dp
->ps
, pp
, nImages
, dp
->cbRow
, dp
->h
);
4310 standard_info_imp(standard_display
*dp
, png_structp pp
, png_infop pi
,
4313 /* Note that the validation routine has the side effect of turning on
4314 * interlace handling in the subsequent code.
4316 standard_info_part1(dp
, pp
, pi
);
4318 /* And the info callback has to call this (or png_read_update_info - see
4319 * below in the png_modifier code for that variant.
4321 if (dp
->use_update_info
)
4323 /* For debugging the effect of multiple calls: */
4324 int i
= dp
->use_update_info
;
4326 png_read_update_info(pp
, pi
);
4330 png_start_read_image(pp
);
4332 /* Validate the height, width and rowbytes plus ensure that sufficient buffer
4333 * exists for decoding the image.
4335 standard_info_part2(dp
, pp
, pi
, nImages
);
4339 standard_info(png_structp pp
, png_infop pi
)
4341 standard_display
*dp
= voidcast(standard_display
*,
4342 png_get_progressive_ptr(pp
));
4344 /* Call with nImages==1 because the progressive reader can only produce one
4347 standard_info_imp(dp
, pp
, pi
, 1 /*only one image*/);
4351 progressive_row(png_structp pp
, png_bytep new_row
, png_uint_32 y
, int pass
)
4353 PNG_CONST standard_display
*dp
= voidcast(standard_display
*,
4354 png_get_progressive_ptr(pp
));
4356 /* When handling interlacing some rows will be absent in each pass, the
4357 * callback still gets called, but with a NULL pointer. This is checked
4358 * in the 'else' clause below. We need our own 'cbRow', but we can't call
4359 * png_get_rowbytes because we got no info structure.
4361 if (new_row
!= NULL
)
4365 /* In the case where the reader doesn't do the interlace it gives
4366 * us the y in the sub-image:
4368 if (dp
->do_interlace
&& dp
->interlace_type
== PNG_INTERLACE_ADAM7
)
4370 #ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED
4371 /* Use this opportunity to validate the png 'current' APIs: */
4372 if (y
!= png_get_current_row_number(pp
))
4373 png_error(pp
, "png_get_current_row_number is broken");
4375 if (pass
!= png_get_current_pass_number(pp
))
4376 png_error(pp
, "png_get_current_pass_number is broken");
4379 y
= PNG_ROW_FROM_PASS_ROW(y
, pass
);
4382 /* Validate this just in case. */
4384 png_error(pp
, "invalid y to progressive row callback");
4386 row
= store_image_row(dp
->ps
, pp
, 0, y
);
4388 #ifdef PNG_READ_INTERLACING_SUPPORTED
4389 /* Combine the new row into the old: */
4390 if (dp
->do_interlace
)
4392 if (dp
->interlace_type
== PNG_INTERLACE_ADAM7
)
4393 deinterlace_row(row
, new_row
, dp
->pixel_size
, dp
->w
, pass
);
4395 row_copy(row
, new_row
, dp
->pixel_size
* dp
->w
);
4398 png_progressive_combine_row(pp
, row
, new_row
);
4399 } else if (dp
->interlace_type
== PNG_INTERLACE_ADAM7
&&
4400 PNG_ROW_IN_INTERLACE_PASS(y
, pass
) &&
4401 PNG_PASS_COLS(dp
->w
, pass
) > 0)
4402 png_error(pp
, "missing row in progressive de-interlacing");
4403 #endif /* PNG_READ_INTERLACING_SUPPORTED */
4407 sequential_row(standard_display
*dp
, png_structp pp
, png_infop pi
,
4408 PNG_CONST
int iImage
, PNG_CONST
int iDisplay
)
4410 PNG_CONST
int npasses
= dp
->npasses
;
4411 PNG_CONST
int do_interlace
= dp
->do_interlace
&&
4412 dp
->interlace_type
== PNG_INTERLACE_ADAM7
;
4413 PNG_CONST png_uint_32 height
= standard_height(pp
, dp
->id
);
4414 PNG_CONST png_uint_32 width
= standard_width(pp
, dp
->id
);
4415 PNG_CONST png_store
* ps
= dp
->ps
;
4418 for (pass
=0; pass
<npasses
; ++pass
)
4421 png_uint_32 wPass
= PNG_PASS_COLS(width
, pass
);
4423 for (y
=0; y
<height
; ++y
)
4427 /* wPass may be zero or this row may not be in this pass.
4428 * png_read_row must not be called in either case.
4430 if (wPass
> 0 && PNG_ROW_IN_INTERLACE_PASS(y
, pass
))
4432 /* Read the row into a pair of temporary buffers, then do the
4433 * merge here into the output rows.
4435 png_byte row
[STANDARD_ROWMAX
], display
[STANDARD_ROWMAX
];
4437 /* The following aids (to some extent) error detection - we can
4438 * see where png_read_row wrote. Use opposite values in row and
4439 * display to make this easier. Don't use 0xff (which is used in
4440 * the image write code to fill unused bits) or 0 (which is a
4441 * likely value to overwrite unused bits with).
4443 memset(row
, 0xc5, sizeof row
);
4444 memset(display
, 0x5c, sizeof display
);
4446 png_read_row(pp
, row
, display
);
4449 deinterlace_row(store_image_row(ps
, pp
, iImage
, y
), row
,
4450 dp
->pixel_size
, dp
->w
, pass
);
4453 deinterlace_row(store_image_row(ps
, pp
, iDisplay
, y
), display
,
4454 dp
->pixel_size
, dp
->w
, pass
);
4459 iImage
>= 0 ? store_image_row(ps
, pp
, iImage
, y
) : NULL
,
4460 iDisplay
>= 0 ? store_image_row(ps
, pp
, iDisplay
, y
) : NULL
);
4464 /* And finish the read operation (only really necessary if the caller wants
4465 * to find additional data in png_info from chunks after the last IDAT.)
4467 png_read_end(pp
, pi
);
4471 standard_row_validate(standard_display
*dp
, png_structp pp
,
4472 int iImage
, int iDisplay
, png_uint_32 y
)
4475 png_byte std
[STANDARD_ROWMAX
];
4477 /* The row must be pre-initialized to the magic number here for the size
4480 memset(std
, 178, sizeof std
);
4481 standard_row(pp
, std
, dp
->id
, y
);
4483 /* At the end both the 'row' and 'display' arrays should end up identical.
4484 * In earlier passes 'row' will be partially filled in, with only the pixels
4485 * that have been read so far, but 'display' will have those pixels
4486 * replicated to fill the unread pixels while reading an interlaced image.
4487 #if PNG_LIBPNG_VER < 10506
4488 * The side effect inside the libpng sequential reader is that the 'row'
4489 * array retains the correct values for unwritten pixels within the row
4490 * bytes, while the 'display' array gets bits off the end of the image (in
4491 * the last byte) trashed. Unfortunately in the progressive reader the
4492 * row bytes are always trashed, so we always do a pixel_cmp here even though
4493 * a memcmp of all cbRow bytes will succeed for the sequential reader.
4497 (where
= pixel_cmp(std
, store_image_row(dp
->ps
, pp
, iImage
, y
),
4498 dp
->bit_width
)) != 0)
4501 sprintf(msg
, "PNG image row[%d][%d] changed from %.2x to %.2x", y
,
4502 where
-1, std
[where
-1],
4503 store_image_row(dp
->ps
, pp
, iImage
, y
)[where
-1]);
4507 #if PNG_LIBPNG_VER < 10506
4508 /* In this case use pixel_cmp because we need to compare a partial
4509 * byte at the end of the row if the row is not an exact multiple
4510 * of 8 bits wide. (This is fixed in libpng-1.5.6 and pixel_cmp is
4511 * changed to match!)
4514 if (iDisplay
>= 0 &&
4515 (where
= pixel_cmp(std
, store_image_row(dp
->ps
, pp
, iDisplay
, y
),
4516 dp
->bit_width
)) != 0)
4519 sprintf(msg
, "display row[%d][%d] changed from %.2x to %.2x", y
,
4520 where
-1, std
[where
-1],
4521 store_image_row(dp
->ps
, pp
, iDisplay
, y
)[where
-1]);
4527 standard_image_validate(standard_display
*dp
, png_structp pp
, int iImage
,
4533 store_image_check(dp
->ps
, pp
, iImage
);
4536 store_image_check(dp
->ps
, pp
, iDisplay
);
4538 for (y
=0; y
<dp
->h
; ++y
)
4539 standard_row_validate(dp
, pp
, iImage
, iDisplay
, y
);
4541 /* This avoids false positives if the validation code is never called! */
4542 dp
->ps
->validated
= 1;
4546 standard_end(png_structp pp
, png_infop pi
)
4548 standard_display
*dp
= voidcast(standard_display
*,
4549 png_get_progressive_ptr(pp
));
4553 /* Validate the image - progressive reading only produces one variant for
4554 * interlaced images.
4556 standard_image_validate(dp
, pp
, 0, -1);
4559 /* A single test run checking the standard image to ensure it is not damaged. */
4561 standard_test(png_store
* PNG_CONST psIn
, png_uint_32 PNG_CONST id
,
4562 int do_interlace
, int use_update_info
)
4565 context(psIn
, fault
);
4567 /* Set up the display (stack frame) variables from the arguments to the
4568 * function and initialize the locals that are filled in later.
4570 standard_display_init(&d
, psIn
, id
, do_interlace
, use_update_info
);
4572 /* Everything is protected by a Try/Catch. The functions called also
4573 * typically have local Try/Catch blocks.
4580 /* Get a png_struct for reading the image. This will throw an error if it
4581 * fails, so we don't need to check the result.
4583 pp
= set_store_for_read(d
.ps
, &pi
, d
.id
,
4584 d
.do_interlace
? (d
.ps
->progressive
?
4585 "pngvalid progressive deinterlacer" :
4586 "pngvalid sequential deinterlacer") : (d
.ps
->progressive
?
4587 "progressive reader" : "sequential reader"));
4589 /* Initialize the palette correctly from the png_store_file. */
4590 standard_palette_init(&d
);
4592 /* Introduce the correct read function. */
4593 if (d
.ps
->progressive
)
4595 png_set_progressive_read_fn(pp
, &d
, standard_info
, progressive_row
,
4598 /* Now feed data into the reader until we reach the end: */
4599 store_progressive_read(d
.ps
, pp
, pi
);
4603 /* Note that this takes the store, not the display. */
4604 png_set_read_fn(pp
, d
.ps
, store_read
);
4606 /* Check the header values: */
4607 png_read_info(pp
, pi
);
4609 /* The code tests both versions of the images that the sequential
4610 * reader can produce.
4612 standard_info_imp(&d
, pp
, pi
, 2 /*images*/);
4614 /* Need the total bytes in the image below; we can't get to this point
4615 * unless the PNG file values have been checked against the expected
4619 sequential_row(&d
, pp
, pi
, 0, 1);
4621 /* After the last pass loop over the rows again to check that the
4625 standard_image_validate(&d
, pp
, 0, 1);
4627 d
.ps
->validated
= 1;
4631 /* Check for validation. */
4632 if (!d
.ps
->validated
)
4633 png_error(pp
, "image read failed silently");
4635 /* Successful completion. */
4639 d
.ps
= fault
; /* make sure this hasn't been clobbered. */
4641 /* In either case clean up the store. */
4642 store_read_reset(d
.ps
);
4646 test_standard(png_modifier
* PNG_CONST pm
, png_byte PNG_CONST colour_type
,
4647 int bdlo
, int PNG_CONST bdhi
)
4649 for (; bdlo
<= bdhi
; ++bdlo
)
4653 for (interlace_type
= PNG_INTERLACE_NONE
;
4654 interlace_type
< PNG_INTERLACE_LAST
; ++interlace_type
)
4656 standard_test(&pm
->this, FILEID(colour_type
, DEPTH(bdlo
), 0/*palette*/,
4657 interlace_type
, 0, 0, 0), 0/*do_interlace*/, pm
->use_update_info
);
4664 return 1; /* keep going */
4668 perform_standard_test(png_modifier
*pm
)
4670 /* Test each colour type over the valid range of bit depths (expressed as
4671 * log2(bit_depth) in turn, stop as soon as any error is detected.
4673 if (!test_standard(pm
, 0, 0, READ_BDHI
))
4676 if (!test_standard(pm
, 2, 3, READ_BDHI
))
4679 if (!test_standard(pm
, 3, 0, 3))
4682 if (!test_standard(pm
, 4, 3, READ_BDHI
))
4685 if (!test_standard(pm
, 6, 3, READ_BDHI
))
4690 /********************************** SIZE TESTS ********************************/
4692 test_size(png_modifier
* PNG_CONST pm
, png_byte PNG_CONST colour_type
,
4693 int bdlo
, int PNG_CONST bdhi
)
4695 /* Run the tests on each combination.
4697 * NOTE: on my 32 bit x86 each of the following blocks takes
4698 * a total of 3.5 seconds if done across every combo of bit depth
4699 * width and height. This is a waste of time in practice, hence the
4700 * hinc and winc stuff:
4702 static PNG_CONST png_byte hinc
[] = {1, 3, 11, 1, 5};
4703 static PNG_CONST png_byte winc
[] = {1, 9, 5, 7, 1};
4704 for (; bdlo
<= bdhi
; ++bdlo
)
4708 for (h
=1; h
<=16; h
+=hinc
[bdlo
]) for (w
=1; w
<=16; w
+=winc
[bdlo
])
4710 /* First test all the 'size' images against the sequential
4711 * reader using libpng to deinterlace (where required.) This
4712 * validates the write side of libpng. There are four possibilities
4715 standard_test(&pm
->this, FILEID(colour_type
, DEPTH(bdlo
), 0/*palette*/,
4716 PNG_INTERLACE_NONE
, w
, h
, 0), 0/*do_interlace*/,
4717 pm
->use_update_info
);
4722 standard_test(&pm
->this, FILEID(colour_type
, DEPTH(bdlo
), 0/*palette*/,
4723 PNG_INTERLACE_NONE
, w
, h
, 1), 0/*do_interlace*/,
4724 pm
->use_update_info
);
4729 standard_test(&pm
->this, FILEID(colour_type
, DEPTH(bdlo
), 0/*palette*/,
4730 PNG_INTERLACE_ADAM7
, w
, h
, 0), 0/*do_interlace*/,
4731 pm
->use_update_info
);
4736 standard_test(&pm
->this, FILEID(colour_type
, DEPTH(bdlo
), 0/*palette*/,
4737 PNG_INTERLACE_ADAM7
, w
, h
, 1), 0/*do_interlace*/,
4738 pm
->use_update_info
);
4743 /* Now validate the interlaced read side - do_interlace true,
4744 * in the progressive case this does actually make a difference
4745 * to the code used in the non-interlaced case too.
4747 standard_test(&pm
->this, FILEID(colour_type
, DEPTH(bdlo
), 0/*palette*/,
4748 PNG_INTERLACE_NONE
, w
, h
, 0), 1/*do_interlace*/,
4749 pm
->use_update_info
);
4754 standard_test(&pm
->this, FILEID(colour_type
, DEPTH(bdlo
), 0/*palette*/,
4755 PNG_INTERLACE_ADAM7
, w
, h
, 0), 1/*do_interlace*/,
4756 pm
->use_update_info
);
4763 return 1; /* keep going */
4767 perform_size_test(png_modifier
*pm
)
4769 /* Test each colour type over the valid range of bit depths (expressed as
4770 * log2(bit_depth) in turn, stop as soon as any error is detected.
4772 if (!test_size(pm
, 0, 0, READ_BDHI
))
4775 if (!test_size(pm
, 2, 3, READ_BDHI
))
4778 /* For the moment don't do the palette test - it's a waste of time when
4779 * compared to the grayscale test.
4782 if (!test_size(pm
, 3, 0, 3))
4786 if (!test_size(pm
, 4, 3, READ_BDHI
))
4789 if (!test_size(pm
, 6, 3, READ_BDHI
))
4794 /******************************* TRANSFORM TESTS ******************************/
4795 #ifdef PNG_READ_TRANSFORMS_SUPPORTED
4796 /* A set of tests to validate libpng image transforms. The possibilities here
4797 * are legion because the transforms can be combined in a combinatorial
4798 * fashion. To deal with this some measure of restraint is required, otherwise
4799 * the tests would take forever.
4801 typedef struct image_pixel
4803 /* A local (pngvalid) representation of a PNG pixel, in all its
4806 unsigned int red
, green
, blue
, alpha
; /* For non-palette images. */
4807 unsigned int palette_index
; /* For a palette image. */
4808 png_byte colour_type
; /* As in the spec. */
4809 png_byte bit_depth
; /* Defines bit size in row */
4810 png_byte sample_depth
; /* Scale of samples */
4811 int have_tRNS
; /* tRNS chunk may need processing */
4813 /* For checking the code calculates double precision floating point values
4814 * along with an error value, accumulated from the transforms. Because an
4815 * sBIT setting allows larger error bounds (indeed, by the spec, apparently
4816 * up to just less than +/-1 in the scaled value) the *lowest* sBIT for each
4817 * channel is stored. This sBIT value is folded in to the stored error value
4818 * at the end of the application of the transforms to the pixel.
4820 double redf
, greenf
, bluef
, alphaf
;
4821 double rede
, greene
, bluee
, alphae
;
4822 png_byte red_sBIT
, green_sBIT
, blue_sBIT
, alpha_sBIT
;
4825 /* Shared utility function, see below. */
4827 image_pixel_setf(image_pixel
*this, unsigned int max
)
4829 this->redf
= this->red
/ (double)max
;
4830 this->greenf
= this->green
/ (double)max
;
4831 this->bluef
= this->blue
/ (double)max
;
4832 this->alphaf
= this->alpha
/ (double)max
;
4834 if (this->red
< max
)
4835 this->rede
= this->redf
* DBL_EPSILON
;
4838 if (this->green
< max
)
4839 this->greene
= this->greenf
* DBL_EPSILON
;
4842 if (this->blue
< max
)
4843 this->bluee
= this->bluef
* DBL_EPSILON
;
4846 if (this->alpha
< max
)
4847 this->alphae
= this->alphaf
* DBL_EPSILON
;
4852 /* Initialize the structure for the next pixel - call this before doing any
4853 * transforms and call it for each pixel since all the fields may need to be
4857 image_pixel_init(image_pixel
*this, png_const_bytep row
, png_byte colour_type
,
4858 png_byte bit_depth
, png_uint_32 x
, store_palette palette
)
4860 PNG_CONST png_byte sample_depth
= (png_byte
)(colour_type
==
4861 PNG_COLOR_TYPE_PALETTE
? 8 : bit_depth
);
4862 PNG_CONST
unsigned int max
= (1U<<sample_depth
)-1;
4864 /* Initially just set everything to the same number and the alpha to opaque.
4865 * Note that this currently assumes a simple palette where entry x has colour
4868 this->palette_index
= this->red
= this->green
= this->blue
=
4869 sample(row
, colour_type
, bit_depth
, x
, 0);
4871 this->red_sBIT
= this->green_sBIT
= this->blue_sBIT
= this->alpha_sBIT
=
4874 /* Then override as appropriate: */
4875 if (colour_type
== 3) /* palette */
4877 /* This permits the caller to default to the sample value. */
4880 PNG_CONST
unsigned int i
= this->palette_index
;
4882 this->red
= palette
[i
].red
;
4883 this->green
= palette
[i
].green
;
4884 this->blue
= palette
[i
].blue
;
4885 this->alpha
= palette
[i
].alpha
;
4889 else /* not palette */
4893 if (colour_type
& 2)
4895 this->green
= sample(row
, colour_type
, bit_depth
, x
, 1);
4896 this->blue
= sample(row
, colour_type
, bit_depth
, x
, 2);
4899 if (colour_type
& 4)
4900 this->alpha
= sample(row
, colour_type
, bit_depth
, x
, ++i
);
4903 /* Calculate the scaled values, these are simply the values divided by
4904 * 'max' and the error is initialized to the double precision epsilon value
4905 * from the header file.
4907 image_pixel_setf(this, max
);
4909 /* Store the input information for use in the transforms - these will
4910 * modify the information.
4912 this->colour_type
= colour_type
;
4913 this->bit_depth
= bit_depth
;
4914 this->sample_depth
= sample_depth
;
4915 this->have_tRNS
= 0;
4918 /* Convert a palette image to an rgb image. This necessarily converts the tRNS
4919 * chunk at the same time, because the tRNS will be in palette form. The way
4920 * palette validation works means that the original palette is never updated,
4921 * instead the image_pixel value from the row contains the RGB of the
4922 * corresponding palette entry and *this* is updated. Consequently this routine
4923 * only needs to change the colour type information.
4926 image_pixel_convert_PLTE(image_pixel
*this)
4928 if (this->colour_type
== PNG_COLOR_TYPE_PALETTE
)
4930 if (this->have_tRNS
)
4932 this->colour_type
= PNG_COLOR_TYPE_RGB_ALPHA
;
4933 this->have_tRNS
= 0;
4936 this->colour_type
= PNG_COLOR_TYPE_RGB
;
4938 /* The bit depth of the row changes at this point too (notice that this is
4939 * the row format, not the sample depth, which is separate.)
4941 this->bit_depth
= 8;
4945 /* Add an alpha channel; this will import the tRNS information because tRNS is
4946 * not valid in an alpha image. The bit depth will invariably be set to at
4947 * least 8. Palette images will be converted to alpha (using the above API).
4950 image_pixel_add_alpha(image_pixel
*this, PNG_CONST standard_display
*display
)
4952 if (this->colour_type
== PNG_COLOR_TYPE_PALETTE
)
4953 image_pixel_convert_PLTE(this);
4955 if ((this->colour_type
& PNG_COLOR_MASK_ALPHA
) == 0)
4957 if (this->colour_type
== PNG_COLOR_TYPE_GRAY
)
4959 if (this->bit_depth
< 8)
4960 this->bit_depth
= 8;
4962 if (this->have_tRNS
)
4964 this->have_tRNS
= 0;
4966 /* Check the input, original, channel value here against the
4967 * original tRNS gray chunk valie.
4969 if (this->red
== display
->transparent
.red
)
4977 this->colour_type
= PNG_COLOR_TYPE_GRAY_ALPHA
;
4980 else if (this->colour_type
== PNG_COLOR_TYPE_RGB
)
4982 if (this->have_tRNS
)
4984 this->have_tRNS
= 0;
4986 /* Again, check the exact input values, not the current transformed
4989 if (this->red
== display
->transparent
.red
&&
4990 this->green
== display
->transparent
.green
&&
4991 this->blue
== display
->transparent
.blue
)
4996 this->colour_type
= PNG_COLOR_TYPE_RGB_ALPHA
;
5000 /* The error in the alpha is zero and the sBIT value comes from the
5001 * original sBIT data (actually it will always be the original bit depth).
5004 this->alpha_sBIT
= display
->alpha_sBIT
;
5008 struct transform_display
;
5009 typedef struct image_transform
5011 /* The name of this transform: a string. */
5012 PNG_CONST
char *name
;
5014 /* Each transform can be disabled from the command line: */
5017 /* The global list of transforms; read only. */
5018 struct image_transform
*PNG_CONST list
;
5020 /* The global count of the number of times this transform has been set on an
5023 unsigned int global_use
;
5025 /* The local count of the number of times this transform has been set. */
5026 unsigned int local_use
;
5028 /* The next transform in the list, each transform must call its own next
5029 * transform after it has processed the pixel successfully.
5031 PNG_CONST
struct image_transform
*next
;
5033 /* A single transform for the image, expressed as a series of function
5034 * callbacks and some space for values.
5036 * First a callback to add any required modifications to the png_modifier;
5037 * this gets called just before the modifier is set up for read.
5039 void (*ini
)(PNG_CONST
struct image_transform
*this,
5040 struct transform_display
*that
);
5042 /* And a callback to set the transform on the current png_read_struct:
5044 void (*set
)(PNG_CONST
struct image_transform
*this,
5045 struct transform_display
*that
, png_structp pp
, png_infop pi
);
5047 /* Then a transform that takes an input pixel in one PNG format or another
5048 * and modifies it by a pngvalid implementation of the transform (thus
5049 * duplicating the libpng intent without, we hope, duplicating the bugs
5050 * in the libpng implementation!) The png_structp is solely to allow error
5051 * reporting via png_error and png_warning.
5053 void (*mod
)(PNG_CONST
struct image_transform
*this, image_pixel
*that
,
5054 png_structp pp
, PNG_CONST
struct transform_display
*display
);
5056 /* Add this transform to the list and return true if the transform is
5057 * meaningful for this colour type and bit depth - if false then the
5058 * transform should have no effect on the image so there's not a lot of
5061 int (*add
)(struct image_transform
*this,
5062 PNG_CONST
struct image_transform
**that
, png_byte colour_type
,
5063 png_byte bit_depth
);
5066 typedef struct transform_display
5068 standard_display
this;
5072 PNG_CONST image_transform
* transform_list
;
5074 /* Local variables */
5075 png_byte output_colour_type
;
5076 png_byte output_bit_depth
;
5078 /* Modifications (not necessarily used.) */
5079 gama_modification gama_mod
;
5080 chrm_modification chrm_mod
;
5081 srgb_modification srgb_mod
;
5082 } transform_display
;
5084 /* Set sRGB, cHRM and gAMA transforms as required by the current encoding. */
5086 transform_set_encoding(transform_display
*this)
5088 /* Set up the png_modifier '_current' fields then use these to determine how
5089 * to add appropriate chunks.
5091 png_modifier
*pm
= this->pm
;
5093 modifier_set_encoding(pm
);
5095 if (modifier_color_encoding_is_set(pm
))
5097 if (modifier_color_encoding_is_sRGB(pm
))
5098 srgb_modification_init(&this->srgb_mod
, pm
, PNG_sRGB_INTENT_ABSOLUTE
);
5102 /* Set gAMA and cHRM separately. */
5103 gama_modification_init(&this->gama_mod
, pm
, pm
->current_gamma
);
5105 if (pm
->current_encoding
!= 0)
5106 chrm_modification_init(&this->chrm_mod
, pm
, pm
->current_encoding
);
5111 /* Three functions to end the list: */
5113 image_transform_ini_end(PNG_CONST image_transform
*this,
5114 transform_display
*that
)
5121 image_transform_set_end(PNG_CONST image_transform
*this,
5122 transform_display
*that
, png_structp pp
, png_infop pi
)
5130 /* At the end of the list recalculate the output image pixel value from the
5131 * double precision values set up by the preceding 'mod' calls:
5134 sample_scale(double sample_value
, unsigned int scale
)
5136 sample_value
= floor(sample_value
* scale
+ .5);
5138 /* Return NaN as 0: */
5139 if (!(sample_value
> 0))
5141 else if (sample_value
> scale
)
5142 sample_value
= scale
;
5144 return (unsigned int)sample_value
;
5148 image_transform_mod_end(PNG_CONST image_transform
*this, image_pixel
*that
,
5149 png_structp pp
, PNG_CONST transform_display
*display
)
5151 PNG_CONST
unsigned int scale
= (1U<<that
->sample_depth
)-1;
5157 /* At the end recalculate the digitized red green and blue values according
5158 * to the current sample_depth of the pixel.
5160 * The sample value is simply scaled to the maximum, checking for over
5161 * and underflow (which can both happen for some image transforms,
5162 * including simple size scaling, though libpng doesn't do that at present.
5164 that
->red
= sample_scale(that
->redf
, scale
);
5166 /* The error value is increased, at the end, according to the lowest sBIT
5167 * value seen. Common sense tells us that the intermediate integer
5168 * representations are no more accurate than +/- 0.5 in the integral values,
5169 * the sBIT allows the implementation to be worse than this. In addition the
5170 * PNG specification actually permits any error within the range (-1..+1),
5171 * but that is ignored here. Instead the final digitized value is compared,
5172 * below to the digitized value of the error limits - this has the net effect
5173 * of allowing (almost) +/-1 in the output value. It's difficult to see how
5174 * any algorithm that digitizes intermediate results can be more accurate.
5176 that
->rede
+= 1./(2*((1U<<that
->red_sBIT
)-1));
5178 if (that
->colour_type
& PNG_COLOR_MASK_COLOR
)
5180 that
->green
= sample_scale(that
->greenf
, scale
);
5181 that
->blue
= sample_scale(that
->bluef
, scale
);
5182 that
->greene
+= 1./(2*((1U<<that
->green_sBIT
)-1));
5183 that
->bluee
+= 1./(2*((1U<<that
->blue_sBIT
)-1));
5187 that
->blue
= that
->green
= that
->red
;
5188 that
->bluef
= that
->greenf
= that
->redf
;
5189 that
->bluee
= that
->greene
= that
->rede
;
5192 if ((that
->colour_type
& PNG_COLOR_MASK_ALPHA
) ||
5193 that
->colour_type
== PNG_COLOR_TYPE_PALETTE
)
5195 that
->alpha
= sample_scale(that
->alphaf
, scale
);
5196 that
->alphae
+= 1./(2*((1U<<that
->alpha_sBIT
)-1));
5200 that
->alpha
= scale
; /* opaque */
5201 that
->alpha
= 1; /* Override this. */
5202 that
->alphae
= 0; /* It's exact ;-) */
5206 /* Static 'end' structure: */
5207 static image_transform image_transform_end
=
5215 image_transform_ini_end
,
5216 image_transform_set_end
,
5217 image_transform_mod_end
,
5218 0 /* never called, I want it to crash if it is! */
5221 /* Reader callbacks and implementations, where they differ from the standard
5225 transform_display_init(transform_display
*dp
, png_modifier
*pm
, png_uint_32 id
,
5226 PNG_CONST image_transform
*transform_list
)
5228 memset(dp
, 0, sizeof dp
);
5230 /* Standard fields */
5231 standard_display_init(&dp
->this, &pm
->this, id
, 0/*do_interlace*/,
5232 pm
->use_update_info
);
5234 /* Parameter fields */
5236 dp
->transform_list
= transform_list
;
5238 /* Local variable fields */
5239 dp
->output_colour_type
= 255; /* invalid */
5240 dp
->output_bit_depth
= 255; /* invalid */
5244 transform_info_imp(transform_display
*dp
, png_structp pp
, png_infop pi
)
5246 /* Reuse the standard stuff as appropriate. */
5247 standard_info_part1(&dp
->this, pp
, pi
);
5249 /* Now set the list of transforms. */
5250 dp
->transform_list
->set(dp
->transform_list
, dp
, pp
, pi
);
5252 /* Update the info structure for these transforms: */
5254 int i
= dp
->this.use_update_info
;
5255 /* Always do one call, even if use_update_info is 0. */
5257 png_read_update_info(pp
, pi
);
5261 /* And get the output information into the standard_display */
5262 standard_info_part2(&dp
->this, pp
, pi
, 1/*images*/);
5264 /* Plus the extra stuff we need for the transform tests: */
5265 dp
->output_colour_type
= png_get_color_type(pp
, pi
);
5266 dp
->output_bit_depth
= png_get_bit_depth(pp
, pi
);
5268 /* Validate the combination of colour type and bit depth that we are getting
5269 * out of libpng; the semantics of something not in the PNG spec are, at
5272 switch (dp
->output_colour_type
)
5274 case PNG_COLOR_TYPE_PALETTE
:
5275 if (dp
->output_bit_depth
> 8) goto error
;
5277 case PNG_COLOR_TYPE_GRAY
:
5278 if (dp
->output_bit_depth
== 1 || dp
->output_bit_depth
== 2 ||
5279 dp
->output_bit_depth
== 4)
5283 if (dp
->output_bit_depth
== 8 || dp
->output_bit_depth
== 16)
5291 pos
= safecat(message
, sizeof message
, 0,
5292 "invalid final bit depth: colour type(");
5293 pos
= safecatn(message
, sizeof message
, pos
, dp
->output_colour_type
);
5294 pos
= safecat(message
, sizeof message
, pos
, ") with bit depth: ");
5295 pos
= safecatn(message
, sizeof message
, pos
, dp
->output_bit_depth
);
5297 png_error(pp
, message
);
5301 /* Use a test pixel to check that the output agrees with what we expect -
5302 * this avoids running the whole test if the output is unexpected.
5305 image_pixel test_pixel
;
5307 memset(&test_pixel
, 0, sizeof test_pixel
);
5308 test_pixel
.colour_type
= dp
->this.colour_type
; /* input */
5309 test_pixel
.bit_depth
= dp
->this.bit_depth
;
5310 if (test_pixel
.colour_type
== PNG_COLOR_TYPE_PALETTE
)
5311 test_pixel
.sample_depth
= 8;
5313 test_pixel
.sample_depth
= test_pixel
.bit_depth
;
5314 /* Don't need sBIT here */
5315 test_pixel
.have_tRNS
= dp
->this.is_transparent
;
5317 dp
->transform_list
->mod(dp
->transform_list
, &test_pixel
, pp
, dp
);
5319 if (test_pixel
.colour_type
!= dp
->output_colour_type
)
5322 size_t pos
= safecat(message
, sizeof message
, 0, "colour type ");
5324 pos
= safecatn(message
, sizeof message
, pos
, dp
->output_colour_type
);
5325 pos
= safecat(message
, sizeof message
, pos
, " expected ");
5326 pos
= safecatn(message
, sizeof message
, pos
, test_pixel
.colour_type
);
5328 png_error(pp
, message
);
5331 if (test_pixel
.bit_depth
!= dp
->output_bit_depth
)
5334 size_t pos
= safecat(message
, sizeof message
, 0, "bit depth ");
5336 pos
= safecatn(message
, sizeof message
, pos
, dp
->output_bit_depth
);
5337 pos
= safecat(message
, sizeof message
, pos
, " expected ");
5338 pos
= safecatn(message
, sizeof message
, pos
, test_pixel
.bit_depth
);
5340 png_error(pp
, message
);
5343 /* If both bit depth and colour type are correct check the sample depth.
5344 * I believe these are both internal errors.
5346 if (test_pixel
.colour_type
== PNG_COLOR_TYPE_PALETTE
)
5348 if (test_pixel
.sample_depth
!= 8) /* oops - internal error! */
5349 png_error(pp
, "pngvalid: internal: palette sample depth not 8");
5351 else if (test_pixel
.sample_depth
!= dp
->output_bit_depth
)
5354 size_t pos
= safecat(message
, sizeof message
, 0,
5355 "internal: sample depth ");
5357 pos
= safecatn(message
, sizeof message
, pos
, dp
->output_bit_depth
);
5358 pos
= safecat(message
, sizeof message
, pos
, " expected ");
5359 pos
= safecatn(message
, sizeof message
, pos
, test_pixel
.sample_depth
);
5361 png_error(pp
, message
);
5367 transform_info(png_structp pp
, png_infop pi
)
5369 transform_info_imp(voidcast(transform_display
*, png_get_progressive_ptr(pp
)),
5374 transform_range_check(png_structp pp
, unsigned int r
, unsigned int g
,
5375 unsigned int b
, unsigned int a
, unsigned int in_digitized
, double in
,
5376 unsigned int out
, png_byte sample_depth
, double err
, double limit
,
5377 PNG_CONST
char *name
, double digitization_error
)
5379 /* Compare the scaled, digitzed, values of our local calculation (in+-err)
5380 * with the digitized values libpng produced; 'sample_depth' is the actual
5381 * digitization depth of the libpng output colors (the bit depth except for
5382 * palette images where it is always 8.) The check on 'err' is to detect
5383 * internal errors in pngvalid itself.
5385 unsigned int max
= (1U<<sample_depth
)-1;
5386 double in_min
= ceil((in
-err
)*max
- digitization_error
);
5387 double in_max
= floor((in
+err
)*max
+ digitization_error
);
5388 if (err
> limit
|| !(out
>= in_min
&& out
<= in_max
))
5393 pos
= safecat(message
, sizeof message
, 0, name
);
5394 pos
= safecat(message
, sizeof message
, pos
, " output value error: rgba(");
5395 pos
= safecatn(message
, sizeof message
, pos
, r
);
5396 pos
= safecat(message
, sizeof message
, pos
, ",");
5397 pos
= safecatn(message
, sizeof message
, pos
, g
);
5398 pos
= safecat(message
, sizeof message
, pos
, ",");
5399 pos
= safecatn(message
, sizeof message
, pos
, b
);
5400 pos
= safecat(message
, sizeof message
, pos
, ",");
5401 pos
= safecatn(message
, sizeof message
, pos
, a
);
5402 pos
= safecat(message
, sizeof message
, pos
, "): ");
5403 pos
= safecatn(message
, sizeof message
, pos
, out
);
5404 pos
= safecat(message
, sizeof message
, pos
, " expected: ");
5405 pos
= safecatn(message
, sizeof message
, pos
, in_digitized
);
5406 pos
= safecat(message
, sizeof message
, pos
, " (");
5407 pos
= safecatd(message
, sizeof message
, pos
, (in
-err
)*max
, 3);
5408 pos
= safecat(message
, sizeof message
, pos
, "..");
5409 pos
= safecatd(message
, sizeof message
, pos
, (in
+err
)*max
, 3);
5410 pos
= safecat(message
, sizeof message
, pos
, ")");
5412 png_error(pp
, message
);
5417 transform_image_validate(transform_display
*dp
, png_structp pp
, png_infop pi
)
5419 /* Constants for the loop below: */
5420 PNG_CONST png_store
* PNG_CONST ps
= dp
->this.ps
;
5421 PNG_CONST png_byte in_ct
= dp
->this.colour_type
;
5422 PNG_CONST png_byte in_bd
= dp
->this.bit_depth
;
5423 PNG_CONST png_uint_32 w
= dp
->this.w
;
5424 PNG_CONST png_uint_32 h
= dp
->this.h
;
5425 PNG_CONST png_byte out_ct
= dp
->output_colour_type
;
5426 PNG_CONST png_byte out_bd
= dp
->output_bit_depth
;
5427 PNG_CONST png_byte sample_depth
= (png_byte
)(out_ct
==
5428 PNG_COLOR_TYPE_PALETTE
? 8 : out_bd
);
5429 PNG_CONST png_byte red_sBIT
= dp
->this.red_sBIT
;
5430 PNG_CONST png_byte green_sBIT
= dp
->this.green_sBIT
;
5431 PNG_CONST png_byte blue_sBIT
= dp
->this.blue_sBIT
;
5432 PNG_CONST png_byte alpha_sBIT
= dp
->this.alpha_sBIT
;
5433 PNG_CONST
int have_tRNS
= dp
->this.is_transparent
;
5434 double digitization_error
;
5436 store_palette out_palette
;
5441 /* Check for row overwrite errors */
5442 store_image_check(dp
->this.ps
, pp
, 0);
5444 /* Read the palette corresponding to the output if the output colour type
5445 * indicates a palette, othewise set out_palette to garbage.
5447 if (out_ct
== PNG_COLOR_TYPE_PALETTE
)
5449 /* Validate that the palette count itself has not changed - this is not
5452 int npalette
= (-1);
5454 (void)read_palette(out_palette
, &npalette
, pp
, pi
);
5455 if (npalette
!= dp
->this.npalette
)
5456 png_error(pp
, "unexpected change in palette size");
5458 digitization_error
= .5;
5462 png_byte in_sample_depth
;
5464 memset(out_palette
, 0x5e, sizeof out_palette
);
5466 /* assume-8-bit-calculations means assume that if the input has 8 bit
5467 * (or less) samples and the output has 16 bit samples the calculations
5468 * will be done with 8 bit precision, not 16.
5470 * TODO: fix this in libpng; png_set_expand_16 should cause 16 bit
5471 * calculations to be used throughout.
5473 if (in_ct
== PNG_COLOR_TYPE_PALETTE
|| in_bd
< 16)
5474 in_sample_depth
= 8;
5476 in_sample_depth
= in_bd
;
5478 if (sample_depth
!= 16 || in_sample_depth
> 8 ||
5479 !dp
->pm
->calculations_use_input_precision
)
5480 digitization_error
= .5;
5482 /* Else errors are at 8 bit precision, scale .5 in 8 bits to the 16 bits:
5485 digitization_error
= .5 * 257;
5490 png_const_bytep PNG_CONST pRow
= store_image_row(ps
, pp
, 0, y
);
5493 /* The original, standard, row pre-transforms. */
5494 png_byte std
[STANDARD_ROWMAX
];
5496 transform_row(pp
, std
, in_ct
, in_bd
, y
);
5498 /* Go through each original pixel transforming it and comparing with what
5499 * libpng did to the same pixel.
5503 image_pixel in_pixel
, out_pixel
;
5504 unsigned int r
, g
, b
, a
;
5506 /* Find out what we think the pixel should be: */
5507 image_pixel_init(&in_pixel
, std
, in_ct
, in_bd
, x
, dp
->this.palette
);
5509 in_pixel
.red_sBIT
= red_sBIT
;
5510 in_pixel
.green_sBIT
= green_sBIT
;
5511 in_pixel
.blue_sBIT
= blue_sBIT
;
5512 in_pixel
.alpha_sBIT
= alpha_sBIT
;
5513 in_pixel
.have_tRNS
= have_tRNS
;
5515 /* For error detection, below. */
5521 dp
->transform_list
->mod(dp
->transform_list
, &in_pixel
, pp
, dp
);
5523 /* Read the output pixel and compare it to what we got, we don't
5524 * use the error field here, so no need to update sBIT.
5526 image_pixel_init(&out_pixel
, pRow
, out_ct
, out_bd
, x
, out_palette
);
5528 /* We don't expect changes to the index here even if the bit depth is
5531 if (in_ct
== PNG_COLOR_TYPE_PALETTE
&&
5532 out_ct
== PNG_COLOR_TYPE_PALETTE
)
5534 if (in_pixel
.palette_index
!= out_pixel
.palette_index
)
5535 png_error(pp
, "unexpected transformed palette index");
5538 /* Check the colours for palette images too - in fact the palette could
5539 * be separately verified itself in most cases.
5541 if (in_pixel
.red
!= out_pixel
.red
)
5542 transform_range_check(pp
, r
, g
, b
, a
, in_pixel
.red
, in_pixel
.redf
,
5543 out_pixel
.red
, sample_depth
, in_pixel
.rede
,
5544 dp
->pm
->limit
+ 1./(2*((1U<<in_pixel
.red_sBIT
)-1)), "red/gray",
5545 digitization_error
);
5547 if ((out_ct
& PNG_COLOR_MASK_COLOR
) != 0 &&
5548 in_pixel
.green
!= out_pixel
.green
)
5549 transform_range_check(pp
, r
, g
, b
, a
, in_pixel
.green
,
5550 in_pixel
.greenf
, out_pixel
.green
, sample_depth
, in_pixel
.greene
,
5551 dp
->pm
->limit
+ 1./(2*((1U<<in_pixel
.green_sBIT
)-1)), "green",
5552 digitization_error
);
5554 if ((out_ct
& PNG_COLOR_MASK_COLOR
) != 0 &&
5555 in_pixel
.blue
!= out_pixel
.blue
)
5556 transform_range_check(pp
, r
, g
, b
, a
, in_pixel
.blue
, in_pixel
.bluef
,
5557 out_pixel
.blue
, sample_depth
, in_pixel
.bluee
,
5558 dp
->pm
->limit
+ 1./(2*((1U<<in_pixel
.blue_sBIT
)-1)), "blue",
5559 digitization_error
);
5561 if ((out_ct
& PNG_COLOR_MASK_ALPHA
) != 0 &&
5562 in_pixel
.alpha
!= out_pixel
.alpha
)
5563 transform_range_check(pp
, r
, g
, b
, a
, in_pixel
.alpha
,
5564 in_pixel
.alphaf
, out_pixel
.alpha
, sample_depth
, in_pixel
.alphae
,
5565 dp
->pm
->limit
+ 1./(2*((1U<<in_pixel
.alpha_sBIT
)-1)), "alpha",
5566 digitization_error
);
5567 } /* pixel (x) loop */
5568 } /* row (y) loop */
5570 /* Record that something was actually checked to avoid a false positive. */
5571 dp
->this.ps
->validated
= 1;
5575 transform_end(png_structp pp
, png_infop pi
)
5577 transform_display
*dp
= voidcast(transform_display
*,
5578 png_get_progressive_ptr(pp
));
5580 if (!dp
->this.speed
)
5581 transform_image_validate(dp
, pp
, pi
);
5583 dp
->this.ps
->validated
= 1;
5586 /* A single test run. */
5588 transform_test(png_modifier
*pmIn
, PNG_CONST png_uint_32 idIn
,
5589 PNG_CONST image_transform
* transform_listIn
, PNG_CONST
char * volatile name
)
5591 transform_display d
;
5592 context(&pmIn
->this, fault
);
5594 transform_display_init(&d
, pmIn
, idIn
, transform_listIn
);
5601 char full_name
[256];
5603 /* Make sure the encoding fields are correct and enter the required
5606 transform_set_encoding(&d
);
5608 /* Add any modifications required by the transform list. */
5609 d
.transform_list
->ini(d
.transform_list
, &d
);
5611 /* Add the color space information, if any, to the name. */
5612 pos
= safecat(full_name
, sizeof full_name
, pos
, name
);
5613 pos
= safecat_current_encoding(full_name
, sizeof full_name
, pos
, d
.pm
);
5615 /* Get a png_struct for reading the image. */
5616 pp
= set_modifier_for_read(d
.pm
, &pi
, d
.this.id
, full_name
);
5617 standard_palette_init(&d
.this);
5620 /* Logging (debugging only) */
5624 (void)store_message(&d
.pm
->this, pp
, buffer
, sizeof buffer
, 0,
5627 fprintf(stderr
, "%s\n", buffer
);
5631 /* Introduce the correct read function. */
5632 if (d
.pm
->this.progressive
)
5634 /* Share the row function with the standard implementation. */
5635 png_set_progressive_read_fn(pp
, &d
, transform_info
, progressive_row
,
5638 /* Now feed data into the reader until we reach the end: */
5639 modifier_progressive_read(d
.pm
, pp
, pi
);
5643 /* modifier_read expects a png_modifier* */
5644 png_set_read_fn(pp
, d
.pm
, modifier_read
);
5646 /* Check the header values: */
5647 png_read_info(pp
, pi
);
5649 /* Process the 'info' requirements. Only one image is generated */
5650 transform_info_imp(&d
, pp
, pi
);
5652 sequential_row(&d
.this, pp
, pi
, -1, 0);
5655 transform_image_validate(&d
, pp
, pi
);
5657 d
.this.ps
->validated
= 1;
5660 modifier_reset(d
.pm
);
5665 modifier_reset((png_modifier
*)fault
);
5669 /* The transforms: */
5670 #define ITSTRUCT(name) image_transform_##name
5671 #define ITDATA(name) image_transform_data_##name
5672 #define image_transform_ini image_transform_default_ini
5674 static image_transform ITSTRUCT(name) =\
5682 image_transform_ini,\
5683 image_transform_png_set_##name##_set,\
5684 image_transform_png_set_##name##_mod,\
5685 image_transform_png_set_##name##_add\
5687 #define PT ITSTRUCT(end) /* stores the previous transform */
5691 image_transform_default_ini(PNG_CONST image_transform
*this,
5692 transform_display
*that
)
5694 this->next
->ini(this->next
, that
);
5698 image_transform_default_add(image_transform
*this,
5699 PNG_CONST image_transform
**that
, png_byte colour_type
, png_byte bit_depth
)
5710 #ifdef PNG_READ_EXPAND_SUPPORTED
5711 /* png_set_palette_to_rgb */
5713 image_transform_png_set_palette_to_rgb_set(PNG_CONST image_transform
*this,
5714 transform_display
*that
, png_structp pp
, png_infop pi
)
5716 png_set_palette_to_rgb(pp
);
5717 this->next
->set(this->next
, that
, pp
, pi
);
5721 image_transform_png_set_palette_to_rgb_mod(PNG_CONST image_transform
*this,
5722 image_pixel
*that
, png_structp pp
, PNG_CONST transform_display
*display
)
5724 if (that
->colour_type
== PNG_COLOR_TYPE_PALETTE
)
5725 image_pixel_convert_PLTE(that
);
5727 this->next
->mod(this->next
, that
, pp
, display
);
5731 image_transform_png_set_palette_to_rgb_add(image_transform
*this,
5732 PNG_CONST image_transform
**that
, png_byte colour_type
, png_byte bit_depth
)
5739 return colour_type
== PNG_COLOR_TYPE_PALETTE
;
5744 #define PT ITSTRUCT(palette_to_rgb)
5745 #endif /* PNG_READ_EXPAND_SUPPORTED */
5747 #ifdef PNG_READ_EXPAND_SUPPORTED
5748 /* png_set_tRNS_to_alpha */
5750 image_transform_png_set_tRNS_to_alpha_set(PNG_CONST image_transform
*this,
5751 transform_display
*that
, png_structp pp
, png_infop pi
)
5753 png_set_tRNS_to_alpha(pp
);
5754 this->next
->set(this->next
, that
, pp
, pi
);
5758 image_transform_png_set_tRNS_to_alpha_mod(PNG_CONST image_transform
*this,
5759 image_pixel
*that
, png_structp pp
, PNG_CONST transform_display
*display
)
5761 /* LIBPNG BUG: this always forces palette images to RGB. */
5762 if (that
->colour_type
== PNG_COLOR_TYPE_PALETTE
)
5763 image_pixel_convert_PLTE(that
);
5765 /* This effectively does an 'expand' only if there is some transparency to
5766 * convert to an alpha channel.
5768 if (that
->have_tRNS
)
5769 image_pixel_add_alpha(that
, &display
->this);
5771 /* LIBPNG BUG: otherwise libpng still expands to 8 bits! */
5774 if (that
->bit_depth
< 8)
5776 if (that
->sample_depth
< 8)
5777 that
->sample_depth
= 8;
5780 this->next
->mod(this->next
, that
, pp
, display
);
5784 image_transform_png_set_tRNS_to_alpha_add(image_transform
*this,
5785 PNG_CONST image_transform
**that
, png_byte colour_type
, png_byte bit_depth
)
5792 /* We don't know yet whether there will be a tRNS chunk, but we know that
5793 * this transformation should do nothing if there already is an alpha
5796 return (colour_type
& PNG_COLOR_MASK_ALPHA
) == 0;
5801 #define PT ITSTRUCT(tRNS_to_alpha)
5802 #endif /* PNG_READ_EXPAND_SUPPORTED */
5804 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
5805 /* png_set_gray_to_rgb */
5807 image_transform_png_set_gray_to_rgb_set(PNG_CONST image_transform
*this,
5808 transform_display
*that
, png_structp pp
, png_infop pi
)
5810 png_set_gray_to_rgb(pp
);
5811 this->next
->set(this->next
, that
, pp
, pi
);
5815 image_transform_png_set_gray_to_rgb_mod(PNG_CONST image_transform
*this,
5816 image_pixel
*that
, png_structp pp
, PNG_CONST transform_display
*display
)
5818 /* NOTE: we can actually pend the tRNS processing at this point because we
5819 * can correctly recognize the original pixel value even though we have
5820 * mapped the one gray channel to the three RGB ones, but in fact libpng
5821 * doesn't do this, so we don't either.
5823 if ((that
->colour_type
& PNG_COLOR_MASK_COLOR
) == 0 && that
->have_tRNS
)
5824 image_pixel_add_alpha(that
, &display
->this);
5826 /* Simply expand the bit depth and alter the colour type as required. */
5827 if (that
->colour_type
== PNG_COLOR_TYPE_GRAY
)
5829 /* RGB images have a bit depth at least equal to '8' */
5830 if (that
->bit_depth
< 8)
5831 that
->sample_depth
= that
->bit_depth
= 8;
5833 /* And just changing the colour type works here because the green and blue
5834 * channels are being maintained in lock-step with the red/gray:
5836 that
->colour_type
= PNG_COLOR_TYPE_RGB
;
5839 else if (that
->colour_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
5840 that
->colour_type
= PNG_COLOR_TYPE_RGB_ALPHA
;
5842 this->next
->mod(this->next
, that
, pp
, display
);
5846 image_transform_png_set_gray_to_rgb_add(image_transform
*this,
5847 PNG_CONST image_transform
**that
, png_byte colour_type
, png_byte bit_depth
)
5854 return (colour_type
& PNG_COLOR_MASK_COLOR
) == 0;
5859 #define PT ITSTRUCT(gray_to_rgb)
5860 #endif /* PNG_READ_GRAY_TO_RGB_SUPPORTED */
5862 #ifdef PNG_READ_EXPAND_SUPPORTED
5863 /* png_set_expand */
5865 image_transform_png_set_expand_set(PNG_CONST image_transform
*this,
5866 transform_display
*that
, png_structp pp
, png_infop pi
)
5869 this->next
->set(this->next
, that
, pp
, pi
);
5873 image_transform_png_set_expand_mod(PNG_CONST image_transform
*this,
5874 image_pixel
*that
, png_structp pp
, PNG_CONST transform_display
*display
)
5876 /* The general expand case depends on what the colour type is: */
5877 if (that
->colour_type
== PNG_COLOR_TYPE_PALETTE
)
5878 image_pixel_convert_PLTE(that
);
5879 else if (that
->bit_depth
< 8) /* grayscale */
5880 that
->sample_depth
= that
->bit_depth
= 8;
5882 if (that
->have_tRNS
)
5883 image_pixel_add_alpha(that
, &display
->this);
5885 this->next
->mod(this->next
, that
, pp
, display
);
5889 image_transform_png_set_expand_add(image_transform
*this,
5890 PNG_CONST image_transform
**that
, png_byte colour_type
, png_byte bit_depth
)
5897 /* 'expand' should do nothing for RGBA or GA input - no tRNS and the bit
5898 * depth is at least 8 already.
5900 return (colour_type
& PNG_COLOR_MASK_ALPHA
) == 0;
5905 #define PT ITSTRUCT(expand)
5906 #endif /* PNG_READ_EXPAND_SUPPORTED */
5908 #ifdef PNG_READ_EXPAND_SUPPORTED
5909 /* png_set_expand_gray_1_2_4_to_8
5910 * LIBPNG BUG: this just does an 'expand'
5913 image_transform_png_set_expand_gray_1_2_4_to_8_set(
5914 PNG_CONST image_transform
*this, transform_display
*that
, png_structp pp
,
5917 png_set_expand_gray_1_2_4_to_8(pp
);
5918 this->next
->set(this->next
, that
, pp
, pi
);
5922 image_transform_png_set_expand_gray_1_2_4_to_8_mod(
5923 PNG_CONST image_transform
*this, image_pixel
*that
, png_structp pp
,
5924 PNG_CONST transform_display
*display
)
5926 image_transform_png_set_expand_mod(this, that
, pp
, display
);
5930 image_transform_png_set_expand_gray_1_2_4_to_8_add(image_transform
*this,
5931 PNG_CONST image_transform
**that
, png_byte colour_type
, png_byte bit_depth
)
5933 return image_transform_png_set_expand_add(this, that
, colour_type
,
5937 IT(expand_gray_1_2_4_to_8
);
5939 #define PT ITSTRUCT(expand_gray_1_2_4_to_8)
5940 #endif /* PNG_READ_EXPAND_SUPPORTED */
5942 #ifdef PNG_READ_EXPAND_16_SUPPORTED
5943 /* png_set_expand_16 */
5945 image_transform_png_set_expand_16_set(PNG_CONST image_transform
*this,
5946 transform_display
*that
, png_structp pp
, png_infop pi
)
5948 png_set_expand_16(pp
);
5949 this->next
->set(this->next
, that
, pp
, pi
);
5953 image_transform_png_set_expand_16_mod(PNG_CONST image_transform
*this,
5954 image_pixel
*that
, png_structp pp
, PNG_CONST transform_display
*display
)
5956 /* Expect expand_16 to expand everything to 16 bits as a result of also
5957 * causing 'expand' to happen.
5959 if (that
->colour_type
== PNG_COLOR_TYPE_PALETTE
)
5960 image_pixel_convert_PLTE(that
);
5962 if (that
->have_tRNS
)
5963 image_pixel_add_alpha(that
, &display
->this);
5965 if (that
->bit_depth
< 16)
5966 that
->sample_depth
= that
->bit_depth
= 16;
5968 this->next
->mod(this->next
, that
, pp
, display
);
5972 image_transform_png_set_expand_16_add(image_transform
*this,
5973 PNG_CONST image_transform
**that
, png_byte colour_type
, png_byte bit_depth
)
5980 /* expand_16 does something unless the bit depth is already 16. */
5981 return bit_depth
< 16;
5986 #define PT ITSTRUCT(expand_16)
5987 #endif /* PNG_READ_EXPAND_16_SUPPORTED */
5989 #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED /* API added in 1.5.4 */
5990 /* png_set_scale_16 */
5992 image_transform_png_set_scale_16_set(PNG_CONST image_transform
*this,
5993 transform_display
*that
, png_structp pp
, png_infop pi
)
5995 png_set_scale_16(pp
);
5996 this->next
->set(this->next
, that
, pp
, pi
);
6000 image_transform_png_set_scale_16_mod(PNG_CONST image_transform
*this,
6001 image_pixel
*that
, png_structp pp
, PNG_CONST transform_display
*display
)
6003 if (that
->bit_depth
== 16)
6005 that
->sample_depth
= that
->bit_depth
= 8;
6006 if (that
->red_sBIT
> 8) that
->red_sBIT
= 8;
6007 if (that
->green_sBIT
> 8) that
->green_sBIT
= 8;
6008 if (that
->blue_sBIT
> 8) that
->blue_sBIT
= 8;
6009 if (that
->alpha_sBIT
> 8) that
->alpha_sBIT
= 8;
6012 this->next
->mod(this->next
, that
, pp
, display
);
6016 image_transform_png_set_scale_16_add(image_transform
*this,
6017 PNG_CONST image_transform
**that
, png_byte colour_type
, png_byte bit_depth
)
6024 return bit_depth
> 8;
6029 #define PT ITSTRUCT(scale_16)
6030 #endif /* PNG_READ_SCALE_16_TO_8_SUPPORTED (1.5.4 on) */
6032 #ifdef PNG_READ_16_TO_8_SUPPORTED /* the default before 1.5.4 */
6033 /* png_set_strip_16 */
6035 image_transform_png_set_strip_16_set(PNG_CONST image_transform
*this,
6036 transform_display
*that
, png_structp pp
, png_infop pi
)
6038 png_set_strip_16(pp
);
6039 this->next
->set(this->next
, that
, pp
, pi
);
6043 image_transform_png_set_strip_16_mod(PNG_CONST image_transform
*this,
6044 image_pixel
*that
, png_structp pp
, PNG_CONST transform_display
*display
)
6046 if (that
->bit_depth
== 16)
6048 that
->sample_depth
= that
->bit_depth
= 8;
6049 if (that
->red_sBIT
> 8) that
->red_sBIT
= 8;
6050 if (that
->green_sBIT
> 8) that
->green_sBIT
= 8;
6051 if (that
->blue_sBIT
> 8) that
->blue_sBIT
= 8;
6052 if (that
->alpha_sBIT
> 8) that
->alpha_sBIT
= 8;
6054 /* Prior to 1.5.4 png_set_strip_16 would use an 'accurate' method if this
6055 * configuration option is set. From 1.5.4 the flag is never set and the
6056 * 'scale' API (above) must be used.
6058 # ifdef PNG_READ_ACCURATE_SCALE_SUPPORTED
6059 # if PNG_LIBPNG_VER >= 10504
6060 # error PNG_READ_ACCURATE_SCALE should not be set
6063 /* The strip 16 algorithm drops the low 8 bits rather than calculating
6064 * 1/257, so we need to adjust the permitted errors appropriately:
6065 * Notice that this is only relevant prior to the addition of the
6066 * png_set_scale_16 API in 1.5.4 (but 1.5.4+ always defines the above!)
6069 PNG_CONST
double d
= (255-128.5)/65535;
6078 this->next
->mod(this->next
, that
, pp
, display
);
6082 image_transform_png_set_strip_16_add(image_transform
*this,
6083 PNG_CONST image_transform
**that
, png_byte colour_type
, png_byte bit_depth
)
6090 return bit_depth
> 8;
6095 #define PT ITSTRUCT(strip_16)
6096 #endif /* PNG_READ_16_TO_8_SUPPORTED */
6098 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
6099 /* png_set_strip_alpha */
6101 image_transform_png_set_strip_alpha_set(PNG_CONST image_transform
*this,
6102 transform_display
*that
, png_structp pp
, png_infop pi
)
6104 png_set_strip_alpha(pp
);
6105 this->next
->set(this->next
, that
, pp
, pi
);
6109 image_transform_png_set_strip_alpha_mod(PNG_CONST image_transform
*this,
6110 image_pixel
*that
, png_structp pp
, PNG_CONST transform_display
*display
)
6112 if (that
->colour_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
6113 that
->colour_type
= PNG_COLOR_TYPE_GRAY
;
6114 else if (that
->colour_type
== PNG_COLOR_TYPE_RGB_ALPHA
)
6115 that
->colour_type
= PNG_COLOR_TYPE_RGB
;
6117 that
->have_tRNS
= 0;
6120 this->next
->mod(this->next
, that
, pp
, display
);
6124 image_transform_png_set_strip_alpha_add(image_transform
*this,
6125 PNG_CONST image_transform
**that
, png_byte colour_type
, png_byte bit_depth
)
6132 return (colour_type
& PNG_COLOR_MASK_ALPHA
) != 0;
6137 #define PT ITSTRUCT(strip_alpha)
6138 #endif /* PNG_READ_STRIP_ALPHA_SUPPORTED */
6140 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
6141 /* png_set_rgb_to_gray(png_structp, int err_action, double red, double green)
6142 * png_set_rgb_to_gray_fixed(png_structp, int err_action, png_fixed_point red,
6143 * png_fixed_point green)
6144 * png_get_rgb_to_gray_status
6146 * The 'default' test here uses values known to be used inside libpng:
6152 * These values are being retained for compatibility, along with the somewhat
6153 * broken truncation calculation in the fast-and-inaccurate code path. Older
6154 * versions of libpng will fail the accuracy tests below because they use the
6155 * truncation algorithm everywhere.
6157 #define data ITDATA(rgb_to_gray)
6160 double gamma
; /* File gamma to use in processing */
6162 /* The following are the parameters for png_set_rgb_to_gray: */
6163 # ifdef PNG_FLOATING_POINT_SUPPORTED
6165 double green_to_set
;
6167 png_fixed_point red_to_set
;
6168 png_fixed_point green_to_set
;
6171 /* The actual coefficients: */
6172 double red_coefficient
;
6173 double green_coefficient
;
6174 double blue_coefficient
;
6176 /* Set if the coeefficients have been overridden. */
6177 int coefficients_overridden
;
6180 #undef image_transform_ini
6181 #define image_transform_ini image_transform_png_set_rgb_to_gray_ini
6183 image_transform_png_set_rgb_to_gray_ini(PNG_CONST image_transform
*this,
6184 transform_display
*that
)
6186 png_modifier
*pm
= that
->pm
;
6187 PNG_CONST color_encoding
*e
= pm
->current_encoding
;
6191 /* Since we check the encoding this flag must be set: */
6192 pm
->test_uses_encoding
= 1;
6194 /* If 'e' is not NULL chromaticity information is present and either a cHRM
6195 * or an sRGB chunk will be inserted.
6199 /* Coefficients come from the encoding, but may need to be normalized to a
6200 * white point Y of 1.0
6202 PNG_CONST
double whiteY
= e
->red
.Y
+ e
->green
.Y
+ e
->blue
.Y
;
6204 data
.red_coefficient
= e
->red
.Y
;
6205 data
.green_coefficient
= e
->green
.Y
;
6206 data
.blue_coefficient
= e
->blue
.Y
;
6210 data
.red_coefficient
/= whiteY
;
6211 data
.green_coefficient
/= whiteY
;
6212 data
.blue_coefficient
/= whiteY
;
6218 /* The default (built in) coeffcients, as above: */
6219 data
.red_coefficient
= 6968 / 32768.;
6220 data
.green_coefficient
= 23434 / 32768.;
6221 data
.blue_coefficient
= 2366 / 32768.;
6224 data
.gamma
= pm
->current_gamma
;
6226 /* If not set then the calculations assume linear encoding (implicitly): */
6227 if (data
.gamma
== 0)
6230 /* The arguments to png_set_rgb_to_gray can override the coefficients implied
6231 * by the color space encoding. If doing exhaustive checks do the override
6232 * in each case, otherwise do it randomly.
6234 if (pm
->test_exhaustive
)
6236 /* First time in coefficients_overridden is 0, the following sets it to 1,
6237 * so repeat if it is set. If a test fails this may mean we subsequently
6238 * skip a non-override test, ignore that.
6240 data
.coefficients_overridden
= !data
.coefficients_overridden
;
6241 pm
->repeat
= data
.coefficients_overridden
!= 0;
6245 data
.coefficients_overridden
= random_choice();
6247 if (data
.coefficients_overridden
)
6249 /* These values override the color encoding defaults, simply use random
6256 data
.green_coefficient
= total
= (ru
& 0xffff) / 65535.;
6258 data
.red_coefficient
= (1 - total
) * (ru
& 0xffff) / 65535.;
6259 total
+= data
.red_coefficient
;
6260 data
.blue_coefficient
= 1 - total
;
6262 # ifdef PNG_FLOATING_POINT_SUPPORTED
6263 data
.red_to_set
= data
.red_coefficient
;
6264 data
.green_to_set
= data
.green_coefficient
;
6266 data
.red_to_set
= fix(data
.red_coefficient
);
6267 data
.green_to_set
= fix(data
.green_coefficient
);
6270 /* The following just changes the error messages: */
6271 pm
->encoding_ignored
= 1;
6276 data
.red_to_set
= -1;
6277 data
.green_to_set
= -1;
6280 /* Adjust the error limit in the png_modifier because of the larger errors
6281 * produced in the digitization during the gamma handling.
6283 if (data
.gamma
!= 1) /* Use gamma tables */
6285 if (that
->this.bit_depth
== 16 || pm
->assume_16_bit_calculations
)
6287 /* The 16 bit case ends up producing a maximum error of about
6288 * +/-5 in 65535, allow for +/-8 with the given gamma.
6290 that
->pm
->limit
+= pow(8./65535, data
.gamma
);
6295 /* Rounding to 8 bits in the linear space causes massive errors which
6296 * will trigger the error check in transform_range_check. Fix that
6297 * here by taking the gamma encoding into account.
6299 that
->pm
->limit
+= pow(1./255, data
.gamma
);
6305 /* With no gamma correction a large error comes from the truncation of the
6306 * calculation in the 8 bit case, allow for that here.
6308 if (that
->this.bit_depth
!= 16)
6309 that
->pm
->limit
+= 4E-3;
6314 image_transform_png_set_rgb_to_gray_set(PNG_CONST image_transform
*this,
6315 transform_display
*that
, png_structp pp
, png_infop pi
)
6317 PNG_CONST
int error_action
= 1; /* no error, no defines in png.h */
6319 # ifdef PNG_FLOATING_POINT_SUPPORTED
6320 png_set_rgb_to_gray(pp
, error_action
, data
.red_to_set
, data
.green_to_set
);
6322 png_set_rgb_to_gray_fixed(pp
, error_action
, data
.red_to_set
,
6326 # ifdef PNG_READ_cHRM_SUPPORTED
6327 if (that
->pm
->current_encoding
!= 0)
6329 /* We have an encoding so a cHRM chunk may have been set; if so then
6330 * check that the libpng APIs give the correct (X,Y,Z) values within
6331 * some margin of error for the round trip through the chromaticity
6334 # ifdef PNG_FLOATING_POINT_SUPPORTED
6335 # define API_function png_get_cHRM_XYZ
6336 # define API_form "FP"
6337 # define API_type double
6338 # define API_cvt(x) (x)
6340 # define API_function png_get_cHRM_XYZ_fixed
6341 # define API_form "fixed"
6342 # define API_type png_fixed_point
6343 # define API_cvt(x) ((double)(x)/PNG_FP_1)
6346 API_type rX
, gX
, bX
;
6347 API_type rY
, gY
, bY
;
6348 API_type rZ
, gZ
, bZ
;
6350 if ((API_function(pp
, pi
, &rX
, &rY
, &rZ
, &gX
, &gY
, &gZ
, &bX
, &bY
, &bZ
)
6351 & PNG_INFO_cHRM
) != 0)
6355 color_encoding e
, o
;
6357 /* Expect libpng to return a normalized result, but the original
6358 * color space encoding may not be normalized.
6360 modifier_current_encoding(that
->pm
, &o
);
6361 normalize_color_encoding(&o
);
6363 /* Sanity check the pngvalid code - the coefficients should match
6364 * the normalized Y values of the encoding unless they were
6367 if (data
.red_to_set
== -1 && data
.green_to_set
== -1 &&
6368 (fabs(o
.red
.Y
- data
.red_coefficient
) > DBL_EPSILON
||
6369 fabs(o
.green
.Y
- data
.green_coefficient
) > DBL_EPSILON
||
6370 fabs(o
.blue
.Y
- data
.blue_coefficient
) > DBL_EPSILON
))
6371 png_error(pp
, "internal pngvalid cHRM coefficient error");
6373 /* Generate a colour space encoding. */
6374 e
.gamma
= o
.gamma
; /* not used */
6375 e
.red
.X
= API_cvt(rX
);
6376 e
.red
.Y
= API_cvt(rY
);
6377 e
.red
.Z
= API_cvt(rZ
);
6378 e
.green
.X
= API_cvt(gX
);
6379 e
.green
.Y
= API_cvt(gY
);
6380 e
.green
.Z
= API_cvt(gZ
);
6381 e
.blue
.X
= API_cvt(bX
);
6382 e
.blue
.Y
= API_cvt(bY
);
6383 e
.blue
.Z
= API_cvt(bZ
);
6385 /* This should match the original one from the png_modifier, within
6386 * the range permitted by the libpng fixed point representation.
6389 el
= "-"; /* Set to element name with error */
6391 # define CHECK(col,x)\
6393 double err = fabs(o.col.x - e.col.x);\
6397 el = #col "(" #x ")";\
6411 /* Here in both fixed and floating cases to check the values read
6412 * from the cHRm chunk. PNG uses fixed point in the cHRM chunk, so
6413 * we can't expect better than +/-.5E-5 on the result, allow 1E-5.
6420 pos
= safecat(buffer
, sizeof buffer
, pos
, API_form
);
6421 pos
= safecat(buffer
, sizeof buffer
, pos
, " cHRM ");
6422 pos
= safecat(buffer
, sizeof buffer
, pos
, el
);
6423 pos
= safecat(buffer
, sizeof buffer
, pos
, " error: ");
6424 pos
= safecatd(buffer
, sizeof buffer
, pos
, maxe
, 7);
6425 pos
= safecat(buffer
, sizeof buffer
, pos
, " ");
6426 /* Print the color space without the gamma value: */
6427 pos
= safecat_color_encoding(buffer
, sizeof buffer
, pos
, &o
, 0);
6428 pos
= safecat(buffer
, sizeof buffer
, pos
, " -> ");
6429 pos
= safecat_color_encoding(buffer
, sizeof buffer
, pos
, &e
, 0);
6431 png_error(pp
, buffer
);
6435 # endif /* READ_cHRM */
6437 this->next
->set(this->next
, that
, pp
, pi
);
6441 image_transform_png_set_rgb_to_gray_mod(PNG_CONST image_transform
*this,
6442 image_pixel
*that
, png_structp pp
, PNG_CONST transform_display
*display
)
6444 if ((that
->colour_type
& PNG_COLOR_MASK_COLOR
) != 0)
6448 if (that
->colour_type
== PNG_COLOR_TYPE_PALETTE
)
6449 image_pixel_convert_PLTE(that
);
6451 /* Image now has RGB channels... */
6453 PNG_CONST png_modifier
*pm
= display
->pm
;
6454 PNG_CONST
unsigned int sample_depth
= that
->sample_depth
;
6457 double rlo
, rhi
, glo
, ghi
, blo
, bhi
, graylo
, grayhi
;
6459 /* Do this using interval arithmetic, otherwise it is too difficult to
6460 * handle the errors correctly.
6462 * To handle the gamma correction work out the upper and lower bounds
6463 * of the digitized value. Assume rounding here - normally the values
6464 * will be identical after this operation if there is only one
6465 * transform, feel free to delete the png_error checks on this below in
6466 * the future (this is just me trying to ensure it works!)
6468 r
= rlo
= rhi
= that
->redf
;
6470 rlo
= digitize(pm
, rlo
, sample_depth
, 1/*round*/);
6472 rhi
= digitize(pm
, rhi
, sample_depth
, 1/*round*/);
6474 g
= glo
= ghi
= that
->greenf
;
6475 glo
-= that
->greene
;
6476 glo
= digitize(pm
, glo
, sample_depth
, 1/*round*/);
6477 ghi
+= that
->greene
;
6478 ghi
= digitize(pm
, ghi
, sample_depth
, 1/*round*/);
6480 b
= blo
= bhi
= that
->bluef
;
6482 blo
= digitize(pm
, blo
, sample_depth
, 1/*round*/);
6483 bhi
+= that
->greene
;
6484 bhi
= digitize(pm
, bhi
, sample_depth
, 1/*round*/);
6486 isgray
= r
==g
&& g
==b
;
6488 if (data
.gamma
!= 1)
6490 PNG_CONST
double power
= 1/data
.gamma
;
6491 PNG_CONST
double abse
= abserr(pm
, sample_depth
, sample_depth
);
6493 /* 'abse' is the absolute error permitted in linear calculations. It
6494 * is used here to capture the error permitted in the handling
6495 * (undoing) of the gamma encoding. Once again digitization occurs
6496 * to handle the upper and lower bounds of the values. This is
6497 * where the real errors are introduced.
6500 rlo
= digitize(pm
, pow(rlo
, power
)-abse
, sample_depth
, 1);
6501 rhi
= digitize(pm
, pow(rhi
, power
)+abse
, sample_depth
, 1);
6504 glo
= digitize(pm
, pow(glo
, power
)-abse
, sample_depth
, 1);
6505 ghi
= digitize(pm
, pow(ghi
, power
)+abse
, sample_depth
, 1);
6508 blo
= digitize(pm
, pow(blo
, power
)-abse
, sample_depth
, 1);
6509 bhi
= digitize(pm
, pow(bhi
, power
)+abse
, sample_depth
, 1);
6512 /* Now calculate the actual gray values. Although the error in the
6513 * coefficients depends on whether they were specified on the command
6514 * line (in which case truncation to 15 bits happened) or not (rounding
6515 * was used) the maxium error in an individual coefficient is always
6516 * 1/32768, because even in the rounding case the requirement that
6517 * coefficients add up to 32768 can cause a larger rounding error.
6519 * The only time when rounding doesn't occur in 1.5.5 and later is when
6520 * the non-gamma code path is used for less than 16 bit data.
6522 gray
= r
* data
.red_coefficient
+ g
* data
.green_coefficient
+
6523 b
* data
.blue_coefficient
;
6526 PNG_CONST
int do_round
= data
.gamma
!= 1 || sample_depth
== 16;
6527 PNG_CONST
double ce
= 1. / 32768;
6529 graylo
= digitize(pm
, rlo
* (data
.red_coefficient
-ce
) +
6530 glo
* (data
.green_coefficient
-ce
) +
6531 blo
* (data
.blue_coefficient
-ce
), sample_depth
, do_round
);
6535 grayhi
= digitize(pm
, rhi
* (data
.red_coefficient
+ce
) +
6536 ghi
* (data
.green_coefficient
+ce
) +
6537 bhi
* (data
.blue_coefficient
+ce
), sample_depth
, do_round
);
6542 /* And invert the gamma. */
6543 if (data
.gamma
!= 1)
6545 PNG_CONST
double power
= data
.gamma
;
6547 gray
= pow(gray
, power
);
6548 graylo
= digitize(pm
, pow(graylo
, power
), sample_depth
, 1);
6549 grayhi
= digitize(pm
, pow(grayhi
, power
), sample_depth
, 1);
6552 /* Now the error can be calculated.
6554 * If r==g==b because there is no overall gamma correction libpng
6555 * currently preserves the original value.
6558 err
= (that
->rede
+ that
->greene
+ that
->bluee
)/3;
6562 err
= fabs(grayhi
-gray
);
6563 if (fabs(gray
- graylo
) > err
)
6564 err
= fabs(graylo
-gray
);
6566 /* Check that this worked: */
6567 if (err
> display
->pm
->limit
)
6572 pos
= safecat(buffer
, sizeof buffer
, pos
, "rgb_to_gray error ");
6573 pos
= safecatd(buffer
, sizeof buffer
, pos
, err
, 6);
6574 pos
= safecat(buffer
, sizeof buffer
, pos
, " exceeds limit ");
6575 pos
= safecatd(buffer
, sizeof buffer
, pos
,
6576 display
->pm
->limit
, 6);
6577 png_error(pp
, buffer
);
6582 that
->bluef
= that
->greenf
= that
->redf
= gray
;
6583 that
->bluee
= that
->greene
= that
->rede
= err
;
6585 /* The sBIT is the minium of the three colour channel sBITs. */
6586 if (that
->red_sBIT
> that
->green_sBIT
)
6587 that
->red_sBIT
= that
->green_sBIT
;
6588 if (that
->red_sBIT
> that
->blue_sBIT
)
6589 that
->red_sBIT
= that
->blue_sBIT
;
6590 that
->blue_sBIT
= that
->green_sBIT
= that
->red_sBIT
;
6592 /* And remove the colour bit in the type: */
6593 if (that
->colour_type
== PNG_COLOR_TYPE_RGB
)
6594 that
->colour_type
= PNG_COLOR_TYPE_GRAY
;
6595 else if (that
->colour_type
== PNG_COLOR_TYPE_RGB_ALPHA
)
6596 that
->colour_type
= PNG_COLOR_TYPE_GRAY_ALPHA
;
6599 this->next
->mod(this->next
, that
, pp
, display
);
6603 image_transform_png_set_rgb_to_gray_add(image_transform
*this,
6604 PNG_CONST image_transform
**that
, png_byte colour_type
, png_byte bit_depth
)
6611 return (colour_type
& PNG_COLOR_MASK_COLOR
) != 0;
6617 #define PT ITSTRUCT(rgb_to_gray)
6618 #undef image_transform_ini
6619 #define image_transform_ini image_transform_default_ini
6620 #endif /* PNG_READ_RGB_TO_GRAY_SUPPORTED */
6622 #ifdef PNG_READ_BACKGROUND_SUPPORTED
6623 /* png_set_background(png_structp, png_const_color_16p background_color,
6624 * int background_gamma_code, int need_expand, double background_gamma)
6625 * png_set_background_fixed(png_structp, png_const_color_16p background_color,
6626 * int background_gamma_code, int need_expand,
6627 * png_fixed_point background_gamma)
6629 * As with rgb_to_gray this ignores the gamma (at present.)
6631 #define data ITDATA(background)
6632 static image_pixel data
;
6635 image_transform_png_set_background_set(PNG_CONST image_transform
*this,
6636 transform_display
*that
, png_structp pp
, png_infop pi
)
6638 png_byte colour_type
, bit_depth
;
6639 png_byte random_bytes
[8]; /* 8 bytes - 64 bits - the biggest pixel */
6642 /* We need a background colour, because we don't know exactly what transforms
6643 * have been set we have to supply the colour in the original file format and
6644 * so we need to know what that is! The background colour is stored in the
6645 * transform_display.
6647 RANDOMIZE(random_bytes
);
6649 /* Read the random value, for colour type 3 the background colour is actually
6650 * expressed as a 24bit rgb, not an index.
6652 colour_type
= that
->this.colour_type
;
6653 if (colour_type
== 3)
6655 colour_type
= PNG_COLOR_TYPE_RGB
;
6660 bit_depth
= that
->this.bit_depth
;
6662 image_pixel_init(&data
, random_bytes
, colour_type
,
6663 bit_depth
, 0/*x*/, 0/*unused: palette*/);
6665 /* Extract the background colour from this image_pixel, but make sure the
6666 * unused fields of 'back' are garbage.
6670 if (colour_type
& PNG_COLOR_MASK_COLOR
)
6672 back
.red
= (png_uint_16
)data
.red
;
6673 back
.green
= (png_uint_16
)data
.green
;
6674 back
.blue
= (png_uint_16
)data
.blue
;
6678 back
.gray
= (png_uint_16
)data
.red
;
6680 # ifdef PNG_FLOATING_POINT_SUPPORTED
6681 png_set_background(pp
, &back
, PNG_BACKGROUND_GAMMA_FILE
, 1/*need expand*/,
6684 png_set_background_fixed(pp
, &back
, PNG_BACKGROUND_GAMMA_FILE
,
6685 1/*need expand*/, 0);
6688 this->next
->set(this->next
, that
, pp
, pi
);
6692 image_transform_png_set_background_mod(PNG_CONST image_transform
*this,
6693 image_pixel
*that
, png_structp pp
, PNG_CONST transform_display
*display
)
6695 /* Check for tRNS first: */
6696 if (that
->have_tRNS
&& that
->colour_type
!= PNG_COLOR_TYPE_PALETTE
)
6697 image_pixel_add_alpha(that
, &display
->this);
6699 /* This is only necessary if the alpha value is less than 1. */
6700 if (that
->alphaf
< 1)
6702 /* Now we do the background calculation without any gamma correction. */
6703 if (that
->alphaf
<= 0)
6705 that
->redf
= data
.redf
;
6706 that
->greenf
= data
.greenf
;
6707 that
->bluef
= data
.bluef
;
6709 that
->rede
= data
.rede
;
6710 that
->greene
= data
.greene
;
6711 that
->bluee
= data
.bluee
;
6713 that
->red_sBIT
= data
.red_sBIT
;
6714 that
->green_sBIT
= data
.green_sBIT
;
6715 that
->blue_sBIT
= data
.blue_sBIT
;
6718 else /* 0 < alpha < 1 */
6720 double alf
= 1 - that
->alphaf
;
6722 that
->redf
= that
->redf
* that
->alphaf
+ data
.redf
* alf
;
6723 that
->rede
= that
->rede
* that
->alphaf
+ data
.rede
* alf
+
6725 that
->greenf
= that
->greenf
* that
->alphaf
+ data
.greenf
* alf
;
6726 that
->greene
= that
->greene
* that
->alphaf
+ data
.greene
* alf
+
6728 that
->bluef
= that
->bluef
* that
->alphaf
+ data
.bluef
* alf
;
6729 that
->bluee
= that
->bluee
* that
->alphaf
+ data
.bluee
* alf
+
6733 /* Remove the alpha type and set the alpha (not in that order.) */
6737 if (that
->colour_type
== PNG_COLOR_TYPE_RGB_ALPHA
)
6738 that
->colour_type
= PNG_COLOR_TYPE_RGB
;
6739 else if (that
->colour_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
6740 that
->colour_type
= PNG_COLOR_TYPE_GRAY
;
6741 /* PNG_COLOR_TYPE_PALETTE is not changed */
6744 this->next
->mod(this->next
, that
, pp
, display
);
6747 #define image_transform_png_set_background_add image_transform_default_add
6752 #define PT ITSTRUCT(background)
6753 #endif /* PNG_READ_BACKGROUND_SUPPORTED */
6755 /* This may just be 'end' if all the transforms are disabled! */
6756 static image_transform
*PNG_CONST image_transform_first
= &PT
;
6759 transform_enable(PNG_CONST
char *name
)
6761 /* Everything starts out enabled, so if we see an 'enable' disabled
6762 * everything else the first time round.
6764 static int all_disabled
= 0;
6766 image_transform
*list
= image_transform_first
;
6768 while (list
!= &image_transform_end
)
6770 if (strcmp(list
->name
, name
) == 0)
6775 else if (!all_disabled
)
6785 fprintf(stderr
, "pngvalid: --transform-enable=%s: unknown transform\n",
6792 transform_disable(PNG_CONST
char *name
)
6794 image_transform
*list
= image_transform_first
;
6796 while (list
!= &image_transform_end
)
6798 if (strcmp(list
->name
, name
) == 0)
6807 fprintf(stderr
, "pngvalid: --transform-disable=%s: unknown transform\n",
6813 image_transform_reset_count(void)
6815 image_transform
*next
= image_transform_first
;
6818 while (next
!= &image_transform_end
)
6820 next
->local_use
= 0;
6826 /* This can only happen if we every have more than 32 transforms (excluding
6827 * the end) in the list.
6829 if (count
> 32) abort();
6833 image_transform_test_counter(png_uint_32 counter
, unsigned int max
)
6835 /* Test the list to see if there is any point contining, given a current
6836 * counter and a 'max' value.
6838 image_transform
*next
= image_transform_first
;
6840 while (next
!= &image_transform_end
)
6842 /* For max 0 or 1 continue until the counter overflows: */
6845 /* Continue if any entry hasn't reacked the max. */
6846 if (max
> 1 && next
->local_use
< max
)
6851 return max
<= 1 && counter
== 0;
6855 image_transform_add(PNG_CONST image_transform
**this, unsigned int max
,
6856 png_uint_32 counter
, char *name
, size_t sizeof_name
, size_t *pos
,
6857 png_byte colour_type
, png_byte bit_depth
)
6859 for (;;) /* until we manage to add something */
6862 image_transform
*list
;
6864 /* Find the next counter value, if the counter is zero this is the start
6865 * of the list. This routine always returns the current counter (not the
6866 * next) so it returns 0 at the end and expects 0 at the beginning.
6868 if (counter
== 0) /* first time */
6870 image_transform_reset_count();
6874 counter
= random_32();
6876 else /* advance the counter */
6880 case 0: ++counter
; break;
6881 case 1: counter
<<= 1; break;
6882 default: counter
= random_32(); break;
6886 /* Now add all these items, if possible */
6887 *this = &image_transform_end
;
6888 list
= image_transform_first
;
6891 /* Go through the whole list adding anything that the counter selects: */
6892 while (list
!= &image_transform_end
)
6894 if ((counter
& mask
) != 0 && list
->enable
&&
6895 (max
== 0 || list
->local_use
< max
))
6897 /* Candidate to add: */
6898 if (list
->add(list
, this, colour_type
, bit_depth
) || max
== 0)
6900 /* Added, so add to the name too. */
6901 *pos
= safecat(name
, sizeof_name
, *pos
, " +");
6902 *pos
= safecat(name
, sizeof_name
, *pos
, list
->name
);
6907 /* Not useful and max>0, so remove it from *this: */
6911 /* And, since we know it isn't useful, stop it being added again
6914 list
->local_use
= max
;
6922 /* Now if anything was added we have something to do. */
6923 if (*this != &image_transform_end
)
6926 /* Nothing added, but was there anything in there to add? */
6927 if (!image_transform_test_counter(counter
, max
))
6932 #ifdef THIS_IS_THE_PROFORMA
6934 image_transform_png_set_@
_set(PNG_CONST image_transform
*this,
6935 transform_display
*that
, png_structp pp
, png_infop pi
)
6938 this->next
->set(this->next
, that
, pp
, pi
);
6942 image_transform_png_set_@
_mod(PNG_CONST image_transform
*this,
6943 image_pixel
*that
, png_structp pp
, PNG_CONST transform_display
*display
)
6945 this->next
->mod(this->next
, that
, pp
, display
);
6949 image_transform_png_set_@
_add(image_transform
*this,
6950 PNG_CONST image_transform
**that
, char *name
, size_t sizeof_name
,
6951 size_t *pos
, png_byte colour_type
, png_byte bit_depth
)
6956 *pos
= safecat(name
, sizeof_name
, *pos
, " +@");
6964 /* png_set_quantize(png_structp, png_colorp palette, int num_palette,
6965 * int maximum_colors, png_const_uint_16p histogram, int full_quantize)
6967 * Very difficult to validate this!
6971 /* The data layout transforms are handled by swapping our own channel data,
6972 * necessarily these need to happen at the end of the transform list because the
6973 * semantic of the channels changes after these are executed. Some of these,
6974 * like set_shift and set_packing, can't be done at present because they change
6975 * the layout of the data at the sub-sample level so sample() won't get the
6978 /* png_set_invert_alpha */
6984 /* png_set_swap_alpha */
6990 /* png_set_filler, (png_structp png_ptr, png_uint_32 filler, int flags)); */
6993 /* png_set_add_alpha, (png_structp png_ptr, png_uint_32 filler, int flags)); */
6996 /* png_set_packing */
6999 /* png_set_packswap */
7002 /* png_set_invert_mono */
7005 /* png_set_shift(png_structp, png_const_color_8p true_bits) */
7009 perform_transform_test(png_modifier
*pm
)
7011 png_byte colour_type
= 0;
7012 png_byte bit_depth
= 0;
7013 int palette_number
= 0;
7015 while (next_format(&colour_type
, &bit_depth
, &palette_number
))
7017 png_uint_32 counter
= 0;
7021 base_pos
= safecat(name
, sizeof name
, 0, "transform:");
7025 size_t pos
= base_pos
;
7026 PNG_CONST image_transform
*list
= 0;
7028 /* 'max' is currently hardwired to '1'; this should be settable on the
7031 counter
= image_transform_add(&list
, 1/*max*/, counter
,
7032 name
, sizeof name
, &pos
, colour_type
, bit_depth
);
7037 /* The command line can change this to checking interlaced images. */
7041 transform_test(pm
, FILEID(colour_type
, bit_depth
, palette_number
,
7042 pm
->interlace_type
, 0, 0, 0), list
, name
);
7051 #endif /* PNG_READ_TRANSFORMS_SUPPORTED */
7053 /********************************* GAMMA TESTS ********************************/
7054 #ifdef PNG_READ_GAMMA_SUPPORTED
7055 /* Reader callbacks and implementations, where they differ from the standard
7058 typedef struct gamma_display
7060 standard_display
this;
7065 double screen_gamma
;
7066 double background_gamma
;
7069 int use_input_precision
;
7073 png_color_16 background_color
;
7075 /* Local variables */
7081 #define ALPHA_MODE_OFFSET 4
7084 gamma_display_init(gamma_display
*dp
, png_modifier
*pm
, png_uint_32 id
,
7085 double file_gamma
, double screen_gamma
, png_byte sbit
, int threshold_test
,
7086 int use_input_precision
, int scale16
, int expand16
,
7087 int do_background
, PNG_CONST png_color_16
*pointer_to_the_background_color
,
7088 double background_gamma
)
7090 /* Standard fields */
7091 standard_display_init(&dp
->this, &pm
->this, id
, 0/*do_interlace*/,
7092 pm
->use_update_info
);
7094 /* Parameter fields */
7096 dp
->file_gamma
= file_gamma
;
7097 dp
->screen_gamma
= screen_gamma
;
7098 dp
->background_gamma
= background_gamma
;
7100 dp
->threshold_test
= threshold_test
;
7101 dp
->use_input_precision
= use_input_precision
;
7102 dp
->scale16
= scale16
;
7103 dp
->expand16
= expand16
;
7104 dp
->do_background
= do_background
;
7105 if (do_background
&& pointer_to_the_background_color
!= 0)
7106 dp
->background_color
= *pointer_to_the_background_color
;
7108 memset(&dp
->background_color
, 0, sizeof dp
->background_color
);
7110 /* Local variable fields */
7111 dp
->maxerrout
= dp
->maxerrpc
= dp
->maxerrabs
= 0;
7115 gamma_info_imp(gamma_display
*dp
, png_structp pp
, png_infop pi
)
7117 /* Reuse the standard stuff as appropriate. */
7118 standard_info_part1(&dp
->this, pp
, pi
);
7120 /* If requested strip 16 to 8 bits - this is handled automagically below
7121 * because the output bit depth is read from the library. Note that there
7122 * are interactions with sBIT but, internally, libpng makes sbit at most
7123 * PNG_MAX_GAMMA_8 when doing the following.
7126 # ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
7127 png_set_scale_16(pp
);
7129 /* The following works both in 1.5.4 and earlier versions: */
7130 # ifdef PNG_READ_16_TO_8_SUPPORTED
7131 png_set_strip_16(pp
);
7133 png_error(pp
, "scale16 (16 to 8 bit conversion) not supported");
7138 # ifdef PNG_READ_EXPAND_16_SUPPORTED
7139 png_set_expand_16(pp
);
7141 png_error(pp
, "expand16 (8 to 16 bit conversion) not supported");
7144 if (dp
->do_background
>= ALPHA_MODE_OFFSET
)
7146 # ifdef PNG_READ_ALPHA_MODE_SUPPORTED
7148 /* This tests the alpha mode handling, if supported. */
7149 int mode
= dp
->do_background
- ALPHA_MODE_OFFSET
;
7151 /* The gamma value is the output gamma, and is in the standard,
7152 * non-inverted, represenation. It provides a default for the PNG file
7153 * gamma, but since the file has a gAMA chunk this does not matter.
7155 PNG_CONST
double sg
= dp
->screen_gamma
;
7156 # ifndef PNG_FLOATING_POINT_SUPPORTED
7157 PNG_CONST png_fixed_point g
= fix(sg
);
7160 # ifdef PNG_FLOATING_POINT_SUPPORTED
7161 png_set_alpha_mode(pp
, mode
, sg
);
7163 png_set_alpha_mode_fixed(pp
, mode
, g
);
7166 /* However, for the standard Porter-Duff algorithm the output defaults
7167 * to be linear, so if the test requires non-linear output it must be
7170 if (mode
== PNG_ALPHA_STANDARD
&& sg
!= 1)
7172 # ifdef PNG_FLOATING_POINT_SUPPORTED
7173 png_set_gamma(pp
, sg
, dp
->file_gamma
);
7175 png_fixed_point f
= fix(dp
->file_gamma
);
7176 png_set_gamma_fixed(pp
, g
, f
);
7181 png_error(pp
, "alpha mode handling not supported");
7187 /* Set up gamma processing. */
7188 # ifdef PNG_FLOATING_POINT_SUPPORTED
7189 png_set_gamma(pp
, dp
->screen_gamma
, dp
->file_gamma
);
7192 png_fixed_point s
= fix(dp
->screen_gamma
);
7193 png_fixed_point f
= fix(dp
->file_gamma
);
7194 png_set_gamma_fixed(pp
, s
, f
);
7198 if (dp
->do_background
)
7200 # ifdef PNG_READ_BACKGROUND_SUPPORTED
7201 /* NOTE: this assumes the caller provided the correct background gamma!
7203 PNG_CONST
double bg
= dp
->background_gamma
;
7204 # ifndef PNG_FLOATING_POINT_SUPPORTED
7205 PNG_CONST png_fixed_point g
= fix(bg
);
7208 # ifdef PNG_FLOATING_POINT_SUPPORTED
7209 png_set_background(pp
, &dp
->background_color
, dp
->do_background
,
7210 0/*need_expand*/, bg
);
7212 png_set_background_fixed(pp
, &dp
->background_color
,
7213 dp
->do_background
, 0/*need_expand*/, g
);
7216 png_error(pp
, "png_set_background not supported");
7222 int i
= dp
->this.use_update_info
;
7223 /* Always do one call, even if use_update_info is 0. */
7225 png_read_update_info(pp
, pi
);
7229 /* Now we may get a different cbRow: */
7230 standard_info_part2(&dp
->this, pp
, pi
, 1 /*images*/);
7234 gamma_info(png_structp pp
, png_infop pi
)
7236 gamma_info_imp(voidcast(gamma_display
*, png_get_progressive_ptr(pp
)), pp
,
7240 /* Validate a single component value - the routine gets the input and output
7241 * sample values as unscaled PNG component values along with a cache of all the
7242 * information required to validate the values.
7244 typedef struct validate_info
7249 int use_input_precision
;
7252 unsigned int sbit_max
;
7253 unsigned int isbit_shift
;
7254 unsigned int outmax
;
7256 double gamma_correction
; /* Overall correction required. */
7257 double file_inverse
; /* Inverse of file gamma. */
7258 double screen_gamma
;
7259 double screen_inverse
; /* Inverse of screen gamma. */
7261 double background_red
; /* Linear background value, red or gray. */
7262 double background_green
;
7263 double background_blue
;
7269 double maxout_total
; /* Total including quantization error */
7276 init_validate_info(validate_info
*vi
, gamma_display
*dp
, png_struct
*pp
,
7277 int in_depth
, int out_depth
)
7279 PNG_CONST
unsigned int outmax
= (1U<<out_depth
)-1;
7284 if (dp
->sbit
> 0 && dp
->sbit
< in_depth
)
7286 vi
->sbit
= dp
->sbit
;
7287 vi
->isbit_shift
= in_depth
- dp
->sbit
;
7292 vi
->sbit
= (png_byte
)in_depth
;
7293 vi
->isbit_shift
= 0;
7296 vi
->sbit_max
= (1U << vi
->sbit
)-1;
7298 /* This mimics the libpng threshold test, '0' is used to prevent gamma
7299 * correction in the validation test.
7301 vi
->screen_gamma
= dp
->screen_gamma
;
7302 if (fabs(vi
->screen_gamma
-1) < PNG_GAMMA_THRESHOLD
)
7303 vi
->screen_gamma
= vi
->screen_inverse
= 0;
7305 vi
->screen_inverse
= 1/vi
->screen_gamma
;
7307 vi
->use_input_precision
= dp
->use_input_precision
;
7308 vi
->outmax
= outmax
;
7309 vi
->maxabs
= abserr(dp
->pm
, in_depth
, out_depth
);
7310 vi
->maxpc
= pcerr(dp
->pm
, in_depth
, out_depth
);
7311 vi
->maxcalc
= calcerr(dp
->pm
, in_depth
, out_depth
);
7312 vi
->maxout
= outerr(dp
->pm
, in_depth
, out_depth
);
7313 vi
->outquant
= output_quantization_factor(dp
->pm
, in_depth
, out_depth
);
7314 vi
->maxout_total
= vi
->maxout
+ vi
->outquant
* .5;
7315 vi
->outlog
= outlog(dp
->pm
, in_depth
, out_depth
);
7317 if ((dp
->this.colour_type
& PNG_COLOR_MASK_ALPHA
) != 0 ||
7318 (dp
->this.colour_type
== 3 && dp
->this.is_transparent
))
7320 vi
->do_background
= dp
->do_background
;
7322 if (vi
->do_background
!= 0)
7324 PNG_CONST
double bg_inverse
= 1/dp
->background_gamma
;
7327 /* Caller must at least put the gray value into the red channel */
7328 r
= dp
->background_color
.red
; r
/= outmax
;
7329 g
= dp
->background_color
.green
; g
/= outmax
;
7330 b
= dp
->background_color
.blue
; b
/= outmax
;
7333 /* libpng doesn't do this optimization, if we do pngvalid will fail.
7335 if (fabs(bg_inverse
-1) >= PNG_GAMMA_THRESHOLD
)
7338 r
= pow(r
, bg_inverse
);
7339 g
= pow(g
, bg_inverse
);
7340 b
= pow(b
, bg_inverse
);
7343 vi
->background_red
= r
;
7344 vi
->background_green
= g
;
7345 vi
->background_blue
= b
;
7349 vi
->do_background
= 0;
7351 if (vi
->do_background
== 0)
7352 vi
->background_red
= vi
->background_green
= vi
->background_blue
= 0;
7354 vi
->gamma_correction
= 1/(dp
->file_gamma
*dp
->screen_gamma
);
7355 if (fabs(vi
->gamma_correction
-1) < PNG_GAMMA_THRESHOLD
)
7356 vi
->gamma_correction
= 0;
7358 vi
->file_inverse
= 1/dp
->file_gamma
;
7359 if (fabs(vi
->file_inverse
-1) < PNG_GAMMA_THRESHOLD
)
7360 vi
->file_inverse
= 0;
7362 vi
->scale16
= dp
->scale16
;
7365 /* This function handles composition of a single non-alpha component. The
7366 * argument is the input sample value, in the range 0..1, and the alpha value.
7367 * The result is the composed, linear, input sample. If alpha is less than zero
7368 * this is the alpha component and the function should not be called!
7371 gamma_component_compose(int do_background
, double input_sample
, double alpha
,
7372 double background
, int *compose
)
7374 switch (do_background
)
7376 case PNG_BACKGROUND_GAMMA_SCREEN
:
7377 case PNG_BACKGROUND_GAMMA_FILE
:
7378 case PNG_BACKGROUND_GAMMA_UNIQUE
:
7379 /* Standard PNG background processing. */
7384 input_sample
= input_sample
* alpha
+ background
* (1-alpha
);
7385 if (compose
!= NULL
)
7390 input_sample
= background
;
7394 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED
7395 case ALPHA_MODE_OFFSET
+ PNG_ALPHA_STANDARD
:
7396 case ALPHA_MODE_OFFSET
+ PNG_ALPHA_BROKEN
:
7397 /* The components are premultiplied in either case and the output is
7398 * gamma encoded (to get standard Porter-Duff we expect the output
7399 * gamma to be set to 1.0!)
7401 case ALPHA_MODE_OFFSET
+ PNG_ALPHA_OPTIMIZED
:
7402 /* The optimization is that the partial-alpha entries are linear
7403 * while the opaque pixels are gamma encoded, but this only affects the
7410 input_sample
*= alpha
;
7411 if (compose
!= NULL
)
7422 /* Standard cases where no compositing is done (so the component
7423 * value is already correct.)
7428 return input_sample
;
7431 /* This API returns the encoded *input* component, in the range 0..1 */
7433 gamma_component_validate(PNG_CONST
char *name
, PNG_CONST validate_info
*vi
,
7434 PNG_CONST
unsigned int id
, PNG_CONST
unsigned int od
,
7435 PNG_CONST
double alpha
/* <0 for the alpha channel itself */,
7436 PNG_CONST
double background
/* component background value */)
7438 PNG_CONST
unsigned int isbit
= id
>> vi
->isbit_shift
;
7439 PNG_CONST
unsigned int sbit_max
= vi
->sbit_max
;
7440 PNG_CONST
unsigned int outmax
= vi
->outmax
;
7441 PNG_CONST
int do_background
= vi
->do_background
;
7445 /* First check on the 'perfect' result obtained from the digitized input
7446 * value, id, and compare this against the actual digitized result, 'od'.
7447 * 'i' is the input result in the range 0..1:
7449 i
= isbit
; i
/= sbit_max
;
7451 /* Check for the fast route: if we don't do any background composition or if
7452 * this is the alpha channel ('alpha' < 0) or if the pixel is opaque then
7453 * just use the gamma_correction field to correct to the final output gamma.
7455 if (alpha
== 1 /* opaque pixel component */ || !do_background
7456 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED
7457 || do_background
== ALPHA_MODE_OFFSET
+ PNG_ALPHA_PNG
7459 || (alpha
< 0 /* alpha channel */
7460 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED
7461 && do_background
!= ALPHA_MODE_OFFSET
+ PNG_ALPHA_BROKEN
7465 /* Then get the gamma corrected version of 'i' and compare to 'od', any
7466 * error less than .5 is insignificant - just quantization of the output
7467 * value to the nearest digital value (nevertheless the error is still
7468 * recorded - it's interesting ;-)
7470 double encoded_sample
= i
;
7471 double encoded_error
;
7473 /* alpha less than 0 indicates the alpha channel, which is always linear
7475 if (alpha
>= 0 && vi
->gamma_correction
> 0)
7476 encoded_sample
= pow(encoded_sample
, vi
->gamma_correction
);
7477 encoded_sample
*= outmax
;
7479 encoded_error
= fabs(od
-encoded_sample
);
7481 if (encoded_error
> vi
->dp
->maxerrout
)
7482 vi
->dp
->maxerrout
= encoded_error
;
7484 if (encoded_error
< vi
->maxout_total
&& encoded_error
< vi
->outlog
)
7488 /* The slow route - attempt to do linear calculations. */
7489 /* There may be an error, or background processing is required, so calculate
7490 * the actual sample values - unencoded light intensity values. Note that in
7491 * practice these are not completely unencoded because they include a
7492 * 'viewing correction' to decrease or (normally) increase the perceptual
7493 * contrast of the image. There's nothing we can do about this - we don't
7494 * know what it is - so assume the unencoded value is perceptually linear.
7497 double input_sample
= i
; /* In range 0..1 */
7498 double output
, error
, encoded_sample
, encoded_error
;
7499 double es_lo
, es_hi
;
7500 int compose
= 0; /* Set to one if composition done */
7501 int output_is_encoded
; /* Set if encoded to screen gamma */
7502 int log_max_error
= 1; /* Check maximum error values */
7503 png_const_charp pass
= 0; /* Reason test passes (or 0 for fail) */
7505 /* Convert to linear light (with the above caveat.) The alpha channel is
7512 if (vi
->file_inverse
> 0)
7513 input_sample
= pow(input_sample
, vi
->file_inverse
);
7515 /* Handle the compose processing: */
7517 input_sample
= gamma_component_compose(do_background
, input_sample
,
7518 alpha
, background
, &tcompose
);
7524 /* And similarly for the output value, but we need to check the background
7525 * handling to linearize it correctly.
7530 output_is_encoded
= vi
->screen_gamma
> 0;
7532 if (alpha
< 0) /* The alpha channel */
7534 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED
7535 if (do_background
!= ALPHA_MODE_OFFSET
+ PNG_ALPHA_BROKEN
)
7538 /* In all other cases the output alpha channel is linear already,
7539 * don't log errors here, they are much larger in linear data.
7541 output_is_encoded
= 0;
7546 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED
7547 else /* A component */
7549 if (do_background
== ALPHA_MODE_OFFSET
+ PNG_ALPHA_OPTIMIZED
&&
7550 alpha
< 1) /* the optimized case - linear output */
7552 if (alpha
> 0) log_max_error
= 0;
7553 output_is_encoded
= 0;
7558 if (output_is_encoded
)
7559 output
= pow(output
, vi
->screen_gamma
);
7561 /* Calculate (or recalculate) the encoded_sample value and repeat the
7562 * check above (unnecessary if we took the fast route, but harmless.)
7564 encoded_sample
= input_sample
;
7565 if (output_is_encoded
)
7566 encoded_sample
= pow(encoded_sample
, vi
->screen_inverse
);
7567 encoded_sample
*= outmax
;
7569 encoded_error
= fabs(od
-encoded_sample
);
7571 /* Don't log errors in the alpha channel, or the 'optimized' case,
7572 * neither are significant to the overall perception.
7574 if (log_max_error
&& encoded_error
> vi
->dp
->maxerrout
)
7575 vi
->dp
->maxerrout
= encoded_error
;
7577 if (encoded_error
< vi
->maxout_total
)
7579 if (encoded_error
< vi
->outlog
)
7582 /* Test passed but error is bigger than the log limit, record why the
7585 pass
= "less than maxout:\n";
7588 /* i: the original input value in the range 0..1
7590 * pngvalid calculations:
7591 * input_sample: linear result; i linearized and composed, range 0..1
7592 * encoded_sample: encoded result; input_sample scaled to ouput bit depth
7594 * libpng calculations:
7595 * output: linear result; od scaled to 0..1 and linearized
7596 * od: encoded result from libpng
7599 /* Now we have the numbers for real errors, both absolute values as as a
7600 * percentage of the correct value (output):
7602 error
= fabs(input_sample
-output
);
7604 if (log_max_error
&& error
> vi
->dp
->maxerrabs
)
7605 vi
->dp
->maxerrabs
= error
;
7607 /* The following is an attempt to ignore the tendency of quantization to
7608 * dominate the percentage errors for lower result values:
7610 if (log_max_error
&& input_sample
> .5)
7612 double percentage_error
= error
/input_sample
;
7613 if (percentage_error
> vi
->dp
->maxerrpc
)
7614 vi
->dp
->maxerrpc
= percentage_error
;
7617 /* Now calculate the digitization limits for 'encoded_sample' using the
7618 * 'max' values. Note that maxout is in the encoded space but maxpc and
7619 * maxabs are in linear light space.
7621 * First find the maximum error in linear light space, range 0..1:
7624 double tmp
= input_sample
* vi
->maxpc
;
7625 if (tmp
< vi
->maxabs
) tmp
= vi
->maxabs
;
7626 /* If 'compose' is true the composition was done in linear space using
7627 * integer arithmetic. This introduces an extra error of +/- 0.5 (at
7628 * least) in the integer space used. 'maxcalc' records this, taking
7629 * into account the possibility that even for 16 bit output 8 bit space
7630 * may have been used.
7632 if (compose
&& tmp
< vi
->maxcalc
) tmp
= vi
->maxcalc
;
7634 /* The 'maxout' value refers to the encoded result, to compare with
7635 * this encode input_sample adjusted by the maximum error (tmp) above.
7637 es_lo
= encoded_sample
- vi
->maxout
;
7639 if (es_lo
> 0 && input_sample
-tmp
> 0)
7641 double low_value
= input_sample
-tmp
;
7642 if (output_is_encoded
)
7643 low_value
= pow(low_value
, vi
->screen_inverse
);
7644 low_value
*= outmax
;
7645 if (low_value
< es_lo
) es_lo
= low_value
;
7647 /* Quantize this appropriately: */
7648 es_lo
= ceil(es_lo
/ vi
->outquant
- .5) * vi
->outquant
;
7654 es_hi
= encoded_sample
+ vi
->maxout
;
7656 if (es_hi
< outmax
&& input_sample
+tmp
< 1)
7658 double high_value
= input_sample
+tmp
;
7659 if (output_is_encoded
)
7660 high_value
= pow(high_value
, vi
->screen_inverse
);
7661 high_value
*= outmax
;
7662 if (high_value
> es_hi
) es_hi
= high_value
;
7664 es_hi
= floor(es_hi
/ vi
->outquant
+ .5) * vi
->outquant
;
7671 /* The primary test is that the final encoded value returned by the
7672 * library should be between the two limits (inclusive) that were
7675 if (od
>= es_lo
&& od
<= es_hi
)
7677 /* The value passes, but we may need to log the information anyway. */
7678 if (encoded_error
< vi
->outlog
)
7682 pass
= "within digitization limits:\n";
7686 /* There has been an error in processing, or we need to log this
7689 double is_lo
, is_hi
;
7691 /* pass is set at this point if either of the tests above would have
7692 * passed. Don't do these additional tests here - just log the
7693 * original [es_lo..es_hi] values.
7695 if (pass
== 0 && vi
->use_input_precision
)
7697 /* Ok, something is wrong - this actually happens in current libpng
7698 * 16-to-8 processing. Assume that the input value (id, adjusted
7699 * for sbit) can be anywhere between value-.5 and value+.5 - quite a
7700 * large range if sbit is low.
7702 double tmp
= (isbit
- .5)/sbit_max
;
7707 else if (alpha
>= 0 && vi
->file_inverse
> 0 && tmp
< 1)
7708 tmp
= pow(tmp
, vi
->file_inverse
);
7710 tmp
= gamma_component_compose(do_background
, tmp
, alpha
, background
,
7713 if (output_is_encoded
&& tmp
> 0 && tmp
< 1)
7714 tmp
= pow(tmp
, vi
->screen_inverse
);
7716 is_lo
= ceil(outmax
* tmp
- vi
->maxout_total
);
7721 tmp
= (isbit
+ .5)/sbit_max
;
7726 else if (alpha
>= 0 && vi
->file_inverse
> 0 && tmp
< 1)
7727 tmp
= pow(tmp
, vi
->file_inverse
);
7729 tmp
= gamma_component_compose(do_background
, tmp
, alpha
, background
,
7732 if (output_is_encoded
&& tmp
> 0 && tmp
< 1)
7733 tmp
= pow(tmp
, vi
->screen_inverse
);
7735 is_hi
= floor(outmax
* tmp
+ vi
->maxout_total
);
7740 if (!(od
< is_lo
|| od
> is_hi
))
7742 if (encoded_error
< vi
->outlog
)
7745 pass
= "within input precision limits:\n";
7748 /* One last chance. If this is an alpha channel and the 16to8
7749 * option has been used and 'inaccurate' scaling is used then the
7750 * bit reduction is obtained by simply using the top 8 bits of the
7753 * This is only done for older libpng versions when the 'inaccurate'
7754 * (chop) method of scaling was used.
7756 # ifndef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED
7757 # if PNG_LIBPNG_VER < 10504
7758 /* This may be required for other components in the future,
7759 * but at present the presence of gamma correction effectively
7760 * prevents the errors in the component scaling (I don't quite
7761 * understand why, but since it's better this way I care not
7762 * to ask, JB 20110419.)
7764 if (pass
== 0 && alpha
< 0 && vi
->scale16
&& vi
->sbit
> 8 &&
7765 vi
->sbit
+ vi
->isbit_shift
== 16)
7767 tmp
= ((id
>> 8) - .5)/255;
7771 is_lo
= ceil(outmax
* tmp
- vi
->maxout_total
);
7772 if (is_lo
< 0) is_lo
= 0;
7778 tmp
= ((id
>> 8) + .5)/255;
7782 is_hi
= floor(outmax
* tmp
+ vi
->maxout_total
);
7783 if (is_hi
> outmax
) is_hi
= outmax
;
7789 if (!(od
< is_lo
|| od
> is_hi
))
7791 if (encoded_error
< vi
->outlog
)
7794 pass
= "within 8 bit limits:\n";
7800 else /* !use_input_precision */
7801 is_lo
= es_lo
, is_hi
= es_hi
;
7803 /* Attempt to output a meaningful error/warning message: the message
7804 * output depends on the background/composite operation being performed
7805 * because this changes what parameters were actually used above.
7809 /* Need either 1/255 or 1/65535 precision here; 3 or 6 decimal
7810 * places. Just use outmax to work out which.
7812 int precision
= (outmax
>= 1000 ? 6 : 3);
7813 int use_input
=1, use_background
=0, do_compose
=0;
7817 pos
= safecat(msg
, sizeof msg
, pos
, "\n\t");
7819 /* Set up the various flags, the output_is_encoded flag above
7820 * is also used below. do_compose is just a double check.
7822 switch (do_background
)
7824 case PNG_BACKGROUND_GAMMA_SCREEN
:
7825 case PNG_BACKGROUND_GAMMA_FILE
:
7826 case PNG_BACKGROUND_GAMMA_UNIQUE
:
7827 use_background
= (alpha
>= 0 && alpha
< 1);
7829 # ifdef PNG_READ_ALPHA_MODE_SUPPORTED
7830 case ALPHA_MODE_OFFSET
+ PNG_ALPHA_STANDARD
:
7831 case ALPHA_MODE_OFFSET
+ PNG_ALPHA_BROKEN
:
7832 case ALPHA_MODE_OFFSET
+ PNG_ALPHA_OPTIMIZED
:
7833 # endif /* ALPHA_MODE_SUPPORTED */
7834 do_compose
= (alpha
> 0 && alpha
< 1);
7835 use_input
= (alpha
!= 0);
7842 /* Check the 'compose' flag */
7843 if (compose
!= do_compose
)
7844 png_error(vi
->pp
, "internal error (compose)");
7846 /* 'name' is the component name */
7847 pos
= safecat(msg
, sizeof msg
, pos
, name
);
7848 pos
= safecat(msg
, sizeof msg
, pos
, "(");
7849 pos
= safecatn(msg
, sizeof msg
, pos
, id
);
7850 if (use_input
|| pass
!= 0/*logging*/)
7854 /* sBIT has reduced the precision of the input: */
7855 pos
= safecat(msg
, sizeof msg
, pos
, ", sbit(");
7856 pos
= safecatn(msg
, sizeof msg
, pos
, vi
->sbit
);
7857 pos
= safecat(msg
, sizeof msg
, pos
, "): ");
7858 pos
= safecatn(msg
, sizeof msg
, pos
, isbit
);
7860 pos
= safecat(msg
, sizeof msg
, pos
, "/");
7861 /* The output is either "id/max" or "id sbit(sbit): isbit/max" */
7862 pos
= safecatn(msg
, sizeof msg
, pos
, vi
->sbit_max
);
7864 pos
= safecat(msg
, sizeof msg
, pos
, ")");
7866 /* A component may have been multiplied (in linear space) by the
7867 * alpha value, 'compose' says whether this is relevant.
7869 if (compose
|| pass
!= 0)
7871 /* If any form of composition is being done report our
7872 * calculated linear value here (the code above doesn't record
7873 * the input value before composition is performed, so what
7874 * gets reported is the value after composition.)
7876 if (use_input
|| pass
!= 0)
7878 if (vi
->file_inverse
> 0)
7880 pos
= safecat(msg
, sizeof msg
, pos
, "^");
7881 pos
= safecatd(msg
, sizeof msg
, pos
, vi
->file_inverse
, 2);
7885 pos
= safecat(msg
, sizeof msg
, pos
, "[linear]");
7887 pos
= safecat(msg
, sizeof msg
, pos
, "*(alpha)");
7888 pos
= safecatd(msg
, sizeof msg
, pos
, alpha
, precision
);
7891 /* Now record the *linear* background value if it was used
7892 * (this function is not passed the original, non-linear,
7893 * value but it is contained in the test name.)
7897 pos
= safecat(msg
, sizeof msg
, pos
, use_input
? "+" : " ");
7898 pos
= safecat(msg
, sizeof msg
, pos
, "(background)");
7899 pos
= safecatd(msg
, sizeof msg
, pos
, background
, precision
);
7900 pos
= safecat(msg
, sizeof msg
, pos
, "*");
7901 pos
= safecatd(msg
, sizeof msg
, pos
, 1-alpha
, precision
);
7905 /* Report the calculated value (input_sample) and the linearized
7906 * libpng value (output) unless this is just a component gamma
7909 if (compose
|| alpha
< 0 || pass
!= 0)
7911 pos
= safecat(msg
, sizeof msg
, pos
,
7912 pass
!= 0 ? " =\n\t" : " = ");
7913 pos
= safecatd(msg
, sizeof msg
, pos
, input_sample
, precision
);
7914 pos
= safecat(msg
, sizeof msg
, pos
, " (libpng: ");
7915 pos
= safecatd(msg
, sizeof msg
, pos
, output
, precision
);
7916 pos
= safecat(msg
, sizeof msg
, pos
, ")");
7918 /* Finally report the output gamma encoding, if any. */
7919 if (output_is_encoded
)
7921 pos
= safecat(msg
, sizeof msg
, pos
, " ^");
7922 pos
= safecatd(msg
, sizeof msg
, pos
, vi
->screen_inverse
, 2);
7923 pos
= safecat(msg
, sizeof msg
, pos
, "(to screen) =");
7927 pos
= safecat(msg
, sizeof msg
, pos
, " [screen is linear] =");
7930 if ((!compose
&& alpha
>= 0) || pass
!= 0)
7932 if (pass
!= 0) /* logging */
7933 pos
= safecat(msg
, sizeof msg
, pos
, "\n\t[overall:");
7935 /* This is the non-composition case, the internal linear
7936 * values are irrelevant (though the log below will reveal
7937 * them.) Output a much shorter warning/error message and report
7938 * the overall gamma correction.
7940 if (vi
->gamma_correction
> 0)
7942 pos
= safecat(msg
, sizeof msg
, pos
, " ^");
7943 pos
= safecatd(msg
, sizeof msg
, pos
, vi
->gamma_correction
, 2);
7944 pos
= safecat(msg
, sizeof msg
, pos
, "(gamma correction) =");
7948 pos
= safecat(msg
, sizeof msg
, pos
,
7949 " [no gamma correction] =");
7952 pos
= safecat(msg
, sizeof msg
, pos
, "]");
7955 /* This is our calculated encoded_sample which should (but does
7958 pos
= safecat(msg
, sizeof msg
, pos
, pass
!= 0 ? "\n\t" : " ");
7959 pos
= safecatd(msg
, sizeof msg
, pos
, is_lo
, 1);
7960 pos
= safecat(msg
, sizeof msg
, pos
, " < ");
7961 pos
= safecatd(msg
, sizeof msg
, pos
, encoded_sample
, 1);
7962 pos
= safecat(msg
, sizeof msg
, pos
, " (libpng: ");
7963 pos
= safecatn(msg
, sizeof msg
, pos
, od
);
7964 pos
= safecat(msg
, sizeof msg
, pos
, ")");
7965 pos
= safecat(msg
, sizeof msg
, pos
, "/");
7966 pos
= safecatn(msg
, sizeof msg
, pos
, outmax
);
7967 pos
= safecat(msg
, sizeof msg
, pos
, " < ");
7968 pos
= safecatd(msg
, sizeof msg
, pos
, is_hi
, 1);
7970 if (pass
== 0) /* The error condition */
7972 # ifdef PNG_WARNINGS_SUPPORTED
7973 png_warning(vi
->pp
, msg
);
7975 store_warning(vi
->pp
, msg
);
7979 else /* logging this value */
7980 store_verbose(&vi
->dp
->pm
->this, vi
->pp
, pass
, msg
);
7989 gamma_image_validate(gamma_display
*dp
, png_structp pp
, png_infop pi
)
7991 /* Get some constants derived from the input and output file formats: */
7992 PNG_CONST png_store
* PNG_CONST ps
= dp
->this.ps
;
7993 PNG_CONST png_byte in_ct
= dp
->this.colour_type
;
7994 PNG_CONST png_byte in_bd
= dp
->this.bit_depth
;
7995 PNG_CONST png_uint_32 w
= dp
->this.w
;
7996 PNG_CONST png_uint_32 h
= dp
->this.h
;
7997 PNG_CONST
size_t cbRow
= dp
->this.cbRow
;
7998 PNG_CONST png_byte out_ct
= png_get_color_type(pp
, pi
);
7999 PNG_CONST png_byte out_bd
= png_get_bit_depth(pp
, pi
);
8001 /* There are three sources of error, firstly the quantization in the
8002 * file encoding, determined by sbit and/or the file depth, secondly
8003 * the output (screen) gamma and thirdly the output file encoding.
8005 * Since this API receives the screen and file gamma in double
8006 * precision it is possible to calculate an exact answer given an input
8007 * pixel value. Therefore we assume that the *input* value is exact -
8008 * sample/maxsample - calculate the corresponding gamma corrected
8009 * output to the limits of double precision arithmetic and compare with
8010 * what libpng returns.
8012 * Since the library must quantize the output to 8 or 16 bits there is
8013 * a fundamental limit on the accuracy of the output of +/-.5 - this
8014 * quantization limit is included in addition to the other limits
8015 * specified by the paramaters to the API. (Effectively, add .5
8018 * The behavior of the 'sbit' paramter is defined by section 12.5
8019 * (sample depth scaling) of the PNG spec. That section forces the
8020 * decoder to assume that the PNG values have been scaled if sBIT is
8023 * png-sample = floor( input-sample * (max-out/max-in) + .5);
8025 * This means that only a subset of the possible PNG values should
8026 * appear in the input. However, the spec allows the encoder to use a
8027 * variety of approximations to the above and doesn't require any
8028 * restriction of the values produced.
8030 * Nevertheless the spec requires that the upper 'sBIT' bits of the
8031 * value stored in a PNG file be the original sample bits.
8032 * Consequently the code below simply scales the top sbit bits by
8033 * (1<<sbit)-1 to obtain an original sample value.
8035 * Because there is limited precision in the input it is arguable that
8036 * an acceptable result is any valid result from input-.5 to input+.5.
8037 * The basic tests below do not do this, however if 'use_input_precision'
8038 * is set a subsequent test is performed below.
8040 PNG_CONST
unsigned int samples_per_pixel
= (out_ct
& 2U) ? 3U : 1U;
8043 PNG_CONST store_palette_entry
*in_palette
= dp
->this.palette
;
8044 PNG_CONST
int in_is_transparent
= dp
->this.is_transparent
;
8045 int out_npalette
= -1;
8046 int out_is_transparent
= 0; /* Just refers to the palette case */
8047 store_palette out_palette
;
8050 /* Check for row overwrite errors */
8051 store_image_check(dp
->this.ps
, pp
, 0);
8053 /* Supply the input and output sample depths here - 8 for an indexed image,
8054 * otherwise the bit depth.
8056 init_validate_info(&vi
, dp
, pp
, in_ct
==3?8:in_bd
, out_ct
==3?8:out_bd
);
8058 processing
= (vi
.gamma_correction
> 0 && !dp
->threshold_test
)
8059 || in_bd
!= out_bd
|| in_ct
!= out_ct
|| vi
.do_background
;
8061 /* TODO: FIX THIS: MAJOR BUG! If the transformations all happen inside
8062 * the palette there is no way of finding out, because libpng fails to
8063 * update the palette on png_read_update_info. Indeed, libpng doesn't
8064 * even do the required work until much later, when it doesn't have any
8065 * info pointer. Oops. For the moment 'processing' is turned off if
8066 * out_ct is palette.
8068 if (in_ct
== 3 && out_ct
== 3)
8071 if (processing
&& out_ct
== 3)
8072 out_is_transparent
= read_palette(out_palette
, &out_npalette
, pp
, pi
);
8076 png_const_bytep pRow
= store_image_row(ps
, pp
, 0, y
);
8077 png_byte std
[STANDARD_ROWMAX
];
8079 transform_row(pp
, std
, in_ct
, in_bd
, y
);
8087 double alpha
= 1; /* serves as a flag value */
8089 /* Record the palette index for index images. */
8090 PNG_CONST
unsigned int in_index
=
8091 in_ct
== 3 ? sample(std
, 3, in_bd
, x
, 0) : 256;
8092 PNG_CONST
unsigned int out_index
=
8093 out_ct
== 3 ? sample(std
, 3, out_bd
, x
, 0) : 256;
8095 /* Handle input alpha - png_set_background will cause the output
8096 * alpha to disappear so there is nothing to check.
8098 if ((in_ct
& PNG_COLOR_MASK_ALPHA
) != 0 || (in_ct
== 3 &&
8101 PNG_CONST
unsigned int input_alpha
= in_ct
== 3 ?
8102 dp
->this.palette
[in_index
].alpha
:
8103 sample(std
, in_ct
, in_bd
, x
, samples_per_pixel
);
8105 unsigned int output_alpha
= 65536 /* as a flag value */;
8109 if (out_is_transparent
)
8110 output_alpha
= out_palette
[out_index
].alpha
;
8113 else if ((out_ct
& PNG_COLOR_MASK_ALPHA
) != 0)
8114 output_alpha
= sample(pRow
, out_ct
, out_bd
, x
,
8117 if (output_alpha
!= 65536)
8118 alpha
= gamma_component_validate("alpha", &vi
, input_alpha
,
8119 output_alpha
, -1/*alpha*/, 0/*background*/);
8121 else /* no alpha in output */
8123 /* This is a copy of the calculation of 'i' above in order to
8124 * have the alpha value to use in the background calculation.
8126 alpha
= input_alpha
>> vi
.isbit_shift
;
8127 alpha
/= vi
.sbit_max
;
8131 /* Handle grayscale or RGB components. */
8132 if ((in_ct
& PNG_COLOR_MASK_COLOR
) == 0) /* grayscale */
8133 (void)gamma_component_validate("gray", &vi
,
8134 sample(std
, in_ct
, in_bd
, x
, 0),
8135 sample(pRow
, out_ct
, out_bd
, x
, 0), alpha
/*component*/,
8137 else /* RGB or palette */
8139 (void)gamma_component_validate("red", &vi
,
8140 in_ct
== 3 ? in_palette
[in_index
].red
:
8141 sample(std
, in_ct
, in_bd
, x
, 0),
8142 out_ct
== 3 ? out_palette
[out_index
].red
:
8143 sample(pRow
, out_ct
, out_bd
, x
, 0),
8144 alpha
/*component*/, vi
.background_red
);
8146 (void)gamma_component_validate("green", &vi
,
8147 in_ct
== 3 ? in_palette
[in_index
].green
:
8148 sample(std
, in_ct
, in_bd
, x
, 1),
8149 out_ct
== 3 ? out_palette
[out_index
].green
:
8150 sample(pRow
, out_ct
, out_bd
, x
, 1),
8151 alpha
/*component*/, vi
.background_green
);
8153 (void)gamma_component_validate("blue", &vi
,
8154 in_ct
== 3 ? in_palette
[in_index
].blue
:
8155 sample(std
, in_ct
, in_bd
, x
, 2),
8156 out_ct
== 3 ? out_palette
[out_index
].blue
:
8157 sample(pRow
, out_ct
, out_bd
, x
, 2),
8158 alpha
/*component*/, vi
.background_blue
);
8163 else if (memcmp(std
, pRow
, cbRow
) != 0)
8167 /* No transform is expected on the threshold tests. */
8168 sprintf(msg
, "gamma: below threshold row %d changed", y
);
8172 } /* row (y) loop */
8174 dp
->this.ps
->validated
= 1;
8178 gamma_end(png_structp pp
, png_infop pi
)
8180 gamma_display
*dp
= voidcast(gamma_display
*, png_get_progressive_ptr(pp
));
8182 if (!dp
->this.speed
)
8183 gamma_image_validate(dp
, pp
, pi
);
8185 dp
->this.ps
->validated
= 1;
8188 /* A single test run checking a gamma transformation.
8190 * maxabs: maximum absolute error as a fraction
8191 * maxout: maximum output error in the output units
8192 * maxpc: maximum percentage error (as a percentage)
8195 gamma_test(png_modifier
*pmIn
, PNG_CONST png_byte colour_typeIn
,
8196 PNG_CONST png_byte bit_depthIn
, PNG_CONST
int palette_numberIn
,
8197 PNG_CONST
int interlace_typeIn
,
8198 PNG_CONST
double file_gammaIn
, PNG_CONST
double screen_gammaIn
,
8199 PNG_CONST png_byte sbitIn
, PNG_CONST
int threshold_testIn
,
8200 PNG_CONST
char *name
,
8201 PNG_CONST
int use_input_precisionIn
, PNG_CONST
int scale16In
,
8202 PNG_CONST
int expand16In
, PNG_CONST
int do_backgroundIn
,
8203 PNG_CONST png_color_16
*bkgd_colorIn
, double bkgd_gammaIn
)
8206 context(&pmIn
->this, fault
);
8208 gamma_display_init(&d
, pmIn
, FILEID(colour_typeIn
, bit_depthIn
,
8209 palette_numberIn
, interlace_typeIn
, 0, 0, 0),
8210 file_gammaIn
, screen_gammaIn
, sbitIn
,
8211 threshold_testIn
, use_input_precisionIn
, scale16In
,
8212 expand16In
, do_backgroundIn
, bkgd_colorIn
, bkgd_gammaIn
);
8218 gama_modification gama_mod
;
8219 srgb_modification srgb_mod
;
8220 sbit_modification sbit_mod
;
8222 /* For the moment don't use the png_modifier support here. */
8223 d
.pm
->encoding_counter
= 0;
8224 modifier_set_encoding(d
.pm
); /* Just resets everything */
8225 d
.pm
->current_gamma
= d
.file_gamma
;
8227 /* Make an appropriate modifier to set the PNG file gamma to the
8228 * given gamma value and the sBIT chunk to the given precision.
8230 d
.pm
->modifications
= NULL
;
8231 gama_modification_init(&gama_mod
, d
.pm
, d
.file_gamma
);
8232 srgb_modification_init(&srgb_mod
, d
.pm
, 127 /*delete*/);
8234 sbit_modification_init(&sbit_mod
, d
.pm
, d
.sbit
);
8236 modification_reset(d
.pm
->modifications
);
8238 /* Get a png_struct for writing the image. */
8239 pp
= set_modifier_for_read(d
.pm
, &pi
, d
.this.id
, name
);
8240 standard_palette_init(&d
.this);
8242 /* Introduce the correct read function. */
8243 if (d
.pm
->this.progressive
)
8245 /* Share the row function with the standard implementation. */
8246 png_set_progressive_read_fn(pp
, &d
, gamma_info
, progressive_row
,
8249 /* Now feed data into the reader until we reach the end: */
8250 modifier_progressive_read(d
.pm
, pp
, pi
);
8254 /* modifier_read expects a png_modifier* */
8255 png_set_read_fn(pp
, d
.pm
, modifier_read
);
8257 /* Check the header values: */
8258 png_read_info(pp
, pi
);
8260 /* Process the 'info' requirements. Only one image is generated */
8261 gamma_info_imp(&d
, pp
, pi
);
8263 sequential_row(&d
.this, pp
, pi
, -1, 0);
8266 gamma_image_validate(&d
, pp
, pi
);
8268 d
.this.ps
->validated
= 1;
8271 modifier_reset(d
.pm
);
8273 if (d
.pm
->log
&& !d
.threshold_test
&& !d
.this.speed
)
8274 fprintf(stderr
, "%d bit %s %s: max error %f (%.2g, %2g%%)\n",
8275 d
.this.bit_depth
, colour_types
[d
.this.colour_type
], name
,
8276 d
.maxerrout
, d
.maxerrabs
, 100*d
.maxerrpc
);
8278 /* Log the summary values too. */
8279 if (d
.this.colour_type
== 0 || d
.this.colour_type
== 4)
8281 switch (d
.this.bit_depth
)
8287 if (d
.maxerrout
> d
.pm
->error_gray_2
)
8288 d
.pm
->error_gray_2
= d
.maxerrout
;
8293 if (d
.maxerrout
> d
.pm
->error_gray_4
)
8294 d
.pm
->error_gray_4
= d
.maxerrout
;
8299 if (d
.maxerrout
> d
.pm
->error_gray_8
)
8300 d
.pm
->error_gray_8
= d
.maxerrout
;
8305 if (d
.maxerrout
> d
.pm
->error_gray_16
)
8306 d
.pm
->error_gray_16
= d
.maxerrout
;
8311 png_error(pp
, "bad bit depth (internal: 1)");
8315 else if (d
.this.colour_type
== 2 || d
.this.colour_type
== 6)
8317 switch (d
.this.bit_depth
)
8321 if (d
.maxerrout
> d
.pm
->error_color_8
)
8322 d
.pm
->error_color_8
= d
.maxerrout
;
8328 if (d
.maxerrout
> d
.pm
->error_color_16
)
8329 d
.pm
->error_color_16
= d
.maxerrout
;
8334 png_error(pp
, "bad bit depth (internal: 2)");
8338 else if (d
.this.colour_type
== 3)
8340 if (d
.maxerrout
> d
.pm
->error_indexed
)
8341 d
.pm
->error_indexed
= d
.maxerrout
;
8346 modifier_reset((png_modifier
*)fault
);
8349 static void gamma_threshold_test(png_modifier
*pm
, png_byte colour_type
,
8350 png_byte bit_depth
, int interlace_type
, double file_gamma
,
8351 double screen_gamma
)
8355 pos
= safecat(name
, sizeof name
, pos
, "threshold ");
8356 pos
= safecatd(name
, sizeof name
, pos
, file_gamma
, 3);
8357 pos
= safecat(name
, sizeof name
, pos
, "/");
8358 pos
= safecatd(name
, sizeof name
, pos
, screen_gamma
, 3);
8360 (void)gamma_test(pm
, colour_type
, bit_depth
, 0/*palette*/, interlace_type
,
8361 file_gamma
, screen_gamma
, 0/*sBIT*/, 1/*threshold test*/, name
,
8362 0 /*no input precision*/,
8363 0 /*no scale16*/, 0 /*no expand16*/, 0 /*no background*/, 0 /*hence*/,
8364 0 /*no background gamma*/);
8368 perform_gamma_threshold_tests(png_modifier
*pm
)
8370 png_byte colour_type
= 0;
8371 png_byte bit_depth
= 0;
8372 int palette_number
= 0;
8374 /* Don't test more than one instance of each palette - it's pointless, in
8375 * fact this test is somewhat excessive since libpng doesn't make this
8376 * decision based on colour type or bit depth!
8378 while (next_format(&colour_type
, &bit_depth
, &palette_number
))
8379 if (palette_number
== 0)
8381 double test_gamma
= 1.0;
8382 while (test_gamma
>= .4)
8384 /* There's little point testing the interlacing vs non-interlacing,
8385 * but this can be set from the command line.
8387 gamma_threshold_test(pm
, colour_type
, bit_depth
, pm
->interlace_type
,
8388 test_gamma
, 1/test_gamma
);
8392 /* And a special test for sRGB */
8393 gamma_threshold_test(pm
, colour_type
, bit_depth
, pm
->interlace_type
,
8401 static void gamma_transform_test(png_modifier
*pm
,
8402 PNG_CONST png_byte colour_type
, PNG_CONST png_byte bit_depth
,
8403 PNG_CONST
int palette_number
,
8404 PNG_CONST
int interlace_type
, PNG_CONST
double file_gamma
,
8405 PNG_CONST
double screen_gamma
, PNG_CONST png_byte sbit
,
8406 PNG_CONST
int use_input_precision
, PNG_CONST
int scale16
)
8411 if (sbit
!= bit_depth
&& sbit
!= 0)
8413 pos
= safecat(name
, sizeof name
, pos
, "sbit(");
8414 pos
= safecatn(name
, sizeof name
, pos
, sbit
);
8415 pos
= safecat(name
, sizeof name
, pos
, ") ");
8419 pos
= safecat(name
, sizeof name
, pos
, "gamma ");
8422 pos
= safecat(name
, sizeof name
, pos
, "16to8 ");
8424 pos
= safecatd(name
, sizeof name
, pos
, file_gamma
, 3);
8425 pos
= safecat(name
, sizeof name
, pos
, "->");
8426 pos
= safecatd(name
, sizeof name
, pos
, screen_gamma
, 3);
8428 gamma_test(pm
, colour_type
, bit_depth
, palette_number
, interlace_type
,
8429 file_gamma
, screen_gamma
, sbit
, 0, name
, use_input_precision
,
8430 scale16
, pm
->test_gamma_expand16
, 0 , 0, 0);
8433 static void perform_gamma_transform_tests(png_modifier
*pm
)
8435 png_byte colour_type
= 0;
8436 png_byte bit_depth
= 0;
8437 int palette_number
= 0;
8439 while (next_format(&colour_type
, &bit_depth
, &palette_number
))
8443 for (i
=0; i
<pm
->ngamma_tests
; ++i
) for (j
=0; j
<pm
->ngamma_tests
; ++j
)
8446 gamma_transform_test(pm
, colour_type
, bit_depth
, palette_number
,
8447 pm
->interlace_type
, 1/pm
->gammas
[i
], pm
->gammas
[j
], 0/*sBIT*/,
8448 pm
->use_input_precision
, 0 /*do not scale16*/);
8456 static void perform_gamma_sbit_tests(png_modifier
*pm
)
8460 /* The only interesting cases are colour and grayscale, alpha is ignored here
8461 * for overall speed. Only bit depths where sbit is less than the bit depth
8464 for (sbit
=pm
->sbitlow
; sbit
<(1<<READ_BDHI
); ++sbit
)
8466 png_byte colour_type
, bit_depth
;
8469 colour_type
= bit_depth
= 0;
8472 while (next_format(&colour_type
, &bit_depth
, &npalette
))
8473 if ((colour_type
& PNG_COLOR_MASK_ALPHA
) == 0 &&
8474 ((colour_type
== 3 && sbit
< 8) ||
8475 (colour_type
!= 3 && sbit
< bit_depth
)))
8479 for (i
=0; i
<pm
->ngamma_tests
; ++i
)
8483 for (j
=0; j
<pm
->ngamma_tests
; ++j
) if (i
!= j
)
8485 gamma_transform_test(pm
, colour_type
, bit_depth
, npalette
,
8486 pm
->interlace_type
, 1/pm
->gammas
[i
], pm
->gammas
[j
],
8487 sbit
, pm
->use_input_precision_sbit
, 0 /*scale16*/);
8497 /* Note that this requires a 16 bit source image but produces 8 bit output, so
8498 * we only need the 16bit write support, but the 16 bit images are only
8499 * generated if DO_16BIT is defined.
8502 static void perform_gamma_scale16_tests(png_modifier
*pm
)
8504 # ifndef PNG_MAX_GAMMA_8
8505 # define PNG_MAX_GAMMA_8 11
8507 /* Include the alpha cases here. Note that sbit matches the internal value
8508 * used by the library - otherwise we will get spurious errors from the
8509 * internal sbit style approximation.
8511 * The threshold test is here because otherwise the 16 to 8 conversion will
8512 * proceed *without* gamma correction, and the tests above will fail (but not
8513 * by much) - this could be fixed, it only appears with the -g option.
8516 for (i
=0; i
<pm
->ngamma_tests
; ++i
)
8518 for (j
=0; j
<pm
->ngamma_tests
; ++j
)
8521 fabs(pm
->gammas
[j
]/pm
->gammas
[i
]-1) >= PNG_GAMMA_THRESHOLD
)
8523 gamma_transform_test(pm
, 0, 16, 0, pm
->interlace_type
,
8524 1/pm
->gammas
[i
], pm
->gammas
[j
], PNG_MAX_GAMMA_8
,
8525 pm
->use_input_precision_16to8
, 1 /*scale16*/);
8530 gamma_transform_test(pm
, 2, 16, 0, pm
->interlace_type
,
8531 1/pm
->gammas
[i
], pm
->gammas
[j
], PNG_MAX_GAMMA_8
,
8532 pm
->use_input_precision_16to8
, 1 /*scale16*/);
8537 gamma_transform_test(pm
, 4, 16, 0, pm
->interlace_type
,
8538 1/pm
->gammas
[i
], pm
->gammas
[j
], PNG_MAX_GAMMA_8
,
8539 pm
->use_input_precision_16to8
, 1 /*scale16*/);
8544 gamma_transform_test(pm
, 6, 16, 0, pm
->interlace_type
,
8545 1/pm
->gammas
[i
], pm
->gammas
[j
], PNG_MAX_GAMMA_8
,
8546 pm
->use_input_precision_16to8
, 1 /*scale16*/);
8554 #endif /* 16 to 8 bit conversion */
8556 #if defined PNG_READ_BACKGROUND_SUPPORTED ||\
8557 defined PNG_READ_ALPHA_MODE_SUPPORTED
8558 static void gamma_composition_test(png_modifier
*pm
,
8559 PNG_CONST png_byte colour_type
, PNG_CONST png_byte bit_depth
,
8560 PNG_CONST
int palette_number
,
8561 PNG_CONST
int interlace_type
, PNG_CONST
double file_gamma
,
8562 PNG_CONST
double screen_gamma
,
8563 PNG_CONST
int use_input_precision
, PNG_CONST
int do_background
,
8564 PNG_CONST
int expand_16
)
8567 png_const_charp base
;
8570 png_color_16 background
;
8572 /* Make up a name and get an appropriate background gamma value. */
8573 switch (do_background
)
8577 bg
= 4; /* should not be used */
8579 case PNG_BACKGROUND_GAMMA_SCREEN
:
8580 base
= " bckg(Screen):";
8581 bg
= 1/screen_gamma
;
8583 case PNG_BACKGROUND_GAMMA_FILE
:
8584 base
= " bckg(File):";
8587 case PNG_BACKGROUND_GAMMA_UNIQUE
:
8588 base
= " bckg(Unique):";
8589 /* This tests the handling of a unique value, the math is such that the
8590 * value tends to be <1, but is neither screen nor file (even if they
8593 bg
= (file_gamma
+ screen_gamma
) / 3;
8595 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED
8596 case ALPHA_MODE_OFFSET
+ PNG_ALPHA_PNG
:
8597 base
= " alpha(PNG)";
8598 bg
= 4; /* should not be used */
8600 case ALPHA_MODE_OFFSET
+ PNG_ALPHA_STANDARD
:
8601 base
= " alpha(Porter-Duff)";
8602 bg
= 4; /* should not be used */
8604 case ALPHA_MODE_OFFSET
+ PNG_ALPHA_OPTIMIZED
:
8605 base
= " alpha(Optimized)";
8606 bg
= 4; /* should not be used */
8608 case ALPHA_MODE_OFFSET
+ PNG_ALPHA_BROKEN
:
8609 base
= " alpha(Broken)";
8610 bg
= 4; /* should not be used */
8615 /* Use random background values - the background is always presented in the
8616 * output space (8 or 16 bit components).
8618 if (expand_16
|| bit_depth
== 16)
8620 png_uint_32 r
= random_32();
8622 background
.red
= (png_uint_16
)r
;
8623 background
.green
= (png_uint_16
)(r
>> 16);
8625 background
.blue
= (png_uint_16
)r
;
8626 background
.gray
= (png_uint_16
)(r
>> 16);
8629 else /* 8 bit colors */
8631 png_uint_32 r
= random_32();
8633 background
.red
= (png_byte
)r
;
8634 background
.green
= (png_byte
)(r
>> 8);
8635 background
.blue
= (png_byte
)(r
>> 16);
8636 background
.gray
= (png_byte
)(r
>> 24);
8639 background
.index
= 193; /* rgb(193,193,193) to detect errors */
8640 if (!(colour_type
& PNG_COLOR_MASK_COLOR
))
8642 /* Grayscale input, we do not convert to RGB (TBD), so we must set the
8643 * background to gray - else libpng seems to fail.
8645 background
.red
= background
.green
= background
.blue
= background
.gray
;
8648 pos
= safecat(name
, sizeof name
, pos
, "gamma ");
8649 pos
= safecatd(name
, sizeof name
, pos
, file_gamma
, 3);
8650 pos
= safecat(name
, sizeof name
, pos
, "->");
8651 pos
= safecatd(name
, sizeof name
, pos
, screen_gamma
, 3);
8653 pos
= safecat(name
, sizeof name
, pos
, base
);
8654 if (do_background
< ALPHA_MODE_OFFSET
)
8656 /* Include the background color and gamma in the name: */
8657 pos
= safecat(name
, sizeof name
, pos
, "(");
8658 /* This assumes no expand gray->rgb - the current code won't handle that!
8660 if (colour_type
& PNG_COLOR_MASK_COLOR
)
8662 pos
= safecatn(name
, sizeof name
, pos
, background
.red
);
8663 pos
= safecat(name
, sizeof name
, pos
, ",");
8664 pos
= safecatn(name
, sizeof name
, pos
, background
.green
);
8665 pos
= safecat(name
, sizeof name
, pos
, ",");
8666 pos
= safecatn(name
, sizeof name
, pos
, background
.blue
);
8669 pos
= safecatn(name
, sizeof name
, pos
, background
.gray
);
8670 pos
= safecat(name
, sizeof name
, pos
, ")^");
8671 pos
= safecatd(name
, sizeof name
, pos
, bg
, 3);
8674 gamma_test(pm
, colour_type
, bit_depth
, palette_number
, interlace_type
,
8675 file_gamma
, screen_gamma
, 0/*sBIT*/, 0, name
, use_input_precision
,
8676 0/*strip 16*/, expand_16
, do_background
, &background
, bg
);
8681 perform_gamma_composition_tests(png_modifier
*pm
, int do_background
,
8684 png_byte colour_type
= 0;
8685 png_byte bit_depth
= 0;
8686 int palette_number
= 0;
8688 /* Skip the non-alpha cases - there is no setting of a transparency colour at
8691 while (next_format(&colour_type
, &bit_depth
, &palette_number
))
8692 if ((colour_type
& PNG_COLOR_MASK_ALPHA
) != 0)
8696 /* Don't skip the i==j case here - it's relevant. */
8697 for (i
=0; i
<pm
->ngamma_tests
; ++i
) for (j
=0; j
<pm
->ngamma_tests
; ++j
)
8699 gamma_composition_test(pm
, colour_type
, bit_depth
, palette_number
,
8700 pm
->interlace_type
, 1/pm
->gammas
[i
], pm
->gammas
[j
],
8701 pm
->use_input_precision
, do_background
, expand_16
);
8708 #endif /* READ_BACKGROUND || READ_ALPHA_MODE */
8711 init_gamma_errors(png_modifier
*pm
)
8713 pm
->error_gray_2
= pm
->error_gray_4
= pm
->error_gray_8
= 0;
8714 pm
->error_color_8
= 0;
8715 pm
->error_indexed
= 0;
8716 pm
->error_gray_16
= pm
->error_color_16
= 0;
8720 summarize_gamma_errors(png_modifier
*pm
, png_const_charp who
, int low_bit_depth
)
8723 printf("Gamma correction with %s:\n", who
);
8727 printf(" 2 bit gray: %.5f\n", pm
->error_gray_2
);
8728 printf(" 4 bit gray: %.5f\n", pm
->error_gray_4
);
8729 printf(" 8 bit gray: %.5f\n", pm
->error_gray_8
);
8730 printf(" 8 bit color: %.5f\n", pm
->error_color_8
);
8731 printf(" indexed: %.5f\n", pm
->error_indexed
);
8735 printf(" 16 bit gray: %.5f\n", pm
->error_gray_16
);
8736 printf(" 16 bit color: %.5f\n", pm
->error_color_16
);
8741 perform_gamma_test(png_modifier
*pm
, int summary
)
8743 /*TODO: remove this*/
8744 /* Save certain values for the temporary overrides below. */
8745 unsigned int calculations_use_input_precision
=
8746 pm
->calculations_use_input_precision
;
8747 double maxout8
= pm
->maxout8
;
8749 /* First some arbitrary no-transform tests: */
8750 if (!pm
->this.speed
&& pm
->test_gamma_threshold
)
8752 perform_gamma_threshold_tests(pm
);
8758 /* Now some real transforms. */
8759 if (pm
->test_gamma_transform
)
8761 init_gamma_errors(pm
);
8762 /*TODO: remove this. Necessary because the current libpng
8763 * implementation works in 8 bits:
8765 if (pm
->test_gamma_expand16
)
8766 pm
->calculations_use_input_precision
= 1;
8767 perform_gamma_transform_tests(pm
);
8768 if (!calculations_use_input_precision
)
8769 pm
->calculations_use_input_precision
= 0;
8773 printf("Gamma correction error summary\n\n");
8774 printf("The printed value is the maximum error in the pixel values\n");
8775 printf("calculated by the libpng gamma correction code. The error\n");
8776 printf("is calculated as the difference between the output pixel\n");
8777 printf("value (always an integer) and the ideal value from the\n");
8778 printf("libpng specification (typically not an integer).\n\n");
8780 printf("Expect this value to be less than .5 for 8 bit formats,\n");
8781 printf("less than 1 for formats with fewer than 8 bits and a small\n");
8782 printf("number (typically less than 5) for the 16 bit formats.\n");
8783 printf("For performance reasons the value for 16 bit formats\n");
8784 printf("increases when the image file includes an sBIT chunk.\n\n");
8786 summarize_gamma_errors(pm
, 0/*who*/, 1);
8790 /* The sbit tests produce much larger errors: */
8791 if (pm
->test_gamma_sbit
)
8793 init_gamma_errors(pm
);
8794 perform_gamma_sbit_tests(pm
);
8797 summarize_gamma_errors(pm
, "sBIT", pm
->sbitlow
< 8U);
8800 #ifdef DO_16BIT /* Should be READ_16BIT_SUPPORTED */
8801 if (pm
->test_gamma_scale16
)
8803 /* The 16 to 8 bit strip operations: */
8804 init_gamma_errors(pm
);
8805 perform_gamma_scale16_tests(pm
);
8809 printf("Gamma correction with 16 to 8 bit reduction:\n");
8810 printf(" 16 bit gray: %.5f\n", pm
->error_gray_16
);
8811 printf(" 16 bit color: %.5f\n", pm
->error_color_16
);
8816 #ifdef PNG_READ_BACKGROUND_SUPPORTED
8817 if (pm
->test_gamma_background
)
8819 init_gamma_errors(pm
);
8821 /*TODO: remove this. Necessary because the current libpng
8822 * implementation works in 8 bits:
8824 if (pm
->test_gamma_expand16
)
8826 pm
->calculations_use_input_precision
= 1;
8827 pm
->maxout8
= .499; /* because the 16 bit background is smashed */
8829 perform_gamma_composition_tests(pm
, PNG_BACKGROUND_GAMMA_UNIQUE
,
8830 pm
->test_gamma_expand16
);
8831 if (!calculations_use_input_precision
)
8832 pm
->calculations_use_input_precision
= 0;
8833 pm
->maxout8
= maxout8
;
8836 summarize_gamma_errors(pm
, "background", 1);
8840 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED
8841 if (pm
->test_gamma_alpha_mode
)
8845 init_gamma_errors(pm
);
8847 /*TODO: remove this. Necessary because the current libpng
8848 * implementation works in 8 bits:
8850 if (pm
->test_gamma_expand16
)
8851 pm
->calculations_use_input_precision
= 1;
8852 for (do_background
= ALPHA_MODE_OFFSET
+ PNG_ALPHA_STANDARD
;
8853 do_background
<= ALPHA_MODE_OFFSET
+ PNG_ALPHA_BROKEN
&& !fail(pm
);
8855 perform_gamma_composition_tests(pm
, do_background
,
8856 pm
->test_gamma_expand16
);
8857 if (!calculations_use_input_precision
)
8858 pm
->calculations_use_input_precision
= 0;
8861 summarize_gamma_errors(pm
, "alpha mode", 1);
8865 #endif /* PNG_READ_GAMMA_SUPPORTED */
8867 /* INTERLACE MACRO VALIDATION */
8868 /* This is copied verbatim from the specification, it is simply the pass
8869 * number in which each pixel in each 8x8 tile appears. The array must
8870 * be indexed adam7[y][x] and notice that the pass numbers are based at
8871 * 1, not 0 - the base libpng uses.
8874 png_byte adam7
[8][8] =
8876 { 1,6,4,6,2,6,4,6 },
8877 { 7,7,7,7,7,7,7,7 },
8878 { 5,6,5,6,5,6,5,6 },
8879 { 7,7,7,7,7,7,7,7 },
8880 { 3,6,4,6,3,6,4,6 },
8881 { 7,7,7,7,7,7,7,7 },
8882 { 5,6,5,6,5,6,5,6 },
8886 /* This routine validates all the interlace support macros in png.h for
8887 * a variety of valid PNG widths and heights. It uses a number of similarly
8888 * named internal routines that feed off the above array.
8891 png_pass_start_row(int pass
)
8895 for (y
=0; y
<8; ++y
) for (x
=0; x
<8; ++x
) if (adam7
[y
][x
] == pass
)
8901 png_pass_start_col(int pass
)
8905 for (x
=0; x
<8; ++x
) for (y
=0; y
<8; ++y
) if (adam7
[y
][x
] == pass
)
8911 png_pass_row_shift(int pass
)
8913 int x
, y
, base
=(-1), inc
=8;
8915 for (y
=0; y
<8; ++y
) for (x
=0; x
<8; ++x
) if (adam7
[y
][x
] == pass
)
8921 else if (inc
== y
-base
)
8924 inc
= y
-base
, base
=y
;
8925 else if (inc
!= y
-base
)
8926 return 0xff; /* error - more than one 'inc' value! */
8929 if (base
== (-1)) return 0xfe; /* error - no row in pass! */
8931 /* The shift is always 1, 2 or 3 - no pass has all the rows! */
8940 /* error - unrecognized 'inc' */
8941 return (inc
<< 8) + 0xfd;
8945 png_pass_col_shift(int pass
)
8947 int x
, y
, base
=(-1), inc
=8;
8949 for (x
=0; x
<8; ++x
) for (y
=0; y
<8; ++y
) if (adam7
[y
][x
] == pass
)
8955 else if (inc
== x
-base
)
8958 inc
= x
-base
, base
=x
;
8959 else if (inc
!= x
-base
)
8960 return 0xff; /* error - more than one 'inc' value! */
8963 if (base
== (-1)) return 0xfe; /* error - no row in pass! */
8965 /* The shift is always 1, 2 or 3 - no pass has all the rows! */
8968 case 1: return 0; /* pass 7 has all the columns */
8975 /* error - unrecognized 'inc' */
8976 return (inc
<< 8) + 0xfd;
8980 png_row_from_pass_row(png_uint_32 yIn
, int pass
)
8982 /* By examination of the array: */
8985 case 0: return yIn
* 8;
8986 case 1: return yIn
* 8;
8987 case 2: return yIn
* 8 + 4;
8988 case 3: return yIn
* 4;
8989 case 4: return yIn
* 4 + 2;
8990 case 5: return yIn
* 2;
8991 case 6: return yIn
* 2 + 1;
8995 return 0xff; /* bad pass number */
8999 png_col_from_pass_col(png_uint_32 xIn
, int pass
)
9001 /* By examination of the array: */
9004 case 0: return xIn
* 8;
9005 case 1: return xIn
* 8 + 4;
9006 case 2: return xIn
* 4;
9007 case 3: return xIn
* 4 + 2;
9008 case 4: return xIn
* 2;
9009 case 5: return xIn
* 2 + 1;
9014 return 0xff; /* bad pass number */
9018 png_row_in_interlace_pass(png_uint_32 y
, int pass
)
9020 /* Is row 'y' in pass 'pass'? */
9024 for (x
=0; x
<8; ++x
) if (adam7
[y
][x
] == pass
)
9031 png_col_in_interlace_pass(png_uint_32 x
, int pass
)
9033 /* Is column 'x' in pass 'pass'? */
9037 for (y
=0; y
<8; ++y
) if (adam7
[y
][x
] == pass
)
9044 png_pass_rows(png_uint_32 height
, int pass
)
9046 png_uint_32 tiles
= height
>>3;
9047 png_uint_32 rows
= 0;
9052 for (y
=0; y
<8; ++y
) for (x
=0; x
<8; ++x
) if (adam7
[y
][x
] == pass
)
9055 if (y
< height
) ++rows
;
9056 break; /* i.e. break the 'x', column, loop. */
9063 png_pass_cols(png_uint_32 width
, int pass
)
9065 png_uint_32 tiles
= width
>>3;
9066 png_uint_32 cols
= 0;
9071 for (x
=0; x
<8; ++x
) for (y
=0; y
<8; ++y
) if (adam7
[y
][x
] == pass
)
9074 if (x
< width
) ++cols
;
9075 break; /* i.e. break the 'y', row, loop. */
9082 perform_interlace_macro_validation(void)
9084 /* The macros to validate, first those that depend only on pass:
9086 * PNG_PASS_START_ROW(pass)
9087 * PNG_PASS_START_COL(pass)
9088 * PNG_PASS_ROW_SHIFT(pass)
9089 * PNG_PASS_COL_SHIFT(pass)
9093 for (pass
=0; pass
<7; ++pass
)
9095 png_uint_32 m
, f
, v
;
9097 m
= PNG_PASS_START_ROW(pass
);
9098 f
= png_pass_start_row(pass
);
9101 fprintf(stderr
, "PNG_PASS_START_ROW(%d) = %u != %x\n", pass
, m
, f
);
9105 m
= PNG_PASS_START_COL(pass
);
9106 f
= png_pass_start_col(pass
);
9109 fprintf(stderr
, "PNG_PASS_START_COL(%d) = %u != %x\n", pass
, m
, f
);
9113 m
= PNG_PASS_ROW_SHIFT(pass
);
9114 f
= png_pass_row_shift(pass
);
9117 fprintf(stderr
, "PNG_PASS_ROW_SHIFT(%d) = %u != %x\n", pass
, m
, f
);
9121 m
= PNG_PASS_COL_SHIFT(pass
);
9122 f
= png_pass_col_shift(pass
);
9125 fprintf(stderr
, "PNG_PASS_COL_SHIFT(%d) = %u != %x\n", pass
, m
, f
);
9129 /* Macros that depend on the image or sub-image height too:
9131 * PNG_PASS_ROWS(height, pass)
9132 * PNG_PASS_COLS(width, pass)
9133 * PNG_ROW_FROM_PASS_ROW(yIn, pass)
9134 * PNG_COL_FROM_PASS_COL(xIn, pass)
9135 * PNG_ROW_IN_INTERLACE_PASS(y, pass)
9136 * PNG_COL_IN_INTERLACE_PASS(x, pass)
9140 /* First the base 0 stuff: */
9141 m
= PNG_ROW_FROM_PASS_ROW(v
, pass
);
9142 f
= png_row_from_pass_row(v
, pass
);
9145 fprintf(stderr
, "PNG_ROW_FROM_PASS_ROW(%u, %d) = %u != %x\n",
9150 m
= PNG_COL_FROM_PASS_COL(v
, pass
);
9151 f
= png_col_from_pass_col(v
, pass
);
9154 fprintf(stderr
, "PNG_COL_FROM_PASS_COL(%u, %d) = %u != %x\n",
9159 m
= PNG_ROW_IN_INTERLACE_PASS(v
, pass
);
9160 f
= png_row_in_interlace_pass(v
, pass
);
9163 fprintf(stderr
, "PNG_ROW_IN_INTERLACE_PASS(%u, %d) = %u != %x\n",
9168 m
= PNG_COL_IN_INTERLACE_PASS(v
, pass
);
9169 f
= png_col_in_interlace_pass(v
, pass
);
9172 fprintf(stderr
, "PNG_COL_IN_INTERLACE_PASS(%u, %d) = %u != %x\n",
9177 /* Then the base 1 stuff: */
9179 m
= PNG_PASS_ROWS(v
, pass
);
9180 f
= png_pass_rows(v
, pass
);
9183 fprintf(stderr
, "PNG_PASS_ROWS(%u, %d) = %u != %x\n",
9188 m
= PNG_PASS_COLS(v
, pass
);
9189 f
= png_pass_cols(v
, pass
);
9192 fprintf(stderr
, "PNG_PASS_COLS(%u, %d) = %u != %x\n",
9197 /* Move to the next v - the stepping algorithm starts skipping
9198 * values above 1024.
9202 if (v
== PNG_UINT_31_MAX
)
9206 if (v
>= PNG_UINT_31_MAX
)
9207 v
= PNG_UINT_31_MAX
-1;
9213 /* Test color encodings. These values are back-calculated from the published
9214 * chromaticities. The values are accurate to about 14 decimal places; 15 are
9215 * given. These values are much more accurate than the ones given in the spec,
9216 * which typically don't exceed 4 decimal places. This allows testing of the
9217 * libpng code to its theoretical accuracy of 4 decimal places. (If pngvalid
9218 * used the published errors the 'slack' permitted would have to be +/-.5E-4 or
9221 * The png_modifier code assumes that encodings[0] is sRGB and treats it
9222 * specially: do not change the first entry in this list!
9224 static PNG_CONST color_encoding test_encodings
[] =
9226 /* sRGB: must be first in this list! */
9228 /*red: */ { 0.412390799265959, 0.212639005871510, 0.019330818715592 },
9229 /*green:*/ { 0.357584339383878, 0.715168678767756, 0.119194779794626 },
9230 /*blue: */ { 0.180480788401834, 0.072192315360734, 0.950532152249660} },
9231 /* Kodak ProPhoto (wide gamut) */
9232 /*gamma:*/ { 1/1.6 /*approximate: uses 1.8 power law compared to sRGB 2.4*/,
9233 /*red: */ { 0.797760489672303, 0.288071128229293, 0.000000000000000 },
9234 /*green:*/ { 0.135185837175740, 0.711843217810102, 0.000000000000000 },
9235 /*blue: */ { 0.031349349581525, 0.000085653960605, 0.825104602510460} },
9236 /* Adobe RGB (1998) */
9237 /*gamma:*/ { 1/(2+51./256),
9238 /*red: */ { 0.576669042910131, 0.297344975250536, 0.027031361386412 },
9239 /*green:*/ { 0.185558237906546, 0.627363566255466, 0.070688852535827 },
9240 /*blue: */ { 0.188228646234995, 0.075291458493998, 0.991337536837639} },
9241 /* Adobe Wide Gamut RGB */
9242 /*gamma:*/ { 1/(2+51./256),
9243 /*red: */ { 0.716500716779386, 0.258728243040113, 0.000000000000000 },
9244 /*green:*/ { 0.101020574397477, 0.724682314948566, 0.051211818965388 },
9245 /*blue: */ { 0.146774385252705, 0.016589442011321, 0.773892783545073} },
9249 int main(int argc
, PNG_CONST
char **argv
)
9251 volatile int summary
= 1; /* Print the error summary at the end */
9252 volatile int memstats
= 0; /* Print memory statistics at the end */
9254 /* Create the given output file on success: */
9255 PNG_CONST
char *volatile touch
= NULL
;
9257 /* This is an array of standard gamma values (believe it or not I've seen
9258 * every one of these mentioned somewhere.)
9260 * In the following list the most useful values are first!
9263 gammas
[]={2.2, 1.0, 2.2/1.45, 1.8, 1.5, 2.4, 2.5, 2.62, 2.9};
9265 /* This records the command and arguments: */
9270 context(&pm
.this, fault
);
9274 /* Preallocate the image buffer, because we know how big it needs to be,
9275 * note that, for testing purposes, it is deliberately mis-aligned by tag
9276 * bytes either side. All rows have an additional five bytes of padding for
9277 * overwrite checking.
9279 store_ensure_image(&pm
.this, NULL
, 2, TRANSFORM_ROWMAX
, TRANSFORM_HEIGHTMAX
);
9281 /* Don't give argv[0], it's normally some horrible libtool string: */
9282 cp
= safecat(command
, sizeof command
, cp
, "pngvalid");
9284 /* Default to error on warning: */
9285 pm
.this.treat_warnings_as_errors
= 1;
9287 /* Store the test gammas */
9289 pm
.ngammas
= (sizeof gammas
) / (sizeof gammas
[0]);
9290 pm
.ngamma_tests
= 0; /* default to off */
9292 /* And the test encodings */
9293 pm
.encodings
= test_encodings
;
9294 pm
.nencodings
= (sizeof test_encodings
) / (sizeof test_encodings
[0]);
9296 pm
.sbitlow
= 8U; /* because libpng doesn't do sBIT below 8! */
9297 /* The following allows results to pass if they correspond to anything in the
9298 * transformed range [input-.5,input+.5]; this is is required because of the
9299 * way libpng treates the 16_TO_8 flag when building the gamma tables.
9303 pm
.use_input_precision_16to8
= 1U;
9305 /* Some default values (set the behavior for 'make check' here).
9306 * These values simply control the maximum error permitted in the gamma
9307 * transformations. The practial limits for human perception are described
9308 * below (the setting for maxpc16), however for 8 bit encodings it isn't
9309 * possible to meet the accepted capabilities of human vision - i.e. 8 bit
9310 * images can never be good enough, regardless of encoding.
9312 pm
.maxout8
= .1; /* Arithmetic error in *encoded* value */
9313 pm
.maxabs8
= .00005; /* 1/20000 */
9314 pm
.maxcalc8
= .004; /* +/-1 in 8 bits for compose errors */
9315 pm
.maxpc8
= .499; /* I.e., .499% fractional error */
9316 pm
.maxout16
= .499; /* Error in *encoded* value */
9317 pm
.maxabs16
= .00005;/* 1/20000 */
9318 pm
.maxcalc16
=.000015;/* +/-1 in 16 bits for compose errors */
9320 /* NOTE: this is a reasonable perceptual limit. We assume that humans can
9321 * perceive light level differences of 1% over a 100:1 range, so we need to
9322 * maintain 1 in 10000 accuracy (in linear light space), which is what the
9323 * following guarantees. It also allows significantly higher errors at
9324 * higher 16 bit values, which is important for performance. The actual
9325 * maximum 16 bit error is about +/-1.9 in the fixed point implementation but
9326 * this is only allowed for values >38149 by the following:
9328 pm
.maxpc16
= .005; /* I.e., 1/200% - 1/20000 */
9330 /* Now parse the command line options. */
9333 int catmore
= 0; /* Set if the argument has an argument. */
9335 /* Record each argument for posterity: */
9336 cp
= safecat(command
, sizeof command
, cp
, " ");
9337 cp
= safecat(command
, sizeof command
, cp
, *++argv
);
9339 if (strcmp(*argv
, "-v") == 0)
9340 pm
.this.verbose
= 1;
9342 else if (strcmp(*argv
, "-l") == 0)
9345 else if (strcmp(*argv
, "-q") == 0)
9346 summary
= pm
.this.verbose
= pm
.log
= 0;
9348 else if (strcmp(*argv
, "-w") == 0)
9349 pm
.this.treat_warnings_as_errors
= 0;
9351 else if (strcmp(*argv
, "--speed") == 0)
9352 pm
.this.speed
= 1, pm
.ngamma_tests
= pm
.ngammas
, pm
.test_standard
= 0,
9355 else if (strcmp(*argv
, "--memory") == 0)
9358 else if (strcmp(*argv
, "--size") == 0)
9361 else if (strcmp(*argv
, "--nosize") == 0)
9364 else if (strcmp(*argv
, "--standard") == 0)
9365 pm
.test_standard
= 1;
9367 else if (strcmp(*argv
, "--nostandard") == 0)
9368 pm
.test_standard
= 0;
9370 else if (strcmp(*argv
, "--transform") == 0)
9371 pm
.test_transform
= 1;
9373 else if (strcmp(*argv
, "--notransform") == 0)
9374 pm
.test_transform
= 0;
9376 #ifdef PNG_READ_TRANSFORMS_SUPPORTED
9377 else if (strncmp(*argv
, "--transform-disable=",
9378 sizeof "--transform-disable") == 0)
9380 pm
.test_transform
= 1;
9381 transform_disable(*argv
+ sizeof "--transform-disable");
9384 else if (strncmp(*argv
, "--transform-enable=",
9385 sizeof "--transform-enable") == 0)
9387 pm
.test_transform
= 1;
9388 transform_enable(*argv
+ sizeof "--transform-enable");
9390 #endif /* PNG_READ_TRANSFORMS_SUPPORTED */
9392 else if (strcmp(*argv
, "--gamma") == 0)
9394 /* Just do two gamma tests here (2.2 and linear) for speed: */
9395 pm
.ngamma_tests
= 2U;
9396 pm
.test_gamma_threshold
= 1;
9397 pm
.test_gamma_transform
= 1;
9398 pm
.test_gamma_sbit
= 1;
9399 pm
.test_gamma_scale16
= 1;
9400 pm
.test_gamma_background
= 1;
9401 pm
.test_gamma_alpha_mode
= 1;
9404 else if (strcmp(*argv
, "--nogamma") == 0)
9405 pm
.ngamma_tests
= 0;
9407 else if (strcmp(*argv
, "--gamma-threshold") == 0)
9408 pm
.ngamma_tests
= 2U, pm
.test_gamma_threshold
= 1;
9410 else if (strcmp(*argv
, "--nogamma-threshold") == 0)
9411 pm
.test_gamma_threshold
= 0;
9413 else if (strcmp(*argv
, "--gamma-transform") == 0)
9414 pm
.ngamma_tests
= 2U, pm
.test_gamma_transform
= 1;
9416 else if (strcmp(*argv
, "--nogamma-transform") == 0)
9417 pm
.test_gamma_transform
= 0;
9419 else if (strcmp(*argv
, "--gamma-sbit") == 0)
9420 pm
.ngamma_tests
= 2U, pm
.test_gamma_sbit
= 1;
9422 else if (strcmp(*argv
, "--nogamma-sbit") == 0)
9423 pm
.test_gamma_sbit
= 0;
9425 else if (strcmp(*argv
, "--gamma-16-to-8") == 0)
9426 pm
.ngamma_tests
= 2U, pm
.test_gamma_scale16
= 1;
9428 else if (strcmp(*argv
, "--nogamma-16-to-8") == 0)
9429 pm
.test_gamma_scale16
= 0;
9431 else if (strcmp(*argv
, "--gamma-background") == 0)
9432 pm
.ngamma_tests
= 2U, pm
.test_gamma_background
= 1;
9434 else if (strcmp(*argv
, "--nogamma-background") == 0)
9435 pm
.test_gamma_background
= 0;
9437 else if (strcmp(*argv
, "--gamma-alpha-mode") == 0)
9438 pm
.ngamma_tests
= 2U, pm
.test_gamma_alpha_mode
= 1;
9440 else if (strcmp(*argv
, "--nogamma-alpha-mode") == 0)
9441 pm
.test_gamma_alpha_mode
= 0;
9443 else if (strcmp(*argv
, "--expand16") == 0)
9444 pm
.test_gamma_expand16
= 1;
9446 else if (strcmp(*argv
, "--noexpand16") == 0)
9447 pm
.test_gamma_expand16
= 0;
9449 else if (strcmp(*argv
, "--more-gammas") == 0)
9450 pm
.ngamma_tests
= 3U;
9452 else if (strcmp(*argv
, "--all-gammas") == 0)
9453 pm
.ngamma_tests
= pm
.ngammas
;
9455 else if (strcmp(*argv
, "--progressive-read") == 0)
9456 pm
.this.progressive
= 1;
9458 else if (strcmp(*argv
, "--use-update-info") == 0)
9459 ++pm
.use_update_info
; /* Can call multiple times */
9461 else if (strcmp(*argv
, "--interlace") == 0)
9462 pm
.interlace_type
= PNG_INTERLACE_ADAM7
;
9464 else if (strcmp(*argv
, "--use-input-precision") == 0)
9465 pm
.use_input_precision
= 1;
9467 else if (strcmp(*argv
, "--calculations-use-input-precision") == 0)
9468 pm
.calculations_use_input_precision
= 1;
9470 else if (strcmp(*argv
, "--assume-16-bit-calculations") == 0)
9471 pm
.assume_16_bit_calculations
= 1;
9473 else if (strcmp(*argv
, "--calculations-follow-bit-depth") == 0)
9474 pm
.calculations_use_input_precision
=
9475 pm
.assume_16_bit_calculations
= 0;
9477 else if (strcmp(*argv
, "--exhaustive") == 0)
9478 pm
.test_exhaustive
= 1;
9480 else if (argc
> 1 && strcmp(*argv
, "--sbitlow") == 0)
9481 --argc
, pm
.sbitlow
= (png_byte
)atoi(*++argv
), catmore
= 1;
9483 else if (argc
> 1 && strcmp(*argv
, "--touch") == 0)
9484 --argc
, touch
= *++argv
, catmore
= 1;
9486 else if (argc
> 1 && strncmp(*argv
, "--max", 5) == 0)
9490 if (strcmp(5+*argv
, "abs8") == 0)
9491 pm
.maxabs8
= atof(*++argv
);
9493 else if (strcmp(5+*argv
, "abs16") == 0)
9494 pm
.maxabs16
= atof(*++argv
);
9496 else if (strcmp(5+*argv
, "calc8") == 0)
9497 pm
.maxcalc8
= atof(*++argv
);
9499 else if (strcmp(5+*argv
, "calc16") == 0)
9500 pm
.maxcalc16
= atof(*++argv
);
9502 else if (strcmp(5+*argv
, "out8") == 0)
9503 pm
.maxout8
= atof(*++argv
);
9505 else if (strcmp(5+*argv
, "out16") == 0)
9506 pm
.maxout16
= atof(*++argv
);
9508 else if (strcmp(5+*argv
, "pc8") == 0)
9509 pm
.maxpc8
= atof(*++argv
);
9511 else if (strcmp(5+*argv
, "pc16") == 0)
9512 pm
.maxpc16
= atof(*++argv
);
9516 fprintf(stderr
, "pngvalid: %s: unknown 'max' option\n", *argv
);
9523 else if (strcmp(*argv
, "--log8") == 0)
9524 --argc
, pm
.log8
= atof(*++argv
), catmore
= 1;
9526 else if (strcmp(*argv
, "--log16") == 0)
9527 --argc
, pm
.log16
= atof(*++argv
), catmore
= 1;
9531 fprintf(stderr
, "pngvalid: %s: unknown argument\n", *argv
);
9535 if (catmore
) /* consumed an extra *argv */
9537 cp
= safecat(command
, sizeof command
, cp
, " ");
9538 cp
= safecat(command
, sizeof command
, cp
, *argv
);
9542 /* If pngvalid is run with no arguments default to a reasonable set of the
9545 if (pm
.test_standard
== 0 && pm
.test_size
== 0 && pm
.test_transform
== 0 &&
9546 pm
.ngamma_tests
== 0)
9548 /* Make this do all the tests done in the test shell scripts with the same
9549 * parameters, where possible. The limitation is that all the progressive
9550 * read and interlace stuff has to be done in separate runs, so only the
9551 * basic 'standard' and 'size' tests are done.
9553 pm
.test_standard
= 1;
9555 pm
.test_transform
= 1;
9556 pm
.ngamma_tests
= 2U;
9559 if (pm
.ngamma_tests
> 0 &&
9560 pm
.test_gamma_threshold
== 0 && pm
.test_gamma_transform
== 0 &&
9561 pm
.test_gamma_sbit
== 0 && pm
.test_gamma_scale16
== 0 &&
9562 pm
.test_gamma_background
== 0 && pm
.test_gamma_alpha_mode
== 0)
9564 pm
.test_gamma_threshold
= 1;
9565 pm
.test_gamma_transform
= 1;
9566 pm
.test_gamma_sbit
= 1;
9567 pm
.test_gamma_scale16
= 1;
9568 pm
.test_gamma_background
= 1;
9569 pm
.test_gamma_alpha_mode
= 1;
9572 else if (pm
.ngamma_tests
== 0)
9574 /* Nothing to test so turn everything off: */
9575 pm
.test_gamma_threshold
= 0;
9576 pm
.test_gamma_transform
= 0;
9577 pm
.test_gamma_sbit
= 0;
9578 pm
.test_gamma_scale16
= 0;
9579 pm
.test_gamma_background
= 0;
9580 pm
.test_gamma_alpha_mode
= 0;
9585 /* Make useful base images */
9586 make_transform_images(&pm
.this);
9588 /* Perform the standard and gamma tests. */
9589 if (pm
.test_standard
)
9591 perform_interlace_macro_validation();
9592 perform_formatting_test(&pm
.this);
9593 perform_standard_test(&pm
);
9594 perform_error_test(&pm
);
9597 /* Various oddly sized images: */
9600 make_size_images(&pm
.this);
9601 perform_size_test(&pm
);
9604 #ifdef PNG_READ_TRANSFORMS_SUPPORTED
9605 /* Combinatorial transforms: */
9606 if (pm
.test_transform
)
9607 perform_transform_test(&pm
);
9608 #endif /* PNG_READ_TRANSFORMS_SUPPORTED */
9610 #ifdef PNG_READ_GAMMA_SUPPORTED
9611 if (pm
.ngamma_tests
> 0)
9612 perform_gamma_test(&pm
, summary
);
9618 fprintf(stderr
, "pngvalid: test aborted (probably failed in cleanup)\n");
9619 if (!pm
.this.verbose
)
9621 if (pm
.this.error
[0] != 0)
9622 fprintf(stderr
, "pngvalid: first error: %s\n", pm
.this.error
);
9624 fprintf(stderr
, "pngvalid: run with -v to see what happened\n");
9631 printf("%s: %s (%s point arithmetic)\n",
9632 (pm
.this.nerrors
|| (pm
.this.treat_warnings_as_errors
&&
9633 pm
.this.nwarnings
)) ? "FAIL" : "PASS",
9635 #if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || PNG_LIBPNG_VER < 10500
9645 printf("Allocated memory statistics (in bytes):\n"
9646 "\tread %lu maximum single, %lu peak, %lu total\n"
9647 "\twrite %lu maximum single, %lu peak, %lu total\n",
9648 (unsigned long)pm
.this.read_memory_pool
.max_max
,
9649 (unsigned long)pm
.this.read_memory_pool
.max_limit
,
9650 (unsigned long)pm
.this.read_memory_pool
.max_total
,
9651 (unsigned long)pm
.this.write_memory_pool
.max_max
,
9652 (unsigned long)pm
.this.write_memory_pool
.max_limit
,
9653 (unsigned long)pm
.this.write_memory_pool
.max_total
);
9656 /* Do this here to provoke memory corruption errors in memory not directly
9657 * allocated by libpng - not a complete test, but better than nothing.
9659 store_delete(&pm
.this);
9661 /* Error exit if there are any errors, and maybe if there are any
9664 if (pm
.this.nerrors
|| (pm
.this.treat_warnings_as_errors
&&
9667 if (!pm
.this.verbose
)
9668 fprintf(stderr
, "pngvalid: %s\n", pm
.this.error
);
9670 fprintf(stderr
, "pngvalid: %d errors, %d warnings\n", pm
.this.nerrors
,
9679 FILE *fsuccess
= fopen(touch
, "wt");
9681 if (fsuccess
!= NULL
)
9684 fprintf(fsuccess
, "PNG validation succeeded\n");
9686 error
= ferror(fsuccess
);
9688 if (fclose(fsuccess
) || error
)
9690 fprintf(stderr
, "%s: write failed\n", touch
);