api nodes(Ideogram): add Ideogram Character (#9616)

* api nodes(Ideogram): add Ideogram Character

* rename renderingSpeed default value from 'balanced' to 'default'
This commit is contained in:
Alexander Piskun
2025-09-03 23:17:37 +03:00
committed by GitHub
parent 26d5b86da8
commit 50333f1715
2 changed files with 91 additions and 8 deletions

View File

@@ -951,7 +951,11 @@ class MagicPrompt2(str, Enum):
class StyleType1(str, Enum): class StyleType1(str, Enum):
AUTO = 'AUTO'
GENERAL = 'GENERAL' GENERAL = 'GENERAL'
REALISTIC = 'REALISTIC'
DESIGN = 'DESIGN'
FICTION = 'FICTION'
class ImagenImageGenerationInstance(BaseModel): class ImagenImageGenerationInstance(BaseModel):
@@ -2676,7 +2680,7 @@ class ReleaseNote(BaseModel):
class RenderingSpeed(str, Enum): class RenderingSpeed(str, Enum):
BALANCED = 'BALANCED' DEFAULT = 'DEFAULT'
TURBO = 'TURBO' TURBO = 'TURBO'
QUALITY = 'QUALITY' QUALITY = 'QUALITY'
@@ -4918,6 +4922,14 @@ class IdeogramV3EditRequest(BaseModel):
None, None,
description='A set of images to use as style references (maximum total size 10MB across all style references). The images should be in JPEG, PNG or WebP format.', description='A set of images to use as style references (maximum total size 10MB across all style references). The images should be in JPEG, PNG or WebP format.',
) )
character_reference_images: Optional[List[str]] = Field(
None,
description='Generations with character reference are subject to the character reference pricing. A set of images to use as character references (maximum total size 10MB across all character references), currently only supports 1 character reference image. The images should be in JPEG, PNG or WebP format.'
)
character_reference_images_mask: Optional[List[str]] = Field(
None,
description='Optional masks for character reference images. When provided, must match the number of character_reference_images. Each mask should be a grayscale image of the same dimensions as the corresponding character reference image. The images should be in JPEG, PNG or WebP format.'
)
class IdeogramV3Request(BaseModel): class IdeogramV3Request(BaseModel):
@@ -4951,6 +4963,14 @@ class IdeogramV3Request(BaseModel):
style_type: Optional[StyleType1] = Field( style_type: Optional[StyleType1] = Field(
None, description='The type of style to apply' None, description='The type of style to apply'
) )
character_reference_images: Optional[List[str]] = Field(
None,
description='Generations with character reference are subject to the character reference pricing. A set of images to use as character references (maximum total size 10MB across all character references), currently only supports 1 character reference image. The images should be in JPEG, PNG or WebP format.'
)
character_reference_images_mask: Optional[List[str]] = Field(
None,
description='Optional masks for character reference images. When provided, must match the number of character_reference_images. Each mask should be a grayscale image of the same dimensions as the corresponding character reference image. The images should be in JPEG, PNG or WebP format.'
)
class ImagenGenerateImageResponse(BaseModel): class ImagenGenerateImageResponse(BaseModel):

View File

@@ -255,6 +255,7 @@ class IdeogramV1(comfy_io.ComfyNode):
display_name="Ideogram V1", display_name="Ideogram V1",
category="api node/image/Ideogram", category="api node/image/Ideogram",
description="Generates images using the Ideogram V1 model.", description="Generates images using the Ideogram V1 model.",
is_api_node=True,
inputs=[ inputs=[
comfy_io.String.Input( comfy_io.String.Input(
"prompt", "prompt",
@@ -383,6 +384,7 @@ class IdeogramV2(comfy_io.ComfyNode):
display_name="Ideogram V2", display_name="Ideogram V2",
category="api node/image/Ideogram", category="api node/image/Ideogram",
description="Generates images using the Ideogram V2 model.", description="Generates images using the Ideogram V2 model.",
is_api_node=True,
inputs=[ inputs=[
comfy_io.String.Input( comfy_io.String.Input(
"prompt", "prompt",
@@ -552,6 +554,7 @@ class IdeogramV3(comfy_io.ComfyNode):
category="api node/image/Ideogram", category="api node/image/Ideogram",
description="Generates images using the Ideogram V3 model. " description="Generates images using the Ideogram V3 model. "
"Supports both regular image generation from text prompts and image editing with mask.", "Supports both regular image generation from text prompts and image editing with mask.",
is_api_node=True,
inputs=[ inputs=[
comfy_io.String.Input( comfy_io.String.Input(
"prompt", "prompt",
@@ -612,11 +615,21 @@ class IdeogramV3(comfy_io.ComfyNode):
), ),
comfy_io.Combo.Input( comfy_io.Combo.Input(
"rendering_speed", "rendering_speed",
options=["BALANCED", "TURBO", "QUALITY"], options=["DEFAULT", "TURBO", "QUALITY"],
default="BALANCED", default="DEFAULT",
tooltip="Controls the trade-off between generation speed and quality", tooltip="Controls the trade-off between generation speed and quality",
optional=True, optional=True,
), ),
comfy_io.Image.Input(
"character_image",
tooltip="Image to use as character reference.",
optional=True,
),
comfy_io.Mask.Input(
"character_mask",
tooltip="Optional mask for character reference image.",
optional=True,
),
], ],
outputs=[ outputs=[
comfy_io.Image.Output(), comfy_io.Image.Output(),
@@ -639,12 +652,46 @@ class IdeogramV3(comfy_io.ComfyNode):
magic_prompt_option="AUTO", magic_prompt_option="AUTO",
seed=0, seed=0,
num_images=1, num_images=1,
rendering_speed="BALANCED", rendering_speed="DEFAULT",
character_image=None,
character_mask=None,
): ):
auth = { auth = {
"auth_token": cls.hidden.auth_token_comfy_org, "auth_token": cls.hidden.auth_token_comfy_org,
"comfy_api_key": cls.hidden.api_key_comfy_org, "comfy_api_key": cls.hidden.api_key_comfy_org,
} }
if rendering_speed == "BALANCED": # for backward compatibility
rendering_speed = "DEFAULT"
character_img_binary = None
character_mask_binary = None
if character_image is not None:
input_tensor = character_image.squeeze().cpu()
if character_mask is not None:
character_mask = resize_mask_to_image(character_mask, character_image, allow_gradient=False)
character_mask = 1.0 - character_mask
if character_mask.shape[1:] != character_image.shape[1:-1]:
raise Exception("Character mask and image must be the same size")
mask_np = (character_mask.squeeze().cpu().numpy() * 255).astype(np.uint8)
mask_img = Image.fromarray(mask_np)
mask_byte_arr = BytesIO()
mask_img.save(mask_byte_arr, format="PNG")
mask_byte_arr.seek(0)
character_mask_binary = mask_byte_arr
character_mask_binary.name = "mask.png"
img_np = (input_tensor.numpy() * 255).astype(np.uint8)
img = Image.fromarray(img_np)
img_byte_arr = BytesIO()
img.save(img_byte_arr, format="PNG")
img_byte_arr.seek(0)
character_img_binary = img_byte_arr
character_img_binary.name = "image.png"
elif character_mask is not None:
raise Exception("Character mask requires character image to be present")
# Check if both image and mask are provided for editing mode # Check if both image and mask are provided for editing mode
if image is not None and mask is not None: if image is not None and mask is not None:
# Edit mode # Edit mode
@@ -693,6 +740,15 @@ class IdeogramV3(comfy_io.ComfyNode):
if num_images > 1: if num_images > 1:
edit_request.num_images = num_images edit_request.num_images = num_images
files = {
"image": img_binary,
"mask": mask_binary,
}
if character_img_binary:
files["character_reference_images"] = character_img_binary
if character_mask_binary:
files["character_mask_binary"] = character_mask_binary
# Execute the operation for edit mode # Execute the operation for edit mode
operation = SynchronousOperation( operation = SynchronousOperation(
endpoint=ApiEndpoint( endpoint=ApiEndpoint(
@@ -702,10 +758,7 @@ class IdeogramV3(comfy_io.ComfyNode):
response_model=IdeogramGenerateResponse, response_model=IdeogramGenerateResponse,
), ),
request=edit_request, request=edit_request,
files={ files=files,
"image": img_binary,
"mask": mask_binary,
},
content_type="multipart/form-data", content_type="multipart/form-data",
auth_kwargs=auth, auth_kwargs=auth,
) )
@@ -739,6 +792,14 @@ class IdeogramV3(comfy_io.ComfyNode):
if num_images > 1: if num_images > 1:
gen_request.num_images = num_images gen_request.num_images = num_images
files = {}
if character_img_binary:
files["character_reference_images"] = character_img_binary
if character_mask_binary:
files["character_mask_binary"] = character_mask_binary
if files:
gen_request.style_type = "AUTO"
# Execute the operation for generation mode # Execute the operation for generation mode
operation = SynchronousOperation( operation = SynchronousOperation(
endpoint=ApiEndpoint( endpoint=ApiEndpoint(
@@ -748,6 +809,8 @@ class IdeogramV3(comfy_io.ComfyNode):
response_model=IdeogramGenerateResponse, response_model=IdeogramGenerateResponse,
), ),
request=gen_request, request=gen_request,
files=files if files else None,
content_type="multipart/form-data",
auth_kwargs=auth, auth_kwargs=auth,
) )