initial
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
*.pyc
|
||||
__pycache__
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 Romeo
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,34 @@
|
||||
# ComfyUI-PNG-Metadata Custom Nodes
|
||||
|
||||
<img src="examples/workflow.png"/>
|
||||
|
||||
ComfyUI-PNG-Metadata is a set of custom nodes for ComfyUI. It provides nodes that allow to add custom metadata to your PNG files, such as the prompt and settings used to generate the image. This also can be used to add "parameters" metadata item compatible with AUTOMATIC1111 metadata.
|
||||
|
||||
To use the nodes, simply add them to your workflow and connect the inputs. This will automatically add the metadata to any standard "save image" nodes.
|
||||
|
||||
The nodes provided in this library are:
|
||||
|
||||
1. **Set Metadata** - Set a single custom metadata field and optionally update 'parameters' field in png metadata.
|
||||
2. **Set Metadata (All)** - Set multiple metadata at once and write them to 'parameters' field in png metadata.
|
||||
|
||||
*Note*: Currently the node execution order is not enforced, so if Metadata nodes execute after the Save Image node, the metadata will not be written to the image. This will be fixed in a future release.
|
||||
|
||||
## Installation
|
||||
|
||||
### Using ComfyUI-Manager
|
||||
1. Install [ComfyUI-Manager](https://github.com/ltdrdata/ComfyUI-Manager) if it isn't already.
|
||||
2. Press Install Custom Nodes from the ComfyUI-Manager menu
|
||||
3. Search for ComfyUI-PNG-Metadata
|
||||
4. Click install
|
||||
|
||||
### Manual installation
|
||||
|
||||
Follow the steps below to install the ComfyUI-PNG-Metadata Library. These commands assume your current working directory is the ComfyUI root directory.
|
||||
|
||||
1. Clone the repository:
|
||||
```
|
||||
git clone https://github.com/romeobuilderotti/ComfyUI-PNG-Metadata custom_nodes/ComfyUI-PNG-Metadata
|
||||
```
|
||||
2. Restart your ComfyUI.
|
||||
3. You can find example workflows in the `custom_nodes/ComfyUI-PNG-Metadata/examples` directory.
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
from .metadata import SetMetadataString, SetMetadataAll
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
"SetMetadataString": SetMetadataString,
|
||||
"SetMetadataAll": SetMetadataAll,
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
"SetMetadataString": "Set Metadata",
|
||||
"SetMetadataAll": "Set Metadata (All)",
|
||||
}
|
||||
|
||||
__version__ = "0.1.0"
|
||||
__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS"]
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 308 KiB |
+113
@@ -0,0 +1,113 @@
|
||||
import comfy
|
||||
|
||||
class SetMetadataString:
|
||||
"""
|
||||
Set a single custom metadata field and optionally update 'parameters' field in png metadata
|
||||
"""
|
||||
CATEGORY = "utils"
|
||||
RETURN_TYPES = ()
|
||||
OUTPUT_NODE = True
|
||||
FUNCTION = "process"
|
||||
|
||||
SET_PARAMETERS = True
|
||||
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {
|
||||
"name": ("STRING", {}),
|
||||
"value": ("STRING", {"forceInput": True, "default": ""}),
|
||||
},
|
||||
"hidden": {
|
||||
"extra_pnginfo": "EXTRA_PNGINFO"
|
||||
},
|
||||
}
|
||||
|
||||
def process(self, name: str, value: str = "", update_parameters: bool = True, extra_pnginfo=None):
|
||||
if extra_pnginfo is not None and name and value:
|
||||
extra_pnginfo[name] = value
|
||||
if self.SET_PARAMETERS and name != "parameters":
|
||||
extra_pnginfo["parameters"] = self.update_parameters(extra_pnginfo.get("parameters", ""), name, value)
|
||||
return (None,)
|
||||
|
||||
def update_parameters(self, params_string: str, name: str, value: str) -> str:
|
||||
"""Modify the a1111 compatible (mostly) parameters string to include the new parameter
|
||||
|
||||
Parameters format:
|
||||
<Prompt>
|
||||
[Negative prompt: <Negative prompt>]
|
||||
[Steps: <steps>, Seed: <seed>, ...]
|
||||
"""
|
||||
prompt, *other = params_string.split("\n") + [""] * 3
|
||||
negative = None
|
||||
params = None
|
||||
for item in other:
|
||||
if item:
|
||||
if item.startswith("Negative prompt: "):
|
||||
negative = item
|
||||
else:
|
||||
params = item
|
||||
|
||||
if name.lower() == "prompt":
|
||||
prompt = value
|
||||
elif name.lower() in ("negative prompt", "negative"):
|
||||
negative = f"Negative prompt: {value}"
|
||||
else:
|
||||
if isinstance(value, str) and any(c in value for c in (',', '\n', '"')):
|
||||
value = '"' + value.replace('"', '\\"') + '"'
|
||||
if params:
|
||||
params += f", {name}: {value}"
|
||||
else:
|
||||
params = f"{name}: {value}"
|
||||
|
||||
return "\n".join(filter(None, [prompt, negative, params]))
|
||||
|
||||
class SetMetadataAll(SetMetadataString):
|
||||
"""
|
||||
Set multiple metadata at once and write them to 'parameters' field in png metadata
|
||||
"""
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {
|
||||
"required": {},
|
||||
"optional": {
|
||||
"prompt": ("STRING", {"forceInput": True, "default": None}),
|
||||
"negative": ("STRING", {"forceInput": True, "default": None}),
|
||||
"model_name": ("STRING", {"forceInput": True, "default": None}),
|
||||
"steps": ("INT", {"forceInput": True, "default": None}),
|
||||
"cfg": ("FLOAT", {"forceInput": True, "default": None}),
|
||||
"sampler_name": (comfy.samplers.KSampler.SAMPLERS, {"forceInput": True, "default": None}),
|
||||
"scheduler": (comfy.samplers.KSampler.SCHEDULERS, {"forceInput": True, "default": None}),
|
||||
"seed": ("INT", {"forceInput": True, "default": None}),
|
||||
},
|
||||
"hidden": {
|
||||
"extra_pnginfo": "EXTRA_PNGINFO"
|
||||
},
|
||||
}
|
||||
|
||||
def process(self, **kwargs):
|
||||
extra_pnginfo = kwargs.pop("extra_pnginfo", None)
|
||||
if extra_pnginfo is not None:
|
||||
params = extra_pnginfo.get("parameters", "")
|
||||
for k, v in kwargs.items():
|
||||
if v is not None:
|
||||
params = self.update_parameters(params, self.convert_name(k), self.convert_value(v))
|
||||
if params:
|
||||
extra_pnginfo["parameters"] = params
|
||||
return (None,)
|
||||
|
||||
def convert_name(self, name: str) -> str:
|
||||
names_dict = {
|
||||
"prompt": "Prompt",
|
||||
"negative": "Negative prompt",
|
||||
"model_name": "Model",
|
||||
"steps": "Steps",
|
||||
"seed": "Seed",
|
||||
"cfg": "CFG scale",
|
||||
"sampler_name": "Sampler",
|
||||
"scheduler": "Scheduler",
|
||||
}
|
||||
return names_dict.get(name, name)
|
||||
|
||||
def convert_value(self, value):
|
||||
return value
|
||||
Reference in New Issue
Block a user