chroma.js icon indicating copy to clipboard operation
chroma.js copied to clipboard

conversion form color temperatures below 2000k results in 1000k

Open Christian-Me opened this issue 2 years ago • 0 comments

The algorithm used for converting RGB to temperature fails for temperatures below 2000k (i.e. chroma.temperature(1500) results in chroma.temperature() = 1000k) This is due to the fact that blue is constant 0 and red constant 1 (255) below 2000k. image

A fix could look like this taking green into account for values below 2000k

/*
 * Based on implementation by Neil Bartlett
 * https://github.com/neilbartlett/color-temperature
 * with modifications for temp < 2000k
 **/

const temperature2rgb = require('./temperature2rgb');
const {unpack} = require('../../utils');
const {round} = Math;

const rgb2temperature = (...args) => {
    const rgb = unpack(args, 'rgb');
    const r = rgb[0], g = rgb[1], b = rgb[2];
    let minTemp = 1000;
    let maxTemp = 40000;
    const eps = 0.4;
    let temp;
    while (maxTemp - minTemp > eps) {
        temp = (maxTemp + minTemp) * 0.5;
        const rgb = temperature2rgb(temp);
        if (b>0) { // temperatures above 2000k
            if ((rgb[2] / rgb[0]) >= (b / r)) {
                maxTemp = temp;
            } else {
                minTemp = temp;
            }
        } else { // below 2000k blue becomes constant 0 and red constant 255! Only green is relevant here
            if (rgb[1] >= g) {
                maxTemp = temp;
            } else {
                minTemp = temp;
            }
        }
    }
    return round(temp);
}

module.exports = rgb2temperature;

If this makes sense I can provide a PR. Thank you for this great library.

Christian-Me avatar Jan 31 '22 18:01 Christian-Me