marzeq/accent-extract
clone
| dir | src/ |
| dir | tests/ |
| dir | vendor/ |
| file | .gitignore |
| file | compile_static.sh |
| file | Makefile |
| file | README.md |
README.md
accent-extract
accent-extract is a small C11 command-line tool that finds dominant colours
in a wallpaper and scores their suitability as UI accents against a supplied
background colour. It produces one script-friendly #RRGGBB score record per
line on standard output.
Dependencies
- A C11 compiler (Clang or GCC)
- SDL3
- SDL3_image 3.4 or newer
pkg-config
The default SDL3_image pkg-config package name is sdl3-image.
On a system that calls it SDL3_image, build with
SDL_IMAGE_PKG=SDL3_image.
Build and test
make
make test
make clean
Static Linux binaries
compile_static.sh produces fully static musl binaries for Linux AMD64 and
ARM64:
./compile_static.sh
Usage
accent-extract wallpaper.png --background '#1e1e1e'
Options:
--background COLOR Required background colour in #RRGGBB form.
--limit N Maximum pre-score dominant candidates (default: 20).
--min-score FLOAT Minimum accent score to print (default: 0.60).
--block-size N Square averaging block size (default: 16).
--tweak Refine output lightness and saturation.
--help Show command help.
Example output:
#7aa2f7 0.884
#c678dd 0.811
#98c379 0.742
Formats and animations
SDL3_image supplies PNG/APNG, JPEG, GIF, WebP, AVIF, BMP, PNM, TGA, TIFF, QOI, JPEG XL, and any other raster decoder enabled in the installed library.
Extraction method
Each frame is divided into blocks (16 by 16 pixels by default), including partial blocks at the right and bottom edges. Pixels are alpha-weighted, so fully transparent pixels contribute nothing. The tool averages in linear sRGB and converts the representative colour back to sRGB. Nearby representatives are merged deterministically using Oklab distance, with prevalence accumulated by visible pixel area and frame duration.
The pre-score pool primarily contains the most prevalent clusters, with up to
one half reserved for chromatic clusters. Those reserved slots balance the
most prevalent chromatic representatives with the highest-chroma
representatives. This prevents a small but visually salient accent from being
crowded out by many shades of a neutral background. The vendored
accent_score() then scores those candidates against the background; the
minimum-score filter is applied and surviving candidates are sorted by score.
Prevalence and accent score are not blended into one metric.
With --tweak, surviving colours receive a final perceptual adjustment. Their
Oklab lightness separation and chroma are nudged 25% toward the scoring
library's preferred values while preserving hue. Out-of-gamut colours are
mapped by reducing chroma. A tweak is retained only if it does not lower the
accent score; displayed scores are recomputed and the results are re-sorted.
Attribution
The unmodified vendor/accent_score.h is vendored
from my own
accent-score
library.