diff --git a/poppler/GfxState.cc b/poppler/GfxState.cc index 0bafb6d..7c20288 100644 --- a/poppler/GfxState.cc +++ b/poppler/GfxState.cc @@ -53,6 +53,7 @@ #include "GlobalParams.h" #include "PopplerCache.h" #include "OutputDev.h" +#include "splash/SplashTypes.h" //------------------------------------------------------------------------ @@ -604,6 +605,24 @@ void GfxDeviceGrayColorSpace::getRGBXLine(Guchar *in, Guchar *out, int length) { } } +void GfxDeviceGrayColorSpace::getCMYKLine(Guchar *in, Guchar *out, int length) { + for (int i = 0; i < length; i++) { + *out++ = 0; + *out++ = 0; + *out++ = 0; + *out++ = in[i]; + } +} + +void GfxDeviceGrayColorSpace::getDeviceNLine(Guchar *in, Guchar *out, int length) { + for (int i = 0; i < length; i++) { + for (int j = 0; j < SPOT_NCOMPS+4; j++) + out[j] = 0; + out[4] = in[i]; + out += (SPOT_NCOMPS+4); + } +} + void GfxDeviceGrayColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { cmyk->c = cmyk->m = cmyk->y = 0; cmyk->k = clip01(gfxColorComp1 - color->c[0]); @@ -900,6 +919,52 @@ void GfxDeviceRGBColorSpace::getRGBXLine(Guchar *in, Guchar *out, int length) { *out++ = 255; } } + +void GfxDeviceRGBColorSpace::getCMYKLine(Guchar *in, Guchar *out, int length) { + GfxColorComp c, m, y, k; + + for (int i = 0; i < length; i++) { + c = byteToCol(255 - *in++); + m = byteToCol(255 - *in++); + y = byteToCol(255 - *in++); + k = c; + if (m < k) { + k = m; + } + if (y < k) { + k = y; + } + *out++ = colToByte(c - k); + *out++ = colToByte(m - k); + *out++ = colToByte(y - k); + *out++ = colToByte(k); + } +} + +void GfxDeviceRGBColorSpace::getDeviceNLine(Guchar *in, Guchar *out, int length) { + GfxColorComp c, m, y, k; + + for (int i = 0; i < length; i++) { + for (int j = 0; j < SPOT_NCOMPS+4; j++) + out[j] = 0; + c = byteToCol(255 - *in++); + m = byteToCol(255 - *in++); + y = byteToCol(255 - *in++); + k = c; + if (m < k) { + k = m; + } + if (y < k) { + k = y; + } + out[0] = colToByte(c - k); + out[1] = colToByte(m - k); + out[2] = colToByte(y - k); + out[3] = colToByte(k); + out += (SPOT_NCOMPS+4); + } +} + void GfxDeviceRGBColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { GfxColorComp c, m, y, k; @@ -1266,6 +1331,29 @@ void GfxDeviceCMYKColorSpace::getRGBXLine(Guchar *in, Guchar *out, int length) } } +void GfxDeviceCMYKColorSpace::getCMYKLine(Guchar *in, Guchar *out, int length) +{ + for (int i = 0; i < length; i++) { + *out++ = *in++; + *out++ = *in++; + *out++ = *in++; + *out++ = *in++; + } +} + +void GfxDeviceCMYKColorSpace::getDeviceNLine(Guchar *in, Guchar *out, int length) +{ + for (int i = 0; i < length; i++) { + for (int j = 0; j < SPOT_NCOMPS+4; j++) + out[j] = 0; + out[0] = *in++; + out[1] = *in++; + out[2] = *in++; + out[3] = *in++; + out += (SPOT_NCOMPS+4); + } +} + void GfxDeviceCMYKColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { cmyk->c = clip01(color->c[0]); cmyk->m = clip01(color->c[1]); @@ -1877,6 +1965,86 @@ void GfxICCBasedColorSpace::getRGBXLine(Guchar *in, Guchar *out, int length) { #endif } +void GfxICCBasedColorSpace::getCMYKLine(Guchar *in, Guchar *out, int length) { +#ifdef USE_CMS + if (lineTransform != NULL && displayPixelType == PT_CMYK) { + transform->doTransform(in,out,length); + } else if (lineTransform != NULL) { + GfxColorComp c, m, y, k; + Guchar* tmp = (Guchar *)gmallocn(3 * length, sizeof(Guchar)); + getRGBLine(in, tmp, length); + Guchar *p = tmp; + for (int i = 0; i < length; i++) { + c = byteToCol(255 - *p++); + m = byteToCol(255 - *p++); + y = byteToCol(255 - *p++); + k = c; + if (m < k) { + k = m; + } + if (y < k) { + k = y; + } + *out++ = colToByte(c - k); + *out++ = colToByte(m - k); + *out++ = colToByte(y - k); + *out++ = colToByte(k); + } + gfree(tmp); + } else { + alt->getCMYKLine(in, out, length); + } +#else + alt->getCMYKLine(in, out, length); +#endif +} + +void GfxICCBasedColorSpace::getDeviceNLine(Guchar *in, Guchar *out, int length) { +#ifdef USE_CMS + if (lineTransform != NULL && displayPixelType == PT_CMYK) { + Guchar* tmp = (Guchar *)gmallocn(4 * length, sizeof(Guchar)); + transform->doTransform(in,tmp,length); + Guchar *p = tmp; + for (int i = 0; i < length; i++) { + for (int j = 0; j < 4; j++) + *out++ = *p++; + for (int j = 4; j < SPOT_NCOMPS+4; j++) + *out++ = 0; + } + gfree(tmp); + } else if (lineTransform != NULL) { + GfxColorComp c, m, y, k; + Guchar* tmp = (Guchar *)gmallocn(3 * length, sizeof(Guchar)); + getRGBLine(in, tmp, length); + Guchar *p = tmp; + for (int i = 0; i < length; i++) { + for (int j = 0; j < SPOT_NCOMPS+4; j++) + out[j] = 0; + c = byteToCol(255 - *p++); + m = byteToCol(255 - *p++); + y = byteToCol(255 - *p++); + k = c; + if (m < k) { + k = m; + } + if (y < k) { + k = y; + } + out[0] = colToByte(c - k); + out[1] = colToByte(m - k); + out[2] = colToByte(y - k); + out[3] = colToByte(k); + out += (SPOT_NCOMPS+4); + } + gfree(tmp); + } else { + alt->getDeviceNLine(in, out, length); + } +#else + alt->getDeviceNLine(in, out, length); +#endif +} + void GfxICCBasedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { #ifdef USE_CMS if (transform != NULL && displayPixelType == PT_CMYK) { @@ -1924,6 +2092,22 @@ GBool GfxICCBasedColorSpace::useGetRGBLine() { #endif } +GBool GfxICCBasedColorSpace::useGetCMYKLine() { +#ifdef USE_CMS + return lineTransform != NULL || alt->useGetCMYKLine(); +#else + return alt->useGetCMYKLine(); +#endif +} + +GBool GfxICCBasedColorSpace::useGetDeviceNLine() { +#ifdef USE_CMS + return lineTransform != NULL || alt->useGetDeviceNLine(); +#else + return alt->useGetDeviceNLine(); +#endif +} + void GfxICCBasedColorSpace::getDeviceN(GfxColor *color, GfxColor *deviceN) { GfxCMYK cmyk; for (int i = 0; i < gfxColorMaxComps; i++) @@ -2148,6 +2332,36 @@ void GfxIndexedColorSpace::getRGBXLine(Guchar *in, Guchar *out, int length) gfree (line); } +void GfxIndexedColorSpace::getCMYKLine(Guchar *in, Guchar *out, int length) { + Guchar *line; + int i, j, n; + + n = base->getNComps(); + line = (Guchar *) gmallocn (length, n); + for (i = 0; i < length; i++) + for (j = 0; j < n; j++) + line[i * n + j] = lookup[in[i] * n + j]; + + base->getCMYKLine(line, out, length); + + gfree (line); +} + +void GfxIndexedColorSpace::getDeviceNLine(Guchar *in, Guchar *out, int length) { + Guchar *line; + int i, j, n; + + n = base->getNComps(); + line = (Guchar *) gmallocn (length, n); + for (i = 0; i < length; i++) + for (j = 0; j < n; j++) + line[i * n + j] = lookup[in[i] * n + j]; + + base->getDeviceNLine(line, out, length); + + gfree (line); +} + void GfxIndexedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { GfxColor color2; @@ -5258,7 +5472,7 @@ GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode, nComps2 = colorSpace2->getNComps(); indexedLookup = indexedCS->getLookup(); colorSpace2->getDefaultRanges(x, y, indexHigh); - if (colorSpace2->useGetGrayLine() || colorSpace2->useGetRGBLine()) { + if (colorSpace2->useGetGrayLine() || colorSpace2->useGetRGBLine() || colorSpace2->useGetCMYKLine() || colorSpace2->useGetDeviceNLine()) { byte_lookup = (Guchar *)gmallocn ((maxPixel + 1), nComps2); useByteLookup = gTrue; } @@ -5285,7 +5499,7 @@ GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode, colorSpace2 = sepCS->getAlt(); nComps2 = colorSpace2->getNComps(); sepFunc = sepCS->getFunc(); - if (colorSpace2->useGetGrayLine() || colorSpace2->useGetRGBLine()) { + if (colorSpace2->useGetGrayLine() || colorSpace2->useGetRGBLine() || colorSpace2->useGetCMYKLine() || colorSpace2->useGetDeviceNLine()) { byte_lookup = (Guchar *)gmallocn ((maxPixel + 1), nComps2); useByteLookup = gTrue; } @@ -5302,7 +5516,7 @@ GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode, } break; default: - if (colorSpace->useGetGrayLine() || colorSpace->useGetRGBLine()) { + if (colorSpace->useGetGrayLine() || colorSpace->useGetRGBLine() || colorSpace->useGetCMYKLine() || colorSpace2->useGetDeviceNLine()) { byte_lookup = (Guchar *)gmallocn ((maxPixel + 1), nComps); useByteLookup = gTrue; } @@ -5599,6 +5813,94 @@ void GfxImageColorMap::getRGBXLine(Guchar *in, Guchar *out, int length) { } +void GfxImageColorMap::getCMYKLine(Guchar *in, Guchar *out, int length) { + int i, j; + Guchar *inp, *tmp_line; + + if (!useCMYKLine()) { + GfxCMYK cmyk; + + inp = in; + for (i = 0; i < length; i++) { + getCMYK (inp, &cmyk); + *out++ = colToByte(cmyk.c); + *out++ = colToByte(cmyk.m); + *out++ = colToByte(cmyk.y); + *out++ = colToByte(cmyk.k); + inp += nComps; + } + return; + } + + switch (colorSpace->getMode()) { + case csIndexed: + case csSeparation: + tmp_line = (Guchar *) gmallocn (length, nComps2); + for (i = 0; i < length; i++) { + for (j = 0; j < nComps2; j++) { + tmp_line[i * nComps2 + j] = byte_lookup[in[i] * nComps2 + j]; + } + } + colorSpace2->getCMYKLine(tmp_line, out, length); + gfree (tmp_line); + break; + + default: + inp = in; + for (j = 0; j < length; j++) + for (i = 0; i < nComps; i++) { + *inp = byte_lookup[*inp * nComps + i]; + inp++; + } + colorSpace->getCMYKLine(in, out, length); + break; + } + +} + +void GfxImageColorMap::getDeviceNLine(Guchar *in, Guchar *out, int length) { + int i, j; + Guchar *inp, *tmp_line; + + if (!useDeviceNLine()) { + GfxColor deviceN; + + inp = in; + for (i = 0; i < length; i++) { + getDeviceN (inp, &deviceN); + for (int j = 0; j < SPOT_NCOMPS+4; j++) + *out++ = deviceN.c[j]; + inp += nComps; + } + return; + } + + switch (colorSpace->getMode()) { + case csIndexed: + case csSeparation: + tmp_line = (Guchar *) gmallocn (length, nComps2); + for (i = 0; i < length; i++) { + for (j = 0; j < nComps2; j++) { + tmp_line[i * nComps2 + j] = byte_lookup[in[i] * nComps2 + j]; + } + } + colorSpace2->getDeviceNLine(tmp_line, out, length); + gfree (tmp_line); + break; + + default: + inp = in; + for (j = 0; j < length; j++) + for (i = 0; i < nComps; i++) { + *inp = byte_lookup[*inp * nComps + i]; + inp++; + } + colorSpace->getDeviceNLine(in, out, length); + break; + } + +} + void GfxImageColorMap::getCMYK(Guchar *x, GfxCMYK *cmyk) { GfxColor color; int i; diff --git a/poppler/GfxState.h b/poppler/GfxState.h index 2f3efcf..498dfeb 100644 --- a/poppler/GfxState.h +++ b/poppler/GfxState.h @@ -210,6 +210,8 @@ public: virtual void getRGBLine(Guchar * /*in*/, unsigned int * /*out*/, int /*length*/) { error(errInternal, -1, "GfxColorSpace::getRGBLine (first variant) this should not happen"); } virtual void getRGBLine(Guchar * /*in*/, Guchar * /*out*/, int /*length*/) { error(errInternal, -1, "GfxColorSpace::getRGBLine (second variant) this should not happen"); } virtual void getRGBXLine(Guchar * /*in*/, Guchar * /*out*/, int /*length*/) { error(errInternal, -1, "GfxColorSpace::getRGBXLine this should not happen"); } + virtual void getCMYKLine(Guchar * /*in*/, Guchar * /*out*/, int /*length*/) { error(errInternal, -1, "GfxColorSpace::getCMYKLine this should not happen"); } + virtual void getDeviceNLine(Guchar * /*in*/, Guchar * /*out*/, int /*length*/) { error(errInternal, -1, "GfxColorSpace::getDeviceNLine this should not happen"); } // create mapping for spot colorants virtual void createMapping(GooList *separationList, int maxSepComps); @@ -218,6 +220,10 @@ public: virtual GBool useGetRGBLine() { return gFalse; } // Does this ColorSpace support getGrayLine? virtual GBool useGetGrayLine() { return gFalse; } + // Does this ColorSpace support getCMYKLine? + virtual GBool useGetCMYKLine() { return gFalse; } + // Does this ColorSpace support getDeviceNLine? + virtual GBool useGetDeviceNLine() { return gFalse; } // Return the number of color components. virtual int getNComps() = 0; @@ -279,9 +285,13 @@ public: virtual void getRGBLine(Guchar *in, unsigned int *out, int length); virtual void getRGBLine(Guchar *in, Guchar *out, int length); virtual void getRGBXLine(Guchar *in, Guchar *out, int length); + virtual void getCMYKLine(Guchar *in, Guchar *out, int length); + virtual void getDeviceNLine(Guchar *in, Guchar *out, int length); virtual GBool useGetRGBLine() { return gTrue; } virtual GBool useGetGrayLine() { return gTrue; } + virtual GBool useGetCMYKLine() { return gTrue; } + virtual GBool useGetDeviceNLine() { return gTrue; } virtual int getNComps() { return 1; } virtual void getDefaultColor(GfxColor *color); @@ -350,9 +360,13 @@ public: virtual void getRGBLine(Guchar *in, unsigned int *out, int length); virtual void getRGBLine(Guchar *in, Guchar *out, int length); virtual void getRGBXLine(Guchar *in, Guchar *out, int length); + virtual void getCMYKLine(Guchar *in, Guchar *out, int length); + virtual void getDeviceNLine(Guchar *in, Guchar *out, int length); virtual GBool useGetRGBLine() { return gTrue; } virtual GBool useGetGrayLine() { return gTrue; } + virtual GBool useGetCMYKLine() { return gTrue; } + virtual GBool useGetDeviceNLine() { return gTrue; } virtual int getNComps() { return 3; } virtual void getDefaultColor(GfxColor *color); @@ -424,7 +438,11 @@ public: virtual void getRGBLine(Guchar *in, unsigned int *out, int length); virtual void getRGBLine(Guchar *, Guchar *out, int length); virtual void getRGBXLine(Guchar *in, Guchar *out, int length); + virtual void getCMYKLine(Guchar *in, Guchar *out, int length); + virtual void getDeviceNLine(Guchar *in, Guchar *out, int length); virtual GBool useGetRGBLine() { return gTrue; } + virtual GBool useGetCMYKLine() { return gTrue; } + virtual GBool useGetDeviceNLine() { return gTrue; } virtual int getNComps() { return 4; } virtual void getDefaultColor(GfxColor *color); @@ -502,8 +520,12 @@ public: virtual void getRGBLine(Guchar *in, unsigned int *out, int length); virtual void getRGBLine(Guchar *in, Guchar *out, int length); virtual void getRGBXLine(Guchar *in, Guchar *out, int length); + virtual void getCMYKLine(Guchar *in, Guchar *out, int length); + virtual void getDeviceNLine(Guchar *in, Guchar *out, int length); virtual GBool useGetRGBLine(); + virtual GBool useGetCMYKLine(); + virtual GBool useGetDeviceNLine(); virtual int getNComps() { return nComps; } virtual void getDefaultColor(GfxColor *color); @@ -548,8 +570,12 @@ public: virtual void getRGBLine(Guchar *in, unsigned int *out, int length); virtual void getRGBLine(Guchar *in, Guchar *out, int length); virtual void getRGBXLine(Guchar *in, Guchar *out, int length); + virtual void getCMYKLine(Guchar *in, Guchar *out, int length); + virtual void getDeviceNLine(Guchar *in, Guchar *out, int length); virtual GBool useGetRGBLine() { return gTrue; } + virtual GBool useGetCMYKLine() { return gTrue; } + virtual GBool useGetDeviceNLine() { return gTrue; } virtual int getNComps() { return 1; } virtual void getDefaultColor(GfxColor *color); @@ -1126,6 +1152,8 @@ public: double getDecodeHigh(int i) { return decodeLow[i] + decodeRange[i]; } bool useRGBLine() { return (colorSpace2 && colorSpace2->useGetRGBLine ()) || (!colorSpace2 && colorSpace->useGetRGBLine ()); } + bool useCMYKLine() { return (colorSpace2 && colorSpace2->useGetCMYKLine ()) || (!colorSpace2 && colorSpace->useGetCMYKLine ()); } + bool useDeviceNLine() { return (colorSpace2 && colorSpace2->useGetDeviceNLine ()) || (!colorSpace2 && colorSpace->useGetDeviceNLine ()); } // Convert an image pixel to a color. void getGray(Guchar *x, GfxGray *gray); @@ -1134,6 +1162,8 @@ public: void getRGBLine(Guchar *in, Guchar *out, int length); void getRGBXLine(Guchar *in, Guchar *out, int length); void getGrayLine(Guchar *in, Guchar *out, int length); + void getCMYKLine(Guchar *in, Guchar *out, int length); + void getDeviceNLine(Guchar *in, Guchar *out, int length); void getCMYK(Guchar *x, GfxCMYK *cmyk); void getDeviceN(Guchar *x, GfxColor *deviceN); void getColor(Guchar *x, GfxColor *color); diff --git a/poppler/SplashOutputDev.cc b/poppler/SplashOutputDev.cc index 4d4e945..e0029d6 100644 --- a/poppler/SplashOutputDev.cc +++ b/poppler/SplashOutputDev.cc @@ -2862,38 +2862,50 @@ GBool SplashOutputDev::imageSrc(void *data, SplashColorPtr colorLine, break; case splashModeRGB8: case splashModeBGR8: - for (x = 0, q = colorLine; x < imgData->width; ++x, p += nComps) { - imgData->colorMap->getRGB(p, &rgb); - *q++ = colToByte(rgb.r); - *q++ = colToByte(rgb.g); - *q++ = colToByte(rgb.b); - } + if (imgData->colorMap->useRGBLine()) + imgData->colorMap->getRGBLine(p, (Guchar *) colorLine, imgData->width); + else + for (x = 0, q = colorLine; x < imgData->width; ++x, p += nComps) { + imgData->colorMap->getRGB(p, &rgb); + *q++ = colToByte(rgb.r); + *q++ = colToByte(rgb.g); + *q++ = colToByte(rgb.b); + } break; case splashModeXBGR8: - for (x = 0, q = colorLine; x < imgData->width; ++x, p += nComps) { - imgData->colorMap->getRGB(p, &rgb); - *q++ = colToByte(rgb.r); - *q++ = colToByte(rgb.g); - *q++ = colToByte(rgb.b); - *q++ = 255; - } + if (imgData->colorMap->useRGBLine()) + imgData->colorMap->getRGBXLine(p, (Guchar *) colorLine, imgData->width); + else + for (x = 0, q = colorLine; x < imgData->width; ++x, p += nComps) { + imgData->colorMap->getRGB(p, &rgb); + *q++ = colToByte(rgb.r); + *q++ = colToByte(rgb.g); + *q++ = colToByte(rgb.b); + *q++ = 255; + } break; #if SPLASH_CMYK case splashModeCMYK8: - for (x = 0, q = colorLine; x < imgData->width; ++x, p += nComps) { - imgData->colorMap->getCMYK(p, &cmyk); - *q++ = colToByte(cmyk.c); - *q++ = colToByte(cmyk.m); - *q++ = colToByte(cmyk.y); - *q++ = colToByte(cmyk.k); - } + if (imgData->colorMap->useCMYKLine()) + imgData->colorMap->getCMYKLine(p, (Guchar *) colorLine, imgData->width); + else + for (x = 0, q = colorLine; x < imgData->width; ++x, p += nComps) { + imgData->colorMap->getCMYK(p, &cmyk); + *q++ = colToByte(cmyk.c); + *q++ = colToByte(cmyk.m); + *q++ = colToByte(cmyk.y); + *q++ = colToByte(cmyk.k); + } break; case splashModeDeviceN8: - for (x = 0, q = colorLine; x < imgData->width; ++x, p += nComps) { - imgData->colorMap->getDeviceN(p, &deviceN); - for (int cp = 0; cp < SPOT_NCOMPS+4; cp++) - *q++ = colToByte(deviceN.c[cp]); - } + if (imgData->colorMap->useDeviceNLine()) + imgData->colorMap->getDeviceNLine(p, (Guchar *) colorLine, imgData->width); + else + for (x = 0, q = colorLine; x < imgData->width; ++x, p += nComps) { + imgData->colorMap->getDeviceN(p, &deviceN); + for (int cp = 0; cp < SPOT_NCOMPS+4; cp++) + *q++ = colToByte(deviceN.c[cp]); + } break; #endif }