Files
CavinHuang-comfyui-nodes-docs/docs/SaltInput.md
2024-07-04 08:39:03 +08:00

8.1 KiB

Documentation

  • Class name: SaltInput
  • Category: SALT/IO
  • Output node: True

SaltInput节点旨在为Salt AI平台的工作流创建和配置输入。它允许用户定义输入的各个方面,如名称、描述、类型和默认值,以及其他属性,如允许的值、是否需要用户覆盖,以及路径是否应被视为相对路径。该节点在为不同类型的数据定制和简化输入过程中发挥着关键作用,确保工作流设计的灵活性和适应性。

Input types

Required

  • input_name
    • 指定输入的名称,作为工作流中输入字段的唯一标识符和标签。
    • Comfy dtype: STRING
    • Python dtype: str
  • input_desc
    • 为输入提供描述,为用户提供关于如何提供输入值的上下文或说明。
    • Comfy dtype: STRING
    • Python dtype: str
  • input_type
    • 定义输入的类型,如STRING、FLOAT、INT等,决定了用户需要提供的数据的预期格式和性质。
    • Comfy dtype: COMBO[STRING]
    • Python dtype: list[str]
  • input_value
    • 输入的默认值,可以预先填写但用户可以更改。支持多行字符串,设计用于动态输入场景。
    • Comfy dtype: STRING
    • Python dtype: str

Optional

  • input_image
    • 可选参数,用于提供图像作为输入,增强节点处理视觉数据类型的能力。
    • Comfy dtype: IMAGE
    • Python dtype: Image
  • input_mask
    • 可选参数,用于提供蒙版作为输入,在需要识别或处理图像特定区域的场景中很有用。
    • Comfy dtype: MASK
    • Python dtype: Mask
  • input_allowed_values
    • 指定输入允许值的字符串,指导用户提供有效数据并确保输入完整性。
    • Comfy dtype: STRING
    • Python dtype: str
  • user_override_required
    • 确定用户是否必须为默认输入值提供覆盖,确保关键输入的用户交互和验证。
    • Comfy dtype: BOOLEAN
    • Python dtype: bool
  • relative_path
    • 指示提供的输入路径是否应被视为相对路径,影响输入数据的访问和管理方式。
    • Comfy dtype: BOOLEAN
    • Python dtype: bool

Output types

  • value
    • 输出配置的输入值。
    • Comfy dtype: *
    • Python dtype: unknown
  • ui
    • 生成输入配置的用户界面表示,包括元数据和输出结果,便于交互和视觉反馈。
    • Comfy dtype: *
    • Python dtype: unknown

Usage tips

  • Infra type: CPU
  • Common nodes: unknown

Source code

class SaltInput:
    @classmethod
    def INPUT_TYPES(cls):
        return {
            "required": {
                "input_name": ("STRING", {}),
                "input_desc": ("STRING", {}),
                "input_type": (["STRING", "FLOAT", "INT", "BOOLEAN", "IMAGE", "MASK", "SEED", "FILE"],),
                "input_value": ("STRING", {"multiline": True, "dynamicPrompts": False})
            },
            "optional": {
                "input_image": ("IMAGE",),
                "input_mask": ("MASK",),
                "input_allowed_values": ("STRING", {"default": ""}),
                "user_override_required": ("BOOLEAN", {"default": False}),
                "relative_path": ("BOOLEAN", {"default": False})
            },
            "hidden": {"unique_id": "UNIQUE_ID"},
        }

    OUTPUT_NODE = True
    RETURN_TYPES = (WILDCARD,)
    RETURN_NAMES = ("value",)

    FUNCTION = "input"
    CATEGORY = "SALT/IO"

    def input(
        self,
        input_name,
        input_desc,
        input_value,
        input_type,
        input_image=None,
        input_mask=None,
        input_allowed_values="",
        user_override_required=False,
        relative_path=False,
        unique_id=0,
    ):
        src_image = None
        src_file = None
        is_asset = False

        # Is an asset type
        if input_type in ["IMAGE", "MASK", "FILE"]:
            is_asset = True

        # UI Output
        ui = {
            "ui": {
                "salt_input": [{
                    "id": unique_id,
                    "name": input_name or "input_" + str(unique_id),
                    "description": input_desc or "",
                    "asset": is_asset or False,
                    "type": input_type or "string",
                    "value": input_value or "",
                }]
            }
        }

        out = ""
        if is_asset:
            # Input value must be evaluated first to override input images/masks
            if input_value.strip():
                input_value = input_value.strip()
                # Load image from path from input_value
                if input_value.endswith(('.png', '.jpeg', '.jpg', '.gif', '.webp', '.tiff')):
                    try:
                        src_image = Image.open(input_value).convert("RGBA")
                    except Exception as e:
                        print(f"Error loading image from specified path {input_value}: {e}")
                # Passthrough input_value (which should be a path from Salt Backend)
                elif input_type == "FILE":

                    src_file = input_value # if os.path.exists(input_value) else "None"
                    if relative_path:
                        src_file = get_relative_path(src_file)

                    # Log value to console
                    log_values(unique_id, input_name, input_type, src_file)
                    
                    return {"ui": ui, "result": (src_file,)}
                else:
                    # Zoinks; how'd we get here?
                    raise AttributeError("Invalid node configuration! Do you mean to use `IMAGE`, `MASK`, or `FILE` input_types?")
            elif isinstance(input_image, torch.Tensor):
                # Input `IMAGE` is provided, so we act like a passthrough
                return (input_image, ui)
            elif isinstance(input_mask, torch.Tensor):
                # Input `MASK` is provided, so we act like a passthrough
                return (input_mask, ui)

            if src_image:
                if input_type == "MASK":
                    # If it's a mask and the image has an alpha channel, extract it
                    if src_image.mode == "RGBA":
                        alpha_channel = src_image.split()[-1]
                        src_image = pil2mask(alpha_channel.convert("L"))
                    # If no alpha channel, convert the whole image to grayscale as a mask (could be bitwise representation)
                    else:
                        src_image = pil2mask(src_image.convert("L"))
                elif input_type == "IMAGE":
                    # Ensure image is in RGB for `IMAGE`` data type
                    src_image = pil2tensor(src_image.convert("RGB"))

            else:
                # Gracefully allow execution to continue, provided a black image (to hopefully signal issue?)
                print("[WARNING] Unable to determine IMAGE or MASK to load!")
                print("[WARNING] Returning image blank")
                src_blank = Image.new("RGB", (512, 512), (0, 0, 0))
                if input_type == "IMAGE":
                    src_image = pil2tensor(src_blank)
                else:
                    src_image = pil2mask(src_blank)

            # Log value to console
            log_values(unique_id, input_name, input_type, src_image)

            return (src_image, ui)

        # We're still here? We must be dealing with a primitive value
        if input_allowed_values != "" and input_value.strip() not in [o.strip() for o in input_allowed_values.split(',')]:
            raise ValueError('The provided input is not a supported value')


        match input_type:
            case "STRING":
                out = str(input_value)
            case "INT":
                out = int(input_value)
            case "SEED":
                out = int(input_value)
            case "FLOAT":
                out = float(input_value)
            case "BOOLEAN":
                out = bool_str(input_value)
            case _:
                out = input_value

        # Log value to console
        log_values(unique_id, input_name, input_type, out)

        return (out, ui)