summaryrefslogtreecommitdiff
path: root/pngrtran.c
diff options
context:
space:
mode:
authorJohn Bowler <jbowler@acm.org>2011-06-17 21:36:09 -0500
committerGlenn Randers-Pehrson <glennrp at users.sourceforge.net>2011-06-17 21:36:09 -0500
commit484a48e22193403cfaab4e9b731955facbc5da8e (patch)
tree5ccf7da375a48a9ecaaa9f9ec6477f401192b9b6 /pngrtran.c
parentcc5226bf2a93b2216db4d64a78503f7b449ee3b1 (diff)
downloadlibpng-484a48e22193403cfaab4e9b731955facbc5da8e.tar.gz
[master] Fixed error in "ACCURATE" 16-to-8 scaling.
Diffstat (limited to 'pngrtran.c')
-rw-r--r--pngrtran.c40
1 files changed, 13 insertions, 27 deletions
diff --git a/pngrtran.c b/pngrtran.c
index 0a3874718..79a7cd6b3 100644
--- a/pngrtran.c
+++ b/pngrtran.c
@@ -1,7 +1,7 @@
/* pngrtran.c - transforms the data in a row for PNG readers
*
- * Last changed in libpng 1.4.8 [June 8, 2011]
+ * Last changed in libpng 1.4.8 [June 18, 2011]
* Copyright (c) 1998-2011 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.)
@@ -1799,32 +1799,18 @@ png_do_chop(png_row_infop row_info, png_bytep row)
for (i = 0; i<istop; i++, sp += 2, dp++)
{
#ifdef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED
- /* This does a more accurate scaling of the 16-bit color
- * value, rather than a simple low-byte truncation.
- *
- * What the ideal calculation should be:
- * *dp = (((((png_uint_32)(*sp) << 8) |
- * (png_uint_32)(*(sp + 1))) * 255 + 127)
- * / (png_uint_32)65535L;
- *
- * GRR: no, I think this is what it really should be:
- * *dp = (((((png_uint_32)(*sp) << 8) |
- * (png_uint_32)(*(sp + 1))) + 128L)
- * / (png_uint_32)257L;
- *
- * GRR: here's the exact calculation with shifts:
- * temp = (((png_uint_32)(*sp) << 8) |
- * (png_uint_32)(*(sp + 1))) + 128L;
- * *dp = (temp - (temp >> 8)) >> 8;
- *
- * Approximate calculation with shift/add instead of multiply/divide:
- * *dp = ((((png_uint_32)(*sp) << 8) |
- * (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8;
- *
- * What we actually do to avoid extra shifting and conversion:
- */
-
- *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0);
+ /* This does a more accurate scaling of the 16-bit color
+ * value, rather than a simple low-byte truncation.
+ *
+ * Prior to libpng-1.4.8 and 1.5.4, the calculation here was
+ * incorrect, so if you used ACCURATE_SCALE you will now see
+ * a slightly different result. In libpng-1.5.4 and
+ * later you will need to use the new png_set_scale_16_to_8()
+ * API to obtain accurate 16-to-8 scaling.
+ */
+ png_int_32 tmp = *sp++; /* must be signed! */
+ tmp += (((int)*sp++ - tmp + 128) * 65535) >> 24;
+ *dp++ = (png_byte)tmp;
#else
/* Simply discard the low order byte */
*dp = *sp;