Files
CavinHuang-comfyui-nodes-docs/docs/SaveAnimatedPNG.md
2024-05-15 08:09:49 +08:00

4.1 KiB
Raw Permalink Blame History

Documentation

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,)}}