-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.html
191 lines (177 loc) · 8.16 KB
/
index.html
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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
<html>
<body onload="test()" id="Body" style="background-color: rgb(0,0,0);">
<script>
/* sRGB Gamma */
function gamma(x) {
return (x < 0.0031308) ? (x * 12.92) : (1.055 * Math.pow(x,1/2.4) - 0.055);
}
/* 10 Degree CMFs from http://cvrl.ioo.ucl.ac.uk/cmfs.htm */
var XYZ_colour_match = [
390,2.952420E-03,4.076779E-04,1.318752E-02,
395,7.641137E-03,1.078166E-03,3.424588E-02,
400,1.879338E-02,2.589775E-03,8.508254E-02,
405,4.204986E-02,5.474207E-03,1.927065E-01,
410,8.277331E-02,1.041303E-02,3.832822E-01,
415,1.395127E-01,1.712968E-02,6.568187E-01,
420,2.077647E-01,2.576133E-02,9.933444E-01,
425,2.688989E-01,3.529554E-02,1.308674E+00,
430,3.281798E-01,4.698226E-02,1.624940E+00,
435,3.693084E-01,6.047429E-02,1.867751E+00,
440,4.026189E-01,7.468288E-02,2.075946E+00,
445,4.042529E-01,8.820537E-02,2.132574E+00,
450,3.932139E-01,1.039030E-01,2.128264E+00,
455,3.482214E-01,1.195389E-01,1.946651E+00,
460,3.013112E-01,1.414586E-01,1.768440E+00,
465,2.534221E-01,1.701373E-01,1.582342E+00,
470,1.914176E-01,1.999859E-01,1.310576E+00,
475,1.283167E-01,2.312426E-01,1.010952E+00,
480,7.593120E-02,2.682271E-01,7.516389E-01,
485,3.836770E-02,3.109438E-01,5.549619E-01,
490,1.400745E-02,3.554018E-01,3.978114E-01,
495,3.446810E-03,4.148227E-01,2.905816E-01,
500,5.652072E-03,4.780482E-01,2.078158E-01,
505,1.561956E-02,5.491344E-01,1.394643E-01,
510,3.778185E-02,6.248296E-01,8.852389E-02,
515,7.538941E-02,7.012292E-01,5.824484E-02,
520,1.201511E-01,7.788199E-01,3.784916E-02,
525,1.756832E-01,8.376358E-01,2.431375E-02,
530,2.380254E-01,8.829552E-01,1.539505E-02,
535,3.046991E-01,9.233858E-01,9.753000E-03,
540,3.841856E-01,9.665325E-01,6.083223E-03,
545,4.633109E-01,9.886887E-01,3.769336E-03,
550,5.374170E-01,9.907500E-01,2.323578E-03,
555,6.230892E-01,9.997775E-01,1.426627E-03,
560,7.123849E-01,9.944304E-01,8.779264E-04,
565,8.016277E-01,9.848127E-01,5.408385E-04,
570,8.933408E-01,9.640545E-01,3.342429E-04,
575,9.721304E-01,9.286495E-01,2.076129E-04,
580,1.034327E+00,8.775360E-01,1.298230E-04,
585,1.106886E+00,8.370838E-01,8.183954E-05,
590,1.147304E+00,7.869950E-01,5.207245E-05,
595,1.160477E+00,7.272309E-01,3.347499E-05,
600,1.148163E+00,6.629035E-01,2.175998E-05,
605,1.113846E+00,5.970375E-01,1.431231E-05,
610,1.048485E+00,5.282296E-01,9.530130E-06,
615,9.617111E-01,4.601308E-01,6.426776E-06,
620,8.629581E-01,3.950755E-01,0.000000E+00,
625,7.603498E-01,3.351794E-01,0.000000E+00,
630,6.413984E-01,2.751807E-01,0.000000E+00,
635,5.290979E-01,2.219564E-01,0.000000E+00,
640,4.323126E-01,1.776882E-01,0.000000E+00,
645,3.496358E-01,1.410203E-01,0.000000E+00,
650,2.714900E-01,1.083996E-01,0.000000E+00,
655,2.056507E-01,8.137687E-02,0.000000E+00,
660,1.538163E-01,6.033976E-02,0.000000E+00,
665,1.136072E-01,4.425383E-02,0.000000E+00,
670,8.281010E-02,3.211852E-02,0.000000E+00,
675,5.954815E-02,2.302574E-02,0.000000E+00,
680,4.221473E-02,1.628841E-02,0.000000E+00,
685,2.948752E-02,1.136106E-02,0.000000E+00,
690,2.025590E-02,7.797457E-03,0.000000E+00,
695,1.410230E-02,5.425391E-03,0.000000E+00,
700,9.816228E-03,3.776140E-03,0.000000E+00,
705,6.809147E-03,2.619372E-03,0.000000E+00,
710,4.666298E-03,1.795595E-03,0.000000E+00,
715,3.194041E-03,1.229980E-03,0.000000E+00,
720,2.205568E-03,8.499903E-04,0.000000E+00,
725,1.524672E-03,5.881375E-04,0.000000E+00,
730,1.061495E-03,4.098928E-04,0.000000E+00,
735,7.400120E-04,2.860718E-04,0.000000E+00,
740,5.153113E-04,1.994949E-04,0.000000E+00,
745,3.631969E-04,1.408466E-04,0.000000E+00,
750,2.556624E-04,9.931439E-05,0.000000E+00,
755,1.809649E-04,7.041878E-05,0.000000E+00,
760,1.287394E-04,5.018934E-05,0.000000E+00,
765,9.172477E-05,3.582218E-05,0.000000E+00,
770,6.577532E-05,2.573083E-05,0.000000E+00,
775,4.708916E-05,1.845353E-05,0.000000E+00,
780,3.407653E-05,1.337946E-05,0.000000E+00,
785,2.469630E-05,9.715798E-06,0.000000E+00,
790,1.794555E-05,7.074424E-06,0.000000E+00,
795,1.306345E-05,5.160948E-06,0.000000E+00,
800,9.565993E-06,3.788729E-06,0.000000E+00,
805,7.037621E-06,2.794625E-06,0.000000E+00,
810,5.166853E-06,2.057152E-06,0.000000E+00,
815,3.815429E-06,1.523114E-06,0.000000E+00,
820,2.837980E-06,1.135758E-06,0.000000E+00,
825,2.113325E-06,8.476168E-07,0.000000E+00,
830,1.579199E-06,6.345380E-07,0.000000E+00
];
/* Get blackbody radiation (in arbitraty units) at some wavelength...
* http://astronomy.swin.edu.au/cosmos/B/Blackbody+Radiation
* https://en.wikipedia.org/wiki/Black-body_radiation#Equations
* https://en.wikipedia.org/wiki/Planck%27s_law
* (Planck's law but with some constants removed) */
function get_blackbody_radiation(kelvin, wavelength)
{
/* This may be inaccurate (extremely small values involved) */
let h = 6.62607004e-34; /* Planck constant */
let k = 1.38064852e-23; /* Boltzman constant */
let c = 299792458; /* Speed of light */
let T = kelvin;
wavelength /= 1000000000; /* To metres instead of nm */
let lambda5 = Math.pow(wavelength, 5.0); /* Wavelength ^ 5 */
return 1.0 / (lambda5 * (Math.pow(Math.E, (h*c)/(wavelength*k*T) - 1.0)));
}
/* Kelvin to XYZ. Method: calculate spectral distrbution and match it to XYZ */
function kelvin_to_XYZ(temperature)
{
let X = 0, Y = 0, Z = 0;
/* Calculate at 5nm intervals (as the colour match data is) */
for (let w = 0; w < (XYZ_colour_match.length/4); w++)
{
let wavelength = XYZ_colour_match[w*4];
let radiation = get_blackbody_radiation(temperature, wavelength);
X += radiation * XYZ_colour_match[w*4+1];
Y += radiation * XYZ_colour_match[w*4+2];
Z += radiation * XYZ_colour_match[w*4+3];
}
/* Normalise */
var colour = {
X: X/Y,
Y: Y/Y,
Z: Z/Y
};
return colour;
}
// the rest of the code is just handling user interaction/HTML stuff and conversion to sRGB
function change_temp(temp) {
let col = kelvin_to_XYZ(temp);
// xyz to srgb
let matrix = [ 3.2404542, -1.5371385, -0.4985314,
-0.9692660, 1.8760108, 0.0415560,
0.0556434, -0.2040259, 1.0572252 ];
let R = col.X*matrix[0] + col.Y*matrix[1] + col.Z*matrix[2];
let G = col.X*matrix[3] + col.Y*matrix[4] + col.Z*matrix[5];
let B = col.X*matrix[6] + col.Y*matrix[7] + col.Z*matrix[8];
let max = Math.max(R, Math.max(G, B));
R = gamma(R/max) * 255;
G = gamma(G/max) * 255;
B = gamma(B/max) * 255;
let style = "rgb("+parseInt(R+0.5).toString()+","+parseInt(G+0.5).toString()+","+parseInt(B+0.5).toString()+")";
console.log("Temp: " + temp.toString() + " RGB: " + style);
document.getElementById("Body").style = "background-color: " + style + ";";
document.getElementById("TempLabel").innerHTML = temp.toString()+" Kelvin<br /><br />sRGB: "+parseInt(R+0.5).toString()+","+parseInt(G+0.5).toString()+","+parseInt(B+0.5).toString()+"<br /><br />XYZ: "+col.X.toPrecision(3).toString()+", "+col.Y.toPrecision(3).toString()+", "+col.Z.toPrecision(3).toString();
if (R > 0) { if (G > 0) { if (B > 0) {return;} } }
document.getElementById("TempLabel").innerHTML = document.getElementById("TempLabel").innerHTML.replace("n", "n (PREVIEW CLIPPED NOT ACCURATE)");
}
function slider() {
change_temp(document.getElementById("TempSlider").value);
}
function test() {
slider();
}
</script>
<div style="margin: auto; width:50%;">
<!-- https://en.wikipedia.org/wiki/Black_body -->
<br></br>
<code style="font-size:18px;">Blackbody to XYZ conversion using Planck's law and XYZ matching functions.</code>
<br></br>
<code style="font-size:18px;">The brightness is normalised so only colour is shown. Lower temperatures are much darker and higher temperatures are much brighter in real life.</code>
<br></br>
<code id="TempLabel" style="font-size:18px;">y</code>
<br></br>
<input id="TempSlider" style="width: 100%;" type="range" min="1000" max="20000" value="5600" oninput="slider()" onchange="slider()"></input>
</div>
</body>
</html>