{"id":13396865,"url":"https://github.com/lokesh/color-thief","last_synced_at":"2026-03-04T21:03:46.414Z","repository":{"id":1769792,"uuid":"2688455","full_name":"lokesh/color-thief","owner":"lokesh","description":"Grab the color palette from an image using just Javascript.  Works in the browser and in Node.","archived":false,"fork":false,"pushed_at":"2024-10-09T21:03:37.000Z","size":1973,"stargazers_count":13079,"open_issues_count":76,"forks_count":1322,"subscribers_count":171,"default_branch":"master","last_synced_at":"2025-05-14T09:02:19.955Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://lokeshdhakar.com/projects/color-thief/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lokesh.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2011-11-01T15:33:12.000Z","updated_at":"2025-05-14T00:05:25.000Z","dependencies_parsed_at":"2024-01-03T06:49:23.586Z","dependency_job_id":"728b6f03-fc7e-4427-9a0c-458a1964eefc","html_url":"https://github.com/lokesh/color-thief","commit_stats":{"total_commits":155,"total_committers":18,"mean_commits":8.61111111111111,"dds":0.1806451612903226,"last_synced_commit":"4dc3bb0b43250f0d006278998aa91c4156f77cc3"},"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lokesh%2Fcolor-thief","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lokesh%2Fcolor-thief/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lokesh%2Fcolor-thief/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lokesh%2Fcolor-thief/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lokesh","download_url":"https://codeload.github.com/lokesh/color-thief/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254110373,"owners_count":22016391,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-30T18:01:05.319Z","updated_at":"2026-03-04T21:03:46.406Z","avatar_url":"https://github.com/lokesh.png","language":"JavaScript","funding_links":[],"categories":["JavaScript","TypeScript","others","其他_机器视觉","Colors","Tools","Uncategorized"],"sub_categories":["资源传输下载","Visual Python","Uncategorized"],"readme":"# Color Thief\n\n\u003e Extract dominant colors and palettes from images in the browser and Node.js.\n\n[![npm version](https://img.shields.io/npm/v/colorthief)](https://www.npmjs.com/package/colorthief)\n[![npm bundle size](https://img.shields.io/bundlephobia/minzip/colorthief)](https://bundlephobia.com/package/colorthief)\n[![types](https://img.shields.io/npm/types/colorthief)](https://www.npmjs.com/package/colorthief)\n\n## Install\n\n```bash\nnpm install colorthief\n```\n\nOr load directly from a CDN:\n\n```html\n\u003cscript src=\"https://unpkg.com/colorthief@3/dist/umd/color-thief.global.js\"\u003e\u003c/script\u003e\n```\n\n## Quick Start\n\n```js\nimport { getColorSync, getPaletteSync, getSwatches } from 'colorthief';\n\n// Dominant color\nconst color = getColorSync(img);\ncolor.hex();      // '#e84393'\ncolor.css();      // 'rgb(232, 67, 147)'\ncolor.isDark;     // false\ncolor.textColor;  // '#000000'\n\n// Palette\nconst palette = getPaletteSync(img, { colorCount: 6 });\npalette.forEach(c =\u003e console.log(c.hex()));\n\n// Semantic swatches (Vibrant, Muted, DarkVibrant, etc.)\nconst swatches = await getSwatches(img);\nswatches.Vibrant?.color.hex();\n```\n\n## Features\n\n- **TypeScript** — full type definitions included\n- **Browser + Node.js** — same API, both platforms\n- **Sync \u0026 async** — synchronous browser API, async for Node.js and Web Workers\n- **Live extraction** — `observe()` watches video, canvas, or img elements and emits palette updates reactively\n- **Web Workers** — offload quantization off the main thread with `worker: true`\n- **Progressive extraction** — 3-pass refinement for instant rough results\n- **OKLCH quantization** — perceptually uniform palettes via `colorSpace: 'oklch'`\n- **Semantic swatches** — Vibrant, Muted, DarkVibrant, DarkMuted, LightVibrant, LightMuted\n- **Rich Color objects** — `.hex()`, `.rgb()`, `.hsl()`, `.oklch()`, `.css()`, contrast ratios, text color recommendations\n- **WCAG contrast** — `color.contrast.white`, `color.contrast.black`, `color.contrast.foreground`\n- **AbortSignal** — cancel in-flight extractions\n- **CLI** — `colorthief photo.jpg` with JSON, CSS, and ANSI output\n- **Zero runtime dependencies**\n\n## API at a Glance\n\n| Function | Description |\n|---|---|\n| `getColorSync(source, options?)` | Dominant color (sync, browser only) |\n| `getPaletteSync(source, options?)` | Color palette (sync, browser only) |\n| `getSwatchesSync(source, options?)` | Semantic swatches (sync, browser only) |\n| `getColor(source, options?)` | Dominant color (async, browser + Node.js) |\n| `getPalette(source, options?)` | Color palette (async, browser + Node.js) |\n| `getSwatches(source, options?)` | Semantic swatches (async, browser + Node.js) |\n| `getPaletteProgressive(source, options?)` | 3-pass progressive palette (async generator) |\n| `observe(source, options)` | Watch a source and emit palette updates (browser only) |\n| `createColor(r, g, b, population)` | Build a Color object from RGB values |\n\n### Options\n\n| Option | Default | Description |\n|---|---|---|\n| `colorCount` | `10` | Number of palette colors (2–20) |\n| `quality` | `10` | Sampling rate (1 = every pixel, 10 = every 10th) |\n| `colorSpace` | `'oklch'` | Quantization space: `'rgb'` or `'oklch'` |\n| `worker` | `false` | Offload to Web Worker (browser only) |\n| `signal` | — | `AbortSignal` to cancel extraction |\n| `ignoreWhite` | `true` | Skip white pixels |\n\n### Color Object\n\n| Property / Method | Returns |\n|---|---|\n| `.rgb()` | `{ r, g, b }` |\n| `.hex()` | `'#ff8000'` |\n| `.hsl()` | `{ h, s, l }` |\n| `.oklch()` | `{ l, c, h }` |\n| `.css(format?)` | `'rgb(255, 128, 0)'`, `'hsl(…)'`, or `'oklch(…)'` |\n| `.array()` | `[r, g, b]` |\n| `.toString()` | Hex string (works in template literals) |\n| `.textColor` | `'#ffffff'` or `'#000000'` |\n| `.isDark` / `.isLight` | Boolean |\n| `.contrast` | `{ white, black, foreground }` — WCAG ratios |\n| `.population` | Raw pixel count |\n| `.proportion` | 0–1 share of total |\n\n## Browser\n\n```js\nimport { getColorSync, getPaletteSync } from 'colorthief';\n\nconst img = document.querySelector('img');\nconst color = getColorSync(img);\nconsole.log(color.hex());\n\nconst palette = getPaletteSync(img, { colorCount: 5 });\n```\n\nAccepts `HTMLImageElement`, `HTMLCanvasElement`, `HTMLVideoElement`, `ImageData`, `ImageBitmap`, and `OffscreenCanvas`.\n\n### Live extraction with observe()\n\n```js\nimport { observe } from 'colorthief';\n\n// Watch a video and update ambient lighting as it plays\nconst controller = observe(videoElement, {\n    throttle: 200,    // ms between updates\n    colorCount: 5,\n    onChange(palette) {\n        updateAmbientBackground(palette);\n    },\n});\n\n// Stop when done\ncontroller.stop();\n```\n\nWorks with `\u003cvideo\u003e`, `\u003ccanvas\u003e`, and `\u003cimg\u003e` elements. For images, it uses a MutationObserver to detect `src` changes. For video and canvas, it polls using requestAnimationFrame with throttle.\n\n## Node.js\n\n```js\nimport { getColor, getPalette } from 'colorthief';\n\nconst color = await getColor('/path/to/image.jpg');\nconsole.log(color.hex());\n\nconst palette = await getPalette(Buffer.from(data), { colorCount: 5 });\n```\n\nAccepts file paths and Buffers. Uses [sharp](https://sharp.pixelplumbing.com/) for image decoding.\n\n## CLI\n\n```bash\n# Dominant color\ncolorthief photo.jpg\n\n# Color palette\ncolorthief palette photo.jpg\n\n# Semantic swatches\ncolorthief swatches photo.jpg\n```\n\n### Output formats\n\n```bash\n# Default: ANSI color swatches\ncolorthief photo.jpg\n# ▇▇ #e84393\n\n# JSON with full color data\ncolorthief photo.jpg --json\n\n# CSS custom properties\ncolorthief palette photo.jpg --css\n# :root {\n#     --color-1: #e84393;\n#     --color-2: #6c5ce7;\n# }\n```\n\n### Options\n\n```bash\ncolorthief palette photo.jpg --count 5        # Number of colors (2-20)\ncolorthief photo.jpg --quality 1              # Sampling quality (1=best)\ncolorthief photo.jpg --color-space rgb        # Color space (rgb or oklch)\n```\n\nStdin is supported — use `-` or pipe directly:\n\n```bash\ncat photo.jpg | colorthief -\n```\n\nMultiple files are supported. Output is prefixed with filenames, and `--json` wraps results in an object keyed by filename.\n\n## Links\n\n- [Demo page \u0026 live examples](https://lokeshdhakar.com/projects/color-thief/)\n- [GitHub](https://github.com/lokesh/color-thief)\n- [npm](https://www.npmjs.com/package/colorthief)\n\n## Contributing\n\n```bash\nnpm run build          # Build all dist formats\nnpm run test           # Run all tests (Mocha + Cypress)\nnpm run test:node      # Node tests only\nnpm run test:browser   # Browser tests (requires npm run dev)\nnpm run dev            # Start local server on port 8080\n```\n\n## Releasing\n\n```bash\n# 1. Make sure you're on master with a clean working tree\ngit status\n\n# 2. Run the full test suite\nnpm run build\nnpm run test:node\nnpm run test:browser   # requires npm run dev in another terminal\n\n# 3. Preview what will be published\nnpm pack --dry-run\n\n# 4. Tag and publish\nnpm version \u003cmajor|minor|patch\u003e   # bumps version, creates git tag\nnpm publish                       # builds via prepublishOnly, then publishes\ngit push \u0026\u0026 git push --tags\n```\n\n## License\n\n[MIT](LICENSE) - Lokesh Dhakar\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flokesh%2Fcolor-thief","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flokesh%2Fcolor-thief","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flokesh%2Fcolor-thief/lists"}