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

214 lines
8.1 KiB
Markdown

# 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
```python
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)
```