@@ -255,6 +255,7 @@ def define_schema(cls):
255
255
display_name = "Ideogram V1" ,
256
256
category = "api node/image/Ideogram" ,
257
257
description = "Generates images using the Ideogram V1 model." ,
258
+ is_api_node = True ,
258
259
inputs = [
259
260
comfy_io .String .Input (
260
261
"prompt" ,
@@ -383,6 +384,7 @@ def define_schema(cls):
383
384
display_name = "Ideogram V2" ,
384
385
category = "api node/image/Ideogram" ,
385
386
description = "Generates images using the Ideogram V2 model." ,
387
+ is_api_node = True ,
386
388
inputs = [
387
389
comfy_io .String .Input (
388
390
"prompt" ,
@@ -552,6 +554,7 @@ def define_schema(cls):
552
554
category = "api node/image/Ideogram" ,
553
555
description = "Generates images using the Ideogram V3 model. "
554
556
"Supports both regular image generation from text prompts and image editing with mask." ,
557
+ is_api_node = True ,
555
558
inputs = [
556
559
comfy_io .String .Input (
557
560
"prompt" ,
@@ -612,11 +615,21 @@ def define_schema(cls):
612
615
),
613
616
comfy_io .Combo .Input (
614
617
"rendering_speed" ,
615
- options = ["BALANCED " , "TURBO" , "QUALITY" ],
616
- default = "BALANCED " ,
618
+ options = ["DEFAULT " , "TURBO" , "QUALITY" ],
619
+ default = "DEFAULT " ,
617
620
tooltip = "Controls the trade-off between generation speed and quality" ,
618
621
optional = True ,
619
622
),
623
+ comfy_io .Image .Input (
624
+ "character_image" ,
625
+ tooltip = "Image to use as character reference." ,
626
+ optional = True ,
627
+ ),
628
+ comfy_io .Mask .Input (
629
+ "character_mask" ,
630
+ tooltip = "Optional mask for character reference image." ,
631
+ optional = True ,
632
+ ),
620
633
],
621
634
outputs = [
622
635
comfy_io .Image .Output (),
@@ -639,12 +652,46 @@ async def execute(
639
652
magic_prompt_option = "AUTO" ,
640
653
seed = 0 ,
641
654
num_images = 1 ,
642
- rendering_speed = "BALANCED" ,
655
+ rendering_speed = "DEFAULT" ,
656
+ character_image = None ,
657
+ character_mask = None ,
643
658
):
644
659
auth = {
645
660
"auth_token" : cls .hidden .auth_token_comfy_org ,
646
661
"comfy_api_key" : cls .hidden .api_key_comfy_org ,
647
662
}
663
+ if rendering_speed == "BALANCED" : # for backward compatibility
664
+ rendering_speed = "DEFAULT"
665
+
666
+ character_img_binary = None
667
+ character_mask_binary = None
668
+
669
+ if character_image is not None :
670
+ input_tensor = character_image .squeeze ().cpu ()
671
+ if character_mask is not None :
672
+ character_mask = resize_mask_to_image (character_mask , character_image , allow_gradient = False )
673
+ character_mask = 1.0 - character_mask
674
+ if character_mask .shape [1 :] != character_image .shape [1 :- 1 ]:
675
+ raise Exception ("Character mask and image must be the same size" )
676
+
677
+ mask_np = (character_mask .squeeze ().cpu ().numpy () * 255 ).astype (np .uint8 )
678
+ mask_img = Image .fromarray (mask_np )
679
+ mask_byte_arr = BytesIO ()
680
+ mask_img .save (mask_byte_arr , format = "PNG" )
681
+ mask_byte_arr .seek (0 )
682
+ character_mask_binary = mask_byte_arr
683
+ character_mask_binary .name = "mask.png"
684
+
685
+ img_np = (input_tensor .numpy () * 255 ).astype (np .uint8 )
686
+ img = Image .fromarray (img_np )
687
+ img_byte_arr = BytesIO ()
688
+ img .save (img_byte_arr , format = "PNG" )
689
+ img_byte_arr .seek (0 )
690
+ character_img_binary = img_byte_arr
691
+ character_img_binary .name = "image.png"
692
+ elif character_mask is not None :
693
+ raise Exception ("Character mask requires character image to be present" )
694
+
648
695
# Check if both image and mask are provided for editing mode
649
696
if image is not None and mask is not None :
650
697
# Edit mode
@@ -693,6 +740,15 @@ async def execute(
693
740
if num_images > 1 :
694
741
edit_request .num_images = num_images
695
742
743
+ files = {
744
+ "image" : img_binary ,
745
+ "mask" : mask_binary ,
746
+ }
747
+ if character_img_binary :
748
+ files ["character_reference_images" ] = character_img_binary
749
+ if character_mask_binary :
750
+ files ["character_mask_binary" ] = character_mask_binary
751
+
696
752
# Execute the operation for edit mode
697
753
operation = SynchronousOperation (
698
754
endpoint = ApiEndpoint (
@@ -702,10 +758,7 @@ async def execute(
702
758
response_model = IdeogramGenerateResponse ,
703
759
),
704
760
request = edit_request ,
705
- files = {
706
- "image" : img_binary ,
707
- "mask" : mask_binary ,
708
- },
761
+ files = files ,
709
762
content_type = "multipart/form-data" ,
710
763
auth_kwargs = auth ,
711
764
)
@@ -739,6 +792,14 @@ async def execute(
739
792
if num_images > 1 :
740
793
gen_request .num_images = num_images
741
794
795
+ files = {}
796
+ if character_img_binary :
797
+ files ["character_reference_images" ] = character_img_binary
798
+ if character_mask_binary :
799
+ files ["character_mask_binary" ] = character_mask_binary
800
+ if files :
801
+ gen_request .style_type = "AUTO"
802
+
742
803
# Execute the operation for generation mode
743
804
operation = SynchronousOperation (
744
805
endpoint = ApiEndpoint (
@@ -748,6 +809,8 @@ async def execute(
748
809
response_model = IdeogramGenerateResponse ,
749
810
),
750
811
request = gen_request ,
812
+ files = files if files else None ,
813
+ content_type = "multipart/form-data" ,
751
814
auth_kwargs = auth ,
752
815
)
753
816
0 commit comments