Title: [153522] trunk/Source/WebCore
Revision
153522
Author
[email protected]
Date
2013-07-31 07:39:38 -0700 (Wed, 31 Jul 2013)

Log Message

[Qt] Images are down-scaled badly
https://bugs.webkit.org/show_bug.cgi?id=119263

Reviewed by Jocelyn Turcotte.

QPainter only does bilinear filtering, which means it will downscaling beyond
0.5x will start skipping pixel and start to degrade the end result. Scaling in
QImage and QPixmap however uses a better but much more expensive sampling that
counts all pixels.

To get the high quality downscaling we must therefore prescale the images before
painting them. To avoid a performance impact on repeated paints the prescaled
image are saved in the QPixmapCache.

* platform/graphics/qt/ImageQt.cpp:
(WebCore::BitmapImage::draw):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (153521 => 153522)


--- trunk/Source/WebCore/ChangeLog	2013-07-31 14:35:07 UTC (rev 153521)
+++ trunk/Source/WebCore/ChangeLog	2013-07-31 14:39:38 UTC (rev 153522)
@@ -1,3 +1,22 @@
+2013-07-31  Allan Sandfeld Jensen  <[email protected]>
+
+        [Qt] Images are down-scaled badly
+        https://bugs.webkit.org/show_bug.cgi?id=119263
+
+        Reviewed by Jocelyn Turcotte.
+
+        QPainter only does bilinear filtering, which means it will downscaling beyond
+        0.5x will start skipping pixel and start to degrade the end result. Scaling in
+        QImage and QPixmap however uses a better but much more expensive sampling that
+        counts all pixels.
+
+        To get the high quality downscaling we must therefore prescale the images before
+        painting them. To avoid a performance impact on repeated paints the prescaled
+        image are saved in the QPixmapCache.
+
+        * platform/graphics/qt/ImageQt.cpp:
+        (WebCore::BitmapImage::draw):
+
 2013-07-31  Grzegorz Czajkowski  <[email protected]>
 
         Remove guessesVector param from isUngrammatical

Modified: trunk/Source/WebCore/platform/graphics/qt/ImageQt.cpp (153521 => 153522)


--- trunk/Source/WebCore/platform/graphics/qt/ImageQt.cpp	2013-07-31 14:35:07 UTC (rev 153521)
+++ trunk/Source/WebCore/platform/graphics/qt/ImageQt.cpp	2013-07-31 14:39:38 UTC (rev 153522)
@@ -47,7 +47,9 @@
 #include <QImageReader>
 #include <QPainter>
 #include <QPixmap>
+#include <QPixmapCache>
 #include <QTransform>
+#include <private/qhexstring_p.h>
 
 #include <math.h>
 
@@ -245,6 +247,7 @@
     QPixmap* image = nativeImageForCurrentFrame();
     if (!image)
         return;
+    QPixmap prescaled;
 
     if (mayFillWithSolidColor()) {
         fillWithSolidColor(ctxt, normalizedDst, solidColor(), styleColorSpace, op);
@@ -255,6 +258,37 @@
     normalizedSrc = adjustSourceRectForDownSampling(normalizedSrc, image->size());
 #endif
 
+    QPainter* painter = ctxt->platformContext();
+    // The quality of down scaling at 0.5x and below in QPainter is not very good
+    // due only using bilinear sampling, so for high quality scaling we need to
+    // perform scaling ourselves.
+#if QT_VERSION >= QT_VERSION_CHECK(5, 1, 0)
+    const float pixelRatio = painter->device()->devicePixelRatio();
+#else
+    const float pixelRatio = 1;
+#endif
+    if (painter->renderHints() & QPainter::SmoothPixmapTransform
+        && (normalizedDst.width() * 2 * pixelRatio < normalizedSrc.width()
+            || normalizedDst.height() * 2 * pixelRatio < normalizedSrc.height())) {
+        // This may not work right with subpixel positions, but that can not currently happen.
+        QRect pixelSrc = normalizedSrc.toRect();
+        QSize scaledSize(normalizedDst.width() * pixelRatio, normalizedDst.height() * pixelRatio);
+        QString key = QStringLiteral("qtwebkit_prescaled_")
+            % HexString<qint64>(image->cacheKey())
+            % HexString<int>(pixelSrc.x()) % HexString<int>(pixelSrc.y())
+            % HexString<int>(pixelSrc.width()) % HexString<int>(pixelSrc.height())
+            % HexString<int>(scaledSize.width()) % HexString<int>(scaledSize.height());
+        if (!QPixmapCache::find(key, &prescaled)) {
+            if (pixelSrc != image->rect())
+                prescaled = image->copy(pixelSrc).scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+            else
+                prescaled = image->scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+            QPixmapCache::insert(key, prescaled);
+        }
+        normalizedSrc = QRectF(QPointF(), prescaled.size());
+        image = &prescaled;
+    }
+
     CompositeOperator previousOperator = ctxt->compositeOperation();
     ctxt->setCompositeOperation(!image->hasAlpha() && op == CompositeSourceOver ? CompositeCopy : op);
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to