Skip to content
PixelKit

Colour

Pull a palette out of any photo

Median cut finds the colour groups, k-means polishes them, and every swatch comes with its contrast against white and black.

Processed on your device

Drop a photo to extract its palette

PNG, JPG, WebP. Stays on your device.

How to use

  1. Drop a photo, illustration or screenshot.
  2. Choose how many colours you want, from 3 to 12. The palette updates instantly.
  3. Switch between HEX, RGB and HSL; click a swatch to copy its value.
  4. Check the contrast figures under each swatch to see whether white or black text works on it.
  5. Copy or download the palette as CSS custom properties or JSON.

How it works

The image is first downsampled to at most 160 px on its longest side — around 25,000 pixels, plenty to find dominant colours and fast enough to run instantly. Pixels that are mostly transparent are ignored.

Median cut (Heckbert, 1982) puts all pixels in one box in RGB space, then repeatedly takes the box with the largest spread weighted by pixel count, sorts it along its widest channel and splits it at the median, until there are as many boxes as colours requested. Each box's average becomes a seed colour.

K-means then refines those seeds: each pixel is assigned to its nearest colour by Euclidean distance, each colour moves to the average of its pixels, and this repeats until colours stop moving (at most eight rounds). Seeding with median cut makes the result deterministic — the same image always gives the same palette.

Contrast uses the WCAG 2.x formula: (L1 + 0.05) / (L2 + 0.05), where L is relative luminance. “AA” means at least 4.5:1, enough for body text; “AA large” means at least 3:1.

Worked example

An image that is three-quarters red #e63946 and one-quarter navy #1d3557 yields exactly those two colours with 75% and 25% shares — even if you ask for six. The tool never invents colours that are not there; it says how many distinct groups it found. White text on that red measures about 4.17:1 (fine for large headings, not for body text), while white on the navy exceeds 12:1.

Limitations

  • Distances are measured in RGB, which does not perfectly match human perception; two swatches can look closer than their numbers suggest.
  • Small but visually important accents (a red logo on a large grey wall) can be absorbed into larger groups. Raise the colour count to surface them.
  • Results are averages, so a swatch may be a colour that no single pixel has exactly.

FAQ

Why does the palette look muddier than the photo?

Each swatch is the average of many pixels, and averaging pulls colours toward the middle. Try more colours, or crop to the area you care about before extracting.

Should I use median cut or k-means?

This tool uses both: median cut gives a stable, well-spread starting point and k-means tightens each colour around its cluster. On its own, k-means depends heavily on random starting points.

How do I use the CSS export?

Paste the :root block into your stylesheet and refer to colours as var(--palette-1) and so on. Rename the variables to roles like --brand or --surface once you decide what each colour is for.

Is my photo uploaded for analysis?

No. Pixels are read from a canvas in your browser and the clustering runs in JavaScript on your device.