In GfxColorSpace we have

virtual void getRGBLine(Guchar *in, unsigned int *out, int length);

That gets a color line for the given input and saves it in out as a 32 bit 
integer with each color packed to fit in 8 bits of that 32.

This works very well for cairo as it can pass a pointer to the cairo image 
data directly but for Splash is not so good as we have to unpack the 32 bit 
integer to 3 (or 4 if XRGB8 format) different Guchar.

So i'm proposing the addition of 
virtual void getRGBLine(Guchar *in, Guchar *out, int length);
that does basically the same but instead of packing the color just saves it in 
output directly.

In my tests this gives us around a 5% free speedup.

The catch is that in some cases we need to "duplicate" the conversion code 
since it is not really easy to generalize the code.

I'm attaching a work-in-progress patch.

Comments?

Albert
diff --git a/poppler/GfxState.cc b/poppler/GfxState.cc
index 8db57b2..8afafe0 100644
--- a/poppler/GfxState.cc
+++ b/poppler/GfxState.cc
@@ -528,6 +528,18 @@ void GfxDeviceGrayColorSpace::getRGBLine(Guchar *in, unsigned int *out,
     out[i] = (in[i] << 16) | (in[i] << 8) | (in[i] << 0);
 }
 
+void GfxDeviceGrayColorSpace::getRGBLine2(Guchar *in, Guchar *out,
+           int length, GBool addFourthComponent) {
+  // TODOO
+  for (int i = 0; i < length; i++) {
+    *out++ = in[i];
+    *out++ = in[i];
+    *out++ = in[i];
+    if (addFourthComponent)
+      *out++ = 255;
+  }
+}
+
 void GfxDeviceGrayColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
   cmyk->c = cmyk->m = cmyk->y = 0;
   cmyk->k = clip01(gfxColorComp1 - color->c[0]);
@@ -1086,26 +1098,44 @@ void GfxDeviceCMYKColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
   rgb->b = clip01(dblToCol(b));
 }
 
-void GfxDeviceCMYKColorSpace::getRGBLine(Guchar *in, unsigned int *out, int length)
+static inline void GfxDeviceCMYKColorSpacegetRGBLineHelper(Guchar *&in, double &r, double &g, double &b)
 {
-  double c, m, y, k, c1, m1, y1, k1, r, g, b;
+  double c, m, y, k, c1, m1, y1, k1;
   
-  Guchar *inp = in;
+  c = byteToDbl(*in++);
+  m = byteToDbl(*in++);
+  y = byteToDbl(*in++);
+  k = byteToDbl(*in++);
+  c1 = 1 - c;
+  m1 = 1 - m;
+  y1 = 1 - y;
+  k1 = 1 - k;
+  cmykToRGBMatrixMultiplication(c, m, y, k, c1, m1, y1, k1, r, g, b);
+}
+
+void GfxDeviceCMYKColorSpace::getRGBLine(Guchar *in, unsigned int *out, int length)
+{
+  double r, g, b;
   for (int i = 0; i < length; i++) {
-    c = byteToDbl(*inp++);
-    m = byteToDbl(*inp++);
-    y = byteToDbl(*inp++);
-    k = byteToDbl(*inp++);
-    c1 = 1 - c;
-    m1 = 1 - m;
-    y1 = 1 - y;
-    k1 = 1 - k;
-    cmykToRGBMatrixMultiplication(c, m, y, k, c1, m1, y1, k1, r, g, b);
-  
+    GfxDeviceCMYKColorSpacegetRGBLineHelper(in, r, g, b);
     *out++ = (dblToByte(clip01(r)) << 16) | (dblToByte(clip01(g)) << 8) | dblToByte(clip01(b));
   }
 }
 
+void GfxDeviceCMYKColorSpace::getRGBLine2(Guchar *in, Guchar *out, int length, GBool addFourthComponent)
+{
+  double r, g, b;
+  
+  for (int i = 0; i < length; i++) {
+    GfxDeviceCMYKColorSpacegetRGBLineHelper(in, r, g, b);
+    *out++ = dblToByte(clip01(r));
+    *out++ = dblToByte(clip01(g));
+    *out++ = dblToByte(clip01(b));
+    if (addFourthComponent)
+      *out++ = 255;
+  }
+}
+
 void GfxDeviceCMYKColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
   cmyk->c = clip01(color->c[0]);
   cmyk->m = clip01(color->c[1]);
@@ -1651,6 +1681,29 @@ void GfxICCBasedColorSpace::getRGBLine(Guchar *in, unsigned int *out,
 #endif
 }
 
+void GfxICCBasedColorSpace::getRGBLine2(Guchar *in, Guchar *out,
+               int length, GBool addFourthComponent) {
+#ifdef USE_CMS
+  if (lineTransform != 0) {
+    Guchar* tmp = (Guchar *)gmallocn(3 * length, sizeof(Guchar));
+    lineTransform->doTransform(in, tmp, length);
+    Guchar *current = tmp;
+    for (int i = 0; i < length; ++i) {
+        *out++ = *current++;
+        *out++ = *current++;
+        *out++ = *current++;
+        if (addFourthComponent)
+          *out++ = 255;
+    }
+    gfree(tmp);
+  } else {
+    alt->getRGBLine2(in, out, length, addFourthComponent);
+  }
+#else
+  alt->getRGBLine2(in, out, length, addFourthComponent);
+#endif
+}
+
 void GfxICCBasedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
 #ifdef USE_CMS
   if (transform != NULL && displayPixelType == PT_CMYK) {
@@ -1690,7 +1743,8 @@ void GfxICCBasedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) {
 #endif
 }
 
-GBool GfxICCBasedColorSpace::useGetRGBLine() {
+static inline GBool GfxICCBasedColorSpaceUseGetRGBLineHelper(GfxColorTransform *lineTransform, GfxColorSpace *alt)
+{
 #ifdef USE_CMS
   return lineTransform != NULL || alt->useGetRGBLine();
 #else
@@ -1698,6 +1752,15 @@ GBool GfxICCBasedColorSpace::useGetRGBLine() {
 #endif
 }
 
+GBool GfxICCBasedColorSpace::useGetRGBLine() {
+  return GfxICCBasedColorSpaceUseGetRGBLineHelper(lineTransform, alt);
+}
+
+GBool GfxICCBasedColorSpace::useGetRGBLine2()
+{
+  return GfxICCBasedColorSpaceUseGetRGBLineHelper(lineTransform, alt);
+}
+
 void GfxICCBasedColorSpace::getDefaultColor(GfxColor *color) {
   int i;
 
@@ -4887,6 +4950,56 @@ void GfxImageColorMap::getRGBLine(Guchar *in, unsigned int *out, int length) {
   }
 
 }
+#include <typeinfo>
+void GfxImageColorMap::getRGBLine2(Guchar *in, Guchar *out, int length, GBool addFourthComponent) {
+  int i, j;
+  Guchar *inp, *tmp_line;
+
+  if (!useRGBLine2()) {
+//     if (colorSpace2)
+//       printf("%s\n", typeid(*colorSpace2).name());
+//     if (!colorSpace2)
+//       printf("%s\n", typeid(*colorSpace).name());
+    GfxRGB rgb;
+
+    inp = in;
+    for (i = 0; i < length; i++) {
+      getRGB (inp, &rgb);
+      *out++ = colToByte(rgb.r);
+      *out++ = colToByte(rgb.b);
+      *out++ = colToByte(rgb.g);
+      if (addFourthComponent)
+        *out++ = 255;
+      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->getRGBLine2(tmp_line, out, length, addFourthComponent);
+    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->getRGBLine2(in, out, length, addFourthComponent);
+    break;
+  }
+
+}
 
 void GfxImageColorMap::getCMYK(Guchar *x, GfxCMYK *cmyk) {
   GfxColor color;
diff --git a/poppler/GfxState.h b/poppler/GfxState.h
index 19594ed..798276d 100644
--- a/poppler/GfxState.h
+++ b/poppler/GfxState.h
@@ -201,10 +201,13 @@ public:
   virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk) = 0;
   virtual void getGrayLine(Guchar * /*in*/, Guchar * /*out*/, int /*length*/) {}
   virtual void getRGBLine(Guchar * /*in*/, unsigned int * /*out*/, int /*length*/) {}
+  virtual void getRGBLine2(Guchar * /*in*/, Guchar * /*out*/, int /*length*/, GBool /*addFourthComponent*/) {}
 
-  // Does this ColorSpace use getRGBLine?
+  // Does this ColorSpace support getRGBLine?
   virtual GBool useGetRGBLine() { return gFalse; }
-  // Does this ColorSpace use getGrayLine?
+  // Does this ColorSpace support getRGBLine2?
+  virtual GBool useGetRGBLine2() { return gFalse; }
+  // Does this ColorSpace support getGrayLine?
   virtual GBool useGetGrayLine() { return gFalse; }
 
   // Return the number of color components.
@@ -257,8 +260,10 @@ public:
   virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
   virtual void getGrayLine(Guchar *in, Guchar *out, int length);
   virtual void getRGBLine(Guchar *in, unsigned int *out, int length);
+  virtual void getRGBLine2(Guchar *in, Guchar *out, int length, GBool addFourthComponent);
 
   virtual GBool useGetRGBLine() { return gTrue; }
+  virtual GBool useGetRGBLine2() { return gTrue; }
   virtual GBool useGetGrayLine() { return gTrue; }
 
   virtual int getNComps() { return 1; }
@@ -394,7 +399,9 @@ public:
   virtual void getRGB(GfxColor *color, GfxRGB *rgb);
   virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
   virtual void getRGBLine(Guchar *in, unsigned int *out, int length);
+  virtual void getRGBLine2(Guchar *, Guchar *out, int length, GBool addFourthComponent);
   virtual GBool useGetRGBLine() { return gTrue; }
+  virtual GBool useGetRGBLine2() { return gTrue; }
 
   virtual int getNComps() { return 4; }
   virtual void getDefaultColor(GfxColor *color);
@@ -468,8 +475,10 @@ public:
   virtual void getRGB(GfxColor *color, GfxRGB *rgb);
   virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk);
   virtual void getRGBLine(Guchar *in, unsigned int *out, int length);
+  virtual void getRGBLine2(Guchar *in, Guchar *out, int length, GBool addFourthComponent);
 
   virtual GBool useGetRGBLine();
+  virtual GBool useGetRGBLine2();
 
   virtual int getNComps() { return nComps; }
   virtual void getDefaultColor(GfxColor *color);
@@ -1068,11 +1077,13 @@ public:
   double getDecodeHigh(int i) { return decodeLow[i] + decodeRange[i]; }
   
   bool useRGBLine() { return (colorSpace2 && colorSpace2->useGetRGBLine ()) || (!colorSpace2 && colorSpace->useGetRGBLine ()); }
+  bool useRGBLine2() { return (colorSpace2 && colorSpace2->useGetRGBLine2 ()) || (!colorSpace2 && colorSpace->useGetRGBLine2 ()); }
 
   // Convert an image pixel to a color.
   void getGray(Guchar *x, GfxGray *gray);
   void getRGB(Guchar *x, GfxRGB *rgb);
   void getRGBLine(Guchar *in, unsigned int *out, int length);
+  void getRGBLine2(Guchar *in, Guchar *out, int length, GBool addFourthComponent);
   void getGrayLine(Guchar *in, Guchar *out, int length);
   void getCMYK(Guchar *x, GfxCMYK *cmyk);
   void getColor(Guchar *x, GfxColor *color);
diff --git a/poppler/SplashOutputDev.cc b/poppler/SplashOutputDev.cc
index fc838d3..d7955ac 100644
--- a/poppler/SplashOutputDev.cc
+++ b/poppler/SplashOutputDev.cc
@@ -2428,39 +2428,13 @@ GBool SplashOutputDev::imageSrc(void *data, SplashColorPtr colorLine,
 	*q++ = colToByte(gray);
       }
 	break;
-	case splashModeXBGR8:
+    case splashModeXBGR8:
     case splashModeRGB8:
     case splashModeBGR8:
-      if (!imgData->colorMap->useRGBLine())
-      {
-        GfxRGB rgb;
-        for (x = 0, p = imgData->imgStr->getLine(), 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->colorMode == splashModeXBGR8) *q++ = 255;
-        }
-      }
-      else
-      {
-        p = imgData->imgStr->getLine();
-        q = colorLine;
-        unsigned int* line = (unsigned int *)gmallocn(imgData->width, sizeof(unsigned int));
-
-        imgData->colorMap->getRGBLine(p, line, imgData->width);
-        for (x = 0; x < imgData->width; ++x) {
-            *q++ = (line[x] >> 16) & 255;
-            *q++ = (line[x] >> 8) & 255;
-            *q++ = (line[x]) & 255;
-            if (imgData->colorMode == splashModeXBGR8) {
-                *q++ = 255;
-            }
-        }
-        gfree(line);
-      }
+      p = imgData->imgStr->getLine();
+      q = colorLine;
+
+      imgData->colorMap->getRGBLine2(p, colorLine, imgData->width, imgData->colorMode == splashModeXBGR8);
       break;
 #if SPLASH_CMYK
     case splashModeCMYK8:
_______________________________________________
poppler mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/poppler

Reply via email to