Initial commit

This commit is contained in:
Zyin055
2022-12-13 01:04:06 -06:00
commit 8c90a927c0
5 changed files with 300 additions and 0 deletions

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 Zyin055
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

19
README.md Normal file
View File

@@ -0,0 +1,19 @@
## What does this do?
This Automatic1111 extension adds a configurable dropdown to allow you to change settings in the txt2img and img2img tabs of the Web UI.
## Screenshots
The new dropdown in the image gallery
![gallery](https://i.imgur.com/bdIkhgu.jpg)
Dropdown values (configurable)
![dropdown](https://i.imgur.com/B1eMWAw.jpg)
Screenshot of config_presets.json
![config](https://i.imgur.com/iJ13uhU.jpg)
## Installation
* In your Automatic1111 Web UI, go to the Extensions tab > Install from URL > URL for extension's git repository: https://github.com/Zyin055/Config-Presets
* Click the Install button

59
config.json Normal file
View File

@@ -0,0 +1,59 @@
{
"Default" : {
},
"Low quality ------ 512x512, steps: 10, batch size: 8, DPM++ 2M Karras" : {
"steps": 10,
"sampler_index": "DPM++ 2M Karras",
"width": 512,
"height": 512,
"enable_hr": False,
"denoising_strength": 0.7,
"batch_count": 1,
"batch_size": 8,
"cfg_scale": 7,
},
"Medium quality - 512x512, steps: 20, batch size: 8, DPM++ 2S a Karras" : {
"steps": 20,
"sampler_index": "DPM++ 2S a Karras",
"width": 512,
"height": 512,
"enable_hr": False,
"denoising_strength": 0.7,
"batch_count": 1,
"batch_size": 8,
"cfg_scale": 7,
},
"High quality ------ 512x512, steps: 40, batch size: 8, DPM++ 2S a Karras" : {
"steps": 40,
"sampler_index": "DPM++ 2S a Karras",
"width": 512,
"height": 512,
"enable_hr": False,
"denoising_strength": 0.7,
"batch_count": 1,
"batch_size": 8,
"cfg_scale": 7,
},
"High res -------- 1024x1024, steps: 30, batch size: 1, DPM++ 2M Karras, Highres fix, Denoising: 0.4" : {
"steps": 30,
"sampler_index": "DPM++ 2M Karras",
"width": 1024,
"height": 1024,
"enable_hr": True,
"denoising_strength": 0.4,
"batch_count": 1,
"batch_size": 1,
"cfg_scale": 7,
},
"Wallpaper ----- 1920x1088, steps: 30, batch size: 1, DPM++ 2M Karras, Highres fix, Denoising: 0.3" : {
"steps": 30,
"sampler_index": "DPM++ 2M Karras",
"width": 1920,
"height": 1088,
"enable_hr": True,
"denoising_strength": 0.3,
"batch_count": 1,
"batch_size": 1,
"cfg_scale": 7,
},
}

View File

@@ -0,0 +1,23 @@
//add tooltip by piggybacking off of javascript/hints.js
//titles["Edit..."] = "[Config Presets] open config.json"
//or do it our more precise way
onUiUpdate(function() {
//set tooltips
gradioApp().querySelectorAll("#config_presets_open_config_file_button").forEach(el => el.setAttribute("title", "[Config Presets] open config.json, requires Gradio restart after editing"))
})
//change() event called by config_preset_dropdown in config_presets.py
function config_preset_dropdown_change() {
//when Python changes the enable_hr checkbox in config_preset_dropdown_change() it doesn't fire off the change() JS event, so do this manually
//there is a race condition between the checkbox being checked in Python, and us firing its change event in JavaScript, so wait a bit before firing the event
setTimeout(function() {
//the "Highres. fix" checkbox has no easy way to identify it, so use its tooltip attribute on the neighboring element
let highresCheckbox = gradioApp().querySelector("label > span[title='Use a two step process to partially create an image at smaller resolution, upscale, and then improve details in it without changing composition'").parentElement.firstChild
let e = document.createEvent("HTMLEvents")
e.initEvent("change", true, false)
highresCheckbox.dispatchEvent(e)
}, 200) //50ms is too fast
}

178
scripts/config_presets.py Normal file
View File

@@ -0,0 +1,178 @@
# Config Presets script for Automatic1111
# Last updated: 12/13/2022
# Author: Zyin
import modules.scripts
import gradio as gr
import ast
import os
import platform
import subprocess as sp
ui_steps = None # "steps" component in ui.py:635, label='Sampling Steps'
ui_sampler_index = None # "steps" component in ui.py:636, label='Sampling method'
ui_width = None # "width" component in ui.py:639, label='Width'
ui_height = None # "height" component in ui.py:640, label='Height'
ui_enable_hr = None # "enable_hr" component in ui.py:645,label='Highres. fix'
ui_denoising_strength = None # "denoising_strength" component in ui.py:650, label='Denoising strength'
ui_batch_count = None # "batch_count" component in ui.py:653, label='Batch count'
ui_batch_size = None # "batch_size" component in ui.py:654, label='Batch size'
ui_cfg_scale = None # "cfg_scale" component in ui.py:656, label='CFG Scale'
#print(f"global modules.scripts.basedir()={modules.scripts.basedir()}")
basedir = modules.scripts.basedir() #C:\Stable Diffusion\extensions\Config-Presets
# Load config from file
config_presets = {}
try:
with open(f"{basedir}/config.json") as file:
config_presets = ast.literal_eval(file.read())
#print("Config Presets: loaded config file 'config.json'")
except FileNotFoundError:
print(f"[ERROR] Config Presets: Could not find config file at '{basedir}/config.json'. The Config Presets dropdown will not work!")
class Script(modules.scripts.Script):
def title(self):
return "Config Presets"
def show(self, is_img2img):
#return True
return modules.scripts.AlwaysVisible # hide this script in the Scripts dropdown
def after_component(self, component, **kwargs):
global ui_steps
global ui_sampler_index
global ui_width
global ui_height
global ui_enable_hr
global ui_denoising_strength
global ui_batch_count
global ui_batch_size
global ui_cfg_scale
# Since we can't get direct access to component variables in ui.py, we detect and save an old reference to them here.
if isinstance(component, gr.components.Slider):
if component.label == "Sampling Steps":
ui_steps = component
#print(f"found ui_steps component: {type(component)}")
elif component.label == "Width":
ui_width = component
#print(f"found ui_width component: {type(component)}")
elif component.label == "Height":
ui_height = component
#print(f"found ui_height component: {type(component)}")
elif component.label == "Denoising strength":
ui_denoising_strength = component
#print(f"found ui_denoising_strength component: {type(component)}")
elif component.label == "Batch count":
ui_batch_count = component
#print(f"found ui_batch_count component: {type(component)}")
elif component.label == "Batch size":
ui_batch_size = component
#print(f"found ui_batch_size component: {type(component)}")
elif component.label == "CFG Scale":
ui_cfg_scale = component
#print(f"found ui_cfg_scale component: {type(component)}")
elif isinstance(component, gr.components.Checkbox):
if component.label == "Highres. fix":
ui_enable_hr = component
#print(f"found ui_enable_hr component: {type(component)}")
elif isinstance(component, gr.components.Radio):
if component.label == "Sampling method":
ui_sampler_index = component
#print(f"found ui_sampler_index component: {type(component)}")
#if component.elem_id == "script_list": #bottom of the script dropdown
#if component.elem_id == "txt2img_style2_index": #doesn't work, need to be added after all the components we edit are loaded
if component.elem_id == "open_folder": #bottom of the image gallery
global config_presets
preset_values = []
for k in config_presets:
preset_values.append(k)
#print(f"Config Presets: added \"{k}\"")
with gr.Column(scale=9):
def config_preset_dropdown_change(dropdown_value):
global config_presets
config_preset = config_presets[dropdown_value]
print(f"Config Presets: changed to {dropdown_value}")
# return config_dict["steps"] if "steps" in config_dict else 20,\
# config_dict["sampler_index"] if "sampler_index" in config_dict else "Euler a",\
# config_dict["width"] if "width" in config_dict else 512,\
# config_dict["height"] if "height" in config_dict else 512,\
# config_dict["enable_hr"] if "enable_hr" in config_dict else False,\
# config_dict["denoising_strength"] if "denoising_strength" in config_dict else 0.7,\
# config_dict["batch_count"] if "batch_count" in config_dict else 1,\
# config_dict["batch_size"] if "batch_size" in config_dict else 1,\
# config_dict["cfg_scale"] if "cfg_scale" in config_dict else 7,\
# I couldn't find a way to get up-to-date values from the UI elements, so instead we just use the default values if something is missing from the config file
return config_preset["steps"] if "steps" in config_preset else ui_steps.value,\
config_preset["sampler_index"] if "sampler_index" in config_preset else ui_sampler_index.value,\
config_preset["width"] if "width" in config_preset else ui_width.value,\
config_preset["height"] if "height" in config_preset else ui_height.value,\
config_preset["enable_hr"] if "enable_hr" in config_preset else ui_enable_hr.value,\
config_preset["denoising_strength"] if "denoising_strength" in config_preset else ui_denoising_strength.value,\
config_preset["batch_count"] if "batch_count" in config_preset else ui_batch_count.value,\
config_preset["batch_size"] if "batch_size" in config_preset else ui_batch_size.value,\
config_preset["cfg_scale"] if "cfg_scale" in config_preset else ui_cfg_scale.value,\
config_preset_dropdown = gr.Dropdown(
label="Config Presets",
choices=preset_values,
elem_id="config_preset_dropdown",
)
config_preset_dropdown.style(container=False) #set to True to give it a white box to sit in
config_preset_dropdown.change(
fn=config_preset_dropdown_change,
show_progress=False,
inputs=[config_preset_dropdown],
outputs=[ui_steps, ui_sampler_index, ui_width, ui_height, ui_enable_hr, ui_denoising_strength, ui_batch_count, ui_batch_size, ui_cfg_scale],
)
config_preset_dropdown.change(
fn=None,
inputs=[],
outputs=[],
_js="function() { config_preset_dropdown_change() }",
)
with gr.Column(scale=1, min_width=30):
def open_file(f):
path = os.path.normpath(f)
if not os.path.exists(path):
print(f'Config Presets: The file at "{path}" does not exist.')
return
# copied from ui.py:538
if platform.system() == "Windows":
os.startfile(path)
elif platform.system() == "Darwin":
sp.Popen(["open", path])
else:
sp.Popen(["xdg-open", path])
#print(f"modules.scripts.basedir()={modules.scripts.basedir()}") # base SD folder
open_config_file_button = gr.Button( #tooltip is set in javascript/config_presets.js
value="Edit...",
elem_id="config_presets_open_config_file_button"
)
open_config_file_button.click(
fn=lambda: open_file(f"{basedir}\\config.json"),
inputs=[],
outputs=[],
)
def ui(self, is_img2img):
pass
def run(self, p, *args):
pass