[devel] Expanded the new TAB characters.

This commit is contained in:
Glenn Randers-Pehrson 2010-07-29 17:58:49 -05:00
parent 31aee0d0c0
commit 29034c5076
8 changed files with 838 additions and 840 deletions

View File

@ -299,7 +299,6 @@ version 1.5.0beta36 [July 29, 2010]
pass. pass.
A new test program, pngvalid.c, validates the gamma code. A new test program, pngvalid.c, validates the gamma code.
Errors in the 16 bit gamma correction (overflows) have been corrected. Errors in the 16 bit gamma correction (overflows) have been corrected.
Gamma handling arithmetic is in a new file, pngarith.c
cHRM chunk testing is done consistently (previously the floating point cHRM chunk testing is done consistently (previously the floating point
API bypassed it, because the test really didn't work on FP, now the test API bypassed it, because the test really didn't work on FP, now the test
is performed on the actual values to be stored in the PNG file so it is performed on the actual values to be stored in the PNG file so it

View File

@ -2770,7 +2770,7 @@ version 1.5.0beta35 [July 24, 2010]
#ifdef blocks in pngconf.h #ifdef blocks in pngconf.h
version 1.5.0beta36 [July 29, 2010] version 1.5.0beta36 [July 29, 2010]
Patches by John Bowler: Patches by John Bowler:
Fixed point APIs are now supported throughout (no missing APIs). Fixed point APIs are now supported throughout (no missing APIs).
Internal fixed point arithmetic support exists for all internal floating Internal fixed point arithmetic support exists for all internal floating
point operations. point operations.
@ -2781,7 +2781,6 @@ version 1.5.0beta36 [July 29, 2010]
pass. pass.
A new test program, pngvalid.c, validates the gamma code. A new test program, pngvalid.c, validates the gamma code.
Errors in the 16 bit gamma correction (overflows) have been corrected. Errors in the 16 bit gamma correction (overflows) have been corrected.
Gamma handling arithmetic is in a new file, pngarith.c
cHRM chunk testing is done consistently (previously the floating point cHRM chunk testing is done consistently (previously the floating point
API bypassed it, because the test really didn't work on FP, now the test API bypassed it, because the test really didn't work on FP, now the test
is performed on the actual values to be stored in the PNG file so it is performed on the actual values to be stored in the PNG file so it

784
png.c
View File

@ -888,7 +888,6 @@ png_check_IHDR(png_structp png_ptr,
if (error == 1) if (error == 1)
png_error(png_ptr, "Invalid IHDR data"); png_error(png_ptr, "Invalid IHDR data");
} }
#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) #if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED)
/* ASCII to fp functions */ /* ASCII to fp functions */
@ -918,16 +917,16 @@ png_check_fp_number(png_charp string, png_size_t size, int *statep,
int type; int type;
/* First find the type of the next character */ /* First find the type of the next character */
{ {
char ch = string[i]; char ch = string[i];
if (ch >= 48 && ch <= 57) if (ch >= 48 && ch <= 57)
type = PNG_FP_DIGIT; type = PNG_FP_DIGIT;
else switch (ch) else switch (ch)
{ {
case 43: case 45: type = PNG_FP_SIGN; break; case 43: case 45: type = PNG_FP_SIGN; break;
case 46: type = PNG_FP_DOT; break; case 46: type = PNG_FP_DOT; break;
case 69: case 101: type = PNG_FP_E; break; case 69: case 101: type = PNG_FP_E; break;
default: goto PNG_FP_End; default: goto PNG_FP_End;
} }
} }
/* Now deal with this type according to the current /* Now deal with this type according to the current
@ -937,57 +936,57 @@ png_check_fp_number(png_charp string, png_size_t size, int *statep,
switch ((state & PNG_FP_STATE) + type) switch ((state & PNG_FP_STATE) + type)
{ {
case PNG_FP_INTEGER + PNG_FP_SIGN: case PNG_FP_INTEGER + PNG_FP_SIGN:
if (state & PNG_FP_SAW_ANY) if (state & PNG_FP_SAW_ANY)
goto PNG_FP_End; /* not a part of the number */ goto PNG_FP_End; /* not a part of the number */
png_fp_add(state, PNG_FP_SAW_SIGN); png_fp_add(state, PNG_FP_SAW_SIGN);
break; break;
case PNG_FP_INTEGER + PNG_FP_DOT: case PNG_FP_INTEGER + PNG_FP_DOT:
/* Ok as trailer, ok as lead of fraction. */ /* Ok as trailer, ok as lead of fraction. */
if (state & PNG_FP_SAW_DOT) /* two dots */ if (state & PNG_FP_SAW_DOT) /* two dots */
goto PNG_FP_End; goto PNG_FP_End;
else if (state & PNG_FP_SAW_DIGIT) /* trailing dot? */ else if (state & PNG_FP_SAW_DIGIT) /* trailing dot? */
png_fp_add(state, PNG_FP_SAW_DOT); png_fp_add(state, PNG_FP_SAW_DOT);
else else
png_fp_set(state, PNG_FP_FRACTION | PNG_FP_SAW_DOT); png_fp_set(state, PNG_FP_FRACTION | PNG_FP_SAW_DOT);
break; break;
case PNG_FP_INTEGER + PNG_FP_DIGIT: case PNG_FP_INTEGER + PNG_FP_DIGIT:
if (state & PNG_FP_SAW_DOT) /* delayed fraction */ if (state & PNG_FP_SAW_DOT) /* delayed fraction */
png_fp_set(state, PNG_FP_FRACTION | PNG_FP_SAW_DOT); png_fp_set(state, PNG_FP_FRACTION | PNG_FP_SAW_DOT);
png_fp_add(state, PNG_FP_SAW_DIGIT + PNG_FP_WAS_VALID); png_fp_add(state, PNG_FP_SAW_DIGIT + PNG_FP_WAS_VALID);
break; break;
case PNG_FP_INTEGER + PNG_FP_E: case PNG_FP_INTEGER + PNG_FP_E:
if ((state & PNG_FP_SAW_DIGIT) == 0) if ((state & PNG_FP_SAW_DIGIT) == 0)
goto PNG_FP_End; goto PNG_FP_End;
png_fp_set(state, PNG_FP_EXPONENT); png_fp_set(state, PNG_FP_EXPONENT);
break; break;
/* case PNG_FP_FRACTION + PNG_FP_SIGN: /* case PNG_FP_FRACTION + PNG_FP_SIGN:
goto PNG_FP_End; ** no sign in exponent */ goto PNG_FP_End; ** no sign in exponent */
/* case PNG_FP_FRACTION + PNG_FP_DOT: /* case PNG_FP_FRACTION + PNG_FP_DOT:
goto PNG_FP_End; ** Because SAW_DOT is always set */ goto PNG_FP_End; ** Because SAW_DOT is always set */
case PNG_FP_FRACTION + PNG_FP_DIGIT: case PNG_FP_FRACTION + PNG_FP_DIGIT:
png_fp_add(state, PNG_FP_SAW_DIGIT + PNG_FP_WAS_VALID); png_fp_add(state, PNG_FP_SAW_DIGIT + PNG_FP_WAS_VALID);
break; break;
case PNG_FP_FRACTION + PNG_FP_E: case PNG_FP_FRACTION + PNG_FP_E:
/* This is correct because the trailing '.' on an /* This is correct because the trailing '.' on an
* integer is handled above - so we can only get here * integer is handled above - so we can only get here
* with the sequence ".E" (with no preceding digits). * with the sequence ".E" (with no preceding digits).
*/ */
if ((state & PNG_FP_SAW_DIGIT) == 0) if ((state & PNG_FP_SAW_DIGIT) == 0)
goto PNG_FP_End; goto PNG_FP_End;
png_fp_set(state, PNG_FP_EXPONENT); png_fp_set(state, PNG_FP_EXPONENT);
break; break;
case PNG_FP_EXPONENT + PNG_FP_SIGN: case PNG_FP_EXPONENT + PNG_FP_SIGN:
if (state & PNG_FP_SAW_ANY) if (state & PNG_FP_SAW_ANY)
goto PNG_FP_End; /* not a part of the number */ goto PNG_FP_End; /* not a part of the number */
png_fp_add(state, PNG_FP_SAW_SIGN); png_fp_add(state, PNG_FP_SAW_SIGN);
break; break;
/* case PNG_FP_EXPONENT + PNG_FP_DOT: /* case PNG_FP_EXPONENT + PNG_FP_DOT:
goto PNG_FP_End; */ goto PNG_FP_End; */
case PNG_FP_EXPONENT + PNG_FP_DIGIT: case PNG_FP_EXPONENT + PNG_FP_DIGIT:
png_fp_add(state, PNG_FP_SAW_DIGIT + PNG_FP_WAS_VALID); png_fp_add(state, PNG_FP_SAW_DIGIT + PNG_FP_WAS_VALID);
break; break;
/* case PNG_FP_EXPONEXT + PNG_FP_E: /* case PNG_FP_EXPONEXT + PNG_FP_E:
goto PNG_FP_End; */ goto PNG_FP_End; */
default: goto PNG_FP_End; /* I.e. break 2 */ default: goto PNG_FP_End; /* I.e. break 2 */
} }
@ -1040,8 +1039,8 @@ png_pow10(int power)
do do
{ {
if (power & 1) d *= mult; if (power & 1) d *= mult;
mult *= mult; mult *= mult;
power >>= 1; power >>= 1;
} }
while (power > 0); while (power > 0);
@ -1077,258 +1076,258 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
if (fp < 0) if (fp < 0)
{ {
fp = -fp; fp = -fp;
*ascii++ = 45; /* '-' PLUS 1 TOTAL 1*/ *ascii++ = 45; /* '-' PLUS 1 TOTAL 1*/
--size; --size;
} }
if (fp >= DBL_MIN && fp <= DBL_MAX) if (fp >= DBL_MIN && fp <= DBL_MAX)
{ {
int exp; /* A base 10 exponent */ int exp; /* A base 10 exponent */
double base; /* 10^exp */ double base; /* 10^exp */
/* First extract a base 10 exponent of the number, /* First extract a base 10 exponent of the number,
* the calculation below rounds down when converting * the calculation below rounds down when converting
* from base 2 to base 10 (multiply by log10(2) - * from base 2 to base 10 (multiply by log10(2) -
* 0.3010, but 77/256 is 0.3008, so exp needs to * 0.3010, but 77/256 is 0.3008, so exp needs to
* be increased. Note that the arithmetic shift * be increased. Note that the arithmetic shift
* performs a floor() unlike C arithmetic - using a * performs a floor() unlike C arithmetic - using a
* C multiply would break the following for negative * C multiply would break the following for negative
* exponents. * exponents.
*/ */
(void)frexp(fp, &exp); /* exponent to base 2 */ (void)frexp(fp, &exp); /* exponent to base 2 */
exp = (exp * 77) >> 8; /* <= exponent to base 10 */ exp = (exp * 77) >> 8; /* <= exponent to base 10 */
/* Avoid underflow here. */ /* Avoid underflow here. */
base = png_pow10(exp); /* May underflow */ base = png_pow10(exp); /* May underflow */
while (base < DBL_MIN || base < fp) while (base < DBL_MIN || base < fp)
{ {
/* And this may overflow. */ /* And this may overflow. */
double test = png_pow10(exp+1); double test = png_pow10(exp+1);
if (test <= DBL_MAX) if (test <= DBL_MAX)
++exp, base = test; ++exp, base = test;
else else
break; break;
} }
/* Normalize fp and correct exp, after this fp is in the /* Normalize fp and correct exp, after this fp is in the
* range [.1,1) and exp is both the exponent and the digit * range [.1,1) and exp is both the exponent and the digit
* *before* which the decimal point should be inserted * *before* which the decimal point should be inserted
* (starting with 0 for the first digit). Note that this * (starting with 0 for the first digit). Note that this
* works even if 10^exp is out of range because of the * works even if 10^exp is out of range because of the
* test on DBL_MAX above. * test on DBL_MAX above.
*/ */
fp /= base; fp /= base;
while (fp >= 1) fp /= 10, ++exp; while (fp >= 1) fp /= 10, ++exp;
/* Because of the code above fp may, at this point, be /* Because of the code above fp may, at this point, be
* less than .1, this is ok because the code below can * less than .1, this is ok because the code below can
* handle the leading zeros this generates, so no attempt * handle the leading zeros this generates, so no attempt
* is made to correct that here. * is made to correct that here.
*/ */
{ {
int czero, clead, cdigits; int czero, clead, cdigits;
char exponent[10]; char exponent[10];
/* Allow up to two leading zeros - this will not lengthen /* Allow up to two leading zeros - this will not lengthen
* the number compared to using E-n. * the number compared to using E-n.
*/ */
if (exp < 0 && exp > -3) /* PLUS 3 TOTAL 4 */ if (exp < 0 && exp > -3) /* PLUS 3 TOTAL 4 */
{ {
czero = -exp; /* PLUS 2 digits: TOTAL 3 */ czero = -exp; /* PLUS 2 digits: TOTAL 3 */
exp = 0; /* Dot added below before first output. */ exp = 0; /* Dot added below before first output. */
} }
else else
czero = 0; /* No zeros to add */ czero = 0; /* No zeros to add */
/* Generate the digit list, stripping trailing zeros and /* Generate the digit list, stripping trailing zeros and
* inserting a '.' before a digit if the exponent is 0. * inserting a '.' before a digit if the exponent is 0.
*/ */
clead = czero; /* Count of leading zeros */ clead = czero; /* Count of leading zeros */
cdigits = 0; /* Count of digits in list. */ cdigits = 0; /* Count of digits in list. */
do do
{ {
double d; double d;
fp *= 10; fp *= 10;
/* Use modf here, not floor and subtract, so that /* Use modf here, not floor and subtract, so that
* the separation is done in one step. At the end * the separation is done in one step. At the end
* of the loop don't break the number into parts so * of the loop don't break the number into parts so
* that the final digit is rounded. * that the final digit is rounded.
*/ */
if (cdigits+czero-clead+1 < (int)precision) if (cdigits+czero-clead+1 < (int)precision)
fp = modf(fp, &d); fp = modf(fp, &d);
else else
{ {
/* End of loop - round the whole number. */ /* End of loop - round the whole number. */
d = floor(fp + .5); d = floor(fp + .5);
if (d > 9) if (d > 9)
{ {
/* Rounding up to 10, handle that here. */ /* Rounding up to 10, handle that here. */
if (czero > 0) if (czero > 0)
{ {
--czero, d = 1; --czero, d = 1;
if (cdigits == 0) --clead; if (cdigits == 0) --clead;
} }
else else
{ {
while (cdigits > 0 && d > 9) while (cdigits > 0 && d > 9)
{ {
int ch = *--ascii; int ch = *--ascii;
if (exp != (-1)) if (exp != (-1))
++exp; ++exp;
else if (ch == 46) else if (ch == 46)
{ {
ch = *--ascii, ++size; ch = *--ascii, ++size;
/* Advance exp to '1', so that the /* Advance exp to '1', so that the
* decimal point happens after the * decimal point happens after the
* previous digit. * previous digit.
*/ */
exp = 1; exp = 1;
} }
--cdigits; --cdigits;
d = ch - 47; /* I.e. 1+(ch-48) */ d = ch - 47; /* I.e. 1+(ch-48) */
} }
/* Did we reach the beginning? If so adjust the /* Did we reach the beginning? If so adjust the
* exponent but take into account the leading * exponent but take into account the leading
* decimal point. * decimal point.
*/ */
if (d > 9) /* cdigits == 0 */ if (d > 9) /* cdigits == 0 */
{ {
if (exp == (-1)) if (exp == (-1))
{ {
/* Leading decimal point (plus zeros?), if /* Leading decimal point (plus zeros?), if
* we lose the decimal point here it must * we lose the decimal point here it must
* be reentered below. * be reentered below.
*/ */
int ch = *--ascii; int ch = *--ascii;
if (ch == 46) if (ch == 46)
++size, exp = 1; ++size, exp = 1;
/* Else lost a leading zero, so 'exp' is /* Else lost a leading zero, so 'exp' is
* still ok at (-1) * still ok at (-1)
*/ */
} }
else else
++exp; ++exp;
/* In all cases we output a '1' */ /* In all cases we output a '1' */
d = 1; d = 1;
} }
} }
} }
fp = 0; /* Guarantees termination below. */ fp = 0; /* Guarantees termination below. */
} }
if (d == 0) if (d == 0)
{ {
++czero; ++czero;
if (cdigits == 0) ++clead; if (cdigits == 0) ++clead;
} }
else else
{ {
/* Included embedded zeros in the digit count. */ /* Included embedded zeros in the digit count. */
cdigits += czero - clead; cdigits += czero - clead;
clead = 0; clead = 0;
while (czero > 0) while (czero > 0)
{ {
/* exp == (-1) means we just output the decimal /* exp == (-1) means we just output the decimal
* place - after the DP don't adjust 'exp' any * place - after the DP don't adjust 'exp' any
* more! * more!
*/ */
if (exp != (-1)) if (exp != (-1))
{ {
if (exp == 0) *ascii++ = 46, --size; if (exp == 0) *ascii++ = 46, --size;
/* PLUS 1: TOTAL 4 */ /* PLUS 1: TOTAL 4 */
--exp; --exp;
} }
*ascii++ = 48, --czero; *ascii++ = 48, --czero;
} }
if (exp != (-1)) if (exp != (-1))
{ {
if (exp == 0) *ascii++ = 46, --size; /* counted above */ if (exp == 0) *ascii++ = 46, --size; /* counted above */
--exp; --exp;
} }
*ascii++ = 48 + (int)d, ++cdigits; *ascii++ = 48 + (int)d, ++cdigits;
} }
} }
while (cdigits+czero-clead < (int)precision && fp > DBL_MIN); while (cdigits+czero-clead < (int)precision && fp > DBL_MIN);
/* The total output count (max) is now 4+precision */ /* The total output count (max) is now 4+precision */
/* Check for an exponent, if we don't need one we are /* Check for an exponent, if we don't need one we are
* done and just need to terminate the string. At * done and just need to terminate the string. At
* this point exp==(-1) is effectively if flag - it got * this point exp==(-1) is effectively if flag - it got
* to '-1' because of the decrement after outputing * to '-1' because of the decrement after outputing
* the decimal point above (the exponent required is * the decimal point above (the exponent required is
* *not* -1!) * *not* -1!)
*/ */
if (exp >= (-1) && exp <= 2) if (exp >= (-1) && exp <= 2)
{ {
/* The following only happens if we didn't output the /* The following only happens if we didn't output the
* leading zeros above for negative exponent, so this * leading zeros above for negative exponent, so this
* doest add to the digit requirement. Note that the * doest add to the digit requirement. Note that the
* two zeros here can only be output if the two leading * two zeros here can only be output if the two leading
* zeros were *not* output, so this doesn't increase * zeros were *not* output, so this doesn't increase
* the output count. * the output count.
*/ */
while (--exp >= 0) *ascii++ = 48; while (--exp >= 0) *ascii++ = 48;
*ascii = 0; *ascii = 0;
/* Total buffer requirement (including the '\0') is /* Total buffer requirement (including the '\0') is
* 5+precision - see check at the start. * 5+precision - see check at the start.
*/ */
return; return;
} }
/* Here if an exponent is required, adjust size for /* Here if an exponent is required, adjust size for
* the digits we output but did not count. The total * the digits we output but did not count. The total
* digit output here so far is at most 1+precision - no * digit output here so far is at most 1+precision - no
* decimal point and no leading or trailing zeros have * decimal point and no leading or trailing zeros have
* been output. * been output.
*/ */
size -= cdigits; size -= cdigits;
*ascii++ = 69, --size; /* 'E': PLUS 1 TOTAL 2+precision*/ *ascii++ = 69, --size; /* 'E': PLUS 1 TOTAL 2+precision*/
if (exp < 0) if (exp < 0)
{ {
*ascii++ = 45, --size; /* '-': PLUS 1 TOTAL 3+precision */ *ascii++ = 45, --size; /* '-': PLUS 1 TOTAL 3+precision */
exp = -exp; exp = -exp;
} }
cdigits = 0; cdigits = 0;
while (exp > 0) while (exp > 0)
{ {
exponent[cdigits++] = 48 + exp % 10; exponent[cdigits++] = 48 + exp % 10;
exp /= 10; exp /= 10;
} }
/* Need another size check here for the exponent digits, so /* Need another size check here for the exponent digits, so
* this need not be considered above. * this need not be considered above.
*/ */
if ((int)size > cdigits) if ((int)size > cdigits)
{ {
while (cdigits > 0) *ascii++ = exponent[--cdigits]; while (cdigits > 0) *ascii++ = exponent[--cdigits];
*ascii = 0; *ascii = 0;
return; return;
} }
} }
} }
else if (!(fp >= DBL_MIN)) else if (!(fp >= DBL_MIN))
{ {
*ascii++ = 48; /* '0' */ *ascii++ = 48; /* '0' */
*ascii = 0; *ascii = 0;
return; return;
} }
else else
{ {
*ascii++ = 105; /* 'i' */ *ascii++ = 105; /* 'i' */
*ascii++ = 110; /* 'n' */ *ascii++ = 110; /* 'n' */
*ascii++ = 102; /* 'f' */ *ascii++ = 102; /* 'f' */
*ascii = 0; *ascii = 0;
return; return;
} }
} }
@ -1369,82 +1368,82 @@ png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times,
{ {
if (a == 0 || times == 0) if (a == 0 || times == 0)
{ {
*res = 0; *res = 0;
return 1; return 1;
} }
else else
{ {
#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED #ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
double r = a; double r = a;
r *= times; r *= times;
r /= div; r /= div;
r = floor(r+.5); r = floor(r+.5);
/* A png_fixed_point is a 32 bit integer. */ /* A png_fixed_point is a 32 bit integer. */
if (r <= 2147483647. && r >= -2147483648.) if (r <= 2147483647. && r >= -2147483648.)
{ {
*res = (png_fixed_point)r; *res = (png_fixed_point)r;
return 1; return 1;
} }
#else #else
int negative = 0; int negative = 0;
png_uint_32 A, T, D; png_uint_32 A, T, D;
if (a < 0) negative = 1, A = -a; else A = a; if (a < 0) negative = 1, A = -a; else A = a;
if (times < 0) negative = !negative, T = -times; else T = times; if (times < 0) negative = !negative, T = -times; else T = times;
if (div < 0) negative = !negative, D = -div; else D = div; if (div < 0) negative = !negative, D = -div; else D = div;
/* Following can't overflow because the arguments only /* Following can't overflow because the arguments only
* have 31 bits each, however the result may be 32 bits. * have 31 bits each, however the result may be 32 bits.
*/ */
png_uint_32 s16 = (A >> 16) * (T & 0xffff) + png_uint_32 s16 = (A >> 16) * (T & 0xffff) +
(A & 0xffff) * (T >> 16); (A & 0xffff) * (T >> 16);
/* Can't overflow because the a*times bit is only 30 /* Can't overflow because the a*times bit is only 30
* bits at most. * bits at most.
*/ */
png_uint_32 s32 = (A >> 16) * (T >> 16) + (s16 >> 16); png_uint_32 s32 = (A >> 16) * (T >> 16) + (s16 >> 16);
png_uint_32 s00 = (A & 0xffff) * (T & 0xffff); png_uint_32 s00 = (A & 0xffff) * (T & 0xffff);
s16 = (s16 & 0xffff) << 16; s16 = (s16 & 0xffff) << 16;
s00 += s16; s00 += s16;
if (s00 < s16) ++s32; /* carry */ if (s00 < s16) ++s32; /* carry */
if (s32 < D) /* else overflow */ if (s32 < D) /* else overflow */
{ {
/* s32.s00 is now the 64 bit product, do a standard /* s32.s00 is now the 64 bit product, do a standard
* division, we know that s32 < D, so the maximum * division, we know that s32 < D, so the maximum
* required shift is 31. * required shift is 31.
*/ */
int bitshift = 32; int bitshift = 32;
png_fixed_point result = 0; /* NOTE: signed */ png_fixed_point result = 0; /* NOTE: signed */
while (--bitshift >= 0) while (--bitshift >= 0)
{ {
png_uint_32 d32, d00; png_uint_32 d32, d00;
if (bitshift > 0) if (bitshift > 0)
d32 = D >> (32-bitshift), d00 = D << bitshift; d32 = D >> (32-bitshift), d00 = D << bitshift;
else else
d32 = 0, d00 = D; d32 = 0, d00 = D;
if (s32 > d32) if (s32 > d32)
{ {
if (s00 < d00) --s32; /* carry */ if (s00 < d00) --s32; /* carry */
s32 -= d32, s00 -= d00, result += 1<<bitshift; s32 -= d32, s00 -= d00, result += 1<<bitshift;
} }
else if (s32 == d32 && s00 >= d00) else if (s32 == d32 && s00 >= d00)
s32 = 0, s00 -= d00, result += 1<<bitshift; s32 = 0, s00 -= d00, result += 1<<bitshift;
} }
/* Handle the rounding. */ /* Handle the rounding. */
if (s00 >= (D >> 1)) ++result; if (s00 >= (D >> 1)) ++result;
if (negative) result = -result; if (negative) result = -result;
/* Check for overflow. */ /* Check for overflow. */
if (negative && result <= 0 || !negative && result >= 0) if (negative && result <= 0 || !negative && result >= 0)
{ {
*res = result; *res = result;
return 1; return 1;
} }
} }
#endif #endif
} }
} }
@ -1837,12 +1836,12 @@ png_gamma_8bit_correct(unsigned value, png_fixed_point gamma)
if (value > 0 && value < 255) if (value > 0 && value < 255)
{ {
# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED # ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
return (png_byte)floor(255*pow(value/255.,gamma*.00001)+.5); return (png_byte)floor(255*pow(value/255.,gamma*.00001)+.5);
# else # else
png_uint_32 log = png_log8bit(value); png_uint_32 log = png_log8bit(value);
png_fixed_point res; png_fixed_point res;
if (png_muldiv(&res, gamma, log, PNG_FP_1)) if (png_muldiv(&res, gamma, log, PNG_FP_1))
return png_exp8bit(res); return png_exp8bit(res);
# endif # endif
/* Overflow. */ /* Overflow. */
@ -1858,12 +1857,12 @@ png_gamma_16bit_correct(unsigned value, png_fixed_point gamma)
if (value > 0 && value < 65535) if (value > 0 && value < 65535)
{ {
# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED # ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
return (png_uint_16)floor(65535*pow(value/65535.,gamma*.00001)+.5); return (png_uint_16)floor(65535*pow(value/65535.,gamma*.00001)+.5);
# else # else
png_uint_32 log = png_log16bit(value); png_uint_32 log = png_log16bit(value);
png_fixed_point res; png_fixed_point res;
if (png_muldiv(&res, gamma, log, PNG_FP_1)) if (png_muldiv(&res, gamma, log, PNG_FP_1))
return png_exp16bit(res); return png_exp16bit(res);
# endif # endif
/* Overflow. */ /* Overflow. */
@ -1928,40 +1927,40 @@ png_build_16bit_table(png_structp png_ptr, png_uint_16pp *ptable,
*/ */
if (png_gamma_significant(gamma)) if (png_gamma_significant(gamma))
{ {
/* The old code would overflow at the end and this would cause the /* The old code would overflow at the end and this would cause the
* 'pow' function to return a result >1, resulting in an * 'pow' function to return a result >1, resulting in an
* arithmetic error. This code follows the spec exactly; ig is * arithmetic error. This code follows the spec exactly; ig is
* the recovered input sample, it always has 8-16 bits. * the recovered input sample, it always has 8-16 bits.
* *
* We want input * 65535/max, rounded, the arithmetic fits in 32 * We want input * 65535/max, rounded, the arithmetic fits in 32
* bits (unsigned) so long as max <= 32767. * bits (unsigned) so long as max <= 32767.
*/ */
unsigned j; unsigned j;
for (j = 0; j < 256; j++) for (j = 0; j < 256; j++)
{ {
png_uint_16 ig = (j << (8-shift)) + i; png_uint_16 ig = (j << (8-shift)) + i;
# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED # ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
/* Inline the 'max' scaling operation: */ /* Inline the 'max' scaling operation: */
sub_table[j] = (png_uint_16)floor(65535*pow(ig/(double)max, sub_table[j] = (png_uint_16)floor(65535*pow(ig/(double)max,
gamma*.00001)+.5); gamma*.00001)+.5);
# else # else
if (shift) if (shift)
ig = (ig * 65535U + max_by_2)/max; ig = (ig * 65535U + max_by_2)/max;
sub_table[j] = png_gamma_16bit_correct(ig, gamma); sub_table[j] = png_gamma_16bit_correct(ig, gamma);
# endif # endif
} }
} }
else else
{ {
/* We must still build a table, but do it the fast way. */ /* We must still build a table, but do it the fast way. */
unsigned j; unsigned j;
for (j = 0; j < 256; j++) for (j = 0; j < 256; j++)
{ {
png_uint_32 ig = (j << (8-shift)) + i; png_uint_32 ig = (j << (8-shift)) + i;
if (shift) if (shift)
ig = (ig * 65535U + max_by_2)/max; ig = (ig * 65535U + max_by_2)/max;
sub_table[j] = ig; sub_table[j] = ig;
} }
} }
} }
} }
@ -2017,8 +2016,8 @@ png_build_16to8_table(png_structp png_ptr, png_uint_16pp *ptable,
while (last <= bound) while (last <= bound)
{ {
table[last & (0xffU >> shift)][last >> (8U - shift)] = out; table[last & (0xffU >> shift)][last >> (8U - shift)] = out;
last++; last++;
} }
} }
@ -2061,18 +2060,18 @@ png_build_gamma_table(png_structp png_ptr, png_byte bit_depth)
{ {
png_build_8bit_table(png_ptr, &png_ptr->gamma_table, png_build_8bit_table(png_ptr, &png_ptr->gamma_table,
png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->gamma, png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->gamma,
png_ptr->screen_gamma) : PNG_FP_1); png_ptr->screen_gamma) : PNG_FP_1);
#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY)) if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY))
{ {
png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1, png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1,
png_reciprocal(png_ptr->gamma)); png_reciprocal(png_ptr->gamma));
png_build_8bit_table(png_ptr, &png_ptr->gamma_from_1, png_build_8bit_table(png_ptr, &png_ptr->gamma_from_1,
png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) : png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) :
png_ptr->gamma/* Probably doing rgb_to_gray */); png_ptr->gamma/* Probably doing rgb_to_gray */);
} }
#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */ #endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
} }
@ -2118,10 +2117,10 @@ png_build_gamma_table(png_structp png_ptr, png_byte bit_depth)
if (png_ptr->transformations & PNG_16_TO_8) if (png_ptr->transformations & PNG_16_TO_8)
{ {
/* PNG_MAX_GAMMA_8 is the number of bits to keep - effectively /* PNG_MAX_GAMMA_8 is the number of bits to keep - effectively
* the significant bits in the *input* when the output will * the significant bits in the *input* when the output will
* eventually be 8 bits. By default it is 11. * eventually be 8 bits. By default it is 11.
*/ */
if (shift < (16U - PNG_MAX_GAMMA_8)) if (shift < (16U - PNG_MAX_GAMMA_8))
shift = (16U - PNG_MAX_GAMMA_8); shift = (16U - PNG_MAX_GAMMA_8);
} }
@ -2132,25 +2131,25 @@ png_build_gamma_table(png_structp png_ptr, png_byte bit_depth)
png_ptr->gamma_shift = shift; png_ptr->gamma_shift = shift;
if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND)) if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND))
png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift, png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift,
png_ptr->screen_gamma > 0 ? png_product2(png_ptr->gamma, png_ptr->screen_gamma > 0 ? png_product2(png_ptr->gamma,
png_ptr->screen_gamma) : PNG_FP_1); png_ptr->screen_gamma) : PNG_FP_1);
else else
png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift, png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift,
png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->gamma, png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->gamma,
png_ptr->screen_gamma) : PNG_FP_1); png_ptr->screen_gamma) : PNG_FP_1);
#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY)) if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY))
{ {
png_build_16bit_table(png_ptr, &png_ptr->gamma_16_to_1, shift, png_build_16bit_table(png_ptr, &png_ptr->gamma_16_to_1, shift,
png_reciprocal(png_ptr->gamma)); png_reciprocal(png_ptr->gamma));
/* Notice that the '16 from 1' table should be full precision, however /* Notice that the '16 from 1' table should be full precision, however
* the lookup on this table still uses gamma_shift, os it can't be. * the lookup on this table still uses gamma_shift, os it can't be.
* TODO: fix this. * TODO: fix this.
*/ */
png_build_16bit_table(png_ptr, &png_ptr->gamma_16_from_1, shift, 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->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) :
png_ptr->gamma/* Probably doing rgb_to_gray */); png_ptr->gamma/* Probably doing rgb_to_gray */);
@ -2159,3 +2158,4 @@ png_build_gamma_table(png_structp png_ptr, png_byte bit_depth)
} }
} }
#endif /* READ_GAMMA */ #endif /* READ_GAMMA */
#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */

View File

@ -866,14 +866,14 @@ png_read_image(png_structp png_ptr, png_bytepp image)
{ {
if (!(png_ptr->transformations & PNG_INTERLACE)) if (!(png_ptr->transformations & PNG_INTERLACE))
{ {
/* Caller called png_start_read_image or png_read_update_info without /* Caller called png_start_read_image or png_read_update_info without
* first turning on the PNG_INTERLACE transform. We can fix this here, * first turning on the PNG_INTERLACE transform. We can fix this here,
* but the caller should do it! * but the caller should do it!
*/ */
png_warning(png_ptr, "Interlace handling should be turned on when " png_warning(png_ptr, "Interlace handling should be turned on when "
"using png_read_image"); "using png_read_image");
/* Make sure this is set correctly */ /* Make sure this is set correctly */
png_ptr->num_rows = png_ptr->height; png_ptr->num_rows = png_ptr->height;
} }
/* Obtain the pass number, which also turns on the PNG_INTERLACE flag in /* Obtain the pass number, which also turns on the PNG_INTERLACE flag in

View File

@ -917,7 +917,7 @@ png_init_read_transformations(png_structp png_ptr)
istop=(int)png_ptr->num_trans; istop=(int)png_ptr->num_trans;
for (i=0; i<istop; i++) for (i=0; i<istop; i++)
png_ptr->trans_alpha[i] = (png_byte)(255 - png_ptr->trans_alpha[i] = (png_byte)(255 -
png_ptr->trans_alpha[i]); png_ptr->trans_alpha[i]);
} }
} }
#endif #endif
@ -985,21 +985,21 @@ png_init_read_transformations(png_structp png_ptr)
case PNG_BACKGROUND_GAMMA_FILE: case PNG_BACKGROUND_GAMMA_FILE:
g = png_reciprocal(png_ptr->gamma); g = png_reciprocal(png_ptr->gamma);
gs = png_reciprocal2(png_ptr->gamma, gs = png_reciprocal2(png_ptr->gamma,
png_ptr->screen_gamma); png_ptr->screen_gamma);
break; break;
case PNG_BACKGROUND_GAMMA_UNIQUE: case PNG_BACKGROUND_GAMMA_UNIQUE:
g = png_reciprocal(png_ptr->background_gamma); g = png_reciprocal(png_ptr->background_gamma);
gs = png_reciprocal2(png_ptr->background_gamma, gs = png_reciprocal2(png_ptr->background_gamma,
png_ptr->screen_gamma); png_ptr->screen_gamma);
break; break;
default: default:
g = PNG_FP_1; /* back_1 */ g = PNG_FP_1; /* back_1 */
gs = PNG_FP_1; /* back */ gs = PNG_FP_1; /* back */
break; break;
} }
if ( png_gamma_significant(gs) ) if ( png_gamma_significant(gs) )
{ {
back.red = (png_byte)png_ptr->background.red; back.red = (png_byte)png_ptr->background.red;
back.green = (png_byte)png_ptr->background.green; back.green = (png_byte)png_ptr->background.green;
@ -1067,8 +1067,8 @@ png_init_read_transformations(png_structp png_ptr)
else else
/* color_type != PNG_COLOR_TYPE_PALETTE */ /* color_type != PNG_COLOR_TYPE_PALETTE */
{ {
png_fixed_point g = PNG_FP_1; png_fixed_point g = PNG_FP_1;
png_fixed_point gs = PNG_FP_1; png_fixed_point gs = PNG_FP_1;
switch (png_ptr->background_gamma_type) switch (png_ptr->background_gamma_type)
{ {
@ -1085,12 +1085,12 @@ png_init_read_transformations(png_structp png_ptr)
case PNG_BACKGROUND_GAMMA_UNIQUE: case PNG_BACKGROUND_GAMMA_UNIQUE:
g = png_reciprocal(png_ptr->background_gamma); g = png_reciprocal(png_ptr->background_gamma);
gs = png_reciprocal2(png_ptr->background_gamma, gs = png_reciprocal2(png_ptr->background_gamma,
png_ptr->screen_gamma); png_ptr->screen_gamma);
break; break;
} }
png_ptr->background_1.gray = png_gamma_correct(png_ptr, png_ptr->background_1.gray = png_gamma_correct(png_ptr,
png_ptr->background.gray, g); png_ptr->background.gray, g);
png_ptr->background.gray = png_gamma_correct(png_ptr, png_ptr->background.gray = png_gamma_correct(png_ptr,
png_ptr->background.gray, gs); png_ptr->background.gray, gs);

View File

@ -992,10 +992,10 @@ png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
{ {
if (PNG_OUT_OF_RANGE(info_ptr->gamma, 45500L, 500)) if (PNG_OUT_OF_RANGE(info_ptr->gamma, 45500L, 500))
{ {
png_warning(png_ptr, png_warning(png_ptr,
"Ignoring incorrect gAMA value when sRGB is also present"); "Ignoring incorrect gAMA value when sRGB is also present");
#ifdef PNG_CONSOLE_IO_SUPPORTED #ifdef PNG_CONSOLE_IO_SUPPORTED
fprintf(stderr, "incorrect gamma=(%d/100000)\n", info_ptr->gamma); fprintf(stderr, "incorrect gamma=(%d/100000)\n", info_ptr->gamma);
#endif #endif
} }
} }
@ -1889,12 +1889,12 @@ png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_size_t heighti = index; png_size_t heighti = index;
if (png_ptr->chunkdata[index] == 45 /* negative height */ || if (png_ptr->chunkdata[index] == 45 /* negative height */ ||
!png_check_fp_number(png_ptr->chunkdata, slength, &state, &index) || !png_check_fp_number(png_ptr->chunkdata, slength, &state, &index) ||
index != slength) index != slength)
png_warning(png_ptr, "Invalid sCAL chunk ignored: bad height format"); png_warning(png_ptr, "Invalid sCAL chunk ignored: bad height format");
else else
/* This is the (only) success case. */ /* This is the (only) success case. */
png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0],
png_ptr->chunkdata+1, png_ptr->chunkdata+heighti); png_ptr->chunkdata+1, png_ptr->chunkdata+heighti);
} }
/* Clean up - just free the temporarily allocated buffer. */ /* Clean up - just free the temporarily allocated buffer. */
@ -3476,10 +3476,10 @@ png_get_num_rows(png_structp png_ptr)
if (png_ptr != NULL) if (png_ptr != NULL)
{ {
if (png_ptr->flags & PNG_FLAG_ROW_INIT) if (png_ptr->flags & PNG_FLAG_ROW_INIT)
return png_ptr->num_rows; return png_ptr->num_rows;
else else
png_error(png_ptr, "Call png_start_read_image or png_read_update_info " png_error(png_ptr, "Call png_start_read_image or png_read_update_info "
"before png_get_num_rows"); "before png_get_num_rows");
} }
/* Here on error */ /* Here on error */

File diff suppressed because it is too large Load Diff

View File

@ -148,7 +148,7 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
int j; int j;
for (j = 0; j<(int)info_ptr->num_trans; j++) for (j = 0; j<(int)info_ptr->num_trans; j++)
info_ptr->trans_alpha[j] = info_ptr->trans_alpha[j] =
(png_byte)(255 - info_ptr->trans_alpha[j]); (png_byte)(255 - info_ptr->trans_alpha[j]);
} }
#endif #endif
png_write_tRNS(png_ptr, info_ptr->trans_alpha, &(info_ptr->trans_color), png_write_tRNS(png_ptr, info_ptr->trans_alpha, &(info_ptr->trans_color),