[poppler] poppler/SplashOutputDev.cc

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Dec 14 22:05:36 UTC 2022


 poppler/SplashOutputDev.cc |   51 +++++++++++++++------------------------------
 1 file changed, 17 insertions(+), 34 deletions(-)

New commits:
commit eac1066f60df2442c5508fb1601fa6a331cac7a0
Author: Thomas Freitag <thomas.freitag.bbr at gmail.com>
Date:   Wed Dec 14 22:05:33 2022 +0000

    Splash: avoid problems because of implicit rounding in non-separable blend modes
    
    Splash uses unsigned char to store color pixel. But in non-separable blend modes int and in some calculations float values are used. To avoid rounding problems because of implicit rounding calculations are now done with int values and when storing int values in unsigned char variables clamp is used!

diff --git a/poppler/SplashOutputDev.cc b/poppler/SplashOutputDev.cc
index 6ba98424..7a604c88 100644
--- a/poppler/SplashOutputDev.cc
+++ b/poppler/SplashOutputDev.cc
@@ -796,51 +796,34 @@ static void splashOutBlendExclusion(SplashColorPtr src, SplashColorPtr dest, Spl
 
 static int getLum(int r, int g, int b)
 {
-    return (int)(0.3 * r + 0.59 * g + 0.11 * b);
+    // (int)(0.3 * r + 0.59 * g + 0.11 * b) =
+    // (int)(256 / 256 * 0.3 * r + 256 / 256 * 0.59 * g + 256 / 256 * 0.11 * b)
+    // (int)((77 * r + 151 * g + 28 * b) / 256)  = // round!
+    return (int)((r * 77 + g * 151 + b * 28 + 0x80) >> 8);
 }
 
 static int getSat(int r, int g, int b)
 {
-    int rgbMin, rgbMax;
+    int rgbMin = std::min({ r, g, b });
+    int rgbMax = std::max({ r, g, b });
 
-    rgbMin = rgbMax = r;
-    if (g < rgbMin) {
-        rgbMin = g;
-    } else if (g > rgbMax) {
-        rgbMax = g;
-    }
-    if (b < rgbMin) {
-        rgbMin = b;
-    } else if (b > rgbMax) {
-        rgbMax = b;
-    }
     return rgbMax - rgbMin;
 }
 
 static void clipColor(int rIn, int gIn, int bIn, unsigned char *rOut, unsigned char *gOut, unsigned char *bOut)
 {
-    int lum, rgbMin, rgbMax;
+    int lum = getLum(rIn, gIn, bIn);
+    int rgbMin = std::min({ rIn, bIn, gIn });
+    int rgbMax = std::max({ rIn, bIn, gIn });
 
-    lum = getLum(rIn, gIn, bIn);
-    rgbMin = rgbMax = rIn;
-    if (gIn < rgbMin) {
-        rgbMin = gIn;
-    } else if (gIn > rgbMax) {
-        rgbMax = gIn;
-    }
-    if (bIn < rgbMin) {
-        rgbMin = bIn;
-    } else if (bIn > rgbMax) {
-        rgbMax = bIn;
-    }
     if (rgbMin < 0) {
-        *rOut = (unsigned char)(lum + ((rIn - lum) * lum) / (lum - rgbMin));
-        *gOut = (unsigned char)(lum + ((gIn - lum) * lum) / (lum - rgbMin));
-        *bOut = (unsigned char)(lum + ((bIn - lum) * lum) / (lum - rgbMin));
+        *rOut = (unsigned char)std::clamp(lum + ((rIn - lum) * lum) / (lum - rgbMin), 0, 255);
+        *gOut = (unsigned char)std::clamp(lum + ((gIn - lum) * lum) / (lum - rgbMin), 0, 255);
+        *bOut = (unsigned char)std::clamp(lum + ((bIn - lum) * lum) / (lum - rgbMin), 0, 255);
     } else if (rgbMax > 255) {
-        *rOut = (unsigned char)(lum + ((rIn - lum) * (255 - lum)) / (rgbMax - lum));
-        *gOut = (unsigned char)(lum + ((gIn - lum) * (255 - lum)) / (rgbMax - lum));
-        *bOut = (unsigned char)(lum + ((bIn - lum) * (255 - lum)) / (rgbMax - lum));
+        *rOut = (unsigned char)std::clamp(lum + ((rIn - lum) * (255 - lum)) / (rgbMax - lum), 0, 255);
+        *gOut = (unsigned char)std::clamp(lum + ((gIn - lum) * (255 - lum)) / (rgbMax - lum), 0, 255);
+        *bOut = (unsigned char)std::clamp(lum + ((bIn - lum) * (255 - lum)) / (rgbMax - lum), 0, 255);
     } else {
         *rOut = rIn;
         *gOut = gIn;
@@ -889,8 +872,8 @@ static void setSat(unsigned char rIn, unsigned char gIn, unsigned char bIn, int
         minOut = bOut;
     }
     if (rgbMax > rgbMin) {
-        *midOut = (unsigned char)((rgbMid - rgbMin) * sat) / (rgbMax - rgbMin);
-        *maxOut = (unsigned char)sat;
+        *midOut = (unsigned char)std::clamp(((rgbMid - rgbMin) * sat) / (rgbMax - rgbMin), 0, 255);
+        *maxOut = (unsigned char)std::clamp(sat, 0, 255);
     } else {
         *midOut = *maxOut = 0;
     }


More information about the poppler mailing list