mirror of
https://github.com/vladmandic/automatic
synced 2026-09-19 17:24:32 +02:00
update common ui
This commit is contained in:
@@ -48,3 +48,4 @@ Tech that can be integrated as part of the core workflow...
|
||||
## Random
|
||||
|
||||
- Bunch of stuff: <https://pharmapsychotic.com/tools.html>
|
||||
- <https://github.com/AUTOMATIC1111/stable-diffusion-webui/compare/89f9faa...20ae71f>
|
||||
|
||||
Submodule extensions-builtin/sd-extension-system-info updated: 2a811ca0c8...8046b15445
Submodule extensions-builtin/sd-webui-controlnet updated: 2e0dc37d22...09cb9a32d1
@@ -44,6 +44,8 @@ group.add_argument('--use-directml', default = False, action='store_true', help
|
||||
group.add_argument("--use-cuda", default=False, action='store_true', help="Force use nVidia CUDA backend, default: %(default)s")
|
||||
group.add_argument("--use-rocm", default=False, action='store_true', help="Force use AMD ROCm backend, default: %(default)s")
|
||||
group.add_argument('--subpath', type=str, help='Customize the URL subpath for usage with reverse proxy')
|
||||
group.add_argument('--backend', type=str, choices=[None, 'original', 'diffusers'], default=None, required=False, help='force backend type')
|
||||
|
||||
|
||||
# removed args are added here as hidden in fixed format for compatbility reasons
|
||||
group.add_argument("-f", action='store_true', help=argparse.SUPPRESS) # allows running as root; implemented outside of webui
|
||||
|
||||
@@ -24,9 +24,6 @@ def run_pnginfo(image):
|
||||
for key, text in items.items():
|
||||
if key != 'UserComment':
|
||||
info += f"<div><b>{html.escape(str(key))}</b>: {html.escape(str(text))}</div>"
|
||||
if len(info) == 0:
|
||||
message = "Nothing found in the image."
|
||||
info = f"<div><p>{message}<p></div>"
|
||||
return '', geninfo, info
|
||||
|
||||
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@ import modules.scripts
|
||||
from modules import sd_samplers, shared
|
||||
from modules.generation_parameters_copypaste import create_override_settings_dict
|
||||
from modules.processing import Processed, StableDiffusionProcessingImg2Img, process_images
|
||||
from modules.ui import plaintext_to_html
|
||||
from modules.ui import plaintext_to_html, infotext_to_html
|
||||
import modules.processing as processing
|
||||
from modules.memstats import memory_stats
|
||||
|
||||
@@ -165,4 +165,4 @@ def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_s
|
||||
p.close()
|
||||
generation_info_js = processed.js()
|
||||
shared.log.debug(f'Processed: {len(processed.images)} Memory: {memory_stats()} img')
|
||||
return processed.images, generation_info_js, plaintext_to_html(processed.info), plaintext_to_html(processed.comments)
|
||||
return processed.images, generation_info_js, infotext_to_html(processed.info), plaintext_to_html(processed.comments)
|
||||
|
||||
@@ -48,8 +48,8 @@ def run_postprocessing(extras_mode, image, image_folder: List[tempfile.NamedTemp
|
||||
outpath = output_dir
|
||||
else:
|
||||
outpath = opts.outdir_samples or opts.outdir_extras_samples
|
||||
infotext = ''
|
||||
for image, name, ext in zip(image_data, image_names, image_ext):
|
||||
infotext = ''
|
||||
if shared.state.interrupted:
|
||||
shared.log.debug('Postprocess interrupted')
|
||||
break
|
||||
@@ -62,10 +62,12 @@ def run_postprocessing(extras_mode, image, image_folder: List[tempfile.NamedTemp
|
||||
basename = os.path.splitext(os.path.basename(name))[0]
|
||||
else:
|
||||
basename = ''
|
||||
infotext = ", ".join([k if k == v else f'{k}: {generation_parameters_copypaste.quote(v)}' for k, v in pp.info.items() if v is not None])
|
||||
_geninfo, items = images.read_info_from_image(image)
|
||||
for k, v in items.items():
|
||||
pp.image.info[k] = v
|
||||
if 'parameters' in items:
|
||||
infotext = items['parameters'] + ', '
|
||||
infotext = infotext + ", ".join([k if k == v else f'{k}: {generation_parameters_copypaste.quote(v)}' for k, v in pp.info.items() if v is not None])
|
||||
pp.image.info["postprocessing"] = infotext
|
||||
if save_output:
|
||||
images.save_image(pp.image, path=outpath, basename=basename, seed=None, prompt=None, extension=ext or opts.samples_format, info=infotext, short_filename=True, no_prompt=True, grid=False, pnginfo_section_name="extras", existing_info=pp.image.info, forced_filename=None)
|
||||
@@ -73,7 +75,7 @@ def run_postprocessing(extras_mode, image, image_folder: List[tempfile.NamedTemp
|
||||
outputs.append(pp.image)
|
||||
|
||||
devices.torch_gc()
|
||||
return outputs, ui_common.plaintext_to_html(infotext), ''
|
||||
return outputs, ui_common.infotext_to_html(infotext), pp.image.info
|
||||
|
||||
|
||||
def run_extras(extras_mode, resize_mode, image, image_folder, input_dir, output_dir, show_extras_results, gfpgan_visibility, codeformer_visibility, codeformer_weight, upscaling_resize, upscaling_resize_w, upscaling_resize_h, upscaling_crop, extras_upscaler_1, extras_upscaler_2, extras_upscaler_2_visibility, upscale_first: bool, save_output: bool = True): #pylint: disable=unused-argument
|
||||
|
||||
@@ -19,7 +19,7 @@ from installer import git_commit
|
||||
import modules.sd_hijack
|
||||
from modules import devices, prompt_parser, masking, sd_samplers, lowvram, generation_parameters_copypaste, script_callbacks, extra_networks, sd_vae_approx, scripts # pylint: disable=unused-import
|
||||
from modules.sd_hijack import model_hijack
|
||||
from modules.shared import opts, cmd_opts, state, log
|
||||
from modules.shared import opts, cmd_opts, state, log, backend, Backend
|
||||
import modules.shared as shared
|
||||
import modules.paths as paths
|
||||
import modules.face_restoration
|
||||
@@ -220,7 +220,7 @@ class StableDiffusionProcessing:
|
||||
source_image = devices.cond_cast_float(source_image)
|
||||
# HACK: Using introspection as the Depth2Image model doesn't appear to uniquely
|
||||
# identify itself with a field common to all models. The conditioning_key is also hybrid.
|
||||
if opts.sd_backend == 'Diffusers': # TODO: Diffusers img2img_image_conditioning
|
||||
if backend == Backend.DIFFUSERS: # TODO: Diffusers img2img_image_conditioning
|
||||
return latent_image.new_zeros(latent_image.shape[0], 5, 1, 1)
|
||||
if isinstance(self.sd_model, LatentDepth2ImageDiffusion):
|
||||
return self.depth2img_image_conditioning(source_image)
|
||||
@@ -522,7 +522,7 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed:
|
||||
assert p.prompt is not None
|
||||
seed = get_fixed_seed(p.seed)
|
||||
subseed = get_fixed_seed(p.subseed)
|
||||
if opts.sd_backend == 'Original':
|
||||
if backend == Backend.ORIGINAL:
|
||||
modules.sd_hijack.model_hijack.apply_circular(p.tiling)
|
||||
modules.sd_hijack.model_hijack.clear_comments()
|
||||
comments = {}
|
||||
@@ -573,11 +573,11 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed:
|
||||
cache[0] = (required_prompts, steps)
|
||||
return cache[1]
|
||||
|
||||
ema_scope_context = p.sd_model.ema_scope if opts.sd_backend == 'Original' else nullcontext
|
||||
ema_scope_context = p.sd_model.ema_scope if backend == Backend.ORIGINAL else nullcontext
|
||||
with torch.no_grad(), ema_scope_context():
|
||||
with devices.autocast():
|
||||
p.init(p.all_prompts, p.all_seeds, p.all_subseeds)
|
||||
if shared.opts.live_previews_enable and opts.show_progress_type == "Approx NN" and opts.sd_backend == 'Original':
|
||||
if shared.opts.live_previews_enable and opts.show_progress_type == "Approx NN" and backend == Backend.ORIGINAL:
|
||||
sd_vae_approx.model()
|
||||
if state.job_count == -1:
|
||||
state.job_count = p.n_iter
|
||||
@@ -618,7 +618,7 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed:
|
||||
if p.n_iter > 1:
|
||||
shared.state.job = f"Batch {n+1} out of {p.n_iter}"
|
||||
|
||||
if opts.sd_backend == 'Original':
|
||||
if backend == Backend.ORIGINAL:
|
||||
uc = get_conds_with_caching(prompt_parser.get_learned_conditioning, negative_prompts, p.steps * step_multiplier, cached_uc)
|
||||
c = get_conds_with_caching(prompt_parser.get_multicond_learned_conditioning, prompts, p.steps * step_multiplier, cached_c)
|
||||
if len(model_hijack.comments) > 0:
|
||||
@@ -671,7 +671,7 @@ def process_images_inner(p: StableDiffusionProcessing) -> Processed:
|
||||
|
||||
for i, x_sample in enumerate(x_samples_ddim):
|
||||
p.batch_index = i
|
||||
if opts.sd_backend == 'Original':
|
||||
if backend == Backend.ORIGINAL:
|
||||
x_sample = 255. * np.moveaxis(x_sample.cpu().numpy(), 0, 2)
|
||||
x_sample = x_sample.astype(np.uint8)
|
||||
else:
|
||||
|
||||
+14
-8
@@ -35,7 +35,7 @@ class CheckpointInfo:
|
||||
self.hash = None
|
||||
self.filename = filename
|
||||
abspath = os.path.abspath(filename)
|
||||
if shared.opts.sd_backend == 'Original':
|
||||
if shared.backend == shared.Backend.ORIGINAL:
|
||||
if shared.opts.ckpt_dir is not None and abspath.startswith(shared.opts.ckpt_dir):
|
||||
name = abspath.replace(shared.opts.ckpt_dir, '')
|
||||
elif abspath.startswith(model_path):
|
||||
@@ -104,7 +104,7 @@ def checkpoint_tiles():
|
||||
def list_models():
|
||||
checkpoints_list.clear()
|
||||
checkpoint_aliases.clear()
|
||||
if shared.opts.sd_backend == 'Original':
|
||||
if shared.backend == shared.Backend.ORIGINAL:
|
||||
model_list = modelloader.load_models(model_path=os.path.join(models_path, 'Stable-diffusion'), model_url=None, command_path=shared.opts.ckpt_dir, ext_filter=[".ckpt", ".safetensors"], download_name=None, ext_blacklist=[".vae.ckpt", ".vae.safetensors"])
|
||||
else:
|
||||
model_list = modelloader.load_diffusers(model_path=os.path.join(models_path, 'Diffusers'), command_path=shared.opts.diffusers_dir)
|
||||
@@ -113,7 +113,7 @@ def list_models():
|
||||
if checkpoint_info.name is not None:
|
||||
checkpoint_info.register()
|
||||
if shared.cmd_opts.ckpt is not None:
|
||||
if not os.path.exists(shared.cmd_opts.ckpt) and shared.opts.sd_backend == 'Original':
|
||||
if not os.path.exists(shared.cmd_opts.ckpt) and shared.backend == shared.Backend.ORIGINAL:
|
||||
if shared.cmd_opts.ckpt.lower() != "none":
|
||||
shared.log.warning(f"Requested checkpoint not found: {shared.cmd_opts.ckpt}")
|
||||
else:
|
||||
@@ -227,7 +227,7 @@ def read_metadata_from_safetensors(filename):
|
||||
|
||||
|
||||
def read_state_dict(checkpoint_file, map_location=None): # pylint: disable=unused-argument
|
||||
if shared.opts.sd_backend == 'Diffusers':
|
||||
if shared.backend == shared.Backend.DIFFUSERS:
|
||||
return None
|
||||
try:
|
||||
pl_sd = None
|
||||
@@ -376,9 +376,9 @@ class SdModelData:
|
||||
if self.sd_model is None:
|
||||
with self.lock:
|
||||
try:
|
||||
if shared.opts.sd_backend == 'Original':
|
||||
if shared.backend == shared.Backend.ORIGINAL:
|
||||
load_model()
|
||||
elif shared.opts.sd_backend == 'Diffusers':
|
||||
elif shared.backend == shared.Backend.DIFFUSERS:
|
||||
load_diffuser()
|
||||
else:
|
||||
shared.log.error(f"Unknown Stable Diffusion backend: {shared.opts.sd_backend}")
|
||||
@@ -429,6 +429,12 @@ def load_diffuser(checkpoint_info=None, already_loaded_state_dict=None, timer=No
|
||||
shared.log.info(f'Loading diffuser model: {checkpoint_info.filename}')
|
||||
scheduler = diffusers.UniPCMultistepScheduler.from_pretrained(checkpoint_info.filename, subfolder="scheduler")
|
||||
sd_model = diffusers.DiffusionPipeline.from_pretrained(checkpoint_info.filename, scheduler=scheduler, **diffusor_config)
|
||||
if shared.cmd_opts.medvram:
|
||||
sd_model.enable_model_cpu_offload()
|
||||
if shared.cmd_opts.lowvram:
|
||||
sd_model.enable_sequential_cpu_offload()
|
||||
if shared.opts.cross_attention_optimization == "xFormers":
|
||||
sd_model.enable_xformers_memory_efficient_attention()
|
||||
sd_model.sd_checkpoint_info = checkpoint_info
|
||||
sd_model.sd_model_checkpoint = checkpoint_info.filename
|
||||
sd_model.sd_model_hash = checkpoint_info.hash
|
||||
@@ -550,7 +556,7 @@ def reload_model_weights(sd_model=None, info=None):
|
||||
if sd_model is None or checkpoint_config != sd_model.used_config:
|
||||
del sd_model
|
||||
checkpoints_loaded.clear()
|
||||
if shared.opts.sd_backend == 'Original':
|
||||
if shared.backend == shared.Backend.ORIGINAL:
|
||||
load_model(checkpoint_info, already_loaded_state_dict=state_dict, timer=timer)
|
||||
else:
|
||||
load_diffuser(checkpoint_info, already_loaded_state_dict=state_dict, timer=timer)
|
||||
@@ -575,7 +581,7 @@ def unload_model_weights(sd_model=None, _info=None):
|
||||
from modules import sd_hijack
|
||||
if model_data.sd_model:
|
||||
model_data.sd_model.to(devices.cpu)
|
||||
if shared.opts.sd_backend == 'Original':
|
||||
if shared.backend == shared.Backend.ORIGINAL:
|
||||
sd_hijack.model_hijack.undo_hijack(model_data.sd_model)
|
||||
model_data.sd_model = None
|
||||
sd_model = None
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
from modules import sd_samplers_compvis, sd_samplers_kdiffusion, sd_samplers_diffusors, shared
|
||||
from modules.sd_samplers_common import samples_to_image_grid, sample_to_image # pylint: disable=unused-import
|
||||
from modules.shared import opts
|
||||
from modules.shared import backend, Backend
|
||||
|
||||
if opts.sd_backend == 'Original':
|
||||
if backend == Backend.ORIGINAL:
|
||||
all_samplers = [
|
||||
*sd_samplers_kdiffusion.samplers_data_k_diffusion,
|
||||
*sd_samplers_compvis.samplers_data_compvis,
|
||||
@@ -23,7 +23,7 @@ def create_sampler(name, model):
|
||||
else:
|
||||
config = all_samplers[0]
|
||||
assert config is not None, f'bad sampler name: {name}'
|
||||
if opts.sd_backend == 'Original':
|
||||
if backend == Backend.ORIGINAL:
|
||||
sampler = config.constructor(model)
|
||||
sampler.config = config
|
||||
return sampler
|
||||
|
||||
+13
-1
@@ -4,10 +4,10 @@ import time
|
||||
import json
|
||||
import datetime
|
||||
import urllib.request
|
||||
from enum import Enum
|
||||
import gradio as gr
|
||||
import tqdm
|
||||
import requests
|
||||
# from ldm.models.diffusion.ddpm import LatentDiffusion
|
||||
from modules import errors, ui_components, shared_items, cmd_args
|
||||
from modules.paths_internal import models_path, script_path, data_path, sd_configs_path, sd_default_config, sd_model_file, default_sd_model_file, extensions_dir, extensions_builtin_dir # pylint: disable=W0611
|
||||
import modules.interrogate
|
||||
@@ -72,6 +72,11 @@ ui_reorder_categories = [
|
||||
]
|
||||
|
||||
|
||||
class Backend(Enum):
|
||||
ORIGINAL = 1
|
||||
DIFFUSERS = 2
|
||||
|
||||
|
||||
def reload_hypernetworks():
|
||||
from modules.hypernetworks import hypernetwork
|
||||
global hypernetworks # pylint: disable=W0603
|
||||
@@ -634,6 +639,13 @@ opts = Options()
|
||||
config_filename = cmd_opts.config
|
||||
opts.load(config_filename)
|
||||
cmd_opts = cmd_args.compatibility_args(opts, cmd_opts)
|
||||
if cmd_opts.backend == 'diffusers':
|
||||
log.info('Overriding backend to Diffusers')
|
||||
opts.data['sd_backend'] = 'Diffusers'
|
||||
if cmd_opts.backend == 'original':
|
||||
log.info('Overriding backend to Diffusers')
|
||||
opts.data['sd_backend'] = 'Original'
|
||||
backend = Backend.DIFFUSERS if opts.sd_backend == 'Diffusers' else Backend.ORIGINAL
|
||||
|
||||
prompt_styles = modules.styles.StyleDatabase(opts.styles_dir)
|
||||
cmd_opts.disable_extension_access = (cmd_opts.share or cmd_opts.listen or (cmd_opts.server_name or False)) and not cmd_opts.insecure
|
||||
|
||||
@@ -207,7 +207,7 @@ class EmbeddingDatabase:
|
||||
continue
|
||||
|
||||
def load_textual_inversion_embeddings(self, force_reload=False):
|
||||
if shared.opts.sd_backend == 'Diffusers': # TODO Diffusers
|
||||
if shared.backend == shared.Backend.DIFFUSERS: # TODO Diffusers
|
||||
return
|
||||
if not force_reload:
|
||||
need_reload = False
|
||||
|
||||
+2
-2
@@ -3,7 +3,7 @@ from modules import sd_samplers, shared
|
||||
from modules.generation_parameters_copypaste import create_override_settings_dict
|
||||
from modules.processing import StableDiffusionProcessingTxt2Img, process_images
|
||||
# from modules.shared import opts, sd_model, debug
|
||||
from modules.ui import plaintext_to_html
|
||||
from modules.ui import plaintext_to_html, infotext_to_html
|
||||
from modules.memstats import memory_stats
|
||||
|
||||
|
||||
@@ -58,4 +58,4 @@ def txt2img(id_task: str, prompt: str, negative_prompt: str, prompt_styles, step
|
||||
p.close()
|
||||
generation_info_js = processed.js()
|
||||
shared.log.debug(f'Processed: {len(processed.images)} Memory: {memory_stats()} txt')
|
||||
return processed.images, generation_info_js, plaintext_to_html(processed.info), plaintext_to_html(processed.comments)
|
||||
return processed.images, generation_info_js, infotext_to_html(processed.info), plaintext_to_html(processed.comments)
|
||||
|
||||
+6
-2
@@ -13,7 +13,7 @@ from modules.call_queue import wrap_gradio_gpu_call, wrap_queued_call, wrap_grad
|
||||
from modules import sd_hijack, sd_models, script_callbacks, ui_extensions, deepbooru, sd_vae, extra_networks, ui_common, ui_postprocessing
|
||||
from modules.ui_components import FormRow, FormColumn, FormGroup, ToolButton, FormHTML # pylint: disable=unused-import
|
||||
from modules.paths import script_path, data_path
|
||||
from modules.shared import opts, cmd_opts
|
||||
from modules.shared import opts, cmd_opts, backend, Backend
|
||||
from modules import prompt_parser
|
||||
import modules.codeformer_model
|
||||
import modules.generation_parameters_copypaste as parameters_copypaste
|
||||
@@ -63,6 +63,10 @@ def plaintext_to_html(text):
|
||||
return ui_common.plaintext_to_html(text)
|
||||
|
||||
|
||||
def infotext_to_html(text):
|
||||
return ui_common.infotext_to_html(text)
|
||||
|
||||
|
||||
def send_gradio_gallery_to_image(x):
|
||||
if len(x) == 0:
|
||||
return None
|
||||
@@ -204,7 +208,7 @@ def update_token_counter(text, steps):
|
||||
prompt_schedules = [[[steps, text]]]
|
||||
flat_prompts = reduce(lambda list1, list2: list1+list2, prompt_schedules)
|
||||
prompts = [prompt_text for step, prompt_text in flat_prompts]
|
||||
if opts.sd_backend == 'Original':
|
||||
if backend == Backend.ORIGINAL:
|
||||
token_count, max_length = max([sd_hijack.model_hijack.get_prompt_lengths(prompt) for prompt in prompts], key=lambda args: args[0])
|
||||
else:
|
||||
tokenizer = modules.shared.sd_model.tokenizer
|
||||
|
||||
+102
-101
@@ -1,6 +1,7 @@
|
||||
import json
|
||||
import html
|
||||
import os
|
||||
import shutil
|
||||
import platform
|
||||
import subprocess
|
||||
import gradio as gr
|
||||
@@ -8,6 +9,7 @@ from modules import call_queue, shared
|
||||
from modules.generation_parameters_copypaste import image_from_url_text
|
||||
import modules.images
|
||||
|
||||
|
||||
folder_symbol = '\U0001f4c2' # 📂
|
||||
|
||||
|
||||
@@ -16,60 +18,99 @@ def update_generation_info(generation_info, html_info, img_index):
|
||||
generation_info = json.loads(generation_info)
|
||||
if img_index < 0 or img_index >= len(generation_info["infotexts"]):
|
||||
return html_info, gr.update()
|
||||
return plaintext_to_html(generation_info["infotexts"][img_index]), gr.update()
|
||||
html_text = infotext_to_html(generation_info["infotexts"][img_index])
|
||||
return html_text, gr.update()
|
||||
except Exception:
|
||||
pass
|
||||
# if the json parse or anything else fails, just return the old html_info
|
||||
return html_info, gr.update()
|
||||
|
||||
|
||||
def plaintext_to_html(text):
|
||||
text = "<p>" + "<br>\n".join([f"{html.escape(x)}" for x in text.split('\n')]) + "</p>"
|
||||
return text
|
||||
res = '<p class="plaintext">' + "<br>\n".join([f"{html.escape(x)}" for x in text.split('\n')]) + '</p>'
|
||||
return res
|
||||
|
||||
|
||||
def infotext_to_html(text):
|
||||
res = '<p class="html_info">Prompt: ' + html.escape(text).replace('\n', '<br>') + '</p>'
|
||||
sections = res.split('Steps:') # before and after prompt+negprompt'
|
||||
if len(sections) > 1:
|
||||
res = sections[0] + '<br>Steps: ' + sections[1].strip().replace(', ', ' | ')
|
||||
res = res.replace('<br><br>', '<br>')
|
||||
return res
|
||||
|
||||
|
||||
def delete_files(js_data, images, _do_make_zip, index):
|
||||
try:
|
||||
data = json.loads(js_data)
|
||||
except Exception:
|
||||
data = { 'index_of_first_image': 0 }
|
||||
start_index = 0
|
||||
if index > -1 and shared.opts.save_selected_only and (index >= data['index_of_first_image']):
|
||||
images = [images[index]]
|
||||
start_index = index
|
||||
filenames = []
|
||||
filenames = []
|
||||
fullfns = []
|
||||
for _image_index, filedata in enumerate(images, start_index):
|
||||
if 'name' in filedata and os.path.isfile(filedata['name']):
|
||||
fullfn = filedata['name']
|
||||
filenames.append(os.path.basename(fullfn))
|
||||
try:
|
||||
os.remove(fullfn)
|
||||
fullfns.append(fullfn)
|
||||
shared.log.info(f"Deleting image: {fullfn}")
|
||||
except Exception as e:
|
||||
shared.log.error(f'Error deleting file: {fullfn} {e}')
|
||||
images = [image for image in images if image['name'] not in fullfns]
|
||||
return images, plaintext_to_html(f"Deleted: {filenames[0] if len(filenames) > 0 else 'none'}")
|
||||
|
||||
|
||||
def save_files(js_data, images, do_make_zip, index):
|
||||
if js_data is None or len(js_data) == 0:
|
||||
return
|
||||
filenames = []
|
||||
fullfns = []
|
||||
os.makedirs(shared.opts.outdir_save, exist_ok=True)
|
||||
|
||||
#quick dictionary to class object conversion. Its necessary due apply_filename_pattern requiring it
|
||||
class MyObject:
|
||||
class MyObject: #quick dictionary to class object conversion. Its necessary due apply_filename_pattern requiring it
|
||||
def __init__(self, d=None):
|
||||
if d is not None:
|
||||
for key, value in d.items():
|
||||
setattr(self, key, value)
|
||||
|
||||
data = json.loads(js_data)
|
||||
try:
|
||||
data = json.loads(js_data)
|
||||
except Exception:
|
||||
data = { 'index_of_first_image': 0 }
|
||||
p = MyObject(data)
|
||||
path = shared.opts.outdir_save
|
||||
save_to_dirs = shared.opts.use_save_to_dirs_for_ui
|
||||
extension: str = shared.opts.samples_format
|
||||
start_index = 0
|
||||
if index > -1 and shared.opts.save_selected_only and (index >= data["index_of_first_image"]): # ensures we are looking at a specific non-grid picture, and we have save_selected_only
|
||||
if index > -1 and shared.opts.save_selected_only and (index >= data['index_of_first_image']): # ensures we are looking at a specific non-grid picture, and we have save_selected_only # pylint: disable=no-member
|
||||
images = [images[index]]
|
||||
start_index = index
|
||||
os.makedirs(shared.opts.outdir_save, exist_ok=True)
|
||||
filenames = []
|
||||
fullfns = []
|
||||
for image_index, filedata in enumerate(images, start_index):
|
||||
image = image_from_url_text(filedata)
|
||||
is_grid = image_index < p.index_of_first_image # pylint: disable=no-member
|
||||
i = 0 if is_grid else (image_index - p.index_of_first_image) # pylint: disable=no-member
|
||||
if len(p.all_seeds) <= i: # pylint: disable=no-member
|
||||
p.all_seeds.append(p.seed) # pylint: disable=no-member
|
||||
if len(p.all_prompts) <= i: # pylint: disable=no-member
|
||||
p.all_prompts.append(p.prompt) # pylint: disable=no-member
|
||||
fullfn, txt_fullfn = modules.images.save_image(image, path, "", seed=p.all_seeds[i], prompt=p.all_prompts[i], extension=extension, info=p.infotexts[image_index], grid=is_grid, p=p, save_to_dirs=save_to_dirs) # pylint: disable=no-member
|
||||
if fullfn is None:
|
||||
continue
|
||||
filename = os.path.relpath(fullfn, path)
|
||||
filenames.append(filename)
|
||||
fullfns.append(fullfn)
|
||||
if txt_fullfn:
|
||||
filenames.append(os.path.basename(txt_fullfn))
|
||||
fullfns.append(txt_fullfn)
|
||||
if 'name' in filedata and os.path.isfile(filedata['name']):
|
||||
fullfn = filedata['name']
|
||||
filenames.append(os.path.basename(fullfn))
|
||||
fullfns.append(fullfn)
|
||||
shutil.copy(fullfn, shared.opts.outdir_save)
|
||||
shared.log.info(f"Copying image: {fullfn} -> {shared.opts.outdir_save}")
|
||||
else:
|
||||
image = image_from_url_text(filedata)
|
||||
is_grid = image_index < p.index_of_first_image # pylint: disable=no-member
|
||||
i = 0 if is_grid else (image_index - p.index_of_first_image) # pylint: disable=no-member
|
||||
if len(p.all_seeds) <= i: # pylint: disable=no-member
|
||||
p.all_seeds.append(p.seed) # pylint: disable=no-member
|
||||
if len(p.all_prompts) <= i: # pylint: disable=no-member
|
||||
p.all_prompts.append(p.prompt) # pylint: disable=no-member
|
||||
fullfn, txt_fullfn = modules.images.save_image(image, shared.opts.outdir_save, "", seed=p.all_seeds[i], prompt=p.all_prompts[i], extension=shared.opts.samples_format, info=p.infotexts[image_index], grid=is_grid, p=p, save_to_dirs=shared.opts.use_save_to_dirs_for_ui) # pylint: disable=no-member
|
||||
if fullfn is None:
|
||||
continue
|
||||
filename = os.path.relpath(fullfn, shared.opts.outdir_save)
|
||||
filenames.append(filename)
|
||||
fullfns.append(fullfn)
|
||||
if txt_fullfn:
|
||||
filenames.append(os.path.basename(txt_fullfn))
|
||||
fullfns.append(txt_fullfn)
|
||||
if do_make_zip:
|
||||
zip_filepath = os.path.join(path, "images.zip")
|
||||
zip_filepath = os.path.join(shared.opts.outdir_save, "images.zip")
|
||||
from zipfile import ZipFile
|
||||
with ZipFile(zip_filepath, "w") as zip_file:
|
||||
for i in range(len(fullfns)):
|
||||
@@ -105,87 +146,47 @@ def create_output_panel(tabname, outdir):
|
||||
with gr.Group(elem_id=f"{tabname}_gallery_container"):
|
||||
result_gallery = gr.Gallery(value=['html/logo.png'], label='Output', show_label=False, elem_id=f"{tabname}_gallery").style(preview=False, container=False, columns=[1,2,3,4,5,6]) # <576px, <768px, <992px, <1200px, <1400px, >1400px
|
||||
|
||||
generation_info = None
|
||||
with gr.Column():
|
||||
with gr.Row(elem_id=f"image_buttons_{tabname}", elem_classes="image-buttons"):
|
||||
open_folder_button = gr.Button('show', visible=not shared.cmd_opts.hide_ui_dir_config)
|
||||
|
||||
if tabname != "extras":
|
||||
save = gr.Button('save', elem_id=f'save_{tabname}')
|
||||
save_zip = gr.Button('zip', elem_id=f'save_zip_{tabname}')
|
||||
|
||||
save = gr.Button('save', elem_id=f'save_{tabname}')
|
||||
save_zip = gr.Button('zip', elem_id=f'save_zip_{tabname}')
|
||||
delete = gr.Button('delete', elem_id=f'delete_{tabname}')
|
||||
buttons = parameters_copypaste.create_buttons(["img2img", "inpaint", "extras"])
|
||||
|
||||
open_folder_button.click(
|
||||
fn=lambda: open_folder(shared.opts.outdir_samples or outdir),
|
||||
inputs=[],
|
||||
outputs=[],
|
||||
)
|
||||
|
||||
if tabname != "extras":
|
||||
download_files = gr.File(None, file_count="multiple", interactive=False, show_label=False, visible=False, elem_id=f'download_files_{tabname}')
|
||||
|
||||
with gr.Group():
|
||||
html_info = gr.HTML(elem_id=f'html_info_{tabname}', elem_classes="infotext")
|
||||
html_log = gr.HTML(elem_id=f'html_log_{tabname}')
|
||||
|
||||
generation_info = gr.Textbox(visible=False, elem_id=f'generation_info_{tabname}')
|
||||
if tabname == 'txt2img' or tabname == 'img2img':
|
||||
generation_info_button = gr.Button(visible=False, elem_id=f"{tabname}_generation_info_button")
|
||||
generation_info_button.click(
|
||||
fn=update_generation_info,
|
||||
_js="function(x, y, z){ return [x, y, selected_gallery_index()] }",
|
||||
inputs=[generation_info, html_info, html_info],
|
||||
outputs=[html_info, html_info],
|
||||
show_progress=False,
|
||||
)
|
||||
|
||||
save.click(
|
||||
fn=call_queue.wrap_gradio_call(save_files),
|
||||
_js="(x, y, z, w) => [x, y, false, selected_gallery_index()]",
|
||||
inputs=[
|
||||
generation_info,
|
||||
result_gallery,
|
||||
html_info,
|
||||
html_info,
|
||||
],
|
||||
outputs=[
|
||||
download_files,
|
||||
html_log,
|
||||
],
|
||||
show_progress=False,
|
||||
)
|
||||
|
||||
save_zip.click(
|
||||
fn=call_queue.wrap_gradio_call(save_files),
|
||||
_js="(x, y, z, w) => [x, y, true, selected_gallery_index()]",
|
||||
inputs=[
|
||||
generation_info,
|
||||
result_gallery,
|
||||
html_info,
|
||||
html_info,
|
||||
],
|
||||
outputs=[
|
||||
download_files,
|
||||
html_log,
|
||||
]
|
||||
)
|
||||
|
||||
else:
|
||||
html_info_x = gr.HTML(elem_id=f'html_info_x_{tabname}')
|
||||
open_folder_button.click(fn=lambda: open_folder(shared.opts.outdir_samples or outdir), inputs=[], outputs=[])
|
||||
download_files = gr.File(None, file_count="multiple", interactive=False, show_label=False, visible=False, elem_id=f'download_files_{tabname}')
|
||||
with gr.Group():
|
||||
html_info = gr.HTML(elem_id=f'html_info_{tabname}', elem_classes="infotext")
|
||||
html_log = gr.HTML(elem_id=f'html_log_{tabname}')
|
||||
generation_info = gr.Textbox(visible=False, elem_id=f'generation_info_{tabname}')
|
||||
generation_info_button = gr.Button(visible=False, elem_id=f"{tabname}_generation_info_button")
|
||||
generation_info_button.click(fn=update_generation_info, _js="function(x, y, z){ return [x, y, selected_gallery_index()] }", show_progress=False,
|
||||
inputs=[generation_info, html_info, html_info],
|
||||
outputs=[html_info, html_info],
|
||||
)
|
||||
save.click(fn=call_queue.wrap_gradio_call(save_files), _js="(x, y, z, w) => [x, y, false, selected_gallery_index()]", show_progress=False,
|
||||
inputs=[generation_info, result_gallery, html_info, html_info],
|
||||
outputs=[download_files, html_log],
|
||||
)
|
||||
save_zip.click(fn=call_queue.wrap_gradio_call(save_files), _js="(x, y, z, w) => [x, y, true, selected_gallery_index()]",
|
||||
inputs=[generation_info, result_gallery, html_info, html_info],
|
||||
outputs=[download_files, html_log],
|
||||
)
|
||||
delete.click(fn=call_queue.wrap_gradio_call(delete_files), _js="(x, y, z, w) => [x, y, true, selected_gallery_index()]",
|
||||
inputs=[generation_info, result_gallery, html_info, html_info],
|
||||
outputs=[result_gallery, html_log],
|
||||
)
|
||||
|
||||
paste_field_names = []
|
||||
if tabname == "txt2img":
|
||||
paste_field_names = modules.scripts.scripts_txt2img.paste_field_names
|
||||
elif tabname == "img2img":
|
||||
paste_field_names = modules.scripts.scripts_img2img.paste_field_names
|
||||
|
||||
else:
|
||||
paste_field_names = []
|
||||
for paste_tabname, paste_button in buttons.items():
|
||||
parameters_copypaste.register_paste_params_button(parameters_copypaste.ParamBinding(
|
||||
paste_button=paste_button, tabname=paste_tabname, source_tabname="txt2img" if tabname == "txt2img" else None, source_image_component=result_gallery,
|
||||
paste_button=paste_button, tabname=paste_tabname, source_tabname=("txt2img" if tabname == "txt2img" else None), source_image_component=result_gallery,
|
||||
paste_field_names=paste_field_names
|
||||
))
|
||||
|
||||
return result_gallery, generation_info if tabname != "extras" else html_info_x, html_info, html_log
|
||||
return result_gallery, generation_info, html_info, html_log
|
||||
|
||||
@@ -3,13 +3,18 @@ from modules import scripts_postprocessing, scripts, shared, gfpgan_model, codef
|
||||
import modules.generation_parameters_copypaste as parameters_copypaste
|
||||
from modules.call_queue import wrap_gradio_gpu_call, wrap_queued_call, wrap_gradio_call # pylint: disable=unused-import
|
||||
from modules.extras import run_pnginfo
|
||||
from modules.ui_common import infotext_to_html
|
||||
|
||||
|
||||
def wrap_pnginfo(image):
|
||||
_, geninfo, info = run_pnginfo(image)
|
||||
return '', infotext_to_html(geninfo), info
|
||||
|
||||
|
||||
def submit_click(tab_index, extras_image, image_batch, extras_batch_input_dir, extras_batch_output_dir, show_extras_results, *script_inputs):
|
||||
result_images, html_info_x, html_info = postprocessing.run_postprocessing(tab_index, extras_image, image_batch, extras_batch_input_dir, extras_batch_output_dir, show_extras_results, *script_inputs)
|
||||
if result_images is not None and len(result_images) > 0:
|
||||
_html_info, _generation_info, html_info_x = run_pnginfo(result_images[0])
|
||||
return result_images, html_info_x, html_info
|
||||
|
||||
result_images, geninfo, _js_info = postprocessing.run_postprocessing(tab_index, extras_image, image_batch, extras_batch_input_dir, extras_batch_output_dir, show_extras_results, *script_inputs)
|
||||
return result_images, geninfo, '{}', ''
|
||||
|
||||
|
||||
def create_ui():
|
||||
@@ -37,32 +42,21 @@ def create_ui():
|
||||
skip = gr.Button('Skip', elem_id=f"{id_part}_skip", variant='secondary')
|
||||
skip.click(fn=lambda: shared.state.skip(), inputs=[], outputs=[])
|
||||
interrupt.click(fn=lambda: shared.state.interrupt(), inputs=[], outputs=[])
|
||||
result_images, html_info_x, html_info, _html_log = ui_common.create_output_panel("extras", shared.opts.outdir_extras_samples)
|
||||
html_info = gr.HTML(elem_id="pnginfo_html_info")
|
||||
generation_info = gr.Textbox(elem_id="pnginfo_generation_info", label="Parameters", visible=False)
|
||||
generation_info_pretty = gr.Textbox(elem_id="pnginfo_generation_info_pretty", label="Parameters")
|
||||
gr.HTML('Full metadata')
|
||||
html2_info = gr.HTML(elem_id="pnginfo_html2_info")
|
||||
result_images, generation_info, html_info, html_log = ui_common.create_output_panel("extras", shared.opts.outdir_extras_samples)
|
||||
gr.HTML('File metadata')
|
||||
exif_info = gr.HTML(elem_id="pnginfo_html_info")
|
||||
for tabname, button in buttons.items():
|
||||
parameters_copypaste.register_paste_params_button(parameters_copypaste.ParamBinding(paste_button=button, tabname=tabname, source_text_component=generation_info, source_image_component=extras_image))
|
||||
|
||||
def pretty_geninfo(generation_info: str):
|
||||
if generation_info is None:
|
||||
return ''
|
||||
sections = generation_info.split('Steps:')
|
||||
if len(sections) > 1:
|
||||
param = sections[0].strip() + '\nSteps:' + sections[1].strip().replace(', ', '\n')
|
||||
return param
|
||||
return generation_info
|
||||
parameters_copypaste.register_paste_params_button(parameters_copypaste.ParamBinding(paste_button=button, tabname=tabname, source_text_component=html_info, source_image_component=extras_image))
|
||||
|
||||
tab_single.select(fn=lambda: 0, inputs=[], outputs=[tab_index])
|
||||
tab_batch.select(fn=lambda: 1, inputs=[], outputs=[tab_index])
|
||||
tab_batch_dir.select(fn=lambda: 2, inputs=[], outputs=[tab_index])
|
||||
generation_info.change(fn=pretty_geninfo, inputs=[generation_info], outputs=[generation_info_pretty])
|
||||
# html_info.change(fn=pretty_geninfo, inputs=[html_info], outputs=[html_info_pretty])
|
||||
_dummy = gr.HTML(visible=False)
|
||||
extras_image.change(
|
||||
fn=wrap_gradio_call(run_pnginfo),
|
||||
fn=wrap_gradio_call(wrap_pnginfo),
|
||||
inputs=[extras_image],
|
||||
outputs=[html_info, generation_info, html2_info],
|
||||
outputs=[_dummy, html_info, exif_info],
|
||||
)
|
||||
submit.click(
|
||||
fn=call_queue.wrap_gradio_gpu_call(submit_click, extra_outputs=[None, '']),
|
||||
@@ -73,12 +67,13 @@ def create_ui():
|
||||
extras_batch_input_dir,
|
||||
extras_batch_output_dir,
|
||||
show_extras_results,
|
||||
*script_inputs
|
||||
*script_inputs,
|
||||
],
|
||||
outputs=[
|
||||
result_images,
|
||||
html_info_x,
|
||||
html_info,
|
||||
generation_info,
|
||||
html_log,
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user