release 2.87 right-click
- finally! right-click any node with IMAGE output adds "Add SaveImageExtended" option - upgraded purify.min.js modified: README.md modified: pyproject.toml modified: save_image_extended.py modified: web/js/contextmenu.js modified: web/js/purify.min.js
This commit is contained in:
@@ -19,12 +19,12 @@ Supports those extensions: **JXL AVIF WebP jpg jpeg j2k jp2 png gif tiff bmp**
|
||||
<br><br>
|
||||
</p>
|
||||
|
||||
## Parameters / Usage
|
||||
## Parameters / Reserved Keywords
|
||||
|
||||
| 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`. |
|
||||
| `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. |
|
||||
@@ -38,11 +38,13 @@ Supports those extensions: **JXL AVIF WebP jpg jpeg j2k jp2 png gif tiff bmp**
|
||||
| `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 |
|
||||
|
||||
|
||||
- Unknown key names in `filename_keys` and `foldername_keys` are treated as fixed strings
|
||||
- if you enter `wrongNumber.attribute`, you will get `attribute` in your filename.
|
||||
- ANY other keyword that exist as a field name in a widget will be resolved.
|
||||
- That is why I do not list all common keywords like `ckpt_name` etc, as they are virtually infinite and exist only within your workflow.
|
||||
- Unknown key names not found in any widget's fields are treated as fixed strings
|
||||
- if you enter `wrongNumber.attribute`, you will also get `attribute` as a fixed string.
|
||||
- Datetime UNIX format is now included! `%Y-%m-%d` or `%F` etc: see [unix datetime formats](https://www.man7.org/linux/man-pages/man1/date.1.html)
|
||||
- default it output only the **name** for `ckpt_name` / `control_net_name` / `lora_name` not the **path**
|
||||
- use `ckpt_path` / `control_net_path` / `lora_path` to get the same subfolders as your models
|
||||
@@ -110,6 +112,12 @@ 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
|
||||
```
|
||||
|
||||
### Tested on / up to:
|
||||
* python 3.10.6
|
||||
* pytorch 2.5.1+cu124
|
||||
* ComfyUI v0.3.12-1-g7fc3ccdc | Released on '2025-01-16'
|
||||
|
||||
|
||||
### Manual Download
|
||||
1. Open a terminal inside the 'custom_nodes' folder located in your ComfyUI installation dir
|
||||
2. Use the `git clone` command to clone the [save-image-extended-comfyui](https://github.com/audioscavenger/save-image-extended-comfyui) repo under ComfyUI\custom_nodes\
|
||||
@@ -216,6 +224,10 @@ TODO:
|
||||
- [x] TODO: test import cv2 / OpenCV: https://github.com/python-pillow/Pillow/issues/5986 -> not faster then PIL
|
||||
|
||||
|
||||
### release 2.87 💾
|
||||
- finally! right-click any node with IMAGE output adds "Add SaveImageExtended" option
|
||||
- upgraded purify.min.js
|
||||
|
||||
### release 2.86 💾
|
||||
- bugfix in counter_digits which does not accept 0 to disable counter
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
+1
-1
@@ -1,7 +1,7 @@
|
||||
[project]
|
||||
name = "save-image-extended-comfyui"
|
||||
description = "Save as JXL, AVIF, WebP, JPEG, JPEG2k, customize the folder, sub-folders, and filenames of your images!"
|
||||
version = "2.86"
|
||||
version = "2.87"
|
||||
license = { file = "LICENSE" }
|
||||
dependencies = ["piexif", "imagecodecs", "pillow", "pillow-avif-plugin", "pillow-jxl-plugin"]
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ import numpy
|
||||
|
||||
# import cv2 # not faster then PIL
|
||||
|
||||
version = 2.86
|
||||
version = 2.87
|
||||
|
||||
avif_supported = False
|
||||
jxl_supported = False
|
||||
@@ -33,8 +33,9 @@ else:
|
||||
avif_supported = True
|
||||
|
||||
# Jxl requires jxlpy wheel to be compiled, and a valid MSVC environment, which is complex task
|
||||
# Therefore we use pillow_jxl which makes more sense
|
||||
try:
|
||||
# jxlpy is in early stages of development. None one has ever compiled it on Windows AFAIK
|
||||
# jxlpy is in early stages of development. No one has ever compiled it on Windows in 2025 AFAIK, please prove me wrong
|
||||
# from jxlpy import JXLImagePlugin
|
||||
# from imagecodecs import (jpegxl_encode, jpegxl_decode, jpegxl_check, jpegxl_version, JPEGXL)
|
||||
import pillow_jxl
|
||||
|
||||
+55
-8
@@ -3,24 +3,28 @@ import { app } from "../../../scripts/app.js";
|
||||
// Adds context menu entries, code partly from pyssssscustom-scripts
|
||||
|
||||
function addMenuHandler(nodeType, cb) {
|
||||
// console.debug("SIE addMenuHandler nodeType:", nodeType);
|
||||
// console.debug("SIE addMenuHandler cb:", cb);
|
||||
const getOpts = nodeType.prototype.getExtraMenuOptions;
|
||||
|
||||
// the below is never called, i suspect app.js has changed a lot
|
||||
nodeType.prototype.getExtraMenuOptions = function () {
|
||||
const r = getOpts.apply(this, arguments);
|
||||
cb.apply(this, arguments);
|
||||
// console.debug("SIE addMenuHandler arguments:", arguments);
|
||||
return r;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function addNode(name, nextTo, options) {
|
||||
console.log("name:", name);
|
||||
console.log("nextTo:", nextTo);
|
||||
options = { side: "left", select: true, shiftY: 0, shiftX: 0, ...(options || {}) };
|
||||
// console.debug("SIE addNode name:", name);
|
||||
// console.debug("SIE addNode nextTo:", nextTo);
|
||||
options = { select: true, shiftY: 0, before: false, ...(options || {}) };
|
||||
const node = LiteGraph.createNode(name);
|
||||
app.graph.add(node);
|
||||
|
||||
node.pos = [
|
||||
options.side === "left" ? nextTo.pos[0] - (node.size[0] + options.offset): nextTo.pos[0] + nextTo.size[0] + options.offset,
|
||||
|
||||
options.before ? nextTo.pos[0] - node.size[0] - 30 : nextTo.pos[0] + nextTo.size[0] + 30,
|
||||
nextTo.pos[1] + options.shiftY,
|
||||
];
|
||||
if (options.select) {
|
||||
@@ -29,12 +33,49 @@ function addNode(name, nextTo, options) {
|
||||
return node;
|
||||
}
|
||||
|
||||
// https://docs.comfy.org/custom-nodes/js/javascript_overview
|
||||
app.registerExtension({
|
||||
name: "SIEContextmenu",
|
||||
name: "SIE.QuickNodes",
|
||||
async beforeRegisterNodeDef(nodeType, nodeData, app) {
|
||||
if (
|
||||
// this could go forever if we want to list all nodes that can output IMAGE
|
||||
// nodeData.name === "VAEDecode" ||
|
||||
// nodeData.name === "LoadImage" ||
|
||||
|
||||
// fortunately, output is an array where "IMAGE" is always the first item.
|
||||
nodeData.output[0] == "IMAGE"
|
||||
) {
|
||||
// console.debug("SIE.QuickNodes VAEDecode nodeType:", nodeType);
|
||||
// console.debug("SIE.QuickNodes VAEDecode nodeData:", nodeData);
|
||||
// console.debug("SIE.QuickNodes VAEDecode app:", app);
|
||||
|
||||
// https://docs.comfy.org/custom-nodes/js/javascript_examples#node-menu
|
||||
// Code below adds SaveImageExtended option on right-click menu for VAEDecode
|
||||
addMenuHandler(nodeType, function (_, options) {
|
||||
options.unshift(
|
||||
{
|
||||
content: "💾 Add SaveImageExtended",
|
||||
callback: () => {
|
||||
// const saveNode = addNode("SaveImageExtended", this, { before: true });
|
||||
const saveNode = addNode("SaveImageExtended", this);
|
||||
this.connect(0, saveNode, 0);
|
||||
},
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
// https://docs.comfy.org/custom-nodes/walkthrough#write-a-client-extension
|
||||
// I forgot why I added this one, probably not needed after all
|
||||
{
|
||||
name: "SIE.Contextmenu",
|
||||
async setup(app) {
|
||||
// console.debug("SIEContextmenu app:", app);
|
||||
app.ui.settings.addSetting({
|
||||
id: "SIE.helpPopup",
|
||||
name: "🦛 SIE: Help popups",
|
||||
name: "💾 SIE: Help popups",
|
||||
defaultValue: true,
|
||||
type: "boolean",
|
||||
options: (value) => [
|
||||
@@ -42,5 +83,11 @@ app.registerExtension({
|
||||
{ value: false, text: "Off", selected: value === false },
|
||||
],
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Vendored
+2
-2
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user