# 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 ```sh make make test make clean ``` ### Static Linux binaries `compile_static.sh` produces fully static musl binaries for Linux AMD64 and ARM64: ```sh ./compile_static.sh ``` ## Usage ```sh accent-extract wallpaper.png --background '#1e1e1e' ``` Options: ```text --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: ```text #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`](vendor/accent_score.h) is vendored from my own [`accent-score`](https://git.marzeq.foo/marzeq/accent-score/src/branch/dev/accent_score.h) library.