diff --git a/src/gui/painting/qcolortransform.cpp b/src/gui/painting/qcolortransform.cpp index 958d2fd2db..698696877b 100644 --- a/src/gui/painting/qcolortransform.cpp +++ b/src/gui/painting/qcolortransform.cpp @@ -222,6 +222,48 @@ QRgba64 QColorTransform::map(QRgba64 rgba64) const return QRgba64::fromRgba64(c.x * 65535.f + 0.5f, c.y * 65535.f + 0.5f, c.z * 65535.f + 0.5f, rgba64.alpha()); } +/*! + Applies the color transformation on the QRgbaFloat16 value \a rgbafp16. + + The input should be opaque or unpremultiplied. + \since 6.4 +*/ +QRgbaFloat16 QColorTransform::map(QRgbaFloat16 rgbafp16) const +{ + if (!d) + return rgbafp16; + QColorVector c; + c.x = d->colorSpaceIn->trc[0].applyExtended(rgbafp16.r); + c.y = d->colorSpaceIn->trc[1].applyExtended(rgbafp16.g); + c.z = d->colorSpaceIn->trc[2].applyExtended(rgbafp16.b); + c = d->colorMatrix.map(c); + rgbafp16.r = d->colorSpaceOut->trc[0].applyInverseExtended(c.x); + rgbafp16.g = d->colorSpaceOut->trc[1].applyInverseExtended(c.y); + rgbafp16.b = d->colorSpaceOut->trc[2].applyInverseExtended(c.z); + return rgbafp16; +} + +/*! + Applies the color transformation on the QRgbaFloat32 value \a rgbafp32. + + The input should be opaque or unpremultiplied. + \since 6.4 +*/ +QRgbaFloat32 QColorTransform::map(QRgbaFloat32 rgbafp32) const +{ + if (!d) + return rgbafp32; + QColorVector c; + c.x = d->colorSpaceIn->trc[0].applyExtended(rgbafp32.r); + c.y = d->colorSpaceIn->trc[1].applyExtended(rgbafp32.g); + c.z = d->colorSpaceIn->trc[2].applyExtended(rgbafp32.b); + c = d->colorMatrix.map(c); + rgbafp32.r = d->colorSpaceOut->trc[0].applyInverseExtended(c.x); + rgbafp32.g = d->colorSpaceOut->trc[1].applyInverseExtended(c.y); + rgbafp32.b = d->colorSpaceOut->trc[2].applyInverseExtended(c.z); + return rgbafp32; +} + /*! Applies the color transformation on the QColor value \a color. diff --git a/src/gui/painting/qcolortransform.h b/src/gui/painting/qcolortransform.h index 14673fe924..02f15ee89f 100644 --- a/src/gui/painting/qcolortransform.h +++ b/src/gui/painting/qcolortransform.h @@ -14,6 +14,12 @@ class QColor; class QRgba64; class QColorSpacePrivate; class QColorTransformPrivate; +class qfloat16; +template +class QRgbaFloat; +typedef QRgbaFloat QRgbaFloat16; +typedef QRgbaFloat QRgbaFloat32; + QT_DECLARE_QESDP_SPECIALIZATION_DTOR_WITH_EXPORT(QColorTransformPrivate, Q_GUI_EXPORT) class QColorTransform @@ -35,6 +41,8 @@ public: Q_GUI_EXPORT QRgb map(QRgb argb) const; Q_GUI_EXPORT QRgba64 map(QRgba64 rgba64) const; + Q_GUI_EXPORT QRgbaFloat16 map(QRgbaFloat16 rgbafp16) const; + Q_GUI_EXPORT QRgbaFloat32 map(QRgbaFloat32 rgbafp32) const; Q_GUI_EXPORT QColor map(const QColor &color) const; friend bool operator==(const QColorTransform &ct1, const QColorTransform &ct2) diff --git a/src/gui/painting/qrgbafloat.h b/src/gui/painting/qrgbafloat.h index 04b2115399..a7cd2d70d3 100644 --- a/src/gui/painting/qrgbafloat.h +++ b/src/gui/painting/qrgbafloat.h @@ -94,6 +94,14 @@ public: const FastType ia = 1.0f / a; return QRgbaFloat{r * ia, g * ia, b * ia, a}; } + constexpr bool operator==(QRgbaFloat f) const + { + return r == f.r && g == f.g && b == f.b && a == f.a; + } + constexpr bool operator!=(QRgbaFloat f) const + { + return !(*this == f); + } }; typedef QRgbaFloat QRgbaFloat16; diff --git a/tests/auto/gui/painting/qcolortransform/tst_qcolortransform.cpp b/tests/auto/gui/painting/qcolortransform/tst_qcolortransform.cpp index 17f115c308..6fbf7ddf27 100644 --- a/tests/auto/gui/painting/qcolortransform/tst_qcolortransform.cpp +++ b/tests/auto/gui/painting/qcolortransform/tst_qcolortransform.cpp @@ -31,6 +31,7 @@ #include #include +#include #include class tst_QColorTransform : public QObject @@ -45,6 +46,10 @@ private slots: void mapRGB32(); void mapRGB64_data(); void mapRGB64(); + void mapRGBAFP16x4_data(); + void mapRGBAFP16x4(); + void mapRGBAFP32x4_data(); + void mapRGBAFP32x4(); void mapQColor_data(); void mapQColor(); void mapRGB32Prepared_data(); @@ -182,6 +187,94 @@ void tst_QColorTransform::mapRGB64() QCOMPARE(result.alpha(), 0xffff); } +void tst_QColorTransform::mapRGBAFP16x4_data() +{ + mapRGB32_data(); +} + +void tst_QColorTransform::mapRGBAFP16x4() +{ + QFETCH(QColorTransform, transform); + QFETCH(bool, sharesRed); + + QRgbaFloat16 testColor = QRgbaFloat16::fromRgba(128, 64, 32, 255); + QRgbaFloat16 result = transform.map(testColor); + QVERIFY(result.red() > result.green()); + QVERIFY(result.green() > result.blue()); + QCOMPARE(result.alpha(), 1.0f); + if (transform.isIdentity()) + QVERIFY(result == testColor); + else + QVERIFY(result != testColor); + + testColor = QRgbaFloat16{0.0f, 0.0f, 0.0f, 1.0f}; + result = transform.map(testColor); + QCOMPARE(result, testColor); + + testColor = QRgbaFloat16{1.0f, 1.0f, 1.0f, 1.0f}; + result = transform.map(testColor); + QCOMPARE(result, testColor); + + testColor = QRgbaFloat16{1.0f, 1.0f, 0.0f, 1.0f}; + result = transform.map(testColor); + QCOMPARE(result.alpha(), 1.0f); + if (sharesRed) + QCOMPARE(result.red(), 1.0f); + + testColor = QRgbaFloat16{0.0f, 1.0f, 1.0f, 1.0f}; + result = transform.map(testColor); + // QRgbaFloat16 might overflow blue if we convert to a smaller gamut: + QCOMPARE(result.blue16(), 65535); + QCOMPARE(result.alpha(), 1.0f); +} + +void tst_QColorTransform::mapRGBAFP32x4_data() +{ + mapRGB32_data(); +} + +void tst_QColorTransform::mapRGBAFP32x4() +{ + QFETCH(QColorTransform, transform); + QFETCH(bool, sharesRed); + + QRgbaFloat32 testColor = QRgbaFloat32::fromRgba(128, 64, 32, 255); + QRgbaFloat32 result = transform.map(testColor); + QVERIFY(result.red() > result.green()); + QVERIFY(result.green() > result.blue()); + QCOMPARE(result.alpha(), 1.0f); + if (transform.isIdentity()) + QVERIFY(result == testColor); + else + QVERIFY(result != testColor); + + testColor = QRgbaFloat32{0.0f, 0.0f, 0.0f, 1.0f}; + result = transform.map(testColor); + QCOMPARE(result.red(), 0.0f); + QCOMPARE(result.green(), 0.0f); + QCOMPARE(result.blue(), 0.0f); + QCOMPARE(result.alpha(), 1.0f); + + testColor = QRgbaFloat32{1.0f, 1.0f, 1.0f, 1.0f}; + result = transform.map(testColor); + QCOMPARE(result.red(), 1.0f); + QCOMPARE(result.green(), 1.0f); + QCOMPARE(result.blue(), 1.0f); + QCOMPARE(result.alpha(), 1.0f); + + testColor = QRgbaFloat32{1.0f, 1.0f, 0.0f, 1.0f}; + result = transform.map(testColor); + QCOMPARE(result.alpha(), 1.0f); + if (sharesRed) + QCOMPARE(result.red(), 1.0f); + + testColor = QRgbaFloat32{0.0f, 1.0f, 1.0f, 1.0f}; + result = transform.map(testColor); + // QRgbaFloat16 might overflow blue if we convert to a smaller gamut: + QCOMPARE(result.blue16(), 65535); + QCOMPARE(result.alpha(), 1.0f); +} + void tst_QColorTransform::mapQColor_data() { mapRGB32_data();