Skip to content

Commit f8c5ba9

Browse files
author
James Campbell
committed
Add browser-side JavaScript/TypeScript library (swatchify npm package)
Port of the Go color extraction library for client-side use: - K-means++ clustering algorithm for dominant color extraction - Zero runtime dependencies, ~2KB gzipped - Accepts File, Blob, HTMLImageElement, Canvas, ImageData, or URL - Includes drag-drop demo page
1 parent 01e318e commit f8c5ba9

File tree

11 files changed

+3344
-0
lines changed

11 files changed

+3344
-0
lines changed

js/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
node_modules/
2+
dist/
3+
*.log
4+
.DS_Store

js/README.md

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
# swatchify
2+
3+
Extract dominant colors from images using k-means clustering — browser-only, zero dependencies.
4+
5+
## Install
6+
7+
```bash
8+
npm install swatchify
9+
```
10+
11+
## Usage
12+
13+
```ts
14+
import { extractColors, generatePaletteCanvas } from 'swatchify';
15+
16+
// From file input
17+
const file = document.querySelector('input[type="file"]').files[0];
18+
const colors = await extractColors(file);
19+
20+
console.log(colors);
21+
// [
22+
// { hex: '#4A90D9', percentage: 32.5, rgb: { r: 74, g: 144, b: 217 } },
23+
// { hex: '#2C3E50', percentage: 24.1, rgb: { r: 44, g: 62, b: 80 } },
24+
// ...
25+
// ]
26+
27+
// Generate a palette canvas
28+
const canvas = generatePaletteCanvas(colors, 500, 100);
29+
document.body.appendChild(canvas);
30+
```
31+
32+
## API
33+
34+
### `extractColors(input, options?)`
35+
36+
Extract dominant colors from an image.
37+
38+
**Input types:**
39+
- `HTMLImageElement`
40+
- `HTMLCanvasElement`
41+
- `ImageData`
42+
- `File` or `Blob`
43+
- URL string (including data URLs)
44+
45+
**Options:**
46+
47+
| Option | Type | Default | Description |
48+
|--------|------|---------|-------------|
49+
| `numColors` | number | 5 | Number of colors to extract |
50+
| `quality` | number | 50 | Quality 0-100 (lower = faster) |
51+
| `excludeWhite` | boolean | false | Filter out near-white colors |
52+
| `excludeBlack` | boolean | false | Filter out near-black colors |
53+
| `minContrast` | number | 0 | Minimum distance between colors |
54+
| `colorThreshold` | number | 30 | Threshold for white/black detection |
55+
56+
**Returns:** `Promise<ExtractedColor[]>`
57+
58+
### `generatePaletteCanvas(colors, width?, height?)`
59+
60+
Create a canvas element showing the color palette.
61+
62+
```ts
63+
const canvas = generatePaletteCanvas(colors, 600, 120);
64+
```
65+
66+
### `generatePaletteDataURL(colors, width?, height?)`
67+
68+
Get the palette as a PNG data URL.
69+
70+
```ts
71+
const dataUrl = generatePaletteDataURL(colors);
72+
img.src = dataUrl;
73+
```
74+
75+
### `getContrastColor(rgb)`
76+
77+
Get black or white text color for optimal contrast on a background.
78+
79+
```ts
80+
import { getContrastColor } from 'swatchify';
81+
82+
const textColor = getContrastColor({ r: 74, g: 144, b: 217 });
83+
// '#FFFFFF'
84+
```
85+
86+
## Types
87+
88+
```ts
89+
interface ExtractedColor {
90+
hex: string; // e.g., "#4A90D9"
91+
percentage: number; // e.g., 32.5
92+
rgb: { r: number; g: number; b: number };
93+
}
94+
95+
interface ExtractOptions {
96+
numColors?: number;
97+
quality?: number;
98+
excludeWhite?: boolean;
99+
excludeBlack?: boolean;
100+
minContrast?: number;
101+
colorThreshold?: number;
102+
}
103+
```
104+
105+
## Development
106+
107+
```bash
108+
cd js
109+
110+
# Install dependencies
111+
npm install
112+
113+
# Run example dev server
114+
npm run dev
115+
116+
# Build library
117+
npm run build
118+
```
119+
120+
## How it works
121+
122+
1. Image is loaded and optionally downscaled based on quality setting
123+
2. Pixels are extracted via Canvas API
124+
3. K-means++ clustering finds dominant color clusters
125+
4. Colors are filtered (white/black exclusion, min contrast)
126+
5. Results sorted by dominance percentage
127+
128+
## License
129+
130+
MIT

0 commit comments

Comments
 (0)