[poppler] poppler/PSOutputDev.cc

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Sat Nov 30 19:34:38 UTC 2019


 poppler/PSOutputDev.cc |  181 +++++++++++++++++++++++++++++++++++--------------
 1 file changed, 132 insertions(+), 49 deletions(-)

New commits:
commit 8d46550c4ff3d4a1923cfc4c42e3fd4d154a7624
Author: William Bader <williambader at hotmail.com>
Date:   Fri Nov 29 01:55:29 2019 -0500

    Improve pdftops -optimizecolorspace by implementing the CMYK to K conversion in more places.
    This fixes the conversion of the PDF in poppler/poppler#833

diff --git a/poppler/PSOutputDev.cc b/poppler/PSOutputDev.cc
index a7c86f8f..511a6ebb 100644
--- a/poppler/PSOutputDev.cc
+++ b/poppler/PSOutputDev.cc
@@ -23,7 +23,7 @@
 // Copyright (C) 2009-2013 Thomas Freitag <Thomas.Freitag at alfa.de>
 // Copyright (C) 2009 Till Kamppeter <till.kamppeter at gmail.com>
 // Copyright (C) 2009 Carlos Garcia Campos <carlosgc at gnome.org>
-// Copyright (C) 2009, 2011, 2012, 2014-2017 William Bader <williambader at hotmail.com>
+// Copyright (C) 2009, 2011, 2012, 2014-2017, 2019 William Bader <williambader at hotmail.com>
 // Copyright (C) 2009 Kovid Goyal <kovid at kovidgoyal.net>
 // Copyright (C) 2009-2011, 2013-2015, 2017 Adrian Johnson <ajohnson at redneon.com>
 // Copyright (C) 2012, 2014 Fabio D'Urso <fabiodurso at hotmail.it>
@@ -4105,6 +4105,16 @@ void PSOutputDev::updateFillColor(GfxState *state) {
       m = colToDbl(cmyk.m);
       y = colToDbl(cmyk.y);
       k = colToDbl(cmyk.k);
+      if (getOptimizeColorSpace()) {
+	double g;
+	g = 0.299*c + 0.587*m + 0.114*y;
+	if ((fabs(m - c) < 0.01 && fabs(m - y) < 0.01) ||
+	    (fabs(m - c) < 0.2 && fabs(m - y) < 0.2 && k + g > 1.5)) {
+	  c = m = y = 0.0;
+	  k += g;
+	  if (k > 1.0) k = 1.0;
+	}
+      }
       writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} k\n", c, m, y, k);
       addProcessColor(c, m, y, k);
     }
@@ -4162,6 +4172,16 @@ void PSOutputDev::updateStrokeColor(GfxState *state) {
       m = colToDbl(cmyk.m);
       y = colToDbl(cmyk.y);
       k = colToDbl(cmyk.k);
+      if (getOptimizeColorSpace()) {
+	double g;
+	g = 0.299*c + 0.587*m + 0.114*y;
+	if ((fabs(m - c) < 0.01 && fabs(m - y) < 0.01) ||
+	    (fabs(m - c) < 0.2 && fabs(m - y) < 0.2 && k + g > 1.5)) {
+	  c = m = y = 0.0;
+	  k += g;
+	  if (k > 1.0) k = 1.0;
+	}
+      }
       writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} K\n", c, m, y, k);
       addProcessColor(c, m, y, k);
     }
@@ -5479,79 +5499,142 @@ void PSOutputDev::doImageL1Sep(Object *ref, GfxImageColorMap *colorMap,
   bool checkProcessColor;
   char hexBuf[32*2 + 2];	// 32 values X 2 chars/value + line ending + null
   unsigned char digit;
+  bool isGray;
 
   // explicit masking
   if (maskStr && !(maskColors && colorMap)) {
     maskToClippingPath(maskStr, maskWidth, maskHeight, maskInvert);
   }
 
-  // width, height, matrix, bits per component
-  writePSFmt("{0:d} {1:d} 8 [{2:d} 0 0 {3:d} 0 {4:d}] pdfIm1Sep{5:s}\n",
-	     width, height,
-	     width, -height, height,
-	     useBinary ? "Bin" : "");
-
   // allocate a line buffer
   lineBuf = (unsigned char *)gmallocn(width, 4);
 
+  // scan for all gray
+  if (getOptimizeColorSpace()) {
+    ImageStream *imgCheckStr;
+    imgCheckStr = new ImageStream(str, width, colorMap->getNumPixelComps(),
+			   colorMap->getBits());
+    imgCheckStr->reset();
+    isGray = true;
+    for (y = 0; y < height; ++y) {
+      for (x = 0; x < width; ++x) {
+	imgCheckStr->getPixel(pixBuf);
+	colorMap->getCMYK(pixBuf, &cmyk);
+	if (colToByte(cmyk.c) != colToByte(cmyk.m) || colToByte(cmyk.c) != colToByte(cmyk.y)) {
+	  isGray = false;
+	  y = height; // end outer loop
+	  break;
+	}
+      }
+    }
+    imgCheckStr->close();
+    delete imgCheckStr;
+  } else {
+    isGray = false;
+  }
+
   // set up to process the data stream
   imgStr = new ImageStream(str, width, colorMap->getNumPixelComps(),
 			   colorMap->getBits());
   imgStr->reset();
 
+  // width, height, matrix, bits per component
+  writePSFmt("{0:d} {1:d} 8 [{2:d} 0 0 {3:d} 0 {4:d}] pdfIm1{5:s}{6:s}\n",
+	     width, height,
+	     width, -height, height,
+	     isGray ? "" : "Sep",
+	     useBinary ? "Bin" : "");
+
   // process the data stream
   checkProcessColor = true;
   i = 0;
-  for (y = 0; y < height; ++y) {
 
-    // read the line
-    if (checkProcessColor) {
-      checkProcessColor = (((psProcessCyan | psProcessMagenta | psProcessYellow | psProcessBlack) & ~processColors) != 0);
-    }
-    if (checkProcessColor) {
-      for (x = 0; x < width; ++x) {
-        imgStr->getPixel(pixBuf);
-        colorMap->getCMYK(pixBuf, &cmyk);
-        lineBuf[4*x+0] = colToByte(cmyk.c);
-        lineBuf[4*x+1] = colToByte(cmyk.m);
-        lineBuf[4*x+2] = colToByte(cmyk.y);
-        lineBuf[4*x+3] = colToByte(cmyk.k);
-        addProcessColor(colToDbl(cmyk.c), colToDbl(cmyk.m),
-		        colToDbl(cmyk.y), colToDbl(cmyk.k));
+  if (isGray) {
+    int g;
+    for (y = 0; y < height; ++y) {
+
+      // read the line
+      if (checkProcessColor) {
+	checkProcessColor = ((psProcessBlack & processColors) == 0);
       }
-    } else {
       for (x = 0; x < width; ++x) {
-        imgStr->getPixel(pixBuf);
-        colorMap->getCMYK(pixBuf, &cmyk);
-        lineBuf[4*x+0] = colToByte(cmyk.c);
-        lineBuf[4*x+1] = colToByte(cmyk.m);
-        lineBuf[4*x+2] = colToByte(cmyk.y);
-        lineBuf[4*x+3] = colToByte(cmyk.k);
+	imgStr->getPixel(pixBuf);
+	colorMap->getCMYK(pixBuf, &cmyk);
+	g = colToByte(cmyk.c) + colToByte(cmyk.k);
+	if (checkProcessColor && g > 0) {
+	  processColors |= psProcessBlack;
+	}
+	g = 255 - g;
+	if (g < 0) g = 0;
+	if (useBinary) {
+	  hexBuf[i++] = g;
+	} else {
+	  digit = g / 16;
+	  hexBuf[i++] = digit + ((digit >= 10)? 'a'-10: '0');
+	  digit = g % 16;
+	  hexBuf[i++] = digit + ((digit >= 10)? 'a'-10: '0');
+	}
+	if (i >= 64) {
+	  if (!useBinary) {
+	    hexBuf[i++] = '\n';
+	  }
+	  writePSBuf(hexBuf, i);
+	  i = 0;
+	}
       }
     }
+  } else {
+    for (y = 0; y < height; ++y) {
 
-    // write one line of each color component
-    if (useBinary) {
-      for (comp = 0; comp < 4; ++comp) {
-        for (x = 0; x < width; ++x) {
-	  hexBuf[i++] = lineBuf[4*x + comp];
-	  if (i >= 64) {
-	    writePSBuf(hexBuf, i);
-	    i = 0;
-	  }
-	}
+      // read the line
+      if (checkProcessColor) {
+        checkProcessColor = (((psProcessCyan | psProcessMagenta | psProcessYellow | psProcessBlack) & ~processColors) != 0);
       }
-    } else {
-      for (comp = 0; comp < 4; ++comp) {
+      if (checkProcessColor) {
         for (x = 0; x < width; ++x) {
-	  digit = lineBuf[4*x + comp] / 16;
-	  hexBuf[i++] = digit + ((digit >= 10)? 'a'-10: '0');
-	  digit = lineBuf[4*x + comp] % 16;
-	  hexBuf[i++] = digit + ((digit >= 10)? 'a'-10: '0');
-	  if (i >= 64) {
-	    hexBuf[i++] = '\n';
-	    writePSBuf(hexBuf, i);
-	    i = 0;
+          imgStr->getPixel(pixBuf);
+          colorMap->getCMYK(pixBuf, &cmyk);
+          lineBuf[4*x+0] = colToByte(cmyk.c);
+          lineBuf[4*x+1] = colToByte(cmyk.m);
+          lineBuf[4*x+2] = colToByte(cmyk.y);
+          lineBuf[4*x+3] = colToByte(cmyk.k);
+          addProcessColor(colToDbl(cmyk.c), colToDbl(cmyk.m),
+		          colToDbl(cmyk.y), colToDbl(cmyk.k));
+        }
+      } else {
+        for (x = 0; x < width; ++x) {
+          imgStr->getPixel(pixBuf);
+          colorMap->getCMYK(pixBuf, &cmyk);
+          lineBuf[4*x+0] = colToByte(cmyk.c);
+          lineBuf[4*x+1] = colToByte(cmyk.m);
+          lineBuf[4*x+2] = colToByte(cmyk.y);
+          lineBuf[4*x+3] = colToByte(cmyk.k);
+        }
+      }
+
+      // write one line of each color component
+      if (useBinary) {
+        for (comp = 0; comp < 4; ++comp) {
+          for (x = 0; x < width; ++x) {
+	    hexBuf[i++] = lineBuf[4*x + comp];
+	    if (i >= 64) {
+	      writePSBuf(hexBuf, i);
+	      i = 0;
+	    }
+	  }
+        }
+      } else {
+        for (comp = 0; comp < 4; ++comp) {
+          for (x = 0; x < width; ++x) {
+	    digit = lineBuf[4*x + comp] / 16;
+	    hexBuf[i++] = digit + ((digit >= 10)? 'a'-10: '0');
+	    digit = lineBuf[4*x + comp] % 16;
+	    hexBuf[i++] = digit + ((digit >= 10)? 'a'-10: '0');
+	    if (i >= 64) {
+	      hexBuf[i++] = '\n';
+	      writePSBuf(hexBuf, i);
+	      i = 0;
+	    }
 	  }
 	}
       }


More information about the poppler mailing list