import gradio as gr import random import time import shared import argparse import modules.path import fooocus_version import modules.html import modules.async_worker as worker import modules.constants as constants import json from modules.settings import load_settings from modules.resolutions import get_resolution_string, resolutions from modules.sdxl_styles import style_keys from collections.abc import Mapping from PIL import Image def generate_clicked(*args): yield gr.update(interactive=False), \ gr.update(visible=True, value=modules.html.make_progress_html(1, 'Processing text encoding ...')), \ gr.update(visible=True, value=None), \ gr.update(visible=False), \ gr.update(), \ gr.update(value=None), \ gr.update() worker.buffer.append(list(args)) finished = False while not finished: time.sleep(0.01) if len(worker.outputs) > 0: flag, product = worker.outputs.pop(0) if flag == 'preview': percentage, title, image = product yield gr.update(interactive=False), \ gr.update(visible=True, value=modules.html.make_progress_html(percentage, title)), \ gr.update(visible=True, value=image) if image is not None else gr.update(), \ gr.update(visible=False), \ gr.update(), \ gr.update(), \ gr.update() if flag == 'results': yield gr.update(interactive=True), \ gr.update(visible=False), \ gr.update(visible=False), \ gr.update(visible=True), \ gr.update(value=product), \ gr.update(), \ gr.update() if flag == 'metadatas': yield gr.update(), gr.update(), gr.update(), gr.update(), gr.update(), gr.update(value=product), gr.update(selected=1) finished = True return def metadata_to_ctrls(metadata, ctrls): if not isinstance(metadata, Mapping): return ctrls if 'prompt' in metadata: ctrls[0] = metadata['prompt'] if 'negative_prompt' in metadata: ctrls[1] = metadata['negative_prompt'] if 'style' in metadata: ctrls[2] = metadata['style'] if 'performance' in metadata: ctrls[3] = metadata['performance'] if 'width' in metadata and 'height' in metadata: ctrls[4] = get_resolution_string(metadata['width'], metadata['height']) elif 'resolution' in metadata: ctrls[4] = metadata['resolution'] # image_number if 'seed' in metadata: ctrls[6] = metadata['seed'] ctrls[32] = False if 'sharpness' in metadata: ctrls[7] = metadata['sharpness'] if 'sampler_name' in metadata: ctrls[8] = metadata['sampler_name'] elif 'sampler' in metadata: ctrls[8] = metadata['sampler'] if 'scheduler' in metadata: ctrls[9] = metadata['scheduler'] if 'steps' in metadata: ctrls[10] = metadata['steps'] if ctrls[10] == constants.STEPS_SPEED: ctrls[3] = 'Speed' elif ctrls[10] == constants.STEPS_QUALITY: ctrls[3] = 'Quality' else: ctrls[3] = 'Custom' if 'switch' in metadata: ctrls[11] = round(metadata['switch'] / ctrls[10], 2) if ctrls[11] != round(constants.SWITCH_SPEED / constants.STEPS_SPEED, 2): ctrls[3] = 'Custom' if 'cfg' in metadata: ctrls[12] = metadata['cfg'] if 'base_model' in metadata: ctrls[13] = metadata['base_model'] elif 'base_model_name' in metadata: ctrls[13] = metadata['base_model_name'] if 'refiner_model' in metadata: ctrls[14] = metadata['refiner_model'] elif 'refiner_model_name' in metadata: ctrls[14] = metadata['refiner_model_name'] if 'base_clip_skip' in metadata: ctrls[15] = metadata['base_clip_skip'] if 'refiner_clip_skip' in metadata: ctrls[16] = metadata['refiner_clip_skip'] if 'l1' in metadata: ctrls[17] = metadata['l1'] if 'w1' in metadata: ctrls[18] = metadata['w1'] if 'l2' in metadata: ctrls[19] = metadata['l2'] if 'w2' in metadata: ctrls[20] = metadata['w2'] if 'l3' in metadata: ctrls[21] = metadata['l3'] if 'w3' in metadata: ctrls[22] = metadata['w3'] if 'l4' in metadata: ctrls[23] = metadata['l4'] if 'w4' in metadata: ctrls[24] = metadata['w4'] if 'l5' in metadata: ctrls[25] = metadata['l5'] if 'w5' in metadata: ctrls[26] = metadata['w5'] # save_metadata_json # save_metadata_png if 'img2img' in metadata: ctrls[29] = metadata['img2img'] if 'start_step' in metadata: if ctrls[3] == 'Speed': ctrls[30] = round(metadata['start_step'] / constants.STEPS_SPEED, 2) elif ctrls[3] == 'Quality': ctrls[30] = round(metadata['start_step'] / constants.STEPS_QUALITY, 2) else: ctrls[30] = round(metadata['start_step'] / ctrls[10], 2) if 'denoise' in metadata: ctrls[31] = metadata['denoise'] # seed_random return ctrls def load_prompt_handler(_file, *args): ctrls=list(args) path = _file.name if path.endswith('.json'): with open(path, encoding='utf-8') as json_file: try: json_obj = json.load(json_file) metadata_to_ctrls(json_obj, ctrls) except Exception as e: print(e) finally: json_file.close() elif path.endswith('.png'): with open(path, 'rb') as png_file: image = Image.open(png_file) png_file.close() if 'Comment' in image.info: try: metadata = json.loads(image.info['Comment']) metadata_to_ctrls(metadata, ctrls) except Exception as e: print(e) return ctrls def load_images_handler(files): return gr.update(value=True), list(map(lambda x: x.name, files)), gr.update(selected=0) def output_to_input_handler(gallery): if len(gallery) == 0: return gr.update(value=False), [], gr.update() else: return gr.update(value=True), list(map(lambda x: x['name'], gallery)), gr.update(selected=0) settings = load_settings() shared.gradio_root = gr.Blocks(title=fooocus_version.full_version, css=modules.html.css).queue() with shared.gradio_root: with gr.Row(): with gr.Column(): progress_window = gr.Image(label='Preview', show_label=True, height=640, visible=False) progress_html = gr.HTML(value=modules.html.make_progress_html(32, 'Progress 32%'), visible=False, elem_id='progress-bar', elem_classes='progress-bar') with gr.Column() as gallery_holder: with gr.Tabs(selected=1) as gallery_tabs: with gr.Tab(label='Input', id=0): input_gallery = gr.Gallery(label='Input', show_label=False, object_fit='contain', height=720, visible=True) with gr.Tab(label='Output', id=1): output_gallery = gr.Gallery(label='Output', show_label=False, object_fit='contain', height=720, visible=True) with gr.Row(elem_classes='type_row'): with gr.Column(scale=0.85): prompt = gr.Textbox(show_label=False, placeholder='Type prompt here.', container=False, autofocus=True, elem_classes='type_row', lines=1024, value=settings['prompt']) with gr.Column(scale=0.15, min_width=0): with gr.Row(): img2img_mode = gr.Checkbox(label='Image-2-Image', value=settings['img2img_mode'], elem_classes='type_small_row') with gr.Row(): run_button = gr.Button(label='Generate', value='Generate', elem_classes='type_small_row') with gr.Row(): advanced_checkbox = gr.Checkbox(label='Advanced', value=settings['advanced_mode'], container=False) def verify_input(img2img, gallery_in, gallery_out): if img2img and len(gallery_in) == 0: if len(gallery_out) == 0: gr.Warning('Image-2-Image: disabled (no images available)') return gr.update(value=False), gr.update(), gr.update() else: gr.Info('Image-2-Image: imported output as input') return gr.update(), list(map(lambda x: x['name'], gallery_out)), gr.update() else: return gr.update(), gr.update(), gr.update() with gr.Column(scale=0.5, visible=settings['advanced_mode']) as advanced_column: with gr.Tab(label='Settings'): performance = gr.Radio(label='Performance', choices=['Speed', 'Quality', 'Custom'], value=settings['performance']) custom_steps = gr.Slider(label='Custom Steps', minimum=10, maximum=200, step=1, value=settings['custom_steps'], visible=settings['performance'] == 'Custom') custom_switch = gr.Slider(label='Custom Switch', minimum=0.2, maximum=1.0, step=0.01, value=settings['custom_switch'], visible=settings['performance'] == 'Custom') resolution = gr.Dropdown(label='Resolution (width × height)', choices=list(resolutions.keys()), value=settings['resolution']) style_selection = gr.Dropdown(label='Style', choices=style_keys, value=settings['style']) image_number = gr.Slider(label='Image Number', minimum=1, maximum=32, step=1, value=settings['image_number']) negative_prompt = gr.Textbox(label='Negative Prompt', show_label=True, placeholder="Type prompt here.", value=settings['negative_prompt']) seed_random = gr.Checkbox(label='Random', value=settings['seed_random']) image_seed = gr.Number(label='Seed', value=settings['seed'], precision=0, visible=not settings['seed_random']) img2img_denoise = gr.Slider(label='Image-2-Image Denoise', minimum=0.2, maximum=1.0, step=0.01, value=settings['img2img_denoise']) with gr.Row(): load_prompt_button = gr.UploadButton(label='Load Prompt', file_count='single', file_types=['.json', '.png'], elem_classes='type_small_row', min_width=0) load_images_button = gr.UploadButton(label='Load Image(s)', file_count='multiple', file_types=["image"], elem_classes='type_small_row', min_width=0) output_to_input_button = gr.Button(label='Output to Input', value='Output to Input', elem_classes='type_small_row', min_width=0) def random_checked(r): return gr.update(visible=not r) def refresh_seed(r, s): if r or not isinstance(s, int) or s < 0 or s > 2**63 - 1: return random.randint(0, 2**63 - 1) else: return s seed_random.change(random_checked, inputs=[seed_random], outputs=[image_seed]) def performance_changed(value): return gr.update(visible=value == 'Custom'), gr.update(visible=value == 'Custom') performance.change(fn=performance_changed, inputs=[performance], outputs=[custom_steps, custom_switch]) load_images_button.upload(fn=load_images_handler, inputs=[load_images_button], outputs=[img2img_mode, input_gallery, gallery_tabs]) output_to_input_button.click(output_to_input_handler, inputs=output_gallery, outputs=[img2img_mode, input_gallery, gallery_tabs]) with gr.Tab(label='Models'): with gr.Row(): base_model = gr.Dropdown(label='SDXL Base Model', choices=modules.path.model_filenames, value=settings['base_model'], show_label=True) refiner_model = gr.Dropdown(label='SDXL Refiner', choices=['None'] + modules.path.model_filenames, value=settings['refiner_model'], show_label=True) with gr.Accordion(label='LoRAs', open=True): lora_ctrls = [] for i in range(5): with gr.Row(): lora_model = gr.Dropdown(label=f'SDXL LoRA {i+1}', choices=['None'] + modules.path.lora_filenames, value=settings[f'lora_{i+1}_model']) lora_weight = gr.Slider(label='Weight', minimum=-2, maximum=2, step=0.01, value=settings[f'lora_{i+1}_weight']) lora_ctrls += [lora_model, lora_weight] with gr.Row(): model_refresh = gr.Button(label='Refresh', value='\U0001f504 Refresh All Files', variant='secondary', elem_classes='refresh_button') with gr.Tab(label='Advanced'): cfg = gr.Slider(label='CFG', minimum=1.0, maximum=20.0, step=0.1, value=settings['cfg']) base_clip_skip = gr.Slider(label='Base CLIP Skip', minimum=-10, maximum=-1, step=1, value=settings['base_clip_skip']) refiner_clip_skip = gr.Slider(label='Refiner CLIP Skip', minimum=-10, maximum=-1, step=1, value=settings['refiner_clip_skip']) sampler_name = gr.Dropdown(label='Sampler', choices=['dpmpp_2m_sde_gpu', 'dpmpp_2m_sde', 'dpmpp_3m_sde_gpu', 'dpmpp_3m_sde', 'dpmpp_sde_gpu', 'dpmpp_sde', 'dpmpp_2s_ancestral', 'euler', 'euler_ancestral', 'heun', 'dpm_2', 'dpm_2_ancestral'], value=settings['sampler']) scheduler = gr.Dropdown(label='Scheduler', choices=['karras', 'exponential', 'simple', 'ddim_uniform'], value=settings['scheduler']) img2img_start_step = gr.Slider(label='Image-2-Image Start Step', minimum=0.0, maximum=0.8, step=0.01, value=settings['img2img_start_step']) sharpness = gr.Slider(label='Sampling Sharpness', minimum=0.0, maximum=40.0, step=0.01, value=settings['sharpness']) gr.HTML('\U0001F4D4 Document') def model_refresh_clicked(): modules.path.update_all_model_names() results = [] results += [gr.update(choices=modules.path.model_filenames), gr.update(choices=['None'] + modules.path.model_filenames)] for i in range(5): results += [gr.update(choices=['None'] + modules.path.lora_filenames), gr.update()] return results model_refresh.click(model_refresh_clicked, [], [base_model, refiner_model] + lora_ctrls) with gr.Tab(label='Metadata'): with gr.Row(): save_metadata_json = gr.Checkbox(label='Save Metadata in JSON', value=settings['save_metadata_json']) save_metadata_png = gr.Checkbox(label='Save Metadata in PNG', value=settings['save_metadata_png']) metadata_viewer = gr.JSON(label='Metadata') advanced_checkbox.change(lambda x: gr.update(visible=x), advanced_checkbox, advanced_column) ctrls = [ prompt, negative_prompt, style_selection, performance, resolution, image_number, image_seed, sharpness, sampler_name, scheduler, custom_steps, custom_switch, cfg ] ctrls += [base_model, refiner_model, base_clip_skip, refiner_clip_skip] + lora_ctrls + [save_metadata_json, save_metadata_png, img2img_mode, img2img_start_step, img2img_denoise] load_prompt_button.upload(fn=load_prompt_handler, inputs=[load_prompt_button] + ctrls + [seed_random], outputs=ctrls + [seed_random]) run_button.click(fn=refresh_seed, inputs=[seed_random, image_seed], outputs=image_seed) \ .then(fn=verify_input, inputs=[img2img_mode, input_gallery, output_gallery], outputs=[img2img_mode, input_gallery, output_gallery]) \ .then(fn=generate_clicked, inputs=ctrls + [input_gallery], outputs=[run_button, progress_html, progress_window, gallery_holder, output_gallery, metadata_viewer, gallery_tabs]) parser = argparse.ArgumentParser() parser.add_argument("--port", type=int, default=None, help="Set the listen port.") parser.add_argument("--share", action='store_true', help="Set whether to share on Gradio.") parser.add_argument("--listen", type=str, default=None, metavar="IP", nargs="?", const="0.0.0.0", help="Set the listen interface.") args = parser.parse_args() shared.gradio_root.launch(inbrowser=True, server_name=args.listen, server_port=args.port, share=args.share)