Compare commits

...
Author SHA1 Message Date
Connum 1495a7460b refactored image paste handling to fill unset images successively, then replace last existing image (fixes #981) 2022-09-26 18:12:55 +02:00
tateisuandAUTOMATIC1111 78d6aef302 use strftime. update hints.js 2022-09-26 16:24:21 +03:00
tateisuandAUTOMATIC1111 b39f06cea7 add [datetime] to image file name pattern 2022-09-26 16:24:21 +03:00
DepFAandAUTOMATIC1111 e61da308ba Disable sentry logging 2022-09-26 16:19:47 +03:00
DepFAandAUTOMATIC1111 b8a8f749ef Update webui.bat 2022-09-26 16:19:47 +03:00
LiamandAUTOMATIC1111 db4ab47f09 copy over fields when sending to img2img: https://github.com/AUTOMATIC1111/stable-diffusion-webui/issues/1029 2022-09-26 08:33:02 +03:00
AUTOMATIC ca3e5519e8 Merge remote-tracking branch 'origin/master' 2022-09-25 19:45:22 +03:00
AUTOMATIC ff107845b4 added hiding items to ui-config.json 2022-09-25 19:43:42 +03:00
EyrieandAUTOMATIC1111 1877a3767e Changed job_id to timestamp 2022-09-25 17:11:07 +03:00
EyrieandAUTOMATIC1111 4c3d4aad60 fix formatting 2022-09-25 17:11:07 +03:00
EyrieandAUTOMATIC1111 e13912dfde fix formatting 2022-09-25 17:11:07 +03:00
EyrieandAUTOMATIC1111 ba34b790d3 Added hints for file & dir patterns 2022-09-25 17:11:07 +03:00
EyrieandAUTOMATIC1111 40166dbf08 Added job_id pattern for directories 2022-09-25 17:11:07 +03:00
AUTOMATIC 073f6eac22 potential fix for embeddings no loading on AMD cards 2022-09-25 15:04:39 +03:00
DepFAandAUTOMATIC1111 50ae19acf6 add custom script source to config path keys 2022-09-25 09:59:31 +03:00
DepFAandAUTOMATIC1111 31a0fbf1ad add attribute to custom script controls 2022-09-25 09:59:31 +03:00
guaneecandAUTOMATIC1111 615b2fc9ce Fix token max length 2022-09-25 09:30:02 +03:00
AUTOMATIC b8eae5de93 Merge remote-tracking branch 'origin/master' 2022-09-25 09:25:47 +03:00
AUTOMATIC 600cc0342d added support for setting hires fix from pasted prompts
added more robust detection of last line with parameters for pasted prompts
2022-09-25 09:25:28 +03:00
DepFAandAUTOMATIC1111 72e2a96284 Correct indent 2022-09-25 08:46:09 +03:00
DepFAandAUTOMATIC1111 ab5a472556 Persist default Number values 2022-09-25 08:46:09 +03:00
DepFAandAUTOMATIC1111 ca13264609 Add attr to skip 2022-09-25 08:46:09 +03:00
DepFAandAUTOMATIC1111 b1320d79b5 Apply to all checkboxes and textboxes 2022-09-25 08:46:09 +03:00
DepFAandAUTOMATIC1111 714dcda068 Add attributes to checkboxes for persisting 2022-09-25 08:46:09 +03:00
achaiahandAUTOMATIC1111 5194a58278 removing duplicates
removing duplicated requirements (transformers, diffusers) and reorganizing alphabetically to be able to spot duplicates in the future.
2022-09-25 08:44:54 +03:00
AUTOMATIC 53be15c204 by popular request, moves width/height sliders higher 2022-09-25 08:40:29 +03:00
EyeDeckandAUTOMATIC1111 b5d705e263 Disable 'batch img2img' when launched with --hide-ui-dir-config
Prevent writing to arbitrary directories, as usual
2022-09-24 19:06:36 +03:00
RnDMonkeyandAUTOMATIC1111 a2bea2f97a added [styles] filename pattern 2022-09-24 11:12:58 +03:00
AUTOMATIC 410bef0853 do not hide preview image too early 2022-09-24 09:16:54 +03:00
AUTOMATIC 31ac0baba0 Reformat some changes from the previous commit. 2022-09-24 08:23:01 +03:00
RnDMonkeyandGitHub ed8b8b3b8c Fix to XY_Grid script console progress bar and other progress bar improvements (#890)
Fix to XY_Grid script console progress bar and other progress bar improvements #890
2022-09-24 08:09:59 +03:00
jciancaandAUTOMATIC1111 7aec029423 Update README.md 2022-09-24 07:58:30 +03:00
jciancaandAUTOMATIC1111 e94ec98102 Update README.md 2022-09-24 07:58:30 +03:00
jciancaandAUTOMATIC1111 db341bd0d8 Add files via upload 2022-09-24 07:58:30 +03:00
innovacionesandAUTOMATIC1111 3e4b7fb869 Remove double loading message 2022-09-24 07:58:07 +03:00
ConnumandAUTOMATIC1111 910a3d9427 make callback queue handling reusable and implement onUiTabChange() 2022-09-24 07:44:05 +03:00
Jacob TyndallandAUTOMATIC1111 0f77e1852f Clear no longer needed VRAM during a 'highres fix' generation created during the first sampling before doing the second (img2img) sampling. Makes it possible to use the feature on an 8GB card. 2022-09-24 07:41:59 +03:00
AUTOMATIC 74f940e818 Merge remote-tracking branch 'origin/master' 2022-09-24 00:13:47 +03:00
AUTOMATIC 71cfb9ebac fix for settings sometimes not applying on javascript side 2022-09-24 00:13:32 +03:00
innovacionesandAUTOMATIC1111 b04a36be37 Tweak margin 2022-09-23 23:41:10 +03:00
innovacionesandAUTOMATIC1111 e1d49c5262 Fix border 2022-09-23 23:41:10 +03:00
innovacionesandAUTOMATIC1111 6cd613811b Fix preview images position 2022-09-23 23:41:10 +03:00
DepFAandAUTOMATIC1111 e560eb8b60 Only switch between visible gallery entries
Since the other tabs are kept in the dom now filtering is needed.
2022-09-23 23:38:45 +03:00
AUTOMATIC e12793e937 delete unwanted console.log 2022-09-23 23:34:33 +03:00
AUTOMATIC c8c662901b fix for inpaint at full resolution breaking if you have an NN upscaler. 2022-09-23 23:29:53 +03:00
AUTOMATIC 39ce23f42d add the bitton to paste parameters into UI for txt2img, img2img, and pnginfo tabs
fixed some [send to..] buttons to work properly with all tabs
2022-09-23 22:49:21 +03:00
AUTOMATIC 9c92a1a9aa removed some information that its owner decided he did not want to share 2022-09-23 20:55:54 +03:00
AUTOMATIC 8ffc07b7b1 one change didn't make it into the previous commit 2022-09-23 20:54:17 +03:00
AUTOMATIC 0065327726 upgrade to gradio==3.4b3 t fixthe inpain bugs
rework progressbar/preview to work with new gradio
remove unnecessary create style button
added link to alternative colab
2022-09-23 20:46:02 +03:00
24 changed files with 519 additions and 200 deletions
+5 -2
View File
@@ -1,7 +1,7 @@
# Stable Diffusion web UI
A browser interface based on Gradio library for Stable Diffusion.
![](screenshot.png)
![](txt2img_Screenshot.png)
## Features
[Detailed feature showcase with images](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Features):
@@ -51,7 +51,10 @@ A browser interface based on Gradio library for Stable Diffusion.
## Installation and Running
Make sure the required [dependencies](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Dependencies) are met and follow the instructions available for both [NVidia](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Install-and-Run-on-NVidia-GPUs) (recommended) and [AMD](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Install-and-Run-on-AMD-GPUs) GPUs.
Alternatively, use [Google Colab](https://colab.research.google.com/drive/1Iy-xW9t1-OQWhb0hNxueGij8phCyluOh).
Alternatively, use Google Colab:
- [Colab, maintained by Akaibu](https://colab.research.google.com/drive/1kw3egmSn-KgWsikYvOMjJkVDsPLjEMzl)
- [Colab, original by me, outdated](https://colab.research.google.com/drive/1Iy-xW9t1-OQWhb0hNxueGij8phCyluOh).
### Automatic Installation on Windows
1. Install [Python 3.10.6](https://www.python.org/downloads/windows/), checking "Add Python to PATH"
+15 -9
View File
@@ -68,13 +68,19 @@ window.addEventListener('paste', e => {
if ( ! isValidImageList( files ) ) {
return;
}
[...gradioApp().querySelectorAll('input[type=file][accept="image/x-png,image/gif,image/jpeg"]')]
.filter(input => !input.matches('.\\!hidden input[type=file]'))
.forEach(input => {
input.files = files;
input.dispatchEvent(new Event('change'))
});
[...gradioApp().querySelectorAll('[data-testid="image"]')]
.filter(imgWrap => !imgWrap.closest('.\\!hidden'))
.forEach(imgWrap => dropReplaceImage( imgWrap, files ));
const visibleImageFields = [...gradioApp().querySelectorAll('[data-testid="image"]')]
.filter(el => uiElementIsVisible(el));
if ( ! visibleImageFields.length ) {
return;
}
const firstFreeImageField = visibleImageFields
.filter(el => el.querySelector('input[type=file]'))?.[0];
dropReplaceImage(
firstFreeImageField ?
firstFreeImageField :
visibleImageFields[visibleImageFields.length - 1]
, files );
});
+4 -5
View File
@@ -13,6 +13,8 @@ titles = {
"Seed": "A value that determines the output of random number generator - if you create an image with same parameters and seed as another image, you'll get the same result",
"\u{1f3b2}\ufe0f": "Set seed to -1, which will cause a new random number to be used every time",
"\u267b\ufe0f": "Reuse seed from last generation, mostly useful if it was randomed",
"\u{1f3a8}": "Add a random artist to the prompt.",
"\u2199\ufe0f": "Read generation parameters from prompt into user interface.",
"Inpaint a part of image": "Draw a mask over an image, and the script will regenerate the masked area with content according to prompt",
"SD upscale": "Upscale image normally, split result into tiles, improve each tile using img2img, merge whole image back",
@@ -48,8 +50,6 @@ titles = {
"Tiling": "Produce an image that can be tiled.",
"Tile overlap": "For SD upscale, how much overlap in pixels should there be between tiles. Tiles overlap so that when they are merged back into one picture, there is no clearly visible seam.",
"Roll": "Add a random artist to the prompt.",
"Variation seed": "Seed of a different picture to be mixed into the generation.",
"Variation strength": "How strong of a variation to produce. At 0, there will be no effect. At 1, you will get the complete picture with variation seed (except for ancestral samplers, where you will just get something).",
"Resize seed from height": "Make an attempt to produce a picture similar to what would have been produced with same seed at specified resolution",
@@ -57,14 +57,13 @@ titles = {
"Interrogate": "Reconstruct prompt from existing image and put it into the prompt field.",
"Images filename pattern": "Use following tags to define how filenames for images are chosen: [steps], [cfg], [prompt], [prompt_spaces], [width], [height], [sampler], [seed], [model_hash], [prompt_words], [date]; leave empty for default.",
"Directory name pattern": "Use following tags to define how subdirectories for images and grids are chosen: [steps], [cfg], [prompt], [prompt_spaces], [width], [height], [sampler], [seed], [model_hash], [prompt_words], [date]; leave empty for default.",
"Images filename pattern": "Use following tags to define how filenames for images are chosen: [steps], [cfg], [prompt], [prompt_spaces], [width], [height], [styles], [sampler], [seed], [model_hash], [prompt_words], [date], [datetime], [job_timestamp]; leave empty for default.",
"Directory name pattern": "Use following tags to define how subdirectories for images and grids are chosen: [steps], [cfg], [prompt], [prompt_spaces], [width], [height], [styles], [sampler], [seed], [model_hash], [prompt_words], [date], [datetime], [job_timestamp]; leave empty for default.",
"Max prompt words": "Set the maximum number of words to be used in the [prompt_words] option; ATTENTION: If the words are too long, they may exceed the maximum length of the file path that the system can handle",
"Loopback": "Process an image, use it as an input, repeat.",
"Loops": "How many times to repeat processing an image and using it as input for the next iteration",
"Style 1": "Style to apply; styles have components for both positive and negative prompts and apply to both",
"Style 2": "Style to apply; styles have components for both positive and negative prompts and apply to both",
"Apply style": "Insert selected styles into prompt fields",
+14 -2
View File
@@ -22,10 +22,22 @@ function negmod(n, m) {
}
function modalImageSwitch(offset){
var galleryButtons = gradioApp().querySelectorAll(".gallery-item.transition-all")
var allgalleryButtons = gradioApp().querySelectorAll(".gallery-item.transition-all")
var galleryButtons = []
allgalleryButtons.forEach(function(elem){
if(elem.parentElement.offsetParent){
galleryButtons.push(elem);
}
})
if(galleryButtons.length>1){
var currentButton = gradioApp().querySelector(".gallery-item.transition-all.\\!ring-2")
var allcurrentButtons = gradioApp().querySelectorAll(".gallery-item.transition-all.\\!ring-2")
var currentButton = null
allcurrentButtons.forEach(function(elem){
if(elem.parentElement.offsetParent){
currentButton = elem;
}
})
var result = -1
galleryButtons.forEach(function(v, i){ if(v==currentButton) { result = i } })
+27 -29
View File
@@ -1,53 +1,51 @@
// code related to showing and updating progressbar shown as the image is being made
global_progressbar = null
global_progressbars = {}
onUiUpdate(function(){
progressbar = gradioApp().getElementById('progressbar')
progressDiv = gradioApp().querySelectorAll('#progressSpan').length > 0;
interrupt = gradioApp().getElementById('interrupt')
if(progressbar!= null && progressbar != global_progressbar){
global_progressbar = progressbar
function check_progressbar(id_part, id_progressbar, id_progressbar_span, id_interrupt, id_preview, id_gallery){
var progressbar = gradioApp().getElementById(id_progressbar)
var interrupt = gradioApp().getElementById(id_interrupt)
if(progressbar!= null && progressbar != global_progressbars[id_progressbar]){
global_progressbars[id_progressbar] = progressbar
var mutationObserver = new MutationObserver(function(m){
txt2img_preview = gradioApp().getElementById('txt2img_preview')
txt2img_gallery = gradioApp().getElementById('txt2img_gallery')
img2img_preview = gradioApp().getElementById('img2img_preview')
img2img_gallery = gradioApp().getElementById('img2img_gallery')
preview = gradioApp().getElementById(id_preview)
gallery = gradioApp().getElementById(id_gallery)
if(txt2img_preview != null && txt2img_gallery != null){
txt2img_preview.style.width = txt2img_gallery.clientWidth + "px"
txt2img_preview.style.height = txt2img_gallery.clientHeight + "px"
if(preview != null && gallery != null){
preview.style.width = gallery.clientWidth + "px"
preview.style.height = gallery.clientHeight + "px"
var progressDiv = gradioApp().querySelectorAll('#' + id_progressbar_span).length > 0;
if(!progressDiv){
interrupt.style.display = "none"
}
}
if(img2img_preview != null && img2img_gallery != null){
img2img_preview.style.width = img2img_gallery.clientWidth + "px"
img2img_preview.style.height = img2img_gallery.clientHeight + "px"
if(!progressDiv){
interrupt.style.display = "none"
}
}
window.setTimeout(requestMoreProgress, 500)
window.setTimeout(function(){ requestMoreProgress(id_part, id_progressbar_span, id_interrupt) }, 500)
});
mutationObserver.observe( progressbar, { childList:true, subtree:true })
}
}
onUiUpdate(function(){
check_progressbar('txt2img', 'txt2img_progressbar', 'txt2img_progress_span', 'txt2img_interrupt', 'txt2img_preview', 'txt2img_gallery')
check_progressbar('img2img', 'img2img_progressbar', 'img2img_progress_span', 'img2img_interrupt', 'img2img_preview', 'img2img_gallery')
})
function requestMoreProgress(){
btn = gradioApp().getElementById("check_progress");
function requestMoreProgress(id_part, id_progressbar_span, id_interrupt){
btn = gradioApp().getElementById(id_part+"_check_progress");
if(btn==null) return;
btn.click();
progressDiv = gradioApp().querySelectorAll('#progressSpan').length > 0;
if(progressDiv){
var progressDiv = gradioApp().querySelectorAll('#' + id_progressbar_span).length > 0;
var interrupt = gradioApp().getElementById(id_interrupt)
if(progressDiv && interrupt){
interrupt.style.display = "block"
}
}
function requestProgress(){
btn = gradioApp().getElementById("check_progress_initial");
function requestProgress(id_part){
btn = gradioApp().getElementById(id_part+"_check_progress_initial");
if(btn==null) return;
btn.click();
+48 -4
View File
@@ -25,13 +25,57 @@ function extract_image_from_gallery(gallery){
return gallery[index];
}
function extract_image_from_gallery_img2img(gallery){
function args_to_array(args){
res = []
for(var i=0;i<args.length;i++){
res.push(args[i])
}
return res
}
function switch_to_txt2img(){
gradioApp().querySelectorAll('button')[0].click();
return args_to_array(arguments);
}
function switch_to_img2img_img2img(){
gradioApp().querySelectorAll('button')[1].click();
gradioApp().getElementById('mode_img2img').querySelectorAll('button')[0].click();
return args_to_array(arguments);
}
function switch_to_img2img_inpaint(){
gradioApp().querySelectorAll('button')[1].click();
gradioApp().getElementById('mode_img2img').querySelectorAll('button')[1].click();
return args_to_array(arguments);
}
function switch_to_extras(){
gradioApp().querySelectorAll('button')[2].click();
return args_to_array(arguments);
}
function extract_image_from_gallery_txt2img(gallery){
switch_to_txt2img()
return extract_image_from_gallery(gallery);
}
function extract_image_from_gallery_img2img(gallery){
switch_to_img2img_img2img()
return extract_image_from_gallery(gallery);
}
function extract_image_from_gallery_inpaint(gallery){
switch_to_img2img_inpaint()
return extract_image_from_gallery(gallery);
}
function extract_image_from_gallery_extras(gallery){
gradioApp().querySelectorAll('button')[2].click();
switch_to_extras()
return extract_image_from_gallery(gallery);
}
@@ -79,13 +123,13 @@ function create_submit_args(args){
}
function submit(){
requestProgress()
requestProgress('txt2img')
return create_submit_args(arguments)
}
function submit_img2img(){
requestProgress()
requestProgress('img2img')
res = create_submit_args(arguments)
+4 -2
View File
@@ -102,6 +102,7 @@ def run_pnginfo(image):
return '', '', ''
items = image.info
geninfo = ''
if "exif" in image.info:
exif = piexif.load(image.info["exif"])
@@ -111,13 +112,14 @@ def run_pnginfo(image):
except ValueError:
exif_comment = exif_comment.decode('utf8', errors="ignore")
items['exif comment'] = exif_comment
geninfo = exif_comment
for field in ['jfif', 'jfif_version', 'jfif_unit', 'jfif_density', 'dpi', 'exif',
'loop', 'background', 'timestamp', 'duration']:
items.pop(field, None)
geninfo = items.get('parameters', geninfo)
info = ''
for key, text in items.items():
@@ -132,4 +134,4 @@ def run_pnginfo(image):
message = "Nothing found in the image."
info = f"<div><p>{message}<p></div>"
return '', '', info
return '', geninfo, info
@@ -0,0 +1,92 @@
import re
import gradio as gr
re_param_code = r"\s*([\w ]+):\s*([^,]+)(?:,|$)"
re_param = re.compile(re_param_code)
re_params = re.compile(r"^(?:" + re_param_code + "){3,}$")
re_imagesize = re.compile(r"^(\d+)x(\d+)$")
type_of_gr_update = type(gr.update())
def parse_generation_parameters(x: str):
"""parses generation parameters string, the one you see in text field under the picture in UI:
```
girl with an artist's beret, determined, blue eyes, desert scene, computer monitors, heavy makeup, by Alphonse Mucha and Charlie Bowater, ((eyeshadow)), (coquettish), detailed, intricate
Negative prompt: ugly, fat, obese, chubby, (((deformed))), [blurry], bad anatomy, disfigured, poorly drawn face, mutation, mutated, (extra_limb), (ugly), (poorly drawn hands), messy drawing
Steps: 20, Sampler: Euler a, CFG scale: 7, Seed: 965400086, Size: 512x512, Model hash: 45dee52b
```
returns a dict with field values
"""
res = {}
prompt = ""
negative_prompt = ""
done_with_prompt = False
*lines, lastline = x.strip().split("\n")
if not re_params.match(lastline):
lines.append(lastline)
lastline = ''
for i, line in enumerate(lines):
line = line.strip()
if line.startswith("Negative prompt:"):
done_with_prompt = True
line = line[16:].strip()
if done_with_prompt:
negative_prompt += ("" if negative_prompt == "" else "\n") + line
else:
prompt += ("" if prompt == "" else "\n") + line
if len(prompt) > 0:
res["Prompt"] = prompt
if len(negative_prompt) > 0:
res["Negative prompt"] = negative_prompt
for k, v in re_param.findall(lastline):
m = re_imagesize.match(v)
if m is not None:
res[k+"-1"] = m.group(1)
res[k+"-2"] = m.group(2)
else:
res[k] = v
return res
def connect_paste(button, paste_fields, input_comp, js=None):
def paste_func(prompt):
params = parse_generation_parameters(prompt)
res = []
for output, key in paste_fields:
if callable(key):
v = key(params)
else:
v = params.get(key, None)
if v is None:
res.append(gr.update())
elif isinstance(v, type_of_gr_update):
res.append(v)
else:
try:
valtype = type(output.value)
val = valtype(v)
res.append(gr.update(value=val))
except Exception:
res.append(gr.update())
return res
button.click(
fn=paste_func,
_js=js,
inputs=[input_comp],
outputs=[x[0] for x in paste_fields],
)
+4 -1
View File
@@ -210,7 +210,7 @@ def draw_prompt_matrix(im, width, height, all_prompts):
def resize_image(resize_mode, im, width, height):
def resize(im, w, h):
if opts.upscaler_for_img2img is None or opts.upscaler_for_img2img == "None":
if opts.upscaler_for_img2img is None or opts.upscaler_for_img2img == "None" or im.mode == 'L':
return im.resize((w, h), resample=LANCZOS)
upscaler = [x for x in shared.sd_upscalers if x.name == opts.upscaler_for_img2img][0]
@@ -290,10 +290,13 @@ def apply_filename_pattern(x, p, seed, prompt):
x = x.replace("[cfg]", str(p.cfg_scale))
x = x.replace("[width]", str(p.width))
x = x.replace("[height]", str(p.height))
x = x.replace("[styles]", sanitize_filename_part(", ".join(p.styles), replace_spaces=False))
x = x.replace("[sampler]", sanitize_filename_part(sd_samplers.samplers[p.sampler_index].name, replace_spaces=False))
x = x.replace("[model_hash]", shared.sd_model.sd_model_hash)
x = x.replace("[date]", datetime.date.today().isoformat())
x = x.replace("[datetime]", datetime.datetime.now().strftime("%Y%m%d%H%M%S"))
x = x.replace("[job_timestamp]", shared.state.job_timestamp)
if cmd_opts.hide_ui_dir_config:
x = re.sub(r'^[\\/]+|\.{2,}[\\/]+|[\\/]+\.{2,}', '', x)
+2
View File
@@ -108,6 +108,8 @@ def img2img(mode: int, prompt: str, negative_prompt: str, prompt_style: str, pro
p.extra_generation_params["Mask blur"] = mask_blur
if is_batch:
assert not shared.cmd_opts.hide_ui_dir_config, "Launched with --hide-ui-dir-config, batch img2img disabled"
process_batch(p, img2img_batch_input_dir, img2img_batch_output_dir, args)
processed = Processed(p, [], p.seed, "")
+5
View File
@@ -488,6 +488,11 @@ class StableDiffusionProcessingTxt2Img(StableDiffusionProcessing):
self.sampler = samplers[self.sampler_index].constructor(self.sd_model)
noise = create_random_tensors(samples.shape[1:], seeds=seeds, subseeds=subseeds, subseed_strength=subseed_strength, seed_resize_from_h=self.seed_resize_from_h, seed_resize_from_w=self.seed_resize_from_w, p=self)
# GC now before running the next img2img to prevent running out of memory
x = None
devices.torch_gc()
samples = self.sampler.sample_img2img(self, samples, noise, conditioning, unconditional_conditioning, steps=self.steps)
return samples
+1
View File
@@ -119,6 +119,7 @@ class ScriptRunner:
continue
for control in controls:
control.custom_script_source = os.path.basename(script.filename)
control.visible = False
inputs += controls
+3 -3
View File
@@ -201,7 +201,7 @@ class StableDiffusionModelHijack:
def process_file(path, filename):
name = os.path.splitext(filename)[0]
data = torch.load(path)
data = torch.load(path, map_location="cpu")
# textual inversion embeddings
if 'string_to_param' in data:
@@ -217,7 +217,7 @@ class StableDiffusionModelHijack:
if len(emb.shape) == 1:
emb = emb.unsqueeze(0)
self.word_embeddings[name] = emb.detach()
self.word_embeddings[name] = emb.detach().to(device)
self.word_embeddings_checksums[name] = f'{const_hash(emb.reshape(-1)*100)&0xffff:04x}'
ids = tokenizer([name], add_special_tokens=False)['input_ids'][0]
@@ -300,7 +300,7 @@ class FrozenCLIPEmbedderWithCustomWords(torch.nn.Module):
remade_batch_tokens = []
id_start = self.wrapped.tokenizer.bos_token_id
id_end = self.wrapped.tokenizer.eos_token_id
maxlen = self.wrapped.max_length - 2
maxlen = self.wrapped.max_length
used_custom_terms = []
cache = {}
+12 -1
View File
@@ -4,6 +4,7 @@ import json
import os
import gradio as gr
import tqdm
import datetime
import modules.artists
from modules.paths import script_path, sd_path
@@ -65,6 +66,7 @@ class State:
job = ""
job_no = 0
job_count = 0
job_timestamp = 0
sampling_step = 0
sampling_steps = 0
current_latent = None
@@ -78,6 +80,8 @@ class State:
self.job_no += 1
self.sampling_step = 0
self.current_image_sampling_step = 0
def get_job_timestamp(self):
return datetime.datetime.now().strftime("%Y%m%d%H%M%S")
state = State()
@@ -116,7 +120,7 @@ def options_section(section_identifer, options_dict):
return options_dict
hide_dirs = {"visible": False} if cmd_opts.hide_ui_dir_config else None
hide_dirs = {"visible": not cmd_opts.hide_ui_dir_config}
options_templates = {}
@@ -307,6 +311,13 @@ class TotalTQDM:
self.reset()
self._tqdm.update()
def updateTotal(self, new_total):
if not opts.multiple_tqdm:
return
if self._tqdm is None:
self.reset()
self._tqdm.total=new_total
def clear(self):
if self._tqdm is not None:
self._tqdm.close()
+156 -104
View File
@@ -27,6 +27,7 @@ import modules.scripts
import modules.gfpgan_model
import modules.codeformer_model
import modules.styles
import modules.generation_parameters_copypaste
# this is a fix for Windows users. Without it, javascript files will be served with text/html content-type and the bowser will not show any UI
mimetypes.init()
@@ -48,7 +49,6 @@ sample_img2img = sample_img2img if os.path.exists(sample_img2img) else None
css_hide_progressbar = """
.wrap .m-12 svg { display:none!important; }
.wrap .m-12::before { content:"Loading..." }
.progress-bar { display:none!important; }
.meta-text { display:none!important; }
"""
@@ -57,6 +57,8 @@ css_hide_progressbar = """
# Important that they exactly match script.js for tooltip to work.
random_symbol = '\U0001f3b2\ufe0f' # 🎲️
reuse_symbol = '\u267b\ufe0f' # ♻️
art_symbol = '\U0001f3a8' # 🎨
paste_symbol = '\u2199\ufe0f' # ↙
def plaintext_to_html(text):
@@ -166,7 +168,7 @@ def wrap_gradio_call(func):
return f
def check_progress_call():
def check_progress_call(id_part):
if shared.state.job_count == 0:
return "", gr_show(False), gr_show(False)
@@ -195,20 +197,20 @@ def check_progress_call():
image = shared.state.current_image
if image is None or progress >= 1:
if image is None:
image = gr.update(value=None)
else:
preview_visibility = gr_show(True)
return f"<span id='progressSpan' style='display: none'>{time.time()}</span><p>{progressbar}</p>", preview_visibility, image
return f"<span id='{id_part}_progress_span' style='display: none'>{time.time()}</span><p>{progressbar}</p>", preview_visibility, image
def check_progress_call_initial():
def check_progress_call_initial(id_part):
shared.state.job_count = -1
shared.state.current_latent = None
shared.state.current_image = None
return check_progress_call()
return check_progress_call(id_part)
def roll_artist(prompt):
@@ -236,8 +238,7 @@ def add_style(name: str, prompt: str, negative_prompt: str):
# reserialize all styles every time we save them
shared.prompt_styles.save_styles(shared.styles_filename)
update = {"visible": True, "choices": list(shared.prompt_styles.styles), "__type__": "update"}
return [update, update, update, update]
return [gr.Dropdown.update(visible=True, choices=list(shared.prompt_styles.styles)) for _ in range(4)]
def apply_styles(prompt, prompt_neg, style1_name, style2_name):
@@ -329,27 +330,32 @@ def connect_reuse_seed(seed: gr.Number, reuse_seed: gr.Button, generation_info:
def create_toprow(is_img2img):
id_part = "img2img" if is_img2img else "txt2img"
with gr.Row(elem_id="toprow"):
with gr.Column(scale=4):
with gr.Row():
with gr.Column(scale=8):
with gr.Column(scale=80):
with gr.Row():
prompt = gr.Textbox(label="Prompt", elem_id="prompt", show_label=False, placeholder="Prompt", lines=2)
roll = gr.Button('Roll', elem_id="roll", visible=len(shared.artist_db.artists) > 0)
with gr.Column(scale=1, elem_id="style_pos_col"):
prompt_style = gr.Dropdown(label="Style 1", elem_id="style_index", choices=[k for k, v in shared.prompt_styles.styles.items()], value=next(iter(shared.prompt_styles.styles.keys())), visible=len(shared.prompt_styles.styles) > 1)
with gr.Column(scale=1, elem_id="roll_col"):
roll = gr.Button(value=art_symbol, elem_id="roll", visible=len(shared.artist_db.artists) > 0)
paste = gr.Button(value=paste_symbol, elem_id="paste")
with gr.Column(scale=10, elem_id="style_pos_col"):
prompt_style = gr.Dropdown(label="Style 1", elem_id=f"{id_part}_style_index", choices=[k for k, v in shared.prompt_styles.styles.items()], value=next(iter(shared.prompt_styles.styles.keys())), visible=len(shared.prompt_styles.styles) > 1)
with gr.Row():
with gr.Column(scale=8):
negative_prompt = gr.Textbox(label="Negative prompt", elem_id="negative_prompt", show_label=False, placeholder="Negative prompt", lines=2)
with gr.Column(scale=1, elem_id="style_neg_col"):
prompt_style2 = gr.Dropdown(label="Style 2", elem_id="style2_index", choices=[k for k, v in shared.prompt_styles.styles.items()], value=next(iter(shared.prompt_styles.styles.keys())), visible=len(shared.prompt_styles.styles) > 1)
prompt_style2 = gr.Dropdown(label="Style 2", elem_id=f"{id_part}_style2_index", choices=[k for k, v in shared.prompt_styles.styles.items()], value=next(iter(shared.prompt_styles.styles.keys())), visible=len(shared.prompt_styles.styles) > 1)
with gr.Column(scale=1):
with gr.Row():
interrupt = gr.Button('Interrupt', elem_id="interrupt")
interrupt = gr.Button('Interrupt', elem_id=f"{id_part}_interrupt")
submit = gr.Button('Generate', elem_id="generate", variant='primary')
interrupt.click(
@@ -366,21 +372,21 @@ def create_toprow(is_img2img):
prompt_style_apply = gr.Button('Apply style', elem_id="style_apply")
save_style = gr.Button('Create style', elem_id="style_create")
return prompt, roll, prompt_style, negative_prompt, prompt_style2, submit, interrogate, prompt_style_apply, save_style
return prompt, roll, prompt_style, negative_prompt, prompt_style2, submit, interrogate, prompt_style_apply, save_style, paste
def setup_progressbar(progressbar, preview):
check_progress = gr.Button('Check progress', elem_id="check_progress", visible=False)
def setup_progressbar(progressbar, preview, id_part):
check_progress = gr.Button('Check progress', elem_id=f"{id_part}_check_progress", visible=False)
check_progress.click(
fn=check_progress_call,
fn=lambda: check_progress_call(id_part),
show_progress=False,
inputs=[],
outputs=[progressbar, preview, preview],
)
check_progress_initial = gr.Button('Check progress (first)', elem_id="check_progress_initial", visible=False)
check_progress_initial = gr.Button('Check progress (first)', elem_id=f"{id_part}_check_progress_initial", visible=False)
check_progress_initial.click(
fn=check_progress_call_initial,
fn=lambda: check_progress_call_initial(id_part),
show_progress=False,
inputs=[],
outputs=[progressbar, preview, preview],
@@ -389,23 +395,27 @@ def setup_progressbar(progressbar, preview):
def create_ui(txt2img, img2img, run_extras, run_pnginfo):
with gr.Blocks(analytics_enabled=False) as txt2img_interface:
txt2img_prompt, roll, txt2img_prompt_style, txt2img_negative_prompt, txt2img_prompt_style2, submit, _, txt2img_prompt_style_apply, txt2img_save_style = create_toprow(is_img2img=False)
txt2img_prompt, roll, txt2img_prompt_style, txt2img_negative_prompt, txt2img_prompt_style2, submit, _, txt2img_prompt_style_apply, txt2img_save_style, paste = create_toprow(is_img2img=False)
dummy_component = gr.Label(visible=False)
with gr.Row(elem_id='progressRow'):
with gr.Column(scale=1):
columnEmpty = "Empty"
with gr.Row(elem_id='txt2img_progress_row'):
with gr.Column(scale=1):
pass
with gr.Column(scale=1):
progressbar = gr.HTML(elem_id="progressbar")
with gr.Column(scale=1):
progressbar = gr.HTML(elem_id="txt2img_progressbar")
txt2img_preview = gr.Image(elem_id='txt2img_preview', visible=False)
setup_progressbar(progressbar, txt2img_preview)
setup_progressbar(progressbar, txt2img_preview, 'txt2img')
with gr.Row().style(equal_height=False):
with gr.Column(variant='panel'):
steps = gr.Slider(minimum=1, maximum=150, step=1, label="Sampling Steps", value=20)
sampler_index = gr.Radio(label='Sampling method', elem_id="txt2img_sampling", choices=[x.name for x in samplers], value=samplers[0].name, type="index")
with gr.Group():
width = gr.Slider(minimum=64, maximum=2048, step=64, label="Width", value=512)
height = gr.Slider(minimum=64, maximum=2048, step=64, label="Height", value=512)
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)
@@ -421,10 +431,6 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo):
cfg_scale = gr.Slider(minimum=1.0, maximum=30.0, step=0.5, label='CFG Scale', value=7.0)
with gr.Group():
width = gr.Slider(minimum=64, maximum=2048, step=64, label="Width", value=512)
height = gr.Slider(minimum=64, maximum=2048, step=64, label="Height", value=512)
seed, reuse_seed, subseed, reuse_subseed, subseed_strength, seed_resize_from_h, seed_resize_from_w, seed_checkbox = create_seed_inputs()
with gr.Group():
@@ -515,28 +521,48 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo):
]
)
txt2img_paste_fields = [
(txt2img_prompt, "Prompt"),
(txt2img_negative_prompt, "Negative prompt"),
(steps, "Steps"),
(sampler_index, "Sampler"),
(restore_faces, "Face restoration"),
(cfg_scale, "CFG scale"),
(seed, "Seed"),
(width, "Size-1"),
(height, "Size-2"),
(batch_size, "Batch size"),
(subseed, "Variation seed"),
(subseed_strength, "Variation seed strength"),
(seed_resize_from_w, "Seed resize from-1"),
(seed_resize_from_h, "Seed resize from-2"),
(denoising_strength, "Denoising strength"),
(enable_hr, lambda d: "Denoising strength" in d),
(hr_options, lambda d: gr.Row.update(visible="Denoising strength" in d)),
]
modules.generation_parameters_copypaste.connect_paste(paste, txt2img_paste_fields, txt2img_prompt)
with gr.Blocks(analytics_enabled=False) as img2img_interface:
img2img_prompt, roll, img2img_prompt_style, img2img_negative_prompt, img2img_prompt_style2, submit, img2img_interrogate, img2img_prompt_style_apply, img2img_save_style = create_toprow(is_img2img=True)
img2img_prompt, roll, img2img_prompt_style, img2img_negative_prompt, img2img_prompt_style2, submit, img2img_interrogate, img2img_prompt_style_apply, img2img_save_style, paste = create_toprow(is_img2img=True)
with gr.Row(elem_id='progressRow'):
with gr.Column(scale=1):
columnEmpty = "Empty"
with gr.Row(elem_id='img2img_progress_row'):
with gr.Column(scale=1):
pass
with gr.Column(scale=1):
progressbar = gr.HTML(elem_id="progressbar")
with gr.Column(scale=1):
progressbar = gr.HTML(elem_id="img2img_progressbar")
img2img_preview = gr.Image(elem_id='img2img_preview', visible=False)
setup_progressbar(progressbar, img2img_preview)
setup_progressbar(progressbar, img2img_preview, 'img2img')
with gr.Row().style(equal_height=False):
with gr.Column(variant='panel'):
with gr.Tabs(elem_id="mode_img2img") as tabs_img2img_mode:
with gr.TabItem('img2img'):
with gr.TabItem('img2img', id='img2img'):
init_img = gr.Image(label="Image for img2img", show_label=False, source="upload", interactive=True, type="pil")
with gr.TabItem('Inpaint'):
with gr.TabItem('Inpaint', id='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="<small>if the editor shows ERROR, switch to another tab and back, then to \"Upload mask\" mode above and back</small>")
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)
@@ -553,10 +579,11 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo):
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("<p class=\"text-gray-500\">Process images in a directory on the same machine where the server is running.</p>")
img2img_batch_input_dir = gr.Textbox(label="Input directory")
img2img_batch_output_dir = gr.Textbox(label="Output directory")
with gr.TabItem('Batch img2img', id='batch'):
hidden = '<br>Disabled when launched with --hide-ui-dir-config.' if shared.cmd_opts.hide_ui_dir_config else ''
gr.HTML(f"<p class=\"text-gray-500\">Process images in a directory on the same machine where the server is running.{hidden}</p>")
img2img_batch_input_dir = gr.Textbox(label="Input directory", **shared.hide_dirs)
img2img_batch_output_dir = gr.Textbox(label="Output directory", **shared.hide_dirs)
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")
@@ -564,6 +591,10 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo):
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")
with gr.Group():
width = gr.Slider(minimum=64, maximum=2048, step=64, label="Width", value=512)
height = gr.Slider(minimum=64, maximum=2048, step=64, label="Height", value=512)
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)
@@ -576,10 +607,6 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo):
cfg_scale = gr.Slider(minimum=1.0, maximum=30.0, step=0.5, label='CFG Scale', value=7.0)
denoising_strength = gr.Slider(minimum=0.0, maximum=1.0, step=0.01, label='Denoising strength', value=0.75)
with gr.Group():
width = gr.Slider(minimum=64, maximum=2048, step=64, label="Width", value=512)
height = gr.Slider(minimum=64, maximum=2048, step=64, label="Height", value=512)
seed, reuse_seed, subseed, reuse_subseed, subseed_strength, seed_resize_from_h, seed_resize_from_w, seed_checkbox = create_seed_inputs()
with gr.Group():
@@ -597,7 +624,6 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo):
img2img_send_to_img2img = gr.Button('Send to img2img')
img2img_send_to_inpaint = gr.Button('Send to inpaint')
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()
@@ -608,16 +634,13 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo):
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_with_mask,
init_img_with_mask_comment,
init_img_inpaint,
init_mask_inpaint,
],
@@ -720,12 +743,31 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo):
outputs=[prompt, negative_prompt, style1, style2],
)
img2img_paste_fields = [
(img2img_prompt, "Prompt"),
(img2img_negative_prompt, "Negative prompt"),
(steps, "Steps"),
(sampler_index, "Sampler"),
(restore_faces, "Face restoration"),
(cfg_scale, "CFG scale"),
(seed, "Seed"),
(width, "Size-1"),
(height, "Size-2"),
(batch_size, "Batch size"),
(subseed, "Variation seed"),
(subseed_strength, "Variation seed strength"),
(seed_resize_from_w, "Seed resize from-1"),
(seed_resize_from_h, "Seed resize from-2"),
(denoising_strength, "Denoising strength"),
]
modules.generation_parameters_copypaste.connect_paste(paste, img2img_paste_fields, img2img_prompt)
with gr.Blocks(analytics_enabled=False) as extras_interface:
with gr.Row().style(equal_height=False):
with gr.Column(variant='panel'):
with gr.Tabs(elem_id="mode_extras"):
with gr.TabItem('Single Image'):
image = gr.Image(label="Source", source="upload", interactive=True, type="pil")
extras_image = gr.Image(label="Source", source="upload", interactive=True, type="pil")
with gr.TabItem('Batch Process'):
image_batch = gr.File(label="Batch Process", file_count="multiple", interactive=True, type="file")
@@ -760,7 +802,7 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo):
_js="get_extras_tab_index",
inputs=[
dummy_component,
image,
extras_image,
image_batch,
gfpgan_visibility,
codeformer_visibility,
@@ -791,20 +833,25 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo):
outputs=[init_img_with_mask],
)
pnginfo_interface = gr.Interface(
wrap_gradio_call(run_pnginfo),
inputs=[
gr.Image(elem_id="pnginfo_image", label="Source", source="upload", interactive=True, type="pil"),
],
outputs=[
gr.HTML(),
gr.HTML(),
gr.HTML(),
],
allow_flagging="never",
analytics_enabled=False,
live=True,
)
with gr.Blocks(analytics_enabled=False) as pnginfo_interface:
with gr.Row().style(equal_height=False):
with gr.Column(variant='panel'):
image = gr.Image(elem_id="pnginfo_image", label="Source", source="upload", interactive=True, type="pil")
with gr.Column(variant='panel'):
html = gr.HTML()
generation_info = gr.Textbox(visible=False)
html2 = gr.HTML()
with gr.Row():
pnginfo_send_to_txt2img = gr.Button('Send to txt2img')
pnginfo_send_to_img2img = gr.Button('Send to img2img')
image.change(
fn=wrap_gradio_call(run_pnginfo),
inputs=[image],
outputs=[html, generation_info, html2],
)
def create_setting_component(key):
def fun():
@@ -853,7 +900,7 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo):
opts.save(shared.config_filename)
return f'{changed} settings changed.'
return f'{changed} settings changed.', opts.dumpjson()
with gr.Blocks(analytics_enabled=False) as settings_interface:
settings_submit = gr.Button(value="Apply settings", variant='primary')
@@ -898,12 +945,6 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo):
if column is not None:
column.__exit__()
settings_submit.click(
fn=run_settings,
inputs=components,
outputs=[result]
)
interfaces = [
(txt2img_interface, "txt2img", "txt2img"),
(img2img_interface, "img2img", "img2img"),
@@ -931,49 +972,39 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo):
interface.render()
text_settings = gr.Textbox(elem_id="settings_json", value=lambda: opts.dumpjson(), visible=False)
settings_submit.click(
fn=lambda: opts.dumpjson(),
inputs=[],
outputs=[text_settings],
)
tabs.change(
fn=lambda x: x,
inputs=[init_img_with_mask],
outputs=[init_img_with_mask],
)
tabs_img2img_mode.change(
fn=lambda x: x,
inputs=[init_img_with_mask],
outputs=[init_img_with_mask],
fn=run_settings,
inputs=components,
outputs=[result, text_settings],
)
paste_field_names = ['Prompt', 'Negative prompt', 'Steps', 'Face restoration', 'Seed', 'Size-1', 'Size-2']
txt2img_fields = [field for field,name in txt2img_paste_fields if name in paste_field_names]
img2img_fields = [field for field,name in img2img_paste_fields if name in paste_field_names]
send_to_img2img.click(
fn=lambda x: image_from_url_text(x),
_js="extract_image_from_gallery_img2img",
inputs=[txt2img_gallery],
outputs=[init_img],
fn=lambda img, *args: (image_from_url_text(img),*args),
_js="(gallery, ...args) => [extract_image_from_gallery_img2img(gallery), ...args]",
inputs=[txt2img_gallery] + txt2img_fields,
outputs=[init_img] + img2img_fields,
)
send_to_inpaint.click(
fn=lambda x: image_from_url_text(x),
_js="extract_image_from_gallery_img2img",
inputs=[txt2img_gallery],
outputs=[init_img_with_mask],
fn=lambda x, *args: (image_from_url_text(x), *args),
_js="(gallery, ...args) => [extract_image_from_gallery_inpaint(gallery), ...args]",
inputs=[txt2img_gallery] + txt2img_fields,
outputs=[init_img_with_mask] + img2img_fields,
)
img2img_send_to_img2img.click(
fn=lambda x: image_from_url_text(x),
_js="extract_image_from_gallery",
_js="extract_image_from_gallery_img2img",
inputs=[img2img_gallery],
outputs=[init_img],
)
img2img_send_to_inpaint.click(
fn=lambda x: image_from_url_text(x),
_js="extract_image_from_gallery",
_js="extract_image_from_gallery_inpaint",
inputs=[img2img_gallery],
outputs=[init_img_with_mask],
)
@@ -982,16 +1013,19 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo):
fn=lambda x: image_from_url_text(x),
_js="extract_image_from_gallery_extras",
inputs=[txt2img_gallery],
outputs=[image],
outputs=[extras_image],
)
img2img_send_to_extras.click(
fn=lambda x: image_from_url_text(x),
_js="extract_image_from_gallery_extras",
inputs=[img2img_gallery],
outputs=[image],
outputs=[extras_image],
)
modules.generation_parameters_copypaste.connect_paste(pnginfo_send_to_txt2img, txt2img_paste_fields, generation_info, 'switch_to_txt2img')
modules.generation_parameters_copypaste.connect_paste(pnginfo_send_to_img2img, img2img_paste_fields, generation_info, 'switch_to_img2img_img2img')
ui_config_file = cmd_opts.ui_config_file
ui_settings = {}
settings_count = len(ui_settings)
@@ -1010,12 +1044,21 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo):
def apply_field(obj, field, condition=None):
key = path + "/" + field
if getattr(obj,'custom_script_source',None) is not None:
key = 'customscript/' + obj.custom_script_source + '/' + key
if getattr(obj, 'do_not_save_to_config', False):
return
saved_value = ui_settings.get(key, None)
if saved_value is None:
ui_settings[key] = getattr(obj, field)
elif condition is None or condition(saved_value):
setattr(obj, field, saved_value)
if type(x) in [gr.Slider, gr.Radio, gr.Checkbox, gr.Textbox, gr.Number] and x.visible:
apply_field(x, 'visible')
if type(x) == gr.Slider:
apply_field(x, 'value')
apply_field(x, 'minimum')
@@ -1025,6 +1068,15 @@ def create_ui(txt2img, img2img, run_extras, run_pnginfo):
if type(x) == gr.Radio:
apply_field(x, 'value', lambda val: val in x.choices)
if type(x) == gr.Checkbox:
apply_field(x, 'value')
if type(x) == gr.Textbox:
apply_field(x, 'value')
if type(x) == gr.Number:
apply_field(x, 'value')
visit(txt2img_interface, loadsave, "txt2img")
visit(img2img_interface, loadsave, "img2img")
visit(extras_interface, loadsave, "extras")
+13 -15
View File
@@ -1,22 +1,20 @@
transformers
diffusers
basicsr
gfpgan
gradio
numpy
Pillow
realesrgan
torch
transformers
omegaconf
pytorch_lightning
diffusers
invisible-watermark
scikit-image>=0.19
fairscale==0.4.4
fonts
font-roboto
gfpgan
gradio
invisible-watermark
git+https://github.com/crowsonkb/k-diffusion.git
numpy
omegaconf
piexif
Pillow
pytorch_lightning
realesrgan
scikit-image>=0.19
git+https://github.com/TencentARC/GFPGAN.git@8d2447a2d918f8eba5a4a01463fd48e45126a379
timm==0.4.12
fairscale==0.4.4
piexif
transformers
torch
+1 -1
View File
@@ -2,7 +2,7 @@ transformers==4.19.2
diffusers==0.3.0
basicsr==1.4.2
gfpgan==1.3.8
gradio==3.3.1
gradio==3.4b3
numpy==1.23.3
Pillow==9.2.0
realesrgan==0.3.0
+46 -9
View File
@@ -2,24 +2,61 @@ function gradioApp(){
return document.getElementsByTagName('gradio-app')[0].shadowRoot;
}
function get_uiCurrentTab() {
return gradioApp().querySelector('.tabs button:not(.border-transparent)')
}
uiUpdateCallbacks = []
uiTabChangeCallbacks = []
let uiCurrentTab = null
function onUiUpdate(callback){
uiUpdateCallbacks.push(callback)
}
function onUiTabChange(callback){
uiTabChangeCallbacks.push(callback)
}
function uiUpdate(root){
uiUpdateCallbacks.forEach(function(x){
try {
x()
} catch (e) {
(console.error || console.log).call(console, e.message, e);
}
})
function runCallback(x){
try {
x()
} catch (e) {
(console.error || console.log).call(console, e.message, e);
}
}
function executeCallbacks(queue) {
queue.forEach(runCallback)
}
document.addEventListener("DOMContentLoaded", function() {
var mutationObserver = new MutationObserver(function(m){
uiUpdate(gradioApp());
executeCallbacks(uiUpdateCallbacks);
const newTab = get_uiCurrentTab();
if ( newTab && ( newTab !== uiCurrentTab ) ) {
uiCurrentTab = newTab;
executeCallbacks(uiTabChangeCallbacks);
}
});
mutationObserver.observe( gradioApp(), { childList:true, subtree:true })
});
/**
* checks that a UI element is not in another hidden element or tab content
*/
function uiElementIsVisible(el) {
let isVisible = !el.closest('.\\!hidden');
if ( ! isVisible ) {
return false;
}
while( isVisible = el.closest('.tabitem')?.style.display !== 'none' ) {
if ( ! isVisible ) {
return false;
} else if ( el.parentElement ) {
el = el.parentElement
} else {
break;
}
}
return isVisible;
}
+26 -5
View File
@@ -141,10 +141,11 @@ class Script(scripts.Script):
y_values = gr.Textbox(label="Y values", visible=False, lines=1)
draw_legend = gr.Checkbox(label='Draw legend', value=True)
return [x_type, x_values, y_type, y_values, draw_legend]
no_fixed_seeds = gr.Checkbox(label='Keep -1 for seeds', value=False)
def run(self, p, x_type, x_values, y_type, y_values, draw_legend):
return [x_type, x_values, y_type, y_values, draw_legend, no_fixed_seeds]
def run(self, p, x_type, x_values, y_type, y_values, draw_legend, no_fixed_seeds):
modules.processing.fix_seed(p)
p.batch_size = 1
@@ -169,7 +170,7 @@ class Script(scripts.Script):
end = int(mc.group(2))
num = int(mc.group(3)) if mc.group(3) is not None else 1
valslist_ext += [int(x) for x in np.linspace(start = start, stop = end, num = num).tolist()]
valslist_ext += [int(x) for x in np.linspace(start=start, stop=end, num=num).tolist()]
else:
valslist_ext.append(val)
@@ -191,7 +192,7 @@ class Script(scripts.Script):
end = float(mc.group(2))
num = int(mc.group(3)) if mc.group(3) is not None else 1
valslist_ext += np.linspace(start = start, stop = end, num = num).tolist()
valslist_ext += np.linspace(start=start, stop=end, num=num).tolist()
else:
valslist_ext.append(val)
@@ -207,6 +208,26 @@ class Script(scripts.Script):
y_opt = axis_options[y_type]
ys = process_axis(y_opt, y_values)
def fix_axis_seeds(axis_opt, axis_list):
if axis_opt.label == 'Seed':
return [int(random.randrange(4294967294)) if val is None or val == '' or val == -1 else val for val in axis_list]
else:
return axis_list
if not no_fixed_seeds:
xs = fix_axis_seeds(x_opt, xs)
ys = fix_axis_seeds(y_opt, ys)
if x_opt.label == 'Steps':
total_steps = sum(xs) * len(ys)
elif y_opt.label == 'Steps':
total_steps = sum(ys) * len(xs)
else:
total_steps = p.steps * len(xs) * len(ys)
print(f"X/Y plot will create {len(xs) * len(ys) * p.n_iter} images on a {len(xs)}x{len(ys)} grid. (Total steps to process: {total_steps * p.n_iter})")
shared.total_tqdm.updateTotal(total_steps * p.n_iter)
def cell(x, y):
pc = copy(p)
x_opt.apply(pc, x, xs)
+35 -8
View File
@@ -74,10 +74,21 @@
height: 100%;
}
#roll{
min-width: 1em;
max-width: 4em;
margin: 0.5em;
#roll_col{
min-width: unset !important;
flex-grow: 0 !important;
padding: 0.4em 0;
}
#roll, #paste{
min-width: 2em;
min-height: 2em;
max-width: 2em;
max-height: 2em;
flex-grow: 0;
padding-left: 0.25em;
padding-right: 0.25em;
margin: 0.1em 0;
}
#style_apply, #style_create, #interrogate{
@@ -89,7 +100,7 @@
min-width: 8em !important;
}
#style_index, #style2_index{
#txt2img_style_index, #txt2img_style2_index, #img2img_style_index, #img2img_style2_index{
margin-top: 1em;
}
@@ -143,7 +154,23 @@ button{
right: 0;
margin-left: auto;
margin-right: auto;
margin-top: 34px;
z-index: 100;
border: none;
border-top-left-radius: 0;
border-top-right-radius: 0;
}
@media screen and (min-width: 768px) {
#txt2img_preview, #img2img_preview {
position: absolute;
}
}
@media screen and (max-width: 767px) {
#txt2img_preview, #img2img_preview {
position: relative;
}
}
#txt2img_preview div.left-0.top-0, #img2img_preview div.left-0.top-0{
@@ -210,7 +237,7 @@ input[type="range"]{
#txt2img_negative_prompt, #img2img_negative_prompt{
}
#progressbar{
#txt2img_progressbar, #img2img_progressbar{
position: absolute;
z-index: 1000;
right: 0;
@@ -219,7 +246,7 @@ input[type="range"]{
display: block;
}
#progressRow{
#txt2img_progress_row, #img2img_progress_row{
margin-bottom: 10px;
margin-top: -18px;
}
@@ -354,7 +381,7 @@ input[type="range"]{
display:none
}
#interrupt{
#txt2img_interrupt, #img2img_interrupt{
position: absolute;
width: 100%;
height: 72px;
Binary file not shown.

After

Width:  |  Height:  |  Size: 526 KiB

+2
View File
@@ -3,6 +3,8 @@
if not defined PYTHON (set PYTHON=python)
if not defined VENV_DIR (set VENV_DIR=venv)
set ERROR_REPORTING=FALSE
mkdir tmp 2>NUL
%PYTHON% -c "" >tmp/stdout.txt 2>tmp/stderr.txt
+1
View File
@@ -50,6 +50,7 @@ def wrap_gradio_gpu_call(func):
shared.state.sampling_step = 0
shared.state.job_count = -1
shared.state.job_no = 0
shared.state.job_timestamp = shared.state.get_job_timestamp()
shared.state.current_latent = None
shared.state.current_image = None
shared.state.current_image_sampling_step = 0
+3
View File
@@ -41,6 +41,9 @@ then
venv_dir="venv"
fi
# Disable sentry logging
export ERROR_REPORTING=FALSE
# Do not reinstall existing pip packages on Debian/Ubuntu
export PIP_IGNORE_INSTALLED=0