Skip to main content

Pure pixel color extraction from wallpaper for Linux desktop theming

Project description

Warnaza

Pure pixel color extraction from wallpaper. No synthesis, no centroid, no generation, only colors that literally exist in your image.


Preview


What it does

Warnaza reads your wallpaper, counts every pixel, and extracts 32 colors sorted from darkest to lightest — split across three zones: dark, mid, and light. It then exports them as CSS variables, shell variables, and JSON so you can use them anywhere in your rice.

What it is not: Warnaza does not generate new colors. It does not run k-means. It does not synthesize a palette. Every color in the output was already in your wallpaper.


Installation

pip install Pillow

That's the only dependency. Everything else is Python stdlib.


Usage

# Basic — extract and export
python warnaza.py wallpaper.jpg

# Full mode — extract + apply templates + deploy + post script
python warnaza.py wallpaper.jpg --full

# Generate only — skip ricing
python warnaza.py wallpaper.jpg --generate-only

# Force dark or light mode
python warnaza.py wallpaper.jpg --mode dark

# Generate preview PNG
python warnaza.py wallpaper.jpg --preview

# Force re-extraction, ignore cache
python warnaza.py wallpaper.jpg --no-cache

Output

File Location Description
*_warnaza.json ~/.config/warnaza/output/ Full palette with all metadata
*_warnaza.css ~/.config/warnaza/output/ CSS custom properties
*_warnaza.sh ~/.config/warnaza/output/ Shell variables, sourceable
*_warnaza_preview.png ~/.config/warnaza/sample/ Visual swatch
Applied templates ~/.cache/warnaza/ Results of template processing

Color naming

32 colors, always. Sorted dark → light, split into three zones:

dark0  dark1  dark2  ...  dark10    (11 colors — darkest to zone boundary)
mid0   mid1   mid2   ...  mid10     (11 colors — mid tones)
light0 light1 light2 ...  light9    (10 colors — zone boundary to lightest)

dark0 is always the darkest color. light9 is always the lightest.

In CSS:

background: var(--warnaza-dark0);
color: var(--warnaza-light9);
border: 1px solid var(--warnaza-mid5);

In shell:

source ~/.config/warnaza/output/wallpaper_warnaza.sh

echo $WARNAZA_DARK0          # #0a0a0f
echo $WARNAZA_MID5_HYPR      # rgba(b4503cff)
echo $WARNAZA_LIGHT9_RGB     # 255,248,220
echo $WARNAZA_MODE           # dark

In JSON:

{
  "dark0": { "hex": "#0a0a0f", "rgb": "10,10,15", "hypr": "rgba(0a0a0fff)", "luminance": 0.3 },
  "mid5":  { "hex": "#b4503c", ... },
  "light9": { ... }
}

Templates

Warnaza uses a simple {{placeholder}} system — same as m3wal.

Place your .template files in ~/.config/warnaza/templates/. Warnaza will process them in parallel and output results to ~/.cache/warnaza/.

Available placeholders:

Placeholder Example output
{{dark0}} #0a0a0f
{{dark0_rgb}} 10,10,15
{{dark0_hypr}} rgba(0a0a0fff)
{{dark0}} ... {{mid5}} ... {{light9}} same formats
{{warnaza_mode}} dark or light
{{wallpaper_path}} /home/user/walls/forest.jpg

Example — Kitty colors:

# ~/.config/warnaza/templates/kitty-colors.conf.template

background  {{dark0}}
foreground  {{light9}}
cursor      {{mid5}}
color0      {{dark0}}
color15     {{light9}}

Output goes to ~/.cache/warnaza/kitty-colors.conf.


Deploy

After templates are processed, Warnaza can copy the results to their final destinations using ~/.config/warnaza/deploy.json:

{
  "deployments": [
    {
      "source": "kitty-colors.conf",
      "destination": "~/.config/kitty/colors.conf"
    },
    {
      "source": "alacritty-colors.toml",
      "destination": "~/.config/alacritty/colors.toml"
    }
  ]
}

source is relative to ~/.cache/warnaza/. destination is the final path on your system.


Post script & hooks

Post script — runs once after everything is done:

# ~/.config/warnaza/warnaza-post.sh
source ~/.config/warnaza/output/$(basename $WARNAZA_WALLPAPER .jpg)_warnaza.sh
pkill -SIGUSR1 kitty
hyprctl reload

Hook scripts — run with all colors as env vars. Enable in config:

[Hook.Scripts]
enabled = true
scripts = reload-hypr.sh, restart-waybar.sh

Place scripts in ~/.config/warnaza/hooks/. Every color is available as an env var:

# Inside your hook script
echo $WARNAZA_DARK0
echo $WARNAZA_MID5_HYPR
echo $WARNAZA_LIGHT9_RGB
echo $WARNAZA_MODE        # dark / light
echo $WARNAZA_WALLPAPER   # full path to wallpaper

Config

Located at ~/.config/warnaza/warnaza.conf — created automatically on first run.

[General]
operation_mode     = full    # full / generate
mode               = auto    # auto / dark / light
brightness_threshold = 128   # 0–255, used for auto mode detection

[Extraction]
bin_size  = 4     # pixel rounding accuracy (2/4/8/16)
delta_min = 5.0   # minimum luminance difference between adjacent palette colors

[Features]
generate_preview = true
set_wallpaper    = true
apply_xresources = true
run_post_script  = true
create_symlink   = true
deploy_configs   = true

[Hooks]
scripts_dir = ~/.config/warnaza/hooks

[Hook.Scripts]
enabled = false
scripts =

[PostScript]
script_path = warnaza-post.sh

Config notes

bin_size — how aggressively pixels are rounded before counting. Lower = more accurate to the original wallpaper, slightly slower. 4 is the recommended default.

delta_min — minimum perceptual luminance gap between adjacent colors in the same zone. Prevents the palette from being filled with near-identical shades. Set lower if you want more similar tones, higher for more contrast.

mode = auto — Warnaza measures average brightness of the wallpaper and picks dark or light based on brightness_threshold. This value is stored in WARNAZA_MODE and {{warnaza_mode}} for use in templates and scripts (e.g. switching GTK theme or gsettings).


Cache

Warnaza caches the extracted palette as JSON in ~/.config/warnaza/output/. On subsequent runs with the same wallpaper filename, it skips extraction and loads from cache — templates and ricing still run.

Use --no-cache to force a fresh extraction.


File structure

~/.config/warnaza/
├── warnaza.conf          ← main config
├── deploy.json           ← deploy mappings
├── warnaza-post.sh       ← post script (create this yourself)
├── current_wallpaper     ← symlink to last used wallpaper
├── templates/            ← your .template files
│   ├── kitty-colors.conf.template
│   └── alacritty-colors.toml.template
├── output/               ← JSON, CSS, SH exports
└── sample/               ← preview PNGs

~/.cache/warnaza/         ← processed template results

How it works

  1. Resize wallpaper to 200×200 (speed)
  2. Round each pixel's RGB to nearest multiple of bin_size
  3. Count frequency of every unique color
  4. Split into 3 luminance zones (dark / mid / light) using CIELAB L*
  5. From each zone, pick the most frequent colors — skipping any that are too similar to the previous pick (delta_min)
  6. Sort final 32 colors dark → light by L*
  7. Export and apply

No k-means. No centroid. No synthesis. If a color is in the output, it was in your wallpaper.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

warnaza-1.0.0.tar.gz (38.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

warnaza-1.0.0-py3-none-any.whl (50.4 kB view details)

Uploaded Python 3

File details

Details for the file warnaza-1.0.0.tar.gz.

File metadata

  • Download URL: warnaza-1.0.0.tar.gz
  • Upload date:
  • Size: 38.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.6

File hashes

Hashes for warnaza-1.0.0.tar.gz
Algorithm Hash digest
SHA256 afb84b8987264088b269e706dff85e467af9c080375ec694243aadcdaaf98eda
MD5 e5318044630960ccf3ebd05329be7b13
BLAKE2b-256 751be22d57f85b59e0501674f6c3316eaaaaa13acfa86ee8b5805e27bdfc8a45

See more details on using hashes here.

File details

Details for the file warnaza-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: warnaza-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 50.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.6

File hashes

Hashes for warnaza-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5c09b3a14d18b1f1ab19225cec92e399b3ac93b4aa568bd2d4b8aff1faf93a5a
MD5 a1c879637b00ba986bf025a916b8e500
BLAKE2b-256 c0cd4ba9300b7cd693086b4098016cfe188bc09b9e4269d5b3ee34d340a5af83

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page