mirror of
https://github.com/easydiffusion/easydiffusion.git
synced 2025-02-08 22:49:18 +01:00
Merge branch 'haka-fix' into main
This commit is contained in:
commit
c2dec9eac4
11
README.md
11
README.md
@ -40,7 +40,7 @@ This distribution currently uses Stable Diffusion 1.4. Once the model for 1.5 be
|
|||||||
You do not need anything else. You do not need WSL, Docker or Conda. The installer will take care of it.
|
You do not need anything else. You do not need WSL, Docker or Conda. The installer will take care of it.
|
||||||
|
|
||||||
# Installation
|
# Installation
|
||||||
1. **Download** [for Windows](https://github.com/cmdr2/stable-diffusion-ui/releases/download/v2.05/stable-diffusion-ui-win64.zip) or [for Linux](https://github.com/cmdr2/stable-diffusion-ui/releases/download/v2.05/stable-diffusion-ui-linux.tar.xz).
|
1. **Download** [for Windows](https://github.com/cmdr2/stable-diffusion-ui/releases/download/v2.16/stable-diffusion-ui-win64.zip) or [for Linux](https://github.com/cmdr2/stable-diffusion-ui/releases/download/v2.16/stable-diffusion-ui-linux.tar.xz).
|
||||||
|
|
||||||
2. **Extract**:
|
2. **Extract**:
|
||||||
- For Windows: After unzipping the file, please move the `stable-diffusion-ui` folder to your `C:` (or any drive like D:, at the top root level), e.g. `C:\stable-diffusion-ui`. This will avoid a common problem with Windows (file path length limits).
|
- For Windows: After unzipping the file, please move the `stable-diffusion-ui` folder to your `C:` (or any drive like D:, at the top root level), e.g. `C:\stable-diffusion-ui`. This will avoid a common problem with Windows (file path length limits).
|
||||||
@ -77,12 +77,17 @@ You can use Face Correction or Upscaling to improve the image further.
|
|||||||
## Problems? Troubleshooting
|
## Problems? Troubleshooting
|
||||||
Please try the common [troubleshooting](Troubleshooting.md) steps. If that doesn't fix it, please ask on the [discord server](https://discord.com/invite/u9yhsFmEkB), or [file an issue](https://github.com/cmdr2/stable-diffusion-ui/issues).
|
Please try the common [troubleshooting](Troubleshooting.md) steps. If that doesn't fix it, please ask on the [discord server](https://discord.com/invite/u9yhsFmEkB), or [file an issue](https://github.com/cmdr2/stable-diffusion-ui/issues).
|
||||||
|
|
||||||
# Advanced Settings
|
# Image Settings
|
||||||
You can also set the configuration like `seed`, `width`, `height`, `num_outputs`, `num_inference_steps` and `guidance_scale` using the 'show' button next to 'Advanced settings'.
|
You can also set the configuration like `seed`, `width`, `height`, `num_outputs`, `num_inference_steps` and `guidance_scale` using the 'show' button next to 'Image settings'.
|
||||||
|
|
||||||
Use the same `seed` number to get the same image for a certain prompt. This is useful for refining a prompt without losing the basic image design. Enable the `random images` checkbox to get random images.
|
Use the same `seed` number to get the same image for a certain prompt. This is useful for refining a prompt without losing the basic image design. Enable the `random images` checkbox to get random images.
|
||||||
|
|
||||||
![Screenshot of advanced settings](media/config-v6.jpg?raw=true)
|
![Screenshot of advanced settings](media/config-v6.jpg?raw=true)
|
||||||
|
|
||||||
|
# System Settings
|
||||||
|
The system settings are reachable via the cogwheel symbol on the top right. It can be used to configure whether all generated images should
|
||||||
|
saved be automically, or to tune the Stable Diffusion image generation.
|
||||||
|
|
||||||
![Screenshot of advanced settings](media/system-settings-v2.jpg?raw=true)
|
![Screenshot of advanced settings](media/system-settings-v2.jpg?raw=true)
|
||||||
|
|
||||||
# Image Modifiers
|
# Image Modifiers
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
set /p answer=Are you a developer of this project (Y/N)?
|
set /p answer=Are you a developer of this project (Y/N)?
|
||||||
if /i "%answer:~,1%" NEQ "Y" exit /b
|
if /i "%answer:~,1%" NEQ "Y" exit /b
|
||||||
|
|
||||||
|
@set PYTHONNOUSERSITE=1
|
||||||
|
|
||||||
@mkdir dist\stable-diffusion-ui
|
@mkdir dist\stable-diffusion-ui
|
||||||
|
|
||||||
@echo "Downloading components for the installer.."
|
@echo "Downloading components for the installer.."
|
||||||
@ -15,11 +17,6 @@ if /i "%answer:~,1%" NEQ "Y" exit /b
|
|||||||
@call conda env create --prefix installer -f environment.yaml
|
@call conda env create --prefix installer -f environment.yaml
|
||||||
@call conda activate .\installer
|
@call conda activate .\installer
|
||||||
|
|
||||||
@echo "Setting up startup scripts.."
|
|
||||||
|
|
||||||
@mkdir installer\etc\conda\activate.d
|
|
||||||
@copy scripts\post_activate.bat installer\etc\conda\activate.d\
|
|
||||||
|
|
||||||
@echo "Creating a distributable package.."
|
@echo "Creating a distributable package.."
|
||||||
|
|
||||||
@call conda install -c conda-forge -y conda-pack
|
@call conda install -c conda-forge -y conda-pack
|
||||||
@ -37,6 +34,7 @@ if /i "%answer:~,1%" NEQ "Y" exit /b
|
|||||||
@copy ..\..\LICENSE .
|
@copy ..\..\LICENSE .
|
||||||
@copy "..\..\CreativeML Open RAIL-M License" .
|
@copy "..\..\CreativeML Open RAIL-M License" .
|
||||||
@copy "..\..\How to install and run.txt" .
|
@copy "..\..\How to install and run.txt" .
|
||||||
|
@echo. > scripts\install_status.txt
|
||||||
|
|
||||||
@echo "Build ready. Zip the 'dist\stable-diffusion-ui' folder."
|
@echo "Build ready. Zip the 'dist\stable-diffusion-ui' folder."
|
||||||
|
|
||||||
|
3
build.sh
3
build.sh
@ -11,6 +11,8 @@ case $yn in
|
|||||||
* ) exit;;
|
* ) exit;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
export PYTHONNOUSERSITE=1
|
||||||
|
|
||||||
mkdir -p dist/stable-diffusion-ui
|
mkdir -p dist/stable-diffusion-ui
|
||||||
|
|
||||||
echo "Downloading components for the installer.."
|
echo "Downloading components for the installer.."
|
||||||
@ -38,6 +40,7 @@ cp ../../scripts/start.sh .
|
|||||||
cp ../../LICENSE .
|
cp ../../LICENSE .
|
||||||
cp "../../CreativeML Open RAIL-M License" .
|
cp "../../CreativeML Open RAIL-M License" .
|
||||||
cp "../../How to install and run.txt" .
|
cp "../../How to install and run.txt" .
|
||||||
|
echo "" > scripts/install_status.txt
|
||||||
|
|
||||||
chmod u+x start.sh
|
chmod u+x start.sh
|
||||||
|
|
||||||
|
@ -1 +1,19 @@
|
|||||||
installer\Scripts\activate.bat
|
@echo off
|
||||||
|
|
||||||
|
@REM Delete the post-activate hook from the old installer
|
||||||
|
if exist "installer\etc\conda\activate.d\post_activate.bat" (
|
||||||
|
echo. > installer\etc\conda\activate.d\post_activate.bat
|
||||||
|
)
|
||||||
|
|
||||||
|
@call installer\Scripts\activate.bat
|
||||||
|
|
||||||
|
@call conda-unpack
|
||||||
|
|
||||||
|
@call conda --version
|
||||||
|
@call git --version
|
||||||
|
|
||||||
|
@cd installer
|
||||||
|
|
||||||
|
@call ..\scripts\on_env_start.bat
|
||||||
|
|
||||||
|
@pause
|
||||||
|
@ -165,13 +165,13 @@ call WHERE uvicorn > .tmp
|
|||||||
|
|
||||||
@if exist "sd-v1-4.ckpt" (
|
@if exist "sd-v1-4.ckpt" (
|
||||||
for %%I in ("sd-v1-4.ckpt") do if "%%~zI" EQU "4265380512" (
|
for %%I in ("sd-v1-4.ckpt") do if "%%~zI" EQU "4265380512" (
|
||||||
echo "Data files (weights) necessary for Stable Diffusion were already downloaded"
|
echo "Data files (weights) necessary for Stable Diffusion were already downloaded. Using the HuggingFace 4 GB Model."
|
||||||
) else (
|
) else (
|
||||||
for %%J in ("sd-v1-4.ckpt") do if "%%~zJ" EQU "7703807346" (
|
for %%J in ("sd-v1-4.ckpt") do if "%%~zJ" EQU "7703807346" (
|
||||||
echo "Data files (weights) necessary for Stable Diffusion were already downloaded"
|
echo "Data files (weights) necessary for Stable Diffusion were already downloaded. Using the HuggingFace 7 GB Model."
|
||||||
) else (
|
) else (
|
||||||
for %%K in ("sd-v1-4.ckpt") do if "%%~zK" EQU "7703810927" (
|
for %%K in ("sd-v1-4.ckpt") do if "%%~zK" EQU "7703810927" (
|
||||||
echo "Data files (weights) necessary for Stable Diffusion were already downloaded"
|
echo "Data files (weights) necessary for Stable Diffusion were already downloaded. Using the Waifu Model."
|
||||||
) else (
|
) else (
|
||||||
echo. & echo "The model file present at %cd%\sd-v1-4.ckpt is invalid. It is only %%~zK bytes in size. Re-downloading.." & echo.
|
echo. & echo "The model file present at %cd%\sd-v1-4.ckpt is invalid. It is only %%~zK bytes in size. Re-downloading.." & echo.
|
||||||
del "sd-v1-4.ckpt"
|
del "sd-v1-4.ckpt"
|
||||||
|
@ -4,4 +4,7 @@ source installer/bin/activate
|
|||||||
|
|
||||||
conda-unpack
|
conda-unpack
|
||||||
|
|
||||||
|
conda --version
|
||||||
|
git --version
|
||||||
|
|
||||||
scripts/on_env_start.sh
|
scripts/on_env_start.sh
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<link rel="icon" type="image/png" href="/media/favicon-16x16.png" sizes="16x16">
|
<link rel="icon" type="image/png" href="/media/favicon-16x16.png" sizes="16x16">
|
||||||
<link rel="icon" type="image/png" href="/media/favicon-32x32.png" sizes="32x32">
|
<link rel="icon" type="image/png" href="/media/favicon-32x32.png" sizes="32x32">
|
||||||
<link rel="stylesheet" href="/media/main.css?v=3">
|
<link rel="stylesheet" href="/media/main.css?v=10">
|
||||||
<link rel="stylesheet" href="/media/modifier-thumbnails.css?v=1">
|
<link rel="stylesheet" href="/media/modifier-thumbnails.css?v=1">
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css">
|
||||||
<link rel="stylesheet" href="/media/drawingboard.min.css">
|
<link rel="stylesheet" href="/media/drawingboard.min.css">
|
||||||
@ -15,7 +15,7 @@
|
|||||||
<div id="container">
|
<div id="container">
|
||||||
<div id="top-nav">
|
<div id="top-nav">
|
||||||
<div id="logo">
|
<div id="logo">
|
||||||
<h1>Stable Diffusion UI <small>v2.17 <span id="updateBranchLabel"></span></small></h1>
|
<h1>Stable Diffusion UI <small>v2.195 <span id="updateBranchLabel"></span></small></h1>
|
||||||
</div>
|
</div>
|
||||||
<ul id="top-nav-items">
|
<ul id="top-nav-items">
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
@ -23,6 +23,7 @@
|
|||||||
<ul id="community-links" class="dropdown-content">
|
<ul id="community-links" class="dropdown-content">
|
||||||
<li><a href="https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md" target="_blank"><i class="fa-solid fa-circle-question fa-fw"></i> Usual problems and solutions</a></li>
|
<li><a href="https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md" target="_blank"><i class="fa-solid fa-circle-question fa-fw"></i> Usual problems and solutions</a></li>
|
||||||
<li><a href="https://discord.com/invite/u9yhsFmEkB" target="_blank"><i class="fa-brands fa-discord fa-fw"></i> Discord user community</a></li>
|
<li><a href="https://discord.com/invite/u9yhsFmEkB" target="_blank"><i class="fa-brands fa-discord fa-fw"></i> Discord user community</a></li>
|
||||||
|
<li><a href="https://www.reddit.com/r/StableDiffusionUI/" target="_blank"><i class="fa-brands fa-reddit fa-fw"></i> Reddit community</a></li>
|
||||||
<li><a href="https://github.com/cmdr2/stable-diffusion-ui" target="_blank"><i class="fa-brands fa-github fa-fw"></i> Source code on GitHub</a></li>
|
<li><a href="https://github.com/cmdr2/stable-diffusion-ui" target="_blank"><i class="fa-brands fa-github fa-fw"></i> Source code on GitHub</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
@ -77,7 +78,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button id="makeImage">Make Image</button>
|
<button id="makeImage">Make Image</button>
|
||||||
<button id="stopImage">Stop</button>
|
<button id="stopImage" class="secondaryButton">Stop All</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="line-separator"> </div>
|
<div class="line-separator"> </div>
|
||||||
@ -121,7 +122,8 @@
|
|||||||
<option value="1536">1536</option>
|
<option value="1536">1536</option>
|
||||||
<option value="1792">1792</option>
|
<option value="1792">1792</option>
|
||||||
<option value="2048">2048</option>
|
<option value="2048">2048</option>
|
||||||
</select> <label for="width"><small>(width)</small></label>
|
</select>
|
||||||
|
<label for="width"><small>(width)</small></label>
|
||||||
<select id="height" name="height" value="512">
|
<select id="height" name="height" value="512">
|
||||||
<option value="128">128 (*)</option>
|
<option value="128">128 (*)</option>
|
||||||
<option value="192">192</option>
|
<option value="192">192</option>
|
||||||
@ -151,8 +153,13 @@
|
|||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
|
<li><b class="settings-subheader">Prompt Settings</b></li>
|
||||||
|
<li class="pl-5"><label for="negative_prompt">Negative Prompt:</label> <input id="negative_prompt" name="negative_prompt" size="55"></li>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
<li><b class="settings-subheader">Render Settings</b></li>
|
<li><b class="settings-subheader">Render Settings</b></li>
|
||||||
<li class="pl-5"><input id="stream_image_progress" name="stream_image_progress" type="checkbox"> <label for="stream_image_progress">Show a live preview of the image <small>(consumes more VRAM, slightly slower image generation)</small></label></li>
|
<li class="pl-5"><input id="stream_image_progress" name="stream_image_progress" type="checkbox"> <label for="stream_image_progress">Show a live preview of the image <small>(uses more VRAM, slightly slower image creation)</small></label></li>
|
||||||
<li class="pl-5"><input id="use_face_correction" name="use_face_correction" type="checkbox" checked> <label for="use_face_correction">Fix incorrect faces and eyes <small>(uses GFPGAN)</small></label></li>
|
<li class="pl-5"><input id="use_face_correction" name="use_face_correction" type="checkbox" checked> <label for="use_face_correction">Fix incorrect faces and eyes <small>(uses GFPGAN)</small></label></li>
|
||||||
<li class="pl-5">
|
<li class="pl-5">
|
||||||
<input id="use_upscale" name="use_upscale" type="checkbox"> <label for="use_upscale">Upscale the image to 4x resolution using </label>
|
<input id="use_upscale" name="use_upscale" type="checkbox"> <label for="use_upscale">Upscale the image to 4x resolution using </label>
|
||||||
@ -183,15 +190,11 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="preview" class="col-free">
|
<div id="preview" class="col-free">
|
||||||
<div id="preview-prompt">
|
|
||||||
<div id="initial-text">
|
<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 "Advanced Settings" for additional settings like seed, image size, number of images to generate etc.<br/><br/>Enjoy! :)
|
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 "Advanced Settings" for additional settings like seed, image size, number of images to generate etc.<br/><br/>Enjoy! :)
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div id="preview-tools">
|
||||||
|
<button id="clear-all-previews" class="secondaryButton"><i class="fa-solid fa-trash-can"></i> Clear All</button>
|
||||||
<div id="outputMsg"></div>
|
|
||||||
<div id="progressBar"></div>
|
|
||||||
<div id="current-images" class="img-preview">
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -210,7 +213,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
<script src="media/main.js?v=4"></script>
|
<script src="media/main.js?v=14"></script>
|
||||||
<script>
|
<script>
|
||||||
async function init() {
|
async function init() {
|
||||||
await loadModifiers()
|
await loadModifiers()
|
||||||
|
@ -54,8 +54,9 @@ label {
|
|||||||
.editor-slider {
|
.editor-slider {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
#outputMsg {
|
.outputMsg {
|
||||||
font-size: small;
|
font-size: small;
|
||||||
|
padding-bottom: 3pt;
|
||||||
}
|
}
|
||||||
#progressBar {
|
#progressBar {
|
||||||
font-size: small;
|
font-size: small;
|
||||||
@ -162,7 +163,7 @@ label {
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
#stopImage:hover {
|
#stopImage:hover {
|
||||||
background: rgb(214, 32, 0);
|
background: rgb(177, 27, 0);
|
||||||
}
|
}
|
||||||
.flex-container {
|
.flex-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -171,7 +172,7 @@ label {
|
|||||||
flex: 50%;
|
flex: 50%;
|
||||||
}
|
}
|
||||||
.col-fixed-10 {
|
.col-fixed-10 {
|
||||||
flex: 0 0 400pt;
|
flex: 0 0 380pt;
|
||||||
}
|
}
|
||||||
.col-free {
|
.col-free {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
@ -209,7 +210,7 @@ label {
|
|||||||
padding-bottom: 10pt;
|
padding-bottom: 10pt;
|
||||||
}
|
}
|
||||||
#preview {
|
#preview {
|
||||||
margin-left: 20pt;
|
margin-left: 10pt;
|
||||||
}
|
}
|
||||||
img {
|
img {
|
||||||
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.15), 0 6px 20px 0 rgba(0, 0, 0, 0.15);
|
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.15), 0 6px 20px 0 rgba(0, 0, 0, 0.15);
|
||||||
@ -243,7 +244,7 @@ img {
|
|||||||
padding-left: 2pt;
|
padding-left: 2pt;
|
||||||
font-size: 10pt;
|
font-size: 10pt;
|
||||||
}
|
}
|
||||||
#preview-prompt {
|
.preview-prompt {
|
||||||
font-size: 16pt;
|
font-size: 16pt;
|
||||||
margin-bottom: 10pt;
|
margin-bottom: 10pt;
|
||||||
}
|
}
|
||||||
@ -363,3 +364,47 @@ img {
|
|||||||
.dropdown:hover .dropdown-content {
|
.dropdown:hover .dropdown-content {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.imageTaskContainer {
|
||||||
|
border: 1px solid #333;
|
||||||
|
margin-bottom: 10pt;
|
||||||
|
padding: 5pt;
|
||||||
|
border-radius: 5pt;
|
||||||
|
box-shadow: 0 20px 28px 0 rgba(0, 0, 0, 0.15), 0 6px 20px 0 rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
.taskStatusLabel {
|
||||||
|
float: left;
|
||||||
|
font-size: 8pt;
|
||||||
|
background:rgb(44, 45, 48);
|
||||||
|
border: 1px solid rgb(61, 62, 66);
|
||||||
|
padding: 2pt 4pt;
|
||||||
|
border-radius: 2pt;
|
||||||
|
margin-right: 5pt;
|
||||||
|
}
|
||||||
|
.activeTaskLabel {
|
||||||
|
background:rgb(0, 90, 30);
|
||||||
|
border: 1px solid rgb(0, 75, 19);
|
||||||
|
color:rgb(204, 255, 217)
|
||||||
|
}
|
||||||
|
.secondaryButton {
|
||||||
|
background: rgb(132, 8, 0);
|
||||||
|
border: 1px solid rgb(122, 29, 0);
|
||||||
|
color: rgb(255, 221, 255);
|
||||||
|
padding: 3pt 6pt;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
.secondaryButton:hover {
|
||||||
|
background: rgb(177, 27, 0);
|
||||||
|
}
|
||||||
|
.stopTask {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
#preview-tools {
|
||||||
|
display: none;
|
||||||
|
padding: 4pt;
|
||||||
|
}
|
||||||
|
.taskConfig {
|
||||||
|
font-size: 10pt;
|
||||||
|
color: #aaa;
|
||||||
|
margin-bottom: 5pt;
|
||||||
|
}
|
314
ui/media/main.js
314
ui/media/main.js
@ -18,6 +18,7 @@ const IMAGE_REGEX = new RegExp('data:image/[A-Za-z]+;base64')
|
|||||||
let sessionId = new Date().getTime()
|
let sessionId = new Date().getTime()
|
||||||
|
|
||||||
let promptField = document.querySelector('#prompt')
|
let promptField = document.querySelector('#prompt')
|
||||||
|
let negativePromptField = document.querySelector('#negative_prompt')
|
||||||
let numOutputsTotalField = document.querySelector('#num_outputs_total')
|
let numOutputsTotalField = document.querySelector('#num_outputs_total')
|
||||||
let numOutputsParallelField = document.querySelector('#num_outputs_parallel')
|
let numOutputsParallelField = document.querySelector('#num_outputs_parallel')
|
||||||
let numInferenceStepsField = document.querySelector('#num_inference_steps')
|
let numInferenceStepsField = document.querySelector('#num_inference_steps')
|
||||||
@ -57,6 +58,10 @@ let initImagePreviewContainer = document.querySelector('#init_image_preview_cont
|
|||||||
let initImageClearBtn = document.querySelector('.init_image_clear')
|
let initImageClearBtn = document.querySelector('.init_image_clear')
|
||||||
let promptStrengthContainer = document.querySelector('#prompt_strength_container')
|
let promptStrengthContainer = document.querySelector('#prompt_strength_container')
|
||||||
|
|
||||||
|
let initialText = document.querySelector("#initial-text")
|
||||||
|
let previewTools = document.querySelector("#preview-tools")
|
||||||
|
let clearAllPreviewsBtn = document.querySelector("#clear-all-previews")
|
||||||
|
|
||||||
// let maskSetting = document.querySelector('#editor-inputs-mask_setting')
|
// let maskSetting = document.querySelector('#editor-inputs-mask_setting')
|
||||||
// let maskImagePreviewContainer = document.querySelector('#mask_preview_container')
|
// let maskImagePreviewContainer = document.querySelector('#mask_preview_container')
|
||||||
// let maskImageClearBtn = document.querySelector('#mask_clear')
|
// let maskImageClearBtn = document.querySelector('#mask_clear')
|
||||||
@ -66,18 +71,19 @@ let editorModifierEntries = document.querySelector('#editor-modifiers-entries')
|
|||||||
let editorModifierTagsList = document.querySelector('#editor-inputs-tags-list')
|
let editorModifierTagsList = document.querySelector('#editor-inputs-tags-list')
|
||||||
let editorTagsContainer = document.querySelector('#editor-inputs-tags-container')
|
let editorTagsContainer = document.querySelector('#editor-inputs-tags-container')
|
||||||
|
|
||||||
|
let imagePreview = document.querySelector("#preview")
|
||||||
let previewImageField = document.querySelector('#preview-image')
|
let previewImageField = document.querySelector('#preview-image')
|
||||||
previewImageField.onchange = () => changePreviewImages(previewImageField.value);
|
previewImageField.onchange = () => changePreviewImages(previewImageField.value);
|
||||||
|
|
||||||
let modifierCardSizeSlider = document.querySelector('#modifier-card-size-slider')
|
let modifierCardSizeSlider = document.querySelector('#modifier-card-size-slider')
|
||||||
modifierCardSizeSlider.onchange = () => resizeModifierCards(modifierCardSizeSlider.value);
|
modifierCardSizeSlider.onchange = () => resizeModifierCards(modifierCardSizeSlider.value);
|
||||||
|
|
||||||
let previewPrompt = document.querySelector('#preview-prompt')
|
// let previewPrompt = document.querySelector('#preview-prompt')
|
||||||
|
|
||||||
let showConfigToggle = document.querySelector('#configToggleBtn')
|
let showConfigToggle = document.querySelector('#configToggleBtn')
|
||||||
// let configBox = document.querySelector('#config')
|
// let configBox = document.querySelector('#config')
|
||||||
let outputMsg = document.querySelector('#outputMsg')
|
// let outputMsg = document.querySelector('#outputMsg')
|
||||||
let progressBar = document.querySelector("#progressBar")
|
// let progressBar = document.querySelector("#progressBar")
|
||||||
|
|
||||||
let soundToggle = document.querySelector('#sound_toggle')
|
let soundToggle = document.querySelector('#sound_toggle')
|
||||||
|
|
||||||
@ -108,8 +114,10 @@ let serverStatus = 'offline'
|
|||||||
let activeTags = []
|
let activeTags = []
|
||||||
let modifiers = []
|
let modifiers = []
|
||||||
let lastPromptUsed = ''
|
let lastPromptUsed = ''
|
||||||
let taskStopped = true
|
let bellPending = false
|
||||||
let batchesDone = 0
|
|
||||||
|
let taskQueue = []
|
||||||
|
let currentTask = null
|
||||||
|
|
||||||
const modifierThumbnailPath = 'media/modifier-thumbnails';
|
const modifierThumbnailPath = 'media/modifier-thumbnails';
|
||||||
const activeCardClass = 'modifier-card-active';
|
const activeCardClass = 'modifier-card-active';
|
||||||
@ -211,7 +219,7 @@ function setStatus(statusType, msg, msgType) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function logMsg(msg, level) {
|
function logMsg(msg, level, outputMsg) {
|
||||||
if (level === 'error') {
|
if (level === 'error') {
|
||||||
outputMsg.innerHTML = '<span style="color: red">Error: ' + msg + '</span>'
|
outputMsg.innerHTML = '<span style="color: red">Error: ' + msg + '</span>'
|
||||||
} else if (level === 'warn') {
|
} else if (level === 'warn') {
|
||||||
@ -223,8 +231,8 @@ function logMsg(msg, level) {
|
|||||||
console.log(level, msg)
|
console.log(level, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
function logError(msg, res) {
|
function logError(msg, res, outputMsg) {
|
||||||
logMsg(msg, 'error')
|
logMsg(msg, 'error', outputMsg)
|
||||||
|
|
||||||
console.log('request error', res)
|
console.log('request error', res)
|
||||||
setStatus('request', 'error', 'error')
|
setStatus('request', 'error', 'error')
|
||||||
@ -332,11 +340,19 @@ function showImages(req, res, livePreview) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// makes a single image. don't call this directly, use makeImage() instead
|
// makes a single image. don't call this directly, use makeImage() instead
|
||||||
async function doMakeImage(reqBody, batchCount) {
|
async function doMakeImage(task) {
|
||||||
if (taskStopped) {
|
if (task.stopped) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const reqBody = task.reqBody
|
||||||
|
const batchCount = task.batchCount
|
||||||
|
const outputContainer = task.outputContainer
|
||||||
|
|
||||||
|
const outputMsg = task['outputMsg']
|
||||||
|
const previewPrompt = task['previewPrompt']
|
||||||
|
const progressBar = task['progressBar']
|
||||||
|
|
||||||
let res = ''
|
let res = ''
|
||||||
let seed = reqBody['seed']
|
let seed = reqBody['seed']
|
||||||
let numOutputs = parseInt(reqBody['num_outputs'])
|
let numOutputs = parseInt(reqBody['num_outputs'])
|
||||||
@ -374,7 +390,7 @@ async function doMakeImage(reqBody, batchCount) {
|
|||||||
finalJSON += jsonStr
|
finalJSON += jsonStr
|
||||||
} else {
|
} else {
|
||||||
let batchSize = stepUpdate.total_steps
|
let batchSize = stepUpdate.total_steps
|
||||||
let overallStepCount = stepUpdate.step + batchesDone * batchSize
|
let overallStepCount = stepUpdate.step + task.batchesDone * batchSize
|
||||||
let totalSteps = batchCount * batchSize
|
let totalSteps = batchCount * batchSize
|
||||||
let percent = 100 * (overallStepCount / totalSteps)
|
let percent = 100 * (overallStepCount / totalSteps)
|
||||||
percent = (percent > 100 ? 100 : percent)
|
percent = (percent > 100 ? 100 : percent)
|
||||||
@ -384,13 +400,13 @@ async function doMakeImage(reqBody, batchCount) {
|
|||||||
stepsRemaining = (stepsRemaining < 0 ? 0 : stepsRemaining)
|
stepsRemaining = (stepsRemaining < 0 ? 0 : stepsRemaining)
|
||||||
timeRemaining = (timeTaken === -1 ? '' : stepsRemaining * timeTaken) // ms
|
timeRemaining = (timeTaken === -1 ? '' : stepsRemaining * timeTaken) // ms
|
||||||
|
|
||||||
outputMsg.innerHTML = `Batch ${batchesDone+1} of ${batchCount}`
|
outputMsg.innerHTML = `Batch ${task.batchesDone+1} of ${batchCount}`
|
||||||
progressBar.innerHTML = `Generating image(s): ${percent}%`
|
outputMsg.innerHTML += `. Generating image(s): ${percent}%`
|
||||||
|
|
||||||
if (timeTaken !== -1) {
|
timeRemaining = (timeTaken !== -1 ? millisecondsToStr(timeRemaining) : '')
|
||||||
progressBar.innerHTML += `<br>Time remaining (approx): ${millisecondsToStr(timeRemaining)}`
|
|
||||||
}
|
outputMsg.innerHTML += `. Time remaining (approx): ${timeRemaining}`
|
||||||
progressBar.style.display = 'block'
|
outputMsg.style.display = 'block'
|
||||||
|
|
||||||
if (stepUpdate.output !== undefined) {
|
if (stepUpdate.output !== undefined) {
|
||||||
showImages(reqBody, stepUpdate, true);
|
showImages(reqBody, stepUpdate, true);
|
||||||
@ -402,7 +418,7 @@ async function doMakeImage(reqBody, batchCount) {
|
|||||||
|
|
||||||
prevTime = t
|
prevTime = t
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logError('Stable Diffusion had an error. Please check the logs in the command-line window.', res)
|
logError('Stable Diffusion had an error. Please check the logs in the command-line window.', res, outputMsg)
|
||||||
res = undefined
|
res = undefined
|
||||||
throw e
|
throw e
|
||||||
}
|
}
|
||||||
@ -410,9 +426,9 @@ async function doMakeImage(reqBody, batchCount) {
|
|||||||
|
|
||||||
if (res.status != 200) {
|
if (res.status != 200) {
|
||||||
if (serverStatus === 'online') {
|
if (serverStatus === 'online') {
|
||||||
logError('Stable Diffusion had an error: ' + await res.text(), res)
|
logError('Stable Diffusion had an error: ' + await res.text(), res, outputMsg)
|
||||||
} else {
|
} else {
|
||||||
logError("Stable Diffusion is still starting up, please wait. If this goes on beyond a few minutes, Stable Diffusion has probably crashed. Please check the error message in the command-line window.", res)
|
logError("Stable Diffusion is still starting up, please wait. If this goes on beyond a few minutes, Stable Diffusion has probably crashed. Please check the error message in the command-line window.", res, outputMsg)
|
||||||
}
|
}
|
||||||
res = undefined
|
res = undefined
|
||||||
progressBar.style.display = 'none'
|
progressBar.style.display = 'none'
|
||||||
@ -432,7 +448,6 @@ async function doMakeImage(reqBody, batchCount) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
res = JSON.parse(finalJSON)
|
res = JSON.parse(finalJSON)
|
||||||
progressBar.style.display = 'none'
|
|
||||||
|
|
||||||
if (res.status !== 'succeeded') {
|
if (res.status !== 'succeeded') {
|
||||||
let msg = ''
|
let msg = ''
|
||||||
@ -450,13 +465,13 @@ async function doMakeImage(reqBody, batchCount) {
|
|||||||
} else {
|
} else {
|
||||||
msg = res
|
msg = res
|
||||||
}
|
}
|
||||||
logError(msg, res)
|
logError(msg, res, outputMsg)
|
||||||
res = undefined
|
res = undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('request error', e)
|
console.log('request error', e)
|
||||||
logError('Stable Diffusion had an error. Please check the logs in the command-line window. <br/><br/>' + e + '<br/><pre>' + e.stack + '</pre>', res)
|
logError('Stable Diffusion had an error. Please check the logs in the command-line window. <br/><br/>' + e + '<br/><pre>' + e.stack + '</pre>', res, outputMsg)
|
||||||
setStatus('request', 'error', 'error')
|
setStatus('request', 'error', 'error')
|
||||||
progressBar.style.display = 'none'
|
progressBar.style.display = 'none'
|
||||||
res = undefined
|
res = undefined
|
||||||
@ -471,48 +486,96 @@ async function doMakeImage(reqBody, batchCount) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function validateInput() {
|
async function checkTasks() {
|
||||||
let width = parseInt(widthField.value)
|
if (taskQueue.length === 0) {
|
||||||
let height = parseInt(heightField.value)
|
setStatus('request', 'done', 'success')
|
||||||
|
setTimeout(checkTasks, 500)
|
||||||
|
stopImageBtn.style.display = 'none'
|
||||||
|
makeImageBtn.innerHTML = 'Make Image'
|
||||||
|
|
||||||
if (IMAGE_REGEX.test(initImagePreview.src)) {
|
currentTask = null
|
||||||
if (initImagePreview.naturalWidth > MAX_INIT_IMAGE_DIMENSION || initImagePreview.naturalHeight > MAX_INIT_IMAGE_DIMENSION) {
|
|
||||||
return {'isValid': false, 'warning': `The dimensions of your initial image are very large, and can cause 'Out of Memory' errors! Please ensure that its dimensions are equal (or smaller) than the desired output image.
|
if (bellPending) {
|
||||||
<br/><br/>
|
if (isSoundEnabled()) {
|
||||||
Your initial image size is ${initImagePreview.naturalWidth}x${initImagePreview.naturalHeight} pixels. Please try to keep it smaller than ${MAX_INIT_IMAGE_DIMENSION}x${MAX_INIT_IMAGE_DIMENSION}.`}
|
playSound()
|
||||||
}
|
}
|
||||||
|
bellPending = false
|
||||||
}
|
}
|
||||||
|
|
||||||
return {'isValid': true}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function makeImage() {
|
|
||||||
if (serverStatus !== 'online') {
|
|
||||||
logError('The server is still starting up..')
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let validation = validateInput()
|
|
||||||
if (validation['isValid']) {
|
|
||||||
outputMsg.innerHTML = 'Starting..'
|
|
||||||
} else {
|
|
||||||
if (validation['error']) {
|
|
||||||
logError(validation['error'])
|
|
||||||
return
|
|
||||||
} else if (validation['warning']) {
|
|
||||||
logMsg(validation['warning'], 'warn')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setStatus('request', 'fetching..')
|
setStatus('request', 'fetching..')
|
||||||
|
|
||||||
makeImageBtn.innerHTML = 'Processing..'
|
|
||||||
makeImageBtn.disabled = true
|
|
||||||
makeImageBtn.style.display = 'none'
|
|
||||||
stopImageBtn.style.display = 'block'
|
stopImageBtn.style.display = 'block'
|
||||||
|
makeImageBtn.innerHTML = 'Enqueue Next Image'
|
||||||
|
bellPending = true
|
||||||
|
|
||||||
taskStopped = false
|
previewTools.style.display = 'block'
|
||||||
batchesDone = 0
|
|
||||||
|
let task = taskQueue.pop()
|
||||||
|
currentTask = task
|
||||||
|
|
||||||
|
let time = new Date().getTime()
|
||||||
|
|
||||||
|
let successCount = 0
|
||||||
|
|
||||||
|
task.isProcessing = true
|
||||||
|
task['stopTask'].innerHTML = '<i class="fa-solid fa-circle-stop"></i> Stop'
|
||||||
|
task['taskStatusLabel'].innerText = "Processing"
|
||||||
|
task['taskStatusLabel'].className += " activeTaskLabel"
|
||||||
|
console.log(task['taskStatusLabel'].className)
|
||||||
|
|
||||||
|
for (let i = 0; i < task.batchCount; i++) {
|
||||||
|
task.reqBody['seed'] = task.seed + (i * task.reqBody['num_outputs'])
|
||||||
|
|
||||||
|
let success = await doMakeImage(task)
|
||||||
|
task.batchesDone++
|
||||||
|
|
||||||
|
if (!task.isProcessing) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
successCount++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
task.isProcessing = false
|
||||||
|
task['stopTask'].innerHTML = '<i class="fa-solid fa-trash-can"></i> Remove'
|
||||||
|
task['taskStatusLabel'].style.display = 'none'
|
||||||
|
|
||||||
|
time = new Date().getTime() - time
|
||||||
|
time /= 1000
|
||||||
|
|
||||||
|
if (successCount === task.batchCount) {
|
||||||
|
task.outputMsg.innerText = 'Processed ' + task.numOutputsTotal + ' images in ' + time + ' seconds'
|
||||||
|
|
||||||
|
// setStatus('request', 'done', 'success')
|
||||||
|
} else {
|
||||||
|
task.outputMsg.innerText = 'Task ended after ' + time + ' seconds'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (randomSeedField.checked) {
|
||||||
|
seedField.value = task.seed
|
||||||
|
}
|
||||||
|
|
||||||
|
currentTask = null
|
||||||
|
|
||||||
|
setTimeout(checkTasks, 10)
|
||||||
|
}
|
||||||
|
setTimeout(checkTasks, 0)
|
||||||
|
|
||||||
|
async function makeImage() {
|
||||||
|
if (serverStatus !== 'online') {
|
||||||
|
alert('The server is still starting up..')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let task = {
|
||||||
|
stopped: false,
|
||||||
|
batchesDone: 0
|
||||||
|
}
|
||||||
|
|
||||||
let seed = (randomSeedField.checked ? Math.floor(Math.random() * 10000000) : parseInt(seedField.value))
|
let seed = (randomSeedField.checked ? Math.floor(Math.random() * 10000000) : parseInt(seedField.value))
|
||||||
let numOutputsTotal = parseInt(numOutputsTotalField.value)
|
let numOutputsTotal = parseInt(numOutputsTotalField.value)
|
||||||
@ -528,11 +591,10 @@ async function makeImage() {
|
|||||||
prompt += ", " + promptTags;
|
prompt += ", " + promptTags;
|
||||||
}
|
}
|
||||||
|
|
||||||
previewPrompt.innerText = prompt
|
|
||||||
|
|
||||||
let reqBody = {
|
let reqBody = {
|
||||||
session_id: sessionId,
|
session_id: sessionId,
|
||||||
prompt: prompt,
|
prompt: prompt,
|
||||||
|
negative_prompt: negativePromptField.value.trim(),
|
||||||
num_outputs: batchSize,
|
num_outputs: batchSize,
|
||||||
num_inference_steps: numInferenceStepsField.value,
|
num_inference_steps: numInferenceStepsField.value,
|
||||||
guidance_scale: guidanceScaleField.value,
|
guidance_scale: guidanceScaleField.value,
|
||||||
@ -575,44 +637,76 @@ async function makeImage() {
|
|||||||
reqBody['use_upscale'] = upscaleModelField.value
|
reqBody['use_upscale'] = upscaleModelField.value
|
||||||
}
|
}
|
||||||
|
|
||||||
let time = new Date().getTime()
|
let taskConfig = `Seed: ${seed}, Sampler: ${reqBody['sampler']}, Inference Steps: ${numInferenceStepsField.value}, Guidance Scale: ${guidanceScaleField.value}`
|
||||||
imagesContainer.innerHTML = ''
|
|
||||||
|
|
||||||
let successCount = 0
|
if (negativePromptField.value.trim() !== '') {
|
||||||
|
taskConfig += `, Negative Prompt: ${negativePromptField.value.trim()}`
|
||||||
for (let i = 0; i < batchCount; i++) {
|
|
||||||
reqBody['seed'] = seed + (i * batchSize)
|
|
||||||
|
|
||||||
let success = await doMakeImage(reqBody, batchCount)
|
|
||||||
batchesDone++
|
|
||||||
|
|
||||||
if (success) {
|
|
||||||
outputMsg.innerText = 'Processed batch ' + (i+1) + '/' + batchCount
|
|
||||||
successCount++
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
makeImageBtn.innerText = 'Make Image'
|
if (reqBody['init_image'] !== undefined) {
|
||||||
makeImageBtn.disabled = false
|
taskConfig += `, Prompt Strength: ${promptStrengthField.value}`
|
||||||
makeImageBtn.style.display = 'block'
|
|
||||||
stopImageBtn.style.display = 'none'
|
|
||||||
|
|
||||||
if (isSoundEnabled()) {
|
|
||||||
playSound()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
time = new Date().getTime() - time
|
if (useFaceCorrectionField.checked) {
|
||||||
time /= 1000
|
taskConfig += `, Fix Faces: ${reqBody['use_face_correction']}`
|
||||||
|
|
||||||
if (successCount === batchCount) {
|
|
||||||
outputMsg.innerText = 'Processed ' + numOutputsTotal + ' images in ' + time + ' seconds'
|
|
||||||
|
|
||||||
setStatus('request', 'done', 'success')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (randomSeedField.checked) {
|
if (useUpscalingField.checked) {
|
||||||
seedField.value = seed
|
taskConfig += `, Upscale: ${reqBody['use_upscale']}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task['reqBody'] = reqBody
|
||||||
|
task['seed'] = seed
|
||||||
|
task['batchCount'] = batchCount
|
||||||
|
task['isProcessing'] = false
|
||||||
|
|
||||||
|
let taskEntry = document.createElement('div')
|
||||||
|
taskEntry.className = 'imageTaskContainer'
|
||||||
|
taskEntry.innerHTML = ` <div class="taskStatusLabel">Enqueued</div>
|
||||||
|
<button class="secondaryButton stopTask"><i class="fa-solid fa-trash-can"></i> Remove</button>
|
||||||
|
<div class="preview-prompt collapsible active"></div>
|
||||||
|
<div class="taskConfig">${taskConfig}</div>
|
||||||
|
<div class="collapsible-content" style="display: block">
|
||||||
|
<div class="outputMsg"></div>
|
||||||
|
<div class="progressBar"></div>
|
||||||
|
<div class="img-preview">
|
||||||
|
</div>`
|
||||||
|
|
||||||
|
createCollapsibles(taskEntry)
|
||||||
|
|
||||||
|
task['numOutputsTotal'] = numOutputsTotal
|
||||||
|
task['taskStatusLabel'] = taskEntry.querySelector('.taskStatusLabel')
|
||||||
|
task['outputContainer'] = taskEntry.querySelector('.img-preview')
|
||||||
|
task['outputMsg'] = taskEntry.querySelector('.outputMsg')
|
||||||
|
task['previewPrompt'] = taskEntry.querySelector('.preview-prompt')
|
||||||
|
task['progressBar'] = taskEntry.querySelector('.progressBar')
|
||||||
|
task['stopTask'] = taskEntry.querySelector('.stopTask')
|
||||||
|
|
||||||
|
task['stopTask'].addEventListener('click', async function() {
|
||||||
|
if (task['isProcessing']) {
|
||||||
|
task.isProcessing = false
|
||||||
|
try {
|
||||||
|
let res = await fetch('/image/stop')
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let idx = taskQueue.indexOf(task)
|
||||||
|
if (idx >= 0) {
|
||||||
|
taskQueue.splice(idx, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
taskEntry.remove()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
imagePreview.insertBefore(taskEntry, previewTools.nextSibling)
|
||||||
|
|
||||||
|
task['previewPrompt'].innerText = prompt
|
||||||
|
|
||||||
|
taskQueue.unshift(task)
|
||||||
|
|
||||||
|
initialText.style.display = 'none'
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a file name with embedded prompt and metadata
|
// create a file name with embedded prompt and metadata
|
||||||
@ -650,17 +744,37 @@ function createFileName(seed) {
|
|||||||
return fileName
|
return fileName
|
||||||
}
|
}
|
||||||
|
|
||||||
stopImageBtn.addEventListener('click', async function() {
|
async function stopAllTasks() {
|
||||||
|
taskQueue.forEach(task => {
|
||||||
|
task.isProcessing = false
|
||||||
|
})
|
||||||
|
taskQueue = []
|
||||||
|
|
||||||
|
if (currentTask !== null) {
|
||||||
|
currentTask.isProcessing = false
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let res = await fetch('/image/stop')
|
let res = await fetch('/image/stop')
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e)
|
console.log(e)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
stopImageBtn.style.display = 'none'
|
clearAllPreviewsBtn.addEventListener('click', async function() {
|
||||||
makeImageBtn.style.display = 'block'
|
await stopAllTasks()
|
||||||
|
|
||||||
taskStopped = true
|
let taskEntries = document.querySelectorAll('.imageTaskContainer')
|
||||||
|
taskEntries.forEach(task => {
|
||||||
|
task.remove()
|
||||||
|
})
|
||||||
|
|
||||||
|
previewTools.style.display = 'none'
|
||||||
|
initialText.style.display = 'block'
|
||||||
|
})
|
||||||
|
|
||||||
|
stopImageBtn.addEventListener('click', async function() {
|
||||||
|
await stopAllTasks()
|
||||||
})
|
})
|
||||||
|
|
||||||
soundToggle.addEventListener('click', handleBoolSettingChange(SOUND_ENABLED_KEY))
|
soundToggle.addEventListener('click', handleBoolSettingChange(SOUND_ENABLED_KEY))
|
||||||
@ -757,7 +871,7 @@ updatePromptStrength()
|
|||||||
|
|
||||||
useBetaChannelField.addEventListener('click', async function(e) {
|
useBetaChannelField.addEventListener('click', async function(e) {
|
||||||
if (serverStatus !== 'online') {
|
if (serverStatus !== 'online') {
|
||||||
logError('The server is still starting up..')
|
// logError('The server is still starting up..')
|
||||||
alert('The server is still starting up..')
|
alert('The server is still starting up..')
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
return false
|
return false
|
||||||
@ -918,6 +1032,22 @@ function millisecondsToStr(milliseconds) {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://gomakethings.com/finding-the-next-and-previous-sibling-elements-that-match-a-selector-with-vanilla-js/
|
||||||
|
function getNextSibling(elem, selector) {
|
||||||
|
// Get the next sibling element
|
||||||
|
var sibling = elem.nextElementSibling
|
||||||
|
|
||||||
|
// If there's no selector, return the first sibling
|
||||||
|
if (!selector) return sibling
|
||||||
|
|
||||||
|
// If the sibling matches our selector, use it
|
||||||
|
// If not, jump to the next sibling and continue the loop
|
||||||
|
while (sibling) {
|
||||||
|
if (sibling.matches(selector)) return sibling
|
||||||
|
sibling = sibling.nextElementSibling
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function createCollapsibles(node) {
|
function createCollapsibles(node) {
|
||||||
if (!node) {
|
if (!node) {
|
||||||
node = document
|
node = document
|
||||||
@ -937,7 +1067,7 @@ function createCollapsibles(node) {
|
|||||||
|
|
||||||
c.addEventListener('click', function() {
|
c.addEventListener('click', function() {
|
||||||
this.classList.toggle("active")
|
this.classList.toggle("active")
|
||||||
let content = this.nextElementSibling
|
let content = getNextSibling(this, '.collapsible-content')
|
||||||
if (content.style.display === "block") {
|
if (content.style.display === "block") {
|
||||||
content.style.display = "none"
|
content.style.display = "none"
|
||||||
handle.innerHTML = '➕' // plus
|
handle.innerHTML = '➕' // plus
|
||||||
|
@ -3,6 +3,7 @@ import json
|
|||||||
class Request:
|
class Request:
|
||||||
session_id: str = "session"
|
session_id: str = "session"
|
||||||
prompt: str = ""
|
prompt: str = ""
|
||||||
|
negative_prompt: str = ""
|
||||||
init_image: str = None # base64
|
init_image: str = None # base64
|
||||||
mask: str = None # base64
|
mask: str = None # base64
|
||||||
num_outputs: int = 1
|
num_outputs: int = 1
|
||||||
@ -30,6 +31,7 @@ class Request:
|
|||||||
return {
|
return {
|
||||||
"session_id": self.session_id,
|
"session_id": self.session_id,
|
||||||
"prompt": self.prompt,
|
"prompt": self.prompt,
|
||||||
|
"negative_prompt": self.negative_prompt,
|
||||||
"num_outputs": self.num_outputs,
|
"num_outputs": self.num_outputs,
|
||||||
"num_inference_steps": self.num_inference_steps,
|
"num_inference_steps": self.num_inference_steps,
|
||||||
"guidance_scale": self.guidance_scale,
|
"guidance_scale": self.guidance_scale,
|
||||||
@ -46,6 +48,7 @@ class Request:
|
|||||||
return f'''
|
return f'''
|
||||||
session_id: {self.session_id}
|
session_id: {self.session_id}
|
||||||
prompt: {self.prompt}
|
prompt: {self.prompt}
|
||||||
|
negative_prompt: {self.negative_prompt}
|
||||||
seed: {self.seed}
|
seed: {self.seed}
|
||||||
num_inference_steps: {self.num_inference_steps}
|
num_inference_steps: {self.num_inference_steps}
|
||||||
sampler: {self.sampler}
|
sampler: {self.sampler}
|
||||||
|
@ -343,7 +343,7 @@ def do_mk_img(req: Request):
|
|||||||
modelCS.to(device)
|
modelCS.to(device)
|
||||||
uc = None
|
uc = None
|
||||||
if opt_scale != 1.0:
|
if opt_scale != 1.0:
|
||||||
uc = modelCS.get_learned_conditioning(batch_size * [""])
|
uc = modelCS.get_learned_conditioning(batch_size * [req.negative_prompt])
|
||||||
if isinstance(prompts, tuple):
|
if isinstance(prompts, tuple):
|
||||||
prompts = list(prompts)
|
prompts = list(prompts)
|
||||||
|
|
||||||
@ -444,7 +444,7 @@ def do_mk_img(req: Request):
|
|||||||
if return_orig_img:
|
if return_orig_img:
|
||||||
save_image(img, img_out_path)
|
save_image(img, img_out_path)
|
||||||
|
|
||||||
save_metadata(meta_out_path, prompts, opt_seed, opt_W, opt_H, opt_ddim_steps, opt_scale, opt_strength, opt_use_face_correction, opt_use_upscale, opt_sampler_name)
|
save_metadata(meta_out_path, prompts, opt_seed, opt_W, opt_H, opt_ddim_steps, opt_scale, opt_strength, opt_use_face_correction, opt_use_upscale, opt_sampler_name, req.negative_prompt)
|
||||||
|
|
||||||
if return_orig_img:
|
if return_orig_img:
|
||||||
img_data = img_to_base64_str(img)
|
img_data = img_to_base64_str(img)
|
||||||
@ -505,8 +505,8 @@ def save_image(img, img_out_path):
|
|||||||
except:
|
except:
|
||||||
print('could not save the file', traceback.format_exc())
|
print('could not save the file', traceback.format_exc())
|
||||||
|
|
||||||
def save_metadata(meta_out_path, prompts, opt_seed, opt_W, opt_H, opt_ddim_steps, opt_scale, opt_prompt_strength, opt_correct_face, opt_upscale, sampler_name):
|
def save_metadata(meta_out_path, prompts, opt_seed, opt_W, opt_H, opt_ddim_steps, opt_scale, opt_prompt_strength, opt_correct_face, opt_upscale, sampler_name, negative_prompt):
|
||||||
metadata = f"{prompts[0]}\nWidth: {opt_W}\nHeight: {opt_H}\nSeed: {opt_seed}\nSteps: {opt_ddim_steps}\nGuidance Scale: {opt_scale}\nPrompt Strength: {opt_prompt_strength}\nUse Face Correction: {opt_correct_face}\nUse Upscaling: {opt_upscale}\nSampler: {sampler_name}"
|
metadata = f"{prompts[0]}\nWidth: {opt_W}\nHeight: {opt_H}\nSeed: {opt_seed}\nSteps: {opt_ddim_steps}\nGuidance Scale: {opt_scale}\nPrompt Strength: {opt_prompt_strength}\nUse Face Correction: {opt_correct_face}\nUse Upscaling: {opt_upscale}\nSampler: {sampler_name}\nNegative Prompt: {negative_prompt}"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(meta_out_path, 'w') as f:
|
with open(meta_out_path, 'w') as f:
|
||||||
|
@ -39,6 +39,7 @@ app.mount('/media', StaticFiles(directory=os.path.join(SD_UI_DIR, 'media/')), na
|
|||||||
class ImageRequest(BaseModel):
|
class ImageRequest(BaseModel):
|
||||||
session_id: str = "session"
|
session_id: str = "session"
|
||||||
prompt: str = ""
|
prompt: str = ""
|
||||||
|
negative_prompt: str = ""
|
||||||
init_image: str = None # base64
|
init_image: str = None # base64
|
||||||
mask: str = None # base64
|
mask: str = None # base64
|
||||||
num_outputs: int = 1
|
num_outputs: int = 1
|
||||||
@ -83,7 +84,10 @@ async def ping():
|
|||||||
model_is_loading = True
|
model_is_loading = True
|
||||||
|
|
||||||
from sd_internal import runtime
|
from sd_internal import runtime
|
||||||
runtime.load_model_ckpt(ckpt_to_use="sd-v1-4")
|
|
||||||
|
custom_weight_path = os.path.join(SCRIPT_DIR, 'custom-model.ckpt')
|
||||||
|
ckpt_to_use = "sd-v1-4" if not os.path.exists(custom_weight_path) else "custom-model"
|
||||||
|
runtime.load_model_ckpt(ckpt_to_use=ckpt_to_use)
|
||||||
|
|
||||||
model_loaded = True
|
model_loaded = True
|
||||||
model_is_loading = False
|
model_is_loading = False
|
||||||
@ -100,6 +104,7 @@ def image(req : ImageRequest):
|
|||||||
r = Request()
|
r = Request()
|
||||||
r.session_id = req.session_id
|
r.session_id = req.session_id
|
||||||
r.prompt = req.prompt
|
r.prompt = req.prompt
|
||||||
|
r.negative_prompt = req.negative_prompt
|
||||||
r.init_image = req.init_image
|
r.init_image = req.init_image
|
||||||
r.mask = req.mask
|
r.mask = req.mask
|
||||||
r.num_outputs = req.num_outputs
|
r.num_outputs = req.num_outputs
|
||||||
|
Loading…
Reference in New Issue
Block a user