API Node
- Image
- BFL
- Luma
- Recraft
- Ideogram
- Stability AI
- OpenAI
- Video
Ideogram V3 - ComfyUI 原生节点文档
Ideogram V3 - ComfyUI 原生节点文档
使用Ideogram最新V3 API创建顶级质量图像和文字渲染的节点
此节点连接到Ideogram V3 API,来完成对应的图像生成任务。
目前此节点支持两种图像生成模式:
- 文生图模式 - 从纯文本提示词生成全新图像
- 局部重绘模式(Inpainting) - 通过提供原始图像和遮罩来重新生成特定区域
文生图模式
这是默认模式,当没有提供图像和遮罩输入时激活。只需提供提示词和所需的参数:
- 在提示词字段中描述你想要的图像
- 选择适当的宽高比或分辨率
- 调整其他参数如魔法提示、种子和渲染质量
- 运行节点生成图像
局部重绘模式
重要提示:此模式要求同时提供图像和遮罩输入。如果只提供其中一个,节点将抛出错误。
- 将原始图像连接到
image
输入端口 - 创建一个与原图相同尺寸的遮罩,白色区域表示要重新生成的部分
- 将遮罩连接到
mask
输入端口 - 在提示词中描述要在遮罩区域生成的内容
- 运行节点执行局部编辑
参数说明
基本参数
参数 | 类型 | 默认值 | 说明 |
---|---|---|---|
prompt | 字符串 | "" | 描述要生成内容的文本提示词 |
aspect_ratio | 选择项 | ”1:1” | 图像宽高比(仅文生图模式有效) |
resolution | 选择项 | ”Auto” | 图像分辨率,设置后会覆盖宽高比设置 |
magic_prompt_option | 选择项 | ”AUTO” | 魔法提示增强选项:AUTO、ON或OFF |
seed | 整数 | 0 | 随机种子值,设为0则随机生成 |
num_images | 整数 | 1 | 生成图像数量(1-8) |
rendering_speed | 选择项 | ”BALANCED” | 渲染速度:BALANCED、TURBO或QUALITY |
可选参数
参数 | 类型 | 说明 |
---|---|---|
image | 图像 | 用于局部重绘模式的输入图像(必须与mask一起提供) |
mask | 遮罩 | 用于局部重绘的遮罩,白色区域将被替换(必须与image一起提供) |
输出
输出 | 类型 | 说明 |
---|---|---|
IMAGE | 图像 | 生成的图像结果 |
工作原理
Ideogram V3节点使用最先进的AI模型处理用户输入,能够理解复杂的设计意图和文字排版需求。它支持两种主要模式:
- 生成模式:从文本提示创建全新图像
- 编辑模式:使用原始图像+遮罩组合,只替换遮罩指定的区域
源码参考
[节点源码 (更新于2025-05-03)]
class IdeogramV3(ComfyNodeABC):
"""
Generates images synchronously using the Ideogram V3 model.
Supports both regular image generation from text prompts and image editing with mask.
Images links are available for a limited period of time; if you would like to keep the image, you must download it.
"""
def __init__(self):
pass
@classmethod
def INPUT_TYPES(cls) -> InputTypeDict:
return {
"required": {
"prompt": (
IO.STRING,
{
"multiline": True,
"default": "",
"tooltip": "Prompt for the image generation or editing",
},
),
},
"optional": {
"image": (
IO.IMAGE,
{
"default": None,
"tooltip": "Optional reference image for image editing.",
},
),
"mask": (
IO.MASK,
{
"default": None,
"tooltip": "Optional mask for inpainting (white areas will be replaced)",
},
),
"aspect_ratio": (
IO.COMBO,
{
"options": list(V3_RATIO_MAP.keys()),
"default": "1:1",
"tooltip": "The aspect ratio for image generation. Ignored if resolution is not set to Auto.",
},
),
"resolution": (
IO.COMBO,
{
"options": V3_RESOLUTIONS,
"default": "Auto",
"tooltip": "The resolution for image generation. If not set to Auto, this overrides the aspect_ratio setting.",
},
),
"magic_prompt_option": (
IO.COMBO,
{
"options": ["AUTO", "ON", "OFF"],
"default": "AUTO",
"tooltip": "Determine if MagicPrompt should be used in generation",
},
),
"seed": (
IO.INT,
{
"default": 0,
"min": 0,
"max": 2147483647,
"step": 1,
"control_after_generate": True,
"display": "number",
},
),
"num_images": (
IO.INT,
{"default": 1, "min": 1, "max": 8, "step": 1, "display": "number"},
),
"rendering_speed": (
IO.COMBO,
{
"options": ["BALANCED", "TURBO", "QUALITY"],
"default": "BALANCED",
"tooltip": "Controls the trade-off between generation speed and quality",
},
),
},
"hidden": {"auth_token": "AUTH_TOKEN_COMFY_ORG"},
}
RETURN_TYPES = (IO.IMAGE,)
FUNCTION = "api_call"
CATEGORY = "api node/image/ideogram/v3"
DESCRIPTION = cleandoc(__doc__ or "")
API_NODE = True
def api_call(
self,
prompt,
image=None,
mask=None,
resolution="Auto",
aspect_ratio="1:1",
magic_prompt_option="AUTO",
seed=0,
num_images=1,
rendering_speed="BALANCED",
auth_token=None,
):
# Check if both image and mask are provided for editing mode
if image is not None and mask is not None:
# Edit mode
path = "/proxy/ideogram/ideogram-v3/edit"
# Process image and mask
input_tensor = image.squeeze().cpu()
# Validate mask dimensions match image
if mask.shape[1:] != image.shape[1:-1]:
raise Exception("Mask and Image must be the same size")
# Process image
img_np = (input_tensor.numpy() * 255).astype(np.uint8)
img = Image.fromarray(img_np)
img_byte_arr = io.BytesIO()
img.save(img_byte_arr, format="PNG")
img_byte_arr.seek(0)
img_binary = img_byte_arr
img_binary.name = "image.png"
# Process mask - white areas will be replaced
mask_np = (mask.squeeze().cpu().numpy() * 255).astype(np.uint8)
mask_img = Image.fromarray(mask_np)
mask_byte_arr = io.BytesIO()
mask_img.save(mask_byte_arr, format="PNG")
mask_byte_arr.seek(0)
mask_binary = mask_byte_arr
mask_binary.name = "mask.png"
# Create edit request
edit_request = IdeogramV3EditRequest(
prompt=prompt,
rendering_speed=rendering_speed,
)
# Add optional parameters
if magic_prompt_option != "AUTO":
edit_request.magic_prompt = magic_prompt_option
if seed != 0:
edit_request.seed = seed
if num_images > 1:
edit_request.num_images = num_images
# Execute the operation for edit mode
operation = SynchronousOperation(
endpoint=ApiEndpoint(
path=path,
method=HttpMethod.POST,
request_model=IdeogramV3EditRequest,
response_model=IdeogramGenerateResponse,
),
request=edit_request,
files={
"image": img_binary,
"mask": mask_binary,
},
content_type="multipart/form-data",
auth_token=auth_token,
)
elif image is not None or mask is not None:
# If only one of image or mask is provided, raise an error
raise Exception("Ideogram V3 image editing requires both an image AND a mask")
else:
# Generation mode
path = "/proxy/ideogram/ideogram-v3/generate"
# Create generation request
gen_request = IdeogramV3Request(
prompt=prompt,
rendering_speed=rendering_speed,
)
# Handle resolution vs aspect ratio
if resolution != "Auto":
gen_request.resolution = resolution
elif aspect_ratio != "1:1":
v3_aspect = V3_RATIO_MAP.get(aspect_ratio)
if v3_aspect:
gen_request.aspect_ratio = v3_aspect
# Add optional parameters
if magic_prompt_option != "AUTO":
gen_request.magic_prompt = magic_prompt_option
if seed != 0:
gen_request.seed = seed
if num_images > 1:
gen_request.num_images = num_images
# Execute the operation for generation mode
operation = SynchronousOperation(
endpoint=ApiEndpoint(
path=path,
method=HttpMethod.POST,
request_model=IdeogramV3Request,
response_model=IdeogramGenerateResponse,
),
request=gen_request,
auth_token=auth_token,
)
# Execute the operation and process response
response = operation.execute()
if not response.data or len(response.data) == 0:
raise Exception("No images were generated in the response")
image_urls = [image_data.url for image_data in response.data if image_data.url]
if not image_urls:
raise Exception("No image URLs were generated in the response")
return (download_and_process_images(image_urls),)