summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Bader <williambader@hotmail.com>2019-11-29 01:55:29 -0500
committerAlbert Astals Cid <tsdgeos@yahoo.es>2019-11-30 19:23:49 +0000
commit8d46550c4ff3d4a1923cfc4c42e3fd4d154a7624 (patch)
treefbdfa2ae567b21574419bf19af82715dc407dafa
parent6e60cd8ef9696c12e4f33eb671013315b2b07790 (diff)
Improve pdftops -optimizecolorspace by implementing the CMYK to K conversion in more places.
This fixes the conversion of the PDF in poppler/poppler#833
-rw-r--r--poppler/PSOutputDev.cc181
1 files changed, 132 insertions, 49 deletions
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@alfa.de>
// Copyright (C) 2009 Till Kamppeter <till.kamppeter@gmail.com>
// Copyright (C) 2009 Carlos Garcia Campos <carlosgc@gnome.org>
-// Copyright (C) 2009, 2011, 2012, 2014-2017 William Bader <williambader@hotmail.com>
+// Copyright (C) 2009, 2011, 2012, 2014-2017, 2019 William Bader <williambader@hotmail.com>
// Copyright (C) 2009 Kovid Goyal <kovid@kovidgoyal.net>
// Copyright (C) 2009-2011, 2013-2015, 2017 Adrian Johnson <ajohnson@redneon.com>
// Copyright (C) 2012, 2014 Fabio D'Urso <fabiodurso@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;
+ }
}
}
}