Hello again, Am 02.07.2015 um 23:01 schrieb Albert Astals Cid: > Another thing i wanted to try for a while but didn't get to was killing the > Splash XRGB8 mode (which is an extension i created) and using the plain > Splash > RGB8 mode since now QImage is smart enough to know how to use that, would you > mind testing if that yields any benefit?
It does improve rendering that includes the background composition by more than two percent with structurally simple documents (i.e. some mathematical texts which do not contain any images themselves). Not doing the alpha blending (but exporting the alpha channel) is still faster, i.e. also slightly above two percent in the same benchmarks. (Meaning XBGR8 with paper colour is 2.2 % slower than RGB8 with paper colour which itself is 2.2 % slower than XBGR8 without paper colour.) An extended patch is attached. (I am not totally sure about the endianess conversion there.) Also note that while conversion from QImage to QPixmap did show no difference between Qt's handlign of ARGB32 and RGB888, painting the resulting QPixmap is 40 % faster for ARGB32, i.e. XBGR8 in Splash parlance. But since painting those images is usually very fast, this will very probably not offset the 2.2 % gain for rendering. Best regards, Adam.
From 135624f165db4cf75608f8cbb6a7da37a591503d Mon Sep 17 00:00:00 2001 From: Adam Reichold <[email protected]> Date: Thu, 2 Jul 2015 21:00:16 +0200 Subject: [PATCH 1/5] Make SplashBitmap XBGR transfer alpha channel Adds an option to SplashBitmap::convertToXBGR and SplashBitmap::getXBGRLine so that both optionally transfer Splash's internal alpha channel into the fourth component of the resulting bitmap data. --- splash/SplashBitmap.cc | 27 ++++++++++++++++++++++----- splash/SplashBitmap.h | 4 ++-- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/splash/SplashBitmap.cc b/splash/SplashBitmap.cc index e886683..7da373b 100644 --- a/splash/SplashBitmap.cc +++ b/splash/SplashBitmap.cc @@ -460,7 +460,7 @@ void SplashBitmap::getRGBLine(int yl, SplashColorPtr line) { } } -void SplashBitmap::getXBGRLine(int yl, SplashColorPtr line) { +void SplashBitmap::getXBGRLine(int yl, SplashColorPtr line, bool useAlpha) { SplashColor col; double c, m, y, k, c1, m1, y1, k1, r, g, b; @@ -503,20 +503,37 @@ void SplashBitmap::getXBGRLine(int yl, SplashColorPtr line) { *line++ = dblToByte(clip01(b)); *line++ = dblToByte(clip01(g)); *line++ = dblToByte(clip01(r)); - *line++ = 255; + *line++ = useAlpha ? getAlpha(x, yl) : 255; } } -GBool SplashBitmap::convertToXBGR() { - if (mode == splashModeXBGR8) +GBool SplashBitmap::convertToXBGR(bool useAlpha) { + if (mode == splashModeXBGR8) { + if (useAlpha) { + // Copy the alpha channel into the fourth component so that XBGR becomes ABGR. + const SplashColorPtr dbegin = data; + const SplashColorPtr dend = data + rowSize * height; + + Guchar *const abegin = alpha; + Guchar *const aend = alpha + width * height; + + SplashColorPtr d = dbegin + 3; + Guchar *a = abegin; + + for(; d < dend && a < aend; d += 4, a += 1) { + *d = *a; + } + } + return gTrue; + } int newrowSize = width * 4; SplashColorPtr newdata = (SplashColorPtr)gmallocn_checkoverflow(newrowSize, height); if (newdata != NULL) { for (int y = 0; y < height; y++) { unsigned char *row = newdata + y * newrowSize; - getXBGRLine(y, row); + getXBGRLine(y, row, useAlpha); } if (rowSize < 0) { gfree(data + (height - 1) * rowSize); diff --git a/splash/SplashBitmap.h b/splash/SplashBitmap.h index 70509ab..99879fb 100644 --- a/splash/SplashBitmap.h +++ b/splash/SplashBitmap.h @@ -75,11 +75,11 @@ 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(); + GBool convertToXBGR(bool useAlpha = false); void getPixel(int x, int y, SplashColorPtr pixel); void getRGBLine(int y, SplashColorPtr line); - void getXBGRLine(int y, SplashColorPtr line); + void getXBGRLine(int y, SplashColorPtr line, bool useAlpha = false); #if SPLASH_CMYK void getCMYKLine(int y, SplashColorPtr line); #endif -- 2.4.5 From 29d0ed18f135339bb567f65b1b3496b3dc5b01b6 Mon Sep 17 00:00:00 2001 From: Adam Reichold <[email protected]> Date: Thu, 2 Jul 2015 21:02:59 +0200 Subject: [PATCH 2/5] Add KeepAlphaChannel render flag to Qt5 frontend Adds a new render flag which will indicate that the image return by Poppler::Page::renderToImage will not be opaque and alpha blended with paper colour, but retain its actually background transparency. This improves performance in synthentic rendering benchmarks by almost five percent and the additional alpha blending that is then done by the consuming application is often a hardware-accellerated operation. --- qt5/src/poppler-page.cc | 6 ++++-- qt5/src/poppler-qt5.h | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/qt5/src/poppler-page.cc b/qt5/src/poppler-page.cc index 408099c..07ad9b6 100644 --- a/qt5/src/poppler-page.cc +++ b/qt5/src/poppler-page.cc @@ -331,13 +331,15 @@ 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 keepAlphaChannel = m_page->parentDoc->m_hints & Document::KeepAlphaChannel; + SplashOutputDev * splash_output = new SplashOutputDev( #if defined(SPLASH_CMYK) (overprint) ? splashModeDeviceN8 : splashModeXBGR8, #else splashModeXBGR8, #endif - 4, gFalse, bgColor, gTrue, thinLineMode, overprint); + 4, gFalse, keepAlphaChannel ? NULL : bgColor, gTrue, thinLineMode, overprint); splash_output->setFontAntialias(m_page->parentDoc->m_hints & Document::TextAntialiasing ? gTrue : gFalse); splash_output->setVectorAntialias(m_page->parentDoc->m_hints & Document::Antialiasing ? gTrue : gFalse); @@ -354,7 +356,7 @@ QImage Page::renderToImage(double xres, double yres, int x, int y, int w, int h, int bw = bitmap->getWidth(); int bh = bitmap->getHeight(); - if (bitmap->convertToXBGR()) + if (bitmap->convertToXBGR(keepAlphaChannel)) { SplashColorPtr dataPtr = bitmap->getDataPtr(); diff --git a/qt5/src/poppler-qt5.h b/qt5/src/poppler-qt5.h index 79c3f74..fa23844 100644 --- a/qt5/src/poppler-qt5.h +++ b/qt5/src/poppler-qt5.h @@ -891,7 +891,8 @@ delete it; TextSlightHinting = 0x00000008, ///< Lighter hinting for text when combined with TextHinting \since 0.18 OverprintPreview = 0x00000010, ///< Overprint preview \since 0.22 ThinLineSolid = 0x00000020, ///< Enhance thin lines solid \since 0.24 - ThinLineShape = 0x00000040 ///< Enhance thin lines shape. Wins over ThinLineSolid \since 0.24 + ThinLineShape = 0x00000040, ///< Enhance thin lines shape. Wins over ThinLineSolid \since 0.24 + KeepAlphaChannel = 0x00000080 ///< Do not compose with the paper color \since 0.34 }; Q_DECLARE_FLAGS( RenderHints, RenderHint ) -- 2.4.5 From e5f9a68df1b6fc9cb310a1ae6a5211028fdebccc Mon Sep 17 00:00:00 2001 From: Adam Reichold <[email protected]> Date: Thu, 2 Jul 2015 21:08:38 +0200 Subject: [PATCH 3/5] Improve efficiency of Poppler::Page::renderToImage Improves the efficiency of rendering into a QImage using the Splash output device by removing a copy of the raw bitmap data since Qt5 will properly free this data using a function supplied during construction, i.e. in this case gfree. This improves performance in synthentic rendering benchmarks by approximately four percent and reduces the maximum working set size. --- qt5/src/poppler-page.cc | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/qt5/src/poppler-page.cc b/qt5/src/poppler-page.cc index 07ad9b6..d2fa3dd 100644 --- a/qt5/src/poppler-page.cc +++ b/qt5/src/poppler-page.cc @@ -358,7 +358,7 @@ QImage Page::renderToImage(double xres, double yres, int x, int y, int w, int h, if (bitmap->convertToXBGR(keepAlphaChannel)) { - SplashColorPtr dataPtr = bitmap->getDataPtr(); + SplashColorPtr dataPtr = bitmap->takeData(); if (QSysInfo::BigEndian == QSysInfo::ByteOrder) { @@ -376,9 +376,8 @@ QImage Page::renderToImage(double xres, double yres, int x, int y, int w, int h, } } - // construct a qimage SHARING the raw bitmap data in memory - QImage tmpimg( dataPtr, bw, bh, QImage::Format_ARGB32 ); - img = tmpimg.copy(); + // Construct a Qt image holding (and also owning) the raw bitmap data. + img = QImage(dataPtr, bw, bh, QImage::Format_ARGB32, gfree, dataPtr); } delete splash_output; #endif -- 2.4.5 From 9ac656a014855428af48ce98f4fea8de1e286fdd Mon Sep 17 00:00:00 2001 From: Adam Reichold <[email protected]> Date: Thu, 2 Jul 2015 21:15:39 +0200 Subject: [PATCH 4/5] Add KeepAlphaChannel render flag to Qt4 frontend Replicates the Qt5 frontend's KeepAlphaChannel flag providing the same interface and functionality. --- qt4/src/poppler-page.cc | 6 ++++-- qt4/src/poppler-qt4.h | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/qt4/src/poppler-page.cc b/qt4/src/poppler-page.cc index 49ad871..55abf8a 100644 --- a/qt4/src/poppler-page.cc +++ b/qt4/src/poppler-page.cc @@ -331,13 +331,15 @@ 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 keepAlphaChannel = m_page->parentDoc->m_hints & Document::KeepAlphaChannel; + SplashOutputDev * splash_output = new SplashOutputDev( #if defined(SPLASH_CMYK) (overprint) ? splashModeDeviceN8 : splashModeXBGR8, #else splashModeXBGR8, #endif - 4, gFalse, bgColor, gTrue, thinLineMode, overprint); + 4, gFalse, keepAlphaChannel ? NULL : bgColor, gTrue, thinLineMode, overprint); splash_output->setFontAntialias(m_page->parentDoc->m_hints & Document::TextAntialiasing ? gTrue : gFalse); splash_output->setVectorAntialias(m_page->parentDoc->m_hints & Document::Antialiasing ? gTrue : gFalse); @@ -354,7 +356,7 @@ QImage Page::renderToImage(double xres, double yres, int x, int y, int w, int h, int bw = bitmap->getWidth(); int bh = bitmap->getHeight(); - if (bitmap->convertToXBGR()) + if (bitmap->convertToXBGR(keepAlphaChannel)) { SplashColorPtr dataPtr = bitmap->getDataPtr(); diff --git a/qt4/src/poppler-qt4.h b/qt4/src/poppler-qt4.h index e5e808d..b4494e3 100644 --- a/qt4/src/poppler-qt4.h +++ b/qt4/src/poppler-qt4.h @@ -901,7 +901,8 @@ delete it; TextSlightHinting = 0x00000008, ///< Lighter hinting for text when combined with TextHinting \since 0.18 OverprintPreview = 0x00000010, ///< Overprint preview \since 0.22 ThinLineSolid = 0x00000020, ///< Enhance thin lines solid \since 0.24 - ThinLineShape = 0x00000040 ///< Enhance thin lines shape. Wins over ThinLineSolid \since 0.24 + ThinLineShape = 0x00000040, ///< Enhance thin lines shape. Wins over ThinLineSolid \since 0.24 + KeepAlphaChannel = 0x00000080 ///< Do not compose with the paper color \since 0.34 }; Q_DECLARE_FLAGS( RenderHints, RenderHint ) -- 2.4.5 From 57c2fe8cb94a846f8baa395fa29adf11c6d5ac27 Mon Sep 17 00:00:00 2001 From: Adam Reichold <[email protected]> Date: Fri, 3 Jul 2015 00:31:56 +0200 Subject: [PATCH 5/5] Switch default image format of Qt5 frontend This changes the Poppler::Page::renderToImage method w.r.t. to the image formats used to render using Splash, i.e. the default will be RGB8. If overprint preview is requested, DeviceN8 will be used and converted to XBGR8 for display. If the internal alpha channel is requested, XBGR8 will be used and augmented by Splash's separate alpha channel. This yields some improvements w.r.t. to rendering including alpha blending with the paper colour, i.e. synthetic benchmarks using structurally simple documents yield more than two percent improvement. --- qt5/src/poppler-page.cc | 99 +++++++++++++++++++++++++++++++------------------ 1 file changed, 62 insertions(+), 37 deletions(-) diff --git a/qt5/src/poppler-page.cc b/qt5/src/poppler-page.cc index d2fa3dd..f80336a 100644 --- a/qt5/src/poppler-page.cc +++ b/qt5/src/poppler-page.cc @@ -294,10 +294,10 @@ QImage Page::renderToImage(double xres, double yres, int x, int y, int w, int h, { #if defined(HAVE_SPLASH) SplashColor bgColor; - GBool overprint = gFalse; + GBool overprintPreview = gFalse; #if defined(SPLASH_CMYK) - overprint = m_page->parentDoc->m_hints & Document::OverprintPreview ? gTrue : gFalse; - if (overprint) + overprintPreview = m_page->parentDoc->m_hints & Document::OverprintPreview ? gTrue : gFalse; + if (overprintPreview) { Guchar c, m, y, k; @@ -326,58 +326,83 @@ QImage Page::renderToImage(double xres, double yres, int x, int y, int w, int h, bgColor[1] = m_page->parentDoc->paperColor.green(); bgColor[2] = m_page->parentDoc->paperColor.red(); } + + SplashColorMode colorMode = splashModeRGB8; + const bool keepAlphaChannel = m_page->parentDoc->m_hints & Document::KeepAlphaChannel; + if (keepAlphaChannel) colorMode = splashModeXBGR8; + +#if defined(SPLASH_CMYK) + if (overprintPreview) colorMode = splashModeDeviceN8; +#endif + SplashThinLineMode thinLineMode = splashThinLineDefault; if (m_page->parentDoc->m_hints & Document::ThinLineShape) thinLineMode = splashThinLineShape; if (m_page->parentDoc->m_hints & Document::ThinLineSolid) thinLineMode = splashThinLineSolid; - const bool keepAlphaChannel = m_page->parentDoc->m_hints & Document::KeepAlphaChannel; - - SplashOutputDev * splash_output = new SplashOutputDev( -#if defined(SPLASH_CMYK) - (overprint) ? splashModeDeviceN8 : splashModeXBGR8, -#else - splashModeXBGR8, -#endif - 4, gFalse, keepAlphaChannel ? NULL : bgColor, gTrue, thinLineMode, overprint); + SplashOutputDev *splash_output = new SplashOutputDev( + colorMode, 4, + gFalse, + keepAlphaChannel ? NULL : bgColor, + gTrue, + thinLineMode, + overprintPreview); splash_output->setFontAntialias(m_page->parentDoc->m_hints & Document::TextAntialiasing ? gTrue : gFalse); splash_output->setVectorAntialias(m_page->parentDoc->m_hints & Document::Antialiasing ? gTrue : gFalse); splash_output->setFreeTypeHinting(m_page->parentDoc->m_hints & Document::TextHinting ? gTrue : gFalse, m_page->parentDoc->m_hints & Document::TextSlightHinting ? gTrue : gFalse); - splash_output->startDoc(m_page->parentDoc->doc); + splash_output->startDoc(m_page->parentDoc->doc); m_page->parentDoc->doc->displayPageSlice(splash_output, m_page->index + 1, xres, yres, rotation, false, true, false, x, y, w, h, NULL, NULL, NULL, NULL, gTrue); SplashBitmap *bitmap = splash_output->getBitmap(); - int bw = bitmap->getWidth(); - int bh = bitmap->getHeight(); - - if (bitmap->convertToXBGR(keepAlphaChannel)) - { - SplashColorPtr dataPtr = bitmap->takeData(); - - if (QSysInfo::BigEndian == QSysInfo::ByteOrder) - { - uchar c; - int count = bw * bh * 4; - for (int k = 0; k < count; k += 4) - { - c = dataPtr[k]; - dataPtr[k] = dataPtr[k+3]; - dataPtr[k+3] = c; - - c = dataPtr[k+1]; - dataPtr[k+1] = dataPtr[k+2]; - dataPtr[k+2] = c; - } - } - // Construct a Qt image holding (and also owning) the raw bitmap data. - img = QImage(dataPtr, bw, bh, QImage::Format_ARGB32, gfree, dataPtr); + const int bw = bitmap->getWidth(); + const int bh = bitmap->getHeight(); + const int brs = bitmap->getRowSize(); + + // If we use DeviceN8, convert to XBGR8. + // If requested, also transfer Splash's internal alpha channel. + if (overprintPreview || keepAlphaChannel) { + if (bitmap->convertToXBGR(keepAlphaChannel)) { + 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]); + } + } + } + + // Construct a Qt image holding (and also owning) the raw bitmap data. + img = QImage(data, bw, bh, brs, QImage::Format_ARGB32, gfree, data); + } + } + else { + SplashColorPtr data = bitmap->takeData(); + + if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { + // Convert byte order from BGR to RGB. + 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]); + } + } + } + + // Construct a Qt image holding (and also owning) the raw bitmap data. + img = QImage(data, bw, bh, brs, QImage::Format_RGB888, gfree, data); } delete splash_output; #endif -- 2.4.5
signature.asc
Description: OpenPGP digital signature
_______________________________________________ poppler mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/poppler
