Files

307 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# `ash-wallpaper.sh` — guide
Turns a color photo into an **Ash** wallpaper: the image is reduced to
Ash-tinted greys (dark variant), while warm *ember/gold* highlights (sunsets,
fire, lamps, skin tones) are selectively kept — the "Pleasantville" effect.
## Quick start
```sh
tools/ash-wallpaper.sh photo.jpg # -> photo-ash.png
tools/ash-wallpaper.sh photo.jpg out.png # custom output path
```
> **Be realistic about the defaults.** This is a ~50-line ImageMagick script,
> not an AI — it applies one fixed rule (*keep warm, high-saturation pixels;
> ash everything else*) to your photo. The default settings are tuned for the
> classic cases (fire, sunsets, lamps). For anything else, expect to tune: the
> samples below were all post-processed in 23 iterations of `HUE_MAX` /
> `SAT_MIN` / `SAT_MAX`. A motif with little warm colour (e.g. a whale) simply
> has little to keep — no parameter will invent highlights that aren't in the
> source.
Requirements: ImageMagick 6.9+ or 7 (`convert` / `magick`). 4K input takes ~10s.
All knobs are environment variables read once per run — tune one, rerun,
compare.
## How it works
1. **Hue band** — the photo's HSL hue channel is thresholded: pixels with
`hue ≤ HUE_MAX` or `hue ≥ HUE_MIN` form the "warm" band (reds, oranges,
golds; the wrap-around at HUE_MIN catches pure crimson reds).
2. **Saturation gate** — inside that band, a saturation ramp decides how much
of the pixel survives: nothing below `SAT_MIN`, everything from `SAT_MAX`.
This is what keeps dull, near-grey warmish pixels as ash.
3. **Softening** — the combined mask is blurred, then re-sharpened with
`SENSITIVITY` so highlights fade into the greys instead of showing hard
cut-out edges.
4. **Base** — a desaturated copy is tinted along the Ash dark ramp
(`BASE_LO` shadows → `BASE_HI` highlights, default void → chalk).
5. **Composite** — the original photo, with saturation multiplied by
`EMBER_BOOST`, is laid over the base through the mask.
## Parameters
| Variable | Default | Meaning |
|---|---|---|
| `HUE_MAX` | `13%` | Upper edge of the warm band, in percent of the hue circle (360°). `13%` ≈ 47°, so reds, orange, ember and gold survive; yellows from ≈47° and all greens/blues fall out. |
| `HUE_MIN` | `94%` | Lower edge of the wrap-around band (`≥ 338°`). Catches deep crimson/cherry reds whose hue sits just below 360°. |
| `SAT_MIN` | `12%` | Saturation (HSL) below which a pixel becomes full grey, no matter its hue. Raise to make the image more monochrome (e.g. muted/desaturated photos: `1825%`). |
| `SAT_MAX` | `45%` | Saturation at which the highlight is fully kept. Pastel skies/candle-lit scenes peak below 45% — lower it (`2535%`) to let soft colour through; raise it (`5570%`) to keep only the most saturated embers. |
| `SENSITIVITY` | `8x45%` | `-sigmoidal-contrast` applied to the mask: `contrast x midpoint`. Higher contrast → crisper, more cut-out-looking highlights; lower (e.g. `3x50%`) → dreamier, feathered bleed. The midpoint shifts the whole mask: `>50%` = only the most certain warm pixels, `<50%` = more generous. |
| `EMBER_BOOST` | `130` | Saturation multiplier (%) on the surviving pixels, so the remaining embers read against all that ash. `100` = untouched colours, `160+` = intense glow. Applied to *all* channels of those pixels, so already-saturated fire can clip — reduce if it looks neon. |
| `BASE_LO` / `BASE_HI` | `#100f12` / `#f3ede1` | Endpoints of the grey ramp (void → chalk). Any colours work, e.g. `BASE_LO=#1c1b1f BASE_HI=#e6dfd1` for a flatter panel→bone ramp. |
### Where the Ash palette sits in the hue wheel
For reference when widening/narrowing the band (hue in IM percent ≈ degrees/360):
| Colour | Hex | Hue | In band at defaults? |
|---|---|---|---|
| blood | `#c15c46` | 11° (3%) | ✅ |
| rust | `#a86a48` | 21° (6%) | ✅ |
| ember | `#e0914f` | 27° (8%) | ✅ |
| gold | `#d6b46a` | 41° (11%) | ✅ |
| pure yellow | — | 60° (17%) | ❌ (needs `HUE_MAX=17%`) |
| moss | `#8f9a5c` | 69° (19%) | ❌ |
| steel | `#7c9aa1` | 187° (52%) | ❌ |
| rot | `#b47e99` | 330° (92%) | ❌ (needs `HUE_MIN=88%` — usually you *don't* want this) |
| violet | `#a585ac` | 292° (81%) | ❌ |
## Samples
Freely-licensed photos from Wikimedia Commons, run through the script (900 px
previews). Each entry lists the exact command; the originals are shown for
comparison and credit.
### Sunset over the sea
```sh
tools/ash-wallpaper.sh sunset.jpg
```
| Original | Ash |
|---|---|
| ![sunset original](../images/samples/sunset-original.jpg) | ![sunset ash](../images/samples/ash-sunset.jpg) |
Source: [“Leigh-on-Sea beach sunset (Unsplash)”](https://commons.wikimedia.org/wiki/File:Leigh-on-Sea_beach_sunset_(Unsplash).jpg)
by Joshua Fuller, CC0.
### Campfire close-up
```sh
tools/ash-wallpaper.sh campfire.jpg
```
| Original | Ash |
|---|---|
| ![campfire original](../images/samples/campfire-original.jpg) | ![campfire ash](../images/samples/ash-campfire.jpg) |
Source: [“Closeup of raging flames in a large bonfire”](https://commons.wikimedia.org/wiki/File:Closeup_of_raging_flames_in_a_large_bonfire._-_Flickr_-_shixart1985.jpg)
by Nenad Stojkovic, [CC BY 2.0](https://creativecommons.org/licenses/by/2.0/).
### Autumn foliage — warm-dominated scene
The whole park is bathed in warm orange, so ~90 % of the frame is "warm":
like the fireworks case below, the result stays close to the original. Narrow
the band (`HUE_MAX=8%`) to let only the saturated ember oranges through:
```sh
tools/ash-wallpaper.sh autumn.jpg
```
| Original | Ash |
|---|---|
| ![autumn original](../images/samples/autumn-original.jpg) | ![autumn ash](../images/samples/ash-autumn.jpg) |
Source: [“Münster, Park Sentmaring 2015 9923”](https://commons.wikimedia.org/wiki/File:M%C3%BCnster,_Park_Sentmaring_--_2015_--_9923.jpg)
by Dietmar Rabich, [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/).
### City at night (ISS)
Street lamps glow soft yellow — the wide-band + soft-gate recipe from below:
```sh
HUE_MAX=17% SAT_MIN=8% SAT_MAX=60% SENSITIVITY=4x50% \
tools/ash-wallpaper.sh city.jpg
```
| Original | Ash |
|---|---|
| ![city original](../images/samples/city-original.jpg) | ![city ash](../images/samples/ash-city.jpg) |
Source: [“Windy City of Lights (ISS070-E-105097)”](https://commons.wikimedia.org/wiki/File:Windy_City_of_Lights_(153622).jpg),
astronaut photograph, NASA/JSC Crew Earth Observations — public domain.
### Redhead portrait
Only hair and lips keep their colour; skin stays close to bone:
```sh
SAT_MIN=18% EMBER_BOOST=150 tools/ash-wallpaper.sh portrait.jpg
```
| Original | Ash |
|---|---|
| ![portrait original](../images/samples/redhead-original.jpg) | ![portrait ash](../images/samples/ash-redhead.jpg) |
Source: [“Woman redhead natural portrait 1”](https://commons.wikimedia.org/wiki/File:Woman_redhead_natural_portrait_1.jpg)
by dusdin (Flickr), cropped by Gridge, [CC BY 2.0](https://creativecommons.org/licenses/by/2.0/).
### Candle light
A dark frame with a warm source — the ideal case; the flame and its glow stay,
everything else turns to ash:
```sh
EMBER_BOOST=120 tools/ash-wallpaper.sh candles.jpg
```
| Original | Ash |
|---|---|
| ![candles original](../images/samples/candles-original.jpg) | ![candles ash](../images/samples/ash-candles.jpg) |
Source: [“Alive”](https://commons.wikimedia.org/wiki/File:Alive_(61565557).jpeg)
by Ranit Sanyal, [CC BY 3.0](https://creativecommons.org/licenses/by/3.0/).
### Fairground at night
Neon rides: the white structure greys out, the warm cabin lighting and the red
LED strips survive. Uses the night recipe:
```sh
HUE_MAX=17% SAT_MIN=8% SAT_MAX=60% SENSITIVITY=4x50% \
tools/ash-wallpaper.sh kirmes.jpg
```
| Original | Ash |
|---|---|
| ![fairground original](../images/samples/kirmes-original.jpg) | ![fairground ash](../images/samples/ash-kirmes.jpg) |
Source: [“Nighttime ferris wheel gondolas … Pattaya fairground”](https://commons.wikimedia.org/wiki/File:DFC_4677_Nighttime_ferris_wheel_gondolas_glow_against_the_dark_sky_at_a_Pattaya_fairground_in_Nong_Pla_Lai_Bang_Lamung_District.jpg)
by PattayaPatrol, [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/).
### Rainy night in Moscow
Red neon and traffic-light reflections are all the colour left — the same
night recipe as above:
```sh
HUE_MAX=17% SAT_MIN=8% SAT_MAX=60% SENSITIVITY=4x50% \
tools/ash-wallpaper.sh rain.jpg
```
| Original | Ash |
|---|---|
| ![rain original](../images/samples/rain-original.jpg) | ![rain ash](../images/samples/ash-rain.jpg) |
Source: [“Late autumn rainy night in Moscow”](https://commons.wikimedia.org/wiki/File:Late_autumn_rainy_night_in_Moscow_(54889230493).jpg)
by kishjar?, [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/).
### Humpback whale — the low-highlight case
A daylight scene with almost no warm colour: only 0.4 % of the frame sits in
the warm band, so the result is (intentionally) almost fully grey. Nothing is
broken — there is simply little for the script to keep:
```sh
tools/ash-wallpaper.sh whale.jpg
```
| Original | Ash |
|---|---|
| ![whale original](../images/samples/whale-original.jpg) | ![whale ash](../images/samples/ash-whale.jpg) |
Source: [“Humpback Breaching”](https://commons.wikimedia.org/wiki/File:HIHWNMS_-_Humpback_Breaching_(33591142200).jpg)
by NOAA National Marine Sanctuaries — public domain.
### Fireworks — the negative case
Here the *whole* sky is lit red by smoke, so 96 % of the pixels are "warm" and
the mask covers everything: the image is barely greyscaled at all. When the
warm colour is the background rather than an accent, the effect has nothing to
work with. Pick a different shot, or narrow the band (`HUE_MAX=8%`) to keep
only the brightest sparks:
```sh
tools/ash-wallpaper.sh fireworks.jpg
```
| Original | Ash |
|---|---|
| ![fireworks original](../images/samples/fireworks-original.jpg) | ![fireworks ash](../images/samples/ash-fireworks.jpg) |
Source: [“Anjuna Beach, Goa, New Year's Eve, Fireworks in the sky”](https://commons.wikimedia.org/wiki/File:Anjuna_Beach,_Goa,_India,_New_Year%27s_Eve,_Fireworks_in_the_sky.jpg)
by Vyacheslav Argenberg, [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/).
### How much of each frame survived
The share of pixels the warmth mask keeps (measured with the **default** gate;
the night-recipe samples were run with a wider band). A quick way to read the
samples above, and a useful sanity check when tuning your own photo:
| Motif | Warm-pixel share (default) | Result |
|---|---|---|
| Humpback whale | 0.4 % | almost fully ash |
| Fairground | 4.2 % | ash with neon accents |
| City at night (ISS) | 17.0 % | ash with a glowing street grid |
| Rainy night Moscow | 17.2 % | ash with red neon |
| Sunset | 19.6 % | ash with a warm horizon |
| Campfire | 40.6 % | dark ash, glowing flames |
| Redhead portrait | 47.1 % | ash with warm hair/lips |
| Candle light | 73.2 % | dark ash with a glowing flame |
| Autumn foliage | 90.0 % | barely greyed — warm *is* the scene |
| Fireworks | 96.4 % | barely greyed — warm *is* the scene |
Rule of thumb: below ~25 % the effect is pronounced; above ~70 % the script
has little to grey out and you should narrow `HUE_MAX` or pick another frame.
## Recipes
```sh
# Warm sunset landscape, keep the drama
tools/ash-wallpaper.sh sunset.jpg
# Night city: street lamps are soft yellow-orange, need a wider + softer gate
HUE_MAX=17% SAT_MIN=8% SAT_MAX=60% SENSITIVITY=4x50% tools/ash-wallpaper.sh city.jpg
# Portrait: only eyes/lips/warm skin glow, everything else ash
SAT_MIN=18% EMBER_BOOST=150 tools/ash-wallpaper.sh portrait.jpg
# Almost pure grey with faint traces of ember
SAT_MIN=20% SAT_MAX=70% EMBER_BOOST=100 tools/ash-wallpaper.sh photo.jpg
# Flatter, dimmer base ramp
BASE_LO=#1c1b1f BASE_HI=#e6dfd1 tools/ash-wallpaper.sh photo.jpg
```
## Batch generation
```sh
for f in ~/Pictures/vacation/*.jpg; do
tools/ash-wallpaper.sh "$f"
done
```
## Using the results
Drop the generated files into the theme or user backgrounds folder — Omarchy
cycles through them with `Super+Ctrl+Space`:
```sh
mkdir -p ~/.config/omarchy/backgrounds/ash-dark
cp photo-ash.png ~/.config/omarchy/backgrounds/ash-dark/
```
## Troubleshooting
- **Highlights cut with hard edges** → lower the `SENSITIVITY` contrast
(first number), e.g. `4x45%`.
- **A warm object disappears** → its hue is outside the band (check the table
above) or its saturation is below `SAT_MIN`.
- **Grey areas look slightly tinted/brown** → those pixels are just inside the
band; raise `SAT_MIN`.
- **Fire/embers look clipped and neon** → lower `EMBER_BOOST` towards 100.
- **Image too bright/dark after tinting** → adjust `BASE_LO`/`BASE_HI` instead
of editing the photo.