mirror of
https://github.com/vladmandic/automatic
synced 2026-09-20 01:31:13 +02:00
improve metadata parser
This commit is contained in:
+2
-1
@@ -4,7 +4,7 @@
|
||||
|
||||
- StableDiffusion 3
|
||||
|
||||
## Update for 2024-06-03
|
||||
## Update for 2024-06-04
|
||||
|
||||
*Note*: New features require `diffusers==0.29.0.dev`
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
- lower overhead on generate calls
|
||||
- cumulative fixes since the last release
|
||||
- add python version check for torch-directml
|
||||
- improve metadata/infotext parser
|
||||
|
||||
## Update for 2024-06-02
|
||||
|
||||
|
||||
+5
-60
@@ -4,71 +4,16 @@ import os
|
||||
import io
|
||||
import re
|
||||
import sys
|
||||
import json
|
||||
import importlib
|
||||
from PIL import Image, ExifTags, TiffImagePlugin, PngImagePlugin
|
||||
from rich import print # pylint: disable=redefined-builtin
|
||||
|
||||
|
||||
def unquote(text):
|
||||
if len(text) == 0 or text[0] != '"' or text[-1] != '"':
|
||||
return text
|
||||
try:
|
||||
return json.loads(text)
|
||||
except Exception:
|
||||
return text
|
||||
module_spec = importlib.util.spec_from_file_location('infotext', os.path.join('modules', 'infotext.py'))
|
||||
infotext = importlib.util.module_from_spec(module_spec)
|
||||
module_spec.loader.exec_module(infotext)
|
||||
|
||||
|
||||
def parse_generation_parameters(infotext):
|
||||
if not isinstance(infotext, str):
|
||||
return {}
|
||||
re_param = re.compile(r'\s*([\w ]+):\s*("(?:\\"[^,]|\\"|\\|[^\"])+"|[^,]*)(?:,|$)') # multi-word: value
|
||||
re_size = re.compile(r"^(\d+)x(\d+)$") # int x int
|
||||
basic_params = ['steps', 'seed', 'width', 'height', 'sampler', 'size', 'cfg scale', 'hires'] # first param is one of those
|
||||
|
||||
sanitized = infotext.replace('prompt:', 'Prompt:').replace('negative prompt:', 'Negative prompt:').replace('Negative Prompt', 'Negative prompt') # cleanup everything in brackets so re_params can work
|
||||
sanitized = re.sub(r'<[^>]*>', lambda match: ' ' * len(match.group()), sanitized)
|
||||
sanitized = re.sub(r'\([^)]*\)', lambda match: ' ' * len(match.group()), sanitized)
|
||||
sanitized = re.sub(r'\{[^}]*\}', lambda match: ' ' * len(match.group()), sanitized)
|
||||
|
||||
params = dict(re_param.findall(sanitized))
|
||||
params = { k.strip():params[k].strip() for k in params if k.lower() not in ['hashes', 'lora', 'embeddings', 'prompt', 'negative prompt']} # remove some keys
|
||||
if len(list(params)) == 0:
|
||||
first_param = None
|
||||
else:
|
||||
try:
|
||||
first_param, first_param_idx = next((s, i) for i, s in enumerate(params) if any(x in s.lower() for x in basic_params))
|
||||
except Exception:
|
||||
first_param, first_param_idx = next(iter(params)), 0
|
||||
if first_param_idx > 0:
|
||||
for _i in range(first_param_idx):
|
||||
params.pop(next(iter(params)))
|
||||
params_idx = sanitized.find(f'{first_param}:') if first_param else -1
|
||||
negative_idx = infotext.find("Negative prompt:")
|
||||
|
||||
prompt = infotext[:params_idx] if negative_idx == -1 else infotext[:negative_idx] # prompt can be with or without negative prompt
|
||||
negative = infotext[negative_idx:params_idx] if negative_idx >= 0 else ''
|
||||
|
||||
for k, v in params.copy().items(): # avoid dict-has-changed
|
||||
if len(v) > 0 and v[0] == '"' and v[-1] == '"':
|
||||
v = unquote(v)
|
||||
m = re_size.match(v)
|
||||
if v.replace('.', '', 1).isdigit():
|
||||
params[k] = float(v) if '.' in v else int(v)
|
||||
elif v == "True":
|
||||
params[k] = True
|
||||
elif v == "False":
|
||||
params[k] = False
|
||||
elif m is not None:
|
||||
params[f"{k}-1"] = int(m.group(1))
|
||||
params[f"{k}-2"] = int(m.group(2))
|
||||
elif k == 'VAE' and v == 'TAESD':
|
||||
params["Full quality"] = False
|
||||
else:
|
||||
params[k] = v
|
||||
params["Prompt"] = prompt.replace('Prompt:', '').strip()
|
||||
params["Negative prompt"] = negative.replace('Negative prompt:', '').strip()
|
||||
return params
|
||||
|
||||
|
||||
class Exif: # pylint: disable=single-string-used-for-slots
|
||||
__slots__ = ('__dict__') # pylint: disable=superfluous-parens
|
||||
@@ -132,7 +77,7 @@ class Exif: # pylint: disable=single-string-used-for-slots
|
||||
|
||||
def parse(self):
|
||||
x = self.exif.pop('parameters', None) or self.exif.pop('UserComment', None)
|
||||
res = parse_generation_parameters(x)
|
||||
res = infotext.parse(x)
|
||||
return res
|
||||
|
||||
def get_bytes(self):
|
||||
|
||||
@@ -146,7 +146,7 @@ def get_extensions_list():
|
||||
return ext_list
|
||||
|
||||
def post_pnginfo(req: models.ReqImageInfo):
|
||||
from modules import images, script_callbacks, generation_parameters_copypaste
|
||||
from modules import images, script_callbacks, infotext
|
||||
if not req.image.strip():
|
||||
return models.ResImageInfo(info="")
|
||||
image = helpers.decode_base64_to_image(req.image.strip())
|
||||
@@ -155,6 +155,6 @@ def post_pnginfo(req: models.ReqImageInfo):
|
||||
geninfo, items = images.read_info_from_image(image)
|
||||
if geninfo is None:
|
||||
geninfo = ""
|
||||
params = generation_parameters_copypaste.parse_generation_parameters(geninfo)
|
||||
params = infotext.parse(geninfo)
|
||||
script_callbacks.infotext_pasted_callback(geninfo, params)
|
||||
return models.ResImageInfo(info=geninfo, items=items, parameters=params)
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import base64
|
||||
import io
|
||||
import os
|
||||
import re
|
||||
import json
|
||||
from PIL import Image
|
||||
import gradio as gr
|
||||
from modules.paths import data_path
|
||||
from modules import shared, gr_tempdir, script_callbacks, images
|
||||
from modules.infotext import parse, mapping, quote, unquote # pylint: disable=unused-import
|
||||
|
||||
|
||||
type_of_gr_update = type(gr.update())
|
||||
@@ -14,7 +13,8 @@ paste_fields = {}
|
||||
registered_param_bindings = []
|
||||
debug = shared.log.trace if os.environ.get('SD_PASTE_DEBUG', None) is not None else lambda *args, **kwargs: None
|
||||
debug('Trace: PASTE')
|
||||
|
||||
parse_generation_parameters = parse # compatibility
|
||||
infotext_to_setting_name_mapping = mapping # compatibility
|
||||
|
||||
class ParamBinding:
|
||||
def __init__(self, paste_button, tabname, source_text_component=None, source_image_component=None, source_tabname=None, override_settings_component=None, paste_field_names=None):
|
||||
@@ -32,21 +32,6 @@ def reset():
|
||||
paste_fields.clear()
|
||||
|
||||
|
||||
def quote(text):
|
||||
if ',' not in str(text) and '\n' not in str(text) and ':' not in str(text):
|
||||
return text
|
||||
return json.dumps(text, ensure_ascii=False)
|
||||
|
||||
|
||||
def unquote(text):
|
||||
if len(text) == 0 or text[0] != '"' or text[-1] != '"':
|
||||
return text
|
||||
try:
|
||||
return json.loads(text)
|
||||
except Exception:
|
||||
return text
|
||||
|
||||
|
||||
def image_from_url_text(filedata):
|
||||
if filedata is None:
|
||||
return None
|
||||
@@ -187,124 +172,13 @@ def send_image_and_dimensions(x):
|
||||
return img, w, h
|
||||
|
||||
|
||||
def parse_generation_parameters(infotext, no_prompt=False):
|
||||
if not isinstance(infotext, str):
|
||||
return {}
|
||||
debug(f'Parse infotext: {infotext}')
|
||||
re_param = re.compile(r'\s*([\w ]+):\s*("(?:\\"[^,]|\\"|\\|[^\"])+"|[^,]*)(?:,|$)') # multi-word: value
|
||||
re_size = re.compile(r"^(\d+)x(\d+)$") # int x int
|
||||
basic_params = ['steps:', 'seed:', 'width:', 'height:', 'sampler:', 'size:', 'cfg scale:'] # first param is one of those
|
||||
|
||||
infotext = infotext.replace('prompt:', 'Prompt:').replace('negative prompt:', 'Negative prompt:').replace('Negative Prompt', 'Negative prompt') # cleanup everything in brackets so re_params can work
|
||||
infotext = infotext.replace(' Steps: ', ', Steps: ').replace('\nSteps: ', ', Steps: ') # fix cases where there is no delimiter between prompt and steps
|
||||
sanitized = infotext
|
||||
sanitized = re.sub(r'<[^>]*>', lambda match: ' ' * len(match.group()), sanitized)
|
||||
sanitized = re.sub(r'\([^)]*\)', lambda match: ' ' * len(match.group()), sanitized)
|
||||
sanitized = re.sub(r'\{[^}]*\}', lambda match: ' ' * len(match.group()), sanitized)
|
||||
|
||||
params = dict(re_param.findall(sanitized))
|
||||
debug(f"Parse params: {params}")
|
||||
params = { k.strip():params[k].strip() for k in params if k.lower() not in ['hashes', 'lora', 'embeddings', 'prompt', 'negative prompt']} # remove some keys
|
||||
if len(list(params)) == 0:
|
||||
first_param = None
|
||||
else:
|
||||
try:
|
||||
first_param, first_param_idx = next((s, i) for i, s in enumerate(params) if any(x in s.lower() for x in basic_params))
|
||||
except Exception:
|
||||
first_param, first_param_idx = next(iter(params)), 0
|
||||
if first_param_idx > 0:
|
||||
for _i in range(first_param_idx):
|
||||
params.pop(next(iter(params)))
|
||||
params_idx = sanitized.find(f'{first_param}:') if first_param else -1
|
||||
negative_idx = infotext.find("Negative prompt:")
|
||||
if 'Steps:' in sanitized:
|
||||
params_idx = max(params_idx, sanitized.find('Steps:'))
|
||||
|
||||
if negative_idx == -1: # prompt can be without negative prompt
|
||||
prompt = infotext[:params_idx] if params_idx > 0 else infotext
|
||||
else:
|
||||
prompt = infotext[:negative_idx]
|
||||
if prompt.startswith('Steps: '):
|
||||
prompt = ''
|
||||
if negative_idx >= 0:
|
||||
negative = infotext[negative_idx:params_idx] if params_idx > 0 else infotext[negative_idx:]
|
||||
else:
|
||||
negative = ''
|
||||
|
||||
for k, v in params.copy().items(): # avoid dict-has-changed
|
||||
if len(v) > 0 and v[0] == '"' and v[-1] == '"':
|
||||
v = unquote(v)
|
||||
m = re_size.match(v)
|
||||
if v.replace('.', '', 1).isdigit():
|
||||
params[k] = float(v) if '.' in v else int(v)
|
||||
elif v == "True":
|
||||
params[k] = True
|
||||
elif v == "False":
|
||||
params[k] = False
|
||||
elif m is not None:
|
||||
params[f"{k}-1"] = int(m.group(1))
|
||||
params[f"{k}-2"] = int(m.group(2))
|
||||
elif k == 'VAE' and v == 'TAESD':
|
||||
params["Full quality"] = False
|
||||
else:
|
||||
params[k] = v
|
||||
if not no_prompt:
|
||||
params["Prompt"] = prompt.replace('Prompt:', '').strip(' ,\n')
|
||||
params["Negative prompt"] = negative.replace('Negative prompt:', '').strip(' ,\n')
|
||||
debug(f"Parse: {params}")
|
||||
return params
|
||||
|
||||
|
||||
settings_map = {}
|
||||
|
||||
|
||||
infotext_to_setting_name_mapping = [
|
||||
('Backend', 'sd_backend'),
|
||||
('Model hash', 'sd_model_checkpoint'),
|
||||
('Refiner', 'sd_model_refiner'),
|
||||
('VAE', 'sd_vae'),
|
||||
('Parser', 'prompt_attention'),
|
||||
('Color correction', 'img2img_color_correction'),
|
||||
# Samplers
|
||||
('Sampler Eta', 'scheduler_eta'),
|
||||
('Sampler ENSD', 'eta_noise_seed_delta'),
|
||||
('Sampler order', 'schedulers_solver_order'),
|
||||
# Samplers diffusers
|
||||
('Sampler beta schedule', 'schedulers_beta_schedule'),
|
||||
('Sampler beta start', 'schedulers_beta_start'),
|
||||
('Sampler beta end', 'schedulers_beta_end'),
|
||||
('Sampler DPM solver', 'schedulers_dpm_solver'),
|
||||
# Samplers original
|
||||
('Sampler brownian', 'schedulers_brownian_noise'),
|
||||
('Sampler discard', 'schedulers_discard_penultimate'),
|
||||
('Sampler dyn threshold', 'schedulers_use_thresholding'),
|
||||
('Sampler karras', 'schedulers_use_karras'),
|
||||
('Sampler low order', 'schedulers_use_loworder'),
|
||||
('Sampler quantization', 'enable_quantization'),
|
||||
('Sampler sigma', 'schedulers_sigma'),
|
||||
('Sampler sigma min', 's_min'),
|
||||
('Sampler sigma max', 's_max'),
|
||||
('Sampler sigma churn', 's_churn'),
|
||||
('Sampler sigma uncond', 's_min_uncond'),
|
||||
('Sampler sigma noise', 's_noise'),
|
||||
('Sampler sigma tmin', 's_tmin'),
|
||||
('Sampler ENSM', 'initial_noise_multiplier'), # img2img only
|
||||
('UniPC skip type', 'uni_pc_skip_type'),
|
||||
('UniPC variant', 'uni_pc_variant'),
|
||||
# Token Merging
|
||||
('Mask weight', 'inpainting_mask_weight'),
|
||||
('ToMe', 'tome_ratio'),
|
||||
('ToDo', 'todo_ratio'),
|
||||
]
|
||||
|
||||
|
||||
def create_override_settings_dict(text_pairs):
|
||||
res = {}
|
||||
params = {}
|
||||
for pair in text_pairs:
|
||||
k, v = pair.split(":", maxsplit=1)
|
||||
params[k] = v.strip()
|
||||
for param_name, setting_name in infotext_to_setting_name_mapping:
|
||||
for param_name, setting_name in mapping:
|
||||
value = params.get(param_name, None)
|
||||
if value is None:
|
||||
continue
|
||||
@@ -325,7 +199,7 @@ def connect_paste(button, local_paste_fields, input_comp, override_settings_comp
|
||||
prompt = ''
|
||||
else:
|
||||
shared.log.debug(f'Paste prompt: type="current" prompt="{prompt}"')
|
||||
params = parse_generation_parameters(prompt, no_prompt=False)
|
||||
params = parse(prompt)
|
||||
script_callbacks.infotext_pasted_callback(prompt, params)
|
||||
res = []
|
||||
applied = {}
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
import os
|
||||
import re
|
||||
import json
|
||||
|
||||
|
||||
debug = lambda *args, **kwargs: None # pylint: disable=unnecessary-lambda-assignment
|
||||
re_size = re.compile(r"^(\d+)x(\d+)$") # int x int
|
||||
re_param = re.compile(r'\s*([\w ]+):\s*("(?:\\"[^,]|\\"|\\|[^\"])+"|[^,]*)(?:,|$)') # multi-word: value
|
||||
|
||||
|
||||
def quote(text):
|
||||
if ',' not in str(text) and '\n' not in str(text) and ':' not in str(text):
|
||||
return text
|
||||
return json.dumps(text, ensure_ascii=False)
|
||||
|
||||
|
||||
def unquote(text):
|
||||
if len(text) == 0 or text[0] != '"' or text[-1] != '"':
|
||||
return text
|
||||
try:
|
||||
return json.loads(text)
|
||||
except Exception:
|
||||
return text
|
||||
|
||||
|
||||
def parse(infotext):
|
||||
if not isinstance(infotext, str):
|
||||
return {}
|
||||
debug(f'Raw: {infotext}')
|
||||
if 'negative prompt:' not in infotext:
|
||||
infotext = 'negative prompt: ' + infotext
|
||||
if 'Prompt:' not in infotext:
|
||||
infotext = 'prompt: ' + infotext
|
||||
|
||||
remaining = infotext
|
||||
prompt = remaining[:infotext.lower().find('negative prompt:')]
|
||||
remaining = remaining.replace(prompt, '')
|
||||
if prompt.lower().startswith('prompt: '):
|
||||
prompt = prompt[8:]
|
||||
# debug(f'Prompt: {prompt}')
|
||||
|
||||
params = ['steps:', 'seed:', 'width:', 'height:', 'sampler:', 'size:', 'cfg scale:'] # first param is one of those
|
||||
param_idx = [remaining.lower().find(p) for p in params if p in remaining]
|
||||
param_idx = min(param_idx) if len(param_idx) > 0 else 0
|
||||
negative = remaining[:param_idx] if param_idx > 0 else remaining
|
||||
remaining = remaining.replace(negative, '')
|
||||
if negative.lower().startswith('negative prompt: '):
|
||||
negative = negative[16:]
|
||||
# debug(f'Negative: {negative}')
|
||||
|
||||
params = dict(re_param.findall(remaining))
|
||||
params['Prompt'] = prompt
|
||||
params['Negative prompt'] = negative
|
||||
for key, val in params.copy().items():
|
||||
val = unquote(val).strip(" ,\n\\n")
|
||||
size = re_size.match(val)
|
||||
if val.replace('.', '', 1).isdigit():
|
||||
params[key] = float(val) if '.' in val else int(val)
|
||||
elif val == "True":
|
||||
params[key] = True
|
||||
elif val == "False":
|
||||
params[key] = False
|
||||
elif key == 'VAE' and val == 'TAESD':
|
||||
params["Full quality"] = False
|
||||
elif size is not None:
|
||||
params[f"{key}-1"] = int(size.group(1))
|
||||
params[f"{key}-2"] = int(size.group(2))
|
||||
elif isinstance(params[key], str):
|
||||
params[key] = val
|
||||
debug(f'Param parsed: type={type(params[key])} {key}={params[key]} raw="{val}"')
|
||||
|
||||
return params
|
||||
|
||||
|
||||
mapping = [
|
||||
('Backend', 'sd_backend'),
|
||||
('Model hash', 'sd_model_checkpoint'),
|
||||
('Refiner', 'sd_model_refiner'),
|
||||
('VAE', 'sd_vae'),
|
||||
('Parser', 'prompt_attention'),
|
||||
('Color correction', 'img2img_color_correction'),
|
||||
# Samplers
|
||||
('Sampler Eta', 'scheduler_eta'),
|
||||
('Sampler ENSD', 'eta_noise_seed_delta'),
|
||||
('Sampler order', 'schedulers_solver_order'),
|
||||
# Samplers diffusers
|
||||
('Sampler beta schedule', 'schedulers_beta_schedule'),
|
||||
('Sampler beta start', 'schedulers_beta_start'),
|
||||
('Sampler beta end', 'schedulers_beta_end'),
|
||||
('Sampler DPM solver', 'schedulers_dpm_solver'),
|
||||
# Samplers original
|
||||
('Sampler brownian', 'schedulers_brownian_noise'),
|
||||
('Sampler discard', 'schedulers_discard_penultimate'),
|
||||
('Sampler dyn threshold', 'schedulers_use_thresholding'),
|
||||
('Sampler karras', 'schedulers_use_karras'),
|
||||
('Sampler low order', 'schedulers_use_loworder'),
|
||||
('Sampler quantization', 'enable_quantization'),
|
||||
('Sampler sigma', 'schedulers_sigma'),
|
||||
('Sampler sigma min', 's_min'),
|
||||
('Sampler sigma max', 's_max'),
|
||||
('Sampler sigma churn', 's_churn'),
|
||||
('Sampler sigma uncond', 's_min_uncond'),
|
||||
('Sampler sigma noise', 's_noise'),
|
||||
('Sampler sigma tmin', 's_tmin'),
|
||||
('Sampler ENSM', 'initial_noise_multiplier'), # img2img only
|
||||
('UniPC skip type', 'uni_pc_skip_type'),
|
||||
('UniPC variant', 'uni_pc_variant'),
|
||||
# Token Merging
|
||||
('Mask weight', 'inpainting_mask_weight'),
|
||||
('ToMe', 'tome_ratio'),
|
||||
('ToDo', 'todo_ratio'),
|
||||
]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import logging
|
||||
log = logging.getLogger(__name__)
|
||||
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s | %(message)s')
|
||||
debug = log.info
|
||||
|
||||
import sys
|
||||
if len(sys.argv) > 1:
|
||||
if os.path.exists(sys.argv[1]):
|
||||
with open(sys.argv[1], 'r', encoding='utf8') as f:
|
||||
parse(f.read())
|
||||
else:
|
||||
parse(sys.argv[1])
|
||||
+10
-10
@@ -4,7 +4,7 @@ from typing import List
|
||||
|
||||
from PIL import Image
|
||||
|
||||
from modules import shared, images, devices, scripts, scripts_postprocessing, generation_parameters_copypaste
|
||||
from modules import shared, images, devices, scripts, scripts_postprocessing, infotext
|
||||
from modules.shared import opts
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ def run_postprocessing(extras_mode, image, image_folder: List[tempfile.NamedTemp
|
||||
image_ext = []
|
||||
outputs = []
|
||||
params = {}
|
||||
infotext = ''
|
||||
info = ''
|
||||
if extras_mode == 1:
|
||||
for img in image_folder:
|
||||
if isinstance(img, Image.Image):
|
||||
@@ -63,7 +63,7 @@ def run_postprocessing(extras_mode, image, image_folder: List[tempfile.NamedTemp
|
||||
processed_images = []
|
||||
for image, name, ext in zip(image_data, image_names, image_ext): # pylint: disable=redefined-argument-from-local
|
||||
shared.log.debug(f'Process: image={image} {args}')
|
||||
infotext = ''
|
||||
info = ''
|
||||
if shared.state.interrupted:
|
||||
shared.log.debug('Postprocess interrupted')
|
||||
break
|
||||
@@ -73,27 +73,27 @@ def run_postprocessing(extras_mode, image, image_folder: List[tempfile.NamedTemp
|
||||
pp = scripts_postprocessing.PostprocessedImage(image.convert("RGB"))
|
||||
scripts.scripts_postproc.run(pp, args)
|
||||
geninfo, items = images.read_info_from_image(image)
|
||||
params = generation_parameters_copypaste.parse_generation_parameters(geninfo)
|
||||
params = infotext.parse(geninfo)
|
||||
for k, v in items.items():
|
||||
pp.image.info[k] = v
|
||||
if 'parameters' in items:
|
||||
infotext = items['parameters'] + ', '
|
||||
infotext = infotext + ", ".join([k if k == v else f'{k}: {generation_parameters_copypaste.quote(v)}' for k, v in pp.info.items() if v is not None])
|
||||
pp.image.info["postprocessing"] = infotext
|
||||
info = items['parameters'] + ', '
|
||||
info = info + ", ".join([k if k == v else f'{k}: {info.quote(v)}' for k, v in pp.info.items() if v is not None])
|
||||
pp.image.info["postprocessing"] = info
|
||||
processed_images.append(pp.image)
|
||||
if save_output:
|
||||
if opts.use_original_name_batch and name is not None:
|
||||
forced_filename = os.path.splitext(os.path.basename(name))[0]
|
||||
images.save_image(pp.image, path=outpath, extension=ext or opts.samples_format, info=infotext, short_filename=True, no_prompt=True, grid=False, pnginfo_section_name="extras", existing_info=pp.image.info, forced_filename=forced_filename)
|
||||
images.save_image(pp.image, path=outpath, extension=ext or opts.samples_format, info=info, short_filename=True, no_prompt=True, grid=False, pnginfo_section_name="extras", existing_info=pp.image.info, forced_filename=forced_filename)
|
||||
else:
|
||||
images.save_image(pp.image, path=outpath, extension=ext or opts.samples_format, info=infotext, short_filename=True, no_prompt=True, grid=False, pnginfo_section_name="extras", existing_info=pp.image.info)
|
||||
images.save_image(pp.image, path=outpath, extension=ext or opts.samples_format, info=info, short_filename=True, no_prompt=True, grid=False, pnginfo_section_name="extras", existing_info=pp.image.info)
|
||||
if extras_mode != 2 or show_extras_results:
|
||||
outputs.append(pp.image)
|
||||
image.close()
|
||||
scripts.scripts_postproc.postprocess(processed_images, args)
|
||||
|
||||
devices.torch_gc()
|
||||
return outputs, infotext, params
|
||||
return outputs, info, params
|
||||
|
||||
|
||||
def run_extras(extras_mode, resize_mode, image, image_folder, input_dir, output_dir, show_extras_results, gfpgan_visibility, codeformer_visibility, codeformer_weight, upscaling_resize, upscaling_resize_w, upscaling_resize_h, upscaling_crop, extras_upscaler_1, extras_upscaler_2, extras_upscaler_2_visibility, upscale_first: bool, save_output: bool = True): #pylint: disable=unused-argument
|
||||
|
||||
@@ -130,8 +130,6 @@ def get_tokens(msg, prompt):
|
||||
|
||||
|
||||
def encode_prompts(pipe, p, prompts: list, negative_prompts: list, steps: int, clip_skip: typing.Optional[int] = None):
|
||||
if getattr(p, 'hidiffusion', False) is True:
|
||||
cache.clear()
|
||||
if 'StableDiffusion' not in pipe.__class__.__name__ and 'DemoFusion' not in pipe.__class__.__name__ and 'StableCascade' not in pipe.__class__.__name__:
|
||||
shared.log.warning(f"Prompt parser not supported: {pipe.__class__.__name__}")
|
||||
return
|
||||
|
||||
+3
-4
@@ -6,7 +6,7 @@ import csv
|
||||
import json
|
||||
import time
|
||||
import random
|
||||
from modules import files_cache, shared
|
||||
from modules import files_cache, shared, infotext
|
||||
|
||||
|
||||
class Style():
|
||||
@@ -132,12 +132,11 @@ def apply_styles_to_extra(p, style: Style):
|
||||
name_exclude = [
|
||||
'size',
|
||||
]
|
||||
from modules.generation_parameters_copypaste import parse_generation_parameters
|
||||
reference_style = get_reference_style()
|
||||
extra = parse_generation_parameters(reference_style) if shared.opts.extra_network_reference else {}
|
||||
extra = infotext.parse(reference_style) if shared.opts.extra_network_reference else {}
|
||||
|
||||
style_extra = apply_wildcards_to_prompt(style.extra, [style.wildcards], silent=True)
|
||||
extra.update(parse_generation_parameters(style_extra))
|
||||
extra.update(infotext.parse(style_extra))
|
||||
extra.pop('Prompt', None)
|
||||
extra.pop('Negative prompt', None)
|
||||
fields = []
|
||||
|
||||
@@ -6,7 +6,7 @@ import platform
|
||||
import subprocess
|
||||
from functools import reduce
|
||||
import gradio as gr
|
||||
from modules import call_queue, shared, prompt_parser, ui_sections, ui_symbols, ui_components, generation_parameters_copypaste, images, scripts, script_callbacks
|
||||
from modules import call_queue, shared, prompt_parser, ui_sections, ui_symbols, ui_components, generation_parameters_copypaste, images, scripts, script_callbacks, infotext
|
||||
|
||||
|
||||
folder_symbol = ui_symbols.folder
|
||||
@@ -23,8 +23,8 @@ def update_generation_info(generation_info, html_info, img_index):
|
||||
generation_info = json.loads(generation_info)
|
||||
if img_index < 0 or img_index >= len(generation_info["infotexts"]):
|
||||
return html_info, generation_info
|
||||
infotext = generation_info["infotexts"][img_index]
|
||||
html_info_formatted = infotext_to_html(infotext)
|
||||
info = generation_info["infotexts"][img_index]
|
||||
html_info_formatted = infotext_to_html(info)
|
||||
return html_info, html_info_formatted
|
||||
except Exception:
|
||||
pass
|
||||
@@ -37,7 +37,7 @@ def plaintext_to_html(text):
|
||||
|
||||
|
||||
def infotext_to_html(text):
|
||||
res = generation_parameters_copypaste.parse_generation_parameters(text)
|
||||
res = infotext.parse(text)
|
||||
prompt = res.get('Prompt', '')
|
||||
negative = res.get('Negative prompt', '')
|
||||
res.pop('Prompt', None)
|
||||
@@ -169,7 +169,7 @@ def save_files(js_data, files, html_info, index):
|
||||
if (js_data is None or len(js_data) == 0) and image is not None and image.info is not None:
|
||||
info = image.info.pop('parameters', None) or image.info.pop('UserComment', None)
|
||||
geninfo, _ = images.read_info_from_image(image)
|
||||
items = generation_parameters_copypaste.parse_generation_parameters(geninfo)
|
||||
items = infotext.parse(geninfo)
|
||||
p = PObject(items)
|
||||
fullfn, txt_fullfn = images.save_image(image, shared.opts.outdir_save, "", seed=p.all_seeds[i], prompt=p.all_prompts[i], info=info, extension=shared.opts.samples_format, grid=is_grid, p=p)
|
||||
if fullfn is None:
|
||||
|
||||
@@ -16,7 +16,7 @@ from collections import OrderedDict
|
||||
import gradio as gr
|
||||
from PIL import Image
|
||||
from starlette.responses import FileResponse, JSONResponse
|
||||
from modules import paths, shared, scripts, files_cache, errors
|
||||
from modules import paths, shared, scripts, files_cache, errors, infotext
|
||||
from modules.ui_components import ToolButton
|
||||
import modules.ui_symbols as symbols
|
||||
|
||||
@@ -877,28 +877,26 @@ def create_ui(container, button_parent, tabname, skip_indexing = False):
|
||||
return ui_refresh_click(title)
|
||||
|
||||
def ui_save_click():
|
||||
from modules import generation_parameters_copypaste
|
||||
filename = os.path.join(paths.data_path, "params.txt")
|
||||
if os.path.exists(filename):
|
||||
with open(filename, "r", encoding="utf8") as file:
|
||||
prompt = file.read()
|
||||
else:
|
||||
prompt = ''
|
||||
params = generation_parameters_copypaste.parse_generation_parameters(prompt)
|
||||
params = infotext.parse(prompt)
|
||||
res = show_details(text=None, img=None, desc=None, info=None, meta=None, parameters=None, description=None, prompt=None, negative=None, wildcards=None, params=params)
|
||||
return res
|
||||
|
||||
def ui_quicksave_click(name):
|
||||
if name is None:
|
||||
return
|
||||
from modules import generation_parameters_copypaste
|
||||
fn = os.path.join(paths.data_path, "params.txt")
|
||||
if os.path.exists(fn):
|
||||
with open(fn, "r", encoding="utf8") as file:
|
||||
prompt = file.read()
|
||||
else:
|
||||
prompt = ''
|
||||
params = generation_parameters_copypaste.parse_generation_parameters(prompt)
|
||||
params = infotext.parse(prompt)
|
||||
fn = os.path.join(shared.opts.styles_dir, os.path.splitext(name)[0] + '.json')
|
||||
prompt = params.get('Prompt', '')
|
||||
item = {
|
||||
|
||||
Reference in New Issue
Block a user