Files
imagepipeline/pipelines/pipeline_aichelberg_indians.py
T
Frank Schwenk 9b6c80da42 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>
2026-07-13 10:15:28 +02:00

279 lines
9.2 KiB
Python

#!/usr/bin/env python3
"""Aichelberg Indians pipeline — tone mapping, gmic variants, xcf export."""
from pathlib import Path
from imagepipeline import Pipeline
INPUT = Path(
"/home/frank/pics/20260712_Aichelberg Indians - Heidelberg Hedgehogs/darktable_exported"
)
OUTPUT_BASE = Path.home() / "pipeline_output"
EXISTING_OUTPUTS: dict[str, Path] = {}
CONTINUE_FROM = Path("/home/frank/pipeline_output/aichelberg-indians_260713081414")
COLOR1 = "#244a89"
COLOR2 = "#c22518"
# COLOR1 = #244a89 -> 36,74,137; COLOR2 = #c22518 -> 194,37,24
ALPHA1 = 160
ALPHA2 = 110
GMIC_TONE_MAPPING = "-fx_map_tones 0.5,0.7,0.1,30,0"
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_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_DROP_SHADOW = "-fx_drop_shadow3d 0,0,0,10,1,1,2,0.5,194,37,24,200,0"
GMIC_BOKEH = (
f"-fx_bokeh 3,5,0,30,8,4,0.3,0.2,36,74,137,{ALPHA1},0.7,30,20,20,1,2,"
f"194,37,24,{ALPHA2},0.15"
)
def main() -> None:
with Pipeline(
name="aichelberg-indians",
input_dir=INPUT,
output_base=OUTPUT_BASE,
existing_outputs=EXISTING_OUTPUTS or None,
continue_from=CONTINUE_FROM,
) as p:
rembg_out = p.step("rembg", inputs="input", step_id="rembg_out")
# recipe: gmic-tone-mapping
input_tone_map = p.step(
"gmic", inputs="input", command=GMIC_TONE_MAPPING, step_id="input_tone_map"
)
# recipe: gmic-tone-mapping-rembg
rembg_tone_map = p.step(
"gmic", inputs=rembg_out, command=GMIC_TONE_MAPPING, step_id="rembg_tone_map"
)
# recipe: gmic-feltpen-rembg
rembg_feltpen = p.step(
"gmic", inputs=rembg_out, command=GMIC_FELTPEN, step_id="rembg_feltpen"
)
composite_feltpen = p.step(
"composite", inputs=[rembg_feltpen, rembg_out], step_id="composite_feltpen"
)
# recipe: gmic-edges-rembg
rembg_edges = p.step(
"gmic", inputs=rembg_out, command=GMIC_EDGES, step_id="rembg_edges"
)
composite_edges = p.step(
"composite", inputs=[rembg_edges, rembg_out], step_id="composite_edges"
)
# recipe: gmic-charred-plastic-rembg
rembg_charred_plastic = p.step(
"gmic",
inputs=rembg_out,
command=GMIC_CHARRED_PLASTIC,
step_id="rembg_charred_plastic",
)
composite_charred_plastic = p.step(
"composite",
inputs=[rembg_charred_plastic, rembg_out],
step_id="composite_charred_plastic",
)
# recipe: gmic-neon-rembg
rembg_neon = p.step(
"gmic", inputs=rembg_out, command=GMIC_NEON, step_id="rembg_neon"
)
composite_neon = p.step(
"composite", inputs=[rembg_neon, rembg_out], step_id="composite_neon"
)
# recipe: gmic-cutout-rembg (tone-mapped input as original)
input_cutout = p.step(
"gmic", inputs=input_tone_map, command=GMIC_CUTOUT, step_id="input_cutout"
)
cutout_mid = p.step(
"composite", inputs=[input_tone_map, input_cutout], step_id="cutout_mid"
)
composite_cutout = p.step(
"composite", inputs=[cutout_mid, rembg_out], step_id="composite_cutout"
)
# recipe: gmic-huffman-glitches-rembg
input_huffman_glitches = p.step(
"gmic",
inputs=input_tone_map,
command=GMIC_HUFFMAN_GLITCHES,
step_id="input_huffman_glitches",
)
huffman_glitches_mid = p.step(
"composite",
inputs=[input_tone_map, input_huffman_glitches],
step_id="huffman_glitches_mid",
)
composite_huffman_glitches = p.step(
"composite",
inputs=[huffman_glitches_mid, rembg_out],
step_id="composite_huffman_glitches",
)
# recipe: gmic-queryprimary-rembg
input_queryprimary = p.step(
"gmic",
inputs=input_tone_map,
command=GMIC_QUERYPRIMARY,
step_id="input_queryprimary",
)
queryprimary_mid = p.step(
"composite",
inputs=[input_tone_map, input_queryprimary],
step_id="queryprimary_mid",
)
composite_queryprimary = p.step(
"composite",
inputs=[queryprimary_mid, rembg_out],
step_id="composite_queryprimary",
)
# recipe: gmic-local-similarity-rembg
input_local_similarity = p.step(
"gmic",
inputs=input_tone_map,
command=GMIC_LOCAL_SIMILARITY,
step_id="input_local_similarity",
)
local_similarity_mid = p.step(
"composite",
inputs=[input_tone_map, input_local_similarity],
step_id="local_similarity_mid",
)
composite_local_similarity = p.step(
"composite",
inputs=[local_similarity_mid, rembg_out],
step_id="composite_local_similarity",
)
# recipe: gmic-luma-invert-rembg
input_luma_invert = p.step(
"gmic",
inputs=input_tone_map,
command=GMIC_LUMA_INVERT,
step_id="input_luma_invert",
)
luma_invert_mid = p.step(
"composite",
inputs=[input_tone_map, input_luma_invert],
step_id="luma_invert_mid",
)
composite_luma_invert = p.step(
"composite",
inputs=[luma_invert_mid, rembg_out],
step_id="composite_luma_invert",
)
# recipe: gmic-crayongraffiti-rembg
input_crayongraffiti = p.step(
"gmic",
inputs=input_tone_map,
command=GMIC_CRAYONGRAFFITI,
step_id="input_crayongraffiti",
)
crayongraffiti_mid = p.step(
"composite",
inputs=[input_tone_map, input_crayongraffiti],
step_id="crayongraffiti_mid",
)
composite_crayongraffiti = p.step(
"composite",
inputs=[crayongraffiti_mid, rembg_out],
step_id="composite_crayongraffiti",
)
# recipe: gmic-anaglyph-rembg
input_anaglyph = p.step(
"gmic", inputs=input_tone_map, command=GMIC_ANAGLYPH, step_id="input_anaglyph"
)
anaglyph_mid = p.step(
"composite", inputs=[input_tone_map, input_anaglyph], step_id="anaglyph_mid"
)
composite_anaglyph = p.step(
"composite", inputs=[anaglyph_mid, rembg_out], step_id="composite_anaglyph"
)
# recipe: xcf-stack — layers up to composites (excludes bokeh + color-bg-drop-shadow)
p.step(
"xcf_stack",
inputs=[
"input",
rembg_out,
input_tone_map,
rembg_tone_map,
rembg_feltpen,
rembg_edges,
rembg_charred_plastic,
rembg_neon,
input_cutout,
input_huffman_glitches,
input_queryprimary,
input_local_similarity,
input_luma_invert,
input_crayongraffiti,
input_anaglyph,
composite_feltpen,
composite_edges,
composite_charred_plastic,
composite_neon,
composite_cutout,
composite_huffman_glitches,
composite_queryprimary,
composite_local_similarity,
composite_luma_invert,
composite_crayongraffiti,
composite_anaglyph,
],
)
# recipe: bokeh-oktagon (tone-mapped input as original)
input_bokeh = p.step(
"gmic", inputs=input_tone_map, command=GMIC_BOKEH, step_id="input_bokeh"
)
bokeh_mid = p.step(
"composite", inputs=[input_tone_map, input_bokeh], step_id="bokeh_mid"
)
p.step("composite", inputs=[bokeh_mid, rembg_out], step_id="composite_bokeh")
# recipe: color-bg-drop-shadow-rembg
color_bg = p.step(
"imagemagick_fill", inputs="input", color1=COLOR1, step_id="color_bg"
)
rembg_shadow = p.step(
"gmic", inputs=rembg_out, command=GMIC_DROP_SHADOW, step_id="rembg_shadow"
)
shadow_color_mid = p.step(
"composite", inputs=[color_bg, rembg_shadow], step_id="shadow_color_mid"
)
p.step(
"composite",
inputs=[shadow_color_mid, rembg_out],
step_id="composite_color_bg_shadow",
)
output_root = p.run()
print(f"Pipeline finished. Output: {output_root}")
if __name__ == "__main__":
main()