dikdimon's picture
Upload extensions using SD-Hub extension
bb7f1f4 verified
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)