diff --git a/src/core/cache.ts b/src/core/cache.ts index 0379711..81d81f1 100644 --- a/src/core/cache.ts +++ b/src/core/cache.ts @@ -24,6 +24,7 @@ export const overlayCache = new LRUCache(500); export const imageDecodeCache = new LRUCache(64); export const paletteDetectionCache = new LRUCache(200); export const baseMinifyCache = new LRUCache(100); +export const colorCaches = new LRUCache>(500); export const tooLargeOverlays = new Set(); export function clearOverlayCache() { @@ -31,5 +32,6 @@ export function clearOverlayCache() { imageDecodeCache.clear(); paletteDetectionCache.clear(); baseMinifyCache.clear(); + colorCaches.clear(); tooLargeOverlays.clear(); } \ No newline at end of file diff --git a/src/core/overlay.ts b/src/core/overlay.ts index 7fd740a..c63a0c0 100644 --- a/src/core/overlay.ts +++ b/src/core/overlay.ts @@ -42,11 +42,10 @@ function findClosestColorIndex(r: number, g: number, b: number) { let index = 0; for (let i = 0; i < ALL_COLORS.length; i++) { const color = ALL_COLORS[i]; - const distance = Math.sqrt( + const distance = Math.pow(r - color[0], 2) + Math.pow(g - color[1], 2) + - Math.pow(b - color[2], 2) - ); + Math.pow(b - color[2], 2); if (distance < minDistance) { minDistance = distance; index = i; diff --git a/src/ui/ccModal.ts b/src/ui/ccModal.ts index fb3f1ec..1b23d63 100644 --- a/src/ui/ccModal.ts +++ b/src/ui/ccModal.ts @@ -1,7 +1,8 @@ /// import { WPLACE_FREE, WPLACE_PAID, WPLACE_NAMES, DEFAULT_FREE_KEYS } from '../core/palette'; import { createCanvas } from '../core/canvas'; -import { config, saveConfig } from '../core/store'; +import { colorCaches } from '../core/cache'; +import { config, saveConfig, type OverlayItem } from '../core/store'; import { MAX_OVERLAY_DIM } from '../core/constants'; import { ensureHook } from '../core/hook'; import { clearOverlayCache, paletteDetectionCache } from '../core/cache'; @@ -38,7 +39,7 @@ type CCState = { selectedPaid: Set; realtime: boolean; - overlay: any | null; + overlay: OverlayItem | null; lastColorCounts: Record; isStale: boolean; }; @@ -191,7 +192,7 @@ export function buildCCModal() { renderPaletteGrid(); } -export function openCCModal(overlay: any) { +export function openCCModal(overlay: OverlayItem) { if (!cc) return; cc.overlay = overlay; @@ -233,7 +234,7 @@ function closeCCModal() { } function weightedNearest(r: number, g: number, b: number, palette: number[][]) { - let best: number[] | null = null, bestDist = Infinity; + let best: [number, number, number] | null = null, bestDist = Infinity; for (let i = 0; i < palette.length; i++) { const [pr, pg, pb] = palette[i]; const rmean = (pr + r) / 2; @@ -243,7 +244,7 @@ function weightedNearest(r: number, g: number, b: number, palette: number[][]) { const x = (512 + rmean) * rdiff * rdiff >> 8; const y = 4 * gdiff * gdiff; const z = (767 - rmean) * bdiff * bdiff >> 8; - const dist = Math.sqrt(x + y + z); + const dist = x + y + z; if (dist < bestDist) { bestDist = dist; best = [pr, pg, pb]; } } return best || [0,0,0]; @@ -266,11 +267,23 @@ function processImage() { const palette = getActivePalette(); const counts: Record = {}; + const id = cc.overlay.id; + let colorCache = colorCaches.get(id); + if (!colorCache) { + colorCache = new Map(); + colorCaches.set(id, colorCache); + } for (let i = 0; i < src.length; i += 4) { const r = src[i], g = src[i+1], b = src[i+2], a = src[i+3]; if (a === 0) { out[i]=0; out[i+1]=0; out[i+2]=0; out[i+3]=0; continue; } - const [nr, ng, nb] = palette.length ? weightedNearest(r,g,b,palette) : [r,g,b]; + const color = (r<<24)|(g<<16)|(b<<8)|a; + let cached = colorCache.get(color); + if (!cached) { + cached = palette.length ? weightedNearest(r,g,b,palette) : [r,g,b]; + colorCache.set(color, cached); + } + const [nr, ng, nb] = cached; out[i]=nr; out[i+1]=ng; out[i+2]=nb; out[i+3]=255; const key = `${nr},${ng},${nb}`; counts[key] = (counts[key] || 0) + 1;