lifehash
Version:
TypeScript/JavaScript implementation of LifeHash, a visual hash algorithm
80 lines (79 loc) • 2.45 kB
JavaScript
import { Color } from './Color.js';
import { clamped, modulo } from './math-utils.js';
export class HSBColor {
constructor(hue, saturation = 1, brightness = 1) {
this.hue = hue;
this.saturation = saturation;
this.brightness = brightness;
}
to_color() {
const v = clamped(this.brightness);
const s = clamped(this.saturation);
let red;
let green;
let blue;
if (s <= 0) {
[red, green, blue] = [v, v, v];
}
else {
let h = modulo(this.hue, 1);
if (h < 0) {
h += 1;
}
h *= 6;
const i = Math.floor(h);
const f = h - i;
const p = v * (1 - s);
const q = v * (1 - s * f);
const t = v * (1 - s * (1 - f));
switch (i) {
case 0:
[red, green, blue] = [v, t, p];
break;
case 1:
[red, green, blue] = [q, v, p];
break;
case 2:
[red, green, blue] = [p, v, t];
break;
case 3:
[red, green, blue] = [p, q, v];
break;
case 4:
[red, green, blue] = [t, p, v];
break;
case 5:
[red, green, blue] = [v, p, q];
break;
default:
throw new Error('Internal error.');
}
}
return new Color(red, green, blue);
}
static make_from_color(color) {
const [r, g, b] = [color.r, color.g, color.b];
const max_value = Math.max(r, g, b);
const min_value = Math.min(r, g, b);
const brightness = max_value;
const d = max_value - min_value;
const saturation = max_value === 0 ? 0 : d / max_value;
let hue;
if (max_value === min_value) {
hue = 0;
}
else if (max_value === r) {
hue = ((g - b) / d + (g < b ? 6 : 0)) / 6;
}
else if (max_value === g) {
hue = ((b - r) / d + 2) / 6;
}
else if (max_value === b) {
hue = ((r - g) / d + 4) / 6;
}
else {
throw new Error('Internal error.');
}
return new HSBColor(hue, saturation, brightness);
}
}