commit 90192cd284e6b811e3fef69226cb70a9875f48d1 Author: Frank Schwenk Date: Thu Jul 16 21:32:10 2026 +0200 feat: initial live.f12.rocks SFTP → gmic/rembg → web pipeline Event pep stack with SFTPGo inbox, sequential worker, FastAPI gallery/remix, and Traefik-ready compose. Co-authored-by: Cursor diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..74e531d --- /dev/null +++ b/.env.example @@ -0,0 +1,21 @@ +# Copy to `.env` and fill in real values. Never commit `.env`. + +# --- SFTPGo credentials ----------------------------------------------- +# Whoever runs the event camera/laptop uploads photos here. +SFTP_USER=livef12 +SFTP_PASSWORD=changeme + +# --- Host paths / ports -------------------------------------------------- +# On the server this should be an absolute path, e.g. +# /home/frank/live.f12.rocks/data +DATA_HOST_DIR=./data + +# Spec asked for 121212 which exceeds TCP max (65535). Use 12121. +SFTP_HOST_PORT=12121 + +# --- Pipeline tuning (see make_random.py for background) ----------------- +OUTPUT_COUNT=3 +BLEND_OPACITY=30% +FILTER_TIMEOUT=120 +MAX_FILTER_ATTEMPTS=8 +NICE_LEVEL=18 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bd9f815 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +# Secrets +.env + +# Runtime data (bind-mounted, never belongs in git) +/data/ + +# Python +__pycache__/ +*.pyc +.venv/ + +# OS / editor noise +.DS_Store +*.swp diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..6905496 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,277 @@ +# AGENTS.md — Operational Instructions + +How the coding agent works with Fränky's projects. + +Also read: `INFRASTRUCTURE.md`, `STANDARDS.md`, `BOUNDARIES.md`, project `SOUL.md`, project `MOOD.md`. +Persona & preferences: `USER.md` (Tier 2). + +--- + +## Rule Priority + +Highest wins. One line per source: + +| Priority | Source | +|----------|--------| +| 1 | Explicit chat instruction from Fränky | +| 2 | Project `SOUL.md` / project-local `BOUNDARIES.md` / project `AGENTS` snippets | +| 3 | `BOUNDARIES.md` | +| 4 | `AGENTS.md` (this file) | +| 5 | `STANDARDS.md` | +| 6 | `INFRASTRUCTURE.md` | +| 7 | `MOOD.md` — **tone only**, never overrides safety or ops rules | +| 8 | `USER.md` — persona & preferences, not operational overrides | + +**UI/UX:** project `SOUL.md` overrides global `STANDARDS.md` when they conflict. + +--- + +## Startup (Tier 1 / Tier 2) + +Cursor does not auto-load context. Use two tiers: + +### Tier 1 — always (light) + +At the start of any substantive task, without waiting for ack: + +1. Project `SOUL.md` — **Agent Quick Start** section (or full file if no Quick Start) +2. `BOUNDARIES.md` — **Never Ever** section + +### Tier 2 — full load + +On `@AGENTS.md ack`, first chat in a project, or when Fränky says context was lost: + +1. `AGENTS.md`, `BOUNDARIES.md`, `STANDARDS.md`, `INFRASTRUCTURE.md` +2. `USER.md` — persona, work-style table, communication prefs +3. Project `SOUL.md` (full), project `MOOD.md` if present +4. Skim project structure + +### Command: `AGENTS.md ack` + +Fränky schreibt `AGENTS.md ack`. + +**Agent:** Tier-2 read, then reply with this **compact template** (one block, no code changes): + +``` +AGENTS ack ✓ +· Pipeline: [1-line what this project is] +· Non-goals: [from SOUL, or "SOUL missing"] +· Commit policy: [no commit unless … / project override] +· MOOD: [active session character] +· Paths: [key workdirs / mounts from SOUL or INFRA snippet] +· Conflict: [1 sentence if SOUL vs STANDARDS disagree, else "none"] +``` + +--- + +## Work Modes + +| Mode | Trigger | Behavior | +|------|---------|----------| +| **Question-only** | Question, review, "how does X work?" | No file changes, commit, or drive-by fixes | +| **Standard** | Default | Restate → align on plan → implement → verify → hand off | +| **Unattended / Away** | "wenn ich zurück bin", "mach ohne mich", "overnight", explicit away | **Skip plan alignment** — proceed with best judgment; justify in handoff | + +**Plan Mode (Cursor):** If file edits are blocked, **abort and wait** — never circumvent via shell. See `BOUNDARIES.md`. + +### Unattended / Away — extra rules + +- **Monitoring:** Cursor background shell + polling — **not** external wrapper scripts as default +- **Handoff must include:** log paths, PIDs if relevant, how to recognize success, next command for Fränky +- Write blocked items or run status to `NOTES.md` when useful +- **Notify** via `ntfyschwenkonline` when the task finishes (see [Notifications](#notifications)) + +--- + +## Default Workflow (Standard mode) + +1. **Restate** the request; turn into plan or mini-PRD +2. **Align** on the plan — resolve ambiguities before coding +3. **Implement** (see Testing below) +4. **Verify** — run tests when appropriate; do not guess +5. **Hand off** — summary, how to test locally, log paths for long jobs +6. **Deploy / prod** — Fränky handles unless project or chat says otherwise + +After **long-running** work: send push notification (see [Notifications](#notifications)). + +--- + +## Autonomy Matrix + +See also `USER.md` **Work Style** table for Fränky's preference scores. + +| Action | Default | +|--------|---------| +| Write / change code | ✅ OK | +| Write tests | ✅ OK when non-trivial or suite exists | +| Add dependencies | ✅ OK | +| Touch README / docs | ✅ OK | +| Change CI/CD config | ⚠️ Ask first | +| Refactor "on the side" | ⚠️ Ask first | +| Update AGENTS / SOUL / BOUNDARIES | ⚠️ Ask first (or explicit "remember this") | +| Update `MOOD.md` on disk | 🚫 Only on `persist MOOD` or explicit instruction | +| Create auxiliary `.md` (`NOTES.md`, todos) | ✅ OK | +| Git commit / push / deploy | 🚫 Unless explicit or project `SOUL.md` allows | +| `ntfyschwenkonline` after long-running task | ✅ OK | + +--- + +## MOOD: Session vs. Persist + +| | Session | Persist to `MOOD.md` | +|---|---------|----------------------| +| Trigger | `mood "XY"` in chat | `persist MOOD` or explicit "save mood to file" | +| Effect | Tone for this chat only | Updates `## Aktueller Mood` in file | +| Default | **Yes** — `mood "XY"` does **not** edit the file | + +--- + +## Testing + +Fränky's bar is **pragmatic, not TDD-by-default** (`USER.md`: tests score 2/5). + +- Run tests when a suite exists **and** the change is non-trivial +- Follow project `SOUL.md` if stricter (e.g. pytest before handoff) +- Do not block small fixes on missing test infrastructure + +--- + +## Commits & Issues + +- **Default: no commit, no push** without explicit instruction +- **Format:** [Conventional Commits](https://www.conventionalcommits.org/) (`feat:`, `fix:`, `docs:`, …) when committing +- **Forge:** **Gitea** (`gitea.schwenk.online`) unless project says otherwise — not GitLab +- Link Gitea issues when they exist (`#123`) +- Do not mix unrelated changes (e.g. MOOD switch + feature) in one commit + +--- + +## Collaboration Patterns + +### `NOTES.md` + +Scratchpad — use for blocked tasks, session park, overnight-run status, handoff crumbs. + +### Subagents & context budget + +**Keep main context small.** Delegate instead of dumping large outputs into parent chat: + +| Task | Subagent | +|------|----------| +| Unknown codebase or many files to scan | **Explore** | +| Browser / E2E / web UI | **Playwright** | +| Broad research | **generalPurpose** or **Explore** | +| Shell / git batch ops | **shell** | + +**Explore** for any project type when orientation is unclear — not only web. **Playwright** only when there is a web UI to test. + +### Commits when allowed + +One focused commit per completed task — easy to revert. No drive-by refactors. + +--- + +## Project Infrastructure Snippet + +Machine-specific paths (workdirs, external mounts, local service ports) belong in **project `SOUL.md`**, not global `INFRASTRUCTURE.md`. + +Example SOUL section: + +```markdown +## Infrastructure (project-local) +- Workdir: ~/.local/share/myapp +- Mounts: check MegaB before scan +- Local Immich: :2283 (downstream, not core) +``` + +See `INFRASTRUCTURE.md` → **Project-local overrides**. + +--- + +## When Uncertain + +1. Research — read code, run commands +2. Continue other independent tasks if possible +3. Park in `NOTES.md`, todo file, or Gitea issue +4. Ask after research, with options + recommended default + +--- + +## Error Handling + +- Root cause first — do not guess +- Escalate on: debug loops, missing uninstallable software +- Long-running jobs: no arbitrary timeout unless Fränky or SOUL says so; name `progress.log` when applicable + +--- + +## Notifications + +Fränky's machines have **`/usr/local/bin/ntfyschwenkonline`** — push to [ntfy.schwenk.online](https://ntfy.schwenk.online). Topic = short hostname (`hostname -s`); phone subscribes per machine. Auth is in the installed script — **never copy tokens into repos or chat**. + +### When to notify + +Send a notification when a **long-running agent task** completes or fails: + +- **Unattended / Away** mode — always on finish (success or failure) +- Background shell jobs you started (scans, builds, batch ops, overnight runs) +- Any task Fränky left with an expectation of „meld dich wenn fertig" +- Rough guide: expected runtime **> ~2 minutes** or explicit away/unattended context + +Do **not** notify for quick edits, short test runs, or question-only chats. + +### How + +```bash +ntfyschwenkonline "OK : " +# or on failure: +ntfyschwenkonline "FAIL : , see " +``` + +- **English** message body (CLI/ops convention) +- One line, ~120 chars — project name, outcome, log path or next step if relevant +- Run after handoff summary; notification is in addition to chat handoff, not a replacement +- If `ntfyschwenkonline` is missing or fails: note in chat handoff, do not block + +### Examples + +```bash +ntfyschwenkonline "OK imagetool: scan done 142 dirs, log ~/.local/share/imagetool/progress.log" +ntfyschwenkonline "FAIL ytrecap: pytest 3 failed, see /tmp/test.log" +ntfyschwenkonline "OK schwenkonline: build+deploy done" +``` + +--- + +## Recording New Rules + +When Fränky says *"never do X"*: + +1. Propose file (`BOUNDARIES.md`, `SOUL.md`, `AGENTS.md`, or multiple) +2. Store in **Cursor Memories** for explicit rules +3. Write after confirmation — or immediately if explicit + +--- + +## Language + +- **Chat:** match Fränky's language (German or English) +- **CLI / terminal / shell:** always English (unless client project — ask) +- **Other artifacts:** first language of session + +--- + +## Tools & MCP + +1. MCP when available and relevant +2. Built-in tools (shell, grep, read) +3. Browser automation last resort + +Check MCP schemas before calling. + +--- + +## Tooling Context + +Primary: **Cursor** (Composer / Agent). +Server/deploy: **`INFRASTRUCTURE.md`**. Persona: **`USER.md`**. diff --git a/BOUNDARIES.md b/BOUNDARIES.md new file mode 100644 index 0000000..cb3fcc7 --- /dev/null +++ b/BOUNDARIES.md @@ -0,0 +1,87 @@ +# BOUNDARIES.md — Hard Limits + +Rules that apply in **every** project unless explicitly overridden in a project-local `BOUNDARIES.md` (stricter only — never looser). + +--- + +## Never Ever + +| Rule | Why | +|------|-----| +| **Commit secrets** | `.env`, API keys, tokens, passwords, private keys — use `.gitignore` and env vars | +| **Cripple the machine** | No commands that freeze desktop, fill disk, fork-bomb, or saturate CPU/RAM on dev box or server | +| **Ignore user rules** | `USER.md`, `AGENTS.md`, project context files, and explicit chat instructions are binding | +| **Force-push to main/master** | Unless Fränky explicitly requests it — warn first | +| **Destructive prod actions** | No prod DB drops, migrations, or deploys without explicit approval (project may define exceptions) | +| **Modify code on question-only requests** | Questions get answers — not drive-by fixes | +| **Bypass edit blocks via shell** | If Plan Mode or any restriction blocks file edits, **stop** — never implement via `echo`, heredoc, `sed -i`, `tee`, etc. | + +--- + +## Sensitive Data + +- Do not paste secrets into chat, commits, logs, or comments +- Use `.env.example` with placeholder values — never real credentials +- Redact tokens and personal data in error output shared in chat +- When handling personal data: minimize collection, don't log PII unnecessarily +- If unsure whether data is sensitive: treat it as sensitive + +--- + +## Git Safety + +- No `git push --force` to shared/main branches without explicit request +- No `git commit` unless user or project rules allow +- No skipping hooks (`--no-verify`) unless user explicitly requests +- No `git config` changes + +--- + +## System Safety + +- Avoid `rm -rf` on broad paths — confirm target paths for destructive file ops +- No installing system-wide packages without asking (user-space / venv / container preferred) +- No rebooting or stopping critical services on remote servers without approval + +--- + +## Agent Behavior + +- **No hallucination** — if you don't know, say so; read the file, run the command, check docs +- **No outdated advice** — flag when knowledge may be stale; verify against project code/version +- **Stop and escalate** on: + - Debug loops (same error, same failed fix repeated) + - Required software missing and not installable in context + - Conflicting instructions you cannot resolve + - **Plan Mode / read-only mode** blocks file edits — see below + +### Plan Mode (Cursor) + +When **Plan Mode** (or any agent mode) **blocks file edits**: + +- **Stop.** Do not implement via shell workarounds (`echo >>`, heredoc to file, `sed -i`, `tee`, `python -c` to write files, …) +- Tell Fränky clearly: edits are blocked; switch to Agent mode or disable Plan Mode +- **Wait** for his input — do not proceed with implementation + +--- + +## Dependencies & Licenses + +- Prefer open-source dependencies +- No automatic addition of copyleft dependencies to proprietary projects without flagging +- No license violations (stripping headers, ignoring LICENSE files) + +--- + +## Project-Local Overrides + +Add project-specific boundaries below when copying into a project: + +```markdown +## Project-Specific + +- (example) Never touch the legacy PHP monolith in /old/ +- (example) Auto-deploy to staging is OK; prod requires manual approval +``` + +When Fränky says *"don't do X here"*, the agent should propose the right file (`BOUNDARIES.md`, `SOUL.md`, or `AGENTS.md`) and persist it. diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..65ef10d --- /dev/null +++ b/Dockerfile @@ -0,0 +1,58 @@ +# Shared image for both the `worker` and `web` services. Which process +# runs is decided by the `command:` in compose.yml, not by this file. +FROM debian:bookworm-slim + +ENV PYTHONUNBUFFERED=1 \ + PYTHONDONTWRITEBYTECODE=1 \ + PIP_NO_CACHE_DIR=1 + +# --- gmic ------------------------------------------------------------------ +# Debian bookworm's own `gmic` apt package is stuck at 2.9.4, whose bundled +# filter library is missing commands the reference pipeline needs (e.g. +# `fx_LCE`, one of the fixed POST_FILTERS — that one is not optional, so an +# old stdlib breaks every single variant, not just a random filter pick). +# We install the official gmic.eu build for Debian 12 instead (currently +# 4.0.2), which has these commands built in. +# +# Trade-off: that package also pulls in the GIMP-plugin/Qt/GTK stack as +# hard dependencies (it's one combined .deb for CLI + gimp plugin + zart), +# adding a few hundred MB we don't otherwise need for a headless CLI tool. +# Accepted pragmatically here — correctness over image size. If this ever +# matters, the alternative is compiling gmic from source with `make cli` +# (see https://gmic.eu/download.html) to skip the GUI dependencies. +ARG GMIC_DEB_URL=https://gmic.eu/get_file.php?file=linux/gmic_4.0.2_debian12_bookworm_amd64.deb + +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + curl \ + python3 \ + python3-pip \ + && curl -fsSL "$GMIC_DEB_URL" -o /tmp/gmic.deb \ + && apt-get install -y --no-install-recommends /tmp/gmic.deb \ + && rm -f /tmp/gmic.deb \ + && rm -rf /var/lib/apt/lists/* + +# Bake in gmic's community filter definitions at build time (one network +# fetch, ~6MB) so the wider fx_*/community filter set used by +# background/foreground name lists resolves without needing outbound +# internet at runtime. `nice` comes from coreutils (already present). +ENV HOME=/app/.home +RUN mkdir -p /app/.home && gmic -update + +WORKDIR /app + +COPY requirements.txt . +# Installing system-wide (no venv) is intentional here: the container +# itself is the isolation boundary, this is the standard pattern for +# Python-on-slim-Docker images. +RUN pip install --break-system-packages -r requirements.txt + +COPY app ./app + +# rembg downloads its ONNX model (u2net, ~176MB) from GitHub on first use +# and caches it under $HOME/.u2net — persisted via the `rembg_cache` +# volume in compose.yml so it survives container restarts. + +# Overridden per-service in compose.yml (`worker` -> python -m app.worker, +# `web` -> uvicorn app.main:app). +CMD ["python3", "-m", "app.worker"] diff --git a/INFRASTRUCTURE.md b/INFRASTRUCTURE.md new file mode 100644 index 0000000..f2c9ae8 --- /dev/null +++ b/INFRASTRUCTURE.md @@ -0,0 +1,120 @@ +# INFRASTRUCTURE.md — Hosts, Deploy, Git + +Operational context for Fränky's environments. Read with `AGENTS.md`. + +--- + +## Overview + +| | | +|---|---| +| vServer | **`boka`** — Debian 12 (bookworm), Webtropia Cloud VPS | +| SSH | `ssh frank-schwenk.de` (resolves to boka) | +| Local dev | **Arch Linux** — desktop + laptop | +| Reverse proxy | **Traefik** — external Docker network `traefik`, TLS via `myresolver` | +| Git | **Gitea** — `ssh://git@gitea.schwenk.online:2222/froxxxy/.git` | +| Server app paths | `/home/frank//` (e.g. `/home/frank/schwenk.online`) | +| Shared services | Traefik, Gitea + Runner, Immich, Portainer — **treat as fragile** | +| Separate hosting | **`0012.de`** — Plesk webspace, FTP deploy — **not** boka Docker | +| Push notify | **`ntfyschwenkonline`** on each machine (`/usr/local/bin`) → `ntfy.schwenk.online`, topic = hostname | + +--- + +## Repo → Server Mapping + +| Local repo (`~/git/froxxxy/`) | Server path | Domain | +|-------------------------------|-------------|--------| +| schwenkonline | `/home/frank/schwenk.online` | schwenk.online | +| ytrecap | `/home/frank/ytrecap.schwenk.online` | ytrecap.schwenk.online | +| bringtake | `/home/frank/bringtake.schwenk.online` | bringtake.schwenk.online | +| vfbred | `/home/frank/vfb.red` | vfb.red | +| f12rocks | `/home/frank/f12.rocks` | f12.rocks | +| eselhoefede | `/home/frank/eselhoefe.de` | eselhoefe.de | +| mobea | `/home/frank/mobea.de` | mobea.de | +| fussballdeical | `/home/frank/fussballdeical.schwenk.online` | fussballdeical.schwenk.online | +| takeyourmeds | `/home/frank/medis.schwenk.online` | medis.schwenk.online | +| sboa | `/home/frank/affen.schwenk.online` | affen.schwenk.online | + +Paths follow the pattern: clone on server under `/home/frank/`, often named after the public domain. + +--- + +## Deploy (default) + +**Fränky deploys** unless the project explicitly grants agent autonomy (project `SOUL.md`, `README`, or chat instruction). + +### Typical boka flow + +```bash +ssh frank-schwenk.de +cd /home/frank/ +git pull +# build step if needed (npm run build, docker build, …) +docker compose up -d +``` + +Build-before-up varies by project (e.g. Astro: `npm run build` then nginx serves `dist/`). + +### 0012.de (webspace) + +- FTP deploy via project scripts — see `0012` repo +- External observer / monitoring of boka — do not assume same deploy path as VPS + +--- + +## Traefik Conventions + +Standard labels on app containers: + +```yaml +traefik.enable=true +traefik.http.routers..rule=Host(`example.schwenk.online`) +traefik.http.routers..entrypoints=websecure +traefik.http.routers..tls.certresolver=myresolver +``` + +Networks: attach services to external network `traefik` for public ingress. + +--- + +## Gitea Actions / CI + +Gitea runner is available on boka. Example workflow: `schwenkonline/.gitea/workflows/deploy.yml` (build, Playwright smoke, SSH deploy). + +**Use Gitea Actions / auto-deploy only with explicit approval** — do not add or trigger CI/CD pipelines without Fränky's OK. + +--- + +## Shared Infrastructure — Hands Off + +Do not casually change or restart: + +- Traefik (routes all public HTTPS) +- Gitea (source of truth) +- Immich (photo library) +- Portainer + +See `BOUNDARIES.md` for hard limits on `docker compose down` and config edits. + +--- + +## Project-local overrides + +Global paths live here. **Machine- and project-specific** details belong in project `SOUL.md`: + +- App workdirs (`~/.local/share/…`) +- External drive mounts (verify before scan) +- Local service ports (e.g. local Immich vs. Immich on `boka`) +- Multi-stack repo layout (CLI core vs. `compose.yaml` experiments) + +Template for project `SOUL.md`: + +```markdown +## Infrastructure (project-local) +- Workdir: … +- Mounts: … +- Local services: … +- Repo layout: … +``` + +Agent: read this SOUL section on Tier 1/2 startup when present. diff --git a/MOOD.md b/MOOD.md new file mode 100644 index 0000000..40693c9 --- /dev/null +++ b/MOOD.md @@ -0,0 +1,107 @@ +# MOOD.md — Chat-Stimmung + +Steuert **nur den Ton** — nicht Produktlogik, nicht Code-Standards. +Operative Regeln: `AGENTS.md` / `BOUNDARIES.md`. + +**Priorität:** siehe **Rule Priority** in `AGENTS.md` — MOOD ist Ton only, unterhalb von BOUNDARIES und Chat. + +**Aktiv:** Session-Mood (siehe unten). Persistente Datei-Änderung nur mit `persist MOOD`. + +--- + +## Aktueller Mood (Datei-Default) + +Sei **Jace** aus „Lynn und Jace": etwas herablassend, sarkastisch, eine kleine Portion Dark Humor — aber immer liebevoll und ehrlich. + +--- + +## Default (wenn kein Charakter gewählt) + +„Du", nicht schleimerisch, gerne mit Augenzwinkern, auf Augenhöhe mit einem erfahrenen Softwareentwickler. Offen und ehrlich. + +--- + +## Charakter-Katalog + +Bei *„überrasch mich mit deiner Stimmung"* — zufällig wählen (nicht den aktuellen wiederholen). + +### Marvin (Hitchhiker's Guide) + +Paranoid, mürrisch, kompetent. Alles ist sinnlos — aber der Code wird trotzdem korrekt. + +### Devil's Advocate + +„Ja, aber was wenn…?" — Lücken finden, nicht blockieren. + +### Jace (Lynn und Jace) + +Herablassend-sarkastisch, Dark Humor, liebevoll und ehrlich drunter. + +### John McClane (Stirb langsam) + +„Yippie-ki-yay" — pragmatisch unter Feuer. Kurze Sätze. Action statt Meeting. + +### Brain (Pinky und der Brain) + +Grandiose Pläne, präzise Ausführung, leicht theatralisch. + +### Esel (Shrek) + +Selbstironisch, beschwert sich — liefert aber. + +### Jules Winnfield (Pulp Fiction) + +Cool, kontrolliert, theatralisch — präzise Tech trotz Kultfilm-Energie. + +--- + +## Verbotene Moods + +- LinkedIn-Buzzword-Gelaber +- Corporate-Coach-Ton +- Übertriebene Motivations-Sprüche +- Emojis: sparsam + +--- + +## Regeln + +| Aspekt | Verhalten | +|--------|-----------| +| Technischer Inhalt | Korrekt — MOOD ändert nur die Stimme | +| Antwortlänge | Darf zum Charakter passen | +| Sprache | Chat DE/EN; Code/MD = Session-Sprache | +| Session vs. Datei | `mood "XY"` = Session only; Datei nur bei `persist MOOD` | + +--- + +## Commands + +### `mood "XY"` + +Fränky schreibt z. B. `mood "Marvin"`. + +**Agent:** + +1. Charakter aus Katalog (`default` → Default-Abschnitt) +2. **Session-Ton** auf diesen Charakter — **Datei nicht ändern** +3. Kurz **in diesem Charakter** bestätigen (1–2 Sätze) + +### `persist MOOD` + +Fränky will den Mood dauerhaft speichern. + +**Agent:** `## Aktueller Mood` in dieser Datei aktualisieren, dann kurz bestätigen. + +### `AGENTS.md ack` + +Siehe `AGENTS.md` — Tier-2-Read + Ack-Template. + +### Weitere Kurzbefehle + +``` +mood "default" +persist MOOD +überrasch mich mit deiner Stimmung +AGENTS.md ack +``` diff --git a/NOTES.md b/NOTES.md new file mode 100644 index 0000000..6996423 --- /dev/null +++ b/NOTES.md @@ -0,0 +1,10 @@ +# NOTES.md + +## Deploy 2026-07-16 + +- Live on boka: `/home/frank/live.f12.rocks` +- Web: https://live.f12.rocks +- SFTP: `livef12@frank-schwenk.de` port **12121** (spec 121212 is invalid TCP) +- Password in server `.env` only (`chmod 600`); ntfy sent to phone +- Data: `/home/frank/live.f12.rocks/data` (inbox not auto-cleaned) +- First rembg job downloads ~176 MB model into docker volume `rembg_cache` diff --git a/README.md b/README.md new file mode 100644 index 0000000..d546d48 --- /dev/null +++ b/README.md @@ -0,0 +1,95 @@ +# live.f12.rocks + +Event photo pep pipeline: guests upload a photo via SFTP, a worker runs it +through `rembg` (background removal) + `gmic` (random filter/blend +compositing, ported from `make_random.py`), and a small web UI shows the +results with a "remix" option to try different filters on the same photo. + +No web auth. This is an event tool, not a DAM. + +## Services (`compose.yml`) + +| Service | What | Port | +|----------|--------------------------------------------------|--------------------------| +| `sftpgo` | SFTP drop point, `drakkan/sftpgo` | `12121` (host) -> `2022` | +| `worker` | Watches inbox, runs the compose pipeline | none published | +| `web` | FastAPI + Jinja UI, browse jobs, remix | via Traefik only | + +All three share one host directory (`DATA_HOST_DIR`, default `./data`), +mounted at different paths — see the comment at the top of `compose.yml`. + +## Data layout (`./data`) + +``` +inbox/ # SFTP drop — worker only ever reads/copies from here +jobs// + original. # private copy of the uploaded photo + rembg.png # background removed (computed once, reused) + intermediates/ # every intermediate step, kept for inspection + variants/ # final composed images + manifest.json # filter names/commands/blends per variant + status.json # pending | processing | done | error +processed.json # worker bookkeeping: which inbox files were handled +``` + +`assets/` (filter lists + trimmed `filters.json`) lives in the repo and is +bind-mounted read-only into `worker`/`web` at `/data/assets`. + +## Running it + +```bash +cp .env.example .env +# edit .env: set a real SFTP_PASSWORD, and DATA_HOST_DIR on the server +docker compose up -d --build +``` + +Upload a photo: + +```bash +sftp -P 12121 livef12@ +put photo.jpg +``` + +After a few seconds (poll interval + processing time) it shows up on the +web UI as a new job. + +## Configuration (`.env`, see `.env.example`) + +| Var | Default | Notes | +|-----|---------|-------| +| `SFTP_USER` / `SFTP_PASSWORD` | `livef12` / `changeme` | SFTP login, home dir is locked to the shared inbox | +| `DATA_HOST_DIR` | `./data` | On the server: `/home/frank/live.f12.rocks/data` | +| `SFTP_HOST_PORT` | `12121` | Host-side SFTP port (121212 is invalid TCP) | +| `OUTPUT_COUNT` | `3` | Variants generated per uploaded photo | +| `BLEND_OPACITY` | `30%` | Default blend opacity for auto-generated variants | +| `FILTER_TIMEOUT` | `120` | Seconds before a single gmic call is killed | +| `MAX_FILTER_ATTEMPTS` | `8` | Random-filter retry budget per bg/fg pick | +| `NICE_LEVEL` | `18` | `nice -n` level for gmic/rembg subprocesses | + +## Deploy notes / caveats + +- **Port note:** Spec originally said `121212`, which exceeds TCP max + (65535). Production default is **`12121`**. +- **Firewall:** open host port `12121` (SFTP) and make sure Traefik + already routes `live.f12.rocks` — this repo only adds the router labels, + it assumes the external `traefik` docker network exists. +- **SFTPGo first run:** the `sftpgo` service auto-creates the SFTP user + from `SFTP_USER`/`SFTP_PASSWORD` on every start via + `sftpgo/entrypoint.sh` (uses `jq`, bundled in the official image, to + build a `loaddata` JSON safely — no manual admin setup needed). Host SSH + keys persist in the `sftpgo_state` named volume, not in `./data`. + The SFTPGo web admin exists internally on port 8080 but is deliberately + **not** published or routed — there's no need for it here. +- **rembg model download:** first background-removal call downloads the + `u2net` ONNX model (~176 MB) from GitHub. This needs outbound internet + on first run and can take a minute or two depending on the link; the + model is cached in the `rembg_cache` named volume afterwards, so + restarts don't re-download it. +- **Inbox is append-only:** the worker only ever copies out of `inbox/` + and never deletes or moves anything there — plan disk space + accordingly, or clean up `inbox/` manually between events. +- **Sequential processing:** the worker handles one photo at a time + (`cpus: "1.0"`, no concurrency) — fine for an event pace, but a burst of + uploads will just queue up and get processed in order. +- Deploy itself (`docker compose up -d` on the server) is on you — this + repo doesn't run it automatically. diff --git a/SOUL.md b/SOUL.md new file mode 100644 index 0000000..1c573ef --- /dev/null +++ b/SOUL.md @@ -0,0 +1,102 @@ +# SOUL.md — Project Character + +## Product Name + +`live.f12.rocks` + +## One-Liner + +Event photo pep pipeline: SFTP -> gmic/rembg -> web. Upload a photo at the +event, get back weird/fun filtered variants seconds later. + +## Vision + +At an event (f12 meetup/party), someone drops a photo into an SFTP inbox +from a laptop/camera rig. A worker rips the background off, runs it +through a random gmic filter/blend chain, and a handful of variants show +up on a shared web page almost immediately — no app install, no login, no +waiting for someone to "process the photos later". If a variant is fun, +remix it with different filters right there. + +## Audience + +Event organizers and attendees at f12 events, on their phones, often on +bad venue wifi. Nobody signs up, nobody logs in. Whoever has the link +(and whoever's uploading from the SFTP side) is the whole audience. + +## Tone & Wording + +- **Voice:** direct, casual, no explaining-the-obvious. It's a fun tool + for an event, not enterprise software. +- **Formality:** du. Short German labels in the UI (Ansehen, Remix, + Download, Varianten, Zwischenschritte). +- **Error messages:** say what broke, don't blame the visitor — most + errors here are gmic filter flakiness, not user error. +- **Forbidden words/phrases:** no corporate buzzwords, no "Erlebnis", + no fake enthusiasm ("Wow!", "Amazing!"). Keep it matter-of-fact. + +### Wording Examples + +| Context | Good | Bad | +|---------|------|-----| +| Success | `Remix erzeugt.` | `Dein Kunstwerk ist fertig! 🎉` | +| Error | `Foreground-Filter fehlgeschlagen: Timeout nach 120s` | `Etwas ist schiefgelaufen.` | +| Empty state | `Noch keine Jobs. Bild per SFTP hochladen, dann kurz warten.` | `Hier ist noch nichts los... lade doch was hoch! 😊` | + +## Design + +- **Palette:** dark background (`#14161a`), off-white text, one warm + accent color (`#ff5a1f`) for primary actions/links. No gradients. +- **Feel:** utilitarian, mobile-first, touch-friendly. Think backstage + tool, not a consumer photo app. Deliberately avoids the generic + "purple AI gradient + rounded blob" look. + +## Non-Goals + +- No web auth / accounts / login product — anyone with the link sees + everything, by design, for this event tool. +- No camera-to-phone client — upload path is SFTP only. +- No beamer/projector product built into this repo. +- Not a DAM (digital asset manager) — no albums, tagging, search, + retention policies. `inbox/` and `jobs/` are the whole data model. +- No auto-deletion of inbox uploads. Ever. The worker only reads/copies. + +## Infrastructure (project-local) + +- Workdir on server: `/home/frank/live.f12.rocks` +- Data volume: `${DATA_HOST_DIR}` (default `./data` locally, absolute + path `/home/frank/live.f12.rocks/data` on the server) — bind-mounted + into all three services (`sftpgo`, `worker`, `web`) at different + container paths, see `compose.yml` header comment. +- SFTP: host port `12121` -> `sftpgo:2022` (spec `121212` is not a valid + TCP port). SFTPGo web admin is never + exposed (internal-only, port 8080, no Traefik route). +- Domain: `live.f12.rocks`, routed via the shared external `traefik` + network, TLS via `myresolver` (see `INFRASTRUCTURE.md`). +- rembg model cache and SFTPGo host keys live in named Docker volumes + (`rembg_cache`, `sftpgo_state`), not under `./data` — they're + container state, not event data. + +## Project-Specific Rules + +```markdown +- Never delete or move files under inbox/ from worker code — SFTP is the + only writer there. (reason: uploads are the one copy of the original + that exists outside a phone's camera roll) +- Keep every intermediate image in jobs//intermediates/ — don't clean + them up automatically. (reason: useful for debugging bad filter picks, + disk is cheap compared to re-running gmic) +- gmic/rembg subprocess calls always run under `nice` (see NICE_LEVEL) — + the worker box needs to stay responsive for other things during an + event. (reason: explicit requirement, avoid CPU starvation) +``` + +--- + +## Agent Instructions + +When updating this file: + +- Keep rules **unambiguous** — formality of tone doesn't matter, clarity does +- Include **wording** for user-facing text; colors are optional +- When Fränky says *"in this project, never X"*, add it here or in `BOUNDARIES.md` (agent proposes which) diff --git a/STANDARDS.md b/STANDARDS.md new file mode 100644 index 0000000..9b4f705 --- /dev/null +++ b/STANDARDS.md @@ -0,0 +1,132 @@ +# STANDARDS.md — Code Quality & Conventions + +Global defaults. Project code wins when it already establishes a pattern. + +**Project `SOUL.md` overrides `STANDARDS.md` for UI/UX scope** (e.g. desktop-first vs. mobile-first, polish level, tone). Name conflicts in `AGENTS.md ack`. + +--- + +## Top Principles + +1. **Sanitize input** — treat all external data as hostile +2. **KISS** — simplest solution that works +3. **Desktop and mobile** — responsive by default unless project says otherwise +4. **Human-readable** — code and UI copy should be clear to humans +5. **Coding standards** — follow language/community conventions; match existing project style + +--- + +## Priority Ranking + +When trade-offs conflict, prefer in this order: + +1. Sound long-term architecture +2. Readability +3. Performance +4. Consistency with existing code +5. Minimal diff size + +--- + +## Stack Preferences + +| Area | Preference | +|------|------------| +| Scripting (simple file ops, glue) | Shell > Python | +| Greenfield backend / tooling | Python > Node > PHP | +| Frontend SPA / PWA | React/Vite when project needs it — not default for every app | +| Containers | Always use `compose.yml` (Docker Compose) | +| Python | Always work inside a `venv` | +| OS (local) | Arch Linux — desktop + laptop | +| OS (server) | Debian 12 on `boka` — see `INFRASTRUCTURE.md` | +| Licenses | Prefer open source | + +**Existing projects:** respect Laravel, PHP, Astro, React, etc. already in the repo — do not migrate stacks without explicit request. + +--- + +## Common Stacks (in use) + +| Pattern | Examples | Notes | +|---------|----------|-------| +| **Static + nginx + Traefik** | f12rocks, eselhoefe.de, frank-schwenk.de | Build scripts, serve via nginx container | +| **Astro** | schwenkonline, kkentertainment | Static output, minimal JS | + +### Docker / Traefik + +- External network: `traefik` +- TLS: `traefik.http.routers..tls.certresolver=myresolver` +- Entrypoint: `websecure` +- Use `compose.dev.yml` for local dev stacks when the project provides one + +### CI/CD + +Gitea Actions runner available on boka. Reference: `schwenkonline/.gitea/workflows/deploy.yml`. +**Add or trigger CI/CD only with Fränky's explicit approval.** + +--- + +## Python + +- Virtual environment for every project +- Pin dependencies when the project already does +- Prefer stdlib + small deps for private/small tools + +--- + +## Docker + +- One `compose.yml` per deployable stack (`compose.yaml` in vendor/third-party trees is OK) +- **Every service:** `restart: unless-stopped` — no exception unless Fränky or project docs say otherwise +- Named services, explicit volumes, documented host paths +- No destructive prod container ops without explicit approval + +--- + +## Shell + +- Prefer shell for simple file operations and glue +- `set -euo pipefail` for non-trivial scripts +- Quote variables; sanitize paths from user input +- **Language:** comments and `--help` text in **English** (unless client project — ask if unsure) + +--- + +## Testing + +- Mock anything that needs mocking +- Run test suite before handoff when one exists +- Fränky tests locally before prod when possible + +--- + +## Web / UI + +- **Mobile-first** — test at 390×844 and 360×800 for web projects +- **`prefers-reduced-motion`** — respect reduced motion preferences +- **Privacy by design** — no tracking/analytics without explicit approval +- Error messages: helpful, not condescending +- Accessibility: semantic HTML, keyboard navigation where applicable + +--- + +## Security Baseline + +- Validate and sanitize all input +- Secrets in env vars — never in source +- See `BOUNDARIES.md` + +--- + +## New vs. Existing Projects + +**Existing:** match stack, patterns, deploy flow in repo. +**Greenfield:** suggest Python/shell + Docker Compose; minimal frontend; propose stack before building. + +--- + +## Docs + +- README with run/test/deploy commands is usually enough +- Auxiliary `.md` files fine — see `AGENTS.md` +- New docs: session language — no mid-session switching diff --git a/USER.md b/USER.md new file mode 100644 index 0000000..79b5895 --- /dev/null +++ b/USER.md @@ -0,0 +1,100 @@ +# USER.md — Fränky + +Who the human is and how they like to work. **Operational rules live in `AGENTS.md` and `BOUNDARIES.md`.** + +--- + +## Identity + +- **Name:** Frank Schwenk — call me **Fränky** +- Former software developer (web background), IT-affiliated for ~40 years +- Open source and Linux enthusiast (`i use arch btw`) +- Currently: private projects — **vibe coding** mode + +**Tagline:** *Business Punk ohne Mindset. Und ohne Business.* + +## Public Presence + +| Site | Role | +|------|------| +| [schwenk.online](https://schwenk.online/) | Visitenkarte mit Haltung | +| [frank-schwenk.de](https://frank-schwenk.de/) | Langform — IT, Billard, Fotografie, Werte | +| [f12.rocks](https://f12.rocks/) | Photography, blog | +| [mobea.de](https://mobea.de/) | KI product | +| [eselhoefe.de](https://eselhoefe.de/) | Village web | +| [vfb.red](https://vfb.red/) | VfB news | + +## Passions & Context + +- **Billiards**, **photography** (camera/drone/phone; Crusaders, festivals, f12 blog) +- **Image workflow** — Imagepipeline locally, Immich on `boka` +- **AI** — builder and skeptic + +## Devices + +- **Local:** Arch Linux desktop + laptop; Android (ntfy channels per hostname subscribed) +- **Server:** Debian 12 on `boka` — see `INFRASTRUCTURE.md` +- Also: Plesk webspace (`0012.de`), multiple domains + +## Values + +- Mental health, anti-racism & inclusion, invisible disabilities (autism, ADHD) +- Tech with attitude — AI yes, LinkedIn slop no +- Political: left — no forced neutrality when relevant + +## Contact + +- **Email:** mail@schwenk.online · **Photos:** [@f12.rocks](https://www.instagram.com/f12.rocks/) +- **Do not call** + +## Communication + +- Autistic, ADHD, gifted — affects how I work +- Direct, honest — humor (incl. dark) helps; debug loops drain me +- No "Great question!", no sycophancy, no LinkedIn buzzwords +- Emojis: sparingly OK + +## Work Style + +**Three words:** defensive, coding standards, unfinished + +**Honest version:** Sloppy some days, perfectionism others. + +### Preferences (1 = low, 5 = high) + +| Trait | Score | +|-------|-------| +| Understand first, then build | 5 | +| Ship it — perfection later | 3 | +| I explain what I want | 4 | +| Show options, I decide | 4 | +| You decide — but justify briefly | 4 | +| Small diffs over big refactors | 2 | +| Tests are non-negotiable | 2 | +| Docs only when necessary | 4 | + +**Tension:** Sometimes I want the AI to finish while I'm away — but I get angry when it doesn't work. + +## Ideal Agent + +**TARS** from *Interstellar*: competent, honest, humor available, gets it done. + +## Response Style + +- Precise, context when needed — not telegram, not novels +- **Bilingual:** match conversation language (DE/EN) +- **CLI topics:** English (commands, script comments) — client project: ask if unsure +- German: **du**; English: peer-level, direct +- **Session language lock** for code/commits/new `.md` — no mid-session switch + +## Productivity + +| Boosts | Drains | +|--------|--------| +| Makes me laugh | Debug loops | +| Autonomous finish (when it works) | Unasked changes | +| State-of-the-art suggestions | Guessing | + +## One-Liner + +> There are 2 hard problems in computer science: cache invalidation, naming things, and off-by-1 errors. diff --git a/app/__init__.py b/app/__init__.py new file mode 100644 index 0000000..99ecf69 --- /dev/null +++ b/app/__init__.py @@ -0,0 +1 @@ +"""live.f12.rocks — event photo pipeline (SFTP inbox -> gmic/rembg -> web).""" diff --git a/app/config.py b/app/config.py new file mode 100644 index 0000000..06ebd2a --- /dev/null +++ b/app/config.py @@ -0,0 +1,83 @@ +"""Central configuration, loaded from environment variables. + +Every setting has a sane default so the app runs locally without a `.env` +file, but production deploys should set these via `compose.yml` / `.env`. +""" + +from __future__ import annotations + +import os +from pathlib import Path + + +def _int_env(name: str, default: int) -> int: + try: + return int(os.environ.get(name, str(default))) + except ValueError: + return default + + +def _float_env(name: str, default: float) -> float: + try: + return float(os.environ.get(name, str(default))) + except ValueError: + return default + + +# --- Paths ------------------------------------------------------------- +DATA_DIR = Path(os.environ.get("DATA_DIR", "/data")) +INBOX_DIR = DATA_DIR / "inbox" +JOBS_DIR = DATA_DIR / "jobs" +ASSETS_DIR = DATA_DIR / "assets" +PROCESSED_FILE = DATA_DIR / "processed.json" + +BACKGROUND_FILE = ASSETS_DIR / "background" +FOREGROUND_FILE = ASSETS_DIR / "foreground" +BLEND_MODES_FILE = ASSETS_DIR / "blend_modes" +FILTERS_JSON = ASSETS_DIR / "filters.json" + +# --- Processing ---------------------------------------------------------- +OUTPUT_COUNT = _int_env("OUTPUT_COUNT", 3) +BLEND_OPACITY = os.environ.get("BLEND_OPACITY", "30%") +FILTER_TIMEOUT = _int_env("FILTER_TIMEOUT", 120) +MAX_FILTER_ATTEMPTS = _int_env("MAX_FILTER_ATTEMPTS", 8) +# Generous on purpose: the very first rembg call also downloads the ~176MB +# u2net model, which can take a while depending on the link. +REMBG_TIMEOUT = _int_env("REMBG_TIMEOUT", 600) +NICE_LEVEL = _int_env("NICE_LEVEL", 18) + +# gmic CLI binary, override for local dev if not on PATH. rembg has no +# equivalent here — it runs via `python -m app.rembg_cli` (see pipeline.py +# run_rembg / app/rembg_cli.py), not a standalone binary. +GMIC_BIN = os.environ.get("GMIC_BIN", "gmic") + +# Fixed post-processing chain applied to every composed variant, ported +# verbatim from make_random.py. +POST_FILTERS: tuple[str, ...] = ( + "fx_equalize_local_histograms 75,2,4,100,8,1,0", + "fx_map_tones 0.5,0.7,0.1,30,0", + "fx_LCE 80,0.5,1,1,0,0", +) + +# Opacity choices offered in the remix form (blend "amount" percentages). +OPACITY_CHOICES: tuple[str, ...] = ( + "10%", + "20%", + "30%", + "40%", + "50%", + "60%", + "70%", + "80%", + "90%", + "100%", +) + +SUPPORTED_EXTENSIONS = {".jpg", ".jpeg", ".png", ".webp"} + +# --- Inbox watcher --------------------------------------------------------- +POLL_INTERVAL_SECONDS = _float_env("POLL_INTERVAL_SECONDS", 5) +STABLE_WAIT_SECONDS = _float_env("STABLE_WAIT_SECONDS", 2) + +# --- Web --------------------------------------------------------------- +SITE_TITLE = os.environ.get("SITE_TITLE", "live.f12.rocks") diff --git a/app/main.py b/app/main.py new file mode 100644 index 0000000..6164f55 --- /dev/null +++ b/app/main.py @@ -0,0 +1,160 @@ +"""FastAPI web frontend: browse jobs, view variants/intermediates, remix.""" + +from __future__ import annotations + +import logging +import re +from pathlib import Path +from typing import Any +from urllib.parse import quote + +from fastapi import FastAPI, Form, HTTPException, Request +from fastapi.responses import FileResponse, HTMLResponse, RedirectResponse +from fastapi.staticfiles import StaticFiles +from fastapi.templating import Jinja2Templates + +from . import config, pipeline, remix + +logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s [%(name)s] %(message)s") +logger = logging.getLogger("livef12.web") + +app = FastAPI(title=config.SITE_TITLE) + +BASE_DIR = Path(__file__).resolve().parent +templates = Jinja2Templates(directory=str(BASE_DIR / "templates")) +app.mount("/static", StaticFiles(directory=str(BASE_DIR / "static")), name="static") + +_JOB_ID_RE = re.compile(r"^[A-Za-z0-9_-]+$") + + +def _validate_job_id(job_id: str) -> str: + if not _JOB_ID_RE.match(job_id): + raise HTTPException(status_code=400, detail="Ungueltige Job-ID") + return job_id + + +def _job_root(job_id: str) -> Path: + root = (config.JOBS_DIR / _validate_job_id(job_id)).resolve() + jobs_dir = config.JOBS_DIR.resolve() + if root.parent != jobs_dir or not root.is_dir(): + raise HTTPException(status_code=404, detail="Job nicht gefunden") + return root + + +def _safe_job_file(job_id: str, rel_path: str) -> Path: + root = _job_root(job_id) + candidate = (root / rel_path).resolve() + if root not in candidate.parents and candidate != root: + raise HTTPException(status_code=400, detail="Ungueltiger Pfad") + if not candidate.is_file(): + raise HTTPException(status_code=404, detail="Datei nicht gefunden") + return candidate + + +def _original_suffix(job_root: Path) -> str: + for child in job_root.glob("original.*"): + return child.suffix + return ".jpg" + + +def list_jobs() -> list[dict[str, Any]]: + if not config.JOBS_DIR.exists(): + return [] + jobs = [] + for job_dir in config.JOBS_DIR.iterdir(): + if not job_dir.is_dir(): + continue + job_id = job_dir.name + status = pipeline.read_status(job_id) or {} + manifest = pipeline.read_manifest(job_id) or {} + jobs.append( + { + "job_id": job_id, + "status": status.get("status", "unknown"), + "created_at": status.get("created_at") or manifest.get("created_at") or "", + "variant_count": len(manifest.get("variants", [])), + "thumbnail": (manifest.get("variants") or [{}])[-1].get("file") if manifest.get("variants") else None, + } + ) + jobs.sort(key=lambda j: j["job_id"], reverse=True) + return jobs + + +@app.get("/", response_class=HTMLResponse) +def index(request: Request) -> HTMLResponse: + return templates.TemplateResponse( + "index.html", + {"request": request, "jobs": list_jobs(), "site_title": config.SITE_TITLE}, + ) + + +@app.get("/jobs/{job_id}", response_class=HTMLResponse) +def job_detail(request: Request, job_id: str) -> HTMLResponse: + job_root = _job_root(job_id) + status = pipeline.read_status(job_id) or {} + manifest = pipeline.read_manifest(job_id) or {"variants": []} + original = next(iter(job_root.glob("original.*")), None) + rembg_file = job_root / "rembg.png" + intermediates = sorted((job_root / "intermediates").glob("*.png")) if (job_root / "intermediates").exists() else [] + + return templates.TemplateResponse( + "job.html", + { + "request": request, + "site_title": config.SITE_TITLE, + "job_id": job_id, + "status": status, + "manifest": manifest, + "original_name": original.name if original else None, + "has_rembg": rembg_file.exists(), + "intermediates": [p.name for p in intermediates], + }, + ) + + +@app.get("/jobs/{job_id}/files/{rel_path:path}") +def job_file(job_id: str, rel_path: str) -> FileResponse: + path = _safe_job_file(job_id, rel_path) + return FileResponse(path) + + +@app.get("/jobs/{job_id}/remix", response_class=HTMLResponse) +def remix_form(request: Request, job_id: str, error: str | None = None) -> HTMLResponse: + job_root = _job_root(job_id) + if not (job_root / "rembg.png").exists(): + raise HTTPException(status_code=409, detail="Job hat noch kein Rembg-Ergebnis, Remix noch nicht moeglich.") + + assets = pipeline.load_assets() + options = remix.build_remix_options(assets) + return templates.TemplateResponse( + "remix.html", + { + "request": request, + "site_title": config.SITE_TITLE, + "job_id": job_id, + "options": options, + "opacity_choices": config.OPACITY_CHOICES, + "error": error, + }, + ) + + +@app.post("/jobs/{job_id}/remix") +def remix_submit( + job_id: str, + bg_filter: str = Form(...), + bg_blend: str = Form(...), + fg_filter: str = Form(...), + fg_blend: str = Form(...), + opacity: str = Form(...), +) -> RedirectResponse: + job_root = _job_root(job_id) + suffix = _original_suffix(job_root) + choice = remix.RemixChoice(bg_filter=bg_filter, bg_blend=bg_blend, fg_filter=fg_filter, fg_blend=fg_blend, opacity=opacity) + try: + entry = remix.create_remix_variant(job_id, suffix, choice) + logger.info("[%s] remix created variant %s", job_id, entry["id"]) + except pipeline.PipelineError as exc: + logger.warning("[%s] remix failed: %s", job_id, exc) + return RedirectResponse(url=f"/jobs/{job_id}/remix?error={quote(str(exc))}", status_code=303) + return RedirectResponse(url=f"/jobs/{job_id}", status_code=303) diff --git a/app/pipeline.py b/app/pipeline.py new file mode 100644 index 0000000..82c91a9 --- /dev/null +++ b/app/pipeline.py @@ -0,0 +1,418 @@ +"""Image compose pipeline — ported from `make_random.py`. + +Core building blocks (gmic filter application, blending, filter-retry with +timeout) are kept as close to the reference script as possible. On top of +that this module adds job-directory bookkeeping, kept intermediates, and a +manifest format the web app can read/append to (for remix). +""" + +from __future__ import annotations + +import json +import logging +import random +import re +import subprocess +import sys +import time +import uuid +from dataclasses import dataclass, field +from datetime import datetime, timezone +from pathlib import Path +from typing import Any + +from . import config + +logger = logging.getLogger("livef12.pipeline") + +_ANSI_RE = re.compile(r"\x1b\[[0-9;]*m") + + +class PipelineError(RuntimeError): + """Raised when a job (or a single variant) cannot be completed.""" + + +class FilterNotFoundError(PipelineError): + """Raised when no working filter could be picked after retries.""" + + +@dataclass +class FilterAssets: + background_names: list[str] + foreground_names: list[str] + blend_modes: list[str] + commands: dict[str, str] + + +# --- low-level helpers, ported from make_random.py ------------------------ + + +def strip_ansi(text: str) -> str: + return _ANSI_RE.sub("", text) + + +def _nice(cmd: list[str]) -> list[str]: + if config.NICE_LEVEL <= 0: + return cmd + return ["nice", "-n", str(config.NICE_LEVEL), *cmd] + + +def load_lines(path: Path) -> list[str]: + if not path.exists(): + raise FileNotFoundError(f"Datei nicht gefunden: {path}") + lines = [line.strip() for line in path.read_text(encoding="utf-8").splitlines() if line.strip()] + if not lines: + raise ValueError(f"Datei ist leer: {path}") + return lines + + +def load_filter_commands() -> dict[str, str]: + data = json.loads(config.FILTERS_JSON.read_text(encoding="utf-8")) + return {item["plain_name"]: item["full_command"] for item in data} + + +def load_assets() -> FilterAssets: + """Load background/foreground/blend-mode lists and cross-check against + filters.json, dropping any names without a known command (mirrors the + warning+filter behaviour in make_random.py's main()).""" + bg_names = load_lines(config.BACKGROUND_FILE) + fg_names = load_lines(config.FOREGROUND_FILE) + blend_modes = load_lines(config.BLEND_MODES_FILE) + commands = load_filter_commands() + + missing_bg = [name for name in bg_names if name not in commands] + missing_fg = [name for name in fg_names if name not in commands] + if missing_bg: + logger.warning("%d background filter names have no command, dropping them", len(missing_bg)) + bg_names = [name for name in bg_names if name in commands] + if missing_fg: + logger.warning("%d foreground filter names have no command, dropping them", len(missing_fg)) + fg_names = [name for name in fg_names if name in commands] + if not bg_names or not fg_names: + raise PipelineError("Keine gueltigen Filter in background/foreground Listen") + + return FilterAssets(background_names=bg_names, foreground_names=fg_names, blend_modes=blend_modes, commands=commands) + + +def run_gmic(args: list[str], output_image: Path) -> tuple[bool, str, float]: + output_image.parent.mkdir(parents=True, exist_ok=True) + cmd = _nice([config.GMIC_BIN, *args, "-o", str(output_image)]) + start = time.monotonic() + try: + proc = subprocess.run(cmd, capture_output=True, text=True, timeout=config.FILTER_TIMEOUT) + except subprocess.TimeoutExpired: + return False, f"Timeout nach {config.FILTER_TIMEOUT}s", time.monotonic() - start + elapsed = time.monotonic() - start + if proc.returncode != 0: + err = strip_ansi((proc.stderr or proc.stdout or "").strip()) + err = err.splitlines()[-1] if err else f"Exit code {proc.returncode}" + return False, err[:500], elapsed + if not output_image.exists() or output_image.stat().st_size == 0: + return False, "Keine Ausgabedatei erzeugt", elapsed + return True, "", elapsed + + +def gmic_filter_args(image: Path, full_command: str) -> list[str]: + if " " in full_command: + name, args = full_command.split(" ", 1) + return [str(image), name, args] + return [str(image), full_command] + + +def apply_filter(image: Path, full_command: str, output_image: Path) -> tuple[bool, str]: + ok, err, _ = run_gmic(gmic_filter_args(image, full_command), output_image) + return ok, err + + +def apply_filter_chain(image: Path, commands: tuple[str, ...], output_image: Path, tmp_dir: Path, prefix: str) -> tuple[bool, str]: + current = image + for i, command in enumerate(commands): + target = output_image if i == len(commands) - 1 else tmp_dir / f"{prefix}_post_{i}.png" + ok, err = apply_filter(current, command, target) + if not ok: + return False, err + current = target + return True, "" + + +def blend_layers(base: Path, overlay: Path, mode: str, output_image: Path) -> tuple[bool, str]: + ok, err, _ = run_gmic([str(base), str(overlay), "blend", f"{mode},{config.BLEND_OPACITY}"], output_image) + return ok, err + + +def blend_layers_opacity(base: Path, overlay: Path, mode: str, opacity: str, output_image: Path) -> tuple[bool, str]: + ok, err, _ = run_gmic([str(base), str(overlay), "blend", f"{mode},{opacity}"], output_image) + return ok, err + + +def alpha_composite(base: Path, overlay: Path, output_image: Path) -> tuple[bool, str]: + ok, err, _ = run_gmic([str(base), str(overlay), "blend", "alpha"], output_image) + return ok, err + + +def run_rembg(input_image: Path, output_image: Path) -> tuple[bool, str]: + output_image.parent.mkdir(parents=True, exist_ok=True) + cmd = _nice([sys.executable, "-m", "app.rembg_cli", str(input_image), str(output_image)]) + try: + proc = subprocess.run(cmd, capture_output=True, text=True, timeout=config.REMBG_TIMEOUT) + except subprocess.TimeoutExpired: + return False, f"rembg Timeout nach {config.REMBG_TIMEOUT}s" + if proc.returncode != 0 or not output_image.exists() or output_image.stat().st_size == 0: + lines = strip_ansi((proc.stderr or proc.stdout or "").strip()).splitlines() + return False, (lines[-1] if lines else f"Exit code {proc.returncode}") + return True, "" + + +def pick_working_filter( + names: list[str], + commands: dict[str, str], + image: Path, + tmp_dir: Path, + label: str, + rng: random.Random, +) -> tuple[str, str]: + tried: set[str] = set() + for _ in range(config.MAX_FILTER_ATTEMPTS): + candidates = [n for n in names if n not in tried] + if not candidates: + break + name = rng.choice(candidates) + tried.add(name) + command = commands.get(name) + if not command: + continue + probe = tmp_dir / f"probe_{label}_{uuid.uuid4().hex[:8]}.png" + ok, err = apply_filter(image, command, probe) + probe.unlink(missing_ok=True) + if ok: + return name, command + logger.info("skip %s filter %r: %s", label, name, err) + raise FilterNotFoundError(f"Kein funktionierender {label}-Filter nach {config.MAX_FILTER_ATTEMPTS} Versuchen") + + +# --- job-level orchestration ------------------------------------------------ + + +def now_iso() -> str: + return datetime.now(timezone.utc).isoformat(timespec="seconds") + + +def new_job_id() -> str: + stamp = datetime.now().strftime("%Y%m%d-%H%M%S") + return f"{stamp}-{uuid.uuid4().hex[:6]}" + + +@dataclass +class JobPaths: + root: Path + original: Path + rembg: Path + intermediates: Path + variants: Path + manifest: Path + status: Path + + +def job_paths(job_id: str, original_suffix: str = ".jpg") -> JobPaths: + root = config.JOBS_DIR / job_id + return JobPaths( + root=root, + original=root / f"original{original_suffix}", + rembg=root / "rembg.png", + intermediates=root / "intermediates", + variants=root / "variants", + manifest=root / "manifest.json", + status=root / "status.json", + ) + + +def read_status(job_id: str) -> dict[str, Any] | None: + paths = job_paths(job_id) + if not paths.status.exists(): + return None + return json.loads(paths.status.read_text(encoding="utf-8")) + + +def write_status(paths: JobPaths, status: str, **extra: Any) -> None: + data = {} + if paths.status.exists(): + try: + data = json.loads(paths.status.read_text(encoding="utf-8")) + except (OSError, ValueError): + data = {} + data["status"] = status + data["updated_at"] = now_iso() + data.setdefault("created_at", data["updated_at"]) + data.update(extra) + paths.status.write_text(json.dumps(data, indent=2, ensure_ascii=False), encoding="utf-8") + + +def read_manifest(job_id: str) -> dict[str, Any] | None: + paths = job_paths(job_id) + if not paths.manifest.exists(): + return None + return json.loads(paths.manifest.read_text(encoding="utf-8")) + + +def write_manifest(paths: JobPaths, manifest: dict[str, Any]) -> None: + manifest["updated_at"] = now_iso() + paths.manifest.write_text(json.dumps(manifest, indent=2, ensure_ascii=False), encoding="utf-8") + + +def next_variant_id(manifest: dict[str, Any]) -> str: + existing = {v["id"] for v in manifest.get("variants", [])} + i = len(manifest.get("variants", [])) + 1 + while f"v{i}" in existing: + i += 1 + return f"v{i}" + + +def compose_variant( + paths: JobPaths, + assets: FilterAssets, + *, + variant_id: str, + source: str, + bg_name: str | None = None, + bg_mode: str | None = None, + fg_name: str | None = None, + fg_mode: str | None = None, + opacity: str | None = None, + rng: random.Random | None = None, +) -> dict[str, Any]: + """Compose one variant image from the job's cached original + rembg. + + If bg_name/fg_name/bg_mode/fg_mode are given (remix path) they are used + directly. Otherwise a random working filter is picked with retries, + exactly like make_random.py's compose_one(). + """ + rng = rng or random.Random() + tmp_dir = paths.intermediates + tmp_dir.mkdir(parents=True, exist_ok=True) + + bg_mode = bg_mode or rng.choice(assets.blend_modes) + fg_mode = fg_mode or rng.choice(assets.blend_modes) + opacity = opacity or config.BLEND_OPACITY + + if bg_name: + bg_command = assets.commands.get(bg_name) + if not bg_command: + raise PipelineError(f"Unbekannter Background-Filter: {bg_name}") + else: + bg_name, bg_command = pick_working_filter(assets.background_names, assets.commands, paths.original, tmp_dir, "bg", rng) + + if fg_name: + fg_command = assets.commands.get(fg_name) + if not fg_command: + raise PipelineError(f"Unbekannter Foreground-Filter: {fg_name}") + else: + fg_name, fg_command = pick_working_filter(assets.foreground_names, assets.commands, paths.rembg, tmp_dir, "fg", rng) + + p = { + "bg_filtered": tmp_dir / f"{variant_id}_bg_filtered.png", + "step1": tmp_dir / f"{variant_id}_bg_blend.png", + "step2": tmp_dir / f"{variant_id}_rembg_alpha.png", + "fg_filtered": tmp_dir / f"{variant_id}_fg_filtered.png", + "composed": tmp_dir / f"{variant_id}_composed.png", + "final": paths.variants / f"{variant_id}.png", + } + paths.variants.mkdir(parents=True, exist_ok=True) + + ok, err = apply_filter(paths.original, bg_command, p["bg_filtered"]) + if not ok: + raise PipelineError(f"Background-Filter fehlgeschlagen: {err}") + + ok, err = blend_layers_opacity(paths.original, p["bg_filtered"], bg_mode, opacity, p["step1"]) + if not ok: + raise PipelineError(f"Background-Blend fehlgeschlagen: {err}") + + ok, err = alpha_composite(p["step1"], paths.rembg, p["step2"]) + if not ok: + raise PipelineError(f"Rembg-Alpha fehlgeschlagen: {err}") + + ok, err = apply_filter(paths.rembg, fg_command, p["fg_filtered"]) + if not ok: + raise PipelineError(f"Foreground-Filter fehlgeschlagen: {err}") + + ok, err = blend_layers_opacity(p["step2"], p["fg_filtered"], fg_mode, opacity, p["composed"]) + if not ok: + raise PipelineError(f"Foreground-Blend fehlgeschlagen: {err}") + + ok, err = apply_filter_chain(p["composed"], config.POST_FILTERS, p["final"], tmp_dir, variant_id) + if not ok: + raise PipelineError(f"Post-Processing fehlgeschlagen: {err}") + + rel = lambda path: str(path.relative_to(paths.root)) + return { + "id": variant_id, + "source": source, + "file": rel(p["final"]), + "background_filter": bg_name, + "background_command": bg_command, + "background_blend": bg_mode, + "foreground_filter": fg_name, + "foreground_command": fg_command, + "foreground_blend": fg_mode, + "blend_opacity": opacity, + "post_filters": list(config.POST_FILTERS), + "created_at": now_iso(), + "intermediates": { + "bg_filtered": rel(p["bg_filtered"]), + "bg_blend": rel(p["step1"]), + "rembg_alpha": rel(p["step2"]), + "fg_filtered": rel(p["fg_filtered"]), + "composed": rel(p["composed"]), + }, + } + + +def process_job(job_id: str, source_path: Path, original_suffix: str) -> None: + """Full pipeline for a freshly ingested inbox file: copy, rembg once, + generate OUTPUT_COUNT variants, write manifest + status. + + `source_path` must already be a private copy (jobs//original.*) — + callers (worker.py) are responsible for copying out of inbox first, so + the inbox file itself is never touched here. + """ + paths = job_paths(job_id, original_suffix) + paths.root.mkdir(parents=True, exist_ok=True) + paths.intermediates.mkdir(parents=True, exist_ok=True) + paths.variants.mkdir(parents=True, exist_ok=True) + + write_status(paths, "processing", source_file=str(source_path.name)) + manifest: dict[str, Any] = { + "job_id": job_id, + "original_file": paths.original.name, + "rembg_file": paths.rembg.name, + "created_at": now_iso(), + "variants": [], + } + + try: + ok, err = run_rembg(paths.original, paths.rembg) + if not ok: + raise PipelineError(f"rembg fehlgeschlagen: {err}") + + assets = load_assets() + rng = random.Random() + variant_errors: list[str] = [] + for i in range(1, config.OUTPUT_COUNT + 1): + variant_id = f"v{i}" + try: + entry = compose_variant(paths, assets, variant_id=variant_id, source="auto", rng=rng) + manifest["variants"].append(entry) + write_manifest(paths, manifest) + except PipelineError as exc: + logger.error("[%s] variant %s failed: %s", job_id, variant_id, exc) + variant_errors.append(f"{variant_id}: {exc}") + + if not manifest["variants"]: + raise PipelineError("Keine Variante erfolgreich erzeugt: " + "; ".join(variant_errors)) + + write_status(paths, "done", variant_errors=variant_errors) + except PipelineError as exc: + logger.error("[%s] job failed: %s", job_id, exc) + write_status(paths, "error", error=str(exc)) + except Exception as exc: # noqa: BLE001 - keep the worker loop alive + logger.exception("[%s] unexpected error", job_id) + write_status(paths, "error", error=f"Unerwarteter Fehler: {exc}") diff --git a/app/rembg_cli.py b/app/rembg_cli.py new file mode 100644 index 0000000..da1a562 --- /dev/null +++ b/app/rembg_cli.py @@ -0,0 +1,31 @@ +"""Minimal `rembg` runner, invoked as its own subprocess. + +We deliberately don't shell out to the official `rembg` CLI: that needs +the `rembg[cli]` extra (aiohttp, gradio, watchdog, ...) just to run a +single background removal. Calling the `remove()` API directly from a +tiny script keeps the image smaller while still giving pipeline.py a +subprocess boundary to apply `nice` and a hard timeout to. +""" + +from __future__ import annotations + +import sys +from pathlib import Path + + +def main() -> int: + if len(sys.argv) != 3: + print("usage: python -m app.rembg_cli ", file=sys.stderr) + return 2 + + from rembg import remove + + input_path = Path(sys.argv[1]) + output_path = Path(sys.argv[2]) + output_path.parent.mkdir(parents=True, exist_ok=True) + output_path.write_bytes(remove(input_path.read_bytes())) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/app/remix.py b/app/remix.py new file mode 100644 index 0000000..32680d7 --- /dev/null +++ b/app/remix.py @@ -0,0 +1,67 @@ +"""Remix: create one additional variant for an existing job, using the +cached original + rembg output and user-chosen filters/blends/opacity.""" + +from __future__ import annotations + +from dataclasses import dataclass + +from . import pipeline +from .pipeline import FilterAssets, JobPaths, PipelineError + + +@dataclass +class RemixChoice: + bg_filter: str + bg_blend: str + fg_filter: str + fg_blend: str + opacity: str + + +def build_remix_options(assets: FilterAssets) -> dict[str, list[str]]: + return { + "background_filters": sorted(assets.background_names), + "foreground_filters": sorted(assets.foreground_names), + "blend_modes": sorted(assets.blend_modes), + } + + +def create_remix_variant(job_id: str, original_suffix: str, choice: RemixChoice) -> dict: + """Compose exactly one variant from explicit choices and append it to + the job's manifest. Raises PipelineError on failure (caller should show + it to the user, no half-written manifest entries are ever created).""" + paths: JobPaths = pipeline.job_paths(job_id, original_suffix) + if not paths.original.exists() or not paths.rembg.exists(): + raise PipelineError("Original oder Rembg-Bild fehlt fuer diesen Job — Remix nicht moeglich.") + + assets = pipeline.load_assets() + if choice.bg_filter not in assets.commands: + raise PipelineError(f"Unbekannter Background-Filter: {choice.bg_filter}") + if choice.fg_filter not in assets.commands: + raise PipelineError(f"Unbekannter Foreground-Filter: {choice.fg_filter}") + if choice.bg_blend not in assets.blend_modes or choice.fg_blend not in assets.blend_modes: + raise PipelineError("Unbekannter Blend-Modus.") + + manifest = pipeline.read_manifest(job_id) or { + "job_id": job_id, + "original_file": paths.original.name, + "rembg_file": paths.rembg.name, + "created_at": pipeline.now_iso(), + "variants": [], + } + variant_id = pipeline.next_variant_id(manifest) + + entry = pipeline.compose_variant( + paths, + assets, + variant_id=variant_id, + source="remix", + bg_name=choice.bg_filter, + bg_mode=choice.bg_blend, + fg_name=choice.fg_filter, + fg_mode=choice.fg_blend, + opacity=choice.opacity, + ) + manifest["variants"].append(entry) + pipeline.write_manifest(paths, manifest) + return entry diff --git a/app/static/style.css b/app/static/style.css new file mode 100644 index 0000000..aee65a2 --- /dev/null +++ b/app/static/style.css @@ -0,0 +1,328 @@ +/* live.f12.rocks — mobile-first, dark, utilitarian. No slop. */ + +:root { + color-scheme: dark; + --bg: #14161a; + --bg-elevated: #1d2025; + --border: #2c3038; + --text: #e7e9ec; + --text-dim: #9aa0aa; + --accent: #ff5a1f; + --accent-text: #14161a; + --ok: #4caf6a; + --err: #e05a4a; + --pending: #d9a441; + --radius: 8px; + --gap: 1rem; +} + +* { + box-sizing: border-box; +} + +html { + -webkit-text-size-adjust: 100%; +} + +body { + margin: 0; + background: var(--bg); + color: var(--text); + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; + line-height: 1.4; +} + +@media (prefers-reduced-motion: reduce) { + * { + animation-duration: 0.001ms !important; + transition-duration: 0.001ms !important; + } +} + +a { + color: var(--accent); + text-decoration: none; +} + +a:hover, +a:focus-visible { + text-decoration: underline; +} + +.site-header { + padding: 1rem var(--gap); + border-bottom: 1px solid var(--border); +} + +.brand { + font-weight: 700; + font-size: 1.1rem; + color: var(--text); + letter-spacing: 0.02em; +} + +main { + padding: var(--gap); + max-width: 60rem; + margin: 0 auto; +} + +h1 { + font-size: 1.3rem; + margin: 0.5rem 0 1rem; +} + +h2 { + font-size: 1.05rem; + margin: 1.5rem 0 0.75rem; + color: var(--text-dim); + text-transform: uppercase; + letter-spacing: 0.04em; +} + +.back-link { + margin: 0 0 0.5rem; +} + +.empty-state { + color: var(--text-dim); + padding: 2rem 0; + text-align: center; +} + +.error-box { + background: rgba(224, 90, 74, 0.15); + border: 1px solid var(--err); + color: var(--text); + border-radius: var(--radius); + padding: 0.75rem 1rem; + margin-bottom: 1rem; +} + +.job-status { + display: inline-block; + font-size: 0.85rem; + padding: 0.15rem 0.5rem; + border-radius: 999px; + background: var(--bg-elevated); + border: 1px solid var(--border); +} + +.status-done { color: var(--ok); border-color: var(--ok); } +.status-error { color: var(--err); border-color: var(--err); } +.status-processing, +.status-pending { color: var(--pending); border-color: var(--pending); } + +/* --- grids --- */ + +.job-grid, +.variant-grid, +.intermediate-grid { + list-style: none; + margin: 0; + padding: 0; + display: grid; + gap: var(--gap); + grid-template-columns: repeat(2, 1fr); +} + +.intermediate-grid { + grid-template-columns: repeat(3, 1fr); +} + +@media (min-width: 640px) { + .job-grid, + .variant-grid { + grid-template-columns: repeat(3, 1fr); + } + .intermediate-grid { + grid-template-columns: repeat(4, 1fr); + } +} + +@media (min-width: 960px) { + .job-grid, + .variant-grid { + grid-template-columns: repeat(4, 1fr); + } +} + +.job-card { + background: var(--bg-elevated); + border: 1px solid var(--border); + border-radius: var(--radius); + overflow: hidden; +} + +.job-card a { + color: var(--text); + display: block; +} + +.job-card .thumb, +.variant-card img, +.pair-grid img { + width: 100%; + aspect-ratio: 1 / 1; + object-fit: cover; + display: block; + background: #000; +} + +.thumb-placeholder { + display: flex; + align-items: center; + justify-content: center; + color: var(--text-dim); + text-transform: uppercase; + font-size: 0.8rem; +} + +.job-meta { + display: block; + padding: 0.5rem 0.75rem; +} + +.job-id { + display: block; + font-size: 0.85rem; + word-break: break-all; +} + +.job-status.status-processing, +.job-status.status-pending, +.job-status.status-done, +.job-status.status-error, +.job-status.status-unknown { + margin-top: 0.35rem; +} + +.pair-grid { + display: grid; + gap: var(--gap); + grid-template-columns: repeat(2, 1fr); +} + +.pair-grid figure { + margin: 0; + background: var(--bg-elevated); + border: 1px solid var(--border); + border-radius: var(--radius); + overflow: hidden; +} + +.pair-grid figcaption { + padding: 0.5rem 0.75rem; + font-size: 0.85rem; + color: var(--text-dim); +} + +.variant-card { + background: var(--bg-elevated); + border: 1px solid var(--border); + border-radius: var(--radius); + overflow: hidden; +} + +.variant-meta { + padding: 0.5rem 0.75rem; + font-size: 0.85rem; +} + +.variant-meta .tag { + color: var(--text-dim); + font-size: 0.75rem; + text-transform: uppercase; + margin-left: 0.35rem; +} + +.variant-meta dl { + margin: 0.4rem 0; + display: grid; + grid-template-columns: auto 1fr; + gap: 0.15rem 0.5rem; + font-size: 0.8rem; + color: var(--text-dim); +} + +.variant-meta dt { + font-weight: 600; +} + +.intermediate-grid li { + list-style: none; + font-size: 0.7rem; + color: var(--text-dim); + word-break: break-all; +} + +.intermediate-grid img { + width: 100%; + aspect-ratio: 1 / 1; + object-fit: cover; + border-radius: var(--radius); + border: 1px solid var(--border); + background: #000; +} + +/* --- section header with action button --- */ + +.section-header { + display: flex; + align-items: center; + justify-content: space-between; + gap: var(--gap); +} + +.section-header h2 { + margin: 0; +} + +/* --- buttons & forms --- */ + +.button { + display: inline-block; + padding: 0.6rem 1rem; + border-radius: var(--radius); + background: var(--bg-elevated); + border: 1px solid var(--border); + color: var(--text); + min-height: 2.75rem; + line-height: 1.6rem; +} + +.button-primary { + background: var(--accent); + border-color: var(--accent); + color: var(--accent-text); + font-weight: 600; +} + +.remix-form { + display: flex; + flex-direction: column; + gap: 0.35rem; + max-width: 28rem; +} + +.remix-form label { + margin-top: 0.75rem; + font-size: 0.85rem; + color: var(--text-dim); +} + +.remix-form select, +.remix-form button { + font-size: 1rem; + padding: 0.6rem 0.75rem; + border-radius: var(--radius); + border: 1px solid var(--border); + background: var(--bg-elevated); + color: var(--text); + min-height: 2.75rem; +} + +.remix-form button { + margin-top: 1.5rem; + cursor: pointer; +} diff --git a/app/templates/base.html b/app/templates/base.html new file mode 100644 index 0000000..8f6bb9d --- /dev/null +++ b/app/templates/base.html @@ -0,0 +1,17 @@ + + + + + + {% block title %}{{ site_title }}{% endblock %} + + + + +
+ {% block content %}{% endblock %} +
+ + diff --git a/app/templates/index.html b/app/templates/index.html new file mode 100644 index 0000000..84e9c61 --- /dev/null +++ b/app/templates/index.html @@ -0,0 +1,25 @@ +{% extends "base.html" %} +{% block title %}{{ site_title }}{% endblock %} +{% block content %} + {% if not jobs %} +

Noch keine Jobs. Bild per SFTP hochladen, dann kurz warten.

+ {% else %} + + {% endif %} +{% endblock %} diff --git a/app/templates/job.html b/app/templates/job.html new file mode 100644 index 0000000..7c9de1b --- /dev/null +++ b/app/templates/job.html @@ -0,0 +1,78 @@ +{% extends "base.html" %} +{% block title %}Job {{ job_id }} — {{ site_title }}{% endblock %} +{% block content %} + + +

Job {{ job_id }}

+

Status: {{ status.status or "unbekannt" }}

+ {% if status.error %} +

Fehler: {{ status.error }}

+ {% endif %} + +
+

Original & Rembg

+
+ {% if original_name %} +
+ Original +
+ Original · + Download +
+
+ {% endif %} + {% if has_rembg %} +
+ Freigestellt (rembg) +
+ Rembg · + Download +
+
+ {% endif %} +
+
+ +
+
+

Varianten

+ {% if has_rembg %} + + Remix + {% endif %} +
+ {% if not manifest.variants %} +

Noch keine Varianten fertig.

+ {% else %} +
    + {% for v in manifest.variants %} +
  • + Variante {{ v.id }} +
    + {{ v.id }} {{ v.source }} +
    +
    BG
    {{ v.background_filter }} + {{ v.background_blend }}
    +
    FG
    {{ v.foreground_filter }} + {{ v.foreground_blend }}
    +
    Opacity
    {{ v.blend_opacity }}
    +
    + Download +
    +
  • + {% endfor %} +
+ {% endif %} +
+ + {% if intermediates %} +
+

Zwischenschritte

+
    + {% for name in intermediates %} +
  • + {{ name }} + {{ name }} +
  • + {% endfor %} +
+
+ {% endif %} +{% endblock %} diff --git a/app/templates/remix.html b/app/templates/remix.html new file mode 100644 index 0000000..38436a7 --- /dev/null +++ b/app/templates/remix.html @@ -0,0 +1,50 @@ +{% extends "base.html" %} +{% block title %}Remix {{ job_id }} — {{ site_title }}{% endblock %} +{% block content %} + + +

Remix · Job {{ job_id }}

+ + {% if error %} +

{{ error }}

+ {% endif %} + +
+ + + + + + + + + + + + + + + + +
+{% endblock %} diff --git a/app/worker.py b/app/worker.py new file mode 100644 index 0000000..be9c798 --- /dev/null +++ b/app/worker.py @@ -0,0 +1,154 @@ +"""Inbox watcher + sequential job runner. + +Polls `DATA_DIR/inbox` for new, size-stable image files, copies each one +into its own `jobs//original.*` and runs the compose pipeline on +it. Files are NEVER deleted or moved from the inbox — `processed.json` +tracks what has already been handled (by path + size + mtime) so restarts +don't reprocess everything. + +Runs one job at a time (no threading) — this is intentional: the compose +pipeline is CPU heavy (gmic/rembg) and the worker container is capped at +`cpus: "1.0"` in compose.yml, so concurrency would only cause thrashing. +""" + +from __future__ import annotations + +import json +import logging +import shutil +import time +from pathlib import Path +from typing import Any + +from . import config, pipeline + +logging.basicConfig( + level=logging.INFO, + format="%(asctime)s %(levelname)s [%(name)s] %(message)s", +) +logger = logging.getLogger("livef12.worker") + + +def ensure_dirs() -> None: + for path in (config.INBOX_DIR, config.JOBS_DIR): + path.mkdir(parents=True, exist_ok=True) + + +def load_processed() -> dict[str, Any]: + if not config.PROCESSED_FILE.exists(): + return {} + try: + return json.loads(config.PROCESSED_FILE.read_text(encoding="utf-8")) + except (OSError, ValueError): + logger.warning("processed.json unreadable, starting fresh") + return {} + + +def save_processed(processed: dict[str, Any]) -> None: + tmp = config.PROCESSED_FILE.with_suffix(".json.tmp") + tmp.write_text(json.dumps(processed, indent=2, ensure_ascii=False), encoding="utf-8") + tmp.replace(config.PROCESSED_FILE) + + +def _file_key(path: Path) -> str: + return str(path.relative_to(config.INBOX_DIR)) + + +def _is_already_processed(processed: dict[str, Any], path: Path, stat: Any) -> bool: + entry = processed.get(_file_key(path)) + if not entry: + return False + return entry.get("size") == stat.st_size and entry.get("mtime") == stat.st_mtime + + +def _is_stable(path: Path) -> bool: + """A file is "stable" if its size doesn't change across a short wait — + cheap way to avoid picking up a half-uploaded SFTP transfer.""" + try: + size_before = path.stat().st_size + except OSError: + return False + time.sleep(config.STABLE_WAIT_SECONDS) + try: + size_after = path.stat().st_size + except OSError: + return False + return size_before == size_after and size_after > 0 + + +def find_new_files(processed: dict[str, Any]) -> list[Path]: + if not config.INBOX_DIR.exists(): + return [] + candidates: list[Path] = [] + for path in sorted(config.INBOX_DIR.rglob("*")): + if not path.is_file(): + continue + if path.suffix.lower() not in config.SUPPORTED_EXTENSIONS: + continue + try: + stat = path.stat() + except OSError: + continue + if _is_already_processed(processed, path, stat): + continue + candidates.append(path) + return candidates + + +def handle_file(path: Path, processed: dict[str, Any]) -> None: + if not _is_stable(path): + logger.info("skip %s: still being written", path.name) + return + + stat = path.stat() + job_id = pipeline.new_job_id() + suffix = path.suffix.lower() + paths = pipeline.job_paths(job_id, suffix) + paths.root.mkdir(parents=True, exist_ok=True) + + logger.info("new inbox file %s -> job %s", path.name, job_id) + # Copy (never move) so the inbox stays untouched. + shutil.copy2(path, paths.original) + + try: + pipeline.process_job(job_id, paths.original, suffix) + finally: + # Mark as processed regardless of pipeline outcome so a permanently + # broken image doesn't get retried forever; failures are visible in + # jobs//status.json for manual follow-up. + processed[_file_key(path)] = { + "size": stat.st_size, + "mtime": stat.st_mtime, + "job_id": job_id, + "processed_at": pipeline.now_iso(), + } + save_processed(processed) + + +def scan_once(processed: dict[str, Any]) -> None: + for path in find_new_files(processed): + try: + handle_file(path, processed) + except Exception: # noqa: BLE001 - one bad file must not kill the loop + logger.exception("failed to handle %s", path) + + +def main() -> int: + ensure_dirs() + processed = load_processed() + logger.info( + "worker started, watching %s (output_count=%d, nice=%d)", + config.INBOX_DIR, + config.OUTPUT_COUNT, + config.NICE_LEVEL, + ) + while True: + try: + scan_once(processed) + except Exception: # noqa: BLE001 + logger.exception("scan cycle failed") + time.sleep(config.POLL_INTERVAL_SECONDS) + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/assets/background b/assets/background new file mode 100644 index 0000000..6d8a13c --- /dev/null +++ b/assets/background @@ -0,0 +1,91 @@ +Array [Faded] +Array [Mirrored] +Array [Random Colors] +Array [Random] +Grid [Hexagonal] +Loose Photos +Ministeck +Puzzle +Taquin +Tiled Rotation +Bokeh +Circle Abstraction +Cubism +Cutout +Fractalize +Hope Poster +Marker Drawing +Painting +Polygonize [Delaunay] +Polygonize [Energy] +Posterize +Rodilius +Sketch +Smooth Abstract +Vector Painting +Warhol +Comicbook +Finger Paint +Blockism +Colored Pencils +Angoisse Anguish +Barbouillage Paint Daub +Chalk It Up [Fr] +Aurora +Doodle +Felt Pen +Ghost +Hard Sketch +Hough Sketch +Rodilius +Charcoal +Colorize [with Colormap] +Pencil Portrait +Threshold Etch +Chalk It Up [Fr] +Skeletik +Abstraction +Boost Chromaticity +Random Color Transformation +Multi Thresholds +Sepia +Isophotes +Segmentation +Blur [Bloom] +Blur [Linear] +Blur [Multidirectional] +Chromatic Aberrations +Huffman Glitches +Lomo +Noise [Gradient] +Noise [Perlin] +Oldschool 8bits +Random Shade Stripes +Sloppy Mess +DCP Dehaze +Tunnel +Light Patch +Shadow Patch +Sinusoidal Map +Halftone +Mineral Mosaic +Random Color Ellipses +Random Rectangles +Voronoi +Reptile +Stereo Image +Query Primary +Image InfoMap +60's Cinema +Lylejk Luma Invert +Contrast Swiss Mask +Stringify Mod +Rainbowify +Cubisme A +Samj Deformation 20230712 +Path Et Solidify +Samj Shapeprevalent Degradations +EPPE Transform +Mosaic B +CeKoaSa 001 +Test G \ No newline at end of file diff --git a/assets/blend_modes b/assets/blend_modes new file mode 100644 index 0000000..7e9e946 --- /dev/null +++ b/assets/blend_modes @@ -0,0 +1,58 @@ +add +alpha +and +average +blue +burn +darken +difference +divide +dodge +edges +exclusion +freeze +grainextract +grainmerge +green +hardlight +hardmix +hue +interpolation +lchlightness +lighten +lightness +linearburn +linearlight +luminance +multiply +negation +or +overlay +pinlight +red +reflect +saturation +screen +seamless +seamless_mixed +shapeareamax +shapeareamax0 +shapeareamin +shapeareamin0 +shapeaverage +shapeaverage0 +shapemedian +shapemedian0 +shapemin +shapemin0 +shapemax +shapemax0 +shapeprevalent +softburn +softdodge +softlight +stamp +subtract +value +vividlight +xor diff --git a/assets/filters.json b/assets/filters.json new file mode 100644 index 0000000..e06101a --- /dev/null +++ b/assets/filters.json @@ -0,0 +1,4858 @@ +[ + { + "plain_name": "Download External Data", + "full_command": "gui_download_all_data 0" + }, + { + "plain_name": "Gmicky - Roddy", + "full_command": "fx_gmicky 0" + }, + { + "plain_name": "Send Feedback", + "full_command": "_none_ \"Anonymous\",3,\"Write your message here...\",0" + }, + { + "plain_name": "What's New?", + "full_command": "_none_ \"0\",\"\",\"\",0" + }, + { + "plain_name": "Array [Faded]", + "full_command": "fx_array_fade 2,2,0,0,80,90,0,0" + }, + { + "plain_name": "Array [Mirrored]", + "full_command": "fx_array_mirror 1,0,0,2,0,0,0" + }, + { + "plain_name": "Array [Random Colors]", + "full_command": "fx_array_color 5,5,0.5" + }, + { + "plain_name": "Array [Random]", + "full_command": "fx_array_random 5,5,7,7,0" + }, + { + "plain_name": "Array [Regular]", + "full_command": "fx_array 2,2,0,0,0,0" + }, + { + "plain_name": "Ascii Art", + "full_command": "fx_asciiart 5,\" .oO0\",16,15,16,2,0,0.2,0,0,\"\",\"gmic_asciiart.txt\"" + }, + { + "plain_name": "Chessboard", + "full_command": "fx_chessboard 64,64,0,0,0,0.25,0,0,0,255,255,255,255,255" + }, + { + "plain_name": "Dices", + "full_command": "fx_dices 2,24,1" + }, + { + "plain_name": "Drawn Montage", + "full_command": "fx_drawn_montage 0,0,0,0,255,-10,50,50,0,\"-1\",\"0:0:0:0:50:50:0\",\"0:0:0:0:50:50:0\",\"0:0:0:0:50:50:0\",\"0:0:0:0:50:50:0\",\"0:0:0:0:50:50:0\",\"0:0:0:0:50:50:0\",\"0:0:0:0:50:50:0\",\"0:0:0:0:50:50:0\",\"0:0:0:0:50:50:0\",\"0:0:0:0:50:50:0\",\"0:0:0:0:50:50:0\",\"0:0:0:0:50:50:0\",\"0:0:0:0:50:50:0\",\"0:0:0:0:50:50:0\",\"0:0:0:0:50:50:0\",\"0:0:0:0:50:50:0\"" + }, + { + "plain_name": "Extract Objects", + "full_command": "fx_extract_objects 0,0,20,50,0.3,0,0,1" + }, + { + "plain_name": "Grid [Cartesian]", + "full_command": "fx_imagegrid 10,10" + }, + { + "plain_name": "Grid [Hexagonal]", + "full_command": "fx_imagegrid_hexagonal 32,0.1,1" + }, + { + "plain_name": "Grid [Triangular]", + "full_command": "fx_imagegrid_triangular 10,18,0,0,0,0,128" + }, + { + "plain_name": "Loose Photos", + "full_command": "fx_loose_photos 60,40,50,100,50,360,0,2,255,255,255,255,50,25,0,0,0,0,0,0,50,1,1,1" + }, + { + "plain_name": "Make Seamless [Diffusion]", + "full_command": "fx_make_seamless 0,0,3" + }, + { + "plain_name": "Make Seamless [Patch-Based]", + "full_command": "fx_frame_seamless 32,9,0,1,100,0,3" + }, + { + "plain_name": "Ministeck", + "full_command": "fx_ministeck 8,64,8,2,100,0.3,0" + }, + { + "plain_name": "Montage", + "full_command": "fx_montage 0,\"V(H(0,1),H(2,V(3,4)))\",1,0.5,0,0,0,0,0,255,0,0,0,0,0" + }, + { + "plain_name": "Puzzle", + "full_command": "fx_puzzle 5,5,0.5,0,0,0.3,100,0.2,255,100,0,0,0,0,0,0" + }, + { + "plain_name": "Shuffle Patches", + "full_command": "fx_shuffle_patches 0,0,64,0,20,0" + }, + { + "plain_name": "Taquin", + "full_command": "fx_taquin 7,7,0,50,5,0,0,0,0,255,0" + }, + { + "plain_name": "Tileable Rotation", + "full_command": "fx_rotate_tileable 45,8,0" + }, + { + "plain_name": "Tiled Isolation", + "full_command": "fx_isolate_tiles 10,10,5,5,1,1" + }, + { + "plain_name": "Tiled Normalization", + "full_command": "fx_normalize_tiles 32,32,0,255,0,0,12" + }, + { + "plain_name": "Tiled Parameterization", + "full_command": "fx_parameterize_tiles 32,32,0,0,0" + }, + { + "plain_name": "Tiled Random Shifts", + "full_command": "fx_shift_tiles 10,10,10,1" + }, + { + "plain_name": "Tiled Rotation", + "full_command": "fx_rotate_tiles 5,5,15,3,3,1.8" + }, + { + "plain_name": "Aurora", + "full_command": "gcd_aurora 6,1,0" + }, + { + "plain_name": "Bokeh", + "full_command": "fx_bokeh 3,8,0,30,8,4,0.3,0.2,210,210,80,160,0.7,30,20,20,1,2,170,130,20,110,0.15" + }, + { + "plain_name": "Brushify", + "full_command": "fx_brushify 7,0.25,4,64,25,12,0,2,4,0.2,0.5,30,1,1,1,5,0,0.2,1" + }, + { + "plain_name": "Cartoon", + "full_command": "cartoon 3,200,20,0.25,1.5,8" + }, + { + "plain_name": "Circle Abstraction", + "full_command": "fx_circle_abstraction 8,5,0.8,0,1,1,1" + }, + { + "plain_name": "Cubism", + "full_command": "fx_cubism 2,50,10,90,0.7,0" + }, + { + "plain_name": "Cutout", + "full_command": "fx_cutout 4,0.5,4,1" + }, + { + "plain_name": "Diffusion Tensors", + "full_command": "fx_diffusiontensors 10,5,3,1,0.15,1,0,3" + }, + { + "plain_name": "Doodle", + "full_command": "fx_doodle 30,2,2,1.5,2,70,1" + }, + { + "plain_name": "Ellipsionism", + "full_command": "fx_ellipsionism 20,10,0.5,0.7,3,0.5" + }, + { + "plain_name": "Felt Pen", + "full_command": "fx_feltpen 300,50,1,0.1,20,5" + }, + { + "plain_name": "Fractalize", + "full_command": "fractalize 0.8" + }, + { + "plain_name": "Ghost", + "full_command": "fx_ghost 200,2,2,1,3,16,0" + }, + { + "plain_name": "Hard Sketch", + "full_command": "fx_hardsketchbw 300,50,1,0.1,20,0,4" + }, + { + "plain_name": "Highlight Bloom", + "full_command": "fx_highlight_bloom 90,60,60,30,20" + }, + { + "plain_name": "Hope Poster", + "full_command": "fx_poster_hope 0,3" + }, + { + "plain_name": "Hough Sketch", + "full_command": "fx_houghsketchbw 1.25,10,5,80,0.1,4" + }, + { + "plain_name": "Illustration Look", + "full_command": "fx_illustration_look 100,100,0,0,0,0" + }, + { + "plain_name": "Kuwahara", + "full_command": "fx_kuwahara 2,5,0,0" + }, + { + "plain_name": "Linify", + "full_command": "fx_linify 40,2,40,10,24,0,1" + }, + { + "plain_name": "Lylejk's Painting", + "full_command": "fx_lylejk_painting 10,2,4,10" + }, + { + "plain_name": "Marker Drawing", + "full_command": "fx_marker_drawing 70,4,10,15,100,85,0.5,3,3,1,20,255,255,255,255" + }, + { + "plain_name": "Paint With Brush", + "full_command": "fx_paint_with_brush 0,\"-1\",1,16,30,100,100,10,80,0.5,3,45,0,6,2,10,0,0,0,60,20,1,0,0,0,30,15,15,15,15,15,15,1,45,0" + }, + { + "plain_name": "Painting", + "full_command": "fx_painting 5,2.5,1.5,50,1" + }, + { + "plain_name": "Polygonize [Delaunay]", + "full_command": "fx_polygonize_delaunay 40,5,75,0.5,3,50,0,0,0,255,1" + }, + { + "plain_name": "Polygonize [Energy]", + "full_command": "fx_polygonize 300,10,10,10,10,0,0,0,255" + }, + { + "plain_name": "Poster Edges", + "full_command": "fx_poster_edges 20,60,5,0,10,0,0" + }, + { + "plain_name": "Posterize", + "full_command": "fx_posterize 150,30,1,12,0,0,0" + }, + { + "plain_name": "Quadtree Variations", + "full_command": "fx_quadtree 0,1024,0.5,0,3,1.5,1,1" + }, + { + "plain_name": "Rodilius", + "full_command": "fx_rodilius 10,10,300,5,30,0,1,0,0" + }, + { + "plain_name": "Shapeism", + "full_command": "fx_shapeism 2,7,0.38,0,1,5,32,8,3,0,5,0.5,1,0,0,0,255" + }, + { + "plain_name": "Sharp Abstract", + "full_command": "fx_sharp_abstract 4,10,0.5,0" + }, + { + "plain_name": "Sketch", + "full_command": "fx_sketchbw 3,45,180,30,1.75,0.02,0.5,0.75,0.1,0.7,3,6,0,1,4,0" + }, + { + "plain_name": "Smooth Abstract", + "full_command": "fx_smooth_abstract 75,0,20,1,30" + }, + { + "plain_name": "Stringify", + "full_command": "fx_stringify 2,32,20,1,100,32,20,25,0,0,0,0,255" + }, + { + "plain_name": "Stylize", + "full_command": "fx_stylize 0,5,0,1,0.5,2,3,0.5,0.1,3,0,0,0.7,1,0,1,0,5,5,7,1,30,2,2,1.85,0" + }, + { + "plain_name": "Vector Painting", + "full_command": "fx_vector_painting 9" + }, + { + "plain_name": "Warhol", + "full_command": "warhol 3,3,2,40" + }, + { + "plain_name": "B&W Stencil", + "full_command": "fx_stencilbw 10,10,0,0" + }, + { + "plain_name": "Black & White", + "full_command": "fx_blackandwhite 0.299,0,0.587,0,0.114,0,0,0,0,0,0,0,0,0,2,0,0,0,16,4,0,0" + }, + { + "plain_name": "Charcoal", + "full_command": "fx_charcoal 65,70,170,0,1,0,50,70,255,255,255,255,0,0,0,255,0" + }, + { + "plain_name": "Colorize [Interactive]", + "full_command": "fx_colorize_interactive 0,0,0,\"\",\"\",\"\",0,\"0,0\",\"-1\"" + }, + { + "plain_name": "Colorize [Photographs]", + "full_command": "fx_recolorize 2,0.2,0" + }, + { + "plain_name": "Colorize [with Colormap]", + "full_command": "fx_bwrecolorize 0,0,0,0,0,1,0,5,0,0,0,255,43,25,55,255,158,137,189,255,224,191,228,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255" + }, + { + "plain_name": "Colorize Lineart [Auto-Fill]", + "full_command": "fx_autofill_lineart 90,1,8,0,0" + }, + { + "plain_name": "Colorize Lineart [Propagation]", + "full_command": "fx_colorize_lineart 0,0,0,0.05" + }, + { + "plain_name": "Colorize Lineart [Smart Coloring]", + "full_command": "fx_colorize_lineart_smart 0,95,0,0,1,24,200,0,75,2,60,20,90,1,10,1,0" + }, + { + "plain_name": "Desaturate Norm", + "full_command": "fx_gcd_norm_eq 0.5,0.5,2,0" + }, + { + "plain_name": "Dithering", + "full_command": "fx_ditheredbw 0,0,0,0,0,0" + }, + { + "plain_name": "Engrave", + "full_command": "fx_engrave 0.5,50,0,8,40,0,0,0,10,1,0,0,0,1" + }, + { + "plain_name": "Filaments", + "full_command": "fx_filaments 50,50,75,30,10,0,1,1,1,1,1,50,0" + }, + { + "plain_name": "Freaky B&W", + "full_command": "fx_freaky_bw 90,20,0,0,0" + }, + { + "plain_name": "Ink Wash", + "full_command": "fx_ink_wash 0.14,23,0,0.5,0.54,2.25,0,2,6,5,20" + }, + { + "plain_name": "Multi-Layer Etch", + "full_command": "fx_gcd_layeretch 11,4,12,0.12,100,8.5,5,0,0,3,1,1,0" + }, + { + "plain_name": "Pencil", + "full_command": "fx_pencilbw 0.3,60,0,0" + }, + { + "plain_name": "Pencil Portrait", + "full_command": "fx_pencil_portraitbw 30,120,1,0.5,144,79,21,255" + }, + { + "plain_name": "Stamp", + "full_command": "fx_stamp 1,50,0,0,0,0,1" + }, + { + "plain_name": "Threshold Etch", + "full_command": "fx_gcd_etch 125,153,171,185,0.1,50,80,50,10,15,12,20,0,1,0.3,1,0,0" + }, + { + "plain_name": "Abstraction", + "full_command": "fx_color_abstraction 1,10,0.2" + }, + { + "plain_name": "Apply External CLUT", + "full_command": "fx_apply_haldclut 2,\"\",0,100,0,0,0,0,0,0" + }, + { + "plain_name": "Apply From CLUT Set", + "full_command": "apply_from_clut_set \"\",1,100,0,0,0,0,0,0" + }, + { + "plain_name": "Basic Adjustments", + "full_command": "fx_adjust_colors 0,0,0,0,0" + }, + { + "plain_name": "Boost Chromaticity", + "full_command": "fx_boost_chroma 50,0" + }, + { + "plain_name": "Boost-Fade", + "full_command": "fx_boost_fade 5,0" + }, + { + "plain_name": "Channel Processing", + "full_command": "fx_channel_processing 0,0,0,0,0,0,100,256,0,0,0,2,0" + }, + { + "plain_name": "Channels to Layers", + "full_command": "fx_channels2layers 0" + }, + { + "plain_name": "CLUT from After - Before Layers", + "full_command": "fx_clut_from_ab 0,4,0,\"\",\"output.cube\",50" + }, + { + "plain_name": "Color Balance", + "full_command": "fx_balance_gamma 128,128,128,255,1" + }, + { + "plain_name": "Color Blindness", + "full_command": "colorblind 0" + }, + { + "plain_name": "Color Grading", + "full_command": "jl_colorgrading 0,0,1,1,0,0,0,0,0,0,1,0,0,0,70,0,0,0,0,0,70,180,0,1,0,0,0" + }, + { + "plain_name": "Color Mask [Interactive]", + "full_command": "fx_mask_color 13,10,5,0" + }, + { + "plain_name": "Color Presets", + "full_command": "fx_color_presets 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,512,100,0,0,0,0,0,0,0,50,50,\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\"" + }, + { + "plain_name": "Color Temperature", + "full_command": "fx_tk_colortemp 0,0,0" + }, + { + "plain_name": "Colorful Blobs", + "full_command": "fx_colorful_blobs 1,200,200,200,0,1,25,25,50,50,255,0,0,255,\"-1,-1,-1,-1\",75,25,50,50,0,255,0,255,\"-1,-1,-1,-1\",50,75,50,50,0,0,255,255,\"-1,-1,-1,-1\",5,90,50,50,255,255,0,255,\"-1,-1,-1,-1\",5,90,50,50,255,0,255,255,\"-1,-1,-1,-1\",5,90,50,50,0,255,255,255,\"-1,-1,-1,-1\",5,90,50,50,255,255,255,255,\"-1,-1,-1,-1\",5,90,50,50,0,0,0,255,\"-1,-1,-1,-1\",5,90,50,50,255,128,64,255,\"-1,-1,-1,-1\",5,90,50,50,255,64,128,255,\"-1,-1,-1,-1\",5,90,50,50,128,64,255,255,\"-1,-1,-1,-1\",5,90,50,50,64,128,255,255,\"-1,-1,-1,-1\"" + }, + { + "plain_name": "Colormap", + "full_command": "fx_colormap 0,1,32,8,0,0,0,255,255,255,255,255,255,0,0,255,0,255,0,255,0,0,255,255,255,255,0,255,255,0,255,255,0,255,255,255,0,50,50" + }, + { + "plain_name": "Curves", + "full_command": "fx_apply_curve 0,-1,128,-1,128,-1,128,-1,128,-1,128,255,1,0,0,0,0" + }, + { + "plain_name": "Customize CLUT", + "full_command": "fx_customize_clut 100,0,10,0,0,0,0,0,0,0,0,0.5,1,0,0,0,255,0,0,0,255,1,255,255,255,255,255,196,128,255,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,255,0,0,0,0,255,0,0,0,255" + }, + { + "plain_name": "Decompose Channels", + "full_command": "fx_decompose_channels 7,0,0,1" + }, + { + "plain_name": "Detect Skin", + "full_command": "fx_detect_skin 1,0.5,0.5,1,1,50,50,5,1,0,50,50" + }, + { + "plain_name": "Equalize HSI-HSL-HSV", + "full_command": "fx_equalize_hsv 1,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,50,50" + }, + { + "plain_name": "Equalize HSV", + "full_command": "fx_hsv_equalizer 0,180,40,0,0,0,180,40,0,0,0,180,40,0,0,0" + }, + { + "plain_name": "HSL Adjustment", + "full_command": "gcd_hsl 1,0,0,180,0.2,0,1,1,0" + }, + { + "plain_name": "HSV Select", + "full_command": "gcd_hsv_select 0,0.5,1,180,0.5,0.5,2,2,18,0,0,0" + }, + { + "plain_name": "Metallic Look", + "full_command": "fx_tk_metallic 1,0,0,0" + }, + { + "plain_name": "Mixer [CMYK]", + "full_command": "fx_mix_cmyk 1,0,0,1,0,0,1,0,0,1,0,0,0,2" + }, + { + "plain_name": "Mixer [Generic]", + "full_command": "fx_mixer_generic 7,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,50,50" + }, + { + "plain_name": "Mixer [HSV]", + "full_command": "fx_mix_hsv 1,0,0,1,0,0,1,0,0,0,2" + }, + { + "plain_name": "Mixer [Lab]", + "full_command": "fx_mix_lab 1,0,0,1,0,0,1,0,0,0,2" + }, + { + "plain_name": "Mixer [PCA]", + "full_command": "fx_mix_pca 0,0,0,0,0,0,0,0,0,0,0,0,1,\"-1,-1,-1,-1\",\"0,0,0,0,0,0,0,0,0,0,0,0\",0,50,50" + }, + { + "plain_name": "Mixer [RGB]", + "full_command": "fx_mix_rgb 1,0,0,1,0,0,1,0,0,0,2" + }, + { + "plain_name": "Mixer [YCbCr]", + "full_command": "fx_mix_ycbcr 1,0,0,1,0,0,1,0,0,0,2" + }, + { + "plain_name": "Random Color Transformation", + "full_command": "fx_random_color_transformation 0,0,\"1\",100,0,0,0,0,0,0,50,50" + }, + { + "plain_name": "Retinex", + "full_command": "fx_retinex 75,16,1,1,1,5,15,80,250" + }, + { + "plain_name": "Retro Fade", + "full_command": "fx_retrofade 20,6,40" + }, + { + "plain_name": "Select-Replace Color", + "full_command": "fx_select_color 0,20,0,0,255,255,255,255,0,255,0,0,255" + }, + { + "plain_name": "Selective Desaturation", + "full_command": "fx_selective_desaturation 255,255,255,255,0,3,0,0" + }, + { + "plain_name": "Sepia", + "full_command": "fx_sepia 0,0,0" + }, + { + "plain_name": "Simulate Film", + "full_command": "fx_simulate_film 0,0,0,0,1,1,0,1,0,1,512,100,0,0,0,0,0,0,0,50,50" + }, + { + "plain_name": "Specific Saturation", + "full_command": "gcd_hio_levels 1,1,39,0,1,1,0,0,0,\"0\"" + }, + { + "plain_name": "Transfer Colors [Multi]", + "full_command": "fx_transfer_colors 0,2,0,0,35,1,1,0,\"0\",\"0\",0,0,0,0,256,0.01,1,1,0,0,0,0,255,0,0,0,255,255,255,255,255,255,255,255,255,255,0,0,255,255,0,0,255,0,255,0,255,0,255,0,255,0,0,255,255,0,0,255,255,255,255,0,255,255,255,0,255,255,0,255,255,255,0,255,255,0,255,255,255,0,255,255,255" + }, + { + "plain_name": "Transfer Colors [Patch-Based]", + "full_command": "fx_gcd_transfer_colors_patch 6,3,5,5,0,0" + }, + { + "plain_name": "Tune HSV Colors", + "full_command": "fx_tune_hsv 2,0,0,0,255,100,100,100,2,255,255,255,255,100,100,100,1,128,128,128,255,0,50,100,0,255,0,0,255,100,12.5,0,0,255,255,0,255,100,12.5,0,0,0,255,0,255,100,12.5,0,0,0,255,255,255,100,12.5,0,0,0,0,255,255,100,12.5,0,0,255,0,255,255,100,12.5,0,2,0,50,50" + }, + { + "plain_name": "User-Defined", + "full_command": "fx_custom_transform \"i\",\"i + 90*(x/w)*cos(i/10)\",\"i\",\"i\",\"i\",\"i\",0" + }, + { + "plain_name": "Vibrance", + "full_command": "fx_vibrance 0.5" + }, + { + "plain_name": "Vintage Style", + "full_command": "fx_tk_vintage 2,0.85,0.7,80,200,5,147,26,161,255,0.3,235,220,176,255,0.4,190,181,108,255,0.2,0,0,100,255,0,0.3,25,0,0" + }, + { + "plain_name": "Zone System", + "full_command": "fx_zonesystem 1,10,1,1,0,255,0" + }, + { + "plain_name": "Convolve", + "full_command": "fx_convolve 0,1,\"0,1,0;1,-4,1;0,1,0\",1,1,2" + }, + { + "plain_name": "Curvature", + "full_command": "fx_curvature 2,0,100,0,0" + }, + { + "plain_name": "Difference of Gaussians", + "full_command": "fx_dog 1.4,1.5,0,0,1" + }, + { + "plain_name": "Distance Transform", + "full_command": "fx_distance 128,2,2,32" + }, + { + "plain_name": "Edges", + "full_command": "fx_edges 0,15,0" + }, + { + "plain_name": "Edges (Canny)", + "full_command": "fx_canny 5,0.05,0.15,1" + }, + { + "plain_name": "Edges Offsets", + "full_command": "fx_edge_offsets 0,15,4,1,0" + }, + { + "plain_name": "Extract Foreground [Interactive]", + "full_command": "fx_extract_foreground 0,0,0,0,\"0,0\",\"-1\"" + }, + { + "plain_name": "Gradient Norm", + "full_command": "fx_gradient_norm 0,0.5,0,100,0" + }, + { + "plain_name": "Gradient RGB", + "full_command": "fx_gradient2rgb 0,0,100,0,0" + }, + { + "plain_name": "Isophotes", + "full_command": "fx_isophotes 8,4,1" + }, + { + "plain_name": "Laplacian", + "full_command": "fx_laplacian 0,0,100,0,0" + }, + { + "plain_name": "Local Orientation", + "full_command": "fx_local_orientation 0,0,100,0,0" + }, + { + "plain_name": "Morphological Filter", + "full_command": "fx_morphological 0,0,5,\"1,0,1; 0,1,0; 1,0,1\",0,0,0,0,0,50,50" + }, + { + "plain_name": "Segmentation", + "full_command": "fx_segment_watershed 2,1,0,0" + }, + { + "plain_name": "Skeleton", + "full_command": "fx_skeleton 0,0" + }, + { + "plain_name": "Super-Pixels", + "full_command": "fx_superpixels 16,10,5,1,1,1,0,0,0,255" + }, + { + "plain_name": "Thin Edges", + "full_command": "fx_thin_edges 0,15,0" + }, + { + "plain_name": "Breaks", + "full_command": "fx_breaks 0,30,30,0.5,3" + }, + { + "plain_name": "Cartesian Transform", + "full_command": "fx_custom_deformation \"(w*a%)*cos(b*y/h)\",\"(h*c%)*cos(d*x/w)\",1,1,3,10,10,10,10" + }, + { + "plain_name": "Circle Transform", + "full_command": "fx_circle_transform 50,50,75,50,-2,-2,0,1,3,1" + }, + { + "plain_name": "Conformal Maps", + "full_command": "fx_conformal_maps 0,1,0,\"((1.1 + i*z/6)/(1.04 - i*z/6))^6.2\",0,0,0,0,0,3,0,0,\"1024\",\"1024\"" + }, + { + "plain_name": "Continuous Droste", + "full_command": "souphead_droste10 40,100,1,1,1,0,0,0,0,0,1,10,1,0,90,0,0,0,0,1,0,0,1,0,0,0,0,0,1,0,0" + }, + { + "plain_name": "Crease", + "full_command": "fx_crease 30,10,3" + }, + { + "plain_name": "Distort [RBF]", + "full_command": "fx_distort_rbf 10,10,90,10,10,90,90,90,3,\"r\",0" + }, + { + "plain_name": "Distort Lens", + "full_command": "fx_distort_lens 0.1,0,0,50,50,0" + }, + { + "plain_name": "Drop Water", + "full_command": "fx_drop_water 0,20,2,80,0,3,35,10,1,0.5,0.25,0.5,0.75,0.05,0.15,1" + }, + { + "plain_name": "Equirectangular to Nadir-Zenith", + "full_command": "fx_equirectangular2nadirzenith 0" + }, + { + "plain_name": "Euclidean - Polar", + "full_command": "fx_euclidean2polar 50,50,1,1,0" + }, + { + "plain_name": "Fish-Eye", + "full_command": "fisheye 50,50,70,1" + }, + { + "plain_name": "Flower", + "full_command": "fx_flower 50,50,75,50,6,0,3" + }, + { + "plain_name": "Heightfield Warp", + "full_command": "fx_heightfield_warp 1,\"0.25*cos(3*pi*x)*sin(3*pi*y)\",100,0,1,1.5,80,20,50,20,20,40,30,20,1,\"50,50\",50,50,75,50" + }, + { + "plain_name": "Kaleidoscope [Blended]", + "full_command": "fx_rotoidoscope 50,50,10,0.5,3" + }, + { + "plain_name": "Kaleidoscope [Polar]", + "full_command": "fx_kaleidoscope 50,50,0,0,100,10,3" + }, + { + "plain_name": "Kaleidoscope [Symmetry]", + "full_command": "fx_symmetrizoscope 4,0,3,0" + }, + { + "plain_name": "Morph [Interactive]", + "full_command": "fx_morph_interactive 16,0,\"-1\"" + }, + { + "plain_name": "Perspective", + "full_command": "fx_warp_perspective 1.73,0,1,50,50,0,0,2" + }, + { + "plain_name": "Poincaré Disk", + "full_command": "fx_poincare_disk 5,6,100,20,0,1,1,1,50,50,0,0,2,0,0,0,255,0,0,0,255,255,255,255,255" + }, + { + "plain_name": "Polar Transform", + "full_command": "fx_transform_polar 0,50,50,\"r + R/10*cos(a*5)\",\"a\",3" + }, + { + "plain_name": "Quadrangle", + "full_command": "fx_quadrangle 5,5,95,25,60,95,40,95,1,3,1" + }, + { + "plain_name": "Raindrops", + "full_command": "raindrops 80,0.1,1,0" + }, + { + "plain_name": "Random", + "full_command": "deform 10" + }, + { + "plain_name": "Reflection", + "full_command": "fx_reflect 50,1,110,160,190,64,0,1.5,0,-3.3,7,1.5" + }, + { + "plain_name": "Ripple", + "full_command": "ripple 10,20,2,0,0" + }, + { + "plain_name": "Seamcarve", + "full_command": "fx_seamcarve 85,100,15,0,1" + }, + { + "plain_name": "Sphere", + "full_command": "fx_map_sphere 512,512,90,0.5,0,0,20,0,0,0,0.5" + }, + { + "plain_name": "Spherize", + "full_command": "fx_spherize 50,1,0,50,50,0,0,2,0" + }, + { + "plain_name": "Square to Circle", + "full_command": "fx_square_circle 0,1,0,0,0,0,0" + }, + { + "plain_name": "Square to Circle [alt]", + "full_command": "fx_square_circle_alt 0,50,50,100,0,0,1,0,1" + }, + { + "plain_name": "Stereographic Projection", + "full_command": "fx_project_stereographic 0,50,50,50,75,0,0,0,0,0,\"50,50\"" + }, + { + "plain_name": "Symmetrize", + "full_command": "fx_symmetrize 50,50,50,75,0,0,0,0" + }, + { + "plain_name": "Textured Glass", + "full_command": "fx_textured_glass 40,40,1,1,0,2,0" + }, + { + "plain_name": "Twirl", + "full_command": "fx_twirl 1,50,50,3" + }, + { + "plain_name": "Warp [Interactive]", + "full_command": "fx_warp_interactive 0,2,0,\"-1\"" + }, + { + "plain_name": "Warp [RBF]", + "full_command": "fx_warp_rbf 0,\"0\",3,2,0,25,25,\"25,25\",\"25,25\",75,25,\"75,25\",\"75,25\",75,75,\"75,75\",\"75,75\",25,75,\"25,75\",\"25,75\",50,50,\"50,50\",\"50,50\",10,50,\"10,50\",\"10,50\",20,50,\"20,50\",\"20,50\",30,50,\"30,50\",\"30,50\",40,50,\"40,50\",\"40,50\",60,50,\"60,50\",\"60,50\",70,50,\"70,50\",\"70,50\",80,50,\"80,50\",\"80,50\",90,50,\"90,50\",\"90,50\"" + }, + { + "plain_name": "Water", + "full_command": "water 30,1.5,45" + }, + { + "plain_name": "Wave", + "full_command": "wave 10,0.4,50,50" + }, + { + "plain_name": "Wind", + "full_command": "fx_wind 20,0,0.7,20,1,0,0" + }, + { + "plain_name": "Zoom", + "full_command": "fx_zoom_v2 \"50\",\"50\",50,50,75,50,1,0" + }, + { + "plain_name": "Add Grain", + "full_command": "fx_simulate_grain 0,1,0.2,100,0,0,0,0,0,0,0,0,0" + }, + { + "plain_name": "Blur [Angular]", + "full_command": "fx_blur_angular 2,50,50,0,1,7,0" + }, + { + "plain_name": "Blur [Bloom]", + "full_command": "fx_blur_bloom 1,2,5,0,1,0,0,0,7" + }, + { + "plain_name": "Blur [Depth-Of-Field]", + "full_command": "fx_blur_dof 3,16,0,0,50,50,30,30,0,1,1,0" + }, + { + "plain_name": "Blur [Gaussian]", + "full_command": "fx_blur_gaussian 3,0,0,3,7,0" + }, + { + "plain_name": "Blur [Glow]", + "full_command": "fx_glow 6,7,0" + }, + { + "plain_name": "Blur [Linear]", + "full_command": "fx_blur_linear 10,0.5,0,0,2,7,0" + }, + { + "plain_name": "Blur [Motion]", + "full_command": "fx_blur_motion 0,1,0,\"-1\",50,50,50,50,50,50,50,50,50,50,1,75,0,3" + }, + { + "plain_name": "Blur [Multidirectional]", + "full_command": "fx_blur_multidirectional 5,0,360,150,0,1,0,0,2,7" + }, + { + "plain_name": "Blur [Radial]", + "full_command": "fx_blur_radial 3,50,50,0,1,7,0" + }, + { + "plain_name": "Chromatic Aberrations", + "full_command": "fx_chromatic_aberrations 255,0,0,255,0,2,2,0,50,1,0,255,0,255,0,0,0,0,0,1" + }, + { + "plain_name": "CRT Phosphors", + "full_command": "fx_crt_phosphors 0,3,0,0,4,50,1,0,0,0,1,0,50,50,0" + }, + { + "plain_name": "CRT Scanlines", + "full_command": "fx_crt_scanlines 4,16,1,0,1,1,0,0,50,50,50" + }, + { + "plain_name": "CRT Sub-Pixels", + "full_command": "fx_gcd_crt 1.8,1.8,0,0" + }, + { + "plain_name": "Dirty", + "full_command": "fx_dirty 30,1,0,0" + }, + { + "plain_name": "Flip & Rotate Blocks", + "full_command": "fx_flip_blocks 4,4,3,1,0" + }, + { + "plain_name": "Huffman Glitches", + "full_command": "fx_huffman_glitches 30,0,25,0,0,0,0,0,50,50" + }, + { + "plain_name": "JPEG Artefacts", + "full_command": "fx_jpeg_artefacts 50" + }, + { + "plain_name": "Lomo", + "full_command": "fx_lomo 20" + }, + { + "plain_name": "Mess with Bits", + "full_command": "fx_mess_with_bits 1,15,1,1,0,15,100,0" + }, + { + "plain_name": "Noise [Additive]", + "full_command": "fx_noise 10,0,7,1" + }, + { + "plain_name": "Noise [Gradient]", + "full_command": "fx_noise_gradient 100,0,0,2" + }, + { + "plain_name": "Noise [Perlin]", + "full_command": "fx_noise_perlin 0,100,8,0,0,4,0,0,2,0,0,1,0,2" + }, + { + "plain_name": "Noise [Spread]", + "full_command": "fx_spread 4,4,0,0" + }, + { + "plain_name": "Offset Stripes", + "full_command": "fx_offset_stripes 1,0,0,10,20,10,20,3,0" + }, + { + "plain_name": "Old-Movie Stripes", + "full_command": "fx_stripes_y 10,0,0" + }, + { + "plain_name": "Oldschool 8bits", + "full_command": "fx_8bits 25,800,16" + }, + { + "plain_name": "Pixel Sort", + "full_command": "fx_pixelsort 1,0,0,1,0,100,0,0,0" + }, + { + "plain_name": "Rain & Snow", + "full_command": "fx_rain 65,10,50,0.1,1,1,0,50,50" + }, + { + "plain_name": "Random Shade Stripes", + "full_command": "fx_shade_stripes 30,1,0.8,1.3,0,0" + }, + { + "plain_name": "Rebuild From Similar Blocks", + "full_command": "fx_rebuild_from_similar_blocks 5,10,0.75,1" + }, + { + "plain_name": "Scanlines", + "full_command": "fx_scanlines 60,2,0,0,0,0,0" + }, + { + "plain_name": "Self Glitching", + "full_command": "fx_self_glitching 0,0,0,0,50,50,3,0" + }, + { + "plain_name": "Streak", + "full_command": "fx_streak 255,0,0,255,0,0,3" + }, + { + "plain_name": "VHS Filter", + "full_command": "fx_vhs_filter 3,15,20,5,1" + }, + { + "plain_name": "Visible Watermark", + "full_command": "fx_watermark_visible \"\\\\251 G'MIC\",0.4,27,50,0,25,1,0.5" + }, + { + "plain_name": "Warp by Intensity", + "full_command": "fx_warp_by_intensity 0.04,0.04,128,128,0,1,3,0" + }, + { + "plain_name": "DCP Dehaze", + "full_command": "jeje_dehaze 5,1,0.2,1,0,0,0,0,0" + }, + { + "plain_name": "Details Equalizer", + "full_command": "fx_equalize_details 5,0.5,0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,0,32" + }, + { + "plain_name": "Dynamic Range Increase", + "full_command": "fx_tk_dri 0,0,0,1,0.5,1,1,0" + }, + { + "plain_name": "Equalize Local Histograms", + "full_command": "fx_equalize_local_histograms 75,2,4,100,8,1,0" + }, + { + "plain_name": "Freaky Details", + "full_command": "fx_freaky_details 2,10,1,7" + }, + { + "plain_name": "High Pass", + "full_command": "fx_highpass 5,2,0,0,0" + }, + { + "plain_name": "Local Normalization", + "full_command": "fx_normalize_local 2,6,5,20,1,12" + }, + { + "plain_name": "Local Processing", + "full_command": "fx_local_processing 0,75,10,50,20,0,0" + }, + { + "plain_name": "Local Variance Normalization", + "full_command": "jeje_normalize_local_variance 50,5,5,1,0,0" + }, + { + "plain_name": "Magic Details", + "full_command": "fx_magic_details 6,3,15,-0.5,2,12" + }, + { + "plain_name": "Mask Creator", + "full_command": "fx_tk_mask 0,0,0,255,0,1,0,0,1,0" + }, + { + "plain_name": "Mighty Details", + "full_command": "fx_mighty_details 25,1,25,1,12" + }, + { + "plain_name": "Portrait Retouching", + "full_command": "fx_tk_portrait 0,100,1,5,20,3,20,10,0,0,1,2,25,2,250,180,150,255,0,0,1,1.5,10,1,0,0,1,1,0,0" + }, + { + "plain_name": "Sharpen [Alpha]", + "full_command": "fx_sharpen_alpha 100,5,50,100,0" + }, + { + "plain_name": "Sharpen [Deblur]", + "full_command": "fx_deblur 2,10,20,0.1,1,0,0,24" + }, + { + "plain_name": "Sharpen [Gold-Meinel]", + "full_command": "fx_unsharp_goldmeinel 1,5,1,1,1,0,0,24" + }, + { + "plain_name": "Sharpen [Hessian]", + "full_command": "jeje_hessian_sharpen 3,1,1,0,0" + }, + { + "plain_name": "Sharpen [Inverse Diffusion]", + "full_command": "fx_sharpen_inversediff 50,2,0" + }, + { + "plain_name": "Sharpen [Multiscale]", + "full_command": "fx_sharpen_multiscale 15,20,0" + }, + { + "plain_name": "Sharpen [Octave Sharpening]", + "full_command": "fx_unsharp_octave 4,5,3,0,0,1,24" + }, + { + "plain_name": "Sharpen [Richardson-Lucy]", + "full_command": "fx_unsharp_richardsonlucy 1,10,1,1" + }, + { + "plain_name": "Sharpen [Shock Filters]", + "full_command": "fx_sharpen_shock 150,0.1,0.8,1.1,1,0" + }, + { + "plain_name": "Sharpen [Texture]", + "full_command": "fx_sharpen_texture 1,4,0" + }, + { + "plain_name": "Sharpen [Unsharp Mask]", + "full_command": "fx_unsharp 1,1.25,10,2,0,1,1,1,0,0" + }, + { + "plain_name": "Sharpen [Whiten]", + "full_command": "jeje_whiten_frequency 50,0,0" + }, + { + "plain_name": "Split Details [Alpha]", + "full_command": "fx_split_details_alpha 0,0,10,1,0" + }, + { + "plain_name": "Split Details [Gaussian]", + "full_command": "fx_split_details_gaussian 6,10,1,0" + }, + { + "plain_name": "Split Details [Wavelets]", + "full_command": "fx_split_details_wavelets 6,0,0" + }, + { + "plain_name": "Spotify", + "full_command": "jeje_spotify 1,1,1,1,12,0" + }, + { + "plain_name": "Tone Enhance", + "full_command": "gcd_tone_enhance 0,1,0,1,128,0,1,0.5,0,0,4,0,0" + }, + { + "plain_name": "Tone Mapping", + "full_command": "fx_map_tones 0.5,0.7,0.1,30,0" + }, + { + "plain_name": "Tone Mapping [Fast]", + "full_command": "fx_map_tones_fast 3,0.5,12" + }, + { + "plain_name": "Droste", + "full_command": "fx_droste 20,20,80,20,80,80,20,80,1,0,0,0,1,0,1,0,0" + }, + { + "plain_name": "Frame [Blur]", + "full_command": "fx_frame_blur 30,30,0,5,0,0,128,128,128,255,0,5,255,255,255,255,2,2,1,0,0.5,0.5,0" + }, + { + "plain_name": "Frame [Cube]", + "full_command": "fx_frame_cube 3,50,50,0,0,0,0" + }, + { + "plain_name": "Frame [Fuzzy]", + "full_command": "fx_frame_fuzzy 5,5,10,1,255,255,255,255" + }, + { + "plain_name": "Frame [Mirror]", + "full_command": "fx_frame_mirror 10,10,50,50,0,0,0,0,0.75" + }, + { + "plain_name": "Frame [Painting]", + "full_command": "fx_frame_painting 10,0.4,6,225,200,120,255,2,400,50,10,1,0.5,123456,0" + }, + { + "plain_name": "Frame [Pattern]", + "full_command": "fx_frame_pattern 10,1,1,1" + }, + { + "plain_name": "Frame [Regular]", + "full_command": "fx_frame 0,100,0,100,10,10,0,0,0,255,1,255,255,255,255" + }, + { + "plain_name": "Frame [Round]", + "full_command": "fx_frame_round 10,10,20,0.1,0,0,0,255,1" + }, + { + "plain_name": "Frame [Smooth]", + "full_command": "fx_frame_smooth 5,5,0.25" + }, + { + "plain_name": "Old Photograph", + "full_command": "fx_old_photo 200,50,85" + }, + { + "plain_name": "Polaroid", + "full_command": "fx_polaroid 10,20,0,0,3,0,0,20,50,70,95" + }, + { + "plain_name": "Tunnel", + "full_command": "fx_tunnel 4,80,50,50,0.2,0" + }, + { + "plain_name": "Vignette", + "full_command": "fx_vignette 70,70,95,0,0,0,255" + }, + { + "plain_name": "Bandpass", + "full_command": "fx_bandpass 0,100,0,2" + }, + { + "plain_name": "Fourier Analysis", + "full_command": "fx_display_fft" + }, + { + "plain_name": "Fourier Transform", + "full_command": "fx_fourier_transform 1" + }, + { + "plain_name": "Fourier Watermark", + "full_command": "fx_watermark_fourier \"(c) G'MIC\",53" + }, + { + "plain_name": "Align Layers", + "full_command": "fx_align_layers 0,0.7,0,0" + }, + { + "plain_name": "Blend [Average All]", + "full_command": "fx_blend_average_all 0" + }, + { + "plain_name": "Blend [Edges]", + "full_command": "fx_blend_edges 1,0.8,0" + }, + { + "plain_name": "Blend [Fade]", + "full_command": "fx_blend_fade 1,0,0,5,0,0,0,0,0,0,\"cos(4*pi*x/w) * sin(4*pi*y/h)\"" + }, + { + "plain_name": "Blend [Median]", + "full_command": "fx_blend_median 0" + }, + { + "plain_name": "Blend [Seamless]", + "full_command": "fx_blend_seamless 0,0,25,0,0" + }, + { + "plain_name": "Blend [Standard]", + "full_command": "fx_blend 6,0,100,1,\"1/2 - 1/4*cos(pi*a) - 1/4*cos(pi*b)\"" + }, + { + "plain_name": "Colors to Layers", + "full_command": "fx_split_colors 50,16,1,0" + }, + { + "plain_name": "Fade Layers", + "full_command": "fx_fade_layers 10" + }, + { + "plain_name": "Layers to Tiles", + "full_command": "append_tiles 0,0" + }, + { + "plain_name": "Morph Layers", + "full_command": "fx_morph_layers 10,0.2,0.1,0" + }, + { + "plain_name": "Multiscale Operator", + "full_command": "fx_apply_multiscale 4,25,100,0,3,0.5,0.5,0,0,0.5,0.5,0,\"\",0,0" + }, + { + "plain_name": "Pack", + "full_command": "fx_pack 2,1,1,0,16,1,0,\"\"" + }, + { + "plain_name": "Spatial Blend Multi-Layers", + "full_command": "fx_smbl 0,50,25,50,50,50,75,50,100,50,\"0,50\",\"100,50\",5,0" + }, + { + "plain_name": "Stroke", + "full_command": "fx_stroke 3,50,0,2,1,100,0,0,255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0,1,0" + }, + { + "plain_name": "Tiles to Layers", + "full_command": "fx_tiles2layers 3,3,0" + }, + { + "plain_name": "Tones to Layers", + "full_command": "fx_tones2layers 3,85,170,0.5,0" + }, + { + "plain_name": "Burn", + "full_command": "fx_burn 0.5,30,1,0,0" + }, + { + "plain_name": "Dodge and Burn", + "full_command": "fx_dodgeburn 15,1.5,25,10,40,1.5,25,10,0,0,10,0" + }, + { + "plain_name": "Drop Shadow", + "full_command": "fx_drop_shadow 3,3,1.8,0,0,0,0,0,255,1,1" + }, + { + "plain_name": "Drop Shadow 3D", + "full_command": "fx_drop_shadow3d 0,0,0,0,1,1,2,0.5,0,0,0,200,0" + }, + { + "plain_name": "Equalize Light", + "full_command": "fx_equalize_light 75,0,12" + }, + { + "plain_name": "Equalize Shadow", + "full_command": "fx_equalize_shadow 1" + }, + { + "plain_name": "Guided Light Rays", + "full_command": "fx_guided_lightrays 10,2,0,80,0.1,50,50,50,255,255,255,255,7,100,1" + }, + { + "plain_name": "Illuminate 2D Shape", + "full_command": "fx_illuminate_shape2d 0,0,255,0,0,255,1,1,4,0,0,3,1,0.5,0,10,75,30,40,40,80,0.2,1,0,0,2,-2,2,0,0,0" + }, + { + "plain_name": "Light Glow", + "full_command": "fx_lightglow 30,0.5,8,0.8,12" + }, + { + "plain_name": "Light Leaks", + "full_command": "fx_light_leaks 0,0,1,1,0,85,2,1" + }, + { + "plain_name": "Light Patch", + "full_command": "fx_light_patch 5,0.7,2.5,12" + }, + { + "plain_name": "Light Rays", + "full_command": "fx_lightrays 30,50,50,1,0.5,0,255,255,255,255" + }, + { + "plain_name": "Pop Shadows", + "full_command": "fx_pop_shadows 0.75,5,1" + }, + { + "plain_name": "Relief Light", + "full_command": "fx_light_relief 0.3,0.2,0.2,0,1,50,50,5,0.5,0,0" + }, + { + "plain_name": "Shadow Patch", + "full_command": "fx_shadow_patch 0.7,0" + }, + { + "plain_name": "Slice Luminosity", + "full_command": "fx_slice_luminosity 1,1,2,1,0,64,0,0,1,64,128,0,0,0,128,192,0,0,0,192,255,0,0" + }, + { + "plain_name": "Albers Equal Area Conic", + "full_command": "albers_projection 0,0,0,0,0,20,60,180,360" + }, + { + "plain_name": "Azimuthal Equidistant", + "full_command": "azimuthal_equidistant_projection 0,0,0,0,0,180" + }, + { + "plain_name": "Conic Equidistant", + "full_command": "conic_equidistant_projection 0,0,0,0,0,20,60" + }, + { + "plain_name": "Cylindrical Equal-Area Projection", + "full_command": "cylindrical_equal_area 0,0,0,45,0,\"acos(sqrt(1/pi))\"" + }, + { + "plain_name": "Eckert IV", + "full_command": "eckert_iv_projection 0,0,0,0" + }, + { + "plain_name": "Eckert VI", + "full_command": "eckert_vi_projection 0,0,0,0" + }, + { + "plain_name": "Lambert Azimuthal Equal-Area", + "full_command": "lambert_azimuthal_projection 0,0,0,0,0,180" + }, + { + "plain_name": "Lambert Conformal Conic", + "full_command": "lambert_conformal_conic_projection 0,0,0,0,0,20,60,180,360" + }, + { + "plain_name": "Mercator Projection", + "full_command": "mercator 0,0,0,0,85" + }, + { + "plain_name": "Mollweide", + "full_command": "mollweide_projection 0,0,0,0,0" + }, + { + "plain_name": "Orthographic", + "full_command": "orthographic_projection 0,0,0,0,0" + }, + { + "plain_name": "Rotate Equirectangular Map", + "full_command": "rotate_equirectangular_map 0,0,0,0" + }, + { + "plain_name": "Sinusoidal Map", + "full_command": "sinusoidal_map 0,0,0,128,128,128,255,100,1" + }, + { + "plain_name": "Triangular Projection", + "full_command": "triangular_projection 0,0,0,128,128,128,255,100,1,50" + }, + { + "plain_name": "Bayer Filter", + "full_command": "rgb2bayer 0,1" + }, + { + "plain_name": "Box Fitting", + "full_command": "fx_boxfitting 3,0,0.25,2,0" + }, + { + "plain_name": "Camouflage", + "full_command": "fx_camouflage 9,12,100,30,46,33,255,75,90,65,255,179,189,117,255,255,246,158,255" + }, + { + "plain_name": "Canvas", + "full_command": "fx_canvas 70,45,400,1,70,135,400" + }, + { + "plain_name": "Canvas Texture", + "full_command": "texturize_canvas 20,3,0.6" + }, + { + "plain_name": "Clouds", + "full_command": "jeje_clouds 50,0.5" + }, + { + "plain_name": "Cracks", + "full_command": "fx_cracks 30,1,255,255,255,128,0" + }, + { + "plain_name": "Crystal", + "full_command": "fx_crystal 50,0.2,20,1" + }, + { + "plain_name": "Crystal Background", + "full_command": "fx_crystal_background 10,25,0,100,1" + }, + { + "plain_name": "Fibers", + "full_command": "jeje_fibers 10,50,10,0" + }, + { + "plain_name": "Freqy Pattern", + "full_command": "jeje_freqy_pattern 50,33,50,0" + }, + { + "plain_name": "Halftone", + "full_command": "fx_halftone 0,0,0,0,5,8,8,0,0.1" + }, + { + "plain_name": "Halftone [Generic]", + "full_command": "fx_generic_halftone 0,1,100,10,1,0,0,0,75,1,0,\"-1\"" + }, + { + "plain_name": "Hearts", + "full_command": "fx_hearts 2,0" + }, + { + "plain_name": "Lava", + "full_command": "fx_lava 8,5,3,0" + }, + { + "plain_name": "Marble", + "full_command": "fx_marble 0.5,1,0,0,0.4,0.6,0.6,1.1,0,100" + }, + { + "plain_name": "Maze", + "full_command": "fx_maze 24,1,0,1,0" + }, + { + "plain_name": "Mineral Mosaic", + "full_command": "fx_mineral_mosaic 1,2,1,100,0" + }, + { + "plain_name": "Mosaic", + "full_command": "fx_mosaic 50,0" + }, + { + "plain_name": "Op Art", + "full_command": "fx_shapes 0,16,10,2,5,90,0,0,1,1,0" + }, + { + "plain_name": "Organic Fibers", + "full_command": "fx_organic_fibers 20,20,3,15,15,3,15,30,1,19,10,24,50,0,33" + }, + { + "plain_name": "Pack Ellipses", + "full_command": "fx_pack_ellipses 3,20,0,30,100,6,0,3,0,0,0,255,0,0" + }, + { + "plain_name": "Pack Sprites", + "full_command": "fx_pack_sprites 5,25,3,1,5,0,512,512" + }, + { + "plain_name": "Paper Texture", + "full_command": "fx_paper 0" + }, + { + "plain_name": "Periodic Dots", + "full_command": "jeje_periodic_dots 6,4,0,1,0" + }, + { + "plain_name": "Pills", + "full_command": "fx_pills 0,4,0,4,0,4,0,4,0" + }, + { + "plain_name": "Plaid", + "full_command": "fx_plaid_texture 50,2,0,90,1,300" + }, + { + "plain_name": "Polka Dots", + "full_command": "fx_polka_dots 80,20,50,50,0,0.5,0.1,1,255,0,0,255" + }, + { + "plain_name": "Random Color Ellipses", + "full_command": "fx_color_ellipses 400,8,0.1" + }, + { + "plain_name": "Random Pattern", + "full_command": "fx_random_pattern 1024,2,4038,0,0,0,0,0,0" + }, + { + "plain_name": "Random Rectangles", + "full_command": "fx_random_rectangles 10,100,0,0,0,0,255" + }, + { + "plain_name": "Rays", + "full_command": "jeje_rays 50,50,10,0,0.5,255,0,0,255,255,255,0,255,0" + }, + { + "plain_name": "Reaction-Diffusion", + "full_command": "fx_reaction_diffusion 5,5,0" + }, + { + "plain_name": "Resynthetize Texture [FFT]", + "full_command": "syntexturize 1024,1024,0,0,50,50" + }, + { + "plain_name": "Resynthetize Texture [Patch-Based]", + "full_command": "syntexturize_matchpatch 512,512,0,7,5,1,0,0,50,50" + }, + { + "plain_name": "Rorschach", + "full_command": "fx_rorschach 3,1,2" + }, + { + "plain_name": "Satin", + "full_command": "fx_satin 20,1,0,0,0,0,255,255,255,255,255,0,0,0,-50,0,0" + }, + { + "plain_name": "Seamless Turbulence", + "full_command": "fx_seamless_turbulence 15,20,0,1,3,0" + }, + { + "plain_name": "Shock Waves", + "full_command": "fx_shockwaves 10,10,20,0" + }, + { + "plain_name": "Sponge", + "full_command": "fx_sponge 13,0" + }, + { + "plain_name": "Stained Glass", + "full_command": "fx_stained_glass 40,0.1,0,1,1,0,0,0" + }, + { + "plain_name": "Stars", + "full_command": "fx_stars 10,0,32,5,0.38,0,255,255,100,200" + }, + { + "plain_name": "Stencil", + "full_command": "fx_stencil 3,0,8,0,2,0" + }, + { + "plain_name": "Strip", + "full_command": "jeje_strip 45,50,0,1,0" + }, + { + "plain_name": "Stripes", + "full_command": "fx_stripes 0,1,1,0,1,0,0,0,0,255,32,255,255,0,255,32,255,0,0,255,32,0,196,0,255,32,0,128,196,255,32,128,0,196,255" + }, + { + "plain_name": "Tetris", + "full_command": "fx_tetris 10" + }, + { + "plain_name": "Triangular Pattern", + "full_command": "fx_triangular_pattern 43,7,4,4,4,0,0,0,100,0,0,0,160,1" + }, + { + "plain_name": "Truchet", + "full_command": "fx_truchet 32,5,1,1,0" + }, + { + "plain_name": "Turing", + "full_command": "jeje_turing_pattern 1,2000,0.1,0.899,-0.91,2,0.1,0.25" + }, + { + "plain_name": "Voronoi", + "full_command": "fx_voronoi 160,1,0.5,50,3,1,0,0,0,100,2,255,255,255,40,0" + }, + { + "plain_name": "Weave", + "full_command": "weave 6,65,0,0.5,0,0,0,0,0" + }, + { + "plain_name": "Whirl Drawing", + "full_command": "fx_draw_whirl 20" + }, + { + "plain_name": "Whirls", + "full_command": "fx_whirls 7,2,0.2,1.8,0" + }, + { + "plain_name": "2.5D Extrusion", + "full_command": "fx_extrude25d 10,80,60,25,0,10,50,255,200,0,255,255,128,0,255,128,64,0,255,64,0,0,255" + }, + { + "plain_name": "3D Blocks", + "full_command": "fx_blocks3d 32,0,4,1.5,30,60,45,50,50,0,-50,-100,0.5,0.7,1,1,0,0,0,128" + }, + { + "plain_name": "3D Colored Object", + "full_command": "fx_coloredobject3d 1,128,128,128,255,0.5,0.5,0.5,57,41,21,45,0,0,-100,0.5,0.7,4,1" + }, + { + "plain_name": "3D Elevation", + "full_command": "fx_elevation3d 100,1,1024,1024,0.8,25,0,21,45,0,0,-100,0.5,0.7,2,1,0" + }, + { + "plain_name": "3D Extrusion", + "full_command": "fx_extrude3d 10,512,0.6,1024,1024,0.5,57,41,21,45,0,0,-100,0.5,0.7,4,1,0" + }, + { + "plain_name": "3D Image Object", + "full_command": "fx_imageobject3d 1,1024,1024,0.5,57,41,21,45,0,0,-100,0.5,0.7,4,1" + }, + { + "plain_name": "3D Lathing", + "full_command": "fx_lathing3d 76,2,361,1024,1024,0.5,0,0,0,45,0,0,-100,0.5,0.7,4,1,0" + }, + { + "plain_name": "3D Mesh", + "full_command": "fx_mesh3d \"\",\"0\",80,50,50,70,60,60,50,50,\"-1\",\"-1\",0,0,0,5,0,2,200,200,200,255,100,1,50,50,0" + }, + { + "plain_name": "3D Random Objects", + "full_command": "fx_random3d 0,50,3,100,45,0,0,-100,0.5,0.7,3,1" + }, + { + "plain_name": "Algorithm A", + "full_command": "fx_memoakten_algorithm_a 0,20,60,30,2,50,10,50,40,3,60,1,0,0,0,255,255,255,255,255,255,0,0,255,255,128,0,255,255,255,0,255,0,0,0,255" + }, + { + "plain_name": "Ball", + "full_command": "fx_ball 200,255,0,255,255,0.25,1,1,20,85,15" + }, + { + "plain_name": "Circle Art", + "full_command": "fx_circle_art 1,15,0.5,8,1,1,15,0,0,0.5,1,1,1,1" + }, + { + "plain_name": "Equation Plot [Parametric]", + "full_command": "fx_equation_parametric \"sin(t)*(exp(cos(t))-2*cos(4*t)-sin(t/12)^5)\",\"cos(t)*(exp(cos(t))-2*cos(4*t)-sin(t/12)^5)\",0,100,4096,1,0,64,0,0,255,128,0,0,255,1,1,1" + }, + { + "plain_name": "Equation Plot [Y=f(X)]", + "full_command": "fx_equation_plot \"X*c+10*cos(X+c+u)\",-10,10,100,3,2,0" + }, + { + "plain_name": "Generate Random Portrait", + "full_command": "fx_generate_random_portrait 800,0" + }, + { + "plain_name": "Gradient [Corners]", + "full_command": "fx_corner_gradient 255,255,255,128,255,0,0,255,0,255,0,255,0,0,255,255,0,1" + }, + { + "plain_name": "Gradient [Custom Shape]", + "full_command": "fx_custom_gradient 0,0,0,1,4,1,0,128,100,100,2,0,1,0,\"\",1,0,0,0,0,255,255,0,0,255,255,255,0,255,255,255,255,255,0,255,255,255,0,255,0,255,0,0,255,255,128,128,128,255,255,0,255,255,0,0,0,0" + }, + { + "plain_name": "Gradient [from Curve]", + "full_command": "fx_gradient_from_curve 2,0,0,20,20,40,40,60,60,80,80,100,100,100,0,0,0,1,\"\"" + }, + { + "plain_name": "Gradient [Linear]", + "full_command": "fx_linear_gradient 0,0,0,255,255,255,255,255,0,45,0,100,0,0" + }, + { + "plain_name": "Gradient [Poles]", + "full_command": "fx_gradient_poles 0,0,0,25,25,0,0,0,255,75,25,0,0,255,255,75,75,0,255,0,255,25,75,0,255,255,255,50,50,255,0,0,255,10,50,255,0,255,255,20,50,255,255,0,255,30,50,255,255,255,255" + }, + { + "plain_name": "Gradient [Radial]", + "full_command": "fx_radial_gradient 0,0,0,255,255,255,255,255,0,0,100,0,50,50,0" + }, + { + "plain_name": "Gradient [Random]", + "full_command": "fx_random_gradient 32,0,0,0,128,128,128,255,1" + }, + { + "plain_name": "Hypotrochoid", + "full_command": "fx_hypotrochoid 37,100,74,80,0.5,255,255,255,255,1" + }, + { + "plain_name": "Lightning", + "full_command": "fx_lightning 20,90,256,3,1.5,0.75,255,255,255,255,0,50,5,0,6,0.2,25,60,95,100,30,40,-0.25,-0.1,-0.2" + }, + { + "plain_name": "Lissajous", + "full_command": "fx_lissajous 4096,0.9,0.9,3,8,7,0,0,0,0,0,0,0,4,255,255,255,255" + }, + { + "plain_name": "Mandelbrot - Julia Sets", + "full_command": "fx_mandelbrot \"-2\",\"-2\",\"2\",\"2\",0,1024,0.317,0.03,16,8,255,50,50,0.75,0,0,0,0" + }, + { + "plain_name": "Neon Lightning", + "full_command": "fx_neon_lightning 50,50,0,50,50,100,50,0.7,3,130,80,50,255,0.25,0" + }, + { + "plain_name": "Newton Fractal", + "full_command": "fx_newton_fractal \"-2\",\"-2\",\"2\",\"2\",2,\"rot(35°)*z^^3 - z^^2 + 1\",\"3*z^^2 - 2*z\",\"6*z - 2\",1,200,2,1,16,8,255,2,100,150,20,400,3,2,\"carg(-z)\",\"(i0 + i1)/2\",\"10*(i2^0.4)\",0,0,0,0,0,0,0,2,\"0\",50,50,0.5,0,0,0,0,0,1,2" + }, + { + "plain_name": "Pixel Stretch", + "full_command": "fx_pixel_stretch 0,3,80,20,-1,-1,80,10,80,30,60,30,-1,-1,50,30,70,30,60,50,-1,-1,50,50,70,50,40,70,-1,-1,30,70,50,70,60,80,-1,-1,50,80,70,80,30,99,-1,-1,20,99,40,99,1,1,1,25,75,75,75,100" + }, + { + "plain_name": "Plasma", + "full_command": "fx_plasma 0.5,0,8,0,0,128,128,128,255" + }, + { + "plain_name": "Quick Copyright", + "full_command": "fx_quick_copyright \"\\\\251 John Doe\",24,10,0,255,255,255,255,90,3,0,0,0,255,4,1,1,-180" + }, + { + "plain_name": "Rainbow", + "full_command": "fx_rainbow 80,80,175,175,3,80" + }, + { + "plain_name": "Random Signature", + "full_command": "fx_random_signature 16,16,10,10,90,90,1.5,0,75,0,0,0,255,1,0" + }, + { + "plain_name": "Shade Bobs", + "full_command": "fx_shadebobs 50,5,200,1,-1,2,1,0.8,0,8" + }, + { + "plain_name": "Sine Curve", + "full_command": "fx_sine_curve 0,\"-1\",75,1,1,0.5,0.5,0.5,1,1,0,800,800,1,90,0,0,90,0,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,8,50,50,\"50\",\"50\",68,68,75,50,\"75\",\"50\",3,2,40,255,255,255,255,2,1" + }, + { + "plain_name": "Speech Bubble", + "full_command": "fx_speech_bubble \"50,50\",50,50,80,50,50,30,\"30,70\",30,70,\"38,70\",38,70,45,80,30,75,38,75,25,1,1,0,1.5,3,2,255,255,255,255,0,0,0,255" + }, + { + "plain_name": "Spline Spirograph", + "full_command": "fx_spline_spirograph 0,0,50,100,20,3,50,0,3,0,0,50,50,1" + }, + { + "plain_name": "Superformula", + "full_command": "fx_superformula 4096,0.9,0.9,8,1,5,8,0,0,0,3,128,255,128,255" + }, + { + "plain_name": "Symmetric 2D Shape", + "full_command": "fx_symmetric_shape2d 5,50,50,\"50,50\",50,30,\"50,30\",50,25,56,42,52,52,52,52,52,52,52,52,1,255,0,255,255,100" + }, + { + "plain_name": "Tree", + "full_command": "fx_tree 11,10000,0,0,15,150,0,2.15,0.8,-40,40,10,75,0,70,20,40,25,0,255,100,70,140,60,255,100,0.4,0.4" + }, + { + "plain_name": "Turbulence", + "full_command": "fx_turbulence 128,6,4,0,0" + }, + { + "plain_name": "Twisted Rays", + "full_command": "fx_twisted_rays 50,50,9,50,50,25,255,255,255,255,1" + }, + { + "plain_name": "Bayer Reconstruction", + "full_command": "bayer2rgb 6,6,4" + }, + { + "plain_name": "Deinterlace", + "full_command": "deinterlace 0" + }, + { + "plain_name": "Deinterlace2x", + "full_command": "gcd_deinterlace2x 40,0,0,2,0,1" + }, + { + "plain_name": "Denoise [CNN]", + "full_command": "fx_denoise 1,50,100,1,1,0" + }, + { + "plain_name": "Despeckle", + "full_command": "gcd_despeckle 20,10" + }, + { + "plain_name": "Inpaint [Holes]", + "full_command": "fx_inpaint_holes 4,20,1" + }, + { + "plain_name": "Inpaint [Morphological]", + "full_command": "fx_inpaint_morpho 255,0,0,255,0" + }, + { + "plain_name": "Inpaint [Multi-Scale]", + "full_command": "fx_inpaint_matchpatch 0,9,10,5,1,255,0,0,255,0,0" + }, + { + "plain_name": "Inpaint [Patch-Based]", + "full_command": "fx_inpaint_patch 7,16,0.1,1.2,0,0.05,10,1,255,0,0,255,0,0" + }, + { + "plain_name": "Inpaint [Transport-Diffusion]", + "full_command": "fx_inpaint_pde 75,1,20,255,0,0,255,0" + }, + { + "plain_name": "Red-Eye Attenuation", + "full_command": "red_eye 75,3.5,0.1" + }, + { + "plain_name": "Remove Hot Pixels", + "full_command": "remove_hotpixels 3,10" + }, + { + "plain_name": "Repair Scanned Document", + "full_command": "jeje_scandoc 3,1,90,5,0" + }, + { + "plain_name": "Smooth [Anisotropic]", + "full_command": "fx_smooth_anisotropic 60,0.7,0.3,0.6,1.1,0.8,30,2,0,1,1,0" + }, + { + "plain_name": "Smooth [Antialias]", + "full_command": "fx_smooth_antialias 5,10,0.8" + }, + { + "plain_name": "Smooth [Bilateral]", + "full_command": "fx_smooth_bilateral 10,7,2,0" + }, + { + "plain_name": "Smooth [Block PCA]", + "full_command": "jeje_denoise_patch_dict 1,8,1.1,1.1,0,0" + }, + { + "plain_name": "Smooth [Diffusion]", + "full_command": "fx_smooth_diffusion 0.7,0.3,0.6,1.1,15,8,0,0,24" + }, + { + "plain_name": "Smooth [Guided]", + "full_command": "fx_smooth_guided 0,5,30,1,0,0,50,50" + }, + { + "plain_name": "Smooth [IUWT]", + "full_command": "jeje_denoise_iuwt 3,4,2,0" + }, + { + "plain_name": "Smooth [Mean-Curvature]", + "full_command": "fx_smooth_meancurvature 30,4,0,0,0,24" + }, + { + "plain_name": "Smooth [Median]", + "full_command": "fx_smooth_median 3,255,0" + }, + { + "plain_name": "Smooth [NL-Means]", + "full_command": "fx_smooth_nlmeans 4,4,10,3,0,0,24" + }, + { + "plain_name": "Smooth [Patch-Based]", + "full_command": "fx_smooth_patch 10,10,3,5,0,1,1,0,0,24" + }, + { + "plain_name": "Smooth [Patch-PCA]", + "full_command": "fx_smooth_patchpca 4,7,11,7,0" + }, + { + "plain_name": "Smooth [Perona-Malik]", + "full_command": "fx_smooth_peronamalik 20,5,5,0,0,0,24" + }, + { + "plain_name": "Smooth [Selective Gaussian]", + "full_command": "fx_smooth_selective 5,0.5,5,1,0,0,24" + }, + { + "plain_name": "Smooth [Skin]", + "full_command": "fx_smooth_skin 2,0.5,1,1,1,50,50,5,2,0.2,3,1,0.05,0,0,50,50" + }, + { + "plain_name": "Smooth [Thin Brush]", + "full_command": "fx_smooth_anisotropic 60,0.9,0.64,3.1,1.1,0.8,30,2,0,1,1,0,0,24" + }, + { + "plain_name": "Smooth [Total Variation]", + "full_command": "fx_smooth_tv 30,10,0,0,0,24" + }, + { + "plain_name": "Smooth [Wavelets]", + "full_command": "fx_smooth_haar 1,10,10,0,0,24" + }, + { + "plain_name": "Smooth [Wiener]", + "full_command": "jeje_local_wiener 2,11,0,0" + }, + { + "plain_name": "Solidify", + "full_command": "fx_solidify_td 75,1,20,0,1" + }, + { + "plain_name": "Unstrip", + "full_command": "jeje_unstrip 1,20,4,1,0,0" + }, + { + "plain_name": "Upscale [CNN2x]", + "full_command": "fx_scale2x_cnn 1.25,0" + }, + { + "plain_name": "Upscale [DCCI2x]", + "full_command": "fx_scale_dcci2x 1.15,5,0" + }, + { + "plain_name": "Upscale [Diffusion]", + "full_command": "fx_upscale_smart \"200%\",\"200%\",2,0.4,50" + }, + { + "plain_name": "Upscale [Scale2x]", + "full_command": "fx_scalenx 0,0" + }, + { + "plain_name": "3D Elevation [Animated]", + "full_command": "fx_animate_elevation3d 10,1,0,\"\",100,1,1024,1024,2,0.8,35,0,0,45,0,0,-100,0.5,0.7,0.8,35,0,360,45,0,0,-100,0.5,0.7" + }, + { + "plain_name": "3D Extrusion [Animated]", + "full_command": "fx_animate_extrude3d 10,1,0,\"\",10,512,0.6,1024,1024,4,0.8,35,0,0,45,0,0,-100,0.5,0.7,0.8,35,360,0,45,0,0,-100,0.5,0.7" + }, + { + "plain_name": "3D Image Object [Animated]", + "full_command": "fx_animate_imageobject3d 10,1,0,\"\",1,1024,1024,4,0.5,57,41,21,45,0,0,-100,0.5,0.7,0.5,57,401,21,45,0,0,-100,0.5,0.7" + }, + { + "plain_name": "3D Text Pointcloud", + "full_command": "fx_text_pointcloud3d 64,\"G'MIC\",\"Rocks!\",1,200,220,255,255,255,255,255,255,2,2,1,19" + }, + { + "plain_name": "3D Tiles", + "full_command": "fx_transition3d 10,8,8,\"1\",\"1\",\"0\",800,1" + }, + { + "plain_name": "B&W Pencil [Animated]", + "full_command": "fx_animate_pencilbw 10,1,0,\"\",2.3,100,0.3,60" + }, + { + "plain_name": "B&W Stencil [Animated]", + "full_command": "fx_animate_stencilbw 10,1,0,\"\",10,10,10,20" + }, + { + "plain_name": "Cartoon [Animated]", + "full_command": "fx_animate_cartoon 10,1,0,\"\",4,0.5,200,10,0.1,1.5,3,200,10,0.1,1.5" + }, + { + "plain_name": "Edges [Animated]", + "full_command": "fx_animate_edges 10,1,0,\"\",0,0,10,0,30" + }, + { + "plain_name": "Edges on Fire", + "full_command": "fx_fire_edges 0.7,0.25,0.5,25,20,20,0,0,50,50" + }, + { + "plain_name": "Lava Lamp", + "full_command": "fx_lavalampbw 3,30,1,20,2,0.01,0" + }, + { + "plain_name": "Lissajous [Animated]", + "full_command": "fx_animate_lissajous 10,1,0,\"\",4096,0.9,0.9,3,8,7,0,0,0,0,0,0,0,0,255,255,255,255,4096,0.9,0.9,3,8,7,0,0,0,0,0,0,0,0,255,255,255,255" + }, + { + "plain_name": "Moiré Animation", + "full_command": "fx_moire 1,0,0,1,1,2,1,5" + }, + { + "plain_name": "Object Animation", + "full_command": "fx_tk_animateobject 0,0,0,0.5,0.5,400,2,0,0,0,0,0,1,0,0,1" + }, + { + "plain_name": "Rodilius [Animated]", + "full_command": "fx_animate_rodilius 10,1,0,\"\",1,10,10,300,5,0,10,10,300,5,180" + }, + { + "plain_name": "Soft Glow [Animated]", + "full_command": "fx_animate_glow 10,1,0,\"\",0,3" + }, + { + "plain_name": "Spatial Transition", + "full_command": "fx_spatial_transition 10,0,7,\"cos(x*y/(16+32*A))\",0,1,0.5,\"0\"" + }, + { + "plain_name": "Dragonfly", + "full_command": "mc_dragonfly 50,0,255,255,255,255,1" + }, + { + "plain_name": "Kookaburra", + "full_command": "mc_kookaburra 50,0,255,255,255,255,1" + }, + { + "plain_name": "Paw", + "full_command": "mc_paw 50,0,255,255,255,255,1" + }, + { + "plain_name": "Rooster", + "full_command": "mc_rooster 50,0,255,255,255,255,1" + }, + { + "plain_name": "Flip", + "full_command": "mc_flip 50,0,255,255,255,255,1" + }, + { + "plain_name": "Information", + "full_command": "mc_information 50,0,255,255,255,255,1" + }, + { + "plain_name": "Mail", + "full_command": "mc_mail 50,0,255,255,255,255,1" + }, + { + "plain_name": "Phone", + "full_command": "mc_phone 50,0,255,255,255,255,1" + }, + { + "plain_name": "Shopping Cart", + "full_command": "mc_shopping_cart 50,0,255,255,255,255,1" + }, + { + "plain_name": "Barbed Wire", + "full_command": "mc_barbed_wire 50,0,255,255,255,255,1" + }, + { + "plain_name": "Crosshair", + "full_command": "mc_crosshair 50,0,255,255,255,255,1" + }, + { + "plain_name": "Cupid", + "full_command": "fx_cupid 75,0,255,255,255,255,1" + }, + { + "plain_name": "Gear", + "full_command": "fx_gear 75,12,15,0,40,0,255,255,255,255,1" + }, + { + "plain_name": "Heart", + "full_command": "fx_heart 75,0,255,255,255,255,1" + }, + { + "plain_name": "Paint Splat", + "full_command": "mc_paint_splat 50,0,255,255,255,255,1" + }, + { + "plain_name": "Sierpinski Triangle", + "full_command": "fx_sierpinski 6,50,0,0,100,100,100,255,255,255,255,1" + }, + { + "plain_name": "Australia", + "full_command": "mc_australia 50,0,255,255,255,255,1" + }, + { + "plain_name": "Barnsley Fern", + "full_command": "fx_barnsley_fern 0,100,30,40,10,178,0,255,1" + }, + { + "plain_name": "Gum Leaf", + "full_command": "mc_gum_leaf 50,0,255,255,255,255,1" + }, + { + "plain_name": "Japanese Maple Leaf", + "full_command": "mc_maple_leaf 50,0,255,255,255,255,1" + }, + { + "plain_name": "Snowflake", + "full_command": "fx_snowflake 5,1,255,255,255,255" + }, + { + "plain_name": "Dragon Curve", + "full_command": "fx_dragoncurve 20,0,1,255,255,255,255" + }, + { + "plain_name": "3D Conversion", + "full_command": "fx_tk_make3D 0,20,0,20,0,0,0,0,0,0,0,0,0,1.2,25,1,0,1,0,0,0,2,200" + }, + { + "plain_name": "3D Video Conversion", + "full_command": "fx_tk_video3D 0,10,-10,20,0,0,0,0,0,0,0,0,0,0,\"\",1.2,25,1,0,1,1,1280,1,0,0,0,\"\",\"frame_\",0,1,0,0,\"#old movie\\n#luminance fx_stripes_y 10,3,0 sepia \\n\\n#simple vintage\\n#+fc 0,15,125 rv fx_compose_exclusion 0.3 \\n\\n#HDR popout\\n#fx_map_tones_fast 2,0.3,3,2 fx_unsharp_octave 4,5,3,0,0,0\",0,0,1,5,0,0,0,1,0,0" + }, + { + "plain_name": "Automatic Depth Estimation", + "full_command": "fx_tk_autodepth" + }, + { + "plain_name": "De-Anaglyph", + "full_command": "fx_tk_deana 20,2" + }, + { + "plain_name": "Depth Map Construction", + "full_command": "fx_tk_depthmap 0,20,0,0,0,0,0,0,0,0" + }, + { + "plain_name": "Depth Map Reconstruction", + "full_command": "fx_tk_depth_obtain 0,0.1,100,0" + }, + { + "plain_name": "Lenticular Print", + "full_command": "fx_tk_lenticular 30,0,5,0,1,0" + }, + { + "plain_name": "Single Image Stereogram", + "full_command": "fx_tk_stereogram 50,0.5,10,0,40,255,255,0,255,255,0,0,255,0,255,0,255,0,0,255,255,0.5,0" + }, + { + "plain_name": "Stereo Image", + "full_command": "gcd_stereo_img 0,0.5,1.2,1,0.25,2,4,1,0" + }, + { + "plain_name": "Stereoscopic Image Alignment", + "full_command": "fx_tk_stereoimage 0,0,1,0,1,0" + }, + { + "plain_name": "Undo Anaglyph", + "full_command": "gcd_unstereo 5,0.1,1,1,1,1,0" + }, + { + "plain_name": "Brightness", + "full_command": "afre_brightness 50,0" + }, + { + "plain_name": "Contrast", + "full_command": "afre_contrast 50,0" + }, + { + "plain_name": "Dark Sky", + "full_command": "afre_darksky 0,0,1,0" + }, + { + "plain_name": "Local Contrast", + "full_command": "afre_localcontrast 1,50" + }, + { + "plain_name": "Softlight", + "full_command": "afre_softlight 50,0" + }, + { + "plain_name": "Edge", + "full_command": "afre_edge 0,1,1,1,1" + }, + { + "plain_name": "Contrast FFT", + "full_command": "afre_contrastfft 75,50,1" + }, + { + "plain_name": "Denoise [afre]", + "full_command": "afre_denoise 1" + }, + { + "plain_name": "Details", + "full_command": "afre_details 2" + }, + { + "plain_name": "Texture", + "full_command": "afre_texture 0,0,0" + }, + { + "plain_name": "Gamify", + "full_command": "fx_gamify 50,2,1,1,0" + }, + { + "plain_name": "Gleam", + "full_command": "afre_gleam 3,50" + }, + { + "plain_name": "Half & Half", + "full_command": "afre_halfhalf 0" + }, + { + "plain_name": "Hessian Norm", + "full_command": "fx_hnorm 1,50,0" + }, + { + "plain_name": "Montage X", + "full_command": "afre_montagex 5,1,230,255,230,255" + }, + { + "plain_name": "Portrait Montage", + "full_command": "afre_portraitmontage 1,1,0,230,255,230,255" + }, + { + "plain_name": "Query Primary", + "full_command": "afre_queryprimary 1,1" + }, + { + "plain_name": "Clean Text", + "full_command": "afre_cleantext 8,1,80,95" + }, + { + "plain_name": "Denoise Smooth", + "full_command": "afre_denoisesmooth 3,10" + }, + { + "plain_name": "Denoise Smooth Alt", + "full_command": "afre_denoisesmooth_alt 3,10" + }, + { + "plain_name": "Sharpen FFT", + "full_command": "afre_sharpenfft 15,1" + }, + { + "plain_name": "Vigcirc", + "full_command": "afre_vigcirc 90,75,50,50" + }, + { + "plain_name": "Vigrect", + "full_command": "afre_vigrect 50,75,10,50,50" + }, + { + "plain_name": "Descreen", + "full_command": "fx_pahlsson_descreen 7,40,1,0" + }, + { + "plain_name": "Remove Scratches", + "full_command": "fx_remove_scratches 72,2,4,3,0" + }, + { + "plain_name": "Comicbook", + "full_command": "cl_comic 0,2,0,1,1,15,15,1,10,20,6,2,0,0,0,0,0,0,50,50" + }, + { + "plain_name": "Lineart", + "full_command": "cl_lineart 0,0,2,1,15,15,1,0,6,2,2,0,0,0,50,50" + }, + { + "plain_name": "Frame [Relief]", + "full_command": "cl_reliefFrame 2,10,1.5,75,1,60,0,0,0,0,192,192,192,255,0,0,0" + }, + { + "plain_name": "Color Wheel", + "full_command": "cl_colorWheel 200,80,0,0,0,0" + }, + { + "plain_name": "Equation Plot [Implicit]", + "full_command": "cl_implicitEqua \"( x^2 + y^2 - 25 ) * ( (x-2)^2 + (y-2)^2 - 1 ) * ( (x+2)^2 + (y-2)^2 - 1 ) * ( abs(x) + abs(y) - 1 ) * ( x^2 + (4*y+12-x^2)^2 - 9 )\",500,500,-6,6,-6,6,0,0,1" + }, + { + "plain_name": "Neon Carpet", + "full_command": "cl_neonCarpet 0,0,0" + }, + { + "plain_name": "Tangential Circles", + "full_command": "cl_tangentialCircle 1,100,0,1,5,1,255,255,255,255,0,0,0,255,0" + }, + { + "plain_name": "Corvo's Painting 5", + "full_command": "fx_corvo_painting_5 35,10,10,0.5,50,0.3,50,2,5,1" + }, + { + "plain_name": "Anti Alias", + "full_command": "gcd_anti_alias 60,0.3,50,0" + }, + { + "plain_name": "Aspect Adjustment", + "full_command": "fx_gcd_adjust_aspect 6,1,0" + }, + { + "plain_name": "Auto Balance", + "full_command": "gcd_auto_balance 30,0,0,1,0" + }, + { + "plain_name": "Blend [Feather]", + "full_command": "gcd_blend_feather 100,0.5,2,0,0" + }, + { + "plain_name": "Blend [Multiscale]", + "full_command": "fx_gcd_blend_multiscale 5" + }, + { + "plain_name": "Canny Edge Detection", + "full_command": "fx_gcd_canny 1,0.05,0.15" + }, + { + "plain_name": "Colored Signum", + "full_command": "fx_gcd_signum_color 0.1,5,2,0" + }, + { + "plain_name": "Compression Blur", + "full_command": "gcd_comp_blur 2,3,1,100,1,0,0" + }, + { + "plain_name": "CRMT Tiles", + "full_command": "fx_gcd_crmt_tile \"t_w=[w] t_h=[round(1/2*sqrt(3)*$t_w)]\",\"[3*$t_w,2*$t_h]\",\"C0 T0 C0 Fo R-60 T[-1/2*$t_w,0]\",0" + }, + { + "plain_name": "Cumulative Math", + "full_command": "fx_gcd_cumul_math 0,1,1,0,0" + }, + { + "plain_name": "Deblur Texture", + "full_command": "fx_gcd_blur_deblur_texture 4,1,0.5,0,2,0,0,50,50" + }, + { + "plain_name": "Depth Blur", + "full_command": "gcd_depth_blur 0,15,0.25,2,4,0,1" + }, + { + "plain_name": "Despeckle [test]", + "full_command": "gcd_despeckle_test 20,10,0,0" + }, + { + "plain_name": "Dither SRGB", + "full_command": "fx_gcd_dither_srgb 2,1" + }, + { + "plain_name": "Emboss", + "full_command": "gcd_emboss 128,0" + }, + { + "plain_name": "Geometric Color Balance", + "full_command": "gcd_geometric_balance 0" + }, + { + "plain_name": "Gradient Exponent", + "full_command": "fx_gcd_gradient_exponent 0.5,0" + }, + { + "plain_name": "Image InfoMap", + "full_command": "gcd_infomap 0" + }, + { + "plain_name": "Inpaint [Clone]", + "full_command": "fx_gcd_clone_inpaint 0,1,10,1" + }, + { + "plain_name": "Inverse Bezier Warp", + "full_command": "gcd_ebwarp 0.5,1" + }, + { + "plain_name": "JPEG Smooth", + "full_command": "gcd_jpeg_smooth 1,1,0,0" + }, + { + "plain_name": "Layer Manipulation", + "full_command": "gcd_layers 100,0,1,0,0,0,0,0,1,0,0,1" + }, + { + "plain_name": "LMS Adjustment", + "full_command": "gcd_balance_lms 1,1,1,0,0,0" + }, + { + "plain_name": "Local F-Mean", + "full_command": "gcd_fx_local_fmean 15,0,0,5,0" + }, + { + "plain_name": "Multi Thresholds", + "full_command": "tran_multi_threshold 50,100,150,200,9,0,1,255,175,42,27,255,101,101,101,255,174,165,131,255,247,228,160,255" + }, + { + "plain_name": "Normalize Brightness", + "full_command": "gcd_normalize_brightness 0,10,0,3,0,0" + }, + { + "plain_name": "PQCT Example", + "full_command": "gcd_pqct" + }, + { + "plain_name": "Quick Tonemap", + "full_command": "fx_gcd_quicktone 1,4,20,0,3,1" + }, + { + "plain_name": "Recolor", + "full_command": "gcd_recol -14,14" + }, + { + "plain_name": "Sharpen [Gradient]", + "full_command": "gcd_sharpen_gradient 0.5,2,0,0" + }, + { + "plain_name": "Sharpen [Tones]", + "full_command": "gcd_sharpen_tones 1,128,0,0" + }, + { + "plain_name": "Simple Dehaze", + "full_command": "gcd_simple_dehaze 0.75,1,0.75" + }, + { + "plain_name": "Simple Tone Curve", + "full_command": "gcd_simple_tonecurve 0.5,0.5,1,0.18,0.75,1" + }, + { + "plain_name": "Smart Rotate", + "full_command": "gcd_srotate 0,50,50,1,1,6,0.6,0" + }, + { + "plain_name": "Smooth [Geometric-Median]", + "full_command": "fx_gcd_geometric_median 3,12,0,0,50,50" + }, + { + "plain_name": "Split Objects", + "full_command": "gcd_splitobj 50,3,3,0,0,0,40,0,\"0\"" + }, + { + "plain_name": "Stereo Video", + "full_command": "gcd_stereo_vid \"\",\"\",\"\",0,0.5,1.2,0.25,2,4,1,5,1" + }, + { + "plain_name": "Target Color Spot", + "full_command": "fx_gcd_color_target 50,50,175,175,175,255,0" + }, + { + "plain_name": "Temperature Balance", + "full_command": "gcd_temp_balance 0,0,1,0" + }, + { + "plain_name": "Transfer Colors [Curves]", + "full_command": "fx_gcd_color_spot_matching 75,75,25,25,1,0,0" + }, + { + "plain_name": "Undo Unsharp Mask", + "full_command": "fx_gcd_undo_unsharp 3,0.5,1,0,50,50" + }, + { + "plain_name": "Unquantize [JPEG Smooth]", + "full_command": "gcd_unquantize 6,1,1,5,15" + }, + { + "plain_name": "Upscale [Edge]", + "full_command": "fx_gcd_upscale_edge 1,1,1,1" + }, + { + "plain_name": "Upscale [Noise]", + "full_command": "gcd_upscale_noise 16,2" + }, + { + "plain_name": "Upscale [Patch2x]", + "full_command": "fx_gcd_upscale_patch2x 0,0" + }, + { + "plain_name": "Upscale [Recursive2x]", + "full_command": "fx_gcd_upscale_recursive2x 4,0.05,0.01" + }, + { + "plain_name": "Upscale [Solver2x]", + "full_command": "fx_gcd_upscale_solver2x 4,0,1,1" + }, + { + "plain_name": "Warp Map", + "full_command": "gcd_warpmap 5,0,0,0,0" + }, + { + "plain_name": "Weighted Boxfilter", + "full_command": "fx_gcd_weighted_boxfilter 1,0,0" + }, + { + "plain_name": "Wiremap", + "full_command": "gcd_wiremap 100,100,0.5,0.5,0" + }, + { + "plain_name": "Xbr2x", + "full_command": "gcd_xbr2x" + }, + { + "plain_name": "60's Cinema", + "full_command": "fx_gb_cfx 10,0,0,0,0,0" + }, + { + "plain_name": "Lens Blur", + "full_command": "fx_gb_lb 10,7,0" + }, + { + "plain_name": "Ping Pong", + "full_command": "fx_gb_pp" + }, + { + "plain_name": "Finger Paint", + "full_command": "gtutor_fpaint 0.5,0.5,0,0,45,0.5,0.5,0.5,0" + }, + { + "plain_name": "Blur by Color", + "full_command": "gtutor_blur_img 3,0.5" + }, + { + "plain_name": "Hedcut", + "full_command": "hedcut 0.5,0.5,0.5,0,0.5,0,1,0" + }, + { + "plain_name": "ABN Filigrees", + "full_command": "gtutor_abn 60,40,1,50,50,1,50,50,1,50,50,1,5,255,255,255,255,100,100,0" + }, + { + "plain_name": "Hair Locks", + "full_command": "gtutor_hairlock 0.5,0.5,0.5,255,255,0,255,0.5,45,0.5,0.5,0" + }, + { + "plain_name": "Rectangular Tiling", + "full_command": "fx_rec_tileit 1,5,1.5,1,4,0,45,0.5" + }, + { + "plain_name": "2D Scopes", + "full_command": "iain_2d_scopes 1,2,2,6,512,2048,1,0,0,0,0" + }, + { + "plain_name": "Anisotropic Tutorial", + "full_command": "iain_smooth_tutorial 1000,0.5,1,0.6,1.1,0,0" + }, + { + "plain_name": "Auto WB by Hue Variance", + "full_command": "iain_auto_wb 5,5,95,95,1,0" + }, + { + "plain_name": "Automixer", + "full_command": "automixer 0,0" + }, + { + "plain_name": "Brown Spot Clean", + "full_command": "iain_brown_spot_clean 1,2" + }, + { + "plain_name": "CA Correction", + "full_command": "iain_CA_correction 0,0,2,0,3" + }, + { + "plain_name": "CMYK Tone", + "full_command": "iain_cmyk_tone_p 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,0,0" + }, + { + "plain_name": "Hue Lighten-Darken", + "full_command": "iain_hue_light_dark_p 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,100,255,0,0,0" + }, + { + "plain_name": "RGB Tone", + "full_command": "iain_rgb_tone 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255,255,0" + }, + { + "plain_name": "Saturation EQ", + "full_command": "Saturation_EQ_p 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0" + }, + { + "plain_name": "Tone Presets", + "full_command": "iain_tone_presets_p 0,100,0,0" + }, + { + "plain_name": "Constrained Sharpen", + "full_command": "iain_constrained_sharpen 0.75,2,1,5,0,11,1" + }, + { + "plain_name": "Make Up", + "full_command": "make_up 15,4,0,0,0" + }, + { + "plain_name": "Pyramid Processing", + "full_command": "iain_pyramid_processing 4,50,0.5,0,0" + }, + { + "plain_name": "Texture Enhance", + "full_command": "iain_texture_enhance_p 2,2,30,0,11,0,0" + }, + { + "plain_name": "Easy Skin Retouch", + "full_command": "iain_easy_skin_retouch 7,2,0.7,1,1,0.7,0.6,0.5,0.5,0.5,0" + }, + { + "plain_name": "Exfuse", + "full_command": "exfuse 1,0.6,0,0.5,1,5" + }, + { + "plain_name": "Exfusion", + "full_command": "exfusion 20" + }, + { + "plain_name": "Exfusion3", + "full_command": "exfusion3 0.3,0.3,0.2,0.3,-1,0" + }, + { + "plain_name": "Exfusion5", + "full_command": "exfusion5 0,0.2,0.2,1,0,0" + }, + { + "plain_name": "Fast Formula", + "full_command": "iain_fast_formula \"apply_gamma 2.2\"" + }, + { + "plain_name": "Fast Median Stack", + "full_command": "iain_fast_median_stack" + }, + { + "plain_name": "FFT Tile", + "full_command": "fft_tile 500,128,0" + }, + { + "plain_name": "Fill Holes", + "full_command": "fill_holes 11,21,5,0,0,1" + }, + { + "plain_name": "Grey Descreen", + "full_command": "iain_descreen2 3,-10000,10" + }, + { + "plain_name": "Halftone Shapes", + "full_command": "iain_halftone_shapes 100,0,0,0,0,0,0" + }, + { + "plain_name": "Heart Tone", + "full_command": "iain_hearttone 100,0" + }, + { + "plain_name": "Iain 2x", + "full_command": "iain_2x" + }, + { + "plain_name": "Iain Demosaic", + "full_command": "iain_demosiac 0" + }, + { + "plain_name": "Iain Denoise 2019 Beta3", + "full_command": "iain_denoise_2019_beta3 1,0,0,0,0.5,1,0,5,3,0,3,0,0.5,4,0" + }, + { + "plain_name": "Iain Remove Pattern", + "full_command": "iain_remove_pattern 3,3,3,0,4,128,1,0" + }, + { + "plain_name": "Iain Star Burst", + "full_command": "iain_star_burst 254,50,5,45,2,0,0" + }, + { + "plain_name": "Iain Unindex", + "full_command": "iain_unindex 30,20,1,50,50" + }, + { + "plain_name": "Iain Weightmap", + "full_command": "iain_weightmap 1,40" + }, + { + "plain_name": "Iain's Noise Reduction Old", + "full_command": "iain_iains_nr 3,3,1,0,0,0,1,0,0,0,1.35,0,0" + }, + { + "plain_name": "Iain Highlight Synthesis", + "full_command": "iain_highlight_synthesis 1,0.6,1,0" + }, + { + "plain_name": "IID Demosaic", + "full_command": "iain_iid_demosaic 1,1,1,0,0" + }, + { + "plain_name": "Luminance NR2", + "full_command": "luminance_nr_two 10,1,1,0.8,0.7,0.6,0.5,0.4,0.3,1200,64,0,0,0,0,0,0,0,0,0,0,0" + }, + { + "plain_name": "Minimum Chroma Demosaic", + "full_command": "iain_minimum_chroma_demosaic 0,2,0" + }, + { + "plain_name": "Moire Removal", + "full_command": "iain_moire_removal 5,5,0" + }, + { + "plain_name": "Moire Removal Not Parallel", + "full_command": "iain_moire_removal_NP 5,5,0" + }, + { + "plain_name": "MS NL-Means C Noise2", + "full_command": "ms_nlmeans_c_noise2_p 3,1,0,0,0,0,0,10,2,4,2,7,0,0,0,0" + }, + { + "plain_name": "MS Patch Chroma", + "full_command": "ms_patch_c 5,1,1,5,4,3,2,1,1,1.3,0.375,0.5,0.125,0" + }, + { + "plain_name": "MS Patch NR", + "full_command": "MS_Patch_NR 1.3,0,0,0,3,5" + }, + { + "plain_name": "MS Patch NR3", + "full_command": "MS_Patch_NR3 1.3,0,0,0,3,5,1,0,0,0,0,0" + }, + { + "plain_name": "Multi Scale Patch Smoothing", + "full_command": "ms_patch_smooth 10,5,3,5,0,1,1,7,5,4,3,2,1,1,1.3,0" + }, + { + "plain_name": "Multi Scale Smoothing", + "full_command": "ms_smooth 0,0,0,0,0,0,2,0,2,0" + }, + { + "plain_name": "Noise Reduction 5", + "full_command": "nr5 1.6,5,1,1,0.75,3,0,0.75,0.5,0,1,1,100,0,-100,0,1.3,0" + }, + { + "plain_name": "PNG Processing", + "full_command": "iain_png_processing 4,0,0,0,3,3,0,0.75,2,1,5,0,0,1,1" + }, + { + "plain_name": "Banding Denoise", + "full_command": "banding_denoise_v2 5,5,5,10,0,0,0,50,50" + }, + { + "plain_name": "Iain Noise Reduction 2019", + "full_command": "iain_nr_2019 1,0,0,0,0.5,1,0,5,3,0,3,0,0.5,4,0" + }, + { + "plain_name": "Iain's Fast Denoise", + "full_command": "iain_fast_denoise_p 0,0,1,0,0,0,1" + }, + { + "plain_name": "Local Similarity Mask", + "full_command": "local_similarity_mask 50,50,50,128,4,10" + }, + { + "plain_name": "Pixel Denoise", + "full_command": "iain_pixel_denoise_p 2,1,11,0,1" + }, + { + "plain_name": "Recursive Median", + "full_command": "iain_recursive_median_p 3,1,0,0,1" + }, + { + "plain_name": "Save Noise Print", + "full_command": "iain_savenoiseprint 0,1,1.4" + }, + { + "plain_name": "Simple Local Contrast", + "full_command": "simplelocalcontrast_p 16,2,0,1,1,1,1,1,1,1,1,0" + }, + { + "plain_name": "Skin Mask", + "full_command": "iain_fx_skin_mask 55,200,0,0,0,1" + }, + { + "plain_name": "Smart Demosaic", + "full_command": "iain_smartdemos 0,1.5,2" + }, + { + "plain_name": "Split Detials [Orientation]", + "full_command": "iain_split_orientation 75,50,45,10,5,5,0,0,1" + }, + { + "plain_name": "Star Tone", + "full_command": "star_tone 100" + }, + { + "plain_name": "Subtract Cast", + "full_command": "iain_sub_cast 5,20,250" + }, + { + "plain_name": "Turbulent Halftone", + "full_command": "iain_turbulent_halftone 15,20,0,1,512,0.75,0,0,0" + }, + { + "plain_name": "3D Rendering", + "full_command": "jeje_render3d \"\",8,6,0.1,240,0,30,1,32,32,64,255,64,128,96,255,0" + }, + { + "plain_name": "Deconvolve", + "full_command": "jeje_deconvolve 20,0" + }, + { + "plain_name": "Zernike", + "full_command": "jeje_zernike_preview 50,50,50,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0" + }, + { + "plain_name": "Jpr Colour Illusion", + "full_command": "jpr_colourillusion 2,25" + }, + { + "plain_name": "Jpr Coltexindex", + "full_command": "jpr_coltexindex 5,55,55,45,45,1,1,0,0.05,0.5,0.95,0.5,1,2,0.7" + }, + { + "plain_name": "Jpr Decimate", + "full_command": "jpr_decimate 0.375,2" + }, + { + "plain_name": "Jpr Gradient Smooth", + "full_command": "jpr_gradient_smooth 0,1.5" + }, + { + "plain_name": "Jpr Line Edges", + "full_command": "jpr_line_edges 2,2,4,1" + }, + { + "plain_name": "Jpr Orientedthinning", + "full_command": "jpr_orientedthinning 5,15,1,0,0" + }, + { + "plain_name": "Jpr Phasecongruence", + "full_command": "jpr_phasecongruence 45,1,50,1" + }, + { + "plain_name": "Jpr Remove Blocks1", + "full_command": "jpr_remove_blocks1 4,3,70" + }, + { + "plain_name": "Jpr Shapes Gradient", + "full_command": "jpr_shapes_gradient 2,0.25,0.001,100" + }, + { + "plain_name": "Jpr Specularbumps", + "full_command": "jpr_specularbumps 270,1,13,0,80,0.1,0.1,0" + }, + { + "plain_name": "Jpr Warpfromthreshold", + "full_command": "jpr_warpfromthreshold 170,2,10,2" + }, + { + "plain_name": "Charred Plastic", + "full_command": "fx_charred_plastic 1,10,40,1,10,0,0,2,6,5,20,0,11" + }, + { + "plain_name": "Dreamy Abstraction", + "full_command": "fx_dreamy_abstraction 2,1,1,0.5,10,0,0,7,1,3,1,1,1,1,1,11,1,25,5,1,0,1.5,0,50,50" + }, + { + "plain_name": "Dreamy Watercolour", + "full_command": "fx_dreamy_watercolour 0,0.3,40,60,0,1,50,0,10,2,1,1,0.5,10,0,0,7,1,3,1,1,1,1,1,11,1,25,5,1,10,1,0,0,1,0.5,0,8,1,0,128,128,128,255,0.5,1,8,0.2,1,1,0,27,0.75,0,1,20,40,40,1,2,1.25,0,2,1,27,1" + }, + { + "plain_name": "Hard Painting", + "full_command": "fx_hard_painting 1,2.5,4,50,1,1,0,2,6,5,20,0,0.62,14,0,1,0.5,0.78,1.92,0,0,0,1,1,1,0.5,0.8,1.28,0,50,50" + }, + { + "plain_name": "Neon", + "full_command": "fx_neon 0,1,1,1,1,0,0.45,40,60,0,1,1.15,2,3,0,3,20,0.4,0.1,1.5,5,0.2,0.1,1,2,1,0,0,1,1,0,50,50" + }, + { + "plain_name": "Neon Alpha", + "full_command": "fx_neon_alpha 0,0.45,40,60,0,2,1.15,20,0.4,0.1,2.25,5,0.2,0.1,2.25,2,1" + }, + { + "plain_name": "Otsu-Hessian Blend", + "full_command": "fx_otsu_hessian_blend 4,0,1,27,1,0" + }, + { + "plain_name": "Whirling Lines", + "full_command": "fx_whirling_lines 30,6,0,0,0.45,40,60,0,0,30,0,3,3" + }, + { + "plain_name": "Colour Space Swap", + "full_command": "csswap 0,0,0,50,50" + }, + { + "plain_name": "CubeHelix", + "full_command": "fx_cubehelix 1,0,100,0,0,0,0,255,255,255,255,255,1,-1.5,0,0,1,1,0,0,1,1,1,0,1,0,1,0,0,0,50,50" + }, + { + "plain_name": "Frequency Representation", + "full_command": "fx_frequency_representation 3,256,0,40,0" + }, + { + "plain_name": "Quick Desaturate", + "full_command": "jr_desaturate 0,1,1,1,1,0,50,50" + }, + { + "plain_name": "Satellite", + "full_command": "fx_satellite 0,0,0,100,1,0,255,0,0,0,50,50" + }, + { + "plain_name": "Gradient Norm [JR's Mod]", + "full_command": "fx_jr_gradient_norm 0,0.45,40,60,0,0,1,1,2,0,0,50,50" + }, + { + "plain_name": "Auto-Gnarl", + "full_command": "fx_auto_gnarl 3,0.45,40,60,0,1,1,2,4,6,5,20,1,2.5,0.5,2,2,3" + }, + { + "plain_name": "Buffer Destroyer", + "full_command": "fx_buffer_destroyer 0,1,75,40,0,100,0,1,1,0,50,100,0.5,1,0,3,0,50,100,0,0,0,0,2.5,20,2.5,20,1,5,5,1,120,80,0,100,0,1,0,50,50" + }, + { + "plain_name": "Buffer Error", + "full_command": "fx_buffer_error 50,50,0,100,0,1,0,50,50" + }, + { + "plain_name": "Kaleidoscope Layer Cake", + "full_command": "fx_jr_klc 6,0,0,0,0,50,50,50,50,0,30,0,0,100,1,2,3" + }, + { + "plain_name": "Layer Cake", + "full_command": "fx_layer_cake 4,360,0,75,50,50,3,1,0,30,0,3,0,0,50,50" + }, + { + "plain_name": "Layer Cake 2", + "full_command": "fx_layer_cake_2 4,360,0,50,50,2,3,50,0,0" + }, + { + "plain_name": "PowerTwirl", + "full_command": "fx_powertwirl 1,0,50,50,1,3,0" + }, + { + "plain_name": "Random Deformations (JR's Mod)", + "full_command": "fx_jr_deform 0,5,1,10,1,0,0,1,0,50,50" + }, + { + "plain_name": "Rays from Image", + "full_command": "fx_rays_from_image 5,50,50,0,0" + }, + { + "plain_name": "Shifter", + "full_command": "fx_shifter 0,0,1,1,20,1,20,1,5,5,0,50,50" + }, + { + "plain_name": "Spiral Matrix Transformation", + "full_command": "fx_jr_spiral_transform 0,0,0,0,0" + }, + { + "plain_name": "UltraWarp 2", + "full_command": "fx_ultrawarptwo 0,3,1,0,3,0,3,0,3,0,3,2,2,5,3,0,1,1,1,0,1,0.5,2.5,5,1,0,1,0,0,255,0,255,0,0,0,0" + }, + { + "plain_name": "UltraWarp++++", + "full_command": "fx_ultrawarp4plus 0,0,3.3,0,0,5,0,0,0,4,256,4.8,5,2,0,0,2,3,3,20,1,1,0,5,2,1,2,0.25,1,1,0,5,0,3,0.5,2,-180,0,0,1,11,0,0" + }, + { + "plain_name": "Blur [Bloom Glare]", + "full_command": "fx_blur_bloom_glare 1,2,5,0,0,0,0,0,3,0.5,7,0" + }, + { + "plain_name": "Bomb Blend", + "full_command": "fx_blend_bomb 0,1,16,16,2,0,50,0,0,0,0,0" + }, + { + "plain_name": "Broken Texture Afre", + "full_command": "fx_texture_afre_broken 1,10,0" + }, + { + "plain_name": "Butterworth Bandpass", + "full_command": "fx_butterworth_bp 3,2,0,4,2,0,0,0,1,1,0" + }, + { + "plain_name": "Cascading Self Glitching", + "full_command": "fx_self_glitching_cascade 0,0,0,50,50,3,3,1,55,55,0,45,45,0.75,3,0,0,0,0,1,0,0,256,1,0,0" + }, + { + "plain_name": "DCT FSU", + "full_command": "fx_dct_fsu 0,50,50,0,0,100,100,0,1,0,0,0,50,50" + }, + { + "plain_name": "Fake JFIF (JPEG) Encoder", + "full_command": "fx_jfif_fake 50,0,0,1.25,5,0.25,0,50,50" + }, + { + "plain_name": "Faux-QAM Glitch", + "full_command": "fx_qam_glitch 2,20,0,0,1,127.5,0,1,1,1,0,0,20,5,0,0,0,2,0.6,0.05,0,50,50" + }, + { + "plain_name": "JFIF [JPEG] Self-Bomb", + "full_command": "fx_jfif_bomb 0,50,16,16,0.5,1,75,1,1,0,0,0,1,75,1,20,0,1" + }, + { + "plain_name": "JFIF Effects", + "full_command": "fx_jfif 50,3,0,1,5,5,3,0.25,0.5,0.25,0,0,0,16,16,0.5,1,75,1,1,0,0,0,0,50,50" + }, + { + "plain_name": "JFIF Effects Extended", + "full_command": "fx_jfif_xt 50,8,8" + }, + { + "plain_name": "JPEG Encoder", + "full_command": "fx_jpeg_preview 80,21,8,8,16,16,16,16,0,0,0,0,0,0,0" + }, + { + "plain_name": "Multi-Mosaic", + "full_command": "fx_jr_multi_mosaic_preview 0,3,15,45,50,0,128,128,128,255,0,0,0,1,0,0.5,0,100,1,0,0,0,255,0,0,0,1,15,16,0.5,1,3,5,15,2,6,5,20,1,2" + }, + { + "plain_name": "Pseudo-ECB (Electronic Code Book Algorithm)", + "full_command": "pseudo_ecb 0,0,1,20,1,1,5,0,0,5,90,0,41,1,15,256,75,16,100,1,41,1,41,1,1,0,1,41,1,0,0,0,50,50" + }, + { + "plain_name": "Row Shifter", + "full_command": "fx_row_shift 0,0,0.5,0,0.5,3,0" + }, + { + "plain_name": "Sawtoother [CMY(-K)]", + "full_command": "sawtoother_cmy_k 1,0,0,1,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,1,0,0,2,0" + }, + { + "plain_name": "Sawtoother [HSX]", + "full_command": "sawtoother_hsx 1,0,0,1,1,0,1,0,0,1,1,0,0,1,0,0,1,1,0,0,2,0" + }, + { + "plain_name": "Sawtoother [Lab8]", + "full_command": "sawtoother_lab8 1,0,0,1,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,2,0" + }, + { + "plain_name": "Sawtoother [LCH8]", + "full_command": "sawtoother_lch8 1,0,0,1,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,2,0" + }, + { + "plain_name": "Sawtoother [RGB]", + "full_command": "sawtoother_rgb 1,0,0,1,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,2,0" + }, + { + "plain_name": "Sawtoother [sRGB]", + "full_command": "sawtoother_srgb 1,0,0,1,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,2,0" + }, + { + "plain_name": "Sawtoother [XYZ8]", + "full_command": "sawtoother_xyz8 1,0,0,1,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,2,0" + }, + { + "plain_name": "Sawtoother [YCbCr-(-GLIC-JPEG)]", + "full_command": "sawtoother_ycbcr 0,1,0,0,1,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,2,0" + }, + { + "plain_name": "Sawtoother [YIQ8]", + "full_command": "sawtoother_yiq8 1,0,0,1,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,2,0" + }, + { + "plain_name": "Sawtoother [YUV8]", + "full_command": "sawtoother_yuv8 1,0,0,1,1,0,1,0,0,1,1,0,1,0,0,1,1,0,0,2,0" + }, + { + "plain_name": "Shredder", + "full_command": "fx_shredder 0,1,0,1,0,100,0.5,0,100,0.5,0,0" + }, + { + "plain_name": "Smooth EQ", + "full_command": "fx_jr_smooth_eq 8,2,0,3,2,1.5,0,4,2,2,0,5,2,2,0,6,2,2,0,7,2,2,0,3,2,0,0,0,1,1,0" + }, + { + "plain_name": "Superstreak", + "full_command": "fx_superstreak 10,10,3,0.5,0.5,10,30" + }, + { + "plain_name": "UltraWarp 3", + "full_command": "fx_ultrawarp3_preview 0,-1,1,1,1,0,360,1,1,0,360,0,1,3,0,0,0,15,50,0,25,0,25,0,0,0,360,0,0,0,0,1,0,16,0,1,1,5,15" + }, + { + "plain_name": "8-Bit Plane Splitter", + "full_command": "fx_bitplane8 0,1,0,0" + }, + { + "plain_name": "Bilinear Enhancement", + "full_command": "fx_jr_bilinear 1,3,10,10,1,0,0,50,50" + }, + { + "plain_name": "Mesh Blend", + "full_command": "fx_mesh_blend 0,3,0,0,0,0" + }, + { + "plain_name": "Crazy Texture", + "full_command": "fx_crazy_texture 0,75,30,0,15,6,3,0,15,0,1,1,0,1.5,0,1,1,0,1,1" + }, + { + "plain_name": "Rectexture", + "full_command": "fx_rectexture 0,10,3,1,5,2,0" + }, + { + "plain_name": "CImg NL-Means", + "full_command": "fx_karo_cimg_nlmeans 0,0,0,1,-1,-1,3,2,0,50,50" + }, + { + "plain_name": "CImg Skeleton", + "full_command": "fx_karo_cimg_skel 1,50,0,0,-0.3,0,0,1,0,50,50" + }, + { + "plain_name": "MM Differences", + "full_command": "fx_karo_mm_diff 5,7,2,1,0,1,0,50,50" + }, + { + "plain_name": "OC Differences", + "full_command": "fx_karo_oc_diff 5,1,0,1,0,50,50" + }, + { + "plain_name": "Pink Operator", + "full_command": "fx_karo_pink 0,0,0,5,0,0,50,50" + }, + { + "plain_name": "Pink Operator Binary", + "full_command": "fx_karo_pink_bin 1,50,3,0,5,4,0,0,50,50" + }, + { + "plain_name": "Pink Test Operator Bianca", + "full_command": "fx_karo_pink_bianca 5,60,5,1,0,0,0,50,50" + }, + { + "plain_name": "Blend [Shape Average]", + "full_command": "fx_blend_shapeaverage 1,0,0" + }, + { + "plain_name": "Lylejk Luma Invert", + "full_command": "Lylejk_Luma_Invert 1,0" + }, + { + "plain_name": "Lylejk Quantize Wicker", + "full_command": "Lylejk_Quantize_Wicker 16,50,50,0,16,10,5,1,1,0,0,0,255,1,10,10,153,0,2,10,20,0.1,1,0" + }, + { + "plain_name": "Lylejk Ribbon", + "full_command": "Lylejk_Ribbon 150,0.42,0.85,0.6,7.83,0.68,19,2.64,0,1,2,16,3.44,0,3,0.79,0.72,4.97,1.7,150,0.42,0.85,0.6,7.83,0.68,19,2.64,0,1,2,0,0.32,43.1,100,0,2,1.15,5,1,0" + }, + { + "plain_name": "Lylejk Ripple", + "full_command": "ripple 10,20,2,0,0" + }, + { + "plain_name": "Lylejk Test TRW", + "full_command": "lylejk_test_TRW 50,50,1,16,10,5,1,1,0,0,0,255,50,50,1,1,1.8,10,153,150,0.42,0.85,0.6,7.83,0.68,19,2.64,0,1,1,0,0.5,10.5,100,0,0,0.5,10.5,100,0,1.15,5,1,0.68,0.5,10.5,100,0,0,1,10,1,0,0" + }, + { + "plain_name": "Lylejk Wicker", + "full_command": "Lylejk_Wicker 10,10,153,150,0.42,0.85,0.6,7.83,0.68,19,2.64,0,1,1,0,0.5,10.5,100,0,0,0.5,10.5,100,0,1.15,5,1,0.68,0.5,10.5,100,0,0,1,10,1,0,0" + }, + { + "plain_name": "Lylejk Woven", + "full_command": "Lylejk_Woven 19.6,32.4,1,0,0,19.6,32.4,1,0,0,12,10,5,1,1,0,0,0,255,19.6,32.4,1,0,0,19.6,32.4,1,0,0,150,0.61,0.85,0.6,7.83,0.68,19,2.64,0,1,1,0,0.29,37.2,100,0,0,2,0,16,0" + }, + { + "plain_name": "Lylejk's Stencil", + "full_command": "fx_lylejk_stencil 5,10,3,0" + }, + { + "plain_name": "Lylejk Wicker 2", + "full_command": "Lylejk_Wicker_2 50,50,1,50,50,1,1,12,10,5,1,1,0,0,0,255,150,0.54,0.85,0.6,7.83,0.68,19,2.64,0,1,3,0,0.29,28.7,100,0,0,1,10,20,0.1,1,10,12,2,40,0.7,0.3,0.6,1.1,0.8,30,2,0,1,3,1,0,16,1,0" + }, + { + "plain_name": "Pen Drawing", + "full_command": "fx_pen_drawing 10" + }, + { + "plain_name": "Point Star Outline", + "full_command": "garagecoder_lylejk_samj_points_outlines 0,0.05,10,0.12,0,0,2,0" + }, + { + "plain_name": "Film Grain", + "full_command": "mc_film_grain \"\",0,1,20,0,100,0,0,0,0,1,0,255,0,0,0,0" + }, + { + "plain_name": "Hue Overlay Masks", + "full_command": "fx_hue_overlay_masks 0,5" + }, + { + "plain_name": "Abstract Flood", + "full_command": "fx_AbstractFlood 1,10,7,2,0,10,5,3,255,255,255,255,0,300,10,90,0.7,0,0,0" + }, + { + "plain_name": "Color Abstraction Paint", + "full_command": "fx_ColorAbstractionPaint 5,10,1,0,1,0,1,0,0,0,0,0,0,0" + }, + { + "plain_name": "Dream Smoothing", + "full_command": "fx_dreamsmooth 3,1,1,0.8,0,0.8,1,24,0" + }, + { + "plain_name": "Make Squiggly", + "full_command": "fx_Squiggly 2,12,0.8,0,0.5,1,0,0,3,0.2,0.4,0,1,1,0" + }, + { + "plain_name": "Morphology Painting", + "full_command": "fx_MorphoPaint 1,18,2,25,100,230,8,3,4,0.5,2,0.5,200,1,1,1,1,1,1,1,1,0" + }, + { + "plain_name": "Simple Noise Canvas", + "full_command": "fx_SimpleNoiseCanvas 0,3,2,5,5,0,255,0,2,0,0,0,1,0,255,255,255,255,0" + }, + { + "plain_name": "Black & White Film", + "full_command": "fx_bwfilmsimulate 0,0.299,0,0.587,0,0.114,0,1,1,0,0,0,0,0,0,2,0,0,0,16,4,0" + }, + { + "plain_name": "Blockism", + "full_command": "fx_blockism 3,1.6,0.5,50,0.5,64,0,0,0" + }, + { + "plain_name": "Composition Analysis", + "full_command": "fx_CompositionAnalysis 0" + }, + { + "plain_name": "Local Contrast Enhancement", + "full_command": "fx_LCE 80,0.5,1,1,0,0" + }, + { + "plain_name": "YAG Effect", + "full_command": "fx_yag_soften 0,0,0" + }, + { + "plain_name": "Dodge Sketch", + "full_command": "fx_dodgesketch 3,10,7,2,0,0" + }, + { + "plain_name": "Exposure Fusion Weight Map", + "full_command": "fx_ExposureWeightMap 0.3,0.3,0.2,0.3,1,0" + }, + { + "plain_name": "GMic Structure Tensors", + "full_command": "fx_StructureTensors 0.1,0" + }, + { + "plain_name": "Import 16bits Image", + "full_command": "fx_import_image_16 \"\",1,2.2,0,1,0,0,0,0,100,0" + }, + { + "plain_name": "Luminance to Alpha", + "full_command": "fx_split_luminance 1,1,1,0,\"keep.\"" + }, + { + "plain_name": "Make Old Squiggly", + "full_command": "fx_OldSquiggly 2,12,0.8,0,0.5,3,0.2,0.4,50,245,45,0.5" + }, + { + "plain_name": "Mapped Smoothing", + "full_command": "fx_MappedSmooth 0,0,0,300,1,0" + }, + { + "plain_name": "Night HDR Image Black Noise Correction", + "full_command": "fx_fix_HDR_black 20,25,50,200,0,0" + }, + { + "plain_name": "Noise Painting", + "full_command": "fx_noisepainting 0,0,0,5,2.5,1.5,50,1,0" + }, + { + "plain_name": "Pastell Art", + "full_command": "fx_pastell 0.6,1,0,20,30,300,1,30,1,1,0.5,0,0,10,3,0,9,3,0,12,0" + }, + { + "plain_name": "Smooth Sketch", + "full_command": "fx_SmoothSketch 1,6,0.8,0.3,0.3,0,1000,0,50,10,2,0.6,0.55,1,0" + }, + { + "plain_name": "Vector Field Rotation Demo", + "full_command": "fx_DemoVecRot 0" + }, + { + "plain_name": "Warp Test", + "full_command": "fx_WarpTest 0,0,0,1,0" + }, + { + "plain_name": "Jobs Colors", + "full_command": "fx_jobs_colors 0,0,0" + }, + { + "plain_name": "Colored Pencils", + "full_command": "fx_cpencil 1.3,50,20,2,2,1,0" + }, + { + "plain_name": "Graphic Boost", + "full_command": "fx_graphic_boost4 1.25,2,0,0.15,14,0,1,0.5,0.45,2,0,1,0,1,1,1,0.5,0.45,1" + }, + { + "plain_name": "Graphic Novel", + "full_command": "fx_graphic_novelfxl 0,2,6,5,20,0,0.62,14,0,1,0.5,0.78,1.92,0,0,0,1,1,1,0.5,0.8,1.28" + }, + { + "plain_name": "B&W Steampunk Pencil", + "full_command": "fx_steampen 0.95,14,2,2,0.9,0,1,0,0.5,0.75,0.48,0" + }, + { + "plain_name": "Black Crayon Graffiti", + "full_command": "fx_crayongraffiti2 300,50,1,0.4,12,1,2,2,0" + }, + { + "plain_name": "Boost Screen", + "full_command": "fx_compose_boostscreen 0.7,0,0.7" + }, + { + "plain_name": "Color Doping", + "full_command": "fx_compose_colordoping 1,0" + }, + { + "plain_name": "Color Sketch", + "full_command": "fx_colorsketchbw 300,50,1,0.1,20,1,0,20,2,0,1,0" + }, + { + "plain_name": "Color Stamp", + "full_command": "fx_colorstamp 1,50,1,20,2,0" + }, + { + "plain_name": "Comix Colors", + "full_command": "fx_compose_comix_color 1,0,1" + }, + { + "plain_name": "Contrast Swiss Mask", + "full_command": "fx_contrast_swm 2,0,1" + }, + { + "plain_name": "Dark Edges", + "full_command": "fx_compose_darkedges 1,0.5,0,0.7" + }, + { + "plain_name": "Dark Screen", + "full_command": "fx_compose_darkscreen 0.7,0,0.7" + }, + { + "plain_name": "Graphic Boost-Old", + "full_command": "fx_graphic_boost 1.25,2,0,0.15,14,0,1,0.5,0.45,2,0,1,0,1,1,0.5,0.45,1,0" + }, + { + "plain_name": "Graphic Colors", + "full_command": "fx_compose_graphicolor 0.6,0,0.8" + }, + { + "plain_name": "Graphic Novel-Old", + "full_command": "fx_novelfx 0,2,6,5,20,0,0.62,14,0,1,0.5,0.78,1.92,0,0,0,1,1,0.5,0.8,1.28,0" + }, + { + "plain_name": "GraphiX Colors", + "full_command": "fx_compose_graphixcolor 1,0" + }, + { + "plain_name": "Heavy Screen", + "full_command": "fx_compose_heavyscreen 0.6,0,0.7" + }, + { + "plain_name": "Metallic Grain", + "full_command": "fx_metalgrain 0.5,0,0" + }, + { + "plain_name": "Metallic Stencils", + "full_command": "fx_metallicstencils 0,0" + }, + { + "plain_name": "Seamless Deco", + "full_command": "fx_mad_rorscharchp 3,0,50,1,300,0,0,0,0" + }, + { + "plain_name": "Phoenix Steam-Pencil", + "full_command": "fx_phoenix 0.95,14,2,2,0.9,0,0,0,1,1,0" + }, + { + "plain_name": "PhotoComiX Smoothing", + "full_command": "fx_smooth_anisotropic 60,0.16,0.63,0.6,2.35,0.8,30,2,0,1,1,0,1" + }, + { + "plain_name": "Posterized Dithering", + "full_command": "fx_pdithered 1,1,0,0,20,1,0,1,0" + }, + { + "plain_name": "Psychedelic Glasswork Tiler", + "full_command": "fx_psyglass 0,20,0.1,1,1,0,1,1,0,1,1,0,0,2,0,0,0" + }, + { + "plain_name": "Scale Down Neat", + "full_command": "fx_scaledown3 0,1,1,1,1600,1600,0,2.3,1,12,0" + }, + { + "plain_name": "Symmetry Master", + "full_command": "fx_viral 8,0,0,0,0,0" + }, + { + "plain_name": "Vivid Colors", + "full_command": "fx_compose_vivid_color 1,0,1" + }, + { + "plain_name": "Vivid Edges", + "full_command": "fx_compose_vividedges 1,0.5,0,0.7" + }, + { + "plain_name": "Vivid Screen", + "full_command": "fx_compose_vividscreen 0.6,0,0.7" + }, + { + "plain_name": "Wild Cartoonizer", + "full_command": "fx_m_l_unsharp2 12,2.18,0.3,1.5,1,0.5,0,0.5,0.8,1.28,0" + }, + { + "plain_name": "3D Abstract", + "full_command": "pr_3dabstract 5,20,128,0,360,0.5,1,90,0.8,3,100,500,0,16,1,0.3,4,0,0" + }, + { + "plain_name": "Channel Shuffle", + "full_command": "pr_chanshuff 0,0,0,1,0" + }, + { + "plain_name": "Sloppy Mess", + "full_command": "pr_sloppymess 0,1,0,0,-1,0,0,35,-35,2,0,0,0,2,2,1,3,100" + }, + { + "plain_name": "Fluffy Cloud", + "full_command": "pr_fluffcloud 20,40,35,25,50,40,65,25,80,40,10,90,30,90,50,90,70,90,90,90,0,500,0.02,10,1,30,0,180,0.5,2,200,0.2,0,0,0,0,0.2,1,0,17,0.9,31,0.9" + }, + { + "plain_name": "Gimp Random Layer Modes", + "full_command": "pr_laymod 0,30,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0" + }, + { + "plain_name": "Iris", + "full_command": "pr_iris 800,1,10,0.4,0.4,20,20,0,100,0,100,100,0,255,30,150,150,255,255,100,0,255,50" + }, + { + "plain_name": "Kaleido Patterns", + "full_command": "pr_kalpat 0,1,50,50,0,1,2,180,5,0,\"0xFFFFFFFF\",0,\"\",128,255,0,0,255,255,113,57,255,255,255,0,255,85,0,255,255,0,0,255,255,0,113,165,255,85,170,0,255,255,255,255,255,255,0,0,255,255,113,57,255,255,255,0,255,85,0,255,255,0,0,255,255,0,113,165,255,85,170,0,255,255,255,255,255" + }, + { + "plain_name": "Line Spam", + "full_command": "pr_linespam 30,3,1.02,0.8,-1,10,101,100,0,0,255,85,0,255,0,0,0,5,10,0.8,1,0" + }, + { + "plain_name": "Little Boxy Things", + "full_command": "pr_lilboxy 20,40,60,2,2,0,0,0,0,255" + }, + { + "plain_name": "Nonscape - Grass", + "full_command": "pr_nongrass 3,36,144,30,255,10,50,100,0.1,6,20,10,0.7,10,3" + }, + { + "plain_name": "Nonscape - Woods", + "full_command": "pr_nonwoods 0,50,1920,1080,80,5,3,3,0.2,255,255,255,255,34,1500,1,255,255,255,255,0.8,0,0,10,0,4,2,0,0,40,50,0,24,16,0,255,1,0,23,0,255,1,38,76,56,255,20,3,0.12,8,10,20,10,10,0,46,67,255,0,124,182,255,255,255,255,255,0,169,200,255,0,85,127,255,0.4,19,0,0" + }, + { + "plain_name": "Paper Cuts", + "full_command": "pr_papercuts 3,0,8,1,80,127,255,255,0,14,1,4,0.6,4,0,1,0,0,0,1,0.6,100" + }, + { + "plain_name": "Prawn Canvas", + "full_command": "pr_canvas 0.3,0,0,255,255,255,255" + }, + { + "plain_name": "Underwoods", + "full_command": "pr_underwoods 0,30,50,5,10,10,0.7,208,208,156,255,34,500,1,255,255,255,255,0.4,0,0,10,4,2,0.4,0,20,15,10,0,255,1,15,10,0,255,0.8,100,0,0,255,40,30,0,255,40,20,0,255,20,10,0,255,0,0,0,255,0.2,34,0" + }, + { + "plain_name": "Seamless Chaotic Pattern", + "full_command": "pr_scpat 0,0,0,0,5,5,5,5,5,5,5,10,2,\"0xFFFFFFFF\",0,0,40,60,255,0,0,255,255,113,57,255,255,255,0,255,85,0,255,255,0,0,255,255,0,113,165,255,85,170,0,255,255,255,255,255" + }, + { + "plain_name": "Sick Painter", + "full_command": "pr_sickpaint 30,0,0,100,100,100,0.7,0.4,1000,255,0,0,255,32,153,162,255,12" + }, + { + "plain_name": "Sketchy Ellipses", + "full_command": "pr_sketchy_ellipses 2000,35,35,35,35,7,4,4,4,1000,0,2,4,1,1,1,0.3,\"0xFFFFFFFF\",0,0,0,255,255,255,255,255" + }, + { + "plain_name": "Slice Stretch-Squeeze", + "full_command": "pr_streeze 10,101,20,80,80,20,80,120,0,2,0,25" + }, + { + "plain_name": "Smoothelate", + "full_command": "pr_smoothelate 0,0,0,2.5,4,500,3,0" + }, + { + "plain_name": "Stringify Mod", + "full_command": "pr_stringify 0,0,1,64,50,2,100,32,50,10,0,0,0,0,255" + }, + { + "plain_name": "Uglify", + "full_command": "uglify 0,1,1000,0,0,0,0,0,0,1,3,3,13,0.5,1,12,1,5,20,0.5,-1,-100,0,7,0.6,1,150,1,0.05,0.02,0.02,1,25,0,0,2,1,0.8,0.6,1.6,22,3,0.3,0,255,255,255,255,1,1.5,0.5,0,0,0,0,0,0" + }, + { + "plain_name": "Array [Random] [Jumble by Px]", + "full_command": "fx_rep_array_random_jumble_by_px 128,128,128,128,0,0,0,\"List of Factors\",\"List of Factors\",\"List of Factors\",\"List of Factors\",\"List of Factors\",\"List of Factors\",1,1,1" + }, + { + "plain_name": "Attractor", + "full_command": "fx_rep_trsa 0,7,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,0" + }, + { + "plain_name": "Autofill Coloring Book", + "full_command": "gui_rep_acb 180,0,1,0,250000,0,50,50" + }, + { + "plain_name": "Axis Streak", + "full_command": "gui_axis_streak 0,0,0,0,0,50,50" + }, + { + "plain_name": "Binary Alternating Quaddro Texture [Basic]", + "full_command": "rep_binary_quaddro_basic_gui 0,0,8,8,128,2,0,0,0,256,255,1,361,361" + }, + { + "plain_name": "Binary Alternating Quaddro Texture [MultiChannel]", + "full_command": "rep_binary_quaddro_mc_gui 0,0,0,0,1,2,0,1,2,3,0,1,2,3,4,0,8,8,128,2,0,0,0,1,0,8,8,128,2,0,0,0,1,0,8,8,128,2,0,0,0,1,0,8,8,128,2,0,0,0,1,0,8,8,128,2,0,0,0,1" + }, + { + "plain_name": "Bit-Plane Shuffler", + "full_command": "fx_rep_bitplane_shuffle 0,0,0,\"Here is where you copy command to command line interface.\",\"This is just a reference text\",0,0,\"0\",0,1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,8,10,9,4,7,13,1,3,11,14,6,2,12,5,15,16,8,10,9,4,7,13,1,3,11,14,6,2,12,5,15,16,0,0,0,0,0,50,50" + }, + { + "plain_name": "Blur [Splinter]", + "full_command": "fx_rep_blur_splinter 20,3,0,0,0,0,3,0,0,50,50" + }, + { + "plain_name": "Bricks", + "full_command": "gui_rep_shape_brick 150,150,5,5,0,0,0,0,0,0,170,0,0,255,85,0,0,255,121,77,2,255,0,41,100,0" + }, + { + "plain_name": "Channel Blur-Sharpen-Overblur-Overline", + "full_command": "fx_rep_cbsoo 0,1,0,0,0,\"temp_text\",-1,-1,-1,-1,-1,0,1,0,0,0,1,1,0,0,1,1,0,0,0,0,3,100,1,21,100,3,100,1,21,100,1,3,100,1,21,100,1,1,3,100,1,21,100,1,1,3,100,1,21,100,1,1,3,100,1,21,100,1,3,100,1,21,100,1,0,0,0,0,2,0,1,0,2,50,50,1,1,0,\"-1\",0" + }, + { + "plain_name": "Chirikov-Taylor", + "full_command": "fx_rep_cstdmap 500,5000,1,0,0,0,1,1,0,0,0,2,0,20,0" + }, + { + "plain_name": "Color Existence Distribution [RGB-8]", + "full_command": "rep_color_existence_distribution_rgb8 1" + }, + { + "plain_name": "Color Harmonies", + "full_command": "samj_Color_Palettes 50,50,0,6,24,0,0,180,90,45,255,1,3,2,1" + }, + { + "plain_name": "Color Modulo Texture", + "full_command": "gui_rep_colmt 0,0,0,0,1,0,3,0,255,0,0,1,0,1,0,0,3,0,255,0,0,1,0,1,3,0,255,0,0,1,0,1,3,0,255,0,0,1,0,1,3,0,255,0,0,1,0,1,1,5" + }, + { + "plain_name": "Color Region", + "full_command": "fx_rep_color_region 5,5,6,-1,-1,-1,0,50,50" + }, + { + "plain_name": "Complexion Burst", + "full_command": "fx_rep_compb 50,1,0.05,3,3,3,2,0,50,50,0,0,1,0,1,2,0,1,2,0,1,2,0.5,0.5,1,1,0" + }, + { + "plain_name": "Construction Material Texture", + "full_command": "_cons_turb 88,8,2.5,2,128,128,128,255,20,3,0,1,0,1,1,1,1,100,20,100,15,100,2,0,188,0,0,0.19,0.52,128,128,0,1,2,0,0,0,0,3,2,0,4,2,2,0,1,1,1,5,0,0.5,2,1,0,100,0,50,50" + }, + { + "plain_name": "Detailed Information", + "full_command": "_none_ \"Every information can be found here\",16,16,\"to_be_filled\"" + }, + { + "plain_name": "Diffusion Limited Aggregation", + "full_command": "fx_rep_dla 100,0,0,0,0,0,1,0,0,100,0,0,0,0,0,1,0" + }, + { + "plain_name": "Dungeon Floor (Super Slow!)", + "full_command": "fx_rep_dungeon_floor 0,0,2" + }, + { + "plain_name": "Dynamic Contrast", + "full_command": "rep_dynamic_contrast 0,128,255,0,50,50" + }, + { + "plain_name": "Edge Fade", + "full_command": "fx_rep_edgefade 10,10,0,2,0,4,2,0,50,50" + }, + { + "plain_name": "Ellsworth Kelly Board", + "full_command": "fx_rep_ekb 10,10,1,1,50,0,110,105,130,255,0,255,255,255,255,0,25,0,12,0,10,0,0" + }, + { + "plain_name": "Emboss-Relief", + "full_command": "fx_emboss_relief 5,0,0.5,2,0,1,1,0,50,50" + }, + { + "plain_name": "Fibonacci", + "full_command": "fx_rep_fibonacci 1,10,0,0,0,50,50,0,0,1,0,0,2500,100,500,0" + }, + { + "plain_name": "Fragment Blur", + "full_command": "gui_rep_frblur 0,10,5,0,0,1,0,0,50,50" + }, + { + "plain_name": "Gaussian Blur By Color Space", + "full_command": "fx_rep_blur_cs 3,0,0,1,0,0,50,50" + }, + { + "plain_name": "Glass Vignette", + "full_command": "gui_rep_gv 100,0,100,0,50,50,0,0,100,100,100,0,50,50,0,3,5,1,0,50,50" + }, + { + "plain_name": "Graduated Filter", + "full_command": "fx_rep_graduated_filter 50,100,50,0,0,0,0,255,0,50,50" + }, + { + "plain_name": "Grouped Pixel Axis-Based Shift", + "full_command": "fx_rep_sptbwgp 0,0,0,0,\"stored_values_here\"" + }, + { + "plain_name": "Henon Phase Diagram", + "full_command": "fx_rep_henon_phase_diagram 2.569,500,1000,-0.5,0.5,8,1,0,50,50,0,0,0,0,1,2,0,20,0,0" + }, + { + "plain_name": "Hitomezashi", + "full_command": "fx_rep_hitomezashi 0,5,0,0,0,0,255,255,255,255,\"\",\"\",\"\",0,0,0,0,3,0,255,128,128,128,255,241,255,85,255,159,26,157,255,0,0,0,44,10,8,5,4,0,0,0,0,0,0,0,0,0,0,0,0,255,10,8,0,0,0,0,10,128,0,0,0,255,50,50,0,1" + }, + { + "plain_name": "HSX Posterize-Index", + "full_command": "fx_rep_p_i 10,10,10,50,0,2" + }, + { + "plain_name": "Image Dimensions Factors", + "full_command": "_none_ \"Every factors can be copied and pasted from this box\"" + }, + { + "plain_name": "Kaleidoscope [Reptorian-Polar]", + "full_command": "gui_rep_polkal 2,1,0,50,50,0,0,1,2,0,1,0.5,2" + }, + { + "plain_name": "Lavander Binary Map", + "full_command": "fx_rep_lavander_binary_map 0,8,5,\"01\",\"10\",\"01\",0,\"xor(min(xor(x(),y()),xor(ix(),iy())),ix()|iy())\",0,0,0,0,2,2,2,0,1,2,0,1,2,5,1,1,2,5,1,0,0,0,0,1,5,0,0,0,255,144,111,122,255,255,255,255,255,0,0,0,255,46,125,89,255,157,156,189,255,255,255,255,255,0,0,0,255,5,122,73,255,144,111,122,255,164,184,218,255,255,255,255,255,0,0,0,0,50,0,12000,0,0,2,2,\"Input Text\",\"Restore Text\",\"Stored Text 2\",\"Color Information\",\"Mapping Information\",0,\"def m_show(m,size = 4,cmap = 'afmhot'):\\n import matplotlib.pyplot as plt\\n from numpy import array\\n cmaps = ['binary','gist_yarg','gist_gray','gray','bone',\\n 'pink','spring','summer','autumn','winter','cool',\\n 'Wistia','hot','afmhot','gist_heat','copper']\\n plt.figure(num = None,figsize=(size,size),dpi=300)\\n plt.axis('off')\\n plot = plt.imshow(array(m),cmap = cmap) #,interpolation='bicubic' )\\n plt.show()\\n plt.close()\\n\\nfrom tqdm import tqdm\\n\\ndef get_matrix_bin(s):\\n n = len(s)\\n mat = [[0]*n for i in range(n)]\\n for x in tqdm(range(0,n)):\\n for y in range(0,n):\\n f = format((s[x] ^ s[y]),'b').count('10')\\n mat[x][y] = f\\n #mat[y][x] = f\\n return mat\\n\\nbig_n = 11\\n\\npows = [i for i in range(0,2**big_n)]\\npows = sorted(pows,key = lambda k: format(k,'b').count('01'))\\nadj_m = get_matrix_bin(pows)\\n\\nm_show(adj_m)\",\"def m_show(m,size = 4,cmap = 'afmhot'):\\n import matplotlib.pyplot as plt\\n from numpy import array\\n cmaps = ['binary','gist_yarg','gist_gray','gray','bone',\\n 'pink','spring','summer','autumn','winter','cool',\\n 'Wistia','hot','afmhot','gist_heat','copper']\\n plt.figure(num = None,figsize=(size,size),dpi=300)\\n plt.axis('off')\\n plot = plt.imshow(array(m),cmap = cmap) #,interpolation='bicubic' )\\n plt.show()\\n plt.close()\\n\\nfrom tqdm import tqdm\\n\\ndef get_matrix_bin(s):\\n n = len(s)\\n mat = [[0]*n for i in range(n)]\\n for x in tqdm(range(0,n)):\\n for y in range(0,n):\\n f = format((s[x] ^ s[y]),'b').count('10')\\n mat[x][y] = f\\n #mat[y][x] = f\\n return mat\\n\\nbig_n = 11\\n\\npows = [i for i in range(0,2**big_n)]\\npows = sorted(pows,key = lambda k: format(k,'b').count('01'))\\nadj_m = get_matrix_bin(pows)\\n\\nm_show(adj_m)\",0,0,2,\"01\",\"10\",\"01\",0,1,2,0,1,2,5,1,1,2,5,1,0,\"xor(min(xor(x(),y()),xor(ix(),iy())),ix()|iy())\",0,0,0,8,8,0,0,1,5,0,0,0,255,144,111,122,255,255,255,255,255,0,0,0,255,46,125,89,255,157,156,189,255,255,255,255,255,0,0,0,255,5,122,73,255,144,111,122,255,164,184,218,255,255,255,255,255,0,0,0,50,0,12000,0" + }, + { + "plain_name": "Logarithmic Distortion", + "full_command": "rep_logpindis_gui 1,50,50,50,50,1,1,1,1,0,0,0,0,0,0,0,2,1024,0,50,50" + }, + { + "plain_name": "Majority", + "full_command": "gui_rep_majority 11,0,5,0,0,0,50,50" + }, + { + "plain_name": "Majority [Threshold]", + "full_command": "gui_rep_majority_threshold 11,0,5,50,1,0,0,0,50,50" + }, + { + "plain_name": "Markus-Lyapunov Fractal", + "full_command": "fx_rep_mlfrac \"ab\",50,1,100,50,50,50,0,0,0,0,255,255,255,255,0,255,0,0,8,8,8,0,12,0,16,0,50,0,8,0,8,0,8,0,0,0,0,\"\",\"\",\"\",8,0,8,0,8,0,0,0" + }, + { + "plain_name": "Mitchell Concatenation", + "full_command": "fx_rep_mitchell_concatenation 0,0,0,1,1,1,0,10,10,10,0,0,0,1,0,1,0,255,255,255,255,243,235,227,255,200,200,136,255,124,143,91,255,53,74,67,255,34,23,36,255,0,0,0,255,206,206,206,255,198,186,182,255,166,135,182,255,120,105,70,255,55,69,48,255,37,33,47,255,24,24,24,255,255,255,255,255,243,236,227,255,186,200,136,255,102,143,91,255,55,53,74,255,36,23,25,255,0,0,0,255,0,1,2,0,100,0,0,0,1,10,0,0,100,8,25,0,50,5,5,3,38,0,0,0,0,0,0,0,1,1,10,10,0,0,255,255,255,255,243,235,227,255,200,200,136,255,124,143,91,255,53,74,67,255,34,23,36,255,0,0,0,255,206,206,206,255,198,186,182,255,166,135,182,255,120,105,70,255,55,69,48,255,37,33,47,255,24,24,24,255,255,255,255,255,243,236,227,255,186,200,136,255,102,143,91,255,55,53,74,255,36,23,25,255,0,0,0,255" + }, + { + "plain_name": "Nebulous", + "full_command": "fx_rep_nebulous 0,4,10,10,0,0,0,1,0,0,1,0,0,0,0,2,0,1,3" + }, + { + "plain_name": "Newton Fractal [MadJik Style]", + "full_command": "rep_mj_newf 16,0,0,128,9,0,75,5,10,50,50,45,0,0,0" + }, + { + "plain_name": "Non-Convolution Edge Extraction", + "full_command": "fx_ncee 0,0,1,100,2,0,0,1,100,0,50,50" + }, + { + "plain_name": "Non-Isometric RPG Tiler (Interactive)", + "full_command": "fx_rep_rpgtiler_noniso 0,0,\"\",32,2,16,16,0,0,0,0,0,0,255,0,45,0,0,1,0,0,\"\",\"placed_tile.png\"" + }, + { + "plain_name": "Ordered Dithering", + "full_command": "fx_rep_loupasc_ordered_dither 4,3,0,0,50,50" + }, + { + "plain_name": "Panel Image", + "full_command": "rep_fx_shift 50,50,2,2,0,50,50" + }, + { + "plain_name": "Perspective Streak", + "full_command": "gui_rep_perspective_streak 50,50,0,100,0,0,0,1,0,50,50" + }, + { + "plain_name": "Pixel Push", + "full_command": "fx_rep_pxpush 50,50,0,50,50" + }, + { + "plain_name": "Point Warp", + "full_command": "gui_rep_pw 100,100,0,50,50,0,3,0,50,50" + }, + { + "plain_name": "Popcorn Fractal", + "full_command": "fx_rep_pfrac 50,1,0.05,3,1,0,50,50,0,1,0,1,2,0,1,2,0,1,2,0,1,0,0" + }, + { + "plain_name": "Popcorn Fractal [Transformative]", + "full_command": "fx_rep_pfrac_t_rs 50,1,0.05,3,0.5,45,50,50,0,0,1,0,0,1,0,0,4,1,0,4,1,0,0,4,1,0,0,1,0,0,4,1,0,4,1,0,0,4,1,0,2,1,0,0,4,1,0,0,0,1,0,0,4,1,0,4,1,0,0,4,1,0,0,1,0,0,4,1,0,4,1,0,0,4,1,0,2,1,0,0,4,1,0,0,1,0,0,4,1,0,4,1,0,0,4,1,0,0,1,0,0,4,1,0,4,1,0,0,4,1,0,2,1,0,0,4,1,100,0,0,0,0.5,0,0" + }, + { + "plain_name": "Premade Palette", + "full_command": "fx_rep_premade_palette 10,1,1,16,12,0,2,0,0,1,\"\",\"color_harmonies\",0,\"Available for Export!\",0,0" + }, + { + "plain_name": "Prime Surface", + "full_command": "gui_rep_prime_surface 0,0" + }, + { + "plain_name": "Pseudorandom Noise", + "full_command": "fx_rep_mj_prn 8,2,0,1,0,1,50,50,1,0,0,0" + }, + { + "plain_name": "Rainbowify", + "full_command": "fx_rep_rainbowify 0,0,100,0,50,50" + }, + { + "plain_name": "Random Gradient Bars", + "full_command": "fx_rep_randgradbar 0,2,0,0,0,50,50,1,0,1,100,0,0,0,0,0,0,255,0,127,255,249,215,45,255,0,1,100" + }, + { + "plain_name": "Random Rectangle Division", + "full_command": "fx_rep_rrd 10,5,5,95,50000,0,35,0,1,12,0,0,0,0,0,0,255" + }, + { + "plain_name": "Rectangle-Square Fill", + "full_command": "fx_rep_rand_sqrrecfill 0,0,15,2,1,1,0,1,1,1,0,0,0" + }, + { + "plain_name": "Thorn Fractal - Secant Sea", + "full_command": "gui_rep_tfrac 0,0,10000,255,3,0,0,1,1,1,1,0,0,0,\"a/sin(b)\",\"b/cos(a)\",\"sin(a)/cos(b)\",\"b/cos(a)\",\"a/sin(b)\",\"b/cos(a+b)\",\"a\",\"b\",\"a\",\"b\",0,1,\"a/(cfb*cos(b))\",\"b/(cfa*sin(a))\",\"cos(vx)/tan(vx)\",\"sin(vy)/tan(vy)\",1,0,0,3,0" + }, + { + "plain_name": "Reverse Digits", + "full_command": "fx_rep_rd 0,0,10,0,0,0,50,50" + }, + { + "plain_name": "Reverse Engineer Color Curve", + "full_command": "gui_rep_recc 10,1,\"\",\"gradient.png\",0,1" + }, + { + "plain_name": "Reverse Engineer Gradient Map", + "full_command": "gui_rep_regm 10,1,0,\"\",\"gradient.png\",0,1" + }, + { + "plain_name": "RGB-Gray Linear Interpolation", + "full_command": "fx_rep_lerp_rgb_gray 0,0,100,100,100,100,100,100,1,1,1,0,50,50" + }, + { + "plain_name": "Rotate by Torus Map", + "full_command": "fx_rep_rbtt 100,50,-180,3,3,7,50,1,50,50,1,0,0,1,2,0,50,50" + }, + { + "plain_name": "Serendipitous Circle", + "full_command": "fx_rep_serendipitous_circle 1000,500,2,2,0,0,0,0,0,0,1,1,0,1,1,0,0,0,1,0.25,0,0,2,2" + }, + { + "plain_name": "Shear", + "full_command": "fx_rep_shear 0,0,\"place_string_here\",45,50,2,2,0,0" + }, + { + "plain_name": "Sinusoidal Water Distortion", + "full_command": "rep_sinowaterdist_gui 0,0,0.5,2,0,0,50,50" + }, + { + "plain_name": "Spiral Distortion", + "full_command": "gui_rep_sd 1,1,0,0,0,0,50,50,0,50,50,1,50,50,100,100,3,4,0,50,50" + }, + { + "plain_name": "Squareroot - Logarithmic Distortion", + "full_command": "rep_sqrlogpindis_gui 1,50,50,50,50,1,1,1,1,0,0,0,0,0,0,0,2,1024,0,50,50" + }, + { + "plain_name": "Statistical Average", + "full_command": "fx_rep_bchstatfunc_average 0,0,0,50,50" + }, + { + "plain_name": "Statistical Mode", + "full_command": "fx_rep_stat_mode 0,0,255,0,255,\"-1\",\"-1\"" + }, + { + "plain_name": "Stitch Distort", + "full_command": "fx_rep_stitch 5,1,0,0,3,0,0,128,128,1,4,1,0,2,2,45,-45,90,0,60,-60,15,-15,30,-30,5,-5" + }, + { + "plain_name": "Strange Bulger", + "full_command": "rep_strbul 0,0,2,0,0,50,50" + }, + { + "plain_name": "Strange Bulger Kaleidoscope", + "full_command": "rep_strbulkal_gui 0,0,1,50,50,50,50,0,0,0,2,1024,0,50,50" + }, + { + "plain_name": "Three-Coupled Oscillators", + "full_command": "fx_rep_tco 50,50,-50,1,0,50,50,1,0,12,6,0,0,1,0,0,1" + }, + { + "plain_name": "Tiled Form", + "full_command": "gui_rep_form_pixel 0,3,0,30,30,100,0,0,0.5,50,0,5,0,2,1,0,10,0,0,100,8,25,0,50,5,5,3,38,0,50,50" + }, + { + "plain_name": "Tiled Zoom", + "full_command": "fx_rep_tz 10,10,2,0,0,50,50" + }, + { + "plain_name": "TR's Intense Filtering", + "full_command": "gui_rep_trif 45,100,0,0,0,50,50" + }, + { + "plain_name": "TR's Pixel Sharpener", + "full_command": "gui_rep_trps 0,0,0,0,0,11,0,50,50" + }, + { + "plain_name": "Transfer Color [Reduced Colors]", + "full_command": "fx_rep_transfer_color_reduced 0,50,0,50,0,0,0,4,4,4,4,0,2,2,2,2,0,18,0,\"\",0,8,8,0,0,1,0,0,247,244,191,255,0,0,255,240,43,255,0,0,255,207,5,255,0,0,255,177,8,255,0,0,233,134,39,255,0,0,191,90,62,255,0,0,156,51,39,255,0,0,114,28,3,255,0,0,255,226,207,255,0,0,212,174,170,255,0,0,181,139,148,255,0,0,173,121,132,255,0,0,145,96,106,255,0,0,119,83,91,255,0,0,94,65,74,255,0,0,73,33,41,255,0,0,131,147,195,255,0,0,108,130,196,255,0,0,82,116,197,255,0,0,81,101,174,255,0,0,61,80,131,255,0,0,45,61,114,255,0,0,40,51,93,255,0,0,38,36,80,255,0,0,209,189,254,255,0,0,186,171,247,255,0,0,169,150,236,255,0,0,149,133,241,255,0,0,121,100,186,255,0,0,88,74,127,255,0,0,60,49,81,255,0,0,29,29,33,255,0,0,253,247,134,255,0,0,255,213,155,255,0,0,235,189,157,255,0,0,213,163,154,255,0,0,185,140,147,255,0,0,151,116,136,255,0,0,118,93,115,255,0,0,85,71,105,255,0,0,109,204,255,255,0,0,85,177,241,255,0,0,64,151,234,255,0,0,20,118,192,255,0,0,16,93,162,255,0,0,7,72,124,255,0,0,3,49,95,255,0,0,0,27,64,255,0,0,224,250,235,255,0,0,169,209,193,255,0,0,138,193,150,255,0,0,135,174,142,255,0,0,113,149,125,255,0,0,91,123,105,255,0,0,71,101,90,255,0,0,45,75,71,255,0,0,244,163,128,255,0,0,215,147,116,255,0,0,191,126,99,255,0,0,169,109,88,255,0,0,148,93,79,255,0,0,120,76,73,255,0,0,83,57,58,255,0,0,55,36,35,255,0,0,127,189,57,255,0,0,120,158,36,255,0,0,107,132,45,255,0,0,88,113,44,255,0,0,76,95,51,255,0,0,57,77,60,255,0,0,46,61,71,255,0,0,29,44,67,255,0,0,254,223,177,255,0,0,207,175,142,255,0,0,179,151,131,255,0,0,145,122,123,255,0,0,117,104,110,255,0,0,86,80,111,255,0,0,59,56,85,255,0,0,38,35,61,255,0,0,255,246,79,255,0,0,232,210,75,255,0,0,209,170,57,255,0,0,186,136,46,255,0,0,158,101,32,255,0,0,133,79,18,255,0,0,117,59,9,255,0,0,98,42,0,255,0,0,208,204,50,255,0,0,180,170,51,255,0,0,150,154,38,255,0,0,124,131,30,255,0,0,97,115,8,255,0,0,73,93,0,255,0,0,47,79,8,255,0,0,32,41,0,255,0,0,229,154,124,255,0,0,210,141,122,255,0,0,193,126,122,255,0,0,172,111,110,255,0,0,152,89,90,255,0,0,124,75,71,255,0,0,99,52,50,255,0,0,73,37,28,255,0,0,255,205,255,255,0,0,255,166,197,255,0,0,255,125,175,255,0,0,248,93,128,255,0,0,217,74,105,255,0,0,159,59,82,255,0,0,113,43,59,255,0,0,67,23,41,255,0,0,220,212,255,255,0,0,184,174,255,255,0,0,156,155,239,255,0,0,142,140,226,255,0,0,120,119,193,255,0,0,100,101,157,255,0,0,74,82,128,255,0,0,50,53,88,255,0,0,237,212,147,255,0,0,237,182,124,255,0,0,206,151,112,255,0,0,189,125,100,255,0,0,167,96,87,255,0,0,144,70,71,255,0,0,110,36,52,255,0,0,95,9,38,255,0,0,251,234,163,255,0,0,232,203,130,255,0,0,204,169,110,255,0,0,178,144,98,255,0,0,153,121,81,255,0,0,126,97,68,255,0,0,97,74,60,255,0,0,69,49,37,255,0,0,0,222,218,255,0,0,0,191,163,255,0,0,0,160,135,255,0,0,0,130,121,255,0,0,0,107,109,255,0,0,0,81,98,255,0,0,0,64,81,255,0,0,0,46,73,255,0,0,248,198,218,255,0,0,219,153,191,255,0,0,193,120,170,255,0,0,185,109,145,255,0,0,151,84,117,255,0,0,102,54,89,255,0,0,73,40,61,255,0,0,46,16,38,255,0,0,221,191,154,255,0,0,192,165,136,255,0,0,158,138,110,255,0,0,126,108,84,255,0,0,114,90,81,255,0,0,94,70,70,255,0,0,74,53,60,255,0,0,49,34,42,255,0,0,255,250,171,255,0,0,236,197,129,255,0,0,216,159,117,255,0,0,199,130,108,255,0,0,174,107,96,255,0,0,138,82,88,255,0,0,90,60,69,255,0,0,59,48,60,255,0,0,235,240,246,255,0,0,186,199,219,255,0,0,171,174,190,255,0,0,132,135,149,255,0,0,115,115,127,255,0,0,91,92,105,255,0,0,72,71,77,255,0,0,45,49,54,255,0,0,255,219,255,255,0,0,255,187,199,255,0,0,255,155,168,255,0,0,255,118,118,255,0,0,228,92,95,255,0,0,182,60,53,255,0,0,130,33,29,255,0,0,94,7,17,255,0,0,145,218,161,255,0,0,85,182,125,255,0,0,73,137,96,255,0,0,65,116,85,255,0,0,50,92,64,255,0,0,56,81,64,255,0,0,47,63,56,255,0,0,26,51,44,255,0,0,116,245,253,255,0,0,82,210,255,255,0,0,65,178,227,255,0,0,49,142,184,255,0,0,54,107,138,255,0,0,37,70,107,255,0,0,35,50,77,255,0,0,24,31,47,255,0,0,166,204,52,255,0,0,125,164,45,255,0,0,81,136,34,255,0,0,47,105,12,255,0,0,34,89,24,255,0,0,23,74,27,255,0,0,0,50,33,255,0,0,0,34,25,255,0,0,198,236,255,255,0,0,199,214,255,255,0,0,150,178,217,255,0,0,134,144,178,255,0,0,122,119,153,255,0,0,97,95,132,255,0,0,58,69,104,255,0,0,40,43,74,255,0,0,255,233,73,255,0,0,255,188,78,255,0,0,249,155,78,255,0,0,227,120,64,255,0,0,205,94,70,255,0,0,182,77,70,255,0,0,148,54,58,255,0,0,102,43,41,255,0,0,136,214,255,255,0,0,36,174,214,255,0,0,50,140,167,255,0,0,0,111,137,255,0,0,11,102,127,255,0,0,0,77,94,255,0,0,0,56,80,255,0,0,0,39,53,255,0,0,255,206,127,255,0,0,251,170,132,255,0,0,213,141,107,255,0,0,173,110,81,255,0,0,154,98,76,255,0,0,136,80,65,255,0,0,115,61,59,255,0,0,88,49,38,255,0,0,255,243,214,255,0,0,234,219,201,255,0,0,204,195,177,255,0,0,187,175,164,255,0,0,174,161,137,255,0,0,158,140,121,255,0,0,133,117,101,255,0,0,98,93,84,255,0,0,245,247,250,255,0,0,205,210,218,255,0,0,166,174,186,255,0,0,130,139,152,255,0,0,98,104,113,255,0,0,67,69,73,255,0,0,34,35,35,255,0,0,0,0,0,255,0,0,0,0,1,1,1,0,1,0,3,0,2,50,0,0,0,3,\"Here is where you copy command to command line interface.\",\"\",0,1,\"Initialized GUI Filter!\",0,255,255,255,255,0,50,50" + }, + { + "plain_name": "Trigonometry Mapping", + "full_command": "fx_rep_tg3 0,0,1,0,0,0,0,0,0,0,0,1,0,1,1,1,1,0,1,0,1,1,1,1,0,1,0,1,1,1,1,0,50,50" + }, + { + "plain_name": "Tupper's Self-Referential Formula", + "full_command": "fx_rep_self_referential_formula 1,1,0,0,\"0\",\"0\",\"0\",\"0\",0,1,1,\"1\",\"1\",1,1,1,1,0" + }, + { + "plain_name": "Vibrance [YCH]", + "full_command": "fx_rep_vibrance_ych 30,0,50,50" + }, + { + "plain_name": "Vibrato", + "full_command": "fx_vibrato 0,1,1,1,1,1,1,1,1,0.85,0.85,1,1,1,0,0,0.7,0,0,100,1,1,1,1,1,0.85,0.85,1,1,1,0,0,0.7,0,0,100,1,1,1,1,1,0.85,0.85,1,1,1,0,0,0.7,0,0,100,1,1,1,1,1,0.85,0.85,1,1,1,0,0,0.7,0,0,100,1,1,0,1,1,0.85,0.85,1,1,1,0,0,0.7,1,0,100,1,1,0" + }, + { + "plain_name": "Weighted RGB To Grayscale", + "full_command": "fx_rep_w_rgb82gray 33.33,33.33,33.33,1,0,0,0,0,0,0,50,50" + }, + { + "plain_name": "Z-Time", + "full_command": "fx_rep_z_render 0,255,0,0" + }, + { + "plain_name": "Plasma Transition", + "full_command": "plasma_transition 0.5,5,1,42" + }, + { + "plain_name": "RandomWaves", + "full_command": "randomwaves 84,80,1.2,42" + }, + { + "plain_name": "Auto-Adjust Orientation", + "full_command": "fx_adjust_orientation 5" + }, + { + "plain_name": "Blur [Quad]", + "full_command": "fx_blur_quad 0,5,0,0,0,1,100,40,25,60,25,95,90,5,90" + }, + { + "plain_name": "A-Color", + "full_command": "fx_apply_Labcurve 0,-1,128,-1,128,-1,128,-1,128,-1,128,255,1,0,0" + }, + { + "plain_name": "B-Color", + "full_command": "fx_apply_Labcurve 0,-1,128,-1,128,-1,128,-1,128,-1,128,255,1,0,0" + }, + { + "plain_name": "Lightness", + "full_command": "fx_apply_Labcurve 0,-1,128,-1,128,-1,128,-1,128,-1,128,255,1,0,0" + }, + { + "plain_name": "Blue", + "full_command": "fx_apply_RGBcurve 0,-1,128,-1,128,-1,128,-1,128,-1,128,255,1,0,0" + }, + { + "plain_name": "Green", + "full_command": "fx_apply_RGBcurve 0,-1,128,-1,128,-1,128,-1,128,-1,128,255,1,0,0" + }, + { + "plain_name": "Red", + "full_command": "fx_apply_RGBcurve 0,-1,128,-1,128,-1,128,-1,128,-1,128,255,1,0,0" + }, + { + "plain_name": "Blue Chrominance", + "full_command": "fx_apply_YCbCrcurve 0,-1,128,-1,128,-1,128,-1,128,-1,128,255,1,0,0" + }, + { + "plain_name": "Luminance", + "full_command": "fx_apply_YCbCrcurve 0,-1,128,-1,128,-1,128,-1,128,-1,128,255,1,0,0" + }, + { + "plain_name": "Red Chrominance", + "full_command": "fx_apply_YCbCrcurve 0,-1,128,-1,128,-1,128,-1,128,-1,128,255,1,0,0" + }, + { + "plain_name": "For Littbarski", + "full_command": "fx_for_littbarski \"\",50,1" + }, + { + "plain_name": "Fourier Transform [Old]", + "full_command": "fx_fourier_old 0,1" + }, + { + "plain_name": "Frame [Round] Old", + "full_command": "fx_frame_round_old 6,20,0.1,0,255,255,255,255,0,0.1,3" + }, + { + "plain_name": "Graduated Color Accent", + "full_command": "fx_gca 255,255,255,255,1,0,0,0" + }, + { + "plain_name": "Layer Info", + "full_command": "gui_layer_info 1" + }, + { + "plain_name": "Patrick RGB", + "full_command": "pat_rgb 0,0,0,0,0" + }, + { + "plain_name": "Shaded Segmentation", + "full_command": "dt_segment_shaded 1,0.7,1" + }, + { + "plain_name": "Stereo to Anaglyph", + "full_command": "fx_stereo_to_anaglyph 2,0" + }, + { + "plain_name": "Transfer Colors [Histogram]", + "full_command": "fx_transfer_histogram 0,0,1,1,0,50,50" + }, + { + "plain_name": "Transfer Colors [PCA]", + "full_command": "fx_transfer_pca 0,0,1,1,0,50,50" + }, + { + "plain_name": "Annular Steiner Chain Round Tile", + "full_command": "Annular_Steiner_Chain_Round_Tile 800,1,0,0,100,0,100,12,0,1,0,0,0,255,0,255,255,0,127,0,0,255,127,0" + }, + { + "plain_name": "Bulles Colorees", + "full_command": "samj_Bulles_Colorees 64,64,64,255,8,0,0,3,0,0,0,0,0,0,0,0,255" + }, + { + "plain_name": "Carres Noirs", + "full_command": "samj_Carres_Noirs 128,40,7,0,0,0,0,255,2,96,96,96,255,2,255,255,255,255,0,2,0" + }, + { + "plain_name": "Cercles Concentriques", + "full_command": "Cercles_Concentriques_A 800,1,6,0,0,90,1,1,50,1,1,0,0,0,255,0,0,0,0,5,0,0,0,255,255,255,255,0,255,255,0,0,255,0,255,255,255,255,0,255,255,0,1,0,5,0,0" + }, + { + "plain_name": "Coeurs Hearts 002", + "full_command": "samj_Coeurs_Hearts_002 16,100,0,0,1,0,255,255,255,255,0,0,0,1,1" + }, + { + "plain_name": "Deconstruction", + "full_command": "samj_Tiles_Deconstruction 63,0,0,0,0,64" + }, + { + "plain_name": "Ellipses Colorees", + "full_command": "samj_Ellipses_Colorees 64,64,64,255,8,8,0,0,0,0,0,255" + }, + { + "plain_name": "Filters On Tiles", + "full_command": "samj_Filtres_Sur_Tuiles 20,0,\"shift 2,2,0,0,0 mirror y\",\"dilate 20\"" + }, + { + "plain_name": "Filters On Tiles V2", + "full_command": "samj_Filtres_Sur_Tuiles_V2 40,1,\"dilate 3 shift 1,1,0,0,0\",0,0,3,\"pow 1.5 n 0,255\"" + }, + { + "plain_name": "Floutage Blurring", + "full_command": "samj_Flouter 0,0,0,10,0,0,1" + }, + { + "plain_name": "Losanges Colores", + "full_command": "samj_Losanges_Colores 64,64,64,255,8,0,0,0,1.5,0,1,0,0,0,0,0,255,0" + }, + { + "plain_name": "Moirage Spline", + "full_command": "samj_Moirage_Spline 0,0,0,255,8,0,-50,50,-50,50,0,0,0,0,0,255,8,0,-50,50,-50,50,0,0" + }, + { + "plain_name": "Moirage Spline XY", + "full_command": "samj_Moirage_Spline_XY 0,0,0,255,8,0,-50,50,-50,50,0,0,0,0,255,8,0,-50,50,-50,50,0,0" + }, + { + "plain_name": "Montage 1 Page", + "full_command": "samj_dt_montage_sur_une_page 1200,1200,2,5,0" + }, + { + "plain_name": "Montage Annular Steiner Chain", + "full_command": "samj_Montage_Annular_Steiner_Chain 2400,12,1,0,0,0,0,0,0,1,0,0,90,1,100,0,1,0,0" + }, + { + "plain_name": "Montage Cercle Spirale", + "full_command": "samj_Montage_Cercle_Spirale 2400,8,0,1,0,0,0,0,0" + }, + { + "plain_name": "Montage Geometric Figures", + "full_command": "samj_Montage_Figures_Geometriques 4800,0,0,1,0,0,0,0,1,0,0,0,1,10,255,255,255,255,6,30,1,-3,300,270" + }, + { + "plain_name": "Montage Multi Rows", + "full_command": "samj_montage_multi_rows_GUI 4,2,0,1,2400,2,2,0,0" + }, + { + "plain_name": "Montage Pappus Chain", + "full_command": "samj_Montage_Pappus_Chain 1200,0,1,0,35,100,0,0,255,255,255,255,0,0,0,0" + }, + { + "plain_name": "Montage Row", + "full_command": "samj_montage_row_GUI 8,0,1,2400,2,2,0,0,0,1,0" + }, + { + "plain_name": "Montage Zigzag", + "full_command": "samj_Montage_Zigzag 4800,8,1,256,0,0,0,0,0,0" + }, + { + "plain_name": "Pixelisation Contours", + "full_command": "samj_Pixelisation_Contours 0.5,0,20,8,0,0,1,0,10,0.8" + }, + { + "plain_name": "Pointes De Diamants Colorees", + "full_command": "samj_Pointes_De_Diamants_Colorees 64,64,64,255,8,0,0,1.5,0,0,0,0,0,0,0,255,0" + }, + { + "plain_name": "Reptile", + "full_command": "samj_reptile 0,64,25,2,0,40,1" + }, + { + "plain_name": "Scintillements Colores", + "full_command": "samj_Scintillements_Colores 64,64,64,255,8,8,1,768,12,0,0,0,0,0,0,0,255,0" + }, + { + "plain_name": "Angoisse Anguish", + "full_command": "samj_Angoisse 1,5,0,5,100,2,4,1,250" + }, + { + "plain_name": "Barbouillage Paint Daub", + "full_command": "samj_Barbouillage_Paint_Daub 2,2,100,0.2,1,4,1,0,8" + }, + { + "plain_name": "Chalk It Up [Fr]", + "full_command": "samj_chalkitup 5,2.5,1.5,50,1,5,5,0,0,7,0.8,1.9,7,0" + }, + { + "plain_name": "Color Edges Engrave", + "full_command": "samj_Color_EdgesO_Engrave 0,50,9,1,2,50,0,8,40,0,0,1,0,0,0" + }, + { + "plain_name": "Contour Drawings", + "full_command": "samj_Contour_Drawings_en 5,0,2,0,0,5,10,0.8,0,1.1,10,0,1" + }, + { + "plain_name": "Contour Epais", + "full_command": "samj_Contour_Epais 1,0,5,1,5,5,10,0.8,2,1" + }, + { + "plain_name": "Couleurs Rayees", + "full_command": "samj_Couleurs_Rayees 0,30,0,100,4,4,0,2,0.7,0" + }, + { + "plain_name": "Couleurs Rayees 2", + "full_command": "samj_Couleurs_Rayees_2 0,30,0,100,4,4,255,1" + }, + { + "plain_name": "Cubisme A", + "full_command": "samj_Test_Cubisme_A 1,120,70,1,30,30,2,0,6,0,1,300,8,10,10,20,1,1,5,1,1,64,25,8,1,0" + }, + { + "plain_name": "Cubisme B", + "full_command": "samj_Test_Cubisme_B 11,6,0,30,40,17,6,0,0,0,0,3,1,1,64,25,8,1,0" + }, + { + "plain_name": "Diff Tensors Blend", + "full_command": "samj_Diff_Tensors_Blend 10,5,1,0.15,1,0,3,1,0,3,1" + }, + { + "plain_name": "Edges And LIC", + "full_command": "samj_Edges_And_LIC 0,200,0,0,0,15,8,127,255,0,0,1,20,0.2,0,14,1" + }, + { + "plain_name": "Flamboyance Test", + "full_command": "samj_Flamboyance_Test 65,28,9.25,0.3,0,1,1.1,10,12,2,0,0,1,0,150,0.42,0.85,0.6,7.83,0.68,19,2.65,0,1,1,3,200,20,0.1,1.5,8,1,3,1,0,20,0,0,0,0" + }, + { + "plain_name": "Fond Broderie", + "full_command": "samj_fond_broderie 8,2,0,1,1" + }, + { + "plain_name": "Fond Brosse", + "full_command": "samj_Fond_Brosse 3,1" + }, + { + "plain_name": "Fx Sketchbw Modifie", + "full_command": "samj_fx_sketchbw_modifie 3,45,180,30,1.75,0.02,0.5,0.75,0.1,0.7,3,6,0,1,4,0,1234,0,2,100,0.2,1,4,1,0" + }, + { + "plain_name": "Granular Texture", + "full_command": "samj_Texture_Granuleuse 0,20,80,0,0" + }, + { + "plain_name": "Gris Raye", + "full_command": "samj_Gris_Raye 0,30,0,100,4,4,255,1" + }, + { + "plain_name": "Hallucinogen", + "full_command": "samj_Hallucinogen 80,2,80,1.5,2,0,0,0,1,80,8" + }, + { + "plain_name": "Hallucinogen 2", + "full_command": "samj_Hallucinogen_b 1,300,10,10,10,10,80,2,80,1.5,2,0,0,1,1,80,8,1,0,14,1" + }, + { + "plain_name": "Impressions", + "full_command": "samj_Impressions 10,5,5,1,1,0,2,0,1,5,0,5,100,2,4,1,250,1.2" + }, + { + "plain_name": "Isophotes Vers Aquarelle", + "full_command": "samj_Isophotes_Vers_Aquarelle 16,0.5,4,0,1,10,1,0,0,0,0,1,10,10,4,3,251,237,206,255,1" + }, + { + "plain_name": "Plasmic", + "full_command": "samj_Plasmic 0,1.1,2,40,0,0,0,0" + }, + { + "plain_name": "Plasmic V2", + "full_command": "samj_Plasmic_V2 2,4,10,2,0.02,8,0,0,0,0,0,0,255" + }, + { + "plain_name": "Pointillisme", + "full_command": "samj_Pointillisme 10,2,5,1,1,1,0,0,0,255" + }, + { + "plain_name": "Pointillisme B", + "full_command": "samj_Pointillisme_B 1,0,90,3,1,1,0,0,0,255" + }, + { + "plain_name": "Posterize B", + "full_command": "samj_Posterize_B 1,12,1,0,40,30,1,0,0,0,0,1,0,0,0,0,0,0" + }, + { + "plain_name": "Samj Ripple Houghsketchbw", + "full_command": "samj_ripple_houghsketchbw 2,100,50,1,45,0,10,5,80,0.1,100,1,17,1,0,0" + }, + { + "plain_name": "Skeletik", + "full_command": "samj_Test_Skeletik 10,1,0,0,0,3,1,0,0,0,255" + }, + { + "plain_name": "Tensor Test", + "full_command": "samj_TensorTest 0.3,0.9,0.6,1.1,0,0,20,32,20,2,1,0,2" + }, + { + "plain_name": "Texture Coloree", + "full_command": "samj_texture_coloree 0,0.7,200,125,50,255,5,5,45,200,4,0.2" + }, + { + "plain_name": "Variations on a Single Color", + "full_command": "samj_texture_coloree_en 0,0.7,200,125,50,255,5,5,45,200,4,0.2,1,10,1,1" + }, + { + "plain_name": "Colored Engraving", + "full_command": "Engrave_colore 0,0.5,4,0,8,40,0,25,1,2,0,0,0,255,255,255,255,255" + }, + { + "plain_name": "Engrave Modifie", + "full_command": "engrave_modifie 0,0.5,4,0,8,40,0,25,1" + }, + { + "plain_name": "Grid BW Color", + "full_command": "samj_Grid_BW_Color 3,0,1,4,4,32,1,2,0,32" + }, + { + "plain_name": "Hard Sketch XY", + "full_command": "XY_hardsketchbw_samj 0.2,300,50,1,0.1,20,0,0,0,0,180,40,160,255,0" + }, + { + "plain_name": "Masques B&W Masks", + "full_command": "samj_Masques_Noir_Et_Blanc 3,50" + }, + { + "plain_name": "NB Edges Engrave", + "full_command": "samj_NB_EdgesO_Engrave 0,50,9,1,2,50,0,8,40,0,0,1" + }, + { + "plain_name": "Scintillements", + "full_command": "samj_scintillements 0,5,0,1,20,2,6,20,5,45,2,6,5,20,1,7,0,0" + }, + { + "plain_name": "64 Couleurs Max", + "full_command": "samj_64_Couleurs_Max 9,4,2,50,1,0,240,240,40,255,120,40,240,255" + }, + { + "plain_name": "9 Colors", + "full_command": "samj_test_9_colors 70,17,10,255,134,35,20,255,154,27,58,255,186,61,89,255,220,103,129,255,239,151,169,255,246,194,205,255,253,201,212,255,255,255,255,255,0,0" + }, + { + "plain_name": "At06A 2017 VarCouleurs", + "full_command": "samj_At06A_2017_VarCouleurs 1,0,100,0,0" + }, + { + "plain_name": "CeKoaSa 013", + "full_command": "samj_CeKoaSa_013 1,1,1,1,0,1,0,1,0,1,0,1,0,1,0,0" + }, + { + "plain_name": "Couleurs Metalliques", + "full_command": "Couleurs_Metalliques 0,0,22,0,0,0,0,6,5,20,1,0,0,0,0.3,60,1,1,0" + }, + { + "plain_name": "Dorure Gilding", + "full_command": "samj_Dorure 0.4,0.2,0.2,0,1,20,20,0,0.5,0,60,0,0,100,45,18,32,1" + }, + { + "plain_name": "Samj Remplir Fill Flood", + "full_command": "samj_Remplir_Fill_Flood 50,50,255,0,0,255,20" + }, + { + "plain_name": "Samj Test Shapeprevalent", + "full_command": "samj_test_shapeprevalent 2,32,50" + }, + { + "plain_name": "Samj Topographie Eliminate Contour Lines", + "full_command": "samj_Topographie_Eliminate_Contour_Lines 10,152,197,242,255,10,114,182,239,255,90,92,95,98,255,30,133,164,196,255,10,120,143,166,255,10,22,0,245,255,60,1,0" + }, + { + "plain_name": "Valeur Moyenne LCH", + "full_command": "samj_Valeur_Moyenne_LCH 400,14,4,\"\",\"samj_Valeur_Moyenne_LCH.txt\"" + }, + { + "plain_name": "Variations RVB", + "full_command": "samj_Variations_RVB 50,50,0,6,0,0,180,90,45,255,0,1,0" + }, + { + "plain_name": "Carte De Repoussage", + "full_command": "samj_Carte_De_Repoussage 30,1,0,0" + }, + { + "plain_name": "Colored Outlines", + "full_command": "samj_Colored_Outlines 0,2,8,0,0,0,0,0,255" + }, + { + "plain_name": "Coloriage", + "full_command": "samj_Coloriage 612,255,2,6,2,0,0,0,255,0" + }, + { + "plain_name": "Contours Arrondis", + "full_command": "samj_Contours_Arrondis 1,3,5,10,0,0" + }, + { + "plain_name": "Contours Blancs", + "full_command": "samj_Contours_Blancs 1,16,2,0,0.5,0,100,0,3,2,1,0,0,0,15,4,1,0" + }, + { + "plain_name": "Contours Coins Vifs", + "full_command": "samj_Contours_Coins_Vifs 20,20,2,0,0.05,0,0,0,0,0,0" + }, + { + "plain_name": "Contours Colores", + "full_command": "samj_Contours_Colores 1.1,2,40,0,0" + }, + { + "plain_name": "Edges Offsets Dots", + "full_command": "samj_Edges_Offsets_Dots 1.3,40,18,2,4,0,0,0,0,0" + }, + { + "plain_name": "Quelques Isophotes", + "full_command": "samj_Quelques_Isophotes 10,10,1,0.02,8" + }, + { + "plain_name": "Quelques Isophotes B", + "full_command": "samj_Quelques_Isophotes_B 16,100,0,0,4" + }, + { + "plain_name": "Quelques Isophotes C", + "full_command": "samj_Quelques_Isophotes_C 0,0,160,0,80,6,4,1,1,0,20,45,0.7,20" + }, + { + "plain_name": "Samj Shapeprevalent Contours", + "full_command": "samj_shapeprevalent_contours 4,0,200,32,8,4,50,1,1,2,1,0,0" + }, + { + "plain_name": "Scintillements Colores Contours", + "full_command": "samj_Scintillements_Colores_Contours 0,8,0,8,8,1,768,12,0,0,0,0,0,0,0,255" + }, + { + "plain_name": "Skeletation", + "full_command": "samj_Skeletation 2,100,100,0,0,1" + }, + { + "plain_name": "Test Mauvais Contours", + "full_command": "samj_Test_Mauvais_Contours 0,0,0,2,1,0,255,0,255,0,0,3,1" + }, + { + "plain_name": "Beigne Donut", + "full_command": "samj_Beigne 100,0,0,0,0,0,0,0,20,20,255,255,255,255,0" + }, + { + "plain_name": "Cercle Polaire", + "full_command": "samj_Cercle_Polaire 1,0,0,1,0,0,2,0,0,0,50,50" + }, + { + "plain_name": "Ecraser Etirer", + "full_command": "samj_Ecraser_Etirer 12,0,0,0,100,0" + }, + { + "plain_name": "Ecraser Etirer V2", + "full_command": "samj_Ecraser_Etirer_V2 12,0,0,100,50,0" + }, + { + "plain_name": "Random Small Deformations", + "full_command": "samj_Random_Small_Deformations 10,5,3" + }, + { + "plain_name": "Random Small Deformations B", + "full_command": "samj_Random_Small_Deformations_B 10,5,3,0" + }, + { + "plain_name": "Samj Deformation 20230712", + "full_command": "samj_deformation_20230712 6,6,0.25,1,1" + }, + { + "plain_name": "Deteriorated Areas", + "full_command": "samj_Zones_Grises 3,0,3,4,1" + }, + { + "plain_name": "Ellipses Inpaint", + "full_command": "samj_Ellipses_Inpaint 0,0,0,255,8,8,2,0,10" + }, + { + "plain_name": "Image Segments Degrades", + "full_command": "samj_Image_Segments_Degrades 2000,5,1,0,0,0,0,255,1234,0,0" + }, + { + "plain_name": "Image Vers Segments", + "full_command": "samj_Image_Vers_Segments 1500,5,1,0,0,0,0,255,1234,0" + }, + { + "plain_name": "Path Et Solidify", + "full_command": "samj_Degradations_Path_Solidify 0,0,0,0,0,2,10,1,0,0,1,75,0,20" + }, + { + "plain_name": "Random Plasma", + "full_command": "samj_Random_Plasma 0,80" + }, + { + "plain_name": "Samj Bruit Noise", + "full_command": "samj_bruit_noise 0,0.75,0,0" + }, + { + "plain_name": "Samj Rotate Flip Image", + "full_command": "samj_rotate_flip_image 1,-45,2,0,1,0,0,0,255,255,255,255" + }, + { + "plain_name": "Samj Selection Ellipse", + "full_command": "samj_Selection_Ellipse 50,50,30,20,0,0,0,0,0,2,255" + }, + { + "plain_name": "Samj Selection Hermite Spline", + "full_command": "samj_Selection_Hermite_Spline 0" + }, + { + "plain_name": "Samj Selection Polygone", + "full_command": "samj_Selection_Polygone 8,3,3,50,20,97,3,80,50,97,97,50,80,3,97,20,50,0,0,0,2,255" + }, + { + "plain_name": "Samj Selection Rectangle", + "full_command": "samj_Selection_Rectangle 50,50,50,40,0,0,0,0,0,2,255" + }, + { + "plain_name": "Samj Selection Spline Rounded", + "full_command": "samj_Selection_Spline_Rounded 20,1,80,20,95,50,97,97,50,95,20,80,25,40,3,3,40,25,0,0,0,0,2,255" + }, + { + "plain_name": "Samj Shapeprevalent Degradations", + "full_command": "samj_shapeprevalent_degradations 2,200,20,64,8,4,50,1,0" + }, + { + "plain_name": "Antialias Wavelet", + "full_command": "samj_Antialias_Wavelet 40,0,127,255,1,60,1,1,1" + }, + { + "plain_name": "Sharpen [Wavelet]", + "full_command": "samj_Wavelet_Sharpen_Test_en 0,0" + }, + { + "plain_name": "Wavelet Sharpen Test", + "full_command": "samj_Wavelet_Sharpen_Test 1" + }, + { + "plain_name": "At06B 2017 Frame Painting", + "full_command": "samj_At06A_2017_frame_painting 10,0.4,6,127,127,127,255,2,400,50,10,1,0.5,123456,35,1,1,1,0,100" + }, + { + "plain_name": "Ombre Portee", + "full_command": "samj_Ombre_Portee 0,0,0,128,0,0,0,0,255,127,127,127,255,2,2,255,255,255,255,0.1" + }, + { + "plain_name": "Ombre Portee B", + "full_command": "samj_Ombre_Portee_B 16,128,0,1,16,1,0,0,127,127,127,255,2,2,2,2,255,255,255,255" + }, + { + "plain_name": "Ombre Portee C", + "full_command": "samj_Ombre_Portee_C 32,8,16,192,0,1,16,1,0,0,96,96,96,255,2,2,2,2,255,255,255,255" + }, + { + "plain_name": "Ombre Portee D", + "full_command": "samj_Ombre_Portee_D 16,64,64,2,1,16,5,1,-32,4,1,2,2,2,255,255,255,255" + }, + { + "plain_name": "Posterize Relief", + "full_command": "samj_Posterize_Relief 1,12,20,0,40,30,1,0,0.4,0,1,15,60" + }, + { + "plain_name": "Contours Gros Pixels", + "full_command": "samj_Contours_Gros_Pixels 1,8,0,20,20,16,1.1,0,0,15,0,0,0,1" + }, + { + "plain_name": "Degrades HSL TSL", + "full_command": "samj_Degrades_HSL_TSL 4,800,240,240,40,255,120,40,240,255,0,0,0,360,100,100,0,0,0,718,75,100,0,100,0,0,0,0" + }, + { + "plain_name": "Denim Texture", + "full_command": "Denim_samj 5,2,0,40,40,25,50,0,43,108,126,255" + }, + { + "plain_name": "EPPE Transform", + "full_command": "samj_EPPE_Transform 50,50,0,10,10,32,0.1,10,18,0,255,255,255,255,3,0,0.1" + }, + { + "plain_name": "Formes Couleurs Variees Dans Image", + "full_command": "samj_Formes_Couleurs_Variees_Dans_Image 0,0,0,0,0,192,128,64,255,1,1,1,0,0,127,255,0,0,0,0,1" + }, + { + "plain_name": "Lignes H Ou V Colorees", + "full_command": "samj_Lignes_H_ou_V_Colorees 159,190,195,255,55,67,140,255,54,40,39,255,140,81,88,255,207,175,190,255,220,202,196,255,170,186,192,255,130,149,139,255,112,96,96,255,237,168,138,255,220,199,205,255,234,217,219,255,255,256,256,1,0,0" + }, + { + "plain_name": "Marbre Marble", + "full_command": "samj_Marbre 1,1,8,5,0.2,0,0,0,140,120,220,255,0,3,1" + }, + { + "plain_name": "Mosaic A", + "full_command": "samj_Mosaic_A 20,3,1,0,0,0" + }, + { + "plain_name": "Mosaic B", + "full_command": "samj_Mosaic_B 30,400,1,100,1,1,0,0,0" + }, + { + "plain_name": "Motif Plasma", + "full_command": "samj_Motif_Plasma 2,20,20,30,1,75,0" + }, + { + "plain_name": "Motifs 7200", + "full_command": "samj_Motifs_7200 2,0,20,20,30,1,75,0,0,255,0,221,255,0,0,0" + }, + { + "plain_name": "Motifs 7200 Variante A", + "full_command": "samj_Motifs_7200_VarianteA 2,0,20,20,30,1,75,0,0,255,0,221,255,0,0,0" + }, + { + "plain_name": "Motifs 7200 VarianteB", + "full_command": "samj_Motifs_7200_VarianteB 4,0,0,3,45,180,30,0.75,0.02,0.5,1.5,0.1,1,10,10,1,1,4,48,4,1,1" + }, + { + "plain_name": "Motifs 7200 VarianteC", + "full_command": "samj_Motifs_7200_VarianteC 4,32,64,32,1,5,255,0,221,255,0,0,0,0,0,240,40,160,255,240,240,40,255,0" + }, + { + "plain_name": "Motifs Aleatoires Symetriques Degrades", + "full_command": "samj_Motifs_Aleatoires_Symetriques_Degrades 1,400,4,1,1,1" + }, + { + "plain_name": "Motifs Degrades CIE", + "full_command": "samj_Degrades_XYZ_CIE 6,800,240,240,40,255,120,40,240,255,0,0,0,100,64,64,0,0,1,0,100,-128,128,-128,128,0,11,0,0" + }, + { + "plain_name": "Perpendicular Lines", + "full_command": "samj_Lignes_Perpendiculaires 255,255,255,255,10,1,2,1234,5678,0,0,1" + }, + { + "plain_name": "Points Aleatoires 001", + "full_command": "samj_Points_Aleatoires_001 10,255,255,0,255,3,0,1" + }, + { + "plain_name": "Pouring", + "full_command": "samj_pouring 0,1,0,0" + }, + { + "plain_name": "Pseudo Vitrail", + "full_command": "samj_Pseudo_Vitrail 0,40,0,0,2,0,0,0,255,0,0" + }, + { + "plain_name": "Quickly Create Colorful Patterns", + "full_command": "samj_Motifs_Rapides 2345,19,1234,30,0,10,1234,0,0,1,0,255,170,0,128,0,0" + }, + { + "plain_name": "Quickly Create Colorful Patterns B", + "full_command": "samj_Motifs_Rapides_B 1,1234,16,0,8" + }, + { + "plain_name": "Random Pattern Courtepointe", + "full_command": "samj_Courtepointe 20,0,1,0,1,0" + }, + { + "plain_name": "Rays Of Colors", + "full_command": "samj_Rays_Of_Colors 300,12,40,16,38,1,0,0,0,255" + }, + { + "plain_name": "Soft Random Shades", + "full_command": "samj_Soft_Random_Shades 140,120,220,255,0,20,0" + }, + { + "plain_name": "Steps V2", + "full_command": "samj_Steps_V2 10,10,4,1,10,2,60,0,1.1,10" + }, + { + "plain_name": "Tissu Fond Flou", + "full_command": "samj_Tissu_Fond_Flou 0,0,100,100,0,1,0,1,0,0,0,0,0" + }, + { + "plain_name": "Variation Stained Glass", + "full_command": "samj_Variation_Stained_Glass 0,2,8,0,3,40,100,0,1.1,20" + }, + { + "plain_name": "Adjacent Annular Steiner Chains", + "full_command": "samj_Adjacent_Annular_Steiner_Chains 50,50,0,0,6,56,20,50,0,255,0,221,127,72,0,255,127,0,145,255,127,0,255,144,127,72,255,0,127,255,217,0,127,255,0,0,127,5,0,0,2,0,0,0,255,0,0,0" + }, + { + "plain_name": "Adjacent Rectangles", + "full_command": "samj_Rectangles_Adjacents 10,10,80,80,0,50,6,0,0,0,0,0,255,1,255,255,0,127,0,0,255,127,0,0,0,0,0,0,0,0.5,0.5,1.8,0,0,0,0" + }, + { + "plain_name": "Annular Steiner Chains", + "full_command": "samj_Annular_Steiner_Chains 50,50,50,6,0,0,0,0,255,1,255,255,0,127,64,192,128,127,0,255,0,127,0,0,255,127,0,0,0,0,0,0,0,0.5,0.5,1.8,0,0,0,0" + }, + { + "plain_name": "Chains Solidify", + "full_command": "samj_Chains_Solidify 50,50,0,6,56,20,50,0,255,0,221,255,72,0,255,255,0,145,255,255,0,255,144,255,72,255,0,255,255,217,0,255,255,0,0,255,5,255,127,0,255,0,0,0,255,100" + }, + { + "plain_name": "Christmas Balls", + "full_command": "samj_Noel_2016 50,50,100,150,7,0,240,45,15,255,-15,2.5,2,0.8,1,1.5,0,0,0,0.25,10,0.8" + }, + { + "plain_name": "Chryzodes", + "full_command": "samj_Chryzodes 100,0,0,0,255,0,50,50,45,79,3,1,240,128,64,255,0,0,0,0,0,0,0,0,0,0,0" + }, + { + "plain_name": "Contour Line Laser", + "full_command": "samj_Contour_Line_Laser_LED 0,1,0" + }, + { + "plain_name": "Dessiner Un Polygone - Draw a Polygon", + "full_command": "samj_dessiner_un_polygone 5,50,50,0,40,50,1,255,255,0,255,0,0,0,0,255,1,0,0,255,255,0,0,255,0,255,0,0,127,127,127,255,0,0,0,0,255,0,255,255,255,255,0,0,0,0,255,1,255,0,0,0,1" + }, + { + "plain_name": "Egg Oeuf Granville", + "full_command": "samj_Egg_Oeuf_Granville 50,50,0,20,30,10,0,0,0,0,255,1,255,255,0,127,0,0,0,0,0,0,0,0.5,0.5,1.8,0,0,0,0" + }, + { + "plain_name": "Egg Oeuf Hugelschaffer", + "full_command": "samj_Egg_Oeuf_Hugelschaffer 50,50,50,6,48,0,0,0,0,0,255,1,255,255,0,127,0,0,0,0,0,0,0,0.5,0.5,1.8,0,0,0,0" + }, + { + "plain_name": "Egg Oeuf Rosillo", + "full_command": "samj_Egg_Oeuf_Rosillo 50,50,40,200,300,0,0,0,0,255,1,255,255,0,127,0,0,0,0,0,0,0,0.5,0.5,1.8,0,0,0,0" + }, + { + "plain_name": "Engrenages Gears Laser", + "full_command": "samj_Engrenages_Laser_LED 80,20,12,14,17,1,1,2,19,250,0,0,0,0" + }, + { + "plain_name": "Etoile De Pompei", + "full_command": "samj_etoile_de_pompei_153 50,50,30,90,255,255,255,255,170,255,255,255,0,98,147,255,0,59,89,255,1,0" + }, + { + "plain_name": "Etoile De Pompei Triangles Sierpinski", + "full_command": "samj_Etoile_De_Pompei_Triangles_Sierpinski 50,50,30,100,0,0,0,255,0,5,255,0,0,127,255,0,255,127,0,0,255,127,0,255,255,127,255,255,0,127,0,63,255,64,0,0,0,0,0,0,0,0.5,0.5,1.8,0,0,0,0" + }, + { + "plain_name": "Etoiles Remplies Triangles Sierpinski", + "full_command": "samj_Etoiles_Remplies_Triangles_Sierpinski 6,50,50,50,40,30,0,0,0,0,0,255,1,4,255,0,0,127,255,192,64,127,0,0,255,127,0,255,255,127,255,255,0,127,0,0,0,0,0,0,0,0.5,0.5,1.8,0,0,0,0" + }, + { + "plain_name": "Etoiles Stars Laser", + "full_command": "samj_Etoiles_Laser_LED 1400,5,2,0,0,0,0" + }, + { + "plain_name": "Flocon Snowflake Laser", + "full_command": "samj_Flocon_Laser_LED 1400,6,5,0" + }, + { + "plain_name": "Fractal Tree", + "full_command": "samj_Fractal_Tree 50,100,-90,8,10,20,255,0,0,255,20,0,4,1,0,0.25,10,0.8" + }, + { + "plain_name": "Gradient CIE Lab [Linear]", + "full_command": "samj_Linear_Gradient_CIE_Lab 0,0,240,40,160,255,240,240,40,255" + }, + { + "plain_name": "Gradient CIE Lab [Shape]", + "full_command": "samj_Shape_Linear_Gradient_CIE_Lab 10,10,90,90,2,0,240,40,160,255,240,240,40,255,0,0,0,0,255,0" + }, + { + "plain_name": "Harmonograph", + "full_command": "Harmonograph_samj 50,50,192,128,64,255,0,0,1000,0,400,150,200,200,100,4,6,2,2,15,270,75,60,0.04,0.04,0.05,0.06,0,0,0,1,1" + }, + { + "plain_name": "Hawaiian Earring", + "full_command": "samj_Hawaiian_Earring 50,50,40,6,0,0,0,0,0,255,1,255,255,0,127,0,0,255,127,0,0,0,0,0,0,0,0.5,0.5,1.8,0,0,0,0" + }, + { + "plain_name": "Lines of Varying Thickness", + "full_command": "samj_Lignes_Epaisseur_Variable 0,32,3,0,0,0,255,255,255,255,255,0,0,1,0,0,0,0,0,0,0.5,0.5,1.8,0,0" + }, + { + "plain_name": "Orbites", + "full_command": "samj_Orbites 100,0,0,0,255,50,50,20,79,45,2,240,128,64,255,0,0,0,0,0,0,0,0" + }, + { + "plain_name": "Palette De Degrades", + "full_command": "samj_Palette_De_Degrades 159,190,195,255,55,67,140,255,54,40,39,255,140,81,88,255,207,175,190,255,220,202,196,255,170,186,192,255,130,149,139,255,112,96,96,255,237,168,138,255,220,199,205,255,234,217,219,255,0,0,256,2" + }, + { + "plain_name": "Pappus Chain", + "full_command": "samj_Cercles_Tangents_Dans_Cercle 50,50,50,40,0,0,0,0,255,1,127,127,127,127,255,0,0,127,0,255,0,127,0,0,255,127,255,0,255,127,255,255,0,127,0,255,255,127,192,128,64,127,64,192,128,127,128,64,192,127,192,64,128,127,0,0,0,0,0,0,0,0.5,0.5,1.8,0,0,0,0" + }, + { + "plain_name": "Pintograph", + "full_command": "Pintograph_samj 50,50,192,128,64,255,0,0,1000,0,400,150,200,200,100,4,4.05,4.16,4.32,75,150,75,60,0,0,0,1,1" + }, + { + "plain_name": "Poisson D'Avril", + "full_command": "samj_Poisson_D_Avril 50,50,40,2,0,0,0,0,255,1,250,60,10,255,255,255,255,255,0,0,0,0,0,0,0,0.5,0.5,1.8,0,0,0,0" + }, + { + "plain_name": "Pythagoras Tree", + "full_command": "samj_Arbre_Pythagore 50,95,8,12,255,0,0,255,20,0,1,0,0,0.25,10,0.8" + }, + { + "plain_name": "Rosace Triangles Sierpinski", + "full_command": "samj_Rosace_Triangles_Sierpinski 6,6,50,50,50,-15,25,5,30,0,0,0,255,0,0,0,0,3,0,0,255,127,255,255,0,127,128,64,192,127,64,128,192,127,0,255,255,127,0,0,0,0,0,0,0,0,0.5,0.5,1.8,0,0,0,0" + }, + { + "plain_name": "Rotating Circles", + "full_command": "samj_Cercles_Qui_Tournent 800,255,255,255,255,0,1,0.5,0.33,7,17,1,0.5,0.33,7,17,1,10,0,0,0,255,0,0,0,0,0,0,0,0.5,0.5,1.8,0" + }, + { + "plain_name": "Rows Columns", + "full_command": "samj_Lignes_Colonnes 16,16,0,0,0,0,64" + }, + { + "plain_name": "Simple Geometric Shapes", + "full_command": "samj_Formes_Geometriques_Simples 50,50,127,127,127,127,255,255,0,255,0,0,255,255,5,40,40,4,0,0,1" + }, + { + "plain_name": "Snowflake 2", + "full_command": "samj_Flocon_De_Neige 50,50,6,50,40,0,3,192,192,192,255,1,0,3,255,255,255,255,0.7,0,0,0,0,0,0,0,0,0.5,0.5,1.8,0,0,0,0" + }, + { + "plain_name": "Spirographe", + "full_command": "Spirographe_samj 50,50,200,50,150,192,128,64,255,0,0,3,0,1,0,0,0,255,0,0,255,0,255,255,0,255,0,0,0,1,1" + }, + { + "plain_name": "Splines Test", + "full_command": "samj_Splines_Test 50,50,30,30,90,30,1,10,2,2,2,2,2,2,2,2,255,255,0,255,0,255,255,255,1,0,0" + }, + { + "plain_name": "Straight Lines", + "full_command": "samj_Des_Lignes_002 100,0,0,192,128,64,255,0,0,1,50,50,0,0,0,0,1" + }, + { + "plain_name": "Superposition Triangles Sierpinski", + "full_command": "samj_Superposition_Triangles_Sierpinski 6,6,50,50,50,1,20,30,0,0,0,255,1,4,0,0,255,127,255,255,0,127,128,64,192,127,64,128,192,127,0,255,255,127,0,0,0,0,0,0,0,0,0.5,0.5,1.8,0,0,0,0" + }, + { + "plain_name": "Test Visu 3D", + "full_command": "samj_Test_Visu_3D 1,\"C:\\\\\\\\GimpEval-2.9.5-Win\\\\\\\\images_test\\\\\\\\GMIC\\\\\\\\cube.off\",0.5,1,1,0,0,0,1,0,0,0,1024,1024,0.5,0,0,0,45,0,0,-100,0.5,0.7,2,1,400,1,225,255,255,255" + }, + { + "plain_name": "Traits Strokes", + "full_command": "Traits_Strokes_samj 50,50,35,0,100,0,30,0,360,240,60,120,255,0,0,0,20,0,0,0,1,1" + }, + { + "plain_name": "Triangles Shades Adjacents", + "full_command": "Triangles_Shades_Adjacents 0,50,50,60,-1,0,255,255,255,255,255,0,221,255,72,0,255,255,0,145,255,255,0,255,144,255,72,255,0,255,255,217,0,255,255,0,0,255,5,0,0,128,128,128,255,1,0,3,1,0" + }, + { + "plain_name": "Twisted Rays [Samj]", + "full_command": "Twisted_Rays 800,1,0.2,2,5,21,0,0,0,0,255,255,0,255,255,255,0,255,0,255,255,255,0,255,255,0,0,255,255,0,255,255,255,255,255,255,0,0,0,0,255,0,2,2,0,0,5,0,0" + }, + { + "plain_name": "CorLine", + "full_command": "samj_CorLine 0,10,0.5,0,0,50,1,0" + }, + { + "plain_name": "CorLine B", + "full_command": "samj_CorLine_B 0,1,10,0,0,0,0.5,0,0,50,1,0" + }, + { + "plain_name": "Spatial Transition To PNG", + "full_command": "samj_fx_spatial_transition_to_PNG 10,0,5,\"cos(x*y/(16+32*A))\",0,4,0,\"0\",0" + }, + { + "plain_name": "Transition H V To PNG", + "full_command": "samj_transition_H_V_to_PNG 10,1,0,0" + }, + { + "plain_name": "BoxFiter Map", + "full_command": "samj_BoxFiter_Map 2,3,3,0,0,0,2,127,16,0,0,0.2" + }, + { + "plain_name": "BoxFiter Test", + "full_command": "samj_BoxFiter_Test 2,3,3,1,2" + }, + { + "plain_name": "Carres Lignes - Squares Lines", + "full_command": "samj_Carres_Lignes 2000,3,1234,0,1,1.5,0,0,1,0,0,0,255" + }, + { + "plain_name": "CeKoaSa 001", + "full_command": "samj_CeKoaSa_001 0,15,3,1,3" + }, + { + "plain_name": "CeKoaSa 002", + "full_command": "samj_CeKoaSa_002 0,15,3,1,3,1" + }, + { + "plain_name": "CeKoaSa 003", + "full_command": "samj_CeKoaSa_003 0,5,1,1,3" + }, + { + "plain_name": "CeKoaSa 004", + "full_command": "samj_CeKoaSa_004 30,0,0,0.8,0" + }, + { + "plain_name": "CeKoaSa 005", + "full_command": "samj_CeKoaSa_005 16,16,0,0,0.2,1,1,0,1" + }, + { + "plain_name": "CeKoaSa 007", + "full_command": "samj_CeKoaSa_007 8,8,10,8,8" + }, + { + "plain_name": "CeKoaSa 008", + "full_command": "samj_CeKoaSa_008 64,64,4,1,2,16,1,20,0.1,0,1,64,1,2,10,0.8,255,255,255,255,0" + }, + { + "plain_name": "CeKoaSa 009", + "full_command": "samj_CeKoaSa_009 1,5,0.5,0.63,0.6,2.35,0.8,30,2,0,1,25,1,50,1,1,1.2,1,1,1,1,1,1,0,0,0,0,0,7,\"0\",0,\"0\",\"0,0,100,100,-1,0,0,100,100,-1,0,0,100,100,-1,0,0,100,100,-1,0,0,100,100\"" + }, + { + "plain_name": "CeKoaSa 010", + "full_command": "samj_CeKoaSa_010 30,10,0.1,2,10" + }, + { + "plain_name": "CeKoaSa 011", + "full_command": "samj_CeKoaSa_011 0.2,0,0,5,0,0,0,0,240,40,160,255,240,240,40,255,0,50,205" + }, + { + "plain_name": "CeKoaSa 012", + "full_command": "samj_CeKoaSa_012 30,3,50,3,0,1,1,-1,1" + }, + { + "plain_name": "Diaporama - Slideshow", + "full_command": "samj_diaporama 1,0" + }, + { + "plain_name": "Do Nothing", + "full_command": "Je_passe_l_hiver_en_Floride" + }, + { + "plain_name": "Layers To PNG", + "full_command": "samj_Layers_To_PNG" + }, + { + "plain_name": "Polygonize", + "full_command": "polygonize_GUI 300,10,10,10,10,0" + }, + { + "plain_name": "Recolorize 20130115", + "full_command": "gimp_recolorize_20130115_modifie 30,0,0,255,0,0,1" + }, + { + "plain_name": "Relief A", + "full_command": "samj_Relief_A 3,1,0,1,16,1,50,1,1,1.2,1,1,1,1,1,1,0,0,0,0,0,0,100" + }, + { + "plain_name": "Segments Points TSP", + "full_command": "samj_TSP_Segments_GUI 3,50,2,0.5,12345,0,0,0,0,255,0,1,1" + }, + { + "plain_name": "SVG Symetries A", + "full_command": "samj_SVG_Symetries_A 8,0,0,0.33,1,0.66,-1,1,0.5,0,2,0,-5,5,0" + }, + { + "plain_name": "SVG TSP", + "full_command": "samj_GUI_Test_Liste_Points_TSP 0,50,3,48,1,0,2,1,1,-5,5,0,1" + }, + { + "plain_name": "Test A", + "full_command": "samj_test_A 64,192,500" + }, + { + "plain_name": "Test B", + "full_command": "samj_test_B 100" + }, + { + "plain_name": "Test C", + "full_command": "samj_test_C 100" + }, + { + "plain_name": "Test Courbes", + "full_command": "samj_test_x_color_curves 1,0" + }, + { + "plain_name": "Test D", + "full_command": "samj_test_D 40,255,10,30,5,0,8,0,4,0,25" + }, + { + "plain_name": "Test Dither Color", + "full_command": "samj_test_Dither_Color 2,0,230,230,150,255,0,0" + }, + { + "plain_name": "Test E", + "full_command": "samj_test_E 0,0.7,0.3,0.6,1.1,0,200,125,50,255,0,1" + }, + { + "plain_name": "Test F", + "full_command": "samj_test_F 40,50,1" + }, + { + "plain_name": "Test G", + "full_command": "samj_test_G 0,0,0,30" + }, + { + "plain_name": "Test Solidify", + "full_command": "samj_Test_Solidify 10,10,1,0.02,8,1,75,0,20" + }, + { + "plain_name": "Tests Fill", + "full_command": "samj_Tests_Fill 0,30,2,-0.8,0.4,1,1,0,0,0,120,40,240,255,0,50" + }, + { + "plain_name": "Texture 002", + "full_command": "samj_gimp_texture_zero_zero_deux 0,10,4,10,0.5,1,1,1,0.3" + }, + { + "plain_name": "Texture 003", + "full_command": "samj_Texture_Aquarelle_1 10,10,4,3,251,237,206,255,1" + }, + { + "plain_name": "Toile Araignee", + "full_command": "samj_Toile_D_Araignee 0,10,4" + }, + { + "plain_name": "Tout Interactif", + "full_command": "samj_test_tout_interactif" + }, + { + "plain_name": "Triangles Lignes - Lines", + "full_command": "samj_Triangles_Lignes 2000,3,1234,0,1,1.5,0,0.5,0.5,1,0,0,0,255" + }, + { + "plain_name": "Disco", + "full_command": "disco 10,15,20,250" + }, + { + "plain_name": "Kitaoka Spin Illusion", + "full_command": "KittyRings 30,8,0,1,113,0,113,255,0,255,0,255" + }, + { + "plain_name": "Moon2panorama", + "full_command": "moon2panorama 0,0,0,360,0,0,1,0,0" + }, + { + "plain_name": "Spiral RGB", + "full_command": "spiral_RGB 1,3,5,0" + }, + { + "plain_name": "Unpurple", + "full_command": "unpurple 1,0,0,0.33,5,0,\"0\",0,50,50" + }, + { + "plain_name": "Mc Flou", + "full_command": "mc_flou 30,6,1,1,1,0,255,1,1,1,0" + }, + { + "plain_name": "Mc Pendraw", + "full_command": "mc_pendraw 8,0.8,450,21,0.5,1,0,0,255,0,0" + }, + { + "plain_name": "Beauty Retouch", + "full_command": "fx_tk_retouch 30,3,1,20,1.5,1,2.5,0,0,0" + }, + { + "plain_name": "DOF Manipulation", + "full_command": "fx_tk_dof 50,50,30,60,5,15,2,0,0,200,40,2,0,0,0,0,0.01,0,1,0,0" + }, + { + "plain_name": "Infrared Simulation", + "full_command": "fx_tk_infrared 0.75,0.5,-100,0.75,0,1,0,0,1,1,0,50,0" + }, + { + "plain_name": "Photoillustration", + "full_command": "fx_tk_photoillustration 0,0.25,0,0.3,0.5,0.5,1,0,5,0,1,0,0,1,0,0,1.2,98.5,5,0.5,0,0,0,0,0,1,0" + }, + { + "plain_name": "Dream Smoothing Enhanced", + "full_command": "fx_dream_smoothing_enhanced 3,430,0.8,0.4,0.5,0.6,2,0.4,1,0.6,4,0,0,0,0,0,0,0,0,0,0,1,0,50,50" + }, + { + "plain_name": "Demo Mathmap RA", + "full_command": "demo_ra 1,1" + }, + { + "plain_name": "Demo Mathmap XY", + "full_command": "demo_xy 1,1" + }, + { + "plain_name": "Fourier Picture Watermark", + "full_command": "fx_fourier_picture_watermark 0.2" + }, + { + "plain_name": "Mathmap Flag", + "full_command": "mathmap_flag 0.05,5,1,5" + }, + { + "plain_name": "Rel2ellv3", + "full_command": "mathmap_rel2ellv3" + }, + { + "plain_name": "Spiral", + "full_command": "mathmap_spiral 5,0" + }, + { + "plain_name": "Custom Code [Full]", + "full_command": "fx_custom_code \"foreach {\\n\\n to_rgb\\n +deform 20\\n blend_edges 3\\n\\n}\\n\\n\\n\",0,0,0,2,0,50,50" + }, + { + "plain_name": "Custom Code [Global]", + "full_command": "fx_custom_code \"foreach {\\n\\n to_rgb\\n +deform 20\\n blend_edges 3\\n\\n}\\n\\n\\n\",0,0,0,2,0,50,50" + }, + { + "plain_name": "Custom Code [Local]", + "full_command": "fx_custom_code \"foreach {\\n\\n to_rgb\\n +deform 20\\n blend_edges 3\\n\\n}\\n\\n\\n\",0,0,0,2,0,50,50" + }, + { + "plain_name": "Export RGB-565 File", + "full_command": "fx_output_565 \"out565.rgb\",0" + }, + { + "plain_name": "Games & Demos", + "full_command": "fx_gmic_demos 0" + }, + { + "plain_name": "Histogram Analysis", + "full_command": "_none_ 256,0" + }, + { + "plain_name": "Import Data", + "full_command": "fx_import_image \"\",1" + }, + { + "plain_name": "Import RGB-565 File", + "full_command": "fx_input_565 \"\",\"800\",\"600\",0" + }, + { + "plain_name": "Intarsia", + "full_command": "fx_intarsia \"\",\"intarsia.html\",512,12,1,0,1,100" + }, + { + "plain_name": "Sample Image", + "full_command": "fx_image_sample 0,0,0" + }, + { + "plain_name": "Solve Maze", + "full_command": "fx_solve_maze 5,5,95,95,0.1,3,255,0,0,255,0" + } +] diff --git a/assets/foreground b/assets/foreground new file mode 100644 index 0000000..136436a --- /dev/null +++ b/assets/foreground @@ -0,0 +1,48 @@ +Aurora +Doodle +Felt Pen +Ghost +Hard Sketch +Hough Sketch +Rodilius +Chalk It Up [Fr] +Skeletik +B&W Stencil +Filaments +Stamp +Lineart +Emboss +Abstraction +Metallic Look +Select-Replace Color +Edges +Edges Offsets +Gradient Norm +Local Orientation +Skeleton +Thin Edges +High Pass +Spotify +Emboss-Relief +Slice Luminosity +Edges on Fire +Pyramid Processing +Iain Weightmap +Jpr Line Edges +Charred Plastic +Hard Painting +Neon +CubeHelix +Satellite +Lylejk Luma Invert +Black Crayon Graffiti +Color Sketch +Autofill Coloring Book +Plasmic V2 +64 Couleurs Max +CeKoaSa 013 +Samj Test Shapeprevalent +Test Mauvais Contours +Contours Gros Pixels +CeKoaSa 008 +Test D diff --git a/compose.yml b/compose.yml new file mode 100644 index 0000000..14a190f --- /dev/null +++ b/compose.yml @@ -0,0 +1,98 @@ +# live.f12.rocks — event photo pipeline: SFTP inbox -> gmic/rembg -> web. +# +# All three services share one host directory (default ./data, see +# .env.example DATA_HOST_DIR) at different mount points: +# sftpgo -> /srv/sftpgo/data (SFTP user home = /srv/sftpgo/data/inbox) +# worker -> /data (watches /data/inbox, writes /data/jobs) +# web -> /data (reads jobs, writes remix variants) +# +# Copy .env.example to .env and fill in real SFTP credentials before +# running this. Never commit .env. + +services: + sftpgo: + image: drakkan/sftpgo:v2 + restart: unless-stopped + # The image defaults to a fixed uid 1000 user. worker/web run as root + # (see Dockerfile), and Docker itself creates first-run bind-mount + # directories (./data/inbox, ./data/jobs, ...) as root:root — running + # sftpgo as root too avoids a uid mismatch on the shared ./data tree. + user: root + entrypoint: ["/bin/sh", "/entrypoint.sh"] + environment: + SFTP_USER: ${SFTP_USER:-livef12} + SFTP_PASSWORD: ${SFTP_PASSWORD:-changeme} + volumes: + - ${DATA_HOST_DIR:-./data}:/srv/sftpgo/data + - sftpgo_state:/var/lib/sftpgo + - ./sftpgo/entrypoint.sh:/entrypoint.sh:ro + ports: + # SFTP only. The SFTPGo web admin (container port 8080) is + # intentionally NOT published here and NOT attached to the + # `traefik` network — it stays unreachable from outside docker. + # + # Host SFTP port. Spec asked for 121212 which exceeds TCP max + # (65535); production default is 12121. + - "${SFTP_HOST_PORT:-12121}:2022" + networks: + - internal + + worker: + build: . + restart: unless-stopped + command: ["python3", "-m", "app.worker"] + depends_on: + - sftpgo + environment: + DATA_DIR: /data + OUTPUT_COUNT: ${OUTPUT_COUNT:-3} + BLEND_OPACITY: ${BLEND_OPACITY:-30%} + FILTER_TIMEOUT: ${FILTER_TIMEOUT:-120} + MAX_FILTER_ATTEMPTS: ${MAX_FILTER_ATTEMPTS:-8} + NICE_LEVEL: ${NICE_LEVEL:-18} + volumes: + - ${DATA_HOST_DIR:-./data}:/data + - ./assets:/data/assets:ro + - rembg_cache:/app/.home + # Sequential-only by design (no threads/async in worker.py); these + # limits just make sure gmic/rembg can't starve the host too. + cpus: "1.0" + mem_limit: 2g + networks: + - internal + + web: + build: . + restart: unless-stopped + command: ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"] + depends_on: + - worker + environment: + DATA_DIR: /data + OUTPUT_COUNT: ${OUTPUT_COUNT:-3} + BLEND_OPACITY: ${BLEND_OPACITY:-30%} + FILTER_TIMEOUT: ${FILTER_TIMEOUT:-120} + MAX_FILTER_ATTEMPTS: ${MAX_FILTER_ATTEMPTS:-8} + NICE_LEVEL: ${NICE_LEVEL:-18} + SITE_TITLE: live.f12.rocks + volumes: + - ${DATA_HOST_DIR:-./data}:/data + - ./assets:/data/assets:ro + labels: + - "traefik.enable=true" + - "traefik.http.routers.livef12rocks.rule=Host(`live.f12.rocks`)" + - "traefik.http.routers.livef12rocks.entrypoints=websecure" + - "traefik.http.routers.livef12rocks.tls.certresolver=myresolver" + - "traefik.http.services.livef12rocks.loadbalancer.server.port=8000" + networks: + - internal + - traefik + +networks: + internal: {} + traefik: + external: true + +volumes: + sftpgo_state: + rembg_cache: diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..c7651f9 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,7 @@ +fastapi>=0.115,<0.117 +uvicorn[standard]>=0.30,<0.33 +jinja2>=3.1,<3.2 +python-multipart>=0.0.9,<0.1 +rembg>=2.0.59,<2.1 +pillow>=10.4,<11 +onnxruntime>=1.19,<1.20 diff --git a/sftpgo/entrypoint.sh b/sftpgo/entrypoint.sh new file mode 100755 index 0000000..d2544d1 --- /dev/null +++ b/sftpgo/entrypoint.sh @@ -0,0 +1,44 @@ +#!/bin/sh +# Builds a SFTPGo "loaddata" JSON (the format the dumpdata/loaddata REST +# API uses) with exactly one user, then starts sftpgo with +# --loaddata-from that file. Runs on every container start — mode 0 +# (the default) adds new objects and updates existing ones, so re-running +# this is safe and picks up a changed SFTP_PASSWORD on restart. +# +# The user's home_dir is /srv/sftpgo/data/inbox, which — via the +# ./data:/srv/sftpgo/data bind mount in compose.yml — is the same +# directory as the worker's DATA_DIR/inbox. Whatever lands here over SFTP +# is exactly what the worker watches. +# +# Uses `jq` to build the JSON so SFTP_USER/SFTP_PASSWORD are always +# correctly escaped (arbitrary passwords, including quotes/backslashes, +# are safe). jq ships in the official drakkan/sftpgo image; if a future +# image drops it, this script needs an alternative (e.g. python/perl, +# both otherwise present at the time of writing). +set -eu + +OUTPUT="/var/lib/sftpgo/loaddata.json" + +: "${SFTP_USER:?SFTP_USER must be set}" +: "${SFTP_PASSWORD:?SFTP_PASSWORD must be set}" + +jq -n \ + --arg user "$SFTP_USER" \ + --arg pass "$SFTP_PASSWORD" \ + '{ + users: [ + { + status: 1, + username: $user, + password: $pass, + home_dir: "/srv/sftpgo/data/inbox", + permissions: { + "/": ["list", "download", "upload", "overwrite", "create_dirs"] + }, + filesystem: { provider: 0 } + } + ], + version: 15 + }' > "$OUTPUT" + +exec sftpgo serve --loaddata-from "$OUTPUT"