5.3 KiB
5.3 KiB
Documentation
- Class name: WAS_Image_Morph_GIF
- Category: WAS Suite/Animation
- Output node: False
- Repo Ref: https://github.com/WASasquatch/was-node-suite-comfyui
WAS_Image_Morph_GIF 节点旨在创建两个图像之间的变形动画。它在一个指定的帧数上平滑地从一个图像过渡到另一个图像,允许定制过渡属性,如帧延迟和循环设置。这个节点特别适用于生成像 GIF 或 APNG 这样的动画序列,可以用于各种多媒体演示或应用程序中。
Input types
Required
- image_a
- 用于变形动画的第一张图像。它设置了过渡的起点,并且对最终输出的外观至关重要。
- Comfy dtype: IMAGE
- Python dtype: PIL.Image.Image or torch.Tensor
- image_b
- 动画变形到的第二张图像。这张图像定义了过渡的结束状态,对变形的整体效果有所贡献。
- Comfy dtype: IMAGE
- Python dtype: PIL.Image.Image or torch.Tensor
Optional
- transition_frames
- 用于两个图像之间过渡的帧数。数量越多,过渡越平滑,但动画时间也更长。
- Comfy dtype: INT
- Python dtype: int
- still_image_delay_ms
- 在开始变形过渡之前的每个静态帧的延迟时间(以毫秒为单位)。
- Comfy dtype: FLOAT
- Python dtype: float
- duration_ms
- 变形过渡期间每帧的持续时间(以毫秒为单位)。
- Comfy dtype: FLOAT
- Python dtype: float
- loops
- 动画应该循环的次数。值为 0 表示动画将无限循环。
- Comfy dtype: INT
- Python dtype: int
- max_size
- 输出图像的最大尺寸(以像素为单位)。可能会调整大小以适应此限制,同时保持纵横比。
- Comfy dtype: INT
- Python dtype: int
- output_path
- 保存输出 GIF 文件的路径。如果未指定,默认为 './ComfyUI/output'。
- Comfy dtype: STRING
- Python dtype: str
- filename
- 输出 GIF 文件的期望名称。如果未提供,默认为 'morph'。
- Comfy dtype: STRING
- Python dtype: str
- filetype
- 输出动画的文件格式。支持 'GIF' 或 'APNG'。
- Comfy dtype: COMBO['GIF', 'APNG']
- Python dtype: str
Output types
- image_a_pass
- 第一个输入图像,未改变,包含在输出中以保持连贯性。
- Comfy dtype: IMAGE
- Python dtype: PIL.Image.Image or torch.Tensor
- image_b_pass
- 第二个输入图像,未改变,包含在输出中以保持连贯性。
- Comfy dtype: IMAGE
- Python dtype: PIL.Image.Image or torch.Tensor
- filepath_text
- 创建的 GIF 文件的完整路径。
- Comfy dtype: TEXT_TYPE
- Python dtype: str
- filename_text
- 创建的 GIF 的文件名。
- Comfy dtype: TEXT_TYPE
- Python dtype: str
Usage tips
- Infra type: CPU
Source code
class WAS_Image_Morph_GIF:
def __init__(self):
pass
@classmethod
def INPUT_TYPES(cls):
return {'required': {'image_a': ('IMAGE',), 'image_b': ('IMAGE',), 'transition_frames': ('INT', {'default': 30, 'min': 2, 'max': 60, 'step': 1}), 'still_image_delay_ms': ('FLOAT', {'default': 2500.0, 'min': 0.1, 'max': 60000.0, 'step': 0.1}), 'duration_ms': ('FLOAT', {'default': 0.1, 'min': 0.1, 'max': 60000.0, 'step': 0.1}), 'loops': ('INT', {'default': 0, 'min': 0, 'max': 100, 'step': 1}), 'max_size': ('INT', {'default': 512, 'min': 128, 'max': 1280, 'step': 1}), 'output_path': ('STRING', {'default': './ComfyUI/output', 'multiline': False}), 'filename': ('STRING', {'default': 'morph', 'multiline': False}), 'filetype': (['GIF', 'APNG'],)}}
@classmethod
def IS_CHANGED(cls, **kwargs):
return float('NaN')
RETURN_TYPES = ('IMAGE', 'IMAGE', TEXT_TYPE, TEXT_TYPE)
RETURN_NAMES = ('image_a_pass', 'image_b_pass', 'filepath_text', 'filename_text')
FUNCTION = 'create_morph_gif'
CATEGORY = 'WAS Suite/Animation'
def create_morph_gif(self, image_a, image_b, transition_frames=10, still_image_delay_ms=10, duration_ms=0.1, loops=0, max_size=512, output_path='./ComfyUI/output', filename='morph', filetype='GIF'):
tokens = TextTokens()
WTools = WAS_Tools_Class()
if 'imageio' not in packages():
install_package('imageio')
if filetype not in ['APNG', 'GIF']:
filetype = 'GIF'
if output_path.strip() in [None, '', '.']:
output_path = './ComfyUI/output'
output_path = tokens.parseTokens(os.path.join(*output_path.split('/')))
if not os.path.exists(output_path):
os.makedirs(output_path, exist_ok=True)
if image_a == None:
image_a = pil2tensor(Image.new('RGB', (512, 512), (0, 0, 0)))
if image_b == None:
image_b = pil2tensor(Image.new('RGB', (512, 512), (255, 255, 255)))
if transition_frames < 2:
transition_frames = 2
elif transition_frames > 60:
transition_frames = 60
if duration_ms < 0.1:
duration_ms = 0.1
elif duration_ms > 60000.0:
duration_ms = 60000.0
output_file = WTools.morph_images([tensor2pil(image_a), tensor2pil(image_b)], steps=int(transition_frames), max_size=int(max_size), loop=int(loops), still_duration=int(still_image_delay_ms), duration=int(duration_ms), output_path=output_path, filename=tokens.parseTokens(filename), filetype=filetype)
return (image_a, image_b, output_file)