From 4af33ccda91669b19a9df01611c0e5146b5a0a52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20G=C3=A4=C3=9Fler?= Date: Sat, 3 Sep 2022 09:24:03 +0200 Subject: [PATCH] Load txt2img setting from files or clipboard (#436) Functional restore defaults From file, non-working paste Working paste settings --- frontend/frontend.py | 44 +++++++++++++++++++++++++++++++++++++--- frontend/ui_functions.py | 44 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+), 3 deletions(-) diff --git a/frontend/frontend.py b/frontend/frontend.py index 0ac7f7c..be959fb 100644 --- a/frontend/frontend.py +++ b/frontend/frontend.py @@ -1,6 +1,13 @@ +import sys +from tkinter.filedialog import askopenfilename import gradio as gr from frontend.css_and_js import css, js, call_JS, js_parse_prompt, js_copy_txt2img_output import frontend.ui_functions as uifn +try: + import pyperclip +except ImportError: + print("Warning: pyperclip is not installed. Pasting settings is unavailable.", file=sys.stderr) + pyperclip = None def draw_gradio_ui(opt, img2img=lambda x: x, txt2img=lambda x: x,imgproc=lambda x: x, txt2img_defaults={}, RealESRGAN=True, GFPGAN=True,LDSR=True, txt2img_toggles={}, txt2img_toggle_defaults='k_euler', show_embeddings=False, img2img_defaults={}, @@ -52,14 +59,17 @@ def draw_gradio_ui(opt, img2img=lambda x: x, txt2img=lambda x: x,imgproc=lambda output_txt2img_params = gr.Highlightedtext(label="Generation parameters", interactive=False, elem_id='highlight') with gr.Group(): with gr.Row(elem_id='txt2img_output_row'): - output_txt2img_copy_params = gr.Button("Copy full parameters").click( + output_txt2img_copy_params = gr.Button("Copy all").click( inputs=[output_txt2img_params], outputs=[], _js=js_copy_txt2img_output, fn=None, show_progress=False) output_txt2img_seed = gr.Number(label='Seed', interactive=False, visible=False) - output_txt2img_copy_seed = gr.Button("Copy only seed").click( + output_txt2img_copy_seed = gr.Button("Copy seed").click( inputs=[output_txt2img_seed], outputs=[], _js='(x) => navigator.clipboard.writeText(x)', fn=None, show_progress=False) + input_txt2img_paste_parameters = gr.Button('Paste settings', visible=pyperclip is not None) + input_txt2img_from_file = gr.Button('From file...') + input_txt2img_defaults = gr.Button('Restore defaults') output_txt2img_stats = gr.HTML(label='Stats') with gr.Column(): @@ -112,9 +122,37 @@ def draw_gradio_ui(opt, img2img=lambda x: x, txt2img=lambda x: x,imgproc=lambda txt2img_height, txt2img_width, txt2img_embeddings, txt2img_variant_amount, txt2img_variant_seed], [output_txt2img_gallery, output_txt2img_seed, output_txt2img_params, output_txt2img_stats] ) + txt2img_settings_elements = [ + txt2img_prompt, txt2img_steps, txt2img_sampling, txt2img_toggles, txt2img_realesrgan_model_name, + txt2img_ddim_eta, txt2img_batch_count, txt2img_batch_size, txt2img_cfg, txt2img_seed, + txt2img_height, txt2img_width, txt2img_embeddings, txt2img_variant_amount, txt2img_variant_seed + ] + txt2img_settings_checkboxgroup_info = [(3, txt2img_toggles.choices)] + input_txt2img_defaults.click( + fn=lambda *x: uifn.load_settings( + *x, txt2img_defaults, uifn.LOAD_SETTINGS_TXT2IMG_NAMES, txt2img_settings_checkboxgroup_info + ), + inputs=txt2img_settings_elements, + outputs=txt2img_settings_elements + ) + + def from_file_func(*inputs): + file_path = askopenfilename() + return uifn.load_settings( + *inputs, file_path, uifn.LOAD_SETTINGS_TXT2IMG_NAMES, txt2img_settings_checkboxgroup_info) + + input_txt2img_from_file.click( + from_file_func, inputs=txt2img_settings_elements, outputs=txt2img_settings_elements) + + input_txt2img_paste_parameters.click( + lambda *x: uifn.load_settings( + *x, pyperclip.paste(), uifn.LOAD_SETTINGS_TXT2IMG_NAMES, txt2img_settings_checkboxgroup_info), + inputs=txt2img_settings_elements, + outputs=txt2img_settings_elements + ) + # txt2img_width.change(fn=uifn.update_dimensions_info, inputs=[txt2img_width, txt2img_height], outputs=txt2img_dimensions_info_text_box) # txt2img_height.change(fn=uifn.update_dimensions_info, inputs=[txt2img_width, txt2img_height], outputs=txt2img_dimensions_info_text_box) - live_prompt_params = [txt2img_prompt, txt2img_width, txt2img_height, txt2img_steps, txt2img_seed, txt2img_batch_count, txt2img_cfg] txt2img_prompt.change( fn=None, diff --git a/frontend/ui_functions.py b/frontend/ui_functions.py index 5140402..0122c41 100644 --- a/frontend/ui_functions.py +++ b/frontend/ui_functions.py @@ -1,10 +1,17 @@ import re +import sys +import os import gradio as gr from PIL import Image, ImageFont, ImageDraw, ImageFilter, ImageOps from io import BytesIO import base64 import re +import yaml +LOAD_SETTINGS_TXT2IMG_NAMES = [ + "prompt", "ddim_steps", "sampler_name", "toggles", "realesrgan_model_name", "ddim_eta", + "n_iter", "batch_size", "cfg_scale", "seed", "height", "width", "fp", "variant_amount", "variant_seed" +] def change_image_editor_mode(choice, cropped_image, resize_mode, width, height): if choice == "Mask": @@ -120,3 +127,40 @@ def resize_image(resize_mode, im, width, height): def update_dimensions_info(width, height): pixel_count_formated = "{:,.0f}".format(width * height) return f"Aspect ratio: {round(width / height, 5)}\nTotal pixel count: {pixel_count_formated}" + +def load_settings(*values): + new_settings, key_names, checkboxgroup_info = values[-3:] + values = list(values[:-3]) + + if new_settings: + if type(new_settings) is str: + if os.path.exists(new_settings): + with open(new_settings, "r", encoding="utf8") as f: + new_settings = yaml.safe_load(f) + elif new_settings.startswith("file://") and os.path.exists(new_settings[7:]): + with open(new_settings[7:], "r", encoding="utf8") as f: + new_settings = yaml.safe_load(f) + else: + new_settings = yaml.safe_load(new_settings) + if type(new_settings) is not dict: + new_settings = {"prompt": new_settings} + if "txt2img" in new_settings: + new_settings = new_settings["txt2img"] + target = new_settings.pop("target", "txt2img") + if target != "txt2img": + print(f"Warning: applying settings to txt2img even though {target} is specified as target.", file=sys.stderr) + + skipped_settings = {} + for key in new_settings.keys(): + if key in key_names: + values[key_names.index(key)] = new_settings[key] + else: + skipped_settings[key] = new_settings[key] + if skipped_settings: + print(f"Settings could not be applied: {skipped_settings}", file=sys.stderr) + + # Convert lists of checkbox indices to lists of checkbox labels: + for (cbg_index, cbg_choices) in checkboxgroup_info: + values[cbg_index] = [cbg_choices[i] for i in values[cbg_index]] + + return values