From 91bfc71261e160451e89f35a7c0eef66ff98877c Mon Sep 17 00:00:00 2001 From: AUTOMATIC <16777216c@gmail.com> Date: Thu, 22 Sep 2022 12:11:48 +0300 Subject: [PATCH] A big rework, just what you were secretly hoping for! SD upscale moved to scripts Batch processing script removed Batch processing added to main img2img and now works with scripts img2img page UI reworked to use tabs --- javascript/ui.js | 52 ++++++++++++++-- modules/extras.py | 18 ++---- modules/img2img.py | 116 +++++++++++++++-------------------- modules/processing.py | 5 +- modules/scripts.py | 1 - modules/shared.py | 3 +- modules/ui.py | 136 ++++++++++++++++++------------------------ scripts/batch.py | 59 ------------------ scripts/sd_upscale.py | 93 +++++++++++++++++++++++++++++ style.css | 8 ++- 10 files changed, 263 insertions(+), 228 deletions(-) delete mode 100644 scripts/batch.py create mode 100644 scripts/sd_upscale.py diff --git a/javascript/ui.js b/javascript/ui.js index f3860d2e..4944800b 100644 --- a/javascript/ui.js +++ b/javascript/ui.js @@ -35,13 +35,36 @@ function extract_image_from_gallery_extras(gallery){ return extract_image_from_gallery(gallery); } -function submit(){ - // this calls a function from progressbar.js - requestProgress() +function get_tab_index(tabId){ + var res = 0 + gradioApp().getElementById(tabId).querySelector('div').querySelectorAll('button').forEach(function(button, i){ + if(button.className.indexOf('bg-white') != -1) + res = i + }) + + return res +} + +function create_tab_index_args(tabId, args){ + var res = [] + for(var i=0; i 0: + left, right = os.path.splitext(filename) + filename = f"{left}-{n}{right}" + + processed_image.save(os.path.join(output_dir, filename)) + + +def img2img(mode: int, prompt: str, negative_prompt: str, prompt_style: str, prompt_style2: str, init_img, init_img_with_mask, init_img_inpaint, init_mask_inpaint, mask_mode, steps: int, sampler_index: int, mask_blur: int, inpainting_fill: int, restore_faces: bool, tiling: bool, n_iter: int, batch_size: int, 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, height: int, width: int, 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, *args): is_inpaint = mode == 1 - is_upscale = mode == 2 + is_batch = mode == 2 if is_inpaint: if mask_mode == 0: @@ -23,8 +63,8 @@ def img2img(prompt: str, negative_prompt: str, prompt_style: str, prompt_style2: mask = ImageChops.lighter(alpha_mask, mask.convert('L')).convert('L') image = image.convert('RGB') else: - image = init_img - mask = init_mask + image = init_img_inpaint + mask = init_mask_inpaint else: image = init_img mask = None @@ -60,79 +100,19 @@ def img2img(prompt: str, negative_prompt: str, prompt_style: str, prompt_style2: resize_mode=resize_mode, denoising_strength=denoising_strength, inpaint_full_res=inpaint_full_res, + inpaint_full_res_padding=inpaint_full_res_padding, inpainting_mask_invert=inpainting_mask_invert, ) print(f"\nimg2img: {prompt}", file=shared.progress_print_out) p.extra_generation_params["Mask blur"] = mask_blur - if is_upscale: - initial_info = None - - processing.fix_seed(p) - seed = p.seed - - upscaler = shared.sd_upscalers[upscaler_index] - img = upscaler.upscale(init_img, init_img.width * 2, init_img.height * 2) - - devices.torch_gc() - - grid = images.split_grid(img, tile_w=width, tile_h=height, overlap=upscale_overlap) - - batch_size = p.batch_size - upscale_count = p.n_iter - p.n_iter = 1 - p.do_not_save_grid = True - p.do_not_save_samples = True - - work = [] - - for y, h, row in grid.tiles: - for tiledata in row: - work.append(tiledata[2]) - - batch_count = math.ceil(len(work) / batch_size) - state.job_count = batch_count * upscale_count - - print(f"SD upscaling will process a total of {len(work)} images tiled as {len(grid.tiles[0][2])}x{len(grid.tiles)} per upscale in a total of {state.job_count} batches.") - - result_images = [] - for n in range(upscale_count): - start_seed = seed + n - p.seed = start_seed - - work_results = [] - for i in range(batch_count): - p.batch_size = batch_size - p.init_images = work[i*batch_size:(i+1)*batch_size] - - state.job = f"Batch {i + 1 + n * batch_count} out of {state.job_count}" - processed = process_images(p) - - if initial_info is None: - initial_info = processed.info - - p.seed = processed.seed + 1 - work_results += processed.images - - image_index = 0 - for y, h, row in grid.tiles: - for tiledata in row: - tiledata[2] = work_results[image_index] if image_index < len(work_results) else Image.new("RGB", (p.width, p.height)) - image_index += 1 - - combined_image = images.combine_grid(grid) - result_images.append(combined_image) - - if opts.samples_save: - images.save_image(combined_image, p.outpath_samples, "", start_seed, prompt, opts.samples_format, info=initial_info, p=p) - - processed = Processed(p, result_images, seed, initial_info) + if is_batch: + process_batch(p, img2img_batch_input_dir, img2img_batch_output_dir, args) + processed = Processed(p, [], p.seed, "") else: - processed = modules.scripts.scripts_img2img.run(p, *args) - if processed is None: processed = process_images(p) diff --git a/modules/processing.py b/modules/processing.py index e844b7e2..f44c3f26 100644 --- a/modules/processing.py +++ b/modules/processing.py @@ -491,7 +491,7 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing): class StableDiffusionProcessingImg2Img(StableDiffusionProcessing): sampler = None - def __init__(self, init_images=None, resize_mode=0, denoising_strength=0.75, mask=None, mask_blur=4, inpainting_fill=0, inpaint_full_res=True, inpainting_mask_invert=0, **kwargs): + def __init__(self, init_images=None, resize_mode=0, denoising_strength=0.75, mask=None, mask_blur=4, inpainting_fill=0, inpaint_full_res=True, inpaint_full_res_padding=0, inpainting_mask_invert=0, **kwargs): super().__init__(**kwargs) self.init_images = init_images @@ -505,6 +505,7 @@ class StableDiffusionProcessingImg2Img(StableDiffusionProcessing): self.mask_blur = mask_blur self.inpainting_fill = inpainting_fill self.inpaint_full_res = inpaint_full_res + self.inpaint_full_res_padding = inpaint_full_res_padding self.inpainting_mask_invert = inpainting_mask_invert self.mask = None self.nmask = None @@ -527,7 +528,7 @@ class StableDiffusionProcessingImg2Img(StableDiffusionProcessing): if self.inpaint_full_res: self.mask_for_overlay = self.image_mask mask = self.image_mask.convert('L') - crop_region = masking.get_crop_region(np.array(mask), opts.upscale_at_full_resolution_padding) + crop_region = masking.get_crop_region(np.array(mask), self.inpaint_full_res_padding) crop_region = masking.expand_crop_region(crop_region, self.width, self.height, mask.width, mask.height) x1, y1, x2, y2 = crop_region diff --git a/modules/scripts.py b/modules/scripts.py index 0e0b949b..9ab207dc 100644 --- a/modules/scripts.py +++ b/modules/scripts.py @@ -143,7 +143,6 @@ class ScriptRunner: return inputs - def run(self, p: StableDiffusionProcessing, *args): script_index = args[0] diff --git a/modules/shared.py b/modules/shared.py index 0a852838..841a9877 100644 --- a/modules/shared.py +++ b/modules/shared.py @@ -147,14 +147,13 @@ class Options: "save_txt": OptionInfo(False, "Create a text file next to every image with generation parameters."), "ESRGAN_tile": OptionInfo(192, "Tile size for ESRGAN upscalers. 0 = no tiling.", gr.Slider, {"minimum": 0, "maximum": 512, "step": 16}), "ESRGAN_tile_overlap": OptionInfo(8, "Tile overlap, in pixels for ESRGAN upscalers. Low values = visible seam.", gr.Slider, {"minimum": 0, "maximum": 48, "step": 1}), - "realesrgan_enabled_models": OptionInfo(["Real-ESRGAN 4x plus", "Real-ESRGAN 4x plus anime 6B"],"Select which RealESRGAN models to show in the web UI. (Requires restart)", gr.CheckboxGroup, lambda: {"choices": realesrgan_models_names()}), + "realesrgan_enabled_models": OptionInfo(["Real-ESRGAN 4x plus", "Real-ESRGAN 4x plus anime 6B"], "Select which RealESRGAN models to show in the web UI. (Requires restart)", gr.CheckboxGroup, lambda: {"choices": realesrgan_models_names()}), "SWIN_tile": OptionInfo(192, "Tile size for all SwinIR.", gr.Slider, {"minimum": 16, "maximum": 512, "step": 16}), "SWIN_tile_overlap": OptionInfo(8, "Tile overlap, in pixels for SwinIR. Low values = visible seam.", gr.Slider, {"minimum": 0, "maximum": 48, "step": 1}), "ldsr_steps": OptionInfo(100, "LDSR processing steps. Lower = faster", gr.Slider, {"minimum": 1, "maximum": 200, "step": 1}), "ldsr_pre_down":OptionInfo(1, "LDSR Pre-process downssample scale. 1 = no down-sampling, 4 = 1/4 scale.", gr.Slider, {"minimum": 1, "maximum": 4, "step": 1}), "ldsr_post_down":OptionInfo(1, "LDSR Post-process down-sample scale. 1 = no down-sampling, 4 = 1/4 scale.", gr.Slider, {"minimum": 1, "maximum": 4, "step": 1}), "random_artist_categories": OptionInfo([], "Allowed categories for random artists selection when using the Roll button", gr.CheckboxGroup, {"choices": artist_db.categories()}), - "upscale_at_full_resolution_padding": OptionInfo(16, "Inpainting at full resolution: padding, in pixels, for the masked region.", gr.Slider, {"minimum": 0, "maximum": 128, "step": 4}), "upscaler_for_hires_fix": OptionInfo(None, "Upscaler for highres. fix", gr.Radio, lambda: {"choices": [x.name for x in sd_upscalers]}), "show_progressbar": OptionInfo(True, "Show progressbar"), "show_progress_every_n_steps": OptionInfo(0, "Show show image creation progress every N sampling steps. Set 0 to disable.", gr.Slider, {"minimum": 0, "maximum": 32, "step": 1}), diff --git a/modules/ui.py b/modules/ui.py index 572dcfb9..3c898bd2 100644 --- a/modules/ui.py +++ b/modules/ui.py @@ -527,36 +527,47 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo): progressbar = gr.HTML(elem_id="progressbar") img2img_preview = gr.Image(elem_id='img2img_preview', visible=False) setup_progressbar(progressbar, img2img_preview) - + with gr.Row().style(equal_height=False): with gr.Column(variant='panel'): - with gr.Group(): - switch_mode = gr.Radio(label='Mode', elem_id="img2img_mode", choices=['Redraw whole image', 'Inpaint a part of image', 'SD upscale'], value='Redraw whole image', type="index", show_label=False) - init_img = gr.Image(label="Image for img2img", source="upload", interactive=True, type="pil") - init_img_with_mask = gr.Image(label="Image for inpainting with mask", elem_id="img2maskimg", source="upload", interactive=True, type="pil", tool="sketch", visible=False, image_mode="RGBA") - init_mask = gr.Image(label="Mask", source="upload", interactive=True, type="pil", visible=False) - init_img_with_mask_comment = gr.HTML(elem_id="mask_bug_info", value="if the editor shows ERROR, switch to another tab and back, then to another img2img mode above and back", visible=False) - with gr.Row(): - resize_mode = gr.Radio(label="Resize mode", elem_id="resize_mode", show_label=False, choices=["Just resize", "Crop and resize", "Resize and fill"], type="index", value="Just resize") - mask_mode = gr.Radio(label="Mask mode", show_label=False, choices=["Draw mask", "Upload mask"], type="index", value="Draw mask") + with gr.Tabs(elem_id="mode_img2img") as tabs_img2img_mode: + with gr.TabItem('img2img'): + init_img = gr.Image(label="Image for img2img", show_label=False, source="upload", interactive=True, type="pil") + + with gr.TabItem('Inpaint'): + init_img_with_mask = gr.Image(label="Image for inpainting with mask", show_label=False, elem_id="img2maskimg", source="upload", interactive=True, type="pil", tool="sketch", image_mode="RGBA") + init_img_with_mask_comment = gr.HTML(elem_id="mask_bug_info", value="if the editor shows ERROR, switch to another tab and back, then to \"Upload mask\" mode above and back") + + init_img_inpaint = gr.Image(label="Image for img2img", show_label=False, source="upload", interactive=True, type="pil", visible=False) + init_mask_inpaint = gr.Image(label="Mask", source="upload", interactive=True, type="pil", visible=False) + + mask_blur = gr.Slider(label='Mask blur', minimum=0, maximum=64, step=1, value=4) + + with gr.Row(): + mask_mode = gr.Radio(label="Mask mode", show_label=False, choices=["Draw mask", "Upload mask"], type="index", value="Draw mask") + inpainting_mask_invert = gr.Radio(label='Masking mode', show_label=False, choices=['Inpaint masked', 'Inpaint not masked'], value='Inpaint masked', type="index") + + inpainting_fill = gr.Radio(label='Masked content', choices=['fill', 'original', 'latent noise', 'latent nothing'], value='fill', type="index") + + with gr.Row(): + inpaint_full_res = gr.Checkbox(label='Inpaint at full resolution', value=False) + inpaint_full_res_padding = gr.Slider(label='Inpaint at full resolution padding, pixels', minimum=0, maximum=256, step=4, value=32) + + with gr.TabItem('Batch img2img'): + gr.HTML("

Process images in a directory on the same machine where the server is running.

") + img2img_batch_input_dir = gr.Textbox(label="Input directory") + img2img_batch_output_dir = gr.Textbox(label="Output directory") + + with gr.Row(): + resize_mode = gr.Radio(label="Resize mode", elem_id="resize_mode", show_label=False, choices=["Just resize", "Crop and resize", "Resize and fill"], type="index", value="Just resize") steps = gr.Slider(minimum=1, maximum=150, step=1, label="Sampling Steps", value=20) sampler_index = gr.Radio(label='Sampling method', choices=[x.name for x in samplers_for_img2img], value=samplers_for_img2img[0].name, type="index") - mask_blur = gr.Slider(label='Mask blur', minimum=0, maximum=64, step=1, value=4, visible=False) - inpainting_fill = gr.Radio(label='Masked content', choices=['fill', 'original', 'latent noise', 'latent nothing'], value='fill', type="index", visible=False) - - with gr.Row(): - inpaint_full_res = gr.Checkbox(label='Inpaint at full resolution', value=False, visible=False) - inpainting_mask_invert = gr.Radio(label='Masking mode', choices=['Inpaint masked', 'Inpaint not masked'], value='Inpaint masked', type="index", visible=False) with gr.Row(): restore_faces = gr.Checkbox(label='Restore faces', value=False, visible=len(shared.face_restorers) > 1) tiling = gr.Checkbox(label='Tiling', value=False) - sd_upscale_overlap = gr.Slider(minimum=0, maximum=256, step=16, label='Tile overlap', value=64, visible=False) - - with gr.Row(): - sd_upscale_upscaler_name = gr.Radio(label='Upscaler', choices=[x.name for x in shared.sd_upscalers], value=shared.sd_upscalers[0].name, type="index", visible=False) with gr.Row(): batch_count = gr.Slider(minimum=1, maximum=cmd_opts.max_batch_count, step=1, label='Batch count', value=1) @@ -589,7 +600,6 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo): img2img_send_to_extras = gr.Button('Send to extras') img2img_save_style = gr.Button('Save prompt as style') - with gr.Group(): html_info = gr.HTML() generation_info = gr.Textbox(visible=False) @@ -597,70 +607,36 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo): 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) - def apply_mode(mode, uploadmask): - is_classic = mode == 0 - is_inpaint = mode == 1 - is_upscale = mode == 2 - - return { - init_img: gr_show(not is_inpaint or (is_inpaint and uploadmask == 1)), - init_img_with_mask: gr_show(is_inpaint and uploadmask == 0), - init_img_with_mask_comment: gr_show(is_inpaint and uploadmask == 0), - init_mask: gr_show(is_inpaint and uploadmask == 1), - mask_mode: gr_show(is_inpaint), - mask_blur: gr_show(is_inpaint), - inpainting_fill: gr_show(is_inpaint), - sd_upscale_upscaler_name: gr_show(is_upscale), - sd_upscale_overlap: gr_show(is_upscale), - inpaint_full_res: gr_show(is_inpaint), - inpainting_mask_invert: gr_show(is_inpaint), - img2img_interrogate: gr_show(not is_inpaint), - } - - switch_mode.change( - apply_mode, - inputs=[switch_mode, mask_mode], + mask_mode.change( + lambda mode, img: { + #init_img_with_mask: gr.Image.update(visible=mode == 0, value=img["image"]), + init_img_with_mask: gr_show(mode == 0), + init_img_with_mask_comment: gr_show(mode == 0), + init_img_inpaint: gr_show(mode == 1), + init_mask_inpaint: gr_show(mode == 1), + }, + inputs=[mask_mode, init_img_with_mask], outputs=[ - init_img, init_img_with_mask, init_img_with_mask_comment, - init_mask, - mask_mode, - mask_blur, - inpainting_fill, - sd_upscale_upscaler_name, - sd_upscale_overlap, - inpaint_full_res, - inpainting_mask_invert, - img2img_interrogate, - ] - ) - - mask_mode.change( - lambda mode: { - init_img: gr_show(mode == 1), - init_img_with_mask: gr_show(mode == 0), - init_mask: gr_show(mode == 1), - }, - inputs=[mask_mode], - outputs=[ - init_img, - init_img_with_mask, - init_mask, + init_img_inpaint, + init_mask_inpaint, ], ) img2img_args = dict( fn=img2img, - _js="submit", + _js="submit_img2img", inputs=[ + dummy_component, img2img_prompt, img2img_negative_prompt, img2img_prompt_style, img2img_prompt_style2, init_img, init_img_with_mask, - init_mask, + init_img_inpaint, + init_mask_inpaint, mask_mode, steps, sampler_index, @@ -668,7 +644,6 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo): inpainting_fill, restore_faces, tiling, - switch_mode, batch_count, batch_size, cfg_scale, @@ -678,10 +653,11 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo): height, width, resize_mode, - sd_upscale_upscaler_name, - sd_upscale_overlap, inpaint_full_res, + inpaint_full_res_padding, inpainting_mask_invert, + img2img_batch_input_dir, + img2img_batch_output_dir, ] + custom_inputs, outputs=[ img2img_gallery, @@ -748,7 +724,7 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo): with gr.Blocks(analytics_enabled=False) as extras_interface: with gr.Row().style(equal_height=False): with gr.Column(variant='panel'): - with gr.Tabs(): + with gr.Tabs(elem_id="mode_extras"): with gr.TabItem('Single Image'): image = gr.Image(label="Source", source="upload", interactive=True, type="pil") @@ -778,9 +754,11 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo): html_info_x = gr.HTML() html_info = gr.HTML() - extras_args = dict( + submit.click( fn=run_extras, + _js="get_extras_tab_index", inputs=[ + dummy_component, image, image_batch, gfpgan_visibility, @@ -798,8 +776,6 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo): ] ) - submit.click(**extras_args) - pnginfo_interface = gr.Interface( wrap_gradio_call(run_pnginfo), inputs=[ @@ -929,6 +905,12 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo): outputs=[init_img_with_mask], ) + tabs_img2img_mode.change( + fn=lambda x: x, + inputs=[init_img_with_mask], + outputs=[init_img_with_mask], + ) + send_to_img2img.click( fn=lambda x: image_from_url_text(x), _js="extract_image_from_gallery_img2img", diff --git a/scripts/batch.py b/scripts/batch.py deleted file mode 100644 index 1af4a7bc..00000000 --- a/scripts/batch.py +++ /dev/null @@ -1,59 +0,0 @@ -import math -import os -import sys -import traceback - -import modules.scripts as scripts -import gradio as gr - -from modules.processing import Processed, process_images -from PIL import Image -from modules.shared import opts, cmd_opts, state - - -class Script(scripts.Script): - def title(self): - return "Batch processing" - - def show(self, is_img2img): - return is_img2img - - def ui(self, is_img2img): - input_dir = gr.Textbox(label="Input directory", lines=1) - output_dir = gr.Textbox(label="Output directory", lines=1) - - return [input_dir, output_dir] - - def run(self, p, input_dir, output_dir): - images = [file for file in [os.path.join(input_dir, x) for x in os.listdir(input_dir)] if os.path.isfile(file)] - - batch_count = math.ceil(len(images) / p.batch_size) - print(f"Will process {len(images)} images in {batch_count} batches.") - - p.batch_count = 1 - p.do_not_save_grid = True - p.do_not_save_samples = True - - state.job_count = batch_count - - for batch_no in range(batch_count): - batch_images = [] - for path in images[batch_no*p.batch_size:(batch_no+1)*p.batch_size]: - try: - img = Image.open(path) - batch_images.append((img, path)) - except: - print(f"Error processing {path}:", file=sys.stderr) - print(traceback.format_exc(), file=sys.stderr) - - if len(batch_images) == 0: - continue - - state.job = f"{batch_no} out of {batch_count}: {batch_images[0][1]}" - p.init_images = [x[0] for x in batch_images] - proc = process_images(p) - for image, (_, path) in zip(proc.images, batch_images): - filename = os.path.basename(path) - image.save(os.path.join(output_dir, filename)) - - return Processed(p, [], p.seed, "") diff --git a/scripts/sd_upscale.py b/scripts/sd_upscale.py new file mode 100644 index 00000000..b87a145b --- /dev/null +++ b/scripts/sd_upscale.py @@ -0,0 +1,93 @@ +import math + +import modules.scripts as scripts +import gradio as gr +from PIL import Image + +from modules import processing, shared, sd_samplers, images, devices +from modules.processing import Processed +from modules.shared import opts, cmd_opts, state + + +class Script(scripts.Script): + def title(self): + return "SD upscale" + + def show(self, is_img2img): + return is_img2img + + def ui(self, is_img2img): + info = gr.HTML("

Will upscale the image to twice the dimensions; use width and height sliders to set tile size

") + overlap = gr.Slider(minimum=0, maximum=256, step=16, label='Tile overlap', value=64, visible=False) + upscaler_index = gr.Radio(label='Upscaler', choices=[x.name for x in shared.sd_upscalers], value=shared.sd_upscalers[0].name, type="index", visible=False) + + return [info, overlap, upscaler_index] + + def run(self, p, _, overlap, upscaler_index): + processing.fix_seed(p) + upscaler = shared.sd_upscalers[upscaler_index] + + p.extra_generation_params["SD upscale overlap"] = overlap + p.extra_generation_params["SD upscale upscaler"] = upscaler.name + + initial_info = None + seed = p.seed + + init_img = p.init_images[0] + img = upscaler.upscale(init_img, init_img.width * 2, init_img.height * 2) + + devices.torch_gc() + + grid = images.split_grid(img, tile_w=p.width, tile_h=p.height, overlap=overlap) + + batch_size = p.batch_size + upscale_count = p.n_iter + p.n_iter = 1 + p.do_not_save_grid = True + p.do_not_save_samples = True + + work = [] + + for y, h, row in grid.tiles: + for tiledata in row: + work.append(tiledata[2]) + + batch_count = math.ceil(len(work) / batch_size) + state.job_count = batch_count * upscale_count + + print(f"SD upscaling will process a total of {len(work)} images tiled as {len(grid.tiles[0][2])}x{len(grid.tiles)} per upscale in a total of {state.job_count} batches.") + + result_images = [] + for n in range(upscale_count): + start_seed = seed + n + p.seed = start_seed + + work_results = [] + for i in range(batch_count): + p.batch_size = batch_size + p.init_images = work[i*batch_size:(i+1)*batch_size] + + state.job = f"Batch {i + 1 + n * batch_count} out of {state.job_count}" + processed = processing.process_images(p) + + if initial_info is None: + initial_info = processed.info + + p.seed = processed.seed + 1 + work_results += processed.images + + image_index = 0 + for y, h, row in grid.tiles: + for tiledata in row: + tiledata[2] = work_results[image_index] if image_index < len(work_results) else Image.new("RGB", (p.width, p.height)) + image_index += 1 + + combined_image = images.combine_grid(grid) + result_images.append(combined_image) + + if opts.samples_save: + images.save_image(combined_image, p.outpath_samples, "", start_seed, p.prompt, opts.samples_format, info=initial_info, p=p) + + processed = Processed(p, result_images, seed, initial_info) + + return processed diff --git a/style.css b/style.css index 655a00e5..de5f94a6 100644 --- a/style.css +++ b/style.css @@ -97,6 +97,11 @@ background: transparent; } +.my-4{ + margin-top: 0; + margin-bottom: 0; +} + #toprow div{ border: none; gap: 0; @@ -198,7 +203,8 @@ input[type="range"]{ #mask_bug_info { text-align: center; display: block; - margin-bottom: 0.5em; + margin-top: -0.75em; + margin-bottom: -0.75em; } #txt2img_negative_prompt, #img2img_negative_prompt{