Every photo is already a palette
The client sent one photograph. A shopfront, warm wood, brass fixtures, and a particular deep green painted on the window frames — the green their whole rebrand is supposed to grow out of. The brief says 'match the photo.' Somewhere between that email and a finished website, someone has to turn pixels into hex codes, and the client cannot do it, because their answer to 'what green is that' is 'the shop green.'
This tool is the bridge. Drop the photo in and it returns the ten colors that actually define it — each as a copyable hex code, each with the percentage of the image it occupies, ranked so the deep green announces itself instead of hiding among the wood tones. No eyedropper hunting, no squinting at the magnifier trying to decide which green pixel is the real one. The algorithm reads every pixel and reports what is actually there.
It is a different job from an eyedropper, and the difference matters. The Color Picker from Image answers 'what exactly is this pixel' — perfect when you know precisely where to point. The extractor answers 'what is this image made of' — the palette-level question, the one you ask when you are starting from a photo and building outward. Designers use both, usually within the same hour.
Pulling a palette in six steps
Load the image
Drag in a JPG, PNG, or WebP. If the subject sits on a big background, crop first — the tool reads the whole image, and backgrounds vote with all their pixels.
Set the palette size
Ten by default, adjustable from one upward. Ten for a working palette, three for a triad, one for a dominant color to theme from. The extraction runs live as you change the number.
Read the swatches
Each swatch shows hex, RGB, and the share of pixels it captured. The order is by population — the first swatch is the color the image is most made of, not the one with the most personality.
Copy what you need
Click any swatch to copy its hex code. One more click copies the whole palette as CSS custom properties, ready to paste into a stylesheet as --brand-green and friends.
Prune the near-duplicates
Photos spawn neighboring shades; delete the ones you will never use. A disciplined palette from a photo is usually five or six colors, not ten.
Extend the winners
Take the two or three keepers into the Tints and Shades Generator and build the full ladder of lighter and darker steps a design system actually consumes.
Inside the median-cut algorithm
The extractor runs median-cut quantization — a clustering method from 1982, when Paul Heckbert needed to display rich photographs on hardware that could only show a handful of colors at once. Forty years later the same algorithm is the standard way to answer 'what colors is this image made of,' because it is fast, deterministic, and its results match intuition remarkably well.
Think of every pixel as a point in three-dimensional space: red, green, and blue are the axes. A sky photo is a elongated cloud of points over in the blue corner; a product shot is a dense cluster near white with a smaller cluster wherever the product's color lives. Median-cut carves that cloud into boxes.
The carving loop: put all pixels in one box. Then, repeatedly, take the box with the most spread — specifically the box whose widest red, green, or blue range is largest — and cut it in two at the median along that axis. The median, not the midpoint: a box with a dense cluster at one end and stragglers at the other splits where the pixels actually are, keeping dense groups intact. Cut until you have as many boxes as the palette size. Average the pixels in each box, count them, and you have your palette: one representative color and one population count per box.
Two honest footnotes. First, the averages are computed on gamma-encoded sRGB values, not linear light — the same shortcut almost every tool takes, and the reason an averaged box can come out very slightly darker than your eye expects. Second, boxes are rectangular in RGB space, and human color perception is not: two visually distant colors can land in one box, and two near-twins can straddle a boundary. In practice both effects are minor, and the pruning step in your workflow absorbs them.
Why two swatches can look like one: RGB distance and the perceptual fix
The footnote above — boxes are rectangular in RGB space while human color perception is not — has a whole discipline behind it. RGB distance treats a 20-point shift in deep blue and a 20-point shift in mid-green as the same size of change; the eye does not, because vision weights green heavily, compresses blues, and judges brightness on its own curve. Two swatches a RGB-identical distance apart can read as twins or as strangers, which is why palettes sometimes carry near-duplicate entries the numbers insist are distinct.
The repair is to measure color distance in a space built for perception. CIELAB, from 1976, plots colors as lightness plus two opponent axes, so numeric distance tracks perceived difference far better; its refinements are bundled into the CIEDE2000 formula. OKLab, published in 2020, does the same job with better hue behavior and trivial computation — and its cylindrical form, OKLCH, is now part of CSS Color Module Level 4, which is why modern stylesheets can declare extracted palettes in oklch() and get visually even lightness ramps for free. In any of these spaces, the distance between two colors is called Delta E, and its scale has usable landmarks:
| Delta E (Lab) | What it means for two swatches |
|---|---|
| below 1 | Imperceptible — the same color for practical purposes |
| 1–2 | Visible only on direct side-by-side inspection |
| 2–10 | Clearly visible difference, still the same family |
| 10–49 | Different colors — a real palette decision |
| 50 and up | Essentially unrelated colors |
The practical use is pruning. When two of ten swatches look nearly identical, their Delta E is usually somewhere under 5 — same family, no design work between them — and one can go. A disciplined rule: merge or delete swatches closer than about Delta E 10 unless the two carry different roles (a surface and its border can legitimately sit close). The same measurement decides which survivor from a multi-photo extraction is 'the same' green across noon and tungsten shots: the swatch that stays within roughly Delta E 10 of itself across lighting conditions is the one the rebrand can trust.
Quantizing a sky, step by step
Here is median-cut on a toy image — eight pixels sampled from a sky, askew with compression noise, exactly the kind of data real photos produce. The pixels: (36,112,232), (40,118,236), (44,120,240), (48,126,244), (50,124,238), (52,126,240), (58,130,246), (60,134,250).
All eight start in one box. The red values span 36 to 60 — a range of 24. Green spans 112 to 134 (range 22), blue spans 232 to 250 (range 18). Red is the widest, so the first cut lands on the red axis, at the median: sorted red values are 36, 40, 44, 48, 50, 52, 58, 60, and the median falls between 48 and 50. Two boxes of four pixels each.
| Box | Pixels | Average color | Hex | Share |
|---|---|---|---|---|
| A (reds 36–48) | 4 | 42, 119, 238 | #2A77EE | 50% |
| B (reds 50–60) | 4 | 55, 129, 244 | #3781F4 | 50% |
Cut box B again — its blue range of 12 is now the widest — and the median along blue falls between 240 and 246. That produces (51,125,239), or #337DEF, and (59,132,248), or #3B84F8. The second value sits one tick from Tailwind's blue-500 #3B82F6, which is the quiet punchline of the exercise: quantize enough sky photographs and you keep landing near the same blue the web already standardized on. The algorithm is not guessing. It is measuring, and the measurement converges.
Input
A 4032×3024 shopfront photo, palette size 10, extraction time well under a second
Output
Ten swatches led by the brass tone at 21.4% and the window green at 9.8% — with six texture-neutrals filling the middle, exactly the palette shape a rebrand pulls from a photograph
On full-size photographs the tool samples rather than reads literally every pixel — at twelve megapixels, every second pixel is already several million data points, and the box geometry stops moving long before you exhaust the image. The determinism survives: same image, same palette, every run.
A rebrand palette, worked from photograph to tokens
The opening scenario deserves its finish. The shopfront photo extracts at ten, prunes to six, and each survivor gets a role before any code is written — the discipline that separates a palette from a screenshot:
| Role | Hex | From the photo | Share | Design use |
|---|---|---|---|---|
| Dominant neutral | #F4EFE6 | Painted wall | 24.6% | Page background |
| Brand primary | #1E3B32 | Window frames — the 'shop green' | 9.8% | Headers, primary buttons |
| Warm metallic | #B08D57 | Brass fixtures | 21.4% | Borders, dividers, small accents |
| Support warm | #8A6240 | Wood tones | 12.1% | Secondary surfaces |
| Ink | #2B2B28 | Signage black | 6.3% | Body text |
| Accent | #C46A4E | Terracotta pot | 2.1% | CTA highlights, links |
Then the contrast check, before the design review rather than during it. The shop green #1E3B32 on the off-white #F4EFE6 measures roughly 10.6 to 1 — comfortably past the 4.5:1 WCAG bar for body text and past the 7:1 AAA line, so it can carry headings and even long-form text. The ink #2B2B28 clears 12:1 and owns paragraphs. The terracotta #C46A4E lands near 3.3:1, which fails body text but passes the 3:1 threshold for large text and graphical elements — a button color and a heading color, not a paragraph color. Thirty seconds of arithmetic, and every role is assigned against evidence rather than vibes.
The last step is tokenization: the six values become CSS custom properties — --surface, --primary, --metal, --wood, --ink, --accent — with the tints-and-shades ladder extending each one before the first component is built. The client's 'match the photo' brief is now six copyable values, a checked contrast sheet, and a theme any developer can apply without ever opening the original photograph.
One honest footnote for the handoff meeting: photo-derived colors are slightly desaturated by real-world lighting, and a tone that reads beautifully in the photograph can sit flat in a UI. The brass #B08D57 may want a small saturation lift before it carries interactive accents. The extraction is the evidence; the final nudge is still a designer's judgment call.
What quantization cannot see
The algorithm is honest, which means it reports the image as it is — not as you wish it were. The gaps between those two things are where the edge cases live.
- Background bias. A white studio backdrop at 60 percent of the frame will dominate every palette. Crop to the subject or accept a palette led by studio white.
- Gradient ladders. A smooth sunset is technically thousands of colors; quantized to ten, you get ten steps of the same hue family. True — but not useful as a palette. Lower the count and pick structure over completeness.
- Noise twins. JPEG compression smears edges into one-off colors that earn their own boxes. Merge or delete them; they are artifacts, not design decisions.
- Local vs. global. A color covering 3 percent of the image can be the whole subject if the subject is small in frame. The percentage is a fact about the image, not a verdict about importance.
- No print values. Hex is screen-native. Pantone and CMYK conversions need physical references; any tool promising exact Pantone matches from a photo is promising something the physics of ink does not support.
- Transparency handling. Transparent PNG pixels are excluded from the count — the right behavior — but a logo rendered on transparency looks different than on a colored background, and the palette only knows the pixels that exist.
What people get wrong building palettes from photos
The extraction itself is reliable; the workflow around it is where palettes go wrong. Five recurring mistakes:
- Promoting the dominant color to brand color. Dominance measures territory, not identity — the color covering a quarter of the frame is usually a wall. The brand-relevant tone is frequently a two-percent accent, and the percentage column exists to assign roles, not rank importance.
- Saving the contrast check for the design review. One minute with the hex values catches the mid-tone accent that fails 4.5:1 before it is baked into twenty components, and the fix is a role reassignment rather than a redesign.
- Laddering before pruning. Generating ten tints of a swatch you will delete tomorrow wastes the ladder and clutters the token file. Extract at ten, prune to the keepers, then build the shade scales for survivors only.
- Extracting from a single photograph. White balance shifts every value in the frame; the same shopfront at noon and under tungsten yields two different palettes. Extract from two or three shots of the same subject and trust the swatches that survive all of them.
- Shipping the raw values as final. Photographic colors arrive slightly desaturated and often a step too dark for screen use. Extraction is evidence gathering; the last nudge — saturation up a notch, lightness up a step — is a human decision the algorithm cannot make for you.
Who pulls colors from images
The palette-from-photo move shows up across the whole design economy:
- Brand designers — pulling a working palette from a client's existing photography when no brand book exists
- Web designers — theming a page from its hero image so headers and accents harmonize with the photography
- Presentation builders — matching slide backgrounds to the photos on them instead of fighting them
- Illustrators — sampling a reference photo's palette to keep a piece inside its mood
- Merch and print designers — pulling shirt or poster palettes from a source photograph
- Developers — generating theme tokens from a marketing image, straight into CSS custom properties
The common thread: a photo exists, color decisions must flow from it, and someone needs the numbers in between. The extractor is the numbers in between. What happens next — ladders, contrast checks, duotones — is where the Tints and Shades Generator and the Duotone Image Maker pick up the thread.
Ten colors, three, or one
Palette size is a design decision before it is a setting. Here is how the options actually differ on the same photograph:
| Palette size | What you learn | What it is for |
|---|---|---|
| 10 | The full inventory: dominants, accents, neutrals, noise | Design system starts, illustration reference |
| 5 | The disciplined cut: dominants and one or two accents | Presentations, merch, most real projects |
| 3 | The triad: the colors that carry the image | Logo work, brand marks, poster comps |
| 1 | The dominant: the color the image is most made of | Page theming, duotone base, background choice |
Our working advice: extract at ten, decide at five. The extra swatches are reconnaissance — they show you the neutral range and the noise floor so you can make an informed cut rather than a blind one. And when the deliverable is a single answer — 'what color is this brand, in one value' — the dominant color at palette size one is the honest, measurable version of an answer that otherwise depends on who you ask.
Input
Two keepers from the shopfront: #1E3B32 for shadows, #F4EFE6 for highlights
Output
A hero image mapped from deep-green shadows to warm off-white highlights — brand-consistent photography without a single original color surviving
Every pixel read, none transmitted
The extraction pipeline has exactly one location: this tab. Your image is decoded into a canvas, the pixel array is read with the standard getImageData call, and the median-cut loop runs in plain JavaScript on that array. The palette renders to the same page. No request leaves the browser with your image attached, because there is nothing for such a request to do.
That property earns its keep on exactly the images people extract colors from — unreleased product shots, client photography under embargo, competitor screenshots being studied. Those files have no business in an upload queue on a color-tool server. Here the queue does not exist, the retention policy is the closing of the tab, and the whole thing still works with the network unplugged.
Color extraction questions, answered
What is a dominant color in an image?
It is the color that occupies the most visual territory — not the loudest one, the largest one. A sky photo's dominant color is whichever band of blue covers the most pixels. Extractors compute this with a quantization algorithm that clusters similar pixels into groups, averages each group, and ranks the groups by how many pixels they captured. The top of that ranking is your dominant color, complete with a percentage.
Why does white or gray dominate my extracted palette?
Because it dominates your image. Product photos on white backgrounds, screenshots with light UI, scans with paper margins — the background pixels outnumber the subject every time. Crop tightly around the subject before extracting, or the algorithm will correctly report that your photo is mostly a studio backdrop. The extractor is not wrong; the input is just mostly background.
How many colors should I extract?
Ten is the default because it captures a full working palette — a couple of dominants, the accents, and the neutrals. Three is right when you need a logo-style triad. One is right when you are theming something from the photo, like a page background or a duotone base. Start at ten, delete what you do not need; deleting is faster than re-running.
Can this tool give me Pantone or CMYK matches?
It gives you hex, RGB, and HSL — the screen-native values. Pantone is a physical ink system and CMYK is a device-dependent print process; neither can be matched honestly from screen values alone without a printed reference. Treat the extracted hex as the starting point for a conversation with your printer, not the end of it.
Why are two of my ten swatches almost identical?
Photos rarely contain clean color families — they contain gradients, compression noise, and focus falloff, all of which spawn near-identical neighbor colors. A quantizer told to find ten boxes will find ten boxes, even if two are separated by a few RGB values. Merge or delete the near-duplicates, or drop the count to eight and let the algorithm fold them together.
Does the extractor handle transparent PNGs?
Yes, and the transparent pixels are skipped rather than counted as anything. A logo on a transparent background is analyzed by its visible pixels only, which is what you want — including transparent pixels as black or white is a classic bug in naive extractors and it quietly poisons the palette.
Is my image uploaded anywhere to extract the colors?
No. The pixels are read from a browser canvas on your machine, the quantization runs in JavaScript in the same tab, and the palette appears on screen. There is no upload, no processing queue, and no stored copy of your image — which matters when the source is an unreleased brand asset.
How do I turn an extracted palette into accessible design tokens?
Check contrast before assigning roles: body text needs 4.5:1 against its background and large text 3:1 under WCAG. A deep extracted tone like #1E3B32 on an off-white like #F4EFE6 measures about 10.6:1 — past the AAA line — while a mid terracotta near #C46A4E lands around 3.3:1, which suits buttons and headings but fails paragraphs. Give the ink role to whichever extracted color clears 12:1, and treat the 3:1 tier as large-display territory.
Should the dominant color be my brand color?
Usually not. Dominance measures territory, not identity — the color covering a quarter of a photo is often a wall or a backdrop, while the tone that carries the brand may hold two percent of the frame. Read the palette with the photo beside you and choose by meaning, then let the percentages assign hierarchy: large-share colors become backgrounds and surfaces, small-share colors become accents and calls to action.
How do I get a consistent palette across many photos?
Extract from several photos of the same subject and keep only the swatches that recur. Lighting varies shot to shot, but underlying surfaces repeat — a color that appears in every extraction at roughly the same value is a property of the subject, and a color that appears once is a property of that afternoon's light. Three extractions are usually enough to separate the two.
What is Delta E?
Delta E is the distance between two colors measured in a perceptual color space — CIELAB by convention, with CIEDE2000 as the refined formula. It converts 'how different do these look' into a number: below 1 is imperceptible, 1–2 is visible side by side, and past 10 the colors read as genuinely different. Palette work uses it to decide when two swatches are effectively duplicates and one should be pruned.
Should I convert my extracted palette to OKLCH?
Worth considering if you are building a modern CSS system. OKLCH expresses each color as lightness, chroma, and hue in a perceptually uniform space, so a ladder of lightness steps — 45%, 55%, 65% — looks evenly spaced to the eye, which RGB hex values never guarantee. All current major browsers support oklch() as of 2023. Keep the hex values alongside for tooling and older embeds, and use OKLCH where the palette becomes a scale rather than a set of fixed swatches.
Where the palette goes next
A freshly extracted palette is a starting point, and three tools turn it into finished decisions:
- Color Picker from Image — the pixel-exact companion, for when you know exactly which point in the photo matters
- Tints and Shades Generator — expand any extracted hex into the full ladder of lighter and darker steps
- Duotone Image Maker — put two extracted colors to work directly on an image
The sequence designers keep repeating: extract the photo's palette at ten, prune to three, ladder the keepers into tints and shades, and theme the layout from the results. One photograph in, a coherent color system out — and every number along the way copied with a click.
Sources and further reading
Sources and further reading
- Leptonica: Color Quantization (Dan Bloomberg's practical notes on median-cut)(leptonica.com)
- MDN Web Docs: CanvasRenderingContext2D.getImageData()(developer.mozilla.org)
- W3C CSS Color Module Level 4(w3.org)
- MDN Web Docs: Canvas API(developer.mozilla.org)
- ICC — sRGB color space profile(color.org)
We cite primary sources (standards bodies, government agencies, official documentation) wherever they exist so you can verify every number on this page yourself.