summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@digia.com>2014-01-23 16:09:20 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-01-29 08:54:55 +0100
commit0226795cf33363a872c777034e0d8934ffaa3819 (patch)
treee65b5dac925c965754ac03928e54ec566504ec2b
parentfa83803119296c2224cf1c7fb7474057a77aa51b (diff)
Round evenly in INV_PREMUL
Currently INV_PREMUL rounds strictly down. While PREMUL rounds evenly. This patch adds 0x8000 to the intermediate results in INV_PREMUL before right shifting, thereby achieving even rounding. The rounding also makes PREMUL(INV_PREMUL()) into an identify operation, which means we can safely convert ARGB32PM to ARGB32 and back without ever losing color details. A test is added to verify this. Change-Id: I1267e109caddcff0c01d726cb5c1c1e9fa5f7996 Reviewed-by: Gunnar Sletta <gunnar.sletta@jollamobile.com>
-rw-r--r--src/gui/painting/qdrawhelper_p.h3
-rw-r--r--tests/auto/gui/image/qimage/tst_qimage.cpp22
2 files changed, 24 insertions, 1 deletions
diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h
index 3c945338a6..0f98b07229 100644
--- a/src/gui/painting/qdrawhelper_p.h
+++ b/src/gui/painting/qdrawhelper_p.h
@@ -699,7 +699,8 @@ static Q_ALWAYS_INLINE uint INV_PREMUL(uint p) {
return 0;
// (p*(0x00ff00ff/alpha)) >> 16 == (p*255)/alpha for all p and alpha <= 256.
const uint invAlpha = 0x00ff00ffU / alpha;
- return qRgba((qRed(p)*invAlpha)>>16, (qGreen(p)*invAlpha)>>16, (qBlue(p)*invAlpha)>>16, alpha);
+ // We add 0x8000 to get even rounding. The rounding also ensures that PREMUL(INV_PREMUL(p)) == p for all p.
+ return qRgba((qRed(p)*invAlpha + 0x8000)>>16, (qGreen(p)*invAlpha + 0x8000)>>16, (qBlue(p)*invAlpha + 0x8000)>>16, alpha);
}
struct quint24 {
diff --git a/tests/auto/gui/image/qimage/tst_qimage.cpp b/tests/auto/gui/image/qimage/tst_qimage.cpp
index f7a672ad18..9ddf571dbd 100644
--- a/tests/auto/gui/image/qimage/tst_qimage.cpp
+++ b/tests/auto/gui/image/qimage/tst_qimage.cpp
@@ -166,6 +166,8 @@ private slots:
void deepCopyWhenPaintingActive();
void scaled_QTBUG19157();
+ void convertOverUnPreMul();
+
void cleanupFunctions();
};
@@ -2422,6 +2424,26 @@ void tst_QImage::scaled_QTBUG19157()
QVERIFY(!foo.isNull());
}
+void tst_QImage::convertOverUnPreMul()
+{
+ QImage image(256, 256, QImage::Format_ARGB32_Premultiplied);
+
+ for (int j = 0; j < 256; j++) {
+ for (int i = 0; i <= j; i++) {
+ image.setPixel(i, j, qRgba(i, i, i, j));
+ }
+ }
+
+ QImage image2 = image.convertToFormat(QImage::Format_ARGB32).convertToFormat(QImage::Format_ARGB32_Premultiplied);
+
+ for (int j = 0; j < 256; j++) {
+ for (int i = 0; i <= j; i++) {
+ QCOMPARE(qAlpha(image2.pixel(i, j)), qAlpha(image.pixel(i, j)));
+ QCOMPARE(qGray(image2.pixel(i, j)), qGray(image.pixel(i, j)));
+ }
+ }
+}
+
static void cleanupFunction(void* info)
{
bool *called = static_cast<bool*>(info);