diff --git a/CHANGELOG.md b/CHANGELOG.md index 68a8c3e0c..3263563f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,11 @@ - all system and image paths are now relative by default - fix extra networks previews - add settings validation when performing load/save - - settings tab in ui now shows settings that are changed from default values + - settings tab in ui now shows settings that are changed from default values + - enable batch **img2img** scale-by workflows + now you can batch process with rescaling based on eah individual original image size + - update **gradio** major version + this may result in some smaller layout changes since its a major version change - optimize model hashing - add cli param `--skip-all` that skips all installer checks use at personal discretion, but it can be useful for bulk deployments diff --git a/extensions-builtin/sd-webui-controlnet b/extensions-builtin/sd-webui-controlnet index 9af9d6b94..bbabb39c6 160000 --- a/extensions-builtin/sd-webui-controlnet +++ b/extensions-builtin/sd-webui-controlnet @@ -1 +1 @@ -Subproject commit 9af9d6b94329092266af5be5c26b40d2e3fe96e9 +Subproject commit bbabb39c6afa320b0a72ddffdc339eb9325230f1 diff --git a/extensions-builtin/stable-diffusion-webui-images-browser b/extensions-builtin/stable-diffusion-webui-images-browser index a48f65350..b8f6e05d1 160000 --- a/extensions-builtin/stable-diffusion-webui-images-browser +++ b/extensions-builtin/stable-diffusion-webui-images-browser @@ -1 +1 @@ -Subproject commit a48f65350dcf33f367cb5a79eee95999f5d692c0 +Subproject commit b8f6e05d1d23b3d0d17b0a9cfbf824bf4a1f98e9 diff --git a/javascript/black-orange.css b/javascript/black-orange.css index 8e4a520c2..21334f6fb 100644 --- a/javascript/black-orange.css +++ b/javascript/black-orange.css @@ -25,6 +25,7 @@ --spacing-md: 4px; --spacing-xxl: 12px; --line-sm: 1.3em; + --line-md: 1.3em; } html { font-size: var(--font-size); } @@ -93,7 +94,7 @@ svg.feather.feather-image, .feather .feather-image { display: none } #img2img_settings { min-width: calc(2 * var(--left-column)); max-width: calc(2 * var(--left-column)); background-color: #111111; padding-top: 16px; } #interrogate, #deepbooru { margin: 0 0px 10px 0px; max-width: 80px; max-height: 80px; font-weight: normal; font-size: 0.95em; } #quicksettings .gr-button-tool { font-size: 1.6rem; box-shadow: none; margin-left: -20px; margin-top: -2px; height: 2.4em; } -#quicksettings > div, #quicksettings > fieldset { line-height: 1.6em; margin-top: 0.4em; } +#quicksettings > div, #quicksettings > fieldset { line-height: 1.4em; margin-top: 0.4em; } #open_folder_extras, #footer, #style_pos_col, #style_neg_col, #roll_col, #extras_upscaler_2, #extras_upscaler_2_visibility, #txt2img_seed_resize_from_w, #txt2img_seed_resize_from_h { display: none; } #save-animation { border-radius: var(--radius-sm) !important; margin-bottom: 16px; background-color: #111111; } #script_list { padding: 4px; margin-top: 20px; margin-bottom: 20px; } diff --git a/javascript/loader.js b/javascript/loader.js index 18d8f96c9..c72a1926c 100644 --- a/javascript/loader.js +++ b/javascript/loader.js @@ -39,6 +39,7 @@ async function removeSplash() { const splash = document.getElementById('splash'); if (splash) splash.remove(); console.log('removeSplash'); + console.log('startupTime', Math.round(performance.now() - appStartTime) / 1000); } window.onload = createSplash; diff --git a/javascript/script.js b/javascript/script.js index b07e2906a..339eedc9f 100644 --- a/javascript/script.js +++ b/javascript/script.js @@ -1,3 +1,5 @@ +const appStartTime = performance.now(); + function gradioApp() { const elems = document.getElementsByTagName('gradio-app'); const elem = elems.length === 0 ? document : elems[0]; diff --git a/javascript/style.css b/javascript/style.css index ae8f529b3..1f568a224 100644 --- a/javascript/style.css +++ b/javascript/style.css @@ -3,12 +3,12 @@ a { font-weight: bold; cursor: pointer; } h2 { margin-top: 1em !important; font-size: 1.4em !important; } div.gradio-container{ max-width: unset !important; padding: 8px !important; } div.tabitem { padding: 0 !important; } -div.form { border-width: 0; box-shadow: none; background: transparent; overflow: visible; gap: 0.5em 1em; } +div.form { border-width: 0; box-shadow: none; background: transparent; overflow: visible; gap: 0.5em 1em; flex-grow: 1 !important; } div.compact{ gap: 1em; } div.gradio-html.min{ min-height: 0; } .block.gradio-checkbox { margin: 0.75em 1.5em 0 0; } .block.gradio-dropdown, .block.gradio-slider, .block.gradio-checkbox, .block.gradio-textbox, .block.gradio-radio, .block.gradio-checkboxgroup, .block.gradio-number, .block.gradio-colorpicker { border-width: 0 !important; box-shadow: none !important;} -.block.padded:not(.gradio-accordion) { padding: 0 !important; } +.block.padded:not(.gradio-accordion) { padding: 0 !important; margin-right: 0; min-width: 100px !important; } .compact{ background: transparent !important; padding: 0 !important; } .dark .gradio-dropdown ul.options li.item:not(:has(.hide)) { background-color: var(--neutral-900); } .gap.compact{ padding: 0; gap: 0.2em 0; } @@ -24,7 +24,7 @@ div.gradio-html.min{ min-height: 0; } .gradio-dropdown.multiselect .token-remove.remove-all.remove-all{ display: flex; } .gradio-dropdown.multiselect div.wrap-inner { overflow-x: hidden; overflow-y: auto; max-height: 50vh; overflow-wrap: anywhere; } .gradio-html div.wrap{ height: 100%; } -.gradio-slider input[type="number"]{ width: 6em; } +.gradio-slider input[type="number"]{ width: 6em; margin-left: 0.5em; } .hidden { display: none; } footer { display: none; } td { border-bottom: none !important; } @@ -34,7 +34,7 @@ td { border-bottom: none !important; } .gradio-button.secondary-down{ background: var(--button-secondary-background-fill); color: var(--button-secondary-text-color); } .gradio-button.secondary-down, .gradio-button.secondary-down:hover{ box-shadow: 1px 1px 1px rgba(0,0,0,0.25) inset, 0px 0px 3px rgba(0,0,0,0.15) inset; } .gradio-button.secondary-down:hover{ background: var(--button-secondary-background-fill-hover); color: var(--button-secondary-text-color-hover); } -.checkboxes-row { margin-bottom: 1em; gap: 0 !important; justify-content: space-around; } +.checkboxes-row { margin-bottom: 1em; gap: 0 !important; justify-content: space-around; flex-wrap: unset !important; } .checkboxes-row > div{ flex: 0; white-space: nowrap; min-width: auto; } button.custom-button{ @@ -78,10 +78,11 @@ button.custom-button{ #txt2img_generate_line2 > button, #img2img_generate_line2 > button, #extras_generate_box > button { height: 2.2em; line-height: 0; min-width: unset; display: block !important; } #txt2img_tools > div, #img2img_tools > div { justify-content: space-around; margin-top: 0.5em; margin-bottom: 0em; } #txt2img_tools > div > button, #img2img_tools > div > button { scale: 120%; } +#txt2img_prompt, #txt2img_neg_prompt, #img2img_prompt, #img2img_neg_prompt { display: contents; } .interrogate-col{ min-width: 0 !important; max-width: fit-content; gap: 0.5em; } .interrogate-col > button{ flex: 1; } #sampler_selection_img2img { margin-top: 1em; } -#txtimg_hr_finalres{ min-height: 0 !important; padding: .625rem .75rem; margin-left: -0.75em } +#txtimg_hr_finalres{ min-height: 0 !important; } #img2img_scale_resolution_preview.block{ display: flex; align-items: end; } #txtimg_hr_finalres .resolution, #img2img_scale_resolution_preview .resolution{ font-weight: bold; } div#extras_scale_to_tab div.form{ flex-direction: row; } @@ -119,8 +120,8 @@ div#extras_scale_to_tab div.form{ flex-direction: row; } #quicksettings > button { margin-left: -0.5em; } #settings { display: flex; flex-flow: row wrap; gap: var(--layout-gap); } -#settings div { border: none; } -#settings > div.tab-content { flex: 100000 0 75%; } +#settings div { border: none; min-width: max-content; overflow-x: auto; } +#settings > div.tab-content { flex: 10 0 75%; } #settings > div.tab-content > div { border: none; padding: 0; } #settings > div.tab-nav { display: grid; grid-template-columns: repeat(auto-fill, .3em minmax(10em, 1fr)); flex: 1 0 auto; width: 12em; align-self: flex-start; gap: var(--spacing-md); } #settings > div.tab-nav button { display: block; border: none; text-align: left; white-space: initial; padding: 0; } @@ -128,12 +129,13 @@ div#extras_scale_to_tab div.form{ flex-direction: row; } #settings .block.gradio-checkbox { margin: 0; width: auto; } #settings .dirtyable { display: grid; grid-template-columns: .3em auto; gap: .5em; } #settings .dirtyable.hidden { display: none; } -#settings .modification-indicator { width: 100%; height: 100%; border-radius: 1em !important; padding: 0; width: 0 } +#settings .modification-indicator { height: 1.2em; border-radius: 1em !important; padding: 0; width: 0; margin-right: 0.5em; } #settings .modification-indicator:disabled { visibility: hidden; } #settings .modification-indicator.unsaved { background: var(--color-accent-soft); width: 4px; } #settings .modification-indicator.changed { background: var(--color-accent); width: 4px; } #settings .modification-indicator.changed.unsaved { background-image: linear-gradient(var(--color-accent) 25%, var(--color-accent-soft) 75%); width: 4px; } #settings_result { margin: 0 1.2em; } +.styler { flex-direction: unset !important; } /* live preview */ .progressDiv{ position: relative; height: 20px; background: #b4c0cc; margin-bottom: -3px; } diff --git a/modules/img2img.py b/modules/img2img.py index 9162a5625..a53e9cc66 100644 --- a/modules/img2img.py +++ b/modules/img2img.py @@ -41,6 +41,9 @@ def process_batch(p, input_files, input_dir, output_dir, inpaint_mask_dir, args) shared.log.error(f"Image error: {e}") continue img = ImageOps.exif_transpose(img) + if p.scale_by != 1: + p.width = int(img.width * p.scale_by) + p.height = int(img.height * p.scale_by) p.init_images = [img] * p.batch_size if is_inpaint_batch: @@ -92,7 +95,6 @@ def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_s override_settings = create_override_settings_dict(override_settings_texts) - is_batch = mode == 5 if mode == 0: # img2img if init_img is None: return @@ -175,12 +177,15 @@ def img2img(id_task: str, mode: int, prompt: str, negative_prompt: str, prompt_s inpainting_mask_invert=inpainting_mask_invert, override_settings=override_settings, ) + p.is_batch = mode == 5 + if selected_scale_tab == 1 and resize_mode != 0: + p.scale_by = scale_by p.scripts = modules.scripts.scripts_img2img p.script_args = args p.extra_generation_params['Resize mode'] = resize_mode if mask: p.extra_generation_params["Mask blur"] = mask_blur - if is_batch: + if p.is_batch: process_batch(p, img2img_batch_files, img2img_batch_input_dir, img2img_batch_output_dir, img2img_batch_inpaint_mask_dir, args) processed = processing.Processed(p, [], p.seed, "") else: diff --git a/modules/processing.py b/modules/processing.py index 2b0df158c..e73b4efec 100644 --- a/modules/processing.py +++ b/modules/processing.py @@ -532,7 +532,9 @@ def print_profile(profile, msg: str): def process_images(p: StableDiffusionProcessing) -> Processed: - stored_opts = {k: shared.opts.data[k] for k in p.override_settings.keys()} + stored_opts = {} + for k in p.override_settings.keys(): + stored_opts[k] = shared.opts.data.get(k, None) try: # if no checkpoint override or the override checkpoint can't be found, remove override entry and load opts checkpoint if p.override_settings.get('sd_model_checkpoint', None) is not None and sd_models.checkpoint_aliases.get(p.override_settings.get('sd_model_checkpoint')) is None: @@ -571,7 +573,6 @@ def process_images(p: StableDiffusionProcessing) -> Processed: setattr(shared.opts, k, v) if k == 'sd_model_checkpoint': sd_models.reload_model_weights() - if k == 'sd_vae': sd_vae.reload_vae_weights() return res @@ -1031,6 +1032,8 @@ class StableDiffusionProcessingImg2Img(StableDiffusionProcessing): self.refiner_prompt = refiner_prompt self.refiner_negative = refiner_negative self.enable_hr = None + self.is_batch = False + self.scale_by = 1.0 def init(self, all_prompts, all_seeds, all_subseeds): if shared.backend == shared.Backend.DIFFUSERS and self.image_mask is None: diff --git a/modules/prompt_parser_diffusers.py b/modules/prompt_parser_diffusers.py index baf479663..61d247b83 100644 --- a/modules/prompt_parser_diffusers.py +++ b/modules/prompt_parser_diffusers.py @@ -1,7 +1,6 @@ import os import typing import torch -import diffusers from compel import Compel, ReturnedEmbeddingsType import modules.shared as shared import modules.prompt_parser as prompt_parser diff --git a/requirements.txt b/requirements.txt index a6c8f9d7c..adfb787ed 100644 --- a/requirements.txt +++ b/requirements.txt @@ -49,7 +49,7 @@ accelerate==0.20.3 opencv-python-headless==4.7.0.72 diffusers==0.20.0 einops==0.4.1 -gradio==3.32.0 +gradio==3.41.1 huggingface_hub==0.16.4 numexpr==2.8.4 numpy==1.24.4 diff --git a/wiki b/wiki index 32fa2e71e..bfa1a6d5c 160000 --- a/wiki +++ b/wiki @@ -1 +1 @@ -Subproject commit 32fa2e71eda8393f886582693a466cdd241c7390 +Subproject commit bfa1a6d5ca7d18ce3e633ba29cce5a6773ae75ee