1// Copyright (C) 2024 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 QCOLORCLUT_H
5#define QCOLORCLUT_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 <QtCore/qlist.h>
19#include <QtGui/private/qcolormatrix_p.h>
20
21QT_BEGIN_NAMESPACE
22
23// A 3/4-dimensional lookup table compatible with ICC lut8, lut16, mAB, and mBA formats.
24class QColorCLUT
25{
26 inline static QColorVector interpolate(const QColorVector &a, const QColorVector &b, float t)
27 {
28 return a + (b - a) * t; // faster than std::lerp by assuming no super large or non-number floats
29 }
30 inline static void interpolateIn(QColorVector &a, const QColorVector &b, float t)
31 {
32 a += (b - a) * t;
33 }
34public:
35 uint32_t gridPointsX = 0;
36 uint32_t gridPointsY = 0;
37 uint32_t gridPointsZ = 0;
38 uint32_t gridPointsW = 1;
39 QList<QColorVector> table;
40
41 bool isEmpty() const { return table.isEmpty(); }
42
43 QColorVector apply(const QColorVector &v) const
44 {
45 Q_ASSERT(table.size() == qsizetype(gridPointsX * gridPointsY * gridPointsZ * gridPointsW));
46 QColorVector frac;
47 const float x = std::clamp(val: v.x, lo: 0.0f, hi: 1.0f) * (gridPointsX - 1);
48 const float y = std::clamp(val: v.y, lo: 0.0f, hi: 1.0f) * (gridPointsY - 1);
49 const float z = std::clamp(val: v.z, lo: 0.0f, hi: 1.0f) * (gridPointsZ - 1);
50 const float w = std::clamp(val: v.w, lo: 0.0f, hi: 1.0f) * (gridPointsW - 1);
51 const uint32_t lox = static_cast<uint32_t>(std::floor(x: x));
52 const uint32_t hix = std::min(a: lox + 1, b: gridPointsX - 1);
53 const uint32_t loy = static_cast<uint32_t>(std::floor(x: y));
54 const uint32_t hiy = std::min(a: loy + 1, b: gridPointsY - 1);
55 const uint32_t loz = static_cast<uint32_t>(std::floor(x: z));
56 const uint32_t hiz = std::min(a: loz + 1, b: gridPointsZ - 1);
57 const uint32_t low = static_cast<uint32_t>(std::floor(x: w));
58 const uint32_t hiw = std::min(a: low + 1, b: gridPointsW - 1);
59 frac.x = x - static_cast<float>(lox);
60 frac.y = y - static_cast<float>(loy);
61 frac.z = z - static_cast<float>(loz);
62 frac.w = w - static_cast<float>(low);
63 if (gridPointsW > 1) {
64 auto index = [&](qsizetype x, qsizetype y, qsizetype z, qsizetype w) -> qsizetype {
65 return x * gridPointsW * gridPointsZ * gridPointsY
66 + y * gridPointsW * gridPointsZ
67 + z * gridPointsW
68 + w;
69 };
70 QColorVector tmp[8];
71 // interpolate over w
72 tmp[0] = interpolate(a: table[index(lox, loy, loz, low)],
73 b: table[index(lox, loy, loz, hiw)], t: frac.w);
74 tmp[1] = interpolate(a: table[index(lox, loy, hiz, low)],
75 b: table[index(lox, loy, hiz, hiw)], t: frac.w);
76 tmp[2] = interpolate(a: table[index(lox, hiy, loz, low)],
77 b: table[index(lox, hiy, loz, hiw)], t: frac.w);
78 tmp[3] = interpolate(a: table[index(lox, hiy, hiz, low)],
79 b: table[index(lox, hiy, hiz, hiw)], t: frac.w);
80 tmp[4] = interpolate(a: table[index(hix, loy, loz, low)],
81 b: table[index(hix, loy, loz, hiw)], t: frac.w);
82 tmp[5] = interpolate(a: table[index(hix, loy, hiz, low)],
83 b: table[index(hix, loy, hiz, hiw)], t: frac.w);
84 tmp[6] = interpolate(a: table[index(hix, hiy, loz, low)],
85 b: table[index(hix, hiy, loz, hiw)], t: frac.w);
86 tmp[7] = interpolate(a: table[index(hix, hiy, hiz, low)],
87 b: table[index(hix, hiy, hiz, hiw)], t: frac.w);
88 // interpolate over z
89 for (int i = 0; i < 4; ++i)
90 interpolateIn(a&: tmp[i * 2], b: tmp[i * 2 + 1], t: frac.z);
91 // interpolate over y
92 for (int i = 0; i < 2; ++i)
93 interpolateIn(a&: tmp[i * 4], b: tmp[i * 4 + 2], t: frac.y);
94 // interpolate over x
95 interpolateIn(a&: tmp[0], b: tmp[4], t: frac.x);
96 return tmp[0];
97 }
98 auto index = [&](qsizetype x, qsizetype y, qsizetype z) -> qsizetype {
99 return x * gridPointsZ * gridPointsY
100 + y * gridPointsZ
101 + z;
102 };
103 QColorVector tmp[8] = {
104 table[index(lox, loy, loz)],
105 table[index(lox, loy, hiz)],
106 table[index(lox, hiy, loz)],
107 table[index(lox, hiy, hiz)],
108 table[index(hix, loy, loz)],
109 table[index(hix, loy, hiz)],
110 table[index(hix, hiy, loz)],
111 table[index(hix, hiy, hiz)]
112 };
113 // interpolate over z
114 for (int i = 0; i < 4; ++i)
115 interpolateIn(a&: tmp[i * 2], b: tmp[i * 2 + 1], t: frac.z);
116 // interpolate over y
117 for (int i = 0; i < 2; ++i)
118 interpolateIn(a&: tmp[i * 4], b: tmp[i * 4 + 2], t: frac.y);
119 // interpolate over x
120 interpolateIn(a&: tmp[0], b: tmp[4], t: frac.x);
121 return tmp[0];
122 }
123};
124
125QT_END_NAMESPACE
126
127#endif // QCOLORCLUT_H
128

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

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