diff options
author | Robin Watts <Robin.Watts@artifex.com> | 2020-02-26 13:03:56 +0000 |
---|---|---|
committer | Chris Liddell <chris.liddell@artifex.com> | 2020-02-27 15:31:11 +0000 |
commit | 3cb8b3a403450d617b2b96ec0349bb99ce0d8379 (patch) | |
tree | ff6112c03306c08d56ffe293ea19b5d192bfbd63 | |
parent | 5d4305e916d3f75492d03dfd79ab1aaedf9545e3 (diff) | |
download | ghostpdl-3cb8b3a403450d617b2b96ec0349bb99ce0d8379.tar.gz |
Fix the overflow case in 16 bit saturation blending.
As seen with the second apple of the bottom row of page 1
of:
gs -sDEVICE=psdcmyk16 -r72 -o out%d.psd -dMaxBitmap=2000M
../tests_private/pdf/PDF_1.7_ATS/AIX4G1C3.pdf
-rw-r--r-- | base/gxblend.c | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/base/gxblend.c b/base/gxblend.c index 642a851d3..859a006c0 100644 --- a/base/gxblend.c +++ b/base/gxblend.c @@ -745,7 +745,7 @@ art_blend_saturation_rgb_16(int n_chan, uint16_t *gs_restrict dst, const uint16_ int mins, maxs; int y; int64_t scale; - int r, g, b; + int64_t r, g, b; minb = rb < gb ? rb : gb; minb = minb < bb ? minb : bb; @@ -764,15 +764,19 @@ art_blend_saturation_rgb_16(int n_chan, uint16_t *gs_restrict dst, const uint16_ maxs = rs > gs ? rs : gs; maxs = maxs > bs ? maxs : bs; + /* -65535 <= maxs - mins <= 65535 i.e. 17 bits */ + /* -65535 <= maxb - minb <= 65535 i.e. 17 bits */ + /* worst case, maxb - minb == +/- 1, so scale would be 33 bits. */ scale = (((int64_t)(maxs - mins)) << 16) / (maxb - minb); + /* 0 <= y <= 65535 */ y = (rb * 77 + gb * 151 + bb * 28 + 0x80) >> 8; r = y + ((((rb - y) * scale) + 0x8000) >> 16); g = y + ((((gb - y) * scale) + 0x8000) >> 16); b = y + ((((bb - y) * scale) + 0x8000) >> 16); - if ((r | g | b) & 0x10000) { + if ((r | g | b) & (int64_t)~0xffff) { int64_t scalemin, scalemax; - int min, max; + int64_t min, max; min = r < g ? r : g; min = min < b ? min : b; @@ -780,7 +784,7 @@ art_blend_saturation_rgb_16(int n_chan, uint16_t *gs_restrict dst, const uint16_ max = max > b ? max : b; if (min < 0) - scalemin = ((int64_t)(y << 16)) / (y - min); + scalemin = (((int64_t)y) << 16) / (y - min); else scalemin = 0x10000; |