aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/libtests/pngvalid.c
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/libtests/pngvalid.c')
-rw-r--r--libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/libtests/pngvalid.c19674
1 files changed, 9837 insertions, 9837 deletions
diff --git a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/libtests/pngvalid.c b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/libtests/pngvalid.c
index c7068fa..3dd6f21 100644
--- a/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/libtests/pngvalid.c
+++ b/libraries/irrlicht-1.8/source/Irrlicht/libpng/contrib/libtests/pngvalid.c
@@ -1,9837 +1,9837 @@
1 1
2/* pngvalid.c - validate libpng by constructing then reading png files. 2/* pngvalid.c - validate libpng by constructing then reading png files.
3 * 3 *
4 * Last changed in libpng 1.5.8 [%RDATE%] 4 * Last changed in libpng 1.5.8 [%RDATE%]
5 * Copyright (c) 2012 Glenn Randers-Pehrson 5 * Copyright (c) 2012 Glenn Randers-Pehrson
6 * Written by John Cunningham Bowler 6 * Written by John Cunningham Bowler
7 * 7 *
8 * This code is released under the libpng license. 8 * This code is released under the libpng license.
9 * For conditions of distribution and use, see the disclaimer 9 * For conditions of distribution and use, see the disclaimer
10 * and license in png.h 10 * and license in png.h
11 * 11 *
12 * NOTES: 12 * NOTES:
13 * This is a C program that is intended to be linked against libpng. It 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 14 * generates bitmaps internally, stores them as PNG files (using the
15 * sequential write code) then reads them back (using the sequential 15 * sequential write code) then reads them back (using the sequential
16 * read code) and validates that the result has the correct data. 16 * read code) and validates that the result has the correct data.
17 * 17 *
18 * The program can be modified and extended to test the correctness of 18 * The program can be modified and extended to test the correctness of
19 * transformations performed by libpng. 19 * transformations performed by libpng.
20 */ 20 */
21 21
22#define _POSIX_SOURCE 1 22#define _POSIX_SOURCE 1
23#define _ISOC99_SOURCE 1 /* For floating point */ 23#define _ISOC99_SOURCE 1 /* For floating point */
24#define _GNU_SOURCE 1 /* For the floating point exception extension */ 24#define _GNU_SOURCE 1 /* For the floating point exception extension */
25 25
26#include <signal.h> 26#include <signal.h>
27 27
28#ifdef HAVE_FEENABLEEXCEPT 28#ifdef HAVE_FEENABLEEXCEPT
29# include <fenv.h> 29# include <fenv.h>
30#endif 30#endif
31 31
32/* Define the following to use this test against your installed libpng, rather 32/* Define the following to use this test against your installed libpng, rather
33 * than the one being built here: 33 * than the one being built here:
34 */ 34 */
35#ifdef PNG_FREESTANDING_TESTS 35#ifdef PNG_FREESTANDING_TESTS
36# include <png.h> 36# include <png.h>
37#else 37#else
38# include "../../png.h" 38# include "../../png.h"
39#endif 39#endif
40 40
41#if PNG_LIBPNG_VER < 10500 41#if PNG_LIBPNG_VER < 10500
42/* This deliberately lacks the PNG_CONST. */ 42/* This deliberately lacks the PNG_CONST. */
43typedef png_byte *png_const_bytep; 43typedef png_byte *png_const_bytep;
44 44
45/* This is copied from 1.5.1 png.h: */ 45/* This is copied from 1.5.1 png.h: */
46#define PNG_INTERLACE_ADAM7_PASSES 7 46#define PNG_INTERLACE_ADAM7_PASSES 7
47#define PNG_PASS_START_ROW(pass) (((1U&~(pass))<<(3-((pass)>>1)))&7) 47#define PNG_PASS_START_ROW(pass) (((1U&~(pass))<<(3-((pass)>>1)))&7)
48#define PNG_PASS_START_COL(pass) (((1U& (pass))<<(3-(((pass)+1)>>1)))&7) 48#define PNG_PASS_START_COL(pass) (((1U& (pass))<<(3-(((pass)+1)>>1)))&7)
49#define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3) 49#define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3)
50#define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3) 50#define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3)
51#define PNG_PASS_ROWS(height, pass) (((height)+(((1<<PNG_PASS_ROW_SHIFT(pass))\ 51#define PNG_PASS_ROWS(height, pass) (((height)+(((1<<PNG_PASS_ROW_SHIFT(pass))\
52 -1)-PNG_PASS_START_ROW(pass)))>>PNG_PASS_ROW_SHIFT(pass)) 52 -1)-PNG_PASS_START_ROW(pass)))>>PNG_PASS_ROW_SHIFT(pass))
53#define PNG_PASS_COLS(width, pass) (((width)+(((1<<PNG_PASS_COL_SHIFT(pass))\ 53#define PNG_PASS_COLS(width, pass) (((width)+(((1<<PNG_PASS_COL_SHIFT(pass))\
54 -1)-PNG_PASS_START_COL(pass)))>>PNG_PASS_COL_SHIFT(pass)) 54 -1)-PNG_PASS_START_COL(pass)))>>PNG_PASS_COL_SHIFT(pass))
55#define PNG_ROW_FROM_PASS_ROW(yIn, pass) \ 55#define PNG_ROW_FROM_PASS_ROW(yIn, pass) \
56 (((yIn)<<PNG_PASS_ROW_SHIFT(pass))+PNG_PASS_START_ROW(pass)) 56 (((yIn)<<PNG_PASS_ROW_SHIFT(pass))+PNG_PASS_START_ROW(pass))
57#define PNG_COL_FROM_PASS_COL(xIn, pass) \ 57#define PNG_COL_FROM_PASS_COL(xIn, pass) \
58 (((xIn)<<PNG_PASS_COL_SHIFT(pass))+PNG_PASS_START_COL(pass)) 58 (((xIn)<<PNG_PASS_COL_SHIFT(pass))+PNG_PASS_START_COL(pass))
59#define PNG_PASS_MASK(pass,off) ( \ 59#define PNG_PASS_MASK(pass,off) ( \
60 ((0x110145AFU>>(((7-(off))-(pass))<<2)) & 0xFU) | \ 60 ((0x110145AFU>>(((7-(off))-(pass))<<2)) & 0xFU) | \
61 ((0x01145AF0U>>(((7-(off))-(pass))<<2)) & 0xF0U)) 61 ((0x01145AF0U>>(((7-(off))-(pass))<<2)) & 0xF0U))
62#define PNG_ROW_IN_INTERLACE_PASS(y, pass) \ 62#define PNG_ROW_IN_INTERLACE_PASS(y, pass) \
63 ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1) 63 ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1)
64#define PNG_COL_IN_INTERLACE_PASS(x, pass) \ 64#define PNG_COL_IN_INTERLACE_PASS(x, pass) \
65 ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1) 65 ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1)
66 66
67/* These are needed too for the default build: */ 67/* These are needed too for the default build: */
68#define PNG_WRITE_16BIT_SUPPORTED 68#define PNG_WRITE_16BIT_SUPPORTED
69#define PNG_READ_16BIT_SUPPORTED 69#define PNG_READ_16BIT_SUPPORTED
70 70
71/* This comes from pnglibconf.h afer 1.5: */ 71/* This comes from pnglibconf.h afer 1.5: */
72#define PNG_FP_1 100000 72#define PNG_FP_1 100000
73#define PNG_GAMMA_THRESHOLD_FIXED\ 73#define PNG_GAMMA_THRESHOLD_FIXED\
74 ((png_fixed_point)(PNG_GAMMA_THRESHOLD * PNG_FP_1)) 74 ((png_fixed_point)(PNG_GAMMA_THRESHOLD * PNG_FP_1))
75#endif 75#endif
76 76
77#include "zlib.h" /* For crc32 */ 77#include "zlib.h" /* For crc32 */
78 78
79#include <float.h> /* For floating point constants */ 79#include <float.h> /* For floating point constants */
80#include <stdlib.h> /* For malloc */ 80#include <stdlib.h> /* For malloc */
81#include <string.h> /* For memcpy, memset */ 81#include <string.h> /* For memcpy, memset */
82#include <math.h> /* For floor */ 82#include <math.h> /* For floor */
83 83
84/* Unused formal parameter errors are removed using the following macro which is 84/* Unused formal parameter errors are removed using the following macro which is
85 * expected to have no bad effects on performance. 85 * expected to have no bad effects on performance.
86 */ 86 */
87#ifndef UNUSED 87#ifndef UNUSED
88# if defined(__GNUC__) || defined(_MSC_VER) 88# if defined(__GNUC__) || defined(_MSC_VER)
89# define UNUSED(param) (void)param; 89# define UNUSED(param) (void)param;
90# else 90# else
91# define UNUSED(param) 91# define UNUSED(param)
92# endif 92# endif
93#endif 93#endif
94 94
95/***************************** EXCEPTION HANDLING *****************************/ 95/***************************** EXCEPTION HANDLING *****************************/
96#include "../visupng/cexcept.h" 96#include "../visupng/cexcept.h"
97 97
98#ifdef __cplusplus 98#ifdef __cplusplus
99# define this not_the_cpp_this 99# define this not_the_cpp_this
100# define new not_the_cpp_new 100# define new not_the_cpp_new
101# define voidcast(type, value) static_cast<type>(value) 101# define voidcast(type, value) static_cast<type>(value)
102#else 102#else
103# define voidcast(type, value) (value) 103# define voidcast(type, value) (value)
104#endif /* __cplusplus */ 104#endif /* __cplusplus */
105 105
106struct png_store; 106struct png_store;
107define_exception_type(struct png_store*); 107define_exception_type(struct png_store*);
108 108
109/* The following are macros to reduce typing everywhere where the well known 109/* The following are macros to reduce typing everywhere where the well known
110 * name 'the_exception_context' must be defined. 110 * name 'the_exception_context' must be defined.
111 */ 111 */
112#define anon_context(ps) struct exception_context *the_exception_context = \ 112#define anon_context(ps) struct exception_context *the_exception_context = \
113 &(ps)->exception_context 113 &(ps)->exception_context
114#define context(ps,fault) anon_context(ps); png_store *fault 114#define context(ps,fault) anon_context(ps); png_store *fault
115 115
116/******************************* UTILITIES ************************************/ 116/******************************* UTILITIES ************************************/
117/* Error handling is particularly problematic in production code - error 117/* Error handling is particularly problematic in production code - error
118 * handlers often themselves have bugs which lead to programs that detect 118 * handlers often themselves have bugs which lead to programs that detect
119 * minor errors crashing. The following functions deal with one very 119 * minor errors crashing. The following functions deal with one very
120 * common class of errors in error handlers - attempting to format error or 120 * common class of errors in error handlers - attempting to format error or
121 * warning messages into buffers that are too small. 121 * warning messages into buffers that are too small.
122 */ 122 */
123static size_t safecat(char *buffer, size_t bufsize, size_t pos, 123static size_t safecat(char *buffer, size_t bufsize, size_t pos,
124 PNG_CONST char *cat) 124 PNG_CONST char *cat)
125{ 125{
126 while (pos < bufsize && cat != NULL && *cat != 0) 126 while (pos < bufsize && cat != NULL && *cat != 0)
127 buffer[pos++] = *cat++; 127 buffer[pos++] = *cat++;
128 128
129 if (pos >= bufsize) 129 if (pos >= bufsize)
130 pos = bufsize-1; 130 pos = bufsize-1;
131 131
132 buffer[pos] = 0; 132 buffer[pos] = 0;
133 return pos; 133 return pos;
134} 134}
135 135
136static size_t safecatn(char *buffer, size_t bufsize, size_t pos, int n) 136static size_t safecatn(char *buffer, size_t bufsize, size_t pos, int n)
137{ 137{
138 char number[64]; 138 char number[64];
139 sprintf(number, "%d", n); 139 sprintf(number, "%d", n);
140 return safecat(buffer, bufsize, pos, number); 140 return safecat(buffer, bufsize, pos, number);
141} 141}
142 142
143#ifdef PNG_READ_TRANSFORMS_SUPPORTED 143#ifdef PNG_READ_TRANSFORMS_SUPPORTED
144static size_t safecatd(char *buffer, size_t bufsize, size_t pos, double d, 144static size_t safecatd(char *buffer, size_t bufsize, size_t pos, double d,
145 int precision) 145 int precision)
146{ 146{
147 char number[64]; 147 char number[64];
148 sprintf(number, "%.*f", precision, d); 148 sprintf(number, "%.*f", precision, d);
149 return safecat(buffer, bufsize, pos, number); 149 return safecat(buffer, bufsize, pos, number);
150} 150}
151#endif 151#endif
152 152
153static PNG_CONST char invalid[] = "invalid"; 153static PNG_CONST char invalid[] = "invalid";
154static PNG_CONST char sep[] = ": "; 154static PNG_CONST char sep[] = ": ";
155 155
156static PNG_CONST char *colour_types[8] = 156static PNG_CONST char *colour_types[8] =
157{ 157{
158 "grayscale", invalid, "truecolour", "indexed-colour", 158 "grayscale", invalid, "truecolour", "indexed-colour",
159 "grayscale with alpha", invalid, "truecolour with alpha", invalid 159 "grayscale with alpha", invalid, "truecolour with alpha", invalid
160}; 160};
161 161
162/* Convert a double precision value to fixed point. */ 162/* Convert a double precision value to fixed point. */
163static png_fixed_point 163static png_fixed_point
164fix(double d) 164fix(double d)
165{ 165{
166 d = floor(d * PNG_FP_1 + .5); 166 d = floor(d * PNG_FP_1 + .5);
167 return (png_fixed_point)d; 167 return (png_fixed_point)d;
168} 168}
169 169
170/* Generate random bytes. This uses a boring repeatable algorithm and it 170/* Generate random bytes. This uses a boring repeatable algorithm and it
171 * is implemented here so that it gives the same set of numbers on every 171 * is implemented here so that it gives the same set of numbers on every
172 * architecture. It's a linear congruential generator (Knuth or Sedgewick 172 * architecture. It's a linear congruential generator (Knuth or Sedgewick
173 * "Algorithms") but it comes from the 'feedback taps' table in Horowitz and 173 * "Algorithms") but it comes from the 'feedback taps' table in Horowitz and
174 * Hill, "The Art of Electronics". 174 * Hill, "The Art of Electronics".
175 */ 175 */
176static void 176static void
177make_random_bytes(png_uint_32* seed, void* pv, size_t size) 177make_random_bytes(png_uint_32* seed, void* pv, size_t size)
178{ 178{
179 png_uint_32 u0 = seed[0], u1 = seed[1]; 179 png_uint_32 u0 = seed[0], u1 = seed[1];
180 png_bytep bytes = voidcast(png_bytep, pv); 180 png_bytep bytes = voidcast(png_bytep, pv);
181 181
182 /* There are thirty three bits, the next bit in the sequence is bit-33 XOR 182 /* There are thirty three bits, the next bit in the sequence is bit-33 XOR
183 * bit-20. The top 1 bit is in u1, the bottom 32 are in u0. 183 * bit-20. The top 1 bit is in u1, the bottom 32 are in u0.
184 */ 184 */
185 size_t i; 185 size_t i;
186 for (i=0; i<size; ++i) 186 for (i=0; i<size; ++i)
187 { 187 {
188 /* First generate 8 new bits then shift them in at the end. */ 188 /* First generate 8 new bits then shift them in at the end. */
189 png_uint_32 u = ((u0 >> (20-8)) ^ ((u1 << 7) | (u0 >> (32-7)))) & 0xff; 189 png_uint_32 u = ((u0 >> (20-8)) ^ ((u1 << 7) | (u0 >> (32-7)))) & 0xff;
190 u1 <<= 8; 190 u1 <<= 8;
191 u1 |= u0 >> 24; 191 u1 |= u0 >> 24;
192 u0 <<= 8; 192 u0 <<= 8;
193 u0 |= u; 193 u0 |= u;
194 *bytes++ = (png_byte)u; 194 *bytes++ = (png_byte)u;
195 } 195 }
196 196
197 seed[0] = u0; 197 seed[0] = u0;
198 seed[1] = u1; 198 seed[1] = u1;
199} 199}
200 200
201static void 201static void
202make_four_random_bytes(png_uint_32* seed, png_bytep bytes) 202make_four_random_bytes(png_uint_32* seed, png_bytep bytes)
203{ 203{
204 make_random_bytes(seed, bytes, 4); 204 make_random_bytes(seed, bytes, 4);
205} 205}
206 206
207static void 207static void
208randomize(void *pv, size_t size) 208randomize(void *pv, size_t size)
209{ 209{
210 static png_uint_32 random_seed[2] = {0x56789abc, 0xd}; 210 static png_uint_32 random_seed[2] = {0x56789abc, 0xd};
211 make_random_bytes(random_seed, pv, size); 211 make_random_bytes(random_seed, pv, size);
212} 212}
213 213
214#define RANDOMIZE(this) randomize(&(this), sizeof (this)) 214#define RANDOMIZE(this) randomize(&(this), sizeof (this))
215 215
216static unsigned int 216static unsigned int
217random_mod(unsigned int max) 217random_mod(unsigned int max)
218{ 218{
219 unsigned int x; 219 unsigned int x;
220 220
221 RANDOMIZE(x); 221 RANDOMIZE(x);
222 222
223 return x % max; /* 0 .. max-1 */ 223 return x % max; /* 0 .. max-1 */
224} 224}
225 225
226static int 226static int
227random_choice(void) 227random_choice(void)
228{ 228{
229 unsigned char x; 229 unsigned char x;
230 230
231 RANDOMIZE(x); 231 RANDOMIZE(x);
232 232
233 return x & 1; 233 return x & 1;
234} 234}
235 235
236/* A numeric ID based on PNG file characteristics. The 'do_interlace' field 236/* A numeric ID based on PNG file characteristics. The 'do_interlace' field
237 * simply records whether pngvalid did the interlace itself or whether it 237 * simply records whether pngvalid did the interlace itself or whether it
238 * was done by libpng. Width and height must be less than 256. 'palette' is an 238 * was done by libpng. Width and height must be less than 256. 'palette' is an
239 * index of the palette to use for formats with a palette (0 otherwise.) 239 * index of the palette to use for formats with a palette (0 otherwise.)
240 */ 240 */
241#define FILEID(col, depth, palette, interlace, width, height, do_interlace) \ 241#define FILEID(col, depth, palette, interlace, width, height, do_interlace) \
242 ((png_uint_32)((col) + ((depth)<<3) + ((palette)<<8) + ((interlace)<<13) + \ 242 ((png_uint_32)((col) + ((depth)<<3) + ((palette)<<8) + ((interlace)<<13) + \
243 (((do_interlace)!=0)<<15) + ((width)<<16) + ((height)<<24))) 243 (((do_interlace)!=0)<<15) + ((width)<<16) + ((height)<<24)))
244 244
245#define COL_FROM_ID(id) ((png_byte)((id)& 0x7U)) 245#define COL_FROM_ID(id) ((png_byte)((id)& 0x7U))
246#define DEPTH_FROM_ID(id) ((png_byte)(((id) >> 3) & 0x1fU)) 246#define DEPTH_FROM_ID(id) ((png_byte)(((id) >> 3) & 0x1fU))
247#define PALETTE_FROM_ID(id) ((int)(((id) >> 8) & 0x1f)) 247#define PALETTE_FROM_ID(id) ((int)(((id) >> 8) & 0x1f))
248#define INTERLACE_FROM_ID(id) ((int)(((id) >> 13) & 0x3)) 248#define INTERLACE_FROM_ID(id) ((int)(((id) >> 13) & 0x3))
249#define DO_INTERLACE_FROM_ID(id) ((int)(((id)>>15) & 1)) 249#define DO_INTERLACE_FROM_ID(id) ((int)(((id)>>15) & 1))
250#define WIDTH_FROM_ID(id) (((id)>>16) & 0xff) 250#define WIDTH_FROM_ID(id) (((id)>>16) & 0xff)
251#define HEIGHT_FROM_ID(id) (((id)>>24) & 0xff) 251#define HEIGHT_FROM_ID(id) (((id)>>24) & 0xff)
252 252
253/* Utility to construct a standard name for a standard image. */ 253/* Utility to construct a standard name for a standard image. */
254static size_t 254static size_t
255standard_name(char *buffer, size_t bufsize, size_t pos, png_byte colour_type, 255standard_name(char *buffer, size_t bufsize, size_t pos, png_byte colour_type,
256 int bit_depth, int npalette, int interlace_type, 256 int bit_depth, int npalette, int interlace_type,
257 png_uint_32 w, png_uint_32 h, int do_interlace) 257 png_uint_32 w, png_uint_32 h, int do_interlace)
258{ 258{
259 pos = safecat(buffer, bufsize, pos, colour_types[colour_type]); 259 pos = safecat(buffer, bufsize, pos, colour_types[colour_type]);
260 if (npalette > 0) 260 if (npalette > 0)
261 { 261 {
262 pos = safecat(buffer, bufsize, pos, "["); 262 pos = safecat(buffer, bufsize, pos, "[");
263 pos = safecatn(buffer, bufsize, pos, npalette); 263 pos = safecatn(buffer, bufsize, pos, npalette);
264 pos = safecat(buffer, bufsize, pos, "]"); 264 pos = safecat(buffer, bufsize, pos, "]");
265 } 265 }
266 pos = safecat(buffer, bufsize, pos, " "); 266 pos = safecat(buffer, bufsize, pos, " ");
267 pos = safecatn(buffer, bufsize, pos, bit_depth); 267 pos = safecatn(buffer, bufsize, pos, bit_depth);
268 pos = safecat(buffer, bufsize, pos, " bit"); 268 pos = safecat(buffer, bufsize, pos, " bit");
269 269
270 if (interlace_type != PNG_INTERLACE_NONE) 270 if (interlace_type != PNG_INTERLACE_NONE)
271 { 271 {
272 pos = safecat(buffer, bufsize, pos, " interlaced"); 272 pos = safecat(buffer, bufsize, pos, " interlaced");
273 if (do_interlace) 273 if (do_interlace)
274 pos = safecat(buffer, bufsize, pos, "(pngvalid)"); 274 pos = safecat(buffer, bufsize, pos, "(pngvalid)");
275 else 275 else
276 pos = safecat(buffer, bufsize, pos, "(libpng)"); 276 pos = safecat(buffer, bufsize, pos, "(libpng)");
277 } 277 }
278 278
279 if (w > 0 || h > 0) 279 if (w > 0 || h > 0)
280 { 280 {
281 pos = safecat(buffer, bufsize, pos, " "); 281 pos = safecat(buffer, bufsize, pos, " ");
282 pos = safecatn(buffer, bufsize, pos, w); 282 pos = safecatn(buffer, bufsize, pos, w);
283 pos = safecat(buffer, bufsize, pos, "x"); 283 pos = safecat(buffer, bufsize, pos, "x");
284 pos = safecatn(buffer, bufsize, pos, h); 284 pos = safecatn(buffer, bufsize, pos, h);
285 } 285 }
286 286
287 return pos; 287 return pos;
288} 288}
289 289
290static size_t 290static size_t
291standard_name_from_id(char *buffer, size_t bufsize, size_t pos, png_uint_32 id) 291standard_name_from_id(char *buffer, size_t bufsize, size_t pos, png_uint_32 id)
292{ 292{
293 return standard_name(buffer, bufsize, pos, COL_FROM_ID(id), 293 return standard_name(buffer, bufsize, pos, COL_FROM_ID(id),
294 DEPTH_FROM_ID(id), PALETTE_FROM_ID(id), INTERLACE_FROM_ID(id), 294 DEPTH_FROM_ID(id), PALETTE_FROM_ID(id), INTERLACE_FROM_ID(id),
295 WIDTH_FROM_ID(id), HEIGHT_FROM_ID(id), DO_INTERLACE_FROM_ID(id)); 295 WIDTH_FROM_ID(id), HEIGHT_FROM_ID(id), DO_INTERLACE_FROM_ID(id));
296} 296}
297 297
298/* Convenience API and defines to list valid formats. Note that 16 bit read and 298/* Convenience API and defines to list valid formats. Note that 16 bit read and
299 * write support is required to do 16 bit read tests (we must be able to make a 299 * write support is required to do 16 bit read tests (we must be able to make a
300 * 16 bit image to test!) 300 * 16 bit image to test!)
301 */ 301 */
302#ifdef PNG_WRITE_16BIT_SUPPORTED 302#ifdef PNG_WRITE_16BIT_SUPPORTED
303# define WRITE_BDHI 4 303# define WRITE_BDHI 4
304# ifdef PNG_READ_16BIT_SUPPORTED 304# ifdef PNG_READ_16BIT_SUPPORTED
305# define READ_BDHI 4 305# define READ_BDHI 4
306# define DO_16BIT 306# define DO_16BIT
307# endif 307# endif
308#else 308#else
309# define WRITE_BDHI 3 309# define WRITE_BDHI 3
310#endif 310#endif
311#ifndef DO_16BIT 311#ifndef DO_16BIT
312# define READ_BDHI 3 312# define READ_BDHI 3
313#endif 313#endif
314 314
315/* The following defines the number of different palettes to generate for 315/* The following defines the number of different palettes to generate for
316 * each log bit depth of a colour type 3 standard image. 316 * each log bit depth of a colour type 3 standard image.
317 */ 317 */
318#define PALETTE_COUNT(bit_depth) ((bit_depth) > 4 ? 1 : 16) 318#define PALETTE_COUNT(bit_depth) ((bit_depth) > 4 ? 1 : 16)
319 319
320static int 320static int
321next_format(png_bytep colour_type, png_bytep bit_depth, int* palette_number) 321next_format(png_bytep colour_type, png_bytep bit_depth, int* palette_number)
322{ 322{
323 if (*bit_depth == 0) 323 if (*bit_depth == 0)
324 { 324 {
325 *colour_type = 0, *bit_depth = 1, *palette_number = 0; 325 *colour_type = 0, *bit_depth = 1, *palette_number = 0;
326 return 1; 326 return 1;
327 } 327 }
328 328
329 if (*colour_type == 3) 329 if (*colour_type == 3)
330 { 330 {
331 /* Add multiple palettes for colour type 3. */ 331 /* Add multiple palettes for colour type 3. */
332 if (++*palette_number < PALETTE_COUNT(*bit_depth)) 332 if (++*palette_number < PALETTE_COUNT(*bit_depth))
333 return 1; 333 return 1;
334 334
335 *palette_number = 0; 335 *palette_number = 0;
336 } 336 }
337 337
338 *bit_depth = (png_byte)(*bit_depth << 1); 338 *bit_depth = (png_byte)(*bit_depth << 1);
339 339
340 /* Palette images are restricted to 8 bit depth */ 340 /* Palette images are restricted to 8 bit depth */
341 if (*bit_depth <= 8 341 if (*bit_depth <= 8
342# ifdef DO_16BIT 342# ifdef DO_16BIT
343 || (*colour_type != 3 && *bit_depth <= 16) 343 || (*colour_type != 3 && *bit_depth <= 16)
344# endif 344# endif
345 ) 345 )
346 return 1; 346 return 1;
347 347
348 /* Move to the next color type, or return 0 at the end. */ 348 /* Move to the next color type, or return 0 at the end. */
349 switch (*colour_type) 349 switch (*colour_type)
350 { 350 {
351 case 0: 351 case 0:
352 *colour_type = 2; 352 *colour_type = 2;
353 *bit_depth = 8; 353 *bit_depth = 8;
354 return 1; 354 return 1;
355 355
356 case 2: 356 case 2:
357 *colour_type = 3; 357 *colour_type = 3;
358 *bit_depth = 1; 358 *bit_depth = 1;
359 return 1; 359 return 1;
360 360
361 case 3: 361 case 3:
362 *colour_type = 4; 362 *colour_type = 4;
363 *bit_depth = 8; 363 *bit_depth = 8;
364 return 1; 364 return 1;
365 365
366 case 4: 366 case 4:
367 *colour_type = 6; 367 *colour_type = 6;
368 *bit_depth = 8; 368 *bit_depth = 8;
369 return 1; 369 return 1;
370 370
371 default: 371 default:
372 return 0; 372 return 0;
373 } 373 }
374} 374}
375 375
376#ifdef PNG_READ_TRANSFORMS_SUPPORTED 376#ifdef PNG_READ_TRANSFORMS_SUPPORTED
377static unsigned int 377static unsigned int
378sample(png_const_bytep row, png_byte colour_type, png_byte bit_depth, 378sample(png_const_bytep row, png_byte colour_type, png_byte bit_depth,
379 png_uint_32 x, unsigned int sample_index) 379 png_uint_32 x, unsigned int sample_index)
380{ 380{
381 png_uint_32 bit_index, result; 381 png_uint_32 bit_index, result;
382 382
383 /* Find a sample index for the desired sample: */ 383 /* Find a sample index for the desired sample: */
384 x *= bit_depth; 384 x *= bit_depth;
385 bit_index = x; 385 bit_index = x;
386 386
387 if ((colour_type & 1) == 0) /* !palette */ 387 if ((colour_type & 1) == 0) /* !palette */
388 { 388 {
389 if (colour_type & 2) 389 if (colour_type & 2)
390 bit_index *= 3; 390 bit_index *= 3;
391 391
392 if (colour_type & 4) 392 if (colour_type & 4)
393 bit_index += x; /* Alpha channel */ 393 bit_index += x; /* Alpha channel */
394 394
395 /* Multiple channels; select one: */ 395 /* Multiple channels; select one: */
396 if (colour_type & (2+4)) 396 if (colour_type & (2+4))
397 bit_index += sample_index * bit_depth; 397 bit_index += sample_index * bit_depth;
398 } 398 }
399 399
400 /* Return the sample from the row as an integer. */ 400 /* Return the sample from the row as an integer. */
401 row += bit_index >> 3; 401 row += bit_index >> 3;
402 result = *row; 402 result = *row;
403 403
404 if (bit_depth == 8) 404 if (bit_depth == 8)
405 return result; 405 return result;
406 406
407 else if (bit_depth > 8) 407 else if (bit_depth > 8)
408 return (result << 8) + *++row; 408 return (result << 8) + *++row;
409 409
410 /* Less than 8 bits per sample. */ 410 /* Less than 8 bits per sample. */
411 bit_index &= 7; 411 bit_index &= 7;
412 return (result >> (8-bit_index-bit_depth)) & ((1U<<bit_depth)-1); 412 return (result >> (8-bit_index-bit_depth)) & ((1U<<bit_depth)-1);
413} 413}
414#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ 414#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
415 415
416/* Copy a single pixel, of a given size, from one buffer to another - 416/* Copy a single pixel, of a given size, from one buffer to another -
417 * while this is basically bit addressed there is an implicit assumption 417 * while this is basically bit addressed there is an implicit assumption
418 * that pixels 8 or more bits in size are byte aligned and that pixels 418 * that pixels 8 or more bits in size are byte aligned and that pixels
419 * do not otherwise cross byte boundaries. (This is, so far as I know, 419 * do not otherwise cross byte boundaries. (This is, so far as I know,
420 * universally true in bitmap computer graphics. [JCB 20101212]) 420 * universally true in bitmap computer graphics. [JCB 20101212])
421 * 421 *
422 * NOTE: The to and from buffers may be the same. 422 * NOTE: The to and from buffers may be the same.
423 */ 423 */
424static void 424static void
425pixel_copy(png_bytep toBuffer, png_uint_32 toIndex, 425pixel_copy(png_bytep toBuffer, png_uint_32 toIndex,
426 png_const_bytep fromBuffer, png_uint_32 fromIndex, unsigned int pixelSize) 426 png_const_bytep fromBuffer, png_uint_32 fromIndex, unsigned int pixelSize)
427{ 427{
428 /* Assume we can multiply by 'size' without overflow because we are 428 /* Assume we can multiply by 'size' without overflow because we are
429 * just working in a single buffer. 429 * just working in a single buffer.
430 */ 430 */
431 toIndex *= pixelSize; 431 toIndex *= pixelSize;
432 fromIndex *= pixelSize; 432 fromIndex *= pixelSize;
433 if (pixelSize < 8) /* Sub-byte */ 433 if (pixelSize < 8) /* Sub-byte */
434 { 434 {
435 /* Mask to select the location of the copied pixel: */ 435 /* Mask to select the location of the copied pixel: */
436 unsigned int destMask = ((1U<<pixelSize)-1) << (8-pixelSize-(toIndex&7)); 436 unsigned int destMask = ((1U<<pixelSize)-1) << (8-pixelSize-(toIndex&7));
437 /* The following read the entire pixels and clears the extra: */ 437 /* The following read the entire pixels and clears the extra: */
438 unsigned int destByte = toBuffer[toIndex >> 3] & ~destMask; 438 unsigned int destByte = toBuffer[toIndex >> 3] & ~destMask;
439 unsigned int sourceByte = fromBuffer[fromIndex >> 3]; 439 unsigned int sourceByte = fromBuffer[fromIndex >> 3];
440 440
441 /* Don't rely on << or >> supporting '0' here, just in case: */ 441 /* Don't rely on << or >> supporting '0' here, just in case: */
442 fromIndex &= 7; 442 fromIndex &= 7;
443 if (fromIndex > 0) sourceByte <<= fromIndex; 443 if (fromIndex > 0) sourceByte <<= fromIndex;
444 if ((toIndex & 7) > 0) sourceByte >>= toIndex & 7; 444 if ((toIndex & 7) > 0) sourceByte >>= toIndex & 7;
445 445
446 toBuffer[toIndex >> 3] = (png_byte)(destByte | (sourceByte & destMask)); 446 toBuffer[toIndex >> 3] = (png_byte)(destByte | (sourceByte & destMask));
447 } 447 }
448 else /* One or more bytes */ 448 else /* One or more bytes */
449 memmove(toBuffer+(toIndex>>3), fromBuffer+(fromIndex>>3), pixelSize>>3); 449 memmove(toBuffer+(toIndex>>3), fromBuffer+(fromIndex>>3), pixelSize>>3);
450} 450}
451 451
452/* Copy a complete row of pixels, taking into account potential partial 452/* Copy a complete row of pixels, taking into account potential partial
453 * bytes at the end. 453 * bytes at the end.
454 */ 454 */
455static void 455static void
456row_copy(png_bytep toBuffer, png_const_bytep fromBuffer, unsigned int bitWidth) 456row_copy(png_bytep toBuffer, png_const_bytep fromBuffer, unsigned int bitWidth)
457{ 457{
458 memcpy(toBuffer, fromBuffer, bitWidth >> 3); 458 memcpy(toBuffer, fromBuffer, bitWidth >> 3);
459 459
460 if ((bitWidth & 7) != 0) 460 if ((bitWidth & 7) != 0)
461 { 461 {
462 unsigned int mask; 462 unsigned int mask;
463 463
464 toBuffer += bitWidth >> 3; 464 toBuffer += bitWidth >> 3;
465 fromBuffer += bitWidth >> 3; 465 fromBuffer += bitWidth >> 3;
466 /* The remaining bits are in the top of the byte, the mask is the bits to 466 /* The remaining bits are in the top of the byte, the mask is the bits to
467 * retain. 467 * retain.
468 */ 468 */
469 mask = 0xff >> (bitWidth & 7); 469 mask = 0xff >> (bitWidth & 7);
470 *toBuffer = (png_byte)((*toBuffer & mask) | (*fromBuffer & ~mask)); 470 *toBuffer = (png_byte)((*toBuffer & mask) | (*fromBuffer & ~mask));
471 } 471 }
472} 472}
473 473
474/* Compare pixels - they are assumed to start at the first byte in the 474/* Compare pixels - they are assumed to start at the first byte in the
475 * given buffers. 475 * given buffers.
476 */ 476 */
477static int 477static int
478pixel_cmp(png_const_bytep pa, png_const_bytep pb, png_uint_32 bit_width) 478pixel_cmp(png_const_bytep pa, png_const_bytep pb, png_uint_32 bit_width)
479{ 479{
480#if PNG_LIBPNG_VER < 10506 480#if PNG_LIBPNG_VER < 10506
481 if (memcmp(pa, pb, bit_width>>3) == 0) 481 if (memcmp(pa, pb, bit_width>>3) == 0)
482 { 482 {
483 png_uint_32 p; 483 png_uint_32 p;
484 484
485 if ((bit_width & 7) == 0) return 0; 485 if ((bit_width & 7) == 0) return 0;
486 486
487 /* Ok, any differences? */ 487 /* Ok, any differences? */
488 p = pa[bit_width >> 3]; 488 p = pa[bit_width >> 3];
489 p ^= pb[bit_width >> 3]; 489 p ^= pb[bit_width >> 3];
490 490
491 if (p == 0) return 0; 491 if (p == 0) return 0;
492 492
493 /* There are, but they may not be significant, remove the bits 493 /* There are, but they may not be significant, remove the bits
494 * after the end (the low order bits in PNG.) 494 * after the end (the low order bits in PNG.)
495 */ 495 */
496 bit_width &= 7; 496 bit_width &= 7;
497 p >>= 8-bit_width; 497 p >>= 8-bit_width;
498 498
499 if (p == 0) return 0; 499 if (p == 0) return 0;
500 } 500 }
501#else 501#else
502 /* From libpng-1.5.6 the overwrite should be fixed, so compare the trailing 502 /* From libpng-1.5.6 the overwrite should be fixed, so compare the trailing
503 * bits too: 503 * bits too:
504 */ 504 */
505 if (memcmp(pa, pb, (bit_width+7)>>3) == 0) 505 if (memcmp(pa, pb, (bit_width+7)>>3) == 0)
506 return 0; 506 return 0;
507#endif 507#endif
508 508
509 /* Return the index of the changed byte. */ 509 /* Return the index of the changed byte. */
510 { 510 {
511 png_uint_32 where = 0; 511 png_uint_32 where = 0;
512 512
513 while (pa[where] == pb[where]) ++where; 513 while (pa[where] == pb[where]) ++where;
514 return 1+where; 514 return 1+where;
515 } 515 }
516} 516}
517 517
518/*************************** BASIC PNG FILE WRITING ***************************/ 518/*************************** BASIC PNG FILE WRITING ***************************/
519/* A png_store takes data from the sequential writer or provides data 519/* A png_store takes data from the sequential writer or provides data
520 * to the sequential reader. It can also store the result of a PNG 520 * to the sequential reader. It can also store the result of a PNG
521 * write for later retrieval. 521 * write for later retrieval.
522 */ 522 */
523#define STORE_BUFFER_SIZE 500 /* arbitrary */ 523#define STORE_BUFFER_SIZE 500 /* arbitrary */
524typedef struct png_store_buffer 524typedef struct png_store_buffer
525{ 525{
526 struct png_store_buffer* prev; /* NOTE: stored in reverse order */ 526 struct png_store_buffer* prev; /* NOTE: stored in reverse order */
527 png_byte buffer[STORE_BUFFER_SIZE]; 527 png_byte buffer[STORE_BUFFER_SIZE];
528} png_store_buffer; 528} png_store_buffer;
529 529
530#define FILE_NAME_SIZE 64 530#define FILE_NAME_SIZE 64
531 531
532typedef struct store_palette_entry /* record of a single palette entry */ 532typedef struct store_palette_entry /* record of a single palette entry */
533{ 533{
534 png_byte red; 534 png_byte red;
535 png_byte green; 535 png_byte green;
536 png_byte blue; 536 png_byte blue;
537 png_byte alpha; 537 png_byte alpha;
538} store_palette_entry, store_palette[256]; 538} store_palette_entry, store_palette[256];
539 539
540typedef struct png_store_file 540typedef struct png_store_file
541{ 541{
542 struct png_store_file* next; /* as many as you like... */ 542 struct png_store_file* next; /* as many as you like... */
543 char name[FILE_NAME_SIZE]; 543 char name[FILE_NAME_SIZE];
544 png_uint_32 id; /* must be correct (see FILEID) */ 544 png_uint_32 id; /* must be correct (see FILEID) */
545 png_size_t datacount; /* In this (the last) buffer */ 545 png_size_t datacount; /* In this (the last) buffer */
546 png_store_buffer data; /* Last buffer in file */ 546 png_store_buffer data; /* Last buffer in file */
547 int npalette; /* Number of entries in palette */ 547 int npalette; /* Number of entries in palette */
548 store_palette_entry* palette; /* May be NULL */ 548 store_palette_entry* palette; /* May be NULL */
549} png_store_file; 549} png_store_file;
550 550
551/* The following is a pool of memory allocated by a single libpng read or write 551/* The following is a pool of memory allocated by a single libpng read or write
552 * operation. 552 * operation.
553 */ 553 */
554typedef struct store_pool 554typedef struct store_pool
555{ 555{
556 struct png_store *store; /* Back pointer */ 556 struct png_store *store; /* Back pointer */
557 struct store_memory *list; /* List of allocated memory */ 557 struct store_memory *list; /* List of allocated memory */
558 png_byte mark[4]; /* Before and after data */ 558 png_byte mark[4]; /* Before and after data */
559 559
560 /* Statistics for this run. */ 560 /* Statistics for this run. */
561 png_alloc_size_t max; /* Maximum single allocation */ 561 png_alloc_size_t max; /* Maximum single allocation */
562 png_alloc_size_t current; /* Current allocation */ 562 png_alloc_size_t current; /* Current allocation */
563 png_alloc_size_t limit; /* Highest current allocation */ 563 png_alloc_size_t limit; /* Highest current allocation */
564 png_alloc_size_t total; /* Total allocation */ 564 png_alloc_size_t total; /* Total allocation */
565 565
566 /* Overall statistics (retained across successive runs). */ 566 /* Overall statistics (retained across successive runs). */
567 png_alloc_size_t max_max; 567 png_alloc_size_t max_max;
568 png_alloc_size_t max_limit; 568 png_alloc_size_t max_limit;
569 png_alloc_size_t max_total; 569 png_alloc_size_t max_total;
570} store_pool; 570} store_pool;
571 571
572typedef struct png_store 572typedef struct png_store
573{ 573{
574 /* For cexcept.h exception handling - simply store one of these; 574 /* For cexcept.h exception handling - simply store one of these;
575 * the context is a self pointer but it may point to a different 575 * the context is a self pointer but it may point to a different
576 * png_store (in fact it never does in this program.) 576 * png_store (in fact it never does in this program.)
577 */ 577 */
578 struct exception_context 578 struct exception_context
579 exception_context; 579 exception_context;
580 580
581 unsigned int verbose :1; 581 unsigned int verbose :1;
582 unsigned int treat_warnings_as_errors :1; 582 unsigned int treat_warnings_as_errors :1;
583 unsigned int expect_error :1; 583 unsigned int expect_error :1;
584 unsigned int expect_warning :1; 584 unsigned int expect_warning :1;
585 unsigned int saw_warning :1; 585 unsigned int saw_warning :1;
586 unsigned int speed :1; 586 unsigned int speed :1;
587 unsigned int progressive :1; /* use progressive read */ 587 unsigned int progressive :1; /* use progressive read */
588 unsigned int validated :1; /* used as a temporary flag */ 588 unsigned int validated :1; /* used as a temporary flag */
589 int nerrors; 589 int nerrors;
590 int nwarnings; 590 int nwarnings;
591 char test[128]; /* Name of test */ 591 char test[128]; /* Name of test */
592 char error[256]; 592 char error[256];
593 593
594 /* Read fields */ 594 /* Read fields */
595 png_structp pread; /* Used to read a saved file */ 595 png_structp pread; /* Used to read a saved file */
596 png_infop piread; 596 png_infop piread;
597 png_store_file* current; /* Set when reading */ 597 png_store_file* current; /* Set when reading */
598 png_store_buffer* next; /* Set when reading */ 598 png_store_buffer* next; /* Set when reading */
599 png_size_t readpos; /* Position in *next */ 599 png_size_t readpos; /* Position in *next */
600 png_byte* image; /* Buffer for reading interlaced images */ 600 png_byte* image; /* Buffer for reading interlaced images */
601 png_size_t cb_image; /* Size of this buffer */ 601 png_size_t cb_image; /* Size of this buffer */
602 png_size_t cb_row; /* Row size of the image(s) */ 602 png_size_t cb_row; /* Row size of the image(s) */
603 png_uint_32 image_h; /* Number of rows in a single image */ 603 png_uint_32 image_h; /* Number of rows in a single image */
604 store_pool read_memory_pool; 604 store_pool read_memory_pool;
605 605
606 /* Write fields */ 606 /* Write fields */
607 png_store_file* saved; 607 png_store_file* saved;
608 png_structp pwrite; /* Used when writing a new file */ 608 png_structp pwrite; /* Used when writing a new file */
609 png_infop piwrite; 609 png_infop piwrite;
610 png_size_t writepos; /* Position in .new */ 610 png_size_t writepos; /* Position in .new */
611 char wname[FILE_NAME_SIZE]; 611 char wname[FILE_NAME_SIZE];
612 png_store_buffer new; /* The end of the new PNG file being written. */ 612 png_store_buffer new; /* The end of the new PNG file being written. */
613 store_pool write_memory_pool; 613 store_pool write_memory_pool;
614 store_palette_entry* palette; 614 store_palette_entry* palette;
615 int npalette; 615 int npalette;
616} png_store; 616} png_store;
617 617
618/* Initialization and cleanup */ 618/* Initialization and cleanup */
619static void 619static void
620store_pool_mark(png_bytep mark) 620store_pool_mark(png_bytep mark)
621{ 621{
622 static png_uint_32 store_seed[2] = { 0x12345678, 1}; 622 static png_uint_32 store_seed[2] = { 0x12345678, 1};
623 623
624 make_four_random_bytes(store_seed, mark); 624 make_four_random_bytes(store_seed, mark);
625} 625}
626 626
627/* Use this for random 32 bit values; this function makes sure the result is 627/* Use this for random 32 bit values; this function makes sure the result is
628 * non-zero. 628 * non-zero.
629 */ 629 */
630static png_uint_32 630static png_uint_32
631random_32(void) 631random_32(void)
632{ 632{
633 633
634 for(;;) 634 for(;;)
635 { 635 {
636 png_byte mark[4]; 636 png_byte mark[4];
637 png_uint_32 result; 637 png_uint_32 result;
638 638
639 store_pool_mark(mark); 639 store_pool_mark(mark);
640 result = png_get_uint_32(mark); 640 result = png_get_uint_32(mark);
641 641
642 if (result != 0) 642 if (result != 0)
643 return result; 643 return result;
644 } 644 }
645} 645}
646 646
647static void 647static void
648store_pool_init(png_store *ps, store_pool *pool) 648store_pool_init(png_store *ps, store_pool *pool)
649{ 649{
650 memset(pool, 0, sizeof *pool); 650 memset(pool, 0, sizeof *pool);
651 651
652 pool->store = ps; 652 pool->store = ps;
653 pool->list = NULL; 653 pool->list = NULL;
654 pool->max = pool->current = pool->limit = pool->total = 0; 654 pool->max = pool->current = pool->limit = pool->total = 0;
655 pool->max_max = pool->max_limit = pool->max_total = 0; 655 pool->max_max = pool->max_limit = pool->max_total = 0;
656 store_pool_mark(pool->mark); 656 store_pool_mark(pool->mark);
657} 657}
658 658
659static void 659static void
660store_init(png_store* ps) 660store_init(png_store* ps)
661{ 661{
662 memset(ps, 0, sizeof *ps); 662 memset(ps, 0, sizeof *ps);
663 init_exception_context(&ps->exception_context); 663 init_exception_context(&ps->exception_context);
664 store_pool_init(ps, &ps->read_memory_pool); 664 store_pool_init(ps, &ps->read_memory_pool);
665 store_pool_init(ps, &ps->write_memory_pool); 665 store_pool_init(ps, &ps->write_memory_pool);
666 ps->verbose = 0; 666 ps->verbose = 0;
667 ps->treat_warnings_as_errors = 0; 667 ps->treat_warnings_as_errors = 0;
668 ps->expect_error = 0; 668 ps->expect_error = 0;
669 ps->expect_warning = 0; 669 ps->expect_warning = 0;
670 ps->saw_warning = 0; 670 ps->saw_warning = 0;
671 ps->speed = 0; 671 ps->speed = 0;
672 ps->progressive = 0; 672 ps->progressive = 0;
673 ps->validated = 0; 673 ps->validated = 0;
674 ps->nerrors = ps->nwarnings = 0; 674 ps->nerrors = ps->nwarnings = 0;
675 ps->pread = NULL; 675 ps->pread = NULL;
676 ps->piread = NULL; 676 ps->piread = NULL;
677 ps->saved = ps->current = NULL; 677 ps->saved = ps->current = NULL;
678 ps->next = NULL; 678 ps->next = NULL;
679 ps->readpos = 0; 679 ps->readpos = 0;
680 ps->image = NULL; 680 ps->image = NULL;
681 ps->cb_image = 0; 681 ps->cb_image = 0;
682 ps->cb_row = 0; 682 ps->cb_row = 0;
683 ps->image_h = 0; 683 ps->image_h = 0;
684 ps->pwrite = NULL; 684 ps->pwrite = NULL;
685 ps->piwrite = NULL; 685 ps->piwrite = NULL;
686 ps->writepos = 0; 686 ps->writepos = 0;
687 ps->new.prev = NULL; 687 ps->new.prev = NULL;
688 ps->palette = NULL; 688 ps->palette = NULL;
689 ps->npalette = 0; 689 ps->npalette = 0;
690} 690}
691 691
692static void 692static void
693store_freebuffer(png_store_buffer* psb) 693store_freebuffer(png_store_buffer* psb)
694{ 694{
695 if (psb->prev) 695 if (psb->prev)
696 { 696 {
697 store_freebuffer(psb->prev); 697 store_freebuffer(psb->prev);
698 free(psb->prev); 698 free(psb->prev);
699 psb->prev = NULL; 699 psb->prev = NULL;
700 } 700 }
701} 701}
702 702
703static void 703static void
704store_freenew(png_store *ps) 704store_freenew(png_store *ps)
705{ 705{
706 store_freebuffer(&ps->new); 706 store_freebuffer(&ps->new);
707 ps->writepos = 0; 707 ps->writepos = 0;
708 if (ps->palette != NULL) 708 if (ps->palette != NULL)
709 { 709 {
710 free(ps->palette); 710 free(ps->palette);
711 ps->palette = NULL; 711 ps->palette = NULL;
712 ps->npalette = 0; 712 ps->npalette = 0;
713 } 713 }
714} 714}
715 715
716static void 716static void
717store_storenew(png_store *ps) 717store_storenew(png_store *ps)
718{ 718{
719 png_store_buffer *pb; 719 png_store_buffer *pb;
720 720
721 if (ps->writepos != STORE_BUFFER_SIZE) 721 if (ps->writepos != STORE_BUFFER_SIZE)
722 png_error(ps->pwrite, "invalid store call"); 722 png_error(ps->pwrite, "invalid store call");
723 723
724 pb = voidcast(png_store_buffer*, malloc(sizeof *pb)); 724 pb = voidcast(png_store_buffer*, malloc(sizeof *pb));
725 725
726 if (pb == NULL) 726 if (pb == NULL)
727 png_error(ps->pwrite, "store new: OOM"); 727 png_error(ps->pwrite, "store new: OOM");
728 728
729 *pb = ps->new; 729 *pb = ps->new;
730 ps->new.prev = pb; 730 ps->new.prev = pb;
731 ps->writepos = 0; 731 ps->writepos = 0;
732} 732}
733 733
734static void 734static void
735store_freefile(png_store_file **ppf) 735store_freefile(png_store_file **ppf)
736{ 736{
737 if (*ppf != NULL) 737 if (*ppf != NULL)
738 { 738 {
739 store_freefile(&(*ppf)->next); 739 store_freefile(&(*ppf)->next);
740 740
741 store_freebuffer(&(*ppf)->data); 741 store_freebuffer(&(*ppf)->data);
742 (*ppf)->datacount = 0; 742 (*ppf)->datacount = 0;
743 if ((*ppf)->palette != NULL) 743 if ((*ppf)->palette != NULL)
744 { 744 {
745 free((*ppf)->palette); 745 free((*ppf)->palette);
746 (*ppf)->palette = NULL; 746 (*ppf)->palette = NULL;
747 (*ppf)->npalette = 0; 747 (*ppf)->npalette = 0;
748 } 748 }
749 free(*ppf); 749 free(*ppf);
750 *ppf = NULL; 750 *ppf = NULL;
751 } 751 }
752} 752}
753 753
754/* Main interface to file storeage, after writing a new PNG file (see the API 754/* Main interface to file storeage, after writing a new PNG file (see the API
755 * below) call store_storefile to store the result with the given name and id. 755 * below) call store_storefile to store the result with the given name and id.
756 */ 756 */
757static void 757static void
758store_storefile(png_store *ps, png_uint_32 id) 758store_storefile(png_store *ps, png_uint_32 id)
759{ 759{
760 png_store_file *pf = voidcast(png_store_file*, malloc(sizeof *pf)); 760 png_store_file *pf = voidcast(png_store_file*, malloc(sizeof *pf));
761 if (pf == NULL) 761 if (pf == NULL)
762 png_error(ps->pwrite, "storefile: OOM"); 762 png_error(ps->pwrite, "storefile: OOM");
763 safecat(pf->name, sizeof pf->name, 0, ps->wname); 763 safecat(pf->name, sizeof pf->name, 0, ps->wname);
764 pf->id = id; 764 pf->id = id;
765 pf->data = ps->new; 765 pf->data = ps->new;
766 pf->datacount = ps->writepos; 766 pf->datacount = ps->writepos;
767 ps->new.prev = NULL; 767 ps->new.prev = NULL;
768 ps->writepos = 0; 768 ps->writepos = 0;
769 pf->palette = ps->palette; 769 pf->palette = ps->palette;
770 pf->npalette = ps->npalette; 770 pf->npalette = ps->npalette;
771 ps->palette = 0; 771 ps->palette = 0;
772 ps->npalette = 0; 772 ps->npalette = 0;
773 773
774 /* And save it. */ 774 /* And save it. */
775 pf->next = ps->saved; 775 pf->next = ps->saved;
776 ps->saved = pf; 776 ps->saved = pf;
777} 777}
778 778
779/* Generate an error message (in the given buffer) */ 779/* Generate an error message (in the given buffer) */
780static size_t 780static size_t
781store_message(png_store *ps, png_structp pp, char *buffer, size_t bufsize, 781store_message(png_store *ps, png_structp pp, char *buffer, size_t bufsize,
782 size_t pos, PNG_CONST char *msg) 782 size_t pos, PNG_CONST char *msg)
783{ 783{
784 if (pp != NULL && pp == ps->pread) 784 if (pp != NULL && pp == ps->pread)
785 { 785 {
786 /* Reading a file */ 786 /* Reading a file */
787 pos = safecat(buffer, bufsize, pos, "read: "); 787 pos = safecat(buffer, bufsize, pos, "read: ");
788 788
789 if (ps->current != NULL) 789 if (ps->current != NULL)
790 { 790 {
791 pos = safecat(buffer, bufsize, pos, ps->current->name); 791 pos = safecat(buffer, bufsize, pos, ps->current->name);
792 pos = safecat(buffer, bufsize, pos, sep); 792 pos = safecat(buffer, bufsize, pos, sep);
793 } 793 }
794 } 794 }
795 795
796 else if (pp != NULL && pp == ps->pwrite) 796 else if (pp != NULL && pp == ps->pwrite)
797 { 797 {
798 /* Writing a file */ 798 /* Writing a file */
799 pos = safecat(buffer, bufsize, pos, "write: "); 799 pos = safecat(buffer, bufsize, pos, "write: ");
800 pos = safecat(buffer, bufsize, pos, ps->wname); 800 pos = safecat(buffer, bufsize, pos, ps->wname);
801 pos = safecat(buffer, bufsize, pos, sep); 801 pos = safecat(buffer, bufsize, pos, sep);
802 } 802 }
803 803
804 else 804 else
805 { 805 {
806 /* Neither reading nor writing (or a memory error in struct delete) */ 806 /* Neither reading nor writing (or a memory error in struct delete) */
807 pos = safecat(buffer, bufsize, pos, "pngvalid: "); 807 pos = safecat(buffer, bufsize, pos, "pngvalid: ");
808 } 808 }
809 809
810 if (ps->test[0] != 0) 810 if (ps->test[0] != 0)
811 { 811 {
812 pos = safecat(buffer, bufsize, pos, ps->test); 812 pos = safecat(buffer, bufsize, pos, ps->test);
813 pos = safecat(buffer, bufsize, pos, sep); 813 pos = safecat(buffer, bufsize, pos, sep);
814 } 814 }
815 pos = safecat(buffer, bufsize, pos, msg); 815 pos = safecat(buffer, bufsize, pos, msg);
816 return pos; 816 return pos;
817} 817}
818 818
819/* Verbose output to the error stream: */ 819/* Verbose output to the error stream: */
820static void 820static void
821store_verbose(png_store *ps, png_structp pp, png_const_charp prefix, 821store_verbose(png_store *ps, png_structp pp, png_const_charp prefix,
822 png_const_charp message) 822 png_const_charp message)
823{ 823{
824 char buffer[512]; 824 char buffer[512];
825 825
826 if (prefix) 826 if (prefix)
827 fputs(prefix, stderr); 827 fputs(prefix, stderr);
828 828
829 (void)store_message(ps, pp, buffer, sizeof buffer, 0, message); 829 (void)store_message(ps, pp, buffer, sizeof buffer, 0, message);
830 fputs(buffer, stderr); 830 fputs(buffer, stderr);
831 fputc('\n', stderr); 831 fputc('\n', stderr);
832} 832}
833 833
834/* Log an error or warning - the relevant count is always incremented. */ 834/* Log an error or warning - the relevant count is always incremented. */
835static void 835static void
836store_log(png_store* ps, png_structp pp, png_const_charp message, int is_error) 836store_log(png_store* ps, png_structp pp, png_const_charp message, int is_error)
837{ 837{
838 /* The warning is copied to the error buffer if there are no errors and it is 838 /* The warning is copied to the error buffer if there are no errors and it is
839 * the first warning. The error is copied to the error buffer if it is the 839 * the first warning. The error is copied to the error buffer if it is the
840 * first error (overwriting any prior warnings). 840 * first error (overwriting any prior warnings).
841 */ 841 */
842 if (is_error ? (ps->nerrors)++ == 0 : 842 if (is_error ? (ps->nerrors)++ == 0 :
843 (ps->nwarnings)++ == 0 && ps->nerrors == 0) 843 (ps->nwarnings)++ == 0 && ps->nerrors == 0)
844 store_message(ps, pp, ps->error, sizeof ps->error, 0, message); 844 store_message(ps, pp, ps->error, sizeof ps->error, 0, message);
845 845
846 if (ps->verbose) 846 if (ps->verbose)
847 store_verbose(ps, pp, is_error ? "error: " : "warning: ", message); 847 store_verbose(ps, pp, is_error ? "error: " : "warning: ", message);
848} 848}
849 849
850/* Internal error function, called with a png_store but no libpng stuff. */ 850/* Internal error function, called with a png_store but no libpng stuff. */
851static void 851static void
852internal_error(png_store *ps, png_const_charp message) 852internal_error(png_store *ps, png_const_charp message)
853{ 853{
854 store_log(ps, NULL, message, 1 /* error */); 854 store_log(ps, NULL, message, 1 /* error */);
855 855
856 /* And finally throw an exception. */ 856 /* And finally throw an exception. */
857 { 857 {
858 struct exception_context *the_exception_context = &ps->exception_context; 858 struct exception_context *the_exception_context = &ps->exception_context;
859 Throw ps; 859 Throw ps;
860 } 860 }
861} 861}
862 862
863/* Functions to use as PNG callbacks. */ 863/* Functions to use as PNG callbacks. */
864static void 864static void
865store_error(png_structp pp, png_const_charp message) /* PNG_NORETURN */ 865store_error(png_structp pp, png_const_charp message) /* PNG_NORETURN */
866{ 866{
867 png_store *ps = voidcast(png_store*, png_get_error_ptr(pp)); 867 png_store *ps = voidcast(png_store*, png_get_error_ptr(pp));
868 868
869 if (!ps->expect_error) 869 if (!ps->expect_error)
870 store_log(ps, pp, message, 1 /* error */); 870 store_log(ps, pp, message, 1 /* error */);
871 871
872 /* And finally throw an exception. */ 872 /* And finally throw an exception. */
873 { 873 {
874 struct exception_context *the_exception_context = &ps->exception_context; 874 struct exception_context *the_exception_context = &ps->exception_context;
875 Throw ps; 875 Throw ps;
876 } 876 }
877} 877}
878 878
879static void 879static void
880store_warning(png_structp pp, png_const_charp message) 880store_warning(png_structp pp, png_const_charp message)
881{ 881{
882 png_store *ps = voidcast(png_store*, png_get_error_ptr(pp)); 882 png_store *ps = voidcast(png_store*, png_get_error_ptr(pp));
883 883
884 if (!ps->expect_warning) 884 if (!ps->expect_warning)
885 store_log(ps, pp, message, 0 /* warning */); 885 store_log(ps, pp, message, 0 /* warning */);
886 else 886 else
887 ps->saw_warning = 1; 887 ps->saw_warning = 1;
888} 888}
889 889
890/* These somewhat odd functions are used when reading an image to ensure that 890/* These somewhat odd functions are used when reading an image to ensure that
891 * the buffer is big enough, the png_structp is for errors. 891 * the buffer is big enough, the png_structp is for errors.
892 */ 892 */
893/* Return a single row from the correct image. */ 893/* Return a single row from the correct image. */
894static png_bytep 894static png_bytep
895store_image_row(PNG_CONST png_store* ps, png_structp pp, int nImage, 895store_image_row(PNG_CONST png_store* ps, png_structp pp, int nImage,
896 png_uint_32 y) 896 png_uint_32 y)
897{ 897{
898 png_size_t coffset = (nImage * ps->image_h + y) * (ps->cb_row + 5) + 2; 898 png_size_t coffset = (nImage * ps->image_h + y) * (ps->cb_row + 5) + 2;
899 899
900 if (ps->image == NULL) 900 if (ps->image == NULL)
901 png_error(pp, "no allocated image"); 901 png_error(pp, "no allocated image");
902 902
903 if (coffset + ps->cb_row + 3 > ps->cb_image) 903 if (coffset + ps->cb_row + 3 > ps->cb_image)
904 png_error(pp, "image too small"); 904 png_error(pp, "image too small");
905 905
906 return ps->image + coffset; 906 return ps->image + coffset;
907} 907}
908 908
909static void 909static void
910store_image_free(png_store *ps, png_structp pp) 910store_image_free(png_store *ps, png_structp pp)
911{ 911{
912 if (ps->image != NULL) 912 if (ps->image != NULL)
913 { 913 {
914 png_bytep image = ps->image; 914 png_bytep image = ps->image;
915 915
916 if (image[-1] != 0xed || image[ps->cb_image] != 0xfe) 916 if (image[-1] != 0xed || image[ps->cb_image] != 0xfe)
917 { 917 {
918 if (pp != NULL) 918 if (pp != NULL)
919 png_error(pp, "png_store image overwrite (1)"); 919 png_error(pp, "png_store image overwrite (1)");
920 else 920 else
921 store_log(ps, NULL, "png_store image overwrite (2)", 1); 921 store_log(ps, NULL, "png_store image overwrite (2)", 1);
922 } 922 }
923 923
924 ps->image = NULL; 924 ps->image = NULL;
925 ps->cb_image = 0; 925 ps->cb_image = 0;
926 --image; 926 --image;
927 free(image); 927 free(image);
928 } 928 }
929} 929}
930 930
931static void 931static void
932store_ensure_image(png_store *ps, png_structp pp, int nImages, png_size_t cbRow, 932store_ensure_image(png_store *ps, png_structp pp, int nImages, png_size_t cbRow,
933 png_uint_32 cRows) 933 png_uint_32 cRows)
934{ 934{
935 png_size_t cb = nImages * cRows * (cbRow + 5); 935 png_size_t cb = nImages * cRows * (cbRow + 5);
936 936
937 if (ps->cb_image < cb) 937 if (ps->cb_image < cb)
938 { 938 {
939 png_bytep image; 939 png_bytep image;
940 940
941 store_image_free(ps, pp); 941 store_image_free(ps, pp);
942 942
943 /* The buffer is deliberately mis-aligned. */ 943 /* The buffer is deliberately mis-aligned. */
944 image = voidcast(png_bytep, malloc(cb+2)); 944 image = voidcast(png_bytep, malloc(cb+2));
945 if (image == NULL) 945 if (image == NULL)
946 { 946 {
947 /* Called from the startup - ignore the error for the moment. */ 947 /* Called from the startup - ignore the error for the moment. */
948 if (pp == NULL) 948 if (pp == NULL)
949 return; 949 return;
950 950
951 png_error(pp, "OOM allocating image buffer"); 951 png_error(pp, "OOM allocating image buffer");
952 } 952 }
953 953
954 /* These magic tags are used to detect overwrites above. */ 954 /* These magic tags are used to detect overwrites above. */
955 ++image; 955 ++image;
956 image[-1] = 0xed; 956 image[-1] = 0xed;
957 image[cb] = 0xfe; 957 image[cb] = 0xfe;
958 958
959 ps->image = image; 959 ps->image = image;
960 ps->cb_image = cb; 960 ps->cb_image = cb;
961 } 961 }
962 962
963 /* We have an adequate sized image; lay out the rows. There are 2 bytes at 963 /* We have an adequate sized image; lay out the rows. There are 2 bytes at
964 * the start and three at the end of each (this ensures that the row 964 * the start and three at the end of each (this ensures that the row
965 * alignment starts out odd - 2+1 and changes for larger images on each row.) 965 * alignment starts out odd - 2+1 and changes for larger images on each row.)
966 */ 966 */
967 ps->cb_row = cbRow; 967 ps->cb_row = cbRow;
968 ps->image_h = cRows; 968 ps->image_h = cRows;
969 969
970 /* For error checking, the whole buffer is set to 10110010 (0xb2 - 178). 970 /* For error checking, the whole buffer is set to 10110010 (0xb2 - 178).
971 * This deliberately doesn't match the bits in the size test image which are 971 * This deliberately doesn't match the bits in the size test image which are
972 * outside the image; these are set to 0xff (all 1). To make the row 972 * outside the image; these are set to 0xff (all 1). To make the row
973 * comparison work in the 'size' test case the size rows are pre-initialized 973 * comparison work in the 'size' test case the size rows are pre-initialized
974 * to the same value prior to calling 'standard_row'. 974 * to the same value prior to calling 'standard_row'.
975 */ 975 */
976 memset(ps->image, 178, cb); 976 memset(ps->image, 178, cb);
977 977
978 /* Then put in the marks. */ 978 /* Then put in the marks. */
979 while (--nImages >= 0) 979 while (--nImages >= 0)
980 { 980 {
981 png_uint_32 y; 981 png_uint_32 y;
982 982
983 for (y=0; y<cRows; ++y) 983 for (y=0; y<cRows; ++y)
984 { 984 {
985 png_bytep row = store_image_row(ps, pp, nImages, y); 985 png_bytep row = store_image_row(ps, pp, nImages, y);
986 986
987 /* The markers: */ 987 /* The markers: */
988 row[-2] = 190; 988 row[-2] = 190;
989 row[-1] = 239; 989 row[-1] = 239;
990 row[cbRow] = 222; 990 row[cbRow] = 222;
991 row[cbRow+1] = 173; 991 row[cbRow+1] = 173;
992 row[cbRow+2] = 17; 992 row[cbRow+2] = 17;
993 } 993 }
994 } 994 }
995} 995}
996 996
997static void 997static void
998store_image_check(PNG_CONST png_store* ps, png_structp pp, int iImage) 998store_image_check(PNG_CONST png_store* ps, png_structp pp, int iImage)
999{ 999{
1000 png_const_bytep image = ps->image; 1000 png_const_bytep image = ps->image;
1001 1001
1002 if (image[-1] != 0xed || image[ps->cb_image] != 0xfe) 1002 if (image[-1] != 0xed || image[ps->cb_image] != 0xfe)
1003 png_error(pp, "image overwrite"); 1003 png_error(pp, "image overwrite");
1004 else 1004 else
1005 { 1005 {
1006 png_size_t cbRow = ps->cb_row; 1006 png_size_t cbRow = ps->cb_row;
1007 png_uint_32 rows = ps->image_h; 1007 png_uint_32 rows = ps->image_h;
1008 1008
1009 image += iImage * (cbRow+5) * ps->image_h; 1009 image += iImage * (cbRow+5) * ps->image_h;
1010 1010
1011 image += 2; /* skip image first row markers */ 1011 image += 2; /* skip image first row markers */
1012 1012
1013 while (rows-- > 0) 1013 while (rows-- > 0)
1014 { 1014 {
1015 if (image[-2] != 190 || image[-1] != 239) 1015 if (image[-2] != 190 || image[-1] != 239)
1016 png_error(pp, "row start overwritten"); 1016 png_error(pp, "row start overwritten");
1017 1017
1018 if (image[cbRow] != 222 || image[cbRow+1] != 173 || 1018 if (image[cbRow] != 222 || image[cbRow+1] != 173 ||
1019 image[cbRow+2] != 17) 1019 image[cbRow+2] != 17)
1020 png_error(pp, "row end overwritten"); 1020 png_error(pp, "row end overwritten");
1021 1021
1022 image += cbRow+5; 1022 image += cbRow+5;
1023 } 1023 }
1024 } 1024 }
1025} 1025}
1026 1026
1027static void 1027static void
1028store_write(png_structp pp, png_bytep pb, png_size_t st) 1028store_write(png_structp pp, png_bytep pb, png_size_t st)
1029{ 1029{
1030 png_store *ps = voidcast(png_store*, png_get_io_ptr(pp)); 1030 png_store *ps = voidcast(png_store*, png_get_io_ptr(pp));
1031 1031
1032 if (ps->pwrite != pp) 1032 if (ps->pwrite != pp)
1033 png_error(pp, "store state damaged"); 1033 png_error(pp, "store state damaged");
1034 1034
1035 while (st > 0) 1035 while (st > 0)
1036 { 1036 {
1037 size_t cb; 1037 size_t cb;
1038 1038
1039 if (ps->writepos >= STORE_BUFFER_SIZE) 1039 if (ps->writepos >= STORE_BUFFER_SIZE)
1040 store_storenew(ps); 1040 store_storenew(ps);
1041 1041
1042 cb = st; 1042 cb = st;
1043 1043
1044 if (cb > STORE_BUFFER_SIZE - ps->writepos) 1044 if (cb > STORE_BUFFER_SIZE - ps->writepos)
1045 cb = STORE_BUFFER_SIZE - ps->writepos; 1045 cb = STORE_BUFFER_SIZE - ps->writepos;
1046 1046
1047 memcpy(ps->new.buffer + ps->writepos, pb, cb); 1047 memcpy(ps->new.buffer + ps->writepos, pb, cb);
1048 pb += cb; 1048 pb += cb;
1049 st -= cb; 1049 st -= cb;
1050 ps->writepos += cb; 1050 ps->writepos += cb;
1051 } 1051 }
1052} 1052}
1053 1053
1054static void 1054static void
1055store_flush(png_structp pp) 1055store_flush(png_structp pp)
1056{ 1056{
1057 UNUSED(pp) /*DOES NOTHING*/ 1057 UNUSED(pp) /*DOES NOTHING*/
1058} 1058}
1059 1059
1060static size_t 1060static size_t
1061store_read_buffer_size(png_store *ps) 1061store_read_buffer_size(png_store *ps)
1062{ 1062{
1063 /* Return the bytes available for read in the current buffer. */ 1063 /* Return the bytes available for read in the current buffer. */
1064 if (ps->next != &ps->current->data) 1064 if (ps->next != &ps->current->data)
1065 return STORE_BUFFER_SIZE; 1065 return STORE_BUFFER_SIZE;
1066 1066
1067 return ps->current->datacount; 1067 return ps->current->datacount;
1068} 1068}
1069 1069
1070#ifdef PNG_READ_TRANSFORMS_SUPPORTED 1070#ifdef PNG_READ_TRANSFORMS_SUPPORTED
1071/* Return total bytes available for read. */ 1071/* Return total bytes available for read. */
1072static size_t 1072static size_t
1073store_read_buffer_avail(png_store *ps) 1073store_read_buffer_avail(png_store *ps)
1074{ 1074{
1075 if (ps->current != NULL && ps->next != NULL) 1075 if (ps->current != NULL && ps->next != NULL)
1076 { 1076 {
1077 png_store_buffer *next = &ps->current->data; 1077 png_store_buffer *next = &ps->current->data;
1078 size_t cbAvail = ps->current->datacount; 1078 size_t cbAvail = ps->current->datacount;
1079 1079
1080 while (next != ps->next && next != NULL) 1080 while (next != ps->next && next != NULL)
1081 { 1081 {
1082 next = next->prev; 1082 next = next->prev;
1083 cbAvail += STORE_BUFFER_SIZE; 1083 cbAvail += STORE_BUFFER_SIZE;
1084 } 1084 }
1085 1085
1086 if (next != ps->next) 1086 if (next != ps->next)
1087 png_error(ps->pread, "buffer read error"); 1087 png_error(ps->pread, "buffer read error");
1088 1088
1089 if (cbAvail > ps->readpos) 1089 if (cbAvail > ps->readpos)
1090 return cbAvail - ps->readpos; 1090 return cbAvail - ps->readpos;
1091 } 1091 }
1092 1092
1093 return 0; 1093 return 0;
1094} 1094}
1095#endif 1095#endif
1096 1096
1097static int 1097static int
1098store_read_buffer_next(png_store *ps) 1098store_read_buffer_next(png_store *ps)
1099{ 1099{
1100 png_store_buffer *pbOld = ps->next; 1100 png_store_buffer *pbOld = ps->next;
1101 png_store_buffer *pbNew = &ps->current->data; 1101 png_store_buffer *pbNew = &ps->current->data;
1102 if (pbOld != pbNew) 1102 if (pbOld != pbNew)
1103 { 1103 {
1104 while (pbNew != NULL && pbNew->prev != pbOld) 1104 while (pbNew != NULL && pbNew->prev != pbOld)
1105 pbNew = pbNew->prev; 1105 pbNew = pbNew->prev;
1106 1106
1107 if (pbNew != NULL) 1107 if (pbNew != NULL)
1108 { 1108 {
1109 ps->next = pbNew; 1109 ps->next = pbNew;
1110 ps->readpos = 0; 1110 ps->readpos = 0;
1111 return 1; 1111 return 1;
1112 } 1112 }
1113 1113
1114 png_error(ps->pread, "buffer lost"); 1114 png_error(ps->pread, "buffer lost");
1115 } 1115 }
1116 1116
1117 return 0; /* EOF or error */ 1117 return 0; /* EOF or error */
1118} 1118}
1119 1119
1120/* Need separate implementation and callback to allow use of the same code 1120/* Need separate implementation and callback to allow use of the same code
1121 * during progressive read, where the io_ptr is set internally by libpng. 1121 * during progressive read, where the io_ptr is set internally by libpng.
1122 */ 1122 */
1123static void 1123static void
1124store_read_imp(png_store *ps, png_bytep pb, png_size_t st) 1124store_read_imp(png_store *ps, png_bytep pb, png_size_t st)
1125{ 1125{
1126 if (ps->current == NULL || ps->next == NULL) 1126 if (ps->current == NULL || ps->next == NULL)
1127 png_error(ps->pread, "store state damaged"); 1127 png_error(ps->pread, "store state damaged");
1128 1128
1129 while (st > 0) 1129 while (st > 0)
1130 { 1130 {
1131 size_t cbAvail = store_read_buffer_size(ps) - ps->readpos; 1131 size_t cbAvail = store_read_buffer_size(ps) - ps->readpos;
1132 1132
1133 if (cbAvail > 0) 1133 if (cbAvail > 0)
1134 { 1134 {
1135 if (cbAvail > st) cbAvail = st; 1135 if (cbAvail > st) cbAvail = st;
1136 memcpy(pb, ps->next->buffer + ps->readpos, cbAvail); 1136 memcpy(pb, ps->next->buffer + ps->readpos, cbAvail);
1137 st -= cbAvail; 1137 st -= cbAvail;
1138 pb += cbAvail; 1138 pb += cbAvail;
1139 ps->readpos += cbAvail; 1139 ps->readpos += cbAvail;
1140 } 1140 }
1141 1141
1142 else if (!store_read_buffer_next(ps)) 1142 else if (!store_read_buffer_next(ps))
1143 png_error(ps->pread, "read beyond end of file"); 1143 png_error(ps->pread, "read beyond end of file");
1144 } 1144 }
1145} 1145}
1146 1146
1147static void 1147static void
1148store_read(png_structp pp, png_bytep pb, png_size_t st) 1148store_read(png_structp pp, png_bytep pb, png_size_t st)
1149{ 1149{
1150 png_store *ps = voidcast(png_store*, png_get_io_ptr(pp)); 1150 png_store *ps = voidcast(png_store*, png_get_io_ptr(pp));
1151 1151
1152 if (ps == NULL || ps->pread != pp) 1152 if (ps == NULL || ps->pread != pp)
1153 png_error(pp, "bad store read call"); 1153 png_error(pp, "bad store read call");
1154 1154
1155 store_read_imp(ps, pb, st); 1155 store_read_imp(ps, pb, st);
1156} 1156}
1157 1157
1158static void 1158static void
1159store_progressive_read(png_store *ps, png_structp pp, png_infop pi) 1159store_progressive_read(png_store *ps, png_structp pp, png_infop pi)
1160{ 1160{
1161 /* Notice that a call to store_read will cause this function to fail because 1161 /* Notice that a call to store_read will cause this function to fail because
1162 * readpos will be set. 1162 * readpos will be set.
1163 */ 1163 */
1164 if (ps->pread != pp || ps->current == NULL || ps->next == NULL) 1164 if (ps->pread != pp || ps->current == NULL || ps->next == NULL)
1165 png_error(pp, "store state damaged (progressive)"); 1165 png_error(pp, "store state damaged (progressive)");
1166 1166
1167 do 1167 do
1168 { 1168 {
1169 if (ps->readpos != 0) 1169 if (ps->readpos != 0)
1170 png_error(pp, "store_read called during progressive read"); 1170 png_error(pp, "store_read called during progressive read");
1171 1171
1172 png_process_data(pp, pi, ps->next->buffer, store_read_buffer_size(ps)); 1172 png_process_data(pp, pi, ps->next->buffer, store_read_buffer_size(ps));
1173 } 1173 }
1174 while (store_read_buffer_next(ps)); 1174 while (store_read_buffer_next(ps));
1175} 1175}
1176 1176
1177/* The caller must fill this in: */ 1177/* The caller must fill this in: */
1178static store_palette_entry * 1178static store_palette_entry *
1179store_write_palette(png_store *ps, int npalette) 1179store_write_palette(png_store *ps, int npalette)
1180{ 1180{
1181 if (ps->pwrite == NULL) 1181 if (ps->pwrite == NULL)
1182 store_log(ps, NULL, "attempt to write palette without write stream", 1); 1182 store_log(ps, NULL, "attempt to write palette without write stream", 1);
1183 1183
1184 if (ps->palette != NULL) 1184 if (ps->palette != NULL)
1185 png_error(ps->pwrite, "multiple store_write_palette calls"); 1185 png_error(ps->pwrite, "multiple store_write_palette calls");
1186 1186
1187 /* This function can only return NULL if called with '0'! */ 1187 /* This function can only return NULL if called with '0'! */
1188 if (npalette > 0) 1188 if (npalette > 0)
1189 { 1189 {
1190 ps->palette = voidcast(store_palette_entry*, malloc(npalette * 1190 ps->palette = voidcast(store_palette_entry*, malloc(npalette *
1191 sizeof *ps->palette)); 1191 sizeof *ps->palette));
1192 1192
1193 if (ps->palette == NULL) 1193 if (ps->palette == NULL)
1194 png_error(ps->pwrite, "store new palette: OOM"); 1194 png_error(ps->pwrite, "store new palette: OOM");
1195 1195
1196 ps->npalette = npalette; 1196 ps->npalette = npalette;
1197 } 1197 }
1198 1198
1199 return ps->palette; 1199 return ps->palette;
1200} 1200}
1201 1201
1202static store_palette_entry * 1202static store_palette_entry *
1203store_current_palette(png_store *ps, int *npalette) 1203store_current_palette(png_store *ps, int *npalette)
1204{ 1204{
1205 /* This is an internal error (the call has been made outside a read 1205 /* This is an internal error (the call has been made outside a read
1206 * operation.) 1206 * operation.)
1207 */ 1207 */
1208 if (ps->current == NULL) 1208 if (ps->current == NULL)
1209 store_log(ps, ps->pread, "no current stream for palette", 1); 1209 store_log(ps, ps->pread, "no current stream for palette", 1);
1210 1210
1211 /* The result may be null if there is no palette. */ 1211 /* The result may be null if there is no palette. */
1212 *npalette = ps->current->npalette; 1212 *npalette = ps->current->npalette;
1213 return ps->current->palette; 1213 return ps->current->palette;
1214} 1214}
1215 1215
1216/***************************** MEMORY MANAGEMENT*** ***************************/ 1216/***************************** MEMORY MANAGEMENT*** ***************************/
1217/* A store_memory is simply the header for an allocated block of memory. The 1217/* A store_memory is simply the header for an allocated block of memory. The
1218 * pointer returned to libpng is just after the end of the header block, the 1218 * pointer returned to libpng is just after the end of the header block, the
1219 * allocated memory is followed by a second copy of the 'mark'. 1219 * allocated memory is followed by a second copy of the 'mark'.
1220 */ 1220 */
1221typedef struct store_memory 1221typedef struct store_memory
1222{ 1222{
1223 store_pool *pool; /* Originating pool */ 1223 store_pool *pool; /* Originating pool */
1224 struct store_memory *next; /* Singly linked list */ 1224 struct store_memory *next; /* Singly linked list */
1225 png_alloc_size_t size; /* Size of memory allocated */ 1225 png_alloc_size_t size; /* Size of memory allocated */
1226 png_byte mark[4]; /* ID marker */ 1226 png_byte mark[4]; /* ID marker */
1227} store_memory; 1227} store_memory;
1228 1228
1229/* Handle a fatal error in memory allocation. This calls png_error if the 1229/* Handle a fatal error in memory allocation. This calls png_error if the
1230 * libpng struct is non-NULL, else it outputs a message and returns. This means 1230 * libpng struct is non-NULL, else it outputs a message and returns. This means
1231 * that a memory problem while libpng is running will abort (png_error) the 1231 * that a memory problem while libpng is running will abort (png_error) the
1232 * handling of particular file while one in cleanup (after the destroy of the 1232 * handling of particular file while one in cleanup (after the destroy of the
1233 * struct has returned) will simply keep going and free (or attempt to free) 1233 * struct has returned) will simply keep going and free (or attempt to free)
1234 * all the memory. 1234 * all the memory.
1235 */ 1235 */
1236static void 1236static void
1237store_pool_error(png_store *ps, png_structp pp, PNG_CONST char *msg) 1237store_pool_error(png_store *ps, png_structp pp, PNG_CONST char *msg)
1238{ 1238{
1239 if (pp != NULL) 1239 if (pp != NULL)
1240 png_error(pp, msg); 1240 png_error(pp, msg);
1241 1241
1242 /* Else we have to do it ourselves. png_error eventually calls store_log, 1242 /* Else we have to do it ourselves. png_error eventually calls store_log,
1243 * above. store_log accepts a NULL png_structp - it just changes what gets 1243 * above. store_log accepts a NULL png_structp - it just changes what gets
1244 * output by store_message. 1244 * output by store_message.
1245 */ 1245 */
1246 store_log(ps, pp, msg, 1 /* error */); 1246 store_log(ps, pp, msg, 1 /* error */);
1247} 1247}
1248 1248
1249static void 1249static void
1250store_memory_free(png_structp pp, store_pool *pool, store_memory *memory) 1250store_memory_free(png_structp pp, store_pool *pool, store_memory *memory)
1251{ 1251{
1252 /* Note that pp may be NULL (see store_pool_delete below), the caller has 1252 /* Note that pp may be NULL (see store_pool_delete below), the caller has
1253 * found 'memory' in pool->list *and* unlinked this entry, so this is a valid 1253 * found 'memory' in pool->list *and* unlinked this entry, so this is a valid
1254 * pointer (for sure), but the contents may have been trashed. 1254 * pointer (for sure), but the contents may have been trashed.
1255 */ 1255 */
1256 if (memory->pool != pool) 1256 if (memory->pool != pool)
1257 store_pool_error(pool->store, pp, "memory corrupted (pool)"); 1257 store_pool_error(pool->store, pp, "memory corrupted (pool)");
1258 1258
1259 else if (memcmp(memory->mark, pool->mark, sizeof memory->mark) != 0) 1259 else if (memcmp(memory->mark, pool->mark, sizeof memory->mark) != 0)
1260 store_pool_error(pool->store, pp, "memory corrupted (start)"); 1260 store_pool_error(pool->store, pp, "memory corrupted (start)");
1261 1261
1262 /* It should be safe to read the size field now. */ 1262 /* It should be safe to read the size field now. */
1263 else 1263 else
1264 { 1264 {
1265 png_alloc_size_t cb = memory->size; 1265 png_alloc_size_t cb = memory->size;
1266 1266
1267 if (cb > pool->max) 1267 if (cb > pool->max)
1268 store_pool_error(pool->store, pp, "memory corrupted (size)"); 1268 store_pool_error(pool->store, pp, "memory corrupted (size)");
1269 1269
1270 else if (memcmp((png_bytep)(memory+1)+cb, pool->mark, sizeof pool->mark) 1270 else if (memcmp((png_bytep)(memory+1)+cb, pool->mark, sizeof pool->mark)
1271 != 0) 1271 != 0)
1272 store_pool_error(pool->store, pp, "memory corrupted (end)"); 1272 store_pool_error(pool->store, pp, "memory corrupted (end)");
1273 1273
1274 /* Finally give the library a chance to find problems too: */ 1274 /* Finally give the library a chance to find problems too: */
1275 else 1275 else
1276 { 1276 {
1277 pool->current -= cb; 1277 pool->current -= cb;
1278 free(memory); 1278 free(memory);
1279 } 1279 }
1280 } 1280 }
1281} 1281}
1282 1282
1283static void 1283static void
1284store_pool_delete(png_store *ps, store_pool *pool) 1284store_pool_delete(png_store *ps, store_pool *pool)
1285{ 1285{
1286 if (pool->list != NULL) 1286 if (pool->list != NULL)
1287 { 1287 {
1288 fprintf(stderr, "%s: %s %s: memory lost (list follows):\n", ps->test, 1288 fprintf(stderr, "%s: %s %s: memory lost (list follows):\n", ps->test,
1289 pool == &ps->read_memory_pool ? "read" : "write", 1289 pool == &ps->read_memory_pool ? "read" : "write",
1290 pool == &ps->read_memory_pool ? (ps->current != NULL ? 1290 pool == &ps->read_memory_pool ? (ps->current != NULL ?
1291 ps->current->name : "unknown file") : ps->wname); 1291 ps->current->name : "unknown file") : ps->wname);
1292 ++ps->nerrors; 1292 ++ps->nerrors;
1293 1293
1294 do 1294 do
1295 { 1295 {
1296 store_memory *next = pool->list; 1296 store_memory *next = pool->list;
1297 pool->list = next->next; 1297 pool->list = next->next;
1298 next->next = NULL; 1298 next->next = NULL;
1299 1299
1300 fprintf(stderr, "\t%lu bytes @ %p\n", 1300 fprintf(stderr, "\t%lu bytes @ %p\n",
1301 (unsigned long)next->size, (PNG_CONST void*)(next+1)); 1301 (unsigned long)next->size, (PNG_CONST void*)(next+1));
1302 /* The NULL means this will always return, even if the memory is 1302 /* The NULL means this will always return, even if the memory is
1303 * corrupted. 1303 * corrupted.
1304 */ 1304 */
1305 store_memory_free(NULL, pool, next); 1305 store_memory_free(NULL, pool, next);
1306 } 1306 }
1307 while (pool->list != NULL); 1307 while (pool->list != NULL);
1308 } 1308 }
1309 1309
1310 /* And reset the other fields too for the next time. */ 1310 /* And reset the other fields too for the next time. */
1311 if (pool->max > pool->max_max) pool->max_max = pool->max; 1311 if (pool->max > pool->max_max) pool->max_max = pool->max;
1312 pool->max = 0; 1312 pool->max = 0;
1313 if (pool->current != 0) /* unexpected internal error */ 1313 if (pool->current != 0) /* unexpected internal error */
1314 fprintf(stderr, "%s: %s %s: memory counter mismatch (internal error)\n", 1314 fprintf(stderr, "%s: %s %s: memory counter mismatch (internal error)\n",
1315 ps->test, pool == &ps->read_memory_pool ? "read" : "write", 1315 ps->test, pool == &ps->read_memory_pool ? "read" : "write",
1316 pool == &ps->read_memory_pool ? (ps->current != NULL ? 1316 pool == &ps->read_memory_pool ? (ps->current != NULL ?
1317 ps->current->name : "unknown file") : ps->wname); 1317 ps->current->name : "unknown file") : ps->wname);
1318 pool->current = 0; 1318 pool->current = 0;
1319 1319
1320 if (pool->limit > pool->max_limit) 1320 if (pool->limit > pool->max_limit)
1321 pool->max_limit = pool->limit; 1321 pool->max_limit = pool->limit;
1322 1322
1323 pool->limit = 0; 1323 pool->limit = 0;
1324 1324
1325 if (pool->total > pool->max_total) 1325 if (pool->total > pool->max_total)
1326 pool->max_total = pool->total; 1326 pool->max_total = pool->total;
1327 1327
1328 pool->total = 0; 1328 pool->total = 0;
1329 1329
1330 /* Get a new mark too. */ 1330 /* Get a new mark too. */
1331 store_pool_mark(pool->mark); 1331 store_pool_mark(pool->mark);
1332} 1332}
1333 1333
1334/* The memory callbacks: */ 1334/* The memory callbacks: */
1335static png_voidp 1335static png_voidp
1336store_malloc(png_structp pp, png_alloc_size_t cb) 1336store_malloc(png_structp pp, png_alloc_size_t cb)
1337{ 1337{
1338 store_pool *pool = voidcast(store_pool*, png_get_mem_ptr(pp)); 1338 store_pool *pool = voidcast(store_pool*, png_get_mem_ptr(pp));
1339 store_memory *new = voidcast(store_memory*, malloc(cb + (sizeof *new) + 1339 store_memory *new = voidcast(store_memory*, malloc(cb + (sizeof *new) +
1340 (sizeof pool->mark))); 1340 (sizeof pool->mark)));
1341 1341
1342 if (new != NULL) 1342 if (new != NULL)
1343 { 1343 {
1344 if (cb > pool->max) 1344 if (cb > pool->max)
1345 pool->max = cb; 1345 pool->max = cb;
1346 1346
1347 pool->current += cb; 1347 pool->current += cb;
1348 1348
1349 if (pool->current > pool->limit) 1349 if (pool->current > pool->limit)
1350 pool->limit = pool->current; 1350 pool->limit = pool->current;
1351 1351
1352 pool->total += cb; 1352 pool->total += cb;
1353 1353
1354 new->size = cb; 1354 new->size = cb;
1355 memcpy(new->mark, pool->mark, sizeof new->mark); 1355 memcpy(new->mark, pool->mark, sizeof new->mark);
1356 memcpy((png_byte*)(new+1) + cb, pool->mark, sizeof pool->mark); 1356 memcpy((png_byte*)(new+1) + cb, pool->mark, sizeof pool->mark);
1357 new->pool = pool; 1357 new->pool = pool;
1358 new->next = pool->list; 1358 new->next = pool->list;
1359 pool->list = new; 1359 pool->list = new;
1360 ++new; 1360 ++new;
1361 } 1361 }
1362 1362
1363 else 1363 else
1364 { 1364 {
1365 /* NOTE: the PNG user malloc function cannot use the png_ptr it is passed 1365 /* NOTE: the PNG user malloc function cannot use the png_ptr it is passed
1366 * other than to retrieve the allocation pointer! libpng calls the 1366 * other than to retrieve the allocation pointer! libpng calls the
1367 * store_malloc callback in two basic cases: 1367 * store_malloc callback in two basic cases:
1368 * 1368 *
1369 * 1) From png_malloc; png_malloc will do a png_error itself if NULL is 1369 * 1) From png_malloc; png_malloc will do a png_error itself if NULL is
1370 * returned. 1370 * returned.
1371 * 2) From png_struct or png_info structure creation; png_malloc is 1371 * 2) From png_struct or png_info structure creation; png_malloc is
1372 * to return so cleanup can be performed. 1372 * to return so cleanup can be performed.
1373 * 1373 *
1374 * To handle this store_malloc can log a message, but can't do anything 1374 * To handle this store_malloc can log a message, but can't do anything
1375 * else. 1375 * else.
1376 */ 1376 */
1377 store_log(pool->store, pp, "out of memory", 1 /* is_error */); 1377 store_log(pool->store, pp, "out of memory", 1 /* is_error */);
1378 } 1378 }
1379 1379
1380 return new; 1380 return new;
1381} 1381}
1382 1382
1383static void 1383static void
1384store_free(png_structp pp, png_voidp memory) 1384store_free(png_structp pp, png_voidp memory)
1385{ 1385{
1386 store_pool *pool = voidcast(store_pool*, png_get_mem_ptr(pp)); 1386 store_pool *pool = voidcast(store_pool*, png_get_mem_ptr(pp));
1387 store_memory *this = voidcast(store_memory*, memory), **test; 1387 store_memory *this = voidcast(store_memory*, memory), **test;
1388 1388
1389 /* Because libpng calls store_free with a dummy png_struct when deleting 1389 /* Because libpng calls store_free with a dummy png_struct when deleting
1390 * png_struct or png_info via png_destroy_struct_2 it is necessary to check 1390 * png_struct or png_info via png_destroy_struct_2 it is necessary to check
1391 * the passed in png_structp to ensure it is valid, and not pass it to 1391 * the passed in png_structp to ensure it is valid, and not pass it to
1392 * png_error if it is not. 1392 * png_error if it is not.
1393 */ 1393 */
1394 if (pp != pool->store->pread && pp != pool->store->pwrite) 1394 if (pp != pool->store->pread && pp != pool->store->pwrite)
1395 pp = NULL; 1395 pp = NULL;
1396 1396
1397 /* First check that this 'memory' really is valid memory - it must be in the 1397 /* First check that this 'memory' really is valid memory - it must be in the
1398 * pool list. If it is, use the shared memory_free function to free it. 1398 * pool list. If it is, use the shared memory_free function to free it.
1399 */ 1399 */
1400 --this; 1400 --this;
1401 for (test = &pool->list; *test != this; test = &(*test)->next) 1401 for (test = &pool->list; *test != this; test = &(*test)->next)
1402 { 1402 {
1403 if (*test == NULL) 1403 if (*test == NULL)
1404 { 1404 {
1405 store_pool_error(pool->store, pp, "bad pointer to free"); 1405 store_pool_error(pool->store, pp, "bad pointer to free");
1406 return; 1406 return;
1407 } 1407 }
1408 } 1408 }
1409 1409
1410 /* Unlink this entry, *test == this. */ 1410 /* Unlink this entry, *test == this. */
1411 *test = this->next; 1411 *test = this->next;
1412 this->next = NULL; 1412 this->next = NULL;
1413 store_memory_free(pp, pool, this); 1413 store_memory_free(pp, pool, this);
1414} 1414}
1415 1415
1416/* Setup functions. */ 1416/* Setup functions. */
1417/* Cleanup when aborting a write or after storing the new file. */ 1417/* Cleanup when aborting a write or after storing the new file. */
1418static void 1418static void
1419store_write_reset(png_store *ps) 1419store_write_reset(png_store *ps)
1420{ 1420{
1421 if (ps->pwrite != NULL) 1421 if (ps->pwrite != NULL)
1422 { 1422 {
1423 anon_context(ps); 1423 anon_context(ps);
1424 1424
1425 Try 1425 Try
1426 png_destroy_write_struct(&ps->pwrite, &ps->piwrite); 1426 png_destroy_write_struct(&ps->pwrite, &ps->piwrite);
1427 1427
1428 Catch_anonymous 1428 Catch_anonymous
1429 { 1429 {
1430 /* memory corruption: continue. */ 1430 /* memory corruption: continue. */
1431 } 1431 }
1432 1432
1433 ps->pwrite = NULL; 1433 ps->pwrite = NULL;
1434 ps->piwrite = NULL; 1434 ps->piwrite = NULL;
1435 } 1435 }
1436 1436
1437 /* And make sure that all the memory has been freed - this will output 1437 /* And make sure that all the memory has been freed - this will output
1438 * spurious errors in the case of memory corruption above, but this is safe. 1438 * spurious errors in the case of memory corruption above, but this is safe.
1439 */ 1439 */
1440 store_pool_delete(ps, &ps->write_memory_pool); 1440 store_pool_delete(ps, &ps->write_memory_pool);
1441 1441
1442 store_freenew(ps); 1442 store_freenew(ps);
1443} 1443}
1444 1444
1445/* The following is the main write function, it returns a png_struct and, 1445/* The following is the main write function, it returns a png_struct and,
1446 * optionally, a png_info suitable for writiing a new PNG file. Use 1446 * optionally, a png_info suitable for writiing a new PNG file. Use
1447 * store_storefile above to record this file after it has been written. The 1447 * store_storefile above to record this file after it has been written. The
1448 * returned libpng structures as destroyed by store_write_reset above. 1448 * returned libpng structures as destroyed by store_write_reset above.
1449 */ 1449 */
1450static png_structp 1450static png_structp
1451set_store_for_write(png_store *ps, png_infopp ppi, 1451set_store_for_write(png_store *ps, png_infopp ppi,
1452 PNG_CONST char * volatile name) 1452 PNG_CONST char * volatile name)
1453{ 1453{
1454 anon_context(ps); 1454 anon_context(ps);
1455 1455
1456 Try 1456 Try
1457 { 1457 {
1458 if (ps->pwrite != NULL) 1458 if (ps->pwrite != NULL)
1459 png_error(ps->pwrite, "write store already in use"); 1459 png_error(ps->pwrite, "write store already in use");
1460 1460
1461 store_write_reset(ps); 1461 store_write_reset(ps);
1462 safecat(ps->wname, sizeof ps->wname, 0, name); 1462 safecat(ps->wname, sizeof ps->wname, 0, name);
1463 1463
1464 /* Don't do the slow memory checks if doing a speed test. */ 1464 /* Don't do the slow memory checks if doing a speed test. */
1465 if (ps->speed) 1465 if (ps->speed)
1466 ps->pwrite = png_create_write_struct(PNG_LIBPNG_VER_STRING, 1466 ps->pwrite = png_create_write_struct(PNG_LIBPNG_VER_STRING,
1467 ps, store_error, store_warning); 1467 ps, store_error, store_warning);
1468 1468
1469 else 1469 else
1470 ps->pwrite = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, 1470 ps->pwrite = png_create_write_struct_2(PNG_LIBPNG_VER_STRING,
1471 ps, store_error, store_warning, &ps->write_memory_pool, 1471 ps, store_error, store_warning, &ps->write_memory_pool,
1472 store_malloc, store_free); 1472 store_malloc, store_free);
1473 1473
1474 png_set_write_fn(ps->pwrite, ps, store_write, store_flush); 1474 png_set_write_fn(ps->pwrite, ps, store_write, store_flush);
1475 1475
1476 if (ppi != NULL) 1476 if (ppi != NULL)
1477 *ppi = ps->piwrite = png_create_info_struct(ps->pwrite); 1477 *ppi = ps->piwrite = png_create_info_struct(ps->pwrite);
1478 } 1478 }
1479 1479
1480 Catch_anonymous 1480 Catch_anonymous
1481 return NULL; 1481 return NULL;
1482 1482
1483 return ps->pwrite; 1483 return ps->pwrite;
1484} 1484}
1485 1485
1486/* Cleanup when finished reading (either due to error or in the success case). 1486/* Cleanup when finished reading (either due to error or in the success case).
1487 */ 1487 */
1488static void 1488static void
1489store_read_reset(png_store *ps) 1489store_read_reset(png_store *ps)
1490{ 1490{
1491 if (ps->pread != NULL) 1491 if (ps->pread != NULL)
1492 { 1492 {
1493 anon_context(ps); 1493 anon_context(ps);
1494 1494
1495 Try 1495 Try
1496 png_destroy_read_struct(&ps->pread, &ps->piread, NULL); 1496 png_destroy_read_struct(&ps->pread, &ps->piread, NULL);
1497 1497
1498 Catch_anonymous 1498 Catch_anonymous
1499 { 1499 {
1500 /* error already output: continue */ 1500 /* error already output: continue */
1501 } 1501 }
1502 1502
1503 ps->pread = NULL; 1503 ps->pread = NULL;
1504 ps->piread = NULL; 1504 ps->piread = NULL;
1505 } 1505 }
1506 1506
1507 /* Always do this to be safe. */ 1507 /* Always do this to be safe. */
1508 store_pool_delete(ps, &ps->read_memory_pool); 1508 store_pool_delete(ps, &ps->read_memory_pool);
1509 1509
1510 ps->current = NULL; 1510 ps->current = NULL;
1511 ps->next = NULL; 1511 ps->next = NULL;
1512 ps->readpos = 0; 1512 ps->readpos = 0;
1513 ps->validated = 0; 1513 ps->validated = 0;
1514} 1514}
1515 1515
1516static void 1516static void
1517store_read_set(png_store *ps, png_uint_32 id) 1517store_read_set(png_store *ps, png_uint_32 id)
1518{ 1518{
1519 png_store_file *pf = ps->saved; 1519 png_store_file *pf = ps->saved;
1520 1520
1521 while (pf != NULL) 1521 while (pf != NULL)
1522 { 1522 {
1523 if (pf->id == id) 1523 if (pf->id == id)
1524 { 1524 {
1525 ps->current = pf; 1525 ps->current = pf;
1526 ps->next = NULL; 1526 ps->next = NULL;
1527 store_read_buffer_next(ps); 1527 store_read_buffer_next(ps);
1528 return; 1528 return;
1529 } 1529 }
1530 1530
1531 pf = pf->next; 1531 pf = pf->next;
1532 } 1532 }
1533 1533
1534 { 1534 {
1535 size_t pos; 1535 size_t pos;
1536 char msg[FILE_NAME_SIZE+64]; 1536 char msg[FILE_NAME_SIZE+64];
1537 1537
1538 pos = standard_name_from_id(msg, sizeof msg, 0, id); 1538 pos = standard_name_from_id(msg, sizeof msg, 0, id);
1539 pos = safecat(msg, sizeof msg, pos, ": file not found"); 1539 pos = safecat(msg, sizeof msg, pos, ": file not found");
1540 png_error(ps->pread, msg); 1540 png_error(ps->pread, msg);
1541 } 1541 }
1542} 1542}
1543 1543
1544/* The main interface for reading a saved file - pass the id number of the file 1544/* The main interface for reading a saved file - pass the id number of the file
1545 * to retrieve. Ids must be unique or the earlier file will be hidden. The API 1545 * to retrieve. Ids must be unique or the earlier file will be hidden. The API
1546 * returns a png_struct and, optionally, a png_info. Both of these will be 1546 * returns a png_struct and, optionally, a png_info. Both of these will be
1547 * destroyed by store_read_reset above. 1547 * destroyed by store_read_reset above.
1548 */ 1548 */
1549static png_structp 1549static png_structp
1550set_store_for_read(png_store *ps, png_infopp ppi, png_uint_32 id, 1550set_store_for_read(png_store *ps, png_infopp ppi, png_uint_32 id,
1551 PNG_CONST char *name) 1551 PNG_CONST char *name)
1552{ 1552{
1553 /* Set the name for png_error */ 1553 /* Set the name for png_error */
1554 safecat(ps->test, sizeof ps->test, 0, name); 1554 safecat(ps->test, sizeof ps->test, 0, name);
1555 1555
1556 if (ps->pread != NULL) 1556 if (ps->pread != NULL)
1557 png_error(ps->pread, "read store already in use"); 1557 png_error(ps->pread, "read store already in use");
1558 1558
1559 store_read_reset(ps); 1559 store_read_reset(ps);
1560 1560
1561 /* Both the create APIs can return NULL if used in their default mode 1561 /* Both the create APIs can return NULL if used in their default mode
1562 * (because there is no other way of handling an error because the jmp_buf 1562 * (because there is no other way of handling an error because the jmp_buf
1563 * by default is stored in png_struct and that has not been allocated!) 1563 * by default is stored in png_struct and that has not been allocated!)
1564 * However, given that store_error works correctly in these circumstances 1564 * However, given that store_error works correctly in these circumstances
1565 * we don't ever expect NULL in this program. 1565 * we don't ever expect NULL in this program.
1566 */ 1566 */
1567 if (ps->speed) 1567 if (ps->speed)
1568 ps->pread = png_create_read_struct(PNG_LIBPNG_VER_STRING, ps, 1568 ps->pread = png_create_read_struct(PNG_LIBPNG_VER_STRING, ps,
1569 store_error, store_warning); 1569 store_error, store_warning);
1570 1570
1571 else 1571 else
1572 ps->pread = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, ps, 1572 ps->pread = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, ps,
1573 store_error, store_warning, &ps->read_memory_pool, store_malloc, 1573 store_error, store_warning, &ps->read_memory_pool, store_malloc,
1574 store_free); 1574 store_free);
1575 1575
1576 if (ps->pread == NULL) 1576 if (ps->pread == NULL)
1577 { 1577 {
1578 struct exception_context *the_exception_context = &ps->exception_context; 1578 struct exception_context *the_exception_context = &ps->exception_context;
1579 1579
1580 store_log(ps, NULL, "png_create_read_struct returned NULL (unexpected)", 1580 store_log(ps, NULL, "png_create_read_struct returned NULL (unexpected)",
1581 1 /*error*/); 1581 1 /*error*/);
1582 1582
1583 Throw ps; 1583 Throw ps;
1584 } 1584 }
1585 1585
1586 store_read_set(ps, id); 1586 store_read_set(ps, id);
1587 1587
1588 if (ppi != NULL) 1588 if (ppi != NULL)
1589 *ppi = ps->piread = png_create_info_struct(ps->pread); 1589 *ppi = ps->piread = png_create_info_struct(ps->pread);
1590 1590
1591 return ps->pread; 1591 return ps->pread;
1592} 1592}
1593 1593
1594/* The overall cleanup of a store simply calls the above then removes all the 1594/* The overall cleanup of a store simply calls the above then removes all the
1595 * saved files. This does not delete the store itself. 1595 * saved files. This does not delete the store itself.
1596 */ 1596 */
1597static void 1597static void
1598store_delete(png_store *ps) 1598store_delete(png_store *ps)
1599{ 1599{
1600 store_write_reset(ps); 1600 store_write_reset(ps);
1601 store_read_reset(ps); 1601 store_read_reset(ps);
1602 store_freefile(&ps->saved); 1602 store_freefile(&ps->saved);
1603 store_image_free(ps, NULL); 1603 store_image_free(ps, NULL);
1604} 1604}
1605 1605
1606/*********************** PNG FILE MODIFICATION ON READ ************************/ 1606/*********************** PNG FILE MODIFICATION ON READ ************************/
1607/* Files may be modified on read. The following structure contains a complete 1607/* Files may be modified on read. The following structure contains a complete
1608 * png_store together with extra members to handle modification and a special 1608 * png_store together with extra members to handle modification and a special
1609 * read callback for libpng. To use this the 'modifications' field must be set 1609 * read callback for libpng. To use this the 'modifications' field must be set
1610 * to a list of png_modification structures that actually perform the 1610 * to a list of png_modification structures that actually perform the
1611 * modification, otherwise a png_modifier is functionally equivalent to a 1611 * modification, otherwise a png_modifier is functionally equivalent to a
1612 * png_store. There is a special read function, set_modifier_for_read, which 1612 * png_store. There is a special read function, set_modifier_for_read, which
1613 * replaces set_store_for_read. 1613 * replaces set_store_for_read.
1614 */ 1614 */
1615typedef enum modifier_state 1615typedef enum modifier_state
1616{ 1616{
1617 modifier_start, /* Initial value */ 1617 modifier_start, /* Initial value */
1618 modifier_signature, /* Have a signature */ 1618 modifier_signature, /* Have a signature */
1619 modifier_IHDR /* Have an IHDR */ 1619 modifier_IHDR /* Have an IHDR */
1620} modifier_state; 1620} modifier_state;
1621 1621
1622typedef struct CIE_color 1622typedef struct CIE_color
1623{ 1623{
1624 /* A single CIE tristimulus value, representing the unique response of a 1624 /* A single CIE tristimulus value, representing the unique response of a
1625 * standard observer to a variety of light spectra. The observer recognizes 1625 * standard observer to a variety of light spectra. The observer recognizes
1626 * all spectra that produce this response as the same color, therefore this 1626 * all spectra that produce this response as the same color, therefore this
1627 * is effectively a description of a color. 1627 * is effectively a description of a color.
1628 */ 1628 */
1629 double X, Y, Z; 1629 double X, Y, Z;
1630} CIE_color; 1630} CIE_color;
1631 1631
1632static double 1632static double
1633chromaticity_x(CIE_color c) 1633chromaticity_x(CIE_color c)
1634{ 1634{
1635 return c.X / (c.X + c.Y + c.Z); 1635 return c.X / (c.X + c.Y + c.Z);
1636} 1636}
1637 1637
1638static double 1638static double
1639chromaticity_y(CIE_color c) 1639chromaticity_y(CIE_color c)
1640{ 1640{
1641 return c.Y / (c.X + c.Y + c.Z); 1641 return c.Y / (c.X + c.Y + c.Z);
1642} 1642}
1643 1643
1644typedef struct color_encoding 1644typedef struct color_encoding
1645{ 1645{
1646 /* A description of an (R,G,B) encoding of color (as defined above); this 1646 /* A description of an (R,G,B) encoding of color (as defined above); this
1647 * includes the actual colors of the (R,G,B) triples (1,0,0), (0,1,0) and 1647 * includes the actual colors of the (R,G,B) triples (1,0,0), (0,1,0) and
1648 * (0,0,1) plus an encoding value that is used to encode the linear 1648 * (0,0,1) plus an encoding value that is used to encode the linear
1649 * components R, G and B to give the actual values R^gamma, G^gamma and 1649 * components R, G and B to give the actual values R^gamma, G^gamma and
1650 * B^gamma that are stored. 1650 * B^gamma that are stored.
1651 */ 1651 */
1652 double gamma; /* Encoding (file) gamma of space */ 1652 double gamma; /* Encoding (file) gamma of space */
1653 CIE_color red, green, blue; /* End points */ 1653 CIE_color red, green, blue; /* End points */
1654} color_encoding; 1654} color_encoding;
1655 1655
1656static CIE_color 1656static CIE_color
1657white_point(PNG_CONST color_encoding *encoding) 1657white_point(PNG_CONST color_encoding *encoding)
1658{ 1658{
1659 CIE_color white; 1659 CIE_color white;
1660 1660
1661 white.X = encoding->red.X + encoding->green.X + encoding->blue.X; 1661 white.X = encoding->red.X + encoding->green.X + encoding->blue.X;
1662 white.Y = encoding->red.Y + encoding->green.Y + encoding->blue.Y; 1662 white.Y = encoding->red.Y + encoding->green.Y + encoding->blue.Y;
1663 white.Z = encoding->red.Z + encoding->green.Z + encoding->blue.Z; 1663 white.Z = encoding->red.Z + encoding->green.Z + encoding->blue.Z;
1664 1664
1665 return white; 1665 return white;
1666} 1666}
1667 1667
1668static void 1668static void
1669normalize_color_encoding(color_encoding *encoding) 1669normalize_color_encoding(color_encoding *encoding)
1670{ 1670{
1671 PNG_CONST double whiteY = encoding->red.Y + encoding->green.Y + 1671 PNG_CONST double whiteY = encoding->red.Y + encoding->green.Y +
1672 encoding->blue.Y; 1672 encoding->blue.Y;
1673 1673
1674 if (whiteY != 1) 1674 if (whiteY != 1)
1675 { 1675 {
1676 encoding->red.X /= whiteY; 1676 encoding->red.X /= whiteY;
1677 encoding->red.Y /= whiteY; 1677 encoding->red.Y /= whiteY;
1678 encoding->red.Z /= whiteY; 1678 encoding->red.Z /= whiteY;
1679 encoding->green.X /= whiteY; 1679 encoding->green.X /= whiteY;
1680 encoding->green.Y /= whiteY; 1680 encoding->green.Y /= whiteY;
1681 encoding->green.Z /= whiteY; 1681 encoding->green.Z /= whiteY;
1682 encoding->blue.X /= whiteY; 1682 encoding->blue.X /= whiteY;
1683 encoding->blue.Y /= whiteY; 1683 encoding->blue.Y /= whiteY;
1684 encoding->blue.Z /= whiteY; 1684 encoding->blue.Z /= whiteY;
1685 } 1685 }
1686} 1686}
1687 1687
1688static size_t 1688static size_t
1689safecat_color_encoding(char *buffer, size_t bufsize, size_t pos, 1689safecat_color_encoding(char *buffer, size_t bufsize, size_t pos,
1690 PNG_CONST color_encoding *e, double encoding_gamma) 1690 PNG_CONST color_encoding *e, double encoding_gamma)
1691{ 1691{
1692 if (e != 0) 1692 if (e != 0)
1693 { 1693 {
1694 if (encoding_gamma != 0) 1694 if (encoding_gamma != 0)
1695 pos = safecat(buffer, bufsize, pos, "("); 1695 pos = safecat(buffer, bufsize, pos, "(");
1696 pos = safecat(buffer, bufsize, pos, "R("); 1696 pos = safecat(buffer, bufsize, pos, "R(");
1697 pos = safecatd(buffer, bufsize, pos, e->red.X, 4); 1697 pos = safecatd(buffer, bufsize, pos, e->red.X, 4);
1698 pos = safecat(buffer, bufsize, pos, ","); 1698 pos = safecat(buffer, bufsize, pos, ",");
1699 pos = safecatd(buffer, bufsize, pos, e->red.Y, 4); 1699 pos = safecatd(buffer, bufsize, pos, e->red.Y, 4);
1700 pos = safecat(buffer, bufsize, pos, ","); 1700 pos = safecat(buffer, bufsize, pos, ",");
1701 pos = safecatd(buffer, bufsize, pos, e->red.Z, 4); 1701 pos = safecatd(buffer, bufsize, pos, e->red.Z, 4);
1702 pos = safecat(buffer, bufsize, pos, "),G("); 1702 pos = safecat(buffer, bufsize, pos, "),G(");
1703 pos = safecatd(buffer, bufsize, pos, e->green.X, 4); 1703 pos = safecatd(buffer, bufsize, pos, e->green.X, 4);
1704 pos = safecat(buffer, bufsize, pos, ","); 1704 pos = safecat(buffer, bufsize, pos, ",");
1705 pos = safecatd(buffer, bufsize, pos, e->green.Y, 4); 1705 pos = safecatd(buffer, bufsize, pos, e->green.Y, 4);
1706 pos = safecat(buffer, bufsize, pos, ","); 1706 pos = safecat(buffer, bufsize, pos, ",");
1707 pos = safecatd(buffer, bufsize, pos, e->green.Z, 4); 1707 pos = safecatd(buffer, bufsize, pos, e->green.Z, 4);
1708 pos = safecat(buffer, bufsize, pos, "),B("); 1708 pos = safecat(buffer, bufsize, pos, "),B(");
1709 pos = safecatd(buffer, bufsize, pos, e->blue.X, 4); 1709 pos = safecatd(buffer, bufsize, pos, e->blue.X, 4);
1710 pos = safecat(buffer, bufsize, pos, ","); 1710 pos = safecat(buffer, bufsize, pos, ",");
1711 pos = safecatd(buffer, bufsize, pos, e->blue.Y, 4); 1711 pos = safecatd(buffer, bufsize, pos, e->blue.Y, 4);
1712 pos = safecat(buffer, bufsize, pos, ","); 1712 pos = safecat(buffer, bufsize, pos, ",");
1713 pos = safecatd(buffer, bufsize, pos, e->blue.Z, 4); 1713 pos = safecatd(buffer, bufsize, pos, e->blue.Z, 4);
1714 pos = safecat(buffer, bufsize, pos, ")"); 1714 pos = safecat(buffer, bufsize, pos, ")");
1715 if (encoding_gamma != 0) 1715 if (encoding_gamma != 0)
1716 pos = safecat(buffer, bufsize, pos, ")"); 1716 pos = safecat(buffer, bufsize, pos, ")");
1717 } 1717 }
1718 1718
1719 if (encoding_gamma != 0) 1719 if (encoding_gamma != 0)
1720 { 1720 {
1721 pos = safecat(buffer, bufsize, pos, "^"); 1721 pos = safecat(buffer, bufsize, pos, "^");
1722 pos = safecatd(buffer, bufsize, pos, encoding_gamma, 5); 1722 pos = safecatd(buffer, bufsize, pos, encoding_gamma, 5);
1723 } 1723 }
1724 1724
1725 return pos; 1725 return pos;
1726} 1726}
1727 1727
1728typedef struct png_modifier 1728typedef struct png_modifier
1729{ 1729{
1730 png_store this; /* I am a png_store */ 1730 png_store this; /* I am a png_store */
1731 struct png_modification *modifications; /* Changes to make */ 1731 struct png_modification *modifications; /* Changes to make */
1732 1732
1733 modifier_state state; /* My state */ 1733 modifier_state state; /* My state */
1734 1734
1735 /* Information from IHDR: */ 1735 /* Information from IHDR: */
1736 png_byte bit_depth; /* From IHDR */ 1736 png_byte bit_depth; /* From IHDR */
1737 png_byte colour_type; /* From IHDR */ 1737 png_byte colour_type; /* From IHDR */
1738 1738
1739 /* While handling PLTE, IDAT and IEND these chunks may be pended to allow 1739 /* While handling PLTE, IDAT and IEND these chunks may be pended to allow
1740 * other chunks to be inserted. 1740 * other chunks to be inserted.
1741 */ 1741 */
1742 png_uint_32 pending_len; 1742 png_uint_32 pending_len;
1743 png_uint_32 pending_chunk; 1743 png_uint_32 pending_chunk;
1744 1744
1745 /* Test values */ 1745 /* Test values */
1746 double *gammas; 1746 double *gammas;
1747 unsigned int ngammas; 1747 unsigned int ngammas;
1748 unsigned int ngamma_tests; /* Number of gamma tests to run*/ 1748 unsigned int ngamma_tests; /* Number of gamma tests to run*/
1749 double current_gamma; /* 0 if not set */ 1749 double current_gamma; /* 0 if not set */
1750 PNG_CONST color_encoding *encodings; 1750 PNG_CONST color_encoding *encodings;
1751 unsigned int nencodings; 1751 unsigned int nencodings;
1752 PNG_CONST color_encoding *current_encoding; /* If an encoding has been set */ 1752 PNG_CONST color_encoding *current_encoding; /* If an encoding has been set */
1753 unsigned int encoding_counter; /* For iteration */ 1753 unsigned int encoding_counter; /* For iteration */
1754 int encoding_ignored; /* Something overwrote it */ 1754 int encoding_ignored; /* Something overwrote it */
1755 1755
1756 /* Control variables used to iterate through possible encodings, the 1756 /* Control variables used to iterate through possible encodings, the
1757 * following must be set to 0 and tested by the function that uses the 1757 * following must be set to 0 and tested by the function that uses the
1758 * png_modifier because the modifier only sets it to 1 (true.) 1758 * png_modifier because the modifier only sets it to 1 (true.)
1759 */ 1759 */
1760 unsigned int repeat :1; /* Repeat this transform test. */ 1760 unsigned int repeat :1; /* Repeat this transform test. */
1761 unsigned int test_uses_encoding :1; 1761 unsigned int test_uses_encoding :1;
1762 1762
1763 /* Lowest sbit to test (libpng fails for sbit < 8) */ 1763 /* Lowest sbit to test (libpng fails for sbit < 8) */
1764 png_byte sbitlow; 1764 png_byte sbitlow;
1765 1765
1766 /* Error control - these are the limits on errors accepted by the gamma tests 1766 /* Error control - these are the limits on errors accepted by the gamma tests
1767 * below. 1767 * below.
1768 */ 1768 */
1769 double maxout8; /* Maximum output value error */ 1769 double maxout8; /* Maximum output value error */
1770 double maxabs8; /* Absolute sample error 0..1 */ 1770 double maxabs8; /* Absolute sample error 0..1 */
1771 double maxcalc8; /* Absolute sample error 0..1 */ 1771 double maxcalc8; /* Absolute sample error 0..1 */
1772 double maxpc8; /* Percentage sample error 0..100% */ 1772 double maxpc8; /* Percentage sample error 0..100% */
1773 double maxout16; /* Maximum output value error */ 1773 double maxout16; /* Maximum output value error */
1774 double maxabs16; /* Absolute sample error 0..1 */ 1774 double maxabs16; /* Absolute sample error 0..1 */
1775 double maxcalc16;/* Absolute sample error 0..1 */ 1775 double maxcalc16;/* Absolute sample error 0..1 */
1776 double maxpc16; /* Percentage sample error 0..100% */ 1776 double maxpc16; /* Percentage sample error 0..100% */
1777 1777
1778 /* This is set by transforms that need to allow a higher limit, it is an 1778 /* This is set by transforms that need to allow a higher limit, it is an
1779 * internal check on pngvalid to ensure that the calculated error limits are 1779 * internal check on pngvalid to ensure that the calculated error limits are
1780 * not ridiculous; without this it is too easy to make a mistake in pngvalid 1780 * not ridiculous; without this it is too easy to make a mistake in pngvalid
1781 * that allows any value through. 1781 * that allows any value through.
1782 */ 1782 */
1783 double limit; /* limit on error values, normally 4E-3 */ 1783 double limit; /* limit on error values, normally 4E-3 */
1784 1784
1785 /* Log limits - values above this are logged, but not necessarily 1785 /* Log limits - values above this are logged, but not necessarily
1786 * warned. 1786 * warned.
1787 */ 1787 */
1788 double log8; /* Absolute error in 8 bits to log */ 1788 double log8; /* Absolute error in 8 bits to log */
1789 double log16; /* Absolute error in 16 bits to log */ 1789 double log16; /* Absolute error in 16 bits to log */
1790 1790
1791 /* Logged 8 and 16 bit errors ('output' values): */ 1791 /* Logged 8 and 16 bit errors ('output' values): */
1792 double error_gray_2; 1792 double error_gray_2;
1793 double error_gray_4; 1793 double error_gray_4;
1794 double error_gray_8; 1794 double error_gray_8;
1795 double error_gray_16; 1795 double error_gray_16;
1796 double error_color_8; 1796 double error_color_8;
1797 double error_color_16; 1797 double error_color_16;
1798 double error_indexed; 1798 double error_indexed;
1799 1799
1800 /* Flags: */ 1800 /* Flags: */
1801 /* Whether to call png_read_update_info, not png_read_start_image, and how 1801 /* Whether to call png_read_update_info, not png_read_start_image, and how
1802 * many times to call it. 1802 * many times to call it.
1803 */ 1803 */
1804 int use_update_info; 1804 int use_update_info;
1805 1805
1806 /* Whether or not to interlace. */ 1806 /* Whether or not to interlace. */
1807 int interlace_type :9; /* int, but must store '1' */ 1807 int interlace_type :9; /* int, but must store '1' */
1808 1808
1809 /* Run the standard tests? */ 1809 /* Run the standard tests? */
1810 unsigned int test_standard :1; 1810 unsigned int test_standard :1;
1811 1811
1812 /* Run the odd-sized image and interlace read/write tests? */ 1812 /* Run the odd-sized image and interlace read/write tests? */
1813 unsigned int test_size :1; 1813 unsigned int test_size :1;
1814 1814
1815 /* Run tests on reading with a combiniation of transforms, */ 1815 /* Run tests on reading with a combiniation of transforms, */
1816 unsigned int test_transform :1; 1816 unsigned int test_transform :1;
1817 1817
1818 /* When to use the use_input_precision option: */ 1818 /* When to use the use_input_precision option: */
1819 unsigned int use_input_precision :1; 1819 unsigned int use_input_precision :1;
1820 unsigned int use_input_precision_sbit :1; 1820 unsigned int use_input_precision_sbit :1;
1821 unsigned int use_input_precision_16to8 :1; 1821 unsigned int use_input_precision_16to8 :1;
1822 1822
1823 /* If set assume that the calculation bit depth is set by the input 1823 /* If set assume that the calculation bit depth is set by the input
1824 * precision, not the output precision. 1824 * precision, not the output precision.
1825 */ 1825 */
1826 unsigned int calculations_use_input_precision :1; 1826 unsigned int calculations_use_input_precision :1;
1827 1827
1828 /* If set assume that the calculations are done in 16 bits even if both input 1828 /* If set assume that the calculations are done in 16 bits even if both input
1829 * and output are 8 bit or less. 1829 * and output are 8 bit or less.
1830 */ 1830 */
1831 unsigned int assume_16_bit_calculations :1; 1831 unsigned int assume_16_bit_calculations :1;
1832 1832
1833 /* Which gamma tests to run: */ 1833 /* Which gamma tests to run: */
1834 unsigned int test_gamma_threshold :1; 1834 unsigned int test_gamma_threshold :1;
1835 unsigned int test_gamma_transform :1; /* main tests */ 1835 unsigned int test_gamma_transform :1; /* main tests */
1836 unsigned int test_gamma_sbit :1; 1836 unsigned int test_gamma_sbit :1;
1837 unsigned int test_gamma_scale16 :1; 1837 unsigned int test_gamma_scale16 :1;
1838 unsigned int test_gamma_background :1; 1838 unsigned int test_gamma_background :1;
1839 unsigned int test_gamma_alpha_mode :1; 1839 unsigned int test_gamma_alpha_mode :1;
1840 unsigned int test_gamma_expand16 :1; 1840 unsigned int test_gamma_expand16 :1;
1841 unsigned int test_exhaustive :1; 1841 unsigned int test_exhaustive :1;
1842 1842
1843 unsigned int log :1; /* Log max error */ 1843 unsigned int log :1; /* Log max error */
1844 1844
1845 /* Buffer information, the buffer size limits the size of the chunks that can 1845 /* Buffer information, the buffer size limits the size of the chunks that can
1846 * be modified - they must fit (including header and CRC) into the buffer! 1846 * be modified - they must fit (including header and CRC) into the buffer!
1847 */ 1847 */
1848 size_t flush; /* Count of bytes to flush */ 1848 size_t flush; /* Count of bytes to flush */
1849 size_t buffer_count; /* Bytes in buffer */ 1849 size_t buffer_count; /* Bytes in buffer */
1850 size_t buffer_position; /* Position in buffer */ 1850 size_t buffer_position; /* Position in buffer */
1851 png_byte buffer[1024]; 1851 png_byte buffer[1024];
1852} png_modifier; 1852} png_modifier;
1853 1853
1854/* This returns true if the test should be stopped now because it has already 1854/* This returns true if the test should be stopped now because it has already
1855 * failed and it is running silently. 1855 * failed and it is running silently.
1856 */ 1856 */
1857static int fail(png_modifier *pm) 1857static int fail(png_modifier *pm)
1858{ 1858{
1859 return !pm->log && !pm->this.verbose && (pm->this.nerrors > 0 || 1859 return !pm->log && !pm->this.verbose && (pm->this.nerrors > 0 ||
1860 (pm->this.treat_warnings_as_errors && pm->this.nwarnings > 0)); 1860 (pm->this.treat_warnings_as_errors && pm->this.nwarnings > 0));
1861} 1861}
1862 1862
1863static void 1863static void
1864modifier_init(png_modifier *pm) 1864modifier_init(png_modifier *pm)
1865{ 1865{
1866 memset(pm, 0, sizeof *pm); 1866 memset(pm, 0, sizeof *pm);
1867 store_init(&pm->this); 1867 store_init(&pm->this);
1868 pm->modifications = NULL; 1868 pm->modifications = NULL;
1869 pm->state = modifier_start; 1869 pm->state = modifier_start;
1870 pm->sbitlow = 1U; 1870 pm->sbitlow = 1U;
1871 pm->ngammas = 0; 1871 pm->ngammas = 0;
1872 pm->ngamma_tests = 0; 1872 pm->ngamma_tests = 0;
1873 pm->gammas = 0; 1873 pm->gammas = 0;
1874 pm->current_gamma = 0; 1874 pm->current_gamma = 0;
1875 pm->encodings = 0; 1875 pm->encodings = 0;
1876 pm->nencodings = 0; 1876 pm->nencodings = 0;
1877 pm->current_encoding = 0; 1877 pm->current_encoding = 0;
1878 pm->encoding_counter = 0; 1878 pm->encoding_counter = 0;
1879 pm->encoding_ignored = 0; 1879 pm->encoding_ignored = 0;
1880 pm->repeat = 0; 1880 pm->repeat = 0;
1881 pm->test_uses_encoding = 0; 1881 pm->test_uses_encoding = 0;
1882 pm->maxout8 = pm->maxpc8 = pm->maxabs8 = pm->maxcalc8 = 0; 1882 pm->maxout8 = pm->maxpc8 = pm->maxabs8 = pm->maxcalc8 = 0;
1883 pm->maxout16 = pm->maxpc16 = pm->maxabs16 = pm->maxcalc16 = 0; 1883 pm->maxout16 = pm->maxpc16 = pm->maxabs16 = pm->maxcalc16 = 0;
1884 pm->limit = 4E-3; 1884 pm->limit = 4E-3;
1885 pm->log8 = pm->log16 = 0; /* Means 'off' */ 1885 pm->log8 = pm->log16 = 0; /* Means 'off' */
1886 pm->error_gray_2 = pm->error_gray_4 = pm->error_gray_8 = 0; 1886 pm->error_gray_2 = pm->error_gray_4 = pm->error_gray_8 = 0;
1887 pm->error_gray_16 = pm->error_color_8 = pm->error_color_16 = 0; 1887 pm->error_gray_16 = pm->error_color_8 = pm->error_color_16 = 0;
1888 pm->error_indexed = 0; 1888 pm->error_indexed = 0;
1889 pm->use_update_info = 0; 1889 pm->use_update_info = 0;
1890 pm->interlace_type = PNG_INTERLACE_NONE; 1890 pm->interlace_type = PNG_INTERLACE_NONE;
1891 pm->test_standard = 0; 1891 pm->test_standard = 0;
1892 pm->test_size = 0; 1892 pm->test_size = 0;
1893 pm->test_transform = 0; 1893 pm->test_transform = 0;
1894 pm->use_input_precision = 0; 1894 pm->use_input_precision = 0;
1895 pm->use_input_precision_sbit = 0; 1895 pm->use_input_precision_sbit = 0;
1896 pm->use_input_precision_16to8 = 0; 1896 pm->use_input_precision_16to8 = 0;
1897 pm->calculations_use_input_precision = 0; 1897 pm->calculations_use_input_precision = 0;
1898 pm->test_gamma_threshold = 0; 1898 pm->test_gamma_threshold = 0;
1899 pm->test_gamma_transform = 0; 1899 pm->test_gamma_transform = 0;
1900 pm->test_gamma_sbit = 0; 1900 pm->test_gamma_sbit = 0;
1901 pm->test_gamma_scale16 = 0; 1901 pm->test_gamma_scale16 = 0;
1902 pm->test_gamma_background = 0; 1902 pm->test_gamma_background = 0;
1903 pm->test_gamma_alpha_mode = 0; 1903 pm->test_gamma_alpha_mode = 0;
1904 pm->test_gamma_expand16 = 0; 1904 pm->test_gamma_expand16 = 0;
1905 pm->test_exhaustive = 0; 1905 pm->test_exhaustive = 0;
1906 pm->log = 0; 1906 pm->log = 0;
1907 1907
1908 /* Rely on the memset for all the other fields - there are no pointers */ 1908 /* Rely on the memset for all the other fields - there are no pointers */
1909} 1909}
1910 1910
1911#ifdef PNG_READ_TRANSFORMS_SUPPORTED 1911#ifdef PNG_READ_TRANSFORMS_SUPPORTED
1912/* If pm->calculations_use_input_precision is set then operations will happen 1912/* If pm->calculations_use_input_precision is set then operations will happen
1913 * with only 8 bit precision unless both the input and output bit depth are 16. 1913 * with only 8 bit precision unless both the input and output bit depth are 16.
1914 * 1914 *
1915 * If pm->assume_16_bit_calculations is set then even 8 bit calculations use 16 1915 * If pm->assume_16_bit_calculations is set then even 8 bit calculations use 16
1916 * bit precision. This only affects those of the following limits that pertain 1916 * bit precision. This only affects those of the following limits that pertain
1917 * to a calculation - not a digitization operation - unless the following API is 1917 * to a calculation - not a digitization operation - unless the following API is
1918 * called directly. 1918 * called directly.
1919 */ 1919 */
1920static double digitize(PNG_CONST png_modifier *pm, double value, 1920static double digitize(PNG_CONST png_modifier *pm, double value,
1921 int sample_depth, int do_round) 1921 int sample_depth, int do_round)
1922{ 1922{
1923 /* 'value' is in the range 0 to 1, the result is the same value rounded to a 1923 /* 'value' is in the range 0 to 1, the result is the same value rounded to a
1924 * multiple of the digitization factor - 8 or 16 bits depending on both the 1924 * multiple of the digitization factor - 8 or 16 bits depending on both the
1925 * sample depth and the 'assume' setting. Digitization is normally by 1925 * sample depth and the 'assume' setting. Digitization is normally by
1926 * rounding and 'do_round' should be 1, if it is 0 the digitized value will 1926 * rounding and 'do_round' should be 1, if it is 0 the digitized value will
1927 * be truncated. 1927 * be truncated.
1928 */ 1928 */
1929 PNG_CONST unsigned int digitization_factor = 1929 PNG_CONST unsigned int digitization_factor =
1930 (pm->assume_16_bit_calculations || sample_depth == 16) ? 65535 : 255; 1930 (pm->assume_16_bit_calculations || sample_depth == 16) ? 65535 : 255;
1931 1931
1932 /* Limiting the range is done as a convenience to the caller - it's easier to 1932 /* Limiting the range is done as a convenience to the caller - it's easier to
1933 * do it once here than every time at the call site. 1933 * do it once here than every time at the call site.
1934 */ 1934 */
1935 if (value <= 0) 1935 if (value <= 0)
1936 value = 0; 1936 value = 0;
1937 else if (value >= 1) 1937 else if (value >= 1)
1938 value = 1; 1938 value = 1;
1939 1939
1940 value *= digitization_factor; 1940 value *= digitization_factor;
1941 if (do_round) value += .5; 1941 if (do_round) value += .5;
1942 return floor(value)/digitization_factor; 1942 return floor(value)/digitization_factor;
1943} 1943}
1944 1944
1945static double abserr(PNG_CONST png_modifier *pm, int in_depth, int out_depth) 1945static double abserr(PNG_CONST png_modifier *pm, int in_depth, int out_depth)
1946{ 1946{
1947 /* Absolute error permitted in linear values - affected by the bit depth of 1947 /* Absolute error permitted in linear values - affected by the bit depth of
1948 * the calculations. 1948 * the calculations.
1949 */ 1949 */
1950 if (pm->assume_16_bit_calculations || (out_depth == 16 && (in_depth == 16 || 1950 if (pm->assume_16_bit_calculations || (out_depth == 16 && (in_depth == 16 ||
1951 !pm->calculations_use_input_precision))) 1951 !pm->calculations_use_input_precision)))
1952 return pm->maxabs16; 1952 return pm->maxabs16;
1953 else 1953 else
1954 return pm->maxabs8; 1954 return pm->maxabs8;
1955} 1955}
1956 1956
1957static double calcerr(PNG_CONST png_modifier *pm, int in_depth, int out_depth) 1957static double calcerr(PNG_CONST png_modifier *pm, int in_depth, int out_depth)
1958{ 1958{
1959 /* Error in the linear composition arithmetic - only relevant when 1959 /* Error in the linear composition arithmetic - only relevant when
1960 * composition actually happens (0 < alpha < 1). 1960 * composition actually happens (0 < alpha < 1).
1961 */ 1961 */
1962 if (pm->assume_16_bit_calculations || (out_depth == 16 && (in_depth == 16 || 1962 if (pm->assume_16_bit_calculations || (out_depth == 16 && (in_depth == 16 ||
1963 !pm->calculations_use_input_precision))) 1963 !pm->calculations_use_input_precision)))
1964 return pm->maxcalc16; 1964 return pm->maxcalc16;
1965 else 1965 else
1966 return pm->maxcalc8; 1966 return pm->maxcalc8;
1967} 1967}
1968 1968
1969static double pcerr(PNG_CONST png_modifier *pm, int in_depth, int out_depth) 1969static double pcerr(PNG_CONST png_modifier *pm, int in_depth, int out_depth)
1970{ 1970{
1971 /* Percentage error permitted in the linear values. Note that the specified 1971 /* Percentage error permitted in the linear values. Note that the specified
1972 * value is a percentage but this routine returns a simple number. 1972 * value is a percentage but this routine returns a simple number.
1973 */ 1973 */
1974 if (pm->assume_16_bit_calculations || (out_depth == 16 && (in_depth == 16 || 1974 if (pm->assume_16_bit_calculations || (out_depth == 16 && (in_depth == 16 ||
1975 !pm->calculations_use_input_precision))) 1975 !pm->calculations_use_input_precision)))
1976 return pm->maxpc16 * .01; 1976 return pm->maxpc16 * .01;
1977 else 1977 else
1978 return pm->maxpc8 * .01; 1978 return pm->maxpc8 * .01;
1979} 1979}
1980 1980
1981/* Output error - the error in the encoded value. This is determined by the 1981/* Output error - the error in the encoded value. This is determined by the
1982 * digitization of the output so can be +/-0.5 in the actual output value. In 1982 * digitization of the output so can be +/-0.5 in the actual output value. In
1983 * the expand_16 case with the current code in libpng the expand happens after 1983 * the expand_16 case with the current code in libpng the expand happens after
1984 * all the calculations are done in 8 bit arithmetic, so even though the output 1984 * all the calculations are done in 8 bit arithmetic, so even though the output
1985 * depth is 16 the output error is determined by the 8 bit calculation. 1985 * depth is 16 the output error is determined by the 8 bit calculation.
1986 * 1986 *
1987 * This limit is not determined by the bit depth of internal calculations. 1987 * This limit is not determined by the bit depth of internal calculations.
1988 * 1988 *
1989 * The specified parameter does *not* include the base .5 digitization error but 1989 * The specified parameter does *not* include the base .5 digitization error but
1990 * it is added here. 1990 * it is added here.
1991 */ 1991 */
1992static double outerr(PNG_CONST png_modifier *pm, int in_depth, int out_depth) 1992static double outerr(PNG_CONST png_modifier *pm, int in_depth, int out_depth)
1993{ 1993{
1994 /* There is a serious error in the 2 and 4 bit grayscale transform because 1994 /* There is a serious error in the 2 and 4 bit grayscale transform because
1995 * the gamma table value (8 bits) is simply shifted, not rounded, so the 1995 * the gamma table value (8 bits) is simply shifted, not rounded, so the
1996 * error in 4 bit grayscale gamma is up to the value below. This is a hack 1996 * error in 4 bit grayscale gamma is up to the value below. This is a hack
1997 * to allow pngvalid to succeed: 1997 * to allow pngvalid to succeed:
1998 * 1998 *
1999 * TODO: fix this in libpng 1999 * TODO: fix this in libpng
2000 */ 2000 */
2001 if (out_depth == 2) 2001 if (out_depth == 2)
2002 return .73182-.5; 2002 return .73182-.5;
2003 2003
2004 if (out_depth == 4) 2004 if (out_depth == 4)
2005 return .90644-.5; 2005 return .90644-.5;
2006 2006
2007 if (out_depth == 16 && (in_depth == 16 || 2007 if (out_depth == 16 && (in_depth == 16 ||
2008 !pm->calculations_use_input_precision)) 2008 !pm->calculations_use_input_precision))
2009 return pm->maxout16; 2009 return pm->maxout16;
2010 2010
2011 /* This is the case where the value was calculated at 8-bit precision then 2011 /* This is the case where the value was calculated at 8-bit precision then
2012 * scaled to 16 bits. 2012 * scaled to 16 bits.
2013 */ 2013 */
2014 else if (out_depth == 16) 2014 else if (out_depth == 16)
2015 return pm->maxout8 * 257; 2015 return pm->maxout8 * 257;
2016 2016
2017 else 2017 else
2018 return pm->maxout8; 2018 return pm->maxout8;
2019} 2019}
2020 2020
2021/* This does the same thing as the above however it returns the value to log, 2021/* This does the same thing as the above however it returns the value to log,
2022 * rather than raising a warning. This is useful for debugging to track down 2022 * rather than raising a warning. This is useful for debugging to track down
2023 * exactly what set of parameters cause high error values. 2023 * exactly what set of parameters cause high error values.
2024 */ 2024 */
2025static double outlog(PNG_CONST png_modifier *pm, int in_depth, int out_depth) 2025static double outlog(PNG_CONST png_modifier *pm, int in_depth, int out_depth)
2026{ 2026{
2027 /* The command line parameters are either 8 bit (0..255) or 16 bit (0..65535) 2027 /* The command line parameters are either 8 bit (0..255) or 16 bit (0..65535)
2028 * and so must be adjusted for low bit depth grayscale: 2028 * and so must be adjusted for low bit depth grayscale:
2029 */ 2029 */
2030 if (out_depth <= 8) 2030 if (out_depth <= 8)
2031 { 2031 {
2032 if (pm->log8 == 0) /* switched off */ 2032 if (pm->log8 == 0) /* switched off */
2033 return 256; 2033 return 256;
2034 2034
2035 if (out_depth < 8) 2035 if (out_depth < 8)
2036 return pm->log8 / 255 * ((1<<out_depth)-1); 2036 return pm->log8 / 255 * ((1<<out_depth)-1);
2037 2037
2038 return pm->log8; 2038 return pm->log8;
2039 } 2039 }
2040 2040
2041 if (out_depth == 16 && (in_depth == 16 || 2041 if (out_depth == 16 && (in_depth == 16 ||
2042 !pm->calculations_use_input_precision)) 2042 !pm->calculations_use_input_precision))
2043 { 2043 {
2044 if (pm->log16 == 0) 2044 if (pm->log16 == 0)
2045 return 65536; 2045 return 65536;
2046 2046
2047 return pm->log16; 2047 return pm->log16;
2048 } 2048 }
2049 2049
2050 /* This is the case where the value was calculated at 8-bit precision then 2050 /* This is the case where the value was calculated at 8-bit precision then
2051 * scaled to 16 bits. 2051 * scaled to 16 bits.
2052 */ 2052 */
2053 if (pm->log8 == 0) 2053 if (pm->log8 == 0)
2054 return 65536; 2054 return 65536;
2055 2055
2056 return pm->log8 * 257; 2056 return pm->log8 * 257;
2057} 2057}
2058 2058
2059/* This complements the above by providing the appropriate quantization for the 2059/* This complements the above by providing the appropriate quantization for the
2060 * final value. Normally this would just be quantization to an integral value, 2060 * final value. Normally this would just be quantization to an integral value,
2061 * but in the 8 bit calculation case it's actually quantization to a multiple of 2061 * but in the 8 bit calculation case it's actually quantization to a multiple of
2062 * 257! 2062 * 257!
2063 */ 2063 */
2064static int output_quantization_factor(PNG_CONST png_modifier *pm, int in_depth, 2064static int output_quantization_factor(PNG_CONST png_modifier *pm, int in_depth,
2065 int out_depth) 2065 int out_depth)
2066{ 2066{
2067 if (out_depth == 16 && in_depth != 16 2067 if (out_depth == 16 && in_depth != 16
2068 && pm->calculations_use_input_precision) 2068 && pm->calculations_use_input_precision)
2069 return 257; 2069 return 257;
2070 else 2070 else
2071 return 1; 2071 return 1;
2072} 2072}
2073 2073
2074/* One modification structure must be provided for each chunk to be modified (in 2074/* One modification structure must be provided for each chunk to be modified (in
2075 * fact more than one can be provided if multiple separate changes are desired 2075 * fact more than one can be provided if multiple separate changes are desired
2076 * for a single chunk.) Modifications include adding a new chunk when a 2076 * for a single chunk.) Modifications include adding a new chunk when a
2077 * suitable chunk does not exist. 2077 * suitable chunk does not exist.
2078 * 2078 *
2079 * The caller of modify_fn will reset the CRC of the chunk and record 'modified' 2079 * The caller of modify_fn will reset the CRC of the chunk and record 'modified'
2080 * or 'added' as appropriate if the modify_fn returns 1 (true). If the 2080 * or 'added' as appropriate if the modify_fn returns 1 (true). If the
2081 * modify_fn is NULL the chunk is simply removed. 2081 * modify_fn is NULL the chunk is simply removed.
2082 */ 2082 */
2083typedef struct png_modification 2083typedef struct png_modification
2084{ 2084{
2085 struct png_modification *next; 2085 struct png_modification *next;
2086 png_uint_32 chunk; 2086 png_uint_32 chunk;
2087 2087
2088 /* If the following is NULL all matching chunks will be removed: */ 2088 /* If the following is NULL all matching chunks will be removed: */
2089 int (*modify_fn)(struct png_modifier *pm, 2089 int (*modify_fn)(struct png_modifier *pm,
2090 struct png_modification *me, int add); 2090 struct png_modification *me, int add);
2091 2091
2092 /* If the following is set to PLTE, IDAT or IEND and the chunk has not been 2092 /* If the following is set to PLTE, IDAT or IEND and the chunk has not been
2093 * found and modified (and there is a modify_fn) the modify_fn will be called 2093 * found and modified (and there is a modify_fn) the modify_fn will be called
2094 * to add the chunk before the relevant chunk. 2094 * to add the chunk before the relevant chunk.
2095 */ 2095 */
2096 png_uint_32 add; 2096 png_uint_32 add;
2097 unsigned int modified :1; /* Chunk was modified */ 2097 unsigned int modified :1; /* Chunk was modified */
2098 unsigned int added :1; /* Chunk was added */ 2098 unsigned int added :1; /* Chunk was added */
2099 unsigned int removed :1; /* Chunk was removed */ 2099 unsigned int removed :1; /* Chunk was removed */
2100} png_modification; 2100} png_modification;
2101 2101
2102static void 2102static void
2103modification_reset(png_modification *pmm) 2103modification_reset(png_modification *pmm)
2104{ 2104{
2105 if (pmm != NULL) 2105 if (pmm != NULL)
2106 { 2106 {
2107 pmm->modified = 0; 2107 pmm->modified = 0;
2108 pmm->added = 0; 2108 pmm->added = 0;
2109 pmm->removed = 0; 2109 pmm->removed = 0;
2110 modification_reset(pmm->next); 2110 modification_reset(pmm->next);
2111 } 2111 }
2112} 2112}
2113 2113
2114static void 2114static void
2115modification_init(png_modification *pmm) 2115modification_init(png_modification *pmm)
2116{ 2116{
2117 memset(pmm, 0, sizeof *pmm); 2117 memset(pmm, 0, sizeof *pmm);
2118 pmm->next = NULL; 2118 pmm->next = NULL;
2119 pmm->chunk = 0; 2119 pmm->chunk = 0;
2120 pmm->modify_fn = NULL; 2120 pmm->modify_fn = NULL;
2121 pmm->add = 0; 2121 pmm->add = 0;
2122 modification_reset(pmm); 2122 modification_reset(pmm);
2123} 2123}
2124 2124
2125static void 2125static void
2126modifier_current_encoding(PNG_CONST png_modifier *pm, color_encoding *ce) 2126modifier_current_encoding(PNG_CONST png_modifier *pm, color_encoding *ce)
2127{ 2127{
2128 if (pm->current_encoding != 0) 2128 if (pm->current_encoding != 0)
2129 *ce = *pm->current_encoding; 2129 *ce = *pm->current_encoding;
2130 2130
2131 else 2131 else
2132 memset(ce, 0, sizeof *ce); 2132 memset(ce, 0, sizeof *ce);
2133 2133
2134 ce->gamma = pm->current_gamma; 2134 ce->gamma = pm->current_gamma;
2135} 2135}
2136 2136
2137static size_t 2137static size_t
2138safecat_current_encoding(char *buffer, size_t bufsize, size_t pos, 2138safecat_current_encoding(char *buffer, size_t bufsize, size_t pos,
2139 PNG_CONST png_modifier *pm) 2139 PNG_CONST png_modifier *pm)
2140{ 2140{
2141 pos = safecat_color_encoding(buffer, bufsize, pos, pm->current_encoding, 2141 pos = safecat_color_encoding(buffer, bufsize, pos, pm->current_encoding,
2142 pm->current_gamma); 2142 pm->current_gamma);
2143 2143
2144 if (pm->encoding_ignored) 2144 if (pm->encoding_ignored)
2145 pos = safecat(buffer, bufsize, pos, "[overridden]"); 2145 pos = safecat(buffer, bufsize, pos, "[overridden]");
2146 2146
2147 return pos; 2147 return pos;
2148} 2148}
2149 2149
2150/* Iterate through the usefully testable color encodings. An encoding is one 2150/* Iterate through the usefully testable color encodings. An encoding is one
2151 * of: 2151 * of:
2152 * 2152 *
2153 * 1) Nothing (no color space, no gamma). 2153 * 1) Nothing (no color space, no gamma).
2154 * 2) Just a gamma value from the gamma array (including 1.0) 2154 * 2) Just a gamma value from the gamma array (including 1.0)
2155 * 3) A color space from the encodings array with the corresponding gamma. 2155 * 3) A color space from the encodings array with the corresponding gamma.
2156 * 4) The same, but with gamma 1.0 (only really useful with 16 bit calculations) 2156 * 4) The same, but with gamma 1.0 (only really useful with 16 bit calculations)
2157 * 2157 *
2158 * The iterator selects these in turn, the randomizer selects one at random, 2158 * The iterator selects these in turn, the randomizer selects one at random,
2159 * which is used depends on the setting of the 'test_exhaustive' flag. Notice 2159 * which is used depends on the setting of the 'test_exhaustive' flag. Notice
2160 * that this function changes the colour space encoding so it must only be 2160 * that this function changes the colour space encoding so it must only be
2161 * called on completion of the previous test. This is what 'modifier_reset' 2161 * called on completion of the previous test. This is what 'modifier_reset'
2162 * does, below. 2162 * does, below.
2163 * 2163 *
2164 * After the function has been called the 'repeat' flag will still be set; the 2164 * After the function has been called the 'repeat' flag will still be set; the
2165 * caller of modifier_reset must reset it at the start of each run of the test! 2165 * caller of modifier_reset must reset it at the start of each run of the test!
2166 */ 2166 */
2167static unsigned int 2167static unsigned int
2168modifier_total_encodings(PNG_CONST png_modifier *pm) 2168modifier_total_encodings(PNG_CONST png_modifier *pm)
2169{ 2169{
2170 return 1 + /* (1) nothing */ 2170 return 1 + /* (1) nothing */
2171 pm->ngammas + /* (2) gamma values to test */ 2171 pm->ngammas + /* (2) gamma values to test */
2172 pm->nencodings + /* (3) total number of encodings */ 2172 pm->nencodings + /* (3) total number of encodings */
2173 /* The following test only works after the first time through the 2173 /* The following test only works after the first time through the
2174 * png_modifier code because 'bit_depth' is set when the IHDR is read. 2174 * png_modifier code because 'bit_depth' is set when the IHDR is read.
2175 * modifier_reset, below, preserves the setting until after it has called 2175 * modifier_reset, below, preserves the setting until after it has called
2176 * the iterate function (also below.) 2176 * the iterate function (also below.)
2177 * 2177 *
2178 * For this reason do not rely on this function outside a call to 2178 * For this reason do not rely on this function outside a call to
2179 * modifier_reset. 2179 * modifier_reset.
2180 */ 2180 */
2181 ((pm->bit_depth == 16 || pm->assume_16_bit_calculations) ? 2181 ((pm->bit_depth == 16 || pm->assume_16_bit_calculations) ?
2182 pm->nencodings : 0); /* (4) encodings with gamma == 1.0 */ 2182 pm->nencodings : 0); /* (4) encodings with gamma == 1.0 */
2183} 2183}
2184 2184
2185static void 2185static void
2186modifier_encoding_iterate(png_modifier *pm) 2186modifier_encoding_iterate(png_modifier *pm)
2187{ 2187{
2188 if (!pm->repeat && /* Else something needs the current encoding again. */ 2188 if (!pm->repeat && /* Else something needs the current encoding again. */
2189 pm->test_uses_encoding) /* Some transform is encoding dependent */ 2189 pm->test_uses_encoding) /* Some transform is encoding dependent */
2190 { 2190 {
2191 if (pm->test_exhaustive) 2191 if (pm->test_exhaustive)
2192 { 2192 {
2193 if (++pm->encoding_counter >= modifier_total_encodings(pm)) 2193 if (++pm->encoding_counter >= modifier_total_encodings(pm))
2194 pm->encoding_counter = 0; /* This will stop the repeat */ 2194 pm->encoding_counter = 0; /* This will stop the repeat */
2195 } 2195 }
2196 2196
2197 else 2197 else
2198 { 2198 {
2199 /* Not exhaustive - choose an encoding at random; generate a number in 2199 /* Not exhaustive - choose an encoding at random; generate a number in
2200 * the range 1..(max-1), so the result is always non-zero: 2200 * the range 1..(max-1), so the result is always non-zero:
2201 */ 2201 */
2202 if (pm->encoding_counter == 0) 2202 if (pm->encoding_counter == 0)
2203 pm->encoding_counter = random_mod(modifier_total_encodings(pm)-1)+1; 2203 pm->encoding_counter = random_mod(modifier_total_encodings(pm)-1)+1;
2204 else 2204 else
2205 pm->encoding_counter = 0; 2205 pm->encoding_counter = 0;
2206 } 2206 }
2207 2207
2208 if (pm->encoding_counter > 0) 2208 if (pm->encoding_counter > 0)
2209 pm->repeat = 1; 2209 pm->repeat = 1;
2210 } 2210 }
2211 2211
2212 else if (!pm->repeat) 2212 else if (!pm->repeat)
2213 pm->encoding_counter = 0; 2213 pm->encoding_counter = 0;
2214} 2214}
2215 2215
2216static void 2216static void
2217modifier_reset(png_modifier *pm) 2217modifier_reset(png_modifier *pm)
2218{ 2218{
2219 store_read_reset(&pm->this); 2219 store_read_reset(&pm->this);
2220 pm->limit = 4E-3; 2220 pm->limit = 4E-3;
2221 pm->pending_len = pm->pending_chunk = 0; 2221 pm->pending_len = pm->pending_chunk = 0;
2222 pm->flush = pm->buffer_count = pm->buffer_position = 0; 2222 pm->flush = pm->buffer_count = pm->buffer_position = 0;
2223 pm->modifications = NULL; 2223 pm->modifications = NULL;
2224 pm->state = modifier_start; 2224 pm->state = modifier_start;
2225 modifier_encoding_iterate(pm); 2225 modifier_encoding_iterate(pm);
2226 /* The following must be set in the next run. In particular 2226 /* The following must be set in the next run. In particular
2227 * test_uses_encodings must be set in the _ini function of each transform 2227 * test_uses_encodings must be set in the _ini function of each transform
2228 * that looks at the encodings. (Not the 'add' function!) 2228 * that looks at the encodings. (Not the 'add' function!)
2229 */ 2229 */
2230 pm->test_uses_encoding = 0; 2230 pm->test_uses_encoding = 0;
2231 pm->current_gamma = 0; 2231 pm->current_gamma = 0;
2232 pm->current_encoding = 0; 2232 pm->current_encoding = 0;
2233 pm->encoding_ignored = 0; 2233 pm->encoding_ignored = 0;
2234 /* These only become value after IHDR is read: */ 2234 /* These only become value after IHDR is read: */
2235 pm->bit_depth = pm->colour_type = 0; 2235 pm->bit_depth = pm->colour_type = 0;
2236} 2236}
2237 2237
2238/* The following must be called before anything else to get the encoding set up 2238/* The following must be called before anything else to get the encoding set up
2239 * on the modifier. In particular it must be called before the transform init 2239 * on the modifier. In particular it must be called before the transform init
2240 * functions are called. 2240 * functions are called.
2241 */ 2241 */
2242static void 2242static void
2243modifier_set_encoding(png_modifier *pm) 2243modifier_set_encoding(png_modifier *pm)
2244{ 2244{
2245 /* Set the encoding to the one specified by the current encoding counter, 2245 /* Set the encoding to the one specified by the current encoding counter,
2246 * first clear out all the settings - this corresponds to an encoding_counter 2246 * first clear out all the settings - this corresponds to an encoding_counter
2247 * of 0. 2247 * of 0.
2248 */ 2248 */
2249 pm->current_gamma = 0; 2249 pm->current_gamma = 0;
2250 pm->current_encoding = 0; 2250 pm->current_encoding = 0;
2251 pm->encoding_ignored = 0; /* not ignored yet - happens in _ini functions. */ 2251 pm->encoding_ignored = 0; /* not ignored yet - happens in _ini functions. */
2252 2252
2253 /* Now, if required, set the gamma and encoding fields. */ 2253 /* Now, if required, set the gamma and encoding fields. */
2254 if (pm->encoding_counter > 0) 2254 if (pm->encoding_counter > 0)
2255 { 2255 {
2256 /* The gammas[] array is an array of screen gammas, not encoding gammas, 2256 /* The gammas[] array is an array of screen gammas, not encoding gammas,
2257 * so we need the inverse: 2257 * so we need the inverse:
2258 */ 2258 */
2259 if (pm->encoding_counter <= pm->ngammas) 2259 if (pm->encoding_counter <= pm->ngammas)
2260 pm->current_gamma = 1/pm->gammas[pm->encoding_counter-1]; 2260 pm->current_gamma = 1/pm->gammas[pm->encoding_counter-1];
2261 2261
2262 else 2262 else
2263 { 2263 {
2264 unsigned int i = pm->encoding_counter - pm->ngammas; 2264 unsigned int i = pm->encoding_counter - pm->ngammas;
2265 2265
2266 if (i >= pm->nencodings) 2266 if (i >= pm->nencodings)
2267 { 2267 {
2268 i %= pm->nencodings; 2268 i %= pm->nencodings;
2269 pm->current_gamma = 1; /* Linear, only in the 16 bit case */ 2269 pm->current_gamma = 1; /* Linear, only in the 16 bit case */
2270 } 2270 }
2271 2271
2272 else 2272 else
2273 pm->current_gamma = pm->encodings[i].gamma; 2273 pm->current_gamma = pm->encodings[i].gamma;
2274 2274
2275 pm->current_encoding = pm->encodings + i; 2275 pm->current_encoding = pm->encodings + i;
2276 } 2276 }
2277 } 2277 }
2278} 2278}
2279 2279
2280/* Enquiry functions to find out what is set. Notice that there is an implicit 2280/* Enquiry functions to find out what is set. Notice that there is an implicit
2281 * assumption below that the first encoding in the list is the one for sRGB. 2281 * assumption below that the first encoding in the list is the one for sRGB.
2282 */ 2282 */
2283static int 2283static int
2284modifier_color_encoding_is_sRGB(PNG_CONST png_modifier *pm) 2284modifier_color_encoding_is_sRGB(PNG_CONST png_modifier *pm)
2285{ 2285{
2286 return pm->current_encoding != 0 && pm->current_encoding == pm->encodings && 2286 return pm->current_encoding != 0 && pm->current_encoding == pm->encodings &&
2287 pm->current_encoding->gamma == pm->current_gamma; 2287 pm->current_encoding->gamma == pm->current_gamma;
2288} 2288}
2289 2289
2290static int 2290static int
2291modifier_color_encoding_is_set(PNG_CONST png_modifier *pm) 2291modifier_color_encoding_is_set(PNG_CONST png_modifier *pm)
2292{ 2292{
2293 return pm->current_gamma != 0; 2293 return pm->current_gamma != 0;
2294} 2294}
2295 2295
2296/* Convenience macros. */ 2296/* Convenience macros. */
2297#define CHUNK(a,b,c,d) (((a)<<24)+((b)<<16)+((c)<<8)+(d)) 2297#define CHUNK(a,b,c,d) (((a)<<24)+((b)<<16)+((c)<<8)+(d))
2298#define CHUNK_IHDR CHUNK(73,72,68,82) 2298#define CHUNK_IHDR CHUNK(73,72,68,82)
2299#define CHUNK_PLTE CHUNK(80,76,84,69) 2299#define CHUNK_PLTE CHUNK(80,76,84,69)
2300#define CHUNK_IDAT CHUNK(73,68,65,84) 2300#define CHUNK_IDAT CHUNK(73,68,65,84)
2301#define CHUNK_IEND CHUNK(73,69,78,68) 2301#define CHUNK_IEND CHUNK(73,69,78,68)
2302#define CHUNK_cHRM CHUNK(99,72,82,77) 2302#define CHUNK_cHRM CHUNK(99,72,82,77)
2303#define CHUNK_gAMA CHUNK(103,65,77,65) 2303#define CHUNK_gAMA CHUNK(103,65,77,65)
2304#define CHUNK_sBIT CHUNK(115,66,73,84) 2304#define CHUNK_sBIT CHUNK(115,66,73,84)
2305#define CHUNK_sRGB CHUNK(115,82,71,66) 2305#define CHUNK_sRGB CHUNK(115,82,71,66)
2306 2306
2307/* The guts of modification are performed during a read. */ 2307/* The guts of modification are performed during a read. */
2308static void 2308static void
2309modifier_crc(png_bytep buffer) 2309modifier_crc(png_bytep buffer)
2310{ 2310{
2311 /* Recalculate the chunk CRC - a complete chunk must be in 2311 /* Recalculate the chunk CRC - a complete chunk must be in
2312 * the buffer, at the start. 2312 * the buffer, at the start.
2313 */ 2313 */
2314 uInt datalen = png_get_uint_32(buffer); 2314 uInt datalen = png_get_uint_32(buffer);
2315 uLong crc = crc32(0, buffer+4, datalen+4); 2315 uLong crc = crc32(0, buffer+4, datalen+4);
2316 /* The cast to png_uint_32 is safe because a crc32 is always a 32 bit value. 2316 /* The cast to png_uint_32 is safe because a crc32 is always a 32 bit value.
2317 */ 2317 */
2318 png_save_uint_32(buffer+datalen+8, (png_uint_32)crc); 2318 png_save_uint_32(buffer+datalen+8, (png_uint_32)crc);
2319} 2319}
2320 2320
2321static void 2321static void
2322modifier_setbuffer(png_modifier *pm) 2322modifier_setbuffer(png_modifier *pm)
2323{ 2323{
2324 modifier_crc(pm->buffer); 2324 modifier_crc(pm->buffer);
2325 pm->buffer_count = png_get_uint_32(pm->buffer)+12; 2325 pm->buffer_count = png_get_uint_32(pm->buffer)+12;
2326 pm->buffer_position = 0; 2326 pm->buffer_position = 0;
2327} 2327}
2328 2328
2329/* Separate the callback into the actual implementation (which is passed the 2329/* Separate the callback into the actual implementation (which is passed the
2330 * png_modifier explicitly) and the callback, which gets the modifier from the 2330 * png_modifier explicitly) and the callback, which gets the modifier from the
2331 * png_struct. 2331 * png_struct.
2332 */ 2332 */
2333static void 2333static void
2334modifier_read_imp(png_modifier *pm, png_bytep pb, png_size_t st) 2334modifier_read_imp(png_modifier *pm, png_bytep pb, png_size_t st)
2335{ 2335{
2336 while (st > 0) 2336 while (st > 0)
2337 { 2337 {
2338 size_t cb; 2338 size_t cb;
2339 png_uint_32 len, chunk; 2339 png_uint_32 len, chunk;
2340 png_modification *mod; 2340 png_modification *mod;
2341 2341
2342 if (pm->buffer_position >= pm->buffer_count) switch (pm->state) 2342 if (pm->buffer_position >= pm->buffer_count) switch (pm->state)
2343 { 2343 {
2344 static png_byte sign[8] = { 137, 80, 78, 71, 13, 10, 26, 10 }; 2344 static png_byte sign[8] = { 137, 80, 78, 71, 13, 10, 26, 10 };
2345 case modifier_start: 2345 case modifier_start:
2346 store_read_imp(&pm->this, pm->buffer, 8); /* size of signature. */ 2346 store_read_imp(&pm->this, pm->buffer, 8); /* size of signature. */
2347 pm->buffer_count = 8; 2347 pm->buffer_count = 8;
2348 pm->buffer_position = 0; 2348 pm->buffer_position = 0;
2349 2349
2350 if (memcmp(pm->buffer, sign, 8) != 0) 2350 if (memcmp(pm->buffer, sign, 8) != 0)
2351 png_error(pm->this.pread, "invalid PNG file signature"); 2351 png_error(pm->this.pread, "invalid PNG file signature");
2352 pm->state = modifier_signature; 2352 pm->state = modifier_signature;
2353 break; 2353 break;
2354 2354
2355 case modifier_signature: 2355 case modifier_signature:
2356 store_read_imp(&pm->this, pm->buffer, 13+12); /* size of IHDR */ 2356 store_read_imp(&pm->this, pm->buffer, 13+12); /* size of IHDR */
2357 pm->buffer_count = 13+12; 2357 pm->buffer_count = 13+12;
2358 pm->buffer_position = 0; 2358 pm->buffer_position = 0;
2359 2359
2360 if (png_get_uint_32(pm->buffer) != 13 || 2360 if (png_get_uint_32(pm->buffer) != 13 ||
2361 png_get_uint_32(pm->buffer+4) != CHUNK_IHDR) 2361 png_get_uint_32(pm->buffer+4) != CHUNK_IHDR)
2362 png_error(pm->this.pread, "invalid IHDR"); 2362 png_error(pm->this.pread, "invalid IHDR");
2363 2363
2364 /* Check the list of modifiers for modifications to the IHDR. */ 2364 /* Check the list of modifiers for modifications to the IHDR. */
2365 mod = pm->modifications; 2365 mod = pm->modifications;
2366 while (mod != NULL) 2366 while (mod != NULL)
2367 { 2367 {
2368 if (mod->chunk == CHUNK_IHDR && mod->modify_fn && 2368 if (mod->chunk == CHUNK_IHDR && mod->modify_fn &&
2369 (*mod->modify_fn)(pm, mod, 0)) 2369 (*mod->modify_fn)(pm, mod, 0))
2370 { 2370 {
2371 mod->modified = 1; 2371 mod->modified = 1;
2372 modifier_setbuffer(pm); 2372 modifier_setbuffer(pm);
2373 } 2373 }
2374 2374
2375 /* Ignore removal or add if IHDR! */ 2375 /* Ignore removal or add if IHDR! */
2376 mod = mod->next; 2376 mod = mod->next;
2377 } 2377 }
2378 2378
2379 /* Cache information from the IHDR (the modified one.) */ 2379 /* Cache information from the IHDR (the modified one.) */
2380 pm->bit_depth = pm->buffer[8+8]; 2380 pm->bit_depth = pm->buffer[8+8];
2381 pm->colour_type = pm->buffer[8+8+1]; 2381 pm->colour_type = pm->buffer[8+8+1];
2382 2382
2383 pm->state = modifier_IHDR; 2383 pm->state = modifier_IHDR;
2384 pm->flush = 0; 2384 pm->flush = 0;
2385 break; 2385 break;
2386 2386
2387 case modifier_IHDR: 2387 case modifier_IHDR:
2388 default: 2388 default:
2389 /* Read a new chunk and process it until we see PLTE, IDAT or 2389 /* Read a new chunk and process it until we see PLTE, IDAT or
2390 * IEND. 'flush' indicates that there is still some data to 2390 * IEND. 'flush' indicates that there is still some data to
2391 * output from the preceding chunk. 2391 * output from the preceding chunk.
2392 */ 2392 */
2393 if ((cb = pm->flush) > 0) 2393 if ((cb = pm->flush) > 0)
2394 { 2394 {
2395 if (cb > st) cb = st; 2395 if (cb > st) cb = st;
2396 pm->flush -= cb; 2396 pm->flush -= cb;
2397 store_read_imp(&pm->this, pb, cb); 2397 store_read_imp(&pm->this, pb, cb);
2398 pb += cb; 2398 pb += cb;
2399 st -= cb; 2399 st -= cb;
2400 if (st == 0) return; 2400 if (st == 0) return;
2401 } 2401 }
2402 2402
2403 /* No more bytes to flush, read a header, or handle a pending 2403 /* No more bytes to flush, read a header, or handle a pending
2404 * chunk. 2404 * chunk.
2405 */ 2405 */
2406 if (pm->pending_chunk != 0) 2406 if (pm->pending_chunk != 0)
2407 { 2407 {
2408 png_save_uint_32(pm->buffer, pm->pending_len); 2408 png_save_uint_32(pm->buffer, pm->pending_len);
2409 png_save_uint_32(pm->buffer+4, pm->pending_chunk); 2409 png_save_uint_32(pm->buffer+4, pm->pending_chunk);
2410 pm->pending_len = 0; 2410 pm->pending_len = 0;
2411 pm->pending_chunk = 0; 2411 pm->pending_chunk = 0;
2412 } 2412 }
2413 else 2413 else
2414 store_read_imp(&pm->this, pm->buffer, 8); 2414 store_read_imp(&pm->this, pm->buffer, 8);
2415 2415
2416 pm->buffer_count = 8; 2416 pm->buffer_count = 8;
2417 pm->buffer_position = 0; 2417 pm->buffer_position = 0;
2418 2418
2419 /* Check for something to modify or a terminator chunk. */ 2419 /* Check for something to modify or a terminator chunk. */
2420 len = png_get_uint_32(pm->buffer); 2420 len = png_get_uint_32(pm->buffer);
2421 chunk = png_get_uint_32(pm->buffer+4); 2421 chunk = png_get_uint_32(pm->buffer+4);
2422 2422
2423 /* Terminators first, they may have to be delayed for added 2423 /* Terminators first, they may have to be delayed for added
2424 * chunks 2424 * chunks
2425 */ 2425 */
2426 if (chunk == CHUNK_PLTE || chunk == CHUNK_IDAT || 2426 if (chunk == CHUNK_PLTE || chunk == CHUNK_IDAT ||
2427 chunk == CHUNK_IEND) 2427 chunk == CHUNK_IEND)
2428 { 2428 {
2429 mod = pm->modifications; 2429 mod = pm->modifications;
2430 2430
2431 while (mod != NULL) 2431 while (mod != NULL)
2432 { 2432 {
2433 if ((mod->add == chunk || 2433 if ((mod->add == chunk ||
2434 (mod->add == CHUNK_PLTE && chunk == CHUNK_IDAT)) && 2434 (mod->add == CHUNK_PLTE && chunk == CHUNK_IDAT)) &&
2435 mod->modify_fn != NULL && !mod->modified && !mod->added) 2435 mod->modify_fn != NULL && !mod->modified && !mod->added)
2436 { 2436 {
2437 /* Regardless of what the modify function does do not run 2437 /* Regardless of what the modify function does do not run
2438 * this again. 2438 * this again.
2439 */ 2439 */
2440 mod->added = 1; 2440 mod->added = 1;
2441 2441
2442 if ((*mod->modify_fn)(pm, mod, 1 /*add*/)) 2442 if ((*mod->modify_fn)(pm, mod, 1 /*add*/))
2443 { 2443 {
2444 /* Reset the CRC on a new chunk */ 2444 /* Reset the CRC on a new chunk */
2445 if (pm->buffer_count > 0) 2445 if (pm->buffer_count > 0)
2446 modifier_setbuffer(pm); 2446 modifier_setbuffer(pm);
2447 2447
2448 else 2448 else
2449 { 2449 {
2450 pm->buffer_position = 0; 2450 pm->buffer_position = 0;
2451 mod->removed = 1; 2451 mod->removed = 1;
2452 } 2452 }
2453 2453
2454 /* The buffer has been filled with something (we assume) 2454 /* The buffer has been filled with something (we assume)
2455 * so output this. Pend the current chunk. 2455 * so output this. Pend the current chunk.
2456 */ 2456 */
2457 pm->pending_len = len; 2457 pm->pending_len = len;
2458 pm->pending_chunk = chunk; 2458 pm->pending_chunk = chunk;
2459 break; /* out of while */ 2459 break; /* out of while */
2460 } 2460 }
2461 } 2461 }
2462 2462
2463 mod = mod->next; 2463 mod = mod->next;
2464 } 2464 }
2465 2465
2466 /* Don't do any further processing if the buffer was modified - 2466 /* Don't do any further processing if the buffer was modified -
2467 * otherwise the code will end up modifying a chunk that was 2467 * otherwise the code will end up modifying a chunk that was
2468 * just added. 2468 * just added.
2469 */ 2469 */
2470 if (mod != NULL) 2470 if (mod != NULL)
2471 break; /* out of switch */ 2471 break; /* out of switch */
2472 } 2472 }
2473 2473
2474 /* If we get to here then this chunk may need to be modified. To 2474 /* If we get to here then this chunk may need to be modified. To
2475 * do this it must be less than 1024 bytes in total size, otherwise 2475 * do this it must be less than 1024 bytes in total size, otherwise
2476 * it just gets flushed. 2476 * it just gets flushed.
2477 */ 2477 */
2478 if (len+12 <= sizeof pm->buffer) 2478 if (len+12 <= sizeof pm->buffer)
2479 { 2479 {
2480 store_read_imp(&pm->this, pm->buffer+pm->buffer_count, 2480 store_read_imp(&pm->this, pm->buffer+pm->buffer_count,
2481 len+12-pm->buffer_count); 2481 len+12-pm->buffer_count);
2482 pm->buffer_count = len+12; 2482 pm->buffer_count = len+12;
2483 2483
2484 /* Check for a modification, else leave it be. */ 2484 /* Check for a modification, else leave it be. */
2485 mod = pm->modifications; 2485 mod = pm->modifications;
2486 while (mod != NULL) 2486 while (mod != NULL)
2487 { 2487 {
2488 if (mod->chunk == chunk) 2488 if (mod->chunk == chunk)
2489 { 2489 {
2490 if (mod->modify_fn == NULL) 2490 if (mod->modify_fn == NULL)
2491 { 2491 {
2492 /* Remove this chunk */ 2492 /* Remove this chunk */
2493 pm->buffer_count = pm->buffer_position = 0; 2493 pm->buffer_count = pm->buffer_position = 0;
2494 mod->removed = 1; 2494 mod->removed = 1;
2495 break; /* Terminate the while loop */ 2495 break; /* Terminate the while loop */
2496 } 2496 }
2497 2497
2498 else if ((*mod->modify_fn)(pm, mod, 0)) 2498 else if ((*mod->modify_fn)(pm, mod, 0))
2499 { 2499 {
2500 mod->modified = 1; 2500 mod->modified = 1;
2501 /* The chunk may have been removed: */ 2501 /* The chunk may have been removed: */
2502 if (pm->buffer_count == 0) 2502 if (pm->buffer_count == 0)
2503 { 2503 {
2504 pm->buffer_position = 0; 2504 pm->buffer_position = 0;
2505 break; 2505 break;
2506 } 2506 }
2507 modifier_setbuffer(pm); 2507 modifier_setbuffer(pm);
2508 } 2508 }
2509 } 2509 }
2510 2510
2511 mod = mod->next; 2511 mod = mod->next;
2512 } 2512 }
2513 } 2513 }
2514 2514
2515 else 2515 else
2516 pm->flush = len+12 - pm->buffer_count; /* data + crc */ 2516 pm->flush = len+12 - pm->buffer_count; /* data + crc */
2517 2517
2518 /* Take the data from the buffer (if there is any). */ 2518 /* Take the data from the buffer (if there is any). */
2519 break; 2519 break;
2520 } 2520 }
2521 2521
2522 /* Here to read from the modifier buffer (not directly from 2522 /* Here to read from the modifier buffer (not directly from
2523 * the store, as in the flush case above.) 2523 * the store, as in the flush case above.)
2524 */ 2524 */
2525 cb = pm->buffer_count - pm->buffer_position; 2525 cb = pm->buffer_count - pm->buffer_position;
2526 2526
2527 if (cb > st) 2527 if (cb > st)
2528 cb = st; 2528 cb = st;
2529 2529
2530 memcpy(pb, pm->buffer + pm->buffer_position, cb); 2530 memcpy(pb, pm->buffer + pm->buffer_position, cb);
2531 st -= cb; 2531 st -= cb;
2532 pb += cb; 2532 pb += cb;
2533 pm->buffer_position += cb; 2533 pm->buffer_position += cb;
2534 } 2534 }
2535} 2535}
2536 2536
2537/* The callback: */ 2537/* The callback: */
2538static void 2538static void
2539modifier_read(png_structp pp, png_bytep pb, png_size_t st) 2539modifier_read(png_structp pp, png_bytep pb, png_size_t st)
2540{ 2540{
2541 png_modifier *pm = voidcast(png_modifier*, png_get_io_ptr(pp)); 2541 png_modifier *pm = voidcast(png_modifier*, png_get_io_ptr(pp));
2542 2542
2543 if (pm == NULL || pm->this.pread != pp) 2543 if (pm == NULL || pm->this.pread != pp)
2544 png_error(pp, "bad modifier_read call"); 2544 png_error(pp, "bad modifier_read call");
2545 2545
2546 modifier_read_imp(pm, pb, st); 2546 modifier_read_imp(pm, pb, st);
2547} 2547}
2548 2548
2549/* Like store_progressive_read but the data is getting changed as we go so we 2549/* Like store_progressive_read but the data is getting changed as we go so we
2550 * need a local buffer. 2550 * need a local buffer.
2551 */ 2551 */
2552static void 2552static void
2553modifier_progressive_read(png_modifier *pm, png_structp pp, png_infop pi) 2553modifier_progressive_read(png_modifier *pm, png_structp pp, png_infop pi)
2554{ 2554{
2555 if (pm->this.pread != pp || pm->this.current == NULL || 2555 if (pm->this.pread != pp || pm->this.current == NULL ||
2556 pm->this.next == NULL) 2556 pm->this.next == NULL)
2557 png_error(pp, "store state damaged (progressive)"); 2557 png_error(pp, "store state damaged (progressive)");
2558 2558
2559 /* This is another Horowitz and Hill random noise generator. In this case 2559 /* This is another Horowitz and Hill random noise generator. In this case
2560 * the aim is to stress the progressive reader with truly horrible variable 2560 * the aim is to stress the progressive reader with truly horrible variable
2561 * buffer sizes in the range 1..500, so a sequence of 9 bit random numbers 2561 * buffer sizes in the range 1..500, so a sequence of 9 bit random numbers
2562 * is generated. We could probably just count from 1 to 32767 and get as 2562 * is generated. We could probably just count from 1 to 32767 and get as
2563 * good a result. 2563 * good a result.
2564 */ 2564 */
2565 for (;;) 2565 for (;;)
2566 { 2566 {
2567 static png_uint_32 noise = 1; 2567 static png_uint_32 noise = 1;
2568 png_size_t cb, cbAvail; 2568 png_size_t cb, cbAvail;
2569 png_byte buffer[512]; 2569 png_byte buffer[512];
2570 2570
2571 /* Generate 15 more bits of stuff: */ 2571 /* Generate 15 more bits of stuff: */
2572 noise = (noise << 9) | ((noise ^ (noise >> (9-5))) & 0x1ff); 2572 noise = (noise << 9) | ((noise ^ (noise >> (9-5))) & 0x1ff);
2573 cb = noise & 0x1ff; 2573 cb = noise & 0x1ff;
2574 2574
2575 /* Check that this number of bytes are available (in the current buffer.) 2575 /* Check that this number of bytes are available (in the current buffer.)
2576 * (This doesn't quite work - the modifier might delete a chunk; unlikely 2576 * (This doesn't quite work - the modifier might delete a chunk; unlikely
2577 * but possible, it doesn't happen at present because the modifier only 2577 * but possible, it doesn't happen at present because the modifier only
2578 * adds chunks to standard images.) 2578 * adds chunks to standard images.)
2579 */ 2579 */
2580 cbAvail = store_read_buffer_avail(&pm->this); 2580 cbAvail = store_read_buffer_avail(&pm->this);
2581 if (pm->buffer_count > pm->buffer_position) 2581 if (pm->buffer_count > pm->buffer_position)
2582 cbAvail += pm->buffer_count - pm->buffer_position; 2582 cbAvail += pm->buffer_count - pm->buffer_position;
2583 2583
2584 if (cb > cbAvail) 2584 if (cb > cbAvail)
2585 { 2585 {
2586 /* Check for EOF: */ 2586 /* Check for EOF: */
2587 if (cbAvail == 0) 2587 if (cbAvail == 0)
2588 break; 2588 break;
2589 2589
2590 cb = cbAvail; 2590 cb = cbAvail;
2591 } 2591 }
2592 2592
2593 modifier_read_imp(pm, buffer, cb); 2593 modifier_read_imp(pm, buffer, cb);
2594 png_process_data(pp, pi, buffer, cb); 2594 png_process_data(pp, pi, buffer, cb);
2595 } 2595 }
2596 2596
2597 /* Check the invariants at the end (if this fails it's a problem in this 2597 /* Check the invariants at the end (if this fails it's a problem in this
2598 * file!) 2598 * file!)
2599 */ 2599 */
2600 if (pm->buffer_count > pm->buffer_position || 2600 if (pm->buffer_count > pm->buffer_position ||
2601 pm->this.next != &pm->this.current->data || 2601 pm->this.next != &pm->this.current->data ||
2602 pm->this.readpos < pm->this.current->datacount) 2602 pm->this.readpos < pm->this.current->datacount)
2603 png_error(pp, "progressive read implementation error"); 2603 png_error(pp, "progressive read implementation error");
2604} 2604}
2605 2605
2606/* Set up a modifier. */ 2606/* Set up a modifier. */
2607static png_structp 2607static png_structp
2608set_modifier_for_read(png_modifier *pm, png_infopp ppi, png_uint_32 id, 2608set_modifier_for_read(png_modifier *pm, png_infopp ppi, png_uint_32 id,
2609 PNG_CONST char *name) 2609 PNG_CONST char *name)
2610{ 2610{
2611 /* Do this first so that the modifier fields are cleared even if an error 2611 /* Do this first so that the modifier fields are cleared even if an error
2612 * happens allocating the png_struct. No allocation is done here so no 2612 * happens allocating the png_struct. No allocation is done here so no
2613 * cleanup is required. 2613 * cleanup is required.
2614 */ 2614 */
2615 pm->state = modifier_start; 2615 pm->state = modifier_start;
2616 pm->bit_depth = 0; 2616 pm->bit_depth = 0;
2617 pm->colour_type = 255; 2617 pm->colour_type = 255;
2618 2618
2619 pm->pending_len = 0; 2619 pm->pending_len = 0;
2620 pm->pending_chunk = 0; 2620 pm->pending_chunk = 0;
2621 pm->flush = 0; 2621 pm->flush = 0;
2622 pm->buffer_count = 0; 2622 pm->buffer_count = 0;
2623 pm->buffer_position = 0; 2623 pm->buffer_position = 0;
2624 2624
2625 return set_store_for_read(&pm->this, ppi, id, name); 2625 return set_store_for_read(&pm->this, ppi, id, name);
2626} 2626}
2627 2627
2628 2628
2629/******************************** MODIFICATIONS *******************************/ 2629/******************************** MODIFICATIONS *******************************/
2630/* Standard modifications to add chunks. These do not require the _SUPPORTED 2630/* Standard modifications to add chunks. These do not require the _SUPPORTED
2631 * macros because the chunks can be there regardless of whether this specific 2631 * macros because the chunks can be there regardless of whether this specific
2632 * libpng supports them. 2632 * libpng supports them.
2633 */ 2633 */
2634typedef struct gama_modification 2634typedef struct gama_modification
2635{ 2635{
2636 png_modification this; 2636 png_modification this;
2637 png_fixed_point gamma; 2637 png_fixed_point gamma;
2638} gama_modification; 2638} gama_modification;
2639 2639
2640static int 2640static int
2641gama_modify(png_modifier *pm, png_modification *me, int add) 2641gama_modify(png_modifier *pm, png_modification *me, int add)
2642{ 2642{
2643 UNUSED(add) 2643 UNUSED(add)
2644 /* This simply dumps the given gamma value into the buffer. */ 2644 /* This simply dumps the given gamma value into the buffer. */
2645 png_save_uint_32(pm->buffer, 4); 2645 png_save_uint_32(pm->buffer, 4);
2646 png_save_uint_32(pm->buffer+4, CHUNK_gAMA); 2646 png_save_uint_32(pm->buffer+4, CHUNK_gAMA);
2647 png_save_uint_32(pm->buffer+8, ((gama_modification*)me)->gamma); 2647 png_save_uint_32(pm->buffer+8, ((gama_modification*)me)->gamma);
2648 return 1; 2648 return 1;
2649} 2649}
2650 2650
2651static void 2651static void
2652gama_modification_init(gama_modification *me, png_modifier *pm, double gammad) 2652gama_modification_init(gama_modification *me, png_modifier *pm, double gammad)
2653{ 2653{
2654 double g; 2654 double g;
2655 2655
2656 modification_init(&me->this); 2656 modification_init(&me->this);
2657 me->this.chunk = CHUNK_gAMA; 2657 me->this.chunk = CHUNK_gAMA;
2658 me->this.modify_fn = gama_modify; 2658 me->this.modify_fn = gama_modify;
2659 me->this.add = CHUNK_PLTE; 2659 me->this.add = CHUNK_PLTE;
2660 g = fix(gammad); 2660 g = fix(gammad);
2661 me->gamma = (png_fixed_point)g; 2661 me->gamma = (png_fixed_point)g;
2662 me->this.next = pm->modifications; 2662 me->this.next = pm->modifications;
2663 pm->modifications = &me->this; 2663 pm->modifications = &me->this;
2664} 2664}
2665 2665
2666typedef struct chrm_modification 2666typedef struct chrm_modification
2667{ 2667{
2668 png_modification this; 2668 png_modification this;
2669 PNG_CONST color_encoding *encoding; 2669 PNG_CONST color_encoding *encoding;
2670 png_fixed_point wx, wy, rx, ry, gx, gy, bx, by; 2670 png_fixed_point wx, wy, rx, ry, gx, gy, bx, by;
2671} chrm_modification; 2671} chrm_modification;
2672 2672
2673static int 2673static int
2674chrm_modify(png_modifier *pm, png_modification *me, int add) 2674chrm_modify(png_modifier *pm, png_modification *me, int add)
2675{ 2675{
2676 UNUSED(add) 2676 UNUSED(add)
2677 /* As with gAMA this just adds the required cHRM chunk to the buffer. */ 2677 /* As with gAMA this just adds the required cHRM chunk to the buffer. */
2678 png_save_uint_32(pm->buffer , 32); 2678 png_save_uint_32(pm->buffer , 32);
2679 png_save_uint_32(pm->buffer+ 4, CHUNK_cHRM); 2679 png_save_uint_32(pm->buffer+ 4, CHUNK_cHRM);
2680 png_save_uint_32(pm->buffer+ 8, ((chrm_modification*)me)->wx); 2680 png_save_uint_32(pm->buffer+ 8, ((chrm_modification*)me)->wx);
2681 png_save_uint_32(pm->buffer+12, ((chrm_modification*)me)->wy); 2681 png_save_uint_32(pm->buffer+12, ((chrm_modification*)me)->wy);
2682 png_save_uint_32(pm->buffer+16, ((chrm_modification*)me)->rx); 2682 png_save_uint_32(pm->buffer+16, ((chrm_modification*)me)->rx);
2683 png_save_uint_32(pm->buffer+20, ((chrm_modification*)me)->ry); 2683 png_save_uint_32(pm->buffer+20, ((chrm_modification*)me)->ry);
2684 png_save_uint_32(pm->buffer+24, ((chrm_modification*)me)->gx); 2684 png_save_uint_32(pm->buffer+24, ((chrm_modification*)me)->gx);
2685 png_save_uint_32(pm->buffer+28, ((chrm_modification*)me)->gy); 2685 png_save_uint_32(pm->buffer+28, ((chrm_modification*)me)->gy);
2686 png_save_uint_32(pm->buffer+32, ((chrm_modification*)me)->bx); 2686 png_save_uint_32(pm->buffer+32, ((chrm_modification*)me)->bx);
2687 png_save_uint_32(pm->buffer+36, ((chrm_modification*)me)->by); 2687 png_save_uint_32(pm->buffer+36, ((chrm_modification*)me)->by);
2688 return 1; 2688 return 1;
2689} 2689}
2690 2690
2691static void 2691static void
2692chrm_modification_init(chrm_modification *me, png_modifier *pm, 2692chrm_modification_init(chrm_modification *me, png_modifier *pm,
2693 PNG_CONST color_encoding *encoding) 2693 PNG_CONST color_encoding *encoding)
2694{ 2694{
2695 CIE_color white = white_point(encoding); 2695 CIE_color white = white_point(encoding);
2696 2696
2697 /* Original end points: */ 2697 /* Original end points: */
2698 me->encoding = encoding; 2698 me->encoding = encoding;
2699 2699
2700 /* Chromaticities (in fixed point): */ 2700 /* Chromaticities (in fixed point): */
2701 me->wx = fix(chromaticity_x(white)); 2701 me->wx = fix(chromaticity_x(white));
2702 me->wy = fix(chromaticity_y(white)); 2702 me->wy = fix(chromaticity_y(white));
2703 2703
2704 me->rx = fix(chromaticity_x(encoding->red)); 2704 me->rx = fix(chromaticity_x(encoding->red));
2705 me->ry = fix(chromaticity_y(encoding->red)); 2705 me->ry = fix(chromaticity_y(encoding->red));
2706 me->gx = fix(chromaticity_x(encoding->green)); 2706 me->gx = fix(chromaticity_x(encoding->green));
2707 me->gy = fix(chromaticity_y(encoding->green)); 2707 me->gy = fix(chromaticity_y(encoding->green));
2708 me->bx = fix(chromaticity_x(encoding->blue)); 2708 me->bx = fix(chromaticity_x(encoding->blue));
2709 me->by = fix(chromaticity_y(encoding->blue)); 2709 me->by = fix(chromaticity_y(encoding->blue));
2710 2710
2711 modification_init(&me->this); 2711 modification_init(&me->this);
2712 me->this.chunk = CHUNK_cHRM; 2712 me->this.chunk = CHUNK_cHRM;
2713 me->this.modify_fn = chrm_modify; 2713 me->this.modify_fn = chrm_modify;
2714 me->this.add = CHUNK_PLTE; 2714 me->this.add = CHUNK_PLTE;
2715 me->this.next = pm->modifications; 2715 me->this.next = pm->modifications;
2716 pm->modifications = &me->this; 2716 pm->modifications = &me->this;
2717} 2717}
2718 2718
2719typedef struct srgb_modification 2719typedef struct srgb_modification
2720{ 2720{
2721 png_modification this; 2721 png_modification this;
2722 png_byte intent; 2722 png_byte intent;
2723} srgb_modification; 2723} srgb_modification;
2724 2724
2725static int 2725static int
2726srgb_modify(png_modifier *pm, png_modification *me, int add) 2726srgb_modify(png_modifier *pm, png_modification *me, int add)
2727{ 2727{
2728 UNUSED(add) 2728 UNUSED(add)
2729 /* As above, ignore add and just make a new chunk */ 2729 /* As above, ignore add and just make a new chunk */
2730 png_save_uint_32(pm->buffer, 1); 2730 png_save_uint_32(pm->buffer, 1);
2731 png_save_uint_32(pm->buffer+4, CHUNK_sRGB); 2731 png_save_uint_32(pm->buffer+4, CHUNK_sRGB);
2732 pm->buffer[8] = ((srgb_modification*)me)->intent; 2732 pm->buffer[8] = ((srgb_modification*)me)->intent;
2733 return 1; 2733 return 1;
2734} 2734}
2735 2735
2736static void 2736static void
2737srgb_modification_init(srgb_modification *me, png_modifier *pm, png_byte intent) 2737srgb_modification_init(srgb_modification *me, png_modifier *pm, png_byte intent)
2738{ 2738{
2739 modification_init(&me->this); 2739 modification_init(&me->this);
2740 me->this.chunk = CHUNK_sBIT; 2740 me->this.chunk = CHUNK_sBIT;
2741 2741
2742 if (intent <= 3) /* if valid, else *delete* sRGB chunks */ 2742 if (intent <= 3) /* if valid, else *delete* sRGB chunks */
2743 { 2743 {
2744 me->this.modify_fn = srgb_modify; 2744 me->this.modify_fn = srgb_modify;
2745 me->this.add = CHUNK_PLTE; 2745 me->this.add = CHUNK_PLTE;
2746 me->intent = intent; 2746 me->intent = intent;
2747 } 2747 }
2748 2748
2749 else 2749 else
2750 { 2750 {
2751 me->this.modify_fn = 0; 2751 me->this.modify_fn = 0;
2752 me->this.add = 0; 2752 me->this.add = 0;
2753 me->intent = 0; 2753 me->intent = 0;
2754 } 2754 }
2755 2755
2756 me->this.next = pm->modifications; 2756 me->this.next = pm->modifications;
2757 pm->modifications = &me->this; 2757 pm->modifications = &me->this;
2758} 2758}
2759 2759
2760typedef struct sbit_modification 2760typedef struct sbit_modification
2761{ 2761{
2762 png_modification this; 2762 png_modification this;
2763 png_byte sbit; 2763 png_byte sbit;
2764} sbit_modification; 2764} sbit_modification;
2765 2765
2766static int 2766static int
2767sbit_modify(png_modifier *pm, png_modification *me, int add) 2767sbit_modify(png_modifier *pm, png_modification *me, int add)
2768{ 2768{
2769 png_byte sbit = ((sbit_modification*)me)->sbit; 2769 png_byte sbit = ((sbit_modification*)me)->sbit;
2770 if (pm->bit_depth > sbit) 2770 if (pm->bit_depth > sbit)
2771 { 2771 {
2772 int cb = 0; 2772 int cb = 0;
2773 switch (pm->colour_type) 2773 switch (pm->colour_type)
2774 { 2774 {
2775 case 0: 2775 case 0:
2776 cb = 1; 2776 cb = 1;
2777 break; 2777 break;
2778 2778
2779 case 2: 2779 case 2:
2780 case 3: 2780 case 3:
2781 cb = 3; 2781 cb = 3;
2782 break; 2782 break;
2783 2783
2784 case 4: 2784 case 4:
2785 cb = 2; 2785 cb = 2;
2786 break; 2786 break;
2787 2787
2788 case 6: 2788 case 6:
2789 cb = 4; 2789 cb = 4;
2790 break; 2790 break;
2791 2791
2792 default: 2792 default:
2793 png_error(pm->this.pread, 2793 png_error(pm->this.pread,
2794 "unexpected colour type in sBIT modification"); 2794 "unexpected colour type in sBIT modification");
2795 } 2795 }
2796 2796
2797 png_save_uint_32(pm->buffer, cb); 2797 png_save_uint_32(pm->buffer, cb);
2798 png_save_uint_32(pm->buffer+4, CHUNK_sBIT); 2798 png_save_uint_32(pm->buffer+4, CHUNK_sBIT);
2799 2799
2800 while (cb > 0) 2800 while (cb > 0)
2801 (pm->buffer+8)[--cb] = sbit; 2801 (pm->buffer+8)[--cb] = sbit;
2802 2802
2803 return 1; 2803 return 1;
2804 } 2804 }
2805 else if (!add) 2805 else if (!add)
2806 { 2806 {
2807 /* Remove the sBIT chunk */ 2807 /* Remove the sBIT chunk */
2808 pm->buffer_count = pm->buffer_position = 0; 2808 pm->buffer_count = pm->buffer_position = 0;
2809 return 1; 2809 return 1;
2810 } 2810 }
2811 else 2811 else
2812 return 0; /* do nothing */ 2812 return 0; /* do nothing */
2813} 2813}
2814 2814
2815static void 2815static void
2816sbit_modification_init(sbit_modification *me, png_modifier *pm, png_byte sbit) 2816sbit_modification_init(sbit_modification *me, png_modifier *pm, png_byte sbit)
2817{ 2817{
2818 modification_init(&me->this); 2818 modification_init(&me->this);
2819 me->this.chunk = CHUNK_sBIT; 2819 me->this.chunk = CHUNK_sBIT;
2820 me->this.modify_fn = sbit_modify; 2820 me->this.modify_fn = sbit_modify;
2821 me->this.add = CHUNK_PLTE; 2821 me->this.add = CHUNK_PLTE;
2822 me->sbit = sbit; 2822 me->sbit = sbit;
2823 me->this.next = pm->modifications; 2823 me->this.next = pm->modifications;
2824 pm->modifications = &me->this; 2824 pm->modifications = &me->this;
2825} 2825}
2826#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ 2826#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
2827 2827
2828/***************************** STANDARD PNG FILES *****************************/ 2828/***************************** STANDARD PNG FILES *****************************/
2829/* Standard files - write and save standard files. */ 2829/* Standard files - write and save standard files. */
2830/* There are two basic forms of standard images. Those which attempt to have 2830/* There are two basic forms of standard images. Those which attempt to have
2831 * all the possible pixel values (not possible for 16bpp images, but a range of 2831 * all the possible pixel values (not possible for 16bpp images, but a range of
2832 * values are produced) and those which have a range of image sizes. The former 2832 * values are produced) and those which have a range of image sizes. The former
2833 * are used for testing transforms, in particular gamma correction and bit 2833 * are used for testing transforms, in particular gamma correction and bit
2834 * reduction and increase. The latter are reserved for testing the behavior of 2834 * reduction and increase. The latter are reserved for testing the behavior of
2835 * libpng with respect to 'odd' image sizes - particularly small images where 2835 * libpng with respect to 'odd' image sizes - particularly small images where
2836 * rows become 1 byte and interlace passes disappear. 2836 * rows become 1 byte and interlace passes disappear.
2837 * 2837 *
2838 * The first, most useful, set are the 'transform' images, the second set of 2838 * The first, most useful, set are the 'transform' images, the second set of
2839 * small images are the 'size' images. 2839 * small images are the 'size' images.
2840 * 2840 *
2841 * The transform files are constructed with rows which fit into a 1024 byte row 2841 * The transform files are constructed with rows which fit into a 1024 byte row
2842 * buffer. This makes allocation easier below. Further regardless of the file 2842 * buffer. This makes allocation easier below. Further regardless of the file
2843 * format every row has 128 pixels (giving 1024 bytes for 64bpp formats). 2843 * format every row has 128 pixels (giving 1024 bytes for 64bpp formats).
2844 * 2844 *
2845 * Files are stored with no gAMA or sBIT chunks, with a PLTE only when needed 2845 * Files are stored with no gAMA or sBIT chunks, with a PLTE only when needed
2846 * and with an ID derived from the colour type, bit depth and interlace type 2846 * and with an ID derived from the colour type, bit depth and interlace type
2847 * as above (FILEID). The width (128) and height (variable) are not stored in 2847 * as above (FILEID). The width (128) and height (variable) are not stored in
2848 * the FILEID - instead the fields are set to 0, indicating a transform file. 2848 * the FILEID - instead the fields are set to 0, indicating a transform file.
2849 * 2849 *
2850 * The size files ar constructed with rows a maximum of 128 bytes wide, allowing 2850 * The size files ar constructed with rows a maximum of 128 bytes wide, allowing
2851 * a maximum width of 16 pixels (for the 64bpp case.) They also have a maximum 2851 * a maximum width of 16 pixels (for the 64bpp case.) They also have a maximum
2852 * height of 16 rows. The width and height are stored in the FILEID and, being 2852 * height of 16 rows. The width and height are stored in the FILEID and, being
2853 * non-zero, indicate a size file. 2853 * non-zero, indicate a size file.
2854 * 2854 *
2855 * For palette image (colour type 3) multiple transform images are stored with 2855 * For palette image (colour type 3) multiple transform images are stored with
2856 * the same bit depth to allow testing of more colour combinations - 2856 * the same bit depth to allow testing of more colour combinations -
2857 * particularly important for testing the gamma code because libpng uses a 2857 * particularly important for testing the gamma code because libpng uses a
2858 * different code path for palette images. For size images a single palette is 2858 * different code path for palette images. For size images a single palette is
2859 * used. 2859 * used.
2860 */ 2860 */
2861 2861
2862/* Make a 'standard' palette. Because there are only 256 entries in a palette 2862/* Make a 'standard' palette. Because there are only 256 entries in a palette
2863 * (maximum) this actually makes a random palette in the hope that enough tests 2863 * (maximum) this actually makes a random palette in the hope that enough tests
2864 * will catch enough errors. (Note that the same palette isn't produced every 2864 * will catch enough errors. (Note that the same palette isn't produced every
2865 * time for the same test - it depends on what previous tests have been run - 2865 * time for the same test - it depends on what previous tests have been run -
2866 * but a given set of arguments to pngvalid will always produce the same palette 2866 * but a given set of arguments to pngvalid will always produce the same palette
2867 * at the same test! This is why pseudo-random number generators are useful for 2867 * at the same test! This is why pseudo-random number generators are useful for
2868 * testing.) 2868 * testing.)
2869 * 2869 *
2870 * The store must be open for write when this is called, otherwise an internal 2870 * The store must be open for write when this is called, otherwise an internal
2871 * error will occur. This routine contains its own magic number seed, so the 2871 * error will occur. This routine contains its own magic number seed, so the
2872 * palettes generated don't change if there are intervening errors (changing the 2872 * palettes generated don't change if there are intervening errors (changing the
2873 * calls to the store_mark seed.) 2873 * calls to the store_mark seed.)
2874 */ 2874 */
2875static store_palette_entry * 2875static store_palette_entry *
2876make_standard_palette(png_store* ps, int npalette, int do_tRNS) 2876make_standard_palette(png_store* ps, int npalette, int do_tRNS)
2877{ 2877{
2878 static png_uint_32 palette_seed[2] = { 0x87654321, 9 }; 2878 static png_uint_32 palette_seed[2] = { 0x87654321, 9 };
2879 2879
2880 int i = 0; 2880 int i = 0;
2881 png_byte values[256][4]; 2881 png_byte values[256][4];
2882 2882
2883 /* Always put in black and white plus the six primary and secondary colors. 2883 /* Always put in black and white plus the six primary and secondary colors.
2884 */ 2884 */
2885 for (; i<8; ++i) 2885 for (; i<8; ++i)
2886 { 2886 {
2887 values[i][1] = (i&1) ? 255 : 0; 2887 values[i][1] = (i&1) ? 255 : 0;
2888 values[i][2] = (i&2) ? 255 : 0; 2888 values[i][2] = (i&2) ? 255 : 0;
2889 values[i][3] = (i&4) ? 255 : 0; 2889 values[i][3] = (i&4) ? 255 : 0;
2890 } 2890 }
2891 2891
2892 /* Then add 62 grays (one quarter of the remaining 256 slots). */ 2892 /* Then add 62 grays (one quarter of the remaining 256 slots). */
2893 { 2893 {
2894 int j = 0; 2894 int j = 0;
2895 png_byte random_bytes[4]; 2895 png_byte random_bytes[4];
2896 png_byte need[256]; 2896 png_byte need[256];
2897 2897
2898 need[0] = 0; /*got black*/ 2898 need[0] = 0; /*got black*/
2899 memset(need+1, 1, (sizeof need)-2); /*need these*/ 2899 memset(need+1, 1, (sizeof need)-2); /*need these*/
2900 need[255] = 0; /*but not white*/ 2900 need[255] = 0; /*but not white*/
2901 2901
2902 while (i<70) 2902 while (i<70)
2903 { 2903 {
2904 png_byte b; 2904 png_byte b;
2905 2905
2906 if (j==0) 2906 if (j==0)
2907 { 2907 {
2908 make_four_random_bytes(palette_seed, random_bytes); 2908 make_four_random_bytes(palette_seed, random_bytes);
2909 j = 4; 2909 j = 4;
2910 } 2910 }
2911 2911
2912 b = random_bytes[--j]; 2912 b = random_bytes[--j];
2913 if (need[b]) 2913 if (need[b])
2914 { 2914 {
2915 values[i][1] = b; 2915 values[i][1] = b;
2916 values[i][2] = b; 2916 values[i][2] = b;
2917 values[i++][3] = b; 2917 values[i++][3] = b;
2918 } 2918 }
2919 } 2919 }
2920 } 2920 }
2921 2921
2922 /* Finally add 192 colors at random - don't worry about matches to things we 2922 /* Finally add 192 colors at random - don't worry about matches to things we
2923 * already have, chance is less than 1/65536. Don't worry about grays, 2923 * already have, chance is less than 1/65536. Don't worry about grays,
2924 * chance is the same, so we get a duplicate or extra gray less than 1 time 2924 * chance is the same, so we get a duplicate or extra gray less than 1 time
2925 * in 170. 2925 * in 170.
2926 */ 2926 */
2927 for (; i<256; ++i) 2927 for (; i<256; ++i)
2928 make_four_random_bytes(palette_seed, values[i]); 2928 make_four_random_bytes(palette_seed, values[i]);
2929 2929
2930 /* Fill in the alpha values in the first byte. Just use all possible values 2930 /* Fill in the alpha values in the first byte. Just use all possible values
2931 * (0..255) in an apparently random order: 2931 * (0..255) in an apparently random order:
2932 */ 2932 */
2933 { 2933 {
2934 store_palette_entry *palette; 2934 store_palette_entry *palette;
2935 png_byte selector[4]; 2935 png_byte selector[4];
2936 2936
2937 make_four_random_bytes(palette_seed, selector); 2937 make_four_random_bytes(palette_seed, selector);
2938 2938
2939 if (do_tRNS) 2939 if (do_tRNS)
2940 for (i=0; i<256; ++i) 2940 for (i=0; i<256; ++i)
2941 values[i][0] = (png_byte)(i ^ selector[0]); 2941 values[i][0] = (png_byte)(i ^ selector[0]);
2942 2942
2943 else 2943 else
2944 for (i=0; i<256; ++i) 2944 for (i=0; i<256; ++i)
2945 values[i][0] = 255; /* no transparency/tRNS chunk */ 2945 values[i][0] = 255; /* no transparency/tRNS chunk */
2946 2946
2947 /* 'values' contains 256 ARGB values, but we only need 'npalette'. 2947 /* 'values' contains 256 ARGB values, but we only need 'npalette'.
2948 * 'npalette' will always be a power of 2: 2, 4, 16 or 256. In the low 2948 * 'npalette' will always be a power of 2: 2, 4, 16 or 256. In the low
2949 * bit depth cases select colors at random, else it is difficult to have 2949 * bit depth cases select colors at random, else it is difficult to have
2950 * a set of low bit depth palette test with any chance of a reasonable 2950 * a set of low bit depth palette test with any chance of a reasonable
2951 * range of colors. Do this by randomly permuting values into the low 2951 * range of colors. Do this by randomly permuting values into the low
2952 * 'npalette' entries using an XOR mask generated here. This also 2952 * 'npalette' entries using an XOR mask generated here. This also
2953 * permutes the npalette == 256 case in a potentially useful way (there is 2953 * permutes the npalette == 256 case in a potentially useful way (there is
2954 * no relationship between palette index and the color value therein!) 2954 * no relationship between palette index and the color value therein!)
2955 */ 2955 */
2956 palette = store_write_palette(ps, npalette); 2956 palette = store_write_palette(ps, npalette);
2957 2957
2958 for (i=0; i<npalette; ++i) 2958 for (i=0; i<npalette; ++i)
2959 { 2959 {
2960 palette[i].alpha = values[i ^ selector[1]][0]; 2960 palette[i].alpha = values[i ^ selector[1]][0];
2961 palette[i].red = values[i ^ selector[1]][1]; 2961 palette[i].red = values[i ^ selector[1]][1];
2962 palette[i].green = values[i ^ selector[1]][2]; 2962 palette[i].green = values[i ^ selector[1]][2];
2963 palette[i].blue = values[i ^ selector[1]][3]; 2963 palette[i].blue = values[i ^ selector[1]][3];
2964 } 2964 }
2965 2965
2966 return palette; 2966 return palette;
2967 } 2967 }
2968} 2968}
2969 2969
2970/* Initialize a standard palette on a write stream. The 'do_tRNS' argument 2970/* Initialize a standard palette on a write stream. The 'do_tRNS' argument
2971 * indicates whether or not to also set the tRNS chunk. 2971 * indicates whether or not to also set the tRNS chunk.
2972 */ 2972 */
2973static void 2973static void
2974init_standard_palette(png_store *ps, png_structp pp, png_infop pi, int npalette, 2974init_standard_palette(png_store *ps, png_structp pp, png_infop pi, int npalette,
2975 int do_tRNS) 2975 int do_tRNS)
2976{ 2976{
2977 store_palette_entry *ppal = make_standard_palette(ps, npalette, do_tRNS); 2977 store_palette_entry *ppal = make_standard_palette(ps, npalette, do_tRNS);
2978 2978
2979 { 2979 {
2980 int i; 2980 int i;
2981 png_color palette[256]; 2981 png_color palette[256];
2982 2982
2983 /* Set all entries to detect overread errors. */ 2983 /* Set all entries to detect overread errors. */
2984 for (i=0; i<npalette; ++i) 2984 for (i=0; i<npalette; ++i)
2985 { 2985 {
2986 palette[i].red = ppal[i].red; 2986 palette[i].red = ppal[i].red;
2987 palette[i].green = ppal[i].green; 2987 palette[i].green = ppal[i].green;
2988 palette[i].blue = ppal[i].blue; 2988 palette[i].blue = ppal[i].blue;
2989 } 2989 }
2990 2990
2991 /* Just in case fill in the rest with detectable values: */ 2991 /* Just in case fill in the rest with detectable values: */
2992 for (; i<256; ++i) 2992 for (; i<256; ++i)
2993 palette[i].red = palette[i].green = palette[i].blue = 42; 2993 palette[i].red = palette[i].green = palette[i].blue = 42;
2994 2994
2995 png_set_PLTE(pp, pi, palette, npalette); 2995 png_set_PLTE(pp, pi, palette, npalette);
2996 } 2996 }
2997 2997
2998 if (do_tRNS) 2998 if (do_tRNS)
2999 { 2999 {
3000 int i, j; 3000 int i, j;
3001 png_byte tRNS[256]; 3001 png_byte tRNS[256];
3002 3002
3003 /* Set all the entries, but skip trailing opaque entries */ 3003 /* Set all the entries, but skip trailing opaque entries */
3004 for (i=j=0; i<npalette; ++i) 3004 for (i=j=0; i<npalette; ++i)
3005 if ((tRNS[i] = ppal[i].alpha) < 255) 3005 if ((tRNS[i] = ppal[i].alpha) < 255)
3006 j = i+1; 3006 j = i+1;
3007 3007
3008 /* Fill in the remainder with a detectable value: */ 3008 /* Fill in the remainder with a detectable value: */
3009 for (; i<256; ++i) 3009 for (; i<256; ++i)
3010 tRNS[i] = 24; 3010 tRNS[i] = 24;
3011 3011
3012 if (j > 0) 3012 if (j > 0)
3013 png_set_tRNS(pp, pi, tRNS, j, 0/*color*/); 3013 png_set_tRNS(pp, pi, tRNS, j, 0/*color*/);
3014 } 3014 }
3015} 3015}
3016 3016
3017/* The number of passes is related to the interlace type. There was no libpng 3017/* The number of passes is related to the interlace type. There was no libpng
3018 * API to determine this prior to 1.5, so we need an inquiry function: 3018 * API to determine this prior to 1.5, so we need an inquiry function:
3019 */ 3019 */
3020static int 3020static int
3021npasses_from_interlace_type(png_structp pp, int interlace_type) 3021npasses_from_interlace_type(png_structp pp, int interlace_type)
3022{ 3022{
3023 switch (interlace_type) 3023 switch (interlace_type)
3024 { 3024 {
3025 default: 3025 default:
3026 png_error(pp, "invalid interlace type"); 3026 png_error(pp, "invalid interlace type");
3027 3027
3028 case PNG_INTERLACE_NONE: 3028 case PNG_INTERLACE_NONE:
3029 return 1; 3029 return 1;
3030 3030
3031 case PNG_INTERLACE_ADAM7: 3031 case PNG_INTERLACE_ADAM7:
3032 return PNG_INTERLACE_ADAM7_PASSES; 3032 return PNG_INTERLACE_ADAM7_PASSES;
3033 } 3033 }
3034} 3034}
3035 3035
3036static unsigned int 3036static unsigned int
3037bit_size(png_structp pp, png_byte colour_type, png_byte bit_depth) 3037bit_size(png_structp pp, png_byte colour_type, png_byte bit_depth)
3038{ 3038{
3039 switch (colour_type) 3039 switch (colour_type)
3040 { 3040 {
3041 default: png_error(pp, "invalid color type"); 3041 default: png_error(pp, "invalid color type");
3042 3042
3043 case 0: return bit_depth; 3043 case 0: return bit_depth;
3044 3044
3045 case 2: return 3*bit_depth; 3045 case 2: return 3*bit_depth;
3046 3046
3047 case 3: return bit_depth; 3047 case 3: return bit_depth;
3048 3048
3049 case 4: return 2*bit_depth; 3049 case 4: return 2*bit_depth;
3050 3050
3051 case 6: return 4*bit_depth; 3051 case 6: return 4*bit_depth;
3052 } 3052 }
3053} 3053}
3054 3054
3055#define TRANSFORM_WIDTH 128U 3055#define TRANSFORM_WIDTH 128U
3056#define TRANSFORM_ROWMAX (TRANSFORM_WIDTH*8U) 3056#define TRANSFORM_ROWMAX (TRANSFORM_WIDTH*8U)
3057#define SIZE_ROWMAX (16*8U) /* 16 pixels, max 8 bytes each - 128 bytes */ 3057#define SIZE_ROWMAX (16*8U) /* 16 pixels, max 8 bytes each - 128 bytes */
3058#define STANDARD_ROWMAX TRANSFORM_ROWMAX /* The larger of the two */ 3058#define STANDARD_ROWMAX TRANSFORM_ROWMAX /* The larger of the two */
3059#define SIZE_HEIGHTMAX 16 /* Maximum range of size images */ 3059#define SIZE_HEIGHTMAX 16 /* Maximum range of size images */
3060 3060
3061static size_t 3061static size_t
3062transform_rowsize(png_structp pp, png_byte colour_type, png_byte bit_depth) 3062transform_rowsize(png_structp pp, png_byte colour_type, png_byte bit_depth)
3063{ 3063{
3064 return (TRANSFORM_WIDTH * bit_size(pp, colour_type, bit_depth)) / 8; 3064 return (TRANSFORM_WIDTH * bit_size(pp, colour_type, bit_depth)) / 8;
3065} 3065}
3066 3066
3067/* transform_width(pp, colour_type, bit_depth) current returns the same number 3067/* transform_width(pp, colour_type, bit_depth) current returns the same number
3068 * every time, so just use a macro: 3068 * every time, so just use a macro:
3069 */ 3069 */
3070#define transform_width(pp, colour_type, bit_depth) TRANSFORM_WIDTH 3070#define transform_width(pp, colour_type, bit_depth) TRANSFORM_WIDTH
3071 3071
3072static png_uint_32 3072static png_uint_32
3073transform_height(png_structp pp, png_byte colour_type, png_byte bit_depth) 3073transform_height(png_structp pp, png_byte colour_type, png_byte bit_depth)
3074{ 3074{
3075 switch (bit_size(pp, colour_type, bit_depth)) 3075 switch (bit_size(pp, colour_type, bit_depth))
3076 { 3076 {
3077 case 1: 3077 case 1:
3078 case 2: 3078 case 2:
3079 case 4: 3079 case 4:
3080 return 1; /* Total of 128 pixels */ 3080 return 1; /* Total of 128 pixels */
3081 3081
3082 case 8: 3082 case 8:
3083 return 2; /* Total of 256 pixels/bytes */ 3083 return 2; /* Total of 256 pixels/bytes */
3084 3084
3085 case 16: 3085 case 16:
3086 return 512; /* Total of 65536 pixels */ 3086 return 512; /* Total of 65536 pixels */
3087 3087
3088 case 24: 3088 case 24:
3089 case 32: 3089 case 32:
3090 return 512; /* 65536 pixels */ 3090 return 512; /* 65536 pixels */
3091 3091
3092 case 48: 3092 case 48:
3093 case 64: 3093 case 64:
3094 return 2048;/* 4 x 65536 pixels. */ 3094 return 2048;/* 4 x 65536 pixels. */
3095# define TRANSFORM_HEIGHTMAX 2048 3095# define TRANSFORM_HEIGHTMAX 2048
3096 3096
3097 default: 3097 default:
3098 return 0; /* Error, will be caught later */ 3098 return 0; /* Error, will be caught later */
3099 } 3099 }
3100} 3100}
3101 3101
3102/* The following can only be defined here, now we have the definitions 3102/* The following can only be defined here, now we have the definitions
3103 * of the transform image sizes. 3103 * of the transform image sizes.
3104 */ 3104 */
3105static png_uint_32 3105static png_uint_32
3106standard_width(png_structp pp, png_uint_32 id) 3106standard_width(png_structp pp, png_uint_32 id)
3107{ 3107{
3108 png_uint_32 width = WIDTH_FROM_ID(id); 3108 png_uint_32 width = WIDTH_FROM_ID(id);
3109 UNUSED(pp) 3109 UNUSED(pp)
3110 3110
3111 if (width == 0) 3111 if (width == 0)
3112 width = transform_width(pp, COL_FROM_ID(id), DEPTH_FROM_ID(id)); 3112 width = transform_width(pp, COL_FROM_ID(id), DEPTH_FROM_ID(id));
3113 3113
3114 return width; 3114 return width;
3115} 3115}
3116 3116
3117static png_uint_32 3117static png_uint_32
3118standard_height(png_structp pp, png_uint_32 id) 3118standard_height(png_structp pp, png_uint_32 id)
3119{ 3119{
3120 png_uint_32 height = HEIGHT_FROM_ID(id); 3120 png_uint_32 height = HEIGHT_FROM_ID(id);
3121 3121
3122 if (height == 0) 3122 if (height == 0)
3123 height = transform_height(pp, COL_FROM_ID(id), DEPTH_FROM_ID(id)); 3123 height = transform_height(pp, COL_FROM_ID(id), DEPTH_FROM_ID(id));
3124 3124
3125 return height; 3125 return height;
3126} 3126}
3127 3127
3128static png_uint_32 3128static png_uint_32
3129standard_rowsize(png_structp pp, png_uint_32 id) 3129standard_rowsize(png_structp pp, png_uint_32 id)
3130{ 3130{
3131 png_uint_32 width = standard_width(pp, id); 3131 png_uint_32 width = standard_width(pp, id);
3132 3132
3133 /* This won't overflow: */ 3133 /* This won't overflow: */
3134 width *= bit_size(pp, COL_FROM_ID(id), DEPTH_FROM_ID(id)); 3134 width *= bit_size(pp, COL_FROM_ID(id), DEPTH_FROM_ID(id));
3135 return (width + 7) / 8; 3135 return (width + 7) / 8;
3136} 3136}
3137 3137
3138static void 3138static void
3139transform_row(png_structp pp, png_byte buffer[TRANSFORM_ROWMAX], 3139transform_row(png_structp pp, png_byte buffer[TRANSFORM_ROWMAX],
3140 png_byte colour_type, png_byte bit_depth, png_uint_32 y) 3140 png_byte colour_type, png_byte bit_depth, png_uint_32 y)
3141{ 3141{
3142 png_uint_32 v = y << 7; 3142 png_uint_32 v = y << 7;
3143 png_uint_32 i = 0; 3143 png_uint_32 i = 0;
3144 3144
3145 switch (bit_size(pp, colour_type, bit_depth)) 3145 switch (bit_size(pp, colour_type, bit_depth))
3146 { 3146 {
3147 case 1: 3147 case 1:
3148 while (i<128/8) buffer[i] = v & 0xff, v += 17, ++i; 3148 while (i<128/8) buffer[i] = v & 0xff, v += 17, ++i;
3149 return; 3149 return;
3150 3150
3151 case 2: 3151 case 2:
3152 while (i<128/4) buffer[i] = v & 0xff, v += 33, ++i; 3152 while (i<128/4) buffer[i] = v & 0xff, v += 33, ++i;
3153 return; 3153 return;
3154 3154
3155 case 4: 3155 case 4:
3156 while (i<128/2) buffer[i] = v & 0xff, v += 65, ++i; 3156 while (i<128/2) buffer[i] = v & 0xff, v += 65, ++i;
3157 return; 3157 return;
3158 3158
3159 case 8: 3159 case 8:
3160 /* 256 bytes total, 128 bytes in each row set as follows: */ 3160 /* 256 bytes total, 128 bytes in each row set as follows: */
3161 while (i<128) buffer[i] = v & 0xff, ++v, ++i; 3161 while (i<128) buffer[i] = v & 0xff, ++v, ++i;
3162 return; 3162 return;
3163 3163
3164 case 16: 3164 case 16:
3165 /* Generate all 65536 pixel values in order, which includes the 8 bit 3165 /* Generate all 65536 pixel values in order, which includes the 8 bit
3166 * GA case as well as the 16 bit G case. 3166 * GA case as well as the 16 bit G case.
3167 */ 3167 */
3168 while (i<128) 3168 while (i<128)
3169 buffer[2*i] = (v>>8) & 0xff, buffer[2*i+1] = v & 0xff, ++v, ++i; 3169 buffer[2*i] = (v>>8) & 0xff, buffer[2*i+1] = v & 0xff, ++v, ++i;
3170 3170
3171 return; 3171 return;
3172 3172
3173 case 24: 3173 case 24:
3174 /* 65535 pixels, but rotate the values. */ 3174 /* 65535 pixels, but rotate the values. */
3175 while (i<128) 3175 while (i<128)
3176 { 3176 {
3177 /* Three bytes per pixel, r, g, b, make b by r^g */ 3177 /* Three bytes per pixel, r, g, b, make b by r^g */
3178 buffer[3*i+0] = (v >> 8) & 0xff; 3178 buffer[3*i+0] = (v >> 8) & 0xff;
3179 buffer[3*i+1] = v & 0xff; 3179 buffer[3*i+1] = v & 0xff;
3180 buffer[3*i+2] = ((v >> 8) ^ v) & 0xff; 3180 buffer[3*i+2] = ((v >> 8) ^ v) & 0xff;
3181 ++v; 3181 ++v;
3182 ++i; 3182 ++i;
3183 } 3183 }
3184 3184
3185 return; 3185 return;
3186 3186
3187 case 32: 3187 case 32:
3188 /* 65535 pixels, r, g, b, a; just replicate */ 3188 /* 65535 pixels, r, g, b, a; just replicate */
3189 while (i<128) 3189 while (i<128)
3190 { 3190 {
3191 buffer[4*i+0] = (v >> 8) & 0xff; 3191 buffer[4*i+0] = (v >> 8) & 0xff;
3192 buffer[4*i+1] = v & 0xff; 3192 buffer[4*i+1] = v & 0xff;
3193 buffer[4*i+2] = (v >> 8) & 0xff; 3193 buffer[4*i+2] = (v >> 8) & 0xff;
3194 buffer[4*i+3] = v & 0xff; 3194 buffer[4*i+3] = v & 0xff;
3195 ++v; 3195 ++v;
3196 ++i; 3196 ++i;
3197 } 3197 }
3198 3198
3199 return; 3199 return;
3200 3200
3201 case 48: 3201 case 48:
3202 /* y is maximum 2047, giving 4x65536 pixels, make 'r' increase by 1 at 3202 /* y is maximum 2047, giving 4x65536 pixels, make 'r' increase by 1 at
3203 * each pixel, g increase by 257 (0x101) and 'b' by 0x1111: 3203 * each pixel, g increase by 257 (0x101) and 'b' by 0x1111:
3204 */ 3204 */
3205 while (i<128) 3205 while (i<128)
3206 { 3206 {
3207 png_uint_32 t = v++; 3207 png_uint_32 t = v++;
3208 buffer[6*i+0] = (t >> 8) & 0xff; 3208 buffer[6*i+0] = (t >> 8) & 0xff;
3209 buffer[6*i+1] = t & 0xff; 3209 buffer[6*i+1] = t & 0xff;
3210 t *= 257; 3210 t *= 257;
3211 buffer[6*i+2] = (t >> 8) & 0xff; 3211 buffer[6*i+2] = (t >> 8) & 0xff;
3212 buffer[6*i+3] = t & 0xff; 3212 buffer[6*i+3] = t & 0xff;
3213 t *= 17; 3213 t *= 17;
3214 buffer[6*i+4] = (t >> 8) & 0xff; 3214 buffer[6*i+4] = (t >> 8) & 0xff;
3215 buffer[6*i+5] = t & 0xff; 3215 buffer[6*i+5] = t & 0xff;
3216 ++i; 3216 ++i;
3217 } 3217 }
3218 3218
3219 return; 3219 return;
3220 3220
3221 case 64: 3221 case 64:
3222 /* As above in the 32 bit case. */ 3222 /* As above in the 32 bit case. */
3223 while (i<128) 3223 while (i<128)
3224 { 3224 {
3225 png_uint_32 t = v++; 3225 png_uint_32 t = v++;
3226 buffer[8*i+0] = (t >> 8) & 0xff; 3226 buffer[8*i+0] = (t >> 8) & 0xff;
3227 buffer[8*i+1] = t & 0xff; 3227 buffer[8*i+1] = t & 0xff;
3228 buffer[8*i+4] = (t >> 8) & 0xff; 3228 buffer[8*i+4] = (t >> 8) & 0xff;
3229 buffer[8*i+5] = t & 0xff; 3229 buffer[8*i+5] = t & 0xff;
3230 t *= 257; 3230 t *= 257;
3231 buffer[8*i+2] = (t >> 8) & 0xff; 3231 buffer[8*i+2] = (t >> 8) & 0xff;
3232 buffer[8*i+3] = t & 0xff; 3232 buffer[8*i+3] = t & 0xff;
3233 buffer[8*i+6] = (t >> 8) & 0xff; 3233 buffer[8*i+6] = (t >> 8) & 0xff;
3234 buffer[8*i+7] = t & 0xff; 3234 buffer[8*i+7] = t & 0xff;
3235 ++i; 3235 ++i;
3236 } 3236 }
3237 return; 3237 return;
3238 3238
3239 default: 3239 default:
3240 break; 3240 break;
3241 } 3241 }
3242 3242
3243 png_error(pp, "internal error"); 3243 png_error(pp, "internal error");
3244} 3244}
3245 3245
3246/* This is just to do the right cast - could be changed to a function to check 3246/* This is just to do the right cast - could be changed to a function to check
3247 * 'bd' but there isn't much point. 3247 * 'bd' but there isn't much point.
3248 */ 3248 */
3249#define DEPTH(bd) ((png_byte)(1U << (bd))) 3249#define DEPTH(bd) ((png_byte)(1U << (bd)))
3250 3250
3251/* Make a standardized image given a an image colour type, bit depth and 3251/* Make a standardized image given a an image colour type, bit depth and
3252 * interlace type. The standard images have a very restricted range of 3252 * interlace type. The standard images have a very restricted range of
3253 * rows and heights and are used for testing transforms rather than image 3253 * rows and heights and are used for testing transforms rather than image
3254 * layout details. See make_size_images below for a way to make images 3254 * layout details. See make_size_images below for a way to make images
3255 * that test odd sizes along with the libpng interlace handling. 3255 * that test odd sizes along with the libpng interlace handling.
3256 */ 3256 */
3257static void 3257static void
3258make_transform_image(png_store* PNG_CONST ps, png_byte PNG_CONST colour_type, 3258make_transform_image(png_store* PNG_CONST ps, png_byte PNG_CONST colour_type,
3259 png_byte PNG_CONST bit_depth, int palette_number, int interlace_type, 3259 png_byte PNG_CONST bit_depth, int palette_number, int interlace_type,
3260 png_const_charp name) 3260 png_const_charp name)
3261{ 3261{
3262 context(ps, fault); 3262 context(ps, fault);
3263 3263
3264 Try 3264 Try
3265 { 3265 {
3266 png_infop pi; 3266 png_infop pi;
3267 png_structp pp = set_store_for_write(ps, &pi, name); 3267 png_structp pp = set_store_for_write(ps, &pi, name);
3268 png_uint_32 h; 3268 png_uint_32 h;
3269 3269
3270 /* In the event of a problem return control to the Catch statement below 3270 /* In the event of a problem return control to the Catch statement below
3271 * to do the clean up - it is not possible to 'return' directly from a Try 3271 * to do the clean up - it is not possible to 'return' directly from a Try
3272 * block. 3272 * block.
3273 */ 3273 */
3274 if (pp == NULL) 3274 if (pp == NULL)
3275 Throw ps; 3275 Throw ps;
3276 3276
3277 h = transform_height(pp, colour_type, bit_depth); 3277 h = transform_height(pp, colour_type, bit_depth);
3278 3278
3279 png_set_IHDR(pp, pi, transform_width(pp, colour_type, bit_depth), h, 3279 png_set_IHDR(pp, pi, transform_width(pp, colour_type, bit_depth), h,
3280 bit_depth, colour_type, interlace_type, 3280 bit_depth, colour_type, interlace_type,
3281 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); 3281 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
3282 3282
3283#ifdef PNG_TEXT_SUPPORTED 3283#ifdef PNG_TEXT_SUPPORTED
3284 { 3284 {
3285 static char key[] = "image name"; /* must be writeable */ 3285 static char key[] = "image name"; /* must be writeable */
3286 size_t pos; 3286 size_t pos;
3287 png_text text; 3287 png_text text;
3288 char copy[FILE_NAME_SIZE]; 3288 char copy[FILE_NAME_SIZE];
3289 3289
3290 /* Use a compressed text string to test the correct interaction of text 3290 /* Use a compressed text string to test the correct interaction of text
3291 * compression and IDAT compression. 3291 * compression and IDAT compression.
3292 */ 3292 */
3293 text.compression = PNG_TEXT_COMPRESSION_zTXt; 3293 text.compression = PNG_TEXT_COMPRESSION_zTXt;
3294 text.key = key; 3294 text.key = key;
3295 /* Yuck: the text must be writable! */ 3295 /* Yuck: the text must be writable! */
3296 pos = safecat(copy, sizeof copy, 0, ps->wname); 3296 pos = safecat(copy, sizeof copy, 0, ps->wname);
3297 text.text = copy; 3297 text.text = copy;
3298 text.text_length = pos; 3298 text.text_length = pos;
3299 text.itxt_length = 0; 3299 text.itxt_length = 0;
3300 text.lang = 0; 3300 text.lang = 0;
3301 text.lang_key = 0; 3301 text.lang_key = 0;
3302 3302
3303 png_set_text(pp, pi, &text, 1); 3303 png_set_text(pp, pi, &text, 1);
3304 } 3304 }
3305#endif 3305#endif
3306 3306
3307 if (colour_type == 3) /* palette */ 3307 if (colour_type == 3) /* palette */
3308 init_standard_palette(ps, pp, pi, 1U << bit_depth, 1/*do tRNS*/); 3308 init_standard_palette(ps, pp, pi, 1U << bit_depth, 1/*do tRNS*/);
3309 3309
3310 png_write_info(pp, pi); 3310 png_write_info(pp, pi);
3311 3311
3312 if (png_get_rowbytes(pp, pi) != 3312 if (png_get_rowbytes(pp, pi) !=
3313 transform_rowsize(pp, colour_type, bit_depth)) 3313 transform_rowsize(pp, colour_type, bit_depth))
3314 png_error(pp, "row size incorrect"); 3314 png_error(pp, "row size incorrect");
3315 3315
3316 else 3316 else
3317 { 3317 {
3318 /* Somewhat confusingly this must be called *after* png_write_info 3318 /* Somewhat confusingly this must be called *after* png_write_info
3319 * because if it is called before, the information in *pp has not been 3319 * because if it is called before, the information in *pp has not been
3320 * updated to reflect the interlaced image. 3320 * updated to reflect the interlaced image.
3321 */ 3321 */
3322 int npasses = png_set_interlace_handling(pp); 3322 int npasses = png_set_interlace_handling(pp);
3323 int pass; 3323 int pass;
3324 3324
3325 if (npasses != npasses_from_interlace_type(pp, interlace_type)) 3325 if (npasses != npasses_from_interlace_type(pp, interlace_type))
3326 png_error(pp, "write: png_set_interlace_handling failed"); 3326 png_error(pp, "write: png_set_interlace_handling failed");
3327 3327
3328 for (pass=0; pass<npasses; ++pass) 3328 for (pass=0; pass<npasses; ++pass)
3329 { 3329 {
3330 png_uint_32 y; 3330 png_uint_32 y;
3331 3331
3332 for (y=0; y<h; ++y) 3332 for (y=0; y<h; ++y)
3333 { 3333 {
3334 png_byte buffer[TRANSFORM_ROWMAX]; 3334 png_byte buffer[TRANSFORM_ROWMAX];
3335 3335
3336 transform_row(pp, buffer, colour_type, bit_depth, y); 3336 transform_row(pp, buffer, colour_type, bit_depth, y);
3337 png_write_row(pp, buffer); 3337 png_write_row(pp, buffer);
3338 } 3338 }
3339 } 3339 }
3340 } 3340 }
3341 3341
3342#ifdef PNG_TEXT_SUPPORTED 3342#ifdef PNG_TEXT_SUPPORTED
3343 { 3343 {
3344 static char key[] = "end marker"; 3344 static char key[] = "end marker";
3345 static char comment[] = "end"; 3345 static char comment[] = "end";
3346 png_text text; 3346 png_text text;
3347 3347
3348 /* Use a compressed text string to test the correct interaction of text 3348 /* Use a compressed text string to test the correct interaction of text
3349 * compression and IDAT compression. 3349 * compression and IDAT compression.
3350 */ 3350 */
3351 text.compression = PNG_TEXT_COMPRESSION_zTXt; 3351 text.compression = PNG_TEXT_COMPRESSION_zTXt;
3352 text.key = key; 3352 text.key = key;
3353 text.text = comment; 3353 text.text = comment;
3354 text.text_length = (sizeof comment)-1; 3354 text.text_length = (sizeof comment)-1;
3355 text.itxt_length = 0; 3355 text.itxt_length = 0;
3356 text.lang = 0; 3356 text.lang = 0;
3357 text.lang_key = 0; 3357 text.lang_key = 0;
3358 3358
3359 png_set_text(pp, pi, &text, 1); 3359 png_set_text(pp, pi, &text, 1);
3360 } 3360 }
3361#endif 3361#endif
3362 3362
3363 png_write_end(pp, pi); 3363 png_write_end(pp, pi);
3364 3364
3365 /* And store this under the appropriate id, then clean up. */ 3365 /* And store this under the appropriate id, then clean up. */
3366 store_storefile(ps, FILEID(colour_type, bit_depth, palette_number, 3366 store_storefile(ps, FILEID(colour_type, bit_depth, palette_number,
3367 interlace_type, 0, 0, 0)); 3367 interlace_type, 0, 0, 0));
3368 3368
3369 store_write_reset(ps); 3369 store_write_reset(ps);
3370 } 3370 }
3371 3371
3372 Catch(fault) 3372 Catch(fault)
3373 { 3373 {
3374 /* Use the png_store returned by the exception. This may help the compiler 3374 /* Use the png_store returned by the exception. This may help the compiler
3375 * because 'ps' is not used in this branch of the setjmp. Note that fault 3375 * because 'ps' is not used in this branch of the setjmp. Note that fault
3376 * and ps will always be the same value. 3376 * and ps will always be the same value.
3377 */ 3377 */
3378 store_write_reset(fault); 3378 store_write_reset(fault);
3379 } 3379 }
3380} 3380}
3381 3381
3382static void 3382static void
3383make_transform_images(png_store *ps) 3383make_transform_images(png_store *ps)
3384{ 3384{
3385 png_byte colour_type = 0; 3385 png_byte colour_type = 0;
3386 png_byte bit_depth = 0; 3386 png_byte bit_depth = 0;
3387 int palette_number = 0; 3387 int palette_number = 0;
3388 3388
3389 /* This is in case of errors. */ 3389 /* This is in case of errors. */
3390 safecat(ps->test, sizeof ps->test, 0, "make standard images"); 3390 safecat(ps->test, sizeof ps->test, 0, "make standard images");
3391 3391
3392 /* Use next_format to enumerate all the combinations we test, including 3392 /* Use next_format to enumerate all the combinations we test, including
3393 * generating multiple low bit depth palette images. 3393 * generating multiple low bit depth palette images.
3394 */ 3394 */
3395 while (next_format(&colour_type, &bit_depth, &palette_number)) 3395 while (next_format(&colour_type, &bit_depth, &palette_number))
3396 { 3396 {
3397 int interlace_type; 3397 int interlace_type;
3398 3398
3399 for (interlace_type = PNG_INTERLACE_NONE; 3399 for (interlace_type = PNG_INTERLACE_NONE;
3400 interlace_type < PNG_INTERLACE_LAST; ++interlace_type) 3400 interlace_type < PNG_INTERLACE_LAST; ++interlace_type)
3401 { 3401 {
3402 char name[FILE_NAME_SIZE]; 3402 char name[FILE_NAME_SIZE];
3403 3403
3404 standard_name(name, sizeof name, 0, colour_type, bit_depth, 3404 standard_name(name, sizeof name, 0, colour_type, bit_depth,
3405 palette_number, interlace_type, 0, 0, 0); 3405 palette_number, interlace_type, 0, 0, 0);
3406 make_transform_image(ps, colour_type, bit_depth, palette_number, 3406 make_transform_image(ps, colour_type, bit_depth, palette_number,
3407 interlace_type, name); 3407 interlace_type, name);
3408 } 3408 }
3409 } 3409 }
3410} 3410}
3411 3411
3412/* The following two routines use the PNG interlace support macros from 3412/* The following two routines use the PNG interlace support macros from
3413 * png.h to interlace or deinterlace rows. 3413 * png.h to interlace or deinterlace rows.
3414 */ 3414 */
3415static void 3415static void
3416interlace_row(png_bytep buffer, png_const_bytep imageRow, 3416interlace_row(png_bytep buffer, png_const_bytep imageRow,
3417 unsigned int pixel_size, png_uint_32 w, int pass) 3417 unsigned int pixel_size, png_uint_32 w, int pass)
3418{ 3418{
3419 png_uint_32 xin, xout, xstep; 3419 png_uint_32 xin, xout, xstep;
3420 3420
3421 /* Note that this can, trivially, be optimized to a memcpy on pass 7, the 3421 /* Note that this can, trivially, be optimized to a memcpy on pass 7, the
3422 * code is presented this way to make it easier to understand. In practice 3422 * code is presented this way to make it easier to understand. In practice
3423 * consult the code in the libpng source to see other ways of doing this. 3423 * consult the code in the libpng source to see other ways of doing this.
3424 */ 3424 */
3425 xin = PNG_PASS_START_COL(pass); 3425 xin = PNG_PASS_START_COL(pass);
3426 xstep = 1U<<PNG_PASS_COL_SHIFT(pass); 3426 xstep = 1U<<PNG_PASS_COL_SHIFT(pass);
3427 3427
3428 for (xout=0; xin<w; xin+=xstep) 3428 for (xout=0; xin<w; xin+=xstep)
3429 { 3429 {
3430 pixel_copy(buffer, xout, imageRow, xin, pixel_size); 3430 pixel_copy(buffer, xout, imageRow, xin, pixel_size);
3431 ++xout; 3431 ++xout;
3432 } 3432 }
3433} 3433}
3434 3434
3435static void 3435static void
3436deinterlace_row(png_bytep buffer, png_const_bytep row, 3436deinterlace_row(png_bytep buffer, png_const_bytep row,
3437 unsigned int pixel_size, png_uint_32 w, int pass) 3437 unsigned int pixel_size, png_uint_32 w, int pass)
3438{ 3438{
3439 /* The inverse of the above, 'row' is part of row 'y' of the output image, 3439 /* The inverse of the above, 'row' is part of row 'y' of the output image,
3440 * in 'buffer'. The image is 'w' wide and this is pass 'pass', distribute 3440 * in 'buffer'. The image is 'w' wide and this is pass 'pass', distribute
3441 * the pixels of row into buffer and return the number written (to allow 3441 * the pixels of row into buffer and return the number written (to allow
3442 * this to be checked). 3442 * this to be checked).
3443 */ 3443 */
3444 png_uint_32 xin, xout, xstep; 3444 png_uint_32 xin, xout, xstep;
3445 3445
3446 xout = PNG_PASS_START_COL(pass); 3446 xout = PNG_PASS_START_COL(pass);
3447 xstep = 1U<<PNG_PASS_COL_SHIFT(pass); 3447 xstep = 1U<<PNG_PASS_COL_SHIFT(pass);
3448 3448
3449 for (xin=0; xout<w; xout+=xstep) 3449 for (xin=0; xout<w; xout+=xstep)
3450 { 3450 {
3451 pixel_copy(buffer, xout, row, xin, pixel_size); 3451 pixel_copy(buffer, xout, row, xin, pixel_size);
3452 ++xin; 3452 ++xin;
3453 } 3453 }
3454} 3454}
3455 3455
3456/* Build a single row for the 'size' test images; this fills in only the 3456/* Build a single row for the 'size' test images; this fills in only the
3457 * first bit_width bits of the sample row. 3457 * first bit_width bits of the sample row.
3458 */ 3458 */
3459static void 3459static void
3460size_row(png_byte buffer[SIZE_ROWMAX], png_uint_32 bit_width, png_uint_32 y) 3460size_row(png_byte buffer[SIZE_ROWMAX], png_uint_32 bit_width, png_uint_32 y)
3461{ 3461{
3462 /* height is in the range 1 to 16, so: */ 3462 /* height is in the range 1 to 16, so: */
3463 y = ((y & 1) << 7) + ((y & 2) << 6) + ((y & 4) << 5) + ((y & 8) << 4); 3463 y = ((y & 1) << 7) + ((y & 2) << 6) + ((y & 4) << 5) + ((y & 8) << 4);
3464 /* the following ensures bits are set in small images: */ 3464 /* the following ensures bits are set in small images: */
3465 y ^= 0xA5; 3465 y ^= 0xA5;
3466 3466
3467 while (bit_width >= 8) 3467 while (bit_width >= 8)
3468 *buffer++ = (png_byte)y++, bit_width -= 8; 3468 *buffer++ = (png_byte)y++, bit_width -= 8;
3469 3469
3470 /* There may be up to 7 remaining bits, these go in the most significant 3470 /* There may be up to 7 remaining bits, these go in the most significant
3471 * bits of the byte. 3471 * bits of the byte.
3472 */ 3472 */
3473 if (bit_width > 0) 3473 if (bit_width > 0)
3474 { 3474 {
3475 png_uint_32 mask = (1U<<(8-bit_width))-1; 3475 png_uint_32 mask = (1U<<(8-bit_width))-1;
3476 *buffer = (png_byte)((*buffer & mask) | (y & ~mask)); 3476 *buffer = (png_byte)((*buffer & mask) | (y & ~mask));
3477 } 3477 }
3478} 3478}
3479 3479
3480static void 3480static void
3481make_size_image(png_store* PNG_CONST ps, png_byte PNG_CONST colour_type, 3481make_size_image(png_store* PNG_CONST ps, png_byte PNG_CONST colour_type,
3482 png_byte PNG_CONST bit_depth, int PNG_CONST interlace_type, 3482 png_byte PNG_CONST bit_depth, int PNG_CONST interlace_type,
3483 png_uint_32 PNG_CONST w, png_uint_32 PNG_CONST h, 3483 png_uint_32 PNG_CONST w, png_uint_32 PNG_CONST h,
3484 int PNG_CONST do_interlace) 3484 int PNG_CONST do_interlace)
3485{ 3485{
3486 context(ps, fault); 3486 context(ps, fault);
3487 3487
3488 Try 3488 Try
3489 { 3489 {
3490 png_infop pi; 3490 png_infop pi;
3491 png_structp pp; 3491 png_structp pp;
3492 unsigned int pixel_size; 3492 unsigned int pixel_size;
3493 3493
3494 /* Make a name and get an appropriate id for the store: */ 3494 /* Make a name and get an appropriate id for the store: */
3495 char name[FILE_NAME_SIZE]; 3495 char name[FILE_NAME_SIZE];
3496 PNG_CONST png_uint_32 id = FILEID(colour_type, bit_depth, 0/*palette*/, 3496 PNG_CONST png_uint_32 id = FILEID(colour_type, bit_depth, 0/*palette*/,
3497 interlace_type, w, h, do_interlace); 3497 interlace_type, w, h, do_interlace);
3498 3498
3499 standard_name_from_id(name, sizeof name, 0, id); 3499 standard_name_from_id(name, sizeof name, 0, id);
3500 pp = set_store_for_write(ps, &pi, name); 3500 pp = set_store_for_write(ps, &pi, name);
3501 3501
3502 /* In the event of a problem return control to the Catch statement below 3502 /* In the event of a problem return control to the Catch statement below
3503 * to do the clean up - it is not possible to 'return' directly from a Try 3503 * to do the clean up - it is not possible to 'return' directly from a Try
3504 * block. 3504 * block.
3505 */ 3505 */
3506 if (pp == NULL) 3506 if (pp == NULL)
3507 Throw ps; 3507 Throw ps;
3508 3508
3509 png_set_IHDR(pp, pi, w, h, bit_depth, colour_type, interlace_type, 3509 png_set_IHDR(pp, pi, w, h, bit_depth, colour_type, interlace_type,
3510 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); 3510 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
3511 3511
3512 if (colour_type == 3) /* palette */ 3512 if (colour_type == 3) /* palette */
3513 init_standard_palette(ps, pp, pi, 1U << bit_depth, 0/*do tRNS*/); 3513 init_standard_palette(ps, pp, pi, 1U << bit_depth, 0/*do tRNS*/);
3514 3514
3515 png_write_info(pp, pi); 3515 png_write_info(pp, pi);
3516 3516
3517 /* Calculate the bit size, divide by 8 to get the byte size - this won't 3517 /* Calculate the bit size, divide by 8 to get the byte size - this won't
3518 * overflow because we know the w values are all small enough even for 3518 * overflow because we know the w values are all small enough even for
3519 * a system where 'unsigned int' is only 16 bits. 3519 * a system where 'unsigned int' is only 16 bits.
3520 */ 3520 */
3521 pixel_size = bit_size(pp, colour_type, bit_depth); 3521 pixel_size = bit_size(pp, colour_type, bit_depth);
3522 if (png_get_rowbytes(pp, pi) != ((w * pixel_size) + 7) / 8) 3522 if (png_get_rowbytes(pp, pi) != ((w * pixel_size) + 7) / 8)
3523 png_error(pp, "row size incorrect"); 3523 png_error(pp, "row size incorrect");
3524 3524
3525 else 3525 else
3526 { 3526 {
3527 int npasses = npasses_from_interlace_type(pp, interlace_type); 3527 int npasses = npasses_from_interlace_type(pp, interlace_type);
3528 png_uint_32 y; 3528 png_uint_32 y;
3529 int pass; 3529 int pass;
3530 png_byte image[16][SIZE_ROWMAX]; 3530 png_byte image[16][SIZE_ROWMAX];
3531 3531
3532 /* To help consistent error detection make the parts of this buffer 3532 /* To help consistent error detection make the parts of this buffer
3533 * that aren't set below all '1': 3533 * that aren't set below all '1':
3534 */ 3534 */
3535 memset(image, 0xff, sizeof image); 3535 memset(image, 0xff, sizeof image);
3536 3536
3537 if (!do_interlace && npasses != png_set_interlace_handling(pp)) 3537 if (!do_interlace && npasses != png_set_interlace_handling(pp))
3538 png_error(pp, "write: png_set_interlace_handling failed"); 3538 png_error(pp, "write: png_set_interlace_handling failed");
3539 3539
3540 /* Prepare the whole image first to avoid making it 7 times: */ 3540 /* Prepare the whole image first to avoid making it 7 times: */
3541 for (y=0; y<h; ++y) 3541 for (y=0; y<h; ++y)
3542 size_row(image[y], w * pixel_size, y); 3542 size_row(image[y], w * pixel_size, y);
3543 3543
3544 for (pass=0; pass<npasses; ++pass) 3544 for (pass=0; pass<npasses; ++pass)
3545 { 3545 {
3546 /* The following two are for checking the macros: */ 3546 /* The following two are for checking the macros: */
3547 PNG_CONST png_uint_32 wPass = PNG_PASS_COLS(w, pass); 3547 PNG_CONST png_uint_32 wPass = PNG_PASS_COLS(w, pass);
3548 3548
3549 /* If do_interlace is set we don't call png_write_row for every 3549 /* If do_interlace is set we don't call png_write_row for every
3550 * row because some of them are empty. In fact, for a 1x1 image, 3550 * row because some of them are empty. In fact, for a 1x1 image,
3551 * most of them are empty! 3551 * most of them are empty!
3552 */ 3552 */
3553 for (y=0; y<h; ++y) 3553 for (y=0; y<h; ++y)
3554 { 3554 {
3555 png_const_bytep row = image[y]; 3555 png_const_bytep row = image[y];
3556 png_byte tempRow[SIZE_ROWMAX]; 3556 png_byte tempRow[SIZE_ROWMAX];
3557 3557
3558 /* If do_interlace *and* the image is interlaced we 3558 /* If do_interlace *and* the image is interlaced we
3559 * need a reduced interlace row; this may be reduced 3559 * need a reduced interlace row; this may be reduced
3560 * to empty. 3560 * to empty.
3561 */ 3561 */
3562 if (do_interlace && interlace_type == PNG_INTERLACE_ADAM7) 3562 if (do_interlace && interlace_type == PNG_INTERLACE_ADAM7)
3563 { 3563 {
3564 /* The row must not be written if it doesn't exist, notice 3564 /* The row must not be written if it doesn't exist, notice
3565 * that there are two conditions here, either the row isn't 3565 * that there are two conditions here, either the row isn't
3566 * ever in the pass or the row would be but isn't wide 3566 * ever in the pass or the row would be but isn't wide
3567 * enough to contribute any pixels. In fact the wPass test 3567 * enough to contribute any pixels. In fact the wPass test
3568 * can be used to skip the whole y loop in this case. 3568 * can be used to skip the whole y loop in this case.
3569 */ 3569 */
3570 if (PNG_ROW_IN_INTERLACE_PASS(y, pass) && wPass > 0) 3570 if (PNG_ROW_IN_INTERLACE_PASS(y, pass) && wPass > 0)
3571 { 3571 {
3572 /* Set to all 1's for error detection (libpng tends to 3572 /* Set to all 1's for error detection (libpng tends to
3573 * set unset things to 0). 3573 * set unset things to 0).
3574 */ 3574 */
3575 memset(tempRow, 0xff, sizeof tempRow); 3575 memset(tempRow, 0xff, sizeof tempRow);
3576 interlace_row(tempRow, row, pixel_size, w, pass); 3576 interlace_row(tempRow, row, pixel_size, w, pass);
3577 row = tempRow; 3577 row = tempRow;
3578 } 3578 }
3579 else 3579 else
3580 continue; 3580 continue;
3581 } 3581 }
3582 3582
3583 /* Only get to here if the row has some pixels in it. */ 3583 /* Only get to here if the row has some pixels in it. */
3584 png_write_row(pp, row); 3584 png_write_row(pp, row);
3585 } 3585 }
3586 } 3586 }
3587 } 3587 }
3588 3588
3589 png_write_end(pp, pi); 3589 png_write_end(pp, pi);
3590 3590
3591 /* And store this under the appropriate id, then clean up. */ 3591 /* And store this under the appropriate id, then clean up. */
3592 store_storefile(ps, id); 3592 store_storefile(ps, id);
3593 3593
3594 store_write_reset(ps); 3594 store_write_reset(ps);
3595 } 3595 }
3596 3596
3597 Catch(fault) 3597 Catch(fault)
3598 { 3598 {
3599 /* Use the png_store returned by the exception. This may help the compiler 3599 /* Use the png_store returned by the exception. This may help the compiler
3600 * because 'ps' is not used in this branch of the setjmp. Note that fault 3600 * because 'ps' is not used in this branch of the setjmp. Note that fault
3601 * and ps will always be the same value. 3601 * and ps will always be the same value.
3602 */ 3602 */
3603 store_write_reset(fault); 3603 store_write_reset(fault);
3604 } 3604 }
3605} 3605}
3606 3606
3607static void 3607static void
3608make_size(png_store* PNG_CONST ps, png_byte PNG_CONST colour_type, int bdlo, 3608make_size(png_store* PNG_CONST ps, png_byte PNG_CONST colour_type, int bdlo,
3609 int PNG_CONST bdhi) 3609 int PNG_CONST bdhi)
3610{ 3610{
3611 for (; bdlo <= bdhi; ++bdlo) 3611 for (; bdlo <= bdhi; ++bdlo)
3612 { 3612 {
3613 png_uint_32 width; 3613 png_uint_32 width;
3614 3614
3615 for (width = 1; width <= 16; ++width) 3615 for (width = 1; width <= 16; ++width)
3616 { 3616 {
3617 png_uint_32 height; 3617 png_uint_32 height;
3618 3618
3619 for (height = 1; height <= 16; ++height) 3619 for (height = 1; height <= 16; ++height)
3620 { 3620 {
3621 /* The four combinations of DIY interlace and interlace or not - 3621 /* The four combinations of DIY interlace and interlace or not -
3622 * no interlace + DIY should be identical to no interlace with 3622 * no interlace + DIY should be identical to no interlace with
3623 * libpng doing it. 3623 * libpng doing it.
3624 */ 3624 */
3625 make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_NONE, 3625 make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_NONE,
3626 width, height, 0); 3626 width, height, 0);
3627 make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_NONE, 3627 make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_NONE,
3628 width, height, 1); 3628 width, height, 1);
3629 make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_ADAM7, 3629 make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_ADAM7,
3630 width, height, 0); 3630 width, height, 0);
3631 make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_ADAM7, 3631 make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_ADAM7,
3632 width, height, 1); 3632 width, height, 1);
3633 } 3633 }
3634 } 3634 }
3635 } 3635 }
3636} 3636}
3637 3637
3638static void 3638static void
3639make_size_images(png_store *ps) 3639make_size_images(png_store *ps)
3640{ 3640{
3641 /* This is in case of errors. */ 3641 /* This is in case of errors. */
3642 safecat(ps->test, sizeof ps->test, 0, "make size images"); 3642 safecat(ps->test, sizeof ps->test, 0, "make size images");
3643 3643
3644 /* Arguments are colour_type, low bit depth, high bit depth 3644 /* Arguments are colour_type, low bit depth, high bit depth
3645 */ 3645 */
3646 make_size(ps, 0, 0, WRITE_BDHI); 3646 make_size(ps, 0, 0, WRITE_BDHI);
3647 make_size(ps, 2, 3, WRITE_BDHI); 3647 make_size(ps, 2, 3, WRITE_BDHI);
3648 make_size(ps, 3, 0, 3 /*palette: max 8 bits*/); 3648 make_size(ps, 3, 0, 3 /*palette: max 8 bits*/);
3649 make_size(ps, 4, 3, WRITE_BDHI); 3649 make_size(ps, 4, 3, WRITE_BDHI);
3650 make_size(ps, 6, 3, WRITE_BDHI); 3650 make_size(ps, 6, 3, WRITE_BDHI);
3651} 3651}
3652 3652
3653/* Return a row based on image id and 'y' for checking: */ 3653/* Return a row based on image id and 'y' for checking: */
3654static void 3654static void
3655standard_row(png_structp pp, png_byte std[STANDARD_ROWMAX], png_uint_32 id, 3655standard_row(png_structp pp, png_byte std[STANDARD_ROWMAX], png_uint_32 id,
3656 png_uint_32 y) 3656 png_uint_32 y)
3657{ 3657{
3658 if (WIDTH_FROM_ID(id) == 0) 3658 if (WIDTH_FROM_ID(id) == 0)
3659 transform_row(pp, std, COL_FROM_ID(id), DEPTH_FROM_ID(id), y); 3659 transform_row(pp, std, COL_FROM_ID(id), DEPTH_FROM_ID(id), y);
3660 else 3660 else
3661 size_row(std, WIDTH_FROM_ID(id) * bit_size(pp, COL_FROM_ID(id), 3661 size_row(std, WIDTH_FROM_ID(id) * bit_size(pp, COL_FROM_ID(id),
3662 DEPTH_FROM_ID(id)), y); 3662 DEPTH_FROM_ID(id)), y);
3663} 3663}
3664 3664
3665/* Tests - individual test cases */ 3665/* Tests - individual test cases */
3666/* Like 'make_standard' but errors are deliberately introduced into the calls 3666/* Like 'make_standard' but errors are deliberately introduced into the calls
3667 * to ensure that they get detected - it should not be possible to write an 3667 * to ensure that they get detected - it should not be possible to write an
3668 * invalid image with libpng! 3668 * invalid image with libpng!
3669 */ 3669 */
3670#ifdef PNG_WARNINGS_SUPPORTED 3670#ifdef PNG_WARNINGS_SUPPORTED
3671static void 3671static void
3672sBIT0_error_fn(png_structp pp, png_infop pi) 3672sBIT0_error_fn(png_structp pp, png_infop pi)
3673{ 3673{
3674 /* 0 is invalid... */ 3674 /* 0 is invalid... */
3675 png_color_8 bad; 3675 png_color_8 bad;
3676 bad.red = bad.green = bad.blue = bad.gray = bad.alpha = 0; 3676 bad.red = bad.green = bad.blue = bad.gray = bad.alpha = 0;
3677 png_set_sBIT(pp, pi, &bad); 3677 png_set_sBIT(pp, pi, &bad);
3678} 3678}
3679 3679
3680static void 3680static void
3681sBIT_error_fn(png_structp pp, png_infop pi) 3681sBIT_error_fn(png_structp pp, png_infop pi)
3682{ 3682{
3683 png_byte bit_depth; 3683 png_byte bit_depth;
3684 png_color_8 bad; 3684 png_color_8 bad;
3685 3685
3686 if (png_get_color_type(pp, pi) == PNG_COLOR_TYPE_PALETTE) 3686 if (png_get_color_type(pp, pi) == PNG_COLOR_TYPE_PALETTE)
3687 bit_depth = 8; 3687 bit_depth = 8;
3688 3688
3689 else 3689 else
3690 bit_depth = png_get_bit_depth(pp, pi); 3690 bit_depth = png_get_bit_depth(pp, pi);
3691 3691
3692 /* Now we know the bit depth we can easily generate an invalid sBIT entry */ 3692 /* Now we know the bit depth we can easily generate an invalid sBIT entry */
3693 bad.red = bad.green = bad.blue = bad.gray = bad.alpha = 3693 bad.red = bad.green = bad.blue = bad.gray = bad.alpha =
3694 (png_byte)(bit_depth+1); 3694 (png_byte)(bit_depth+1);
3695 png_set_sBIT(pp, pi, &bad); 3695 png_set_sBIT(pp, pi, &bad);
3696} 3696}
3697 3697
3698static PNG_CONST struct 3698static PNG_CONST struct
3699{ 3699{
3700 void (*fn)(png_structp, png_infop); 3700 void (*fn)(png_structp, png_infop);
3701 PNG_CONST char *msg; 3701 PNG_CONST char *msg;
3702 unsigned int warning :1; /* the error is a warning... */ 3702 unsigned int warning :1; /* the error is a warning... */
3703} error_test[] = 3703} error_test[] =
3704 { 3704 {
3705 /* no warnings makes these errors undetectable. */ 3705 /* no warnings makes these errors undetectable. */
3706 { sBIT0_error_fn, "sBIT(0): failed to detect error", 1 }, 3706 { sBIT0_error_fn, "sBIT(0): failed to detect error", 1 },
3707 { sBIT_error_fn, "sBIT(too big): failed to detect error", 1 }, 3707 { sBIT_error_fn, "sBIT(too big): failed to detect error", 1 },
3708 }; 3708 };
3709 3709
3710static void 3710static void
3711make_error(png_store* volatile psIn, png_byte PNG_CONST colour_type, 3711make_error(png_store* volatile psIn, png_byte PNG_CONST colour_type,
3712 png_byte bit_depth, int interlace_type, int test, png_const_charp name) 3712 png_byte bit_depth, int interlace_type, int test, png_const_charp name)
3713{ 3713{
3714 png_store * volatile ps = psIn; 3714 png_store * volatile ps = psIn;
3715 3715
3716 context(ps, fault); 3716 context(ps, fault);
3717 3717
3718 Try 3718 Try
3719 { 3719 {
3720 png_structp pp; 3720 png_structp pp;
3721 png_infop pi; 3721 png_infop pi;
3722 3722
3723 pp = set_store_for_write(ps, &pi, name); 3723 pp = set_store_for_write(ps, &pi, name);
3724 3724
3725 if (pp == NULL) 3725 if (pp == NULL)
3726 Throw ps; 3726 Throw ps;
3727 3727
3728 png_set_IHDR(pp, pi, transform_width(pp, colour_type, bit_depth), 3728 png_set_IHDR(pp, pi, transform_width(pp, colour_type, bit_depth),
3729 transform_height(pp, colour_type, bit_depth), bit_depth, colour_type, 3729 transform_height(pp, colour_type, bit_depth), bit_depth, colour_type,
3730 interlace_type, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); 3730 interlace_type, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
3731 3731
3732 if (colour_type == 3) /* palette */ 3732 if (colour_type == 3) /* palette */
3733 init_standard_palette(ps, pp, pi, 1U << bit_depth, 0/*do tRNS*/); 3733 init_standard_palette(ps, pp, pi, 1U << bit_depth, 0/*do tRNS*/);
3734 3734
3735 /* Time for a few errors; these are in various optional chunks, the 3735 /* Time for a few errors; these are in various optional chunks, the
3736 * standard tests test the standard chunks pretty well. 3736 * standard tests test the standard chunks pretty well.
3737 */ 3737 */
3738# define exception__prev exception_prev_1 3738# define exception__prev exception_prev_1
3739# define exception__env exception_env_1 3739# define exception__env exception_env_1
3740 Try 3740 Try
3741 { 3741 {
3742 /* Expect this to throw: */ 3742 /* Expect this to throw: */
3743 ps->expect_error = !error_test[test].warning; 3743 ps->expect_error = !error_test[test].warning;
3744 ps->expect_warning = error_test[test].warning; 3744 ps->expect_warning = error_test[test].warning;
3745 ps->saw_warning = 0; 3745 ps->saw_warning = 0;
3746 error_test[test].fn(pp, pi); 3746 error_test[test].fn(pp, pi);
3747 3747
3748 /* Normally the error is only detected here: */ 3748 /* Normally the error is only detected here: */
3749 png_write_info(pp, pi); 3749 png_write_info(pp, pi);
3750 3750
3751 /* And handle the case where it was only a warning: */ 3751 /* And handle the case where it was only a warning: */
3752 if (ps->expect_warning && ps->saw_warning) 3752 if (ps->expect_warning && ps->saw_warning)
3753 Throw ps; 3753 Throw ps;
3754 3754
3755 /* If we get here there is a problem, we have success - no error or 3755 /* If we get here there is a problem, we have success - no error or
3756 * no warning - when we shouldn't have success. Log an error. 3756 * no warning - when we shouldn't have success. Log an error.
3757 */ 3757 */
3758 store_log(ps, pp, error_test[test].msg, 1 /*error*/); 3758 store_log(ps, pp, error_test[test].msg, 1 /*error*/);
3759 } 3759 }
3760 3760
3761 Catch (fault) 3761 Catch (fault)
3762 ps = fault; /* expected exit, make sure ps is not clobbered */ 3762 ps = fault; /* expected exit, make sure ps is not clobbered */
3763#undef exception__prev 3763#undef exception__prev
3764#undef exception__env 3764#undef exception__env
3765 3765
3766 /* And clear these flags */ 3766 /* And clear these flags */
3767 ps->expect_error = 0; 3767 ps->expect_error = 0;
3768 ps->expect_warning = 0; 3768 ps->expect_warning = 0;
3769 3769
3770 /* Now write the whole image, just to make sure that the detected, or 3770 /* Now write the whole image, just to make sure that the detected, or
3771 * undetected, errro has not created problems inside libpng. 3771 * undetected, errro has not created problems inside libpng.
3772 */ 3772 */
3773 if (png_get_rowbytes(pp, pi) != 3773 if (png_get_rowbytes(pp, pi) !=
3774 transform_rowsize(pp, colour_type, bit_depth)) 3774 transform_rowsize(pp, colour_type, bit_depth))
3775 png_error(pp, "row size incorrect"); 3775 png_error(pp, "row size incorrect");
3776 3776
3777 else 3777 else
3778 { 3778 {
3779 png_uint_32 h = transform_height(pp, colour_type, bit_depth); 3779 png_uint_32 h = transform_height(pp, colour_type, bit_depth);
3780 int npasses = png_set_interlace_handling(pp); 3780 int npasses = png_set_interlace_handling(pp);
3781 int pass; 3781 int pass;
3782 3782
3783 if (npasses != npasses_from_interlace_type(pp, interlace_type)) 3783 if (npasses != npasses_from_interlace_type(pp, interlace_type))
3784 png_error(pp, "write: png_set_interlace_handling failed"); 3784 png_error(pp, "write: png_set_interlace_handling failed");
3785 3785
3786 for (pass=0; pass<npasses; ++pass) 3786 for (pass=0; pass<npasses; ++pass)
3787 { 3787 {
3788 png_uint_32 y; 3788 png_uint_32 y;
3789 3789
3790 for (y=0; y<h; ++y) 3790 for (y=0; y<h; ++y)
3791 { 3791 {
3792 png_byte buffer[TRANSFORM_ROWMAX]; 3792 png_byte buffer[TRANSFORM_ROWMAX];
3793 3793
3794 transform_row(pp, buffer, colour_type, bit_depth, y); 3794 transform_row(pp, buffer, colour_type, bit_depth, y);
3795 png_write_row(pp, buffer); 3795 png_write_row(pp, buffer);
3796 } 3796 }
3797 } 3797 }
3798 } 3798 }
3799 3799
3800 png_write_end(pp, pi); 3800 png_write_end(pp, pi);
3801 3801
3802 /* The following deletes the file that was just written. */ 3802 /* The following deletes the file that was just written. */
3803 store_write_reset(ps); 3803 store_write_reset(ps);
3804 } 3804 }
3805 3805
3806 Catch(fault) 3806 Catch(fault)
3807 { 3807 {
3808 store_write_reset(fault); 3808 store_write_reset(fault);
3809 } 3809 }
3810} 3810}
3811 3811
3812static int 3812static int
3813make_errors(png_modifier* PNG_CONST pm, png_byte PNG_CONST colour_type, 3813make_errors(png_modifier* PNG_CONST pm, png_byte PNG_CONST colour_type,
3814 int bdlo, int PNG_CONST bdhi) 3814 int bdlo, int PNG_CONST bdhi)
3815{ 3815{
3816 for (; bdlo <= bdhi; ++bdlo) 3816 for (; bdlo <= bdhi; ++bdlo)
3817 { 3817 {
3818 int interlace_type; 3818 int interlace_type;
3819 3819
3820 for (interlace_type = PNG_INTERLACE_NONE; 3820 for (interlace_type = PNG_INTERLACE_NONE;
3821 interlace_type < PNG_INTERLACE_LAST; ++interlace_type) 3821 interlace_type < PNG_INTERLACE_LAST; ++interlace_type)
3822 { 3822 {
3823 unsigned int test; 3823 unsigned int test;
3824 char name[FILE_NAME_SIZE]; 3824 char name[FILE_NAME_SIZE];
3825 3825
3826 standard_name(name, sizeof name, 0, colour_type, 1<<bdlo, 0, 3826 standard_name(name, sizeof name, 0, colour_type, 1<<bdlo, 0,
3827 interlace_type, 0, 0, 0); 3827 interlace_type, 0, 0, 0);
3828 3828
3829 for (test=0; test<(sizeof error_test)/(sizeof error_test[0]); ++test) 3829 for (test=0; test<(sizeof error_test)/(sizeof error_test[0]); ++test)
3830 { 3830 {
3831 make_error(&pm->this, colour_type, DEPTH(bdlo), interlace_type, 3831 make_error(&pm->this, colour_type, DEPTH(bdlo), interlace_type,
3832 test, name); 3832 test, name);
3833 3833
3834 if (fail(pm)) 3834 if (fail(pm))
3835 return 0; 3835 return 0;
3836 } 3836 }
3837 } 3837 }
3838 } 3838 }
3839 3839
3840 return 1; /* keep going */ 3840 return 1; /* keep going */
3841} 3841}
3842#endif 3842#endif
3843 3843
3844static void 3844static void
3845perform_error_test(png_modifier *pm) 3845perform_error_test(png_modifier *pm)
3846{ 3846{
3847#ifdef PNG_WARNINGS_SUPPORTED /* else there are no cases that work! */ 3847#ifdef PNG_WARNINGS_SUPPORTED /* else there are no cases that work! */
3848 /* Need to do this here because we just write in this test. */ 3848 /* Need to do this here because we just write in this test. */
3849 safecat(pm->this.test, sizeof pm->this.test, 0, "error test"); 3849 safecat(pm->this.test, sizeof pm->this.test, 0, "error test");
3850 3850
3851 if (!make_errors(pm, 0, 0, WRITE_BDHI)) 3851 if (!make_errors(pm, 0, 0, WRITE_BDHI))
3852 return; 3852 return;
3853 3853
3854 if (!make_errors(pm, 2, 3, WRITE_BDHI)) 3854 if (!make_errors(pm, 2, 3, WRITE_BDHI))
3855 return; 3855 return;
3856 3856
3857 if (!make_errors(pm, 3, 0, 3)) 3857 if (!make_errors(pm, 3, 0, 3))
3858 return; 3858 return;
3859 3859
3860 if (!make_errors(pm, 4, 3, WRITE_BDHI)) 3860 if (!make_errors(pm, 4, 3, WRITE_BDHI))
3861 return; 3861 return;
3862 3862
3863 if (!make_errors(pm, 6, 3, WRITE_BDHI)) 3863 if (!make_errors(pm, 6, 3, WRITE_BDHI))
3864 return; 3864 return;
3865#else 3865#else
3866 UNUSED(pm) 3866 UNUSED(pm)
3867#endif 3867#endif
3868} 3868}
3869 3869
3870/* This is just to validate the internal PNG formatting code - if this fails 3870/* This is just to validate the internal PNG formatting code - if this fails
3871 * then the warning messages the library outputs will probably be garbage. 3871 * then the warning messages the library outputs will probably be garbage.
3872 */ 3872 */
3873static void 3873static void
3874perform_formatting_test(png_store *volatile ps) 3874perform_formatting_test(png_store *volatile ps)
3875{ 3875{
3876#ifdef PNG_TIME_RFC1123_SUPPORTED 3876#ifdef PNG_TIME_RFC1123_SUPPORTED
3877 /* The handle into the formatting code is the RFC1123 support; this test does 3877 /* The handle into the formatting code is the RFC1123 support; this test does
3878 * nothing if that is compiled out. 3878 * nothing if that is compiled out.
3879 */ 3879 */
3880 context(ps, fault); 3880 context(ps, fault);
3881 3881
3882 Try 3882 Try
3883 { 3883 {
3884 png_const_charp correct = "29 Aug 2079 13:53:60 +0000"; 3884 png_const_charp correct = "29 Aug 2079 13:53:60 +0000";
3885 png_const_charp result; 3885 png_const_charp result;
3886 png_structp pp; 3886 png_structp pp;
3887 png_time pt; 3887 png_time pt;
3888 3888
3889 pp = set_store_for_write(ps, NULL, "libpng formatting test"); 3889 pp = set_store_for_write(ps, NULL, "libpng formatting test");
3890 3890
3891 if (pp == NULL) 3891 if (pp == NULL)
3892 Throw ps; 3892 Throw ps;
3893 3893
3894 3894
3895 /* Arbitrary settings: */ 3895 /* Arbitrary settings: */
3896 pt.year = 2079; 3896 pt.year = 2079;
3897 pt.month = 8; 3897 pt.month = 8;
3898 pt.day = 29; 3898 pt.day = 29;
3899 pt.hour = 13; 3899 pt.hour = 13;
3900 pt.minute = 53; 3900 pt.minute = 53;
3901 pt.second = 60; /* a leap second */ 3901 pt.second = 60; /* a leap second */
3902 3902
3903 result = png_convert_to_rfc1123(pp, &pt); 3903 result = png_convert_to_rfc1123(pp, &pt);
3904 3904
3905 if (result == NULL) 3905 if (result == NULL)
3906 png_error(pp, "png_convert_to_rfc1123 failed"); 3906 png_error(pp, "png_convert_to_rfc1123 failed");
3907 3907
3908 if (strcmp(result, correct) != 0) 3908 if (strcmp(result, correct) != 0)
3909 { 3909 {
3910 size_t pos = 0; 3910 size_t pos = 0;
3911 char msg[128]; 3911 char msg[128];
3912 3912
3913 pos = safecat(msg, sizeof msg, pos, "png_convert_to_rfc1123("); 3913 pos = safecat(msg, sizeof msg, pos, "png_convert_to_rfc1123(");
3914 pos = safecat(msg, sizeof msg, pos, correct); 3914 pos = safecat(msg, sizeof msg, pos, correct);
3915 pos = safecat(msg, sizeof msg, pos, ") returned: '"); 3915 pos = safecat(msg, sizeof msg, pos, ") returned: '");
3916 pos = safecat(msg, sizeof msg, pos, result); 3916 pos = safecat(msg, sizeof msg, pos, result);
3917 pos = safecat(msg, sizeof msg, pos, "'"); 3917 pos = safecat(msg, sizeof msg, pos, "'");
3918 3918
3919 png_error(pp, msg); 3919 png_error(pp, msg);
3920 } 3920 }
3921 3921
3922 store_write_reset(ps); 3922 store_write_reset(ps);
3923 } 3923 }
3924 3924
3925 Catch(fault) 3925 Catch(fault)
3926 { 3926 {
3927 store_write_reset(fault); 3927 store_write_reset(fault);
3928 } 3928 }
3929#else 3929#else
3930 UNUSED(ps) 3930 UNUSED(ps)
3931#endif 3931#endif
3932} 3932}
3933 3933
3934/* Because we want to use the same code in both the progressive reader and the 3934/* Because we want to use the same code in both the progressive reader and the
3935 * sequential reader it is necessary to deal with the fact that the progressive 3935 * sequential reader it is necessary to deal with the fact that the progressive
3936 * reader callbacks only have one parameter (png_get_progressive_ptr()), so this 3936 * reader callbacks only have one parameter (png_get_progressive_ptr()), so this
3937 * must contain all the test parameters and all the local variables directly 3937 * must contain all the test parameters and all the local variables directly
3938 * accessible to the sequential reader implementation. 3938 * accessible to the sequential reader implementation.
3939 * 3939 *
3940 * The technique adopted is to reinvent part of what Dijkstra termed a 3940 * The technique adopted is to reinvent part of what Dijkstra termed a
3941 * 'display'; an array of pointers to the stack frames of enclosing functions so 3941 * 'display'; an array of pointers to the stack frames of enclosing functions so
3942 * that a nested function definition can access the local (C auto) variables of 3942 * that a nested function definition can access the local (C auto) variables of
3943 * the functions that contain its definition. In fact C provides the first 3943 * the functions that contain its definition. In fact C provides the first
3944 * pointer (the local variables - the stack frame pointer) and the last (the 3944 * pointer (the local variables - the stack frame pointer) and the last (the
3945 * global variables - the BCPL global vector typically implemented as global 3945 * global variables - the BCPL global vector typically implemented as global
3946 * addresses), this code requires one more pointer to make the display - the 3946 * addresses), this code requires one more pointer to make the display - the
3947 * local variables (and function call parameters) of the function that actually 3947 * local variables (and function call parameters) of the function that actually
3948 * invokes either the progressive or sequential reader. 3948 * invokes either the progressive or sequential reader.
3949 * 3949 *
3950 * Perhaps confusingly this technique is confounded with classes - the 3950 * Perhaps confusingly this technique is confounded with classes - the
3951 * 'standard_display' defined here is sub-classed as the 'gamma_display' below. 3951 * 'standard_display' defined here is sub-classed as the 'gamma_display' below.
3952 * A gamma_display is a standard_display, taking advantage of the ANSI-C 3952 * A gamma_display is a standard_display, taking advantage of the ANSI-C
3953 * requirement that the pointer to the first member of a structure must be the 3953 * requirement that the pointer to the first member of a structure must be the
3954 * same as the pointer to the structure. This allows us to reuse standard_ 3954 * same as the pointer to the structure. This allows us to reuse standard_
3955 * functions in the gamma test code; something that could not be done with 3955 * functions in the gamma test code; something that could not be done with
3956 * nested functions! 3956 * nested functions!
3957 */ 3957 */
3958typedef struct standard_display 3958typedef struct standard_display
3959{ 3959{
3960 png_store* ps; /* Test parameters (passed to the function) */ 3960 png_store* ps; /* Test parameters (passed to the function) */
3961 png_byte colour_type; 3961 png_byte colour_type;
3962 png_byte bit_depth; 3962 png_byte bit_depth;
3963 png_byte red_sBIT; /* Input data sBIT values. */ 3963 png_byte red_sBIT; /* Input data sBIT values. */
3964 png_byte green_sBIT; 3964 png_byte green_sBIT;
3965 png_byte blue_sBIT; 3965 png_byte blue_sBIT;
3966 png_byte alpha_sBIT; 3966 png_byte alpha_sBIT;
3967 int interlace_type; 3967 int interlace_type;
3968 png_uint_32 id; /* Calculated file ID */ 3968 png_uint_32 id; /* Calculated file ID */
3969 png_uint_32 w; /* Width of image */ 3969 png_uint_32 w; /* Width of image */
3970 png_uint_32 h; /* Height of image */ 3970 png_uint_32 h; /* Height of image */
3971 int npasses; /* Number of interlaced passes */ 3971 int npasses; /* Number of interlaced passes */
3972 png_uint_32 pixel_size; /* Width of one pixel in bits */ 3972 png_uint_32 pixel_size; /* Width of one pixel in bits */
3973 png_uint_32 bit_width; /* Width of output row in bits */ 3973 png_uint_32 bit_width; /* Width of output row in bits */
3974 size_t cbRow; /* Bytes in a row of the output image */ 3974 size_t cbRow; /* Bytes in a row of the output image */
3975 int do_interlace; /* Do interlacing internally */ 3975 int do_interlace; /* Do interlacing internally */
3976 int is_transparent; /* Transparency information was present. */ 3976 int is_transparent; /* Transparency information was present. */
3977 int speed; /* Doing a speed test */ 3977 int speed; /* Doing a speed test */
3978 int use_update_info;/* Call update_info, not start_image */ 3978 int use_update_info;/* Call update_info, not start_image */
3979 struct 3979 struct
3980 { 3980 {
3981 png_uint_16 red; 3981 png_uint_16 red;
3982 png_uint_16 green; 3982 png_uint_16 green;
3983 png_uint_16 blue; 3983 png_uint_16 blue;
3984 } transparent; /* The transparent color, if set. */ 3984 } transparent; /* The transparent color, if set. */
3985 int npalette; /* Number of entries in the palette. */ 3985 int npalette; /* Number of entries in the palette. */
3986 store_palette 3986 store_palette
3987 palette; 3987 palette;
3988} standard_display; 3988} standard_display;
3989 3989
3990static void 3990static void
3991standard_display_init(standard_display *dp, png_store* ps, png_uint_32 id, 3991standard_display_init(standard_display *dp, png_store* ps, png_uint_32 id,
3992 int do_interlace, int use_update_info) 3992 int do_interlace, int use_update_info)
3993{ 3993{
3994 memset(dp, 0, sizeof *dp); 3994 memset(dp, 0, sizeof *dp);
3995 3995
3996 dp->ps = ps; 3996 dp->ps = ps;
3997 dp->colour_type = COL_FROM_ID(id); 3997 dp->colour_type = COL_FROM_ID(id);
3998 dp->bit_depth = DEPTH_FROM_ID(id); 3998 dp->bit_depth = DEPTH_FROM_ID(id);
3999 if (dp->bit_depth < 1 || dp->bit_depth > 16) 3999 if (dp->bit_depth < 1 || dp->bit_depth > 16)
4000 internal_error(ps, "internal: bad bit depth"); 4000 internal_error(ps, "internal: bad bit depth");
4001 if (dp->colour_type == 3) 4001 if (dp->colour_type == 3)
4002 dp->red_sBIT = dp->blue_sBIT = dp->green_sBIT = dp->alpha_sBIT = 8; 4002 dp->red_sBIT = dp->blue_sBIT = dp->green_sBIT = dp->alpha_sBIT = 8;
4003 else 4003 else
4004 dp->red_sBIT = dp->blue_sBIT = dp->green_sBIT = dp->alpha_sBIT = 4004 dp->red_sBIT = dp->blue_sBIT = dp->green_sBIT = dp->alpha_sBIT =
4005 dp->bit_depth; 4005 dp->bit_depth;
4006 dp->interlace_type = INTERLACE_FROM_ID(id); 4006 dp->interlace_type = INTERLACE_FROM_ID(id);
4007 dp->id = id; 4007 dp->id = id;
4008 /* All the rest are filled in after the read_info: */ 4008 /* All the rest are filled in after the read_info: */
4009 dp->w = 0; 4009 dp->w = 0;
4010 dp->h = 0; 4010 dp->h = 0;
4011 dp->npasses = 0; 4011 dp->npasses = 0;
4012 dp->pixel_size = 0; 4012 dp->pixel_size = 0;
4013 dp->bit_width = 0; 4013 dp->bit_width = 0;
4014 dp->cbRow = 0; 4014 dp->cbRow = 0;
4015 dp->do_interlace = do_interlace; 4015 dp->do_interlace = do_interlace;
4016 dp->is_transparent = 0; 4016 dp->is_transparent = 0;
4017 dp->speed = ps->speed; 4017 dp->speed = ps->speed;
4018 dp->use_update_info = use_update_info; 4018 dp->use_update_info = use_update_info;
4019 dp->npalette = 0; 4019 dp->npalette = 0;
4020 /* Preset the transparent color to black: */ 4020 /* Preset the transparent color to black: */
4021 memset(&dp->transparent, 0, sizeof dp->transparent); 4021 memset(&dp->transparent, 0, sizeof dp->transparent);
4022 /* Preset the palette to full intensity/opaque througout: */ 4022 /* Preset the palette to full intensity/opaque througout: */
4023 memset(dp->palette, 0xff, sizeof dp->palette); 4023 memset(dp->palette, 0xff, sizeof dp->palette);
4024} 4024}
4025 4025
4026/* Initialize the palette fields - this must be done later because the palette 4026/* Initialize the palette fields - this must be done later because the palette
4027 * comes from the particular png_store_file that is selected. 4027 * comes from the particular png_store_file that is selected.
4028 */ 4028 */
4029static void 4029static void
4030standard_palette_init(standard_display *dp) 4030standard_palette_init(standard_display *dp)
4031{ 4031{
4032 store_palette_entry *palette = store_current_palette(dp->ps, &dp->npalette); 4032 store_palette_entry *palette = store_current_palette(dp->ps, &dp->npalette);
4033 4033
4034 /* The remaining entries remain white/opaque. */ 4034 /* The remaining entries remain white/opaque. */
4035 if (dp->npalette > 0) 4035 if (dp->npalette > 0)
4036 { 4036 {
4037 int i = dp->npalette; 4037 int i = dp->npalette;
4038 memcpy(dp->palette, palette, i * sizeof *palette); 4038 memcpy(dp->palette, palette, i * sizeof *palette);
4039 4039
4040 /* Check for a non-opaque palette entry: */ 4040 /* Check for a non-opaque palette entry: */
4041 while (--i >= 0) 4041 while (--i >= 0)
4042 if (palette[i].alpha < 255) 4042 if (palette[i].alpha < 255)
4043 break; 4043 break;
4044 4044
4045# ifdef __GNUC__ 4045# ifdef __GNUC__
4046 /* GCC can't handle the more obviously optimizable version. */ 4046 /* GCC can't handle the more obviously optimizable version. */
4047 if (i >= 0) 4047 if (i >= 0)
4048 dp->is_transparent = 1; 4048 dp->is_transparent = 1;
4049 else 4049 else
4050 dp->is_transparent = 0; 4050 dp->is_transparent = 0;
4051# else 4051# else
4052 dp->is_transparent = (i >= 0); 4052 dp->is_transparent = (i >= 0);
4053# endif 4053# endif
4054 } 4054 }
4055} 4055}
4056 4056
4057/* Utility to read the palette from the PNG file and convert it into 4057/* Utility to read the palette from the PNG file and convert it into
4058 * store_palette format. This returns 1 if there is any transparency in the 4058 * store_palette format. This returns 1 if there is any transparency in the
4059 * palette (it does not check for a transparent colour in the non-palette case.) 4059 * palette (it does not check for a transparent colour in the non-palette case.)
4060 */ 4060 */
4061static int 4061static int
4062read_palette(store_palette palette, int *npalette, png_structp pp, png_infop pi) 4062read_palette(store_palette palette, int *npalette, png_structp pp, png_infop pi)
4063{ 4063{
4064 png_colorp pal; 4064 png_colorp pal;
4065 png_bytep trans_alpha; 4065 png_bytep trans_alpha;
4066 int num; 4066 int num;
4067 4067
4068 pal = 0; 4068 pal = 0;
4069 *npalette = -1; 4069 *npalette = -1;
4070 4070
4071 if (png_get_PLTE(pp, pi, &pal, npalette) & PNG_INFO_PLTE) 4071 if (png_get_PLTE(pp, pi, &pal, npalette) & PNG_INFO_PLTE)
4072 { 4072 {
4073 int i = *npalette; 4073 int i = *npalette;
4074 4074
4075 if (i <= 0 || i > 256) 4075 if (i <= 0 || i > 256)
4076 png_error(pp, "validate: invalid PLTE count"); 4076 png_error(pp, "validate: invalid PLTE count");
4077 4077
4078 while (--i >= 0) 4078 while (--i >= 0)
4079 { 4079 {
4080 palette[i].red = pal[i].red; 4080 palette[i].red = pal[i].red;
4081 palette[i].green = pal[i].green; 4081 palette[i].green = pal[i].green;
4082 palette[i].blue = pal[i].blue; 4082 palette[i].blue = pal[i].blue;
4083 } 4083 }
4084 4084
4085 /* Mark the remainder of the entries with a flag value (other than 4085 /* Mark the remainder of the entries with a flag value (other than
4086 * white/opaque which is the flag value stored above.) 4086 * white/opaque which is the flag value stored above.)
4087 */ 4087 */
4088 memset(palette + *npalette, 126, (256-*npalette) * sizeof *palette); 4088 memset(palette + *npalette, 126, (256-*npalette) * sizeof *palette);
4089 } 4089 }
4090 4090
4091 else /* !png_get_PLTE */ 4091 else /* !png_get_PLTE */
4092 { 4092 {
4093 if (*npalette != (-1)) 4093 if (*npalette != (-1))
4094 png_error(pp, "validate: invalid PLTE result"); 4094 png_error(pp, "validate: invalid PLTE result");
4095 /* But there is no palette, so record this: */ 4095 /* But there is no palette, so record this: */
4096 *npalette = 0; 4096 *npalette = 0;
4097 memset(palette, 113, sizeof (store_palette)); 4097 memset(palette, 113, sizeof (store_palette));
4098 } 4098 }
4099 4099
4100 trans_alpha = 0; 4100 trans_alpha = 0;
4101 num = 2; /* force error below */ 4101 num = 2; /* force error below */
4102 if ((png_get_tRNS(pp, pi, &trans_alpha, &num, 0) & PNG_INFO_tRNS) != 0 && 4102 if ((png_get_tRNS(pp, pi, &trans_alpha, &num, 0) & PNG_INFO_tRNS) != 0 &&
4103 (trans_alpha != NULL || num != 1/*returns 1 for a transparent color*/) && 4103 (trans_alpha != NULL || num != 1/*returns 1 for a transparent color*/) &&
4104 /* Oops, if a palette tRNS gets expanded png_read_update_info (at least so 4104 /* Oops, if a palette tRNS gets expanded png_read_update_info (at least so
4105 * far as 1.5.4) does not remove the trans_alpha pointer, only num_trans, 4105 * far as 1.5.4) does not remove the trans_alpha pointer, only num_trans,
4106 * so in the above call we get a success, we get a pointer (who knows what 4106 * so in the above call we get a success, we get a pointer (who knows what
4107 * to) and we get num_trans == 0: 4107 * to) and we get num_trans == 0:
4108 */ 4108 */
4109 !(trans_alpha != NULL && num == 0)) /* TODO: fix this in libpng. */ 4109 !(trans_alpha != NULL && num == 0)) /* TODO: fix this in libpng. */
4110 { 4110 {
4111 int i; 4111 int i;
4112 4112
4113 /* Any of these are crash-worthy - given the implementation of 4113 /* Any of these are crash-worthy - given the implementation of
4114 * png_get_tRNS up to 1.5 an app won't crash if it just checks the 4114 * png_get_tRNS up to 1.5 an app won't crash if it just checks the
4115 * result above and fails to check that the variables it passed have 4115 * result above and fails to check that the variables it passed have
4116 * actually been filled in! Note that if the app were to pass the 4116 * actually been filled in! Note that if the app were to pass the
4117 * last, png_color_16p, variable too it couldn't rely on this. 4117 * last, png_color_16p, variable too it couldn't rely on this.
4118 */ 4118 */
4119 if (trans_alpha == NULL || num <= 0 || num > 256 || num > *npalette) 4119 if (trans_alpha == NULL || num <= 0 || num > 256 || num > *npalette)
4120 png_error(pp, "validate: unexpected png_get_tRNS (palette) result"); 4120 png_error(pp, "validate: unexpected png_get_tRNS (palette) result");
4121 4121
4122 for (i=0; i<num; ++i) 4122 for (i=0; i<num; ++i)
4123 palette[i].alpha = trans_alpha[i]; 4123 palette[i].alpha = trans_alpha[i];
4124 4124
4125 for (num=*npalette; i<num; ++i) 4125 for (num=*npalette; i<num; ++i)
4126 palette[i].alpha = 255; 4126 palette[i].alpha = 255;
4127 4127
4128 for (; i<256; ++i) 4128 for (; i<256; ++i)
4129 palette[i].alpha = 33; /* flag value */ 4129 palette[i].alpha = 33; /* flag value */
4130 4130
4131 return 1; /* transparency */ 4131 return 1; /* transparency */
4132 } 4132 }
4133 4133
4134 else 4134 else
4135 { 4135 {
4136 /* No palette transparency - just set the alpha channel to opaque. */ 4136 /* No palette transparency - just set the alpha channel to opaque. */
4137 int i; 4137 int i;
4138 4138
4139 for (i=0, num=*npalette; i<num; ++i) 4139 for (i=0, num=*npalette; i<num; ++i)
4140 palette[i].alpha = 255; 4140 palette[i].alpha = 255;
4141 4141
4142 for (; i<256; ++i) 4142 for (; i<256; ++i)
4143 palette[i].alpha = 55; /* flag value */ 4143 palette[i].alpha = 55; /* flag value */
4144 4144
4145 return 0; /* no transparency */ 4145 return 0; /* no transparency */
4146 } 4146 }
4147} 4147}
4148 4148
4149/* Utility to validate the palette if it should not have changed (the 4149/* Utility to validate the palette if it should not have changed (the
4150 * non-transform case). 4150 * non-transform case).
4151 */ 4151 */
4152static void 4152static void
4153standard_palette_validate(standard_display *dp, png_structp pp, png_infop pi) 4153standard_palette_validate(standard_display *dp, png_structp pp, png_infop pi)
4154{ 4154{
4155 int npalette; 4155 int npalette;
4156 store_palette palette; 4156 store_palette palette;
4157 4157
4158 if (read_palette(palette, &npalette, pp, pi) != dp->is_transparent) 4158 if (read_palette(palette, &npalette, pp, pi) != dp->is_transparent)
4159 png_error(pp, "validate: palette transparency changed"); 4159 png_error(pp, "validate: palette transparency changed");
4160 4160
4161 if (npalette != dp->npalette) 4161 if (npalette != dp->npalette)
4162 { 4162 {
4163 size_t pos = 0; 4163 size_t pos = 0;
4164 char msg[64]; 4164 char msg[64];
4165 4165
4166 pos = safecat(msg, sizeof msg, pos, "validate: palette size changed: "); 4166 pos = safecat(msg, sizeof msg, pos, "validate: palette size changed: ");
4167 pos = safecatn(msg, sizeof msg, pos, dp->npalette); 4167 pos = safecatn(msg, sizeof msg, pos, dp->npalette);
4168 pos = safecat(msg, sizeof msg, pos, " -> "); 4168 pos = safecat(msg, sizeof msg, pos, " -> ");
4169 pos = safecatn(msg, sizeof msg, pos, npalette); 4169 pos = safecatn(msg, sizeof msg, pos, npalette);
4170 png_error(pp, msg); 4170 png_error(pp, msg);
4171 } 4171 }
4172 4172
4173 { 4173 {
4174 int i = npalette; /* npalette is aliased */ 4174 int i = npalette; /* npalette is aliased */
4175 4175
4176 while (--i >= 0) 4176 while (--i >= 0)
4177 if (palette[i].red != dp->palette[i].red || 4177 if (palette[i].red != dp->palette[i].red ||
4178 palette[i].green != dp->palette[i].green || 4178 palette[i].green != dp->palette[i].green ||
4179 palette[i].blue != dp->palette[i].blue || 4179 palette[i].blue != dp->palette[i].blue ||
4180 palette[i].alpha != dp->palette[i].alpha) 4180 palette[i].alpha != dp->palette[i].alpha)
4181 png_error(pp, "validate: PLTE or tRNS chunk changed"); 4181 png_error(pp, "validate: PLTE or tRNS chunk changed");
4182 } 4182 }
4183} 4183}
4184 4184
4185/* By passing a 'standard_display' the progressive callbacks can be used 4185/* By passing a 'standard_display' the progressive callbacks can be used
4186 * directly by the sequential code, the functions suffixed "_imp" are the 4186 * directly by the sequential code, the functions suffixed "_imp" are the
4187 * implementations, the functions without the suffix are the callbacks. 4187 * implementations, the functions without the suffix are the callbacks.
4188 * 4188 *
4189 * The code for the info callback is split into two because this callback calls 4189 * The code for the info callback is split into two because this callback calls
4190 * png_read_update_info or png_start_read_image and what gets called depends on 4190 * png_read_update_info or png_start_read_image and what gets called depends on
4191 * whether the info needs updating (we want to test both calls in pngvalid.) 4191 * whether the info needs updating (we want to test both calls in pngvalid.)
4192 */ 4192 */
4193static void 4193static void
4194standard_info_part1(standard_display *dp, png_structp pp, png_infop pi) 4194standard_info_part1(standard_display *dp, png_structp pp, png_infop pi)
4195{ 4195{
4196 if (png_get_bit_depth(pp, pi) != dp->bit_depth) 4196 if (png_get_bit_depth(pp, pi) != dp->bit_depth)
4197 png_error(pp, "validate: bit depth changed"); 4197 png_error(pp, "validate: bit depth changed");
4198 4198
4199 if (png_get_color_type(pp, pi) != dp->colour_type) 4199 if (png_get_color_type(pp, pi) != dp->colour_type)
4200 png_error(pp, "validate: color type changed"); 4200 png_error(pp, "validate: color type changed");
4201 4201
4202 if (png_get_filter_type(pp, pi) != PNG_FILTER_TYPE_BASE) 4202 if (png_get_filter_type(pp, pi) != PNG_FILTER_TYPE_BASE)
4203 png_error(pp, "validate: filter type changed"); 4203 png_error(pp, "validate: filter type changed");
4204 4204
4205 if (png_get_interlace_type(pp, pi) != dp->interlace_type) 4205 if (png_get_interlace_type(pp, pi) != dp->interlace_type)
4206 png_error(pp, "validate: interlacing changed"); 4206 png_error(pp, "validate: interlacing changed");
4207 4207
4208 if (png_get_compression_type(pp, pi) != PNG_COMPRESSION_TYPE_BASE) 4208 if (png_get_compression_type(pp, pi) != PNG_COMPRESSION_TYPE_BASE)
4209 png_error(pp, "validate: compression type changed"); 4209 png_error(pp, "validate: compression type changed");
4210 4210
4211 dp->w = png_get_image_width(pp, pi); 4211 dp->w = png_get_image_width(pp, pi);
4212 4212
4213 if (dp->w != standard_width(pp, dp->id)) 4213 if (dp->w != standard_width(pp, dp->id))
4214 png_error(pp, "validate: image width changed"); 4214 png_error(pp, "validate: image width changed");
4215 4215
4216 dp->h = png_get_image_height(pp, pi); 4216 dp->h = png_get_image_height(pp, pi);
4217 4217
4218 if (dp->h != standard_height(pp, dp->id)) 4218 if (dp->h != standard_height(pp, dp->id))
4219 png_error(pp, "validate: image height changed"); 4219 png_error(pp, "validate: image height changed");
4220 4220
4221 /* Record (but don't check at present) the input sBIT according to the colour 4221 /* Record (but don't check at present) the input sBIT according to the colour
4222 * type information. 4222 * type information.
4223 */ 4223 */
4224 { 4224 {
4225 png_color_8p sBIT = 0; 4225 png_color_8p sBIT = 0;
4226 4226
4227 if (png_get_sBIT(pp, pi, &sBIT) & PNG_INFO_sBIT) 4227 if (png_get_sBIT(pp, pi, &sBIT) & PNG_INFO_sBIT)
4228 { 4228 {
4229 int sBIT_invalid = 0; 4229 int sBIT_invalid = 0;
4230 4230
4231 if (sBIT == 0) 4231 if (sBIT == 0)
4232 png_error(pp, "validate: unexpected png_get_sBIT result"); 4232 png_error(pp, "validate: unexpected png_get_sBIT result");
4233 4233
4234 if (dp->colour_type & PNG_COLOR_MASK_COLOR) 4234 if (dp->colour_type & PNG_COLOR_MASK_COLOR)
4235 { 4235 {
4236 if (sBIT->red == 0 || sBIT->red > dp->bit_depth) 4236 if (sBIT->red == 0 || sBIT->red > dp->bit_depth)
4237 sBIT_invalid = 1; 4237 sBIT_invalid = 1;
4238 else 4238 else
4239 dp->red_sBIT = sBIT->red; 4239 dp->red_sBIT = sBIT->red;
4240 4240
4241 if (sBIT->green == 0 || sBIT->green > dp->bit_depth) 4241 if (sBIT->green == 0 || sBIT->green > dp->bit_depth)
4242 sBIT_invalid = 1; 4242 sBIT_invalid = 1;
4243 else 4243 else
4244 dp->green_sBIT = sBIT->green; 4244 dp->green_sBIT = sBIT->green;
4245 4245
4246 if (sBIT->blue == 0 || sBIT->blue > dp->bit_depth) 4246 if (sBIT->blue == 0 || sBIT->blue > dp->bit_depth)
4247 sBIT_invalid = 1; 4247 sBIT_invalid = 1;
4248 else 4248 else
4249 dp->blue_sBIT = sBIT->blue; 4249 dp->blue_sBIT = sBIT->blue;
4250 } 4250 }
4251 4251
4252 else /* !COLOR */ 4252 else /* !COLOR */
4253 { 4253 {
4254 if (sBIT->gray == 0 || sBIT->gray > dp->bit_depth) 4254 if (sBIT->gray == 0 || sBIT->gray > dp->bit_depth)
4255 sBIT_invalid = 1; 4255 sBIT_invalid = 1;
4256 else 4256 else
4257 dp->blue_sBIT = dp->green_sBIT = dp->red_sBIT = sBIT->gray; 4257 dp->blue_sBIT = dp->green_sBIT = dp->red_sBIT = sBIT->gray;
4258 } 4258 }
4259 4259
4260 /* All 8 bits in tRNS for a palette image are significant - see the 4260 /* All 8 bits in tRNS for a palette image are significant - see the
4261 * spec. 4261 * spec.
4262 */ 4262 */
4263 if (dp->colour_type & PNG_COLOR_MASK_ALPHA) 4263 if (dp->colour_type & PNG_COLOR_MASK_ALPHA)
4264 { 4264 {
4265 if (sBIT->alpha == 0 || sBIT->alpha > dp->bit_depth) 4265 if (sBIT->alpha == 0 || sBIT->alpha > dp->bit_depth)
4266 sBIT_invalid = 1; 4266 sBIT_invalid = 1;
4267 else 4267 else
4268 dp->alpha_sBIT = sBIT->alpha; 4268 dp->alpha_sBIT = sBIT->alpha;
4269 } 4269 }
4270 4270
4271 if (sBIT_invalid) 4271 if (sBIT_invalid)
4272 png_error(pp, "validate: sBIT value out of range"); 4272 png_error(pp, "validate: sBIT value out of range");
4273 } 4273 }
4274 } 4274 }
4275 4275
4276 /* Important: this is validating the value *before* any transforms have been 4276 /* Important: this is validating the value *before* any transforms have been
4277 * put in place. It doesn't matter for the standard tests, where there are 4277 * put in place. It doesn't matter for the standard tests, where there are
4278 * no transforms, but it does for other tests where rowbytes may change after 4278 * no transforms, but it does for other tests where rowbytes may change after
4279 * png_read_update_info. 4279 * png_read_update_info.
4280 */ 4280 */
4281 if (png_get_rowbytes(pp, pi) != standard_rowsize(pp, dp->id)) 4281 if (png_get_rowbytes(pp, pi) != standard_rowsize(pp, dp->id))
4282 png_error(pp, "validate: row size changed"); 4282 png_error(pp, "validate: row size changed");
4283 4283
4284 /* Validate the colour type 3 palette (this can be present on other color 4284 /* Validate the colour type 3 palette (this can be present on other color
4285 * types.) 4285 * types.)
4286 */ 4286 */
4287 standard_palette_validate(dp, pp, pi); 4287 standard_palette_validate(dp, pp, pi);
4288 4288
4289 /* In any case always check for a tranparent color (notice that the 4289 /* In any case always check for a tranparent color (notice that the
4290 * colour type 3 case must not give a successful return on the get_tRNS call 4290 * colour type 3 case must not give a successful return on the get_tRNS call
4291 * with these arguments!) 4291 * with these arguments!)
4292 */ 4292 */
4293 { 4293 {
4294 png_color_16p trans_color = 0; 4294 png_color_16p trans_color = 0;
4295 4295
4296 if (png_get_tRNS(pp, pi, 0, 0, &trans_color) & PNG_INFO_tRNS) 4296 if (png_get_tRNS(pp, pi, 0, 0, &trans_color) & PNG_INFO_tRNS)
4297 { 4297 {
4298 if (trans_color == 0) 4298 if (trans_color == 0)
4299 png_error(pp, "validate: unexpected png_get_tRNS (color) result"); 4299 png_error(pp, "validate: unexpected png_get_tRNS (color) result");
4300 4300
4301 switch (dp->colour_type) 4301 switch (dp->colour_type)
4302 { 4302 {
4303 case 0: 4303 case 0:
4304 dp->transparent.red = dp->transparent.green = dp->transparent.blue = 4304 dp->transparent.red = dp->transparent.green = dp->transparent.blue =
4305 trans_color->gray; 4305 trans_color->gray;
4306 dp->is_transparent = 1; 4306 dp->is_transparent = 1;
4307 break; 4307 break;
4308 4308
4309 case 2: 4309 case 2:
4310 dp->transparent.red = trans_color->red; 4310 dp->transparent.red = trans_color->red;
4311 dp->transparent.green = trans_color->green; 4311 dp->transparent.green = trans_color->green;
4312 dp->transparent.blue = trans_color->blue; 4312 dp->transparent.blue = trans_color->blue;
4313 dp->is_transparent = 1; 4313 dp->is_transparent = 1;
4314 break; 4314 break;
4315 4315
4316 case 3: 4316 case 3:
4317 /* Not expected because it should result in the array case 4317 /* Not expected because it should result in the array case
4318 * above. 4318 * above.
4319 */ 4319 */
4320 png_error(pp, "validate: unexpected png_get_tRNS result"); 4320 png_error(pp, "validate: unexpected png_get_tRNS result");
4321 break; 4321 break;
4322 4322
4323 default: 4323 default:
4324 png_error(pp, "validate: invalid tRNS chunk with alpha image"); 4324 png_error(pp, "validate: invalid tRNS chunk with alpha image");
4325 } 4325 }
4326 } 4326 }
4327 } 4327 }
4328 4328
4329 /* Read the number of passes - expected to match the value used when 4329 /* Read the number of passes - expected to match the value used when
4330 * creating the image (interlaced or not). This has the side effect of 4330 * creating the image (interlaced or not). This has the side effect of
4331 * turning on interlace handling (if do_interlace is not set.) 4331 * turning on interlace handling (if do_interlace is not set.)
4332 */ 4332 */
4333 dp->npasses = npasses_from_interlace_type(pp, dp->interlace_type); 4333 dp->npasses = npasses_from_interlace_type(pp, dp->interlace_type);
4334 if (!dp->do_interlace && dp->npasses != png_set_interlace_handling(pp)) 4334 if (!dp->do_interlace && dp->npasses != png_set_interlace_handling(pp))
4335 png_error(pp, "validate: file changed interlace type"); 4335 png_error(pp, "validate: file changed interlace type");
4336 4336
4337 /* Caller calls png_read_update_info or png_start_read_image now, then calls 4337 /* Caller calls png_read_update_info or png_start_read_image now, then calls
4338 * part2. 4338 * part2.
4339 */ 4339 */
4340} 4340}
4341 4341
4342/* This must be called *after* the png_read_update_info call to get the correct 4342/* This must be called *after* the png_read_update_info call to get the correct
4343 * 'rowbytes' value, otherwise png_get_rowbytes will refer to the untransformed 4343 * 'rowbytes' value, otherwise png_get_rowbytes will refer to the untransformed
4344 * image. 4344 * image.
4345 */ 4345 */
4346static void 4346static void
4347standard_info_part2(standard_display *dp, png_structp pp, png_infop pi, 4347standard_info_part2(standard_display *dp, png_structp pp, png_infop pi,
4348 int nImages) 4348 int nImages)
4349{ 4349{
4350 /* Record cbRow now that it can be found. */ 4350 /* Record cbRow now that it can be found. */
4351 dp->pixel_size = bit_size(pp, png_get_color_type(pp, pi), 4351 dp->pixel_size = bit_size(pp, png_get_color_type(pp, pi),
4352 png_get_bit_depth(pp, pi)); 4352 png_get_bit_depth(pp, pi));
4353 dp->bit_width = png_get_image_width(pp, pi) * dp->pixel_size; 4353 dp->bit_width = png_get_image_width(pp, pi) * dp->pixel_size;
4354 dp->cbRow = png_get_rowbytes(pp, pi); 4354 dp->cbRow = png_get_rowbytes(pp, pi);
4355 4355
4356 /* Validate the rowbytes here again. */ 4356 /* Validate the rowbytes here again. */
4357 if (dp->cbRow != (dp->bit_width+7)/8) 4357 if (dp->cbRow != (dp->bit_width+7)/8)
4358 png_error(pp, "bad png_get_rowbytes calculation"); 4358 png_error(pp, "bad png_get_rowbytes calculation");
4359 4359
4360 /* Then ensure there is enough space for the output image(s). */ 4360 /* Then ensure there is enough space for the output image(s). */
4361 store_ensure_image(dp->ps, pp, nImages, dp->cbRow, dp->h); 4361 store_ensure_image(dp->ps, pp, nImages, dp->cbRow, dp->h);
4362} 4362}
4363 4363
4364static void 4364static void
4365standard_info_imp(standard_display *dp, png_structp pp, png_infop pi, 4365standard_info_imp(standard_display *dp, png_structp pp, png_infop pi,
4366 int nImages) 4366 int nImages)
4367{ 4367{
4368 /* Note that the validation routine has the side effect of turning on 4368 /* Note that the validation routine has the side effect of turning on
4369 * interlace handling in the subsequent code. 4369 * interlace handling in the subsequent code.
4370 */ 4370 */
4371 standard_info_part1(dp, pp, pi); 4371 standard_info_part1(dp, pp, pi);
4372 4372
4373 /* And the info callback has to call this (or png_read_update_info - see 4373 /* And the info callback has to call this (or png_read_update_info - see
4374 * below in the png_modifier code for that variant. 4374 * below in the png_modifier code for that variant.
4375 */ 4375 */
4376 if (dp->use_update_info) 4376 if (dp->use_update_info)
4377 { 4377 {
4378 /* For debugging the effect of multiple calls: */ 4378 /* For debugging the effect of multiple calls: */
4379 int i = dp->use_update_info; 4379 int i = dp->use_update_info;
4380 while (i-- > 0) 4380 while (i-- > 0)
4381 png_read_update_info(pp, pi); 4381 png_read_update_info(pp, pi);
4382 } 4382 }
4383 4383
4384 else 4384 else
4385 png_start_read_image(pp); 4385 png_start_read_image(pp);
4386 4386
4387 /* Validate the height, width and rowbytes plus ensure that sufficient buffer 4387 /* Validate the height, width and rowbytes plus ensure that sufficient buffer
4388 * exists for decoding the image. 4388 * exists for decoding the image.
4389 */ 4389 */
4390 standard_info_part2(dp, pp, pi, nImages); 4390 standard_info_part2(dp, pp, pi, nImages);
4391} 4391}
4392 4392
4393static void 4393static void
4394standard_info(png_structp pp, png_infop pi) 4394standard_info(png_structp pp, png_infop pi)
4395{ 4395{
4396 standard_display *dp = voidcast(standard_display*, 4396 standard_display *dp = voidcast(standard_display*,
4397 png_get_progressive_ptr(pp)); 4397 png_get_progressive_ptr(pp));
4398 4398
4399 /* Call with nImages==1 because the progressive reader can only produce one 4399 /* Call with nImages==1 because the progressive reader can only produce one
4400 * image. 4400 * image.
4401 */ 4401 */
4402 standard_info_imp(dp, pp, pi, 1 /*only one image*/); 4402 standard_info_imp(dp, pp, pi, 1 /*only one image*/);
4403} 4403}
4404 4404
4405static void 4405static void
4406progressive_row(png_structp pp, png_bytep new_row, png_uint_32 y, int pass) 4406progressive_row(png_structp pp, png_bytep new_row, png_uint_32 y, int pass)
4407{ 4407{
4408 PNG_CONST standard_display *dp = voidcast(standard_display*, 4408 PNG_CONST standard_display *dp = voidcast(standard_display*,
4409 png_get_progressive_ptr(pp)); 4409 png_get_progressive_ptr(pp));
4410 4410
4411 /* When handling interlacing some rows will be absent in each pass, the 4411 /* When handling interlacing some rows will be absent in each pass, the
4412 * callback still gets called, but with a NULL pointer. This is checked 4412 * callback still gets called, but with a NULL pointer. This is checked
4413 * in the 'else' clause below. We need our own 'cbRow', but we can't call 4413 * in the 'else' clause below. We need our own 'cbRow', but we can't call
4414 * png_get_rowbytes because we got no info structure. 4414 * png_get_rowbytes because we got no info structure.
4415 */ 4415 */
4416 if (new_row != NULL) 4416 if (new_row != NULL)
4417 { 4417 {
4418 png_bytep row; 4418 png_bytep row;
4419 4419
4420 /* In the case where the reader doesn't do the interlace it gives 4420 /* In the case where the reader doesn't do the interlace it gives
4421 * us the y in the sub-image: 4421 * us the y in the sub-image:
4422 */ 4422 */
4423 if (dp->do_interlace && dp->interlace_type == PNG_INTERLACE_ADAM7) 4423 if (dp->do_interlace && dp->interlace_type == PNG_INTERLACE_ADAM7)
4424 { 4424 {
4425#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED 4425#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED
4426 /* Use this opportunity to validate the png 'current' APIs: */ 4426 /* Use this opportunity to validate the png 'current' APIs: */
4427 if (y != png_get_current_row_number(pp)) 4427 if (y != png_get_current_row_number(pp))
4428 png_error(pp, "png_get_current_row_number is broken"); 4428 png_error(pp, "png_get_current_row_number is broken");
4429 4429
4430 if (pass != png_get_current_pass_number(pp)) 4430 if (pass != png_get_current_pass_number(pp))
4431 png_error(pp, "png_get_current_pass_number is broken"); 4431 png_error(pp, "png_get_current_pass_number is broken");
4432#endif 4432#endif
4433 4433
4434 y = PNG_ROW_FROM_PASS_ROW(y, pass); 4434 y = PNG_ROW_FROM_PASS_ROW(y, pass);
4435 } 4435 }
4436 4436
4437 /* Validate this just in case. */ 4437 /* Validate this just in case. */
4438 if (y >= dp->h) 4438 if (y >= dp->h)
4439 png_error(pp, "invalid y to progressive row callback"); 4439 png_error(pp, "invalid y to progressive row callback");
4440 4440
4441 row = store_image_row(dp->ps, pp, 0, y); 4441 row = store_image_row(dp->ps, pp, 0, y);
4442 4442
4443#ifdef PNG_READ_INTERLACING_SUPPORTED 4443#ifdef PNG_READ_INTERLACING_SUPPORTED
4444 /* Combine the new row into the old: */ 4444 /* Combine the new row into the old: */
4445 if (dp->do_interlace) 4445 if (dp->do_interlace)
4446 { 4446 {
4447 if (dp->interlace_type == PNG_INTERLACE_ADAM7) 4447 if (dp->interlace_type == PNG_INTERLACE_ADAM7)
4448 deinterlace_row(row, new_row, dp->pixel_size, dp->w, pass); 4448 deinterlace_row(row, new_row, dp->pixel_size, dp->w, pass);
4449 else 4449 else
4450 row_copy(row, new_row, dp->pixel_size * dp->w); 4450 row_copy(row, new_row, dp->pixel_size * dp->w);
4451 } 4451 }
4452 else 4452 else
4453 png_progressive_combine_row(pp, row, new_row); 4453 png_progressive_combine_row(pp, row, new_row);
4454 } else if (dp->interlace_type == PNG_INTERLACE_ADAM7 && 4454 } else if (dp->interlace_type == PNG_INTERLACE_ADAM7 &&
4455 PNG_ROW_IN_INTERLACE_PASS(y, pass) && 4455 PNG_ROW_IN_INTERLACE_PASS(y, pass) &&
4456 PNG_PASS_COLS(dp->w, pass) > 0) 4456 PNG_PASS_COLS(dp->w, pass) > 0)
4457 png_error(pp, "missing row in progressive de-interlacing"); 4457 png_error(pp, "missing row in progressive de-interlacing");
4458#endif /* PNG_READ_INTERLACING_SUPPORTED */ 4458#endif /* PNG_READ_INTERLACING_SUPPORTED */
4459} 4459}
4460 4460
4461static void 4461static void
4462sequential_row(standard_display *dp, png_structp pp, png_infop pi, 4462sequential_row(standard_display *dp, png_structp pp, png_infop pi,
4463 PNG_CONST int iImage, PNG_CONST int iDisplay) 4463 PNG_CONST int iImage, PNG_CONST int iDisplay)
4464{ 4464{
4465 PNG_CONST int npasses = dp->npasses; 4465 PNG_CONST int npasses = dp->npasses;
4466 PNG_CONST int do_interlace = dp->do_interlace && 4466 PNG_CONST int do_interlace = dp->do_interlace &&
4467 dp->interlace_type == PNG_INTERLACE_ADAM7; 4467 dp->interlace_type == PNG_INTERLACE_ADAM7;
4468 PNG_CONST png_uint_32 height = standard_height(pp, dp->id); 4468 PNG_CONST png_uint_32 height = standard_height(pp, dp->id);
4469 PNG_CONST png_uint_32 width = standard_width(pp, dp->id); 4469 PNG_CONST png_uint_32 width = standard_width(pp, dp->id);
4470 PNG_CONST png_store* ps = dp->ps; 4470 PNG_CONST png_store* ps = dp->ps;
4471 int pass; 4471 int pass;
4472 4472
4473 for (pass=0; pass<npasses; ++pass) 4473 for (pass=0; pass<npasses; ++pass)
4474 { 4474 {
4475 png_uint_32 y; 4475 png_uint_32 y;
4476 png_uint_32 wPass = PNG_PASS_COLS(width, pass); 4476 png_uint_32 wPass = PNG_PASS_COLS(width, pass);
4477 4477
4478 for (y=0; y<height; ++y) 4478 for (y=0; y<height; ++y)
4479 { 4479 {
4480 if (do_interlace) 4480 if (do_interlace)
4481 { 4481 {
4482 /* wPass may be zero or this row may not be in this pass. 4482 /* wPass may be zero or this row may not be in this pass.
4483 * png_read_row must not be called in either case. 4483 * png_read_row must not be called in either case.
4484 */ 4484 */
4485 if (wPass > 0 && PNG_ROW_IN_INTERLACE_PASS(y, pass)) 4485 if (wPass > 0 && PNG_ROW_IN_INTERLACE_PASS(y, pass))
4486 { 4486 {
4487 /* Read the row into a pair of temporary buffers, then do the 4487 /* Read the row into a pair of temporary buffers, then do the
4488 * merge here into the output rows. 4488 * merge here into the output rows.
4489 */ 4489 */
4490 png_byte row[STANDARD_ROWMAX], display[STANDARD_ROWMAX]; 4490 png_byte row[STANDARD_ROWMAX], display[STANDARD_ROWMAX];
4491 4491
4492 /* The following aids (to some extent) error detection - we can 4492 /* The following aids (to some extent) error detection - we can
4493 * see where png_read_row wrote. Use opposite values in row and 4493 * see where png_read_row wrote. Use opposite values in row and
4494 * display to make this easier. Don't use 0xff (which is used in 4494 * display to make this easier. Don't use 0xff (which is used in
4495 * the image write code to fill unused bits) or 0 (which is a 4495 * the image write code to fill unused bits) or 0 (which is a
4496 * likely value to overwrite unused bits with). 4496 * likely value to overwrite unused bits with).
4497 */ 4497 */
4498 memset(row, 0xc5, sizeof row); 4498 memset(row, 0xc5, sizeof row);
4499 memset(display, 0x5c, sizeof display); 4499 memset(display, 0x5c, sizeof display);
4500 4500
4501 png_read_row(pp, row, display); 4501 png_read_row(pp, row, display);
4502 4502
4503 if (iImage >= 0) 4503 if (iImage >= 0)
4504 deinterlace_row(store_image_row(ps, pp, iImage, y), row, 4504 deinterlace_row(store_image_row(ps, pp, iImage, y), row,
4505 dp->pixel_size, dp->w, pass); 4505 dp->pixel_size, dp->w, pass);
4506 4506
4507 if (iDisplay >= 0) 4507 if (iDisplay >= 0)
4508 deinterlace_row(store_image_row(ps, pp, iDisplay, y), display, 4508 deinterlace_row(store_image_row(ps, pp, iDisplay, y), display,
4509 dp->pixel_size, dp->w, pass); 4509 dp->pixel_size, dp->w, pass);
4510 } 4510 }
4511 } 4511 }
4512 else 4512 else
4513 png_read_row(pp, 4513 png_read_row(pp,
4514 iImage >= 0 ? store_image_row(ps, pp, iImage, y) : NULL, 4514 iImage >= 0 ? store_image_row(ps, pp, iImage, y) : NULL,
4515 iDisplay >= 0 ? store_image_row(ps, pp, iDisplay, y) : NULL); 4515 iDisplay >= 0 ? store_image_row(ps, pp, iDisplay, y) : NULL);
4516 } 4516 }
4517 } 4517 }
4518 4518
4519 /* And finish the read operation (only really necessary if the caller wants 4519 /* And finish the read operation (only really necessary if the caller wants
4520 * to find additional data in png_info from chunks after the last IDAT.) 4520 * to find additional data in png_info from chunks after the last IDAT.)
4521 */ 4521 */
4522 png_read_end(pp, pi); 4522 png_read_end(pp, pi);
4523} 4523}
4524 4524
4525static void 4525static void
4526standard_row_validate(standard_display *dp, png_structp pp, 4526standard_row_validate(standard_display *dp, png_structp pp,
4527 int iImage, int iDisplay, png_uint_32 y) 4527 int iImage, int iDisplay, png_uint_32 y)
4528{ 4528{
4529 int where; 4529 int where;
4530 png_byte std[STANDARD_ROWMAX]; 4530 png_byte std[STANDARD_ROWMAX];
4531 4531
4532 /* The row must be pre-initialized to the magic number here for the size 4532 /* The row must be pre-initialized to the magic number here for the size
4533 * tests to pass: 4533 * tests to pass:
4534 */ 4534 */
4535 memset(std, 178, sizeof std); 4535 memset(std, 178, sizeof std);
4536 standard_row(pp, std, dp->id, y); 4536 standard_row(pp, std, dp->id, y);
4537 4537
4538 /* At the end both the 'row' and 'display' arrays should end up identical. 4538 /* At the end both the 'row' and 'display' arrays should end up identical.
4539 * In earlier passes 'row' will be partially filled in, with only the pixels 4539 * In earlier passes 'row' will be partially filled in, with only the pixels
4540 * that have been read so far, but 'display' will have those pixels 4540 * that have been read so far, but 'display' will have those pixels
4541 * replicated to fill the unread pixels while reading an interlaced image. 4541 * replicated to fill the unread pixels while reading an interlaced image.
4542#if PNG_LIBPNG_VER < 10506 4542#if PNG_LIBPNG_VER < 10506
4543 * The side effect inside the libpng sequential reader is that the 'row' 4543 * The side effect inside the libpng sequential reader is that the 'row'
4544 * array retains the correct values for unwritten pixels within the row 4544 * array retains the correct values for unwritten pixels within the row
4545 * bytes, while the 'display' array gets bits off the end of the image (in 4545 * bytes, while the 'display' array gets bits off the end of the image (in
4546 * the last byte) trashed. Unfortunately in the progressive reader the 4546 * the last byte) trashed. Unfortunately in the progressive reader the
4547 * row bytes are always trashed, so we always do a pixel_cmp here even though 4547 * row bytes are always trashed, so we always do a pixel_cmp here even though
4548 * a memcmp of all cbRow bytes will succeed for the sequential reader. 4548 * a memcmp of all cbRow bytes will succeed for the sequential reader.
4549#endif 4549#endif
4550 */ 4550 */
4551 if (iImage >= 0 && 4551 if (iImage >= 0 &&
4552 (where = pixel_cmp(std, store_image_row(dp->ps, pp, iImage, y), 4552 (where = pixel_cmp(std, store_image_row(dp->ps, pp, iImage, y),
4553 dp->bit_width)) != 0) 4553 dp->bit_width)) != 0)
4554 { 4554 {
4555 char msg[64]; 4555 char msg[64];
4556 sprintf(msg, "PNG image row[%d][%d] changed from %.2x to %.2x", y, 4556 sprintf(msg, "PNG image row[%d][%d] changed from %.2x to %.2x", y,
4557 where-1, std[where-1], 4557 where-1, std[where-1],
4558 store_image_row(dp->ps, pp, iImage, y)[where-1]); 4558 store_image_row(dp->ps, pp, iImage, y)[where-1]);
4559 png_error(pp, msg); 4559 png_error(pp, msg);
4560 } 4560 }
4561 4561
4562#if PNG_LIBPNG_VER < 10506 4562#if PNG_LIBPNG_VER < 10506
4563 /* In this case use pixel_cmp because we need to compare a partial 4563 /* In this case use pixel_cmp because we need to compare a partial
4564 * byte at the end of the row if the row is not an exact multiple 4564 * byte at the end of the row if the row is not an exact multiple
4565 * of 8 bits wide. (This is fixed in libpng-1.5.6 and pixel_cmp is 4565 * of 8 bits wide. (This is fixed in libpng-1.5.6 and pixel_cmp is
4566 * changed to match!) 4566 * changed to match!)
4567 */ 4567 */
4568#endif 4568#endif
4569 if (iDisplay >= 0 && 4569 if (iDisplay >= 0 &&
4570 (where = pixel_cmp(std, store_image_row(dp->ps, pp, iDisplay, y), 4570 (where = pixel_cmp(std, store_image_row(dp->ps, pp, iDisplay, y),
4571 dp->bit_width)) != 0) 4571 dp->bit_width)) != 0)
4572 { 4572 {
4573 char msg[64]; 4573 char msg[64];
4574 sprintf(msg, "display row[%d][%d] changed from %.2x to %.2x", y, 4574 sprintf(msg, "display row[%d][%d] changed from %.2x to %.2x", y,
4575 where-1, std[where-1], 4575 where-1, std[where-1],
4576 store_image_row(dp->ps, pp, iDisplay, y)[where-1]); 4576 store_image_row(dp->ps, pp, iDisplay, y)[where-1]);
4577 png_error(pp, msg); 4577 png_error(pp, msg);
4578 } 4578 }
4579} 4579}
4580 4580
4581static void 4581static void
4582standard_image_validate(standard_display *dp, png_structp pp, int iImage, 4582standard_image_validate(standard_display *dp, png_structp pp, int iImage,
4583 int iDisplay) 4583 int iDisplay)
4584{ 4584{
4585 png_uint_32 y; 4585 png_uint_32 y;
4586 4586
4587 if (iImage >= 0) 4587 if (iImage >= 0)
4588 store_image_check(dp->ps, pp, iImage); 4588 store_image_check(dp->ps, pp, iImage);
4589 4589
4590 if (iDisplay >= 0) 4590 if (iDisplay >= 0)
4591 store_image_check(dp->ps, pp, iDisplay); 4591 store_image_check(dp->ps, pp, iDisplay);
4592 4592
4593 for (y=0; y<dp->h; ++y) 4593 for (y=0; y<dp->h; ++y)
4594 standard_row_validate(dp, pp, iImage, iDisplay, y); 4594 standard_row_validate(dp, pp, iImage, iDisplay, y);
4595 4595
4596 /* This avoids false positives if the validation code is never called! */ 4596 /* This avoids false positives if the validation code is never called! */
4597 dp->ps->validated = 1; 4597 dp->ps->validated = 1;
4598} 4598}
4599 4599
4600static void 4600static void
4601standard_end(png_structp pp, png_infop pi) 4601standard_end(png_structp pp, png_infop pi)
4602{ 4602{
4603 standard_display *dp = voidcast(standard_display*, 4603 standard_display *dp = voidcast(standard_display*,
4604 png_get_progressive_ptr(pp)); 4604 png_get_progressive_ptr(pp));
4605 4605
4606 UNUSED(pi) 4606 UNUSED(pi)
4607 4607
4608 /* Validate the image - progressive reading only produces one variant for 4608 /* Validate the image - progressive reading only produces one variant for
4609 * interlaced images. 4609 * interlaced images.
4610 */ 4610 */
4611 standard_image_validate(dp, pp, 0, -1); 4611 standard_image_validate(dp, pp, 0, -1);
4612} 4612}
4613 4613
4614/* A single test run checking the standard image to ensure it is not damaged. */ 4614/* A single test run checking the standard image to ensure it is not damaged. */
4615static void 4615static void
4616standard_test(png_store* PNG_CONST psIn, png_uint_32 PNG_CONST id, 4616standard_test(png_store* PNG_CONST psIn, png_uint_32 PNG_CONST id,
4617 int do_interlace, int use_update_info) 4617 int do_interlace, int use_update_info)
4618{ 4618{
4619 standard_display d; 4619 standard_display d;
4620 context(psIn, fault); 4620 context(psIn, fault);
4621 4621
4622 /* Set up the display (stack frame) variables from the arguments to the 4622 /* Set up the display (stack frame) variables from the arguments to the
4623 * function and initialize the locals that are filled in later. 4623 * function and initialize the locals that are filled in later.
4624 */ 4624 */
4625 standard_display_init(&d, psIn, id, do_interlace, use_update_info); 4625 standard_display_init(&d, psIn, id, do_interlace, use_update_info);
4626 4626
4627 /* Everything is protected by a Try/Catch. The functions called also 4627 /* Everything is protected by a Try/Catch. The functions called also
4628 * typically have local Try/Catch blocks. 4628 * typically have local Try/Catch blocks.
4629 */ 4629 */
4630 Try 4630 Try
4631 { 4631 {
4632 png_structp pp; 4632 png_structp pp;
4633 png_infop pi; 4633 png_infop pi;
4634 4634
4635 /* Get a png_struct for reading the image. This will throw an error if it 4635 /* Get a png_struct for reading the image. This will throw an error if it
4636 * fails, so we don't need to check the result. 4636 * fails, so we don't need to check the result.
4637 */ 4637 */
4638 pp = set_store_for_read(d.ps, &pi, d.id, 4638 pp = set_store_for_read(d.ps, &pi, d.id,
4639 d.do_interlace ? (d.ps->progressive ? 4639 d.do_interlace ? (d.ps->progressive ?
4640 "pngvalid progressive deinterlacer" : 4640 "pngvalid progressive deinterlacer" :
4641 "pngvalid sequential deinterlacer") : (d.ps->progressive ? 4641 "pngvalid sequential deinterlacer") : (d.ps->progressive ?
4642 "progressive reader" : "sequential reader")); 4642 "progressive reader" : "sequential reader"));
4643 4643
4644 /* Initialize the palette correctly from the png_store_file. */ 4644 /* Initialize the palette correctly from the png_store_file. */
4645 standard_palette_init(&d); 4645 standard_palette_init(&d);
4646 4646
4647 /* Introduce the correct read function. */ 4647 /* Introduce the correct read function. */
4648 if (d.ps->progressive) 4648 if (d.ps->progressive)
4649 { 4649 {
4650 png_set_progressive_read_fn(pp, &d, standard_info, progressive_row, 4650 png_set_progressive_read_fn(pp, &d, standard_info, progressive_row,
4651 standard_end); 4651 standard_end);
4652 4652
4653 /* Now feed data into the reader until we reach the end: */ 4653 /* Now feed data into the reader until we reach the end: */
4654 store_progressive_read(d.ps, pp, pi); 4654 store_progressive_read(d.ps, pp, pi);
4655 } 4655 }
4656 else 4656 else
4657 { 4657 {
4658 /* Note that this takes the store, not the display. */ 4658 /* Note that this takes the store, not the display. */
4659 png_set_read_fn(pp, d.ps, store_read); 4659 png_set_read_fn(pp, d.ps, store_read);
4660 4660
4661 /* Check the header values: */ 4661 /* Check the header values: */
4662 png_read_info(pp, pi); 4662 png_read_info(pp, pi);
4663 4663
4664 /* The code tests both versions of the images that the sequential 4664 /* The code tests both versions of the images that the sequential
4665 * reader can produce. 4665 * reader can produce.
4666 */ 4666 */
4667 standard_info_imp(&d, pp, pi, 2 /*images*/); 4667 standard_info_imp(&d, pp, pi, 2 /*images*/);
4668 4668
4669 /* Need the total bytes in the image below; we can't get to this point 4669 /* Need the total bytes in the image below; we can't get to this point
4670 * unless the PNG file values have been checked against the expected 4670 * unless the PNG file values have been checked against the expected
4671 * values. 4671 * values.
4672 */ 4672 */
4673 { 4673 {
4674 sequential_row(&d, pp, pi, 0, 1); 4674 sequential_row(&d, pp, pi, 0, 1);
4675 4675
4676 /* After the last pass loop over the rows again to check that the 4676 /* After the last pass loop over the rows again to check that the
4677 * image is correct. 4677 * image is correct.
4678 */ 4678 */
4679 if (!d.speed) 4679 if (!d.speed)
4680 standard_image_validate(&d, pp, 0, 1); 4680 standard_image_validate(&d, pp, 0, 1);
4681 else 4681 else
4682 d.ps->validated = 1; 4682 d.ps->validated = 1;
4683 } 4683 }
4684 } 4684 }
4685 4685
4686 /* Check for validation. */ 4686 /* Check for validation. */
4687 if (!d.ps->validated) 4687 if (!d.ps->validated)
4688 png_error(pp, "image read failed silently"); 4688 png_error(pp, "image read failed silently");
4689 4689
4690 /* Successful completion. */ 4690 /* Successful completion. */
4691 } 4691 }
4692 4692
4693 Catch(fault) 4693 Catch(fault)
4694 d.ps = fault; /* make sure this hasn't been clobbered. */ 4694 d.ps = fault; /* make sure this hasn't been clobbered. */
4695 4695
4696 /* In either case clean up the store. */ 4696 /* In either case clean up the store. */
4697 store_read_reset(d.ps); 4697 store_read_reset(d.ps);
4698} 4698}
4699 4699
4700static int 4700static int
4701test_standard(png_modifier* PNG_CONST pm, png_byte PNG_CONST colour_type, 4701test_standard(png_modifier* PNG_CONST pm, png_byte PNG_CONST colour_type,
4702 int bdlo, int PNG_CONST bdhi) 4702 int bdlo, int PNG_CONST bdhi)
4703{ 4703{
4704 for (; bdlo <= bdhi; ++bdlo) 4704 for (; bdlo <= bdhi; ++bdlo)
4705 { 4705 {
4706 int interlace_type; 4706 int interlace_type;
4707 4707
4708 for (interlace_type = PNG_INTERLACE_NONE; 4708 for (interlace_type = PNG_INTERLACE_NONE;
4709 interlace_type < PNG_INTERLACE_LAST; ++interlace_type) 4709 interlace_type < PNG_INTERLACE_LAST; ++interlace_type)
4710 { 4710 {
4711 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/, 4711 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/,
4712 interlace_type, 0, 0, 0), 0/*do_interlace*/, pm->use_update_info); 4712 interlace_type, 0, 0, 0), 0/*do_interlace*/, pm->use_update_info);
4713 4713
4714 if (fail(pm)) 4714 if (fail(pm))
4715 return 0; 4715 return 0;
4716 } 4716 }
4717 } 4717 }
4718 4718
4719 return 1; /* keep going */ 4719 return 1; /* keep going */
4720} 4720}
4721 4721
4722static void 4722static void
4723perform_standard_test(png_modifier *pm) 4723perform_standard_test(png_modifier *pm)
4724{ 4724{
4725 /* Test each colour type over the valid range of bit depths (expressed as 4725 /* Test each colour type over the valid range of bit depths (expressed as
4726 * log2(bit_depth) in turn, stop as soon as any error is detected. 4726 * log2(bit_depth) in turn, stop as soon as any error is detected.
4727 */ 4727 */
4728 if (!test_standard(pm, 0, 0, READ_BDHI)) 4728 if (!test_standard(pm, 0, 0, READ_BDHI))
4729 return; 4729 return;
4730 4730
4731 if (!test_standard(pm, 2, 3, READ_BDHI)) 4731 if (!test_standard(pm, 2, 3, READ_BDHI))
4732 return; 4732 return;
4733 4733
4734 if (!test_standard(pm, 3, 0, 3)) 4734 if (!test_standard(pm, 3, 0, 3))
4735 return; 4735 return;
4736 4736
4737 if (!test_standard(pm, 4, 3, READ_BDHI)) 4737 if (!test_standard(pm, 4, 3, READ_BDHI))
4738 return; 4738 return;
4739 4739
4740 if (!test_standard(pm, 6, 3, READ_BDHI)) 4740 if (!test_standard(pm, 6, 3, READ_BDHI))
4741 return; 4741 return;
4742} 4742}
4743 4743
4744 4744
4745/********************************** SIZE TESTS ********************************/ 4745/********************************** SIZE TESTS ********************************/
4746static int 4746static int
4747test_size(png_modifier* PNG_CONST pm, png_byte PNG_CONST colour_type, 4747test_size(png_modifier* PNG_CONST pm, png_byte PNG_CONST colour_type,
4748 int bdlo, int PNG_CONST bdhi) 4748 int bdlo, int PNG_CONST bdhi)
4749{ 4749{
4750 /* Run the tests on each combination. 4750 /* Run the tests on each combination.
4751 * 4751 *
4752 * NOTE: on my 32 bit x86 each of the following blocks takes 4752 * NOTE: on my 32 bit x86 each of the following blocks takes
4753 * a total of 3.5 seconds if done across every combo of bit depth 4753 * a total of 3.5 seconds if done across every combo of bit depth
4754 * width and height. This is a waste of time in practice, hence the 4754 * width and height. This is a waste of time in practice, hence the
4755 * hinc and winc stuff: 4755 * hinc and winc stuff:
4756 */ 4756 */
4757 static PNG_CONST png_byte hinc[] = {1, 3, 11, 1, 5}; 4757 static PNG_CONST png_byte hinc[] = {1, 3, 11, 1, 5};
4758 static PNG_CONST png_byte winc[] = {1, 9, 5, 7, 1}; 4758 static PNG_CONST png_byte winc[] = {1, 9, 5, 7, 1};
4759 for (; bdlo <= bdhi; ++bdlo) 4759 for (; bdlo <= bdhi; ++bdlo)
4760 { 4760 {
4761 png_uint_32 h, w; 4761 png_uint_32 h, w;
4762 4762
4763 for (h=1; h<=16; h+=hinc[bdlo]) for (w=1; w<=16; w+=winc[bdlo]) 4763 for (h=1; h<=16; h+=hinc[bdlo]) for (w=1; w<=16; w+=winc[bdlo])
4764 { 4764 {
4765 /* First test all the 'size' images against the sequential 4765 /* First test all the 'size' images against the sequential
4766 * reader using libpng to deinterlace (where required.) This 4766 * reader using libpng to deinterlace (where required.) This
4767 * validates the write side of libpng. There are four possibilities 4767 * validates the write side of libpng. There are four possibilities
4768 * to validate. 4768 * to validate.
4769 */ 4769 */
4770 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/, 4770 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/,
4771 PNG_INTERLACE_NONE, w, h, 0), 0/*do_interlace*/, 4771 PNG_INTERLACE_NONE, w, h, 0), 0/*do_interlace*/,
4772 pm->use_update_info); 4772 pm->use_update_info);
4773 4773
4774 if (fail(pm)) 4774 if (fail(pm))
4775 return 0; 4775 return 0;
4776 4776
4777 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/, 4777 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/,
4778 PNG_INTERLACE_NONE, w, h, 1), 0/*do_interlace*/, 4778 PNG_INTERLACE_NONE, w, h, 1), 0/*do_interlace*/,
4779 pm->use_update_info); 4779 pm->use_update_info);
4780 4780
4781 if (fail(pm)) 4781 if (fail(pm))
4782 return 0; 4782 return 0;
4783 4783
4784 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/, 4784 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/,
4785 PNG_INTERLACE_ADAM7, w, h, 0), 0/*do_interlace*/, 4785 PNG_INTERLACE_ADAM7, w, h, 0), 0/*do_interlace*/,
4786 pm->use_update_info); 4786 pm->use_update_info);
4787 4787
4788 if (fail(pm)) 4788 if (fail(pm))
4789 return 0; 4789 return 0;
4790 4790
4791 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/, 4791 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/,
4792 PNG_INTERLACE_ADAM7, w, h, 1), 0/*do_interlace*/, 4792 PNG_INTERLACE_ADAM7, w, h, 1), 0/*do_interlace*/,
4793 pm->use_update_info); 4793 pm->use_update_info);
4794 4794
4795 if (fail(pm)) 4795 if (fail(pm))
4796 return 0; 4796 return 0;
4797 4797
4798 /* Now validate the interlaced read side - do_interlace true, 4798 /* Now validate the interlaced read side - do_interlace true,
4799 * in the progressive case this does actually make a difference 4799 * in the progressive case this does actually make a difference
4800 * to the code used in the non-interlaced case too. 4800 * to the code used in the non-interlaced case too.
4801 */ 4801 */
4802 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/, 4802 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/,
4803 PNG_INTERLACE_NONE, w, h, 0), 1/*do_interlace*/, 4803 PNG_INTERLACE_NONE, w, h, 0), 1/*do_interlace*/,
4804 pm->use_update_info); 4804 pm->use_update_info);
4805 4805
4806 if (fail(pm)) 4806 if (fail(pm))
4807 return 0; 4807 return 0;
4808 4808
4809 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/, 4809 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/,
4810 PNG_INTERLACE_ADAM7, w, h, 0), 1/*do_interlace*/, 4810 PNG_INTERLACE_ADAM7, w, h, 0), 1/*do_interlace*/,
4811 pm->use_update_info); 4811 pm->use_update_info);
4812 4812
4813 if (fail(pm)) 4813 if (fail(pm))
4814 return 0; 4814 return 0;
4815 } 4815 }
4816 } 4816 }
4817 4817
4818 return 1; /* keep going */ 4818 return 1; /* keep going */
4819} 4819}
4820 4820
4821static void 4821static void
4822perform_size_test(png_modifier *pm) 4822perform_size_test(png_modifier *pm)
4823{ 4823{
4824 /* Test each colour type over the valid range of bit depths (expressed as 4824 /* Test each colour type over the valid range of bit depths (expressed as
4825 * log2(bit_depth) in turn, stop as soon as any error is detected. 4825 * log2(bit_depth) in turn, stop as soon as any error is detected.
4826 */ 4826 */
4827 if (!test_size(pm, 0, 0, READ_BDHI)) 4827 if (!test_size(pm, 0, 0, READ_BDHI))
4828 return; 4828 return;
4829 4829
4830 if (!test_size(pm, 2, 3, READ_BDHI)) 4830 if (!test_size(pm, 2, 3, READ_BDHI))
4831 return; 4831 return;
4832 4832
4833 /* For the moment don't do the palette test - it's a waste of time when 4833 /* For the moment don't do the palette test - it's a waste of time when
4834 * compared to the grayscale test. 4834 * compared to the grayscale test.
4835 */ 4835 */
4836#if 0 4836#if 0
4837 if (!test_size(pm, 3, 0, 3)) 4837 if (!test_size(pm, 3, 0, 3))
4838 return; 4838 return;
4839#endif 4839#endif
4840 4840
4841 if (!test_size(pm, 4, 3, READ_BDHI)) 4841 if (!test_size(pm, 4, 3, READ_BDHI))
4842 return; 4842 return;
4843 4843
4844 if (!test_size(pm, 6, 3, READ_BDHI)) 4844 if (!test_size(pm, 6, 3, READ_BDHI))
4845 return; 4845 return;
4846} 4846}
4847 4847
4848 4848
4849/******************************* TRANSFORM TESTS ******************************/ 4849/******************************* TRANSFORM TESTS ******************************/
4850#ifdef PNG_READ_TRANSFORMS_SUPPORTED 4850#ifdef PNG_READ_TRANSFORMS_SUPPORTED
4851/* A set of tests to validate libpng image transforms. The possibilities here 4851/* A set of tests to validate libpng image transforms. The possibilities here
4852 * are legion because the transforms can be combined in a combinatorial 4852 * are legion because the transforms can be combined in a combinatorial
4853 * fashion. To deal with this some measure of restraint is required, otherwise 4853 * fashion. To deal with this some measure of restraint is required, otherwise
4854 * the tests would take forever. 4854 * the tests would take forever.
4855 */ 4855 */
4856typedef struct image_pixel 4856typedef struct image_pixel
4857{ 4857{
4858 /* A local (pngvalid) representation of a PNG pixel, in all its 4858 /* A local (pngvalid) representation of a PNG pixel, in all its
4859 * various forms. 4859 * various forms.
4860 */ 4860 */
4861 unsigned int red, green, blue, alpha; /* For non-palette images. */ 4861 unsigned int red, green, blue, alpha; /* For non-palette images. */
4862 unsigned int palette_index; /* For a palette image. */ 4862 unsigned int palette_index; /* For a palette image. */
4863 png_byte colour_type; /* As in the spec. */ 4863 png_byte colour_type; /* As in the spec. */
4864 png_byte bit_depth; /* Defines bit size in row */ 4864 png_byte bit_depth; /* Defines bit size in row */
4865 png_byte sample_depth; /* Scale of samples */ 4865 png_byte sample_depth; /* Scale of samples */
4866 int have_tRNS; /* tRNS chunk may need processing */ 4866 int have_tRNS; /* tRNS chunk may need processing */
4867 4867
4868 /* For checking the code calculates double precision floating point values 4868 /* For checking the code calculates double precision floating point values
4869 * along with an error value, accumulated from the transforms. Because an 4869 * along with an error value, accumulated from the transforms. Because an
4870 * sBIT setting allows larger error bounds (indeed, by the spec, apparently 4870 * sBIT setting allows larger error bounds (indeed, by the spec, apparently
4871 * up to just less than +/-1 in the scaled value) the *lowest* sBIT for each 4871 * up to just less than +/-1 in the scaled value) the *lowest* sBIT for each
4872 * channel is stored. This sBIT value is folded in to the stored error value 4872 * channel is stored. This sBIT value is folded in to the stored error value
4873 * at the end of the application of the transforms to the pixel. 4873 * at the end of the application of the transforms to the pixel.
4874 */ 4874 */
4875 double redf, greenf, bluef, alphaf; 4875 double redf, greenf, bluef, alphaf;
4876 double rede, greene, bluee, alphae; 4876 double rede, greene, bluee, alphae;
4877 png_byte red_sBIT, green_sBIT, blue_sBIT, alpha_sBIT; 4877 png_byte red_sBIT, green_sBIT, blue_sBIT, alpha_sBIT;
4878} image_pixel; 4878} image_pixel;
4879 4879
4880/* Shared utility function, see below. */ 4880/* Shared utility function, see below. */
4881static void 4881static void
4882image_pixel_setf(image_pixel *this, unsigned int max) 4882image_pixel_setf(image_pixel *this, unsigned int max)
4883{ 4883{
4884 this->redf = this->red / (double)max; 4884 this->redf = this->red / (double)max;
4885 this->greenf = this->green / (double)max; 4885 this->greenf = this->green / (double)max;
4886 this->bluef = this->blue / (double)max; 4886 this->bluef = this->blue / (double)max;
4887 this->alphaf = this->alpha / (double)max; 4887 this->alphaf = this->alpha / (double)max;
4888 4888
4889 if (this->red < max) 4889 if (this->red < max)
4890 this->rede = this->redf * DBL_EPSILON; 4890 this->rede = this->redf * DBL_EPSILON;
4891 else 4891 else
4892 this->rede = 0; 4892 this->rede = 0;
4893 if (this->green < max) 4893 if (this->green < max)
4894 this->greene = this->greenf * DBL_EPSILON; 4894 this->greene = this->greenf * DBL_EPSILON;
4895 else 4895 else
4896 this->greene = 0; 4896 this->greene = 0;
4897 if (this->blue < max) 4897 if (this->blue < max)
4898 this->bluee = this->bluef * DBL_EPSILON; 4898 this->bluee = this->bluef * DBL_EPSILON;
4899 else 4899 else
4900 this->bluee = 0; 4900 this->bluee = 0;
4901 if (this->alpha < max) 4901 if (this->alpha < max)
4902 this->alphae = this->alphaf * DBL_EPSILON; 4902 this->alphae = this->alphaf * DBL_EPSILON;
4903 else 4903 else
4904 this->alphae = 0; 4904 this->alphae = 0;
4905} 4905}
4906 4906
4907/* Initialize the structure for the next pixel - call this before doing any 4907/* Initialize the structure for the next pixel - call this before doing any
4908 * transforms and call it for each pixel since all the fields may need to be 4908 * transforms and call it for each pixel since all the fields may need to be
4909 * reset. 4909 * reset.
4910 */ 4910 */
4911static void 4911static void
4912image_pixel_init(image_pixel *this, png_const_bytep row, png_byte colour_type, 4912image_pixel_init(image_pixel *this, png_const_bytep row, png_byte colour_type,
4913 png_byte bit_depth, png_uint_32 x, store_palette palette) 4913 png_byte bit_depth, png_uint_32 x, store_palette palette)
4914{ 4914{
4915 PNG_CONST png_byte sample_depth = (png_byte)(colour_type == 4915 PNG_CONST png_byte sample_depth = (png_byte)(colour_type ==
4916 PNG_COLOR_TYPE_PALETTE ? 8 : bit_depth); 4916 PNG_COLOR_TYPE_PALETTE ? 8 : bit_depth);
4917 PNG_CONST unsigned int max = (1U<<sample_depth)-1; 4917 PNG_CONST unsigned int max = (1U<<sample_depth)-1;
4918 4918
4919 /* Initially just set everything to the same number and the alpha to opaque. 4919 /* Initially just set everything to the same number and the alpha to opaque.
4920 * Note that this currently assumes a simple palette where entry x has colour 4920 * Note that this currently assumes a simple palette where entry x has colour
4921 * rgb(x,x,x)! 4921 * rgb(x,x,x)!
4922 */ 4922 */
4923 this->palette_index = this->red = this->green = this->blue = 4923 this->palette_index = this->red = this->green = this->blue =
4924 sample(row, colour_type, bit_depth, x, 0); 4924 sample(row, colour_type, bit_depth, x, 0);
4925 this->alpha = max; 4925 this->alpha = max;
4926 this->red_sBIT = this->green_sBIT = this->blue_sBIT = this->alpha_sBIT = 4926 this->red_sBIT = this->green_sBIT = this->blue_sBIT = this->alpha_sBIT =
4927 sample_depth; 4927 sample_depth;
4928 4928
4929 /* Then override as appropriate: */ 4929 /* Then override as appropriate: */
4930 if (colour_type == 3) /* palette */ 4930 if (colour_type == 3) /* palette */
4931 { 4931 {
4932 /* This permits the caller to default to the sample value. */ 4932 /* This permits the caller to default to the sample value. */
4933 if (palette != 0) 4933 if (palette != 0)
4934 { 4934 {
4935 PNG_CONST unsigned int i = this->palette_index; 4935 PNG_CONST unsigned int i = this->palette_index;
4936 4936
4937 this->red = palette[i].red; 4937 this->red = palette[i].red;
4938 this->green = palette[i].green; 4938 this->green = palette[i].green;
4939 this->blue = palette[i].blue; 4939 this->blue = palette[i].blue;
4940 this->alpha = palette[i].alpha; 4940 this->alpha = palette[i].alpha;
4941 } 4941 }
4942 } 4942 }
4943 4943
4944 else /* not palette */ 4944 else /* not palette */
4945 { 4945 {
4946 unsigned int i = 0; 4946 unsigned int i = 0;
4947 4947
4948 if (colour_type & 2) 4948 if (colour_type & 2)
4949 { 4949 {
4950 this->green = sample(row, colour_type, bit_depth, x, 1); 4950 this->green = sample(row, colour_type, bit_depth, x, 1);
4951 this->blue = sample(row, colour_type, bit_depth, x, 2); 4951 this->blue = sample(row, colour_type, bit_depth, x, 2);
4952 i = 2; 4952 i = 2;
4953 } 4953 }
4954 if (colour_type & 4) 4954 if (colour_type & 4)
4955 this->alpha = sample(row, colour_type, bit_depth, x, ++i); 4955 this->alpha = sample(row, colour_type, bit_depth, x, ++i);
4956 } 4956 }
4957 4957
4958 /* Calculate the scaled values, these are simply the values divided by 4958 /* Calculate the scaled values, these are simply the values divided by
4959 * 'max' and the error is initialized to the double precision epsilon value 4959 * 'max' and the error is initialized to the double precision epsilon value
4960 * from the header file. 4960 * from the header file.
4961 */ 4961 */
4962 image_pixel_setf(this, max); 4962 image_pixel_setf(this, max);
4963 4963
4964 /* Store the input information for use in the transforms - these will 4964 /* Store the input information for use in the transforms - these will
4965 * modify the information. 4965 * modify the information.
4966 */ 4966 */
4967 this->colour_type = colour_type; 4967 this->colour_type = colour_type;
4968 this->bit_depth = bit_depth; 4968 this->bit_depth = bit_depth;
4969 this->sample_depth = sample_depth; 4969 this->sample_depth = sample_depth;
4970 this->have_tRNS = 0; 4970 this->have_tRNS = 0;
4971} 4971}
4972 4972
4973/* Convert a palette image to an rgb image. This necessarily converts the tRNS 4973/* Convert a palette image to an rgb image. This necessarily converts the tRNS
4974 * chunk at the same time, because the tRNS will be in palette form. The way 4974 * chunk at the same time, because the tRNS will be in palette form. The way
4975 * palette validation works means that the original palette is never updated, 4975 * palette validation works means that the original palette is never updated,
4976 * instead the image_pixel value from the row contains the RGB of the 4976 * instead the image_pixel value from the row contains the RGB of the
4977 * corresponding palette entry and *this* is updated. Consequently this routine 4977 * corresponding palette entry and *this* is updated. Consequently this routine
4978 * only needs to change the colour type information. 4978 * only needs to change the colour type information.
4979 */ 4979 */
4980static void 4980static void
4981image_pixel_convert_PLTE(image_pixel *this) 4981image_pixel_convert_PLTE(image_pixel *this)
4982{ 4982{
4983 if (this->colour_type == PNG_COLOR_TYPE_PALETTE) 4983 if (this->colour_type == PNG_COLOR_TYPE_PALETTE)
4984 { 4984 {
4985 if (this->have_tRNS) 4985 if (this->have_tRNS)
4986 { 4986 {
4987 this->colour_type = PNG_COLOR_TYPE_RGB_ALPHA; 4987 this->colour_type = PNG_COLOR_TYPE_RGB_ALPHA;
4988 this->have_tRNS = 0; 4988 this->have_tRNS = 0;
4989 } 4989 }
4990 else 4990 else
4991 this->colour_type = PNG_COLOR_TYPE_RGB; 4991 this->colour_type = PNG_COLOR_TYPE_RGB;
4992 4992
4993 /* The bit depth of the row changes at this point too (notice that this is 4993 /* The bit depth of the row changes at this point too (notice that this is
4994 * the row format, not the sample depth, which is separate.) 4994 * the row format, not the sample depth, which is separate.)
4995 */ 4995 */
4996 this->bit_depth = 8; 4996 this->bit_depth = 8;
4997 } 4997 }
4998} 4998}
4999 4999
5000/* Add an alpha channel; this will import the tRNS information because tRNS is 5000/* Add an alpha channel; this will import the tRNS information because tRNS is
5001 * not valid in an alpha image. The bit depth will invariably be set to at 5001 * not valid in an alpha image. The bit depth will invariably be set to at
5002 * least 8. Palette images will be converted to alpha (using the above API). 5002 * least 8. Palette images will be converted to alpha (using the above API).
5003 */ 5003 */
5004static void 5004static void
5005image_pixel_add_alpha(image_pixel *this, PNG_CONST standard_display *display) 5005image_pixel_add_alpha(image_pixel *this, PNG_CONST standard_display *display)
5006{ 5006{
5007 if (this->colour_type == PNG_COLOR_TYPE_PALETTE) 5007 if (this->colour_type == PNG_COLOR_TYPE_PALETTE)
5008 image_pixel_convert_PLTE(this); 5008 image_pixel_convert_PLTE(this);
5009 5009
5010 if ((this->colour_type & PNG_COLOR_MASK_ALPHA) == 0) 5010 if ((this->colour_type & PNG_COLOR_MASK_ALPHA) == 0)
5011 { 5011 {
5012 if (this->colour_type == PNG_COLOR_TYPE_GRAY) 5012 if (this->colour_type == PNG_COLOR_TYPE_GRAY)
5013 { 5013 {
5014 if (this->bit_depth < 8) 5014 if (this->bit_depth < 8)
5015 this->bit_depth = 8; 5015 this->bit_depth = 8;
5016 5016
5017 if (this->have_tRNS) 5017 if (this->have_tRNS)
5018 { 5018 {
5019 this->have_tRNS = 0; 5019 this->have_tRNS = 0;
5020 5020
5021 /* Check the input, original, channel value here against the 5021 /* Check the input, original, channel value here against the
5022 * original tRNS gray chunk valie. 5022 * original tRNS gray chunk valie.
5023 */ 5023 */
5024 if (this->red == display->transparent.red) 5024 if (this->red == display->transparent.red)
5025 this->alphaf = 0; 5025 this->alphaf = 0;
5026 else 5026 else
5027 this->alphaf = 1; 5027 this->alphaf = 1;
5028 } 5028 }
5029 else 5029 else
5030 this->alphaf = 1; 5030 this->alphaf = 1;
5031 5031
5032 this->colour_type = PNG_COLOR_TYPE_GRAY_ALPHA; 5032 this->colour_type = PNG_COLOR_TYPE_GRAY_ALPHA;
5033 } 5033 }
5034 5034
5035 else if (this->colour_type == PNG_COLOR_TYPE_RGB) 5035 else if (this->colour_type == PNG_COLOR_TYPE_RGB)
5036 { 5036 {
5037 if (this->have_tRNS) 5037 if (this->have_tRNS)
5038 { 5038 {
5039 this->have_tRNS = 0; 5039 this->have_tRNS = 0;
5040 5040
5041 /* Again, check the exact input values, not the current transformed 5041 /* Again, check the exact input values, not the current transformed
5042 * value! 5042 * value!
5043 */ 5043 */
5044 if (this->red == display->transparent.red && 5044 if (this->red == display->transparent.red &&
5045 this->green == display->transparent.green && 5045 this->green == display->transparent.green &&
5046 this->blue == display->transparent.blue) 5046 this->blue == display->transparent.blue)
5047 this->alphaf = 0; 5047 this->alphaf = 0;
5048 else 5048 else
5049 this->alphaf = 1; 5049 this->alphaf = 1;
5050 5050
5051 this->colour_type = PNG_COLOR_TYPE_RGB_ALPHA; 5051 this->colour_type = PNG_COLOR_TYPE_RGB_ALPHA;
5052 } 5052 }
5053 } 5053 }
5054 5054
5055 /* The error in the alpha is zero and the sBIT value comes from the 5055 /* The error in the alpha is zero and the sBIT value comes from the
5056 * original sBIT data (actually it will always be the original bit depth). 5056 * original sBIT data (actually it will always be the original bit depth).
5057 */ 5057 */
5058 this->alphae = 0; 5058 this->alphae = 0;
5059 this->alpha_sBIT = display->alpha_sBIT; 5059 this->alpha_sBIT = display->alpha_sBIT;
5060 } 5060 }
5061} 5061}
5062 5062
5063struct transform_display; 5063struct transform_display;
5064typedef struct image_transform 5064typedef struct image_transform
5065{ 5065{
5066 /* The name of this transform: a string. */ 5066 /* The name of this transform: a string. */
5067 PNG_CONST char *name; 5067 PNG_CONST char *name;
5068 5068
5069 /* Each transform can be disabled from the command line: */ 5069 /* Each transform can be disabled from the command line: */
5070 int enable; 5070 int enable;
5071 5071
5072 /* The global list of transforms; read only. */ 5072 /* The global list of transforms; read only. */
5073 struct image_transform *PNG_CONST list; 5073 struct image_transform *PNG_CONST list;
5074 5074
5075 /* The global count of the number of times this transform has been set on an 5075 /* The global count of the number of times this transform has been set on an
5076 * image. 5076 * image.
5077 */ 5077 */
5078 unsigned int global_use; 5078 unsigned int global_use;
5079 5079
5080 /* The local count of the number of times this transform has been set. */ 5080 /* The local count of the number of times this transform has been set. */
5081 unsigned int local_use; 5081 unsigned int local_use;
5082 5082
5083 /* The next transform in the list, each transform must call its own next 5083 /* The next transform in the list, each transform must call its own next
5084 * transform after it has processed the pixel successfully. 5084 * transform after it has processed the pixel successfully.
5085 */ 5085 */
5086 PNG_CONST struct image_transform *next; 5086 PNG_CONST struct image_transform *next;
5087 5087
5088 /* A single transform for the image, expressed as a series of function 5088 /* A single transform for the image, expressed as a series of function
5089 * callbacks and some space for values. 5089 * callbacks and some space for values.
5090 * 5090 *
5091 * First a callback to add any required modifications to the png_modifier; 5091 * First a callback to add any required modifications to the png_modifier;
5092 * this gets called just before the modifier is set up for read. 5092 * this gets called just before the modifier is set up for read.
5093 */ 5093 */
5094 void (*ini)(PNG_CONST struct image_transform *this, 5094 void (*ini)(PNG_CONST struct image_transform *this,
5095 struct transform_display *that); 5095 struct transform_display *that);
5096 5096
5097 /* And a callback to set the transform on the current png_read_struct: 5097 /* And a callback to set the transform on the current png_read_struct:
5098 */ 5098 */
5099 void (*set)(PNG_CONST struct image_transform *this, 5099 void (*set)(PNG_CONST struct image_transform *this,
5100 struct transform_display *that, png_structp pp, png_infop pi); 5100 struct transform_display *that, png_structp pp, png_infop pi);
5101 5101
5102 /* Then a transform that takes an input pixel in one PNG format or another 5102 /* Then a transform that takes an input pixel in one PNG format or another
5103 * and modifies it by a pngvalid implementation of the transform (thus 5103 * and modifies it by a pngvalid implementation of the transform (thus
5104 * duplicating the libpng intent without, we hope, duplicating the bugs 5104 * duplicating the libpng intent without, we hope, duplicating the bugs
5105 * in the libpng implementation!) The png_structp is solely to allow error 5105 * in the libpng implementation!) The png_structp is solely to allow error
5106 * reporting via png_error and png_warning. 5106 * reporting via png_error and png_warning.
5107 */ 5107 */
5108 void (*mod)(PNG_CONST struct image_transform *this, image_pixel *that, 5108 void (*mod)(PNG_CONST struct image_transform *this, image_pixel *that,
5109 png_structp pp, PNG_CONST struct transform_display *display); 5109 png_structp pp, PNG_CONST struct transform_display *display);
5110 5110
5111 /* Add this transform to the list and return true if the transform is 5111 /* Add this transform to the list and return true if the transform is
5112 * meaningful for this colour type and bit depth - if false then the 5112 * meaningful for this colour type and bit depth - if false then the
5113 * transform should have no effect on the image so there's not a lot of 5113 * transform should have no effect on the image so there's not a lot of
5114 * point running it. 5114 * point running it.
5115 */ 5115 */
5116 int (*add)(struct image_transform *this, 5116 int (*add)(struct image_transform *this,
5117 PNG_CONST struct image_transform **that, png_byte colour_type, 5117 PNG_CONST struct image_transform **that, png_byte colour_type,
5118 png_byte bit_depth); 5118 png_byte bit_depth);
5119} image_transform; 5119} image_transform;
5120 5120
5121typedef struct transform_display 5121typedef struct transform_display
5122{ 5122{
5123 standard_display this; 5123 standard_display this;
5124 5124
5125 /* Parameters */ 5125 /* Parameters */
5126 png_modifier* pm; 5126 png_modifier* pm;
5127 PNG_CONST image_transform* transform_list; 5127 PNG_CONST image_transform* transform_list;
5128 5128
5129 /* Local variables */ 5129 /* Local variables */
5130 png_byte output_colour_type; 5130 png_byte output_colour_type;
5131 png_byte output_bit_depth; 5131 png_byte output_bit_depth;
5132 5132
5133 /* Modifications (not necessarily used.) */ 5133 /* Modifications (not necessarily used.) */
5134 gama_modification gama_mod; 5134 gama_modification gama_mod;
5135 chrm_modification chrm_mod; 5135 chrm_modification chrm_mod;
5136 srgb_modification srgb_mod; 5136 srgb_modification srgb_mod;
5137} transform_display; 5137} transform_display;
5138 5138
5139/* Set sRGB, cHRM and gAMA transforms as required by the current encoding. */ 5139/* Set sRGB, cHRM and gAMA transforms as required by the current encoding. */
5140static void 5140static void
5141transform_set_encoding(transform_display *this) 5141transform_set_encoding(transform_display *this)
5142{ 5142{
5143 /* Set up the png_modifier '_current' fields then use these to determine how 5143 /* Set up the png_modifier '_current' fields then use these to determine how
5144 * to add appropriate chunks. 5144 * to add appropriate chunks.
5145 */ 5145 */
5146 png_modifier *pm = this->pm; 5146 png_modifier *pm = this->pm;
5147 5147
5148 modifier_set_encoding(pm); 5148 modifier_set_encoding(pm);
5149 5149
5150 if (modifier_color_encoding_is_set(pm)) 5150 if (modifier_color_encoding_is_set(pm))
5151 { 5151 {
5152 if (modifier_color_encoding_is_sRGB(pm)) 5152 if (modifier_color_encoding_is_sRGB(pm))
5153 srgb_modification_init(&this->srgb_mod, pm, PNG_sRGB_INTENT_ABSOLUTE); 5153 srgb_modification_init(&this->srgb_mod, pm, PNG_sRGB_INTENT_ABSOLUTE);
5154 5154
5155 else 5155 else
5156 { 5156 {
5157 /* Set gAMA and cHRM separately. */ 5157 /* Set gAMA and cHRM separately. */
5158 gama_modification_init(&this->gama_mod, pm, pm->current_gamma); 5158 gama_modification_init(&this->gama_mod, pm, pm->current_gamma);
5159 5159
5160 if (pm->current_encoding != 0) 5160 if (pm->current_encoding != 0)
5161 chrm_modification_init(&this->chrm_mod, pm, pm->current_encoding); 5161 chrm_modification_init(&this->chrm_mod, pm, pm->current_encoding);
5162 } 5162 }
5163 } 5163 }
5164} 5164}
5165 5165
5166/* Three functions to end the list: */ 5166/* Three functions to end the list: */
5167static void 5167static void
5168image_transform_ini_end(PNG_CONST image_transform *this, 5168image_transform_ini_end(PNG_CONST image_transform *this,
5169 transform_display *that) 5169 transform_display *that)
5170{ 5170{
5171 UNUSED(this) 5171 UNUSED(this)
5172 UNUSED(that) 5172 UNUSED(that)
5173} 5173}
5174 5174
5175static void 5175static void
5176image_transform_set_end(PNG_CONST image_transform *this, 5176image_transform_set_end(PNG_CONST image_transform *this,
5177 transform_display *that, png_structp pp, png_infop pi) 5177 transform_display *that, png_structp pp, png_infop pi)
5178{ 5178{
5179 UNUSED(this) 5179 UNUSED(this)
5180 UNUSED(that) 5180 UNUSED(that)
5181 UNUSED(pp) 5181 UNUSED(pp)
5182 UNUSED(pi) 5182 UNUSED(pi)
5183} 5183}
5184 5184
5185/* At the end of the list recalculate the output image pixel value from the 5185/* At the end of the list recalculate the output image pixel value from the
5186 * double precision values set up by the preceding 'mod' calls: 5186 * double precision values set up by the preceding 'mod' calls:
5187 */ 5187 */
5188static unsigned int 5188static unsigned int
5189sample_scale(double sample_value, unsigned int scale) 5189sample_scale(double sample_value, unsigned int scale)
5190{ 5190{
5191 sample_value = floor(sample_value * scale + .5); 5191 sample_value = floor(sample_value * scale + .5);
5192 5192
5193 /* Return NaN as 0: */ 5193 /* Return NaN as 0: */
5194 if (!(sample_value > 0)) 5194 if (!(sample_value > 0))
5195 sample_value = 0; 5195 sample_value = 0;
5196 else if (sample_value > scale) 5196 else if (sample_value > scale)
5197 sample_value = scale; 5197 sample_value = scale;
5198 5198
5199 return (unsigned int)sample_value; 5199 return (unsigned int)sample_value;
5200} 5200}
5201 5201
5202static void 5202static void
5203image_transform_mod_end(PNG_CONST image_transform *this, image_pixel *that, 5203image_transform_mod_end(PNG_CONST image_transform *this, image_pixel *that,
5204 png_structp pp, PNG_CONST transform_display *display) 5204 png_structp pp, PNG_CONST transform_display *display)
5205{ 5205{
5206 PNG_CONST unsigned int scale = (1U<<that->sample_depth)-1; 5206 PNG_CONST unsigned int scale = (1U<<that->sample_depth)-1;
5207 5207
5208 UNUSED(this) 5208 UNUSED(this)
5209 UNUSED(pp) 5209 UNUSED(pp)
5210 UNUSED(display) 5210 UNUSED(display)
5211 5211
5212 /* At the end recalculate the digitized red green and blue values according 5212 /* At the end recalculate the digitized red green and blue values according
5213 * to the current sample_depth of the pixel. 5213 * to the current sample_depth of the pixel.
5214 * 5214 *
5215 * The sample value is simply scaled to the maximum, checking for over 5215 * The sample value is simply scaled to the maximum, checking for over
5216 * and underflow (which can both happen for some image transforms, 5216 * and underflow (which can both happen for some image transforms,
5217 * including simple size scaling, though libpng doesn't do that at present. 5217 * including simple size scaling, though libpng doesn't do that at present.
5218 */ 5218 */
5219 that->red = sample_scale(that->redf, scale); 5219 that->red = sample_scale(that->redf, scale);
5220 5220
5221 /* The error value is increased, at the end, according to the lowest sBIT 5221 /* The error value is increased, at the end, according to the lowest sBIT
5222 * value seen. Common sense tells us that the intermediate integer 5222 * value seen. Common sense tells us that the intermediate integer
5223 * representations are no more accurate than +/- 0.5 in the integral values, 5223 * representations are no more accurate than +/- 0.5 in the integral values,
5224 * the sBIT allows the implementation to be worse than this. In addition the 5224 * the sBIT allows the implementation to be worse than this. In addition the
5225 * PNG specification actually permits any error within the range (-1..+1), 5225 * PNG specification actually permits any error within the range (-1..+1),
5226 * but that is ignored here. Instead the final digitized value is compared, 5226 * but that is ignored here. Instead the final digitized value is compared,
5227 * below to the digitized value of the error limits - this has the net effect 5227 * below to the digitized value of the error limits - this has the net effect
5228 * of allowing (almost) +/-1 in the output value. It's difficult to see how 5228 * of allowing (almost) +/-1 in the output value. It's difficult to see how
5229 * any algorithm that digitizes intermediate results can be more accurate. 5229 * any algorithm that digitizes intermediate results can be more accurate.
5230 */ 5230 */
5231 that->rede += 1./(2*((1U<<that->red_sBIT)-1)); 5231 that->rede += 1./(2*((1U<<that->red_sBIT)-1));
5232 5232
5233 if (that->colour_type & PNG_COLOR_MASK_COLOR) 5233 if (that->colour_type & PNG_COLOR_MASK_COLOR)
5234 { 5234 {
5235 that->green = sample_scale(that->greenf, scale); 5235 that->green = sample_scale(that->greenf, scale);
5236 that->blue = sample_scale(that->bluef, scale); 5236 that->blue = sample_scale(that->bluef, scale);
5237 that->greene += 1./(2*((1U<<that->green_sBIT)-1)); 5237 that->greene += 1./(2*((1U<<that->green_sBIT)-1));
5238 that->bluee += 1./(2*((1U<<that->blue_sBIT)-1)); 5238 that->bluee += 1./(2*((1U<<that->blue_sBIT)-1));
5239 } 5239 }
5240 else 5240 else
5241 { 5241 {
5242 that->blue = that->green = that->red; 5242 that->blue = that->green = that->red;
5243 that->bluef = that->greenf = that->redf; 5243 that->bluef = that->greenf = that->redf;
5244 that->bluee = that->greene = that->rede; 5244 that->bluee = that->greene = that->rede;
5245 } 5245 }
5246 5246
5247 if ((that->colour_type & PNG_COLOR_MASK_ALPHA) || 5247 if ((that->colour_type & PNG_COLOR_MASK_ALPHA) ||
5248 that->colour_type == PNG_COLOR_TYPE_PALETTE) 5248 that->colour_type == PNG_COLOR_TYPE_PALETTE)
5249 { 5249 {
5250 that->alpha = sample_scale(that->alphaf, scale); 5250 that->alpha = sample_scale(that->alphaf, scale);
5251 that->alphae += 1./(2*((1U<<that->alpha_sBIT)-1)); 5251 that->alphae += 1./(2*((1U<<that->alpha_sBIT)-1));
5252 } 5252 }
5253 else 5253 else
5254 { 5254 {
5255 that->alpha = scale; /* opaque */ 5255 that->alpha = scale; /* opaque */
5256 that->alpha = 1; /* Override this. */ 5256 that->alpha = 1; /* Override this. */
5257 that->alphae = 0; /* It's exact ;-) */ 5257 that->alphae = 0; /* It's exact ;-) */
5258 } 5258 }
5259} 5259}
5260 5260
5261/* Static 'end' structure: */ 5261/* Static 'end' structure: */
5262static image_transform image_transform_end = 5262static image_transform image_transform_end =
5263{ 5263{
5264 "(end)", /* name */ 5264 "(end)", /* name */
5265 1, /* enable */ 5265 1, /* enable */
5266 0, /* list */ 5266 0, /* list */
5267 0, /* global_use */ 5267 0, /* global_use */
5268 0, /* local_use */ 5268 0, /* local_use */
5269 0, /* next */ 5269 0, /* next */
5270 image_transform_ini_end, 5270 image_transform_ini_end,
5271 image_transform_set_end, 5271 image_transform_set_end,
5272 image_transform_mod_end, 5272 image_transform_mod_end,
5273 0 /* never called, I want it to crash if it is! */ 5273 0 /* never called, I want it to crash if it is! */
5274}; 5274};
5275 5275
5276/* Reader callbacks and implementations, where they differ from the standard 5276/* Reader callbacks and implementations, where they differ from the standard
5277 * ones. 5277 * ones.
5278 */ 5278 */
5279static void 5279static void
5280transform_display_init(transform_display *dp, png_modifier *pm, png_uint_32 id, 5280transform_display_init(transform_display *dp, png_modifier *pm, png_uint_32 id,
5281 PNG_CONST image_transform *transform_list) 5281 PNG_CONST image_transform *transform_list)
5282{ 5282{
5283 memset(dp, 0, sizeof *dp); 5283 memset(dp, 0, sizeof *dp);
5284 5284
5285 /* Standard fields */ 5285 /* Standard fields */
5286 standard_display_init(&dp->this, &pm->this, id, 0/*do_interlace*/, 5286 standard_display_init(&dp->this, &pm->this, id, 0/*do_interlace*/,
5287 pm->use_update_info); 5287 pm->use_update_info);
5288 5288
5289 /* Parameter fields */ 5289 /* Parameter fields */
5290 dp->pm = pm; 5290 dp->pm = pm;
5291 dp->transform_list = transform_list; 5291 dp->transform_list = transform_list;
5292 5292
5293 /* Local variable fields */ 5293 /* Local variable fields */
5294 dp->output_colour_type = 255; /* invalid */ 5294 dp->output_colour_type = 255; /* invalid */
5295 dp->output_bit_depth = 255; /* invalid */ 5295 dp->output_bit_depth = 255; /* invalid */
5296} 5296}
5297 5297
5298static void 5298static void
5299transform_info_imp(transform_display *dp, png_structp pp, png_infop pi) 5299transform_info_imp(transform_display *dp, png_structp pp, png_infop pi)
5300{ 5300{
5301 /* Reuse the standard stuff as appropriate. */ 5301 /* Reuse the standard stuff as appropriate. */
5302 standard_info_part1(&dp->this, pp, pi); 5302 standard_info_part1(&dp->this, pp, pi);
5303 5303
5304 /* Now set the list of transforms. */ 5304 /* Now set the list of transforms. */
5305 dp->transform_list->set(dp->transform_list, dp, pp, pi); 5305 dp->transform_list->set(dp->transform_list, dp, pp, pi);
5306 5306
5307 /* Update the info structure for these transforms: */ 5307 /* Update the info structure for these transforms: */
5308 { 5308 {
5309 int i = dp->this.use_update_info; 5309 int i = dp->this.use_update_info;
5310 /* Always do one call, even if use_update_info is 0. */ 5310 /* Always do one call, even if use_update_info is 0. */
5311 do 5311 do
5312 png_read_update_info(pp, pi); 5312 png_read_update_info(pp, pi);
5313 while (--i > 0); 5313 while (--i > 0);
5314 } 5314 }
5315 5315
5316 /* And get the output information into the standard_display */ 5316 /* And get the output information into the standard_display */
5317 standard_info_part2(&dp->this, pp, pi, 1/*images*/); 5317 standard_info_part2(&dp->this, pp, pi, 1/*images*/);
5318 5318
5319 /* Plus the extra stuff we need for the transform tests: */ 5319 /* Plus the extra stuff we need for the transform tests: */
5320 dp->output_colour_type = png_get_color_type(pp, pi); 5320 dp->output_colour_type = png_get_color_type(pp, pi);
5321 dp->output_bit_depth = png_get_bit_depth(pp, pi); 5321 dp->output_bit_depth = png_get_bit_depth(pp, pi);
5322 5322
5323 /* Validate the combination of colour type and bit depth that we are getting 5323 /* Validate the combination of colour type and bit depth that we are getting
5324 * out of libpng; the semantics of something not in the PNG spec are, at 5324 * out of libpng; the semantics of something not in the PNG spec are, at
5325 * best, unclear. 5325 * best, unclear.
5326 */ 5326 */
5327 switch (dp->output_colour_type) 5327 switch (dp->output_colour_type)
5328 { 5328 {
5329 case PNG_COLOR_TYPE_PALETTE: 5329 case PNG_COLOR_TYPE_PALETTE:
5330 if (dp->output_bit_depth > 8) goto error; 5330 if (dp->output_bit_depth > 8) goto error;
5331 /*FALL THROUGH*/ 5331 /*FALL THROUGH*/
5332 case PNG_COLOR_TYPE_GRAY: 5332 case PNG_COLOR_TYPE_GRAY:
5333 if (dp->output_bit_depth == 1 || dp->output_bit_depth == 2 || 5333 if (dp->output_bit_depth == 1 || dp->output_bit_depth == 2 ||
5334 dp->output_bit_depth == 4) 5334 dp->output_bit_depth == 4)
5335 break; 5335 break;
5336 /*FALL THROUGH*/ 5336 /*FALL THROUGH*/
5337 default: 5337 default:
5338 if (dp->output_bit_depth == 8 || dp->output_bit_depth == 16) 5338 if (dp->output_bit_depth == 8 || dp->output_bit_depth == 16)
5339 break; 5339 break;
5340 /*FALL THROUGH*/ 5340 /*FALL THROUGH*/
5341 error: 5341 error:
5342 { 5342 {
5343 char message[128]; 5343 char message[128];
5344 size_t pos; 5344 size_t pos;
5345 5345
5346 pos = safecat(message, sizeof message, 0, 5346 pos = safecat(message, sizeof message, 0,
5347 "invalid final bit depth: colour type("); 5347 "invalid final bit depth: colour type(");
5348 pos = safecatn(message, sizeof message, pos, dp->output_colour_type); 5348 pos = safecatn(message, sizeof message, pos, dp->output_colour_type);
5349 pos = safecat(message, sizeof message, pos, ") with bit depth: "); 5349 pos = safecat(message, sizeof message, pos, ") with bit depth: ");
5350 pos = safecatn(message, sizeof message, pos, dp->output_bit_depth); 5350 pos = safecatn(message, sizeof message, pos, dp->output_bit_depth);
5351 5351
5352 png_error(pp, message); 5352 png_error(pp, message);
5353 } 5353 }
5354 } 5354 }
5355 5355
5356 /* Use a test pixel to check that the output agrees with what we expect - 5356 /* Use a test pixel to check that the output agrees with what we expect -
5357 * this avoids running the whole test if the output is unexpected. 5357 * this avoids running the whole test if the output is unexpected.
5358 */ 5358 */
5359 { 5359 {
5360 image_pixel test_pixel; 5360 image_pixel test_pixel;
5361 5361
5362 memset(&test_pixel, 0, sizeof test_pixel); 5362 memset(&test_pixel, 0, sizeof test_pixel);
5363 test_pixel.colour_type = dp->this.colour_type; /* input */ 5363 test_pixel.colour_type = dp->this.colour_type; /* input */
5364 test_pixel.bit_depth = dp->this.bit_depth; 5364 test_pixel.bit_depth = dp->this.bit_depth;
5365 if (test_pixel.colour_type == PNG_COLOR_TYPE_PALETTE) 5365 if (test_pixel.colour_type == PNG_COLOR_TYPE_PALETTE)
5366 test_pixel.sample_depth = 8; 5366 test_pixel.sample_depth = 8;
5367 else 5367 else
5368 test_pixel.sample_depth = test_pixel.bit_depth; 5368 test_pixel.sample_depth = test_pixel.bit_depth;
5369 /* Don't need sBIT here, but it must be set to non-zero to avoid 5369 /* Don't need sBIT here, but it must be set to non-zero to avoid
5370 * arithmetic overflows. 5370 * arithmetic overflows.
5371 */ 5371 */
5372 test_pixel.have_tRNS = dp->this.is_transparent; 5372 test_pixel.have_tRNS = dp->this.is_transparent;
5373 test_pixel.red_sBIT = test_pixel.green_sBIT = test_pixel.blue_sBIT = 5373 test_pixel.red_sBIT = test_pixel.green_sBIT = test_pixel.blue_sBIT =
5374 test_pixel.alpha_sBIT = test_pixel.sample_depth; 5374 test_pixel.alpha_sBIT = test_pixel.sample_depth;
5375 5375
5376 dp->transform_list->mod(dp->transform_list, &test_pixel, pp, dp); 5376 dp->transform_list->mod(dp->transform_list, &test_pixel, pp, dp);
5377 5377
5378 if (test_pixel.colour_type != dp->output_colour_type) 5378 if (test_pixel.colour_type != dp->output_colour_type)
5379 { 5379 {
5380 char message[128]; 5380 char message[128];
5381 size_t pos = safecat(message, sizeof message, 0, "colour type "); 5381 size_t pos = safecat(message, sizeof message, 0, "colour type ");
5382 5382
5383 pos = safecatn(message, sizeof message, pos, dp->output_colour_type); 5383 pos = safecatn(message, sizeof message, pos, dp->output_colour_type);
5384 pos = safecat(message, sizeof message, pos, " expected "); 5384 pos = safecat(message, sizeof message, pos, " expected ");
5385 pos = safecatn(message, sizeof message, pos, test_pixel.colour_type); 5385 pos = safecatn(message, sizeof message, pos, test_pixel.colour_type);
5386 5386
5387 png_error(pp, message); 5387 png_error(pp, message);
5388 } 5388 }
5389 5389
5390 if (test_pixel.bit_depth != dp->output_bit_depth) 5390 if (test_pixel.bit_depth != dp->output_bit_depth)
5391 { 5391 {
5392 char message[128]; 5392 char message[128];
5393 size_t pos = safecat(message, sizeof message, 0, "bit depth "); 5393 size_t pos = safecat(message, sizeof message, 0, "bit depth ");
5394 5394
5395 pos = safecatn(message, sizeof message, pos, dp->output_bit_depth); 5395 pos = safecatn(message, sizeof message, pos, dp->output_bit_depth);
5396 pos = safecat(message, sizeof message, pos, " expected "); 5396 pos = safecat(message, sizeof message, pos, " expected ");
5397 pos = safecatn(message, sizeof message, pos, test_pixel.bit_depth); 5397 pos = safecatn(message, sizeof message, pos, test_pixel.bit_depth);
5398 5398
5399 png_error(pp, message); 5399 png_error(pp, message);
5400 } 5400 }
5401 5401
5402 /* If both bit depth and colour type are correct check the sample depth. 5402 /* If both bit depth and colour type are correct check the sample depth.
5403 * I believe these are both internal errors. 5403 * I believe these are both internal errors.
5404 */ 5404 */
5405 if (test_pixel.colour_type == PNG_COLOR_TYPE_PALETTE) 5405 if (test_pixel.colour_type == PNG_COLOR_TYPE_PALETTE)
5406 { 5406 {
5407 if (test_pixel.sample_depth != 8) /* oops - internal error! */ 5407 if (test_pixel.sample_depth != 8) /* oops - internal error! */
5408 png_error(pp, "pngvalid: internal: palette sample depth not 8"); 5408 png_error(pp, "pngvalid: internal: palette sample depth not 8");
5409 } 5409 }
5410 else if (test_pixel.sample_depth != dp->output_bit_depth) 5410 else if (test_pixel.sample_depth != dp->output_bit_depth)
5411 { 5411 {
5412 char message[128]; 5412 char message[128];
5413 size_t pos = safecat(message, sizeof message, 0, 5413 size_t pos = safecat(message, sizeof message, 0,
5414 "internal: sample depth "); 5414 "internal: sample depth ");
5415 5415
5416 pos = safecatn(message, sizeof message, pos, dp->output_bit_depth); 5416 pos = safecatn(message, sizeof message, pos, dp->output_bit_depth);
5417 pos = safecat(message, sizeof message, pos, " expected "); 5417 pos = safecat(message, sizeof message, pos, " expected ");
5418 pos = safecatn(message, sizeof message, pos, test_pixel.sample_depth); 5418 pos = safecatn(message, sizeof message, pos, test_pixel.sample_depth);
5419 5419
5420 png_error(pp, message); 5420 png_error(pp, message);
5421 } 5421 }
5422 } 5422 }
5423} 5423}
5424 5424
5425static void 5425static void
5426transform_info(png_structp pp, png_infop pi) 5426transform_info(png_structp pp, png_infop pi)
5427{ 5427{
5428 transform_info_imp(voidcast(transform_display*, png_get_progressive_ptr(pp)), 5428 transform_info_imp(voidcast(transform_display*, png_get_progressive_ptr(pp)),
5429 pp, pi); 5429 pp, pi);
5430} 5430}
5431 5431
5432static void 5432static void
5433transform_range_check(png_structp pp, unsigned int r, unsigned int g, 5433transform_range_check(png_structp pp, unsigned int r, unsigned int g,
5434 unsigned int b, unsigned int a, unsigned int in_digitized, double in, 5434 unsigned int b, unsigned int a, unsigned int in_digitized, double in,
5435 unsigned int out, png_byte sample_depth, double err, double limit, 5435 unsigned int out, png_byte sample_depth, double err, double limit,
5436 PNG_CONST char *name, double digitization_error) 5436 PNG_CONST char *name, double digitization_error)
5437{ 5437{
5438 /* Compare the scaled, digitzed, values of our local calculation (in+-err) 5438 /* Compare the scaled, digitzed, values of our local calculation (in+-err)
5439 * with the digitized values libpng produced; 'sample_depth' is the actual 5439 * with the digitized values libpng produced; 'sample_depth' is the actual
5440 * digitization depth of the libpng output colors (the bit depth except for 5440 * digitization depth of the libpng output colors (the bit depth except for
5441 * palette images where it is always 8.) The check on 'err' is to detect 5441 * palette images where it is always 8.) The check on 'err' is to detect
5442 * internal errors in pngvalid itself. 5442 * internal errors in pngvalid itself.
5443 */ 5443 */
5444 unsigned int max = (1U<<sample_depth)-1; 5444 unsigned int max = (1U<<sample_depth)-1;
5445 double in_min = ceil((in-err)*max - digitization_error); 5445 double in_min = ceil((in-err)*max - digitization_error);
5446 double in_max = floor((in+err)*max + digitization_error); 5446 double in_max = floor((in+err)*max + digitization_error);
5447 if (err > limit || !(out >= in_min && out <= in_max)) 5447 if (err > limit || !(out >= in_min && out <= in_max))
5448 { 5448 {
5449 char message[256]; 5449 char message[256];
5450 size_t pos; 5450 size_t pos;
5451 5451
5452 pos = safecat(message, sizeof message, 0, name); 5452 pos = safecat(message, sizeof message, 0, name);
5453 pos = safecat(message, sizeof message, pos, " output value error: rgba("); 5453 pos = safecat(message, sizeof message, pos, " output value error: rgba(");
5454 pos = safecatn(message, sizeof message, pos, r); 5454 pos = safecatn(message, sizeof message, pos, r);
5455 pos = safecat(message, sizeof message, pos, ","); 5455 pos = safecat(message, sizeof message, pos, ",");
5456 pos = safecatn(message, sizeof message, pos, g); 5456 pos = safecatn(message, sizeof message, pos, g);
5457 pos = safecat(message, sizeof message, pos, ","); 5457 pos = safecat(message, sizeof message, pos, ",");
5458 pos = safecatn(message, sizeof message, pos, b); 5458 pos = safecatn(message, sizeof message, pos, b);
5459 pos = safecat(message, sizeof message, pos, ","); 5459 pos = safecat(message, sizeof message, pos, ",");
5460 pos = safecatn(message, sizeof message, pos, a); 5460 pos = safecatn(message, sizeof message, pos, a);
5461 pos = safecat(message, sizeof message, pos, "): "); 5461 pos = safecat(message, sizeof message, pos, "): ");
5462 pos = safecatn(message, sizeof message, pos, out); 5462 pos = safecatn(message, sizeof message, pos, out);
5463 pos = safecat(message, sizeof message, pos, " expected: "); 5463 pos = safecat(message, sizeof message, pos, " expected: ");
5464 pos = safecatn(message, sizeof message, pos, in_digitized); 5464 pos = safecatn(message, sizeof message, pos, in_digitized);
5465 pos = safecat(message, sizeof message, pos, " ("); 5465 pos = safecat(message, sizeof message, pos, " (");
5466 pos = safecatd(message, sizeof message, pos, (in-err)*max, 3); 5466 pos = safecatd(message, sizeof message, pos, (in-err)*max, 3);
5467 pos = safecat(message, sizeof message, pos, ".."); 5467 pos = safecat(message, sizeof message, pos, "..");
5468 pos = safecatd(message, sizeof message, pos, (in+err)*max, 3); 5468 pos = safecatd(message, sizeof message, pos, (in+err)*max, 3);
5469 pos = safecat(message, sizeof message, pos, ")"); 5469 pos = safecat(message, sizeof message, pos, ")");
5470 5470
5471 png_error(pp, message); 5471 png_error(pp, message);
5472 } 5472 }
5473} 5473}
5474 5474
5475static void 5475static void
5476transform_image_validate(transform_display *dp, png_structp pp, png_infop pi) 5476transform_image_validate(transform_display *dp, png_structp pp, png_infop pi)
5477{ 5477{
5478 /* Constants for the loop below: */ 5478 /* Constants for the loop below: */
5479 PNG_CONST png_store* PNG_CONST ps = dp->this.ps; 5479 PNG_CONST png_store* PNG_CONST ps = dp->this.ps;
5480 PNG_CONST png_byte in_ct = dp->this.colour_type; 5480 PNG_CONST png_byte in_ct = dp->this.colour_type;
5481 PNG_CONST png_byte in_bd = dp->this.bit_depth; 5481 PNG_CONST png_byte in_bd = dp->this.bit_depth;
5482 PNG_CONST png_uint_32 w = dp->this.w; 5482 PNG_CONST png_uint_32 w = dp->this.w;
5483 PNG_CONST png_uint_32 h = dp->this.h; 5483 PNG_CONST png_uint_32 h = dp->this.h;
5484 PNG_CONST png_byte out_ct = dp->output_colour_type; 5484 PNG_CONST png_byte out_ct = dp->output_colour_type;
5485 PNG_CONST png_byte out_bd = dp->output_bit_depth; 5485 PNG_CONST png_byte out_bd = dp->output_bit_depth;
5486 PNG_CONST png_byte sample_depth = (png_byte)(out_ct == 5486 PNG_CONST png_byte sample_depth = (png_byte)(out_ct ==
5487 PNG_COLOR_TYPE_PALETTE ? 8 : out_bd); 5487 PNG_COLOR_TYPE_PALETTE ? 8 : out_bd);
5488 PNG_CONST png_byte red_sBIT = dp->this.red_sBIT; 5488 PNG_CONST png_byte red_sBIT = dp->this.red_sBIT;
5489 PNG_CONST png_byte green_sBIT = dp->this.green_sBIT; 5489 PNG_CONST png_byte green_sBIT = dp->this.green_sBIT;
5490 PNG_CONST png_byte blue_sBIT = dp->this.blue_sBIT; 5490 PNG_CONST png_byte blue_sBIT = dp->this.blue_sBIT;
5491 PNG_CONST png_byte alpha_sBIT = dp->this.alpha_sBIT; 5491 PNG_CONST png_byte alpha_sBIT = dp->this.alpha_sBIT;
5492 PNG_CONST int have_tRNS = dp->this.is_transparent; 5492 PNG_CONST int have_tRNS = dp->this.is_transparent;
5493 double digitization_error; 5493 double digitization_error;
5494 5494
5495 store_palette out_palette; 5495 store_palette out_palette;
5496 png_uint_32 y; 5496 png_uint_32 y;
5497 5497
5498 UNUSED(pi) 5498 UNUSED(pi)
5499 5499
5500 /* Check for row overwrite errors */ 5500 /* Check for row overwrite errors */
5501 store_image_check(dp->this.ps, pp, 0); 5501 store_image_check(dp->this.ps, pp, 0);
5502 5502
5503 /* Read the palette corresponding to the output if the output colour type 5503 /* Read the palette corresponding to the output if the output colour type
5504 * indicates a palette, othewise set out_palette to garbage. 5504 * indicates a palette, othewise set out_palette to garbage.
5505 */ 5505 */
5506 if (out_ct == PNG_COLOR_TYPE_PALETTE) 5506 if (out_ct == PNG_COLOR_TYPE_PALETTE)
5507 { 5507 {
5508 /* Validate that the palette count itself has not changed - this is not 5508 /* Validate that the palette count itself has not changed - this is not
5509 * expected. 5509 * expected.
5510 */ 5510 */
5511 int npalette = (-1); 5511 int npalette = (-1);
5512 5512
5513 (void)read_palette(out_palette, &npalette, pp, pi); 5513 (void)read_palette(out_palette, &npalette, pp, pi);
5514 if (npalette != dp->this.npalette) 5514 if (npalette != dp->this.npalette)
5515 png_error(pp, "unexpected change in palette size"); 5515 png_error(pp, "unexpected change in palette size");
5516 5516
5517 digitization_error = .5; 5517 digitization_error = .5;
5518 } 5518 }
5519 else 5519 else
5520 { 5520 {
5521 png_byte in_sample_depth; 5521 png_byte in_sample_depth;
5522 5522
5523 memset(out_palette, 0x5e, sizeof out_palette); 5523 memset(out_palette, 0x5e, sizeof out_palette);
5524 5524
5525 /* assume-8-bit-calculations means assume that if the input has 8 bit 5525 /* assume-8-bit-calculations means assume that if the input has 8 bit
5526 * (or less) samples and the output has 16 bit samples the calculations 5526 * (or less) samples and the output has 16 bit samples the calculations
5527 * will be done with 8 bit precision, not 16. 5527 * will be done with 8 bit precision, not 16.
5528 * 5528 *
5529 * TODO: fix this in libpng; png_set_expand_16 should cause 16 bit 5529 * TODO: fix this in libpng; png_set_expand_16 should cause 16 bit
5530 * calculations to be used throughout. 5530 * calculations to be used throughout.
5531 */ 5531 */
5532 if (in_ct == PNG_COLOR_TYPE_PALETTE || in_bd < 16) 5532 if (in_ct == PNG_COLOR_TYPE_PALETTE || in_bd < 16)
5533 in_sample_depth = 8; 5533 in_sample_depth = 8;
5534 else 5534 else
5535 in_sample_depth = in_bd; 5535 in_sample_depth = in_bd;
5536 5536
5537 if (sample_depth != 16 || in_sample_depth > 8 || 5537 if (sample_depth != 16 || in_sample_depth > 8 ||
5538 !dp->pm->calculations_use_input_precision) 5538 !dp->pm->calculations_use_input_precision)
5539 digitization_error = .5; 5539 digitization_error = .5;
5540 5540
5541 /* Else errors are at 8 bit precision, scale .5 in 8 bits to the 16 bits: 5541 /* Else errors are at 8 bit precision, scale .5 in 8 bits to the 16 bits:
5542 */ 5542 */
5543 else 5543 else
5544 digitization_error = .5 * 257; 5544 digitization_error = .5 * 257;
5545 } 5545 }
5546 5546
5547 for (y=0; y<h; ++y) 5547 for (y=0; y<h; ++y)
5548 { 5548 {
5549 png_const_bytep PNG_CONST pRow = store_image_row(ps, pp, 0, y); 5549 png_const_bytep PNG_CONST pRow = store_image_row(ps, pp, 0, y);
5550 png_uint_32 x; 5550 png_uint_32 x;
5551 5551
5552 /* The original, standard, row pre-transforms. */ 5552 /* The original, standard, row pre-transforms. */
5553 png_byte std[STANDARD_ROWMAX]; 5553 png_byte std[STANDARD_ROWMAX];
5554 5554
5555 transform_row(pp, std, in_ct, in_bd, y); 5555 transform_row(pp, std, in_ct, in_bd, y);
5556 5556
5557 /* Go through each original pixel transforming it and comparing with what 5557 /* Go through each original pixel transforming it and comparing with what
5558 * libpng did to the same pixel. 5558 * libpng did to the same pixel.
5559 */ 5559 */
5560 for (x=0; x<w; ++x) 5560 for (x=0; x<w; ++x)
5561 { 5561 {
5562 image_pixel in_pixel, out_pixel; 5562 image_pixel in_pixel, out_pixel;
5563 unsigned int r, g, b, a; 5563 unsigned int r, g, b, a;
5564 5564
5565 /* Find out what we think the pixel should be: */ 5565 /* Find out what we think the pixel should be: */
5566 image_pixel_init(&in_pixel, std, in_ct, in_bd, x, dp->this.palette); 5566 image_pixel_init(&in_pixel, std, in_ct, in_bd, x, dp->this.palette);
5567 5567
5568 in_pixel.red_sBIT = red_sBIT; 5568 in_pixel.red_sBIT = red_sBIT;
5569 in_pixel.green_sBIT = green_sBIT; 5569 in_pixel.green_sBIT = green_sBIT;
5570 in_pixel.blue_sBIT = blue_sBIT; 5570 in_pixel.blue_sBIT = blue_sBIT;
5571 in_pixel.alpha_sBIT = alpha_sBIT; 5571 in_pixel.alpha_sBIT = alpha_sBIT;
5572 in_pixel.have_tRNS = have_tRNS; 5572 in_pixel.have_tRNS = have_tRNS;
5573 5573
5574 /* For error detection, below. */ 5574 /* For error detection, below. */
5575 r = in_pixel.red; 5575 r = in_pixel.red;
5576 g = in_pixel.green; 5576 g = in_pixel.green;
5577 b = in_pixel.blue; 5577 b = in_pixel.blue;
5578 a = in_pixel.alpha; 5578 a = in_pixel.alpha;
5579 5579
5580 dp->transform_list->mod(dp->transform_list, &in_pixel, pp, dp); 5580 dp->transform_list->mod(dp->transform_list, &in_pixel, pp, dp);
5581 5581
5582 /* Read the output pixel and compare it to what we got, we don't 5582 /* Read the output pixel and compare it to what we got, we don't
5583 * use the error field here, so no need to update sBIT. 5583 * use the error field here, so no need to update sBIT.
5584 */ 5584 */
5585 image_pixel_init(&out_pixel, pRow, out_ct, out_bd, x, out_palette); 5585 image_pixel_init(&out_pixel, pRow, out_ct, out_bd, x, out_palette);
5586 5586
5587 /* We don't expect changes to the index here even if the bit depth is 5587 /* We don't expect changes to the index here even if the bit depth is
5588 * changed. 5588 * changed.
5589 */ 5589 */
5590 if (in_ct == PNG_COLOR_TYPE_PALETTE && 5590 if (in_ct == PNG_COLOR_TYPE_PALETTE &&
5591 out_ct == PNG_COLOR_TYPE_PALETTE) 5591 out_ct == PNG_COLOR_TYPE_PALETTE)
5592 { 5592 {
5593 if (in_pixel.palette_index != out_pixel.palette_index) 5593 if (in_pixel.palette_index != out_pixel.palette_index)
5594 png_error(pp, "unexpected transformed palette index"); 5594 png_error(pp, "unexpected transformed palette index");
5595 } 5595 }
5596 5596
5597 /* Check the colours for palette images too - in fact the palette could 5597 /* Check the colours for palette images too - in fact the palette could
5598 * be separately verified itself in most cases. 5598 * be separately verified itself in most cases.
5599 */ 5599 */
5600 if (in_pixel.red != out_pixel.red) 5600 if (in_pixel.red != out_pixel.red)
5601 transform_range_check(pp, r, g, b, a, in_pixel.red, in_pixel.redf, 5601 transform_range_check(pp, r, g, b, a, in_pixel.red, in_pixel.redf,
5602 out_pixel.red, sample_depth, in_pixel.rede, 5602 out_pixel.red, sample_depth, in_pixel.rede,
5603 dp->pm->limit + 1./(2*((1U<<in_pixel.red_sBIT)-1)), "red/gray", 5603 dp->pm->limit + 1./(2*((1U<<in_pixel.red_sBIT)-1)), "red/gray",
5604 digitization_error); 5604 digitization_error);
5605 5605
5606 if ((out_ct & PNG_COLOR_MASK_COLOR) != 0 && 5606 if ((out_ct & PNG_COLOR_MASK_COLOR) != 0 &&
5607 in_pixel.green != out_pixel.green) 5607 in_pixel.green != out_pixel.green)
5608 transform_range_check(pp, r, g, b, a, in_pixel.green, 5608 transform_range_check(pp, r, g, b, a, in_pixel.green,
5609 in_pixel.greenf, out_pixel.green, sample_depth, in_pixel.greene, 5609 in_pixel.greenf, out_pixel.green, sample_depth, in_pixel.greene,
5610 dp->pm->limit + 1./(2*((1U<<in_pixel.green_sBIT)-1)), "green", 5610 dp->pm->limit + 1./(2*((1U<<in_pixel.green_sBIT)-1)), "green",
5611 digitization_error); 5611 digitization_error);
5612 5612
5613 if ((out_ct & PNG_COLOR_MASK_COLOR) != 0 && 5613 if ((out_ct & PNG_COLOR_MASK_COLOR) != 0 &&
5614 in_pixel.blue != out_pixel.blue) 5614 in_pixel.blue != out_pixel.blue)
5615 transform_range_check(pp, r, g, b, a, in_pixel.blue, in_pixel.bluef, 5615 transform_range_check(pp, r, g, b, a, in_pixel.blue, in_pixel.bluef,
5616 out_pixel.blue, sample_depth, in_pixel.bluee, 5616 out_pixel.blue, sample_depth, in_pixel.bluee,
5617 dp->pm->limit + 1./(2*((1U<<in_pixel.blue_sBIT)-1)), "blue", 5617 dp->pm->limit + 1./(2*((1U<<in_pixel.blue_sBIT)-1)), "blue",
5618 digitization_error); 5618 digitization_error);
5619 5619
5620 if ((out_ct & PNG_COLOR_MASK_ALPHA) != 0 && 5620 if ((out_ct & PNG_COLOR_MASK_ALPHA) != 0 &&
5621 in_pixel.alpha != out_pixel.alpha) 5621 in_pixel.alpha != out_pixel.alpha)
5622 transform_range_check(pp, r, g, b, a, in_pixel.alpha, 5622 transform_range_check(pp, r, g, b, a, in_pixel.alpha,
5623 in_pixel.alphaf, out_pixel.alpha, sample_depth, in_pixel.alphae, 5623 in_pixel.alphaf, out_pixel.alpha, sample_depth, in_pixel.alphae,
5624 dp->pm->limit + 1./(2*((1U<<in_pixel.alpha_sBIT)-1)), "alpha", 5624 dp->pm->limit + 1./(2*((1U<<in_pixel.alpha_sBIT)-1)), "alpha",
5625 digitization_error); 5625 digitization_error);
5626 } /* pixel (x) loop */ 5626 } /* pixel (x) loop */
5627 } /* row (y) loop */ 5627 } /* row (y) loop */
5628 5628
5629 /* Record that something was actually checked to avoid a false positive. */ 5629 /* Record that something was actually checked to avoid a false positive. */
5630 dp->this.ps->validated = 1; 5630 dp->this.ps->validated = 1;
5631} 5631}
5632 5632
5633static void 5633static void
5634transform_end(png_structp pp, png_infop pi) 5634transform_end(png_structp pp, png_infop pi)
5635{ 5635{
5636 transform_display *dp = voidcast(transform_display*, 5636 transform_display *dp = voidcast(transform_display*,
5637 png_get_progressive_ptr(pp)); 5637 png_get_progressive_ptr(pp));
5638 5638
5639 if (!dp->this.speed) 5639 if (!dp->this.speed)
5640 transform_image_validate(dp, pp, pi); 5640 transform_image_validate(dp, pp, pi);
5641 else 5641 else
5642 dp->this.ps->validated = 1; 5642 dp->this.ps->validated = 1;
5643} 5643}
5644 5644
5645/* A single test run. */ 5645/* A single test run. */
5646static void 5646static void
5647transform_test(png_modifier *pmIn, PNG_CONST png_uint_32 idIn, 5647transform_test(png_modifier *pmIn, PNG_CONST png_uint_32 idIn,
5648 PNG_CONST image_transform* transform_listIn, PNG_CONST char * volatile name) 5648 PNG_CONST image_transform* transform_listIn, PNG_CONST char * volatile name)
5649{ 5649{
5650 transform_display d; 5650 transform_display d;
5651 context(&pmIn->this, fault); 5651 context(&pmIn->this, fault);
5652 5652
5653 transform_display_init(&d, pmIn, idIn, transform_listIn); 5653 transform_display_init(&d, pmIn, idIn, transform_listIn);
5654 5654
5655 Try 5655 Try
5656 { 5656 {
5657 size_t pos = 0; 5657 size_t pos = 0;
5658 png_structp pp; 5658 png_structp pp;
5659 png_infop pi; 5659 png_infop pi;
5660 char full_name[256]; 5660 char full_name[256];
5661 5661
5662 /* Make sure the encoding fields are correct and enter the required 5662 /* Make sure the encoding fields are correct and enter the required
5663 * modifications. 5663 * modifications.
5664 */ 5664 */
5665 transform_set_encoding(&d); 5665 transform_set_encoding(&d);
5666 5666
5667 /* Add any modifications required by the transform list. */ 5667 /* Add any modifications required by the transform list. */
5668 d.transform_list->ini(d.transform_list, &d); 5668 d.transform_list->ini(d.transform_list, &d);
5669 5669
5670 /* Add the color space information, if any, to the name. */ 5670 /* Add the color space information, if any, to the name. */
5671 pos = safecat(full_name, sizeof full_name, pos, name); 5671 pos = safecat(full_name, sizeof full_name, pos, name);
5672 pos = safecat_current_encoding(full_name, sizeof full_name, pos, d.pm); 5672 pos = safecat_current_encoding(full_name, sizeof full_name, pos, d.pm);
5673 5673
5674 /* Get a png_struct for reading the image. */ 5674 /* Get a png_struct for reading the image. */
5675 pp = set_modifier_for_read(d.pm, &pi, d.this.id, full_name); 5675 pp = set_modifier_for_read(d.pm, &pi, d.this.id, full_name);
5676 standard_palette_init(&d.this); 5676 standard_palette_init(&d.this);
5677 5677
5678# if 0 5678# if 0
5679 /* Logging (debugging only) */ 5679 /* Logging (debugging only) */
5680 { 5680 {
5681 char buffer[256]; 5681 char buffer[256];
5682 5682
5683 (void)store_message(&d.pm->this, pp, buffer, sizeof buffer, 0, 5683 (void)store_message(&d.pm->this, pp, buffer, sizeof buffer, 0,
5684 "running test"); 5684 "running test");
5685 5685
5686 fprintf(stderr, "%s\n", buffer); 5686 fprintf(stderr, "%s\n", buffer);
5687 } 5687 }
5688# endif 5688# endif
5689 5689
5690 /* Introduce the correct read function. */ 5690 /* Introduce the correct read function. */
5691 if (d.pm->this.progressive) 5691 if (d.pm->this.progressive)
5692 { 5692 {
5693 /* Share the row function with the standard implementation. */ 5693 /* Share the row function with the standard implementation. */
5694 png_set_progressive_read_fn(pp, &d, transform_info, progressive_row, 5694 png_set_progressive_read_fn(pp, &d, transform_info, progressive_row,
5695 transform_end); 5695 transform_end);
5696 5696
5697 /* Now feed data into the reader until we reach the end: */ 5697 /* Now feed data into the reader until we reach the end: */
5698 modifier_progressive_read(d.pm, pp, pi); 5698 modifier_progressive_read(d.pm, pp, pi);
5699 } 5699 }
5700 else 5700 else
5701 { 5701 {
5702 /* modifier_read expects a png_modifier* */ 5702 /* modifier_read expects a png_modifier* */
5703 png_set_read_fn(pp, d.pm, modifier_read); 5703 png_set_read_fn(pp, d.pm, modifier_read);
5704 5704
5705 /* Check the header values: */ 5705 /* Check the header values: */
5706 png_read_info(pp, pi); 5706 png_read_info(pp, pi);
5707 5707
5708 /* Process the 'info' requirements. Only one image is generated */ 5708 /* Process the 'info' requirements. Only one image is generated */
5709 transform_info_imp(&d, pp, pi); 5709 transform_info_imp(&d, pp, pi);
5710 5710
5711 sequential_row(&d.this, pp, pi, -1, 0); 5711 sequential_row(&d.this, pp, pi, -1, 0);
5712 5712
5713 if (!d.this.speed) 5713 if (!d.this.speed)
5714 transform_image_validate(&d, pp, pi); 5714 transform_image_validate(&d, pp, pi);
5715 else 5715 else
5716 d.this.ps->validated = 1; 5716 d.this.ps->validated = 1;
5717 } 5717 }
5718 5718
5719 modifier_reset(d.pm); 5719 modifier_reset(d.pm);
5720 } 5720 }
5721 5721
5722 Catch(fault) 5722 Catch(fault)
5723 { 5723 {
5724 modifier_reset((png_modifier*)fault); 5724 modifier_reset((png_modifier*)fault);
5725 } 5725 }
5726} 5726}
5727 5727
5728/* The transforms: */ 5728/* The transforms: */
5729#define ITSTRUCT(name) image_transform_##name 5729#define ITSTRUCT(name) image_transform_##name
5730#define ITDATA(name) image_transform_data_##name 5730#define ITDATA(name) image_transform_data_##name
5731#define image_transform_ini image_transform_default_ini 5731#define image_transform_ini image_transform_default_ini
5732#define IT(name)\ 5732#define IT(name)\
5733static image_transform ITSTRUCT(name) =\ 5733static image_transform ITSTRUCT(name) =\
5734{\ 5734{\
5735 #name,\ 5735 #name,\
5736 1, /*enable*/\ 5736 1, /*enable*/\
5737 &PT, /*list*/\ 5737 &PT, /*list*/\
5738 0, /*global_use*/\ 5738 0, /*global_use*/\
5739 0, /*local_use*/\ 5739 0, /*local_use*/\
5740 0, /*next*/\ 5740 0, /*next*/\
5741 image_transform_ini,\ 5741 image_transform_ini,\
5742 image_transform_png_set_##name##_set,\ 5742 image_transform_png_set_##name##_set,\
5743 image_transform_png_set_##name##_mod,\ 5743 image_transform_png_set_##name##_mod,\
5744 image_transform_png_set_##name##_add\ 5744 image_transform_png_set_##name##_add\
5745} 5745}
5746#define PT ITSTRUCT(end) /* stores the previous transform */ 5746#define PT ITSTRUCT(end) /* stores the previous transform */
5747 5747
5748/* To save code: */ 5748/* To save code: */
5749static void 5749static void
5750image_transform_default_ini(PNG_CONST image_transform *this, 5750image_transform_default_ini(PNG_CONST image_transform *this,
5751 transform_display *that) 5751 transform_display *that)
5752{ 5752{
5753 this->next->ini(this->next, that); 5753 this->next->ini(this->next, that);
5754} 5754}
5755 5755
5756static int 5756static int
5757image_transform_default_add(image_transform *this, 5757image_transform_default_add(image_transform *this,
5758 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth) 5758 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth)
5759{ 5759{
5760 UNUSED(colour_type) 5760 UNUSED(colour_type)
5761 UNUSED(bit_depth) 5761 UNUSED(bit_depth)
5762 5762
5763 this->next = *that; 5763 this->next = *that;
5764 *that = this; 5764 *that = this;
5765 5765
5766 return 1; 5766 return 1;
5767} 5767}
5768 5768
5769#ifdef PNG_READ_EXPAND_SUPPORTED 5769#ifdef PNG_READ_EXPAND_SUPPORTED
5770/* png_set_palette_to_rgb */ 5770/* png_set_palette_to_rgb */
5771static void 5771static void
5772image_transform_png_set_palette_to_rgb_set(PNG_CONST image_transform *this, 5772image_transform_png_set_palette_to_rgb_set(PNG_CONST image_transform *this,
5773 transform_display *that, png_structp pp, png_infop pi) 5773 transform_display *that, png_structp pp, png_infop pi)
5774{ 5774{
5775 png_set_palette_to_rgb(pp); 5775 png_set_palette_to_rgb(pp);
5776 this->next->set(this->next, that, pp, pi); 5776 this->next->set(this->next, that, pp, pi);
5777} 5777}
5778 5778
5779static void 5779static void
5780image_transform_png_set_palette_to_rgb_mod(PNG_CONST image_transform *this, 5780image_transform_png_set_palette_to_rgb_mod(PNG_CONST image_transform *this,
5781 image_pixel *that, png_structp pp, PNG_CONST transform_display *display) 5781 image_pixel *that, png_structp pp, PNG_CONST transform_display *display)
5782{ 5782{
5783 if (that->colour_type == PNG_COLOR_TYPE_PALETTE) 5783 if (that->colour_type == PNG_COLOR_TYPE_PALETTE)
5784 image_pixel_convert_PLTE(that); 5784 image_pixel_convert_PLTE(that);
5785 5785
5786 this->next->mod(this->next, that, pp, display); 5786 this->next->mod(this->next, that, pp, display);
5787} 5787}
5788 5788
5789static int 5789static int
5790image_transform_png_set_palette_to_rgb_add(image_transform *this, 5790image_transform_png_set_palette_to_rgb_add(image_transform *this,
5791 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth) 5791 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth)
5792{ 5792{
5793 UNUSED(bit_depth) 5793 UNUSED(bit_depth)
5794 5794
5795 this->next = *that; 5795 this->next = *that;
5796 *that = this; 5796 *that = this;
5797 5797
5798 return colour_type == PNG_COLOR_TYPE_PALETTE; 5798 return colour_type == PNG_COLOR_TYPE_PALETTE;
5799} 5799}
5800 5800
5801IT(palette_to_rgb); 5801IT(palette_to_rgb);
5802#undef PT 5802#undef PT
5803#define PT ITSTRUCT(palette_to_rgb) 5803#define PT ITSTRUCT(palette_to_rgb)
5804#endif /* PNG_READ_EXPAND_SUPPORTED */ 5804#endif /* PNG_READ_EXPAND_SUPPORTED */
5805 5805
5806#ifdef PNG_READ_EXPAND_SUPPORTED 5806#ifdef PNG_READ_EXPAND_SUPPORTED
5807/* png_set_tRNS_to_alpha */ 5807/* png_set_tRNS_to_alpha */
5808static void 5808static void
5809image_transform_png_set_tRNS_to_alpha_set(PNG_CONST image_transform *this, 5809image_transform_png_set_tRNS_to_alpha_set(PNG_CONST image_transform *this,
5810 transform_display *that, png_structp pp, png_infop pi) 5810 transform_display *that, png_structp pp, png_infop pi)
5811{ 5811{
5812 png_set_tRNS_to_alpha(pp); 5812 png_set_tRNS_to_alpha(pp);
5813 this->next->set(this->next, that, pp, pi); 5813 this->next->set(this->next, that, pp, pi);
5814} 5814}
5815 5815
5816static void 5816static void
5817image_transform_png_set_tRNS_to_alpha_mod(PNG_CONST image_transform *this, 5817image_transform_png_set_tRNS_to_alpha_mod(PNG_CONST image_transform *this,
5818 image_pixel *that, png_structp pp, PNG_CONST transform_display *display) 5818 image_pixel *that, png_structp pp, PNG_CONST transform_display *display)
5819{ 5819{
5820 /* LIBPNG BUG: this always forces palette images to RGB. */ 5820 /* LIBPNG BUG: this always forces palette images to RGB. */
5821 if (that->colour_type == PNG_COLOR_TYPE_PALETTE) 5821 if (that->colour_type == PNG_COLOR_TYPE_PALETTE)
5822 image_pixel_convert_PLTE(that); 5822 image_pixel_convert_PLTE(that);
5823 5823
5824 /* This effectively does an 'expand' only if there is some transparency to 5824 /* This effectively does an 'expand' only if there is some transparency to
5825 * convert to an alpha channel. 5825 * convert to an alpha channel.
5826 */ 5826 */
5827 if (that->have_tRNS) 5827 if (that->have_tRNS)
5828 image_pixel_add_alpha(that, &display->this); 5828 image_pixel_add_alpha(that, &display->this);
5829 5829
5830 /* LIBPNG BUG: otherwise libpng still expands to 8 bits! */ 5830 /* LIBPNG BUG: otherwise libpng still expands to 8 bits! */
5831 else 5831 else
5832 { 5832 {
5833 if (that->bit_depth < 8) 5833 if (that->bit_depth < 8)
5834 that->bit_depth =8; 5834 that->bit_depth =8;
5835 if (that->sample_depth < 8) 5835 if (that->sample_depth < 8)
5836 that->sample_depth = 8; 5836 that->sample_depth = 8;
5837 } 5837 }
5838 5838
5839 this->next->mod(this->next, that, pp, display); 5839 this->next->mod(this->next, that, pp, display);
5840} 5840}
5841 5841
5842static int 5842static int
5843image_transform_png_set_tRNS_to_alpha_add(image_transform *this, 5843image_transform_png_set_tRNS_to_alpha_add(image_transform *this,
5844 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth) 5844 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth)
5845{ 5845{
5846 UNUSED(bit_depth) 5846 UNUSED(bit_depth)
5847 5847
5848 this->next = *that; 5848 this->next = *that;
5849 *that = this; 5849 *that = this;
5850 5850
5851 /* We don't know yet whether there will be a tRNS chunk, but we know that 5851 /* We don't know yet whether there will be a tRNS chunk, but we know that
5852 * this transformation should do nothing if there already is an alpha 5852 * this transformation should do nothing if there already is an alpha
5853 * channel. 5853 * channel.
5854 */ 5854 */
5855 return (colour_type & PNG_COLOR_MASK_ALPHA) == 0; 5855 return (colour_type & PNG_COLOR_MASK_ALPHA) == 0;
5856} 5856}
5857 5857
5858IT(tRNS_to_alpha); 5858IT(tRNS_to_alpha);
5859#undef PT 5859#undef PT
5860#define PT ITSTRUCT(tRNS_to_alpha) 5860#define PT ITSTRUCT(tRNS_to_alpha)
5861#endif /* PNG_READ_EXPAND_SUPPORTED */ 5861#endif /* PNG_READ_EXPAND_SUPPORTED */
5862 5862
5863#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED 5863#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
5864/* png_set_gray_to_rgb */ 5864/* png_set_gray_to_rgb */
5865static void 5865static void
5866image_transform_png_set_gray_to_rgb_set(PNG_CONST image_transform *this, 5866image_transform_png_set_gray_to_rgb_set(PNG_CONST image_transform *this,
5867 transform_display *that, png_structp pp, png_infop pi) 5867 transform_display *that, png_structp pp, png_infop pi)
5868{ 5868{
5869 png_set_gray_to_rgb(pp); 5869 png_set_gray_to_rgb(pp);
5870 this->next->set(this->next, that, pp, pi); 5870 this->next->set(this->next, that, pp, pi);
5871} 5871}
5872 5872
5873static void 5873static void
5874image_transform_png_set_gray_to_rgb_mod(PNG_CONST image_transform *this, 5874image_transform_png_set_gray_to_rgb_mod(PNG_CONST image_transform *this,
5875 image_pixel *that, png_structp pp, PNG_CONST transform_display *display) 5875 image_pixel *that, png_structp pp, PNG_CONST transform_display *display)
5876{ 5876{
5877 /* NOTE: we can actually pend the tRNS processing at this point because we 5877 /* NOTE: we can actually pend the tRNS processing at this point because we
5878 * can correctly recognize the original pixel value even though we have 5878 * can correctly recognize the original pixel value even though we have
5879 * mapped the one gray channel to the three RGB ones, but in fact libpng 5879 * mapped the one gray channel to the three RGB ones, but in fact libpng
5880 * doesn't do this, so we don't either. 5880 * doesn't do this, so we don't either.
5881 */ 5881 */
5882 if ((that->colour_type & PNG_COLOR_MASK_COLOR) == 0 && that->have_tRNS) 5882 if ((that->colour_type & PNG_COLOR_MASK_COLOR) == 0 && that->have_tRNS)
5883 image_pixel_add_alpha(that, &display->this); 5883 image_pixel_add_alpha(that, &display->this);
5884 5884
5885 /* Simply expand the bit depth and alter the colour type as required. */ 5885 /* Simply expand the bit depth and alter the colour type as required. */
5886 if (that->colour_type == PNG_COLOR_TYPE_GRAY) 5886 if (that->colour_type == PNG_COLOR_TYPE_GRAY)
5887 { 5887 {
5888 /* RGB images have a bit depth at least equal to '8' */ 5888 /* RGB images have a bit depth at least equal to '8' */
5889 if (that->bit_depth < 8) 5889 if (that->bit_depth < 8)
5890 that->sample_depth = that->bit_depth = 8; 5890 that->sample_depth = that->bit_depth = 8;
5891 5891
5892 /* And just changing the colour type works here because the green and blue 5892 /* And just changing the colour type works here because the green and blue
5893 * channels are being maintained in lock-step with the red/gray: 5893 * channels are being maintained in lock-step with the red/gray:
5894 */ 5894 */
5895 that->colour_type = PNG_COLOR_TYPE_RGB; 5895 that->colour_type = PNG_COLOR_TYPE_RGB;
5896 } 5896 }
5897 5897
5898 else if (that->colour_type == PNG_COLOR_TYPE_GRAY_ALPHA) 5898 else if (that->colour_type == PNG_COLOR_TYPE_GRAY_ALPHA)
5899 that->colour_type = PNG_COLOR_TYPE_RGB_ALPHA; 5899 that->colour_type = PNG_COLOR_TYPE_RGB_ALPHA;
5900 5900
5901 this->next->mod(this->next, that, pp, display); 5901 this->next->mod(this->next, that, pp, display);
5902} 5902}
5903 5903
5904static int 5904static int
5905image_transform_png_set_gray_to_rgb_add(image_transform *this, 5905image_transform_png_set_gray_to_rgb_add(image_transform *this,
5906 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth) 5906 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth)
5907{ 5907{
5908 UNUSED(bit_depth) 5908 UNUSED(bit_depth)
5909 5909
5910 this->next = *that; 5910 this->next = *that;
5911 *that = this; 5911 *that = this;
5912 5912
5913 return (colour_type & PNG_COLOR_MASK_COLOR) == 0; 5913 return (colour_type & PNG_COLOR_MASK_COLOR) == 0;
5914} 5914}
5915 5915
5916IT(gray_to_rgb); 5916IT(gray_to_rgb);
5917#undef PT 5917#undef PT
5918#define PT ITSTRUCT(gray_to_rgb) 5918#define PT ITSTRUCT(gray_to_rgb)
5919#endif /* PNG_READ_GRAY_TO_RGB_SUPPORTED */ 5919#endif /* PNG_READ_GRAY_TO_RGB_SUPPORTED */
5920 5920
5921#ifdef PNG_READ_EXPAND_SUPPORTED 5921#ifdef PNG_READ_EXPAND_SUPPORTED
5922/* png_set_expand */ 5922/* png_set_expand */
5923static void 5923static void
5924image_transform_png_set_expand_set(PNG_CONST image_transform *this, 5924image_transform_png_set_expand_set(PNG_CONST image_transform *this,
5925 transform_display *that, png_structp pp, png_infop pi) 5925 transform_display *that, png_structp pp, png_infop pi)
5926{ 5926{
5927 png_set_expand(pp); 5927 png_set_expand(pp);
5928 this->next->set(this->next, that, pp, pi); 5928 this->next->set(this->next, that, pp, pi);
5929} 5929}
5930 5930
5931static void 5931static void
5932image_transform_png_set_expand_mod(PNG_CONST image_transform *this, 5932image_transform_png_set_expand_mod(PNG_CONST image_transform *this,
5933 image_pixel *that, png_structp pp, PNG_CONST transform_display *display) 5933 image_pixel *that, png_structp pp, PNG_CONST transform_display *display)
5934{ 5934{
5935 /* The general expand case depends on what the colour type is: */ 5935 /* The general expand case depends on what the colour type is: */
5936 if (that->colour_type == PNG_COLOR_TYPE_PALETTE) 5936 if (that->colour_type == PNG_COLOR_TYPE_PALETTE)
5937 image_pixel_convert_PLTE(that); 5937 image_pixel_convert_PLTE(that);
5938 else if (that->bit_depth < 8) /* grayscale */ 5938 else if (that->bit_depth < 8) /* grayscale */
5939 that->sample_depth = that->bit_depth = 8; 5939 that->sample_depth = that->bit_depth = 8;
5940 5940
5941 if (that->have_tRNS) 5941 if (that->have_tRNS)
5942 image_pixel_add_alpha(that, &display->this); 5942 image_pixel_add_alpha(that, &display->this);
5943 5943
5944 this->next->mod(this->next, that, pp, display); 5944 this->next->mod(this->next, that, pp, display);
5945} 5945}
5946 5946
5947static int 5947static int
5948image_transform_png_set_expand_add(image_transform *this, 5948image_transform_png_set_expand_add(image_transform *this,
5949 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth) 5949 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth)
5950{ 5950{
5951 UNUSED(bit_depth) 5951 UNUSED(bit_depth)
5952 5952
5953 this->next = *that; 5953 this->next = *that;
5954 *that = this; 5954 *that = this;
5955 5955
5956 /* 'expand' should do nothing for RGBA or GA input - no tRNS and the bit 5956 /* 'expand' should do nothing for RGBA or GA input - no tRNS and the bit
5957 * depth is at least 8 already. 5957 * depth is at least 8 already.
5958 */ 5958 */
5959 return (colour_type & PNG_COLOR_MASK_ALPHA) == 0; 5959 return (colour_type & PNG_COLOR_MASK_ALPHA) == 0;
5960} 5960}
5961 5961
5962IT(expand); 5962IT(expand);
5963#undef PT 5963#undef PT
5964#define PT ITSTRUCT(expand) 5964#define PT ITSTRUCT(expand)
5965#endif /* PNG_READ_EXPAND_SUPPORTED */ 5965#endif /* PNG_READ_EXPAND_SUPPORTED */
5966 5966
5967#ifdef PNG_READ_EXPAND_SUPPORTED 5967#ifdef PNG_READ_EXPAND_SUPPORTED
5968/* png_set_expand_gray_1_2_4_to_8 5968/* png_set_expand_gray_1_2_4_to_8
5969 * LIBPNG BUG: this just does an 'expand' 5969 * LIBPNG BUG: this just does an 'expand'
5970 */ 5970 */
5971static void 5971static void
5972image_transform_png_set_expand_gray_1_2_4_to_8_set( 5972image_transform_png_set_expand_gray_1_2_4_to_8_set(
5973 PNG_CONST image_transform *this, transform_display *that, png_structp pp, 5973 PNG_CONST image_transform *this, transform_display *that, png_structp pp,
5974 png_infop pi) 5974 png_infop pi)
5975{ 5975{
5976 png_set_expand_gray_1_2_4_to_8(pp); 5976 png_set_expand_gray_1_2_4_to_8(pp);
5977 this->next->set(this->next, that, pp, pi); 5977 this->next->set(this->next, that, pp, pi);
5978} 5978}
5979 5979
5980static void 5980static void
5981image_transform_png_set_expand_gray_1_2_4_to_8_mod( 5981image_transform_png_set_expand_gray_1_2_4_to_8_mod(
5982 PNG_CONST image_transform *this, image_pixel *that, png_structp pp, 5982 PNG_CONST image_transform *this, image_pixel *that, png_structp pp,
5983 PNG_CONST transform_display *display) 5983 PNG_CONST transform_display *display)
5984{ 5984{
5985 image_transform_png_set_expand_mod(this, that, pp, display); 5985 image_transform_png_set_expand_mod(this, that, pp, display);
5986} 5986}
5987 5987
5988static int 5988static int
5989image_transform_png_set_expand_gray_1_2_4_to_8_add(image_transform *this, 5989image_transform_png_set_expand_gray_1_2_4_to_8_add(image_transform *this,
5990 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth) 5990 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth)
5991{ 5991{
5992 return image_transform_png_set_expand_add(this, that, colour_type, 5992 return image_transform_png_set_expand_add(this, that, colour_type,
5993 bit_depth); 5993 bit_depth);
5994} 5994}
5995 5995
5996IT(expand_gray_1_2_4_to_8); 5996IT(expand_gray_1_2_4_to_8);
5997#undef PT 5997#undef PT
5998#define PT ITSTRUCT(expand_gray_1_2_4_to_8) 5998#define PT ITSTRUCT(expand_gray_1_2_4_to_8)
5999#endif /* PNG_READ_EXPAND_SUPPORTED */ 5999#endif /* PNG_READ_EXPAND_SUPPORTED */
6000 6000
6001#ifdef PNG_READ_EXPAND_16_SUPPORTED 6001#ifdef PNG_READ_EXPAND_16_SUPPORTED
6002/* png_set_expand_16 */ 6002/* png_set_expand_16 */
6003static void 6003static void
6004image_transform_png_set_expand_16_set(PNG_CONST image_transform *this, 6004image_transform_png_set_expand_16_set(PNG_CONST image_transform *this,
6005 transform_display *that, png_structp pp, png_infop pi) 6005 transform_display *that, png_structp pp, png_infop pi)
6006{ 6006{
6007 png_set_expand_16(pp); 6007 png_set_expand_16(pp);
6008 this->next->set(this->next, that, pp, pi); 6008 this->next->set(this->next, that, pp, pi);
6009} 6009}
6010 6010
6011static void 6011static void
6012image_transform_png_set_expand_16_mod(PNG_CONST image_transform *this, 6012image_transform_png_set_expand_16_mod(PNG_CONST image_transform *this,
6013 image_pixel *that, png_structp pp, PNG_CONST transform_display *display) 6013 image_pixel *that, png_structp pp, PNG_CONST transform_display *display)
6014{ 6014{
6015 /* Expect expand_16 to expand everything to 16 bits as a result of also 6015 /* Expect expand_16 to expand everything to 16 bits as a result of also
6016 * causing 'expand' to happen. 6016 * causing 'expand' to happen.
6017 */ 6017 */
6018 if (that->colour_type == PNG_COLOR_TYPE_PALETTE) 6018 if (that->colour_type == PNG_COLOR_TYPE_PALETTE)
6019 image_pixel_convert_PLTE(that); 6019 image_pixel_convert_PLTE(that);
6020 6020
6021 if (that->have_tRNS) 6021 if (that->have_tRNS)
6022 image_pixel_add_alpha(that, &display->this); 6022 image_pixel_add_alpha(that, &display->this);
6023 6023
6024 if (that->bit_depth < 16) 6024 if (that->bit_depth < 16)
6025 that->sample_depth = that->bit_depth = 16; 6025 that->sample_depth = that->bit_depth = 16;
6026 6026
6027 this->next->mod(this->next, that, pp, display); 6027 this->next->mod(this->next, that, pp, display);
6028} 6028}
6029 6029
6030static int 6030static int
6031image_transform_png_set_expand_16_add(image_transform *this, 6031image_transform_png_set_expand_16_add(image_transform *this,
6032 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth) 6032 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth)
6033{ 6033{
6034 UNUSED(colour_type) 6034 UNUSED(colour_type)
6035 6035
6036 this->next = *that; 6036 this->next = *that;
6037 *that = this; 6037 *that = this;
6038 6038
6039 /* expand_16 does something unless the bit depth is already 16. */ 6039 /* expand_16 does something unless the bit depth is already 16. */
6040 return bit_depth < 16; 6040 return bit_depth < 16;
6041} 6041}
6042 6042
6043IT(expand_16); 6043IT(expand_16);
6044#undef PT 6044#undef PT
6045#define PT ITSTRUCT(expand_16) 6045#define PT ITSTRUCT(expand_16)
6046#endif /* PNG_READ_EXPAND_16_SUPPORTED */ 6046#endif /* PNG_READ_EXPAND_16_SUPPORTED */
6047 6047
6048#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED /* API added in 1.5.4 */ 6048#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED /* API added in 1.5.4 */
6049/* png_set_scale_16 */ 6049/* png_set_scale_16 */
6050static void 6050static void
6051image_transform_png_set_scale_16_set(PNG_CONST image_transform *this, 6051image_transform_png_set_scale_16_set(PNG_CONST image_transform *this,
6052 transform_display *that, png_structp pp, png_infop pi) 6052 transform_display *that, png_structp pp, png_infop pi)
6053{ 6053{
6054 png_set_scale_16(pp); 6054 png_set_scale_16(pp);
6055 this->next->set(this->next, that, pp, pi); 6055 this->next->set(this->next, that, pp, pi);
6056} 6056}
6057 6057
6058static void 6058static void
6059image_transform_png_set_scale_16_mod(PNG_CONST image_transform *this, 6059image_transform_png_set_scale_16_mod(PNG_CONST image_transform *this,
6060 image_pixel *that, png_structp pp, PNG_CONST transform_display *display) 6060 image_pixel *that, png_structp pp, PNG_CONST transform_display *display)
6061{ 6061{
6062 if (that->bit_depth == 16) 6062 if (that->bit_depth == 16)
6063 { 6063 {
6064 that->sample_depth = that->bit_depth = 8; 6064 that->sample_depth = that->bit_depth = 8;
6065 if (that->red_sBIT > 8) that->red_sBIT = 8; 6065 if (that->red_sBIT > 8) that->red_sBIT = 8;
6066 if (that->green_sBIT > 8) that->green_sBIT = 8; 6066 if (that->green_sBIT > 8) that->green_sBIT = 8;
6067 if (that->blue_sBIT > 8) that->blue_sBIT = 8; 6067 if (that->blue_sBIT > 8) that->blue_sBIT = 8;
6068 if (that->alpha_sBIT > 8) that->alpha_sBIT = 8; 6068 if (that->alpha_sBIT > 8) that->alpha_sBIT = 8;
6069 } 6069 }
6070 6070
6071 this->next->mod(this->next, that, pp, display); 6071 this->next->mod(this->next, that, pp, display);
6072} 6072}
6073 6073
6074static int 6074static int
6075image_transform_png_set_scale_16_add(image_transform *this, 6075image_transform_png_set_scale_16_add(image_transform *this,
6076 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth) 6076 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth)
6077{ 6077{
6078 UNUSED(colour_type) 6078 UNUSED(colour_type)
6079 6079
6080 this->next = *that; 6080 this->next = *that;
6081 *that = this; 6081 *that = this;
6082 6082
6083 return bit_depth > 8; 6083 return bit_depth > 8;
6084} 6084}
6085 6085
6086IT(scale_16); 6086IT(scale_16);
6087#undef PT 6087#undef PT
6088#define PT ITSTRUCT(scale_16) 6088#define PT ITSTRUCT(scale_16)
6089#endif /* PNG_READ_SCALE_16_TO_8_SUPPORTED (1.5.4 on) */ 6089#endif /* PNG_READ_SCALE_16_TO_8_SUPPORTED (1.5.4 on) */
6090 6090
6091#ifdef PNG_READ_16_TO_8_SUPPORTED /* the default before 1.5.4 */ 6091#ifdef PNG_READ_16_TO_8_SUPPORTED /* the default before 1.5.4 */
6092/* png_set_strip_16 */ 6092/* png_set_strip_16 */
6093static void 6093static void
6094image_transform_png_set_strip_16_set(PNG_CONST image_transform *this, 6094image_transform_png_set_strip_16_set(PNG_CONST image_transform *this,
6095 transform_display *that, png_structp pp, png_infop pi) 6095 transform_display *that, png_structp pp, png_infop pi)
6096{ 6096{
6097 png_set_strip_16(pp); 6097 png_set_strip_16(pp);
6098 this->next->set(this->next, that, pp, pi); 6098 this->next->set(this->next, that, pp, pi);
6099} 6099}
6100 6100
6101static void 6101static void
6102image_transform_png_set_strip_16_mod(PNG_CONST image_transform *this, 6102image_transform_png_set_strip_16_mod(PNG_CONST image_transform *this,
6103 image_pixel *that, png_structp pp, PNG_CONST transform_display *display) 6103 image_pixel *that, png_structp pp, PNG_CONST transform_display *display)
6104{ 6104{
6105 if (that->bit_depth == 16) 6105 if (that->bit_depth == 16)
6106 { 6106 {
6107 that->sample_depth = that->bit_depth = 8; 6107 that->sample_depth = that->bit_depth = 8;
6108 if (that->red_sBIT > 8) that->red_sBIT = 8; 6108 if (that->red_sBIT > 8) that->red_sBIT = 8;
6109 if (that->green_sBIT > 8) that->green_sBIT = 8; 6109 if (that->green_sBIT > 8) that->green_sBIT = 8;
6110 if (that->blue_sBIT > 8) that->blue_sBIT = 8; 6110 if (that->blue_sBIT > 8) that->blue_sBIT = 8;
6111 if (that->alpha_sBIT > 8) that->alpha_sBIT = 8; 6111 if (that->alpha_sBIT > 8) that->alpha_sBIT = 8;
6112 6112
6113 /* Prior to 1.5.4 png_set_strip_16 would use an 'accurate' method if this 6113 /* Prior to 1.5.4 png_set_strip_16 would use an 'accurate' method if this
6114 * configuration option is set. From 1.5.4 the flag is never set and the 6114 * configuration option is set. From 1.5.4 the flag is never set and the
6115 * 'scale' API (above) must be used. 6115 * 'scale' API (above) must be used.
6116 */ 6116 */
6117# ifdef PNG_READ_ACCURATE_SCALE_SUPPORTED 6117# ifdef PNG_READ_ACCURATE_SCALE_SUPPORTED
6118# if PNG_LIBPNG_VER >= 10504 6118# if PNG_LIBPNG_VER >= 10504
6119# error PNG_READ_ACCURATE_SCALE should not be set 6119# error PNG_READ_ACCURATE_SCALE should not be set
6120# endif 6120# endif
6121 6121
6122 /* The strip 16 algorithm drops the low 8 bits rather than calculating 6122 /* The strip 16 algorithm drops the low 8 bits rather than calculating
6123 * 1/257, so we need to adjust the permitted errors appropriately: 6123 * 1/257, so we need to adjust the permitted errors appropriately:
6124 * Notice that this is only relevant prior to the addition of the 6124 * Notice that this is only relevant prior to the addition of the
6125 * png_set_scale_16 API in 1.5.4 (but 1.5.4+ always defines the above!) 6125 * png_set_scale_16 API in 1.5.4 (but 1.5.4+ always defines the above!)
6126 */ 6126 */
6127 { 6127 {
6128 PNG_CONST double d = (255-128.5)/65535; 6128 PNG_CONST double d = (255-128.5)/65535;
6129 that->rede += d; 6129 that->rede += d;
6130 that->greene += d; 6130 that->greene += d;
6131 that->bluee += d; 6131 that->bluee += d;
6132 that->alphae += d; 6132 that->alphae += d;
6133 } 6133 }
6134# endif 6134# endif
6135 } 6135 }
6136 6136
6137 this->next->mod(this->next, that, pp, display); 6137 this->next->mod(this->next, that, pp, display);
6138} 6138}
6139 6139
6140static int 6140static int
6141image_transform_png_set_strip_16_add(image_transform *this, 6141image_transform_png_set_strip_16_add(image_transform *this,
6142 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth) 6142 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth)
6143{ 6143{
6144 UNUSED(colour_type) 6144 UNUSED(colour_type)
6145 6145
6146 this->next = *that; 6146 this->next = *that;
6147 *that = this; 6147 *that = this;
6148 6148
6149 return bit_depth > 8; 6149 return bit_depth > 8;
6150} 6150}
6151 6151
6152IT(strip_16); 6152IT(strip_16);
6153#undef PT 6153#undef PT
6154#define PT ITSTRUCT(strip_16) 6154#define PT ITSTRUCT(strip_16)
6155#endif /* PNG_READ_16_TO_8_SUPPORTED */ 6155#endif /* PNG_READ_16_TO_8_SUPPORTED */
6156 6156
6157#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED 6157#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
6158/* png_set_strip_alpha */ 6158/* png_set_strip_alpha */
6159static void 6159static void
6160image_transform_png_set_strip_alpha_set(PNG_CONST image_transform *this, 6160image_transform_png_set_strip_alpha_set(PNG_CONST image_transform *this,
6161 transform_display *that, png_structp pp, png_infop pi) 6161 transform_display *that, png_structp pp, png_infop pi)
6162{ 6162{
6163 png_set_strip_alpha(pp); 6163 png_set_strip_alpha(pp);
6164 this->next->set(this->next, that, pp, pi); 6164 this->next->set(this->next, that, pp, pi);
6165} 6165}
6166 6166
6167static void 6167static void
6168image_transform_png_set_strip_alpha_mod(PNG_CONST image_transform *this, 6168image_transform_png_set_strip_alpha_mod(PNG_CONST image_transform *this,
6169 image_pixel *that, png_structp pp, PNG_CONST transform_display *display) 6169 image_pixel *that, png_structp pp, PNG_CONST transform_display *display)
6170{ 6170{
6171 if (that->colour_type == PNG_COLOR_TYPE_GRAY_ALPHA) 6171 if (that->colour_type == PNG_COLOR_TYPE_GRAY_ALPHA)
6172 that->colour_type = PNG_COLOR_TYPE_GRAY; 6172 that->colour_type = PNG_COLOR_TYPE_GRAY;
6173 else if (that->colour_type == PNG_COLOR_TYPE_RGB_ALPHA) 6173 else if (that->colour_type == PNG_COLOR_TYPE_RGB_ALPHA)
6174 that->colour_type = PNG_COLOR_TYPE_RGB; 6174 that->colour_type = PNG_COLOR_TYPE_RGB;
6175 6175
6176 that->have_tRNS = 0; 6176 that->have_tRNS = 0;
6177 that->alphaf = 1; 6177 that->alphaf = 1;
6178 6178
6179 this->next->mod(this->next, that, pp, display); 6179 this->next->mod(this->next, that, pp, display);
6180} 6180}
6181 6181
6182static int 6182static int
6183image_transform_png_set_strip_alpha_add(image_transform *this, 6183image_transform_png_set_strip_alpha_add(image_transform *this,
6184 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth) 6184 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth)
6185{ 6185{
6186 UNUSED(bit_depth) 6186 UNUSED(bit_depth)
6187 6187
6188 this->next = *that; 6188 this->next = *that;
6189 *that = this; 6189 *that = this;
6190 6190
6191 return (colour_type & PNG_COLOR_MASK_ALPHA) != 0; 6191 return (colour_type & PNG_COLOR_MASK_ALPHA) != 0;
6192} 6192}
6193 6193
6194IT(strip_alpha); 6194IT(strip_alpha);
6195#undef PT 6195#undef PT
6196#define PT ITSTRUCT(strip_alpha) 6196#define PT ITSTRUCT(strip_alpha)
6197#endif /* PNG_READ_STRIP_ALPHA_SUPPORTED */ 6197#endif /* PNG_READ_STRIP_ALPHA_SUPPORTED */
6198 6198
6199#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED 6199#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
6200/* png_set_rgb_to_gray(png_structp, int err_action, double red, double green) 6200/* png_set_rgb_to_gray(png_structp, int err_action, double red, double green)
6201 * png_set_rgb_to_gray_fixed(png_structp, int err_action, png_fixed_point red, 6201 * png_set_rgb_to_gray_fixed(png_structp, int err_action, png_fixed_point red,
6202 * png_fixed_point green) 6202 * png_fixed_point green)
6203 * png_get_rgb_to_gray_status 6203 * png_get_rgb_to_gray_status
6204 * 6204 *
6205 * The 'default' test here uses values known to be used inside libpng: 6205 * The 'default' test here uses values known to be used inside libpng:
6206 * 6206 *
6207 * red: 6968 6207 * red: 6968
6208 * green: 23434 6208 * green: 23434
6209 * blue: 2366 6209 * blue: 2366
6210 * 6210 *
6211 * These values are being retained for compatibility, along with the somewhat 6211 * These values are being retained for compatibility, along with the somewhat
6212 * broken truncation calculation in the fast-and-inaccurate code path. Older 6212 * broken truncation calculation in the fast-and-inaccurate code path. Older
6213 * versions of libpng will fail the accuracy tests below because they use the 6213 * versions of libpng will fail the accuracy tests below because they use the
6214 * truncation algorithm everywhere. 6214 * truncation algorithm everywhere.
6215 */ 6215 */
6216#define data ITDATA(rgb_to_gray) 6216#define data ITDATA(rgb_to_gray)
6217static struct 6217static struct
6218{ 6218{
6219 double gamma; /* File gamma to use in processing */ 6219 double gamma; /* File gamma to use in processing */
6220 6220
6221 /* The following are the parameters for png_set_rgb_to_gray: */ 6221 /* The following are the parameters for png_set_rgb_to_gray: */
6222# ifdef PNG_FLOATING_POINT_SUPPORTED 6222# ifdef PNG_FLOATING_POINT_SUPPORTED
6223 double red_to_set; 6223 double red_to_set;
6224 double green_to_set; 6224 double green_to_set;
6225# else 6225# else
6226 png_fixed_point red_to_set; 6226 png_fixed_point red_to_set;
6227 png_fixed_point green_to_set; 6227 png_fixed_point green_to_set;
6228# endif 6228# endif
6229 6229
6230 /* The actual coefficients: */ 6230 /* The actual coefficients: */
6231 double red_coefficient; 6231 double red_coefficient;
6232 double green_coefficient; 6232 double green_coefficient;
6233 double blue_coefficient; 6233 double blue_coefficient;
6234 6234
6235 /* Set if the coeefficients have been overridden. */ 6235 /* Set if the coeefficients have been overridden. */
6236 int coefficients_overridden; 6236 int coefficients_overridden;
6237} data; 6237} data;
6238 6238
6239#undef image_transform_ini 6239#undef image_transform_ini
6240#define image_transform_ini image_transform_png_set_rgb_to_gray_ini 6240#define image_transform_ini image_transform_png_set_rgb_to_gray_ini
6241static void 6241static void
6242image_transform_png_set_rgb_to_gray_ini(PNG_CONST image_transform *this, 6242image_transform_png_set_rgb_to_gray_ini(PNG_CONST image_transform *this,
6243 transform_display *that) 6243 transform_display *that)
6244{ 6244{
6245 png_modifier *pm = that->pm; 6245 png_modifier *pm = that->pm;
6246 PNG_CONST color_encoding *e = pm->current_encoding; 6246 PNG_CONST color_encoding *e = pm->current_encoding;
6247 6247
6248 UNUSED(this) 6248 UNUSED(this)
6249 6249
6250 /* Since we check the encoding this flag must be set: */ 6250 /* Since we check the encoding this flag must be set: */
6251 pm->test_uses_encoding = 1; 6251 pm->test_uses_encoding = 1;
6252 6252
6253 /* If 'e' is not NULL chromaticity information is present and either a cHRM 6253 /* If 'e' is not NULL chromaticity information is present and either a cHRM
6254 * or an sRGB chunk will be inserted. 6254 * or an sRGB chunk will be inserted.
6255 */ 6255 */
6256 if (e != 0) 6256 if (e != 0)
6257 { 6257 {
6258 /* Coefficients come from the encoding, but may need to be normalized to a 6258 /* Coefficients come from the encoding, but may need to be normalized to a
6259 * white point Y of 1.0 6259 * white point Y of 1.0
6260 */ 6260 */
6261 PNG_CONST double whiteY = e->red.Y + e->green.Y + e->blue.Y; 6261 PNG_CONST double whiteY = e->red.Y + e->green.Y + e->blue.Y;
6262 6262
6263 data.red_coefficient = e->red.Y; 6263 data.red_coefficient = e->red.Y;
6264 data.green_coefficient = e->green.Y; 6264 data.green_coefficient = e->green.Y;
6265 data.blue_coefficient = e->blue.Y; 6265 data.blue_coefficient = e->blue.Y;
6266 6266
6267 if (whiteY != 1) 6267 if (whiteY != 1)
6268 { 6268 {
6269 data.red_coefficient /= whiteY; 6269 data.red_coefficient /= whiteY;
6270 data.green_coefficient /= whiteY; 6270 data.green_coefficient /= whiteY;
6271 data.blue_coefficient /= whiteY; 6271 data.blue_coefficient /= whiteY;
6272 } 6272 }
6273 } 6273 }
6274 6274
6275 else 6275 else
6276 { 6276 {
6277 /* The default (built in) coeffcients, as above: */ 6277 /* The default (built in) coeffcients, as above: */
6278 data.red_coefficient = 6968 / 32768.; 6278 data.red_coefficient = 6968 / 32768.;
6279 data.green_coefficient = 23434 / 32768.; 6279 data.green_coefficient = 23434 / 32768.;
6280 data.blue_coefficient = 2366 / 32768.; 6280 data.blue_coefficient = 2366 / 32768.;
6281 } 6281 }
6282 6282
6283 data.gamma = pm->current_gamma; 6283 data.gamma = pm->current_gamma;
6284 6284
6285 /* If not set then the calculations assume linear encoding (implicitly): */ 6285 /* If not set then the calculations assume linear encoding (implicitly): */
6286 if (data.gamma == 0) 6286 if (data.gamma == 0)
6287 data.gamma = 1; 6287 data.gamma = 1;
6288 6288
6289 /* The arguments to png_set_rgb_to_gray can override the coefficients implied 6289 /* The arguments to png_set_rgb_to_gray can override the coefficients implied
6290 * by the color space encoding. If doing exhaustive checks do the override 6290 * by the color space encoding. If doing exhaustive checks do the override
6291 * in each case, otherwise do it randomly. 6291 * in each case, otherwise do it randomly.
6292 */ 6292 */
6293 if (pm->test_exhaustive) 6293 if (pm->test_exhaustive)
6294 { 6294 {
6295 /* First time in coefficients_overridden is 0, the following sets it to 1, 6295 /* First time in coefficients_overridden is 0, the following sets it to 1,
6296 * so repeat if it is set. If a test fails this may mean we subsequently 6296 * so repeat if it is set. If a test fails this may mean we subsequently
6297 * skip a non-override test, ignore that. 6297 * skip a non-override test, ignore that.
6298 */ 6298 */
6299 data.coefficients_overridden = !data.coefficients_overridden; 6299 data.coefficients_overridden = !data.coefficients_overridden;
6300 pm->repeat = data.coefficients_overridden != 0; 6300 pm->repeat = data.coefficients_overridden != 0;
6301 } 6301 }
6302 6302
6303 else 6303 else
6304 data.coefficients_overridden = random_choice(); 6304 data.coefficients_overridden = random_choice();
6305 6305
6306 if (data.coefficients_overridden) 6306 if (data.coefficients_overridden)
6307 { 6307 {
6308 /* These values override the color encoding defaults, simply use random 6308 /* These values override the color encoding defaults, simply use random
6309 * numbers. 6309 * numbers.
6310 */ 6310 */
6311 png_uint_32 ru; 6311 png_uint_32 ru;
6312 double total; 6312 double total;
6313 6313
6314 RANDOMIZE(ru); 6314 RANDOMIZE(ru);
6315 data.green_coefficient = total = (ru & 0xffff) / 65535.; 6315 data.green_coefficient = total = (ru & 0xffff) / 65535.;
6316 ru >>= 16; 6316 ru >>= 16;
6317 data.red_coefficient = (1 - total) * (ru & 0xffff) / 65535.; 6317 data.red_coefficient = (1 - total) * (ru & 0xffff) / 65535.;
6318 total += data.red_coefficient; 6318 total += data.red_coefficient;
6319 data.blue_coefficient = 1 - total; 6319 data.blue_coefficient = 1 - total;
6320 6320
6321# ifdef PNG_FLOATING_POINT_SUPPORTED 6321# ifdef PNG_FLOATING_POINT_SUPPORTED
6322 data.red_to_set = data.red_coefficient; 6322 data.red_to_set = data.red_coefficient;
6323 data.green_to_set = data.green_coefficient; 6323 data.green_to_set = data.green_coefficient;
6324# else 6324# else
6325 data.red_to_set = fix(data.red_coefficient); 6325 data.red_to_set = fix(data.red_coefficient);
6326 data.green_to_set = fix(data.green_coefficient); 6326 data.green_to_set = fix(data.green_coefficient);
6327# endif 6327# endif
6328 6328
6329 /* The following just changes the error messages: */ 6329 /* The following just changes the error messages: */
6330 pm->encoding_ignored = 1; 6330 pm->encoding_ignored = 1;
6331 } 6331 }
6332 6332
6333 else 6333 else
6334 { 6334 {
6335 data.red_to_set = -1; 6335 data.red_to_set = -1;
6336 data.green_to_set = -1; 6336 data.green_to_set = -1;
6337 } 6337 }
6338 6338
6339 /* Adjust the error limit in the png_modifier because of the larger errors 6339 /* Adjust the error limit in the png_modifier because of the larger errors
6340 * produced in the digitization during the gamma handling. 6340 * produced in the digitization during the gamma handling.
6341 */ 6341 */
6342 if (data.gamma != 1) /* Use gamma tables */ 6342 if (data.gamma != 1) /* Use gamma tables */
6343 { 6343 {
6344 if (that->this.bit_depth == 16 || pm->assume_16_bit_calculations) 6344 if (that->this.bit_depth == 16 || pm->assume_16_bit_calculations)
6345 { 6345 {
6346 /* The 16 bit case ends up producing a maximum error of about 6346 /* The 16 bit case ends up producing a maximum error of about
6347 * +/-5 in 65535, allow for +/-8 with the given gamma. 6347 * +/-5 in 65535, allow for +/-8 with the given gamma.
6348 */ 6348 */
6349 that->pm->limit += pow(8./65535, data.gamma); 6349 that->pm->limit += pow(8./65535, data.gamma);
6350 } 6350 }
6351 6351
6352 else 6352 else
6353 { 6353 {
6354 /* Rounding to 8 bits in the linear space causes massive errors which 6354 /* Rounding to 8 bits in the linear space causes massive errors which
6355 * will trigger the error check in transform_range_check. Fix that 6355 * will trigger the error check in transform_range_check. Fix that
6356 * here by taking the gamma encoding into account. 6356 * here by taking the gamma encoding into account.
6357 */ 6357 */
6358 that->pm->limit += pow(1./255, data.gamma); 6358 that->pm->limit += pow(1./255, data.gamma);
6359 } 6359 }
6360 } 6360 }
6361 6361
6362 else 6362 else
6363 { 6363 {
6364 /* With no gamma correction a large error comes from the truncation of the 6364 /* With no gamma correction a large error comes from the truncation of the
6365 * calculation in the 8 bit case, allow for that here. 6365 * calculation in the 8 bit case, allow for that here.
6366 */ 6366 */
6367 if (that->this.bit_depth != 16) 6367 if (that->this.bit_depth != 16)
6368 that->pm->limit += 4E-3; 6368 that->pm->limit += 4E-3;
6369 } 6369 }
6370} 6370}
6371 6371
6372static void 6372static void
6373image_transform_png_set_rgb_to_gray_set(PNG_CONST image_transform *this, 6373image_transform_png_set_rgb_to_gray_set(PNG_CONST image_transform *this,
6374 transform_display *that, png_structp pp, png_infop pi) 6374 transform_display *that, png_structp pp, png_infop pi)
6375{ 6375{
6376 PNG_CONST int error_action = 1; /* no error, no defines in png.h */ 6376 PNG_CONST int error_action = 1; /* no error, no defines in png.h */
6377 6377
6378# ifdef PNG_FLOATING_POINT_SUPPORTED 6378# ifdef PNG_FLOATING_POINT_SUPPORTED
6379 png_set_rgb_to_gray(pp, error_action, data.red_to_set, data.green_to_set); 6379 png_set_rgb_to_gray(pp, error_action, data.red_to_set, data.green_to_set);
6380# else 6380# else
6381 png_set_rgb_to_gray_fixed(pp, error_action, data.red_to_set, 6381 png_set_rgb_to_gray_fixed(pp, error_action, data.red_to_set,
6382 data.green_to_set); 6382 data.green_to_set);
6383# endif 6383# endif
6384 6384
6385# ifdef PNG_READ_cHRM_SUPPORTED 6385# ifdef PNG_READ_cHRM_SUPPORTED
6386 if (that->pm->current_encoding != 0) 6386 if (that->pm->current_encoding != 0)
6387 { 6387 {
6388 /* We have an encoding so a cHRM chunk may have been set; if so then 6388 /* We have an encoding so a cHRM chunk may have been set; if so then
6389 * check that the libpng APIs give the correct (X,Y,Z) values within 6389 * check that the libpng APIs give the correct (X,Y,Z) values within
6390 * some margin of error for the round trip through the chromaticity 6390 * some margin of error for the round trip through the chromaticity
6391 * form. 6391 * form.
6392 */ 6392 */
6393# ifdef PNG_FLOATING_POINT_SUPPORTED 6393# ifdef PNG_FLOATING_POINT_SUPPORTED
6394# define API_function png_get_cHRM_XYZ 6394# define API_function png_get_cHRM_XYZ
6395# define API_form "FP" 6395# define API_form "FP"
6396# define API_type double 6396# define API_type double
6397# define API_cvt(x) (x) 6397# define API_cvt(x) (x)
6398# else 6398# else
6399# define API_function png_get_cHRM_XYZ_fixed 6399# define API_function png_get_cHRM_XYZ_fixed
6400# define API_form "fixed" 6400# define API_form "fixed"
6401# define API_type png_fixed_point 6401# define API_type png_fixed_point
6402# define API_cvt(x) ((double)(x)/PNG_FP_1) 6402# define API_cvt(x) ((double)(x)/PNG_FP_1)
6403# endif 6403# endif
6404 6404
6405 API_type rX, gX, bX; 6405 API_type rX, gX, bX;
6406 API_type rY, gY, bY; 6406 API_type rY, gY, bY;
6407 API_type rZ, gZ, bZ; 6407 API_type rZ, gZ, bZ;
6408 6408
6409 if ((API_function(pp, pi, &rX, &rY, &rZ, &gX, &gY, &gZ, &bX, &bY, &bZ) 6409 if ((API_function(pp, pi, &rX, &rY, &rZ, &gX, &gY, &gZ, &bX, &bY, &bZ)
6410 & PNG_INFO_cHRM) != 0) 6410 & PNG_INFO_cHRM) != 0)
6411 { 6411 {
6412 double maxe; 6412 double maxe;
6413 PNG_CONST char *el; 6413 PNG_CONST char *el;
6414 color_encoding e, o; 6414 color_encoding e, o;
6415 6415
6416 /* Expect libpng to return a normalized result, but the original 6416 /* Expect libpng to return a normalized result, but the original
6417 * color space encoding may not be normalized. 6417 * color space encoding may not be normalized.
6418 */ 6418 */
6419 modifier_current_encoding(that->pm, &o); 6419 modifier_current_encoding(that->pm, &o);
6420 normalize_color_encoding(&o); 6420 normalize_color_encoding(&o);
6421 6421
6422 /* Sanity check the pngvalid code - the coefficients should match 6422 /* Sanity check the pngvalid code - the coefficients should match
6423 * the normalized Y values of the encoding unless they were 6423 * the normalized Y values of the encoding unless they were
6424 * overridden. 6424 * overridden.
6425 */ 6425 */
6426 if (data.red_to_set == -1 && data.green_to_set == -1 && 6426 if (data.red_to_set == -1 && data.green_to_set == -1 &&
6427 (fabs(o.red.Y - data.red_coefficient) > DBL_EPSILON || 6427 (fabs(o.red.Y - data.red_coefficient) > DBL_EPSILON ||
6428 fabs(o.green.Y - data.green_coefficient) > DBL_EPSILON || 6428 fabs(o.green.Y - data.green_coefficient) > DBL_EPSILON ||
6429 fabs(o.blue.Y - data.blue_coefficient) > DBL_EPSILON)) 6429 fabs(o.blue.Y - data.blue_coefficient) > DBL_EPSILON))
6430 png_error(pp, "internal pngvalid cHRM coefficient error"); 6430 png_error(pp, "internal pngvalid cHRM coefficient error");
6431 6431
6432 /* Generate a colour space encoding. */ 6432 /* Generate a colour space encoding. */
6433 e.gamma = o.gamma; /* not used */ 6433 e.gamma = o.gamma; /* not used */
6434 e.red.X = API_cvt(rX); 6434 e.red.X = API_cvt(rX);
6435 e.red.Y = API_cvt(rY); 6435 e.red.Y = API_cvt(rY);
6436 e.red.Z = API_cvt(rZ); 6436 e.red.Z = API_cvt(rZ);
6437 e.green.X = API_cvt(gX); 6437 e.green.X = API_cvt(gX);
6438 e.green.Y = API_cvt(gY); 6438 e.green.Y = API_cvt(gY);
6439 e.green.Z = API_cvt(gZ); 6439 e.green.Z = API_cvt(gZ);
6440 e.blue.X = API_cvt(bX); 6440 e.blue.X = API_cvt(bX);
6441 e.blue.Y = API_cvt(bY); 6441 e.blue.Y = API_cvt(bY);
6442 e.blue.Z = API_cvt(bZ); 6442 e.blue.Z = API_cvt(bZ);
6443 6443
6444 /* This should match the original one from the png_modifier, within 6444 /* This should match the original one from the png_modifier, within
6445 * the range permitted by the libpng fixed point representation. 6445 * the range permitted by the libpng fixed point representation.
6446 */ 6446 */
6447 maxe = 0; 6447 maxe = 0;
6448 el = "-"; /* Set to element name with error */ 6448 el = "-"; /* Set to element name with error */
6449 6449
6450# define CHECK(col,x)\ 6450# define CHECK(col,x)\
6451 {\ 6451 {\
6452 double err = fabs(o.col.x - e.col.x);\ 6452 double err = fabs(o.col.x - e.col.x);\
6453 if (err > maxe)\ 6453 if (err > maxe)\
6454 {\ 6454 {\
6455 maxe = err;\ 6455 maxe = err;\
6456 el = #col "(" #x ")";\ 6456 el = #col "(" #x ")";\
6457 }\ 6457 }\
6458 } 6458 }
6459 6459
6460 CHECK(red,X) 6460 CHECK(red,X)
6461 CHECK(red,Y) 6461 CHECK(red,Y)
6462 CHECK(red,Z) 6462 CHECK(red,Z)
6463 CHECK(green,X) 6463 CHECK(green,X)
6464 CHECK(green,Y) 6464 CHECK(green,Y)
6465 CHECK(green,Z) 6465 CHECK(green,Z)
6466 CHECK(blue,X) 6466 CHECK(blue,X)
6467 CHECK(blue,Y) 6467 CHECK(blue,Y)
6468 CHECK(blue,Z) 6468 CHECK(blue,Z)
6469 6469
6470 /* Here in both fixed and floating cases to check the values read 6470 /* Here in both fixed and floating cases to check the values read
6471 * from the cHRm chunk. PNG uses fixed point in the cHRM chunk, so 6471 * from the cHRm chunk. PNG uses fixed point in the cHRM chunk, so
6472 * we can't expect better than +/-.5E-5 on the result, allow 1E-5. 6472 * we can't expect better than +/-.5E-5 on the result, allow 1E-5.
6473 */ 6473 */
6474 if (maxe >= 1E-5) 6474 if (maxe >= 1E-5)
6475 { 6475 {
6476 size_t pos = 0; 6476 size_t pos = 0;
6477 char buffer[256]; 6477 char buffer[256];
6478 6478
6479 pos = safecat(buffer, sizeof buffer, pos, API_form); 6479 pos = safecat(buffer, sizeof buffer, pos, API_form);
6480 pos = safecat(buffer, sizeof buffer, pos, " cHRM "); 6480 pos = safecat(buffer, sizeof buffer, pos, " cHRM ");
6481 pos = safecat(buffer, sizeof buffer, pos, el); 6481 pos = safecat(buffer, sizeof buffer, pos, el);
6482 pos = safecat(buffer, sizeof buffer, pos, " error: "); 6482 pos = safecat(buffer, sizeof buffer, pos, " error: ");
6483 pos = safecatd(buffer, sizeof buffer, pos, maxe, 7); 6483 pos = safecatd(buffer, sizeof buffer, pos, maxe, 7);
6484 pos = safecat(buffer, sizeof buffer, pos, " "); 6484 pos = safecat(buffer, sizeof buffer, pos, " ");
6485 /* Print the color space without the gamma value: */ 6485 /* Print the color space without the gamma value: */
6486 pos = safecat_color_encoding(buffer, sizeof buffer, pos, &o, 0); 6486 pos = safecat_color_encoding(buffer, sizeof buffer, pos, &o, 0);
6487 pos = safecat(buffer, sizeof buffer, pos, " -> "); 6487 pos = safecat(buffer, sizeof buffer, pos, " -> ");
6488 pos = safecat_color_encoding(buffer, sizeof buffer, pos, &e, 0); 6488 pos = safecat_color_encoding(buffer, sizeof buffer, pos, &e, 0);
6489 6489
6490 png_error(pp, buffer); 6490 png_error(pp, buffer);
6491 } 6491 }
6492 } 6492 }
6493 } 6493 }
6494# endif /* READ_cHRM */ 6494# endif /* READ_cHRM */
6495 6495
6496 this->next->set(this->next, that, pp, pi); 6496 this->next->set(this->next, that, pp, pi);
6497} 6497}
6498 6498
6499static void 6499static void
6500image_transform_png_set_rgb_to_gray_mod(PNG_CONST image_transform *this, 6500image_transform_png_set_rgb_to_gray_mod(PNG_CONST image_transform *this,
6501 image_pixel *that, png_structp pp, PNG_CONST transform_display *display) 6501 image_pixel *that, png_structp pp, PNG_CONST transform_display *display)
6502{ 6502{
6503 if ((that->colour_type & PNG_COLOR_MASK_COLOR) != 0) 6503 if ((that->colour_type & PNG_COLOR_MASK_COLOR) != 0)
6504 { 6504 {
6505 double gray, err; 6505 double gray, err;
6506 6506
6507 if (that->colour_type == PNG_COLOR_TYPE_PALETTE) 6507 if (that->colour_type == PNG_COLOR_TYPE_PALETTE)
6508 image_pixel_convert_PLTE(that); 6508 image_pixel_convert_PLTE(that);
6509 6509
6510 /* Image now has RGB channels... */ 6510 /* Image now has RGB channels... */
6511 { 6511 {
6512 PNG_CONST png_modifier *pm = display->pm; 6512 PNG_CONST png_modifier *pm = display->pm;
6513 PNG_CONST unsigned int sample_depth = that->sample_depth; 6513 PNG_CONST unsigned int sample_depth = that->sample_depth;
6514 int isgray; 6514 int isgray;
6515 double r, g, b; 6515 double r, g, b;
6516 double rlo, rhi, glo, ghi, blo, bhi, graylo, grayhi; 6516 double rlo, rhi, glo, ghi, blo, bhi, graylo, grayhi;
6517 6517
6518 /* Do this using interval arithmetic, otherwise it is too difficult to 6518 /* Do this using interval arithmetic, otherwise it is too difficult to
6519 * handle the errors correctly. 6519 * handle the errors correctly.
6520 * 6520 *
6521 * To handle the gamma correction work out the upper and lower bounds 6521 * To handle the gamma correction work out the upper and lower bounds
6522 * of the digitized value. Assume rounding here - normally the values 6522 * of the digitized value. Assume rounding here - normally the values
6523 * will be identical after this operation if there is only one 6523 * will be identical after this operation if there is only one
6524 * transform, feel free to delete the png_error checks on this below in 6524 * transform, feel free to delete the png_error checks on this below in
6525 * the future (this is just me trying to ensure it works!) 6525 * the future (this is just me trying to ensure it works!)
6526 */ 6526 */
6527 r = rlo = rhi = that->redf; 6527 r = rlo = rhi = that->redf;
6528 rlo -= that->rede; 6528 rlo -= that->rede;
6529 rlo = digitize(pm, rlo, sample_depth, 1/*round*/); 6529 rlo = digitize(pm, rlo, sample_depth, 1/*round*/);
6530 rhi += that->rede; 6530 rhi += that->rede;
6531 rhi = digitize(pm, rhi, sample_depth, 1/*round*/); 6531 rhi = digitize(pm, rhi, sample_depth, 1/*round*/);
6532 6532
6533 g = glo = ghi = that->greenf; 6533 g = glo = ghi = that->greenf;
6534 glo -= that->greene; 6534 glo -= that->greene;
6535 glo = digitize(pm, glo, sample_depth, 1/*round*/); 6535 glo = digitize(pm, glo, sample_depth, 1/*round*/);
6536 ghi += that->greene; 6536 ghi += that->greene;
6537 ghi = digitize(pm, ghi, sample_depth, 1/*round*/); 6537 ghi = digitize(pm, ghi, sample_depth, 1/*round*/);
6538 6538
6539 b = blo = bhi = that->bluef; 6539 b = blo = bhi = that->bluef;
6540 blo -= that->bluee; 6540 blo -= that->bluee;
6541 blo = digitize(pm, blo, sample_depth, 1/*round*/); 6541 blo = digitize(pm, blo, sample_depth, 1/*round*/);
6542 bhi += that->greene; 6542 bhi += that->greene;
6543 bhi = digitize(pm, bhi, sample_depth, 1/*round*/); 6543 bhi = digitize(pm, bhi, sample_depth, 1/*round*/);
6544 6544
6545 isgray = r==g && g==b; 6545 isgray = r==g && g==b;
6546 6546
6547 if (data.gamma != 1) 6547 if (data.gamma != 1)
6548 { 6548 {
6549 PNG_CONST double power = 1/data.gamma; 6549 PNG_CONST double power = 1/data.gamma;
6550 PNG_CONST double abse = abserr(pm, sample_depth, sample_depth); 6550 PNG_CONST double abse = abserr(pm, sample_depth, sample_depth);
6551 6551
6552 /* 'abse' is the absolute error permitted in linear calculations. It 6552 /* 'abse' is the absolute error permitted in linear calculations. It
6553 * is used here to capture the error permitted in the handling 6553 * is used here to capture the error permitted in the handling
6554 * (undoing) of the gamma encoding. Once again digitization occurs 6554 * (undoing) of the gamma encoding. Once again digitization occurs
6555 * to handle the upper and lower bounds of the values. This is 6555 * to handle the upper and lower bounds of the values. This is
6556 * where the real errors are introduced. 6556 * where the real errors are introduced.
6557 */ 6557 */
6558 r = pow(r, power); 6558 r = pow(r, power);
6559 rlo = digitize(pm, pow(rlo, power)-abse, sample_depth, 1); 6559 rlo = digitize(pm, pow(rlo, power)-abse, sample_depth, 1);
6560 rhi = digitize(pm, pow(rhi, power)+abse, sample_depth, 1); 6560 rhi = digitize(pm, pow(rhi, power)+abse, sample_depth, 1);
6561 6561
6562 g = pow(g, power); 6562 g = pow(g, power);
6563 glo = digitize(pm, pow(glo, power)-abse, sample_depth, 1); 6563 glo = digitize(pm, pow(glo, power)-abse, sample_depth, 1);
6564 ghi = digitize(pm, pow(ghi, power)+abse, sample_depth, 1); 6564 ghi = digitize(pm, pow(ghi, power)+abse, sample_depth, 1);
6565 6565
6566 b = pow(b, power); 6566 b = pow(b, power);
6567 blo = digitize(pm, pow(blo, power)-abse, sample_depth, 1); 6567 blo = digitize(pm, pow(blo, power)-abse, sample_depth, 1);
6568 bhi = digitize(pm, pow(bhi, power)+abse, sample_depth, 1); 6568 bhi = digitize(pm, pow(bhi, power)+abse, sample_depth, 1);
6569 } 6569 }
6570 6570
6571 /* Now calculate the actual gray values. Although the error in the 6571 /* Now calculate the actual gray values. Although the error in the
6572 * coefficients depends on whether they were specified on the command 6572 * coefficients depends on whether they were specified on the command
6573 * line (in which case truncation to 15 bits happened) or not (rounding 6573 * line (in which case truncation to 15 bits happened) or not (rounding
6574 * was used) the maxium error in an individual coefficient is always 6574 * was used) the maxium error in an individual coefficient is always
6575 * 1/32768, because even in the rounding case the requirement that 6575 * 1/32768, because even in the rounding case the requirement that
6576 * coefficients add up to 32768 can cause a larger rounding error. 6576 * coefficients add up to 32768 can cause a larger rounding error.
6577 * 6577 *
6578 * The only time when rounding doesn't occur in 1.5.5 and later is when 6578 * The only time when rounding doesn't occur in 1.5.5 and later is when
6579 * the non-gamma code path is used for less than 16 bit data. 6579 * the non-gamma code path is used for less than 16 bit data.
6580 */ 6580 */
6581 gray = r * data.red_coefficient + g * data.green_coefficient + 6581 gray = r * data.red_coefficient + g * data.green_coefficient +
6582 b * data.blue_coefficient; 6582 b * data.blue_coefficient;
6583 6583
6584 { 6584 {
6585 PNG_CONST int do_round = data.gamma != 1 || sample_depth == 16; 6585 PNG_CONST int do_round = data.gamma != 1 || sample_depth == 16;
6586 PNG_CONST double ce = 1. / 32768; 6586 PNG_CONST double ce = 1. / 32768;
6587 6587
6588 graylo = digitize(pm, rlo * (data.red_coefficient-ce) + 6588 graylo = digitize(pm, rlo * (data.red_coefficient-ce) +
6589 glo * (data.green_coefficient-ce) + 6589 glo * (data.green_coefficient-ce) +
6590 blo * (data.blue_coefficient-ce), sample_depth, do_round); 6590 blo * (data.blue_coefficient-ce), sample_depth, do_round);
6591 if (graylo <= 0) 6591 if (graylo <= 0)
6592 graylo = 0; 6592 graylo = 0;
6593 6593
6594 grayhi = digitize(pm, rhi * (data.red_coefficient+ce) + 6594 grayhi = digitize(pm, rhi * (data.red_coefficient+ce) +
6595 ghi * (data.green_coefficient+ce) + 6595 ghi * (data.green_coefficient+ce) +
6596 bhi * (data.blue_coefficient+ce), sample_depth, do_round); 6596 bhi * (data.blue_coefficient+ce), sample_depth, do_round);
6597 if (grayhi >= 1) 6597 if (grayhi >= 1)
6598 grayhi = 1; 6598 grayhi = 1;
6599 } 6599 }
6600 6600
6601 /* And invert the gamma. */ 6601 /* And invert the gamma. */
6602 if (data.gamma != 1) 6602 if (data.gamma != 1)
6603 { 6603 {
6604 PNG_CONST double power = data.gamma; 6604 PNG_CONST double power = data.gamma;
6605 6605
6606 gray = pow(gray, power); 6606 gray = pow(gray, power);
6607 graylo = digitize(pm, pow(graylo, power), sample_depth, 1); 6607 graylo = digitize(pm, pow(graylo, power), sample_depth, 1);
6608 grayhi = digitize(pm, pow(grayhi, power), sample_depth, 1); 6608 grayhi = digitize(pm, pow(grayhi, power), sample_depth, 1);
6609 } 6609 }
6610 6610
6611 /* Now the error can be calculated. 6611 /* Now the error can be calculated.
6612 * 6612 *
6613 * If r==g==b because there is no overall gamma correction libpng 6613 * If r==g==b because there is no overall gamma correction libpng
6614 * currently preserves the original value. 6614 * currently preserves the original value.
6615 */ 6615 */
6616 if (isgray) 6616 if (isgray)
6617 err = (that->rede + that->greene + that->bluee)/3; 6617 err = (that->rede + that->greene + that->bluee)/3;
6618 6618
6619 else 6619 else
6620 { 6620 {
6621 err = fabs(grayhi-gray); 6621 err = fabs(grayhi-gray);
6622 if (fabs(gray - graylo) > err) 6622 if (fabs(gray - graylo) > err)
6623 err = fabs(graylo-gray); 6623 err = fabs(graylo-gray);
6624 6624
6625 /* Check that this worked: */ 6625 /* Check that this worked: */
6626 if (err > display->pm->limit) 6626 if (err > display->pm->limit)
6627 { 6627 {
6628 size_t pos = 0; 6628 size_t pos = 0;
6629 char buffer[128]; 6629 char buffer[128];
6630 6630
6631 pos = safecat(buffer, sizeof buffer, pos, "rgb_to_gray error "); 6631 pos = safecat(buffer, sizeof buffer, pos, "rgb_to_gray error ");
6632 pos = safecatd(buffer, sizeof buffer, pos, err, 6); 6632 pos = safecatd(buffer, sizeof buffer, pos, err, 6);
6633 pos = safecat(buffer, sizeof buffer, pos, " exceeds limit "); 6633 pos = safecat(buffer, sizeof buffer, pos, " exceeds limit ");
6634 pos = safecatd(buffer, sizeof buffer, pos, 6634 pos = safecatd(buffer, sizeof buffer, pos,
6635 display->pm->limit, 6); 6635 display->pm->limit, 6);
6636 png_error(pp, buffer); 6636 png_error(pp, buffer);
6637 } 6637 }
6638 } 6638 }
6639 } 6639 }
6640 6640
6641 that->bluef = that->greenf = that->redf = gray; 6641 that->bluef = that->greenf = that->redf = gray;
6642 that->bluee = that->greene = that->rede = err; 6642 that->bluee = that->greene = that->rede = err;
6643 6643
6644 /* The sBIT is the minium of the three colour channel sBITs. */ 6644 /* The sBIT is the minium of the three colour channel sBITs. */
6645 if (that->red_sBIT > that->green_sBIT) 6645 if (that->red_sBIT > that->green_sBIT)
6646 that->red_sBIT = that->green_sBIT; 6646 that->red_sBIT = that->green_sBIT;
6647 if (that->red_sBIT > that->blue_sBIT) 6647 if (that->red_sBIT > that->blue_sBIT)
6648 that->red_sBIT = that->blue_sBIT; 6648 that->red_sBIT = that->blue_sBIT;
6649 that->blue_sBIT = that->green_sBIT = that->red_sBIT; 6649 that->blue_sBIT = that->green_sBIT = that->red_sBIT;
6650 6650
6651 /* And remove the colour bit in the type: */ 6651 /* And remove the colour bit in the type: */
6652 if (that->colour_type == PNG_COLOR_TYPE_RGB) 6652 if (that->colour_type == PNG_COLOR_TYPE_RGB)
6653 that->colour_type = PNG_COLOR_TYPE_GRAY; 6653 that->colour_type = PNG_COLOR_TYPE_GRAY;
6654 else if (that->colour_type == PNG_COLOR_TYPE_RGB_ALPHA) 6654 else if (that->colour_type == PNG_COLOR_TYPE_RGB_ALPHA)
6655 that->colour_type = PNG_COLOR_TYPE_GRAY_ALPHA; 6655 that->colour_type = PNG_COLOR_TYPE_GRAY_ALPHA;
6656 } 6656 }
6657 6657
6658 this->next->mod(this->next, that, pp, display); 6658 this->next->mod(this->next, that, pp, display);
6659} 6659}
6660 6660
6661static int 6661static int
6662image_transform_png_set_rgb_to_gray_add(image_transform *this, 6662image_transform_png_set_rgb_to_gray_add(image_transform *this,
6663 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth) 6663 PNG_CONST image_transform **that, png_byte colour_type, png_byte bit_depth)
6664{ 6664{
6665 UNUSED(bit_depth) 6665 UNUSED(bit_depth)
6666 6666
6667 this->next = *that; 6667 this->next = *that;
6668 *that = this; 6668 *that = this;
6669 6669
6670 return (colour_type & PNG_COLOR_MASK_COLOR) != 0; 6670 return (colour_type & PNG_COLOR_MASK_COLOR) != 0;
6671} 6671}
6672 6672
6673#undef data 6673#undef data
6674IT(rgb_to_gray); 6674IT(rgb_to_gray);
6675#undef PT 6675#undef PT
6676#define PT ITSTRUCT(rgb_to_gray) 6676#define PT ITSTRUCT(rgb_to_gray)
6677#undef image_transform_ini 6677#undef image_transform_ini
6678#define image_transform_ini image_transform_default_ini 6678#define image_transform_ini image_transform_default_ini
6679#endif /* PNG_READ_RGB_TO_GRAY_SUPPORTED */ 6679#endif /* PNG_READ_RGB_TO_GRAY_SUPPORTED */
6680 6680
6681#ifdef PNG_READ_BACKGROUND_SUPPORTED 6681#ifdef PNG_READ_BACKGROUND_SUPPORTED
6682/* png_set_background(png_structp, png_const_color_16p background_color, 6682/* png_set_background(png_structp, png_const_color_16p background_color,
6683 * int background_gamma_code, int need_expand, double background_gamma) 6683 * int background_gamma_code, int need_expand, double background_gamma)
6684 * png_set_background_fixed(png_structp, png_const_color_16p background_color, 6684 * png_set_background_fixed(png_structp, png_const_color_16p background_color,
6685 * int background_gamma_code, int need_expand, 6685 * int background_gamma_code, int need_expand,
6686 * png_fixed_point background_gamma) 6686 * png_fixed_point background_gamma)
6687 * 6687 *
6688 * As with rgb_to_gray this ignores the gamma (at present.) 6688 * As with rgb_to_gray this ignores the gamma (at present.)
6689*/ 6689*/
6690#define data ITDATA(background) 6690#define data ITDATA(background)
6691static image_pixel data; 6691static image_pixel data;
6692 6692
6693static void 6693static void
6694image_transform_png_set_background_set(PNG_CONST image_transform *this, 6694image_transform_png_set_background_set(PNG_CONST image_transform *this,
6695 transform_display *that, png_structp pp, png_infop pi) 6695 transform_display *that, png_structp pp, png_infop pi)
6696{ 6696{
6697 png_byte colour_type, bit_depth; 6697 png_byte colour_type, bit_depth;
6698 png_byte random_bytes[8]; /* 8 bytes - 64 bits - the biggest pixel */ 6698 png_byte random_bytes[8]; /* 8 bytes - 64 bits - the biggest pixel */
6699 png_color_16 back; 6699 png_color_16 back;
6700 6700
6701 /* We need a background colour, because we don't know exactly what transforms 6701 /* We need a background colour, because we don't know exactly what transforms
6702 * have been set we have to supply the colour in the original file format and 6702 * have been set we have to supply the colour in the original file format and
6703 * so we need to know what that is! The background colour is stored in the 6703 * so we need to know what that is! The background colour is stored in the
6704 * transform_display. 6704 * transform_display.
6705 */ 6705 */
6706 RANDOMIZE(random_bytes); 6706 RANDOMIZE(random_bytes);
6707 6707
6708 /* Read the random value, for colour type 3 the background colour is actually 6708 /* Read the random value, for colour type 3 the background colour is actually
6709 * expressed as a 24bit rgb, not an index. 6709 * expressed as a 24bit rgb, not an index.
6710 */ 6710 */
6711 colour_type = that->this.colour_type; 6711 colour_type = that->this.colour_type;
6712 if (colour_type == 3) 6712 if (colour_type == 3)
6713 { 6713 {
6714 colour_type = PNG_COLOR_TYPE_RGB; 6714 colour_type = PNG_COLOR_TYPE_RGB;
6715 bit_depth = 8; 6715 bit_depth = 8;
6716 } 6716 }
6717 6717
6718 else 6718 else
6719 bit_depth = that->this.bit_depth; 6719 bit_depth = that->this.bit_depth;
6720 6720
6721 image_pixel_init(&data, random_bytes, colour_type, 6721 image_pixel_init(&data, random_bytes, colour_type,
6722 bit_depth, 0/*x*/, 0/*unused: palette*/); 6722 bit_depth, 0/*x*/, 0/*unused: palette*/);
6723 6723
6724 /* Extract the background colour from this image_pixel, but make sure the 6724 /* Extract the background colour from this image_pixel, but make sure the
6725 * unused fields of 'back' are garbage. 6725 * unused fields of 'back' are garbage.
6726 */ 6726 */
6727 RANDOMIZE(back); 6727 RANDOMIZE(back);
6728 6728
6729 if (colour_type & PNG_COLOR_MASK_COLOR) 6729 if (colour_type & PNG_COLOR_MASK_COLOR)
6730 { 6730 {
6731 back.red = (png_uint_16)data.red; 6731 back.red = (png_uint_16)data.red;
6732 back.green = (png_uint_16)data.green; 6732 back.green = (png_uint_16)data.green;
6733 back.blue = (png_uint_16)data.blue; 6733 back.blue = (png_uint_16)data.blue;
6734 } 6734 }
6735 6735
6736 else 6736 else
6737 back.gray = (png_uint_16)data.red; 6737 back.gray = (png_uint_16)data.red;
6738 6738
6739# ifdef PNG_FLOATING_POINT_SUPPORTED 6739# ifdef PNG_FLOATING_POINT_SUPPORTED
6740 png_set_background(pp, &back, PNG_BACKGROUND_GAMMA_FILE, 1/*need expand*/, 6740 png_set_background(pp, &back, PNG_BACKGROUND_GAMMA_FILE, 1/*need expand*/,
6741 0); 6741 0);
6742# else 6742# else
6743 png_set_background_fixed(pp, &back, PNG_BACKGROUND_GAMMA_FILE, 6743 png_set_background_fixed(pp, &back, PNG_BACKGROUND_GAMMA_FILE,
6744 1/*need expand*/, 0); 6744 1/*need expand*/, 0);
6745# endif 6745# endif
6746 6746
6747 this->next->set(this->next, that, pp, pi); 6747 this->next->set(this->next, that, pp, pi);
6748} 6748}
6749 6749
6750static void 6750static void
6751image_transform_png_set_background_mod(PNG_CONST image_transform *this, 6751image_transform_png_set_background_mod(PNG_CONST image_transform *this,
6752 image_pixel *that, png_structp pp, PNG_CONST transform_display *display) 6752 image_pixel *that, png_structp pp, PNG_CONST transform_display *display)
6753{ 6753{
6754 /* Check for tRNS first: */ 6754 /* Check for tRNS first: */
6755 if (that->have_tRNS && that->colour_type != PNG_COLOR_TYPE_PALETTE) 6755 if (that->have_tRNS && that->colour_type != PNG_COLOR_TYPE_PALETTE)
6756 image_pixel_add_alpha(that, &display->this); 6756 image_pixel_add_alpha(that, &display->this);
6757 6757
6758 /* This is only necessary if the alpha value is less than 1. */ 6758 /* This is only necessary if the alpha value is less than 1. */
6759 if (that->alphaf < 1) 6759 if (that->alphaf < 1)
6760 { 6760 {
6761 /* Now we do the background calculation without any gamma correction. */ 6761 /* Now we do the background calculation without any gamma correction. */
6762 if (that->alphaf <= 0) 6762 if (that->alphaf <= 0)
6763 { 6763 {
6764 that->redf = data.redf; 6764 that->redf = data.redf;
6765 that->greenf = data.greenf; 6765 that->greenf = data.greenf;
6766 that->bluef = data.bluef; 6766 that->bluef = data.bluef;
6767 6767
6768 that->rede = data.rede; 6768 that->rede = data.rede;
6769 that->greene = data.greene; 6769 that->greene = data.greene;
6770 that->bluee = data.bluee; 6770 that->bluee = data.bluee;
6771 6771
6772 that->red_sBIT= data.red_sBIT; 6772 that->red_sBIT= data.red_sBIT;
6773 that->green_sBIT= data.green_sBIT; 6773 that->green_sBIT= data.green_sBIT;
6774 that->blue_sBIT= data.blue_sBIT; 6774 that->blue_sBIT= data.blue_sBIT;
6775 } 6775 }
6776 6776
6777 else /* 0 < alpha < 1 */ 6777 else /* 0 < alpha < 1 */
6778 { 6778 {
6779 double alf = 1 - that->alphaf; 6779 double alf = 1 - that->alphaf;
6780 6780
6781 that->redf = that->redf * that->alphaf + data.redf * alf; 6781 that->redf = that->redf * that->alphaf + data.redf * alf;
6782 that->rede = that->rede * that->alphaf + data.rede * alf + 6782 that->rede = that->rede * that->alphaf + data.rede * alf +
6783 DBL_EPSILON; 6783 DBL_EPSILON;
6784 that->greenf = that->greenf * that->alphaf + data.greenf * alf; 6784 that->greenf = that->greenf * that->alphaf + data.greenf * alf;
6785 that->greene = that->greene * that->alphaf + data.greene * alf + 6785 that->greene = that->greene * that->alphaf + data.greene * alf +
6786 DBL_EPSILON; 6786 DBL_EPSILON;
6787 that->bluef = that->bluef * that->alphaf + data.bluef * alf; 6787 that->bluef = that->bluef * that->alphaf + data.bluef * alf;
6788 that->bluee = that->bluee * that->alphaf + data.bluee * alf + 6788 that->bluee = that->bluee * that->alphaf + data.bluee * alf +
6789 DBL_EPSILON; 6789 DBL_EPSILON;
6790 } 6790 }
6791 6791
6792 /* Remove the alpha type and set the alpha (not in that order.) */ 6792 /* Remove the alpha type and set the alpha (not in that order.) */
6793 that->alphaf = 1; 6793 that->alphaf = 1;
6794 that->alphae = 0; 6794 that->alphae = 0;
6795 6795
6796 if (that->colour_type == PNG_COLOR_TYPE_RGB_ALPHA) 6796 if (that->colour_type == PNG_COLOR_TYPE_RGB_ALPHA)
6797 that->colour_type = PNG_COLOR_TYPE_RGB; 6797 that->colour_type = PNG_COLOR_TYPE_RGB;
6798 else if (that->colour_type == PNG_COLOR_TYPE_GRAY_ALPHA) 6798 else if (that->colour_type == PNG_COLOR_TYPE_GRAY_ALPHA)
6799 that->colour_type = PNG_COLOR_TYPE_GRAY; 6799 that->colour_type = PNG_COLOR_TYPE_GRAY;
6800 /* PNG_COLOR_TYPE_PALETTE is not changed */ 6800 /* PNG_COLOR_TYPE_PALETTE is not changed */
6801 } 6801 }
6802 6802
6803 this->next->mod(this->next, that, pp, display); 6803 this->next->mod(this->next, that, pp, display);
6804} 6804}
6805 6805
6806#define image_transform_png_set_background_add image_transform_default_add 6806#define image_transform_png_set_background_add image_transform_default_add
6807 6807
6808#undef data 6808#undef data
6809IT(background); 6809IT(background);
6810#undef PT 6810#undef PT
6811#define PT ITSTRUCT(background) 6811#define PT ITSTRUCT(background)
6812#endif /* PNG_READ_BACKGROUND_SUPPORTED */ 6812#endif /* PNG_READ_BACKGROUND_SUPPORTED */
6813 6813
6814/* This may just be 'end' if all the transforms are disabled! */ 6814/* This may just be 'end' if all the transforms are disabled! */
6815static image_transform *PNG_CONST image_transform_first = &PT; 6815static image_transform *PNG_CONST image_transform_first = &PT;
6816 6816
6817static void 6817static void
6818transform_enable(PNG_CONST char *name) 6818transform_enable(PNG_CONST char *name)
6819{ 6819{
6820 /* Everything starts out enabled, so if we see an 'enable' disabled 6820 /* Everything starts out enabled, so if we see an 'enable' disabled
6821 * everything else the first time round. 6821 * everything else the first time round.
6822 */ 6822 */
6823 static int all_disabled = 0; 6823 static int all_disabled = 0;
6824 int found_it = 0; 6824 int found_it = 0;
6825 image_transform *list = image_transform_first; 6825 image_transform *list = image_transform_first;
6826 6826
6827 while (list != &image_transform_end) 6827 while (list != &image_transform_end)
6828 { 6828 {
6829 if (strcmp(list->name, name) == 0) 6829 if (strcmp(list->name, name) == 0)
6830 { 6830 {
6831 list->enable = 1; 6831 list->enable = 1;
6832 found_it = 1; 6832 found_it = 1;
6833 } 6833 }
6834 else if (!all_disabled) 6834 else if (!all_disabled)
6835 list->enable = 0; 6835 list->enable = 0;
6836 6836
6837 list = list->list; 6837 list = list->list;
6838 } 6838 }
6839 6839
6840 all_disabled = 1; 6840 all_disabled = 1;
6841 6841
6842 if (!found_it) 6842 if (!found_it)
6843 { 6843 {
6844 fprintf(stderr, "pngvalid: --transform-enable=%s: unknown transform\n", 6844 fprintf(stderr, "pngvalid: --transform-enable=%s: unknown transform\n",
6845 name); 6845 name);
6846 exit(1); 6846 exit(1);
6847 } 6847 }
6848} 6848}
6849 6849
6850static void 6850static void
6851transform_disable(PNG_CONST char *name) 6851transform_disable(PNG_CONST char *name)
6852{ 6852{
6853 image_transform *list = image_transform_first; 6853 image_transform *list = image_transform_first;
6854 6854
6855 while (list != &image_transform_end) 6855 while (list != &image_transform_end)
6856 { 6856 {
6857 if (strcmp(list->name, name) == 0) 6857 if (strcmp(list->name, name) == 0)
6858 { 6858 {
6859 list->enable = 0; 6859 list->enable = 0;
6860 return; 6860 return;
6861 } 6861 }
6862 6862
6863 list = list->list; 6863 list = list->list;
6864 } 6864 }
6865 6865
6866 fprintf(stderr, "pngvalid: --transform-disable=%s: unknown transform\n", 6866 fprintf(stderr, "pngvalid: --transform-disable=%s: unknown transform\n",
6867 name); 6867 name);
6868 exit(1); 6868 exit(1);
6869} 6869}
6870 6870
6871static void 6871static void
6872image_transform_reset_count(void) 6872image_transform_reset_count(void)
6873{ 6873{
6874 image_transform *next = image_transform_first; 6874 image_transform *next = image_transform_first;
6875 int count = 0; 6875 int count = 0;
6876 6876
6877 while (next != &image_transform_end) 6877 while (next != &image_transform_end)
6878 { 6878 {
6879 next->local_use = 0; 6879 next->local_use = 0;
6880 next->next = 0; 6880 next->next = 0;
6881 next = next->list; 6881 next = next->list;
6882 ++count; 6882 ++count;
6883 } 6883 }
6884 6884
6885 /* This can only happen if we every have more than 32 transforms (excluding 6885 /* This can only happen if we every have more than 32 transforms (excluding
6886 * the end) in the list. 6886 * the end) in the list.
6887 */ 6887 */
6888 if (count > 32) abort(); 6888 if (count > 32) abort();
6889} 6889}
6890 6890
6891static int 6891static int
6892image_transform_test_counter(png_uint_32 counter, unsigned int max) 6892image_transform_test_counter(png_uint_32 counter, unsigned int max)
6893{ 6893{
6894 /* Test the list to see if there is any point contining, given a current 6894 /* Test the list to see if there is any point contining, given a current
6895 * counter and a 'max' value. 6895 * counter and a 'max' value.
6896 */ 6896 */
6897 image_transform *next = image_transform_first; 6897 image_transform *next = image_transform_first;
6898 6898
6899 while (next != &image_transform_end) 6899 while (next != &image_transform_end)
6900 { 6900 {
6901 /* For max 0 or 1 continue until the counter overflows: */ 6901 /* For max 0 or 1 continue until the counter overflows: */
6902 counter >>= 1; 6902 counter >>= 1;
6903 6903
6904 /* Continue if any entry hasn't reacked the max. */ 6904 /* Continue if any entry hasn't reacked the max. */
6905 if (max > 1 && next->local_use < max) 6905 if (max > 1 && next->local_use < max)
6906 return 1; 6906 return 1;
6907 next = next->list; 6907 next = next->list;
6908 } 6908 }
6909 6909
6910 return max <= 1 && counter == 0; 6910 return max <= 1 && counter == 0;
6911} 6911}
6912 6912
6913static png_uint_32 6913static png_uint_32
6914image_transform_add(PNG_CONST image_transform **this, unsigned int max, 6914image_transform_add(PNG_CONST image_transform **this, unsigned int max,
6915 png_uint_32 counter, char *name, size_t sizeof_name, size_t *pos, 6915 png_uint_32 counter, char *name, size_t sizeof_name, size_t *pos,
6916 png_byte colour_type, png_byte bit_depth) 6916 png_byte colour_type, png_byte bit_depth)
6917{ 6917{
6918 for (;;) /* until we manage to add something */ 6918 for (;;) /* until we manage to add something */
6919 { 6919 {
6920 png_uint_32 mask; 6920 png_uint_32 mask;
6921 image_transform *list; 6921 image_transform *list;
6922 6922
6923 /* Find the next counter value, if the counter is zero this is the start 6923 /* Find the next counter value, if the counter is zero this is the start
6924 * of the list. This routine always returns the current counter (not the 6924 * of the list. This routine always returns the current counter (not the
6925 * next) so it returns 0 at the end and expects 0 at the beginning. 6925 * next) so it returns 0 at the end and expects 0 at the beginning.
6926 */ 6926 */
6927 if (counter == 0) /* first time */ 6927 if (counter == 0) /* first time */
6928 { 6928 {
6929 image_transform_reset_count(); 6929 image_transform_reset_count();
6930 if (max <= 1) 6930 if (max <= 1)
6931 counter = 1; 6931 counter = 1;
6932 else 6932 else
6933 counter = random_32(); 6933 counter = random_32();
6934 } 6934 }
6935 else /* advance the counter */ 6935 else /* advance the counter */
6936 { 6936 {
6937 switch (max) 6937 switch (max)
6938 { 6938 {
6939 case 0: ++counter; break; 6939 case 0: ++counter; break;
6940 case 1: counter <<= 1; break; 6940 case 1: counter <<= 1; break;
6941 default: counter = random_32(); break; 6941 default: counter = random_32(); break;
6942 } 6942 }
6943 } 6943 }
6944 6944
6945 /* Now add all these items, if possible */ 6945 /* Now add all these items, if possible */
6946 *this = &image_transform_end; 6946 *this = &image_transform_end;
6947 list = image_transform_first; 6947 list = image_transform_first;
6948 mask = 1; 6948 mask = 1;
6949 6949
6950 /* Go through the whole list adding anything that the counter selects: */ 6950 /* Go through the whole list adding anything that the counter selects: */
6951 while (list != &image_transform_end) 6951 while (list != &image_transform_end)
6952 { 6952 {
6953 if ((counter & mask) != 0 && list->enable && 6953 if ((counter & mask) != 0 && list->enable &&
6954 (max == 0 || list->local_use < max)) 6954 (max == 0 || list->local_use < max))
6955 { 6955 {
6956 /* Candidate to add: */ 6956 /* Candidate to add: */
6957 if (list->add(list, this, colour_type, bit_depth) || max == 0) 6957 if (list->add(list, this, colour_type, bit_depth) || max == 0)
6958 { 6958 {
6959 /* Added, so add to the name too. */ 6959 /* Added, so add to the name too. */
6960 *pos = safecat(name, sizeof_name, *pos, " +"); 6960 *pos = safecat(name, sizeof_name, *pos, " +");
6961 *pos = safecat(name, sizeof_name, *pos, list->name); 6961 *pos = safecat(name, sizeof_name, *pos, list->name);
6962 } 6962 }
6963 6963
6964 else 6964 else
6965 { 6965 {
6966 /* Not useful and max>0, so remove it from *this: */ 6966 /* Not useful and max>0, so remove it from *this: */
6967 *this = list->next; 6967 *this = list->next;
6968 list->next = 0; 6968 list->next = 0;
6969 6969
6970 /* And, since we know it isn't useful, stop it being added again 6970 /* And, since we know it isn't useful, stop it being added again
6971 * in this run: 6971 * in this run:
6972 */ 6972 */
6973 list->local_use = max; 6973 list->local_use = max;
6974 } 6974 }
6975 } 6975 }
6976 6976
6977 mask <<= 1; 6977 mask <<= 1;
6978 list = list->list; 6978 list = list->list;
6979 } 6979 }
6980 6980
6981 /* Now if anything was added we have something to do. */ 6981 /* Now if anything was added we have something to do. */
6982 if (*this != &image_transform_end) 6982 if (*this != &image_transform_end)
6983 return counter; 6983 return counter;
6984 6984
6985 /* Nothing added, but was there anything in there to add? */ 6985 /* Nothing added, but was there anything in there to add? */
6986 if (!image_transform_test_counter(counter, max)) 6986 if (!image_transform_test_counter(counter, max))
6987 return 0; 6987 return 0;
6988 } 6988 }
6989} 6989}
6990 6990
6991#ifdef THIS_IS_THE_PROFORMA 6991#ifdef THIS_IS_THE_PROFORMA
6992static void 6992static void
6993image_transform_png_set_@_set(PNG_CONST image_transform *this, 6993image_transform_png_set_@_set(PNG_CONST image_transform *this,
6994 transform_display *that, png_structp pp, png_infop pi) 6994 transform_display *that, png_structp pp, png_infop pi)
6995{ 6995{
6996 png_set_@(pp); 6996 png_set_@(pp);
6997 this->next->set(this->next, that, pp, pi); 6997 this->next->set(this->next, that, pp, pi);
6998} 6998}
6999 6999
7000static void 7000static void
7001image_transform_png_set_@_mod(PNG_CONST image_transform *this, 7001image_transform_png_set_@_mod(PNG_CONST image_transform *this,
7002 image_pixel *that, png_structp pp, PNG_CONST transform_display *display) 7002 image_pixel *that, png_structp pp, PNG_CONST transform_display *display)
7003{ 7003{
7004 this->next->mod(this->next, that, pp, display); 7004 this->next->mod(this->next, that, pp, display);
7005} 7005}
7006 7006
7007static int 7007static int
7008image_transform_png_set_@_add(image_transform *this, 7008image_transform_png_set_@_add(image_transform *this,
7009 PNG_CONST image_transform **that, char *name, size_t sizeof_name, 7009 PNG_CONST image_transform **that, char *name, size_t sizeof_name,
7010 size_t *pos, png_byte colour_type, png_byte bit_depth) 7010 size_t *pos, png_byte colour_type, png_byte bit_depth)
7011{ 7011{
7012 this->next = *that; 7012 this->next = *that;
7013 *that = this; 7013 *that = this;
7014 7014
7015 *pos = safecat(name, sizeof_name, *pos, " +@"); 7015 *pos = safecat(name, sizeof_name, *pos, " +@");
7016 7016
7017 return 1; 7017 return 1;
7018} 7018}
7019 7019
7020IT(@); 7020IT(@);
7021#endif 7021#endif
7022 7022
7023/* png_set_quantize(png_structp, png_colorp palette, int num_palette, 7023/* png_set_quantize(png_structp, png_colorp palette, int num_palette,
7024 * int maximum_colors, png_const_uint_16p histogram, int full_quantize) 7024 * int maximum_colors, png_const_uint_16p histogram, int full_quantize)
7025 * 7025 *
7026 * Very difficult to validate this! 7026 * Very difficult to validate this!
7027 */ 7027 */
7028/*NOTE: TBD NYI */ 7028/*NOTE: TBD NYI */
7029 7029
7030/* The data layout transforms are handled by swapping our own channel data, 7030/* The data layout transforms are handled by swapping our own channel data,
7031 * necessarily these need to happen at the end of the transform list because the 7031 * necessarily these need to happen at the end of the transform list because the
7032 * semantic of the channels changes after these are executed. Some of these, 7032 * semantic of the channels changes after these are executed. Some of these,
7033 * like set_shift and set_packing, can't be done at present because they change 7033 * like set_shift and set_packing, can't be done at present because they change
7034 * the layout of the data at the sub-sample level so sample() won't get the 7034 * the layout of the data at the sub-sample level so sample() won't get the
7035 * right answer. 7035 * right answer.
7036 */ 7036 */
7037/* png_set_invert_alpha */ 7037/* png_set_invert_alpha */
7038/*NOTE: TBD NYI */ 7038/*NOTE: TBD NYI */
7039 7039
7040/* png_set_bgr */ 7040/* png_set_bgr */
7041/*NOTE: TBD NYI */ 7041/*NOTE: TBD NYI */
7042 7042
7043/* png_set_swap_alpha */ 7043/* png_set_swap_alpha */
7044/*NOTE: TBD NYI */ 7044/*NOTE: TBD NYI */
7045 7045
7046/* png_set_swap */ 7046/* png_set_swap */
7047/*NOTE: TBD NYI */ 7047/*NOTE: TBD NYI */
7048 7048
7049/* png_set_filler, (png_structp png_ptr, png_uint_32 filler, int flags)); */ 7049/* png_set_filler, (png_structp png_ptr, png_uint_32 filler, int flags)); */
7050/*NOTE: TBD NYI */ 7050/*NOTE: TBD NYI */
7051 7051
7052/* png_set_add_alpha, (png_structp png_ptr, png_uint_32 filler, int flags)); */ 7052/* png_set_add_alpha, (png_structp png_ptr, png_uint_32 filler, int flags)); */
7053/*NOTE: TBD NYI */ 7053/*NOTE: TBD NYI */
7054 7054
7055/* png_set_packing */ 7055/* png_set_packing */
7056/*NOTE: TBD NYI */ 7056/*NOTE: TBD NYI */
7057 7057
7058/* png_set_packswap */ 7058/* png_set_packswap */
7059/*NOTE: TBD NYI */ 7059/*NOTE: TBD NYI */
7060 7060
7061/* png_set_invert_mono */ 7061/* png_set_invert_mono */
7062/*NOTE: TBD NYI */ 7062/*NOTE: TBD NYI */
7063 7063
7064/* png_set_shift(png_structp, png_const_color_8p true_bits) */ 7064/* png_set_shift(png_structp, png_const_color_8p true_bits) */
7065/*NOTE: TBD NYI */ 7065/*NOTE: TBD NYI */
7066 7066
7067static void 7067static void
7068perform_transform_test(png_modifier *pm) 7068perform_transform_test(png_modifier *pm)
7069{ 7069{
7070 png_byte colour_type = 0; 7070 png_byte colour_type = 0;
7071 png_byte bit_depth = 0; 7071 png_byte bit_depth = 0;
7072 int palette_number = 0; 7072 int palette_number = 0;
7073 7073
7074 while (next_format(&colour_type, &bit_depth, &palette_number)) 7074 while (next_format(&colour_type, &bit_depth, &palette_number))
7075 { 7075 {
7076 png_uint_32 counter = 0; 7076 png_uint_32 counter = 0;
7077 size_t base_pos; 7077 size_t base_pos;
7078 char name[64]; 7078 char name[64];
7079 7079
7080 base_pos = safecat(name, sizeof name, 0, "transform:"); 7080 base_pos = safecat(name, sizeof name, 0, "transform:");
7081 7081
7082 for (;;) 7082 for (;;)
7083 { 7083 {
7084 size_t pos = base_pos; 7084 size_t pos = base_pos;
7085 PNG_CONST image_transform *list = 0; 7085 PNG_CONST image_transform *list = 0;
7086 7086
7087 /* 'max' is currently hardwired to '1'; this should be settable on the 7087 /* 'max' is currently hardwired to '1'; this should be settable on the
7088 * command line. 7088 * command line.
7089 */ 7089 */
7090 counter = image_transform_add(&list, 1/*max*/, counter, 7090 counter = image_transform_add(&list, 1/*max*/, counter,
7091 name, sizeof name, &pos, colour_type, bit_depth); 7091 name, sizeof name, &pos, colour_type, bit_depth);
7092 7092
7093 if (counter == 0) 7093 if (counter == 0)
7094 break; 7094 break;
7095 7095
7096 /* The command line can change this to checking interlaced images. */ 7096 /* The command line can change this to checking interlaced images. */
7097 do 7097 do
7098 { 7098 {
7099 pm->repeat = 0; 7099 pm->repeat = 0;
7100 transform_test(pm, FILEID(colour_type, bit_depth, palette_number, 7100 transform_test(pm, FILEID(colour_type, bit_depth, palette_number,
7101 pm->interlace_type, 0, 0, 0), list, name); 7101 pm->interlace_type, 0, 0, 0), list, name);
7102 7102
7103 if (fail(pm)) 7103 if (fail(pm))
7104 return; 7104 return;
7105 } 7105 }
7106 while (pm->repeat); 7106 while (pm->repeat);
7107 } 7107 }
7108 } 7108 }
7109} 7109}
7110#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ 7110#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
7111 7111
7112/********************************* GAMMA TESTS ********************************/ 7112/********************************* GAMMA TESTS ********************************/
7113#ifdef PNG_READ_GAMMA_SUPPORTED 7113#ifdef PNG_READ_GAMMA_SUPPORTED
7114/* Reader callbacks and implementations, where they differ from the standard 7114/* Reader callbacks and implementations, where they differ from the standard
7115 * ones. 7115 * ones.
7116 */ 7116 */
7117typedef struct gamma_display 7117typedef struct gamma_display
7118{ 7118{
7119 standard_display this; 7119 standard_display this;
7120 7120
7121 /* Parameters */ 7121 /* Parameters */
7122 png_modifier* pm; 7122 png_modifier* pm;
7123 double file_gamma; 7123 double file_gamma;
7124 double screen_gamma; 7124 double screen_gamma;
7125 double background_gamma; 7125 double background_gamma;
7126 png_byte sbit; 7126 png_byte sbit;
7127 int threshold_test; 7127 int threshold_test;
7128 int use_input_precision; 7128 int use_input_precision;
7129 int scale16; 7129 int scale16;
7130 int expand16; 7130 int expand16;
7131 int do_background; 7131 int do_background;
7132 png_color_16 background_color; 7132 png_color_16 background_color;
7133 7133
7134 /* Local variables */ 7134 /* Local variables */
7135 double maxerrout; 7135 double maxerrout;
7136 double maxerrpc; 7136 double maxerrpc;
7137 double maxerrabs; 7137 double maxerrabs;
7138} gamma_display; 7138} gamma_display;
7139 7139
7140#define ALPHA_MODE_OFFSET 4 7140#define ALPHA_MODE_OFFSET 4
7141 7141
7142static void 7142static void
7143gamma_display_init(gamma_display *dp, png_modifier *pm, png_uint_32 id, 7143gamma_display_init(gamma_display *dp, png_modifier *pm, png_uint_32 id,
7144 double file_gamma, double screen_gamma, png_byte sbit, int threshold_test, 7144 double file_gamma, double screen_gamma, png_byte sbit, int threshold_test,
7145 int use_input_precision, int scale16, int expand16, 7145 int use_input_precision, int scale16, int expand16,
7146 int do_background, PNG_CONST png_color_16 *pointer_to_the_background_color, 7146 int do_background, PNG_CONST png_color_16 *pointer_to_the_background_color,
7147 double background_gamma) 7147 double background_gamma)
7148{ 7148{
7149 /* Standard fields */ 7149 /* Standard fields */
7150 standard_display_init(&dp->this, &pm->this, id, 0/*do_interlace*/, 7150 standard_display_init(&dp->this, &pm->this, id, 0/*do_interlace*/,
7151 pm->use_update_info); 7151 pm->use_update_info);
7152 7152
7153 /* Parameter fields */ 7153 /* Parameter fields */
7154 dp->pm = pm; 7154 dp->pm = pm;
7155 dp->file_gamma = file_gamma; 7155 dp->file_gamma = file_gamma;
7156 dp->screen_gamma = screen_gamma; 7156 dp->screen_gamma = screen_gamma;
7157 dp->background_gamma = background_gamma; 7157 dp->background_gamma = background_gamma;
7158 dp->sbit = sbit; 7158 dp->sbit = sbit;
7159 dp->threshold_test = threshold_test; 7159 dp->threshold_test = threshold_test;
7160 dp->use_input_precision = use_input_precision; 7160 dp->use_input_precision = use_input_precision;
7161 dp->scale16 = scale16; 7161 dp->scale16 = scale16;
7162 dp->expand16 = expand16; 7162 dp->expand16 = expand16;
7163 dp->do_background = do_background; 7163 dp->do_background = do_background;
7164 if (do_background && pointer_to_the_background_color != 0) 7164 if (do_background && pointer_to_the_background_color != 0)
7165 dp->background_color = *pointer_to_the_background_color; 7165 dp->background_color = *pointer_to_the_background_color;
7166 else 7166 else
7167 memset(&dp->background_color, 0, sizeof dp->background_color); 7167 memset(&dp->background_color, 0, sizeof dp->background_color);
7168 7168
7169 /* Local variable fields */ 7169 /* Local variable fields */
7170 dp->maxerrout = dp->maxerrpc = dp->maxerrabs = 0; 7170 dp->maxerrout = dp->maxerrpc = dp->maxerrabs = 0;
7171} 7171}
7172 7172
7173static void 7173static void
7174gamma_info_imp(gamma_display *dp, png_structp pp, png_infop pi) 7174gamma_info_imp(gamma_display *dp, png_structp pp, png_infop pi)
7175{ 7175{
7176 /* Reuse the standard stuff as appropriate. */ 7176 /* Reuse the standard stuff as appropriate. */
7177 standard_info_part1(&dp->this, pp, pi); 7177 standard_info_part1(&dp->this, pp, pi);
7178 7178
7179 /* If requested strip 16 to 8 bits - this is handled automagically below 7179 /* If requested strip 16 to 8 bits - this is handled automagically below
7180 * because the output bit depth is read from the library. Note that there 7180 * because the output bit depth is read from the library. Note that there
7181 * are interactions with sBIT but, internally, libpng makes sbit at most 7181 * are interactions with sBIT but, internally, libpng makes sbit at most
7182 * PNG_MAX_GAMMA_8 when doing the following. 7182 * PNG_MAX_GAMMA_8 when doing the following.
7183 */ 7183 */
7184 if (dp->scale16) 7184 if (dp->scale16)
7185# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED 7185# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
7186 png_set_scale_16(pp); 7186 png_set_scale_16(pp);
7187# else 7187# else
7188 /* The following works both in 1.5.4 and earlier versions: */ 7188 /* The following works both in 1.5.4 and earlier versions: */
7189# ifdef PNG_READ_16_TO_8_SUPPORTED 7189# ifdef PNG_READ_16_TO_8_SUPPORTED
7190 png_set_strip_16(pp); 7190 png_set_strip_16(pp);
7191# else 7191# else
7192 png_error(pp, "scale16 (16 to 8 bit conversion) not supported"); 7192 png_error(pp, "scale16 (16 to 8 bit conversion) not supported");
7193# endif 7193# endif
7194# endif 7194# endif
7195 7195
7196 if (dp->expand16) 7196 if (dp->expand16)
7197# ifdef PNG_READ_EXPAND_16_SUPPORTED 7197# ifdef PNG_READ_EXPAND_16_SUPPORTED
7198 png_set_expand_16(pp); 7198 png_set_expand_16(pp);
7199# else 7199# else
7200 png_error(pp, "expand16 (8 to 16 bit conversion) not supported"); 7200 png_error(pp, "expand16 (8 to 16 bit conversion) not supported");
7201# endif 7201# endif
7202 7202
7203 if (dp->do_background >= ALPHA_MODE_OFFSET) 7203 if (dp->do_background >= ALPHA_MODE_OFFSET)
7204 { 7204 {
7205# ifdef PNG_READ_ALPHA_MODE_SUPPORTED 7205# ifdef PNG_READ_ALPHA_MODE_SUPPORTED
7206 { 7206 {
7207 /* This tests the alpha mode handling, if supported. */ 7207 /* This tests the alpha mode handling, if supported. */
7208 int mode = dp->do_background - ALPHA_MODE_OFFSET; 7208 int mode = dp->do_background - ALPHA_MODE_OFFSET;
7209 7209
7210 /* The gamma value is the output gamma, and is in the standard, 7210 /* The gamma value is the output gamma, and is in the standard,
7211 * non-inverted, represenation. It provides a default for the PNG file 7211 * non-inverted, represenation. It provides a default for the PNG file
7212 * gamma, but since the file has a gAMA chunk this does not matter. 7212 * gamma, but since the file has a gAMA chunk this does not matter.
7213 */ 7213 */
7214 PNG_CONST double sg = dp->screen_gamma; 7214 PNG_CONST double sg = dp->screen_gamma;
7215# ifndef PNG_FLOATING_POINT_SUPPORTED 7215# ifndef PNG_FLOATING_POINT_SUPPORTED
7216 PNG_CONST png_fixed_point g = fix(sg); 7216 PNG_CONST png_fixed_point g = fix(sg);
7217# endif 7217# endif
7218 7218
7219# ifdef PNG_FLOATING_POINT_SUPPORTED 7219# ifdef PNG_FLOATING_POINT_SUPPORTED
7220 png_set_alpha_mode(pp, mode, sg); 7220 png_set_alpha_mode(pp, mode, sg);
7221# else 7221# else
7222 png_set_alpha_mode_fixed(pp, mode, g); 7222 png_set_alpha_mode_fixed(pp, mode, g);
7223# endif 7223# endif
7224 7224
7225 /* However, for the standard Porter-Duff algorithm the output defaults 7225 /* However, for the standard Porter-Duff algorithm the output defaults
7226 * to be linear, so if the test requires non-linear output it must be 7226 * to be linear, so if the test requires non-linear output it must be
7227 * corrected here. 7227 * corrected here.
7228 */ 7228 */
7229 if (mode == PNG_ALPHA_STANDARD && sg != 1) 7229 if (mode == PNG_ALPHA_STANDARD && sg != 1)
7230 { 7230 {
7231# ifdef PNG_FLOATING_POINT_SUPPORTED 7231# ifdef PNG_FLOATING_POINT_SUPPORTED
7232 png_set_gamma(pp, sg, dp->file_gamma); 7232 png_set_gamma(pp, sg, dp->file_gamma);
7233# else 7233# else
7234 png_fixed_point f = fix(dp->file_gamma); 7234 png_fixed_point f = fix(dp->file_gamma);
7235 png_set_gamma_fixed(pp, g, f); 7235 png_set_gamma_fixed(pp, g, f);
7236# endif 7236# endif
7237 } 7237 }
7238 } 7238 }
7239# else 7239# else
7240 png_error(pp, "alpha mode handling not supported"); 7240 png_error(pp, "alpha mode handling not supported");
7241# endif 7241# endif
7242 } 7242 }
7243 7243
7244 else 7244 else
7245 { 7245 {
7246 /* Set up gamma processing. */ 7246 /* Set up gamma processing. */
7247# ifdef PNG_FLOATING_POINT_SUPPORTED 7247# ifdef PNG_FLOATING_POINT_SUPPORTED
7248 png_set_gamma(pp, dp->screen_gamma, dp->file_gamma); 7248 png_set_gamma(pp, dp->screen_gamma, dp->file_gamma);
7249# else 7249# else
7250 { 7250 {
7251 png_fixed_point s = fix(dp->screen_gamma); 7251 png_fixed_point s = fix(dp->screen_gamma);
7252 png_fixed_point f = fix(dp->file_gamma); 7252 png_fixed_point f = fix(dp->file_gamma);
7253 png_set_gamma_fixed(pp, s, f); 7253 png_set_gamma_fixed(pp, s, f);
7254 } 7254 }
7255# endif 7255# endif
7256 7256
7257 if (dp->do_background) 7257 if (dp->do_background)
7258 { 7258 {
7259# ifdef PNG_READ_BACKGROUND_SUPPORTED 7259# ifdef PNG_READ_BACKGROUND_SUPPORTED
7260 /* NOTE: this assumes the caller provided the correct background gamma! 7260 /* NOTE: this assumes the caller provided the correct background gamma!
7261 */ 7261 */
7262 PNG_CONST double bg = dp->background_gamma; 7262 PNG_CONST double bg = dp->background_gamma;
7263# ifndef PNG_FLOATING_POINT_SUPPORTED 7263# ifndef PNG_FLOATING_POINT_SUPPORTED
7264 PNG_CONST png_fixed_point g = fix(bg); 7264 PNG_CONST png_fixed_point g = fix(bg);
7265# endif 7265# endif
7266 7266
7267# ifdef PNG_FLOATING_POINT_SUPPORTED 7267# ifdef PNG_FLOATING_POINT_SUPPORTED
7268 png_set_background(pp, &dp->background_color, dp->do_background, 7268 png_set_background(pp, &dp->background_color, dp->do_background,
7269 0/*need_expand*/, bg); 7269 0/*need_expand*/, bg);
7270# else 7270# else
7271 png_set_background_fixed(pp, &dp->background_color, 7271 png_set_background_fixed(pp, &dp->background_color,
7272 dp->do_background, 0/*need_expand*/, g); 7272 dp->do_background, 0/*need_expand*/, g);
7273# endif 7273# endif
7274# else 7274# else
7275 png_error(pp, "png_set_background not supported"); 7275 png_error(pp, "png_set_background not supported");
7276# endif 7276# endif
7277 } 7277 }
7278 } 7278 }
7279 7279
7280 { 7280 {
7281 int i = dp->this.use_update_info; 7281 int i = dp->this.use_update_info;
7282 /* Always do one call, even if use_update_info is 0. */ 7282 /* Always do one call, even if use_update_info is 0. */
7283 do 7283 do
7284 png_read_update_info(pp, pi); 7284 png_read_update_info(pp, pi);
7285 while (--i > 0); 7285 while (--i > 0);
7286 } 7286 }
7287 7287
7288 /* Now we may get a different cbRow: */ 7288 /* Now we may get a different cbRow: */
7289 standard_info_part2(&dp->this, pp, pi, 1 /*images*/); 7289 standard_info_part2(&dp->this, pp, pi, 1 /*images*/);
7290} 7290}
7291 7291
7292static void 7292static void
7293gamma_info(png_structp pp, png_infop pi) 7293gamma_info(png_structp pp, png_infop pi)
7294{ 7294{
7295 gamma_info_imp(voidcast(gamma_display*, png_get_progressive_ptr(pp)), pp, 7295 gamma_info_imp(voidcast(gamma_display*, png_get_progressive_ptr(pp)), pp,
7296 pi); 7296 pi);
7297} 7297}
7298 7298
7299/* Validate a single component value - the routine gets the input and output 7299/* Validate a single component value - the routine gets the input and output
7300 * sample values as unscaled PNG component values along with a cache of all the 7300 * sample values as unscaled PNG component values along with a cache of all the
7301 * information required to validate the values. 7301 * information required to validate the values.
7302 */ 7302 */
7303typedef struct validate_info 7303typedef struct validate_info
7304{ 7304{
7305 png_structp pp; 7305 png_structp pp;
7306 gamma_display *dp; 7306 gamma_display *dp;
7307 png_byte sbit; 7307 png_byte sbit;
7308 int use_input_precision; 7308 int use_input_precision;
7309 int do_background; 7309 int do_background;
7310 int scale16; 7310 int scale16;
7311 unsigned int sbit_max; 7311 unsigned int sbit_max;
7312 unsigned int isbit_shift; 7312 unsigned int isbit_shift;
7313 unsigned int outmax; 7313 unsigned int outmax;
7314 7314
7315 double gamma_correction; /* Overall correction required. */ 7315 double gamma_correction; /* Overall correction required. */
7316 double file_inverse; /* Inverse of file gamma. */ 7316 double file_inverse; /* Inverse of file gamma. */
7317 double screen_gamma; 7317 double screen_gamma;
7318 double screen_inverse; /* Inverse of screen gamma. */ 7318 double screen_inverse; /* Inverse of screen gamma. */
7319 7319
7320 double background_red; /* Linear background value, red or gray. */ 7320 double background_red; /* Linear background value, red or gray. */
7321 double background_green; 7321 double background_green;
7322 double background_blue; 7322 double background_blue;
7323 7323
7324 double maxabs; 7324 double maxabs;
7325 double maxpc; 7325 double maxpc;
7326 double maxcalc; 7326 double maxcalc;
7327 double maxout; 7327 double maxout;
7328 double maxout_total; /* Total including quantization error */ 7328 double maxout_total; /* Total including quantization error */
7329 double outlog; 7329 double outlog;
7330 int outquant; 7330 int outquant;
7331} 7331}
7332validate_info; 7332validate_info;
7333 7333
7334static void 7334static void
7335init_validate_info(validate_info *vi, gamma_display *dp, png_struct *pp, 7335init_validate_info(validate_info *vi, gamma_display *dp, png_struct *pp,
7336 int in_depth, int out_depth) 7336 int in_depth, int out_depth)
7337{ 7337{
7338 PNG_CONST unsigned int outmax = (1U<<out_depth)-1; 7338 PNG_CONST unsigned int outmax = (1U<<out_depth)-1;
7339 7339
7340 vi->pp = pp; 7340 vi->pp = pp;
7341 vi->dp = dp; 7341 vi->dp = dp;
7342 7342
7343 if (dp->sbit > 0 && dp->sbit < in_depth) 7343 if (dp->sbit > 0 && dp->sbit < in_depth)
7344 { 7344 {
7345 vi->sbit = dp->sbit; 7345 vi->sbit = dp->sbit;
7346 vi->isbit_shift = in_depth - dp->sbit; 7346 vi->isbit_shift = in_depth - dp->sbit;
7347 } 7347 }
7348 7348
7349 else 7349 else
7350 { 7350 {
7351 vi->sbit = (png_byte)in_depth; 7351 vi->sbit = (png_byte)in_depth;
7352 vi->isbit_shift = 0; 7352 vi->isbit_shift = 0;
7353 } 7353 }
7354 7354
7355 vi->sbit_max = (1U << vi->sbit)-1; 7355 vi->sbit_max = (1U << vi->sbit)-1;
7356 7356
7357 /* This mimics the libpng threshold test, '0' is used to prevent gamma 7357 /* This mimics the libpng threshold test, '0' is used to prevent gamma
7358 * correction in the validation test. 7358 * correction in the validation test.
7359 */ 7359 */
7360 vi->screen_gamma = dp->screen_gamma; 7360 vi->screen_gamma = dp->screen_gamma;
7361 if (fabs(vi->screen_gamma-1) < PNG_GAMMA_THRESHOLD) 7361 if (fabs(vi->screen_gamma-1) < PNG_GAMMA_THRESHOLD)
7362 vi->screen_gamma = vi->screen_inverse = 0; 7362 vi->screen_gamma = vi->screen_inverse = 0;
7363 else 7363 else
7364 vi->screen_inverse = 1/vi->screen_gamma; 7364 vi->screen_inverse = 1/vi->screen_gamma;
7365 7365
7366 vi->use_input_precision = dp->use_input_precision; 7366 vi->use_input_precision = dp->use_input_precision;
7367 vi->outmax = outmax; 7367 vi->outmax = outmax;
7368 vi->maxabs = abserr(dp->pm, in_depth, out_depth); 7368 vi->maxabs = abserr(dp->pm, in_depth, out_depth);
7369 vi->maxpc = pcerr(dp->pm, in_depth, out_depth); 7369 vi->maxpc = pcerr(dp->pm, in_depth, out_depth);
7370 vi->maxcalc = calcerr(dp->pm, in_depth, out_depth); 7370 vi->maxcalc = calcerr(dp->pm, in_depth, out_depth);
7371 vi->maxout = outerr(dp->pm, in_depth, out_depth); 7371 vi->maxout = outerr(dp->pm, in_depth, out_depth);
7372 vi->outquant = output_quantization_factor(dp->pm, in_depth, out_depth); 7372 vi->outquant = output_quantization_factor(dp->pm, in_depth, out_depth);
7373 vi->maxout_total = vi->maxout + vi->outquant * .5; 7373 vi->maxout_total = vi->maxout + vi->outquant * .5;
7374 vi->outlog = outlog(dp->pm, in_depth, out_depth); 7374 vi->outlog = outlog(dp->pm, in_depth, out_depth);
7375 7375
7376 if ((dp->this.colour_type & PNG_COLOR_MASK_ALPHA) != 0 || 7376 if ((dp->this.colour_type & PNG_COLOR_MASK_ALPHA) != 0 ||
7377 (dp->this.colour_type == 3 && dp->this.is_transparent)) 7377 (dp->this.colour_type == 3 && dp->this.is_transparent))
7378 { 7378 {
7379 vi->do_background = dp->do_background; 7379 vi->do_background = dp->do_background;
7380 7380
7381 if (vi->do_background != 0) 7381 if (vi->do_background != 0)
7382 { 7382 {
7383 PNG_CONST double bg_inverse = 1/dp->background_gamma; 7383 PNG_CONST double bg_inverse = 1/dp->background_gamma;
7384 double r, g, b; 7384 double r, g, b;
7385 7385
7386 /* Caller must at least put the gray value into the red channel */ 7386 /* Caller must at least put the gray value into the red channel */
7387 r = dp->background_color.red; r /= outmax; 7387 r = dp->background_color.red; r /= outmax;
7388 g = dp->background_color.green; g /= outmax; 7388 g = dp->background_color.green; g /= outmax;
7389 b = dp->background_color.blue; b /= outmax; 7389 b = dp->background_color.blue; b /= outmax;
7390 7390
7391# if 0 7391# if 0
7392 /* libpng doesn't do this optimization, if we do pngvalid will fail. 7392 /* libpng doesn't do this optimization, if we do pngvalid will fail.
7393 */ 7393 */
7394 if (fabs(bg_inverse-1) >= PNG_GAMMA_THRESHOLD) 7394 if (fabs(bg_inverse-1) >= PNG_GAMMA_THRESHOLD)
7395# endif 7395# endif
7396 { 7396 {
7397 r = pow(r, bg_inverse); 7397 r = pow(r, bg_inverse);
7398 g = pow(g, bg_inverse); 7398 g = pow(g, bg_inverse);
7399 b = pow(b, bg_inverse); 7399 b = pow(b, bg_inverse);
7400 } 7400 }
7401 7401
7402 vi->background_red = r; 7402 vi->background_red = r;
7403 vi->background_green = g; 7403 vi->background_green = g;
7404 vi->background_blue = b; 7404 vi->background_blue = b;
7405 } 7405 }
7406 } 7406 }
7407 else 7407 else
7408 vi->do_background = 0; 7408 vi->do_background = 0;
7409 7409
7410 if (vi->do_background == 0) 7410 if (vi->do_background == 0)
7411 vi->background_red = vi->background_green = vi->background_blue = 0; 7411 vi->background_red = vi->background_green = vi->background_blue = 0;
7412 7412
7413 vi->gamma_correction = 1/(dp->file_gamma*dp->screen_gamma); 7413 vi->gamma_correction = 1/(dp->file_gamma*dp->screen_gamma);
7414 if (fabs(vi->gamma_correction-1) < PNG_GAMMA_THRESHOLD) 7414 if (fabs(vi->gamma_correction-1) < PNG_GAMMA_THRESHOLD)
7415 vi->gamma_correction = 0; 7415 vi->gamma_correction = 0;
7416 7416
7417 vi->file_inverse = 1/dp->file_gamma; 7417 vi->file_inverse = 1/dp->file_gamma;
7418 if (fabs(vi->file_inverse-1) < PNG_GAMMA_THRESHOLD) 7418 if (fabs(vi->file_inverse-1) < PNG_GAMMA_THRESHOLD)
7419 vi->file_inverse = 0; 7419 vi->file_inverse = 0;
7420 7420
7421 vi->scale16 = dp->scale16; 7421 vi->scale16 = dp->scale16;
7422} 7422}
7423 7423
7424/* This function handles composition of a single non-alpha component. The 7424/* This function handles composition of a single non-alpha component. The
7425 * argument is the input sample value, in the range 0..1, and the alpha value. 7425 * argument is the input sample value, in the range 0..1, and the alpha value.
7426 * The result is the composed, linear, input sample. If alpha is less than zero 7426 * The result is the composed, linear, input sample. If alpha is less than zero
7427 * this is the alpha component and the function should not be called! 7427 * this is the alpha component and the function should not be called!
7428 */ 7428 */
7429static double 7429static double
7430gamma_component_compose(int do_background, double input_sample, double alpha, 7430gamma_component_compose(int do_background, double input_sample, double alpha,
7431 double background, int *compose) 7431 double background, int *compose)
7432{ 7432{
7433 switch (do_background) 7433 switch (do_background)
7434 { 7434 {
7435 case PNG_BACKGROUND_GAMMA_SCREEN: 7435 case PNG_BACKGROUND_GAMMA_SCREEN:
7436 case PNG_BACKGROUND_GAMMA_FILE: 7436 case PNG_BACKGROUND_GAMMA_FILE:
7437 case PNG_BACKGROUND_GAMMA_UNIQUE: 7437 case PNG_BACKGROUND_GAMMA_UNIQUE:
7438 /* Standard PNG background processing. */ 7438 /* Standard PNG background processing. */
7439 if (alpha < 1) 7439 if (alpha < 1)
7440 { 7440 {
7441 if (alpha > 0) 7441 if (alpha > 0)
7442 { 7442 {
7443 input_sample = input_sample * alpha + background * (1-alpha); 7443 input_sample = input_sample * alpha + background * (1-alpha);
7444 if (compose != NULL) 7444 if (compose != NULL)
7445 *compose = 1; 7445 *compose = 1;
7446 } 7446 }
7447 7447
7448 else 7448 else
7449 input_sample = background; 7449 input_sample = background;
7450 } 7450 }
7451 break; 7451 break;
7452 7452
7453#ifdef PNG_READ_ALPHA_MODE_SUPPORTED 7453#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
7454 case ALPHA_MODE_OFFSET + PNG_ALPHA_STANDARD: 7454 case ALPHA_MODE_OFFSET + PNG_ALPHA_STANDARD:
7455 case ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN: 7455 case ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN:
7456 /* The components are premultiplied in either case and the output is 7456 /* The components are premultiplied in either case and the output is
7457 * gamma encoded (to get standard Porter-Duff we expect the output 7457 * gamma encoded (to get standard Porter-Duff we expect the output
7458 * gamma to be set to 1.0!) 7458 * gamma to be set to 1.0!)
7459 */ 7459 */
7460 case ALPHA_MODE_OFFSET + PNG_ALPHA_OPTIMIZED: 7460 case ALPHA_MODE_OFFSET + PNG_ALPHA_OPTIMIZED:
7461 /* The optimization is that the partial-alpha entries are linear 7461 /* The optimization is that the partial-alpha entries are linear
7462 * while the opaque pixels are gamma encoded, but this only affects the 7462 * while the opaque pixels are gamma encoded, but this only affects the
7463 * output encoding. 7463 * output encoding.
7464 */ 7464 */
7465 if (alpha < 1) 7465 if (alpha < 1)
7466 { 7466 {
7467 if (alpha > 0) 7467 if (alpha > 0)
7468 { 7468 {
7469 input_sample *= alpha; 7469 input_sample *= alpha;
7470 if (compose != NULL) 7470 if (compose != NULL)
7471 *compose = 1; 7471 *compose = 1;
7472 } 7472 }
7473 7473
7474 else 7474 else
7475 input_sample = 0; 7475 input_sample = 0;
7476 } 7476 }
7477 break; 7477 break;
7478#endif 7478#endif
7479 7479
7480 default: 7480 default:
7481 /* Standard cases where no compositing is done (so the component 7481 /* Standard cases where no compositing is done (so the component
7482 * value is already correct.) 7482 * value is already correct.)
7483 */ 7483 */
7484 break; 7484 break;
7485 } 7485 }
7486 7486
7487 return input_sample; 7487 return input_sample;
7488} 7488}
7489 7489
7490/* This API returns the encoded *input* component, in the range 0..1 */ 7490/* This API returns the encoded *input* component, in the range 0..1 */
7491static double 7491static double
7492gamma_component_validate(PNG_CONST char *name, PNG_CONST validate_info *vi, 7492gamma_component_validate(PNG_CONST char *name, PNG_CONST validate_info *vi,
7493 PNG_CONST unsigned int id, PNG_CONST unsigned int od, 7493 PNG_CONST unsigned int id, PNG_CONST unsigned int od,
7494 PNG_CONST double alpha /* <0 for the alpha channel itself */, 7494 PNG_CONST double alpha /* <0 for the alpha channel itself */,
7495 PNG_CONST double background /* component background value */) 7495 PNG_CONST double background /* component background value */)
7496{ 7496{
7497 PNG_CONST unsigned int isbit = id >> vi->isbit_shift; 7497 PNG_CONST unsigned int isbit = id >> vi->isbit_shift;
7498 PNG_CONST unsigned int sbit_max = vi->sbit_max; 7498 PNG_CONST unsigned int sbit_max = vi->sbit_max;
7499 PNG_CONST unsigned int outmax = vi->outmax; 7499 PNG_CONST unsigned int outmax = vi->outmax;
7500 PNG_CONST int do_background = vi->do_background; 7500 PNG_CONST int do_background = vi->do_background;
7501 7501
7502 double i; 7502 double i;
7503 7503
7504 /* First check on the 'perfect' result obtained from the digitized input 7504 /* First check on the 'perfect' result obtained from the digitized input
7505 * value, id, and compare this against the actual digitized result, 'od'. 7505 * value, id, and compare this against the actual digitized result, 'od'.
7506 * 'i' is the input result in the range 0..1: 7506 * 'i' is the input result in the range 0..1:
7507 */ 7507 */
7508 i = isbit; i /= sbit_max; 7508 i = isbit; i /= sbit_max;
7509 7509
7510 /* Check for the fast route: if we don't do any background composition or if 7510 /* Check for the fast route: if we don't do any background composition or if
7511 * this is the alpha channel ('alpha' < 0) or if the pixel is opaque then 7511 * this is the alpha channel ('alpha' < 0) or if the pixel is opaque then
7512 * just use the gamma_correction field to correct to the final output gamma. 7512 * just use the gamma_correction field to correct to the final output gamma.
7513 */ 7513 */
7514 if (alpha == 1 /* opaque pixel component */ || !do_background 7514 if (alpha == 1 /* opaque pixel component */ || !do_background
7515#ifdef PNG_READ_ALPHA_MODE_SUPPORTED 7515#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
7516 || do_background == ALPHA_MODE_OFFSET + PNG_ALPHA_PNG 7516 || do_background == ALPHA_MODE_OFFSET + PNG_ALPHA_PNG
7517#endif 7517#endif
7518 || (alpha < 0 /* alpha channel */ 7518 || (alpha < 0 /* alpha channel */
7519#ifdef PNG_READ_ALPHA_MODE_SUPPORTED 7519#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
7520 && do_background != ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN 7520 && do_background != ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN
7521#endif 7521#endif
7522 )) 7522 ))
7523 { 7523 {
7524 /* Then get the gamma corrected version of 'i' and compare to 'od', any 7524 /* Then get the gamma corrected version of 'i' and compare to 'od', any
7525 * error less than .5 is insignificant - just quantization of the output 7525 * error less than .5 is insignificant - just quantization of the output
7526 * value to the nearest digital value (nevertheless the error is still 7526 * value to the nearest digital value (nevertheless the error is still
7527 * recorded - it's interesting ;-) 7527 * recorded - it's interesting ;-)
7528 */ 7528 */
7529 double encoded_sample = i; 7529 double encoded_sample = i;
7530 double encoded_error; 7530 double encoded_error;
7531 7531
7532 /* alpha less than 0 indicates the alpha channel, which is always linear 7532 /* alpha less than 0 indicates the alpha channel, which is always linear
7533 */ 7533 */
7534 if (alpha >= 0 && vi->gamma_correction > 0) 7534 if (alpha >= 0 && vi->gamma_correction > 0)
7535 encoded_sample = pow(encoded_sample, vi->gamma_correction); 7535 encoded_sample = pow(encoded_sample, vi->gamma_correction);
7536 encoded_sample *= outmax; 7536 encoded_sample *= outmax;
7537 7537
7538 encoded_error = fabs(od-encoded_sample); 7538 encoded_error = fabs(od-encoded_sample);
7539 7539
7540 if (encoded_error > vi->dp->maxerrout) 7540 if (encoded_error > vi->dp->maxerrout)
7541 vi->dp->maxerrout = encoded_error; 7541 vi->dp->maxerrout = encoded_error;
7542 7542
7543 if (encoded_error < vi->maxout_total && encoded_error < vi->outlog) 7543 if (encoded_error < vi->maxout_total && encoded_error < vi->outlog)
7544 return i; 7544 return i;
7545 } 7545 }
7546 7546
7547 /* The slow route - attempt to do linear calculations. */ 7547 /* The slow route - attempt to do linear calculations. */
7548 /* There may be an error, or background processing is required, so calculate 7548 /* There may be an error, or background processing is required, so calculate
7549 * the actual sample values - unencoded light intensity values. Note that in 7549 * the actual sample values - unencoded light intensity values. Note that in
7550 * practice these are not completely unencoded because they include a 7550 * practice these are not completely unencoded because they include a
7551 * 'viewing correction' to decrease or (normally) increase the perceptual 7551 * 'viewing correction' to decrease or (normally) increase the perceptual
7552 * contrast of the image. There's nothing we can do about this - we don't 7552 * contrast of the image. There's nothing we can do about this - we don't
7553 * know what it is - so assume the unencoded value is perceptually linear. 7553 * know what it is - so assume the unencoded value is perceptually linear.
7554 */ 7554 */
7555 { 7555 {
7556 double input_sample = i; /* In range 0..1 */ 7556 double input_sample = i; /* In range 0..1 */
7557 double output, error, encoded_sample, encoded_error; 7557 double output, error, encoded_sample, encoded_error;
7558 double es_lo, es_hi; 7558 double es_lo, es_hi;
7559 int compose = 0; /* Set to one if composition done */ 7559 int compose = 0; /* Set to one if composition done */
7560 int output_is_encoded; /* Set if encoded to screen gamma */ 7560 int output_is_encoded; /* Set if encoded to screen gamma */
7561 int log_max_error = 1; /* Check maximum error values */ 7561 int log_max_error = 1; /* Check maximum error values */
7562 png_const_charp pass = 0; /* Reason test passes (or 0 for fail) */ 7562 png_const_charp pass = 0; /* Reason test passes (or 0 for fail) */
7563 7563
7564 /* Convert to linear light (with the above caveat.) The alpha channel is 7564 /* Convert to linear light (with the above caveat.) The alpha channel is
7565 * already linear. 7565 * already linear.
7566 */ 7566 */
7567 if (alpha >= 0) 7567 if (alpha >= 0)
7568 { 7568 {
7569 int tcompose; 7569 int tcompose;
7570 7570
7571 if (vi->file_inverse > 0) 7571 if (vi->file_inverse > 0)
7572 input_sample = pow(input_sample, vi->file_inverse); 7572 input_sample = pow(input_sample, vi->file_inverse);
7573 7573
7574 /* Handle the compose processing: */ 7574 /* Handle the compose processing: */
7575 tcompose = 0; 7575 tcompose = 0;
7576 input_sample = gamma_component_compose(do_background, input_sample, 7576 input_sample = gamma_component_compose(do_background, input_sample,
7577 alpha, background, &tcompose); 7577 alpha, background, &tcompose);
7578 7578
7579 if (tcompose) 7579 if (tcompose)
7580 compose = 1; 7580 compose = 1;
7581 } 7581 }
7582 7582
7583 /* And similarly for the output value, but we need to check the background 7583 /* And similarly for the output value, but we need to check the background
7584 * handling to linearize it correctly. 7584 * handling to linearize it correctly.
7585 */ 7585 */
7586 output = od; 7586 output = od;
7587 output /= outmax; 7587 output /= outmax;
7588 7588
7589 output_is_encoded = vi->screen_gamma > 0; 7589 output_is_encoded = vi->screen_gamma > 0;
7590 7590
7591 if (alpha < 0) /* The alpha channel */ 7591 if (alpha < 0) /* The alpha channel */
7592 { 7592 {
7593#ifdef PNG_READ_ALPHA_MODE_SUPPORTED 7593#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
7594 if (do_background != ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN) 7594 if (do_background != ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN)
7595#endif 7595#endif
7596 { 7596 {
7597 /* In all other cases the output alpha channel is linear already, 7597 /* In all other cases the output alpha channel is linear already,
7598 * don't log errors here, they are much larger in linear data. 7598 * don't log errors here, they are much larger in linear data.
7599 */ 7599 */
7600 output_is_encoded = 0; 7600 output_is_encoded = 0;
7601 log_max_error = 0; 7601 log_max_error = 0;
7602 } 7602 }
7603 } 7603 }
7604 7604
7605#ifdef PNG_READ_ALPHA_MODE_SUPPORTED 7605#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
7606 else /* A component */ 7606 else /* A component */
7607 { 7607 {
7608 if (do_background == ALPHA_MODE_OFFSET + PNG_ALPHA_OPTIMIZED && 7608 if (do_background == ALPHA_MODE_OFFSET + PNG_ALPHA_OPTIMIZED &&
7609 alpha < 1) /* the optimized case - linear output */ 7609 alpha < 1) /* the optimized case - linear output */
7610 { 7610 {
7611 if (alpha > 0) log_max_error = 0; 7611 if (alpha > 0) log_max_error = 0;
7612 output_is_encoded = 0; 7612 output_is_encoded = 0;
7613 } 7613 }
7614 } 7614 }
7615#endif 7615#endif
7616 7616
7617 if (output_is_encoded) 7617 if (output_is_encoded)
7618 output = pow(output, vi->screen_gamma); 7618 output = pow(output, vi->screen_gamma);
7619 7619
7620 /* Calculate (or recalculate) the encoded_sample value and repeat the 7620 /* Calculate (or recalculate) the encoded_sample value and repeat the
7621 * check above (unnecessary if we took the fast route, but harmless.) 7621 * check above (unnecessary if we took the fast route, but harmless.)
7622 */ 7622 */
7623 encoded_sample = input_sample; 7623 encoded_sample = input_sample;
7624 if (output_is_encoded) 7624 if (output_is_encoded)
7625 encoded_sample = pow(encoded_sample, vi->screen_inverse); 7625 encoded_sample = pow(encoded_sample, vi->screen_inverse);
7626 encoded_sample *= outmax; 7626 encoded_sample *= outmax;
7627 7627
7628 encoded_error = fabs(od-encoded_sample); 7628 encoded_error = fabs(od-encoded_sample);
7629 7629
7630 /* Don't log errors in the alpha channel, or the 'optimized' case, 7630 /* Don't log errors in the alpha channel, or the 'optimized' case,
7631 * neither are significant to the overall perception. 7631 * neither are significant to the overall perception.
7632 */ 7632 */
7633 if (log_max_error && encoded_error > vi->dp->maxerrout) 7633 if (log_max_error && encoded_error > vi->dp->maxerrout)
7634 vi->dp->maxerrout = encoded_error; 7634 vi->dp->maxerrout = encoded_error;
7635 7635
7636 if (encoded_error < vi->maxout_total) 7636 if (encoded_error < vi->maxout_total)
7637 { 7637 {
7638 if (encoded_error < vi->outlog) 7638 if (encoded_error < vi->outlog)
7639 return i; 7639 return i;
7640 7640
7641 /* Test passed but error is bigger than the log limit, record why the 7641 /* Test passed but error is bigger than the log limit, record why the
7642 * test passed: 7642 * test passed:
7643 */ 7643 */
7644 pass = "less than maxout:\n"; 7644 pass = "less than maxout:\n";
7645 } 7645 }
7646 7646
7647 /* i: the original input value in the range 0..1 7647 /* i: the original input value in the range 0..1
7648 * 7648 *
7649 * pngvalid calculations: 7649 * pngvalid calculations:
7650 * input_sample: linear result; i linearized and composed, range 0..1 7650 * input_sample: linear result; i linearized and composed, range 0..1
7651 * encoded_sample: encoded result; input_sample scaled to ouput bit depth 7651 * encoded_sample: encoded result; input_sample scaled to ouput bit depth
7652 * 7652 *
7653 * libpng calculations: 7653 * libpng calculations:
7654 * output: linear result; od scaled to 0..1 and linearized 7654 * output: linear result; od scaled to 0..1 and linearized
7655 * od: encoded result from libpng 7655 * od: encoded result from libpng
7656 */ 7656 */
7657 7657
7658 /* Now we have the numbers for real errors, both absolute values as as a 7658 /* Now we have the numbers for real errors, both absolute values as as a
7659 * percentage of the correct value (output): 7659 * percentage of the correct value (output):
7660 */ 7660 */
7661 error = fabs(input_sample-output); 7661 error = fabs(input_sample-output);
7662 7662
7663 if (log_max_error && error > vi->dp->maxerrabs) 7663 if (log_max_error && error > vi->dp->maxerrabs)
7664 vi->dp->maxerrabs = error; 7664 vi->dp->maxerrabs = error;
7665 7665
7666 /* The following is an attempt to ignore the tendency of quantization to 7666 /* The following is an attempt to ignore the tendency of quantization to
7667 * dominate the percentage errors for lower result values: 7667 * dominate the percentage errors for lower result values:
7668 */ 7668 */
7669 if (log_max_error && input_sample > .5) 7669 if (log_max_error && input_sample > .5)
7670 { 7670 {
7671 double percentage_error = error/input_sample; 7671 double percentage_error = error/input_sample;
7672 if (percentage_error > vi->dp->maxerrpc) 7672 if (percentage_error > vi->dp->maxerrpc)
7673 vi->dp->maxerrpc = percentage_error; 7673 vi->dp->maxerrpc = percentage_error;
7674 } 7674 }
7675 7675
7676 /* Now calculate the digitization limits for 'encoded_sample' using the 7676 /* Now calculate the digitization limits for 'encoded_sample' using the
7677 * 'max' values. Note that maxout is in the encoded space but maxpc and 7677 * 'max' values. Note that maxout is in the encoded space but maxpc and
7678 * maxabs are in linear light space. 7678 * maxabs are in linear light space.
7679 * 7679 *
7680 * First find the maximum error in linear light space, range 0..1: 7680 * First find the maximum error in linear light space, range 0..1:
7681 */ 7681 */
7682 { 7682 {
7683 double tmp = input_sample * vi->maxpc; 7683 double tmp = input_sample * vi->maxpc;
7684 if (tmp < vi->maxabs) tmp = vi->maxabs; 7684 if (tmp < vi->maxabs) tmp = vi->maxabs;
7685 /* If 'compose' is true the composition was done in linear space using 7685 /* If 'compose' is true the composition was done in linear space using
7686 * integer arithmetic. This introduces an extra error of +/- 0.5 (at 7686 * integer arithmetic. This introduces an extra error of +/- 0.5 (at
7687 * least) in the integer space used. 'maxcalc' records this, taking 7687 * least) in the integer space used. 'maxcalc' records this, taking
7688 * into account the possibility that even for 16 bit output 8 bit space 7688 * into account the possibility that even for 16 bit output 8 bit space
7689 * may have been used. 7689 * may have been used.
7690 */ 7690 */
7691 if (compose && tmp < vi->maxcalc) tmp = vi->maxcalc; 7691 if (compose && tmp < vi->maxcalc) tmp = vi->maxcalc;
7692 7692
7693 /* The 'maxout' value refers to the encoded result, to compare with 7693 /* The 'maxout' value refers to the encoded result, to compare with
7694 * this encode input_sample adjusted by the maximum error (tmp) above. 7694 * this encode input_sample adjusted by the maximum error (tmp) above.
7695 */ 7695 */
7696 es_lo = encoded_sample - vi->maxout; 7696 es_lo = encoded_sample - vi->maxout;
7697 7697
7698 if (es_lo > 0 && input_sample-tmp > 0) 7698 if (es_lo > 0 && input_sample-tmp > 0)
7699 { 7699 {
7700 double low_value = input_sample-tmp; 7700 double low_value = input_sample-tmp;
7701 if (output_is_encoded) 7701 if (output_is_encoded)
7702 low_value = pow(low_value, vi->screen_inverse); 7702 low_value = pow(low_value, vi->screen_inverse);
7703 low_value *= outmax; 7703 low_value *= outmax;
7704 if (low_value < es_lo) es_lo = low_value; 7704 if (low_value < es_lo) es_lo = low_value;
7705 7705
7706 /* Quantize this appropriately: */ 7706 /* Quantize this appropriately: */
7707 es_lo = ceil(es_lo / vi->outquant - .5) * vi->outquant; 7707 es_lo = ceil(es_lo / vi->outquant - .5) * vi->outquant;
7708 } 7708 }
7709 7709
7710 else 7710 else
7711 es_lo = 0; 7711 es_lo = 0;
7712 7712
7713 es_hi = encoded_sample + vi->maxout; 7713 es_hi = encoded_sample + vi->maxout;
7714 7714
7715 if (es_hi < outmax && input_sample+tmp < 1) 7715 if (es_hi < outmax && input_sample+tmp < 1)
7716 { 7716 {
7717 double high_value = input_sample+tmp; 7717 double high_value = input_sample+tmp;
7718 if (output_is_encoded) 7718 if (output_is_encoded)
7719 high_value = pow(high_value, vi->screen_inverse); 7719 high_value = pow(high_value, vi->screen_inverse);
7720 high_value *= outmax; 7720 high_value *= outmax;
7721 if (high_value > es_hi) es_hi = high_value; 7721 if (high_value > es_hi) es_hi = high_value;
7722 7722
7723 es_hi = floor(es_hi / vi->outquant + .5) * vi->outquant; 7723 es_hi = floor(es_hi / vi->outquant + .5) * vi->outquant;
7724 } 7724 }
7725 7725
7726 else 7726 else
7727 es_hi = outmax; 7727 es_hi = outmax;
7728 } 7728 }
7729 7729
7730 /* The primary test is that the final encoded value returned by the 7730 /* The primary test is that the final encoded value returned by the
7731 * library should be between the two limits (inclusive) that were 7731 * library should be between the two limits (inclusive) that were
7732 * calculated above. 7732 * calculated above.
7733 */ 7733 */
7734 if (od >= es_lo && od <= es_hi) 7734 if (od >= es_lo && od <= es_hi)
7735 { 7735 {
7736 /* The value passes, but we may need to log the information anyway. */ 7736 /* The value passes, but we may need to log the information anyway. */
7737 if (encoded_error < vi->outlog) 7737 if (encoded_error < vi->outlog)
7738 return i; 7738 return i;
7739 7739
7740 if (pass == 0) 7740 if (pass == 0)
7741 pass = "within digitization limits:\n"; 7741 pass = "within digitization limits:\n";
7742 } 7742 }
7743 7743
7744 { 7744 {
7745 /* There has been an error in processing, or we need to log this 7745 /* There has been an error in processing, or we need to log this
7746 * value. 7746 * value.
7747 */ 7747 */
7748 double is_lo, is_hi; 7748 double is_lo, is_hi;
7749 7749
7750 /* pass is set at this point if either of the tests above would have 7750 /* pass is set at this point if either of the tests above would have
7751 * passed. Don't do these additional tests here - just log the 7751 * passed. Don't do these additional tests here - just log the
7752 * original [es_lo..es_hi] values. 7752 * original [es_lo..es_hi] values.
7753 */ 7753 */
7754 if (pass == 0 && vi->use_input_precision) 7754 if (pass == 0 && vi->use_input_precision)
7755 { 7755 {
7756 /* Ok, something is wrong - this actually happens in current libpng 7756 /* Ok, something is wrong - this actually happens in current libpng
7757 * 16-to-8 processing. Assume that the input value (id, adjusted 7757 * 16-to-8 processing. Assume that the input value (id, adjusted
7758 * for sbit) can be anywhere between value-.5 and value+.5 - quite a 7758 * for sbit) can be anywhere between value-.5 and value+.5 - quite a
7759 * large range if sbit is low. 7759 * large range if sbit is low.
7760 */ 7760 */
7761 double tmp = (isbit - .5)/sbit_max; 7761 double tmp = (isbit - .5)/sbit_max;
7762 7762
7763 if (tmp <= 0) 7763 if (tmp <= 0)
7764 tmp = 0; 7764 tmp = 0;
7765 7765
7766 else if (alpha >= 0 && vi->file_inverse > 0 && tmp < 1) 7766 else if (alpha >= 0 && vi->file_inverse > 0 && tmp < 1)
7767 tmp = pow(tmp, vi->file_inverse); 7767 tmp = pow(tmp, vi->file_inverse);
7768 7768
7769 tmp = gamma_component_compose(do_background, tmp, alpha, background, 7769 tmp = gamma_component_compose(do_background, tmp, alpha, background,
7770 NULL); 7770 NULL);
7771 7771
7772 if (output_is_encoded && tmp > 0 && tmp < 1) 7772 if (output_is_encoded && tmp > 0 && tmp < 1)
7773 tmp = pow(tmp, vi->screen_inverse); 7773 tmp = pow(tmp, vi->screen_inverse);
7774 7774
7775 is_lo = ceil(outmax * tmp - vi->maxout_total); 7775 is_lo = ceil(outmax * tmp - vi->maxout_total);
7776 7776
7777 if (is_lo < 0) 7777 if (is_lo < 0)
7778 is_lo = 0; 7778 is_lo = 0;
7779 7779
7780 tmp = (isbit + .5)/sbit_max; 7780 tmp = (isbit + .5)/sbit_max;
7781 7781
7782 if (tmp <= 0) 7782 if (tmp <= 0)
7783 tmp = 0; 7783 tmp = 0;
7784 7784
7785 else if (alpha >= 0 && vi->file_inverse > 0 && tmp < 1) 7785 else if (alpha >= 0 && vi->file_inverse > 0 && tmp < 1)
7786 tmp = pow(tmp, vi->file_inverse); 7786 tmp = pow(tmp, vi->file_inverse);
7787 7787
7788 tmp = gamma_component_compose(do_background, tmp, alpha, background, 7788 tmp = gamma_component_compose(do_background, tmp, alpha, background,
7789 NULL); 7789 NULL);
7790 7790
7791 if (output_is_encoded && tmp > 0 && tmp < 1) 7791 if (output_is_encoded && tmp > 0 && tmp < 1)
7792 tmp = pow(tmp, vi->screen_inverse); 7792 tmp = pow(tmp, vi->screen_inverse);
7793 7793
7794 is_hi = floor(outmax * tmp + vi->maxout_total); 7794 is_hi = floor(outmax * tmp + vi->maxout_total);
7795 7795
7796 if (is_hi > outmax) 7796 if (is_hi > outmax)
7797 is_hi = outmax; 7797 is_hi = outmax;
7798 7798
7799 if (!(od < is_lo || od > is_hi)) 7799 if (!(od < is_lo || od > is_hi))
7800 { 7800 {
7801 if (encoded_error < vi->outlog) 7801 if (encoded_error < vi->outlog)
7802 return i; 7802 return i;
7803 7803
7804 pass = "within input precision limits:\n"; 7804 pass = "within input precision limits:\n";
7805 } 7805 }
7806 7806
7807 /* One last chance. If this is an alpha channel and the 16to8 7807 /* One last chance. If this is an alpha channel and the 16to8
7808 * option has been used and 'inaccurate' scaling is used then the 7808 * option has been used and 'inaccurate' scaling is used then the
7809 * bit reduction is obtained by simply using the top 8 bits of the 7809 * bit reduction is obtained by simply using the top 8 bits of the
7810 * value. 7810 * value.
7811 * 7811 *
7812 * This is only done for older libpng versions when the 'inaccurate' 7812 * This is only done for older libpng versions when the 'inaccurate'
7813 * (chop) method of scaling was used. 7813 * (chop) method of scaling was used.
7814 */ 7814 */
7815# ifndef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED 7815# ifndef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED
7816# if PNG_LIBPNG_VER < 10504 7816# if PNG_LIBPNG_VER < 10504
7817 /* This may be required for other components in the future, 7817 /* This may be required for other components in the future,
7818 * but at present the presence of gamma correction effectively 7818 * but at present the presence of gamma correction effectively
7819 * prevents the errors in the component scaling (I don't quite 7819 * prevents the errors in the component scaling (I don't quite
7820 * understand why, but since it's better this way I care not 7820 * understand why, but since it's better this way I care not
7821 * to ask, JB 20110419.) 7821 * to ask, JB 20110419.)
7822 */ 7822 */
7823 if (pass == 0 && alpha < 0 && vi->scale16 && vi->sbit > 8 && 7823 if (pass == 0 && alpha < 0 && vi->scale16 && vi->sbit > 8 &&
7824 vi->sbit + vi->isbit_shift == 16) 7824 vi->sbit + vi->isbit_shift == 16)
7825 { 7825 {
7826 tmp = ((id >> 8) - .5)/255; 7826 tmp = ((id >> 8) - .5)/255;
7827 7827
7828 if (tmp > 0) 7828 if (tmp > 0)
7829 { 7829 {
7830 is_lo = ceil(outmax * tmp - vi->maxout_total); 7830 is_lo = ceil(outmax * tmp - vi->maxout_total);
7831 if (is_lo < 0) is_lo = 0; 7831 if (is_lo < 0) is_lo = 0;
7832 } 7832 }
7833 7833
7834 else 7834 else
7835 is_lo = 0; 7835 is_lo = 0;
7836 7836
7837 tmp = ((id >> 8) + .5)/255; 7837 tmp = ((id >> 8) + .5)/255;
7838 7838
7839 if (tmp < 1) 7839 if (tmp < 1)
7840 { 7840 {
7841 is_hi = floor(outmax * tmp + vi->maxout_total); 7841 is_hi = floor(outmax * tmp + vi->maxout_total);
7842 if (is_hi > outmax) is_hi = outmax; 7842 if (is_hi > outmax) is_hi = outmax;
7843 } 7843 }
7844 7844
7845 else 7845 else
7846 is_hi = outmax; 7846 is_hi = outmax;
7847 7847
7848 if (!(od < is_lo || od > is_hi)) 7848 if (!(od < is_lo || od > is_hi))
7849 { 7849 {
7850 if (encoded_error < vi->outlog) 7850 if (encoded_error < vi->outlog)
7851 return i; 7851 return i;
7852 7852
7853 pass = "within 8 bit limits:\n"; 7853 pass = "within 8 bit limits:\n";
7854 } 7854 }
7855 } 7855 }
7856# endif 7856# endif
7857# endif 7857# endif
7858 } 7858 }
7859 else /* !use_input_precision */ 7859 else /* !use_input_precision */
7860 is_lo = es_lo, is_hi = es_hi; 7860 is_lo = es_lo, is_hi = es_hi;
7861 7861
7862 /* Attempt to output a meaningful error/warning message: the message 7862 /* Attempt to output a meaningful error/warning message: the message
7863 * output depends on the background/composite operation being performed 7863 * output depends on the background/composite operation being performed
7864 * because this changes what parameters were actually used above. 7864 * because this changes what parameters were actually used above.
7865 */ 7865 */
7866 { 7866 {
7867 size_t pos = 0; 7867 size_t pos = 0;
7868 /* Need either 1/255 or 1/65535 precision here; 3 or 6 decimal 7868 /* Need either 1/255 or 1/65535 precision here; 3 or 6 decimal
7869 * places. Just use outmax to work out which. 7869 * places. Just use outmax to work out which.
7870 */ 7870 */
7871 int precision = (outmax >= 1000 ? 6 : 3); 7871 int precision = (outmax >= 1000 ? 6 : 3);
7872 int use_input=1, use_background=0, do_compose=0; 7872 int use_input=1, use_background=0, do_compose=0;
7873 char msg[256]; 7873 char msg[256];
7874 7874
7875 if (pass != 0) 7875 if (pass != 0)
7876 pos = safecat(msg, sizeof msg, pos, "\n\t"); 7876 pos = safecat(msg, sizeof msg, pos, "\n\t");
7877 7877
7878 /* Set up the various flags, the output_is_encoded flag above 7878 /* Set up the various flags, the output_is_encoded flag above
7879 * is also used below. do_compose is just a double check. 7879 * is also used below. do_compose is just a double check.
7880 */ 7880 */
7881 switch (do_background) 7881 switch (do_background)
7882 { 7882 {
7883 case PNG_BACKGROUND_GAMMA_SCREEN: 7883 case PNG_BACKGROUND_GAMMA_SCREEN:
7884 case PNG_BACKGROUND_GAMMA_FILE: 7884 case PNG_BACKGROUND_GAMMA_FILE:
7885 case PNG_BACKGROUND_GAMMA_UNIQUE: 7885 case PNG_BACKGROUND_GAMMA_UNIQUE:
7886 use_background = (alpha >= 0 && alpha < 1); 7886 use_background = (alpha >= 0 && alpha < 1);
7887 /*FALL THROUGH*/ 7887 /*FALL THROUGH*/
7888# ifdef PNG_READ_ALPHA_MODE_SUPPORTED 7888# ifdef PNG_READ_ALPHA_MODE_SUPPORTED
7889 case ALPHA_MODE_OFFSET + PNG_ALPHA_STANDARD: 7889 case ALPHA_MODE_OFFSET + PNG_ALPHA_STANDARD:
7890 case ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN: 7890 case ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN:
7891 case ALPHA_MODE_OFFSET + PNG_ALPHA_OPTIMIZED: 7891 case ALPHA_MODE_OFFSET + PNG_ALPHA_OPTIMIZED:
7892# endif /* ALPHA_MODE_SUPPORTED */ 7892# endif /* ALPHA_MODE_SUPPORTED */
7893 do_compose = (alpha > 0 && alpha < 1); 7893 do_compose = (alpha > 0 && alpha < 1);
7894 use_input = (alpha != 0); 7894 use_input = (alpha != 0);
7895 break; 7895 break;
7896 7896
7897 default: 7897 default:
7898 break; 7898 break;
7899 } 7899 }
7900 7900
7901 /* Check the 'compose' flag */ 7901 /* Check the 'compose' flag */
7902 if (compose != do_compose) 7902 if (compose != do_compose)
7903 png_error(vi->pp, "internal error (compose)"); 7903 png_error(vi->pp, "internal error (compose)");
7904 7904
7905 /* 'name' is the component name */ 7905 /* 'name' is the component name */
7906 pos = safecat(msg, sizeof msg, pos, name); 7906 pos = safecat(msg, sizeof msg, pos, name);
7907 pos = safecat(msg, sizeof msg, pos, "("); 7907 pos = safecat(msg, sizeof msg, pos, "(");
7908 pos = safecatn(msg, sizeof msg, pos, id); 7908 pos = safecatn(msg, sizeof msg, pos, id);
7909 if (use_input || pass != 0/*logging*/) 7909 if (use_input || pass != 0/*logging*/)
7910 { 7910 {
7911 if (isbit != id) 7911 if (isbit != id)
7912 { 7912 {
7913 /* sBIT has reduced the precision of the input: */ 7913 /* sBIT has reduced the precision of the input: */
7914 pos = safecat(msg, sizeof msg, pos, ", sbit("); 7914 pos = safecat(msg, sizeof msg, pos, ", sbit(");
7915 pos = safecatn(msg, sizeof msg, pos, vi->sbit); 7915 pos = safecatn(msg, sizeof msg, pos, vi->sbit);
7916 pos = safecat(msg, sizeof msg, pos, "): "); 7916 pos = safecat(msg, sizeof msg, pos, "): ");
7917 pos = safecatn(msg, sizeof msg, pos, isbit); 7917 pos = safecatn(msg, sizeof msg, pos, isbit);
7918 } 7918 }
7919 pos = safecat(msg, sizeof msg, pos, "/"); 7919 pos = safecat(msg, sizeof msg, pos, "/");
7920 /* The output is either "id/max" or "id sbit(sbit): isbit/max" */ 7920 /* The output is either "id/max" or "id sbit(sbit): isbit/max" */
7921 pos = safecatn(msg, sizeof msg, pos, vi->sbit_max); 7921 pos = safecatn(msg, sizeof msg, pos, vi->sbit_max);
7922 } 7922 }
7923 pos = safecat(msg, sizeof msg, pos, ")"); 7923 pos = safecat(msg, sizeof msg, pos, ")");
7924 7924
7925 /* A component may have been multiplied (in linear space) by the 7925 /* A component may have been multiplied (in linear space) by the
7926 * alpha value, 'compose' says whether this is relevant. 7926 * alpha value, 'compose' says whether this is relevant.
7927 */ 7927 */
7928 if (compose || pass != 0) 7928 if (compose || pass != 0)
7929 { 7929 {
7930 /* If any form of composition is being done report our 7930 /* If any form of composition is being done report our
7931 * calculated linear value here (the code above doesn't record 7931 * calculated linear value here (the code above doesn't record
7932 * the input value before composition is performed, so what 7932 * the input value before composition is performed, so what
7933 * gets reported is the value after composition.) 7933 * gets reported is the value after composition.)
7934 */ 7934 */
7935 if (use_input || pass != 0) 7935 if (use_input || pass != 0)
7936 { 7936 {
7937 if (vi->file_inverse > 0) 7937 if (vi->file_inverse > 0)
7938 { 7938 {
7939 pos = safecat(msg, sizeof msg, pos, "^"); 7939 pos = safecat(msg, sizeof msg, pos, "^");
7940 pos = safecatd(msg, sizeof msg, pos, vi->file_inverse, 2); 7940 pos = safecatd(msg, sizeof msg, pos, vi->file_inverse, 2);
7941 } 7941 }
7942 7942
7943 else 7943 else
7944 pos = safecat(msg, sizeof msg, pos, "[linear]"); 7944 pos = safecat(msg, sizeof msg, pos, "[linear]");
7945 7945
7946 pos = safecat(msg, sizeof msg, pos, "*(alpha)"); 7946 pos = safecat(msg, sizeof msg, pos, "*(alpha)");
7947 pos = safecatd(msg, sizeof msg, pos, alpha, precision); 7947 pos = safecatd(msg, sizeof msg, pos, alpha, precision);
7948 } 7948 }
7949 7949
7950 /* Now record the *linear* background value if it was used 7950 /* Now record the *linear* background value if it was used
7951 * (this function is not passed the original, non-linear, 7951 * (this function is not passed the original, non-linear,
7952 * value but it is contained in the test name.) 7952 * value but it is contained in the test name.)
7953 */ 7953 */
7954 if (use_background) 7954 if (use_background)
7955 { 7955 {
7956 pos = safecat(msg, sizeof msg, pos, use_input ? "+" : " "); 7956 pos = safecat(msg, sizeof msg, pos, use_input ? "+" : " ");
7957 pos = safecat(msg, sizeof msg, pos, "(background)"); 7957 pos = safecat(msg, sizeof msg, pos, "(background)");
7958 pos = safecatd(msg, sizeof msg, pos, background, precision); 7958 pos = safecatd(msg, sizeof msg, pos, background, precision);
7959 pos = safecat(msg, sizeof msg, pos, "*"); 7959 pos = safecat(msg, sizeof msg, pos, "*");
7960 pos = safecatd(msg, sizeof msg, pos, 1-alpha, precision); 7960 pos = safecatd(msg, sizeof msg, pos, 1-alpha, precision);
7961 } 7961 }
7962 } 7962 }
7963 7963
7964 /* Report the calculated value (input_sample) and the linearized 7964 /* Report the calculated value (input_sample) and the linearized
7965 * libpng value (output) unless this is just a component gamma 7965 * libpng value (output) unless this is just a component gamma
7966 * correction. 7966 * correction.
7967 */ 7967 */
7968 if (compose || alpha < 0 || pass != 0) 7968 if (compose || alpha < 0 || pass != 0)
7969 { 7969 {
7970 pos = safecat(msg, sizeof msg, pos, 7970 pos = safecat(msg, sizeof msg, pos,
7971 pass != 0 ? " =\n\t" : " = "); 7971 pass != 0 ? " =\n\t" : " = ");
7972 pos = safecatd(msg, sizeof msg, pos, input_sample, precision); 7972 pos = safecatd(msg, sizeof msg, pos, input_sample, precision);
7973 pos = safecat(msg, sizeof msg, pos, " (libpng: "); 7973 pos = safecat(msg, sizeof msg, pos, " (libpng: ");
7974 pos = safecatd(msg, sizeof msg, pos, output, precision); 7974 pos = safecatd(msg, sizeof msg, pos, output, precision);
7975 pos = safecat(msg, sizeof msg, pos, ")"); 7975 pos = safecat(msg, sizeof msg, pos, ")");
7976 7976
7977 /* Finally report the output gamma encoding, if any. */ 7977 /* Finally report the output gamma encoding, if any. */
7978 if (output_is_encoded) 7978 if (output_is_encoded)
7979 { 7979 {
7980 pos = safecat(msg, sizeof msg, pos, " ^"); 7980 pos = safecat(msg, sizeof msg, pos, " ^");
7981 pos = safecatd(msg, sizeof msg, pos, vi->screen_inverse, 2); 7981 pos = safecatd(msg, sizeof msg, pos, vi->screen_inverse, 2);
7982 pos = safecat(msg, sizeof msg, pos, "(to screen) ="); 7982 pos = safecat(msg, sizeof msg, pos, "(to screen) =");
7983 } 7983 }
7984 7984
7985 else 7985 else
7986 pos = safecat(msg, sizeof msg, pos, " [screen is linear] ="); 7986 pos = safecat(msg, sizeof msg, pos, " [screen is linear] =");
7987 } 7987 }
7988 7988
7989 if ((!compose && alpha >= 0) || pass != 0) 7989 if ((!compose && alpha >= 0) || pass != 0)
7990 { 7990 {
7991 if (pass != 0) /* logging */ 7991 if (pass != 0) /* logging */
7992 pos = safecat(msg, sizeof msg, pos, "\n\t[overall:"); 7992 pos = safecat(msg, sizeof msg, pos, "\n\t[overall:");
7993 7993
7994 /* This is the non-composition case, the internal linear 7994 /* This is the non-composition case, the internal linear
7995 * values are irrelevant (though the log below will reveal 7995 * values are irrelevant (though the log below will reveal
7996 * them.) Output a much shorter warning/error message and report 7996 * them.) Output a much shorter warning/error message and report
7997 * the overall gamma correction. 7997 * the overall gamma correction.
7998 */ 7998 */
7999 if (vi->gamma_correction > 0) 7999 if (vi->gamma_correction > 0)
8000 { 8000 {
8001 pos = safecat(msg, sizeof msg, pos, " ^"); 8001 pos = safecat(msg, sizeof msg, pos, " ^");
8002 pos = safecatd(msg, sizeof msg, pos, vi->gamma_correction, 2); 8002 pos = safecatd(msg, sizeof msg, pos, vi->gamma_correction, 2);
8003 pos = safecat(msg, sizeof msg, pos, "(gamma correction) ="); 8003 pos = safecat(msg, sizeof msg, pos, "(gamma correction) =");
8004 } 8004 }
8005 8005
8006 else 8006 else
8007 pos = safecat(msg, sizeof msg, pos, 8007 pos = safecat(msg, sizeof msg, pos,
8008 " [no gamma correction] ="); 8008 " [no gamma correction] =");
8009 8009
8010 if (pass != 0) 8010 if (pass != 0)
8011 pos = safecat(msg, sizeof msg, pos, "]"); 8011 pos = safecat(msg, sizeof msg, pos, "]");
8012 } 8012 }
8013 8013
8014 /* This is our calculated encoded_sample which should (but does 8014 /* This is our calculated encoded_sample which should (but does
8015 * not) match od: 8015 * not) match od:
8016 */ 8016 */
8017 pos = safecat(msg, sizeof msg, pos, pass != 0 ? "\n\t" : " "); 8017 pos = safecat(msg, sizeof msg, pos, pass != 0 ? "\n\t" : " ");
8018 pos = safecatd(msg, sizeof msg, pos, is_lo, 1); 8018 pos = safecatd(msg, sizeof msg, pos, is_lo, 1);
8019 pos = safecat(msg, sizeof msg, pos, " < "); 8019 pos = safecat(msg, sizeof msg, pos, " < ");
8020 pos = safecatd(msg, sizeof msg, pos, encoded_sample, 1); 8020 pos = safecatd(msg, sizeof msg, pos, encoded_sample, 1);
8021 pos = safecat(msg, sizeof msg, pos, " (libpng: "); 8021 pos = safecat(msg, sizeof msg, pos, " (libpng: ");
8022 pos = safecatn(msg, sizeof msg, pos, od); 8022 pos = safecatn(msg, sizeof msg, pos, od);
8023 pos = safecat(msg, sizeof msg, pos, ")"); 8023 pos = safecat(msg, sizeof msg, pos, ")");
8024 pos = safecat(msg, sizeof msg, pos, "/"); 8024 pos = safecat(msg, sizeof msg, pos, "/");
8025 pos = safecatn(msg, sizeof msg, pos, outmax); 8025 pos = safecatn(msg, sizeof msg, pos, outmax);
8026 pos = safecat(msg, sizeof msg, pos, " < "); 8026 pos = safecat(msg, sizeof msg, pos, " < ");
8027 pos = safecatd(msg, sizeof msg, pos, is_hi, 1); 8027 pos = safecatd(msg, sizeof msg, pos, is_hi, 1);
8028 8028
8029 if (pass == 0) /* The error condition */ 8029 if (pass == 0) /* The error condition */
8030 { 8030 {
8031# ifdef PNG_WARNINGS_SUPPORTED 8031# ifdef PNG_WARNINGS_SUPPORTED
8032 png_warning(vi->pp, msg); 8032 png_warning(vi->pp, msg);
8033# else 8033# else
8034 store_warning(vi->pp, msg); 8034 store_warning(vi->pp, msg);
8035# endif 8035# endif
8036 } 8036 }
8037 8037
8038 else /* logging this value */ 8038 else /* logging this value */
8039 store_verbose(&vi->dp->pm->this, vi->pp, pass, msg); 8039 store_verbose(&vi->dp->pm->this, vi->pp, pass, msg);
8040 } 8040 }
8041 } 8041 }
8042 } 8042 }
8043 8043
8044 return i; 8044 return i;
8045} 8045}
8046 8046
8047static void 8047static void
8048gamma_image_validate(gamma_display *dp, png_structp pp, png_infop pi) 8048gamma_image_validate(gamma_display *dp, png_structp pp, png_infop pi)
8049{ 8049{
8050 /* Get some constants derived from the input and output file formats: */ 8050 /* Get some constants derived from the input and output file formats: */
8051 PNG_CONST png_store* PNG_CONST ps = dp->this.ps; 8051 PNG_CONST png_store* PNG_CONST ps = dp->this.ps;
8052 PNG_CONST png_byte in_ct = dp->this.colour_type; 8052 PNG_CONST png_byte in_ct = dp->this.colour_type;
8053 PNG_CONST png_byte in_bd = dp->this.bit_depth; 8053 PNG_CONST png_byte in_bd = dp->this.bit_depth;
8054 PNG_CONST png_uint_32 w = dp->this.w; 8054 PNG_CONST png_uint_32 w = dp->this.w;
8055 PNG_CONST png_uint_32 h = dp->this.h; 8055 PNG_CONST png_uint_32 h = dp->this.h;
8056 PNG_CONST size_t cbRow = dp->this.cbRow; 8056 PNG_CONST size_t cbRow = dp->this.cbRow;
8057 PNG_CONST png_byte out_ct = png_get_color_type(pp, pi); 8057 PNG_CONST png_byte out_ct = png_get_color_type(pp, pi);
8058 PNG_CONST png_byte out_bd = png_get_bit_depth(pp, pi); 8058 PNG_CONST png_byte out_bd = png_get_bit_depth(pp, pi);
8059 8059
8060 /* There are three sources of error, firstly the quantization in the 8060 /* There are three sources of error, firstly the quantization in the
8061 * file encoding, determined by sbit and/or the file depth, secondly 8061 * file encoding, determined by sbit and/or the file depth, secondly
8062 * the output (screen) gamma and thirdly the output file encoding. 8062 * the output (screen) gamma and thirdly the output file encoding.
8063 * 8063 *
8064 * Since this API receives the screen and file gamma in double 8064 * Since this API receives the screen and file gamma in double
8065 * precision it is possible to calculate an exact answer given an input 8065 * precision it is possible to calculate an exact answer given an input
8066 * pixel value. Therefore we assume that the *input* value is exact - 8066 * pixel value. Therefore we assume that the *input* value is exact -
8067 * sample/maxsample - calculate the corresponding gamma corrected 8067 * sample/maxsample - calculate the corresponding gamma corrected
8068 * output to the limits of double precision arithmetic and compare with 8068 * output to the limits of double precision arithmetic and compare with
8069 * what libpng returns. 8069 * what libpng returns.
8070 * 8070 *
8071 * Since the library must quantize the output to 8 or 16 bits there is 8071 * Since the library must quantize the output to 8 or 16 bits there is
8072 * a fundamental limit on the accuracy of the output of +/-.5 - this 8072 * a fundamental limit on the accuracy of the output of +/-.5 - this
8073 * quantization limit is included in addition to the other limits 8073 * quantization limit is included in addition to the other limits
8074 * specified by the paramaters to the API. (Effectively, add .5 8074 * specified by the paramaters to the API. (Effectively, add .5
8075 * everywhere.) 8075 * everywhere.)
8076 * 8076 *
8077 * The behavior of the 'sbit' paramter is defined by section 12.5 8077 * The behavior of the 'sbit' paramter is defined by section 12.5
8078 * (sample depth scaling) of the PNG spec. That section forces the 8078 * (sample depth scaling) of the PNG spec. That section forces the
8079 * decoder to assume that the PNG values have been scaled if sBIT is 8079 * decoder to assume that the PNG values have been scaled if sBIT is
8080 * present: 8080 * present:
8081 * 8081 *
8082 * png-sample = floor( input-sample * (max-out/max-in) + .5); 8082 * png-sample = floor( input-sample * (max-out/max-in) + .5);
8083 * 8083 *
8084 * This means that only a subset of the possible PNG values should 8084 * This means that only a subset of the possible PNG values should
8085 * appear in the input. However, the spec allows the encoder to use a 8085 * appear in the input. However, the spec allows the encoder to use a
8086 * variety of approximations to the above and doesn't require any 8086 * variety of approximations to the above and doesn't require any
8087 * restriction of the values produced. 8087 * restriction of the values produced.
8088 * 8088 *
8089 * Nevertheless the spec requires that the upper 'sBIT' bits of the 8089 * Nevertheless the spec requires that the upper 'sBIT' bits of the
8090 * value stored in a PNG file be the original sample bits. 8090 * value stored in a PNG file be the original sample bits.
8091 * Consequently the code below simply scales the top sbit bits by 8091 * Consequently the code below simply scales the top sbit bits by
8092 * (1<<sbit)-1 to obtain an original sample value. 8092 * (1<<sbit)-1 to obtain an original sample value.
8093 * 8093 *
8094 * Because there is limited precision in the input it is arguable that 8094 * Because there is limited precision in the input it is arguable that
8095 * an acceptable result is any valid result from input-.5 to input+.5. 8095 * an acceptable result is any valid result from input-.5 to input+.5.
8096 * The basic tests below do not do this, however if 'use_input_precision' 8096 * The basic tests below do not do this, however if 'use_input_precision'
8097 * is set a subsequent test is performed below. 8097 * is set a subsequent test is performed below.
8098 */ 8098 */
8099 PNG_CONST unsigned int samples_per_pixel = (out_ct & 2U) ? 3U : 1U; 8099 PNG_CONST unsigned int samples_per_pixel = (out_ct & 2U) ? 3U : 1U;
8100 int processing; 8100 int processing;
8101 png_uint_32 y; 8101 png_uint_32 y;
8102 PNG_CONST store_palette_entry *in_palette = dp->this.palette; 8102 PNG_CONST store_palette_entry *in_palette = dp->this.palette;
8103 PNG_CONST int in_is_transparent = dp->this.is_transparent; 8103 PNG_CONST int in_is_transparent = dp->this.is_transparent;
8104 int out_npalette = -1; 8104 int out_npalette = -1;
8105 int out_is_transparent = 0; /* Just refers to the palette case */ 8105 int out_is_transparent = 0; /* Just refers to the palette case */
8106 store_palette out_palette; 8106 store_palette out_palette;
8107 validate_info vi; 8107 validate_info vi;
8108 8108
8109 /* Check for row overwrite errors */ 8109 /* Check for row overwrite errors */
8110 store_image_check(dp->this.ps, pp, 0); 8110 store_image_check(dp->this.ps, pp, 0);
8111 8111
8112 /* Supply the input and output sample depths here - 8 for an indexed image, 8112 /* Supply the input and output sample depths here - 8 for an indexed image,
8113 * otherwise the bit depth. 8113 * otherwise the bit depth.
8114 */ 8114 */
8115 init_validate_info(&vi, dp, pp, in_ct==3?8:in_bd, out_ct==3?8:out_bd); 8115 init_validate_info(&vi, dp, pp, in_ct==3?8:in_bd, out_ct==3?8:out_bd);
8116 8116
8117 processing = (vi.gamma_correction > 0 && !dp->threshold_test) 8117 processing = (vi.gamma_correction > 0 && !dp->threshold_test)
8118 || in_bd != out_bd || in_ct != out_ct || vi.do_background; 8118 || in_bd != out_bd || in_ct != out_ct || vi.do_background;
8119 8119
8120 /* TODO: FIX THIS: MAJOR BUG! If the transformations all happen inside 8120 /* TODO: FIX THIS: MAJOR BUG! If the transformations all happen inside
8121 * the palette there is no way of finding out, because libpng fails to 8121 * the palette there is no way of finding out, because libpng fails to
8122 * update the palette on png_read_update_info. Indeed, libpng doesn't 8122 * update the palette on png_read_update_info. Indeed, libpng doesn't
8123 * even do the required work until much later, when it doesn't have any 8123 * even do the required work until much later, when it doesn't have any
8124 * info pointer. Oops. For the moment 'processing' is turned off if 8124 * info pointer. Oops. For the moment 'processing' is turned off if
8125 * out_ct is palette. 8125 * out_ct is palette.
8126 */ 8126 */
8127 if (in_ct == 3 && out_ct == 3) 8127 if (in_ct == 3 && out_ct == 3)
8128 processing = 0; 8128 processing = 0;
8129 8129
8130 if (processing && out_ct == 3) 8130 if (processing && out_ct == 3)
8131 out_is_transparent = read_palette(out_palette, &out_npalette, pp, pi); 8131 out_is_transparent = read_palette(out_palette, &out_npalette, pp, pi);
8132 8132
8133 for (y=0; y<h; ++y) 8133 for (y=0; y<h; ++y)
8134 { 8134 {
8135 png_const_bytep pRow = store_image_row(ps, pp, 0, y); 8135 png_const_bytep pRow = store_image_row(ps, pp, 0, y);
8136 png_byte std[STANDARD_ROWMAX]; 8136 png_byte std[STANDARD_ROWMAX];
8137 8137
8138 transform_row(pp, std, in_ct, in_bd, y); 8138 transform_row(pp, std, in_ct, in_bd, y);
8139 8139
8140 if (processing) 8140 if (processing)
8141 { 8141 {
8142 unsigned int x; 8142 unsigned int x;
8143 8143
8144 for (x=0; x<w; ++x) 8144 for (x=0; x<w; ++x)
8145 { 8145 {
8146 double alpha = 1; /* serves as a flag value */ 8146 double alpha = 1; /* serves as a flag value */
8147 8147
8148 /* Record the palette index for index images. */ 8148 /* Record the palette index for index images. */
8149 PNG_CONST unsigned int in_index = 8149 PNG_CONST unsigned int in_index =
8150 in_ct == 3 ? sample(std, 3, in_bd, x, 0) : 256; 8150 in_ct == 3 ? sample(std, 3, in_bd, x, 0) : 256;
8151 PNG_CONST unsigned int out_index = 8151 PNG_CONST unsigned int out_index =
8152 out_ct == 3 ? sample(std, 3, out_bd, x, 0) : 256; 8152 out_ct == 3 ? sample(std, 3, out_bd, x, 0) : 256;
8153 8153
8154 /* Handle input alpha - png_set_background will cause the output 8154 /* Handle input alpha - png_set_background will cause the output
8155 * alpha to disappear so there is nothing to check. 8155 * alpha to disappear so there is nothing to check.
8156 */ 8156 */
8157 if ((in_ct & PNG_COLOR_MASK_ALPHA) != 0 || (in_ct == 3 && 8157 if ((in_ct & PNG_COLOR_MASK_ALPHA) != 0 || (in_ct == 3 &&
8158 in_is_transparent)) 8158 in_is_transparent))
8159 { 8159 {
8160 PNG_CONST unsigned int input_alpha = in_ct == 3 ? 8160 PNG_CONST unsigned int input_alpha = in_ct == 3 ?
8161 dp->this.palette[in_index].alpha : 8161 dp->this.palette[in_index].alpha :
8162 sample(std, in_ct, in_bd, x, samples_per_pixel); 8162 sample(std, in_ct, in_bd, x, samples_per_pixel);
8163 8163
8164 unsigned int output_alpha = 65536 /* as a flag value */; 8164 unsigned int output_alpha = 65536 /* as a flag value */;
8165 8165
8166 if (out_ct == 3) 8166 if (out_ct == 3)
8167 { 8167 {
8168 if (out_is_transparent) 8168 if (out_is_transparent)
8169 output_alpha = out_palette[out_index].alpha; 8169 output_alpha = out_palette[out_index].alpha;
8170 } 8170 }
8171 8171
8172 else if ((out_ct & PNG_COLOR_MASK_ALPHA) != 0) 8172 else if ((out_ct & PNG_COLOR_MASK_ALPHA) != 0)
8173 output_alpha = sample(pRow, out_ct, out_bd, x, 8173 output_alpha = sample(pRow, out_ct, out_bd, x,
8174 samples_per_pixel); 8174 samples_per_pixel);
8175 8175
8176 if (output_alpha != 65536) 8176 if (output_alpha != 65536)
8177 alpha = gamma_component_validate("alpha", &vi, input_alpha, 8177 alpha = gamma_component_validate("alpha", &vi, input_alpha,
8178 output_alpha, -1/*alpha*/, 0/*background*/); 8178 output_alpha, -1/*alpha*/, 0/*background*/);
8179 8179
8180 else /* no alpha in output */ 8180 else /* no alpha in output */
8181 { 8181 {
8182 /* This is a copy of the calculation of 'i' above in order to 8182 /* This is a copy of the calculation of 'i' above in order to
8183 * have the alpha value to use in the background calculation. 8183 * have the alpha value to use in the background calculation.
8184 */ 8184 */
8185 alpha = input_alpha >> vi.isbit_shift; 8185 alpha = input_alpha >> vi.isbit_shift;
8186 alpha /= vi.sbit_max; 8186 alpha /= vi.sbit_max;
8187 } 8187 }
8188 } 8188 }
8189 8189
8190 /* Handle grayscale or RGB components. */ 8190 /* Handle grayscale or RGB components. */
8191 if ((in_ct & PNG_COLOR_MASK_COLOR) == 0) /* grayscale */ 8191 if ((in_ct & PNG_COLOR_MASK_COLOR) == 0) /* grayscale */
8192 (void)gamma_component_validate("gray", &vi, 8192 (void)gamma_component_validate("gray", &vi,
8193 sample(std, in_ct, in_bd, x, 0), 8193 sample(std, in_ct, in_bd, x, 0),
8194 sample(pRow, out_ct, out_bd, x, 0), alpha/*component*/, 8194 sample(pRow, out_ct, out_bd, x, 0), alpha/*component*/,
8195 vi.background_red); 8195 vi.background_red);
8196 else /* RGB or palette */ 8196 else /* RGB or palette */
8197 { 8197 {
8198 (void)gamma_component_validate("red", &vi, 8198 (void)gamma_component_validate("red", &vi,
8199 in_ct == 3 ? in_palette[in_index].red : 8199 in_ct == 3 ? in_palette[in_index].red :
8200 sample(std, in_ct, in_bd, x, 0), 8200 sample(std, in_ct, in_bd, x, 0),
8201 out_ct == 3 ? out_palette[out_index].red : 8201 out_ct == 3 ? out_palette[out_index].red :
8202 sample(pRow, out_ct, out_bd, x, 0), 8202 sample(pRow, out_ct, out_bd, x, 0),
8203 alpha/*component*/, vi.background_red); 8203 alpha/*component*/, vi.background_red);
8204 8204
8205 (void)gamma_component_validate("green", &vi, 8205 (void)gamma_component_validate("green", &vi,
8206 in_ct == 3 ? in_palette[in_index].green : 8206 in_ct == 3 ? in_palette[in_index].green :
8207 sample(std, in_ct, in_bd, x, 1), 8207 sample(std, in_ct, in_bd, x, 1),
8208 out_ct == 3 ? out_palette[out_index].green : 8208 out_ct == 3 ? out_palette[out_index].green :
8209 sample(pRow, out_ct, out_bd, x, 1), 8209 sample(pRow, out_ct, out_bd, x, 1),
8210 alpha/*component*/, vi.background_green); 8210 alpha/*component*/, vi.background_green);
8211 8211
8212 (void)gamma_component_validate("blue", &vi, 8212 (void)gamma_component_validate("blue", &vi,
8213 in_ct == 3 ? in_palette[in_index].blue : 8213 in_ct == 3 ? in_palette[in_index].blue :
8214 sample(std, in_ct, in_bd, x, 2), 8214 sample(std, in_ct, in_bd, x, 2),
8215 out_ct == 3 ? out_palette[out_index].blue : 8215 out_ct == 3 ? out_palette[out_index].blue :
8216 sample(pRow, out_ct, out_bd, x, 2), 8216 sample(pRow, out_ct, out_bd, x, 2),
8217 alpha/*component*/, vi.background_blue); 8217 alpha/*component*/, vi.background_blue);
8218 } 8218 }
8219 } 8219 }
8220 } 8220 }
8221 8221
8222 else if (memcmp(std, pRow, cbRow) != 0) 8222 else if (memcmp(std, pRow, cbRow) != 0)
8223 { 8223 {
8224 char msg[64]; 8224 char msg[64];
8225 8225
8226 /* No transform is expected on the threshold tests. */ 8226 /* No transform is expected on the threshold tests. */
8227 sprintf(msg, "gamma: below threshold row %d changed", y); 8227 sprintf(msg, "gamma: below threshold row %d changed", y);
8228 8228
8229 png_error(pp, msg); 8229 png_error(pp, msg);
8230 } 8230 }
8231 } /* row (y) loop */ 8231 } /* row (y) loop */
8232 8232
8233 dp->this.ps->validated = 1; 8233 dp->this.ps->validated = 1;
8234} 8234}
8235 8235
8236static void 8236static void
8237gamma_end(png_structp pp, png_infop pi) 8237gamma_end(png_structp pp, png_infop pi)
8238{ 8238{
8239 gamma_display *dp = voidcast(gamma_display*, png_get_progressive_ptr(pp)); 8239 gamma_display *dp = voidcast(gamma_display*, png_get_progressive_ptr(pp));
8240 8240
8241 if (!dp->this.speed) 8241 if (!dp->this.speed)
8242 gamma_image_validate(dp, pp, pi); 8242 gamma_image_validate(dp, pp, pi);
8243 else 8243 else
8244 dp->this.ps->validated = 1; 8244 dp->this.ps->validated = 1;
8245} 8245}
8246 8246
8247/* A single test run checking a gamma transformation. 8247/* A single test run checking a gamma transformation.
8248 * 8248 *
8249 * maxabs: maximum absolute error as a fraction 8249 * maxabs: maximum absolute error as a fraction
8250 * maxout: maximum output error in the output units 8250 * maxout: maximum output error in the output units
8251 * maxpc: maximum percentage error (as a percentage) 8251 * maxpc: maximum percentage error (as a percentage)
8252 */ 8252 */
8253static void 8253static void
8254gamma_test(png_modifier *pmIn, PNG_CONST png_byte colour_typeIn, 8254gamma_test(png_modifier *pmIn, PNG_CONST png_byte colour_typeIn,
8255 PNG_CONST png_byte bit_depthIn, PNG_CONST int palette_numberIn, 8255 PNG_CONST png_byte bit_depthIn, PNG_CONST int palette_numberIn,
8256 PNG_CONST int interlace_typeIn, 8256 PNG_CONST int interlace_typeIn,
8257 PNG_CONST double file_gammaIn, PNG_CONST double screen_gammaIn, 8257 PNG_CONST double file_gammaIn, PNG_CONST double screen_gammaIn,
8258 PNG_CONST png_byte sbitIn, PNG_CONST int threshold_testIn, 8258 PNG_CONST png_byte sbitIn, PNG_CONST int threshold_testIn,
8259 PNG_CONST char *name, 8259 PNG_CONST char *name,
8260 PNG_CONST int use_input_precisionIn, PNG_CONST int scale16In, 8260 PNG_CONST int use_input_precisionIn, PNG_CONST int scale16In,
8261 PNG_CONST int expand16In, PNG_CONST int do_backgroundIn, 8261 PNG_CONST int expand16In, PNG_CONST int do_backgroundIn,
8262 PNG_CONST png_color_16 *bkgd_colorIn, double bkgd_gammaIn) 8262 PNG_CONST png_color_16 *bkgd_colorIn, double bkgd_gammaIn)
8263{ 8263{
8264 gamma_display d; 8264 gamma_display d;
8265 context(&pmIn->this, fault); 8265 context(&pmIn->this, fault);
8266 8266
8267 gamma_display_init(&d, pmIn, FILEID(colour_typeIn, bit_depthIn, 8267 gamma_display_init(&d, pmIn, FILEID(colour_typeIn, bit_depthIn,
8268 palette_numberIn, interlace_typeIn, 0, 0, 0), 8268 palette_numberIn, interlace_typeIn, 0, 0, 0),
8269 file_gammaIn, screen_gammaIn, sbitIn, 8269 file_gammaIn, screen_gammaIn, sbitIn,
8270 threshold_testIn, use_input_precisionIn, scale16In, 8270 threshold_testIn, use_input_precisionIn, scale16In,
8271 expand16In, do_backgroundIn, bkgd_colorIn, bkgd_gammaIn); 8271 expand16In, do_backgroundIn, bkgd_colorIn, bkgd_gammaIn);
8272 8272
8273 Try 8273 Try
8274 { 8274 {
8275 png_structp pp; 8275 png_structp pp;
8276 png_infop pi; 8276 png_infop pi;
8277 gama_modification gama_mod; 8277 gama_modification gama_mod;
8278 srgb_modification srgb_mod; 8278 srgb_modification srgb_mod;
8279 sbit_modification sbit_mod; 8279 sbit_modification sbit_mod;
8280 8280
8281 /* For the moment don't use the png_modifier support here. */ 8281 /* For the moment don't use the png_modifier support here. */
8282 d.pm->encoding_counter = 0; 8282 d.pm->encoding_counter = 0;
8283 modifier_set_encoding(d.pm); /* Just resets everything */ 8283 modifier_set_encoding(d.pm); /* Just resets everything */
8284 d.pm->current_gamma = d.file_gamma; 8284 d.pm->current_gamma = d.file_gamma;
8285 8285
8286 /* Make an appropriate modifier to set the PNG file gamma to the 8286 /* Make an appropriate modifier to set the PNG file gamma to the
8287 * given gamma value and the sBIT chunk to the given precision. 8287 * given gamma value and the sBIT chunk to the given precision.
8288 */ 8288 */
8289 d.pm->modifications = NULL; 8289 d.pm->modifications = NULL;
8290 gama_modification_init(&gama_mod, d.pm, d.file_gamma); 8290 gama_modification_init(&gama_mod, d.pm, d.file_gamma);
8291 srgb_modification_init(&srgb_mod, d.pm, 127 /*delete*/); 8291 srgb_modification_init(&srgb_mod, d.pm, 127 /*delete*/);
8292 if (d.sbit > 0) 8292 if (d.sbit > 0)
8293 sbit_modification_init(&sbit_mod, d.pm, d.sbit); 8293 sbit_modification_init(&sbit_mod, d.pm, d.sbit);
8294 8294
8295 modification_reset(d.pm->modifications); 8295 modification_reset(d.pm->modifications);
8296 8296
8297 /* Get a png_struct for writing the image. */ 8297 /* Get a png_struct for writing the image. */
8298 pp = set_modifier_for_read(d.pm, &pi, d.this.id, name); 8298 pp = set_modifier_for_read(d.pm, &pi, d.this.id, name);
8299 standard_palette_init(&d.this); 8299 standard_palette_init(&d.this);
8300 8300
8301 /* Introduce the correct read function. */ 8301 /* Introduce the correct read function. */
8302 if (d.pm->this.progressive) 8302 if (d.pm->this.progressive)
8303 { 8303 {
8304 /* Share the row function with the standard implementation. */ 8304 /* Share the row function with the standard implementation. */
8305 png_set_progressive_read_fn(pp, &d, gamma_info, progressive_row, 8305 png_set_progressive_read_fn(pp, &d, gamma_info, progressive_row,
8306 gamma_end); 8306 gamma_end);
8307 8307
8308 /* Now feed data into the reader until we reach the end: */ 8308 /* Now feed data into the reader until we reach the end: */
8309 modifier_progressive_read(d.pm, pp, pi); 8309 modifier_progressive_read(d.pm, pp, pi);
8310 } 8310 }
8311 else 8311 else
8312 { 8312 {
8313 /* modifier_read expects a png_modifier* */ 8313 /* modifier_read expects a png_modifier* */
8314 png_set_read_fn(pp, d.pm, modifier_read); 8314 png_set_read_fn(pp, d.pm, modifier_read);
8315 8315
8316 /* Check the header values: */ 8316 /* Check the header values: */
8317 png_read_info(pp, pi); 8317 png_read_info(pp, pi);
8318 8318
8319 /* Process the 'info' requirements. Only one image is generated */ 8319 /* Process the 'info' requirements. Only one image is generated */
8320 gamma_info_imp(&d, pp, pi); 8320 gamma_info_imp(&d, pp, pi);
8321 8321
8322 sequential_row(&d.this, pp, pi, -1, 0); 8322 sequential_row(&d.this, pp, pi, -1, 0);
8323 8323
8324 if (!d.this.speed) 8324 if (!d.this.speed)
8325 gamma_image_validate(&d, pp, pi); 8325 gamma_image_validate(&d, pp, pi);
8326 else 8326 else
8327 d.this.ps->validated = 1; 8327 d.this.ps->validated = 1;
8328 } 8328 }
8329 8329
8330 modifier_reset(d.pm); 8330 modifier_reset(d.pm);
8331 8331
8332 if (d.pm->log && !d.threshold_test && !d.this.speed) 8332 if (d.pm->log && !d.threshold_test && !d.this.speed)
8333 fprintf(stderr, "%d bit %s %s: max error %f (%.2g, %2g%%)\n", 8333 fprintf(stderr, "%d bit %s %s: max error %f (%.2g, %2g%%)\n",
8334 d.this.bit_depth, colour_types[d.this.colour_type], name, 8334 d.this.bit_depth, colour_types[d.this.colour_type], name,
8335 d.maxerrout, d.maxerrabs, 100*d.maxerrpc); 8335 d.maxerrout, d.maxerrabs, 100*d.maxerrpc);
8336 8336
8337 /* Log the summary values too. */ 8337 /* Log the summary values too. */
8338 if (d.this.colour_type == 0 || d.this.colour_type == 4) 8338 if (d.this.colour_type == 0 || d.this.colour_type == 4)
8339 { 8339 {
8340 switch (d.this.bit_depth) 8340 switch (d.this.bit_depth)
8341 { 8341 {
8342 case 1: 8342 case 1:
8343 break; 8343 break;
8344 8344
8345 case 2: 8345 case 2:
8346 if (d.maxerrout > d.pm->error_gray_2) 8346 if (d.maxerrout > d.pm->error_gray_2)
8347 d.pm->error_gray_2 = d.maxerrout; 8347 d.pm->error_gray_2 = d.maxerrout;
8348 8348
8349 break; 8349 break;
8350 8350
8351 case 4: 8351 case 4:
8352 if (d.maxerrout > d.pm->error_gray_4) 8352 if (d.maxerrout > d.pm->error_gray_4)
8353 d.pm->error_gray_4 = d.maxerrout; 8353 d.pm->error_gray_4 = d.maxerrout;
8354 8354
8355 break; 8355 break;
8356 8356
8357 case 8: 8357 case 8:
8358 if (d.maxerrout > d.pm->error_gray_8) 8358 if (d.maxerrout > d.pm->error_gray_8)
8359 d.pm->error_gray_8 = d.maxerrout; 8359 d.pm->error_gray_8 = d.maxerrout;
8360 8360
8361 break; 8361 break;
8362 8362
8363 case 16: 8363 case 16:
8364 if (d.maxerrout > d.pm->error_gray_16) 8364 if (d.maxerrout > d.pm->error_gray_16)
8365 d.pm->error_gray_16 = d.maxerrout; 8365 d.pm->error_gray_16 = d.maxerrout;
8366 8366
8367 break; 8367 break;
8368 8368
8369 default: 8369 default:
8370 png_error(pp, "bad bit depth (internal: 1)"); 8370 png_error(pp, "bad bit depth (internal: 1)");
8371 } 8371 }
8372 } 8372 }
8373 8373
8374 else if (d.this.colour_type == 2 || d.this.colour_type == 6) 8374 else if (d.this.colour_type == 2 || d.this.colour_type == 6)
8375 { 8375 {
8376 switch (d.this.bit_depth) 8376 switch (d.this.bit_depth)
8377 { 8377 {
8378 case 8: 8378 case 8:
8379 8379
8380 if (d.maxerrout > d.pm->error_color_8) 8380 if (d.maxerrout > d.pm->error_color_8)
8381 d.pm->error_color_8 = d.maxerrout; 8381 d.pm->error_color_8 = d.maxerrout;
8382 8382
8383 break; 8383 break;
8384 8384
8385 case 16: 8385 case 16:
8386 8386
8387 if (d.maxerrout > d.pm->error_color_16) 8387 if (d.maxerrout > d.pm->error_color_16)
8388 d.pm->error_color_16 = d.maxerrout; 8388 d.pm->error_color_16 = d.maxerrout;
8389 8389
8390 break; 8390 break;
8391 8391
8392 default: 8392 default:
8393 png_error(pp, "bad bit depth (internal: 2)"); 8393 png_error(pp, "bad bit depth (internal: 2)");
8394 } 8394 }
8395 } 8395 }
8396 8396
8397 else if (d.this.colour_type == 3) 8397 else if (d.this.colour_type == 3)
8398 { 8398 {
8399 if (d.maxerrout > d.pm->error_indexed) 8399 if (d.maxerrout > d.pm->error_indexed)
8400 d.pm->error_indexed = d.maxerrout; 8400 d.pm->error_indexed = d.maxerrout;
8401 } 8401 }
8402 } 8402 }
8403 8403
8404 Catch(fault) 8404 Catch(fault)
8405 modifier_reset((png_modifier*)fault); 8405 modifier_reset((png_modifier*)fault);
8406} 8406}
8407 8407
8408static void gamma_threshold_test(png_modifier *pm, png_byte colour_type, 8408static void gamma_threshold_test(png_modifier *pm, png_byte colour_type,
8409 png_byte bit_depth, int interlace_type, double file_gamma, 8409 png_byte bit_depth, int interlace_type, double file_gamma,
8410 double screen_gamma) 8410 double screen_gamma)
8411{ 8411{
8412 size_t pos = 0; 8412 size_t pos = 0;
8413 char name[64]; 8413 char name[64];
8414 pos = safecat(name, sizeof name, pos, "threshold "); 8414 pos = safecat(name, sizeof name, pos, "threshold ");
8415 pos = safecatd(name, sizeof name, pos, file_gamma, 3); 8415 pos = safecatd(name, sizeof name, pos, file_gamma, 3);
8416 pos = safecat(name, sizeof name, pos, "/"); 8416 pos = safecat(name, sizeof name, pos, "/");
8417 pos = safecatd(name, sizeof name, pos, screen_gamma, 3); 8417 pos = safecatd(name, sizeof name, pos, screen_gamma, 3);
8418 8418
8419 (void)gamma_test(pm, colour_type, bit_depth, 0/*palette*/, interlace_type, 8419 (void)gamma_test(pm, colour_type, bit_depth, 0/*palette*/, interlace_type,
8420 file_gamma, screen_gamma, 0/*sBIT*/, 1/*threshold test*/, name, 8420 file_gamma, screen_gamma, 0/*sBIT*/, 1/*threshold test*/, name,
8421 0 /*no input precision*/, 8421 0 /*no input precision*/,
8422 0 /*no scale16*/, 0 /*no expand16*/, 0 /*no background*/, 0 /*hence*/, 8422 0 /*no scale16*/, 0 /*no expand16*/, 0 /*no background*/, 0 /*hence*/,
8423 0 /*no background gamma*/); 8423 0 /*no background gamma*/);
8424} 8424}
8425 8425
8426static void 8426static void
8427perform_gamma_threshold_tests(png_modifier *pm) 8427perform_gamma_threshold_tests(png_modifier *pm)
8428{ 8428{
8429 png_byte colour_type = 0; 8429 png_byte colour_type = 0;
8430 png_byte bit_depth = 0; 8430 png_byte bit_depth = 0;
8431 int palette_number = 0; 8431 int palette_number = 0;
8432 8432
8433 /* Don't test more than one instance of each palette - it's pointless, in 8433 /* Don't test more than one instance of each palette - it's pointless, in
8434 * fact this test is somewhat excessive since libpng doesn't make this 8434 * fact this test is somewhat excessive since libpng doesn't make this
8435 * decision based on colour type or bit depth! 8435 * decision based on colour type or bit depth!
8436 */ 8436 */
8437 while (next_format(&colour_type, &bit_depth, &palette_number)) 8437 while (next_format(&colour_type, &bit_depth, &palette_number))
8438 if (palette_number == 0) 8438 if (palette_number == 0)
8439 { 8439 {
8440 double test_gamma = 1.0; 8440 double test_gamma = 1.0;
8441 while (test_gamma >= .4) 8441 while (test_gamma >= .4)
8442 { 8442 {
8443 /* There's little point testing the interlacing vs non-interlacing, 8443 /* There's little point testing the interlacing vs non-interlacing,
8444 * but this can be set from the command line. 8444 * but this can be set from the command line.
8445 */ 8445 */
8446 gamma_threshold_test(pm, colour_type, bit_depth, pm->interlace_type, 8446 gamma_threshold_test(pm, colour_type, bit_depth, pm->interlace_type,
8447 test_gamma, 1/test_gamma); 8447 test_gamma, 1/test_gamma);
8448 test_gamma *= .95; 8448 test_gamma *= .95;
8449 } 8449 }
8450 8450
8451 /* And a special test for sRGB */ 8451 /* And a special test for sRGB */
8452 gamma_threshold_test(pm, colour_type, bit_depth, pm->interlace_type, 8452 gamma_threshold_test(pm, colour_type, bit_depth, pm->interlace_type,
8453 .45455, 2.2); 8453 .45455, 2.2);
8454 8454
8455 if (fail(pm)) 8455 if (fail(pm))
8456 return; 8456 return;
8457 } 8457 }
8458} 8458}
8459 8459
8460static void gamma_transform_test(png_modifier *pm, 8460static void gamma_transform_test(png_modifier *pm,
8461 PNG_CONST png_byte colour_type, PNG_CONST png_byte bit_depth, 8461 PNG_CONST png_byte colour_type, PNG_CONST png_byte bit_depth,
8462 PNG_CONST int palette_number, 8462 PNG_CONST int palette_number,
8463 PNG_CONST int interlace_type, PNG_CONST double file_gamma, 8463 PNG_CONST int interlace_type, PNG_CONST double file_gamma,
8464 PNG_CONST double screen_gamma, PNG_CONST png_byte sbit, 8464 PNG_CONST double screen_gamma, PNG_CONST png_byte sbit,
8465 PNG_CONST int use_input_precision, PNG_CONST int scale16) 8465 PNG_CONST int use_input_precision, PNG_CONST int scale16)
8466{ 8466{
8467 size_t pos = 0; 8467 size_t pos = 0;
8468 char name[64]; 8468 char name[64];
8469 8469
8470 if (sbit != bit_depth && sbit != 0) 8470 if (sbit != bit_depth && sbit != 0)
8471 { 8471 {
8472 pos = safecat(name, sizeof name, pos, "sbit("); 8472 pos = safecat(name, sizeof name, pos, "sbit(");
8473 pos = safecatn(name, sizeof name, pos, sbit); 8473 pos = safecatn(name, sizeof name, pos, sbit);
8474 pos = safecat(name, sizeof name, pos, ") "); 8474 pos = safecat(name, sizeof name, pos, ") ");
8475 } 8475 }
8476 8476
8477 else 8477 else
8478 pos = safecat(name, sizeof name, pos, "gamma "); 8478 pos = safecat(name, sizeof name, pos, "gamma ");
8479 8479
8480 if (scale16) 8480 if (scale16)
8481 pos = safecat(name, sizeof name, pos, "16to8 "); 8481 pos = safecat(name, sizeof name, pos, "16to8 ");
8482 8482
8483 pos = safecatd(name, sizeof name, pos, file_gamma, 3); 8483 pos = safecatd(name, sizeof name, pos, file_gamma, 3);
8484 pos = safecat(name, sizeof name, pos, "->"); 8484 pos = safecat(name, sizeof name, pos, "->");
8485 pos = safecatd(name, sizeof name, pos, screen_gamma, 3); 8485 pos = safecatd(name, sizeof name, pos, screen_gamma, 3);
8486 8486
8487 gamma_test(pm, colour_type, bit_depth, palette_number, interlace_type, 8487 gamma_test(pm, colour_type, bit_depth, palette_number, interlace_type,
8488 file_gamma, screen_gamma, sbit, 0, name, use_input_precision, 8488 file_gamma, screen_gamma, sbit, 0, name, use_input_precision,
8489 scale16, pm->test_gamma_expand16, 0 , 0, 0); 8489 scale16, pm->test_gamma_expand16, 0 , 0, 0);
8490} 8490}
8491 8491
8492static void perform_gamma_transform_tests(png_modifier *pm) 8492static void perform_gamma_transform_tests(png_modifier *pm)
8493{ 8493{
8494 png_byte colour_type = 0; 8494 png_byte colour_type = 0;
8495 png_byte bit_depth = 0; 8495 png_byte bit_depth = 0;
8496 int palette_number = 0; 8496 int palette_number = 0;
8497 8497
8498 while (next_format(&colour_type, &bit_depth, &palette_number)) 8498 while (next_format(&colour_type, &bit_depth, &palette_number))
8499 { 8499 {
8500 unsigned int i, j; 8500 unsigned int i, j;
8501 8501
8502 for (i=0; i<pm->ngamma_tests; ++i) for (j=0; j<pm->ngamma_tests; ++j) 8502 for (i=0; i<pm->ngamma_tests; ++i) for (j=0; j<pm->ngamma_tests; ++j)
8503 if (i != j) 8503 if (i != j)
8504 { 8504 {
8505 gamma_transform_test(pm, colour_type, bit_depth, palette_number, 8505 gamma_transform_test(pm, colour_type, bit_depth, palette_number,
8506 pm->interlace_type, 1/pm->gammas[i], pm->gammas[j], 0/*sBIT*/, 8506 pm->interlace_type, 1/pm->gammas[i], pm->gammas[j], 0/*sBIT*/,
8507 pm->use_input_precision, 0 /*do not scale16*/); 8507 pm->use_input_precision, 0 /*do not scale16*/);
8508 8508
8509 if (fail(pm)) 8509 if (fail(pm))
8510 return; 8510 return;
8511 } 8511 }
8512 } 8512 }
8513} 8513}
8514 8514
8515static void perform_gamma_sbit_tests(png_modifier *pm) 8515static void perform_gamma_sbit_tests(png_modifier *pm)
8516{ 8516{
8517 png_byte sbit; 8517 png_byte sbit;
8518 8518
8519 /* The only interesting cases are colour and grayscale, alpha is ignored here 8519 /* The only interesting cases are colour and grayscale, alpha is ignored here
8520 * for overall speed. Only bit depths where sbit is less than the bit depth 8520 * for overall speed. Only bit depths where sbit is less than the bit depth
8521 * are tested. 8521 * are tested.
8522 */ 8522 */
8523 for (sbit=pm->sbitlow; sbit<(1<<READ_BDHI); ++sbit) 8523 for (sbit=pm->sbitlow; sbit<(1<<READ_BDHI); ++sbit)
8524 { 8524 {
8525 png_byte colour_type, bit_depth; 8525 png_byte colour_type, bit_depth;
8526 int npalette; 8526 int npalette;
8527 8527
8528 colour_type = bit_depth = 0; 8528 colour_type = bit_depth = 0;
8529 npalette = 0; 8529 npalette = 0;
8530 8530
8531 while (next_format(&colour_type, &bit_depth, &npalette)) 8531 while (next_format(&colour_type, &bit_depth, &npalette))
8532 if ((colour_type & PNG_COLOR_MASK_ALPHA) == 0 && 8532 if ((colour_type & PNG_COLOR_MASK_ALPHA) == 0 &&
8533 ((colour_type == 3 && sbit < 8) || 8533 ((colour_type == 3 && sbit < 8) ||
8534 (colour_type != 3 && sbit < bit_depth))) 8534 (colour_type != 3 && sbit < bit_depth)))
8535 { 8535 {
8536 unsigned int i; 8536 unsigned int i;
8537 8537
8538 for (i=0; i<pm->ngamma_tests; ++i) 8538 for (i=0; i<pm->ngamma_tests; ++i)
8539 { 8539 {
8540 unsigned int j; 8540 unsigned int j;
8541 8541
8542 for (j=0; j<pm->ngamma_tests; ++j) if (i != j) 8542 for (j=0; j<pm->ngamma_tests; ++j) if (i != j)
8543 { 8543 {
8544 gamma_transform_test(pm, colour_type, bit_depth, npalette, 8544 gamma_transform_test(pm, colour_type, bit_depth, npalette,
8545 pm->interlace_type, 1/pm->gammas[i], pm->gammas[j], 8545 pm->interlace_type, 1/pm->gammas[i], pm->gammas[j],
8546 sbit, pm->use_input_precision_sbit, 0 /*scale16*/); 8546 sbit, pm->use_input_precision_sbit, 0 /*scale16*/);
8547 8547
8548 if (fail(pm)) 8548 if (fail(pm))
8549 return; 8549 return;
8550 } 8550 }
8551 } 8551 }
8552 } 8552 }
8553 } 8553 }
8554} 8554}
8555 8555
8556/* Note that this requires a 16 bit source image but produces 8 bit output, so 8556/* Note that this requires a 16 bit source image but produces 8 bit output, so
8557 * we only need the 16bit write support, but the 16 bit images are only 8557 * we only need the 16bit write support, but the 16 bit images are only
8558 * generated if DO_16BIT is defined. 8558 * generated if DO_16BIT is defined.
8559 */ 8559 */
8560#ifdef DO_16BIT 8560#ifdef DO_16BIT
8561static void perform_gamma_scale16_tests(png_modifier *pm) 8561static void perform_gamma_scale16_tests(png_modifier *pm)
8562{ 8562{
8563# ifndef PNG_MAX_GAMMA_8 8563# ifndef PNG_MAX_GAMMA_8
8564# define PNG_MAX_GAMMA_8 11 8564# define PNG_MAX_GAMMA_8 11
8565# endif 8565# endif
8566 /* Include the alpha cases here. Note that sbit matches the internal value 8566 /* Include the alpha cases here. Note that sbit matches the internal value
8567 * used by the library - otherwise we will get spurious errors from the 8567 * used by the library - otherwise we will get spurious errors from the
8568 * internal sbit style approximation. 8568 * internal sbit style approximation.
8569 * 8569 *
8570 * The threshold test is here because otherwise the 16 to 8 conversion will 8570 * The threshold test is here because otherwise the 16 to 8 conversion will
8571 * proceed *without* gamma correction, and the tests above will fail (but not 8571 * proceed *without* gamma correction, and the tests above will fail (but not
8572 * by much) - this could be fixed, it only appears with the -g option. 8572 * by much) - this could be fixed, it only appears with the -g option.
8573 */ 8573 */
8574 unsigned int i, j; 8574 unsigned int i, j;
8575 for (i=0; i<pm->ngamma_tests; ++i) 8575 for (i=0; i<pm->ngamma_tests; ++i)
8576 { 8576 {
8577 for (j=0; j<pm->ngamma_tests; ++j) 8577 for (j=0; j<pm->ngamma_tests; ++j)
8578 { 8578 {
8579 if (i != j && 8579 if (i != j &&
8580 fabs(pm->gammas[j]/pm->gammas[i]-1) >= PNG_GAMMA_THRESHOLD) 8580 fabs(pm->gammas[j]/pm->gammas[i]-1) >= PNG_GAMMA_THRESHOLD)
8581 { 8581 {
8582 gamma_transform_test(pm, 0, 16, 0, pm->interlace_type, 8582 gamma_transform_test(pm, 0, 16, 0, pm->interlace_type,
8583 1/pm->gammas[i], pm->gammas[j], PNG_MAX_GAMMA_8, 8583 1/pm->gammas[i], pm->gammas[j], PNG_MAX_GAMMA_8,
8584 pm->use_input_precision_16to8, 1 /*scale16*/); 8584 pm->use_input_precision_16to8, 1 /*scale16*/);
8585 8585
8586 if (fail(pm)) 8586 if (fail(pm))
8587 return; 8587 return;
8588 8588
8589 gamma_transform_test(pm, 2, 16, 0, pm->interlace_type, 8589 gamma_transform_test(pm, 2, 16, 0, pm->interlace_type,
8590 1/pm->gammas[i], pm->gammas[j], PNG_MAX_GAMMA_8, 8590 1/pm->gammas[i], pm->gammas[j], PNG_MAX_GAMMA_8,
8591 pm->use_input_precision_16to8, 1 /*scale16*/); 8591 pm->use_input_precision_16to8, 1 /*scale16*/);
8592 8592
8593 if (fail(pm)) 8593 if (fail(pm))
8594 return; 8594 return;
8595 8595
8596 gamma_transform_test(pm, 4, 16, 0, pm->interlace_type, 8596 gamma_transform_test(pm, 4, 16, 0, pm->interlace_type,
8597 1/pm->gammas[i], pm->gammas[j], PNG_MAX_GAMMA_8, 8597 1/pm->gammas[i], pm->gammas[j], PNG_MAX_GAMMA_8,
8598 pm->use_input_precision_16to8, 1 /*scale16*/); 8598 pm->use_input_precision_16to8, 1 /*scale16*/);
8599 8599
8600 if (fail(pm)) 8600 if (fail(pm))
8601 return; 8601 return;
8602 8602
8603 gamma_transform_test(pm, 6, 16, 0, pm->interlace_type, 8603 gamma_transform_test(pm, 6, 16, 0, pm->interlace_type,
8604 1/pm->gammas[i], pm->gammas[j], PNG_MAX_GAMMA_8, 8604 1/pm->gammas[i], pm->gammas[j], PNG_MAX_GAMMA_8,
8605 pm->use_input_precision_16to8, 1 /*scale16*/); 8605 pm->use_input_precision_16to8, 1 /*scale16*/);
8606 8606
8607 if (fail(pm)) 8607 if (fail(pm))
8608 return; 8608 return;
8609 } 8609 }
8610 } 8610 }
8611 } 8611 }
8612} 8612}
8613#endif /* 16 to 8 bit conversion */ 8613#endif /* 16 to 8 bit conversion */
8614 8614
8615#if defined PNG_READ_BACKGROUND_SUPPORTED ||\ 8615#if defined PNG_READ_BACKGROUND_SUPPORTED ||\
8616 defined PNG_READ_ALPHA_MODE_SUPPORTED 8616 defined PNG_READ_ALPHA_MODE_SUPPORTED
8617static void gamma_composition_test(png_modifier *pm, 8617static void gamma_composition_test(png_modifier *pm,
8618 PNG_CONST png_byte colour_type, PNG_CONST png_byte bit_depth, 8618 PNG_CONST png_byte colour_type, PNG_CONST png_byte bit_depth,
8619 PNG_CONST int palette_number, 8619 PNG_CONST int palette_number,
8620 PNG_CONST int interlace_type, PNG_CONST double file_gamma, 8620 PNG_CONST int interlace_type, PNG_CONST double file_gamma,
8621 PNG_CONST double screen_gamma, 8621 PNG_CONST double screen_gamma,
8622 PNG_CONST int use_input_precision, PNG_CONST int do_background, 8622 PNG_CONST int use_input_precision, PNG_CONST int do_background,
8623 PNG_CONST int expand_16) 8623 PNG_CONST int expand_16)
8624{ 8624{
8625 size_t pos = 0; 8625 size_t pos = 0;
8626 png_const_charp base; 8626 png_const_charp base;
8627 double bg; 8627 double bg;
8628 char name[128]; 8628 char name[128];
8629 png_color_16 background; 8629 png_color_16 background;
8630 8630
8631 /* Make up a name and get an appropriate background gamma value. */ 8631 /* Make up a name and get an appropriate background gamma value. */
8632 switch (do_background) 8632 switch (do_background)
8633 { 8633 {
8634 default: 8634 default:
8635 base = ""; 8635 base = "";
8636 bg = 4; /* should not be used */ 8636 bg = 4; /* should not be used */
8637 break; 8637 break;
8638 case PNG_BACKGROUND_GAMMA_SCREEN: 8638 case PNG_BACKGROUND_GAMMA_SCREEN:
8639 base = " bckg(Screen):"; 8639 base = " bckg(Screen):";
8640 bg = 1/screen_gamma; 8640 bg = 1/screen_gamma;
8641 break; 8641 break;
8642 case PNG_BACKGROUND_GAMMA_FILE: 8642 case PNG_BACKGROUND_GAMMA_FILE:
8643 base = " bckg(File):"; 8643 base = " bckg(File):";
8644 bg = file_gamma; 8644 bg = file_gamma;
8645 break; 8645 break;
8646 case PNG_BACKGROUND_GAMMA_UNIQUE: 8646 case PNG_BACKGROUND_GAMMA_UNIQUE:
8647 base = " bckg(Unique):"; 8647 base = " bckg(Unique):";
8648 /* This tests the handling of a unique value, the math is such that the 8648 /* This tests the handling of a unique value, the math is such that the
8649 * value tends to be <1, but is neither screen nor file (even if they 8649 * value tends to be <1, but is neither screen nor file (even if they
8650 * match!) 8650 * match!)
8651 */ 8651 */
8652 bg = (file_gamma + screen_gamma) / 3; 8652 bg = (file_gamma + screen_gamma) / 3;
8653 break; 8653 break;
8654#ifdef PNG_READ_ALPHA_MODE_SUPPORTED 8654#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
8655 case ALPHA_MODE_OFFSET + PNG_ALPHA_PNG: 8655 case ALPHA_MODE_OFFSET + PNG_ALPHA_PNG:
8656 base = " alpha(PNG)"; 8656 base = " alpha(PNG)";
8657 bg = 4; /* should not be used */ 8657 bg = 4; /* should not be used */
8658 break; 8658 break;
8659 case ALPHA_MODE_OFFSET + PNG_ALPHA_STANDARD: 8659 case ALPHA_MODE_OFFSET + PNG_ALPHA_STANDARD:
8660 base = " alpha(Porter-Duff)"; 8660 base = " alpha(Porter-Duff)";
8661 bg = 4; /* should not be used */ 8661 bg = 4; /* should not be used */
8662 break; 8662 break;
8663 case ALPHA_MODE_OFFSET + PNG_ALPHA_OPTIMIZED: 8663 case ALPHA_MODE_OFFSET + PNG_ALPHA_OPTIMIZED:
8664 base = " alpha(Optimized)"; 8664 base = " alpha(Optimized)";
8665 bg = 4; /* should not be used */ 8665 bg = 4; /* should not be used */
8666 break; 8666 break;
8667 case ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN: 8667 case ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN:
8668 base = " alpha(Broken)"; 8668 base = " alpha(Broken)";
8669 bg = 4; /* should not be used */ 8669 bg = 4; /* should not be used */
8670 break; 8670 break;
8671#endif 8671#endif
8672 } 8672 }
8673 8673
8674 /* Use random background values - the background is always presented in the 8674 /* Use random background values - the background is always presented in the
8675 * output space (8 or 16 bit components). 8675 * output space (8 or 16 bit components).
8676 */ 8676 */
8677 if (expand_16 || bit_depth == 16) 8677 if (expand_16 || bit_depth == 16)
8678 { 8678 {
8679 png_uint_32 r = random_32(); 8679 png_uint_32 r = random_32();
8680 8680
8681 background.red = (png_uint_16)r; 8681 background.red = (png_uint_16)r;
8682 background.green = (png_uint_16)(r >> 16); 8682 background.green = (png_uint_16)(r >> 16);
8683 r = random_32(); 8683 r = random_32();
8684 background.blue = (png_uint_16)r; 8684 background.blue = (png_uint_16)r;
8685 background.gray = (png_uint_16)(r >> 16); 8685 background.gray = (png_uint_16)(r >> 16);
8686 } 8686 }
8687 8687
8688 else /* 8 bit colors */ 8688 else /* 8 bit colors */
8689 { 8689 {
8690 png_uint_32 r = random_32(); 8690 png_uint_32 r = random_32();
8691 8691
8692 background.red = (png_byte)r; 8692 background.red = (png_byte)r;
8693 background.green = (png_byte)(r >> 8); 8693 background.green = (png_byte)(r >> 8);
8694 background.blue = (png_byte)(r >> 16); 8694 background.blue = (png_byte)(r >> 16);
8695 background.gray = (png_byte)(r >> 24); 8695 background.gray = (png_byte)(r >> 24);
8696 } 8696 }
8697 8697
8698 background.index = 193; /* rgb(193,193,193) to detect errors */ 8698 background.index = 193; /* rgb(193,193,193) to detect errors */
8699 if (!(colour_type & PNG_COLOR_MASK_COLOR)) 8699 if (!(colour_type & PNG_COLOR_MASK_COLOR))
8700 { 8700 {
8701 /* Grayscale input, we do not convert to RGB (TBD), so we must set the 8701 /* Grayscale input, we do not convert to RGB (TBD), so we must set the
8702 * background to gray - else libpng seems to fail. 8702 * background to gray - else libpng seems to fail.
8703 */ 8703 */
8704 background.red = background.green = background.blue = background.gray; 8704 background.red = background.green = background.blue = background.gray;
8705 } 8705 }
8706 8706
8707 pos = safecat(name, sizeof name, pos, "gamma "); 8707 pos = safecat(name, sizeof name, pos, "gamma ");
8708 pos = safecatd(name, sizeof name, pos, file_gamma, 3); 8708 pos = safecatd(name, sizeof name, pos, file_gamma, 3);
8709 pos = safecat(name, sizeof name, pos, "->"); 8709 pos = safecat(name, sizeof name, pos, "->");
8710 pos = safecatd(name, sizeof name, pos, screen_gamma, 3); 8710 pos = safecatd(name, sizeof name, pos, screen_gamma, 3);
8711 8711
8712 pos = safecat(name, sizeof name, pos, base); 8712 pos = safecat(name, sizeof name, pos, base);
8713 if (do_background < ALPHA_MODE_OFFSET) 8713 if (do_background < ALPHA_MODE_OFFSET)
8714 { 8714 {
8715 /* Include the background color and gamma in the name: */ 8715 /* Include the background color and gamma in the name: */
8716 pos = safecat(name, sizeof name, pos, "("); 8716 pos = safecat(name, sizeof name, pos, "(");
8717 /* This assumes no expand gray->rgb - the current code won't handle that! 8717 /* This assumes no expand gray->rgb - the current code won't handle that!
8718 */ 8718 */
8719 if (colour_type & PNG_COLOR_MASK_COLOR) 8719 if (colour_type & PNG_COLOR_MASK_COLOR)
8720 { 8720 {
8721 pos = safecatn(name, sizeof name, pos, background.red); 8721 pos = safecatn(name, sizeof name, pos, background.red);
8722 pos = safecat(name, sizeof name, pos, ","); 8722 pos = safecat(name, sizeof name, pos, ",");
8723 pos = safecatn(name, sizeof name, pos, background.green); 8723 pos = safecatn(name, sizeof name, pos, background.green);
8724 pos = safecat(name, sizeof name, pos, ","); 8724 pos = safecat(name, sizeof name, pos, ",");
8725 pos = safecatn(name, sizeof name, pos, background.blue); 8725 pos = safecatn(name, sizeof name, pos, background.blue);
8726 } 8726 }
8727 else 8727 else
8728 pos = safecatn(name, sizeof name, pos, background.gray); 8728 pos = safecatn(name, sizeof name, pos, background.gray);
8729 pos = safecat(name, sizeof name, pos, ")^"); 8729 pos = safecat(name, sizeof name, pos, ")^");
8730 pos = safecatd(name, sizeof name, pos, bg, 3); 8730 pos = safecatd(name, sizeof name, pos, bg, 3);
8731 } 8731 }
8732 8732
8733 gamma_test(pm, colour_type, bit_depth, palette_number, interlace_type, 8733 gamma_test(pm, colour_type, bit_depth, palette_number, interlace_type,
8734 file_gamma, screen_gamma, 0/*sBIT*/, 0, name, use_input_precision, 8734 file_gamma, screen_gamma, 0/*sBIT*/, 0, name, use_input_precision,
8735 0/*strip 16*/, expand_16, do_background, &background, bg); 8735 0/*strip 16*/, expand_16, do_background, &background, bg);
8736} 8736}
8737 8737
8738 8738
8739static void 8739static void
8740perform_gamma_composition_tests(png_modifier *pm, int do_background, 8740perform_gamma_composition_tests(png_modifier *pm, int do_background,
8741 int expand_16) 8741 int expand_16)
8742{ 8742{
8743 png_byte colour_type = 0; 8743 png_byte colour_type = 0;
8744 png_byte bit_depth = 0; 8744 png_byte bit_depth = 0;
8745 int palette_number = 0; 8745 int palette_number = 0;
8746 8746
8747 /* Skip the non-alpha cases - there is no setting of a transparency colour at 8747 /* Skip the non-alpha cases - there is no setting of a transparency colour at
8748 * present. 8748 * present.
8749 */ 8749 */
8750 while (next_format(&colour_type, &bit_depth, &palette_number)) 8750 while (next_format(&colour_type, &bit_depth, &palette_number))
8751 if ((colour_type & PNG_COLOR_MASK_ALPHA) != 0) 8751 if ((colour_type & PNG_COLOR_MASK_ALPHA) != 0)
8752 { 8752 {
8753 unsigned int i, j; 8753 unsigned int i, j;
8754 8754
8755 /* Don't skip the i==j case here - it's relevant. */ 8755 /* Don't skip the i==j case here - it's relevant. */
8756 for (i=0; i<pm->ngamma_tests; ++i) for (j=0; j<pm->ngamma_tests; ++j) 8756 for (i=0; i<pm->ngamma_tests; ++i) for (j=0; j<pm->ngamma_tests; ++j)
8757 { 8757 {
8758 gamma_composition_test(pm, colour_type, bit_depth, palette_number, 8758 gamma_composition_test(pm, colour_type, bit_depth, palette_number,
8759 pm->interlace_type, 1/pm->gammas[i], pm->gammas[j], 8759 pm->interlace_type, 1/pm->gammas[i], pm->gammas[j],
8760 pm->use_input_precision, do_background, expand_16); 8760 pm->use_input_precision, do_background, expand_16);
8761 8761
8762 if (fail(pm)) 8762 if (fail(pm))
8763 return; 8763 return;
8764 } 8764 }
8765 } 8765 }
8766} 8766}
8767#endif /* READ_BACKGROUND || READ_ALPHA_MODE */ 8767#endif /* READ_BACKGROUND || READ_ALPHA_MODE */
8768 8768
8769static void 8769static void
8770init_gamma_errors(png_modifier *pm) 8770init_gamma_errors(png_modifier *pm)
8771{ 8771{
8772 pm->error_gray_2 = pm->error_gray_4 = pm->error_gray_8 = 0; 8772 pm->error_gray_2 = pm->error_gray_4 = pm->error_gray_8 = 0;
8773 pm->error_color_8 = 0; 8773 pm->error_color_8 = 0;
8774 pm->error_indexed = 0; 8774 pm->error_indexed = 0;
8775 pm->error_gray_16 = pm->error_color_16 = 0; 8775 pm->error_gray_16 = pm->error_color_16 = 0;
8776} 8776}
8777 8777
8778static void 8778static void
8779summarize_gamma_errors(png_modifier *pm, png_const_charp who, int low_bit_depth) 8779summarize_gamma_errors(png_modifier *pm, png_const_charp who, int low_bit_depth)
8780{ 8780{
8781 if (who) 8781 if (who)
8782 printf("Gamma correction with %s:\n", who); 8782 printf("Gamma correction with %s:\n", who);
8783 8783
8784 if (low_bit_depth) 8784 if (low_bit_depth)
8785 { 8785 {
8786 printf(" 2 bit gray: %.5f\n", pm->error_gray_2); 8786 printf(" 2 bit gray: %.5f\n", pm->error_gray_2);
8787 printf(" 4 bit gray: %.5f\n", pm->error_gray_4); 8787 printf(" 4 bit gray: %.5f\n", pm->error_gray_4);
8788 printf(" 8 bit gray: %.5f\n", pm->error_gray_8); 8788 printf(" 8 bit gray: %.5f\n", pm->error_gray_8);
8789 printf(" 8 bit color: %.5f\n", pm->error_color_8); 8789 printf(" 8 bit color: %.5f\n", pm->error_color_8);
8790 printf(" indexed: %.5f\n", pm->error_indexed); 8790 printf(" indexed: %.5f\n", pm->error_indexed);
8791 } 8791 }
8792 8792
8793#ifdef DO_16BIT 8793#ifdef DO_16BIT
8794 printf(" 16 bit gray: %.5f\n", pm->error_gray_16); 8794 printf(" 16 bit gray: %.5f\n", pm->error_gray_16);
8795 printf(" 16 bit color: %.5f\n", pm->error_color_16); 8795 printf(" 16 bit color: %.5f\n", pm->error_color_16);
8796#endif 8796#endif
8797} 8797}
8798 8798
8799static void 8799static void
8800perform_gamma_test(png_modifier *pm, int summary) 8800perform_gamma_test(png_modifier *pm, int summary)
8801{ 8801{
8802 /*TODO: remove this*/ 8802 /*TODO: remove this*/
8803 /* Save certain values for the temporary overrides below. */ 8803 /* Save certain values for the temporary overrides below. */
8804 unsigned int calculations_use_input_precision = 8804 unsigned int calculations_use_input_precision =
8805 pm->calculations_use_input_precision; 8805 pm->calculations_use_input_precision;
8806 double maxout8 = pm->maxout8; 8806 double maxout8 = pm->maxout8;
8807 8807
8808 /* First some arbitrary no-transform tests: */ 8808 /* First some arbitrary no-transform tests: */
8809 if (!pm->this.speed && pm->test_gamma_threshold) 8809 if (!pm->this.speed && pm->test_gamma_threshold)
8810 { 8810 {
8811 perform_gamma_threshold_tests(pm); 8811 perform_gamma_threshold_tests(pm);
8812 8812
8813 if (fail(pm)) 8813 if (fail(pm))
8814 return; 8814 return;
8815 } 8815 }
8816 8816
8817 /* Now some real transforms. */ 8817 /* Now some real transforms. */
8818 if (pm->test_gamma_transform) 8818 if (pm->test_gamma_transform)
8819 { 8819 {
8820 init_gamma_errors(pm); 8820 init_gamma_errors(pm);
8821 /*TODO: remove this. Necessary because the current libpng 8821 /*TODO: remove this. Necessary because the current libpng
8822 * implementation works in 8 bits: 8822 * implementation works in 8 bits:
8823 */ 8823 */
8824 if (pm->test_gamma_expand16) 8824 if (pm->test_gamma_expand16)
8825 pm->calculations_use_input_precision = 1; 8825 pm->calculations_use_input_precision = 1;
8826 perform_gamma_transform_tests(pm); 8826 perform_gamma_transform_tests(pm);
8827 if (!calculations_use_input_precision) 8827 if (!calculations_use_input_precision)
8828 pm->calculations_use_input_precision = 0; 8828 pm->calculations_use_input_precision = 0;
8829 8829
8830 if (summary) 8830 if (summary)
8831 { 8831 {
8832 printf("Gamma correction error summary\n\n"); 8832 printf("Gamma correction error summary\n\n");
8833 printf("The printed value is the maximum error in the pixel values\n"); 8833 printf("The printed value is the maximum error in the pixel values\n");
8834 printf("calculated by the libpng gamma correction code. The error\n"); 8834 printf("calculated by the libpng gamma correction code. The error\n");
8835 printf("is calculated as the difference between the output pixel\n"); 8835 printf("is calculated as the difference between the output pixel\n");
8836 printf("value (always an integer) and the ideal value from the\n"); 8836 printf("value (always an integer) and the ideal value from the\n");
8837 printf("libpng specification (typically not an integer).\n\n"); 8837 printf("libpng specification (typically not an integer).\n\n");
8838 8838
8839 printf("Expect this value to be less than .5 for 8 bit formats,\n"); 8839 printf("Expect this value to be less than .5 for 8 bit formats,\n");
8840 printf("less than 1 for formats with fewer than 8 bits and a small\n"); 8840 printf("less than 1 for formats with fewer than 8 bits and a small\n");
8841 printf("number (typically less than 5) for the 16 bit formats.\n"); 8841 printf("number (typically less than 5) for the 16 bit formats.\n");
8842 printf("For performance reasons the value for 16 bit formats\n"); 8842 printf("For performance reasons the value for 16 bit formats\n");
8843 printf("increases when the image file includes an sBIT chunk.\n\n"); 8843 printf("increases when the image file includes an sBIT chunk.\n\n");
8844 8844
8845 summarize_gamma_errors(pm, 0/*who*/, 1); 8845 summarize_gamma_errors(pm, 0/*who*/, 1);
8846 } 8846 }
8847 } 8847 }
8848 8848
8849 /* The sbit tests produce much larger errors: */ 8849 /* The sbit tests produce much larger errors: */
8850 if (pm->test_gamma_sbit) 8850 if (pm->test_gamma_sbit)
8851 { 8851 {
8852 init_gamma_errors(pm); 8852 init_gamma_errors(pm);
8853 perform_gamma_sbit_tests(pm); 8853 perform_gamma_sbit_tests(pm);
8854 8854
8855 if (summary) 8855 if (summary)
8856 summarize_gamma_errors(pm, "sBIT", pm->sbitlow < 8U); 8856 summarize_gamma_errors(pm, "sBIT", pm->sbitlow < 8U);
8857 } 8857 }
8858 8858
8859#ifdef DO_16BIT /* Should be READ_16BIT_SUPPORTED */ 8859#ifdef DO_16BIT /* Should be READ_16BIT_SUPPORTED */
8860 if (pm->test_gamma_scale16) 8860 if (pm->test_gamma_scale16)
8861 { 8861 {
8862 /* The 16 to 8 bit strip operations: */ 8862 /* The 16 to 8 bit strip operations: */
8863 init_gamma_errors(pm); 8863 init_gamma_errors(pm);
8864 perform_gamma_scale16_tests(pm); 8864 perform_gamma_scale16_tests(pm);
8865 8865
8866 if (summary) 8866 if (summary)
8867 { 8867 {
8868 printf("Gamma correction with 16 to 8 bit reduction:\n"); 8868 printf("Gamma correction with 16 to 8 bit reduction:\n");
8869 printf(" 16 bit gray: %.5f\n", pm->error_gray_16); 8869 printf(" 16 bit gray: %.5f\n", pm->error_gray_16);
8870 printf(" 16 bit color: %.5f\n", pm->error_color_16); 8870 printf(" 16 bit color: %.5f\n", pm->error_color_16);
8871 } 8871 }
8872 } 8872 }
8873#endif 8873#endif
8874 8874
8875#ifdef PNG_READ_BACKGROUND_SUPPORTED 8875#ifdef PNG_READ_BACKGROUND_SUPPORTED
8876 if (pm->test_gamma_background) 8876 if (pm->test_gamma_background)
8877 { 8877 {
8878 init_gamma_errors(pm); 8878 init_gamma_errors(pm);
8879 8879
8880 /*TODO: remove this. Necessary because the current libpng 8880 /*TODO: remove this. Necessary because the current libpng
8881 * implementation works in 8 bits: 8881 * implementation works in 8 bits:
8882 */ 8882 */
8883 if (pm->test_gamma_expand16) 8883 if (pm->test_gamma_expand16)
8884 { 8884 {
8885 pm->calculations_use_input_precision = 1; 8885 pm->calculations_use_input_precision = 1;
8886 pm->maxout8 = .499; /* because the 16 bit background is smashed */ 8886 pm->maxout8 = .499; /* because the 16 bit background is smashed */
8887 } 8887 }
8888 perform_gamma_composition_tests(pm, PNG_BACKGROUND_GAMMA_UNIQUE, 8888 perform_gamma_composition_tests(pm, PNG_BACKGROUND_GAMMA_UNIQUE,
8889 pm->test_gamma_expand16); 8889 pm->test_gamma_expand16);
8890 if (!calculations_use_input_precision) 8890 if (!calculations_use_input_precision)
8891 pm->calculations_use_input_precision = 0; 8891 pm->calculations_use_input_precision = 0;
8892 pm->maxout8 = maxout8; 8892 pm->maxout8 = maxout8;
8893 8893
8894 if (summary) 8894 if (summary)
8895 summarize_gamma_errors(pm, "background", 1); 8895 summarize_gamma_errors(pm, "background", 1);
8896 } 8896 }
8897#endif 8897#endif
8898 8898
8899#ifdef PNG_READ_ALPHA_MODE_SUPPORTED 8899#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
8900 if (pm->test_gamma_alpha_mode) 8900 if (pm->test_gamma_alpha_mode)
8901 { 8901 {
8902 int do_background; 8902 int do_background;
8903 8903
8904 init_gamma_errors(pm); 8904 init_gamma_errors(pm);
8905 8905
8906 /*TODO: remove this. Necessary because the current libpng 8906 /*TODO: remove this. Necessary because the current libpng
8907 * implementation works in 8 bits: 8907 * implementation works in 8 bits:
8908 */ 8908 */
8909 if (pm->test_gamma_expand16) 8909 if (pm->test_gamma_expand16)
8910 pm->calculations_use_input_precision = 1; 8910 pm->calculations_use_input_precision = 1;
8911 for (do_background = ALPHA_MODE_OFFSET + PNG_ALPHA_STANDARD; 8911 for (do_background = ALPHA_MODE_OFFSET + PNG_ALPHA_STANDARD;
8912 do_background <= ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN && !fail(pm); 8912 do_background <= ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN && !fail(pm);
8913 ++do_background) 8913 ++do_background)
8914 perform_gamma_composition_tests(pm, do_background, 8914 perform_gamma_composition_tests(pm, do_background,
8915 pm->test_gamma_expand16); 8915 pm->test_gamma_expand16);
8916 if (!calculations_use_input_precision) 8916 if (!calculations_use_input_precision)
8917 pm->calculations_use_input_precision = 0; 8917 pm->calculations_use_input_precision = 0;
8918 8918
8919 if (summary) 8919 if (summary)
8920 summarize_gamma_errors(pm, "alpha mode", 1); 8920 summarize_gamma_errors(pm, "alpha mode", 1);
8921 } 8921 }
8922#endif 8922#endif
8923} 8923}
8924#endif /* PNG_READ_GAMMA_SUPPORTED */ 8924#endif /* PNG_READ_GAMMA_SUPPORTED */
8925 8925
8926/* INTERLACE MACRO VALIDATION */ 8926/* INTERLACE MACRO VALIDATION */
8927/* This is copied verbatim from the specification, it is simply the pass 8927/* This is copied verbatim from the specification, it is simply the pass
8928 * number in which each pixel in each 8x8 tile appears. The array must 8928 * number in which each pixel in each 8x8 tile appears. The array must
8929 * be indexed adam7[y][x] and notice that the pass numbers are based at 8929 * be indexed adam7[y][x] and notice that the pass numbers are based at
8930 * 1, not 0 - the base libpng uses. 8930 * 1, not 0 - the base libpng uses.
8931 */ 8931 */
8932static PNG_CONST 8932static PNG_CONST
8933png_byte adam7[8][8] = 8933png_byte adam7[8][8] =
8934{ 8934{
8935 { 1,6,4,6,2,6,4,6 }, 8935 { 1,6,4,6,2,6,4,6 },
8936 { 7,7,7,7,7,7,7,7 }, 8936 { 7,7,7,7,7,7,7,7 },
8937 { 5,6,5,6,5,6,5,6 }, 8937 { 5,6,5,6,5,6,5,6 },
8938 { 7,7,7,7,7,7,7,7 }, 8938 { 7,7,7,7,7,7,7,7 },
8939 { 3,6,4,6,3,6,4,6 }, 8939 { 3,6,4,6,3,6,4,6 },
8940 { 7,7,7,7,7,7,7,7 }, 8940 { 7,7,7,7,7,7,7,7 },
8941 { 5,6,5,6,5,6,5,6 }, 8941 { 5,6,5,6,5,6,5,6 },
8942 { 7,7,7,7,7,7,7,7 } 8942 { 7,7,7,7,7,7,7,7 }
8943}; 8943};
8944 8944
8945/* This routine validates all the interlace support macros in png.h for 8945/* This routine validates all the interlace support macros in png.h for
8946 * a variety of valid PNG widths and heights. It uses a number of similarly 8946 * a variety of valid PNG widths and heights. It uses a number of similarly
8947 * named internal routines that feed off the above array. 8947 * named internal routines that feed off the above array.
8948 */ 8948 */
8949static png_uint_32 8949static png_uint_32
8950png_pass_start_row(int pass) 8950png_pass_start_row(int pass)
8951{ 8951{
8952 int x, y; 8952 int x, y;
8953 ++pass; 8953 ++pass;
8954 for (y=0; y<8; ++y) for (x=0; x<8; ++x) if (adam7[y][x] == pass) 8954 for (y=0; y<8; ++y) for (x=0; x<8; ++x) if (adam7[y][x] == pass)
8955 return y; 8955 return y;
8956 return 0xf; 8956 return 0xf;
8957} 8957}
8958 8958
8959static png_uint_32 8959static png_uint_32
8960png_pass_start_col(int pass) 8960png_pass_start_col(int pass)
8961{ 8961{
8962 int x, y; 8962 int x, y;
8963 ++pass; 8963 ++pass;
8964 for (x=0; x<8; ++x) for (y=0; y<8; ++y) if (adam7[y][x] == pass) 8964 for (x=0; x<8; ++x) for (y=0; y<8; ++y) if (adam7[y][x] == pass)
8965 return x; 8965 return x;
8966 return 0xf; 8966 return 0xf;
8967} 8967}
8968 8968
8969static int 8969static int
8970png_pass_row_shift(int pass) 8970png_pass_row_shift(int pass)
8971{ 8971{
8972 int x, y, base=(-1), inc=8; 8972 int x, y, base=(-1), inc=8;
8973 ++pass; 8973 ++pass;
8974 for (y=0; y<8; ++y) for (x=0; x<8; ++x) if (adam7[y][x] == pass) 8974 for (y=0; y<8; ++y) for (x=0; x<8; ++x) if (adam7[y][x] == pass)
8975 { 8975 {
8976 if (base == (-1)) 8976 if (base == (-1))
8977 base = y; 8977 base = y;
8978 else if (base == y) 8978 else if (base == y)
8979 {} 8979 {}
8980 else if (inc == y-base) 8980 else if (inc == y-base)
8981 base=y; 8981 base=y;
8982 else if (inc == 8) 8982 else if (inc == 8)
8983 inc = y-base, base=y; 8983 inc = y-base, base=y;
8984 else if (inc != y-base) 8984 else if (inc != y-base)
8985 return 0xff; /* error - more than one 'inc' value! */ 8985 return 0xff; /* error - more than one 'inc' value! */
8986 } 8986 }
8987 8987
8988 if (base == (-1)) return 0xfe; /* error - no row in pass! */ 8988 if (base == (-1)) return 0xfe; /* error - no row in pass! */
8989 8989
8990 /* The shift is always 1, 2 or 3 - no pass has all the rows! */ 8990 /* The shift is always 1, 2 or 3 - no pass has all the rows! */
8991 switch (inc) 8991 switch (inc)
8992 { 8992 {
8993case 2: return 1; 8993case 2: return 1;
8994case 4: return 2; 8994case 4: return 2;
8995case 8: return 3; 8995case 8: return 3;
8996default: break; 8996default: break;
8997 } 8997 }
8998 8998
8999 /* error - unrecognized 'inc' */ 8999 /* error - unrecognized 'inc' */
9000 return (inc << 8) + 0xfd; 9000 return (inc << 8) + 0xfd;
9001} 9001}
9002 9002
9003static int 9003static int
9004png_pass_col_shift(int pass) 9004png_pass_col_shift(int pass)
9005{ 9005{
9006 int x, y, base=(-1), inc=8; 9006 int x, y, base=(-1), inc=8;
9007 ++pass; 9007 ++pass;
9008 for (x=0; x<8; ++x) for (y=0; y<8; ++y) if (adam7[y][x] == pass) 9008 for (x=0; x<8; ++x) for (y=0; y<8; ++y) if (adam7[y][x] == pass)
9009 { 9009 {
9010 if (base == (-1)) 9010 if (base == (-1))
9011 base = x; 9011 base = x;
9012 else if (base == x) 9012 else if (base == x)
9013 {} 9013 {}
9014 else if (inc == x-base) 9014 else if (inc == x-base)
9015 base=x; 9015 base=x;
9016 else if (inc == 8) 9016 else if (inc == 8)
9017 inc = x-base, base=x; 9017 inc = x-base, base=x;
9018 else if (inc != x-base) 9018 else if (inc != x-base)
9019 return 0xff; /* error - more than one 'inc' value! */ 9019 return 0xff; /* error - more than one 'inc' value! */
9020 } 9020 }
9021 9021
9022 if (base == (-1)) return 0xfe; /* error - no row in pass! */ 9022 if (base == (-1)) return 0xfe; /* error - no row in pass! */
9023 9023
9024 /* The shift is always 1, 2 or 3 - no pass has all the rows! */ 9024 /* The shift is always 1, 2 or 3 - no pass has all the rows! */
9025 switch (inc) 9025 switch (inc)
9026 { 9026 {
9027case 1: return 0; /* pass 7 has all the columns */ 9027case 1: return 0; /* pass 7 has all the columns */
9028case 2: return 1; 9028case 2: return 1;
9029case 4: return 2; 9029case 4: return 2;
9030case 8: return 3; 9030case 8: return 3;
9031default: break; 9031default: break;
9032 } 9032 }
9033 9033
9034 /* error - unrecognized 'inc' */ 9034 /* error - unrecognized 'inc' */
9035 return (inc << 8) + 0xfd; 9035 return (inc << 8) + 0xfd;
9036} 9036}
9037 9037
9038static png_uint_32 9038static png_uint_32
9039png_row_from_pass_row(png_uint_32 yIn, int pass) 9039png_row_from_pass_row(png_uint_32 yIn, int pass)
9040{ 9040{
9041 /* By examination of the array: */ 9041 /* By examination of the array: */
9042 switch (pass) 9042 switch (pass)
9043 { 9043 {
9044case 0: return yIn * 8; 9044case 0: return yIn * 8;
9045case 1: return yIn * 8; 9045case 1: return yIn * 8;
9046case 2: return yIn * 8 + 4; 9046case 2: return yIn * 8 + 4;
9047case 3: return yIn * 4; 9047case 3: return yIn * 4;
9048case 4: return yIn * 4 + 2; 9048case 4: return yIn * 4 + 2;
9049case 5: return yIn * 2; 9049case 5: return yIn * 2;
9050case 6: return yIn * 2 + 1; 9050case 6: return yIn * 2 + 1;
9051default: break; 9051default: break;
9052 } 9052 }
9053 9053
9054 return 0xff; /* bad pass number */ 9054 return 0xff; /* bad pass number */
9055} 9055}
9056 9056
9057static png_uint_32 9057static png_uint_32
9058png_col_from_pass_col(png_uint_32 xIn, int pass) 9058png_col_from_pass_col(png_uint_32 xIn, int pass)
9059{ 9059{
9060 /* By examination of the array: */ 9060 /* By examination of the array: */
9061 switch (pass) 9061 switch (pass)
9062 { 9062 {
9063case 0: return xIn * 8; 9063case 0: return xIn * 8;
9064case 1: return xIn * 8 + 4; 9064case 1: return xIn * 8 + 4;
9065case 2: return xIn * 4; 9065case 2: return xIn * 4;
9066case 3: return xIn * 4 + 2; 9066case 3: return xIn * 4 + 2;
9067case 4: return xIn * 2; 9067case 4: return xIn * 2;
9068case 5: return xIn * 2 + 1; 9068case 5: return xIn * 2 + 1;
9069case 6: return xIn; 9069case 6: return xIn;
9070default: break; 9070default: break;
9071 } 9071 }
9072 9072
9073 return 0xff; /* bad pass number */ 9073 return 0xff; /* bad pass number */
9074} 9074}
9075 9075
9076static int 9076static int
9077png_row_in_interlace_pass(png_uint_32 y, int pass) 9077png_row_in_interlace_pass(png_uint_32 y, int pass)
9078{ 9078{
9079 /* Is row 'y' in pass 'pass'? */ 9079 /* Is row 'y' in pass 'pass'? */
9080 int x; 9080 int x;
9081 y &= 7; 9081 y &= 7;
9082 ++pass; 9082 ++pass;
9083 for (x=0; x<8; ++x) if (adam7[y][x] == pass) 9083 for (x=0; x<8; ++x) if (adam7[y][x] == pass)
9084 return 1; 9084 return 1;
9085 9085
9086 return 0; 9086 return 0;
9087} 9087}
9088 9088
9089static int 9089static int
9090png_col_in_interlace_pass(png_uint_32 x, int pass) 9090png_col_in_interlace_pass(png_uint_32 x, int pass)
9091{ 9091{
9092 /* Is column 'x' in pass 'pass'? */ 9092 /* Is column 'x' in pass 'pass'? */
9093 int y; 9093 int y;
9094 x &= 7; 9094 x &= 7;
9095 ++pass; 9095 ++pass;
9096 for (y=0; y<8; ++y) if (adam7[y][x] == pass) 9096 for (y=0; y<8; ++y) if (adam7[y][x] == pass)
9097 return 1; 9097 return 1;
9098 9098
9099 return 0; 9099 return 0;
9100} 9100}
9101 9101
9102static png_uint_32 9102static png_uint_32
9103png_pass_rows(png_uint_32 height, int pass) 9103png_pass_rows(png_uint_32 height, int pass)
9104{ 9104{
9105 png_uint_32 tiles = height>>3; 9105 png_uint_32 tiles = height>>3;
9106 png_uint_32 rows = 0; 9106 png_uint_32 rows = 0;
9107 unsigned int x, y; 9107 unsigned int x, y;
9108 9108
9109 height &= 7; 9109 height &= 7;
9110 ++pass; 9110 ++pass;
9111 for (y=0; y<8; ++y) for (x=0; x<8; ++x) if (adam7[y][x] == pass) 9111 for (y=0; y<8; ++y) for (x=0; x<8; ++x) if (adam7[y][x] == pass)
9112 { 9112 {
9113 rows += tiles; 9113 rows += tiles;
9114 if (y < height) ++rows; 9114 if (y < height) ++rows;
9115 break; /* i.e. break the 'x', column, loop. */ 9115 break; /* i.e. break the 'x', column, loop. */
9116 } 9116 }
9117 9117
9118 return rows; 9118 return rows;
9119} 9119}
9120 9120
9121static png_uint_32 9121static png_uint_32
9122png_pass_cols(png_uint_32 width, int pass) 9122png_pass_cols(png_uint_32 width, int pass)
9123{ 9123{
9124 png_uint_32 tiles = width>>3; 9124 png_uint_32 tiles = width>>3;
9125 png_uint_32 cols = 0; 9125 png_uint_32 cols = 0;
9126 unsigned int x, y; 9126 unsigned int x, y;
9127 9127
9128 width &= 7; 9128 width &= 7;
9129 ++pass; 9129 ++pass;
9130 for (x=0; x<8; ++x) for (y=0; y<8; ++y) if (adam7[y][x] == pass) 9130 for (x=0; x<8; ++x) for (y=0; y<8; ++y) if (adam7[y][x] == pass)
9131 { 9131 {
9132 cols += tiles; 9132 cols += tiles;
9133 if (x < width) ++cols; 9133 if (x < width) ++cols;
9134 break; /* i.e. break the 'y', row, loop. */ 9134 break; /* i.e. break the 'y', row, loop. */
9135 } 9135 }
9136 9136
9137 return cols; 9137 return cols;
9138} 9138}
9139 9139
9140static void 9140static void
9141perform_interlace_macro_validation(void) 9141perform_interlace_macro_validation(void)
9142{ 9142{
9143 /* The macros to validate, first those that depend only on pass: 9143 /* The macros to validate, first those that depend only on pass:
9144 * 9144 *
9145 * PNG_PASS_START_ROW(pass) 9145 * PNG_PASS_START_ROW(pass)
9146 * PNG_PASS_START_COL(pass) 9146 * PNG_PASS_START_COL(pass)
9147 * PNG_PASS_ROW_SHIFT(pass) 9147 * PNG_PASS_ROW_SHIFT(pass)
9148 * PNG_PASS_COL_SHIFT(pass) 9148 * PNG_PASS_COL_SHIFT(pass)
9149 */ 9149 */
9150 int pass; 9150 int pass;
9151 9151
9152 for (pass=0; pass<7; ++pass) 9152 for (pass=0; pass<7; ++pass)
9153 { 9153 {
9154 png_uint_32 m, f, v; 9154 png_uint_32 m, f, v;
9155 9155
9156 m = PNG_PASS_START_ROW(pass); 9156 m = PNG_PASS_START_ROW(pass);
9157 f = png_pass_start_row(pass); 9157 f = png_pass_start_row(pass);
9158 if (m != f) 9158 if (m != f)
9159 { 9159 {
9160 fprintf(stderr, "PNG_PASS_START_ROW(%d) = %u != %x\n", pass, m, f); 9160 fprintf(stderr, "PNG_PASS_START_ROW(%d) = %u != %x\n", pass, m, f);
9161 exit(1); 9161 exit(1);
9162 } 9162 }
9163 9163
9164 m = PNG_PASS_START_COL(pass); 9164 m = PNG_PASS_START_COL(pass);
9165 f = png_pass_start_col(pass); 9165 f = png_pass_start_col(pass);
9166 if (m != f) 9166 if (m != f)
9167 { 9167 {
9168 fprintf(stderr, "PNG_PASS_START_COL(%d) = %u != %x\n", pass, m, f); 9168 fprintf(stderr, "PNG_PASS_START_COL(%d) = %u != %x\n", pass, m, f);
9169 exit(1); 9169 exit(1);
9170 } 9170 }
9171 9171
9172 m = PNG_PASS_ROW_SHIFT(pass); 9172 m = PNG_PASS_ROW_SHIFT(pass);
9173 f = png_pass_row_shift(pass); 9173 f = png_pass_row_shift(pass);
9174 if (m != f) 9174 if (m != f)
9175 { 9175 {
9176 fprintf(stderr, "PNG_PASS_ROW_SHIFT(%d) = %u != %x\n", pass, m, f); 9176 fprintf(stderr, "PNG_PASS_ROW_SHIFT(%d) = %u != %x\n", pass, m, f);
9177 exit(1); 9177 exit(1);
9178 } 9178 }
9179 9179
9180 m = PNG_PASS_COL_SHIFT(pass); 9180 m = PNG_PASS_COL_SHIFT(pass);
9181 f = png_pass_col_shift(pass); 9181 f = png_pass_col_shift(pass);
9182 if (m != f) 9182 if (m != f)
9183 { 9183 {
9184 fprintf(stderr, "PNG_PASS_COL_SHIFT(%d) = %u != %x\n", pass, m, f); 9184 fprintf(stderr, "PNG_PASS_COL_SHIFT(%d) = %u != %x\n", pass, m, f);
9185 exit(1); 9185 exit(1);
9186 } 9186 }
9187 9187
9188 /* Macros that depend on the image or sub-image height too: 9188 /* Macros that depend on the image or sub-image height too:
9189 * 9189 *
9190 * PNG_PASS_ROWS(height, pass) 9190 * PNG_PASS_ROWS(height, pass)
9191 * PNG_PASS_COLS(width, pass) 9191 * PNG_PASS_COLS(width, pass)
9192 * PNG_ROW_FROM_PASS_ROW(yIn, pass) 9192 * PNG_ROW_FROM_PASS_ROW(yIn, pass)
9193 * PNG_COL_FROM_PASS_COL(xIn, pass) 9193 * PNG_COL_FROM_PASS_COL(xIn, pass)
9194 * PNG_ROW_IN_INTERLACE_PASS(y, pass) 9194 * PNG_ROW_IN_INTERLACE_PASS(y, pass)
9195 * PNG_COL_IN_INTERLACE_PASS(x, pass) 9195 * PNG_COL_IN_INTERLACE_PASS(x, pass)
9196 */ 9196 */
9197 for (v=0;;) 9197 for (v=0;;)
9198 { 9198 {
9199 /* First the base 0 stuff: */ 9199 /* First the base 0 stuff: */
9200 m = PNG_ROW_FROM_PASS_ROW(v, pass); 9200 m = PNG_ROW_FROM_PASS_ROW(v, pass);
9201 f = png_row_from_pass_row(v, pass); 9201 f = png_row_from_pass_row(v, pass);
9202 if (m != f) 9202 if (m != f)
9203 { 9203 {
9204 fprintf(stderr, "PNG_ROW_FROM_PASS_ROW(%u, %d) = %u != %x\n", 9204 fprintf(stderr, "PNG_ROW_FROM_PASS_ROW(%u, %d) = %u != %x\n",
9205 v, pass, m, f); 9205 v, pass, m, f);
9206 exit(1); 9206 exit(1);
9207 } 9207 }
9208 9208
9209 m = PNG_COL_FROM_PASS_COL(v, pass); 9209 m = PNG_COL_FROM_PASS_COL(v, pass);
9210 f = png_col_from_pass_col(v, pass); 9210 f = png_col_from_pass_col(v, pass);
9211 if (m != f) 9211 if (m != f)
9212 { 9212 {
9213 fprintf(stderr, "PNG_COL_FROM_PASS_COL(%u, %d) = %u != %x\n", 9213 fprintf(stderr, "PNG_COL_FROM_PASS_COL(%u, %d) = %u != %x\n",
9214 v, pass, m, f); 9214 v, pass, m, f);
9215 exit(1); 9215 exit(1);
9216 } 9216 }
9217 9217
9218 m = PNG_ROW_IN_INTERLACE_PASS(v, pass); 9218 m = PNG_ROW_IN_INTERLACE_PASS(v, pass);
9219 f = png_row_in_interlace_pass(v, pass); 9219 f = png_row_in_interlace_pass(v, pass);
9220 if (m != f) 9220 if (m != f)
9221 { 9221 {
9222 fprintf(stderr, "PNG_ROW_IN_INTERLACE_PASS(%u, %d) = %u != %x\n", 9222 fprintf(stderr, "PNG_ROW_IN_INTERLACE_PASS(%u, %d) = %u != %x\n",
9223 v, pass, m, f); 9223 v, pass, m, f);
9224 exit(1); 9224 exit(1);
9225 } 9225 }
9226 9226
9227 m = PNG_COL_IN_INTERLACE_PASS(v, pass); 9227 m = PNG_COL_IN_INTERLACE_PASS(v, pass);
9228 f = png_col_in_interlace_pass(v, pass); 9228 f = png_col_in_interlace_pass(v, pass);
9229 if (m != f) 9229 if (m != f)
9230 { 9230 {
9231 fprintf(stderr, "PNG_COL_IN_INTERLACE_PASS(%u, %d) = %u != %x\n", 9231 fprintf(stderr, "PNG_COL_IN_INTERLACE_PASS(%u, %d) = %u != %x\n",
9232 v, pass, m, f); 9232 v, pass, m, f);
9233 exit(1); 9233 exit(1);
9234 } 9234 }
9235 9235
9236 /* Then the base 1 stuff: */ 9236 /* Then the base 1 stuff: */
9237 ++v; 9237 ++v;
9238 m = PNG_PASS_ROWS(v, pass); 9238 m = PNG_PASS_ROWS(v, pass);
9239 f = png_pass_rows(v, pass); 9239 f = png_pass_rows(v, pass);
9240 if (m != f) 9240 if (m != f)
9241 { 9241 {
9242 fprintf(stderr, "PNG_PASS_ROWS(%u, %d) = %u != %x\n", 9242 fprintf(stderr, "PNG_PASS_ROWS(%u, %d) = %u != %x\n",
9243 v, pass, m, f); 9243 v, pass, m, f);
9244 exit(1); 9244 exit(1);
9245 } 9245 }
9246 9246
9247 m = PNG_PASS_COLS(v, pass); 9247 m = PNG_PASS_COLS(v, pass);
9248 f = png_pass_cols(v, pass); 9248 f = png_pass_cols(v, pass);
9249 if (m != f) 9249 if (m != f)
9250 { 9250 {
9251 fprintf(stderr, "PNG_PASS_COLS(%u, %d) = %u != %x\n", 9251 fprintf(stderr, "PNG_PASS_COLS(%u, %d) = %u != %x\n",
9252 v, pass, m, f); 9252 v, pass, m, f);
9253 exit(1); 9253 exit(1);
9254 } 9254 }
9255 9255
9256 /* Move to the next v - the stepping algorithm starts skipping 9256 /* Move to the next v - the stepping algorithm starts skipping
9257 * values above 1024. 9257 * values above 1024.
9258 */ 9258 */
9259 if (v > 1024) 9259 if (v > 1024)
9260 { 9260 {
9261 if (v == PNG_UINT_31_MAX) 9261 if (v == PNG_UINT_31_MAX)
9262 break; 9262 break;
9263 9263
9264 v = (v << 1) ^ v; 9264 v = (v << 1) ^ v;
9265 if (v >= PNG_UINT_31_MAX) 9265 if (v >= PNG_UINT_31_MAX)
9266 v = PNG_UINT_31_MAX-1; 9266 v = PNG_UINT_31_MAX-1;
9267 } 9267 }
9268 } 9268 }
9269 } 9269 }
9270} 9270}
9271 9271
9272/* Test color encodings. These values are back-calculated from the published 9272/* Test color encodings. These values are back-calculated from the published
9273 * chromaticities. The values are accurate to about 14 decimal places; 15 are 9273 * chromaticities. The values are accurate to about 14 decimal places; 15 are
9274 * given. These values are much more accurate than the ones given in the spec, 9274 * given. These values are much more accurate than the ones given in the spec,
9275 * which typically don't exceed 4 decimal places. This allows testing of the 9275 * which typically don't exceed 4 decimal places. This allows testing of the
9276 * libpng code to its theoretical accuracy of 4 decimal places. (If pngvalid 9276 * libpng code to its theoretical accuracy of 4 decimal places. (If pngvalid
9277 * used the published errors the 'slack' permitted would have to be +/-.5E-4 or 9277 * used the published errors the 'slack' permitted would have to be +/-.5E-4 or
9278 * more.) 9278 * more.)
9279 * 9279 *
9280 * The png_modifier code assumes that encodings[0] is sRGB and treats it 9280 * The png_modifier code assumes that encodings[0] is sRGB and treats it
9281 * specially: do not change the first entry in this list! 9281 * specially: do not change the first entry in this list!
9282 */ 9282 */
9283static PNG_CONST color_encoding test_encodings[] = 9283static PNG_CONST color_encoding test_encodings[] =
9284{ 9284{
9285/* sRGB: must be first in this list! */ 9285/* sRGB: must be first in this list! */
9286/*gamma:*/ { 1/2.2, 9286/*gamma:*/ { 1/2.2,
9287/*red: */ { 0.412390799265959, 0.212639005871510, 0.019330818715592 }, 9287/*red: */ { 0.412390799265959, 0.212639005871510, 0.019330818715592 },
9288/*green:*/ { 0.357584339383878, 0.715168678767756, 0.119194779794626 }, 9288/*green:*/ { 0.357584339383878, 0.715168678767756, 0.119194779794626 },
9289/*blue: */ { 0.180480788401834, 0.072192315360734, 0.950532152249660} }, 9289/*blue: */ { 0.180480788401834, 0.072192315360734, 0.950532152249660} },
9290/* Kodak ProPhoto (wide gamut) */ 9290/* Kodak ProPhoto (wide gamut) */
9291/*gamma:*/ { 1/1.6 /*approximate: uses 1.8 power law compared to sRGB 2.4*/, 9291/*gamma:*/ { 1/1.6 /*approximate: uses 1.8 power law compared to sRGB 2.4*/,
9292/*red: */ { 0.797760489672303, 0.288071128229293, 0.000000000000000 }, 9292/*red: */ { 0.797760489672303, 0.288071128229293, 0.000000000000000 },
9293/*green:*/ { 0.135185837175740, 0.711843217810102, 0.000000000000000 }, 9293/*green:*/ { 0.135185837175740, 0.711843217810102, 0.000000000000000 },
9294/*blue: */ { 0.031349349581525, 0.000085653960605, 0.825104602510460} }, 9294/*blue: */ { 0.031349349581525, 0.000085653960605, 0.825104602510460} },
9295/* Adobe RGB (1998) */ 9295/* Adobe RGB (1998) */
9296/*gamma:*/ { 1/(2+51./256), 9296/*gamma:*/ { 1/(2+51./256),
9297/*red: */ { 0.576669042910131, 0.297344975250536, 0.027031361386412 }, 9297/*red: */ { 0.576669042910131, 0.297344975250536, 0.027031361386412 },
9298/*green:*/ { 0.185558237906546, 0.627363566255466, 0.070688852535827 }, 9298/*green:*/ { 0.185558237906546, 0.627363566255466, 0.070688852535827 },
9299/*blue: */ { 0.188228646234995, 0.075291458493998, 0.991337536837639} }, 9299/*blue: */ { 0.188228646234995, 0.075291458493998, 0.991337536837639} },
9300/* Adobe Wide Gamut RGB */ 9300/* Adobe Wide Gamut RGB */
9301/*gamma:*/ { 1/(2+51./256), 9301/*gamma:*/ { 1/(2+51./256),
9302/*red: */ { 0.716500716779386, 0.258728243040113, 0.000000000000000 }, 9302/*red: */ { 0.716500716779386, 0.258728243040113, 0.000000000000000 },
9303/*green:*/ { 0.101020574397477, 0.724682314948566, 0.051211818965388 }, 9303/*green:*/ { 0.101020574397477, 0.724682314948566, 0.051211818965388 },
9304/*blue: */ { 0.146774385252705, 0.016589442011321, 0.773892783545073} }, 9304/*blue: */ { 0.146774385252705, 0.016589442011321, 0.773892783545073} },
9305}; 9305};
9306 9306
9307/* signal handler 9307/* signal handler
9308 * 9308 *
9309 * This attempts to trap signals and escape without crashing. It needs a 9309 * This attempts to trap signals and escape without crashing. It needs a
9310 * context pointer so that it can throw an exception (call longjmp) to recover 9310 * context pointer so that it can throw an exception (call longjmp) to recover
9311 * from the condition; this is handled by making the png_modifier used by 'main' 9311 * from the condition; this is handled by making the png_modifier used by 'main'
9312 * into a global variable. 9312 * into a global variable.
9313 */ 9313 */
9314static png_modifier pm; 9314static png_modifier pm;
9315 9315
9316static void signal_handler(int signum) 9316static void signal_handler(int signum)
9317{ 9317{
9318 9318
9319 size_t pos = 0; 9319 size_t pos = 0;
9320 char msg[64]; 9320 char msg[64];
9321 9321
9322 pos = safecat(msg, sizeof msg, pos, "caught signal: "); 9322 pos = safecat(msg, sizeof msg, pos, "caught signal: ");
9323 9323
9324 switch (signum) 9324 switch (signum)
9325 { 9325 {
9326 case SIGABRT: 9326 case SIGABRT:
9327 pos = safecat(msg, sizeof msg, pos, "abort"); 9327 pos = safecat(msg, sizeof msg, pos, "abort");
9328 break; 9328 break;
9329 9329
9330 case SIGFPE: 9330 case SIGFPE:
9331 pos = safecat(msg, sizeof msg, pos, "floating point exception"); 9331 pos = safecat(msg, sizeof msg, pos, "floating point exception");
9332 break; 9332 break;
9333 9333
9334 case SIGILL: 9334 case SIGILL:
9335 pos = safecat(msg, sizeof msg, pos, "illegal instruction"); 9335 pos = safecat(msg, sizeof msg, pos, "illegal instruction");
9336 break; 9336 break;
9337 9337
9338 case SIGINT: 9338 case SIGINT:
9339 pos = safecat(msg, sizeof msg, pos, "interrupt"); 9339 pos = safecat(msg, sizeof msg, pos, "interrupt");
9340 break; 9340 break;
9341 9341
9342 case SIGSEGV: 9342 case SIGSEGV:
9343 pos = safecat(msg, sizeof msg, pos, "invalid memory access"); 9343 pos = safecat(msg, sizeof msg, pos, "invalid memory access");
9344 break; 9344 break;
9345 9345
9346 case SIGTERM: 9346 case SIGTERM:
9347 pos = safecat(msg, sizeof msg, pos, "termination request"); 9347 pos = safecat(msg, sizeof msg, pos, "termination request");
9348 break; 9348 break;
9349 9349
9350 default: 9350 default:
9351 pos = safecat(msg, sizeof msg, pos, "unknown "); 9351 pos = safecat(msg, sizeof msg, pos, "unknown ");
9352 pos = safecatn(msg, sizeof msg, pos, signum); 9352 pos = safecatn(msg, sizeof msg, pos, signum);
9353 break; 9353 break;
9354 } 9354 }
9355 9355
9356 store_log(&pm.this, NULL/*png_structp*/, msg, 1/*error*/); 9356 store_log(&pm.this, NULL/*png_structp*/, msg, 1/*error*/);
9357 9357
9358 /* And finally throw an exception so we can keep going, unless this is 9358 /* And finally throw an exception so we can keep going, unless this is
9359 * SIGTERM in which case stop now. 9359 * SIGTERM in which case stop now.
9360 */ 9360 */
9361 if (signum != SIGTERM) 9361 if (signum != SIGTERM)
9362 { 9362 {
9363 struct exception_context *the_exception_context = 9363 struct exception_context *the_exception_context =
9364 &pm.this.exception_context; 9364 &pm.this.exception_context;
9365 9365
9366 Throw &pm.this; 9366 Throw &pm.this;
9367 } 9367 }
9368 9368
9369 else 9369 else
9370 exit(1); 9370 exit(1);
9371} 9371}
9372 9372
9373/* main program */ 9373/* main program */
9374int main(int argc, PNG_CONST char **argv) 9374int main(int argc, PNG_CONST char **argv)
9375{ 9375{
9376 volatile int summary = 1; /* Print the error summary at the end */ 9376 volatile int summary = 1; /* Print the error summary at the end */
9377 volatile int memstats = 0; /* Print memory statistics at the end */ 9377 volatile int memstats = 0; /* Print memory statistics at the end */
9378 9378
9379 /* Create the given output file on success: */ 9379 /* Create the given output file on success: */
9380 PNG_CONST char *volatile touch = NULL; 9380 PNG_CONST char *volatile touch = NULL;
9381 9381
9382 /* This is an array of standard gamma values (believe it or not I've seen 9382 /* This is an array of standard gamma values (believe it or not I've seen
9383 * every one of these mentioned somewhere.) 9383 * every one of these mentioned somewhere.)
9384 * 9384 *
9385 * In the following list the most useful values are first! 9385 * In the following list the most useful values are first!
9386 */ 9386 */
9387 static double 9387 static double
9388 gammas[]={2.2, 1.0, 2.2/1.45, 1.8, 1.5, 2.4, 2.5, 2.62, 2.9}; 9388 gammas[]={2.2, 1.0, 2.2/1.45, 1.8, 1.5, 2.4, 2.5, 2.62, 2.9};
9389 9389
9390 /* This records the command and arguments: */ 9390 /* This records the command and arguments: */
9391 size_t cp = 0; 9391 size_t cp = 0;
9392 char command[1024]; 9392 char command[1024];
9393 9393
9394 anon_context(&pm.this); 9394 anon_context(&pm.this);
9395 9395
9396 /* Add appropriate signal handlers, just the ANSI specified ones: */ 9396 /* Add appropriate signal handlers, just the ANSI specified ones: */
9397 signal(SIGABRT, signal_handler); 9397 signal(SIGABRT, signal_handler);
9398 signal(SIGFPE, signal_handler); 9398 signal(SIGFPE, signal_handler);
9399 signal(SIGILL, signal_handler); 9399 signal(SIGILL, signal_handler);
9400 signal(SIGINT, signal_handler); 9400 signal(SIGINT, signal_handler);
9401 signal(SIGSEGV, signal_handler); 9401 signal(SIGSEGV, signal_handler);
9402 signal(SIGTERM, signal_handler); 9402 signal(SIGTERM, signal_handler);
9403 9403
9404#ifdef HAVE_FEENABLEEXCEPT 9404#ifdef HAVE_FEENABLEEXCEPT
9405 /* Only required to enable FP exceptions on platforms where they start off 9405 /* Only required to enable FP exceptions on platforms where they start off
9406 * disabled; this is not necessary but if it is not done pngvalid will likely 9406 * disabled; this is not necessary but if it is not done pngvalid will likely
9407 * end up ignoring FP conditions that other platforms fault. 9407 * end up ignoring FP conditions that other platforms fault.
9408 */ 9408 */
9409 feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW); 9409 feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
9410#endif 9410#endif
9411 9411
9412 modifier_init(&pm); 9412 modifier_init(&pm);
9413 9413
9414 /* Preallocate the image buffer, because we know how big it needs to be, 9414 /* Preallocate the image buffer, because we know how big it needs to be,
9415 * note that, for testing purposes, it is deliberately mis-aligned by tag 9415 * note that, for testing purposes, it is deliberately mis-aligned by tag
9416 * bytes either side. All rows have an additional five bytes of padding for 9416 * bytes either side. All rows have an additional five bytes of padding for
9417 * overwrite checking. 9417 * overwrite checking.
9418 */ 9418 */
9419 store_ensure_image(&pm.this, NULL, 2, TRANSFORM_ROWMAX, TRANSFORM_HEIGHTMAX); 9419 store_ensure_image(&pm.this, NULL, 2, TRANSFORM_ROWMAX, TRANSFORM_HEIGHTMAX);
9420 9420
9421 /* Don't give argv[0], it's normally some horrible libtool string: */ 9421 /* Don't give argv[0], it's normally some horrible libtool string: */
9422 cp = safecat(command, sizeof command, cp, "pngvalid"); 9422 cp = safecat(command, sizeof command, cp, "pngvalid");
9423 9423
9424 /* Default to error on warning: */ 9424 /* Default to error on warning: */
9425 pm.this.treat_warnings_as_errors = 1; 9425 pm.this.treat_warnings_as_errors = 1;
9426 9426
9427 /* Store the test gammas */ 9427 /* Store the test gammas */
9428 pm.gammas = gammas; 9428 pm.gammas = gammas;
9429 pm.ngammas = (sizeof gammas) / (sizeof gammas[0]); 9429 pm.ngammas = (sizeof gammas) / (sizeof gammas[0]);
9430 pm.ngamma_tests = 0; /* default to off */ 9430 pm.ngamma_tests = 0; /* default to off */
9431 9431
9432 /* And the test encodings */ 9432 /* And the test encodings */
9433 pm.encodings = test_encodings; 9433 pm.encodings = test_encodings;
9434 pm.nencodings = (sizeof test_encodings) / (sizeof test_encodings[0]); 9434 pm.nencodings = (sizeof test_encodings) / (sizeof test_encodings[0]);
9435 9435
9436 pm.sbitlow = 8U; /* because libpng doesn't do sBIT below 8! */ 9436 pm.sbitlow = 8U; /* because libpng doesn't do sBIT below 8! */
9437 /* The following allows results to pass if they correspond to anything in the 9437 /* The following allows results to pass if they correspond to anything in the
9438 * transformed range [input-.5,input+.5]; this is is required because of the 9438 * transformed range [input-.5,input+.5]; this is is required because of the
9439 * way libpng treates the 16_TO_8 flag when building the gamma tables. 9439 * way libpng treates the 16_TO_8 flag when building the gamma tables.
9440 * 9440 *
9441 * TODO: review this 9441 * TODO: review this
9442 */ 9442 */
9443 pm.use_input_precision_16to8 = 1U; 9443 pm.use_input_precision_16to8 = 1U;
9444 9444
9445 /* Some default values (set the behavior for 'make check' here). 9445 /* Some default values (set the behavior for 'make check' here).
9446 * These values simply control the maximum error permitted in the gamma 9446 * These values simply control the maximum error permitted in the gamma
9447 * transformations. The practial limits for human perception are described 9447 * transformations. The practial limits for human perception are described
9448 * below (the setting for maxpc16), however for 8 bit encodings it isn't 9448 * below (the setting for maxpc16), however for 8 bit encodings it isn't
9449 * possible to meet the accepted capabilities of human vision - i.e. 8 bit 9449 * possible to meet the accepted capabilities of human vision - i.e. 8 bit
9450 * images can never be good enough, regardless of encoding. 9450 * images can never be good enough, regardless of encoding.
9451 */ 9451 */
9452 pm.maxout8 = .1; /* Arithmetic error in *encoded* value */ 9452 pm.maxout8 = .1; /* Arithmetic error in *encoded* value */
9453 pm.maxabs8 = .00005; /* 1/20000 */ 9453 pm.maxabs8 = .00005; /* 1/20000 */
9454 pm.maxcalc8 = .004; /* +/-1 in 8 bits for compose errors */ 9454 pm.maxcalc8 = .004; /* +/-1 in 8 bits for compose errors */
9455 pm.maxpc8 = .499; /* I.e., .499% fractional error */ 9455 pm.maxpc8 = .499; /* I.e., .499% fractional error */
9456 pm.maxout16 = .499; /* Error in *encoded* value */ 9456 pm.maxout16 = .499; /* Error in *encoded* value */
9457 pm.maxabs16 = .00005;/* 1/20000 */ 9457 pm.maxabs16 = .00005;/* 1/20000 */
9458 pm.maxcalc16 =.000015;/* +/-1 in 16 bits for compose errors */ 9458 pm.maxcalc16 =.000015;/* +/-1 in 16 bits for compose errors */
9459 9459
9460 /* NOTE: this is a reasonable perceptual limit. We assume that humans can 9460 /* NOTE: this is a reasonable perceptual limit. We assume that humans can
9461 * perceive light level differences of 1% over a 100:1 range, so we need to 9461 * perceive light level differences of 1% over a 100:1 range, so we need to
9462 * maintain 1 in 10000 accuracy (in linear light space), which is what the 9462 * maintain 1 in 10000 accuracy (in linear light space), which is what the
9463 * following guarantees. It also allows significantly higher errors at 9463 * following guarantees. It also allows significantly higher errors at
9464 * higher 16 bit values, which is important for performance. The actual 9464 * higher 16 bit values, which is important for performance. The actual
9465 * maximum 16 bit error is about +/-1.9 in the fixed point implementation but 9465 * maximum 16 bit error is about +/-1.9 in the fixed point implementation but
9466 * this is only allowed for values >38149 by the following: 9466 * this is only allowed for values >38149 by the following:
9467 */ 9467 */
9468 pm.maxpc16 = .005; /* I.e., 1/200% - 1/20000 */ 9468 pm.maxpc16 = .005; /* I.e., 1/200% - 1/20000 */
9469 9469
9470 /* Now parse the command line options. */ 9470 /* Now parse the command line options. */
9471 while (--argc >= 1) 9471 while (--argc >= 1)
9472 { 9472 {
9473 int catmore = 0; /* Set if the argument has an argument. */ 9473 int catmore = 0; /* Set if the argument has an argument. */
9474 9474
9475 /* Record each argument for posterity: */ 9475 /* Record each argument for posterity: */
9476 cp = safecat(command, sizeof command, cp, " "); 9476 cp = safecat(command, sizeof command, cp, " ");
9477 cp = safecat(command, sizeof command, cp, *++argv); 9477 cp = safecat(command, sizeof command, cp, *++argv);
9478 9478
9479 if (strcmp(*argv, "-v") == 0) 9479 if (strcmp(*argv, "-v") == 0)
9480 pm.this.verbose = 1; 9480 pm.this.verbose = 1;
9481 9481
9482 else if (strcmp(*argv, "-l") == 0) 9482 else if (strcmp(*argv, "-l") == 0)
9483 pm.log = 1; 9483 pm.log = 1;
9484 9484
9485 else if (strcmp(*argv, "-q") == 0) 9485 else if (strcmp(*argv, "-q") == 0)
9486 summary = pm.this.verbose = pm.log = 0; 9486 summary = pm.this.verbose = pm.log = 0;
9487 9487
9488 else if (strcmp(*argv, "-w") == 0) 9488 else if (strcmp(*argv, "-w") == 0)
9489 pm.this.treat_warnings_as_errors = 0; 9489 pm.this.treat_warnings_as_errors = 0;
9490 9490
9491 else if (strcmp(*argv, "--speed") == 0) 9491 else if (strcmp(*argv, "--speed") == 0)
9492 pm.this.speed = 1, pm.ngamma_tests = pm.ngammas, pm.test_standard = 0, 9492 pm.this.speed = 1, pm.ngamma_tests = pm.ngammas, pm.test_standard = 0,
9493 summary = 0; 9493 summary = 0;
9494 9494
9495 else if (strcmp(*argv, "--memory") == 0) 9495 else if (strcmp(*argv, "--memory") == 0)
9496 memstats = 1; 9496 memstats = 1;
9497 9497
9498 else if (strcmp(*argv, "--size") == 0) 9498 else if (strcmp(*argv, "--size") == 0)
9499 pm.test_size = 1; 9499 pm.test_size = 1;
9500 9500
9501 else if (strcmp(*argv, "--nosize") == 0) 9501 else if (strcmp(*argv, "--nosize") == 0)
9502 pm.test_size = 0; 9502 pm.test_size = 0;
9503 9503
9504 else if (strcmp(*argv, "--standard") == 0) 9504 else if (strcmp(*argv, "--standard") == 0)
9505 pm.test_standard = 1; 9505 pm.test_standard = 1;
9506 9506
9507 else if (strcmp(*argv, "--nostandard") == 0) 9507 else if (strcmp(*argv, "--nostandard") == 0)
9508 pm.test_standard = 0; 9508 pm.test_standard = 0;
9509 9509
9510 else if (strcmp(*argv, "--transform") == 0) 9510 else if (strcmp(*argv, "--transform") == 0)
9511 pm.test_transform = 1; 9511 pm.test_transform = 1;
9512 9512
9513 else if (strcmp(*argv, "--notransform") == 0) 9513 else if (strcmp(*argv, "--notransform") == 0)
9514 pm.test_transform = 0; 9514 pm.test_transform = 0;
9515 9515
9516#ifdef PNG_READ_TRANSFORMS_SUPPORTED 9516#ifdef PNG_READ_TRANSFORMS_SUPPORTED
9517 else if (strncmp(*argv, "--transform-disable=", 9517 else if (strncmp(*argv, "--transform-disable=",
9518 sizeof "--transform-disable") == 0) 9518 sizeof "--transform-disable") == 0)
9519 { 9519 {
9520 pm.test_transform = 1; 9520 pm.test_transform = 1;
9521 transform_disable(*argv + sizeof "--transform-disable"); 9521 transform_disable(*argv + sizeof "--transform-disable");
9522 } 9522 }
9523 9523
9524 else if (strncmp(*argv, "--transform-enable=", 9524 else if (strncmp(*argv, "--transform-enable=",
9525 sizeof "--transform-enable") == 0) 9525 sizeof "--transform-enable") == 0)
9526 { 9526 {
9527 pm.test_transform = 1; 9527 pm.test_transform = 1;
9528 transform_enable(*argv + sizeof "--transform-enable"); 9528 transform_enable(*argv + sizeof "--transform-enable");
9529 } 9529 }
9530#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ 9530#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
9531 9531
9532 else if (strcmp(*argv, "--gamma") == 0) 9532 else if (strcmp(*argv, "--gamma") == 0)
9533 { 9533 {
9534 /* Just do two gamma tests here (2.2 and linear) for speed: */ 9534 /* Just do two gamma tests here (2.2 and linear) for speed: */
9535 pm.ngamma_tests = 2U; 9535 pm.ngamma_tests = 2U;
9536 pm.test_gamma_threshold = 1; 9536 pm.test_gamma_threshold = 1;
9537 pm.test_gamma_transform = 1; 9537 pm.test_gamma_transform = 1;
9538 pm.test_gamma_sbit = 1; 9538 pm.test_gamma_sbit = 1;
9539 pm.test_gamma_scale16 = 1; 9539 pm.test_gamma_scale16 = 1;
9540 pm.test_gamma_background = 1; 9540 pm.test_gamma_background = 1;
9541 pm.test_gamma_alpha_mode = 1; 9541 pm.test_gamma_alpha_mode = 1;
9542 } 9542 }
9543 9543
9544 else if (strcmp(*argv, "--nogamma") == 0) 9544 else if (strcmp(*argv, "--nogamma") == 0)
9545 pm.ngamma_tests = 0; 9545 pm.ngamma_tests = 0;
9546 9546
9547 else if (strcmp(*argv, "--gamma-threshold") == 0) 9547 else if (strcmp(*argv, "--gamma-threshold") == 0)
9548 pm.ngamma_tests = 2U, pm.test_gamma_threshold = 1; 9548 pm.ngamma_tests = 2U, pm.test_gamma_threshold = 1;
9549 9549
9550 else if (strcmp(*argv, "--nogamma-threshold") == 0) 9550 else if (strcmp(*argv, "--nogamma-threshold") == 0)
9551 pm.test_gamma_threshold = 0; 9551 pm.test_gamma_threshold = 0;
9552 9552
9553 else if (strcmp(*argv, "--gamma-transform") == 0) 9553 else if (strcmp(*argv, "--gamma-transform") == 0)
9554 pm.ngamma_tests = 2U, pm.test_gamma_transform = 1; 9554 pm.ngamma_tests = 2U, pm.test_gamma_transform = 1;
9555 9555
9556 else if (strcmp(*argv, "--nogamma-transform") == 0) 9556 else if (strcmp(*argv, "--nogamma-transform") == 0)
9557 pm.test_gamma_transform = 0; 9557 pm.test_gamma_transform = 0;
9558 9558
9559 else if (strcmp(*argv, "--gamma-sbit") == 0) 9559 else if (strcmp(*argv, "--gamma-sbit") == 0)
9560 pm.ngamma_tests = 2U, pm.test_gamma_sbit = 1; 9560 pm.ngamma_tests = 2U, pm.test_gamma_sbit = 1;
9561 9561
9562 else if (strcmp(*argv, "--nogamma-sbit") == 0) 9562 else if (strcmp(*argv, "--nogamma-sbit") == 0)
9563 pm.test_gamma_sbit = 0; 9563 pm.test_gamma_sbit = 0;
9564 9564
9565 else if (strcmp(*argv, "--gamma-16-to-8") == 0) 9565 else if (strcmp(*argv, "--gamma-16-to-8") == 0)
9566 pm.ngamma_tests = 2U, pm.test_gamma_scale16 = 1; 9566 pm.ngamma_tests = 2U, pm.test_gamma_scale16 = 1;
9567 9567
9568 else if (strcmp(*argv, "--nogamma-16-to-8") == 0) 9568 else if (strcmp(*argv, "--nogamma-16-to-8") == 0)
9569 pm.test_gamma_scale16 = 0; 9569 pm.test_gamma_scale16 = 0;
9570 9570
9571 else if (strcmp(*argv, "--gamma-background") == 0) 9571 else if (strcmp(*argv, "--gamma-background") == 0)
9572 pm.ngamma_tests = 2U, pm.test_gamma_background = 1; 9572 pm.ngamma_tests = 2U, pm.test_gamma_background = 1;
9573 9573
9574 else if (strcmp(*argv, "--nogamma-background") == 0) 9574 else if (strcmp(*argv, "--nogamma-background") == 0)
9575 pm.test_gamma_background = 0; 9575 pm.test_gamma_background = 0;
9576 9576
9577 else if (strcmp(*argv, "--gamma-alpha-mode") == 0) 9577 else if (strcmp(*argv, "--gamma-alpha-mode") == 0)
9578 pm.ngamma_tests = 2U, pm.test_gamma_alpha_mode = 1; 9578 pm.ngamma_tests = 2U, pm.test_gamma_alpha_mode = 1;
9579 9579
9580 else if (strcmp(*argv, "--nogamma-alpha-mode") == 0) 9580 else if (strcmp(*argv, "--nogamma-alpha-mode") == 0)
9581 pm.test_gamma_alpha_mode = 0; 9581 pm.test_gamma_alpha_mode = 0;
9582 9582
9583 else if (strcmp(*argv, "--expand16") == 0) 9583 else if (strcmp(*argv, "--expand16") == 0)
9584 pm.test_gamma_expand16 = 1; 9584 pm.test_gamma_expand16 = 1;
9585 9585
9586 else if (strcmp(*argv, "--noexpand16") == 0) 9586 else if (strcmp(*argv, "--noexpand16") == 0)
9587 pm.test_gamma_expand16 = 0; 9587 pm.test_gamma_expand16 = 0;
9588 9588
9589 else if (strcmp(*argv, "--more-gammas") == 0) 9589 else if (strcmp(*argv, "--more-gammas") == 0)
9590 pm.ngamma_tests = 3U; 9590 pm.ngamma_tests = 3U;
9591 9591
9592 else if (strcmp(*argv, "--all-gammas") == 0) 9592 else if (strcmp(*argv, "--all-gammas") == 0)
9593 pm.ngamma_tests = pm.ngammas; 9593 pm.ngamma_tests = pm.ngammas;
9594 9594
9595 else if (strcmp(*argv, "--progressive-read") == 0) 9595 else if (strcmp(*argv, "--progressive-read") == 0)
9596 pm.this.progressive = 1; 9596 pm.this.progressive = 1;
9597 9597
9598 else if (strcmp(*argv, "--use-update-info") == 0) 9598 else if (strcmp(*argv, "--use-update-info") == 0)
9599 ++pm.use_update_info; /* Can call multiple times */ 9599 ++pm.use_update_info; /* Can call multiple times */
9600 9600
9601 else if (strcmp(*argv, "--interlace") == 0) 9601 else if (strcmp(*argv, "--interlace") == 0)
9602 pm.interlace_type = PNG_INTERLACE_ADAM7; 9602 pm.interlace_type = PNG_INTERLACE_ADAM7;
9603 9603
9604 else if (strcmp(*argv, "--use-input-precision") == 0) 9604 else if (strcmp(*argv, "--use-input-precision") == 0)
9605 pm.use_input_precision = 1; 9605 pm.use_input_precision = 1;
9606 9606
9607 else if (strcmp(*argv, "--calculations-use-input-precision") == 0) 9607 else if (strcmp(*argv, "--calculations-use-input-precision") == 0)
9608 pm.calculations_use_input_precision = 1; 9608 pm.calculations_use_input_precision = 1;
9609 9609
9610 else if (strcmp(*argv, "--assume-16-bit-calculations") == 0) 9610 else if (strcmp(*argv, "--assume-16-bit-calculations") == 0)
9611 pm.assume_16_bit_calculations = 1; 9611 pm.assume_16_bit_calculations = 1;
9612 9612
9613 else if (strcmp(*argv, "--calculations-follow-bit-depth") == 0) 9613 else if (strcmp(*argv, "--calculations-follow-bit-depth") == 0)
9614 pm.calculations_use_input_precision = 9614 pm.calculations_use_input_precision =
9615 pm.assume_16_bit_calculations = 0; 9615 pm.assume_16_bit_calculations = 0;
9616 9616
9617 else if (strcmp(*argv, "--exhaustive") == 0) 9617 else if (strcmp(*argv, "--exhaustive") == 0)
9618 pm.test_exhaustive = 1; 9618 pm.test_exhaustive = 1;
9619 9619
9620 else if (argc > 1 && strcmp(*argv, "--sbitlow") == 0) 9620 else if (argc > 1 && strcmp(*argv, "--sbitlow") == 0)
9621 --argc, pm.sbitlow = (png_byte)atoi(*++argv), catmore = 1; 9621 --argc, pm.sbitlow = (png_byte)atoi(*++argv), catmore = 1;
9622 9622
9623 else if (argc > 1 && strcmp(*argv, "--touch") == 0) 9623 else if (argc > 1 && strcmp(*argv, "--touch") == 0)
9624 --argc, touch = *++argv, catmore = 1; 9624 --argc, touch = *++argv, catmore = 1;
9625 9625
9626 else if (argc > 1 && strncmp(*argv, "--max", 5) == 0) 9626 else if (argc > 1 && strncmp(*argv, "--max", 5) == 0)
9627 { 9627 {
9628 --argc; 9628 --argc;
9629 9629
9630 if (strcmp(5+*argv, "abs8") == 0) 9630 if (strcmp(5+*argv, "abs8") == 0)
9631 pm.maxabs8 = atof(*++argv); 9631 pm.maxabs8 = atof(*++argv);
9632 9632
9633 else if (strcmp(5+*argv, "abs16") == 0) 9633 else if (strcmp(5+*argv, "abs16") == 0)
9634 pm.maxabs16 = atof(*++argv); 9634 pm.maxabs16 = atof(*++argv);
9635 9635
9636 else if (strcmp(5+*argv, "calc8") == 0) 9636 else if (strcmp(5+*argv, "calc8") == 0)
9637 pm.maxcalc8 = atof(*++argv); 9637 pm.maxcalc8 = atof(*++argv);
9638 9638
9639 else if (strcmp(5+*argv, "calc16") == 0) 9639 else if (strcmp(5+*argv, "calc16") == 0)
9640 pm.maxcalc16 = atof(*++argv); 9640 pm.maxcalc16 = atof(*++argv);
9641 9641
9642 else if (strcmp(5+*argv, "out8") == 0) 9642 else if (strcmp(5+*argv, "out8") == 0)
9643 pm.maxout8 = atof(*++argv); 9643 pm.maxout8 = atof(*++argv);
9644 9644
9645 else if (strcmp(5+*argv, "out16") == 0) 9645 else if (strcmp(5+*argv, "out16") == 0)
9646 pm.maxout16 = atof(*++argv); 9646 pm.maxout16 = atof(*++argv);
9647 9647
9648 else if (strcmp(5+*argv, "pc8") == 0) 9648 else if (strcmp(5+*argv, "pc8") == 0)
9649 pm.maxpc8 = atof(*++argv); 9649 pm.maxpc8 = atof(*++argv);
9650 9650
9651 else if (strcmp(5+*argv, "pc16") == 0) 9651 else if (strcmp(5+*argv, "pc16") == 0)
9652 pm.maxpc16 = atof(*++argv); 9652 pm.maxpc16 = atof(*++argv);
9653 9653
9654 else 9654 else
9655 { 9655 {
9656 fprintf(stderr, "pngvalid: %s: unknown 'max' option\n", *argv); 9656 fprintf(stderr, "pngvalid: %s: unknown 'max' option\n", *argv);
9657 exit(1); 9657 exit(1);
9658 } 9658 }
9659 9659
9660 catmore = 1; 9660 catmore = 1;
9661 } 9661 }
9662 9662
9663 else if (strcmp(*argv, "--log8") == 0) 9663 else if (strcmp(*argv, "--log8") == 0)
9664 --argc, pm.log8 = atof(*++argv), catmore = 1; 9664 --argc, pm.log8 = atof(*++argv), catmore = 1;
9665 9665
9666 else if (strcmp(*argv, "--log16") == 0) 9666 else if (strcmp(*argv, "--log16") == 0)
9667 --argc, pm.log16 = atof(*++argv), catmore = 1; 9667 --argc, pm.log16 = atof(*++argv), catmore = 1;
9668 9668
9669 else 9669 else
9670 { 9670 {
9671 fprintf(stderr, "pngvalid: %s: unknown argument\n", *argv); 9671 fprintf(stderr, "pngvalid: %s: unknown argument\n", *argv);
9672 exit(1); 9672 exit(1);
9673 } 9673 }
9674 9674
9675 if (catmore) /* consumed an extra *argv */ 9675 if (catmore) /* consumed an extra *argv */
9676 { 9676 {
9677 cp = safecat(command, sizeof command, cp, " "); 9677 cp = safecat(command, sizeof command, cp, " ");
9678 cp = safecat(command, sizeof command, cp, *argv); 9678 cp = safecat(command, sizeof command, cp, *argv);
9679 } 9679 }
9680 } 9680 }
9681 9681
9682 /* If pngvalid is run with no arguments default to a reasonable set of the 9682 /* If pngvalid is run with no arguments default to a reasonable set of the
9683 * tests. 9683 * tests.
9684 */ 9684 */
9685 if (pm.test_standard == 0 && pm.test_size == 0 && pm.test_transform == 0 && 9685 if (pm.test_standard == 0 && pm.test_size == 0 && pm.test_transform == 0 &&
9686 pm.ngamma_tests == 0) 9686 pm.ngamma_tests == 0)
9687 { 9687 {
9688 /* Make this do all the tests done in the test shell scripts with the same 9688 /* Make this do all the tests done in the test shell scripts with the same
9689 * parameters, where possible. The limitation is that all the progressive 9689 * parameters, where possible. The limitation is that all the progressive
9690 * read and interlace stuff has to be done in separate runs, so only the 9690 * read and interlace stuff has to be done in separate runs, so only the
9691 * basic 'standard' and 'size' tests are done. 9691 * basic 'standard' and 'size' tests are done.
9692 */ 9692 */
9693 pm.test_standard = 1; 9693 pm.test_standard = 1;
9694 pm.test_size = 1; 9694 pm.test_size = 1;
9695 pm.test_transform = 1; 9695 pm.test_transform = 1;
9696 pm.ngamma_tests = 2U; 9696 pm.ngamma_tests = 2U;
9697 } 9697 }
9698 9698
9699 if (pm.ngamma_tests > 0 && 9699 if (pm.ngamma_tests > 0 &&
9700 pm.test_gamma_threshold == 0 && pm.test_gamma_transform == 0 && 9700 pm.test_gamma_threshold == 0 && pm.test_gamma_transform == 0 &&
9701 pm.test_gamma_sbit == 0 && pm.test_gamma_scale16 == 0 && 9701 pm.test_gamma_sbit == 0 && pm.test_gamma_scale16 == 0 &&
9702 pm.test_gamma_background == 0 && pm.test_gamma_alpha_mode == 0) 9702 pm.test_gamma_background == 0 && pm.test_gamma_alpha_mode == 0)
9703 { 9703 {
9704 pm.test_gamma_threshold = 1; 9704 pm.test_gamma_threshold = 1;
9705 pm.test_gamma_transform = 1; 9705 pm.test_gamma_transform = 1;
9706 pm.test_gamma_sbit = 1; 9706 pm.test_gamma_sbit = 1;
9707 pm.test_gamma_scale16 = 1; 9707 pm.test_gamma_scale16 = 1;
9708 pm.test_gamma_background = 1; 9708 pm.test_gamma_background = 1;
9709 pm.test_gamma_alpha_mode = 1; 9709 pm.test_gamma_alpha_mode = 1;
9710 } 9710 }
9711 9711
9712 else if (pm.ngamma_tests == 0) 9712 else if (pm.ngamma_tests == 0)
9713 { 9713 {
9714 /* Nothing to test so turn everything off: */ 9714 /* Nothing to test so turn everything off: */
9715 pm.test_gamma_threshold = 0; 9715 pm.test_gamma_threshold = 0;
9716 pm.test_gamma_transform = 0; 9716 pm.test_gamma_transform = 0;
9717 pm.test_gamma_sbit = 0; 9717 pm.test_gamma_sbit = 0;
9718 pm.test_gamma_scale16 = 0; 9718 pm.test_gamma_scale16 = 0;
9719 pm.test_gamma_background = 0; 9719 pm.test_gamma_background = 0;
9720 pm.test_gamma_alpha_mode = 0; 9720 pm.test_gamma_alpha_mode = 0;
9721 } 9721 }
9722 9722
9723 Try 9723 Try
9724 { 9724 {
9725 /* Make useful base images */ 9725 /* Make useful base images */
9726 make_transform_images(&pm.this); 9726 make_transform_images(&pm.this);
9727 9727
9728 /* Perform the standard and gamma tests. */ 9728 /* Perform the standard and gamma tests. */
9729 if (pm.test_standard) 9729 if (pm.test_standard)
9730 { 9730 {
9731 perform_interlace_macro_validation(); 9731 perform_interlace_macro_validation();
9732 perform_formatting_test(&pm.this); 9732 perform_formatting_test(&pm.this);
9733 perform_standard_test(&pm); 9733 perform_standard_test(&pm);
9734 perform_error_test(&pm); 9734 perform_error_test(&pm);
9735 } 9735 }
9736 9736
9737 /* Various oddly sized images: */ 9737 /* Various oddly sized images: */
9738 if (pm.test_size) 9738 if (pm.test_size)
9739 { 9739 {
9740 make_size_images(&pm.this); 9740 make_size_images(&pm.this);
9741 perform_size_test(&pm); 9741 perform_size_test(&pm);
9742 } 9742 }
9743 9743
9744#ifdef PNG_READ_TRANSFORMS_SUPPORTED 9744#ifdef PNG_READ_TRANSFORMS_SUPPORTED
9745 /* Combinatorial transforms: */ 9745 /* Combinatorial transforms: */
9746 if (pm.test_transform) 9746 if (pm.test_transform)
9747 perform_transform_test(&pm); 9747 perform_transform_test(&pm);
9748#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ 9748#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
9749 9749
9750#ifdef PNG_READ_GAMMA_SUPPORTED 9750#ifdef PNG_READ_GAMMA_SUPPORTED
9751 if (pm.ngamma_tests > 0) 9751 if (pm.ngamma_tests > 0)
9752 perform_gamma_test(&pm, summary); 9752 perform_gamma_test(&pm, summary);
9753#endif 9753#endif
9754 } 9754 }
9755 9755
9756 Catch_anonymous 9756 Catch_anonymous
9757 { 9757 {
9758 fprintf(stderr, "pngvalid: test aborted (probably failed in cleanup)\n"); 9758 fprintf(stderr, "pngvalid: test aborted (probably failed in cleanup)\n");
9759 if (!pm.this.verbose) 9759 if (!pm.this.verbose)
9760 { 9760 {
9761 if (pm.this.error[0] != 0) 9761 if (pm.this.error[0] != 0)
9762 fprintf(stderr, "pngvalid: first error: %s\n", pm.this.error); 9762 fprintf(stderr, "pngvalid: first error: %s\n", pm.this.error);
9763 9763
9764 fprintf(stderr, "pngvalid: run with -v to see what happened\n"); 9764 fprintf(stderr, "pngvalid: run with -v to see what happened\n");
9765 } 9765 }
9766 exit(1); 9766 exit(1);
9767 } 9767 }
9768 9768
9769 if (summary) 9769 if (summary)
9770 { 9770 {
9771 printf("%s: %s (%s point arithmetic)\n", 9771 printf("%s: %s (%s point arithmetic)\n",
9772 (pm.this.nerrors || (pm.this.treat_warnings_as_errors && 9772 (pm.this.nerrors || (pm.this.treat_warnings_as_errors &&
9773 pm.this.nwarnings)) ? "FAIL" : "PASS", 9773 pm.this.nwarnings)) ? "FAIL" : "PASS",
9774 command, 9774 command,
9775#if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || PNG_LIBPNG_VER < 10500 9775#if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || PNG_LIBPNG_VER < 10500
9776 "floating" 9776 "floating"
9777#else 9777#else
9778 "fixed" 9778 "fixed"
9779#endif 9779#endif
9780 ); 9780 );
9781 } 9781 }
9782 9782
9783 if (memstats) 9783 if (memstats)
9784 { 9784 {
9785 printf("Allocated memory statistics (in bytes):\n" 9785 printf("Allocated memory statistics (in bytes):\n"
9786 "\tread %lu maximum single, %lu peak, %lu total\n" 9786 "\tread %lu maximum single, %lu peak, %lu total\n"
9787 "\twrite %lu maximum single, %lu peak, %lu total\n", 9787 "\twrite %lu maximum single, %lu peak, %lu total\n",
9788 (unsigned long)pm.this.read_memory_pool.max_max, 9788 (unsigned long)pm.this.read_memory_pool.max_max,
9789 (unsigned long)pm.this.read_memory_pool.max_limit, 9789 (unsigned long)pm.this.read_memory_pool.max_limit,
9790 (unsigned long)pm.this.read_memory_pool.max_total, 9790 (unsigned long)pm.this.read_memory_pool.max_total,
9791 (unsigned long)pm.this.write_memory_pool.max_max, 9791 (unsigned long)pm.this.write_memory_pool.max_max,
9792 (unsigned long)pm.this.write_memory_pool.max_limit, 9792 (unsigned long)pm.this.write_memory_pool.max_limit,
9793 (unsigned long)pm.this.write_memory_pool.max_total); 9793 (unsigned long)pm.this.write_memory_pool.max_total);
9794 } 9794 }
9795 9795
9796 /* Do this here to provoke memory corruption errors in memory not directly 9796 /* Do this here to provoke memory corruption errors in memory not directly
9797 * allocated by libpng - not a complete test, but better than nothing. 9797 * allocated by libpng - not a complete test, but better than nothing.
9798 */ 9798 */
9799 store_delete(&pm.this); 9799 store_delete(&pm.this);
9800 9800
9801 /* Error exit if there are any errors, and maybe if there are any 9801 /* Error exit if there are any errors, and maybe if there are any
9802 * warnings. 9802 * warnings.
9803 */ 9803 */
9804 if (pm.this.nerrors || (pm.this.treat_warnings_as_errors && 9804 if (pm.this.nerrors || (pm.this.treat_warnings_as_errors &&
9805 pm.this.nwarnings)) 9805 pm.this.nwarnings))
9806 { 9806 {
9807 if (!pm.this.verbose) 9807 if (!pm.this.verbose)
9808 fprintf(stderr, "pngvalid: %s\n", pm.this.error); 9808 fprintf(stderr, "pngvalid: %s\n", pm.this.error);
9809 9809
9810 fprintf(stderr, "pngvalid: %d errors, %d warnings\n", pm.this.nerrors, 9810 fprintf(stderr, "pngvalid: %d errors, %d warnings\n", pm.this.nerrors,
9811 pm.this.nwarnings); 9811 pm.this.nwarnings);
9812 9812
9813 exit(1); 9813 exit(1);
9814 } 9814 }
9815 9815
9816 /* Success case. */ 9816 /* Success case. */
9817 if (touch != NULL) 9817 if (touch != NULL)
9818 { 9818 {
9819 FILE *fsuccess = fopen(touch, "wt"); 9819 FILE *fsuccess = fopen(touch, "wt");
9820 9820
9821 if (fsuccess != NULL) 9821 if (fsuccess != NULL)
9822 { 9822 {
9823 int error = 0; 9823 int error = 0;
9824 fprintf(fsuccess, "PNG validation succeeded\n"); 9824 fprintf(fsuccess, "PNG validation succeeded\n");
9825 fflush(fsuccess); 9825 fflush(fsuccess);
9826 error = ferror(fsuccess); 9826 error = ferror(fsuccess);
9827 9827
9828 if (fclose(fsuccess) || error) 9828 if (fclose(fsuccess) || error)
9829 { 9829 {
9830 fprintf(stderr, "%s: write failed\n", touch); 9830 fprintf(stderr, "%s: write failed\n", touch);
9831 exit(1); 9831 exit(1);
9832 } 9832 }
9833 } 9833 }
9834 } 9834 }
9835 9835
9836 return 0; 9836 return 0;
9837} 9837}