UNPKG

@valeera/mathx

Version:

A math library written in TS.

225 lines (182 loc) 4.91 kB
import { IColorRGBA, IColorRGBAJson } from "./interfaces/IColorRGBA"; import { COLOR_HEX_MAP } from "./COLOR_HEX_MAP"; import { IColorRGB } from "./interfaces/IColorRGB"; import { ArraybufferDataType } from "../ArraybufferDataType"; import { WEIGHT_GRAY_RED, WEIGHT_GRAY_GREEN, WEIGHT_GRAY_BLUE } from "../constants"; import { IColorRYB } from "./interfaces/IColorRYB"; import { hue2rgb } from "./utils"; export class ColorRGBA extends Uint8Array implements IColorRGBA { public static average = (color: IColorRGB | IColorRGBA): number => { return (color[0] + color[1] + color[2]) / 3; }; public static averageWeighted = ( color: IColorRGB | IColorRGBA | ArrayLike<number>, wr = WEIGHT_GRAY_RED, wg = WEIGHT_GRAY_GREEN, wb = WEIGHT_GRAY_BLUE, ): number => { return color[0] * wr + color[1] * wg + color[2] * wb; }; public static clone = (color: IColorRGBA | ArrayLike<number>): IColorRGBA => { return new ColorRGBA(color[0], color[1], color[2], color[3]); }; public static create = (r = 0, g = 0, b = 0, a = 1): IColorRGBA => { return new ColorRGBA(r, g, b, a); }; public static equals = (a: IColorRGBA, b: IColorRGBA): boolean => { return ( (a.r ?? a[0]) === (b.r ?? b[0]) && (a.g ?? a[1]) === (b.g ?? b[1]) && (a.b ?? a[2]) === (b.b ?? b[2]) && (a.a ?? a[3]) === (b.a ?? b[3]) ); }; public static fromArray = (arr: ArrayLike<number>, out: IColorRGBA = new ColorRGBA()): IColorRGBA => { out[0] = arr[0]; out[1] = arr[1]; out[2] = arr[2]; out[3] = arr[3]; return out; }; public static fromColorRYB = ( color: IColorRYB | number[] | Uint8Array, out: IColorRGBA = new ColorRGBA(), ): IColorRGBA => { let r = color[0]; let y = color[1]; let b = color[2]; // Remove the whiteness from the color. let w = Math.min(r, y, b); r -= w; y -= w; b -= w; let my = Math.max(r, y, b); // Get the green out of the yellow and blue let g = Math.min(y, b); y -= g; b -= g; if (b && g) { b *= 2.0; g *= 2.0; } // Redistribute the remaining yellow. r += y; g += y; // Normalize to values. let mg = Math.max(r, g, b); if (mg) { let n = my / mg; r *= n; g *= n; b *= n; } // Add the white back in. r += w; g += w; b += w; out[0] = r; out[1] = g; out[2] = b; out[3] = 1; return out; }; public static fromHex = (hex: number, alpha = 255, out: IColorRGBA = new ColorRGBA()): IColorRGBA => { out[0] = hex >> 16; out[1] = (hex >> 8) & 255; out[2] = hex & 255; out[3] = alpha; return out; }; public static fromHSL = (h: number, s: number, l: number, out = new ColorRGBA()) => { let r; let g; let b; if (s === 0) { r = g = b = l; // achromatic } else { let q = l < 0.5 ? l * (1 + s) : l + s - l * s; let p = 2 * l - q; r = hue2rgb(p, q, h + 1 / 3); g = hue2rgb(p, q, h); b = hue2rgb(p, q, h - 1 / 3); } out[0] = Math.round(r * 255); out[1] = Math.round(g * 255); out[2] = Math.round(b * 255); out[3] = 255; return out; }; public static fromJson = (json: IColorRGBAJson, out: IColorRGBA = new ColorRGBA()): IColorRGBA => { out[0] = json.r; out[1] = json.g; out[2] = json.b; out[3] = json.a; return out; }; public static fromScalar = (scalar: number, alpha = 255, out: IColorRGBA = new ColorRGBA()): IColorRGBA => { out[0] = scalar; out[1] = scalar; out[2] = scalar; out[3] = alpha; return out; }; public static fromString = (str: string, out: IColorRGBA = new ColorRGBA()): IColorRGBA => { if (str in COLOR_HEX_MAP) { return ColorRGBA.fromHex(COLOR_HEX_MAP[str], 255, out); } else if (str.startsWith("#")) { str = str.substring(1); return ColorRGBA.fromScalar(parseInt(str, 16), 255, out); } else if (str.startsWith("rgba(")) { str = str.substring(4, str.length - 1); const arr = str.split(","); out[0] = parseInt(arr[0], 10); out[1] = parseInt(arr[1], 10); out[2] = parseInt(arr[2], 10); out[3] = parseInt(arr[3], 10); } return out; }; public static grayscale = ( color: IColorRGBA | ArrayLike<number>, wr = WEIGHT_GRAY_RED, wg = WEIGHT_GRAY_GREEN, wb = WEIGHT_GRAY_BLUE, out: IColorRGBA = new ColorRGBA(), ): IColorRGBA => { const gray = ColorRGBA.averageWeighted(color, wr, wg, wb); ColorRGBA.fromScalar(gray, color[3], out); return out; }; public readonly dataType = ArraybufferDataType.COLOR_RGBA; public constructor(r = 0, g = 0, b = 0, a = 255) { super(4); this[0] = r; this[1] = g; this[2] = b; this[3] = a; } public get r(): number { return this[0]; } public set r(val: number) { this[0] = val; } public get g(): number { return this[1]; } public set g(val: number) { this[1] = val; } public get b(): number { return this[2]; } public set b(val: number) { this[2] = val; } public get a(): number { return this[3]; } public set a(val: number) { this[3] = val; } }