@xivdyetools/core 1.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +37 -0
- package/README.md +400 -0
- package/dist/constants/index.d.ts +56 -0
- package/dist/constants/index.d.ts.map +1 -0
- package/dist/constants/index.js +103 -0
- package/dist/constants/index.js.map +1 -0
- package/dist/data/colors_xiv.json +3130 -0
- package/dist/data/locales/de.json +231 -0
- package/dist/data/locales/en.json +231 -0
- package/dist/data/locales/fr.json +231 -0
- package/dist/data/locales/ja.json +231 -0
- package/dist/data/locales/ko.json +233 -0
- package/dist/data/locales/zh.json +233 -0
- package/dist/data/presets.json +390 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/services/APIService.d.ts +246 -0
- package/dist/services/APIService.d.ts.map +1 -0
- package/dist/services/APIService.js +499 -0
- package/dist/services/APIService.js.map +1 -0
- package/dist/services/ColorService.d.ts +146 -0
- package/dist/services/ColorService.d.ts.map +1 -0
- package/dist/services/ColorService.js +209 -0
- package/dist/services/ColorService.js.map +1 -0
- package/dist/services/DyeService.d.ts +230 -0
- package/dist/services/DyeService.d.ts.map +1 -0
- package/dist/services/DyeService.js +326 -0
- package/dist/services/DyeService.js.map +1 -0
- package/dist/services/LocalizationService.d.ts +338 -0
- package/dist/services/LocalizationService.d.ts.map +1 -0
- package/dist/services/LocalizationService.js +449 -0
- package/dist/services/LocalizationService.js.map +1 -0
- package/dist/services/PaletteService.d.ts +137 -0
- package/dist/services/PaletteService.d.ts.map +1 -0
- package/dist/services/PaletteService.js +349 -0
- package/dist/services/PaletteService.js.map +1 -0
- package/dist/services/PresetService.d.ts +196 -0
- package/dist/services/PresetService.d.ts.map +1 -0
- package/dist/services/PresetService.js +261 -0
- package/dist/services/PresetService.js.map +1 -0
- package/dist/services/color/ColorAccessibility.d.ts +39 -0
- package/dist/services/color/ColorAccessibility.d.ts.map +1 -0
- package/dist/services/color/ColorAccessibility.js +71 -0
- package/dist/services/color/ColorAccessibility.js.map +1 -0
- package/dist/services/color/ColorConverter.d.ts +146 -0
- package/dist/services/color/ColorConverter.d.ts.map +1 -0
- package/dist/services/color/ColorConverter.js +393 -0
- package/dist/services/color/ColorConverter.js.map +1 -0
- package/dist/services/color/ColorManipulator.d.ts +36 -0
- package/dist/services/color/ColorManipulator.d.ts.map +1 -0
- package/dist/services/color/ColorManipulator.js +56 -0
- package/dist/services/color/ColorManipulator.js.map +1 -0
- package/dist/services/color/ColorblindnessSimulator.d.ts +35 -0
- package/dist/services/color/ColorblindnessSimulator.d.ts.map +1 -0
- package/dist/services/color/ColorblindnessSimulator.js +110 -0
- package/dist/services/color/ColorblindnessSimulator.js.map +1 -0
- package/dist/services/dye/DyeDatabase.d.ts +131 -0
- package/dist/services/dye/DyeDatabase.d.ts.map +1 -0
- package/dist/services/dye/DyeDatabase.js +367 -0
- package/dist/services/dye/DyeDatabase.js.map +1 -0
- package/dist/services/dye/DyeSearch.d.ts +55 -0
- package/dist/services/dye/DyeSearch.d.ts.map +1 -0
- package/dist/services/dye/DyeSearch.js +196 -0
- package/dist/services/dye/DyeSearch.js.map +1 -0
- package/dist/services/dye/HarmonyGenerator.d.ts +110 -0
- package/dist/services/dye/HarmonyGenerator.d.ts.map +1 -0
- package/dist/services/dye/HarmonyGenerator.js +221 -0
- package/dist/services/dye/HarmonyGenerator.js.map +1 -0
- package/dist/services/localization/LocaleLoader.d.ts +38 -0
- package/dist/services/localization/LocaleLoader.d.ts.map +1 -0
- package/dist/services/localization/LocaleLoader.js +83 -0
- package/dist/services/localization/LocaleLoader.js.map +1 -0
- package/dist/services/localization/LocaleRegistry.d.ts +73 -0
- package/dist/services/localization/LocaleRegistry.d.ts.map +1 -0
- package/dist/services/localization/LocaleRegistry.js +84 -0
- package/dist/services/localization/LocaleRegistry.js.map +1 -0
- package/dist/services/localization/TranslationProvider.d.ts +157 -0
- package/dist/services/localization/TranslationProvider.d.ts.map +1 -0
- package/dist/services/localization/TranslationProvider.js +289 -0
- package/dist/services/localization/TranslationProvider.js.map +1 -0
- package/dist/types/index.d.ts +409 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +87 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/logger.d.ts +84 -0
- package/dist/types/logger.d.ts.map +1 -0
- package/dist/types/logger.js +54 -0
- package/dist/types/logger.js.map +1 -0
- package/dist/utils/index.d.ts +441 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +577 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/kd-tree.d.ts +76 -0
- package/dist/utils/kd-tree.d.ts.map +1 -0
- package/dist/utils/kd-tree.js +195 -0
- package/dist/utils/kd-tree.js.map +1 -0
- package/dist/version.d.ts +11 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +11 -0
- package/dist/version.js.map +1 -0
- package/package.json +84 -0
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Color Converter
|
|
3
|
+
* Per R-4: Focused class for color format conversions
|
|
4
|
+
* Handles conversions between hex, RGB, and HSV color formats
|
|
5
|
+
*/
|
|
6
|
+
import { createHexColor } from '../../types/index.js';
|
|
7
|
+
import { ErrorCode, AppError } from '../../types/index.js';
|
|
8
|
+
import { RGB_MIN, RGB_MAX, HUE_MAX } from '../../constants/index.js';
|
|
9
|
+
import { clamp, round, isValidHexColor, isValidRGB, isValidHSV } from '../../utils/index.js';
|
|
10
|
+
/**
|
|
11
|
+
* Simple LRU cache implementation
|
|
12
|
+
* Per P-1: Caching for color conversions (60-80% speedup)
|
|
13
|
+
*/
|
|
14
|
+
class LRUCache {
|
|
15
|
+
constructor(maxSize = 1000) {
|
|
16
|
+
this.cache = new Map();
|
|
17
|
+
this.maxSize = maxSize;
|
|
18
|
+
}
|
|
19
|
+
get(key) {
|
|
20
|
+
// CORE-PERF-001: Use has() check first to properly handle undefined values
|
|
21
|
+
// and ensure atomic move-to-end operation for LRU ordering
|
|
22
|
+
if (!this.cache.has(key))
|
|
23
|
+
return undefined;
|
|
24
|
+
const value = this.cache.get(key);
|
|
25
|
+
// Move to end (most recently used) - delete + set is atomic in synchronous JS
|
|
26
|
+
this.cache.delete(key);
|
|
27
|
+
this.cache.set(key, value);
|
|
28
|
+
return value;
|
|
29
|
+
}
|
|
30
|
+
set(key, value) {
|
|
31
|
+
if (this.cache.has(key)) {
|
|
32
|
+
// Update existing
|
|
33
|
+
this.cache.delete(key);
|
|
34
|
+
}
|
|
35
|
+
else if (this.cache.size >= this.maxSize) {
|
|
36
|
+
// Remove least recently used (first item)
|
|
37
|
+
const firstKey = this.cache.keys().next().value;
|
|
38
|
+
if (firstKey !== undefined) {
|
|
39
|
+
this.cache.delete(firstKey);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
this.cache.set(key, value);
|
|
43
|
+
}
|
|
44
|
+
clear() {
|
|
45
|
+
this.cache.clear();
|
|
46
|
+
}
|
|
47
|
+
get size() {
|
|
48
|
+
return this.cache.size;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Color format converter with LRU caching
|
|
53
|
+
* Per R-4: Single Responsibility - format conversions only
|
|
54
|
+
*
|
|
55
|
+
* Refactored for testability: Supports dependency injection of cache configuration
|
|
56
|
+
*/
|
|
57
|
+
export class ColorConverter {
|
|
58
|
+
/**
|
|
59
|
+
* Constructor with optional cache configuration
|
|
60
|
+
* @param config Configuration for cache sizes (default: 1000 entries per cache)
|
|
61
|
+
*/
|
|
62
|
+
constructor(config = {}) {
|
|
63
|
+
const cacheSize = config.cacheSize ?? 1000;
|
|
64
|
+
this.hexToRgbCache = new LRUCache(cacheSize);
|
|
65
|
+
this.rgbToHexCache = new LRUCache(cacheSize);
|
|
66
|
+
this.rgbToHsvCache = new LRUCache(cacheSize);
|
|
67
|
+
this.hsvToRgbCache = new LRUCache(cacheSize);
|
|
68
|
+
this.hexToHsvCache = new LRUCache(cacheSize);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Get the default singleton instance
|
|
72
|
+
* Per Issue #6: Returns eagerly-initialized instance to avoid race conditions
|
|
73
|
+
*/
|
|
74
|
+
static getDefault() {
|
|
75
|
+
return this.defaultInstance;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Clear all caches (useful for testing or memory management)
|
|
79
|
+
*/
|
|
80
|
+
clearCaches() {
|
|
81
|
+
this.hexToRgbCache.clear();
|
|
82
|
+
this.rgbToHexCache.clear();
|
|
83
|
+
this.rgbToHsvCache.clear();
|
|
84
|
+
this.hsvToRgbCache.clear();
|
|
85
|
+
this.hexToHsvCache.clear();
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Static method: Clear all caches of the default instance
|
|
89
|
+
*/
|
|
90
|
+
static clearCaches() {
|
|
91
|
+
this.getDefault().clearCaches();
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Get cache statistics (for monitoring)
|
|
95
|
+
*/
|
|
96
|
+
getCacheStats() {
|
|
97
|
+
return {
|
|
98
|
+
hexToRgb: this.hexToRgbCache.size,
|
|
99
|
+
rgbToHex: this.rgbToHexCache.size,
|
|
100
|
+
rgbToHsv: this.rgbToHsvCache.size,
|
|
101
|
+
hsvToRgb: this.hsvToRgbCache.size,
|
|
102
|
+
hexToHsv: this.hexToHsvCache.size,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Static method: Get cache statistics from default instance
|
|
107
|
+
*/
|
|
108
|
+
static getCacheStats() {
|
|
109
|
+
return this.getDefault().getCacheStats();
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Convert hexadecimal color to RGB
|
|
113
|
+
* Per P-1: Cached for performance
|
|
114
|
+
* @example hexToRgb("#FF0000") -> { r: 255, g: 0, b: 0 }
|
|
115
|
+
*/
|
|
116
|
+
hexToRgb(hex) {
|
|
117
|
+
if (!isValidHexColor(hex)) {
|
|
118
|
+
throw new AppError(ErrorCode.INVALID_HEX_COLOR, `Invalid hex color: ${hex}. Use format #RRGGBB or #RGB`, 'error');
|
|
119
|
+
}
|
|
120
|
+
// Normalize hex for cache key
|
|
121
|
+
let hexForCache = hex.toUpperCase().replace('#', '');
|
|
122
|
+
if (hexForCache.length === 3) {
|
|
123
|
+
hexForCache = hexForCache
|
|
124
|
+
.split('')
|
|
125
|
+
.map((c) => c + c)
|
|
126
|
+
.join('');
|
|
127
|
+
}
|
|
128
|
+
const cacheKey = hexForCache;
|
|
129
|
+
// Check cache
|
|
130
|
+
const cached = this.hexToRgbCache.get(cacheKey);
|
|
131
|
+
if (cached) {
|
|
132
|
+
return cached;
|
|
133
|
+
}
|
|
134
|
+
// Remove # and expand shorthand (#RGB -> #RRGGBB)
|
|
135
|
+
let normalizedHex = hex.replace('#', '');
|
|
136
|
+
if (normalizedHex.length === 3) {
|
|
137
|
+
normalizedHex = normalizedHex
|
|
138
|
+
.split('')
|
|
139
|
+
.map((char) => char + char)
|
|
140
|
+
.join('');
|
|
141
|
+
}
|
|
142
|
+
const r = parseInt(normalizedHex.substring(0, 2), 16);
|
|
143
|
+
const g = parseInt(normalizedHex.substring(2, 4), 16);
|
|
144
|
+
const b = parseInt(normalizedHex.substring(4, 6), 16);
|
|
145
|
+
const result = { r, g, b };
|
|
146
|
+
// Cache result
|
|
147
|
+
this.hexToRgbCache.set(cacheKey, result);
|
|
148
|
+
return result;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Static method: Convert hex to RGB using default instance
|
|
152
|
+
*/
|
|
153
|
+
static hexToRgb(hex) {
|
|
154
|
+
return this.getDefault().hexToRgb(hex);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Convert RGB to hexadecimal color
|
|
158
|
+
* Per P-1: Cached for performance
|
|
159
|
+
* @example rgbToHex(255, 0, 0) -> "#FF0000"
|
|
160
|
+
*/
|
|
161
|
+
rgbToHex(r, g, b) {
|
|
162
|
+
if (!isValidRGB(r, g, b)) {
|
|
163
|
+
throw new AppError(ErrorCode.INVALID_RGB_VALUE, `Invalid RGB values: r=${r}, g=${g}, b=${b}. Values must be 0-255`, 'error');
|
|
164
|
+
}
|
|
165
|
+
// Create cache key
|
|
166
|
+
const cacheKey = `${r},${g},${b}`;
|
|
167
|
+
// Check cache
|
|
168
|
+
const cached = this.rgbToHexCache.get(cacheKey);
|
|
169
|
+
if (cached) {
|
|
170
|
+
return cached;
|
|
171
|
+
}
|
|
172
|
+
const toHex = (value) => {
|
|
173
|
+
const hex = Math.round(value).toString(16);
|
|
174
|
+
return hex.length === 1 ? '0' + hex : hex;
|
|
175
|
+
};
|
|
176
|
+
const result = createHexColor(`#${toHex(r)}${toHex(g)}${toHex(b)}`.toUpperCase());
|
|
177
|
+
// Cache result
|
|
178
|
+
this.rgbToHexCache.set(cacheKey, result);
|
|
179
|
+
return result;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Static method: Convert RGB to hex using default instance
|
|
183
|
+
*/
|
|
184
|
+
static rgbToHex(r, g, b) {
|
|
185
|
+
return this.getDefault().rgbToHex(r, g, b);
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Convert RGB to HSV
|
|
189
|
+
* Per P-1: Cached for performance, optimized single-pass min/max
|
|
190
|
+
* @example rgbToHsv(255, 0, 0) -> { h: 0, s: 100, v: 100 }
|
|
191
|
+
*/
|
|
192
|
+
rgbToHsv(r, g, b) {
|
|
193
|
+
if (!isValidRGB(r, g, b)) {
|
|
194
|
+
throw new AppError(ErrorCode.INVALID_RGB_VALUE, `Invalid RGB values: r=${r}, g=${g}, b=${b}`, 'error');
|
|
195
|
+
}
|
|
196
|
+
// Create cache key
|
|
197
|
+
const cacheKey = `${r},${g},${b}`;
|
|
198
|
+
// Check cache
|
|
199
|
+
const cached = this.rgbToHsvCache.get(cacheKey);
|
|
200
|
+
if (cached) {
|
|
201
|
+
return cached;
|
|
202
|
+
}
|
|
203
|
+
// Per P-1: Optimized single-pass min/max calculation
|
|
204
|
+
// Normalize RGB to 0-1 range
|
|
205
|
+
const rNorm = r / 255;
|
|
206
|
+
const gNorm = g / 255;
|
|
207
|
+
const bNorm = b / 255;
|
|
208
|
+
// Single-pass min/max (optimized)
|
|
209
|
+
const max = Math.max(rNorm, gNorm, bNorm);
|
|
210
|
+
const min = Math.min(rNorm, gNorm, bNorm);
|
|
211
|
+
const delta = max - min;
|
|
212
|
+
// Calculate Value (brightness)
|
|
213
|
+
const v = max * 100;
|
|
214
|
+
// Calculate Saturation
|
|
215
|
+
const s = max === 0 ? 0 : (delta / max) * 100;
|
|
216
|
+
// Calculate Hue
|
|
217
|
+
let h = 0;
|
|
218
|
+
if (delta !== 0) {
|
|
219
|
+
if (max === rNorm) {
|
|
220
|
+
h = ((gNorm - bNorm) / delta + (gNorm < bNorm ? 6 : 0)) * 60;
|
|
221
|
+
}
|
|
222
|
+
else if (max === gNorm) {
|
|
223
|
+
h = ((bNorm - rNorm) / delta + 2) * 60;
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
h = ((rNorm - gNorm) / delta + 4) * 60;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
const result = { h: round(h, 2), s: round(s, 2), v: round(v, 2) };
|
|
230
|
+
// Cache result
|
|
231
|
+
this.rgbToHsvCache.set(cacheKey, result);
|
|
232
|
+
return result;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Static method: Convert RGB to HSV using default instance
|
|
236
|
+
*/
|
|
237
|
+
static rgbToHsv(r, g, b) {
|
|
238
|
+
return this.getDefault().rgbToHsv(r, g, b);
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Normalize hue to [0, 360) range.
|
|
242
|
+
* CORE-BUG-001: Ensures consistent cache keys for equivalent hue values
|
|
243
|
+
* (e.g., h=359.9999 and h=0.0001 both produce similar cache keys after rounding)
|
|
244
|
+
* Also handles negative values and values >= 360.
|
|
245
|
+
*/
|
|
246
|
+
normalizeHue(h) {
|
|
247
|
+
return ((h % HUE_MAX) + HUE_MAX) % HUE_MAX;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Convert HSV to RGB
|
|
251
|
+
* Per P-1: Cached for performance
|
|
252
|
+
* @example hsvToRgb(0, 100, 100) -> { r: 255, g: 0, b: 0 }
|
|
253
|
+
*/
|
|
254
|
+
hsvToRgb(h, s, v) {
|
|
255
|
+
if (!isValidHSV(h, s, v)) {
|
|
256
|
+
throw new AppError(ErrorCode.INVALID_RGB_VALUE, `Invalid HSV values: h=${h}, s=${s}, v=${v}`, 'error');
|
|
257
|
+
}
|
|
258
|
+
// CORE-BUG-001: Normalize hue BEFORE creating cache key
|
|
259
|
+
// This ensures h=359.9999 and h=0.0001 produce consistent cache keys
|
|
260
|
+
// after rounding, preventing cache thrashing for equivalent colors
|
|
261
|
+
const hNormalized = this.normalizeHue(h);
|
|
262
|
+
// Create cache key using consistent rounding (2 decimal places)
|
|
263
|
+
// Per Issue #17: Use same round() utility as rgbToHsv for consistency
|
|
264
|
+
const cacheKey = `${round(hNormalized, 2)},${round(s, 2)},${round(v, 2)}`;
|
|
265
|
+
// Check cache
|
|
266
|
+
const cached = this.hsvToRgbCache.get(cacheKey);
|
|
267
|
+
if (cached) {
|
|
268
|
+
return cached;
|
|
269
|
+
}
|
|
270
|
+
// Normalize HSV (use already normalized hue)
|
|
271
|
+
const hNorm = hNormalized / 60;
|
|
272
|
+
const sNorm = s / 100;
|
|
273
|
+
const vNorm = v / 100;
|
|
274
|
+
const c = vNorm * sNorm;
|
|
275
|
+
const x = c * (1 - Math.abs((hNorm % 2) - 1));
|
|
276
|
+
const m = vNorm - c;
|
|
277
|
+
let rNorm = 0, gNorm = 0, bNorm = 0;
|
|
278
|
+
if (hNorm >= 0 && hNorm < 1) {
|
|
279
|
+
[rNorm, gNorm, bNorm] = [c, x, 0];
|
|
280
|
+
}
|
|
281
|
+
else if (hNorm >= 1 && hNorm < 2) {
|
|
282
|
+
[rNorm, gNorm, bNorm] = [x, c, 0];
|
|
283
|
+
}
|
|
284
|
+
else if (hNorm >= 2 && hNorm < 3) {
|
|
285
|
+
[rNorm, gNorm, bNorm] = [0, c, x];
|
|
286
|
+
}
|
|
287
|
+
else if (hNorm >= 3 && hNorm < 4) {
|
|
288
|
+
[rNorm, gNorm, bNorm] = [0, x, c];
|
|
289
|
+
}
|
|
290
|
+
else if (hNorm >= 4 && hNorm < 5) {
|
|
291
|
+
[rNorm, gNorm, bNorm] = [x, 0, c];
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
[rNorm, gNorm, bNorm] = [c, 0, x];
|
|
295
|
+
}
|
|
296
|
+
const r = Math.round((rNorm + m) * 255);
|
|
297
|
+
const g = Math.round((gNorm + m) * 255);
|
|
298
|
+
const b = Math.round((bNorm + m) * 255);
|
|
299
|
+
const result = {
|
|
300
|
+
r: clamp(r, RGB_MIN, RGB_MAX),
|
|
301
|
+
g: clamp(g, RGB_MIN, RGB_MAX),
|
|
302
|
+
b: clamp(b, RGB_MIN, RGB_MAX),
|
|
303
|
+
};
|
|
304
|
+
// Cache result
|
|
305
|
+
this.hsvToRgbCache.set(cacheKey, result);
|
|
306
|
+
return result;
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Static method: Convert HSV to RGB using default instance
|
|
310
|
+
*/
|
|
311
|
+
static hsvToRgb(h, s, v) {
|
|
312
|
+
return this.getDefault().hsvToRgb(h, s, v);
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Convert hex to HSV
|
|
316
|
+
* Per P-1: Cached for performance
|
|
317
|
+
*/
|
|
318
|
+
hexToHsv(hex) {
|
|
319
|
+
// Normalize hex for cache key
|
|
320
|
+
let hexForCache = hex.toUpperCase().replace('#', '');
|
|
321
|
+
if (hexForCache.length === 3) {
|
|
322
|
+
hexForCache = hexForCache
|
|
323
|
+
.split('')
|
|
324
|
+
.map((c) => c + c)
|
|
325
|
+
.join('');
|
|
326
|
+
}
|
|
327
|
+
const cacheKey = hexForCache;
|
|
328
|
+
// Check cache
|
|
329
|
+
const cached = this.hexToHsvCache.get(cacheKey);
|
|
330
|
+
if (cached) {
|
|
331
|
+
return cached;
|
|
332
|
+
}
|
|
333
|
+
const rgb = this.hexToRgb(hex);
|
|
334
|
+
const result = this.rgbToHsv(rgb.r, rgb.g, rgb.b);
|
|
335
|
+
// Cache result
|
|
336
|
+
this.hexToHsvCache.set(cacheKey, result);
|
|
337
|
+
return result;
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Static method: Convert hex to HSV using default instance
|
|
341
|
+
*/
|
|
342
|
+
static hexToHsv(hex) {
|
|
343
|
+
return this.getDefault().hexToHsv(hex);
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Convert HSV to hex
|
|
347
|
+
*/
|
|
348
|
+
hsvToHex(h, s, v) {
|
|
349
|
+
const rgb = this.hsvToRgb(h, s, v);
|
|
350
|
+
return this.rgbToHex(rgb.r, rgb.g, rgb.b);
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Static method: Convert HSV to hex using default instance
|
|
354
|
+
*/
|
|
355
|
+
static hsvToHex(h, s, v) {
|
|
356
|
+
return this.getDefault().hsvToHex(h, s, v);
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Normalize a hex color to #RRGGBB format
|
|
360
|
+
*/
|
|
361
|
+
normalizeHex(hex) {
|
|
362
|
+
const rgb = this.hexToRgb(hex);
|
|
363
|
+
return this.rgbToHex(rgb.r, rgb.g, rgb.b);
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Static method: Normalize hex using default instance
|
|
367
|
+
*/
|
|
368
|
+
static normalizeHex(hex) {
|
|
369
|
+
return this.getDefault().normalizeHex(hex);
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Calculate Euclidean distance between two RGB colors
|
|
373
|
+
* Returns 0 for identical colors, ~441.67 for white vs black
|
|
374
|
+
*/
|
|
375
|
+
getColorDistance(hex1, hex2) {
|
|
376
|
+
const rgb1 = this.hexToRgb(hex1);
|
|
377
|
+
const rgb2 = this.hexToRgb(hex2);
|
|
378
|
+
const dr = rgb1.r - rgb2.r;
|
|
379
|
+
const dg = rgb1.g - rgb2.g;
|
|
380
|
+
const db = rgb1.b - rgb2.b;
|
|
381
|
+
return Math.sqrt(dr * dr + dg * dg + db * db);
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Static method: Calculate color distance using default instance
|
|
385
|
+
*/
|
|
386
|
+
static getColorDistance(hex1, hex2) {
|
|
387
|
+
return this.getDefault().getColorDistance(hex1, hex2);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
// Default singleton instance for static API compatibility
|
|
391
|
+
// Per Issue #6: Eager initialization to avoid race conditions in concurrent scenarios
|
|
392
|
+
ColorConverter.defaultInstance = new ColorConverter();
|
|
393
|
+
//# sourceMappingURL=ColorConverter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ColorConverter.js","sourceRoot":"","sources":["../../../src/services/color/ColorConverter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAE7F;;;GAGG;AACH,MAAM,QAAQ;IAIZ,YAAY,UAAkB,IAAI;QAChC,IAAI,CAAC,KAAK,GAAG,IAAI,GAAG,EAAE,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,GAAG,CAAC,GAAM;QACR,2EAA2E;QAC3E,2DAA2D;QAC3D,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,SAAS,CAAC;QAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;QACnC,8EAA8E;QAC9E,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACvB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC3B,OAAO,KAAK,CAAC;IACf,CAAC;IAED,GAAG,CAAC,GAAM,EAAE,KAAQ;QAClB,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,kBAAkB;YAClB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACzB,CAAC;aAAM,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAC3C,0CAA0C;YAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;YAChD,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAC3B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC7B,CAAC;IAED,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;CACF;AASD;;;;;GAKG;AACH,MAAM,OAAO,cAAc;IAYzB;;;OAGG;IACH,YAAY,SAA+B,EAAE;QAC3C,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,IAAI,CAAC;QAC3C,IAAI,CAAC,aAAa,GAAG,IAAI,QAAQ,CAAc,SAAS,CAAC,CAAC;QAC1D,IAAI,CAAC,aAAa,GAAG,IAAI,QAAQ,CAAmB,SAAS,CAAC,CAAC;QAC/D,IAAI,CAAC,aAAa,GAAG,IAAI,QAAQ,CAAc,SAAS,CAAC,CAAC;QAC1D,IAAI,CAAC,aAAa,GAAG,IAAI,QAAQ,CAAc,SAAS,CAAC,CAAC;QAC1D,IAAI,CAAC,aAAa,GAAG,IAAI,QAAQ,CAAc,SAAS,CAAC,CAAC;IAC5D,CAAC;IAED;;;OAGG;IACK,MAAM,CAAC,UAAU;QACvB,OAAO,IAAI,CAAC,eAAe,CAAC;IAC9B,CAAC;IAED;;OAEG;IACH,WAAW;QACT,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;IAC7B,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,WAAW;QAChB,IAAI,CAAC,UAAU,EAAE,CAAC,WAAW,EAAE,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,aAAa;QAOX,OAAO;YACL,QAAQ,EAAE,IAAI,CAAC,aAAa,CAAC,IAAI;YACjC,QAAQ,EAAE,IAAI,CAAC,aAAa,CAAC,IAAI;YACjC,QAAQ,EAAE,IAAI,CAAC,aAAa,CAAC,IAAI;YACjC,QAAQ,EAAE,IAAI,CAAC,aAAa,CAAC,IAAI;YACjC,QAAQ,EAAE,IAAI,CAAC,aAAa,CAAC,IAAI;SAClC,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,aAAa;QAOlB,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC,aAAa,EAAE,CAAC;IAC3C,CAAC;IAED;;;;OAIG;IACH,QAAQ,CAAC,GAAW;QAClB,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,QAAQ,CAChB,SAAS,CAAC,iBAAiB,EAC3B,sBAAsB,GAAG,8BAA8B,EACvD,OAAO,CACR,CAAC;QACJ,CAAC;QAED,8BAA8B;QAC9B,IAAI,WAAW,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACrD,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,WAAW,GAAG,WAAW;iBACtB,KAAK,CAAC,EAAE,CAAC;iBACT,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;iBACjB,IAAI,CAAC,EAAE,CAAC,CAAC;QACd,CAAC;QACD,MAAM,QAAQ,GAAG,WAAW,CAAC;QAE7B,cAAc;QACd,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAChD,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,kDAAkD;QAClD,IAAI,aAAa,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACzC,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/B,aAAa,GAAG,aAAa;iBAC1B,KAAK,CAAC,EAAE,CAAC;iBACT,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,IAAI,CAAC;iBAC1B,IAAI,CAAC,EAAE,CAAC,CAAC;QACd,CAAC;QAED,MAAM,CAAC,GAAG,QAAQ,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACtD,MAAM,CAAC,GAAG,QAAQ,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACtD,MAAM,CAAC,GAAG,QAAQ,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAEtD,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;QAC3B,eAAe;QACf,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACzC,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,GAAW;QACzB,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IACzC,CAAC;IAED;;;;OAIG;IACH,QAAQ,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS;QACtC,IAAI,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,QAAQ,CAChB,SAAS,CAAC,iBAAiB,EAC3B,yBAAyB,CAAC,OAAO,CAAC,OAAO,CAAC,wBAAwB,EAClE,OAAO,CACR,CAAC;QACJ,CAAC;QAED,mBAAmB;QACnB,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAElC,cAAc;QACd,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAChD,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,MAAM,KAAK,GAAG,CAAC,KAAa,EAAU,EAAE;YACtC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;YAC3C,OAAO,GAAG,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QAC5C,CAAC,CAAC;QAEF,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;QAClF,eAAe;QACf,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACzC,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS;QAC7C,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED;;;;OAIG;IACH,QAAQ,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS;QACtC,IAAI,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,QAAQ,CAChB,SAAS,CAAC,iBAAiB,EAC3B,yBAAyB,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,EAC5C,OAAO,CACR,CAAC;QACJ,CAAC;QAED,mBAAmB;QACnB,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAElC,cAAc;QACd,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAChD,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,qDAAqD;QACrD,6BAA6B;QAC7B,MAAM,KAAK,GAAG,CAAC,GAAG,GAAG,CAAC;QACtB,MAAM,KAAK,GAAG,CAAC,GAAG,GAAG,CAAC;QACtB,MAAM,KAAK,GAAG,CAAC,GAAG,GAAG,CAAC;QAEtB,kCAAkC;QAClC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;QAC1C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;QAC1C,MAAM,KAAK,GAAG,GAAG,GAAG,GAAG,CAAC;QAExB,+BAA+B;QAC/B,MAAM,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC;QAEpB,uBAAuB;QACvB,MAAM,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;QAE9C,gBAAgB;QAChB,IAAI,CAAC,GAAG,CAAC,CAAC;QACV,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;YAChB,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;gBAClB,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;YAC/D,CAAC;iBAAM,IAAI,GAAG,KAAK,KAAK,EAAE,CAAC;gBACzB,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;YACzC,CAAC;iBAAM,CAAC;gBACN,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;YACzC,CAAC;QACH,CAAC;QAED,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QAClE,eAAe;QACf,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACzC,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS;QAC7C,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED;;;;;OAKG;IACK,YAAY,CAAC,CAAS;QAC5B,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,GAAG,OAAO,CAAC,GAAG,OAAO,CAAC;IAC7C,CAAC;IAED;;;;OAIG;IACH,QAAQ,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS;QACtC,IAAI,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;YACzB,MAAM,IAAI,QAAQ,CAChB,SAAS,CAAC,iBAAiB,EAC3B,yBAAyB,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,EAC5C,OAAO,CACR,CAAC;QACJ,CAAC;QAED,wDAAwD;QACxD,qEAAqE;QACrE,mEAAmE;QACnE,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAEzC,gEAAgE;QAChE,sEAAsE;QACtE,MAAM,QAAQ,GAAG,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QAE1E,cAAc;QACd,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAChD,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,6CAA6C;QAC7C,MAAM,KAAK,GAAG,WAAW,GAAG,EAAE,CAAC;QAC/B,MAAM,KAAK,GAAG,CAAC,GAAG,GAAG,CAAC;QACtB,MAAM,KAAK,GAAG,CAAC,GAAG,GAAG,CAAC;QAEtB,MAAM,CAAC,GAAG,KAAK,GAAG,KAAK,CAAC;QACxB,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC9C,MAAM,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;QAEpB,IAAI,KAAK,GAAG,CAAC,EACX,KAAK,GAAG,CAAC,EACT,KAAK,GAAG,CAAC,CAAC;QAEZ,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YAC5B,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACpC,CAAC;aAAM,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACnC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACpC,CAAC;aAAM,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACnC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACpC,CAAC;aAAM,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACnC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACpC,CAAC;aAAM,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACnC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACpC,CAAC;aAAM,CAAC;YACN,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACpC,CAAC;QAED,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;QACxC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;QACxC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;QAExC,MAAM,MAAM,GAAG;YACb,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC;YAC7B,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC;YAC7B,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC;SAC9B,CAAC;QACF,eAAe;QACf,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACzC,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS;QAC7C,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED;;;OAGG;IACH,QAAQ,CAAC,GAAW;QAClB,8BAA8B;QAC9B,IAAI,WAAW,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACrD,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,WAAW,GAAG,WAAW;iBACtB,KAAK,CAAC,EAAE,CAAC;iBACT,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;iBACjB,IAAI,CAAC,EAAE,CAAC,CAAC;QACd,CAAC;QACD,MAAM,QAAQ,GAAG,WAAW,CAAC;QAE7B,cAAc;QACd,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAChD,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;QAClD,eAAe;QACf,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACzC,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,GAAW;QACzB,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,QAAQ,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS;QACtC,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QACnC,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS;QAC7C,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7C,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,GAAW;QACtB,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC/B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,YAAY,CAAC,GAAW;QAC7B,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IAC7C,CAAC;IAED;;;OAGG;IACH,gBAAgB,CAAC,IAAY,EAAE,IAAY;QACzC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAEjC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;QAC3B,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;QAC3B,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;QAE3B,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;IAChD,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,gBAAgB,CAAC,IAAY,EAAE,IAAY;QAChD,OAAO,IAAI,CAAC,UAAU,EAAE,CAAC,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACxD,CAAC;;AAzZD,0DAA0D;AAC1D,sFAAsF;AACvE,8BAAe,GAAmB,IAAI,cAAc,EAAE,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Color Manipulator
|
|
3
|
+
* Per R-4: Focused class for color manipulation operations
|
|
4
|
+
* Handles brightness, saturation, hue rotation, inversion, and desaturation
|
|
5
|
+
*/
|
|
6
|
+
import type { HexColor } from '../../types/index.js';
|
|
7
|
+
/**
|
|
8
|
+
* Color manipulation utilities
|
|
9
|
+
* Per R-4: Single Responsibility - color manipulation only
|
|
10
|
+
*/
|
|
11
|
+
export declare class ColorManipulator {
|
|
12
|
+
/**
|
|
13
|
+
* Adjust brightness of a color
|
|
14
|
+
* @param amount -100 to 100 (negative = darker, positive = lighter)
|
|
15
|
+
*/
|
|
16
|
+
static adjustBrightness(hex: string, amount: number): HexColor;
|
|
17
|
+
/**
|
|
18
|
+
* Adjust saturation of a color
|
|
19
|
+
* @param amount -100 to 100 (negative = less saturated, positive = more saturated)
|
|
20
|
+
*/
|
|
21
|
+
static adjustSaturation(hex: string, amount: number): HexColor;
|
|
22
|
+
/**
|
|
23
|
+
* Rotate hue of a color
|
|
24
|
+
* @param degrees Amount to rotate hue (can be negative or positive)
|
|
25
|
+
*/
|
|
26
|
+
static rotateHue(hex: string, degrees: number): HexColor;
|
|
27
|
+
/**
|
|
28
|
+
* Invert a color (create complementary color)
|
|
29
|
+
*/
|
|
30
|
+
static invert(hex: string): HexColor;
|
|
31
|
+
/**
|
|
32
|
+
* Desaturate a color (convert to grayscale)
|
|
33
|
+
*/
|
|
34
|
+
static desaturate(hex: string): HexColor;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=ColorManipulator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ColorManipulator.d.ts","sourceRoot":"","sources":["../../../src/services/color/ColorManipulator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAIrD;;;GAGG;AACH,qBAAa,gBAAgB;IAC3B;;;OAGG;IACH,MAAM,CAAC,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,QAAQ;IAM9D;;;OAGG;IACH,MAAM,CAAC,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,QAAQ;IAM9D;;;OAGG;IACH,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,QAAQ;IAOxD;;OAEG;IACH,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ;IAKpC;;OAEG;IACH,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ;CAIzC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Color Manipulator
|
|
3
|
+
* Per R-4: Focused class for color manipulation operations
|
|
4
|
+
* Handles brightness, saturation, hue rotation, inversion, and desaturation
|
|
5
|
+
*/
|
|
6
|
+
import { clamp } from '../../utils/index.js';
|
|
7
|
+
import { ColorConverter } from './ColorConverter.js';
|
|
8
|
+
/**
|
|
9
|
+
* Color manipulation utilities
|
|
10
|
+
* Per R-4: Single Responsibility - color manipulation only
|
|
11
|
+
*/
|
|
12
|
+
export class ColorManipulator {
|
|
13
|
+
/**
|
|
14
|
+
* Adjust brightness of a color
|
|
15
|
+
* @param amount -100 to 100 (negative = darker, positive = lighter)
|
|
16
|
+
*/
|
|
17
|
+
static adjustBrightness(hex, amount) {
|
|
18
|
+
const hsv = ColorConverter.hexToHsv(hex);
|
|
19
|
+
hsv.v = clamp(hsv.v + amount, 0, 100);
|
|
20
|
+
return ColorConverter.hsvToHex(hsv.h, hsv.s, hsv.v);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Adjust saturation of a color
|
|
24
|
+
* @param amount -100 to 100 (negative = less saturated, positive = more saturated)
|
|
25
|
+
*/
|
|
26
|
+
static adjustSaturation(hex, amount) {
|
|
27
|
+
const hsv = ColorConverter.hexToHsv(hex);
|
|
28
|
+
hsv.s = clamp(hsv.s + amount, 0, 100);
|
|
29
|
+
return ColorConverter.hsvToHex(hsv.h, hsv.s, hsv.v);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Rotate hue of a color
|
|
33
|
+
* @param degrees Amount to rotate hue (can be negative or positive)
|
|
34
|
+
*/
|
|
35
|
+
static rotateHue(hex, degrees) {
|
|
36
|
+
const hsv = ColorConverter.hexToHsv(hex);
|
|
37
|
+
// Normalize to 0-360 to handle negative values properly
|
|
38
|
+
hsv.h = (((hsv.h + degrees) % 360) + 360) % 360;
|
|
39
|
+
return ColorConverter.hsvToHex(hsv.h, hsv.s, hsv.v);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Invert a color (create complementary color)
|
|
43
|
+
*/
|
|
44
|
+
static invert(hex) {
|
|
45
|
+
const rgb = ColorConverter.hexToRgb(hex);
|
|
46
|
+
return ColorConverter.rgbToHex(255 - rgb.r, 255 - rgb.g, 255 - rgb.b);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Desaturate a color (convert to grayscale)
|
|
50
|
+
*/
|
|
51
|
+
static desaturate(hex) {
|
|
52
|
+
const hsv = ColorConverter.hexToHsv(hex);
|
|
53
|
+
return ColorConverter.hsvToHex(hsv.h, 0, hsv.v);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=ColorManipulator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ColorManipulator.js","sourceRoot":"","sources":["../../../src/services/color/ColorManipulator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD;;;GAGG;AACH,MAAM,OAAO,gBAAgB;IAC3B;;;OAGG;IACH,MAAM,CAAC,gBAAgB,CAAC,GAAW,EAAE,MAAc;QACjD,MAAM,GAAG,GAAG,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACzC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;QACtC,OAAO,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;IACtD,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,gBAAgB,CAAC,GAAW,EAAE,MAAc;QACjD,MAAM,GAAG,GAAG,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACzC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;QACtC,OAAO,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;IACtD,CAAC;IAED;;;OAGG;IACH,MAAM,CAAC,SAAS,CAAC,GAAW,EAAE,OAAe;QAC3C,MAAM,GAAG,GAAG,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACzC,wDAAwD;QACxD,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;QAChD,OAAO,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;IACtD,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,MAAM,CAAC,GAAW;QACvB,MAAM,GAAG,GAAG,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACzC,OAAO,cAAc,CAAC,QAAQ,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IACxE,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,UAAU,CAAC,GAAW;QAC3B,MAAM,GAAG,GAAG,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACzC,OAAO,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;IAClD,CAAC;CACF"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Colorblindness Simulator
|
|
3
|
+
* Per R-4: Focused class for colorblindness simulation
|
|
4
|
+
* Uses Brettel 1997 transformation matrices
|
|
5
|
+
*/
|
|
6
|
+
import type { RGB, HexColor, VisionType } from '../../types/index.js';
|
|
7
|
+
/**
|
|
8
|
+
* Colorblindness simulator using Brettel 1997 matrices
|
|
9
|
+
* Per R-4: Single Responsibility - colorblindness simulation only
|
|
10
|
+
*/
|
|
11
|
+
export declare class ColorblindnessSimulator {
|
|
12
|
+
private static readonly colorblindCache;
|
|
13
|
+
/**
|
|
14
|
+
* Clear colorblindness cache
|
|
15
|
+
*/
|
|
16
|
+
static clearCache(): void;
|
|
17
|
+
/**
|
|
18
|
+
* Get cache statistics
|
|
19
|
+
*/
|
|
20
|
+
static getCacheStats(): {
|
|
21
|
+
colorblind: number;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Simulate colorblindness on an RGB color
|
|
25
|
+
* Uses Brettel 1997 transformation matrices (pre-computed constants)
|
|
26
|
+
* Per P-1: Cached by ${r},${g},${b}_${visionType} key
|
|
27
|
+
* @example simulateColorblindness({ r: 255, g: 0, b: 0 }, 'deuteranopia')
|
|
28
|
+
*/
|
|
29
|
+
static simulateColorblindness(rgb: RGB, visionType: VisionType): RGB;
|
|
30
|
+
/**
|
|
31
|
+
* Simulate colorblindness on a hex color
|
|
32
|
+
*/
|
|
33
|
+
static simulateColorblindnessHex(hex: string, visionType: VisionType): HexColor;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=ColorblindnessSimulator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ColorblindnessSimulator.d.ts","sourceRoot":"","sources":["../../../src/services/color/ColorblindnessSimulator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAgDtE;;;GAGG;AACH,qBAAa,uBAAuB;IAElC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAmC;IAE1E;;OAEG;IACH,MAAM,CAAC,UAAU,IAAI,IAAI;IAIzB;;OAEG;IACH,MAAM,CAAC,aAAa,IAAI;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE;IAM9C;;;;;OAKG;IACH,MAAM,CAAC,sBAAsB,CAAC,GAAG,EAAE,GAAG,EAAE,UAAU,EAAE,UAAU,GAAG,GAAG;IA+CpE;;OAEG;IACH,MAAM,CAAC,yBAAyB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,GAAG,QAAQ;CAKhF"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Colorblindness Simulator
|
|
3
|
+
* Per R-4: Focused class for colorblindness simulation
|
|
4
|
+
* Uses Brettel 1997 transformation matrices
|
|
5
|
+
*/
|
|
6
|
+
import { ErrorCode, AppError } from '../../types/index.js';
|
|
7
|
+
import { BRETTEL_MATRICES } from '../../constants/index.js';
|
|
8
|
+
import { clamp, round, isValidRGB } from '../../utils/index.js';
|
|
9
|
+
import { ColorConverter } from './ColorConverter.js';
|
|
10
|
+
/**
|
|
11
|
+
* Simple LRU cache implementation
|
|
12
|
+
*/
|
|
13
|
+
class LRUCache {
|
|
14
|
+
constructor(maxSize = 1000) {
|
|
15
|
+
this.cache = new Map();
|
|
16
|
+
this.maxSize = maxSize;
|
|
17
|
+
}
|
|
18
|
+
get(key) {
|
|
19
|
+
const value = this.cache.get(key);
|
|
20
|
+
if (value !== undefined) {
|
|
21
|
+
this.cache.delete(key);
|
|
22
|
+
this.cache.set(key, value);
|
|
23
|
+
}
|
|
24
|
+
return value;
|
|
25
|
+
}
|
|
26
|
+
set(key, value) {
|
|
27
|
+
if (this.cache.has(key)) {
|
|
28
|
+
this.cache.delete(key);
|
|
29
|
+
}
|
|
30
|
+
else if (this.cache.size >= this.maxSize) {
|
|
31
|
+
const firstKey = this.cache.keys().next().value;
|
|
32
|
+
if (firstKey !== undefined) {
|
|
33
|
+
this.cache.delete(firstKey);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
this.cache.set(key, value);
|
|
37
|
+
}
|
|
38
|
+
clear() {
|
|
39
|
+
this.cache.clear();
|
|
40
|
+
}
|
|
41
|
+
get size() {
|
|
42
|
+
return this.cache.size;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Colorblindness simulator using Brettel 1997 matrices
|
|
47
|
+
* Per R-4: Single Responsibility - colorblindness simulation only
|
|
48
|
+
*/
|
|
49
|
+
export class ColorblindnessSimulator {
|
|
50
|
+
/**
|
|
51
|
+
* Clear colorblindness cache
|
|
52
|
+
*/
|
|
53
|
+
static clearCache() {
|
|
54
|
+
this.colorblindCache.clear();
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Get cache statistics
|
|
58
|
+
*/
|
|
59
|
+
static getCacheStats() {
|
|
60
|
+
return {
|
|
61
|
+
colorblind: this.colorblindCache.size,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Simulate colorblindness on an RGB color
|
|
66
|
+
* Uses Brettel 1997 transformation matrices (pre-computed constants)
|
|
67
|
+
* Per P-1: Cached by ${r},${g},${b}_${visionType} key
|
|
68
|
+
* @example simulateColorblindness({ r: 255, g: 0, b: 0 }, 'deuteranopia')
|
|
69
|
+
*/
|
|
70
|
+
static simulateColorblindness(rgb, visionType) {
|
|
71
|
+
if (visionType === 'normal') {
|
|
72
|
+
return { ...rgb };
|
|
73
|
+
}
|
|
74
|
+
if (!isValidRGB(rgb.r, rgb.g, rgb.b)) {
|
|
75
|
+
throw new AppError(ErrorCode.INVALID_RGB_VALUE, 'Invalid RGB values for colorblindness simulation', 'error');
|
|
76
|
+
}
|
|
77
|
+
// Per P-1: Cache key format: ${r},${g},${b}_${visionType}
|
|
78
|
+
const cacheKey = `${rgb.r},${rgb.g},${rgb.b}_${visionType}`;
|
|
79
|
+
// Check cache
|
|
80
|
+
const cached = this.colorblindCache.get(cacheKey);
|
|
81
|
+
if (cached) {
|
|
82
|
+
return cached;
|
|
83
|
+
}
|
|
84
|
+
// Per P-1: BRETTEL_MATRICES are already pre-computed constants (no recalculation needed)
|
|
85
|
+
const matrix = BRETTEL_MATRICES[visionType];
|
|
86
|
+
// Normalize RGB to 0-1 range
|
|
87
|
+
const rNorm = rgb.r / 255;
|
|
88
|
+
const gNorm = rgb.g / 255;
|
|
89
|
+
const bNorm = rgb.b / 255;
|
|
90
|
+
// Apply transformation matrix
|
|
91
|
+
const transformedR = round(clamp((matrix[0][0] * rNorm + matrix[0][1] * gNorm + matrix[0][2] * bNorm) * 255, 0, 255));
|
|
92
|
+
const transformedG = round(clamp((matrix[1][0] * rNorm + matrix[1][1] * gNorm + matrix[1][2] * bNorm) * 255, 0, 255));
|
|
93
|
+
const transformedB = round(clamp((matrix[2][0] * rNorm + matrix[2][1] * gNorm + matrix[2][2] * bNorm) * 255, 0, 255));
|
|
94
|
+
const result = { r: transformedR, g: transformedG, b: transformedB };
|
|
95
|
+
// Cache result
|
|
96
|
+
this.colorblindCache.set(cacheKey, result);
|
|
97
|
+
return result;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Simulate colorblindness on a hex color
|
|
101
|
+
*/
|
|
102
|
+
static simulateColorblindnessHex(hex, visionType) {
|
|
103
|
+
const rgb = ColorConverter.hexToRgb(hex);
|
|
104
|
+
const simulated = this.simulateColorblindness(rgb, visionType);
|
|
105
|
+
return ColorConverter.rgbToHex(simulated.r, simulated.g, simulated.b);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// Per P-1: LRU cache for colorblindness simulation
|
|
109
|
+
ColorblindnessSimulator.colorblindCache = new LRUCache(1000);
|
|
110
|
+
//# sourceMappingURL=ColorblindnessSimulator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ColorblindnessSimulator.js","sourceRoot":"","sources":["../../../src/services/color/ColorblindnessSimulator.ts"],"names":[],"mappings":"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"}
|