Compare commits

...
Author SHA1 Message Date
receyuki f9aa0f108e Update README.md 2023-09-28 22:59:04 +08:00
Rhys Yang 3b795c9c42 Add alternative str input for model_name, sampler_name and scheduler 2023-09-28 20:08:46 +08:00
Rhys Yang e5fd46b07e Update README.md 2023-09-28 05:52:17 +08:00
Rhys Yang 96ded420e1 Update README.md 2023-09-28 02:38:17 +08:00
receyuki 426d6710e0 Update README.md 2023-09-28 00:38:28 +08:00
receyuki 30aaa3ef9c Update README.md 2023-09-28 00:29:08 +08:00
receyuki 4d33bfff0a Update README.md 2023-09-28 00:27:55 +08:00
receyuki 5afc486fea Update README.md 2023-09-28 00:23:31 +08:00
receyuki 97bb1e7f61 Update README.md 2023-09-28 00:09:58 +08:00
10 changed files with 1407 additions and 42 deletions
+57 -8
View File
@@ -5,7 +5,7 @@
<img alt="GitHub" src="https://img.shields.io/github/license/receyuki/comfyui-prompt-reader-node"></a>
<img alt="GitHub tag (with filter)" src="https://img.shields.io/github/v/tag/receyuki/comfyui-prompt-reader-node?label=node">
<a href="https://github.com/receyuki/stable-diffusion-prompt-reader">
<img alt="GitHub release (with filter)" src="https://img.shields.io/github/v/release/receyuki/stable-diffusion-prompt-reader?label=core"></a>
<img alt="GitHub tag (with filter)" src="https://img.shields.io/github/v/tag/receyuki/stable-diffusion-prompt-reader?label=core"></a>
<a href="https://github.com/psf/black">
<img alt="Code style: black" src="https://img.shields.io/badge/code%20style-black-000000.svg"></a>
<br><br>
@@ -22,7 +22,7 @@ additional metadata to ensure compatibility with metadata detection on websites
<a href="#usage">Usage</a> •
<a href="#credits">Credits</a>
</p>
<img src="images/screenshot_v100b1.png">
<img src="./images/screenshot_v100b2.png">
</div>
@@ -43,13 +43,12 @@ See [SD Prompt Reader](https://github.com/receyuki/stable-diffusion-prompt-reade
## Installation
### Install via [ComfyUI Manager](https://github.com/ltdrdata/ComfyUI-Manager) (Recommended)
~~Search for `SD Prompt Reader` in the ComfyUI Manager and install it.~~
Waiting for approval.
Search for `SD Prompt Reader` in the ComfyUI Manager and install it.
### Install manually
1. `cd` to the `custom_node` folder
2. Clone this repo
```shell
git clone https://github.com/receyuki/comfyui-prompt-reader-node.git
git clone --recursive https://github.com/receyuki/comfyui-prompt-reader-node.git
```
3. Install dependencies
```shell
@@ -63,8 +62,58 @@ git pull --recurse-submodules
```
## Usage
Example workflow coming soon.
### Prompt Reader Node
- The Prompt Reader Node works exactly the same as the
[standalone SD Prompt Reader](https://github.com/receyuki/stable-diffusion-prompt-reader).
It uses the Image Data Reader from the
[standalone SD Prompt Reader](https://github.com/receyuki/stable-diffusion-prompt-reader),
allowing it to support the same formats and receive updates along with the
[SD Prompt Reader](https://github.com/receyuki/stable-diffusion-prompt-reader).
***For images containing multiple sets of parameters, such as those processed through `hires-fix` or `refiner`,
you will need to modify the `data_index` to select the parameters you need***
***For images generated by SDXL and containing multiple sets of prompts,
the text_g will be combined with text_l into a single prompt***
<div align="center">
<img src="./images/reader.png" width="25%" height="25%" alt="reader node">
</div>
### Prompt Saver Node & Parameter Generator Node
- The Prompt Saver Node and The Parameter Generator Node are designed to be used together.
- The Prompt Saver Node will write additional metadata in the A1111 format to the output images
to be compatible with any tools that support the A1111 format,
including SD Prompt Reader and Civitai.
Due to custom nodes and complex workflows potentially causing issues with SD Prompt Reader's ability
to read image metadata correctly, it is recommended to embed this node within the workflow
to ensure maximum compatibility.
- Since it's not possible to directly extract metadata from KSampler, it is necessary to
use the Parameter Generator Node to generate parameters and simultaneously output them to both
the Prompt Saver Node and KSampler.
<div align="center">
<img src="./images/generator_saver.png" width="50%" height="50%" alt="generator and saver node">
</div>
### Prompt Merger Node & Type Converter Node
- Since the A1111 format cannot store `text_g` and `text_l` separately, SDXL users need to use
the Prompt Merger Node to combine `text_g` and `text_l` into a single prompt.
- In some cases, inputs like `model_name`, `sampler_name`, and `scheduler` may conflict with other custom nodes.
You can use the SD Type Converter to convert them into `STRING` type and then
input them into `model_name_str`, `sampler_name_str`, and `scheduler_str`. Please note that inputs of type `STRING`
have higher priority, so do not connect `STRING` inputs unless necessary, as the Prompt Saver will prioritize reading
`STRING` inputs over regular ones.
<div align="center">
<img src="./images/merger_converter.png" width="25%" height="25%" alt="merger and converter node">
</div>
### [Example Workflow](./workflows/example_workflow.json)
<div align="center">
<img src="./images/example_workflow.png" width="100%" height="100%" alt="example workflow">
</div>
## Credits
- The SD Prompt Reader node is based on [ComfyUI_Load_Image_With_Metadata](https://github.com/tkoenig89/ComfyUI_Load_Image_With_Metadata)
- The SD Prompt Saver node is based on [comfy-image-saver](https://github.com/giriss/comfy-image-saver) & [stable-diffusion-webui](https://github.com/AUTOMATIC1111/stable-diffusion-webui)
- The SD Prompt Reader node is based on [ComfyUI Load Image With Metadata](https://github.com/tkoenig89/ComfyUI_Load_Image_With_Metadata)
- The SD Prompt Saver node is based on [Comfy Image Saver](https://github.com/giriss/comfy-image-saver) & [Stable Diffusion Webui](https://github.com/AUTOMATIC1111/stable-diffusion-webui)
+1 -1
View File
@@ -1 +1 @@
VERSION = "1.0.0b1"
VERSION = "1.0.0b2"
Binary file not shown.

After

Width:  |  Height:  |  Size: 906 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 385 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 738 KiB

After

Width:  |  Height:  |  Size: 730 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 787 KiB

+83 -33
View File
@@ -185,7 +185,10 @@ class SDPromptSaver:
"required": {
"images": ("IMAGE",),
"filename_prefix": ("STRING", {"default": "ComfyUI"}),
},
"optional": {
"model_name": (folder_paths.get_filename_list("checkpoints"),),
"model_name_str": ("STRING", {"default": ""}),
"seed": (
"INT",
{
@@ -209,12 +212,12 @@ class SDPromptSaver:
},
),
"sampler_name": (comfy.samplers.KSampler.SAMPLERS,),
"sampler_name_str": ("STRING", {"default": ""}),
"scheduler": (comfy.samplers.KSampler.SCHEDULERS,),
"scheduler_str": ("STRING", {"default": ""}),
"positive": ("STRING", {"default": "", "multiline": True}),
"negative": ("STRING", {"default": "", "multiline": True}),
"extension": (["png", "jpg", "webp"],),
},
"optional": {
"width": (
"INT",
{"default": 0, "min": 1, "max": MAX_RESOLUTION, "step": 8},
@@ -242,11 +245,14 @@ class SDPromptSaver:
images,
filename_prefix,
model_name: str = "",
model_name_str: str = "",
seed: int = 0,
steps: int = 0,
cfg: float = 0.0,
sampler_name: str = "",
sampler_name_str: str = "",
scheduler: str = "",
scheduler_str: str = "",
positive: str = "",
negative: str = "",
extension: str = "png",
@@ -269,12 +275,17 @@ class SDPromptSaver:
filename_prefix, self.output_dir, images[0].shape[1], images[0].shape[0]
)
results = list()
model_name_real = model_name_str if model_name_str else model_name
sampler_name_real = sampler_name_str if sampler_name_str else sampler_name
scheduler_real = scheduler if scheduler_str else scheduler
for image in images:
i = 255.0 * image.cpu().numpy()
img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8))
metadata = None
model_hash = (
f"Model hash: {self.calculate_model_hash(model_name)}, "
f"Model hash: {self.calculate_model_hash(model_name_real)}, "
if calculate_model_hash
else ""
)
@@ -282,12 +293,12 @@ class SDPromptSaver:
f"{positive}\n"
f"Negative prompt: {negative}\n"
f"Steps: {steps}, "
f"Sampler: {sampler_name}{''if scheduler == 'normal' else '_'+scheduler}, "
f"Sampler: {sampler_name_real}{''if scheduler_real == 'normal' else '_'+scheduler_real}, "
f"CFG scale: {cfg}, "
f"Seed: {seed}, "
f"Size: {img.width if width==0 else width}x{img.height if height==0 else height}, "
f"{model_hash}"
f"Model: {Path(model_name).stem}, "
f"Model: {Path(model_name_real).stem}, "
f"Version: ComfyUI"
)
file = Path(full_output_folder) / f"{filename}_{counter:05}_.{extension}"
@@ -338,32 +349,6 @@ class SDPromptSaver:
return hash_sha256.hexdigest()[:10]
class SDPromptMerger:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"text_g": (
"STRING",
{"default": "", "multiline": True, "forceInput": True},
),
"text_l": (
"STRING",
{"default": "", "multiline": True, "forceInput": True},
),
},
}
RETURN_TYPES = ("STRING",)
FUNCTION = "merge_prompt"
CATEGORY = "SD Prompt Reader"
def merge_prompt(self, text_g, text_l):
if text_l == "":
return text_g
return (text_g + "\n" + text_l,)
class SDParameterGenerator:
@classmethod
def INPUT_TYPES(s):
@@ -477,16 +462,81 @@ class SDParameterGenerator:
)
class SDPromptMerger:
@classmethod
def INPUT_TYPES(s):
return {
"required": {
"text_g": (
"STRING",
{"default": "", "multiline": True, "forceInput": True},
),
"text_l": (
"STRING",
{"default": "", "multiline": True, "forceInput": True},
),
},
}
RETURN_TYPES = ("STRING",)
FUNCTION = "merge_prompt"
CATEGORY = "SD Prompt Reader"
def merge_prompt(self, text_g, text_l):
if text_l == "":
return text_g
return (text_g + "\n" + text_l,)
class SDTypeConverter:
@classmethod
def INPUT_TYPES(s):
return {
"required": {},
"optional": {
"model_name": (folder_paths.get_filename_list("checkpoints"),),
"sampler_name": (comfy.samplers.KSampler.SAMPLERS,),
"scheduler": (comfy.samplers.KSampler.SCHEDULERS,),
},
}
RETURN_TYPES = (
"STRING",
"STRING",
"STRING",
)
RETURN_NAMES = (
"MODEL_NAME_STR",
"SAMPLER_NAME_STR",
"SCHEDULER_STR",
)
FUNCTION = "convert_string"
CATEGORY = "SD Prompt Reader"
def convert_string(
self, model_name: str = "", sampler_name: str = "", scheduler: str = ""
):
return (
model_name,
sampler_name,
scheduler,
)
NODE_CLASS_MAPPINGS = {
"SDPromptReader": SDPromptReader,
"SDPromptSaver": SDPromptSaver,
"SDPromptMerger": SDPromptMerger,
"SDParameterGenerator": SDParameterGenerator,
"SDPromptMerger": SDPromptMerger,
"SDTypeConverter": SDTypeConverter,
}
NODE_DISPLAY_NAME_MAPPINGS = {
"SDPromptReader": "SD Prompt Reader",
"SDPromptSaver": "SD Prompt Saver",
"SDPromptMerger": "SD Prompt Merger",
"SDParameterGenerator": "SD Parameter Generator",
"SDPromptMerger": "SD Prompt Merger",
"SDTypeConverter": "SD Type Converter",
}
File diff suppressed because it is too large Load Diff