VirtualBox

source: vbox/trunk/src/libs/libpng-1.6.45/contrib/libtests/pngvalid.c@ 107813

Last change on this file since 107813 was 107813, checked in by vboxsync, 3 weeks ago

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

  • Property svn:eol-style set to native
File size: 377.8 KB
Line 
1/* pngvalid.c - validate libpng by constructing then reading png files.
2 *
3 * Copyright (c) 2021 Cosmin Truta
4 * Copyright (c) 2014-2017 John Cunningham Bowler
5 *
6 * This code is released under the libpng license.
7 * For conditions of distribution and use, see the disclaimer
8 * and license in png.h
9 *
10 * NOTES:
11 * This is a C program that is intended to be linked against libpng. It
12 * generates bitmaps internally, stores them as PNG files (using the
13 * sequential write code) then reads them back (using the sequential
14 * read code) and validates that the result has the correct data.
15 *
16 * The program can be modified and extended to test the correctness of
17 * transformations performed by libpng.
18 */
19
20#define _POSIX_SOURCE 1
21#define _ISOC99_SOURCE 1 /* For floating point */
22#define _GNU_SOURCE 1 /* For the floating point exception extension */
23#define _BSD_SOURCE 1 /* For the floating point exception extension */
24#define _DEFAULT_SOURCE 1 /* For the floating point exception extension */
25
26#include <signal.h>
27#include <stdio.h>
28
29#if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H)
30# include <config.h>
31#endif
32
33#ifdef HAVE_FEENABLEEXCEPT /* from config.h, if included */
34# include <fenv.h>
35#endif
36
37#ifndef FE_DIVBYZERO
38# define FE_DIVBYZERO 0
39#endif
40#ifndef FE_INVALID
41# define FE_INVALID 0
42#endif
43#ifndef FE_OVERFLOW
44# define FE_OVERFLOW 0
45#endif
46
47/* Define the following to use this test against your installed libpng, rather
48 * than the one being built here:
49 */
50#ifdef PNG_FREESTANDING_TESTS
51# include <png.h>
52#else
53# include "../../png.h"
54#endif
55
56#ifdef PNG_ZLIB_HEADER
57# include PNG_ZLIB_HEADER
58#else
59# include <zlib.h> /* For crc32 */
60#endif
61
62/* 1.6.1 added support for the configure test harness, which uses 77 to indicate
63 * a skipped test, in earlier versions we need to succeed on a skipped test, so:
64 */
65#if PNG_LIBPNG_VER >= 10601 && defined(HAVE_CONFIG_H)
66# define SKIP 77
67#else
68# define SKIP 0
69#endif
70
71/* pngvalid requires write support and one of the fixed or floating point APIs.
72 * progressive read is also required currently as the progressive read pointer
73 * is used to record the 'display' structure.
74 */
75#if defined PNG_WRITE_SUPPORTED &&\
76 (defined PNG_PROGRESSIVE_READ_SUPPORTED) &&\
77 (defined PNG_FIXED_POINT_SUPPORTED || defined PNG_FLOATING_POINT_SUPPORTED)
78
79#if PNG_LIBPNG_VER < 10500
80/* This deliberately lacks the const. */
81typedef png_byte *png_const_bytep;
82
83/* This is copied from 1.5.1 png.h: */
84#define PNG_INTERLACE_ADAM7_PASSES 7
85#define PNG_PASS_START_ROW(pass) (((1U&~(pass))<<(3-((pass)>>1)))&7)
86#define PNG_PASS_START_COL(pass) (((1U& (pass))<<(3-(((pass)+1)>>1)))&7)
87#define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3)
88#define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3)
89#define PNG_PASS_ROWS(height, pass) (((height)+(((1<<PNG_PASS_ROW_SHIFT(pass))\
90 -1)-PNG_PASS_START_ROW(pass)))>>PNG_PASS_ROW_SHIFT(pass))
91#define PNG_PASS_COLS(width, pass) (((width)+(((1<<PNG_PASS_COL_SHIFT(pass))\
92 -1)-PNG_PASS_START_COL(pass)))>>PNG_PASS_COL_SHIFT(pass))
93#define PNG_ROW_FROM_PASS_ROW(yIn, pass) \
94 (((yIn)<<PNG_PASS_ROW_SHIFT(pass))+PNG_PASS_START_ROW(pass))
95#define PNG_COL_FROM_PASS_COL(xIn, pass) \
96 (((xIn)<<PNG_PASS_COL_SHIFT(pass))+PNG_PASS_START_COL(pass))
97#define PNG_PASS_MASK(pass,off) ( \
98 ((0x110145AFU>>(((7-(off))-(pass))<<2)) & 0xFU) | \
99 ((0x01145AF0U>>(((7-(off))-(pass))<<2)) & 0xF0U))
100#define PNG_ROW_IN_INTERLACE_PASS(y, pass) \
101 ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1)
102#define PNG_COL_IN_INTERLACE_PASS(x, pass) \
103 ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1)
104
105/* These are needed too for the default build: */
106#define PNG_WRITE_16BIT_SUPPORTED
107#define PNG_READ_16BIT_SUPPORTED
108
109/* This comes from pnglibconf.h after 1.5: */
110#define PNG_FP_1 100000
111#define PNG_GAMMA_THRESHOLD_FIXED\
112 ((png_fixed_point)(PNG_GAMMA_THRESHOLD * PNG_FP_1))
113#endif
114
115#if PNG_LIBPNG_VER < 10600
116 /* 1.6.0 constifies many APIs, the following exists to allow pngvalid to be
117 * compiled against earlier versions.
118 */
119# define png_const_structp png_structp
120#endif
121
122#ifndef RELEASE_BUILD
123 /* RELEASE_BUILD is true for releases and release candidates: */
124# define RELEASE_BUILD (PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC)
125#endif
126#if RELEASE_BUILD
127# define debugonly(something)
128#else /* !RELEASE_BUILD */
129# define debugonly(something) something
130#endif /* !RELEASE_BUILD */
131
132#include <float.h> /* For floating point constants */
133#include <stdlib.h> /* For malloc */
134#include <string.h> /* For memcpy, memset */
135#include <math.h> /* For floor */
136
137/* Convenience macros. */
138#define CHUNK(a,b,c,d) (((a)<<24)+((b)<<16)+((c)<<8)+(d))
139#define CHUNK_IHDR CHUNK(73,72,68,82)
140#define CHUNK_PLTE CHUNK(80,76,84,69)
141#define CHUNK_IDAT CHUNK(73,68,65,84)
142#define CHUNK_IEND CHUNK(73,69,78,68)
143#define CHUNK_cHRM CHUNK(99,72,82,77)
144#define CHUNK_gAMA CHUNK(103,65,77,65)
145#define CHUNK_sBIT CHUNK(115,66,73,84)
146#define CHUNK_sRGB CHUNK(115,82,71,66)
147
148/* Unused formal parameter errors are removed using the following macro which is
149 * expected to have no bad effects on performance.
150 */
151#ifndef UNUSED
152# if defined(__GNUC__) || defined(_MSC_VER)
153# define UNUSED(param) (void)param;
154# else
155# define UNUSED(param)
156# endif
157#endif
158
159/***************************** EXCEPTION HANDLING *****************************/
160#ifdef PNG_FREESTANDING_TESTS
161# include <cexcept.h>
162#else
163# include "../visupng/cexcept.h"
164#endif
165
166#ifdef __cplusplus
167# define this not_the_cpp_this
168# define new not_the_cpp_new
169# define voidcast(type, value) static_cast<type>(value)
170#else
171# define voidcast(type, value) (value)
172#endif /* __cplusplus */
173
174struct png_store;
175define_exception_type(struct png_store*);
176
177/* The following are macros to reduce typing everywhere where the well known
178 * name 'the_exception_context' must be defined.
179 */
180#define anon_context(ps) struct exception_context *the_exception_context = \
181 &(ps)->exception_context
182#define context(ps,fault) anon_context(ps); png_store *fault
183
184/* This macro returns the number of elements in an array as an (unsigned int),
185 * it is necessary to avoid the inability of certain versions of GCC to use
186 * the value of a compile-time constant when performing range checks. It must
187 * be passed an array name.
188 */
189#define ARRAY_SIZE(a) ((unsigned int)((sizeof (a))/(sizeof (a)[0])))
190
191/* GCC BUG 66447 (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66447) requires
192 * some broken GCC versions to be fixed up to avoid invalid whining about auto
193 * variables that are *not* changed within the scope of a setjmp being changed.
194 *
195 * Feel free to extend the list of broken versions.
196 */
197#define is_gnu(major,minor)\
198 (defined __GNUC__) && __GNUC__ == (major) && __GNUC_MINOR__ == (minor)
199#define is_gnu_patch(major,minor,patch)\
200 is_gnu(major,minor) && __GNUC_PATCHLEVEL__ == 0
201/* For the moment just do it always; all versions of GCC seem to be broken: */
202#ifdef __GNUC__
203 const void * volatile make_volatile_for_gnu;
204# define gnu_volatile(x) make_volatile_for_gnu = &x;
205#else /* !GNUC broken versions */
206# define gnu_volatile(x)
207#endif /* !GNUC broken versions */
208
209/******************************* UTILITIES ************************************/
210/* Error handling is particularly problematic in production code - error
211 * handlers often themselves have bugs which lead to programs that detect
212 * minor errors crashing. The following functions deal with one very
213 * common class of errors in error handlers - attempting to format error or
214 * warning messages into buffers that are too small.
215 */
216static size_t safecat(char *buffer, size_t bufsize, size_t pos,
217 const char *cat)
218{
219 while (pos < bufsize && cat != NULL && *cat != 0)
220 buffer[pos++] = *cat++;
221
222 if (pos >= bufsize)
223 pos = bufsize-1;
224
225 buffer[pos] = 0;
226 return pos;
227}
228
229static size_t safecatn(char *buffer, size_t bufsize, size_t pos, int n)
230{
231 char number[64];
232 sprintf(number, "%d", n);
233 return safecat(buffer, bufsize, pos, number);
234}
235
236#ifdef PNG_READ_TRANSFORMS_SUPPORTED
237static size_t safecatd(char *buffer, size_t bufsize, size_t pos, double d,
238 int precision)
239{
240 char number[64];
241 sprintf(number, "%.*f", precision, d);
242 return safecat(buffer, bufsize, pos, number);
243}
244#endif
245
246static const char invalid[] = "invalid";
247static const char sep[] = ": ";
248
249static const char *colour_types[8] =
250{
251 "grayscale", invalid, "truecolour", "indexed-colour",
252 "grayscale with alpha", invalid, "truecolour with alpha", invalid
253};
254
255#ifdef PNG_READ_TRANSFORMS_SUPPORTED
256/* Convert a double precision value to fixed point. */
257static png_fixed_point
258fix(double d)
259{
260 d = floor(d * PNG_FP_1 + .5);
261 return (png_fixed_point)d;
262}
263#endif /* PNG_READ_SUPPORTED */
264
265/* Generate random bytes. This uses a boring repeatable algorithm and it
266 * is implemented here so that it gives the same set of numbers on every
267 * architecture. It's a linear congruential generator (Knuth or Sedgewick
268 * "Algorithms") but it comes from the 'feedback taps' table in Horowitz and
269 * Hill, "The Art of Electronics" (Pseudo-Random Bit Sequences and Noise
270 * Generation.)
271 */
272static void
273make_random_bytes(png_uint_32* seed, void* pv, size_t size)
274{
275 png_uint_32 u0 = seed[0], u1 = seed[1];
276 png_bytep bytes = voidcast(png_bytep, pv);
277
278 /* There are thirty three bits, the next bit in the sequence is bit-33 XOR
279 * bit-20. The top 1 bit is in u1, the bottom 32 are in u0.
280 */
281 size_t i;
282 for (i=0; i<size; ++i)
283 {
284 /* First generate 8 new bits then shift them in at the end. */
285 png_uint_32 u = ((u0 >> (20-8)) ^ ((u1 << 7) | (u0 >> (32-7)))) & 0xff;
286 u1 <<= 8;
287 u1 |= u0 >> 24;
288 u0 <<= 8;
289 u0 |= u;
290 *bytes++ = (png_byte)u;
291 }
292
293 seed[0] = u0;
294 seed[1] = u1;
295}
296
297static void
298make_four_random_bytes(png_uint_32* seed, png_bytep bytes)
299{
300 make_random_bytes(seed, bytes, 4);
301}
302
303#if defined PNG_READ_SUPPORTED || defined PNG_WRITE_tRNS_SUPPORTED ||\
304 defined PNG_WRITE_FILTER_SUPPORTED
305static void
306randomize_bytes(void *pv, size_t size)
307{
308 static png_uint_32 random_seed[2] = {0x56789abc, 0xd};
309 make_random_bytes(random_seed, pv, size);
310}
311
312#define R8(this) randomize_bytes(&(this), sizeof (this))
313
314#ifdef PNG_READ_SUPPORTED
315static png_byte
316random_byte(void)
317{
318 unsigned char b1[1];
319 randomize_bytes(b1, sizeof b1);
320 return b1[0];
321}
322#endif /* READ */
323
324static png_uint_16
325random_u16(void)
326{
327 unsigned char b2[2];
328 randomize_bytes(b2, sizeof b2);
329 return png_get_uint_16(b2);
330}
331
332#if defined PNG_READ_RGB_TO_GRAY_SUPPORTED ||\
333 defined PNG_READ_FILLER_SUPPORTED
334static png_uint_32
335random_u32(void)
336{
337 unsigned char b4[4];
338 randomize_bytes(b4, sizeof b4);
339 return png_get_uint_32(b4);
340}
341#endif /* READ_FILLER || READ_RGB_TO_GRAY */
342
343#endif /* READ || WRITE_tRNS || WRITE_FILTER */
344
345#if defined PNG_READ_TRANSFORMS_SUPPORTED ||\
346 defined PNG_WRITE_FILTER_SUPPORTED
347static unsigned int
348random_mod(unsigned int max)
349{
350 return random_u16() % max; /* 0 .. max-1 */
351}
352#endif /* READ_TRANSFORMS || WRITE_FILTER */
353
354#if (defined PNG_READ_RGB_TO_GRAY_SUPPORTED) ||\
355 (defined PNG_READ_FILLER_SUPPORTED)
356static int
357random_choice(void)
358{
359 return random_byte() & 1;
360}
361#endif /* READ_RGB_TO_GRAY || READ_FILLER */
362
363/* A numeric ID based on PNG file characteristics. The 'do_interlace' field
364 * simply records whether pngvalid did the interlace itself or whether it
365 * was done by libpng. Width and height must be less than 256. 'palette' is an
366 * index of the palette to use for formats with a palette otherwise a boolean
367 * indicating if a tRNS chunk was generated.
368 */
369#define FILEID(col, depth, palette, interlace, width, height, do_interlace) \
370 ((png_uint_32)((col) + ((depth)<<3) + ((palette)<<8) + ((interlace)<<13) + \
371 (((do_interlace)!=0)<<15) + ((width)<<16) + ((height)<<24)))
372
373#define COL_FROM_ID(id) ((png_byte)((id)& 0x7U))
374#define DEPTH_FROM_ID(id) ((png_byte)(((id) >> 3) & 0x1fU))
375#define PALETTE_FROM_ID(id) (((id) >> 8) & 0x1f)
376#define INTERLACE_FROM_ID(id) ((png_byte)(((id) >> 13) & 0x3))
377#define DO_INTERLACE_FROM_ID(id) ((int)(((id)>>15) & 1))
378#define WIDTH_FROM_ID(id) (((id)>>16) & 0xff)
379#define HEIGHT_FROM_ID(id) (((id)>>24) & 0xff)
380
381/* Utility to construct a standard name for a standard image. */
382static size_t
383standard_name(char *buffer, size_t bufsize, size_t pos, png_byte colour_type,
384 int bit_depth, unsigned int npalette, int interlace_type,
385 png_uint_32 w, png_uint_32 h, int do_interlace)
386{
387 pos = safecat(buffer, bufsize, pos, colour_types[colour_type]);
388 if (colour_type == 3) /* must have a palette */
389 {
390 pos = safecat(buffer, bufsize, pos, "[");
391 pos = safecatn(buffer, bufsize, pos, npalette);
392 pos = safecat(buffer, bufsize, pos, "]");
393 }
394
395 else if (npalette != 0)
396 pos = safecat(buffer, bufsize, pos, "+tRNS");
397
398 pos = safecat(buffer, bufsize, pos, " ");
399 pos = safecatn(buffer, bufsize, pos, bit_depth);
400 pos = safecat(buffer, bufsize, pos, " bit");
401
402 if (interlace_type != PNG_INTERLACE_NONE)
403 {
404 pos = safecat(buffer, bufsize, pos, " interlaced");
405 if (do_interlace)
406 pos = safecat(buffer, bufsize, pos, "(pngvalid)");
407 else
408 pos = safecat(buffer, bufsize, pos, "(libpng)");
409 }
410
411 if (w > 0 || h > 0)
412 {
413 pos = safecat(buffer, bufsize, pos, " ");
414 pos = safecatn(buffer, bufsize, pos, w);
415 pos = safecat(buffer, bufsize, pos, "x");
416 pos = safecatn(buffer, bufsize, pos, h);
417 }
418
419 return pos;
420}
421
422static size_t
423standard_name_from_id(char *buffer, size_t bufsize, size_t pos, png_uint_32 id)
424{
425 return standard_name(buffer, bufsize, pos, COL_FROM_ID(id),
426 DEPTH_FROM_ID(id), PALETTE_FROM_ID(id), INTERLACE_FROM_ID(id),
427 WIDTH_FROM_ID(id), HEIGHT_FROM_ID(id), DO_INTERLACE_FROM_ID(id));
428}
429
430/* Convenience API and defines to list valid formats. Note that 16 bit read and
431 * write support is required to do 16 bit read tests (we must be able to make a
432 * 16 bit image to test!)
433 */
434#ifdef PNG_WRITE_16BIT_SUPPORTED
435# define WRITE_BDHI 4
436# ifdef PNG_READ_16BIT_SUPPORTED
437# define READ_BDHI 4
438# define DO_16BIT
439# endif
440#else
441# define WRITE_BDHI 3
442#endif
443#ifndef DO_16BIT
444# define READ_BDHI 3
445#endif
446
447/* The following defines the number of different palettes to generate for
448 * each log bit depth of a colour type 3 standard image.
449 */
450#define PALETTE_COUNT(bit_depth) ((bit_depth) > 4 ? 1U : 16U)
451
452static int
453next_format(png_bytep colour_type, png_bytep bit_depth,
454 unsigned int* palette_number, int low_depth_gray, int tRNS)
455{
456 if (*bit_depth == 0)
457 {
458 *colour_type = 0;
459 if (low_depth_gray)
460 *bit_depth = 1;
461 else
462 *bit_depth = 8;
463 *palette_number = 0;
464 return 1;
465 }
466
467 if (*colour_type < 4/*no alpha channel*/)
468 {
469 /* Add multiple palettes for colour type 3, one image with tRNS
470 * and one without for other non-alpha formats:
471 */
472 unsigned int pn = ++*palette_number;
473 png_byte ct = *colour_type;
474
475 if (((ct == 0/*GRAY*/ || ct/*RGB*/ == 2) && tRNS && pn < 2) ||
476 (ct == 3/*PALETTE*/ && pn < PALETTE_COUNT(*bit_depth)))
477 return 1;
478
479 /* No: next bit depth */
480 *palette_number = 0;
481 }
482
483 *bit_depth = (png_byte)(*bit_depth << 1);
484
485 /* Palette images are restricted to 8 bit depth */
486 if (*bit_depth <= 8
487#ifdef DO_16BIT
488 || (*colour_type != 3 && *bit_depth <= 16)
489#endif
490 )
491 return 1;
492
493 /* Move to the next color type, or return 0 at the end. */
494 switch (*colour_type)
495 {
496 case 0:
497 *colour_type = 2;
498 *bit_depth = 8;
499 return 1;
500
501 case 2:
502 *colour_type = 3;
503 *bit_depth = 1;
504 return 1;
505
506 case 3:
507 *colour_type = 4;
508 *bit_depth = 8;
509 return 1;
510
511 case 4:
512 *colour_type = 6;
513 *bit_depth = 8;
514 return 1;
515
516 default:
517 return 0;
518 }
519}
520
521#ifdef PNG_READ_TRANSFORMS_SUPPORTED
522static unsigned int
523sample(png_const_bytep row, png_byte colour_type, png_byte bit_depth,
524 png_uint_32 x, unsigned int sample_index, int swap16, int littleendian)
525{
526 png_uint_32 bit_index, result;
527
528 /* Find a sample index for the desired sample: */
529 x *= bit_depth;
530 bit_index = x;
531
532 if ((colour_type & 1) == 0) /* !palette */
533 {
534 if (colour_type & 2)
535 bit_index *= 3;
536
537 if (colour_type & 4)
538 bit_index += x; /* Alpha channel */
539
540 /* Multiple channels; select one: */
541 if (colour_type & (2+4))
542 bit_index += sample_index * bit_depth;
543 }
544
545 /* Return the sample from the row as an integer. */
546 row += bit_index >> 3;
547 result = *row;
548
549 if (bit_depth == 8)
550 return result;
551
552 else if (bit_depth > 8)
553 {
554 if (swap16)
555 return (*++row << 8) + result;
556 else
557 return (result << 8) + *++row;
558 }
559
560 /* Less than 8 bits per sample. By default PNG has the big end of
561 * the egg on the left of the screen, but if littleendian is set
562 * then the big end is on the right.
563 */
564 bit_index &= 7;
565
566 if (!littleendian)
567 bit_index = 8-bit_index-bit_depth;
568
569 return (result >> bit_index) & ((1U<<bit_depth)-1);
570}
571#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
572
573/* Copy a single pixel, of a given size, from one buffer to another -
574 * while this is basically bit addressed there is an implicit assumption
575 * that pixels 8 or more bits in size are byte aligned and that pixels
576 * do not otherwise cross byte boundaries. (This is, so far as I know,
577 * universally true in bitmap computer graphics. [JCB 20101212])
578 *
579 * NOTE: The to and from buffers may be the same.
580 */
581static void
582pixel_copy(png_bytep toBuffer, png_uint_32 toIndex,
583 png_const_bytep fromBuffer, png_uint_32 fromIndex, unsigned int pixelSize,
584 int littleendian)
585{
586 /* Assume we can multiply by 'size' without overflow because we are
587 * just working in a single buffer.
588 */
589 toIndex *= pixelSize;
590 fromIndex *= pixelSize;
591 if (pixelSize < 8) /* Sub-byte */
592 {
593 /* Mask to select the location of the copied pixel: */
594 unsigned int destMask = ((1U<<pixelSize)-1) <<
595 (littleendian ? toIndex&7 : 8-pixelSize-(toIndex&7));
596 /* The following read the entire pixels and clears the extra: */
597 unsigned int destByte = toBuffer[toIndex >> 3] & ~destMask;
598 unsigned int sourceByte = fromBuffer[fromIndex >> 3];
599
600 /* Don't rely on << or >> supporting '0' here, just in case: */
601 fromIndex &= 7;
602 if (littleendian)
603 {
604 if (fromIndex > 0) sourceByte >>= fromIndex;
605 if ((toIndex & 7) > 0) sourceByte <<= toIndex & 7;
606 }
607
608 else
609 {
610 if (fromIndex > 0) sourceByte <<= fromIndex;
611 if ((toIndex & 7) > 0) sourceByte >>= toIndex & 7;
612 }
613
614 toBuffer[toIndex >> 3] = (png_byte)(destByte | (sourceByte & destMask));
615 }
616 else /* One or more bytes */
617 memmove(toBuffer+(toIndex>>3), fromBuffer+(fromIndex>>3), pixelSize>>3);
618}
619
620#ifdef PNG_READ_SUPPORTED
621/* Copy a complete row of pixels, taking into account potential partial
622 * bytes at the end.
623 */
624static void
625row_copy(png_bytep toBuffer, png_const_bytep fromBuffer, unsigned int bitWidth,
626 int littleendian)
627{
628 memcpy(toBuffer, fromBuffer, bitWidth >> 3);
629
630 if ((bitWidth & 7) != 0)
631 {
632 unsigned int mask;
633
634 toBuffer += bitWidth >> 3;
635 fromBuffer += bitWidth >> 3;
636 if (littleendian)
637 mask = 0xff << (bitWidth & 7);
638 else
639 mask = 0xff >> (bitWidth & 7);
640 *toBuffer = (png_byte)((*toBuffer & mask) | (*fromBuffer & ~mask));
641 }
642}
643
644/* Compare pixels - they are assumed to start at the first byte in the
645 * given buffers.
646 */
647static int
648pixel_cmp(png_const_bytep pa, png_const_bytep pb, png_uint_32 bit_width)
649{
650#if PNG_LIBPNG_VER < 10506
651 if (memcmp(pa, pb, bit_width>>3) == 0)
652 {
653 png_uint_32 p;
654
655 if ((bit_width & 7) == 0) return 0;
656
657 /* Ok, any differences? */
658 p = pa[bit_width >> 3];
659 p ^= pb[bit_width >> 3];
660
661 if (p == 0) return 0;
662
663 /* There are, but they may not be significant, remove the bits
664 * after the end (the low order bits in PNG.)
665 */
666 bit_width &= 7;
667 p >>= 8-bit_width;
668
669 if (p == 0) return 0;
670 }
671#else
672 /* From libpng-1.5.6 the overwrite should be fixed, so compare the trailing
673 * bits too:
674 */
675 if (memcmp(pa, pb, (bit_width+7)>>3) == 0)
676 return 0;
677#endif
678
679 /* Return the index of the changed byte. */
680 {
681 png_uint_32 where = 0;
682
683 while (pa[where] == pb[where]) ++where;
684 return 1+where;
685 }
686}
687#endif /* PNG_READ_SUPPORTED */
688
689/*************************** BASIC PNG FILE WRITING ***************************/
690/* A png_store takes data from the sequential writer or provides data
691 * to the sequential reader. It can also store the result of a PNG
692 * write for later retrieval.
693 */
694#define STORE_BUFFER_SIZE 500 /* arbitrary */
695typedef struct png_store_buffer
696{
697 struct png_store_buffer* prev; /* NOTE: stored in reverse order */
698 png_byte buffer[STORE_BUFFER_SIZE];
699} png_store_buffer;
700
701#define FILE_NAME_SIZE 64
702
703typedef struct store_palette_entry /* record of a single palette entry */
704{
705 png_byte red;
706 png_byte green;
707 png_byte blue;
708 png_byte alpha;
709} store_palette_entry, store_palette[256];
710
711typedef struct png_store_file
712{
713 struct png_store_file* next; /* as many as you like... */
714 char name[FILE_NAME_SIZE];
715 unsigned int IDAT_bits; /* Number of bits in IDAT size */
716 png_uint_32 IDAT_size; /* Total size of IDAT data */
717 png_uint_32 id; /* must be correct (see FILEID) */
718 size_t datacount; /* In this (the last) buffer */
719 png_store_buffer data; /* Last buffer in file */
720 int npalette; /* Number of entries in palette */
721 store_palette_entry* palette; /* May be NULL */
722} png_store_file;
723
724/* The following is a pool of memory allocated by a single libpng read or write
725 * operation.
726 */
727typedef struct store_pool
728{
729 struct png_store *store; /* Back pointer */
730 struct store_memory *list; /* List of allocated memory */
731 png_byte mark[4]; /* Before and after data */
732
733 /* Statistics for this run. */
734 png_alloc_size_t max; /* Maximum single allocation */
735 png_alloc_size_t current; /* Current allocation */
736 png_alloc_size_t limit; /* Highest current allocation */
737 png_alloc_size_t total; /* Total allocation */
738
739 /* Overall statistics (retained across successive runs). */
740 png_alloc_size_t max_max;
741 png_alloc_size_t max_limit;
742 png_alloc_size_t max_total;
743} store_pool;
744
745typedef struct png_store
746{
747 /* For cexcept.h exception handling - simply store one of these;
748 * the context is a self pointer but it may point to a different
749 * png_store (in fact it never does in this program.)
750 */
751 struct exception_context
752 exception_context;
753
754 unsigned int verbose :1;
755 unsigned int treat_warnings_as_errors :1;
756 unsigned int expect_error :1;
757 unsigned int expect_warning :1;
758 unsigned int saw_warning :1;
759 unsigned int speed :1;
760 unsigned int progressive :1; /* use progressive read */
761 unsigned int validated :1; /* used as a temporary flag */
762 int nerrors;
763 int nwarnings;
764 int noptions; /* number of options below: */
765 struct {
766 unsigned char option; /* option number, 0..30 */
767 unsigned char setting; /* setting (unset,invalid,on,off) */
768 } options[16];
769 char test[128]; /* Name of test */
770 char error[256];
771
772 /* Share fields */
773 png_uint_32 chunklen; /* Length of chunk+overhead (chunkpos >= 8) */
774 png_uint_32 chunktype;/* Type of chunk (valid if chunkpos >= 4) */
775 png_uint_32 chunkpos; /* Position in chunk */
776 png_uint_32 IDAT_size;/* Accumulated IDAT size in .new */
777 unsigned int IDAT_bits;/* Cache of the file store value */
778
779 /* Read fields */
780 png_structp pread; /* Used to read a saved file */
781 png_infop piread;
782 png_store_file* current; /* Set when reading */
783 png_store_buffer* next; /* Set when reading */
784 size_t readpos; /* Position in *next */
785 png_byte* image; /* Buffer for reading interlaced images */
786 size_t cb_image; /* Size of this buffer */
787 size_t cb_row; /* Row size of the image(s) */
788 uLong IDAT_crc;
789 png_uint_32 IDAT_len; /* Used when re-chunking IDAT chunks */
790 png_uint_32 IDAT_pos; /* Used when re-chunking IDAT chunks */
791 png_uint_32 image_h; /* Number of rows in a single image */
792 store_pool read_memory_pool;
793
794 /* Write fields */
795 png_store_file* saved;
796 png_structp pwrite; /* Used when writing a new file */
797 png_infop piwrite;
798 size_t writepos; /* Position in .new */
799 char wname[FILE_NAME_SIZE];
800 png_store_buffer new; /* The end of the new PNG file being written. */
801 store_pool write_memory_pool;
802 store_palette_entry* palette;
803 int npalette;
804} png_store;
805
806/* Initialization and cleanup */
807static void
808store_pool_mark(png_bytep mark)
809{
810 static png_uint_32 store_seed[2] = { 0x12345678, 1};
811
812 make_four_random_bytes(store_seed, mark);
813}
814
815#ifdef PNG_READ_TRANSFORMS_SUPPORTED
816/* Use this for random 32 bit values; this function makes sure the result is
817 * non-zero.
818 */
819static png_uint_32
820random_32(void)
821{
822
823 for (;;)
824 {
825 png_byte mark[4];
826 png_uint_32 result;
827
828 store_pool_mark(mark);
829 result = png_get_uint_32(mark);
830
831 if (result != 0)
832 return result;
833 }
834}
835#endif /* PNG_READ_SUPPORTED */
836
837static void
838store_pool_init(png_store *ps, store_pool *pool)
839{
840 memset(pool, 0, sizeof *pool);
841
842 pool->store = ps;
843 pool->list = NULL;
844 pool->max = pool->current = pool->limit = pool->total = 0;
845 pool->max_max = pool->max_limit = pool->max_total = 0;
846 store_pool_mark(pool->mark);
847}
848
849static void
850store_init(png_store* ps)
851{
852 memset(ps, 0, sizeof *ps);
853 init_exception_context(&ps->exception_context);
854 store_pool_init(ps, &ps->read_memory_pool);
855 store_pool_init(ps, &ps->write_memory_pool);
856 ps->verbose = 0;
857 ps->treat_warnings_as_errors = 0;
858 ps->expect_error = 0;
859 ps->expect_warning = 0;
860 ps->saw_warning = 0;
861 ps->speed = 0;
862 ps->progressive = 0;
863 ps->validated = 0;
864 ps->nerrors = ps->nwarnings = 0;
865 ps->pread = NULL;
866 ps->piread = NULL;
867 ps->saved = ps->current = NULL;
868 ps->next = NULL;
869 ps->readpos = 0;
870 ps->image = NULL;
871 ps->cb_image = 0;
872 ps->cb_row = 0;
873 ps->image_h = 0;
874 ps->pwrite = NULL;
875 ps->piwrite = NULL;
876 ps->writepos = 0;
877 ps->chunkpos = 8;
878 ps->chunktype = 0;
879 ps->chunklen = 16;
880 ps->IDAT_size = 0;
881 ps->IDAT_bits = 0;
882 ps->new.prev = NULL;
883 ps->palette = NULL;
884 ps->npalette = 0;
885 ps->noptions = 0;
886}
887
888static void
889store_freebuffer(png_store_buffer* psb)
890{
891 if (psb->prev)
892 {
893 store_freebuffer(psb->prev);
894 free(psb->prev);
895 psb->prev = NULL;
896 }
897}
898
899static void
900store_freenew(png_store *ps)
901{
902 store_freebuffer(&ps->new);
903 ps->writepos = 0;
904 ps->chunkpos = 8;
905 ps->chunktype = 0;
906 ps->chunklen = 16;
907 ps->IDAT_size = 0;
908 ps->IDAT_bits = 0;
909 if (ps->palette != NULL)
910 {
911 free(ps->palette);
912 ps->palette = NULL;
913 ps->npalette = 0;
914 }
915}
916
917static void
918store_storenew(png_store *ps)
919{
920 png_store_buffer *pb;
921
922 pb = voidcast(png_store_buffer*, malloc(sizeof *pb));
923
924 if (pb == NULL)
925 png_error(ps->pwrite, "store new: OOM");
926
927 *pb = ps->new;
928 ps->new.prev = pb;
929 ps->writepos = 0;
930}
931
932static void
933store_freefile(png_store_file **ppf)
934{
935 if (*ppf != NULL)
936 {
937 store_freefile(&(*ppf)->next);
938
939 store_freebuffer(&(*ppf)->data);
940 (*ppf)->datacount = 0;
941 if ((*ppf)->palette != NULL)
942 {
943 free((*ppf)->palette);
944 (*ppf)->palette = NULL;
945 (*ppf)->npalette = 0;
946 }
947 free(*ppf);
948 *ppf = NULL;
949 }
950}
951
952static unsigned int
953bits_of(png_uint_32 num)
954{
955 /* Return the number of bits in 'num' */
956 unsigned int b = 0;
957
958 if (num & 0xffff0000U) b += 16U, num >>= 16;
959 if (num & 0xff00U) b += 8U, num >>= 8;
960 if (num & 0xf0U) b += 4U, num >>= 4;
961 if (num & 0xcU) b += 2U, num >>= 2;
962 if (num & 0x2U) ++b, num >>= 1;
963 if (num) ++b;
964
965 return b; /* 0..32 */
966}
967
968/* Main interface to file storage, after writing a new PNG file (see the API
969 * below) call store_storefile to store the result with the given name and id.
970 */
971static void
972store_storefile(png_store *ps, png_uint_32 id)
973{
974 png_store_file *pf;
975
976 if (ps->chunkpos != 0U || ps->chunktype != 0U || ps->chunklen != 0U ||
977 ps->IDAT_size == 0)
978 png_error(ps->pwrite, "storefile: incomplete write");
979
980 pf = voidcast(png_store_file*, malloc(sizeof *pf));
981 if (pf == NULL)
982 png_error(ps->pwrite, "storefile: OOM");
983 safecat(pf->name, sizeof pf->name, 0, ps->wname);
984 pf->id = id;
985 pf->data = ps->new;
986 pf->datacount = ps->writepos;
987 pf->IDAT_size = ps->IDAT_size;
988 pf->IDAT_bits = bits_of(ps->IDAT_size);
989 /* Because the IDAT always has zlib header stuff this must be true: */
990 if (pf->IDAT_bits == 0U)
991 png_error(ps->pwrite, "storefile: 0 sized IDAT");
992 ps->new.prev = NULL;
993 ps->writepos = 0;
994 ps->chunkpos = 8;
995 ps->chunktype = 0;
996 ps->chunklen = 16;
997 ps->IDAT_size = 0;
998 pf->palette = ps->palette;
999 pf->npalette = ps->npalette;
1000 ps->palette = 0;
1001 ps->npalette = 0;
1002
1003 /* And save it. */
1004 pf->next = ps->saved;
1005 ps->saved = pf;
1006}
1007
1008/* Generate an error message (in the given buffer) */
1009static size_t
1010store_message(png_store *ps, png_const_structp pp, char *buffer, size_t bufsize,
1011 size_t pos, const char *msg)
1012{
1013 if (pp != NULL && pp == ps->pread)
1014 {
1015 /* Reading a file */
1016 pos = safecat(buffer, bufsize, pos, "read: ");
1017
1018 if (ps->current != NULL)
1019 {
1020 pos = safecat(buffer, bufsize, pos, ps->current->name);
1021 pos = safecat(buffer, bufsize, pos, sep);
1022 }
1023 }
1024
1025 else if (pp != NULL && pp == ps->pwrite)
1026 {
1027 /* Writing a file */
1028 pos = safecat(buffer, bufsize, pos, "write: ");
1029 pos = safecat(buffer, bufsize, pos, ps->wname);
1030 pos = safecat(buffer, bufsize, pos, sep);
1031 }
1032
1033 else
1034 {
1035 /* Neither reading nor writing (or a memory error in struct delete) */
1036 pos = safecat(buffer, bufsize, pos, "pngvalid: ");
1037 }
1038
1039 if (ps->test[0] != 0)
1040 {
1041 pos = safecat(buffer, bufsize, pos, ps->test);
1042 pos = safecat(buffer, bufsize, pos, sep);
1043 }
1044 pos = safecat(buffer, bufsize, pos, msg);
1045 return pos;
1046}
1047
1048/* Verbose output to the error stream: */
1049static void
1050store_verbose(png_store *ps, png_const_structp pp, png_const_charp prefix,
1051 png_const_charp message)
1052{
1053 char buffer[512];
1054
1055 if (prefix)
1056 fputs(prefix, stderr);
1057
1058 (void)store_message(ps, pp, buffer, sizeof buffer, 0, message);
1059 fputs(buffer, stderr);
1060 fputc('\n', stderr);
1061}
1062
1063/* Log an error or warning - the relevant count is always incremented. */
1064static void
1065store_log(png_store* ps, png_const_structp pp, png_const_charp message,
1066 int is_error)
1067{
1068 /* The warning is copied to the error buffer if there are no errors and it is
1069 * the first warning. The error is copied to the error buffer if it is the
1070 * first error (overwriting any prior warnings).
1071 */
1072 if (is_error ? (ps->nerrors)++ == 0 :
1073 (ps->nwarnings)++ == 0 && ps->nerrors == 0)
1074 store_message(ps, pp, ps->error, sizeof ps->error, 0, message);
1075
1076 if (ps->verbose)
1077 store_verbose(ps, pp, is_error ? "error: " : "warning: ", message);
1078}
1079
1080#ifdef PNG_READ_SUPPORTED
1081/* Internal error function, called with a png_store but no libpng stuff. */
1082static void
1083internal_error(png_store *ps, png_const_charp message)
1084{
1085 store_log(ps, NULL, message, 1 /* error */);
1086
1087 /* And finally throw an exception. */
1088 {
1089 struct exception_context *the_exception_context = &ps->exception_context;
1090 Throw ps;
1091 }
1092}
1093#endif /* PNG_READ_SUPPORTED */
1094
1095/* Functions to use as PNG callbacks. */
1096static void PNGCBAPI
1097store_error(png_structp ppIn, png_const_charp message) /* PNG_NORETURN */
1098{
1099 png_const_structp pp = ppIn;
1100 png_store *ps = voidcast(png_store*, png_get_error_ptr(pp));
1101
1102 if (!ps->expect_error)
1103 store_log(ps, pp, message, 1 /* error */);
1104
1105 /* And finally throw an exception. */
1106 {
1107 struct exception_context *the_exception_context = &ps->exception_context;
1108 Throw ps;
1109 }
1110}
1111
1112static void PNGCBAPI
1113store_warning(png_structp ppIn, png_const_charp message)
1114{
1115 png_const_structp pp = ppIn;
1116 png_store *ps = voidcast(png_store*, png_get_error_ptr(pp));
1117
1118 if (!ps->expect_warning)
1119 store_log(ps, pp, message, 0 /* warning */);
1120 else
1121 ps->saw_warning = 1;
1122}
1123
1124/* These somewhat odd functions are used when reading an image to ensure that
1125 * the buffer is big enough, the png_structp is for errors.
1126 */
1127/* Return a single row from the correct image. */
1128static png_bytep
1129store_image_row(const png_store* ps, png_const_structp pp, int nImage,
1130 png_uint_32 y)
1131{
1132 size_t coffset = (nImage * ps->image_h + y) * (ps->cb_row + 5) + 2;
1133
1134 if (ps->image == NULL)
1135 png_error(pp, "no allocated image");
1136
1137 if (coffset + ps->cb_row + 3 > ps->cb_image)
1138 png_error(pp, "image too small");
1139
1140 return ps->image + coffset;
1141}
1142
1143static void
1144store_image_free(png_store *ps, png_const_structp pp)
1145{
1146 if (ps->image != NULL)
1147 {
1148 png_bytep image = ps->image;
1149
1150 if (image[-1] != 0xed || image[ps->cb_image] != 0xfe)
1151 {
1152 if (pp != NULL)
1153 png_error(pp, "png_store image overwrite (1)");
1154 else
1155 store_log(ps, NULL, "png_store image overwrite (2)", 1);
1156 }
1157
1158 ps->image = NULL;
1159 ps->cb_image = 0;
1160 --image;
1161 free(image);
1162 }
1163}
1164
1165static void
1166store_ensure_image(png_store *ps, png_const_structp pp, int nImages,
1167 size_t cbRow, png_uint_32 cRows)
1168{
1169 size_t cb = nImages * cRows * (cbRow + 5);
1170
1171 if (ps->cb_image < cb)
1172 {
1173 png_bytep image;
1174
1175 store_image_free(ps, pp);
1176
1177 /* The buffer is deliberately mis-aligned. */
1178 image = voidcast(png_bytep, malloc(cb+2));
1179 if (image == NULL)
1180 {
1181 /* Called from the startup - ignore the error for the moment. */
1182 if (pp == NULL)
1183 return;
1184
1185 png_error(pp, "OOM allocating image buffer");
1186 }
1187
1188 /* These magic tags are used to detect overwrites above. */
1189 ++image;
1190 image[-1] = 0xed;
1191 image[cb] = 0xfe;
1192
1193 ps->image = image;
1194 ps->cb_image = cb;
1195 }
1196
1197 /* We have an adequate sized image; lay out the rows. There are 2 bytes at
1198 * the start and three at the end of each (this ensures that the row
1199 * alignment starts out odd - 2+1 and changes for larger images on each row.)
1200 */
1201 ps->cb_row = cbRow;
1202 ps->image_h = cRows;
1203
1204 /* For error checking, the whole buffer is set to 10110010 (0xb2 - 178).
1205 * This deliberately doesn't match the bits in the size test image which are
1206 * outside the image; these are set to 0xff (all 1). To make the row
1207 * comparison work in the 'size' test case the size rows are pre-initialized
1208 * to the same value prior to calling 'standard_row'.
1209 */
1210 memset(ps->image, 178, cb);
1211
1212 /* Then put in the marks. */
1213 while (--nImages >= 0)
1214 {
1215 png_uint_32 y;
1216
1217 for (y=0; y<cRows; ++y)
1218 {
1219 png_bytep row = store_image_row(ps, pp, nImages, y);
1220
1221 /* The markers: */
1222 row[-2] = 190;
1223 row[-1] = 239;
1224 row[cbRow] = 222;
1225 row[cbRow+1] = 173;
1226 row[cbRow+2] = 17;
1227 }
1228 }
1229}
1230
1231#ifdef PNG_READ_SUPPORTED
1232static void
1233store_image_check(const png_store* ps, png_const_structp pp, int iImage)
1234{
1235 png_const_bytep image = ps->image;
1236
1237 if (image[-1] != 0xed || image[ps->cb_image] != 0xfe)
1238 png_error(pp, "image overwrite");
1239 else
1240 {
1241 size_t cbRow = ps->cb_row;
1242 png_uint_32 rows = ps->image_h;
1243
1244 image += iImage * (cbRow+5) * ps->image_h;
1245
1246 image += 2; /* skip image first row markers */
1247
1248 for (; rows > 0; --rows)
1249 {
1250 if (image[-2] != 190 || image[-1] != 239)
1251 png_error(pp, "row start overwritten");
1252
1253 if (image[cbRow] != 222 || image[cbRow+1] != 173 ||
1254 image[cbRow+2] != 17)
1255 png_error(pp, "row end overwritten");
1256
1257 image += cbRow+5;
1258 }
1259 }
1260}
1261#endif /* PNG_READ_SUPPORTED */
1262
1263static int
1264valid_chunktype(png_uint_32 chunktype)
1265{
1266 /* Each byte in the chunk type must be in one of the ranges 65..90, 97..122
1267 * (both inclusive), so:
1268 */
1269 unsigned int i;
1270
1271 for (i=0; i<4; ++i)
1272 {
1273 unsigned int c = chunktype & 0xffU;
1274
1275 if (!((c >= 65U && c <= 90U) || (c >= 97U && c <= 122U)))
1276 return 0;
1277
1278 chunktype >>= 8;
1279 }
1280
1281 return 1; /* It's valid */
1282}
1283
1284static void PNGCBAPI
1285store_write(png_structp ppIn, png_bytep pb, size_t st)
1286{
1287 png_const_structp pp = ppIn;
1288 png_store *ps = voidcast(png_store*, png_get_io_ptr(pp));
1289 size_t writepos = ps->writepos;
1290 png_uint_32 chunkpos = ps->chunkpos;
1291 png_uint_32 chunktype = ps->chunktype;
1292 png_uint_32 chunklen = ps->chunklen;
1293
1294 if (ps->pwrite != pp)
1295 png_error(pp, "store state damaged");
1296
1297 /* Technically this is legal, but in practice libpng never writes more than
1298 * the maximum chunk size at once so if it happens something weird has
1299 * changed inside libpng (probably).
1300 */
1301 if (st > 0x7fffffffU)
1302 png_error(pp, "unexpected write size");
1303
1304 /* Now process the bytes to be written. Do this in units of the space in the
1305 * output (write) buffer or, at the start 4 bytes for the chunk type and
1306 * length limited in any case by the amount of data.
1307 */
1308 while (st > 0)
1309 {
1310 if (writepos >= STORE_BUFFER_SIZE)
1311 store_storenew(ps), writepos = 0;
1312
1313 if (chunkpos < 4)
1314 {
1315 png_byte b = *pb++;
1316 --st;
1317 chunklen = (chunklen << 8) + b;
1318 ps->new.buffer[writepos++] = b;
1319 ++chunkpos;
1320 }
1321
1322 else if (chunkpos < 8)
1323 {
1324 png_byte b = *pb++;
1325 --st;
1326 chunktype = (chunktype << 8) + b;
1327 ps->new.buffer[writepos++] = b;
1328
1329 if (++chunkpos == 8)
1330 {
1331 chunklen &= 0xffffffffU;
1332 if (chunklen > 0x7fffffffU)
1333 png_error(pp, "chunk length too great");
1334
1335 chunktype &= 0xffffffffU;
1336 if (chunktype == CHUNK_IDAT)
1337 {
1338 if (chunklen > ~ps->IDAT_size)
1339 png_error(pp, "pngvalid internal image too large");
1340
1341 ps->IDAT_size += chunklen;
1342 }
1343
1344 else if (!valid_chunktype(chunktype))
1345 png_error(pp, "invalid chunk type");
1346
1347 chunklen += 12; /* for header and CRC */
1348 }
1349 }
1350
1351 else /* chunkpos >= 8 */
1352 {
1353 size_t cb = st;
1354
1355 if (cb > STORE_BUFFER_SIZE - writepos)
1356 cb = STORE_BUFFER_SIZE - writepos;
1357
1358 if (cb > chunklen - chunkpos/* bytes left in chunk*/)
1359 cb = (size_t)/*SAFE*/(chunklen - chunkpos);
1360
1361 memcpy(ps->new.buffer + writepos, pb, cb);
1362 chunkpos += (png_uint_32)/*SAFE*/cb;
1363 pb += cb;
1364 writepos += cb;
1365 st -= cb;
1366
1367 if (chunkpos >= chunklen) /* must be equal */
1368 chunkpos = chunktype = chunklen = 0;
1369 }
1370 } /* while (st > 0) */
1371
1372 ps->writepos = writepos;
1373 ps->chunkpos = chunkpos;
1374 ps->chunktype = chunktype;
1375 ps->chunklen = chunklen;
1376}
1377
1378static void PNGCBAPI
1379store_flush(png_structp ppIn)
1380{
1381 UNUSED(ppIn) /*DOES NOTHING*/
1382}
1383
1384#ifdef PNG_READ_SUPPORTED
1385static size_t
1386store_read_buffer_size(png_store *ps)
1387{
1388 /* Return the bytes available for read in the current buffer. */
1389 if (ps->next != &ps->current->data)
1390 return STORE_BUFFER_SIZE;
1391
1392 return ps->current->datacount;
1393}
1394
1395/* Return total bytes available for read. */
1396static size_t
1397store_read_buffer_avail(png_store *ps)
1398{
1399 if (ps->current != NULL && ps->next != NULL)
1400 {
1401 png_store_buffer *next = &ps->current->data;
1402 size_t cbAvail = ps->current->datacount;
1403
1404 while (next != ps->next && next != NULL)
1405 {
1406 next = next->prev;
1407 cbAvail += STORE_BUFFER_SIZE;
1408 }
1409
1410 if (next != ps->next)
1411 png_error(ps->pread, "buffer read error");
1412
1413 if (cbAvail > ps->readpos)
1414 return cbAvail - ps->readpos;
1415 }
1416
1417 return 0;
1418}
1419
1420static int
1421store_read_buffer_next(png_store *ps)
1422{
1423 png_store_buffer *pbOld = ps->next;
1424 png_store_buffer *pbNew = &ps->current->data;
1425 if (pbOld != pbNew)
1426 {
1427 while (pbNew != NULL && pbNew->prev != pbOld)
1428 pbNew = pbNew->prev;
1429
1430 if (pbNew != NULL)
1431 {
1432 ps->next = pbNew;
1433 ps->readpos = 0;
1434 return 1;
1435 }
1436
1437 png_error(ps->pread, "buffer lost");
1438 }
1439
1440 return 0; /* EOF or error */
1441}
1442
1443/* Need separate implementation and callback to allow use of the same code
1444 * during progressive read, where the io_ptr is set internally by libpng.
1445 */
1446static void
1447store_read_imp(png_store *ps, png_bytep pb, size_t st)
1448{
1449 if (ps->current == NULL || ps->next == NULL)
1450 png_error(ps->pread, "store state damaged");
1451
1452 while (st > 0)
1453 {
1454 size_t cbAvail = store_read_buffer_size(ps) - ps->readpos;
1455
1456 if (cbAvail > 0)
1457 {
1458 if (cbAvail > st) cbAvail = st;
1459 memcpy(pb, ps->next->buffer + ps->readpos, cbAvail);
1460 st -= cbAvail;
1461 pb += cbAvail;
1462 ps->readpos += cbAvail;
1463 }
1464
1465 else if (!store_read_buffer_next(ps))
1466 png_error(ps->pread, "read beyond end of file");
1467 }
1468}
1469
1470static size_t
1471store_read_chunk(png_store *ps, png_bytep pb, size_t max, size_t min)
1472{
1473 png_uint_32 chunklen = ps->chunklen;
1474 png_uint_32 chunktype = ps->chunktype;
1475 png_uint_32 chunkpos = ps->chunkpos;
1476 size_t st = max;
1477
1478 if (st > 0) do
1479 {
1480 if (chunkpos >= chunklen) /* end of last chunk */
1481 {
1482 png_byte buffer[8];
1483
1484 /* Read the header of the next chunk: */
1485 store_read_imp(ps, buffer, 8U);
1486 chunklen = png_get_uint_32(buffer) + 12U;
1487 chunktype = png_get_uint_32(buffer+4U);
1488 chunkpos = 0U; /* Position read so far */
1489 }
1490
1491 if (chunktype == CHUNK_IDAT)
1492 {
1493 png_uint_32 IDAT_pos = ps->IDAT_pos;
1494 png_uint_32 IDAT_len = ps->IDAT_len;
1495 png_uint_32 IDAT_size = ps->IDAT_size;
1496
1497 /* The IDAT headers are constructed here; skip the input header. */
1498 if (chunkpos < 8U)
1499 chunkpos = 8U;
1500
1501 if (IDAT_pos == IDAT_len)
1502 {
1503 png_byte random = random_byte();
1504
1505 /* Make a new IDAT chunk, if IDAT_len is 0 this is the first IDAT,
1506 * if IDAT_size is 0 this is the end. At present this is set up
1507 * using a random number so that there is a 25% chance before
1508 * the start of the first IDAT chunk being 0 length.
1509 */
1510 if (IDAT_len == 0U) /* First IDAT */
1511 {
1512 switch (random & 3U)
1513 {
1514 case 0U: IDAT_len = 12U; break; /* 0 bytes */
1515 case 1U: IDAT_len = 13U; break; /* 1 byte */
1516 default: IDAT_len = random_u32();
1517 IDAT_len %= IDAT_size;
1518 IDAT_len += 13U; /* 1..IDAT_size bytes */
1519 break;
1520 }
1521 }
1522
1523 else if (IDAT_size == 0U) /* all IDAT data read */
1524 {
1525 /* The last (IDAT) chunk should be positioned at the CRC now: */
1526 if (chunkpos != chunklen-4U)
1527 png_error(ps->pread, "internal: IDAT size mismatch");
1528
1529 /* The only option here is to add a zero length IDAT, this
1530 * happens 25% of the time. Because of the check above
1531 * chunklen-4U-chunkpos must be zero, we just need to skip the
1532 * CRC now.
1533 */
1534 if ((random & 3U) == 0U)
1535 IDAT_len = 12U; /* Output another 0 length IDAT */
1536
1537 else
1538 {
1539 /* End of IDATs, skip the CRC to make the code above load the
1540 * next chunk header next time round.
1541 */
1542 png_byte buffer[4];
1543
1544 store_read_imp(ps, buffer, 4U);
1545 chunkpos += 4U;
1546 ps->IDAT_pos = IDAT_pos;
1547 ps->IDAT_len = IDAT_len;
1548 ps->IDAT_size = 0U;
1549 continue; /* Read the next chunk */
1550 }
1551 }
1552
1553 else
1554 {
1555 /* Middle of IDATs, use 'random' to determine the number of bits
1556 * to use in the IDAT length.
1557 */
1558 IDAT_len = random_u32();
1559 IDAT_len &= (1U << (1U + random % ps->IDAT_bits)) - 1U;
1560 if (IDAT_len > IDAT_size)
1561 IDAT_len = IDAT_size;
1562 IDAT_len += 12U; /* zero bytes may occur */
1563 }
1564
1565 IDAT_pos = 0U;
1566 ps->IDAT_crc = 0x35af061e; /* Ie: crc32(0UL, "IDAT", 4) */
1567 } /* IDAT_pos == IDAT_len */
1568
1569 if (IDAT_pos < 8U) /* Return the header */ do
1570 {
1571 png_uint_32 b;
1572 unsigned int shift;
1573
1574 if (IDAT_pos < 4U)
1575 b = IDAT_len - 12U;
1576
1577 else
1578 b = CHUNK_IDAT;
1579
1580 shift = 3U & IDAT_pos;
1581 ++IDAT_pos;
1582
1583 if (shift < 3U)
1584 b >>= 8U*(3U-shift);
1585
1586 *pb++ = 0xffU & b;
1587 }
1588 while (--st > 0 && IDAT_pos < 8);
1589
1590 else if (IDAT_pos < IDAT_len - 4U) /* I.e not the CRC */
1591 {
1592 if (chunkpos < chunklen-4U)
1593 {
1594 uInt avail = (uInt)-1;
1595
1596 if (avail > (IDAT_len-4U) - IDAT_pos)
1597 avail = (uInt)/*SAFE*/((IDAT_len-4U) - IDAT_pos);
1598
1599 if (avail > st)
1600 avail = (uInt)/*SAFE*/st;
1601
1602 if (avail > (chunklen-4U) - chunkpos)
1603 avail = (uInt)/*SAFE*/((chunklen-4U) - chunkpos);
1604
1605 store_read_imp(ps, pb, avail);
1606 ps->IDAT_crc = crc32(ps->IDAT_crc, pb, avail);
1607 pb += (size_t)/*SAFE*/avail;
1608 st -= (size_t)/*SAFE*/avail;
1609 chunkpos += (png_uint_32)/*SAFE*/avail;
1610 IDAT_size -= (png_uint_32)/*SAFE*/avail;
1611 IDAT_pos += (png_uint_32)/*SAFE*/avail;
1612 }
1613
1614 else /* skip the input CRC */
1615 {
1616 png_byte buffer[4];
1617
1618 store_read_imp(ps, buffer, 4U);
1619 chunkpos += 4U;
1620 }
1621 }
1622
1623 else /* IDAT crc */ do
1624 {
1625 uLong b = ps->IDAT_crc;
1626 unsigned int shift = (IDAT_len - IDAT_pos); /* 4..1 */
1627 ++IDAT_pos;
1628
1629 if (shift > 1U)
1630 b >>= 8U*(shift-1U);
1631
1632 *pb++ = 0xffU & b;
1633 }
1634 while (--st > 0 && IDAT_pos < IDAT_len);
1635
1636 ps->IDAT_pos = IDAT_pos;
1637 ps->IDAT_len = IDAT_len;
1638 ps->IDAT_size = IDAT_size;
1639 }
1640
1641 else /* !IDAT */
1642 {
1643 /* If there is still some pending IDAT data after the IDAT chunks have
1644 * been processed there is a problem:
1645 */
1646 if (ps->IDAT_len > 0 && ps->IDAT_size > 0)
1647 png_error(ps->pread, "internal: missing IDAT data");
1648
1649 if (chunktype == CHUNK_IEND && ps->IDAT_len == 0U)
1650 png_error(ps->pread, "internal: missing IDAT");
1651
1652 if (chunkpos < 8U) /* Return the header */ do
1653 {
1654 png_uint_32 b;
1655 unsigned int shift;
1656
1657 if (chunkpos < 4U)
1658 b = chunklen - 12U;
1659
1660 else
1661 b = chunktype;
1662
1663 shift = 3U & chunkpos;
1664 ++chunkpos;
1665
1666 if (shift < 3U)
1667 b >>= 8U*(3U-shift);
1668
1669 *pb++ = 0xffU & b;
1670 }
1671 while (--st > 0 && chunkpos < 8);
1672
1673 else /* Return chunk bytes, including the CRC */
1674 {
1675 size_t avail = st;
1676
1677 if (avail > chunklen - chunkpos)
1678 avail = (size_t)/*SAFE*/(chunklen - chunkpos);
1679
1680 store_read_imp(ps, pb, avail);
1681 pb += avail;
1682 st -= avail;
1683 chunkpos += (png_uint_32)/*SAFE*/avail;
1684
1685 /* Check for end of chunk and end-of-file; don't try to read a new
1686 * chunk header at this point unless instructed to do so by 'min'.
1687 */
1688 if (chunkpos >= chunklen && max-st >= min &&
1689 store_read_buffer_avail(ps) == 0)
1690 break;
1691 }
1692 } /* !IDAT */
1693 }
1694 while (st > 0);
1695
1696 ps->chunklen = chunklen;
1697 ps->chunktype = chunktype;
1698 ps->chunkpos = chunkpos;
1699
1700 return st; /* space left */
1701}
1702
1703static void PNGCBAPI
1704store_read(png_structp ppIn, png_bytep pb, size_t st)
1705{
1706 png_const_structp pp = ppIn;
1707 png_store *ps = voidcast(png_store*, png_get_io_ptr(pp));
1708
1709 if (ps == NULL || ps->pread != pp)
1710 png_error(pp, "bad store read call");
1711
1712 store_read_chunk(ps, pb, st, st);
1713}
1714
1715static void
1716store_progressive_read(png_store *ps, png_structp pp, png_infop pi)
1717{
1718 if (ps->pread != pp || ps->current == NULL || ps->next == NULL)
1719 png_error(pp, "store state damaged (progressive)");
1720
1721 /* This is another Horowitz and Hill random noise generator. In this case
1722 * the aim is to stress the progressive reader with truly horrible variable
1723 * buffer sizes in the range 1..500, so a sequence of 9 bit random numbers
1724 * is generated. We could probably just count from 1 to 32767 and get as
1725 * good a result.
1726 */
1727 while (store_read_buffer_avail(ps) > 0)
1728 {
1729 static png_uint_32 noise = 2;
1730 size_t cb;
1731 png_byte buffer[512];
1732
1733 /* Generate 15 more bits of stuff: */
1734 noise = (noise << 9) | ((noise ^ (noise >> (9-5))) & 0x1ff);
1735 cb = noise & 0x1ff;
1736 cb -= store_read_chunk(ps, buffer, cb, 1);
1737 png_process_data(pp, pi, buffer, cb);
1738 }
1739}
1740#endif /* PNG_READ_SUPPORTED */
1741
1742/* The caller must fill this in: */
1743static store_palette_entry *
1744store_write_palette(png_store *ps, int npalette)
1745{
1746 if (ps->pwrite == NULL)
1747 store_log(ps, NULL, "attempt to write palette without write stream", 1);
1748
1749 if (ps->palette != NULL)
1750 png_error(ps->pwrite, "multiple store_write_palette calls");
1751
1752 /* This function can only return NULL if called with '0'! */
1753 if (npalette > 0)
1754 {
1755 ps->palette = voidcast(store_palette_entry*, malloc(npalette *
1756 sizeof *ps->palette));
1757
1758 if (ps->palette == NULL)
1759 png_error(ps->pwrite, "store new palette: OOM");
1760
1761 ps->npalette = npalette;
1762 }
1763
1764 return ps->palette;
1765}
1766
1767#ifdef PNG_READ_SUPPORTED
1768static store_palette_entry *
1769store_current_palette(png_store *ps, int *npalette)
1770{
1771 /* This is an internal error (the call has been made outside a read
1772 * operation.)
1773 */
1774 if (ps->current == NULL)
1775 {
1776 store_log(ps, ps->pread, "no current stream for palette", 1);
1777 return NULL;
1778 }
1779
1780 /* The result may be null if there is no palette. */
1781 *npalette = ps->current->npalette;
1782 return ps->current->palette;
1783}
1784#endif /* PNG_READ_SUPPORTED */
1785
1786/***************************** MEMORY MANAGEMENT*** ***************************/
1787#ifdef PNG_USER_MEM_SUPPORTED
1788/* A store_memory is simply the header for an allocated block of memory. The
1789 * pointer returned to libpng is just after the end of the header block, the
1790 * allocated memory is followed by a second copy of the 'mark'.
1791 */
1792typedef struct store_memory
1793{
1794 store_pool *pool; /* Originating pool */
1795 struct store_memory *next; /* Singly linked list */
1796 png_alloc_size_t size; /* Size of memory allocated */
1797 png_byte mark[4]; /* ID marker */
1798} store_memory;
1799
1800/* Handle a fatal error in memory allocation. This calls png_error if the
1801 * libpng struct is non-NULL, else it outputs a message and returns. This means
1802 * that a memory problem while libpng is running will abort (png_error) the
1803 * handling of particular file while one in cleanup (after the destroy of the
1804 * struct has returned) will simply keep going and free (or attempt to free)
1805 * all the memory.
1806 */
1807static void
1808store_pool_error(png_store *ps, png_const_structp pp, const char *msg)
1809{
1810 if (pp != NULL)
1811 png_error(pp, msg);
1812
1813 /* Else we have to do it ourselves. png_error eventually calls store_log,
1814 * above. store_log accepts a NULL png_structp - it just changes what gets
1815 * output by store_message.
1816 */
1817 store_log(ps, pp, msg, 1 /* error */);
1818}
1819
1820static void
1821store_memory_free(png_const_structp pp, store_pool *pool, store_memory *memory)
1822{
1823 /* Note that pp may be NULL (see store_pool_delete below), the caller has
1824 * found 'memory' in pool->list *and* unlinked this entry, so this is a valid
1825 * pointer (for sure), but the contents may have been trashed.
1826 */
1827 if (memory->pool != pool)
1828 store_pool_error(pool->store, pp, "memory corrupted (pool)");
1829
1830 else if (memcmp(memory->mark, pool->mark, sizeof memory->mark) != 0)
1831 store_pool_error(pool->store, pp, "memory corrupted (start)");
1832
1833 /* It should be safe to read the size field now. */
1834 else
1835 {
1836 png_alloc_size_t cb = memory->size;
1837
1838 if (cb > pool->max)
1839 store_pool_error(pool->store, pp, "memory corrupted (size)");
1840
1841 else if (memcmp((png_bytep)(memory+1)+cb, pool->mark, sizeof pool->mark)
1842 != 0)
1843 store_pool_error(pool->store, pp, "memory corrupted (end)");
1844
1845 /* Finally give the library a chance to find problems too: */
1846 else
1847 {
1848 pool->current -= cb;
1849 free(memory);
1850 }
1851 }
1852}
1853
1854static void
1855store_pool_delete(png_store *ps, store_pool *pool)
1856{
1857 if (pool->list != NULL)
1858 {
1859 fprintf(stderr, "%s: %s %s: memory lost (list follows):\n", ps->test,
1860 pool == &ps->read_memory_pool ? "read" : "write",
1861 pool == &ps->read_memory_pool ? (ps->current != NULL ?
1862 ps->current->name : "unknown file") : ps->wname);
1863 ++ps->nerrors;
1864
1865 do
1866 {
1867 store_memory *next = pool->list;
1868 pool->list = next->next;
1869 next->next = NULL;
1870
1871 fprintf(stderr, "\t%lu bytes @ %p\n",
1872 (unsigned long)next->size, (const void*)(next+1));
1873 /* The NULL means this will always return, even if the memory is
1874 * corrupted.
1875 */
1876 store_memory_free(NULL, pool, next);
1877 }
1878 while (pool->list != NULL);
1879 }
1880
1881 /* And reset the other fields too for the next time. */
1882 if (pool->max > pool->max_max) pool->max_max = pool->max;
1883 pool->max = 0;
1884 if (pool->current != 0) /* unexpected internal error */
1885 fprintf(stderr, "%s: %s %s: memory counter mismatch (internal error)\n",
1886 ps->test, pool == &ps->read_memory_pool ? "read" : "write",
1887 pool == &ps->read_memory_pool ? (ps->current != NULL ?
1888 ps->current->name : "unknown file") : ps->wname);
1889 pool->current = 0;
1890
1891 if (pool->limit > pool->max_limit)
1892 pool->max_limit = pool->limit;
1893
1894 pool->limit = 0;
1895
1896 if (pool->total > pool->max_total)
1897 pool->max_total = pool->total;
1898
1899 pool->total = 0;
1900
1901 /* Get a new mark too. */
1902 store_pool_mark(pool->mark);
1903}
1904
1905/* The memory callbacks: */
1906static png_voidp PNGCBAPI
1907store_malloc(png_structp ppIn, png_alloc_size_t cb)
1908{
1909 png_const_structp pp = ppIn;
1910 store_pool *pool = voidcast(store_pool*, png_get_mem_ptr(pp));
1911 store_memory *new = voidcast(store_memory*, malloc(cb + (sizeof *new) +
1912 (sizeof pool->mark)));
1913
1914 if (new != NULL)
1915 {
1916 if (cb > pool->max)
1917 pool->max = cb;
1918
1919 pool->current += cb;
1920
1921 if (pool->current > pool->limit)
1922 pool->limit = pool->current;
1923
1924 pool->total += cb;
1925
1926 new->size = cb;
1927 memcpy(new->mark, pool->mark, sizeof new->mark);
1928 memcpy((png_byte*)(new+1) + cb, pool->mark, sizeof pool->mark);
1929 new->pool = pool;
1930 new->next = pool->list;
1931 pool->list = new;
1932 ++new;
1933 }
1934
1935 else
1936 {
1937 /* NOTE: the PNG user malloc function cannot use the png_ptr it is passed
1938 * other than to retrieve the allocation pointer! libpng calls the
1939 * store_malloc callback in two basic cases:
1940 *
1941 * 1) From png_malloc; png_malloc will do a png_error itself if NULL is
1942 * returned.
1943 * 2) From png_struct or png_info structure creation; png_malloc is
1944 * to return so cleanup can be performed.
1945 *
1946 * To handle this store_malloc can log a message, but can't do anything
1947 * else.
1948 */
1949 store_log(pool->store, pp, "out of memory", 1 /* is_error */);
1950 }
1951
1952 return new;
1953}
1954
1955static void PNGCBAPI
1956store_free(png_structp ppIn, png_voidp memory)
1957{
1958 png_const_structp pp = ppIn;
1959 store_pool *pool = voidcast(store_pool*, png_get_mem_ptr(pp));
1960 store_memory *this = voidcast(store_memory*, memory), **test;
1961
1962 /* Because libpng calls store_free with a dummy png_struct when deleting
1963 * png_struct or png_info via png_destroy_struct_2 it is necessary to check
1964 * the passed in png_structp to ensure it is valid, and not pass it to
1965 * png_error if it is not.
1966 */
1967 if (pp != pool->store->pread && pp != pool->store->pwrite)
1968 pp = NULL;
1969
1970 /* First check that this 'memory' really is valid memory - it must be in the
1971 * pool list. If it is, use the shared memory_free function to free it.
1972 */
1973 --this;
1974 for (test = &pool->list; *test != this; test = &(*test)->next)
1975 {
1976 if (*test == NULL)
1977 {
1978 store_pool_error(pool->store, pp, "bad pointer to free");
1979 return;
1980 }
1981 }
1982
1983 /* Unlink this entry, *test == this. */
1984 *test = this->next;
1985 this->next = NULL;
1986 store_memory_free(pp, pool, this);
1987}
1988#endif /* PNG_USER_MEM_SUPPORTED */
1989
1990/* Setup functions. */
1991/* Cleanup when aborting a write or after storing the new file. */
1992static void
1993store_write_reset(png_store *ps)
1994{
1995 if (ps->pwrite != NULL)
1996 {
1997 anon_context(ps);
1998
1999 Try
2000 png_destroy_write_struct(&ps->pwrite, &ps->piwrite);
2001
2002 Catch_anonymous
2003 {
2004 /* memory corruption: continue. */
2005 }
2006
2007 ps->pwrite = NULL;
2008 ps->piwrite = NULL;
2009 }
2010
2011 /* And make sure that all the memory has been freed - this will output
2012 * spurious errors in the case of memory corruption above, but this is safe.
2013 */
2014# ifdef PNG_USER_MEM_SUPPORTED
2015 store_pool_delete(ps, &ps->write_memory_pool);
2016# endif
2017
2018 store_freenew(ps);
2019}
2020
2021/* The following is the main write function, it returns a png_struct and,
2022 * optionally, a png_info suitable for writiing a new PNG file. Use
2023 * store_storefile above to record this file after it has been written. The
2024 * returned libpng structures as destroyed by store_write_reset above.
2025 */
2026static png_structp
2027set_store_for_write(png_store *ps, png_infopp ppi, const char *name)
2028{
2029 anon_context(ps);
2030
2031 Try
2032 {
2033 if (ps->pwrite != NULL)
2034 png_error(ps->pwrite, "write store already in use");
2035
2036 store_write_reset(ps);
2037 safecat(ps->wname, sizeof ps->wname, 0, name);
2038
2039 /* Don't do the slow memory checks if doing a speed test, also if user
2040 * memory is not supported we can't do it anyway.
2041 */
2042# ifdef PNG_USER_MEM_SUPPORTED
2043 if (!ps->speed)
2044 ps->pwrite = png_create_write_struct_2(PNG_LIBPNG_VER_STRING,
2045 ps, store_error, store_warning, &ps->write_memory_pool,
2046 store_malloc, store_free);
2047
2048 else
2049# endif
2050 ps->pwrite = png_create_write_struct(PNG_LIBPNG_VER_STRING,
2051 ps, store_error, store_warning);
2052
2053 png_set_write_fn(ps->pwrite, ps, store_write, store_flush);
2054
2055# ifdef PNG_SET_OPTION_SUPPORTED
2056 {
2057 int opt;
2058 for (opt=0; opt<ps->noptions; ++opt)
2059 if (png_set_option(ps->pwrite, ps->options[opt].option,
2060 ps->options[opt].setting) == PNG_OPTION_INVALID)
2061 png_error(ps->pwrite, "png option invalid");
2062 }
2063# endif
2064
2065 if (ppi != NULL)
2066 *ppi = ps->piwrite = png_create_info_struct(ps->pwrite);
2067 }
2068
2069 Catch_anonymous
2070 return NULL;
2071
2072 return ps->pwrite;
2073}
2074
2075/* Cleanup when finished reading (either due to error or in the success case).
2076 * This routine exists even when there is no read support to make the code
2077 * tidier (avoid a mass of ifdefs) and so easier to maintain.
2078 */
2079static void
2080store_read_reset(png_store *ps)
2081{
2082# ifdef PNG_READ_SUPPORTED
2083 if (ps->pread != NULL)
2084 {
2085 anon_context(ps);
2086
2087 Try
2088 png_destroy_read_struct(&ps->pread, &ps->piread, NULL);
2089
2090 Catch_anonymous
2091 {
2092 /* error already output: continue */
2093 }
2094
2095 ps->pread = NULL;
2096 ps->piread = NULL;
2097 }
2098# endif
2099
2100# ifdef PNG_USER_MEM_SUPPORTED
2101 /* Always do this to be safe. */
2102 store_pool_delete(ps, &ps->read_memory_pool);
2103# endif
2104
2105 ps->current = NULL;
2106 ps->next = NULL;
2107 ps->readpos = 0;
2108 ps->validated = 0;
2109
2110 ps->chunkpos = 8;
2111 ps->chunktype = 0;
2112 ps->chunklen = 16;
2113 ps->IDAT_size = 0;
2114}
2115
2116#ifdef PNG_READ_SUPPORTED
2117static void
2118store_read_set(png_store *ps, png_uint_32 id)
2119{
2120 png_store_file *pf = ps->saved;
2121
2122 while (pf != NULL)
2123 {
2124 if (pf->id == id)
2125 {
2126 ps->current = pf;
2127 ps->next = NULL;
2128 ps->IDAT_size = pf->IDAT_size;
2129 ps->IDAT_bits = pf->IDAT_bits; /* just a cache */
2130 ps->IDAT_len = 0;
2131 ps->IDAT_pos = 0;
2132 ps->IDAT_crc = 0UL;
2133 store_read_buffer_next(ps);
2134 return;
2135 }
2136
2137 pf = pf->next;
2138 }
2139
2140 {
2141 size_t pos;
2142 char msg[FILE_NAME_SIZE+64];
2143
2144 pos = standard_name_from_id(msg, sizeof msg, 0, id);
2145 pos = safecat(msg, sizeof msg, pos, ": file not found");
2146 png_error(ps->pread, msg);
2147 }
2148}
2149
2150/* The main interface for reading a saved file - pass the id number of the file
2151 * to retrieve. Ids must be unique or the earlier file will be hidden. The API
2152 * returns a png_struct and, optionally, a png_info. Both of these will be
2153 * destroyed by store_read_reset above.
2154 */
2155static png_structp
2156set_store_for_read(png_store *ps, png_infopp ppi, png_uint_32 id,
2157 const char *name)
2158{
2159 /* Set the name for png_error */
2160 safecat(ps->test, sizeof ps->test, 0, name);
2161
2162 if (ps->pread != NULL)
2163 png_error(ps->pread, "read store already in use");
2164
2165 store_read_reset(ps);
2166
2167 /* Both the create APIs can return NULL if used in their default mode
2168 * (because there is no other way of handling an error because the jmp_buf
2169 * by default is stored in png_struct and that has not been allocated!)
2170 * However, given that store_error works correctly in these circumstances
2171 * we don't ever expect NULL in this program.
2172 */
2173# ifdef PNG_USER_MEM_SUPPORTED
2174 if (!ps->speed)
2175 ps->pread = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, ps,
2176 store_error, store_warning, &ps->read_memory_pool, store_malloc,
2177 store_free);
2178
2179 else
2180# endif
2181 ps->pread = png_create_read_struct(PNG_LIBPNG_VER_STRING, ps, store_error,
2182 store_warning);
2183
2184 if (ps->pread == NULL)
2185 {
2186 struct exception_context *the_exception_context = &ps->exception_context;
2187
2188 store_log(ps, NULL, "png_create_read_struct returned NULL (unexpected)",
2189 1 /*error*/);
2190
2191 Throw ps;
2192 }
2193
2194# ifdef PNG_SET_OPTION_SUPPORTED
2195 {
2196 int opt;
2197 for (opt=0; opt<ps->noptions; ++opt)
2198 if (png_set_option(ps->pread, ps->options[opt].option,
2199 ps->options[opt].setting) == PNG_OPTION_INVALID)
2200 png_error(ps->pread, "png option invalid");
2201 }
2202# endif
2203
2204 store_read_set(ps, id);
2205
2206 if (ppi != NULL)
2207 *ppi = ps->piread = png_create_info_struct(ps->pread);
2208
2209 return ps->pread;
2210}
2211#endif /* PNG_READ_SUPPORTED */
2212
2213/* The overall cleanup of a store simply calls the above then removes all the
2214 * saved files. This does not delete the store itself.
2215 */
2216static void
2217store_delete(png_store *ps)
2218{
2219 store_write_reset(ps);
2220 store_read_reset(ps);
2221 store_freefile(&ps->saved);
2222 store_image_free(ps, NULL);
2223}
2224
2225/*********************** PNG FILE MODIFICATION ON READ ************************/
2226/* Files may be modified on read. The following structure contains a complete
2227 * png_store together with extra members to handle modification and a special
2228 * read callback for libpng. To use this the 'modifications' field must be set
2229 * to a list of png_modification structures that actually perform the
2230 * modification, otherwise a png_modifier is functionally equivalent to a
2231 * png_store. There is a special read function, set_modifier_for_read, which
2232 * replaces set_store_for_read.
2233 */
2234typedef enum modifier_state
2235{
2236 modifier_start, /* Initial value */
2237 modifier_signature, /* Have a signature */
2238 modifier_IHDR /* Have an IHDR */
2239} modifier_state;
2240
2241typedef struct CIE_color
2242{
2243 /* A single CIE tristimulus value, representing the unique response of a
2244 * standard observer to a variety of light spectra. The observer recognizes
2245 * all spectra that produce this response as the same color, therefore this
2246 * is effectively a description of a color.
2247 */
2248 double X, Y, Z;
2249} CIE_color;
2250
2251typedef struct color_encoding
2252{
2253 /* A description of an (R,G,B) encoding of color (as defined above); this
2254 * includes the actual colors of the (R,G,B) triples (1,0,0), (0,1,0) and
2255 * (0,0,1) plus an encoding value that is used to encode the linear
2256 * components R, G and B to give the actual values R^gamma, G^gamma and
2257 * B^gamma that are stored.
2258 */
2259 double gamma; /* Encoding (file) gamma of space */
2260 CIE_color red, green, blue; /* End points */
2261} color_encoding;
2262
2263#ifdef PNG_READ_SUPPORTED
2264#if defined PNG_READ_TRANSFORMS_SUPPORTED && defined PNG_READ_cHRM_SUPPORTED
2265static double
2266chromaticity_x(CIE_color c)
2267{
2268 return c.X / (c.X + c.Y + c.Z);
2269}
2270
2271static double
2272chromaticity_y(CIE_color c)
2273{
2274 return c.Y / (c.X + c.Y + c.Z);
2275}
2276
2277static CIE_color
2278white_point(const color_encoding *encoding)
2279{
2280 CIE_color white;
2281
2282 white.X = encoding->red.X + encoding->green.X + encoding->blue.X;
2283 white.Y = encoding->red.Y + encoding->green.Y + encoding->blue.Y;
2284 white.Z = encoding->red.Z + encoding->green.Z + encoding->blue.Z;
2285
2286 return white;
2287}
2288#endif /* READ_TRANSFORMS && READ_cHRM */
2289
2290#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
2291static void
2292normalize_color_encoding(color_encoding *encoding)
2293{
2294 const double whiteY = encoding->red.Y + encoding->green.Y +
2295 encoding->blue.Y;
2296
2297 if (whiteY != 1)
2298 {
2299 encoding->red.X /= whiteY;
2300 encoding->red.Y /= whiteY;
2301 encoding->red.Z /= whiteY;
2302 encoding->green.X /= whiteY;
2303 encoding->green.Y /= whiteY;
2304 encoding->green.Z /= whiteY;
2305 encoding->blue.X /= whiteY;
2306 encoding->blue.Y /= whiteY;
2307 encoding->blue.Z /= whiteY;
2308 }
2309}
2310#endif
2311
2312#ifdef PNG_READ_TRANSFORMS_SUPPORTED
2313static size_t
2314safecat_color_encoding(char *buffer, size_t bufsize, size_t pos,
2315 const color_encoding *e, double encoding_gamma)
2316{
2317 if (e != 0)
2318 {
2319 if (encoding_gamma != 0)
2320 pos = safecat(buffer, bufsize, pos, "(");
2321 pos = safecat(buffer, bufsize, pos, "R(");
2322 pos = safecatd(buffer, bufsize, pos, e->red.X, 4);
2323 pos = safecat(buffer, bufsize, pos, ",");
2324 pos = safecatd(buffer, bufsize, pos, e->red.Y, 4);
2325 pos = safecat(buffer, bufsize, pos, ",");
2326 pos = safecatd(buffer, bufsize, pos, e->red.Z, 4);
2327 pos = safecat(buffer, bufsize, pos, "),G(");
2328 pos = safecatd(buffer, bufsize, pos, e->green.X, 4);
2329 pos = safecat(buffer, bufsize, pos, ",");
2330 pos = safecatd(buffer, bufsize, pos, e->green.Y, 4);
2331 pos = safecat(buffer, bufsize, pos, ",");
2332 pos = safecatd(buffer, bufsize, pos, e->green.Z, 4);
2333 pos = safecat(buffer, bufsize, pos, "),B(");
2334 pos = safecatd(buffer, bufsize, pos, e->blue.X, 4);
2335 pos = safecat(buffer, bufsize, pos, ",");
2336 pos = safecatd(buffer, bufsize, pos, e->blue.Y, 4);
2337 pos = safecat(buffer, bufsize, pos, ",");
2338 pos = safecatd(buffer, bufsize, pos, e->blue.Z, 4);
2339 pos = safecat(buffer, bufsize, pos, ")");
2340 if (encoding_gamma != 0)
2341 pos = safecat(buffer, bufsize, pos, ")");
2342 }
2343
2344 if (encoding_gamma != 0)
2345 {
2346 pos = safecat(buffer, bufsize, pos, "^");
2347 pos = safecatd(buffer, bufsize, pos, encoding_gamma, 5);
2348 }
2349
2350 return pos;
2351}
2352#endif /* READ_TRANSFORMS */
2353#endif /* PNG_READ_SUPPORTED */
2354
2355typedef struct png_modifier
2356{
2357 png_store this; /* I am a png_store */
2358 struct png_modification *modifications; /* Changes to make */
2359
2360 modifier_state state; /* My state */
2361
2362 /* Information from IHDR: */
2363 png_byte bit_depth; /* From IHDR */
2364 png_byte colour_type; /* From IHDR */
2365
2366 /* While handling PLTE, IDAT and IEND these chunks may be pended to allow
2367 * other chunks to be inserted.
2368 */
2369 png_uint_32 pending_len;
2370 png_uint_32 pending_chunk;
2371
2372 /* Test values */
2373 double *gammas;
2374 unsigned int ngammas;
2375 unsigned int ngamma_tests; /* Number of gamma tests to run*/
2376 double current_gamma; /* 0 if not set */
2377 const color_encoding *encodings;
2378 unsigned int nencodings;
2379 const color_encoding *current_encoding; /* If an encoding has been set */
2380 unsigned int encoding_counter; /* For iteration */
2381 int encoding_ignored; /* Something overwrote it */
2382
2383 /* Control variables used to iterate through possible encodings, the
2384 * following must be set to 0 and tested by the function that uses the
2385 * png_modifier because the modifier only sets it to 1 (true.)
2386 */
2387 unsigned int repeat :1; /* Repeat this transform test. */
2388 unsigned int test_uses_encoding :1;
2389
2390 /* Lowest sbit to test (pre-1.7 libpng fails for sbit < 8) */
2391 png_byte sbitlow;
2392
2393 /* Error control - these are the limits on errors accepted by the gamma tests
2394 * below.
2395 */
2396 double maxout8; /* Maximum output value error */
2397 double maxabs8; /* Absolute sample error 0..1 */
2398 double maxcalc8; /* Absolute sample error 0..1 */
2399 double maxpc8; /* Percentage sample error 0..100% */
2400 double maxout16; /* Maximum output value error */
2401 double maxabs16; /* Absolute sample error 0..1 */
2402 double maxcalc16;/* Absolute sample error 0..1 */
2403 double maxcalcG; /* Absolute sample error 0..1 */
2404 double maxpc16; /* Percentage sample error 0..100% */
2405
2406 /* This is set by transforms that need to allow a higher limit, it is an
2407 * internal check on pngvalid to ensure that the calculated error limits are
2408 * not ridiculous; without this it is too easy to make a mistake in pngvalid
2409 * that allows any value through.
2410 *
2411 * NOTE: this is not checked in release builds.
2412 */
2413 double limit; /* limit on error values, normally 4E-3 */
2414
2415 /* Log limits - values above this are logged, but not necessarily
2416 * warned.
2417 */
2418 double log8; /* Absolute error in 8 bits to log */
2419 double log16; /* Absolute error in 16 bits to log */
2420
2421 /* Logged 8 and 16 bit errors ('output' values): */
2422 double error_gray_2;
2423 double error_gray_4;
2424 double error_gray_8;
2425 double error_gray_16;
2426 double error_color_8;
2427 double error_color_16;
2428 double error_indexed;
2429
2430 /* Flags: */
2431 /* Whether to call png_read_update_info, not png_read_start_image, and how
2432 * many times to call it.
2433 */
2434 int use_update_info;
2435
2436 /* Whether or not to interlace. */
2437 int interlace_type :9; /* int, but must store '1' */
2438
2439 /* Run the standard tests? */
2440 unsigned int test_standard :1;
2441
2442 /* Run the odd-sized image and interlace read/write tests? */
2443 unsigned int test_size :1;
2444
2445 /* Run tests on reading with a combination of transforms, */
2446 unsigned int test_transform :1;
2447 unsigned int test_tRNS :1; /* Includes tRNS images */
2448
2449 /* When to use the use_input_precision option, this controls the gamma
2450 * validation code checks. If set any value that is within the transformed
2451 * range input-.5 to input+.5 will be accepted, otherwise the value must be
2452 * within the normal limits. It should not be necessary to set this; the
2453 * result should always be exact within the permitted error limits.
2454 */
2455 unsigned int use_input_precision :1;
2456 unsigned int use_input_precision_sbit :1;
2457 unsigned int use_input_precision_16to8 :1;
2458
2459 /* If set assume that the calculation bit depth is set by the input
2460 * precision, not the output precision.
2461 */
2462 unsigned int calculations_use_input_precision :1;
2463
2464 /* If set assume that the calculations are done in 16 bits even if the sample
2465 * depth is 8 bits.
2466 */
2467 unsigned int assume_16_bit_calculations :1;
2468
2469 /* Which gamma tests to run: */
2470 unsigned int test_gamma_threshold :1;
2471 unsigned int test_gamma_transform :1; /* main tests */
2472 unsigned int test_gamma_sbit :1;
2473 unsigned int test_gamma_scale16 :1;
2474 unsigned int test_gamma_background :1;
2475 unsigned int test_gamma_alpha_mode :1;
2476 unsigned int test_gamma_expand16 :1;
2477 unsigned int test_exhaustive :1;
2478
2479 /* Whether or not to run the low-bit-depth grayscale tests. This fails on
2480 * gamma images in some cases because of gross inaccuracies in the grayscale
2481 * gamma handling for low bit depth.
2482 */
2483 unsigned int test_lbg :1;
2484 unsigned int test_lbg_gamma_threshold :1;
2485 unsigned int test_lbg_gamma_transform :1;
2486 unsigned int test_lbg_gamma_sbit :1;
2487 unsigned int test_lbg_gamma_composition :1;
2488
2489 unsigned int log :1; /* Log max error */
2490
2491 /* Buffer information, the buffer size limits the size of the chunks that can
2492 * be modified - they must fit (including header and CRC) into the buffer!
2493 */
2494 size_t flush; /* Count of bytes to flush */
2495 size_t buffer_count; /* Bytes in buffer */
2496 size_t buffer_position; /* Position in buffer */
2497 png_byte buffer[1024];
2498} png_modifier;
2499
2500/* This returns true if the test should be stopped now because it has already
2501 * failed and it is running silently.
2502 */
2503static int fail(png_modifier *pm)
2504{
2505 return !pm->log && !pm->this.verbose && (pm->this.nerrors > 0 ||
2506 (pm->this.treat_warnings_as_errors && pm->this.nwarnings > 0));
2507}
2508
2509static void
2510modifier_init(png_modifier *pm)
2511{
2512 memset(pm, 0, sizeof *pm);
2513 store_init(&pm->this);
2514 pm->modifications = NULL;
2515 pm->state = modifier_start;
2516 pm->sbitlow = 1U;
2517 pm->ngammas = 0;
2518 pm->ngamma_tests = 0;
2519 pm->gammas = 0;
2520 pm->current_gamma = 0;
2521 pm->encodings = 0;
2522 pm->nencodings = 0;
2523 pm->current_encoding = 0;
2524 pm->encoding_counter = 0;
2525 pm->encoding_ignored = 0;
2526 pm->repeat = 0;
2527 pm->test_uses_encoding = 0;
2528 pm->maxout8 = pm->maxpc8 = pm->maxabs8 = pm->maxcalc8 = 0;
2529 pm->maxout16 = pm->maxpc16 = pm->maxabs16 = pm->maxcalc16 = 0;
2530 pm->maxcalcG = 0;
2531 pm->limit = 4E-3;
2532 pm->log8 = pm->log16 = 0; /* Means 'off' */
2533 pm->error_gray_2 = pm->error_gray_4 = pm->error_gray_8 = 0;
2534 pm->error_gray_16 = pm->error_color_8 = pm->error_color_16 = 0;
2535 pm->error_indexed = 0;
2536 pm->use_update_info = 0;
2537 pm->interlace_type = PNG_INTERLACE_NONE;
2538 pm->test_standard = 0;
2539 pm->test_size = 0;
2540 pm->test_transform = 0;
2541# ifdef PNG_WRITE_tRNS_SUPPORTED
2542 pm->test_tRNS = 1;
2543# else
2544 pm->test_tRNS = 0;
2545# endif
2546 pm->use_input_precision = 0;
2547 pm->use_input_precision_sbit = 0;
2548 pm->use_input_precision_16to8 = 0;
2549 pm->calculations_use_input_precision = 0;
2550 pm->assume_16_bit_calculations = 0;
2551 pm->test_gamma_threshold = 0;
2552 pm->test_gamma_transform = 0;
2553 pm->test_gamma_sbit = 0;
2554 pm->test_gamma_scale16 = 0;
2555 pm->test_gamma_background = 0;
2556 pm->test_gamma_alpha_mode = 0;
2557 pm->test_gamma_expand16 = 0;
2558 pm->test_lbg = 1;
2559 pm->test_lbg_gamma_threshold = 1;
2560 pm->test_lbg_gamma_transform = 1;
2561 pm->test_lbg_gamma_sbit = 1;
2562 pm->test_lbg_gamma_composition = 1;
2563 pm->test_exhaustive = 0;
2564 pm->log = 0;
2565
2566 /* Rely on the memset for all the other fields - there are no pointers */
2567}
2568
2569#ifdef PNG_READ_TRANSFORMS_SUPPORTED
2570
2571/* This controls use of checks that explicitly know how libpng digitizes the
2572 * samples in calculations; setting this circumvents simple error limit checking
2573 * in the rgb_to_gray check, replacing it with an exact copy of the libpng 1.5
2574 * algorithm.
2575 */
2576#define DIGITIZE PNG_LIBPNG_VER != 10700
2577
2578/* If pm->calculations_use_input_precision is set then operations will happen
2579 * with the precision of the input, not the precision of the output depth.
2580 *
2581 * If pm->assume_16_bit_calculations is set then even 8 bit calculations use 16
2582 * bit precision. This only affects those of the following limits that pertain
2583 * to a calculation - not a digitization operation - unless the following API is
2584 * called directly.
2585 */
2586#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
2587#if DIGITIZE
2588static double digitize(double value, int depth, int do_round)
2589{
2590 /* 'value' is in the range 0 to 1, the result is the same value rounded to a
2591 * multiple of the digitization factor - 8 or 16 bits depending on both the
2592 * sample depth and the 'assume' setting. Digitization is normally by
2593 * rounding and 'do_round' should be 1, if it is 0 the digitized value will
2594 * be truncated.
2595 */
2596 unsigned int digitization_factor = (1U << depth) - 1;
2597
2598 /* Limiting the range is done as a convenience to the caller - it's easier to
2599 * do it once here than every time at the call site.
2600 */
2601 if (value <= 0)
2602 value = 0;
2603
2604 else if (value >= 1)
2605 value = 1;
2606
2607 value *= digitization_factor;
2608 if (do_round) value += .5;
2609 return floor(value)/digitization_factor;
2610}
2611#endif
2612#endif /* RGB_TO_GRAY */
2613
2614#ifdef PNG_READ_GAMMA_SUPPORTED
2615static double abserr(const png_modifier *pm, int in_depth, int out_depth)
2616{
2617 /* Absolute error permitted in linear values - affected by the bit depth of
2618 * the calculations.
2619 */
2620 if (pm->assume_16_bit_calculations ||
2621 (pm->calculations_use_input_precision ? in_depth : out_depth) == 16)
2622 return pm->maxabs16;
2623 else
2624 return pm->maxabs8;
2625}
2626
2627static double calcerr(const png_modifier *pm, int in_depth, int out_depth)
2628{
2629 /* Error in the linear composition arithmetic - only relevant when
2630 * composition actually happens (0 < alpha < 1).
2631 */
2632 if ((pm->calculations_use_input_precision ? in_depth : out_depth) == 16)
2633 return pm->maxcalc16;
2634 else if (pm->assume_16_bit_calculations)
2635 return pm->maxcalcG;
2636 else
2637 return pm->maxcalc8;
2638}
2639
2640static double pcerr(const png_modifier *pm, int in_depth, int out_depth)
2641{
2642 /* Percentage error permitted in the linear values. Note that the specified
2643 * value is a percentage but this routine returns a simple number.
2644 */
2645 if (pm->assume_16_bit_calculations ||
2646 (pm->calculations_use_input_precision ? in_depth : out_depth) == 16)
2647 return pm->maxpc16 * .01;
2648 else
2649 return pm->maxpc8 * .01;
2650}
2651
2652/* Output error - the error in the encoded value. This is determined by the
2653 * digitization of the output so can be +/-0.5 in the actual output value. In
2654 * the expand_16 case with the current code in libpng the expand happens after
2655 * all the calculations are done in 8 bit arithmetic, so even though the output
2656 * depth is 16 the output error is determined by the 8 bit calculation.
2657 *
2658 * This limit is not determined by the bit depth of internal calculations.
2659 *
2660 * The specified parameter does *not* include the base .5 digitization error but
2661 * it is added here.
2662 */
2663static double outerr(const png_modifier *pm, int in_depth, int out_depth)
2664{
2665 /* There is a serious error in the 2 and 4 bit grayscale transform because
2666 * the gamma table value (8 bits) is simply shifted, not rounded, so the
2667 * error in 4 bit grayscale gamma is up to the value below. This is a hack
2668 * to allow pngvalid to succeed:
2669 *
2670 * TODO: fix this in libpng
2671 */
2672 if (out_depth == 2)
2673 return .73182-.5;
2674
2675 if (out_depth == 4)
2676 return .90644-.5;
2677
2678 if ((pm->calculations_use_input_precision ? in_depth : out_depth) == 16)
2679 return pm->maxout16;
2680
2681 /* This is the case where the value was calculated at 8-bit precision then
2682 * scaled to 16 bits.
2683 */
2684 else if (out_depth == 16)
2685 return pm->maxout8 * 257;
2686
2687 else
2688 return pm->maxout8;
2689}
2690
2691/* This does the same thing as the above however it returns the value to log,
2692 * rather than raising a warning. This is useful for debugging to track down
2693 * exactly what set of parameters cause high error values.
2694 */
2695static double outlog(const png_modifier *pm, int in_depth, int out_depth)
2696{
2697 /* The command line parameters are either 8 bit (0..255) or 16 bit (0..65535)
2698 * and so must be adjusted for low bit depth grayscale:
2699 */
2700 if (out_depth <= 8)
2701 {
2702 if (pm->log8 == 0) /* switched off */
2703 return 256;
2704
2705 if (out_depth < 8)
2706 return pm->log8 / 255 * ((1<<out_depth)-1);
2707
2708 return pm->log8;
2709 }
2710
2711 if ((pm->calculations_use_input_precision ? in_depth : out_depth) == 16)
2712 {
2713 if (pm->log16 == 0)
2714 return 65536;
2715
2716 return pm->log16;
2717 }
2718
2719 /* This is the case where the value was calculated at 8-bit precision then
2720 * scaled to 16 bits.
2721 */
2722 if (pm->log8 == 0)
2723 return 65536;
2724
2725 return pm->log8 * 257;
2726}
2727
2728/* This complements the above by providing the appropriate quantization for the
2729 * final value. Normally this would just be quantization to an integral value,
2730 * but in the 8 bit calculation case it's actually quantization to a multiple of
2731 * 257!
2732 */
2733static int output_quantization_factor(const png_modifier *pm, int in_depth,
2734 int out_depth)
2735{
2736 if (out_depth == 16 && in_depth != 16 &&
2737 pm->calculations_use_input_precision)
2738 return 257;
2739 else
2740 return 1;
2741}
2742#endif /* PNG_READ_GAMMA_SUPPORTED */
2743
2744/* One modification structure must be provided for each chunk to be modified (in
2745 * fact more than one can be provided if multiple separate changes are desired
2746 * for a single chunk.) Modifications include adding a new chunk when a
2747 * suitable chunk does not exist.
2748 *
2749 * The caller of modify_fn will reset the CRC of the chunk and record 'modified'
2750 * or 'added' as appropriate if the modify_fn returns 1 (true). If the
2751 * modify_fn is NULL the chunk is simply removed.
2752 */
2753typedef struct png_modification
2754{
2755 struct png_modification *next;
2756 png_uint_32 chunk;
2757
2758 /* If the following is NULL all matching chunks will be removed: */
2759 int (*modify_fn)(struct png_modifier *pm,
2760 struct png_modification *me, int add);
2761
2762 /* If the following is set to PLTE, IDAT or IEND and the chunk has not been
2763 * found and modified (and there is a modify_fn) the modify_fn will be called
2764 * to add the chunk before the relevant chunk.
2765 */
2766 png_uint_32 add;
2767 unsigned int modified :1; /* Chunk was modified */
2768 unsigned int added :1; /* Chunk was added */
2769 unsigned int removed :1; /* Chunk was removed */
2770} png_modification;
2771
2772static void
2773modification_reset(png_modification *pmm)
2774{
2775 if (pmm != NULL)
2776 {
2777 pmm->modified = 0;
2778 pmm->added = 0;
2779 pmm->removed = 0;
2780 modification_reset(pmm->next);
2781 }
2782}
2783
2784static void
2785modification_init(png_modification *pmm)
2786{
2787 memset(pmm, 0, sizeof *pmm);
2788 pmm->next = NULL;
2789 pmm->chunk = 0;
2790 pmm->modify_fn = NULL;
2791 pmm->add = 0;
2792 modification_reset(pmm);
2793}
2794
2795#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
2796static void
2797modifier_current_encoding(const png_modifier *pm, color_encoding *ce)
2798{
2799 if (pm->current_encoding != 0)
2800 *ce = *pm->current_encoding;
2801
2802 else
2803 memset(ce, 0, sizeof *ce);
2804
2805 ce->gamma = pm->current_gamma;
2806}
2807#endif
2808
2809#ifdef PNG_READ_TRANSFORMS_SUPPORTED
2810static size_t
2811safecat_current_encoding(char *buffer, size_t bufsize, size_t pos,
2812 const png_modifier *pm)
2813{
2814 pos = safecat_color_encoding(buffer, bufsize, pos, pm->current_encoding,
2815 pm->current_gamma);
2816
2817 if (pm->encoding_ignored)
2818 pos = safecat(buffer, bufsize, pos, "[overridden]");
2819
2820 return pos;
2821}
2822#endif
2823
2824/* Iterate through the usefully testable color encodings. An encoding is one
2825 * of:
2826 *
2827 * 1) Nothing (no color space, no gamma).
2828 * 2) Just a gamma value from the gamma array (including 1.0)
2829 * 3) A color space from the encodings array with the corresponding gamma.
2830 * 4) The same, but with gamma 1.0 (only really useful with 16 bit calculations)
2831 *
2832 * The iterator selects these in turn, the randomizer selects one at random,
2833 * which is used depends on the setting of the 'test_exhaustive' flag. Notice
2834 * that this function changes the colour space encoding so it must only be
2835 * called on completion of the previous test. This is what 'modifier_reset'
2836 * does, below.
2837 *
2838 * After the function has been called the 'repeat' flag will still be set; the
2839 * caller of modifier_reset must reset it at the start of each run of the test!
2840 */
2841static unsigned int
2842modifier_total_encodings(const png_modifier *pm)
2843{
2844 return 1 + /* (1) nothing */
2845 pm->ngammas + /* (2) gamma values to test */
2846 pm->nencodings + /* (3) total number of encodings */
2847 /* The following test only works after the first time through the
2848 * png_modifier code because 'bit_depth' is set when the IHDR is read.
2849 * modifier_reset, below, preserves the setting until after it has called
2850 * the iterate function (also below.)
2851 *
2852 * For this reason do not rely on this function outside a call to
2853 * modifier_reset.
2854 */
2855 ((pm->bit_depth == 16 || pm->assume_16_bit_calculations) ?
2856 pm->nencodings : 0); /* (4) encodings with gamma == 1.0 */
2857}
2858
2859static void
2860modifier_encoding_iterate(png_modifier *pm)
2861{
2862 if (!pm->repeat && /* Else something needs the current encoding again. */
2863 pm->test_uses_encoding) /* Some transform is encoding dependent */
2864 {
2865 if (pm->test_exhaustive)
2866 {
2867 if (++pm->encoding_counter >= modifier_total_encodings(pm))
2868 pm->encoding_counter = 0; /* This will stop the repeat */
2869 }
2870
2871 else
2872 {
2873 /* Not exhaustive - choose an encoding at random; generate a number in
2874 * the range 1..(max-1), so the result is always non-zero:
2875 */
2876 if (pm->encoding_counter == 0)
2877 pm->encoding_counter = random_mod(modifier_total_encodings(pm)-1)+1;
2878 else
2879 pm->encoding_counter = 0;
2880 }
2881
2882 if (pm->encoding_counter > 0)
2883 pm->repeat = 1;
2884 }
2885
2886 else if (!pm->repeat)
2887 pm->encoding_counter = 0;
2888}
2889
2890static void
2891modifier_reset(png_modifier *pm)
2892{
2893 store_read_reset(&pm->this);
2894 pm->limit = 4E-3;
2895 pm->pending_len = pm->pending_chunk = 0;
2896 pm->flush = pm->buffer_count = pm->buffer_position = 0;
2897 pm->modifications = NULL;
2898 pm->state = modifier_start;
2899 modifier_encoding_iterate(pm);
2900 /* The following must be set in the next run. In particular
2901 * test_uses_encodings must be set in the _ini function of each transform
2902 * that looks at the encodings. (Not the 'add' function!)
2903 */
2904 pm->test_uses_encoding = 0;
2905 pm->current_gamma = 0;
2906 pm->current_encoding = 0;
2907 pm->encoding_ignored = 0;
2908 /* These only become value after IHDR is read: */
2909 pm->bit_depth = pm->colour_type = 0;
2910}
2911
2912/* The following must be called before anything else to get the encoding set up
2913 * on the modifier. In particular it must be called before the transform init
2914 * functions are called.
2915 */
2916static void
2917modifier_set_encoding(png_modifier *pm)
2918{
2919 /* Set the encoding to the one specified by the current encoding counter,
2920 * first clear out all the settings - this corresponds to an encoding_counter
2921 * of 0.
2922 */
2923 pm->current_gamma = 0;
2924 pm->current_encoding = 0;
2925 pm->encoding_ignored = 0; /* not ignored yet - happens in _ini functions. */
2926
2927 /* Now, if required, set the gamma and encoding fields. */
2928 if (pm->encoding_counter > 0)
2929 {
2930 /* The gammas[] array is an array of screen gammas, not encoding gammas,
2931 * so we need the inverse:
2932 */
2933 if (pm->encoding_counter <= pm->ngammas)
2934 pm->current_gamma = 1/pm->gammas[pm->encoding_counter-1];
2935
2936 else
2937 {
2938 unsigned int i = pm->encoding_counter - pm->ngammas;
2939
2940 if (i >= pm->nencodings)
2941 {
2942 i %= pm->nencodings;
2943 pm->current_gamma = 1; /* Linear, only in the 16 bit case */
2944 }
2945
2946 else
2947 pm->current_gamma = pm->encodings[i].gamma;
2948
2949 pm->current_encoding = pm->encodings + i;
2950 }
2951 }
2952}
2953
2954/* Enquiry functions to find out what is set. Notice that there is an implicit
2955 * assumption below that the first encoding in the list is the one for sRGB.
2956 */
2957static int
2958modifier_color_encoding_is_sRGB(const png_modifier *pm)
2959{
2960 return pm->current_encoding != 0 && pm->current_encoding == pm->encodings &&
2961 pm->current_encoding->gamma == pm->current_gamma;
2962}
2963
2964static int
2965modifier_color_encoding_is_set(const png_modifier *pm)
2966{
2967 return pm->current_gamma != 0;
2968}
2969
2970/* The guts of modification are performed during a read. */
2971static void
2972modifier_crc(png_bytep buffer)
2973{
2974 /* Recalculate the chunk CRC - a complete chunk must be in
2975 * the buffer, at the start.
2976 */
2977 uInt datalen = png_get_uint_32(buffer);
2978 uLong crc = crc32(0, buffer+4, datalen+4);
2979 /* The cast to png_uint_32 is safe because a crc32 is always a 32 bit value.
2980 */
2981 png_save_uint_32(buffer+datalen+8, (png_uint_32)crc);
2982}
2983
2984static void
2985modifier_setbuffer(png_modifier *pm)
2986{
2987 modifier_crc(pm->buffer);
2988 pm->buffer_count = png_get_uint_32(pm->buffer)+12;
2989 pm->buffer_position = 0;
2990}
2991
2992/* Separate the callback into the actual implementation (which is passed the
2993 * png_modifier explicitly) and the callback, which gets the modifier from the
2994 * png_struct.
2995 */
2996static void
2997modifier_read_imp(png_modifier *pm, png_bytep pb, size_t st)
2998{
2999 while (st > 0)
3000 {
3001 size_t cb;
3002 png_uint_32 len, chunk;
3003 png_modification *mod;
3004
3005 if (pm->buffer_position >= pm->buffer_count) switch (pm->state)
3006 {
3007 static png_byte sign[8] = { 137, 80, 78, 71, 13, 10, 26, 10 };
3008 case modifier_start:
3009 store_read_chunk(&pm->this, pm->buffer, 8, 8); /* signature. */
3010 pm->buffer_count = 8;
3011 pm->buffer_position = 0;
3012
3013 if (memcmp(pm->buffer, sign, 8) != 0)
3014 png_error(pm->this.pread, "invalid PNG file signature");
3015 pm->state = modifier_signature;
3016 break;
3017
3018 case modifier_signature:
3019 store_read_chunk(&pm->this, pm->buffer, 13+12, 13+12); /* IHDR */
3020 pm->buffer_count = 13+12;
3021 pm->buffer_position = 0;
3022
3023 if (png_get_uint_32(pm->buffer) != 13 ||
3024 png_get_uint_32(pm->buffer+4) != CHUNK_IHDR)
3025 png_error(pm->this.pread, "invalid IHDR");
3026
3027 /* Check the list of modifiers for modifications to the IHDR. */
3028 mod = pm->modifications;
3029 while (mod != NULL)
3030 {
3031 if (mod->chunk == CHUNK_IHDR && mod->modify_fn &&
3032 (*mod->modify_fn)(pm, mod, 0))
3033 {
3034 mod->modified = 1;
3035 modifier_setbuffer(pm);
3036 }
3037
3038 /* Ignore removal or add if IHDR! */
3039 mod = mod->next;
3040 }
3041
3042 /* Cache information from the IHDR (the modified one.) */
3043 pm->bit_depth = pm->buffer[8+8];
3044 pm->colour_type = pm->buffer[8+8+1];
3045
3046 pm->state = modifier_IHDR;
3047 pm->flush = 0;
3048 break;
3049
3050 case modifier_IHDR:
3051 default:
3052 /* Read a new chunk and process it until we see PLTE, IDAT or
3053 * IEND. 'flush' indicates that there is still some data to
3054 * output from the preceding chunk.
3055 */
3056 if ((cb = pm->flush) > 0)
3057 {
3058 if (cb > st) cb = st;
3059 pm->flush -= cb;
3060 store_read_chunk(&pm->this, pb, cb, cb);
3061 pb += cb;
3062 st -= cb;
3063 if (st == 0) return;
3064 }
3065
3066 /* No more bytes to flush, read a header, or handle a pending
3067 * chunk.
3068 */
3069 if (pm->pending_chunk != 0)
3070 {
3071 png_save_uint_32(pm->buffer, pm->pending_len);
3072 png_save_uint_32(pm->buffer+4, pm->pending_chunk);
3073 pm->pending_len = 0;
3074 pm->pending_chunk = 0;
3075 }
3076 else
3077 store_read_chunk(&pm->this, pm->buffer, 8, 8);
3078
3079 pm->buffer_count = 8;
3080 pm->buffer_position = 0;
3081
3082 /* Check for something to modify or a terminator chunk. */
3083 len = png_get_uint_32(pm->buffer);
3084 chunk = png_get_uint_32(pm->buffer+4);
3085
3086 /* Terminators first, they may have to be delayed for added
3087 * chunks
3088 */
3089 if (chunk == CHUNK_PLTE || chunk == CHUNK_IDAT ||
3090 chunk == CHUNK_IEND)
3091 {
3092 mod = pm->modifications;
3093
3094 while (mod != NULL)
3095 {
3096 if ((mod->add == chunk ||
3097 (mod->add == CHUNK_PLTE && chunk == CHUNK_IDAT)) &&
3098 mod->modify_fn != NULL && !mod->modified && !mod->added)
3099 {
3100 /* Regardless of what the modify function does do not run
3101 * this again.
3102 */
3103 mod->added = 1;
3104
3105 if ((*mod->modify_fn)(pm, mod, 1 /*add*/))
3106 {
3107 /* Reset the CRC on a new chunk */
3108 if (pm->buffer_count > 0)
3109 modifier_setbuffer(pm);
3110
3111 else
3112 {
3113 pm->buffer_position = 0;
3114 mod->removed = 1;
3115 }
3116
3117 /* The buffer has been filled with something (we assume)
3118 * so output this. Pend the current chunk.
3119 */
3120 pm->pending_len = len;
3121 pm->pending_chunk = chunk;
3122 break; /* out of while */
3123 }
3124 }
3125
3126 mod = mod->next;
3127 }
3128
3129 /* Don't do any further processing if the buffer was modified -
3130 * otherwise the code will end up modifying a chunk that was
3131 * just added.
3132 */
3133 if (mod != NULL)
3134 break; /* out of switch */
3135 }
3136
3137 /* If we get to here then this chunk may need to be modified. To
3138 * do this it must be less than 1024 bytes in total size, otherwise
3139 * it just gets flushed.
3140 */
3141 if (len+12 <= sizeof pm->buffer)
3142 {
3143 size_t s = len+12-pm->buffer_count;
3144 store_read_chunk(&pm->this, pm->buffer+pm->buffer_count, s, s);
3145 pm->buffer_count = len+12;
3146
3147 /* Check for a modification, else leave it be. */
3148 mod = pm->modifications;
3149 while (mod != NULL)
3150 {
3151 if (mod->chunk == chunk)
3152 {
3153 if (mod->modify_fn == NULL)
3154 {
3155 /* Remove this chunk */
3156 pm->buffer_count = pm->buffer_position = 0;
3157 mod->removed = 1;
3158 break; /* Terminate the while loop */
3159 }
3160
3161 else if ((*mod->modify_fn)(pm, mod, 0))
3162 {
3163 mod->modified = 1;
3164 /* The chunk may have been removed: */
3165 if (pm->buffer_count == 0)
3166 {
3167 pm->buffer_position = 0;
3168 break;
3169 }
3170 modifier_setbuffer(pm);
3171 }
3172 }
3173
3174 mod = mod->next;
3175 }
3176 }
3177
3178 else
3179 pm->flush = len+12 - pm->buffer_count; /* data + crc */
3180
3181 /* Take the data from the buffer (if there is any). */
3182 break;
3183 }
3184
3185 /* Here to read from the modifier buffer (not directly from
3186 * the store, as in the flush case above.)
3187 */
3188 cb = pm->buffer_count - pm->buffer_position;
3189
3190 if (cb > st)
3191 cb = st;
3192
3193 memcpy(pb, pm->buffer + pm->buffer_position, cb);
3194 st -= cb;
3195 pb += cb;
3196 pm->buffer_position += cb;
3197 }
3198}
3199
3200/* The callback: */
3201static void PNGCBAPI
3202modifier_read(png_structp ppIn, png_bytep pb, size_t st)
3203{
3204 png_const_structp pp = ppIn;
3205 png_modifier *pm = voidcast(png_modifier*, png_get_io_ptr(pp));
3206
3207 if (pm == NULL || pm->this.pread != pp)
3208 png_error(pp, "bad modifier_read call");
3209
3210 modifier_read_imp(pm, pb, st);
3211}
3212
3213/* Like store_progressive_read but the data is getting changed as we go so we
3214 * need a local buffer.
3215 */
3216static void
3217modifier_progressive_read(png_modifier *pm, png_structp pp, png_infop pi)
3218{
3219 if (pm->this.pread != pp || pm->this.current == NULL ||
3220 pm->this.next == NULL)
3221 png_error(pp, "store state damaged (progressive)");
3222
3223 /* This is another Horowitz and Hill random noise generator. In this case
3224 * the aim is to stress the progressive reader with truly horrible variable
3225 * buffer sizes in the range 1..500, so a sequence of 9 bit random numbers
3226 * is generated. We could probably just count from 1 to 32767 and get as
3227 * good a result.
3228 */
3229 for (;;)
3230 {
3231 static png_uint_32 noise = 1;
3232 size_t cb, cbAvail;
3233 png_byte buffer[512];
3234
3235 /* Generate 15 more bits of stuff: */
3236 noise = (noise << 9) | ((noise ^ (noise >> (9-5))) & 0x1ff);
3237 cb = noise & 0x1ff;
3238
3239 /* Check that this number of bytes are available (in the current buffer.)
3240 * (This doesn't quite work - the modifier might delete a chunk; unlikely
3241 * but possible, it doesn't happen at present because the modifier only
3242 * adds chunks to standard images.)
3243 */
3244 cbAvail = store_read_buffer_avail(&pm->this);
3245 if (pm->buffer_count > pm->buffer_position)
3246 cbAvail += pm->buffer_count - pm->buffer_position;
3247
3248 if (cb > cbAvail)
3249 {
3250 /* Check for EOF: */
3251 if (cbAvail == 0)
3252 break;
3253
3254 cb = cbAvail;
3255 }
3256
3257 modifier_read_imp(pm, buffer, cb);
3258 png_process_data(pp, pi, buffer, cb);
3259 }
3260
3261 /* Check the invariants at the end (if this fails it's a problem in this
3262 * file!)
3263 */
3264 if (pm->buffer_count > pm->buffer_position ||
3265 pm->this.next != &pm->this.current->data ||
3266 pm->this.readpos < pm->this.current->datacount)
3267 png_error(pp, "progressive read implementation error");
3268}
3269
3270/* Set up a modifier. */
3271static png_structp
3272set_modifier_for_read(png_modifier *pm, png_infopp ppi, png_uint_32 id,
3273 const char *name)
3274{
3275 /* Do this first so that the modifier fields are cleared even if an error
3276 * happens allocating the png_struct. No allocation is done here so no
3277 * cleanup is required.
3278 */
3279 pm->state = modifier_start;
3280 pm->bit_depth = 0;
3281 pm->colour_type = 255;
3282
3283 pm->pending_len = 0;
3284 pm->pending_chunk = 0;
3285 pm->flush = 0;
3286 pm->buffer_count = 0;
3287 pm->buffer_position = 0;
3288
3289 return set_store_for_read(&pm->this, ppi, id, name);
3290}
3291
3292
3293/******************************** MODIFICATIONS *******************************/
3294/* Standard modifications to add chunks. These do not require the _SUPPORTED
3295 * macros because the chunks can be there regardless of whether this specific
3296 * libpng supports them.
3297 */
3298typedef struct gama_modification
3299{
3300 png_modification this;
3301 png_fixed_point gamma;
3302} gama_modification;
3303
3304static int
3305gama_modify(png_modifier *pm, png_modification *me, int add)
3306{
3307 UNUSED(add)
3308 /* This simply dumps the given gamma value into the buffer. */
3309 png_save_uint_32(pm->buffer, 4);
3310 png_save_uint_32(pm->buffer+4, CHUNK_gAMA);
3311 png_save_uint_32(pm->buffer+8, ((gama_modification*)me)->gamma);
3312 return 1;
3313}
3314
3315static void
3316gama_modification_init(gama_modification *me, png_modifier *pm, double gammad)
3317{
3318 double g;
3319
3320 modification_init(&me->this);
3321 me->this.chunk = CHUNK_gAMA;
3322 me->this.modify_fn = gama_modify;
3323 me->this.add = CHUNK_PLTE;
3324 g = fix(gammad);
3325 me->gamma = (png_fixed_point)g;
3326 me->this.next = pm->modifications;
3327 pm->modifications = &me->this;
3328}
3329
3330typedef struct chrm_modification
3331{
3332 png_modification this;
3333 const color_encoding *encoding;
3334 png_fixed_point wx, wy, rx, ry, gx, gy, bx, by;
3335} chrm_modification;
3336
3337static int
3338chrm_modify(png_modifier *pm, png_modification *me, int add)
3339{
3340 UNUSED(add)
3341 /* As with gAMA this just adds the required cHRM chunk to the buffer. */
3342 png_save_uint_32(pm->buffer , 32);
3343 png_save_uint_32(pm->buffer+ 4, CHUNK_cHRM);
3344 png_save_uint_32(pm->buffer+ 8, ((chrm_modification*)me)->wx);
3345 png_save_uint_32(pm->buffer+12, ((chrm_modification*)me)->wy);
3346 png_save_uint_32(pm->buffer+16, ((chrm_modification*)me)->rx);
3347 png_save_uint_32(pm->buffer+20, ((chrm_modification*)me)->ry);
3348 png_save_uint_32(pm->buffer+24, ((chrm_modification*)me)->gx);
3349 png_save_uint_32(pm->buffer+28, ((chrm_modification*)me)->gy);
3350 png_save_uint_32(pm->buffer+32, ((chrm_modification*)me)->bx);
3351 png_save_uint_32(pm->buffer+36, ((chrm_modification*)me)->by);
3352 return 1;
3353}
3354
3355static void
3356chrm_modification_init(chrm_modification *me, png_modifier *pm,
3357 const color_encoding *encoding)
3358{
3359 CIE_color white = white_point(encoding);
3360
3361 /* Original end points: */
3362 me->encoding = encoding;
3363
3364 /* Chromaticities (in fixed point): */
3365 me->wx = fix(chromaticity_x(white));
3366 me->wy = fix(chromaticity_y(white));
3367
3368 me->rx = fix(chromaticity_x(encoding->red));
3369 me->ry = fix(chromaticity_y(encoding->red));
3370 me->gx = fix(chromaticity_x(encoding->green));
3371 me->gy = fix(chromaticity_y(encoding->green));
3372 me->bx = fix(chromaticity_x(encoding->blue));
3373 me->by = fix(chromaticity_y(encoding->blue));
3374
3375 modification_init(&me->this);
3376 me->this.chunk = CHUNK_cHRM;
3377 me->this.modify_fn = chrm_modify;
3378 me->this.add = CHUNK_PLTE;
3379 me->this.next = pm->modifications;
3380 pm->modifications = &me->this;
3381}
3382
3383typedef struct srgb_modification
3384{
3385 png_modification this;
3386 png_byte intent;
3387} srgb_modification;
3388
3389static int
3390srgb_modify(png_modifier *pm, png_modification *me, int add)
3391{
3392 UNUSED(add)
3393 /* As above, ignore add and just make a new chunk */
3394 png_save_uint_32(pm->buffer, 1);
3395 png_save_uint_32(pm->buffer+4, CHUNK_sRGB);
3396 pm->buffer[8] = ((srgb_modification*)me)->intent;
3397 return 1;
3398}
3399
3400static void
3401srgb_modification_init(srgb_modification *me, png_modifier *pm, png_byte intent)
3402{
3403 modification_init(&me->this);
3404 me->this.chunk = CHUNK_sBIT;
3405
3406 if (intent <= 3) /* if valid, else *delete* sRGB chunks */
3407 {
3408 me->this.modify_fn = srgb_modify;
3409 me->this.add = CHUNK_PLTE;
3410 me->intent = intent;
3411 }
3412
3413 else
3414 {
3415 me->this.modify_fn = 0;
3416 me->this.add = 0;
3417 me->intent = 0;
3418 }
3419
3420 me->this.next = pm->modifications;
3421 pm->modifications = &me->this;
3422}
3423
3424#ifdef PNG_READ_GAMMA_SUPPORTED
3425typedef struct sbit_modification
3426{
3427 png_modification this;
3428 png_byte sbit;
3429} sbit_modification;
3430
3431static int
3432sbit_modify(png_modifier *pm, png_modification *me, int add)
3433{
3434 png_byte sbit = ((sbit_modification*)me)->sbit;
3435 if (pm->bit_depth > sbit)
3436 {
3437 int cb = 0;
3438 switch (pm->colour_type)
3439 {
3440 case 0:
3441 cb = 1;
3442 break;
3443
3444 case 2:
3445 case 3:
3446 cb = 3;
3447 break;
3448
3449 case 4:
3450 cb = 2;
3451 break;
3452
3453 case 6:
3454 cb = 4;
3455 break;
3456
3457 default:
3458 png_error(pm->this.pread,
3459 "unexpected colour type in sBIT modification");
3460 }
3461
3462 png_save_uint_32(pm->buffer, cb);
3463 png_save_uint_32(pm->buffer+4, CHUNK_sBIT);
3464
3465 while (cb > 0)
3466 (pm->buffer+8)[--cb] = sbit;
3467
3468 return 1;
3469 }
3470 else if (!add)
3471 {
3472 /* Remove the sBIT chunk */
3473 pm->buffer_count = pm->buffer_position = 0;
3474 return 1;
3475 }
3476 else
3477 return 0; /* do nothing */
3478}
3479
3480static void
3481sbit_modification_init(sbit_modification *me, png_modifier *pm, png_byte sbit)
3482{
3483 modification_init(&me->this);
3484 me->this.chunk = CHUNK_sBIT;
3485 me->this.modify_fn = sbit_modify;
3486 me->this.add = CHUNK_PLTE;
3487 me->sbit = sbit;
3488 me->this.next = pm->modifications;
3489 pm->modifications = &me->this;
3490}
3491#endif /* PNG_READ_GAMMA_SUPPORTED */
3492#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
3493
3494/***************************** STANDARD PNG FILES *****************************/
3495/* Standard files - write and save standard files. */
3496/* There are two basic forms of standard images. Those which attempt to have
3497 * all the possible pixel values (not possible for 16bpp images, but a range of
3498 * values are produced) and those which have a range of image sizes. The former
3499 * are used for testing transforms, in particular gamma correction and bit
3500 * reduction and increase. The latter are reserved for testing the behavior of
3501 * libpng with respect to 'odd' image sizes - particularly small images where
3502 * rows become 1 byte and interlace passes disappear.
3503 *
3504 * The first, most useful, set are the 'transform' images, the second set of
3505 * small images are the 'size' images.
3506 *
3507 * The transform files are constructed with rows which fit into a 1024 byte row
3508 * buffer. This makes allocation easier below. Further regardless of the file
3509 * format every row has 128 pixels (giving 1024 bytes for 64bpp formats).
3510 *
3511 * Files are stored with no gAMA or sBIT chunks, with a PLTE only when needed
3512 * and with an ID derived from the colour type, bit depth and interlace type
3513 * as above (FILEID). The width (128) and height (variable) are not stored in
3514 * the FILEID - instead the fields are set to 0, indicating a transform file.
3515 *
3516 * The size files ar constructed with rows a maximum of 128 bytes wide, allowing
3517 * a maximum width of 16 pixels (for the 64bpp case.) They also have a maximum
3518 * height of 16 rows. The width and height are stored in the FILEID and, being
3519 * non-zero, indicate a size file.
3520 *
3521 * Because the PNG filter code is typically the largest CPU consumer within
3522 * libpng itself there is a tendency to attempt to optimize it. This results in
3523 * special case code which needs to be validated. To cause this to happen the
3524 * 'size' images are made to use each possible filter, in so far as this is
3525 * possible for smaller images.
3526 *
3527 * For palette image (colour type 3) multiple transform images are stored with
3528 * the same bit depth to allow testing of more colour combinations -
3529 * particularly important for testing the gamma code because libpng uses a
3530 * different code path for palette images. For size images a single palette is
3531 * used.
3532 */
3533
3534/* Make a 'standard' palette. Because there are only 256 entries in a palette
3535 * (maximum) this actually makes a random palette in the hope that enough tests
3536 * will catch enough errors. (Note that the same palette isn't produced every
3537 * time for the same test - it depends on what previous tests have been run -
3538 * but a given set of arguments to pngvalid will always produce the same palette
3539 * at the same test! This is why pseudo-random number generators are useful for
3540 * testing.)
3541 *
3542 * The store must be open for write when this is called, otherwise an internal
3543 * error will occur. This routine contains its own magic number seed, so the
3544 * palettes generated don't change if there are intervening errors (changing the
3545 * calls to the store_mark seed.)
3546 */
3547static store_palette_entry *
3548make_standard_palette(png_store* ps, int npalette, int do_tRNS)
3549{
3550 static png_uint_32 palette_seed[2] = { 0x87654321, 9 };
3551
3552 int i = 0;
3553 png_byte values[256][4];
3554
3555 /* Always put in black and white plus the six primary and secondary colors.
3556 */
3557 for (; i<8; ++i)
3558 {
3559 values[i][1] = (png_byte)((i&1) ? 255U : 0U);
3560 values[i][2] = (png_byte)((i&2) ? 255U : 0U);
3561 values[i][3] = (png_byte)((i&4) ? 255U : 0U);
3562 }
3563
3564 /* Then add 62 grays (one quarter of the remaining 256 slots). */
3565 {
3566 int j = 0;
3567 png_byte random_bytes[4];
3568 png_byte need[256];
3569
3570 need[0] = 0; /*got black*/
3571 memset(need+1, 1, (sizeof need)-2); /*need these*/
3572 need[255] = 0; /*but not white*/
3573
3574 while (i<70)
3575 {
3576 png_byte b;
3577
3578 if (j==0)
3579 {
3580 make_four_random_bytes(palette_seed, random_bytes);
3581 j = 4;
3582 }
3583
3584 b = random_bytes[--j];
3585 if (need[b])
3586 {
3587 values[i][1] = b;
3588 values[i][2] = b;
3589 values[i++][3] = b;
3590 }
3591 }
3592 }
3593
3594 /* Finally add 192 colors at random - don't worry about matches to things we
3595 * already have, chance is less than 1/65536. Don't worry about grays,
3596 * chance is the same, so we get a duplicate or extra gray less than 1 time
3597 * in 170.
3598 */
3599 for (; i<256; ++i)
3600 make_four_random_bytes(palette_seed, values[i]);
3601
3602 /* Fill in the alpha values in the first byte. Just use all possible values
3603 * (0..255) in an apparently random order:
3604 */
3605 {
3606 store_palette_entry *palette;
3607 png_byte selector[4];
3608
3609 make_four_random_bytes(palette_seed, selector);
3610
3611 if (do_tRNS)
3612 for (i=0; i<256; ++i)
3613 values[i][0] = (png_byte)(i ^ selector[0]);
3614
3615 else
3616 for (i=0; i<256; ++i)
3617 values[i][0] = 255; /* no transparency/tRNS chunk */
3618
3619 /* 'values' contains 256 ARGB values, but we only need 'npalette'.
3620 * 'npalette' will always be a power of 2: 2, 4, 16 or 256. In the low
3621 * bit depth cases select colors at random, else it is difficult to have
3622 * a set of low bit depth palette test with any chance of a reasonable
3623 * range of colors. Do this by randomly permuting values into the low
3624 * 'npalette' entries using an XOR mask generated here. This also
3625 * permutes the npalette == 256 case in a potentially useful way (there is
3626 * no relationship between palette index and the color value therein!)
3627 */
3628 palette = store_write_palette(ps, npalette);
3629
3630 for (i=0; i<npalette; ++i)
3631 {
3632 palette[i].alpha = values[i ^ selector[1]][0];
3633 palette[i].red = values[i ^ selector[1]][1];
3634 palette[i].green = values[i ^ selector[1]][2];
3635 palette[i].blue = values[i ^ selector[1]][3];
3636 }
3637
3638 return palette;
3639 }
3640}
3641
3642/* Initialize a standard palette on a write stream. The 'do_tRNS' argument
3643 * indicates whether or not to also set the tRNS chunk.
3644 */
3645/* TODO: the png_structp here can probably be 'const' in the future */
3646static void
3647init_standard_palette(png_store *ps, png_structp pp, png_infop pi, int npalette,
3648 int do_tRNS)
3649{
3650 store_palette_entry *ppal = make_standard_palette(ps, npalette, do_tRNS);
3651
3652 {
3653 int i;
3654 png_color palette[256];
3655
3656 /* Set all entries to detect overread errors. */
3657 for (i=0; i<npalette; ++i)
3658 {
3659 palette[i].red = ppal[i].red;
3660 palette[i].green = ppal[i].green;
3661 palette[i].blue = ppal[i].blue;
3662 }
3663
3664 /* Just in case fill in the rest with detectable values: */
3665 for (; i<256; ++i)
3666 palette[i].red = palette[i].green = palette[i].blue = 42;
3667
3668 png_set_PLTE(pp, pi, palette, npalette);
3669 }
3670
3671 if (do_tRNS)
3672 {
3673 int i, j;
3674 png_byte tRNS[256];
3675
3676 /* Set all the entries, but skip trailing opaque entries */
3677 for (i=j=0; i<npalette; ++i)
3678 if ((tRNS[i] = ppal[i].alpha) < 255)
3679 j = i+1;
3680
3681 /* Fill in the remainder with a detectable value: */
3682 for (; i<256; ++i)
3683 tRNS[i] = 24;
3684
3685#ifdef PNG_WRITE_tRNS_SUPPORTED
3686 if (j > 0)
3687 png_set_tRNS(pp, pi, tRNS, j, 0/*color*/);
3688#endif
3689 }
3690}
3691
3692#ifdef PNG_WRITE_tRNS_SUPPORTED
3693static void
3694set_random_tRNS(png_structp pp, png_infop pi, png_byte colour_type,
3695 int bit_depth)
3696{
3697 /* To make this useful the tRNS color needs to match at least one pixel.
3698 * Random values are fine for gray, including the 16-bit case where we know
3699 * that the test image contains all the gray values. For RGB we need more
3700 * method as only 65536 different RGB values are generated.
3701 */
3702 png_color_16 tRNS;
3703 png_uint_16 mask = (png_uint_16)((1U << bit_depth)-1);
3704
3705 R8(tRNS); /* makes unset fields random */
3706
3707 if (colour_type & 2/*RGB*/)
3708 {
3709 if (bit_depth == 8)
3710 {
3711 tRNS.red = random_u16();
3712 tRNS.green = random_u16();
3713 tRNS.blue = tRNS.red ^ tRNS.green;
3714 tRNS.red &= mask;
3715 tRNS.green &= mask;
3716 tRNS.blue &= mask;
3717 }
3718
3719 else /* bit_depth == 16 */
3720 {
3721 tRNS.red = random_u16();
3722 tRNS.green = (png_uint_16)(tRNS.red * 257);
3723 tRNS.blue = (png_uint_16)(tRNS.green * 17);
3724 }
3725 }
3726
3727 else
3728 {
3729 tRNS.gray = random_u16();
3730 tRNS.gray &= mask;
3731 }
3732
3733 png_set_tRNS(pp, pi, NULL, 0, &tRNS);
3734}
3735#endif
3736
3737/* The number of passes is related to the interlace type. There was no libpng
3738 * API to determine this prior to 1.5, so we need an inquiry function:
3739 */
3740static int
3741npasses_from_interlace_type(png_const_structp pp, int interlace_type)
3742{
3743 switch (interlace_type)
3744 {
3745 default:
3746 png_error(pp, "invalid interlace type");
3747
3748 case PNG_INTERLACE_NONE:
3749 return 1;
3750
3751 case PNG_INTERLACE_ADAM7:
3752 return PNG_INTERLACE_ADAM7_PASSES;
3753 }
3754}
3755
3756static unsigned int
3757bit_size(png_const_structp pp, png_byte colour_type, png_byte bit_depth)
3758{
3759 switch (colour_type)
3760 {
3761 default: png_error(pp, "invalid color type");
3762
3763 case 0: return bit_depth;
3764
3765 case 2: return 3*bit_depth;
3766
3767 case 3: return bit_depth;
3768
3769 case 4: return 2*bit_depth;
3770
3771 case 6: return 4*bit_depth;
3772 }
3773}
3774
3775#define TRANSFORM_WIDTH 128U
3776#define TRANSFORM_ROWMAX (TRANSFORM_WIDTH*8U)
3777#define SIZE_ROWMAX (16*8U) /* 16 pixels, max 8 bytes each - 128 bytes */
3778#define STANDARD_ROWMAX TRANSFORM_ROWMAX /* The larger of the two */
3779#define SIZE_HEIGHTMAX 16 /* Maximum range of size images */
3780
3781static size_t
3782transform_rowsize(png_const_structp pp, png_byte colour_type,
3783 png_byte bit_depth)
3784{
3785 return (TRANSFORM_WIDTH * bit_size(pp, colour_type, bit_depth)) / 8;
3786}
3787
3788/* transform_width(pp, colour_type, bit_depth) current returns the same number
3789 * every time, so just use a macro:
3790 */
3791#define transform_width(pp, colour_type, bit_depth) TRANSFORM_WIDTH
3792
3793static png_uint_32
3794transform_height(png_const_structp pp, png_byte colour_type, png_byte bit_depth)
3795{
3796 switch (bit_size(pp, colour_type, bit_depth))
3797 {
3798 case 1:
3799 case 2:
3800 case 4:
3801 return 1; /* Total of 128 pixels */
3802
3803 case 8:
3804 return 2; /* Total of 256 pixels/bytes */
3805
3806 case 16:
3807 return 512; /* Total of 65536 pixels */
3808
3809 case 24:
3810 case 32:
3811 return 512; /* 65536 pixels */
3812
3813 case 48:
3814 case 64:
3815 return 2048;/* 4 x 65536 pixels. */
3816# define TRANSFORM_HEIGHTMAX 2048
3817
3818 default:
3819 return 0; /* Error, will be caught later */
3820 }
3821}
3822
3823#ifdef PNG_READ_SUPPORTED
3824/* The following can only be defined here, now we have the definitions
3825 * of the transform image sizes.
3826 */
3827static png_uint_32
3828standard_width(png_const_structp pp, png_uint_32 id)
3829{
3830 png_uint_32 width = WIDTH_FROM_ID(id);
3831 UNUSED(pp)
3832
3833 if (width == 0)
3834 width = transform_width(pp, COL_FROM_ID(id), DEPTH_FROM_ID(id));
3835
3836 return width;
3837}
3838
3839static png_uint_32
3840standard_height(png_const_structp pp, png_uint_32 id)
3841{
3842 png_uint_32 height = HEIGHT_FROM_ID(id);
3843
3844 if (height == 0)
3845 height = transform_height(pp, COL_FROM_ID(id), DEPTH_FROM_ID(id));
3846
3847 return height;
3848}
3849
3850static png_uint_32
3851standard_rowsize(png_const_structp pp, png_uint_32 id)
3852{
3853 png_uint_32 width = standard_width(pp, id);
3854
3855 /* This won't overflow: */
3856 width *= bit_size(pp, COL_FROM_ID(id), DEPTH_FROM_ID(id));
3857 return (width + 7) / 8;
3858}
3859#endif /* PNG_READ_SUPPORTED */
3860
3861static void
3862transform_row(png_const_structp pp, png_byte buffer[TRANSFORM_ROWMAX],
3863 png_byte colour_type, png_byte bit_depth, png_uint_32 y)
3864{
3865 png_uint_32 v = y << 7;
3866 png_uint_32 i = 0;
3867
3868 switch (bit_size(pp, colour_type, bit_depth))
3869 {
3870 case 1:
3871 while (i<128/8) buffer[i] = (png_byte)(v & 0xff), v += 17, ++i;
3872 return;
3873
3874 case 2:
3875 while (i<128/4) buffer[i] = (png_byte)(v & 0xff), v += 33, ++i;
3876 return;
3877
3878 case 4:
3879 while (i<128/2) buffer[i] = (png_byte)(v & 0xff), v += 65, ++i;
3880 return;
3881
3882 case 8:
3883 /* 256 bytes total, 128 bytes in each row set as follows: */
3884 while (i<128) buffer[i] = (png_byte)(v & 0xff), ++v, ++i;
3885 return;
3886
3887 case 16:
3888 /* Generate all 65536 pixel values in order, which includes the 8 bit
3889 * GA case as well as the 16 bit G case.
3890 */
3891 while (i<128)
3892 {
3893 buffer[2*i] = (png_byte)((v>>8) & 0xff);
3894 buffer[2*i+1] = (png_byte)(v & 0xff);
3895 ++v;
3896 ++i;
3897 }
3898
3899 return;
3900
3901 case 24:
3902 /* 65535 pixels, but rotate the values. */
3903 while (i<128)
3904 {
3905 /* Three bytes per pixel, r, g, b, make b by r^g */
3906 buffer[3*i+0] = (png_byte)((v >> 8) & 0xff);
3907 buffer[3*i+1] = (png_byte)(v & 0xff);
3908 buffer[3*i+2] = (png_byte)(((v >> 8) ^ v) & 0xff);
3909 ++v;
3910 ++i;
3911 }
3912
3913 return;
3914
3915 case 32:
3916 /* 65535 pixels, r, g, b, a; just replicate */
3917 while (i<128)
3918 {
3919 buffer[4*i+0] = (png_byte)((v >> 8) & 0xff);
3920 buffer[4*i+1] = (png_byte)(v & 0xff);
3921 buffer[4*i+2] = (png_byte)((v >> 8) & 0xff);
3922 buffer[4*i+3] = (png_byte)(v & 0xff);
3923 ++v;
3924 ++i;
3925 }
3926
3927 return;
3928
3929 case 48:
3930 /* y is maximum 2047, giving 4x65536 pixels, make 'r' increase by 1 at
3931 * each pixel, g increase by 257 (0x101) and 'b' by 0x1111:
3932 */
3933 while (i<128)
3934 {
3935 png_uint_32 t = v++;
3936 buffer[6*i+0] = (png_byte)((t >> 8) & 0xff);
3937 buffer[6*i+1] = (png_byte)(t & 0xff);
3938 t *= 257;
3939 buffer[6*i+2] = (png_byte)((t >> 8) & 0xff);
3940 buffer[6*i+3] = (png_byte)(t & 0xff);
3941 t *= 17;
3942 buffer[6*i+4] = (png_byte)((t >> 8) & 0xff);
3943 buffer[6*i+5] = (png_byte)(t & 0xff);
3944 ++i;
3945 }
3946
3947 return;
3948
3949 case 64:
3950 /* As above in the 32 bit case. */
3951 while (i<128)
3952 {
3953 png_uint_32 t = v++;
3954 buffer[8*i+0] = (png_byte)((t >> 8) & 0xff);
3955 buffer[8*i+1] = (png_byte)(t & 0xff);
3956 buffer[8*i+4] = (png_byte)((t >> 8) & 0xff);
3957 buffer[8*i+5] = (png_byte)(t & 0xff);
3958 t *= 257;
3959 buffer[8*i+2] = (png_byte)((t >> 8) & 0xff);
3960 buffer[8*i+3] = (png_byte)(t & 0xff);
3961 buffer[8*i+6] = (png_byte)((t >> 8) & 0xff);
3962 buffer[8*i+7] = (png_byte)(t & 0xff);
3963 ++i;
3964 }
3965 return;
3966
3967 default:
3968 break;
3969 }
3970
3971 png_error(pp, "internal error");
3972}
3973
3974/* This is just to do the right cast - could be changed to a function to check
3975 * 'bd' but there isn't much point.
3976 */
3977#define DEPTH(bd) ((png_byte)(1U << (bd)))
3978
3979/* This is just a helper for compiling on minimal systems with no write
3980 * interlacing support. If there is no write interlacing we can't generate test
3981 * cases with interlace:
3982 */
3983#ifdef PNG_WRITE_INTERLACING_SUPPORTED
3984# define INTERLACE_LAST PNG_INTERLACE_LAST
3985# define check_interlace_type(type) ((void)(type))
3986# define set_write_interlace_handling(pp,type) png_set_interlace_handling(pp)
3987# define do_own_interlace 0
3988#elif PNG_LIBPNG_VER != 10700
3989# define set_write_interlace_handling(pp,type) (1)
3990static void
3991check_interlace_type(int const interlace_type)
3992{
3993 /* Prior to 1.7.0 libpng does not support the write of an interlaced image
3994 * unless PNG_WRITE_INTERLACING_SUPPORTED, even with do_interlace so the
3995 * code here does the pixel interlace itself, so:
3996 */
3997 if (interlace_type != PNG_INTERLACE_NONE)
3998 {
3999 /* This is an internal error - --interlace tests should be skipped, not
4000 * attempted.
4001 */
4002 fprintf(stderr, "pngvalid: no interlace support\n");
4003 exit(99);
4004 }
4005}
4006# define INTERLACE_LAST (PNG_INTERLACE_NONE+1)
4007# define do_own_interlace 0
4008#else /* libpng 1.7+ */
4009# define set_write_interlace_handling(pp,type)\
4010 npasses_from_interlace_type(pp,type)
4011# define check_interlace_type(type) ((void)(type))
4012# define INTERLACE_LAST PNG_INTERLACE_LAST
4013# define do_own_interlace 1
4014#endif /* WRITE_INTERLACING tests */
4015
4016#if PNG_LIBPNG_VER == 10700 || defined PNG_WRITE_INTERLACING_SUPPORTED
4017# define CAN_WRITE_INTERLACE 1
4018#else
4019# define CAN_WRITE_INTERLACE 0
4020#endif
4021
4022/* Do the same thing for read interlacing; this controls whether read tests do
4023 * their own de-interlace or use libpng.
4024 */
4025#ifdef PNG_READ_INTERLACING_SUPPORTED
4026# define do_read_interlace 0
4027#else /* no libpng read interlace support */
4028# define do_read_interlace 1
4029#endif
4030/* The following two routines use the PNG interlace support macros from
4031 * png.h to interlace or deinterlace rows.
4032 */
4033static void
4034interlace_row(png_bytep buffer, png_const_bytep imageRow,
4035 unsigned int pixel_size, png_uint_32 w, int pass, int littleendian)
4036{
4037 png_uint_32 xin, xout, xstep;
4038
4039 /* Note that this can, trivially, be optimized to a memcpy on pass 7, the
4040 * code is presented this way to make it easier to understand. In practice
4041 * consult the code in the libpng source to see other ways of doing this.
4042 *
4043 * It is OK for buffer and imageRow to be identical, because 'xin' moves
4044 * faster than 'xout' and we copy up.
4045 */
4046 xin = PNG_PASS_START_COL(pass);
4047 xstep = 1U<<PNG_PASS_COL_SHIFT(pass);
4048
4049 for (xout=0; xin<w; xin+=xstep)
4050 {
4051 pixel_copy(buffer, xout, imageRow, xin, pixel_size, littleendian);
4052 ++xout;
4053 }
4054}
4055
4056#ifdef PNG_READ_SUPPORTED
4057static void
4058deinterlace_row(png_bytep buffer, png_const_bytep row,
4059 unsigned int pixel_size, png_uint_32 w, int pass, int littleendian)
4060{
4061 /* The inverse of the above, 'row' is part of row 'y' of the output image,
4062 * in 'buffer'. The image is 'w' wide and this is pass 'pass', distribute
4063 * the pixels of row into buffer and return the number written (to allow
4064 * this to be checked).
4065 */
4066 png_uint_32 xin, xout, xstep;
4067
4068 xout = PNG_PASS_START_COL(pass);
4069 xstep = 1U<<PNG_PASS_COL_SHIFT(pass);
4070
4071 for (xin=0; xout<w; xout+=xstep)
4072 {
4073 pixel_copy(buffer, xout, row, xin, pixel_size, littleendian);
4074 ++xin;
4075 }
4076}
4077#endif /* PNG_READ_SUPPORTED */
4078
4079/* Make a standardized image given an image colour type, bit depth and
4080 * interlace type. The standard images have a very restricted range of
4081 * rows and heights and are used for testing transforms rather than image
4082 * layout details. See make_size_images below for a way to make images
4083 * that test odd sizes along with the libpng interlace handling.
4084 */
4085#ifdef PNG_WRITE_FILTER_SUPPORTED
4086static void
4087choose_random_filter(png_structp pp, int start)
4088{
4089 /* Choose filters randomly except that on the very first row ensure that
4090 * there is at least one previous row filter.
4091 */
4092 int filters = PNG_ALL_FILTERS & random_mod(256U);
4093
4094 /* There may be no filters; skip the setting. */
4095 if (filters != 0)
4096 {
4097 if (start && filters < PNG_FILTER_UP)
4098 filters |= PNG_FILTER_UP;
4099
4100 png_set_filter(pp, 0/*method*/, filters);
4101 }
4102}
4103#else /* !WRITE_FILTER */
4104# define choose_random_filter(pp, start) ((void)0)
4105#endif /* !WRITE_FILTER */
4106
4107static void
4108make_transform_image(png_store* const ps, png_byte const colour_type,
4109 png_byte const bit_depth, unsigned int palette_number,
4110 int interlace_type, png_const_charp name)
4111{
4112 context(ps, fault);
4113
4114 check_interlace_type(interlace_type);
4115
4116 Try
4117 {
4118 png_infop pi;
4119 png_structp pp = set_store_for_write(ps, &pi, name);
4120 png_uint_32 h, w;
4121
4122 /* In the event of a problem return control to the Catch statement below
4123 * to do the clean up - it is not possible to 'return' directly from a Try
4124 * block.
4125 */
4126 if (pp == NULL)
4127 Throw ps;
4128
4129 w = transform_width(pp, colour_type, bit_depth);
4130 h = transform_height(pp, colour_type, bit_depth);
4131
4132 png_set_IHDR(pp, pi, w, h, bit_depth, colour_type, interlace_type,
4133 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
4134
4135#ifdef PNG_TEXT_SUPPORTED
4136# if defined(PNG_READ_zTXt_SUPPORTED) && defined(PNG_WRITE_zTXt_SUPPORTED)
4137# define TEXT_COMPRESSION PNG_TEXT_COMPRESSION_zTXt
4138# else
4139# define TEXT_COMPRESSION PNG_TEXT_COMPRESSION_NONE
4140# endif
4141 {
4142 static char key[] = "image name"; /* must be writeable */
4143 size_t pos;
4144 png_text text;
4145 char copy[FILE_NAME_SIZE];
4146
4147 /* Use a compressed text string to test the correct interaction of text
4148 * compression and IDAT compression.
4149 */
4150 text.compression = TEXT_COMPRESSION;
4151 text.key = key;
4152 /* Yuck: the text must be writable! */
4153 pos = safecat(copy, sizeof copy, 0, ps->wname);
4154 text.text = copy;
4155 text.text_length = pos;
4156 text.itxt_length = 0;
4157 text.lang = 0;
4158 text.lang_key = 0;
4159
4160 png_set_text(pp, pi, &text, 1);
4161 }
4162#endif
4163
4164 if (colour_type == 3) /* palette */
4165 init_standard_palette(ps, pp, pi, 1U << bit_depth, 1/*do tRNS*/);
4166
4167# ifdef PNG_WRITE_tRNS_SUPPORTED
4168 else if (palette_number)
4169 set_random_tRNS(pp, pi, colour_type, bit_depth);
4170# endif
4171
4172 png_write_info(pp, pi);
4173
4174 if (png_get_rowbytes(pp, pi) !=
4175 transform_rowsize(pp, colour_type, bit_depth))
4176 png_error(pp, "transform row size incorrect");
4177
4178 else
4179 {
4180 /* Somewhat confusingly this must be called *after* png_write_info
4181 * because if it is called before, the information in *pp has not been
4182 * updated to reflect the interlaced image.
4183 */
4184 int npasses = set_write_interlace_handling(pp, interlace_type);
4185 int pass;
4186
4187 if (npasses != npasses_from_interlace_type(pp, interlace_type))
4188 png_error(pp, "write: png_set_interlace_handling failed");
4189
4190 for (pass=0; pass<npasses; ++pass)
4191 {
4192 png_uint_32 y;
4193
4194 /* do_own_interlace is a pre-defined boolean (a #define) which is
4195 * set if we have to work out the interlaced rows here.
4196 */
4197 for (y=0; y<h; ++y)
4198 {
4199 png_byte buffer[TRANSFORM_ROWMAX];
4200
4201 transform_row(pp, buffer, colour_type, bit_depth, y);
4202
4203# if do_own_interlace
4204 /* If do_own_interlace *and* the image is interlaced we need a
4205 * reduced interlace row; this may be reduced to empty.
4206 */
4207 if (interlace_type == PNG_INTERLACE_ADAM7)
4208 {
4209 /* The row must not be written if it doesn't exist, notice
4210 * that there are two conditions here, either the row isn't
4211 * ever in the pass or the row would be but isn't wide
4212 * enough to contribute any pixels. In fact the wPass test
4213 * can be used to skip the whole y loop in this case.
4214 */
4215 if (PNG_ROW_IN_INTERLACE_PASS(y, pass) &&
4216 PNG_PASS_COLS(w, pass) > 0)
4217 interlace_row(buffer, buffer,
4218 bit_size(pp, colour_type, bit_depth), w, pass,
4219 0/*data always bigendian*/);
4220 else
4221 continue;
4222 }
4223# endif /* do_own_interlace */
4224
4225 choose_random_filter(pp, pass == 0 && y == 0);
4226 png_write_row(pp, buffer);
4227 }
4228 }
4229 }
4230
4231#ifdef PNG_TEXT_SUPPORTED
4232 {
4233 static char key[] = "end marker";
4234 static char comment[] = "end";
4235 png_text text;
4236
4237 /* Use a compressed text string to test the correct interaction of text
4238 * compression and IDAT compression.
4239 */
4240 text.compression = TEXT_COMPRESSION;
4241 text.key = key;
4242 text.text = comment;
4243 text.text_length = (sizeof comment)-1;
4244 text.itxt_length = 0;
4245 text.lang = 0;
4246 text.lang_key = 0;
4247
4248 png_set_text(pp, pi, &text, 1);
4249 }
4250#endif
4251
4252 png_write_end(pp, pi);
4253
4254 /* And store this under the appropriate id, then clean up. */
4255 store_storefile(ps, FILEID(colour_type, bit_depth, palette_number,
4256 interlace_type, 0, 0, 0));
4257
4258 store_write_reset(ps);
4259 }
4260
4261 Catch(fault)
4262 {
4263 /* Use the png_store returned by the exception. This may help the compiler
4264 * because 'ps' is not used in this branch of the setjmp. Note that fault
4265 * and ps will always be the same value.
4266 */
4267 store_write_reset(fault);
4268 }
4269}
4270
4271static void
4272make_transform_images(png_modifier *pm)
4273{
4274 png_byte colour_type = 0;
4275 png_byte bit_depth = 0;
4276 unsigned int palette_number = 0;
4277
4278 /* This is in case of errors. */
4279 safecat(pm->this.test, sizeof pm->this.test, 0, "make standard images");
4280
4281 /* Use next_format to enumerate all the combinations we test, including
4282 * generating multiple low bit depth palette images. Non-A images (palette
4283 * and direct) are created with and without tRNS chunks.
4284 */
4285 while (next_format(&colour_type, &bit_depth, &palette_number, 1, 1))
4286 {
4287 int interlace_type;
4288
4289 for (interlace_type = PNG_INTERLACE_NONE;
4290 interlace_type < INTERLACE_LAST; ++interlace_type)
4291 {
4292 char name[FILE_NAME_SIZE];
4293
4294 standard_name(name, sizeof name, 0, colour_type, bit_depth,
4295 palette_number, interlace_type, 0, 0, do_own_interlace);
4296 make_transform_image(&pm->this, colour_type, bit_depth, palette_number,
4297 interlace_type, name);
4298 }
4299 }
4300}
4301
4302/* Build a single row for the 'size' test images; this fills in only the
4303 * first bit_width bits of the sample row.
4304 */
4305static void
4306size_row(png_byte buffer[SIZE_ROWMAX], png_uint_32 bit_width, png_uint_32 y)
4307{
4308 /* height is in the range 1 to 16, so: */
4309 y = ((y & 1) << 7) + ((y & 2) << 6) + ((y & 4) << 5) + ((y & 8) << 4);
4310 /* the following ensures bits are set in small images: */
4311 y ^= 0xA5;
4312
4313 while (bit_width >= 8)
4314 *buffer++ = (png_byte)y++, bit_width -= 8;
4315
4316 /* There may be up to 7 remaining bits, these go in the most significant
4317 * bits of the byte.
4318 */
4319 if (bit_width > 0)
4320 {
4321 png_uint_32 mask = (1U<<(8-bit_width))-1;
4322 *buffer = (png_byte)((*buffer & mask) | (y & ~mask));
4323 }
4324}
4325
4326static void
4327make_size_image(png_store* const ps, png_byte const colour_type,
4328 png_byte const bit_depth, int const interlace_type,
4329 png_uint_32 const w, png_uint_32 const h,
4330 int const do_interlace)
4331{
4332 context(ps, fault);
4333
4334 check_interlace_type(interlace_type);
4335
4336 Try
4337 {
4338 png_infop pi;
4339 png_structp pp;
4340 unsigned int pixel_size;
4341
4342 /* Make a name and get an appropriate id for the store: */
4343 char name[FILE_NAME_SIZE];
4344 png_uint_32 id = FILEID(colour_type, bit_depth, 0/*palette*/,
4345 interlace_type, w, h, do_interlace);
4346
4347 standard_name_from_id(name, sizeof name, 0, id);
4348 pp = set_store_for_write(ps, &pi, name);
4349
4350 /* In the event of a problem return control to the Catch statement below
4351 * to do the clean up - it is not possible to 'return' directly from a Try
4352 * block.
4353 */
4354 if (pp == NULL)
4355 Throw ps;
4356
4357 png_set_IHDR(pp, pi, w, h, bit_depth, colour_type, interlace_type,
4358 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
4359
4360#ifdef PNG_TEXT_SUPPORTED
4361 {
4362 static char key[] = "image name"; /* must be writeable */
4363 size_t pos;
4364 png_text text;
4365 char copy[FILE_NAME_SIZE];
4366
4367 /* Use a compressed text string to test the correct interaction of text
4368 * compression and IDAT compression.
4369 */
4370 text.compression = TEXT_COMPRESSION;
4371 text.key = key;
4372 /* Yuck: the text must be writable! */
4373 pos = safecat(copy, sizeof copy, 0, ps->wname);
4374 text.text = copy;
4375 text.text_length = pos;
4376 text.itxt_length = 0;
4377 text.lang = 0;
4378 text.lang_key = 0;
4379
4380 png_set_text(pp, pi, &text, 1);
4381 }
4382#endif
4383
4384 if (colour_type == 3) /* palette */
4385 init_standard_palette(ps, pp, pi, 1U << bit_depth, 0/*do tRNS*/);
4386
4387 png_write_info(pp, pi);
4388
4389 /* Calculate the bit size, divide by 8 to get the byte size - this won't
4390 * overflow because we know the w values are all small enough even for
4391 * a system where 'unsigned int' is only 16 bits.
4392 */
4393 pixel_size = bit_size(pp, colour_type, bit_depth);
4394 if (png_get_rowbytes(pp, pi) != ((w * pixel_size) + 7) / 8)
4395 png_error(pp, "size row size incorrect");
4396
4397 else
4398 {
4399 int npasses = npasses_from_interlace_type(pp, interlace_type);
4400 png_uint_32 y;
4401 int pass;
4402 png_byte image[16][SIZE_ROWMAX];
4403
4404 /* To help consistent error detection make the parts of this buffer
4405 * that aren't set below all '1':
4406 */
4407 memset(image, 0xff, sizeof image);
4408
4409 if (!do_interlace &&
4410 npasses != set_write_interlace_handling(pp, interlace_type))
4411 png_error(pp, "write: png_set_interlace_handling failed");
4412
4413 /* Prepare the whole image first to avoid making it 7 times: */
4414 for (y=0; y<h; ++y)
4415 size_row(image[y], w * pixel_size, y);
4416
4417 for (pass=0; pass<npasses; ++pass)
4418 {
4419 /* The following two are for checking the macros: */
4420 png_uint_32 wPass = PNG_PASS_COLS(w, pass);
4421
4422 /* If do_interlace is set we don't call png_write_row for every
4423 * row because some of them are empty. In fact, for a 1x1 image,
4424 * most of them are empty!
4425 */
4426 for (y=0; y<h; ++y)
4427 {
4428 png_const_bytep row = image[y];
4429 png_byte tempRow[SIZE_ROWMAX];
4430
4431 /* If do_interlace *and* the image is interlaced we
4432 * need a reduced interlace row; this may be reduced
4433 * to empty.
4434 */
4435 if (do_interlace && interlace_type == PNG_INTERLACE_ADAM7)
4436 {
4437 /* The row must not be written if it doesn't exist, notice
4438 * that there are two conditions here, either the row isn't
4439 * ever in the pass or the row would be but isn't wide
4440 * enough to contribute any pixels. In fact the wPass test
4441 * can be used to skip the whole y loop in this case.
4442 */
4443 if (PNG_ROW_IN_INTERLACE_PASS(y, pass) && wPass > 0)
4444 {
4445 /* Set to all 1's for error detection (libpng tends to
4446 * set unset things to 0).
4447 */
4448 memset(tempRow, 0xff, sizeof tempRow);
4449 interlace_row(tempRow, row, pixel_size, w, pass,
4450 0/*data always bigendian*/);
4451 row = tempRow;
4452 }
4453 else
4454 continue;
4455 }
4456
4457# ifdef PNG_WRITE_FILTER_SUPPORTED
4458 /* Only get to here if the row has some pixels in it, set the
4459 * filters to 'all' for the very first row and thereafter to a
4460 * single filter. It isn't well documented, but png_set_filter
4461 * does accept a filter number (per the spec) as well as a bit
4462 * mask.
4463 *
4464 * The code now uses filters at random, except that on the first
4465 * row of an image it ensures that a previous row filter is in
4466 * the set so that libpng allocates the row buffer.
4467 */
4468 {
4469 int filters = 8 << random_mod(PNG_FILTER_VALUE_LAST);
4470
4471 if (pass == 0 && y == 0 &&
4472 (filters < PNG_FILTER_UP || w == 1U))
4473 filters |= PNG_FILTER_UP;
4474
4475 png_set_filter(pp, 0/*method*/, filters);
4476 }
4477# endif
4478
4479 png_write_row(pp, row);
4480 }
4481 }
4482 }
4483
4484#ifdef PNG_TEXT_SUPPORTED
4485 {
4486 static char key[] = "end marker";
4487 static char comment[] = "end";
4488 png_text text;
4489
4490 /* Use a compressed text string to test the correct interaction of text
4491 * compression and IDAT compression.
4492 */
4493 text.compression = TEXT_COMPRESSION;
4494 text.key = key;
4495 text.text = comment;
4496 text.text_length = (sizeof comment)-1;
4497 text.itxt_length = 0;
4498 text.lang = 0;
4499 text.lang_key = 0;
4500
4501 png_set_text(pp, pi, &text, 1);
4502 }
4503#endif
4504
4505 png_write_end(pp, pi);
4506
4507 /* And store this under the appropriate id, then clean up. */
4508 store_storefile(ps, id);
4509
4510 store_write_reset(ps);
4511 }
4512
4513 Catch(fault)
4514 {
4515 /* Use the png_store returned by the exception. This may help the compiler
4516 * because 'ps' is not used in this branch of the setjmp. Note that fault
4517 * and ps will always be the same value.
4518 */
4519 store_write_reset(fault);
4520 }
4521}
4522
4523static void
4524make_size(png_store* const ps, png_byte const colour_type, int bdlo,
4525 int const bdhi)
4526{
4527 for (; bdlo <= bdhi; ++bdlo)
4528 {
4529 png_uint_32 width;
4530
4531 for (width = 1; width <= 16; ++width)
4532 {
4533 png_uint_32 height;
4534
4535 for (height = 1; height <= 16; ++height)
4536 {
4537 /* The four combinations of DIY interlace and interlace or not -
4538 * no interlace + DIY should be identical to no interlace with
4539 * libpng doing it.
4540 */
4541 make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_NONE,
4542 width, height, 0);
4543 make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_NONE,
4544 width, height, 1);
4545# ifdef PNG_WRITE_INTERLACING_SUPPORTED
4546 make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_ADAM7,
4547 width, height, 0);
4548# endif
4549# if CAN_WRITE_INTERLACE
4550 /* 1.7.0 removes the hack that prevented app write of an interlaced
4551 * image if WRITE_INTERLACE was not supported
4552 */
4553 make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_ADAM7,
4554 width, height, 1);
4555# endif
4556 }
4557 }
4558 }
4559}
4560
4561static void
4562make_size_images(png_store *ps)
4563{
4564 /* This is in case of errors. */
4565 safecat(ps->test, sizeof ps->test, 0, "make size images");
4566
4567 /* Arguments are colour_type, low bit depth, high bit depth
4568 */
4569 make_size(ps, 0, 0, WRITE_BDHI);
4570 make_size(ps, 2, 3, WRITE_BDHI);
4571 make_size(ps, 3, 0, 3 /*palette: max 8 bits*/);
4572 make_size(ps, 4, 3, WRITE_BDHI);
4573 make_size(ps, 6, 3, WRITE_BDHI);
4574}
4575
4576#ifdef PNG_READ_SUPPORTED
4577/* Return a row based on image id and 'y' for checking: */
4578static void
4579standard_row(png_const_structp pp, png_byte std[STANDARD_ROWMAX],
4580 png_uint_32 id, png_uint_32 y)
4581{
4582 if (WIDTH_FROM_ID(id) == 0)
4583 transform_row(pp, std, COL_FROM_ID(id), DEPTH_FROM_ID(id), y);
4584 else
4585 size_row(std, WIDTH_FROM_ID(id) * bit_size(pp, COL_FROM_ID(id),
4586 DEPTH_FROM_ID(id)), y);
4587}
4588#endif /* PNG_READ_SUPPORTED */
4589
4590/* Tests - individual test cases */
4591/* Like 'make_standard' but errors are deliberately introduced into the calls
4592 * to ensure that they get detected - it should not be possible to write an
4593 * invalid image with libpng!
4594 */
4595/* TODO: the 'set' functions can probably all be made to take a
4596 * png_const_structp rather than a modifiable one.
4597 */
4598#ifdef PNG_WARNINGS_SUPPORTED
4599static void
4600sBIT0_error_fn(png_structp pp, png_infop pi)
4601{
4602 /* 0 is invalid... */
4603 png_color_8 bad;
4604 bad.red = bad.green = bad.blue = bad.gray = bad.alpha = 0;
4605 png_set_sBIT(pp, pi, &bad);
4606}
4607
4608static void
4609sBIT_error_fn(png_structp pp, png_infop pi)
4610{
4611 png_byte bit_depth;
4612 png_color_8 bad;
4613
4614 if (png_get_color_type(pp, pi) == PNG_COLOR_TYPE_PALETTE)
4615 bit_depth = 8;
4616
4617 else
4618 bit_depth = png_get_bit_depth(pp, pi);
4619
4620 /* Now we know the bit depth we can easily generate an invalid sBIT entry */
4621 bad.red = bad.green = bad.blue = bad.gray = bad.alpha =
4622 (png_byte)(bit_depth+1);
4623 png_set_sBIT(pp, pi, &bad);
4624}
4625
4626static const struct
4627{
4628 void (*fn)(png_structp, png_infop);
4629 const char *msg;
4630 unsigned int warning :1; /* the error is a warning... */
4631} error_test[] =
4632 {
4633 /* no warnings makes these errors undetectable prior to 1.7.0 */
4634 { sBIT0_error_fn, "sBIT(0): failed to detect error",
4635 PNG_LIBPNG_VER != 10700 },
4636
4637 { sBIT_error_fn, "sBIT(too big): failed to detect error",
4638 PNG_LIBPNG_VER != 10700 },
4639 };
4640
4641static void
4642make_error(png_store* const ps, png_byte const colour_type,
4643 png_byte bit_depth, int interlace_type, int test, png_const_charp name)
4644{
4645 context(ps, fault);
4646
4647 check_interlace_type(interlace_type);
4648
4649 Try
4650 {
4651 png_infop pi;
4652 png_structp pp = set_store_for_write(ps, &pi, name);
4653 png_uint_32 w, h;
4654 gnu_volatile(pp)
4655
4656 if (pp == NULL)
4657 Throw ps;
4658
4659 w = transform_width(pp, colour_type, bit_depth);
4660 gnu_volatile(w)
4661 h = transform_height(pp, colour_type, bit_depth);
4662 gnu_volatile(h)
4663 png_set_IHDR(pp, pi, w, h, bit_depth, colour_type, interlace_type,
4664 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
4665
4666 if (colour_type == 3) /* palette */
4667 init_standard_palette(ps, pp, pi, 1U << bit_depth, 0/*do tRNS*/);
4668
4669 /* Time for a few errors; these are in various optional chunks, the
4670 * standard tests test the standard chunks pretty well.
4671 */
4672# define exception__prev exception_prev_1
4673# define exception__env exception_env_1
4674 Try
4675 {
4676 gnu_volatile(exception__prev)
4677
4678 /* Expect this to throw: */
4679 ps->expect_error = !error_test[test].warning;
4680 ps->expect_warning = error_test[test].warning;
4681 ps->saw_warning = 0;
4682 error_test[test].fn(pp, pi);
4683
4684 /* Normally the error is only detected here: */
4685 png_write_info(pp, pi);
4686
4687 /* And handle the case where it was only a warning: */
4688 if (ps->expect_warning && ps->saw_warning)
4689 Throw ps;
4690
4691 /* If we get here there is a problem, we have success - no error or
4692 * no warning - when we shouldn't have success. Log an error.
4693 */
4694 store_log(ps, pp, error_test[test].msg, 1 /*error*/);
4695 }
4696
4697 Catch (fault)
4698 { /* expected exit */
4699 }
4700#undef exception__prev
4701#undef exception__env
4702
4703 /* And clear these flags */
4704 ps->expect_warning = 0;
4705
4706 if (ps->expect_error)
4707 ps->expect_error = 0;
4708
4709 else
4710 {
4711 /* Now write the whole image, just to make sure that the detected, or
4712 * undetected, error has not created problems inside libpng. This
4713 * doesn't work if there was a png_error in png_write_info because that
4714 * can abort before PLTE was written.
4715 */
4716 if (png_get_rowbytes(pp, pi) !=
4717 transform_rowsize(pp, colour_type, bit_depth))
4718 png_error(pp, "row size incorrect");
4719
4720 else
4721 {
4722 int npasses = set_write_interlace_handling(pp, interlace_type);
4723 int pass;
4724
4725 if (npasses != npasses_from_interlace_type(pp, interlace_type))
4726 png_error(pp, "write: png_set_interlace_handling failed");
4727
4728 for (pass=0; pass<npasses; ++pass)
4729 {
4730 png_uint_32 y;
4731
4732 for (y=0; y<h; ++y)
4733 {
4734 png_byte buffer[TRANSFORM_ROWMAX];
4735
4736 transform_row(pp, buffer, colour_type, bit_depth, y);
4737
4738# if do_own_interlace
4739 /* If do_own_interlace *and* the image is interlaced we
4740 * need a reduced interlace row; this may be reduced to
4741 * empty.
4742 */
4743 if (interlace_type == PNG_INTERLACE_ADAM7)
4744 {
4745 /* The row must not be written if it doesn't exist,
4746 * notice that there are two conditions here, either the
4747 * row isn't ever in the pass or the row would be but
4748 * isn't wide enough to contribute any pixels. In fact
4749 * the wPass test can be used to skip the whole y loop
4750 * in this case.
4751 */
4752 if (PNG_ROW_IN_INTERLACE_PASS(y, pass) &&
4753 PNG_PASS_COLS(w, pass) > 0)
4754 interlace_row(buffer, buffer,
4755 bit_size(pp, colour_type, bit_depth), w, pass,
4756 0/*data always bigendian*/);
4757 else
4758 continue;
4759 }
4760# endif /* do_own_interlace */
4761
4762 png_write_row(pp, buffer);
4763 }
4764 }
4765 } /* image writing */
4766
4767 png_write_end(pp, pi);
4768 }
4769
4770 /* The following deletes the file that was just written. */
4771 store_write_reset(ps);
4772 }
4773
4774 Catch(fault)
4775 {
4776 store_write_reset(fault);
4777 }
4778}
4779
4780static int
4781make_errors(png_modifier* const pm, png_byte const colour_type,
4782 int bdlo, int const bdhi)
4783{
4784 for (; bdlo <= bdhi; ++bdlo)
4785 {
4786 int interlace_type;
4787
4788 for (interlace_type = PNG_INTERLACE_NONE;
4789 interlace_type < INTERLACE_LAST; ++interlace_type)
4790 {
4791 unsigned int test;
4792 char name[FILE_NAME_SIZE];
4793
4794 standard_name(name, sizeof name, 0, colour_type, 1<<bdlo, 0,
4795 interlace_type, 0, 0, do_own_interlace);
4796
4797 for (test=0; test<ARRAY_SIZE(error_test); ++test)
4798 {
4799 make_error(&pm->this, colour_type, DEPTH(bdlo), interlace_type,
4800 test, name);
4801
4802 if (fail(pm))
4803 return 0;
4804 }
4805 }
4806 }
4807
4808 return 1; /* keep going */
4809}
4810#endif /* PNG_WARNINGS_SUPPORTED */
4811
4812static void
4813perform_error_test(png_modifier *pm)
4814{
4815#ifdef PNG_WARNINGS_SUPPORTED /* else there are no cases that work! */
4816 /* Need to do this here because we just write in this test. */
4817 safecat(pm->this.test, sizeof pm->this.test, 0, "error test");
4818
4819 if (!make_errors(pm, 0, 0, WRITE_BDHI))
4820 return;
4821
4822 if (!make_errors(pm, 2, 3, WRITE_BDHI))
4823 return;
4824
4825 if (!make_errors(pm, 3, 0, 3))
4826 return;
4827
4828 if (!make_errors(pm, 4, 3, WRITE_BDHI))
4829 return;
4830
4831 if (!make_errors(pm, 6, 3, WRITE_BDHI))
4832 return;
4833#else
4834 UNUSED(pm)
4835#endif
4836}
4837
4838/* This is just to validate the internal PNG formatting code - if this fails
4839 * then the warning messages the library outputs will probably be garbage.
4840 */
4841static void
4842perform_formatting_test(png_store *ps)
4843{
4844#ifdef PNG_TIME_RFC1123_SUPPORTED
4845 /* The handle into the formatting code is the RFC1123 support; this test does
4846 * nothing if that is compiled out.
4847 */
4848 context(ps, fault);
4849
4850 Try
4851 {
4852 png_const_charp correct = "29 Aug 2079 13:53:60 +0000";
4853 png_const_charp result;
4854# if PNG_LIBPNG_VER >= 10600
4855 char timestring[29];
4856# endif
4857 png_structp pp;
4858 png_time pt;
4859
4860 pp = set_store_for_write(ps, NULL, "libpng formatting test");
4861
4862 if (pp == NULL)
4863 Throw ps;
4864
4865
4866 /* Arbitrary settings: */
4867 pt.year = 2079;
4868 pt.month = 8;
4869 pt.day = 29;
4870 pt.hour = 13;
4871 pt.minute = 53;
4872 pt.second = 60; /* a leap second */
4873
4874# if PNG_LIBPNG_VER < 10600
4875 result = png_convert_to_rfc1123(pp, &pt);
4876# else
4877 if (png_convert_to_rfc1123_buffer(timestring, &pt))
4878 result = timestring;
4879
4880 else
4881 result = NULL;
4882# endif
4883
4884 if (result == NULL)
4885 png_error(pp, "png_convert_to_rfc1123 failed");
4886
4887 if (strcmp(result, correct) != 0)
4888 {
4889 size_t pos = 0;
4890 char msg[128];
4891
4892 pos = safecat(msg, sizeof msg, pos, "png_convert_to_rfc1123(");
4893 pos = safecat(msg, sizeof msg, pos, correct);
4894 pos = safecat(msg, sizeof msg, pos, ") returned: '");
4895 pos = safecat(msg, sizeof msg, pos, result);
4896 pos = safecat(msg, sizeof msg, pos, "'");
4897
4898 png_error(pp, msg);
4899 }
4900
4901 store_write_reset(ps);
4902 }
4903
4904 Catch(fault)
4905 {
4906 store_write_reset(fault);
4907 }
4908#else
4909 UNUSED(ps)
4910#endif
4911}
4912
4913#ifdef PNG_READ_SUPPORTED
4914/* Because we want to use the same code in both the progressive reader and the
4915 * sequential reader it is necessary to deal with the fact that the progressive
4916 * reader callbacks only have one parameter (png_get_progressive_ptr()), so this
4917 * must contain all the test parameters and all the local variables directly
4918 * accessible to the sequential reader implementation.
4919 *
4920 * The technique adopted is to reinvent part of what Dijkstra termed a
4921 * 'display'; an array of pointers to the stack frames of enclosing functions so
4922 * that a nested function definition can access the local (C auto) variables of
4923 * the functions that contain its definition. In fact C provides the first
4924 * pointer (the local variables - the stack frame pointer) and the last (the
4925 * global variables - the BCPL global vector typically implemented as global
4926 * addresses), this code requires one more pointer to make the display - the
4927 * local variables (and function call parameters) of the function that actually
4928 * invokes either the progressive or sequential reader.
4929 *
4930 * Perhaps confusingly this technique is confounded with classes - the
4931 * 'standard_display' defined here is sub-classed as the 'gamma_display' below.
4932 * A gamma_display is a standard_display, taking advantage of the ANSI-C
4933 * requirement that the pointer to the first member of a structure must be the
4934 * same as the pointer to the structure. This allows us to reuse standard_
4935 * functions in the gamma test code; something that could not be done with
4936 * nested functions!
4937 */
4938typedef struct standard_display
4939{
4940 png_store* ps; /* Test parameters (passed to the function) */
4941 png_byte colour_type;
4942 png_byte bit_depth;
4943 png_byte red_sBIT; /* Input data sBIT values. */
4944 png_byte green_sBIT;
4945 png_byte blue_sBIT;
4946 png_byte alpha_sBIT;
4947 png_byte interlace_type;
4948 png_byte filler; /* Output has a filler */
4949 png_uint_32 id; /* Calculated file ID */
4950 png_uint_32 w; /* Width of image */
4951 png_uint_32 h; /* Height of image */
4952 int npasses; /* Number of interlaced passes */
4953 png_uint_32 pixel_size; /* Width of one pixel in bits */
4954 png_uint_32 bit_width; /* Width of output row in bits */
4955 size_t cbRow; /* Bytes in a row of the output image */
4956 int do_interlace; /* Do interlacing internally */
4957 int littleendian; /* App (row) data is little endian */
4958 int is_transparent; /* Transparency information was present. */
4959 int has_tRNS; /* color type GRAY or RGB with a tRNS chunk. */
4960 int speed; /* Doing a speed test */
4961 int use_update_info;/* Call update_info, not start_image */
4962 struct
4963 {
4964 png_uint_16 red;
4965 png_uint_16 green;
4966 png_uint_16 blue;
4967 } transparent; /* The transparent color, if set. */
4968 int npalette; /* Number of entries in the palette. */
4969 store_palette
4970 palette;
4971} standard_display;
4972
4973static void
4974standard_display_init(standard_display *dp, png_store* ps, png_uint_32 id,
4975 int do_interlace, int use_update_info)
4976{
4977 memset(dp, 0, sizeof *dp);
4978
4979 dp->ps = ps;
4980 dp->colour_type = COL_FROM_ID(id);
4981 dp->bit_depth = DEPTH_FROM_ID(id);
4982 if (dp->bit_depth < 1 || dp->bit_depth > 16)
4983 internal_error(ps, "internal: bad bit depth");
4984 if (dp->colour_type == 3)
4985 dp->red_sBIT = dp->blue_sBIT = dp->green_sBIT = dp->alpha_sBIT = 8;
4986 else
4987 dp->red_sBIT = dp->blue_sBIT = dp->green_sBIT = dp->alpha_sBIT =
4988 dp->bit_depth;
4989 dp->interlace_type = INTERLACE_FROM_ID(id);
4990 check_interlace_type(dp->interlace_type);
4991 dp->id = id;
4992 /* All the rest are filled in after the read_info: */
4993 dp->w = 0;
4994 dp->h = 0;
4995 dp->npasses = 0;
4996 dp->pixel_size = 0;
4997 dp->bit_width = 0;
4998 dp->cbRow = 0;
4999 dp->do_interlace = do_interlace;
5000 dp->littleendian = 0;
5001 dp->is_transparent = 0;
5002 dp->speed = ps->speed;
5003 dp->use_update_info = use_update_info;
5004 dp->npalette = 0;
5005 /* Preset the transparent color to black: */
5006 memset(&dp->transparent, 0, sizeof dp->transparent);
5007 /* Preset the palette to full intensity/opaque throughout: */
5008 memset(dp->palette, 0xff, sizeof dp->palette);
5009}
5010
5011/* Initialize the palette fields - this must be done later because the palette
5012 * comes from the particular png_store_file that is selected.
5013 */
5014static void
5015standard_palette_init(standard_display *dp)
5016{
5017 store_palette_entry *palette = store_current_palette(dp->ps, &dp->npalette);
5018
5019 /* The remaining entries remain white/opaque. */
5020 if (dp->npalette > 0)
5021 {
5022 int i = dp->npalette;
5023 memcpy(dp->palette, palette, i * sizeof *palette);
5024
5025 /* Check for a non-opaque palette entry: */
5026 while (--i >= 0)
5027 if (palette[i].alpha < 255)
5028 break;
5029
5030# ifdef __GNUC__
5031 /* GCC can't handle the more obviously optimizable version. */
5032 if (i >= 0)
5033 dp->is_transparent = 1;
5034 else
5035 dp->is_transparent = 0;
5036# else
5037 dp->is_transparent = (i >= 0);
5038# endif
5039 }
5040}
5041
5042/* Utility to read the palette from the PNG file and convert it into
5043 * store_palette format. This returns 1 if there is any transparency in the
5044 * palette (it does not check for a transparent colour in the non-palette case.)
5045 */
5046static int
5047read_palette(store_palette palette, int *npalette, png_const_structp pp,
5048 png_infop pi)
5049{
5050 png_colorp pal;
5051 png_bytep trans_alpha;
5052 int num;
5053
5054 pal = 0;
5055 *npalette = -1;
5056
5057 if (png_get_PLTE(pp, pi, &pal, npalette) & PNG_INFO_PLTE)
5058 {
5059 int i = *npalette;
5060
5061 if (i <= 0 || i > 256)
5062 png_error(pp, "validate: invalid PLTE count");
5063
5064 while (--i >= 0)
5065 {
5066 palette[i].red = pal[i].red;
5067 palette[i].green = pal[i].green;
5068 palette[i].blue = pal[i].blue;
5069 }
5070
5071 /* Mark the remainder of the entries with a flag value (other than
5072 * white/opaque which is the flag value stored above.)
5073 */
5074 memset(palette + *npalette, 126, (256-*npalette) * sizeof *palette);
5075 }
5076
5077 else /* !png_get_PLTE */
5078 {
5079 if (*npalette != (-1))
5080 png_error(pp, "validate: invalid PLTE result");
5081 /* But there is no palette, so record this: */
5082 *npalette = 0;
5083 memset(palette, 113, sizeof (store_palette));
5084 }
5085
5086 trans_alpha = 0;
5087 num = 2; /* force error below */
5088 if ((png_get_tRNS(pp, pi, &trans_alpha, &num, 0) & PNG_INFO_tRNS) != 0 &&
5089 (trans_alpha != NULL || num != 1/*returns 1 for a transparent color*/) &&
5090 /* Oops, if a palette tRNS gets expanded png_read_update_info (at least so
5091 * far as 1.5.4) does not remove the trans_alpha pointer, only num_trans,
5092 * so in the above call we get a success, we get a pointer (who knows what
5093 * to) and we get num_trans == 0:
5094 */
5095 !(trans_alpha != NULL && num == 0)) /* TODO: fix this in libpng. */
5096 {
5097 int i;
5098
5099 /* Any of these are crash-worthy - given the implementation of
5100 * png_get_tRNS up to 1.5 an app won't crash if it just checks the
5101 * result above and fails to check that the variables it passed have
5102 * actually been filled in! Note that if the app were to pass the
5103 * last, png_color_16p, variable too it couldn't rely on this.
5104 */
5105 if (trans_alpha == NULL || num <= 0 || num > 256 || num > *npalette)
5106 png_error(pp, "validate: unexpected png_get_tRNS (palette) result");
5107
5108 for (i=0; i<num; ++i)
5109 palette[i].alpha = trans_alpha[i];
5110
5111 for (num=*npalette; i<num; ++i)
5112 palette[i].alpha = 255;
5113
5114 for (; i<256; ++i)
5115 palette[i].alpha = 33; /* flag value */
5116
5117 return 1; /* transparency */
5118 }
5119
5120 else
5121 {
5122 /* No palette transparency - just set the alpha channel to opaque. */
5123 int i;
5124
5125 for (i=0, num=*npalette; i<num; ++i)
5126 palette[i].alpha = 255;
5127
5128 for (; i<256; ++i)
5129 palette[i].alpha = 55; /* flag value */
5130
5131 return 0; /* no transparency */
5132 }
5133}
5134
5135/* Utility to validate the palette if it should not have changed (the
5136 * non-transform case).
5137 */
5138static void
5139standard_palette_validate(standard_display *dp, png_const_structp pp,
5140 png_infop pi)
5141{
5142 int npalette;
5143 store_palette palette;
5144
5145 if (read_palette(palette, &npalette, pp, pi) != dp->is_transparent)
5146 png_error(pp, "validate: palette transparency changed");
5147
5148 if (npalette != dp->npalette)
5149 {
5150 size_t pos = 0;
5151 char msg[64];
5152
5153 pos = safecat(msg, sizeof msg, pos, "validate: palette size changed: ");
5154 pos = safecatn(msg, sizeof msg, pos, dp->npalette);
5155 pos = safecat(msg, sizeof msg, pos, " -> ");
5156 pos = safecatn(msg, sizeof msg, pos, npalette);
5157 png_error(pp, msg);
5158 }
5159
5160 {
5161 int i = npalette; /* npalette is aliased */
5162
5163 while (--i >= 0)
5164 if (palette[i].red != dp->palette[i].red ||
5165 palette[i].green != dp->palette[i].green ||
5166 palette[i].blue != dp->palette[i].blue ||
5167 palette[i].alpha != dp->palette[i].alpha)
5168 png_error(pp, "validate: PLTE or tRNS chunk changed");
5169 }
5170}
5171
5172/* By passing a 'standard_display' the progressive callbacks can be used
5173 * directly by the sequential code, the functions suffixed "_imp" are the
5174 * implementations, the functions without the suffix are the callbacks.
5175 *
5176 * The code for the info callback is split into two because this callback calls
5177 * png_read_update_info or png_start_read_image and what gets called depends on
5178 * whether the info needs updating (we want to test both calls in pngvalid.)
5179 */
5180static void
5181standard_info_part1(standard_display *dp, png_structp pp, png_infop pi)
5182{
5183 if (png_get_bit_depth(pp, pi) != dp->bit_depth)
5184 png_error(pp, "validate: bit depth changed");
5185
5186 if (png_get_color_type(pp, pi) != dp->colour_type)
5187 png_error(pp, "validate: color type changed");
5188
5189 if (png_get_filter_type(pp, pi) != PNG_FILTER_TYPE_BASE)
5190 png_error(pp, "validate: filter type changed");
5191
5192 if (png_get_interlace_type(pp, pi) != dp->interlace_type)
5193 png_error(pp, "validate: interlacing changed");
5194
5195 if (png_get_compression_type(pp, pi) != PNG_COMPRESSION_TYPE_BASE)
5196 png_error(pp, "validate: compression type changed");
5197
5198 dp->w = png_get_image_width(pp, pi);
5199
5200 if (dp->w != standard_width(pp, dp->id))
5201 png_error(pp, "validate: image width changed");
5202
5203 dp->h = png_get_image_height(pp, pi);
5204
5205 if (dp->h != standard_height(pp, dp->id))
5206 png_error(pp, "validate: image height changed");
5207
5208 /* Record (but don't check at present) the input sBIT according to the colour
5209 * type information.
5210 */
5211 {
5212 png_color_8p sBIT = 0;
5213
5214 if (png_get_sBIT(pp, pi, &sBIT) & PNG_INFO_sBIT)
5215 {
5216 int sBIT_invalid = 0;
5217
5218 if (sBIT == 0)
5219 png_error(pp, "validate: unexpected png_get_sBIT result");
5220
5221 if (dp->colour_type & PNG_COLOR_MASK_COLOR)
5222 {
5223 if (sBIT->red == 0 || sBIT->red > dp->bit_depth)
5224 sBIT_invalid = 1;
5225 else
5226 dp->red_sBIT = sBIT->red;
5227
5228 if (sBIT->green == 0 || sBIT->green > dp->bit_depth)
5229 sBIT_invalid = 1;
5230 else
5231 dp->green_sBIT = sBIT->green;
5232
5233 if (sBIT->blue == 0 || sBIT->blue > dp->bit_depth)
5234 sBIT_invalid = 1;
5235 else
5236 dp->blue_sBIT = sBIT->blue;
5237 }
5238
5239 else /* !COLOR */
5240 {
5241 if (sBIT->gray == 0 || sBIT->gray > dp->bit_depth)
5242 sBIT_invalid = 1;
5243 else
5244 dp->blue_sBIT = dp->green_sBIT = dp->red_sBIT = sBIT->gray;
5245 }
5246
5247 /* All 8 bits in tRNS for a palette image are significant - see the
5248 * spec.
5249 */
5250 if (dp->colour_type & PNG_COLOR_MASK_ALPHA)
5251 {
5252 if (sBIT->alpha == 0 || sBIT->alpha > dp->bit_depth)
5253 sBIT_invalid = 1;
5254 else
5255 dp->alpha_sBIT = sBIT->alpha;
5256 }
5257
5258 if (sBIT_invalid)
5259 png_error(pp, "validate: sBIT value out of range");
5260 }
5261 }
5262
5263 /* Important: this is validating the value *before* any transforms have been
5264 * put in place. It doesn't matter for the standard tests, where there are
5265 * no transforms, but it does for other tests where rowbytes may change after
5266 * png_read_update_info.
5267 */
5268 if (png_get_rowbytes(pp, pi) != standard_rowsize(pp, dp->id))
5269 png_error(pp, "validate: row size changed");
5270
5271 /* Validate the colour type 3 palette (this can be present on other color
5272 * types.)
5273 */
5274 standard_palette_validate(dp, pp, pi);
5275
5276 /* In any case always check for a transparent color (notice that the
5277 * colour type 3 case must not give a successful return on the get_tRNS call
5278 * with these arguments!)
5279 */
5280 {
5281 png_color_16p trans_color = 0;
5282
5283 if (png_get_tRNS(pp, pi, 0, 0, &trans_color) & PNG_INFO_tRNS)
5284 {
5285 if (trans_color == 0)
5286 png_error(pp, "validate: unexpected png_get_tRNS (color) result");
5287
5288 switch (dp->colour_type)
5289 {
5290 case 0:
5291 dp->transparent.red = dp->transparent.green = dp->transparent.blue =
5292 trans_color->gray;
5293 dp->has_tRNS = 1;
5294 break;
5295
5296 case 2:
5297 dp->transparent.red = trans_color->red;
5298 dp->transparent.green = trans_color->green;
5299 dp->transparent.blue = trans_color->blue;
5300 dp->has_tRNS = 1;
5301 break;
5302
5303 case 3:
5304 /* Not expected because it should result in the array case
5305 * above.
5306 */
5307 png_error(pp, "validate: unexpected png_get_tRNS result");
5308 break;
5309
5310 default:
5311 png_error(pp, "validate: invalid tRNS chunk with alpha image");
5312 }
5313 }
5314 }
5315
5316 /* Read the number of passes - expected to match the value used when
5317 * creating the image (interlaced or not). This has the side effect of
5318 * turning on interlace handling (if do_interlace is not set.)
5319 */
5320 dp->npasses = npasses_from_interlace_type(pp, dp->interlace_type);
5321 if (!dp->do_interlace)
5322 {
5323# ifdef PNG_READ_INTERLACING_SUPPORTED
5324 if (dp->npasses != png_set_interlace_handling(pp))
5325 png_error(pp, "validate: file changed interlace type");
5326# else /* !READ_INTERLACING */
5327 /* This should never happen: the relevant tests (!do_interlace) should
5328 * not be run.
5329 */
5330 if (dp->npasses > 1)
5331 png_error(pp, "validate: no libpng interlace support");
5332# endif /* !READ_INTERLACING */
5333 }
5334
5335 /* Caller calls png_read_update_info or png_start_read_image now, then calls
5336 * part2.
5337 */
5338}
5339
5340/* This must be called *after* the png_read_update_info call to get the correct
5341 * 'rowbytes' value, otherwise png_get_rowbytes will refer to the untransformed
5342 * image.
5343 */
5344static void
5345standard_info_part2(standard_display *dp, png_const_structp pp,
5346 png_const_infop pi, int nImages)
5347{
5348 /* Record cbRow now that it can be found. */
5349 {
5350 png_byte ct = png_get_color_type(pp, pi);
5351 png_byte bd = png_get_bit_depth(pp, pi);
5352
5353 if (bd >= 8 && (ct == PNG_COLOR_TYPE_RGB || ct == PNG_COLOR_TYPE_GRAY) &&
5354 dp->filler)
5355 ct |= 4; /* handle filler as faked alpha channel */
5356
5357 dp->pixel_size = bit_size(pp, ct, bd);
5358 }
5359 dp->bit_width = png_get_image_width(pp, pi) * dp->pixel_size;
5360 dp->cbRow = png_get_rowbytes(pp, pi);
5361
5362 /* Validate the rowbytes here again. */
5363 if (dp->cbRow != (dp->bit_width+7)/8)
5364 png_error(pp, "bad png_get_rowbytes calculation");
5365
5366 /* Then ensure there is enough space for the output image(s). */
5367 store_ensure_image(dp->ps, pp, nImages, dp->cbRow, dp->h);
5368}
5369
5370static void
5371standard_info_imp(standard_display *dp, png_structp pp, png_infop pi,
5372 int nImages)
5373{
5374 /* Note that the validation routine has the side effect of turning on
5375 * interlace handling in the subsequent code.
5376 */
5377 standard_info_part1(dp, pp, pi);
5378
5379 /* And the info callback has to call this (or png_read_update_info - see
5380 * below in the png_modifier code for that variant.
5381 */
5382 if (dp->use_update_info)
5383 {
5384 /* For debugging the effect of multiple calls: */
5385 int i = dp->use_update_info;
5386 while (i-- > 0)
5387 png_read_update_info(pp, pi);
5388 }
5389
5390 else
5391 png_start_read_image(pp);
5392
5393 /* Validate the height, width and rowbytes plus ensure that sufficient buffer
5394 * exists for decoding the image.
5395 */
5396 standard_info_part2(dp, pp, pi, nImages);
5397}
5398
5399static void PNGCBAPI
5400standard_info(png_structp pp, png_infop pi)
5401{
5402 standard_display *dp = voidcast(standard_display*,
5403 png_get_progressive_ptr(pp));
5404
5405 /* Call with nImages==1 because the progressive reader can only produce one
5406 * image.
5407 */
5408 standard_info_imp(dp, pp, pi, 1 /*only one image*/);
5409}
5410
5411static void PNGCBAPI
5412progressive_row(png_structp ppIn, png_bytep new_row, png_uint_32 y, int pass)
5413{
5414 png_const_structp pp = ppIn;
5415 const standard_display *dp = voidcast(standard_display*,
5416 png_get_progressive_ptr(pp));
5417
5418 /* When handling interlacing some rows will be absent in each pass, the
5419 * callback still gets called, but with a NULL pointer. This is checked
5420 * in the 'else' clause below. We need our own 'cbRow', but we can't call
5421 * png_get_rowbytes because we got no info structure.
5422 */
5423 if (new_row != NULL)
5424 {
5425 png_bytep row;
5426
5427 /* In the case where the reader doesn't do the interlace it gives
5428 * us the y in the sub-image:
5429 */
5430 if (dp->do_interlace && dp->interlace_type == PNG_INTERLACE_ADAM7)
5431 {
5432#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED
5433 /* Use this opportunity to validate the png 'current' APIs: */
5434 if (y != png_get_current_row_number(pp))
5435 png_error(pp, "png_get_current_row_number is broken");
5436
5437 if (pass != png_get_current_pass_number(pp))
5438 png_error(pp, "png_get_current_pass_number is broken");
5439#endif /* USER_TRANSFORM_INFO */
5440
5441 y = PNG_ROW_FROM_PASS_ROW(y, pass);
5442 }
5443
5444 /* Validate this just in case. */
5445 if (y >= dp->h)
5446 png_error(pp, "invalid y to progressive row callback");
5447
5448 row = store_image_row(dp->ps, pp, 0, y);
5449
5450 /* Combine the new row into the old: */
5451#ifdef PNG_READ_INTERLACING_SUPPORTED
5452 if (dp->do_interlace)
5453#endif /* READ_INTERLACING */
5454 {
5455 if (dp->interlace_type == PNG_INTERLACE_ADAM7)
5456 deinterlace_row(row, new_row, dp->pixel_size, dp->w, pass,
5457 dp->littleendian);
5458 else
5459 row_copy(row, new_row, dp->pixel_size * dp->w, dp->littleendian);
5460 }
5461#ifdef PNG_READ_INTERLACING_SUPPORTED
5462 else
5463 png_progressive_combine_row(pp, row, new_row);
5464#endif /* PNG_READ_INTERLACING_SUPPORTED */
5465 }
5466
5467 else if (dp->interlace_type == PNG_INTERLACE_ADAM7 &&
5468 PNG_ROW_IN_INTERLACE_PASS(y, pass) &&
5469 PNG_PASS_COLS(dp->w, pass) > 0)
5470 png_error(pp, "missing row in progressive de-interlacing");
5471}
5472
5473static void
5474sequential_row(standard_display *dp, png_structp pp, png_infop pi,
5475 int iImage, int iDisplay)
5476{
5477 int npasses = dp->npasses;
5478 int do_interlace = dp->do_interlace &&
5479 dp->interlace_type == PNG_INTERLACE_ADAM7;
5480 png_uint_32 height = standard_height(pp, dp->id);
5481 png_uint_32 width = standard_width(pp, dp->id);
5482 const png_store* ps = dp->ps;
5483 int pass;
5484
5485 for (pass=0; pass<npasses; ++pass)
5486 {
5487 png_uint_32 y;
5488 png_uint_32 wPass = PNG_PASS_COLS(width, pass);
5489
5490 for (y=0; y<height; ++y)
5491 {
5492 if (do_interlace)
5493 {
5494 /* wPass may be zero or this row may not be in this pass.
5495 * png_read_row must not be called in either case.
5496 */
5497 if (wPass > 0 && PNG_ROW_IN_INTERLACE_PASS(y, pass))
5498 {
5499 /* Read the row into a pair of temporary buffers, then do the
5500 * merge here into the output rows.
5501 */
5502 png_byte row[STANDARD_ROWMAX], display[STANDARD_ROWMAX];
5503
5504 /* The following aids (to some extent) error detection - we can
5505 * see where png_read_row wrote. Use opposite values in row and
5506 * display to make this easier. Don't use 0xff (which is used in
5507 * the image write code to fill unused bits) or 0 (which is a
5508 * likely value to overwrite unused bits with).
5509 */
5510 memset(row, 0xc5, sizeof row);
5511 memset(display, 0x5c, sizeof display);
5512
5513 png_read_row(pp, row, display);
5514
5515 if (iImage >= 0)
5516 deinterlace_row(store_image_row(ps, pp, iImage, y), row,
5517 dp->pixel_size, dp->w, pass, dp->littleendian);
5518
5519 if (iDisplay >= 0)
5520 deinterlace_row(store_image_row(ps, pp, iDisplay, y), display,
5521 dp->pixel_size, dp->w, pass, dp->littleendian);
5522 }
5523 }
5524 else
5525 png_read_row(pp,
5526 iImage >= 0 ? store_image_row(ps, pp, iImage, y) : NULL,
5527 iDisplay >= 0 ? store_image_row(ps, pp, iDisplay, y) : NULL);
5528 }
5529 }
5530
5531 /* And finish the read operation (only really necessary if the caller wants
5532 * to find additional data in png_info from chunks after the last IDAT.)
5533 */
5534 png_read_end(pp, pi);
5535}
5536
5537#ifdef PNG_TEXT_SUPPORTED
5538static void
5539standard_check_text(png_const_structp pp, png_const_textp tp,
5540 png_const_charp keyword, png_const_charp text)
5541{
5542 char msg[1024];
5543 size_t pos = safecat(msg, sizeof msg, 0, "text: ");
5544 size_t ok;
5545
5546 pos = safecat(msg, sizeof msg, pos, keyword);
5547 pos = safecat(msg, sizeof msg, pos, ": ");
5548 ok = pos;
5549
5550 if (tp->compression != TEXT_COMPRESSION)
5551 {
5552 char buf[64];
5553
5554 sprintf(buf, "compression [%d->%d], ", TEXT_COMPRESSION,
5555 tp->compression);
5556 pos = safecat(msg, sizeof msg, pos, buf);
5557 }
5558
5559 if (tp->key == NULL || strcmp(tp->key, keyword) != 0)
5560 {
5561 pos = safecat(msg, sizeof msg, pos, "keyword \"");
5562 if (tp->key != NULL)
5563 {
5564 pos = safecat(msg, sizeof msg, pos, tp->key);
5565 pos = safecat(msg, sizeof msg, pos, "\", ");
5566 }
5567
5568 else
5569 pos = safecat(msg, sizeof msg, pos, "null, ");
5570 }
5571
5572 if (tp->text == NULL)
5573 pos = safecat(msg, sizeof msg, pos, "text lost, ");
5574
5575 else
5576 {
5577 if (tp->text_length != strlen(text))
5578 {
5579 char buf[64];
5580 sprintf(buf, "text length changed[%lu->%lu], ",
5581 (unsigned long)strlen(text), (unsigned long)tp->text_length);
5582 pos = safecat(msg, sizeof msg, pos, buf);
5583 }
5584
5585 if (strcmp(tp->text, text) != 0)
5586 {
5587 pos = safecat(msg, sizeof msg, pos, "text becomes \"");
5588 pos = safecat(msg, sizeof msg, pos, tp->text);
5589 pos = safecat(msg, sizeof msg, pos, "\" (was \"");
5590 pos = safecat(msg, sizeof msg, pos, text);
5591 pos = safecat(msg, sizeof msg, pos, "\"), ");
5592 }
5593 }
5594
5595 if (tp->itxt_length != 0)
5596 pos = safecat(msg, sizeof msg, pos, "iTXt length set, ");
5597
5598 if (tp->lang != NULL)
5599 {
5600 pos = safecat(msg, sizeof msg, pos, "iTXt language \"");
5601 pos = safecat(msg, sizeof msg, pos, tp->lang);
5602 pos = safecat(msg, sizeof msg, pos, "\", ");
5603 }
5604
5605 if (tp->lang_key != NULL)
5606 {
5607 pos = safecat(msg, sizeof msg, pos, "iTXt keyword \"");
5608 pos = safecat(msg, sizeof msg, pos, tp->lang_key);
5609 pos = safecat(msg, sizeof msg, pos, "\", ");
5610 }
5611
5612 if (pos > ok)
5613 {
5614 msg[pos-2] = '\0'; /* Remove the ", " at the end */
5615 png_error(pp, msg);
5616 }
5617}
5618
5619static void
5620standard_text_validate(standard_display *dp, png_const_structp pp,
5621 png_infop pi, int check_end)
5622{
5623 png_textp tp = NULL;
5624 png_uint_32 num_text = png_get_text(pp, pi, &tp, NULL);
5625
5626 if (num_text == 2 && tp != NULL)
5627 {
5628 standard_check_text(pp, tp, "image name", dp->ps->current->name);
5629
5630 /* This exists because prior to 1.5.18 the progressive reader left the
5631 * png_struct z_stream unreset at the end of the image, so subsequent
5632 * attempts to use it simply returns Z_STREAM_END.
5633 */
5634 if (check_end)
5635 standard_check_text(pp, tp+1, "end marker", "end");
5636 }
5637
5638 else
5639 {
5640 char msg[64];
5641
5642 sprintf(msg, "expected two text items, got %lu",
5643 (unsigned long)num_text);
5644 png_error(pp, msg);
5645 }
5646}
5647#else
5648# define standard_text_validate(dp,pp,pi,check_end) ((void)0)
5649#endif
5650
5651static void
5652standard_row_validate(standard_display *dp, png_const_structp pp,
5653 int iImage, int iDisplay, png_uint_32 y)
5654{
5655 int where;
5656 png_byte std[STANDARD_ROWMAX];
5657
5658 /* The row must be pre-initialized to the magic number here for the size
5659 * tests to pass:
5660 */
5661 memset(std, 178, sizeof std);
5662 standard_row(pp, std, dp->id, y);
5663
5664 /* At the end both the 'row' and 'display' arrays should end up identical.
5665 * In earlier passes 'row' will be partially filled in, with only the pixels
5666 * that have been read so far, but 'display' will have those pixels
5667 * replicated to fill the unread pixels while reading an interlaced image.
5668 */
5669 if (iImage >= 0 &&
5670 (where = pixel_cmp(std, store_image_row(dp->ps, pp, iImage, y),
5671 dp->bit_width)) != 0)
5672 {
5673 char msg[64];
5674 sprintf(msg, "PNG image row[%lu][%d] changed from %.2x to %.2x",
5675 (unsigned long)y, where-1, std[where-1],
5676 store_image_row(dp->ps, pp, iImage, y)[where-1]);
5677 png_error(pp, msg);
5678 }
5679
5680 if (iDisplay >= 0 &&
5681 (where = pixel_cmp(std, store_image_row(dp->ps, pp, iDisplay, y),
5682 dp->bit_width)) != 0)
5683 {
5684 char msg[64];
5685 sprintf(msg, "display row[%lu][%d] changed from %.2x to %.2x",
5686 (unsigned long)y, where-1, std[where-1],
5687 store_image_row(dp->ps, pp, iDisplay, y)[where-1]);
5688 png_error(pp, msg);
5689 }
5690}
5691
5692static void
5693standard_image_validate(standard_display *dp, png_const_structp pp, int iImage,
5694 int iDisplay)
5695{
5696 png_uint_32 y;
5697
5698 if (iImage >= 0)
5699 store_image_check(dp->ps, pp, iImage);
5700
5701 if (iDisplay >= 0)
5702 store_image_check(dp->ps, pp, iDisplay);
5703
5704 for (y=0; y<dp->h; ++y)
5705 standard_row_validate(dp, pp, iImage, iDisplay, y);
5706
5707 /* This avoids false positives if the validation code is never called! */
5708 dp->ps->validated = 1;
5709}
5710
5711static void PNGCBAPI
5712standard_end(png_structp ppIn, png_infop pi)
5713{
5714 png_const_structp pp = ppIn;
5715 standard_display *dp = voidcast(standard_display*,
5716 png_get_progressive_ptr(pp));
5717
5718 UNUSED(pi)
5719
5720 /* Validate the image - progressive reading only produces one variant for
5721 * interlaced images.
5722 */
5723 standard_text_validate(dp, pp, pi,
5724 PNG_LIBPNG_VER >= 10518/*check_end: see comments above*/);
5725 standard_image_validate(dp, pp, 0, -1);
5726}
5727
5728/* A single test run checking the standard image to ensure it is not damaged. */
5729static void
5730standard_test(png_store* const psIn, png_uint_32 const id,
5731 int do_interlace, int use_update_info)
5732{
5733 standard_display d;
5734 context(psIn, fault);
5735
5736 /* Set up the display (stack frame) variables from the arguments to the
5737 * function and initialize the locals that are filled in later.
5738 */
5739 standard_display_init(&d, psIn, id, do_interlace, use_update_info);
5740
5741 /* Everything is protected by a Try/Catch. The functions called also
5742 * typically have local Try/Catch blocks.
5743 */
5744 Try
5745 {
5746 png_structp pp;
5747 png_infop pi;
5748
5749 /* Get a png_struct for reading the image. This will throw an error if it
5750 * fails, so we don't need to check the result.
5751 */
5752 pp = set_store_for_read(d.ps, &pi, d.id,
5753 d.do_interlace ? (d.ps->progressive ?
5754 "pngvalid progressive deinterlacer" :
5755 "pngvalid sequential deinterlacer") : (d.ps->progressive ?
5756 "progressive reader" : "sequential reader"));
5757
5758 /* Initialize the palette correctly from the png_store_file. */
5759 standard_palette_init(&d);
5760
5761 /* Introduce the correct read function. */
5762 if (d.ps->progressive)
5763 {
5764 png_set_progressive_read_fn(pp, &d, standard_info, progressive_row,
5765 standard_end);
5766
5767 /* Now feed data into the reader until we reach the end: */
5768 store_progressive_read(d.ps, pp, pi);
5769 }
5770 else
5771 {
5772 /* Note that this takes the store, not the display. */
5773 png_set_read_fn(pp, d.ps, store_read);
5774
5775 /* Check the header values: */
5776 png_read_info(pp, pi);
5777
5778 /* The code tests both versions of the images that the sequential
5779 * reader can produce.
5780 */
5781 standard_info_imp(&d, pp, pi, 2 /*images*/);
5782
5783 /* Need the total bytes in the image below; we can't get to this point
5784 * unless the PNG file values have been checked against the expected
5785 * values.
5786 */
5787 {
5788 sequential_row(&d, pp, pi, 0, 1);
5789
5790 /* After the last pass loop over the rows again to check that the
5791 * image is correct.
5792 */
5793 if (!d.speed)
5794 {
5795 standard_text_validate(&d, pp, pi, 1/*check_end*/);
5796 standard_image_validate(&d, pp, 0, 1);
5797 }
5798 else
5799 d.ps->validated = 1;
5800 }
5801 }
5802
5803 /* Check for validation. */
5804 if (!d.ps->validated)
5805 png_error(pp, "image read failed silently");
5806
5807 /* Successful completion. */
5808 }
5809
5810 Catch(fault)
5811 d.ps = fault; /* make sure this hasn't been clobbered. */
5812
5813 /* In either case clean up the store. */
5814 store_read_reset(d.ps);
5815}
5816
5817static int
5818test_standard(png_modifier* const pm, png_byte const colour_type,
5819 int bdlo, int const bdhi)
5820{
5821 for (; bdlo <= bdhi; ++bdlo)
5822 {
5823 int interlace_type;
5824
5825 for (interlace_type = PNG_INTERLACE_NONE;
5826 interlace_type < INTERLACE_LAST; ++interlace_type)
5827 {
5828 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo),
5829 0/*palette*/, interlace_type, 0, 0, 0), do_read_interlace,
5830 pm->use_update_info);
5831
5832 if (fail(pm))
5833 return 0;
5834 }
5835 }
5836
5837 return 1; /* keep going */
5838}
5839
5840static void
5841perform_standard_test(png_modifier *pm)
5842{
5843 /* Test each colour type over the valid range of bit depths (expressed as
5844 * log2(bit_depth) in turn, stop as soon as any error is detected.
5845 */
5846 if (!test_standard(pm, 0, 0, READ_BDHI))
5847 return;
5848
5849 if (!test_standard(pm, 2, 3, READ_BDHI))
5850 return;
5851
5852 if (!test_standard(pm, 3, 0, 3))
5853 return;
5854
5855 if (!test_standard(pm, 4, 3, READ_BDHI))
5856 return;
5857
5858 if (!test_standard(pm, 6, 3, READ_BDHI))
5859 return;
5860}
5861
5862
5863/********************************** SIZE TESTS ********************************/
5864static int
5865test_size(png_modifier* const pm, png_byte const colour_type,
5866 int bdlo, int const bdhi)
5867{
5868 /* Run the tests on each combination.
5869 *
5870 * NOTE: on my 32 bit x86 each of the following blocks takes
5871 * a total of 3.5 seconds if done across every combo of bit depth
5872 * width and height. This is a waste of time in practice, hence the
5873 * hinc and winc stuff:
5874 */
5875 static const png_byte hinc[] = {1, 3, 11, 1, 5};
5876 static const png_byte winc[] = {1, 9, 5, 7, 1};
5877 int save_bdlo = bdlo;
5878
5879 for (; bdlo <= bdhi; ++bdlo)
5880 {
5881 png_uint_32 h, w;
5882
5883 for (h=1; h<=16; h+=hinc[bdlo])
5884 {
5885 for (w=1; w<=16; w+=winc[bdlo])
5886 {
5887 /* First test all the 'size' images against the sequential
5888 * reader using libpng to deinterlace (where required.) This
5889 * validates the write side of libpng. There are four possibilities
5890 * to validate.
5891 */
5892 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo),
5893 0/*palette*/, PNG_INTERLACE_NONE, w, h, 0), 0/*do_interlace*/,
5894 pm->use_update_info);
5895
5896 if (fail(pm))
5897 return 0;
5898
5899 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo),
5900 0/*palette*/, PNG_INTERLACE_NONE, w, h, 1), 0/*do_interlace*/,
5901 pm->use_update_info);
5902
5903 if (fail(pm))
5904 return 0;
5905
5906 /* Now validate the interlaced read side - do_interlace true,
5907 * in the progressive case this does actually make a difference
5908 * to the code used in the non-interlaced case too.
5909 */
5910 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo),
5911 0/*palette*/, PNG_INTERLACE_NONE, w, h, 0), 1/*do_interlace*/,
5912 pm->use_update_info);
5913
5914 if (fail(pm))
5915 return 0;
5916
5917# if CAN_WRITE_INTERLACE
5918 /* Validate the pngvalid code itself: */
5919 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo),
5920 0/*palette*/, PNG_INTERLACE_ADAM7, w, h, 1), 1/*do_interlace*/,
5921 pm->use_update_info);
5922
5923 if (fail(pm))
5924 return 0;
5925# endif
5926 }
5927 }
5928 }
5929
5930 /* Now do the tests of libpng interlace handling, after we have made sure
5931 * that the pngvalid version works:
5932 */
5933 for (bdlo = save_bdlo; bdlo <= bdhi; ++bdlo)
5934 {
5935 png_uint_32 h, w;
5936
5937 for (h=1; h<=16; h+=hinc[bdlo])
5938 {
5939 for (w=1; w<=16; w+=winc[bdlo])
5940 {
5941# ifdef PNG_READ_INTERLACING_SUPPORTED
5942 /* Test with pngvalid generated interlaced images first; we have
5943 * already verify these are ok (unless pngvalid has self-consistent
5944 * read/write errors, which is unlikely), so this detects errors in
5945 * the read side first:
5946 */
5947# if CAN_WRITE_INTERLACE
5948 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo),
5949 0/*palette*/, PNG_INTERLACE_ADAM7, w, h, 1), 0/*do_interlace*/,
5950 pm->use_update_info);
5951
5952 if (fail(pm))
5953 return 0;
5954# endif
5955# endif /* READ_INTERLACING */
5956
5957# ifdef PNG_WRITE_INTERLACING_SUPPORTED
5958 /* Test the libpng write side against the pngvalid read side: */
5959 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo),
5960 0/*palette*/, PNG_INTERLACE_ADAM7, w, h, 0), 1/*do_interlace*/,
5961 pm->use_update_info);
5962
5963 if (fail(pm))
5964 return 0;
5965# endif
5966
5967# ifdef PNG_READ_INTERLACING_SUPPORTED
5968# ifdef PNG_WRITE_INTERLACING_SUPPORTED
5969 /* Test both together: */
5970 standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo),
5971 0/*palette*/, PNG_INTERLACE_ADAM7, w, h, 0), 0/*do_interlace*/,
5972 pm->use_update_info);
5973
5974 if (fail(pm))
5975 return 0;
5976# endif
5977# endif /* READ_INTERLACING */
5978 }
5979 }
5980 }
5981
5982 return 1; /* keep going */
5983}
5984
5985static void
5986perform_size_test(png_modifier *pm)
5987{
5988 /* Test each colour type over the valid range of bit depths (expressed as
5989 * log2(bit_depth) in turn, stop as soon as any error is detected.
5990 */
5991 if (!test_size(pm, 0, 0, READ_BDHI))
5992 return;
5993
5994 if (!test_size(pm, 2, 3, READ_BDHI))
5995 return;
5996
5997 /* For the moment don't do the palette test - it's a waste of time when
5998 * compared to the grayscale test.
5999 */
6000#if 0
6001 if (!test_size(pm, 3, 0, 3))
6002 return;
6003#endif
6004
6005 if (!test_size(pm, 4, 3, READ_BDHI))
6006 return;
6007
6008 if (!test_size(pm, 6, 3, READ_BDHI))
6009 return;
6010}
6011
6012
6013/******************************* TRANSFORM TESTS ******************************/
6014#ifdef PNG_READ_TRANSFORMS_SUPPORTED
6015/* A set of tests to validate libpng image transforms. The possibilities here
6016 * are legion because the transforms can be combined in a combinatorial
6017 * fashion. To deal with this some measure of restraint is required, otherwise
6018 * the tests would take forever.
6019 */
6020typedef struct image_pixel
6021{
6022 /* A local (pngvalid) representation of a PNG pixel, in all its
6023 * various forms.
6024 */
6025 unsigned int red, green, blue, alpha; /* For non-palette images. */
6026 unsigned int palette_index; /* For a palette image. */
6027 png_byte colour_type; /* As in the spec. */
6028 png_byte bit_depth; /* Defines bit size in row */
6029 png_byte sample_depth; /* Scale of samples */
6030 unsigned int have_tRNS :1; /* tRNS chunk may need processing */
6031 unsigned int swap_rgb :1; /* RGB swapped to BGR */
6032 unsigned int alpha_first :1; /* Alpha at start, not end */
6033 unsigned int alpha_inverted :1; /* Alpha channel inverted */
6034 unsigned int mono_inverted :1; /* Gray channel inverted */
6035 unsigned int swap16 :1; /* Byte swap 16-bit components */
6036 unsigned int littleendian :1; /* High bits on right */
6037 unsigned int sig_bits :1; /* Pixel shifted (sig bits only) */
6038
6039 /* For checking the code calculates double precision floating point values
6040 * along with an error value, accumulated from the transforms. Because an
6041 * sBIT setting allows larger error bounds (indeed, by the spec, apparently
6042 * up to just less than +/-1 in the scaled value) the *lowest* sBIT for each
6043 * channel is stored. This sBIT value is folded in to the stored error value
6044 * at the end of the application of the transforms to the pixel.
6045 *
6046 * If sig_bits is set above the red, green, blue and alpha values have been
6047 * scaled so they only contain the significant bits of the component values.
6048 */
6049 double redf, greenf, bluef, alphaf;
6050 double rede, greene, bluee, alphae;
6051 png_byte red_sBIT, green_sBIT, blue_sBIT, alpha_sBIT;
6052} image_pixel;
6053
6054/* Shared utility function, see below. */
6055static void
6056image_pixel_setf(image_pixel *this, unsigned int rMax, unsigned int gMax,
6057 unsigned int bMax, unsigned int aMax)
6058{
6059 this->redf = this->red / (double)rMax;
6060 this->greenf = this->green / (double)gMax;
6061 this->bluef = this->blue / (double)bMax;
6062 this->alphaf = this->alpha / (double)aMax;
6063
6064 if (this->red < rMax)
6065 this->rede = this->redf * DBL_EPSILON;
6066 else
6067 this->rede = 0;
6068 if (this->green < gMax)
6069 this->greene = this->greenf * DBL_EPSILON;
6070 else
6071 this->greene = 0;
6072 if (this->blue < bMax)
6073 this->bluee = this->bluef * DBL_EPSILON;
6074 else
6075 this->bluee = 0;
6076 if (this->alpha < aMax)
6077 this->alphae = this->alphaf * DBL_EPSILON;
6078 else
6079 this->alphae = 0;
6080}
6081
6082/* Initialize the structure for the next pixel - call this before doing any
6083 * transforms and call it for each pixel since all the fields may need to be
6084 * reset.
6085 */
6086static void
6087image_pixel_init(image_pixel *this, png_const_bytep row, png_byte colour_type,
6088 png_byte bit_depth, png_uint_32 x, store_palette palette,
6089 const image_pixel *format /*from pngvalid transform of input*/)
6090{
6091 png_byte sample_depth =
6092 (png_byte)(colour_type == PNG_COLOR_TYPE_PALETTE ? 8 : bit_depth);
6093 unsigned int max = (1U<<sample_depth)-1;
6094 int swap16 = (format != 0 && format->swap16);
6095 int littleendian = (format != 0 && format->littleendian);
6096 int sig_bits = (format != 0 && format->sig_bits);
6097
6098 /* Initially just set everything to the same number and the alpha to opaque.
6099 * Note that this currently assumes a simple palette where entry x has colour
6100 * rgb(x,x,x)!
6101 */
6102 this->palette_index = this->red = this->green = this->blue =
6103 sample(row, colour_type, bit_depth, x, 0, swap16, littleendian);
6104 this->alpha = max;
6105 this->red_sBIT = this->green_sBIT = this->blue_sBIT = this->alpha_sBIT =
6106 sample_depth;
6107
6108 /* Then override as appropriate: */
6109 if (colour_type == 3) /* palette */
6110 {
6111 /* This permits the caller to default to the sample value. */
6112 if (palette != 0)
6113 {
6114 unsigned int i = this->palette_index;
6115
6116 this->red = palette[i].red;
6117 this->green = palette[i].green;
6118 this->blue = palette[i].blue;
6119 this->alpha = palette[i].alpha;
6120 }
6121 }
6122
6123 else /* not palette */
6124 {
6125 unsigned int i = 0;
6126
6127 if ((colour_type & 4) != 0 && format != 0 && format->alpha_first)
6128 {
6129 this->alpha = this->red;
6130 /* This handles the gray case for 'AG' pixels */
6131 this->palette_index = this->red = this->green = this->blue =
6132 sample(row, colour_type, bit_depth, x, 1, swap16, littleendian);
6133 i = 1;
6134 }
6135
6136 if (colour_type & 2)
6137 {
6138 /* Green is second for both BGR and RGB: */
6139 this->green = sample(row, colour_type, bit_depth, x, ++i, swap16,
6140 littleendian);
6141
6142 if (format != 0 && format->swap_rgb) /* BGR */
6143 this->red = sample(row, colour_type, bit_depth, x, ++i, swap16,
6144 littleendian);
6145 else
6146 this->blue = sample(row, colour_type, bit_depth, x, ++i, swap16,
6147 littleendian);
6148 }
6149
6150 else /* grayscale */ if (format != 0 && format->mono_inverted)
6151 this->red = this->green = this->blue = this->red ^ max;
6152
6153 if ((colour_type & 4) != 0) /* alpha */
6154 {
6155 if (format == 0 || !format->alpha_first)
6156 this->alpha = sample(row, colour_type, bit_depth, x, ++i, swap16,
6157 littleendian);
6158
6159 if (format != 0 && format->alpha_inverted)
6160 this->alpha ^= max;
6161 }
6162 }
6163
6164 /* Calculate the scaled values, these are simply the values divided by
6165 * 'max' and the error is initialized to the double precision epsilon value
6166 * from the header file.
6167 */
6168 image_pixel_setf(this,
6169 sig_bits ? (1U << format->red_sBIT)-1 : max,
6170 sig_bits ? (1U << format->green_sBIT)-1 : max,
6171 sig_bits ? (1U << format->blue_sBIT)-1 : max,
6172 sig_bits ? (1U << format->alpha_sBIT)-1 : max);
6173
6174 /* Store the input information for use in the transforms - these will
6175 * modify the information.
6176 */
6177 this->colour_type = colour_type;
6178 this->bit_depth = bit_depth;
6179 this->sample_depth = sample_depth;
6180 this->have_tRNS = 0;
6181 this->swap_rgb = 0;
6182 this->alpha_first = 0;
6183 this->alpha_inverted = 0;
6184 this->mono_inverted = 0;
6185 this->swap16 = 0;
6186 this->littleendian = 0;
6187 this->sig_bits = 0;
6188}
6189
6190#if defined PNG_READ_EXPAND_SUPPORTED || defined PNG_READ_GRAY_TO_RGB_SUPPORTED\
6191 || defined PNG_READ_EXPAND_SUPPORTED || defined PNG_READ_EXPAND_16_SUPPORTED\
6192 || defined PNG_READ_BACKGROUND_SUPPORTED
6193/* Convert a palette image to an rgb image. This necessarily converts the tRNS
6194 * chunk at the same time, because the tRNS will be in palette form. The way
6195 * palette validation works means that the original palette is never updated,
6196 * instead the image_pixel value from the row contains the RGB of the
6197 * corresponding palette entry and *this* is updated. Consequently this routine
6198 * only needs to change the colour type information.
6199 */
6200static void
6201image_pixel_convert_PLTE(image_pixel *this)
6202{
6203 if (this->colour_type == PNG_COLOR_TYPE_PALETTE)
6204 {
6205 if (this->have_tRNS)
6206 {
6207 this->colour_type = PNG_COLOR_TYPE_RGB_ALPHA;
6208 this->have_tRNS = 0;
6209 }
6210 else
6211 this->colour_type = PNG_COLOR_TYPE_RGB;
6212
6213 /* The bit depth of the row changes at this point too (notice that this is
6214 * the row format, not the sample depth, which is separate.)
6215 */
6216 this->bit_depth = 8;
6217 }
6218}
6219
6220/* Add an alpha channel; this will import the tRNS information because tRNS is
6221 * not valid in an alpha image. The bit depth will invariably be set to at
6222 * least 8 prior to 1.7.0. Palette images will be converted to alpha (using
6223 * the above API). With png_set_background the alpha channel is never expanded
6224 * but this routine is used by pngvalid to simplify code; 'for_background'
6225 * records this.
6226 */
6227static void
6228image_pixel_add_alpha(image_pixel *this, const standard_display *display,
6229 int for_background)
6230{
6231 if (this->colour_type == PNG_COLOR_TYPE_PALETTE)
6232 image_pixel_convert_PLTE(this);
6233
6234 if ((this->colour_type & PNG_COLOR_MASK_ALPHA) == 0)
6235 {
6236 if (this->colour_type == PNG_COLOR_TYPE_GRAY)
6237 {
6238# if PNG_LIBPNG_VER != 10700
6239 if (!for_background && this->bit_depth < 8)
6240 this->bit_depth = this->sample_depth = 8;
6241# endif
6242
6243 if (this->have_tRNS)
6244 {
6245 /* After 1.7 the expansion of bit depth only happens if there is a
6246 * tRNS chunk to expand at this point.
6247 */
6248# if PNG_LIBPNG_VER == 10700
6249 if (!for_background && this->bit_depth < 8)
6250 this->bit_depth = this->sample_depth = 8;
6251# endif
6252
6253 this->have_tRNS = 0;
6254
6255 /* Check the input, original, channel value here against the
6256 * original tRNS gray chunk valie.
6257 */
6258 if (this->red == display->transparent.red)
6259 this->alphaf = 0;
6260 else
6261 this->alphaf = 1;
6262 }
6263 else
6264 this->alphaf = 1;
6265
6266 this->colour_type = PNG_COLOR_TYPE_GRAY_ALPHA;
6267 }
6268
6269 else if (this->colour_type == PNG_COLOR_TYPE_RGB)
6270 {
6271 if (this->have_tRNS)
6272 {
6273 this->have_tRNS = 0;
6274
6275 /* Again, check the exact input values, not the current transformed
6276 * value!
6277 */
6278 if (this->red == display->transparent.red &&
6279 this->green == display->transparent.green &&
6280 this->blue == display->transparent.blue)
6281 this->alphaf = 0;
6282 else
6283 this->alphaf = 1;
6284 }
6285 else
6286 this->alphaf = 1;
6287
6288 this->colour_type = PNG_COLOR_TYPE_RGB_ALPHA;
6289 }
6290
6291 /* The error in the alpha is zero and the sBIT value comes from the
6292 * original sBIT data (actually it will always be the original bit depth).
6293 */
6294 this->alphae = 0;
6295 this->alpha_sBIT = display->alpha_sBIT;
6296 }
6297}
6298#endif /* transforms that need image_pixel_add_alpha */
6299
6300struct transform_display;
6301typedef struct image_transform
6302{
6303 /* The name of this transform: a string. */
6304 const char *name;
6305
6306 /* Each transform can be disabled from the command line: */
6307 int enable;
6308
6309 /* The global list of transforms; read only. */
6310 struct image_transform *const list;
6311
6312 /* The global count of the number of times this transform has been set on an
6313 * image.
6314 */
6315 unsigned int global_use;
6316
6317 /* The local count of the number of times this transform has been set. */
6318 unsigned int local_use;
6319
6320 /* The next transform in the list, each transform must call its own next
6321 * transform after it has processed the pixel successfully.
6322 */
6323 const struct image_transform *next;
6324
6325 /* A single transform for the image, expressed as a series of function
6326 * callbacks and some space for values.
6327 *
6328 * First a callback to add any required modifications to the png_modifier;
6329 * this gets called just before the modifier is set up for read.
6330 */
6331 void (*ini)(const struct image_transform *this,
6332 struct transform_display *that);
6333
6334 /* And a callback to set the transform on the current png_read_struct:
6335 */
6336 void (*set)(const struct image_transform *this,
6337 struct transform_display *that, png_structp pp, png_infop pi);
6338
6339 /* Then a transform that takes an input pixel in one PNG format or another
6340 * and modifies it by a pngvalid implementation of the transform (thus
6341 * duplicating the libpng intent without, we hope, duplicating the bugs
6342 * in the libpng implementation!) The png_structp is solely to allow error
6343 * reporting via png_error and png_warning.
6344 */
6345 void (*mod)(const struct image_transform *this, image_pixel *that,
6346 png_const_structp pp, const struct transform_display *display);
6347
6348 /* Add this transform to the list and return true if the transform is
6349 * meaningful for this colour type and bit depth - if false then the
6350 * transform should have no effect on the image so there's not a lot of
6351 * point running it.
6352 */
6353 int (*add)(struct image_transform *this,
6354 const struct image_transform **that, png_byte colour_type,
6355 png_byte bit_depth);
6356} image_transform;
6357
6358typedef struct transform_display
6359{
6360 standard_display this;
6361
6362 /* Parameters */
6363 png_modifier* pm;
6364 const image_transform* transform_list;
6365 unsigned int max_gamma_8;
6366
6367 /* Local variables */
6368 png_byte output_colour_type;
6369 png_byte output_bit_depth;
6370 png_byte unpacked;
6371
6372 /* Modifications (not necessarily used.) */
6373 gama_modification gama_mod;
6374 chrm_modification chrm_mod;
6375 srgb_modification srgb_mod;
6376} transform_display;
6377
6378/* Set sRGB, cHRM and gAMA transforms as required by the current encoding. */
6379static void
6380transform_set_encoding(transform_display *this)
6381{
6382 /* Set up the png_modifier '_current' fields then use these to determine how
6383 * to add appropriate chunks.
6384 */
6385 png_modifier *pm = this->pm;
6386
6387 modifier_set_encoding(pm);
6388
6389 if (modifier_color_encoding_is_set(pm))
6390 {
6391 if (modifier_color_encoding_is_sRGB(pm))
6392 srgb_modification_init(&this->srgb_mod, pm, PNG_sRGB_INTENT_ABSOLUTE);
6393
6394 else
6395 {
6396 /* Set gAMA and cHRM separately. */
6397 gama_modification_init(&this->gama_mod, pm, pm->current_gamma);
6398
6399 if (pm->current_encoding != 0)
6400 chrm_modification_init(&this->chrm_mod, pm, pm->current_encoding);
6401 }
6402 }
6403}
6404
6405/* Three functions to end the list: */
6406static void
6407image_transform_ini_end(const image_transform *this,
6408 transform_display *that)
6409{
6410 UNUSED(this)
6411 UNUSED(that)
6412}
6413
6414static void
6415image_transform_set_end(const image_transform *this,
6416 transform_display *that, png_structp pp, png_infop pi)
6417{
6418 UNUSED(this)
6419 UNUSED(that)
6420 UNUSED(pp)
6421 UNUSED(pi)
6422}
6423
6424/* At the end of the list recalculate the output image pixel value from the
6425 * double precision values set up by the preceding 'mod' calls:
6426 */
6427static unsigned int
6428sample_scale(double sample_value, unsigned int scale)
6429{
6430 sample_value = floor(sample_value * scale + .5);
6431
6432 /* Return NaN as 0: */
6433 if (!(sample_value > 0))
6434 sample_value = 0;
6435 else if (sample_value > scale)
6436 sample_value = scale;
6437
6438 return (unsigned int)sample_value;
6439}
6440
6441static void
6442image_transform_mod_end(const image_transform *this, image_pixel *that,
6443 png_const_structp pp, const transform_display *display)
6444{
6445 unsigned int scale = (1U<<that->sample_depth)-1;
6446 int sig_bits = that->sig_bits;
6447
6448 UNUSED(this)
6449 UNUSED(pp)
6450 UNUSED(display)
6451
6452 /* At the end recalculate the digitized red green and blue values according
6453 * to the current sample_depth of the pixel.
6454 *
6455 * The sample value is simply scaled to the maximum, checking for over
6456 * and underflow (which can both happen for some image transforms,
6457 * including simple size scaling, though libpng doesn't do that at present.
6458 */
6459 that->red = sample_scale(that->redf, scale);
6460
6461 /* This is a bit bogus; really the above calculation should use the red_sBIT
6462 * value, not sample_depth, but because libpng does png_set_shift by just
6463 * shifting the bits we get errors if we don't do it the same way.
6464 */
6465 if (sig_bits && that->red_sBIT < that->sample_depth)
6466 that->red >>= that->sample_depth - that->red_sBIT;
6467
6468 /* The error value is increased, at the end, according to the lowest sBIT
6469 * value seen. Common sense tells us that the intermediate integer
6470 * representations are no more accurate than +/- 0.5 in the integral values,
6471 * the sBIT allows the implementation to be worse than this. In addition the
6472 * PNG specification actually permits any error within the range (-1..+1),
6473 * but that is ignored here. Instead the final digitized value is compared,
6474 * below to the digitized value of the error limits - this has the net effect
6475 * of allowing (almost) +/-1 in the output value. It's difficult to see how
6476 * any algorithm that digitizes intermediate results can be more accurate.
6477 */
6478 that->rede += 1./(2*((1U<<that->red_sBIT)-1));
6479
6480 if (that->colour_type & PNG_COLOR_MASK_COLOR)
6481 {
6482 that->green = sample_scale(that->greenf, scale);
6483 if (sig_bits && that->green_sBIT < that->sample_depth)
6484 that->green >>= that->sample_depth - that->green_sBIT;
6485
6486 that->blue = sample_scale(that->bluef, scale);
6487 if (sig_bits && that->blue_sBIT < that->sample_depth)
6488 that->blue >>= that->sample_depth - that->blue_sBIT;
6489
6490 that->greene += 1./(2*((1U<<that->green_sBIT)-1));
6491 that->bluee += 1./(2*((1U<<that->blue_sBIT)-1));
6492 }
6493 else
6494 {
6495 that->blue = that->green = that->red;
6496 that->bluef = that->greenf = that->redf;
6497 that->bluee = that->greene = that->rede;
6498 }
6499
6500 if ((that->colour_type & PNG_COLOR_MASK_ALPHA) ||
6501 that->colour_type == PNG_COLOR_TYPE_PALETTE)
6502 {
6503 that->alpha = sample_scale(that->alphaf, scale);
6504 that->alphae += 1./(2*((1U<<that->alpha_sBIT)-1));
6505 }
6506 else
6507 {
6508 that->alpha = scale; /* opaque */
6509 that->alphaf = 1; /* Override this. */
6510 that->alphae = 0; /* It's exact ;-) */
6511 }
6512
6513 if (sig_bits && that->alpha_sBIT < that->sample_depth)
6514 that->alpha >>= that->sample_depth - that->alpha_sBIT;
6515}
6516
6517/* Static 'end' structure: */
6518static image_transform image_transform_end =
6519{
6520 "(end)", /* name */
6521 1, /* enable */
6522 0, /* list */
6523 0, /* global_use */
6524 0, /* local_use */
6525 0, /* next */
6526 image_transform_ini_end,
6527 image_transform_set_end,
6528 image_transform_mod_end,
6529 0 /* never called, I want it to crash if it is! */
6530};
6531
6532/* Reader callbacks and implementations, where they differ from the standard
6533 * ones.
6534 */
6535static void
6536transform_display_init(transform_display *dp, png_modifier *pm, png_uint_32 id,
6537 const image_transform *transform_list)
6538{
6539 memset(dp, 0, sizeof *dp);
6540
6541 /* Standard fields */
6542 standard_display_init(&dp->this, &pm->this, id, do_read_interlace,
6543 pm->use_update_info);
6544
6545 /* Parameter fields */
6546 dp->pm = pm;
6547 dp->transform_list = transform_list;
6548 dp->max_gamma_8 = 16;
6549
6550 /* Local variable fields */
6551 dp->output_colour_type = 255; /* invalid */
6552 dp->output_bit_depth = 255; /* invalid */
6553 dp->unpacked = 0; /* not unpacked */
6554}
6555
6556static void
6557transform_info_imp(transform_display *dp, png_structp pp, png_infop pi)
6558{
6559 /* Reuse the standard stuff as appropriate. */
6560 standard_info_part1(&dp->this, pp, pi);
6561
6562 /* Now set the list of transforms. */
6563 dp->transform_list->set(dp->transform_list, dp, pp, pi);
6564
6565 /* Update the info structure for these transforms: */
6566 {
6567 int i = dp->this.use_update_info;
6568 /* Always do one call, even if use_update_info is 0. */
6569 do
6570 png_read_update_info(pp, pi);
6571 while (--i > 0);
6572 }
6573
6574 /* And get the output information into the standard_display */
6575 standard_info_part2(&dp->this, pp, pi, 1/*images*/);
6576
6577 /* Plus the extra stuff we need for the transform tests: */
6578 dp->output_colour_type = png_get_color_type(pp, pi);
6579 dp->output_bit_depth = png_get_bit_depth(pp, pi);
6580
6581 /* If png_set_filler is in action then fake the output color type to include
6582 * an alpha channel where appropriate.
6583 */
6584 if (dp->output_bit_depth >= 8 &&
6585 (dp->output_colour_type == PNG_COLOR_TYPE_RGB ||
6586 dp->output_colour_type == PNG_COLOR_TYPE_GRAY) && dp->this.filler)
6587 dp->output_colour_type |= 4;
6588
6589 /* Validate the combination of colour type and bit depth that we are getting
6590 * out of libpng; the semantics of something not in the PNG spec are, at
6591 * best, unclear.
6592 */
6593 switch (dp->output_colour_type)
6594 {
6595 case PNG_COLOR_TYPE_PALETTE:
6596 if (dp->output_bit_depth > 8) goto error;
6597 /* FALLTHROUGH */
6598 case PNG_COLOR_TYPE_GRAY:
6599 if (dp->output_bit_depth == 1 || dp->output_bit_depth == 2 ||
6600 dp->output_bit_depth == 4)
6601 break;
6602 /* FALLTHROUGH */
6603 default:
6604 if (dp->output_bit_depth == 8 || dp->output_bit_depth == 16)
6605 break;
6606 /* FALLTHROUGH */
6607 error:
6608 {
6609 char message[128];
6610 size_t pos;
6611
6612 pos = safecat(message, sizeof message, 0,
6613 "invalid final bit depth: colour type(");
6614 pos = safecatn(message, sizeof message, pos, dp->output_colour_type);
6615 pos = safecat(message, sizeof message, pos, ") with bit depth: ");
6616 pos = safecatn(message, sizeof message, pos, dp->output_bit_depth);
6617
6618 png_error(pp, message);
6619 }
6620 }
6621
6622 /* Use a test pixel to check that the output agrees with what we expect -
6623 * this avoids running the whole test if the output is unexpected. This also
6624 * checks for internal errors.
6625 */
6626 {
6627 image_pixel test_pixel;
6628
6629 memset(&test_pixel, 0, sizeof test_pixel);
6630 test_pixel.colour_type = dp->this.colour_type; /* input */
6631 test_pixel.bit_depth = dp->this.bit_depth;
6632 if (test_pixel.colour_type == PNG_COLOR_TYPE_PALETTE)
6633 test_pixel.sample_depth = 8;
6634 else
6635 test_pixel.sample_depth = test_pixel.bit_depth;
6636 /* Don't need sBIT here, but it must be set to non-zero to avoid
6637 * arithmetic overflows.
6638 */
6639 test_pixel.have_tRNS = dp->this.is_transparent != 0;
6640 test_pixel.red_sBIT = test_pixel.green_sBIT = test_pixel.blue_sBIT =
6641 test_pixel.alpha_sBIT = test_pixel.sample_depth;
6642
6643 dp->transform_list->mod(dp->transform_list, &test_pixel, pp, dp);
6644
6645 if (test_pixel.colour_type != dp->output_colour_type)
6646 {
6647 char message[128];
6648 size_t pos = safecat(message, sizeof message, 0, "colour type ");
6649
6650 pos = safecatn(message, sizeof message, pos, dp->output_colour_type);
6651 pos = safecat(message, sizeof message, pos, " expected ");
6652 pos = safecatn(message, sizeof message, pos, test_pixel.colour_type);
6653
6654 png_error(pp, message);
6655 }
6656
6657 if (test_pixel.bit_depth != dp->output_bit_depth)
6658 {
6659 char message[128];
6660 size_t pos = safecat(message, sizeof message, 0, "bit depth ");
6661
6662 pos = safecatn(message, sizeof message, pos, dp->output_bit_depth);
6663 pos = safecat(message, sizeof message, pos, " expected ");
6664 pos = safecatn(message, sizeof message, pos, test_pixel.bit_depth);
6665
6666 png_error(pp, message);
6667 }
6668
6669 /* If both bit depth and colour type are correct check the sample depth.
6670 */
6671 if (test_pixel.colour_type == PNG_COLOR_TYPE_PALETTE &&
6672 test_pixel.sample_depth != 8) /* oops - internal error! */
6673 png_error(pp, "pngvalid: internal: palette sample depth not 8");
6674 else if (dp->unpacked && test_pixel.bit_depth != 8)
6675 png_error(pp, "pngvalid: internal: bad unpacked pixel depth");
6676 else if (!dp->unpacked && test_pixel.colour_type != PNG_COLOR_TYPE_PALETTE
6677 && test_pixel.bit_depth != test_pixel.sample_depth)
6678 {
6679 char message[128];
6680 size_t pos = safecat(message, sizeof message, 0,
6681 "internal: sample depth ");
6682
6683 /* Because unless something has set 'unpacked' or the image is palette
6684 * mapped we expect the transform to keep sample depth and bit depth
6685 * the same.
6686 */
6687 pos = safecatn(message, sizeof message, pos, test_pixel.sample_depth);
6688 pos = safecat(message, sizeof message, pos, " expected ");
6689 pos = safecatn(message, sizeof message, pos, test_pixel.bit_depth);
6690
6691 png_error(pp, message);
6692 }
6693 else if (test_pixel.bit_depth != dp->output_bit_depth)
6694 {
6695 /* This could be a libpng error too; libpng has not produced what we
6696 * expect for the output bit depth.
6697 */
6698 char message[128];
6699 size_t pos = safecat(message, sizeof message, 0,
6700 "internal: bit depth ");
6701
6702 pos = safecatn(message, sizeof message, pos, dp->output_bit_depth);
6703 pos = safecat(message, sizeof message, pos, " expected ");
6704 pos = safecatn(message, sizeof message, pos, test_pixel.bit_depth);
6705
6706 png_error(pp, message);
6707 }
6708 }
6709}
6710
6711static void PNGCBAPI
6712transform_info(png_structp pp, png_infop pi)
6713{
6714 transform_info_imp(voidcast(transform_display*, png_get_progressive_ptr(pp)),
6715 pp, pi);
6716}
6717
6718static void
6719transform_range_check(png_const_structp pp, unsigned int r, unsigned int g,
6720 unsigned int b, unsigned int a, unsigned int in_digitized, double in,
6721 unsigned int out, png_byte sample_depth, double err, double limit,
6722 const char *name, double digitization_error)
6723{
6724 /* Compare the scaled, digitized, values of our local calculation (in+-err)
6725 * with the digitized values libpng produced; 'sample_depth' is the actual
6726 * digitization depth of the libpng output colors (the bit depth except for
6727 * palette images where it is always 8.) The check on 'err' is to detect
6728 * internal errors in pngvalid itself.
6729 */
6730 unsigned int max = (1U<<sample_depth)-1;
6731 double in_min = ceil((in-err)*max - digitization_error);
6732 double in_max = floor((in+err)*max + digitization_error);
6733 if (debugonly(err > limit ||) !(out >= in_min && out <= in_max))
6734 {
6735 char message[256];
6736 size_t pos;
6737
6738 pos = safecat(message, sizeof message, 0, name);
6739 pos = safecat(message, sizeof message, pos, " output value error: rgba(");
6740 pos = safecatn(message, sizeof message, pos, r);
6741 pos = safecat(message, sizeof message, pos, ",");
6742 pos = safecatn(message, sizeof message, pos, g);
6743 pos = safecat(message, sizeof message, pos, ",");
6744 pos = safecatn(message, sizeof message, pos, b);
6745 pos = safecat(message, sizeof message, pos, ",");
6746 pos = safecatn(message, sizeof message, pos, a);
6747 pos = safecat(message, sizeof message, pos, "): ");
6748 pos = safecatn(message, sizeof message, pos, out);
6749 pos = safecat(message, sizeof message, pos, " expected: ");
6750 pos = safecatn(message, sizeof message, pos, in_digitized);
6751 pos = safecat(message, sizeof message, pos, " (");
6752 pos = safecatd(message, sizeof message, pos, (in-err)*max, 3);
6753 pos = safecat(message, sizeof message, pos, "..");
6754 pos = safecatd(message, sizeof message, pos, (in+err)*max, 3);
6755 pos = safecat(message, sizeof message, pos, ")");
6756
6757 png_error(pp, message);
6758 }
6759
6760 UNUSED(limit)
6761}
6762
6763static void
6764transform_image_validate(transform_display *dp, png_const_structp pp,
6765 png_infop pi)
6766{
6767 /* Constants for the loop below: */
6768 const png_store* const ps = dp->this.ps;
6769 png_byte in_ct = dp->this.colour_type;
6770 png_byte in_bd = dp->this.bit_depth;
6771 png_uint_32 w = dp->this.w;
6772 png_uint_32 h = dp->this.h;
6773 png_byte out_ct = dp->output_colour_type;
6774 png_byte out_bd = dp->output_bit_depth;
6775 png_byte sample_depth =
6776 (png_byte)(out_ct == PNG_COLOR_TYPE_PALETTE ? 8 : out_bd);
6777 png_byte red_sBIT = dp->this.red_sBIT;
6778 png_byte green_sBIT = dp->this.green_sBIT;
6779 png_byte blue_sBIT = dp->this.blue_sBIT;
6780 png_byte alpha_sBIT = dp->this.alpha_sBIT;
6781 int have_tRNS = dp->this.is_transparent;
6782 double digitization_error;
6783
6784 store_palette out_palette;
6785 png_uint_32 y;
6786
6787 UNUSED(pi)
6788
6789 /* Check for row overwrite errors */
6790 store_image_check(dp->this.ps, pp, 0);
6791
6792 /* Read the palette corresponding to the output if the output colour type
6793 * indicates a palette, otherwise set out_palette to garbage.
6794 */
6795 if (out_ct == PNG_COLOR_TYPE_PALETTE)
6796 {
6797 /* Validate that the palette count itself has not changed - this is not
6798 * expected.
6799 */
6800 int npalette = (-1);
6801
6802 (void)read_palette(out_palette, &npalette, pp, pi);
6803 if (npalette != dp->this.npalette)
6804 png_error(pp, "unexpected change in palette size");
6805
6806 digitization_error = .5;
6807 }
6808 else
6809 {
6810 png_byte in_sample_depth;
6811
6812 memset(out_palette, 0x5e, sizeof out_palette);
6813
6814 /* use-input-precision means assume that if the input has 8 bit (or less)
6815 * samples and the output has 16 bit samples the calculations will be done
6816 * with 8 bit precision, not 16.
6817 */
6818 if (in_ct == PNG_COLOR_TYPE_PALETTE || in_bd < 16)
6819 in_sample_depth = 8;
6820 else
6821 in_sample_depth = in_bd;
6822
6823 if (sample_depth != 16 || in_sample_depth > 8 ||
6824 !dp->pm->calculations_use_input_precision)
6825 digitization_error = .5;
6826
6827 /* Else calculations are at 8 bit precision, and the output actually
6828 * consists of scaled 8-bit values, so scale .5 in 8 bits to the 16 bits:
6829 */
6830 else
6831 digitization_error = .5 * 257;
6832 }
6833
6834 for (y=0; y<h; ++y)
6835 {
6836 png_const_bytep const pRow = store_image_row(ps, pp, 0, y);
6837 png_uint_32 x;
6838
6839 /* The original, standard, row pre-transforms. */
6840 png_byte std[STANDARD_ROWMAX];
6841
6842 transform_row(pp, std, in_ct, in_bd, y);
6843
6844 /* Go through each original pixel transforming it and comparing with what
6845 * libpng did to the same pixel.
6846 */
6847 for (x=0; x<w; ++x)
6848 {
6849 image_pixel in_pixel, out_pixel;
6850 unsigned int r, g, b, a;
6851
6852 /* Find out what we think the pixel should be: */
6853 image_pixel_init(&in_pixel, std, in_ct, in_bd, x, dp->this.palette,
6854 NULL);
6855
6856 in_pixel.red_sBIT = red_sBIT;
6857 in_pixel.green_sBIT = green_sBIT;
6858 in_pixel.blue_sBIT = blue_sBIT;
6859 in_pixel.alpha_sBIT = alpha_sBIT;
6860 in_pixel.have_tRNS = have_tRNS != 0;
6861
6862 /* For error detection, below. */
6863 r = in_pixel.red;
6864 g = in_pixel.green;
6865 b = in_pixel.blue;
6866 a = in_pixel.alpha;
6867
6868 /* This applies the transforms to the input data, including output
6869 * format operations which must be used when reading the output
6870 * pixel that libpng produces.
6871 */
6872 dp->transform_list->mod(dp->transform_list, &in_pixel, pp, dp);
6873
6874 /* Read the output pixel and compare it to what we got, we don't
6875 * use the error field here, so no need to update sBIT. in_pixel
6876 * says whether we expect libpng to change the output format.
6877 */
6878 image_pixel_init(&out_pixel, pRow, out_ct, out_bd, x, out_palette,
6879 &in_pixel);
6880
6881 /* We don't expect changes to the index here even if the bit depth is
6882 * changed.
6883 */
6884 if (in_ct == PNG_COLOR_TYPE_PALETTE &&
6885 out_ct == PNG_COLOR_TYPE_PALETTE)
6886 {
6887 if (in_pixel.palette_index != out_pixel.palette_index)
6888 png_error(pp, "unexpected transformed palette index");
6889 }
6890
6891 /* Check the colours for palette images too - in fact the palette could
6892 * be separately verified itself in most cases.
6893 */
6894 if (in_pixel.red != out_pixel.red)
6895 transform_range_check(pp, r, g, b, a, in_pixel.red, in_pixel.redf,
6896 out_pixel.red, sample_depth, in_pixel.rede,
6897 dp->pm->limit + 1./(2*((1U<<in_pixel.red_sBIT)-1)), "red/gray",
6898 digitization_error);
6899
6900 if ((out_ct & PNG_COLOR_MASK_COLOR) != 0 &&
6901 in_pixel.green != out_pixel.green)
6902 transform_range_check(pp, r, g, b, a, in_pixel.green,
6903 in_pixel.greenf, out_pixel.green, sample_depth, in_pixel.greene,
6904 dp->pm->limit + 1./(2*((1U<<in_pixel.green_sBIT)-1)), "green",
6905 digitization_error);
6906
6907 if ((out_ct & PNG_COLOR_MASK_COLOR) != 0 &&
6908 in_pixel.blue != out_pixel.blue)
6909 transform_range_check(pp, r, g, b, a, in_pixel.blue, in_pixel.bluef,
6910 out_pixel.blue, sample_depth, in_pixel.bluee,
6911 dp->pm->limit + 1./(2*((1U<<in_pixel.blue_sBIT)-1)), "blue",
6912 digitization_error);
6913
6914 if ((out_ct & PNG_COLOR_MASK_ALPHA) != 0 &&
6915 in_pixel.alpha != out_pixel.alpha)
6916 transform_range_check(pp, r, g, b, a, in_pixel.alpha,
6917 in_pixel.alphaf, out_pixel.alpha, sample_depth, in_pixel.alphae,
6918 dp->pm->limit + 1./(2*((1U<<in_pixel.alpha_sBIT)-1)), "alpha",
6919 digitization_error);
6920 } /* pixel (x) loop */
6921 } /* row (y) loop */
6922
6923 /* Record that something was actually checked to avoid a false positive. */
6924 dp->this.ps->validated = 1;
6925}
6926
6927static void PNGCBAPI
6928transform_end(png_structp ppIn, png_infop pi)
6929{
6930 png_const_structp pp = ppIn;
6931 transform_display *dp = voidcast(transform_display*,
6932 png_get_progressive_ptr(pp));
6933
6934 if (!dp->this.speed)
6935 transform_image_validate(dp, pp, pi);
6936 else
6937 dp->this.ps->validated = 1;
6938}
6939
6940/* A single test run. */
6941static void
6942transform_test(png_modifier *pmIn, png_uint_32 idIn,
6943 const image_transform* transform_listIn, const char * const name)
6944{
6945 transform_display d;
6946 context(&pmIn->this, fault);
6947
6948 transform_display_init(&d, pmIn, idIn, transform_listIn);
6949
6950 Try
6951 {
6952 size_t pos = 0;
6953 png_structp pp;
6954 png_infop pi;
6955 char full_name[256];
6956
6957 /* Make sure the encoding fields are correct and enter the required
6958 * modifications.
6959 */
6960 transform_set_encoding(&d);
6961
6962 /* Add any modifications required by the transform list. */
6963 d.transform_list->ini(d.transform_list, &d);
6964
6965 /* Add the color space information, if any, to the name. */
6966 pos = safecat(full_name, sizeof full_name, pos, name);
6967 pos = safecat_current_encoding(full_name, sizeof full_name, pos, d.pm);
6968
6969 /* Get a png_struct for reading the image. */
6970 pp = set_modifier_for_read(d.pm, &pi, d.this.id, full_name);
6971 standard_palette_init(&d.this);
6972
6973# if 0
6974 /* Logging (debugging only) */
6975 {
6976 char buffer[256];
6977
6978 (void)store_message(&d.pm->this, pp, buffer, sizeof buffer, 0,
6979 "running test");
6980
6981 fprintf(stderr, "%s\n", buffer);
6982 }
6983# endif
6984
6985 /* Introduce the correct read function. */
6986 if (d.pm->this.progressive)
6987 {
6988 /* Share the row function with the standard implementation. */
6989 png_set_progressive_read_fn(pp, &d, transform_info, progressive_row,
6990 transform_end);
6991
6992 /* Now feed data into the reader until we reach the end: */
6993 modifier_progressive_read(d.pm, pp, pi);
6994 }
6995 else
6996 {
6997 /* modifier_read expects a png_modifier* */
6998 png_set_read_fn(pp, d.pm, modifier_read);
6999
7000 /* Check the header values: */
7001 png_read_info(pp, pi);
7002
7003 /* Process the 'info' requirements. Only one image is generated */
7004 transform_info_imp(&d, pp, pi);
7005
7006 sequential_row(&d.this, pp, pi, -1, 0);
7007
7008 if (!d.this.speed)
7009 transform_image_validate(&d, pp, pi);
7010 else
7011 d.this.ps->validated = 1;
7012 }
7013
7014 modifier_reset(d.pm);
7015 }
7016
7017 Catch(fault)
7018 {
7019 modifier_reset(voidcast(png_modifier*,(void*)fault));
7020 }
7021}
7022
7023/* The transforms: */
7024#define ITSTRUCT(name) image_transform_##name
7025#define ITDATA(name) image_transform_data_##name
7026#define image_transform_ini image_transform_default_ini
7027#define IT(name)\
7028static image_transform ITSTRUCT(name) =\
7029{\
7030 #name,\
7031 1, /*enable*/\
7032 &PT, /*list*/\
7033 0, /*global_use*/\
7034 0, /*local_use*/\
7035 0, /*next*/\
7036 image_transform_ini,\
7037 image_transform_png_set_##name##_set,\
7038 image_transform_png_set_##name##_mod,\
7039 image_transform_png_set_##name##_add\
7040}
7041#define PT ITSTRUCT(end) /* stores the previous transform */
7042
7043/* To save code: */
7044extern void image_transform_default_ini(const image_transform *this,
7045 transform_display *that); /* silence GCC warnings */
7046
7047void /* private, but almost always needed */
7048image_transform_default_ini(const image_transform *this,
7049 transform_display *that)
7050{
7051 this->next->ini(this->next, that);
7052}
7053
7054#ifdef PNG_READ_BACKGROUND_SUPPORTED
7055static int
7056image_transform_default_add(image_transform *this,
7057 const image_transform **that, png_byte colour_type, png_byte bit_depth)
7058{
7059 UNUSED(colour_type)
7060 UNUSED(bit_depth)
7061
7062 this->next = *that;
7063 *that = this;
7064
7065 return 1;
7066}
7067#endif
7068
7069#ifdef PNG_READ_EXPAND_SUPPORTED
7070/* png_set_palette_to_rgb */
7071static void
7072image_transform_png_set_palette_to_rgb_set(const image_transform *this,
7073 transform_display *that, png_structp pp, png_infop pi)
7074{
7075 png_set_palette_to_rgb(pp);
7076 this->next->set(this->next, that, pp, pi);
7077}
7078
7079static void
7080image_transform_png_set_palette_to_rgb_mod(const image_transform *this,
7081 image_pixel *that, png_const_structp pp,
7082 const transform_display *display)
7083{
7084 if (that->colour_type == PNG_COLOR_TYPE_PALETTE)
7085 image_pixel_convert_PLTE(that);
7086
7087 this->next->mod(this->next, that, pp, display);
7088}
7089
7090static int
7091image_transform_png_set_palette_to_rgb_add(image_transform *this,
7092 const image_transform **that, png_byte colour_type, png_byte bit_depth)
7093{
7094 UNUSED(bit_depth)
7095
7096 this->next = *that;
7097 *that = this;
7098
7099 return colour_type == PNG_COLOR_TYPE_PALETTE;
7100}
7101
7102IT(palette_to_rgb);
7103#undef PT
7104#define PT ITSTRUCT(palette_to_rgb)
7105#endif /* PNG_READ_EXPAND_SUPPORTED */
7106
7107#ifdef PNG_READ_EXPAND_SUPPORTED
7108/* png_set_tRNS_to_alpha */
7109static void
7110image_transform_png_set_tRNS_to_alpha_set(const image_transform *this,
7111 transform_display *that, png_structp pp, png_infop pi)
7112{
7113 png_set_tRNS_to_alpha(pp);
7114
7115 /* If there was a tRNS chunk that would get expanded and add an alpha
7116 * channel is_transparent must be updated:
7117 */
7118 if (that->this.has_tRNS)
7119 that->this.is_transparent = 1;
7120
7121 this->next->set(this->next, that, pp, pi);
7122}
7123
7124static void
7125image_transform_png_set_tRNS_to_alpha_mod(const image_transform *this,
7126 image_pixel *that, png_const_structp pp,
7127 const transform_display *display)
7128{
7129#if PNG_LIBPNG_VER != 10700
7130 /* LIBPNG BUG: this always forces palette images to RGB. */
7131 if (that->colour_type == PNG_COLOR_TYPE_PALETTE)
7132 image_pixel_convert_PLTE(that);
7133#endif
7134
7135 /* This effectively does an 'expand' only if there is some transparency to
7136 * convert to an alpha channel.
7137 */
7138 if (that->have_tRNS)
7139# if PNG_LIBPNG_VER == 10700
7140 if (that->colour_type != PNG_COLOR_TYPE_PALETTE &&
7141 (that->colour_type & PNG_COLOR_MASK_ALPHA) == 0)
7142# endif
7143 image_pixel_add_alpha(that, &display->this, 0/*!for background*/);
7144
7145#if PNG_LIBPNG_VER != 10700
7146 /* LIBPNG BUG: otherwise libpng still expands to 8 bits! */
7147 else
7148 {
7149 if (that->bit_depth < 8)
7150 that->bit_depth =8;
7151 if (that->sample_depth < 8)
7152 that->sample_depth = 8;
7153 }
7154#endif
7155
7156 this->next->mod(this->next, that, pp, display);
7157}
7158
7159static int
7160image_transform_png_set_tRNS_to_alpha_add(image_transform *this,
7161 const image_transform **that, png_byte colour_type, png_byte bit_depth)
7162{
7163 UNUSED(bit_depth)
7164
7165 this->next = *that;
7166 *that = this;
7167
7168 /* We don't know yet whether there will be a tRNS chunk, but we know that
7169 * this transformation should do nothing if there already is an alpha
7170 * channel. In addition, after the bug fix in 1.7.0, there is no longer
7171 * any action on a palette image.
7172 */
7173 return
7174# if PNG_LIBPNG_VER == 10700
7175 colour_type != PNG_COLOR_TYPE_PALETTE &&
7176# endif
7177 (colour_type & PNG_COLOR_MASK_ALPHA) == 0;
7178}
7179
7180IT(tRNS_to_alpha);
7181#undef PT
7182#define PT ITSTRUCT(tRNS_to_alpha)
7183#endif /* PNG_READ_EXPAND_SUPPORTED */
7184
7185#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
7186/* png_set_gray_to_rgb */
7187static void
7188image_transform_png_set_gray_to_rgb_set(const image_transform *this,
7189 transform_display *that, png_structp pp, png_infop pi)
7190{
7191 png_set_gray_to_rgb(pp);
7192 /* NOTE: this doesn't result in tRNS expansion. */
7193 this->next->set(this->next, that, pp, pi);
7194}
7195
7196static void
7197image_transform_png_set_gray_to_rgb_mod(const image_transform *this,
7198 image_pixel *that, png_const_structp pp,
7199 const transform_display *display)
7200{
7201 /* NOTE: we can actually pend the tRNS processing at this point because we
7202 * can correctly recognize the original pixel value even though we have
7203 * mapped the one gray channel to the three RGB ones, but in fact libpng
7204 * doesn't do this, so we don't either.
7205 */
7206 if ((that->colour_type & PNG_COLOR_MASK_COLOR) == 0 && that->have_tRNS)
7207 image_pixel_add_alpha(that, &display->this, 0/*!for background*/);
7208
7209 /* Simply expand the bit depth and alter the colour type as required. */
7210 if (that->colour_type == PNG_COLOR_TYPE_GRAY)
7211 {
7212 /* RGB images have a bit depth at least equal to '8' */
7213 if (that->bit_depth < 8)
7214 that->sample_depth = that->bit_depth = 8;
7215
7216 /* And just changing the colour type works here because the green and blue
7217 * channels are being maintained in lock-step with the red/gray:
7218 */
7219 that->colour_type = PNG_COLOR_TYPE_RGB;
7220 }
7221
7222 else if (that->colour_type == PNG_COLOR_TYPE_GRAY_ALPHA)
7223 that->colour_type = PNG_COLOR_TYPE_RGB_ALPHA;
7224
7225 this->next->mod(this->next, that, pp, display);
7226}
7227
7228static int
7229image_transform_png_set_gray_to_rgb_add(image_transform *this,
7230 const image_transform **that, png_byte colour_type, png_byte bit_depth)
7231{
7232 UNUSED(bit_depth)
7233
7234 this->next = *that;
7235 *that = this;
7236
7237 return (colour_type & PNG_COLOR_MASK_COLOR) == 0;
7238}
7239
7240IT(gray_to_rgb);
7241#undef PT
7242#define PT ITSTRUCT(gray_to_rgb)
7243#endif /* PNG_READ_GRAY_TO_RGB_SUPPORTED */
7244
7245#ifdef PNG_READ_EXPAND_SUPPORTED
7246/* png_set_expand */
7247static void
7248image_transform_png_set_expand_set(const image_transform *this,
7249 transform_display *that, png_structp pp, png_infop pi)
7250{
7251 png_set_expand(pp);
7252
7253 if (that->this.has_tRNS)
7254 that->this.is_transparent = 1;
7255
7256 this->next->set(this->next, that, pp, pi);
7257}
7258
7259static void
7260image_transform_png_set_expand_mod(const image_transform *this,
7261 image_pixel *that, png_const_structp pp,
7262 const transform_display *display)
7263{
7264 /* The general expand case depends on what the colour type is: */
7265 if (that->colour_type == PNG_COLOR_TYPE_PALETTE)
7266 image_pixel_convert_PLTE(that);
7267 else if (that->bit_depth < 8) /* grayscale */
7268 that->sample_depth = that->bit_depth = 8;
7269
7270 if (that->have_tRNS)
7271 image_pixel_add_alpha(that, &display->this, 0/*!for background*/);
7272
7273 this->next->mod(this->next, that, pp, display);
7274}
7275
7276static int
7277image_transform_png_set_expand_add(image_transform *this,
7278 const image_transform **that, png_byte colour_type, png_byte bit_depth)
7279{
7280 UNUSED(bit_depth)
7281
7282 this->next = *that;
7283 *that = this;
7284
7285 /* 'expand' should do nothing for RGBA or GA input - no tRNS and the bit
7286 * depth is at least 8 already.
7287 */
7288 return (colour_type & PNG_COLOR_MASK_ALPHA) == 0;
7289}
7290
7291IT(expand);
7292#undef PT
7293#define PT ITSTRUCT(expand)
7294#endif /* PNG_READ_EXPAND_SUPPORTED */
7295
7296#ifdef PNG_READ_EXPAND_SUPPORTED
7297/* png_set_expand_gray_1_2_4_to_8
7298 * Pre 1.7.0 LIBPNG BUG: this just does an 'expand'
7299 */
7300static void
7301image_transform_png_set_expand_gray_1_2_4_to_8_set(
7302 const image_transform *this, transform_display *that, png_structp pp,
7303 png_infop pi)
7304{
7305 png_set_expand_gray_1_2_4_to_8(pp);
7306 /* NOTE: don't expect this to expand tRNS */
7307 this->next->set(this->next, that, pp, pi);
7308}
7309
7310static void
7311image_transform_png_set_expand_gray_1_2_4_to_8_mod(
7312 const image_transform *this, image_pixel *that, png_const_structp pp,
7313 const transform_display *display)
7314{
7315#if PNG_LIBPNG_VER != 10700
7316 image_transform_png_set_expand_mod(this, that, pp, display);
7317#else
7318 /* Only expand grayscale of bit depth less than 8: */
7319 if (that->colour_type == PNG_COLOR_TYPE_GRAY &&
7320 that->bit_depth < 8)
7321 that->sample_depth = that->bit_depth = 8;
7322
7323 this->next->mod(this->next, that, pp, display);
7324#endif /* 1.7 or later */
7325}
7326
7327static int
7328image_transform_png_set_expand_gray_1_2_4_to_8_add(image_transform *this,
7329 const image_transform **that, png_byte colour_type, png_byte bit_depth)
7330{
7331#if PNG_LIBPNG_VER != 10700
7332 return image_transform_png_set_expand_add(this, that, colour_type,
7333 bit_depth);
7334#else
7335 UNUSED(bit_depth)
7336
7337 this->next = *that;
7338 *that = this;
7339
7340 /* This should do nothing unless the color type is gray and the bit depth is
7341 * less than 8:
7342 */
7343 return colour_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8;
7344#endif /* 1.7 or later */
7345}
7346
7347IT(expand_gray_1_2_4_to_8);
7348#undef PT
7349#define PT ITSTRUCT(expand_gray_1_2_4_to_8)
7350#endif /* PNG_READ_EXPAND_SUPPORTED */
7351
7352#ifdef PNG_READ_EXPAND_16_SUPPORTED
7353/* png_set_expand_16 */
7354static void
7355image_transform_png_set_expand_16_set(const image_transform *this,
7356 transform_display *that, png_structp pp, png_infop pi)
7357{
7358 png_set_expand_16(pp);
7359
7360 /* NOTE: prior to 1.7 libpng does SET_EXPAND as well, so tRNS is expanded. */
7361# if PNG_LIBPNG_VER != 10700
7362 if (that->this.has_tRNS)
7363 that->this.is_transparent = 1;
7364# endif
7365
7366 this->next->set(this->next, that, pp, pi);
7367}
7368
7369static void
7370image_transform_png_set_expand_16_mod(const image_transform *this,
7371 image_pixel *that, png_const_structp pp,
7372 const transform_display *display)
7373{
7374 /* Expect expand_16 to expand everything to 16 bits as a result of also
7375 * causing 'expand' to happen.
7376 */
7377 if (that->colour_type == PNG_COLOR_TYPE_PALETTE)
7378 image_pixel_convert_PLTE(that);
7379
7380 if (that->have_tRNS)
7381 image_pixel_add_alpha(that, &display->this, 0/*!for background*/);
7382
7383 if (that->bit_depth < 16)
7384 that->sample_depth = that->bit_depth = 16;
7385
7386 this->next->mod(this->next, that, pp, display);
7387}
7388
7389static int
7390image_transform_png_set_expand_16_add(image_transform *this,
7391 const image_transform **that, png_byte colour_type, png_byte bit_depth)
7392{
7393 UNUSED(colour_type)
7394
7395 this->next = *that;
7396 *that = this;
7397
7398 /* expand_16 does something unless the bit depth is already 16. */
7399 return bit_depth < 16;
7400}
7401
7402IT(expand_16);
7403#undef PT
7404#define PT ITSTRUCT(expand_16)
7405#endif /* PNG_READ_EXPAND_16_SUPPORTED */
7406
7407#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED /* API added in 1.5.4 */
7408/* png_set_scale_16 */
7409static void
7410image_transform_png_set_scale_16_set(const image_transform *this,
7411 transform_display *that, png_structp pp, png_infop pi)
7412{
7413 png_set_scale_16(pp);
7414# if PNG_LIBPNG_VER != 10700
7415 /* libpng will limit the gamma table size: */
7416 that->max_gamma_8 = PNG_MAX_GAMMA_8;
7417# endif
7418 this->next->set(this->next, that, pp, pi);
7419}
7420
7421static void
7422image_transform_png_set_scale_16_mod(const image_transform *this,
7423 image_pixel *that, png_const_structp pp,
7424 const transform_display *display)
7425{
7426 if (that->bit_depth == 16)
7427 {
7428 that->sample_depth = that->bit_depth = 8;
7429 if (that->red_sBIT > 8) that->red_sBIT = 8;
7430 if (that->green_sBIT > 8) that->green_sBIT = 8;
7431 if (that->blue_sBIT > 8) that->blue_sBIT = 8;
7432 if (that->alpha_sBIT > 8) that->alpha_sBIT = 8;
7433 }
7434
7435 this->next->mod(this->next, that, pp, display);
7436}
7437
7438static int
7439image_transform_png_set_scale_16_add(image_transform *this,
7440 const image_transform **that, png_byte colour_type, png_byte bit_depth)
7441{
7442 UNUSED(colour_type)
7443
7444 this->next = *that;
7445 *that = this;
7446
7447 return bit_depth > 8;
7448}
7449
7450IT(scale_16);
7451#undef PT
7452#define PT ITSTRUCT(scale_16)
7453#endif /* PNG_READ_SCALE_16_TO_8_SUPPORTED (1.5.4 on) */
7454
7455#ifdef PNG_READ_16_TO_8_SUPPORTED /* the default before 1.5.4 */
7456/* png_set_strip_16 */
7457static void
7458image_transform_png_set_strip_16_set(const image_transform *this,
7459 transform_display *that, png_structp pp, png_infop pi)
7460{
7461 png_set_strip_16(pp);
7462# if PNG_LIBPNG_VER != 10700
7463 /* libpng will limit the gamma table size: */
7464 that->max_gamma_8 = PNG_MAX_GAMMA_8;
7465# endif
7466 this->next->set(this->next, that, pp, pi);
7467}
7468
7469static void
7470image_transform_png_set_strip_16_mod(const image_transform *this,
7471 image_pixel *that, png_const_structp pp,
7472 const transform_display *display)
7473{
7474 if (that->bit_depth == 16)
7475 {
7476 that->sample_depth = that->bit_depth = 8;
7477 if (that->red_sBIT > 8) that->red_sBIT = 8;
7478 if (that->green_sBIT > 8) that->green_sBIT = 8;
7479 if (that->blue_sBIT > 8) that->blue_sBIT = 8;
7480 if (that->alpha_sBIT > 8) that->alpha_sBIT = 8;
7481
7482 /* Prior to 1.5.4 png_set_strip_16 would use an 'accurate' method if this
7483 * configuration option is set. From 1.5.4 the flag is never set and the
7484 * 'scale' API (above) must be used.
7485 */
7486# ifdef PNG_READ_ACCURATE_SCALE_SUPPORTED
7487# if PNG_LIBPNG_VER >= 10504
7488# error PNG_READ_ACCURATE_SCALE should not be set
7489# endif
7490
7491 /* The strip 16 algorithm drops the low 8 bits rather than calculating
7492 * 1/257, so we need to adjust the permitted errors appropriately:
7493 * Notice that this is only relevant prior to the addition of the
7494 * png_set_scale_16 API in 1.5.4 (but 1.5.4+ always defines the above!)
7495 */
7496 {
7497 const double d = (255-128.5)/65535;
7498 that->rede += d;
7499 that->greene += d;
7500 that->bluee += d;
7501 that->alphae += d;
7502 }
7503# endif
7504 }
7505
7506 this->next->mod(this->next, that, pp, display);
7507}
7508
7509static int
7510image_transform_png_set_strip_16_add(image_transform *this,
7511 const image_transform **that, png_byte colour_type, png_byte bit_depth)
7512{
7513 UNUSED(colour_type)
7514
7515 this->next = *that;
7516 *that = this;
7517
7518 return bit_depth > 8;
7519}
7520
7521IT(strip_16);
7522#undef PT
7523#define PT ITSTRUCT(strip_16)
7524#endif /* PNG_READ_16_TO_8_SUPPORTED */
7525
7526#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
7527/* png_set_strip_alpha */
7528static void
7529image_transform_png_set_strip_alpha_set(const image_transform *this,
7530 transform_display *that, png_structp pp, png_infop pi)
7531{
7532 png_set_strip_alpha(pp);
7533 this->next->set(this->next, that, pp, pi);
7534}
7535
7536static void
7537image_transform_png_set_strip_alpha_mod(const image_transform *this,
7538 image_pixel *that, png_const_structp pp,
7539 const transform_display *display)
7540{
7541 if (that->colour_type == PNG_COLOR_TYPE_GRAY_ALPHA)
7542 that->colour_type = PNG_COLOR_TYPE_GRAY;
7543 else if (that->colour_type == PNG_COLOR_TYPE_RGB_ALPHA)
7544 that->colour_type = PNG_COLOR_TYPE_RGB;
7545
7546 that->have_tRNS = 0;
7547 that->alphaf = 1;
7548
7549 this->next->mod(this->next, that, pp, display);
7550}
7551
7552static int
7553image_transform_png_set_strip_alpha_add(image_transform *this,
7554 const image_transform **that, png_byte colour_type, png_byte bit_depth)
7555{
7556 UNUSED(bit_depth)
7557
7558 this->next = *that;
7559 *that = this;
7560
7561 return (colour_type & PNG_COLOR_MASK_ALPHA) != 0;
7562}
7563
7564IT(strip_alpha);
7565#undef PT
7566#define PT ITSTRUCT(strip_alpha)
7567#endif /* PNG_READ_STRIP_ALPHA_SUPPORTED */
7568
7569#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
7570/* png_set_rgb_to_gray(png_structp, int err_action, double red, double green)
7571 * png_set_rgb_to_gray_fixed(png_structp, int err_action, png_fixed_point red,
7572 * png_fixed_point green)
7573 * png_get_rgb_to_gray_status
7574 *
7575 * The 'default' test here uses values known to be used inside libpng prior to
7576 * 1.7.0:
7577 *
7578 * red: 6968
7579 * green: 23434
7580 * blue: 2366
7581 *
7582 * These values are being retained for compatibility, along with the somewhat
7583 * broken truncation calculation in the fast-and-inaccurate code path. Older
7584 * versions of libpng will fail the accuracy tests below because they use the
7585 * truncation algorithm everywhere.
7586 */
7587#define data ITDATA(rgb_to_gray)
7588static struct
7589{
7590 double gamma; /* File gamma to use in processing */
7591
7592 /* The following are the parameters for png_set_rgb_to_gray: */
7593# ifdef PNG_FLOATING_POINT_SUPPORTED
7594 double red_to_set;
7595 double green_to_set;
7596# else
7597 png_fixed_point red_to_set;
7598 png_fixed_point green_to_set;
7599# endif
7600
7601 /* The actual coefficients: */
7602 double red_coefficient;
7603 double green_coefficient;
7604 double blue_coefficient;
7605
7606 /* Set if the coeefficients have been overridden. */
7607 int coefficients_overridden;
7608} data;
7609
7610#undef image_transform_ini
7611#define image_transform_ini image_transform_png_set_rgb_to_gray_ini
7612static void
7613image_transform_png_set_rgb_to_gray_ini(const image_transform *this,
7614 transform_display *that)
7615{
7616 png_modifier *pm = that->pm;
7617 const color_encoding *e = pm->current_encoding;
7618
7619 UNUSED(this)
7620
7621 /* Since we check the encoding this flag must be set: */
7622 pm->test_uses_encoding = 1;
7623
7624 /* If 'e' is not NULL chromaticity information is present and either a cHRM
7625 * or an sRGB chunk will be inserted.
7626 */
7627 if (e != 0)
7628 {
7629 /* Coefficients come from the encoding, but may need to be normalized to a
7630 * white point Y of 1.0
7631 */
7632 const double whiteY = e->red.Y + e->green.Y + e->blue.Y;
7633
7634 data.red_coefficient = e->red.Y;
7635 data.green_coefficient = e->green.Y;
7636 data.blue_coefficient = e->blue.Y;
7637
7638 if (whiteY != 1)
7639 {
7640 data.red_coefficient /= whiteY;
7641 data.green_coefficient /= whiteY;
7642 data.blue_coefficient /= whiteY;
7643 }
7644 }
7645
7646 else
7647 {
7648 /* The default (built in) coefficients, as above: */
7649# if PNG_LIBPNG_VER != 10700
7650 data.red_coefficient = 6968 / 32768.;
7651 data.green_coefficient = 23434 / 32768.;
7652 data.blue_coefficient = 2366 / 32768.;
7653# else
7654 data.red_coefficient = .2126;
7655 data.green_coefficient = .7152;
7656 data.blue_coefficient = .0722;
7657# endif
7658 }
7659
7660 data.gamma = pm->current_gamma;
7661
7662 /* If not set then the calculations assume linear encoding (implicitly): */
7663 if (data.gamma == 0)
7664 data.gamma = 1;
7665
7666 /* The arguments to png_set_rgb_to_gray can override the coefficients implied
7667 * by the color space encoding. If doing exhaustive checks do the override
7668 * in each case, otherwise do it randomly.
7669 */
7670 if (pm->test_exhaustive)
7671 {
7672 /* First time in coefficients_overridden is 0, the following sets it to 1,
7673 * so repeat if it is set. If a test fails this may mean we subsequently
7674 * skip a non-override test, ignore that.
7675 */
7676 data.coefficients_overridden = !data.coefficients_overridden;
7677 pm->repeat = data.coefficients_overridden != 0;
7678 }
7679
7680 else
7681 data.coefficients_overridden = random_choice();
7682
7683 if (data.coefficients_overridden)
7684 {
7685 /* These values override the color encoding defaults, simply use random
7686 * numbers.
7687 */
7688 png_uint_32 ru;
7689 double total;
7690
7691 ru = random_u32();
7692 data.green_coefficient = total = (ru & 0xffff) / 65535.;
7693 ru >>= 16;
7694 data.red_coefficient = (1 - total) * (ru & 0xffff) / 65535.;
7695 total += data.red_coefficient;
7696 data.blue_coefficient = 1 - total;
7697
7698# ifdef PNG_FLOATING_POINT_SUPPORTED
7699 data.red_to_set = data.red_coefficient;
7700 data.green_to_set = data.green_coefficient;
7701# else
7702 data.red_to_set = fix(data.red_coefficient);
7703 data.green_to_set = fix(data.green_coefficient);
7704# endif
7705
7706 /* The following just changes the error messages: */
7707 pm->encoding_ignored = 1;
7708 }
7709
7710 else
7711 {
7712 data.red_to_set = -1;
7713 data.green_to_set = -1;
7714 }
7715
7716 /* Adjust the error limit in the png_modifier because of the larger errors
7717 * produced in the digitization during the gamma handling.
7718 */
7719 if (data.gamma != 1) /* Use gamma tables */
7720 {
7721 if (that->this.bit_depth == 16 || pm->assume_16_bit_calculations)
7722 {
7723 /* The computations have the form:
7724 *
7725 * r * rc + g * gc + b * bc
7726 *
7727 * Each component of which is +/-1/65535 from the gamma_to_1 table
7728 * lookup, resulting in a base error of +/-6. The gamma_from_1
7729 * conversion adds another +/-2 in the 16-bit case and
7730 * +/-(1<<(15-PNG_MAX_GAMMA_8)) in the 8-bit case.
7731 */
7732# if PNG_LIBPNG_VER != 10700
7733 if (that->this.bit_depth < 16)
7734 that->max_gamma_8 = PNG_MAX_GAMMA_8;
7735# endif
7736 that->pm->limit += pow(
7737 (that->this.bit_depth == 16 || that->max_gamma_8 > 14 ?
7738 8. :
7739 6. + (1<<(15-that->max_gamma_8))
7740 )/65535, data.gamma);
7741 }
7742
7743 else
7744 {
7745 /* Rounding to 8 bits in the linear space causes massive errors which
7746 * will trigger the error check in transform_range_check. Fix that
7747 * here by taking the gamma encoding into account.
7748 *
7749 * When DIGITIZE is set because a pre-1.7 version of libpng is being
7750 * tested allow a bigger slack.
7751 *
7752 * NOTE: this number only affects the internal limit check in pngvalid,
7753 * it has no effect on the limits applied to the libpng values.
7754 */
7755#if DIGITIZE
7756 that->pm->limit += pow( 2.0/255, data.gamma);
7757#else
7758 that->pm->limit += pow( 1.0/255, data.gamma);
7759#endif
7760 }
7761 }
7762
7763 else
7764 {
7765 /* With no gamma correction a large error comes from the truncation of the
7766 * calculation in the 8 bit case, allow for that here.
7767 */
7768 if (that->this.bit_depth != 16 && !pm->assume_16_bit_calculations)
7769 that->pm->limit += 4E-3;
7770 }
7771}
7772
7773static void
7774image_transform_png_set_rgb_to_gray_set(const image_transform *this,
7775 transform_display *that, png_structp pp, png_infop pi)
7776{
7777 int error_action = 1; /* no error, no defines in png.h */
7778
7779# ifdef PNG_FLOATING_POINT_SUPPORTED
7780 png_set_rgb_to_gray(pp, error_action, data.red_to_set, data.green_to_set);
7781# else
7782 png_set_rgb_to_gray_fixed(pp, error_action, data.red_to_set,
7783 data.green_to_set);
7784# endif
7785
7786# ifdef PNG_READ_cHRM_SUPPORTED
7787 if (that->pm->current_encoding != 0)
7788 {
7789 /* We have an encoding so a cHRM chunk may have been set; if so then
7790 * check that the libpng APIs give the correct (X,Y,Z) values within
7791 * some margin of error for the round trip through the chromaticity
7792 * form.
7793 */
7794# ifdef PNG_FLOATING_POINT_SUPPORTED
7795# define API_function png_get_cHRM_XYZ
7796# define API_form "FP"
7797# define API_type double
7798# define API_cvt(x) (x)
7799# else
7800# define API_function png_get_cHRM_XYZ_fixed
7801# define API_form "fixed"
7802# define API_type png_fixed_point
7803# define API_cvt(x) ((double)(x)/PNG_FP_1)
7804# endif
7805
7806 API_type rX, gX, bX;
7807 API_type rY, gY, bY;
7808 API_type rZ, gZ, bZ;
7809
7810 if ((API_function(pp, pi, &rX, &rY, &rZ, &gX, &gY, &gZ, &bX, &bY, &bZ)
7811 & PNG_INFO_cHRM) != 0)
7812 {
7813 double maxe;
7814 const char *el;
7815 color_encoding e, o;
7816
7817 /* Expect libpng to return a normalized result, but the original
7818 * color space encoding may not be normalized.
7819 */
7820 modifier_current_encoding(that->pm, &o);
7821 normalize_color_encoding(&o);
7822
7823 /* Sanity check the pngvalid code - the coefficients should match
7824 * the normalized Y values of the encoding unless they were
7825 * overridden.
7826 */
7827 if (data.red_to_set == -1 && data.green_to_set == -1 &&
7828 (fabs(o.red.Y - data.red_coefficient) > DBL_EPSILON ||
7829 fabs(o.green.Y - data.green_coefficient) > DBL_EPSILON ||
7830 fabs(o.blue.Y - data.blue_coefficient) > DBL_EPSILON))
7831 png_error(pp, "internal pngvalid cHRM coefficient error");
7832
7833 /* Generate a colour space encoding. */
7834 e.gamma = o.gamma; /* not used */
7835 e.red.X = API_cvt(rX);
7836 e.red.Y = API_cvt(rY);
7837 e.red.Z = API_cvt(rZ);
7838 e.green.X = API_cvt(gX);
7839 e.green.Y = API_cvt(gY);
7840 e.green.Z = API_cvt(gZ);
7841 e.blue.X = API_cvt(bX);
7842 e.blue.Y = API_cvt(bY);
7843 e.blue.Z = API_cvt(bZ);
7844
7845 /* This should match the original one from the png_modifier, within
7846 * the range permitted by the libpng fixed point representation.
7847 */
7848 maxe = 0;
7849 el = "-"; /* Set to element name with error */
7850
7851# define CHECK(col,x)\
7852 {\
7853 double err = fabs(o.col.x - e.col.x);\
7854 if (err > maxe)\
7855 {\
7856 maxe = err;\
7857 el = #col "(" #x ")";\
7858 }\
7859 }
7860
7861 CHECK(red,X)
7862 CHECK(red,Y)
7863 CHECK(red,Z)
7864 CHECK(green,X)
7865 CHECK(green,Y)
7866 CHECK(green,Z)
7867 CHECK(blue,X)
7868 CHECK(blue,Y)
7869 CHECK(blue,Z)
7870
7871 /* Here in both fixed and floating cases to check the values read
7872 * from the cHRm chunk. PNG uses fixed point in the cHRM chunk, so
7873 * we can't expect better than +/-.5E-5 on the result, allow 1E-5.
7874 */
7875 if (maxe >= 1E-5)
7876 {
7877 size_t pos = 0;
7878 char buffer[256];
7879
7880 pos = safecat(buffer, sizeof buffer, pos, API_form);
7881 pos = safecat(buffer, sizeof buffer, pos, " cHRM ");
7882 pos = safecat(buffer, sizeof buffer, pos, el);
7883 pos = safecat(buffer, sizeof buffer, pos, " error: ");
7884 pos = safecatd(buffer, sizeof buffer, pos, maxe, 7);
7885 pos = safecat(buffer, sizeof buffer, pos, " ");
7886 /* Print the color space without the gamma value: */
7887 pos = safecat_color_encoding(buffer, sizeof buffer, pos, &o, 0);
7888 pos = safecat(buffer, sizeof buffer, pos, " -> ");
7889 pos = safecat_color_encoding(buffer, sizeof buffer, pos, &e, 0);
7890
7891 png_error(pp, buffer);
7892 }
7893 }
7894 }
7895# endif /* READ_cHRM */
7896
7897 this->next->set(this->next, that, pp, pi);
7898}
7899
7900static void
7901image_transform_png_set_rgb_to_gray_mod(const image_transform *this,
7902 image_pixel *that, png_const_structp pp,
7903 const transform_display *display)
7904{
7905 if ((that->colour_type & PNG_COLOR_MASK_COLOR) != 0)
7906 {
7907 double gray, err;
7908
7909# if PNG_LIBPNG_VER != 10700
7910 if (that->colour_type == PNG_COLOR_TYPE_PALETTE)
7911 image_pixel_convert_PLTE(that);
7912# endif
7913
7914 /* Image now has RGB channels... */
7915# if DIGITIZE
7916 {
7917 png_modifier *pm = display->pm;
7918 unsigned int sample_depth = that->sample_depth;
7919 unsigned int calc_depth = (pm->assume_16_bit_calculations ? 16 :
7920 sample_depth);
7921 unsigned int gamma_depth =
7922 (sample_depth == 16 ?
7923 display->max_gamma_8 :
7924 (pm->assume_16_bit_calculations ?
7925 display->max_gamma_8 :
7926 sample_depth));
7927 int isgray;
7928 double r, g, b;
7929 double rlo, rhi, glo, ghi, blo, bhi, graylo, grayhi;
7930
7931 /* Do this using interval arithmetic, otherwise it is too difficult to
7932 * handle the errors correctly.
7933 *
7934 * To handle the gamma correction work out the upper and lower bounds
7935 * of the digitized value. Assume rounding here - normally the values
7936 * will be identical after this operation if there is only one
7937 * transform, feel free to delete the png_error checks on this below in
7938 * the future (this is just me trying to ensure it works!)
7939 *
7940 * Interval arithmetic is exact, but to implement it it must be
7941 * possible to control the floating point implementation rounding mode.
7942 * This cannot be done in ANSI-C, so instead I reduce the 'lo' values
7943 * by DBL_EPSILON and increase the 'hi' values by the same.
7944 */
7945# define DD(v,d,r) (digitize(v*(1-DBL_EPSILON), d, r) * (1-DBL_EPSILON))
7946# define DU(v,d,r) (digitize(v*(1+DBL_EPSILON), d, r) * (1+DBL_EPSILON))
7947
7948 r = rlo = rhi = that->redf;
7949 rlo -= that->rede;
7950 rlo = DD(rlo, calc_depth, 1/*round*/);
7951 rhi += that->rede;
7952 rhi = DU(rhi, calc_depth, 1/*round*/);
7953
7954 g = glo = ghi = that->greenf;
7955 glo -= that->greene;
7956 glo = DD(glo, calc_depth, 1/*round*/);
7957 ghi += that->greene;
7958 ghi = DU(ghi, calc_depth, 1/*round*/);
7959
7960 b = blo = bhi = that->bluef;
7961 blo -= that->bluee;
7962 blo = DD(blo, calc_depth, 1/*round*/);
7963 bhi += that->bluee;
7964 bhi = DU(bhi, calc_depth, 1/*round*/);
7965
7966 isgray = r==g && g==b;
7967
7968 if (data.gamma != 1)
7969 {
7970 const double power = 1/data.gamma;
7971 const double abse = .5/(sample_depth == 16 ? 65535 : 255);
7972
7973 /* If a gamma calculation is done it is done using lookup tables of
7974 * precision gamma_depth, so the already digitized value above may
7975 * need to be further digitized here.
7976 */
7977 if (gamma_depth != calc_depth)
7978 {
7979 rlo = DD(rlo, gamma_depth, 0/*truncate*/);
7980 rhi = DU(rhi, gamma_depth, 0/*truncate*/);
7981 glo = DD(glo, gamma_depth, 0/*truncate*/);
7982 ghi = DU(ghi, gamma_depth, 0/*truncate*/);
7983 blo = DD(blo, gamma_depth, 0/*truncate*/);
7984 bhi = DU(bhi, gamma_depth, 0/*truncate*/);
7985 }
7986
7987 /* 'abse' is the error in the gamma table calculation itself. */
7988 r = pow(r, power);
7989 rlo = DD(pow(rlo, power)-abse, calc_depth, 1);
7990 rhi = DU(pow(rhi, power)+abse, calc_depth, 1);
7991
7992 g = pow(g, power);
7993 glo = DD(pow(glo, power)-abse, calc_depth, 1);
7994 ghi = DU(pow(ghi, power)+abse, calc_depth, 1);
7995
7996 b = pow(b, power);
7997 blo = DD(pow(blo, power)-abse, calc_depth, 1);
7998 bhi = DU(pow(bhi, power)+abse, calc_depth, 1);
7999 }
8000
8001 /* Now calculate the actual gray values. Although the error in the
8002 * coefficients depends on whether they were specified on the command
8003 * line (in which case truncation to 15 bits happened) or not (rounding
8004 * was used) the maximum error in an individual coefficient is always
8005 * 2/32768, because even in the rounding case the requirement that
8006 * coefficients add up to 32768 can cause a larger rounding error.
8007 *
8008 * The only time when rounding doesn't occur in 1.5.5 and later is when
8009 * the non-gamma code path is used for less than 16 bit data.
8010 */
8011 gray = r * data.red_coefficient + g * data.green_coefficient +
8012 b * data.blue_coefficient;
8013
8014 {
8015 int do_round = data.gamma != 1 || calc_depth == 16;
8016 const double ce = 2. / 32768;
8017
8018 graylo = DD(rlo * (data.red_coefficient-ce) +
8019 glo * (data.green_coefficient-ce) +
8020 blo * (data.blue_coefficient-ce), calc_depth, do_round);
8021 if (graylo > gray) /* always accept the right answer */
8022 graylo = gray;
8023
8024 grayhi = DU(rhi * (data.red_coefficient+ce) +
8025 ghi * (data.green_coefficient+ce) +
8026 bhi * (data.blue_coefficient+ce), calc_depth, do_round);
8027 if (grayhi < gray)
8028 grayhi = gray;
8029 }
8030
8031 /* And invert the gamma. */
8032 if (data.gamma != 1)
8033 {
8034 const double power = data.gamma;
8035
8036 /* And this happens yet again, shifting the values once more. */
8037 if (gamma_depth != sample_depth)
8038 {
8039 rlo = DD(rlo, gamma_depth, 0/*truncate*/);
8040 rhi = DU(rhi, gamma_depth, 0/*truncate*/);
8041 glo = DD(glo, gamma_depth, 0/*truncate*/);
8042 ghi = DU(ghi, gamma_depth, 0/*truncate*/);
8043 blo = DD(blo, gamma_depth, 0/*truncate*/);
8044 bhi = DU(bhi, gamma_depth, 0/*truncate*/);
8045 }
8046
8047 gray = pow(gray, power);
8048 graylo = DD(pow(graylo, power), sample_depth, 1);
8049 grayhi = DU(pow(grayhi, power), sample_depth, 1);
8050 }
8051
8052# undef DD
8053# undef DU
8054
8055 /* Now the error can be calculated.
8056 *
8057 * If r==g==b because there is no overall gamma correction libpng
8058 * currently preserves the original value.
8059 */
8060 if (isgray)
8061 err = (that->rede + that->greene + that->bluee)/3;
8062
8063 else
8064 {
8065 err = fabs(grayhi-gray);
8066
8067 if (fabs(gray - graylo) > err)
8068 err = fabs(graylo-gray);
8069
8070#if !RELEASE_BUILD
8071 /* Check that this worked: */
8072 if (err > pm->limit)
8073 {
8074 size_t pos = 0;
8075 char buffer[128];
8076
8077 pos = safecat(buffer, sizeof buffer, pos, "rgb_to_gray error ");
8078 pos = safecatd(buffer, sizeof buffer, pos, err, 6);
8079 pos = safecat(buffer, sizeof buffer, pos, " exceeds limit ");
8080 pos = safecatd(buffer, sizeof buffer, pos, pm->limit, 6);
8081 png_warning(pp, buffer);
8082 pm->limit = err;
8083 }
8084#endif /* !RELEASE_BUILD */
8085 }
8086 }
8087# else /* !DIGITIZE */
8088 {
8089 double r = that->redf;
8090 double re = that->rede;
8091 double g = that->greenf;
8092 double ge = that->greene;
8093 double b = that->bluef;
8094 double be = that->bluee;
8095
8096# if PNG_LIBPNG_VER != 10700
8097 /* The true gray case involves no math in earlier versions (not
8098 * true, there was some if gamma correction was happening too.)
8099 */
8100 if (r == g && r == b)
8101 {
8102 gray = r;
8103 err = re;
8104 if (err < ge) err = ge;
8105 if (err < be) err = be;
8106 }
8107
8108 else
8109# endif /* before 1.7 */
8110 if (data.gamma == 1)
8111 {
8112 /* There is no need to do the conversions to and from linear space,
8113 * so the calculation should be a lot more accurate. There is a
8114 * built in error in the coefficients because they only have 15 bits
8115 * and are adjusted to make sure they add up to 32768. This
8116 * involves a integer calculation with truncation of the form:
8117 *
8118 * ((int)(coefficient * 100000) * 32768)/100000
8119 *
8120 * This is done to the red and green coefficients (the ones
8121 * provided to the API) then blue is calculated from them so the
8122 * result adds up to 32768. In the worst case this can result in
8123 * a -1 error in red and green and a +2 error in blue. Consequently
8124 * the worst case in the calculation below is 2/32768 error.
8125 *
8126 * TODO: consider fixing this in libpng by rounding the calculation
8127 * limiting the error to 1/32768.
8128 *
8129 * Handling this by adding 2/32768 here avoids needing to increase
8130 * the global error limits to take this into account.)
8131 */
8132 gray = r * data.red_coefficient + g * data.green_coefficient +
8133 b * data.blue_coefficient;
8134 err = re * data.red_coefficient + ge * data.green_coefficient +
8135 be * data.blue_coefficient + 2./32768 + gray * 5 * DBL_EPSILON;
8136 }
8137
8138 else
8139 {
8140 /* The calculation happens in linear space, and this produces much
8141 * wider errors in the encoded space. These are handled here by
8142 * factoring the errors in to the calculation. There are two table
8143 * lookups in the calculation and each introduces a quantization
8144 * error defined by the table size.
8145 */
8146 png_modifier *pm = display->pm;
8147 double in_qe = (that->sample_depth > 8 ? .5/65535 : .5/255);
8148 double out_qe = (that->sample_depth > 8 ? .5/65535 :
8149 (pm->assume_16_bit_calculations ? .5/(1<<display->max_gamma_8) :
8150 .5/255));
8151 double rhi, ghi, bhi, grayhi;
8152 double g1 = 1/data.gamma;
8153
8154 rhi = r + re + in_qe; if (rhi > 1) rhi = 1;
8155 r -= re + in_qe; if (r < 0) r = 0;
8156 ghi = g + ge + in_qe; if (ghi > 1) ghi = 1;
8157 g -= ge + in_qe; if (g < 0) g = 0;
8158 bhi = b + be + in_qe; if (bhi > 1) bhi = 1;
8159 b -= be + in_qe; if (b < 0) b = 0;
8160
8161 r = pow(r, g1)*(1-DBL_EPSILON); rhi = pow(rhi, g1)*(1+DBL_EPSILON);
8162 g = pow(g, g1)*(1-DBL_EPSILON); ghi = pow(ghi, g1)*(1+DBL_EPSILON);
8163 b = pow(b, g1)*(1-DBL_EPSILON); bhi = pow(bhi, g1)*(1+DBL_EPSILON);
8164
8165 /* Work out the lower and upper bounds for the gray value in the
8166 * encoded space, then work out an average and error. Remove the
8167 * previously added input quantization error at this point.
8168 */
8169 gray = r * data.red_coefficient + g * data.green_coefficient +
8170 b * data.blue_coefficient - 2./32768 - out_qe;
8171 if (gray <= 0)
8172 gray = 0;
8173 else
8174 {
8175 gray *= (1 - 6 * DBL_EPSILON);
8176 gray = pow(gray, data.gamma) * (1-DBL_EPSILON);
8177 }
8178
8179 grayhi = rhi * data.red_coefficient + ghi * data.green_coefficient +
8180 bhi * data.blue_coefficient + 2./32768 + out_qe;
8181 grayhi *= (1 + 6 * DBL_EPSILON);
8182 if (grayhi >= 1)
8183 grayhi = 1;
8184 else
8185 grayhi = pow(grayhi, data.gamma) * (1+DBL_EPSILON);
8186
8187 err = (grayhi - gray) / 2;
8188 gray = (grayhi + gray) / 2;
8189
8190 if (err <= in_qe)
8191 err = gray * DBL_EPSILON;
8192
8193 else
8194 err -= in_qe;
8195
8196#if !RELEASE_BUILD
8197 /* Validate that the error is within limits (this has caused
8198 * problems before, it's much easier to detect them here.)
8199 */
8200 if (err > pm->limit)
8201 {
8202 size_t pos = 0;
8203 char buffer[128];
8204
8205 pos = safecat(buffer, sizeof buffer, pos, "rgb_to_gray error ");
8206 pos = safecatd(buffer, sizeof buffer, pos, err, 6);
8207 pos = safecat(buffer, sizeof buffer, pos, " exceeds limit ");
8208 pos = safecatd(buffer, sizeof buffer, pos, pm->limit, 6);
8209 png_warning(pp, buffer);
8210 pm->limit = err;
8211 }
8212#endif /* !RELEASE_BUILD */
8213 }
8214 }
8215# endif /* !DIGITIZE */
8216
8217 that->bluef = that->greenf = that->redf = gray;
8218 that->bluee = that->greene = that->rede = err;
8219
8220 /* The sBIT is the minimum of the three colour channel sBITs. */
8221 if (that->red_sBIT > that->green_sBIT)
8222 that->red_sBIT = that->green_sBIT;
8223 if (that->red_sBIT > that->blue_sBIT)
8224 that->red_sBIT = that->blue_sBIT;
8225 that->blue_sBIT = that->green_sBIT = that->red_sBIT;
8226
8227 /* And remove the colour bit in the type: */
8228 if (that->colour_type == PNG_COLOR_TYPE_RGB)
8229 that->colour_type = PNG_COLOR_TYPE_GRAY;
8230 else if (that->colour_type == PNG_COLOR_TYPE_RGB_ALPHA)
8231 that->colour_type = PNG_COLOR_TYPE_GRAY_ALPHA;
8232 }
8233
8234 this->next->mod(this->next, that, pp, display);
8235}
8236
8237static int
8238image_transform_png_set_rgb_to_gray_add(image_transform *this,
8239 const image_transform **that, png_byte colour_type, png_byte bit_depth)
8240{
8241 UNUSED(bit_depth)
8242
8243 this->next = *that;
8244 *that = this;
8245
8246 return (colour_type & PNG_COLOR_MASK_COLOR) != 0;
8247}
8248
8249#undef data
8250IT(rgb_to_gray);
8251#undef PT
8252#define PT ITSTRUCT(rgb_to_gray)
8253#undef image_transform_ini
8254#define image_transform_ini image_transform_default_ini
8255#endif /* PNG_READ_RGB_TO_GRAY_SUPPORTED */
8256
8257#ifdef PNG_READ_BACKGROUND_SUPPORTED
8258/* png_set_background(png_structp, png_const_color_16p background_color,
8259 * int background_gamma_code, int need_expand, double background_gamma)
8260 * png_set_background_fixed(png_structp, png_const_color_16p background_color,
8261 * int background_gamma_code, int need_expand,
8262 * png_fixed_point background_gamma)
8263 *
8264 * This ignores the gamma (at present.)
8265*/
8266#define data ITDATA(background)
8267static image_pixel data;
8268
8269static void
8270image_transform_png_set_background_set(const image_transform *this,
8271 transform_display *that, png_structp pp, png_infop pi)
8272{
8273 png_byte colour_type, bit_depth;
8274 png_byte random_bytes[8]; /* 8 bytes - 64 bits - the biggest pixel */
8275 int expand;
8276 png_color_16 back;
8277
8278 /* We need a background colour, because we don't know exactly what transforms
8279 * have been set we have to supply the colour in the original file format and
8280 * so we need to know what that is! The background colour is stored in the
8281 * transform_display.
8282 */
8283 R8(random_bytes);
8284
8285 /* Read the random value, for colour type 3 the background colour is actually
8286 * expressed as a 24bit rgb, not an index.
8287 */
8288 colour_type = that->this.colour_type;
8289 if (colour_type == 3)
8290 {
8291 colour_type = PNG_COLOR_TYPE_RGB;
8292 bit_depth = 8;
8293 expand = 0; /* passing in an RGB not a pixel index */
8294 }
8295
8296 else
8297 {
8298 if (that->this.has_tRNS)
8299 that->this.is_transparent = 1;
8300
8301 bit_depth = that->this.bit_depth;
8302 expand = 1;
8303 }
8304
8305 image_pixel_init(&data, random_bytes, colour_type,
8306 bit_depth, 0/*x*/, 0/*unused: palette*/, NULL/*format*/);
8307
8308 /* Extract the background colour from this image_pixel, but make sure the
8309 * unused fields of 'back' are garbage.
8310 */
8311 R8(back);
8312
8313 if (colour_type & PNG_COLOR_MASK_COLOR)
8314 {
8315 back.red = (png_uint_16)data.red;
8316 back.green = (png_uint_16)data.green;
8317 back.blue = (png_uint_16)data.blue;
8318 }
8319
8320 else
8321 back.gray = (png_uint_16)data.red;
8322
8323#ifdef PNG_FLOATING_POINT_SUPPORTED
8324 png_set_background(pp, &back, PNG_BACKGROUND_GAMMA_FILE, expand, 0);
8325#else
8326 png_set_background_fixed(pp, &back, PNG_BACKGROUND_GAMMA_FILE, expand, 0);
8327#endif
8328
8329 this->next->set(this->next, that, pp, pi);
8330}
8331
8332static void
8333image_transform_png_set_background_mod(const image_transform *this,
8334 image_pixel *that, png_const_structp pp,
8335 const transform_display *display)
8336{
8337 /* Check for tRNS first: */
8338 if (that->have_tRNS && that->colour_type != PNG_COLOR_TYPE_PALETTE)
8339 image_pixel_add_alpha(that, &display->this, 1/*for background*/);
8340
8341 /* This is only necessary if the alpha value is less than 1. */
8342 if (that->alphaf < 1)
8343 {
8344 /* Now we do the background calculation without any gamma correction. */
8345 if (that->alphaf <= 0)
8346 {
8347 that->redf = data.redf;
8348 that->greenf = data.greenf;
8349 that->bluef = data.bluef;
8350
8351 that->rede = data.rede;
8352 that->greene = data.greene;
8353 that->bluee = data.bluee;
8354
8355 that->red_sBIT= data.red_sBIT;
8356 that->green_sBIT= data.green_sBIT;
8357 that->blue_sBIT= data.blue_sBIT;
8358 }
8359
8360 else /* 0 < alpha < 1 */
8361 {
8362 double alf = 1 - that->alphaf;
8363
8364 that->redf = that->redf * that->alphaf + data.redf * alf;
8365 that->rede = that->rede * that->alphaf + data.rede * alf +
8366 DBL_EPSILON;
8367 that->greenf = that->greenf * that->alphaf + data.greenf * alf;
8368 that->greene = that->greene * that->alphaf + data.greene * alf +
8369 DBL_EPSILON;
8370 that->bluef = that->bluef * that->alphaf + data.bluef * alf;
8371 that->bluee = that->bluee * that->alphaf + data.bluee * alf +
8372 DBL_EPSILON;
8373 }
8374
8375 /* Remove the alpha type and set the alpha (not in that order.) */
8376 that->alphaf = 1;
8377 that->alphae = 0;
8378 }
8379
8380 if (that->colour_type == PNG_COLOR_TYPE_RGB_ALPHA)
8381 that->colour_type = PNG_COLOR_TYPE_RGB;
8382 else if (that->colour_type == PNG_COLOR_TYPE_GRAY_ALPHA)
8383 that->colour_type = PNG_COLOR_TYPE_GRAY;
8384 /* PNG_COLOR_TYPE_PALETTE is not changed */
8385
8386 this->next->mod(this->next, that, pp, display);
8387}
8388
8389#define image_transform_png_set_background_add image_transform_default_add
8390
8391#undef data
8392IT(background);
8393#undef PT
8394#define PT ITSTRUCT(background)
8395#endif /* PNG_READ_BACKGROUND_SUPPORTED */
8396
8397/* png_set_quantize(png_structp, png_colorp palette, int num_palette,
8398 * int maximum_colors, png_const_uint_16p histogram, int full_quantize)
8399 *
8400 * Very difficult to validate this!
8401 */
8402/*NOTE: TBD NYI */
8403
8404/* The data layout transforms are handled by swapping our own channel data,
8405 * necessarily these need to happen at the end of the transform list because the
8406 * semantic of the channels changes after these are executed. Some of these,
8407 * like set_shift and set_packing, can't be done at present because they change
8408 * the layout of the data at the sub-sample level so sample() won't get the
8409 * right answer.
8410 */
8411/* png_set_invert_alpha */
8412#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
8413/* Invert the alpha channel
8414 *
8415 * png_set_invert_alpha(png_structrp png_ptr)
8416 */
8417static void
8418image_transform_png_set_invert_alpha_set(const image_transform *this,
8419 transform_display *that, png_structp pp, png_infop pi)
8420{
8421 png_set_invert_alpha(pp);
8422 this->next->set(this->next, that, pp, pi);
8423}
8424
8425static void
8426image_transform_png_set_invert_alpha_mod(const image_transform *this,
8427 image_pixel *that, png_const_structp pp,
8428 const transform_display *display)
8429{
8430 if (that->colour_type & 4)
8431 that->alpha_inverted = 1;
8432
8433 this->next->mod(this->next, that, pp, display);
8434}
8435
8436static int
8437image_transform_png_set_invert_alpha_add(image_transform *this,
8438 const image_transform **that, png_byte colour_type, png_byte bit_depth)
8439{
8440 UNUSED(bit_depth)
8441
8442 this->next = *that;
8443 *that = this;
8444
8445 /* Only has an effect on pixels with alpha: */
8446 return (colour_type & 4) != 0;
8447}
8448
8449IT(invert_alpha);
8450#undef PT
8451#define PT ITSTRUCT(invert_alpha)
8452
8453#endif /* PNG_READ_INVERT_ALPHA_SUPPORTED */
8454
8455/* png_set_bgr */
8456#ifdef PNG_READ_BGR_SUPPORTED
8457/* Swap R,G,B channels to order B,G,R.
8458 *
8459 * png_set_bgr(png_structrp png_ptr)
8460 *
8461 * This only has an effect on RGB and RGBA pixels.
8462 */
8463static void
8464image_transform_png_set_bgr_set(const image_transform *this,
8465 transform_display *that, png_structp pp, png_infop pi)
8466{
8467 png_set_bgr(pp);
8468 this->next->set(this->next, that, pp, pi);
8469}
8470
8471static void
8472image_transform_png_set_bgr_mod(const image_transform *this,
8473 image_pixel *that, png_const_structp pp,
8474 const transform_display *display)
8475{
8476 if (that->colour_type == PNG_COLOR_TYPE_RGB ||
8477 that->colour_type == PNG_COLOR_TYPE_RGBA)
8478 that->swap_rgb = 1;
8479
8480 this->next->mod(this->next, that, pp, display);
8481}
8482
8483static int
8484image_transform_png_set_bgr_add(image_transform *this,
8485 const image_transform **that, png_byte colour_type, png_byte bit_depth)
8486{
8487 UNUSED(bit_depth)
8488
8489 this->next = *that;
8490 *that = this;
8491
8492 return colour_type == PNG_COLOR_TYPE_RGB ||
8493 colour_type == PNG_COLOR_TYPE_RGBA;
8494}
8495
8496IT(bgr);
8497#undef PT
8498#define PT ITSTRUCT(bgr)
8499
8500#endif /* PNG_READ_BGR_SUPPORTED */
8501
8502/* png_set_swap_alpha */
8503#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
8504/* Put the alpha channel first.
8505 *
8506 * png_set_swap_alpha(png_structrp png_ptr)
8507 *
8508 * This only has an effect on GA and RGBA pixels.
8509 */
8510static void
8511image_transform_png_set_swap_alpha_set(const image_transform *this,
8512 transform_display *that, png_structp pp, png_infop pi)
8513{
8514 png_set_swap_alpha(pp);
8515 this->next->set(this->next, that, pp, pi);
8516}
8517
8518static void
8519image_transform_png_set_swap_alpha_mod(const image_transform *this,
8520 image_pixel *that, png_const_structp pp,
8521 const transform_display *display)
8522{
8523 if (that->colour_type == PNG_COLOR_TYPE_GA ||
8524 that->colour_type == PNG_COLOR_TYPE_RGBA)
8525 that->alpha_first = 1;
8526
8527 this->next->mod(this->next, that, pp, display);
8528}
8529
8530static int
8531image_transform_png_set_swap_alpha_add(image_transform *this,
8532 const image_transform **that, png_byte colour_type, png_byte bit_depth)
8533{
8534 UNUSED(bit_depth)
8535
8536 this->next = *that;
8537 *that = this;
8538
8539 return colour_type == PNG_COLOR_TYPE_GA ||
8540 colour_type == PNG_COLOR_TYPE_RGBA;
8541}
8542
8543IT(swap_alpha);
8544#undef PT
8545#define PT ITSTRUCT(swap_alpha)
8546
8547#endif /* PNG_READ_SWAP_ALPHA_SUPPORTED */
8548
8549/* png_set_swap */
8550#ifdef PNG_READ_SWAP_SUPPORTED
8551/* Byte swap 16-bit components.
8552 *
8553 * png_set_swap(png_structrp png_ptr)
8554 */
8555static void
8556image_transform_png_set_swap_set(const image_transform *this,
8557 transform_display *that, png_structp pp, png_infop pi)
8558{
8559 png_set_swap(pp);
8560 this->next->set(this->next, that, pp, pi);
8561}
8562
8563static void
8564image_transform_png_set_swap_mod(const image_transform *this,
8565 image_pixel *that, png_const_structp pp,
8566 const transform_display *display)
8567{
8568 if (that->bit_depth == 16)
8569 that->swap16 = 1;
8570
8571 this->next->mod(this->next, that, pp, display);
8572}
8573
8574static int
8575image_transform_png_set_swap_add(image_transform *this,
8576 const image_transform **that, png_byte colour_type, png_byte bit_depth)
8577{
8578 UNUSED(colour_type)
8579
8580 this->next = *that;
8581 *that = this;
8582
8583 return bit_depth == 16;
8584}
8585
8586IT(swap);
8587#undef PT
8588#define PT ITSTRUCT(swap)
8589
8590#endif /* PNG_READ_SWAP_SUPPORTED */
8591
8592#ifdef PNG_READ_FILLER_SUPPORTED
8593/* Add a filler byte to 8-bit Gray or 24-bit RGB images.
8594 *
8595 * png_set_filler, (png_structp png_ptr, png_uint_32 filler, int flags));
8596 *
8597 * Flags:
8598 *
8599 * PNG_FILLER_BEFORE
8600 * PNG_FILLER_AFTER
8601 */
8602#define data ITDATA(filler)
8603static struct
8604{
8605 png_uint_32 filler;
8606 int flags;
8607} data;
8608
8609static void
8610image_transform_png_set_filler_set(const image_transform *this,
8611 transform_display *that, png_structp pp, png_infop pi)
8612{
8613 /* Need a random choice for 'before' and 'after' as well as for the
8614 * filler. The 'filler' value has all 32 bits set, but only bit_depth
8615 * will be used. At this point we don't know bit_depth.
8616 */
8617 data.filler = random_u32();
8618 data.flags = random_choice();
8619
8620 png_set_filler(pp, data.filler, data.flags);
8621
8622 /* The standard display handling stuff also needs to know that
8623 * there is a filler, so set that here.
8624 */
8625 that->this.filler = 1;
8626
8627 this->next->set(this->next, that, pp, pi);
8628}
8629
8630static void
8631image_transform_png_set_filler_mod(const image_transform *this,
8632 image_pixel *that, png_const_structp pp,
8633 const transform_display *display)
8634{
8635 if (that->bit_depth >= 8 &&
8636 (that->colour_type == PNG_COLOR_TYPE_RGB ||
8637 that->colour_type == PNG_COLOR_TYPE_GRAY))
8638 {
8639 unsigned int max = (1U << that->bit_depth)-1;
8640 that->alpha = data.filler & max;
8641 that->alphaf = ((double)that->alpha) / max;
8642 that->alphae = 0;
8643
8644 /* The filler has been stored in the alpha channel, we must record
8645 * that this has been done for the checking later on, the color
8646 * type is faked to have an alpha channel, but libpng won't report
8647 * this; the app has to know the extra channel is there and this
8648 * was recording in standard_display::filler above.
8649 */
8650 that->colour_type |= 4; /* alpha added */
8651 that->alpha_first = data.flags == PNG_FILLER_BEFORE;
8652 }
8653
8654 this->next->mod(this->next, that, pp, display);
8655}
8656
8657static int
8658image_transform_png_set_filler_add(image_transform *this,
8659 const image_transform **that, png_byte colour_type, png_byte bit_depth)
8660{
8661 this->next = *that;
8662 *that = this;
8663
8664 return bit_depth >= 8 && (colour_type == PNG_COLOR_TYPE_RGB ||
8665 colour_type == PNG_COLOR_TYPE_GRAY);
8666}
8667
8668#undef data
8669IT(filler);
8670#undef PT
8671#define PT ITSTRUCT(filler)
8672
8673/* png_set_add_alpha, (png_structp png_ptr, png_uint_32 filler, int flags)); */
8674/* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */
8675#define data ITDATA(add_alpha)
8676static struct
8677{
8678 png_uint_32 filler;
8679 int flags;
8680} data;
8681
8682static void
8683image_transform_png_set_add_alpha_set(const image_transform *this,
8684 transform_display *that, png_structp pp, png_infop pi)
8685{
8686 /* Need a random choice for 'before' and 'after' as well as for the
8687 * filler. The 'filler' value has all 32 bits set, but only bit_depth
8688 * will be used. At this point we don't know bit_depth.
8689 */
8690 data.filler = random_u32();
8691 data.flags = random_choice();
8692
8693 png_set_add_alpha(pp, data.filler, data.flags);
8694 this->next->set(this->next, that, pp, pi);
8695}
8696
8697static void
8698image_transform_png_set_add_alpha_mod(const image_transform *this,
8699 image_pixel *that, png_const_structp pp,
8700 const transform_display *display)
8701{
8702 if (that->bit_depth >= 8 &&
8703 (that->colour_type == PNG_COLOR_TYPE_RGB ||
8704 that->colour_type == PNG_COLOR_TYPE_GRAY))
8705 {
8706 unsigned int max = (1U << that->bit_depth)-1;
8707 that->alpha = data.filler & max;
8708 that->alphaf = ((double)that->alpha) / max;
8709 that->alphae = 0;
8710
8711 that->colour_type |= 4; /* alpha added */
8712 that->alpha_first = data.flags == PNG_FILLER_BEFORE;
8713 }
8714
8715 this->next->mod(this->next, that, pp, display);
8716}
8717
8718static int
8719image_transform_png_set_add_alpha_add(image_transform *this,
8720 const image_transform **that, png_byte colour_type, png_byte bit_depth)
8721{
8722 this->next = *that;
8723 *that = this;
8724
8725 return bit_depth >= 8 && (colour_type == PNG_COLOR_TYPE_RGB ||
8726 colour_type == PNG_COLOR_TYPE_GRAY);
8727}
8728
8729#undef data
8730IT(add_alpha);
8731#undef PT
8732#define PT ITSTRUCT(add_alpha)
8733
8734#endif /* PNG_READ_FILLER_SUPPORTED */
8735
8736/* png_set_packing */
8737#ifdef PNG_READ_PACK_SUPPORTED
8738/* Use 1 byte per pixel in 1, 2, or 4-bit depth files.
8739 *
8740 * png_set_packing(png_structrp png_ptr)
8741 *
8742 * This should only affect grayscale and palette images with less than 8 bits
8743 * per pixel.
8744 */
8745static void
8746image_transform_png_set_packing_set(const image_transform *this,
8747 transform_display *that, png_structp pp, png_infop pi)
8748{
8749 png_set_packing(pp);
8750 that->unpacked = 1;
8751 this->next->set(this->next, that, pp, pi);
8752}
8753
8754static void
8755image_transform_png_set_packing_mod(const image_transform *this,
8756 image_pixel *that, png_const_structp pp,
8757 const transform_display *display)
8758{
8759 /* The general expand case depends on what the colour type is,
8760 * low bit-depth pixel values are unpacked into bytes without
8761 * scaling, so sample_depth is not changed.
8762 */
8763 if (that->bit_depth < 8) /* grayscale or palette */
8764 that->bit_depth = 8;
8765
8766 this->next->mod(this->next, that, pp, display);
8767}
8768
8769static int
8770image_transform_png_set_packing_add(image_transform *this,
8771 const image_transform **that, png_byte colour_type, png_byte bit_depth)
8772{
8773 UNUSED(colour_type)
8774
8775 this->next = *that;
8776 *that = this;
8777
8778 /* Nothing should happen unless the bit depth is less than 8: */
8779 return bit_depth < 8;
8780}
8781
8782IT(packing);
8783#undef PT
8784#define PT ITSTRUCT(packing)
8785
8786#endif /* PNG_READ_PACK_SUPPORTED */
8787
8788/* png_set_packswap */
8789#ifdef PNG_READ_PACKSWAP_SUPPORTED
8790/* Swap pixels packed into bytes; reverses the order on screen so that
8791 * the high order bits correspond to the rightmost pixels.
8792 *
8793 * png_set_packswap(png_structrp png_ptr)
8794 */
8795static void
8796image_transform_png_set_packswap_set(const image_transform *this,
8797 transform_display *that, png_structp pp, png_infop pi)
8798{
8799 png_set_packswap(pp);
8800 that->this.littleendian = 1;
8801 this->next->set(this->next, that, pp, pi);
8802}
8803
8804static void
8805image_transform_png_set_packswap_mod(const image_transform *this,
8806 image_pixel *that, png_const_structp pp,
8807 const transform_display *display)
8808{
8809 if (that->bit_depth < 8)
8810 that->littleendian = 1;
8811
8812 this->next->mod(this->next, that, pp, display);
8813}
8814
8815static int
8816image_transform_png_set_packswap_add(image_transform *this,
8817 const image_transform **that, png_byte colour_type, png_byte bit_depth)
8818{
8819 UNUSED(colour_type)
8820
8821 this->next = *that;
8822 *that = this;
8823
8824 return bit_depth < 8;
8825}
8826
8827IT(packswap);
8828#undef PT
8829#define PT ITSTRUCT(packswap)
8830
8831#endif /* PNG_READ_PACKSWAP_SUPPORTED */
8832
8833
8834/* png_set_invert_mono */
8835#ifdef PNG_READ_INVERT_MONO_SUPPORTED
8836/* Invert the gray channel
8837 *
8838 * png_set_invert_mono(png_structrp png_ptr)
8839 */
8840static void
8841image_transform_png_set_invert_mono_set(const image_transform *this,
8842 transform_display *that, png_structp pp, png_infop pi)
8843{
8844 png_set_invert_mono(pp);
8845 this->next->set(this->next, that, pp, pi);
8846}
8847
8848static void
8849image_transform_png_set_invert_mono_mod(const image_transform *this,
8850 image_pixel *that, png_const_structp pp,
8851 const transform_display *display)
8852{
8853 if (that->colour_type & 4)
8854 that->mono_inverted = 1;
8855
8856 this->next->mod(this->next, that, pp, display);
8857}
8858
8859static int
8860image_transform_png_set_invert_mono_add(image_transform *this,
8861 const image_transform **that, png_byte colour_type, png_byte bit_depth)
8862{
8863 UNUSED(bit_depth)
8864
8865 this->next = *that;
8866 *that = this;
8867
8868 /* Only has an effect on pixels with no colour: */
8869 return (colour_type & 2) == 0;
8870}
8871
8872IT(invert_mono);
8873#undef PT
8874#define PT ITSTRUCT(invert_mono)
8875
8876#endif /* PNG_READ_INVERT_MONO_SUPPORTED */
8877
8878#ifdef PNG_READ_SHIFT_SUPPORTED
8879/* png_set_shift(png_structp, png_const_color_8p true_bits)
8880 *
8881 * The output pixels will be shifted by the given true_bits
8882 * values.
8883 */
8884#define data ITDATA(shift)
8885static png_color_8 data;
8886
8887static void
8888image_transform_png_set_shift_set(const image_transform *this,
8889 transform_display *that, png_structp pp, png_infop pi)
8890{
8891 /* Get a random set of shifts. The shifts need to do something
8892 * to test the transform, so they are limited to the bit depth
8893 * of the input image. Notice that in the following the 'gray'
8894 * field is randomized independently. This acts as a check that
8895 * libpng does use the correct field.
8896 */
8897 unsigned int depth = that->this.bit_depth;
8898
8899 data.red = (png_byte)/*SAFE*/(random_mod(depth)+1);
8900 data.green = (png_byte)/*SAFE*/(random_mod(depth)+1);
8901 data.blue = (png_byte)/*SAFE*/(random_mod(depth)+1);
8902 data.gray = (png_byte)/*SAFE*/(random_mod(depth)+1);
8903 data.alpha = (png_byte)/*SAFE*/(random_mod(depth)+1);
8904
8905 png_set_shift(pp, &data);
8906 this->next->set(this->next, that, pp, pi);
8907}
8908
8909static void
8910image_transform_png_set_shift_mod(const image_transform *this,
8911 image_pixel *that, png_const_structp pp,
8912 const transform_display *display)
8913{
8914 /* Copy the correct values into the sBIT fields, libpng does not do
8915 * anything to palette data:
8916 */
8917 if (that->colour_type != PNG_COLOR_TYPE_PALETTE)
8918 {
8919 that->sig_bits = 1;
8920
8921 /* The sBIT fields are reset to the values previously sent to
8922 * png_set_shift according to the colour type.
8923 * does.
8924 */
8925 if (that->colour_type & 2) /* RGB channels */
8926 {
8927 that->red_sBIT = data.red;
8928 that->green_sBIT = data.green;
8929 that->blue_sBIT = data.blue;
8930 }
8931
8932 else /* One grey channel */
8933 that->red_sBIT = that->green_sBIT = that->blue_sBIT = data.gray;
8934
8935 that->alpha_sBIT = data.alpha;
8936 }
8937
8938 this->next->mod(this->next, that, pp, display);
8939}
8940
8941static int
8942image_transform_png_set_shift_add(image_transform *this,
8943 const image_transform **that, png_byte colour_type, png_byte bit_depth)
8944{
8945 UNUSED(bit_depth)
8946
8947 this->next = *that;
8948 *that = this;
8949
8950 return colour_type != PNG_COLOR_TYPE_PALETTE;
8951}
8952
8953IT(shift);
8954#undef PT
8955#define PT ITSTRUCT(shift)
8956
8957#endif /* PNG_READ_SHIFT_SUPPORTED */
8958
8959#ifdef THIS_IS_THE_PROFORMA
8960static void
8961image_transform_png_set_@_set(const image_transform *this,
8962 transform_display *that, png_structp pp, png_infop pi)
8963{
8964 png_set_@(pp);
8965 this->next->set(this->next, that, pp, pi);
8966}
8967
8968static void
8969image_transform_png_set_@_mod(const image_transform *this,
8970 image_pixel *that, png_const_structp pp,
8971 const transform_display *display)
8972{
8973 this->next->mod(this->next, that, pp, display);
8974}
8975
8976static int
8977image_transform_png_set_@_add(image_transform *this,
8978 const image_transform **that, png_byte colour_type, png_byte bit_depth)
8979{
8980 this->next = *that;
8981 *that = this;
8982
8983 return 1;
8984}
8985
8986IT(@);
8987#endif
8988
8989
8990/* This may just be 'end' if all the transforms are disabled! */
8991static image_transform *const image_transform_first = &PT;
8992
8993static void
8994transform_enable(const char *name)
8995{
8996 /* Everything starts out enabled, so if we see an 'enable' disabled
8997 * everything else the first time round.
8998 */
8999 static int all_disabled = 0;
9000 int found_it = 0;
9001 image_transform *list = image_transform_first;
9002
9003 while (list != &image_transform_end)
9004 {
9005 if (strcmp(list->name, name) == 0)
9006 {
9007 list->enable = 1;
9008 found_it = 1;
9009 }
9010 else if (!all_disabled)
9011 list->enable = 0;
9012
9013 list = list->list;
9014 }
9015
9016 all_disabled = 1;
9017
9018 if (!found_it)
9019 {
9020 fprintf(stderr, "pngvalid: --transform-enable=%s: unknown transform\n",
9021 name);
9022 exit(99);
9023 }
9024}
9025
9026static void
9027transform_disable(const char *name)
9028{
9029 image_transform *list = image_transform_first;
9030
9031 while (list != &image_transform_end)
9032 {
9033 if (strcmp(list->name, name) == 0)
9034 {
9035 list->enable = 0;
9036 return;
9037 }
9038
9039 list = list->list;
9040 }
9041
9042 fprintf(stderr, "pngvalid: --transform-disable=%s: unknown transform\n",
9043 name);
9044 exit(99);
9045}
9046
9047static void
9048image_transform_reset_count(void)
9049{
9050 image_transform *next = image_transform_first;
9051 int count = 0;
9052
9053 while (next != &image_transform_end)
9054 {
9055 next->local_use = 0;
9056 next->next = 0;
9057 next = next->list;
9058 ++count;
9059 }
9060
9061 /* This can only happen if we every have more than 32 transforms (excluding
9062 * the end) in the list.
9063 */
9064 if (count > 32) abort();
9065}
9066
9067static int
9068image_transform_test_counter(png_uint_32 counter, unsigned int max)
9069{
9070 /* Test the list to see if there is any point continuing, given a current
9071 * counter and a 'max' value.
9072 */
9073 image_transform *next = image_transform_first;
9074
9075 while (next != &image_transform_end)
9076 {
9077 /* For max 0 or 1 continue until the counter overflows: */
9078 counter >>= 1;
9079
9080 /* Continue if any entry hasn't reacked the max. */
9081 if (max > 1 && next->local_use < max)
9082 return 1;
9083 next = next->list;
9084 }
9085
9086 return max <= 1 && counter == 0;
9087}
9088
9089static png_uint_32
9090image_transform_add(const image_transform **this, unsigned int max,
9091 png_uint_32 counter, char *name, size_t sizeof_name, size_t *pos,
9092 png_byte colour_type, png_byte bit_depth)
9093{
9094 for (;;) /* until we manage to add something */
9095 {
9096 png_uint_32 mask;
9097 image_transform *list;
9098
9099 /* Find the next counter value, if the counter is zero this is the start
9100 * of the list. This routine always returns the current counter (not the
9101 * next) so it returns 0 at the end and expects 0 at the beginning.
9102 */
9103 if (counter == 0) /* first time */
9104 {
9105 image_transform_reset_count();
9106 if (max <= 1)
9107 counter = 1;
9108 else
9109 counter = random_32();
9110 }
9111 else /* advance the counter */
9112 {
9113 switch (max)
9114 {
9115 case 0: ++counter; break;
9116 case 1: counter <<= 1; break;
9117 default: counter = random_32(); break;
9118 }
9119 }
9120
9121 /* Now add all these items, if possible */
9122 *this = &image_transform_end;
9123 list = image_transform_first;
9124 mask = 1;
9125
9126 /* Go through the whole list adding anything that the counter selects: */
9127 while (list != &image_transform_end)
9128 {
9129 if ((counter & mask) != 0 && list->enable &&
9130 (max == 0 || list->local_use < max))
9131 {
9132 /* Candidate to add: */
9133 if (list->add(list, this, colour_type, bit_depth) || max == 0)
9134 {
9135 /* Added, so add to the name too. */
9136 *pos = safecat(name, sizeof_name, *pos, " +");
9137 *pos = safecat(name, sizeof_name, *pos, list->name);
9138 }
9139
9140 else
9141 {
9142 /* Not useful and max>0, so remove it from *this: */
9143 *this = list->next;
9144 list->next = 0;
9145
9146 /* And, since we know it isn't useful, stop it being added again
9147 * in this run:
9148 */
9149 list->local_use = max;
9150 }
9151 }
9152
9153 mask <<= 1;
9154 list = list->list;
9155 }
9156
9157 /* Now if anything was added we have something to do. */
9158 if (*this != &image_transform_end)
9159 return counter;
9160
9161 /* Nothing added, but was there anything in there to add? */
9162 if (!image_transform_test_counter(counter, max))
9163 return 0;
9164 }
9165}
9166
9167static void
9168perform_transform_test(png_modifier *pm)
9169{
9170 png_byte colour_type = 0;
9171 png_byte bit_depth = 0;
9172 unsigned int palette_number = 0;
9173
9174 while (next_format(&colour_type, &bit_depth, &palette_number, pm->test_lbg,
9175 pm->test_tRNS))
9176 {
9177 png_uint_32 counter = 0;
9178 size_t base_pos;
9179 char name[64];
9180
9181 base_pos = safecat(name, sizeof name, 0, "transform:");
9182
9183 for (;;)
9184 {
9185 size_t pos = base_pos;
9186 const image_transform *list = 0;
9187
9188 /* 'max' is currently hardwired to '1'; this should be settable on the
9189 * command line.
9190 */
9191 counter = image_transform_add(&list, 1/*max*/, counter,
9192 name, sizeof name, &pos, colour_type, bit_depth);
9193
9194 if (counter == 0)
9195 break;
9196
9197 /* The command line can change this to checking interlaced images. */
9198 do
9199 {
9200 pm->repeat = 0;
9201 transform_test(pm, FILEID(colour_type, bit_depth, palette_number,
9202 pm->interlace_type, 0, 0, 0), list, name);
9203
9204 if (fail(pm))
9205 return;
9206 }
9207 while (pm->repeat);
9208 }
9209 }
9210}
9211#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
9212
9213/********************************* GAMMA TESTS ********************************/
9214#ifdef PNG_READ_GAMMA_SUPPORTED
9215/* Reader callbacks and implementations, where they differ from the standard
9216 * ones.
9217 */
9218typedef struct gamma_display
9219{
9220 standard_display this;
9221
9222 /* Parameters */
9223 png_modifier* pm;
9224 double file_gamma;
9225 double screen_gamma;
9226 double background_gamma;
9227 png_byte sbit;
9228 int threshold_test;
9229 int use_input_precision;
9230 int scale16;
9231 int expand16;
9232 int do_background;
9233 png_color_16 background_color;
9234
9235 /* Local variables */
9236 double maxerrout;
9237 double maxerrpc;
9238 double maxerrabs;
9239} gamma_display;
9240
9241#define ALPHA_MODE_OFFSET 4
9242
9243static void
9244gamma_display_init(gamma_display *dp, png_modifier *pm, png_uint_32 id,
9245 double file_gamma, double screen_gamma, png_byte sbit, int threshold_test,
9246 int use_input_precision, int scale16, int expand16,
9247 int do_background, const png_color_16 *pointer_to_the_background_color,
9248 double background_gamma)
9249{
9250 /* Standard fields */
9251 standard_display_init(&dp->this, &pm->this, id, do_read_interlace,
9252 pm->use_update_info);
9253
9254 /* Parameter fields */
9255 dp->pm = pm;
9256 dp->file_gamma = file_gamma;
9257 dp->screen_gamma = screen_gamma;
9258 dp->background_gamma = background_gamma;
9259 dp->sbit = sbit;
9260 dp->threshold_test = threshold_test;
9261 dp->use_input_precision = use_input_precision;
9262 dp->scale16 = scale16;
9263 dp->expand16 = expand16;
9264 dp->do_background = do_background;
9265 if (do_background && pointer_to_the_background_color != 0)
9266 dp->background_color = *pointer_to_the_background_color;
9267 else
9268 memset(&dp->background_color, 0, sizeof dp->background_color);
9269
9270 /* Local variable fields */
9271 dp->maxerrout = dp->maxerrpc = dp->maxerrabs = 0;
9272}
9273
9274static void
9275gamma_info_imp(gamma_display *dp, png_structp pp, png_infop pi)
9276{
9277 /* Reuse the standard stuff as appropriate. */
9278 standard_info_part1(&dp->this, pp, pi);
9279
9280 /* If requested strip 16 to 8 bits - this is handled automagically below
9281 * because the output bit depth is read from the library. Note that there
9282 * are interactions with sBIT but, internally, libpng makes sbit at most
9283 * PNG_MAX_GAMMA_8 prior to 1.7 when doing the following.
9284 */
9285 if (dp->scale16)
9286# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
9287 png_set_scale_16(pp);
9288# else
9289 /* The following works both in 1.5.4 and earlier versions: */
9290# ifdef PNG_READ_16_TO_8_SUPPORTED
9291 png_set_strip_16(pp);
9292# else
9293 png_error(pp, "scale16 (16 to 8 bit conversion) not supported");
9294# endif
9295# endif
9296
9297 if (dp->expand16)
9298# ifdef PNG_READ_EXPAND_16_SUPPORTED
9299 png_set_expand_16(pp);
9300# else
9301 png_error(pp, "expand16 (8 to 16 bit conversion) not supported");
9302# endif
9303
9304 if (dp->do_background >= ALPHA_MODE_OFFSET)
9305 {
9306# ifdef PNG_READ_ALPHA_MODE_SUPPORTED
9307 {
9308 /* This tests the alpha mode handling, if supported. */
9309 int mode = dp->do_background - ALPHA_MODE_OFFSET;
9310
9311 /* The gamma value is the output gamma, and is in the standard,
9312 * non-inverted, representation. It provides a default for the PNG file
9313 * gamma, but since the file has a gAMA chunk this does not matter.
9314 */
9315 const double sg = dp->screen_gamma;
9316# ifndef PNG_FLOATING_POINT_SUPPORTED
9317 png_fixed_point g = fix(sg);
9318# endif
9319
9320# ifdef PNG_FLOATING_POINT_SUPPORTED
9321 png_set_alpha_mode(pp, mode, sg);
9322# else
9323 png_set_alpha_mode_fixed(pp, mode, g);
9324# endif
9325
9326 /* However, for the standard Porter-Duff algorithm the output defaults
9327 * to be linear, so if the test requires non-linear output it must be
9328 * corrected here.
9329 */
9330 if (mode == PNG_ALPHA_STANDARD && sg != 1)
9331 {
9332# ifdef PNG_FLOATING_POINT_SUPPORTED
9333 png_set_gamma(pp, sg, dp->file_gamma);
9334# else
9335 png_fixed_point f = fix(dp->file_gamma);
9336 png_set_gamma_fixed(pp, g, f);
9337# endif
9338 }
9339 }
9340# else
9341 png_error(pp, "alpha mode handling not supported");
9342# endif
9343 }
9344
9345 else
9346 {
9347 /* Set up gamma processing. */
9348# ifdef PNG_FLOATING_POINT_SUPPORTED
9349 png_set_gamma(pp, dp->screen_gamma, dp->file_gamma);
9350# else
9351 {
9352 png_fixed_point s = fix(dp->screen_gamma);
9353 png_fixed_point f = fix(dp->file_gamma);
9354 png_set_gamma_fixed(pp, s, f);
9355 }
9356# endif
9357
9358 if (dp->do_background)
9359 {
9360# ifdef PNG_READ_BACKGROUND_SUPPORTED
9361 /* NOTE: this assumes the caller provided the correct background gamma!
9362 */
9363 const double bg = dp->background_gamma;
9364# ifndef PNG_FLOATING_POINT_SUPPORTED
9365 png_fixed_point g = fix(bg);
9366# endif
9367
9368# ifdef PNG_FLOATING_POINT_SUPPORTED
9369 png_set_background(pp, &dp->background_color, dp->do_background,
9370 0/*need_expand*/, bg);
9371# else
9372 png_set_background_fixed(pp, &dp->background_color,
9373 dp->do_background, 0/*need_expand*/, g);
9374# endif
9375# else
9376 png_error(pp, "png_set_background not supported");
9377# endif
9378 }
9379 }
9380
9381 {
9382 int i = dp->this.use_update_info;
9383 /* Always do one call, even if use_update_info is 0. */
9384 do
9385 png_read_update_info(pp, pi);
9386 while (--i > 0);
9387 }
9388
9389 /* Now we may get a different cbRow: */
9390 standard_info_part2(&dp->this, pp, pi, 1 /*images*/);
9391}
9392
9393static void PNGCBAPI
9394gamma_info(png_structp pp, png_infop pi)
9395{
9396 gamma_info_imp(voidcast(gamma_display*, png_get_progressive_ptr(pp)), pp,
9397 pi);
9398}
9399
9400/* Validate a single component value - the routine gets the input and output
9401 * sample values as unscaled PNG component values along with a cache of all the
9402 * information required to validate the values.
9403 */
9404typedef struct validate_info
9405{
9406 png_const_structp pp;
9407 gamma_display *dp;
9408 png_byte sbit;
9409 int use_input_precision;
9410 int do_background;
9411 int scale16;
9412 unsigned int sbit_max;
9413 unsigned int isbit_shift;
9414 unsigned int outmax;
9415
9416 double gamma_correction; /* Overall correction required. */
9417 double file_inverse; /* Inverse of file gamma. */
9418 double screen_gamma;
9419 double screen_inverse; /* Inverse of screen gamma. */
9420
9421 double background_red; /* Linear background value, red or gray. */
9422 double background_green;
9423 double background_blue;
9424
9425 double maxabs;
9426 double maxpc;
9427 double maxcalc;
9428 double maxout;
9429 double maxout_total; /* Total including quantization error */
9430 double outlog;
9431 int outquant;
9432}
9433validate_info;
9434
9435static void
9436init_validate_info(validate_info *vi, gamma_display *dp, png_const_structp pp,
9437 int in_depth, int out_depth)
9438{
9439 unsigned int outmax = (1U<<out_depth)-1;
9440
9441 vi->pp = pp;
9442 vi->dp = dp;
9443
9444 if (dp->sbit > 0 && dp->sbit < in_depth)
9445 {
9446 vi->sbit = dp->sbit;
9447 vi->isbit_shift = in_depth - dp->sbit;
9448 }
9449
9450 else
9451 {
9452 vi->sbit = (png_byte)in_depth;
9453 vi->isbit_shift = 0;
9454 }
9455
9456 vi->sbit_max = (1U << vi->sbit)-1;
9457
9458 /* This mimics the libpng threshold test, '0' is used to prevent gamma
9459 * correction in the validation test.
9460 */
9461 vi->screen_gamma = dp->screen_gamma;
9462 if (fabs(vi->screen_gamma-1) < PNG_GAMMA_THRESHOLD)
9463 vi->screen_gamma = vi->screen_inverse = 0;
9464 else
9465 vi->screen_inverse = 1/vi->screen_gamma;
9466
9467 vi->use_input_precision = dp->use_input_precision;
9468 vi->outmax = outmax;
9469 vi->maxabs = abserr(dp->pm, in_depth, out_depth);
9470 vi->maxpc = pcerr(dp->pm, in_depth, out_depth);
9471 vi->maxcalc = calcerr(dp->pm, in_depth, out_depth);
9472 vi->maxout = outerr(dp->pm, in_depth, out_depth);
9473 vi->outquant = output_quantization_factor(dp->pm, in_depth, out_depth);
9474 vi->maxout_total = vi->maxout + vi->outquant * .5;
9475 vi->outlog = outlog(dp->pm, in_depth, out_depth);
9476
9477 if ((dp->this.colour_type & PNG_COLOR_MASK_ALPHA) != 0 ||
9478 (dp->this.colour_type == 3 && dp->this.is_transparent) ||
9479 ((dp->this.colour_type == 0 || dp->this.colour_type == 2) &&
9480 dp->this.has_tRNS))
9481 {
9482 vi->do_background = dp->do_background;
9483
9484 if (vi->do_background != 0)
9485 {
9486 const double bg_inverse = 1/dp->background_gamma;
9487 double r, g, b;
9488
9489 /* Caller must at least put the gray value into the red channel */
9490 r = dp->background_color.red; r /= outmax;
9491 g = dp->background_color.green; g /= outmax;
9492 b = dp->background_color.blue; b /= outmax;
9493
9494# if 0
9495 /* libpng doesn't do this optimization, if we do pngvalid will fail.
9496 */
9497 if (fabs(bg_inverse-1) >= PNG_GAMMA_THRESHOLD)
9498# endif
9499 {
9500 r = pow(r, bg_inverse);
9501 g = pow(g, bg_inverse);
9502 b = pow(b, bg_inverse);
9503 }
9504
9505 vi->background_red = r;
9506 vi->background_green = g;
9507 vi->background_blue = b;
9508 }
9509 }
9510 else /* Do not expect any background processing */
9511 vi->do_background = 0;
9512
9513 if (vi->do_background == 0)
9514 vi->background_red = vi->background_green = vi->background_blue = 0;
9515
9516 vi->gamma_correction = 1/(dp->file_gamma*dp->screen_gamma);
9517 if (fabs(vi->gamma_correction-1) < PNG_GAMMA_THRESHOLD)
9518 vi->gamma_correction = 0;
9519
9520 vi->file_inverse = 1/dp->file_gamma;
9521 if (fabs(vi->file_inverse-1) < PNG_GAMMA_THRESHOLD)
9522 vi->file_inverse = 0;
9523
9524 vi->scale16 = dp->scale16;
9525}
9526
9527/* This function handles composition of a single non-alpha component. The
9528 * argument is the input sample value, in the range 0..1, and the alpha value.
9529 * The result is the composed, linear, input sample. If alpha is less than zero
9530 * this is the alpha component and the function should not be called!
9531 */
9532static double
9533gamma_component_compose(int do_background, double input_sample, double alpha,
9534 double background, int *compose)
9535{
9536 switch (do_background)
9537 {
9538#ifdef PNG_READ_BACKGROUND_SUPPORTED
9539 case PNG_BACKGROUND_GAMMA_SCREEN:
9540 case PNG_BACKGROUND_GAMMA_FILE:
9541 case PNG_BACKGROUND_GAMMA_UNIQUE:
9542 /* Standard PNG background processing. */
9543 if (alpha < 1)
9544 {
9545 if (alpha > 0)
9546 {
9547 input_sample = input_sample * alpha + background * (1-alpha);
9548 if (compose != NULL)
9549 *compose = 1;
9550 }
9551
9552 else
9553 input_sample = background;
9554 }
9555 break;
9556#endif
9557
9558#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
9559 case ALPHA_MODE_OFFSET + PNG_ALPHA_STANDARD:
9560 case ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN:
9561 /* The components are premultiplied in either case and the output is
9562 * gamma encoded (to get standard Porter-Duff we expect the output
9563 * gamma to be set to 1.0!)
9564 */
9565 case ALPHA_MODE_OFFSET + PNG_ALPHA_OPTIMIZED:
9566 /* The optimization is that the partial-alpha entries are linear
9567 * while the opaque pixels are gamma encoded, but this only affects the
9568 * output encoding.
9569 */
9570 if (alpha < 1)
9571 {
9572 if (alpha > 0)
9573 {
9574 input_sample *= alpha;
9575 if (compose != NULL)
9576 *compose = 1;
9577 }
9578
9579 else
9580 input_sample = 0;
9581 }
9582 break;
9583#endif
9584
9585 default:
9586 /* Standard cases where no compositing is done (so the component
9587 * value is already correct.)
9588 */
9589 UNUSED(alpha)
9590 UNUSED(background)
9591 UNUSED(compose)
9592 break;
9593 }
9594
9595 return input_sample;
9596}
9597
9598/* This API returns the encoded *input* component, in the range 0..1 */
9599static double
9600gamma_component_validate(const char *name, const validate_info *vi,
9601 unsigned int id, unsigned int od,
9602 const double alpha /* <0 for the alpha channel itself */,
9603 const double background /* component background value */)
9604{
9605 unsigned int isbit = id >> vi->isbit_shift;
9606 unsigned int sbit_max = vi->sbit_max;
9607 unsigned int outmax = vi->outmax;
9608 int do_background = vi->do_background;
9609
9610 double i;
9611
9612 /* First check on the 'perfect' result obtained from the digitized input
9613 * value, id, and compare this against the actual digitized result, 'od'.
9614 * 'i' is the input result in the range 0..1:
9615 */
9616 i = isbit; i /= sbit_max;
9617
9618 /* Check for the fast route: if we don't do any background composition or if
9619 * this is the alpha channel ('alpha' < 0) or if the pixel is opaque then
9620 * just use the gamma_correction field to correct to the final output gamma.
9621 */
9622 if (alpha == 1 /* opaque pixel component */ || !do_background
9623#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
9624 || do_background == ALPHA_MODE_OFFSET + PNG_ALPHA_PNG
9625#endif
9626 || (alpha < 0 /* alpha channel */
9627#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
9628 && do_background != ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN
9629#endif
9630 ))
9631 {
9632 /* Then get the gamma corrected version of 'i' and compare to 'od', any
9633 * error less than .5 is insignificant - just quantization of the output
9634 * value to the nearest digital value (nevertheless the error is still
9635 * recorded - it's interesting ;-)
9636 */
9637 double encoded_sample = i;
9638 double encoded_error;
9639
9640 /* alpha less than 0 indicates the alpha channel, which is always linear
9641 */
9642 if (alpha >= 0 && vi->gamma_correction > 0)
9643 encoded_sample = pow(encoded_sample, vi->gamma_correction);
9644 encoded_sample *= outmax;
9645
9646 encoded_error = fabs(od-encoded_sample);
9647
9648 if (encoded_error > vi->dp->maxerrout)
9649 vi->dp->maxerrout = encoded_error;
9650
9651 if (encoded_error < vi->maxout_total && encoded_error < vi->outlog)
9652 return i;
9653 }
9654
9655 /* The slow route - attempt to do linear calculations. */
9656 /* There may be an error, or background processing is required, so calculate
9657 * the actual sample values - unencoded light intensity values. Note that in
9658 * practice these are not completely unencoded because they include a
9659 * 'viewing correction' to decrease or (normally) increase the perceptual
9660 * contrast of the image. There's nothing we can do about this - we don't
9661 * know what it is - so assume the unencoded value is perceptually linear.
9662 */
9663 {
9664 double input_sample = i; /* In range 0..1 */
9665 double output, error, encoded_sample, encoded_error;
9666 double es_lo, es_hi;
9667 int compose = 0; /* Set to one if composition done */
9668 int output_is_encoded; /* Set if encoded to screen gamma */
9669 int log_max_error = 1; /* Check maximum error values */
9670 png_const_charp pass = 0; /* Reason test passes (or 0 for fail) */
9671
9672 /* Convert to linear light (with the above caveat.) The alpha channel is
9673 * already linear.
9674 */
9675 if (alpha >= 0)
9676 {
9677 int tcompose;
9678
9679 if (vi->file_inverse > 0)
9680 input_sample = pow(input_sample, vi->file_inverse);
9681
9682 /* Handle the compose processing: */
9683 tcompose = 0;
9684 input_sample = gamma_component_compose(do_background, input_sample,
9685 alpha, background, &tcompose);
9686
9687 if (tcompose)
9688 compose = 1;
9689 }
9690
9691 /* And similarly for the output value, but we need to check the background
9692 * handling to linearize it correctly.
9693 */
9694 output = od;
9695 output /= outmax;
9696
9697 output_is_encoded = vi->screen_gamma > 0;
9698
9699 if (alpha < 0) /* The alpha channel */
9700 {
9701#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
9702 if (do_background != ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN)
9703#endif
9704 {
9705 /* In all other cases the output alpha channel is linear already,
9706 * don't log errors here, they are much larger in linear data.
9707 */
9708 output_is_encoded = 0;
9709 log_max_error = 0;
9710 }
9711 }
9712
9713#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
9714 else /* A component */
9715 {
9716 if (do_background == ALPHA_MODE_OFFSET + PNG_ALPHA_OPTIMIZED &&
9717 alpha < 1) /* the optimized case - linear output */
9718 {
9719 if (alpha > 0) log_max_error = 0;
9720 output_is_encoded = 0;
9721 }
9722 }
9723#endif
9724
9725 if (output_is_encoded)
9726 output = pow(output, vi->screen_gamma);
9727
9728 /* Calculate (or recalculate) the encoded_sample value and repeat the
9729 * check above (unnecessary if we took the fast route, but harmless.)
9730 */
9731 encoded_sample = input_sample;
9732 if (output_is_encoded)
9733 encoded_sample = pow(encoded_sample, vi->screen_inverse);
9734 encoded_sample *= outmax;
9735
9736 encoded_error = fabs(od-encoded_sample);
9737
9738 /* Don't log errors in the alpha channel, or the 'optimized' case,
9739 * neither are significant to the overall perception.
9740 */
9741 if (log_max_error && encoded_error > vi->dp->maxerrout)
9742 vi->dp->maxerrout = encoded_error;
9743
9744 if (encoded_error < vi->maxout_total)
9745 {
9746 if (encoded_error < vi->outlog)
9747 return i;
9748
9749 /* Test passed but error is bigger than the log limit, record why the
9750 * test passed:
9751 */
9752 pass = "less than maxout:\n";
9753 }
9754
9755 /* i: the original input value in the range 0..1
9756 *
9757 * pngvalid calculations:
9758 * input_sample: linear result; i linearized and composed, range 0..1
9759 * encoded_sample: encoded result; input_sample scaled to output bit depth
9760 *
9761 * libpng calculations:
9762 * output: linear result; od scaled to 0..1 and linearized
9763 * od: encoded result from libpng
9764 */
9765
9766 /* Now we have the numbers for real errors, both absolute values as as a
9767 * percentage of the correct value (output):
9768 */
9769 error = fabs(input_sample-output);
9770
9771 if (log_max_error && error > vi->dp->maxerrabs)
9772 vi->dp->maxerrabs = error;
9773
9774 /* The following is an attempt to ignore the tendency of quantization to
9775 * dominate the percentage errors for lower result values:
9776 */
9777 if (log_max_error && input_sample > .5)
9778 {
9779 double percentage_error = error/input_sample;
9780 if (percentage_error > vi->dp->maxerrpc)
9781 vi->dp->maxerrpc = percentage_error;
9782 }
9783
9784 /* Now calculate the digitization limits for 'encoded_sample' using the
9785 * 'max' values. Note that maxout is in the encoded space but maxpc and
9786 * maxabs are in linear light space.
9787 *
9788 * First find the maximum error in linear light space, range 0..1:
9789 */
9790 {
9791 double tmp = input_sample * vi->maxpc;
9792 if (tmp < vi->maxabs) tmp = vi->maxabs;
9793 /* If 'compose' is true the composition was done in linear space using
9794 * integer arithmetic. This introduces an extra error of +/- 0.5 (at
9795 * least) in the integer space used. 'maxcalc' records this, taking
9796 * into account the possibility that even for 16 bit output 8 bit space
9797 * may have been used.
9798 */
9799 if (compose && tmp < vi->maxcalc) tmp = vi->maxcalc;
9800
9801 /* The 'maxout' value refers to the encoded result, to compare with
9802 * this encode input_sample adjusted by the maximum error (tmp) above.
9803 */
9804 es_lo = encoded_sample - vi->maxout;
9805
9806 if (es_lo > 0 && input_sample-tmp > 0)
9807 {
9808 double low_value = input_sample-tmp;
9809 if (output_is_encoded)
9810 low_value = pow(low_value, vi->screen_inverse);
9811 low_value *= outmax;
9812 if (low_value < es_lo) es_lo = low_value;
9813
9814 /* Quantize this appropriately: */
9815 es_lo = ceil(es_lo / vi->outquant - .5) * vi->outquant;
9816 }
9817
9818 else
9819 es_lo = 0;
9820
9821 es_hi = encoded_sample + vi->maxout;
9822
9823 if (es_hi < outmax && input_sample+tmp < 1)
9824 {
9825 double high_value = input_sample+tmp;
9826 if (output_is_encoded)
9827 high_value = pow(high_value, vi->screen_inverse);
9828 high_value *= outmax;
9829 if (high_value > es_hi) es_hi = high_value;
9830
9831 es_hi = floor(es_hi / vi->outquant + .5) * vi->outquant;
9832 }
9833
9834 else
9835 es_hi = outmax;
9836 }
9837
9838 /* The primary test is that the final encoded value returned by the
9839 * library should be between the two limits (inclusive) that were
9840 * calculated above.
9841 */
9842 if (od >= es_lo && od <= es_hi)
9843 {
9844 /* The value passes, but we may need to log the information anyway. */
9845 if (encoded_error < vi->outlog)
9846 return i;
9847
9848 if (pass == 0)
9849 pass = "within digitization limits:\n";
9850 }
9851
9852 {
9853 /* There has been an error in processing, or we need to log this
9854 * value.
9855 */
9856 double is_lo, is_hi;
9857
9858 /* pass is set at this point if either of the tests above would have
9859 * passed. Don't do these additional tests here - just log the
9860 * original [es_lo..es_hi] values.
9861 */
9862 if (pass == 0 && vi->use_input_precision && vi->dp->sbit)
9863 {
9864 /* Ok, something is wrong - this actually happens in current libpng
9865 * 16-to-8 processing. Assume that the input value (id, adjusted
9866 * for sbit) can be anywhere between value-.5 and value+.5 - quite a
9867 * large range if sbit is low.
9868 *
9869 * NOTE: at present because the libpng gamma table stuff has been
9870 * changed to use a rounding algorithm to correct errors in 8-bit
9871 * calculations the precise sbit calculation (a shift) has been
9872 * lost. This can result in up to a +/-1 error in the presence of
9873 * an sbit less than the bit depth.
9874 */
9875# if PNG_LIBPNG_VER != 10700
9876# define SBIT_ERROR .5
9877# else
9878# define SBIT_ERROR 1.
9879# endif
9880 double tmp = (isbit - SBIT_ERROR)/sbit_max;
9881
9882 if (tmp <= 0)
9883 tmp = 0;
9884
9885 else if (alpha >= 0 && vi->file_inverse > 0 && tmp < 1)
9886 tmp = pow(tmp, vi->file_inverse);
9887
9888 tmp = gamma_component_compose(do_background, tmp, alpha, background,
9889 NULL);
9890
9891 if (output_is_encoded && tmp > 0 && tmp < 1)
9892 tmp = pow(tmp, vi->screen_inverse);
9893
9894 is_lo = ceil(outmax * tmp - vi->maxout_total);
9895
9896 if (is_lo < 0)
9897 is_lo = 0;
9898
9899 tmp = (isbit + SBIT_ERROR)/sbit_max;
9900
9901 if (tmp >= 1)
9902 tmp = 1;
9903
9904 else if (alpha >= 0 && vi->file_inverse > 0 && tmp < 1)
9905 tmp = pow(tmp, vi->file_inverse);
9906
9907 tmp = gamma_component_compose(do_background, tmp, alpha, background,
9908 NULL);
9909
9910 if (output_is_encoded && tmp > 0 && tmp < 1)
9911 tmp = pow(tmp, vi->screen_inverse);
9912
9913 is_hi = floor(outmax * tmp + vi->maxout_total);
9914
9915 if (is_hi > outmax)
9916 is_hi = outmax;
9917
9918 if (!(od < is_lo || od > is_hi))
9919 {
9920 if (encoded_error < vi->outlog)
9921 return i;
9922
9923 pass = "within input precision limits:\n";
9924 }
9925
9926 /* One last chance. If this is an alpha channel and the 16to8
9927 * option has been used and 'inaccurate' scaling is used then the
9928 * bit reduction is obtained by simply using the top 8 bits of the
9929 * value.
9930 *
9931 * This is only done for older libpng versions when the 'inaccurate'
9932 * (chop) method of scaling was used.
9933 */
9934# ifndef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED
9935# if PNG_LIBPNG_VER < 10504
9936 /* This may be required for other components in the future,
9937 * but at present the presence of gamma correction effectively
9938 * prevents the errors in the component scaling (I don't quite
9939 * understand why, but since it's better this way I care not
9940 * to ask, JB 20110419.)
9941 */
9942 if (pass == 0 && alpha < 0 && vi->scale16 && vi->sbit > 8 &&
9943 vi->sbit + vi->isbit_shift == 16)
9944 {
9945 tmp = ((id >> 8) - .5)/255;
9946
9947 if (tmp > 0)
9948 {
9949 is_lo = ceil(outmax * tmp - vi->maxout_total);
9950 if (is_lo < 0) is_lo = 0;
9951 }
9952
9953 else
9954 is_lo = 0;
9955
9956 tmp = ((id >> 8) + .5)/255;
9957
9958 if (tmp < 1)
9959 {
9960 is_hi = floor(outmax * tmp + vi->maxout_total);
9961 if (is_hi > outmax) is_hi = outmax;
9962 }
9963
9964 else
9965 is_hi = outmax;
9966
9967 if (!(od < is_lo || od > is_hi))
9968 {
9969 if (encoded_error < vi->outlog)
9970 return i;
9971
9972 pass = "within 8 bit limits:\n";
9973 }
9974 }
9975# endif
9976# endif
9977 }
9978 else /* !use_input_precision */
9979 is_lo = es_lo, is_hi = es_hi;
9980
9981 /* Attempt to output a meaningful error/warning message: the message
9982 * output depends on the background/composite operation being performed
9983 * because this changes what parameters were actually used above.
9984 */
9985 {
9986 size_t pos = 0;
9987 /* Need either 1/255 or 1/65535 precision here; 3 or 6 decimal
9988 * places. Just use outmax to work out which.
9989 */
9990 int precision = (outmax >= 1000 ? 6 : 3);
9991 int use_input=1, use_background=0, do_compose=0;
9992 char msg[256];
9993
9994 if (pass != 0)
9995 pos = safecat(msg, sizeof msg, pos, "\n\t");
9996
9997 /* Set up the various flags, the output_is_encoded flag above
9998 * is also used below. do_compose is just a double check.
9999 */
10000 switch (do_background)
10001 {
10002# ifdef PNG_READ_BACKGROUND_SUPPORTED
10003 case PNG_BACKGROUND_GAMMA_SCREEN:
10004 case PNG_BACKGROUND_GAMMA_FILE:
10005 case PNG_BACKGROUND_GAMMA_UNIQUE:
10006 use_background = (alpha >= 0 && alpha < 1);
10007# endif
10008# ifdef PNG_READ_ALPHA_MODE_SUPPORTED
10009 /* FALLTHROUGH */
10010 case ALPHA_MODE_OFFSET + PNG_ALPHA_STANDARD:
10011 case ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN:
10012 case ALPHA_MODE_OFFSET + PNG_ALPHA_OPTIMIZED:
10013# endif /* ALPHA_MODE_SUPPORTED */
10014# if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
10015 (defined PNG_READ_ALPHA_MODE_SUPPORTED)
10016 do_compose = (alpha > 0 && alpha < 1);
10017 use_input = (alpha != 0);
10018 break;
10019# endif
10020
10021 default:
10022 break;
10023 }
10024
10025 /* Check the 'compose' flag */
10026 if (compose != do_compose)
10027 png_error(vi->pp, "internal error (compose)");
10028
10029 /* 'name' is the component name */
10030 pos = safecat(msg, sizeof msg, pos, name);
10031 pos = safecat(msg, sizeof msg, pos, "(");
10032 pos = safecatn(msg, sizeof msg, pos, id);
10033 if (use_input || pass != 0/*logging*/)
10034 {
10035 if (isbit != id)
10036 {
10037 /* sBIT has reduced the precision of the input: */
10038 pos = safecat(msg, sizeof msg, pos, ", sbit(");
10039 pos = safecatn(msg, sizeof msg, pos, vi->sbit);
10040 pos = safecat(msg, sizeof msg, pos, "): ");
10041 pos = safecatn(msg, sizeof msg, pos, isbit);
10042 }
10043 pos = safecat(msg, sizeof msg, pos, "/");
10044 /* The output is either "id/max" or "id sbit(sbit): isbit/max" */
10045 pos = safecatn(msg, sizeof msg, pos, vi->sbit_max);
10046 }
10047 pos = safecat(msg, sizeof msg, pos, ")");
10048
10049 /* A component may have been multiplied (in linear space) by the
10050 * alpha value, 'compose' says whether this is relevant.
10051 */
10052 if (compose || pass != 0)
10053 {
10054 /* If any form of composition is being done report our
10055 * calculated linear value here (the code above doesn't record
10056 * the input value before composition is performed, so what
10057 * gets reported is the value after composition.)
10058 */
10059 if (use_input || pass != 0)
10060 {
10061 if (vi->file_inverse > 0)
10062 {
10063 pos = safecat(msg, sizeof msg, pos, "^");
10064 pos = safecatd(msg, sizeof msg, pos, vi->file_inverse, 2);
10065 }
10066
10067 else
10068 pos = safecat(msg, sizeof msg, pos, "[linear]");
10069
10070 pos = safecat(msg, sizeof msg, pos, "*(alpha)");
10071 pos = safecatd(msg, sizeof msg, pos, alpha, precision);
10072 }
10073
10074 /* Now record the *linear* background value if it was used
10075 * (this function is not passed the original, non-linear,
10076 * value but it is contained in the test name.)
10077 */
10078 if (use_background)
10079 {
10080 pos = safecat(msg, sizeof msg, pos, use_input ? "+" : " ");
10081 pos = safecat(msg, sizeof msg, pos, "(background)");
10082 pos = safecatd(msg, sizeof msg, pos, background, precision);
10083 pos = safecat(msg, sizeof msg, pos, "*");
10084 pos = safecatd(msg, sizeof msg, pos, 1-alpha, precision);
10085 }
10086 }
10087
10088 /* Report the calculated value (input_sample) and the linearized
10089 * libpng value (output) unless this is just a component gamma
10090 * correction.
10091 */
10092 if (compose || alpha < 0 || pass != 0)
10093 {
10094 pos = safecat(msg, sizeof msg, pos,
10095 pass != 0 ? " =\n\t" : " = ");
10096 pos = safecatd(msg, sizeof msg, pos, input_sample, precision);
10097 pos = safecat(msg, sizeof msg, pos, " (libpng: ");
10098 pos = safecatd(msg, sizeof msg, pos, output, precision);
10099 pos = safecat(msg, sizeof msg, pos, ")");
10100
10101 /* Finally report the output gamma encoding, if any. */
10102 if (output_is_encoded)
10103 {
10104 pos = safecat(msg, sizeof msg, pos, " ^");
10105 pos = safecatd(msg, sizeof msg, pos, vi->screen_inverse, 2);
10106 pos = safecat(msg, sizeof msg, pos, "(to screen) =");
10107 }
10108
10109 else
10110 pos = safecat(msg, sizeof msg, pos, " [screen is linear] =");
10111 }
10112
10113 if ((!compose && alpha >= 0) || pass != 0)
10114 {
10115 if (pass != 0) /* logging */
10116 pos = safecat(msg, sizeof msg, pos, "\n\t[overall:");
10117
10118 /* This is the non-composition case, the internal linear
10119 * values are irrelevant (though the log below will reveal
10120 * them.) Output a much shorter warning/error message and report
10121 * the overall gamma correction.
10122 */
10123 if (vi->gamma_correction > 0)
10124 {
10125 pos = safecat(msg, sizeof msg, pos, " ^");
10126 pos = safecatd(msg, sizeof msg, pos, vi->gamma_correction, 2);
10127 pos = safecat(msg, sizeof msg, pos, "(gamma correction) =");
10128 }
10129
10130 else
10131 pos = safecat(msg, sizeof msg, pos,
10132 " [no gamma correction] =");
10133
10134 if (pass != 0)
10135 pos = safecat(msg, sizeof msg, pos, "]");
10136 }
10137
10138 /* This is our calculated encoded_sample which should (but does
10139 * not) match od:
10140 */
10141 pos = safecat(msg, sizeof msg, pos, pass != 0 ? "\n\t" : " ");
10142 pos = safecatd(msg, sizeof msg, pos, is_lo, 1);
10143 pos = safecat(msg, sizeof msg, pos, " < ");
10144 pos = safecatd(msg, sizeof msg, pos, encoded_sample, 1);
10145 pos = safecat(msg, sizeof msg, pos, " (libpng: ");
10146 pos = safecatn(msg, sizeof msg, pos, od);
10147 pos = safecat(msg, sizeof msg, pos, ")");
10148 pos = safecat(msg, sizeof msg, pos, "/");
10149 pos = safecatn(msg, sizeof msg, pos, outmax);
10150 pos = safecat(msg, sizeof msg, pos, " < ");
10151 pos = safecatd(msg, sizeof msg, pos, is_hi, 1);
10152
10153 if (pass == 0) /* The error condition */
10154 {
10155# ifdef PNG_WARNINGS_SUPPORTED
10156 png_warning(vi->pp, msg);
10157# else
10158 store_warning(vi->pp, msg);
10159# endif
10160 }
10161
10162 else /* logging this value */
10163 store_verbose(&vi->dp->pm->this, vi->pp, pass, msg);
10164 }
10165 }
10166 }
10167
10168 return i;
10169}
10170
10171static void
10172gamma_image_validate(gamma_display *dp, png_const_structp pp,
10173 png_infop pi)
10174{
10175 /* Get some constants derived from the input and output file formats: */
10176 const png_store* const ps = dp->this.ps;
10177 png_byte in_ct = dp->this.colour_type;
10178 png_byte in_bd = dp->this.bit_depth;
10179 png_uint_32 w = dp->this.w;
10180 png_uint_32 h = dp->this.h;
10181 const size_t cbRow = dp->this.cbRow;
10182 png_byte out_ct = png_get_color_type(pp, pi);
10183 png_byte out_bd = png_get_bit_depth(pp, pi);
10184
10185 /* There are three sources of error, firstly the quantization in the
10186 * file encoding, determined by sbit and/or the file depth, secondly
10187 * the output (screen) gamma and thirdly the output file encoding.
10188 *
10189 * Since this API receives the screen and file gamma in double
10190 * precision it is possible to calculate an exact answer given an input
10191 * pixel value. Therefore we assume that the *input* value is exact -
10192 * sample/maxsample - calculate the corresponding gamma corrected
10193 * output to the limits of double precision arithmetic and compare with
10194 * what libpng returns.
10195 *
10196 * Since the library must quantize the output to 8 or 16 bits there is
10197 * a fundamental limit on the accuracy of the output of +/-.5 - this
10198 * quantization limit is included in addition to the other limits
10199 * specified by the parameters to the API. (Effectively, add .5
10200 * everywhere.)
10201 *
10202 * The behavior of the 'sbit' parameter is defined by section 12.5
10203 * (sample depth scaling) of the PNG spec. That section forces the
10204 * decoder to assume that the PNG values have been scaled if sBIT is
10205 * present:
10206 *
10207 * png-sample = floor( input-sample * (max-out/max-in) + .5);
10208 *
10209 * This means that only a subset of the possible PNG values should
10210 * appear in the input. However, the spec allows the encoder to use a
10211 * variety of approximations to the above and doesn't require any
10212 * restriction of the values produced.
10213 *
10214 * Nevertheless the spec requires that the upper 'sBIT' bits of the
10215 * value stored in a PNG file be the original sample bits.
10216 * Consequently the code below simply scales the top sbit bits by
10217 * (1<<sbit)-1 to obtain an original sample value.
10218 *
10219 * Because there is limited precision in the input it is arguable that
10220 * an acceptable result is any valid result from input-.5 to input+.5.
10221 * The basic tests below do not do this, however if 'use_input_precision'
10222 * is set a subsequent test is performed above.
10223 */
10224 unsigned int samples_per_pixel = (out_ct & 2U) ? 3U : 1U;
10225 int processing;
10226 png_uint_32 y;
10227 const store_palette_entry *in_palette = dp->this.palette;
10228 int in_is_transparent = dp->this.is_transparent;
10229 int process_tRNS;
10230 int out_npalette = -1;
10231 int out_is_transparent = 0; /* Just refers to the palette case */
10232 store_palette out_palette;
10233 validate_info vi;
10234
10235 /* Check for row overwrite errors */
10236 store_image_check(dp->this.ps, pp, 0);
10237
10238 /* Supply the input and output sample depths here - 8 for an indexed image,
10239 * otherwise the bit depth.
10240 */
10241 init_validate_info(&vi, dp, pp, in_ct==3?8:in_bd, out_ct==3?8:out_bd);
10242
10243 processing = (vi.gamma_correction > 0 && !dp->threshold_test)
10244 || in_bd != out_bd || in_ct != out_ct || vi.do_background;
10245 process_tRNS = dp->this.has_tRNS && vi.do_background;
10246
10247 /* TODO: FIX THIS: MAJOR BUG! If the transformations all happen inside
10248 * the palette there is no way of finding out, because libpng fails to
10249 * update the palette on png_read_update_info. Indeed, libpng doesn't
10250 * even do the required work until much later, when it doesn't have any
10251 * info pointer. Oops. For the moment 'processing' is turned off if
10252 * out_ct is palette.
10253 */
10254 if (in_ct == 3 && out_ct == 3)
10255 processing = 0;
10256
10257 if (processing && out_ct == 3)
10258 out_is_transparent = read_palette(out_palette, &out_npalette, pp, pi);
10259
10260 for (y=0; y<h; ++y)
10261 {
10262 png_const_bytep pRow = store_image_row(ps, pp, 0, y);
10263 png_byte std[STANDARD_ROWMAX];
10264
10265 transform_row(pp, std, in_ct, in_bd, y);
10266
10267 if (processing)
10268 {
10269 unsigned int x;
10270
10271 for (x=0; x<w; ++x)
10272 {
10273 double alpha = 1; /* serves as a flag value */
10274
10275 /* Record the palette index for index images. */
10276 unsigned int in_index =
10277 in_ct == 3 ? sample(std, 3, in_bd, x, 0, 0, 0) : 256;
10278 unsigned int out_index =
10279 out_ct == 3 ? sample(std, 3, out_bd, x, 0, 0, 0) : 256;
10280
10281 /* Handle input alpha - png_set_background will cause the output
10282 * alpha to disappear so there is nothing to check.
10283 */
10284 if ((in_ct & PNG_COLOR_MASK_ALPHA) != 0 ||
10285 (in_ct == 3 && in_is_transparent))
10286 {
10287 unsigned int input_alpha = in_ct == 3 ?
10288 dp->this.palette[in_index].alpha :
10289 sample(std, in_ct, in_bd, x, samples_per_pixel, 0, 0);
10290
10291 unsigned int output_alpha = 65536 /* as a flag value */;
10292
10293 if (out_ct == 3)
10294 {
10295 if (out_is_transparent)
10296 output_alpha = out_palette[out_index].alpha;
10297 }
10298
10299 else if ((out_ct & PNG_COLOR_MASK_ALPHA) != 0)
10300 output_alpha = sample(pRow, out_ct, out_bd, x,
10301 samples_per_pixel, 0, 0);
10302
10303 if (output_alpha != 65536)
10304 alpha = gamma_component_validate("alpha", &vi, input_alpha,
10305 output_alpha, -1/*alpha*/, 0/*background*/);
10306
10307 else /* no alpha in output */
10308 {
10309 /* This is a copy of the calculation of 'i' above in order to
10310 * have the alpha value to use in the background calculation.
10311 */
10312 alpha = input_alpha >> vi.isbit_shift;
10313 alpha /= vi.sbit_max;
10314 }
10315 }
10316
10317 else if (process_tRNS)
10318 {
10319 /* alpha needs to be set appropriately for this pixel, it is
10320 * currently 1 and needs to be 0 for an input pixel which matches
10321 * the values in tRNS.
10322 */
10323 switch (in_ct)
10324 {
10325 case 0: /* gray */
10326 if (sample(std, in_ct, in_bd, x, 0, 0, 0) ==
10327 dp->this.transparent.red)
10328 alpha = 0;
10329 break;
10330
10331 case 2: /* RGB */
10332 if (sample(std, in_ct, in_bd, x, 0, 0, 0) ==
10333 dp->this.transparent.red &&
10334 sample(std, in_ct, in_bd, x, 1, 0, 0) ==
10335 dp->this.transparent.green &&
10336 sample(std, in_ct, in_bd, x, 2, 0, 0) ==
10337 dp->this.transparent.blue)
10338 alpha = 0;
10339 break;
10340
10341 default:
10342 break;
10343 }
10344 }
10345
10346 /* Handle grayscale or RGB components. */
10347 if ((in_ct & PNG_COLOR_MASK_COLOR) == 0) /* grayscale */
10348 (void)gamma_component_validate("gray", &vi,
10349 sample(std, in_ct, in_bd, x, 0, 0, 0),
10350 sample(pRow, out_ct, out_bd, x, 0, 0, 0),
10351 alpha/*component*/, vi.background_red);
10352 else /* RGB or palette */
10353 {
10354 (void)gamma_component_validate("red", &vi,
10355 in_ct == 3 ? in_palette[in_index].red :
10356 sample(std, in_ct, in_bd, x, 0, 0, 0),
10357 out_ct == 3 ? out_palette[out_index].red :
10358 sample(pRow, out_ct, out_bd, x, 0, 0, 0),
10359 alpha/*component*/, vi.background_red);
10360
10361 (void)gamma_component_validate("green", &vi,
10362 in_ct == 3 ? in_palette[in_index].green :
10363 sample(std, in_ct, in_bd, x, 1, 0, 0),
10364 out_ct == 3 ? out_palette[out_index].green :
10365 sample(pRow, out_ct, out_bd, x, 1, 0, 0),
10366 alpha/*component*/, vi.background_green);
10367
10368 (void)gamma_component_validate("blue", &vi,
10369 in_ct == 3 ? in_palette[in_index].blue :
10370 sample(std, in_ct, in_bd, x, 2, 0, 0),
10371 out_ct == 3 ? out_palette[out_index].blue :
10372 sample(pRow, out_ct, out_bd, x, 2, 0, 0),
10373 alpha/*component*/, vi.background_blue);
10374 }
10375 }
10376 }
10377
10378 else if (memcmp(std, pRow, cbRow) != 0)
10379 {
10380 char msg[64];
10381
10382 /* No transform is expected on the threshold tests. */
10383 sprintf(msg, "gamma: below threshold row %lu changed",
10384 (unsigned long)y);
10385
10386 png_error(pp, msg);
10387 }
10388 } /* row (y) loop */
10389
10390 dp->this.ps->validated = 1;
10391}
10392
10393static void PNGCBAPI
10394gamma_end(png_structp ppIn, png_infop pi)
10395{
10396 png_const_structp pp = ppIn;
10397 gamma_display *dp = voidcast(gamma_display*, png_get_progressive_ptr(pp));
10398
10399 if (!dp->this.speed)
10400 gamma_image_validate(dp, pp, pi);
10401 else
10402 dp->this.ps->validated = 1;
10403}
10404
10405/* A single test run checking a gamma transformation.
10406 *
10407 * maxabs: maximum absolute error as a fraction
10408 * maxout: maximum output error in the output units
10409 * maxpc: maximum percentage error (as a percentage)
10410 */
10411static void
10412gamma_test(png_modifier *pmIn, png_byte colour_typeIn,
10413 png_byte bit_depthIn, int palette_numberIn,
10414 int interlace_typeIn,
10415 const double file_gammaIn, const double screen_gammaIn,
10416 png_byte sbitIn, int threshold_testIn,
10417 const char *name,
10418 int use_input_precisionIn, int scale16In,
10419 int expand16In, int do_backgroundIn,
10420 const png_color_16 *bkgd_colorIn, double bkgd_gammaIn)
10421{
10422 gamma_display d;
10423 context(&pmIn->this, fault);
10424
10425 gamma_display_init(&d, pmIn, FILEID(colour_typeIn, bit_depthIn,
10426 palette_numberIn, interlace_typeIn, 0, 0, 0),
10427 file_gammaIn, screen_gammaIn, sbitIn,
10428 threshold_testIn, use_input_precisionIn, scale16In,
10429 expand16In, do_backgroundIn, bkgd_colorIn, bkgd_gammaIn);
10430
10431 Try
10432 {
10433 png_structp pp;
10434 png_infop pi;
10435 gama_modification gama_mod;
10436 srgb_modification srgb_mod;
10437 sbit_modification sbit_mod;
10438
10439 /* For the moment don't use the png_modifier support here. */
10440 d.pm->encoding_counter = 0;
10441 modifier_set_encoding(d.pm); /* Just resets everything */
10442 d.pm->current_gamma = d.file_gamma;
10443
10444 /* Make an appropriate modifier to set the PNG file gamma to the
10445 * given gamma value and the sBIT chunk to the given precision.
10446 */
10447 d.pm->modifications = NULL;
10448 gama_modification_init(&gama_mod, d.pm, d.file_gamma);
10449 srgb_modification_init(&srgb_mod, d.pm, 127 /*delete*/);
10450 if (d.sbit > 0)
10451 sbit_modification_init(&sbit_mod, d.pm, d.sbit);
10452
10453 modification_reset(d.pm->modifications);
10454
10455 /* Get a png_struct for reading the image. */
10456 pp = set_modifier_for_read(d.pm, &pi, d.this.id, name);
10457 standard_palette_init(&d.this);
10458
10459 /* Introduce the correct read function. */
10460 if (d.pm->this.progressive)
10461 {
10462 /* Share the row function with the standard implementation. */
10463 png_set_progressive_read_fn(pp, &d, gamma_info, progressive_row,
10464 gamma_end);
10465
10466 /* Now feed data into the reader until we reach the end: */
10467 modifier_progressive_read(d.pm, pp, pi);
10468 }
10469 else
10470 {
10471 /* modifier_read expects a png_modifier* */
10472 png_set_read_fn(pp, d.pm, modifier_read);
10473
10474 /* Check the header values: */
10475 png_read_info(pp, pi);
10476
10477 /* Process the 'info' requirements. Only one image is generated */
10478 gamma_info_imp(&d, pp, pi);
10479
10480 sequential_row(&d.this, pp, pi, -1, 0);
10481
10482 if (!d.this.speed)
10483 gamma_image_validate(&d, pp, pi);
10484 else
10485 d.this.ps->validated = 1;
10486 }
10487
10488 modifier_reset(d.pm);
10489
10490 if (d.pm->log && !d.threshold_test && !d.this.speed)
10491 fprintf(stderr, "%d bit %s %s: max error %f (%.2g, %2g%%)\n",
10492 d.this.bit_depth, colour_types[d.this.colour_type], name,
10493 d.maxerrout, d.maxerrabs, 100*d.maxerrpc);
10494
10495 /* Log the summary values too. */
10496 if (d.this.colour_type == 0 || d.this.colour_type == 4)
10497 {
10498 switch (d.this.bit_depth)
10499 {
10500 case 1:
10501 break;
10502
10503 case 2:
10504 if (d.maxerrout > d.pm->error_gray_2)
10505 d.pm->error_gray_2 = d.maxerrout;
10506
10507 break;
10508
10509 case 4:
10510 if (d.maxerrout > d.pm->error_gray_4)
10511 d.pm->error_gray_4 = d.maxerrout;
10512
10513 break;
10514
10515 case 8:
10516 if (d.maxerrout > d.pm->error_gray_8)
10517 d.pm->error_gray_8 = d.maxerrout;
10518
10519 break;
10520
10521 case 16:
10522 if (d.maxerrout > d.pm->error_gray_16)
10523 d.pm->error_gray_16 = d.maxerrout;
10524
10525 break;
10526
10527 default:
10528 png_error(pp, "bad bit depth (internal: 1)");
10529 }
10530 }
10531
10532 else if (d.this.colour_type == 2 || d.this.colour_type == 6)
10533 {
10534 switch (d.this.bit_depth)
10535 {
10536 case 8:
10537
10538 if (d.maxerrout > d.pm->error_color_8)
10539 d.pm->error_color_8 = d.maxerrout;
10540
10541 break;
10542
10543 case 16:
10544
10545 if (d.maxerrout > d.pm->error_color_16)
10546 d.pm->error_color_16 = d.maxerrout;
10547
10548 break;
10549
10550 default:
10551 png_error(pp, "bad bit depth (internal: 2)");
10552 }
10553 }
10554
10555 else if (d.this.colour_type == 3)
10556 {
10557 if (d.maxerrout > d.pm->error_indexed)
10558 d.pm->error_indexed = d.maxerrout;
10559 }
10560 }
10561
10562 Catch(fault)
10563 modifier_reset(voidcast(png_modifier*,(void*)fault));
10564}
10565
10566static void gamma_threshold_test(png_modifier *pm, png_byte colour_type,
10567 png_byte bit_depth, int interlace_type, double file_gamma,
10568 double screen_gamma)
10569{
10570 size_t pos = 0;
10571 char name[64];
10572 pos = safecat(name, sizeof name, pos, "threshold ");
10573 pos = safecatd(name, sizeof name, pos, file_gamma, 3);
10574 pos = safecat(name, sizeof name, pos, "/");
10575 pos = safecatd(name, sizeof name, pos, screen_gamma, 3);
10576
10577 (void)gamma_test(pm, colour_type, bit_depth, 0/*palette*/, interlace_type,
10578 file_gamma, screen_gamma, 0/*sBIT*/, 1/*threshold test*/, name,
10579 0 /*no input precision*/,
10580 0 /*no scale16*/, 0 /*no expand16*/, 0 /*no background*/, 0 /*hence*/,
10581 0 /*no background gamma*/);
10582}
10583
10584static void
10585perform_gamma_threshold_tests(png_modifier *pm)
10586{
10587 png_byte colour_type = 0;
10588 png_byte bit_depth = 0;
10589 unsigned int palette_number = 0;
10590
10591 /* Don't test more than one instance of each palette - it's pointless, in
10592 * fact this test is somewhat excessive since libpng doesn't make this
10593 * decision based on colour type or bit depth!
10594 *
10595 * CHANGED: now test two palettes and, as a side effect, images with and
10596 * without tRNS.
10597 */
10598 while (next_format(&colour_type, &bit_depth, &palette_number,
10599 pm->test_lbg_gamma_threshold, pm->test_tRNS))
10600 if (palette_number < 2)
10601 {
10602 double test_gamma = 1.0;
10603 while (test_gamma >= .4)
10604 {
10605 /* There's little point testing the interlacing vs non-interlacing,
10606 * but this can be set from the command line.
10607 */
10608 gamma_threshold_test(pm, colour_type, bit_depth, pm->interlace_type,
10609 test_gamma, 1/test_gamma);
10610 test_gamma *= .95;
10611 }
10612
10613 /* And a special test for sRGB */
10614 gamma_threshold_test(pm, colour_type, bit_depth, pm->interlace_type,
10615 .45455, 2.2);
10616
10617 if (fail(pm))
10618 return;
10619 }
10620}
10621
10622static void gamma_transform_test(png_modifier *pm,
10623 png_byte colour_type, png_byte bit_depth,
10624 int palette_number,
10625 int interlace_type, const double file_gamma,
10626 const double screen_gamma, png_byte sbit,
10627 int use_input_precision, int scale16)
10628{
10629 size_t pos = 0;
10630 char name[64];
10631
10632 if (sbit != bit_depth && sbit != 0)
10633 {
10634 pos = safecat(name, sizeof name, pos, "sbit(");
10635 pos = safecatn(name, sizeof name, pos, sbit);
10636 pos = safecat(name, sizeof name, pos, ") ");
10637 }
10638
10639 else
10640 pos = safecat(name, sizeof name, pos, "gamma ");
10641
10642 if (scale16)
10643 pos = safecat(name, sizeof name, pos, "16to8 ");
10644
10645 pos = safecatd(name, sizeof name, pos, file_gamma, 3);
10646 pos = safecat(name, sizeof name, pos, "->");
10647 pos = safecatd(name, sizeof name, pos, screen_gamma, 3);
10648
10649 gamma_test(pm, colour_type, bit_depth, palette_number, interlace_type,
10650 file_gamma, screen_gamma, sbit, 0, name, use_input_precision,
10651 scale16, pm->test_gamma_expand16, 0 , 0, 0);
10652}
10653
10654static void perform_gamma_transform_tests(png_modifier *pm)
10655{
10656 png_byte colour_type = 0;
10657 png_byte bit_depth = 0;
10658 unsigned int palette_number = 0;
10659
10660 while (next_format(&colour_type, &bit_depth, &palette_number,
10661 pm->test_lbg_gamma_transform, pm->test_tRNS))
10662 {
10663 unsigned int i, j;
10664
10665 for (i=0; i<pm->ngamma_tests; ++i)
10666 {
10667 for (j=0; j<pm->ngamma_tests; ++j)
10668 {
10669 if (i != j)
10670 {
10671 gamma_transform_test(pm, colour_type, bit_depth, palette_number,
10672 pm->interlace_type, 1/pm->gammas[i], pm->gammas[j],
10673 0/*sBIT*/, pm->use_input_precision, 0/*do not scale16*/);
10674
10675 if (fail(pm))
10676 return;
10677 }
10678 }
10679 }
10680 }
10681}
10682
10683static void perform_gamma_sbit_tests(png_modifier *pm)
10684{
10685 png_byte sbit;
10686
10687 /* The only interesting cases are colour and grayscale, alpha is ignored here
10688 * for overall speed. Only bit depths where sbit is less than the bit depth
10689 * are tested.
10690 */
10691 for (sbit=pm->sbitlow; sbit<(1<<READ_BDHI); ++sbit)
10692 {
10693 png_byte colour_type = 0, bit_depth = 0;
10694 unsigned int npalette = 0;
10695
10696 while (next_format(&colour_type, &bit_depth, &npalette,
10697 pm->test_lbg_gamma_sbit, pm->test_tRNS))
10698 if ((colour_type & PNG_COLOR_MASK_ALPHA) == 0 &&
10699 ((colour_type == 3 && sbit < 8) ||
10700 (colour_type != 3 && sbit < bit_depth)))
10701 {
10702 unsigned int i;
10703
10704 for (i=0; i<pm->ngamma_tests; ++i)
10705 {
10706 unsigned int j;
10707
10708 for (j=0; j<pm->ngamma_tests; ++j)
10709 {
10710 if (i != j)
10711 {
10712 gamma_transform_test(pm, colour_type, bit_depth, npalette,
10713 pm->interlace_type, 1/pm->gammas[i], pm->gammas[j],
10714 sbit, pm->use_input_precision_sbit, 0 /*scale16*/);
10715
10716 if (fail(pm))
10717 return;
10718 }
10719 }
10720 }
10721 }
10722 }
10723}
10724
10725/* Note that this requires a 16 bit source image but produces 8 bit output, so
10726 * we only need the 16bit write support, but the 16 bit images are only
10727 * generated if DO_16BIT is defined.
10728 */
10729#ifdef DO_16BIT
10730static void perform_gamma_scale16_tests(png_modifier *pm)
10731{
10732# ifndef PNG_MAX_GAMMA_8
10733# define PNG_MAX_GAMMA_8 11
10734# endif
10735# if defined PNG_MAX_GAMMA_8 || PNG_LIBPNG_VER != 10700
10736# define SBIT_16_TO_8 PNG_MAX_GAMMA_8
10737# else
10738# define SBIT_16_TO_8 16
10739# endif
10740 /* Include the alpha cases here. Note that sbit matches the internal value
10741 * used by the library - otherwise we will get spurious errors from the
10742 * internal sbit style approximation.
10743 *
10744 * The threshold test is here because otherwise the 16 to 8 conversion will
10745 * proceed *without* gamma correction, and the tests above will fail (but not
10746 * by much) - this could be fixed, it only appears with the -g option.
10747 */
10748 unsigned int i, j;
10749 for (i=0; i<pm->ngamma_tests; ++i)
10750 {
10751 for (j=0; j<pm->ngamma_tests; ++j)
10752 {
10753 if (i != j &&
10754 fabs(pm->gammas[j]/pm->gammas[i]-1) >= PNG_GAMMA_THRESHOLD)
10755 {
10756 gamma_transform_test(pm, 0, 16, 0, pm->interlace_type,
10757 1/pm->gammas[i], pm->gammas[j], SBIT_16_TO_8,
10758 pm->use_input_precision_16to8, 1 /*scale16*/);
10759
10760 if (fail(pm))
10761 return;
10762
10763 gamma_transform_test(pm, 2, 16, 0, pm->interlace_type,
10764 1/pm->gammas[i], pm->gammas[j], SBIT_16_TO_8,
10765 pm->use_input_precision_16to8, 1 /*scale16*/);
10766
10767 if (fail(pm))
10768 return;
10769
10770 gamma_transform_test(pm, 4, 16, 0, pm->interlace_type,
10771 1/pm->gammas[i], pm->gammas[j], SBIT_16_TO_8,
10772 pm->use_input_precision_16to8, 1 /*scale16*/);
10773
10774 if (fail(pm))
10775 return;
10776
10777 gamma_transform_test(pm, 6, 16, 0, pm->interlace_type,
10778 1/pm->gammas[i], pm->gammas[j], SBIT_16_TO_8,
10779 pm->use_input_precision_16to8, 1 /*scale16*/);
10780
10781 if (fail(pm))
10782 return;
10783 }
10784 }
10785 }
10786}
10787#endif /* 16 to 8 bit conversion */
10788
10789#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
10790 defined(PNG_READ_ALPHA_MODE_SUPPORTED)
10791static void gamma_composition_test(png_modifier *pm,
10792 png_byte colour_type, png_byte bit_depth,
10793 int palette_number,
10794 int interlace_type, const double file_gamma,
10795 const double screen_gamma,
10796 int use_input_precision, int do_background,
10797 int expand_16)
10798{
10799 size_t pos = 0;
10800 png_const_charp base;
10801 double bg;
10802 char name[128];
10803 png_color_16 background;
10804
10805 /* Make up a name and get an appropriate background gamma value. */
10806 switch (do_background)
10807 {
10808 default:
10809 base = "";
10810 bg = 4; /* should not be used */
10811 break;
10812 case PNG_BACKGROUND_GAMMA_SCREEN:
10813 base = " bckg(Screen):";
10814 bg = 1/screen_gamma;
10815 break;
10816 case PNG_BACKGROUND_GAMMA_FILE:
10817 base = " bckg(File):";
10818 bg = file_gamma;
10819 break;
10820 case PNG_BACKGROUND_GAMMA_UNIQUE:
10821 base = " bckg(Unique):";
10822 /* This tests the handling of a unique value, the math is such that the
10823 * value tends to be <1, but is neither screen nor file (even if they
10824 * match!)
10825 */
10826 bg = (file_gamma + screen_gamma) / 3;
10827 break;
10828#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
10829 case ALPHA_MODE_OFFSET + PNG_ALPHA_PNG:
10830 base = " alpha(PNG)";
10831 bg = 4; /* should not be used */
10832 break;
10833 case ALPHA_MODE_OFFSET + PNG_ALPHA_STANDARD:
10834 base = " alpha(Porter-Duff)";
10835 bg = 4; /* should not be used */
10836 break;
10837 case ALPHA_MODE_OFFSET + PNG_ALPHA_OPTIMIZED:
10838 base = " alpha(Optimized)";
10839 bg = 4; /* should not be used */
10840 break;
10841 case ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN:
10842 base = " alpha(Broken)";
10843 bg = 4; /* should not be used */
10844 break;
10845#endif
10846 }
10847
10848 /* Use random background values - the background is always presented in the
10849 * output space (8 or 16 bit components).
10850 */
10851 if (expand_16 || bit_depth == 16)
10852 {
10853 png_uint_32 r = random_32();
10854
10855 background.red = (png_uint_16)r;
10856 background.green = (png_uint_16)(r >> 16);
10857 r = random_32();
10858 background.blue = (png_uint_16)r;
10859 background.gray = (png_uint_16)(r >> 16);
10860
10861 /* In earlier libpng versions, those where DIGITIZE is set, any background
10862 * gamma correction in the expand16 case was done using 8-bit gamma
10863 * correction tables, resulting in larger errors. To cope with those
10864 * cases use a 16-bit background value which will handle this gamma
10865 * correction.
10866 */
10867# if DIGITIZE
10868 if (expand_16 && (do_background == PNG_BACKGROUND_GAMMA_UNIQUE ||
10869 do_background == PNG_BACKGROUND_GAMMA_FILE) &&
10870 fabs(bg*screen_gamma-1) > PNG_GAMMA_THRESHOLD)
10871 {
10872 /* The background values will be looked up in an 8-bit table to do
10873 * the gamma correction, so only select values which are an exact
10874 * match for the 8-bit table entries:
10875 */
10876 background.red = (png_uint_16)((background.red >> 8) * 257);
10877 background.green = (png_uint_16)((background.green >> 8) * 257);
10878 background.blue = (png_uint_16)((background.blue >> 8) * 257);
10879 background.gray = (png_uint_16)((background.gray >> 8) * 257);
10880 }
10881# endif
10882 }
10883
10884 else /* 8 bit colors */
10885 {
10886 png_uint_32 r = random_32();
10887
10888 background.red = (png_byte)r;
10889 background.green = (png_byte)(r >> 8);
10890 background.blue = (png_byte)(r >> 16);
10891 background.gray = (png_byte)(r >> 24);
10892 }
10893
10894 background.index = 193; /* rgb(193,193,193) to detect errors */
10895
10896 if (!(colour_type & PNG_COLOR_MASK_COLOR))
10897 {
10898 /* Because, currently, png_set_background is always called with
10899 * 'need_expand' false in this case and because the gamma test itself
10900 * doesn't cause an expand to 8-bit for lower bit depths the colour must
10901 * be reduced to the correct range.
10902 */
10903 if (bit_depth < 8)
10904 background.gray &= (png_uint_16)((1U << bit_depth)-1);
10905
10906 /* Grayscale input, we do not convert to RGB (TBD), so we must set the
10907 * background to gray - else libpng seems to fail.
10908 */
10909 background.red = background.green = background.blue = background.gray;
10910 }
10911
10912 pos = safecat(name, sizeof name, pos, "gamma ");
10913 pos = safecatd(name, sizeof name, pos, file_gamma, 3);
10914 pos = safecat(name, sizeof name, pos, "->");
10915 pos = safecatd(name, sizeof name, pos, screen_gamma, 3);
10916
10917 pos = safecat(name, sizeof name, pos, base);
10918 if (do_background < ALPHA_MODE_OFFSET)
10919 {
10920 /* Include the background color and gamma in the name: */
10921 pos = safecat(name, sizeof name, pos, "(");
10922 /* This assumes no expand gray->rgb - the current code won't handle that!
10923 */
10924 if (colour_type & PNG_COLOR_MASK_COLOR)
10925 {
10926 pos = safecatn(name, sizeof name, pos, background.red);
10927 pos = safecat(name, sizeof name, pos, ",");
10928 pos = safecatn(name, sizeof name, pos, background.green);
10929 pos = safecat(name, sizeof name, pos, ",");
10930 pos = safecatn(name, sizeof name, pos, background.blue);
10931 }
10932 else
10933 pos = safecatn(name, sizeof name, pos, background.gray);
10934 pos = safecat(name, sizeof name, pos, ")^");
10935 pos = safecatd(name, sizeof name, pos, bg, 3);
10936 }
10937
10938 gamma_test(pm, colour_type, bit_depth, palette_number, interlace_type,
10939 file_gamma, screen_gamma, 0/*sBIT*/, 0, name, use_input_precision,
10940 0/*strip 16*/, expand_16, do_background, &background, bg);
10941}
10942
10943
10944static void
10945perform_gamma_composition_tests(png_modifier *pm, int do_background,
10946 int expand_16)
10947{
10948 png_byte colour_type = 0;
10949 png_byte bit_depth = 0;
10950 unsigned int palette_number = 0;
10951
10952 /* Skip the non-alpha cases - there is no setting of a transparency colour at
10953 * present.
10954 *
10955 * TODO: incorrect; the palette case sets tRNS and, now RGB and gray do,
10956 * however the palette case fails miserably so is commented out below.
10957 */
10958 while (next_format(&colour_type, &bit_depth, &palette_number,
10959 pm->test_lbg_gamma_composition, pm->test_tRNS))
10960 if ((colour_type & PNG_COLOR_MASK_ALPHA) != 0
10961#if 0 /* TODO: FIXME */
10962 /*TODO: FIXME: this should work */
10963 || colour_type == 3
10964#endif
10965 || (colour_type != 3 && palette_number != 0))
10966 {
10967 unsigned int i, j;
10968
10969 /* Don't skip the i==j case here - it's relevant. */
10970 for (i=0; i<pm->ngamma_tests; ++i)
10971 {
10972 for (j=0; j<pm->ngamma_tests; ++j)
10973 {
10974 gamma_composition_test(pm, colour_type, bit_depth, palette_number,
10975 pm->interlace_type, 1/pm->gammas[i], pm->gammas[j],
10976 pm->use_input_precision, do_background, expand_16);
10977
10978 if (fail(pm))
10979 return;
10980 }
10981 }
10982 }
10983}
10984#endif /* READ_BACKGROUND || READ_ALPHA_MODE */
10985
10986static void
10987init_gamma_errors(png_modifier *pm)
10988{
10989 /* Use -1 to catch tests that were not actually run */
10990 pm->error_gray_2 = pm->error_gray_4 = pm->error_gray_8 = -1.;
10991 pm->error_color_8 = -1.;
10992 pm->error_indexed = -1.;
10993 pm->error_gray_16 = pm->error_color_16 = -1.;
10994}
10995
10996static void
10997print_one(const char *leader, double err)
10998{
10999 if (err != -1.)
11000 printf(" %s %.5f\n", leader, err);
11001}
11002
11003static void
11004summarize_gamma_errors(png_modifier *pm, png_const_charp who, int low_bit_depth,
11005 int indexed)
11006{
11007 fflush(stderr);
11008
11009 if (who)
11010 printf("\nGamma correction with %s:\n", who);
11011
11012 else
11013 printf("\nBasic gamma correction:\n");
11014
11015 if (low_bit_depth)
11016 {
11017 print_one(" 2 bit gray: ", pm->error_gray_2);
11018 print_one(" 4 bit gray: ", pm->error_gray_4);
11019 print_one(" 8 bit gray: ", pm->error_gray_8);
11020 print_one(" 8 bit color:", pm->error_color_8);
11021 if (indexed)
11022 print_one(" indexed: ", pm->error_indexed);
11023 }
11024
11025 print_one("16 bit gray: ", pm->error_gray_16);
11026 print_one("16 bit color:", pm->error_color_16);
11027
11028 fflush(stdout);
11029}
11030
11031static void
11032perform_gamma_test(png_modifier *pm, int summary)
11033{
11034 /*TODO: remove this*/
11035 /* Save certain values for the temporary overrides below. */
11036 unsigned int calculations_use_input_precision =
11037 pm->calculations_use_input_precision;
11038# ifdef PNG_READ_BACKGROUND_SUPPORTED
11039 double maxout8 = pm->maxout8;
11040# endif
11041
11042 /* First some arbitrary no-transform tests: */
11043 if (!pm->this.speed && pm->test_gamma_threshold)
11044 {
11045 perform_gamma_threshold_tests(pm);
11046
11047 if (fail(pm))
11048 return;
11049 }
11050
11051 /* Now some real transforms. */
11052 if (pm->test_gamma_transform)
11053 {
11054 if (summary)
11055 {
11056 fflush(stderr);
11057 printf("Gamma correction error summary\n\n");
11058 printf("The printed value is the maximum error in the pixel values\n");
11059 printf("calculated by the libpng gamma correction code. The error\n");
11060 printf("is calculated as the difference between the output pixel\n");
11061 printf("value (always an integer) and the ideal value from the\n");
11062 printf("libpng specification (typically not an integer).\n\n");
11063
11064 printf("Expect this value to be less than .5 for 8 bit formats,\n");
11065 printf("less than 1 for formats with fewer than 8 bits and a small\n");
11066 printf("number (typically less than 5) for the 16 bit formats.\n");
11067 printf("For performance reasons the value for 16 bit formats\n");
11068 printf("increases when the image file includes an sBIT chunk.\n");
11069 fflush(stdout);
11070 }
11071
11072 init_gamma_errors(pm);
11073 /*TODO: remove this. Necessary because the current libpng
11074 * implementation works in 8 bits:
11075 */
11076 if (pm->test_gamma_expand16)
11077 pm->calculations_use_input_precision = 1;
11078 perform_gamma_transform_tests(pm);
11079 if (!calculations_use_input_precision)
11080 pm->calculations_use_input_precision = 0;
11081
11082 if (summary)
11083 summarize_gamma_errors(pm, NULL/*who*/, 1/*low bit depth*/, 1/*indexed*/);
11084
11085 if (fail(pm))
11086 return;
11087 }
11088
11089 /* The sbit tests produce much larger errors: */
11090 if (pm->test_gamma_sbit)
11091 {
11092 init_gamma_errors(pm);
11093 perform_gamma_sbit_tests(pm);
11094
11095 if (summary)
11096 summarize_gamma_errors(pm, "sBIT", pm->sbitlow < 8U, 1/*indexed*/);
11097
11098 if (fail(pm))
11099 return;
11100 }
11101
11102#ifdef DO_16BIT /* Should be READ_16BIT_SUPPORTED */
11103 if (pm->test_gamma_scale16)
11104 {
11105 /* The 16 to 8 bit strip operations: */
11106 init_gamma_errors(pm);
11107 perform_gamma_scale16_tests(pm);
11108
11109 if (summary)
11110 {
11111 fflush(stderr);
11112 printf("\nGamma correction with 16 to 8 bit reduction:\n");
11113 printf(" 16 bit gray: %.5f\n", pm->error_gray_16);
11114 printf(" 16 bit color: %.5f\n", pm->error_color_16);
11115 fflush(stdout);
11116 }
11117
11118 if (fail(pm))
11119 return;
11120 }
11121#endif
11122
11123#ifdef PNG_READ_BACKGROUND_SUPPORTED
11124 if (pm->test_gamma_background)
11125 {
11126 init_gamma_errors(pm);
11127
11128 /*TODO: remove this. Necessary because the current libpng
11129 * implementation works in 8 bits:
11130 */
11131 if (pm->test_gamma_expand16)
11132 {
11133 pm->calculations_use_input_precision = 1;
11134 pm->maxout8 = .499; /* because the 16 bit background is smashed */
11135 }
11136 perform_gamma_composition_tests(pm, PNG_BACKGROUND_GAMMA_UNIQUE,
11137 pm->test_gamma_expand16);
11138 if (!calculations_use_input_precision)
11139 pm->calculations_use_input_precision = 0;
11140 pm->maxout8 = maxout8;
11141
11142 if (summary)
11143 summarize_gamma_errors(pm, "background", 1, 0/*indexed*/);
11144
11145 if (fail(pm))
11146 return;
11147 }
11148#endif
11149
11150#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
11151 if (pm->test_gamma_alpha_mode)
11152 {
11153 int do_background;
11154
11155 init_gamma_errors(pm);
11156
11157 /*TODO: remove this. Necessary because the current libpng
11158 * implementation works in 8 bits:
11159 */
11160 if (pm->test_gamma_expand16)
11161 pm->calculations_use_input_precision = 1;
11162 for (do_background = ALPHA_MODE_OFFSET + PNG_ALPHA_STANDARD;
11163 do_background <= ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN && !fail(pm);
11164 ++do_background)
11165 perform_gamma_composition_tests(pm, do_background,
11166 pm->test_gamma_expand16);
11167 if (!calculations_use_input_precision)
11168 pm->calculations_use_input_precision = 0;
11169
11170 if (summary)
11171 summarize_gamma_errors(pm, "alpha mode", 1, 0/*indexed*/);
11172
11173 if (fail(pm))
11174 return;
11175 }
11176#endif
11177}
11178#endif /* PNG_READ_GAMMA_SUPPORTED */
11179#endif /* PNG_READ_SUPPORTED */
11180
11181/* INTERLACE MACRO VALIDATION */
11182/* This is copied verbatim from the specification, it is simply the pass
11183 * number in which each pixel in each 8x8 tile appears. The array must
11184 * be indexed adam7[y][x] and notice that the pass numbers are based at
11185 * 1, not 0 - the base libpng uses.
11186 */
11187static const
11188png_byte adam7[8][8] =
11189{
11190 { 1,6,4,6,2,6,4,6 },
11191 { 7,7,7,7,7,7,7,7 },
11192 { 5,6,5,6,5,6,5,6 },
11193 { 7,7,7,7,7,7,7,7 },
11194 { 3,6,4,6,3,6,4,6 },
11195 { 7,7,7,7,7,7,7,7 },
11196 { 5,6,5,6,5,6,5,6 },
11197 { 7,7,7,7,7,7,7,7 }
11198};
11199
11200/* This routine validates all the interlace support macros in png.h for
11201 * a variety of valid PNG widths and heights. It uses a number of similarly
11202 * named internal routines that feed off the above array.
11203 */
11204static png_uint_32
11205png_pass_start_row(int pass)
11206{
11207 int x, y;
11208 ++pass;
11209 for (y=0; y<8; ++y)
11210 for (x=0; x<8; ++x)
11211 if (adam7[y][x] == pass)
11212 return y;
11213 return 0xf;
11214}
11215
11216static png_uint_32
11217png_pass_start_col(int pass)
11218{
11219 int x, y;
11220 ++pass;
11221 for (x=0; x<8; ++x)
11222 for (y=0; y<8; ++y)
11223 if (adam7[y][x] == pass)
11224 return x;
11225 return 0xf;
11226}
11227
11228static int
11229png_pass_row_shift(int pass)
11230{
11231 int x, y, base=(-1), inc=8;
11232 ++pass;
11233 for (y=0; y<8; ++y)
11234 {
11235 for (x=0; x<8; ++x)
11236 {
11237 if (adam7[y][x] == pass)
11238 {
11239 if (base == (-1))
11240 base = y;
11241 else if (base == y)
11242 {}
11243 else if (inc == y-base)
11244 base=y;
11245 else if (inc == 8)
11246 inc = y-base, base=y;
11247 else if (inc != y-base)
11248 return 0xff; /* error - more than one 'inc' value! */
11249 }
11250 }
11251 }
11252
11253 if (base == (-1)) return 0xfe; /* error - no row in pass! */
11254
11255 /* The shift is always 1, 2 or 3 - no pass has all the rows! */
11256 switch (inc)
11257 {
11258case 2: return 1;
11259case 4: return 2;
11260case 8: return 3;
11261default: break;
11262 }
11263
11264 /* error - unrecognized 'inc' */
11265 return (inc << 8) + 0xfd;
11266}
11267
11268static int
11269png_pass_col_shift(int pass)
11270{
11271 int x, y, base=(-1), inc=8;
11272 ++pass;
11273 for (x=0; x<8; ++x)
11274 {
11275 for (y=0; y<8; ++y)
11276 {
11277 if (adam7[y][x] == pass)
11278 {
11279 if (base == (-1))
11280 base = x;
11281 else if (base == x)
11282 {}
11283 else if (inc == x-base)
11284 base=x;
11285 else if (inc == 8)
11286 inc = x-base, base=x;
11287 else if (inc != x-base)
11288 return 0xff; /* error - more than one 'inc' value! */
11289 }
11290 }
11291 }
11292
11293 if (base == (-1)) return 0xfe; /* error - no row in pass! */
11294
11295 /* The shift is always 1, 2 or 3 - no pass has all the rows! */
11296 switch (inc)
11297 {
11298case 1: return 0; /* pass 7 has all the columns */
11299case 2: return 1;
11300case 4: return 2;
11301case 8: return 3;
11302default: break;
11303 }
11304
11305 /* error - unrecognized 'inc' */
11306 return (inc << 8) + 0xfd;
11307}
11308
11309static png_uint_32
11310png_row_from_pass_row(png_uint_32 yIn, int pass)
11311{
11312 /* By examination of the array: */
11313 switch (pass)
11314 {
11315case 0: return yIn * 8;
11316case 1: return yIn * 8;
11317case 2: return yIn * 8 + 4;
11318case 3: return yIn * 4;
11319case 4: return yIn * 4 + 2;
11320case 5: return yIn * 2;
11321case 6: return yIn * 2 + 1;
11322default: break;
11323 }
11324
11325 return 0xff; /* bad pass number */
11326}
11327
11328static png_uint_32
11329png_col_from_pass_col(png_uint_32 xIn, int pass)
11330{
11331 /* By examination of the array: */
11332 switch (pass)
11333 {
11334case 0: return xIn * 8;
11335case 1: return xIn * 8 + 4;
11336case 2: return xIn * 4;
11337case 3: return xIn * 4 + 2;
11338case 4: return xIn * 2;
11339case 5: return xIn * 2 + 1;
11340case 6: return xIn;
11341default: break;
11342 }
11343
11344 return 0xff; /* bad pass number */
11345}
11346
11347static int
11348png_row_in_interlace_pass(png_uint_32 y, int pass)
11349{
11350 /* Is row 'y' in pass 'pass'? */
11351 int x;
11352 y &= 7;
11353 ++pass;
11354 for (x=0; x<8; ++x)
11355 if (adam7[y][x] == pass)
11356 return 1;
11357
11358 return 0;
11359}
11360
11361static int
11362png_col_in_interlace_pass(png_uint_32 x, int pass)
11363{
11364 /* Is column 'x' in pass 'pass'? */
11365 int y;
11366 x &= 7;
11367 ++pass;
11368 for (y=0; y<8; ++y)
11369 if (adam7[y][x] == pass)
11370 return 1;
11371
11372 return 0;
11373}
11374
11375static png_uint_32
11376png_pass_rows(png_uint_32 height, int pass)
11377{
11378 png_uint_32 tiles = height>>3;
11379 png_uint_32 rows = 0;
11380 unsigned int x, y;
11381
11382 height &= 7;
11383 ++pass;
11384 for (y=0; y<8; ++y)
11385 {
11386 for (x=0; x<8; ++x)
11387 {
11388 if (adam7[y][x] == pass)
11389 {
11390 rows += tiles;
11391 if (y < height) ++rows;
11392 break; /* i.e. break the 'x', column, loop. */
11393 }
11394 }
11395 }
11396
11397 return rows;
11398}
11399
11400static png_uint_32
11401png_pass_cols(png_uint_32 width, int pass)
11402{
11403 png_uint_32 tiles = width>>3;
11404 png_uint_32 cols = 0;
11405 unsigned int x, y;
11406
11407 width &= 7;
11408 ++pass;
11409 for (x=0; x<8; ++x)
11410 {
11411 for (y=0; y<8; ++y)
11412 {
11413 if (adam7[y][x] == pass)
11414 {
11415 cols += tiles;
11416 if (x < width) ++cols;
11417 break; /* i.e. break the 'y', row, loop. */
11418 }
11419 }
11420 }
11421
11422 return cols;
11423}
11424
11425static void
11426perform_interlace_macro_validation(void)
11427{
11428 /* The macros to validate, first those that depend only on pass:
11429 *
11430 * PNG_PASS_START_ROW(pass)
11431 * PNG_PASS_START_COL(pass)
11432 * PNG_PASS_ROW_SHIFT(pass)
11433 * PNG_PASS_COL_SHIFT(pass)
11434 */
11435 int pass;
11436
11437 for (pass=0; pass<7; ++pass)
11438 {
11439 png_uint_32 m, f, v;
11440
11441 m = PNG_PASS_START_ROW(pass);
11442 f = png_pass_start_row(pass);
11443 if (m != f)
11444 {
11445 fprintf(stderr, "PNG_PASS_START_ROW(%d) = %u != %x\n", pass, m, f);
11446 exit(99);
11447 }
11448
11449 m = PNG_PASS_START_COL(pass);
11450 f = png_pass_start_col(pass);
11451 if (m != f)
11452 {
11453 fprintf(stderr, "PNG_PASS_START_COL(%d) = %u != %x\n", pass, m, f);
11454 exit(99);
11455 }
11456
11457 m = PNG_PASS_ROW_SHIFT(pass);
11458 f = png_pass_row_shift(pass);
11459 if (m != f)
11460 {
11461 fprintf(stderr, "PNG_PASS_ROW_SHIFT(%d) = %u != %x\n", pass, m, f);
11462 exit(99);
11463 }
11464
11465 m = PNG_PASS_COL_SHIFT(pass);
11466 f = png_pass_col_shift(pass);
11467 if (m != f)
11468 {
11469 fprintf(stderr, "PNG_PASS_COL_SHIFT(%d) = %u != %x\n", pass, m, f);
11470 exit(99);
11471 }
11472
11473 /* Macros that depend on the image or sub-image height too:
11474 *
11475 * PNG_PASS_ROWS(height, pass)
11476 * PNG_PASS_COLS(width, pass)
11477 * PNG_ROW_FROM_PASS_ROW(yIn, pass)
11478 * PNG_COL_FROM_PASS_COL(xIn, pass)
11479 * PNG_ROW_IN_INTERLACE_PASS(y, pass)
11480 * PNG_COL_IN_INTERLACE_PASS(x, pass)
11481 */
11482 for (v=0;;)
11483 {
11484 /* The first two tests overflow if the pass row or column is outside
11485 * the possible range for a 32-bit result. In fact the values should
11486 * never be outside the range for a 31-bit result, but checking for 32
11487 * bits here ensures that if an app uses a bogus pass row or column
11488 * (just so long as it fits in a 32 bit integer) it won't get a
11489 * possibly dangerous overflow.
11490 */
11491 /* First the base 0 stuff: */
11492 if (v < png_pass_rows(0xFFFFFFFFU, pass))
11493 {
11494 m = PNG_ROW_FROM_PASS_ROW(v, pass);
11495 f = png_row_from_pass_row(v, pass);
11496 if (m != f)
11497 {
11498 fprintf(stderr, "PNG_ROW_FROM_PASS_ROW(%u, %d) = %u != %x\n",
11499 v, pass, m, f);
11500 exit(99);
11501 }
11502 }
11503
11504 if (v < png_pass_cols(0xFFFFFFFFU, pass))
11505 {
11506 m = PNG_COL_FROM_PASS_COL(v, pass);
11507 f = png_col_from_pass_col(v, pass);
11508 if (m != f)
11509 {
11510 fprintf(stderr, "PNG_COL_FROM_PASS_COL(%u, %d) = %u != %x\n",
11511 v, pass, m, f);
11512 exit(99);
11513 }
11514 }
11515
11516 m = PNG_ROW_IN_INTERLACE_PASS(v, pass);
11517 f = png_row_in_interlace_pass(v, pass);
11518 if (m != f)
11519 {
11520 fprintf(stderr, "PNG_ROW_IN_INTERLACE_PASS(%u, %d) = %u != %x\n",
11521 v, pass, m, f);
11522 exit(99);
11523 }
11524
11525 m = PNG_COL_IN_INTERLACE_PASS(v, pass);
11526 f = png_col_in_interlace_pass(v, pass);
11527 if (m != f)
11528 {
11529 fprintf(stderr, "PNG_COL_IN_INTERLACE_PASS(%u, %d) = %u != %x\n",
11530 v, pass, m, f);
11531 exit(99);
11532 }
11533
11534 /* Then the base 1 stuff: */
11535 ++v;
11536 m = PNG_PASS_ROWS(v, pass);
11537 f = png_pass_rows(v, pass);
11538 if (m != f)
11539 {
11540 fprintf(stderr, "PNG_PASS_ROWS(%u, %d) = %u != %x\n",
11541 v, pass, m, f);
11542 exit(99);
11543 }
11544
11545 m = PNG_PASS_COLS(v, pass);
11546 f = png_pass_cols(v, pass);
11547 if (m != f)
11548 {
11549 fprintf(stderr, "PNG_PASS_COLS(%u, %d) = %u != %x\n",
11550 v, pass, m, f);
11551 exit(99);
11552 }
11553
11554 /* Move to the next v - the stepping algorithm starts skipping
11555 * values above 1024.
11556 */
11557 if (v > 1024)
11558 {
11559 if (v == PNG_UINT_31_MAX)
11560 break;
11561
11562 v = (v << 1) ^ v;
11563 if (v >= PNG_UINT_31_MAX)
11564 v = PNG_UINT_31_MAX-1;
11565 }
11566 }
11567 }
11568}
11569
11570/* Test color encodings. These values are back-calculated from the published
11571 * chromaticities. The values are accurate to about 14 decimal places; 15 are
11572 * given. These values are much more accurate than the ones given in the spec,
11573 * which typically don't exceed 4 decimal places. This allows testing of the
11574 * libpng code to its theoretical accuracy of 4 decimal places. (If pngvalid
11575 * used the published errors the 'slack' permitted would have to be +/-.5E-4 or
11576 * more.)
11577 *
11578 * The png_modifier code assumes that encodings[0] is sRGB and treats it
11579 * specially: do not change the first entry in this list!
11580 */
11581static const color_encoding test_encodings[] =
11582{
11583/* sRGB: must be first in this list! */
11584/*gamma:*/ { 1/2.2,
11585/*red: */ { 0.412390799265959, 0.212639005871510, 0.019330818715592 },
11586/*green:*/ { 0.357584339383878, 0.715168678767756, 0.119194779794626 },
11587/*blue: */ { 0.180480788401834, 0.072192315360734, 0.950532152249660} },
11588/* Kodak ProPhoto (wide gamut) */
11589/*gamma:*/ { 1/1.6 /*approximate: uses 1.8 power law compared to sRGB 2.4*/,
11590/*red: */ { 0.797760489672303, 0.288071128229293, 0.000000000000000 },
11591/*green:*/ { 0.135185837175740, 0.711843217810102, 0.000000000000000 },
11592/*blue: */ { 0.031349349581525, 0.000085653960605, 0.825104602510460} },
11593/* Adobe RGB (1998) */
11594/*gamma:*/ { 1/(2+51./256),
11595/*red: */ { 0.576669042910131, 0.297344975250536, 0.027031361386412 },
11596/*green:*/ { 0.185558237906546, 0.627363566255466, 0.070688852535827 },
11597/*blue: */ { 0.188228646234995, 0.075291458493998, 0.991337536837639} },
11598/* Adobe Wide Gamut RGB */
11599/*gamma:*/ { 1/(2+51./256),
11600/*red: */ { 0.716500716779386, 0.258728243040113, 0.000000000000000 },
11601/*green:*/ { 0.101020574397477, 0.724682314948566, 0.051211818965388 },
11602/*blue: */ { 0.146774385252705, 0.016589442011321, 0.773892783545073} },
11603/* Fake encoding which selects just the green channel */
11604/*gamma:*/ { 1.45/2.2, /* the 'Mac' gamma */
11605/*red: */ { 0.716500716779386, 0.000000000000000, 0.000000000000000 },
11606/*green:*/ { 0.101020574397477, 1.000000000000000, 0.051211818965388 },
11607/*blue: */ { 0.146774385252705, 0.000000000000000, 0.773892783545073} },
11608};
11609
11610/* signal handler
11611 *
11612 * This attempts to trap signals and escape without crashing. It needs a
11613 * context pointer so that it can throw an exception (call longjmp) to recover
11614 * from the condition; this is handled by making the png_modifier used by 'main'
11615 * into a global variable.
11616 */
11617static png_modifier pm;
11618
11619static void signal_handler(int signum)
11620{
11621
11622 size_t pos = 0;
11623 char msg[64];
11624
11625 pos = safecat(msg, sizeof msg, pos, "caught signal: ");
11626
11627 switch (signum)
11628 {
11629 case SIGABRT:
11630 pos = safecat(msg, sizeof msg, pos, "abort");
11631 break;
11632
11633 case SIGFPE:
11634 pos = safecat(msg, sizeof msg, pos, "floating point exception");
11635 break;
11636
11637 case SIGILL:
11638 pos = safecat(msg, sizeof msg, pos, "illegal instruction");
11639 break;
11640
11641 case SIGINT:
11642 pos = safecat(msg, sizeof msg, pos, "interrupt");
11643 break;
11644
11645 case SIGSEGV:
11646 pos = safecat(msg, sizeof msg, pos, "invalid memory access");
11647 break;
11648
11649 case SIGTERM:
11650 pos = safecat(msg, sizeof msg, pos, "termination request");
11651 break;
11652
11653 default:
11654 pos = safecat(msg, sizeof msg, pos, "unknown ");
11655 pos = safecatn(msg, sizeof msg, pos, signum);
11656 break;
11657 }
11658
11659 store_log(&pm.this, NULL/*png_structp*/, msg, 1/*error*/);
11660
11661 /* And finally throw an exception so we can keep going, unless this is
11662 * SIGTERM in which case stop now.
11663 */
11664 if (signum != SIGTERM)
11665 {
11666 struct exception_context *the_exception_context =
11667 &pm.this.exception_context;
11668
11669 Throw &pm.this;
11670 }
11671
11672 else
11673 exit(1);
11674}
11675
11676/* main program */
11677int main(int argc, char **argv)
11678{
11679 int summary = 1; /* Print the error summary at the end */
11680 int memstats = 0; /* Print memory statistics at the end */
11681
11682 /* Create the given output file on success: */
11683 const char *touch = NULL;
11684
11685 /* This is an array of standard gamma values (believe it or not I've seen
11686 * every one of these mentioned somewhere.)
11687 *
11688 * In the following list the most useful values are first!
11689 */
11690 static double
11691 gammas[]={2.2, 1.0, 2.2/1.45, 1.8, 1.5, 2.4, 2.5, 2.62, 2.9};
11692
11693 /* This records the command and arguments: */
11694 size_t cp = 0;
11695 char command[1024];
11696
11697 anon_context(&pm.this);
11698
11699 gnu_volatile(summary)
11700 gnu_volatile(memstats)
11701 gnu_volatile(touch)
11702
11703 /* Add appropriate signal handlers, just the ANSI specified ones: */
11704 signal(SIGABRT, signal_handler);
11705 signal(SIGFPE, signal_handler);
11706 signal(SIGILL, signal_handler);
11707 signal(SIGINT, signal_handler);
11708 signal(SIGSEGV, signal_handler);
11709 signal(SIGTERM, signal_handler);
11710
11711#ifdef HAVE_FEENABLEEXCEPT
11712 /* Only required to enable FP exceptions on platforms where they start off
11713 * disabled; this is not necessary but if it is not done pngvalid will likely
11714 * end up ignoring FP conditions that other platforms fault.
11715 */
11716 feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
11717#endif
11718
11719 modifier_init(&pm);
11720
11721 /* Preallocate the image buffer, because we know how big it needs to be,
11722 * note that, for testing purposes, it is deliberately mis-aligned by tag
11723 * bytes either side. All rows have an additional five bytes of padding for
11724 * overwrite checking.
11725 */
11726 store_ensure_image(&pm.this, NULL, 2, TRANSFORM_ROWMAX, TRANSFORM_HEIGHTMAX);
11727
11728 /* Don't give argv[0], it's normally some horrible libtool string: */
11729 cp = safecat(command, sizeof command, cp, "pngvalid");
11730
11731 /* Default to error on warning: */
11732 pm.this.treat_warnings_as_errors = 1;
11733
11734 /* Default assume_16_bit_calculations appropriately; this tells the checking
11735 * code that 16-bit arithmetic is used for 8-bit samples when it would make a
11736 * difference.
11737 */
11738 pm.assume_16_bit_calculations = PNG_LIBPNG_VER == 10700;
11739
11740 /* Currently 16 bit expansion happens at the end of the pipeline, so the
11741 * calculations are done in the input bit depth not the output.
11742 *
11743 * TODO: fix this
11744 */
11745 pm.calculations_use_input_precision = 1U;
11746
11747 /* Store the test gammas */
11748 pm.gammas = gammas;
11749 pm.ngammas = ARRAY_SIZE(gammas);
11750 pm.ngamma_tests = 0; /* default to off */
11751
11752 /* Low bit depth gray images don't do well in the gamma tests, until
11753 * this is fixed turn them off for some gamma cases:
11754 */
11755# ifdef PNG_WRITE_tRNS_SUPPORTED
11756 pm.test_tRNS = 1;
11757# endif
11758 pm.test_lbg = PNG_LIBPNG_VER >= 10600;
11759 pm.test_lbg_gamma_threshold = 1;
11760 pm.test_lbg_gamma_transform = PNG_LIBPNG_VER >= 10600;
11761 pm.test_lbg_gamma_sbit = 1;
11762 pm.test_lbg_gamma_composition = PNG_LIBPNG_VER == 10700;
11763
11764 /* And the test encodings */
11765 pm.encodings = test_encodings;
11766 pm.nencodings = ARRAY_SIZE(test_encodings);
11767
11768# if PNG_LIBPNG_VER != 10700
11769 pm.sbitlow = 8U; /* because libpng doesn't do sBIT below 8! */
11770# else
11771 pm.sbitlow = 1U;
11772# endif
11773
11774 /* The following allows results to pass if they correspond to anything in the
11775 * transformed range [input-.5,input+.5]; this is is required because of the
11776 * way libpng treats the 16_TO_8 flag when building the gamma tables in
11777 * releases up to 1.6.0.
11778 *
11779 * TODO: review this
11780 */
11781 pm.use_input_precision_16to8 = 1U;
11782 pm.use_input_precision_sbit = 1U; /* because libpng now rounds sBIT */
11783
11784 /* Some default values (set the behavior for 'make check' here).
11785 * These values simply control the maximum error permitted in the gamma
11786 * transformations. The practical limits for human perception are described
11787 * below (the setting for maxpc16), however for 8 bit encodings it isn't
11788 * possible to meet the accepted capabilities of human vision - i.e. 8 bit
11789 * images can never be good enough, regardless of encoding.
11790 */
11791 pm.maxout8 = .1; /* Arithmetic error in *encoded* value */
11792 pm.maxabs8 = .00005; /* 1/20000 */
11793 pm.maxcalc8 = 1./255; /* +/-1 in 8 bits for compose errors */
11794 pm.maxpc8 = .499; /* I.e., .499% fractional error */
11795 pm.maxout16 = .499; /* Error in *encoded* value */
11796 pm.maxabs16 = .00005;/* 1/20000 */
11797 pm.maxcalc16 =1./65535;/* +/-1 in 16 bits for compose errors */
11798# if PNG_LIBPNG_VER != 10700
11799 pm.maxcalcG = 1./((1<<PNG_MAX_GAMMA_8)-1);
11800# else
11801 pm.maxcalcG = 1./((1<<16)-1);
11802# endif
11803
11804 /* NOTE: this is a reasonable perceptual limit. We assume that humans can
11805 * perceive light level differences of 1% over a 100:1 range, so we need to
11806 * maintain 1 in 10000 accuracy (in linear light space), which is what the
11807 * following guarantees. It also allows significantly higher errors at
11808 * higher 16 bit values, which is important for performance. The actual
11809 * maximum 16 bit error is about +/-1.9 in the fixed point implementation but
11810 * this is only allowed for values >38149 by the following:
11811 */
11812 pm.maxpc16 = .005; /* I.e., 1/200% - 1/20000 */
11813
11814 /* Now parse the command line options. */
11815 while (--argc >= 1)
11816 {
11817 int catmore = 0; /* Set if the argument has an argument. */
11818
11819 /* Record each argument for posterity: */
11820 cp = safecat(command, sizeof command, cp, " ");
11821 cp = safecat(command, sizeof command, cp, *++argv);
11822
11823 if (strcmp(*argv, "-v") == 0)
11824 pm.this.verbose = 1;
11825
11826 else if (strcmp(*argv, "-l") == 0)
11827 pm.log = 1;
11828
11829 else if (strcmp(*argv, "-q") == 0)
11830 summary = pm.this.verbose = pm.log = 0;
11831
11832 else if (strcmp(*argv, "-w") == 0 ||
11833 strcmp(*argv, "--strict") == 0)
11834 pm.this.treat_warnings_as_errors = 1; /* NOTE: this is the default! */
11835
11836 else if (strcmp(*argv, "--nostrict") == 0)
11837 pm.this.treat_warnings_as_errors = 0;
11838
11839 else if (strcmp(*argv, "--speed") == 0)
11840 pm.this.speed = 1, pm.ngamma_tests = pm.ngammas, pm.test_standard = 0,
11841 summary = 0;
11842
11843 else if (strcmp(*argv, "--memory") == 0)
11844 memstats = 1;
11845
11846 else if (strcmp(*argv, "--size") == 0)
11847 pm.test_size = 1;
11848
11849 else if (strcmp(*argv, "--nosize") == 0)
11850 pm.test_size = 0;
11851
11852 else if (strcmp(*argv, "--standard") == 0)
11853 pm.test_standard = 1;
11854
11855 else if (strcmp(*argv, "--nostandard") == 0)
11856 pm.test_standard = 0;
11857
11858 else if (strcmp(*argv, "--transform") == 0)
11859 pm.test_transform = 1;
11860
11861 else if (strcmp(*argv, "--notransform") == 0)
11862 pm.test_transform = 0;
11863
11864#ifdef PNG_READ_TRANSFORMS_SUPPORTED
11865 else if (strncmp(*argv, "--transform-disable=",
11866 sizeof "--transform-disable") == 0)
11867 {
11868 pm.test_transform = 1;
11869 transform_disable(*argv + sizeof "--transform-disable");
11870 }
11871
11872 else if (strncmp(*argv, "--transform-enable=",
11873 sizeof "--transform-enable") == 0)
11874 {
11875 pm.test_transform = 1;
11876 transform_enable(*argv + sizeof "--transform-enable");
11877 }
11878#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
11879
11880 else if (strcmp(*argv, "--gamma") == 0)
11881 {
11882 /* Just do two gamma tests here (2.2 and linear) for speed: */
11883 pm.ngamma_tests = 2U;
11884 pm.test_gamma_threshold = 1;
11885 pm.test_gamma_transform = 1;
11886 pm.test_gamma_sbit = 1;
11887 pm.test_gamma_scale16 = 1;
11888 pm.test_gamma_background = 1; /* composition */
11889 pm.test_gamma_alpha_mode = 1;
11890 }
11891
11892 else if (strcmp(*argv, "--nogamma") == 0)
11893 pm.ngamma_tests = 0;
11894
11895 else if (strcmp(*argv, "--gamma-threshold") == 0)
11896 pm.ngamma_tests = 2U, pm.test_gamma_threshold = 1;
11897
11898 else if (strcmp(*argv, "--nogamma-threshold") == 0)
11899 pm.test_gamma_threshold = 0;
11900
11901 else if (strcmp(*argv, "--gamma-transform") == 0)
11902 pm.ngamma_tests = 2U, pm.test_gamma_transform = 1;
11903
11904 else if (strcmp(*argv, "--nogamma-transform") == 0)
11905 pm.test_gamma_transform = 0;
11906
11907 else if (strcmp(*argv, "--gamma-sbit") == 0)
11908 pm.ngamma_tests = 2U, pm.test_gamma_sbit = 1;
11909
11910 else if (strcmp(*argv, "--nogamma-sbit") == 0)
11911 pm.test_gamma_sbit = 0;
11912
11913 else if (strcmp(*argv, "--gamma-16-to-8") == 0)
11914 pm.ngamma_tests = 2U, pm.test_gamma_scale16 = 1;
11915
11916 else if (strcmp(*argv, "--nogamma-16-to-8") == 0)
11917 pm.test_gamma_scale16 = 0;
11918
11919 else if (strcmp(*argv, "--gamma-background") == 0)
11920 pm.ngamma_tests = 2U, pm.test_gamma_background = 1;
11921
11922 else if (strcmp(*argv, "--nogamma-background") == 0)
11923 pm.test_gamma_background = 0;
11924
11925 else if (strcmp(*argv, "--gamma-alpha-mode") == 0)
11926 pm.ngamma_tests = 2U, pm.test_gamma_alpha_mode = 1;
11927
11928 else if (strcmp(*argv, "--nogamma-alpha-mode") == 0)
11929 pm.test_gamma_alpha_mode = 0;
11930
11931 else if (strcmp(*argv, "--expand16") == 0)
11932 {
11933# ifdef PNG_READ_EXPAND_16_SUPPORTED
11934 pm.test_gamma_expand16 = 1;
11935# else
11936 fprintf(stderr, "pngvalid: --expand16: no read support\n");
11937 return SKIP;
11938# endif
11939 }
11940
11941 else if (strcmp(*argv, "--noexpand16") == 0)
11942 pm.test_gamma_expand16 = 0;
11943
11944 else if (strcmp(*argv, "--low-depth-gray") == 0)
11945 pm.test_lbg = pm.test_lbg_gamma_threshold =
11946 pm.test_lbg_gamma_transform = pm.test_lbg_gamma_sbit =
11947 pm.test_lbg_gamma_composition = 1;
11948
11949 else if (strcmp(*argv, "--nolow-depth-gray") == 0)
11950 pm.test_lbg = pm.test_lbg_gamma_threshold =
11951 pm.test_lbg_gamma_transform = pm.test_lbg_gamma_sbit =
11952 pm.test_lbg_gamma_composition = 0;
11953
11954 else if (strcmp(*argv, "--tRNS") == 0)
11955 {
11956# ifdef PNG_WRITE_tRNS_SUPPORTED
11957 pm.test_tRNS = 1;
11958# else
11959 fprintf(stderr, "pngvalid: --tRNS: no write support\n");
11960 return SKIP;
11961# endif
11962 }
11963
11964 else if (strcmp(*argv, "--notRNS") == 0)
11965 pm.test_tRNS = 0;
11966
11967 else if (strcmp(*argv, "--more-gammas") == 0)
11968 pm.ngamma_tests = 3U;
11969
11970 else if (strcmp(*argv, "--all-gammas") == 0)
11971 pm.ngamma_tests = pm.ngammas;
11972
11973 else if (strcmp(*argv, "--progressive-read") == 0)
11974 pm.this.progressive = 1;
11975
11976 else if (strcmp(*argv, "--use-update-info") == 0)
11977 ++pm.use_update_info; /* Can call multiple times */
11978
11979 else if (strcmp(*argv, "--interlace") == 0)
11980 {
11981# if CAN_WRITE_INTERLACE
11982 pm.interlace_type = PNG_INTERLACE_ADAM7;
11983# else /* !CAN_WRITE_INTERLACE */
11984 fprintf(stderr, "pngvalid: no write interlace support\n");
11985 return SKIP;
11986# endif /* !CAN_WRITE_INTERLACE */
11987 }
11988
11989 else if (strcmp(*argv, "--use-input-precision") == 0)
11990 pm.use_input_precision = 1U;
11991
11992 else if (strcmp(*argv, "--use-calculation-precision") == 0)
11993 pm.use_input_precision = 0;
11994
11995 else if (strcmp(*argv, "--calculations-use-input-precision") == 0)
11996 pm.calculations_use_input_precision = 1U;
11997
11998 else if (strcmp(*argv, "--assume-16-bit-calculations") == 0)
11999 pm.assume_16_bit_calculations = 1U;
12000
12001 else if (strcmp(*argv, "--calculations-follow-bit-depth") == 0)
12002 pm.calculations_use_input_precision =
12003 pm.assume_16_bit_calculations = 0;
12004
12005 else if (strcmp(*argv, "--exhaustive") == 0)
12006 pm.test_exhaustive = 1;
12007
12008 else if (argc > 1 && strcmp(*argv, "--sbitlow") == 0)
12009 --argc, pm.sbitlow = (png_byte)atoi(*++argv), catmore = 1;
12010
12011 else if (argc > 1 && strcmp(*argv, "--touch") == 0)
12012 --argc, touch = *++argv, catmore = 1;
12013
12014 else if (argc > 1 && strncmp(*argv, "--max", 5) == 0)
12015 {
12016 --argc;
12017
12018 if (strcmp(5+*argv, "abs8") == 0)
12019 pm.maxabs8 = atof(*++argv);
12020
12021 else if (strcmp(5+*argv, "abs16") == 0)
12022 pm.maxabs16 = atof(*++argv);
12023
12024 else if (strcmp(5+*argv, "calc8") == 0)
12025 pm.maxcalc8 = atof(*++argv);
12026
12027 else if (strcmp(5+*argv, "calc16") == 0)
12028 pm.maxcalc16 = atof(*++argv);
12029
12030 else if (strcmp(5+*argv, "out8") == 0)
12031 pm.maxout8 = atof(*++argv);
12032
12033 else if (strcmp(5+*argv, "out16") == 0)
12034 pm.maxout16 = atof(*++argv);
12035
12036 else if (strcmp(5+*argv, "pc8") == 0)
12037 pm.maxpc8 = atof(*++argv);
12038
12039 else if (strcmp(5+*argv, "pc16") == 0)
12040 pm.maxpc16 = atof(*++argv);
12041
12042 else
12043 {
12044 fprintf(stderr, "pngvalid: %s: unknown 'max' option\n", *argv);
12045 exit(99);
12046 }
12047
12048 catmore = 1;
12049 }
12050
12051 else if (strcmp(*argv, "--log8") == 0)
12052 --argc, pm.log8 = atof(*++argv), catmore = 1;
12053
12054 else if (strcmp(*argv, "--log16") == 0)
12055 --argc, pm.log16 = atof(*++argv), catmore = 1;
12056
12057#ifdef PNG_SET_OPTION_SUPPORTED
12058 else if (strncmp(*argv, "--option=", 9) == 0)
12059 {
12060 /* Syntax of the argument is <option>:{on|off} */
12061 const char *arg = 9+*argv;
12062 unsigned char option=0, setting=0;
12063
12064#ifdef PNG_ARM_NEON
12065 if (strncmp(arg, "arm-neon:", 9) == 0)
12066 option = PNG_ARM_NEON, arg += 9;
12067
12068 else
12069#endif
12070#ifdef PNG_EXTENSIONS
12071 if (strncmp(arg, "extensions:", 11) == 0)
12072 option = PNG_EXTENSIONS, arg += 11;
12073
12074 else
12075#endif
12076#ifdef PNG_MAXIMUM_INFLATE_WINDOW
12077 if (strncmp(arg, "max-inflate-window:", 19) == 0)
12078 option = PNG_MAXIMUM_INFLATE_WINDOW, arg += 19;
12079
12080 else
12081#endif
12082 {
12083 fprintf(stderr, "pngvalid: %s: %s: unknown option\n", *argv, arg);
12084 exit(99);
12085 }
12086
12087 if (strcmp(arg, "off") == 0)
12088 setting = PNG_OPTION_OFF;
12089
12090 else if (strcmp(arg, "on") == 0)
12091 setting = PNG_OPTION_ON;
12092
12093 else
12094 {
12095 fprintf(stderr,
12096 "pngvalid: %s: %s: unknown setting (use 'on' or 'off')\n",
12097 *argv, arg);
12098 exit(99);
12099 }
12100
12101 pm.this.options[pm.this.noptions].option = option;
12102 pm.this.options[pm.this.noptions++].setting = setting;
12103 }
12104#endif /* PNG_SET_OPTION_SUPPORTED */
12105
12106 else
12107 {
12108 fprintf(stderr, "pngvalid: %s: unknown argument\n", *argv);
12109 exit(99);
12110 }
12111
12112 if (catmore) /* consumed an extra *argv */
12113 {
12114 cp = safecat(command, sizeof command, cp, " ");
12115 cp = safecat(command, sizeof command, cp, *argv);
12116 }
12117 }
12118
12119 /* If pngvalid is run with no arguments default to a reasonable set of the
12120 * tests.
12121 */
12122 if (pm.test_standard == 0 && pm.test_size == 0 && pm.test_transform == 0 &&
12123 pm.ngamma_tests == 0)
12124 {
12125 /* Make this do all the tests done in the test shell scripts with the same
12126 * parameters, where possible. The limitation is that all the progressive
12127 * read and interlace stuff has to be done in separate runs, so only the
12128 * basic 'standard' and 'size' tests are done.
12129 */
12130 pm.test_standard = 1;
12131 pm.test_size = 1;
12132 pm.test_transform = 1;
12133 pm.ngamma_tests = 2U;
12134 }
12135
12136 if (pm.ngamma_tests > 0 &&
12137 pm.test_gamma_threshold == 0 && pm.test_gamma_transform == 0 &&
12138 pm.test_gamma_sbit == 0 && pm.test_gamma_scale16 == 0 &&
12139 pm.test_gamma_background == 0 && pm.test_gamma_alpha_mode == 0)
12140 {
12141 pm.test_gamma_threshold = 1;
12142 pm.test_gamma_transform = 1;
12143 pm.test_gamma_sbit = 1;
12144 pm.test_gamma_scale16 = 1;
12145 pm.test_gamma_background = 1;
12146 pm.test_gamma_alpha_mode = 1;
12147 }
12148
12149 else if (pm.ngamma_tests == 0)
12150 {
12151 /* Nothing to test so turn everything off: */
12152 pm.test_gamma_threshold = 0;
12153 pm.test_gamma_transform = 0;
12154 pm.test_gamma_sbit = 0;
12155 pm.test_gamma_scale16 = 0;
12156 pm.test_gamma_background = 0;
12157 pm.test_gamma_alpha_mode = 0;
12158 }
12159
12160 Try
12161 {
12162 /* Make useful base images */
12163 make_transform_images(&pm);
12164
12165 /* Perform the standard and gamma tests. */
12166 if (pm.test_standard)
12167 {
12168 perform_interlace_macro_validation();
12169 perform_formatting_test(&pm.this);
12170# ifdef PNG_READ_SUPPORTED
12171 perform_standard_test(&pm);
12172# endif
12173 perform_error_test(&pm);
12174 }
12175
12176 /* Various oddly sized images: */
12177 if (pm.test_size)
12178 {
12179 make_size_images(&pm.this);
12180# ifdef PNG_READ_SUPPORTED
12181 perform_size_test(&pm);
12182# endif
12183 }
12184
12185#ifdef PNG_READ_TRANSFORMS_SUPPORTED
12186 /* Combinatorial transforms: */
12187 if (pm.test_transform)
12188 perform_transform_test(&pm);
12189#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
12190
12191#ifdef PNG_READ_GAMMA_SUPPORTED
12192 if (pm.ngamma_tests > 0)
12193 perform_gamma_test(&pm, summary);
12194#endif
12195 }
12196
12197 Catch_anonymous
12198 {
12199 fprintf(stderr, "pngvalid: test aborted (probably failed in cleanup)\n");
12200 if (!pm.this.verbose)
12201 {
12202 if (pm.this.error[0] != 0)
12203 fprintf(stderr, "pngvalid: first error: %s\n", pm.this.error);
12204
12205 fprintf(stderr, "pngvalid: run with -v to see what happened\n");
12206 }
12207 exit(1);
12208 }
12209
12210 if (summary)
12211 {
12212 printf("%s: %s (%s point arithmetic)\n",
12213 (pm.this.nerrors || (pm.this.treat_warnings_as_errors &&
12214 pm.this.nwarnings)) ? "FAIL" : "PASS",
12215 command,
12216#if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || PNG_LIBPNG_VER < 10500
12217 "floating"
12218#else
12219 "fixed"
12220#endif
12221 );
12222 }
12223
12224 if (memstats)
12225 {
12226 printf("Allocated memory statistics (in bytes):\n"
12227 "\tread %lu maximum single, %lu peak, %lu total\n"
12228 "\twrite %lu maximum single, %lu peak, %lu total\n",
12229 (unsigned long)pm.this.read_memory_pool.max_max,
12230 (unsigned long)pm.this.read_memory_pool.max_limit,
12231 (unsigned long)pm.this.read_memory_pool.max_total,
12232 (unsigned long)pm.this.write_memory_pool.max_max,
12233 (unsigned long)pm.this.write_memory_pool.max_limit,
12234 (unsigned long)pm.this.write_memory_pool.max_total);
12235 }
12236
12237 /* Do this here to provoke memory corruption errors in memory not directly
12238 * allocated by libpng - not a complete test, but better than nothing.
12239 */
12240 store_delete(&pm.this);
12241
12242 /* Error exit if there are any errors, and maybe if there are any
12243 * warnings.
12244 */
12245 if (pm.this.nerrors || (pm.this.treat_warnings_as_errors &&
12246 pm.this.nwarnings))
12247 {
12248 if (!pm.this.verbose)
12249 fprintf(stderr, "pngvalid: %s\n", pm.this.error);
12250
12251 fprintf(stderr, "pngvalid: %d errors, %d warnings\n", pm.this.nerrors,
12252 pm.this.nwarnings);
12253
12254 exit(1);
12255 }
12256
12257 /* Success case. */
12258 if (touch != NULL)
12259 {
12260 FILE *fsuccess = fopen(touch, "wt");
12261
12262 if (fsuccess != NULL)
12263 {
12264 int error = 0;
12265 fprintf(fsuccess, "PNG validation succeeded\n");
12266 fflush(fsuccess);
12267 error = ferror(fsuccess);
12268
12269 if (fclose(fsuccess) || error)
12270 {
12271 fprintf(stderr, "%s: write failed\n", touch);
12272 exit(1);
12273 }
12274 }
12275
12276 else
12277 {
12278 fprintf(stderr, "%s: open failed\n", touch);
12279 exit(1);
12280 }
12281 }
12282
12283 /* This is required because some very minimal configurations do not use it:
12284 */
12285 UNUSED(fail)
12286 return 0;
12287}
12288#else /* write or low level APIs not supported */
12289int main(void)
12290{
12291 fprintf(stderr,
12292 "pngvalid: no low level write support in libpng, all tests skipped\n");
12293 /* So the test is skipped: */
12294 return SKIP;
12295}
12296#endif
Note: See TracBrowser for help on using the repository browser.

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