Upgrade the Save File node: customize subfolders, file names with checkpoint names, or any sampler attribute your want! [w/NOTE: This node is a fork from @thedyze, since the a/original repository is no longer maintained. Simply uninstall the original version and REINSTALL this one.]
Save as JXL, AVIF, WebP, JPEG, JPEG2k, customize the folder, sub-folders, and filenames of your images!
Supports those extensions: JXL AVIF WebP jpg jpeg j2k jp2 png gif tiff bmp
<p align="center"> <img src="assets/save-image-extended-comfyui-example.png" /> </p>json
(text) file, in each folder.| Attribute | Description |
| --- | --- |
| filename_prefix
| Fixed string prefixed to file name. |
| filename_keys
| Comma separated string with sampler parameters to add to filename. E.g: sampler_name, scheduler, cfg, denoise
Added to filename in written order. resolution
also works. vae_name
model_name
(upscale model), ckpt_name
(checkpoint) are others that should work. Here you can try any parameter name of any node. As long as the parameter has the same variable name defined in the prompt
object, they should work. The same applies to foldername_keys
. |
| foldername_prefix
| Fixed string prefixed to subfolders. |
| foldername_keys
| Same rules as for filename_keys
. Create subfolders by using /
or ../
etc. |
| delimiter
| now a free field Delimiter = any string you like. You can also use /
to create subfolders. |
| save_job_data
| Saves information about each job as entries in a jobs.json
text file, inside the generated subfolder. Multiple options for its content: prompt
, basic data
, sampler settings
, loaded models
. |
| job_data_per_image
| Saves individual job data file per image. |
| job_custom_text
| Custom string to save along with the job data. |
| save_metadata
| Saves metadata into the image. |
| counter_digits
| Number of digits used for the image counter. 3
= image_001.png, based on highest number in the subfolder, ignores gaps. Can be disabled when == 0. |
| counter_position
| Image counter postition: image_001.png or 001_image.png. |
| one_counter_per_folder
| Toggles one counter per subfolder, or resets when a parameter/prompt changes. |
| image_preview
| Turns the image preview on and off. |
| output_ext
| File extension: WEBP by default, AVIF, PNG, JXL, JPG, etc. |
| quality
| Quality for JPEG/JXL/WebP/AVIF/J2K formats; Quality is relative to each format. Example: AVIF 60 is same quality as WebP 90. PNG compression is fixed at 4 and not affected by this. PNG compression times skyrocket above level 4 for zero benefits on filesize. |
| named_keys
| Prefix each value by its key name. Example: prefix-seed=123456-width=1024-cfg=5.0-0001.avif |
filename_keys
and foldername_keys
are treated as fixed strings
wrongNumber.attribute
, you will get attribute
in your filename.%Y-%m-%d
or %F
etc: see unix datetime formatsckpt_name
/ control_net_name
/ lora_name
not the path
ckpt_path
/ control_net_path
/ lora_path
to get the same subfolders as your models.custom_string
will prevent appending delimiter, the dot will be the delimiter#num.text
prefix = PREFIX
filename = cfg, sampler_name, /steps, %F %H-%M-%S
foldername = ckpt_name/, .cfg
v1-5-pruned.cfg / PREFIX-8.0-euler / 20-2024-12-18 23-17-17-0001.png
prefix = PREFIX
filename = cfg, sampler_name, steps, %F %H-%M-%S
foldername = ckpt_name, /, cfg
v1-5-pruned / 8.0 / PREFIX-cfg-8.0-euler-20-2024-12-18 23-21-41-0001.png
prefix = PREFIX
filename = "cfg", cfg
foldername = ckpt_name, /, cfg
v1-5-pruned / 8.0 / PREFIX-cfg-8.0-0002.png
images
- The generated images.Optional:
positive_text_opt
- Optional string saved as positive_text_opt
in job.json when save_job_data
=True.negative_text_opt
- Optional string saved as negative_text_opt
in job.json when save_job_data
=True.Converts unix datetime formats following POSIX format. Examples:
| Unix datetime | Example | Comment | | --- | --- | --- | | %F or %Y-%m-%d | 2024-05-22 | | | %D | 05/22/24 | This effectively creates subfolders | | %F %H-%M-%S | 2024-05-22 09-13-58 | | | %Y/%V | 2024/21 | year subfolder / ISO week number subfolder |
<p align="center"> <img src="assets/save-image-extended-comfyui-example-2.png" /> </p>There is a requirements.txt that will take care of that, but just in case:
pip install numpy pillow pillow-avif-plugin pillow-jxl-plugin
git clone
command to clone the save-image-extended-comfyui repo under ComfyUI\custom_nodes\git clone https://github.com/audioscavenger/save-image-extended-comfyui
pnginfo.js
.EXIF data is too long
.Disclaimer: Does not check for illegal characters entered in file or folder names. May not be compatible with every other custom node, depending on changes in the prompt
object.
Tested and working with default samplers, Efficiency nodes, UltimateSDUpscale, ComfyRoll, composer, NegiTools, and 45 other nodes.
Quality and compression settings: min = 1, default is 90, max = 100 will activate lossless for AVIF and WEBP only.
Quick comparison of size per extension, for the same 512x512 picture, with similar visual quality: | Ext | Compression | Maker | Size | Compression | | --- | --- | --- | --- | --- | | png | max 9 | PIL | 413111 | 0% | | j2k | n/a | PIL | 395028 | 4% | | jxl | lossless | PIL | 301310 | 27% | | jxl | 90 | PIL | 179210 | 57% | | jpeg | 90 | PIL | 88554 | 79% | | avif | 90 | Imagick | 67272 | 84% | | webp | 90 | Imagick | 64416 | 84% | | webp | 90 | PIL | 64356 | 84% | | avif | 60 | PIL | 47353 | 89% | | avif | 60 | Imagick | 33691 | 92% |
PNG compression 0-9 is fixed at level 4 for the following reason: zero compression benefits above level 4, while saving time skyrockets. Test results below for a 2560x1440 image on an Intel i7-9700: | Compression | time | Size | | --- | --- | --- | | 0 | 0.5s | 10.6 MB | | 1 | 0.6s | 4.6 MB | | 2 | 0.6s | 4.5 MB | | 3 | 0.6s | 4.4 MB | | 4 | 0.7s | 4.0 MB | | 5 | 1.1s | 4.0 MB | | 6 | 1.9s | 4.0 MB | | 7 | 2.6s | 4.0 MB | | 9 | 10.5s | 3.9 MB |
About extensions WebP AVIF JPEG JXL: ComfyUI can only load PNG and WebP atm... Feel free to ask ComfyUI team to add support for AVIF/jpeg/JXL!
The metadata Are included under the EXIF tags IFD below, as defined here WAS Node Suite also use those tags. They must be next to each other in order to Comfy to be able to load them with drag and drop.
| Data | EXIF | Name | String looks like | | --- | --- | --- | --- | | prompt | 0x010f | Make | Prompt: {"5" ... } | | workflow | 0x010e | ImageDescription | Workflow: {"5" ... } |
You can retrieve the prompt manually with exiftool, here are some example commands:
exiftool -Parameters -Prompt -Workflow image.png
exiftool -Parameters -UserComment -ImageDescription image.{jpg|jpeg|webp|avif|jxl}
JPEG XL is a heated debate on chromium forum and if true, that Google is working on WebP2, JXL is unlikely to take off any day soon. Proponents arguably declare with no proof, that jxl is better and faster than the current best codec: AVIF. But again, without support from the industry, it's going nowhere.
I tested with compression 90 and it's good compared to WebP, with a caveat. The compression offered by pillow is 3x lower then Image Magick for the same level. No idea why.
jobs.json sample: <br>
<p align="center"> <img src="assets/save-image-extended-comfyui-jobs-example.png" /> <br><br> Happy saving! </p>Reboot by AudioscavengeR since 2024-05-05, original idea from @thedyze
I won't promise you the moon, but since I use this node myself, I will maintain it as much as I can. I do provide a way to contact me, and will accept PR and collabs. Once I feel like I don't have time to work on it, I will gladly transfer ownership or let collabs maintain it.
TODO:
steps_total
as an input to a Ksampler, will issue the index of the output, instead of the steps value ("[nodeNum, 0]" instead of steps value). FIX: use steps_total
instead of steps
!__all__
in init.pylen(splitKey) = 2
to identify actual "node.widget" format/name
in foldername_keys, Comfy thinks you want to save outside the output folderpnginfo.js and
app.js`Like my work? This tool helped you? Want to sponsor more awesomeness like this?
<p align="center"> <a href="https://www.paypal.com/donate/?hosted_button_id=CD7P7PK3WP8WU"><img src="/assets/paypal-Donate-QR-Code.png" /></a> </p>