# piexif # for testing # jpegxl support: imagecodecs will bring libjxl 0.9.0 # imagecodecs # pillow-jxl-plugin is simpler numpy piexif imagecodecs pillow pillow-avif-plugin pillow-jxl-plugin







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
json (text) file, in each folder.
| Attribute | Description |
| — | — |
| filename_prefix | Static 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. 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. |
| resolution | Saved image reolution in format 000x000 (pixels).
| named_keys | Prefix each value by its key name. Example: prefix-seed=123456-width=1024-cfg=5.0-0001.avif |
ckpt_name etc, as they are virtually infinite and exist only within your workflow.wrongNumber.attribute, you will also get attribute as a fixed string.%Y-%m-%d or %F etc: see unix datetime formatsckpt_name / control_net_name / lora_name not the pathckpt_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.textPREFIXcfg, sampler_name, /steps, %F %H-%M-%Sckpt_name/, .cfgv1-5-pruned.cfg / PREFIX-8.0-euler / 20-2024-12-18 23-17-17-0001.pngPREFIXcfg, sampler_name, steps, %F %H-%M-%Sckpt_name, /, cfgv1-5-pruned / 8.0 / PREFIX-cfg-8.0-euler-20-2024-12-18 23-21-41-0001.pngPREFIX"cfg", cfgckpt_name, /, cfgv1-5-pruned / 8.0 / PREFIX-cfg-8.0-0002.pngimages – 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 |
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 512×512 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 2560×1440 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.pngexiftool -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:
Happy saving!
*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?