84 lines
4.1 KiB
Markdown
84 lines
4.1 KiB
Markdown
# 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,)}}
|
||
``` |