QImage pixelColor and setPixelColor must use unpremultiplied QColor

QColor always uses unpremultiplied alpha, but the new QImage methods
were based on the QRgb versions which might be either. This patches fixes
the two new methods so they treat QColor alpha correctly.

Change-Id: I78a5b875ad4e78ad7fde3b811c6187482b4f6d15
Reviewed-by: Gunnar Sletta <gunnar@sletta.org>
bb10
Allan Sandfeld Jensen 2015-12-03 15:15:19 +01:00
parent 2366ecfb2d
commit c04e7dead8
2 changed files with 40 additions and 8 deletions

View File

@ -2380,17 +2380,25 @@ QColor QImage::pixelColor(int x, int y) const
return QColor();
}
QRgba64 c;
const uchar * s = constScanLine(y);
switch (d->format) {
case Format_BGR30:
case Format_A2BGR30_Premultiplied:
return QColor(qConvertA2rgb30ToRgb64<PixelOrderBGR>(reinterpret_cast<const quint32 *>(s)[x]));
c = qConvertA2rgb30ToRgb64<PixelOrderBGR>(reinterpret_cast<const quint32 *>(s)[x]);
break;
case Format_RGB30:
case Format_A2RGB30_Premultiplied:
return QColor(qConvertA2rgb30ToRgb64<PixelOrderRGB>(reinterpret_cast<const quint32 *>(s)[x]));
c = qConvertA2rgb30ToRgb64<PixelOrderRGB>(reinterpret_cast<const quint32 *>(s)[x]);
break;
default:
return QColor(pixel(x, y));
c = QRgba64::fromArgb32(pixel(x, y));
break;
}
// QColor is always unpremultiplied
if (hasAlphaChannel() && qPixelLayouts[d->format].premultiplied)
c = c.unpremultiplied();
return QColor(c);
}
/*!
@ -2421,6 +2429,12 @@ void QImage::setPixelColor(int x, int y, const QColor &color)
qWarning("QImage::setPixelColor: coordinate (%d,%d) out of range", x, y);
return;
}
// QColor is always unpremultiplied
QRgba64 c = color.rgba64();
if (!hasAlphaChannel())
c.setAlpha(65535);
else if (qPixelLayouts[d->format].premultiplied)
c = c.premultiplied();
// detach is called from within scanLine
uchar * s = scanLine(y);
switch (d->format) {
@ -2430,19 +2444,19 @@ void QImage::setPixelColor(int x, int y, const QColor &color)
qWarning("QImage::setPixelColor: called on monochrome or indexed format");
return;
case Format_BGR30:
((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderBGR>(color.rgba64()) | 0xc0000000;
((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderBGR>(c) | 0xc0000000;
return;
case Format_A2BGR30_Premultiplied:
((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderBGR>(color.rgba64());
((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderBGR>(c);
return;
case Format_RGB30:
((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderRGB>(color.rgba64()) | 0xc0000000;
((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderRGB>(c) | 0xc0000000;
return;
case Format_A2RGB30_Premultiplied:
((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderRGB>(color.rgba64());
((uint *)s)[x] = qConvertRgb64ToRgb30<PixelOrderRGB>(c);
return;
default:
setPixel(x, y, color.rgba());
setPixel(x, y, c.toArgb32());
return;
}
}

View File

@ -196,6 +196,8 @@ private slots:
void metadataPassthrough();
void pixelColor();
private:
const QString m_prefix;
};
@ -3020,5 +3022,21 @@ void tst_QImage::metadataPassthrough()
QCOMPARE(swapped.devicePixelRatio(), a.devicePixelRatio());
}
void tst_QImage::pixelColor()
{
QImage argb32(1, 1, QImage::Format_ARGB32);
QImage argb32pm(1, 1, QImage::Format_ARGB32_Premultiplied);
QColor c(Qt::red);
c.setAlpha(128);
argb32.setPixelColor(QPoint(0, 0), c);
argb32pm.setPixelColor(QPoint(0, 0), c);
QCOMPARE(argb32.pixelColor(QPoint(0, 0)), c);
QCOMPARE(argb32pm.pixelColor(QPoint(0, 0)), c);
QImage t = argb32.convertToFormat(QImage::Format_ARGB32_Premultiplied);
QCOMPARE(t.pixel(0,0), argb32pm.pixel(0,0));
}
QTEST_GUILESS_MAIN(tst_QImage)
#include "tst_qimage.moc"