Skip to content

Sheraff/palette

Repository files navigation

Color palette extraction

Warning

This library is still in development and the API is subject to change.

  • The entry point is extractColors.ts
  • use pnpm test to launch the tests
  • use pnpm serve to get a visual preview of what is happening on localhost:3000

With an emphasis on

  • Accuracy, using a clustering algorithm and saliency feature detection to find the most representative colors. Other libraries use a simple histogram and manual thresholding / quantization
  • Usability, by returning colors that are visually distinct and can be used in a design. Other libraries return "just the main colors", we also look for contrast and accents
  • Speed, by using worker threads and array buffers. Other libraries are synchronous and require a lot of memory to run
const colors = await extractColors(buffer, 3, {
	workers: true,
	colorSpace: oklabSpace,
	strategy: gapStatisticKmeans({ max: 10 }),
	clamp: 0.005,
})

How does it work

image step
maroon5-scrambled original image (here the original image is scrambled to avoid infringing on copyrights)
Screenshot 2024-09-29 at 14 52 30 main colors are extracted by k-means clustering
maroon5-masked the background is picked from extracted colors by looking at the most prevalent colors outside of the masked center
maroon5-saliency the foreground is picked from the most salient features by Itti-Koch filtering of the image
Screenshot 2024-09-29 at 14 54 39 main colors are split into 2 pools depending on their proximity with either the background or the foreground
Screenshot 2024-09-29 at 14 55 01
  • the accent is picked from the foreground pool based on its chroma, prevalence, and distance to the already picked colors.
  • the alternate background is picked from the background pool based on its prevalence and contrast with the foreground colors.
finally we look back at the original image to determine if the background and the alternate background formed a gradient in the original image. This allows us to use either flat color or a gradient in our UI.

Sample of results

Screenshot 2026-01-11 at 22 45 51

Multi-threading

A lot of the work done by this library is CPU intensive, so if performance is at all a concern, you should enable multithreading by using the workers: true option. If piscina is installed, it will be used to manage the worker pool, and the pool can be provided (worker: pool) to integrate with the rest of your application

Unit-testing colors

Because changes on "color manipulation" algorithms can be chaotic, we need to be able to test our resulting colors with some form of fuzzy matching. Additionally, color codes don't immediately mentally map to actual colors, making tests hard to read.

For this we base our tests on "named colors" (taken from the CSS list):

t.diagnostic(`accent: ${hex(accent)} >> ${nameColor(accent)} (${simpleColor(accent)})`)
assert.strictEqual(nameColor(accent), 'lightcoral')
// will output: ℹ accent: #f85963 >> lightcoral (salmon)

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors