#!/usr/bin/env python3
"""La carta macchiata di Faraway, rifatta da zero, per lo sfondo delle slide.

La scatola, il regolamento e il retro delle carte hanno un bianco con macchie
grigie leggere, tipo pietra chiara. Non la prendiamo dalla loro grafica:
l'autorizzazione di Catch Up copre il logo e le illustrazioni di Maxime Morin,
non il resto del progetto grafico. Qui la si ricrea con del rumore: nessun
file loro, solo lo stesso effetto.

Misurato sull'icona che ci ha mandato Matthieu: luminosita' fra 233 e 254,
media 248. Qui le macchie sono leggere e tirano un pelo al viola, come ha
chiesto Paolo guardando la prima prova.

Uscita: carta.png, 1400x3000, piu' grande di tutte e due le slide.
"""
import numpy as np
from PIL import Image, ImageFilter
import os

W, H = 1400, 3000
rng = np.random.default_rng(20260923)          # seme fisso: esce sempre uguale

def rumore(scala):
    """Rumore morbido: una griglia di valori a caso ingrandita e sfumata."""
    piccola = rng.random((H // scala + 2, W // scala + 2)).astype(np.float32)
    im = Image.fromarray((piccola * 255).astype(np.uint8)).resize(
        (W + 2 * scala, H + 2 * scala), Image.BICUBIC)
    im = im.filter(ImageFilter.GaussianBlur(scala * 0.35))
    return np.asarray(im, dtype=np.float32)[:H, :W] / 255.0

# macchie: piu' scale sommate, come le chiazze di una pietra
campo = 0.45 * rumore(220) + 0.30 * rumore(90) + 0.17 * rumore(36) + 0.08 * rumore(12)
campo = (campo - campo.min()) / (campo.max() - campo.min())
# le macchie non sono sfumate ovunque: hanno un bordo, come sulla carta vera
macchie = np.clip((campo - 0.52) / 0.16, 0, 1) ** 1.4
# qualche venatura piu' scura dentro le macchie
vene = np.clip((rumore(18) - 0.62) / 0.12, 0, 1) * macchie
# grana fine, appena percettibile
grana = rng.normal(0, 1, (H, W)).astype(np.float32)

# Quanto scuriscono macchie e vene. Prima versione: 10,5 e 5, troppo marcate
# per Paolo ("il grigio e' molto intenso"). Ora la meta' circa.
scuro = 6.0 * macchie + 2.5 * vene
# Le macchie tirano un pelo al viola: il verde cala piu' del rosso e del blu,
# cosi' il grigio diventa lavanda senza che si veda un colore vero e proprio.
r = 250.0 - 0.86 * scuro
g = 249.6 - 1.00 * scuro
b = 251.0 - 0.72 * scuro
rgb = np.stack([r, g, b], axis=-1) + 0.9 * grana[..., None]
luce = rgb.mean(axis=-1)
rgb = rgb.clip(0, 255).astype(np.uint8)

qui = os.path.dirname(os.path.abspath(__file__))
Image.fromarray(rgb).save(os.path.join(qui, 'carta.png'), optimize=True)
print('carta.png', W, 'x', H, 'luminosita', int(luce.min()), '-', int(luce.max()), 'media', round(float(luce.mean()), 1))
