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>
This commit is contained in:
parent
092074f9df
commit
05251bca1d
@ -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");
|
||||
|
@ -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
|
||||
{
|
||||
@ -583,6 +586,91 @@ float QColorSpace::gamma() const noexcept
|
||||
return d_ptr->gamma;
|
||||
}
|
||||
|
||||
/*!
|
||||
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.
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user