Merge pull request #242 from Hakorr/main

Image item refactor
This commit is contained in:
cmdr2 2022-09-29 12:03:45 +05:30 committed by GitHub
commit a3b0cde59d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 107 additions and 133 deletions

View File

@ -70,38 +70,36 @@ label {
font-size: 8pt; font-size: 8pt;
} }
.imgSeedLabel { .imgSeedLabel {
position: absolute; font-size: 1em;
transform: translateX(-100%); background-color: rgb(44, 45, 48);
margin-top: 5pt; border-radius: 5px;
margin-left: -5pt; padding: 5px;
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: 55pt;
margin-left: -5pt;
} }
.imgItem { .imgItem {
display: inline; display: inline-block;
padding-right: 10px; margin-top: 1em;
margin-right: 1em;
}
.imgContainer {
display: flex;
justify-content: flex-end;
} }
.imgItemInfo { .imgItemInfo {
opacity: 0.5; padding-bottom: 0.5em;
display: flex;
align-items: flex-end;
flex-direction: column;
position: absolute;
padding: 5px;
opacity: 0.25;
transition: 0.1s all;
}
.imgContainer:hover > .imgItemInfo {
opacity: 1;
}
.imgItemInfo * {
margin-bottom: 7px;
} }
#container { #container {
width: 90%; width: 90%;
margin-left: auto; margin-left: auto;

View File

@ -259,18 +259,84 @@ async function healthCheck() {
} }
} }
function makeImageElement(width, height, outputContainer) { function showImages(req, res, livePreview) {
let imgItem = document.createElement('div') res.output.forEach((result, index) => {
imgItem.className = 'imgItem' if(typeof res != 'object') return;
let img = document.createElement('img') const imageData = result?.data || result?.path + '?t=' + new Date().getTime(),
img.width = parseInt(width) imageSeed = req.seed,
img.height = parseInt(height) imageWidth = req.width,
imageHeight = req.height,
imageIdentifier = 'IMG_ID_' + (imageSeed + '').replace(/\d/g, c => 'SUOMIPERKL'[c]) + 'X'.repeat(index);
imgItem.appendChild(img) if (!imageData.includes('/')) {
outputContainer.insertBefore(imgItem, outputContainer.firstChild) // res contained no data for the image, stop execution
return imgItem setStatus('request', 'invalid image', 'error');
return;
}
let imageItemElem = document.querySelector('#' + imageIdentifier);
if(!imageItemElem) {
imageItemElem = document.createElement('div');
imageItemElem.className = 'imgItem';
imageItemElem.id = imageIdentifier;
imageItemElem.innerHTML = `
<div class="imgContainer">
<img/>
<div class="imgItemInfo">
<span class="imgSeedLabel"></span>
<button class="imgUseBtn">Use as Input</button>
<button class="imgSaveBtn">Download</button>
</div>
</div>
`;
const useAsInputBtn = imageItemElem.querySelector('.imgUseBtn'),
saveImageBtn = imageItemElem.querySelector('.imgSaveBtn');
useAsInputBtn.addEventListener('click', e => {
const imgData = e.path.find(x => x == imageItemElem).querySelector('img').src;
initImageSelector.value = null;
initImagePreview.src = imgData;
initImagePreviewContainer.style.display = 'block';
inpaintingEditorContainer.style.display = 'none';
promptStrengthContainer.style.display = 'block';
maskSetting.checked = false;
// maskSetting.style.display = 'block';
randomSeedField.checked = false;
seedField.value = imageSeed;
seedField.disabled = false;
});
saveImageBtn.addEventListener('click', e => {
const imgData = e.path.find(x => x == imageItemElem).querySelector('img').src;
const imgDownload = document.createElement('a');
imgDownload.download = createFileName(imageSeed);
imgDownload.href = imgData;
imgDownload.click();
});
imagesContainer.appendChild(imageItemElem);
}
const imageElem = imageItemElem.querySelector('img'),
imageSeedLabel = imageItemElem.querySelector('.imgSeedLabel');
imageElem.src = imageData;
imageElem.width = parseInt(imageWidth);
imageElem.height = parseInt(imageHeight);
imageSeedLabel.innerText = livePreview
? '(Live Preview)'
: 'Seed: ' + imageSeed;
});
} }
// makes a single image. don't call this directly, use makeImage() instead // makes a single image. don't call this directly, use makeImage() instead
@ -291,14 +357,6 @@ async function doMakeImage(task) {
let seed = reqBody['seed'] let seed = reqBody['seed']
let numOutputs = parseInt(reqBody['num_outputs']) let numOutputs = parseInt(reqBody['num_outputs'])
let images = []
function makeImageContainers(numImages) {
for (let i = images.length; i < numImages; i++) {
images.push(makeImageElement(reqBody.width, reqBody.height, outputContainer))
}
}
try { try {
res = await fetch('/image', { res = await fetch('/image', {
method: 'POST', method: 'POST',
@ -351,14 +409,7 @@ async function doMakeImage(task) {
outputMsg.style.display = 'block' outputMsg.style.display = 'block'
if (stepUpdate.output !== undefined) { if (stepUpdate.output !== undefined) {
makeImageContainers(numOutputs) showImages(reqBody, stepUpdate, true);
for (idx in stepUpdate.output) {
let imgItem = images[idx]
let img = imgItem.firstChild
let tmpImageData = stepUpdate.output[idx]
img.src = tmpImageData['path'] + '?t=' + new Date().getTime()
}
} }
} }
} catch (e) { } catch (e) {
@ -426,87 +477,13 @@ async function doMakeImage(task) {
res = undefined res = undefined
} }
if (!res) { if (!res) return false;
return false
}
lastPromptUsed = reqBody['prompt'] lastPromptUsed = reqBody['prompt'];
makeImageContainers(res.output.length) showImages(reqBody, res, false);
for (let idx in res.output) { return true;
let imgBody = ''
let seed = 0
try {
let imgData = res.output[idx]
imgBody = imgData.data
seed = imgData.seed
} catch (e) {
console.log(imgBody)
setStatus('request', 'invalid image', 'error')
continue
}
let imgItem = images[idx]
let img = imgItem.firstChild
img.src = imgBody
let imgItemInfo = document.createElement('span')
imgItemInfo.className = 'imgItemInfo'
imgItemInfo.style.opacity = 0
let imgSeedLabel = document.createElement('span')
imgSeedLabel.className = 'imgSeedLabel'
imgSeedLabel.innerText = 'Seed: ' + seed
let imgUseBtn = document.createElement('button')
imgUseBtn.className = 'imgUseBtn'
imgUseBtn.innerText = 'Use as Input'
let imgSaveBtn = document.createElement('button')
imgSaveBtn.className = 'imgSaveBtn'
imgSaveBtn.innerText = 'Download'
imgItem.appendChild(imgItemInfo)
imgItemInfo.appendChild(imgSeedLabel)
imgItemInfo.appendChild(imgUseBtn)
imgItemInfo.appendChild(imgSaveBtn)
imgUseBtn.addEventListener('click', function() {
initImageSelector.value = null
initImagePreview.src = imgBody
initImagePreviewContainer.style.display = 'block'
inpaintingEditorContainer.style.display = 'none'
promptStrengthContainer.style.display = 'block'
maskSetting.checked = false
// maskSetting.style.display = 'block'
randomSeedField.checked = false
seedField.value = seed
seedField.disabled = false
})
imgSaveBtn.addEventListener('click', function() {
let imgDownload = document.createElement('a')
imgDownload.download = createFileName();
imgDownload.href = imgBody
imgDownload.click()
})
imgItem.addEventListener('mouseenter', function() {
imgItemInfo.style.opacity = 1
})
imgItem.addEventListener('mouseleave', function() {
imgItemInfo.style.opacity = 0
})
}
return true
} }
async function checkTasks() { async function checkTasks() {
@ -734,12 +711,11 @@ async function makeImage() {
// create a file name with embedded prompt and metadata // create a file name with embedded prompt and metadata
// for easier cateloging and comparison // for easier cateloging and comparison
function createFileName() { function createFileName(seed) {
// Most important information is the prompt // Most important information is the prompt
let underscoreName = lastPromptUsed.replace(/[^a-zA-Z0-9]/g, '_') let underscoreName = lastPromptUsed.replace(/[^a-zA-Z0-9]/g, '_')
underscoreName = underscoreName.substring(0, 100) underscoreName = underscoreName.substring(0, 100)
const seed = seedField.value
const steps = numInferenceStepsField.value const steps = numInferenceStepsField.value
const guidance = guidanceScaleField.value const guidance = guidanceScaleField.value