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
use cie1931::Cie1931xyY;
#[derive(Debug, Clone, Copy)]
pub struct ColorTemp(pub u16);
impl ColorTemp {
pub fn new(k: u16) -> ColorTemp {
ColorTemp(k)
}
}
impl ColorTemp {
#[allow(non_snake_case)]
pub fn to_cie1931xyY(&self) -> Option<Cie1931xyY>
{
if self.0 < 1667 { return None; }
if self.0 > 25000 { return None; }
let ct = self.0 as f32;
let x = if ct < 4000.0 {
-0.2661239 * (10.0_f32).powi(9) / ct.powi(3)
- 0.2343580 * (10.0_f32).powi(6) / ct.powi(2)
+ 0.8776956 * (10.0_f32).powi(3) / ct
+ 0.179910
} else {
-3.0258469 * (10.0_f32).powi(9) / ct.powi(3)
+ 2.1070379 * (10.0_f32).powi(6) / ct.powi(2)
+ 0.2226347 * (10.0_f32).powi(3) / ct
+ 0.240390
};
let y = if ct < 2222.0 {
-1.1063814 * x.powi(3)
- 1.34811020 * x.powi(2)
+ 2.18444832 * x
- 0.20219683
} else if ct < 4000.0 {
-0.9549476 * x.powi(3)
- 1.37418593 * x.powi(2)
+ 2.09137015 * x
- 0.16748867
} else {
3.0817580 * x.powi(3)
- 5.87338670 * x.powi(2)
+ 3.75112997 * x
- 0.37001483
};
Some(Cie1931xyY::new(x, y, 1.0))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_planckian_locus() {
let ct = ColorTemp::new(2222);
let xy = ct.to_cie1931xyY().unwrap();
assert!(xy.v.x > 0.5030);
assert!(xy.v.x < 0.5035);
assert!(xy.v.y > 0.4151);
assert!(xy.v.y < 0.4154);
let ct = ColorTemp::new(4000);
let xy = ct.to_cie1931xyY().unwrap();
assert!(xy.v.x > 0.3802);
assert!(xy.v.x < 0.3807);
assert!(xy.v.y > 0.3766);
assert!(xy.v.y < 0.3769);
let ct = ColorTemp::new(10000);
let xy = ct.to_cie1931xyY().unwrap();
assert!(xy.v.x > 0.2805);
assert!(xy.v.x < 0.2808);
assert!(xy.v.y > 0.2882);
assert!(xy.v.y < 0.2884);
}
}