chromancy
v2.0.3
Published
The fastest way to steal colors from images in the browser. Extract average, dominant, and palette colors with property analysis, batch processing, and Web Worker support — all in a 15KB package.
Maintainers
Readme
Chromancy
The fastest way to steal colors from images in the browser. Extract average, dominant, and palette colors with property analysis, batch processing, and Web Worker support — all in a 15KB package.
Table of Contents
Features
- 🎨 Average, Dominant & Palette — Extract average color, dominant color, and a full color palette from any image
- 🌈 Multiple Output Formats — Get colors as
rgb,hex,hsl, or{ r, g, b }objects - 📊 Image Properties — Analyze brightness, warmth, saturation, and contrast
- 🚀 Web Worker Support — Offload heavy analysis to a worker thread without blocking the UI
- ⚡ Batch Processing — Analyze multiple images in parallel with a single call
- 💾 URL Caching — Automatically cache results for URL inputs to avoid re-analysis
- 🪶 Lightweight — Only ~15KB minified, zero dependencies
- 🖼️ Flexible Input — Pass an
HTMLImageElementor a URL string directly - 🧊 Alpha Channel Support — Automatically skips fully transparent pixels
Installation
npm install chromancyOr with Yarn:
yarn add chromancyQuick Start
import { chromancy } from 'chromancy';
const result = await chromancy('https://example.com/photo.jpg');
console.log(result.averageColor); // "rgb(128,64,32)"
console.log(result.dominantColor); // "rgb(200,100,50)"
console.log(result.palette); // ["rgb(...)", "rgb(...)", ...]
console.log(result.properties); // { brightness, warmth, saturation, contrast }API Reference
chromancy(source, options)
The main function for extracting colors from an image.
Parameters:
| Parameter | Type | Description |
|-----------|------|-------------|
| source | HTMLImageElement \| string | An image element or a URL string |
| options | ChromancyOptions | (Optional) Configuration options |
Returns: Promise<ChromancyResult>
import { chromancy } from 'chromancy';
// With an image element
const img = document.getElementById('my-image');
const result = await chromancy(img, { paletteSize: 5 });
// With a URL string
const result = await chromancy('https://example.com/photo.jpg', {
outputFormat: 'hex',
paletteSize: 3,
});Runs color analysis in a Web Worker to avoid blocking the main thread. Falls back to chromancy() if Web Workers are not supported.
Parameters: Same as chromancy()
Returns: Promise<ChromancyResult>
paletteSize: 5,
});chromancyBatch(sources, options)
Analyzes multiple images in parallel.
Parameters:
| Parameter | Type | Description |
|-----------|------|-------------|
| sources | Array<HTMLImageElement \| string> | Array of image elements or URL strings |
| options | ChromancyOptions | (Optional) Configuration options |
Returns: Promise<ChromancyResult[]>
import { chromancyBatch } from 'chromancy';
const results = await chromancyBatch([
'https://example.com/1.jpg',
'https://example.com/2.jpg',
'https://example.com/3.jpg',
], { paletteSize: 5 });
// results[0] -> result for 1.jpg
// results[1] -> result for 2.jpg
// results[2] -> result for 3.jpgclearCache()
Clears the URL result cache.
import { chromancy, clearCache } from 'chromancy';
// First call — analyzes the image
await chromancy('https://example.com/photo.jpg');
// Second call — returns cached result instantly
await chromancy('https://example.com/photo.jpg');
// Clear cache when needed
clearCache();rgbToHex(rgb)
Converts an RGB string to a Hex string.
import { rgbToHex } from 'chromancy';
rgbToHex('rgb(128, 64, 32)'); // "#804020"rgbToHsl(rgb)
Converts an RGB string to an HSL string.
import { rgbToHsl } from 'chromancy';
rgbToHsl('rgb(128, 64, 32)'); // "hsl(20, 43%, 31%)"rgbToObject(rgb)
Converts an RGB string to an { r, g, b } object.
import { rgbToObject } from 'chromancy';
rgbToObject('rgb(128, 64, 32)'); // { r: 128, g: 64, b: 32 }Options
| Option | Type | Description | Default |
|--------|------|-------------|---------|
| maxSize | number | Maximum width or height (in pixels) to resize the image for analysis | 100 |
| quantizationLevel | number | Color quantization level. Lower = more color bins (finer detail), Higher = less precision | 32 |
| sampleRate | number | Fraction of pixels to sample (0 to 1). 0.5 = half of pixels | 0.1 |
| paletteSize | number | Number of distinct colors in the palette. Set to 0 to disable | 5 |
| colorScale | number | Normalizes and scales color intensity. 0 = no scaling | 0 |
| outputFormat | string | Output format: 'rgb', 'hex', 'hsl', or 'object' | 'rgb' |
Output Formats
// RGB (default)
const rgb = await chromancy(url, { paletteSize: 3 });
// rgb.averageColor -> "rgb(128,64,32)"
// Hex
const hex = await chromancy(url, { paletteSize: 3, outputFormat: 'hex' });
// hex.averageColor -> "#804020"
// HSL
const hsl = await chromancy(url, { paletteSize: 3, outputFormat: 'hsl' });
// hsl.averageColor -> "hsl(20,43%,31%)"
// Object
const obj = await chromancy(url, { paletteSize: 3, outputFormat: 'object' });
// obj.averageColor -> { r: 128, g: 64, b: 32 }Examples
Vanilla JavaScript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Chromancy Example</title>
</head>
<body>
<img id="my-image" src="photo.jpg" alt="Sample" />
<script type="module">
import { chromancy } from 'chromancy';
const img = document.getElementById('my-image');
chromancy(img, { maxSize: 150, paletteSize: 5 })
.then((result) => {
document.body.style.backgroundColor = result.dominantColor;
console.log('Palette:', result.palette);
})
.catch((err) => console.error(err));
</script>
</body>
</html>React
import { useRef, useEffect } from 'react';
import { chromancy } from 'chromancy';
function ImageAnalyzer() {
const imageRef = useRef(null);
useEffect(() => {
async function analyze() {
if (!imageRef.current) return;
const result = await chromancy(imageRef.current, { paletteSize: 5 });
document.body.style.backgroundColor = result.dominantColor;
}
analyze();
}, []);
return <img ref={imageRef} src="photo.jpg" alt="Sample" style={{ maxWidth: '100%' }} />;
}
export default ImageAnalyzer;TypeScript
import { chromancy, ChromancyOptions, ChromancyResult } from 'chromancy';
const options: ChromancyOptions = {
maxSize: 150,
quantizationLevel: 16,
sampleRate: 0.2,
paletteSize: 5,
outputFormat: 'hex',
};
const result: ChromancyResult = await chromancy('https://example.com/photo.jpg', options);
console.log(result.averageColor); // string (e.g., "#804020")
console.log(result.dominantColor); // string
console.log(result.palette); // string[]
console.log(result.properties); // { brightness, warmth, saturation, contrast }Next.js
Because this library requires the browser's DOM, use dynamic import with ssr: false:
'use client';
import { useRef, useEffect } from 'react';
export default function ImageAnalyzer() {
const imageRef = useRef<HTMLImageElement>(null);
useEffect(() => {
async function analyze() {
if (!imageRef.current) return;
const { chromancy } = await import('chromancy');
const result = await chromancy(imageRef.current, { maxSize: 150, paletteSize: 5 });
document.body.style.backgroundColor = result.dominantColor;
}
analyze();
}, []);
return (
<img
ref={imageRef}
src="/your-image.jpg"
alt="Sample"
style={{ maxWidth: '100%', height: 'auto' }}
/>
);
}Browser Support
Chromancy uses browser DOM APIs (canvas, document) and works in all modern browsers:
| Chrome | Firefox | Safari | Edge | |--------|---------|--------|------| | ✅ 60+ | ✅ 60+ | ✅ 12+ | ✅ 79+ |
⚠️ Note: Cross-origin images require proper CORS headers. The library will throw an error if the image cannot be loaded due to CORS restrictions.
License
MIT © sahajohn
