1 Commits

Author SHA1 Message Date
Frank Schwenk 2da66dcb78 Now added delete for real
Test / pytest (push) Failing after 14s
2026-07-27 22:48:16 +02:00
8 changed files with 693 additions and 22 deletions
+9 -2
View File
@@ -35,7 +35,7 @@ class CompositeModule(SubprocessModule):
"mode": Param(
"string",
default="over",
choices=("over", "multiply", "screen"),
choices=("over", "multiply", "screen", "linearburn", "hardmix"),
help="ImageMagick -compose mode",
),
"output_ext": Param(
@@ -55,7 +55,14 @@ class CompositeModule(SubprocessModule):
raise ValueError("composite requires at least one matched input group")
command = self.resolve_command()
mode = ctx.params["mode"]
# ImageMagick accepts these case-insensitively; keep canonical spellings.
mode = {
"over": "Over",
"multiply": "Multiply",
"screen": "Screen",
"linearburn": "LinearBurn",
"hardmix": "HardMix",
}[ctx.params["mode"]]
output_ext = ctx.params["output_ext"]
foreground_opacity = ctx.params["foreground_opacity"]
ctx.output_dir.mkdir(parents=True, exist_ok=True)
+9 -2
View File
@@ -90,6 +90,9 @@ class DarktableStyleModule(SubprocessModule):
)
self.log_image(ctx, index, total, src)
format_name, conf_options = resolve_export_format(src, out_ext)
# darktable-cli options must come before --core; anything after
# --core is parsed as darktable GUI flags (e.g. --style-overwrite
# after --core makes darktable 5.x print usage and fail).
cmd = [
"darktable-cli",
str(src),
@@ -98,12 +101,16 @@ class DarktableStyleModule(SubprocessModule):
style,
"--out-ext",
format_name,
]
if style_overwrite:
cmd.append("--style-overwrite")
cmd.extend(
[
"--core",
"--configdir",
str(config_dir),
]
)
for conf in conf_options:
cmd.extend(["--conf", conf])
if style_overwrite:
cmd.append("--style-overwrite")
run_command(cmd, timeout=self.default_timeout)
+359
View File
@@ -0,0 +1,359 @@
#!/usr/bin/env python3
"""GoBlue — curated Crusaders looks for sideline / blog edits.
Keeps vortex / ink_press / cyan_punch, pulls proven combines from older
pipelines (aichelberg, crusaders, orange, rezepttest) recolored to club blues,
plus a set of new G'MIC mid-layer looks.
"""
from pathlib import Path
from imagepipeline import Pipeline
INPUT = Path(
"/home/frank/pics/20260719_Biberach Beavers - Albershausen Crusaders/"
"darktable_exported/png"
)
OUTPUT_BASE = Path.home() / "pipeline_output"
EXISTING_OUTPUTS: dict[str, Path] = {}
CONTINUE_FROM: Path | None = None
# Club blues (#GoBlue)
COLOR1 = "#0064b0" # 0,100,176
COLOR2 = "#00badf" # 0,186,223
R1, G1, B1 = 0, 100, 176
R2, G2, B2 = 0, 186, 223
ALPHA1 = 160
ALPHA2 = 110
# --- shared / kept from previous goblue ---
GMIC_TONE_MAPPING = "-fx_map_tones 0.5,0.7,0.1,30,0"
GMIC_ANGULAR = "-fx_blur_angular 2.5,50,50,0,0,7,0"
GMIC_INK_WASH = "-fx_ink_wash 0.14,23,0,0.5,0.54,2.25,0,0,0,0,0,0,0,0,0"
GMIC_DROP_SHADOW = f"-fx_drop_shadow3d 0,0,0,10,1,1,2,0.5,{R2},{G2},{B2},200,0"
# --- from aichelberg (on tone-mapped original) ---
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_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"
# --- from crusaders (custom gradient B on rembg) ---
GMIC_GRADIENT_B = (
f'-fx_custom_gradient 0,0,0,1,2,1,0,128,100,100,2,0,1,0,"",1,0,'
f"{R2},{G2},{B2},255,{R1},{G1},{B1},255,255,255,0,255,255,255,255,255,0,255,"
f"255,255,0,255,0,255,0,0,255,255,128,128,128,255,255,0,255,255,0,0,0,0"
)
# --- from rezepttest bokeh, crusaders colors ---
GMIC_BOKEH = (
f"-fx_bokeh 3,5,0,30,8,4,0.3,0.2,{R1},{G1},{B1},{ALPHA1},0.7,30,20,20,1,2,"
f"{R2},{G2},{B2},{ALPHA2},0.15"
)
# --- new mid-layer filters ---
GMIC_LOOSE_PHOTOS = (
"-fx_loose_photos 60,40,50,100,50,360,0,2,255,255,255,50,25,0,0,0,0,0,0,50,1,1,1"
)
GMIC_BLUR_LINEAR = "-fx_blur_linear 10,0.5,0,0,2,7,0"
GMIC_TUNNEL = "-fx_tunnel 4,80,50,50,0.2,0"
GMIC_BARBOUILLAGE = "-samj_Barbouillage_Paint_Daub 2,2,100,0.2,1,4,1,0,8"
# Multi Thresholds with club-blue palette (dark → COLOR1 → COLOR2 → light → near-white)
GMIC_MULTI_THRESHOLD = (
f"-tran_multi_threshold 50,100,150,200,"
f"0,20,40,{R1},{G1},{B1},{R2},{G2},{B2},126,200,227,232,244,252"
)
GMIC_OLDSCHOOL_8BITS = "-fx_8bits 25,800,16"
def main() -> None:
with Pipeline(
name="crusaders-goblue",
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")
tone = p.step("gmic", inputs="input", command=GMIC_TONE_MAPPING, step_id="tone")
# ========== kept from previous goblue ==========
angular = p.step(
"gmic", inputs="input", command=GMIC_ANGULAR, step_id="angular"
)
vortex = p.step("composite", inputs=[angular, rembg_out], step_id="vortex")
ink = p.step("gmic", inputs=tone, command=GMIC_INK_WASH, step_id="ink")
ink_press = p.step("composite", inputs=[ink, rembg_out], step_id="ink_press")
radial_bg = p.step(
"imagemagick_fill",
inputs="input",
color1=COLOR1,
color2=COLOR2,
gradient=True,
radial=True,
step_id="radial_bg",
)
rembg_shadow = p.step(
"gmic", inputs=rembg_out, command=GMIC_DROP_SHADOW, step_id="rembg_shadow"
)
punch_mid = p.step(
"composite", inputs=[radial_bg, rembg_shadow], step_id="punch_mid"
)
cyan_punch = p.step(
"composite", inputs=[punch_mid, rembg_out], step_id="cyan_punch"
)
# ========== from aichelberg (tone → filter → mid → rembg) ==========
input_cutout = p.step(
"gmic", inputs=tone, command=GMIC_CUTOUT, step_id="input_cutout"
)
cutout_mid = p.step(
"composite", inputs=[tone, input_cutout], step_id="cutout_mid"
)
composite_cutout = p.step(
"composite", inputs=[cutout_mid, rembg_out], step_id="composite_cutout"
)
input_huffman = p.step(
"gmic",
inputs=tone,
command=GMIC_HUFFMAN_GLITCHES,
step_id="input_huffman_glitches",
)
huffman_mid = p.step(
"composite",
inputs=[tone, input_huffman],
step_id="huffman_glitches_mid",
)
composite_huffman_glitches = p.step(
"composite",
inputs=[huffman_mid, rembg_out],
step_id="composite_huffman_glitches",
)
input_local_sim = p.step(
"gmic",
inputs=tone,
command=GMIC_LOCAL_SIMILARITY,
step_id="input_local_similarity",
)
local_sim_mid = p.step(
"composite",
inputs=[tone, input_local_sim],
step_id="local_similarity_mid",
)
composite_local_similarity = p.step(
"composite",
inputs=[local_sim_mid, rembg_out],
step_id="composite_local_similarity",
)
input_luma_invert = p.step(
"gmic", inputs=tone, command=GMIC_LUMA_INVERT, step_id="input_luma_invert"
)
luma_invert_mid = p.step(
"composite",
inputs=[tone, 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",
)
input_crayon = p.step(
"gmic",
inputs=tone,
command=GMIC_CRAYONGRAFFITI,
step_id="input_crayongraffiti",
)
crayon_mid = p.step(
"composite",
inputs=[tone, input_crayon],
step_id="crayongraffiti_mid",
)
composite_crayongraffiti = p.step(
"composite",
inputs=[crayon_mid, rembg_out],
step_id="composite_crayongraffiti",
)
# ========== from crusaders ==========
# composite_04: radial club-blue gradient + rembg
composite_04 = p.step(
"composite", inputs=[radial_bg, rembg_out], step_id="composite_04"
)
# composite_12: rembg custom gradient B + rembg
rembg_gradient_b = p.step(
"gmic", inputs=rembg_out, command=GMIC_GRADIENT_B, step_id="rembg_gradient_b"
)
composite_12 = p.step(
"composite", inputs=[rembg_gradient_b, rembg_out], step_id="composite_12"
)
# ========== from orange (composite_02: original + drop shadow + rembg) ==========
shadow_mid = p.step(
"composite", inputs=["input", rembg_shadow], step_id="shadow_mid"
)
composite_02 = p.step(
"composite", inputs=[shadow_mid, rembg_out], step_id="composite_02"
)
# ========== from rezepttest (composite_bokeh, club blues) ==========
input_bokeh = p.step(
"gmic", inputs="input", command=GMIC_BOKEH, step_id="input_bokeh"
)
bokeh_mid = p.step(
"composite", inputs=["input", input_bokeh], step_id="bokeh_mid"
)
composite_bokeh = p.step(
"composite", inputs=[bokeh_mid, rembg_out], step_id="composite_bokeh"
)
# ========== new compositions ==========
# original / loose photos (linearburn 50%) / rembg
loose = p.step(
"gmic", inputs="input", command=GMIC_LOOSE_PHOTOS, step_id="loose_photos"
)
loose_mid = p.step(
"composite",
inputs=["input", loose],
mode="linearburn",
foreground_opacity=0.5,
step_id="loose_photos_mid",
)
composite_loose_photos = p.step(
"composite",
inputs=[loose_mid, rembg_out],
step_id="composite_loose_photos",
)
# original with blur linear / rembg
blur_linear = p.step(
"gmic", inputs="input", command=GMIC_BLUR_LINEAR, step_id="blur_linear"
)
composite_blur_linear = p.step(
"composite",
inputs=[blur_linear, rembg_out],
step_id="composite_blur_linear",
)
# original with tunnel / rembg
tunnel = p.step("gmic", inputs="input", command=GMIC_TUNNEL, step_id="tunnel")
composite_tunnel = p.step(
"composite", inputs=[tunnel, rembg_out], step_id="composite_tunnel"
)
# original with barbouillage / rembg
barbouillage = p.step(
"gmic",
inputs="input",
command=GMIC_BARBOUILLAGE,
step_id="barbouillage",
)
composite_barbouillage = p.step(
"composite",
inputs=[barbouillage, rembg_out],
step_id="composite_barbouillage",
)
# original / luma invert (multiply 50%) / rembg
luma_on_input = p.step(
"gmic",
inputs="input",
command=GMIC_LUMA_INVERT,
step_id="luma_invert_on_input",
)
luma_mul_mid = p.step(
"composite",
inputs=["input", luma_on_input],
mode="multiply",
foreground_opacity=0.5,
step_id="luma_invert_multiply_mid",
)
composite_luma_invert_multiply = p.step(
"composite",
inputs=[luma_mul_mid, rembg_out],
step_id="composite_luma_invert_multiply",
)
# original / multi thresholds (hardmix 50%) / rembg
multi_threshold = p.step(
"gmic",
inputs="input",
command=GMIC_MULTI_THRESHOLD,
step_id="multi_threshold",
)
multi_mid = p.step(
"composite",
inputs=["input", multi_threshold],
mode="hardmix",
foreground_opacity=0.5,
step_id="multi_threshold_mid",
)
composite_multi_threshold = p.step(
"composite",
inputs=[multi_mid, rembg_out],
step_id="composite_multi_threshold",
)
# original / oldschool 8bits (screen) / rembg
oldschool = p.step(
"gmic",
inputs="input",
command=GMIC_OLDSCHOOL_8BITS,
step_id="oldschool_8bits",
)
oldschool_mid = p.step(
"composite",
inputs=["input", oldschool],
mode="screen",
step_id="oldschool_8bits_mid",
)
composite_oldschool_8bits = p.step(
"composite",
inputs=[oldschool_mid, rembg_out],
step_id="composite_oldschool_8bits",
)
p.step(
"xcf_stack",
inputs=[
"input",
rembg_out,
vortex,
ink_press,
cyan_punch,
composite_cutout,
composite_huffman_glitches,
composite_local_similarity,
composite_luma_invert,
composite_crayongraffiti,
composite_04,
composite_12,
composite_02,
composite_bokeh,
composite_loose_photos,
composite_blur_linear,
composite_tunnel,
composite_barbouillage,
composite_luma_invert_multiply,
composite_multi_threshold,
composite_oldschool_8bits,
],
step_id="xcf_looks",
)
output_root = p.run()
print(f"Pipeline finished. Output: {output_root}")
if __name__ == "__main__":
main()
+12 -12
View File
@@ -5,7 +5,7 @@ from pathlib import Path
from imagepipeline import Pipeline
INPUT = Path("/home/frank/pics/20260704_Hellraisers und The Shape Schlossplatz/darktable_exported")
INPUT = Path("/home/frank/pics/20260726_Hellraisers Schlossplatz die Zweite/darktable_exported/png")
OUTPUT_BASE = Path.home() / "pipeline_output"
# Reuse outputs from a previous run or external folder (key = step id, e.g. rembg_01).
@@ -14,24 +14,24 @@ EXISTING_OUTPUTS: dict[str, Path] = {}
# Resume an aborted run: point to its output root folder (or None for a fresh run).
CONTINUE_FROM: Path | None = None
COLOR1 = "#AA4E00"
COLOR2 = "#EDDD93"
COLOR1 = "#732f74"
COLOR2 = "#552577"
# COLOR1 = #AA4E00 -> 170,78,0; COLOR2 = #EDDD93 -> 237,221,147
GMIC_DROP_SHADOW = "-fx_drop_shadow3d 0,0,0,10,1,1,2,0.5,237,221,147,200,0"
# COLOR1 = #732f74 -> 45,18,45; COLOR2 = #552577 -> 33,14,46
GMIC_DROP_SHADOW = "-fx_drop_shadow3d 0,0,0,10,1,1,2,0.5,33,14,46,200,0"
GMIC_BWRECOLOR = (
"-fx_bwrecolorize 0,0,0,0,0,1,0,2,237,221,147,255,170,78,0,255,"
"158,137,189,255,224,191,228,255,170,78,0,255,255,255,255,255,255,255,"
"255,255,170,78,0,255"
"-fx_bwrecolorize 0,0,0,0,0,1,0,2,33,14,46,255,45,18,45,255,"
"158,137,189,255,224,191,228,255,45,18,45,255,255,255,255,255,255,255,"
"255,255,45,18,45,255"
)
GMIC_GRADIENT_A = (
'-fx_custom_gradient 0,0,0,1,2,1,0,128,100,100,2,0,1,0,"",1,0,170,78,0,255,'
"237,221,147,255,255,255,0,255,255,255,255,255,0,255,255,255,0,255,0,255,0,0,"
'-fx_custom_gradient 0,0,0,1,2,1,0,128,100,100,2,0,1,0,"",1,0,45,18,45,255,'
"33,14,46,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_GRADIENT_B = (
'-fx_custom_gradient 0,0,0,1,2,1,0,128,100,100,2,0,1,0,"",1,0,237,221,147,255,'
"170,78,0,255,255,255,0,255,255,255,255,255,0,255,255,255,0,255,0,255,0,0,"
'-fx_custom_gradient 0,0,0,1,2,1,0,128,100,100,2,0,1,0,"",1,0,33,14,46,255,'
"45,18,45,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"
)
+294
View File
@@ -0,0 +1,294 @@
#!/usr/bin/env python3
"""Sports — generic red/yellow looks for sideline / blog edits.
Keeps proven composites from crusaders-goblue (recolored), plus four new
BG/FG G'MIC blend recipes.
"""
from pathlib import Path
from imagepipeline import Pipeline
INPUT = Path(
"/home/frank/pics/20260726_Bikepark Winnenden/darktable_exported/png"
)
OUTPUT_BASE = Path.home() / "pipeline_output"
EXISTING_OUTPUTS: dict[str, Path] = {}
CONTINUE_FROM: Path | None = Path(
"/home/frank/pipeline_output/sports_260726190157"
)
# Standard sports red / yellow
COLOR1 = "#e30613" # 227,6,19
COLOR2 = "#ffcc00" # 255,204,0
R1, G1, B1 = 227, 6, 19
R2, G2, B2 = 255, 204, 0
ALPHA1 = 160
ALPHA2 = 110
# --- shared / kept from goblue ---
GMIC_TONE_MAPPING = "-fx_map_tones 0.5,0.7,0.1,30,0"
GMIC_ANGULAR = "-fx_blur_angular 2.5,50,50,0,0,7,0"
GMIC_INK_WASH = "-fx_ink_wash 0.14,23,0,0.5,0.54,2.25,0,0,0,0,0,0,0,0,0"
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_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_BOKEH = (
f"-fx_bokeh 3,5,0,30,8,4,0.3,0.2,{R1},{G1},{B1},{ALPHA1},0.7,30,20,20,1,2,"
f"{R2},{G2},{B2},{ALPHA2},0.15"
)
GMIC_LOOSE_PHOTOS = (
"-fx_loose_photos 60,40,50,100,50,360,0,2,255,255,255,50,25,0,0,0,0,0,0,50,1,1,1"
)
GMIC_BLUR_LINEAR = "-fx_blur_linear 10,0.5,0,0,2,7,0"
GMIC_TUNNEL = "-fx_tunnel 4,80,50,50,0.2,0"
# --- new BG/FG recipes (filter on copy → G'MIC blend → next layer) ---
# Rainbowify + lchlightness / Autofill Coloring Book + interpolation
GMIC_RAINBOWIFY_AUTOFILL = (
"+fx_rep_rainbowify 0,0,100 blend lchlightness "
"+gui_rep_acb 180,0,1,0,250000 blend interpolation"
)
# Hard Sketch + burn / Jpr Line Edges + add
GMIC_HARDSKETCH_LINE_EDGES = (
"+fx_hardsketchbw 300,50,1,0.1,20,0,4 blend burn "
"+jpr_line_edges 2,2,4,1 blend add"
)
# Blur [Linear] + shapeaverage / Charred Plastic + blue
GMIC_BLUR_CHARRED = (
"+fx_blur_linear 10,0.5,0,0,2,7,0 blend shapeaverage "
"+fx_charred_plastic 1,10,40,1,10,0,0,2,6,5,20,0,11 blend blue"
)
# Colored Pencils + hue / Black Crayon Graffiti + green
GMIC_PENCILS_CRAYON = (
"+fx_cpencil 1.3,50,20,2,2,1 blend hue "
"+fx_crayongraffiti2 300,50,1,0.4,12,1,2,2,0 blend green"
)
def main() -> None:
with Pipeline(
name="sports",
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")
tone = p.step("gmic", inputs="input", command=GMIC_TONE_MAPPING, step_id="tone")
# ========== kept from goblue ==========
angular = p.step(
"gmic", inputs="input", command=GMIC_ANGULAR, step_id="angular"
)
vortex = p.step("composite", inputs=[angular, rembg_out], step_id="vortex")
ink = p.step("gmic", inputs=tone, command=GMIC_INK_WASH, step_id="ink")
ink_press = p.step("composite", inputs=[ink, rembg_out], step_id="ink_press")
input_cutout = p.step(
"gmic", inputs=tone, command=GMIC_CUTOUT, step_id="input_cutout"
)
cutout_mid = p.step(
"composite", inputs=[tone, input_cutout], step_id="cutout_mid"
)
composite_cutout = p.step(
"composite", inputs=[cutout_mid, rembg_out], step_id="composite_cutout"
)
input_huffman = p.step(
"gmic",
inputs=tone,
command=GMIC_HUFFMAN_GLITCHES,
step_id="input_huffman_glitches",
)
huffman_mid = p.step(
"composite",
inputs=[tone, input_huffman],
step_id="huffman_glitches_mid",
)
composite_huffman_glitches = p.step(
"composite",
inputs=[huffman_mid, rembg_out],
step_id="composite_huffman_glitches",
)
input_local_sim = p.step(
"gmic",
inputs=tone,
command=GMIC_LOCAL_SIMILARITY,
step_id="input_local_similarity",
)
local_sim_mid = p.step(
"composite",
inputs=[tone, input_local_sim],
step_id="local_similarity_mid",
)
composite_local_similarity = p.step(
"composite",
inputs=[local_sim_mid, rembg_out],
step_id="composite_local_similarity",
)
input_crayon = p.step(
"gmic",
inputs=tone,
command=GMIC_CRAYONGRAFFITI,
step_id="input_crayongraffiti",
)
crayon_mid = p.step(
"composite",
inputs=[tone, input_crayon],
step_id="crayongraffiti_mid",
)
composite_crayongraffiti = p.step(
"composite",
inputs=[crayon_mid, rembg_out],
step_id="composite_crayongraffiti",
)
input_bokeh = p.step(
"gmic", inputs="input", command=GMIC_BOKEH, step_id="input_bokeh"
)
bokeh_mid = p.step(
"composite", inputs=["input", input_bokeh], step_id="bokeh_mid"
)
composite_bokeh = p.step(
"composite", inputs=[bokeh_mid, rembg_out], step_id="composite_bokeh"
)
loose = p.step(
"gmic", inputs="input", command=GMIC_LOOSE_PHOTOS, step_id="loose_photos"
)
loose_mid = p.step(
"composite",
inputs=["input", loose],
mode="linearburn",
foreground_opacity=0.5,
step_id="loose_photos_mid",
)
composite_loose_photos = p.step(
"composite",
inputs=[loose_mid, rembg_out],
step_id="composite_loose_photos",
)
blur_linear = p.step(
"gmic", inputs="input", command=GMIC_BLUR_LINEAR, step_id="blur_linear"
)
composite_blur_linear = p.step(
"composite",
inputs=[blur_linear, rembg_out],
step_id="composite_blur_linear",
)
tunnel = p.step("gmic", inputs="input", command=GMIC_TUNNEL, step_id="tunnel")
composite_tunnel = p.step(
"composite", inputs=[tunnel, rembg_out], step_id="composite_tunnel"
)
luma_on_input = p.step(
"gmic",
inputs="input",
command=GMIC_LUMA_INVERT,
step_id="luma_invert_on_input",
)
luma_mul_mid = p.step(
"composite",
inputs=["input", luma_on_input],
mode="multiply",
foreground_opacity=0.5,
step_id="luma_invert_multiply_mid",
)
composite_luma_invert_multiply = p.step(
"composite",
inputs=[luma_mul_mid, rembg_out],
step_id="composite_luma_invert_multiply",
)
# ========== new BG/FG recipes ==========
rainbowify_autofill = p.step(
"gmic",
inputs="input",
command=GMIC_RAINBOWIFY_AUTOFILL,
step_id="rainbowify_autofill",
)
composite_rainbowify_autofill = p.step(
"composite",
inputs=[rainbowify_autofill, rembg_out],
step_id="composite_rainbowify_autofill",
)
hardsketch_line_edges = p.step(
"gmic",
inputs="input",
command=GMIC_HARDSKETCH_LINE_EDGES,
step_id="hardsketch_line_edges",
)
composite_hardsketch_line_edges = p.step(
"composite",
inputs=[hardsketch_line_edges, rembg_out],
step_id="composite_hardsketch_line_edges",
)
blur_charred = p.step(
"gmic",
inputs="input",
command=GMIC_BLUR_CHARRED,
step_id="blur_charred",
)
composite_blur_charred = p.step(
"composite",
inputs=[blur_charred, rembg_out],
step_id="composite_blur_charred",
)
pencils_crayon = p.step(
"gmic",
inputs="input",
command=GMIC_PENCILS_CRAYON,
step_id="pencils_crayon",
)
composite_pencils_crayon = p.step(
"composite",
inputs=[pencils_crayon, rembg_out],
step_id="composite_pencils_crayon",
)
p.step(
"xcf_stack",
inputs=[
"input",
rembg_out,
vortex,
ink_press,
composite_cutout,
composite_huffman_glitches,
composite_local_similarity,
composite_crayongraffiti,
composite_bokeh,
composite_loose_photos,
composite_blur_linear,
composite_tunnel,
composite_luma_invert_multiply,
composite_rainbowify_autofill,
composite_hardsketch_line_edges,
composite_blur_charred,
composite_pencils_crayon,
],
step_id="xcf_looks",
)
output_root = p.run()
print(f"Pipeline finished. Output: {output_root}")
if __name__ == "__main__":
main()
+2 -2
View File
@@ -6,7 +6,7 @@ from pathlib import Path
from imagepipeline import Pipeline
INPUT = Path(
"/home/frank/pics/20260712_Aichelberg Indians - Heidelberg Hedgehogs/darktable_exported/edits"
"/home/frank/pics/20260726_Hellraisers Schlossplatz die Zweite/darktable_exported/gimp"
)
OUTPUT_BASE = Path.home() / "pipeline_output"
@@ -21,7 +21,7 @@ def main() -> None:
output_base=OUTPUT_BASE,
) as p:
resized = p.step("imagemagick_resize", inputs="input", max_edge=MAX_EDGE)
p.step("darktable_style", inputs=resized, style=STYLE)
p.step("darktable_style", inputs=resized, style=STYLE, out_ext="jpg")
output_root = p.run()
print(f"Pipeline finished. Output: {output_root}")
+1 -1
View File
@@ -36,10 +36,10 @@ def has_darktable_style(style_name: str, config_dir: Path | None = None) -> bool
style_name,
"--out-ext",
"png",
"--style-overwrite",
"--core",
"--configdir",
str(config),
"--style-overwrite",
]
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode != 0:
+4
View File
@@ -260,6 +260,10 @@ class TestModuleParameters:
def test_composite_mode_choices(self) -> None:
with pytest.raises(ValueError, match="must be one of"):
CompositeModule.validate_module_params({"mode": "invalid"})
params = CompositeModule.validate_module_params({"mode": "linearburn"})
assert params["mode"] == "linearburn"
params = CompositeModule.validate_module_params({"mode": "hardmix"})
assert params["mode"] == "hardmix"
def test_rembg_defaults(self) -> None:
params = RembgModule.validate_module_params({})