Skip to content
PaletteViva

How image palette extraction works

Almost every palette extractor on the web is called a quantiser, and most of them are averages. That is the whole reason a sunset comes back as six shades of grey. This page explains what is actually happening to your pixels, and what to look for when a tool gives you a palette you do not recognise.

First: why the obvious approach fails

The obvious approach is to shrink the image and read the small version. Average a 1000-pixel-wide photo down to 40 pixels and you have 40 colours. It is fast, it fits in three lines of code, and it is wrong in two separate ways.

The first is interpolation. Resizing blends neighbouring pixels together, and blending red with green in RGB arithmetically produces a muddy brown that exists nowhere in the photograph. Red and green are not two points on a line with brown in the middle; they are two directions. The second is proportion. A photograph spends most of its pixels on mid-tone gradients — sky, skin, walls — so the colours that dominate by count are the ones nobody was looking at. The colour you actually wanted might be one percent of the image.

Quantisation: reducing thousands of colours to a few

A 12-megapixel photograph contains up to a few hundred thousand distinct colours, so every extractor has to reduce that set. There are four standard ways, and they differ less in result than in reputation.

  • Uniform quantisation — divide each channel into fixed bands, such as 32 steps of 8. Trivial to implement, and it produces histogram artefacts: a smooth gradient gets sliced at arbitrary RGB boundaries rather than at colour boundaries you can see.
  • Median cut — repeatedly split the set of colours along its widest axis so each group holds a similar number of pixels. Efficient, deterministic, and the workhorse of GIF-era palette generation. Where it splits can leave a palette that is technically representative and visually lopsided.
  • Octree quantisation — merge colours in a tree indexed by bit precision, cheap and streaming-friendly, which is why it dominates video codecs. Its merge order is fixed, so it can quietly erase the least common colours, which are often the ones that give an image its character.
  • k-means clustering — iteratively group colours around their means until the groups stop moving. The best quality per colour on typical photographs, and the most sensitive to where you start: run it with a bad initial guess and two clusters land on the same region of colour while another goes empty.

PaletteViva uses median cut to choose good starting points and k-means to refine them, in a colour space described below. That combination is not exotic — it is the standard professional answer — and the difference from the average web tool is mostly in the two decisions that follow.

The colour space is the part that gets skipped

Clustering needs to know how far apart two colours are, and in RGB that question has no sensible answer. RGB is a device format: its three axes are how much light each of three primaries emits, not how different two colours look. In sRGB, #000000 and #0000ff sit 255 units apart while #0000ff and #00ffff sit 255 units apart too — yet one pair is a black-to-blue jump nobody would call a small difference and the other is a shade change within one hue.

A perceptually uniform space fixes that by making equal distances mean equal perceived differences. OKLab, published in 2020 and now the basis of perceptual work in modern CSS, does this well and computes quickly. Cluster in OKLab and two colours that land in the same group are ones you would also have put together; the group centres then correspond to colours a person would name.

The medoid: never return a colour that is not in the image

Here is the detail that separates a palette you trust from one you do not. A cluster has a centroid — the mathematical mean of its members — and that mean is almost never an actual pixel. Averaging two real colours produces a third colour that the image never contained. That is where "average" palettes come from, and it is why a palette can look plausible while containing nothing you can find in the picture.

The fix is to use the cluster's medoid instead: the real pixel closest to the centroid. Clusters still decide which colours win; the values returned are pixels that exist. Every swatch in our palette extractor is a pointer to a specific coordinate in your file, which is also why clicking a swatch can take you to the place the colour came from.

Flat artwork is not a photograph

A logo, an illustration or a screenshot of an interface contains a few dozen distinct colours, and every pixel is one of them. Clustering that kind of image is actively harmful: it will happily merge your brand red with your brand orange and hand back the beige in between. When the number of distinct colours is small, the right algorithm is not clustering but counting — find the exact colours, keep the ones that cover the most area, and drop anything too close to something already kept. That is what our extractor does, and it is why a logo's palette comes back as the logo's colours.

Why "give me eight colours" is the wrong question

More swatches stop being useful sooner than people expect. Past roughly a dozen, additional entries are perceptually near-identical, so the palette stops conveying information and starts asking you to make decisions about nothing. Five to eight is where most work lives.

A second question hides behind the first: which eight? Most tools answer only "the most common". But the most saturated colours in a grey photograph, and the quietest tones in a colourful one, are both legitimate answers to a legitimate need. Our extractor offers dominance, even coverage, vibrancy and mutedness as separate rules over the same set of real colours, because "the palette the image is made of" and "the palette I want to design with" are different requests.

A method for checking any extractor

  1. Use an image you know. A logo with five known brand colours is the fastest test there is: a clustering extractor will hand you blends.
  2. Look for near-duplicates. Two swatches a fraction of a step apart mean the tool did not deduplicate, so its palette is shorter than it looks.
  3. Check whether the colours exist. Search the image for the exact hex value. If it is not there, the palette is an average.
  4. Try the same image twice. A palette that changes between runs came from random seeds, which means you cannot reproduce your own result.
  5. Read the percentages. A palette with no proportions hides the fact that its most prominent swatch covers 0.3% of the picture.

Ready to try it on your own file? Extract a palette from an image , or start from a single pixel with the image color picker . If you want the vocabulary for what comes out — hex, RGB, HSL, OKLCH — that is covered in the formats explained .