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. |
| 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 delimiterprefix = 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:
| 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 piexif pillow pillow-avif-plugin
For Jpeg XL / jxl it's more complicated. You cannot compile the wheel jxlpy on Windows. Therefore, we use an alternative: imagecodecs
pip install -U imagecodecs
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
JPEG XL is a heated debate on chromium forum and if true indeed 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, with a caveat. The compression offered by pillow is 3x lower then Image Magick for the same level. No idea why.
Pillow cannot save Exif data in JPEG2000, nor can it compress it in any way. Who the heck is using JPEG2000 in 2024 anyway?
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: default is 90, 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% |
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}
ComfyUI cannot load lossless WebP atm. Feel free to try and fix pnginfo.js
Incompatible with extended-saveimage-comfyui - This node can be safely discarded, as it only offers WebP output. My node already adds JPEG and WebP.
You asked for it... Now you can select which node to get the widget values from! Formerly, this custom node would simply return the last value found: useless if you have multiple same nodes... To see node numbers in the UI, enable the badge IDs: <br>
<p align="center"> <img src="assets/ComfyUI-enable-badge-ids.png" /> </p>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>