4.1 KiB
4.1 KiB
Documentation
- Class name: SaveAnimatedPNG
- Category: image/animation
- Output node: True
- Repo Ref: https://github.com/comfyanonymous/ComfyUI
SaveAnimatedPNG节点旨在高效地将一系列图像保存为动画PNG文件。它考虑了帧率和压缩级别,以优化动画的性能和存储需求。该节点在图像生成工作流的最终输出阶段扮演着关键角色,确保生成的动画既高质量又高效打包。
Input types
Required
- images
- ‘images’参数至关重要,因为它定义了将被编译成动画PNG的图像序列。它直接影响最终输出,决定了动画的内容和质量。
- Comfy dtype: IMAGE
- Python dtype: torch.Tensor
- fps
- ‘fps’参数决定了动画播放的速度,以每秒多少帧来衡量。它是设置动画节奏和确保流畅观看体验的关键因素。
- Comfy dtype: FLOAT
- Python dtype: float
- compress_level
- ‘compress_level’参数调整PNG文件的压缩级别,这有助于平衡文件大小与图像质量。这对于优化存储和加载时间非常重要。
- Comfy dtype: INT
- Python dtype: int
Optional
- filename_prefix
- ‘filename_prefix’参数允许用户为输出文件名指定自定义前缀,这对于组织和识别保存的动画非常有用。
- Comfy dtype: STRING
- Python dtype: str
- prompt
- ‘prompt’参数用于存储与正在保存的图像相关的附加上下文或描述。它可以为将来的参考或元数据目的提供有价值的信息。
- Comfy dtype: PROMPT
- Python dtype: str
- extra_pnginfo
- ‘extra_pnginfo’参数允许在PNG文件中包含额外的元数据,这可以用来嵌入自定义数据或注释。
- Comfy dtype: EXTRA_PNGINFO
- Python dtype: Dict[str, str]
Output types
- ui
- ‘ui’参数封装了节点操作生成的用户界面元素。它包括文件名和子文件夹等详细信息,这些对于用户定位和与保存的动画交互至关重要。
- Comfy dtype: DICT
- Python dtype: Dict[str, Any]
Usage tips
- Infra type: CPU
Source code
class SaveAnimatedPNG:
def __init__(self):
self.output_dir = folder_paths.get_output_directory()
self.type = 'output'
self.prefix_append = ''
@classmethod
def INPUT_TYPES(s):
return {'required': {'images': ('IMAGE',), 'filename_prefix': ('STRING', {'default': 'ComfyUI'}), 'fps': ('FLOAT', {'default': 6.0, 'min': 0.01, 'max': 1000.0, 'step': 0.01}), 'compress_level': ('INT', {'default': 4, 'min': 0, 'max': 9})}, 'hidden': {'prompt': 'PROMPT', 'extra_pnginfo': 'EXTRA_PNGINFO'}}
RETURN_TYPES = ()
FUNCTION = 'save_images'
OUTPUT_NODE = True
CATEGORY = 'image/animation'
def save_images(self, images, fps, compress_level, filename_prefix='ComfyUI', prompt=None, extra_pnginfo=None):
filename_prefix += self.prefix_append
(full_output_folder, filename, counter, subfolder, filename_prefix) = folder_paths.get_save_image_path(filename_prefix, self.output_dir, images[0].shape[1], images[0].shape[0])
results = list()
pil_images = []
for image in images:
i = 255.0 * image.cpu().numpy()
img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8))
pil_images.append(img)
metadata = None
if not args.disable_metadata:
metadata = PngInfo()
if prompt is not None:
metadata.add(b'comf', 'prompt'.encode('latin-1', 'strict') + b'\x00' + json.dumps(prompt).encode('latin-1', 'strict'), after_idat=True)
if extra_pnginfo is not None:
for x in extra_pnginfo:
metadata.add(b'comf', x.encode('latin-1', 'strict') + b'\x00' + json.dumps(extra_pnginfo[x]).encode('latin-1', 'strict'), after_idat=True)
file = f'{filename}_{counter:05}_.png'
pil_images[0].save(os.path.join(full_output_folder, file), pnginfo=metadata, compress_level=compress_level, save_all=True, duration=int(1000.0 / fps), append_images=pil_images[1:])
results.append({'filename': file, 'subfolder': subfolder, 'type': self.type})
return {'ui': {'images': results, 'animated': (True,)}}