Centralize conversion from unpremultiplied to premultiplied image format
Makes it possible to add new unpremultiplied formats later. Change-Id: Id998a2674ca9067a0e2a5f85c7baf04bcd9a9912 Reviewed-by: Marc Mutz <marc.mutz@qt.io>
This commit is contained in:
parent
a149b3fd53
commit
990d150fe5
@ -165,7 +165,7 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
|
||||
if (srcLayout->hasAlphaChannel && !srcLayout->premultiplied &&
|
||||
!destLayout->hasAlphaChannel && destLayout->storeFromRGB32) {
|
||||
// Avoid unnecessary premultiply and unpremultiply when converting from unpremultiplied src format.
|
||||
fetch = qPixelLayouts[src->format + 1].fetchToARGB32PM;
|
||||
fetch = qPixelLayouts[qt_toPremultipliedFormat(src->format)].fetchToARGB32PM;
|
||||
if (dest->format == QImage::Format_RGB32)
|
||||
store = storeRGB32FromARGB32;
|
||||
else
|
||||
@ -383,7 +383,7 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
|
||||
if (srcLayout->hasAlphaChannel && !srcLayout->premultiplied &&
|
||||
!destLayout->hasAlphaChannel && destLayout->storeFromRGB32) {
|
||||
// Avoid unnecessary premultiply and unpremultiply when converting from unpremultiplied src format.
|
||||
fetch = qPixelLayouts[data->format + 1].fetchToARGB32PM;
|
||||
fetch = qPixelLayouts[qt_toPremultipliedFormat(data->format)].fetchToARGB32PM;
|
||||
if (data->format == QImage::Format_RGB32)
|
||||
store = storeRGB32FromARGB32;
|
||||
else
|
||||
@ -485,9 +485,8 @@ bool convert_generic_inplace_over_rgb64(QImageData *data, QImage::Format dst_for
|
||||
if (srcLayout->hasAlphaChannel && !srcLayout->premultiplied &&
|
||||
destLayout->hasAlphaChannel && !destLayout->premultiplied) {
|
||||
// Avoid unnecessary premultiply and unpremultiply when converting between two unpremultiplied formats.
|
||||
// This abuses the fact unpremultiplied formats are always before their premultiplied counterparts.
|
||||
fetch = qPixelLayouts[data->format + 1].fetchToRGBA64PM;
|
||||
store = qStoreFromRGBA64PM[dst_format + 1];
|
||||
fetch = qPixelLayouts[qt_toPremultipliedFormat(data->format)].fetchToRGBA64PM;
|
||||
store = qStoreFromRGBA64PM[qt_toPremultipliedFormat(dst_format)];
|
||||
}
|
||||
|
||||
auto convertSegment = [=](int yStart, int yEnd) {
|
||||
@ -580,9 +579,8 @@ bool convert_generic_inplace_over_rgba32f(QImageData *data, QImage::Format dst_f
|
||||
if (srcLayout->hasAlphaChannel && !srcLayout->premultiplied &&
|
||||
destLayout->hasAlphaChannel && !destLayout->premultiplied) {
|
||||
// Avoid unnecessary premultiply and unpremultiply when converting between two unpremultiplied formats.
|
||||
// This abuses the fact unpremultiplied formats are always before their premultiplied counterparts.
|
||||
fetch = qFetchToRGBA32F[data->format + 1];
|
||||
store = qStoreFromRGBA32F[dst_format + 1];
|
||||
fetch = qFetchToRGBA32F[qt_toPremultipliedFormat(data->format)];
|
||||
store = qStoreFromRGBA32F[qt_toPremultipliedFormat(dst_format)];
|
||||
}
|
||||
|
||||
auto convertSegment = [=](int yStart, int yEnd) {
|
||||
@ -1323,7 +1321,7 @@ static void convert_ARGB32_to_RGBA64(QImageData *dest, const QImageData *src, Qt
|
||||
|
||||
const uchar *src_data = src->data;
|
||||
uchar *dest_data = dest->data;
|
||||
const FetchAndConvertPixelsFunc64 fetch = qPixelLayouts[src->format + 1].fetchToRGBA64PM;
|
||||
const FetchAndConvertPixelsFunc64 fetch = qPixelLayouts[qt_toPremultipliedFormat(src->format)].fetchToRGBA64PM;
|
||||
|
||||
for (int i = 0; i < src->height; ++i) {
|
||||
fetch(reinterpret_cast<QRgba64 *>(dest_data), src_data, 0, src->width, nullptr, nullptr);
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include <QtCore/private/qnumeric_p.h>
|
||||
#include <QtCore/qlist.h>
|
||||
#include <QtCore/qmap.h>
|
||||
#include <QtCore/qttypetraits.h>
|
||||
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
@ -315,6 +317,20 @@ inline QImage::Format qt_alphaVersion(QImage::Format format)
|
||||
return QImage::Format_ARGB32_Premultiplied;
|
||||
}
|
||||
|
||||
constexpr QImage::Format qt_toUnpremultipliedFormat(QImage::Format format)
|
||||
{
|
||||
// Assumes input is already a premultiplied format with an unpremultiplied counterpart
|
||||
// This abuses the fact unpremultiplied formats are always before their premultiplied counterparts.
|
||||
return static_cast<QImage::Format>(qToUnderlying(format) - 1);
|
||||
}
|
||||
|
||||
constexpr QImage::Format qt_toPremultipliedFormat(QImage::Format format)
|
||||
{
|
||||
// Assumes input is already an unpremultiplied format
|
||||
// This abuses the fact unpremultiplied formats are always before their premultiplied counterparts.
|
||||
return static_cast<QImage::Format>(qToUnderlying(format) + 1);
|
||||
}
|
||||
|
||||
inline bool qt_highColorPrecision(QImage::Format format, bool opaque = false)
|
||||
{
|
||||
// Formats with higher color precision than ARGB32_Premultiplied.
|
||||
|
@ -238,6 +238,9 @@ private slots:
|
||||
void fromMonoHBITMAP();
|
||||
#endif // Q_OS_WIN
|
||||
|
||||
void tofromPremultipliedFormat_data();
|
||||
void tofromPremultipliedFormat();
|
||||
|
||||
private:
|
||||
const QString m_prefix;
|
||||
};
|
||||
@ -4211,5 +4214,27 @@ void tst_QImage::fromMonoHBITMAP() // QTBUG-72343, corruption for mono bitmaps
|
||||
|
||||
#endif // Q_OS_WIN
|
||||
|
||||
void tst_QImage::tofromPremultipliedFormat_data()
|
||||
{
|
||||
QTest::addColumn<QImage::Format>("unpremul");
|
||||
QTest::addColumn<QImage::Format>("premul");
|
||||
|
||||
// Test all available formats with both premultiplied and unpremultiplied versions
|
||||
QTest::newRow("argb32") << QImage::Format_ARGB32 << QImage::Format_ARGB32_Premultiplied;
|
||||
QTest::newRow("rgba8888") << QImage::Format_RGBA8888 << QImage::Format_RGBA8888_Premultiplied;
|
||||
QTest::newRow("rgba64") << QImage::Format_RGBA64 << QImage::Format_RGBA64_Premultiplied;
|
||||
QTest::newRow("rgba16fpx4") << QImage::Format_RGBA16FPx4 << QImage::Format_RGBA16FPx4_Premultiplied;
|
||||
QTest::newRow("rgba32fpx4") << QImage::Format_RGBA32FPx4 << QImage::Format_RGBA32FPx4_Premultiplied;
|
||||
}
|
||||
|
||||
void tst_QImage::tofromPremultipliedFormat()
|
||||
{
|
||||
QFETCH(QImage::Format, unpremul);
|
||||
QFETCH(QImage::Format, premul);
|
||||
|
||||
QCOMPARE(qt_toPremultipliedFormat(unpremul), premul);
|
||||
QCOMPARE(qt_toUnpremultipliedFormat(premul), unpremul);
|
||||
}
|
||||
|
||||
QTEST_GUILESS_MAIN(tst_QImage)
|
||||
#include "tst_qimage.moc"
|
||||
|
Loading…
x
Reference in New Issue
Block a user