homebridge-virtual-accessories
Version:
Virtual HomeKit accessories for Homebridge.
146 lines • 4.74 kB
JavaScript
export class ColorHSL {
hue;
saturation;
luminance;
constructor(hue, saturation, luminance) {
this.hue = hue;
this.saturation = saturation;
this.luminance = luminance;
}
}
export class ColorRGB {
red;
green;
blue;
constructor(red, green, blue) {
this.red = red;
this.green = green;
this.blue = blue;
}
}
/**
* Colors
*/
export class Colors {
static isValidHex(value) {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(value);
return (result !== undefined);
}
static HSLToHex(hsl) {
const hue = hsl.hue;
const saturation = hsl.saturation;
const luminance = hsl.luminance;
const hueDecimal = luminance / 100;
const a = (saturation * Math.min(hueDecimal, 1 - hueDecimal)) / 100;
const hexFunc = (n) => {
const k = (n + hue / 30) % 12;
const color = hueDecimal - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
// Convert to Hex and prefix with "0" if required
return Math.round(255 * color)
.toString(16)
.padStart(2, '0');
};
return `#${hexFunc(0)}${hexFunc(8)}${hexFunc(4)}`;
}
static HexToHSL(hex) {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
if (!result) {
return undefined;
}
const red = parseInt(result[1], 16) / 255;
const green = parseInt(result[2], 16) / 255;
const blue = parseInt(result[3], 16) / 255;
const max = Math.max(red, green, blue);
const min = Math.min(red, green, blue);
let hue = (max + min) / 2;
let saturation = hue;
let luminance = hue;
if (max === min) {
// Achromatic
return new ColorHSL(0, 0, luminance);
}
const d = max - min;
saturation = luminance > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case red:
hue = (green - blue) / d + (green < blue ? 6 : 0);
break;
case green:
hue = (blue - red) / d + 2;
break;
case blue:
hue = (red - green) / d + 4;
break;
}
hue /= 6;
saturation = saturation * 100;
saturation = Math.round(saturation);
luminance = luminance * 100;
luminance = Math.round(luminance);
hue = Math.round(360 * hue);
return new ColorHSL(hue, saturation, luminance);
}
static HSLToRGB(hsl) {
const hue = hsl.hue / 100;
const saturation = hsl.saturation / 100;
const luminance = hsl.luminance / 100;
if (saturation === 0) {
return new ColorRGB(luminance, luminance, luminance);
}
const HueToRGB = (p, q, t) => {
if (t < 0) {
t += 1;
}
if (t > 1) {
t -= 1;
}
if (t < 1 / 6) {
return p + (q - p) * 6 * t;
}
if (t < 1 / 2) {
return q;
}
if (t < 2 / 3) {
return p + (q - p) * (2 / 3 - t) * 6;
}
return p;
};
const q = luminance < 0.5 ?
luminance * (1 + saturation) :
luminance + saturation - luminance * saturation;
const p = 2 * luminance - q;
const red = HueToRGB(p, q, hue + 1 / 3);
const green = HueToRGB(p, q, hue);
const blue = HueToRGB(p, q, hue - 1 / 3);
return new ColorRGB(red * 255, green * 255, blue * 255);
}
static RGBToHSL(rgb) {
const red = rgb.red / 255;
const green = rgb.green / 255;
const blue = rgb.blue / 255;
const max = Math.max(red, green, blue);
const min = Math.min(red, green, blue);
let hue = (max + min) / 2;
let saturation = hue;
const luminance = hue;
if (max === min) {
// Achromatic
return new ColorHSL(0, 0, luminance);
}
const d = max - min;
saturation = luminance >= 0.5 ? d / (2 - (max + min)) : d / (max + min);
switch (max) {
case red:
hue = ((green - blue) / d + 0) * 60;
break;
case green:
hue = ((blue - red) / d + 2) * 60;
break;
case blue:
hue = ((red - green) / d + 4) * 60;
break;
}
return new ColorHSL(Math.round(hue), Math.round(saturation * 100), Math.round(luminance * 100));
}
}
//# sourceMappingURL=colorUtils.js.map