```  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
```
```//! A simple crate that calculates color temperatures
//!
//! It implements an algorithm by Tanner Helland that calculates
//! RGB values for specific color temperatures. It can also do
//! the inverse by aproxmiation.
//!
//! This crate includes unit tests to ensure functionality
//!
//! ## Examples
//!
//! Following are some simple examples of how to use this crate
//!
//! ```rust
//! extern crate colortemp;
//!
//! let mut rgb = colortemp::temp_to_rgb(2000);
//! println!("{:?}", rgb);
//! ```
//!
//! The values generated by this crate can include uncertainty
//! and might therefore not be suitable for scientific computing.
//!
//! If you wish to change this, PR's are always welcome 😁

mod tests;

macro_rules! normalise {
(\$x:expr) => {{
if \$x < 0.0 {
\$x = 0.;
} else if \$x > 255.0 {
\$x = 255.0;
}
}};
}

pub use colortemp::*;
mod colortemp {

/// A simple container format to describe an RGB value
#[derive(Debug, PartialEq)]
pub struct RGB {
pub r: f64,
pub g: f64,
pub b: f64,
}

// Calculate the RGB value of a color temperature (in Kelvin)
pub fn temp_to_rgb(kelvin: i64) -> RGB {
let (mut r, mut g, mut b);
let temp = kelvin / 100;

/* Calculate red */
if temp <= 66 {
r = 255.;
} else {
r = (temp as f64) - 60.;
r = 329.698727446 * r.powf(-329.698727446);
normalise!(r);
}

/* Calculate green */
if temp <= 66 {
g = temp as f64;
g = 99.4708025861 * g.ln() - 161.1195681661;
normalise!(g);
} else {
g = temp as f64 - 60.;
g = 288.1221695283 * g.powf(-0.0755148492);
normalise!(g);
}

/* Feeling bluueeee */
if temp >= 66 {
b = 255.;
} else {

if temp <= 19 {
b = 0.;
} else {
b = temp as f64 - 10.;
b = 138.5177312231 * b.ln() - 305.0447927307;
normalise!(b);
}
}

return RGB {
r: r.round(),
g: g.round(),
b: b.round(),
};
}

/// Calculates the color temperature for a given RGB value
///
/// This is implemented via a reverse lookup onto @temperature_to_rgb and
/// as such should be considered rather slow
///
pub fn rgb_to_temp(col: RGB) -> i64 {
let (r, b) = (col.r, col.b);

let mut temp = 0;
let mut test_rgb;

let epsilon = 2.;
let (mut min, mut max) = (1000, 40000);

while (max as f64) - (min as f64) > epsilon {
temp = (max + min) / 2;
test_rgb = temp_to_rgb(temp);
if (test_rgb.b / test_rgb.r) >= (b / r) {
max = temp;
} else {
min = temp;
}
}

return temp;
}
}
```