Spaces:
Running
Running
Download BeadQR/miniprogram/utils/palette.js from Ethscriptions/cut: direct link, hf CLI and curl.
- Browser
- Download file 2.66 kB
-
https://huggingface.co/spaces/Ethscriptions/cut/resolve/main/BeadQR/miniprogram/utils/palette.js
- Command line
-
hf download hf://spaces/Ethscriptions/cut/BeadQR/miniprogram/utils/palette.js
-
curl -L -o palette.js https://huggingface.co/spaces/Ethscriptions/cut/resolve/main/BeadQR/miniprogram/utils/palette.js
2.66 kB
| // MARD 色库预设 + 预处理(Typed Array 结构,供匹配引擎高速读取) | |
| const { MARD_PALETTE, MARD_SMART_ORDER } = require('./palette-data') | |
| const { hexToRgb, rgbToOklabInto, luma } = require('./color') | |
| // 颜色匹配模式:darkMax/lightMin 为二维码深/浅模块允许的亮度范围 | |
| const MATCH_MODES = [ | |
| { id: 'rich', label: '色彩优先', hint: '更像原图', darkMax: 0.4, lightMin: 0.74 }, | |
| { id: 'balanced', label: '均衡', hint: '推荐', darkMax: 0.36, lightMin: 0.78 }, | |
| { id: 'strict', label: '扫码优先', hint: '最稳', darkMax: 0.3, lightMin: 0.84 }, | |
| ] | |
| const byId = new Map(MARD_PALETTE.map((c) => [c.id, c])) | |
| const pick = (ids) => ids.map((id) => byId.get(id)).filter(Boolean) | |
| const STANDARD_221 = MARD_PALETTE.filter((c) => /^[A-HM]\d+$/.test(c.id)) | |
| const PRESETS = [ | |
| { id: '221', label: '标准 221 色', short: '221 色', detail: 'MARD 标准色,最常见', list: () => STANDARD_221 }, | |
| { id: '291', label: '完整 291 色', short: '291 色', detail: '含扩展色,颜色最全', list: () => MARD_PALETTE }, | |
| ...[144, 96, 72, 48, 24].map((n) => ({ | |
| id: String(n), | |
| label: `精选 ${n} 色`, | |
| short: `${n} 色`, | |
| detail: n <= 48 ? '入门套装,买豆更省' : '常用色,兼顾效果与成本', | |
| list: () => pick(MARD_SMART_ORDER.slice(0, n)), | |
| })), | |
| ] | |
| const cache = {} | |
| function preparePalette(presetId) { | |
| if (cache[presetId]) return cache[presetId] | |
| const preset = PRESETS.find((p) => p.id === presetId) || PRESETS[0] | |
| const list = preset.list() | |
| const n = list.length | |
| const rgb = new Uint8Array(n * 3) | |
| const lab = new Float32Array(n * 3) | |
| const lum = new Float32Array(n) | |
| list.forEach((c, i) => { | |
| const [r, g, b] = hexToRgb(c.hex) | |
| rgb[i * 3] = r; rgb[i * 3 + 1] = g; rgb[i * 3 + 2] = b | |
| rgbToOklabInto(r, g, b, lab, i * 3) | |
| lum[i] = luma(r, g, b) | |
| }) | |
| // 色与色之间的距离矩阵(291² ≈ 8.5 万项,一次性计算) | |
| const pair = new Float32Array(n * n) | |
| for (let i = 0; i < n; i += 1) { | |
| for (let j = i + 1; j < n; j += 1) { | |
| const dl = lab[i * 3] - lab[j * 3] | |
| const da = lab[i * 3 + 1] - lab[j * 3 + 1] | |
| const db = lab[i * 3 + 2] - lab[j * 3 + 2] | |
| const d = Math.sqrt(dl * dl + da * da + db * db) | |
| pair[i * n + j] = d | |
| pair[j * n + i] = d | |
| } | |
| } | |
| const prepared = { | |
| id: preset.id, | |
| label: preset.label, | |
| short: preset.short, | |
| n, | |
| ids: list.map((c) => c.id), | |
| hexes: list.map((c) => c.hex), | |
| rgb, | |
| lab, | |
| lum, | |
| pair, | |
| subsets: {}, | |
| luts: {}, | |
| } | |
| cache[presetId] = prepared | |
| return prepared | |
| } | |
| module.exports = { MATCH_MODES, PRESETS, preparePalette } | |