mirror of
https://github.com/easydiffusion/easydiffusion.git
synced 2025-06-25 12:22:49 +02:00
Merge branch 'beta' of https://github.com/patriceac/stable-diffusion-ui into beta
This commit is contained in:
commit
145e083f8e
@ -21,6 +21,10 @@
|
||||
Our focus continues to remain on an easy installation experience, and an easy user-interface. While still remaining pretty powerful, in terms of features and speed.
|
||||
|
||||
### Detailed changelog
|
||||
* 2.5.30 - 28 Mar 2023 - Refactor task entry config to use a generating method. Added ability for plugins to easily add to this. Removed confusing sentence from `contributing.md`
|
||||
* 2.5.30 - 28 Mar 2023 - Allow the user to undo the deletion of tasks or images, instead of showing a pop-up each time. The new `Undo` button will be present at the top of the UI. Thanks @JeLuf.
|
||||
* 2.5.30 - 28 Mar 2023 - Support saving lossless WEBP images. Thanks @ogmaresca.
|
||||
* 2.5.30 - 28 Mar 2023 - Lots of bug fixes for the UI (Read LoRA flag in metadata files, new prompt weight format with scrollwheel, fix overflow with lots of tabs, clear button in image editor, shorter filenames in download). Thanks @patriceac, @JeLuf and @ogmaresca.
|
||||
* 2.5.29 - 27 Mar 2023 - Fix a bug where some non-square images would fail while inpainting with a `The size of tensor a must match size of tensor b` error.
|
||||
* 2.5.29 - 27 Mar 2023 - Fix the `incorrect number of channels` error, when given a PNG image with an alpha channel in `Test Diffusers`.
|
||||
* 2.5.29 - 27 Mar 2023 - Fix broken inpainting in `Test Diffusers` (beta).
|
||||
|
@ -42,8 +42,6 @@ or for Windows
|
||||
10) Congrats, now any changes you make in your repo `ui` folder are linked to this running archive of the app and can be previewed in the browser.
|
||||
11) Please update CHANGES.md in your pull requests.
|
||||
|
||||
Check the `ui/frontend/build/README.md` for instructions on running and building the React code.
|
||||
|
||||
## Development environment for Installer changes
|
||||
Build the Windows installer using Windows, and the Linux installer using Linux. Don't mix the two, and don't use WSL. An Ubuntu VM is fine for building the Linux installer on a Windows host.
|
||||
|
||||
|
@ -95,7 +95,7 @@ if "%ERRORLEVEL%" EQU "0" (
|
||||
set PYTHONNOUSERSITE=1
|
||||
set PYTHONPATH=%INSTALL_ENV_DIR%\lib\site-packages
|
||||
|
||||
call python -m pip install --upgrade sdkit==1.0.59 -q || (
|
||||
call python -m pip install --upgrade sdkit==1.0.61 -q || (
|
||||
echo "Error updating sdkit"
|
||||
)
|
||||
)
|
||||
@ -106,7 +106,7 @@ if "%ERRORLEVEL%" EQU "0" (
|
||||
set PYTHONNOUSERSITE=1
|
||||
set PYTHONPATH=%INSTALL_ENV_DIR%\lib\site-packages
|
||||
|
||||
call python -m pip install sdkit==1.0.59 || (
|
||||
call python -m pip install sdkit==1.0.61 || (
|
||||
echo "Error installing sdkit. Sorry about that, please try to:" & echo " 1. Run this installer again." & echo " 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/wiki/Troubleshooting" & echo " 3. If those steps don't help, please copy *all* the error messages in this window, and ask the community at https://discord.com/invite/u9yhsFmEkB" & echo " 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues" & echo "Thanks!"
|
||||
pause
|
||||
exit /b
|
||||
|
@ -103,7 +103,7 @@ if python ../scripts/check_modules.py sdkit sdkit.models ldm transformers numpy
|
||||
export PYTHONNOUSERSITE=1
|
||||
export PYTHONPATH="$INSTALL_ENV_DIR/lib/python3.8/site-packages"
|
||||
|
||||
python -m pip install --upgrade sdkit==1.0.59 -q
|
||||
python -m pip install --upgrade sdkit==1.0.61 -q
|
||||
fi
|
||||
else
|
||||
echo "Installing sdkit: https://pypi.org/project/sdkit/"
|
||||
@ -111,7 +111,7 @@ else
|
||||
export PYTHONNOUSERSITE=1
|
||||
export PYTHONPATH="$INSTALL_ENV_DIR/lib/python3.8/site-packages"
|
||||
|
||||
if python -m pip install sdkit==1.0.59 ; then
|
||||
if python -m pip install sdkit==1.0.61 ; then
|
||||
echo "Installed."
|
||||
else
|
||||
fail "sdkit install failed"
|
||||
|
@ -147,7 +147,7 @@ def filter_images(task_data: TaskData, images: list, user_stopped):
|
||||
def construct_response(images: list, seeds: list, task_data: TaskData, base_seed: int):
|
||||
return [
|
||||
ResponseImage(
|
||||
data=img_to_base64_str(img, task_data.output_format, task_data.output_quality),
|
||||
data=img_to_base64_str(img, task_data.output_format, task_data.output_quality, task_data.output_lossless),
|
||||
seed=seed,
|
||||
)
|
||||
for img, seed in zip(images, seeds)
|
||||
|
@ -43,6 +43,7 @@ class TaskData(BaseModel):
|
||||
block_nsfw: bool = False
|
||||
output_format: str = "jpeg" # or "png" or "webp"
|
||||
output_quality: int = 75
|
||||
output_lossless: bool = False
|
||||
metadata_output_format: str = "txt" # or "json"
|
||||
stream_image_progress: bool = False
|
||||
stream_image_progress_interval: int = 5
|
||||
|
@ -45,13 +45,16 @@ def save_images_to_disk(images: list, filtered_images: list, req: GenerateImageR
|
||||
file_name=make_filename,
|
||||
output_format=task_data.output_format,
|
||||
output_quality=task_data.output_quality,
|
||||
output_lossless=task_data.output_lossless,
|
||||
)
|
||||
if task_data.metadata_output_format.lower() in ["json", "txt", "embed"]:
|
||||
if task_data.metadata_output_format:
|
||||
for metadata_output_format in task_data.metadata_output_format.split(','):
|
||||
if metadata_output_format.lower() in ["json", "txt", "embed"]:
|
||||
save_dicts(
|
||||
metadata_entries,
|
||||
save_dir_path,
|
||||
file_name=make_filename,
|
||||
output_format=task_data.metadata_output_format,
|
||||
output_format=metadata_output_format,
|
||||
file_format=task_data.output_format,
|
||||
)
|
||||
else:
|
||||
@ -63,6 +66,7 @@ def save_images_to_disk(images: list, filtered_images: list, req: GenerateImageR
|
||||
file_name=make_filename,
|
||||
output_format=task_data.output_format,
|
||||
output_quality=task_data.output_quality,
|
||||
output_lossless=task_data.output_lossless,
|
||||
)
|
||||
save_images(
|
||||
filtered_images,
|
||||
@ -70,6 +74,7 @@ def save_images_to_disk(images: list, filtered_images: list, req: GenerateImageR
|
||||
file_name=make_filter_filename,
|
||||
output_format=task_data.output_format,
|
||||
output_quality=task_data.output_quality,
|
||||
output_lossless=task_data.output_lossless,
|
||||
)
|
||||
if task_data.metadata_output_format.lower() in ["json", "txt", "embed"]:
|
||||
save_dicts(
|
||||
|
@ -30,7 +30,7 @@
|
||||
<h1>
|
||||
<img id="logo_img" src="/media/images/icon-512x512.png" >
|
||||
Easy Diffusion
|
||||
<small>v2.5.29 <span id="updateBranchLabel"></span></small>
|
||||
<small>v2.5.30 <span id="updateBranchLabel"></span></small>
|
||||
</h1>
|
||||
</div>
|
||||
<div id="server-status">
|
||||
@ -237,6 +237,9 @@
|
||||
<option value="png">png</option>
|
||||
<option value="webp">webp</option>
|
||||
</select>
|
||||
<span id="output_lossless_container" class="displayNone">
|
||||
<input id="output_lossless" name="output_lossless" type="checkbox"><label for="output_lossless">Lossless</label></td></tr>
|
||||
</span>
|
||||
</td></tr>
|
||||
<tr class="pl-5" id="output_quality_row"><td><label for="output_quality">Image Quality:</label></td><td>
|
||||
<input id="output_quality_slider" name="output_quality" class="editor-slider" value="75" type="range" min="10" max="95"> <input id="output_quality" name="output_quality" size="4" pattern="^[0-9\.]+$" onkeypress="preventNonNumericalInput(event)">
|
||||
@ -289,18 +292,16 @@
|
||||
</div>
|
||||
|
||||
<div id="preview" class="col-free">
|
||||
<div id="initial-text">
|
||||
Type a prompt and press the "Make Image" button.<br/><br/>You can set an "Initial Image" if you want to guide the AI.<br/><br/>
|
||||
You can also add modifiers like "Realistic", "Pencil Sketch", "ArtStation" etc by browsing through the "Image Modifiers" section
|
||||
and selecting the desired modifiers.<br/><br/>
|
||||
Click "Image Settings" for additional settings like seed, image size, number of images to generate etc.<br/><br/>Enjoy! :)
|
||||
</div>
|
||||
|
||||
<div id="preview-content">
|
||||
<div id="preview-tools">
|
||||
<div id="preview-tools" class="displayNone">
|
||||
<button id="clear-all-previews" class="secondaryButton"><i class="fa-solid fa-trash-can icon"></i> Clear All</button>
|
||||
<button class="tertiaryButton" id="show-download-popup"><i class="fa-solid fa-download"></i> Download images</button>
|
||||
<div class="display-settings">
|
||||
<button id="undo" class="displayNone primaryButton">
|
||||
Undo <i class="fa-solid fa-rotate-left icon"></i>
|
||||
<span class="simple-tooltip left">Undo last remove</span>
|
||||
</button>
|
||||
<span class="auto-scroll"></span> <!-- hack for Rabbit Hole update -->
|
||||
<button id="auto_scroll_btn" class="tertiaryButton">
|
||||
<i class="fa-solid fa-arrows-up-to-line icon"></i>
|
||||
@ -325,6 +326,12 @@
|
||||
<div class="clearfix" style="clear: both;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="initial-text">
|
||||
Type a prompt and press the "Make Image" button.<br/><br/>You can set an "Initial Image" if you want to guide the AI.<br/><br/>
|
||||
You can also add modifiers like "Realistic", "Pencil Sketch", "ArtStation" etc by browsing through the "Image Modifiers" section
|
||||
and selecting the desired modifiers.<br/><br/>
|
||||
Click "Image Settings" for additional settings like seed, image size, number of images to generate etc.<br/><br/>Enjoy! :)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -13,6 +13,10 @@
|
||||
z-index: 1001;
|
||||
}
|
||||
|
||||
#viewFullSizeImgModal:not(.active) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#viewFullSizeImgModal > * {
|
||||
pointer-events: auto;
|
||||
margin: 0;
|
||||
|
@ -309,8 +309,7 @@ div.img-preview img {
|
||||
#server-status {
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
top: 4px;
|
||||
text-align: right;
|
||||
}
|
||||
#server-status-color {
|
||||
@ -336,6 +335,7 @@ div.img-preview img {
|
||||
position: relative;
|
||||
background: var(--background-color4);
|
||||
display: flex;
|
||||
padding: 12px 0 0;
|
||||
}
|
||||
.tab .icon {
|
||||
padding-right: 4pt;
|
||||
@ -344,8 +344,7 @@ div.img-preview img {
|
||||
}
|
||||
#logo {
|
||||
display: inline;
|
||||
padding: 12px;
|
||||
padding-top: 8px;
|
||||
padding: 0 12px 12px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
#logo h1 {
|
||||
@ -559,7 +558,6 @@ div.img-preview img {
|
||||
float: right;
|
||||
}
|
||||
#preview-tools {
|
||||
display: none;
|
||||
padding: 4pt;
|
||||
}
|
||||
#preview-tools .display-settings .dropdown-content {
|
||||
@ -574,6 +572,11 @@ div.img-preview img {
|
||||
margin-bottom: 5pt;
|
||||
margin-top: 5pt;
|
||||
}
|
||||
|
||||
.taskConfigContainer {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.img-batch {
|
||||
display: inline;
|
||||
}
|
||||
@ -881,9 +884,6 @@ input::file-selector-button {
|
||||
.tab .icon {
|
||||
padding-right: 0px;
|
||||
}
|
||||
#server-status {
|
||||
top: 75%;
|
||||
}
|
||||
.popup > div {
|
||||
padding-left: 5px !important;
|
||||
padding-right: 5px !important;
|
||||
@ -1126,6 +1126,8 @@ input::file-selector-button {
|
||||
.tab-container {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.tab {
|
||||
|
@ -26,6 +26,7 @@ const SETTINGS_IDS_LIST = [
|
||||
"lora_alpha",
|
||||
"output_format",
|
||||
"output_quality",
|
||||
"output_lossless",
|
||||
"negative_prompt",
|
||||
"stream_image_progress",
|
||||
"use_face_correction",
|
||||
|
@ -97,6 +97,7 @@ const TASK_MAPPING = {
|
||||
return
|
||||
}
|
||||
randomSeedField.checked = false
|
||||
randomSeedField.dispatchEvent(new Event('change')) // let plugins know that the state of the random seed toggle changed
|
||||
seedField.disabled = false
|
||||
seedField.value = seed
|
||||
},
|
||||
@ -230,6 +231,20 @@ const TASK_MAPPING = {
|
||||
readUI: () => vaeModelField.value,
|
||||
parse: (val) => val
|
||||
},
|
||||
use_lora_model: { name: 'LoRA model',
|
||||
setUI: (use_lora_model) => {
|
||||
const oldVal = loraModelField.value
|
||||
use_lora_model = (use_lora_model === undefined || use_lora_model === null || use_lora_model === 'None' ? '' : use_lora_model)
|
||||
|
||||
if (use_lora_model !== '') {
|
||||
use_lora_model = getModelPath(use_lora_model, ['.ckpt', '.safetensors'])
|
||||
use_lora_model = use_lora_model !== '' ? use_lora_model : oldVal
|
||||
}
|
||||
loraModelField.value = use_lora_model
|
||||
},
|
||||
readUI: () => loraModelField.value,
|
||||
parse: (val) => val
|
||||
},
|
||||
use_hypernetwork_model: { name: 'Hypernetwork model',
|
||||
setUI: (use_hypernetwork_model) => {
|
||||
const oldVal = hypernetworkModelField.value
|
||||
|
@ -744,6 +744,7 @@
|
||||
"block_nsfw": false,
|
||||
"output_format": "png",
|
||||
"output_quality": 75,
|
||||
"output_lossless": false,
|
||||
}
|
||||
const TASK_OPTIONAL = {
|
||||
"device": 'string',
|
||||
@ -755,6 +756,7 @@
|
||||
"use_vae_model": 'string',
|
||||
"use_hypernetwork_model": 'string',
|
||||
"hypernetwork_strength": 'number',
|
||||
"output_lossless": 'boolean',
|
||||
}
|
||||
|
||||
// Higer values will result in...
|
||||
|
@ -171,6 +171,7 @@ const IMAGE_EDITOR_ACTIONS = [
|
||||
icon: "fa-solid fa-xmark",
|
||||
handler: (editor) => {
|
||||
editor.ctx_current.clearRect(0, 0, editor.width, editor.height)
|
||||
imageEditor.setImage(null, editor.width, editor.height) // properly reset the drawing canvas
|
||||
},
|
||||
trackHistory: true
|
||||
},
|
||||
|
@ -229,7 +229,7 @@ function refreshInactiveTags(inactiveTags) {
|
||||
let overlays = document.querySelector('#editor-inputs-tags-list').querySelectorAll('.modifier-card-overlay')
|
||||
overlays.forEach (i => {
|
||||
let modifierName = i.parentElement.getElementsByClassName('modifier-card-label')[0].getElementsByTagName("p")[0].innerText
|
||||
if (inactiveTags.find(element => element === modifierName) !== undefined) {
|
||||
if (inactiveTags?.find(element => element === modifierName) !== undefined) {
|
||||
i.parentElement.classList.add('modifier-toggle-inactive')
|
||||
}
|
||||
})
|
||||
|
@ -5,6 +5,28 @@ const MIN_GPUS_TO_SHOW_SELECTION = 2
|
||||
const IMAGE_REGEX = new RegExp('data:image/[A-Za-z]+;base64')
|
||||
const htmlTaskMap = new WeakMap()
|
||||
|
||||
const taskConfigSetup = {
|
||||
taskConfig: {
|
||||
seed: { value: ({ seed }) => seed, label: 'Seed' },
|
||||
dimensions: { value: ({ reqBody }) => `${reqBody?.width}x${reqBody?.height}`, label: 'Dimensions' },
|
||||
sampler_name: 'Sampler',
|
||||
num_inference_steps: 'Inference Steps',
|
||||
guidance_scale: 'Guidance Scale',
|
||||
use_stable_diffusion_model: 'Model',
|
||||
use_vae_model: { label: 'VAE', visible: ({ reqBody }) => reqBody?.use_vae_model !== undefined && reqBody?.use_vae_model.trim() !== ''},
|
||||
negative_prompt: { label: 'Negative Prompt', visible: ({ reqBody }) => reqBody?.negative_prompt !== undefined && reqBody?.negative_prompt.trim() !== ''},
|
||||
prompt_strength: 'Prompt Strength',
|
||||
use_face_correction: 'Fix Faces',
|
||||
upscale: { value: ({ reqBody }) => `${reqBody?.use_upscale} (${reqBody?.upscale_amount || 4}x)`, label: 'Upscale', visible: ({ reqBody }) => !!reqBody?.use_upscale },
|
||||
use_hypernetwork_model: 'Hypernetwork',
|
||||
hypernetwork_strength: { label: 'Hypernetwork Strength', visible: ({ reqBody }) => !!reqBody?.use_hypernetwork_model },
|
||||
use_lora_model: { label: 'Lora Model', visible: ({ reqBody }) => !!reqBody?.use_lora_model },
|
||||
preserve_init_image_color_profile: 'Preserve Color Profile',
|
||||
},
|
||||
pluginTaskConfig: {},
|
||||
getCSSKey: (key) => key.split('_').map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join('')
|
||||
}
|
||||
|
||||
let imageCounter = 0
|
||||
let imageRequest = []
|
||||
|
||||
@ -50,6 +72,8 @@ let loraModelField = new ModelDropdown(document.querySelector('#lora_model'), 'l
|
||||
let loraAlphaSlider = document.querySelector('#lora_alpha_slider')
|
||||
let loraAlphaField = document.querySelector('#lora_alpha')
|
||||
let outputFormatField = document.querySelector('#output_format')
|
||||
let outputLosslessField = document.querySelector('#output_lossless')
|
||||
let outputLosslessContainer = document.querySelector('#output_lossless_container')
|
||||
let blockNSFWField = document.querySelector('#block_nsfw')
|
||||
let showOnlyFilteredImageField = document.querySelector("#show_only_filtered_image")
|
||||
let updateBranchLabel = document.querySelector("#updateBranchLabel")
|
||||
@ -86,6 +110,11 @@ const processOrder = document.querySelector('#process_order_toggle')
|
||||
|
||||
let imagePreview = document.querySelector("#preview")
|
||||
let imagePreviewContent = document.querySelector("#preview-content")
|
||||
|
||||
let undoButton = document.querySelector("#undo")
|
||||
let undoBuffer = []
|
||||
const UNDO_LIMIT = 20
|
||||
|
||||
imagePreview.addEventListener('drop', function(ev) {
|
||||
const data = ev.dataTransfer?.getData("text/plain");
|
||||
if (!data) {
|
||||
@ -254,6 +283,42 @@ function playSound() {
|
||||
}
|
||||
}
|
||||
|
||||
function undoableRemove(element, doubleUndo=false) {
|
||||
let data = { 'element': element, 'parent': element.parentNode, 'prev': element.previousSibling, 'next': element.nextSibling, 'doubleUndo': doubleUndo }
|
||||
undoBuffer.push(data)
|
||||
if (undoBuffer.length > UNDO_LIMIT) {
|
||||
// Remove item from memory and also remove it from the data structures
|
||||
let item = undoBuffer.shift()
|
||||
htmlTaskMap.delete(item.element)
|
||||
item.element.querySelectorAll('[data-imagecounter]').forEach( (img) => { delete imageRequest[img.dataset['imagecounter']] })
|
||||
}
|
||||
element.remove()
|
||||
if (undoBuffer.length != 0) {
|
||||
undoButton.classList.remove('displayNone')
|
||||
}
|
||||
}
|
||||
|
||||
function undoRemove() {
|
||||
let data = undoBuffer.pop()
|
||||
if (!data) {
|
||||
return
|
||||
}
|
||||
if (data.next == null) {
|
||||
data.parent.appendChild(data.element)
|
||||
} else {
|
||||
data.parent.insertBefore(data.element, data.next)
|
||||
}
|
||||
if (data.doubleUndo) {
|
||||
undoRemove()
|
||||
}
|
||||
if (undoBuffer.length == 0) {
|
||||
undoButton.classList.add('displayNone')
|
||||
}
|
||||
updateInitialText()
|
||||
}
|
||||
|
||||
undoButton.addEventListener('click', () => { undoRemove() })
|
||||
|
||||
function showImages(reqBody, res, outputContainer, livePreview) {
|
||||
let imageItemElements = outputContainer.querySelectorAll('.imgItem')
|
||||
if(typeof res != 'object') return
|
||||
@ -293,8 +358,7 @@ function showImages(reqBody, res, outputContainer, livePreview) {
|
||||
const imageRemoveBtn = imageItemElem.querySelector('.imgPreviewItemClearBtn')
|
||||
let parentTaskContainer = imageRemoveBtn.closest('.imageTaskContainer')
|
||||
imageRemoveBtn.addEventListener('click', (e) => {
|
||||
shiftOrConfirm(e, "Remove the image from the results?", () => {
|
||||
imageItemElem.style.display = 'none'
|
||||
undoableRemove(imageItemElem)
|
||||
let allHidden = true;
|
||||
let children = parentTaskContainer.querySelectorAll('.imgItem');
|
||||
for(let x = 0; x < children.length; x++) {
|
||||
@ -305,10 +369,9 @@ function showImages(reqBody, res, outputContainer, livePreview) {
|
||||
}
|
||||
if(allHidden === true) {
|
||||
const req = htmlTaskMap.get(parentTaskContainer)
|
||||
if(!req.isProcessing || req.batchesDone == req.batchCount) {parentTaskContainer.parentNode.removeChild(parentTaskContainer)}
|
||||
if(!req.isProcessing || req.batchesDone == req.batchCount) { undoableRemove(parentTaskContainer, true) }
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
const imageElem = imageItemElem.querySelector('img')
|
||||
imageElem.src = imageData
|
||||
@ -569,7 +632,7 @@ function makeImage() {
|
||||
}))
|
||||
newTaskRequests.forEach(createTask)
|
||||
|
||||
initialText.style.display = 'none'
|
||||
updateInitialText()
|
||||
}
|
||||
|
||||
async function onIdle() {
|
||||
@ -867,7 +930,7 @@ async function onTaskStart(task) {
|
||||
setStatus('request', 'fetching..')
|
||||
renderButtons.style.display = 'flex'
|
||||
renameMakeImageButton()
|
||||
previewTools.style.display = 'block'
|
||||
updateInitialText()
|
||||
}
|
||||
|
||||
/* Hover effect for the init image in the task list */
|
||||
@ -905,6 +968,29 @@ function onTaskEntryDragOver(event) {
|
||||
}
|
||||
}
|
||||
|
||||
function generateConfig({ label, value, visible, cssKey }) {
|
||||
if (!visible) return null;
|
||||
return `<div class="taskConfigContainer task${cssKey}Container"><b>${label}:</b> <span class="task${cssKey}">${value}`
|
||||
}
|
||||
|
||||
function getVisibleConfig(config, task) {
|
||||
const mergedTaskConfig = { ...config.taskConfig, ...config.pluginTaskConfig }
|
||||
return Object.keys(mergedTaskConfig)
|
||||
.map((key) => {
|
||||
const value = mergedTaskConfig?.[key]?.value?.(task) ?? task.reqBody[key]
|
||||
const visible = mergedTaskConfig?.[key]?.visible?.(task) ?? value !== undefined ?? true
|
||||
const label = mergedTaskConfig?.[key]?.label ?? mergedTaskConfig?.[key]
|
||||
const cssKey = config.getCSSKey(key)
|
||||
return { label, visible, value, cssKey }
|
||||
})
|
||||
.map((obj) => generateConfig(obj))
|
||||
.filter(obj => obj)
|
||||
}
|
||||
|
||||
function createTaskConfig(task) {
|
||||
return getVisibleConfig(taskConfigSetup, task).join('</span>, </div>')
|
||||
}
|
||||
|
||||
function createTask(task) {
|
||||
let taskConfig = ''
|
||||
|
||||
@ -913,33 +999,8 @@ function createTask(task) {
|
||||
let w = task.reqBody.width * h / task.reqBody.height >>0
|
||||
taskConfig += `<div class="task-initimg" style="float:left;"><img style="width:${w}px;height:${h}px;" src="${task.reqBody.init_image}"><div class="task-fs-initimage"></div></div>`
|
||||
}
|
||||
taskConfig += `<b>Seed:</b> ${task.seed}, <b>Sampler:</b> ${task.reqBody.sampler_name}, <b>Inference Steps:</b> ${task.reqBody.num_inference_steps}, <b>Guidance Scale:</b> ${task.reqBody.guidance_scale}, <b>Model:</b> ${task.reqBody.use_stable_diffusion_model}`
|
||||
|
||||
if (task.reqBody.use_vae_model.trim() !== '') {
|
||||
taskConfig += `, <b>VAE:</b> ${task.reqBody.use_vae_model}`
|
||||
}
|
||||
if (task.reqBody.negative_prompt.trim() !== '') {
|
||||
taskConfig += `, <b>Negative Prompt:</b> ${task.reqBody.negative_prompt}`
|
||||
}
|
||||
if (task.reqBody.init_image !== undefined) {
|
||||
taskConfig += `, <b>Prompt Strength:</b> ${task.reqBody.prompt_strength}`
|
||||
}
|
||||
if (task.reqBody.use_face_correction) {
|
||||
taskConfig += `, <b>Fix Faces:</b> ${task.reqBody.use_face_correction}`
|
||||
}
|
||||
if (task.reqBody.use_upscale) {
|
||||
taskConfig += `, <b>Upscale:</b> ${task.reqBody.use_upscale} (${task.reqBody.upscale_amount || 4}x)`
|
||||
}
|
||||
if (task.reqBody.use_hypernetwork_model) {
|
||||
taskConfig += `, <b>Hypernetwork:</b> ${task.reqBody.use_hypernetwork_model}`
|
||||
taskConfig += `, <b>Hypernetwork Strength:</b> ${task.reqBody.hypernetwork_strength}`
|
||||
}
|
||||
if (task.reqBody.use_lora_model) {
|
||||
taskConfig += `, <b>LoRA:</b> ${task.reqBody.use_lora_model}`
|
||||
}
|
||||
if (task.reqBody.preserve_init_image_color_profile) {
|
||||
taskConfig += `, <b>Preserve Color Profile:</b> true`
|
||||
}
|
||||
taskConfig += `<div class="taskConfigData">${createTaskConfig(task)}</span></div></div>`;
|
||||
|
||||
let taskEntry = document.createElement('div')
|
||||
taskEntry.id = `imageTaskContainer-${Date.now()}`
|
||||
@ -999,13 +1060,16 @@ function createTask(task) {
|
||||
task['stopTask'].addEventListener('click', (e) => {
|
||||
e.stopPropagation()
|
||||
|
||||
let question = (task['isProcessing'] ? "Stop this task?" : "Remove this task?")
|
||||
shiftOrConfirm(e, question, async function(e) {
|
||||
if (task['isProcessing']) {
|
||||
shiftOrConfirm(e, "Stop this task?", async function(e) {
|
||||
if (task.batchesDone <= 0 || !task.isProcessing) {
|
||||
removeTask(taskEntry)
|
||||
}
|
||||
abortTask(task)
|
||||
})
|
||||
} else {
|
||||
removeTask(taskEntry)
|
||||
}
|
||||
})
|
||||
|
||||
task['useSettings'] = taskEntry.querySelector('.useSettings')
|
||||
@ -1035,7 +1099,6 @@ function getCurrentUserRequest() {
|
||||
numOutputsTotal: numOutputsTotal,
|
||||
batchCount: Math.ceil(numOutputsTotal / numOutputsParallel),
|
||||
seed,
|
||||
|
||||
reqBody: {
|
||||
seed,
|
||||
used_random_seed: randomSeedField.checked,
|
||||
@ -1057,6 +1120,7 @@ function getCurrentUserRequest() {
|
||||
block_nsfw: blockNSFWField.checked,
|
||||
output_format: outputFormatField.value,
|
||||
output_quality: parseInt(outputQualityField.value),
|
||||
output_lossless: outputLosslessField.checked,
|
||||
metadata_output_format: metadataOutputFormatField.value,
|
||||
original_prompt: promptField.value,
|
||||
active_tags: (activeTags.map(x => x.name)),
|
||||
@ -1066,7 +1130,6 @@ function getCurrentUserRequest() {
|
||||
if (IMAGE_REGEX.test(initImagePreview.src)) {
|
||||
newTask.reqBody.init_image = initImagePreview.src
|
||||
newTask.reqBody.prompt_strength = parseFloat(promptStrengthField.value)
|
||||
|
||||
// if (IMAGE_REGEX.test(maskImagePreview.src)) {
|
||||
// newTask.reqBody.mask = maskImagePreview.src
|
||||
// }
|
||||
@ -1192,31 +1255,10 @@ function createFileName(prompt, seed, steps, guidance, outputFormat) {
|
||||
|
||||
// Most important information is the prompt
|
||||
let underscoreName = prompt.replace(/[^a-zA-Z0-9]/g, '_')
|
||||
underscoreName = underscoreName.substring(0, 100)
|
||||
//const steps = numInferenceStepsField.value
|
||||
//const guidance = guidanceScaleField.value
|
||||
underscoreName = underscoreName.substring(0, 70)
|
||||
|
||||
// name and the top level metadata
|
||||
let fileName = `${underscoreName}_Seed-${seed}_Steps-${steps}_Guidance-${guidance}`
|
||||
|
||||
// add the tags
|
||||
// let tags = []
|
||||
// let tagString = ''
|
||||
// document.querySelectorAll(modifyTagsSelector).forEach(function(tag) {
|
||||
// tags.push(tag.innerHTML)
|
||||
// })
|
||||
|
||||
// join the tags with a pipe
|
||||
// if (activeTags.length > 0) {
|
||||
// tagString = '_Tags-'
|
||||
// tagString += tags.join('|')
|
||||
// }
|
||||
|
||||
// // append empty or populated tags
|
||||
// fileName += `${tagString}`
|
||||
|
||||
// add the file extension
|
||||
fileName += '.' + outputFormat
|
||||
let fileName = `${underscoreName}_S${seed}_St${steps}_G${guidance}.${outputFormat}`
|
||||
|
||||
return fileName
|
||||
}
|
||||
@ -1235,13 +1277,21 @@ async function stopAllTasks() {
|
||||
})
|
||||
}
|
||||
|
||||
function removeTask(taskToRemove) {
|
||||
taskToRemove.remove()
|
||||
|
||||
function updateInitialText() {
|
||||
if (document.querySelector('.imageTaskContainer') === null) {
|
||||
previewTools.style.display = 'none'
|
||||
initialText.style.display = 'block'
|
||||
if (undoBuffer.length == 0) {
|
||||
previewTools.classList.add('displayNone')
|
||||
}
|
||||
initialText.classList.remove('displayNone')
|
||||
} else {
|
||||
initialText.classList.add('displayNone')
|
||||
previewTools.classList.remove('displayNone')
|
||||
}
|
||||
}
|
||||
|
||||
function removeTask(taskToRemove) {
|
||||
undoableRemove(taskToRemove)
|
||||
updateInitialText()
|
||||
}
|
||||
|
||||
clearAllPreviewsBtn.addEventListener('click', (e) => { shiftOrConfirm(e, "Clear all the results and tasks in this window?", async function() {
|
||||
@ -1296,7 +1346,7 @@ function downloadAllImages() {
|
||||
|
||||
document.querySelectorAll(".imageTaskContainer").forEach(container => {
|
||||
if (optTree) {
|
||||
let name = ++i + '-' + container.querySelector('.preview-prompt').textContent.replace(/[^a-zA-Z0-9]/g, '_')
|
||||
let name = ++i + '-' + container.querySelector('.preview-prompt').textContent.replace(/[^a-zA-Z0-9]/g, '_').substring(0,25)
|
||||
folder = zip.folder(name)
|
||||
}
|
||||
container.querySelectorAll(".imgContainer img").forEach(img => {
|
||||
@ -1325,9 +1375,9 @@ function downloadAllImages() {
|
||||
})
|
||||
})
|
||||
if (optZIP) {
|
||||
let now = new Date()
|
||||
let now = Date.now().toString(36).toUpperCase()
|
||||
zip.generateAsync({type:"blob"}).then(function (blob) {
|
||||
saveAs(blob, `EasyDiffusion-Images-${now.toISOString()}.zip`);
|
||||
saveAs(blob, `EasyDiffusion-Images-${now}.zip`);
|
||||
})
|
||||
}
|
||||
|
||||
@ -1517,13 +1567,26 @@ outputQualitySlider.addEventListener('input', updateOutputQuality)
|
||||
outputQualityField.addEventListener('input', debounce(updateOutputQualitySlider, 1500))
|
||||
updateOutputQuality()
|
||||
|
||||
outputFormatField.addEventListener('change', e => {
|
||||
if (outputFormatField.value === 'png') {
|
||||
outputQualityRow.style.display='none'
|
||||
function updateOutputQualityVisibility() {
|
||||
if (outputFormatField.value === 'webp') {
|
||||
outputLosslessContainer.classList.remove('displayNone')
|
||||
if (outputLosslessField.checked) {
|
||||
outputQualityRow.classList.add('displayNone')
|
||||
} else {
|
||||
outputQualityRow.style.display='table-row'
|
||||
outputQualityRow.classList.remove('displayNone')
|
||||
}
|
||||
})
|
||||
}
|
||||
else if (outputFormatField.value === 'png') {
|
||||
outputQualityRow.classList.add('displayNone')
|
||||
outputLosslessContainer.classList.add('displayNone')
|
||||
} else {
|
||||
outputQualityRow.classList.remove('displayNone')
|
||||
outputLosslessContainer.classList.add('displayNone')
|
||||
}
|
||||
}
|
||||
|
||||
outputFormatField.addEventListener('change', updateOutputQualityVisibility)
|
||||
outputLosslessField.addEventListener('change', updateOutputQualityVisibility)
|
||||
/********************* Zoom Slider **********************/
|
||||
thumbnailSizeField.addEventListener('change', () => {
|
||||
(function (s) {
|
||||
|
@ -76,7 +76,15 @@ var PARAMETERS = [
|
||||
{
|
||||
value: "embed",
|
||||
label: "embed"
|
||||
}
|
||||
},
|
||||
{
|
||||
value: "embed,txt",
|
||||
label: "embed & txt",
|
||||
},
|
||||
{
|
||||
value: "embed,json",
|
||||
label: "embed & json",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 40 KiB |
Binary file not shown.
After Width: | Height: | Size: 57 KiB |
@ -2428,6 +2428,19 @@
|
||||
"path": "artist/by_yoshitaka_amano/landscape-0.jpg"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"modifier": "by Zdzislaw Beksinski",
|
||||
"previews": [
|
||||
{
|
||||
"name": "portrait",
|
||||
"path": "artist/by_zdzislaw_beksinski/portrait-0.jpg"
|
||||
},
|
||||
{
|
||||
"name": "landscape",
|
||||
"path": "artist/by_zdzislaw_beksinski/landscape-0.jpg"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -1,4 +1,8 @@
|
||||
(function () { "use strict"
|
||||
(function () {
|
||||
"use strict"
|
||||
|
||||
const MAX_WEIGHT = 5
|
||||
|
||||
if (typeof editorModifierTagsList !== 'object') {
|
||||
console.error('editorModifierTagsList missing...')
|
||||
return
|
||||
@ -34,34 +38,42 @@
|
||||
break
|
||||
}
|
||||
}
|
||||
if (s.charAt(0) !== '(' && s.charAt(s.length - 1) !== ')' && s.trim().includes(' ')) {
|
||||
s = '(' + s + ')'
|
||||
t = '(' + t + ')'
|
||||
}
|
||||
if (delta < 0) {
|
||||
// wheel scrolling up
|
||||
if (s.substring(0, 1) == '[' && s.substring(s.length-1) == ']') {
|
||||
s = s.substring(1, s.length - 1)
|
||||
t = t.substring(1, t.length - 1)
|
||||
if (s.substring(s.length - 1) == '-') {
|
||||
s = s.substring(0, s.length - 1)
|
||||
t = t.substring(0, t.length - 1)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s.substring(0, 10) !== '('.repeat(10) && s.substring(s.length-10) !== ')'.repeat(10)) {
|
||||
s = '(' + s + ')'
|
||||
t = '(' + t + ')'
|
||||
if (s.substring(s.length - MAX_WEIGHT) !== '+'.repeat(MAX_WEIGHT)) {
|
||||
s = s + '+'
|
||||
t = t + '+'
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
// wheel scrolling down
|
||||
if (s.substring(0, 1) == '(' && s.substring(s.length-1) == ')') {
|
||||
s = s.substring(1, s.length - 1)
|
||||
t = t.substring(1, t.length - 1)
|
||||
if (s.substring(s.length - 1) == '+') {
|
||||
s = s.substring(0, s.length - 1)
|
||||
t = t.substring(0, t.length - 1)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s.substring(0, 10) !== '['.repeat(10) && s.substring(s.length-10) !== ']'.repeat(10)) {
|
||||
s = '[' + s + ']'
|
||||
t = '[' + t + ']'
|
||||
if (s.substring(s.length - MAX_WEIGHT) !== '-'.repeat(MAX_WEIGHT)) {
|
||||
s = s + '-'
|
||||
t = t + '-'
|
||||
}
|
||||
}
|
||||
}
|
||||
if (s.charAt(0) === '(' && s.charAt(s.length - 1) === ')') {
|
||||
s = s.substring(1, s.length - 1)
|
||||
t = t.substring(1, t.length - 1)
|
||||
}
|
||||
i.parentElement.getElementsByClassName('modifier-card-label')[0].getElementsByTagName("p")[0].innerText = s
|
||||
// update activeTags
|
||||
for (let it = 0; it < overlays.length; it++) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user