-
Notifications
You must be signed in to change notification settings - Fork 116
/
gradients.js
147 lines (124 loc) · 3.99 KB
/
gradients.js
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
let colorPicker_A;
let colorPicker_B;
let color_A;
let color_B;
function setup() {
createCanvas(650, 465);
background(255);
colorMode(RGB);
colorPicker_A = createColorPicker('#002185');
colorPicker_A.parent('picker-A');
color_A = colorPicker_A.color();
colorPicker_B = createColorPicker('#fcd200');
colorPicker_B.parent('picker-B');
color_B = colorPicker_B.color();
drawGradient("Mixbox", color_A, color_B, 50, 200, 65, 465);
drawGradient("RGB", color_A, color_B, 250, 400, 65, 465);
drawGradient("OkLab", color_A, color_B, 450, 600, 65, 465);
}
function draw() {
if(color_A.toString() != colorPicker_A.color().toString() || color_B.toString() != colorPicker_B.color().toString())
{
background(255);
color_A = colorPicker_A.color();
color_B = colorPicker_B.color();
drawGradient("Mixbox", color_A, color_B, 50, 200, 65, 465);
drawGradient("RGB", color_A, color_B, 250, 400, 65, 465);
drawGradient("OkLab", color_A, color_B, 450, 600, 65, 465);
}
}
function drawGradient(method, color1, color2, x1, x2, y1, y2)
{
textSize(28);
textStyle(BOLD);
fill(79, 118, 123);
text(method, x1 + (x2-x1)/2 - textWidth(method)/2, y1-30);
let mixedColor;
for (let y = y1; y <= y2; y++)
{
let t = (y-y1)/(y2-y1);
if(match(method, 'Mixbox'))
{
mixedColor = mixbox.lerp(color1, color2, t);
}
else if(match(method, 'RGB'))
{
mixedColor = lerpColor(color1, color2, t);
}
else if(match(method, 'OkLab'))
{
let c1 = [red(color1), green(color1), blue(color1)];
let c2 = [red(color2), green(color2), blue(color2)];
let tmp = linear_to_rgb (oklab_to_linear_srgb(linearMix(linear_srgb_to_oklab(rgb_to_linear(c1)),linear_srgb_to_oklab(rgb_to_linear(c2)),t)));
mixedColor = color(tmp[0], tmp[1], tmp[2]);
}
strokeWeight(2);
stroke(mixedColor);
line(x1, y, x2, y);
noStroke();
}
}
/* THE FOLLOWING CODE IS HANDLING THE CONVERSION TO OkLAB SPACE */
/* https://bottosson.github.io/posts/oklab/ */
function linear_srgb_to_oklab(c)
{
let l = 0.4122214708 * c[0] + 0.5363325363 * c[1] + 0.0514459929 * c[2];
let m = 0.2119034982 * c[0] + 0.6806995451 * c[1] + 0.1073969566 * c[2];
let s = 0.0883024619 * c[0] + 0.2817188376 * c[1] + 0.6299787005 * c[2];
let l_ = Math.cbrt(l);
let m_ = Math.cbrt(m);
let s_ = Math.cbrt(s);
var lab = [ 0.2104542553*l_ + 0.7936177850*m_ - 0.0040720468*s_,
1.9779984951*l_ - 2.4285922050*m_ + 0.4505937099*s_,
0.0259040371*l_ + 0.7827717662*m_ - 0.8086757660*s_ ];
return lab;
}
function oklab_to_linear_srgb(c)
{
let l_ = c[0] + 0.3963377774 * c[1] + 0.2158037573 * c[2];
let m_ = c[0] - 0.1055613458 * c[1] - 0.0638541728 * c[2];
let s_ = c[0] - 0.0894841775 * c[1] - 1.2914855480 * c[2];
let l = l_*l_*l_;
let m = m_*m_*m_;
let s = s_*s_*s_;
var lrgb = [ 4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,
-1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,
-0.0041960863 * l - 0.7034186147 * m + 1.7076147010 * s];
return lrgb;
}
function rgb_to_linear(rgb) // receiving Color object, returning array of 3 linear RGB values in range 0-1
{
var res = [0,0,0];
var float_rgb = [rgb[0]/255, rgb[1]/255, rgb[2]/255];
for (let i = 0; i < 3; ++i)
{
let c = float_rgb[i];
if (c >= 0.04045)
res[i] = pow((c + 0.055)/(1 + 0.055), 2.4);
else
res[i] = c / 12.92;
}
return res;
}
function linear_to_rgb(lrgb) // receiving array of 3 linear RGB values, returning an array of gamma encoded RGB values in range 0-255
{
var res = [0,0,0];
for (let i = 0; i < 3; ++i)
{
let c = lrgb[i];
if (c >= 0.0031308)
res[i] = 1.055 * pow(c, 1.0/2.4) - 0.055;
else
res[i] = 12.92 * c;
}
return [round(res[0]*255), round(res[1]*255), round(res[2]*255)];
}
function linearMix (a, b, t)
{
var res = [0,0,0];
for(let i=0; i<3; i++)
{
res[i] = a[i] * (1-t) + b[i]*t;
}
return res;
}