File size: 8,849 Bytes
bb7f1f4 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
import contextlib
import gradio as gr
from modules import scripts, shared, script_callbacks
from modules.ui_components import FormRow, FormColumn, FormGroup, ToolButton
import json
import os
import random
stylespath = ""
def get_json_content(file_path):
try:
with open(file_path, 'rt', encoding="utf-8") as file:
json_data = json.load(file)
return json_data
except Exception as e:
print(f"A Problem occurred: {str(e)}")
def read_sdxl_styles(json_data):
# Check that data is a list
if not isinstance(json_data, list):
print("Error: input data must be a list")
return None
names = []
# Iterate over each item in the data list
for item in json_data:
# Check that the item is a dictionary
if isinstance(item, dict):
# Check that 'name' is a key in the dictionary
if 'name' in item:
# Append the value of 'name' to the names list
names.append(item['name'])
names.sort()
return names
def getStyles():
global stylespath
json_path = os.path.join(scripts.basedir(), 'sdxl_styles.json')
stylespath = json_path
json_data = get_json_content(json_path)
styles = read_sdxl_styles(json_data)
return styles
def createPositive(style, positive):
json_data = get_json_content(stylespath)
try:
# Check if json_data is a list
if not isinstance(json_data, list):
raise ValueError(
"Invalid JSON data. Expected a list of templates.")
for template in json_data:
# Check if template contains 'name' and 'prompt' fields
if 'name' not in template or 'prompt' not in template:
raise ValueError(
"Invalid template. Missing 'name' or 'prompt' field.")
# Replace {prompt} in the matching template
if template['name'] == style:
positive = template['prompt'].replace(
'{prompt}', positive)
return positive
# If function hasn't returned yet, no matching template was found
raise ValueError(f"No template found with name '{style}'.")
except Exception as e:
print(f"An error occurred: {str(e)}")
def createNegative(style, negative):
json_data = get_json_content(stylespath)
try:
# Check if json_data is a list
if not isinstance(json_data, list):
raise ValueError(
"Invalid JSON data. Expected a list of templates.")
for template in json_data:
# Check if template contains 'name' and 'prompt' fields
if 'name' not in template or 'prompt' not in template:
raise ValueError(
"Invalid template. Missing 'name' or 'prompt' field.")
# Replace {prompt} in the matching template
if template['name'] == style:
json_negative_prompt = template.get('negative_prompt', "")
if negative:
negative = f"{json_negative_prompt}, {negative}" if json_negative_prompt else negative
else:
negative = json_negative_prompt
return negative
# If function hasn't returned yet, no matching template was found
raise ValueError(f"No template found with name '{style}'.")
except Exception as e:
print(f"An error occurred: {str(e)}")
class StyleSelectorXL(scripts.Script):
def __init__(self) -> None:
super().__init__()
styleNames = getStyles()
def title(self):
return "Style Selector for SDXL 1.0"
def show(self, is_img2img):
return scripts.AlwaysVisible
def ui(self, is_img2img):
enabled = getattr(shared.opts, "enable_styleselector_by_default", True)
with gr.Group():
with gr.Accordion("SDXL Styles", open=enabled):
with FormRow():
with FormColumn(min_width=160):
is_enabled = gr.Checkbox(
value=enabled, label="Enable Style Selector", info="Enable Or Disable Style Selector ")
with FormColumn(elem_id="Randomize Style"):
randomize = gr.Checkbox(
value=False, label="Randomize Style", info="This Will Override Selected Style")
with FormColumn(elem_id="Randomize For Each Iteration"):
randomizeEach = gr.Checkbox(
value=False, label="Randomize For Each Iteration", info="Every prompt in Batch Will Have Random Style")
with FormRow():
with FormColumn(min_width=160):
allstyles = gr.Checkbox(
value=False, label="Generate All Styles In Order", info="To Generate Your Prompt in All Available Styles, Its Better to set batch count to " + str(len(self.styleNames)) + " ( Style Count)")
style_ui_type = shared.opts.data.get(
"styles_ui", "radio-buttons")
if style_ui_type == "select-list":
style = gr.Dropdown(
self.styleNames, value='base', multiselect=False, label="Select Style")
else:
style = gr.Radio(
label='Style', choices=self.styleNames, value='base')
# Ignore the error if the attribute is not present
return [is_enabled, randomize, randomizeEach, allstyles, style]
def process(self, p, is_enabled, randomize, randomizeEach, allstyles, style):
if not is_enabled:
return
if randomize:
style = random.choice(self.styleNames)
batchCount = len(p.all_prompts)
if(batchCount == 1):
# for each image in batch
for i, prompt in enumerate(p.all_prompts):
positivePrompt = createPositive(style, prompt)
p.all_prompts[i] = positivePrompt
for i, prompt in enumerate(p.all_negative_prompts):
negativePrompt = createNegative(style, prompt)
p.all_negative_prompts[i] = negativePrompt
if(batchCount > 1):
styles = {}
for i, prompt in enumerate(p.all_prompts):
if(randomize):
styles[i] = random.choice(self.styleNames)
else:
styles[i] = style
if(allstyles):
styles[i] = self.styleNames[i % len(self.styleNames)]
# for each image in batch
for i, prompt in enumerate(p.all_prompts):
positivePrompt = createPositive(
styles[i] if randomizeEach or allstyles else styles[0], prompt)
p.all_prompts[i] = positivePrompt
for i, prompt in enumerate(p.all_negative_prompts):
negativePrompt = createNegative(
styles[i] if randomizeEach or allstyles else styles[0], prompt)
p.all_negative_prompts[i] = negativePrompt
p.extra_generation_params["Style Selector Enabled"] = True
p.extra_generation_params["Style Selector Randomize"] = randomize
p.extra_generation_params["Style Selector Style"] = style
def after_component(self, component, **kwargs):
# https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/7456#issuecomment-1414465888 helpfull link
# Find the text2img textbox component
if kwargs.get("elem_id") == "txt2img_prompt": # postive prompt textbox
self.boxx = component
# Find the img2img textbox component
if kwargs.get("elem_id") == "img2img_prompt": # postive prompt textbox
self.boxxIMG = component
# this code below works aswell, you can send negative prompt text box,provided you change the code a little
# switch self.boxx with self.neg_prompt_boxTXT and self.boxxIMG with self.neg_prompt_boxIMG
# if kwargs.get("elem_id") == "txt2img_neg_prompt":
#self.neg_prompt_boxTXT = component
# if kwargs.get("elem_id") == "img2img_neg_prompt":
#self.neg_prompt_boxIMG = component
def on_ui_settings():
section = ("styleselector", "Style Selector")
shared.opts.add_option("styles_ui", shared.OptionInfo(
"radio-buttons", "How should Style Names Rendered on UI", gr.Radio, {"choices": ["radio-buttons", "select-list"]}, section=section))
shared.opts.add_option(
"enable_styleselector_by_default",
shared.OptionInfo(
True,
"enable Style Selector by default",
gr.Checkbox,
section=section
)
)
script_callbacks.on_ui_settings(on_ui_settings)
|