core/colorspace: move Colorimetry::toOther to ColorDescription
With some rendering intents we need to apply behavior based on brightness levels or the SDR colorimetry
This commit is contained in:
parent
833476a111
commit
418143a45b
6 changed files with 27 additions and 24 deletions
|
@ -85,8 +85,8 @@ void TestColorspaces::roundtripConversion()
|
||||||
void TestColorspaces::nonNormalizedPrimaries()
|
void TestColorspaces::nonNormalizedPrimaries()
|
||||||
{
|
{
|
||||||
// this test ensures that non-normalized primaries don't mess up the transformations between color spaces
|
// this test ensures that non-normalized primaries don't mess up the transformations between color spaces
|
||||||
const auto from = Colorimetry::fromName(NamedColorimetry::BT709);
|
const auto &from = ColorDescription::sRGB;
|
||||||
const auto to = Colorimetry(Colorimetry::xyToXYZ(from.red()) * 2, Colorimetry::xyToXYZ(from.green()) * 2, Colorimetry::xyToXYZ(from.blue()) * 2, Colorimetry::xyToXYZ(from.white()) * 2);
|
const ColorDescription to(Colorimetry(Colorimetry::xyToXYZ(from.containerColorimetry().red()) * 2, Colorimetry::xyToXYZ(from.containerColorimetry().green()) * 2, Colorimetry::xyToXYZ(from.containerColorimetry().blue()) * 2, Colorimetry::xyToXYZ(from.containerColorimetry().white()) * 2), from.transferFunction(), from.referenceLuminance(), from.minLuminance(), from.maxAverageLuminance(), from.maxHdrLuminance());
|
||||||
|
|
||||||
const auto convertedWhite = from.toOther(to, RenderingIntent::RelativeColorimetric) * QVector3D(1, 1, 1);
|
const auto convertedWhite = from.toOther(to, RenderingIntent::RelativeColorimetric) * QVector3D(1, 1, 1);
|
||||||
QCOMPARE_LE(std::abs(1 - convertedWhite.x()), s_resolution10bit);
|
QCOMPARE_LE(std::abs(1 - convertedWhite.x()), s_resolution10bit);
|
||||||
|
|
|
@ -517,7 +517,7 @@ bool DrmOutput::needsChannelFactorFallback() const
|
||||||
|
|
||||||
QVector3D DrmOutput::effectiveChannelFactors() const
|
QVector3D DrmOutput::effectiveChannelFactors() const
|
||||||
{
|
{
|
||||||
QVector3D adaptedChannelFactors = Colorimetry::fromName(NamedColorimetry::BT709).toOther(m_state.colorDescription.containerColorimetry(), RenderingIntent::RelativeColorimetric) * m_channelFactors;
|
QVector3D adaptedChannelFactors = ColorDescription::sRGB.toOther(colorDescription(), RenderingIntent::RelativeColorimetric) * m_channelFactors;
|
||||||
// normalize red to be the original brightness value again
|
// normalize red to be the original brightness value again
|
||||||
adaptedChannelFactors *= m_channelFactors.x() / adaptedChannelFactors.x();
|
adaptedChannelFactors *= m_channelFactors.x() / adaptedChannelFactors.x();
|
||||||
if (m_state.highDynamicRange || !m_brightnessDevice) {
|
if (m_state.highDynamicRange || !m_brightnessDevice) {
|
||||||
|
|
|
@ -23,7 +23,7 @@ ColorPipeline ColorPipeline::create(const ColorDescription &from, const ColorDes
|
||||||
|
|
||||||
// FIXME this assumes that the range stays the same with matrix multiplication
|
// FIXME this assumes that the range stays the same with matrix multiplication
|
||||||
// that's not necessarily true, and figuring out the actual range could be complicated..
|
// that's not necessarily true, and figuring out the actual range could be complicated..
|
||||||
ret.addMatrix(from.containerColorimetry().toOther(to.containerColorimetry(), intent), ret.currentOutputRange());
|
ret.addMatrix(from.toOther(to, intent), ret.currentOutputRange());
|
||||||
|
|
||||||
ret.addInverseTransferFunction(to.transferFunction());
|
ret.addInverseTransferFunction(to.transferFunction());
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -126,18 +126,6 @@ const QMatrix4x4 &Colorimetry::fromXYZ() const
|
||||||
return m_fromXYZ;
|
return m_fromXYZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
QMatrix4x4 Colorimetry::toOther(const Colorimetry &other, RenderingIntent intent) const
|
|
||||||
{
|
|
||||||
switch (intent) {
|
|
||||||
case RenderingIntent::Perceptual:
|
|
||||||
case RenderingIntent::RelativeColorimetric:
|
|
||||||
return other.fromXYZ() * chromaticAdaptationMatrix(this->white(), other.white()) * toXYZ();
|
|
||||||
case RenderingIntent::AbsoluteColorimetric:
|
|
||||||
return other.fromXYZ() * toXYZ();
|
|
||||||
}
|
|
||||||
Q_UNREACHABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
Colorimetry Colorimetry::adaptedTo(QVector2D newWhitepoint) const
|
Colorimetry Colorimetry::adaptedTo(QVector2D newWhitepoint) const
|
||||||
{
|
{
|
||||||
const auto mat = chromaticAdaptationMatrix(this->white(), newWhitepoint);
|
const auto mat = chromaticAdaptationMatrix(this->white(), newWhitepoint);
|
||||||
|
@ -273,11 +261,26 @@ std::optional<double> ColorDescription::maxHdrLuminance() const
|
||||||
return m_maxHdrLuminance;
|
return m_maxHdrLuminance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QMatrix4x4 ColorDescription::toOther(const ColorDescription &other, RenderingIntent intent) const
|
||||||
|
{
|
||||||
|
switch (intent) {
|
||||||
|
case RenderingIntent::Perceptual: {
|
||||||
|
const Colorimetry &srcContainer = containerColorimetry() == NamedColorimetry::BT709 ? other.sdrColorimetry() : containerColorimetry();
|
||||||
|
return other.containerColorimetry().fromXYZ() * Colorimetry::chromaticAdaptationMatrix(srcContainer.white(), other.containerColorimetry().white()) * srcContainer.toXYZ();
|
||||||
|
}
|
||||||
|
case RenderingIntent::RelativeColorimetric:
|
||||||
|
return other.containerColorimetry().fromXYZ() * Colorimetry::chromaticAdaptationMatrix(containerColorimetry().white(), other.containerColorimetry().white()) * containerColorimetry().toXYZ();
|
||||||
|
case RenderingIntent::AbsoluteColorimetric:
|
||||||
|
return other.containerColorimetry().fromXYZ() * containerColorimetry().toXYZ();
|
||||||
|
}
|
||||||
|
Q_UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
QVector3D ColorDescription::mapTo(QVector3D rgb, const ColorDescription &dst, RenderingIntent intent) const
|
QVector3D ColorDescription::mapTo(QVector3D rgb, const ColorDescription &dst, RenderingIntent intent) const
|
||||||
{
|
{
|
||||||
rgb = m_transferFunction.encodedToNits(rgb);
|
rgb = m_transferFunction.encodedToNits(rgb);
|
||||||
rgb *= dst.referenceLuminance() / m_referenceLuminance;
|
rgb *= dst.referenceLuminance() / m_referenceLuminance;
|
||||||
rgb = m_containerColorimetry.toOther(dst.containerColorimetry(), intent) * rgb;
|
rgb = toOther(dst, intent) * rgb;
|
||||||
return dst.transferFunction().nitsToEncoded(rgb);
|
return dst.transferFunction().nitsToEncoded(rgb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,10 +70,6 @@ public:
|
||||||
* @returns a matrix that transforms from the XYZ representation to the linear RGB representation of colors in this colorimetry
|
* @returns a matrix that transforms from the XYZ representation to the linear RGB representation of colors in this colorimetry
|
||||||
*/
|
*/
|
||||||
const QMatrix4x4 &fromXYZ() const;
|
const QMatrix4x4 &fromXYZ() const;
|
||||||
/**
|
|
||||||
* @returns a matrix that transforms from linear RGB in this colorimetry to linear RGB in the other colorimetry
|
|
||||||
*/
|
|
||||||
QMatrix4x4 toOther(const Colorimetry &colorimetry, RenderingIntent intent) const;
|
|
||||||
bool operator==(const Colorimetry &other) const;
|
bool operator==(const Colorimetry &other) const;
|
||||||
bool operator==(NamedColorimetry name) const;
|
bool operator==(NamedColorimetry name) const;
|
||||||
/**
|
/**
|
||||||
|
@ -179,9 +175,14 @@ public:
|
||||||
|
|
||||||
bool operator==(const ColorDescription &other) const = default;
|
bool operator==(const ColorDescription &other) const = default;
|
||||||
|
|
||||||
QVector3D mapTo(QVector3D rgb, const ColorDescription &other, RenderingIntent intent) const;
|
|
||||||
ColorDescription withTransferFunction(const TransferFunction &func) const;
|
ColorDescription withTransferFunction(const TransferFunction &func) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns a matrix that transforms from linear RGB in this color description to linear RGB in the other one
|
||||||
|
*/
|
||||||
|
QMatrix4x4 toOther(const ColorDescription &other, RenderingIntent intent) const;
|
||||||
|
QVector3D mapTo(QVector3D rgb, const ColorDescription &other, RenderingIntent intent) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This color description describes display-referred sRGB, with a gamma22 transfer function
|
* This color description describes display-referred sRGB, with a gamma22 transfer function
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -471,8 +471,7 @@ QMatrix4x4 GLShader::getUniformMatrix4x4(const char *name)
|
||||||
|
|
||||||
bool GLShader::setColorspaceUniforms(const ColorDescription &src, const ColorDescription &dst, RenderingIntent intent)
|
bool GLShader::setColorspaceUniforms(const ColorDescription &src, const ColorDescription &dst, RenderingIntent intent)
|
||||||
{
|
{
|
||||||
const auto &srcColorimetry = intent == RenderingIntent::Perceptual && src.containerColorimetry() == NamedColorimetry::BT709 ? dst.sdrColorimetry() : src.containerColorimetry();
|
return setUniform(Mat4Uniform::ColorimetryTransformation, src.toOther(dst, intent))
|
||||||
return setUniform(Mat4Uniform::ColorimetryTransformation, srcColorimetry.toOther(dst.containerColorimetry(), intent))
|
|
||||||
&& setUniform(IntUniform::SourceNamedTransferFunction, src.transferFunction().type)
|
&& setUniform(IntUniform::SourceNamedTransferFunction, src.transferFunction().type)
|
||||||
&& setUniform(Vec2Uniform::SourceTransferFunctionParams, QVector2D(src.transferFunction().minLuminance, src.transferFunction().maxLuminance - src.transferFunction().minLuminance))
|
&& setUniform(Vec2Uniform::SourceTransferFunctionParams, QVector2D(src.transferFunction().minLuminance, src.transferFunction().maxLuminance - src.transferFunction().minLuminance))
|
||||||
&& setUniform(FloatUniform::SourceReferenceLuminance, src.referenceLuminance())
|
&& setUniform(FloatUniform::SourceReferenceLuminance, src.referenceLuminance())
|
||||||
|
|
Loading…
Reference in a new issue