changes to checkpointloader. added hash + more
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
This repository contains custom nodes for ComfyUI.
|
||||
|
||||
## Prompt With Style
|
||||
|
||||

|
||||
|
||||
Example workflow in the prompt_with_styles.json file and mikey_node_workflow.json
|
||||
@@ -19,7 +20,9 @@ There is a V1 and V2 Prompt with Style node with different functionality, style
|
||||
|
||||
### Wildcards
|
||||
|
||||
Wildcards are supported using the `__word__` syntax. Folder location is comfyui/wildcards You can select more than 1 line from the wildcard by using the syntax `[2$$__wildcard__]` for 2 lines in this example. You can also add a word to search for in the wildcard file e.g. `__wildcard|word__`
|
||||
Wildcards are supported using the `__word__` syntax. Folder location is comfyui/wildcards You can select more than 1 line from the wildcard by using the syntax `2$$__wildcard__` for 2 lines in this example. You can also add a word to search for in the wildcard file e.g. `__wildcard|word__`
|
||||
|
||||
You can also make sure it selects the same line from the wildcard by using the `__!wildcard__` syntax, not the ! before the filename. You can also use `__+wildcard__` `__-wildcard__` and `__*wildcard__` to use the offset + 1 or - 1, or randomly select a different line.
|
||||
|
||||
### Styles
|
||||
|
||||
@@ -53,6 +56,7 @@ The format needs to look like the following example:
|
||||
```
|
||||
|
||||
## Mikey Sampler and Mikey Sampler Base Only
|
||||
|
||||

|
||||

|
||||
|
||||
@@ -60,7 +64,7 @@ Example workflow: mikey_node_workflow.json
|
||||
|
||||
This is a sampler node as a companion to the Prompt with Style node, to allow for very straightforward image generation with SDXL.
|
||||
|
||||
The node uses a base -> refiner -> upscale with model -> base to produce the final image. It has an inbuilt image complexity detection function to make sure there aren't too many steps run on the final base sampler which can scramble faces and other simple areas on a large image.
|
||||
The node uses a base -> refiner -> upscale with model -> base to produce the final image. It has an inbuilt image complexity detection function to make sure there aren't too many steps run on the final base sampler which can scramble faces and other simple areas on a large image.
|
||||
|
||||
The Base Only version of the sampler uses a slightly different approach. It uses a base -> base -> upscale with model -> base to produce the final image.
|
||||
The other key difference with the Base Only version is it skips a step in the middle and adds it to the end. This is a trick which adds extra detail to the image. The smooth step number will add even more extra steps to the end. This might be required if you have an image with a plain background and are seeing some spotty effects created by the skip step method. Usually only 1 extra step is required to clean up the spots. You can also go -1 for very busy images for even more detail.
|
||||
@@ -71,7 +75,7 @@ The seed is used by the samplers.
|
||||
|
||||
The upscale_by setting is how large you want the final image to be before it runs the last base sampler over the image. A value of 1 will output the original image size. 2 will be 2x the size of the original.
|
||||
|
||||
The highres_strength setting allows you to control this last stage and how much detail it adds. Setting of 1 is the sweet spot I found didn't scramble faces in a few test images. Dial it down if you are still getting scrambled images, or turn it up if you want to add more detail.
|
||||
The highres_strength setting allows you to control this last stage and how much detail it adds. Setting of 1 is the sweet spot I found didn't scramble faces in a few test images. Dial it down if you are still getting scrambled images, or turn it up if you want to add more detail.
|
||||
|
||||
## Mikey Sampler Tiled and Mikey Sampler Tiled Base Only
|
||||
|
||||
@@ -80,6 +84,7 @@ The highres_strength setting allows you to control this last stage and how much
|
||||
These samplers use a tiled approach to resample the image after the upscale model has upscaled the image, to help enhance the image with more details.
|
||||
|
||||
## Style Conditioner
|
||||
|
||||

|
||||
|
||||
This chonky node is for injecting the style prompt into your conditioner by averaging the conditioner passed through the node.
|
||||
@@ -87,11 +92,13 @@ This chonky node is for injecting the style prompt into your conditioner by aver
|
||||
A strength value of 0.5 would be even split between the conditioner passed in and the style selected.
|
||||
|
||||
## Empty Latent Ratio Select SDXL
|
||||
|
||||

|
||||
|
||||
This node allows you to select from a range of different aspect ratios.
|
||||
|
||||
## Empty Latent Ratio Custom SDXL
|
||||
|
||||

|
||||
|
||||
This node allows you to enter your own aspect ratio or image size from wherever, and it will make it fit under 1024x1024 resolution.
|
||||
@@ -124,7 +131,7 @@ It is a really powerful and convenient ratio selector, because you can create al
|
||||
|
||||
The swap axis option will rotate the dimensions by 90 degrees if set to true.
|
||||
|
||||
If use preset seed is set to true, it will use the seed number to select one of the available presets. This can be used to cycle or randomly select presets, which is super convenient.
|
||||
If use preset seed is set to true, it will use the seed number to select one of the available presets. This can be used to cycle or randomly select presets, which is super convenient.
|
||||
|
||||
## Ratio Advanced
|
||||
|
||||
@@ -136,18 +143,20 @@ When creating a latent image you need to set the width and height. But the Clip
|
||||
|
||||
This node has options to setup the dimensions for each of these using different methods:
|
||||
|
||||
* Select a ratio from the select widget, or choose custom to enter your own dimensions.
|
||||
* If you select custom, you need to fill in the width and height options.
|
||||
* If you enter a number into the mult input e.g. cte_mult (clip text encoder) it will multiply the latent width and height to create the width and height for that dimension.
|
||||
* If you enter a number into the res input, it will create a width and height that fits into the res^2 image size while maintining the same ratio as the latent width and height.
|
||||
* If you enter a number into the fit_size input, it will create a width and height that has the largest dimension equal to fit_size while maintaining the same ratio as the latent width and height.
|
||||
* Select a ratio from the select widget, or choose custom to enter your own dimensions.
|
||||
* If you select custom, you need to fill in the width and height options.
|
||||
* If you enter a number into the mult input e.g. cte_mult (clip text encoder) it will multiply the latent width and height to create the width and height for that dimension.
|
||||
* If you enter a number into the res input, it will create a width and height that fits into the res^2 image size while maintining the same ratio as the latent width and height.
|
||||
* If you enter a number into the fit_size input, it will create a width and height that has the largest dimension equal to fit_size while maintaining the same ratio as the latent width and height.
|
||||
|
||||
## Resize Image for SDXL
|
||||
|
||||

|
||||
|
||||
This node allows you to resize an image to fit into 1024x1024 resolution. Good for Img2Img workflows.
|
||||
|
||||
## Batch Resize Image for SDXL
|
||||
|
||||

|
||||
|
||||
Given a path to a folder containing images, it will resize all images in the folder to fit the 1024^2 resolution and feed into the workflow. Careful of folders with lots of images!
|
||||
@@ -161,6 +170,7 @@ The filename will start with a datestamp, then part of the positive prompt.
|
||||
It will also save the positive prompt and negative prompt to the png data.
|
||||
|
||||
## Upscale Tile Calculator
|
||||
|
||||

|
||||
|
||||
Made for the [Ultimate SD Upscaler](https://github.com/ssitu/ComfyUI_UltimateSDUpscale) to help calcuate tile size to evenly fit inside the larger image and not get weird edges.
|
||||
@@ -168,6 +178,7 @@ Made for the [Ultimate SD Upscaler](https://github.com/ssitu/ComfyUI_UltimateSDU
|
||||
The resolution is what is suitable for the model you are using, 1.5: 512, 2.1: 768, SDXL Base: 1024, SDXL Refiner: 768
|
||||
|
||||
## Wildcard Processor
|
||||
|
||||

|
||||
|
||||
This node is for building a string using your wildcard files.
|
||||
@@ -213,7 +224,8 @@ Converts an integer to a string.
|
||||
Converts a float to a string.
|
||||
|
||||
## Removed Nodes
|
||||
- VAE Decode 6GB
|
||||
|
||||
- VAE Decode 6GB
|
||||
|
||||
## Installation
|
||||
|
||||
|
||||
+217
-59
@@ -218,7 +218,8 @@ def read_styles():
|
||||
def find_and_replace_wildcards(prompt, offset_seed, debug=False):
|
||||
# wildcards use the __file_name__ syntax with optional |word_to_find
|
||||
wildcard_path = os.path.join(folder_paths.base_path, 'wildcards')
|
||||
wildcard_regex = r'(\[(\d+)\$\$)?__((?:[^|_]+_)*[^|_]+)((?:\|[^|]+)*)__\]?'
|
||||
wildcard_regex = r'((\d+)\$\$)?__(!|\+|-|\*)?((?:[^|_]+_)*[^|_]+)((?:\|[^|]+)*)__'
|
||||
# r'(\[(\d+)\$\$)?__((?:[^|_]+_)*[^|_]+)((?:\|[^|]+)*)__\]?'
|
||||
match_strings = []
|
||||
random.seed(offset_seed)
|
||||
offset = offset_seed
|
||||
@@ -227,10 +228,19 @@ def find_and_replace_wildcards(prompt, offset_seed, debug=False):
|
||||
last_end = 0
|
||||
|
||||
for m in re.finditer(wildcard_regex, prompt):
|
||||
full_match, lines_count_str, actual_match, words_to_find_str = m.groups()
|
||||
full_match, lines_count_str, offset_type, actual_match, words_to_find_str = m.groups()
|
||||
# Append everything up to this match
|
||||
new_prompt += prompt[last_end:m.start()]
|
||||
|
||||
# lock indicator
|
||||
lock_indicator = offset_type == '!'
|
||||
# increment indicator
|
||||
increment_indicator = offset_type == '+'
|
||||
# decrement indicator
|
||||
decrement_indicator = offset_type == '-'
|
||||
# random indicator
|
||||
random_indicator = offset_type == '*'
|
||||
|
||||
#for full_match, lines_count_str, actual_match, words_to_find_str in re.findall(wildcard_regex, prompt):
|
||||
words_to_find = words_to_find_str.split('|')[1:] if words_to_find_str else None
|
||||
if debug:
|
||||
@@ -254,7 +264,16 @@ def find_and_replace_wildcards(prompt, offset_seed, debug=False):
|
||||
store_offset = None
|
||||
if actual_match in match_strings:
|
||||
store_offset = offset
|
||||
offset = random.randint(0, 1000000)
|
||||
if lock_indicator:
|
||||
offset = offset_seed
|
||||
elif random_indicator:
|
||||
offset = random.randint(0, 1000000)
|
||||
elif increment_indicator:
|
||||
offset = offset_seed + 1
|
||||
elif decrement_indicator:
|
||||
offset = offset_seed - 1
|
||||
else:
|
||||
offset = random.randint(0, 1000000)
|
||||
selected_lines = []
|
||||
with open(file_path, 'r', encoding='utf-8') as file:
|
||||
file_lines = file.readlines()
|
||||
@@ -781,14 +800,14 @@ class RatioAdvanced:
|
||||
# check if target_fit_size not 0
|
||||
if target_fit_size != 0:
|
||||
target_w, target_h = self.fit(target_w, target_h, target_fit_size)
|
||||
prompt.get(str(unique_id))['inputs']['output_latent_w'] = str(latent_width)
|
||||
prompt.get(str(unique_id))['inputs']['output_latent_h'] = str(latent_height)
|
||||
prompt.get(str(unique_id))['inputs']['output_cte_w'] = str(cte_w)
|
||||
prompt.get(str(unique_id))['inputs']['output_cte_h'] = str(cte_h)
|
||||
prompt.get(str(unique_id))['inputs']['output_target_w'] = str(target_w)
|
||||
prompt.get(str(unique_id))['inputs']['output_target_h'] = str(target_h)
|
||||
prompt.get(str(unique_id))['inputs']['output_crop_w'] = str(crop_w)
|
||||
prompt.get(str(unique_id))['inputs']['output_crop_h'] = str(crop_h)
|
||||
#prompt.get(str(unique_id))['inputs']['output_latent_w'] = str(latent_width)
|
||||
#prompt.get(str(unique_id))['inputs']['output_latent_h'] = str(latent_height)
|
||||
#prompt.get(str(unique_id))['inputs']['output_cte_w'] = str(cte_w)
|
||||
#prompt.get(str(unique_id))['inputs']['output_cte_h'] = str(cte_h)
|
||||
#prompt.get(str(unique_id))['inputs']['output_target_w'] = str(target_w)
|
||||
#prompt.get(str(unique_id))['inputs']['output_target_h'] = str(target_h)
|
||||
#prompt.get(str(unique_id))['inputs']['output_crop_w'] = str(crop_w)
|
||||
#prompt.get(str(unique_id))['inputs']['output_crop_h'] = str(crop_h)
|
||||
return (latent_width, latent_height,
|
||||
cte_w, cte_h,
|
||||
target_w, target_h,
|
||||
@@ -837,14 +856,14 @@ class PresetRatioSelector:
|
||||
cte_w, cte_h = cte_h, cte_w
|
||||
target_w, target_h = target_h, target_w
|
||||
crop_w, crop_h = crop_h, crop_w
|
||||
prompt.get(str(unique_id))['inputs']['output_latent_w'] = str(latent_width)
|
||||
prompt.get(str(unique_id))['inputs']['output_latent_h'] = str(latent_height)
|
||||
prompt.get(str(unique_id))['inputs']['output_cte_w'] = str(cte_w)
|
||||
prompt.get(str(unique_id))['inputs']['output_cte_h'] = str(cte_h)
|
||||
prompt.get(str(unique_id))['inputs']['output_target_w'] = str(target_w)
|
||||
prompt.get(str(unique_id))['inputs']['output_target_h'] = str(target_h)
|
||||
prompt.get(str(unique_id))['inputs']['output_crop_w'] = str(crop_w)
|
||||
prompt.get(str(unique_id))['inputs']['output_crop_h'] = str(crop_h)
|
||||
#prompt.get(str(unique_id))['inputs']['output_latent_w'] = str(latent_width)
|
||||
#prompt.get(str(unique_id))['inputs']['output_latent_h'] = str(latent_height)
|
||||
#prompt.get(str(unique_id))['inputs']['output_cte_w'] = str(cte_w)
|
||||
#prompt.get(str(unique_id))['inputs']['output_cte_h'] = str(cte_h)
|
||||
#prompt.get(str(unique_id))['inputs']['output_target_w'] = str(target_w)
|
||||
#prompt.get(str(unique_id))['inputs']['output_target_h'] = str(target_h)
|
||||
#prompt.get(str(unique_id))['inputs']['output_crop_w'] = str(crop_w)
|
||||
#prompt.get(str(unique_id))['inputs']['output_crop_h'] = str(crop_h)
|
||||
return (latent_width, latent_height,
|
||||
cte_w, cte_h,
|
||||
target_w, target_h,
|
||||
@@ -2064,16 +2083,16 @@ class PromptWithStyleV3:
|
||||
sdxl_neg_cond = CLIPTextEncodeSDXL.encode(self, clip_base_neg, width, height, 0, 0, target_width, target_height, neg_prompt_, neg_style_)[0]
|
||||
refiner_pos_cond = CLIPTextEncodeSDXLRefiner.encode(self, clip_refiner, 6, refiner_width, refiner_height, pos_prompt_)[0]
|
||||
refiner_neg_cond = CLIPTextEncodeSDXLRefiner.encode(self, clip_refiner, 2.5, refiner_width, refiner_height, neg_prompt_)[0]
|
||||
prompt.get(str(unique_id))['inputs']['output_positive_prompt'] = pos_prompt_
|
||||
prompt.get(str(unique_id))['inputs']['output_negative_prompt'] = neg_prompt_
|
||||
prompt.get(str(unique_id))['inputs']['output_latent_width'] = width
|
||||
prompt.get(str(unique_id))['inputs']['output_latent_height'] = height
|
||||
prompt.get(str(unique_id))['inputs']['output_target_width'] = target_width
|
||||
prompt.get(str(unique_id))['inputs']['output_target_height'] = target_height
|
||||
prompt.get(str(unique_id))['inputs']['output_refiner_width'] = refiner_width
|
||||
prompt.get(str(unique_id))['inputs']['output_refiner_height'] = refiner_height
|
||||
prompt.get(str(unique_id))['inputs']['output_crop_w'] = 0
|
||||
prompt.get(str(unique_id))['inputs']['output_crop_h'] = 0
|
||||
#prompt.get(str(unique_id))['inputs']['output_positive_prompt'] = pos_prompt_
|
||||
#prompt.get(str(unique_id))['inputs']['output_negative_prompt'] = neg_prompt_
|
||||
#prompt.get(str(unique_id))['inputs']['output_latent_width'] = width
|
||||
#prompt.get(str(unique_id))['inputs']['output_latent_height'] = height
|
||||
#prompt.get(str(unique_id))['inputs']['output_target_width'] = target_width
|
||||
#prompt.get(str(unique_id))['inputs']['output_target_height'] = target_height
|
||||
#prompt.get(str(unique_id))['inputs']['output_refiner_width'] = refiner_width
|
||||
#prompt.get(str(unique_id))['inputs']['output_refiner_height'] = refiner_height
|
||||
#prompt.get(str(unique_id))['inputs']['output_crop_w'] = 0
|
||||
#prompt.get(str(unique_id))['inputs']['output_crop_h'] = 0
|
||||
return (base_model, {"samples":latent},
|
||||
sdxl_pos_cond, sdxl_neg_cond,
|
||||
refiner_pos_cond, refiner_neg_cond,
|
||||
@@ -2127,16 +2146,16 @@ class PromptWithStyleV3:
|
||||
sdxl_neg_cond = CLIPTextEncodeSDXL.encode(self, clip_base_neg, width, height, 0, 0, target_width, target_height, neg_prompt_, neg_style_)[0]
|
||||
refiner_pos_cond = CLIPTextEncodeSDXLRefiner.encode(self, clip_refiner, 6, refiner_width, refiner_height, pos_prompt_)[0]
|
||||
refiner_neg_cond = CLIPTextEncodeSDXLRefiner.encode(self, clip_refiner, 2.5, refiner_width, refiner_height, neg_prompt_)[0]
|
||||
prompt.get(str(unique_id))['inputs']['output_positive_prompt'] = pos_prompt_
|
||||
prompt.get(str(unique_id))['inputs']['output_negative_prompt'] = neg_prompt_
|
||||
prompt.get(str(unique_id))['inputs']['output_latent_width'] = width
|
||||
prompt.get(str(unique_id))['inputs']['output_latent_height'] = height
|
||||
prompt.get(str(unique_id))['inputs']['output_target_width'] = target_width
|
||||
prompt.get(str(unique_id))['inputs']['output_target_height'] = target_height
|
||||
prompt.get(str(unique_id))['inputs']['output_refiner_width'] = refiner_width
|
||||
prompt.get(str(unique_id))['inputs']['output_refiner_height'] = refiner_height
|
||||
prompt.get(str(unique_id))['inputs']['output_crop_w'] = 0
|
||||
prompt.get(str(unique_id))['inputs']['output_crop_h'] = 0
|
||||
#prompt.get(str(unique_id))['inputs']['output_positive_prompt'] = pos_prompt_
|
||||
#prompt.get(str(unique_id))['inputs']['output_negative_prompt'] = neg_prompt_
|
||||
#prompt.get(str(unique_id))['inputs']['output_latent_width'] = width
|
||||
#prompt.get(str(unique_id))['inputs']['output_latent_height'] = height
|
||||
#prompt.get(str(unique_id))['inputs']['output_target_width'] = target_width
|
||||
#prompt.get(str(unique_id))['inputs']['output_target_height'] = target_height
|
||||
#prompt.get(str(unique_id))['inputs']['output_refiner_width'] = refiner_width
|
||||
#prompt.get(str(unique_id))['inputs']['output_refiner_height'] = refiner_height
|
||||
#prompt.get(str(unique_id))['inputs']['output_crop_w'] = 0
|
||||
#prompt.get(str(unique_id))['inputs']['output_crop_h'] = 0
|
||||
return (base_model, {"samples":latent},
|
||||
sdxl_pos_cond, sdxl_neg_cond,
|
||||
refiner_pos_cond, refiner_neg_cond,
|
||||
@@ -2168,16 +2187,16 @@ class PromptWithStyleV3:
|
||||
refiner_neg_cond = ConditioningAverage.addWeighted(self, refiner_neg_conds[i], refiner_neg_cond, 1 / weight)[0]
|
||||
# return
|
||||
extra_pnginfo['PromptWithStyle'] = prompt_with_style
|
||||
prompt.get(str(unique_id))['inputs']['output_positive_prompt'] = pos_prompt_
|
||||
prompt.get(str(unique_id))['inputs']['output_negative_prompt'] = neg_prompt_
|
||||
prompt.get(str(unique_id))['inputs']['output_latent_width'] = width
|
||||
prompt.get(str(unique_id))['inputs']['output_latent_height'] = height
|
||||
prompt.get(str(unique_id))['inputs']['output_target_width'] = target_width
|
||||
prompt.get(str(unique_id))['inputs']['output_target_height'] = target_height
|
||||
prompt.get(str(unique_id))['inputs']['output_refiner_width'] = refiner_width
|
||||
prompt.get(str(unique_id))['inputs']['output_refiner_height'] = refiner_height
|
||||
prompt.get(str(unique_id))['inputs']['output_crop_w'] = 0
|
||||
prompt.get(str(unique_id))['inputs']['output_crop_h'] = 0
|
||||
#prompt.get(str(unique_id))['inputs']['output_positive_prompt'] = pos_prompt_
|
||||
#prompt.get(str(unique_id))['inputs']['output_negative_prompt'] = neg_prompt_
|
||||
#prompt.get(str(unique_id))['inputs']['output_latent_width'] = width
|
||||
#prompt.get(str(unique_id))['inputs']['output_latent_height'] = height
|
||||
#prompt.get(str(unique_id))['inputs']['output_target_width'] = target_width
|
||||
#prompt.get(str(unique_id))['inputs']['output_target_height'] = target_height
|
||||
#prompt.get(str(unique_id))['inputs']['output_refiner_width'] = refiner_width
|
||||
#prompt.get(str(unique_id))['inputs']['output_refiner_height'] = refiner_height
|
||||
#prompt.get(str(unique_id))['inputs']['output_crop_w'] = 0
|
||||
#prompt.get(str(unique_id))['inputs']['output_crop_h'] = 0
|
||||
return (base_model, {"samples":latent},
|
||||
sdxl_pos_cond, sdxl_neg_cond,
|
||||
refiner_pos_cond, refiner_neg_cond,
|
||||
@@ -2293,7 +2312,7 @@ class WildcardAndLoraSyntaxProcessor:
|
||||
if len(text_) != len(text):
|
||||
seed = random.randint(0, 1000000)
|
||||
else:
|
||||
seed = 0
|
||||
seed = 1
|
||||
# extract and load loras
|
||||
model, clip, stripped_text = self.extract_and_load_loras(text_, model, clip)
|
||||
# process wildcards again
|
||||
@@ -2347,7 +2366,7 @@ class StyleConditionerBaseOnly:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
s.styles, s.pos_style, s.neg_style = read_styles()
|
||||
return {"required": {"style": (s.styles,),"strength": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.1}),
|
||||
return {"required": {"style": (s.styles,),"strength": ("FLOAT", {"default": 0.5, "min": 0.0, "max": 1.0, "step": 0.01}),
|
||||
"positive_cond_base": ("CONDITIONING",), "negative_cond_base": ("CONDITIONING",),
|
||||
"base_clip": ("CLIP",),
|
||||
"use_seed": (['true','false'], {'default': 'false'}),
|
||||
@@ -3818,8 +3837,7 @@ class Text2InputOr3rdOption:
|
||||
class CheckpointLoaderSimpleMikey:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {"required": { "ckpt_name": (folder_paths.get_filename_list("checkpoints"), ),
|
||||
},
|
||||
return {"required": { "ckpt_name": (folder_paths.get_filename_list("checkpoints"), ),},
|
||||
"hidden": {"unique_id": "UNIQUE_ID", "extra_pnginfo": "EXTRA_PNGINFO", "prompt": "PROMPT"}}
|
||||
|
||||
RETURN_TYPES = ("MODEL", "CLIP", "VAE", "STRING", "STRING")
|
||||
@@ -3831,13 +3849,43 @@ class CheckpointLoaderSimpleMikey:
|
||||
def load_checkpoint(self, ckpt_name, output_vae=True, output_clip=True, unique_id=None, extra_pnginfo=None, prompt=None):
|
||||
ckpt_path = folder_paths.get_full_path("checkpoints", ckpt_name)
|
||||
out = comfy.sd.load_checkpoint_guess_config(ckpt_path, output_vae=True, output_clip=True, embedding_directory=folder_paths.get_folder_paths("embeddings"))
|
||||
# get hash using python, there is no function in the comfy library
|
||||
hash = get_file_hash(ckpt_path)[:10]
|
||||
# just return the filename, not path
|
||||
hash = get_file_hash(ckpt_path)
|
||||
ckpt_name = os.path.basename(ckpt_name)
|
||||
#prompt.get(str(unique_id))['inputs']['output_ckpt_hash'] = hash
|
||||
#prompt.get(str(unique_id))['inputs']['output_ckpt_name'] = ckpt_name
|
||||
return out[:3] + (ckpt_name, hash)
|
||||
|
||||
class CheckpointHash:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {"required": { "ckpt_name": ("STRING", {"forceInput": True}),},
|
||||
"hidden": {"unique_id": "UNIQUE_ID", "extra_pnginfo": "EXTRA_PNGINFO", "prompt": "PROMPT"}}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
RETURN_NAMES = ("ckpt_hash",)
|
||||
FUNCTION = "get_hash"
|
||||
CATEGORY = "Mikey/Loaders"
|
||||
|
||||
def get_hash(self, ckpt_name, extra_pnginfo, prompt, unique_id):
|
||||
ckpt_path = folder_paths.get_full_path("checkpoints", ckpt_name)
|
||||
hash = get_file_hash(ckpt_path)
|
||||
prompt.get(str(unique_id))['inputs']['output_ckpt_hash'] = hash
|
||||
prompt.get(str(unique_id))['inputs']['output_ckpt_name'] = ckpt_name
|
||||
return out[:3] + (ckpt_name, hash)
|
||||
return (get_file_hash(ckpt_path),)
|
||||
|
||||
class SRPromptInputAdd:
|
||||
@classmethod
|
||||
def INPUT_TYPES(s):
|
||||
return {'required': {'input_str': ('STRING', {'forceInput': True}),},
|
||||
"hidden": {"unique_id": "UNIQUE_ID", "extra_pnginfo": "EXTRA_PNGINFO", "prompt": "PROMPT"}}
|
||||
|
||||
RETURN_TYPES = ("STRING",)
|
||||
FUNCTION = "add"
|
||||
CATEGORY = "Mikey/Meta"
|
||||
|
||||
def add(self, input_str, unique_id=None, extra_pnginfo=None, prompt=None):
|
||||
prompt.get(str(unique_id))['inputs']['input_str'] = input_str
|
||||
return (input_str,)
|
||||
|
||||
class TextPreserve:
|
||||
@classmethod
|
||||
@@ -3854,6 +3902,8 @@ class TextPreserve:
|
||||
CATEGORY = 'Mikey/Text'
|
||||
|
||||
def process(self, text, result_text, unique_id=None, extra_pnginfo=None, prompt=None):
|
||||
# reset random seed
|
||||
random.seed()
|
||||
preserve_text = text
|
||||
# search and replace
|
||||
text = search_and_replace(text, extra_pnginfo, prompt)
|
||||
@@ -4673,6 +4723,110 @@ class CinematicLook:
|
||||
# batch_tensor = torch.cat(images, dim=0)
|
||||
# return (batch_tensor, )
|
||||
|
||||
class MosaicExpandImage:
|
||||
@classmethod
|
||||
def INPUT_TYPES(cls):
|
||||
return {'required': {'image': ('IMAGE', {'default': None}),
|
||||
'left': ('INT', {'default': 0, 'min': 0, 'max': 5}),
|
||||
'top': ('INT', {'default': 0, 'min': 0, 'max': 5}),
|
||||
'right': ('INT', {'default': 0, 'min': 0, 'max': 5}),
|
||||
'bottom': ('INT', {'default': 0, 'min': 0, 'max': 5})}}
|
||||
|
||||
RETURN_TYPES = ('IMAGE','MASK',)
|
||||
RETURN_NAMES = ('result_img',)
|
||||
FUNCTION = 'mosaic_expand'
|
||||
CATEGORY = 'Mikey/Image'
|
||||
|
||||
def mosaic_expand(self, image, left, top, right, bottom):
|
||||
img = tensor2pil(image)
|
||||
width, height = img.size
|
||||
width_5th, height_5th = width // 5, height // 5
|
||||
|
||||
def create_mosaic(side_img, num_fifths, vertical=False):
|
||||
block_size = 50
|
||||
num_blocks_wide = side_img.width // block_size
|
||||
num_blocks_high = (num_fifths * height_5th) // block_size if vertical else side_img.height // block_size
|
||||
mosaic_width = block_size * num_blocks_wide
|
||||
mosaic_height = block_size * num_blocks_high
|
||||
|
||||
mosaic_img = Image.new('RGB', (mosaic_width, mosaic_height))
|
||||
|
||||
for i in range(num_blocks_wide):
|
||||
for j in range(num_blocks_high):
|
||||
# Calculate the average color of each block
|
||||
section = side_img.crop((i * block_size, j * block_size, (i + 1) * block_size, (j + 1) * block_size))
|
||||
avg_color = np.array(section).mean(axis=(0, 1)).astype(np.uint8)
|
||||
# Fill the corresponding block in the mosaic
|
||||
for x in range(block_size):
|
||||
for y in range(block_size):
|
||||
mosaic_x = i * block_size + x
|
||||
mosaic_y = j * block_size + y
|
||||
mosaic_img.putpixel((mosaic_x, mosaic_y), tuple(avg_color))
|
||||
return mosaic_img
|
||||
|
||||
self.new_width = width + width_5th * (left + right)
|
||||
self.new_height = height + height_5th * (top + bottom)
|
||||
new_img = Image.new('RGB', (self.new_width, self.new_height))
|
||||
|
||||
# Create and paste mosaic strips
|
||||
if right > 0:
|
||||
right_side = img.crop((width - width_5th * right, 0, width, height))
|
||||
right_mosaic = create_mosaic(right_side, right)
|
||||
right_mosaic = right_mosaic.transpose(Image.FLIP_LEFT_RIGHT)
|
||||
# resize mosaic to match new height
|
||||
right_mosaic = right_mosaic.resize((width_5th * right + 8, self.new_height))
|
||||
new_img.paste(right_mosaic, (width + width_5th * left, 0))
|
||||
|
||||
if left > 0:
|
||||
left_side = img.crop((0, 0, width_5th * left, height))
|
||||
left_mosaic = create_mosaic(left_side, left)
|
||||
left_mosaic = left_mosaic.transpose(Image.FLIP_LEFT_RIGHT)
|
||||
# resize mosaic to match new height
|
||||
left_mosaic = left_mosaic.resize((width_5th * left + 8, self.new_height))
|
||||
new_img.paste(left_mosaic, (0, 0))
|
||||
|
||||
if top > 0:
|
||||
top_side = img.crop((0, 0, width, height_5th * top))
|
||||
top_mosaic = create_mosaic(top_side, top, vertical=True)
|
||||
top_mosaic = top_mosaic.transpose(Image.FLIP_TOP_BOTTOM)
|
||||
top_mosaic = top_mosaic.resize((width + 32, height_5th * top + 8))
|
||||
new_img.paste(top_mosaic, (width_5th * left, 0))
|
||||
|
||||
if bottom > 0:
|
||||
bottom_side = img.crop((0, height - height_5th * bottom, width, height))
|
||||
bottom_mosaic = create_mosaic(bottom_side, bottom, vertical=True)
|
||||
bottom_mosaic = bottom_mosaic.transpose(Image.FLIP_TOP_BOTTOM)
|
||||
bottom_mosaic = bottom_mosaic.resize((width + 32, height_5th * bottom + 8))
|
||||
new_img.paste(bottom_mosaic, (width_5th * left, height + height_5th * top))
|
||||
|
||||
# Paste original image
|
||||
new_img.paste(img, (width_5th * left, height_5th * top))
|
||||
new_img = pil2tensor(new_img)
|
||||
|
||||
# create black and white mask image where white is the original image
|
||||
mask = Image.new('RGB', (self.new_width, self.new_height), (0, 0, 0))
|
||||
white = Image.new('RGB', (width, height), (255, 255, 255))
|
||||
# for each side that has been expanded, shrink that side of the white box by 8 pixels
|
||||
if right > 0:
|
||||
white = white.crop((0, 0, width - 64, height))
|
||||
if left > 0:
|
||||
white = white.crop((64, 0, width, height))
|
||||
if top > 0:
|
||||
white = white.crop((0, 64, width, height))
|
||||
if bottom > 0:
|
||||
white = white.crop((0, 0, width, height - 64))
|
||||
paste_x = width_5th * left + 64
|
||||
if left > 0:
|
||||
paste_x += 64
|
||||
paste_y = height_5th * top
|
||||
if top > 0:
|
||||
paste_y += 64
|
||||
mask.paste(white, (paste_x, paste_y))
|
||||
mask = np.array(mask.getchannel('R')).astype(np.float32) / 255.0
|
||||
mask = 1. - torch.from_numpy(mask)
|
||||
mask = mask.unsqueeze(0)
|
||||
return (new_img, mask)
|
||||
|
||||
NODE_CLASS_MAPPINGS = {
|
||||
'Wildcard Processor': WildcardProcessor,
|
||||
'Empty Latent Ratio Select SDXL': EmptyLatentRatioSelector,
|
||||
@@ -4724,6 +4878,7 @@ NODE_CLASS_MAPPINGS = {
|
||||
'TextCombinations3': TextCombinations3,
|
||||
'Text2InputOr3rdOption': Text2InputOr3rdOption,
|
||||
'Checkpoint Loader Simple Mikey': CheckpointLoaderSimpleMikey,
|
||||
'CheckpointHash': CheckpointHash,
|
||||
'TextPreserve': TextPreserve,
|
||||
'TextConcat': TextConcat,
|
||||
'OobaPrompt': OobaPrompt,
|
||||
@@ -4731,7 +4886,8 @@ NODE_CLASS_MAPPINGS = {
|
||||
'LMStudioPrompt': LMStudioPrompt,
|
||||
'EvalFloats': EvalFloats,
|
||||
'ImageOverlay': ImageOverlay,
|
||||
'CinematicLook': CinematicLook
|
||||
'CinematicLook': CinematicLook,
|
||||
'MosaicExpandImage': MosaicExpandImage
|
||||
}
|
||||
|
||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
@@ -4785,6 +4941,7 @@ NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
'TextCombinations3': 'Text Combinations 3 (Mikey)',
|
||||
'Text2InputOr3rdOption': 'Text 2 Inputs Or 3rd Option Instead (Mikey)',
|
||||
'Checkpoint Loader Simple Mikey': 'Checkpoint Loader Simple (Mikey)',
|
||||
'CheckpointHash': 'Checkpoint Hash (Mikey)',
|
||||
'TextPreserve': 'Text Preserve (Mikey)',
|
||||
'TextConcat': 'Text Concat (Mikey)',
|
||||
'OobaPrompt': 'OobaPrompt (Mikey)',
|
||||
@@ -4792,5 +4949,6 @@ NODE_DISPLAY_NAME_MAPPINGS = {
|
||||
'LMStudioPrompt': 'LM Studio Prompt (Mikey)',
|
||||
'EvalFloats': 'Eval Floats (Mikey)',
|
||||
'ImageOverlay': 'Image Overlay (Mikey)',
|
||||
'CinematicLook': 'Cinematic Look (Mikey)'
|
||||
'CinematicLook': 'Cinematic Look (Mikey)',
|
||||
'MosaicExpandImage': 'Mosaic Expand Image (Mikey)'
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user