UNPKG

@thi.ng/color

Version:

Array-based color types, CSS parsing, conversions, transformations, declarative theme generation, gradients, presets

1,353 lines (1,352 loc) 11.4 kB
import { clamp01 } from "@thi.ng/math/interval"; import { mix, mixBilinear } from "@thi.ng/math/mix"; import { fract } from "@thi.ng/math/prec"; import { lch } from "./lch/lch.js"; const MAX_CHROMA = [ [ 4, 22, 30, 34, 38, 43, 47, 52, 56, 61, 66, 70, 75, 80, 84, 74, 65, 56, 47, 39, 32, 25, 18, 11, 5 ], [ 4, 22, 30, 34, 39, 43, 48, 52, 57, 61, 66, 71, 75, 80, 82, 72, 63, 54, 46, 38, 31, 24, 17, 10, 5 ], [ 4, 22, 31, 35, 39, 44, 49, 53, 58, 63, 67, 72, 77, 82, 83, 73, 63, 54, 46, 38, 31, 24, 17, 10, 5 ], [ 3, 20, 32, 37, 41, 46, 51, 55, 60, 65, 70, 75, 80, 85, 85, 74, 65, 55, 47, 39, 31, 24, 17, 10, 5 ], [ 2, 15, 27, 39, 44, 49, 54, 59, 64, 69, 75, 80, 85, 90, 89, 78, 67, 57, 48, 40, 32, 25, 18, 10, 5 ], [ 2, 11, 22, 32, 43, 53, 59, 64, 70, 76, 81, 87, 93, 99, 96, 84, 72, 61, 51, 42, 34, 26, 19, 11, 5 ], [ 1, 10, 19, 27, 36, 44, 52, 59, 66, 72, 77, 83, 88, 93, 98, 92, 79, 67, 56, 45, 36, 28, 20, 12, 6 ], [ 1, 9, 17, 24, 31, 38, 45, 51, 57, 61, 66, 70, 75, 79, 84, 88, 90, 75, 62, 51, 40, 30, 22, 13, 6 ], [ 1, 8, 15, 22, 28, 35, 40, 46, 50, 54, 58, 62, 66, 70, 74, 78, 82, 86, 73, 59, 46, 35, 24, 15, 7 ], [ 1, 7, 13, 20, 26, 32, 37, 42, 46, 50, 53, 57, 61, 64, 68, 72, 75, 79, 83, 72, 55, 41, 29, 18, 8 ], [ 1, 7, 12, 19, 25, 30, 35, 40, 43, 47, 50, 54, 57, 60, 64, 67, 71, 74, 78, 81, 73, 53, 36, 22, 10 ], [ 1, 7, 12, 19, 24, 29, 34, 38, 42, 45, 48, 51, 55, 58, 61, 65, 68, 71, 75, 78, 82, 79, 50, 29, 12 ], [ 1, 7, 12, 19, 24, 29, 33, 37, 41, 44, 47, 50, 54, 57, 60, 63, 67, 70, 73, 77, 80, 83, 86, 48, 19 ], [ 1, 7, 12, 19, 24, 29, 33, 37, 41, 44, 47, 50, 53, 57, 60, 63, 66, 70, 73, 76, 80, 83, 86, 90, 45 ], [ 1, 7, 12, 19, 25, 30, 34, 38, 41, 44, 48, 51, 54, 58, 61, 64, 67, 71, 74, 78, 81, 84, 88, 91, 94 ], [ 1, 7, 13, 20, 26, 31, 35, 39, 43, 46, 49, 53, 56, 60, 63, 66, 70, 73, 77, 80, 84, 87, 91, 94, 60 ], [ 1, 8, 15, 21, 27, 33, 37, 42, 45, 49, 52, 56, 59, 63, 66, 70, 74, 77, 81, 85, 88, 92, 96, 96, 44 ], [ 1, 9, 16, 23, 29, 35, 40, 45, 49, 52, 56, 60, 64, 68, 72, 76, 80, 84, 87, 91, 95, 99, 103, 77, 35 ], [ 1, 10, 18, 26, 33, 39, 44, 48, 52, 56, 60, 65, 69, 73, 77, 82, 86, 90, 94, 99, 103, 107, 110, 65, 30 ], [ 2, 10, 21, 28, 30, 34, 37, 40, 44, 47, 51, 55, 58, 62, 65, 69, 73, 76, 80, 83, 87, 91, 94, 58, 26 ], [ 1, 10, 18, 24, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, 56, 60, 63, 66, 69, 72, 75, 78, 81, 52, 24 ], [ 1, 8, 15, 21, 23, 26, 28, 31, 33, 36, 39, 42, 44, 47, 50, 53, 55, 58, 61, 64, 66, 69, 72, 48, 22 ], [ 1, 7, 13, 19, 21, 23, 25, 28, 30, 33, 35, 37, 40, 42, 45, 47, 50, 52, 55, 57, 60, 62, 65, 46, 21 ], [ 1, 7, 12, 17, 19, 21, 23, 25, 28, 30, 32, 34, 37, 39, 41, 44, 46, 48, 50, 53, 55, 57, 60, 44, 20 ], [ 1, 6, 11, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 39, 41, 43, 45, 47, 49, 51, 54, 56, 43, 19 ], [ 1, 6, 11, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 43, 19 ], [ 1, 6, 10, 15, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 35, 37, 39, 41, 43, 45, 47, 49, 51, 43, 20 ], [ 1, 6, 10, 13, 16, 18, 20, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 46, 48, 49, 33, 16 ], [ 1, 6, 10, 13, 16, 18, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 42, 44, 46, 48, 37, 25, 11 ], [ 1, 7, 11, 13, 16, 18, 20, 22, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 40, 30, 20, 10 ], [ 1, 7, 11, 15, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 43, 34, 26, 17, 8 ], [ 1, 7, 12, 15, 17, 19, 21, 23, 25, 27, 29, 31, 34, 36, 38, 40, 42, 44, 46, 46, 38, 31, 23, 15, 7 ], [ 1, 8, 13, 16, 18, 20, 22, 25, 27, 29, 31, 33, 36, 38, 40, 42, 45, 47, 49, 42, 35, 28, 21, 13, 7 ], [ 1, 10, 15, 18, 20, 22, 24, 27, 29, 31, 34, 36, 39, 41, 43, 46, 48, 51, 46, 40, 33, 26, 19, 12, 6 ], [ 2, 10, 17, 19, 22, 24, 27, 29, 32, 35, 37, 40, 43, 45, 48, 51, 53, 51, 44, 38, 31, 25, 18, 11, 6 ], [ 2, 13, 19, 22, 25, 28, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 56, 49, 43, 37, 30, 24, 18, 11, 6 ], [ 3, 17, 22, 26, 29, 32, 36, 39, 42, 46, 49, 53, 56, 60, 63, 62, 55, 49, 43, 36, 30, 24, 18, 11, 6 ], [ 6, 23, 27, 31, 35, 39, 43, 47, 51, 56, 60, 64, 68, 73, 69, 62, 56, 49, 43, 36, 30, 24, 18, 11, 6 ], [ 18, 30, 34, 39, 44, 49, 54, 60, 65, 70, 76, 81, 84, 77, 70, 64, 57, 50, 44, 37, 31, 25, 18, 11, 6 ], [ 12, 41, 45, 52, 59, 66, 73, 80, 87, 94, 102, 95, 88, 81, 74, 66, 60, 53, 46, 39, 32, 26, 19, 11, 6 ], [ 9, 58, 65, 75, 85, 96, 106, 117, 124, 116, 109, 101, 93, 86, 78, 71, 63, 56, 49, 42, 34, 27, 20, 12, 6 ], [ 7, 42, 58, 66, 74, 82, 91, 99, 108, 117, 119, 110, 102, 94, 85, 77, 69, 61, 53, 45, 37, 30, 22, 13, 7 ], [ 6, 34, 47, 53, 60, 67, 74, 81, 88, 95, 102, 109, 114, 105, 95, 86, 77, 68, 59, 51, 42, 33, 25, 16, 8 ], [ 5, 29, 40, 46, 52, 57, 63, 70, 76, 82, 88, 94, 100, 107, 110, 100, 89, 79, 69, 58, 48, 38, 29, 19, 9 ], [ 4, 26, 36, 41, 46, 52, 57, 62, 68, 73, 79, 85, 90, 96, 101, 104, 91, 79, 67, 56, 45, 35, 26, 17, 8 ], [ 4, 24, 34, 38, 43, 48, 53, 58, 63, 68, 73, 78, 83, 88, 94, 91, 79, 69, 59, 49, 40, 31, 23, 15, 7 ], [ 4, 23, 32, 36, 40, 45, 50, 55, 59, 64, 69, 74, 79, 84, 89, 82, 72, 62, 53, 44, 36, 28, 20, 12, 6 ], [ 4, 22, 31, 35, 39, 44, 48, 53, 57, 62, 67, 71, 76, 81, 86, 77, 67, 58, 50, 41, 33, 26, 19, 11, 6 ] ]; const RES_H = MAX_CHROMA.length; const RES_L = MAX_CHROMA[0].length; const maxChroma = (l, h) => { h = fract(h); l = clamp01(l); if (l < 1) { const h1 = h * RES_H | 0; const l1 = l * RES_L | 0; const lutH1 = MAX_CHROMA[h1]; const lutH2 = MAX_CHROMA[(h1 + 1) % RES_H]; return mixBilinear( lutH1[l1], lutH2[l1], l1 < RES_L - 1 ? lutH1[l1 + 1] : 0, l1 < RES_L - 1 ? lutH2[l1 + 1] : 0, h * RES_H - h1, l * RES_L - l1 ) * 0.01; } return 0; }; const lchMaxChroma = (l, h, a = 1) => lch(l, maxChroma(l, h), h, a); const maxLumaChroma = (h) => { const h1 = fract(h) * RES_H | 0; const t = h * RES_H - h1; const [l1, c1] = __maxLC(MAX_CHROMA[h1]); const [l2, c2] = __maxLC(MAX_CHROMA[(h1 + 1) % RES_H]); return { l: mix(l1, l2, t) / RES_L, c: mix(c1, c2, t) * 0.01 }; }; const lchMaxLumaChroma = (h, a = 1) => { const max = maxLumaChroma(h); return lch(max.l, max.c, h, a); }; const __maxLC = (chroma) => { let maxL = 0; let maxC = 0; for (let i = RES_L; i-- > 0; ) { if (chroma[i] >= maxC) { maxC = chroma[i]; maxL = i; } else break; } return [maxL, maxC]; }; export { lchMaxChroma, lchMaxLumaChroma, maxChroma, maxLumaChroma };