summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Johnson <ajohnson@redneon.com>2020-05-16 22:08:32 +0200
committerAlbert Astals Cid <tsdgeos@yahoo.es>2020-05-21 09:00:29 +0000
commit1f698b44564b0313c019557616866eae11bf2cc9 (patch)
treef7686f173583fc7497e4956e5b8402a9a6bab8af
parentd5efac76267c7adf7636514280614efcc1ac3392 (diff)
Use ICC profiles in PS output
When printing PDFs that use ICC based colors, Poppler always uses the alternate color space in the PostScript output (usually DeviceRGB or DeviceCMYK). The attached patch will use the ICC profile color space in the PS output. Most of the patch is modifying GfxColorTransform and callers to store the source profile as well as the transform. The GfxICCBasedColorSpace class has a new method, getPostScriptCSA(), which uses the LCMS function cmsGetPostScriptCSA() to generate the CIEBased color space dictionary equivalent to the ICC profile. Based on patch from issue #125.
-rw-r--r--poppler/GfxState.cc114
-rw-r--r--poppler/GfxState.h12
-rw-r--r--poppler/PSOutputDev.cc77
-rw-r--r--poppler/PSOutputDev.h8
4 files changed, 153 insertions, 58 deletions
diff --git a/poppler/GfxState.cc b/poppler/GfxState.cc
index 7141c9f8..f5f11c13 100644
--- a/poppler/GfxState.cc
+++ b/poppler/GfxState.cc
@@ -196,16 +196,22 @@ void GfxColorTransform::doTransform(void *in, void *out, unsigned int size) {
}
// transformA should be a cmsHTRANSFORM
-GfxColorTransform::GfxColorTransform(void *transformA, int cmsIntentA, unsigned int inputPixelTypeA, unsigned int transformPixelTypeA) {
+GfxColorTransform::GfxColorTransform(void *sourceProfileA, void *transformA, int cmsIntentA, unsigned int inputPixelTypeA, unsigned int transformPixelTypeA) {
+ sourceProfile = sourceProfileA;
transform = transformA;
refCount = 1;
cmsIntent = cmsIntentA;
inputPixelType = inputPixelTypeA;
transformPixelType = transformPixelTypeA;
+ psCSA = NULL;
}
GfxColorTransform::~GfxColorTransform() {
+ if (sourceProfile)
+ cmsCloseProfile(sourceProfile);
cmsDeleteTransform(transform);
+ if (psCSA)
+ gfree(psCSA);
}
void GfxColorTransform::ref() {
@@ -216,6 +222,31 @@ unsigned int GfxColorTransform::unref() {
return --refCount;
}
+char *GfxColorTransform::getPostScriptCSA()
+{
+ int size;
+
+ if (psCSA)
+ return psCSA;
+
+ if (sourceProfile == NULL) {
+ error(errSyntaxWarning, -1, "profile is NULL");
+ return NULL;
+ }
+
+ size = cmsGetPostScriptCSA(cmsGetProfileContextID(sourceProfile), sourceProfile, cmsIntent, 0, NULL, 0);
+ if (size == 0) {
+ error(errSyntaxWarning, -1, "PostScript CSA is NULL");
+ return NULL;
+ }
+
+ psCSA = (char*)gmalloc(size+1);
+ cmsGetPostScriptCSA(cmsGetProfileContextID(sourceProfile), sourceProfile, cmsIntent, 0, psCSA, size);
+ psCSA[size] = 0;
+
+ return psCSA;
+}
+
static cmsHPROFILE RGBProfile = nullptr;
static GooString *displayProfileName = nullptr; // display profile file Name
static cmsHPROFILE displayProfile = nullptr; // display profile
@@ -248,9 +279,8 @@ void GfxColorSpace::setDisplayProfile(void *displayProfileA) {
INTENT_RELATIVE_COLORIMETRIC,LCMS_FLAGS)) == nullptr) {
error(errSyntaxWarning, -1, "Can't create Lab transform");
} else {
- XYZ2DisplayTransform = new GfxColorTransform(transform, INTENT_RELATIVE_COLORIMETRIC, PT_XYZ, displayPixelType);
+ XYZ2DisplayTransform = new GfxColorTransform(displayProfile, transform, INTENT_RELATIVE_COLORIMETRIC, PT_XYZ, displayPixelType);
}
- cmsCloseProfile(XYZProfile);
}
}
@@ -525,10 +555,10 @@ int GfxColorSpace::setupColorProfiles()
CHANNELS_SH(nChannels) | BYTES_SH(1),
INTENT_RELATIVE_COLORIMETRIC,LCMS_FLAGS)) == nullptr) {
error(errSyntaxWarning, -1, "Can't create Lab transform");
+ cmsCloseProfile(XYZProfile);
} else {
- XYZ2DisplayTransform = new GfxColorTransform(transform, INTENT_RELATIVE_COLORIMETRIC, PT_XYZ, displayPixelType);
+ XYZ2DisplayTransform = new GfxColorTransform(XYZProfile, transform, INTENT_RELATIVE_COLORIMETRIC, PT_XYZ, displayPixelType);
}
- cmsCloseProfile(XYZProfile);
}
return 0;
}
@@ -1789,16 +1819,7 @@ GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr, OutputDev *out, GfxState
int transformIntent = cs->getIntent();
int cmsIntent = INTENT_RELATIVE_COLORIMETRIC;
if (state != nullptr) {
- const char *intent = state->getRenderingIntent();
- if (intent != nullptr) {
- if (strcmp(intent, "AbsoluteColorimetric") == 0) {
- cmsIntent = INTENT_ABSOLUTE_COLORIMETRIC;
- } else if (strcmp(intent, "Saturation") == 0) {
- cmsIntent = INTENT_SATURATION;
- } else if (strcmp(intent, "Perceptual") == 0) {
- cmsIntent = INTENT_PERCEPTUAL;
- }
- }
+ cmsIntent = state->getCmsRenderingIntent();
}
if (transformIntent == cmsIntent) {
return cs;
@@ -1883,16 +1904,7 @@ GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr, OutputDev *out, GfxState
int cmsIntent = INTENT_RELATIVE_COLORIMETRIC;
if (state != nullptr) {
- const char *intent = state->getRenderingIntent();
- if (intent != nullptr) {
- if (strcmp(intent, "AbsoluteColorimetric") == 0) {
- cmsIntent = INTENT_ABSOLUTE_COLORIMETRIC;
- } else if (strcmp(intent, "Saturation") == 0) {
- cmsIntent = INTENT_SATURATION;
- } else if (strcmp(intent, "Perceptual") == 0) {
- cmsIntent = INTENT_PERCEPTUAL;
- }
- }
+ cmsIntent = state->getCmsRenderingIntent();
}
if ((transform = cmsCreateTransform(hp,
COLORSPACE_SH(cst) |CHANNELS_SH(nCompsA) | BYTES_SH(1),
@@ -1903,7 +1915,7 @@ GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr, OutputDev *out, GfxState
error(errSyntaxWarning, -1, "Can't create transform");
cs->transform = nullptr;
} else {
- cs->transform = new GfxColorTransform(transform, cmsIntent, cst, dcst);
+ cs->transform = new GfxColorTransform(hp, transform, cmsIntent, cst, dcst);
}
if (dcst == PT_RGB || dcst == PT_CMYK) {
// create line transform only when the display is RGB type color space
@@ -1913,10 +1925,12 @@ GfxColorSpace *GfxICCBasedColorSpace::parse(Array *arr, OutputDev *out, GfxState
error(errSyntaxWarning, -1, "Can't create transform");
cs->lineTransform = nullptr;
} else {
- cs->lineTransform = new GfxColorTransform(transform, cmsIntent, cst, dcst);
+ cs->lineTransform = new GfxColorTransform(NULL, transform, cmsIntent, cst, dcst);
}
}
- cmsCloseProfile(hp);
+ if (cs->transform == nullptr) {
+ cmsCloseProfile(hp);
+ }
}
// put this colorSpace into cache
if (out && iccProfileStreamA != Ref::INVALID()) {
@@ -2368,6 +2382,16 @@ void GfxICCBasedColorSpace::getDefaultRanges(double *decodeLow,
#endif
}
+#ifdef USE_CMS
+char *GfxICCBasedColorSpace::getPostScriptCSA()
+{
+ if (transform)
+ return transform->getPostScriptCSA();
+ else
+ return NULL;
+}
+#endif
+
//------------------------------------------------------------------------
// GfxIndexedColorSpace
//------------------------------------------------------------------------
@@ -6597,37 +6621,46 @@ void GfxState::setDisplayProfile(cmsHPROFILE localDisplayProfileA) {
CHANNELS_SH(nChannels) | BYTES_SH(1),
INTENT_RELATIVE_COLORIMETRIC,LCMS_FLAGS)) == nullptr) {
error(errSyntaxWarning, -1, "Can't create Lab transform");
+ cmsCloseProfile(XYZProfile);
} else {
- XYZ2DisplayTransformRelCol = new GfxColorTransform(transform, INTENT_RELATIVE_COLORIMETRIC, PT_XYZ, localDisplayPixelType);
+ XYZ2DisplayTransformRelCol = new GfxColorTransform(XYZProfile, transform, INTENT_RELATIVE_COLORIMETRIC, PT_XYZ, localDisplayPixelType);
}
+
+ XYZProfile = cmsCreateXYZProfile();
if ((transform = cmsCreateTransform(XYZProfile, TYPE_XYZ_DBL,
localDisplayProfile,
COLORSPACE_SH(localDisplayPixelType) |
CHANNELS_SH(nChannels) | BYTES_SH(1),
INTENT_ABSOLUTE_COLORIMETRIC,LCMS_FLAGS)) == nullptr) {
error(errSyntaxWarning, -1, "Can't create Lab transform");
+ cmsCloseProfile(XYZProfile);
} else {
- XYZ2DisplayTransformAbsCol = new GfxColorTransform(transform, INTENT_ABSOLUTE_COLORIMETRIC, PT_XYZ, localDisplayPixelType);
+ XYZ2DisplayTransformAbsCol = new GfxColorTransform(XYZProfile, transform, INTENT_ABSOLUTE_COLORIMETRIC, PT_XYZ, localDisplayPixelType);
}
+
+ XYZProfile = cmsCreateXYZProfile();
if ((transform = cmsCreateTransform(XYZProfile, TYPE_XYZ_DBL,
localDisplayProfile,
COLORSPACE_SH(localDisplayPixelType) |
CHANNELS_SH(nChannels) | BYTES_SH(1),
INTENT_SATURATION,LCMS_FLAGS)) == nullptr) {
error(errSyntaxWarning, -1, "Can't create Lab transform");
+ cmsCloseProfile(XYZProfile);
} else {
- XYZ2DisplayTransformSat = new GfxColorTransform(transform, INTENT_SATURATION, PT_XYZ, localDisplayPixelType);
+ XYZ2DisplayTransformSat = new GfxColorTransform(XYZProfile, transform, INTENT_SATURATION, PT_XYZ, localDisplayPixelType);
}
+
+ XYZProfile = cmsCreateXYZProfile();
if ((transform = cmsCreateTransform(XYZProfile, TYPE_XYZ_DBL,
localDisplayProfile,
COLORSPACE_SH(localDisplayPixelType) |
CHANNELS_SH(nChannels) | BYTES_SH(1),
INTENT_PERCEPTUAL,LCMS_FLAGS)) == nullptr) {
error(errSyntaxWarning, -1, "Can't create Lab transform");
+ cmsCloseProfile(XYZProfile);
} else {
- XYZ2DisplayTransformPerc = new GfxColorTransform(transform, INTENT_PERCEPTUAL, PT_XYZ, localDisplayPixelType);
+ XYZ2DisplayTransformPerc = new GfxColorTransform(XYZProfile, transform, INTENT_PERCEPTUAL, PT_XYZ, localDisplayPixelType);
}
- cmsCloseProfile(XYZProfile);
}
}
@@ -6648,6 +6681,21 @@ GfxColorTransform *GfxState::getXYZ2DisplayTransform() {
return transform;
}
+int GfxState::getCmsRenderingIntent() {
+ const char *intent = getRenderingIntent();
+ int cmsIntent = INTENT_RELATIVE_COLORIMETRIC;
+ if (intent) {
+ if (strcmp(intent, "AbsoluteColorimetric") == 0) {
+ cmsIntent = INTENT_ABSOLUTE_COLORIMETRIC;
+ } else if (strcmp(intent, "Saturation") == 0) {
+ cmsIntent = INTENT_SATURATION;
+ } else if (strcmp(intent, "Perceptual") == 0) {
+ cmsIntent = INTENT_PERCEPTUAL;
+ }
+ }
+ return cmsIntent;
+}
+
#endif
void GfxState::setPath(GfxPath *pathA) {
diff --git a/poppler/GfxState.h b/poppler/GfxState.h
index 6d445ecf..3da66e8c 100644
--- a/poppler/GfxState.h
+++ b/poppler/GfxState.h
@@ -193,7 +193,8 @@ class GfxColorTransform {
public:
void doTransform(void *in, void *out, unsigned int size);
// transformA should be a cmsHTRANSFORM
- GfxColorTransform(void *transformA, int cmsIntent, unsigned int inputPixelType, unsigned int transformPixelType);
+ GfxColorTransform(void *sourceProfileA, void *transformA, int cmsIntent,
+ unsigned int inputPixelType, unsigned int transformPixelType);
~GfxColorTransform();
GfxColorTransform(const GfxColorTransform &) = delete;
GfxColorTransform& operator=(const GfxColorTransform &) = delete;
@@ -202,13 +203,17 @@ public:
int getTransformPixelType() const { return transformPixelType; }
void ref();
unsigned int unref();
+ void *getSourceProfile() { return sourceProfile; }
+ char *getPostScriptCSA();
private:
GfxColorTransform() {}
+ void *sourceProfile;
void *transform;
unsigned int refCount;
int cmsIntent;
unsigned int inputPixelType;
unsigned int transformPixelType;
+ char *psCSA;
};
class GfxColorSpace {
@@ -569,6 +574,10 @@ public:
// ICCBased-specific access.
GfxColorSpace *getAlt() { return alt; }
+ Ref getRef() { return iccProfileStream; }
+#ifdef USE_CMS
+ char *getPostScriptCSA();
+#endif
private:
@@ -1594,6 +1603,7 @@ public:
void setDisplayProfile(void *localDisplayProfileA);
void *getDisplayProfile() { return localDisplayProfile; }
GfxColorTransform *getXYZ2DisplayTransform();
+ int getCmsRenderingIntent();
#endif
// Add to path.
diff --git a/poppler/PSOutputDev.cc b/poppler/PSOutputDev.cc
index 8ad72c36..9a920fbb 100644
--- a/poppler/PSOutputDev.cc
+++ b/poppler/PSOutputDev.cc
@@ -3945,6 +3945,10 @@ void PSOutputDev::endPage() {
(*overlayCbk)(this, overlayCbkData);
}
+ for (const auto& item : iccEmitted) {
+ writePSFmt("userdict /{0:s} undef\n", item.c_str());
+ }
+ iccEmitted.clear();
if (mode == psModeForm) {
writePS("pdfEndPage\n");
@@ -3955,8 +3959,8 @@ void PSOutputDev::endPage() {
if (!manualCtrl) {
writePS("showpage\n");
}
- writePS("%%PageTrailer\n");
- writePageTrailer();
+ writePS("%%PageTrailer\n");
+ writePageTrailer();
}
}
@@ -4022,7 +4026,7 @@ void PSOutputDev::updateFillColorSpace(GfxState *state) {
case psLevel2:
case psLevel3:
if (state->getFillColorSpace()->getMode() != csPattern) {
- dumpColorSpaceL2(state->getFillColorSpace(), true, false, false);
+ dumpColorSpaceL2(state, state->getFillColorSpace(), true, false, false);
writePS(" cs\n");
}
break;
@@ -4043,7 +4047,7 @@ void PSOutputDev::updateStrokeColorSpace(GfxState *state) {
case psLevel2:
case psLevel3:
if (state->getStrokeColorSpace()->getMode() != csPattern) {
- dumpColorSpaceL2(state->getStrokeColorSpace(), true, false, false);
+ dumpColorSpaceL2(state, state->getStrokeColorSpace(), true, false, false);
writePS(" CS\n");
}
break;
@@ -4940,7 +4944,7 @@ bool PSOutputDev::patchMeshShadedFill(GfxState *state,
writePS("<<\n");
writePS(" /ShadingType 7\n");
writePS(" /ColorSpace ");
- dumpColorSpaceL2(shading->getColorSpace(), false, false, false);
+ dumpColorSpaceL2(state, shading->getColorSpace(), false, false, false);
writePS("\n");
writePS(" /DataSource [\n");
@@ -5233,12 +5237,12 @@ void PSOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
break;
case psLevel2:
case psLevel2Sep:
- doImageL2(ref, nullptr, invert, inlineImg, str, width, height, len,
+ doImageL2(state, ref, nullptr, invert, inlineImg, str, width, height, len,
nullptr, nullptr, 0, 0, false);
break;
case psLevel3:
case psLevel3Sep:
- doImageL3(ref, nullptr, invert, inlineImg, str, width, height, len,
+ doImageL3(state, ref, nullptr, invert, inlineImg, str, width, height, len,
nullptr, nullptr, 0, 0, false);
break;
}
@@ -5277,12 +5281,12 @@ void PSOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
break;
case psLevel2:
case psLevel2Sep:
- doImageL2(ref, colorMap, false, inlineImg, str,
+ doImageL2(state, ref, colorMap, false, inlineImg, str,
width, height, len, maskColors, nullptr, 0, 0, false);
break;
case psLevel3:
case psLevel3Sep:
- doImageL3(ref, colorMap, false, inlineImg, str,
+ doImageL3(state, ref, colorMap, false, inlineImg, str,
width, height, len, maskColors, nullptr, 0, 0, false);
break;
}
@@ -5312,12 +5316,12 @@ void PSOutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *str,
break;
case psLevel2:
case psLevel2Sep:
- doImageL2(ref, colorMap, false, false, str, width, height, len,
+ doImageL2(state, ref, colorMap, false, false, str, width, height, len,
nullptr, maskStr, maskWidth, maskHeight, maskInvert);
break;
case psLevel3:
case psLevel3Sep:
- doImageL3(ref, colorMap, false, false, str, width, height, len,
+ doImageL3(state, ref, colorMap, false, false, str, width, height, len,
nullptr, maskStr, maskWidth, maskHeight, maskInvert);
break;
}
@@ -5769,7 +5773,7 @@ void PSOutputDev::maskToClippingPath(Stream *maskStr, int maskWidth, int maskHei
maskStr->close();
}
-void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
+void PSOutputDev::doImageL2(GfxState* state, Object *ref, GfxImageColorMap *colorMap,
bool invert, bool inlineImg,
Stream *str, int width, int height, int len,
const int *maskColors, Stream *maskStr,
@@ -5961,7 +5965,7 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
bool isCustomColor =
(level == psLevel1Sep || level == psLevel2Sep || level == psLevel3Sep) &&
colorMap->getColorSpace()->getMode() == csDeviceN;
- dumpColorSpaceL2(colorMap->getColorSpace(), false, !isCustomColor, false);
+ dumpColorSpaceL2(state, colorMap->getColorSpace(), false, !isCustomColor, false);
writePS(" setcolorspace\n");
}
@@ -6249,7 +6253,7 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
}
//~ this doesn't currently support OPI
-void PSOutputDev::doImageL3(Object *ref, GfxImageColorMap *colorMap,
+void PSOutputDev::doImageL3(GfxState *state, Object *ref, GfxImageColorMap *colorMap,
bool invert, bool inlineImg,
Stream *str, int width, int height, int len,
const int *maskColors, Stream *maskStr,
@@ -6364,7 +6368,7 @@ void PSOutputDev::doImageL3(Object *ref, GfxImageColorMap *colorMap,
bool isCustomColor =
(level == psLevel1Sep || level == psLevel2Sep || level == psLevel3Sep) &&
colorMap->getColorSpace()->getMode() == csDeviceN;
- dumpColorSpaceL2(colorMap->getColorSpace(), false, !isCustomColor, false);
+ dumpColorSpaceL2(state, colorMap->getColorSpace(), false, !isCustomColor, false);
writePS(" setcolorspace\n");
}
@@ -6663,7 +6667,7 @@ void PSOutputDev::doImageL3(Object *ref, GfxImageColorMap *colorMap,
}
}
-void PSOutputDev::dumpColorSpaceL2(GfxColorSpace *colorSpace,
+void PSOutputDev::dumpColorSpaceL2(GfxState *state, GfxColorSpace *colorSpace,
bool genXform, bool updateColors,
bool map01) {
GfxCalGrayColorSpace *calGrayCS;
@@ -6804,17 +6808,48 @@ void PSOutputDev::dumpColorSpaceL2(GfxColorSpace *colorSpace,
break;
case csICCBased:
+#if USE_CMS
+ {
+ GfxICCBasedColorSpace *iccBasedCS;
+ iccBasedCS = (GfxICCBasedColorSpace *)colorSpace;
+ Ref ref = iccBasedCS->getRef();
+ int intent = state->getCmsRenderingIntent();
+ GooString *name = GooString::format("ICCBased-{0:d}-{1:d}-{2:d}", ref.num, ref.gen, intent);
+ const auto& it = iccEmitted.find(name->toStr());
+ if (it != iccEmitted.end()) {
+ writePSFmt("{0:t}", name);
+ if (genXform) {
+ writePS(" {}");
+ }
+ } else {
+ char *csa = iccBasedCS->getPostScriptCSA();
+ if (csa) {
+ writePSFmt("userdict /{0:t} {1:s} put\n", name, csa);
+ iccEmitted.emplace(name->toStr());
+ writePSFmt("{0:t}", name);
+ if (genXform) {
+ writePS(" {}");
+ }
+ } else {
+ dumpColorSpaceL2(state, ((GfxICCBasedColorSpace *)colorSpace)->getAlt(),
+ genXform, updateColors, false);
+ }
+ }
+ delete name;
+ }
+#else
// there is no transform function to the alternate color space, so
// we can use it directly
- dumpColorSpaceL2(((GfxICCBasedColorSpace *)colorSpace)->getAlt(),
+ dumpColorSpaceL2(state, ((GfxICCBasedColorSpace *)colorSpace)->getAlt(),
genXform, updateColors, false);
+#endif
break;
case csIndexed:
indexedCS = (GfxIndexedColorSpace *)colorSpace;
baseCS = indexedCS->getBase();
writePS("[/Indexed ");
- dumpColorSpaceL2(baseCS, false, false, true);
+ dumpColorSpaceL2(state, baseCS, false, false, true);
n = indexedCS->getIndexHigh();
numComps = baseCS->getNComps();
lookup = indexedCS->getLookup();
@@ -6889,7 +6924,7 @@ void PSOutputDev::dumpColorSpaceL2(GfxColorSpace *colorSpace,
writePS("[/Separation ");
writePSString(separationCS->getName()->toStr());
writePS(" ");
- dumpColorSpaceL2(separationCS->getAlt(), false, false, false);
+ dumpColorSpaceL2(state, separationCS->getAlt(), false, false, false);
writePS("\n");
cvtFunction(separationCS->getFunc());
writePS("]");
@@ -6911,7 +6946,7 @@ void PSOutputDev::dumpColorSpaceL2(GfxColorSpace *colorSpace,
writePS(" ");
}
writePS("]\n");
- dumpColorSpaceL2(deviceNCS->getAlt(), false, updateColors, false);
+ dumpColorSpaceL2(state, deviceNCS->getAlt(), false, updateColors, false);
writePS("\n");
cvtFunction(deviceNCS->getTintTransformFunc(), map01 && deviceNCS->getAlt()->getMode() == csLab);
writePS("]\n");
@@ -6920,7 +6955,7 @@ void PSOutputDev::dumpColorSpaceL2(GfxColorSpace *colorSpace,
}
} else {
// DeviceN color spaces are a Level 3 PostScript feature.
- dumpColorSpaceL2(deviceNCS->getAlt(), false, updateColors, map01);
+ dumpColorSpaceL2(state, deviceNCS->getAlt(), false, updateColors, map01);
if (genXform) {
writePS(" ");
cvtFunction(deviceNCS->getTintTransformFunc());
diff --git a/poppler/PSOutputDev.h b/poppler/PSOutputDev.h
index 5114a1d6..8641d14e 100644
--- a/poppler/PSOutputDev.h
+++ b/poppler/PSOutputDev.h
@@ -395,17 +395,17 @@ private:
Stream *str, int width, int height, int len,
const int *maskColors, Stream *maskStr,
int maskWidth, int maskHeight, bool maskInvert);
- void doImageL2(Object *ref, GfxImageColorMap *colorMap,
+ void doImageL2(GfxState *state, Object *ref, GfxImageColorMap *colorMap,
bool invert, bool inlineImg,
Stream *str, int width, int height, int len,
const int *maskColors, Stream *maskStr,
int maskWidth, int maskHeight, bool maskInvert);
- void doImageL3(Object *ref, GfxImageColorMap *colorMap,
+ void doImageL3(GfxState *state, Object *ref, GfxImageColorMap *colorMap,
bool invert, bool inlineImg,
Stream *str, int width, int height, int len,
const int *maskColors, Stream *maskStr,
int maskWidth, int maskHeight, bool maskInvert);
- void dumpColorSpaceL2(GfxColorSpace *colorSpace,
+ void dumpColorSpaceL2(GfxState *state, GfxColorSpace *colorSpace,
bool genXform, bool updateColors,
bool map01);
bool tilingPatternFillL1(GfxState *state, Catalog *cat, Object *str,
@@ -557,6 +557,8 @@ private:
bool enableLZW; // enable LZW compression
bool enableFlate; // enable Flate compression
+ std::unordered_set<std::string> iccEmitted; // contains ICCBased CSAs that have been emitted
+
#ifdef OPI_SUPPORT
int opi13Nest; // nesting level of OPI 1.3 objects
int opi20Nest; // nesting level of OPI 2.0 objects