Fooocus/modules/sdxl_styles.py

117 lines
4.4 KiB
Python

import os
import re
import json
from modules.util import get_files_from_folder
# cannot use modules.config - validators causing circular imports
styles_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '../sdxl_styles/'))
wildcards_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '../wildcards/'))
wildprompts_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '../wildprompts/'))
wildcards_max_bfs_depth = 64
def normalize_key(k):
k = k.replace('-', ' ')
words = k.split(' ')
words = [w[:1].upper() + w[1:].lower() for w in words]
k = ' '.join(words)
k = k.replace('3d', '3D')
k = k.replace('Sai', 'SAI')
k = k.replace('Mre', 'MRE')
k = k.replace('(s', '(S')
return k
styles = {}
wildprompts = {}
styles_files = get_files_from_folder(styles_path, ['.json'])
wildcards_files = get_files_from_folder(wildcards_path, ['.txt'])
def GetLegalWildpromptNames():
wildprompts_files = get_files_from_folder(wildprompts_path, ['.txt'])
return [os.path.splitext(file)[0] for file in wildprompts_files]
for x in ['sdxl_styles_fooocus.json',
'sdxl_styles_sai.json',
'sdxl_styles_mre.json',
'sdxl_styles_twri.json',
'sdxl_styles_diva.json',
'sdxl_styles_marc_k3nt3l.json']:
if x in styles_files:
styles_files.remove(x)
styles_files.append(x)
for styles_file in styles_files:
try:
with open(os.path.join(styles_path, styles_file), encoding='utf-8') as f:
for entry in json.load(f):
name = normalize_key(entry['name'])
prompt = entry['prompt'] if 'prompt' in entry else ''
negative_prompt = entry['negative_prompt'] if 'negative_prompt' in entry else ''
styles[name] = (prompt, negative_prompt)
except Exception as e:
print(str(e))
print(f'Failed to load style file {styles_file}')
style_keys = list(styles.keys())
fooocus_expansion = "Fooocus V2"
legal_style_names = [fooocus_expansion] + style_keys
legal_wildcard_names = [os.path.splitext(file)[0] for file in wildcards_files]
legal_wildprompt_names = GetLegalWildpromptNames()
def apply_style(style, positive):
p, n = styles[style]
return p.replace('{prompt}', positive).splitlines(), n.splitlines()
def apply_wildcards(wildcard_text, rng, directory=wildcards_path):
for _ in range(wildcards_max_bfs_depth):
placeholders = re.findall(r'__([\w-]+)__', wildcard_text)
if len(placeholders) == 0:
return wildcard_text
print(f'[Wildcards] processing: {wildcard_text}')
for placeholder in placeholders:
try:
words = open(os.path.join(directory, f'{placeholder}.txt'), encoding='utf-8').read().splitlines()
words = [x for x in words if x != '']
assert len(words) > 0
wildcard_text = wildcard_text.replace(f'__{placeholder}__', rng.choice(words), 1)
except:
print(f'[Wildcards] Warning: {placeholder}.txt missing or empty. '
f'Using "{placeholder}" as a normal word.')
wildcard_text = wildcard_text.replace(f'__{placeholder}__', placeholder)
print(f'[Wildcards] {wildcard_text}')
print(f'[Wildcards] BFS stack overflow. Current text: {wildcard_text}')
return wildcard_text
def apply_wildprompts(wildprompt_selections, rng):
prompts = []
for wildprompt_selection in wildprompt_selections:
try:
wildprompt_text = open(os.path.join(wildprompts_path, f'{wildprompt_selection}.txt'), encoding='utf-8').read().splitlines()
wildprompt_text = [x for x in wildprompt_text if x != '']
assert len(wildprompt_text) > 0
prompts.append(rng.choice(wildprompt_text))
except:
print(f'[Wildprompts] Warning: {wildprompt_selection}.txt missing or empty. ')
return ', '.join(prompts)
def get_all_wildprompts(wildprompt_selections):
prompts = []
try:
wildprompt_text = open(os.path.join(wildprompts_path, f'{wildprompt_selections[0]}.txt'), encoding='utf-8').read().splitlines()
wildprompt_text = [x for x in wildprompt_text if x != '']
assert len(wildprompt_text) > 0
prompts.extend(wildprompt_text)
except:
print(f'[Wildprompts] Warning: {wildprompt_selections[0]}.txt missing or empty. ')
return prompts