script.js 14.1 KB
Newer Older
1 2


3
titles = {
4
    "Sampling steps": "How many times to improve the generated image iteratively; higher values take longer; very low values can produce bad results",
5 6
    "Sampling method": "Which algorithm to use to produce the image",
	"GFPGAN": "Restore low quality faces using GFPGAN neural network",
7
	"Euler a": "Euler Ancestral - very creative, each can get a completely different picture depending on step count, setting steps to higher than 30-40 does not help",
8
	"DDIM": "Denoising Diffusion Implicit Models - best at inpainting",
A
AUTOMATIC 已提交
9

10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
	"Batch count": "How many batches of images to create",
	"Batch size": "How many image to create in a single batch",
    "CFG Scale": "Classifier Free Guidance Scale - how strongly the image should conform to prompt - lower values produce more creative results",
    "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",

    "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",

    "Just resize": "Resize image to target resolution. Unless height and width match, you will get incorrect aspect ratio.",
    "Crop and resize": "Resize the image so that entirety of target resolution is filled with the image. Crop parts that stick out.",
    "Resize and fill": "Resize the image so that entirety of image is inside target resolution. Fill empty space with image's colors.",

    "Mask blur": "How much to blur the mask before processing, in pixels.",
    "Masked content": "What to put inside the masked area before processing it with Stable Diffusion.",
    "fill": "fill it with colors of the image",
    "original": "keep whatever was there originally",
    "latent noise": "fill it with latent space noise",
    "latent nothing": "fill it with latent space zeroes",
    "Inpaint at full resolution": "Upscale masked region to target resolution, do inpainting, downscale back and paste into original image",

30
    "Denoising strength": "Determines how little respect the algorithm should have for image's content. At 0, nothing will change, and at 1 you'll get an unrelated image. With values below 1.0, processing will take less steps than the Sampling Steps slider specifies.",
31
    "Denoising strength change factor": "In loopback mode, on each loop the denoising strength is multiplied by this value. <1 means decreasing variety so your sequence will converge on a fixed picture. >1 means increasing variety so your sequence will become more and more chaotic.",
A
AUTOMATIC 已提交
32 33 34

    "Interrupt": "Stop processing images and return any results accumulated so far.",
    "Save": "Write image to a directory (default - log/images) and generation parameters into csv file.",
A
AUTOMATIC 已提交
35 36 37 38 39 40

    "X values": "Separate values for X axis using commas.",
    "Y values": "Separate values for Y axis using commas.",

    "None": "Do not do anything special",
    "Prompt matrix": "Separate prompts into parts using vertical pipe character (|) and the script will create a picture for every combination of them (except for the first part, which will be present in all combinations)",
41 42
    "X/Y plot": "Create a grid where images will have different parameters. Use inputs below to specify which parameters will be shared by columns and rows",
    "Custom code": "Run Python code. Advanced user only. Must run program with --allow-code for this to work",
A
AUTOMATIC 已提交
43 44

    "Prompt S/R": "Separate a list of words with commas, and the first word will be used as a keyword: script will search for this word in the prompt, and replace it with others",
45 46

    "Tiling": "Produce an image that can be tiled.",
47
    "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.",
48

A
AUTOMATIC 已提交
49
    "Roll": "Add a random artist to the prompt.",
50 51 52 53 54

    "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",
    "Resize seed from width": "Make an attempt to produce a picture similar to what would have been produced with same seed at specified resolution",
A
AUTOMATIC 已提交
55

A
Austere Grim 已提交
56
    "Interrogate": "Reconstruct prompt from existing image and put it into the prompt field.",
57 58 59

    "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.",
60 61 62

    "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",
A
AUTOMATIC 已提交
63 64 65 66 67 68


    "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",
    "Create style": "Save current prompts as a style. If you add the token {prompt} to the text, the style use that as placeholder for your prompt when you use the style in the future.",
69 70

    "Checkpoint name": "Loads weights from checkpoint before making images. You can either use hash or a part of filename (as seen in settings) for checkpoint name. Recommended to use with Y axis for less switching.",
71 72 73
}

function gradioApp(){
74
    return document.getElementsByTagName('gradio-app')[0].shadowRoot;
75 76
}

A
AUTOMATIC 已提交
77 78
global_progressbar = null

D
DepFA 已提交
79 80 81 82
function closeModal() {
  gradioApp().getElementById("lightboxModal").style.display = "none";
}

83 84 85
function showModal(event) {
  var source = event.target || event.srcElement;
  gradioApp().getElementById("modalImage").src = source.src
86 87 88
  var lb = gradioApp().getElementById("lightboxModal")
  lb.style.display = "block";
  lb.focus()
89
  event.stopPropagation()
D
DepFA 已提交
90 91
}

92 93 94 95 96 97
function negmod(n, m) {
  return ((n % m) + m) % m;
}

function modalImageSwitch(offset){
  var galleryButtons = gradioApp().querySelectorAll(".gallery-item.transition-all")
98

99 100
  if(galleryButtons.length>1){
      var currentButton  = gradioApp().querySelector(".gallery-item.transition-all.\\!ring-2")
101

102 103
      var result = -1
      galleryButtons.forEach(function(v, i){ if(v==currentButton) { result = i } })
D
DepFA 已提交
104

105 106 107 108 109 110 111
      if(result != -1){
        nextButton = galleryButtons[negmod((result+offset),galleryButtons.length)]
        nextButton.click()
        gradioApp().getElementById("modalImage").src = nextButton.children[0].src
        setTimeout( function(){gradioApp().getElementById("lightboxModal").focus()},10)
      }
  }
112

113
}
D
DepFA 已提交
114

115 116 117
function modalNextImage(event){
  modalImageSwitch(1)
  event.stopPropagation()
D
DepFA 已提交
118 119
}

120 121 122 123 124 125 126 127 128 129 130 131 132
function modalPrevImage(event){
  modalImageSwitch(-1)  
  event.stopPropagation()
}

function modalKeyHandler(event){
    switch (event.key) {
        case "ArrowLeft":
            modalPrevImage(event)
            break;
        case "ArrowRight":
            modalNextImage(event)
            break;
133 134 135
    }
}

D
typo  
DepFA 已提交
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
function showGalleryImage(){
    setTimeout(function() {
        fullImg_preview = gradioApp().querySelectorAll('img.w-full.object-contain')
        
        if(fullImg_preview != null){
            fullImg_preview.forEach(function function_name(e) {
                if(e && e.parentElement.tagName == 'DIV'){

                    e.style.cursor='pointer'

                    e.addEventListener('click', function (evt) {
                      showModal(evt)

                    },true);
                }
            });
        }

    }, 100);
}

function galleryImageHandler(e){
    if(e && e.parentElement.tagName == 'BUTTON'){
        e.onclick = showGalleryImage;
    }
}

163
function addTitles(root){
A
AUTOMATIC 已提交
164
	root.querySelectorAll('span, button, select').forEach(function(span){
165
		tooltip = titles[span.textContent];
A
AUTOMATIC 已提交
166 167 168 169 170

		if(!tooltip){
		    tooltip = titles[span.value];
		}

171 172 173 174
		if(tooltip){
			span.title = tooltip;
		}
	})
A
AUTOMATIC 已提交
175 176 177 178 179 180 181 182

	root.querySelectorAll('select').forEach(function(select){
	    if (select.onchange != null) return;

	    select.onchange = function(){
            select.title = titles[select.value] || "";
	    }
	})
A
AUTOMATIC 已提交
183 184 185 186 187 188

	progressbar = root.getElementById('progressbar')
	if(progressbar!= null && progressbar != global_progressbar){
	    global_progressbar = progressbar

        var mutationObserver = new MutationObserver(function(m){
A
AUTOMATIC 已提交
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
            txt2img_preview = gradioApp().getElementById('txt2img_preview')
            txt2img_gallery = gradioApp().getElementById('txt2img_gallery')

            img2img_preview = gradioApp().getElementById('img2img_preview')
            img2img_gallery = gradioApp().getElementById('img2img_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(img2img_preview != null && img2img_gallery != null){
                img2img_preview.style.width = img2img_gallery.clientWidth + "px"
                img2img_preview.style.height = img2img_gallery.clientHeight + "px"
            }
D
DepFA 已提交
204
		
A
AUTOMATIC 已提交
205 206 207 208
            window.setTimeout(requestProgress, 500)
        });
        mutationObserver.observe( progressbar, { childList:true, subtree:true })
	}
209 210
	
	fullImg_preview = gradioApp().querySelectorAll('img.w-full')
A
AUTOMATIC 已提交
211

212 213 214 215
	    if(fullImg_preview != null){
		fullImg_preview.forEach(galleryImageHandler);
	}
	
216 217 218 219
}

document.addEventListener("DOMContentLoaded", function() {
    var mutationObserver = new MutationObserver(function(m){
220
        addTitles(gradioApp());
221
    });
222
    mutationObserver.observe( gradioApp(), { childList:true, subtree:true })
D
DepFA 已提交
223 224 225 226 227 228 229 230 231 232
	
    const modalFragment = document.createDocumentFragment();
    const modal = document.createElement('div')
    modal.onclick = closeModal;
    
    const modalClose = document.createElement('span')
    modalClose.className = 'modalClose cursor';
    modalClose.innerHTML = '&times;'
    modalClose.onclick = closeModal;
    modal.id = "lightboxModal";
233 234
    modal.tabIndex=0
    modal.addEventListener('keydown', modalKeyHandler, true)
D
DepFA 已提交
235 236 237 238 239
    modal.appendChild(modalClose)

    const modalImage = document.createElement('img')
    modalImage.id = 'modalImage';
    modalImage.onclick = closeModal;
240 241
    modalImage.tabIndex=0
    modalImage.addEventListener('keydown', modalKeyHandler, true)
D
DepFA 已提交
242 243
    modal.appendChild(modalImage)

244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
    const modalPrev = document.createElement('a')
    modalPrev.className = 'modalPrev';
    modalPrev.innerHTML = '&#10094;'
    modalPrev.tabIndex=0
    modalPrev.addEventListener('click',modalPrevImage,true);
    modalPrev.addEventListener('keydown', modalKeyHandler, true)
    modal.appendChild(modalPrev)

    const modalNext = document.createElement('a')
    modalNext.className = 'modalNext';
    modalNext.innerHTML = '&#10095;'
    modalNext.tabIndex=0
    modalNext.addEventListener('click',modalNextImage,true);
    modalNext.addEventListener('keydown', modalKeyHandler, true)

    modal.appendChild(modalNext)


D
DepFA 已提交
262 263 264 265
    gradioApp().getRootNode().appendChild(modal)
    
    document.body.appendChild(modalFragment);
	
266
});
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286

function selected_gallery_index(){
    var gr = gradioApp()
    var buttons = gradioApp().querySelectorAll(".gallery-item")
    var button = gr.querySelector(".gallery-item.\\!ring-2")

    var result = -1
    buttons.forEach(function(v, i){ if(v==button) { result = i } })

    return result
}

function extract_image_from_gallery(gallery){
    if(gallery.length == 1){
        return gallery[0]
    }

    index = selected_gallery_index()

    if (index < 0 || index >= gallery.length){
A
AUTOMATIC 已提交
287
        return [null]
288 289 290
    }

    return gallery[index];
S
Seki 已提交
291 292 293 294 295 296 297 298 299 300
}

function extract_image_from_gallery_img2img(gallery){
    gradioApp().querySelectorAll('button')[1].click();
    return extract_image_from_gallery(gallery);
}

function extract_image_from_gallery_extras(gallery){
    gradioApp().querySelectorAll('button')[2].click();
    return extract_image_from_gallery(gallery);
301
}
A
AUTOMATIC 已提交
302 303 304 305 306 307 308 309 310 311 312 313

function requestProgress(){
    btn = gradioApp().getElementById("check_progress");
    if(btn==null) return;

    btn.click();
}

function submit(){
    window.setTimeout(requestProgress, 500)

    res = []
314
    for(var i=0;i<arguments.length;i++){
A
AUTOMATIC 已提交
315 316
        res.push(arguments[i])
    }
317 318 319 320 321 322 323 324 325

    // As it is currently, txt2img and img2img send back the previous output args (txt2img_gallery, generation_info, html_info) whenever you generate a new image.
    // This can lead to uploading a huge gallery of previously generated images, which leads to an unnecessary delay between submitting and beginning to generate.
    // I don't know why gradio is seding outputs along with inputs, but we can prevent sending the image gallery here, which seems to be an issue for some.
    // If gradio at some point stops sending outputs, this may break something
    if(Array.isArray(res[res.length - 3])){
        res[res.length - 3] = null
    }

A
AUTOMATIC 已提交
326
    return res
327
}
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343

window.addEventListener('paste', e => {
    const files = e.clipboardData.files;
    if (!files || files.length !== 1) {
        return;
    }
    if (!['image/png', 'image/gif', 'image/jpeg'].includes(files[0].type)) {
        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'))
        });
});
A
AUTOMATIC 已提交
344

345 346 347
function ask_for_style_name(_, prompt_text, negative_prompt_text) {
    name_ = prompt('Style name:')
    return name_ === null ? [null, null, null]: [name_, prompt_text, negative_prompt_text]
A
AUTOMATIC 已提交
348
}