Fix QImage::fill with semi-transparent QColor

A few formats were not treating the input QColor correctly. Fixed and
added more exhaustive test.

Change-Id: I872aeeb45e518f9a34b4ac35642264821f9927f2
Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
(cherry picked from commit 95712c5e5438e4eb5cd205ab4659febf3192137a)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Allan Sandfeld Jensen 2021-02-10 16:26:25 +01:00 committed by Qt Cherry-pick Bot
parent f94fbaf80a
commit 1803f904bd
2 changed files with 40 additions and 17 deletions

View File

@ -1781,6 +1781,8 @@ void QImage::fill(const QColor &color)
if (!d) if (!d)
return; return;
QRgba64 opaque = color.rgba64();
opaque.setAlpha(65535);
switch (d->format) { switch (d->format) {
case QImage::Format_RGB32: case QImage::Format_RGB32:
case QImage::Format_ARGB32: case QImage::Format_ARGB32:
@ -1799,12 +1801,10 @@ void QImage::fill(const QColor &color)
fill(ARGB2RGBA(qPremultiply(color.rgba()))); fill(ARGB2RGBA(qPremultiply(color.rgba())));
break; break;
case QImage::Format_BGR30: case QImage::Format_BGR30:
case QImage::Format_A2BGR30_Premultiplied: fill(qConvertRgb64ToRgb30<PixelOrderBGR>(opaque));
fill(qConvertRgb64ToRgb30<PixelOrderBGR>(color.rgba64()));
break; break;
case QImage::Format_RGB30: case QImage::Format_RGB30:
case QImage::Format_A2RGB30_Premultiplied: fill(qConvertRgb64ToRgb30<PixelOrderRGB>(opaque));
fill(qConvertRgb64ToRgb30<PixelOrderRGB>(color.rgba64()));
break; break;
case QImage::Format_RGB16: case QImage::Format_RGB16:
fill((uint) qConvertRgb32To16(color.rgba())); fill((uint) qConvertRgb32To16(color.rgba()));
@ -1827,19 +1827,18 @@ void QImage::fill(const QColor &color)
else else
fill((uint) 0); fill((uint) 0);
break; break;
case QImage::Format_RGBX64: { case QImage::Format_RGBX64:
QRgba64 c = color.rgba64(); qt_rectfill<quint64>(reinterpret_cast<quint64*>(d->data), opaque,
c.setAlpha(65535);
qt_rectfill<quint64>(reinterpret_cast<quint64*>(d->data), c,
0, 0, d->width, d->height, d->bytes_per_line); 0, 0, d->width, d->height, d->bytes_per_line);
break; break;
}
case QImage::Format_RGBA64: case QImage::Format_RGBA64:
case QImage::Format_RGBA64_Premultiplied:
qt_rectfill<quint64>(reinterpret_cast<quint64*>(d->data), color.rgba64(), qt_rectfill<quint64>(reinterpret_cast<quint64*>(d->data), color.rgba64(),
0, 0, d->width, d->height, d->bytes_per_line); 0, 0, d->width, d->height, d->bytes_per_line);
break; break;
case QImage::Format_RGBA64_Premultiplied:
qt_rectfill<quint64>(reinterpret_cast<quint64 *>(d->data), color.rgba64().premultiplied(),
0, 0, d->width, d->height, d->bytes_per_line);
break;
default: { default: {
QPainter p(this); QPainter p(this);
p.setCompositionMode(QPainter::CompositionMode_Source); p.setCompositionMode(QPainter::CompositionMode_Source);

View File

@ -148,6 +148,7 @@ private slots:
void fillColor_data(); void fillColor_data();
void fillColor(); void fillColor();
void fillColorWithAlpha_data();
void fillColorWithAlpha(); void fillColorWithAlpha();
void fillRGB888(); void fillRGB888();
@ -2348,15 +2349,38 @@ void tst_QImage::fillColor()
} }
} }
void tst_QImage::fillColorWithAlpha_data()
{
QTest::addColumn<QImage::Format>("format");
for (int c = QImage::Format_RGB32; c < QImage::NImageFormats; ++c) {
if (c == QImage::Format_Grayscale8)
continue;
if (c == QImage::Format_Grayscale16)
continue;
if (c == QImage::Format_Alpha8)
continue;
QTest::newRow(qPrintable(formatToString(QImage::Format(c)))) << QImage::Format(c);
}
}
void tst_QImage::fillColorWithAlpha() void tst_QImage::fillColorWithAlpha()
{ {
QImage argb32(1, 1, QImage::Format_ARGB32); QFETCH(QImage::Format, format);
argb32.fill(QColor(255, 0, 0, 127)); QImage image(1, 1, format);
QCOMPARE(argb32.pixel(0, 0), qRgba(255, 0, 0, 127)); image.fill(QColor(255, 170, 85, 170));
QRgb referenceColor = qRgba(255, 170, 85, 170);
QImage argb32pm(1, 1, QImage::Format_ARGB32_Premultiplied); if (!image.hasAlphaChannel())
argb32pm.fill(QColor(255, 0, 0, 127)); referenceColor = 0xff000000 | referenceColor;
QCOMPARE(argb32pm.pixel(0, 0), 0x7f7f0000u); else if (image.pixelFormat().premultiplied() == QPixelFormat::Premultiplied)
referenceColor = qPremultiply(referenceColor);
QRgb color = image.pixel(0, 0);
QCOMPARE(qRed(color) & 0xf0, qRed(referenceColor) & 0xf0);
QCOMPARE(qGreen(color) & 0xf0, qGreen(referenceColor) & 0xf0);
QCOMPARE(qBlue(color) & 0xf0, qBlue(referenceColor) & 0xf0);
QCOMPARE(qAlpha(color) & 0xf0, qAlpha(referenceColor) & 0xf0);
} }
void tst_QImage::fillRGB888() void tst_QImage::fillRGB888()