Custom color-space based on chromaticities
Change-Id: I7fa6efa8993aa2b79ea60b6a21bf57c4f67a120f Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
This commit is contained in:
parent
fe57936d8c
commit
78a7e54f8f
@ -52,6 +52,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include <QtGui/qtguiglobal.h>
|
#include <QtGui/qtguiglobal.h>
|
||||||
|
#include <QtCore/qpoint.h>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
@ -61,7 +62,13 @@ class QColorVector
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QColorVector() = default;
|
QColorVector() = default;
|
||||||
constexpr QColorVector(float x, float y, float z) : x(x), y(y), z(z), _unused(0.0f) { }
|
Q_DECL_CONSTEXPR QColorVector(float x, float y, float z) : x(x), y(y), z(z), _unused(0.0f) { }
|
||||||
|
explicit Q_DECL_CONSTEXPR QColorVector(const QPointF &chr) // from XY chromaticity
|
||||||
|
: x(chr.x() / chr.y())
|
||||||
|
, y(1.0f)
|
||||||
|
, z((1.0 - chr.x() - chr.y()) / chr.y())
|
||||||
|
, _unused(0.0f)
|
||||||
|
{ }
|
||||||
float x; // X, x or red
|
float x; // X, x or red
|
||||||
float y; // Y, y or green
|
float y; // Y, y or green
|
||||||
float z; // Z, Y or blue
|
float z; // Z, Y or blue
|
||||||
@ -69,11 +76,28 @@ public:
|
|||||||
|
|
||||||
friend inline bool operator==(const QColorVector &v1, const QColorVector &v2);
|
friend inline bool operator==(const QColorVector &v1, const QColorVector &v2);
|
||||||
friend inline bool operator!=(const QColorVector &v1, const QColorVector &v2);
|
friend inline bool operator!=(const QColorVector &v1, const QColorVector &v2);
|
||||||
|
bool isNull() const
|
||||||
|
{
|
||||||
|
return !x && !y && !z;
|
||||||
|
}
|
||||||
|
|
||||||
static constexpr QColorVector null() { return QColorVector(0.0f, 0.0f, 0.0f); }
|
static Q_DECL_CONSTEXPR QColorVector null() { return QColorVector(0.0f, 0.0f, 0.0f); }
|
||||||
// Common whitepoints on normalized XYZ form:
|
static bool isValidChromaticity(const QPointF &chr)
|
||||||
static constexpr QColorVector D50() { return QColorVector(0.96421f, 1.0f, 0.82519f); }
|
{
|
||||||
static constexpr QColorVector D65() { return QColorVector(0.95043f, 1.0f, 1.08890f); }
|
if (chr.x() < qreal(0.0) || chr.x() > qreal(1.0))
|
||||||
|
return false;
|
||||||
|
if (chr.y() <= qreal(0.0) || chr.y() > qreal(1.0))
|
||||||
|
return false;
|
||||||
|
if (chr.x() + chr.y() > qreal(1.0))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Common whitepoints:
|
||||||
|
static Q_DECL_CONSTEXPR QPointF D50Chromaticity() { return QPointF(0.34567, 0.35850); }
|
||||||
|
static Q_DECL_CONSTEXPR QPointF D65Chromaticity() { return QPointF(0.31271, 0.32902); }
|
||||||
|
static Q_DECL_CONSTEXPR QColorVector D50() { return QColorVector(D50Chromaticity()); }
|
||||||
|
static Q_DECL_CONSTEXPR QColorVector D65() { return QColorVector(D65Chromaticity()); }
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool operator==(const QColorVector &v1, const QColorVector &v2)
|
inline bool operator==(const QColorVector &v1, const QColorVector &v2)
|
||||||
@ -102,6 +126,10 @@ public:
|
|||||||
friend inline bool operator==(const QColorMatrix &m1, const QColorMatrix &m2);
|
friend inline bool operator==(const QColorMatrix &m1, const QColorMatrix &m2);
|
||||||
friend inline bool operator!=(const QColorMatrix &m1, const QColorMatrix &m2);
|
friend inline bool operator!=(const QColorMatrix &m1, const QColorMatrix &m2);
|
||||||
|
|
||||||
|
bool isNull() const
|
||||||
|
{
|
||||||
|
return r.isNull() && g.isNull() && b.isNull();
|
||||||
|
}
|
||||||
bool isValid() const
|
bool isValid() const
|
||||||
{
|
{
|
||||||
// A color matrix must be invertible
|
// A color matrix must be invertible
|
||||||
@ -167,6 +195,13 @@ public:
|
|||||||
{
|
{
|
||||||
return { { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f } };
|
return { { 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f }, { 0.0f, 0.0f, 1.0f } };
|
||||||
}
|
}
|
||||||
|
static QColorMatrix fromScale(QColorVector v)
|
||||||
|
{
|
||||||
|
return QColorMatrix { { v.x, 0.0f, 0.0f },
|
||||||
|
{ 0.0f, v.y, 0.0f },
|
||||||
|
{ 0.0f, 0.0f, v.z } };
|
||||||
|
}
|
||||||
|
// These are used to recognize matrices from ICC profiles:
|
||||||
static QColorMatrix toXyzFromSRgb()
|
static QColorMatrix toXyzFromSRgb()
|
||||||
{
|
{
|
||||||
return QColorMatrix { { 0.4360217452f, 0.2224751115f, 0.0139281144f },
|
return QColorMatrix { { 0.4360217452f, 0.2224751115f, 0.0139281144f },
|
||||||
|
@ -53,6 +53,102 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
QColorSpacePrimaries::QColorSpacePrimaries(QColorSpace::Gamut gamut)
|
||||||
|
{
|
||||||
|
switch (gamut) {
|
||||||
|
case QColorSpace::Gamut::SRgb:
|
||||||
|
redPoint = QPointF(0.640, 0.330);
|
||||||
|
greenPoint = QPointF(0.300, 0.600);
|
||||||
|
bluePoint = QPointF(0.150, 0.060);
|
||||||
|
whitePoint = QColorVector::D65Chromaticity();
|
||||||
|
break;
|
||||||
|
case QColorSpace::Gamut::DciP3D65:
|
||||||
|
redPoint = QPointF(0.680, 0.320);
|
||||||
|
greenPoint = QPointF(0.265, 0.690);
|
||||||
|
bluePoint = QPointF(0.150, 0.060);
|
||||||
|
whitePoint = QColorVector::D65Chromaticity();
|
||||||
|
break;
|
||||||
|
case QColorSpace::Gamut::Bt2020:
|
||||||
|
redPoint = QPointF(0.708, 0.292);
|
||||||
|
greenPoint = QPointF(0.190, 0.797);
|
||||||
|
bluePoint = QPointF(0.131, 0.046);
|
||||||
|
whitePoint = QColorVector::D65Chromaticity();
|
||||||
|
break;
|
||||||
|
case QColorSpace::Gamut::AdobeRgb:
|
||||||
|
redPoint = QPointF(0.640, 0.330);
|
||||||
|
greenPoint = QPointF(0.210, 0.710);
|
||||||
|
bluePoint = QPointF(0.150, 0.060);
|
||||||
|
whitePoint = QColorVector::D65Chromaticity();
|
||||||
|
break;
|
||||||
|
case QColorSpace::Gamut::ProPhotoRgb:
|
||||||
|
redPoint = QPointF(0.7347, 0.2653);
|
||||||
|
greenPoint = QPointF(0.1596, 0.8404);
|
||||||
|
bluePoint = QPointF(0.0366, 0.0001);
|
||||||
|
whitePoint = QColorVector::D50Chromaticity();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Q_UNREACHABLE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QColorSpacePrimaries::areValid() const
|
||||||
|
{
|
||||||
|
if (!QColorVector::isValidChromaticity(redPoint))
|
||||||
|
return false;
|
||||||
|
if (!QColorVector::isValidChromaticity(greenPoint))
|
||||||
|
return false;
|
||||||
|
if (!QColorVector::isValidChromaticity(bluePoint))
|
||||||
|
return false;
|
||||||
|
if (!QColorVector::isValidChromaticity(whitePoint))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QColorMatrix QColorSpacePrimaries::toXyzMatrix() const
|
||||||
|
{
|
||||||
|
// This converts to XYZ in some undefined scale.
|
||||||
|
QColorMatrix toXyz = { QColorVector(redPoint),
|
||||||
|
QColorVector(greenPoint),
|
||||||
|
QColorVector(bluePoint) };
|
||||||
|
|
||||||
|
// Since the white point should be (1.0, 1.0, 1.0) in the
|
||||||
|
// input, we can figure out the scale by using the
|
||||||
|
// inverse conversion on the white point.
|
||||||
|
QColorVector wXyz(whitePoint);
|
||||||
|
QColorVector whiteScale = toXyz.inverted().map(wXyz);
|
||||||
|
|
||||||
|
// Now we have scaled conversion to XYZ relative to the given whitepoint
|
||||||
|
toXyz = toXyz * QColorMatrix::fromScale(whiteScale);
|
||||||
|
|
||||||
|
// But we want a conversion to XYZ relative to D50
|
||||||
|
QColorVector wXyzD50 = QColorVector::D50();
|
||||||
|
|
||||||
|
if (wXyz != wXyzD50) {
|
||||||
|
// Do chromatic adaptation to map our white point to XYZ D50.
|
||||||
|
|
||||||
|
// The Bradford method chromatic adaptation matrix:
|
||||||
|
QColorMatrix abrad = { { 0.8951f, -0.7502f, 0.0389f },
|
||||||
|
{ 0.2664f, 1.7135f, -0.0685f },
|
||||||
|
{ -0.1614f, 0.0367f, 1.0296f } };
|
||||||
|
QColorMatrix abradinv = { { 0.9869929f, 0.4323053f, -0.0085287f },
|
||||||
|
{ -0.1470543f, 0.5183603f, 0.0400428f },
|
||||||
|
{ 0.1599627f, 0.0492912f, 0.9684867f } };
|
||||||
|
|
||||||
|
QColorVector srcCone = abrad.map(wXyz);
|
||||||
|
QColorVector dstCone = abrad.map(wXyzD50);
|
||||||
|
|
||||||
|
QColorMatrix wToD50 = { { dstCone.x / srcCone.x, 0, 0 },
|
||||||
|
{ 0, dstCone.y / srcCone.y, 0 },
|
||||||
|
{ 0, 0, dstCone.z / srcCone.z } };
|
||||||
|
|
||||||
|
|
||||||
|
QColorMatrix chromaticAdaptation = abradinv * (wToD50 * abrad);
|
||||||
|
toXyz = chromaticAdaptation * toXyz;
|
||||||
|
}
|
||||||
|
|
||||||
|
return toXyz;
|
||||||
|
}
|
||||||
|
|
||||||
QColorSpacePrivate::QColorSpacePrivate()
|
QColorSpacePrivate::QColorSpacePrivate()
|
||||||
: id(QColorSpace::Unknown)
|
: id(QColorSpace::Unknown)
|
||||||
, gamut(QColorSpace::Gamut::Custom)
|
, gamut(QColorSpace::Gamut::Custom)
|
||||||
@ -128,6 +224,21 @@ QColorSpacePrivate::QColorSpacePrivate(QColorSpace::Gamut gamut, QColorSpace::Tr
|
|||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QColorSpacePrivate::QColorSpacePrivate(const QColorSpacePrimaries &primaries,
|
||||||
|
QColorSpace::TransferFunction fun,
|
||||||
|
float gamma)
|
||||||
|
: gamut(QColorSpace::Gamut::Custom)
|
||||||
|
, transferFunction(fun)
|
||||||
|
, gamma(gamma)
|
||||||
|
{
|
||||||
|
Q_ASSERT(primaries.areValid());
|
||||||
|
toXyz = primaries.toXyzMatrix();
|
||||||
|
whitePoint = QColorVector(primaries.whitePoint);
|
||||||
|
if (!identifyColorSpace())
|
||||||
|
id = QColorSpace::Unknown;
|
||||||
|
setTransferFunction();
|
||||||
|
}
|
||||||
|
|
||||||
bool QColorSpacePrivate::identifyColorSpace()
|
bool QColorSpacePrivate::identifyColorSpace()
|
||||||
{
|
{
|
||||||
switch (gamut) {
|
switch (gamut) {
|
||||||
@ -195,33 +306,14 @@ void QColorSpacePrivate::initialize()
|
|||||||
|
|
||||||
void QColorSpacePrivate::setToXyzMatrix()
|
void QColorSpacePrivate::setToXyzMatrix()
|
||||||
{
|
{
|
||||||
switch (gamut) {
|
if (gamut == QColorSpace::Gamut::Custom) {
|
||||||
case QColorSpace::Gamut::SRgb:
|
|
||||||
toXyz = QColorMatrix::toXyzFromSRgb();
|
|
||||||
whitePoint = QColorVector::D65();
|
|
||||||
return;
|
|
||||||
case QColorSpace::Gamut::AdobeRgb:
|
|
||||||
toXyz = QColorMatrix::toXyzFromAdobeRgb();
|
|
||||||
whitePoint = QColorVector::D65();
|
|
||||||
return;
|
|
||||||
case QColorSpace::Gamut::DciP3D65:
|
|
||||||
toXyz = QColorMatrix::toXyzFromDciP3D65();
|
|
||||||
whitePoint = QColorVector::D65();
|
|
||||||
return;
|
|
||||||
case QColorSpace::Gamut::ProPhotoRgb:
|
|
||||||
toXyz = QColorMatrix::toXyzFromProPhotoRgb();
|
|
||||||
whitePoint = QColorVector::D50();
|
|
||||||
return;
|
|
||||||
case QColorSpace::Gamut::Bt2020:
|
|
||||||
toXyz = QColorMatrix::toXyzFromBt2020();
|
|
||||||
whitePoint = QColorVector::D65();
|
|
||||||
return;
|
|
||||||
case QColorSpace::Gamut::Custom:
|
|
||||||
toXyz = QColorMatrix::null();
|
toXyz = QColorMatrix::null();
|
||||||
whitePoint = QColorVector::D50();
|
whitePoint = QColorVector::D50();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Q_UNREACHABLE();
|
QColorSpacePrimaries primaries(gamut);
|
||||||
|
toXyz = primaries.toXyzMatrix();
|
||||||
|
whitePoint = QColorVector(primaries.whitePoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QColorSpacePrivate::setTransferFunction()
|
void QColorSpacePrivate::setTransferFunction()
|
||||||
@ -386,6 +478,23 @@ QColorSpace::QColorSpace(QColorSpace::Gamut gamut, float gamma)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Creates a custom colorspace with a gamut based on the chromaticities of the primary colors \a whitePoint,
|
||||||
|
\a redPoint, \a greenPoint and \a bluePoint, and using the transfer function \a fun and optionally \a gamma.
|
||||||
|
*/
|
||||||
|
QColorSpace::QColorSpace(const QPointF &whitePoint, const QPointF &redPoint,
|
||||||
|
const QPointF &greenPoint, const QPointF &bluePoint,
|
||||||
|
QColorSpace::TransferFunction fun, float gamma)
|
||||||
|
{
|
||||||
|
QColorSpacePrimaries primaries(whitePoint, redPoint, greenPoint, bluePoint);
|
||||||
|
if (!primaries.areValid()) {
|
||||||
|
qWarning() << "QColorSpace attempted constructed from invalid primaries:" << whitePoint << redPoint << greenPoint << bluePoint;
|
||||||
|
d_ptr = QColorSpace(QColorSpace::Undefined).d_ptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
d_ptr = new QColorSpacePrivate(primaries, fun, gamma);
|
||||||
|
}
|
||||||
|
|
||||||
QColorSpace::~QColorSpace()
|
QColorSpace::~QColorSpace()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -85,6 +85,9 @@ public:
|
|||||||
QColorSpace(ColorSpaceId colorSpaceId = Undefined);
|
QColorSpace(ColorSpaceId colorSpaceId = Undefined);
|
||||||
QColorSpace(Gamut gamut, TransferFunction fun, float gamma = 0.0f);
|
QColorSpace(Gamut gamut, TransferFunction fun, float gamma = 0.0f);
|
||||||
QColorSpace(Gamut gamut, float gamma);
|
QColorSpace(Gamut gamut, float gamma);
|
||||||
|
QColorSpace(const QPointF &whitePoint, const QPointF &redPoint,
|
||||||
|
const QPointF &greenPoint, const QPointF &bluePoint,
|
||||||
|
TransferFunction fun, float gamma = 0.0f);
|
||||||
~QColorSpace();
|
~QColorSpace();
|
||||||
|
|
||||||
QColorSpace(QColorSpace &&colorSpace);
|
QColorSpace(QColorSpace &&colorSpace);
|
||||||
|
@ -57,15 +57,41 @@
|
|||||||
#include "qcolortrclut_p.h"
|
#include "qcolortrclut_p.h"
|
||||||
|
|
||||||
#include <QtCore/qshareddata.h>
|
#include <QtCore/qshareddata.h>
|
||||||
|
#include <QtCore/qpoint.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class Q_GUI_EXPORT QColorSpacePrimaries
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QColorSpacePrimaries() = default;
|
||||||
|
QColorSpacePrimaries(QColorSpace::Gamut gamut);
|
||||||
|
QColorSpacePrimaries(QPointF whitePoint,
|
||||||
|
QPointF redPoint,
|
||||||
|
QPointF greenPoint,
|
||||||
|
QPointF bluePoint)
|
||||||
|
: whitePoint(whitePoint)
|
||||||
|
, redPoint(redPoint)
|
||||||
|
, greenPoint(greenPoint)
|
||||||
|
, bluePoint(bluePoint)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
QColorMatrix toXyzMatrix() const;
|
||||||
|
bool areValid() const;
|
||||||
|
|
||||||
|
QPointF whitePoint;
|
||||||
|
QPointF redPoint;
|
||||||
|
QPointF greenPoint;
|
||||||
|
QPointF bluePoint;
|
||||||
|
};
|
||||||
|
|
||||||
class QColorSpacePrivate : public QSharedData
|
class QColorSpacePrivate : public QSharedData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QColorSpacePrivate();
|
QColorSpacePrivate();
|
||||||
QColorSpacePrivate(QColorSpace::ColorSpaceId colorSpaceId);
|
QColorSpacePrivate(QColorSpace::ColorSpaceId colorSpaceId);
|
||||||
QColorSpacePrivate(QColorSpace::Gamut gamut, QColorSpace::TransferFunction fun, float gamma);
|
QColorSpacePrivate(QColorSpace::Gamut gamut, QColorSpace::TransferFunction fun, float gamma);
|
||||||
|
QColorSpacePrivate(const QColorSpacePrimaries &primaries, QColorSpace::TransferFunction fun, float gamma);
|
||||||
QColorSpacePrivate(const QColorSpacePrivate &other) = default;
|
QColorSpacePrivate(const QColorSpacePrivate &other) = default;
|
||||||
QColorSpacePrivate &operator=(const QColorSpacePrivate &other) = default;
|
QColorSpacePrivate &operator=(const QColorSpacePrivate &other) = default;
|
||||||
|
|
||||||
|
@ -33,6 +33,8 @@
|
|||||||
#include <qimage.h>
|
#include <qimage.h>
|
||||||
#include <qimagereader.h>
|
#include <qimagereader.h>
|
||||||
|
|
||||||
|
#include <private/qcolorspace_p.h>
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(QColorSpace::ColorSpaceId)
|
Q_DECLARE_METATYPE(QColorSpace::ColorSpaceId)
|
||||||
Q_DECLARE_METATYPE(QColorSpace::Gamut)
|
Q_DECLARE_METATYPE(QColorSpace::Gamut)
|
||||||
Q_DECLARE_METATYPE(QColorSpace::TransferFunction)
|
Q_DECLARE_METATYPE(QColorSpace::TransferFunction)
|
||||||
@ -59,6 +61,10 @@ private slots:
|
|||||||
void loadImage();
|
void loadImage();
|
||||||
|
|
||||||
void gamut();
|
void gamut();
|
||||||
|
void primariesXyz();
|
||||||
|
void primaries2_data();
|
||||||
|
void primaries2();
|
||||||
|
void invalidPrimaries();
|
||||||
};
|
};
|
||||||
|
|
||||||
tst_QColorSpace::tst_QColorSpace()
|
tst_QColorSpace::tst_QColorSpace()
|
||||||
@ -289,5 +295,67 @@ void tst_QColorSpace::gamut()
|
|||||||
QVERIFY(tgreen.blueF() > 0.2);
|
QVERIFY(tgreen.blueF() > 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QColorSpace::primariesXyz()
|
||||||
|
{
|
||||||
|
QColorSpace sRgb = QColorSpace::SRgb;
|
||||||
|
QColorSpace adobeRgb = QColorSpace::AdobeRgb;
|
||||||
|
QColorSpace displayP3 = QColorSpace::DisplayP3;
|
||||||
|
QColorSpace proPhotoRgb = QColorSpace::ProPhotoRgb;
|
||||||
|
QColorSpace bt2020 = QColorSpace::Bt2020;
|
||||||
|
|
||||||
|
// Check if our calculated matrices, match the precalculated ones.
|
||||||
|
QCOMPARE(sRgb.d_func()->toXyz, QColorMatrix::toXyzFromSRgb());
|
||||||
|
QCOMPARE(adobeRgb.d_func()->toXyz, QColorMatrix::toXyzFromAdobeRgb());
|
||||||
|
QCOMPARE(displayP3.d_func()->toXyz, QColorMatrix::toXyzFromDciP3D65());
|
||||||
|
QCOMPARE(proPhotoRgb.d_func()->toXyz, QColorMatrix::toXyzFromProPhotoRgb());
|
||||||
|
QCOMPARE(bt2020.d_func()->toXyz, QColorMatrix::toXyzFromBt2020());
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QColorSpace::primaries2_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QColorSpace::Gamut>("gamut");
|
||||||
|
|
||||||
|
QTest::newRow("sRGB") << QColorSpace::Gamut::SRgb;
|
||||||
|
QTest::newRow("DCI-P3 (D65)") << QColorSpace::Gamut::DciP3D65;
|
||||||
|
QTest::newRow("Adobe RGB (1998)") << QColorSpace::Gamut::AdobeRgb;
|
||||||
|
QTest::newRow("ProPhoto RGB") << QColorSpace::Gamut::ProPhotoRgb;
|
||||||
|
QTest::newRow("BT.2020") << QColorSpace::Gamut::Bt2020;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QColorSpace::primaries2()
|
||||||
|
{
|
||||||
|
QFETCH(QColorSpace::Gamut, gamut);
|
||||||
|
QColorSpacePrimaries primaries(gamut);
|
||||||
|
|
||||||
|
QColorSpace original(gamut, QColorSpace::TransferFunction::Linear);
|
||||||
|
QColorSpace custom1(primaries.whitePoint, primaries.redPoint,
|
||||||
|
primaries.greenPoint, primaries.bluePoint, QColorSpace::TransferFunction::Linear);
|
||||||
|
QCOMPARE(original, custom1);
|
||||||
|
|
||||||
|
// A custom color swizzled color-space:
|
||||||
|
QColorSpace custom2(primaries.whitePoint, primaries.bluePoint,
|
||||||
|
primaries.greenPoint, primaries.redPoint, QColorSpace::TransferFunction::Linear);
|
||||||
|
|
||||||
|
QVERIFY(custom1 != custom2);
|
||||||
|
QColor color1(255, 127, 63);
|
||||||
|
QColor color2 = custom1.transformationToColorSpace(custom2).map(color1);
|
||||||
|
QCOMPARE(color2.red(), color1.blue());
|
||||||
|
QCOMPARE(color2.green(), color1.green());
|
||||||
|
QCOMPARE(color2.blue(), color1.red());
|
||||||
|
QCOMPARE(color2.alpha(), color1.alpha());
|
||||||
|
QColor color3 = custom2.transformationToColorSpace(custom1).map(color2);
|
||||||
|
QCOMPARE(color3.red(), color1.red());
|
||||||
|
QCOMPARE(color3.green(), color1.green());
|
||||||
|
QCOMPARE(color3.blue(), color1.blue());
|
||||||
|
QCOMPARE(color3.alpha(), color1.alpha());
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QColorSpace::invalidPrimaries()
|
||||||
|
{
|
||||||
|
QColorSpace custom(QPointF(), QPointF(), QPointF(), QPointF(), QColorSpace::TransferFunction::Linear);
|
||||||
|
QVERIFY(!custom.isValid());
|
||||||
|
QCOMPARE(custom.colorSpaceId(), QColorSpace::Undefined);
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_MAIN(tst_QColorSpace)
|
QTEST_MAIN(tst_QColorSpace)
|
||||||
#include "tst_qcolorspace.moc"
|
#include "tst_qcolorspace.moc"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user