From 90192cd284e6b811e3fef69226cb70a9875f48d1 Mon Sep 17 00:00:00 2001 From: Frank Schwenk Date: Thu, 16 Jul 2026 21:32:10 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20initial=20live.f12.rocks=20SFTP=20?= =?UTF-8?q?=E2=86=92=20gmic/rembg=20=E2=86=92=20web=20pipeline?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Event pep stack with SFTPGo inbox, sequential worker, FastAPI gallery/remix, and Traefik-ready compose. Co-authored-by: Cursor --- .env.example | 21 + .gitignore | 14 + AGENTS.md | 277 +++ BOUNDARIES.md | 87 + Dockerfile | 58 + INFRASTRUCTURE.md | 120 + MOOD.md | 107 + NOTES.md | 10 + README.md | 95 + SOUL.md | 102 + STANDARDS.md | 132 ++ USER.md | 100 + app/__init__.py | 1 + app/config.py | 83 + app/main.py | 160 ++ app/pipeline.py | 418 ++++ app/rembg_cli.py | 31 + app/remix.py | 67 + app/static/style.css | 328 +++ app/templates/base.html | 17 + app/templates/index.html | 25 + app/templates/job.html | 78 + app/templates/remix.html | 50 + app/worker.py | 154 ++ assets/background | 91 + assets/blend_modes | 58 + assets/filters.json | 4858 ++++++++++++++++++++++++++++++++++++++ assets/foreground | 48 + compose.yml | 98 + requirements.txt | 7 + sftpgo/entrypoint.sh | 44 + 31 files changed, 7739 insertions(+) create mode 100644 .env.example create mode 100644 .gitignore create mode 100644 AGENTS.md create mode 100644 BOUNDARIES.md create mode 100644 Dockerfile create mode 100644 INFRASTRUCTURE.md create mode 100644 MOOD.md create mode 100644 NOTES.md create mode 100644 README.md create mode 100644 SOUL.md create mode 100644 STANDARDS.md create mode 100644 USER.md create mode 100644 app/__init__.py create mode 100644 app/config.py create mode 100644 app/main.py create mode 100644 app/pipeline.py create mode 100644 app/rembg_cli.py create mode 100644 app/remix.py create mode 100644 app/static/style.css create mode 100644 app/templates/base.html create mode 100644 app/templates/index.html create mode 100644 app/templates/job.html create mode 100644 app/templates/remix.html create mode 100644 app/worker.py create mode 100644 assets/background create mode 100644 assets/blend_modes create mode 100644 assets/filters.json create mode 100644 assets/foreground create mode 100644 compose.yml create mode 100644 requirements.txt create mode 100755 sftpgo/entrypoint.sh 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"