メインコンテンツへスキップ
ComfyUI ネイティブ Ideogram V3 ノード このノードは Ideogram V3 API に接続し、画像生成タスクを実行します。 現在、このノードは以下の2つの画像生成モードをサポートしています:
  • テキストから画像へ(Text-to-Image)モード:テキストプロンプトから新しい画像を生成
  • インペインティング(Inpainting)モード:元の画像とマスクを指定することで、特定の領域を再生成

テキストから画像へ(Text-to-Image)モード

これはデフォルトのモードであり、画像またはマスクの入力が提供されていない場合に有効になります。単にプロンプトと必要なパラメータを指定してください:
  1. プロンプト欄に、生成したい画像の内容を記述します
  2. 適切なアスペクト比または解像度を選択します
  3. マジックプロンプト、シード、レンダリング品質などのその他のパラメータを調整します
  4. ノードを実行して画像を生成します

インペインティング(Inpainting)モード

重要なお知らせ:このモードでは、画像とマスクの両方の入力が必須です。片方のみが提供された場合、ノードはエラーをスローします。
  1. 元の画像を image 入力ポートに接続します
  2. 元の画像と同じサイズのマスクを作成し、白色の領域が再生成対象となるようにします
  3. マスクを mask 入力ポートに接続します
  4. プロンプト欄に、マスクで指定された領域に生成したい内容を記述します
  5. ノードを実行して局所的な編集を行います

パラメータ説明

基本パラメータ

パラメータデフォルト値説明
prompt文字列""生成するコンテンツを記述するテキストプロンプト
aspect_ratio選択肢”1:1”画像のアスペクト比(テキストから画像へモードのみ有効)
resolution選択肢”Auto”画像の解像度。設定するとアスペクト比の設定を上書きします
magic_prompt_option選択肢”AUTO”マジックプロンプトの強化設定:AUTOONOFF
seed整数0乱数シード値。0 の場合はランダム生成になります
num_images整数1生成する画像の枚数(1~8)
rendering_speed選択肢”BALANCED”レンダリング速度:BALANCEDTURBOQUALITY

オプションパラメータ

パラメータ説明
image画像インペインティングモード用の入力画像(マスクと同時に指定必須
maskマスクインペインティング用のマスク。白色の領域が置き換えられます(画像と同時に指定必須

出力

出力説明
IMAGE画像生成された画像

動作原理

Ideogram V3 ノードは、最先端のAIモデルを活用してユーザー入力を処理し、複雑なデザイン意図やテキストレイアウト要件を理解することができます。主に以下の2つのモードをサポートしています:
  1. 生成モード:テキストプロンプトから新しい画像を作成
  2. 編集モード:元の画像とマスクの組み合わせを使用し、マスクで指定された領域のみを置き換えます

ソースコード

[ノードソースコード(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),)