Image Color Extractor
Extract the dominant colors from any image
Drag & drop an image here
or click to browse
Supports JPEG, PNG, WebP, GIF
Extraction Settings
Extracted Palette
Click a swatch to copy its hex value.
CSS Variables
Upload an image and the color extractor returns its dominant colors as hex and RGB swatches, sorted from dark to light and ready to copy into CSS. It runs entirely in the browser using the Canvas API, so a 4K photo is analyzed in milliseconds without any upload. The result is a small, reusable palette drawn from the image’s actual pixels rather than a set of guessed complementary colors.
How Median-Cut Quantization Works
Median cut treats every pixel as a point in RGB space and builds a palette by repeatedly subdividing that cloud:
- Downscale the image so its longest edge is 100 pixels — a 4000×3000 photo becomes 100×75, or 7,500 pixels to analyze.
- Put every pixel into one bucket.
- Find the bucket with the widest spread on any single channel (red, green, or blue).
- Sort that bucket by the widest channel and split it at the median into two buckets.
- Repeat until the requested number of buckets exists or none can be split further.
- Average the pixels in each bucket to produce the final color.
Because the split always targets the widest channel first, the buckets end up spread across the image’s true color range. No random numbers are involved, which is what makes the output reproducible.
Step by Step
- Upload — drag and drop a JPEG, PNG, WebP, or GIF, or click to browse. Nothing is sent to a server.
- Choose a count — 5, 6, or 8 colors. The palette re-renders instantly.
- Inspect — each swatch shows its hex value and
rgb(...)triple. - Copy — click a swatch to copy its hex, use “Copy All Hex Values” for a newline-separated list, or copy the generated
:rootblock of CSS custom properties (--color-1through--color-8).
A Worked Example: Four Pixels, Two Colors
Requesting 2 colors from four pixels — (10,10,10), (12,12,12), (240,250,240), (235,245,235):
- Green has the widest spread (10 to 250, range 240), so the bucket is sorted by green.
- Splitting after the second pixel gives
{(10,10,10), (12,12,12)}and{(235,245,235), (240,250,240)}. - Averaging each bucket yields
rgb(11,11,11)→#0b0b0bandrgb(238,248,238)→#eef8ee.
Two buckets, one very dark and one very light, which is exactly what the input describes. A real photo simply has thousands of such buckets and a more interesting split order.
Why External Image URLs Are Blocked (CORS)
The extraction step calls ctx.getImageData(0, 0, w, h) to read raw pixels. Browsers protect users from cross-origin pixel theft by “tainting” a canvas whenever it draws an image from another origin without CORS headers. Once tainted, getImageData throws a SecurityError and the tool cannot analyze anything. Some sites do send Access-Control-Allow-Origin, in which case a URL image would work — but you cannot rely on that, and failing on half your images would be worse than not offering URLs at all. Uploading the file avoids the problem because a device file loaded via FileReader becomes a data URL that does not taint the canvas. The practical trade-off is one extra drag-and-drop; the benefit is that no image ever touches a network.
When to Reach for Another Tool
This tool extracts colors that are already in an image. If you want a harmonious scheme generated from a brand color, use the Color Palette Generator. If you need to sample an exact pixel from an on-screen design, use the Color Picker. If the image needs cropping or flattening before the palette looks right, run it through the Image Cropper first.
Practical Tips for Better Palettes
- Crop out irrelevant borders first. A white margin or a browser chrome strip can occupy so many pixels that it dominates a bucket, because the downscale preserves proportions. Trim it in an editor before uploading.
- Ask for 5 when in doubt. Fewer buckets means each is a broader average, which usually matches the image’s overall mood better than eight narrowly split shades.
- Expect averages, not exact pixels. A photo of grass has no single green; the swatch is a representative average, not a color that exists at any one pixel.
- Copy the CSS variables, not just the hexes. The generated
:rootblock names them--color-1onward and pastes straight into a project, which keeps a palette consistent across components.
Photos, Logos, and Screenshots
A logo with flat fills produces clean, repeatable swatches and is the ideal input. A photograph produces averages, because median cut merges thousands of nearby pixels into each bucket. Screenshots sit in between: large flat UI colors survive the downscale well, but antialiased text and soft gradients can smear across buckets.
Related Tools
- Color Palette Generator — Build harmonious schemes from a single seed color.
- Color Picker — Pick and convert colors between HEX, RGB, and HSL.
- Image Compressor — Shrink an image before extracting its colors.
- Image Cropper — Crop, rotate, and flip before extraction.
- Color Name Finder — Turn a hex value into its closest named color.
Frequently Asked Questions
How does the color extraction actually work?
The image is downscaled so its longest edge is at most 100 pixels, then median-cut quantization repeatedly splits the color space at its widest channel and averages each resulting group. The method is deterministic, so the same image always yields the same palette — no random seeding like k-means.
Why can't I paste an image URL instead of uploading a file?
Canvas security. Reading pixels requires `ctx.getImageData`, and the browser blocks it on a canvas tainted by a cross-origin image that did not send permissive CORS headers. Rather than fail unpredictably, the tool only accepts files from your device, loaded through a data URL that never taints the canvas.
Why are the choices limited to 5, 6, or 8 colors?
A palette of 5–8 colors captures the dominant tones of most photos and screenshots without drowning you in near-duplicate shades. If the image contains fewer unique colors than you requested, median cut runs out of buckets to split and returns fewer swatches.
In what order are the extracted colors shown?
Darkest to lightest, measured by Rec. 601 perceived luminance (0.299R + 0.587G + 0.114B). That ordering makes it obvious which swatch works as a dark background, which is mid-tone, and which is a light accent.
Why do I sometimes get fewer colors than I asked for?
Median cut stops when no bucket can be split further, which happens when there are fewer distinct colors in the image than requested. A two-color logo asked for 8 swatches will return 2, not 8 near-identical repeats.
Do transparent pixels change the palette?
Yes, and usually not in a helpful way. The algorithm ignores the alpha channel and averages the RGB values underneath, so fully transparent regions still contribute whatever color their hidden pixels hold — often black or white. Crop or flatten transparency first if it is distorting the result.
Reviewed by the HandyTools Hub team · Last updated