Skip to content
Tech News
← Back to articles

Okmain: How to pick an OK main colour of an image

read original get Color Palette Generator Tool → more articles
Why This Matters

This article introduces Okmain, a method for selecting a representative, visually appealing main colour from an image by using advanced clustering and colour analysis techniques. It improves upon simple pixel-based approaches, ensuring the chosen colour better reflects the image's vibrancy and diversity, which is valuable for app design and UI consistency. The approach enhances user experience by providing more accurate and attractive colour backgrounds for visual elements.

Key Takeaways

Your app has a card with an image. You want the back of the card to be a solid colour that is somewhat representative of the image and also visually pleasant. How would you do that?

A company I consult for did that by resizing the entire image to 1x1 (a single pixel) and using the colour of the pixel. This is a super popular approach! However, the colours were often dull and muddy even when the original image had vivid colours. It irked me, so I spent a weekend searching for prior art and trying a few tricks to do better. Then, I wrote a library. Inspired by Oklab's naming, it's called Okmain because it looks for an OK main colour:

Here are the tricks I came up with:

colour clustering

Oklab colour calculations

chroma + position cluster sorting

The rest is just implementing the tricks in Rust, writing a Python wrapper, making everything fast and robust, writing documentation, releasing to crates.io and PyPI, and writing this blogpost. Easy !

Colour clustering

Most images have multiple clusters of colours, so simply averaging all colours into one doesn't work well. Take this image: while the green of the field and the blue of the sky are beautiful colours, simply averaging the colours produces a much less exciting colour (source):

Instead, we can find groups of similar colours and average inside the group. K-means is a well-known algorithm for exactly that. We can run it on all pixels, clustering their colours and ignoring the pixel positions (for now).

... continue reading