Files
whoshue/README.md
T

6.7 KiB
Raw Blame History

whoshue

A pixel-art color analyzer for KDE/Wayland. Capture a game/application window, select part of its preview, and inspect the captured colors. The analyzer is a normal desktop window; it does not flash calibration colors or hide itself.

Run

On CachyOS/Arch with KDE, the capture backend uses xdg-desktop-portal, xdg-desktop-portal-kde, and PipeWire. Building needs Rust, a C toolchain, pkgconf, Clang/libclang, and PipeWire development libraries (libpipewire).

cargo run --release
# Or start with a local image, without requesting screen sharing:
cargo run --release -- /path/to/screenshot.png
  1. Click Choose source…. KDE handles selecting a window, screen, or region. Click it again to choose a different source.
  2. Drag a rectangle in the source preview. Capture display pauses during the drag, then returns to its previous live/frozen state. The crop is stored in source pixels and resets if the source dimensions change.
  3. Freeze holds the displayed frame and analysis; Resume takes the newest available frame. Stop sharing closes capture and keeps the last image.
  4. Inspect the nearest-neighbor zoomed crop. Hover for source coordinates, RGB/hex and HSV; click to copy hex. Click palette swatches to copy them too.
  5. Save crop PNG writes a uniquely named PNG in the system temporary directory and displays its path. Drop an image or click Open image… to browse for a file in KDE's file picker.

Color analysis and vision checks

The Color analysis tab has four distributions:

  • Hue: HSV hue in 36 ten-degree bins; saturation below 5% counts as neutral.
  • Saturation: HSV saturation, from neutral to fully saturated.
  • Brightness (V): HSV value, the maximum RGB channel. This is not perceived lightness: fully saturated red and green both have 100% value.
  • Luminance: relative luminance in linear sRGB, weighted for contrast.

Saturation, value, and luminance use 20 five-percentage-point bins, including 100% in the final bin. Each has a mean. Switch between pixel frequency and equal weight per distinct RGB color; hover bars for counts and percentages. The exact palette is ordered by count, then RGB for deterministic ties. Fully transparent pixels are excluded; partially transparent pixels retain their stored RGB values and count once. Pixel inspection includes HSV and relative luminance.

Use Compare vision below the selection to show the original crop alongside protanopia, deuteranopia, tritanopia, or grayscale. The first three use the Machado–Oliveira–Fernandes full-severity model, applied in linear RGB and then encoded back to sRGB. Grayscale uses relative luminance and tests removal of color cues; it does not model all aspects of achromatopsia. Preview mode does not change histograms, copied pixel values, or the exported PNG: those always use the original.

Vision check automatically checks all four scenarios. It flags pairs whose OKLab distance falls from at least 0.08 to at most 0.04, losing at least 50% of the original separation. These are project-specific screening heuristics, not validated visibility thresholds or WCAG criteria. Each scenario shows original and simulated swatches, numeric hex values, and up to six closest candidate pairs. The preview button opens the corresponding simulation for the current crop.

The check is bounded to the 64 most frequent opaque colors and reports both color and pixel coverage. Partially/fully transparent pixels have no known backdrop and are excluded from this check. No findings does not establish accessibility. The check cannot infer adjacency, text/background relationships, or the gameplay meaning of a color. Review important cues in context and combine color with shapes, labels, or differences in lightness. Select a smaller region when an important detail is outside the reported palette coverage.

References:

Choosing a source always opens KDE's picker. The last portal token is saved at $XDG_CONFIG_HOME/whoshue/config.toml (normally ~/.config/whoshue/config.toml) for the command-line capture diagnostic. No capture starts until Choose source… is clicked. Cancelling the file picker leaves the current image/capture unchanged.

Portal requests share one application-lifetime async runtime. PipeWire runs on a separate blocking worker so restarting capture or opening another portal dialog cannot strand the cached D-Bus connection on a stopped executor.

Limits and next work

  • Window capture is preferred: screen/region capture includes overlapping windows, including whoshue if placed inside the captured area.
  • Selection follows coordinates within the source, not a moving sprite.
  • Analysis uses source pixels before preview scaling, but these are rendered colors, not necessarily original game-asset colors. HDR and color-profile conversion have not been validated; the current path assumes ordinary SDR RGB.
  • Live analysis refreshes at most five times per second. Large selections with many unique colors are more expensive; release builds are recommended.
  • Game-specific behavior on focus loss/minimization needs desktop testing.
  • Perceptual OKLCH views, color/hue highlighting, and comparing saved selections are future features; the distributions currently use HSV and relative luminance.

Validation

cargo test --offline --locked
cargo clippy --offline --locked --all-targets -- -D warnings
cargo fmt --check

Tests cover hue boundaries, neutral/transparent pixel handling, weighting, cropping, selection coordinates, pixel-format conversion, frozen-frame behavior, resize handling, all histogram/vision UI views, file-picker cancellation/reopening, and repeated portal requests during/after capture. The portal regression test requires dbus-run-session and permission to create a local socket; it uses its own private bus and does not open desktop dialogs. Color tests cover histogram endpoints and weighting, sRGB gamma, simulation reference colors, alpha handling, warning positives/negatives, palette coverage, and preserving source pixels. Actual portal capture requires a running Wayland desktop and permission through KDE's picker.

For a capture-only diagnostic (saves the first full source frame):

cargo run -- --selftest /tmp/whoshue-selftest.png