[poppler] 2 commits - qt4/src qt5/src splash/SplashBitmap.cc splash/SplashBitmap.h

Albert Astals Cid aacid at kemper.freedesktop.org
Thu Aug 27 13:58:18 PDT 2015


 qt4/src/poppler-page.cc |   42 ++++++++++++++---------------------------
 qt5/src/poppler-page.cc |   42 ++++++++++++++---------------------------
 splash/SplashBitmap.cc  |   49 +++++++++++++++++++++++++++++++++++++-----------
 splash/SplashBitmap.h   |   11 ++++++++--
 4 files changed, 77 insertions(+), 67 deletions(-)

New commits:
commit 6e469dbe239714b478488af5ff73046e6a46a908
Author: Adam Reichold <adam.reichold at t-online.de>
Date:   Sun Aug 16 21:05:38 2015 +0200

    Change default Qt frontend image format
    
    Change the default image format used by the Qt frontends to XBGR/RGB32
    which allows efficient blending and pixmap conversion via Qt. Also use
    the premultiplied conversion for IgnorePaperColor to elide a further
    copy for pixmap conversion.

diff --git a/qt4/src/poppler-page.cc b/qt4/src/poppler-page.cc
index e965ee8..16a18f1 100644
--- a/qt4/src/poppler-page.cc
+++ b/qt4/src/poppler-page.cc
@@ -327,11 +327,7 @@ QImage Page::renderToImage(double xres, double yres, int x, int y, int w, int h,
         bgColor[2] = m_page->parentDoc->paperColor.red();
       }
 
-      SplashColorMode colorMode = splashModeRGB8;
-
-      const bool ignorePaperColor = m_page->parentDoc->m_hints & Document::IgnorePaperColor;
-      if (ignorePaperColor) colorMode = splashModeXBGR8;
-
+      SplashColorMode colorMode = splashModeXBGR8;
 #if SPLASH_CMYK
       if (overprintPreview) colorMode = splashModeDeviceN8;
 #endif
@@ -340,6 +336,8 @@ QImage Page::renderToImage(double xres, double yres, int x, int y, int w, int h,
       if (m_page->parentDoc->m_hints & Document::ThinLineShape) thinLineMode = splashThinLineShape;
       if (m_page->parentDoc->m_hints & Document::ThinLineSolid) thinLineMode = splashThinLineSolid;
 
+      const bool ignorePaperColor = m_page->parentDoc->m_hints & Document::IgnorePaperColor;
+
       SplashOutputDev splash_output(
                   colorMode, 4,
                   gFalse,
@@ -367,45 +365,31 @@ QImage Page::renderToImage(double xres, double yres, int x, int y, int w, int h,
 
       // If we use DeviceN8, convert to XBGR8.
       // If requested, also transfer Splash's internal alpha channel.
-      if (overprintPreview || ignorePaperColor) {
-          const SplashBitmap::ConversionMode mode = ignorePaperColor
-                  ? SplashBitmap::conversionAlpha
-                  : SplashBitmap::conversionOpaque;
-
-          if (bitmap->convertToXBGR(mode)) {
-              SplashColorPtr data = bitmap->getDataPtr();
-
-              if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
-                  // Convert byte order from RGBX to XBGR.
-                  for (int i = 0; i < bh; ++i) {
-                      for (int j = 0; j < bw; ++j) {
-                          SplashColorPtr pixel = &data[i * brs + j];
-
-                          qSwap(pixel[0], pixel[3]);
-                          qSwap(pixel[1], pixel[2]);
-                      }
-                  }
-              }
+      const SplashBitmap::ConversionMode mode = ignorePaperColor
+              ? SplashBitmap::conversionAlphaPremultiplied
+              : SplashBitmap::conversionOpaque;
 
-              // Construct a Qt image sharing the raw bitmap data.
-              img = QImage(data, bw, bh, brs, QImage::Format_ARGB32).copy();
-          }
-      } else {
+      const QImage::Format format = ignorePaperColor
+              ? QImage::Format_ARGB32_Premultiplied
+              : QImage::Format_RGB32;
+
+      if (bitmap->convertToXBGR(mode)) {
           SplashColorPtr data = bitmap->getDataPtr();
 
           if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
-              // Convert byte order from BGR to RGB.
+              // Convert byte order from RGBX to XBGR.
               for (int i = 0; i < bh; ++i) {
                   for (int j = 0; j < bw; ++j) {
                       SplashColorPtr pixel = &data[i * brs + j];
 
-                      qSwap(pixel[0], pixel[2]);
+                      qSwap(pixel[0], pixel[3]);
+                      qSwap(pixel[1], pixel[2]);
                   }
               }
           }
 
           // Construct a Qt image sharing the raw bitmap data.
-          img = QImage(data, bw, bh, brs, QImage::Format_RGB888).copy();
+          img = QImage(data, bw, bh, brs, format).copy();
       }
 #endif
       break;
diff --git a/qt5/src/poppler-page.cc b/qt5/src/poppler-page.cc
index 58cea3a..3832861 100644
--- a/qt5/src/poppler-page.cc
+++ b/qt5/src/poppler-page.cc
@@ -327,11 +327,7 @@ QImage Page::renderToImage(double xres, double yres, int x, int y, int w, int h,
         bgColor[2] = m_page->parentDoc->paperColor.red();
       }
 
-      SplashColorMode colorMode = splashModeRGB8;
- 
-      const bool ignorePaperColor = m_page->parentDoc->m_hints & Document::IgnorePaperColor;
-      if (ignorePaperColor) colorMode = splashModeXBGR8;
-
+      SplashColorMode colorMode = splashModeXBGR8;
 #if SPLASH_CMYK
       if (overprintPreview) colorMode = splashModeDeviceN8;
 #endif
@@ -340,6 +336,8 @@ QImage Page::renderToImage(double xres, double yres, int x, int y, int w, int h,
       if (m_page->parentDoc->m_hints & Document::ThinLineShape) thinLineMode = splashThinLineShape;
       if (m_page->parentDoc->m_hints & Document::ThinLineSolid) thinLineMode = splashThinLineSolid;
 
+      const bool ignorePaperColor = m_page->parentDoc->m_hints & Document::IgnorePaperColor;
+
       SplashOutputDev splash_output(
                   colorMode, 4,
                   gFalse,
@@ -367,45 +365,31 @@ QImage Page::renderToImage(double xres, double yres, int x, int y, int w, int h,
 
       // If we use DeviceN8, convert to XBGR8.
       // If requested, also transfer Splash's internal alpha channel.
-      if (overprintPreview || ignorePaperColor) {
-          const SplashBitmap::ConversionMode mode = ignorePaperColor
-                  ? SplashBitmap::conversionAlpha
-                  : SplashBitmap::conversionOpaque;
-
-          if (bitmap->convertToXBGR(mode)) {
-              SplashColorPtr data = bitmap->takeData();
-
-              if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
-                  // Convert byte order from RGBX to XBGR.
-                  for (int i = 0; i < bh; ++i) {
-                      for (int j = 0; j < bw; ++j) {
-                          SplashColorPtr pixel = &data[i * brs + j];
-
-                          qSwap(pixel[0], pixel[3]);
-                          qSwap(pixel[1], pixel[2]);
-                      }
-                  }
-              }
+      const SplashBitmap::ConversionMode mode = ignorePaperColor
+              ? SplashBitmap::conversionAlphaPremultiplied
+              : SplashBitmap::conversionOpaque;
 
-              // Construct a Qt image holding (and also owning) the raw bitmap data.
-              img = QImage(data, bw, bh, brs, QImage::Format_ARGB32, gfree, data);
-          }
-      } else {
+      const QImage::Format format = ignorePaperColor
+              ? QImage::Format_ARGB32_Premultiplied
+              : QImage::Format_RGB32;
+
+      if (bitmap->convertToXBGR(mode)) {
           SplashColorPtr data = bitmap->takeData();
 
           if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
-              // Convert byte order from BGR to RGB.
+              // Convert byte order from RGBX to XBGR.
               for (int i = 0; i < bh; ++i) {
                   for (int j = 0; j < bw; ++j) {
                       SplashColorPtr pixel = &data[i * brs + j];
 
-                      qSwap(pixel[0], pixel[2]);
+                      qSwap(pixel[0], pixel[3]);
+                      qSwap(pixel[1], pixel[2]);
                   }
               }
           }
 
           // Construct a Qt image holding (and also owning) the raw bitmap data.
-          img = QImage(data, bw, bh, brs, QImage::Format_RGB888, gfree, data);
+          img = QImage(data, bw, bh, brs, format, gfree, data);
       }
 #endif
       break;
commit 56fc0bb2f20adfd89835f3132bfef3033fdcd80d
Author: Adam Reichold <adam.reichold at t-online.de>
Date:   Sun Aug 16 21:01:52 2015 +0200

    Add premultiplied alpha channel to SplashBitmap
    
    This extends the convertToXBGR method so that it can either
     * leave the alpha channel of the bitmap data opaque,
     * copy the alpha channel into the bitmap data,
     * transfer the alpha channel into the bitmap data and
       perform premultiplication on the bitmap data.

diff --git a/qt4/src/poppler-page.cc b/qt4/src/poppler-page.cc
index 292f960..e965ee8 100644
--- a/qt4/src/poppler-page.cc
+++ b/qt4/src/poppler-page.cc
@@ -368,7 +368,11 @@ QImage Page::renderToImage(double xres, double yres, int x, int y, int w, int h,
       // If we use DeviceN8, convert to XBGR8.
       // If requested, also transfer Splash's internal alpha channel.
       if (overprintPreview || ignorePaperColor) {
-          if (bitmap->convertToXBGR(ignorePaperColor)) {
+          const SplashBitmap::ConversionMode mode = ignorePaperColor
+                  ? SplashBitmap::conversionAlpha
+                  : SplashBitmap::conversionOpaque;
+
+          if (bitmap->convertToXBGR(mode)) {
               SplashColorPtr data = bitmap->getDataPtr();
 
               if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
diff --git a/qt5/src/poppler-page.cc b/qt5/src/poppler-page.cc
index 8e071c1..58cea3a 100644
--- a/qt5/src/poppler-page.cc
+++ b/qt5/src/poppler-page.cc
@@ -368,7 +368,11 @@ QImage Page::renderToImage(double xres, double yres, int x, int y, int w, int h,
       // If we use DeviceN8, convert to XBGR8.
       // If requested, also transfer Splash's internal alpha channel.
       if (overprintPreview || ignorePaperColor) {
-          if (bitmap->convertToXBGR(ignorePaperColor)) {
+          const SplashBitmap::ConversionMode mode = ignorePaperColor
+                  ? SplashBitmap::conversionAlpha
+                  : SplashBitmap::conversionOpaque;
+
+          if (bitmap->convertToXBGR(mode)) {
               SplashColorPtr data = bitmap->takeData();
 
               if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
diff --git a/splash/SplashBitmap.cc b/splash/SplashBitmap.cc
index c905c97..7c14b31 100644
--- a/splash/SplashBitmap.cc
+++ b/splash/SplashBitmap.cc
@@ -461,7 +461,7 @@ void SplashBitmap::getRGBLine(int yl, SplashColorPtr line) {
   }
 }
 
-void SplashBitmap::getXBGRLine(int yl, SplashColorPtr line, bool useAlpha) {
+void SplashBitmap::getXBGRLine(int yl, SplashColorPtr line, ConversionMode conversionMode) {
   SplashColor col;
   double c, m, y, k, c1, m1, y1, k1, r, g, b;
 
@@ -501,16 +501,34 @@ void SplashBitmap::getXBGRLine(int yl, SplashColorPtr line, bool useAlpha) {
     y1 = 1 - y;
     k1 = 1 - k;
     cmykToRGBMatrixMultiplication(c, m, y, k, c1, m1, y1, k1, r, g, b);
-    *line++ = dblToByte(clip01(b));
-    *line++ = dblToByte(clip01(g));
-    *line++ = dblToByte(clip01(r));
-    *line++ = useAlpha ? getAlpha(x, yl) : 255;
+
+    if (conversionMode == conversionAlphaPremultiplied) {
+        const double a = getAlpha(x, yl) / 255.0;
+
+        *line++ = dblToByte(clip01(b * a));
+        *line++ = dblToByte(clip01(g * a));
+        *line++ = dblToByte(clip01(r * a));
+    } else {
+        *line++ = dblToByte(clip01(b));
+        *line++ = dblToByte(clip01(g));
+        *line++ = dblToByte(clip01(r));
+    }
+
+    if (conversionMode != conversionOpaque) {
+        *line++ = getAlpha(x, yl);
+    } else {
+        *line++ = 255;
+    }
   }
 }
 
-GBool SplashBitmap::convertToXBGR(bool useAlpha) {
+static inline Guchar div255(int x) {
+  return (Guchar)((x + (x >> 8) + 0x80) >> 8);
+}
+
+GBool SplashBitmap::convertToXBGR(ConversionMode conversionMode) {
   if (mode == splashModeXBGR8) {
-    if (useAlpha) {
+    if (conversionMode != conversionOpaque) {
       // Copy the alpha channel into the fourth component so that XBGR becomes ABGR.
       const SplashColorPtr dbegin = data;
       const SplashColorPtr dend = data + rowSize * height;
@@ -518,11 +536,20 @@ GBool SplashBitmap::convertToXBGR(bool useAlpha) {
       Guchar *const abegin = alpha;
       Guchar *const aend = alpha + width * height;
 
-      SplashColorPtr d = dbegin + 3;
+      SplashColorPtr d = dbegin;
       Guchar *a = abegin;
 
-      for(; d < dend && a < aend; d += 4, a += 1) {
-        *d = *a;
+      if (conversionMode == conversionAlphaPremultiplied) {
+          for (; d < dend && a < aend; d += 4, a += 1) {
+              d[0] = div255(d[0] * *a);
+              d[1] = div255(d[1] * *a);
+              d[2] = div255(d[2] * *a);
+              d[3] = *a;
+          }
+      } else {
+          for (d += 3; d < dend && a < aend; d += 4, a += 1) {
+              *d = *a;
+          }
       }
     }
 
@@ -534,7 +561,7 @@ GBool SplashBitmap::convertToXBGR(bool useAlpha) {
   if (newdata != NULL) {
     for (int y = 0; y < height; y++) {
       unsigned char *row = newdata + y * newrowSize;
-      getXBGRLine(y, row, useAlpha);
+      getXBGRLine(y, row, conversionMode);
     }
     if (rowSize < 0) {
       gfree(data + (height - 1) * rowSize);
diff --git a/splash/SplashBitmap.h b/splash/SplashBitmap.h
index 9fa7613..4417af7 100644
--- a/splash/SplashBitmap.h
+++ b/splash/SplashBitmap.h
@@ -76,11 +76,18 @@ public:
   SplashError writeImgFile(SplashImageFileFormat format, FILE *f, int hDPI, int vDPI, const char *compressionString = "");
   SplashError writeImgFile(ImgWriter *writer, FILE *f, int hDPI, int vDPI);
 
-  GBool convertToXBGR(bool useAlpha = false);
+  enum ConversionMode
+  {
+      conversionOpaque,
+      conversionAlpha,
+      conversionAlphaPremultiplied
+  };
+
+  GBool convertToXBGR(ConversionMode conversionMode = conversionOpaque);
 
   void getPixel(int x, int y, SplashColorPtr pixel);
   void getRGBLine(int y, SplashColorPtr line);
-  void getXBGRLine(int y, SplashColorPtr line, bool useAlpha = false);
+  void getXBGRLine(int y, SplashColorPtr line, ConversionMode conversionMode = conversionOpaque);
 #if SPLASH_CMYK
   void getCMYKLine(int y, SplashColorPtr line);
 #endif


More information about the poppler mailing list