-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathutil-color.cpp
112 lines (96 loc) · 2.48 KB
/
util-color.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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include "util-math.h"
namespace util
{
// Color space conversions
float3 RGBtoHSV(rgb c)
{
float minComp = minComponent(c);
float maxComp = maxComponent(c);
float delta = maxComp - minComp;
if (maxComp == 0.0f)
return float3(0.0f);
float3 result = { 0, delta / maxComp, maxComp };
if (delta == 0.0f)
return result;
if (c.r == maxComp)
result.x = (c.g - c.b) / delta;
else if (c.g == maxComp)
result.x = 2.0f + (c.b - c.r) / delta;
else
result.x = 4.0f + (c.r - c.g) / delta;
if (result.x < 0.0f)
result.x += 6.0f;
result.x *= 60.0f;
return result;
}
rgb HSVtoRGB(float3 c)
{
if (c.y == 0.0f)
return rgb(c.z);
float h = modPositive(c.x, 360.0f) / 60.0f;
int i = int(floor(h));
ASSERT_WARN(i >= 0 && i < 6);
float f = h - i;
float p = c.z * (1.0f - c.y);
float q = c.z * (1.0f - c.y * f);
float t = c.z * (1.0f - c.y * (1.0f - f));
switch (i)
{
case 0: return { c.z, t, p };
case 1: return { q, c.z, p };
case 2: return { p, c.z, t };
case 3: return { p, q, c.z };
case 4: return { t, p, c.z };
case 5: return { c.z, p, q };
default:
return rgb(0.0f);
}
}
// White point for CIELAB conversion (in XYZ color space),
// chosen to make RGB (1, 1, 1) come out to CIELAB (100, 0, 0).
static const float xyzWhitePoint[] = { 0.9505f, 1.0f, 1.0887f };
float3 RGBtoCIELAB(rgb c)
{
// Convert RGB to XYZ color space
static const float3x3 RGBtoXYZ =
{
0.4124f, 0.2126f, 0.0193f,
0.3576f, 0.7152f, 0.1192f,
0.1805f, 0.0722f, 0.9502f,
};
float3 xyz = c * RGBtoXYZ;
// Convert to CIELAB space
xyz /= float3(xyzWhitePoint);
float3 warp = select(
xyz > 0.00885645f,
pow(xyz, 1.0f/3.0f),
7.787037f * xyz + 0.137931f);
return
{
116.0f * warp.y - 16.0f,
500.0f * (warp.x - warp.y),
200.0f * (warp.y - warp.z),
};
}
rgb CIELABtoRGB(float3 c)
{
// Convert CIELAB to XYZ
float warpY = (c.x + 16.0f) / 116.0f;
float warpX = warpY + c.y / 500.0f;
float warpZ = warpY - c.z / 200.0f;
float3 warp = { warpX, warpY, warpZ };
float3 xyz = select(
warp > 0.206897f,
warp * warp * warp,
(warp - 0.137931f) / 7.787037f);
xyz *= float3(xyzWhitePoint);
// Convert XYZ to RGB color space
static const float3x3 XYZtoRGB =
{
3.2406f, -0.9689f, 0.0557f,
-1.5372f, 1.8758f, -0.2040f,
-0.4986f, 0.0415f, 1.0570f,
};
return xyz * XYZtoRGB;
}
}