Spaces:
Running
Running
File size: 1,975 Bytes
414dc55 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | """Deterministic noir pixel palettes derived from a descriptor accent + seed.
Calm, professional, muted - dark slate base, warm parchment, a single accent. No
neon. Everything is computed (no assets), so portraits are instant and offline.
"""
from __future__ import annotations
import hashlib
from dataclasses import dataclass
RGBA = tuple[int, int, int, int]
_INK: RGBA = (18, 20, 28, 255)
_BG: RGBA = (20, 22, 31, 255)
_PANEL: RGBA = (33, 36, 49, 255)
_PARCHMENT: RGBA = (217, 200, 160, 255)
_SKIN_TONES: tuple[RGBA, ...] = (
(224, 187, 153, 255),
(198, 156, 121, 255),
(165, 124, 92, 255),
(122, 90, 66, 255),
(90, 66, 50, 255),
)
_HAIR_TONES: tuple[RGBA, ...] = (
(35, 28, 24, 255),
(62, 44, 32, 255),
(120, 110, 105, 255),
(95, 70, 45, 255),
)
@dataclass(frozen=True)
class Palette:
bg: RGBA
panel: RGBA
ink: RGBA
parchment: RGBA
skin: RGBA
hair: RGBA
cloth: RGBA
cloth_dark: RGBA
accent: RGBA
def seed_from(*parts: str) -> int:
digest = hashlib.sha256("|".join(parts).encode("utf-8")).digest()
return int.from_bytes(digest[:4], "big")
def _hex_to_rgba(value: str, fallback: RGBA) -> RGBA:
value = value.strip().lstrip("#")
if len(value) != 6:
return fallback
try:
return (int(value[0:2], 16), int(value[2:4], 16), int(value[4:6], 16), 255)
except ValueError:
return fallback
def _darken(color: RGBA, factor: float = 0.6) -> RGBA:
return (int(color[0] * factor), int(color[1] * factor), int(color[2] * factor), 255)
def build_palette(seed: int, accent_hex: str | None) -> Palette:
accent = _hex_to_rgba(accent_hex or "", (184, 134, 11, 255))
skin = _SKIN_TONES[seed % len(_SKIN_TONES)]
hair = _HAIR_TONES[(seed >> 3) % len(_HAIR_TONES)]
return Palette(
bg=_BG, panel=_PANEL, ink=_INK, parchment=_PARCHMENT,
skin=skin, hair=hair, cloth=accent, cloth_dark=_darken(accent, 0.55), accent=accent,
)
|