color-temperature
Version:
Kelvin color temperature to RGB convertor
184 lines (158 loc) • 5.3 kB
JavaScript
/**
* color-temperature.js
*
* Neil Bartlett
* neilbartlett.com
* 2015-01-22
*
* Copyright [2015] [Neil Bartlett] *
*
* Color Temperature is the color due to black body radiation at a given
* temperature. The temperature is given in Kelvin. The concept is widely used
* in photography and in tools such as f.lux.
*
* The function here converts a given color temperature into a near equivalent
* in the RGB colorspace. The function is based on a curve fit on standard sparse
* set of Kelvin to RGB mappings.
*
* Two conversions are presented here. The one colorTempertature2RGBUSingTH
* is a JS version of the algorithm developed by Tanner Helland. The second is a
* slightly more accurate conversion based on a refitting of the original data
* using different curve fit functions. The performance cost of the two
* approaches is very similar and in general the second algorithm is preferred.
*
* NOTE The approximations used are suitable for photo-mainpulation and other
* non-critical uses. They are not suitable for medical or other high accuracy
* use cases.
*
* Accuracy is best between 1000K and 40000K.
*
* See http://github.com/neilbartlett/color-temperature for further details.
*
**/
/**
* A JS verion of Tanner Helland's original algorithm.
* Input: color temperature in degrees Kelvin
* Output: json object of red, green and blue components of the Kelvin temperature
*/
module.exports.colorTemperature2rgbUsingTH = colorTemperature2rgbUsingTH = function(kelvin) {
var temperature = kelvin / 100.0;
var red, green, blue;
if (temperature <= 66.0) {
red = 255;
} else {
red = temperature - 60.0;
red = 329.698727446 * Math.pow(red, -0.1332047592);
if (red < 0) red = 0;
if (red > 255) red = 255;
}
/* Calculate green */
if (temperature <= 66.0) {
green = temperature;
green = 99.4708025861 * Math.log(green) - 161.1195681661;
if (green < 0) green = 0;
if (green > 255) green = 255;
} else {
green = temperature - 60.0;
green = 288.1221695283 * Math.pow(green, -0.0755148492);
if (green < 0) green = 0;
if (green > 255) green = 255;
}
/* Calculate blue */
if (temperature >= 66.0) {
blue = 255;
} else {
if (temperature <= 19.0) {
blue = 0;
} else {
blue = temperature - 10;
blue = 138.5177312231 * Math.log(blue) - 305.0447927307;
if (blue < 0) blue = 0;
if (blue > 255) blue = 255;
}
}
return {red: Math.round(red), blue: Math.round(blue), green: Math.round(green)};
}
/**
* A more accurate version algorithm based on a different curve fit to the
* original RGB to Kelvin data.
* Input: color temperature in degrees Kelvin
* Output: json object of red, green and blue components of the Kelvin temperature
*/
module.exports.colorTemperature2rgb = colorTemperature2rgb = function(kelvin) {
var temperature = kelvin / 100.0;
var red, green, blue;
if (temperature < 66.0) {
red = 255;
} else {
// a + b x + c Log[x] /.
// {a -> 351.97690566805693`,
// b -> 0.114206453784165`,
// c -> -40.25366309332127
//x -> (kelvin/100) - 55}
red = temperature - 55.0;
red = 351.97690566805693+ 0.114206453784165 * red - 40.25366309332127 * Math.log(red);
if (red < 0) red = 0;
if (red > 255) red = 255;
}
/* Calculate green */
if (temperature < 66.0) {
// a + b x + c Log[x] /.
// {a -> -155.25485562709179`,
// b -> -0.44596950469579133`,
// c -> 104.49216199393888`,
// x -> (kelvin/100) - 2}
green = temperature - 2;
green = -155.25485562709179 - 0.44596950469579133 * green + 104.49216199393888 * Math.log(green);
if (green < 0) green = 0;
if (green > 255) green = 255;
} else {
// a + b x + c Log[x] /.
// {a -> 325.4494125711974`,
// b -> 0.07943456536662342`,
// c -> -28.0852963507957`,
// x -> (kelvin/100) - 50}
green = temperature - 50.0;
green = 325.4494125711974 + 0.07943456536662342 * green - 28.0852963507957 * Math.log(green);
if (green < 0) green = 0;
if (green > 255) green = 255;
}
/* Calculate blue */
if (temperature >= 66.0) {
blue = 255;
} else {
if (temperature <= 20.0) {
blue = 0;
} else {
// a + b x + c Log[x] /.
// {a -> -254.76935184120902`,
// b -> 0.8274096064007395`,
// c -> 115.67994401066147`,
// x -> kelvin/100 - 10}
blue = temperature - 10;
blue = -254.76935184120902 + 0.8274096064007395 * blue + 115.67994401066147 * Math.log(blue);
if (blue < 0) blue = 0;
if (blue > 255) blue = 255;
}
}
return {red: Math.round(red), blue: Math.round(blue), green: Math.round(green)};
}
/**
convert an rgb in JSON format into to a Kelvin color temperature
*/
module.exports.rgb2colorTemperature = rgb2colorTemperature = function(rgb) {
var temperature, testRGB;
var epsilon=0.4;
var minTemperature = 1000;
var maxTemperature = 40000;
while (maxTemperature - minTemperature > epsilon) {
temperature = (maxTemperature + minTemperature) / 2;
testRGB = colorTemperature2rgb(temperature);
if ((testRGB.blue / testRGB.red) >= (rgb.blue / rgb.red)) {
maxTemperature = temperature;
} else {
minTemperature = temperature;
}
}
return Math.round(temperature);
};