diff -ru4NwbB libpng-1.6.0beta33/arm/arm_init.c libpng-1.7.0alpha01/arm/arm_init.c --- libpng-1.6.0beta33/arm/arm_init.c 2012-12-15 07:25:15.067576000 -0600 +++ libpng-1.7.0alpha01/arm/arm_init.c 2012-12-14 23:20:14.649205000 -0600 @@ -2,9 +2,9 @@ /* arm_init.c - NEON optimised filter functions * * Copyright (c) 2012 Glenn Randers-Pehrson * Written by Mans Rullgard, 2011. - * Last changed in libpng 1.5.14 [(PENDING RELEASE)] + * Last changed in libpng 1.6.0 [(PENDING RELEASE)] * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer * and license in png.h diff -ru4NwbB libpng-1.6.0beta33/configure.ac libpng-1.7.0alpha01/configure.ac --- libpng-1.6.0beta33/configure.ac 2012-12-15 08:22:45.407827842 -0600 +++ libpng-1.7.0alpha01/configure.ac 2012-12-15 10:06:02.017991297 -0600 @@ -38,9 +38,9 @@ dnl stop configure from automagically running automake PNGLIB_VERSION=1.7.0alpha01 PNGLIB_MAJOR=1 -PNGLIB_MINOR=6 +PNGLIB_MINOR=7 PNGLIB_RELEASE=%RELEASE% dnl End of version number stuff diff -ru4NwbB libpng-1.6.0beta33/contrib/gregbook/Makefile.sgi libpng-1.7.0alpha01/contrib/gregbook/Makefile.sgi --- libpng-1.6.0beta33/contrib/gregbook/Makefile.sgi 2012-12-15 08:22:35.264896311 -0600 +++ libpng-1.7.0alpha01/contrib/gregbook/Makefile.sgi 2012-12-15 10:05:51.584937411 -0600 @@ -22,11 +22,11 @@ # macros -------------------------------------------------------------------- -PNGINC = -I/usr/local/include/libpng16 -PNGLIB = -L/usr/local/lib -lpng16 # dynamically linked against libpng -#PNGLIB = /usr/local/lib/libpng16.a # statically linked against libpng +PNGINC = -I/usr/local/include/libpng17 +PNGLIB = -L/usr/local/lib -lpng17 # dynamically linked against libpng +#PNGLIB = /usr/local/lib/libpng17.a # statically linked against libpng # or: #PNGINC = -I../.. #PNGLIB = -L../.. -lpng #PNGLIB = ../../libpng.a diff -ru4NwbB libpng-1.6.0beta33/contrib/gregbook/Makefile.unx libpng-1.7.0alpha01/contrib/gregbook/Makefile.unx --- libpng-1.6.0beta33/contrib/gregbook/Makefile.unx 2012-12-15 08:22:35.275834871 -0600 +++ libpng-1.7.0alpha01/contrib/gregbook/Makefile.unx 2012-12-15 10:05:51.595119407 -0600 @@ -25,16 +25,16 @@ # macros -------------------------------------------------------------------- #PNGDIR = /usr/local/lib -#PNGINC = -I/usr/local/include/libpng16 -#PNGLIBd = -L$(PNGDIR) -lpng16 # dynamically linked, installed libpng -#PNGLIBs = $(PNGDIR)/libpng16.a # statically linked, installed libpng +#PNGINC = -I/usr/local/include/libpng17 +#PNGLIBd = -L$(PNGDIR) -lpng17 # dynamically linked, installed libpng +#PNGLIBs = $(PNGDIR)/libpng17.a # statically linked, installed libpng # or: PNGDIR = ../..# this one is for libpng-x.y.z/contrib/gregbook builds #PNGDIR = ../libpng PNGINC = -I$(PNGDIR) -PNGLIBd = -Wl,-rpath,$(PNGDIR) -L$(PNGDIR) -lpng16 # dynamically linked +PNGLIBd = -Wl,-rpath,$(PNGDIR) -L$(PNGDIR) -lpng17 # dynamically linked PNGLIBs = $(PNGDIR)/libpng.a # statically linked, local libpng ZDIR = /usr/local/lib #ZDIR = /usr/lib64 diff -ru4NwbB libpng-1.6.0beta33/contrib/libtests/pngvalid.c libpng-1.7.0alpha01/contrib/libtests/pngvalid.c --- libpng-1.6.0beta33/contrib/libtests/pngvalid.c 2012-12-15 08:22:37.833553322 -0600 +++ libpng-1.7.0alpha01/contrib/libtests/pngvalid.c 2012-12-15 10:05:54.233679133 -0600 @@ -343,13 +343,18 @@ #define PALETTE_COUNT(bit_depth) ((bit_depth) > 4 ? 1U : 16U) static int next_format(png_bytep colour_type, png_bytep bit_depth, - unsigned int* palette_number) + unsigned int* palette_number, int no_low_depth_gray) { if (*bit_depth == 0) { - *colour_type = 0, *bit_depth = 1, *palette_number = 0; + *colour_type = 0; + if (no_low_depth_gray) + *bit_depth = 8; + else + *bit_depth = 1; + *palette_number = 0; return 1; } if (*colour_type == 3) @@ -1827,8 +1832,9 @@ double maxpc8; /* Percentage sample error 0..100% */ double maxout16; /* Maximum output value error */ double maxabs16; /* Absolute sample error 0..1 */ double maxcalc16;/* Absolute sample error 0..1 */ + double maxcalcG; /* Absolute sample error 0..1 */ double maxpc16; /* Percentage sample error 0..100% */ /* This is set by transforms that need to allow a higher limit, it is an * internal check on pngvalid to ensure that the calculated error limits are @@ -1869,9 +1875,14 @@ /* Run tests on reading with a combiniation of transforms, */ unsigned int test_transform :1; - /* When to use the use_input_precision option: */ + /* When to use the use_input_precision option, this controls the gamma + * validation code checks. If set any value that is within the transformed + * range input-.5 to input+.5 will be accepted, otherwise the value must be + * within the normal limits. It should not be necessary to set this; the + * result should always be exact within the permitted error limits. + */ unsigned int use_input_precision :1; unsigned int use_input_precision_sbit :1; unsigned int use_input_precision_16to8 :1; @@ -1879,10 +1890,10 @@ * precision, not the output precision. */ unsigned int calculations_use_input_precision :1; - /* If set assume that the calculations are done in 16 bits even if both input - * and output are 8 bit or less. + /* If set assume that the calculations are done in 16 bits even if the sample + * depth is 8 bits. */ unsigned int assume_16_bit_calculations :1; /* Which gamma tests to run: */ @@ -1935,8 +1946,9 @@ pm->repeat = 0; pm->test_uses_encoding = 0; pm->maxout8 = pm->maxpc8 = pm->maxabs8 = pm->maxcalc8 = 0; pm->maxout16 = pm->maxpc16 = pm->maxabs16 = pm->maxcalc16 = 0; + pm->maxcalcG = 0; pm->limit = 4E-3; pm->log8 = pm->log16 = 0; /* Means 'off' */ pm->error_gray_2 = pm->error_gray_4 = pm->error_gray_8 = 0; pm->error_gray_16 = pm->error_color_8 = pm->error_color_16 = 0; @@ -1949,8 +1961,9 @@ pm->use_input_precision = 0; pm->use_input_precision_sbit = 0; pm->use_input_precision_16to8 = 0; pm->calculations_use_input_precision = 0; + pm->assume_16_bit_calculations = 0; pm->test_gamma_threshold = 0; pm->test_gamma_transform = 0; pm->test_gamma_sbit = 0; pm->test_gamma_scale16 = 0; @@ -1963,28 +1976,35 @@ /* Rely on the memset for all the other fields - there are no pointers */ } #ifdef PNG_READ_TRANSFORMS_SUPPORTED + +/* This controls use of checks that explicitly know how libpng digitizes the + * samples in calculations; setting this circumvents simple error limit checking + * in the rgb_to_gray check, replacing it with an exact copy of the libpng 1.5 + * algorithm. + */ +#define DIGITIZE PNG_LIBPNG_VER < 10600 + /* If pm->calculations_use_input_precision is set then operations will happen - * with only 8 bit precision unless both the input and output bit depth are 16. + * with the precision of the input, not the precision of the output depth. * * If pm->assume_16_bit_calculations is set then even 8 bit calculations use 16 * bit precision. This only affects those of the following limits that pertain * to a calculation - not a digitization operation - unless the following API is * called directly. */ #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED -static double digitize(PNG_CONST png_modifier *pm, double value, - int sample_depth, int do_round) +#if DIGITIZE +static double digitize(double value, int depth, int do_round) { /* 'value' is in the range 0 to 1, the result is the same value rounded to a * multiple of the digitization factor - 8 or 16 bits depending on both the * sample depth and the 'assume' setting. Digitization is normally by * rounding and 'do_round' should be 1, if it is 0 the digitized value will * be truncated. */ - PNG_CONST unsigned int digitization_factor = - (pm->assume_16_bit_calculations || sample_depth == 16) ? 65535 : 255; + PNG_CONST unsigned int digitization_factor = (1U << depth) -1; /* Limiting the range is done as a convenience to the caller - it's easier to * do it once here than every time at the call site. */ @@ -1997,33 +2018,32 @@ if (do_round) value += .5; return floor(value)/digitization_factor; } #endif +#endif /* RGB_TO_GRAY */ -#if (defined PNG_READ_GAMMA_SUPPORTED) ||\ - (defined PNG_READ_RGB_TO_GRAY_SUPPORTED) +#ifdef PNG_READ_GAMMA_SUPPORTED static double abserr(PNG_CONST png_modifier *pm, int in_depth, int out_depth) { /* Absolute error permitted in linear values - affected by the bit depth of * the calculations. */ - if (pm->assume_16_bit_calculations || (out_depth == 16 && (in_depth == 16 || - !pm->calculations_use_input_precision))) + if (pm->assume_16_bit_calculations || + (pm->calculations_use_input_precision ? in_depth : out_depth) == 16) return pm->maxabs16; else return pm->maxabs8; } -#endif -#ifdef PNG_READ_GAMMA_SUPPORTED static double calcerr(PNG_CONST png_modifier *pm, int in_depth, int out_depth) { /* Error in the linear composition arithmetic - only relevant when * composition actually happens (0 < alpha < 1). */ - if (pm->assume_16_bit_calculations || (out_depth == 16 && (in_depth == 16 || - !pm->calculations_use_input_precision))) + if ((pm->calculations_use_input_precision ? in_depth : out_depth) == 16) return pm->maxcalc16; + else if (pm->assume_16_bit_calculations) + return pm->maxcalcG; else return pm->maxcalc8; } @@ -2031,10 +2051,10 @@ { /* Percentage error permitted in the linear values. Note that the specified * value is a percentage but this routine returns a simple number. */ - if (pm->assume_16_bit_calculations || (out_depth == 16 && (in_depth == 16 || - !pm->calculations_use_input_precision))) + if (pm->assume_16_bit_calculations || + (pm->calculations_use_input_precision ? in_depth : out_depth) == 16) return pm->maxpc16 * .01; else return pm->maxpc8 * .01; } @@ -2064,10 +2084,9 @@ if (out_depth == 4) return .90644-.5; - if (out_depth == 16 && (in_depth == 16 || - !pm->calculations_use_input_precision)) + if ((pm->calculations_use_input_precision ? in_depth : out_depth) == 16) return pm->maxout16; /* This is the case where the value was calculated at 8-bit precision then * scaled to 16 bits. @@ -2098,10 +2117,9 @@ return pm->log8; } - if (out_depth == 16 && (in_depth == 16 || - !pm->calculations_use_input_precision)) + if ((pm->calculations_use_input_precision ? in_depth : out_depth) == 16) { if (pm->log16 == 0) return 65536; @@ -2124,10 +2142,10 @@ */ static int output_quantization_factor(PNG_CONST png_modifier *pm, int in_depth, int out_depth) { - if (out_depth == 16 && in_depth != 16 - && pm->calculations_use_input_precision) + if (out_depth == 16 && in_depth != 16 && + pm->calculations_use_input_precision) return 257; else return 1; } @@ -3472,9 +3490,9 @@ /* Use next_format to enumerate all the combinations we test, including * generating multiple low bit depth palette images. */ - while (next_format(&colour_type, &bit_depth, &palette_number)) + while (next_format(&colour_type, &bit_depth, &palette_number, 0)) { int interlace_type; for (interlace_type = PNG_INTERLACE_NONE; @@ -5783,14 +5801,11 @@ png_byte in_sample_depth; memset(out_palette, 0x5e, sizeof out_palette); - /* assume-8-bit-calculations means assume that if the input has 8 bit - * (or less) samples and the output has 16 bit samples the calculations - * will be done with 8 bit precision, not 16. - * - * TODO: fix this in libpng; png_set_expand_16 should cause 16 bit - * calculations to be used throughout. + /* use-input-precision means assume that if the input has 8 bit (or less) + * samples and the output has 16 bit samples the calculations will be done + * with 8 bit precision, not 16. */ if (in_ct == PNG_COLOR_TYPE_PALETTE || in_bd < 16) in_sample_depth = 8; else @@ -5799,9 +5814,10 @@ if (sample_depth != 16 || in_sample_depth > 8 || !dp->pm->calculations_use_input_precision) digitization_error = .5; - /* Else errors are at 8 bit precision, scale .5 in 8 bits to the 16 bits: + /* Else calculations are at 8 bit precision, and the output actually + * consists of scaled 8-bit values, so scale .5 in 8 bits to the 16 bits: */ else digitization_error = .5 * 257; } @@ -6615,12 +6631,25 @@ if (data.gamma != 1) /* Use gamma tables */ { if (that->this.bit_depth == 16 || pm->assume_16_bit_calculations) { - /* The 16 bit case ends up producing a maximum error of about - * +/-5 in 65535, allow for +/-8 with the given gamma. - */ - that->pm->limit += pow(8./65535, data.gamma); + /* The computations have the form: + * + * r * rc + g * gc + b * bc + * + * Each component of which is +/-1/65535 from the gamma_to_1 table + * lookup, resulting in a base error of +/-6. The gamma_from_1 + * convertion adds another +/-2 in the 16-bit case and + * +/-(1<<(15-PNG_MAX_GAMMA_8)) in the 8-bit case. + */ + that->pm->limit += pow( +# if PNG_MAX_GAMMA_8 < 14 + (that->this.bit_depth == 16 ? 8. : + 6. + (1<<(15-PNG_MAX_GAMMA_8))) +# else + 8. +# endif + /65535, data.gamma); } else { @@ -6636,9 +6665,9 @@ { /* With no gamma correction a large error comes from the truncation of the * calculation in the 8 bit case, allow for that here. */ - if (that->this.bit_depth != 16) + if (that->this.bit_depth != 16 && !pm->assume_16_bit_calculations) that->pm->limit += 4E-3; } } @@ -6781,11 +6810,16 @@ if (that->colour_type == PNG_COLOR_TYPE_PALETTE) image_pixel_convert_PLTE(that); /* Image now has RGB channels... */ +# if DIGITIZE { PNG_CONST png_modifier *pm = display->pm; - PNG_CONST unsigned int sample_depth = that->sample_depth; + const unsigned int sample_depth = that->sample_depth; + const unsigned int calc_depth = (pm->assume_16_bit_calculations ? 16 : + sample_depth); + const unsigned int gamma_depth = (sample_depth == 16 ? 16 : + (pm->assume_16_bit_calculations ? PNG_MAX_GAMMA_8 : sample_depth)); int isgray; double r, g, b; double rlo, rhi, glo, ghi, blo, bhi, graylo, grayhi; @@ -6799,48 +6833,48 @@ * the future (this is just me trying to ensure it works!) */ r = rlo = rhi = that->redf; rlo -= that->rede; - rlo = digitize(pm, rlo, sample_depth, 1/*round*/); + rlo = digitize(rlo, calc_depth, 1/*round*/); rhi += that->rede; - rhi = digitize(pm, rhi, sample_depth, 1/*round*/); + rhi = digitize(rhi, calc_depth, 1/*round*/); g = glo = ghi = that->greenf; glo -= that->greene; - glo = digitize(pm, glo, sample_depth, 1/*round*/); + glo = digitize(glo, calc_depth, 1/*round*/); ghi += that->greene; - ghi = digitize(pm, ghi, sample_depth, 1/*round*/); + ghi = digitize(ghi, calc_depth, 1/*round*/); b = blo = bhi = that->bluef; blo -= that->bluee; - blo = digitize(pm, blo, sample_depth, 1/*round*/); + blo = digitize(blo, calc_depth, 1/*round*/); bhi += that->greene; - bhi = digitize(pm, bhi, sample_depth, 1/*round*/); + bhi = digitize(bhi, calc_depth, 1/*round*/); isgray = r==g && g==b; if (data.gamma != 1) { PNG_CONST double power = 1/data.gamma; - PNG_CONST double abse = abserr(pm, sample_depth, sample_depth); + PNG_CONST double abse = calc_depth == 16 ? .5/65535 : .5/255; /* 'abse' is the absolute error permitted in linear calculations. It * is used here to capture the error permitted in the handling * (undoing) of the gamma encoding. Once again digitization occurs * to handle the upper and lower bounds of the values. This is * where the real errors are introduced. */ r = pow(r, power); - rlo = digitize(pm, pow(rlo, power)-abse, sample_depth, 1); - rhi = digitize(pm, pow(rhi, power)+abse, sample_depth, 1); + rlo = digitize(pow(rlo, power)-abse, calc_depth, 1); + rhi = digitize(pow(rhi, power)+abse, calc_depth, 1); g = pow(g, power); - glo = digitize(pm, pow(glo, power)-abse, sample_depth, 1); - ghi = digitize(pm, pow(ghi, power)+abse, sample_depth, 1); + glo = digitize(pow(glo, power)-abse, calc_depth, 1); + ghi = digitize(pow(ghi, power)+abse, calc_depth, 1); b = pow(b, power); - blo = digitize(pm, pow(blo, power)-abse, sample_depth, 1); - bhi = digitize(pm, pow(bhi, power)+abse, sample_depth, 1); + blo = digitize(pow(blo, power)-abse, calc_depth, 1); + bhi = digitize(pow(bhi, power)+abse, calc_depth, 1); } /* Now calculate the actual gray values. Although the error in the * coefficients depends on whether they were specified on the command @@ -6855,20 +6889,20 @@ gray = r * data.red_coefficient + g * data.green_coefficient + b * data.blue_coefficient; { - PNG_CONST int do_round = data.gamma != 1 || sample_depth == 16; + PNG_CONST int do_round = data.gamma != 1 || calc_depth == 16; PNG_CONST double ce = 1. / 32768; - graylo = digitize(pm, rlo * (data.red_coefficient-ce) + + graylo = digitize(rlo * (data.red_coefficient-ce) + glo * (data.green_coefficient-ce) + - blo * (data.blue_coefficient-ce), sample_depth, do_round); + blo * (data.blue_coefficient-ce), gamma_depth, do_round); if (graylo <= 0) graylo = 0; - grayhi = digitize(pm, rhi * (data.red_coefficient+ce) + + grayhi = digitize(rhi * (data.red_coefficient+ce) + ghi * (data.green_coefficient+ce) + - bhi * (data.blue_coefficient+ce), sample_depth, do_round); + bhi * (data.blue_coefficient+ce), gamma_depth, do_round); if (grayhi >= 1) grayhi = 1; } @@ -6877,10 +6911,10 @@ { PNG_CONST double power = data.gamma; gray = pow(gray, power); - graylo = digitize(pm, pow(graylo, power), sample_depth, 1); - grayhi = digitize(pm, pow(grayhi, power), sample_depth, 1); + graylo = digitize(pow(graylo, power), sample_depth, 1); + grayhi = digitize(pow(grayhi, power), sample_depth, 1); } /* Now the error can be calculated. * @@ -6896,22 +6930,130 @@ if (fabs(gray - graylo) > err) err = fabs(graylo-gray); /* Check that this worked: */ - if (err > display->pm->limit) + if (err > pm->limit) { size_t pos = 0; char buffer[128]; pos = safecat(buffer, sizeof buffer, pos, "rgb_to_gray error "); pos = safecatd(buffer, sizeof buffer, pos, err, 6); pos = safecat(buffer, sizeof buffer, pos, " exceeds limit "); - pos = safecatd(buffer, sizeof buffer, pos, - display->pm->limit, 6); + pos = safecatd(buffer, sizeof buffer, pos, pm->limit, 6); png_error(pp, buffer); } } } +# else /* DIGITIZE */ + { + double r = that->redf; + double re = that->rede; + double g = that->greenf; + double ge = that->greene; + double b = that->bluef; + double be = that->bluee; + + /* The true gray case involves no math. */ + if (r == g && r == b) + { + gray = r; + err = re; + if (err < ge) err = ge; + if (err < be) err = be; + } + + else if (data.gamma == 1) + { + /* There is no need to do the convertions to and from linear space, + * so the calculation should be a lot more accurate. There is a + * built in 1/32768 error in the coefficients because they only have + * 15 bits and are adjusted to make sure they add up to 32768, so + * the result may have an additional error up to 1/32768. (Note + * that adding the 1/32768 here avoids needing to increase the + * global error limits to take this into account.) + */ + gray = r * data.red_coefficient + g * data.green_coefficient + + b * data.blue_coefficient; + err = re * data.red_coefficient + ge * data.green_coefficient + + be * data.blue_coefficient + 1./32768 + gray * 5 * DBL_EPSILON; + } + + else + { + /* The calculation happens in linear space, and this produces much + * wider errors in the encoded space. These are handled here by + * factoring the errors in to the calculation. There are two table + * lookups in the calculation and each introduces a quantization + * error defined by the table size. + */ + PNG_CONST png_modifier *pm = display->pm; + double in_qe = (that->sample_depth > 8 ? .5/65535 : .5/255); + double out_qe = (that->sample_depth > 8 ? .5/65535 : + (pm->assume_16_bit_calculations ? .5/(1< 1) rhi = 1; + r -= re + in_qe; if (r < 0) r = 0; + ghi = g + ge + in_qe; if (ghi > 1) ghi = 1; + g -= ge + in_qe; if (g < 0) g = 0; + bhi = b + be + in_qe; if (bhi > 1) bhi = 1; + b -= be + in_qe; if (b < 0) b = 0; + + r = pow(r, g1)*(1-DBL_EPSILON); rhi = pow(rhi, g1)*(1+DBL_EPSILON); + g = pow(g, g1)*(1-DBL_EPSILON); ghi = pow(ghi, g1)*(1+DBL_EPSILON); + b = pow(b, g1)*(1-DBL_EPSILON); bhi = pow(bhi, g1)*(1+DBL_EPSILON); + + /* Work out the lower and upper bounds for the gray value in the + * encoded space, then work out an average and error. Remove the + * previously added input quantization error at this point. + */ + gray = r * data.red_coefficient + g * data.green_coefficient + + b * data.blue_coefficient - 1./32768 - out_qe; + if (gray <= 0) + gray = 0; + else + { + gray *= (1 - 6 * DBL_EPSILON); + gray = pow(gray, data.gamma) * (1-DBL_EPSILON); + } + + grayhi = rhi * data.red_coefficient + ghi * data.green_coefficient + + bhi * data.blue_coefficient + 1./32768 + out_qe; + grayhi *= (1 + 6 * DBL_EPSILON); + if (grayhi >= 1) + grayhi = 1; + else + grayhi = pow(grayhi, data.gamma) * (1+DBL_EPSILON); + + err = (grayhi - gray) / 2; + gray = (grayhi + gray) / 2; + + if (err <= in_qe) + err = gray * DBL_EPSILON; + + else + err -= in_qe; + + /* Validate that the error is within limits (this has caused + * problems before, it's much easier to detect them here.) + */ + if (err > pm->limit) + { + size_t pos = 0; + char buffer[128]; + + pos = safecat(buffer, sizeof buffer, pos, "rgb_to_gray error "); + pos = safecatd(buffer, sizeof buffer, pos, err, 6); + pos = safecat(buffer, sizeof buffer, pos, " exceeds limit "); + pos = safecatd(buffer, sizeof buffer, pos, pm->limit, 6); + png_error(pp, buffer); + } + } + } +# endif /* !DIGITIZE */ that->bluef = that->greenf = that->redf = gray; that->bluee = that->greene = that->rede = err; @@ -6958,9 +7100,9 @@ * png_set_background_fixed(png_structp, png_const_color_16p background_color, * int background_gamma_code, int need_expand, * png_fixed_point background_gamma) * - * As with rgb_to_gray this ignores the gamma (at present.) + * This ignores the gamma (at present.) */ #define data ITDATA(background) static image_pixel data; @@ -6969,8 +7111,9 @@ transform_display *that, png_structp pp, png_infop pi) { png_byte colour_type, bit_depth; png_byte random_bytes[8]; /* 8 bytes - 64 bits - the biggest pixel */ + int expand; png_color_16 back; /* We need a background colour, because we don't know exactly what transforms * have been set we have to supply the colour in the original file format and @@ -6986,12 +7129,16 @@ if (colour_type == 3) { colour_type = PNG_COLOR_TYPE_RGB; bit_depth = 8; + expand = 0; /* passing in an RGB not a pixel index */ } else + { bit_depth = that->this.bit_depth; + expand = 1; + } image_pixel_init(&data, random_bytes, colour_type, bit_depth, 0/*x*/, 0/*unused: palette*/); @@ -7010,13 +7157,11 @@ else back.gray = (png_uint_16)data.red; # ifdef PNG_FLOATING_POINT_SUPPORTED - png_set_background(pp, &back, PNG_BACKGROUND_GAMMA_FILE, 1/*need expand*/, - 0); + png_set_background(pp, &back, PNG_BACKGROUND_GAMMA_FILE, expand, 0); # else - png_set_background_fixed(pp, &back, PNG_BACKGROUND_GAMMA_FILE, - 1/*need expand*/, 0); + png_set_background_fixed(pp, &back, PNG_BACKGROUND_GAMMA_FILE, expand, 0); # endif this->next->set(this->next, that, pp, pi); } @@ -7346,9 +7491,9 @@ png_byte colour_type = 0; png_byte bit_depth = 0; unsigned int palette_number = 0; - while (next_format(&colour_type, &bit_depth, &palette_number)) + while (next_format(&colour_type, &bit_depth, &palette_number, 0)) { png_uint_32 counter = 0; size_t base_pos; char name[64]; @@ -8031,16 +8176,27 @@ /* pass is set at this point if either of the tests above would have * passed. Don't do these additional tests here - just log the * original [es_lo..es_hi] values. */ - if (pass == 0 && vi->use_input_precision) + if (pass == 0 && vi->use_input_precision && vi->dp->sbit) { /* Ok, something is wrong - this actually happens in current libpng * 16-to-8 processing. Assume that the input value (id, adjusted * for sbit) can be anywhere between value-.5 and value+.5 - quite a * large range if sbit is low. + * + * NOTE: at present because the libpng gamma table stuff has been + * changed to use a rounding algorithm to correct errors in 8-bit + * calculations the precise sbit calculation (a shift) has been + * lost. This can result in up to a +/-1 error in the presence of + * an sbit less than the bit depth. */ - double tmp = (isbit - .5)/sbit_max; +# if PNG_LIBPNG_VER < 10600 +# define SBIT_ERROR .5 +# else +# define SBIT_ERROR 1. +# endif + double tmp = (isbit - SBIT_ERROR)/sbit_max; if (tmp <= 0) tmp = 0; @@ -8057,12 +8213,12 @@ if (is_lo < 0) is_lo = 0; - tmp = (isbit + .5)/sbit_max; + tmp = (isbit + SBIT_ERROR)/sbit_max; - if (tmp <= 0) - tmp = 0; + if (tmp >= 1) + tmp = 1; else if (alpha >= 0 && vi->file_inverse > 0 && tmp < 1) tmp = pow(tmp, vi->file_inverse); @@ -8377,9 +8533,9 @@ * * Because there is limited precision in the input it is arguable that * an acceptable result is any valid result from input-.5 to input+.5. * The basic tests below do not do this, however if 'use_input_precision' - * is set a subsequent test is performed below. + * is set a subsequent test is performed above. */ PNG_CONST unsigned int samples_per_pixel = (out_ct & 2U) ? 3U : 1U; int processing; png_uint_32 y; @@ -8719,9 +8875,9 @@ /* Don't test more than one instance of each palette - it's pointless, in * fact this test is somewhat excessive since libpng doesn't make this * decision based on colour type or bit depth! */ - while (next_format(&colour_type, &bit_depth, &palette_number)) + while (next_format(&colour_type, &bit_depth, &palette_number, 1/*gamma*/)) if (palette_number == 0) { double test_gamma = 1.0; while (test_gamma >= .4) @@ -8780,9 +8936,9 @@ png_byte colour_type = 0; png_byte bit_depth = 0; unsigned int palette_number = 0; - while (next_format(&colour_type, &bit_depth, &palette_number)) + while (next_format(&colour_type, &bit_depth, &palette_number, 1/*gamma*/)) { unsigned int i, j; for (i=0; ingamma_tests; ++i) for (j=0; jngamma_tests; ++j) @@ -8810,9 +8966,9 @@ { png_byte colour_type = 0, bit_depth = 0; unsigned int npalette = 0; - while (next_format(&colour_type, &bit_depth, &npalette)) + while (next_format(&colour_type, &bit_depth, &npalette, 1/*gamma*/)) if ((colour_type & PNG_COLOR_MASK_ALPHA) == 0 && ((colour_type == 3 && sbit < 8) || (colour_type != 3 && sbit < bit_depth))) { @@ -8845,8 +9001,9 @@ { # ifndef PNG_MAX_GAMMA_8 # define PNG_MAX_GAMMA_8 11 # endif +# define SBIT_16_TO_8 PNG_MAX_GAMMA_8 /* Include the alpha cases here. Note that sbit matches the internal value * used by the library - otherwise we will get spurious errors from the * internal sbit style approximation. * @@ -8862,30 +9019,30 @@ if (i != j && fabs(pm->gammas[j]/pm->gammas[i]-1) >= PNG_GAMMA_THRESHOLD) { gamma_transform_test(pm, 0, 16, 0, pm->interlace_type, - 1/pm->gammas[i], pm->gammas[j], PNG_MAX_GAMMA_8, + 1/pm->gammas[i], pm->gammas[j], SBIT_16_TO_8, pm->use_input_precision_16to8, 1 /*scale16*/); if (fail(pm)) return; gamma_transform_test(pm, 2, 16, 0, pm->interlace_type, - 1/pm->gammas[i], pm->gammas[j], PNG_MAX_GAMMA_8, + 1/pm->gammas[i], pm->gammas[j], SBIT_16_TO_8, pm->use_input_precision_16to8, 1 /*scale16*/); if (fail(pm)) return; gamma_transform_test(pm, 4, 16, 0, pm->interlace_type, - 1/pm->gammas[i], pm->gammas[j], PNG_MAX_GAMMA_8, + 1/pm->gammas[i], pm->gammas[j], SBIT_16_TO_8, pm->use_input_precision_16to8, 1 /*scale16*/); if (fail(pm)) return; gamma_transform_test(pm, 6, 16, 0, pm->interlace_type, - 1/pm->gammas[i], pm->gammas[j], PNG_MAX_GAMMA_8, + 1/pm->gammas[i], pm->gammas[j], SBIT_16_TO_8, pm->use_input_precision_16to8, 1 /*scale16*/); if (fail(pm)) return; @@ -9029,9 +9186,9 @@ /* Skip the non-alpha cases - there is no setting of a transparency colour at * present. */ - while (next_format(&colour_type, &bit_depth, &palette_number)) + while (next_format(&colour_type, &bit_depth, &palette_number, 1/*gamma*/)) if ((colour_type & PNG_COLOR_MASK_ALPHA) != 0) { unsigned int i, j; @@ -9051,33 +9208,48 @@ static void init_gamma_errors(png_modifier *pm) { - pm->error_gray_2 = pm->error_gray_4 = pm->error_gray_8 = 0; - pm->error_color_8 = 0; - pm->error_indexed = 0; - pm->error_gray_16 = pm->error_color_16 = 0; + /* Use -1 to catch tests that were not actually run */ + pm->error_gray_2 = pm->error_gray_4 = pm->error_gray_8 = -1.; + pm->error_color_8 = -1.; + pm->error_indexed = -1.; + pm->error_gray_16 = pm->error_color_16 = -1.; +} + +static void +print_one(const char *leader, double err) +{ + if (err != -1.) + printf(" %s %.5f\n", leader, err); } static void -summarize_gamma_errors(png_modifier *pm, png_const_charp who, int low_bit_depth) +summarize_gamma_errors(png_modifier *pm, png_const_charp who, int low_bit_depth, + int indexed) { + fflush(stderr); + if (who) - printf("Gamma correction with %s:\n", who); + printf("\nGamma correction with %s:\n", who); + + else + printf("\nBasic gamma correction:\n"); if (low_bit_depth) { - printf(" 2 bit gray: %.5f\n", pm->error_gray_2); - printf(" 4 bit gray: %.5f\n", pm->error_gray_4); - printf(" 8 bit gray: %.5f\n", pm->error_gray_8); - printf(" 8 bit color: %.5f\n", pm->error_color_8); - printf(" indexed: %.5f\n", pm->error_indexed); + print_one(" 2 bit gray: ", pm->error_gray_2); + print_one(" 4 bit gray: ", pm->error_gray_4); + print_one(" 8 bit gray: ", pm->error_gray_8); + print_one(" 8 bit color:", pm->error_color_8); + if (indexed) + print_one(" indexed: ", pm->error_indexed); } -#ifdef DO_16BIT - printf(" 16 bit gray: %.5f\n", pm->error_gray_16); - printf(" 16 bit color: %.5f\n", pm->error_color_16); -#endif + print_one("16 bit gray: ", pm->error_gray_16); + print_one("16 bit color:", pm->error_color_16); + + fflush(stdout); } static void perform_gamma_test(png_modifier *pm, int summary) @@ -9101,20 +9273,11 @@ /* Now some real transforms. */ if (pm->test_gamma_transform) { - init_gamma_errors(pm); - /*TODO: remove this. Necessary because the current libpng - * implementation works in 8 bits: - */ - if (pm->test_gamma_expand16) - pm->calculations_use_input_precision = 1; - perform_gamma_transform_tests(pm); - if (!calculations_use_input_precision) - pm->calculations_use_input_precision = 0; - if (summary) { + fflush(stderr); printf("Gamma correction error summary\n\n"); printf("The printed value is the maximum error in the pixel values\n"); printf("calculated by the libpng gamma correction code. The error\n"); printf("is calculated as the difference between the output pixel\n"); @@ -9124,12 +9287,27 @@ printf("Expect this value to be less than .5 for 8 bit formats,\n"); printf("less than 1 for formats with fewer than 8 bits and a small\n"); printf("number (typically less than 5) for the 16 bit formats.\n"); printf("For performance reasons the value for 16 bit formats\n"); - printf("increases when the image file includes an sBIT chunk.\n\n"); - - summarize_gamma_errors(pm, 0/*who*/, 1); + printf("increases when the image file includes an sBIT chunk.\n"); + fflush(stdout); } + + init_gamma_errors(pm); + /*TODO: remove this. Necessary because the current libpng + * implementation works in 8 bits: + */ + if (pm->test_gamma_expand16) + pm->calculations_use_input_precision = 1; + perform_gamma_transform_tests(pm); + if (!calculations_use_input_precision) + pm->calculations_use_input_precision = 0; + + if (summary) + summarize_gamma_errors(pm, 0/*who*/, 1/*low bit depth*/, 1/*indexed*/); + + if (fail(pm)) + return; } /* The sbit tests produce much larger errors: */ if (pm->test_gamma_sbit) @@ -9137,9 +9315,12 @@ init_gamma_errors(pm); perform_gamma_sbit_tests(pm); if (summary) - summarize_gamma_errors(pm, "sBIT", pm->sbitlow < 8U); + summarize_gamma_errors(pm, "sBIT", pm->sbitlow < 8U, 1/*indexed*/); + + if (fail(pm)) + return; } #ifdef DO_16BIT /* Should be READ_16BIT_SUPPORTED */ if (pm->test_gamma_scale16) @@ -9149,12 +9330,17 @@ perform_gamma_scale16_tests(pm); if (summary) { - printf("Gamma correction with 16 to 8 bit reduction:\n"); + fflush(stderr); + printf("\nGamma correction with 16 to 8 bit reduction:\n"); printf(" 16 bit gray: %.5f\n", pm->error_gray_16); printf(" 16 bit color: %.5f\n", pm->error_color_16); + fflush(stdout); } + + if (fail(pm)) + return; } #endif #ifdef PNG_READ_BACKGROUND_SUPPORTED @@ -9176,9 +9362,12 @@ pm->calculations_use_input_precision = 0; pm->maxout8 = maxout8; if (summary) - summarize_gamma_errors(pm, "background", 1); + summarize_gamma_errors(pm, "background", 1, 0/*indexed*/); + + if (fail(pm)) + return; } #endif #ifdef PNG_READ_ALPHA_MODE_SUPPORTED @@ -9201,9 +9390,12 @@ if (!calculations_use_input_precision) pm->calculations_use_input_precision = 0; if (summary) - summarize_gamma_errors(pm, "alpha mode", 1); + summarize_gamma_errors(pm, "alpha mode", 1, 0/*indexed*/); + + if (fail(pm)) + return; } #endif } #endif /* PNG_READ_GAMMA_SUPPORTED */ @@ -9709,8 +9901,24 @@ /* Default to error on warning: */ pm.this.treat_warnings_as_errors = 1; + /* Default assume_16_bit_calculations appropriately; this tells the checking + * code that 16-bit arithmetic is used for 8-bit samples when it would make a + * difference. + * + * TODO: IMPORTANT; set to '>= 10600' below to enable development, change + * this to the correct value before release! + */ + pm.assume_16_bit_calculations = PNG_LIBPNG_VER >= 10600; + + /* Currently 16 bit expansion happens at the end of the pipeline, so the + * calculations are done in the input bit depth not the output. + * + * TODO: fix this + */ + pm.calculations_use_input_precision = 1U; + /* Store the test gammas */ pm.gammas = gammas; pm.ngammas = (sizeof gammas) / (sizeof gammas[0]); pm.ngamma_tests = 0; /* default to off */ @@ -9719,15 +9927,18 @@ pm.encodings = test_encodings; pm.nencodings = (sizeof test_encodings) / (sizeof test_encodings[0]); pm.sbitlow = 8U; /* because libpng doesn't do sBIT below 8! */ + /* The following allows results to pass if they correspond to anything in the * transformed range [input-.5,input+.5]; this is is required because of the - * way libpng treates the 16_TO_8 flag when building the gamma tables. + * way libpng treates the 16_TO_8 flag when building the gamma tables in + * releases up to 1.6.0. * * TODO: review this */ pm.use_input_precision_16to8 = 1U; + pm.use_input_precision_sbit = 1U; /* because libpng now rounds sBIT */ /* Some default values (set the behavior for 'make check' here). * These values simply control the maximum error permitted in the gamma * transformations. The practial limits for human perception are described @@ -9736,13 +9947,14 @@ * images can never be good enough, regardless of encoding. */ pm.maxout8 = .1; /* Arithmetic error in *encoded* value */ pm.maxabs8 = .00005; /* 1/20000 */ - pm.maxcalc8 = .004; /* +/-1 in 8 bits for compose errors */ + pm.maxcalc8 = 1./255; /* +/-1 in 8 bits for compose errors */ pm.maxpc8 = .499; /* I.e., .499% fractional error */ pm.maxout16 = .499; /* Error in *encoded* value */ pm.maxabs16 = .00005;/* 1/20000 */ - pm.maxcalc16 =.000015;/* +/-1 in 16 bits for compose errors */ + pm.maxcalc16 =1./65535;/* +/-1 in 16 bits for compose errors */ + pm.maxcalcG = 1./((1<test_uses_encoding = 0; + pm->maxout8 = pm->maxpc8 = pm->maxabs8 = pm->maxcalc8 = 0; + pm->maxout16 = pm->maxpc16 = pm->maxabs16 = pm->maxcalc16 = 0; + pm->limit = 4E-3; + pm->log8 = pm->log16 = 0; /* Means 'off' */ + pm->error_gray_2 = pm->error_gray_4 = pm->error_gray_8 = 0; +--- 1947,1953 ---- + pm->test_uses_encoding = 0; + pm->maxout8 = pm->maxpc8 = pm->maxabs8 = pm->maxcalc8 = 0; + pm->maxout16 = pm->maxpc16 = pm->maxabs16 = pm->maxcalc16 = 0; ++ pm->maxcalcG = 0; + pm->limit = 4E-3; + pm->log8 = pm->log16 = 0; /* Means 'off' */ + pm->error_gray_2 = pm->error_gray_4 = pm->error_gray_8 = 0; +*************** +*** 1950,1955 **** + pm->use_input_precision_sbit = 0; + pm->use_input_precision_16to8 = 0; + pm->calculations_use_input_precision = 0; + pm->test_gamma_threshold = 0; + pm->test_gamma_transform = 0; + pm->test_gamma_sbit = 0; +--- 1962,1968 ---- + pm->use_input_precision_sbit = 0; + pm->use_input_precision_16to8 = 0; + pm->calculations_use_input_precision = 0; ++ pm->assume_16_bit_calculations = 0; + pm->test_gamma_threshold = 0; + pm->test_gamma_transform = 0; + pm->test_gamma_sbit = 0; +*************** +*** 1964,1971 **** + } + + #ifdef PNG_READ_TRANSFORMS_SUPPORTED + /* If pm->calculations_use_input_precision is set then operations will happen +- * with only 8 bit precision unless both the input and output bit depth are 16. + * + * If pm->assume_16_bit_calculations is set then even 8 bit calculations use 16 + * bit precision. This only affects those of the following limits that pertain +--- 1977,1992 ---- + } + + #ifdef PNG_READ_TRANSFORMS_SUPPORTED ++ ++ /* This controls use of checks that explicitly know how libpng digitizes the ++ * samples in calculations; setting this circumvents simple error limit checking ++ * in the rgb_to_gray check, replacing it with an exact copy of the libpng 1.5 ++ * algorithm. ++ */ ++ #define DIGITIZE PNG_LIBPNG_VER < 10600 ++ + /* If pm->calculations_use_input_precision is set then operations will happen ++ * with the precision of the input, not the precision of the output depth. + * + * If pm->assume_16_bit_calculations is set then even 8 bit calculations use 16 + * bit precision. This only affects those of the following limits that pertain +*************** +*** 1973,1980 **** + * called directly. + */ + #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +- static double digitize(PNG_CONST png_modifier *pm, double value, +- int sample_depth, int do_round) + { + /* 'value' is in the range 0 to 1, the result is the same value rounded to a + * multiple of the digitization factor - 8 or 16 bits depending on both the +--- 1994,2001 ---- + * called directly. + */ + #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED ++ #if DIGITIZE ++ static double digitize(double value, int depth, int do_round) + { + /* 'value' is in the range 0 to 1, the result is the same value rounded to a + * multiple of the digitization factor - 8 or 16 bits depending on both the +*************** +*** 1982,1995 **** + * rounding and 'do_round' should be 1, if it is 0 the digitized value will + * be truncated. + */ +- PNG_CONST unsigned int digitization_factor = +- (pm->assume_16_bit_calculations || sample_depth == 16) ? 65535 : 255; + + /* Limiting the range is done as a convenience to the caller - it's easier to + * do it once here than every time at the call site. + */ + if (value <= 0) + value = 0; + else if (value >= 1) + value = 1; + +--- 2003,2016 ---- + * rounding and 'do_round' should be 1, if it is 0 the digitized value will + * be truncated. + */ ++ PNG_CONST unsigned int digitization_factor = (1U << depth) -1; + + /* Limiting the range is done as a convenience to the caller - it's easier to + * do it once here than every time at the call site. + */ + if (value <= 0) + value = 0; ++ + else if (value >= 1) + value = 1; + +*************** +*** 1998,2028 **** + return floor(value)/digitization_factor; + } + #endif + +- #if (defined PNG_READ_GAMMA_SUPPORTED) ||\ +- (defined PNG_READ_RGB_TO_GRAY_SUPPORTED) + static double abserr(PNG_CONST png_modifier *pm, int in_depth, int out_depth) + { + /* Absolute error permitted in linear values - affected by the bit depth of + * the calculations. + */ +- if (pm->assume_16_bit_calculations || (out_depth == 16 && (in_depth == 16 || +- !pm->calculations_use_input_precision))) + return pm->maxabs16; + else + return pm->maxabs8; + } +- #endif + +- #ifdef PNG_READ_GAMMA_SUPPORTED + static double calcerr(PNG_CONST png_modifier *pm, int in_depth, int out_depth) + { + /* Error in the linear composition arithmetic - only relevant when + * composition actually happens (0 < alpha < 1). + */ +- if (pm->assume_16_bit_calculations || (out_depth == 16 && (in_depth == 16 || +- !pm->calculations_use_input_precision))) + return pm->maxcalc16; + else + return pm->maxcalc8; + } +--- 2019,2048 ---- + return floor(value)/digitization_factor; + } + #endif ++ #endif /* RGB_TO_GRAY */ + ++ #ifdef PNG_READ_GAMMA_SUPPORTED + static double abserr(PNG_CONST png_modifier *pm, int in_depth, int out_depth) + { + /* Absolute error permitted in linear values - affected by the bit depth of + * the calculations. + */ ++ if (pm->assume_16_bit_calculations || ++ (pm->calculations_use_input_precision ? in_depth : out_depth) == 16) + return pm->maxabs16; + else + return pm->maxabs8; + } + + static double calcerr(PNG_CONST png_modifier *pm, int in_depth, int out_depth) + { + /* Error in the linear composition arithmetic - only relevant when + * composition actually happens (0 < alpha < 1). + */ ++ if ((pm->calculations_use_input_precision ? in_depth : out_depth) == 16) + return pm->maxcalc16; ++ else if (pm->assume_16_bit_calculations) ++ return pm->maxcalcG; + else + return pm->maxcalc8; + } +*************** +*** 2032,2039 **** + /* Percentage error permitted in the linear values. Note that the specified + * value is a percentage but this routine returns a simple number. + */ +- if (pm->assume_16_bit_calculations || (out_depth == 16 && (in_depth == 16 || +- !pm->calculations_use_input_precision))) + return pm->maxpc16 * .01; + else + return pm->maxpc8 * .01; +--- 2052,2059 ---- + /* Percentage error permitted in the linear values. Note that the specified + * value is a percentage but this routine returns a simple number. + */ ++ if (pm->assume_16_bit_calculations || ++ (pm->calculations_use_input_precision ? in_depth : out_depth) == 16) + return pm->maxpc16 * .01; + else + return pm->maxpc8 * .01; +*************** +*** 2065,2072 **** + if (out_depth == 4) + return .90644-.5; + +- if (out_depth == 16 && (in_depth == 16 || +- !pm->calculations_use_input_precision)) + return pm->maxout16; + + /* This is the case where the value was calculated at 8-bit precision then +--- 2085,2091 ---- + if (out_depth == 4) + return .90644-.5; + ++ if ((pm->calculations_use_input_precision ? in_depth : out_depth) == 16) + return pm->maxout16; + + /* This is the case where the value was calculated at 8-bit precision then +*************** +*** 2099,2106 **** + return pm->log8; + } + +- if (out_depth == 16 && (in_depth == 16 || +- !pm->calculations_use_input_precision)) + { + if (pm->log16 == 0) + return 65536; +--- 2118,2124 ---- + return pm->log8; + } + ++ if ((pm->calculations_use_input_precision ? in_depth : out_depth) == 16) + { + if (pm->log16 == 0) + return 65536; +*************** +*** 2125,2132 **** + static int output_quantization_factor(PNG_CONST png_modifier *pm, int in_depth, + int out_depth) + { +- if (out_depth == 16 && in_depth != 16 +- && pm->calculations_use_input_precision) + return 257; + else + return 1; +--- 2143,2150 ---- + static int output_quantization_factor(PNG_CONST png_modifier *pm, int in_depth, + int out_depth) + { ++ if (out_depth == 16 && in_depth != 16 && ++ pm->calculations_use_input_precision) + return 257; + else + return 1; +*************** +*** 3473,3479 **** + /* Use next_format to enumerate all the combinations we test, including + * generating multiple low bit depth palette images. + */ +- while (next_format(&colour_type, &bit_depth, &palette_number)) + { + int interlace_type; + +--- 3491,3497 ---- + /* Use next_format to enumerate all the combinations we test, including + * generating multiple low bit depth palette images. + */ ++ while (next_format(&colour_type, &bit_depth, &palette_number, 0)) + { + int interlace_type; + +*************** +*** 5784,5795 **** + + memset(out_palette, 0x5e, sizeof out_palette); + +- /* assume-8-bit-calculations means assume that if the input has 8 bit +- * (or less) samples and the output has 16 bit samples the calculations +- * will be done with 8 bit precision, not 16. +- * +- * TODO: fix this in libpng; png_set_expand_16 should cause 16 bit +- * calculations to be used throughout. + */ + if (in_ct == PNG_COLOR_TYPE_PALETTE || in_bd < 16) + in_sample_depth = 8; +--- 5802,5810 ---- + + memset(out_palette, 0x5e, sizeof out_palette); + ++ /* use-input-precision means assume that if the input has 8 bit (or less) ++ * samples and the output has 16 bit samples the calculations will be done ++ * with 8 bit precision, not 16. + */ + if (in_ct == PNG_COLOR_TYPE_PALETTE || in_bd < 16) + in_sample_depth = 8; +*************** +*** 5800,5806 **** + !dp->pm->calculations_use_input_precision) + digitization_error = .5; + +- /* Else errors are at 8 bit precision, scale .5 in 8 bits to the 16 bits: + */ + else + digitization_error = .5 * 257; +--- 5815,5822 ---- + !dp->pm->calculations_use_input_precision) + digitization_error = .5; + ++ /* Else calculations are at 8 bit precision, and the output actually ++ * consists of scaled 8-bit values, so scale .5 in 8 bits to the 16 bits: + */ + else + digitization_error = .5 * 257; +*************** +*** 6616,6625 **** + { + if (that->this.bit_depth == 16 || pm->assume_16_bit_calculations) + { +- /* The 16 bit case ends up producing a maximum error of about +- * +/-5 in 65535, allow for +/-8 with the given gamma. + */ +- that->pm->limit += pow(8./65535, data.gamma); + } + + else +--- 6632,6654 ---- + { + if (that->this.bit_depth == 16 || pm->assume_16_bit_calculations) + { ++ /* The computations have the form: ++ * ++ * r * rc + g * gc + b * bc ++ * ++ * Each component of which is +/-1/65535 from the gamma_to_1 table ++ * lookup, resulting in a base error of +/-6. The gamma_from_1 ++ * convertion adds another +/-2 in the 16-bit case and ++ * +/-(1<<(15-PNG_MAX_GAMMA_8)) in the 8-bit case. + */ ++ that->pm->limit += pow( ++ # if PNG_MAX_GAMMA_8 < 14 ++ (that->this.bit_depth == 16 ? 8. : ++ 6. + (1<<(15-PNG_MAX_GAMMA_8))) ++ # else ++ 8. ++ # endif ++ /65535, data.gamma); + } + + else +*************** +*** 6637,6643 **** + /* With no gamma correction a large error comes from the truncation of the + * calculation in the 8 bit case, allow for that here. + */ +- if (that->this.bit_depth != 16) + that->pm->limit += 4E-3; + } + } +--- 6666,6672 ---- + /* With no gamma correction a large error comes from the truncation of the + * calculation in the 8 bit case, allow for that here. + */ ++ if (that->this.bit_depth != 16 && !pm->assume_16_bit_calculations) + that->pm->limit += 4E-3; + } + } +*************** +*** 6782,6790 **** + image_pixel_convert_PLTE(that); + + /* Image now has RGB channels... */ + { + PNG_CONST png_modifier *pm = display->pm; +- PNG_CONST unsigned int sample_depth = that->sample_depth; + int isgray; + double r, g, b; + double rlo, rhi, glo, ghi, blo, bhi, graylo, grayhi; +--- 6811,6824 ---- + image_pixel_convert_PLTE(that); + + /* Image now has RGB channels... */ ++ # if DIGITIZE + { + PNG_CONST png_modifier *pm = display->pm; ++ const unsigned int sample_depth = that->sample_depth; ++ const unsigned int calc_depth = (pm->assume_16_bit_calculations ? 16 : ++ sample_depth); ++ const unsigned int gamma_depth = (sample_depth == 16 ? 16 : ++ (pm->assume_16_bit_calculations ? PNG_MAX_GAMMA_8 : sample_depth)); + int isgray; + double r, g, b; + double rlo, rhi, glo, ghi, blo, bhi, graylo, grayhi; +*************** +*** 6800,6827 **** + */ + r = rlo = rhi = that->redf; + rlo -= that->rede; +- rlo = digitize(pm, rlo, sample_depth, 1/*round*/); + rhi += that->rede; +- rhi = digitize(pm, rhi, sample_depth, 1/*round*/); + + g = glo = ghi = that->greenf; + glo -= that->greene; +- glo = digitize(pm, glo, sample_depth, 1/*round*/); + ghi += that->greene; +- ghi = digitize(pm, ghi, sample_depth, 1/*round*/); + + b = blo = bhi = that->bluef; + blo -= that->bluee; +- blo = digitize(pm, blo, sample_depth, 1/*round*/); + bhi += that->greene; +- bhi = digitize(pm, bhi, sample_depth, 1/*round*/); + + isgray = r==g && g==b; + + if (data.gamma != 1) + { + PNG_CONST double power = 1/data.gamma; +- PNG_CONST double abse = abserr(pm, sample_depth, sample_depth); + + /* 'abse' is the absolute error permitted in linear calculations. It + * is used here to capture the error permitted in the handling +--- 6834,6861 ---- + */ + r = rlo = rhi = that->redf; + rlo -= that->rede; ++ rlo = digitize(rlo, calc_depth, 1/*round*/); + rhi += that->rede; ++ rhi = digitize(rhi, calc_depth, 1/*round*/); + + g = glo = ghi = that->greenf; + glo -= that->greene; ++ glo = digitize(glo, calc_depth, 1/*round*/); + ghi += that->greene; ++ ghi = digitize(ghi, calc_depth, 1/*round*/); + + b = blo = bhi = that->bluef; + blo -= that->bluee; ++ blo = digitize(blo, calc_depth, 1/*round*/); + bhi += that->greene; ++ bhi = digitize(bhi, calc_depth, 1/*round*/); + + isgray = r==g && g==b; + + if (data.gamma != 1) + { + PNG_CONST double power = 1/data.gamma; ++ PNG_CONST double abse = calc_depth == 16 ? .5/65535 : .5/255; + + /* 'abse' is the absolute error permitted in linear calculations. It + * is used here to capture the error permitted in the handling +*************** +*** 6830,6845 **** + * where the real errors are introduced. + */ + r = pow(r, power); +- rlo = digitize(pm, pow(rlo, power)-abse, sample_depth, 1); +- rhi = digitize(pm, pow(rhi, power)+abse, sample_depth, 1); + + g = pow(g, power); +- glo = digitize(pm, pow(glo, power)-abse, sample_depth, 1); +- ghi = digitize(pm, pow(ghi, power)+abse, sample_depth, 1); + + b = pow(b, power); +- blo = digitize(pm, pow(blo, power)-abse, sample_depth, 1); +- bhi = digitize(pm, pow(bhi, power)+abse, sample_depth, 1); + } + + /* Now calculate the actual gray values. Although the error in the +--- 6864,6879 ---- + * where the real errors are introduced. + */ + r = pow(r, power); ++ rlo = digitize(pow(rlo, power)-abse, calc_depth, 1); ++ rhi = digitize(pow(rhi, power)+abse, calc_depth, 1); + + g = pow(g, power); ++ glo = digitize(pow(glo, power)-abse, calc_depth, 1); ++ ghi = digitize(pow(ghi, power)+abse, calc_depth, 1); + + b = pow(b, power); ++ blo = digitize(pow(blo, power)-abse, calc_depth, 1); ++ bhi = digitize(pow(bhi, power)+abse, calc_depth, 1); + } + + /* Now calculate the actual gray values. Although the error in the +*************** +*** 6856,6873 **** + b * data.blue_coefficient; + + { +- PNG_CONST int do_round = data.gamma != 1 || sample_depth == 16; + PNG_CONST double ce = 1. / 32768; + +- graylo = digitize(pm, rlo * (data.red_coefficient-ce) + + glo * (data.green_coefficient-ce) + +- blo * (data.blue_coefficient-ce), sample_depth, do_round); + if (graylo <= 0) + graylo = 0; + +- grayhi = digitize(pm, rhi * (data.red_coefficient+ce) + + ghi * (data.green_coefficient+ce) + +- bhi * (data.blue_coefficient+ce), sample_depth, do_round); + if (grayhi >= 1) + grayhi = 1; + } +--- 6890,6907 ---- + b * data.blue_coefficient; + + { ++ PNG_CONST int do_round = data.gamma != 1 || calc_depth == 16; + PNG_CONST double ce = 1. / 32768; + ++ graylo = digitize(rlo * (data.red_coefficient-ce) + + glo * (data.green_coefficient-ce) + ++ blo * (data.blue_coefficient-ce), gamma_depth, do_round); + if (graylo <= 0) + graylo = 0; + ++ grayhi = digitize(rhi * (data.red_coefficient+ce) + + ghi * (data.green_coefficient+ce) + ++ bhi * (data.blue_coefficient+ce), gamma_depth, do_round); + if (grayhi >= 1) + grayhi = 1; + } +*************** +*** 6878,6885 **** + PNG_CONST double power = data.gamma; + + gray = pow(gray, power); +- graylo = digitize(pm, pow(graylo, power), sample_depth, 1); +- grayhi = digitize(pm, pow(grayhi, power), sample_depth, 1); + } + + /* Now the error can be calculated. +--- 6912,6919 ---- + PNG_CONST double power = data.gamma; + + gray = pow(gray, power); ++ graylo = digitize(pow(graylo, power), sample_depth, 1); ++ grayhi = digitize(pow(grayhi, power), sample_depth, 1); + } + + /* Now the error can be calculated. +*************** +*** 6897,6903 **** + err = fabs(graylo-gray); + + /* Check that this worked: */ +- if (err > display->pm->limit) + { + size_t pos = 0; + char buffer[128]; +--- 6931,6937 ---- + err = fabs(graylo-gray); + + /* Check that this worked: */ ++ if (err > pm->limit) + { + size_t pos = 0; + char buffer[128]; +*************** +*** 6905,6916 **** + pos = safecat(buffer, sizeof buffer, pos, "rgb_to_gray error "); + pos = safecatd(buffer, sizeof buffer, pos, err, 6); + pos = safecat(buffer, sizeof buffer, pos, " exceeds limit "); +- pos = safecatd(buffer, sizeof buffer, pos, +- display->pm->limit, 6); + png_error(pp, buffer); + } + } + } + + that->bluef = that->greenf = that->redf = gray; + that->bluee = that->greene = that->rede = err; +--- 6939,7058 ---- + pos = safecat(buffer, sizeof buffer, pos, "rgb_to_gray error "); + pos = safecatd(buffer, sizeof buffer, pos, err, 6); + pos = safecat(buffer, sizeof buffer, pos, " exceeds limit "); ++ pos = safecatd(buffer, sizeof buffer, pos, pm->limit, 6); + png_error(pp, buffer); + } + } + } ++ # else /* DIGITIZE */ ++ { ++ double r = that->redf; ++ double re = that->rede; ++ double g = that->greenf; ++ double ge = that->greene; ++ double b = that->bluef; ++ double be = that->bluee; ++ ++ /* The true gray case involves no math. */ ++ if (r == g && r == b) ++ { ++ gray = r; ++ err = re; ++ if (err < ge) err = ge; ++ if (err < be) err = be; ++ } ++ ++ else if (data.gamma == 1) ++ { ++ /* There is no need to do the convertions to and from linear space, ++ * so the calculation should be a lot more accurate. There is a ++ * built in 1/32768 error in the coefficients because they only have ++ * 15 bits and are adjusted to make sure they add up to 32768, so ++ * the result may have an additional error up to 1/32768. (Note ++ * that adding the 1/32768 here avoids needing to increase the ++ * global error limits to take this into account.) ++ */ ++ gray = r * data.red_coefficient + g * data.green_coefficient + ++ b * data.blue_coefficient; ++ err = re * data.red_coefficient + ge * data.green_coefficient + ++ be * data.blue_coefficient + 1./32768 + gray * 5 * DBL_EPSILON; ++ } ++ ++ else ++ { ++ /* The calculation happens in linear space, and this produces much ++ * wider errors in the encoded space. These are handled here by ++ * factoring the errors in to the calculation. There are two table ++ * lookups in the calculation and each introduces a quantization ++ * error defined by the table size. ++ */ ++ PNG_CONST png_modifier *pm = display->pm; ++ double in_qe = (that->sample_depth > 8 ? .5/65535 : .5/255); ++ double out_qe = (that->sample_depth > 8 ? .5/65535 : ++ (pm->assume_16_bit_calculations ? .5/(1< 1) rhi = 1; ++ r -= re + in_qe; if (r < 0) r = 0; ++ ghi = g + ge + in_qe; if (ghi > 1) ghi = 1; ++ g -= ge + in_qe; if (g < 0) g = 0; ++ bhi = b + be + in_qe; if (bhi > 1) bhi = 1; ++ b -= be + in_qe; if (b < 0) b = 0; ++ ++ r = pow(r, g1)*(1-DBL_EPSILON); rhi = pow(rhi, g1)*(1+DBL_EPSILON); ++ g = pow(g, g1)*(1-DBL_EPSILON); ghi = pow(ghi, g1)*(1+DBL_EPSILON); ++ b = pow(b, g1)*(1-DBL_EPSILON); bhi = pow(bhi, g1)*(1+DBL_EPSILON); ++ ++ /* Work out the lower and upper bounds for the gray value in the ++ * encoded space, then work out an average and error. Remove the ++ * previously added input quantization error at this point. ++ */ ++ gray = r * data.red_coefficient + g * data.green_coefficient + ++ b * data.blue_coefficient - 1./32768 - out_qe; ++ if (gray <= 0) ++ gray = 0; ++ else ++ { ++ gray *= (1 - 6 * DBL_EPSILON); ++ gray = pow(gray, data.gamma) * (1-DBL_EPSILON); ++ } ++ ++ grayhi = rhi * data.red_coefficient + ghi * data.green_coefficient + ++ bhi * data.blue_coefficient + 1./32768 + out_qe; ++ grayhi *= (1 + 6 * DBL_EPSILON); ++ if (grayhi >= 1) ++ grayhi = 1; ++ else ++ grayhi = pow(grayhi, data.gamma) * (1+DBL_EPSILON); ++ ++ err = (grayhi - gray) / 2; ++ gray = (grayhi + gray) / 2; ++ ++ if (err <= in_qe) ++ err = gray * DBL_EPSILON; ++ ++ else ++ err -= in_qe; ++ ++ /* Validate that the error is within limits (this has caused ++ * problems before, it's much easier to detect them here.) ++ */ ++ if (err > pm->limit) ++ { ++ size_t pos = 0; ++ char buffer[128]; ++ ++ pos = safecat(buffer, sizeof buffer, pos, "rgb_to_gray error "); ++ pos = safecatd(buffer, sizeof buffer, pos, err, 6); ++ pos = safecat(buffer, sizeof buffer, pos, " exceeds limit "); ++ pos = safecatd(buffer, sizeof buffer, pos, pm->limit, 6); ++ png_error(pp, buffer); ++ } ++ } ++ } ++ # endif /* !DIGITIZE */ + + that->bluef = that->greenf = that->redf = gray; + that->bluee = that->greene = that->rede = err; +*************** +*** 6959,6965 **** + * int background_gamma_code, int need_expand, + * png_fixed_point background_gamma) + * +- * As with rgb_to_gray this ignores the gamma (at present.) + */ + #define data ITDATA(background) + static image_pixel data; +--- 7101,7107 ---- + * int background_gamma_code, int need_expand, + * png_fixed_point background_gamma) + * ++ * This ignores the gamma (at present.) + */ + #define data ITDATA(background) + static image_pixel data; +*************** +*** 6970,6975 **** + { + png_byte colour_type, bit_depth; + png_byte random_bytes[8]; /* 8 bytes - 64 bits - the biggest pixel */ + png_color_16 back; + + /* We need a background colour, because we don't know exactly what transforms +--- 7112,7118 ---- + { + png_byte colour_type, bit_depth; + png_byte random_bytes[8]; /* 8 bytes - 64 bits - the biggest pixel */ ++ int expand; + png_color_16 back; + + /* We need a background colour, because we don't know exactly what transforms +*************** +*** 6987,6996 **** + { + colour_type = PNG_COLOR_TYPE_RGB; + bit_depth = 8; + } + + else + bit_depth = that->this.bit_depth; + + image_pixel_init(&data, random_bytes, colour_type, + bit_depth, 0/*x*/, 0/*unused: palette*/); +--- 7130,7143 ---- + { + colour_type = PNG_COLOR_TYPE_RGB; + bit_depth = 8; ++ expand = 0; /* passing in an RGB not a pixel index */ + } + + else ++ { + bit_depth = that->this.bit_depth; ++ expand = 1; ++ } + + image_pixel_init(&data, random_bytes, colour_type, + bit_depth, 0/*x*/, 0/*unused: palette*/); +*************** +*** 7011,7021 **** + back.gray = (png_uint_16)data.red; + + # ifdef PNG_FLOATING_POINT_SUPPORTED +- png_set_background(pp, &back, PNG_BACKGROUND_GAMMA_FILE, 1/*need expand*/, +- 0); + # else +- png_set_background_fixed(pp, &back, PNG_BACKGROUND_GAMMA_FILE, +- 1/*need expand*/, 0); + # endif + + this->next->set(this->next, that, pp, pi); +--- 7158,7166 ---- + back.gray = (png_uint_16)data.red; + + # ifdef PNG_FLOATING_POINT_SUPPORTED ++ png_set_background(pp, &back, PNG_BACKGROUND_GAMMA_FILE, expand, 0); + # else ++ png_set_background_fixed(pp, &back, PNG_BACKGROUND_GAMMA_FILE, expand, 0); + # endif + + this->next->set(this->next, that, pp, pi); +*************** +*** 7347,7353 **** + png_byte bit_depth = 0; + unsigned int palette_number = 0; + +- while (next_format(&colour_type, &bit_depth, &palette_number)) + { + png_uint_32 counter = 0; + size_t base_pos; +--- 7492,7498 ---- + png_byte bit_depth = 0; + unsigned int palette_number = 0; + ++ while (next_format(&colour_type, &bit_depth, &palette_number, 0)) + { + png_uint_32 counter = 0; + size_t base_pos; +*************** +*** 8032,8045 **** + * passed. Don't do these additional tests here - just log the + * original [es_lo..es_hi] values. + */ +- if (pass == 0 && vi->use_input_precision) + { + /* Ok, something is wrong - this actually happens in current libpng + * 16-to-8 processing. Assume that the input value (id, adjusted + * for sbit) can be anywhere between value-.5 and value+.5 - quite a + * large range if sbit is low. + */ +- double tmp = (isbit - .5)/sbit_max; + + if (tmp <= 0) + tmp = 0; +--- 8177,8201 ---- + * passed. Don't do these additional tests here - just log the + * original [es_lo..es_hi] values. + */ ++ if (pass == 0 && vi->use_input_precision && vi->dp->sbit) + { + /* Ok, something is wrong - this actually happens in current libpng + * 16-to-8 processing. Assume that the input value (id, adjusted + * for sbit) can be anywhere between value-.5 and value+.5 - quite a + * large range if sbit is low. ++ * ++ * NOTE: at present because the libpng gamma table stuff has been ++ * changed to use a rounding algorithm to correct errors in 8-bit ++ * calculations the precise sbit calculation (a shift) has been ++ * lost. This can result in up to a +/-1 error in the presence of ++ * an sbit less than the bit depth. + */ ++ # if PNG_LIBPNG_VER < 10600 ++ # define SBIT_ERROR .5 ++ # else ++ # define SBIT_ERROR 1. ++ # endif ++ double tmp = (isbit - SBIT_ERROR)/sbit_max; + + if (tmp <= 0) + tmp = 0; +*************** +*** 8058,8067 **** + if (is_lo < 0) + is_lo = 0; + +- tmp = (isbit + .5)/sbit_max; + +- if (tmp <= 0) +- tmp = 0; + + else if (alpha >= 0 && vi->file_inverse > 0 && tmp < 1) + tmp = pow(tmp, vi->file_inverse); +--- 8214,8223 ---- + if (is_lo < 0) + is_lo = 0; + ++ tmp = (isbit + SBIT_ERROR)/sbit_max; + ++ if (tmp >= 1) ++ tmp = 1; + + else if (alpha >= 0 && vi->file_inverse > 0 && tmp < 1) + tmp = pow(tmp, vi->file_inverse); +*************** +*** 8378,8384 **** + * Because there is limited precision in the input it is arguable that + * an acceptable result is any valid result from input-.5 to input+.5. + * The basic tests below do not do this, however if 'use_input_precision' +- * is set a subsequent test is performed below. + */ + PNG_CONST unsigned int samples_per_pixel = (out_ct & 2U) ? 3U : 1U; + int processing; +--- 8534,8540 ---- + * Because there is limited precision in the input it is arguable that + * an acceptable result is any valid result from input-.5 to input+.5. + * The basic tests below do not do this, however if 'use_input_precision' ++ * is set a subsequent test is performed above. + */ + PNG_CONST unsigned int samples_per_pixel = (out_ct & 2U) ? 3U : 1U; + int processing; +*************** +*** 8720,8726 **** + * fact this test is somewhat excessive since libpng doesn't make this + * decision based on colour type or bit depth! + */ +- while (next_format(&colour_type, &bit_depth, &palette_number)) + if (palette_number == 0) + { + double test_gamma = 1.0; +--- 8876,8882 ---- + * fact this test is somewhat excessive since libpng doesn't make this + * decision based on colour type or bit depth! + */ ++ while (next_format(&colour_type, &bit_depth, &palette_number, 1/*gamma*/)) + if (palette_number == 0) + { + double test_gamma = 1.0; +*************** +*** 8781,8787 **** + png_byte bit_depth = 0; + unsigned int palette_number = 0; + +- while (next_format(&colour_type, &bit_depth, &palette_number)) + { + unsigned int i, j; + +--- 8937,8943 ---- + png_byte bit_depth = 0; + unsigned int palette_number = 0; + ++ while (next_format(&colour_type, &bit_depth, &palette_number, 1/*gamma*/)) + { + unsigned int i, j; + +*************** +*** 8811,8817 **** + png_byte colour_type = 0, bit_depth = 0; + unsigned int npalette = 0; + +- while (next_format(&colour_type, &bit_depth, &npalette)) + if ((colour_type & PNG_COLOR_MASK_ALPHA) == 0 && + ((colour_type == 3 && sbit < 8) || + (colour_type != 3 && sbit < bit_depth))) +--- 8967,8973 ---- + png_byte colour_type = 0, bit_depth = 0; + unsigned int npalette = 0; + ++ while (next_format(&colour_type, &bit_depth, &npalette, 1/*gamma*/)) + if ((colour_type & PNG_COLOR_MASK_ALPHA) == 0 && + ((colour_type == 3 && sbit < 8) || + (colour_type != 3 && sbit < bit_depth))) +*************** +*** 8846,8851 **** + # ifndef PNG_MAX_GAMMA_8 + # define PNG_MAX_GAMMA_8 11 + # endif + /* Include the alpha cases here. Note that sbit matches the internal value + * used by the library - otherwise we will get spurious errors from the + * internal sbit style approximation. +--- 9002,9008 ---- + # ifndef PNG_MAX_GAMMA_8 + # define PNG_MAX_GAMMA_8 11 + # endif ++ # define SBIT_16_TO_8 PNG_MAX_GAMMA_8 + /* Include the alpha cases here. Note that sbit matches the internal value + * used by the library - otherwise we will get spurious errors from the + * internal sbit style approximation. +*************** +*** 8863,8890 **** + fabs(pm->gammas[j]/pm->gammas[i]-1) >= PNG_GAMMA_THRESHOLD) + { + gamma_transform_test(pm, 0, 16, 0, pm->interlace_type, +- 1/pm->gammas[i], pm->gammas[j], PNG_MAX_GAMMA_8, + pm->use_input_precision_16to8, 1 /*scale16*/); + + if (fail(pm)) + return; + + gamma_transform_test(pm, 2, 16, 0, pm->interlace_type, +- 1/pm->gammas[i], pm->gammas[j], PNG_MAX_GAMMA_8, + pm->use_input_precision_16to8, 1 /*scale16*/); + + if (fail(pm)) + return; + + gamma_transform_test(pm, 4, 16, 0, pm->interlace_type, +- 1/pm->gammas[i], pm->gammas[j], PNG_MAX_GAMMA_8, + pm->use_input_precision_16to8, 1 /*scale16*/); + + if (fail(pm)) + return; + + gamma_transform_test(pm, 6, 16, 0, pm->interlace_type, +- 1/pm->gammas[i], pm->gammas[j], PNG_MAX_GAMMA_8, + pm->use_input_precision_16to8, 1 /*scale16*/); + + if (fail(pm)) +--- 9020,9047 ---- + fabs(pm->gammas[j]/pm->gammas[i]-1) >= PNG_GAMMA_THRESHOLD) + { + gamma_transform_test(pm, 0, 16, 0, pm->interlace_type, ++ 1/pm->gammas[i], pm->gammas[j], SBIT_16_TO_8, + pm->use_input_precision_16to8, 1 /*scale16*/); + + if (fail(pm)) + return; + + gamma_transform_test(pm, 2, 16, 0, pm->interlace_type, ++ 1/pm->gammas[i], pm->gammas[j], SBIT_16_TO_8, + pm->use_input_precision_16to8, 1 /*scale16*/); + + if (fail(pm)) + return; + + gamma_transform_test(pm, 4, 16, 0, pm->interlace_type, ++ 1/pm->gammas[i], pm->gammas[j], SBIT_16_TO_8, + pm->use_input_precision_16to8, 1 /*scale16*/); + + if (fail(pm)) + return; + + gamma_transform_test(pm, 6, 16, 0, pm->interlace_type, ++ 1/pm->gammas[i], pm->gammas[j], SBIT_16_TO_8, + pm->use_input_precision_16to8, 1 /*scale16*/); + + if (fail(pm)) +*************** +*** 9030,9036 **** + /* Skip the non-alpha cases - there is no setting of a transparency colour at + * present. + */ +- while (next_format(&colour_type, &bit_depth, &palette_number)) + if ((colour_type & PNG_COLOR_MASK_ALPHA) != 0) + { + unsigned int i, j; +--- 9187,9193 ---- + /* Skip the non-alpha cases - there is no setting of a transparency colour at + * present. + */ ++ while (next_format(&colour_type, &bit_depth, &palette_number, 1/*gamma*/)) + if ((colour_type & PNG_COLOR_MASK_ALPHA) != 0) + { + unsigned int i, j; +*************** +*** 9052,9082 **** + static void + init_gamma_errors(png_modifier *pm) + { +- pm->error_gray_2 = pm->error_gray_4 = pm->error_gray_8 = 0; +- pm->error_color_8 = 0; +- pm->error_indexed = 0; +- pm->error_gray_16 = pm->error_color_16 = 0; + } + + static void +- summarize_gamma_errors(png_modifier *pm, png_const_charp who, int low_bit_depth) + { + if (who) +- printf("Gamma correction with %s:\n", who); + + if (low_bit_depth) + { +- printf(" 2 bit gray: %.5f\n", pm->error_gray_2); +- printf(" 4 bit gray: %.5f\n", pm->error_gray_4); +- printf(" 8 bit gray: %.5f\n", pm->error_gray_8); +- printf(" 8 bit color: %.5f\n", pm->error_color_8); +- printf(" indexed: %.5f\n", pm->error_indexed); + } + +- #ifdef DO_16BIT +- printf(" 16 bit gray: %.5f\n", pm->error_gray_16); +- printf(" 16 bit color: %.5f\n", pm->error_color_16); +- #endif + } + + static void +--- 9209,9254 ---- + static void + init_gamma_errors(png_modifier *pm) + { ++ /* Use -1 to catch tests that were not actually run */ ++ pm->error_gray_2 = pm->error_gray_4 = pm->error_gray_8 = -1.; ++ pm->error_color_8 = -1.; ++ pm->error_indexed = -1.; ++ pm->error_gray_16 = pm->error_color_16 = -1.; + } + + static void ++ print_one(const char *leader, double err) + { ++ if (err != -1.) ++ printf(" %s %.5f\n", leader, err); ++ } ++ ++ static void ++ summarize_gamma_errors(png_modifier *pm, png_const_charp who, int low_bit_depth, ++ int indexed) ++ { ++ fflush(stderr); ++ + if (who) ++ printf("\nGamma correction with %s:\n", who); ++ ++ else ++ printf("\nBasic gamma correction:\n"); + + if (low_bit_depth) + { ++ print_one(" 2 bit gray: ", pm->error_gray_2); ++ print_one(" 4 bit gray: ", pm->error_gray_4); ++ print_one(" 8 bit gray: ", pm->error_gray_8); ++ print_one(" 8 bit color:", pm->error_color_8); ++ if (indexed) ++ print_one(" indexed: ", pm->error_indexed); + } + ++ print_one("16 bit gray: ", pm->error_gray_16); ++ print_one("16 bit color:", pm->error_color_16); ++ ++ fflush(stdout); + } + + static void +*************** +*** 9102,9119 **** + /* Now some real transforms. */ + if (pm->test_gamma_transform) + { +- init_gamma_errors(pm); +- /*TODO: remove this. Necessary because the current libpng +- * implementation works in 8 bits: +- */ +- if (pm->test_gamma_expand16) +- pm->calculations_use_input_precision = 1; +- perform_gamma_transform_tests(pm); +- if (!calculations_use_input_precision) +- pm->calculations_use_input_precision = 0; +- + if (summary) + { + printf("Gamma correction error summary\n\n"); + printf("The printed value is the maximum error in the pixel values\n"); + printf("calculated by the libpng gamma correction code. The error\n"); +--- 9274,9282 ---- + /* Now some real transforms. */ + if (pm->test_gamma_transform) + { + if (summary) + { ++ fflush(stderr); + printf("Gamma correction error summary\n\n"); + printf("The printed value is the maximum error in the pixel values\n"); + printf("calculated by the libpng gamma correction code. The error\n"); +*************** +*** 9125,9134 **** + printf("less than 1 for formats with fewer than 8 bits and a small\n"); + printf("number (typically less than 5) for the 16 bit formats.\n"); + printf("For performance reasons the value for 16 bit formats\n"); +- printf("increases when the image file includes an sBIT chunk.\n\n"); +- +- summarize_gamma_errors(pm, 0/*who*/, 1); + } + } + + /* The sbit tests produce much larger errors: */ +--- 9288,9312 ---- + printf("less than 1 for formats with fewer than 8 bits and a small\n"); + printf("number (typically less than 5) for the 16 bit formats.\n"); + printf("For performance reasons the value for 16 bit formats\n"); ++ printf("increases when the image file includes an sBIT chunk.\n"); ++ fflush(stdout); + } ++ ++ init_gamma_errors(pm); ++ /*TODO: remove this. Necessary because the current libpng ++ * implementation works in 8 bits: ++ */ ++ if (pm->test_gamma_expand16) ++ pm->calculations_use_input_precision = 1; ++ perform_gamma_transform_tests(pm); ++ if (!calculations_use_input_precision) ++ pm->calculations_use_input_precision = 0; ++ ++ if (summary) ++ summarize_gamma_errors(pm, 0/*who*/, 1/*low bit depth*/, 1/*indexed*/); ++ ++ if (fail(pm)) ++ return; + } + + /* The sbit tests produce much larger errors: */ +*************** +*** 9138,9144 **** + perform_gamma_sbit_tests(pm); + + if (summary) +- summarize_gamma_errors(pm, "sBIT", pm->sbitlow < 8U); + } + + #ifdef DO_16BIT /* Should be READ_16BIT_SUPPORTED */ +--- 9316,9325 ---- + perform_gamma_sbit_tests(pm); + + if (summary) ++ summarize_gamma_errors(pm, "sBIT", pm->sbitlow < 8U, 1/*indexed*/); ++ ++ if (fail(pm)) ++ return; + } + + #ifdef DO_16BIT /* Should be READ_16BIT_SUPPORTED */ +*************** +*** 9150,9159 **** + + if (summary) + { +- printf("Gamma correction with 16 to 8 bit reduction:\n"); + printf(" 16 bit gray: %.5f\n", pm->error_gray_16); + printf(" 16 bit color: %.5f\n", pm->error_color_16); + } + } + #endif + +--- 9331,9345 ---- + + if (summary) + { ++ fflush(stderr); ++ printf("\nGamma correction with 16 to 8 bit reduction:\n"); + printf(" 16 bit gray: %.5f\n", pm->error_gray_16); + printf(" 16 bit color: %.5f\n", pm->error_color_16); ++ fflush(stdout); + } ++ ++ if (fail(pm)) ++ return; + } + #endif + +*************** +*** 9177,9183 **** + pm->maxout8 = maxout8; + + if (summary) +- summarize_gamma_errors(pm, "background", 1); + } + #endif + +--- 9363,9372 ---- + pm->maxout8 = maxout8; + + if (summary) ++ summarize_gamma_errors(pm, "background", 1, 0/*indexed*/); ++ ++ if (fail(pm)) ++ return; + } + #endif + +*************** +*** 9202,9208 **** + pm->calculations_use_input_precision = 0; + + if (summary) +- summarize_gamma_errors(pm, "alpha mode", 1); + } + #endif + } +--- 9391,9400 ---- + pm->calculations_use_input_precision = 0; + + if (summary) ++ summarize_gamma_errors(pm, "alpha mode", 1, 0/*indexed*/); ++ ++ if (fail(pm)) ++ return; + } + #endif + } +*************** +*** 9710,9715 **** + /* Default to error on warning: */ + pm.this.treat_warnings_as_errors = 1; + + /* Store the test gammas */ + pm.gammas = gammas; + pm.ngammas = (sizeof gammas) / (sizeof gammas[0]); +--- 9902,9923 ---- + /* Default to error on warning: */ + pm.this.treat_warnings_as_errors = 1; + ++ /* Default assume_16_bit_calculations appropriately; this tells the checking ++ * code that 16-bit arithmetic is used for 8-bit samples when it would make a ++ * difference. ++ * ++ * TODO: IMPORTANT; set to '>= 10600' below to enable development, change ++ * this to the correct value before release! ++ */ ++ pm.assume_16_bit_calculations = PNG_LIBPNG_VER >= 10600; ++ ++ /* Currently 16 bit expansion happens at the end of the pipeline, so the ++ * calculations are done in the input bit depth not the output. ++ * ++ * TODO: fix this ++ */ ++ pm.calculations_use_input_precision = 1U; ++ + /* Store the test gammas */ + pm.gammas = gammas; + pm.ngammas = (sizeof gammas) / (sizeof gammas[0]); +*************** +*** 9720,9732 **** + pm.nencodings = (sizeof test_encodings) / (sizeof test_encodings[0]); + + pm.sbitlow = 8U; /* because libpng doesn't do sBIT below 8! */ + /* The following allows results to pass if they correspond to anything in the + * transformed range [input-.5,input+.5]; this is is required because of the +- * way libpng treates the 16_TO_8 flag when building the gamma tables. + * + * TODO: review this + */ + pm.use_input_precision_16to8 = 1U; + + /* Some default values (set the behavior for 'make check' here). + * These values simply control the maximum error permitted in the gamma +--- 9928,9943 ---- + pm.nencodings = (sizeof test_encodings) / (sizeof test_encodings[0]); + + pm.sbitlow = 8U; /* because libpng doesn't do sBIT below 8! */ ++ + /* The following allows results to pass if they correspond to anything in the + * transformed range [input-.5,input+.5]; this is is required because of the ++ * way libpng treates the 16_TO_8 flag when building the gamma tables in ++ * releases up to 1.6.0. + * + * TODO: review this + */ + pm.use_input_precision_16to8 = 1U; ++ pm.use_input_precision_sbit = 1U; /* because libpng now rounds sBIT */ + + /* Some default values (set the behavior for 'make check' here). + * These values simply control the maximum error permitted in the gamma +*************** +*** 9737,9747 **** + */ + pm.maxout8 = .1; /* Arithmetic error in *encoded* value */ + pm.maxabs8 = .00005; /* 1/20000 */ +- pm.maxcalc8 = .004; /* +/-1 in 8 bits for compose errors */ + pm.maxpc8 = .499; /* I.e., .499% fractional error */ + pm.maxout16 = .499; /* Error in *encoded* value */ + pm.maxabs16 = .00005;/* 1/20000 */ +- pm.maxcalc16 =.000015;/* +/-1 in 16 bits for compose errors */ + + /* NOTE: this is a reasonable perceptual limit. We assume that humans can + * perceive light level differences of 1% over a 100:1 range, so we need to +--- 9948,9959 ---- + */ + pm.maxout8 = .1; /* Arithmetic error in *encoded* value */ + pm.maxabs8 = .00005; /* 1/20000 */ ++ pm.maxcalc8 = 1./255; /* +/-1 in 8 bits for compose errors */ + pm.maxpc8 = .499; /* I.e., .499% fractional error */ + pm.maxout16 = .499; /* Error in *encoded* value */ + pm.maxabs16 = .00005;/* 1/20000 */ ++ pm.maxcalc16 =1./65535;/* +/-1 in 16 bits for compose errors */ ++ pm.maxcalcG = 1./((1<>16 + * + * The command arguments are: + * + * scale target source + * + * and the program works out a pair of numbers, mult and add, that evaluate: + * + * number * target + * round( --------------- ) + * source + * + * exactly for number in the range 0..source + */ +#define _ISOC99_SOURCE 1 + +#include +#include +#include +#include + +static double minerr; +static unsigned long minmult, minadd, minshift; +static long mindelta; + +static int +test(unsigned long target, unsigned long source, unsigned long mult, + long add, unsigned long shift, long delta) +{ + unsigned long i; + double maxerr = 0; + double rs = (double)target/source; + + for (i=0; i<=source; ++i) + { + unsigned long t = i*mult+add; + double err = fabs((t >> shift) - i*rs); + + if (err > minerr) + return 0; + + if (err > maxerr) + maxerr = err; + } + + if (maxerr < minerr) + { + minerr = maxerr; + minmult = mult; + minadd = add; + minshift = shift; + mindelta = delta; + } + + return maxerr < .5; +} + +static int +dotest(unsigned long target, unsigned long source, unsigned long mult, + long add, unsigned long shift, long delta, int print) +{ + if (test(target, source, mult, add, shift, delta)) + { + if (print & 4) + printf(" {%11lu,%6ld /* >>%lu */ }, /* %lu/%lu */\n", + mult, add, shift, target, source); + + else if (print & 2) + printf(" {%11lu,%6ld,%3lu }, /* %lu/%lu */\n", + mult, add, shift, target, source); + + else if (print) + printf("number * %lu/%lu = (number * %lu + %ld) >> %lu [delta %ld]\n", + target, source, mult, add, shift, delta); + + return 1; + } + + return 0; +} + +static int +find(unsigned long target, unsigned long source, int print, int fixshift) +{ + unsigned long shift = 0; + unsigned long shiftlim = 0; + + /* In the final math the sum is at most (source*mult+add) >> shift, so: + * + * source*mult+add < 1<<32 + * mult < (1<<32)/source + * + * but: + * + * mult = (target<>1)) / source; + long delta; + long limit = 1; /* seems to be sufficient */ + long add, start, end; + + end = 1<>%lu */ }, /* %lu/%lu ERROR: .5+%g*/\n", + minmult, minadd, minshift, target, source, minerr-.5); + + else if (print & 2) + printf(" {%11lu,%6ld,%3lu }, /* %lu/%lu ERROR: .5+%g*/\n", + minmult, minadd, minshift, target, source, minerr-.5); + + else if (print) + printf( + "number * %lu/%lu ~= (number * %lu + %ld) >> %lu +/-.5+%g [delta %ld]\n", + target, source, minmult, minadd, minshift, minerr-.5, mindelta); + + return 0; +} + +static void +usage(const char *prog) +{ + fprintf(stderr, + "usage: %s {--denominator|--maxshift|--code} target {source}\n" + " For each 'source' prints 'mult' and 'add' such that:\n\n" + " (number * mult + add) >> 16 = round(number*target/source)\n\n" + " for all integer values of number in the range 0..source.\n\n" + " --denominator: swap target and source (specify a single source first\n" + " and follow with multiple targets.)\n" + " --maxshift: find the lowest shift value that works for all the\n" + " repeated 'source' values\n" + " --code: output C code for array/structure initialization\n", + prog); + exit(1); +} + +int +main(int argc, const char **argv) +{ + int i, err = 0, maxshift = 0, firstsrc = 1, code = 0, denominator = 0; + unsigned long target, shift = 0; + + while (argc > 1) + { + if (strcmp(argv[firstsrc], "--maxshift") == 0) + { + maxshift = 1; + ++firstsrc; + } + + else if (strcmp(argv[firstsrc], "--code") == 0) + { + code = 1; + ++firstsrc; + } + + else if (strcmp(argv[firstsrc], "--denominator") == 0) + { + denominator = 1; + ++firstsrc; + } + + else + break; + } + + + if (argc < 2+firstsrc) + usage(argv[0]); + + target = strtoul(argv[firstsrc++], 0, 0); + if (target == 0) usage(argv[0]); + + for (i=firstsrc; i shift) shift = minshift; + } + + if (maxshift) for (i=firstsrc; i>16 + * + * The command arguments are: + * + * scale target source + * + * and the program works out a pair of numbers, mult and add, that evaluate: + * + * number * target + * round( --------------- ) + * source + * + * exactly for number in the range 0..source + */ +#define _ISOC99_SOURCE 1 + +#include +#include +#include +#include + +static double minerr; +static unsigned long minmult, minadd, minshift; +static long mindelta; + +static int +test(unsigned long target, unsigned long source, unsigned long mult, + long add, unsigned long shift, long delta) +{ + unsigned long i; + double maxerr = 0; + double rs = (double)target/source; + + for (i=0; i<=source; ++i) + { + unsigned long t = i*mult+add; + double err = fabs((t >> shift) - i*rs); + + if (err > minerr) + return 0; + + if (err > maxerr) + maxerr = err; + } + + if (maxerr < minerr) + { + minerr = maxerr; + minmult = mult; + minadd = add; + minshift = shift; + mindelta = delta; + } + + return maxerr < .5; +} + +static int +dotest(unsigned long target, unsigned long source, unsigned long mult, + long add, unsigned long shift, long delta, int print) +{ + if (test(target, source, mult, add, shift, delta)) + { + if (print & 4) + printf(" {%11lu,%6ld /* >>%lu */ }, /* %lu/%lu */\n", + mult, add, shift, target, source); + + else if (print & 2) + printf(" {%11lu,%6ld,%3lu }, /* %lu/%lu */\n", + mult, add, shift, target, source); + + else if (print) + printf("number * %lu/%lu = (number * %lu + %ld) >> %lu [delta %ld]\n", + target, source, mult, add, shift, delta); + + return 1; + } + + return 0; +} + +static int +find(unsigned long target, unsigned long source, int print, int fixshift) +{ + unsigned long shift = 0; + unsigned long shiftlim = 0; + + /* In the final math the sum is at most (source*mult+add) >> shift, so: + * + * source*mult+add < 1<<32 + * mult < (1<<32)/source + * + * but: + * + * mult = (target<>1)) / source; + long delta; + long limit = 1; /* seems to be sufficient */ + long add, start, end; + + end = 1<>%lu */ }, /* %lu/%lu ERROR: .5+%g*/\n", + minmult, minadd, minshift, target, source, minerr-.5); + + else if (print & 2) + printf(" {%11lu,%6ld,%3lu }, /* %lu/%lu ERROR: .5+%g*/\n", + minmult, minadd, minshift, target, source, minerr-.5); + + else if (print) + printf( + "number * %lu/%lu ~= (number * %lu + %ld) >> %lu +/-.5+%g [delta %ld]\n", + target, source, minmult, minadd, minshift, minerr-.5, mindelta); + + return 0; +} + +static void +usage(const char *prog) +{ + fprintf(stderr, + "usage: %s {--denominator|--maxshift|--code} target {source}\n" + " For each 'source' prints 'mult' and 'add' such that:\n\n" + " (number * mult + add) >> 16 = round(number*target/source)\n\n" + " for all integer values of number in the range 0..source.\n\n" + " --denominator: swap target and source (specify a single source first\n" + " and follow with multiple targets.)\n" + " --maxshift: find the lowest shift value that works for all the\n" + " repeated 'source' values\n" + " --code: output C code for array/structure initialization\n", + prog); + exit(1); +} + +int +main(int argc, const char **argv) +{ + int i, err = 0, maxshift = 0, firstsrc = 1, code = 0, denominator = 0; + unsigned long target, shift = 0; + + while (argc > 1) + { + if (strcmp(argv[firstsrc], "--maxshift") == 0) + { + maxshift = 1; + ++firstsrc; + } + + else if (strcmp(argv[firstsrc], "--code") == 0) + { + code = 1; + ++firstsrc; + } + + else if (strcmp(argv[firstsrc], "--denominator") == 0) + { + denominator = 1; + ++firstsrc; + } + + else + break; + } + + + if (argc < 2+firstsrc) + usage(argv[0]); + + target = strtoul(argv[firstsrc++], 0, 0); + if (target == 0) usage(argv[0]); + + for (i=firstsrc; i shift) shift = minshift; + } + + if (maxshift) for (i=firstsrc; ifree_me) { + info_ptr->valid &= ~PNG_INFO_tRNS; png_free(png_ptr, info_ptr->trans_alpha); info_ptr->trans_alpha = NULL; - info_ptr->valid &= ~PNG_INFO_tRNS; + info_ptr->num_trans = 0; } #endif #ifdef PNG_sCAL_SUPPORTED @@ -731,31 +747,8 @@ } return 1; } - -# if PNG_LIBPNG_VER < 10700 -/* To do: remove the following from libpng-1.7 */ -/* Original API that uses a private buffer in png_struct. - * Deprecated because it causes png_struct to carry a spurious temporary - * buffer (png_struct::time_buffer), better to have the caller pass this in. - */ -png_const_charp PNGAPI -png_convert_to_rfc1123(png_structrp png_ptr, png_const_timep ptime) -{ - if (png_ptr != NULL) - { - /* The only failure above if png_ptr != NULL is from an invalid ptime */ - if (!png_convert_to_rfc1123_buffer(png_ptr->time_buffer, ptime)) - png_warning(png_ptr, "Ignoring invalid time value"); - - else - return png_ptr->time_buffer; - } - - return NULL; -} -# endif # endif /* PNG_TIME_RFC1123_SUPPORTED */ #endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ @@ -767,15 +760,15 @@ return PNG_STRING_COPYRIGHT #else # ifdef __STDC__ return PNG_STRING_NEWLINE \ - "libpng version 1.7.0alpha01 - December 15, 2012" PNG_STRING_NEWLINE \ + "libpng version 1.6.0beta32 - November 25, 2012" PNG_STRING_NEWLINE \ "Copyright (c) 1998-2012 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \ "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \ PNG_STRING_NEWLINE; # else - return "libpng version 1.7.0alpha01 - December 15, 2012\ + return "libpng version 1.6.0beta32 - November 25, 2012\ Copyright (c) 1998-2012 Glenn Randers-Pehrson\ Copyright (c) 1996-1997 Andreas Dilger\ Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc."; # endif @@ -2286,9 +2279,9 @@ void /* PRIVATE */ png_colorspace_set_rgb_coefficients(png_structrp png_ptr) { /* Set the rgb_to_gray coefficients from the colorspace. */ - if (!png_ptr->rgb_to_gray_coefficients_set && + if ((png_ptr->colorspace.flags & PNG_COLORSPACE_RGB_TO_GRAY_SET) == 0 && (png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0) { /* png_set_background has not been called, get the coefficients from the Y * values of the colorspace colorants. @@ -3262,8 +3255,9 @@ #endif #ifdef PNG_READ_GAMMA_SUPPORTED /* A local convenience routine. */ +#ifndef PNG_FLOATING_ARITHMETIC_SUPPORTED static png_fixed_point png_product2(png_fixed_point a, png_fixed_point b) { /* The required result is 1/a * 1/b; the following preserves accuracy. */ @@ -3282,8 +3276,9 @@ #endif return 0; /* overflow */ } +#endif /* The inverse of the above. */ png_fixed_point png_reciprocal2(png_fixed_point a, png_fixed_point b) @@ -3660,8 +3655,9 @@ else return png_gamma_16bit_correct(value, gamma_val); } +#if 0 /* Internal function to build a single 16-bit table - the table consists of * 'num' 256 entry subtables, where 'num' is determined by 'shift' - the amount * to shift the input values right (or 16-number_of_signifiant_bits). * @@ -3669,9 +3665,9 @@ * png_error (i.e. if one of the mallocs below fails) - i.e. the *table argument * should be somewhere that will be cleaned. */ static void -png_build_16bit_table(png_structrp png_ptr, png_uint_16pp *ptable, +png_build_16bit_table(png_structrp png_ptr, png_uint_16p *ptable, PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val) { /* Various values derived from 'shift': */ PNG_CONST unsigned int num = 1U << (8U - shift); @@ -3750,9 +3746,9 @@ (png_uint_16pp)png_calloc(png_ptr, num * (sizeof (png_uint_16p))); /* 'num' is the number of tables and also the number of low bits of low * bits of the input 16-bit value used to select a table. Each table is - * itself index by the high 8 bits of the value. + * itself indexed by the high 8 bits of the value. */ for (i = 0; i < num; i++) table[i] = (png_uint_16p)png_malloc(png_ptr, 256 * (sizeof (png_uint_16))); @@ -3817,8 +3813,506 @@ else for (i=0; i<256; ++i) table[i] = (png_byte)i; } +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) +static void +png_build_8to16_table(png_structrp png_ptr, png_uint_16pp ptable, + PNG_CONST png_fixed_point gamma_val) +{ + unsigned int i; + png_uint_16p table = *ptable = (png_uint_16p)png_malloc(png_ptr, + sizeof (png_uint_16[256])); + + if (png_gamma_significant(gamma_val)) for (i=0; i<256; i++) + table[i] = png_gamma_16bit_correct(i*257, gamma_val); + + else for (i=0; i<256; ++i) + table[i] = (png_uint_16)(i*257); +} + +static void +png_build_16to8_table(png_structrp png_ptr, png_bytepp ptable8, + png_uint_16pp ptable16, png_fixed_point gamma_val, int gamma_shift) + /* Build a table of (1<<(16-gamma_shift))+1 entries to find 8-bit values + * encoded by gamma_val. The table is to be indexed with a 16-bit value + * scaled down by gamma_shift: + * + * table[(value + (1<<(gamma_shift-1)) >> gamma_shift] + * + * Because of the rounding the table is 2^(16-gamma_shift)+1 entries. + * Each table entry must contain value^gamma_val, rounded to 8 bits. + */ +{ + unsigned int size = 1U << (16-gamma_shift); + unsigned int add = (gamma_shift > 0 ? 1U<<(gamma_shift-1) : 0U); + png_bytep table8; + png_uint_16p table16; + unsigned int i; + + /* If 'table8' it gets the output values as 8-bit bytes, if 'table16' is set + * the same values are scaled by 257 to give 16-bit values. + */ + if (ptable8) + { + table8 = png_voidcast(png_bytep, png_malloc(png_ptr, size+1)); + *ptable8 = table8; + table8[0] = 0; + } + + else + table8 = NULL; + + if (ptable16) + { + table16 = png_voidcast(png_uint_16p, png_malloc(png_ptr, + sizeof (png_uint_16) * (size+1))); + *ptable16 = table16; + table16[0] = 0; + } + + else + table16 = NULL; + + i = 1; + +# define FILL(val) do {\ + if (table8) table8[i] = (val);\ + if (table16) table16[i] = (png_uint_16)((val)*257U);\ + ++i; + } while (0) + + if (gamma_val < PNG_FP_1 - PNG_GAMMA_THRESHOLD_FIXED) + { + /* gamma < 1; the output values will jump by more than one for each table + * entry initially. + */ + png_byte last_out = 0; + + while (i < size) + { + png_byte out = (png_byte)PNG_DIV257(png_gamma_16bit_correct( + i << gamma_shift, gamma_val)); + + FILL(out); + + if (out <= last_out) + { + /* The table values are no longer advancing at each step, swap to + * finding the *last* table index corresponding to this value + * of 'out' - this is the one that corresponds to out+.5, below this + * is calculated as out*257+128; the exact value would be + * out*257+128.5, so we get a lower value, rounding ensures that we + * fill all the table entries corresponding to 'out' (with some very + * small chance of error at the boundaries.) + */ + png_fixed_point gamma_inv = png_reciprocal(gamma_val); + + while (out < 255 && i < size) + { + unsigned int next_index = (png_gamma_16bit_correct(out*257+128, + gamma_inv) + add) >> gamma_shift; + + while (i <= next_index && i < size) + FILL(out); + + ++out; + } + + break; /* fill remaining entries with 255 */ + } + } + } + + else if (gamma_val > PNG_FP_1 + PNG_GAMMA_THRESHOLD_FIXED) + { + /* gamma > 1; initially multiple table entries will correspond to the same + * value, invert the above loops. + */ + png_fixed_point gamma_inv = png_reciprocal(gamma_val); + png_byte out = 0; + + while (out < 255) + { + unsigned int next_index = (png_gamma_16bit_correct(out*257+128, + gamma_inv) + add) >> gamma_shift; + + /* If this 'out' value falls in the same slot as the last one + * recalculate the value for this slot. + */ + if (next_index <= i) + { + i = next_index; + break; + } + + while (i <= next_index && i < size) + FILL(out); + + ++out; + } + + while (i < size && out < 255) + { + out = (png_byte)PNG_DIV257(png_gamma_16bit_correct(i << gamma_shift, + gamma_val)); + FILL(out); + } + } + + else /* gamma_val not significant */ + { + png_byte out = 0; /* current output value */ + + add += 128; + + while (out < 255 && i < size) { + unsigned int next_index = (out*257+add) >> gamma_shift; + + while (i <= next_index && i < size) + FILL(out); + + ++out; + } + } + + /* Fill in the remainder of the table */ + while (i <= size) + FILL(255); +} +#endif /* BACKGROUND || ALPHA_MODE || RGB_TO_GRAY */ +#endif /* UNUSED */ + +#define PNG_GAMMA_TABLE_8 0 /* 8-bit entries in png_byte */ +#define PNG_GAMMA_TABLE_8_IN_16 1 /* 8-bit entries * 257 in png_uint_16 */ +#define PNG_GAMMA_TABLE_16 2 /* 16-bit entries in png_uint_16 */ + +typedef struct +{ + png_fixed_point gamma; + png_uint_32 mult; + unsigned int add; + unsigned int shift; /* input value is (i * mult + add) >> shift */ + unsigned int output; /* One of the above values */ + int adjust; /* Divide or multiple output by 257 */ + png_voidp table; /* Lookup table */ +} gamma_table_data; + +static unsigned int +write_gamma_table_entry(const gamma_table_data *data, png_uint_32 i) + /* Calculate and write a single entry into table[i], the value of the entry + * written is returned. + */ +{ + png_uint_32 in = (i * data->mult + data->add) >> data->shift; + unsigned int out; + + /* If the output is TABLE_8 with no adjust, or the output is not with an + * adjust, use 8-bit correction. + */ + if ((data->output == PNG_GAMMA_TABLE_8) != (data->adjust != 0)) + { + out = png_gamma_8bit_correct((unsigned int)in, data->gamma); + + if (data->adjust != 0) + out *= 257U; + } + + else /* 16-bit correction */ + { + out = png_gamma_16bit_correct((unsigned int)in, data->gamma); + + if (data->adjust != 0) + out = PNG_DIV257(out); + } + + if (data->output == PNG_GAMMA_TABLE_8) + ((png_bytep)data->table)[i] = (png_byte)out; + + else + ((png_uint_16p)data->table)[i] = (png_uint_16)out; + + return out; +} + +static void +write_gamma_table(const gamma_table_data *data, png_uint_32 lo, + unsigned int loval, png_uint_32 hi, unsigned int hival) + /* Fill in gamma table entries between lo and hi, exclusive. The entries at + * table[lo] and table[hi] have already been written, the intervening entries + * are written. + */ +{ + if (hi > lo+1) /* Else nothing to fill in */ + { + if (hival == loval) + { + /* All intervening entries must be the same. */ + if (data->output == PNG_GAMMA_TABLE_8) + { + png_bytep table8 = ((png_bytep)data->table); + + while (++lo < hi) + table8[lo] = (png_byte)loval; + } + + else + { + png_uint_16p table16 = ((png_uint_16p)data->table); + + while (++lo < hi) + table16[lo] = (png_uint_16)loval; + } + } + + else + { + png_uint_32 mid = (lo+hi) >> 1; + unsigned int midval = write_gamma_table_entry(data, mid); + + /* The algorithm used is to divide the entries to be written in half + * and fill in the middle. For all practical tables with significant + * gamma this will result in a performance gain because the expensive + * gamma correction arithmetic is avoided for some entries. + */ + write_gamma_table(data, lo, loval, mid, midval); + write_gamma_table(data, mid, midval, hi, hival); + } + } +} + +static void * +png_build_gamma_table(png_structrp png_ptr, png_fixed_point gamma_val, + unsigned int output/*as above*/, unsigned int input_depth, int use_shift) + /* Build a gamma lookup table to encode input_depth bit input values. + * The table will have 2^input_depth entries plus an extra one if use_shift + * is specified. With shift the table is accessed: + * + * table[(original-value + rounding) >> shift] + * + * And an extra entry exists to accomodate overflow of original-value on + * rounding. If use_shift is not specified the table is accessed with an + * input_depth bit value and the original values must have been correctly + * scaled to this range (not using a shift!) + * + * Each table entry contains input-value^gamma_val rounded to the output + * precision. This is 8 bit precision unless output is specified as + * PNG_GAMMA_TABLE_16, in which case it is 16-bit precision. For + * PNG_GAMMA_TABLE_8_IN_16 the 8-bit value is scaled to 16-bits by + * multiplying by 257. + */ +{ + png_uint_32 size; + unsigned int hival; + gamma_table_data data; + + /* If use_shift is true or if the input or output is not 8-bit the gamma + * correction will use the 16-bit correction code. This requires a value in + * the range 0..65535. For use_shift the value is simply: + * + * input << shift + * + * For the scaling case the value is: + * + * round(input * 65535 / ((1<> shift; + * + * With 'mult' and 'add' chosen to minimize the error for all input values + * in the range 0..((1< PNG_GAMMA_TABLE_8; + + if (use_shift) + { + /* The multiplier does the shift: */ + data.mult = 1U << (8-input_depth); + data.add = 0; + data.shift = 0; + if (input_depth < 8) ++size; + } + + else + { + data.mult = multadd255[input_depth-1].mult; + data.add = multadd255[input_depth-1].add; + data.shift = multadd255[input_depth-1].shift; + } + } + + else + { + /* 16-bit correction is used for cases where input or output require more + * than 8 bits. + */ + data.adjust = output == PNG_GAMMA_TABLE_8; + + if (use_shift) + { + data.mult = 1U << (16-input_depth); + data.add = 0; + data.shift = 0; + if (input_depth < 16) ++size; + } + + else + { + data.mult = multadd65535[input_depth-1].mult; + data.add = multadd65535[input_depth-1].add; + data.shift = multadd65535[input_depth-1].shift; + } + } + + if (output == PNG_GAMMA_TABLE_8) + { + data.table = png_malloc(png_ptr, size * sizeof (png_byte)); + ((png_bytep)data.table)[0] = 0; + hival = ((png_bytep)data.table)[size-1] = 255; + } + + else + { + /* Output is 16 bits, although it may only have 8 bits of precision */ + data.table = png_malloc(png_ptr, size * sizeof (png_uint_16)); + ((png_uint_16p)data.table)[0] = 0; + hival = ((png_uint_16p)data.table)[size-1] = 65535; + } + + if (png_gamma_significant(gamma_val)) + write_gamma_table(&data, 0, 0, size-1, hival); + + else /* gamma_val not significant */ + { + if (output == PNG_GAMMA_TABLE_8) + { + png_uint_32 i; + png_bytep table8 = ((png_bytep)data.table); + + if (data.adjust) + for (i=1; i> + data.shift); + + else + for (i=1; i> data.shift); + } + + else + { + png_uint_32 i; + png_uint_16p table16 = ((png_uint_16p)data.table); + + if (data.adjust) + for (i=1; i> + data.shift) * 257U); + + else + for (i=1; i> + data.shift); + } + } + + return data.table; +} + /* Used from png_read_destroy and below to release the memory used by the gamma * tables. */ void /* PRIVATE */ @@ -3826,19 +4320,10 @@ { png_free(png_ptr, png_ptr->gamma_table); png_ptr->gamma_table = NULL; - if (png_ptr->gamma_16_table != NULL) - { - int i; - int istop = (1 << (8 - png_ptr->gamma_shift)); - for (i = 0; i < istop; i++) - { - png_free(png_ptr, png_ptr->gamma_16_table[i]); - } png_free(png_ptr, png_ptr->gamma_16_table); png_ptr->gamma_16_table = NULL; - } #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) @@ -3846,30 +4331,12 @@ png_ptr->gamma_from_1 = NULL; png_free(png_ptr, png_ptr->gamma_to_1); png_ptr->gamma_to_1 = NULL; - if (png_ptr->gamma_16_from_1 != NULL) - { - int i; - int istop = (1 << (8 - png_ptr->gamma_shift)); - for (i = 0; i < istop; i++) - { - png_free(png_ptr, png_ptr->gamma_16_from_1[i]); - } png_free(png_ptr, png_ptr->gamma_16_from_1); png_ptr->gamma_16_from_1 = NULL; - } - if (png_ptr->gamma_16_to_1 != NULL) - { - int i; - int istop = (1 << (8 - png_ptr->gamma_shift)); - for (i = 0; i < istop; i++) - { - png_free(png_ptr, png_ptr->gamma_16_to_1[i]); - } png_free(png_ptr, png_ptr->gamma_16_to_1); png_ptr->gamma_16_to_1 = NULL; - } #endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ } /* We build the 8- or 16-bit gamma tables here. Note that for 16-bit @@ -3877,9 +4344,9 @@ * the future. Note also how the gamma_16 tables are segmented so that * we don't need to allocate > 64K chunks for a full 16-bit table. */ void /* PRIVATE */ -png_build_gamma_table(png_structrp png_ptr, int bit_depth) +png_build_gamma_tables(png_structrp png_ptr, int bit_depth) { png_debug(1, "in png_build_gamma_table"); /* Remove any existing table; this copes with multiple calls to @@ -3895,29 +4362,46 @@ } if (bit_depth <= 8) { - png_build_8bit_table(png_ptr, &png_ptr->gamma_table, - png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->colorspace.gamma, - png_ptr->screen_gamma) : PNG_FP_1); + png_ptr->gamma_table = png_voidcast(png_bytep, png_build_gamma_table( + png_ptr, png_ptr->screen_gamma > 0 ? + png_reciprocal2(png_ptr->colorspace.gamma, png_ptr->screen_gamma) : + PNG_FP_1, PNG_GAMMA_TABLE_8, 8/*input depth*/, 0/*scale*/)); #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) if (png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) { - png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1, - png_reciprocal(png_ptr->colorspace.gamma)); + /* This sets the accuracy of 8-bit composition and the 8-bit RGB to gray + * conversion - PNG_MAX_GAMMA_8 (the number of bits in the sixteen bit + * value that are considered significant.) + */ + png_ptr->gamma_to_1 = png_voidcast(png_uint_16p, png_build_gamma_table( + png_ptr, png_reciprocal(png_ptr->colorspace.gamma), + PNG_GAMMA_TABLE_16, 8/*input depth*/, 0/*scale*/)); + + png_ptr->gamma_from_1 = png_voidcast(png_bytep, png_build_gamma_table( + png_ptr, png_ptr->screen_gamma > 0 ? + png_reciprocal(png_ptr->screen_gamma) : + png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */, + PNG_GAMMA_TABLE_8, PNG_MAX_GAMMA_8/*input depth*/, 1/*shift*/)); - png_build_8bit_table(png_ptr, &png_ptr->gamma_from_1, - png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) : - png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */); + png_ptr->gamma_shift = 16-PNG_MAX_GAMMA_8; } #endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ } else { png_byte shift, sig_bit; + int table_type; + +# ifdef PNG_16BIT_SUPPORTED + table_type = PNG_GAMMA_TABLE_16; +# else + table_type = PNG_GAMMA_TABLE_8_IN_16; +# endif if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) { sig_bit = png_ptr->sig_bit.red; @@ -3930,26 +4414,8 @@ } else sig_bit = png_ptr->sig_bit.gray; - /* 16-bit gamma code uses this equation: - * - * ov = table[(iv & 0xff) >> gamma_shift][iv >> 8] - * - * Where 'iv' is the input color value and 'ov' is the output value - - * pow(iv, gamma). - * - * Thus the gamma table consists of up to 256 256 entry tables. The table - * is selected by the (8-gamma_shift) most significant of the low 8 bits of - * the color value then indexed by the upper 8 bits: - * - * table[low bits][high 8 bits] - * - * So the table 'n' corresponds to all those 'iv' of: - * - * ..<(n+1 << gamma_shift)-1> - * - */ if (sig_bit > 0 && sig_bit < 16U) shift = (png_byte)(16U - sig_bit); /* shift == insignificant bits */ else @@ -3958,53 +4424,42 @@ if (png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) { /* PNG_MAX_GAMMA_8 is the number of bits to keep - effectively * the significant bits in the *input* when the output will - * eventually be 8 bits. By default it is 11. + * eventually be 8 bits. */ if (shift < (16U - PNG_MAX_GAMMA_8)) shift = (16U - PNG_MAX_GAMMA_8); - } - if (shift > 8U) - shift = 8U; /* Guarantees at least one table! */ + table_type = PNG_GAMMA_TABLE_8_IN_16; + } png_ptr->gamma_shift = shift; -#ifdef PNG_16BIT_SUPPORTED - /* NOTE: prior to 1.5.4 this test used to include PNG_BACKGROUND (now - * PNG_COMPOSE). This effectively smashed the background calculation for - * 16-bit output because the 8-bit table assumes the result will be reduced - * to 8 bits. - */ - if (png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) -#endif - png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift, - png_ptr->screen_gamma > 0 ? png_product2(png_ptr->colorspace.gamma, - png_ptr->screen_gamma) : PNG_FP_1); - -#ifdef PNG_16BIT_SUPPORTED - else - png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift, - png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->colorspace.gamma, - png_ptr->screen_gamma) : PNG_FP_1); -#endif + png_ptr->gamma_16_table = png_voidcast(png_uint_16p, png_build_gamma_table( + png_ptr, png_ptr->screen_gamma > 0 ? png_reciprocal2( + png_ptr->colorspace.gamma, png_ptr->screen_gamma) : PNG_FP_1, + table_type, (16-shift)/*input depth*/, 1/*shift*/)); #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) if (png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) { - png_build_16bit_table(png_ptr, &png_ptr->gamma_16_to_1, shift, - png_reciprocal(png_ptr->colorspace.gamma)); + png_ptr->gamma_16_to_1 = png_voidcast(png_uint_16p, + png_build_gamma_table(png_ptr, + png_reciprocal(png_ptr->colorspace.gamma), PNG_GAMMA_TABLE_16, + (16-shift)/*input depth*/, 1/*shift*/)); /* Notice that the '16 from 1' table should be full precision, however * the lookup on this table still uses gamma_shift, so it can't be. * TODO: fix this. */ - png_build_16bit_table(png_ptr, &png_ptr->gamma_16_from_1, shift, - png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) : - png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */); + png_ptr->gamma_16_from_1 = png_voidcast(png_uint_16p, + png_build_gamma_table(png_ptr, png_ptr->screen_gamma > 0 ? + png_reciprocal(png_ptr->screen_gamma) : + png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */, + PNG_GAMMA_TABLE_16, (16-shift)/*input depth*/, 1/*shift*/)); } #endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ } } diff -ru4NwbB libpng-1.6.0beta33/png.h libpng-1.7.0alpha01/png.h --- libpng-1.6.0beta33/png.h 2012-12-15 08:22:34.934444179 -0600 +++ libpng-1.7.0alpha01/png.h 2012-12-15 10:05:51.244513356 -0600 @@ -1,8 +1,8 @@ /* png.h - header file for PNG reference library * - * libpng version 1.7.0alpha01 - December 15, 2012 + * libpng version 1.6.0beta32 - November 25, 2012 * Copyright (c) 1998-2012 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -10,9 +10,9 @@ * * Authors and maintainers: * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat * libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger - * libpng versions 0.97, January 1998, through 1.7.0alpha01 - December 15, 2012: Glenn + * libpng versions 0.97, January 1998, through 1.6.0beta32 - November 25, 2012: Glenn * See also "Contributing Authors", below. * * Note about libpng version numbers: * @@ -165,9 +165,9 @@ * 1.5.6 15 10506 15.so.15.6[.0] * 1.5.7beta01-05 15 10507 15.so.15.7[.0] * 1.5.7rc01-03 15 10507 15.so.15.7[.0] * 1.5.7 15 10507 15.so.15.7[.0] - * 1.6.0beta01-34 16 10600 16.so.16.0[.0] + * 1.6.0beta01-32 16 10600 16.so.16.0[.0] * * Henceforth the source version will match the shared-library major * and minor numbers; the shared-library major version number will be * used for changes in backward compatibility, as it is intended. The @@ -197,9 +197,9 @@ * this sentence. * * This code is released under the libpng license. * - * libpng versions 1.2.6, August 15, 2004, through 1.7.0alpha01, December 15, 2012, are + * libpng versions 1.2.6, August 15, 2004, through 1.6.0beta32, November 25, 2012, are * Copyright (c) 2004, 2006-2012 Glenn Randers-Pehrson, and are * distributed according to the same disclaimer and license as libpng-1.2.5 * with the following individual added to the list of Contributing Authors: * @@ -309,15 +309,15 @@ /* * Y2K compliance in libpng: * ========================= * - * December 15, 2012 + * November 25, 2012 * * Since the PNG Development group is an ad-hoc body, we can't make * an official declaration. * * This is your unofficial assurance that libpng from version 0.71 and - * upward through 1.7.0alpha01 are Y2K compliant. It is my belief that + * upward through 1.6.0beta32 are Y2K compliant. It is my belief that * earlier versions were also Y2K compliant. * * Libpng only has two year fields. One is a 2-byte unsigned integer * that will hold years up to 65535. The other, which is deprecated, @@ -375,25 +375,25 @@ * skip to the end of this file and read the section entitled 'simplified API'. */ /* Version information for png.h - this should match the version in png.c */ -#define PNG_LIBPNG_VER_STRING "1.7.0alpha01" +#define PNG_LIBPNG_VER_STRING "1.6.0beta32" #define PNG_HEADER_VERSION_STRING \ - " libpng version 1.7.0alpha01 - December 15, 2012\n" + " libpng version 1.6.0beta32 - November 25, 2012\n" -#define PNG_LIBPNG_VER_SONUM %SONUM% -#define PNG_LIBPNG_VER_DLLNUM %DLLNUM% +#define PNG_LIBPNG_VER_SONUM 16 +#define PNG_LIBPNG_VER_DLLNUM 16 /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */ -#define PNG_LIBPNG_VER_MAJOR %MAJOR% -#define PNG_LIBPNG_VER_MINOR %MINOR% -#define PNG_LIBPNG_VER_RELEASE %RELEASE% +#define PNG_LIBPNG_VER_MAJOR 1 +#define PNG_LIBPNG_VER_MINOR 6 +#define PNG_LIBPNG_VER_RELEASE 0 /* This should match the numeric part of the final component of * PNG_LIBPNG_VER_STRING, omitting any leading zero: */ -#define PNG_LIBPNG_VER_BUILD %BUILDNUM% +#define PNG_LIBPNG_VER_BUILD 32 /* Release Status */ #define PNG_LIBPNG_BUILD_ALPHA 1 #define PNG_LIBPNG_BUILD_BETA 2 @@ -408,17 +408,17 @@ PNG_LIBPNG_BUILD_SPECIAL */ #define PNG_LIBPNG_BUILD_SPECIAL 32 /* Cannot be OR'ed with PNG_LIBPNG_BUILD_PRIVATE */ -#define PNG_LIBPNG_BUILD_BASE_TYPE %BUILDTYPE% +#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_BETA /* Careful here. At one time, Guy wanted to use 082, but that would be octal. * We must not include leading zeros. * Versions 0.7 through 1.0.0 were in the range 0 to 100 here (only * version 1.0.0 was mis-numbered 100 instead of 10000). From * version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release */ -#define PNG_LIBPNG_VER %VER_NUM% /* %MAJOR%.%MINOR%.%RELEASE% */ +#define PNG_LIBPNG_VER 10600 /* 1.6.0 */ /* Library configuration: these options cannot be changed after * the library has been built. */ @@ -521,9 +521,9 @@ /* This triggers a compiler error in png.c, if png.c and png.h * do not agree upon the version number. */ -typedef char* png_libpng_version_%_VER_%; +typedef char* png_libpng_version_1_6_0beta32; /* Basic control structions. Read libpng-manual.txt or libpng.3 for more info. * * png_struct is the cache of information used while reading or writing a single @@ -1115,15 +1115,12 @@ #ifdef PNG_TIME_RFC1123_SUPPORTED /* Convert to a US string format: there is no localization support in this * routine. The original implementation used a 29 character buffer in - * png_struct, this will be removed in future versions. + * png_struct, this has been removed. */ -#if PNG_LIBPNG_VER < 10700 -/* To do: remove this from libpng17 (and from libpng17/png.c and pngstruct.h) */ -PNG_EXPORTA(23, png_const_charp, png_convert_to_rfc1123, (png_structrp png_ptr, - png_const_timep ptime),PNG_DEPRECATED); -#endif +PNG_REMOVED(23, png_const_charp, png_convert_to_rfc1123, (png_structrp png_ptr, + png_const_timep ptime),PNG_DEPRECATED) PNG_EXPORT(241, int, png_convert_to_rfc1123_buffer, (char out[29], png_const_timep ptime)); #endif @@ -1618,32 +1615,38 @@ */ PNG_EXPORT(67, void, png_set_filter, (png_structrp png_ptr, int method, int filters)); -/* Flags for png_set_filter() to say which filters to use. The flags - * are chosen so that they don't conflict with real filter types - * below, in case they are supplied instead of the #defined constants. - * These values should NOT be changed. - */ -#define PNG_NO_FILTERS 0x00 -#define PNG_FILTER_NONE 0x08 -#define PNG_FILTER_SUB 0x10 -#define PNG_FILTER_UP 0x20 -#define PNG_FILTER_AVG 0x40 -#define PNG_FILTER_PAETH 0x80 -#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \ - PNG_FILTER_AVG | PNG_FILTER_PAETH) - /* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. - * These defines should NOT be changed. + * These defines match the values in the PNG specification. */ #define PNG_FILTER_VALUE_NONE 0 #define PNG_FILTER_VALUE_SUB 1 #define PNG_FILTER_VALUE_UP 2 #define PNG_FILTER_VALUE_AVG 3 #define PNG_FILTER_VALUE_PAETH 4 #define PNG_FILTER_VALUE_LAST 5 +/* The above values are valid arguments to png_set_filter() if only a single + * filter is to be used. If multiple filters are to be allowed (the default is + * to allow any of them) then a combination of the following masks must be used + * and the low three bits of the argument to png_set_filter must be 0. + * + * The resultant argument fits in a single byte. + */ +#define PNG_FILTER_NONE (0x08 << PNG_FILTER_VALUE_NONE) +#define PNG_FILTER_SUB (0x08 << PNG_FILTER_VALUE_SUB) +#define PNG_FILTER_UP (0x08 << PNG_FILTER_VALUE_UP) +#define PNG_FILTER_AVG (0x08 << PNG_FILTER_VALUE_AVG) +#define PNG_FILTER_PAETH (0x08 << PNG_FILTER_VALUE_PAETH) + +/* Then two convenience values. PNG_NO_FILTERS is the same as + * PNG_FILTER_VALUE_NONE, but this is harmless because they mean the same thing. + */ +#define PNG_NO_FILTERS 0x00 +#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \ + PNG_FILTER_AVG | PNG_FILTER_PAETH) + #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* EXPERIMENTAL */ /* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_ * defines, either the default (minimum-sum-of-absolute-differences), or * the experimental method (weighted-minimum-sum-of-absolute-differences). diff -ru4NwbB libpng-1.6.0beta33/pngconf.h libpng-1.7.0alpha01/pngconf.h --- libpng-1.6.0beta33/pngconf.h 2012-12-15 08:22:34.942006734 -0600 +++ libpng-1.7.0alpha01/pngconf.h 2012-12-15 10:05:51.252400150 -0600 @@ -1,8 +1,8 @@ /* pngconf.h - machine configurable file for libpng * - * libpng version 1.7.0alpha01 - December 15, 2012 + * libpng version 1.6.0beta32 - November 25, 2012 * * Copyright (c) 1998-2012 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) diff -ru4NwbB libpng-1.6.0beta33/pngerror.c libpng-1.7.0alpha01/pngerror.c --- libpng-1.6.0beta33/pngerror.c 2012-12-15 08:22:35.003725735 -0600 +++ libpng-1.7.0alpha01/pngerror.c 2012-12-15 10:05:51.318655496 -0600 @@ -1,8 +1,8 @@ /* pngerror.c - stub functions for i/o and memory allocation * - * Last changed in libpng 1.6.0 [(PENDING RELEASE)] + * Last changed in libpng 1.6.0 [(PENDING RELEASE)] * Copyright (c) 1998-2012 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -162,9 +162,9 @@ case PNG_NUMBER_FORMAT_02u: /* Expects at least 2 digits. */ mincount = 2; - /* FALL THROUGH */ + /* fall through */ case PNG_NUMBER_FORMAT_u: *--end = digits[number % 10]; number /= 10; @@ -172,9 +172,9 @@ case PNG_NUMBER_FORMAT_02x: /* This format expects at least two digits */ mincount = 2; - /* FALL THROUGH */ + /* fall through */ case PNG_NUMBER_FORMAT_x: *--end = digits[number & 0xf]; number >>= 4; diff -ru4NwbB libpng-1.6.0beta33/pngget.c libpng-1.7.0alpha01/pngget.c --- libpng-1.6.0beta33/pngget.c 2012-12-15 08:22:35.012327871 -0600 +++ libpng-1.7.0alpha01/pngget.c 2012-12-15 10:05:51.327423151 -0600 @@ -1,8 +1,8 @@ /* pngget.c - retrieval of values from info struct * - * Last changed in libpng 1.6.0 [(PENDING RELEASE)] + * Last changed in libpng 1.6.0 [(PENDING RELEASE)] * Copyright (c) 1998-2012 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * diff -ru4NwbB libpng-1.6.0beta33/pngmem.c libpng-1.7.0alpha01/pngmem.c --- libpng-1.6.0beta33/pngmem.c 2012-12-15 08:22:35.018121390 -0600 +++ libpng-1.7.0alpha01/pngmem.c 2012-12-15 10:05:51.333218736 -0600 @@ -1,8 +1,8 @@ /* pngmem.c - stub functions for memory allocation * - * Last changed in libpng 1.6.0 [(PENDING RELEASE)] + * Last changed in libpng 1.6.0 [(PENDING RELEASE)] * Copyright (c) 1998-2012 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * diff -ru4NwbB libpng-1.6.0beta33/pngpread.c libpng-1.7.0alpha01/pngpread.c --- libpng-1.6.0beta33/pngpread.c 2012-12-15 08:22:35.026756641 -0600 +++ libpng-1.7.0alpha01/pngpread.c 2012-12-15 10:05:51.341991614 -0600 @@ -1,8 +1,8 @@ /* pngpread.c - read a png file in push mode * - * Last changed in libpng 1.6.0 [(PENDING RELEASE)] + * Last changed in libpng 1.6.0 [(PENDING RELEASE)] * Copyright (c) 1998-2012 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * diff -ru4NwbB libpng-1.6.0beta33/pngpriv.h libpng-1.7.0alpha01/pngpriv.h --- libpng-1.6.0beta33/pngpriv.h 2012-12-15 08:22:34.952465247 -0600 +++ libpng-1.7.0alpha01/pngpriv.h 2012-12-15 10:05:51.263343874 -0600 @@ -5,9 +5,9 @@ * Copyright (c) 1998-2012 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * - * Last changed in libpng 1.6.0 [(PENDING RELEASE)] + * Last changed in libpng 1.6.0 [(PENDING RELEASE)] * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer * and license in png.h @@ -457,9 +457,9 @@ /* 0x80 (unused) */ #define PNG_HAVE_CHUNK_HEADER 0x100 #define PNG_WROTE_tIME 0x200 #define PNG_WROTE_INFO_BEFORE_PLTE 0x400 -#define PNG_BACKGROUND_IS_GRAY 0x800 + /* 0x800 (unused) */ #define PNG_HAVE_PNG_SIGNATURE 0x1000 #define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */ /* 0x4000 (unused) */ #define PNG_IS_READ_STRUCT 0x8000 /* Else is a write struct */ @@ -472,9 +472,9 @@ #define PNG_SWAP_BYTES 0x0010 #define PNG_INVERT_MONO 0x0020 #define PNG_QUANTIZE 0x0040 #define PNG_COMPOSE 0x0080 /* Was PNG_BACKGROUND */ -#define PNG_BACKGROUND_EXPAND 0x0100 + /* 0x0100 unused */ #define PNG_EXPAND_16 0x0200 /* Added to libpng 1.5.2 */ #define PNG_16_TO_8 0x0400 /* Becomes 'chop' in 1.5.4 */ #define PNG_RGBA 0x0800 #define PNG_EXPAND 0x1000 @@ -528,10 +528,10 @@ #define PNG_FLAG_STRIP_ERROR_TEXT 0x80000 #define PNG_FLAG_BENIGN_ERRORS_WARN 0x100000 /* Added to libpng-1.4.0 */ #define PNG_FLAG_APP_WARNINGS_WARN 0x200000 /* Added to libpng-1.6.0 */ #define PNG_FLAG_APP_ERRORS_WARN 0x400000 /* Added to libpng-1.6.0 */ - /* 0x800000 unused */ - /* 0x1000000 unused */ +#define PNG_FLAG_BACKGROUND_IS_GRAY 0x800000 +#define PNG_FLAG_BACKGROUND_EXPAND 0x1000000 /* 0x2000000 unused */ /* 0x4000000 unused */ /* 0x8000000 unused */ /* 0x10000000 unused */ @@ -732,8 +732,18 @@ png_compression_bufferp *list),PNG_EMPTY); /* Free the buffer list used by the compressed write code. */ #endif +#ifdef PNG_WRITE_FILTER_SUPPORTED +PNG_INTERNAL_FUNCTION(void,png_write_alloc_filter_row_buffers, + (png_structrp png_ptr, int filters),PNG_EMPTY); + /* Allocate pixel row buffers to cache filtered rows while testing candidate + * filters. + * TODO: avoid this, only one spare row buffer (at most) is required, this + * wastes a lot of memory for large images. + */ +#endif + #if defined(PNG_FLOATING_POINT_SUPPORTED) && \ !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) && \ (defined(PNG_gAMA_SUPPORTED) || defined(PNG_cHRM_SUPPORTED) || \ defined(PNG_sCAL_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) || \ @@ -1801,9 +1811,9 @@ PNG_INTERNAL_FUNCTION(png_byte,png_gamma_8bit_correct,(unsigned int value, png_fixed_point gamma_value),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_destroy_gamma_table,(png_structrp png_ptr), PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_build_gamma_table,(png_structrp png_ptr, +PNG_INTERNAL_FUNCTION(void,png_build_gamma_tables,(png_structrp png_ptr, int bit_depth),PNG_EMPTY); #endif /* SIMPLIFIED READ/WRITE SUPPORT */ diff -ru4NwbB libpng-1.6.0beta33/pngread.c libpng-1.7.0alpha01/pngread.c --- libpng-1.6.0beta33/pngread.c 2012-12-15 08:22:35.042416044 -0600 +++ libpng-1.7.0alpha01/pngread.c 2012-12-15 10:05:51.358080657 -0600 @@ -1,8 +1,8 @@ /* pngread.c - read a PNG file * - * Last changed in libpng 1.6.0 [(PENDING RELEASE)] + * Last changed in libpng 1.6.0 [(PENDING RELEASE)] * Copyright (c) 1998-2012 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * diff -ru4NwbB libpng-1.6.0beta33/pngrio.c libpng-1.7.0alpha01/pngrio.c --- libpng-1.6.0beta33/pngrio.c 2012-12-15 08:22:35.048045941 -0600 +++ libpng-1.7.0alpha01/pngrio.c 2012-12-15 10:05:51.364078284 -0600 @@ -1,8 +1,8 @@ /* pngrio.c - functions for data input * - * Last changed in libpng 1.6.0 [(PENDING RELEASE)] + * Last changed in libpng 1.6.0 [(PENDING RELEASE)] * Copyright (c) 1998-2012 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -101,16 +101,18 @@ #else png_ptr->read_data_fn = read_data_fn; #endif +#ifdef PNG_WRITE_SUPPORTED /* It is an error to write to a read device */ if (png_ptr->write_data_fn != NULL) { png_ptr->write_data_fn = NULL; png_warning(png_ptr, "Can't set both read_data_fn and write_data_fn in the" " same structure"); } +#endif #ifdef PNG_WRITE_FLUSH_SUPPORTED png_ptr->output_flush_fn = NULL; #endif diff -ru4NwbB libpng-1.6.0beta33/pngrtran.c libpng-1.7.0alpha01/pngrtran.c --- libpng-1.6.0beta33/pngrtran.c 2012-12-15 08:22:35.066116908 -0600 +++ libpng-1.7.0alpha01/pngrtran.c 2012-12-15 10:05:51.382798290 -0600 @@ -1,8 +1,8 @@ /* pngrtran.c - transforms the data in a row for PNG readers * - * Last changed in libpng 1.6.0 [(PENDING RELEASE)] + * Last changed in libpng 1.6.0 [(PENDING RELEASE)] * Copyright (c) 1998-2012 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -129,11 +129,13 @@ if (!png_rtran_ok(png_ptr, 0) || background_color == NULL) return; - if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN) + if (background_gamma_code != PNG_BACKGROUND_GAMMA_SCREEN && + background_gamma_code != PNG_BACKGROUND_GAMMA_FILE && + background_gamma_code != PNG_BACKGROUND_GAMMA_UNIQUE) { - png_warning(png_ptr, "Application must supply a known background gamma"); + png_app_error(png_ptr, "invalid gamma type"); return; } png_ptr->transformations |= PNG_COMPOSE | PNG_STRIP_ALPHA; @@ -142,12 +144,14 @@ png_ptr->background = *background_color; png_ptr->background_gamma = background_gamma; png_ptr->background_gamma_type = (png_byte)(background_gamma_code); + if (need_expand) - png_ptr->transformations |= PNG_BACKGROUND_EXPAND; + png_ptr->flags |= PNG_FLAG_BACKGROUND_EXPAND; + else - png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND; + png_ptr->flags &= ~PNG_FLAG_BACKGROUND_EXPAND; } # ifdef PNG_FLOATING_POINT_SUPPORTED void PNGAPI @@ -366,9 +370,9 @@ /* And obtain alpha pre-multiplication by composing on black: */ memset(&png_ptr->background, 0, (sizeof png_ptr->background)); png_ptr->background_gamma = png_ptr->colorspace.gamma; /* just in case */ png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_FILE; - png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND; + png_ptr->flags &= ~PNG_FLAG_BACKGROUND_EXPAND; if (png_ptr->transformations & PNG_COMPOSE) png_error(png_ptr, "conflicting calls to set alpha mode and background"); @@ -1004,9 +1008,11 @@ green_int = (png_uint_16)(((png_uint_32)green*32768)/100000); png_ptr->rgb_to_gray_red_coeff = red_int; png_ptr->rgb_to_gray_green_coeff = green_int; - png_ptr->rgb_to_gray_coefficients_set = 1; +# if defined PNG_COLORS_SPACE_SUPPORTED || defined PNG_GAMMA_SUPPORTED + png_ptr->colorspace.flags |= PNG_COLORSPACE_RGB_TO_GRAY_SET; +# endif } else { @@ -1090,25 +1096,265 @@ /* Initialize everything needed for the read. This includes modifying * the palette. */ +#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) +static void +gamma_correct_background(unsigned int value, unsigned int depth, + png_uint_16p backgroundp, png_uint_16p background_1p, + png_fixed_point gamma_correct, png_fixed_point gamma_to_1) +{ + switch (depth) + { + case 8: + if (gamma_correct != PNG_FP_1) + *backgroundp = png_gamma_8bit_correct(value, gamma_correct); + + else + *backgroundp = (png_uint_16)value; + + if (gamma_to_1 != PNG_FP_1) + *background_1p = png_gamma_16bit_correct(value*257, gamma_to_1); + + else + *background_1p = (png_uint_16)(value*257); + + return; + + case 16: + if (gamma_correct != PNG_FP_1) + *backgroundp = png_gamma_16bit_correct(value, gamma_correct); + + else + *backgroundp = (png_uint_16)value; + + if (gamma_to_1 != PNG_FP_1) + *background_1p = png_gamma_16bit_correct(value, gamma_to_1); + + else + *background_1p = (png_uint_16)value; + + return; + + default: + /* Low bit depth gray levels; do no harm. */ + break; + } + + *backgroundp = (png_uint_16)value; + *background_1p = 0; /* should not be used */ +} -/*For the moment 'png_init_palette_transformations' and - * 'png_init_rgb_transformations' only do some flag canceling optimizations. - * The intent is that these two routines should have palette or rgb operations - * extracted from 'png_init_read_transformations'. - */ static void /* PRIVATE */ -png_init_palette_transformations(png_structrp png_ptr) +png_init_background_transformations(png_structrp png_ptr) + /* Set the png_ptr->background and png_ptr->background_1 members correctly + * for the bit depth and format. + */ { - /* Called to handle the (input) palette case. In png_do_read_transformations - * the first step is to expand the palette if requested, so this code must - * take care to only make changes that are invariant with respect to the - * palette expansion, or only do them if there is no expansion. + /* png_ptr->background is only assigned by png_set_background and + * png_set_alpha_mode (which just zeros out the fields.) png_set_background + * can set the PNG_FLAG_BACKGROUND_EXPAND flag if the input value is in the + * file format, for example if it comes from a bKGD chunk. + * + * Under some circumstances deficiencies in the current libpng code mean that + * the bit depth of the values must differ from the final bit depth; the bit + * depth has to match that at which the processing of the image pixels + * happens and this is not always the final bit depth. This is fixed up + * here. * - * STRIP_ALPHA has already been handled in the caller (by setting num_trans - * to 0.) + * First find the required depth. */ + unsigned int bit_depth, required_bit_depth; + unsigned int color_type = png_ptr->color_type; + const png_uint_32 transform = png_ptr->transformations; + const int expand = (png_ptr->flags & PNG_FLAG_BACKGROUND_EXPAND) != 0; + + if (color_type & PNG_COLOR_MASK_PALETTE) + required_bit_depth = bit_depth = 8; + + else + { + required_bit_depth = bit_depth = png_ptr->bit_depth; + + /* But not PNG_EXPAND_16 at present because it happens after the compose + * operation where the background is used! + */ + if (bit_depth < 8 && (transform & PNG_EXPAND) != 0) + required_bit_depth = 8; + } + + /* bit_depth and color_type now refer to the original file data and + * required_bit_depth is correct for the processing libpng does, however it + * does not necessarily match the output the application gets, fix that and + * the color type here: + */ + if (!expand) + { + /* The background bit_depth and color_type need correcting */ + if ((transform & PNG_EXPAND) != 0) + color_type &= ~PNG_COLOR_MASK_PALETTE; + + /* The RGB<->gray transformations do the to gray operation first, then the + * from gray. + */ + if ((transform & PNG_RGB_TO_GRAY) != 0) + color_type &= ~PNG_COLOR_MASK_COLOR; + + if ((transform & PNG_GRAY_TO_RGB) != 0) + color_type |= PNG_COLOR_MASK_COLOR; + + bit_depth = required_bit_depth; + + /* The expansion to 16 bits and the scaling back from 16 bits per + * component to only 8 happens after the background processing (at + * present) so these transforms only affect the screen value, not the + * required value. Note that the 16_TO_8 conversions happen before the 8 + * to 16 one, so in theory both could occur - the order of the tests below + * must be correct! + * + * TODO: Note that the second of these changes cause an input 16-bit + * background value to be temporarily crushed to 8-bits per component, + * losing precision. This is a bug and should be fixed. + */ + if (bit_depth == 16 && + (transform & (PNG_16_TO_8|PNG_SCALE_16_TO_8)) != 0) + bit_depth = 8; + + if (bit_depth == 8 && (color_type & PNG_COLOR_MASK_PALETTE) == 0 && + (transform & PNG_EXPAND_16) != 0) + bit_depth = 16; + } + + /* Now make the background have the correct format, this involves reading the + * correct fields from png_ptr->background, adjusting the bit depth of the + * result and potentially gamma correcting the value then calculating the + * png_ptr->background_1 values too. + */ + { + unsigned int mult = 1; + png_fixed_point gamma_to_1, gamma_correct; + + switch (png_ptr->background_gamma_type) + { + case PNG_BACKGROUND_GAMMA_SCREEN: + gamma_to_1 = png_ptr->screen_gamma; + gamma_correct = PNG_FP_1; + break; + + case PNG_BACKGROUND_GAMMA_FILE: + gamma_to_1 = png_reciprocal(png_ptr->colorspace.gamma); + gamma_correct = png_reciprocal2(png_ptr->colorspace.gamma, + png_ptr->screen_gamma); + break; + + case PNG_BACKGROUND_GAMMA_UNIQUE: + gamma_to_1 = png_reciprocal(png_ptr->background_gamma); + gamma_correct = png_reciprocal2(png_ptr->background_gamma, + png_ptr->screen_gamma); + break; + + default: + gamma_to_1 = PNG_FP_1; + gamma_correct = PNG_FP_1; + break; + } + +# define CORRECT(v, c)\ + gamma_correct_background((v)*mult, bit_depth,\ + &png_ptr->background.c, &png_ptr->background_1.c,\ + gamma_correct, gamma_to_1);\ + if (bit_depth > required_bit_depth)\ + png_ptr->background.c =\ + (png_uint_16)PNG_DIV257(png_ptr->background.c) + + /* The multiplier 'mult' scales the values to 'required_depth', + * 'bit_depth' is the depth of the resultant values. + */ + while (bit_depth < required_bit_depth) + mult += mult << bit_depth, bit_depth <<= 1; + + /* In the event that this still leaves the background bit depth greater + * than the libpng required depth scale the values back to the 8-bit + * range, the test below verifies that this is correct. + */ + if (bit_depth > required_bit_depth) + { + if (bit_depth != 16 || required_bit_depth != 8) + png_error(png_ptr, "internal error handling background depth"); + } + + if ((color_type & PNG_COLOR_MASK_COLOR) != 0) + { + png_ptr->flags &= ~PNG_FLAG_BACKGROUND_IS_GRAY; /* checked below */ + + /* If need_expand was passed to png_set_background the background value + * was in the file format, therefore if the file is a palette file the + * background will have been an index into the palette. Notice that if + * need_expand was false then the color is RGB even if the output still + * has a palette. + */ + if (expand && (color_type & PNG_COLOR_MASK_PALETTE) != 0) + { + unsigned int index = png_ptr->background.index; + + if (index < png_ptr->num_palette && png_ptr->palette != NULL) + { + /* In fact 'mult' is always 1 at present in this case */ + CORRECT(png_ptr->palette[index].red, red); + CORRECT(png_ptr->palette[index].green, green); + CORRECT(png_ptr->palette[index].blue, blue); + } + + else + { + png_app_error(png_ptr, "out of range background index"); + memset(&png_ptr->background, 0, sizeof png_ptr->background); + memset(&png_ptr->background_1, 0, sizeof png_ptr->background_1); + } + } + + else + { + CORRECT(png_ptr->background.red, red); + CORRECT(png_ptr->background.green, green); + CORRECT(png_ptr->background.blue, blue); + } + + if (png_ptr->background.red == png_ptr->background.blue && + png_ptr->background.red == png_ptr->background.green) + { + png_ptr->flags |= PNG_FLAG_BACKGROUND_IS_GRAY; + png_ptr->background.gray = png_ptr->background.red; + png_ptr->background_1.gray = png_ptr->background_1.red; + } + + else + png_ptr->background.gray = png_ptr->background_1.gray = 0; + } + + else + { + png_ptr->flags |= PNG_FLAG_BACKGROUND_IS_GRAY; + + CORRECT(png_ptr->background.gray, gray); + + png_ptr->background.red = + png_ptr->background.green = + png_ptr->background.blue = png_ptr->background.gray; + + png_ptr->background_1.red = + png_ptr->background_1.green = + png_ptr->background_1.blue = png_ptr->background_1.gray; + } +# undef CORRECT + } +} +#endif /* READ_BACKGROUND || READ_ALPHA_MODE */ + +static void /* PRIVATE */ +png_init_palette_transformations(png_structrp png_ptr) +{ int input_has_alpha = 0; int input_has_transparency = 0; if (png_ptr->num_trans > 0) @@ -1128,57 +1374,17 @@ /* If no alpha we can optimize. */ if (!input_has_alpha) { /* Any alpha means background and associative alpha processing is - * required, however if the alpha is 0 or 1 throughout OPTIIMIZE_ALPHA + * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA * and ENCODE_ALPHA are irrelevant. */ png_ptr->transformations &= ~PNG_ENCODE_ALPHA; png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; if (!input_has_transparency) - png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND); - } - -#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) - /* png_set_background handling - deals with the complexity of whether the - * background color is in the file format or the screen format in the case - * where an 'expand' will happen. - */ - - /* The following code cannot be entered in the alpha pre-multiplication case - * because PNG_BACKGROUND_EXPAND is cancelled below. - */ - if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && - (png_ptr->transformations & PNG_EXPAND)) - { - { - png_ptr->background.red = - png_ptr->palette[png_ptr->background.index].red; - png_ptr->background.green = - png_ptr->palette[png_ptr->background.index].green; - png_ptr->background.blue = - png_ptr->palette[png_ptr->background.index].blue; - -#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED - if (png_ptr->transformations & PNG_INVERT_ALPHA) - { - if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) - { - /* Invert the alpha channel (in tRNS) unless the pixels are - * going to be expanded, in which case leave it for later - */ - int i, istop = png_ptr->num_trans; - - for (i=0; itrans_alpha[i] = (png_byte)(255 - - png_ptr->trans_alpha[i]); - } - } -#endif /* PNG_READ_INVERT_ALPHA_SUPPORTED */ + png_ptr->transformations &= ~PNG_COMPOSE; } - } /* background expand and (therefore) no alpha association. */ -#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */ } static void /* PRIVATE */ png_init_rgb_transformations(png_structrp png_ptr) @@ -1202,68 +1408,10 @@ png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; # endif if (!input_has_transparency) - png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND); - } - -#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED) - /* png_set_background handling - deals with the complexity of whether the - * background color is in the file format or the screen format in the case - * where an 'expand' will happen. - */ - - /* The following code cannot be entered in the alpha pre-multiplication case - * because PNG_BACKGROUND_EXPAND is cancelled below. - */ - if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) && - (png_ptr->transformations & PNG_EXPAND) && - !(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) - /* i.e., GRAY or GRAY_ALPHA */ - { - { - /* Expand background and tRNS chunks */ - int gray = png_ptr->background.gray; - int trans_gray = png_ptr->trans_color.gray; - - switch (png_ptr->bit_depth) - { - case 1: - gray *= 0xff; - trans_gray *= 0xff; - break; - - case 2: - gray *= 0x55; - trans_gray *= 0x55; - break; - - case 4: - gray *= 0x11; - trans_gray *= 0x11; - break; - - default: - - case 8: - /* FALL THROUGH (Already 8 bits) */ - - case 16: - /* Already a full 16 bits */ - break; - } - - png_ptr->background.red = png_ptr->background.green = - png_ptr->background.blue = (png_uint_16)gray; - - if (!(png_ptr->transformations & PNG_EXPAND_tRNS)) - { - png_ptr->trans_color.red = png_ptr->trans_color.green = - png_ptr->trans_color.blue = (png_uint_16)trans_gray; - } + png_ptr->transformations &= ~PNG_COMPOSE; } - } /* background expand and (therefore) no alpha association. */ -#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */ } void /* PRIVATE */ png_init_read_transformations(png_structrp png_ptr) @@ -1346,18 +1494,18 @@ * * 1) PNG_EXPAND (including PNG_EXPAND_tRNS) * 2) PNG_STRIP_ALPHA (if no compose) * 3) PNG_RGB_TO_GRAY - * 4) PNG_GRAY_TO_RGB iff !PNG_BACKGROUND_IS_GRAY + * 4) PNG_GRAY_TO_RGB iff !PNG_FLAG_BACKGROUND_IS_GRAY * 5) PNG_COMPOSE * 6) PNG_GAMMA * 7) PNG_STRIP_ALPHA (if compose) * 8) PNG_ENCODE_ALPHA * 9) PNG_SCALE_16_TO_8 * 10) PNG_16_TO_8 * 11) PNG_QUANTIZE (converts to palette) * 12) PNG_EXPAND_16 - * 13) PNG_GRAY_TO_RGB iff PNG_BACKGROUND_IS_GRAY + * 13) PNG_GRAY_TO_RGB iff PNG_FLAG_BACKGROUND_IS_GRAY * 14) PNG_INVERT_MONO * 15) PNG_SHIFT * 16) PNG_PACK * 17) PNG_BGR @@ -1368,18 +1516,21 @@ * 22) PNG_SWAP_BYTES * 23) PNG_USER_TRANSFORM [must be last] */ #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED - if ((png_ptr->transformations & PNG_STRIP_ALPHA) && - !(png_ptr->transformations & PNG_COMPOSE)) + if (png_ptr->transformations & PNG_STRIP_ALPHA) + { + if (!(png_ptr->transformations & PNG_FILLER)) + png_ptr->transformations &= ~(PNG_INVERT_ALPHA|PNG_SWAP_ALPHA); + + if (!(png_ptr->transformations & PNG_COMPOSE)) { /* Stripping the alpha channel happens immediately after the 'expand' - * transformations, before all other transformation, so it cancels out + * transformations, before all other transformations, so it cancels out * the alpha handling. It has the side effect negating the effect of * PNG_EXPAND_tRNS too: */ - png_ptr->transformations &= ~(PNG_BACKGROUND_EXPAND | PNG_ENCODE_ALPHA | - PNG_EXPAND_tRNS); + png_ptr->transformations &= ~(PNG_ENCODE_ALPHA | PNG_EXPAND_tRNS); png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; /* Kill the tRNS chunk itself too. Prior to 1.5.4 this did not happen * so transparency information would remain just so long as it wasn't @@ -1389,8 +1540,9 @@ * get.) This makes the behavior consistent from 1.5.4: */ png_ptr->num_trans = 0; } + } #endif /* STRIP_ALPHA supported, no COMPOSE */ #ifdef PNG_READ_ALPHA_MODE_SUPPORTED /* If the screen gamma is about 1.0 then the OPTIMIZE_ALPHA and ENCODE_ALPHA @@ -1410,53 +1562,21 @@ if (png_ptr->transformations & PNG_RGB_TO_GRAY) png_colorspace_set_rgb_coefficients(png_ptr); #endif -#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED -#if defined PNG_READ_EXPAND_SUPPORTED && defined PNG_READ_BACKGROUND_SUPPORTED - /* Detect gray background and attempt to enable optimization for - * gray --> RGB case. - * - * Note: if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or - * RGB_ALPHA (in which case need_expand is superfluous anyway), the - * background color might actually be gray yet not be flagged as such. - * This is not a problem for the current code, which uses - * PNG_BACKGROUND_IS_GRAY only to decide when to do the - * png_do_gray_to_rgb() transformation. - * - * TODO: this code needs to be revised to avoid the complexity and - * interdependencies. The color type of the background should be recorded in - * png_set_background, along with the bit depth, then the code has a record - * of exactly what color space the background is currently in. - */ - if (png_ptr->transformations & PNG_BACKGROUND_EXPAND) - { - /* PNG_BACKGROUND_EXPAND: the background is in the file color space, so if - * the file was grayscale the background value is gray. - */ - if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) - png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; - } + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + png_init_palette_transformations(png_ptr); - else if (png_ptr->transformations & PNG_COMPOSE) - { - /* PNG_COMPOSE: png_set_background was called with need_expand false, - * so the color is in the color space of the output or png_set_alpha_mode - * was called and the color is black. Ignore RGB_TO_GRAY because that - * happens before GRAY_TO_RGB. + else + png_init_rgb_transformations(png_ptr); + +#ifdef PNG_READ_BACKGROUND_SUPPORTED + /* Set up the background information if required, it is only used if + * PNG_COMPOSE is specified. */ - if (png_ptr->transformations & PNG_GRAY_TO_RGB) - { - if (png_ptr->background.red == png_ptr->background.green && - png_ptr->background.red == png_ptr->background.blue) - { - png_ptr->mode |= PNG_BACKGROUND_IS_GRAY; - png_ptr->background.gray = png_ptr->background.red; - } - } - } -#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */ -#endif /* PNG_READ_GRAY_TO_RGB_SUPPORTED */ + if (png_ptr->transformations & PNG_COMPOSE) + png_init_background_transformations(png_ptr); +#endif /* For indexed PNG data (PNG_COLOR_TYPE_PALETTE) many of the transformations * can be performed directly on the palette, and some (such as rgb to gray) * can be optimized inside the palette. This is particularly true of the @@ -1467,76 +1587,13 @@ * earlier and the palette stuff is actually handled on the first row. This * leads to the reported bug that the palette returned by png_get_PLTE is not * updated. */ - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - png_init_palette_transformations(png_ptr); - - else - png_init_rgb_transformations(png_ptr); - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ - defined(PNG_READ_EXPAND_16_SUPPORTED) - if ((png_ptr->transformations & PNG_EXPAND_16) && - (png_ptr->transformations & PNG_COMPOSE) && - !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) && - png_ptr->bit_depth != 16) - { - /* TODO: fix this. Because the expand_16 operation is after the compose - * handling the background color must be 8, not 16, bits deep, but the - * application will supply a 16-bit value so reduce it here. - * - * The PNG_BACKGROUND_EXPAND code above does not expand to 16 bits at - * present, so that case is ok (until do_expand_16 is moved.) - * - * NOTE: this discards the low 16 bits of the user supplied background - * color, but until expand_16 works properly there is no choice! - */ -# define CHOP(x) (x)=((png_uint_16)PNG_DIV257(x)) - CHOP(png_ptr->background.red); - CHOP(png_ptr->background.green); - CHOP(png_ptr->background.blue); - CHOP(png_ptr->background.gray); -# undef CHOP - } -#endif /* PNG_READ_BACKGROUND_SUPPORTED && PNG_READ_EXPAND_16_SUPPORTED */ - -#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ - (defined(PNG_READ_SCALE_16_TO_8_SUPPORTED) || \ - defined(PNG_READ_STRIP_16_TO_8_SUPPORTED)) - if ((png_ptr->transformations & (PNG_16_TO_8|PNG_SCALE_16_TO_8)) && - (png_ptr->transformations & PNG_COMPOSE) && - !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) && - png_ptr->bit_depth == 16) - { - /* On the other hand, if a 16-bit file is to be reduced to 8-bits per - * component this will also happen after PNG_COMPOSE and so the background - * color must be pre-expanded here. - * - * TODO: fix this too. - */ - png_ptr->background.red = (png_uint_16)(png_ptr->background.red * 257); - png_ptr->background.green = - (png_uint_16)(png_ptr->background.green * 257); - png_ptr->background.blue = (png_uint_16)(png_ptr->background.blue * 257); - png_ptr->background.gray = (png_uint_16)(png_ptr->background.gray * 257); - } +#if 0 /* NYI */ + png_do_palette_transformations(png_ptr); #endif - /* NOTE: below 'PNG_READ_ALPHA_MODE_SUPPORTED' is presumed to also enable the - * background support (see the comments in scripts/pnglibconf.dfa), this - * allows pre-multiplication of the alpha channel to be implemented as - * compositing on black. This is probably sub-optimal and has been done in - * 1.5.4 betas simply to enable external critique and testing (i.e. to - * implement the new API quickly, without lots of internal changes.) - */ - #ifdef PNG_READ_GAMMA_SUPPORTED -# ifdef PNG_READ_BACKGROUND_SUPPORTED - /* Includes ALPHA_MODE */ - png_ptr->background_1 = png_ptr->background; -# endif - /* This needs to change - in the palette image case a whole set of tables are * built when it would be quicker to just calculate the correct value for * each palette entry directly. Also, the test is too tricky - why check * PNG_RGB_TO_GRAY if PNG_GAMMA is not set? The answer seems to be that @@ -1563,9 +1620,9 @@ )) || ((png_ptr->transformations & PNG_ENCODE_ALPHA) && png_gamma_significant(png_ptr->screen_gamma)) ) { - png_build_gamma_table(png_ptr, png_ptr->bit_depth); + png_build_gamma_tables(png_ptr, png_ptr->bit_depth); #ifdef PNG_READ_BACKGROUND_SUPPORTED if (png_ptr->transformations & PNG_COMPOSE) { @@ -1580,113 +1637,43 @@ "libpng does not support gamma+background+rgb_to_gray"); if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) { - /* We don't get to here unless there is a tRNS chunk with non-opaque - * entries - see the checking code at the start of this function. - */ - png_color back, back_1; + unsigned int i, num_palette = png_ptr->num_palette; + png_color back; + png_color_16 back_1 = png_ptr->background_1; png_colorp palette = png_ptr->palette; - int num_palette = png_ptr->num_palette; - int i; - if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) - { - - back.red = png_ptr->gamma_table[png_ptr->background.red]; - back.green = png_ptr->gamma_table[png_ptr->background.green]; - back.blue = png_ptr->gamma_table[png_ptr->background.blue]; - - back_1.red = png_ptr->gamma_to_1[png_ptr->background.red]; - back_1.green = png_ptr->gamma_to_1[png_ptr->background.green]; - back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue]; - } - else - { - png_fixed_point g, gs; - - switch (png_ptr->background_gamma_type) - { - case PNG_BACKGROUND_GAMMA_SCREEN: - g = (png_ptr->screen_gamma); - gs = PNG_FP_1; - break; - - case PNG_BACKGROUND_GAMMA_FILE: - g = png_reciprocal(png_ptr->colorspace.gamma); - gs = png_reciprocal2(png_ptr->colorspace.gamma, - png_ptr->screen_gamma); - break; - - case PNG_BACKGROUND_GAMMA_UNIQUE: - g = png_reciprocal(png_ptr->background_gamma); - gs = png_reciprocal2(png_ptr->background_gamma, - png_ptr->screen_gamma); - break; - default: - g = PNG_FP_1; /* back_1 */ - gs = PNG_FP_1; /* back */ - break; - } - - if (png_gamma_significant(gs)) - { - back.red = png_gamma_8bit_correct(png_ptr->background.red, - gs); - back.green = png_gamma_8bit_correct(png_ptr->background.green, - gs); - back.blue = png_gamma_8bit_correct(png_ptr->background.blue, - gs); - } - else - { back.red = (png_byte)png_ptr->background.red; back.green = (png_byte)png_ptr->background.green; back.blue = (png_byte)png_ptr->background.blue; - } - - if (png_gamma_significant(g)) - { - back_1.red = png_gamma_8bit_correct(png_ptr->background.red, - g); - back_1.green = png_gamma_8bit_correct( - png_ptr->background.green, g); - back_1.blue = png_gamma_8bit_correct(png_ptr->background.blue, - g); - } - - else - { - back_1.red = (png_byte)png_ptr->background.red; - back_1.green = (png_byte)png_ptr->background.green; - back_1.blue = (png_byte)png_ptr->background.blue; - } - } for (i = 0; i < num_palette; i++) { - if (i < (int)png_ptr->num_trans && - png_ptr->trans_alpha[i] != 0xff) + if (i < png_ptr->num_trans && png_ptr->trans_alpha[i] != 0xff) { if (png_ptr->trans_alpha[i] == 0) { palette[i] = back; } else /* if (png_ptr->trans_alpha[i] != 0xff) */ { - png_byte v, w; + png_uint_16 v, w; + unsigned int alpha = png_ptr->trans_alpha[i] * 257U; + unsigned int shift = png_ptr->gamma_shift; + unsigned int add = (shift > 0 ? 1U<<(shift-1) : 0); v = png_ptr->gamma_to_1[palette[i].red]; - png_composite(w, v, png_ptr->trans_alpha[i], back_1.red); - palette[i].red = png_ptr->gamma_from_1[w]; + png_composite_16(w, v, alpha, back_1.red); + palette[i].red = png_ptr->gamma_from_1[(w+add)>>shift]; v = png_ptr->gamma_to_1[palette[i].green]; - png_composite(w, v, png_ptr->trans_alpha[i], back_1.green); - palette[i].green = png_ptr->gamma_from_1[w]; + png_composite_16(w, v, alpha, back_1.green); + palette[i].green = png_ptr->gamma_from_1[(w+add)>>shift]; v = png_ptr->gamma_to_1[palette[i].blue]; - png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue); - palette[i].blue = png_ptr->gamma_from_1[w]; + png_composite_16(w, v, alpha, back_1.blue); + palette[i].blue = png_ptr->gamma_from_1[(w+add)>>shift]; } } else { @@ -1703,93 +1690,8 @@ * transformations elsewhere. */ png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA); } /* color_type == PNG_COLOR_TYPE_PALETTE */ - - /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */ - else /* color_type != PNG_COLOR_TYPE_PALETTE */ - { - int gs_sig, g_sig; - png_fixed_point g = PNG_FP_1; /* Correction to linear */ - png_fixed_point gs = PNG_FP_1; /* Correction to screen */ - - switch (png_ptr->background_gamma_type) - { - case PNG_BACKGROUND_GAMMA_SCREEN: - g = png_ptr->screen_gamma; - /* gs = PNG_FP_1; */ - break; - - case PNG_BACKGROUND_GAMMA_FILE: - g = png_reciprocal(png_ptr->colorspace.gamma); - gs = png_reciprocal2(png_ptr->colorspace.gamma, - png_ptr->screen_gamma); - break; - - case PNG_BACKGROUND_GAMMA_UNIQUE: - g = png_reciprocal(png_ptr->background_gamma); - gs = png_reciprocal2(png_ptr->background_gamma, - png_ptr->screen_gamma); - break; - - default: - png_error(png_ptr, "invalid background gamma type"); - } - - g_sig = png_gamma_significant(g); - gs_sig = png_gamma_significant(gs); - - if (g_sig) - png_ptr->background_1.gray = png_gamma_correct(png_ptr, - png_ptr->background.gray, g); - - if (gs_sig) - png_ptr->background.gray = png_gamma_correct(png_ptr, - png_ptr->background.gray, gs); - - if ((png_ptr->background.red != png_ptr->background.green) || - (png_ptr->background.red != png_ptr->background.blue) || - (png_ptr->background.red != png_ptr->background.gray)) - { - /* RGB or RGBA with color background */ - if (g_sig) - { - png_ptr->background_1.red = png_gamma_correct(png_ptr, - png_ptr->background.red, g); - - png_ptr->background_1.green = png_gamma_correct(png_ptr, - png_ptr->background.green, g); - - png_ptr->background_1.blue = png_gamma_correct(png_ptr, - png_ptr->background.blue, g); - } - - if (gs_sig) - { - png_ptr->background.red = png_gamma_correct(png_ptr, - png_ptr->background.red, gs); - - png_ptr->background.green = png_gamma_correct(png_ptr, - png_ptr->background.green, gs); - - png_ptr->background.blue = png_gamma_correct(png_ptr, - png_ptr->background.blue, gs); - } - } - - else - { - /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */ - png_ptr->background_1.red = png_ptr->background_1.green - = png_ptr->background_1.blue = png_ptr->background_1.gray; - - png_ptr->background.red = png_ptr->background.green - = png_ptr->background.blue = png_ptr->background.gray; - } - - /* The background is now in screen gamma: */ - png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_SCREEN; - } /* color_type != PNG_COLOR_TYPE_PALETTE */ }/* png_ptr->transformations & PNG_BACKGROUND */ else /* Transformation does not include PNG_BACKGROUND */ @@ -2234,9 +2136,9 @@ /* If gray -> RGB, do so now only if background is non-gray; else do later * for performance reasons */ if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && - !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) + !(png_ptr->flags & PNG_FLAG_BACKGROUND_IS_GRAY)) png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1); #endif #if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\ @@ -2319,9 +2221,9 @@ #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED /* NOTE: moved here in 1.5.4 (from much later in this list.) */ if ((png_ptr->transformations & PNG_GRAY_TO_RGB) && - (png_ptr->mode & PNG_BACKGROUND_IS_GRAY)) + (png_ptr->flags & PNG_FLAG_BACKGROUND_IS_GRAY)) png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1); #endif #ifdef PNG_READ_INVERT_SUPPORTED @@ -3283,25 +3185,26 @@ (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0; if (row_info->bit_depth == 8) { -#ifdef PNG_READ_GAMMA_SUPPORTED /* Notice that gamma to/from 1 are not necessarily inverses (if * there is an overall gamma correction). Prior to 1.5.5 this code * checked the linearized values for equality; this doesn't match * the documentation, the original values must be checked. */ if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) { + PNG_CONST unsigned int shift = 15 + png_ptr->gamma_shift; + PNG_CONST png_uint_32 add = 1U << (shift-1); png_bytep sp = row; png_bytep dp = row; png_uint_32 i; for (i = 0; i < row_width; i++) { - png_byte red = *(sp++); - png_byte green = *(sp++); - png_byte blue = *(sp++); + unsigned int red = *(sp++); + unsigned int green = *(sp++); + unsigned int blue = *(sp++); if (red != green || red != blue) { red = png_ptr->gamma_to_1[red]; @@ -3309,9 +3212,9 @@ blue = png_ptr->gamma_to_1[blue]; rgb_error |= 1; *(dp++) = png_ptr->gamma_from_1[ - (rc*red + gc*green + bc*blue + 16384)>>15]; + (rc*red + gc*green + bc*blue + add)>>shift]; } else { @@ -3320,9 +3223,9 @@ */ if (png_ptr->gamma_table != NULL) red = png_ptr->gamma_table[red]; - *(dp++) = red; + *(dp++) = (png_byte)red; } if (have_alpha) *(dp++) = *(sp++); @@ -3327,10 +3230,10 @@ if (have_alpha) *(dp++) = *(sp++); } } + else -#endif { png_bytep sp = row; png_bytep dp = row; png_uint_32 i; @@ -3343,12 +3246,9 @@ if (red != green || red != blue) { rgb_error |= 1; - /* NOTE: this is the historical approach which simply - * truncates the results. - */ - *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15); + *(dp++) = (png_byte)((rc*red+gc*green+bc*blue+16384)>>15); } else *(dp++) = red; @@ -3360,11 +3260,12 @@ } else /* RGB bit_depth == 16 */ { -#ifdef PNG_READ_GAMMA_SUPPORTED if (png_ptr->gamma_16_to_1 != NULL && png_ptr->gamma_16_from_1 != NULL) { + unsigned int shift = png_ptr->gamma_shift; + unsigned int add = (shift > 0 ? (1U << (shift-1)) : 0); png_bytep sp = row; png_bytep dp = row; png_uint_32 i; @@ -3378,28 +3279,25 @@ if (red == green && red == blue) { if (png_ptr->gamma_16_table != NULL) - w = png_ptr->gamma_16_table[(red&0xff) - >> png_ptr->gamma_shift][red>>8]; + w = png_ptr->gamma_16_table[(red+add) >> shift]; else w = red; } else { - png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff) - >> png_ptr->gamma_shift][red>>8]; - png_uint_16 green_1 = - png_ptr->gamma_16_to_1[(green&0xff) >> - png_ptr->gamma_shift][green>>8]; - png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff) - >> png_ptr->gamma_shift][blue>>8]; + png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red+add) + >> shift]; + png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green+add) + >> shift]; + png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue+add) + >> shift]; png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1 + bc*blue_1 + 16384)>>15); - w = png_ptr->gamma_16_from_1[(gray16&0xff) >> - png_ptr->gamma_shift][gray16 >> 8]; + w = png_ptr->gamma_16_from_1[(gray16+add) >> shift]; rgb_error |= 1; } *(dp++) = (png_byte)((w>>8) & 0xff); @@ -3411,10 +3309,10 @@ *(dp++) = *(sp++); } } } + else -#endif { png_bytep sp = row; png_bytep dp = row; png_uint_32 i; @@ -3433,10 +3331,9 @@ /* From 1.5.5 in the 16 bit case do the accurate conversion even * in the 'fast' case - this is because this is where the code * ends up when handling linear 16 bit data. */ - gray16 = (png_uint_16)((rc*red + gc*green + bc*blue + 16384) >> - 15); + gray16 = (png_uint_16)((rc*red+gc*green+bc*blue+16384) >> 15); *(dp++) = (png_byte)((gray16>>8) & 0xff); *(dp++) = (png_byte)(gray16 & 0xff); if (have_alpha) @@ -3526,23 +3423,21 @@ */ void /* PRIVATE */ png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr) { -#ifdef PNG_READ_GAMMA_SUPPORTED png_const_bytep gamma_table = png_ptr->gamma_table; png_const_bytep gamma_from_1 = png_ptr->gamma_from_1; - png_const_bytep gamma_to_1 = png_ptr->gamma_to_1; - png_const_uint_16pp gamma_16 = png_ptr->gamma_16_table; - png_const_uint_16pp gamma_16_from_1 = png_ptr->gamma_16_from_1; - png_const_uint_16pp gamma_16_to_1 = png_ptr->gamma_16_to_1; - int gamma_shift = png_ptr->gamma_shift; - int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0; -#endif + png_const_uint_16p gamma_to_1 = png_ptr->gamma_to_1; + png_const_uint_16p gamma_16 = png_ptr->gamma_16_table; + png_const_uint_16p gamma_16_from_1 = png_ptr->gamma_16_from_1; + png_const_uint_16p gamma_16_to_1 = png_ptr->gamma_16_to_1; + PNG_CONST unsigned int shift = png_ptr->gamma_shift; + PNG_CONST unsigned int add = (shift > 0 ? 1U<<(shift-1) : 0); + PNG_CONST int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0; png_bytep sp; png_uint_32 i; png_uint_32 row_width = row_info->width; - int shift; png_debug(1, "in png_do_compose"); { @@ -3553,167 +3448,166 @@ switch (row_info->bit_depth) { case 1: { + int bit_shift = 7; sp = row; - shift = 7; for (i = 0; i < row_width; i++) { - if ((png_uint_16)((*sp >> shift) & 0x01) + if ((png_uint_16)((*sp >> bit_shift) & 0x01) == png_ptr->trans_color.gray) { - unsigned int tmp = *sp & (0x7f7f >> (7 - shift)); - tmp |= png_ptr->background.gray << shift; + unsigned int tmp = *sp & (0x7f7f >> (7 - bit_shift)); + tmp |= png_ptr->background.gray << bit_shift; *sp = (png_byte)(tmp & 0xff); } - if (!shift) + if (!bit_shift) { - shift = 7; + bit_shift = 7; sp++; } else - shift--; + bit_shift--; } break; } case 2: { -#ifdef PNG_READ_GAMMA_SUPPORTED +#if 0 if (gamma_table != NULL) { + int bit_shift = 6; sp = row; - shift = 6; for (i = 0; i < row_width; i++) { - if ((png_uint_16)((*sp >> shift) & 0x03) + if ((png_uint_16)((*sp >> bit_shift) & 0x03) == png_ptr->trans_color.gray) { - unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); - tmp |= png_ptr->background.gray << shift; + unsigned int tmp = *sp & (0x3f3f >> (6 - bit_shift)); + tmp |= png_ptr->background.gray << bit_shift; *sp = (png_byte)(tmp & 0xff); } else { - unsigned int p = (*sp >> shift) & 0x03; + unsigned int p = (*sp >> bit_shift) & 0x03; unsigned int g = (gamma_table [p | (p << 2) | (p << 4) | (p << 6)] >> 6) & 0x03; - unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); - tmp |= g << shift; + unsigned int tmp = *sp & (0x3f3f >> (6 - bit_shift)); + tmp |= g << bit_shift; *sp = (png_byte)(tmp & 0xff); } - if (!shift) + if (!bit_shift) { - shift = 6; + bit_shift = 6; sp++; } else - shift -= 2; + bit_shift -= 2; } } else #endif { + int bit_shift = 6; sp = row; - shift = 6; for (i = 0; i < row_width; i++) { - if ((png_uint_16)((*sp >> shift) & 0x03) + if ((png_uint_16)((*sp >> bit_shift) & 0x03) == png_ptr->trans_color.gray) { - unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); - tmp |= png_ptr->background.gray << shift; + unsigned int tmp = *sp & (0x3f3f >> (6 - bit_shift)); + tmp |= png_ptr->background.gray << bit_shift; *sp = (png_byte)(tmp & 0xff); } - if (!shift) + if (!bit_shift) { - shift = 6; + bit_shift = 6; sp++; } else - shift -= 2; + bit_shift -= 2; } } break; } case 4: { -#ifdef PNG_READ_GAMMA_SUPPORTED +#if 0 if (gamma_table != NULL) { + int bit_shift = 4; sp = row; - shift = 4; for (i = 0; i < row_width; i++) { - if ((png_uint_16)((*sp >> shift) & 0x0f) + if ((png_uint_16)((*sp >> bit_shift) & 0x0f) == png_ptr->trans_color.gray) { - unsigned int tmp = *sp & (0xf0f >> (4 - shift)); - tmp |= png_ptr->background.gray << shift; + unsigned int tmp = *sp & (0xf0f >> (4 - bit_shift)); + tmp |= png_ptr->background.gray << bit_shift; *sp = (png_byte)(tmp & 0xff); } else { - unsigned int p = (*sp >> shift) & 0x0f; + unsigned int p = (*sp >> bit_shift) & 0x0f; unsigned int g = (gamma_table[p | (p << 4)] >> 4) & 0x0f; - unsigned int tmp = *sp & (0xf0f >> (4 - shift)); - tmp |= g << shift; + unsigned int tmp = *sp & (0xf0f >> (4 - bit_shift)); + tmp |= g << bit_shift; *sp = (png_byte)(tmp & 0xff); } - if (!shift) + if (!bit_shift) { - shift = 4; + bit_shift = 4; sp++; } else - shift -= 4; + bit_shift -= 4; } } else #endif { + int bit_shift = 4; sp = row; - shift = 4; for (i = 0; i < row_width; i++) { - if ((png_uint_16)((*sp >> shift) & 0x0f) + if ((png_uint_16)((*sp >> bit_shift) & 0x0f) == png_ptr->trans_color.gray) { - unsigned int tmp = *sp & (0xf0f >> (4 - shift)); - tmp |= png_ptr->background.gray << shift; + unsigned int tmp = *sp & (0xf0f >> (4 - bit_shift)); + tmp |= png_ptr->background.gray << bit_shift; *sp = (png_byte)(tmp & 0xff); } - if (!shift) + if (!bit_shift) { - shift = 4; + bit_shift = 4; sp++; } else - shift -= 4; + bit_shift -= 4; } } break; } case 8: { -#ifdef PNG_READ_GAMMA_SUPPORTED if (gamma_table != NULL) { sp = row; for (i = 0; i < row_width; i++, sp++) @@ -3724,10 +3618,10 @@ else *sp = gamma_table[*sp]; } } + else -#endif { sp = row; for (i = 0; i < row_width; i++, sp++) { @@ -3739,9 +3633,8 @@ } case 16: { -#ifdef PNG_READ_GAMMA_SUPPORTED if (gamma_16 != NULL) { sp = row; for (i = 0; i < row_width; i++, sp += 2) @@ -3760,9 +3653,9 @@ } else { - v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + v = gamma_16[(v+add) >> shift]; *sp = (png_byte)((v >> 8) & 0xff); *(sp + 1) = (png_byte)(v & 0xff); } } @@ -3766,10 +3659,10 @@ *(sp + 1) = (png_byte)(v & 0xff); } } } + else -#endif { sp = row; for (i = 0; i < row_width; i++, sp += 2) { @@ -3798,9 +3691,8 @@ case PNG_COLOR_TYPE_RGB: { if (row_info->bit_depth == 8) { -#ifdef PNG_READ_GAMMA_SUPPORTED if (gamma_table != NULL) { sp = row; for (i = 0; i < row_width; i++, sp += 3) @@ -3821,10 +3713,10 @@ *(sp + 2) = gamma_table[*(sp + 2)]; } } } + else -#endif { sp = row; for (i = 0; i < row_width; i++, sp += 3) { @@ -3840,9 +3732,8 @@ } } else /* if (row_info->bit_depth == 16) */ { -#ifdef PNG_READ_GAMMA_SUPPORTED if (gamma_16 != NULL) { sp = row; for (i = 0; i < row_width; i++, sp += 6) @@ -3872,25 +3763,24 @@ } else { - png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + png_uint_16 v = gamma_16[(r+add) >> shift]; *sp = (png_byte)((v >> 8) & 0xff); *(sp + 1) = (png_byte)(v & 0xff); - v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + v = gamma_16[(g+add) >> shift]; *(sp + 2) = (png_byte)((v >> 8) & 0xff); *(sp + 3) = (png_byte)(v & 0xff); - v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + v = gamma_16[(b+add) >> shift]; *(sp + 4) = (png_byte)((v >> 8) & 0xff); *(sp + 5) = (png_byte)(v & 0xff); } } } else -#endif { sp = row; for (i = 0; i < row_width; i++, sp += 6) { @@ -3925,9 +3815,8 @@ case PNG_COLOR_TYPE_GRAY_ALPHA: { if (row_info->bit_depth == 8) { -#ifdef PNG_READ_GAMMA_SUPPORTED if (gamma_to_1 != NULL && gamma_from_1 != NULL && gamma_table != NULL) { sp = row; @@ -3945,20 +3834,26 @@ } else { - png_byte v, w; + unsigned int v, w; v = gamma_to_1[*sp]; - png_composite(w, v, a, png_ptr->background_1.gray); + png_composite_16(w, v, 257*a, + png_ptr->background_1.gray); + if (!optimize) - w = gamma_from_1[w]; - *sp = w; + w = gamma_from_1[(w+add)>>shift]; + + else /* alpha pixels linear and approximate */ + w = PNG_DIV257(w); + + *sp = (png_byte)w; } } } + else -#endif { sp = row; for (i = 0; i < row_width; i++, sp += 2) { @@ -3971,11 +3866,11 @@ png_composite(*sp, *sp, a, png_ptr->background.gray); } } } + else /* if (png_ptr->bit_depth == 16) */ { -#ifdef PNG_READ_GAMMA_SUPPORTED if (gamma_16 != NULL && gamma_16_from_1 != NULL && gamma_16_to_1 != NULL) { sp = row; @@ -3987,9 +3882,9 @@ if (a == (png_uint_16)0xffff) { png_uint_16 v; - v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + v = gamma_16[((sp[0]<<8)+sp[1]+add) >> shift]; *sp = (png_byte)((v >> 8) & 0xff); *(sp + 1) = (png_byte)(v & 0xff); } @@ -4004,14 +3899,17 @@ else { png_uint_16 g, v, w; - g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + g = gamma_16_to_1[((sp[0]<<8)+sp[1]+add) >> shift]; png_composite_16(v, g, a, png_ptr->background_1.gray); - if (optimize) - w = v; + + if (!optimize) + w = gamma_16_from_1[(v+add) >> shift]; + else - w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8]; + w = v; + *sp = (png_byte)((w >> 8) & 0xff); *(sp + 1) = (png_byte)(w & 0xff); } } @@ -4015,10 +3913,10 @@ *(sp + 1) = (png_byte)(w & 0xff); } } } + else -#endif { sp = row; for (i = 0; i < row_width; i++, sp += 4) { @@ -4050,9 +3948,8 @@ case PNG_COLOR_TYPE_RGB_ALPHA: { if (row_info->bit_depth == 8) { -#ifdef PNG_READ_GAMMA_SUPPORTED if (gamma_to_1 != NULL && gamma_from_1 != NULL && gamma_table != NULL) { sp = row; @@ -4076,29 +3973,51 @@ } else { - png_byte v, w; + unsigned int v, w; + unsigned int alpha = a * 257U; v = gamma_to_1[*sp]; - png_composite(w, v, a, png_ptr->background_1.red); - if (!optimize) w = gamma_from_1[w]; - *sp = w; + png_composite_16(w, v, alpha, + png_ptr->background_1.red); + + if (!optimize) + w = gamma_from_1[(w+add)>>shift]; + + else + w = PNG_DIV257(w); + + *sp = (png_byte)w; v = gamma_to_1[*(sp + 1)]; - png_composite(w, v, a, png_ptr->background_1.green); - if (!optimize) w = gamma_from_1[w]; - *(sp + 1) = w; + png_composite_16(w, v, alpha, + png_ptr->background_1.green); + + if (!optimize) + w = gamma_from_1[(w+add)>>shift]; + + else + w = PNG_DIV257(w); + + *(sp + 1) = (png_byte)w; v = gamma_to_1[*(sp + 2)]; - png_composite(w, v, a, png_ptr->background_1.blue); - if (!optimize) w = gamma_from_1[w]; - *(sp + 2) = w; + png_composite_16(w, v, alpha, + png_ptr->background_1.blue); + + if (!optimize) + w = gamma_from_1[(w+add)>>shift]; + + else + w = PNG_DIV257(w); + + *(sp + 2) = (png_byte)w; } } } + else -#endif { sp = row; for (i = 0; i < row_width; i++, sp += 4) { @@ -4123,11 +4042,11 @@ } } } } + else /* if (row_info->bit_depth == 16) */ { -#ifdef PNG_READ_GAMMA_SUPPORTED if (gamma_16 != NULL && gamma_16_from_1 != NULL && gamma_16_to_1 != NULL) { sp = row; @@ -4139,17 +4058,17 @@ if (a == (png_uint_16)0xffff) { png_uint_16 v; - v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + v = gamma_16[((sp[0]<<8)+sp[1]+add) >> shift]; *sp = (png_byte)((v >> 8) & 0xff); *(sp + 1) = (png_byte)(v & 0xff); - v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + v = gamma_16[((sp[2]<<8)+sp[3]+add) >> shift]; *(sp + 2) = (png_byte)((v >> 8) & 0xff); *(sp + 3) = (png_byte)(v & 0xff); - v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + v = gamma_16[((sp[4]<<8)+sp[5]+add) >> shift]; *(sp + 4) = (png_byte)((v >> 8) & 0xff); *(sp + 5) = (png_byte)(v & 0xff); } @@ -4170,39 +4089,39 @@ else { png_uint_16 v, w; - v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + v = gamma_16_to_1[((sp[0]<<8)+sp[1]+add) >> shift]; png_composite_16(w, v, a, png_ptr->background_1.red); + if (!optimize) - w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> - 8]; + w = gamma_16_from_1[(w+add) >> shift]; + *sp = (png_byte)((w >> 8) & 0xff); *(sp + 1) = (png_byte)(w & 0xff); - v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; + v = gamma_16_to_1[((sp[2]<<8)+sp[3]+add) >> shift]; png_composite_16(w, v, a, png_ptr->background_1.green); + if (!optimize) - w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> - 8]; + w = gamma_16_from_1[(w+add) >> shift]; *(sp + 2) = (png_byte)((w >> 8) & 0xff); *(sp + 3) = (png_byte)(w & 0xff); - v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; + v = gamma_16_to_1[((sp[4]<<8)+sp[5]+add) >> shift]; png_composite_16(w, v, a, png_ptr->background_1.blue); + if (!optimize) - w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> - 8]; + w = gamma_16_from_1[(w+add) >> shift]; *(sp + 4) = (png_byte)((w >> 8) & 0xff); *(sp + 5) = (png_byte)(w & 0xff); } } } else -#endif { sp = row; for (i = 0; i < row_width; i++, sp += 8) { @@ -4267,18 +4186,24 @@ void /* PRIVATE */ png_do_gamma(png_row_infop row_info, png_bytep row, png_structrp png_ptr) { png_const_bytep gamma_table = png_ptr->gamma_table; - png_const_uint_16pp gamma_16_table = png_ptr->gamma_16_table; - int gamma_shift = png_ptr->gamma_shift; + png_const_uint_16p gamma_16_table = png_ptr->gamma_16_table; + int shift = png_ptr->gamma_shift; + int add = (shift > 0 ? 1U << (shift-1) : 0); png_bytep sp; png_uint_32 i; png_uint_32 row_width=row_info->width; png_debug(1, "in png_do_gamma"); - if (((row_info->bit_depth <= 8 && gamma_table != NULL) || + /* Prior to libpng 1.7.0 this code would attempt to gamma correct 2 and 4 bit + * gray level values, the results are ridiculously inaccurate. In 1.7.0 the + * code is removed and a warning is introduced to catch cases where an + * application might actually try it. + */ + if (((row_info->bit_depth == 8 && gamma_table != NULL) || (row_info->bit_depth == 16 && gamma_16_table != NULL))) { switch (row_info->color_type) { @@ -4304,19 +4229,19 @@ for (i = 0; i < row_width; i++) { png_uint_16 v; - v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + v = gamma_16_table[((sp[0]<<8)+sp[1]+add) >> shift]; *sp = (png_byte)((v >> 8) & 0xff); *(sp + 1) = (png_byte)(v & 0xff); sp += 2; - v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + v = gamma_16_table[((sp[0]<<8)+sp[1]+add) >> shift]; *sp = (png_byte)((v >> 8) & 0xff); *(sp + 1) = (png_byte)(v & 0xff); sp += 2; - v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + v = gamma_16_table[((sp[0]<<8)+sp[1]+add) >> shift]; *sp = (png_byte)((v >> 8) & 0xff); *(sp + 1) = (png_byte)(v & 0xff); sp += 2; } @@ -4348,19 +4273,21 @@ { sp = row; for (i = 0; i < row_width; i++) { - png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + png_uint_16 v; + + v = gamma_16_table[((sp[0]<<8)+sp[1]+add) >> shift]; *sp = (png_byte)((v >> 8) & 0xff); *(sp + 1) = (png_byte)(v & 0xff); sp += 2; - v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + v = gamma_16_table[((sp[0]<<8)+sp[1]+add) >> shift]; *sp = (png_byte)((v >> 8) & 0xff); *(sp + 1) = (png_byte)(v & 0xff); sp += 2; - v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + v = gamma_16_table[((sp[0]<<8)+sp[1]+add) >> shift]; *sp = (png_byte)((v >> 8) & 0xff); *(sp + 1) = (png_byte)(v & 0xff); sp += 4; } @@ -4384,9 +4311,11 @@ { sp = row; for (i = 0; i < row_width; i++) { - png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + png_uint_16 v; + + v = gamma_16_table[((sp[0]<<8)+sp[1]+add) >> shift]; *sp = (png_byte)((v >> 8) & 0xff); *(sp + 1) = (png_byte)(v & 0xff); sp += 4; } @@ -4395,42 +4324,9 @@ } case PNG_COLOR_TYPE_GRAY: { - if (row_info->bit_depth == 2) - { - sp = row; - for (i = 0; i < row_width; i += 4) - { - int a = *sp & 0xc0; - int b = *sp & 0x30; - int c = *sp & 0x0c; - int d = *sp & 0x03; - - *sp = (png_byte)( - ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)]) ) & 0xc0)| - ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)| - ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)| - ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) )); - sp++; - } - } - - if (row_info->bit_depth == 4) - { - sp = row; - for (i = 0; i < row_width; i += 2) - { - int msb = *sp & 0xf0; - int lsb = *sp & 0x0f; - - *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0) - | (((int)gamma_table[(lsb << 4) | lsb]) >> 4)); - sp++; - } - } - - else if (row_info->bit_depth == 8) + if (row_info->bit_depth == 8) { sp = row; for (i = 0; i < row_width; i++) { @@ -4438,14 +4334,16 @@ sp++; } } - else if (row_info->bit_depth == 16) + else /*row_info->bit_depth == 16 */ { sp = row; for (i = 0; i < row_width; i++) { - png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp]; + png_uint_16 v; + + v = gamma_16_table[((sp[0]<<8)+sp[1]+add) >> shift]; *sp = (png_byte)((v >> 8) & 0xff); *(sp + 1) = (png_byte)(v & 0xff); sp += 2; } @@ -4473,33 +4371,35 @@ png_debug(1, "in png_do_encode_alpha"); if (row_info->color_type & PNG_COLOR_MASK_ALPHA) { + PNG_CONST unsigned int shift = png_ptr->gamma_shift; + PNG_CONST unsigned int add = (shift > 0 ? 1U<<(shift-1) : 0); + if (row_info->bit_depth == 8) { - PNG_CONST png_bytep table = png_ptr->gamma_from_1; + PNG_CONST png_bytep gamma_from_1 = png_ptr->gamma_from_1; - if (table != NULL) + if (gamma_from_1 != NULL) { PNG_CONST int step = (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2; /* The alpha channel is the last component: */ row += step - 1; for (; row_width > 0; --row_width, row += step) - *row = table[*row]; + *row = gamma_from_1[(257U**row+add)>>shift]; return; } } else if (row_info->bit_depth == 16) { - PNG_CONST png_uint_16pp table = png_ptr->gamma_16_from_1; - PNG_CONST int gamma_shift = png_ptr->gamma_shift; + PNG_CONST png_uint_16p gamma_16_from_1 = png_ptr->gamma_16_from_1; - if (table != NULL) + if (gamma_16_from_1 != NULL) { PNG_CONST int step = (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4; @@ -4509,9 +4409,9 @@ for (; row_width > 0; --row_width, row += step) { png_uint_16 v; - v = table[*(row + 1) >> gamma_shift][*row]; + v = gamma_16_from_1[((row[0]<<8)+row[1]+add) >> shift]; *row = (png_byte)((v >> 8) & 0xff); *(row + 1) = (png_byte)(v & 0xff); } diff -ru4NwbB libpng-1.6.0beta33/pngrutil.c libpng-1.7.0alpha01/pngrutil.c --- libpng-1.6.0beta33/pngrutil.c 2012-12-15 08:22:35.082722722 -0600 +++ libpng-1.7.0alpha01/pngrutil.c 2012-12-15 10:05:51.400181711 -0600 @@ -561,9 +561,9 @@ * limited only by the maximum chunk size. */ png_alloc_size_t limit = PNG_SIZE_MAX; -# ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED +# ifdef PNG_SET_USER_LIMITS_SUPPOPRTED if (png_ptr->user_chunk_malloc_max > 0 && png_ptr->user_chunk_malloc_max < limit) limit = png_ptr->user_chunk_malloc_max; # elif PNG_USER_CHUNK_MALLOC_MAX > 0 @@ -1581,9 +1581,10 @@ } if (--png_ptr->user_chunk_cache_max == 1) { - png_warning(png_ptr, "No space in chunk cache for sPLT"); + /* Warn the first time */ + png_chunk_benign_error(png_ptr, "chunk cache full"); png_crc_finish(png_ptr, length); return; } } @@ -1831,8 +1832,10 @@ * png_info. Fix this. */ png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans, &(png_ptr->trans_color)); + + png_ptr->trans_alpha = info_ptr->trans_alpha; } #endif #ifdef PNG_READ_bKGD_SUPPORTED @@ -2369,9 +2372,9 @@ if (--png_ptr->user_chunk_cache_max == 1) { png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "no space in chunk cache"); + png_chunk_benign_error(png_ptr, "chunk cache full"); return; } } #endif @@ -2448,9 +2451,9 @@ if (--png_ptr->user_chunk_cache_max == 1) { png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "no space in chunk cache"); + png_chunk_benign_error(png_ptr, "chunk cache full"); return; } } #endif @@ -2557,9 +2560,9 @@ if (--png_ptr->user_chunk_cache_max == 1) { png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "no space in chunk cache"); + png_chunk_benign_error(png_ptr, "chunk cache full"); return; } } #endif @@ -2697,9 +2700,9 @@ png_free(png_ptr, png_ptr->unknown_chunk.data); png_ptr->unknown_chunk.data = NULL; } -# ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED +# ifdef PNG_SET_USER_LIMITS_SUPPOPRTED if (png_ptr->user_chunk_malloc_max > 0 && png_ptr->user_chunk_malloc_max < limit) limit = png_ptr->user_chunk_malloc_max; @@ -2892,9 +2895,9 @@ switch (png_ptr->user_chunk_cache_max) { case 2: png_ptr->user_chunk_cache_max = 1; - png_chunk_benign_error(png_ptr, "no space in chunk cache"); + png_chunk_benign_error(png_ptr, "chunk cache full"); /* FALL THROUGH */ case 1: /* NOTE: prior to 1.6.0 this case resulted in an unknown critical * chunk being skipped, now there will be a hard error below. @@ -4369,9 +4372,9 @@ if (row_bytes > (png_uint_32)65536L) png_error(png_ptr, "This image requires a row greater than 64KB"); #endif - if (row_bytes + 48 > png_ptr->old_big_row_buf_size) + if (row_bytes + 48 > png_ptr->big_row_buf_size) { png_free(png_ptr, png_ptr->big_row_buf); png_free(png_ptr, png_ptr->big_prev_row); @@ -4406,9 +4409,9 @@ /* Use 31 bytes of padding before and 17 bytes after row_buf. */ png_ptr->row_buf = png_ptr->big_row_buf + 31; png_ptr->prev_row = png_ptr->big_prev_row + 31; #endif - png_ptr->old_big_row_buf_size = row_bytes + 48; + png_ptr->big_row_buf_size = row_bytes + 48; } #ifdef PNG_MAX_MALLOC_64K if (png_ptr->rowbytes > 65535) diff -ru4NwbB libpng-1.6.0beta33/pngset.c libpng-1.7.0alpha01/pngset.c --- libpng-1.6.0beta33/pngset.c 2012-12-15 08:22:35.092114465 -0600 +++ libpng-1.7.0alpha01/pngset.c 2012-12-15 10:05:51.410067337 -0600 @@ -1,8 +1,8 @@ /* pngset.c - storage of image information into info struct * - * Last changed in libpng 1.6.0 [(PENDING RELEASE)] + * Last changed in libpng 1.6.0 [(PENDING RELEASE)] * Copyright (c) 1998-2012 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -909,54 +909,91 @@ if (png_ptr == NULL || info_ptr == NULL) return; - if (trans_alpha != NULL) + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + png_chunk_report(png_ptr, + "png_set_tRNS: invalid on PNG with alpha channel", PNG_CHUNK_ERROR); + + else if (info_ptr->color_type & PNG_COLOR_MASK_PALETTE) { - /* It may not actually be necessary to set png_ptr->trans_alpha here; - * we do it for backward compatibility with the way the png_handle_tRNS - * function used to do the allocation. - * - * 1.6.0: The above statement is incorrect; png_handle_tRNS effectively - * relies on png_set_tRNS storing the information in png_struct - * (otherwise it won't be there for the code in pngrtran.c). - */ + int max_num; + /* Free the old data; num_trans 0 can be used to kill the tRNS */ png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0); - /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */ - png_ptr->trans_alpha = info_ptr->trans_alpha = png_voidcast(png_bytep, - png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH)); + /* Do this just in case the old data was not owned by libpng: */ + info_ptr->valid &= ~PNG_INFO_tRNS; + info_ptr->trans_alpha = NULL; + info_ptr->num_trans = 0; + + /* Expect png_set_PLTE to happen before png_set_tRNS, so num_palette will + * be set, but this is not a requirement of the API. + */ + if (png_ptr->num_palette) + max_num = png_ptr->num_palette; + + else + max_num = 1 << png_ptr->bit_depth; + + if (num_trans > max_num) + { + png_chunk_report(png_ptr, "png_set_tRNS: num_trans too large", + PNG_CHUNK_ERROR); + /* If control returns simply limit it; the behavior prior to 1.7 was to + * issue a warning and skip the palette in png_write_tRNS. + */ + num_trans = max_num; + } + + /* But only attempt a malloc if there is something to do; so the app can + * set a tRNS array then later delete it. + */ + if (num_trans > 0 && trans_alpha != NULL) + { + /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1, + * this avoids issues where a palette image contains out of range + * indices. + */ + info_ptr->trans_alpha = png_voidcast(png_bytep, png_malloc(png_ptr, + PNG_MAX_PALETTE_LENGTH)); + info_ptr->free_me |= PNG_FREE_TRNS; - if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH) - memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans); + memcpy(info_ptr->trans_alpha, trans_alpha, num_trans); + info_ptr->valid |= PNG_INFO_tRNS; + info_ptr->num_trans = (png_uint_16)num_trans; /* SAFE */ + } } + else /* not a PALETTE image */ + { + /* Invalidate any prior transparent color, set num_trans too, it is not + * used internally in this case but png_get_tRNS still returns it. + */ + info_ptr->valid &= ~PNG_INFO_tRNS; + info_ptr->num_trans = 0; /* for png_get_tRNS */ + if (trans_color != NULL) { int sample_max = (1 << info_ptr->bit_depth); if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY && - trans_color->gray > sample_max) || + trans_color->gray <= sample_max) || (info_ptr->color_type == PNG_COLOR_TYPE_RGB && - (trans_color->red > sample_max || - trans_color->green > sample_max || - trans_color->blue > sample_max))) - png_warning(png_ptr, - "tRNS chunk has out-of-range samples for bit_depth"); - + trans_color->red <= sample_max && + trans_color->green <= sample_max && + trans_color->blue <= sample_max)) + { info_ptr->trans_color = *trans_color; - - if (num_trans == 0) - num_trans = 1; + info_ptr->valid |= PNG_INFO_tRNS; + info_ptr->num_trans = 1; /* for png_get_tRNS */ } - info_ptr->num_trans = (png_uint_16)num_trans; - - if (num_trans != 0) - { - info_ptr->valid |= PNG_INFO_tRNS; - info_ptr->free_me |= PNG_FREE_TRNS; + else + png_chunk_report(png_ptr, + "tRNS chunk has out-of-range samples for bit_depth", + PNG_CHUNK_ERROR); + } } } #endif @@ -1486,29 +1523,29 @@ /* Images with dimensions larger than these limits will be * rejected by png_set_IHDR(). To accept any PNG datastream * regardless of dimensions, set both limits to 0x7ffffffL. */ - if (png_ptr == NULL) - return; - + if (png_ptr != NULL) + { png_ptr->user_width_max = user_width_max; png_ptr->user_height_max = user_height_max; } +} /* This function was added to libpng 1.4.0 */ void PNGAPI png_set_chunk_cache_max (png_structrp png_ptr, png_uint_32 user_chunk_cache_max) { - if (png_ptr) + if (png_ptr != NULL) png_ptr->user_chunk_cache_max = user_chunk_cache_max; } /* This function was added to libpng 1.4.1 */ void PNGAPI png_set_chunk_malloc_max (png_structrp png_ptr, png_alloc_size_t user_chunk_malloc_max) { - if (png_ptr) + if (png_ptr != NULL) png_ptr->user_chunk_malloc_max = user_chunk_malloc_max; } #endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */ diff -ru4NwbB libpng-1.6.0beta33/pngstruct.h libpng-1.7.0alpha01/pngstruct.h --- libpng-1.6.0beta33/pngstruct.h 2012-12-15 08:22:34.959263272 -0600 +++ libpng-1.7.0alpha01/pngstruct.h 2012-12-15 10:05:51.270718581 -0600 @@ -4,9 +4,9 @@ * Copyright (c) 1998-2012 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * - * Last changed in libpng 1.6.0 [(PENDING RELEASE)] + * Last changed in libpng 1.6.0 [(PENDING RELEASE)] * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer * and license in png.h @@ -47,12 +47,12 @@ /* zlib.h declares a magic type 'uInt' that limits the amount of data that zlib * can handle at once. This type need be no larger than 16 bits (so maximum of * 65535), this define allows us to discover how big it is, but limited by the - * maximuum for png_size_t. The value can be overriden in a library build - * (pngusr.h, or set it in CPPFLAGS) and it works to set it to a considerably - * lower value (e.g. 255 works). A lower value may help memory usage (slightly) - * and may even improve performance on some systems (and degrade it on others.) + * maximum for size_t. The value can be overriden in a library build (pngusr.h, + * or set it in CPPFLAGS) and it works to set it to a considerably lower value + * (e.g. 255 works). A lower value may help memory usage (slightly) and may + * even improve performance on some systems (and degrade it on others.) */ #ifndef ZLIB_IO_MAX # define ZLIB_IO_MAX ((uInt)-1) #endif @@ -136,348 +136,412 @@ #define PNG_COLORSPACE_FROM_cHRM 0x0010 #define PNG_COLORSPACE_FROM_sRGB 0x0020 #define PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB 0x0040 #define PNG_COLORSPACE_MATCHES_sRGB 0x0080 /* exact match on profile */ +#define PNG_COLORSPACE_RGB_TO_GRAY_SET 0x0100 /* user specified coeffs */ #define PNG_COLORSPACE_INVALID 0x8000 #define PNG_COLORSPACE_CANCEL(flags) (0xffff ^ (flags)) #endif /* COLORSPACE || GAMMA */ struct png_struct_def { -#ifdef PNG_SETJMP_SUPPORTED - jmp_buf jmp_buf_local; /* New name in 1.6.0 for jmp_buf in png_struct */ - png_longjmp_ptr longjmp_fn;/* setjmp non-local goto function. */ - jmp_buf *jmp_buf_ptr; /* passed to longjmp_fn */ - size_t jmp_buf_size; /* size of the above, if allocated */ -#endif - png_error_ptr error_fn; /* function for printing errors and aborting */ -#ifdef PNG_WARNINGS_SUPPORTED - png_error_ptr warning_fn; /* function for printing warnings */ -#endif - png_voidp error_ptr; /* user supplied struct for error functions */ - png_rw_ptr write_data_fn; /* function for writing output data */ - png_rw_ptr read_data_fn; /* function for reading input data */ - png_voidp io_ptr; /* ptr to application struct for I/O functions */ - -#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED - png_user_transform_ptr read_user_transform_fn; /* user read transform */ -#endif - -#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED - png_user_transform_ptr write_user_transform_fn; /* user write transform */ -#endif - -/* These were added in libpng-1.0.2 */ -#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) - png_voidp user_transform_ptr; /* user supplied struct for user transform */ - png_byte user_transform_depth; /* bit depth of user transformed pixels */ - png_byte user_transform_channels; /* channels in user transformed pixels */ -#endif -#endif - - png_uint_32 mode; /* tells us where we are in the PNG file */ - png_uint_32 flags; /* flags indicating various things to libpng */ - png_uint_32 transformations; /* which transformations to perform */ - - png_uint_32 zowner; /* ID (chunk type) of zstream owner, 0 if none */ - z_stream zstream; /* decompression structure */ - -#ifdef PNG_WRITE_SUPPORTED - png_compression_bufferp zbuffer_list; /* Created on demand during write */ - uInt zbuffer_size; /* size of the actual buffer */ - - int zlib_level; /* holds zlib compression level */ - int zlib_method; /* holds zlib compression method */ - int zlib_window_bits; /* holds zlib compression window bits */ - int zlib_mem_level; /* holds zlib compression memory level */ - int zlib_strategy; /* holds zlib compression strategy */ -#endif -/* Added at libpng 1.5.4 */ -#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED - int zlib_text_level; /* holds zlib compression level */ - int zlib_text_method; /* holds zlib compression method */ - int zlib_text_window_bits; /* holds zlib compression window bits */ - int zlib_text_mem_level; /* holds zlib compression memory level */ - int zlib_text_strategy; /* holds zlib compression strategy */ -#endif -/* End of material added at libpng 1.5.4 */ -/* Added at libpng 1.6.0 */ -#ifdef PNG_WRITE_SUPPORTED - int zlib_set_level; /* Actual values set into the zstream on write */ - int zlib_set_method; - int zlib_set_window_bits; - int zlib_set_mem_level; - int zlib_set_strategy; -#endif - + /* Rearranged in libpng 1.7 to attempt to lessen padding; in general + * (char), (short), (int) and pointer types are kept separate, however + * associated members under the control of the same #define are still + * together. + * + * First the frequently accessed fields. Many processors perform arithmetic + * in the address pipeline, but frequently the amount of addition or + * subtraction is limited. By putting these fields at the head of png_struct + * the hope is that such processors will generate code that is both smaller + * and faster. + */ + png_colorp palette; /* palette from the input file */ + size_t rowbytes; /* size of row in bytes */ + size_t info_rowbytes; /* cache of updated row bytes */ png_uint_32 width; /* width of image in pixels */ png_uint_32 height; /* height of image in pixels */ png_uint_32 num_rows; /* number of rows in current pass */ png_uint_32 usr_width; /* width of row at start of write */ - png_size_t rowbytes; /* size of row in bytes */ png_uint_32 iwidth; /* width of current interlaced row in pixels */ png_uint_32 row_number; /* current row in interlace pass */ png_uint_32 chunk_name; /* PNG_CHUNK() id of current chunk */ - png_bytep prev_row; /* buffer to save previous (unfiltered) row. - * This is a pointer into big_prev_row - */ - png_bytep row_buf; /* buffer to save current (unfiltered) row. - * This is a pointer into big_row_buf - */ -#ifdef PNG_WRITE_SUPPORTED - png_bytep sub_row; /* buffer to save "sub" row when filtering */ - png_bytep up_row; /* buffer to save "up" row when filtering */ - png_bytep avg_row; /* buffer to save "avg" row when filtering */ - png_bytep paeth_row; /* buffer to save "Paeth" row when filtering */ -#endif - png_size_t info_rowbytes; /* Added in 1.5.4: cache of updated row bytes */ - - png_uint_32 idat_size; /* current IDAT size for read */ png_uint_32 crc; /* current chunk CRC value */ - png_colorp palette; /* palette from the input file */ - png_uint_16 num_palette; /* number of color entries in palette */ + png_uint_32 mode; /* tells us where we are in the PNG file */ + png_uint_32 flags; /* flags indicating various things to libpng */ + png_uint_32 transformations;/* which transformations to perform */ + png_uint_32 zowner; /* ID (chunk type) of zstream owner, 0 if none */ + png_uint_32 free_me; /* items libpng is responsible for freeing */ -/* Added at libpng-1.5.10 */ + int maximum_pixel_depth; /* pixel depth used for the row buffers */ #ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED int num_palette_max; /* maximum palette index found in IDAT */ #endif + png_uint_16 num_palette; /* number of color entries in palette */ png_uint_16 num_trans; /* number of transparency values */ - png_byte compression; /* file compression type (always 0) */ + + /* Single byte values, typically used either to save space or to hold 1-byte + * values from the PNG chunk specifications. + */ + png_byte compression_type; /* file compression type (always 0) */ png_byte filter; /* file filter type (always 0) */ png_byte interlaced; /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ png_byte pass; /* current interlace pass (0 - 6) */ png_byte do_filter; /* row filter flags (see PNG_FILTER_ below ) */ png_byte color_type; /* color type of file */ png_byte bit_depth; /* bit depth of file */ - png_byte usr_bit_depth; /* bit depth of users row: write only */ png_byte pixel_depth; /* number of bits per pixel */ png_byte channels; /* number of channels in file */ -#ifdef PNG_WRITE_SUPPORTED - png_byte usr_channels; /* channels at start of write: write only */ -#endif png_byte sig_bytes; /* magic bytes read/written from start of file */ - png_byte maximum_pixel_depth; - /* pixel depth used for the row buffers */ png_byte transformed_pixel_depth; /* pixel depth after read/write transforms */ -#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) - png_uint_16 filler; /* filler bytes for pixel expansion */ + + /* ERROR HANDLING */ +#ifdef PNG_SETJMP_SUPPORTED + /* jmp_buf can have very high alignment requirements on some systems, so put + * it first. + */ + jmp_buf jmp_buf_local; + jmp_buf *jmp_buf_ptr; /* passed to longjmp_fn */ + png_longjmp_ptr longjmp_fn; /* setjmp non-local goto function. */ + size_t jmp_buf_size; /* size of *jmp_buf_ptr, if allocated */ #endif -#if defined(PNG_bKGD_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ - defined(PNG_READ_ALPHA_MODE_SUPPORTED) - png_byte background_gamma_type; - png_fixed_point background_gamma; - png_color_16 background; /* background color in screen gamma space */ -#ifdef PNG_READ_GAMMA_SUPPORTED - png_color_16 background_1; /* background normalized to gamma 1.0 */ + /* Error/warning callbacks */ + png_error_ptr error_fn; /* print an error message and abort */ +#ifdef PNG_WARNINGS_SUPPORTED + png_error_ptr warning_fn; /* print a warning and continue */ #endif -#endif /* PNG_bKGD_SUPPORTED */ + png_voidp error_ptr; /* user supplied data for the above */ -#ifdef PNG_WRITE_FLUSH_SUPPORTED - png_flush_ptr output_flush_fn; /* Function for flushing output */ - png_uint_32 flush_dist; /* how many rows apart to flush, 0 - no flush */ - png_uint_32 flush_rows; /* number of rows written since last flush */ + /* MEMORY ALLOCATION */ +#ifdef PNG_USER_MEM_SUPPORTED + png_malloc_ptr malloc_fn; /* allocate memory */ + png_free_ptr free_fn; /* free memory */ + png_voidp mem_ptr; /* user supplied data for the above */ #endif -#ifdef PNG_READ_GAMMA_SUPPORTED - int gamma_shift; /* number of "insignificant" bits in 16-bit gamma */ - png_fixed_point screen_gamma; /* screen gamma value (display_exponent) */ + /* IO and BASIC READ/WRITE SUPPORT */ + png_voidp io_ptr; /* user supplied data for IO callbacks */ - png_bytep gamma_table; /* gamma table for 8-bit depth files */ - png_uint_16pp gamma_16_table; /* gamma table for 16-bit depth files */ -#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ - defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ - defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) - png_bytep gamma_from_1; /* converts from 1.0 to screen */ - png_bytep gamma_to_1; /* converts from file to 1.0 */ - png_uint_16pp gamma_16_from_1; /* converts from 1.0 to screen */ - png_uint_16pp gamma_16_to_1; /* converts from file to 1.0 */ -#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ -#endif +#ifdef PNG_READ_SUPPORTED + png_rw_ptr read_data_fn; /* read some bytes (must succeed) */ + png_read_status_ptr read_row_fn; /* called after each row is decoded */ + png_bytep read_buffer; /* buffer for reading chunk data */ -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED) - png_color_8 sig_bit; /* significant bits in each available channel */ -#endif + /* During read the following array is set up to point to the appropriate + * un-filter function, this allows per-image and per-processor optimization. + */ + void (*read_filter[PNG_FILTER_VALUE_LAST-1])(png_row_infop row_info, + png_bytep row, png_const_bytep prev_row); -#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) - png_color_8 shift; /* shift for significant bit tranformation */ +#if (defined PNG_COLORSPACE_SUPPORTED || defined PNG_GAMMA_SUPPORTED) + /* The png_struct colorspace structure is only required on read - on write it + * is in (just) the info_struct. + */ + png_colorspace colorspace; #endif +#endif /* PNG_READ_SUPPORTED */ -#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \ - || defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - png_bytep trans_alpha; /* alpha values for paletted files */ - png_color_16 trans_color; /* transparent color for non-paletted files */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_uint_32 user_width_max; /* Maximum width on read */ + png_uint_32 user_height_max; /* Maximum height on read */ + /* Total memory that a single zTXt, sPLT, iTXt, iCCP, or unknown chunk + * can occupy when decompressed. 0 means unlimited. This field is a counter + * - it is decremented as memory is allocated. + */ + png_alloc_size_t user_chunk_malloc_max; +#endif +#ifdef PNG_USER_LIMITS_SUPPORTED + /* limit on total *number* of sPLT, text and unknown chunks that can be + * stored. 0 means unlimited. This field is a counter - it is decremented + * as chunks are encountered. + */ + png_uint_32 user_chunk_cache_max; #endif - png_read_status_ptr read_row_fn; /* called after each row is decoded */ - png_write_status_ptr write_row_fn; /* called after each row is encoded */ + /* The progressive reader gets passed data and calls application handling + * functions when appropriate. + */ #ifdef PNG_PROGRESSIVE_READ_SUPPORTED png_progressive_info_ptr info_fn; /* called after header data fully read */ - png_progressive_row_ptr row_fn; /* called after a prog. row is decoded */ + png_progressive_row_ptr row_fn; /* called after a row is decoded */ png_progressive_end_ptr end_fn; /* called after image is complete */ + + /* Progressive read control data */ png_bytep save_buffer_ptr; /* current location in save_buffer */ png_bytep save_buffer; /* buffer for previously read data */ png_bytep current_buffer_ptr; /* current location in current_buffer */ png_bytep current_buffer; /* buffer for recently used data */ + + size_t save_buffer_size; /* amount of data now in save_buffer */ + size_t save_buffer_max; /* total size of save_buffer */ + size_t buffer_size; /* total amount of available input data */ + size_t current_buffer_size; /* amount of data now in current_buffer */ + png_uint_32 push_length; /* size of current input chunk */ png_uint_32 skip_length; /* bytes to skip in input data */ - png_size_t save_buffer_size; /* amount of data now in save_buffer */ - png_size_t save_buffer_max; /* total size of save_buffer */ - png_size_t buffer_size; /* total amount of available input data */ - png_size_t current_buffer_size; /* amount of data now in current_buffer */ + int process_mode; /* what push library is currently doing */ int cur_palette; /* current push library palette index */ +#endif -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ - -#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) -/* For the Borland special 64K segment handler */ - png_bytepp offset_table_ptr; - png_bytep offset_table; - png_uint_16 offset_table_number; - png_uint_16 offset_table_count; - png_uint_16 offset_table_count_free; +#ifdef PNG_WRITE_SUPPORTED + png_rw_ptr write_data_fn;/* write some bytes (must succeed) */ + png_write_status_ptr write_row_fn; /* called after each row is encoded */ #endif -#ifdef PNG_READ_QUANTIZE_SUPPORTED - png_bytep palette_lookup; /* lookup table for quantizing */ - png_bytep quantize_index; /* index translation for palette files */ +#ifdef PNG_WRITE_FLUSH_SUPPORTED + png_flush_ptr output_flush_fn; /* Function for flushing output */ + png_uint_32 flush_dist; /* how many rows apart to flush, 0 - no flush */ + png_uint_32 flush_rows; /* number of rows written since last flush */ #endif #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - png_byte heuristic_method; /* heuristic for row filter selection */ - png_byte num_prev_filters; /* number of weights for previous rows */ png_bytep prev_filters; /* filter type(s) of previous row(s) */ png_uint_16p filter_weights; /* weight(s) for previous line(s) */ png_uint_16p inv_filter_weights; /* 1/weight(s) for previous line(s) */ png_uint_16p filter_costs; /* relative filter calculation cost */ png_uint_16p inv_filter_costs; /* 1/relative filter calculation cost */ + png_byte heuristic_method; /* heuristic for row filter selection */ + png_byte num_prev_filters; /* number of weights for previous rows */ #endif -#if PNG_LIBPNG_VER < 10700 -/* To do: remove this from libpng-1.7 */ -#ifdef PNG_TIME_RFC1123_SUPPORTED - char time_buffer[29]; /* String to hold RFC 1123 time text */ +#ifdef PNG_WRITE_SUPPORTED + png_byte usr_bit_depth; /* bit depth of users row */ + png_byte usr_channels; /* channels at start of write */ #endif + +#ifdef PNG_IO_STATE_SUPPORTED + png_uint_32 io_state; /* tells the app read/write progress */ #endif -/* New members added in libpng-1.0.6 */ + /* ROW BUFFERS + * + * Members that hold pointers to the decompressed image rows. + */ + png_bytep row_buf; /* buffer for the current (unfiltered) row */ +#if (defined PNG_WRITE_FILTER_SUPPORTED) || (defined PNG_READ_SUPPORTED) + png_bytep prev_row; /* buffer to save the previous (unfiltered) row */ +#endif - png_uint_32 free_me; /* flags items libpng is responsible for freeing */ +#ifdef PNG_READ_SUPPORTED + /* The row_buf and prev_row pointers are misaligned so that the start of the + * row - after the filter byte - is aligned, the 'big_' pointers record the + * original allocated pointer. + */ + png_bytep big_row_buf; + png_bytep big_prev_row; + size_t big_row_buf_size; /* Actual size of both */ +#endif +#ifdef PNG_WRITE_SUPPORTED + /* This is somewhat excessive, there is no obvious reason on write to + * allocate a buffer for each possible filtered row, only for the one being + * tested and the current best. + * + * TODO: fix this + */ + png_bytep sub_row; /* buffer to save "sub" row when filtering */ + png_bytep up_row; /* buffer to save "up" row when filtering */ + png_bytep avg_row; /* buffer to save "avg" row when filtering */ + png_bytep paeth_row; /* buffer to save "Paeth" row when filtering */ +#endif + + /* UNKNOWN CHUNK HANDLING */ + /* TODO: this is excessively complicated, there are multiple ways of doing + * the same thing. It should be cleaned up, possibly by finding out which + * APIs applications really use. + */ #ifdef PNG_USER_CHUNKS_SUPPORTED + /* General purpose pointer for all user/unknown chunk handling; points to + * application supplied data for use in the read_user_chunk_fn callback + * (currently there is no write side support - the write side must use the + * set_unknown_chunks interface.) + */ png_voidp user_chunk_ptr; +#endif + #ifdef PNG_READ_USER_CHUNKS_SUPPORTED + /* This is called back from the unknown chunk handling */ png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */ #endif +#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED + /* Temporary storage for unknown chunk that the library doesn't recognize, + * used while reading the chunk. + */ + png_unknown_chunk unknown_chunk; #endif #ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED - int unknown_default; /* As PNG_HANDLE_* */ - unsigned int num_chunk_list; /* Number of entries in the list */ png_bytep chunk_list; /* List of png_byte[5]; the textual chunk name * followed by a PNG_HANDLE_* byte */ + int unknown_default; /* As PNG_HANDLE_* */ + unsigned int num_chunk_list; /* Number of entries in the list */ #endif -/* New members added in libpng-1.0.3 */ -#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED - png_byte rgb_to_gray_status; - /* Added in libpng 1.5.5 to record setting of coefficients: */ - png_byte rgb_to_gray_coefficients_set; - /* These were changed from png_byte in libpng-1.0.6 */ - png_uint_16 rgb_to_gray_red_coeff; - png_uint_16 rgb_to_gray_green_coeff; - /* deleted in 1.5.5: rgb_to_gray_blue_coeff; */ + /* USER TRANSFORM SUPPORT */ +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + png_user_transform_ptr read_user_transform_fn; /* user read transform */ +#endif +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + png_user_transform_ptr write_user_transform_fn; /* user write transform */ +#endif +#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED + png_voidp user_transform_ptr; /* user supplied data for the above */ + png_byte user_transform_depth; /* bit depth of user transformed pixels */ + png_byte user_transform_channels; /* channels in user transformed pixels */ #endif -/* New member added in libpng-1.0.4 (renamed in 1.0.9) */ -#if defined(PNG_MNG_FEATURES_SUPPORTED) -/* Changed from png_byte to png_uint_32 at version 1.2.0 */ - png_uint_32 mng_features_permitted; + /* READ TRANSFORM SUPPORT + * + * Quite a lot of things can be done to the original image data on read, and + * most of these are configurable. The data required by the configurable + * read transforms should be stored here. The png_color_16 and png_color_8 + * structures have low alignment requirements and odd sizes, so may cause + * misalignment when present. Member alignment is as follows: + * + * png_color_16 png_uint_16 + * png_color_8 png_byte + */ + /* GAMMA/BACKGROUND/ALPHA-MODE/RGB-TO-GRAY/tRNS/sBIT + * + * These things are all interrelated because they need some or all of the + * gamma tables. Some attempt has been made below to order these members by + * size, so that as little padding as possible is required. + */ +#ifdef PNG_READ_GAMMA_SUPPORTED + png_bytep gamma_table; /* gamma table for 8-bit depth files */ + png_uint_16p gamma_16_table; /* gamma table for 16-bit depth files */ + +#if defined PNG_READ_BACKGROUND_SUPPORTED ||\ + defined PNG_READ_ALPHA_MODE_SUPPORTED ||\ + defined PNG_READ_RGB_TO_GRAY_SUPPORTED + png_bytep gamma_from_1; /* converts from 1.0 to screen */ + png_uint_16p gamma_to_1; /* converts from file to 1.0 */ + png_uint_16p gamma_16_from_1; /* converts from 1.0 to screen */ + png_uint_16p gamma_16_to_1; /* converts from file to 1.0 */ +#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ +#endif /* PNG_READ_GAMMA_SUPPORTED */ + +#if defined PNG_READ_tRNS_SUPPORTED || defined PNG_READ_BACKGROUND_SUPPORTED ||\ + defined PNG_READ_EXPAND_SUPPORTED + png_bytep trans_alpha; /* alpha values for paletted files */ #endif -/* New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 */ -#ifdef PNG_MNG_FEATURES_SUPPORTED - png_byte filter_type; + /* Integer values */ +#if defined PNG_READ_BACKGROUND_SUPPORTED ||\ + defined PNG_READ_ALPHA_MODE_SUPPORTED + png_fixed_point background_gamma; +#endif +#ifdef PNG_READ_GAMMA_SUPPORTED + png_fixed_point screen_gamma; /* screen gamma value (display_exponent) */ + int gamma_shift; /* number of "insignificant" bits in 16-bit gamma */ #endif -/* New members added in libpng-1.2.0 */ + /* png_color_16 */ +#if defined PNG_READ_BACKGROUND_SUPPORTED ||\ + defined PNG_READ_ALPHA_MODE_SUPPORTED + png_color_16 background; /* background color in screen gamma space */ + png_color_16 background_1; /* background normalized to gamma 1.0 */ +#endif +#if defined PNG_READ_tRNS_SUPPORTED || defined PNG_READ_BACKGROUND_SUPPORTED ||\ + defined PNG_READ_EXPAND_SUPPORTED + png_color_16 trans_color; /* transparent color for non-paletted files */ +#endif -/* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */ -#ifdef PNG_USER_MEM_SUPPORTED - png_voidp mem_ptr; /* user supplied struct for mem functions */ - png_malloc_ptr malloc_fn; /* function for allocating memory */ - png_free_ptr free_fn; /* function for freeing memory */ + /* png_uint_16 */ +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + png_uint_16 rgb_to_gray_red_coeff; + png_uint_16 rgb_to_gray_green_coeff; + /* The blue coefficient is calculated from the above */ #endif -/* New member added in libpng-1.0.13 and 1.2.0 */ - png_bytep big_row_buf; /* buffer to save current (unfiltered) row */ + /* png_color_8 */ +#if defined PNG_READ_GAMMA_SUPPORTED || defined PNG_READ_sBIT_SUPPORTED + png_color_8 sig_bit; /* significant bits in each available channel */ +#endif -#ifdef PNG_READ_QUANTIZE_SUPPORTED -/* The following three members were added at version 1.0.14 and 1.2.4 */ - png_bytep quantize_sort; /* working sort array */ - png_bytep index_to_palette; /* where the original index currently is - in the palette */ - png_bytep palette_to_index; /* which original index points to this - palette color */ + /* png_byte */ +#if defined PNG_READ_BACKGROUND_SUPPORTED ||\ + defined PNG_READ_ALPHA_MODE_SUPPORTED + png_byte background_gamma_type; +#endif +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + png_byte rgb_to_gray_status; #endif -/* New members added in libpng-1.0.16 and 1.2.6 */ - png_byte compression_type; + /* SHIFT - both READ_SHIFT and WRITE_SHIFT */ +#if defined PNG_READ_SHIFT_SUPPORTED || defined PNG_WRITE_SHIFT_SUPPORTED + png_color_8 shift; /* shift for significant bit tranformation */ +#endif -#ifdef PNG_USER_LIMITS_SUPPORTED - png_uint_32 user_width_max; - png_uint_32 user_height_max; + /* FILLER SUPPORT (pixel expansion or read, contraction on write) */ +#if defined PNG_READ_FILLER_SUPPORTED || defined PNG_WRITE_FILLER_SUPPORTED + png_uint_16 filler; /* filler bytes for pixel expansion */ +#endif - /* Added in libpng-1.4.0: Total number of sPLT, text, and unknown - * chunks that can be stored (0 means unlimited). + /* QUANTIZE (convert to color-mapped) */ +#ifdef PNG_READ_QUANTIZE_SUPPORTED + png_bytep palette_lookup; /* lookup table for quantizing */ + png_bytep quantize_index; /* index translation for palette files */ + png_bytep quantize_sort; /* working sort array */ + png_bytep index_to_palette; /* where the original index currently is in the + * palette */ - png_uint_32 user_chunk_cache_max; - - /* Total memory that a zTXt, sPLT, iTXt, iCCP, or unknown chunk - * can occupy when decompressed. 0 means unlimited. + png_bytep palette_to_index; /* which original index points to this palette + * color */ - png_alloc_size_t user_chunk_malloc_max; #endif -/* New member added in libpng-1.0.25 and 1.2.17 */ -#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED - /* Temporary storage for unknown chunk that the library doesn't recognize, - * used while reading the chunk. - */ - png_unknown_chunk unknown_chunk; + /* MNG SUPPORT */ +#ifdef PNG_MNG_FEATURES_SUPPORTED + png_uint_32 mng_features_permitted; + png_byte filter_type; #endif -/* New member added in libpng-1.2.26 */ - png_size_t old_big_row_buf_size; + /* COMPRESSION AND DECOMPRESSION SUPPORT. + * + * zlib expects a 'zstream' as the fundamental control structure, it allows + * all the parameters to be passed as one pointer. + */ + z_stream zstream; /* decompression structure */ #ifdef PNG_READ_SUPPORTED -/* New member added in libpng-1.2.30 */ - png_bytep read_buffer; /* buffer for reading chunk data */ + /* These, and IDAT_read_size below, control how much input and output (at + * most) is available to zlib. + */ + png_uint_32 idat_size; /* current IDAT size for read */ png_alloc_size_t read_buffer_size; /* current size of the buffer */ #endif -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED - uInt IDAT_read_size; /* limit on read buffer size for IDAT */ -#endif -#ifdef PNG_IO_STATE_SUPPORTED -/* New member added in libpng-1.4.0 */ - png_uint_32 io_state; +#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED + int zlib_text_level; /* holds zlib compression level */ + int zlib_text_method; /* holds zlib compression method */ + int zlib_text_window_bits; /* holds zlib compression window bits */ + int zlib_text_mem_level; /* holds zlib compression memory level */ + int zlib_text_strategy; /* holds zlib compression strategy */ #endif -/* New member added in libpng-1.5.6 */ - png_bytep big_prev_row; +#ifdef PNG_WRITE_SUPPORTED + int zlib_level; /* holds zlib compression level */ + int zlib_method; /* holds zlib compression method */ + int zlib_window_bits; /* holds zlib compression window bits */ + int zlib_mem_level; /* holds zlib compression memory level */ + int zlib_strategy; /* holds zlib compression strategy */ - void (*read_filter[PNG_FILTER_VALUE_LAST-1])(png_row_infop row_info, - png_bytep row, png_const_bytep prev_row); + int zlib_set_level; /* Actual values set into the zstream on write */ + int zlib_set_method; + int zlib_set_window_bits; + int zlib_set_mem_level; + int zlib_set_strategy; -#ifdef PNG_READ_SUPPORTED -#if defined PNG_COLORSPACE_SUPPORTED || defined PNG_GAMMA_SUPPORTED - png_colorspace colorspace; + png_compression_bufferp zbuffer_list; /* Created on demand during write */ + uInt zbuffer_size; /* size of the actual zlib buffer */ #endif + +#ifdef PNG_SEQUENTIAL_READ_SUPPORTED + uInt IDAT_read_size; /* limit on read buffer size for IDAT */ #endif }; #endif /* PNGSTRUCT_H */ diff -ru4NwbB libpng-1.6.0beta33/pngtest.c libpng-1.7.0alpha01/pngtest.c --- libpng-1.6.0beta33/pngtest.c 2012-12-15 08:22:35.102408430 -0600 +++ libpng-1.7.0alpha01/pngtest.c 2012-12-15 10:05:51.420441903 -0600 @@ -1,8 +1,8 @@ /* pngtest.c - a simple test program to test libpng * - * Last changed in libpng 1.6.0 [(PENDING RELEASE)] + * Last changed in libpng 1.6.0 [(PENDING RELEASE)] * Copyright (c) 1998-2012 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -1948,5 +1948,5 @@ } #endif /* Generate a compiler error if there is an old png.h in the search path. */ -typedef png_libpng_version_%_VER_% Your_png_h_is_not_version_%_VER_%; +typedef png_libpng_version_1_6_0beta32 Your_png_h_is_not_version_1_6_0beta32; diff -ru4NwbB libpng-1.6.0beta33/pngtrans.c libpng-1.7.0alpha01/pngtrans.c --- libpng-1.6.0beta33/pngtrans.c 2012-12-15 08:22:35.110156186 -0600 +++ libpng-1.7.0alpha01/pngtrans.c 2012-12-15 10:05:51.428159584 -0600 @@ -1,8 +1,8 @@ /* pngtrans.c - transforms the data in a row (used by both readers and writers) * - * Last changed in libpng 1.6.0 [(PENDING RELEASE)] + * Last changed in libpng 1.6.0 [(PENDING RELEASE)] * Copyright (c) 1998-2012 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -56,9 +56,11 @@ if (png_ptr->bit_depth < 8) { png_ptr->transformations |= PNG_PACK; +# ifdef PNG_WRITE_SUPPORTED png_ptr->usr_bit_depth = 8; +# endif } } #endif diff -ru4NwbB libpng-1.6.0beta33/pngwio.c libpng-1.7.0alpha01/pngwio.c --- libpng-1.6.0beta33/pngwio.c 2012-12-15 08:22:35.115737137 -0600 +++ libpng-1.7.0alpha01/pngwio.c 2012-12-15 10:05:51.433866372 -0600 @@ -1,8 +1,8 @@ /* pngwio.c - functions for data output * - * Last changed in libpng 1.6.0 [(PENDING RELEASE)] + * Last changed in libpng 1.6.0 [(PENDING RELEASE)] * Copyright (c) 1998-2012 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -150,8 +150,9 @@ png_ptr->output_flush_fn = output_flush_fn; # endif #endif /* PNG_WRITE_FLUSH_SUPPORTED */ +#ifdef PNG_READ_SUPPORTED /* It is an error to read while writing a png file */ if (png_ptr->read_data_fn != NULL) { png_ptr->read_data_fn = NULL; @@ -159,6 +160,7 @@ png_warning(png_ptr, "Can't set both read_data_fn and write_data_fn in the" " same structure"); } +#endif } #endif /* PNG_WRITE_SUPPORTED */ diff -ru4NwbB libpng-1.6.0beta33/pngwrite.c libpng-1.7.0alpha01/pngwrite.c --- libpng-1.6.0beta33/pngwrite.c 2012-12-15 08:22:35.126743178 -0600 +++ libpng-1.7.0alpha01/pngwrite.c 2012-12-15 10:05:51.445074845 -0600 @@ -1,8 +1,8 @@ /* pngwrite.c - general routines to write a PNG file * - * Last changed in libpng 1.6.0 [(PENDING RELEASE)] + * Last changed in libpng 1.6.0 [(PENDING RELEASE)] * Copyright (c) 1998-2012 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -215,10 +215,15 @@ /* Invert the alpha channel (in tRNS) */ if ((png_ptr->transformations & PNG_INVERT_ALPHA) && info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) { - int j; - for (j = 0; j<(int)info_ptr->num_trans; j++) + int j, jend; + + jend = info_ptr->num_trans; + if (jend > PNG_MAX_PALETTE_LENGTH) + jend = PNG_MAX_PALETTE_LENGTH; + + for (j = 0; jtrans_alpha[j] = (png_byte)(255 - info_ptr->trans_alpha[j]); } #endif @@ -926,121 +931,101 @@ #ifdef PNG_MNG_FEATURES_SUPPORTED if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && (method == PNG_INTRAPIXEL_DIFFERENCING)) method = PNG_FILTER_TYPE_BASE; - #endif - if (method == PNG_FILTER_TYPE_BASE) - { - switch (filters & (PNG_ALL_FILTERS | 0x07)) - { -#ifdef PNG_WRITE_FILTER_SUPPORTED - case 5: - case 6: - case 7: png_app_error(png_ptr, "Unknown row filter for method 0"); - /* FALL THROUGH */ -#endif /* PNG_WRITE_FILTER_SUPPORTED */ - case PNG_FILTER_VALUE_NONE: - png_ptr->do_filter = PNG_FILTER_NONE; break; + /* The only supported method, except for the check above, is + * PNG_FILTER_TYPE_BASE. The code below does not use 'method' other than + * for the check, so just keep going if png_app_error returns. + */ + if (method != PNG_FILTER_TYPE_BASE) + png_app_error(png_ptr, "Unknown custom filter method"); + + /* If filter writing is not supported the 'filters' value must be zero, + * otherwise the value must be a single, valid, filter value or a set of the + * mask values. The defines in png.h are such that the filter masks used in + * this API and internally are 1<<(3+value), value is in the range 0..4, so + * this fits in a byte. + */ #ifdef PNG_WRITE_FILTER_SUPPORTED - case PNG_FILTER_VALUE_SUB: - png_ptr->do_filter = PNG_FILTER_SUB; break; - - case PNG_FILTER_VALUE_UP: - png_ptr->do_filter = PNG_FILTER_UP; break; + /* Notice that PNG_NO_FILTERS is 0 and passes this test; this is OK + * because filters then gets set to PNG_FILTER_NONE, as is required. + */ + if (filters < PNG_FILTER_VALUE_LAST) + filters = 0x08 << filters; - case PNG_FILTER_VALUE_AVG: - png_ptr->do_filter = PNG_FILTER_AVG; break; + else if ((filters & ~PNG_ALL_FILTERS) != 0) + { + png_app_error(png_ptr, "png_set_filter: invalid filters mask/value"); - case PNG_FILTER_VALUE_PAETH: - png_ptr->do_filter = PNG_FILTER_PAETH; break; + /* For compatibility with the previous behavior assume a mask value was + * passed and ignore the non-mask bits. + */ + filters &= PNG_ALL_FILTERS; - default: - png_ptr->do_filter = (png_byte)filters; break; -#else - default: - png_app_error(png_ptr, "Unknown row filter for method 0"); -#endif /* PNG_WRITE_FILTER_SUPPORTED */ + /* For a possibly foolish consistency (it shouldn't matter) set + * PNG_FILTER_NONE rather than 0. + */ + if (filters == 0) + filters = PNG_FILTER_NONE; } +# else + /* PNG_FILTER_VALUE_NONE and PNG_NO_FILTERS are both 0. */ + if (filters != 0 && filters != PNG_FILTER_NONE) + png_app_error(png_ptr, "png_set_filter: no filters supported"); + + filters = PNG_FILTER_NONE; +# endif +# ifdef PNG_WRITE_FILTER_SUPPORTED /* If we have allocated the row_buf, this means we have already started * with the image and we should have allocated all of the filter buffers * that have been selected. If prev_row isn't already allocated, then * it is too late to start using the filters that need it, since we * will be missing the data in the previous row. If an application * wants to start and stop using particular filters during compression, * it should start out with all of the filters, and then add and * remove them after the start of compression. + * + * NOTE: this is a nasty constraint on the code, because it means that the + * prev_row buffer must be maintained even if there are currently no + * 'prev_row' requiring filters active. */ if (png_ptr->row_buf != NULL) { -#ifdef PNG_WRITE_FILTER_SUPPORTED - if ((png_ptr->do_filter & PNG_FILTER_SUB) && png_ptr->sub_row == NULL) - { - png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; - } - - if ((png_ptr->do_filter & PNG_FILTER_UP) && png_ptr->up_row == NULL) - { - if (png_ptr->prev_row == NULL) - { - png_warning(png_ptr, "Can't add Up filter after starting"); - png_ptr->do_filter = (png_byte)(png_ptr->do_filter & - ~PNG_FILTER_UP); - } + /* Repeat the checks in png_write_start_row; 1 pixel high or wide + * images cannot benefit from certain filters. If this isn't done here + * the check below will fire on 1 pixel high images. + */ + if (png_ptr->height == 1) + filters &= ~(PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH); - else - { - png_ptr->up_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; - } - } + if (png_ptr->width == 1) + filters &= ~(PNG_FILTER_SUB|PNG_FILTER_AVG|PNG_FILTER_PAETH); - if ((png_ptr->do_filter & PNG_FILTER_AVG) && png_ptr->avg_row == NULL) - { - if (png_ptr->prev_row == NULL) + if ((filters & (PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH)) != 0 + && png_ptr->prev_row == NULL) { - png_warning(png_ptr, "Can't add Average filter after starting"); - png_ptr->do_filter = (png_byte)(png_ptr->do_filter & - ~PNG_FILTER_AVG); - } - - else - { - png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; - } - } - - if ((png_ptr->do_filter & PNG_FILTER_PAETH) && - png_ptr->paeth_row == NULL) - { - if (png_ptr->prev_row == NULL) - { - png_warning(png_ptr, "Can't add Paeth filter after starting"); - png_ptr->do_filter &= (png_byte)(~PNG_FILTER_PAETH); + /* This is the error case, however it is benign - the previous row + * is not available so the filter can't be used. Just warn here. + */ + png_app_warning(png_ptr, + "png_set_filter: UP/AVG/PAETH cannot be added after start"); + filters &= ~(PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH); } - else - { - png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; - } + /* Allocate any required buffers that have not already been allocated. + */ + png_write_alloc_filter_row_buffers(png_ptr, filters); } - - if (png_ptr->do_filter == PNG_NO_FILTERS) #endif /* PNG_WRITE_FILTER_SUPPORTED */ - png_ptr->do_filter = PNG_FILTER_NONE; - } - } - else - png_error(png_ptr, "Unknown custom filter method"); + + /* Finally store the value. + * TODO: this field could probably be removed if neither READ nor + * WRITE_FILTER are supported. + */ + png_ptr->do_filter = (png_byte)filters; /* SAFE: checked above */ } /* This allows us to influence the way in which libpng chooses the "best" * filter for the current scanline. While the "minimum-sum-of-absolute- diff -ru4NwbB libpng-1.6.0beta33/pngwtran.c libpng-1.7.0alpha01/pngwtran.c --- libpng-1.6.0beta33/pngwtran.c 2012-12-15 08:22:35.133566445 -0600 +++ libpng-1.7.0alpha01/pngwtran.c 2012-12-15 10:05:51.452049007 -0600 @@ -1,8 +1,8 @@ /* pngwtran.c - transforms the data in a row for PNG writers * - * Last changed in libpng 1.6.0 [(PENDING RELEASE)] + * Last changed in libpng 1.6.0 [(PENDING RELEASE)] * Copyright (c) 1998-2012 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * diff -ru4NwbB libpng-1.6.0beta33/pngwutil.c libpng-1.7.0alpha01/pngwutil.c --- libpng-1.6.0beta33/pngwutil.c 2012-12-15 08:22:35.146220665 -0600 +++ libpng-1.7.0alpha01/pngwutil.c 2012-12-15 10:05:51.465230438 -0600 @@ -1,8 +1,8 @@ /* pngwutil.c - utilities to write a PNG file * - * Last changed in libpng 1.6.0 [(PENDING RELEASE)] + * Last changed in libpng 1.6.0 [(PENDING RELEASE)] * Copyright (c) 1998-2012 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -1424,10 +1424,14 @@ png_debug(1, "in png_write_tRNS"); if (color_type == PNG_COLOR_TYPE_PALETTE) { - if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette) + if (num_trans <= 0 || num_trans > png_ptr->num_palette) { + /* This is an error which can only be reliably detected late, change to + * a png_app_warning here so that it will fail in debug. It should be + * a png_app_error. + */ png_app_warning(png_ptr, "Invalid number of transparent colors specified"); return; } @@ -1441,9 +1445,10 @@ { /* One 16 bit value */ if (tran->gray >= (1 << png_ptr->bit_depth)) { - png_app_warning(png_ptr, + /* This can no longer happen because it is checked in png_set_tRNS */ + png_warning(png_ptr, "Ignoring attempt to write tRNS chunk out-of-range for bit_depth"); return; } @@ -1463,9 +1468,10 @@ #else if (buf[0] | buf[2] | buf[4]) #endif { - png_app_warning(png_ptr, + /* Also checked in png_set_tRNS */ + png_warning(png_ptr, "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"); return; } @@ -1473,9 +1479,10 @@ } else { - png_app_warning(png_ptr, "Can't write tRNS with an alpha channel"); + /* Checked in png_set_tRNS */ + png_warning(png_ptr, "Can't write tRNS with an alpha channel"); } } #endif @@ -1930,8 +1937,49 @@ png_write_complete_chunk(png_ptr, png_tIME, buf, (png_size_t)7); } #endif +#ifdef PNG_WRITE_FILTER_SUPPORTED +void /* PRIVATE */ +png_write_alloc_filter_row_buffers(png_structrp png_ptr, int filters) + /* Allocate row buffers for any filters that need them, this is also called + * from png_set_filter if the filters are changed during write to ensure that + * the required buffers exist. png_set_filter ensures that up/avg/paeth are + * only set if png_ptr->prev_row is allocated. + */ +{ + /* The buffer size is determined just by the output row size, not any + * processing requirements. + */ + png_alloc_size_t buf_size = png_ptr->rowbytes + 1; + + if ((filters & PNG_FILTER_SUB) != 0 && png_ptr->sub_row == NULL) + { + png_ptr->sub_row = png_voidcast(png_bytep, png_malloc(png_ptr, buf_size)); + png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; + } + + if ((filters & PNG_FILTER_UP) != 0 && png_ptr->up_row == NULL) + { + png_ptr->up_row = png_voidcast(png_bytep, png_malloc(png_ptr, buf_size)); + png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; + } + + if ((filters & PNG_FILTER_AVG) != 0 && png_ptr->avg_row == NULL) + { + png_ptr->avg_row = png_voidcast(png_bytep, png_malloc(png_ptr, buf_size)); + png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; + } + + if ((filters & PNG_FILTER_PAETH) != 0 && png_ptr->paeth_row == NULL) + { + png_ptr->paeth_row = png_voidcast(png_bytep, png_malloc(png_ptr, + buf_size)); + png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; + } +} +#endif /* PNG_WRITE_FILTER_SUPPORTED */ + /* Initializes the row writing capability of libpng */ void /* PRIVATE */ png_write_start_row(png_structrp png_ptr) { @@ -1950,64 +1998,56 @@ /* Offset to next interlace block in the y direction */ static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; #endif +#ifdef PNG_WRITE_FILTER_SUPPORTED + int filters; +#endif + png_alloc_size_t buf_size; int usr_pixel_depth; png_debug(1, "in png_write_start_row"); + if (png_ptr == NULL) + return; + usr_pixel_depth = png_ptr->usr_channels * png_ptr->usr_bit_depth; buf_size = PNG_ROWBYTES(usr_pixel_depth, png_ptr->width) + 1; /* 1.5.6: added to allow checking in the row write code. */ png_ptr->transformed_pixel_depth = png_ptr->pixel_depth; png_ptr->maximum_pixel_depth = (png_byte)usr_pixel_depth; /* Set up row buffer */ - png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, buf_size); + png_ptr->row_buf = png_voidcast(png_bytep, png_malloc(png_ptr, buf_size)); png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE; #ifdef PNG_WRITE_FILTER_SUPPORTED - /* Set up filtering buffer, if using this filter */ - if (png_ptr->do_filter & PNG_FILTER_SUB) - { - png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, png_ptr->rowbytes + 1); + filters = png_ptr->do_filter; - png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; - } + if (png_ptr->height == 1) + filters &= ~(PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH); - /* We only need to keep the previous row if we are using one of these. */ - if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) - { - /* Set up previous row buffer */ - png_ptr->prev_row = (png_bytep)png_calloc(png_ptr, buf_size); + if (png_ptr->width == 1) + filters &= ~(PNG_FILTER_SUB|PNG_FILTER_AVG|PNG_FILTER_PAETH); - if (png_ptr->do_filter & PNG_FILTER_UP) - { - png_ptr->up_row = (png_bytep)png_malloc(png_ptr, - png_ptr->rowbytes + 1); + if (filters == 0) + filters = PNG_FILTER_NONE; - png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; - } + /* We only need to keep the previous row if we are using one of the following + * filters. + */ + if (filters & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) + png_ptr->prev_row = png_voidcast(png_bytep, png_calloc(png_ptr, + buf_size)); - if (png_ptr->do_filter & PNG_FILTER_AVG) - { - png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, - png_ptr->rowbytes + 1); + png_write_alloc_filter_row_buffers(png_ptr, filters); - png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; - } - - if (png_ptr->do_filter & PNG_FILTER_PAETH) - { - png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, - png_ptr->rowbytes + 1); - - png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; - } - } + png_ptr->do_filter = (png_byte)filters; /* in case it was changed above */ +#else + png_ptr->do_filter = PNG_FILTER_NONE; #endif /* PNG_WRITE_FILTER_SUPPORTED */ #ifdef PNG_WRITE_INTERLACING_SUPPORTED /* If interlaced, we need to set up width and height of pass */ diff -ru4NwbB libpng-1.6.0beta33/projects/vstudio/libpng/libpng.vcxproj libpng-1.7.0alpha01/projects/vstudio/libpng/libpng.vcxproj --- libpng-1.6.0beta33/projects/vstudio/libpng/libpng.vcxproj 2012-12-15 08:22:37.650759334 -0600 +++ libpng-1.7.0alpha01/projects/vstudio/libpng/libpng.vcxproj 2012-12-15 10:05:54.046969866 -0600 @@ -62,25 +62,25 @@ false - $(ProjectName)16 + $(ProjectName)17 false - $(ProjectName)16 + $(ProjectName)17 false - $(ProjectName)16 + $(ProjectName)17 false - $(ProjectName)16 + $(ProjectName)17 Use @@ -106,9 +106,9 @@ Windows true zlib.lib - 16 + 17 $(OutDir) @@ -163,9 +163,9 @@ true true true zlib.lib - 16 + 17 $(OutDir) diff -ru4NwbB libpng-1.6.0beta33/projects/vstudio/pngtest/pngtest.vcxproj libpng-1.7.0alpha01/projects/vstudio/pngtest/pngtest.vcxproj --- libpng-1.6.0beta33/projects/vstudio/pngtest/pngtest.vcxproj 2012-12-15 08:22:37.661580689 -0600 +++ libpng-1.7.0alpha01/projects/vstudio/pngtest/pngtest.vcxproj 2012-12-15 10:05:54.057833368 -0600 @@ -95,9 +95,9 @@ Console true - libpng16.lib + libpng17.lib $(OutDir) Executing PNG test program @@ -128,9 +128,9 @@ Console true - libpng16.lib;zlib.lib + libpng17.lib;zlib.lib $(OutDir) Executing PNG test program @@ -163,9 +163,9 @@ true true true UseLinkTimeCodeGeneration - libpng16.lib + libpng17.lib $(OutDir) Executing PNG test program @@ -198,9 +198,9 @@ Console true true true - libpng16.lib;zlib.lib + libpng17.lib;zlib.lib UseLinkTimeCodeGeneration $(OutDir) diff -ru4NwbB libpng-1.6.0beta33/projects/vstudio/pngunknown/pngunknown.vcxproj libpng-1.7.0alpha01/projects/vstudio/pngunknown/pngunknown.vcxproj --- libpng-1.6.0beta33/projects/vstudio/pngunknown/pngunknown.vcxproj 2012-12-15 08:22:37.672454427 -0600 +++ libpng-1.7.0alpha01/projects/vstudio/pngunknown/pngunknown.vcxproj 2012-12-15 10:05:54.068913777 -0600 @@ -95,9 +95,9 @@ Console true - libpng16.lib;zlib.lib + libpng17.lib;zlib.lib $(OutDir) Executing PNG validation program @@ -128,9 +128,9 @@ Console true - libpng16.lib;zlib.lib + libpng17.lib;zlib.lib $(OutDir) Executing PNG validation program @@ -162,9 +162,9 @@ Console true true true - libpng16.lib;zlib.lib + libpng17.lib;zlib.lib $(OutDir) UseLinkTimeCodeGeneration @@ -198,9 +198,9 @@ Console true true true - libpng16.lib;zlib.lib + libpng17.lib;zlib.lib $(OutDir) UseLinkTimeCodeGeneration diff -ru4NwbB libpng-1.6.0beta33/projects/vstudio/pngvalid/pngvalid.vcxproj libpng-1.7.0alpha01/projects/vstudio/pngvalid/pngvalid.vcxproj --- libpng-1.6.0beta33/projects/vstudio/pngvalid/pngvalid.vcxproj 2012-12-15 08:22:37.682948223 -0600 +++ libpng-1.7.0alpha01/projects/vstudio/pngvalid/pngvalid.vcxproj 2012-12-15 10:05:54.079960027 -0600 @@ -95,9 +95,9 @@ Console true - libpng16.lib;zlib.lib + libpng17.lib;zlib.lib $(OutDir) Executing PNG validation program @@ -128,9 +128,9 @@ Console true - libpng16.lib;zlib.lib + libpng17.lib;zlib.lib $(OutDir) Executing PNG validation program @@ -162,9 +162,9 @@ Console true true true - libpng16.lib;zlib.lib + libpng17.lib;zlib.lib $(OutDir) UseLinkTimeCodeGeneration @@ -198,9 +198,9 @@ Console true true true - libpng16.lib;zlib.lib + libpng17.lib;zlib.lib $(OutDir) UseLinkTimeCodeGeneration diff -ru4NwbB libpng-1.6.0beta33/projects/vstudio/readme.txt libpng-1.7.0alpha01/projects/vstudio/readme.txt --- libpng-1.6.0beta33/projects/vstudio/readme.txt 2012-12-15 08:22:37.631136652 -0600 +++ libpng-1.7.0alpha01/projects/vstudio/readme.txt 2012-12-15 10:05:54.026459335 -0600 @@ -39,9 +39,9 @@ problems. If you don't use the Visual Studio defaults your application must still be built with the default runtime option (/MD). If, for some reason, it is not then your -application will crash inside libpng16.dll as soon as libpng tries to read +application will crash inside libpng17.dll as soon as libpng tries to read from a file handle you pass in. If you do not want to use the DLL, for example for a very small application, the 'release library' configuration may be more appropriate. This is built diff -ru4NwbB libpng-1.6.0beta33/scripts/pnglibconf.dfa libpng-1.7.0alpha01/scripts/pnglibconf.dfa --- libpng-1.6.0beta33/scripts/pnglibconf.dfa 2012-12-15 08:22:37.557499978 -0600 +++ libpng-1.7.0alpha01/scripts/pnglibconf.dfa 2012-12-15 10:05:53.962818622 -0600 @@ -275,50 +275,42 @@ # Added at libpng-1.4.0 option IO_STATE -# This is only for PowerPC big-endian and 680x0 systems -# some testing, not enabled by default. -# NO LONGER USED - -#option READ_BIG_ENDIAN disabled - -# Allow users to control limits on what the READ code will -# read: - -# Added at libpng-1.2.43; adds limit fields to png_struct, -# allows some usages of these fields - -option USER_LIMITS - -# Added at libpng-1.2.6; adds setting APIs, allows additional -# usage of this field (UTSL) - -option SET_USER_LIMITS requires USER_LIMITS - -# Feature added at libpng-1.4.0, this flag added at 1.4.1 -option SET_USER_LIMITS enables SET_CHUNK_CACHE_LIMIT -# Feature added at libpng-1.4.1, this flag added at 1.4.1 +# Libpng limits: limit the size of images and data on read. +# +# If this option is disabled all the limit checking code will be disabled: -option SET_USER_LIMITS enables SET_CHUNK_MALLOC_LIMIT +option USER_LIMITS requires READ -# Libpng limits. -# -# If these settings are *not* set libpng will not limit the size of +# If the following settings are *not* set libpng will not limit the size of # images or the size of data in ancilliary chunks. This does lead to -# security issues if PNG files come from untrusted sources. +# security issues if PNG files come from untrusted sources. Settings have the +# following interpretations: +# +# USER_WIDTH_MAX: maximum width of an image that will be read +# USER_HEIGHT_MAX: maximum height +# USER_CHUNK_MALLOC_MAX: maximum in-memory (decompressed) size of a single chunk +# USER_CHUNK_CACHE_MAX: maximum number of chunks to be cached +# +# Only chunks that are variable in number are counted towards the +# USER_CHUNK_CACHE_MAX limit setting USER_WIDTH_MAX setting USER_HEIGHT_MAX -setting USER_CHUNK_CACHE_MAX setting USER_CHUNK_MALLOC_MAX +setting USER_CHUNK_CACHE_MAX # To default all these settings to values that are large but probably # safe turn the SAFE_LIMITS option on; this will cause the value in # pngpriv.h to be used. Individual values can also be set, simply set # them in pngusr.dfa with '@#define PNG_setting value' lines. option SAFE_LIMITS enables USER_LIMITS disabled = SAFE_LIMITS SAFE_LIMITS +# If this option is enabled APIs to set the above limits at run time are added; +# without these the hardwired (compile time) limits will be used. +option SET_USER_LIMITS requires USER_LIMITS + # All of the following options relate to code capabilities for # processing image data before creating a PNG or after reading one. # You can remove these capabilities safely and still be PNG # conformant, however the library that results is still non-standard. diff -ru4NwbB libpng-1.6.0beta33/scripts/symbols.def libpng-1.7.0alpha01/scripts/symbols.def --- libpng-1.6.0beta33/scripts/symbols.def 2012-12-15 08:22:37.579864777 -0600 +++ libpng-1.7.0alpha01/scripts/symbols.def 2012-12-15 10:05:53.985900614 -0600 @@ -27,9 +27,8 @@ png_info_init_3 @19 png_write_info_before_PLTE @20 png_write_info @21 png_read_info @22 - png_convert_to_rfc1123 @23 png_convert_from_struct_tm @24 png_convert_from_time_t @25 png_set_expand @26 png_set_expand_gray_1_2_4_to_8 @27