@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,349 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @xivdyetools/core - Palette Extraction Service
|
|
3
|
+
*
|
|
4
|
+
* Extracts dominant colors from pixel data using K-means clustering.
|
|
5
|
+
* Matches extracted colors to closest FFXIV dyes.
|
|
6
|
+
*
|
|
7
|
+
* @module services/PaletteService
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { PaletteService, DyeService, dyeDatabase } from '@xivdyetools/core';
|
|
11
|
+
*
|
|
12
|
+
* const paletteService = new PaletteService();
|
|
13
|
+
* const dyeService = new DyeService(dyeDatabase);
|
|
14
|
+
*
|
|
15
|
+
* // Extract 4 dominant colors from pixel data
|
|
16
|
+
* const palette = paletteService.extractPalette(pixels, 4);
|
|
17
|
+
*
|
|
18
|
+
* // Extract and match to dyes in one step
|
|
19
|
+
* const matches = paletteService.extractAndMatchPalette(pixels, 4, dyeService);
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
import { NoOpLogger } from '../types/index.js';
|
|
23
|
+
import { ColorService } from './ColorService.js';
|
|
24
|
+
// ============================================================================
|
|
25
|
+
// K-Means Clustering Implementation
|
|
26
|
+
// ============================================================================
|
|
27
|
+
/**
|
|
28
|
+
* Calculate Euclidean distance between two RGB colors
|
|
29
|
+
*/
|
|
30
|
+
function rgbDistance(a, b) {
|
|
31
|
+
const dr = a.r - b.r;
|
|
32
|
+
const dg = a.g - b.g;
|
|
33
|
+
const db = a.b - b.b;
|
|
34
|
+
return Math.sqrt(dr * dr + dg * dg + db * db);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Calculate the mean of an array of RGB colors
|
|
38
|
+
*/
|
|
39
|
+
function rgbMean(colors) {
|
|
40
|
+
if (colors.length === 0) {
|
|
41
|
+
return { r: 0, g: 0, b: 0 };
|
|
42
|
+
}
|
|
43
|
+
let sumR = 0;
|
|
44
|
+
let sumG = 0;
|
|
45
|
+
let sumB = 0;
|
|
46
|
+
for (const c of colors) {
|
|
47
|
+
sumR += c.r;
|
|
48
|
+
sumG += c.g;
|
|
49
|
+
sumB += c.b;
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
r: Math.round(sumR / colors.length),
|
|
53
|
+
g: Math.round(sumG / colors.length),
|
|
54
|
+
b: Math.round(sumB / colors.length),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* K-means++ initialization for better starting centroids
|
|
59
|
+
* Selects initial centroids that are well-distributed
|
|
60
|
+
* CORE-PERF-003: Optimized from O(n*k²) to O(n*k) by caching minimum distances
|
|
61
|
+
*/
|
|
62
|
+
function kMeansPlusPlusInit(pixels, k) {
|
|
63
|
+
if (pixels.length === 0 || k <= 0) {
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
66
|
+
const centroids = [];
|
|
67
|
+
// First centroid: random pixel
|
|
68
|
+
const firstIndex = Math.floor(Math.random() * pixels.length);
|
|
69
|
+
centroids.push({ ...pixels[firstIndex] });
|
|
70
|
+
// CORE-PERF-003: Cache minimum distances to avoid O(k) inner loop
|
|
71
|
+
// Initialize with distance to first centroid
|
|
72
|
+
const minDistances = new Array(pixels.length);
|
|
73
|
+
for (let j = 0; j < pixels.length; j++) {
|
|
74
|
+
minDistances[j] = rgbDistance(pixels[j], centroids[0]);
|
|
75
|
+
}
|
|
76
|
+
// Remaining centroids: weighted probability by distance squared
|
|
77
|
+
for (let i = 1; i < k; i++) {
|
|
78
|
+
// Calculate total distance (squared) for probability distribution
|
|
79
|
+
let totalDistanceSquared = 0;
|
|
80
|
+
for (let j = 0; j < pixels.length; j++) {
|
|
81
|
+
totalDistanceSquared += minDistances[j] * minDistances[j];
|
|
82
|
+
}
|
|
83
|
+
// Select next centroid with probability proportional to distance squared
|
|
84
|
+
let selectedIndex = 0;
|
|
85
|
+
if (totalDistanceSquared === 0) {
|
|
86
|
+
// All remaining pixels are duplicates of centroids
|
|
87
|
+
selectedIndex = Math.floor(Math.random() * pixels.length);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
let threshold = Math.random() * totalDistanceSquared;
|
|
91
|
+
for (let j = 0; j < pixels.length; j++) {
|
|
92
|
+
threshold -= minDistances[j] * minDistances[j];
|
|
93
|
+
if (threshold <= 0) {
|
|
94
|
+
selectedIndex = j;
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
centroids.push({ ...pixels[selectedIndex] });
|
|
100
|
+
// CORE-PERF-003: Only compute distance to the NEW centroid and update minimums
|
|
101
|
+
// This reduces complexity from O(n*k) per iteration to O(n) per iteration
|
|
102
|
+
const newCentroid = centroids[centroids.length - 1];
|
|
103
|
+
for (let j = 0; j < pixels.length; j++) {
|
|
104
|
+
const distToNew = rgbDistance(pixels[j], newCentroid);
|
|
105
|
+
if (distToNew < minDistances[j]) {
|
|
106
|
+
minDistances[j] = distToNew;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return centroids;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Assign each pixel to its nearest centroid
|
|
114
|
+
* Returns array of cluster indices and the clusters themselves
|
|
115
|
+
*/
|
|
116
|
+
function assignToClusters(pixels, centroids) {
|
|
117
|
+
const assignments = new Array(pixels.length);
|
|
118
|
+
const clusters = centroids.map(() => []);
|
|
119
|
+
for (let i = 0; i < pixels.length; i++) {
|
|
120
|
+
const pixel = pixels[i];
|
|
121
|
+
let minDist = Infinity;
|
|
122
|
+
let nearestCluster = 0;
|
|
123
|
+
for (let j = 0; j < centroids.length; j++) {
|
|
124
|
+
const dist = rgbDistance(pixel, centroids[j]);
|
|
125
|
+
if (dist < minDist) {
|
|
126
|
+
minDist = dist;
|
|
127
|
+
nearestCluster = j;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
assignments[i] = nearestCluster;
|
|
131
|
+
clusters[nearestCluster].push(pixel);
|
|
132
|
+
}
|
|
133
|
+
return { assignments, clusters };
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Update centroids to be the mean of their clusters
|
|
137
|
+
* Returns new centroids and the maximum movement distance
|
|
138
|
+
*/
|
|
139
|
+
function updateCentroids(centroids, clusters) {
|
|
140
|
+
const newCentroids = [];
|
|
141
|
+
let maxMovement = 0;
|
|
142
|
+
for (let i = 0; i < centroids.length; i++) {
|
|
143
|
+
const cluster = clusters[i];
|
|
144
|
+
if (cluster.length === 0) {
|
|
145
|
+
// Empty cluster: keep old centroid
|
|
146
|
+
newCentroids.push({ ...centroids[i] });
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
const newCentroid = rgbMean(cluster);
|
|
150
|
+
const movement = rgbDistance(centroids[i], newCentroid);
|
|
151
|
+
if (movement > maxMovement) {
|
|
152
|
+
maxMovement = movement;
|
|
153
|
+
}
|
|
154
|
+
newCentroids.push(newCentroid);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return { newCentroids, maxMovement };
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Run K-means clustering on pixel data
|
|
161
|
+
*/
|
|
162
|
+
function kMeansClustering(pixels, k, maxIterations, convergenceThreshold) {
|
|
163
|
+
if (pixels.length === 0) {
|
|
164
|
+
return { centroids: [], clusterSizes: [] };
|
|
165
|
+
}
|
|
166
|
+
// Limit k to number of unique pixels
|
|
167
|
+
const effectiveK = Math.min(k, pixels.length);
|
|
168
|
+
// Initialize centroids using K-means++
|
|
169
|
+
let centroids = kMeansPlusPlusInit(pixels, effectiveK);
|
|
170
|
+
// Iterate until convergence or max iterations
|
|
171
|
+
for (let iter = 0; iter < maxIterations; iter++) {
|
|
172
|
+
// Assign pixels to clusters
|
|
173
|
+
const { clusters } = assignToClusters(pixels, centroids);
|
|
174
|
+
// Update centroids
|
|
175
|
+
const { newCentroids, maxMovement } = updateCentroids(centroids, clusters);
|
|
176
|
+
centroids = newCentroids;
|
|
177
|
+
// Check for convergence
|
|
178
|
+
if (maxMovement < convergenceThreshold) {
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
// Final assignment to get cluster sizes
|
|
183
|
+
const { clusters } = assignToClusters(pixels, centroids);
|
|
184
|
+
const clusterSizes = clusters.map((c) => c.length);
|
|
185
|
+
return { centroids, clusterSizes };
|
|
186
|
+
}
|
|
187
|
+
// ============================================================================
|
|
188
|
+
// PaletteService Class
|
|
189
|
+
// ============================================================================
|
|
190
|
+
/**
|
|
191
|
+
* Service for extracting color palettes from images
|
|
192
|
+
*
|
|
193
|
+
* Uses K-means clustering to find dominant colors, then matches
|
|
194
|
+
* them to the closest FFXIV dyes.
|
|
195
|
+
*/
|
|
196
|
+
export class PaletteService {
|
|
197
|
+
/**
|
|
198
|
+
* Create a new PaletteService
|
|
199
|
+
* @param options - Optional configuration including logger
|
|
200
|
+
*/
|
|
201
|
+
constructor(options = {}) {
|
|
202
|
+
this.logger = options.logger ?? NoOpLogger;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Sample pixels from an array if it exceeds maxSamples
|
|
206
|
+
* Uses uniform sampling to maintain color distribution
|
|
207
|
+
* CORE-PERF-004: Fixed potential out-of-bounds access on last iteration
|
|
208
|
+
*/
|
|
209
|
+
samplePixels(pixels, maxSamples) {
|
|
210
|
+
if (pixels.length <= maxSamples) {
|
|
211
|
+
return pixels;
|
|
212
|
+
}
|
|
213
|
+
const step = pixels.length / maxSamples;
|
|
214
|
+
const samples = [];
|
|
215
|
+
for (let i = 0; i < maxSamples; i++) {
|
|
216
|
+
// Clamp index to prevent out-of-bounds access due to floating-point rounding
|
|
217
|
+
const index = Math.min(Math.floor(i * step), pixels.length - 1);
|
|
218
|
+
samples.push(pixels[index]);
|
|
219
|
+
}
|
|
220
|
+
return samples;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Extract dominant colors from pixel data
|
|
224
|
+
*
|
|
225
|
+
* @param pixels - Array of RGB pixel values
|
|
226
|
+
* @param options - Extraction options (colorCount, maxIterations, etc.)
|
|
227
|
+
* @returns Array of extracted colors sorted by dominance (most dominant first)
|
|
228
|
+
*
|
|
229
|
+
* @example
|
|
230
|
+
* ```typescript
|
|
231
|
+
* const pixels = [{ r: 255, g: 0, b: 0 }, { r: 254, g: 1, b: 1 }, ...];
|
|
232
|
+
* const palette = paletteService.extractPalette(pixels, { colorCount: 4 });
|
|
233
|
+
* // Returns: [{ color: { r: 255, g: 0, b: 0 }, dominance: 45, pixelCount: 4500 }, ...]
|
|
234
|
+
* ```
|
|
235
|
+
*/
|
|
236
|
+
extractPalette(pixels, options = {}) {
|
|
237
|
+
const opts = { ...PaletteService.DEFAULT_OPTIONS, ...options };
|
|
238
|
+
// Validate colorCount
|
|
239
|
+
const colorCount = Math.max(1, Math.min(10, opts.colorCount));
|
|
240
|
+
// SECURITY: Clamp maxIterations to prevent DoS via algorithmic complexity
|
|
241
|
+
const maxIterations = Math.max(1, Math.min(100, opts.maxIterations));
|
|
242
|
+
if (pixels.length === 0) {
|
|
243
|
+
this.logger.warn('PaletteService.extractPalette: Empty pixel array');
|
|
244
|
+
return [];
|
|
245
|
+
}
|
|
246
|
+
this.logger.info(`Extracting ${colorCount} colors from ${pixels.length} pixels`);
|
|
247
|
+
// Sample pixels if too many
|
|
248
|
+
const sampledPixels = this.samplePixels(pixels, opts.maxSamples);
|
|
249
|
+
// Run K-means clustering
|
|
250
|
+
const { centroids, clusterSizes } = kMeansClustering(sampledPixels, colorCount, maxIterations, opts.convergenceThreshold);
|
|
251
|
+
// Calculate total pixels for dominance percentage
|
|
252
|
+
const totalPixels = clusterSizes.reduce((sum, size) => sum + size, 0);
|
|
253
|
+
// Build result array
|
|
254
|
+
const result = centroids.map((color, i) => ({
|
|
255
|
+
color,
|
|
256
|
+
dominance: totalPixels > 0 ? Math.round((clusterSizes[i] / totalPixels) * 100) : 0,
|
|
257
|
+
pixelCount: clusterSizes[i],
|
|
258
|
+
}));
|
|
259
|
+
// Sort by dominance (most dominant first)
|
|
260
|
+
result.sort((a, b) => b.dominance - a.dominance);
|
|
261
|
+
this.logger.info(`Extracted colors: ${result.map((r) => `${r.dominance}%`).join(', ')}`);
|
|
262
|
+
return result;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Extract colors from pixel data and match each to the closest FFXIV dye
|
|
266
|
+
*
|
|
267
|
+
* @param pixels - Array of RGB pixel values
|
|
268
|
+
* @param dyeService - DyeService instance for matching
|
|
269
|
+
* @param options - Extraction options
|
|
270
|
+
* @returns Array of palette matches sorted by dominance
|
|
271
|
+
*
|
|
272
|
+
* @example
|
|
273
|
+
* ```typescript
|
|
274
|
+
* const matches = paletteService.extractAndMatchPalette(pixels, dyeService, { colorCount: 4 });
|
|
275
|
+
* // Returns: [{ extracted: {...}, matchedDye: {...}, distance: 12.3, dominance: 45 }, ...]
|
|
276
|
+
* ```
|
|
277
|
+
*/
|
|
278
|
+
extractAndMatchPalette(pixels, dyeService, options = {}) {
|
|
279
|
+
// Extract palette
|
|
280
|
+
const extracted = this.extractPalette(pixels, options);
|
|
281
|
+
// Match each extracted color to closest dye
|
|
282
|
+
const matches = [];
|
|
283
|
+
for (const ex of extracted) {
|
|
284
|
+
// Convert RGB to hex for DyeService
|
|
285
|
+
const hex = ColorService.rgbToHex(ex.color.r, ex.color.g, ex.color.b);
|
|
286
|
+
const matchedDye = dyeService.findClosestDye(hex);
|
|
287
|
+
if (matchedDye) {
|
|
288
|
+
// Calculate distance between extracted and matched colors
|
|
289
|
+
const distance = rgbDistance(ex.color, matchedDye.rgb);
|
|
290
|
+
matches.push({
|
|
291
|
+
extracted: ex.color,
|
|
292
|
+
matchedDye,
|
|
293
|
+
distance,
|
|
294
|
+
dominance: ex.dominance,
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
return matches;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Convert flat pixel array (Uint8ClampedArray from canvas) to RGB array
|
|
302
|
+
* Skips alpha channel
|
|
303
|
+
*
|
|
304
|
+
* @param data - Flat array of RGBA values [r, g, b, a, r, g, b, a, ...]
|
|
305
|
+
* @returns Array of RGB objects
|
|
306
|
+
*/
|
|
307
|
+
static pixelDataToRGB(data) {
|
|
308
|
+
const pixels = [];
|
|
309
|
+
for (let i = 0; i < data.length; i += 4) {
|
|
310
|
+
pixels.push({
|
|
311
|
+
r: data[i],
|
|
312
|
+
g: data[i + 1],
|
|
313
|
+
b: data[i + 2],
|
|
314
|
+
// Skip alpha at data[i + 3]
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
return pixels;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Filter out near-transparent pixels from RGBA data
|
|
321
|
+
* Useful for images with transparent backgrounds
|
|
322
|
+
*
|
|
323
|
+
* @param data - Flat array of RGBA values
|
|
324
|
+
* @param alphaThreshold - Minimum alpha to include (0-255, default: 128)
|
|
325
|
+
* @returns Array of RGB objects for non-transparent pixels
|
|
326
|
+
*/
|
|
327
|
+
static pixelDataToRGBFiltered(data, alphaThreshold = 128) {
|
|
328
|
+
const pixels = [];
|
|
329
|
+
for (let i = 0; i < data.length; i += 4) {
|
|
330
|
+
const alpha = data[i + 3];
|
|
331
|
+
if (alpha >= alphaThreshold) {
|
|
332
|
+
pixels.push({
|
|
333
|
+
r: data[i],
|
|
334
|
+
g: data[i + 1],
|
|
335
|
+
b: data[i + 2],
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
return pixels;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
/** Default extraction options */
|
|
343
|
+
PaletteService.DEFAULT_OPTIONS = {
|
|
344
|
+
colorCount: 4,
|
|
345
|
+
maxIterations: 25,
|
|
346
|
+
convergenceThreshold: 1.0,
|
|
347
|
+
maxSamples: 10000,
|
|
348
|
+
};
|
|
349
|
+
//# sourceMappingURL=PaletteService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PaletteService.js","sourceRoot":"","sources":["../../src/services/PaletteService.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAuDjD,+EAA+E;AAC/E,oCAAoC;AACpC,+EAA+E;AAE/E;;GAEG;AACH,SAAS,WAAW,CAAC,CAAM,EAAE,CAAM;IACjC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACrB,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACrB,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACrB,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;AAChD,CAAC;AAED;;GAEG;AACH,SAAS,OAAO,CAAC,MAAa;IAC5B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;IAC9B,CAAC;IAED,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,IAAI,IAAI,GAAG,CAAC,CAAC;IAEb,KAAK,MAAM,CAAC,IAAI,MAAM,EAAE,CAAC;QACvB,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;QACZ,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;QACZ,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;IACd,CAAC;IAED,OAAO;QACL,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC;QACnC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC;QACnC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC;KACpC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAS,kBAAkB,CAAC,MAAa,EAAE,CAAS;IAClD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAClC,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,SAAS,GAAU,EAAE,CAAC;IAE5B,+BAA+B;IAC/B,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IAC7D,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;IAE1C,kEAAkE;IAClE,6CAA6C;IAC7C,MAAM,YAAY,GAAa,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACxD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,YAAY,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IACzD,CAAC;IAED,gEAAgE;IAChE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,kEAAkE;QAClE,IAAI,oBAAoB,GAAG,CAAC,CAAC;QAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACvC,oBAAoB,IAAI,YAAY,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;QAC5D,CAAC;QAED,yEAAyE;QACzE,IAAI,aAAa,GAAG,CAAC,CAAC;QACtB,IAAI,oBAAoB,KAAK,CAAC,EAAE,CAAC;YAC/B,mDAAmD;YACnD,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAC5D,CAAC;aAAM,CAAC;YACN,IAAI,SAAS,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,oBAAoB,CAAC;YAErD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACvC,SAAS,IAAI,YAAY,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;gBAC/C,IAAI,SAAS,IAAI,CAAC,EAAE,CAAC;oBACnB,aAAa,GAAG,CAAC,CAAC;oBAClB,MAAM;gBACR,CAAC;YACH,CAAC;QACH,CAAC;QAED,SAAS,CAAC,IAAI,CAAC,EAAE,GAAG,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;QAE7C,+EAA+E;QAC/E,0EAA0E;QAC1E,MAAM,WAAW,GAAG,SAAS,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACpD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACvC,MAAM,SAAS,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;YACtD,IAAI,SAAS,GAAG,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;gBAChC,YAAY,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;YAC9B,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;GAGG;AACH,SAAS,gBAAgB,CACvB,MAAa,EACb,SAAgB;IAEhB,MAAM,WAAW,GAAa,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACvD,MAAM,QAAQ,GAAY,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;IAElD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACxB,IAAI,OAAO,GAAG,QAAQ,CAAC;QACvB,IAAI,cAAc,GAAG,CAAC,CAAC;QAEvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC1C,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9C,IAAI,IAAI,GAAG,OAAO,EAAE,CAAC;gBACnB,OAAO,GAAG,IAAI,CAAC;gBACf,cAAc,GAAG,CAAC,CAAC;YACrB,CAAC;QACH,CAAC;QAED,WAAW,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC;QAChC,QAAQ,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACvC,CAAC;IAED,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC;AACnC,CAAC;AAED;;;GAGG;AACH,SAAS,eAAe,CACtB,SAAgB,EAChB,QAAiB;IAEjB,MAAM,YAAY,GAAU,EAAE,CAAC;IAC/B,IAAI,WAAW,GAAG,CAAC,CAAC;IAEpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QAE5B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,mCAAmC;YACnC,YAAY,CAAC,IAAI,CAAC,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;YACrC,MAAM,QAAQ,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;YACxD,IAAI,QAAQ,GAAG,WAAW,EAAE,CAAC;gBAC3B,WAAW,GAAG,QAAQ,CAAC;YACzB,CAAC;YACD,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAED,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC;AACvC,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB,CACvB,MAAa,EACb,CAAS,EACT,aAAqB,EACrB,oBAA4B;IAE5B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;IAC7C,CAAC;IAED,qCAAqC;IACrC,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAE9C,uCAAuC;IACvC,IAAI,SAAS,GAAG,kBAAkB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAEvD,8CAA8C;IAC9C,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,aAAa,EAAE,IAAI,EAAE,EAAE,CAAC;QAChD,4BAA4B;QAC5B,MAAM,EAAE,QAAQ,EAAE,GAAG,gBAAgB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAEzD,mBAAmB;QACnB,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,GAAG,eAAe,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAC3E,SAAS,GAAG,YAAY,CAAC;QAEzB,wBAAwB;QACxB,IAAI,WAAW,GAAG,oBAAoB,EAAE,CAAC;YACvC,MAAM;QACR,CAAC;IACH,CAAC;IAED,wCAAwC;IACxC,MAAM,EAAE,QAAQ,EAAE,GAAG,gBAAgB,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACzD,MAAM,YAAY,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAEnD,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC;AACrC,CAAC;AAED,+EAA+E;AAC/E,uBAAuB;AACvB,+EAA+E;AAE/E;;;;;GAKG;AACH,MAAM,OAAO,cAAc;IAWzB;;;OAGG;IACH,YAAY,UAAiC,EAAE;QAC7C,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,UAAU,CAAC;IAC7C,CAAC;IAED;;;;OAIG;IACK,YAAY,CAAC,MAAa,EAAE,UAAkB;QACpD,IAAI,MAAM,CAAC,MAAM,IAAI,UAAU,EAAE,CAAC;YAChC,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,GAAG,UAAU,CAAC;QACxC,MAAM,OAAO,GAAU,EAAE,CAAC;QAE1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE,EAAE,CAAC;YACpC,6EAA6E;YAC7E,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAChE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAC9B,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,cAAc,CAAC,MAAa,EAAE,UAAoC,EAAE;QAClE,MAAM,IAAI,GAAG,EAAE,GAAG,cAAc,CAAC,eAAe,EAAE,GAAG,OAAO,EAAE,CAAC;QAE/D,sBAAsB;QACtB,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;QAE9D,0EAA0E;QAC1E,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC;QAErE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC;YACrE,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,UAAU,gBAAgB,MAAM,CAAC,MAAM,SAAS,CAAC,CAAC;QAEjF,4BAA4B;QAC5B,MAAM,aAAa,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QAEjE,yBAAyB;QACzB,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,gBAAgB,CAClD,aAAa,EACb,UAAU,EACV,aAAa,EACb,IAAI,CAAC,oBAAoB,CAC1B,CAAC;QAEF,kDAAkD;QAClD,MAAM,WAAW,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC;QAEtE,qBAAqB;QACrB,MAAM,MAAM,GAAqB,SAAS,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;YAC5D,KAAK;YACL,SAAS,EAAE,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;YAClF,UAAU,EAAE,YAAY,CAAC,CAAC,CAAC;SAC5B,CAAC,CAAC,CAAC;QAEJ,0CAA0C;QAC1C,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;QAEjD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,qBAAqB,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEzF,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,sBAAsB,CACpB,MAAa,EACb,UAAsB,EACtB,UAAoC,EAAE;QAEtC,kBAAkB;QAClB,MAAM,SAAS,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAEvD,4CAA4C;QAC5C,MAAM,OAAO,GAAmB,EAAE,CAAC;QAEnC,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE,CAAC;YAC3B,oCAAoC;YACpC,MAAM,GAAG,GAAG,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACtE,MAAM,UAAU,GAAG,UAAU,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;YAElD,IAAI,UAAU,EAAE,CAAC;gBACf,0DAA0D;gBAC1D,MAAM,QAAQ,GAAG,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC;gBAEvD,OAAO,CAAC,IAAI,CAAC;oBACX,SAAS,EAAE,EAAE,CAAC,KAAK;oBACnB,UAAU;oBACV,QAAQ;oBACR,SAAS,EAAE,EAAE,CAAC,SAAS;iBACxB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,cAAc,CAAC,IAAkC;QACtD,MAAM,MAAM,GAAU,EAAE,CAAC;QAEzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YACxC,MAAM,CAAC,IAAI,CAAC;gBACV,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;gBACV,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;gBACd,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;gBACd,4BAA4B;aAC7B,CAAC,CAAC;QACL,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;;;;;OAOG;IACH,MAAM,CAAC,sBAAsB,CAC3B,IAAkC,EAClC,iBAAyB,GAAG;QAE5B,MAAM,MAAM,GAAU,EAAE,CAAC;QAEzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YACxC,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC1B,IAAI,KAAK,IAAI,cAAc,EAAE,CAAC;gBAC5B,MAAM,CAAC,IAAI,CAAC;oBACV,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;oBACV,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;oBACd,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;iBACf,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;;AA/LD,iCAAiC;AACT,8BAAe,GAAuC;IAC5E,UAAU,EAAE,CAAC;IACb,aAAa,EAAE,EAAE;IACjB,oBAAoB,EAAE,GAAG;IACzB,UAAU,EAAE,KAAK;CAClB,CAAC"}
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @xivdyetools/core - Preset Service
|
|
3
|
+
*
|
|
4
|
+
* Manages preset color palettes for FFXIV glamours.
|
|
5
|
+
* Provides themed color combinations for jobs, seasons, events, and aesthetics.
|
|
6
|
+
*
|
|
7
|
+
* @module services/PresetService
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { PresetService, presetData, DyeService, dyeDatabase } from '@xivdyetools/core';
|
|
11
|
+
*
|
|
12
|
+
* const presetService = new PresetService(presetData);
|
|
13
|
+
* const dyeService = new DyeService(dyeDatabase);
|
|
14
|
+
*
|
|
15
|
+
* // Get all job presets
|
|
16
|
+
* const jobPresets = presetService.getPresetsByCategory('jobs');
|
|
17
|
+
*
|
|
18
|
+
* // Get a preset with resolved dye objects
|
|
19
|
+
* const rdmPreset = presetService.getPresetWithDyes('job-rdm', dyeService);
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
import type { PresetData, PresetPalette, PresetCategory, CategoryMeta, ResolvedPreset, Dye } from '../types/index.js';
|
|
23
|
+
/**
|
|
24
|
+
* Interface for DyeService to resolve dye IDs to Dye objects
|
|
25
|
+
* Using interface to avoid circular dependency
|
|
26
|
+
*/
|
|
27
|
+
interface IDyeService {
|
|
28
|
+
getDyeById(id: number): Dye | null;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Service for managing preset color palettes
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```typescript
|
|
35
|
+
* const presetService = new PresetService(presetData);
|
|
36
|
+
*
|
|
37
|
+
* // List categories
|
|
38
|
+
* const categories = presetService.getCategories();
|
|
39
|
+
*
|
|
40
|
+
* // Get presets by category
|
|
41
|
+
* const jobPresets = presetService.getPresetsByCategory('jobs');
|
|
42
|
+
*
|
|
43
|
+
* // Search presets
|
|
44
|
+
* const results = presetService.searchPresets('red');
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export declare class PresetService {
|
|
48
|
+
private data;
|
|
49
|
+
private presetById;
|
|
50
|
+
/**
|
|
51
|
+
* Initialize the preset service with preset data
|
|
52
|
+
* @param presetData - Preset data object (import from presets.json)
|
|
53
|
+
*/
|
|
54
|
+
constructor(presetData: PresetData);
|
|
55
|
+
/**
|
|
56
|
+
* Get all preset categories with metadata
|
|
57
|
+
* @returns Array of category metadata with IDs
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```typescript
|
|
61
|
+
* const categories = presetService.getCategories();
|
|
62
|
+
* // [{ id: 'jobs', name: 'FFXIV Jobs', description: '...', icon: '⚔️' }, ...]
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
getCategories(): (CategoryMeta & {
|
|
66
|
+
id: string;
|
|
67
|
+
})[];
|
|
68
|
+
/**
|
|
69
|
+
* Get metadata for a specific category
|
|
70
|
+
* @param category - Category identifier
|
|
71
|
+
* @returns Category metadata or undefined if not found
|
|
72
|
+
*/
|
|
73
|
+
getCategoryMeta(category: PresetCategory): CategoryMeta | undefined;
|
|
74
|
+
/**
|
|
75
|
+
* Get all presets
|
|
76
|
+
* @returns Array of all preset palettes
|
|
77
|
+
*/
|
|
78
|
+
getAllPresets(): PresetPalette[];
|
|
79
|
+
/**
|
|
80
|
+
* Get all presets in a specific category
|
|
81
|
+
* @param category - Category to filter by
|
|
82
|
+
* @returns Array of presets in that category
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```typescript
|
|
86
|
+
* const jobPresets = presetService.getPresetsByCategory('jobs');
|
|
87
|
+
* // Returns all job-themed presets (RDM, BLM, WHM, etc.)
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
getPresetsByCategory(category: PresetCategory): PresetPalette[];
|
|
91
|
+
/**
|
|
92
|
+
* Get a specific preset by ID
|
|
93
|
+
* @param id - Preset identifier (e.g., "job-rdm")
|
|
94
|
+
* @returns Preset or undefined if not found
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* const rdm = presetService.getPreset('job-rdm');
|
|
99
|
+
* if (rdm) {
|
|
100
|
+
* console.log(rdm.name); // "Red Mage"
|
|
101
|
+
* console.log(rdm.dyes); // [5738, 13115, 13117, 5729]
|
|
102
|
+
* }
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
getPreset(id: string): PresetPalette | undefined;
|
|
106
|
+
/**
|
|
107
|
+
* Get preset count by category
|
|
108
|
+
* @returns Map of category to preset count
|
|
109
|
+
*/
|
|
110
|
+
getPresetCountByCategory(): Map<PresetCategory, number>;
|
|
111
|
+
/**
|
|
112
|
+
* Search presets by name or tags
|
|
113
|
+
* @param query - Search query (case-insensitive)
|
|
114
|
+
* @returns Array of matching presets
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```typescript
|
|
118
|
+
* // Search by name
|
|
119
|
+
* const results = presetService.searchPresets('red');
|
|
120
|
+
* // Returns: Red Mage, Blood Red themed presets, etc.
|
|
121
|
+
*
|
|
122
|
+
* // Search by tag
|
|
123
|
+
* const tankResults = presetService.searchPresets('tank');
|
|
124
|
+
* // Returns: Paladin, Warrior, Dark Knight, Gunbreaker
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
127
|
+
searchPresets(query: string): PresetPalette[];
|
|
128
|
+
/**
|
|
129
|
+
* Search presets by tag (exact match)
|
|
130
|
+
* @param tag - Tag to search for (case-insensitive)
|
|
131
|
+
* @returns Array of presets with that tag
|
|
132
|
+
*/
|
|
133
|
+
getPresetsByTag(tag: string): PresetPalette[];
|
|
134
|
+
/**
|
|
135
|
+
* Get a random preset, optionally filtered by category
|
|
136
|
+
* @param category - Optional category to filter by
|
|
137
|
+
* @returns Random preset, or undefined if no presets exist
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* ```typescript
|
|
141
|
+
* // Random from all presets
|
|
142
|
+
* const random = presetService.getRandomPreset();
|
|
143
|
+
*
|
|
144
|
+
* // Random job preset
|
|
145
|
+
* const randomJob = presetService.getRandomPreset('jobs');
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
getRandomPreset(category?: PresetCategory): PresetPalette | undefined;
|
|
149
|
+
/**
|
|
150
|
+
* Get preset with resolved Dye objects
|
|
151
|
+
* Requires a DyeService instance to resolve dye IDs to full Dye objects
|
|
152
|
+
*
|
|
153
|
+
* @param id - Preset identifier
|
|
154
|
+
* @param dyeService - DyeService instance for resolving dye IDs
|
|
155
|
+
* @returns Resolved preset with full Dye objects, or undefined if preset not found
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* ```typescript
|
|
159
|
+
* const dyeService = new DyeService(dyeDatabase);
|
|
160
|
+
* const resolved = presetService.getPresetWithDyes('job-rdm', dyeService);
|
|
161
|
+
*
|
|
162
|
+
* if (resolved) {
|
|
163
|
+
* resolved.resolvedDyes.forEach(dye => {
|
|
164
|
+
* if (dye) {
|
|
165
|
+
* console.log(`${dye.name}: ${dye.hex}`);
|
|
166
|
+
* }
|
|
167
|
+
* });
|
|
168
|
+
* }
|
|
169
|
+
* ```
|
|
170
|
+
*/
|
|
171
|
+
getPresetWithDyes(id: string, dyeService: IDyeService): ResolvedPreset | undefined;
|
|
172
|
+
/**
|
|
173
|
+
* Resolve multiple presets with their Dye objects
|
|
174
|
+
* @param presets - Array of presets to resolve
|
|
175
|
+
* @param dyeService - DyeService instance for resolving dye IDs
|
|
176
|
+
* @returns Array of resolved presets
|
|
177
|
+
*/
|
|
178
|
+
resolvePresets(presets: PresetPalette[], dyeService: IDyeService): ResolvedPreset[];
|
|
179
|
+
/**
|
|
180
|
+
* Get data version
|
|
181
|
+
* @returns Version string from preset data
|
|
182
|
+
*/
|
|
183
|
+
getVersion(): string;
|
|
184
|
+
/**
|
|
185
|
+
* Get last update timestamp
|
|
186
|
+
* @returns ISO date string of last update
|
|
187
|
+
*/
|
|
188
|
+
getLastUpdated(): string;
|
|
189
|
+
/**
|
|
190
|
+
* Get total number of presets
|
|
191
|
+
* @returns Total preset count
|
|
192
|
+
*/
|
|
193
|
+
getPresetCount(): number;
|
|
194
|
+
}
|
|
195
|
+
export {};
|
|
196
|
+
//# sourceMappingURL=PresetService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PresetService.d.ts","sourceRoot":"","sources":["../../src/services/PresetService.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EACV,UAAU,EACV,aAAa,EACb,cAAc,EACd,YAAY,EACZ,cAAc,EACd,GAAG,EACJ,MAAM,mBAAmB,CAAC;AAE3B;;;GAGG;AACH,UAAU,WAAW;IACnB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC;CACpC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,IAAI,CAAa;IACzB,OAAO,CAAC,UAAU,CAA6B;IAE/C;;;OAGG;gBACS,UAAU,EAAE,UAAU;IAUlC;;;;;;;;;OASG;IACH,aAAa,IAAI,CAAC,YAAY,GAAG;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE;IAOlD;;;;OAIG;IACH,eAAe,CAAC,QAAQ,EAAE,cAAc,GAAG,YAAY,GAAG,SAAS;IAQnE;;;OAGG;IACH,aAAa,IAAI,aAAa,EAAE;IAIhC;;;;;;;;;;OAUG;IACH,oBAAoB,CAAC,QAAQ,EAAE,cAAc,GAAG,aAAa,EAAE;IAI/D;;;;;;;;;;;;;OAaG;IACH,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAIhD;;;OAGG;IACH,wBAAwB,IAAI,GAAG,CAAC,cAAc,EAAE,MAAM,CAAC;IAYvD;;;;;;;;;;;;;;;OAeG;IACH,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,EAAE;IAc7C;;;;OAIG;IACH,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,EAAE;IAS7C;;;;;;;;;;;;;OAaG;IACH,eAAe,CAAC,QAAQ,CAAC,EAAE,cAAc,GAAG,aAAa,GAAG,SAAS;IAcrE;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,GAAG,cAAc,GAAG,SAAS;IAYlF;;;;;OAKG;IACH,cAAc,CAAC,OAAO,EAAE,aAAa,EAAE,EAAE,UAAU,EAAE,WAAW,GAAG,cAAc,EAAE;IAWnF;;;OAGG;IACH,UAAU,IAAI,MAAM;IAIpB;;;OAGG;IACH,cAAc,IAAI,MAAM;IAIxB;;;OAGG;IACH,cAAc,IAAI,MAAM;CAGzB"}
|