soiz1's picture
Upload 225 files
7aec436 verified
// RGB <-> HSV conversion functions are based on https://github.com/LLK/scratch-vm/blob/develop/src/util/color.js
/**
* @typedef RGB
* @property {number} red red [0-255]
* @property {number} green green [0-255]
* @property {number} blue blue [0-255]
*/
/**
* @typedef HSV
* @property {number} hue hue [0-360)
* @property {number} saturation saturation [0-1]
* @property {number} value value [0-1]
*/
/**
* @param {string} hex
* @returns {RGB}
*/
export const hexToRgb = (hex) => {
const parsed = parseInt(hex.substring(1), 16);
return {
red: (parsed >> 16) & 0xff,
green: (parsed >> 8) & 0xff,
blue: parsed & 0xff
};
};
/**
* @param {RGB} color
* @returns {string}
*/
export const rgbToHex = (color) => {
const format = (n) => n.toString(16).padStart(2, '0');
return `#${format(color.red)}${format(color.green)}${format(color.blue)}`;
};
/**
* @param {RGB} color
* @returns {HSV}
*/
export const rgbToHsv = (color) => {
const r = color.red / 255;
const g = color.green / 255;
const b = color.blue / 255;
const x = Math.min(Math.min(r, g), b);
const v = Math.max(Math.max(r, g), b);
// For grays, hue will be arbitrarily reported as zero. Otherwise, calculate
let h = 0;
let s = 0;
if (x !== v) {
const f = r === x ? g - b : g === x ? b - r : r - g;
const i = r === x ? 3 : g === x ? 5 : 1;
h = ((i - f / (v - x)) * 60) % 360;
s = (v - x) / v;
}
return {
hue: h,
saturation: s,
value: v
};
};
/**
* @param {HSV} color
* @returns {RGB}
*/
export const hsvToRgb = (color) => {
let h = color.hue % 360;
if (h < 0) h += 360;
const s = Math.max(0, Math.min(color.saturation, 1));
const v = Math.max(0, Math.min(color.value, 1));
const i = Math.floor(h / 60);
const f = h / 60 - i;
const p = v * (1 - s);
const q = v * (1 - s * f);
const t = v * (1 - s * (1 - f));
let r;
let g;
let b;
switch (i) {
default:
case 0:
r = v;
g = t;
b = p;
break;
case 1:
r = q;
g = v;
b = p;
break;
case 2:
r = p;
g = v;
b = t;
break;
case 3:
r = p;
g = q;
b = v;
break;
case 4:
r = t;
g = p;
b = v;
break;
case 5:
r = v;
g = p;
b = q;
break;
}
return {
red: Math.floor(r * 255),
green: Math.floor(g * 255),
blue: Math.floor(b * 255),
};
};
/**
* @param {string} hex
* @returns {string}
*/
export const darken = (hex) => {
const rgb = hexToRgb(hex);
const hsv = rgbToHsv(rgb);
// don't need to clamp value; hsvToRgb will do it for us
hsv.value -= 0.1;
const newRgb = hsvToRgb(hsv);
return rgbToHex(newRgb);
};