# Sfondi dalle foto — La Leggenda del Regolo Il prompt iniziale parlava di Calenzano: questo progetto è ambientato a **San Piero a Sieve, Mugello, fine maggio 2007**. Lo stile è quello delle avventure VGA del 1993, coerente con `prompts/STILE.md`: pixel nitidi, tavolozza calda limitata, ambienti vuoti. La prospettiva e l'architettura della fotografia hanno priorità rispetto alla vecchia indicazione generica «vista laterale come un teatro». ## Cartelle | Percorso | Contenuto | | --- | --- | | `assets/raw/foto/` | Foto JPG, JPEG, PNG e WEBP; estensioni anche maiuscole; scansione non ricorsiva | | `assets/raw/foto/da-fare/` | Oratorio, escluso dal batch per ora | | `prompts/backgrounds/base.txt` | Stile comune; se assente si usa quello incluso in `tools/genera.py` | | `prompts/backgrounds/.txt` | Istruzioni della scena, aggiunte allo stile comune | | `assets/generated/.png` | Risultato 16:9, 1536×864, stesso nome base dell'originale | | `assets/generated/.responses/` | Risposte originali conservate per riprendere senza ripagare una generazione | | `assets/generated/registro.json` | Stato, prompt completo, hash foto, modello, tentativi, errori e uso quando disponibile | | `assets/generated/index.html` | Confronto prima/dopo di tutte le foto in input, anche quelle ancora da generare | | `assets/scenes/` | Sfondi del gioco a 640×360, preparati separatamente dopo revisione | Foto, prompt e risultati intermedi sono esclusi da Git, secondo le convenzioni del progetto. Per trasferire il lavoro su un altro computer servono anche queste cartelle locali: il solo repository non include le foto e i prompt specifici. ## Generare con Codex (la strada normale: gratis) Dal 23 ottobre 2026 gli sfondi si fanno con lo **strumento immagini integrato di Codex**, che non usa l'API e non costa niente. Serve solo il prompt in `prompts/backgrounds/.txt`, scritto come gli altri. `tools/genera.py` e `OPENAI_API_KEY` restano per quando Codex non basta (sotto, «Installazione»). La prima volta così: l'ingresso della scuola (`assets/generated/scuola-ingresso.png`). ```zsh cd ~/Workspaces/misc/LeggendaDelRegolo codex exec -C . -s workspace-write -o /tmp/codex-sfondo.txt \ "Genera UNO sfondo con il tuo strumento di generazione immagini integrato (non l'API, non tools/genera.py). Prompt: unisci, in quest'ordine, prompts/backgrounds/base.txt e prompts/backgrounds/NOME.txt. Immagini allegate: la prima è la foto da trasformare; le altre sono sfondi già approvati del gioco, solo come riferimento di stile, tavolozza e luce. Formato 16:9 orizzontale, 1536x864 (ridimensiona con magick -filter point se esce diverso). Salva come assets/generated/NOME.png (se esiste già, NOME-prova-2.png). Non modificare nessun altro file. Alla fine scrivi in italiano il percorso e la dimensione in pixel." \ -i assets/raw/foto/NOME.jpg -i assets/scenes/villa-adami.png -i assets/scenes/salita-villa-adami.png \ /`. - Poi, come sempre: confronto con la foto, `make background SRC=assets/generated/NOME.png` e la scena in `story.js`. ## Installazione Python 3.10 o successivo: ```zsh python3 -m venv .venv source .venv/bin/activate python3 -m pip install -r requirements.txt ``` Per le chiamate reali il processo deve ricevere `OPENAI_API_KEY` nell'ambiente. Non salvare la chiave nel codice, nei prompt o in Git. Il programma non carica file `.env` e non stampa la chiave. In zsh puoi inserirla senza mostrarla o registrarla nella cronologia: ```zsh read -rs 'OPENAI_API_KEY?Chiave OpenAI: ' export OPENAI_API_KEY ``` ## Comandi Eseguire dalla radice del repository (i percorsi predefiniti sono comunque relativi allo script, non alla directory da cui lo si lancia): ```zsh python3 tools/genera.py --dry-run python3 tools/genera.py --test --dry-run python3 tools/genera.py --limit 10 --dry-run python3 tools/genera.py --gallery-only ``` Questi comandi non chiamano l'API. `--dry-run` non scrive nulla e non richiede SDK o chiave. `--gallery-only` scrive soltanto il confronto HTML. Per generare, dopo aver controllato l'elenco: ```zsh python3 tools/genera.py --test # prima foto non ancora completata, in ordine alfabetico python3 tools/genera.py --limit 10 # al massimo dieci foto ancora da completare python3 tools/genera.py # tutte le foto ancora da completare (ora solo le due nuove vedute) ``` Ogni esecuzione reale mostra il conteggio, il modello, la qualità e il massimo numero di tentativi. Richiede di scrivere **GENERA** prima di contattare OpenAI. Una risposta vuota, diversa o EOF annulla l'esecuzione. Non esiste conferma automatica. `--test` genera davvero una foto: per simulare aggiungere `--dry-run`. Per usare le cartelle del prompt originale: ```zsh python3 tools/genera.py --input-dir originali --output-dir generate --prompt-dir prompt --dry-run ``` Opzioni: `--model gpt-image-2`, `--quality high` (anche `low`, `medium`, `auto`), `--timeout 180` secondi, `--attempts 3` richieste massime per foto, prima inclusa. Il batch è sequenziale; non usa il servizio Batch API. `--test` e `--limit` sono alternativi. Foto con uguale nome base, anche con estensioni diverse, causano un errore preventivo per evitare collisioni sui PNG. ## API e recupero errori Usa l'OpenAI Python SDK e `client.images.edit`, modello predefinito `gpt-image-2`, `size="1536x864"`, `output_format="png"`, `n=1`. Questo formato è previsto dalla [documentazione ufficiale di Images Edit](https://developers.openai.com/api/reference/resources/images/methods/edit). Non viene passato `input_fidelity`: per questo modello gli input hanno già alta fedeltà, come indicato nella [guida ufficiale](https://developers.openai.com/api/docs/guides/image-prompting). Nessun cambio automatico di modello in caso di errore. Pillow applica l'orientamento EXIF e converte la foto in PNG per l'invio, senza modificare l'originale. Il risultato viene controllato e, solo se già in 16:9, normalizzato a 1536×864 con nearest-neighbor. Risposte con proporzioni diverse restano nella cache per revisione: non vengono stirate o ritagliate di nascosto. Timeout, errori di connessione, 408, 409, 429 e 5xx vengono ritentati con attesa esponenziale limitata; gli altri errori HTTP non vengono ritentati. I retry automatici dell'SDK sono disattivati per rispettare il numero richiesto. **Un timeout può verificarsi dopo che il server ha elaborato l'immagine: riprovare può comportare un altro addebito.** Non viene inventata una stima in euro; il costo dipende da input, output, qualità e tariffa del modello. I PNG esistenti vengono saltati anche senza registro. Prima di chiamare l'API vengono verificati: se sono corrotti o di formato diverso, il programma si ferma senza sovrascriverli. Una modifica al prompt non rigenera immagini completate: per una variante usare un'altra `--output-dir`. Se manca il risultato finale ma esiste una risposta nella cache, la finalizzazione riparte da quella senza API. Non avviare due processi sulla stessa cartella di output contemporaneamente. Il registro si aggiorna prima di ogni tentativo e dopo ogni foto, tramite sostituzione atomica. Gli errori SDK sono registrati per tipo/codice, senza corpo della risposta o intestazioni. Un errore su una foto non blocca le altre; l'uscita è 1 se ci sono errori, 130 se si interrompe con Ctrl-C. ## Le due scene preparate 1. **`pieve-dalla-salita`**: la Pieve vista tornando con lo sguardo verso il basso dalla salita. Conservare facciata, campanile, canonica, statua, cancello, parapetti e pendenza. Togliere persone, auto e allestimenti temporanei della cena. Villa Adami e Fortezza sono più su, dietro la camera: non inserirle artificialmente nell'immagine. 2. **`salita-villa-adami`**: casa ocra, persiane, leone di terracotta, ringhiera, muro di sostegno e bivio. Conservare la strada bassa a sinistra e la salita a destra che curva lungo il muro. La foto verticale richiede estensione laterale: le parti non fotografate saranno una ricostruzione da controllare. Rimuovere le auto, lasciare leggibile il bivio. La Fortezza non è visibile nella foto e non va inventata sullo sfondo. L'oratorio resta per dopo. Il percorso indicato da Andrea è **Pieve → Villa Adami → salita → Fortezza**. Questo materiale documenta la geografia corretta; il prototipo conserva per ora i suoi collegamenti di prova. Le prime due immagini sono state generate il 23 ottobre 2026 **con lo strumento immagini integrato**, dopo aver completato la preparazione e i test senza rete. Lo script Python non ha effettuato chiamate API reali. I prompt effettivamente usati sono salvati nei due file `*.integrated.txt` e nel registro, con `assets/scenes/piazza-colonna.png` come ulteriore riferimento di stile. Il modello interno dello strumento non è dichiarato: nel registro non viene attribuito a `gpt-image-2`. I file restituiti a 1672×941 sono conservati integri in `.responses/`, con copie normalizzate a 1536×864 e copie per il gioco a 640×360/64 colori. Il generatore li riconosce come completati e li salta. ## Preparare i file del gioco Dopo aver controllato visivamente i master, riusare lo strumento già presente: ```zsh python3 tools/prepare_background.py assets/generated/pieve-dalla-salita.png assets/scenes/pieve-dalla-salita.png --colors 64 python3 tools/prepare_background.py assets/generated/salita-villa-adami.png assets/scenes/salita-villa-adami.png --colors 64 ``` Le copie hanno 640×360 pixel e al massimo 64 colori, senza retinatura. Il motore le ingrandisce senza sfocatura. Gli sfondi non vengono collegati automaticamente alla storia: vanno definite aree calpestabili e uscite sulla composizione finale. ## Verifica senza rete ```zsh python3 -m unittest discover -s tests -p 'test_genera.py' ``` I test usano foto sintetiche e un client simulato: nessuna chiave vera, nessuna richiesta API, nessun costo. La verifica reale del modello resta distinta.