@xivdyetools/core 4.3.0 → 5.1.0
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/README.md +1 -1
- package/dist/blending/blending.d.ts +26 -6
- package/dist/blending/blending.d.ts.map +1 -1
- package/dist/blending/blending.js +79 -32
- package/dist/blending/blending.js.map +1 -1
- package/dist/blending/conversions.d.ts +0 -12
- package/dist/blending/conversions.d.ts.map +1 -1
- package/dist/blending/conversions.js +25 -28
- package/dist/blending/conversions.js.map +1 -1
- package/dist/blending/index.d.ts +4 -1
- package/dist/blending/index.d.ts.map +1 -1
- package/dist/blending/index.js.map +1 -1
- package/dist/blending/types.d.ts +38 -0
- package/dist/blending/types.d.ts.map +1 -1
- package/dist/config/band-vocabulary.d.ts +9 -0
- package/dist/config/band-vocabulary.d.ts.map +1 -1
- package/dist/config/band-vocabulary.js +12 -3
- package/dist/config/band-vocabulary.js.map +1 -1
- package/dist/services/ColorService.d.ts +37 -15
- package/dist/services/ColorService.d.ts.map +1 -1
- package/dist/services/ColorService.js +70 -69
- package/dist/services/ColorService.js.map +1 -1
- package/dist/services/color/ColorConverter.d.ts +28 -35
- package/dist/services/color/ColorConverter.d.ts.map +1 -1
- package/dist/services/color/ColorConverter.js +70 -63
- package/dist/services/color/ColorConverter.js.map +1 -1
- package/dist/services/dye/HarmonyGenerator.d.ts +2 -2
- package/dist/services/dye/HarmonyGenerator.d.ts.map +1 -1
- package/dist/services/dye/HarmonyGenerator.js +28 -4
- package/dist/services/dye/HarmonyGenerator.js.map +1 -1
- package/dist/types/index.d.ts +3 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +2 -2
- package/dist/types/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/services/color/RybColorMixer.d.ts +0 -102
- package/dist/services/color/RybColorMixer.d.ts.map +0 -1
- package/dist/services/color/RybColorMixer.js +0 -362
- package/dist/services/color/RybColorMixer.js.map +0 -1
- package/dist/services/color/SpectralMixer.d.ts +0 -43
- package/dist/services/color/SpectralMixer.d.ts.map +0 -1
- package/dist/services/color/SpectralMixer.js +0 -59
- package/dist/services/color/SpectralMixer.js.map +0 -1
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* RYB (Red-Yellow-Blue) Subtractive Color Mixing
|
|
3
|
-
*
|
|
4
|
-
* Implements the Gossett-Chen algorithm from their 2006 paper
|
|
5
|
-
* "Paint Inspired Color Mixing and Compositing for Visualization"
|
|
6
|
-
*
|
|
7
|
-
* Uses trilinear interpolation in a 3D color cube to convert between
|
|
8
|
-
* RYB and RGB color spaces, enabling intuitive "paint-like" color mixing.
|
|
9
|
-
*
|
|
10
|
-
* Key insight: In RYB (subtractive mixing):
|
|
11
|
-
* - Red + Yellow = Orange
|
|
12
|
-
* - Yellow + Blue = Green
|
|
13
|
-
* - Red + Blue = Violet
|
|
14
|
-
*
|
|
15
|
-
* This differs from RGB (additive mixing) where Blue + Yellow = Gray.
|
|
16
|
-
*
|
|
17
|
-
* @module services/color/RybColorMixer
|
|
18
|
-
*/
|
|
19
|
-
import type { RGB, HexColor } from '@xivdyetools/types';
|
|
20
|
-
/**
|
|
21
|
-
* RYB color type (Red, Yellow, Blue) with values 0-255
|
|
22
|
-
*/
|
|
23
|
-
export interface RYB {
|
|
24
|
-
r: number;
|
|
25
|
-
y: number;
|
|
26
|
-
b: number;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* RYB Color Mixer
|
|
30
|
-
*
|
|
31
|
-
* Provides methods for RYB ↔ RGB conversion and paint-like color mixing.
|
|
32
|
-
*/
|
|
33
|
-
export declare class RybColorMixer {
|
|
34
|
-
/**
|
|
35
|
-
* Mix two colors using RYB subtractive color mixing
|
|
36
|
-
*
|
|
37
|
-
* This produces results similar to mixing physical paints:
|
|
38
|
-
* - Blue + Yellow = Green (not gray like in RGB)
|
|
39
|
-
* - Red + Yellow = Orange
|
|
40
|
-
* - Red + Blue = Violet
|
|
41
|
-
*
|
|
42
|
-
* @param hex1 First hex color
|
|
43
|
-
* @param hex2 Second hex color
|
|
44
|
-
* @param ratio Mix ratio (0 = all hex1, 0.5 = equal mix, 1 = all hex2). Default: 0.5
|
|
45
|
-
* @returns Mixed color as hex
|
|
46
|
-
*
|
|
47
|
-
* @example
|
|
48
|
-
* // Mix blue and yellow to get green
|
|
49
|
-
* RybColorMixer.mixColors('#0000FF', '#FFFF00') // Returns greenish color
|
|
50
|
-
*/
|
|
51
|
-
static mixColors(hex1: string, hex2: string, ratio?: number): HexColor;
|
|
52
|
-
/**
|
|
53
|
-
* Convert RYB to RGB using trilinear interpolation
|
|
54
|
-
*
|
|
55
|
-
* Uses the Gossett-Chen cube corner values to interpolate
|
|
56
|
-
* any point within the RYB color space to its RGB equivalent.
|
|
57
|
-
*
|
|
58
|
-
* @param r Red component (0-255)
|
|
59
|
-
* @param y Yellow component (0-255)
|
|
60
|
-
* @param b Blue component (0-255)
|
|
61
|
-
* @returns RGB color
|
|
62
|
-
*
|
|
63
|
-
* @example
|
|
64
|
-
* // Convert RYB yellow+blue (green) to RGB
|
|
65
|
-
* RybColorMixer.rybToRgb(0, 255, 255) // Returns { r: 0, g: 255, b: 89 }
|
|
66
|
-
*/
|
|
67
|
-
static rybToRgb(r: number, y: number, b: number): RGB;
|
|
68
|
-
/**
|
|
69
|
-
* Convert RGB to RYB using Multi-Start Newton-Raphson
|
|
70
|
-
*
|
|
71
|
-
* Since RYB→RGB is non-linear and the cube can be complex,
|
|
72
|
-
* we use multiple starting points to find the best global solution
|
|
73
|
-
* (minimizing RGB error).
|
|
74
|
-
*
|
|
75
|
-
* @param r Red component (0-255)
|
|
76
|
-
* @param g Green component (0-255)
|
|
77
|
-
* @param b Blue component (0-255)
|
|
78
|
-
* @returns RYB color
|
|
79
|
-
*
|
|
80
|
-
* @example
|
|
81
|
-
* // Convert RGB green to RYB
|
|
82
|
-
* RybColorMixer.rgbToRyb(0, 255, 0) // Returns approximately { r: 0, y: ~255, b: ~255 }
|
|
83
|
-
*/
|
|
84
|
-
static rgbToRyb(r: number, g: number, b: number): RYB;
|
|
85
|
-
/**
|
|
86
|
-
* Convert hex color to RYB
|
|
87
|
-
*
|
|
88
|
-
* @param hex Hex color string
|
|
89
|
-
* @returns RYB color
|
|
90
|
-
*/
|
|
91
|
-
static hexToRyb(hex: string): RYB;
|
|
92
|
-
/**
|
|
93
|
-
* Convert RYB to hex color
|
|
94
|
-
*
|
|
95
|
-
* @param r Red component (0-255)
|
|
96
|
-
* @param y Yellow component (0-255)
|
|
97
|
-
* @param b Blue component (0-255)
|
|
98
|
-
* @returns Hex color string
|
|
99
|
-
*/
|
|
100
|
-
static rybToHex(r: number, y: number, b: number): HexColor;
|
|
101
|
-
}
|
|
102
|
-
//# sourceMappingURL=RybColorMixer.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"RybColorMixer.d.ts","sourceRoot":"","sources":["../../../src/services/color/RybColorMixer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAIxD;;GAEG;AACH,MAAM,WAAW,GAAG;IAClB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AA4CD;;;;GAIG;AACH,qBAAa,aAAa;IAKxB;;;;;;;;;;;;;;;;OAgBG;IACH,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,MAAY,GAAG,QAAQ;IAsB3E;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,GAAG;IAerD;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,GAAG;IAqLrD;;;;;OAKG;IACH,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG;IAKjC;;;;;;;OAOG;IACH,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,QAAQ;CA8D3D"}
|
|
@@ -1,362 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* RYB (Red-Yellow-Blue) Subtractive Color Mixing
|
|
3
|
-
*
|
|
4
|
-
* Implements the Gossett-Chen algorithm from their 2006 paper
|
|
5
|
-
* "Paint Inspired Color Mixing and Compositing for Visualization"
|
|
6
|
-
*
|
|
7
|
-
* Uses trilinear interpolation in a 3D color cube to convert between
|
|
8
|
-
* RYB and RGB color spaces, enabling intuitive "paint-like" color mixing.
|
|
9
|
-
*
|
|
10
|
-
* Key insight: In RYB (subtractive mixing):
|
|
11
|
-
* - Red + Yellow = Orange
|
|
12
|
-
* - Yellow + Blue = Green
|
|
13
|
-
* - Red + Blue = Violet
|
|
14
|
-
*
|
|
15
|
-
* This differs from RGB (additive mixing) where Blue + Yellow = Gray.
|
|
16
|
-
*
|
|
17
|
-
* @module services/color/RybColorMixer
|
|
18
|
-
*/
|
|
19
|
-
import { clamp } from '../../utils/index.js';
|
|
20
|
-
import { ColorConverter } from './ColorConverter.js';
|
|
21
|
-
/**
|
|
22
|
-
* RYB Cube Corner Values (Gossett-Chen)
|
|
23
|
-
*
|
|
24
|
-
* These define the 8 corners of the RYB color cube and their
|
|
25
|
-
* corresponding RGB values. The cube is indexed by [R,Y,B] coordinates.
|
|
26
|
-
*
|
|
27
|
-
* The blue corner is adjusted (r=0.165) to shift the hue and prevent
|
|
28
|
-
* "flat spots" in the spectrum. Similarly, green and violet primaries
|
|
29
|
-
* are tuned for more intuitive color mixing.
|
|
30
|
-
*/
|
|
31
|
-
/**
|
|
32
|
-
* RYB Cube Corner Values (Gossett-Chen - Subtractive/Paint Model)
|
|
33
|
-
*
|
|
34
|
-
* 0,0,0 is White (Canvas)
|
|
35
|
-
* 1,1,1 is Black (Sludge)
|
|
36
|
-
*
|
|
37
|
-
* This model correctly simulates paint mixing where adding pigments subtracts light.
|
|
38
|
-
* The corners are tuned to produce expected secondary colors:
|
|
39
|
-
* - Red + Yellow = Orange
|
|
40
|
-
* - Yellow + Blue = Green
|
|
41
|
-
* - Red + Blue = Violet
|
|
42
|
-
*/
|
|
43
|
-
const RYB_CORNERS = {
|
|
44
|
-
'0,0,0': { r: 1.0, g: 1.0, b: 1.0 }, // White
|
|
45
|
-
'1,0,0': { r: 1.0, g: 0.0, b: 0.0 }, // Red
|
|
46
|
-
'0,1,0': { r: 1.0, g: 1.0, b: 0.0 }, // Yellow
|
|
47
|
-
'0,0,1': { r: 0.163, g: 0.373, b: 0.6 }, // Blue
|
|
48
|
-
'1,1,0': { r: 1.0, g: 0.5, b: 0.0 }, // Orange
|
|
49
|
-
'1,0,1': { r: 0.5, g: 0.0, b: 0.5 }, // Violet
|
|
50
|
-
'0,1,1': { r: 0.0, g: 0.66, b: 0.2 }, // Green
|
|
51
|
-
'1,1,1': { r: 0.2, g: 0.09, b: 0.0 }, // Black
|
|
52
|
-
};
|
|
53
|
-
/**
|
|
54
|
-
* RYB Color Mixer
|
|
55
|
-
*
|
|
56
|
-
* Provides methods for RYB ↔ RGB conversion and paint-like color mixing.
|
|
57
|
-
*/
|
|
58
|
-
export class RybColorMixer {
|
|
59
|
-
// ============================================================================
|
|
60
|
-
// Public API
|
|
61
|
-
// ============================================================================
|
|
62
|
-
/**
|
|
63
|
-
* Mix two colors using RYB subtractive color mixing
|
|
64
|
-
*
|
|
65
|
-
* This produces results similar to mixing physical paints:
|
|
66
|
-
* - Blue + Yellow = Green (not gray like in RGB)
|
|
67
|
-
* - Red + Yellow = Orange
|
|
68
|
-
* - Red + Blue = Violet
|
|
69
|
-
*
|
|
70
|
-
* @param hex1 First hex color
|
|
71
|
-
* @param hex2 Second hex color
|
|
72
|
-
* @param ratio Mix ratio (0 = all hex1, 0.5 = equal mix, 1 = all hex2). Default: 0.5
|
|
73
|
-
* @returns Mixed color as hex
|
|
74
|
-
*
|
|
75
|
-
* @example
|
|
76
|
-
* // Mix blue and yellow to get green
|
|
77
|
-
* RybColorMixer.mixColors('#0000FF', '#FFFF00') // Returns greenish color
|
|
78
|
-
*/
|
|
79
|
-
static mixColors(hex1, hex2, ratio = 0.5) {
|
|
80
|
-
ratio = clamp(ratio, 0, 1);
|
|
81
|
-
// Convert hex → RGB → RYB
|
|
82
|
-
const rgb1 = ColorConverter.hexToRgb(hex1);
|
|
83
|
-
const rgb2 = ColorConverter.hexToRgb(hex2);
|
|
84
|
-
const ryb1 = this.rgbToRyb(rgb1.r, rgb1.g, rgb1.b);
|
|
85
|
-
const ryb2 = this.rgbToRyb(rgb2.r, rgb2.g, rgb2.b);
|
|
86
|
-
// Linear interpolation in RYB space
|
|
87
|
-
const mixedRyb = {
|
|
88
|
-
r: ryb1.r + (ryb2.r - ryb1.r) * ratio,
|
|
89
|
-
y: ryb1.y + (ryb2.y - ryb1.y) * ratio,
|
|
90
|
-
b: ryb1.b + (ryb2.b - ryb1.b) * ratio,
|
|
91
|
-
};
|
|
92
|
-
// Convert RYB → RGB → hex
|
|
93
|
-
const mixedRgb = this.rybToRgb(mixedRyb.r, mixedRyb.y, mixedRyb.b);
|
|
94
|
-
return ColorConverter.rgbToHex(mixedRgb.r, mixedRgb.g, mixedRgb.b);
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Convert RYB to RGB using trilinear interpolation
|
|
98
|
-
*
|
|
99
|
-
* Uses the Gossett-Chen cube corner values to interpolate
|
|
100
|
-
* any point within the RYB color space to its RGB equivalent.
|
|
101
|
-
*
|
|
102
|
-
* @param r Red component (0-255)
|
|
103
|
-
* @param y Yellow component (0-255)
|
|
104
|
-
* @param b Blue component (0-255)
|
|
105
|
-
* @returns RGB color
|
|
106
|
-
*
|
|
107
|
-
* @example
|
|
108
|
-
* // Convert RYB yellow+blue (green) to RGB
|
|
109
|
-
* RybColorMixer.rybToRgb(0, 255, 255) // Returns { r: 0, g: 255, b: 89 }
|
|
110
|
-
*/
|
|
111
|
-
static rybToRgb(r, y, b) {
|
|
112
|
-
// Normalize to 0-1 range
|
|
113
|
-
const rNorm = clamp(r / 255, 0, 1);
|
|
114
|
-
const yNorm = clamp(y / 255, 0, 1);
|
|
115
|
-
const bNorm = clamp(b / 255, 0, 1);
|
|
116
|
-
const result = this.trilinearInterpolate(rNorm, yNorm, bNorm);
|
|
117
|
-
return {
|
|
118
|
-
r: Math.round(clamp(result.r * 255, 0, 255)),
|
|
119
|
-
g: Math.round(clamp(result.g * 255, 0, 255)),
|
|
120
|
-
b: Math.round(clamp(result.b * 255, 0, 255)),
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
/**
|
|
124
|
-
* Convert RGB to RYB using Multi-Start Newton-Raphson
|
|
125
|
-
*
|
|
126
|
-
* Since RYB→RGB is non-linear and the cube can be complex,
|
|
127
|
-
* we use multiple starting points to find the best global solution
|
|
128
|
-
* (minimizing RGB error).
|
|
129
|
-
*
|
|
130
|
-
* @param r Red component (0-255)
|
|
131
|
-
* @param g Green component (0-255)
|
|
132
|
-
* @param b Blue component (0-255)
|
|
133
|
-
* @returns RYB color
|
|
134
|
-
*
|
|
135
|
-
* @example
|
|
136
|
-
* // Convert RGB green to RYB
|
|
137
|
-
* RybColorMixer.rgbToRyb(0, 255, 0) // Returns approximately { r: 0, y: ~255, b: ~255 }
|
|
138
|
-
*/
|
|
139
|
-
static rgbToRyb(r, g, b) {
|
|
140
|
-
// Normalize target RGB to 0-1
|
|
141
|
-
const targetR = clamp(r / 255, 0, 1);
|
|
142
|
-
const targetG = clamp(g / 255, 0, 1);
|
|
143
|
-
const targetB = clamp(b / 255, 0, 1);
|
|
144
|
-
// Multi-start candidates to avoid local minima
|
|
145
|
-
const candidates = [
|
|
146
|
-
{ r: 0.5, y: 0.5, b: 0.5 }, // Center
|
|
147
|
-
{ r: 0, y: 0, b: 0 }, // White (Subtractive 000)
|
|
148
|
-
{ r: 1, y: 1, b: 1 }, // Black (Subtractive 111)
|
|
149
|
-
{ r: 1, y: 0, b: 0 }, // Red
|
|
150
|
-
{ r: 0, y: 1, b: 0 }, // Yellow
|
|
151
|
-
{ r: 0, y: 0, b: 1 }, // Blue
|
|
152
|
-
{ r: 0, y: 1, b: 1 }, // Green
|
|
153
|
-
{ r: 1, y: 1, b: 0 }, // Orange
|
|
154
|
-
{ r: 1, y: 0, b: 1 }, // Purple
|
|
155
|
-
];
|
|
156
|
-
let bestRyb = { r: 0, y: 0, b: 0 };
|
|
157
|
-
let minError = Infinity;
|
|
158
|
-
const maxIterations = 20;
|
|
159
|
-
const tolerance = 0.001;
|
|
160
|
-
const epsilon = 0.001; // For numerical Jacobian
|
|
161
|
-
for (const start of candidates) {
|
|
162
|
-
let rybR = start.r;
|
|
163
|
-
let rybY = start.y;
|
|
164
|
-
let rybB = start.b;
|
|
165
|
-
for (let i = 0; i < maxIterations; i++) {
|
|
166
|
-
// Convert current RYB guess to RGB
|
|
167
|
-
const currentRgb = this.trilinearInterpolate(rybR, rybY, rybB);
|
|
168
|
-
// Calculate error
|
|
169
|
-
const errorR = targetR - currentRgb.r;
|
|
170
|
-
const errorG = targetG - currentRgb.g;
|
|
171
|
-
const errorB = targetB - currentRgb.b;
|
|
172
|
-
const currentError = Math.sqrt(errorR * errorR + errorG * errorG + errorB * errorB);
|
|
173
|
-
// Track best solution found so far
|
|
174
|
-
if (currentError < minError) {
|
|
175
|
-
minError = currentError;
|
|
176
|
-
bestRyb = { r: rybR, y: rybY, b: rybB };
|
|
177
|
-
}
|
|
178
|
-
if (currentError < tolerance) {
|
|
179
|
-
// Good enough match
|
|
180
|
-
return {
|
|
181
|
-
r: Math.round(rybR * 255),
|
|
182
|
-
y: Math.round(rybY * 255),
|
|
183
|
-
b: Math.round(rybB * 255),
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
// Compute numerical Jacobian and update
|
|
187
|
-
const J = this.computeJacobian(rybR, rybY, rybB, epsilon);
|
|
188
|
-
const delta = this.solveLinearSystem(J, errorR, errorG, errorB);
|
|
189
|
-
// Apply damped update
|
|
190
|
-
const damping = 0.5;
|
|
191
|
-
rybR = clamp(rybR + delta[0] * damping, 0, 1);
|
|
192
|
-
rybY = clamp(rybY + delta[1] * damping, 0, 1);
|
|
193
|
-
rybB = clamp(rybB + delta[2] * damping, 0, 1);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
return {
|
|
197
|
-
r: Math.round(bestRyb.r * 255),
|
|
198
|
-
y: Math.round(bestRyb.y * 255),
|
|
199
|
-
b: Math.round(bestRyb.b * 255),
|
|
200
|
-
};
|
|
201
|
-
}
|
|
202
|
-
/**
|
|
203
|
-
* Compute the 3×3 Jacobian matrix numerically using finite differences
|
|
204
|
-
*
|
|
205
|
-
* J[i][j] = ∂RGB[i]/∂RYB[j]
|
|
206
|
-
*
|
|
207
|
-
* @param r Current RYB red (0-1)
|
|
208
|
-
* @param y Current RYB yellow (0-1)
|
|
209
|
-
* @param b Current RYB blue (0-1)
|
|
210
|
-
* @param epsilon Step size for finite differences
|
|
211
|
-
* @returns 3×3 Jacobian matrix as [row][col]
|
|
212
|
-
* @internal
|
|
213
|
-
*/
|
|
214
|
-
static computeJacobian(r, y, b, epsilon) {
|
|
215
|
-
const J = [
|
|
216
|
-
[0, 0, 0],
|
|
217
|
-
[0, 0, 0],
|
|
218
|
-
[0, 0, 0],
|
|
219
|
-
];
|
|
220
|
-
// Perturb RYB Red
|
|
221
|
-
const rPlus = this.trilinearInterpolate(Math.min(r + epsilon, 1), y, b);
|
|
222
|
-
const rMinus = this.trilinearInterpolate(Math.max(r - epsilon, 0), y, b);
|
|
223
|
-
const rDenom = Math.min(r + epsilon, 1) - Math.max(r - epsilon, 0);
|
|
224
|
-
if (rDenom > 0) {
|
|
225
|
-
J[0][0] = (rPlus.r - rMinus.r) / rDenom;
|
|
226
|
-
J[1][0] = (rPlus.g - rMinus.g) / rDenom;
|
|
227
|
-
J[2][0] = (rPlus.b - rMinus.b) / rDenom;
|
|
228
|
-
}
|
|
229
|
-
// Perturb RYB Yellow
|
|
230
|
-
const yPlus = this.trilinearInterpolate(r, Math.min(y + epsilon, 1), b);
|
|
231
|
-
const yMinus = this.trilinearInterpolate(r, Math.max(y - epsilon, 0), b);
|
|
232
|
-
const yDenom = Math.min(y + epsilon, 1) - Math.max(y - epsilon, 0);
|
|
233
|
-
if (yDenom > 0) {
|
|
234
|
-
J[0][1] = (yPlus.r - yMinus.r) / yDenom;
|
|
235
|
-
J[1][1] = (yPlus.g - yMinus.g) / yDenom;
|
|
236
|
-
J[2][1] = (yPlus.b - yMinus.b) / yDenom;
|
|
237
|
-
}
|
|
238
|
-
// Perturb RYB Blue
|
|
239
|
-
const bPlus = this.trilinearInterpolate(r, y, Math.min(b + epsilon, 1));
|
|
240
|
-
const bMinus = this.trilinearInterpolate(r, y, Math.max(b - epsilon, 0));
|
|
241
|
-
const bDenom = Math.min(b + epsilon, 1) - Math.max(b - epsilon, 0);
|
|
242
|
-
if (bDenom > 0) {
|
|
243
|
-
J[0][2] = (bPlus.r - bMinus.r) / bDenom;
|
|
244
|
-
J[1][2] = (bPlus.g - bMinus.g) / bDenom;
|
|
245
|
-
J[2][2] = (bPlus.b - bMinus.b) / bDenom;
|
|
246
|
-
}
|
|
247
|
-
return J;
|
|
248
|
-
}
|
|
249
|
-
/**
|
|
250
|
-
* Solve a 3×3 linear system Ax = b using Cramer's rule
|
|
251
|
-
*
|
|
252
|
-
* @param A 3×3 matrix
|
|
253
|
-
* @param b1 First component of b vector
|
|
254
|
-
* @param b2 Second component of b vector
|
|
255
|
-
* @param b3 Third component of b vector
|
|
256
|
-
* @returns Solution vector [x1, x2, x3]
|
|
257
|
-
* @internal
|
|
258
|
-
*/
|
|
259
|
-
static solveLinearSystem(A, b1, b2, b3) {
|
|
260
|
-
// Calculate determinant of A
|
|
261
|
-
const detA = A[0][0] * (A[1][1] * A[2][2] - A[1][2] * A[2][1]) -
|
|
262
|
-
A[0][1] * (A[1][0] * A[2][2] - A[1][2] * A[2][0]) +
|
|
263
|
-
A[0][2] * (A[1][0] * A[2][1] - A[1][1] * A[2][0]);
|
|
264
|
-
// If matrix is singular, fall back to simple diagonal approximation
|
|
265
|
-
if (Math.abs(detA) < 1e-10) {
|
|
266
|
-
// Use diagonal elements as fallback
|
|
267
|
-
const x1 = A[0][0] !== 0 ? b1 / A[0][0] : 0;
|
|
268
|
-
const x2 = A[1][1] !== 0 ? b2 / A[1][1] : 0;
|
|
269
|
-
const x3 = A[2][2] !== 0 ? b3 / A[2][2] : 0;
|
|
270
|
-
return [x1, x2, x3];
|
|
271
|
-
}
|
|
272
|
-
// Cramer's rule: replace column i with b, compute det, divide by detA
|
|
273
|
-
// x1 = det(A with col 0 replaced by b) / detA
|
|
274
|
-
const detA1 = b1 * (A[1][1] * A[2][2] - A[1][2] * A[2][1]) -
|
|
275
|
-
A[0][1] * (b2 * A[2][2] - A[1][2] * b3) +
|
|
276
|
-
A[0][2] * (b2 * A[2][1] - A[1][1] * b3);
|
|
277
|
-
// x2 = det(A with col 1 replaced by b) / detA
|
|
278
|
-
const detA2 = A[0][0] * (b2 * A[2][2] - A[1][2] * b3) -
|
|
279
|
-
b1 * (A[1][0] * A[2][2] - A[1][2] * A[2][0]) +
|
|
280
|
-
A[0][2] * (A[1][0] * b3 - b2 * A[2][0]);
|
|
281
|
-
// x3 = det(A with col 2 replaced by b) / detA
|
|
282
|
-
const detA3 = A[0][0] * (A[1][1] * b3 - b2 * A[2][1]) -
|
|
283
|
-
A[0][1] * (A[1][0] * b3 - b2 * A[2][0]) +
|
|
284
|
-
b1 * (A[1][0] * A[2][1] - A[1][1] * A[2][0]);
|
|
285
|
-
return [detA1 / detA, detA2 / detA, detA3 / detA];
|
|
286
|
-
}
|
|
287
|
-
/**
|
|
288
|
-
* Convert hex color to RYB
|
|
289
|
-
*
|
|
290
|
-
* @param hex Hex color string
|
|
291
|
-
* @returns RYB color
|
|
292
|
-
*/
|
|
293
|
-
static hexToRyb(hex) {
|
|
294
|
-
const rgb = ColorConverter.hexToRgb(hex);
|
|
295
|
-
return this.rgbToRyb(rgb.r, rgb.g, rgb.b);
|
|
296
|
-
}
|
|
297
|
-
/**
|
|
298
|
-
* Convert RYB to hex color
|
|
299
|
-
*
|
|
300
|
-
* @param r Red component (0-255)
|
|
301
|
-
* @param y Yellow component (0-255)
|
|
302
|
-
* @param b Blue component (0-255)
|
|
303
|
-
* @returns Hex color string
|
|
304
|
-
*/
|
|
305
|
-
static rybToHex(r, y, b) {
|
|
306
|
-
const rgb = this.rybToRgb(r, y, b);
|
|
307
|
-
return ColorConverter.rgbToHex(rgb.r, rgb.g, rgb.b);
|
|
308
|
-
}
|
|
309
|
-
// ============================================================================
|
|
310
|
-
// Private Helpers
|
|
311
|
-
// ============================================================================
|
|
312
|
-
/**
|
|
313
|
-
* Trilinear interpolation within the RYB color cube
|
|
314
|
-
*
|
|
315
|
-
* Given normalized RYB coordinates (0-1), interpolates between
|
|
316
|
-
* the 8 corner RGB values to produce the output RGB color.
|
|
317
|
-
*
|
|
318
|
-
* @param r Normalized red (0-1)
|
|
319
|
-
* @param y Normalized yellow (0-1)
|
|
320
|
-
* @param b Normalized blue (0-1)
|
|
321
|
-
* @returns Normalized RGB (0-1)
|
|
322
|
-
* @internal
|
|
323
|
-
*/
|
|
324
|
-
static trilinearInterpolate(r, y, b) {
|
|
325
|
-
// Get the 8 corner values
|
|
326
|
-
const c000 = RYB_CORNERS['0,0,0'];
|
|
327
|
-
const c100 = RYB_CORNERS['1,0,0'];
|
|
328
|
-
const c010 = RYB_CORNERS['0,1,0'];
|
|
329
|
-
const c110 = RYB_CORNERS['1,1,0'];
|
|
330
|
-
const c001 = RYB_CORNERS['0,0,1'];
|
|
331
|
-
const c101 = RYB_CORNERS['1,0,1'];
|
|
332
|
-
const c011 = RYB_CORNERS['0,1,1'];
|
|
333
|
-
const c111 = RYB_CORNERS['1,1,1'];
|
|
334
|
-
// Interpolate along R axis (between r=0 and r=1 planes)
|
|
335
|
-
const c00 = this.lerpRgb(c000, c100, r);
|
|
336
|
-
const c01 = this.lerpRgb(c001, c101, r);
|
|
337
|
-
const c10 = this.lerpRgb(c010, c110, r);
|
|
338
|
-
const c11 = this.lerpRgb(c011, c111, r);
|
|
339
|
-
// Interpolate along Y axis
|
|
340
|
-
const c0 = this.lerpRgb(c00, c10, y);
|
|
341
|
-
const c1 = this.lerpRgb(c01, c11, y);
|
|
342
|
-
// Interpolate along B axis (final result)
|
|
343
|
-
return this.lerpRgb(c0, c1, b);
|
|
344
|
-
}
|
|
345
|
-
/**
|
|
346
|
-
* Linear interpolation between two RGB colors
|
|
347
|
-
*
|
|
348
|
-
* @param a First color
|
|
349
|
-
* @param b Second color
|
|
350
|
-
* @param t Interpolation factor (0 = a, 1 = b)
|
|
351
|
-
* @returns Interpolated color
|
|
352
|
-
* @internal
|
|
353
|
-
*/
|
|
354
|
-
static lerpRgb(a, b, t) {
|
|
355
|
-
return {
|
|
356
|
-
r: a.r + (b.r - a.r) * t,
|
|
357
|
-
g: a.g + (b.g - a.g) * t,
|
|
358
|
-
b: a.b + (b.b - a.b) * t,
|
|
359
|
-
};
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
//# sourceMappingURL=RybColorMixer.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"RybColorMixer.js","sourceRoot":"","sources":["../../../src/services/color/RybColorMixer.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Spectral Color Mixer
|
|
3
|
-
*
|
|
4
|
-
* Wrapper for spectral.js library that provides Kubelka-Munk theory-based
|
|
5
|
-
* realistic pigment/paint mixing. This produces results that closely match
|
|
6
|
-
* how actual paints and pigments mix in the physical world.
|
|
7
|
-
*
|
|
8
|
-
* Key characteristics:
|
|
9
|
-
* - Based on Kubelka-Munk light absorption/scattering theory
|
|
10
|
-
* - Simulates how pigments interact with light
|
|
11
|
-
* - Blue + Yellow = Green (like real paint!)
|
|
12
|
-
* - Uses spectral reflectance curves (380-750nm)
|
|
13
|
-
*
|
|
14
|
-
* @module services/color/SpectralMixer
|
|
15
|
-
*/
|
|
16
|
-
import type { HexColor } from '@xivdyetools/types';
|
|
17
|
-
/**
|
|
18
|
-
* Spectral Color Mixer using Kubelka-Munk theory
|
|
19
|
-
*
|
|
20
|
-
* Provides realistic paint/pigment color mixing by simulating
|
|
21
|
-
* how light interacts with pigmented materials.
|
|
22
|
-
*/
|
|
23
|
-
export declare class SpectralMixer {
|
|
24
|
-
/**
|
|
25
|
-
* Mix two colors using Kubelka-Munk spectral mixing
|
|
26
|
-
*
|
|
27
|
-
* This produces results similar to mixing physical paints:
|
|
28
|
-
* - Blue + Yellow = Green (like mixing paints)
|
|
29
|
-
* - More realistic tinting and shading
|
|
30
|
-
* - Handles complementary colors naturally
|
|
31
|
-
*
|
|
32
|
-
* @param hex1 First hex color
|
|
33
|
-
* @param hex2 Second hex color
|
|
34
|
-
* @param ratio Mix ratio (0 = all hex1, 0.5 = equal mix, 1 = all hex2). Default: 0.5
|
|
35
|
-
* @returns Mixed color as hex
|
|
36
|
-
*
|
|
37
|
-
* @example
|
|
38
|
-
* // Mix blue and yellow to get green
|
|
39
|
-
* SpectralMixer.mixColors('#0000FF', '#FFFF00') // Returns green-ish color
|
|
40
|
-
*/
|
|
41
|
-
static mixColors(hex1: string, hex2: string, ratio?: number): HexColor;
|
|
42
|
-
}
|
|
43
|
-
//# sourceMappingURL=SpectralMixer.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SpectralMixer.d.ts","sourceRoot":"","sources":["../../../src/services/color/SpectralMixer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAGnD;;;;;GAKG;AACH,qBAAa,aAAa;IACxB;;;;;;;;;;;;;;;;OAgBG;IACH,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,MAAY,GAAG,QAAQ;CAoB5E"}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Spectral Color Mixer
|
|
3
|
-
*
|
|
4
|
-
* Wrapper for spectral.js library that provides Kubelka-Munk theory-based
|
|
5
|
-
* realistic pigment/paint mixing. This produces results that closely match
|
|
6
|
-
* how actual paints and pigments mix in the physical world.
|
|
7
|
-
*
|
|
8
|
-
* Key characteristics:
|
|
9
|
-
* - Based on Kubelka-Munk light absorption/scattering theory
|
|
10
|
-
* - Simulates how pigments interact with light
|
|
11
|
-
* - Blue + Yellow = Green (like real paint!)
|
|
12
|
-
* - Uses spectral reflectance curves (380-750nm)
|
|
13
|
-
*
|
|
14
|
-
* @module services/color/SpectralMixer
|
|
15
|
-
*/
|
|
16
|
-
import * as spectral from 'spectral.js';
|
|
17
|
-
import { ColorConverter } from './ColorConverter.js';
|
|
18
|
-
/**
|
|
19
|
-
* Spectral Color Mixer using Kubelka-Munk theory
|
|
20
|
-
*
|
|
21
|
-
* Provides realistic paint/pigment color mixing by simulating
|
|
22
|
-
* how light interacts with pigmented materials.
|
|
23
|
-
*/
|
|
24
|
-
export class SpectralMixer {
|
|
25
|
-
/**
|
|
26
|
-
* Mix two colors using Kubelka-Munk spectral mixing
|
|
27
|
-
*
|
|
28
|
-
* This produces results similar to mixing physical paints:
|
|
29
|
-
* - Blue + Yellow = Green (like mixing paints)
|
|
30
|
-
* - More realistic tinting and shading
|
|
31
|
-
* - Handles complementary colors naturally
|
|
32
|
-
*
|
|
33
|
-
* @param hex1 First hex color
|
|
34
|
-
* @param hex2 Second hex color
|
|
35
|
-
* @param ratio Mix ratio (0 = all hex1, 0.5 = equal mix, 1 = all hex2). Default: 0.5
|
|
36
|
-
* @returns Mixed color as hex
|
|
37
|
-
*
|
|
38
|
-
* @example
|
|
39
|
-
* // Mix blue and yellow to get green
|
|
40
|
-
* SpectralMixer.mixColors('#0000FF', '#FFFF00') // Returns green-ish color
|
|
41
|
-
*/
|
|
42
|
-
static mixColors(hex1, hex2, ratio = 0.5) {
|
|
43
|
-
// Clamp ratio to valid range
|
|
44
|
-
ratio = Math.max(0, Math.min(1, ratio));
|
|
45
|
-
// Create spectral Color objects
|
|
46
|
-
const color1 = new spectral.Color(hex1);
|
|
47
|
-
const color2 = new spectral.Color(hex2);
|
|
48
|
-
// Mix using Kubelka-Munk theory
|
|
49
|
-
// The mix function takes [color, concentration] pairs
|
|
50
|
-
// We use (1 - ratio) for color1 and ratio for color2
|
|
51
|
-
const mixed = spectral.mix([color1, 1 - ratio], [color2, ratio]);
|
|
52
|
-
// Convert to hex string
|
|
53
|
-
// toString returns hex format by default with gamut mapping
|
|
54
|
-
const hexResult = mixed.toString({ format: 'hex', method: 'map' });
|
|
55
|
-
// Normalize to our HexColor format
|
|
56
|
-
return ColorConverter.normalizeHex(hexResult);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
//# sourceMappingURL=SpectralMixer.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SpectralMixer.js","sourceRoot":"","sources":["../../../src/services/color/SpectralMixer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,QAAQ,MAAM,aAAa,CAAC;AAGxC,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD;;;;;GAKG;AACH,MAAM,OAAO,aAAa;IACxB;;;;;;;;;;;;;;;;OAgBG;IACH,MAAM,CAAC,SAAS,CAAC,IAAY,EAAE,IAAY,EAAE,QAAgB,GAAG;QAC9D,6BAA6B;QAC7B,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;QAExC,gCAAgC;QAChC,MAAM,MAAM,GAAG,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACxC,MAAM,MAAM,GAAG,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAExC,gCAAgC;QAChC,sDAAsD;QACtD,qDAAqD;QACrD,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;QAEjE,wBAAwB;QACxB,4DAA4D;QAC5D,MAAM,SAAS,GAAG,KAAK,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QAEnE,mCAAmC;QACnC,OAAO,cAAc,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;IAChD,CAAC;CACF"}
|