Files
klarbild/README.md
T

4.8 KiB
Raw Blame History

Klarbild

Verwandelt Screenshots und Fundstücke in saubere, druckfertige Bilder — Rahmen und Shop-Oberflächen entfernen, exakte Fotoformate (30×40 cm etc.), The-Frame-Querformat, für den Cricut freistellen, und automatisch nach Picdrop ausliefern.

Claim: „Screenshot rein, sauberes Bild raus."

Stack

Astro 5 (SSR, Node standalone) + React-Inseln · Postgres · S3 (MinIO) · pg-boss · sharp · pdf-lib (Druckbogen) · grammY (Telegram) · OKLCH-Tokens, kein Tailwind. Deploy: Gitea → Coolify → Hetzner.

Entwicklung

npm install
cp .env.example .env   # Werte eintragen
npm run dev

Migrationen und Seeds laufen beim Serverstart automatisch. Erststart-Passwörter über SEED_TILL_PASSWORD / SEED_LEA_PASSWORD.

Funktionen (Kurzüberblick)

  • Modi: Bereinigen (Screenshot säubern/freistellen/formatieren), Umwandeln (ein Bild + Text, z. B. Foto → Ölgemälde), Kombinieren (mehrere Bilder + Text), Neu erzeugen (nur Text).
  • Formate: feste cm-/DIN-/Screen-Formate und frei definierbare — Schlüssel WxH (z. B. 25x35) oder sticker<N> (sticker5 = 5×5 cm). Parsing in src/lib/format.ts, keine Migration nötig.
  • Dateiformat: PNG (verlustfrei, Transparenz) oder JPG (klein, Picdrop-freundlich). Global über settings.output_ext, pro Rezept via recipes.output_ext, pro Umwandlung im Studio. JPG nur ohne Alpha.
  • Auslieferung: Picdrop (SFTP/FTPS) + beliebige Zusatzziele; NAS/Backup-Ziele; optionaler .md-Metadaten-Beileger pro Ziel schaltbar. Nicht-transparente Ergebnisse gehen als JPG an Picdrop.
  • Bibliothek: Ordner, Farbmarkierungen, Prompt-Anzeige, Vorher/Nachher, Vollbild + „In Fotos sichern".
  • Rechte/Datenschutz: Sichtbarkeit (eigene/alle), anonyme Generierungen, private Sessions, NSFW-Gate.
  • Telegram-Bot (grammY-Webhook) als vollwertiger Website-Ersatz. API-Token (Bearer) für /api/*.
  • Druck (/druck, ohne KI): Bilder exakt auf physische Maße bringen (interaktiver Zuschnitt mit Zoom/Verschieben) und mehrere davon in 100-%-Größe mit Schnittmarken auf einen Bogen setzen — Passbildsatz, Kita-Satz, Sticker. Papier DIN A6A2 inkl. A3+, Fotopapier 9×1320×30, Letter/Legal oder freies Maß. Marken: Eckmarken (0,25 pt, außerhalb des Endformats) oder durchgehende Linien. Beschnittzugabe 010 mm. Ausgabe: PDF in 1:1 (pdf-lib) bzw. Einzelbild mit dpi-Metadaten. Layout: gleiche Größen → exaktes Raster, gemischte Größen → MaxRects-Packer. Kern: src/lib/paper.ts (Formate), src/lib/printlayout.ts (reine Mathematik, getestet), src/lib/printrender.ts (sharp + pdf-lib). Auch per Telegram („📐 Druckbogen") und MCP (exact_size, print_sheet).
  • Admin: Key/Picdrop/Modelle/Nutzer/Kostendeckel/Presets/Speicherverwaltung, Picdrop-Diagnose.

Datenmodell / Migrationen

Nummerierte SQL in migrations/, beim Start automatisch (kein ORM-Push). Wichtige Spalten: items.has_alpha, jobs.status (inkl. failed), jobs.finished_at, settings.output_ext / recipes.output_ext, settings.*_metadata_sidecar, delivery_targets.*, print_presets (Bogen-Vorlagen, 013).

Tests

npm test — Node-Testrunner über tsx. Deckt die Druck-Layoutmathematik ab (Maß-Parsing, mm → px exakt, Überlappungsfreiheit, Ränder, Beschnittzugabe, Markengeometrie, Mehrseitigkeit).

Stolpersteine & Lösungen (Learnings)

  • „Bild bei Picdrop ✓, aber nicht in der Galerie": Fehldiagnose vermeiden — die Dateien lagen die ganze Zeit korrekt per SFTP in /POSTER LEA (per Admin → Picdrop → „Ordner anzeigen" verifizierbar). Der eigentliche Grund war die Sortierung in der Picdrop-Weboberfläche, nicht das Format. Unabhängig davon liefern wir nicht-transparente Ergebnisse jetzt als JPG aus (src/lib/delivery.ts, deliverableBuffer): ~25 MB PNG → ~2 MB JPG, schneller und handlicher — plus wählbares Ausgabeformat (output_ext).
  • „Unbekanntes Format: sticker5": Seed legte ein Rezept mit Formatschlüssel sticker5 an, den der Resolver nicht kannte → jeder Lauf schlug fehl. Lösung: generisches Parsen von sticker<N>/WxH.
  • Auftrag trotz Fehler grün: jobs.status kannte kein failed; alle Positionen fehlgeschlagen wurde trotzdem done. Lösung: Status failed, wenn done=0 && failed>0 (src/worker.ts maybeComplete).
  • Doppelte Datums-/UUID-Namen: \b-Wortgrenzen greifen nicht an Unterstrichen. Lösung: \b entfernt, Datum/UUID/Hex global ersetzt (src/lib/pipeline.ts cleanMotif).
  • Content-Type bei gemischten PNG/JPG-Ergebnissen: file.ts snifft jetzt die Magic Bytes.
  • .tmp--Reste auf Picdrop: früher Temp-Rename-Bug; cleanupTmp + Admin-Knopf „Reste aufräumen".

Status

Reihenfolge und Nachweise siehe CLAUDE.md. Anforderungen im Handover-Paket (Imagetool-Lea/00..07). Führend: 01-anforderungen.md.