@fimbul-works/vec-color
Version:
A comprehensive, type-safe color manipulation library for TypeScript that provides a wide range of color space conversions, blending operations, and accessibility utilities.
71 lines (70 loc) • 2.01 kB
JavaScript
import { Vec3 } from "@fimbul-works/vec";
/**
* Converts color temperature in Kelvin to RGB
* Valid range is 1000K to 40000K
* @param kelvin Temperature in Kelvin (1000-40000)
* @returns Vec3 containing RGB values
* @see https://tannerhelland.com/2012/09/18/convert-temperature-rgb-algorithm-code.html
*/
export function kelvinToRGB(kelvin) {
kelvin = Math.max(1000, Math.min(40000, kelvin));
let r;
let g;
let b;
// Red
if (kelvin <= 6600) {
r = 1;
}
else {
r = ((kelvin / 100 - 60) * -0.0132872 + 1.29293) ** 2;
}
// Green
if (kelvin <= 6600) {
g = ((kelvin / 100 - 2) * 0.017991) ** 2;
}
else {
g = ((kelvin / 100 - 60) * -0.011679 + 1.12989) ** 2;
}
// Blue
if (kelvin <= 2000) {
b = 0;
}
else if (kelvin <= 6600) {
b = ((kelvin / 100 - 10) * 0.0201616) ** 2;
}
else {
b = 1;
}
// Clamp and normalize values
return new Vec3(Math.max(0, Math.min(1, r)), Math.max(0, Math.min(1, g)), Math.max(0, Math.min(1, b)));
}
/**
* Estimates the color temperature of an RGB color
* This is an approximation as not all colors map to a temperature
* @param rgb Vec3 containing RGB values
* @returns Approximate color temperature in Kelvin or null if no good match
*/
export function estimateColorTemperature(rgb, iterations = 20) {
let min = 1000;
let max = 40000;
let closest = null;
let minDiff = Number.POSITIVE_INFINITY;
for (let i = 0; i < iterations; i++) {
const mid = (min + max) / 2;
const test = kelvinToRGB(mid);
const diff = Math.abs(test.x - rgb.x) +
Math.abs(test.y - rgb.y) +
Math.abs(test.z - rgb.z);
if (diff < minDiff) {
minDiff = diff;
closest = mid;
}
if (test.x / test.z > rgb.x / rgb.z) {
max = mid;
}
else {
min = mid;
}
}
return minDiff < 0.5 ? closest : null;
}