diff --git a/index.html b/index.html
index e4cbc816..a7ee3098 100644
--- a/index.html
+++ b/index.html
@@ -66,16 +66,29 @@
padding-top: 10px;
font-size: small;
}
- .imgUseBtn {
+ .imgSeedLabel {
position: absolute;
transform: translateX(-100%);
margin-top: 5pt;
margin-left: -5pt;
+ font-size: 10pt;
+
+ background-color: #333;
+ opacity: 0.8;
+ color: #ddd;
+ border-radius: 3pt;
+ padding: 1pt 3pt;
+ }
+ .imgUseBtn {
+ position: absolute;
+ transform: translateX(-100%);
+ margin-top: 30pt;
+ margin-left: -5pt;
}
.imgSaveBtn {
position: absolute;
transform: translateX(-100%);
- margin-top: 30pt;
+ margin-top: 55pt;
margin-left: -5pt;
}
.imgItem {
@@ -108,11 +121,11 @@
-
-
+
+
-
+
@@ -137,7 +150,8 @@ const SOUND_ENABLED_KEY = "soundEnabled"
const HEALTH_PING_INTERVAL = 5 // seconds
let promptField = document.querySelector('#prompt')
-let numOutputsField = document.querySelector('#num_outputs')
+let numOutputsTotalField = document.querySelector('#num_outputs_total')
+let numOutputsParallelField = document.querySelector('#num_outputs_parallel')
let numInferenceStepsField = document.querySelector('#num_inference_steps')
let guidanceScaleField = document.querySelector('#guidance_scale')
let guidanceScaleValueLabel = document.querySelector('#guidance_scale_value')
@@ -199,6 +213,12 @@ function setStatus(statusType, msg, msgType) {
}
}
+function logError(msg, res) {
+ outputMsg.innerHTML = 'Error: ' + msg + ''
+ console.log('request error', res)
+ setStatus('request', 'error', 'error')
+}
+
function playSound() {
const audio = new Audio('/media/ding.mp3')
audio.volume = 0.2
@@ -220,43 +240,10 @@ async function healthCheck() {
}
}
-async function makeImage() {
- setStatus('request', 'fetching..')
-
- makeImageBtn.innerHTML = 'Processing..'
- makeImageBtn.disabled = true
-
- outputMsg.innerHTML = 'Fetching..'
-
- function logError(msg, res) {
- outputMsg.innerHTML = 'Error: ' + msg + ''
- console.log('request error', res)
- setStatus('request', 'error', 'error')
- }
-
- let seed = (randomSeedField.checked ? Math.floor(Math.random() * 10000) : seedField.value)
-
- let reqBody = {
- prompt: promptField.value,
- num_outputs: numOutputsField.value,
- num_inference_steps: numInferenceStepsField.value,
- guidance_scale: guidanceScaleField.value / 10,
- width: widthField.value,
- height: heightField.value,
- seed: seed,
- }
-
- if (initImagePreview.src.indexOf('data:image/png;base64') !== -1) {
- reqBody['init_image'] = initImagePreview.src
- reqBody['prompt_strength'] = promptStrengthField.value / 10
-
- if (maskImagePreview.src.indexOf('data:image/png;base64') !== -1) {
- reqBody['mask'] = maskImagePreview.src
- }
- }
-
+// makes a single image. don't call this directly, use makeImage() instead
+async function doMakeImage(reqBody) {
let res = ''
- let time = new Date().getTime()
+ let seed = reqBody['seed']
try {
res = await fetch('/image', {
@@ -293,24 +280,10 @@ async function makeImage() {
setStatus('request', 'error', 'error')
}
- makeImageBtn.innerHTML = 'Make Image'
- makeImageBtn.disabled = false
-
- if (isSoundEnabled()) {
- playSound()
- }
-
if (!res) {
return
}
- time = new Date().getTime() - time
- time /= 1000
-
- outputMsg.innerHTML = 'Processed in ' + time + ' seconds. Seed: ' + seed
-
- imagesContainer.innerHTML = ''
-
for (let idx in res.output) {
let imgBody = ''
@@ -319,7 +292,7 @@ async function makeImage() {
} catch (e) {
console.log(imgBody)
setStatus('request', 'invalid image', 'error')
- return
+ continue
}
let imgItem = document.createElement('div')
@@ -330,6 +303,10 @@ async function makeImage() {
img.height = parseInt(reqBody.height)
img.src = imgBody
+ let imgSeedLabel = document.createElement('span')
+ imgSeedLabel.className = 'imgSeedLabel'
+ imgSeedLabel.innerHTML = 'Seed: ' + seed
+
let imgUseBtn = document.createElement('button')
imgUseBtn.className = 'imgUseBtn'
imgUseBtn.innerHTML = 'Use as Input'
@@ -339,6 +316,7 @@ async function makeImage() {
imgSaveBtn.innerHTML = 'Download'
imgItem.appendChild(img)
+ imgItem.appendChild(imgSeedLabel)
imgItem.appendChild(imgUseBtn)
imgItem.appendChild(imgSaveBtn)
imagesContainer.appendChild(imgItem)
@@ -364,6 +342,62 @@ async function makeImage() {
imgDownload.click()
})
}
+}
+
+async function makeImage() {
+ setStatus('request', 'fetching..')
+
+ makeImageBtn.innerHTML = 'Processing..'
+ makeImageBtn.disabled = true
+
+ outputMsg.innerHTML = 'Fetching..'
+
+ let seed = (randomSeedField.checked ? Math.floor(Math.random() * 10000) : parseInt(seedField.value))
+ let numOutputsTotal = parseInt(numOutputsTotalField.value)
+ let numOutputsParallel = parseInt(numOutputsParallelField.value)
+ let batchCount = Math.ceil(numOutputsTotal / numOutputsParallel)
+ let batchSize = numOutputsParallel
+
+ let reqBody = {
+ prompt: promptField.value,
+ num_outputs: batchSize,
+ num_inference_steps: numInferenceStepsField.value,
+ guidance_scale: parseInt(guidanceScaleField.value) / 10,
+ width: widthField.value,
+ height: heightField.value,
+ }
+
+ if (initImagePreview.src.indexOf('data:image/png;base64') !== -1) {
+ reqBody['init_image'] = initImagePreview.src
+ reqBody['prompt_strength'] = parseInt(promptStrengthField.value) / 10
+
+ if (maskImagePreview.src.indexOf('data:image/png;base64') !== -1) {
+ reqBody['mask'] = maskImagePreview.src
+ }
+ }
+
+ let time = new Date().getTime()
+ imagesContainer.innerHTML = ''
+
+ for (let i = 0; i < batchCount; i++) {
+ reqBody['seed'] = seed + i
+
+ await doMakeImage(reqBody)
+
+ outputMsg.innerHTML = 'Processed batch ' + (i+1) + '/' + batchCount
+ }
+
+ makeImageBtn.innerHTML = 'Make Image'
+ makeImageBtn.disabled = false
+
+ if (isSoundEnabled()) {
+ playSound()
+ }
+
+ time = new Date().getTime() - time
+ time /= 1000
+
+ outputMsg.innerHTML = 'Processed ' + numOutputsTotal + ' images in ' + time + ' seconds'
setStatus('request', 'done', 'success')