diff --git a/poppler/SplashOutputDev.cc b/poppler/SplashOutputDev.cc index a7cc6bc..d7ba754 100644 --- a/poppler/SplashOutputDev.cc +++ b/poppler/SplashOutputDev.cc @@ -2818,6 +2818,39 @@ struct SplashOutImageData { int width, height, y; }; +#ifdef USE_CMS +GBool SplashOutputDev::useIccImageSrc(void *data) { + SplashOutImageData *imgData = (SplashOutImageData *)data; + + if (!imgData->lookup && imgData->colorMap->getColorSpace()->getMode() == csICCBased) { + GfxICCBasedColorSpace *colorSpace = (GfxICCBasedColorSpace *) imgData->colorMap->getColorSpace(); + switch (imgData->colorMode) { + case splashModeMono1: + case splashModeMono8: + if (colorSpace->getAlt() != NULL && colorSpace->getAlt()->getMode() == csDeviceGray) + return gTrue; + break; + case splashModeRGB8: + case splashModeBGR8: + if (colorSpace->getAlt() != NULL && colorSpace->getAlt()->getMode() == csDeviceRGB) + return gTrue; + break; + case splashModeXBGR8: + return gFalse; + break; +#if SPLASH_CMYK + case splashModeCMYK8: + if (colorSpace->getAlt() != NULL && colorSpace->getAlt()->getMode() == csDeviceCMYK) + return gTrue; + break; +#endif + } + } + + return gFalse; +} +#endif + GBool SplashOutputDev::imageSrc(void *data, SplashColorPtr colorLine, Guchar * /*alphaLine*/) { SplashOutImageData *imgData = (SplashOutImageData *)data; @@ -2965,6 +2998,71 @@ GBool SplashOutputDev::imageSrc(void *data, SplashColorPtr colorLine, return gTrue; } +#ifdef USE_CMS +GBool SplashOutputDev::iccImageSrc(void *data, SplashColorPtr colorLine, + Guchar * /*alphaLine*/) { + SplashOutImageData *imgData = (SplashOutImageData *)data; + Guchar *p; + int nComps; + + if (imgData->y == imgData->height) { + return gFalse; + } + if (!(p = imgData->imgStr->getLine())) { + int destComps = 1; + if (imgData->colorMode == splashModeRGB8 || imgData->colorMode == splashModeBGR8) + destComps = 3; + else if (imgData->colorMode == splashModeXBGR8) + destComps = 4; +#if SPLASH_CMYK + else if (imgData->colorMode == splashModeCMYK8) + destComps = 4; + else if (imgData->colorMode == splashModeDeviceN8) + destComps = SPOT_NCOMPS + 4; +#endif + memset(colorLine, 0, imgData->width * destComps); + return gFalse; + } + + nComps = imgData->colorMap->getNumPixelComps(); + memcpy(colorLine, p, imgData->width * nComps); + + ++imgData->y; + return gTrue; +} + +void SplashOutputDev::iccTransform(void *data, SplashBitmap *bitmap) { + SplashOutImageData *imgData = (SplashOutImageData *)data; + int nComps = imgData->colorMap->getNumPixelComps(); + + Guchar *colorLine = (Guchar *) gmalloc(nComps * bitmap->getWidth()); + for (int i = 0; i < bitmap->getHeight(); i++) { + Guchar *p = bitmap->getDataPtr() + i * bitmap->getRowSize(); + switch (imgData->colorMode) { + case splashModeMono1: + case splashModeMono8: + imgData->colorMap->getGrayLine(p, colorLine, bitmap->getWidth()); + memcpy(p, colorLine, nComps * bitmap->getWidth()); + break; + case splashModeRGB8: + case splashModeBGR8: + imgData->colorMap->getRGBLine(p, colorLine, bitmap->getWidth()); + memcpy(p, colorLine, nComps * bitmap->getWidth()); + break; +#if SPLASH_CMYK + case splashModeCMYK8: + imgData->colorMap->getCMYKLine(p, colorLine, bitmap->getWidth()); + memcpy(p, colorLine, nComps * bitmap->getWidth()); + break; +#endif + case splashModeXBGR8: + break; + } + } + gfree(colorLine); +} +#endif + GBool SplashOutputDev::alphaImageSrc(void *data, SplashColorPtr colorLine, Guchar *alphaLine) { SplashOutImageData *imgData = (SplashOutImageData *)data; @@ -3176,6 +3274,7 @@ void SplashOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, SplashOutImageData imgData; SplashColorMode srcMode; SplashImageSource src; + SplashICCTransform tf; GfxGray gray; GfxRGB rgb; #if SPLASH_CMYK @@ -3293,8 +3392,14 @@ void SplashOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, } else { srcMode = colorMode; } +#ifdef USE_CMS + src = maskColors ? &alphaImageSrc : useIccImageSrc(&imgData) ? &iccImageSrc : &imageSrc; + tf = maskColors == NULL && useIccImageSrc(&imgData) ? &iccTransform : NULL; +#else src = maskColors ? &alphaImageSrc : &imageSrc; - splash->drawImage(src, &imgData, srcMode, maskColors ? gTrue : gFalse, + tf = NULL; +#endif + splash->drawImage(src, tf, &imgData, srcMode, maskColors ? gTrue : gFalse, width, height, mat, interpolate); if (inlineImg) { while (imgData.y < height) { @@ -3596,7 +3701,7 @@ void SplashOutputDev::drawMaskedImage(GfxState *state, Object *ref, } else { srcMode = colorMode; } - splash->drawImage(&maskedImageSrc, &imgData, srcMode, gTrue, + splash->drawImage(&maskedImageSrc, NULL, &imgData, srcMode, gTrue, width, height, mat, interpolate); delete maskBitmap; gfree(imgData.lookup); @@ -3671,7 +3776,7 @@ void SplashOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, maskSplash = new Splash(maskBitmap, vectorAntialias); maskColor[0] = 0; maskSplash->clear(maskColor); - maskSplash->drawImage(&imageSrc, &imgMaskData, splashModeMono8, gFalse, + maskSplash->drawImage(&imageSrc, NULL, &imgMaskData, splashModeMono8, gFalse, maskWidth, maskHeight, mat, maskInterpolate); delete imgMaskData.imgStr; maskStr->close(); @@ -3759,7 +3864,7 @@ void SplashOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, } else { srcMode = colorMode; } - splash->drawImage(&imageSrc, &imgData, srcMode, gFalse, width, height, mat, interpolate); + splash->drawImage(&imageSrc, NULL, &imgData, srcMode, gFalse, width, height, mat, interpolate); splash->setSoftMask(NULL); gfree(imgData.lookup); delete imgData.imgStr; @@ -4358,7 +4463,7 @@ GBool SplashOutputDev::tilingPatternFill(GfxState *state, Gfx *gfxA, Catalog *ca } retValue = gTrue; } else { - retValue = splash->drawImage(&tilingBitmapSrc, &imgData, colorMode, gTrue, result_width, result_height, matc, gFalse, gTrue) == splashOk; + retValue = splash->drawImage(&tilingBitmapSrc, NULL, &imgData, colorMode, gTrue, result_width, result_height, matc, gFalse, gTrue) == splashOk; } delete tBitmap; delete gfx; diff --git a/poppler/SplashOutputDev.h b/poppler/SplashOutputDev.h index ae20fac..2238a33 100644 --- a/poppler/SplashOutputDev.h +++ b/poppler/SplashOutputDev.h @@ -383,6 +383,12 @@ private: GBool dropEmptySubpaths); void drawType3Glyph(GfxState *state, T3FontCache *t3Font, T3FontCacheTag *tag, Guchar *data); +#ifdef USE_CMS + GBool useIccImageSrc(void *data); + static void iccTransform(void *data, SplashBitmap *bitmap); + static GBool iccImageSrc(void *data, SplashColorPtr colorLine, + Guchar *alphaLine); +#endif static GBool imageMaskSrc(void *data, SplashColorPtr line); static GBool imageSrc(void *data, SplashColorPtr colorLine, Guchar *alphaLine); diff --git a/splash/Splash.cc b/splash/Splash.cc index d8ee640..5b4c8a2 100644 --- a/splash/Splash.cc +++ b/splash/Splash.cc @@ -3659,7 +3659,7 @@ void Splash::blitMask(SplashBitmap *src, int xDest, int yDest, } } -SplashError Splash::drawImage(SplashImageSource src, void *srcData, +SplashError Splash::drawImage(SplashImageSource src, SplashICCTransform tf, void *srcData, SplashColorMode srcMode, GBool srcAlpha, int w, int h, SplashCoord *mat, GBool interpolate, GBool tilingPattern) { @@ -3750,6 +3750,9 @@ SplashError Splash::drawImage(SplashImageSource src, void *srcData, if (scaledImg == NULL) { return splashErrBadArg; } + if (tf != NULL) { + (*tf)(srcData, scaledImg); + } blitImage(scaledImg, srcAlpha, x0, y0, clipRes); delete scaledImg; } @@ -3788,6 +3791,9 @@ SplashError Splash::drawImage(SplashImageSource src, void *srcData, if (scaledImg == NULL) { return splashErrBadArg; } + if (tf != NULL) { + (*tf)(srcData, scaledImg); + } vertFlipImage(scaledImg, scaledWidth, scaledHeight, nComps); blitImage(scaledImg, srcAlpha, x0, y0, clipRes); delete scaledImg; @@ -3795,14 +3801,14 @@ SplashError Splash::drawImage(SplashImageSource src, void *srcData, // all other cases } else { - return arbitraryTransformImage(src, srcData, srcMode, nComps, srcAlpha, + return arbitraryTransformImage(src, tf, srcData, srcMode, nComps, srcAlpha, w, h, mat, interpolate, tilingPattern); } return splashOk; } -SplashError Splash::arbitraryTransformImage(SplashImageSource src, void *srcData, +SplashError Splash::arbitraryTransformImage(SplashImageSource src, SplashICCTransform tf, void *srcData, SplashColorMode srcMode, int nComps, GBool srcAlpha, int srcWidth, int srcHeight, @@ -3937,6 +3943,9 @@ SplashError Splash::arbitraryTransformImage(SplashImageSource src, void *srcData return splashErrBadArg; } + if (tf != NULL) { + (*tf)(srcData, scaledImg); + } // construct the three sections i = 0; if (vy[1] < vy[i]) { diff --git a/splash/Splash.h b/splash/Splash.h index cf98e6c..e5ef65b 100644 --- a/splash/Splash.h +++ b/splash/Splash.h @@ -56,6 +56,9 @@ typedef GBool (*SplashImageMaskSource)(void *data, SplashColorPtr pixel); typedef GBool (*SplashImageSource)(void *data, SplashColorPtr colorLine, Guchar *alphaLine); +// Use ICCColorSpace to transform a bitmap +typedef void (*SplashICCTransform)(void *data, SplashBitmap *bitmap); + //------------------------------------------------------------------------ enum SplashPipeResultColorCtrl { @@ -211,7 +214,7 @@ public: // BGR8 BGR8 // CMYK8 CMYK8 // The matrix behaves as for fillImageMask. - SplashError drawImage(SplashImageSource src, void *srcData, + SplashError drawImage(SplashImageSource src, SplashICCTransform tf, void *srcData, SplashColorMode srcMode, GBool srcAlpha, int w, int h, SplashCoord *mat, GBool interpolate, GBool tilingPattern = gFalse); @@ -357,7 +360,7 @@ private: SplashBitmap *dest); void blitMask(SplashBitmap *src, int xDest, int yDest, SplashClipResult clipRes); - SplashError arbitraryTransformImage(SplashImageSource src, void *srcData, + SplashError arbitraryTransformImage(SplashImageSource src, SplashICCTransform tf, void *srcData, SplashColorMode srcMode, int nComps, GBool srcAlpha, int srcWidth, int srcHeight,