@trishchuk/coolors-mcp 1.0.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/.claude/settings.local.json +39 -0
- package/.env +2 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +73 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +71 -0
- package/.github/pull_request_template.md +97 -0
- package/.github/workflows/ci.yml +127 -0
- package/.github/workflows/deploy-docs.yml +56 -0
- package/.github/workflows/release.yml +99 -0
- package/.mcp.json +12 -0
- package/.prettierignore +1 -0
- package/CLAUDE.md +201 -0
- package/DOCUMENTATION.md +274 -0
- package/GEMINI.md +54 -0
- package/LICENSE +21 -0
- package/README.md +401 -0
- package/demo/content_based_color.png +0 -0
- package/demo/music-player.html +621 -0
- package/demo/podcast-player.html +903 -0
- package/dist/bin/coolors-mcp.d.ts +1 -0
- package/dist/bin/coolors-mcp.js +154 -0
- package/dist/bin/coolors-mcp.js.map +1 -0
- package/dist/bin/server.d.ts +1 -0
- package/dist/bin/server.js +3292 -0
- package/dist/bin/server.js.map +1 -0
- package/dist/chunk-IQ7NN26V.js +114 -0
- package/dist/chunk-IQ7NN26V.js.map +1 -0
- package/dist/chunk-P3ARRKLS.js +1214 -0
- package/dist/chunk-P3ARRKLS.js.map +1 -0
- package/dist/color/index.d.ts +716 -0
- package/dist/color/index.js +153 -0
- package/dist/color/index.js.map +1 -0
- package/dist/coolors-mcp.d.ts +136 -0
- package/dist/coolors-mcp.js +7 -0
- package/dist/coolors-mcp.js.map +1 -0
- package/docs/.vitepress/cache/deps/@braintree_sanitize-url.js +93 -0
- package/docs/.vitepress/cache/deps/@braintree_sanitize-url.js.map +7 -0
- package/docs/.vitepress/cache/deps/_metadata.json +127 -0
- package/docs/.vitepress/cache/deps/chunk-BUSYA2B4.js +9 -0
- package/docs/.vitepress/cache/deps/chunk-BUSYA2B4.js.map +7 -0
- package/docs/.vitepress/cache/deps/chunk-JD3CXNQ6.js +12683 -0
- package/docs/.vitepress/cache/deps/chunk-JD3CXNQ6.js.map +7 -0
- package/docs/.vitepress/cache/deps/chunk-SYPOPCWC.js +9719 -0
- package/docs/.vitepress/cache/deps/chunk-SYPOPCWC.js.map +7 -0
- package/docs/.vitepress/cache/deps/cytoscape-cose-bilkent.js +4710 -0
- package/docs/.vitepress/cache/deps/cytoscape-cose-bilkent.js.map +7 -0
- package/docs/.vitepress/cache/deps/cytoscape.js +30278 -0
- package/docs/.vitepress/cache/deps/cytoscape.js.map +7 -0
- package/docs/.vitepress/cache/deps/dayjs.js +285 -0
- package/docs/.vitepress/cache/deps/dayjs.js.map +7 -0
- package/docs/.vitepress/cache/deps/debug.js +468 -0
- package/docs/.vitepress/cache/deps/debug.js.map +7 -0
- package/docs/.vitepress/cache/deps/package.json +3 -0
- package/docs/.vitepress/cache/deps/prismjs.js +1466 -0
- package/docs/.vitepress/cache/deps/prismjs.js.map +7 -0
- package/docs/.vitepress/cache/deps/prismjs_components_prism-bash.js +228 -0
- package/docs/.vitepress/cache/deps/prismjs_components_prism-bash.js.map +7 -0
- package/docs/.vitepress/cache/deps/prismjs_components_prism-javascript.js +142 -0
- package/docs/.vitepress/cache/deps/prismjs_components_prism-javascript.js.map +7 -0
- package/docs/.vitepress/cache/deps/prismjs_components_prism-json.js +27 -0
- package/docs/.vitepress/cache/deps/prismjs_components_prism-json.js.map +7 -0
- package/docs/.vitepress/cache/deps/prismjs_components_prism-python.js +65 -0
- package/docs/.vitepress/cache/deps/prismjs_components_prism-python.js.map +7 -0
- package/docs/.vitepress/cache/deps/prismjs_components_prism-typescript.js +53 -0
- package/docs/.vitepress/cache/deps/prismjs_components_prism-typescript.js.map +7 -0
- package/docs/.vitepress/cache/deps/prismjs_components_prism-yaml.js +73 -0
- package/docs/.vitepress/cache/deps/prismjs_components_prism-yaml.js.map +7 -0
- package/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js +4507 -0
- package/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js.map +7 -0
- package/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js +584 -0
- package/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js.map +7 -0
- package/docs/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap.js +1146 -0
- package/docs/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap.js.map +7 -0
- package/docs/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js.js +1667 -0
- package/docs/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js.js.map +7 -0
- package/docs/.vitepress/cache/deps/vitepress___minisearch.js +1814 -0
- package/docs/.vitepress/cache/deps/vitepress___minisearch.js.map +7 -0
- package/docs/.vitepress/cache/deps/vue.js +344 -0
- package/docs/.vitepress/cache/deps/vue.js.map +7 -0
- package/docs/.vitepress/components/ClientGrid.vue +125 -0
- package/docs/.vitepress/components/CodeBlock.vue +231 -0
- package/docs/.vitepress/components/ConfigModal.vue +477 -0
- package/docs/.vitepress/components/DiagramModal.vue +528 -0
- package/docs/.vitepress/components/TroubleshootingModal.vue +472 -0
- package/docs/.vitepress/config.js +162 -0
- package/docs/.vitepress/theme/FundingLayout.vue +251 -0
- package/docs/.vitepress/theme/Layout.vue +134 -0
- package/docs/.vitepress/theme/components/AdBanner.vue +317 -0
- package/docs/.vitepress/theme/components/AdPlaceholder.vue +78 -0
- package/docs/.vitepress/theme/components/FundingEffects.vue +322 -0
- package/docs/.vitepress/theme/components/FundingHero.vue +345 -0
- package/docs/.vitepress/theme/components/SupportSection.vue +511 -0
- package/docs/.vitepress/theme/custom-app.css +339 -0
- package/docs/.vitepress/theme/custom.css +699 -0
- package/docs/.vitepress/theme/index.js +25 -0
- package/docs/README.md +198 -0
- package/docs/concepts/accessibility.md +473 -0
- package/docs/concepts/color-spaces.md +222 -0
- package/docs/concepts/distance-metrics.md +384 -0
- package/docs/concepts/hct.md +261 -0
- package/docs/concepts/image-analysis.md +396 -0
- package/docs/concepts/material-design.md +306 -0
- package/docs/concepts/theme-matching.md +399 -0
- package/docs/examples/basic-colors.md +490 -0
- package/docs/examples/creating-themes.md +898 -0
- package/docs/examples/css-refactoring.md +824 -0
- package/docs/examples/image-extraction.md +882 -0
- package/docs/getting-started.md +366 -0
- package/docs/index.md +190 -0
- package/docs/installation.md +157 -0
- package/docs/tools/README.md +234 -0
- package/docs/tools/accessibility.md +614 -0
- package/docs/tools/color-operations.md +374 -0
- package/docs/tools/image-extraction.md +624 -0
- package/docs/tools/material-design.md +347 -0
- package/docs/tools/theme-matching.md +552 -0
- package/eslint.config.ts +14 -0
- package/examples/theme-matching.md +113 -0
- package/jsr.json +7 -0
- package/mcp-config.json +8 -0
- package/note.md +35 -0
- package/package.json +122 -0
- package/research_results.md +53 -0
- package/src/bin/coolors-mcp.ts +194 -0
- package/src/bin/server.ts +61 -0
- package/src/color/__tests__/conversions-argb.test.ts +198 -0
- package/src/color/__tests__/extract-colors.test.ts +360 -0
- package/src/color/__tests__/image-utils.test.ts +242 -0
- package/src/color/__tests__/reference-colors.test.ts +278 -0
- package/src/color/__tests__/round-trip.test.ts +197 -0
- package/src/color/conversions.test.ts +402 -0
- package/src/color/conversions.ts +393 -0
- package/src/color/dislike/__tests__/dislike-analyzer.test.ts +248 -0
- package/src/color/dislike/dislike-analyzer.ts +114 -0
- package/src/color/extract-colors.ts +228 -0
- package/src/color/hct/__tests__/hct-class.test.ts +232 -0
- package/src/color/hct/harmonization.ts +204 -0
- package/src/color/hct/hct-class.ts +109 -0
- package/src/color/hct/hct-solver.ts +168 -0
- package/src/color/hct/index.ts +39 -0
- package/src/color/hct/tonal-palette.ts +211 -0
- package/src/color/hct/types.ts +88 -0
- package/src/color/image-utils.ts +79 -0
- package/src/color/index.ts +87 -0
- package/src/color/material-theme.ts +157 -0
- package/src/color/metrics.test.ts +276 -0
- package/src/color/metrics.ts +281 -0
- package/src/color/quantize/__tests__/quantizer_celebi.test.ts +195 -0
- package/src/color/quantize/lab_point_provider.ts +55 -0
- package/src/color/quantize/point_provider.ts +27 -0
- package/src/color/quantize/quantizer_celebi.ts +51 -0
- package/src/color/quantize/quantizer_celebi_test.ts +71 -0
- package/src/color/quantize/quantizer_map.ts +47 -0
- package/src/color/quantize/quantizer_wsmeans.ts +232 -0
- package/src/color/quantize/quantizer_wu.ts +472 -0
- package/src/color/score/__tests__/score.test.ts +224 -0
- package/src/color/score/score.ts +175 -0
- package/src/color/types.ts +151 -0
- package/src/color/utils/color_utils.ts +292 -0
- package/src/color/utils/math_utils.ts +145 -0
- package/src/color/utils.test.ts +403 -0
- package/src/color/utils.ts +315 -0
- package/src/constants.ts +5 -0
- package/src/coolors-mcp.ts +37 -0
- package/src/examples/addition.ts +333 -0
- package/src/examples/color-demo.ts +125 -0
- package/src/examples/custom-logger.ts +201 -0
- package/src/examples/oauth-server.ts +113 -0
- package/src/examples/session-context.ts +269 -0
- package/src/session.ts +116 -0
- package/src/theme/__tests__/matcher.test.ts +180 -0
- package/src/theme/__tests__/parser.test.ts +148 -0
- package/src/theme/__tests__/refactor.test.ts +224 -0
- package/src/theme/index.ts +34 -0
- package/src/theme/matcher.ts +395 -0
- package/src/theme/parser.ts +392 -0
- package/src/theme/refactor.ts +360 -0
- package/src/theme/types.ts +152 -0
- package/src/tools/__tests__/gradient-generator.test.ts +206 -0
- package/src/tools/__tests__/palette-with-locks.test.ts +109 -0
- package/src/tools/color-conversion.tool.ts +54 -0
- package/src/tools/color-distance.tool.ts +41 -0
- package/src/tools/colors.ts +31 -0
- package/src/tools/contrast-checker.tool.ts +37 -0
- package/src/tools/dislike-analyzer.tool.ts +247 -0
- package/src/tools/gradient-generator.tool.ts +250 -0
- package/src/tools/image-extraction.tools.ts +289 -0
- package/src/tools/index.ts +39 -0
- package/src/tools/material-theme.tools.ts +250 -0
- package/src/tools/palette-generator.tool.ts +135 -0
- package/src/tools/palette-with-locks.tool.ts +221 -0
- package/src/tools/registry.ts +142 -0
- package/src/tools/simple-tools.ts +37 -0
- package/src/tools/theme-matching.tools.ts +334 -0
- package/src/types.ts +182 -0
- package/src/utils.ts +22 -0
- package/tsconfig.json +8 -0
- package/vitest.config.js +15 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
# Color Spaces
|
|
2
|
+
|
|
3
|
+
Understanding different color spaces is crucial for professional color operations. Each color space has its strengths and optimal use cases.
|
|
4
|
+
|
|
5
|
+
## RGB (Red, Green, Blue)
|
|
6
|
+
|
|
7
|
+
The fundamental color model for digital displays.
|
|
8
|
+
|
|
9
|
+
- **Range**: 0-255 for each channel
|
|
10
|
+
- **Use Cases**: Screen display, web colors
|
|
11
|
+
- **Format**: `rgb(255, 99, 71)` or `#FF6347`
|
|
12
|
+
|
|
13
|
+
```javascript
|
|
14
|
+
// RGB representation
|
|
15
|
+
{
|
|
16
|
+
r: 255, // Red channel (0-255)
|
|
17
|
+
g: 99, // Green channel (0-255)
|
|
18
|
+
b: 71 // Blue channel (0-255)
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## HSL (Hue, Saturation, Lightness)
|
|
23
|
+
|
|
24
|
+
Intuitive color model for human understanding.
|
|
25
|
+
|
|
26
|
+
- **Hue**: 0-360° (color wheel position)
|
|
27
|
+
- **Saturation**: 0-100% (color purity)
|
|
28
|
+
- **Lightness**: 0-100% (brightness)
|
|
29
|
+
- **Use Cases**: Color picking, theme generation
|
|
30
|
+
|
|
31
|
+
```javascript
|
|
32
|
+
// HSL representation
|
|
33
|
+
{
|
|
34
|
+
h: 9, // Hue in degrees
|
|
35
|
+
s: 100, // Saturation percentage
|
|
36
|
+
l: 64 // Lightness percentage
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## LAB (CIE L*a*b*)
|
|
41
|
+
|
|
42
|
+
Perceptually uniform color space based on human vision.
|
|
43
|
+
|
|
44
|
+
- **L**: Lightness (0-100)
|
|
45
|
+
- **a**: Green-red axis (-128 to 127)
|
|
46
|
+
- **b**: Blue-yellow axis (-128 to 127)
|
|
47
|
+
- **Use Cases**: Color difference calculations, print
|
|
48
|
+
|
|
49
|
+
```javascript
|
|
50
|
+
// LAB representation
|
|
51
|
+
{
|
|
52
|
+
l: 62.2, // Lightness
|
|
53
|
+
a: 57.8, // Green-red component
|
|
54
|
+
b: 46.4 // Blue-yellow component
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## HCT (Hue, Chroma, Tone)
|
|
59
|
+
|
|
60
|
+
Google's perceptually uniform color space, optimized for UI.
|
|
61
|
+
|
|
62
|
+
- **Hue**: 0-360° (color wheel position)
|
|
63
|
+
- **Chroma**: 0-120+ (color intensity)
|
|
64
|
+
- **Tone**: 0-100 (perceptual lightness)
|
|
65
|
+
- **Use Cases**: Material Design, UI theming
|
|
66
|
+
|
|
67
|
+
### Why HCT is Superior for UI
|
|
68
|
+
|
|
69
|
+
1. **Predictable Contrast**: Tone values directly correlate with WCAG contrast ratios
|
|
70
|
+
- 40 tone difference ≈ 3:1 contrast
|
|
71
|
+
- 50 tone difference ≈ 4.5:1 contrast
|
|
72
|
+
|
|
73
|
+
2. **Perceptual Uniformity**: Equal changes in values produce equal perceptual changes
|
|
74
|
+
|
|
75
|
+
3. **UI-Optimized**: Designed specifically for interface design, not general color science
|
|
76
|
+
|
|
77
|
+
```javascript
|
|
78
|
+
// HCT representation
|
|
79
|
+
{
|
|
80
|
+
h: 25.5, // Hue in degrees
|
|
81
|
+
c: 48.2, // Chroma (color intensity)
|
|
82
|
+
t: 67.5 // Tone (perceptual lightness)
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Color Space Conversions
|
|
87
|
+
|
|
88
|
+
Coolors MCP handles all conversions through RGB as the central format:
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
HSL ↔ RGB ↔ HEX
|
|
92
|
+
↓ ↑
|
|
93
|
+
XYZ
|
|
94
|
+
↓ ↑
|
|
95
|
+
LAB
|
|
96
|
+
↓ ↑
|
|
97
|
+
HCT
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Conversion Examples
|
|
101
|
+
|
|
102
|
+
```javascript
|
|
103
|
+
// Convert hex to multiple formats
|
|
104
|
+
const hex = "#6366F1";
|
|
105
|
+
|
|
106
|
+
// To RGB
|
|
107
|
+
"rgb(99, 102, 241)"
|
|
108
|
+
|
|
109
|
+
// To HSL
|
|
110
|
+
"hsl(239, 84%, 67%)"
|
|
111
|
+
|
|
112
|
+
// To LAB
|
|
113
|
+
"lab(47.9, 35.2, -65.7)"
|
|
114
|
+
|
|
115
|
+
// To HCT
|
|
116
|
+
"hct(265.8, 87.2, 47.9)"
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Choosing the Right Color Space
|
|
120
|
+
|
|
121
|
+
### For Color Picking
|
|
122
|
+
Use **HSL** - intuitive for users to understand and manipulate.
|
|
123
|
+
|
|
124
|
+
### For Color Matching
|
|
125
|
+
Use **LAB** or **HCT** - perceptually uniform for accurate comparisons.
|
|
126
|
+
|
|
127
|
+
### For UI Themes
|
|
128
|
+
Use **HCT** - designed for interface design with predictable contrast.
|
|
129
|
+
|
|
130
|
+
### For Web/Digital
|
|
131
|
+
Use **RGB/Hex** - native format for browsers and displays.
|
|
132
|
+
|
|
133
|
+
### For Print
|
|
134
|
+
Use **LAB** - device-independent and accurate for print reproduction.
|
|
135
|
+
|
|
136
|
+
## Perceptual Distance Metrics
|
|
137
|
+
|
|
138
|
+
Different color spaces affect distance calculations:
|
|
139
|
+
|
|
140
|
+
### RGB Distance (Euclidean)
|
|
141
|
+
Simple but perceptually inaccurate:
|
|
142
|
+
```
|
|
143
|
+
distance = √((r₂-r₁)² + (g₂-g₁)² + (b₂-b₁)²)
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Delta E (LAB-based)
|
|
147
|
+
Industry standard for color difference:
|
|
148
|
+
- **Delta E 76**: Original formula
|
|
149
|
+
- **Delta E 94**: Improved for textiles
|
|
150
|
+
- **Delta E 2000**: Most accurate, accounts for human perception
|
|
151
|
+
|
|
152
|
+
### HCT Distance
|
|
153
|
+
Weighted for UI applications:
|
|
154
|
+
```
|
|
155
|
+
distance = √((h₂-h₁)² + (c₂-c₁)² + 2×(t₂-t₁)²)
|
|
156
|
+
```
|
|
157
|
+
Tone is weighted 2x because lightness differences are more noticeable in UI.
|
|
158
|
+
|
|
159
|
+
## Color Space Limitations
|
|
160
|
+
|
|
161
|
+
### RGB Limitations
|
|
162
|
+
- Not perceptually uniform
|
|
163
|
+
- Difficult for humans to predict color changes
|
|
164
|
+
- Poor for color difference calculations
|
|
165
|
+
|
|
166
|
+
### HSL Limitations
|
|
167
|
+
- Saturation and lightness are not perceptually uniform
|
|
168
|
+
- Colors with same L value may appear different brightness
|
|
169
|
+
- Not suitable for accessibility calculations
|
|
170
|
+
|
|
171
|
+
### LAB Limitations
|
|
172
|
+
- Can represent impossible colors
|
|
173
|
+
- Less intuitive for designers
|
|
174
|
+
- Blue region has known inaccuracies
|
|
175
|
+
|
|
176
|
+
### HCT Advantages
|
|
177
|
+
- Specifically designed for UI/UX
|
|
178
|
+
- Predictable contrast ratios
|
|
179
|
+
- Perceptually uniform
|
|
180
|
+
- No impossible colors
|
|
181
|
+
|
|
182
|
+
## Practical Applications
|
|
183
|
+
|
|
184
|
+
### Theme Generation
|
|
185
|
+
HCT enables predictable theme generation:
|
|
186
|
+
```javascript
|
|
187
|
+
// Generate accessible color variations
|
|
188
|
+
const baseHCT = { h: 265, c: 50, t: 50 };
|
|
189
|
+
|
|
190
|
+
// Light variant (3:1 contrast)
|
|
191
|
+
const light = { ...baseHCT, t: 90 };
|
|
192
|
+
|
|
193
|
+
// Dark variant (4.5:1 contrast)
|
|
194
|
+
const dark = { ...baseHCT, t: 20 };
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Color Harmonies
|
|
198
|
+
Different spaces excel at different harmonies:
|
|
199
|
+
- **HSL**: Best for analogous colors (rotate hue)
|
|
200
|
+
- **HCT**: Best for tonal variations (adjust tone)
|
|
201
|
+
- **LAB**: Best for perceptual interpolation
|
|
202
|
+
|
|
203
|
+
### Gradient Generation
|
|
204
|
+
Color space affects gradient smoothness:
|
|
205
|
+
- **RGB**: Can produce muddy colors in middle
|
|
206
|
+
- **HSL**: Can produce unnatural brightness shifts
|
|
207
|
+
- **LAB/HCT**: Smooth perceptual transitions
|
|
208
|
+
|
|
209
|
+
## Best Practices
|
|
210
|
+
|
|
211
|
+
1. **Store colors in RGB/Hex** for compatibility
|
|
212
|
+
2. **Convert to HCT** for manipulation and theming
|
|
213
|
+
3. **Use LAB/Delta E** for color matching
|
|
214
|
+
4. **Display in HSL** for user interfaces
|
|
215
|
+
5. **Calculate contrast** in relative luminance
|
|
216
|
+
|
|
217
|
+
## See Also
|
|
218
|
+
|
|
219
|
+
- [HCT Color System](./hct.md) - Deep dive into HCT
|
|
220
|
+
- [Material Design](./material-design.md) - Using HCT in practice
|
|
221
|
+
- [Accessibility](./accessibility.md) - Color contrast and WCAG
|
|
222
|
+
- [Theme Matching](./theme-matching.md) - Algorithm details
|
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
# Distance Metrics
|
|
2
|
+
|
|
3
|
+
Understanding how to measure the difference between colors is crucial for color matching, palette generation, and theme creation. Different metrics serve different purposes.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Color distance metrics quantify how different two colors appear. The challenge is that simple mathematical distance doesn't match human perception - two colors that are numerically similar might look very different, and vice versa.
|
|
8
|
+
|
|
9
|
+
## Available Metrics
|
|
10
|
+
|
|
11
|
+
### Euclidean Distance (RGB)
|
|
12
|
+
|
|
13
|
+
The simplest metric, calculating straight-line distance in RGB space:
|
|
14
|
+
|
|
15
|
+
```javascript
|
|
16
|
+
distance = √((r₂-r₁)² + (g₂-g₁)² + (b₂-b₁)²)
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**Pros:**
|
|
20
|
+
- Fast to compute
|
|
21
|
+
- Simple to understand
|
|
22
|
+
- Good for rough comparisons
|
|
23
|
+
|
|
24
|
+
**Cons:**
|
|
25
|
+
- Not perceptually uniform
|
|
26
|
+
- Poor for subtle color differences
|
|
27
|
+
- Doesn't match human vision
|
|
28
|
+
|
|
29
|
+
**When to use:**
|
|
30
|
+
- Quick filtering
|
|
31
|
+
- Performance-critical applications
|
|
32
|
+
- When accuracy isn't crucial
|
|
33
|
+
|
|
34
|
+
### Delta E CIE76
|
|
35
|
+
|
|
36
|
+
The original perceptual color difference formula using LAB color space:
|
|
37
|
+
|
|
38
|
+
```javascript
|
|
39
|
+
ΔE*₇₆ = √((L₂-L₁)² + (a₂-a₁)² + (b₂-b₁)²)
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**Characteristics:**
|
|
43
|
+
- First attempt at perceptual uniformity
|
|
44
|
+
- Simple LAB distance calculation
|
|
45
|
+
- Threshold: ΔE < 2.3 is barely perceptible
|
|
46
|
+
|
|
47
|
+
**When to use:**
|
|
48
|
+
- Basic perceptual matching
|
|
49
|
+
- Legacy systems
|
|
50
|
+
- When computation speed matters
|
|
51
|
+
|
|
52
|
+
### Delta E CIE94
|
|
53
|
+
|
|
54
|
+
Improved formula with weighting factors for different color attributes:
|
|
55
|
+
|
|
56
|
+
```javascript
|
|
57
|
+
ΔE*₉₄ = √((ΔL/kₗSₗ)² + (ΔC/kᴄSᴄ)² + (ΔH/kₕSₕ)²)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**Improvements:**
|
|
61
|
+
- Separate weights for lightness, chroma, hue
|
|
62
|
+
- Better for textiles and graphics
|
|
63
|
+
- More accurate than CIE76
|
|
64
|
+
|
|
65
|
+
**When to use:**
|
|
66
|
+
- Textile industry
|
|
67
|
+
- Graphic arts
|
|
68
|
+
- Better accuracy than CIE76
|
|
69
|
+
|
|
70
|
+
### Delta E 2000 (CIEDE2000)
|
|
71
|
+
|
|
72
|
+
The most accurate standard for color difference, addressing perceptual non-uniformities:
|
|
73
|
+
|
|
74
|
+
```javascript
|
|
75
|
+
// Complex formula with multiple correction factors
|
|
76
|
+
ΔE*₀₀ = √((ΔL'/kₗSₗ)² + (ΔC'/kᴄSᴄ)² + (ΔH'/kₕSₕ)² + Rᴛ(ΔC'/kᴄSᴄ)(ΔH'/kₕSₕ))
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**Features:**
|
|
80
|
+
- Rotation term for blue region
|
|
81
|
+
- Lightness, chroma, hue corrections
|
|
82
|
+
- Most accurate for human perception
|
|
83
|
+
- Industry standard
|
|
84
|
+
|
|
85
|
+
**When to use:**
|
|
86
|
+
- Color matching applications
|
|
87
|
+
- Quality control
|
|
88
|
+
- When accuracy is paramount
|
|
89
|
+
- Default for most use cases
|
|
90
|
+
|
|
91
|
+
### HCT Distance
|
|
92
|
+
|
|
93
|
+
Weighted distance in Google's HCT color space:
|
|
94
|
+
|
|
95
|
+
```javascript
|
|
96
|
+
distance = √((Δh × wₕ)² + (Δc × wᴄ)² + (Δt × wᴛ)²)
|
|
97
|
+
// Typical weights: wₕ=1, wᴄ=1, wᴛ=2
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**Advantages:**
|
|
101
|
+
- Optimized for UI colors
|
|
102
|
+
- Tone component predicts contrast
|
|
103
|
+
- Better for Material Design
|
|
104
|
+
|
|
105
|
+
**When to use:**
|
|
106
|
+
- UI/UX design
|
|
107
|
+
- Material Design systems
|
|
108
|
+
- Theme matching
|
|
109
|
+
- Accessibility considerations
|
|
110
|
+
|
|
111
|
+
## Perceptibility Thresholds
|
|
112
|
+
|
|
113
|
+
Different ΔE values represent different levels of color difference:
|
|
114
|
+
|
|
115
|
+
| ΔE Value | Perception | Use Case |
|
|
116
|
+
|----------|------------|----------|
|
|
117
|
+
| 0-1 | Not perceptible | Exact matches |
|
|
118
|
+
| 1-2 | Barely perceptible | Very close matches |
|
|
119
|
+
| 2-3.5 | Perceptible by experts | Close matches |
|
|
120
|
+
| 3.5-5 | Noticeable difference | Acceptable matches |
|
|
121
|
+
| 5-10 | Clear difference | Related colors |
|
|
122
|
+
| >10 | Different colors | Distinct colors |
|
|
123
|
+
|
|
124
|
+
## Metric Comparison
|
|
125
|
+
|
|
126
|
+
### Performance Comparison
|
|
127
|
+
|
|
128
|
+
```javascript
|
|
129
|
+
// Relative computation time (normalized)
|
|
130
|
+
{
|
|
131
|
+
"euclidean": 1, // Baseline
|
|
132
|
+
"deltaE76": 2, // 2x slower
|
|
133
|
+
"deltaE94": 3, // 3x slower
|
|
134
|
+
"deltaE2000": 10, // 10x slower
|
|
135
|
+
"hct": 4 // 4x slower
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Accuracy Comparison
|
|
140
|
+
|
|
141
|
+
```javascript
|
|
142
|
+
// Correlation with human perception (0-1)
|
|
143
|
+
{
|
|
144
|
+
"euclidean": 0.65, // Poor
|
|
145
|
+
"deltaE76": 0.75, // Fair
|
|
146
|
+
"deltaE94": 0.85, // Good
|
|
147
|
+
"deltaE2000": 0.95, // Excellent
|
|
148
|
+
"hct": 0.90 // Very good for UI
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Using Distance Metrics in Coolors MCP
|
|
153
|
+
|
|
154
|
+
### Basic Color Distance
|
|
155
|
+
|
|
156
|
+
```javascript
|
|
157
|
+
// Using Delta E 2000 (default)
|
|
158
|
+
{
|
|
159
|
+
"name": "color_distance",
|
|
160
|
+
"arguments": {
|
|
161
|
+
"color1": "#6366f1",
|
|
162
|
+
"color2": "#5355d1"
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
// Result: 5.2 (noticeable but related)
|
|
166
|
+
|
|
167
|
+
// Using specific metric
|
|
168
|
+
{
|
|
169
|
+
"name": "color_distance",
|
|
170
|
+
"arguments": {
|
|
171
|
+
"color1": "#6366f1",
|
|
172
|
+
"color2": "#5355d1",
|
|
173
|
+
"metric": "euclidean"
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
// Result: 32.5 (less meaningful number)
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Weighted HCT Distance
|
|
180
|
+
|
|
181
|
+
```javascript
|
|
182
|
+
// Custom weights for UI matching
|
|
183
|
+
{
|
|
184
|
+
"name": "color_distance",
|
|
185
|
+
"arguments": {
|
|
186
|
+
"color1": "#6366f1",
|
|
187
|
+
"color2": "#5355d1",
|
|
188
|
+
"metric": "weighted",
|
|
189
|
+
"weights": {
|
|
190
|
+
"hue": 1,
|
|
191
|
+
"chroma": 1,
|
|
192
|
+
"tone": 2 // Emphasize lightness
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Choosing the Right Metric
|
|
199
|
+
|
|
200
|
+
### Decision Tree
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
Is performance critical?
|
|
204
|
+
├─ Yes → Euclidean
|
|
205
|
+
└─ No → Is it for UI/UX?
|
|
206
|
+
├─ Yes → HCT Distance
|
|
207
|
+
└─ No → Need maximum accuracy?
|
|
208
|
+
├─ Yes → Delta E 2000
|
|
209
|
+
└─ No → Delta E 76
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Use Case Guidelines
|
|
213
|
+
|
|
214
|
+
| Use Case | Recommended Metric | Reason |
|
|
215
|
+
|----------|-------------------|---------|
|
|
216
|
+
| CSS color matching | Delta E 2000 | Accuracy |
|
|
217
|
+
| Real-time filtering | Euclidean | Speed |
|
|
218
|
+
| Theme generation | HCT | UI optimization |
|
|
219
|
+
| Print color matching | Delta E 2000 | Industry standard |
|
|
220
|
+
| Palette creation | HCT | Perceptual uniformity |
|
|
221
|
+
| Image quantization | Delta E 76 | Balance |
|
|
222
|
+
|
|
223
|
+
## Implementation Examples
|
|
224
|
+
|
|
225
|
+
### Finding Similar Colors
|
|
226
|
+
|
|
227
|
+
```javascript
|
|
228
|
+
function findSimilarColors(targetColor, palette, threshold = 5) {
|
|
229
|
+
return palette.filter(color => {
|
|
230
|
+
const distance = colorDistance(targetColor, color, 'deltaE2000');
|
|
231
|
+
return distance < threshold;
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Usage
|
|
236
|
+
const similar = findSimilarColors('#6366f1', myPalette, 10);
|
|
237
|
+
// Returns colors within ΔE 10 of target
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Color Clustering
|
|
241
|
+
|
|
242
|
+
```javascript
|
|
243
|
+
function clusterColors(colors, maxDistance = 5) {
|
|
244
|
+
const clusters = [];
|
|
245
|
+
|
|
246
|
+
colors.forEach(color => {
|
|
247
|
+
let added = false;
|
|
248
|
+
|
|
249
|
+
for (const cluster of clusters) {
|
|
250
|
+
const distance = colorDistance(color, cluster.center, 'deltaE2000');
|
|
251
|
+
if (distance < maxDistance) {
|
|
252
|
+
cluster.colors.push(color);
|
|
253
|
+
added = true;
|
|
254
|
+
break;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if (!added) {
|
|
259
|
+
clusters.push({
|
|
260
|
+
center: color,
|
|
261
|
+
colors: [color]
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
return clusters;
|
|
267
|
+
}
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### Perceptual Interpolation
|
|
271
|
+
|
|
272
|
+
```javascript
|
|
273
|
+
function interpolatePerceptual(color1, color2, steps) {
|
|
274
|
+
// Convert to LAB for perceptual interpolation
|
|
275
|
+
const lab1 = rgbToLab(color1);
|
|
276
|
+
const lab2 = rgbToLab(color2);
|
|
277
|
+
|
|
278
|
+
const colors = [];
|
|
279
|
+
for (let i = 0; i <= steps; i++) {
|
|
280
|
+
const t = i / steps;
|
|
281
|
+
const lab = {
|
|
282
|
+
l: lab1.l + (lab2.l - lab1.l) * t,
|
|
283
|
+
a: lab1.a + (lab2.a - lab1.a) * t,
|
|
284
|
+
b: lab1.b + (lab2.b - lab1.b) * t
|
|
285
|
+
};
|
|
286
|
+
colors.push(labToRgb(lab));
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
return colors;
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
## Advanced Concepts
|
|
294
|
+
|
|
295
|
+
### Weighted Metrics
|
|
296
|
+
|
|
297
|
+
Different applications benefit from custom weightings:
|
|
298
|
+
|
|
299
|
+
```javascript
|
|
300
|
+
// UI Design - emphasize tone differences
|
|
301
|
+
const uiWeights = { lightness: 2, chroma: 1, hue: 0.5 };
|
|
302
|
+
|
|
303
|
+
// Brand Colors - emphasize hue accuracy
|
|
304
|
+
const brandWeights = { lightness: 1, chroma: 1.5, hue: 2 };
|
|
305
|
+
|
|
306
|
+
// Accessibility - focus on lightness
|
|
307
|
+
const a11yWeights = { lightness: 3, chroma: 0.5, hue: 0.5 };
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### Context-Aware Distance
|
|
311
|
+
|
|
312
|
+
Distance perception changes based on viewing conditions:
|
|
313
|
+
|
|
314
|
+
```javascript
|
|
315
|
+
function contextualDistance(color1, color2, context) {
|
|
316
|
+
switch(context) {
|
|
317
|
+
case 'small-text':
|
|
318
|
+
// Need larger differences for readability
|
|
319
|
+
return colorDistance(color1, color2) * 1.5;
|
|
320
|
+
|
|
321
|
+
case 'large-area':
|
|
322
|
+
// Subtle differences more noticeable
|
|
323
|
+
return colorDistance(color1, color2) * 0.8;
|
|
324
|
+
|
|
325
|
+
case 'dark-mode':
|
|
326
|
+
// Adjust for dark backgrounds
|
|
327
|
+
return adjustedDarkModeDistance(color1, color2);
|
|
328
|
+
|
|
329
|
+
default:
|
|
330
|
+
return colorDistance(color1, color2);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### Multi-Dimensional Distance
|
|
336
|
+
|
|
337
|
+
Sometimes you need to consider multiple factors:
|
|
338
|
+
|
|
339
|
+
```javascript
|
|
340
|
+
function multiFactorDistance(color1, color2) {
|
|
341
|
+
const perceptual = deltaE2000(color1, color2);
|
|
342
|
+
const contrast = Math.abs(getContrast(color1) - getContrast(color2));
|
|
343
|
+
const semantic = getSemanticDistance(color1, color2);
|
|
344
|
+
|
|
345
|
+
return {
|
|
346
|
+
overall: (perceptual * 0.6 + contrast * 0.3 + semantic * 0.1),
|
|
347
|
+
components: { perceptual, contrast, semantic }
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
## Common Pitfalls
|
|
353
|
+
|
|
354
|
+
### RGB Distance Misuse
|
|
355
|
+
❌ Don't use RGB distance for perceptual matching
|
|
356
|
+
✅ Use Delta E or HCT distance instead
|
|
357
|
+
|
|
358
|
+
### Ignoring Context
|
|
359
|
+
❌ Don't use the same threshold for all use cases
|
|
360
|
+
✅ Adjust thresholds based on application
|
|
361
|
+
|
|
362
|
+
### Over-Engineering
|
|
363
|
+
❌ Don't always use the most complex metric
|
|
364
|
+
✅ Choose based on actual requirements
|
|
365
|
+
|
|
366
|
+
### Wrong Color Space
|
|
367
|
+
❌ Don't interpolate in RGB for gradients
|
|
368
|
+
✅ Use LAB or HCT for smooth transitions
|
|
369
|
+
|
|
370
|
+
## Best Practices
|
|
371
|
+
|
|
372
|
+
1. **Start with Delta E 2000** - It's the most accurate general-purpose metric
|
|
373
|
+
2. **Use HCT for UI** - Better for interface design and accessibility
|
|
374
|
+
3. **Cache computations** - Distance calculations can be expensive
|
|
375
|
+
4. **Test with real users** - Perception varies between individuals
|
|
376
|
+
5. **Consider viewing conditions** - Screen, lighting affect perception
|
|
377
|
+
6. **Document your choice** - Explain why you chose a specific metric
|
|
378
|
+
|
|
379
|
+
## See Also
|
|
380
|
+
|
|
381
|
+
- [Color Spaces](./color-spaces.md) - Understanding different color models
|
|
382
|
+
- [HCT System](./hct.md) - Google's perceptual color space
|
|
383
|
+
- [Theme Matching](./theme-matching.md) - Using distance for matching
|
|
384
|
+
- [Accessibility](./accessibility.md) - Contrast and perception
|