Compile

Vom Skript zur nativen Executable — ein Klick. Der Empfänger installiert nichts.

Das ist das Feature, das OpticScript abhebt: Jedes Skript, das Sie im Playground schreiben, ist einen Button-Klick von einer echten, in sich geschlossenen .exe (oder Linux- / macOS-Binary) entfernt. Keine Python-Runtime, kein Node-Setup, kein pip install, kein Docker-Image, keine node_modules. Eine Datei. Versenden. Fertig.

$ ls -lh bin/
-rwxr-xr-x  1 mlc  staff   16M  17. Mai 12:33  enhance
$ ./enhance --input portrait.jpg --output portrait_warm.jpg \
            --brightness 1.15 --saturation 1.4 --vignette 0.5
✓ portrait_warm.jpg

Diese Binary ist ~16 MB groß, bettet die komplette Bild-Engine plus Ihr Skript ein und läuft in derselben nativen Geschwindigkeit wie der Playground selbst.

Im Playground — ein Klick

Den Make Exe-Button in der Editor-Toolbar klicken. Ein Dialog öffnet sich, fragt nach einem Tool-Namen, wählt standardmäßig Ihre aktuelle Plattform, und kurz darauf bekommen Sie den Pfad zur fertigen Binary. Der Build dauert Millisekunden, keine Minuten — die Engine liegt als vorgebauter Stub bereit; der Compiler hängt Ihr Skript als Blob an dessen Ende.

Dasselbe auf der Kommandozeile:

mlcos-compile-rs enhance.js
# → ./enhance       (Linux/macOS)
# → ./enhance.exe   (Windows)

Überall ausführbar — der Empfänger braucht kein OpticScript, keinen Playground, kein Rust, Go, Python oder sonstige Runtime. Die Binary ist vollständig eigenständig.

Was in der Binary landet

Eingebettet Warum das zählt
Die Bild-Engine (~16 MB) Native Pixel-Ops, keine externe Runtime.
Ihr Skript Als JS-Quelltext — --help liest es zurück, damit Sie auch später noch wissen, was das Tool tut.
Beide eingebauten Schriften (Inter + JetBrains Mono) Text-Overlays / Wasserzeichen brauchen keine Font-Dateien.
Installierte Engine-Erweiterungen Custom JS-Module (z.B. die cube-Extension) reisen automatisch mit.

Was nicht eingebettet wird (bewusst extern):

  • KI-Modellgewichte (GFPGAN, Real-ESRGAN). Tools, die diese aufrufen, laufen neben dem AI Tools Pack — dieselben Modelldateien wie im Playground.

Ihre Skript-Direktiven werden zu CLI-Flags

Jede //!INPUT:-, //!OUTPUT:- und //!PARAM:-Zeile am Skript-Anfang wird zu einem getypten Kommandozeilen-Flag. Das Skript:

// enhance.js
//!INPUT: INPUT
//!OUTPUT: OUTPUT
//!PARAM: BRIGHTNESS:number=1.10,min=0.5,max=2.0
//!PARAM: SATURATION:number=1.20,min=0,max=3
//!PARAM: VIGNETTE:number=0.30,min=0,max=1

Engine.loadImage(INPUT)
  .brightness(BRIGHTNESS)
  .saturation(SATURATION)
  .vignette(VIGNETTE)
  .save(OUTPUT);

Kompiliert, dann --help:

$ ./enhance --help
enhance
Erstellt mit MLC OpticScript v2.1.3 · https://mlcgo.eu
Copyright (c) 2026 Michael Lechner · Elastic License 2.0

VERWENDUNG:
    enhance --INPUT=<Pfad> --OUTPUT=<Pfad> --BRIGHTNESS=<Wert>
            --SATURATION=<Wert> --VIGNETTE=<Wert>

EINGABEN:
    --INPUT=<Pfad>          (Bild laden)

AUSGABEN:
    --OUTPUT=<Pfad>         (Speicherziel; `-` für stdout)

PARAMETER:
    --BRIGHTNESS=<Wert>     (Standard: 1.10)
    --SATURATION=<Wert>     (Standard: 1.20)
    --VIGNETTE=<Wert>       (Standard: 0.30)

Die in //!PARAM: deklarierten min/max-Bereiche werden zur Laufzeit geprüft — Werte außerhalb des Bereichs werden abgelehnt, bevor das Skript überhaupt startet.

Einen ganzen Ordner verarbeiten — ohne Skriptänderung

Dieselbe Binary erledigt Batch-Verarbeitung. --INPUT auf einen Glob und --OUTPUT auf ein Template setzen — die Engine bleibt über den ganzen Loop "warm":

./enhance --INPUT='photos/*.jpg' --OUTPUT='enhanced/{stem}.png'
batch: 17 Datei(en) via --INPUT
✓ OUTPUT → enhanced/IMG_0001.png
✓ OUTPUT → enhanced/IMG_0002.png
…
Eingabe-Muster Beispiel
Glob 'photos/*.jpg', '**/*.png'
Dateiliste (eine pro Zeile) @todo.txt (#-Kommentare erlaubt)
Komma-Liste a.png,b.png,c.png

Ausgabe-Templates unterstützen die Platzhalter {stem} / {name} / {ext} / {dir} / {idx} / {n}.

Filter-Modus — - ist stdin / stdout

Jede kompilierte Binary funktioniert auch als Unix-Filter:

# PNG von stdin lesen, JPEG nach stdout schreiben
cat foto.png | ./enhance --INPUT=- --OUTPUT=- \
                         --stdout-format=jpg --silent > raus.jpg

# Zwei Filter verketten
cat in.jpg | ./grayscale --INPUT=- --OUTPUT=- --silent \
           | ./watermark --INPUT=- --OUTPUT=- --silent \
                         --BRAND="© Acme" > final.png

Feature-Check

Was in jeder kompilierten Binary „einfach läuft", ohne externe Abhängigkeiten:

  • PNG / JPEG / WebP / AVIF / TIFF lesen + schreiben
  • Animiertes WebP + APNG + Multi-Page TIFF für Animationen
  • EXIF beim Laden gelesen, beim JPEG-Save geschrieben (meta.exif.*)
  • SVG-Import (resvg) und SVG-Export (vtracer) — voller Vektor-Loop
  • 35+ Pixel-Operationen — Weichzeichnen, Schärfen, Warp, Blend, Farbkorrektur, Kantenerkennung, …
  • Textrendering mit zwei eingebetteten Variable-Fonts (Inter, JetBrains Mono)
  • WarpGrid-Mesh-Transformationen für Perspektive / 3D-Flächen-Projektion
  • Eigene Convolution-Kernel für Schärfen / Prägen / Motion-Blur / etc.

Cross-Plattform-Builds

Der „Make Exe"-Button im Playground baut standardmäßig für Ihr aktuelles OS. Cross-Compilation (z.B. Windows-.exe von macOS aus) ist ein Pro-Feature — siehe Preisliste.

Auf der Kommandozeile:

# Nativ (Host-Plattform)
mlcos-compile-rs enhance.js --overwrite

# Ausgabename / -pfad überschreiben
mlcos-compile-rs enhance.js --name colour-enhancer --output ~/bin/

# Cross-Target (Pro): auf einen vorgebauten Stub für das Ziel-OS zeigen
mlcos-compile-rs enhance.js --stub ./stubs/mlcos-run-rs-windows-x64.exe

Drei Wege zur Distribution, sortiert nach Aufwand

Nicht jedes Mal braucht es einen vollständigen Compile. Wenn Ihr Publikum den OpticScript-Installer schon hat, gibt es leichtere Varianten:

Zielgruppe Was Sie ausliefern Was sie installieren
Eigenes Team / intern enhance.js + mlcos-run-rs enhance.js … OpticScript
Poliertes Tool, intern mlcos-compile-rs --wrap=auto enhance.jsenhance.cmd / enhance.sh OpticScript
Externe Nutzer enhance.exe (kompiliert) Nichts

Kompilierte Binaries sind die Antwort für die dritte Zeile — die, in der Sie null Rückfragen vom Empfänger wollen.

Fehlerbehebung

  • INPUT is not defined zur Laufzeit — das Skript verwendet INPUT, deklariert aber //!INPUT: INPUT nicht (oder den passenden Key). Die Direktive ergänzen, damit der Compiler weiß, was er verdrahten soll.
  • batch mode … requires a placeholder — Ihr Eingabe-Flag passte auf mehrere Dateien, aber der Ausgabe-Pfad ist fix. Einen Platzhalter wie {stem} in die Ausgabe einbauen.
  • two inputs are multi-valued patterns; only one input may batch — Eine der Eingaben auf eine einzelne Datei fixieren; die andere darf weiter batchen.

Siehe auch