-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
utilities.cpp
72 lines (57 loc) · 2.06 KB
/
utilities.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include "utilities.h"
namespace Utilities
{
std::array<qreal, 3> QColorTosRGB(const QColor &colour)
{
// TODO: I only used qreal here because it's what colour.getRgbF() used in Qt5.
// Now that Qt6 doesn't use it for that, maybe I should switch to something
// else here...
std::array<qreal, 3> srgb;
srgb[0] = colour.redF();
srgb[1] = colour.greenF();
srgb[2] = colour.blueF();
return srgb;
}
// https://en.wikipedia.org/wiki/SRGB#From_sRGB_to_CIE_XYZ
std::array<qreal, 3> sRGBToLinearRGB(const std::array<qreal, 3> &srgb)
{
std::array<qreal, 3> linear_rgb;
for (std::size_t i = 0; i < srgb.size(); ++i)
{
if (srgb[i] <= qreal(0.04045))
linear_rgb[i] = srgb[i] / qreal(12.92);
else
linear_rgb[i] = qPow((srgb[i] + qreal(0.055)) / qreal(1.055), qreal(2.4));
}
return linear_rgb;
}
// https://en.wikipedia.org/wiki/SRGB#From_sRGB_to_CIE_XYZ
std::array<qreal, 3> LinearRGBToXYZ(const std::array<qreal, 3> &linear_rgb)
{
std::array<qreal, 3> xyz;
xyz[0] = linear_rgb[0] * qreal(0.4124) + linear_rgb[1] * qreal(0.3576) + linear_rgb[2] * qreal(0.1805);
xyz[1] = linear_rgb[0] * qreal(0.2126) + linear_rgb[1] * qreal(0.7152) + linear_rgb[2] * qreal(0.0722);
xyz[2] = linear_rgb[0] * qreal(0.0193) + linear_rgb[1] * qreal(0.1192) + linear_rgb[2] * qreal(0.9505);
return xyz;
}
// https://en.wikipedia.org/wiki/CIELAB_color_space#From_CIEXYZ_to_CIELAB
std::array<qreal, 3> XYZToLAB(const std::array<qreal, 3> &xyz)
{
const auto f = [](const qreal t)
{
constexpr qreal magic = qreal(6) / qreal(29);
if (t > magic * magic * magic)
return qPow(t, qreal(1) / qreal(3));
else
return t / (3 * magic * magic) + qreal(4) / qreal(29);
};
const qreal x_adjusted = xyz[0] / qreal(0.950489);
const qreal y_adjusted = xyz[1] / qreal(1);
const qreal z_adjusted = xyz[2] / qreal(1.088840);
std::array<qreal, 3> lab;
lab[0] = qreal(116) * f(y_adjusted) - qreal(16);
lab[1] = qreal(500) * (f(x_adjusted) - f(y_adjusted));
lab[2] = qreal(200) * (f(y_adjusted) - f(z_adjusted));
return lab;
}
}