@@ -349,6 +349,43 @@ def test_parameter_order():
349349 ]
350350
351351
352+ def test_prepare_mask ():
353+ connection_workflows = {"connection1" : make_dummy_graph (42 )}
354+ connection = create_mock_connection (connection_workflows )
355+ workflows = WorkflowCollection (connection )
356+
357+ jobs = JobQueue ()
358+ workspace = CustomWorkspace (workflows , dummy_generate , jobs )
359+
360+ mask = Mask .rectangle (Bounds (10 , 10 , 40 , 40 ), 0 )
361+ canvas_bounds = Bounds (0 , 0 , 100 , 100 )
362+ selection_bounds = Bounds (12 , 12 , 34 , 34 )
363+ selection_node = ComfyNode (0 , "ETN_Selection" , {"context" : "automatic" , "padding" : 3 })
364+
365+ prepared_mask , bounds = workspace .prepare_mask (
366+ selection_node , copy (mask ), selection_bounds , canvas_bounds
367+ )
368+ assert bounds == Bounds (6 , 6 , 48 , 48 ) # mask.bounds + padding // multiple of 8
369+ assert prepared_mask is not None
370+ assert prepared_mask .bounds == Bounds (4 , 4 , 40 , 40 )
371+
372+ selection_node .inputs ["context" ] = "mask_bounds"
373+ prepared_mask , bounds = workspace .prepare_mask (
374+ selection_node , copy (mask ), selection_bounds , canvas_bounds
375+ )
376+ assert bounds == Bounds (9 , 9 , 40 , 40 ) # selection_bounds + padding // multiple of 8
377+ assert prepared_mask is not None
378+ assert prepared_mask .bounds == Bounds (1 , 1 , 40 , 40 )
379+
380+ selection_node .inputs ["context" ] = "entire_image"
381+ prepared_mask , bounds = workspace .prepare_mask (
382+ selection_node , copy (mask ), selection_bounds , canvas_bounds
383+ )
384+ assert bounds == canvas_bounds
385+ assert prepared_mask is not None
386+ assert prepared_mask .bounds == mask .bounds
387+
388+
352389def test_text_output ():
353390 connection_workflows = {"connection1" : make_dummy_graph (42 )}
354391 connection = create_mock_connection (connection_workflows , ComfyObjectInfo ({}))
@@ -490,10 +527,7 @@ def test_expand():
490527 }
491528
492529 w = ComfyWorkflow ()
493- w = workflow .expand_custom (w , input , images , 123 , models )
494-
495- def find_img_id (image : Image ):
496- return next ((id for id , img in w .images .items () if img == image ), "not-found" )
530+ w = workflow .expand_custom (w , input , images , Bounds (0 , 0 , 4 , 4 ), 123 , models )
497531
498532 expected = [
499533 ComfyNode (1 , "ETN_LoadImageCache" , {"id" : img_id (images .initial_image )}),
@@ -554,7 +588,7 @@ def test_expand_animation():
554588 models = ClientModels ()
555589
556590 w = ComfyWorkflow ()
557- w = workflow .expand_custom (w , input , images , 123 , models )
591+ w = workflow .expand_custom (w , input , images , Bounds ( 0 , 0 , 4 , 4 ), 123 , models )
558592
559593 expected = [
560594 ComfyNode (1 , "ETN_LoadImageCache" , {"id" : img_id (in_images [0 ])}),
@@ -582,3 +616,53 @@ def test_expand_animation():
582616 ]
583617 for node in expected :
584618 assert node in w , f"Node { node } not found in\n { json .dumps (w .root , indent = 2 )} "
619+
620+
621+ def test_expand_selection ():
622+ ext = ComfyWorkflow ()
623+ select , select_active , off_x , off_y = ext .add (
624+ "ETN_KritaSelection" , 4 , context = "automatic" , padding = 2
625+ )
626+ canvas , width , height , seed = ext .add ("ETN_KritaCanvas" , 4 )
627+ ext .add (
628+ "Sink" ,
629+ 1 ,
630+ image = canvas ,
631+ width = width ,
632+ height = height ,
633+ mask = select ,
634+ has_selection = select_active ,
635+ offset_x = off_x ,
636+ offset_y = off_y ,
637+ )
638+
639+ params = {}
640+ input = CustomWorkflowInput (workflow = ext .root , params = params )
641+ images = ImageInput .from_extent (Extent (8 , 16 ))
642+ images .initial_image = Image .create (Extent (8 , 16 ), Qt .GlobalColor .red )
643+ images .hires_mask = Image .create (Extent (8 , 16 ), Qt .GlobalColor .green )
644+ bounds = Bounds (2 , 3 , 8 , 16 ) # selection from (2,2) to (6,6)
645+ models = ClientModels ()
646+
647+ w = ComfyWorkflow ()
648+ w = workflow .expand_custom (w , input , images , bounds , 123 , models )
649+
650+ expected = [
651+ ComfyNode (1 , "ETN_LoadImageCache" , {"id" : img_id (images .hires_mask )}),
652+ ComfyNode (2 , "ETN_LoadImageCache" , {"id" : img_id (images .initial_image )}),
653+ ComfyNode (
654+ 3 ,
655+ "Sink" ,
656+ {
657+ "image" : Output (2 , 0 ),
658+ "width" : 8 ,
659+ "height" : 16 ,
660+ "mask" : Output (1 , 1 ),
661+ "has_selection" : True ,
662+ "offset_x" : 2 ,
663+ "offset_y" : 3 ,
664+ },
665+ ),
666+ ]
667+ for node in expected :
668+ assert node in w , f"Node { node } not found in\n { json .dumps (w .root , indent = 2 )} "
0 commit comments