[poppler] poppler/SplashOutputDev.cc poppler/SplashOutputDev.h splash/Splash.cc splash/Splash.h

Albert Astals Cid aacid at kemper.freedesktop.org
Sun May 24 09:42:15 PDT 2015


 poppler/SplashOutputDev.cc |  142 +++++++++++++++++++++++++++++++++++++++++++--
 poppler/SplashOutputDev.h  |    8 ++
 splash/Splash.cc           |   17 ++++-
 splash/Splash.h            |    9 +-
 4 files changed, 163 insertions(+), 13 deletions(-)

New commits:
commit 3db4cb6f07229e26405bfb512c626a272f6351f5
Author: Thomas Freitag <Thomas.Freitag at alfa.de>
Date:   Sun May 24 18:41:30 2015 +0200

    Splash: Speed up of rendering icc based images
    
    Bug #90171

diff --git a/poppler/SplashOutputDev.cc b/poppler/SplashOutputDev.cc
index a7cc6bc..5a9832d 100644
--- a/poppler/SplashOutputDev.cc
+++ b/poppler/SplashOutputDev.cc
@@ -2818,6 +2818,37 @@ 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 splashModeXBGR8:
+    case splashModeRGB8:
+    case splashModeBGR8:
+      if (colorSpace->getAlt() != NULL && colorSpace->getAlt()->getMode() == csDeviceRGB)
+        return gTrue;
+      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 +2996,100 @@ 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;
+  }
+
+  if (imgData->colorMode == splashModeXBGR8) {
+    SplashColorPtr q;
+    int x;
+    for (x = 0, q = colorLine; x < imgData->width; ++x) {
+      *q++ = *p++;
+      *q++ = *p++;
+      *q++ = *p++;
+      *q++ = 255;
+    }
+  } else {
+    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());
+  Guchar *rgbxLine = (imgData->colorMode == splashModeXBGR8) ? (Guchar *) gmalloc(3 * bitmap->getWidth()) : NULL;
+  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:
+      Guchar *q;
+      Guchar *b = p;
+      int x;
+      for (x = 0, q = rgbxLine; x < bitmap->getWidth(); ++x, ++b) {
+        *q++ = *b++;
+        *q++ = *b++;
+        *q++ = *b++;
+      }
+      imgData->colorMap->getRGBLine(rgbxLine, colorLine, bitmap->getWidth());
+      b = p;
+      for (x = 0, q = colorLine; x < bitmap->getWidth(); ++x, ++b) {
+        *b++ = *q++;
+        *b++ = *q++;
+        *b++ = *q++;
+      }
+      break;
+    }
+  }
+  gfree(colorLine);
+  if (rgbxLine != NULL) 
+    gfree(rgbxLine);
+}
+#endif
+
 GBool SplashOutputDev::alphaImageSrc(void *data, SplashColorPtr colorLine,
 				     Guchar *alphaLine) {
   SplashOutImageData *imgData = (SplashOutImageData *)data;
@@ -3176,6 +3301,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 +3419,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 +3728,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 +3803,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 +3891,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 +4490,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..d34426c 100644
--- a/poppler/SplashOutputDev.h
+++ b/poppler/SplashOutputDev.h
@@ -14,7 +14,7 @@
 // under GPL version 2 or later
 //
 // Copyright (C) 2005 Takashi Iwai <tiwai at suse.de>
-// Copyright (C) 2009-2014 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2009-2015 Thomas Freitag <Thomas.Freitag at alfa.de>
 // Copyright (C) 2009 Carlos Garcia Campos <carlosgc at gnome.org>
 // Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
 // Copyright (C) 2011 Andreas Hartmetz <ahartmetz at gmail.com>
@@ -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..276cc8f 100644
--- a/splash/Splash.cc
+++ b/splash/Splash.cc
@@ -13,7 +13,7 @@
 //
 // Copyright (C) 2005-2015 Albert Astals Cid <aacid at kde.org>
 // Copyright (C) 2005 Marco Pesenti Gritti <mpg at redhat.com>
-// Copyright (C) 2010-2014 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2010-2015 Thomas Freitag <Thomas.Freitag at alfa.de>
 // Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
 // Copyright (C) 2011-2013, 2015 William Bader <williambader at hotmail.com>
 // Copyright (C) 2012 Markus Trippelsdorf <markus at trippelsdorf.de>
@@ -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..7576454 100644
--- a/splash/Splash.h
+++ b/splash/Splash.h
@@ -13,7 +13,7 @@
 //
 // Copyright (C) 2005 Marco Pesenti Gritti <mpg at redhat.com>
 // Copyright (C) 2007, 2011 Albert Astals Cid <aacid at kde.org>
-// Copyright (C) 2010-2013 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2010-2013, 2015 Thomas Freitag <Thomas.Freitag at alfa.de>
 // Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
 // Copyright (C) 2012 Adrian Johnson <ajohnson at redneon.com>
 //
@@ -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,


More information about the poppler mailing list