1 commit a21a5b22c10b900d44d40fe30a203302b2a67f8b
2 Author: John Bowler <jbowler@acm.org>
3 Date: Mon Mar 30 21:38:31 2015 -0500
5 [libpng16] Fixed rgb_to_gray checks and added tRNS checks to pngvalid.c
7 #diff --git a/ANNOUNCE b/ANNOUNCE
8 #index 73fadac..7e6c842 100644
12 #-Libpng 1.6.18beta01 - March 27, 2015
13 #+Libpng 1.6.18beta01 - March 31, 2015
15 # This is not intended to be a public release. It will be replaced
16 # within a few weeks by a public version or by another test version.
17 #@@ -25,10 +25,11 @@ Other information:
19 # Changes since the last public release (1.6.17):
21 #-Version 1.6.18beta01 [March 27, 2015]
22 #+Version 1.6.18beta01 [March 31, 2015]
23 # Removed PNG_SET_CHUNK_[CACHE|MALLOC]_LIMIT_SUPPORTED macros. They
24 # have been combined with PNG_SET_USER_LIMITS_SUPPORTED (resolves
25 # bug report by Andrew Church).
26 #+ Fixed rgb_to_gray checks and added tRNS checks to pngvalid.c
28 # Send comments/corrections/commendations to png-mng-implement at lists.sf.net
29 # (subscription required; visit
30 #diff --git a/CHANGES b/CHANGES
31 #index fe07211..35b5979 100644
34 #@@ -5205,10 +5205,11 @@ Version 1.6.17rc06 [March 23, 2015]
35 # Version 1.6.17 [March 26, 2015]
38 #-Version 1.6.18beta01 [March 27, 2015]
39 #+Version 1.6.18beta01 [March 31, 2015]
40 # Removed PNG_SET_CHUNK_[CACHE|MALLOC]_LIMIT_SUPPORTED macros. They
41 # have been combined with PNG_SET_USER_LIMITS_SUPPORTED (resolves
42 # bug report by Andrew Church).
43 #+ Fixed rgb_to_gray checks and added tRNS checks to pngvalid.c
45 # Send comments/corrections/commendations to png-mng-implement at lists.sf.net
46 # (subscription required; visit
47 diff --git a/autogen.sh b/autogen.sh
48 index 9af34bd..702a0c1 100755
51 @@ -73,8 +73,9 @@ done
52 # present bad things are happening.
54 # The autotools generated files:
55 -libpng_autotools_files="Makefile.in aclocal.m4 config.guess config.h.in\
56 - config.sub configure depcomp install-sh ltmain.sh missing test-driver"
57 +libpng_autotools_files="Makefile.in aclocal.m4 config.guess config.h.in
58 + config.h.in~ config.sub configure depcomp install-sh ltmain.sh missing\
61 # Files generated by versions of configue >2.68 or automake >1.13 (i.e. later
62 # versions than those required by configure.ac):
63 diff --git a/contrib/libtests/pngvalid.c b/contrib/libtests/pngvalid.c
64 index 8852f87..60f23dc 100644
65 --- a/contrib/libtests/pngvalid.c
66 +++ b/contrib/libtests/pngvalid.c
67 @@ -258,7 +258,7 @@ make_four_random_bytes(png_uint_32* seed, png_bytep bytes)
68 make_random_bytes(seed, bytes, 4);
71 -#ifdef PNG_READ_SUPPORTED
72 +#if defined PNG_READ_SUPPORTED || defined PNG_WRITE_tRNS_SUPPORTED
74 randomize(void *pv, size_t size)
76 @@ -267,7 +267,9 @@ randomize(void *pv, size_t size)
79 #define RANDOMIZE(this) randomize(&(this), sizeof (this))
80 +#endif /* READ || WRITE_tRNS */
82 +#ifdef PNG_READ_SUPPORTED
84 random_mod(unsigned int max)
86 @@ -295,7 +297,8 @@ random_choice(void)
87 /* A numeric ID based on PNG file characteristics. The 'do_interlace' field
88 * simply records whether pngvalid did the interlace itself or whether it
89 * was done by libpng. Width and height must be less than 256. 'palette' is an
90 - * index of the palette to use for formats with a palette (0 otherwise.)
91 + * index of the palette to use for formats with a palette otherwise a boolean
92 + * indicating if a tRNS chunk was generated.
94 #define FILEID(col, depth, palette, interlace, width, height, do_interlace) \
95 ((png_uint_32)((col) + ((depth)<<3) + ((palette)<<8) + ((interlace)<<13) + \
96 @@ -316,12 +319,16 @@ standard_name(char *buffer, size_t bufsize, size_t pos, png_byte colour_type,
97 png_uint_32 w, png_uint_32 h, int do_interlace)
99 pos = safecat(buffer, bufsize, pos, colour_types[colour_type]);
101 + if (colour_type == 3) /* must have a palette */
103 pos = safecat(buffer, bufsize, pos, "[");
104 pos = safecatn(buffer, bufsize, pos, npalette);
105 pos = safecat(buffer, bufsize, pos, "]");
108 + else if (npalette != 0)
109 + pos = safecat(buffer, bufsize, pos, "+tRNS");
111 pos = safecat(buffer, bufsize, pos, " ");
112 pos = safecatn(buffer, bufsize, pos, bit_depth);
113 pos = safecat(buffer, bufsize, pos, " bit");
114 @@ -378,25 +385,32 @@ standard_name_from_id(char *buffer, size_t bufsize, size_t pos, png_uint_32 id)
117 next_format(png_bytep colour_type, png_bytep bit_depth,
118 - unsigned int* palette_number, int no_low_depth_gray)
119 + unsigned int* palette_number, int low_depth_gray, int tRNS)
124 - if (no_low_depth_gray)
127 + if (low_depth_gray)
135 - if (*colour_type == 3)
136 + if (*colour_type < 4/*no alpha channel*/)
138 - /* Add multiple palettes for colour type 3. */
139 - if (++*palette_number < PALETTE_COUNT(*bit_depth))
140 + /* Add multiple palettes for colour type 3, one image with tRNS
141 + * and one without for other non-alpha formats:
143 + unsigned int pn = ++*palette_number;
144 + png_byte ct = *colour_type;
146 + if (((ct == 0/*GRAY*/ || ct/*RGB*/ == 2) && tRNS && pn < 2) ||
147 + (ct == 3/*PALETTE*/ && pn < PALETTE_COUNT(*bit_depth)))
150 + /* No: next bit depth */
154 @@ -1959,6 +1973,7 @@ typedef struct png_modifier
156 /* Run tests on reading with a combination of transforms, */
157 unsigned int test_transform :1;
158 + unsigned int test_tRNS :1; /* Includes tRNS images */
160 /* When to use the use_input_precision option, this controls the gamma
161 * validation code checks. If set any value that is within the transformed
162 @@ -1990,6 +2005,16 @@ typedef struct png_modifier
163 unsigned int test_gamma_expand16 :1;
164 unsigned int test_exhaustive :1;
166 + /* Whether or not to run the low-bit-depth grayscale tests. This fail on
167 + * gamma images in some cases because of gross inaccuracies in the grayscale
168 + * gamma handling for low bit depth.
170 + unsigned int test_lbg :1;
171 + unsigned int test_lbg_gamma_threshold :1;
172 + unsigned int test_lbg_gamma_transform :1;
173 + unsigned int test_lbg_gamma_sbit :1;
174 + unsigned int test_lbg_gamma_composition :1;
176 unsigned int log :1; /* Log max error */
178 /* Buffer information, the buffer size limits the size of the chunks that can
179 @@ -2042,6 +2067,11 @@ modifier_init(png_modifier *pm)
180 pm->test_standard = 0;
182 pm->test_transform = 0;
183 +# ifdef PNG_WRITE_tRNS_SUPPORTED
188 pm->use_input_precision = 0;
189 pm->use_input_precision_sbit = 0;
190 pm->use_input_precision_16to8 = 0;
191 @@ -2054,6 +2084,11 @@ modifier_init(png_modifier *pm)
192 pm->test_gamma_background = 0;
193 pm->test_gamma_alpha_mode = 0;
194 pm->test_gamma_expand16 = 0;
196 + pm->test_lbg_gamma_threshold = 1;
197 + pm->test_lbg_gamma_transform = 1;
198 + pm->test_lbg_gamma_sbit = 1;
199 + pm->test_lbg_gamma_composition = 1;
200 pm->test_exhaustive = 0;
203 @@ -3192,6 +3227,45 @@ init_standard_palette(png_store *ps, png_structp pp, png_infop pi, int npalette,
207 +#ifdef PNG_WRITE_tRNS_SUPPORTED
209 +set_random_tRNS(png_structp pp, png_infop pi, PNG_CONST png_byte colour_type,
210 + PNG_CONST int bit_depth)
212 + /* To make this useful the tRNS color needs to match at least one pixel.
213 + * Random values are fine for gray, including the 16-bit case where we know
214 + * that the test image contains all the gray values. For RGB we need more
215 + * method as only 65536 different RGB values are generated.
218 + const png_uint_16 mask = (png_uint_16)((1U << bit_depth)-1);
222 + if (colour_type & 2/*RGB*/)
224 + if (bit_depth == 8)
226 + tRNS.blue = tRNS.red ^ tRNS.green;
228 + tRNS.green &= mask;
232 + else /* bit_depth == 16 */
234 + tRNS.green = (png_uint_16)(tRNS.red * 257);
235 + tRNS.blue = (png_uint_16)(tRNS.green * 17);
242 + png_set_tRNS(pp, pi, NULL, 0, &tRNS);
246 /* The number of passes is related to the interlace type. There was no libpng
247 * API to determine this prior to 1.5, so we need an inquiry function:
249 @@ -3525,6 +3599,11 @@ make_transform_image(png_store* PNG_CONST ps, png_byte PNG_CONST colour_type,
250 if (colour_type == 3) /* palette */
251 init_standard_palette(ps, pp, pi, 1U << bit_depth, 1/*do tRNS*/);
253 +# ifdef PNG_WRITE_tRNS_SUPPORTED
254 + else if (palette_number)
255 + set_random_tRNS(pp, pi, colour_type, bit_depth);
258 png_write_info(pp, pi);
260 if (png_get_rowbytes(pp, pi) !=
261 @@ -3598,19 +3677,20 @@ make_transform_image(png_store* PNG_CONST ps, png_byte PNG_CONST colour_type,
265 -make_transform_images(png_store *ps)
266 +make_transform_images(png_modifier *pm)
268 png_byte colour_type = 0;
269 png_byte bit_depth = 0;
270 unsigned int palette_number = 0;
272 /* This is in case of errors. */
273 - safecat(ps->test, sizeof ps->test, 0, "make standard images");
274 + safecat(pm->this.test, sizeof pm->this.test, 0, "make standard images");
276 /* Use next_format to enumerate all the combinations we test, including
277 - * generating multiple low bit depth palette images.
278 + * generating multiple low bit depth palette images. Non-A images (palette
279 + * and direct) are created with and without tRNS chunks.
281 - while (next_format(&colour_type, &bit_depth, &palette_number, 0))
282 + while (next_format(&colour_type, &bit_depth, &palette_number, 1, 1))
286 @@ -3621,7 +3701,7 @@ make_transform_images(png_store *ps)
288 standard_name(name, sizeof name, 0, colour_type, bit_depth,
289 palette_number, interlace_type, 0, 0, 0);
290 - make_transform_image(ps, colour_type, bit_depth, palette_number,
291 + make_transform_image(&pm->this, colour_type, bit_depth, palette_number,
292 interlace_type, name);
295 @@ -4287,6 +4367,7 @@ typedef struct standard_display
296 size_t cbRow; /* Bytes in a row of the output image */
297 int do_interlace; /* Do interlacing internally */
298 int is_transparent; /* Transparency information was present. */
299 + int has_tRNS; /* color type GRAY or RGB with a tRNS chunk. */
300 int speed; /* Doing a speed test */
301 int use_update_info;/* Call update_info, not start_image */
303 @@ -4619,14 +4700,14 @@ standard_info_part1(standard_display *dp, png_structp pp, png_infop pi)
305 dp->transparent.red = dp->transparent.green = dp->transparent.blue =
307 - dp->is_transparent = 1;
312 dp->transparent.red = trans_color->red;
313 dp->transparent.green = trans_color->green;
314 dp->transparent.blue = trans_color->blue;
315 - dp->is_transparent = 1;
320 @@ -5518,7 +5599,7 @@ image_pixel_add_alpha(image_pixel *this, PNG_CONST standard_display *display)
321 if (this->colour_type == PNG_COLOR_TYPE_GRAY)
323 if (this->bit_depth < 8)
324 - this->bit_depth = 8;
325 + this->bit_depth = this->sample_depth = 8;
329 @@ -5553,9 +5634,11 @@ image_pixel_add_alpha(image_pixel *this, PNG_CONST standard_display *display)
334 - this->colour_type = PNG_COLOR_TYPE_RGB_ALPHA;
339 + this->colour_type = PNG_COLOR_TYPE_RGB_ALPHA;
342 /* The error in the alpha is zero and the sBIT value comes from the
343 @@ -5848,8 +5931,9 @@ transform_info_imp(transform_display *dp, png_structp pp, png_infop pi)
344 /* If png_set_filler is in action then fake the output color type to include
345 * an alpha channel where appropriate.
347 - if (dp->output_bit_depth >= 8 && (dp->output_colour_type == PNG_COLOR_TYPE_RGB ||
348 - dp->output_colour_type == PNG_COLOR_TYPE_GRAY) && dp->this.filler)
349 + if (dp->output_bit_depth >= 8 &&
350 + (dp->output_colour_type == PNG_COLOR_TYPE_RGB ||
351 + dp->output_colour_type == PNG_COLOR_TYPE_GRAY) && dp->this.filler)
352 dp->output_colour_type |= 4;
354 /* Validate the combination of colour type and bit depth that we are getting
355 @@ -6372,6 +6456,13 @@ image_transform_png_set_tRNS_to_alpha_set(PNG_CONST image_transform *this,
356 transform_display *that, png_structp pp, png_infop pi)
358 png_set_tRNS_to_alpha(pp);
360 + /* If there was a tRNS chunk that would get expanded and add an alpha
361 + * channel is_transparent must be updated:
363 + if (that->this.has_tRNS)
364 + that->this.is_transparent = 1;
366 this->next->set(this->next, that, pp, pi);
369 @@ -6430,6 +6521,7 @@ image_transform_png_set_gray_to_rgb_set(PNG_CONST image_transform *this,
370 transform_display *that, png_structp pp, png_infop pi)
372 png_set_gray_to_rgb(pp);
373 + /* NOTE: this doesn't result in tRNS expansion. */
374 this->next->set(this->next, that, pp, pi);
377 @@ -6489,6 +6581,10 @@ image_transform_png_set_expand_set(PNG_CONST image_transform *this,
378 transform_display *that, png_structp pp, png_infop pi)
382 + if (that->this.has_tRNS)
383 + that->this.is_transparent = 1;
385 this->next->set(this->next, that, pp, pi);
388 @@ -6539,6 +6635,7 @@ image_transform_png_set_expand_gray_1_2_4_to_8_set(
391 png_set_expand_gray_1_2_4_to_8(pp);
392 + /* NOTE: don't expect this to expand tRNS */
393 this->next->set(this->next, that, pp, pi);
396 @@ -6570,6 +6667,11 @@ image_transform_png_set_expand_16_set(PNG_CONST image_transform *this,
397 transform_display *that, png_structp pp, png_infop pi)
399 png_set_expand_16(pp);
401 + /* NOTE: at present libpng does SET_EXPAND as well, so tRNS is expanded. */
402 + if (that->this.has_tRNS)
403 + that->this.is_transparent = 1;
405 this->next->set(this->next, that, pp, pi);
408 @@ -6940,14 +7042,14 @@ image_transform_png_set_rgb_to_gray_ini(PNG_CONST image_transform *this,
409 * When DIGITIZE is set because a pre-1.7 version of libpng is being
410 * tested allow a bigger slack.
412 - * NOTE: this magic number was determined by experiment to be 1.25.
413 - * There's no great merit to the value below, however it only affects
414 - * the limit used for checking for internal calculation errors, not
415 - * the actual limit imposed by pngvalid on the output errors.
416 + * NOTE: this magic number was determined by experiment to be about
417 + * 1.263. There's no great merit to the value below, however it only
418 + * affects the limit used for checking for internal calculation errors,
419 + * not the actual limit imposed by pngvalid on the output errors.
421 that->pm->limit += pow(
428 @@ -7111,7 +7213,8 @@ image_transform_png_set_rgb_to_gray_mod(PNG_CONST image_transform *this,
429 const unsigned int sample_depth = that->sample_depth;
430 const unsigned int calc_depth = (pm->assume_16_bit_calculations ? 16 :
432 - const unsigned int gamma_depth = (sample_depth == 16 ? 16 :
433 + const unsigned int gamma_depth = (sample_depth == 16 ?
435 (pm->assume_16_bit_calculations ? PNG_MAX_GAMMA_8 : sample_depth));
438 @@ -7125,56 +7228,73 @@ image_transform_png_set_rgb_to_gray_mod(PNG_CONST image_transform *this,
439 * will be identical after this operation if there is only one
440 * transform, feel free to delete the png_error checks on this below in
441 * the future (this is just me trying to ensure it works!)
443 + * Interval arithmetic is exact, but to implement it it must be
444 + * possible to control the floating point implementation rounding mode.
445 + * This cannot be done in ANSI-C, so instead I reduce the 'lo' values
446 + * by DBL_EPSILON and increase the 'hi' values by the same.
448 +# define DD(v,d,r) (digitize(v*(1-DBL_EPSILON), d, r) * (1-DBL_EPSILON))
449 +# define DU(v,d,r) (digitize(v*(1+DBL_EPSILON), d, r) * (1+DBL_EPSILON))
451 r = rlo = rhi = that->redf;
453 - rlo = digitize(rlo, calc_depth, 1/*round*/);
454 + rlo = DD(rlo, calc_depth, 1/*round*/);
456 - rhi = digitize(rhi, calc_depth, 1/*round*/);
457 + rhi = DU(rhi, calc_depth, 1/*round*/);
459 g = glo = ghi = that->greenf;
461 - glo = digitize(glo, calc_depth, 1/*round*/);
462 + glo = DD(glo, calc_depth, 1/*round*/);
464 - ghi = digitize(ghi, calc_depth, 1/*round*/);
465 + ghi = DU(ghi, calc_depth, 1/*round*/);
467 b = blo = bhi = that->bluef;
469 - blo = digitize(blo, calc_depth, 1/*round*/);
470 + blo = DD(blo, calc_depth, 1/*round*/);
472 - bhi = digitize(bhi, calc_depth, 1/*round*/);
473 + bhi = DU(bhi, calc_depth, 1/*round*/);
475 isgray = r==g && g==b;
479 PNG_CONST double power = 1/data.gamma;
480 - PNG_CONST double abse = calc_depth == 16 ? .5/65535 : .5/255;
481 + PNG_CONST double abse = .5/(sample_depth == 16 ? 65535 : 255);
483 - /* 'abse' is the absolute error permitted in linear calculations. It
484 - * is used here to capture the error permitted in the handling
485 - * (undoing) of the gamma encoding. Once again digitization occurs
486 - * to handle the upper and lower bounds of the values. This is
487 - * where the real errors are introduced.
488 + /* If a gamma calculation is done it is done using lookup tables of
489 + * precision gamma_depth, so the already digitized value above may
490 + * need to be further digitized here.
492 + if (gamma_depth != calc_depth)
494 + rlo = DD(rlo, gamma_depth, 0/*truncate*/);
495 + rhi = DU(rhi, gamma_depth, 0/*truncate*/);
496 + glo = DD(glo, gamma_depth, 0/*truncate*/);
497 + ghi = DU(ghi, gamma_depth, 0/*truncate*/);
498 + blo = DD(blo, gamma_depth, 0/*truncate*/);
499 + bhi = DU(bhi, gamma_depth, 0/*truncate*/);
502 + /* 'abse' is the error in the gamma table calculation itself. */
504 - rlo = digitize(pow(rlo, power)-abse, calc_depth, 1);
505 - rhi = digitize(pow(rhi, power)+abse, calc_depth, 1);
506 + rlo = DD(pow(rlo, power)-abse, calc_depth, 1);
507 + rhi = DU(pow(rhi, power)+abse, calc_depth, 1);
510 - glo = digitize(pow(glo, power)-abse, calc_depth, 1);
511 - ghi = digitize(pow(ghi, power)+abse, calc_depth, 1);
512 + glo = DD(pow(glo, power)-abse, calc_depth, 1);
513 + ghi = DU(pow(ghi, power)+abse, calc_depth, 1);
516 - blo = digitize(pow(blo, power)-abse, calc_depth, 1);
517 - bhi = digitize(pow(bhi, power)+abse, calc_depth, 1);
518 + blo = DD(pow(blo, power)-abse, calc_depth, 1);
519 + bhi = DU(pow(bhi, power)+abse, calc_depth, 1);
522 /* Now calculate the actual gray values. Although the error in the
523 * coefficients depends on whether they were specified on the command
524 * line (in which case truncation to 15 bits happened) or not (rounding
525 * was used) the maxium error in an individual coefficient is always
526 - * 1/32768, because even in the rounding case the requirement that
527 + * 2/32768, because even in the rounding case the requirement that
528 * coefficients add up to 32768 can cause a larger rounding error.
530 * The only time when rounding doesn't occur in 1.5.5 and later is when
531 @@ -7185,19 +7305,19 @@ image_transform_png_set_rgb_to_gray_mod(PNG_CONST image_transform *this,
534 PNG_CONST int do_round = data.gamma != 1 || calc_depth == 16;
535 - PNG_CONST double ce = 1. / 32768;
536 + PNG_CONST double ce = 2. / 32768;
538 - graylo = digitize(rlo * (data.red_coefficient-ce) +
539 + graylo = DD(rlo * (data.red_coefficient-ce) +
540 glo * (data.green_coefficient-ce) +
541 - blo * (data.blue_coefficient-ce), gamma_depth, do_round);
544 + blo * (data.blue_coefficient-ce), calc_depth, do_round);
545 + if (graylo > gray) /* always accept the right answer */
548 - grayhi = digitize(rhi * (data.red_coefficient+ce) +
549 + grayhi = DU(rhi * (data.red_coefficient+ce) +
550 ghi * (data.green_coefficient+ce) +
551 - bhi * (data.blue_coefficient+ce), gamma_depth, do_round);
554 + bhi * (data.blue_coefficient+ce), calc_depth, do_round);
559 /* And invert the gamma. */
560 @@ -7205,11 +7325,25 @@ image_transform_png_set_rgb_to_gray_mod(PNG_CONST image_transform *this,
562 PNG_CONST double power = data.gamma;
564 + /* And this happens yet again, shifting the values once more. */
565 + if (gamma_depth != sample_depth)
567 + rlo = DD(rlo, gamma_depth, 0/*truncate*/);
568 + rhi = DU(rhi, gamma_depth, 0/*truncate*/);
569 + glo = DD(glo, gamma_depth, 0/*truncate*/);
570 + ghi = DU(ghi, gamma_depth, 0/*truncate*/);
571 + blo = DD(blo, gamma_depth, 0/*truncate*/);
572 + bhi = DU(bhi, gamma_depth, 0/*truncate*/);
575 gray = pow(gray, power);
576 - graylo = digitize(pow(graylo, power), sample_depth, 1);
577 - grayhi = digitize(pow(grayhi, power), sample_depth, 1);
578 + graylo = DD(pow(graylo, power), sample_depth, 1);
579 + grayhi = DU(pow(grayhi, power), sample_depth, 1);
585 /* Now the error can be calculated.
587 * If r==g==b because there is no overall gamma correction libpng
588 @@ -7260,16 +7394,28 @@ image_transform_png_set_rgb_to_gray_mod(PNG_CONST image_transform *this,
590 /* There is no need to do the conversions to and from linear space,
591 * so the calculation should be a lot more accurate. There is a
592 - * built in 1/32768 error in the coefficients because they only have
593 - * 15 bits and are adjusted to make sure they add up to 32768, so
594 - * the result may have an additional error up to 1/32768. (Note
595 - * that adding the 1/32768 here avoids needing to increase the
596 - * global error limits to take this into account.)
597 + * built in error in the coefficients because they only have 15 bits
598 + * and are adjusted to make sure they add up to 32768. This
599 + * involves a integer calculation with truncation of the form:
601 + * ((int)(coefficient * 100000) * 32768)/100000
603 + * This is done to the red and green coefficients (the ones
604 + * provided to the API) then blue is calculated from them so the
605 + * result adds up to 32768. In the worst case this can result in
606 + * a -1 error in red and green and a +2 error in blue. Consequently
607 + * the worst case in the calculation below is 2/32768 error.
609 + * TODO: consider fixing this in libpng by rounding the calculation
610 + * limiting the error to 1/32768.
612 + * Handling this by adding 2/32768 here avoids needing to increase
613 + * the global error limits to take this into account.)
615 gray = r * data.red_coefficient + g * data.green_coefficient +
616 b * data.blue_coefficient;
617 err = re * data.red_coefficient + ge * data.green_coefficient +
618 - be * data.blue_coefficient + 1./32768 + gray * 5 * DBL_EPSILON;
619 + be * data.blue_coefficient + 2./32768 + gray * 5 * DBL_EPSILON;
623 @@ -7304,7 +7450,7 @@ image_transform_png_set_rgb_to_gray_mod(PNG_CONST image_transform *this,
624 * previously added input quantization error at this point.
626 gray = r * data.red_coefficient + g * data.green_coefficient +
627 - b * data.blue_coefficient - 1./32768 - out_qe;
628 + b * data.blue_coefficient - 2./32768 - out_qe;
632 @@ -7314,7 +7460,7 @@ image_transform_png_set_rgb_to_gray_mod(PNG_CONST image_transform *this,
635 grayhi = rhi * data.red_coefficient + ghi * data.green_coefficient +
636 - bhi * data.blue_coefficient + 1./32768 + out_qe;
637 + bhi * data.blue_coefficient + 2./32768 + out_qe;
638 grayhi *= (1 + 6 * DBL_EPSILON);
641 @@ -7429,6 +7575,9 @@ image_transform_png_set_background_set(PNG_CONST image_transform *this,
645 + if (that->this.has_tRNS)
646 + that->this.is_transparent = 1;
648 bit_depth = that->this.bit_depth;
651 @@ -7506,14 +7655,14 @@ image_transform_png_set_background_mod(PNG_CONST image_transform *this,
652 /* Remove the alpha type and set the alpha (not in that order.) */
656 - if (that->colour_type == PNG_COLOR_TYPE_RGB_ALPHA)
657 - that->colour_type = PNG_COLOR_TYPE_RGB;
658 - else if (that->colour_type == PNG_COLOR_TYPE_GRAY_ALPHA)
659 - that->colour_type = PNG_COLOR_TYPE_GRAY;
660 - /* PNG_COLOR_TYPE_PALETTE is not changed */
663 + if (that->colour_type == PNG_COLOR_TYPE_RGB_ALPHA)
664 + that->colour_type = PNG_COLOR_TYPE_RGB;
665 + else if (that->colour_type == PNG_COLOR_TYPE_GRAY_ALPHA)
666 + that->colour_type = PNG_COLOR_TYPE_GRAY;
667 + /* PNG_COLOR_TYPE_PALETTE is not changed */
669 this->next->mod(this->next, that, pp, display);
672 @@ -8301,7 +8450,8 @@ perform_transform_test(png_modifier *pm)
673 png_byte bit_depth = 0;
674 unsigned int palette_number = 0;
676 - while (next_format(&colour_type, &bit_depth, &palette_number, 0))
677 + while (next_format(&colour_type, &bit_depth, &palette_number, pm->test_lbg,
680 png_uint_32 counter = 0;
682 @@ -8604,7 +8754,9 @@ init_validate_info(validate_info *vi, gamma_display *dp, png_const_structp pp,
683 vi->outlog = outlog(dp->pm, in_depth, out_depth);
685 if ((dp->this.colour_type & PNG_COLOR_MASK_ALPHA) != 0 ||
686 - (dp->this.colour_type == 3 && dp->this.is_transparent))
687 + (dp->this.colour_type == 3 && dp->this.is_transparent) ||
688 + ((dp->this.colour_type == 0 || dp->this.colour_type == 2) &&
689 + dp->this.has_tRNS))
691 vi->do_background = dp->do_background;
693 @@ -8634,7 +8786,7 @@ init_validate_info(validate_info *vi, gamma_display *dp, png_const_structp pp,
694 vi->background_blue = b;
698 + else /* Do not expect any background processing */
699 vi->do_background = 0;
701 if (vi->do_background == 0)
702 @@ -9350,6 +9502,7 @@ gamma_image_validate(gamma_display *dp, png_const_structp pp,
704 PNG_CONST store_palette_entry *in_palette = dp->this.palette;
705 PNG_CONST int in_is_transparent = dp->this.is_transparent;
707 int out_npalette = -1;
708 int out_is_transparent = 0; /* Just refers to the palette case */
709 store_palette out_palette;
710 @@ -9365,6 +9518,7 @@ gamma_image_validate(gamma_display *dp, png_const_structp pp,
712 processing = (vi.gamma_correction > 0 && !dp->threshold_test)
713 || in_bd != out_bd || in_ct != out_ct || vi.do_background;
714 + process_tRNS = dp->this.has_tRNS && vi.do_background;
716 /* TODO: FIX THIS: MAJOR BUG! If the transformations all happen inside
717 * the palette there is no way of finding out, because libpng fails to
718 @@ -9403,8 +9557,8 @@ gamma_image_validate(gamma_display *dp, png_const_structp pp,
719 /* Handle input alpha - png_set_background will cause the output
720 * alpha to disappear so there is nothing to check.
722 - if ((in_ct & PNG_COLOR_MASK_ALPHA) != 0 || (in_ct == 3 &&
723 - in_is_transparent))
724 + if ((in_ct & PNG_COLOR_MASK_ALPHA) != 0 ||
725 + (in_ct == 3 && in_is_transparent))
727 PNG_CONST unsigned int input_alpha = in_ct == 3 ?
728 dp->this.palette[in_index].alpha :
729 @@ -9436,6 +9590,35 @@ gamma_image_validate(gamma_display *dp, png_const_structp pp,
733 + else if (process_tRNS)
735 + /* alpha needs to be set appropriately for this pixel, it is
736 + * currently 1 and needs to be 0 for an input pixel which matches
737 + * the values in tRNS.
742 + if (sample(std, in_ct, in_bd, x, 0, 0, 0) ==
743 + dp->this.transparent.red)
748 + if (sample(std, in_ct, in_bd, x, 0, 0, 0) ==
749 + dp->this.transparent.red &&
750 + sample(std, in_ct, in_bd, x, 1, 0, 0) ==
751 + dp->this.transparent.green &&
752 + sample(std, in_ct, in_bd, x, 2, 0, 0) ==
753 + dp->this.transparent.blue)
762 /* Handle grayscale or RGB components. */
763 if ((in_ct & PNG_COLOR_MASK_COLOR) == 0) /* grayscale */
764 (void)gamma_component_validate("gray", &vi,
765 @@ -9545,7 +9728,7 @@ gamma_test(png_modifier *pmIn, PNG_CONST png_byte colour_typeIn,
767 modification_reset(d.pm->modifications);
769 - /* Get a png_struct for writing the image. */
770 + /* Get a png_struct for reading the image. */
771 pp = set_modifier_for_read(d.pm, &pi, d.this.id, name);
772 standard_palette_init(&d.this);
774 @@ -9684,9 +9867,13 @@ perform_gamma_threshold_tests(png_modifier *pm)
775 /* Don't test more than one instance of each palette - it's pointless, in
776 * fact this test is somewhat excessive since libpng doesn't make this
777 * decision based on colour type or bit depth!
779 + * CHANGED: now test two palettes and, as a side effect, images with and
782 - while (next_format(&colour_type, &bit_depth, &palette_number, 1/*gamma*/))
783 - if (palette_number == 0)
784 + while (next_format(&colour_type, &bit_depth, &palette_number,
785 + pm->test_lbg_gamma_threshold, pm->test_tRNS))
786 + if (palette_number < 2)
788 double test_gamma = 1.0;
789 while (test_gamma >= .4)
790 @@ -9746,7 +9933,8 @@ static void perform_gamma_transform_tests(png_modifier *pm)
791 png_byte bit_depth = 0;
792 unsigned int palette_number = 0;
794 - while (next_format(&colour_type, &bit_depth, &palette_number, 1/*gamma*/))
795 + while (next_format(&colour_type, &bit_depth, &palette_number,
796 + pm->test_lbg_gamma_transform, pm->test_tRNS))
800 @@ -9776,7 +9964,8 @@ static void perform_gamma_sbit_tests(png_modifier *pm)
801 png_byte colour_type = 0, bit_depth = 0;
802 unsigned int npalette = 0;
804 - while (next_format(&colour_type, &bit_depth, &npalette, 1/*gamma*/))
805 + while (next_format(&colour_type, &bit_depth, &npalette,
806 + pm->test_lbg_gamma_sbit, pm->test_tRNS))
807 if ((colour_type & PNG_COLOR_MASK_ALPHA) == 0 &&
808 ((colour_type == 3 && sbit < 8) ||
809 (colour_type != 3 && sbit < bit_depth)))
810 @@ -9967,8 +10156,17 @@ static void gamma_composition_test(png_modifier *pm,
813 background.index = 193; /* rgb(193,193,193) to detect errors */
815 if (!(colour_type & PNG_COLOR_MASK_COLOR))
817 + /* Because, currently, png_set_background is always called with
818 + * 'need_expand' false in this case and because the gamma test itself
819 + * doesn't cause an expand to 8-bit for lower bit depths the colour must
820 + * be reduced to the correct range.
823 + background.gray &= (png_uint_16)((1U << bit_depth)-1);
825 /* Grayscale input, we do not convert to RGB (TBD), so we must set the
826 * background to gray - else libpng seems to fail.
828 @@ -10017,9 +10215,18 @@ perform_gamma_composition_tests(png_modifier *pm, int do_background,
830 /* Skip the non-alpha cases - there is no setting of a transparency colour at
833 - while (next_format(&colour_type, &bit_depth, &palette_number, 1/*gamma*/))
834 - if ((colour_type & PNG_COLOR_MASK_ALPHA) != 0)
836 + * TODO: incorrect; the palette case sets tRNS and, now RGB and gray do,
837 + * however the palette case fails miserably so is commented out below.
839 + while (next_format(&colour_type, &bit_depth, &palette_number,
840 + pm->test_lbg_gamma_composition, pm->test_tRNS))
841 + if ((colour_type & PNG_COLOR_MASK_ALPHA) != 0
842 +#if 0 /* TODO: FIXME */
843 + /*TODO: FIXME: this should work */
844 + || colour_type == 3
846 + || (colour_type != 3 && palette_number != 0))
850 @@ -10751,6 +10958,18 @@ int main(int argc, char **argv)
851 pm.ngammas = ARRAY_SIZE(gammas);
852 pm.ngamma_tests = 0; /* default to off */
854 + /* Low bit depth gray images don't do well in the gamma tests, until
855 + * this is fixed turn them off for some gamma cases:
857 +# ifdef PNG_WRITE_tRNS_SUPPORTED
861 + pm.test_lbg_gamma_threshold = 1;
862 + pm.test_lbg_gamma_transform = 0/*PNG_LIBPNG_VER >= 10700*/;
863 + pm.test_lbg_gamma_sbit = 1;
864 + pm.test_lbg_gamma_composition = 0;
866 /* And the test encodings */
867 pm.encodings = test_encodings;
868 pm.nencodings = ARRAY_SIZE(test_encodings);
869 @@ -10863,7 +11082,7 @@ int main(int argc, char **argv)
870 pm.test_gamma_transform = 1;
871 pm.test_gamma_sbit = 1;
872 pm.test_gamma_scale16 = 1;
873 - pm.test_gamma_background = 1;
874 + pm.test_gamma_background = 1; /* composition */
875 pm.test_gamma_alpha_mode = 1;
878 @@ -10912,6 +11131,24 @@ int main(int argc, char **argv)
879 else if (strcmp(*argv, "--noexpand16") == 0)
880 pm.test_gamma_expand16 = 0;
882 + else if (strcmp(*argv, "--low-depth-gray") == 0)
883 + pm.test_lbg = pm.test_lbg_gamma_threshold =
884 + pm.test_lbg_gamma_transform = pm.test_lbg_gamma_sbit =
885 + pm.test_lbg_gamma_composition = 1;
887 + else if (strcmp(*argv, "--nolow-depth-gray") == 0)
888 + pm.test_lbg = pm.test_lbg_gamma_threshold =
889 + pm.test_lbg_gamma_transform = pm.test_lbg_gamma_sbit =
890 + pm.test_lbg_gamma_composition = 0;
892 +# ifdef PNG_WRITE_tRNS_SUPPORTED
893 + else if (strcmp(*argv, "--tRNS") == 0)
897 + else if (strcmp(*argv, "--notRNS") == 0)
900 else if (strcmp(*argv, "--more-gammas") == 0)
901 pm.ngamma_tests = 3U;
903 @@ -11102,7 +11339,7 @@ int main(int argc, char **argv)
906 /* Make useful base images */
907 - make_transform_images(&pm.this);
908 + make_transform_images(&pm);
910 /* Perform the standard and gamma tests. */
911 if (pm.test_standard)