@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.
Files changed (197) hide show
  1. package/.claude/settings.local.json +39 -0
  2. package/.env +2 -0
  3. package/.github/ISSUE_TEMPLATE/bug_report.md +73 -0
  4. package/.github/ISSUE_TEMPLATE/feature_request.md +71 -0
  5. package/.github/pull_request_template.md +97 -0
  6. package/.github/workflows/ci.yml +127 -0
  7. package/.github/workflows/deploy-docs.yml +56 -0
  8. package/.github/workflows/release.yml +99 -0
  9. package/.mcp.json +12 -0
  10. package/.prettierignore +1 -0
  11. package/CLAUDE.md +201 -0
  12. package/DOCUMENTATION.md +274 -0
  13. package/GEMINI.md +54 -0
  14. package/LICENSE +21 -0
  15. package/README.md +401 -0
  16. package/demo/content_based_color.png +0 -0
  17. package/demo/music-player.html +621 -0
  18. package/demo/podcast-player.html +903 -0
  19. package/dist/bin/coolors-mcp.d.ts +1 -0
  20. package/dist/bin/coolors-mcp.js +154 -0
  21. package/dist/bin/coolors-mcp.js.map +1 -0
  22. package/dist/bin/server.d.ts +1 -0
  23. package/dist/bin/server.js +3292 -0
  24. package/dist/bin/server.js.map +1 -0
  25. package/dist/chunk-IQ7NN26V.js +114 -0
  26. package/dist/chunk-IQ7NN26V.js.map +1 -0
  27. package/dist/chunk-P3ARRKLS.js +1214 -0
  28. package/dist/chunk-P3ARRKLS.js.map +1 -0
  29. package/dist/color/index.d.ts +716 -0
  30. package/dist/color/index.js +153 -0
  31. package/dist/color/index.js.map +1 -0
  32. package/dist/coolors-mcp.d.ts +136 -0
  33. package/dist/coolors-mcp.js +7 -0
  34. package/dist/coolors-mcp.js.map +1 -0
  35. package/docs/.vitepress/cache/deps/@braintree_sanitize-url.js +93 -0
  36. package/docs/.vitepress/cache/deps/@braintree_sanitize-url.js.map +7 -0
  37. package/docs/.vitepress/cache/deps/_metadata.json +127 -0
  38. package/docs/.vitepress/cache/deps/chunk-BUSYA2B4.js +9 -0
  39. package/docs/.vitepress/cache/deps/chunk-BUSYA2B4.js.map +7 -0
  40. package/docs/.vitepress/cache/deps/chunk-JD3CXNQ6.js +12683 -0
  41. package/docs/.vitepress/cache/deps/chunk-JD3CXNQ6.js.map +7 -0
  42. package/docs/.vitepress/cache/deps/chunk-SYPOPCWC.js +9719 -0
  43. package/docs/.vitepress/cache/deps/chunk-SYPOPCWC.js.map +7 -0
  44. package/docs/.vitepress/cache/deps/cytoscape-cose-bilkent.js +4710 -0
  45. package/docs/.vitepress/cache/deps/cytoscape-cose-bilkent.js.map +7 -0
  46. package/docs/.vitepress/cache/deps/cytoscape.js +30278 -0
  47. package/docs/.vitepress/cache/deps/cytoscape.js.map +7 -0
  48. package/docs/.vitepress/cache/deps/dayjs.js +285 -0
  49. package/docs/.vitepress/cache/deps/dayjs.js.map +7 -0
  50. package/docs/.vitepress/cache/deps/debug.js +468 -0
  51. package/docs/.vitepress/cache/deps/debug.js.map +7 -0
  52. package/docs/.vitepress/cache/deps/package.json +3 -0
  53. package/docs/.vitepress/cache/deps/prismjs.js +1466 -0
  54. package/docs/.vitepress/cache/deps/prismjs.js.map +7 -0
  55. package/docs/.vitepress/cache/deps/prismjs_components_prism-bash.js +228 -0
  56. package/docs/.vitepress/cache/deps/prismjs_components_prism-bash.js.map +7 -0
  57. package/docs/.vitepress/cache/deps/prismjs_components_prism-javascript.js +142 -0
  58. package/docs/.vitepress/cache/deps/prismjs_components_prism-javascript.js.map +7 -0
  59. package/docs/.vitepress/cache/deps/prismjs_components_prism-json.js +27 -0
  60. package/docs/.vitepress/cache/deps/prismjs_components_prism-json.js.map +7 -0
  61. package/docs/.vitepress/cache/deps/prismjs_components_prism-python.js +65 -0
  62. package/docs/.vitepress/cache/deps/prismjs_components_prism-python.js.map +7 -0
  63. package/docs/.vitepress/cache/deps/prismjs_components_prism-typescript.js +53 -0
  64. package/docs/.vitepress/cache/deps/prismjs_components_prism-typescript.js.map +7 -0
  65. package/docs/.vitepress/cache/deps/prismjs_components_prism-yaml.js +73 -0
  66. package/docs/.vitepress/cache/deps/prismjs_components_prism-yaml.js.map +7 -0
  67. package/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js +4507 -0
  68. package/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js.map +7 -0
  69. package/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js +584 -0
  70. package/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js.map +7 -0
  71. package/docs/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap.js +1146 -0
  72. package/docs/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap.js.map +7 -0
  73. package/docs/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js.js +1667 -0
  74. package/docs/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js.js.map +7 -0
  75. package/docs/.vitepress/cache/deps/vitepress___minisearch.js +1814 -0
  76. package/docs/.vitepress/cache/deps/vitepress___minisearch.js.map +7 -0
  77. package/docs/.vitepress/cache/deps/vue.js +344 -0
  78. package/docs/.vitepress/cache/deps/vue.js.map +7 -0
  79. package/docs/.vitepress/components/ClientGrid.vue +125 -0
  80. package/docs/.vitepress/components/CodeBlock.vue +231 -0
  81. package/docs/.vitepress/components/ConfigModal.vue +477 -0
  82. package/docs/.vitepress/components/DiagramModal.vue +528 -0
  83. package/docs/.vitepress/components/TroubleshootingModal.vue +472 -0
  84. package/docs/.vitepress/config.js +162 -0
  85. package/docs/.vitepress/theme/FundingLayout.vue +251 -0
  86. package/docs/.vitepress/theme/Layout.vue +134 -0
  87. package/docs/.vitepress/theme/components/AdBanner.vue +317 -0
  88. package/docs/.vitepress/theme/components/AdPlaceholder.vue +78 -0
  89. package/docs/.vitepress/theme/components/FundingEffects.vue +322 -0
  90. package/docs/.vitepress/theme/components/FundingHero.vue +345 -0
  91. package/docs/.vitepress/theme/components/SupportSection.vue +511 -0
  92. package/docs/.vitepress/theme/custom-app.css +339 -0
  93. package/docs/.vitepress/theme/custom.css +699 -0
  94. package/docs/.vitepress/theme/index.js +25 -0
  95. package/docs/README.md +198 -0
  96. package/docs/concepts/accessibility.md +473 -0
  97. package/docs/concepts/color-spaces.md +222 -0
  98. package/docs/concepts/distance-metrics.md +384 -0
  99. package/docs/concepts/hct.md +261 -0
  100. package/docs/concepts/image-analysis.md +396 -0
  101. package/docs/concepts/material-design.md +306 -0
  102. package/docs/concepts/theme-matching.md +399 -0
  103. package/docs/examples/basic-colors.md +490 -0
  104. package/docs/examples/creating-themes.md +898 -0
  105. package/docs/examples/css-refactoring.md +824 -0
  106. package/docs/examples/image-extraction.md +882 -0
  107. package/docs/getting-started.md +366 -0
  108. package/docs/index.md +190 -0
  109. package/docs/installation.md +157 -0
  110. package/docs/tools/README.md +234 -0
  111. package/docs/tools/accessibility.md +614 -0
  112. package/docs/tools/color-operations.md +374 -0
  113. package/docs/tools/image-extraction.md +624 -0
  114. package/docs/tools/material-design.md +347 -0
  115. package/docs/tools/theme-matching.md +552 -0
  116. package/eslint.config.ts +14 -0
  117. package/examples/theme-matching.md +113 -0
  118. package/jsr.json +7 -0
  119. package/mcp-config.json +8 -0
  120. package/note.md +35 -0
  121. package/package.json +122 -0
  122. package/research_results.md +53 -0
  123. package/src/bin/coolors-mcp.ts +194 -0
  124. package/src/bin/server.ts +61 -0
  125. package/src/color/__tests__/conversions-argb.test.ts +198 -0
  126. package/src/color/__tests__/extract-colors.test.ts +360 -0
  127. package/src/color/__tests__/image-utils.test.ts +242 -0
  128. package/src/color/__tests__/reference-colors.test.ts +278 -0
  129. package/src/color/__tests__/round-trip.test.ts +197 -0
  130. package/src/color/conversions.test.ts +402 -0
  131. package/src/color/conversions.ts +393 -0
  132. package/src/color/dislike/__tests__/dislike-analyzer.test.ts +248 -0
  133. package/src/color/dislike/dislike-analyzer.ts +114 -0
  134. package/src/color/extract-colors.ts +228 -0
  135. package/src/color/hct/__tests__/hct-class.test.ts +232 -0
  136. package/src/color/hct/harmonization.ts +204 -0
  137. package/src/color/hct/hct-class.ts +109 -0
  138. package/src/color/hct/hct-solver.ts +168 -0
  139. package/src/color/hct/index.ts +39 -0
  140. package/src/color/hct/tonal-palette.ts +211 -0
  141. package/src/color/hct/types.ts +88 -0
  142. package/src/color/image-utils.ts +79 -0
  143. package/src/color/index.ts +87 -0
  144. package/src/color/material-theme.ts +157 -0
  145. package/src/color/metrics.test.ts +276 -0
  146. package/src/color/metrics.ts +281 -0
  147. package/src/color/quantize/__tests__/quantizer_celebi.test.ts +195 -0
  148. package/src/color/quantize/lab_point_provider.ts +55 -0
  149. package/src/color/quantize/point_provider.ts +27 -0
  150. package/src/color/quantize/quantizer_celebi.ts +51 -0
  151. package/src/color/quantize/quantizer_celebi_test.ts +71 -0
  152. package/src/color/quantize/quantizer_map.ts +47 -0
  153. package/src/color/quantize/quantizer_wsmeans.ts +232 -0
  154. package/src/color/quantize/quantizer_wu.ts +472 -0
  155. package/src/color/score/__tests__/score.test.ts +224 -0
  156. package/src/color/score/score.ts +175 -0
  157. package/src/color/types.ts +151 -0
  158. package/src/color/utils/color_utils.ts +292 -0
  159. package/src/color/utils/math_utils.ts +145 -0
  160. package/src/color/utils.test.ts +403 -0
  161. package/src/color/utils.ts +315 -0
  162. package/src/constants.ts +5 -0
  163. package/src/coolors-mcp.ts +37 -0
  164. package/src/examples/addition.ts +333 -0
  165. package/src/examples/color-demo.ts +125 -0
  166. package/src/examples/custom-logger.ts +201 -0
  167. package/src/examples/oauth-server.ts +113 -0
  168. package/src/examples/session-context.ts +269 -0
  169. package/src/session.ts +116 -0
  170. package/src/theme/__tests__/matcher.test.ts +180 -0
  171. package/src/theme/__tests__/parser.test.ts +148 -0
  172. package/src/theme/__tests__/refactor.test.ts +224 -0
  173. package/src/theme/index.ts +34 -0
  174. package/src/theme/matcher.ts +395 -0
  175. package/src/theme/parser.ts +392 -0
  176. package/src/theme/refactor.ts +360 -0
  177. package/src/theme/types.ts +152 -0
  178. package/src/tools/__tests__/gradient-generator.test.ts +206 -0
  179. package/src/tools/__tests__/palette-with-locks.test.ts +109 -0
  180. package/src/tools/color-conversion.tool.ts +54 -0
  181. package/src/tools/color-distance.tool.ts +41 -0
  182. package/src/tools/colors.ts +31 -0
  183. package/src/tools/contrast-checker.tool.ts +37 -0
  184. package/src/tools/dislike-analyzer.tool.ts +247 -0
  185. package/src/tools/gradient-generator.tool.ts +250 -0
  186. package/src/tools/image-extraction.tools.ts +289 -0
  187. package/src/tools/index.ts +39 -0
  188. package/src/tools/material-theme.tools.ts +250 -0
  189. package/src/tools/palette-generator.tool.ts +135 -0
  190. package/src/tools/palette-with-locks.tool.ts +221 -0
  191. package/src/tools/registry.ts +142 -0
  192. package/src/tools/simple-tools.ts +37 -0
  193. package/src/tools/theme-matching.tools.ts +334 -0
  194. package/src/types.ts +182 -0
  195. package/src/utils.ts +22 -0
  196. package/tsconfig.json +8 -0
  197. package/vitest.config.js +15 -0
@@ -0,0 +1,261 @@
1
+ # HCT Color System
2
+
3
+ HCT (Hue, Chroma, Tone) is Google's perceptually uniform color space, specifically designed for user interface applications. It forms the foundation of Material Design 3's dynamic color system.
4
+
5
+ ## What is HCT?
6
+
7
+ HCT is a color space that combines the best aspects of LAB (perceptual uniformity) with practical considerations for UI design:
8
+
9
+ - **Hue** (0-360°): The color's position on the color wheel
10
+ - **Chroma** (0-120+): The color's intensity or purity
11
+ - **Tone** (0-100): The color's perceptual lightness
12
+
13
+ ## Why HCT?
14
+
15
+ ### Problem with Traditional Color Spaces
16
+
17
+ Traditional color spaces have significant limitations for UI design:
18
+
19
+ 1. **RGB**: Not perceptually uniform; equal numeric changes don't produce equal visual changes
20
+ 2. **HSL**: Lightness is not perceptually accurate; colors with same L can appear very different
21
+ 3. **LAB**: While perceptually uniform, it's not optimized for UI contrast requirements
22
+
23
+ ### HCT's Solutions
24
+
25
+ HCT addresses these issues with UI-specific optimizations:
26
+
27
+ 1. **Predictable Contrast**: Tone values directly correlate with WCAG contrast ratios
28
+ 2. **Perceptual Uniformity**: Equal changes produce equal perceptual differences
29
+ 3. **No Impossible Colors**: All HCT values represent real, displayable colors
30
+ 4. **Chroma Preservation**: Maintains color intensity across tone changes better than HSL
31
+
32
+ ## Tone and Contrast
33
+
34
+ The most powerful feature of HCT is the predictable relationship between tone values and contrast ratios:
35
+
36
+ ### Contrast Guarantees
37
+
38
+ ```
39
+ Tone Difference | Approximate Contrast Ratio
40
+ ----------------|---------------------------
41
+ 40 | 3:1 (WCAG AA large text)
42
+ 50 | 4.5:1 (WCAG AA normal text)
43
+ 70 | 7:1 (WCAG AAA)
44
+ ```
45
+
46
+ ### Example: Accessible Color Pairs
47
+
48
+ ```javascript
49
+ // Base color
50
+ const primary = { h: 265, c: 50, t: 50 };
51
+
52
+ // Guaranteed accessible combinations
53
+ const onPrimary = { h: 265, c: 50, t: 100 }; // t: 50 → 100 = 50 diff = 4.5:1
54
+ const primaryContainer = { h: 265, c: 25, t: 90 }; // Lower chroma, high tone
55
+ const onPrimaryContainer = { h: 265, c: 50, t: 10 }; // t: 90 → 10 = 80 diff = 7:1+
56
+ ```
57
+
58
+ ## Material Design Integration
59
+
60
+ HCT is the foundation of Material Design 3's color system:
61
+
62
+ ### Tonal Palettes
63
+
64
+ Material Design uses 13 standard tones:
65
+ ```
66
+ [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 95, 99, 100]
67
+ ```
68
+
69
+ Each tone has specific use cases:
70
+ - **0-10**: On-colors for light surfaces
71
+ - **20-40**: Accent and emphasis colors
72
+ - **50**: Medium, often primary color
73
+ - **60-80**: Containers and surfaces
74
+ - **90-100**: Backgrounds and on-colors for dark surfaces
75
+
76
+ ### Color Roles
77
+
78
+ HCT enables semantic color roles with guaranteed contrast:
79
+
80
+ ```javascript
81
+ // Primary color family
82
+ primary: tone(40) // Main brand color
83
+ onPrimary: tone(100) // Text on primary
84
+ primaryContainer: tone(90) // Light container
85
+ onPrimaryContainer: tone(10) // Text on container
86
+
87
+ // Surface colors
88
+ surface: tone(99) // Main background
89
+ onSurface: tone(10) // Text on surface
90
+ surfaceVariant: tone(95) // Secondary background
91
+ onSurfaceVariant: tone(30) // Secondary text
92
+ ```
93
+
94
+ ## Chroma Behavior
95
+
96
+ Chroma in HCT represents color intensity, but unlike saturation in HSL, it maintains perceptual consistency:
97
+
98
+ ### Chroma Ranges
99
+
100
+ - **0-20**: Neutral, grayscale colors
101
+ - **20-40**: Muted, subtle colors
102
+ - **40-60**: Moderate intensity (recommended for UI)
103
+ - **60-80**: Vibrant colors
104
+ - **80+**: Very vibrant (use sparingly)
105
+
106
+ ### Chroma and Tone Interaction
107
+
108
+ Maximum achievable chroma varies by tone:
109
+ ```
110
+ Tone 0-10: Low max chroma (dark colors can't be very colorful)
111
+ Tone 40-60: Highest max chroma (mid-tones most colorful)
112
+ Tone 90-100: Low max chroma (light colors can't be very colorful)
113
+ ```
114
+
115
+ ## Practical Applications
116
+
117
+ ### 1. Theme Generation
118
+
119
+ Generate a complete theme from a single color:
120
+
121
+ ```javascript
122
+ function generateTheme(sourceColor) {
123
+ const hct = toHct(sourceColor);
124
+
125
+ return {
126
+ primary: { ...hct, t: 40 },
127
+ secondary: { h: hct.h + 60, c: hct.c * 0.5, t: 40 },
128
+ tertiary: { h: hct.h + 120, c: hct.c * 0.7, t: 40 },
129
+ error: { h: 25, c: 84, t: 40 },
130
+ neutral: { h: hct.h, c: 4, t: 50 },
131
+ neutralVariant: { h: hct.h, c: 8, t: 50 }
132
+ };
133
+ }
134
+ ```
135
+
136
+ ### 2. Accessible Color Variations
137
+
138
+ Create accessible color variations:
139
+
140
+ ```javascript
141
+ function createAccessiblePair(baseHct, contrastRatio = 4.5) {
142
+ const toneDiff = contrastRatio >= 7 ? 70 :
143
+ contrastRatio >= 4.5 ? 50 : 40;
144
+
145
+ const lighter = { ...baseHct, t: Math.min(100, baseHct.t + toneDiff) };
146
+ const darker = { ...baseHct, t: Math.max(0, baseHct.t - toneDiff) };
147
+
148
+ return baseHct.t > 50 ? darker : lighter;
149
+ }
150
+ ```
151
+
152
+ ### 3. Color Harmonization
153
+
154
+ Harmonize colors to work together:
155
+
156
+ ```javascript
157
+ function harmonize(color1Hct, color2Hct) {
158
+ // Adjust hues to be more harmonious
159
+ const hueDiff = Math.abs(color2Hct.h - color1Hct.h);
160
+
161
+ if (hueDiff > 180) {
162
+ // Colors are opposite, increase harmony
163
+ const targetHue = color1Hct.h + (hueDiff > 270 ? 60 : -60);
164
+ return { ...color2Hct, h: targetHue };
165
+ }
166
+
167
+ return color2Hct;
168
+ }
169
+ ```
170
+
171
+ ## HCT vs Other Color Spaces
172
+
173
+ ### HCT vs LAB
174
+
175
+ | Aspect | HCT | LAB |
176
+ |--------|-----|-----|
177
+ | Perceptual Uniformity | ✅ Optimized for UI | ✅ General purpose |
178
+ | Contrast Prediction | ✅ Direct tone mapping | ❌ Requires calculation |
179
+ | UI Optimization | ✅ Designed for screens | ❌ Designed for all media |
180
+ | Impossible Colors | ❌ None | ✅ Can represent |
181
+
182
+ ### HCT vs HSL
183
+
184
+ | Aspect | HCT | HSL |
185
+ |--------|-----|-----|
186
+ | Perceptual Uniformity | ✅ Yes | ❌ No |
187
+ | Lightness Accuracy | ✅ Perceptual | ❌ Mathematical |
188
+ | Contrast Prediction | ✅ Built-in | ❌ Requires calculation |
189
+ | Designer Familiarity | 🔶 Learning curve | ✅ Well known |
190
+
191
+ ## Advanced Concepts
192
+
193
+ ### CAM16 Foundation
194
+
195
+ HCT is built on the CAM16 color appearance model, which models how humans perceive color under different viewing conditions.
196
+
197
+ ### Viewing Conditions
198
+
199
+ HCT assumes standard viewing conditions:
200
+ - Average surround
201
+ - Adapting luminance of 200 cd/m²
202
+ - 20% background luminance
203
+ - D65 white point
204
+
205
+ ### Gamut Mapping
206
+
207
+ HCT automatically maps colors to the sRGB gamut, ensuring all colors are displayable:
208
+
209
+ ```javascript
210
+ // HCT handles gamut mapping internally
211
+ const vibrantHct = { h: 120, c: 200, t: 50 }; // Very high chroma
212
+ const displayable = hctToRgb(vibrantHct); // Automatically in gamut
213
+ ```
214
+
215
+ ## Best Practices
216
+
217
+ 1. **Use standard tones** for consistency with Material Design
218
+ 2. **Maintain 50+ tone difference** for text on backgrounds
219
+ 3. **Keep chroma between 40-60** for most UI elements
220
+ 4. **Use lower chroma (4-16)** for neutral colors
221
+ 5. **Test with different tones** to ensure accessibility
222
+
223
+ ## Common Patterns
224
+
225
+ ### Dark/Light Theme Switching
226
+
227
+ ```javascript
228
+ // Light theme
229
+ const lightPrimary = { h: 265, c: 50, t: 40 };
230
+ const lightSurface = { h: 265, c: 0, t: 99 };
231
+
232
+ // Dark theme (invert tones)
233
+ const darkPrimary = { h: 265, c: 50, t: 80 };
234
+ const darkSurface = { h: 265, c: 0, t: 10 };
235
+ ```
236
+
237
+ ### Error States
238
+
239
+ ```javascript
240
+ // Standard error colors in HCT
241
+ const error = { h: 25, c: 84, t: 40 }; // Red-orange, high chroma
242
+ const errorContainer = { h: 25, c: 30, t: 90 }; // Muted, light
243
+ const onError = { h: 25, c: 0, t: 100 }; // White
244
+ const onErrorContainer = { h: 25, c: 84, t: 10 }; // Dark red
245
+ ```
246
+
247
+ ## Implementation Details
248
+
249
+ Coolors MCP implements HCT using Google's Material Color Utilities algorithms:
250
+
251
+ 1. **Color Conversion**: Accurate CAM16 to/from RGB conversion
252
+ 2. **Gamut Mapping**: Automatic sRGB gamut clipping
253
+ 3. **Tone Mapping**: Precise tone to luminance conversion
254
+ 4. **Chroma Maximization**: Finding maximum chroma for any hue/tone
255
+
256
+ ## See Also
257
+
258
+ - [Color Spaces](./color-spaces.md) - Comparison with other color models
259
+ - [Material Design](./material-design.md) - HCT in Material Design 3
260
+ - [Accessibility](./accessibility.md) - Using tone for contrast
261
+ - [Theme Matching](./theme-matching.md) - HCT-based matching algorithm
@@ -0,0 +1,396 @@
1
+ # Image Color Analysis
2
+
3
+ Coolors MCP provides advanced image color extraction using Google's Material Color Utilities algorithms, enabling dynamic theme generation from images.
4
+
5
+ ## Overview
6
+
7
+ Image color extraction involves:
8
+ 1. **Quantization** - Reducing colors to a representative set
9
+ 2. **Scoring** - Evaluating colors for UI suitability
10
+ 3. **Selection** - Choosing optimal source colors
11
+ 4. **Theme Generation** - Creating complete color schemes
12
+
13
+ ## The Extraction Process
14
+
15
+ ### 1. Quantization
16
+
17
+ Quantization is a lossy compression process that selects a limited number of colors that best represent the original image.
18
+
19
+ #### Celebi Algorithm
20
+ Coolors MCP uses the Celebi quantizer, which combines:
21
+ - **Wu's algorithm**: Fast color quantization
22
+ - **WSMeans**: Weighted spatial color clustering
23
+
24
+ ```javascript
25
+ // Extract up to 128 representative colors
26
+ const colors = quantize(pixels, 128);
27
+ ```
28
+
29
+ #### How It Works
30
+ 1. **Spatial clustering**: Groups similar colors that appear near each other
31
+ 2. **Color frequency**: Weights colors by how often they appear
32
+ 3. **Perceptual grouping**: Merges perceptually similar colors
33
+ 4. **Output**: Typically 5-128 distinct colors
34
+
35
+ ### 2. Color Scoring
36
+
37
+ Not all colors are suitable for UI themes. The scoring algorithm evaluates colors based on:
38
+
39
+ #### Key Metrics
40
+
41
+ **Chroma Score**
42
+ Colors closer to the target chroma of 48 receive higher scores:
43
+ ```javascript
44
+ chromaScore = 1 - Math.abs(chroma - 48) / 48;
45
+ ```
46
+
47
+ **Population Score**
48
+ More frequent colors score higher:
49
+ ```javascript
50
+ populationScore = pixelCount / totalPixels;
51
+ ```
52
+
53
+ **Color Diversity**
54
+ Promotes visually distinct colors:
55
+ - Higher scores for well-represented hues (30° neighborhood)
56
+ - Penalizes colors too similar to already selected ones
57
+ - Ensures good distribution across color wheel
58
+
59
+ #### Filtering Criteria
60
+ Colors are filtered out if they:
61
+ - Have very low chroma (<15) - too close to grayscale
62
+ - Are extremely rare (<0.01% of pixels)
63
+ - Fall in the "dislike zone" (dark yellow-greens)
64
+ - Are too similar to already selected colors
65
+
66
+ ### 3. Source Color Selection
67
+
68
+ The system selects multiple source colors for theme options:
69
+
70
+ ```javascript
71
+ // Typical selection process
72
+ 1. Extract and score all colors
73
+ 2. Select top-scoring distinct colors (usually 3-5)
74
+ 3. Present as theme options to user
75
+ 4. Use selected color as source for theme generation
76
+ ```
77
+
78
+ ## Image Sources
79
+
80
+ ### Wallpapers
81
+ User device wallpapers provide personalized color schemes:
82
+ - Analyzed on device for privacy
83
+ - Updates dynamically when wallpaper changes
84
+ - Creates cohesive system-wide theming
85
+
86
+ ### App Content
87
+ Content-based colors adapt to current context:
88
+ - **Album art** → Music player theme
89
+ - **Product images** → E-commerce theme
90
+ - **Video thumbnails** → Media player theme
91
+ - **Logos** → Brand-consistent theme
92
+
93
+ ### User Photos
94
+ Personal photos for custom themes:
95
+ - Profile pictures for personal spaces
96
+ - Gallery images for creative apps
97
+ - Artwork for design applications
98
+
99
+ ## Implementation
100
+
101
+ ### Basic Extraction
102
+
103
+ ```javascript
104
+ {
105
+ "name": "extract_image_colors",
106
+ "arguments": {
107
+ "imageData": [/* RGBA pixel array */],
108
+ "maxColors": 5
109
+ }
110
+ }
111
+
112
+ // Returns
113
+ {
114
+ "colors": [
115
+ { "hex": "#6366f1", "population": 0.23, "score": 0.89 },
116
+ { "hex": "#ec4899", "population": 0.15, "score": 0.76 },
117
+ { "hex": "#10b981", "population": 0.12, "score": 0.71 }
118
+ ]
119
+ }
120
+ ```
121
+
122
+ ### Theme from Image
123
+
124
+ ```javascript
125
+ {
126
+ "name": "generate_theme_from_image",
127
+ "arguments": {
128
+ "imageData": [/* RGBA pixel array */],
129
+ "variant": "tonalSpot"
130
+ }
131
+ }
132
+
133
+ // Returns complete Material Design theme
134
+ {
135
+ "source": "#6366f1",
136
+ "schemes": {
137
+ "light": { /* light theme colors */ },
138
+ "dark": { /* dark theme colors */ }
139
+ }
140
+ }
141
+ ```
142
+
143
+ ## Advanced Features
144
+
145
+ ### Dislike Color Detection
146
+
147
+ The system automatically detects and adjusts universally disliked colors:
148
+
149
+ #### The "Bile Zone"
150
+ Dark yellow-greens (reminiscent of biological waste) are universally disliked:
151
+ - **Hue range**: 50-120° (yellow-green)
152
+ - **Chroma**: 20-50
153
+ - **Tone**: 20-50
154
+
155
+ #### Automatic Fixing
156
+ ```javascript
157
+ if (isDisliked(color)) {
158
+ // Shift hue away from dislike zone
159
+ color.hue = adjustHue(color.hue);
160
+ // Increase tone for lighter appearance
161
+ color.tone = Math.max(60, color.tone);
162
+ }
163
+ ```
164
+
165
+ ### Multi-Region Analysis
166
+
167
+ For complex images, analyze different regions:
168
+
169
+ ```javascript
170
+ // Analyze specific image regions
171
+ const regions = [
172
+ { x: 0, y: 0, width: 100, height: 100 }, // Top-left
173
+ { x: 100, y: 100, width: 200, height: 200 } // Center
174
+ ];
175
+
176
+ regions.forEach(region => {
177
+ const colors = extractFromRegion(image, region);
178
+ // Process regional colors
179
+ });
180
+ ```
181
+
182
+ ### Temporal Consistency
183
+
184
+ For video or animated content:
185
+
186
+ ```javascript
187
+ // Extract colors from multiple frames
188
+ const frames = [0, 30, 60, 90, 120];
189
+ const frameColors = frames.map(f => extractFrame(video, f));
190
+
191
+ // Find consistent colors across frames
192
+ const stableColors = findStableColors(frameColors);
193
+ ```
194
+
195
+ ## Color Suitability Scoring
196
+
197
+ ### UI Suitability Factors
198
+
199
+ | Factor | Weight | Description |
200
+ |--------|--------|-------------|
201
+ | Chroma | 40% | Preference for moderate chroma (~48) |
202
+ | Population | 30% | How much of image uses this color |
203
+ | Diversity | 20% | Distinctness from other colors |
204
+ | Accessibility | 10% | Potential for good contrast |
205
+
206
+ ### Scoring Algorithm
207
+
208
+ ```javascript
209
+ function scoreColor(color, population, existingColors) {
210
+ const chromaScore = scoreChroma(color.chroma);
211
+ const popScore = population / totalPopulation;
212
+ const diversityScore = scoreDiversity(color, existingColors);
213
+ const accessScore = scoreAccessibility(color);
214
+
215
+ return (
216
+ chromaScore * 0.4 +
217
+ popScore * 0.3 +
218
+ diversityScore * 0.2 +
219
+ accessScore * 0.1
220
+ );
221
+ }
222
+ ```
223
+
224
+ ## Best Practices
225
+
226
+ ### Image Preparation
227
+
228
+ #### Optimal Images
229
+ - **Resolution**: 200-500px wide (resize larger images)
230
+ - **Format**: RGB/RGBA
231
+ - **Quality**: Avoid heavily compressed images
232
+ - **Content**: Clear subject with distinct colors
233
+
234
+ #### Pre-processing
235
+ ```javascript
236
+ // Resize for performance
237
+ const resized = resizeImage(original, 300);
238
+
239
+ // Enhance contrast if needed
240
+ const enhanced = enhanceContrast(resized, 1.2);
241
+
242
+ // Extract colors
243
+ const colors = extractColors(enhanced);
244
+ ```
245
+
246
+ ### Performance Optimization
247
+
248
+ #### Sampling Strategies
249
+ ```javascript
250
+ // Fast: Sample every 5th pixel
251
+ const fastColors = quantize(pixels, 128, { sampling: 5 });
252
+
253
+ // Quality: Full pixel analysis
254
+ const qualityColors = quantize(pixels, 128, { sampling: 1 });
255
+
256
+ // Adaptive: Based on image size
257
+ const sampling = pixels.length > 100000 ? 5 : 1;
258
+ ```
259
+
260
+ #### Caching
261
+ ```javascript
262
+ // Cache extracted colors
263
+ const cache = new Map();
264
+ const hash = hashImage(imageData);
265
+
266
+ if (cache.has(hash)) {
267
+ return cache.get(hash);
268
+ }
269
+
270
+ const colors = extractColors(imageData);
271
+ cache.set(hash, colors);
272
+ ```
273
+
274
+ ## Use Cases
275
+
276
+ ### Dynamic Theming
277
+ Apps that adapt to content:
278
+ - Music players matching album art
279
+ - News readers matching article images
280
+ - Photo galleries with ambient themes
281
+
282
+ ### Brand Extraction
283
+ Deriving brand colors from logos:
284
+ ```javascript
285
+ const logo = loadImage('logo.png');
286
+ const brandColors = extractColors(logo, {
287
+ maxColors: 3,
288
+ minChroma: 30 // Ensure vibrant colors
289
+ });
290
+ ```
291
+
292
+ ### Palette Generation
293
+ Creating artist palettes from artwork:
294
+ ```javascript
295
+ const artwork = loadImage('painting.jpg');
296
+ const palette = extractColors(artwork, {
297
+ maxColors: 12,
298
+ includeNeutrals: true
299
+ });
300
+ ```
301
+
302
+ ## Integration Examples
303
+
304
+ ### Web Applications
305
+
306
+ ```javascript
307
+ // Extract colors from uploaded image
308
+ async function themeFromUpload(file) {
309
+ const image = await loadImage(file);
310
+ const canvas = createCanvas(image);
311
+ const pixels = getPixelData(canvas);
312
+
313
+ const response = await coolorsMCP.extractColors({
314
+ imageData: pixels,
315
+ maxColors: 5
316
+ });
317
+
318
+ return response.colors[0]; // Use top color
319
+ }
320
+ ```
321
+
322
+ ### React Component
323
+
324
+ ```jsx
325
+ function ImageThemeProvider({ imageUrl, children }) {
326
+ const [theme, setTheme] = useState(null);
327
+
328
+ useEffect(() => {
329
+ extractThemeFromImage(imageUrl).then(setTheme);
330
+ }, [imageUrl]);
331
+
332
+ return (
333
+ <ThemeContext.Provider value={theme}>
334
+ {children}
335
+ </ThemeContext.Provider>
336
+ );
337
+ }
338
+ ```
339
+
340
+ ### Node.js Server
341
+
342
+ ```javascript
343
+ const sharp = require('sharp');
344
+
345
+ async function extractFromBuffer(buffer) {
346
+ // Resize and convert to raw pixels
347
+ const { data, info } = await sharp(buffer)
348
+ .resize(300)
349
+ .raw()
350
+ .toBuffer({ resolveWithObject: true });
351
+
352
+ // Extract colors
353
+ const colors = await coolorsMCP.extractColors({
354
+ imageData: Array.from(data),
355
+ width: info.width,
356
+ height: info.height
357
+ });
358
+
359
+ return colors;
360
+ }
361
+ ```
362
+
363
+ ## Limitations
364
+
365
+ ### Technical Constraints
366
+ - Maximum image size: ~5MB recommended
367
+ - Color count: 128 colors maximum per extraction
368
+ - Processing time: ~100-500ms for typical images
369
+
370
+ ### Accuracy Considerations
371
+ - Compressed images may lose color fidelity
372
+ - Very dark/light images provide limited options
373
+ - Monochrome images need fallback strategies
374
+
375
+ ## Troubleshooting
376
+
377
+ ### Common Issues
378
+
379
+ #### No Suitable Colors Found
380
+ **Cause**: Image too monochrome or low contrast
381
+ **Solution**: Adjust scoring thresholds or provide fallback
382
+
383
+ #### Inconsistent Results
384
+ **Cause**: Image compression or resizing artifacts
385
+ **Solution**: Use higher quality source images
386
+
387
+ #### Performance Problems
388
+ **Cause**: Processing large images
389
+ **Solution**: Resize before extraction
390
+
391
+ ## See Also
392
+
393
+ - [Material Design](./material-design.md) - Theme generation from colors
394
+ - [Color Spaces](./color-spaces.md) - Understanding color models
395
+ - [HCT System](./hct.md) - Perceptual color space
396
+ - [Accessibility](./accessibility.md) - Ensuring extracted colors are usable