mirror of
https://github.com/vladmandic/automatic
synced 2026-09-01 10:01:01 +02:00
17b7176e0d
A single handler bound to the AR dropdown, width and height (in the shared create_resolution_inputs and the resize section) wrote both sliders on every change. With a ratio selected it locked one axis and snapped it back on each edit, the two sliders looped, and the math ran server-side one round-trip per keystroke, echoing a value back into the field being typed in and yanking it. Move aspect-ratio linking to the browser (ui/resolutionLock.ts): a debounced edit writes only the partner axis, never the field being edited, and commits immediately on blur, enter, or slider release. Keep the kanvas notify on notifyKanvasResize wired to the resize sliders' gradio .change, so it still fires on programmatic size updates (detect, paste, swap) that client-side listeners miss. Drop the per-change AR wiring, res_apply, and the resolutionChange* helpers.
404 lines
34 KiB
Python
404 lines
34 KiB
Python
import gradio as gr
|
|
from modules import shared, modelloader, ui_symbols, ui_common, sd_samplers
|
|
from modules.logger import log
|
|
from modules.ui_components import ToolButton
|
|
from modules.caption import caption
|
|
|
|
|
|
def create_toprow(is_img2img: bool = False, id_part: str | None = None, generate_visible: bool = True, negative_visible: bool = True, reprocess_visible: bool = True):
|
|
def apply_styles(prompt, prompt_neg, styles):
|
|
prompt = shared.prompt_styles.apply_styles_to_prompt(prompt, styles, wildcards=not shared.opts.extra_networks_apply_unparsed)
|
|
prompt_neg = shared.prompt_styles.apply_negative_styles_to_prompt(prompt_neg, styles, wildcards=not shared.opts.extra_networks_apply_unparsed)
|
|
return [gr.Textbox.update(value=prompt), gr.Textbox.update(value=prompt_neg), gr.Dropdown.update(value=[])]
|
|
|
|
def parse_style(styles):
|
|
return styles.split('|') if styles is not None else None
|
|
|
|
if id_part is None:
|
|
id_part = "img2img" if is_img2img else "txt2img"
|
|
with gr.Row(elem_id=f"{id_part}_toprow", variant="compact"):
|
|
with gr.Column(elem_id=f"{id_part}_prompt_container", scale=4):
|
|
with gr.Row():
|
|
with gr.Column(scale=80):
|
|
with gr.Row(elem_id=f"{id_part}_prompt_row"):
|
|
prompt = gr.Textbox(elem_id=f"{id_part}_prompt", label="Prompt", show_label=False, lines=3 if negative_visible else 5, placeholder="Prompt", elem_classes=["prompt", "main-prompts"])
|
|
with gr.Row():
|
|
with gr.Column(scale=80):
|
|
with gr.Row(elem_id=f"{id_part}_negative_row"):
|
|
negative_prompt = gr.Textbox(elem_id=f"{id_part}_neg_prompt", label="Negative prompt", show_label=False, lines=3, placeholder="Negative prompt", elem_classes=["prompt", "main-prompts"], visible=negative_visible)
|
|
with gr.Column(scale=1, elem_id=f"{id_part}_actions_column"):
|
|
with gr.Row(elem_id=f"{id_part}_generate_box"):
|
|
reprocess = []
|
|
submit = gr.Button('Generate', elem_id=f"{id_part}_generate", variant='primary', visible=generate_visible)
|
|
if reprocess_visible:
|
|
reprocess.append(gr.Button('Reprocess', elem_id=f"{id_part}_reprocess", variant='primary', visible=True))
|
|
reprocess.append(gr.Button('Reprocess decode', elem_id=f"{id_part}_reprocess_decode", variant='primary', visible=False))
|
|
reprocess.append(gr.Button('Reprocess refine', elem_id=f"{id_part}_reprocess_refine", variant='primary', visible=False))
|
|
reprocess.append(gr.Button('Reprocess face', elem_id=f"{id_part}_reprocess_detail", variant='primary', visible=False))
|
|
with gr.Row(elem_id=f"{id_part}_generate_line2"):
|
|
interrupt = gr.Button('Stop', elem_id=f"{id_part}_interrupt")
|
|
interrupt.click(fn=lambda: shared.state.interrupt(), _js="requestInterrupt", inputs=[], outputs=[])
|
|
skip = gr.Button('Skip', elem_id=f"{id_part}_skip")
|
|
skip.click(fn=lambda: shared.state.skip(), inputs=[], outputs=[])
|
|
pause = gr.Button('Pause', elem_id=f"{id_part}_pause")
|
|
pause.click(fn=lambda: shared.state.pause(), _js='checkPaused', inputs=[], outputs=[])
|
|
with gr.Row(elem_id=f"{id_part}_tools"):
|
|
button_paste = gr.Button(value='Restore', variant='secondary', elem_id=f"{id_part}_paste") # symbols.paste
|
|
button_clear = gr.Button(value='Clear', variant='secondary', elem_id=f"{id_part}_clear_prompt_btn") # symbols.clear
|
|
button_extra = gr.Button(value='Networks', variant='secondary', elem_id=f"{id_part}_extra_networks_btn") # symbols.networks
|
|
button_clear.click(fn=lambda *x: ['', ''], inputs=[prompt, negative_prompt], outputs=[prompt, negative_prompt], show_progress='hidden')
|
|
with gr.Row(elem_id=f"{id_part}_counters"):
|
|
token_counter = gr.HTML(value="<span>0/75</span>", elem_id=f"{id_part}_token_counter", elem_classes=["token-counter"], visible=False)
|
|
token_button = gr.Button(visible=False, elem_id=f"{id_part}_token_button")
|
|
negative_token_counter = gr.HTML(value="<span>0/75</span>", elem_id=f"{id_part}_negative_token_counter", elem_classes=["token-counter"], visible=False)
|
|
negative_token_button = gr.Button(visible=False, elem_id=f"{id_part}_negative_token_button")
|
|
with gr.Row(elem_id=f"{id_part}_styles_row"):
|
|
styles = gr.Dropdown(label="Styles", elem_id=f"{id_part}_styles", choices=[style.name for style in shared.prompt_styles.styles.values()], value=[], multiselect=True)
|
|
_styles_btn_refresh = ui_common.create_refresh_button(styles, shared.prompt_styles.reload, lambda: {"choices": [style.name for style in shared.prompt_styles.styles.values()]}, f"{id_part}_styles_refresh")
|
|
styles_btn_select = ToolButton('Select', elem_id=f"{id_part}_styles_select", visible=False)
|
|
styles_btn_apply = ToolButton(ui_symbols.style_apply, elem_id=f"{id_part}_styles_apply", visible=True)
|
|
styles_btn_save = ToolButton(ui_symbols.style_save, elem_id=f"{id_part}_styles_save", visible=True)
|
|
styles_btn_select.click(_js="applyStyles", fn=parse_style, inputs=[styles], outputs=[styles], show_progress='hidden')
|
|
styles_btn_apply.click(fn=apply_styles, inputs=[prompt, negative_prompt, styles], outputs=[prompt, negative_prompt, styles], show_progress='hidden')
|
|
styles_btn_save.click(fn=lambda: None, _js='() => quickSaveStyle()', inputs=[], outputs=[], show_progress='hidden')
|
|
return prompt, styles, negative_prompt, submit, reprocess, button_paste, button_extra, token_counter, token_button, negative_token_counter, negative_token_button
|
|
|
|
|
|
def create_resolution_inputs(tab, default_width=1024, default_height=1024):
|
|
width = gr.Slider(minimum=64, maximum=4096, step=8, label="Width", value=default_width, elem_id=f"{tab}_width")
|
|
height = gr.Slider(minimum=64, maximum=4096, step=8, label="Height", value=default_height, elem_id=f"{tab}_height")
|
|
ar_list = ['AR'] + [x.strip() for x in shared.opts.aspect_ratios.split(',') if x.strip() != '']
|
|
gr.Dropdown(show_label=False, interactive=True, choices=ar_list, value=ar_list[0], elem_id=f"{tab}_ar", elem_classes=["ar-dropdown"]) # aspect-ratio linking wired client-side in ui/resolutionLock.ts
|
|
res_switch_btn = ToolButton(value=ui_symbols.switch, elem_id=f"{tab}_res_btn_swap")
|
|
res_switch_btn.click(lambda w, h: (h, w), inputs=[width, height], outputs=[width, height], show_progress='hidden')
|
|
return width, height
|
|
|
|
|
|
def create_caption_button(tab: str, inputs: list | None = None, outputs: str | None = None, what: str = ''):
|
|
button_caption = gr.Button(ui_symbols.caption, elem_id=f"{tab}_caption_{what}", elem_classes=['caption', 'image-fit'])
|
|
if inputs is not None and outputs is not None:
|
|
button_caption.click(fn=caption.caption, inputs=inputs, outputs=[outputs])
|
|
return button_caption
|
|
|
|
|
|
def create_batch_inputs(tab, accordion=True):
|
|
with gr.Accordion(open=False, label="Batch", elem_id=f"{tab}_batch", elem_classes=["small-accordion"]) if accordion else gr.Group():
|
|
with gr.Row(elem_id=f"{tab}_row_batch"):
|
|
batch_count = gr.Slider(minimum=1, step=1, label='Batch count', value=1, elem_id=f"{tab}_batch_count", scale=5)
|
|
batch_size = gr.Slider(minimum=1, maximum=32, step=1, label='Batch size', value=1, elem_id=f"{tab}_batch_size", scale=5)
|
|
return batch_count, batch_size
|
|
|
|
|
|
def create_seed_inputs(tab, reuse_visible=True, accordion=True, subseed_visible=True, seed_resize_visible=False):
|
|
with gr.Accordion(open=False, label="Seed", elem_id=f"{tab}_seed_group", elem_classes=["small-accordion"]) if accordion else gr.Group():
|
|
with gr.Row(elem_id=f"{tab}_seed_row", variant="compact"):
|
|
seed = gr.Number(label='Initial seed', value=-1, elem_id=f"{tab}_seed", container=True)
|
|
random_seed = ToolButton(ui_symbols.random, elem_id=f"{tab}_seed_random")
|
|
reuse_seed = ToolButton(ui_symbols.reuse, elem_id=f"{tab}_seed_reuse", visible=reuse_visible)
|
|
with gr.Row(elem_id=f"{tab}_subseed_row", variant="compact", visible=subseed_visible):
|
|
subseed = gr.Number(label='Variation', value=-1, elem_id=f"{tab}_subseed", container=True)
|
|
random_subseed = ToolButton(ui_symbols.random, elem_id=f"{tab}_subseed_random")
|
|
reuse_subseed = ToolButton(ui_symbols.reuse, elem_id=f"{tab}_subseed_reuse", visible=reuse_visible)
|
|
subseed_strength = gr.Slider(label='Variation strength', value=0.0, minimum=0, maximum=1, step=0.01, elem_id=f"{tab}_subseed_strength", elem_classes=["subseed-strength"])
|
|
with gr.Row(visible=seed_resize_visible):
|
|
seed_resize_from_w = gr.Slider(minimum=0, maximum=4096, step=8, label="Resize seed from width", value=0, elem_id=f"{tab}_seed_resize_from_w")
|
|
seed_resize_from_h = gr.Slider(minimum=0, maximum=4096, step=8, label="Resize seed from height", value=0, elem_id=f"{tab}_seed_resize_from_h")
|
|
random_seed.click(fn=lambda: -1, show_progress='hidden', inputs=[], outputs=[seed])
|
|
random_subseed.click(fn=lambda: -1, show_progress='hidden', inputs=[], outputs=[subseed])
|
|
return seed, reuse_seed, subseed, reuse_subseed, subseed_strength, seed_resize_from_h, seed_resize_from_w
|
|
|
|
|
|
def create_video_inputs(tab:str, show_always:bool=False):
|
|
def video_type_change(video_type):
|
|
return [
|
|
gr.update(visible=video_type != 'None' or show_always),
|
|
gr.update(visible=video_type in ['GIF', 'PNG'] or show_always),
|
|
gr.update(visible=video_type not in ['None', 'GIF', 'PNG'] or show_always),
|
|
gr.update(visible=video_type not in ['None', 'GIF', 'PNG'] or show_always),
|
|
]
|
|
with gr.Row():
|
|
video_codecs = ['None', 'GIF', 'PNG', 'MP4/MP4V', 'MP4/AVC1', 'MP4/JVT3', 'MKV/H264', 'AVI/DIVX', 'AVI/RGBA', 'MJPEG/MJPG', 'MPG/MPG1', 'AVR/AVR1']
|
|
video_type = gr.Dropdown(label='Video format', choices=video_codecs, value='MP4/MP4V', elem_id=f"{tab}_video_type")
|
|
with gr.Row():
|
|
video_duration = gr.Slider(label='Video duration', minimum=0.25, maximum=300, step=0.25, value=2, visible=show_always, elem_id=f"{tab}_video_duration")
|
|
video_loop = gr.Checkbox(label='Loop video', value=True, visible=show_always, elem_id=f"{tab}_video_loop")
|
|
with gr.Row():
|
|
video_pad = gr.Slider(label='Pad frames', minimum=0, maximum=24, step=1, value=1, visible=show_always, elem_id=f"{tab}_video_pad")
|
|
video_interpolate = gr.Slider(label='Interpolate frames', minimum=0, maximum=24, step=1, value=0, visible=show_always, elem_id=f"{tab}_video_interpolate")
|
|
video_type.change(fn=video_type_change, inputs=[video_type], outputs=[video_duration, video_loop, video_pad, video_interpolate])
|
|
return video_type, video_duration, video_loop, video_pad, video_interpolate
|
|
|
|
|
|
def create_advanced_inputs(tab):
|
|
with gr.Accordion(open=False, label="Advanced", elem_id=f"{tab}_advanced", elem_classes=["small-accordion"]):
|
|
with gr.Group():
|
|
with gr.Row():
|
|
clip_skip = gr.Slider(label='CLiP skip', value=1, minimum=0, maximum=12, step=0.1, elem_id=f"{tab}_clip_skip", interactive=shared.opts.clip_skip_enabled)
|
|
with gr.Row(elem_id=f"{tab}_vae_options"):
|
|
vae_type = gr.Dropdown(label='VAE type', choices=['Full', 'Tiny', 'Remote'], value='Full', elem_id=f"{tab}_vae_type")
|
|
with gr.Row(elem_id=f"{tab}_advanced_options"):
|
|
tiling = gr.Checkbox(label='Texture tiling', value=False, elem_id=f"{tab}_tiling")
|
|
hidiffusion = gr.Checkbox(label='HiDiffusion', value=False, elem_id=f"{tab}_hidiffusion")
|
|
return vae_type, tiling, hidiffusion, clip_skip
|
|
|
|
|
|
def create_latent_inputs(tab):
|
|
# Latent Corrections (during diffusion)
|
|
with gr.Accordion(open=False, label="Latent Corrections", elem_id=f"{tab}_latent_corrections", elem_classes=["small-accordion"]):
|
|
with gr.Group():
|
|
with gr.Row(elem_id=f"{tab}_hdr_mode_row"):
|
|
hdr_mode = gr.Dropdown(label="Correction mode", choices=["Relative values", "Absolute values"], type="index", value="Relative values", elem_id=f"{tab}_hdr_mode", show_label=False)
|
|
hdr_apply_hires = gr.Checkbox(label="Apply to hires", value=True, elem_id=f"{tab}_hdr_apply_hires")
|
|
with gr.Row(elem_id=f"{tab}_correction_row"):
|
|
hdr_brightness = gr.Slider(minimum=-4.0, maximum=4.0, step=0.05, value=0, label="Latent brightness", elem_id=f"{tab}_hdr_brightness")
|
|
hdr_sharpen = gr.Slider(minimum=-4.0, maximum=4.0, step=0.05, value=0, label="Latent sharpen", elem_id=f"{tab}_hdr_sharpen")
|
|
hdr_color = gr.Slider(minimum=0.0, maximum=16.0, step=0.1, value=0.0, label="Latent color", elem_id=f"{tab}_hdr_color")
|
|
with gr.Row(elem_id=f"{tab}_hdr_clamp_row"):
|
|
hdr_clamp = gr.Checkbox(label="Latent clamp", value=False, elem_id=f"{tab}_hdr_clamp")
|
|
hdr_boundary = gr.Slider(minimum=0.0, maximum=10.0, step=0.1, value=4.0, label="Latent range", elem_id=f"{tab}_hdr_boundary")
|
|
hdr_threshold = gr.Slider(minimum=0.0, maximum=1.0, step=0.01, value=0.95, label="Latent threshold", elem_id=f"{tab}_hdr_threshold")
|
|
with gr.Row(elem_id=f"{tab}_hdr_max_row"):
|
|
hdr_maximize = gr.Checkbox(label="Latent maximize", value=False, elem_id=f"{tab}_hdr_maximize")
|
|
hdr_max_center = gr.Slider(minimum=0.0, maximum=2.0, step=0.1, value=0.6, label="Latent center", elem_id=f"{tab}_hdr_max_center")
|
|
hdr_max_boundary = gr.Slider(minimum=0.5, maximum=2.0, step=0.1, value=1.0, label="Latent max range", elem_id=f"{tab}_hdr_max_boundary")
|
|
with gr.Row(elem_id=f"{tab}_hdr_color_row"):
|
|
hdr_color_picker = gr.ColorPicker(label="Latent tint", show_label=True, container=False, value=None, elem_id=f"{tab}_hdr_color_picker")
|
|
hdr_tint_ratio = gr.Slider(label="Tint strength", minimum=-4.0, maximum=4.0, step=0.05, value=0.0, elem_id=f"{tab}_hdr_tint_ratio")
|
|
return hdr_mode, hdr_brightness, hdr_color, hdr_sharpen, hdr_clamp, hdr_boundary, hdr_threshold, hdr_maximize, hdr_max_center, hdr_max_boundary, hdr_color_picker, hdr_tint_ratio, hdr_apply_hires
|
|
|
|
|
|
def create_color_inputs(tab):
|
|
# Color Grading (post-generation pixel-space)
|
|
with gr.Accordion(open=False, label="Color Grading", elem_id=f"{tab}_color_grading", elem_classes=["small-accordion"]):
|
|
with gr.Group():
|
|
with gr.Row(elem_id=f"{tab}_grading_basic_row"):
|
|
grading_brightness = gr.Slider(minimum=-1.0, maximum=1.0, step=0.05, value=0, label='Brightness', elem_id=f"{tab}_grading_brightness")
|
|
grading_contrast = gr.Slider(minimum=-1.0, maximum=1.0, step=0.05, value=0, label='Contrast', elem_id=f"{tab}_grading_contrast")
|
|
grading_saturation = gr.Slider(minimum=-1.0, maximum=1.0, step=0.05, value=0, label='Saturation', elem_id=f"{tab}_grading_saturation")
|
|
with gr.Row(elem_id=f"{tab}_grading_basic2_row"):
|
|
grading_hue = gr.Slider(minimum=0.0, maximum=1.0, step=0.05, value=0, label='Hue', elem_id=f"{tab}_grading_hue")
|
|
grading_gamma = gr.Slider(minimum=0.1, maximum=10.0, step=0.1, value=1.0, label='Gamma', elem_id=f"{tab}_grading_gamma")
|
|
grading_sharpness = gr.Slider(minimum=0.0, maximum=2.0, step=0.05, value=0, label='Sharpness', elem_id=f"{tab}_grading_sharpness")
|
|
grading_color_temp = gr.Slider(minimum=2000, maximum=12000, step=100, value=6500, label='Color temp', elem_id=f"{tab}_grading_color_temp")
|
|
with gr.Group():
|
|
gr.HTML('<h3>Tone</h3>')
|
|
with gr.Row(elem_id=f"{tab}_grading_tone_row"):
|
|
grading_shadows = gr.Slider(minimum=-1.0, maximum=1.0, step=0.05, value=0, label='Shadows', elem_id=f"{tab}_grading_shadows")
|
|
grading_midtones = gr.Slider(minimum=-1.0, maximum=1.0, step=0.05, value=0, label='Midtones', elem_id=f"{tab}_grading_midtones")
|
|
grading_highlights = gr.Slider(minimum=-1.0, maximum=1.0, step=0.05, value=0, label='Highlights', elem_id=f"{tab}_grading_highlights")
|
|
with gr.Row(elem_id=f"{tab}_grading_clahe_row"):
|
|
grading_clahe_clip = gr.Slider(minimum=0.0, maximum=5.0, step=0.25, value=0, label='CLAHE clip', elem_id=f"{tab}_grading_clahe_clip")
|
|
grading_clahe_grid = gr.Slider(minimum=2, maximum=16, step=1, value=8, label='CLAHE grid', elem_id=f"{tab}_grading_clahe_grid")
|
|
with gr.Group():
|
|
with gr.Row(elem_id=f"{tab}_grading_split_row"):
|
|
grading_shadows_tint = gr.ColorPicker(label="Shadows tint", value="#000000", elem_id=f"{tab}_grading_shadows_tint")
|
|
grading_highlights_tint = gr.ColorPicker(label="Highlights tint", value="#ffffff", elem_id=f"{tab}_grading_highlights_tint")
|
|
grading_split_tone_balance = gr.Slider(minimum=0.0, maximum=1.0, step=0.05, value=0.5, label='Split tone balance', elem_id=f"{tab}_grading_split_tone_balance")
|
|
with gr.Group():
|
|
gr.HTML('<h3>Effects</h3>')
|
|
with gr.Row(elem_id=f"{tab}_grading_effects_row"):
|
|
grading_vignette = gr.Slider(minimum=0.0, maximum=1.0, step=0.05, value=0, label='Vignette', elem_id=f"{tab}_grading_vignette")
|
|
grading_grain = gr.Slider(minimum=0.0, maximum=1.0, step=0.05, value=0, label='Grain', elem_id=f"{tab}_grading_grain")
|
|
with gr.Group():
|
|
gr.HTML('<h3>LUT</h3>')
|
|
with gr.Row(elem_id=f"{tab}_grading_lut_row"):
|
|
grading_lut_cube_file = gr.File(label='LUT .cube file', file_types=['.cube'], elem_id=f"{tab}_grading_lut_file")
|
|
grading_lut_strength = gr.Slider(minimum=0.0, maximum=2.0, step=0.05, value=1.0, label='LUT strength', elem_id=f"{tab}_grading_lut_strength")
|
|
return grading_brightness, grading_contrast, grading_saturation, grading_hue, grading_gamma, grading_sharpness, grading_color_temp, grading_shadows, grading_midtones, grading_highlights, grading_clahe_clip, grading_clahe_grid, grading_shadows_tint, grading_highlights_tint, grading_split_tone_balance, grading_vignette, grading_grain, grading_lut_cube_file, grading_lut_strength
|
|
|
|
|
|
def create_sampler_and_steps_selection(choices, tabname, default_steps:int=20):
|
|
if choices is None:
|
|
sd_samplers.set_samplers()
|
|
choices = [x for x in sd_samplers.samplers if not x.name == 'Same as primary']
|
|
with gr.Row(elem_id=f"{tabname}_sampler_row", elem_classes=['flex-break', 'flexbox']):
|
|
steps = gr.Slider(minimum=1, maximum=100, step=1, label="Steps", elem_id=f"{tabname}_steps", value=default_steps)
|
|
sampler_index = gr.Dropdown(label='Sampling method', elem_id=f"{tabname}_sampling", choices=[x.name for x in choices], value='Default', type="index")
|
|
return steps, sampler_index
|
|
|
|
|
|
def create_sampler_options(tabname):
|
|
def set_sampler_options(sampler_options):
|
|
shared.opts.data['schedulers_dynamic_shift'] = 'dynamic' in sampler_options
|
|
shared.opts.data['schedulers_use_thresholding'] = 'thresholding' in sampler_options
|
|
shared.opts.data['schedulers_use_loworder'] = 'low order' in sampler_options
|
|
shared.opts.data['schedulers_rescale_betas'] = 'rescale' in sampler_options
|
|
log.debug(f'Sampler set options: {sampler_options}')
|
|
shared.opts.save(silent=True)
|
|
|
|
def set_sampler_fallback(fallback):
|
|
log.debug(f'Sampler set options: fallback={fallback}')
|
|
shared.opts.schedulers_fallback = fallback
|
|
shared.opts.save(silent=True)
|
|
|
|
def set_sampler_timesteps(timesteps):
|
|
log.debug(f'Sampler set options: timesteps={timesteps}')
|
|
shared.opts.schedulers_timesteps = timesteps
|
|
shared.opts.save(silent=True)
|
|
|
|
def set_sampler_spacing(spacing):
|
|
log.debug(f'Sampler set options: spacing={spacing}')
|
|
shared.opts.schedulers_timestep_spacing = spacing
|
|
shared.opts.save(silent=True)
|
|
|
|
def set_sampler_sigma(sampler_sigma):
|
|
log.debug(f'Sampler set options: sigma={sampler_sigma}')
|
|
shared.opts.schedulers_sigma = sampler_sigma
|
|
shared.opts.save(silent=True)
|
|
|
|
def set_sampler_order(sampler_order):
|
|
log.debug(f'Sampler set options: order={sampler_order}')
|
|
shared.opts.schedulers_solver_order = sampler_order
|
|
shared.opts.save(silent=True)
|
|
|
|
def set_sampler_prediction(sampler_prediction):
|
|
log.debug(f'Sampler set options: prediction={sampler_prediction}')
|
|
shared.opts.schedulers_prediction_type = sampler_prediction
|
|
shared.opts.save(silent=True)
|
|
|
|
def set_sampler_beta(sampler_beta):
|
|
log.debug(f'Sampler set options: beta={sampler_beta}')
|
|
shared.opts.schedulers_beta_schedule = sampler_beta
|
|
shared.opts.save(silent=True)
|
|
|
|
def set_sampler_shift(sampler_shift, sampler_base_shift, sampler_max_shift):
|
|
log.debug(f'Sampler set options: shift={sampler_shift} base={sampler_base_shift} max={sampler_max_shift}')
|
|
shared.opts.schedulers_shift = sampler_shift
|
|
shared.opts.schedulers_base_shift = sampler_base_shift
|
|
shared.opts.schedulers_max_shift = sampler_max_shift
|
|
shared.opts.save(silent=True)
|
|
|
|
def set_sigma_adjust(val, start, end):
|
|
log.debug(f'Sampler set options: sigma={val} min={start} max={end}')
|
|
shared.opts.schedulers_sigma_adjust = val
|
|
shared.opts.schedulers_sigma_adjust_min = start
|
|
shared.opts.schedulers_sigma_adjust_max = end
|
|
shared.opts.save(silent=True)
|
|
|
|
# 'linear', 'scaled_linear', 'squaredcos_cap_v2'
|
|
def set_sampler_preset(preset):
|
|
if preset == 'AYS SD15':
|
|
return '999,850,736,645,545,455,343,233,124,24'
|
|
if preset == 'AYS SDXL':
|
|
return '999,845,730,587,443,310,193,116,53,13'
|
|
return ''
|
|
|
|
with gr.Row(elem_classes=['flex-break']):
|
|
sampler_sigma = gr.Dropdown(label='Sigma method', elem_id=f"{tabname}_sampler_sigma", choices=['default', 'karras', 'betas', 'exponential', 'lambdas', 'flowmatch'], value=shared.opts.schedulers_sigma, type='value')
|
|
sampler_spacing = gr.Dropdown(label='Timestep spacing', elem_id=f"{tabname}_sampler_spacing", choices=['default', 'linspace', 'leading', 'trailing'], value=shared.opts.schedulers_timestep_spacing, type='value')
|
|
with gr.Row(elem_classes=['flex-break']):
|
|
sampler_beta = gr.Dropdown(label='Beta schedule', elem_id=f"{tabname}_sampler_beta", choices=['default', 'linear', 'scaled', 'cosine', 'sigmoid'], value=shared.opts.schedulers_beta_schedule, type='value')
|
|
sampler_prediction = gr.Dropdown(label='Prediction method', elem_id=f"{tabname}_sampler_prediction", choices=['default', 'epsilon', 'sample', 'v_prediction', 'flow_prediction'], value=shared.opts.schedulers_prediction_type, type='value')
|
|
with gr.Row(elem_classes=['flex-break']):
|
|
sampler_presets = gr.Dropdown(label='Timesteps presets', elem_id=f"{tabname}_sampler_presets", choices=['None', 'AYS SD15', 'AYS SDXL'], value='None', type='value')
|
|
sampler_timesteps = gr.Textbox(label='Timesteps override', elem_id=f"{tabname}_sampler_timesteps", value=shared.opts.schedulers_timesteps)
|
|
with gr.Row(elem_classes=['flex-break']):
|
|
sampler_sigma_adjust_val = gr.Slider(minimum=0.5, maximum=1.5, step=0.01, label='Sigma adjust', value=shared.opts.schedulers_sigma_adjust, elem_id=f"{tabname}_sampler_sigma_adjust")
|
|
sampler_sigma_adjust_min = gr.Slider(minimum=0.0, maximum=1.0, step=0.01, label='Adjust start', value=shared.opts.schedulers_sigma_adjust_min, elem_id=f"{tabname}_sampler_sigma_adjust_min")
|
|
sampler_sigma_adjust_max = gr.Slider(minimum=0.0, maximum=1.0, step=0.01, label='Adjust end', value=shared.opts.schedulers_sigma_adjust_max, elem_id=f"{tabname}_sampler_sigma_adjust_max")
|
|
with gr.Row(elem_classes=['flex-break']):
|
|
sampler_order = gr.Slider(minimum=0, maximum=5, step=1, label="Sampler order", value=shared.opts.schedulers_solver_order, elem_id=f"{tabname}_sampler_order")
|
|
with gr.Row(elem_classes=['flex-break']):
|
|
sampler_shift = gr.Slider(minimum=0, maximum=10, step=0.1, label="Flow shift", value=shared.opts.schedulers_shift, elem_id=f"{tabname}_sampler_shift")
|
|
sampler_base_shift = gr.Slider(minimum=0, maximum=10, step=0.01, label="Base shift", value=shared.opts.schedulers_base_shift, elem_id=f"{tabname}_sampler_base_shift")
|
|
sampler_max_shift = gr.Slider(minimum=0, maximum=10, step=0.01, label="Max shift", value=shared.opts.schedulers_max_shift, elem_id=f"{tabname}_sampler_max_shift")
|
|
with gr.Row(elem_classes=['flex-break']):
|
|
options = ['low order', 'thresholding', 'dynamic', 'rescale']
|
|
values = []
|
|
values += ['low order'] if shared.opts.data.get('schedulers_use_loworder', True) else []
|
|
values += ['thresholding'] if shared.opts.data.get('schedulers_use_thresholding', False) else []
|
|
values += ['dynamic'] if shared.opts.data.get('schedulers_dynamic_shift', False) else []
|
|
values += ['rescale'] if shared.opts.data.get('schedulers_rescale_betas', False) else []
|
|
sampler_options = gr.CheckboxGroup(label='Options', elem_id=f"{tabname}_sampler_options", choices=options, value=values, type='value')
|
|
with gr.Row(elem_classes=['flex-break']):
|
|
sampler_fallback = gr.Checkbox(label='Fallback on invalid', value=shared.opts.schedulers_fallback, elem_id=f"{tabname}_sampler_fallback")
|
|
|
|
sampler_sigma.change(fn=set_sampler_sigma, inputs=[sampler_sigma], outputs=[])
|
|
sampler_spacing.change(fn=set_sampler_spacing, inputs=[sampler_spacing], outputs=[])
|
|
sampler_presets.change(fn=set_sampler_preset, inputs=[sampler_presets], outputs=[sampler_timesteps])
|
|
sampler_timesteps.change(fn=set_sampler_timesteps, inputs=[sampler_timesteps], outputs=[])
|
|
sampler_beta.change(fn=set_sampler_beta, inputs=[sampler_beta], outputs=[])
|
|
sampler_prediction.change(fn=set_sampler_prediction, inputs=[sampler_prediction], outputs=[])
|
|
sampler_order.change(fn=set_sampler_order, inputs=[sampler_order], outputs=[])
|
|
sampler_shift.change(fn=set_sampler_shift, inputs=[sampler_shift, sampler_base_shift, sampler_max_shift], outputs=[])
|
|
sampler_options.change(fn=set_sampler_options, inputs=[sampler_options], outputs=[])
|
|
sampler_fallback.change(fn=set_sampler_fallback, inputs=[sampler_fallback], outputs=[])
|
|
sampler_sigma_adjust_val.change(fn=set_sigma_adjust, inputs=[sampler_sigma_adjust_val, sampler_sigma_adjust_min, sampler_sigma_adjust_max], outputs=[])
|
|
sampler_sigma_adjust_min.change(fn=set_sigma_adjust, inputs=[sampler_sigma_adjust_val, sampler_sigma_adjust_min, sampler_sigma_adjust_max], outputs=[])
|
|
sampler_sigma_adjust_max.change(fn=set_sigma_adjust, inputs=[sampler_sigma_adjust_val, sampler_sigma_adjust_min, sampler_sigma_adjust_max], outputs=[])
|
|
|
|
|
|
def create_hires_inputs(tab):
|
|
with gr.Accordion(open=False, label="Refine", elem_id=f"{tab}_refine_accordion", elem_classes=["small-accordion"]):
|
|
with gr.Row(elem_id=f"{tab}_hires_row1"):
|
|
enable_hr = gr.Checkbox(label='Enable refine pass', value=False, elem_id=f"{tab}_enable_hr")
|
|
hr_resize_mode, hr_upscaler, hr_resize_context, hr_resize_x, hr_resize_y, hr_scale, _selected_scale_tab = create_resize_inputs(tab, None, accordion=False, latent=True, non_zero=False)
|
|
with gr.Row(elem_id=f"{tab}_hires_fix_row2"):
|
|
hr_force = gr.Checkbox(label='Force HiRes', value=False, elem_id=f"{tab}_hr_force")
|
|
with gr.Row(elem_id=f"{tab}_hires_fix_row2"):
|
|
hr_sampler_index = gr.Dropdown(label='Refine sampler', elem_id=f"{tab}_sampling_alt", choices=[x.name for x in sd_samplers.samplers], value='Same as primary', type="index")
|
|
with gr.Row(elem_id=f"{tab}_hires_row2"):
|
|
hr_second_pass_steps = gr.Slider(minimum=0, maximum=99, step=1, label='HiRes steps', elem_id=f"{tab}_steps_alt", value=20)
|
|
denoising_strength = gr.Slider(minimum=0.0, maximum=0.99, step=0.01, label='Strength', value=0.3, elem_id=f"{tab}_denoising_strength")
|
|
with gr.Row(elem_id=f"{tab}_refiner_row1"):
|
|
refiner_start = gr.Slider(minimum=0.0, maximum=1.0, step=0.05, label='Refiner start', value=0.0, elem_id=f"{tab}_refiner_start")
|
|
refiner_steps = gr.Slider(minimum=0, maximum=99, step=1, label="Refiner steps", elem_id=f"{tab}_refiner_steps", value=20)
|
|
refiner_prompt = gr.Textbox(value='', lines=2, label='Refine prompt', elem_id=f"{tab}_refiner_prompt", elem_classes=["prompt"], placeholder="refine prompt or leave empty to use main prompt")
|
|
refiner_negative = gr.Textbox(value='', lines=2, label='Refine negative prompt', elem_id=f"{tab}_refiner_neg_prompt", elem_classes=["prompt"], placeholder="refine negative prompt or leave empty to use main prompt")
|
|
return enable_hr, hr_sampler_index, denoising_strength, hr_resize_mode, hr_resize_context, hr_upscaler, hr_force, hr_second_pass_steps, hr_scale, hr_resize_x, hr_resize_y, refiner_steps, refiner_start, refiner_prompt, refiner_negative
|
|
|
|
|
|
def create_resize_inputs(tab, images, accordion=True, latent=False, non_zero=True, prefix=''):
|
|
dummy_component = gr.Number(visible=False, value=0)
|
|
if len(prefix) > 0 and not prefix.startswith(' '):
|
|
prefix = f' {prefix}' if prefix != 'before' else ''
|
|
with gr.Accordion(open=False, label="Resize", elem_classes=["small-accordion"], elem_id=f"{tab}_resize_group") if accordion else gr.Group():
|
|
with gr.Row():
|
|
available_upscalers = [x.name for x in shared.sd_upscalers]
|
|
if len(available_upscalers) == 0:
|
|
available_upscalers = ['None']
|
|
if not latent:
|
|
available_upscalers = [x for x in available_upscalers if not x.lower().startswith('latent')]
|
|
resize_mode = gr.Dropdown(label=f"Mode{prefix}" if non_zero else "Resize mode", elem_id=f"{tab}_resize_mode", choices=shared.resize_modes, type="index", value='Fixed')
|
|
resize_name = gr.Dropdown(label=f"Method{prefix}" if non_zero else "Resize method", elem_id=f"{tab}_resize_name", choices=available_upscalers, value=available_upscalers[0], visible=True)
|
|
resize_context_choices = ["Add with forward", "Remove with forward", "Add with backward", "Remove with backward"]
|
|
resize_context = gr.Dropdown(label=f"Context{prefix}", elem_id=f"{tab}_resize_context", choices=resize_context_choices, value=resize_context_choices[0], visible=False)
|
|
resize_refresh_btn = ui_common.create_refresh_button(resize_name, modelloader.load_upscalers, lambda: {"choices": modelloader.load_upscalers()}, f'{tab}_upscalers_refresh')
|
|
|
|
def resize_mode_change(mode):
|
|
if mode is None or mode == 0:
|
|
return gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
|
|
return gr.update(visible=mode != 5), gr.update(visible=mode == 5), gr.update(visible=mode != 5)
|
|
resize_mode.change(fn=resize_mode_change, inputs=[resize_mode], outputs=[resize_name, resize_context, resize_refresh_btn])
|
|
|
|
with gr.Row(visible=True) as _resize_group:
|
|
with gr.Column(elem_id=f"{tab}_column_size"):
|
|
selected_scale_tab = gr.State(value=0 if tab != 'img2img' else 1) # pylint: disable=abstract-class-instantiated
|
|
with gr.Tabs(elem_id=f"{tab}_scale_tabs", selected=0 if non_zero else 1):
|
|
with gr.Tab(label="Fixed", id=0, elem_id=f"{tab}_scale_tab_fixed") as tab_scale_to:
|
|
with gr.Row(elem_id=f"{tab}_resize_row_fixed"):
|
|
with gr.Column(elem_id=f"{tab}_column_fixed1", scale=6):
|
|
suffix = '_resize' if tab != 'img2img' else ''
|
|
width = gr.Slider(minimum=64 if non_zero else 0, maximum=8192, step=8, label=f"Width{prefix}" if non_zero else "Resize width", value=1024 if non_zero else 0, elem_id=f"{tab}{suffix}_width")
|
|
height = gr.Slider(minimum=64 if non_zero else 0, maximum=8192, step=8, label=f"Height{prefix}" if non_zero else "Resize height", value=1024 if non_zero else 0, elem_id=f"{tab}{suffix}_height")
|
|
with gr.Column(elem_id=f"{tab}_column_fixed2", scale=1):
|
|
ar_list = ['AR'] + [x.strip() for x in shared.opts.aspect_ratios.split(',') if x.strip() != '']
|
|
gr.Dropdown(show_label=False, interactive=True, choices=ar_list, value=ar_list[0], elem_id=f"{tab}_resize_ar", elem_classes=["ar-dropdown"]) # aspect-ratio linking wired client-side in ui/resolutionLock.ts
|
|
res_switch_btn = ToolButton(value=ui_symbols.switch, elem_id=f"{tab}_resize_size_swap")
|
|
res_switch_btn.click(lambda w, h: (h, w), inputs=[width, height], outputs=[width, height], show_progress='hidden')
|
|
detect_image_size_btn = ToolButton(value=ui_symbols.detect, elem_id=f"{tab}_resize_detect_size")
|
|
el = tab.split('_')[0]
|
|
detect_image_size_btn.click(fn=lambda w, h, _: (w or gr.update(), h or gr.update()), _js=f'currentImageResolution{el}', inputs=[dummy_component, dummy_component, dummy_component], outputs=[width, height], show_progress='hidden')
|
|
# keep the kanvas stage synced to the resize sliders; .change fires on user and programmatic updates (detect, paste, swap) and writes nothing back
|
|
width.change(fn=None, _js='notifyKanvasResize', inputs=[width, height], outputs=[], show_progress='hidden')
|
|
height.change(fn=None, _js='notifyKanvasResize', inputs=[width, height], outputs=[], show_progress='hidden')
|
|
with gr.Tab(label="Scale", id=1, elem_id=f"{tab}_scale_tab_scale") as tab_scale_by:
|
|
scale_by = gr.Slider(minimum=0.05, maximum=8.0, step=0.05, label=f"Scale{prefix}" if non_zero else "Resize scale", value=1.0, elem_id=f"{tab}_scale")
|
|
if images is not None:
|
|
for component in images:
|
|
component.change(fn=lambda: None, _js="updateImg2imgResizeToTextAfterChangingImage", inputs=[], outputs=[], show_progress='hidden')
|
|
tab_scale_to.select(fn=lambda: 0, inputs=[], outputs=[selected_scale_tab])
|
|
tab_scale_by.select(fn=lambda: 1, inputs=[], outputs=[selected_scale_tab])
|
|
# resize_mode.change(fn=lambda x: gr.update(visible=x != 0), inputs=[resize_mode], outputs=[_resize_group])
|
|
return resize_mode, resize_name, resize_context, width, height, scale_by, selected_scale_tab
|