Avvio in debug da VS Code e correzione dell'output a riga di comando
Aggiunta la configurazione .vscode allineata a quella di Mimante ed Encelado: F5 apre la finestra di Titano, una seconda configurazione entra con i breakpoint nella verifica del motore (--selftest), che è un punto d'ingresso separato e non raggiungibile dall'interfaccia. Nei task: build, verifica, cattura interfaccia e pulisci. La verifica usciva con codice 0 ma senza stampare nulla quando lanciata con "dotnet run" o con l'output su file. La causa è AttachConsole: l'eseguibile è un'applicazione a finestre e senza aggancio non si farebbe leggere da un terminale, ma se lo standard output è già dirottato l'aggancio lo sostituisce e i messaggi finiscono nella console invece che nella pipe. Ora l'aggancio avviene solo quando l'output non è già dirottato. Verificato nei tre casi: eseguibile diretto, dotnet run e redirezione su file, 55 righe in tutti e tre. Svuotato Modifiche.txt: il file è dell'utente. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Vendored
+7
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
// Fornisce il debugger "coreclr" richiesto da launch.json.
|
||||||
|
"ms-dotnettools.csharp",
|
||||||
|
"ms-dotnettools.csdevkit"
|
||||||
|
]
|
||||||
|
}
|
||||||
Vendored
+43
@@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
// Titano è un'applicazione desktop: F5 apre la stessa finestra che si ottiene
|
||||||
|
// facendo doppio clic su Titano.exe. La seconda configurazione esiste perché la
|
||||||
|
// verifica del motore NON è raggiungibile da quella finestra — è un punto
|
||||||
|
// d'ingresso a sé (--selftest), e volerci mettere un breakpoint dentro è la
|
||||||
|
// ragione più frequente per aprire il debugger su questo progetto.
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Titano",
|
||||||
|
"type": "coreclr",
|
||||||
|
"request": "launch",
|
||||||
|
"preLaunchTask": "build",
|
||||||
|
"program": "${workspaceFolder}/bin/Debug/net10.0-windows/Titano.exe",
|
||||||
|
"args": [],
|
||||||
|
"cwd": "${workspaceFolder}/bin/Debug/net10.0-windows",
|
||||||
|
"console": "internalConsole",
|
||||||
|
"stopAtEntry": false,
|
||||||
|
"enableStepFiltering": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Terminale integrato e non console interna: --selftest scrive con
|
||||||
|
// AttachConsole sulla console del processo padre, che nella console interna
|
||||||
|
// non esiste. Nel terminale l'esito delle 23 verifiche si legge davvero.
|
||||||
|
"name": "Titano — verifica del motore",
|
||||||
|
"type": "coreclr",
|
||||||
|
"request": "launch",
|
||||||
|
"preLaunchTask": "build",
|
||||||
|
"program": "${workspaceFolder}/bin/Debug/net10.0-windows/Titano.exe",
|
||||||
|
"args": ["--selftest"],
|
||||||
|
"cwd": "${workspaceFolder}/bin/Debug/net10.0-windows",
|
||||||
|
"console": "integratedTerminal",
|
||||||
|
"stopAtEntry": false,
|
||||||
|
"enableStepFiltering": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Attach a Titano (processo già avviato)",
|
||||||
|
"type": "coreclr",
|
||||||
|
"request": "attach",
|
||||||
|
"processName": "Titano.exe"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Vendored
+95
@@ -0,0 +1,95 @@
|
|||||||
|
{
|
||||||
|
// Stessa impostazione di Mimante ed Encelado: attività "process" che chiamano
|
||||||
|
// dotnet, nomi in italiano, $msCompile per portare gli errori nel pannello
|
||||||
|
// Problemi. Titano non ha una catena MSBuild dedicata perché non ne ha bisogno:
|
||||||
|
// è un solo progetto, senza pacchetti da ripristinare e senza installatore.
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"label": "build",
|
||||||
|
"detail": "Compilazione di debug, per F5 e per il controllo rapido degli errori.",
|
||||||
|
"type": "process",
|
||||||
|
"command": "dotnet",
|
||||||
|
"args": [
|
||||||
|
"build",
|
||||||
|
"${workspaceFolder}/Titano.slnx",
|
||||||
|
"-c",
|
||||||
|
"Debug",
|
||||||
|
"/property:GenerateFullPaths=true",
|
||||||
|
"/consoleloggerparameters:NoSummary"
|
||||||
|
],
|
||||||
|
"group": { "kind": "build", "isDefault": true },
|
||||||
|
"problemMatcher": "$msCompile"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "verifica",
|
||||||
|
"detail": "Genera una sequenza sintetica e la fa attraversare tutta la pipeline: 23 controlli, encoder e contenitore compresi. Da eseguire dopo ogni modifica.",
|
||||||
|
// In Release e non in Debug: le stesse verifiche passano da ~47 s a ~6 s,
|
||||||
|
// perché i cicli in virgola mobile di flow e blur non sono ottimizzati in Debug.
|
||||||
|
"type": "process",
|
||||||
|
"command": "dotnet",
|
||||||
|
"args": [
|
||||||
|
"run",
|
||||||
|
"--project",
|
||||||
|
"${workspaceFolder}/Titano.csproj",
|
||||||
|
"-c",
|
||||||
|
"Release",
|
||||||
|
"--",
|
||||||
|
"--selftest"
|
||||||
|
],
|
||||||
|
"group": { "kind": "test", "isDefault": true },
|
||||||
|
"presentation": { "reveal": "always", "panel": "dedicated" },
|
||||||
|
"problemMatcher": "$msCompile"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "cattura interfaccia",
|
||||||
|
"detail": "Salva un'immagine della finestra in bin/interfaccia.png. Serve a controllare la resa dei controlli disegnati a mano senza doverli guardare a occhio.",
|
||||||
|
"type": "process",
|
||||||
|
"command": "dotnet",
|
||||||
|
"args": [
|
||||||
|
"run",
|
||||||
|
"--project",
|
||||||
|
"${workspaceFolder}/Titano.csproj",
|
||||||
|
"-c",
|
||||||
|
"Release",
|
||||||
|
"--",
|
||||||
|
"--capture",
|
||||||
|
"${workspaceFolder}/bin/interfaccia.png",
|
||||||
|
"${input:sequenza}",
|
||||||
|
"${input:scheda}"
|
||||||
|
],
|
||||||
|
"presentation": { "reveal": "always", "panel": "dedicated" },
|
||||||
|
"problemMatcher": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "pulisci",
|
||||||
|
"detail": "Rimuove bin e obj di entrambe le configurazioni.",
|
||||||
|
"type": "process",
|
||||||
|
"command": "dotnet",
|
||||||
|
"args": ["clean", "${workspaceFolder}/Titano.slnx", "-v", "m"],
|
||||||
|
"problemMatcher": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"id": "sequenza",
|
||||||
|
"type": "promptString",
|
||||||
|
// Il valore predefinito è la sequenza lasciata sul disco dal task "verifica":
|
||||||
|
// eseguito quello, la cattura ha già qualcosa di sensato da mostrare.
|
||||||
|
// Lasciando il campo vuoto si cattura la finestra senza sequenza caricata.
|
||||||
|
"description": "Cartella della sequenza da caricare (vuoto = finestra vuota)",
|
||||||
|
"default": "${env:TEMP}\\Titano.SelfTest\\sequenza"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "scheda",
|
||||||
|
"type": "pickString",
|
||||||
|
"description": "Quale sezione del pannello di configurazione mostrare",
|
||||||
|
"options": [
|
||||||
|
{ "label": "Generale", "value": "0" },
|
||||||
|
{ "label": "Elaborazione immagini", "value": "1" },
|
||||||
|
{ "label": "Esportazione", "value": "2" }
|
||||||
|
],
|
||||||
|
"default": "0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
TITANO - registro delle modifiche
|
|
||||||
=================================
|
|
||||||
|
|
||||||
2026-08-13 Prima versione completa dell'applicazione.
|
|
||||||
|
|
||||||
Sviluppo da zero di Titano, applicazione desktop per time-lapse professionali,
|
|
||||||
con il vincolo di non usare alcuna libreria o strumento di terze parti.
|
|
||||||
Il progetto non contiene nessun PackageReference: oltre alla libreria standard
|
|
||||||
di .NET si usano solo API native di Windows richiamate via P/Invoke scritto a mano.
|
|
||||||
|
|
||||||
MODULI REALIZZATI
|
|
||||||
|
|
||||||
1. Ingestion e parsing metadati (Metadata/)
|
|
||||||
- Parser binario TIFF/Exif proprietario: header, catena di IFD, tutti i tipi
|
|
||||||
di dato della specifica, sotto-directory Exif e GPS.
|
|
||||||
- Riconoscimento dei contenitori: JPEG (percorso dei marker senza decodifica),
|
|
||||||
TIFF e RAW derivati, PNG (percorso dei chunk), HEIF/AVIF/WebP per scansione.
|
|
||||||
- Scanner XMP proprietario come sorgente complementare.
|
|
||||||
- Timestamp con frazione di secondo (SubSecTimeOriginal) e fuso orario;
|
|
||||||
tempo di posa, apertura e ISO anche nelle varianti APEX.
|
|
||||||
- Calcolo degli intervalli reali, cadenza nominale mediana e segnalazione
|
|
||||||
delle pause dell'intervallometro.
|
|
||||||
|
|
||||||
2. Deflicker e smoothing dell'esposizione (Analysis/)
|
|
||||||
- Misura della luminanza come media logaritmica troncata su istogramma,
|
|
||||||
calcolata in luce lineare su campionamento a griglia fissa.
|
|
||||||
- Curva target da regressione lineare locale pesata su finestra mobile, con
|
|
||||||
seconda passata robusta (peso di Tukey) che scarta i fotogrammi anomali.
|
|
||||||
Le rampe reali di luce restano intatte, lo sfarfallio viene rimosso.
|
|
||||||
- Applicazione dei guadagni con compressione dolce delle alte luci e
|
|
||||||
stabilizzazione opzionale del bilanciamento colore.
|
|
||||||
|
|
||||||
3. Motion blur sintetico e interpolazione (Motion/)
|
|
||||||
- Optical flow proprietario: piramide gaussiana e schema differenziale
|
|
||||||
iterativo su griglia rada, con filtro mediano fra i livelli.
|
|
||||||
- Shutter angle reale per fotogramma; sfocatura mancante composta in
|
|
||||||
quadratura e resa con filtro di ricostruzione direzionale.
|
|
||||||
- Interpolazione temporale con warping bidirezionale per uniformare la
|
|
||||||
cadenza e gestire in modo adattivo la durata dei fotogrammi.
|
|
||||||
|
|
||||||
4. Streaming ed encoding video (Video/)
|
|
||||||
- Multiplexer MP4 (ISO-BMFF) scritto da zero: ftyp, mdat in streaming con
|
|
||||||
dimensione a 64 bit, moov completo con stts a durate variabili, stss,
|
|
||||||
stsz, co64, avcC/hvcC costruiti dai parameter set del bitstream.
|
|
||||||
- Encoder pilotato direttamente come Media Foundation Transform, con
|
|
||||||
percorso asincrono per le trasformazioni hardware (Intel/AMD/NVIDIA)
|
|
||||||
e ripiego automatico su quelle software.
|
|
||||||
- Conversione RGB lineare a NV12 BT.709 scritta in-house.
|
|
||||||
|
|
||||||
5. Interfaccia (UI/)
|
|
||||||
- Tema scuro con ogni controllo disegnato a mano in GDI+: pulsanti,
|
|
||||||
interruttori, cursori, schede, barra di avanzamento.
|
|
||||||
- Grafico vettoriale della curva di esposizione: luminanza misurata
|
|
||||||
sovrapposta alla curva target, area di correzione, corsia dei guadagni,
|
|
||||||
fasce delle anomalie di cadenza, zoom, spostamento e tooltip.
|
|
||||||
- Tabella dei fotogrammi a rendering virtuale.
|
|
||||||
- Pannello di configurazione in tre sezioni: Generale, Elaborazione
|
|
||||||
immagini, Esportazione video.
|
|
||||||
- Anteprima elaborata dallo stesso motore usato in esportazione.
|
|
||||||
|
|
||||||
ARCHITETTURA
|
|
||||||
- Nessun file temporaneo: i dati passano fra le fasi solo in memoria, l'unica
|
|
||||||
scrittura su disco è il flusso compresso finale.
|
|
||||||
- Impronta di memoria costante: buffer poolati e canale a capacità limitata,
|
|
||||||
l'occupazione non dipende dal numero di fotogrammi della sequenza.
|
|
||||||
- Thread di calcolo separati dal thread dell'interfaccia.
|
|
||||||
|
|
||||||
VERIFICA
|
|
||||||
Comando "Titano.exe --selftest": genera una sequenza sintetica dalle
|
|
||||||
proprietà note e la fa attraversare l'intera pipeline confrontando 23
|
|
||||||
grandezze con i valori attesi. Tutte superate, compresa la ri-decodifica
|
|
||||||
del file prodotto con il lettore di sistema.
|
|
||||||
|
|||||||
+18
-2
@@ -15,7 +15,7 @@ internal static class Program
|
|||||||
{
|
{
|
||||||
if (args.Length > 0 && args[0] is "--selftest" or "-t")
|
if (args.Length > 0 && args[0] is "--selftest" or "-t")
|
||||||
{
|
{
|
||||||
AttachConsole(AttachParentProcess);
|
EnsureConsole();
|
||||||
string directory = args.Length > 1
|
string directory = args.Length > 1
|
||||||
? args[1]
|
? args[1]
|
||||||
: Path.Combine(Path.GetTempPath(), "Titano.SelfTest");
|
: Path.Combine(Path.GetTempPath(), "Titano.SelfTest");
|
||||||
@@ -28,7 +28,7 @@ internal static class Program
|
|||||||
|
|
||||||
if (args.Length > 1 && args[0] == "--capture")
|
if (args.Length > 1 && args[0] == "--capture")
|
||||||
{
|
{
|
||||||
AttachConsole(AttachParentProcess);
|
EnsureConsole();
|
||||||
ApplicationConfiguration.Initialize();
|
ApplicationConfiguration.Initialize();
|
||||||
return Capture(args[1], args.Length > 2 ? args[2] : null,
|
return Capture(args[1], args.Length > 2 ? args[2] : null,
|
||||||
args.Length > 3 && int.TryParse(args[3], out int tab) ? tab : 0);
|
args.Length > 3 && int.TryParse(args[3], out int tab) ? tab : 0);
|
||||||
@@ -39,6 +39,22 @@ internal static class Program
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Rende visibili i messaggi delle modalità a riga di comando.
|
||||||
|
///
|
||||||
|
/// L'eseguibile è compilato come applicazione a finestre e quindi nasce senza console:
|
||||||
|
/// agganciare quella del processo padre è l'unico modo di farsi leggere da un terminale.
|
||||||
|
/// Ma se lo standard output è già dirottato — una pipe, un file di registro, il task di
|
||||||
|
/// un editor — l'aggancio sostituirebbe quel dirottamento e i messaggi finirebbero nella
|
||||||
|
/// console invece che dove sono attesi. In quel caso non si aggancia niente: i gestori
|
||||||
|
/// ereditati vanno già bene.
|
||||||
|
/// </summary>
|
||||||
|
private static void EnsureConsole()
|
||||||
|
{
|
||||||
|
if (Console.IsOutputRedirected) return;
|
||||||
|
AttachConsole(AttachParentProcess);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Apre l'interfaccia, opzionalmente vi carica una sequenza, e ne salva un'immagine.
|
/// Apre l'interfaccia, opzionalmente vi carica una sequenza, e ne salva un'immagine.
|
||||||
/// Serve a verificare la resa dei controlli disegnati a mano senza intervento manuale.
|
/// Serve a verificare la resa dei controlli disegnati a mano senza intervento manuale.
|
||||||
|
|||||||
Reference in New Issue
Block a user