feat: add aichelberg-indians pipeline and rebuild RECIPES.md

Replace the verbose recipe catalog with a compact agent reference (modules,
ImageMagick ops, G'MIC commands, combines) and add the Indians Aichelberg
tone-mapping pipeline with gmic variants and xcf export.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Frank Schwenk
2026-07-13 10:15:28 +02:00
parent 765ebbe3da
commit 9b6c80da42
2 changed files with 513 additions and 550 deletions
+235 -550
View File
@@ -1,625 +1,310 @@
# RECIPES.md — Declarative Pipeline Recipes
# RECIPES.md
*Open this file when you forget how recipes work — rules first, catalog below.*
Not executable code. Named building blocks for creating or editing pipelines in `pipelines/<name>.py`. Load via `@RECIPES.md` in Cursor when working on pipelines.
Reference for agents building `pipelines/<name>.py`. Not executable — expand to `p.step(...)` calls.
---
## 1. Rules cheat sheet
## Rules
1. **What a recipe is** — a named list of declarative lines. Agents turn it into Python using modules from `imagepipeline/modules/`.
2. **Layer order** — in every `combine` / composite recipe, lines are listed **bottom layer → top layer** (first line = background, last line = foreground on top).
3. **Indentation** — recipe id on its own line; indented lines below are the layers/steps of that recipe.
4. **`combine` = composite** — a multi-line recipe produces one output image by stacking those layers.
5. **Two-layer vs three-layer** — the `composite` module accepts exactly 2 inputs. Three or more layers need chained composites (bottom pair first, then add the next layer on top):
1. **combine** = one output image. Layers **bottom → top** (first line = background).
2. **composite** takes exactly **2** inputs. For 3+ layers: `composite(A,B)``composite(mid, C)` → …
3. **rembg** once per pipeline — reuse the same step ref in every combine.
4. **G'MIC in Python:** `command="-filter args"` (leading `-`). Multi-frame output: framework keeps frame `000001`.
5. **Colors:** hex (`#RRGGBB`) for `imagemagick_fill` / `color_to_alpha`. G'MIC color slots: `R,G,B` ints 0255 from hex bytes.
6. **Placeholders** at pipeline top: `COLOR1`, `COLOR2`, `R1,G1,B1`, `R2,G2,B2`, `ALPHA1` (default 160), `ALPHA2` (default 110), `STYLE`, `MAX_EDGE`, `PROMPT`, `MODEL`, `TEMPLATE_IMAGE`, `YELLOW`.
7. **xcf_stack:** separate step, not a combine layer. `inputs=[...]` bottom → top; include `"input"` for originals. Needs `gimp` on PATH.
8. Lines starting with `#` in user prompts = human notes — ignore.
```text
# 3 layers: A (bottom), B (middle), C (top)
combine
A
B
C
# → composite(A, B) then composite(result, C)
```
6. **Shared expensive steps** — `rembg` runs once per pipeline and is reused. Recipe lines say `rembg`, but the agent must not re-run it for every composite.
7. **`xcf_stack` (GIMP export)** — stacks **listed step outputs** into one `.xcf` per image. Pass step refs in `inputs=[...]` (bottom layer → top). The runner waits until all listed steps finish. Requires `gimp` on PATH. Not a layer inside a `combine` block — a separate recipe.
8. **Placeholders** — `COLOR1`, `COLOR2`, `COLOR`, `STYLE`, `MAX_EDGE`, `PROMPT`, `MODEL`, `TEMPLATE_IMAGE`, etc. are filled in at pipeline creation time (from your prompt or constants at the top of the script).
9. **Colors** — hex for backgrounds (`#RRGGBB` or `#RRGGBBAA`). G'MIC filters need `R,G,B` tuples (see [GMIC color derivation](#6-gmic-color-derivation) below).
10. **Single-step vs composite vs pipeline** — one declarative line = one module step. Multiple indented lines in a **composite** recipe = layers (bottom → top). Multiple indented lines in a **pipeline** recipe = sequential steps (first step first, output feeds the next).
11. **Recipe inclusion** — an indented line that matches a **recipe id** from this file expands that recipe instead of inlining its steps:
- In a **pipeline** recipe (e.g. `colorsplash-watermark`): resolve the referenced recipe, then chain the next line on its output.
- In a **composite** recipe: layers stay declarative (layer descriptions, not recipe ids). Do not nest composite recipes as layers.
- Expand recursively; share expensive steps (`rembg`, etc.) once across all expanded recipes in the same pipeline.
12. **Notes (human only)** — freeform reminders for you. **Agents must ignore them entirely** when building pipelines:
- **Full-line note:** line starts with `#` (optional leading spaces) — not a layer, not a recipe id.
- **Inline note:** `# …` after a recipe id on the same line (everything from `#` onward is ignored).
- Notes may be German or English. They never become code, constants, or prompts.
13. **Quick read examples:**
```text
original-stereo-rembg # wie horseland 3d effekt
original
rembg with gmic: gcd_stereo_img …
rembg
```
```text
colorsplash
# team gallery default look
original as greyscale
rembg
```
```text
colorsplash-watermark
colorsplash
darktable style STYLE
```
**Hex → RGB:** `#244a89``36,74,137`. Strip `#RRGGBBAA` alpha for G'MIC tuples.
---
## 2. How agents use this file
## Layer lines (example)
- Recipes are **names + declarative steps**, not Python.
- When creating or editing a pipeline: read `@RECIPES.md`, resolve named recipes, substitute placeholders, emit real `Pipeline` code.
- **Recipe inclusion:** if an indented line is a known recipe id (e.g. `colorsplash` inside `colorsplash-watermark`), look up that recipe, expand it, and use its output as the input for the next step. Expand recursively. Do not duplicate shared steps — one `rembg` (etc.) per pipeline when multiple included recipes need it.
- **Pipeline vs composite:** multiple indented lines that are **sequential steps or recipe refs** = pipeline recipe (chain). Multiple indented **layer** lines (original, rembg, backgrounds, gmic-on-rembg, …) = composite recipe (combine). When unsure: if any line is another recipe id, treat the parent as a pipeline recipe.
- **Ignore notes:** skip any line that is only a `#` comment (after indent trim). Strip inline `# …` suffixes on recipe-id lines. Do not copy note text into Python comments unless Fränky asks.
- **`xcf_stack`:** list every layer source in `inputs=[...]` (bottom → top). Include `"input"` for the original. The runner schedules `xcf_stack` after all listed steps complete. See `imagepipeline/modules/xcf_stack.py` and `pipelines/pipeline_rezepttest.py`.
- **Shared steps:** define `rembg` (and other expensive steps) **once** per pipeline and reference the step in composites — mirror `pipelines/pipeline_baxxter.py`.
- Follow the **Rules cheat sheet** above — especially layer order and chained composites.
- **3+ layers:** chain `composite` steps (see baxxter, crusaders, orange).
---
## 3. Vocabulary
| Recipe term | Maps to |
|-------------|---------|
| `original` | `inputs="input"` |
| `original as greyscale` | `gmic_grayscale` on input |
| `grayscale` | `imagemagick_grayscale` on input |
| `rembg` | `rembg` on input (outputs `.png`) |
| `white background` / `black background` | `imagemagick_fill` solid `#ffffff` / `#000000` |
| `gradient background COLOR1 COLOR2 45 degree` | `imagemagick_fill` linear, `angle=45` |
| `gradient background COLOR1 COLOR2 radial` | `imagemagick_fill` radial |
| `COLOR background` | `imagemagick_fill` solid `color1=COLOR` |
| `rembg with gmic: FILTER` | `gmic` on rembg output; command = `-FILTER` |
| `original with gmic: FILTER` | `gmic` on input; command = `-FILTER` |
| `layer opacity N%` | `composite` `foreground_opacity=N/100` on that layer |
| `make layer 5% bigger then crop to original size` | `imagemagick_scale_crop` `scale=1.05` |
| `COLOR to alpha` | `color_to_alpha` `color=COLOR` |
| `resize max edge MAX_EDGE` | `imagemagick_resize` `max_edge=MAX_EDGE` |
| `crop square` | `crop_square` |
| `darktable style STYLE` | `darktable_style` `style=STYLE` |
| `xcf stack layers: LAYER1, LAYER2, …` | `xcf_stack` with `inputs=[...]` in that order |
| `xcf stack skip missing` | `xcf_stack` `skip_missing=true` |
| `openrouter edit PROMPT MODEL` | `openrouter_edit` |
| `openrouter gallery match TEMPLATE_IMAGE` | `openrouter_edit` with `template_image` |
**Placeholders:** `COLOR1`, `COLOR2`, `COLOR`, `STYLE`, `MAX_EDGE`, `PROMPT`, `MODEL`, `TEMPLATE_IMAGE`, `YELLOW` — substituted from the user prompt or pipeline constants.
---
## 4. Single-step recipes
One entry per built-in module. Format: recipe id, declarative line(s), Python mapping.
### rembg
One combine, bottom → top. Other phrases: `grayscale` / `original as greyscale`, `white`/`black background`, `original with gmic: ID`, `#COLOR to alpha`, `resize max edge N`, `crop square`, `darktable style STYLE`, `openrouter edit …`, `xcf stack layers: a, b, c`.
```text
rembg
rembg
```
- **Module:** `rembg` — `p.step("rembg", inputs="input")`
- **Note:** outputs `.png`; downstream steps match by stem.
### rembg-alpha-matting-off
```text
rembg-alpha-matting-off
rembg
```
- **Module:** `rembg` — `alpha_matting=False`
### grayscale-gmic
```text
grayscale-gmic
original as greyscale
```
- **Module:** `gmic_grayscale` — default command `-to_gray`
### grayscale-imagemagick
```text
grayscale-imagemagick
grayscale
```
- **Module:** `imagemagick_grayscale`
### resize-max-edge
```text
resize-max-edge
resize max edge MAX_EDGE
```
- **Module:** `imagemagick_resize` — e.g. `max_edge=2000`
- **Source:** `pipelines/pipeline_2000px.py`
### scale-crop-5pct
```text
scale-crop-5pct
make layer 5% bigger then crop to original size
```
- **Module:** `imagemagick_scale_crop` — `scale=1.05`
### solid-fill
```text
solid-fill
COLOR background
```
- **Module:** `imagemagick_fill` — `color1=COLOR`
### gradient-linear-45
```text
gradient-linear-45
gradient background COLOR1 COLOR2 45 degree
```
- **Module:** `imagemagick_fill` — `gradient=True`, `angle=45`
### gradient-radial
```text
gradient-radial
demo-combine
gradient background COLOR1 COLOR2 radial
original
rembg with gmic: gmic-drop-shadow
make layer 5% bigger then crop to original size
rembg
```
- **Module:** `imagemagick_fill` — `gradient=True`, `radial=True`
### gmic
```text
gmic
gmic: COMMAND
```
- **Module:** `gmic` — `command="-COMMAND"` (leading `-` as in existing pipelines)
### color-to-alpha
```text
color-to-alpha
COLOR to alpha
```
- **Module:** `color_to_alpha` — outputs `.png`
### darktable-style
```text
darktable-style
darktable style STYLE
```
- **Module:** `darktable_style` — style must exist in `~/.config/darktable/styles/`
### crop-square
```text
crop-square
crop square
```
- **Module:** `crop_square` — center-crop to largest square
### xcf-stack
```text
xcf-stack # GIMP layer export — one .xcf per input image
xcf stack layers: input, rembg, composite_01, composite_02, …
```
- **Module:** `xcf_stack` — `p.step("xcf_stack", inputs=["input", step_a, step_b, …])`
- **Layer order in XCF:** same as `inputs` list (bottom → top); GIMP layer names = step ids (`input` for originals)
- **Matching:** layers matched by filename stem (extension may differ, e.g. rembg `.png` on `.jpg` input)
- **Output:** `{stem}.xcf` per input image
- **Requires:** `gimp` on PATH
- **Source:** `pipelines/pipeline_rezepttest.py`
### xcf-stack-skip-missing
```text
xcf-stack-skip-missing
xcf stack skip missing
```
- **Module:** `xcf_stack` — `skip_missing=True`
### openrouter-edit
```text
openrouter-edit
openrouter edit PROMPT MODEL
```
- **Module:** `openrouter_edit` — needs `OPENROUTER_API_KEY` in `.env`
- **Source:** `pipelines/example_ai.py`
### openrouter-gallery-match
```text
openrouter-gallery-match
openrouter gallery match TEMPLATE_IMAGE
```
- **Module:** `openrouter_edit` with `template_image=TEMPLATE_IMAGE` and gallery-match prompt
- **Source:** `pipelines/pipeline_team_gallery_match.py`
### ai-exposure
```text
ai-exposure
ai exposure strength STRENGTH
```
- **Module:** `ai_exposure` — optional `[ai]` extra; `max_edge`, `strength`
### ai-tone-map
```text
ai-tone-map
ai tone map strength STRENGTH
```
- **Module:** `ai_tone_map` — optional `[ai]` extra
### comfy-flux-edit
```text
comfy-flux-edit
comfy flux edit PROMPT
```
- **Module:** `comfy_flux_edit` — local ComfyUI; very slow on CPU
---
## 5. Composite and pipeline recipes
## Modules
**Composite** recipes produce one output image. Layers listed bottom → top.
**Pipeline** recipes chain steps or other recipes in order (output of step *n* → input of step *n+1*).
**Parameterized** recipes use `COLOR1` / `COLOR2` (hex) — derive G'MIC RGB via [section 6](#6-gmic-color-derivation).
| name | parameters (defaults) | notes |
|------|----------------------|-------|
| `rembg` | `model`=`birefnet-general`, `alpha_matting`=`True` | output `.png` |
| `gmic` | `command` (required) | timeout 300s |
| `gmic_grayscale` | `command`=`-to_gray` | |
| `composite` | `mode`=`over`, `output_ext`=`.png`, `foreground_opacity`=`1.0` | 2 inputs: bg, fg |
| `imagemagick_fill` | `color1`, `color2`=`""`, `gradient`=`False`, `radial`=`False`, `angle`=`None` | sized to input |
| `imagemagick_grayscale` | `colorspace`=`Gray` | |
| `imagemagick_resize` | `max_edge`=`2000` | no upscale |
| `imagemagick_scale_crop` | `scale`=`1.05` | center crop after scale |
| `color_to_alpha` | `color` (required), `fuzz`=`0.0` | output `.png` |
| `crop_square` | — | center square crop |
| `darktable_style` | `style` (required), `style_overwrite`=`True`, `out_ext`=`""`, `config_dir`=`~/.config/darktable` | jpeg/png only |
| `xcf_stack` | `skip_missing`=`False`, `timeout`=`120` | multi-input step |
| `openrouter_edit` | `prompt`, `model`, `strength`=`0.3`, `template_image`=`None`, `api_key_env`=`OPENROUTER_API_KEY` + AI common | needs `.env` |
| `ai_exposure` | `strength`=`1.0` + AI common | `[ai]` extra |
| `ai_tone_map` | `checkpoint`=`""`, `strength`=`1.0`, `net_input_size`=`256` + AI common | `[ai]` extra |
| `comfy_flux_edit` | `prompt`, `denoise`=`0.35`, `seed`=`-1`, `server_url`, `workflow_path`, `poll_interval`=`2.0` + AI common | local ComfyUI |
### colorsplash
**AI common** (`ai_exposure`, `ai_tone_map`, `openrouter_edit`, `comfy_flux_edit`): `skip_existing`=`True`, `max_edge`=`2048`, `device`=`cpu`.
---
## ImageMagick operations
Used via modules above — not free-form CLI in pipelines. `W×H` = size of reference input image.
| id | module | operation |
|----|--------|-----------|
| `im-solid` | `imagemagick_fill` | `-size W×H xc:COLOR` |
| `im-gradient-linear` | `imagemagick_fill` | `-size W×H -define gradient:angle=N gradient:COLOR1-COLOR2` |
| `im-gradient-radial` | `imagemagick_fill` | `-size W×H radial-gradient:COLOR1-COLOR2` |
| `im-grayscale` | `imagemagick_grayscale` | `-colorspace Gray` |
| `im-resize-max-edge` | `imagemagick_resize` | `-auto-orient -resize {N}x{N}>` (no upscale) |
| `im-scale-crop` | `imagemagick_scale_crop` | `-resize {w×scale}x{h×scale}! -gravity Center -crop w×h+0+0 +repage` |
| `im-crop-square` | `crop_square` | `-auto-orient -crop S×S+X+Y +repage` (center square) |
| `im-color-to-alpha` | `color_to_alpha` | `-alpha on [-fuzz N%] -transparent COLOR` |
| `im-composite-over` | `composite` | `(bg) (fg) -compose over -composite` |
| `im-composite-multiply` | `composite` | `mode=multiply` |
| `im-composite-screen` | `composite` | `mode=screen` |
| `im-composite-opacity` | `composite` | fg: `-channel A -evaluate multiply {0..1}` then compose |
**Layer line → id:** `COLOR background``im-solid`; `gradient … 45 degree``im-gradient-linear`; `gradient … radial``im-gradient-radial`; `grayscale``im-grayscale`; `resize max edge N``im-resize-max-edge`; `make layer 5% bigger …``im-scale-crop` (`scale=1.05`); `crop square``im-crop-square`; `COLOR to alpha``im-color-to-alpha`.
---
## G'MIC commands
Python string = `-` + filter + args. Placeholders `R1,G1,B1` / `R2,G2,B2` from `COLOR1` / `COLOR2`.
| id | command |
|----|---------|
| `gmic-tone-mapping` | `fx_map_tones 0.5,0.7,0.1,30,0` |
| `gmic-grayscale` | `to_gray` (via `gmic_grayscale`) |
| `gmic-feltpen` | `fx_feltpen 300,50,1,0.1,20,5` |
| `gmic-edges` | `fx_edges 0,15,0` |
| `gmic-charred-plastic` | `fx_charred_plastic 1,10,40,1,10,0,0,2,6,5,20,0,11` |
| `gmic-neon` | `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` |
| `gmic-cutout` | `fx_cutout 4,0.5,4,1` |
| `gmic-poster` | `fx_poster_hope 0,3` |
| `gmic-color-abstraction` | `fx_color_abstraction 1,10,0.2` |
| `gmic-huffman-glitches` | `fx_huffman_glitches 30,0,25,0,0,0,0,0,50,50` |
| `gmic-queryprimary` | `afre_queryprimary 1,1` |
| `gmic-local-similarity` | `local_similarity_mask 50,50,50,128,4,10` |
| `gmic-luma-invert` | `Lylejk_Luma_Invert 1,0` |
| `gmic-crayongraffiti` | `fx_crayongraffiti2 300,50,1,0.4,12,1,2,2,0` |
| `gmic-anaglyph` | `fx_stereo_to_anaglyph 2,0` |
| `gmic-stereo` | `gcd_stereo_img 0,0,2.028,1,1.714,3.06,4,1,0` |
| `gmic-drop-shadow` | `fx_drop_shadow3d 0,0,0,10,1,1,2,0.5,R2,G2,B2,200,0` |
| `gmic-jpr-smooth` | `jpr_gradient_smooth 0,1.5` |
| `gmic-bokeh` | `fx_bokeh 3,5,0,30,8,4,0.3,0.2,R1,G1,B1,ALPHA1,0.7,30,20,20,1,2,R2,G2,B2,ALPHA2,0.15` |
| `gmic-bwrecolor` | `fx_bwrecolorize 0,0,0,0,0,1,0,2,R2,G2,B2,255,R1,G1,B1,255,158,137,189,255,224,191,228,255,R1,G1,B1,0,255,255,255,255,255,255,255,255,255,R1,G1,B1,0,255` |
| `gmic-custom-gradient-a` | `fx_custom_gradient 0,0,0,1,2,1,0,128,100,100,2,0,1,0,"",1,0,R1,G1,B1,0,255,R2,G2,B2,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` |
| `gmic-custom-gradient-b` | `fx_custom_gradient 0,0,0,1,2,1,0,128,100,100,2,0,1,0,"",1,0,R2,G2,B2,255,R1,G1,B1,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` |
**Typical input:** `original with gmic:` = on `"input"`; `rembg with gmic:` = on rembg step.
---
## Combines
Format: recipe id, then layers bottom → top. `→` = chained composites.
### 2 layers
```text
colorsplash
original as greyscale
rembg
```
- **Layers:** grayscale background, rembg cutout on top
- **Source:** baxxter, orange, crusaders, `pipeline_colorsplash_watermark_f12.py`
### colorsplash-watermark
```text
colorsplash-watermark
colorsplash
darktable style STYLE
```
- **Type:** pipeline recipe (includes `colorsplash`, then chains `darktable_style`)
- **Python:** expand `colorsplash` → composite step ref → `p.step("darktable_style", inputs=combined, style=STYLE)`
- **Source:** `pipelines/pipeline_colorsplash_watermark_f12.py` (`STYLE = "Watermark F12.rocks"`)
### rembg-white-bg
```text
rembg-white-bg
white background
rembg
```
- **Source:** baxxter, crusaders
### rembg-black-bg
```text
rembg-black-bg
black background
rembg
```
- **Source:** baxxter, crusaders
### rembg-gradient-45
```text
rembg-gradient-45
gradient background COLOR1 COLOR2 45 degree
rembg
```
- **Source:** baxxter, crusaders
### rembg-radial-2colors
```text
rembg-radial-2colors
gradient background COLOR1 COLOR2 radial
rembg
```
- **Source:** baxxter, crusaders
rembg-custom-gradient-a
rembg with gmic: gmic-custom-gradient-a
rembg
### original-stereo-rembg
rembg-custom-gradient-b
rembg with gmic: gmic-custom-gradient-b
rembg
```text
original-stereo-rembg # wie horseland 3d effekt
original
rembg with gmic: gcd_stereo_img 0,0,2.028,1,1.714,3.06,4,1,0
gmic-feltpen-rembg
rembg with gmic: gmic-feltpen
rembg
gmic-edges-rembg
rembg with gmic: gmic-edges
rembg
gmic-charred-plastic-rembg
rembg with gmic: gmic-charred-plastic
rembg
gmic-neon-rembg
rembg with gmic: gmic-neon
rembg
```
- **3 layers:** composite(original, rembg_stereo) → composite(result, rembg)
- **Source:** baxxter, crusaders
### 3 layers
### original-stereo-black-alpha-rembg
```text
original-stereo-rembg
original
rembg with gmic: gmic-stereo
rembg
→ composite(original, rembg_stereo) → composite(_, rembg)
original-drop-shadow-rembg
original
rembg with gmic: gmic-drop-shadow
rembg
original-bwrecolor-rembg
original
rembg with gmic: gmic-bwrecolor
rembg
→ first composite: foreground_opacity=0.5
original-jpr-smooth-rembg
original
rembg with gmic: gmic-jpr-smooth
make layer 5% bigger then crop to original size
rembg
→ gmic → scale_crop on middle layer, then 3-layer chain
bokeh-oktagon
original
original with gmic: gmic-bokeh
rembg
color-bg-drop-shadow-rembg
COLOR1 background
rembg with gmic: gmic-drop-shadow
rembg
yellow-bg-drop-shadow-rembg
YELLOW background
rembg with gmic: gmic-drop-shadow
rembg
gmic-cutout-rembg
original
original with gmic: gmic-cutout
rembg
gmic-poster-rembg
original
original with gmic: gmic-poster
rembg
gmic-color-abstraction-rembg
original
original with gmic: gmic-color-abstraction
rembg
gmic-huffman-glitches-rembg
original
original with gmic: gmic-huffman-glitches
rembg
gmic-queryprimary-rembg
original
original with gmic: gmic-queryprimary
rembg
gmic-local-similarity-rembg
original
original with gmic: gmic-local-similarity
rembg
gmic-luma-invert-rembg
original
original with gmic: gmic-luma-invert
rembg
gmic-crayongraffiti-rembg
original
original with gmic: gmic-crayongraffiti
rembg
gmic-anaglyph-rembg
original
original with gmic: gmic-anaglyph
rembg
```
### 4 layers (middle pipeline)
```text
original-stereo-black-alpha-rembg
original
rembg with gmic: gcd_stereo_img 0,0,2.028,1,1.714,3.06,4,1,0
rembg with gmic: gmic-stereo
#000000 to alpha
rembg
```
- **Middle layer:** stereo gmic, then `#000000 to alpha` on that output
- **Source:** crusaders, baxxter_2
### original-drop-shadow-rembg
```text
original-drop-shadow-rembg
original
rembg with gmic: fx_drop_shadow3d 0,0,0,10,1,1,2,0.5,R2,G2,B2,200,0
rembg
```
- **Shadow color:** RGB from `COLOR2` (see [GMIC color derivation](#6-gmic-color-derivation))
- **Source:** baxxter, orange, crusaders
### original-bwrecolor-rembg
```text
original-bwrecolor-rembg
original
rembg with gmic: fx_bwrecolorize 0,0,0,0,0,1,0,2,R2,G2,B2,255,R1,G1,B1,255,158,137,189,255,224,191,228,255,R1,G1,B1,0,255,255,255,255,255,255,255,255,255,R1,G1,B1,0,255
rembg
```
- **Middle layer opacity:** 50% (`foreground_opacity=0.5` on first composite)
- **Palette:** `R1,G1,B1` from `COLOR1`, `R2,G2,B2` from `COLOR2`
- **Source:** baxxter, orange, crusaders
### rembg-custom-gradient-a
```text
rembg-custom-gradient-a
rembg with gmic: fx_custom_gradient 0,0,0,1,2,1,0,128,100,100,2,0,1,0,"",1,0,R1,G1,B1,0,255,R2,G2,B2,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
rembg
```
- **Gradient direction:** COLOR1 → COLOR2 on the rembg cutout
- **Source:** baxxter, orange, crusaders
### rembg-custom-gradient-b
```text
rembg-custom-gradient-b
rembg with gmic: fx_custom_gradient 0,0,0,1,2,1,0,128,100,100,2,0,1,0,"",1,0,R2,G2,B2,255,R1,G1,B1,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
rembg
```
- **Gradient direction:** COLOR2 → COLOR1 on the rembg cutout
- **Source:** baxxter, orange, crusaders
### original-jpr-smooth-rembg
```text
original-jpr-smooth-rembg
original
rembg with gmic: jpr_gradient_smooth 0,1.5
make layer 5% bigger then crop to original size
rembg
```
- **Middle layer:** jpr smooth on rembg, then scale 5% + center crop
- **Source:** baxxter, crusaders
### bokeh-oktagon
```text
bokeh-oktagon
original
original with gmic: fx_bokeh 3,5,0,30,8,4,0.3,0.2,R1,G1,B1,ALPHA1,0.7,30,20,20,1,2,R2,G2,B2,ALPHA2,0.15
rembg
```
- **3 layers:** composite(original, input_bokeh) → composite(result, rembg)
- **Colors:** `R1,G1,B1` from **COLOR1**; `R2,G2,B2` from **COLOR2**; `ALPHA1` / `ALPHA2` are 0255 (defaults 160 / 110)
- **G'MIC:** octagonal bokeh discs — first color pair `R1,G1,B1,ALPHA1`, second `R2,G2,B2,ALPHA2`
### original-jpr-smooth-grey-alpha-rembg
```text
original-jpr-smooth-grey-alpha-rembg
original
rembg with gmic: jpr_gradient_smooth 0,1.5
rembg with gmic: gmic-jpr-smooth
#7f7f7f to alpha
make layer 5% bigger then crop to original size
rembg
```
- **Middle layer:** jpr smooth → `#7f7f7f to alpha` → scale 5% + crop
- **Source:** crusaders, baxxter_2
### color-bg-drop-shadow-rembg
```text
color-bg-drop-shadow-rembg
COLOR1 background
rembg with gmic: fx_drop_shadow3d 0,0,0,10,1,1,2,0.5,R2,G2,B2,200,0
rembg
```
- **3 layers:** solid COLOR1 bg, drop-shadow rembg in middle, rembg on top
- **Source:** orange (`COLOR1 = #AA4E00`), crusaders
### yellow-bg-drop-shadow-rembg
```text
yellow-bg-drop-shadow-rembg
YELLOW background
rembg with gmic: fx_drop_shadow3d 0,0,0,10,1,1,2,0.5,R2,G2,B2,200,0
rembg
```
- **Source:** `pipelines/pipeline_baxxter_2.py` (`YELLOW = #d7fd00`, shadow RGB from baxxter COLOR2)
### resize-2000px
```text
resize-2000px
resize max edge 2000
```
- **Single-step preset** — not a composite
- **Source:** `pipelines/pipeline_2000px.py`
### openrouter-enhance
```text
openrouter-enhance
openrouter edit PROMPT MODEL
```
- **Single-step** — subtle enhancement prompt from `pipelines/example_ai.py`
- **Typical:** `max_edge=2048`
### team-gallery-match
```text
team-gallery-match
openrouter gallery match TEMPLATE_IMAGE
```
- **Single-step** — style-match new photos to existing gallery reference
- **Source:** `pipelines/pipeline_team_gallery_match.py`
---
## 6. GMIC color derivation
G'MIC commands in parameterized recipes use **comma-separated RGB integers**, not hex.
### Hex → RGB
1. Take `#RRGGBB` or strip alpha from `#RRGGBBAA` (last two hex digits = alpha, ignored for GMIC tuples).
2. Split into three byte pairs → decimal 0255.
| Hex | R,G,B |
|-----|-------|
| `#AA4E00` | 170, 78, 0 |
| `#EDDD93` | 237, 221, 147 |
| `#d7fd00` | 215, 253, 0 |
| `#fc0ade` | 252, 10, 222 |
| `#0064b0` | 0, 100, 176 |
| `#00badf` | 0, 186, 223 |
### Where colors go
| Recipe | Color usage |
|--------|-------------|
| `original-drop-shadow-rembg` | shadow tint: `R2,G2,B2` from **COLOR2** in `fx_drop_shadow3d …,R2,G2,B2,200,0` |
| `original-bwrecolor-rembg` | highlight `R2,G2,B2`, accent `R1,G1,B1` in `fx_bwrecolorize` |
| `rembg-custom-gradient-a` | starts with `R1,G1,B1`, transitions via `R2,G2,B2` |
| `rembg-custom-gradient-b` | starts with `R2,G2,B2`, transitions via `R1,G1,B1` |
| `bokeh-oktagon` | bokeh tints `R1,G1,B1,ALPHA1` and `R2,G2,B2,ALPHA2` in `fx_bokeh` |
| `imagemagick_fill` backgrounds | use full hex including alpha if needed (`#d7fd00ff`) |
### Agent workflow
1. Define `COLOR1` and `COLOR2` as constants at the top of the pipeline script.
2. Add a short comment with derived RGB tuples (as in `pipeline_orange.py`).
3. Build GMIC command strings using those integers.
---
## 7. Usage examples
### Compose by recipe name
```text
Create pipeline "foo" with recipes colorsplash and rembg-radial-2colors, COLOR1=#123456, COLOR2=#654321
```
Agent: shared `rembg` step, `gmic_grayscale`, two `imagemagick_fill` gradients, two `composite` outputs (separate variants, not chained).
### Pipeline recipe with inclusion
```text
Create pipeline "watermark" with recipe colorsplash-watermark, STYLE="Watermark F12.rocks"
```
Agent: expand `colorsplash` inside `colorsplash-watermark`, then chain `darktable_style` on the composite output.
### Pipeline chain (not a combine)
```text
colorsplash-watermark
colorsplash
colorsplash # expand combine first
darktable style STYLE
```
### With GIMP layer export
---
```text
Create pipeline "foo" with recipes colorsplash, rembg-radial-2colors, and xcf-stack
## Agent example
Request: *pipeline with colorsplash + rembg-radial-2colors, COLOR1=#244a89, COLOR2=#c22518*
```python
rembg_out = p.step("rembg", inputs="input")
grayscale = p.step("gmic_grayscale", inputs="input")
gradient_bg = p.step("imagemagick_fill", inputs="input", color1=COLOR1, color2=COLOR2, gradient=True, radial=True)
p.step("composite", inputs=[grayscale, rembg_out]) # colorsplash
p.step("composite", inputs=[gradient_bg, rembg_out]) # rembg-radial-2colors
```
Agent: build all composite steps, then `p.step("xcf_stack", inputs=["input", rembg_out, …, composite_final])` listing every layer bottom → top.
3-layer combine (drop shadow on original):
```text
xcf-stack
xcf stack layers: input, rembg, composite_colorsplash, composite_radial, …
```python
rembg_shadow = p.step("gmic", inputs=rembg_out, command=GMIC_DROP_SHADOW)
mid = p.step("composite", inputs=["input", rembg_shadow])
p.step("composite", inputs=[mid, rembg_out])
```
### Full combine list (baxxter style)
xcf export:
Paste a raw list of `combine` blocks (bottom → top). Agent maps each block to a recipe id from section 5 or expands inline steps. Reuse one `rembg` step for the whole pipeline.
### Extend existing pipeline
```text
Add recipe color-bg-drop-shadow-rembg to pipeline_orange.py with current COLOR1
```python
p.step("xcf_stack", inputs=["input", rembg_out, grayscale, composite_colorsplash, ...])
```
Agent: read existing constants, append new composite steps using the same `rembg_out` and `rembg_shadow` pattern.
### Human notes in prompts
You may add `# notizen` in recipe blocks in this file anytime — agents ignore them per section 1 rule 11.