Fix alpha handling of QImage::setPixel
It was treated differently depending on format, made it consistently behave the same for all formats (following the behavior of the primary formats). Pick-to: 6.1 6.0 5.15 Change-Id: Ie24e19957d076fdf3ebd333074e26ede187489eb Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
This commit is contained in:
parent
b3544bfd46
commit
c32cd44d34
@ -2486,7 +2486,7 @@ void QImage::setPixel(int x, int y, uint index_or_rgb)
|
|||||||
((uint *)s)[x] = index_or_rgb;
|
((uint *)s)[x] = index_or_rgb;
|
||||||
return;
|
return;
|
||||||
case Format_RGB16:
|
case Format_RGB16:
|
||||||
((quint16 *)s)[x] = qConvertRgb32To16(qUnpremultiply(index_or_rgb));
|
((quint16 *)s)[x] = qConvertRgb32To16(index_or_rgb);
|
||||||
return;
|
return;
|
||||||
case Format_RGBX8888:
|
case Format_RGBX8888:
|
||||||
((uint *)s)[x] = ARGB2RGBA(0xff000000 | index_or_rgb);
|
((uint *)s)[x] = ARGB2RGBA(0xff000000 | index_or_rgb);
|
||||||
@ -2507,6 +2507,10 @@ void QImage::setPixel(int x, int y, uint index_or_rgb)
|
|||||||
case Format_A2RGB30_Premultiplied:
|
case Format_A2RGB30_Premultiplied:
|
||||||
((uint *)s)[x] = qConvertArgb32ToA2rgb30<PixelOrderRGB>(index_or_rgb);
|
((uint *)s)[x] = qConvertArgb32ToA2rgb30<PixelOrderRGB>(index_or_rgb);
|
||||||
return;
|
return;
|
||||||
|
case Format_RGBA64:
|
||||||
|
case Format_RGBA64_Premultiplied:
|
||||||
|
((QRgba64 *)s)[x] = QRgba64::fromArgb32(index_or_rgb);
|
||||||
|
return;
|
||||||
case Format_Invalid:
|
case Format_Invalid:
|
||||||
case NImageFormats:
|
case NImageFormats:
|
||||||
Q_ASSERT(false);
|
Q_ASSERT(false);
|
||||||
@ -2516,6 +2520,9 @@ void QImage::setPixel(int x, int y, uint index_or_rgb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const QPixelLayout *layout = &qPixelLayouts[d->format];
|
const QPixelLayout *layout = &qPixelLayouts[d->format];
|
||||||
|
if (!hasAlphaChannel())
|
||||||
|
layout->storeFromRGB32(s, &index_or_rgb, x, 1, nullptr, nullptr);
|
||||||
|
else
|
||||||
layout->storeFromARGB32PM(s, &index_or_rgb, x, 1, nullptr, nullptr);
|
layout->storeFromARGB32PM(s, &index_or_rgb, x, 1, nullptr, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1333,7 +1333,7 @@ static void QT_FASTCALL storeRGB64FromRGB32(uchar *dest, const uint *src, int in
|
|||||||
{
|
{
|
||||||
QRgba64 *d = reinterpret_cast<QRgba64 *>(dest) + index;
|
QRgba64 *d = reinterpret_cast<QRgba64 *>(dest) + index;
|
||||||
for (int i = 0; i < count; ++i)
|
for (int i = 0; i < count; ++i)
|
||||||
d[i] = QRgba64::fromArgb32(src[i]);
|
d[i] = QRgba64::fromArgb32(src[i] | 0xff000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const uint *QT_FASTCALL fetchRGBA64ToARGB32PM(uint *buffer, const uchar *src, int index, int count,
|
static const uint *QT_FASTCALL fetchRGBA64ToARGB32PM(uint *buffer, const uchar *src, int index, int count,
|
||||||
@ -1345,12 +1345,24 @@ static const uint *QT_FASTCALL fetchRGBA64ToARGB32PM(uint *buffer, const uchar *
|
|||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<bool Mask>
|
||||||
static void QT_FASTCALL storeRGBA64FromARGB32PM(uchar *dest, const uint *src, int index, int count,
|
static void QT_FASTCALL storeRGBA64FromARGB32PM(uchar *dest, const uint *src, int index, int count,
|
||||||
const QList<QRgb> *, QDitherInfo *)
|
const QList<QRgb> *, QDitherInfo *)
|
||||||
{
|
{
|
||||||
QRgba64 *d = reinterpret_cast<QRgba64 *>(dest) + index;
|
QRgba64 *d = reinterpret_cast<QRgba64 *>(dest) + index;
|
||||||
for (int i = 0; i < count; ++i)
|
for (int i = 0; i < count; ++i) {
|
||||||
d[i] = QRgba64::fromArgb32(src[i]).unpremultiplied();
|
d[i] = QRgba64::fromArgb32(src[i]).unpremultiplied();
|
||||||
|
if (Mask)
|
||||||
|
d[i].setAlpha(65535);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void QT_FASTCALL storeRGBA64FromARGB32(uchar *dest, const uint *src, int index, int count,
|
||||||
|
const QList<QRgb> *, QDitherInfo *)
|
||||||
|
{
|
||||||
|
QRgba64 *d = reinterpret_cast<QRgba64 *>(dest) + index;
|
||||||
|
for (int i = 0; i < count; ++i)
|
||||||
|
d[i] = QRgba64::fromArgb32(src[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note:
|
// Note:
|
||||||
@ -1437,15 +1449,15 @@ QPixelLayout qPixelLayouts[QImage::NImageFormats] = {
|
|||||||
{ false, false, QPixelLayout::BPP64, rbSwap_4x16,
|
{ false, false, QPixelLayout::BPP64, rbSwap_4x16,
|
||||||
convertPassThrough, nullptr,
|
convertPassThrough, nullptr,
|
||||||
fetchRGB64ToRGB32, fetchPassThrough64,
|
fetchRGB64ToRGB32, fetchPassThrough64,
|
||||||
storeRGB64FromRGB32, storeRGB64FromRGB32 }, // Format_RGBX64
|
storeRGBA64FromARGB32PM<true>, storeRGB64FromRGB32 }, // Format_RGBX64
|
||||||
{ true, false, QPixelLayout::BPP64, rbSwap_4x16,
|
{ true, false, QPixelLayout::BPP64, rbSwap_4x16,
|
||||||
convertARGB32ToARGB32PM, nullptr,
|
convertARGB32ToARGB32PM, nullptr,
|
||||||
fetchRGBA64ToARGB32PM, fetchRGBA64ToRGBA64PM,
|
fetchRGBA64ToARGB32PM, fetchRGBA64ToRGBA64PM,
|
||||||
storeRGBA64FromARGB32PM, storeRGB64FromRGB32 }, // Format_RGBA64
|
storeRGBA64FromARGB32PM<false>, storeRGB64FromRGB32 }, // Format_RGBA64
|
||||||
{ true, true, QPixelLayout::BPP64, rbSwap_4x16,
|
{ true, true, QPixelLayout::BPP64, rbSwap_4x16,
|
||||||
convertPassThrough, nullptr,
|
convertPassThrough, nullptr,
|
||||||
fetchRGB64ToRGB32, fetchPassThrough64,
|
fetchRGB64ToRGB32, fetchPassThrough64,
|
||||||
storeRGB64FromRGB32, storeRGB64FromRGB32 }, // Format_RGBA64_Premultiplied
|
storeRGBA64FromARGB32, storeRGB64FromRGB32 }, // Format_RGBA64_Premultiplied
|
||||||
{ false, false, QPixelLayout::BPP16, nullptr,
|
{ false, false, QPixelLayout::BPP16, nullptr,
|
||||||
convertGrayscale16ToRGB32, convertGrayscale16ToRGBA64,
|
convertGrayscale16ToRGB32, convertGrayscale16ToRGBA64,
|
||||||
fetchGrayscale16ToRGB32, fetchGrayscale16ToRGBA64,
|
fetchGrayscale16ToRGB32, fetchGrayscale16ToRGBA64,
|
||||||
|
@ -102,6 +102,10 @@ private slots:
|
|||||||
|
|
||||||
void setPixel_data();
|
void setPixel_data();
|
||||||
void setPixel();
|
void setPixel();
|
||||||
|
void setPixelWithAlpha_data();
|
||||||
|
void setPixelWithAlpha();
|
||||||
|
void setPixelColorWithAlpha_data();
|
||||||
|
void setPixelColorWithAlpha();
|
||||||
|
|
||||||
void defaultColorTable_data();
|
void defaultColorTable_data();
|
||||||
void defaultColorTable();
|
void defaultColorTable();
|
||||||
@ -1457,6 +1461,62 @@ void tst_QImage::setPixel()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QImage::setPixelWithAlpha_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::setPixelWithAlpha()
|
||||||
|
{
|
||||||
|
QFETCH(QImage::Format, format);
|
||||||
|
QImage image(1, 1, format);
|
||||||
|
QRgb referenceColor = qRgba(0, 170, 85, 170);
|
||||||
|
image.setPixel(0, 0, referenceColor);
|
||||||
|
|
||||||
|
if (!image.hasAlphaChannel())
|
||||||
|
referenceColor = 0xff000000 | 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::setPixelColorWithAlpha_data()
|
||||||
|
{
|
||||||
|
setPixelWithAlpha_data();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QImage::setPixelColorWithAlpha()
|
||||||
|
{
|
||||||
|
QFETCH(QImage::Format, format);
|
||||||
|
QImage image(1, 1, format);
|
||||||
|
image.setPixelColor(0, 0, QColor(170, 85, 255, 170));
|
||||||
|
QRgb referenceColor = qRgba(170, 85, 255, 170);
|
||||||
|
|
||||||
|
if (!image.hasAlphaChannel())
|
||||||
|
referenceColor = 0xff000000 | referenceColor;
|
||||||
|
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::convertToFormatPreserveDotsPrMeter()
|
void tst_QImage::convertToFormatPreserveDotsPrMeter()
|
||||||
{
|
{
|
||||||
QImage img(100, 100, QImage::Format_ARGB32_Premultiplied);
|
QImage img(100, 100, QImage::Format_ARGB32_Premultiplied);
|
||||||
@ -2352,17 +2412,7 @@ void tst_QImage::fillColor()
|
|||||||
|
|
||||||
void tst_QImage::fillColorWithAlpha_data()
|
void tst_QImage::fillColorWithAlpha_data()
|
||||||
{
|
{
|
||||||
QTest::addColumn<QImage::Format>("format");
|
setPixelWithAlpha_data();
|
||||||
|
|
||||||
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()
|
||||||
|
Loading…
Reference in New Issue
Block a user