colortemp 0.1.0

Simple functions to calculate color temperatures and RGB values
Documentation
//! 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;
    }
}