From 79e9b6426ff8fe57313f92d62bed421dc8e360b0 Mon Sep 17 00:00:00 2001 From: Acly Date: Tue, 30 Dec 2025 23:47:29 +0100 Subject: [PATCH] Support transmitting partial tiles/crops of the canvas in Krita workflows --- krita.py | 43 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/krita.py b/krita.py index ac36231..7dbbfcc 100644 --- a/krita.py +++ b/krita.py @@ -90,9 +90,11 @@ class KritaOutput(io.ComfyNode): category="krita", inputs=[ io.Image.Input("images"), + io.Int.Input("x", "offset x", default=0), + io.Int.Input("y", "offset y", default=0), io.String.Input("name", default=""), io.Combo.Input( - "batch_mode", OutputBatchMode, "batch_mode", default=OutputBatchMode.default + "batch_mode", OutputBatchMode, "batch mode", default=OutputBatchMode.default ), io.Boolean.Input("resize_canvas", "resize canvas", default=False), ], @@ -103,6 +105,8 @@ class KritaOutput(io.ComfyNode): def execute( cls, images: torch.Tensor, + x: int = 0, + y: int = 0, name="", batch_mode: OutputBatchMode | str = OutputBatchMode.default, resize_canvas=False, @@ -110,6 +114,8 @@ class KritaOutput(io.ComfyNode): batch_mode = batch_mode.value if isinstance(batch_mode, OutputBatchMode) else batch_mode info = { "name": name, + "offset_x": x, + "offset_y": y, "batch_mode": batch_mode, "resize_canvas": resize_canvas, } @@ -171,6 +177,21 @@ class KritaCanvas(io.ComfyNode): return io.NodeOutput(_placeholder_image(), 512, 512, 0) +class SelectionContext(Enum): + automatic = "automatic" + entire_image = "entire image" + mask_bounds = "mask bounds" + + +_selection_context_help = """ +Determines the section (crop bounding box) of the image and mask to transmit: +- automatic: area around the selection determined by Krita settings +- entire image: always use the entire canvas area +- mask bounds: tight bounding box of the current selection + +This affects the Selection and Canvas nodes. The offset x/y outputs indicate the top-left corner of the context area relative to the full canvas.""" + + class KritaSelection(io.ComfyNode): @classmethod def define_schema(cls): @@ -178,12 +199,26 @@ class KritaSelection(io.ComfyNode): node_id="ETN_KritaSelection", display_name="Krita Selection", category="krita", - outputs=[io.Mask.Output(display_name="mask"), io.Boolean.Output(display_name="active")], + inputs=[ + io.Combo.Input( + "context", + options=SelectionContext, + default=SelectionContext.entire_image, + tooltip=_selection_context_help, + ), + io.Int.Input("padding", "padding", default=0, min=0), + ], + outputs=[ + io.Mask.Output("mask", "mask"), + io.Boolean.Output("active", "active"), + io.Int.Output("x", "offset x"), + io.Int.Output("y", "offset y"), + ], ) @classmethod - def execute(cls): - return io.NodeOutput(torch.ones(1, 512, 512), False) + def execute(cls, **kwargs): + return io.NodeOutput(torch.ones(1, 512, 512), False, 0, 0) class KritaImageLayer(io.ComfyNode):