summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2019-02-26 14:55:33 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-08-02 21:07:54 +0200
commit05251bca1dc5aabdd1e4548a1bf1bf757f615791 (patch)
tree377406bb433923001f2aa937eaf8fc89ecf23be7
parent092074f9df073c9af075810602d61ac54a115d89 (diff)
Add an easier way to change colorspaces
Adds setters for transfer-functions and primaries. This allows us to remove use of private QColorSpace API from the PNG handler. Change-Id: Ieeff81c813c253649500acd1e53f35247b872325 Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io>
-rw-r--r--src/gui/image/qpnghandler.cpp16
-rw-r--r--src/gui/painting/qcolorspace.cpp106
-rw-r--r--src/gui/painting/qcolorspace.h7
-rw-r--r--tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp47
4 files changed, 154 insertions, 22 deletions
diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp
index 3bf4e9db15..16d6c25b8b 100644
--- a/src/gui/image/qpnghandler.cpp
+++ b/src/gui/image/qpnghandler.cpp
@@ -53,7 +53,6 @@
#include <qcolorspace.h>
#include <private/qcolorspace_p.h>
-#include <private/qicc_p.h>
#include <png.h>
#include <pngconf.h>
@@ -681,10 +680,7 @@ bool QPngHandlerPrivate::readPngImage(QImage *outImage)
// This configuration forces gamma correction and
// thus changes the output colorspace
png_set_gamma(png_ptr, 1.0f / gamma, fileGamma);
- QColorSpacePrivate *csPrivate = QColorSpacePrivate::getWritable(colorSpace);
- csPrivate->transferFunction = QColorSpace::TransferFunction::Gamma;
- csPrivate->gamma = 1.0f / gamma;
- csPrivate->setTransferFunction();
+ colorSpace = colorSpace.withTransferFunction(QColorSpace::TransferFunction::Gamma, 1.0f / gamma);
colorSpaceState = GammaChrm;
}
@@ -984,14 +980,8 @@ bool QPNGImageWriter::writeImage(const QImage& image, volatile int compression_i
if (image.colorSpace().isValid()) {
QColorSpace cs = image.colorSpace();
// Support the old gamma making it override transferfunction.
- if (gamma != 0.0 && !qFuzzyCompare(cs.gamma(), 1.0f / gamma)) {
- QColorSpacePrivate *csPrivate = QColorSpacePrivate::getWritable(cs);
- csPrivate->transferFunction = QColorSpace::TransferFunction::Gamma;
- csPrivate->gamma = 1.0f / gamma;
- csPrivate->setTransferFunction();
- csPrivate->iccProfile.clear();
- csPrivate->description.clear();
- }
+ if (gamma != 0.0 && !qFuzzyCompare(cs.gamma(), 1.0f / gamma))
+ cs = cs.withTransferFunction(QColorSpace::TransferFunction::Gamma, 1.0f / gamma);
QByteArray iccProfileName = QColorSpacePrivate::get(cs)->description.toLatin1();
if (iccProfileName.isEmpty())
iccProfileName = QByteArrayLiteral("Custom");
diff --git a/src/gui/painting/qcolorspace.cpp b/src/gui/painting/qcolorspace.cpp
index a14d630814..043a951521 100644
--- a/src/gui/painting/qcolorspace.cpp
+++ b/src/gui/painting/qcolorspace.cpp
@@ -163,24 +163,22 @@ QColorSpacePrivate::QColorSpacePrivate()
QColorSpacePrivate::QColorSpacePrivate(QColorSpace::ColorSpaceId colorSpaceId)
: id(colorSpaceId)
+ , gamma(0.0f)
{
switch (colorSpaceId) {
case QColorSpace::Undefined:
primaries = QColorSpace::Primaries::Custom;
transferFunction = QColorSpace::TransferFunction::Custom;
- gamma = 0.0f;
description = QStringLiteral("Undefined");
break;
case QColorSpace::SRgb:
primaries = QColorSpace::Primaries::SRgb;
transferFunction = QColorSpace::TransferFunction::SRgb;
- gamma = 2.31f; // ?
description = QStringLiteral("sRGB");
break;
case QColorSpace::SRgbLinear:
primaries = QColorSpace::Primaries::SRgb;
transferFunction = QColorSpace::TransferFunction::Linear;
- gamma = 1.0f;
description = QStringLiteral("Linear sRGB");
break;
case QColorSpace::AdobeRgb:
@@ -192,19 +190,16 @@ QColorSpacePrivate::QColorSpacePrivate(QColorSpace::ColorSpaceId colorSpaceId)
case QColorSpace::DisplayP3:
primaries = QColorSpace::Primaries::DciP3D65;
transferFunction = QColorSpace::TransferFunction::SRgb;
- gamma = 2.31f; // ?
description = QStringLiteral("Display P3");
break;
case QColorSpace::ProPhotoRgb:
primaries = QColorSpace::Primaries::ProPhotoRgb;
transferFunction = QColorSpace::TransferFunction::ProPhotoRgb;
- gamma = 1.8f;
description = QStringLiteral("ProPhoto RGB");
break;
case QColorSpace::Bt2020:
primaries = QColorSpace::Primaries::Bt2020;
transferFunction = QColorSpace::TransferFunction::Bt2020;
- gamma = 2.1f; // ?
description = QStringLiteral("BT.2020");
break;
case QColorSpace::Unknown:
@@ -236,8 +231,7 @@ QColorSpacePrivate::QColorSpacePrivate(const QColorSpacePrimaries &primaries,
Q_ASSERT(primaries.areValid());
toXyz = primaries.toXyzMatrix();
whitePoint = QColorVector(primaries.whitePoint);
- if (!identifyColorSpace())
- id = QColorSpace::Unknown;
+ identifyColorSpace();
setTransferFunction();
}
@@ -304,6 +298,7 @@ bool QColorSpacePrivate::identifyColorSpace()
default:
break;
}
+ id = QColorSpace::Unknown;
return false;
}
@@ -331,6 +326,8 @@ void QColorSpacePrivate::setTransferFunction()
case QColorSpace::TransferFunction::Linear:
trc[0].m_type = QColorTrc::Type::Function;
trc[0].m_fun = QColorTransferFunction();
+ if (qFuzzyIsNull(gamma))
+ gamma = 1.0f;
break;
case QColorSpace::TransferFunction::Gamma:
trc[0].m_type = QColorTrc::Type::Function;
@@ -339,14 +336,20 @@ void QColorSpacePrivate::setTransferFunction()
case QColorSpace::TransferFunction::SRgb:
trc[0].m_type = QColorTrc::Type::Function;
trc[0].m_fun = QColorTransferFunction::fromSRgb();
+ if (qFuzzyIsNull(gamma))
+ gamma = 2.31f;
break;
case QColorSpace::TransferFunction::ProPhotoRgb:
trc[0].m_type = QColorTrc::Type::Function;
trc[0].m_fun = QColorTransferFunction::fromProPhotoRgb();
+ if (qFuzzyIsNull(gamma))
+ gamma = 1.8f;
break;
case QColorSpace::TransferFunction::Bt2020:
trc[0].m_type = QColorTrc::Type::Function;
trc[0].m_fun = QColorTransferFunction::fromBt2020();
+ if (qFuzzyIsNull(gamma))
+ gamma = 1.961f;
break;
case QColorSpace::TransferFunction::Custom:
break;
@@ -564,7 +567,7 @@ QColorSpace::Primaries QColorSpace::primaries() const noexcept
Returns the predefined transfer function of the color space
or \c TransferFunction::Custom if it doesn't match any of them.
- \sa gamma()
+ \sa gamma(), setTransferFunction(), withTransferFunction()
*/
QColorSpace::TransferFunction QColorSpace::transferFunction() const noexcept
{
@@ -584,6 +587,91 @@ float QColorSpace::gamma() const noexcept
}
/*!
+ Sets the transfer function to \a transferFunction and \a gamma.
+
+ \note This also changes colorSpaceId().
+
+ \sa transferFunction(), gamma(), withTransferFunction()
+*/
+void QColorSpace::setTransferFunction(QColorSpace::TransferFunction transferFunction, float gamma)
+{
+ if (!isValid() || transferFunction == QColorSpace::TransferFunction::Custom)
+ return;
+ if (d_ptr->transferFunction == transferFunction && d_ptr->gamma == gamma)
+ return;
+ d_ptr.detach();
+ d_ptr->description.clear();
+ d_ptr->transferFunction = transferFunction;
+ d_ptr->gamma = gamma;
+ d_ptr->identifyColorSpace();
+ d_ptr->setTransferFunction();
+}
+
+/*!
+ Returns a copy of this color space, except using the transfer function
+ \a transferFunction and \a gamma.
+
+ \sa transferFunction(), gamma(), setTransferFunction()
+*/
+QColorSpace QColorSpace::withTransferFunction(QColorSpace::TransferFunction transferFunction, float gamma) const
+{
+ if (!isValid() || transferFunction == QColorSpace::TransferFunction::Custom)
+ return *this;
+ if (d_ptr->transferFunction == transferFunction && d_ptr->gamma == gamma)
+ return *this;
+ QColorSpace out(*this);
+ out.setTransferFunction(transferFunction, gamma);
+ return out;
+}
+
+/*!
+ Sets the primaries to those of the \a primariesId set.
+
+ \note This also changes colorSpaceId().
+
+ \sa primaries()
+*/
+void QColorSpace::setPrimaries(QColorSpace::Primaries primariesId)
+{
+ if (!isValid() || primariesId == QColorSpace::Primaries::Custom)
+ return;
+ if (d_ptr->primaries == primariesId)
+ return;
+ d_ptr.detach();
+ d_ptr->description.clear();
+ d_ptr->primaries = primariesId;
+ d_ptr->identifyColorSpace();
+ d_ptr->setToXyzMatrix();
+}
+
+/*!
+ Set primaries to the chromaticities of \a whitePoint, \a redPoint, \a greenPoint
+ and \a bluePoint.
+
+ \note This also changes colorSpaceId().
+
+ \sa primaries()
+*/
+void QColorSpace::setPrimaries(const QPointF &whitePoint, const QPointF &redPoint,
+ const QPointF &greenPoint, const QPointF &bluePoint)
+{
+ if (!isValid())
+ return;
+ QColorSpacePrimaries primaries(whitePoint, redPoint, greenPoint, bluePoint);
+ if (!primaries.areValid())
+ return;
+ QColorMatrix toXyz = primaries.toXyzMatrix();
+ if (QColorVector(primaries.whitePoint) == d_ptr->whitePoint && toXyz == d_ptr->toXyz)
+ return;
+ d_ptr.detach();
+ d_ptr->description.clear();
+ d_ptr->primaries = QColorSpace::Primaries::Custom;
+ d_ptr->toXyz = toXyz;
+ d_ptr->whitePoint = QColorVector(primaries.whitePoint);
+ d_ptr->identifyColorSpace();
+}
+
+/*!
Returns an ICC profile representing the color space.
If the color space was generated from an ICC profile, that profile
diff --git a/src/gui/painting/qcolorspace.h b/src/gui/painting/qcolorspace.h
index a9871fc277..a7c1091911 100644
--- a/src/gui/painting/qcolorspace.h
+++ b/src/gui/painting/qcolorspace.h
@@ -103,6 +103,13 @@ public:
TransferFunction transferFunction() const noexcept;
float gamma() const noexcept;
+ void setTransferFunction(TransferFunction transferFunction, float gamma = 0.0f);
+ QColorSpace withTransferFunction(TransferFunction transferFunction, float gamma = 0.0f) const;
+
+ void setPrimaries(Primaries primariesId);
+ void setPrimaries(const QPointF &whitePoint, const QPointF &redPoint,
+ const QPointF &greenPoint, const QPointF &bluePoint);
+
bool isValid() const noexcept;
friend Q_GUI_EXPORT bool operator==(const QColorSpace &colorSpace1, const QColorSpace &colorSpace2);
diff --git a/tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp b/tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp
index c0f3559f57..bc1a45013c 100644
--- a/tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp
+++ b/tests/auto/gui/painting/qcolorspace/tst_qcolorspace.cpp
@@ -66,6 +66,9 @@ private slots:
void primaries2_data();
void primaries2();
void invalidPrimaries();
+
+ void changeTransferFunction();
+ void changePrimaries();
};
tst_QColorSpace::tst_QColorSpace()
@@ -375,5 +378,49 @@ void tst_QColorSpace::invalidPrimaries()
QCOMPARE(custom.colorSpaceId(), QColorSpace::Undefined);
}
+void tst_QColorSpace::changeTransferFunction()
+{
+ QColorSpace sRgb = QColorSpace::SRgb;
+
+ QColorSpace sRgbLinear = sRgb.withTransferFunction(QColorSpace::TransferFunction::Linear);
+ QCOMPARE(sRgbLinear.transferFunction(), QColorSpace::TransferFunction::Linear);
+ QCOMPARE(sRgbLinear.gamma(), 1.0f);
+ QCOMPARE(sRgbLinear.primaries(), QColorSpace::Primaries::SRgb);
+ QCOMPARE(sRgbLinear.colorSpaceId(), QColorSpace::SRgbLinear);
+ QCOMPARE(sRgbLinear, QColorSpace(QColorSpace::SRgbLinear));
+ QVERIFY(sRgbLinear != sRgb);
+ QCOMPARE(sRgbLinear.withTransferFunction(QColorSpace::TransferFunction::SRgb), sRgb);
+
+ QColorSpace aRgb = QColorSpace::AdobeRgb;
+ aRgb.setTransferFunction(QColorSpace::TransferFunction::SRgb);
+ QCOMPARE(aRgb.transferFunction(), QColorSpace::TransferFunction::SRgb);
+ QCOMPARE(aRgb.primaries(), QColorSpace::Primaries::AdobeRgb);
+ QCOMPARE(aRgb.colorSpaceId(), QColorSpace::Unknown);
+ QVERIFY(aRgb != QColorSpace(QColorSpace::AdobeRgb));
+ QVERIFY(aRgb != sRgb);
+ QCOMPARE(aRgb.withTransferFunction(QColorSpace::TransferFunction::Gamma, 2.2f),
+ QColorSpace(QColorSpace::AdobeRgb));
+ QVERIFY(aRgb != QColorSpace(QColorSpace::AdobeRgb));
+ aRgb.setTransferFunction(QColorSpace::TransferFunction::Gamma, 2.2f);
+ QVERIFY(aRgb == QColorSpace(QColorSpace::AdobeRgb));
+
+ QColorSpace undefined;
+ QCOMPARE(undefined.withTransferFunction(QColorSpace::TransferFunction::Linear), undefined);
+ undefined.setTransferFunction(QColorSpace::TransferFunction::SRgb);
+ QCOMPARE(undefined, QColorSpace());
+}
+
+void tst_QColorSpace::changePrimaries()
+{
+ QColorSpace cs = QColorSpace::SRgb;
+ cs.setPrimaries(QColorSpace::Primaries::DciP3D65);
+ QVERIFY(cs.isValid());
+ QCOMPARE(cs, QColorSpace(QColorSpace::DisplayP3));
+ cs.setTransferFunction(QColorSpace::TransferFunction::Linear);
+ cs.setPrimaries(QPointF(0.3127, 0.3290), QPointF(0.640, 0.330),
+ QPointF(0.3000, 0.6000), QPointF(0.150, 0.060));
+ QCOMPARE(cs, QColorSpace(QColorSpace::SRgbLinear));
+}
+
QTEST_MAIN(tst_QColorSpace)
#include "tst_qcolorspace.moc"