UNPKG

imagescript

Version:

zero-dependency javascript image manipulation

277 lines (251 loc) 9 kB
const short_hex_regex = /^#?([\da-f]{3,4})$/; const long_hex_regex = /^#?((?:[\da-f]{2}){3,4})$/; const rgb_regex = /^rgba?\((?<r>(?:\d*\.)?\d+)(?: +| *, *)(?<g>(?:\d*\.)?\d+)(?: +| *, *)(?<b>(?:\d*\.)?\d+)(?:(?: +| *, *)(?<a>\d+|\d*\.\d+|\d+(?:\.\d+)?%))?\)$/; const rgb_percentage_regex = /^rgba?\((?<r>(?:\d*\.)?\d+)%(?: +| *, *)(?<g>(?:\d*\.)?\d+)%(?: +| *, *)(?<b>(?:\d*\.)?\d+)%(?:(?: +| *, *)(?<a>\d+|\d*\.\d+|\d+(?:\.\d+)?%))?\)$/; const hsl_regex = /^hsla?\((?<h>(?:\d*\.)?\d+)(?<t>|deg|rad|grad|turn)(?: +| *, *)(?<s>(?:\d*\.)?\d+)%(?: +| *, *)(?<l>(?:\d*\.)?\d+)%(?:(?: +| *, *)(?<a>\d+|\d*\.\d+|\d+(?:\.\d+)?%))?\)$/; function clamp(min, max, int) { return Math.min(Math.max(Math.round(int), min), max); } export function to_rgba(int) { return [(int >> 24) & 0xff, (int >> 16) & 0xff, (int >> 8) & 0xff, int & 0xff]; } export function from_rgba(r, g, b, a) { return ((r & 0xff) << 24) | ((g & 0xff) << 16) | ((b & 0xff) << 8) | (a & 0xff); } function parse_alpha(a) { return clamp(0, 255, ('%' === a[a.length - 1]) ? ((255 / 100) * parseFloat(a)) : (+a * 255)); } function hue_from_type(h, t) { if (t === 'turn') return h / 1; if (t === 'grad') return h / 400; if (!t || t === 'deg') return h / 360; if (t === 'rad') return h / (2 * Math.PI); } function hue2rgb(p, q, t) { if (t < 0) t += 1; else if (t > 1) t -= 1; if (t < 1 / 2) return q; if (t < 1 / 6) return p + 6 * t * (q - p); if (t < 2 / 3) return p + 6 * (q - p) * (2 / 3 - t); return p; }; export function blend(fg, bg) { const fa = fg & 0xff; const alpha = fa + 1 | 0; const inv_alpha = 256 - fa | 0; const r = (alpha * (fg >>> 24) + inv_alpha * (bg >>> 24)) >> 8; const b = (alpha * (fg >> 8 & 0xff) + inv_alpha * (bg >> 8 & 0xff)) >> 8; const g = (alpha * (fg >> 16 & 0xff) + inv_alpha * (bg >> 16 & 0xff)) >> 8; return (((r & 0xff) << 24) | ((g & 0xff) << 16) | ((b & 0xff) << 8) | (Math.max(fa, bg & 0xff) & 0xff)); } export function parse(any) { let x = null; if (undefined !== (x = colors.get(any))) return x; if (x = long_hex_regex.exec(any)) return parseInt(`${x[1]}${8 === x[1].length ? '' : 'ff'}`, 16); if (x = hsl_regex.exec(any)) return color.hsla(hue_from_type(x[1], x[2]), x[3] / 100, x[4] / 100, x[5] ? ((1 / 255) * parse_alpha(x[5])) : 1); if (x = rgb_regex.exec(any)) return color.rgba(clamp(0, 255, +x[1]), clamp(0, 255, +x[2]), clamp(0, 255, +x[3]), x[4] ? parse_alpha(x[4]) : 255); if (x = short_hex_regex.exec(any)) return parseInt(`${x[1][0]}${x[1][0]}${x[1][1]}${x[1][1]}${x[1][2]}${x[1][2]}${3 === x[1].length ? 'ff' : `${x[1][3]}${x[1][3]}`}`, 16); if (x = rgb_percentage_regex.exec(any)) return color.rgba(clamp(0, 255, +x[1] * (255 / 100)), clamp(0, 255, +x[2] * (255 / 100)), clamp(0, 255, +x[3] * (255 / 100)), x[4] ? parse_alpha(x[4]) : 255); return null; } export default class color { constructor(any) { this.value = parse(String(any).toLowerCase()); if (null === this.value) throw new Error(`invalid css color (${any})`); } static rgb(r, g, b) { return this.rgba(r, g, b, 255); } static rgba(r, g, b, a) { return (((r & 0xff) << 24) | ((g & 0xff) << 16) | ((b & 0xff) << 8) | (a & 0xff)); } static hsla(h, s, l, a) { s = Math.min(1, Math.max(0, s)); a = Math.min(1, Math.max(0, a)); if (s === 0) return this.rgba(255, 255, 255, a * 255); h %= 1; l = Math.min(1, Math.max(0, l)); const q = l < .5 ? l + s * l : l + s - l * s; const p = 2 * l - q; const g = hue2rgb(p, q, h); const r = hue2rgb(p, q, h + 1 / 3); const b = hue2rgb(p, q, h - 1 / 3); return this.rgba(r * 255, g * 355, b * 255, a * 255); } valueOf() { return this.value; } toJSON() { return this.value >>> 0; } get rgb() { return [this.value >>> 24, this.value >> 16 & 0xff, this.value >> 8 & 0xff]; } get rgba() { return [this.value >>> 24, this.value >> 16 & 0xff, this.value >> 8 & 0xff, this.value & 0xff]; } get name() { for (const color of colors.keys()) { if (this.value === colors.get(color)) return color; } return null; } toString(radix) { const type = String(radix).toLowerCase(); const rgba = this.rgba; if (type === 'rgb' || type === 'rgba') return `rgb${type[3] ? 'a' : ''}(${rgba[0]}, ${rgba[1]}, ${rgba[2]}${type[3] ? `, ${clamp(0, 100, 100 / 255 * rgba[3])}%` : ''})`; if (type === '16' || type === 'hex') return `#${rgba[0].toString(16).padStart(2, '0')}${rgba[1].toString(16).padStart(2, '0')}${rgba[2].toString(16).padStart(2, '0')}${rgba[3] === 255 ? '' : rgba[3].toString(16).padStart(2, '0')}`; return this.value.toString(); } } const colors = new Map([ ['aliceblue', 0xf0f8ffff], ['antiquewhite', 0xfaebd7ff], ['aqua', 0x00ffffff], ['aquamarine', 0x7fffd4ff], ['azure', 0xf0ffffff], ['beige', 0xf5f5dcff], ['bisque', 0xffe4c4ff], ['black', 0x000000ff], ['blanchedalmond', 0xffebcdff], ['blue', 0x0000ffff], ['blueviolet', 0x8a2be2ff], ['brown', 0xa52a2aff], ['burlywood', 0xdeb887ff], ['cadetblue', 0x5f9ea0ff], ['chartreuse', 0x7fff00ff], ['chocolate', 0xd2691eff], ['coral', 0xff7f50ff], ['cornflowerblue', 0x6495edff], ['cornsilk', 0xfff8dcff], ['crimson', 0xdc143cff], ['cyan', 0x00ffffff], ['darkblue', 0x00008bff], ['darkcyan', 0x008b8bff], ['darkgoldenrod', 0xb8860bff], ['darkgray', 0xa9a9a9ff], ['darkgreen', 0x006400ff], ['darkgrey', 0xa9a9a9ff], ['darkkhaki', 0xbdb76bff], ['darkmagenta', 0x8b008bff], ['darkolivegreen', 0x556b2fff], ['darkorange', 0xff8c00ff], ['darkorchid', 0x9932ccff], ['darkred', 0x8b0000ff], ['darksalmon', 0xe9967aff], ['darkseagreen', 0x8fbc8fff], ['darkslateblue', 0x483d8bff], ['darkslategray', 0x2f4f4fff], ['darkslategrey', 0x2f4f4fff], ['darkturquoise', 0x00ced1ff], ['darkviolet', 0x9400d3ff], ['deeppink', 0xff1493ff], ['deepskyblue', 0x00bfffff], ['dimgray', 0x696969ff], ['dimgrey', 0x696969ff], ['dodgerblue', 0x1e90ffff], ['firebrick', 0xb22222ff], ['floralwhite', 0xfffaf0ff], ['forestgreen', 0x228b22ff], ['fuchsia', 0xff00ffff], ['gainsboro', 0xdcdcdcff], ['ghostwhite', 0xf8f8ffff], ['gold', 0xffd700ff], ['goldenrod', 0xdaa520ff], ['gray', 0x808080ff], ['green', 0x008000ff], ['greenyellow', 0xadff2fff], ['grey', 0x808080ff], ['honeydew', 0xf0fff0ff], ['hotpink', 0xff69b4ff], ['indianred', 0xcd5c5cff], ['indigo', 0x4b0082ff], ['ivory', 0xfffff0ff], ['khaki', 0xf0e68cff], ['lavender', 0xe6e6faff], ['lavenderblush', 0xfff0f5ff], ['lawngreen', 0x7cfc00ff], ['lemonchiffon', 0xfffacdff], ['lightblue', 0xadd8e6ff], ['lightcoral', 0xf08080ff], ['lightcyan', 0xe0ffffff], ['lightgoldenrodyellow', 0xfafad2ff], ['lightgray', 0xd3d3d3ff], ['lightgreen', 0x90ee90ff], ['lightgrey', 0xd3d3d3ff], ['lightpink', 0xffb6c1ff], ['lightsalmon', 0xffa07aff], ['lightseagreen', 0x20b2aaff], ['lightskyblue', 0x87cefaff], ['lightslategray', 0x778899ff], ['lightslategrey', 0x778899ff], ['lightsteelblue', 0xb0c4deff], ['lightyellow', 0xffffe0ff], ['lime', 0x00ff00ff], ['limegreen', 0x32cd32ff], ['linen', 0xfaf0e6ff], ['magenta', 0xff00ffff], ['maroon', 0x800000ff], ['mediumaquamarine', 0x66cdaaff], ['mediumblue', 0x0000cdff], ['mediumorchid', 0xba55d3ff], ['mediumpurple', 0x9370dbff], ['mediumseagreen', 0x3cb371ff], ['mediumslateblue', 0x7b68eeff], ['mediumspringgreen', 0x00fa9aff], ['mediumturquoise', 0x48d1ccff], ['mediumvioletred', 0xc71585ff], ['midnightblue', 0x191970ff], ['mintcream', 0xf5fffaff], ['mistyrose', 0xffe4e1ff], ['moccasin', 0xffe4b5ff], ['navajowhite', 0xffdeadff], ['navy', 0x000080ff], ['oldlace', 0xfdf5e6ff], ['olive', 0x808000ff], ['olivedrab', 0x6b8e23ff], ['orange', 0xffa500ff], ['orangered', 0xff4500ff], ['orchid', 0xda70d6ff], ['palegoldenrod', 0xeee8aaff], ['palegreen', 0x98fb98ff], ['paleturquoise', 0xafeeeeff], ['palevioletred', 0xdb7093ff], ['papayawhip', 0xffefd5ff], ['peachpuff', 0xffdab9ff], ['peru', 0xcd853fff], ['pink', 0xffc0cbff], ['plum', 0xdda0ddff], ['powderblue', 0xb0e0e6ff], ['purple', 0x800080ff], ['rebeccapurple', 0x663399ff], ['red', 0xff0000ff], ['rosybrown', 0xbc8f8fff], ['royalblue', 0x4169e1ff], ['saddlebrown', 0x8b4513ff], ['salmon', 0xfa8072ff], ['sandybrown', 0xf4a460ff], ['seagreen', 0x2e8b57ff], ['seashell', 0xfff5eeff], ['sienna', 0xa0522dff], ['silver', 0xc0c0c0ff], ['skyblue', 0x87ceebff], ['slateblue', 0x6a5acdff], ['slategray', 0x708090ff], ['slategrey', 0x708090ff], ['snow', 0xfffafaff], ['springgreen', 0x00ff7fff], ['steelblue', 0x4682b4ff], ['tan', 0xd2b48cff], ['teal', 0x008080ff], ['thistle', 0xd8bfd8ff], ['tomato', 0xff6347ff], ['transparent', 0x00000000], ['turquoise', 0x40e0d0ff], ['violet', 0xee82eeff], ['wheat', 0xf5deb3ff], ['white', 0xffffffff], ['whitesmoke', 0xf5f5f5ff], ['yellow', 0xffff00ff], ['yellowgreen', 0x9acd32ff], ]);