move seed, variation seed and variation seed strength to a single row, dump resize seed from UI

add a way for scripts to register a callback for before/after just a single component's creation
This commit is contained in:
AUTOMATIC1111 2023-08-12 17:46:13 +03:00
parent 6aa26a26d5
commit f0b72b8121
7 changed files with 191 additions and 126 deletions

View File

@ -116,7 +116,7 @@ def process_batch(p, input_dir, output_dir, inpaint_mask_dir, args, to_scale=Fal
process_images(p) process_images(p)
def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_styles, init_img, sketch, init_img_with_mask, inpaint_color_sketch, inpaint_color_sketch_orig, init_img_inpaint, init_mask_inpaint, steps: int, sampler_name: str, mask_blur: int, mask_alpha: float, inpainting_fill: int, n_iter: int, batch_size: int, cfg_scale: float, image_cfg_scale: float, denoising_strength: float, seed: int, subseed: int, subseed_strength: float, seed_resize_from_h: int, seed_resize_from_w: int, seed_enable_extras: bool, selected_scale_tab: int, height: int, width: int, scale_by: float, resize_mode: int, inpaint_full_res: bool, inpaint_full_res_padding: int, inpainting_mask_invert: int, img2img_batch_input_dir: str, img2img_batch_output_dir: str, img2img_batch_inpaint_mask_dir: str, override_settings_texts, img2img_batch_use_png_info: bool, img2img_batch_png_info_props: list, img2img_batch_png_info_dir: str, request: gr.Request, *args): def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_styles, init_img, sketch, init_img_with_mask, inpaint_color_sketch, inpaint_color_sketch_orig, init_img_inpaint, init_mask_inpaint, steps: int, sampler_name: str, mask_blur: int, mask_alpha: float, inpainting_fill: int, n_iter: int, batch_size: int, cfg_scale: float, image_cfg_scale: float, denoising_strength: float, selected_scale_tab: int, height: int, width: int, scale_by: float, resize_mode: int, inpaint_full_res: bool, inpaint_full_res_padding: int, inpainting_mask_invert: int, img2img_batch_input_dir: str, img2img_batch_output_dir: str, img2img_batch_inpaint_mask_dir: str, override_settings_texts, img2img_batch_use_png_info: bool, img2img_batch_png_info_props: list, img2img_batch_png_info_dir: str, request: gr.Request, *args):
override_settings = create_override_settings_dict(override_settings_texts) override_settings = create_override_settings_dict(override_settings_texts)
is_batch = mode == 5 is_batch = mode == 5
@ -166,12 +166,6 @@ def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_s
prompt=prompt, prompt=prompt,
negative_prompt=negative_prompt, negative_prompt=negative_prompt,
styles=prompt_styles, styles=prompt_styles,
seed=seed,
subseed=subseed,
subseed_strength=subseed_strength,
seed_resize_from_h=seed_resize_from_h,
seed_resize_from_w=seed_resize_from_w,
seed_enable_extras=seed_enable_extras,
sampler_name=sampler_name, sampler_name=sampler_name,
batch_size=batch_size, batch_size=batch_size,
n_iter=n_iter, n_iter=n_iter,

View File

@ -0,0 +1,95 @@
import json
import gradio as gr
from modules import scripts, ui, errors
from modules.shared import cmd_opts
from modules.ui_components import ToolButton
class ScriptSeed(scripts.ScriptBuiltin):
section = "seed"
create_group = False
def __init__(self):
self.seed = None
self.reuse_seed = None
self.reuse_subseed = None
def title(self):
return "Seed"
def show(self, is_img2img):
return scripts.AlwaysVisible
def ui(self, is_img2img):
with gr.Row(elem_id=self.elem_id("seed_row")):
if cmd_opts.use_textbox_seed:
self.seed = gr.Textbox(label='Seed', value="", elem_id=self.elem_id("seed"))
else:
self.seed = gr.Number(label='Seed', value=-1, elem_id=self.elem_id("seed"), precision=0)
random_seed = ToolButton(ui.random_symbol, elem_id=self.elem_id("random_seed"), label='Random seed')
reuse_seed = ToolButton(ui.reuse_symbol, elem_id=self.elem_id("reuse_seed"), label='Reuse seed')
subseed = gr.Number(label='Variation seed', value=-1, elem_id=self.elem_id("subseed"), precision=0)
random_subseed = ToolButton(ui.random_symbol, elem_id=self.elem_id("random_subseed"))
reuse_subseed = ToolButton(ui.reuse_symbol, elem_id=self.elem_id("reuse_subseed"))
subseed_strength = gr.Slider(label='Variation strength', value=0.0, minimum=0, maximum=1, step=0.01, elem_id=self.elem_id("subseed_strength"))
random_seed.click(fn=None, _js="function(){setRandomSeed('" + self.elem_id("seed") + "')}", show_progress=False, inputs=[], outputs=[])
random_subseed.click(fn=None, _js="function(){setRandomSeed('" + self.elem_id("subseed") + "')}", show_progress=False, inputs=[], outputs=[])
self.infotext_fields = [
(self.seed, "Seed"),
(subseed, "Variation seed"),
(subseed_strength, "Variation seed strength"),
]
self.on_after_component(lambda x: connect_reuse_seed(self.seed, reuse_seed, x.component, False), elem_id=f'generation_info_{self.tabname}')
self.on_after_component(lambda x: connect_reuse_seed(self.seed, reuse_subseed, x.component, True), elem_id=f'generation_info_{self.tabname}')
return self.seed, subseed, subseed_strength
def before_process(self, p, seed, subseed, subseed_strength):
p.seed = seed
if subseed_strength > 0:
p.subseed = subseed
p.subseed_strength = subseed_strength
def connect_reuse_seed(seed: gr.Number, reuse_seed: gr.Button, generation_info: gr.Textbox, is_subseed):
""" Connects a 'reuse (sub)seed' button's click event so that it copies last used
(sub)seed value from generation info the to the seed field. If copying subseed and subseed strength
was 0, i.e. no variation seed was used, it copies the normal seed value instead."""
def copy_seed(gen_info_string: str, index):
res = -1
try:
gen_info = json.loads(gen_info_string)
index -= gen_info.get('index_of_first_image', 0)
if is_subseed and gen_info.get('subseed_strength', 0) > 0:
all_subseeds = gen_info.get('all_subseeds', [-1])
res = all_subseeds[index if 0 <= index < len(all_subseeds) else 0]
else:
all_seeds = gen_info.get('all_seeds', [-1])
res = all_seeds[index if 0 <= index < len(all_seeds) else 0]
except json.decoder.JSONDecodeError:
if gen_info_string:
errors.report(f"Error parsing JSON generation info: {gen_info_string}")
return [res, gr.update()]
reuse_seed.click(
fn=copy_seed,
_js="(x, y) => [x, selected_gallery_index()]",
show_progress=False,
inputs=[generation_info, seed],
outputs=[seed, seed]
)

View File

@ -3,6 +3,7 @@ import re
import sys import sys
import inspect import inspect
from collections import namedtuple from collections import namedtuple
from dataclasses import dataclass
import gradio as gr import gradio as gr
@ -21,6 +22,11 @@ class PostprocessBatchListArgs:
self.images = images self.images = images
@dataclass
class OnComponent:
component: gr.blocks.Block
class Script: class Script:
name = None name = None
"""script's internal name derived from title""" """script's internal name derived from title"""
@ -35,6 +41,7 @@ class Script:
is_txt2img = False is_txt2img = False
is_img2img = False is_img2img = False
tabname = None
group = None group = None
"""A gr.Group component that has all script's UI inside it.""" """A gr.Group component that has all script's UI inside it."""
@ -55,6 +62,12 @@ class Script:
api_info = None api_info = None
"""Generated value of type modules.api.models.ScriptInfo with information about the script for API""" """Generated value of type modules.api.models.ScriptInfo with information about the script for API"""
on_before_component_elem_id = []
"""list of callbacks to be called before a component with an elem_id is created"""
on_after_component_elem_id = []
"""list of callbacks to be called after a component with an elem_id is created"""
def title(self): def title(self):
"""this function should return the title of the script. This is what will be displayed in the dropdown menu.""" """this function should return the title of the script. This is what will be displayed in the dropdown menu."""
@ -215,6 +228,24 @@ class Script:
pass pass
def on_before_component(self, callback, *, elem_id):
"""
Calls callback before a component is created. The callback function is called with a single argument of type OnComponent.
This function is an alternative to before_component in that it also cllows to run before a component is created, but
it doesn't require to be called for every created component - just for the one you need.
"""
self.on_before_component_elem_id.append((elem_id, callback))
def on_after_component(self, callback, *, elem_id):
"""
Calls callback after a component is created. The callback function is called with a single argument of type OnComponent.
"""
self.on_after_component_elem_id.append((elem_id, callback))
def describe(self): def describe(self):
"""unused""" """unused"""
return "" return ""
@ -236,6 +267,17 @@ class Script:
pass pass
class ScriptBuiltin(Script):
def elem_id(self, item_id):
"""helper function to generate id for a HTML element, constructs final id out of tab and user-supplied item_id"""
need_tabname = self.show(True) == self.show(False)
tabname = ('img2img' if self.is_img2img else 'txt2txt') + "_" if need_tabname else ""
return f'{tabname}{item_id}'
current_basedir = paths.script_path current_basedir = paths.script_path
@ -354,10 +396,17 @@ class ScriptRunner:
self.selectable_scripts = [] self.selectable_scripts = []
self.alwayson_scripts = [] self.alwayson_scripts = []
self.titles = [] self.titles = []
self.title_map = {}
self.infotext_fields = [] self.infotext_fields = []
self.paste_field_names = [] self.paste_field_names = []
self.inputs = [None] self.inputs = [None]
self.on_before_component_elem_id = {}
"""dict of callbacks to be called before an element is created; key=elem_id, value=list of callbacks"""
self.on_after_component_elem_id = {}
"""dict of callbacks to be called after an element is created; key=elem_id, value=list of callbacks"""
def initialize_scripts(self, is_img2img): def initialize_scripts(self, is_img2img):
from modules import scripts_auto_postprocessing from modules import scripts_auto_postprocessing
@ -372,6 +421,7 @@ class ScriptRunner:
script.filename = script_data.path script.filename = script_data.path
script.is_txt2img = not is_img2img script.is_txt2img = not is_img2img
script.is_img2img = is_img2img script.is_img2img = is_img2img
script.tabname = "img2img" if is_img2img else "txt2img"
visibility = script.show(script.is_img2img) visibility = script.show(script.is_img2img)
@ -446,6 +496,8 @@ class ScriptRunner:
self.inputs = [None] self.inputs = [None]
def setup_ui(self): def setup_ui(self):
all_titles = [wrap_call(script.title, script.filename, "title") or script.filename for script in self.scripts]
self.title_map = {title.lower(): script for title, script in zip(all_titles, self.scripts)}
self.titles = [wrap_call(script.title, script.filename, "title") or f"{script.filename} [error]" for script in self.selectable_scripts] self.titles = [wrap_call(script.title, script.filename, "title") or f"{script.filename} [error]" for script in self.selectable_scripts]
self.setup_ui_for_section(None) self.setup_ui_for_section(None)
@ -492,6 +544,13 @@ class ScriptRunner:
self.infotext_fields.append((dropdown, lambda x: gr.update(value=x.get('Script', 'None')))) self.infotext_fields.append((dropdown, lambda x: gr.update(value=x.get('Script', 'None'))))
self.infotext_fields.extend([(script.group, onload_script_visibility) for script in self.selectable_scripts]) self.infotext_fields.extend([(script.group, onload_script_visibility) for script in self.selectable_scripts])
for script in self.scripts:
for elem_id, callback in script.on_before_component_elem_id:
self.on_before_component_elem_id.get(elem_id, []).append((callback, script))
for elem_id, callback in script.on_after_component_elem_id:
self.on_after_component_elem_id.get(elem_id, []).append((callback, script))
return self.inputs return self.inputs
def run(self, p, *args): def run(self, p, *args):
@ -585,6 +644,13 @@ class ScriptRunner:
errors.report(f"Error running postprocess_image: {script.filename}", exc_info=True) errors.report(f"Error running postprocess_image: {script.filename}", exc_info=True)
def before_component(self, component, **kwargs): def before_component(self, component, **kwargs):
for callbacks in self.on_before_component_elem_id.get(kwargs.get("elem_id"), []):
for callback, script in callbacks:
try:
callback(OnComponent(component=component))
except Exception:
errors.report(f"Error running on_before_component: {script.filename}", exc_info=True)
for script in self.scripts: for script in self.scripts:
try: try:
script.before_component(component, **kwargs) script.before_component(component, **kwargs)
@ -592,12 +658,22 @@ class ScriptRunner:
errors.report(f"Error running before_component: {script.filename}", exc_info=True) errors.report(f"Error running before_component: {script.filename}", exc_info=True)
def after_component(self, component, **kwargs): def after_component(self, component, **kwargs):
for callbacks in self.on_after_component_elem_id.get(component.elem_id, []):
for callback, script in callbacks:
try:
callback(OnComponent(component=component))
except Exception:
errors.report(f"Error running on_after_component: {script.filename}", exc_info=True)
for script in self.scripts: for script in self.scripts:
try: try:
script.after_component(component, **kwargs) script.after_component(component, **kwargs)
except Exception: except Exception:
errors.report(f"Error running after_component: {script.filename}", exc_info=True) errors.report(f"Error running after_component: {script.filename}", exc_info=True)
def script(self, title):
return self.title_map.get(title.lower())
def reload_sources(self, cache): def reload_sources(self, cache):
for si, script in list(enumerate(self.scripts)): for si, script in list(enumerate(self.scripts)):
args_from = script.args_from args_from = script.args_from
@ -616,7 +692,6 @@ class ScriptRunner:
self.scripts[si].args_from = args_from self.scripts[si].args_from = args_from
self.scripts[si].args_to = args_to self.scripts[si].args_to = args_to
def before_hr(self, p): def before_hr(self, p):
for script in self.alwayson_scripts: for script in self.alwayson_scripts:
try: try:

View File

@ -73,6 +73,7 @@ ui_reorder_categories_builtin_items = [
"checkboxes", "checkboxes",
"dimensions", "dimensions",
"cfg", "cfg",
"denoising",
"seed", "seed",
"batch", "batch",
"override_settings", "override_settings",

View File

@ -9,7 +9,7 @@ from modules.ui import plaintext_to_html
import gradio as gr import gradio as gr
def txt2img(id_task: str, prompt: str, negative_prompt: str, prompt_styles, steps: int, sampler_name: str, n_iter: int, batch_size: int, cfg_scale: float, seed: int, subseed: int, subseed_strength: float, seed_resize_from_h: int, seed_resize_from_w: int, seed_enable_extras: bool, height: int, width: int, enable_hr: bool, denoising_strength: float, hr_scale: float, hr_upscaler: str, hr_second_pass_steps: int, hr_resize_x: int, hr_resize_y: int, hr_checkpoint_name: str, hr_sampler_name: str, hr_prompt: str, hr_negative_prompt, override_settings_texts, request: gr.Request, *args): def txt2img(id_task: str, prompt: str, negative_prompt: str, prompt_styles, steps: int, sampler_name: str, n_iter: int, batch_size: int, cfg_scale: float, height: int, width: int, enable_hr: bool, denoising_strength: float, hr_scale: float, hr_upscaler: str, hr_second_pass_steps: int, hr_resize_x: int, hr_resize_y: int, hr_checkpoint_name: str, hr_sampler_name: str, hr_prompt: str, hr_negative_prompt, override_settings_texts, request: gr.Request, *args):
override_settings = create_override_settings_dict(override_settings_texts) override_settings = create_override_settings_dict(override_settings_texts)
p = processing.StableDiffusionProcessingTxt2Img( p = processing.StableDiffusionProcessingTxt2Img(
@ -19,12 +19,6 @@ def txt2img(id_task: str, prompt: str, negative_prompt: str, prompt_styles, step
prompt=prompt, prompt=prompt,
styles=prompt_styles, styles=prompt_styles,
negative_prompt=negative_prompt, negative_prompt=negative_prompt,
seed=seed,
subseed=subseed,
subseed_strength=subseed_strength,
seed_resize_from_h=seed_resize_from_h,
seed_resize_from_w=seed_resize_from_w,
seed_enable_extras=seed_enable_extras,
sampler_name=sampler_name, sampler_name=sampler_name,
batch_size=batch_size, batch_size=batch_size,
n_iter=n_iter, n_iter=n_iter,

View File

@ -1,5 +1,4 @@
import datetime import datetime
import json
import mimetypes import mimetypes
import os import os
import sys import sys
@ -13,7 +12,7 @@ from PIL import Image, PngImagePlugin # noqa: F401
from modules.call_queue import wrap_gradio_gpu_call, wrap_queued_call, wrap_gradio_call from modules.call_queue import wrap_gradio_gpu_call, wrap_queued_call, wrap_gradio_call
from modules import gradio_extensons # noqa: F401 from modules import gradio_extensons # noqa: F401
from modules import sd_hijack, sd_models, script_callbacks, ui_extensions, deepbooru, extra_networks, ui_common, ui_postprocessing, progress, ui_loadsave, errors, shared_items, ui_settings, timer, sysinfo, ui_checkpoint_merger, ui_prompt_styles, scripts, sd_samplers, processing, ui_extra_networks from modules import sd_hijack, sd_models, script_callbacks, ui_extensions, deepbooru, extra_networks, ui_common, ui_postprocessing, progress, ui_loadsave, shared_items, ui_settings, timer, sysinfo, ui_checkpoint_merger, ui_prompt_styles, scripts, sd_samplers, processing, ui_extra_networks
from modules.ui_components import FormRow, FormGroup, ToolButton, FormHTML, InputAccordion from modules.ui_components import FormRow, FormGroup, ToolButton, FormHTML, InputAccordion
from modules.paths import script_path from modules.paths import script_path
from modules.ui_common import create_refresh_button from modules.ui_common import create_refresh_button
@ -142,45 +141,6 @@ def interrogate_deepbooru(image):
return gr.update() if prompt is None else prompt return gr.update() if prompt is None else prompt
def create_seed_inputs(target_interface):
with FormRow(elem_id=f"{target_interface}_seed_row", variant="compact"):
if cmd_opts.use_textbox_seed:
seed = gr.Textbox(label='Seed', value="", elem_id=f"{target_interface}_seed")
else:
seed = gr.Number(label='Seed', value=-1, elem_id=f"{target_interface}_seed", precision=0)
random_seed = ToolButton(random_symbol, elem_id=f"{target_interface}_random_seed", label='Random seed')
reuse_seed = ToolButton(reuse_symbol, elem_id=f"{target_interface}_reuse_seed", label='Reuse seed')
seed_checkbox = gr.Checkbox(label='Extra', elem_id=f"{target_interface}_subseed_show", value=False)
# Components to show/hide based on the 'Extra' checkbox
seed_extras = []
with FormRow(visible=False, elem_id=f"{target_interface}_subseed_row") as seed_extra_row_1:
seed_extras.append(seed_extra_row_1)
subseed = gr.Number(label='Variation seed', value=-1, elem_id=f"{target_interface}_subseed", precision=0)
random_subseed = ToolButton(random_symbol, elem_id=f"{target_interface}_random_subseed")
reuse_subseed = ToolButton(reuse_symbol, elem_id=f"{target_interface}_reuse_subseed")
subseed_strength = gr.Slider(label='Variation strength', value=0.0, minimum=0, maximum=1, step=0.01, elem_id=f"{target_interface}_subseed_strength")
with FormRow(visible=False) as seed_extra_row_2:
seed_extras.append(seed_extra_row_2)
seed_resize_from_w = gr.Slider(minimum=0, maximum=2048, step=8, label="Resize seed from width", value=0, elem_id=f"{target_interface}_seed_resize_from_w")
seed_resize_from_h = gr.Slider(minimum=0, maximum=2048, step=8, label="Resize seed from height", value=0, elem_id=f"{target_interface}_seed_resize_from_h")
random_seed.click(fn=None, _js="function(){setRandomSeed('" + target_interface + "_seed')}", show_progress=False, inputs=[], outputs=[])
random_subseed.click(fn=None, _js="function(){setRandomSeed('" + target_interface + "_subseed')}", show_progress=False, inputs=[], outputs=[])
def change_visibility(show):
return {comp: gr_show(show) for comp in seed_extras}
seed_checkbox.change(change_visibility, show_progress=False, inputs=[seed_checkbox], outputs=seed_extras)
return seed, reuse_seed, subseed, reuse_subseed, subseed_strength, seed_resize_from_h, seed_resize_from_w, seed_checkbox
def connect_clear_prompt(button): def connect_clear_prompt(button):
"""Given clear button, prompt, and token_counter objects, setup clear prompt button click event""" """Given clear button, prompt, and token_counter objects, setup clear prompt button click event"""
button.click( button.click(
@ -191,39 +151,6 @@ def connect_clear_prompt(button):
) )
def connect_reuse_seed(seed: gr.Number, reuse_seed: gr.Button, generation_info: gr.Textbox, dummy_component, is_subseed):
""" Connects a 'reuse (sub)seed' button's click event so that it copies last used
(sub)seed value from generation info the to the seed field. If copying subseed and subseed strength
was 0, i.e. no variation seed was used, it copies the normal seed value instead."""
def copy_seed(gen_info_string: str, index):
res = -1
try:
gen_info = json.loads(gen_info_string)
index -= gen_info.get('index_of_first_image', 0)
if is_subseed and gen_info.get('subseed_strength', 0) > 0:
all_subseeds = gen_info.get('all_subseeds', [-1])
res = all_subseeds[index if 0 <= index < len(all_subseeds) else 0]
else:
all_seeds = gen_info.get('all_seeds', [-1])
res = all_seeds[index if 0 <= index < len(all_seeds) else 0]
except json.decoder.JSONDecodeError:
if gen_info_string:
errors.report(f"Error parsing JSON generation info: {gen_info_string}")
return [res, gr_show(False)]
reuse_seed.click(
fn=copy_seed,
_js="(x, y) => [x, selected_gallery_index()]",
show_progress=False,
inputs=[generation_info, dummy_component],
outputs=[seed, dummy_component]
)
def update_token_counter(text, steps): def update_token_counter(text, steps):
try: try:
text, _ = extra_networks.parse_prompt(text) text, _ = extra_networks.parse_prompt(text)
@ -429,10 +356,8 @@ def create_ui():
batch_size = gr.Slider(minimum=1, maximum=8, step=1, label='Batch size', value=1, elem_id="txt2img_batch_size") batch_size = gr.Slider(minimum=1, maximum=8, step=1, label='Batch size', value=1, elem_id="txt2img_batch_size")
elif category == "cfg": elif category == "cfg":
cfg_scale = gr.Slider(minimum=1.0, maximum=30.0, step=0.5, label='CFG Scale', value=7.0, elem_id="txt2img_cfg_scale") with gr.Row():
cfg_scale = gr.Slider(minimum=1.0, maximum=30.0, step=0.5, label='CFG Scale', value=7.0, elem_id="txt2img_cfg_scale")
elif category == "seed":
seed, reuse_seed, subseed, reuse_subseed, subseed_strength, seed_resize_from_h, seed_resize_from_w, seed_checkbox = create_seed_inputs('txt2img')
elif category == "checkboxes": elif category == "checkboxes":
with FormRow(elem_classes="checkboxes-row", variant="compact"): with FormRow(elem_classes="checkboxes-row", variant="compact"):
@ -509,9 +434,6 @@ def create_ui():
txt2img_gallery, generation_info, html_info, html_log = create_output_panel("txt2img", opts.outdir_txt2img_samples) txt2img_gallery, generation_info, html_info, html_log = create_output_panel("txt2img", opts.outdir_txt2img_samples)
connect_reuse_seed(seed, reuse_seed, generation_info, dummy_component, is_subseed=False)
connect_reuse_seed(subseed, reuse_subseed, generation_info, dummy_component, is_subseed=True)
txt2img_args = dict( txt2img_args = dict(
fn=wrap_gradio_gpu_call(modules.txt2img.txt2img, extra_outputs=[None, '', '']), fn=wrap_gradio_gpu_call(modules.txt2img.txt2img, extra_outputs=[None, '', '']),
_js="submit", _js="submit",
@ -525,8 +447,6 @@ def create_ui():
batch_count, batch_count,
batch_size, batch_size,
cfg_scale, cfg_scale,
seed,
subseed, subseed_strength, seed_resize_from_h, seed_resize_from_w, seed_checkbox,
height, height,
width, width,
enable_hr, enable_hr,
@ -577,15 +497,9 @@ def create_ui():
(steps, "Steps"), (steps, "Steps"),
(sampler_name, "Sampler"), (sampler_name, "Sampler"),
(cfg_scale, "CFG scale"), (cfg_scale, "CFG scale"),
(seed, "Seed"),
(width, "Size-1"), (width, "Size-1"),
(height, "Size-2"), (height, "Size-2"),
(batch_size, "Batch size"), (batch_size, "Batch size"),
(seed_checkbox, lambda d: "Variation seed" in d or "Seed resize from-1" in d),
(subseed, "Variation seed"),
(subseed_strength, "Variation seed strength"),
(seed_resize_from_w, "Seed resize from-1"),
(seed_resize_from_h, "Seed resize from-2"),
(toprow.ui_styles.dropdown, lambda d: d["Styles array"] if isinstance(d.get("Styles array"), list) else gr.update()), (toprow.ui_styles.dropdown, lambda d: d["Styles array"] if isinstance(d.get("Styles array"), list) else gr.update()),
(denoising_strength, "Denoising strength"), (denoising_strength, "Denoising strength"),
(enable_hr, lambda d: "Denoising strength" in d and ("Hires upscale" in d or "Hires upscaler" in d or "Hires resize-1" in d)), (enable_hr, lambda d: "Denoising strength" in d and ("Hires upscale" in d or "Hires upscaler" in d or "Hires resize-1" in d)),
@ -613,7 +527,7 @@ def create_ui():
steps, steps,
sampler_name, sampler_name,
cfg_scale, cfg_scale,
seed, scripts.scripts_txt2img.script('Seed').seed,
width, width,
height, height,
] ]
@ -783,15 +697,13 @@ def create_ui():
batch_count = gr.Slider(minimum=1, step=1, label='Batch count', value=1, elem_id="img2img_batch_count") batch_count = gr.Slider(minimum=1, step=1, label='Batch count', value=1, elem_id="img2img_batch_count")
batch_size = gr.Slider(minimum=1, maximum=8, step=1, label='Batch size', value=1, elem_id="img2img_batch_size") batch_size = gr.Slider(minimum=1, maximum=8, step=1, label='Batch size', value=1, elem_id="img2img_batch_size")
elif category == "cfg": elif category == "denoising":
with FormGroup(): denoising_strength = gr.Slider(minimum=0.0, maximum=1.0, step=0.01, label='Denoising strength', value=0.75, elem_id="img2img_denoising_strength")
with FormRow():
cfg_scale = gr.Slider(minimum=1.0, maximum=30.0, step=0.5, label='CFG Scale', value=7.0, elem_id="img2img_cfg_scale")
image_cfg_scale = gr.Slider(minimum=0, maximum=3.0, step=0.05, label='Image CFG Scale', value=1.5, elem_id="img2img_image_cfg_scale", visible=False)
denoising_strength = gr.Slider(minimum=0.0, maximum=1.0, step=0.01, label='Denoising strength', value=0.75, elem_id="img2img_denoising_strength")
elif category == "seed": elif category == "cfg":
seed, reuse_seed, subseed, reuse_subseed, subseed_strength, seed_resize_from_h, seed_resize_from_w, seed_checkbox = create_seed_inputs('img2img') with gr.Row():
cfg_scale = gr.Slider(minimum=1.0, maximum=30.0, step=0.5, label='CFG Scale', value=7.0, elem_id="img2img_cfg_scale")
image_cfg_scale = gr.Slider(minimum=0, maximum=3.0, step=0.05, label='Image CFG Scale', value=1.5, elem_id="img2img_image_cfg_scale", visible=False)
elif category == "checkboxes": elif category == "checkboxes":
with FormRow(elem_classes="checkboxes-row", variant="compact"): with FormRow(elem_classes="checkboxes-row", variant="compact"):
@ -849,9 +761,6 @@ def create_ui():
img2img_gallery, generation_info, html_info, html_log = create_output_panel("img2img", opts.outdir_img2img_samples) img2img_gallery, generation_info, html_info, html_log = create_output_panel("img2img", opts.outdir_img2img_samples)
connect_reuse_seed(seed, reuse_seed, generation_info, dummy_component, is_subseed=False)
connect_reuse_seed(subseed, reuse_subseed, generation_info, dummy_component, is_subseed=True)
img2img_args = dict( img2img_args = dict(
fn=wrap_gradio_gpu_call(modules.img2img.img2img, extra_outputs=[None, '', '']), fn=wrap_gradio_gpu_call(modules.img2img.img2img, extra_outputs=[None, '', '']),
_js="submit_img2img", _js="submit_img2img",
@ -878,8 +787,6 @@ def create_ui():
cfg_scale, cfg_scale,
image_cfg_scale, image_cfg_scale,
denoising_strength, denoising_strength,
seed,
subseed, subseed_strength, seed_resize_from_h, seed_resize_from_w, seed_checkbox,
selected_scale_tab, selected_scale_tab,
height, height,
width, width,
@ -966,15 +873,9 @@ def create_ui():
(sampler_name, "Sampler"), (sampler_name, "Sampler"),
(cfg_scale, "CFG scale"), (cfg_scale, "CFG scale"),
(image_cfg_scale, "Image CFG scale"), (image_cfg_scale, "Image CFG scale"),
(seed, "Seed"),
(width, "Size-1"), (width, "Size-1"),
(height, "Size-2"), (height, "Size-2"),
(batch_size, "Batch size"), (batch_size, "Batch size"),
(seed_checkbox, lambda d: "Variation seed" in d or "Seed resize from-1" in d),
(subseed, "Variation seed"),
(subseed_strength, "Variation seed strength"),
(seed_resize_from_w, "Seed resize from-1"),
(seed_resize_from_h, "Seed resize from-2"),
(toprow.ui_styles.dropdown, lambda d: d["Styles array"] if isinstance(d.get("Styles array"), list) else gr.update()), (toprow.ui_styles.dropdown, lambda d: d["Styles array"] if isinstance(d.get("Styles array"), list) else gr.update()),
(denoising_strength, "Denoising strength"), (denoising_strength, "Denoising strength"),
(mask_blur, "Mask blur"), (mask_blur, "Mask blur"),

View File

@ -222,14 +222,18 @@ div.block.gradio-accordion {
padding: 0.1em 0.75em; padding: 0.1em 0.75em;
} }
[id$=_seed], [id$=_subseed]{
max-width: 10em;
}
[id$=_subseed_show]{ [id$=_subseed_show]{
min-width: auto !important; min-width: auto !important;
flex-grow: 0 !important; flex-grow: 0 !important;
display: flex; display: flex;
} }
[id$=_subseed_show] label{ [id$=_subseed_show] .label-wrap{
margin-bottom: 0.5em; margin: 0 0 0 0.5em;
align-self: end; align-self: end;
} }
@ -1028,5 +1032,6 @@ div.accordions{
div.accordions > div.input-accordion.input-accordion-open{ div.accordions > div.input-accordion.input-accordion-open{
flex: 1 auto; flex: 1 auto;
flex-flow: column;
} }