1// Copyright (C) 2018 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QCOLORTRANSFERFUNCTION_P_H
5#define QCOLORTRANSFERFUNCTION_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtGui/private/qtguiglobal_p.h>
19
20#include <cmath>
21
22QT_BEGIN_NAMESPACE
23
24// Defines a ICC parametric curve type 4
25class Q_GUI_EXPORT QColorTransferFunction
26{
27public:
28 QColorTransferFunction() noexcept
29 : m_a(1.0f), m_b(0.0f), m_c(1.0f), m_d(0.0f), m_e(0.0f), m_f(0.0f), m_g(1.0f), m_flags(0)
30 { }
31 QColorTransferFunction(float a, float b, float c, float d, float e, float f, float g) noexcept
32 : m_a(a), m_b(b), m_c(c), m_d(d), m_e(e), m_f(f), m_g(g), m_flags(0)
33 { }
34
35 bool isGamma() const
36 {
37 updateHints();
38 return m_flags & quint32(Hints::IsGamma);
39 }
40 bool isLinear() const
41 {
42 updateHints();
43 return m_flags & quint32(Hints::IsLinear);
44 }
45 bool isSRgb() const
46 {
47 updateHints();
48 return m_flags & quint32(Hints::IsSRgb);
49 }
50
51 float apply(float x) const
52 {
53 if (x < m_d)
54 return m_c * x + m_f;
55 else
56 return std::pow(x: m_a * x + m_b, y: m_g) + m_e;
57 }
58
59 QColorTransferFunction inverted() const
60 {
61 float a, b, c, d, e, f, g;
62
63 d = m_c * m_d + m_f;
64
65 if (!qFuzzyIsNull(f: m_c)) {
66 c = 1.0f / m_c;
67 f = -m_f / m_c;
68 } else {
69 c = 0.0f;
70 f = 0.0f;
71 }
72
73 if (!qFuzzyIsNull(f: m_a) && !qFuzzyIsNull(f: m_g)) {
74 a = std::pow(x: 1.0f / m_a, y: m_g);
75 b = -a * m_e;
76 e = -m_b / m_a;
77 g = 1.0f / m_g;
78 } else {
79 a = 0.0f;
80 b = 0.0f;
81 e = 1.0f;
82 g = 1.0f;
83 }
84
85 return QColorTransferFunction(a, b, c, d, e, f, g);
86 }
87
88 // A few predefined curves:
89 static QColorTransferFunction fromGamma(float gamma)
90 {
91 return QColorTransferFunction(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, gamma);
92 }
93 static QColorTransferFunction fromSRgb()
94 {
95 return QColorTransferFunction(1.0f / 1.055f, 0.055f / 1.055f, 1.0f / 12.92f, 0.04045f, 0.0f, 0.0f, 2.4f);
96 }
97 static QColorTransferFunction fromProPhotoRgb()
98 {
99 return QColorTransferFunction(1.0f, 0.0f, 1.0f / 16.0f, 16.0f / 512.0f, 0.0f, 0.0f, 1.8f);
100 }
101 bool matches(const QColorTransferFunction &o) const
102 {
103 return paramCompare(p1: m_a, p2: o.m_a) && paramCompare(p1: m_b, p2: o.m_b)
104 && paramCompare(p1: m_c, p2: o.m_c) && paramCompare(p1: m_d, p2: o.m_d)
105 && paramCompare(p1: m_e, p2: o.m_e) && paramCompare(p1: m_f, p2: o.m_f)
106 && paramCompare(p1: m_g, p2: o.m_g);
107 }
108 friend inline bool operator==(const QColorTransferFunction &f1, const QColorTransferFunction &f2);
109 friend inline bool operator!=(const QColorTransferFunction &f1, const QColorTransferFunction &f2);
110
111 float m_a;
112 float m_b;
113 float m_c;
114 float m_d;
115 float m_e;
116 float m_f;
117 float m_g;
118
119private:
120 static inline bool paramCompare(float p1, float p2)
121 {
122 // Much fuzzier than fuzzy compare.
123 // It tries match parameters that has been passed through a 8.8
124 // fixed point form.
125 return (qAbs(t: p1 - p2) <= (1.0f / 512.0f));
126 }
127
128 void updateHints() const
129 {
130 if (m_flags & quint32(Hints::Calculated))
131 return;
132 // We do not consider the case with m_d = 1.0f linear or simple,
133 // since it wouldn't be linear for applyExtended().
134 bool simple = paramCompare(p1: m_a, p2: 1.0f) && paramCompare(p1: m_b, p2: 0.0f)
135 && paramCompare(p1: m_d, p2: 0.0f)
136 && paramCompare(p1: m_e, p2: 0.0f);
137 if (simple) {
138 m_flags |= quint32(Hints::IsGamma);
139 if (qFuzzyCompare(p1: m_g, p2: 1.0f))
140 m_flags |= quint32(Hints::IsLinear);
141 } else {
142 if (*this == fromSRgb())
143 m_flags |= quint32(Hints::IsSRgb);
144 }
145 m_flags |= quint32(Hints::Calculated);
146 }
147 enum class Hints : quint32 {
148 Calculated = 1,
149 IsGamma = 2,
150 IsLinear = 4,
151 IsSRgb = 8
152 };
153 mutable quint32 m_flags;
154};
155
156inline bool operator==(const QColorTransferFunction &f1, const QColorTransferFunction &f2)
157{
158 return f1.matches(o: f2);
159}
160inline bool operator!=(const QColorTransferFunction &f1, const QColorTransferFunction &f2)
161{
162 return !f1.matches(o: f2);
163}
164
165QT_END_NAMESPACE
166
167#endif // QCOLORTRANSFERFUNCTION_P_H
168

source code of qtbase/src/gui/painting/qcolortransferfunction_p.h