107 lines
3 KiB
JavaScript
107 lines
3 KiB
JavaScript
// Source: https://gist.github.com/uredkar/bd305f2dda9abf5b393d417424777c87#file-cie_rgb_converter-js
|
|
|
|
/**
|
|
* Converts CIE color space to RGB color space
|
|
* @param {Number} x
|
|
* @param {Number} y
|
|
* @param {Number} brightness - Ranges from 1 to 254
|
|
* @return {Array} Array that contains the color values for red, green and blue
|
|
*/
|
|
function toRGB(x, y, brightness) {
|
|
//Set to maximum brightness if no custom value was given (Not the slick ECMAScript 6 way for compatibility reasons)
|
|
if (brightness === undefined) {
|
|
brightness = 254;
|
|
}
|
|
|
|
var z = 1.0 - x - y;
|
|
var Y = (brightness / 254).toFixed(2);
|
|
var X = (Y / y) * x;
|
|
var Z = (Y / y) * z;
|
|
|
|
//Convert to RGB using Wide RGB D65 conversion
|
|
var red = X * 1.656492 - Y * 0.354851 - Z * 0.255038;
|
|
var green = -X * 0.707196 + Y * 1.655397 + Z * 0.036152;
|
|
var blue = X * 0.051713 - Y * 0.121364 + Z * 1.011530;
|
|
|
|
//If red, green or blue is larger than 1.0 set it back to the maximum of 1.0
|
|
if (red > blue && red > green && red > 1.0) {
|
|
|
|
green = green / red;
|
|
blue = blue / red;
|
|
red = 1.0;
|
|
}
|
|
else if (green > blue && green > red && green > 1.0) {
|
|
|
|
red = red / green;
|
|
blue = blue / green;
|
|
green = 1.0;
|
|
}
|
|
else if (blue > red && blue > green && blue > 1.0) {
|
|
|
|
red = red / blue;
|
|
green = green / blue;
|
|
blue = 1.0;
|
|
}
|
|
|
|
//Reverse gamma correction
|
|
red = red <= 0.0031308 ? 12.92 * red : (1.0 + 0.055) * Math.pow(red, (1.0 / 2.4)) - 0.055;
|
|
green = green <= 0.0031308 ? 12.92 * green : (1.0 + 0.055) * Math.pow(green, (1.0 / 2.4)) - 0.055;
|
|
blue = blue <= 0.0031308 ? 12.92 * blue : (1.0 + 0.055) * Math.pow(blue, (1.0 / 2.4)) - 0.055;
|
|
|
|
|
|
//Convert normalized decimal to decimal
|
|
red = Math.round(red * 255);
|
|
green = Math.round(green * 255);
|
|
blue = Math.round(blue * 255);
|
|
|
|
if (isNaN(red))
|
|
red = 0;
|
|
|
|
if (isNaN(green))
|
|
green = 0;
|
|
|
|
if (isNaN(blue))
|
|
blue = 0;
|
|
|
|
|
|
return [red, green, blue];
|
|
}
|
|
|
|
|
|
/**
|
|
* Converts RGB color space to CIE color space
|
|
* @param {Number} red
|
|
* @param {Number} green
|
|
* @param {Number} blue
|
|
* @return {Array} Array that contains the CIE color values for x and y
|
|
*/
|
|
function toXY(red, green, blue) {
|
|
if (red > 1) { red /= 255; }
|
|
if (green > 1) { green /= 255; }
|
|
if (blue > 1) { blue /= 255; }
|
|
|
|
//Apply a gamma correction to the RGB values, which makes the color more vivid and more the like the color displayed on the screen of your device
|
|
var red = (red > 0.04045) ? Math.pow((red + 0.055) / (1.0 + 0.055), 2.4) : (red / 12.92);
|
|
var green = (green > 0.04045) ? Math.pow((green + 0.055) / (1.0 + 0.055), 2.4) : (green / 12.92);
|
|
var blue = (blue > 0.04045) ? Math.pow((blue + 0.055) / (1.0 + 0.055), 2.4) : (blue / 12.92);
|
|
|
|
//RGB values to XYZ using the Wide RGB D65 conversion formula
|
|
var X = red * 0.664511 + green * 0.154324 + blue * 0.162028;
|
|
var Y = red * 0.283881 + green * 0.668433 + blue * 0.047685;
|
|
var Z = red * 0.000088 + green * 0.072310 + blue * 0.986039;
|
|
|
|
//Calculate the xy values from the XYZ values
|
|
var x = (X / (X + Y + Z)).toFixed(4);
|
|
var y = (Y / (X + Y + Z)).toFixed(4);
|
|
|
|
if (isNaN(x))
|
|
x = 0;
|
|
|
|
if (isNaN(y))
|
|
y = 0;
|
|
|
|
|
|
return [x, y];
|
|
}
|
|
|