🪛 Save image with extra metadata¶
Documentation¶
- Class name:
Save image with extra metadata [Crystools]
- Category:
crystools 🪛/Image
- Output node:
True
This node is designed to save images with additional metadata, which can include workflow details and custom metadata provided by the user. It extends the functionality of a standard image saving process by allowing the inclusion of extra information directly within the image file, enhancing traceability and context for each saved image.
Input types¶
Required¶
image
- The image to be saved. This parameter is crucial as it determines the content that will be stored and subsequently used for further processing or reference.
- Comfy dtype:
IMAGE
- Python dtype:
PIL.Image.Image
filename_prefix
- A prefix for the filename under which the image will be saved. This helps in organizing and identifying images easily, especially when dealing with multiple images or batches.
- Comfy dtype:
STRING
- Python dtype:
str
with_workflow
- A flag indicating whether workflow details should be included in the image's metadata. This can be useful for tracking the processing history or steps involved in generating the image.
- Comfy dtype:
BOOLEAN
- Python dtype:
bool
Optional¶
metadata_extra
- Additional metadata in JSON format to be included with the image. This provides flexibility in embedding various types of information as part of the image's metadata.
- Comfy dtype:
STRING
- Python dtype:
str
Output types¶
Metadata RAW
- Comfy dtype:
METADATA_RAW
- The result of the image saving process, including the saved image's path and any associated metadata.
- Python dtype:
dict
- Comfy dtype:
Usage tips¶
- Infra type:
CPU
- Common nodes: unknown
Source code¶
class CImageSaveWithExtraMetadata(SaveImage):
def __init__(self):
super().__init__()
self.data_cached = None
self.data_cached_text = None
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
# if it is required, in next node does not receive any value even the cache!
"image": ("IMAGE",),
"filename_prefix": ("STRING", {"default": "ComfyUI"}),
"with_workflow": BOOLEAN,
},
"optional": {
"metadata_extra": ("STRING", {"multiline": True, "default": json.dumps({
"Title": "Image generated by Crystian",
"Description": "More info: https:\/\/www.instagram.com\/crystian.ia", # "\/" is for escape / on json
"Author": "crystian.ia",
"Software": "ComfyUI",
"Category": "StableDiffusion",
"Rating": 5,
"UserComment": "",
"Keywords": [
""
],
"Copyrights": "",
}, indent=CONFIG["indent"]).replace("\\/", "/"),
}),
},
"hidden": {
"prompt": "PROMPT",
"extra_pnginfo": "EXTRA_PNGINFO",
},
}
CATEGORY = CATEGORY.MAIN.value + CATEGORY.IMAGE.value
RETURN_TYPES = ("METADATA_RAW",)
RETURN_NAMES = ("Metadata RAW",)
OUTPUT_NODE = True
FUNCTION = "execute"
def execute(self, image=None, filename_prefix="ComfyUI", with_workflow=True, metadata_extra=None, prompt=None, extra_pnginfo=None):
data = {
"result": [''],
"ui": {
"text": [''],
"images": [],
}
}
if image is not None:
if with_workflow is True:
extra_pnginfo_new = extra_pnginfo.copy()
prompt = prompt.copy()
else:
extra_pnginfo_new = None
prompt = None
if metadata_extra is not None and metadata_extra != 'undefined':
try:
metadata_extra = json.loads(f"{{{metadata_extra}}}")
except Exception as e:
logger.error(f"Error parsing metadata_extra (it will send as string), error: {e}")
metadata_extra = {"extra": str(metadata_extra)}
if isinstance(metadata_extra, dict):
for k, v in metadata_extra.items():
if extra_pnginfo_new is None:
extra_pnginfo_new = {}
extra_pnginfo_new[k] = v
saved = super().save_images(image, filename_prefix, prompt, extra_pnginfo_new)
image = saved["ui"]["images"][0]
image_path = Path(self.output_dir).joinpath(image["subfolder"], image["filename"])
img, promptFromImage, metadata = buildMetadata(image_path)
images = [image]
result = metadata
data["result"] = [result]
data["ui"]["images"] = images
else:
logger.debug("Source: Empty on CImageSaveWithExtraMetadata")
return data