KWin
Loading...
Searching...
No Matches
colortransformation.cpp
Go to the documentation of this file.
1/*
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5 SPDX-FileCopyrightText: 2022 Xaver Hugl <xaver.hugl@gmail.com>
6
7 SPDX-License-Identifier: GPL-2.0-or-later
8*/
10#include "colorpipelinestage.h"
11
12#include <lcms2.h>
13
14#include "utils/common.h"
15
16namespace KWin
17{
18
19ColorTransformation::ColorTransformation(std::vector<std::unique_ptr<ColorPipelineStage>> &&stages)
20 : m_pipeline(cmsPipelineAlloc(nullptr, 3, 3))
21 , m_stages(std::move(stages))
22{
23 if (!m_pipeline) {
24 qCWarning(KWIN_CORE) << "Failed to allocate cmsPipeline!";
25 m_valid = false;
26 return;
27 }
28 for (auto &stage : m_stages) {
29 if (!cmsPipelineInsertStage(m_pipeline, cmsAT_END, stage->stage())) {
30 qCWarning(KWIN_CORE) << "Failed to insert cmsPipeline stage!";
31 m_valid = false;
32 return;
33 }
34 }
35}
36
38{
39 if (m_pipeline) {
40 cmsStage *last = nullptr;
41 do {
42 cmsPipelineUnlinkStage(m_pipeline, cmsAT_END, &last);
43 } while (last);
44 cmsPipelineFree(m_pipeline);
45 }
46}
47
49{
50 for (auto &stage : transformation->m_stages) {
51 auto dup = stage->dup();
52 if (!cmsPipelineInsertStage(m_pipeline, cmsAT_END, dup->stage())) {
53 qCWarning(KWIN_CORE) << "Failed to insert cmsPipeline stage!";
54 m_valid = false;
55 return;
56 }
57 m_stages.push_back(std::move(dup));
58 }
59}
60
62{
63 return m_valid;
64}
65
66std::tuple<uint16_t, uint16_t, uint16_t> ColorTransformation::transform(uint16_t r, uint16_t g, uint16_t b) const
67{
68 const uint16_t in[3] = {r, g, b};
69 uint16_t out[3] = {0, 0, 0};
70 cmsPipelineEval16(in, out, m_pipeline);
71 return {out[0], out[1], out[2]};
72}
73
74QVector3D ColorTransformation::transform(QVector3D in) const
75{
76 QVector3D ret;
77 cmsPipelineEvalFloat(&in[0], &ret[0], m_pipeline);
78 return ret;
79}
80
81std::unique_ptr<ColorTransformation> ColorTransformation::createScalingTransform(const QVector3D &scale)
82{
83 std::array<double, 3> curveParams = {1.0, scale.x(), 0.0};
84 auto r = cmsBuildParametricToneCurve(nullptr, 2, curveParams.data());
85 curveParams = {1.0, scale.y(), 0.0};
86 auto g = cmsBuildParametricToneCurve(nullptr, 2, curveParams.data());
87 curveParams = {1.0, scale.z(), 0.0};
88 auto b = cmsBuildParametricToneCurve(nullptr, 2, curveParams.data());
89 if (!r || !g || !b) {
90 qCWarning(KWIN_CORE) << "Failed to build tone curves";
91 return nullptr;
92 }
93 const std::array curves = {r, g, b};
94 const auto stage = cmsStageAllocToneCurves(nullptr, 3, curves.data());
95 if (!stage) {
96 qCWarning(KWIN_CORE) << "Failed to allocate tone curves";
97 return nullptr;
98 }
99 std::vector<std::unique_ptr<ColorPipelineStage>> stages;
100 stages.push_back(std::make_unique<ColorPipelineStage>(stage));
101 auto transform = std::make_unique<ColorTransformation>(std::move(stages));
102 if (!transform->valid()) {
103 return nullptr;
104 }
105 return transform;
106}
107}
ColorTransformation(std::vector< std::unique_ptr< ColorPipelineStage > > &&stages)
static std::unique_ptr< ColorTransformation > createScalingTransform(const QVector3D &scale)
void append(ColorTransformation *transformation)
std::tuple< uint16_t, uint16_t, uint16_t > transform(uint16_t r, uint16_t g, uint16_t b) const
struct _cmsStage_struct cmsStage