From f8012f580bb3d4782ce3d612793a7763cff06270 Mon Sep 17 00:00:00 2001 From: Xaver Hugl Date: Tue, 10 Oct 2023 13:49:52 +0200 Subject: [PATCH] plugins/colorpicker: convert picked color to sRGB The API doesn't have any colorspace data, so we need to make sure we're sending sRGB BUG: 387757 --- src/libkwineffects/colorspace.cpp | 44 +++++++++++++++++++++++++ src/libkwineffects/colorspace.h | 2 ++ src/plugins/colorpicker/colorpicker.cpp | 3 +- 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/libkwineffects/colorspace.cpp b/src/libkwineffects/colorspace.cpp index 1cbd9ae9fe..92d293d26d 100644 --- a/src/libkwineffects/colorspace.cpp +++ b/src/libkwineffects/colorspace.cpp @@ -159,4 +159,48 @@ bool ColorDescription::operator==(const ColorDescription &other) const && m_maxHdrBrightness == other.maxHdrBrightness() && m_maxHdrHighlightBrightness == other.maxHdrHighlightBrightness(); } + +static float srgbToLinear(float sRGB) +{ + if (sRGB < 0.04045) { + return std::max(sRGB / 12.92, 0.0); + } else { + return std::clamp(std::pow((sRGB + 0.055) / 1.055, 12.0 / 5.0), 0.0, 1.0); + } +} + +static float linearToSRGB(float linear) +{ + if (linear < 0.0031308) { + return std::max(linear / 12.92, 0.0); + } else { + return std::clamp(std::pow(linear, 5.0 / 12.0) * 1.055 - 0.055, 0.0, 1.0); + } +} + +QVector3D ColorDescription::mapTo(QVector3D rgb, const ColorDescription &dst) const +{ + Q_ASSERT_X(m_transferFunction != NamedTransferFunction::PerceptualQuantizer && dst.transferFunction() != NamedTransferFunction::PerceptualQuantizer, + "ColorDescription::mapTo", "PQ isn't supported yet"); + switch (m_transferFunction) { + case NamedTransferFunction::sRGB: + rgb = QVector3D(srgbToLinear(rgb.x()), srgbToLinear(rgb.y()), srgbToLinear(rgb.z())); + break; + case NamedTransferFunction::linear: + rgb /= m_sdrBrightness; + break; + case NamedTransferFunction::PerceptualQuantizer: + return QVector3D(); + } + rgb = m_colorimetry.toOther(dst.colorimetry()) * rgb; + switch (dst.transferFunction()) { + case NamedTransferFunction::sRGB: + return QVector3D(linearToSRGB(rgb.x()), linearToSRGB(rgb.y()), linearToSRGB(rgb.z())); + case NamedTransferFunction::linear: + return rgb * dst.sdrBrightness(); + case NamedTransferFunction::PerceptualQuantizer: + return QVector3D(); + } + return QVector3D(); +} } diff --git a/src/libkwineffects/colorspace.h b/src/libkwineffects/colorspace.h index dc0490f8c7..19559c1d1e 100644 --- a/src/libkwineffects/colorspace.h +++ b/src/libkwineffects/colorspace.h @@ -76,6 +76,8 @@ public: bool operator==(const ColorDescription &other) const; + QVector3D mapTo(QVector3D rgb, const ColorDescription &other) const; + static const ColorDescription sRGB; private: diff --git a/src/plugins/colorpicker/colorpicker.cpp b/src/plugins/colorpicker/colorpicker.cpp index 90be531842..dc721dfef4 100644 --- a/src/plugins/colorpicker/colorpicker.cpp +++ b/src/plugins/colorpicker/colorpicker.cpp @@ -63,7 +63,8 @@ void ColorPickerEffect::paintScreen(const RenderTarget &renderTarget, const Rend const QPoint texturePosition = viewport.mapToRenderTarget(m_scheduledPosition).toPoint(); glReadnPixels(texturePosition.x(), renderTarget.size().height() - texturePosition.y() - PIXEL_SIZE, PIXEL_SIZE, PIXEL_SIZE, GL_RGBA, GL_UNSIGNED_BYTE, 4, data); - QDBusConnection::sessionBus().send(m_replyMessage.createReply(QColor(data[0], data[1], data[2]))); + QVector3D sRGB = renderTarget.colorDescription().mapTo(QVector3D(data[0] / 255.0, data[1] / 255.0, data[2] / 255.0), ColorDescription::sRGB); + QDBusConnection::sessionBus().send(m_replyMessage.createReply(QColor(255 * sRGB.x(), 255 * sRGB.y(), 255 * sRGB.z()))); m_picking = false; m_scheduledPosition = QPoint(-1, -1); }