Compare commits

...

372 Commits

Author SHA1 Message Date
ab6ec3a9b7 Fix - setting can be null sometimes (autosave) 2022-11-14 18:10:23 +05:30
e252c9ac05 Only set the userprofile if in a new micromamba installation 2022-11-14 10:11:28 +05:30
a212fb35c1 Merge pull request #469 from JeLuF/patch-1
set USERPROFILE to local profile (fixes #468)
2022-11-14 10:07:17 +05:30
e59fbac761 set USERPROFILE to local profile (fixes #468)
According to this analysis: https://discord.com/channels/1014774730907209781/1040225028828057620/1040324719074889779
the USERPROFILE variable must not contain unicode characters as well. Only setting APPDATA is not sufficient.
2022-11-13 09:19:01 +01:00
745ea5fb05 Update index.html 2022-11-12 17:39:29 +05:30
fa16ca4eec Update auto-save.js 2022-11-12 17:39:26 +05:30
d7757b8b03 Update index.html 2022-11-12 17:25:07 +05:30
98aefad249 Skip if a setting isn't present 2022-11-12 17:24:48 +05:30
c17222dbe4 The error level is unreliable on Windows when testing a command. My cmd.exe shell hooks are broken, and this condition always fails for me 2022-11-12 13:08:46 +05:30
abd8c69395 Bypass a bug in micromamba, where it fails silently if the APPDATA env variable has special characters like öäü 2022-11-12 13:07:29 +05:30
a7fde73df4 Tabs to spaces in bootstrap scripts 2022-11-12 12:47:39 +05:30
d1c9db874f Set the PYTHONPATH right at the start, to prevent it from picking up a system-wide python 2022-11-11 11:37:15 +05:30
82fda5cb03 Temporarily remove the default-on behavior for GFPGAN, until the CPU version is fixed 2022-11-09 11:24:14 +05:30
65587536ab Fix typo in binding of host/ip 2022-11-09 11:08:25 +05:30
ad31be8344 Fix 2022-11-09 11:05:07 +05:30
25815c81bf Bring back the configurable host/port 2022-11-09 11:03:03 +05:30
852a22f86d temporary rollback of configurable host/port 2022-11-09 10:58:25 +05:30
e22b171b7b Merge pull request #445 from JeLuF/err-handle
Improve error handling
2022-11-09 10:08:55 +05:30
842e7e559e Update bootstrap.bat 2022-11-08 10:30:26 +05:30
a62ee7850b Merge branch 'err-handle' of github.com:JeLuF/stable-diffusion-ui into err-handle 2022-11-05 23:31:19 +01:00
d3a90ccc0d Windows error handling
- cd to the script location on start of 'Start Stable Diffusion UI.cmd'
- Bail out when downloading micromamba fails
- add env variables SD_UI_BIND_IP and SD_UI_BIND_PORT to configure uvicorn
2022-11-05 23:30:40 +01:00
46b13ee664 Merge branch 'cmdr2:main' into err-handle 2022-11-05 20:49:19 +01:00
cfa6dc7836 Add blank lines to error message 2022-11-05 19:02:19 +01:00
f969bfa7be More error handling, central error function 2022-11-05 18:59:59 +01:00
e86a883d0a Merge pull request #439 from JeLuF/patch-9
Add a link to the wiki to the "Help & Community" dropdown.
2022-11-05 11:01:49 +05:30
82d764000a Fix https://github.com/cmdr2/stable-diffusion-ui/issues/441 - numerical validation 2022-11-04 19:54:59 +05:30
63dcb8cfe1 Add a link to the wiki to the "Help & Community" dropdown. 2022-11-03 20:39:08 +01:00
ea7006eec4 Set the PYTHONPATH before installation to prevent conda from knowing about any system-wide python installations (and skipping package installs due to that) 2022-11-02 19:45:49 +05:30
053bce7a8e Set the correct mimetype in the base64 image 2022-10-31 19:05:57 +05:30
2f208832a9 Merge pull request #424 from patriceac/patch-1
Fixing the parsing of Set and Permute operators in custom tags
2022-10-31 18:25:30 +05:30
f08a875cd2 Update main.js
Fix parsing of Set and Permute operators in custom tags.
2022-10-30 00:26:53 -07:00
d492d3f738 Update main.js
Fixing the parsing of Set and Permute operators in custom tags.
2022-10-30 00:22:01 -07:00
33e25d9241 Deduce the filename in developer_console.sh instead of hardcoding it 2022-10-29 20:25:11 +05:30
fc11018158 Re-download micromamba if necessary 2022-10-29 19:41:52 +05:30
450fb2553c fix: change to the correct working directory
changes to the directory containing `start.sh` prior to activating the conda environment

this allows you to run the program without first changing to the correct directory, eg: `$ ~/bin/stable-diffusion-ui/start.sh`
2022-10-29 15:08:25 +05:30
0b678b1f16 Merge pull request #413 from JeLuF/patch-7
Change "Advanced Settings" to "Image settings"
2022-10-28 13:10:04 +05:30
79b5e85b15 Change "Advanced Settings" to "Image settings"
The menu has been renamed, so the welcome text should reflect this.
2022-10-28 09:21:31 +02:00
9f90749f99 Merge pull request #405 from JeLuF/patch-6
Add disk space requirements
2022-10-28 00:22:08 +05:30
1257e34487 Add disk space requirements 2022-10-27 17:39:54 +02:00
a45743f443 Update CONTRIBUTING.md 2022-10-27 20:56:49 +05:30
cf313939aa Merge pull request #402 from cmdr2/beta
Retry micromamba download on windows
2022-10-27 19:50:12 +05:30
873d4bd3f2 Retry micromamba download on windows 2022-10-27 19:47:20 +05:30
f43f3fc84b Merge pull request #401 from cmdr2/beta
Download micromamba again if it failed to download the first time
2022-10-27 16:07:10 +05:30
0e1fed86ba Download micromamba again if it failed to download the first time 2022-10-27 16:06:16 +05:30
5c1bbc08ca Merge pull request #399 from JeLuF/patch-5
Undo curl change
2022-10-27 07:37:15 +05:30
6ba32b95f3 Undo curl change
#392 Resume Downloads
The retry options also don't work on some windows machines:
https://discord.com/channels/1014774730907209781/1014774732018683926/1034935751332347922
2022-10-27 00:26:24 +02:00
6d43e0951c Update on_sd_start.sh 2022-10-27 00:49:32 +05:30
1dc2c6f183 Update README.md 2022-10-26 18:31:39 +05:30
984b8f7e6f No need to generate arch-specific installers 2022-10-26 18:28:21 +05:30
0f8448b2c0 Merge pull request #396 from cmdr2/main
Merge main
2022-10-26 18:11:53 +05:30
088c546bee Merge pull request #394 from JeLuF/patch-4
Retry downloads on flaky internet connections
2022-10-26 17:36:46 +05:30
20fff378f0 Merge pull request #395 from cmdr2/beta
Use micromamba to install git and conda, instead of bundling a copy of git and conda in the installer. This will not affect existing installations, they'll continue using the previously bundled git and conda that came with the old installer
2022-10-26 17:35:30 +05:30
4994a7ac85 Update on_sd_start.sh 2022-10-26 13:27:49 +02:00
a959c69d32 Retry downloads for flaky internet connections
See issue #392
2022-10-26 13:26:19 +02:00
39244568be Merge pull request #391 from cmdr2/installer_umamba
Remove the extra python version print
2022-10-26 16:02:25 +05:30
c8fc0bb4f5 Remove the extra python version print 2022-10-26 16:02:00 +05:30
654ad5c71f Merge pull request #390 from cmdr2/installer_umamba
Report the python version after activating the SD environment, that l…
2022-10-26 16:00:56 +05:30
7b9d18caea Report the python version after activating the SD environment, that log is not very useful otherwise 2022-10-26 16:00:21 +05:30
8d347efec2 Merge pull request #389 from cmdr2/installer_umamba
Use micromamba to install git and conda, instead of bundling a copy of git and conda in the installer. This will not affect existing installations, they'll continue using the previously bundled git and conda that came with the old installer
2022-10-26 13:06:43 +05:30
85de6dd52e Merge branch 'beta' into installer_umamba 2022-10-26 13:01:22 +05:30
c024b39c8b Get ready for installer_umamba 2022-10-26 12:55:39 +05:30
1f0db48487 Bump version 2022-10-26 12:53:22 +05:30
2bc5f475f4 Merge pull request #386 from cmdr2/beta
Refactor the previously saved settings into the new auto-save system
2022-10-26 12:48:15 +05:30
5abf4c99de Merge pull request #385 from cmdr2/main
Merge from main
2022-10-26 12:45:47 +05:30
137e519b66 Move the installer activation to on_sd_start 2022-10-26 12:15:58 +05:30
dcb27e7de8 Build the win installer on windows, and linux/mac installer on linux/mac 2022-10-26 11:45:43 +05:30
d4d5b5a75c Fix the echo script 2022-10-26 11:40:27 +05:30
a83b3f8408 typo in the help copy script 2022-10-26 11:28:45 +05:30
da9af8673f Create the scripts folder in the installers 2022-10-26 11:27:34 +05:30
1b4ba3b396 Update the build scripts for generating the installers 2022-10-26 11:26:10 +05:30
eb2f1cbc9e Update README.md 2022-10-26 11:03:12 +05:30
28f58f72dd Update README.md 2022-10-26 11:02:53 +05:30
81389401df Update README.md 2022-10-26 11:02:06 +05:30
c618c5c5f0 Update README.md 2022-10-26 10:55:25 +05:30
0eaff4c626 Update README.md 2022-10-26 10:55:00 +05:30
9783c1052d Update README.md 2022-10-25 22:58:44 +05:30
f732fa9736 Use call to start the conda script; activate the installer env first even in the developer console 2022-10-25 20:26:46 +05:30
0c2d227da1 Activate the installer env while starting up, like the previous installer did in the start script 2022-10-25 19:21:26 +05:30
a281efef04 deactivate any pre-activated conda environments, by returning to (base) and then deactivating that. On Windows and Linux 2022-10-25 18:07:29 +05:30
538dcec348 deactivate any pre-activated conda environments before installing 2022-10-25 17:26:33 +05:30
0d38c8ae8f Bring back the post-installation test for torch 2022-10-25 16:38:08 +05:30
967c1a2da9 No need for conda 4.14, disable the broken test for torch 2022-10-25 15:42:22 +05:30
f3da326b77 Remove debug logging 2022-10-25 14:36:57 +05:30
153a6e2cb0 Temporarily disable sd_start for linux 2022-10-25 14:30:08 +05:30
95f37b9d36 Use conda 4.14 in the new installer as well (like the previous installer did) 2022-10-25 13:00:57 +05:30
60c37a1fc7 Set the PYTHONPATH before testing the SD installation 2022-10-25 12:48:56 +05:30
615c61e230 Fix a broken PYTHONPATH export in the linux script, used ; instead of : 2022-10-25 12:44:05 +05:30
dd7cb74edc Tweak reset-image-settin
gs button some more
2022-10-25 11:12:34 +05:30
4eed2c7582 Tweak the position of the reset-image-settings button 2022-10-25 11:11:37 +05:30
100e830e04 Bust the cache for included media 2022-10-25 11:03:07 +05:30
af28d82ebc Merge pull request #377 from madrang/beta
Missing '?' in case renderRequest is ever undefined.
2022-10-25 10:46:17 +05:30
6285980f98 Merge pull request #377 from madrang/beta
Missing '?' in case renderRequest is ever undefined.
2022-10-25 10:44:37 +05:30
a5d19cd31f Update index.html 2022-10-25 10:32:55 +05:30
9c9998b468 Merge pull request #364 from mdiller/mdiller_settings
Settings Refactor
2022-10-25 10:32:38 +05:30
011eb55a53 Merge pull request #383 from cmdr2/main
Merge from main
2022-10-25 10:32:17 +05:30
d178f3d1b9 Missing 'e' 2022-10-23 15:01:11 -04:00
6e9d73ec64 Fixe forgotten current_state_error, is now in task_manager 2022-10-23 15:00:36 -04:00
8d1adf4f80 Fix the incorrect command used for downloading and extracting micromamba on linux/osx 2022-10-23 15:13:24 +05:30
d0b7f58e7c Fix a bug in the new linux installer's legacy path 2022-10-23 15:02:03 +05:30
19d24e5644 Merge branch 'main' of github.com:cmdr2/stable-diffusion-ui 2022-10-23 14:38:11 +05:30
461f618b8a Replace grep with findstr on Windows 2022-10-23 14:37:59 +05:30
5ff14d1fed Install conda only if it's not present in the legacy and new installer dir 2022-10-23 11:57:23 +05:30
80c9c1bb05 Install a new conda only if not already present locally 2022-10-23 11:36:31 +05:30
a111d9b18a Supress detached head warning 2022-10-23 11:28:08 +05:30
df14913c67 Always install conda, don't use the system's version 2022-10-23 11:16:28 +05:30
b6c6fef770 Use findstr instead of grep on windows 2022-10-23 10:47:44 +05:30
1a2f37b0ec Make the micromamba binary executable after download on linux 2022-10-23 10:38:01 +05:30
6f3c662783 Bump version 2022-10-23 10:28:27 +05:30
3772137c8f Include usr/bin in the installer PATH; newlines at the end of all files 2022-10-23 10:23:43 +05:30
1ec95d42ba Missing '?' in case renderRequest is ever undefined. 2022-10-22 21:19:42 -04:00
338c2243e3 Newline after printing env info in developer scripts 2022-10-22 23:28:43 +05:30
e8d61225f5 Make the linux installer executable 2022-10-22 23:26:59 +05:30
cc356ce67d Initial commit of the new micromamba-based installer; This should work seamlessly for new and existing users; Also allows the installer to run on mac (but the installation will fail because the mac-specific environment.yaml hasn't been added yet) 2022-10-22 23:24:13 +05:30
5ee05e3aaa Merge pull request #376 from cmdr2/beta
Custom Modifiers; Try to fix the 503 error bug; Show the number of images being created in the Make Image button
2022-10-22 22:27:05 +05:30
5568a09f49 Merge pull request #375 from madrang/beta
Improved render response checks
2022-10-22 22:23:05 +05:30
1199c431ff Removed a new line by mistake. Formatting... 2022-10-22 12:51:43 -04:00
305f2fa448 In case of failure, display error in renderRequest.detail 2022-10-22 12:32:41 -04:00
b051685727 More logging for each state and improved handling. 2022-10-22 12:31:14 -04:00
7580bb21c3 Fix upscale multiple images bug 2022-10-22 08:38:19 +05:30
62102236a2 Merge pull request #372 from rbertus2000/beta
fix multiple images with upscale/fix face button
2022-10-22 08:34:34 +05:30
32d7835119 added a simple tooltip to the reset button 2022-10-21 17:44:04 -07:00
726abf6e65 removed some extra comment stuff 2022-10-21 17:31:57 -07:00
c154a4bdc8 removed second auto-savecss reference 2022-10-21 17:30:09 -07:00
5453925e26 Merge branch 'beta' into mdiller_settings 2022-10-21 17:16:50 -07:00
537e314b49 updated to consume the old settings nicely 2022-10-21 17:13:13 -07:00
1696a5c8e1 modifyCurrentRequest with rest parameters 2022-10-21 23:04:42 +02:00
816cf8f702 fix multiple images with upscale/fix face button 2022-10-21 22:40:26 +02:00
e8167541af Show a tip regarding custom modifiers 2022-10-21 21:35:20 +05:30
329360aa5b Show the number of images it'll make in the Make Image button 2022-10-21 15:18:05 +05:30
eb1a276e60 Move the image modifers toolbar back to the top 2022-10-21 14:54:45 +05:30
a53bac1a94 Fix a bug where a null value for custom modifiers would break 2022-10-21 14:43:32 +05:30
93bf93d3a1 Fix a bug where a null value for custom modifiers would break 2022-10-21 14:42:02 +05:30
4174c8c25c Increase version 2022-10-21 14:36:51 +05:30
48a88a8624 Custom modifiers 2022-10-21 14:08:16 +05:30
d17e216f91 Replace the thumbnail image for glass caustics image modifier 2022-10-21 13:08:23 +05:30
9a71e9ba86 Merge pull request #369 from cmdr2/main
Merge main
2022-10-21 09:57:53 +05:30
ef478a4a9e Remove the message about system-related settings 2022-10-21 09:41:31 +05:30
1bd7d40716 Merge pull request #368 from madrang/HTTP503-Fix
Fix HTTP503 Error.
2022-10-21 07:35:52 +05:30
807e9573fb Check result status, not json object. 2022-10-20 20:36:45 -04:00
3fe2545228 Merge pull request #367 from cmdr2/beta
Refactor the time delays into constants and mention the units
2022-10-20 17:25:38 +05:30
090dfff730 Refactor the time delays into constants and mention the units 2022-10-20 17:22:01 +05:30
f94e9449d5 Merge pull request #366 from cmdr2/beta
Specify multiple word options in a prompt; UI Plugins system
2022-10-20 16:07:25 +05:30
d8753adc4e Merge branch 'beta' of github.com:cmdr2/stable-diffusion-ui into beta 2022-10-20 16:05:28 +05:30
2e17ea99e2 Don't cache ui plugins in the browser 2022-10-20 16:05:18 +05:30
c4daf8524e Merge pull request #365 from cmdr2/merge
Merge main
2022-10-20 15:58:03 +05:30
9d16898926 Merge branch 'beta' into merge 2022-10-20 15:57:46 +05:30
f4bcc1f2e5 Bug fix - autosave wasn't saving the changes in the textboxes next to guidance scale and prompt strength sliders 2022-10-20 15:26:18 +05:30
63e8614ace Refactor the image button code 2022-10-20 15:10:34 +05:30
5d686b146d Remove the new label from Upscale 2022-10-20 12:14:09 +05:30
e85758dc5f Merge pull request #361 from rbertus2000/beta
fix seed for parallel renders with filters applied
2022-10-20 12:03:00 +05:30
d08f090800 Merge branch 'beta' into mdiller_settings 2022-10-19 21:17:56 -07:00
8554473c21 the rest of the fking owl 2022-10-19 21:12:01 -07:00
01fb1bde8b fix seed for parallel renders with filters applied 2022-10-19 23:16:51 +02:00
29e32ffc42 Mark the new upscale button as new 2022-10-19 22:08:58 +05:30
88bd60a083 Button to draw another 25 steps 2022-10-19 22:08:42 +05:30
48b7b725b0 Add a button to fix faces on generated images 2022-10-19 22:02:59 +05:30
8d8c932d8c Bump version 2022-10-19 21:59:15 +05:30
253d355bd2 New upscale button for images; Fix a bug where the string seed would get appended with numbers 2022-10-19 21:58:51 +05:30
e287df1320 Allow loading UI plugins from a /plugins/ URL path, which loads files ending with .plugin.js inside the plugins/ui folder 2022-10-19 21:34:40 +05:30
bae0bec1cc Change the image buttons plugins to a list instead of a dict 2022-10-19 21:21:19 +05:30
602686a5d2 Move the current implementation of upscale/redo/double size into a custom plugin 2022-10-19 20:27:06 +05:30
af05d94198 Allow plugin buttons for image overlay to decide whether they should be displayed or not 2022-10-19 20:10:45 +05:30
5fa3a7ca44 UI-side plugin system; Use PLUGINS['IMAGE_INFO_BUTTONS'] to add additional buttons on the generated images 2022-10-19 19:50:05 +05:30
9609350789 Rework the API for image buttons 2022-10-19 18:23:34 +05:30
9c1e73ffff Fix missing auto-save.css include 2022-10-19 18:10:22 +05:30
50741c70c0 Add a 'Make Similar Images' button 2022-10-19 17:26:35 +05:30
083f9dd29b Bump version 2022-10-19 13:50:36 +05:30
7d5fabbd25 Merge branch 'beta' of github.com:cmdr2/stable-diffusion-ui into beta 2022-10-19 13:50:17 +05:30
105f071847 Expand curly braces in prompts, for e.g. 'hello {foo,bar}' => 'hello foo' and 'hello bar' 2022-10-19 13:50:05 +05:30
48222ce44c updated to make autosaving on by default and updated some of the new logic 2022-10-18 22:13:45 -07:00
0922ba938c Remove unnecessary tabs 2022-10-19 09:59:18 +05:30
44191cd908 Merge pull request #357 from rbertus2000/beta
fixed img_id for parallel renders
2022-10-19 09:57:05 +05:30
b5f6e9d01b Merge pull request #357 from rbertus2000/beta
fixed img_id for parallel renders
2022-10-19 09:52:58 +05:30
0922349344 made some updates and moved some stuff to auto-save js 2022-10-18 20:49:58 -07:00
d2d9c2dd0f fixed corresponding txt file id 2022-10-19 01:17:44 +02:00
4241fb9386 fixed img_id for parallel renders 2022-10-18 22:38:37 +02:00
946dfdf7b8 Bring back the upscale/double/redo buttons 2022-10-18 22:29:15 +05:30
4da9843479 Move image modifiers JS to a separate file 2022-10-18 22:28:04 +05:30
eccb3c643d Separate the inpainting editor JS into a separate file 2022-10-18 22:09:11 +05:30
bfa5a51ce8 Use a local copy of fontawesome, to allow working offline 2022-10-18 21:40:17 +05:30
9066ad6cdf Use locally hosted fonts, to be able to work offline 2022-10-18 21:06:56 +05:30
f7b513dff2 Refactor the CSS and JS into separate files, attempt 1 2022-10-18 20:18:56 +05:30
3de5f10d52 Merge pull request #356 from cmdr2/beta
Task Manager (support multiple tabs and user agents), Themes, Auto-save settings, Prompt Matrix (one prompt per line), Load Prompts from a file, UI theme tweaks
2022-10-18 19:16:58 +05:30
07429a862c Merge branch 'beta' of github.com:cmdr2/stable-diffusion-ui into beta 2022-10-18 19:02:52 +05:30
2f2bddf020 Allow empty prompts; Allow collapsing a results box for an empty prompt 2022-10-18 19:02:34 +05:30
ad03adaebf Merge pull request #355 from cmdr2/main
Merge main
2022-10-18 18:51:30 +05:30
ac7a5488ee Disable the upscale/redo/double size buttons temporarily, so that the release can proceed to main 2022-10-18 18:50:47 +05:30
6de93d4fbb Reduce the padding around the screen edges 2022-10-18 16:28:18 +05:30
8a312f76c5 Merge pull request #352 from madrang/HTTPException-fix
Replaced 'return HTTPException' by 'raise HTTPException'
2022-10-18 16:23:31 +05:30
4a956b5a55 Make the label 10pt 2022-10-18 16:20:35 +05:30
83d6c3ba88 Fix the broken 'time remaining' counter 2022-10-18 16:12:17 +05:30
52daf6b864 Revert "Use python 3.9"
This reverts commit c8420e152f.
2022-10-18 15:37:02 +05:30
c8420e152f Use python 3.9 2022-10-18 15:34:37 +05:30
1dff19af26 Revert "Use python 3.10"
This reverts commit a1e2eca802.
2022-10-18 15:15:12 +05:30
a1e2eca802 Use python 3.10 2022-10-18 15:11:28 +05:30
48b63a26c8 Don't disable the random field when the output image is used as the new init image 2022-10-18 14:51:23 +05:30
b23bc4a5b6 Don't disable the random field when the output image is used as the new init image 2022-10-18 14:49:39 +05:30
b6ef18b0d8 Merge pull request #354 from madrang/beta
Fixed theme loading with extensions.
2022-10-18 12:52:48 +05:30
372484f976 Fixed theme loading with extensions. 2022-10-18 03:21:59 -04:00
086cf67e93 Remove commented-out script copying line 2022-10-18 12:48:20 +05:30
efffca83fe Merge pull request #353 from mdiller/mdiller_themes
Theme Selection
2022-10-18 12:11:19 +05:30
d2215c2ba9 removed accent hue in a couple places where it didnt need to be specified 2022-10-17 23:36:05 -07:00
89b1b6e242 Replaced 'return HTTPException' by 'raise HTTPException' 2022-10-18 02:30:30 -04:00
e476d68848 fixed a couple things and added some more themes 2022-10-17 23:19:22 -07:00
da8835bc77 updated to behave better and apply variables that are dependant 2022-10-17 23:00:08 -07:00
f170c2611c Merge branch 'beta' into mdiller_themes 2022-10-17 22:23:02 -07:00
351b17d1d9 added a theme dropdown box 2022-10-17 22:22:27 -07:00
14e88706df Set and use a local profile directory for new installations - does not affect existing installations 2022-10-18 09:46:25 +05:30
926e3e2712 Merge pull request #351 from madrang/fix-bug332
Force encoding to utf-8 on text file operations Fixes #332
2022-10-18 09:40:54 +05:30
c39043fb9d Merge pull request #350 from madrang/beta
Fixed file path bugs introduced by mistake and made img_id sequential.
2022-10-18 09:21:46 +05:30
5b0b582039 Force encoding to utf-8 on text file operations Fixes #332 2022-10-17 22:38:29 -04:00
ffe40fa3a3 Fixed file path bugs introduced by mistake and made img_id sequential based on time for better sorting of renders. 2022-10-17 21:27:15 -04:00
03bd9a5731 Temporary fix for lagging progress updates check 2022-10-17 21:53:46 +05:30
cb82170187 Fix the bug where custom models weren't getting picked up 2022-10-17 21:22:05 +05:30
5b9e16af83 Merge branch 'beta' of github.com:cmdr2/stable-diffusion-ui into beta 2022-10-17 18:40:14 +05:30
7b1b2a4bef Enable auto-save of settings by default 2022-10-17 18:40:04 +05:30
1f1a0b7b53 Merge pull request #347 from cmdr2/task_manager
Cosmetic tweaks to loading status
2022-10-17 18:05:29 +05:30
320acfae89 Cosmetic tweaks to loading status 2022-10-17 18:04:46 +05:30
1c171d0f12 Merge pull request #346 from cmdr2/task_manager
Allow multiple tabs and computers to generate tasks without throwing errors (by @madrang)
2022-10-17 17:57:10 +05:30
22bf3618ea Bump version 2022-10-17 17:56:52 +05:30
5f1593f4d0 Style the busy and waiting colors 2022-10-17 17:52:55 +05:30
9af75bf9b2 Don't throw an error if a task was stopped before it started processing 2022-10-17 17:41:27 +05:30
344fa729a5 Don't stop another session's task when the 'Stop All Tasks' button is pressed 2022-10-17 17:36:20 +05:30
33d3d90a93 Merge pull request #329 from madrang/task-queue-rendering
Task queue rendering
2022-10-17 16:59:10 +05:30
24dfc09f35 Merge branch 'beta' into task-queue-rendering 2022-10-17 15:22:54 +05:30
e533bc0847 Merge pull request #330 from madrang/use_cpu_fix
Update use_cpu on Redo and Double Size to move renders to/from cpu and gpu after starting.
2022-10-17 15:22:13 +05:30
306333ceba Merge pull request #345 from cmdr2/main
Update the troubleshooting link to the new wiki page
2022-10-17 15:17:05 +05:30
e96312b470 Update the troubleshooting link to the new wiki page 2022-10-17 15:16:31 +05:30
fb60b4bca7 Merge pull request #344 from cmdr2/main
Update Troubleshooting.md
2022-10-17 15:13:11 +05:30
0612e4429d Update Troubleshooting.md 2022-10-17 15:12:47 +05:30
ee80aa26db Lighter color on hover for input elements 2022-10-17 14:34:48 +05:30
a45e667e9c Fix a bug (after merge) where the image info wouldn't get set 2022-10-17 14:19:16 +05:30
1b4a2369bb Don't save prompts by default 2022-10-17 13:48:06 +05:30
224483f6ac Rearrange the prompts box - move the prompt load button to the top, hide negative prompts behind a collapsible 2022-10-17 13:45:08 +05:30
c61574b782 Fix typo while merging b1dd4069db to beta 2022-10-17 13:04:33 +05:30
6c71d95932 Bump version 2022-10-17 13:01:31 +05:30
e859f5c7a1 Merge pull request #343 from cmdr2/main
Merge main
2022-10-17 12:59:21 +05:30
dc402f5f0e Downloaded images named with their correct prompt and settings 2022-10-17 12:57:45 +05:30
188894c837 Push back the auto-save settings change by @mdiller 2022-10-17 12:44:05 +05:30
70f99a70a5 Merge pull request #342 from cmdr2/revert-335-mdiller_beta
Revert "Auto-saving Settings"
2022-10-17 11:40:12 +05:30
fb4fbd23d8 Revert "Auto-saving Settings" 2022-10-17 11:40:01 +05:30
f58b2383b9 Revert "Fix typo while merging"
This reverts commit 05caf1fe28.
2022-10-17 11:39:51 +05:30
05caf1fe28 Fix typo while merging 2022-10-17 11:36:02 +05:30
704486abc2 Merge pull request #335 from mdiller/mdiller_beta
Auto-saving Settings
2022-10-17 11:35:03 +05:30
1ec023b435 Merge branch 'beta' into mdiller_beta 2022-10-17 11:34:50 +05:30
fd21eeb477 Uncomment the git reset 2022-10-17 11:26:02 +05:30
edf2b2df6f Bump version; Shrink the size of the editor panel and font size 2022-10-17 11:21:35 +05:30
9ce338622c Merge pull request #340 from mdiller/mdiller_styling
Updated/Fixed CSS Styling
2022-10-17 10:50:10 +05:30
2b35529cbd Merge pull request #338 from JeLuF/patch-3
Add: ModuleNotFoundError: No module named 'gfpgan'
2022-10-17 10:36:26 +05:30
2edc06c662 Forgot to update UI if failed to get new server state 2022-10-16 21:32:59 -04:00
cb4d66d6fe removed temporary thing from env start script 2022-10-15 21:15:11 -07:00
f80602b51a tweaked styling of the size hint for the image 2022-10-15 18:39:56 -07:00
58d8a5ce46 added support for theming buttons 2022-10-15 18:34:59 -07:00
72a65218be updated some of the styling and positioning of some stuff 2022-10-15 18:04:41 -07:00
1b0d5b710e fixed styling to work properly for mobile 2022-10-15 17:26:52 -07:00
2a25ac0847 reorganized colors to make them themeable 2022-10-15 16:41:38 -07:00
9aefdf35a1 fixed bug with prompt strength showing up during non-img2img stuff 2022-10-15 15:30:04 -07:00
231961c017 removed newline from end of mainjs file 2022-10-15 15:25:36 -07:00
ee621fa091 pruned out all the auto-settings saving stuff 2022-10-15 15:23:48 -07:00
a69a04cfb6 reorganized and fixed the auto-save settings stuff so its all in its own file 2022-10-15 15:10:42 -07:00
b1aed344c7 moved auto-save settings stuff to new file and removed ui changes from main.js. this not done, just first step 2022-10-15 14:54:34 -07:00
3e08d665c7 removed non-settings related stuff from html 2022-10-15 14:46:18 -07:00
4a94c86433 removed stuff from styling that wasnt settings-related 2022-10-15 14:41:57 -07:00
d4878f6ed3 temporarily removed git reset and checkouts 2022-10-15 14:35:39 -07:00
d94719ea02 Add: ModuleNotFoundError: No module named 'gfpgan'
Common error
2022-10-15 20:11:39 +02:00
982b5221b1 Improved serverState tracking 2022-10-15 05:48:12 -04:00
cbdf03450d Added timeout to critical locking tasks with matching exception 2022-10-15 05:31:17 -04:00
7625e591fe Fixed output_dir not liking the move to JSONResponse 2022-10-15 04:47:12 -04:00
8fdb1e7ec9 Improved locking and logging when cleaning old cached sessions. 2022-10-15 04:39:45 -04:00
d3b28c42e6 Better error handling with cache.put 2022-10-15 04:08:17 -04:00
1b32423881 Renamed a missing ServerStates to task_manager.ServerStates 2022-10-15 03:32:00 -04:00
7de699c7fa Moved a lot of code into task_manager.py 2022-10-15 03:28:20 -04:00
e9f9670eb5 Changed '/get' from a query to a path parameter 2022-10-15 01:32:53 -04:00
3d4e961320 time.time() is in seconds not ms. 2022-10-15 00:51:06 -04:00
db2fb33d53 Merge pull request #336 from ZacTheHac/main
Downloaded images named with their correct prompt and settings
2022-10-15 10:14:38 +05:30
ff3db04ab7 temp_images needs twice the size if show_only_filtered_image is false 2022-10-14 23:21:44 -04:00
c7f6763c48 Runtime cleanup and moved apply_filters to it's own function 2022-10-14 23:20:57 -04:00
b1dd4069db Downloaded images named with their correct prompt and settings 2022-10-14 19:46:31 -07:00
58c647d433 updated to fix the formatting to make for a cleaner diff in the pull request 2022-10-14 17:30:54 -07:00
333ea4aa53 added a bunch of changes including cleaning up styling and inputs and adding auto-saving settings. see PR for more info. 2022-10-14 17:30:54 -07:00
3ad59da2a9 Move negative prompt box next to the main prompt box 2022-10-14 23:01:23 +05:30
2d9b211eeb Reduce the size of the prompt header in the task list 2022-10-14 22:58:36 +05:30
4f5a352985 Update use_cpu using UI on Redo and Double Size 2022-10-14 12:08:22 -04:00
6ae3b77c2f LoadingModel detection 2022-10-14 06:03:18 -04:00
4a7260b1be StopAsyncIteration should not trigger HTTP500.
Now returns faster into the ready state.
2022-10-14 05:20:44 -04:00
f91c77bdc6 Failed task go immediately into the buffer state with the error. 2022-10-14 04:47:13 -04:00
476e938d23 Forgot a color change for batched tasks. taskStatusLabel could have class activeTaskLabel replace by waitingTaskLabel again. 2022-10-14 04:18:34 -04:00
1ec9d986bb Render queue first draft 2022-10-14 03:47:25 -04:00
4b88cfa51a More simple time check 2022-10-14 03:43:33 -04:00
bc56226a28 Grouped many endpoints into one 2022-10-14 03:42:43 -04:00
a6e5474fdb CSS waitingTaskLabel for task waiting to start 2022-10-14 00:56:04 -04:00
8c7ca2c34d Executable permission 2022-10-13 10:40:24 +05:30
91fccc6691 Executable permission 2022-10-13 10:39:34 +05:30
93d1737357 Merge pull request #322 from madrang/prompt-fix
Remove trailing coma in promptMatrix when activeTags is empty
2022-10-13 10:36:27 +05:30
5ba1ae9ae4 Remove trailing coma in promptMatrix when activeTags is empty 2022-10-13 00:45:29 -04:00
8cb408bc6e Merge pull request #312 from madrang/guided-upscale
Added Upscale Button
2022-10-12 15:17:40 +05:30
197a89a37a Only comments changes to better describe buffering cases. 2022-10-12 03:08:25 -04:00
d336ead3b1 Updated old comments of doMakeImage to better reflect the updated reading process. 2022-10-12 02:57:09 -04:00
662644663e Improved redo when used with in-pictures editor 2022-10-12 02:32:00 -04:00
4c7819effb Corrected an issue when resuming background page on mobile and added comments to stream reader. 2022-10-12 00:33:00 -04:00
8b5b9ee8f1 Fix error on stopping tasks. 2022-10-11 23:15:06 -04:00
89b911a9dc Original code was missing a check on 'success' to abort failed tasks. 2022-10-11 22:04:41 -04:00
b673e216b6 In a batched task, keep all error messages.
If there are other batches in the task sent,
it should not remove previous errors.
2022-10-11 21:53:08 -04:00
a1b2f0ccf1 Reordered error checks to first check task status,
If none use connection status and the last step is now the generic message.
2022-10-11 20:10:40 -04:00
f269facf9d Stop hiding exceptions after read is complete. 2022-10-11 20:08:44 -04:00
5a36d280d7 Improve error display to always have some debug informations present. 2022-10-11 18:40:05 -04:00
c39563b123 Track read complete to read buffer until the end. 2022-10-11 18:38:23 -04:00
548149de8e Removed a nested try/catch that wasn't displaying all the informations.
Kept the outside try/catch that had better logging.
2022-10-11 16:42:27 -04:00
d6d4ce0ac4 Moved done check after data read in 'doMakeImage'. 2022-10-11 16:19:34 -04:00
83b0239791 Fixed an old hidden parsing crash that was there but hidden by the old try/catch block. 2022-10-11 15:32:06 -04:00
d1fa13d67a e.message wont start with 'JSON.parse' on mobile.
Removed message check but made the try/catch more narrow to not hide other errors.
2022-10-11 13:52:18 -04:00
3abd570678 Enable strict mode to throw errors on any undeclared variables. 2022-10-10 22:31:47 -04:00
b0b0781bd7 Use requestIdleCallback if available 2022-10-10 22:30:17 -04:00
1aa28ddee1 Improved Redo and DoubleSize 2022-10-10 22:29:15 -04:00
09b50badb1 Fix removing old tasks stopping the current render. 2022-10-10 22:28:34 -04:00
7060108a8b Don't hide errors if they are unexpected. 2022-10-10 22:27:49 -04:00
e6f0d5bf44 Fixed a few undeclared variables I found. 2022-10-10 22:27:15 -04:00
399642f958 Fix the broken linux developer console script 2022-10-10 19:37:05 +05:30
781effc34e Splitted ImgX2 into Redo and Double Size. 2022-10-10 04:06:15 -04:00
324c8f8146 Fixed showImages to clone batched reqBody and not reuse same objects. 2022-10-10 02:32:27 -04:00
27e372e38f Clone the complete task object instead of only reqBody.
Avoids altering already completed tasks for reruns.
2022-10-10 02:31:02 -04:00
87122ce211 Each output render need it own instance of reqBody to avoid altering the other runs after they are completed. 2022-10-09 21:18:27 -04:00
c0c6675423 Removed dead code 2022-10-09 21:16:42 -04:00
fa4aeb5261 Only replace existing seeds when needed. 2022-10-09 21:16:24 -04:00
4e51eeb998 Bug fixes for createTask, use task object, not UI infos. 2022-10-09 19:59:34 -04:00
a27c3f09b3 Renamed getStartUpscaleHandler to getStartNewTaskHandler and added new tasks types. 2022-10-09 19:58:16 -04:00
3e5f117066 Cleaned up button creation for new tasks 2022-10-09 19:56:51 -04:00
3753fb3ea4 Added upscale button with matching 'getStartUpscaleHandler' function. 2022-10-09 07:19:00 -04:00
d3e49cf1e9 Cleanup of 'createTask' 2022-10-09 07:17:43 -04:00
ffcf46a371 Set the custom temp variable only while installing 2022-10-09 10:02:59 +05:30
fc5eedbef5 Update on_sd_start.bat 2022-10-09 09:56:44 +05:30
d78b6c4445 Revert "Revert "Revert "Disable the uvicorn check, seems to be failing incorrectly for some reason"""
This reverts commit 6e056bb337.
2022-10-08 22:45:43 +05:30
6e056bb337 Revert "Revert "Disable the uvicorn check, seems to be failing incorrectly for some reason""
This reverts commit b5c2c1009c.
2022-10-08 22:43:37 +05:30
b5c2c1009c Revert "Disable the uvicorn check, seems to be failing incorrectly for some reason"
This reverts commit e30aca7531.
2022-10-08 22:37:44 +05:30
b54029a04a Merge branch 'main' of github.com:cmdr2/stable-diffusion-ui 2022-10-08 22:26:23 +05:30
e30aca7531 Disable the uvicorn check, seems to be failing incorrectly for some reason 2022-10-08 22:26:14 +05:30
866722b68f Update README.md 2022-10-08 19:53:45 +05:30
d93f3468d3 Merge pull request #303 from madrang/resize-inpainting-disable
Resize in-painting disable
2022-10-08 19:48:43 +05:30
83032e858a Merge branch 'beta' of github.com:cmdr2/stable-diffusion-ui into beta 2022-10-08 18:22:13 +05:30
6855e314b3 Store the output format setting in localStorage 2022-10-08 18:22:01 +05:30
2c4a8619a8 Only 'resizeInpaintingEditor' if 'aspectRatio' has changed. 2022-10-08 08:42:25 -04:00
3247d83252 Refactored the readme, to make it more readable and highlight the features better 2022-10-08 18:08:06 +05:30
109ff2d8a5 Task queue screenshot 2022-10-08 18:00:23 +05:30
48797d12eb Simple screenshot 2022-10-08 17:56:50 +05:30
abe66d8af0 Updated settings screenshot 2022-10-08 17:49:14 +05:30
58c9b70b26 Merge branch 'main' of github.com:cmdr2/stable-diffusion-ui 2022-10-08 17:38:09 +05:30
996643bde8 Update main screenshot 2022-10-08 17:37:59 +05:30
68dd9a29e8 Run 'resizeInpaintingEditor' once when 'maskSetting' is changed. 2022-10-08 07:56:01 -04:00
68c4b55945 Disable 'resizeInpaintingEditor' when 'maskSetting' is unchecked. 2022-10-08 07:55:24 -04:00
bab86c9ce2 Merge pull request #302 from cmdr2/canvas-resize
Follow the output aspect ratio in the inpainting editor
2022-10-08 16:55:36 +05:30
5f24e4d705 Increased the inpainting editor size; Fix a bug with the brush size not resetting 2022-10-08 16:53:47 +05:30
66c7b3fcb2 Don't use setAttribute to overwrite the style 2022-10-08 16:47:15 +05:30
1ffe29c657 Merge pull request #301 from madrang/resizeCanvas
Resize canvas following selected aspect ratio
2022-10-08 16:37:11 +05:30
6b7d4877e6 Initial implementation of prompt matrix - creates multiple task entries for the different permutations 2022-10-08 15:56:56 +05:30
80826eb500 Add min-width to .drawing-board-controls to keep the in-painting controls on one line. 2022-10-08 05:54:53 -04:00
11962facde resize 'inpaintingEditor' on change from 'widthField' and 'heightField' 2022-10-08 05:53:44 -04:00
c7eccfd804 Update Troubleshooting.md 2022-10-08 14:02:57 +05:30
ad617e0deb Merge pull request #300 from cmdr2/beta
Don't delete the model variables twice
2022-10-08 13:59:06 +05:30
7ae70d5a4d Don't delete the model variables twice 2022-10-08 13:58:44 +05:30
62d1a0291e Merge pull request #299 from cmdr2/beta
Unload the previous model while reloading
2022-10-08 13:19:58 +05:30
883dc72fc6 Unload the previous model while reloading 2022-10-08 13:19:18 +05:30
65b2e9633c Merge pull request #298 from cmdr2/beta
Didn't fix the ckpt bug properly
2022-10-08 12:49:09 +05:30
3b923e0d37 Didn't fix the ckpt bug properly 2022-10-08 12:48:37 +05:30
4938cb9bbc Merge pull request #297 from cmdr2/beta
Load prompts from a file; Bugfix - model load failure would incorrectly set the global state
2022-10-08 12:37:15 +05:30
a208564f06 Wait for the model to load before changing the global 'model loaded' state 2022-10-08 12:35:23 +05:30
6c6ca4daf4 Merge branch 'main' of github.com:cmdr2/stable-diffusion-ui 2022-10-08 12:06:22 +05:30
1024da601d Set a custom temp path to workaround the pip bug 2022-10-08 12:06:11 +05:30
55d05ee590 Use euler_a and num_inference_steps 25 as the default 2022-10-07 23:54:42 +05:30
66f39e070b Read prompts from a text file; Allow specifying multiple prompts in the textbox by separating them by new lines 2022-10-07 23:46:56 +05:30
252681001e Update README.md 2022-10-07 20:09:04 +05:30
a39014b3b1 Update README.md 2022-10-07 20:08:48 +05:30
bccf7e3f69 Merge pull request #293 from cmdr2/main
Merge from main
2022-10-07 19:58:49 +05:30
62 changed files with 4143 additions and 2065 deletions

View File

@ -13,12 +13,11 @@ If you would like to contribute to this project, there is a discord for dicussio
This is in-flux, but one way to get a development environment running for editing the UI of this project is:
(swap `.sh` or `.bat` in instructions depending on your environment, and be sure to adjust any paths to match where you're working)
1) `git clone` the repository, e.g. to `/projects/stable-diffusion-ui-repo`
2) Download the pre-built end user archive from the link on github, and extract it, e.g. to `/projects/stable-diffusion-ui-archive`
3) `cd /projects/stable-diffusion-ui-archive` and run the script to set up and start the project, e.g. `start.sh`
4) Check you can view and generate images on `localhost:9000`
5) Close the server, and edit `/projects/stable-diffusion-ui-archive/scripts/on_env_start.sh`
6) Comment out the lines near the bottom that copies the `files/ui` folder, e.g:
1) Install the project to a new location using the [usual installation process](https://github.com/cmdr2/stable-diffusion-ui#installation), e.g. to `/projects/stable-diffusion-ui-archive`
2) Start the newly installed project, and check that you can view and generate images on `localhost:9000`
3) Next, please clone the project repository using `git clone` (e.g. to `/projects/stable-diffusion-ui-repo`)
4) Close the server (started in step 2), and edit `/projects/stable-diffusion-ui-archive/scripts/on_env_start.sh` (or `on_env_start.bat`)
5) Comment out the lines near the bottom that copies the `files/ui` folder, e.g:
for `.sh`
```
@ -33,13 +32,13 @@ REM @xcopy sd-ui-files\ui ui /s /i /Y
REM @copy sd-ui-files\scripts\on_sd_start.bat scripts\ /Y
REM @copy "sd-ui-files\scripts\Start Stable Diffusion UI.cmd" . /Y
```
7) Comment out the line at the top of `/projects/stable-diffusion-ui-archive/scripts/on_sd_start.sh` that copies `on_env_start`. For e.g. `@copy sd-ui-files\scripts\on_env_start.bat scripts\ /Y`
6) Next, comment out the line at the top of `/projects/stable-diffusion-ui-archive/scripts/on_sd_start.sh` (or `on_sd_start.bat`) that copies `on_env_start`. For e.g. `@rem @copy sd-ui-files\scripts\on_env_start.bat scripts\ /Y`
8) Delete the current `ui` folder at `/projects/stable-diffusion-ui-archive/ui`
9) Now make a symlink between the repository clone (where you will be making changes) and this archive (where you will be running stable diffusion):
`ln -s /projects/stable-diffusion-ui-repo/ui /projects/stable-diffusion-ui-archive/ui`
or for Windows
`mklink /D \projects\stable-diffusion-ui-archive\ui \projects\stable-diffusion-ui-repo\ui` (link name first, source repo dir second)
9) Run the archive again `start.sh` and ensure you can still use the UI.
`mklink /J \projects\stable-diffusion-ui-archive\ui \projects\stable-diffusion-ui-repo\ui` (link name first, source repo dir second)
9) Run the project again (like in step 2) and ensure you can still use the UI.
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.
Check the `ui/frontend/build/README.md` for instructions on running and building the React code.
@ -47,9 +46,5 @@ Check the `ui/frontend/build/README.md` for instructions on running and building
## 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.
1. Install Miniconda 3 or Anaconda.
2. Install `conda install -c conda-forge -y conda-pack`
3. Open the Anaconda Prompt. Do not use WSL if you're building for Windows.
4. Run `build.bat` or `./build.sh` depending on whether you're in Windows or Linux.
5. Compress the `stable-diffusion-ui` folder created inside the `dist` folder. Make a `zip` for Windows, and `tar.xz` for Linux (smaller files, and Linux users already have tar).
6. Make a new GitHub release and upload the Windows and Linux installer builds.
1. Run `build.bat` or `./build.sh` depending on whether you're in Windows or Linux.
2. Make a new GitHub release and upload the Windows and Linux installer builds created inside the `dist` folder.

114
README.md
View File

@ -1,49 +1,77 @@
# Stable Diffusion UI v2
### A simple 1-click way to install and use [Stable Diffusion](https://github.com/CompVis/stable-diffusion) on your own computer. No dependencies or technical knowledge required.
# Stable Diffusion UI
### Easiest way to install and use [Stable Diffusion](https://github.com/CompVis/stable-diffusion) on your own computer. No dependencies or technical knowledge required. 1-click install, powerful features.
[![Discord Server](https://img.shields.io/discord/1014774730907209781?label=Discord)](https://discord.com/invite/u9yhsFmEkB) (for support, and development discussion) | [Troubleshooting guide for common problems](Troubleshooting.md)
----
## Step 1: Download the installer
<p float="left">
<a href="#installation"><img src="https://github.com/cmdr2/stable-diffusion-ui/raw/develop/media/download-win.png" width="200" /></a>
<a href="#installation"><img src="https://github.com/cmdr2/stable-diffusion-ui/raw/develop/media/download-linux.png" width="200" /></a>
</p>
[![Discord Server](https://img.shields.io/discord/1014774730907209781?label=Discord)](https://discord.com/invite/u9yhsFmEkB) (for support, and development discussion) | [Troubleshooting guide for common problems](Troubleshooting.md)
## Step 2: Run the program
- On Windows: Double-click `Start Stable Diffusion UI.cmd`
- On Linux: Run `./start.sh` in a terminal
️‍🔥🎉 **New!** Use Custom Weights, Task Queue, Negative Prompt, Live Preview, More Samplers, In-Painting, Face Correction (GFPGAN) and Upscaling (RealESRGAN) have been added!
## Step 3: There is no step 3!
It's simple to get started. You don't need to install or struggle with Python, Anaconda, Docker etc.
This distribution currently uses Stable Diffusion 1.4. Once the model for 1.5 becomes publicly available, the model in this distribution will be updated.
The installer will take care of whatever is needed. A friendly [Discord community](https://discord.com/invite/u9yhsFmEkB) will help you if you face any problems.
# Features in the new v2 Version:
----
# Easy for new users, powerful features for advanced users
### Features:
- **No Dependencies or Technical Knowledge Required**: 1-click install for Windows 10/11 and Linux. *No dependencies*, no need for WSL or Docker or Conda or technical setup. Just download and run!
- **Face Correction (GFPGAN) and Upscaling (RealESRGAN)**
- **In-Painting**
- **Clutter-free UI**: a friendly and simple UI, while providing a lot of powerful features
- Supports "*Text to Image*" and "*Image to Image*"
- **Custom Models**: Use your own `.ckpt` file, by placing it inside the `models/stable-diffusion` folder!
- **Live Preview**: See the image as the AI is drawing it
- **Task Queue**: Queue up all your ideas, without waiting for the current task to finish
- **Custom Weights**: Use your own `.ckpt` file, by placing it inside the `stable-diffusion` folder (rename it to `custom-model.ckpt`)
- **Negative Prompt**: Specify aspects of the image to *remove*.
- **Lots of Samplers:** ddim, plms, heun, euler, euler_a, dpm2, dpm2_a, lms
- **In-Painting**: Specify areas of your image to paint into
- **Face Correction (GFPGAN) and Upscaling (RealESRGAN)**
- **Image Modifiers**: A library of *modifier tags* like *"Realistic"*, *"Pencil Sketch"*, *"ArtStation"* etc. Experiment with various styles quickly.
- **New UI**: with cleaner design
- **Waifu Model Support**: Just replace the `stable-diffusion\sd-v1-4.ckpt` file after installation with the Waifu model
- Supports "*Text to Image*" and "*Image to Image*"
- **Loopback**: Use the output image as the input image for the next img2img task
- **Negative Prompt**: Specify aspects of the image to *remove*.
- **Attention/Emphasis:** () in the prompt increases the model's attention to enclosed words, and [] decreases it
- **Weighted Prompts:** Use weights for specific words in your prompt to change their importance, e.g. `red:2.4 dragon:1.2`
- **Prompt Matrix:** (in beta) Quickly create multiple variations of your prompt, e.g. `a photograph of an astronaut riding a horse | illustration | cinematic lighting`
- **Lots of Samplers:** ddim, plms, heun, euler, euler_a, dpm2, dpm2_a, lms
- **Multiple Prompts File:** Queue multiple prompts by entering one prompt per line, or by running a text file
- **NSFW Setting**: A setting in the UI to control *NSFW content*
- **JPEG/PNG output**
- **Save generated images to disk**
- **Use CPU setting**: If you don't have a compatible graphics card, but still want to run it on your CPU.
- **Auto-updater**: Gets you the latest improvements and bug-fixes to a rapidly evolving project.
- **Low Memory Usage**: Creates 512x512 images with less than 4GB of VRAM!
- **Developer Console**: A developer-mode for those who want to modify their Stable Diffusion code, and edit the conda environment.
![Screenshot of advanced settings](media/shot-v9.jpg?raw=true)
### Easy for new users:
![Screenshot of the initial UI](media/shot-v10-simple.jpg?raw=true)
### Powerful features for advanced users:
![Screenshot of advanced settings](media/shot-v10.jpg?raw=true)
### Live Preview
Useful for judging (and stopping) an image quickly, without waiting for it to finish rendering.
## Live Preview
![live-512](https://user-images.githubusercontent.com/844287/192097249-729a0a1e-a677-485e-9ccc-16a9e848fabe.gif)
### Task Queue
![Screenshot of task queue](media/task-queue-v1.jpg?raw=true)
# System Requirements
1. Windows 10/11, or Linux. Experimental support for Mac is coming soon.
2. An NVIDIA graphics card, preferably with 4GB or more of VRAM. But if you don't have a compatible graphics card, you can still use it with a "Use CPU" setting. It'll be very slow, but it should still work.
2. An NVIDIA graphics card, preferably with 4GB or more of VRAM. If you don't have a compatible graphics card, it'll automatically run in the slower "CPU Mode".
3. Minimum 8 GB of RAM and 25GB of disk space.
You do not need anything else. You do not need WSL, Docker or Conda. The installer will take care of it.
You don't need to install or struggle with Python, Anaconda, Docker etc. The installer will take care of whatever is needed.
# Installation
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).
1. **Download** [for Windows](https://github.com/cmdr2/stable-diffusion-ui/releases/download/v2.3.5/stable-diffusion-ui-windows.zip) or [for Linux](https://github.com/cmdr2/stable-diffusion-ui/releases/download/v2.3.5/stable-diffusion-ui-linux.zip).
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).
@ -57,49 +85,19 @@ This will automatically install Stable Diffusion, set it up, and start the inter
**To Uninstall:** Just delete the `stable-diffusion-ui` folder to uninstall all the downloaded packages.
# Usage
Open http://localhost:9000 in your browser (after running step 3 previously). It may take a few moments for the back-end to be ready.
## With a text description
1. Enter a text prompt, like `a photograph of an astronaut riding a horse` in the textbox.
2. Press `Make Image`. This will take some time, depending on your system's processing power.
3. See the image generated using your prompt.
## With an image
1. Click `Browse..` next to `Initial Image`. Select your desired image.
2. An optional text prompt can help you further describe the kind of image you want to generate.
3. Press `Make Image`. See the image generated using your prompt.
You can use Face Correction or Upscaling to improve the image further.
**Pro tip:** You can also click `Use as Input` on a generated image, to use it as the input image for your next generation. This can be useful for sequentially refining the generated image with a single click.
**Another tip:** Images with the same aspect ratio of your generated image work best. E.g. 1:1 if you're generating images sized 512x512.
## 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).
# 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 '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.
![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)
# Image Modifiers
![Screenshot of advanced settings](media/modifiers-v1.jpg?raw=true)
# How to use?
Please use our [guide](https://github.com/cmdr2/stable-diffusion-ui/wiki/How-to-Use) to understand how to use the features in this UI.
# Bugs reports and code contributions welcome
If there are any problems or suggestions, please feel free to ask on the [discord server](https://discord.com/invite/u9yhsFmEkB) or [file an issue](https://github.com/cmdr2/stable-diffusion-ui/issues).
Also, please feel free to submit a pull request, if you have any code contributions in mind. Join the [discord server](https://discord.com/invite/u9yhsFmEkB) for development-related discussions, and for helping other users.
We could really use help on these aspects (click to view tasks that need your help):
* [User Interface](https://github.com/users/cmdr2/projects/1/views/1)
* [Engine](https://github.com/users/cmdr2/projects/3/views/1)
* [Installer](https://github.com/users/cmdr2/projects/4/views/1)
* [Documentation](https://github.com/users/cmdr2/projects/5/views/1)
If you have any code contributions in mind, please feel free to say Hi to us on the [discord server](https://discord.com/invite/u9yhsFmEkB). We use the Discord server for development-related discussions, and for helping users.
# Disclaimer
The authors of this project are not responsible for any content generated using this interface.

View File

@ -1,75 +1 @@
Common issues and their solutions. If these solutions don't work, please feel free to ask at the [discord server](https://discord.com/invite/u9yhsFmEkB) or [file an issue](https://github.com/cmdr2/stable-diffusion-ui/issues).
## RuntimeError: CUDA out of memory
This can happen if your PC has less than 6GB of VRAM.
Try disabling the "Turbo mode" setting under "Advanced Settings", since that takes an additional 1 GB of VRAM (to increase the speed).
Additionally, a common reason for this error is that you're using an initial image larger than 768x768 pixels. Try using a smaller initial image.
Also try generating smaller sized images.
## basicsr module not found
For Windows: Please download and extract basicsr from [here](https://github.com/cmdr2/stable-diffusion-ui/releases/download/v2.16/basicsr-win64.zip), and place the `basicsr` folder inside the `stable-diffusion-ui\stable-diffusion\env\lib\site-packages` folder. Then run the `Start Stable Diffusion UI.cmd` file again.
For Linux: Please contact on the [discord server](https://discord.com/invite/u9yhsFmEkB).
## No ldm found, or antlr4 or any other missing module, or ClobberError: This transaction has incompatible packages due to a shared path
On Windows, please ensure that you had placed the `stable-diffusion-ui` folder after unzipping to the root of C: or D: (or any drive). For e.g. `C:\stable-diffusion-ui`. **Note:** This has to be done **before** you start the installation process. If you have already installed (and are facing this error), please delete the installed folder, and start fresh by unzipping and placing the folder at the top of your drive.
This error can also be caused if you already have conda/miniconda/anaconda installed, due to package conflicts. Please open your Anaconda Prompt, and run `conda clean --all` to clean up unused packages.
If nothing works, this could be due to a corrupted installation. Please try reinstalling this, by deleting the installed folder, and unzipping from the downloaded zip file.
## Killed uvicorn server:app --app-dir ... --port 9000 --host 0.0.0.0
This happens if your PC ran out of RAM. Stable Diffusion requires a lot of RAM, and requires atleast 10 GB of RAM to work well. You can also try closing all other applications before running Stable Diffusion UI.
## Green image generated
This usually happens if you're running NVIDIA 1650 or 1660 Super. To solve this, please close and run the Stable Diffusion command on your computer. If you're using the older Docker-based solution (v1), please upgrade to v2: https://github.com/cmdr2/stable-diffusion-ui/tree/v2#installation
If you're still seeing this error, please try enabling "Full Precision" under "Advanced Settings" in the Stable Diffusion UI.
## './docker-compose.yml' is invalid:
> ERROR: The Compose file './docker-compose.yml' is invalid because:
> services.stability-ai.deploy.resources.reservations value Additional properties are not allowed ('devices' was unexpected)
Please ensure you have `docker-compose` version 1.29 or higher. Check `docker-compose --version`, and if required [update it to 1.29](https://docs.docker.com/compose/install/). (Thanks [HVRyan](https://github.com/HVRyan))
## RuntimeError: Found no NVIDIA driver on your system:
If you have an NVIDIA GPU and the latest [NVIDIA driver](http://www.nvidia.com/Download/index.aspx), please ensure that you've installed [nvidia-container-toolkit](https://stackoverflow.com/a/58432877). (Thanks [u/exintrovert420](https://www.reddit.com/user/exintrovert420/))
## Some other process is already running at port 9000 / port 9000 could not be bound
You can override the port used. Please change `docker-compose.yml` inside the project directory, and update the line `9000:9000` to `1337:9000` (where 1337 is whichever port number you want).
After doing this, please restart your server, by running `./server restart`.
After this, you can access the server at `http://localhost:1337` (where 1337 is the new port you specified earlier).
## RuntimeError: CUDA error: unknown error
Please ensure that you have an NVIDIA GPU and the latest [NVIDIA driver](http://www.nvidia.com/Download/index.aspx), and that you've installed [nvidia-container-toolkit](https://stackoverflow.com/a/58432877).
Also, if you are using WSL (Windows), please ensure you have the latest WSL kernel by running `wsl --shutdown` and then `wsl --update`. (Thanks [AndrWeisR](https://github.com/AndrWeisR))
# For support queries
## Entering a conda environment in an existing installation
This will give you an activated conda environment in the terminal, so you can run commands and force-install any packages, if required.
Users don't need to have the Anaconda Prompt installed to do this anymore, since the installer bundles a portable version of conda inside it. Just follow these steps.
**Windows:**
1. Open the terminal: Press Win+R, type "cmd", and press "Run"
2. Type `cd C:\stable-diffusion-ui` and press enter (or wherever you've installed it)
3. Type `installer\Scripts\activate.bat` and press enter
4. Type `cd stable-diffusion` and press enter
5. Type `conda activate .\env` and press enter
6. Type `python --version` and press enter. You should see 3.8.5.
**Linux:**
1. Open the terminal
2. Type `cd /path/to/stable-diffusion-ui` and press enter
3. Type `installer/bin/activate` and press enter
4. Type `cd stable-diffusion` and press enter
5. Type `conda activate ./env` and press enter
6. Type `python --version` and press enter. You should see 3.8.5.
This will give you an activated conda environment. To confirm, type `python --version` and press enter. You should see 3.8.5.
Moved to https://github.com/cmdr2/stable-diffusion-ui/wiki/Troubleshooting

View File

@ -8,40 +8,40 @@
set /p answer=Are you a developer of this project (Y/N)?
if /i "%answer:~,1%" NEQ "Y" exit /b
@set PYTHONNOUSERSITE=1
mkdir dist\win\stable-diffusion-ui\scripts
@REM mkdir dist\linux-mac\stable-diffusion-ui\scripts
@mkdir dist\stable-diffusion-ui
@rem copy the installer files for Windows
@echo "Downloading components for the installer.."
copy scripts\on_env_start.bat dist\win\stable-diffusion-ui\scripts\
copy scripts\bootstrap.bat dist\win\stable-diffusion-ui\scripts\
copy "scripts\Start Stable Diffusion UI.cmd" dist\win\stable-diffusion-ui\
copy LICENSE dist\win\stable-diffusion-ui\
copy "CreativeML Open RAIL-M License" dist\win\stable-diffusion-ui\
copy "How to install and run.txt" dist\win\stable-diffusion-ui\
echo. > dist\win\stable-diffusion-ui\scripts\install_status.txt
@call conda env create --prefix installer -f environment.yaml
@call conda activate .\installer
@rem copy the installer files for Linux and Mac
@echo "Creating a distributable package.."
@REM copy scripts\on_env_start.sh dist\linux-mac\stable-diffusion-ui\scripts\
@REM copy scripts\bootstrap.sh dist\linux-mac\stable-diffusion-ui\scripts\
@REM copy scripts\start.sh dist\linux-mac\stable-diffusion-ui\
@REM copy LICENSE dist\linux-mac\stable-diffusion-ui\
@REM copy "CreativeML Open RAIL-M License" dist\linux-mac\stable-diffusion-ui\
@REM copy "How to install and run.txt" dist\linux-mac\stable-diffusion-ui\
@REM echo. > dist\linux-mac\stable-diffusion-ui\scripts\install_status.txt
@call conda install -c conda-forge -y conda-pack
@call conda pack --n-threads -1 --prefix installer --format tar
@rem make the zip
@cd dist\stable-diffusion-ui
@mkdir installer
cd dist\win
call powershell Compress-Archive -Path stable-diffusion-ui -DestinationPath ..\stable-diffusion-ui-windows.zip
cd ..\..
@call tar -xf ..\..\installer.tar -C installer
@REM cd dist\linux-mac
@REM call powershell Compress-Archive -Path stable-diffusion-ui -DestinationPath ..\stable-diffusion-ui-linux.zip
@REM call powershell Compress-Archive -Path stable-diffusion-ui -DestinationPath ..\stable-diffusion-ui-mac.zip
@REM cd ..\..
@mkdir scripts
echo "Build ready. Upload the zip files inside the 'dist' folder."
@copy ..\..\scripts\on_env_start.bat scripts\
@copy "..\..\scripts\Start Stable Diffusion UI.cmd" .
@copy ..\..\LICENSE .
@copy "..\..\CreativeML Open RAIL-M License" .
@copy "..\..\How to install and run.txt" .
@echo. > scripts\install_status.txt
@echo "Build ready. Zip the 'dist\stable-diffusion-ui' folder."
@echo "Cleaning up.."
@cd ..\..
@rmdir /s /q installer
@del installer.tar
pause

View File

@ -11,45 +11,39 @@ case $yn in
* ) exit;;
esac
export PYTHONNOUSERSITE=1
# mkdir -p dist/win/stable-diffusion-ui/scripts
mkdir -p dist/linux-mac/stable-diffusion-ui/scripts
mkdir -p dist/stable-diffusion-ui
# copy the installer files for Windows
echo "Downloading components for the installer.."
# cp scripts/on_env_start.bat dist/win/stable-diffusion-ui/scripts/
# cp scripts/bootstrap.bat dist/win/stable-diffusion-ui/scripts/
# cp "scripts/Start Stable Diffusion UI.cmd" dist/win/stable-diffusion-ui/
# cp LICENSE dist/win/stable-diffusion-ui/
# cp "CreativeML Open RAIL-M License" dist/win/stable-diffusion-ui/
# cp "How to install and run.txt" dist/win/stable-diffusion-ui/
# echo "" > dist/win/stable-diffusion-ui/scripts/install_status.txt
source ~/miniconda3/etc/profile.d/conda.sh
# copy the installer files for Linux and Mac
conda install -c conda-forge -y conda-pack
cp scripts/on_env_start.sh dist/linux-mac/stable-diffusion-ui/scripts/
cp scripts/bootstrap.sh dist/linux-mac/stable-diffusion-ui/scripts/
cp scripts/functions.sh dist/linux-mac/stable-diffusion-ui/scripts/
cp scripts/start.sh dist/linux-mac/stable-diffusion-ui/
cp LICENSE dist/linux-mac/stable-diffusion-ui/
cp "CreativeML Open RAIL-M License" dist/linux-mac/stable-diffusion-ui/
cp "How to install and run.txt" dist/linux-mac/stable-diffusion-ui/
echo "" > dist/linux-mac/stable-diffusion-ui/scripts/install_status.txt
conda env create --prefix installer -f environment.yaml
conda activate ./installer
# make the zip
echo "Creating a distributable package.."
conda pack --n-threads -1 --prefix installer --format tar
cd dist/stable-diffusion-ui
mkdir installer
tar -xf ../../installer.tar -C installer
mkdir scripts
cp ../../scripts/on_env_start.sh scripts/
cp ../../scripts/start.sh .
cp ../../LICENSE .
cp "../../CreativeML Open RAIL-M License" .
cp "../../How to install and run.txt" .
echo "" > scripts/install_status.txt
chmod u+x start.sh
echo "Build ready. Zip the 'dist/stable-diffusion-ui' folder."
echo "Cleaning up.."
# cd dist/win
# zip -r ../stable-diffusion-ui-windows.zip stable-diffusion-ui
# cd ../..
cd dist/linux-mac
zip -r ../stable-diffusion-ui-linux.zip stable-diffusion-ui
zip -r ../stable-diffusion-ui-mac.zip stable-diffusion-ui
cd ../..
rm -rf installer
rm installer.tar
echo "Build ready. Upload the zip files inside the 'dist' folder."

BIN
media/config-v7.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

BIN
media/shot-v10-simple.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

BIN
media/shot-v10.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

BIN
media/task-queue-v1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

View File

@ -2,13 +2,33 @@
echo "Opening Stable Diffusion UI - Developer Console.." & echo.
@call installer\Scripts\activate.bat
set PATH=C:\Windows\System32;%PATH%
@call conda-unpack
@rem set legacy and new installer's PATH, if they exist
if exist "installer" set PATH=%cd%\installer;%cd%\installer\Library\bin;%cd%\installer\Scripts;%cd%\installer\Library\usr\bin;%PATH%
if exist "installer_files\env" set PATH=%cd%\installer_files\env;%cd%\installer_files\env\Library\bin;%cd%\installer_files\env\Scripts;%cd%\installer_files\Library\usr\bin;%PATH%
@call conda --version
@call git --version
set PYTHONPATH=%cd%\installer;%cd%\installer_files\env
@call conda activate .\stable-diffusion\env
@rem activate the installer env
call conda activate
cmd /k
@rem Test the environment
echo "Environment Info:"
call where git
call git --version
call where conda
call conda --version
echo.
@rem activate the environment
call conda activate .\stable-diffusion\env
call where python
call python --version
echo.
cmd /k

View File

@ -1,19 +1,27 @@
@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
)
cd /d %~dp0
set PATH=C:\Windows\System32;%PATH%
@call installer\Scripts\activate.bat
@rem set legacy installer's PATH, if it exists
if exist "installer" set PATH=%cd%\installer;%cd%\installer\Library\bin;%cd%\installer\Scripts;%cd%\installer\Library\usr\bin;%PATH%
@call conda-unpack
@rem Setup the packages required for the installer
call scripts\bootstrap.bat
@call conda --version
@call git --version
@rem set new installer's PATH, if it downloaded any packages
if exist "installer_files\env" set PATH=%cd%\installer_files\env;%cd%\installer_files\env\Library\bin;%cd%\installer_files\env\Scripts;%cd%\installer_files\Library\usr\bin;%PATH%
@cd installer
set PYTHONPATH=%cd%\installer;%cd%\installer_files\env
@call ..\scripts\on_env_start.bat
@rem Test the bootstrap
call where git
call git --version
call where conda
call conda --version
@rem Download the rest of the installer and UI
call scripts\on_env_start.bat
@pause

77
scripts/bootstrap.bat Normal file
View File

@ -0,0 +1,77 @@
@echo off
@rem This script will install git and conda (if not found on the PATH variable)
@rem using micromamba (an 8mb static-linked single-file binary, conda replacement).
@rem For users who already have git and conda, this step will be skipped.
@rem This enables a user to install this project without manually installing conda and git.
@rem config
set MAMBA_ROOT_PREFIX=%cd%\installer_files\mamba
set INSTALL_ENV_DIR=%cd%\installer_files\env
set LEGACY_INSTALL_ENV_DIR=%cd%\installer
set MICROMAMBA_DOWNLOAD_URL=https://github.com/cmdr2/stable-diffusion-ui/releases/download/v1.1/micromamba.exe
set umamba_exists=F
set OLD_APPDATA=%APPDATA%
set OLD_USERPROFILE=%USERPROFILE%
set APPDATA=%cd%\installer_files\appdata
set USERPROFILE=%cd%\profile
@rem figure out whether git and conda needs to be installed
if exist "%INSTALL_ENV_DIR%" set PATH=%INSTALL_ENV_DIR%;%INSTALL_ENV_DIR%\Library\bin;%INSTALL_ENV_DIR%\Scripts;%INSTALL_ENV_DIR%\Library\usr\bin;%PATH%
set PACKAGES_TO_INSTALL=
if not exist "%LEGACY_INSTALL_ENV_DIR%\etc\profile.d\conda.sh" (
if not exist "%INSTALL_ENV_DIR%\etc\profile.d\conda.sh" set PACKAGES_TO_INSTALL=%PACKAGES_TO_INSTALL% conda
)
call git --version >.tmp1 2>.tmp2
if "%ERRORLEVEL%" NEQ "0" set PACKAGES_TO_INSTALL=%PACKAGES_TO_INSTALL% git
call "%MAMBA_ROOT_PREFIX%\micromamba.exe" --version >.tmp1 2>.tmp2
if "%ERRORLEVEL%" EQU "0" set umamba_exists=T
@rem (if necessary) install git and conda into a contained environment
if "%PACKAGES_TO_INSTALL%" NEQ "" (
@rem download micromamba
if "%umamba_exists%" == "F" (
echo "Downloading micromamba from %MICROMAMBA_DOWNLOAD_URL% to %MAMBA_ROOT_PREFIX%\micromamba.exe"
mkdir "%MAMBA_ROOT_PREFIX%"
call curl -Lk "%MICROMAMBA_DOWNLOAD_URL%" > "%MAMBA_ROOT_PREFIX%\micromamba.exe"
@REM if "%ERRORLEVEL%" NEQ "0" (
@REM echo "There was a problem downloading micromamba. Cannot continue."
@REM pause
@REM exit /b
@REM )
mkdir "%APPDATA%"
mkdir "%USERPROFILE%"
@rem test the mamba binary
echo Micromamba version:
call "%MAMBA_ROOT_PREFIX%\micromamba.exe" --version
)
@rem create the installer env
if not exist "%INSTALL_ENV_DIR%" (
call "%MAMBA_ROOT_PREFIX%\micromamba.exe" create -y --prefix "%INSTALL_ENV_DIR%"
)
echo "Packages to install:%PACKAGES_TO_INSTALL%"
call "%MAMBA_ROOT_PREFIX%\micromamba.exe" install -y --prefix "%INSTALL_ENV_DIR%" -c conda-forge %PACKAGES_TO_INSTALL%
if not exist "%INSTALL_ENV_DIR%" (
echo "There was a problem while installing%PACKAGES_TO_INSTALL% using micromamba. Cannot continue."
pause
exit /b
)
)
@rem revert to the old APPDATA. only needed it for bypassing a bug in micromamba (with special characters)
set APPDATA=%OLD_APPDATA%
set USERPROFILE=%OLD_USERPROFILE%

86
scripts/bootstrap.sh Executable file
View File

@ -0,0 +1,86 @@
#!/bin/bash
# This script will install git and conda (if not found on the PATH variable)
# using micromamba (an 8mb static-linked single-file binary, conda replacement).
# For users who already have git and conda, this step will be skipped.
# This enables a user to install this project without manually installing conda and git.
source ./scripts/functions.sh
set -o pipefail
OS_NAME=$(uname -s)
case "${OS_NAME}" in
Linux*) OS_NAME="linux";;
Darwin*) OS_NAME="osx";;
*) echo "Unknown OS: $OS_NAME! This script runs only on Linux or Mac" && exit
esac
OS_ARCH=$(uname -m)
case "${OS_ARCH}" in
x86_64*) OS_ARCH="64";;
arm64*) OS_ARCH="arm64";;
*) echo "Unknown system architecture: $OS_ARCH! This script runs only on x86_64 or arm64" && exit
esac
# https://mamba.readthedocs.io/en/latest/installation.html
if [ "$OS_NAME" == "linux" ] && [ "$OS_ARCH" == "arm64" ]; then OS_ARCH="aarch64"; fi
# config
export MAMBA_ROOT_PREFIX="$(pwd)/installer_files/mamba"
INSTALL_ENV_DIR="$(pwd)/installer_files/env"
LEGACY_INSTALL_ENV_DIR="$(pwd)/installer"
MICROMAMBA_DOWNLOAD_URL="https://micro.mamba.pm/api/micromamba/${OS_NAME}-${OS_ARCH}/latest"
umamba_exists="F"
# figure out whether git and conda needs to be installed
if [ -e "$INSTALL_ENV_DIR" ]; then export PATH="$INSTALL_ENV_DIR/bin:$PATH"; fi
PACKAGES_TO_INSTALL=""
if [ ! -e "$LEGACY_INSTALL_ENV_DIR/etc/profile.d/conda.sh" ] && [ ! -e "$INSTALL_ENV_DIR/etc/profile.d/conda.sh" ]; then PACKAGES_TO_INSTALL="$PACKAGES_TO_INSTALL conda"; fi
if ! hash "git" &>/dev/null; then PACKAGES_TO_INSTALL="$PACKAGES_TO_INSTALL git"; fi
if "$MAMBA_ROOT_PREFIX/micromamba" --version &>/dev/null; then umamba_exists="T"; fi
# (if necessary) install git and conda into a contained environment
if [ "$PACKAGES_TO_INSTALL" != "" ]; then
# download micromamba
if [ "$umamba_exists" == "F" ]; then
echo "Downloading micromamba from $MICROMAMBA_DOWNLOAD_URL to $MAMBA_ROOT_PREFIX/micromamba"
mkdir -p "$MAMBA_ROOT_PREFIX"
curl -L "$MICROMAMBA_DOWNLOAD_URL" | tar -xvj bin/micromamba -O > "$MAMBA_ROOT_PREFIX/micromamba"
if [ "$?" != "0" ]; then
echo
echo "EE micromamba download failed"
echo "EE If the lines above contain 'bzip2: Cannot exec', your system doesn't have bzip2 installed"
echo "EE If there are network errors, please check your internet setup"
fail "micromamba download failed"
fi
chmod u+x "$MAMBA_ROOT_PREFIX/micromamba"
# test the mamba binary
echo "Micromamba version:"
"$MAMBA_ROOT_PREFIX/micromamba" --version
fi
# create the installer env
if [ ! -e "$INSTALL_ENV_DIR" ]; then
"$MAMBA_ROOT_PREFIX/micromamba" create -y --prefix "$INSTALL_ENV_DIR" || fail "unable to create the install environment"
fi
if [ ! -e "$INSTALL_ENV_DIR" ]; then
fail "There was a problem while installing$PACKAGES_TO_INSTALL using micromamba. Cannot continue."
fi
echo "Packages to install:$PACKAGES_TO_INSTALL"
"$MAMBA_ROOT_PREFIX/micromamba" install -y --prefix "$INSTALL_ENV_DIR" -c conda-forge $PACKAGES_TO_INSTALL
if [ "$?" != "0" ]; then
fail "Installation of the packages '$PACKAGES_TO_INSTALL' failed."
fi
fi

35
scripts/developer_console.sh Normal file → Executable file
View File

@ -1,17 +1,42 @@
#!/bin/bash
cd "$(dirname "${BASH_SOURCE[0]}")"
if [ "$0" == "bash" ]; then
echo "Opening Stable Diffusion UI - Developer Console.."
echo ""
source installer/bin/activate
# set legacy and new installer's PATH, if they exist
if [ -e "installer" ]; then export PATH="$(pwd)/installer/bin:$PATH"; fi
if [ -e "installer_files/env" ]; then export PATH="$(pwd)/installer_files/env/bin:$PATH"; fi
conda-unpack
# activate the installer env
CONDA_BASEPATH=$(conda info --base)
source "$CONDA_BASEPATH/etc/profile.d/conda.sh" # avoids the 'shell not initialized' error
conda --version
conda activate
# test the environment
echo "Environment Info:"
which git
git --version
which conda
conda --version
echo ""
# activate the environment
CONDA_BASEPATH=$(conda info --base)
source "$CONDA_BASEPATH/etc/profile.d/conda.sh" # otherwise conda complains about 'shell not initialized' (needed when running in a script)
conda activate ./stable-diffusion/env
which python
python --version
echo ""
else
bash --init-file open_dev_console.sh
fi
file_name=$(basename "${BASH_SOURCE[0]}")
bash --init-file "$file_name"
fi

32
scripts/functions.sh Normal file
View File

@ -0,0 +1,32 @@
#
# utility functions for all scripts
#
fail() {
echo
echo "EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE"
echo
if [ "$1" != "" ]; then
echo ERROR: $1
else
echo An error occurred.
fi
cat <<EOF
Error downloading Stable Diffusion UI. Sorry about that, please try to:
1. Run this installer again.
2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/wiki/Troubleshooting
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
4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues
Thanks!
EOF
read -p "Press any key to continue"
exit 1
}

View File

@ -4,8 +4,6 @@
set PATH=C:\Windows\System32;%PATH%
@cd ..
if exist "scripts\config.bat" (
@call scripts\config.bat
)
@ -14,7 +12,7 @@ if "%update_branch%"=="" (
set update_branch=main
)
@>nul grep -c "conda_sd_ui_deps_installed" scripts\install_status.txt
@>nul findstr /m "conda_sd_ui_deps_installed" scripts\install_status.txt
@if "%ERRORLEVEL%" NEQ "0" (
for /f "tokens=*" %%a in ('python -c "import os; parts = os.getcwd().split(os.path.sep); print(len(parts))"') do if "%%a" NEQ "2" (
echo. & echo "!!!! WARNING !!!!" & echo.
@ -28,14 +26,14 @@ if "%update_branch%"=="" (
)
)
@>nul grep -c "sd_ui_git_cloned" scripts\install_status.txt
@>nul findstr /m "sd_ui_git_cloned" scripts\install_status.txt
@if "%ERRORLEVEL%" EQU "0" (
@echo "Stable Diffusion UI's git repository was already installed. Updating from %update_branch%.."
@cd sd-ui-files
@call git reset --hard
@call git checkout "%update_branch%"
@call git -c advice.detachedHead=false checkout "%update_branch%"
@call git pull
@cd ..
@ -46,7 +44,7 @@ if "%update_branch%"=="" (
@call git clone -b "%update_branch%" https://github.com/cmdr2/stable-diffusion-ui.git sd-ui-files && (
@echo sd_ui_git_cloned >> scripts\install_status.txt
) || (
@echo "Error downloading Stable Diffusion UI. 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/blob/main/Troubleshooting.md" & 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!"
@echo "Error downloading Stable Diffusion UI. 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
)
@ -54,9 +52,10 @@ if "%update_branch%"=="" (
@xcopy sd-ui-files\ui ui /s /i /Y
@copy sd-ui-files\scripts\on_sd_start.bat scripts\ /Y
@copy sd-ui-files\scripts\bootstrap.bat scripts\ /Y
@copy "sd-ui-files\scripts\Start Stable Diffusion UI.cmd" . /Y
@copy "sd-ui-files\scripts\Developer Console.cmd" . /Y
@call scripts\on_sd_start.bat
@pause
@pause

View File

@ -1,5 +1,7 @@
#!/bin/bash
source ./scripts/functions.sh
printf "\n\nStable Diffusion UI\n\n"
if [ -f "scripts/config.sh" ]; then
@ -16,7 +18,7 @@ if [ -f "scripts/install_status.txt" ] && [ `grep -c sd_ui_git_cloned scripts/in
cd sd-ui-files
git reset --hard
git checkout "$update_branch"
git -c advice.detachedHead=false checkout "$update_branch"
git pull
cd ..
@ -27,15 +29,14 @@ else
if git clone -b "$update_branch" https://github.com/cmdr2/stable-diffusion-ui.git sd-ui-files ; then
echo sd_ui_git_cloned >> scripts/install_status.txt
else
printf "\n\nError downloading Stable Diffusion UI. Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
read -p "Press any key to continue"
exit
fail "git clone failed"
fi
fi
rm -rf ui
cp -Rf sd-ui-files/ui .
cp sd-ui-files/scripts/on_sd_start.sh scripts/
cp sd-ui-files/scripts/bootstrap.sh scripts/
cp sd-ui-files/scripts/start.sh .
cp sd-ui-files/scripts/developer_console.sh .

View File

@ -1,16 +1,24 @@
@echo off
@copy sd-ui-files\scripts\on_env_start.bat scripts\ /Y
@copy sd-ui-files\scripts\bootstrap.bat scripts\ /Y
if exist "%cd%\profile" (
set USERPROFILE=%cd%\profile
)
@rem activate the installer env
call conda activate
@REM Caution, this file will make your eyes and brain bleed. It's such an unholy mess.
@REM Note to self: Please rewrite this in Python. For the sake of your own sanity.
@copy "sd-ui-files\scripts\Developer Console.cmd" . /Y
@REM remove the old version of the dev console script, if it's still present
if exist "Open Developer Console.cmd" del "Open Developer Console.cmd"
@call python -c "import os; import shutil; frm = 'sd-ui-files\\ui\\hotfix\\9c24e6cd9f499d02c4f21a033736dabd365962dc80fe3aeb57a8f85ea45a20a3.26fead7ea4f0f843f6eb4055dfd25693f1a71f3c6871b184042d4b126244e142'; dst = os.path.join(os.path.expanduser('~'), '.cache', 'huggingface', 'transformers', '9c24e6cd9f499d02c4f21a033736dabd365962dc80fe3aeb57a8f85ea45a20a3.26fead7ea4f0f843f6eb4055dfd25693f1a71f3c6871b184042d4b126244e142'); shutil.copyfile(frm, dst) if os.path.exists(dst) else print(''); print('Hotfixed broken JSON file from OpenAI');"
@>nul grep -c "sd_git_cloned" scripts\install_status.txt
@>nul findstr /m "sd_git_cloned" scripts\install_status.txt
@if "%ERRORLEVEL%" EQU "0" (
@echo "Stable Diffusion's git repository was already installed. Updating.."
@ -18,7 +26,7 @@ if exist "Open Developer Console.cmd" del "Open Developer Console.cmd"
@call git reset --hard
@call git pull
@call git checkout f6cfebffa752ee11a7b07497b8529d5971de916c
@call git -c advice.detachedHead=false checkout f6cfebffa752ee11a7b07497b8529d5971de916c
@call git apply ..\ui\sd_internal\ddim_callback.patch
@call git apply ..\ui\sd_internal\env_yaml.patch
@ -30,13 +38,13 @@ if exist "Open Developer Console.cmd" del "Open Developer Console.cmd"
@call git clone https://github.com/basujindal/stable-diffusion.git && (
@echo sd_git_cloned >> scripts\install_status.txt
) || (
@echo "Error downloading Stable Diffusion. 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/blob/main/Troubleshooting.md" & 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!"
@echo "Error downloading Stable Diffusion. 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
)
@cd stable-diffusion
@call git checkout f6cfebffa752ee11a7b07497b8529d5971de916c
@call git -c advice.detachedHead=false checkout f6cfebffa752ee11a7b07497b8529d5971de916c
@call git apply ..\ui\sd_internal\ddim_callback.patch
@call git apply ..\ui\sd_internal\env_yaml.patch
@ -46,7 +54,7 @@ if exist "Open Developer Console.cmd" del "Open Developer Console.cmd"
@cd stable-diffusion
@>nul grep -c "conda_sd_env_created" ..\scripts\install_status.txt
@>nul findstr /m "conda_sd_env_created" ..\scripts\install_status.txt
@if "%ERRORLEVEL%" EQU "0" (
@echo "Packages necessary for Stable Diffusion were already installed"
@ -59,8 +67,14 @@ if exist "Open Developer Console.cmd" del "Open Developer Console.cmd"
@REM prevent conda from using packages from the user's home directory, to avoid conflicts
@set PYTHONNOUSERSITE=1
set USERPROFILE=%cd%\profile
set TMP=%cd%\tmp
set TEMP=%cd%\tmp
set PYTHONPATH=%cd%;%cd%\env\lib\site-packages
@call conda env create --prefix env -f environment.yaml || (
@echo. & echo "Error installing the packages necessary for Stable Diffusion. 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/blob/main/Troubleshooting.md" & 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!" & echo.
@echo. & echo "Error installing the packages necessary for Stable Diffusion. 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!" & echo.
pause
exit /b
)
@ -68,13 +82,13 @@ if exist "Open Developer Console.cmd" del "Open Developer Console.cmd"
@call conda activate .\env
@call conda install -c conda-forge -y --prefix env antlr4-python3-runtime=4.8 || (
@echo. & echo "Error installing antlr4-python3-runtime for Stable Diffusion. 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/blob/main/Troubleshooting.md" & 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!" & echo.
@echo. & echo "Error installing antlr4-python3-runtime for Stable Diffusion. 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!" & echo.
pause
exit /b
)
for /f "tokens=*" %%a in ('python -c "import torch; import ldm; import transformers; import numpy; import antlr4; print(42)"') do if "%%a" NEQ "42" (
@echo. & echo "Dependency test failed! Error installing the packages necessary for Stable Diffusion. 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/blob/main/Troubleshooting.md" & 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!" & echo.
@echo. & echo "Dependency test failed! Error installing the packages necessary for Stable Diffusion. 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!" & echo.
pause
exit /b
)
@ -84,7 +98,7 @@ if exist "Open Developer Console.cmd" del "Open Developer Console.cmd"
set PATH=C:\Windows\System32;%PATH%
@>nul grep -c "conda_sd_gfpgan_deps_installed" ..\scripts\install_status.txt
@>nul findstr /m "conda_sd_gfpgan_deps_installed" ..\scripts\install_status.txt
@if "%ERRORLEVEL%" EQU "0" (
@echo "Packages necessary for GFPGAN (Face Correction) were already installed"
) else (
@ -92,20 +106,26 @@ set PATH=C:\Windows\System32;%PATH%
@set PYTHONNOUSERSITE=1
set USERPROFILE=%cd%\profile
set TMP=%cd%\tmp
set TEMP=%cd%\tmp
set PYTHONPATH=%cd%;%cd%\env\lib\site-packages
@call pip install -e git+https://github.com/TencentARC/GFPGAN#egg=GFPGAN || (
@echo. & echo "Error installing the packages necessary for GFPGAN (Face Correction). 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/blob/main/Troubleshooting.md" & 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!" & echo.
@echo. & echo "Error installing the packages necessary for GFPGAN (Face Correction). 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!" & echo.
pause
exit /b
)
@call pip install basicsr==1.4.2 || (
@echo. & echo "Error installing the basicsr package necessary for GFPGAN (Face Correction). 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/blob/main/Troubleshooting.md" & 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!" & echo.
@echo. & echo "Error installing the basicsr package necessary for GFPGAN (Face Correction). 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!" & echo.
pause
exit /b
)
for /f "tokens=*" %%a in ('python -c "from gfpgan import GFPGANer; print(42)"') do if "%%a" NEQ "42" (
@echo. & echo "Dependency test failed! Error installing the packages necessary for GFPGAN (Face Correction). 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/blob/main/Troubleshooting.md" & 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!" & echo.
@echo. & echo "Dependency test failed! Error installing the packages necessary for GFPGAN (Face Correction). 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!" & echo.
pause
exit /b
)
@ -113,7 +133,7 @@ set PATH=C:\Windows\System32;%PATH%
@echo conda_sd_gfpgan_deps_installed >> ..\scripts\install_status.txt
)
@>nul grep -c "conda_sd_esrgan_deps_installed" ..\scripts\install_status.txt
@>nul findstr /m "conda_sd_esrgan_deps_installed" ..\scripts\install_status.txt
@if "%ERRORLEVEL%" EQU "0" (
@echo "Packages necessary for ESRGAN (Resolution Upscaling) were already installed"
) else (
@ -121,14 +141,20 @@ set PATH=C:\Windows\System32;%PATH%
@set PYTHONNOUSERSITE=1
set USERPROFILE=%cd%\profile
set TMP=%cd%\tmp
set TEMP=%cd%\tmp
set PYTHONPATH=%cd%;%cd%\env\lib\site-packages
@call pip install -e git+https://github.com/xinntao/Real-ESRGAN#egg=realesrgan || (
@echo. & echo "Error installing the packages necessary for ESRGAN (Resolution Upscaling). 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/blob/main/Troubleshooting.md" & 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!" & echo.
@echo. & echo "Error installing the packages necessary for ESRGAN (Resolution Upscaling). 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!" & echo.
pause
exit /b
)
for /f "tokens=*" %%a in ('python -c "from basicsr.archs.rrdbnet_arch import RRDBNet; from realesrgan import RealESRGANer; print(42)"') do if "%%a" NEQ "42" (
@echo. & echo "Dependency test failed! Error installing the packages necessary for ESRGAN (Resolution Upscaling). 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/blob/main/Troubleshooting.md" & 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!" & echo.
@echo. & echo "Dependency test failed! Error installing the packages necessary for ESRGAN (Resolution Upscaling). 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!" & echo.
pause
exit /b
)
@ -136,7 +162,7 @@ set PATH=C:\Windows\System32;%PATH%
@echo conda_sd_esrgan_deps_installed >> ..\scripts\install_status.txt
)
@>nul grep -c "conda_sd_ui_deps_installed" ..\scripts\install_status.txt
@>nul findstr /m "conda_sd_ui_deps_installed" ..\scripts\install_status.txt
@if "%ERRORLEVEL%" EQU "0" (
echo "Packages necessary for Stable Diffusion UI were already installed"
) else (
@ -144,22 +170,28 @@ set PATH=C:\Windows\System32;%PATH%
@set PYTHONNOUSERSITE=1
set USERPROFILE=%cd%\profile
set TMP=%cd%\tmp
set TEMP=%cd%\tmp
set PYTHONPATH=%cd%;%cd%\env\lib\site-packages
@call conda install -c conda-forge -y --prefix env uvicorn fastapi || (
echo "Error installing the packages necessary for Stable Diffusion UI. 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/blob/main/Troubleshooting.md" & 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!"
echo "Error installing the packages necessary for Stable Diffusion UI. 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
)
)
call WHERE uvicorn > .tmp
@>nul grep -c "uvicorn" .tmp
@>nul findstr /m "uvicorn" .tmp
@if "%ERRORLEVEL%" NEQ "0" (
@echo. & echo "UI packages not found! 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/blob/main/Troubleshooting.md" & 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!" & echo.
@echo. & echo "UI packages not found! 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!" & echo.
pause
exit /b
)
@>nul grep -c "conda_sd_ui_deps_installed" ..\scripts\install_status.txt
@>nul findstr /m "conda_sd_ui_deps_installed" ..\scripts\install_status.txt
@if "%ERRORLEVEL%" NEQ "0" (
@echo conda_sd_ui_deps_installed >> ..\scripts\install_status.txt
)
@ -194,12 +226,12 @@ echo. > "..\models\stable-diffusion\Put your custom ckpt files here.txt"
@if exist "sd-v1-4.ckpt" (
for %%I in ("sd-v1-4.ckpt") do if "%%~zI" NEQ "4265380512" (
echo. & echo "Error: The downloaded model file was invalid! Bytes downloaded: %%~zI" & echo.
echo. & echo "Error downloading the data files (weights) for Stable Diffusion. 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/blob/main/Troubleshooting.md" & 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!" & echo.
echo. & echo "Error downloading the data files (weights) for Stable Diffusion. 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!" & echo.
pause
exit /b
)
) else (
@echo. & echo "Error downloading the data files (weights) for Stable Diffusion. 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/blob/main/Troubleshooting.md" & 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!" & echo.
@echo. & echo "Error downloading the data files (weights) for Stable Diffusion. 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!" & echo.
pause
exit /b
)
@ -224,12 +256,12 @@ echo. > "..\models\stable-diffusion\Put your custom ckpt files here.txt"
@if exist "GFPGANv1.3.pth" (
for %%I in ("GFPGANv1.3.pth") do if "%%~zI" NEQ "348632874" (
echo. & echo "Error: The downloaded GFPGAN model file was invalid! Bytes downloaded: %%~zI" & echo.
echo. & echo "Error downloading the data files (weights) for GFPGAN (Face Correction). 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/blob/main/Troubleshooting.md" & 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!" & echo.
echo. & echo "Error downloading the data files (weights) for GFPGAN (Face Correction). 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!" & echo.
pause
exit /b
)
) else (
@echo. & echo "Error downloading the data files (weights) for GFPGAN (Face Correction). 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/blob/main/Troubleshooting.md" & 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!" & echo.
@echo. & echo "Error downloading the data files (weights) for GFPGAN (Face Correction). 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!" & echo.
pause
exit /b
)
@ -254,12 +286,12 @@ echo. > "..\models\stable-diffusion\Put your custom ckpt files here.txt"
@if exist "RealESRGAN_x4plus.pth" (
for %%I in ("RealESRGAN_x4plus.pth") do if "%%~zI" NEQ "67040989" (
echo. & echo "Error: The downloaded ESRGAN x4plus model file was invalid! Bytes downloaded: %%~zI" & echo.
echo. & echo "Error downloading the data files (weights) for ESRGAN (Resolution Upscaling) x4plus. 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/blob/main/Troubleshooting.md" & 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!" & echo.
echo. & echo "Error downloading the data files (weights) for ESRGAN (Resolution Upscaling) x4plus. 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!" & echo.
pause
exit /b
)
) else (
@echo. & echo "Error downloading the data files (weights) for ESRGAN (Resolution Upscaling) x4plus. 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/blob/main/Troubleshooting.md" & 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!" & echo.
@echo. & echo "Error downloading the data files (weights) for ESRGAN (Resolution Upscaling) x4plus. 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!" & echo.
pause
exit /b
)
@ -284,12 +316,12 @@ echo. > "..\models\stable-diffusion\Put your custom ckpt files here.txt"
@if exist "RealESRGAN_x4plus_anime_6B.pth" (
for %%I in ("RealESRGAN_x4plus_anime_6B.pth") do if "%%~zI" NEQ "17938799" (
echo. & echo "Error: The downloaded ESRGAN x4plus_anime model file was invalid! Bytes downloaded: %%~zI" & echo.
echo. & echo "Error downloading the data files (weights) for ESRGAN (Resolution Upscaling) x4plus_anime. 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/blob/main/Troubleshooting.md" & 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!" & echo.
echo. & echo "Error downloading the data files (weights) for ESRGAN (Resolution Upscaling) x4plus_anime. 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!" & echo.
pause
exit /b
)
) else (
@echo. & echo "Error downloading the data files (weights) for ESRGAN (Resolution Upscaling) x4plus_anime. 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/blob/main/Troubleshooting.md" & 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!" & echo.
@echo. & echo "Error downloading the data files (weights) for ESRGAN (Resolution Upscaling) x4plus_anime. 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!" & echo.
pause
exit /b
)
@ -297,7 +329,7 @@ echo. > "..\models\stable-diffusion\Put your custom ckpt files here.txt"
@>nul grep -c "sd_install_complete" ..\scripts\install_status.txt
@>nul findstr /m "sd_install_complete" ..\scripts\install_status.txt
@if "%ERRORLEVEL%" NEQ "0" (
@echo sd_weights_downloaded >> ..\scripts\install_status.txt
@echo sd_install_complete >> ..\scripts\install_status.txt
@ -312,12 +344,16 @@ echo. > "..\models\stable-diffusion\Put your custom ckpt files here.txt"
@cd ..\..\..
@echo PYTHONPATH=%PYTHONPATH%
call where python
call python --version
@cd ..
@set SD_UI_PATH=%cd%\ui
@cd stable-diffusion
@call python --version
@if NOT DEFINED SD_UI_BIND_PORT set SD_UI_BIND_PORT=9000
@if NOT DEFINED SD_UI_BIND_IP set SD_UI_BIND_IP=0.0.0.0
@uvicorn server:app --app-dir "%SD_UI_PATH%" --port %SD_UI_BIND_PORT% --host %SD_UI_BIND_IP%
@uvicorn server:app --app-dir "%SD_UI_PATH%" --port 9000 --host 0.0.0.0
@pause
@pause

View File

@ -1,15 +1,22 @@
#!/bin/bash
source ./scripts/functions.sh
cp sd-ui-files/scripts/on_env_start.sh scripts/
cp sd-ui-files/scripts/bootstrap.sh scripts/
source installer/etc/profile.d/conda.sh
# activate the installer env
CONDA_BASEPATH=$(conda info --base)
source "$CONDA_BASEPATH/etc/profile.d/conda.sh" # avoids the 'shell not initialized' error
cp sd-ui-files/scripts/developer_console.sh .
conda activate || fail "Failed to activate conda"
# remove the old version of the dev console script, if it's still present
if [ -e "open_dev_console.sh" ]; then
rm "open_dev_console.sh"
fi
python -c "import os; import shutil; frm = 'sd-ui-files/ui/hotfix/9c24e6cd9f499d02c4f21a033736dabd365962dc80fe3aeb57a8f85ea45a20a3.26fead7ea4f0f843f6eb4055dfd25693f1a71f3c6871b184042d4b126244e142'; dst = os.path.join(os.path.expanduser('~'), '.cache', 'huggingface', 'transformers', '9c24e6cd9f499d02c4f21a033736dabd365962dc80fe3aeb57a8f85ea45a20a3.26fead7ea4f0f843f6eb4055dfd25693f1a71f3c6871b184042d4b126244e142'); shutil.copyfile(frm, dst) if os.path.exists(dst) else print(''); print('Hotfixed broken JSON file from OpenAI');"
python -c "import os; import shutil; frm = 'sd-ui-files/ui/hotfix/9c24e6cd9f499d02c4f21a033736dabd365962dc80fe3aeb57a8f85ea45a20a3.26fead7ea4f0f843f6eb4055dfd25693f1a71f3c6871b184042d4b126244e142'; dst = os.path.join(os.path.expanduser('~'), '.cache', 'huggingface', 'transformers', '9c24e6cd9f499d02c4f21a033736dabd365962dc80fe3aeb57a8f85ea45a20a3.26fead7ea4f0f843f6eb4055dfd25693f1a71f3c6871b184042d4b126244e142'); shutil.copyfile(frm, dst) if os.path.exists(dst) else print(''); print('Hotfixed broken JSON file from OpenAI');"
# Caution, this file will make your eyes and brain bleed. It's such an unholy mess.
# Note to self: Please rewrite this in Python. For the sake of your own sanity.
@ -21,10 +28,10 @@ if [ -e "scripts/install_status.txt" ] && [ `grep -c sd_git_cloned scripts/insta
git reset --hard
git pull
git checkout f6cfebffa752ee11a7b07497b8529d5971de916c
git -c advice.detachedHead=false checkout f6cfebffa752ee11a7b07497b8529d5971de916c
git apply ../ui/sd_internal/ddim_callback.patch
git apply ../ui/sd_internal/env_yaml.patch
git apply ../ui/sd_internal/ddim_callback.patch || fail "ddim patch failed"
git apply ../ui/sd_internal/env_yaml.patch || fail "yaml patch failed"
cd ..
else
@ -33,16 +40,14 @@ else
if git clone https://github.com/basujindal/stable-diffusion.git ; then
echo sd_git_cloned >> scripts/install_status.txt
else
printf "\n\nError downloading Stable Diffusion. Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
read -p "Press any key to continue"
exit
fail "git clone of basujindal/stable-diffusion.git failed"
fi
cd stable-diffusion
git checkout f6cfebffa752ee11a7b07497b8529d5971de916c
git -c advice.detachedHead=false checkout f6cfebffa752ee11a7b07497b8529d5971de916c
git apply ../ui/sd_internal/ddim_callback.patch
git apply ../ui/sd_internal/env_yaml.patch
git apply ../ui/sd_internal/ddim_callback.patch || fail "ddim patch failed"
git apply ../ui/sd_internal/env_yaml.patch || fail "yaml patch failed"
cd ..
fi
@ -52,37 +57,32 @@ cd stable-diffusion
if [ `grep -c conda_sd_env_created ../scripts/install_status.txt` -gt "0" ]; then
echo "Packages necessary for Stable Diffusion were already installed"
conda activate ./env
conda activate ./env || fail "conda activate failed"
else
printf "\n\nDownloading packages necessary for Stable Diffusion..\n"
printf "\n\n***** This will take some time (depending on the speed of the Internet connection) and may appear to be stuck, but please be patient ***** ..\n\n"
# prevent conda from using packages from the user's home directory, to avoid conflicts
export PYTHONNOUSERSITE=1
export PYTHONPATH="$(pwd):$(pwd)/env/lib/site-packages"
if conda env create --prefix env --force -f environment.yaml ; then
echo "Installed. Testing.."
else
printf "\n\nError installing the packages necessary for Stable Diffusion. Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
read -p "Press any key to continue"
exit
fail "'conda env create' failed"
fi
conda activate ./env
conda activate ./env || fail "conda activate failed"
if conda install -c conda-forge --prefix ./env -y antlr4-python3-runtime=4.8 ; then
echo "Installed. Testing.."
else
printf "\n\nError installing antlr4-python3-runtime for Stable Diffusion. Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
read -p "Press any key to continue"
exit
fail "Error installing antlr4-python3-runtime"
fi
out_test=`python -c "import torch; import ldm; import transformers; import numpy; import antlr4; print(42)"`
if [ "$out_test" != "42" ]; then
printf "\n\nDependency test failed! Error installing the packages necessary for Stable Diffusion. Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
read -p "Press any key to continue"
exit
fail "Dependency test failed"
fi
echo conda_sd_env_created >> ../scripts/install_status.txt
@ -94,20 +94,20 @@ else
printf "\n\nDownloading packages necessary for GFPGAN (Face Correction)..\n"
export PYTHONNOUSERSITE=1
export PYTHONPATH="$(pwd):$(pwd)/env/lib/site-packages"
if pip install -e git+https://github.com/TencentARC/GFPGAN#egg=GFPGAN ; then
echo "Installed. Testing.."
else
printf "\n\nError installing the packages necessary for GFPGAN (Face Correction). Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
read -p "Press any key to continue"
exit
fail "Error installing the packages necessary for GFPGAN (Face Correction)."
fi
out_test=`python -c "from gfpgan import GFPGANer; print(42)"`
if [ "$out_test" != "42" ]; then
printf "\n\nDependency test failed! Error installing the packages necessary for GFPGAN (Face Correction). Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
read -p "Press any key to continue"
exit
echo "EE The dependency check has failed. This usually means that some system libraries are missing."
echo "EE On Debian/Ubuntu systems, this are often these packages: libsm6 libxext6 libxrender-dev"
echo "EE Other Linux distributions might have different package names for these libraries."
fail "GFPGAN dependency test failed"
fi
echo conda_sd_gfpgan_deps_installed >> ../scripts/install_status.txt
@ -119,20 +119,17 @@ else
printf "\n\nDownloading packages necessary for ESRGAN (Resolution Upscaling)..\n"
export PYTHONNOUSERSITE=1
export PYTHONPATH="$(pwd):$(pwd)/env/lib/site-packages"
if pip install -e git+https://github.com/xinntao/Real-ESRGAN#egg=realesrgan ; then
echo "Installed. Testing.."
else
printf "\n\nError installing the packages necessary for ESRGAN (Resolution Upscaling). Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
read -p "Press any key to continue"
exit
fail "Error installing the packages necessary for ESRGAN"
fi
out_test=`python -c "from basicsr.archs.rrdbnet_arch import RRDBNet; from realesrgan import RealESRGANer; print(42)"`
if [ "$out_test" != "42" ]; then
printf "\n\nDependency test failed! Error installing the packages necessary for ESRGAN (Resolution Upscaling). Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
read -p "Press any key to continue"
exit
fail "ESRGAN dependency test failed"
fi
echo conda_sd_esrgan_deps_installed >> ../scripts/install_status.txt
@ -144,19 +141,16 @@ else
printf "\n\nDownloading packages necessary for Stable Diffusion UI..\n\n"
export PYTHONNOUSERSITE=1
export PYTHONPATH="$(pwd):$(pwd)/env/lib/site-packages"
if conda install -c conda-forge --prefix ./env -y uvicorn fastapi ; then
echo "Installed. Testing.."
else
printf "\n\nError installing the packages necessary for Stable Diffusion UI. Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
read -p "Press any key to continue"
exit
fail "'conda install uvicorn' failed"
fi
if ! command -v uvicorn &> /dev/null; then
printf "\n\nUI packages not found! Error installing the packages necessary for Stable Diffusion UI. Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
read -p "Press any key to continue"
exit
fail "UI packages not found!"
fi
echo conda_sd_ui_deps_installed >> ../scripts/install_status.txt
@ -186,15 +180,10 @@ if [ ! -f "sd-v1-4.ckpt" ]; then
if [ -f "sd-v1-4.ckpt" ]; then
model_size=`find "sd-v1-4.ckpt" -printf "%s"`
if [ ! "$model_size" == "4265380512" ]; then
printf "\n\nError: The downloaded model file was invalid! Bytes downloaded: $model_size\n\n"
printf "\n\nError downloading the data files (weights) for Stable Diffusion. Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
read -p "Press any key to continue"
exit
fail "The downloaded model file was invalid! Bytes downloaded: $model_size"
fi
else
printf "\n\nError downloading the data files (weights) for Stable Diffusion. Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
read -p "Press any key to continue"
exit
fail "Error downloading the data files (weights) for Stable Diffusion"
fi
fi
@ -218,15 +207,10 @@ if [ ! -f "GFPGANv1.3.pth" ]; then
if [ -f "GFPGANv1.3.pth" ]; then
model_size=`find "GFPGANv1.3.pth" -printf "%s"`
if [ ! "$model_size" -eq "348632874" ]; then
printf "\n\nError: The downloaded GFPGAN model file was invalid! Bytes downloaded: $model_size\n\n"
printf "\n\nError downloading the data files (weights) for GFPGAN (Face Correction). Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
read -p "Press any key to continue"
exit
fail "The downloaded GFPGAN model file was invalid! Bytes downloaded: $model_size"
fi
else
printf "\n\nError downloading the data files (weights) for GFPGAN (Face Correction). Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
read -p "Press any key to continue"
exit
fail "Error downloading the data files (weights) for GFPGAN (Face Correction)."
fi
fi
@ -250,15 +234,10 @@ if [ ! -f "RealESRGAN_x4plus.pth" ]; then
if [ -f "RealESRGAN_x4plus.pth" ]; then
model_size=`find "RealESRGAN_x4plus.pth" -printf "%s"`
if [ ! "$model_size" -eq "67040989" ]; then
printf "\n\nError: The downloaded ESRGAN x4plus model file was invalid! Bytes downloaded: $model_size\n\n"
printf "\n\nError downloading the data files (weights) for ESRGAN (Resolution Upscaling) x4plus. Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
read -p "Press any key to continue"
exit
fail "The downloaded ESRGAN x4plus model file was invalid! Bytes downloaded: $model_size"
fi
else
printf "\n\nError downloading the data files (weights) for ESRGAN (Resolution Upscaling) x4plus. Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
read -p "Press any key to continue"
exit
fail "Error downloading the data files (weights) for ESRGAN (Resolution Upscaling) x4plus"
fi
fi
@ -282,15 +261,10 @@ if [ ! -f "RealESRGAN_x4plus_anime_6B.pth" ]; then
if [ -f "RealESRGAN_x4plus_anime_6B.pth" ]; then
model_size=`find "RealESRGAN_x4plus_anime_6B.pth" -printf "%s"`
if [ ! "$model_size" -eq "17938799" ]; then
printf "\n\nError: The downloaded ESRGAN x4plus_anime model file was invalid! Bytes downloaded: $model_size\n\n"
printf "\n\nError downloading the data files (weights) for ESRGAN (Resolution Upscaling) x4plus_anime. Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
read -p "Press any key to continue"
exit
fail "The downloaded ESRGAN x4plus_anime model file was invalid! Bytes downloaded: $model_size"
fi
else
printf "\n\nError downloading the data files (weights) for ESRGAN (Resolution Upscaling) x4plus_anime. Sorry about that, please try to:\n 1. Run this installer again.\n 2. If that doesn't fix it, please try the common troubleshooting steps at https://github.com/cmdr2/stable-diffusion-ui/blob/main/Troubleshooting.md\n 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\n 4. If that doesn't solve the problem, please file an issue at https://github.com/cmdr2/stable-diffusion-ui/issues\nThanks!\n\n"
read -p "Press any key to continue"
exit
fail "Error downloading the data files (weights) for ESRGAN (Resolution Upscaling) x4plus_anime."
fi
fi
@ -303,15 +277,16 @@ fi
printf "\n\nStable Diffusion is ready!\n\n"
SD_PATH=`pwd`
export PYTHONPATH="$SD_PATH;$SD_PATH/env/lib/python3.8/site-packages"
export PYTHONPATH="$SD_PATH:$SD_PATH/env/lib/python3.8/site-packages"
echo "PYTHONPATH=$PYTHONPATH"
which python
python --version
cd ..
export SD_UI_PATH=`pwd`/ui
cd stable-diffusion
python --version
uvicorn server:app --app-dir "$SD_UI_PATH" --port 9000 --host 0.0.0.0
uvicorn server:app --app-dir "$SD_UI_PATH" --port ${SD_UI_BIND_PORT:-9000} --host ${SD_UI_BIND_IP:-0.0.0.0}
read -p "Press any key to continue"

20
scripts/start.sh Normal file → Executable file
View File

@ -1,10 +1,22 @@
#!/bin/bash
source installer/bin/activate
cd "$(dirname "${BASH_SOURCE[0]}")"
conda-unpack
# set legacy installer's PATH, if it exists
if [ -e "installer" ]; then export PATH="$(pwd)/installer/bin:$PATH"; fi
conda --version
git --version
# Setup the packages required for the installer
scripts/bootstrap.sh || exit 1
# set new installer's PATH, if it downloaded any packages
if [ -e "installer_files/env" ]; then export PATH="$(pwd)/installer_files/env/bin:$PATH"; fi
# Test the bootstrap
which git
git --version || exit 1
which conda
conda --version || exit 1
# Download the rest of the installer and UI
scripts/on_env_start.sh

View File

@ -2,26 +2,30 @@
<html>
<head>
<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-32x32.png" sizes="32x32">
<link rel="stylesheet" href="/media/main.css?v=21">
<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="/media/drawingboard.min.css">
<script src="/media/jquery-3.6.1.min.js"></script>
<script src="/media/drawingboard.min.js"></script>
<link rel="icon" type="image/png" href="/media/images/favicon-16x16.png" sizes="16x16">
<link rel="icon" type="image/png" href="/media/images/favicon-32x32.png" sizes="32x32">
<link rel="stylesheet" href="/media/css/fonts.css?v=1">
<link rel="stylesheet" href="/media/css/themes.css?v=1">
<link rel="stylesheet" href="/media/css/main.css?v=3">
<link rel="stylesheet" href="/media/css/auto-save.css?v=2">
<link rel="stylesheet" href="/media/css/modifier-thumbnails.css?v=2">
<link rel="stylesheet" href="/media/css/fontawesome-all.min.css?v=1">
<link rel="stylesheet" href="/media/css/drawingboard.min.css">
<script src="/media/js/jquery-3.6.1.min.js"></script>
<script src="/media/js/drawingboard.min.js"></script>
</head>
<body>
<div id="container">
<div id="top-nav">
<div id="logo">
<h1>Stable Diffusion UI <small>v2.2 <span id="updateBranchLabel"></span></small></h1>
<h1>Stable Diffusion UI <small>v2.3.5 <span id="updateBranchLabel"></span></small></h1>
</div>
<ul id="top-nav-items">
<li class="dropdown">
<span><i class="fa fa-comments icon"></i> Help & Community</span>
<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/wiki/" target="_blank"><i class="fa-solid fa-book fa-fw"></i> User guide</a></li>
<li><a href="https://github.com/cmdr2/stable-diffusion-ui/wiki/Troubleshooting" 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://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>
@ -33,11 +37,18 @@
<ul id="system-settings-entries">
<li><b class="settings-subheader">System Settings</b></li>
<br/>
<li><label for="theme">Theme: </label><select id="theme" name="theme"><option value="theme-default">Default</option></select></li>
<li><input id="save_to_disk" name="save_to_disk" type="checkbox"> <label for="save_to_disk">Automatically save to <input id="diskPath" name="diskPath" size="40" disabled></label></li>
<li><input id="sound_toggle" name="sound_toggle" type="checkbox" checked> <label for="sound_toggle">Play sound on task completion</label></li>
<li><input id="turbo" name="turbo" type="checkbox" checked> <label for="turbo">Turbo mode <small>(generates images faster, but uses an additional 1 GB of GPU memory)</small></label></li>
<li><input id="use_cpu" name="use_cpu" type="checkbox"> <label for="use_cpu">Use CPU instead of GPU <small>(warning: this will be *very* slow)</small></label></li>
<li><input id="use_full_precision" name="use_full_precision" type="checkbox"> <label for="use_full_precision">Use full precision <small>(for GPU-only. warning: this will consume more VRAM)</small></label></li>
<li>
<input id="auto_save_settings" name="auto_save_settings" checked type="checkbox">
<label for="auto_save_settings">Automatically save settings <small>(settings restored on browser load)</small></label>
<br/>
<button id="configureSettingsSaveBtn">Configure</button>
</li>
<!-- <li><input id="allow_nsfw" name="allow_nsfw" type="checkbox"> <label for="allow_nsfw">Allow NSFW Content (You confirm you are above 18 years of age)</label></li> -->
<br/>
<li><input id="use_beta_channel" name="use_beta_channel" type="checkbox"> <label for="use_beta_channel">🔥Beta channel. Get the latest features immediately (but could be less stable). Please restart the program after changing this.</label></li>
@ -55,16 +66,25 @@
</div>
<div id="editor-inputs">
<div id="editor-inputs-prompt" class="row">
<label for="prompt">Prompt</label>
<label for="prompt"><b>Enter Prompt</b></label> <small>or</small> <button id="promptsFromFileBtn">Load from a file</button>
<textarea id="prompt" class="col-free">a photograph of an astronaut riding a horse</textarea>
<input id="prompt_from_file" name="prompt_from_file" type="file" /> <!-- hidden -->
<label for="negative_prompt" class="collapsible" id="negative_prompt_handle">Negative Prompt <small>(optional)</small></label>
<div class="collapsible-content">
<input id="negative_prompt" name="negative_prompt" placeholder="list the things to remove from the image (e.g. fog, green)">
</div>
</div>
<div id="editor-inputs-init-image" class="row">
<label for="init_image"><b>Initial Image:</b> (optional) </label> <input id="init_image" name="init_image" type="file" /><br/>
<label for="init_image">Initial Image (img2img) <small>(optional)</small> </label> <input id="init_image" name="init_image" type="file" /><br/>
<div id="init_image_preview_container" class="image_preview_container">
<img id="init_image_preview" src="" width="100" height="100" />
<button class="init_image_clear image_clear_btn">X</button>
<div id="init_image_wrapper">
<img id="init_image_preview" src="" />
<span id="init_image_size_box"></span>
<button class="init_image_clear image_clear_btn">X</button>
</div>
<br/>
<input id="enable_mask" name="enable_mask" type="checkbox"> <label for="enable_mask">In-Painting (beta) <small>(select the area which the AI will paint into)</small></label>
@ -84,29 +104,37 @@
<div class="line-separator">&nbsp;</div>
<div id="editor-settings" class="panel-box settings-box">
<h4 class="collapsible">Image Settings</h4>
<h4 class="collapsible">
Image Settings
<i id="reset-image-settings" class="fa-solid fa-arrow-rotate-left">
<span class="simple-tooltip right">
Reset Image Settings
</span>
</i>
</h4>
<ul id="editor-settings-entries" class="collapsible-content">
<li><b class="settings-subheader">Image Settings</b></li>
<li class="pl-5"><label for="seed">Seed:</label> <input id="seed" name="seed" size="10" value="30000"> <input id="random_seed" name="random_seed" type="checkbox" checked> <label for="random_seed">Random Image</label></li>
<li class="pl-5"><label for="num_outputs_total">Number of images to make:</label> <input id="num_outputs_total" name="num_outputs_total" value="1" size="1"> <label for="num_outputs_parallel">Generate in parallel:</label> <input id="num_outputs_parallel" name="num_outputs_parallel" value="1" size="1"> (images at once)</li>
<li class="pl-5"><label for="stable_diffusion_model">Model:</label>
<li><table>
<tr><b class="settings-subheader">Image Settings</b></tr>
<tr class="pl-5"><td><label for="seed">Seed:</label></td><td><input id="seed" name="seed" size="10" value="30000" onkeypress="preventNonNumericalInput(event)"> <input id="random_seed" name="random_seed" type="checkbox" checked><label for="random_seed">Random</label></td></tr>
<tr class="pl-5"><td><label for="num_outputs_total">Number of Images:</label></td><td><input id="num_outputs_total" name="num_outputs_total" value="1" size="1" onkeypress="preventNonNumericalInput(event)"> <label><small>(total)</small></label> <input id="num_outputs_parallel" name="num_outputs_parallel" value="1" size="1" onkeypress="preventNonNumericalInput(event)"> <label for="num_outputs_parallel"><small>(in parallel)</small></label></td></tr>
<tr class="pl-5"><td><label for="stable_diffusion_model">Model:</label></td><td>
<select id="stable_diffusion_model" name="stable_diffusion_model">
<!-- <option value="sd-v1-4" selected>sd-v1-4</option> -->
</select>
</li>
<li id="samplerSelection" class="pl-5"><label for="sampler">Sampler:</label>
</td></tr>
<tr id="samplerSelection" class="pl-5"><td><label for="sampler">Sampler:</label></td><td>
<select id="sampler" name="sampler">
<option value="plms" selected>plms</option>
<option value="plms">plms</option>
<option value="ddim">ddim</option>
<option value="heun">heun</option>
<option value="euler">euler</option>
<option value="euler_a">euler_a</option>
<option value="euler_a" selected>euler_a</option>
<option value="dpm2">dpm2</option>
<option value="dpm2_a">dpm2_a</option>
<option value="lms">lms</option>
</select>
</li>
<li class="pl-5"><label>Image Size: </label>
</td></tr>
<tr class="pl-5"><td><label>Image Size: </label></td><td>
<select id="width" name="width" value="512">
<option value="128">128 (*)</option>
<option value="192">192</option>
@ -151,58 +179,58 @@
<option value="2048">2048</option>
</select>
<label for="height"><small>(height)</small></label>
</li>
<li class="pl-5"><label for="num_inference_steps">Number of inference steps:</label> <input id="num_inference_steps" name="num_inference_steps" size="4" value="50"></li>
<li class="pl-5"><label for="guidance_scale_slider">Guidance Scale:</label> <input id="guidance_scale_slider" name="guidance_scale_slider" class="editor-slider" value="75" type="range" min="10" max="500"> <input id="guidance_scale" name="guidance_scale" size="4"></li>
<li class="pl-5"><span id="prompt_strength_container"><label for="prompt_strength_slider">Prompt Strength:</label> <input id="prompt_strength_slider" name="prompt_strength_slider" class="editor-slider" value="80" type="range" min="0" max="99"> <input id="prompt_strength" name="prompt_strength" size="4"><br/></span></li>
<li class="pl-5"><label for="output_format">Output format:</label>
</td></tr>
<tr class="pl-5"><td><label for="num_inference_steps">Inference Steps:</label></td><td> <input id="num_inference_steps" name="num_inference_steps" size="4" value="25" onkeypress="preventNonNumericalInput(event)"></td></tr>
<tr class="pl-5"><td><label for="guidance_scale_slider">Guidance Scale:</label></td><td> <input id="guidance_scale_slider" name="guidance_scale_slider" class="editor-slider" value="75" type="range" min="10" max="500"> <input id="guidance_scale" name="guidance_scale" size="4" pattern="^[0-9\.]+$" onkeypress="preventNonNumericalInput(event)"></td></tr>
<tr id="prompt_strength_container" class="pl-5"><td><label for="prompt_strength_slider">Prompt Strength:</label></td><td> <input id="prompt_strength_slider" name="prompt_strength_slider" class="editor-slider" value="80" type="range" min="0" max="99"> <input id="prompt_strength" name="prompt_strength" size="4" pattern="^[0-9\.]+$" onkeypress="preventNonNumericalInput(event)"><br/></td></tr></span>
<tr class="pl-5"><td><label for="output_format">Output Format:</label></td><td>
<select id="output_format" name="output_format">
<option value="jpeg" selected>jpeg</option>
<option value="png">png</option>
</select>
</li>
<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>
</td></tr>
</li></table>
<br/>
<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>(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="stream_image_progress" name="stream_image_progress" type="checkbox"> <label for="stream_image_progress">Show a live preview <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"> <label for="use_face_correction">Fix incorrect faces and eyes <small>(uses GFPGAN)</small></label></li>
<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 image by 4x with </label>
<select id="upscale_model" name="upscale_model">
<option value="RealESRGAN_x4plus" selected>RealESRGAN_x4plus</option>
<option value="RealESRGAN_x4plus_anime_6B">RealESRGAN_x4plus_anime_6B</option>
</select>
</li>
<li class="pl-5"><input id="show_only_filtered_image" name="show_only_filtered_image" type="checkbox" checked> <label for="show_only_filtered_image">Show only the corrected/upscaled image</label></li>
<br/>
<li><small>The system-related settings have been moved to the top-right corner.</small></li>
</ul>
</div>
<div id="editor-modifiers" class="panel-box">
<button id="modifier-settings-btn" title="Add custom modifiers"><i class="fa fa-gear"></i></button>
<h4 class="collapsible">Image Modifiers (art styles, tags etc)</h4>
<div id="editor-modifiers-entries" class="collapsible-content">
<label for="preview-image">Image Style:</label>
<select id="preview-image" name="preview-image" value="portrait">
<option value="portrait" selected="">Face</option>
<option value="landscape">Landscape</option>
</select>
&nbsp;
<label for="modifier-card-size-slider">Thumbnail Size:</label>
<input id="modifier-card-size-slider" name="modifier-card-size-slider" value="0" type="range" min="-3" max="5">
<div id="editor-modifiers-entries-toolbar">
<label for="preview-image">Image Style:</label>
<select id="preview-image" name="preview-image" value="portrait">
<option value="portrait" selected="">Face</option>
<option value="landscape">Landscape</option>
</select>
&nbsp;
<label for="modifier-card-size-slider">Thumbnail Size:</label>
<input id="modifier-card-size-slider" name="modifier-card-size-slider" value="0" type="range" min="-3" max="5">
</div>
</div>
</div>
</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 "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 "Image Settings" for additional settings like seed, image size, number of images to generate etc.<br/><br/>Enjoy! :)
</div>
<div id="preview-tools">
<button id="clear-all-previews" class="secondaryButton"><i class="fa-solid fa-trash-can"></i> Clear All</button>
@ -210,10 +238,30 @@
</div>
</div>
<div id="save-settings-config" style="display:none">
<div>
<span id="save-settings-config-close-btn">X</span>
<h1>Save Settings Configuration</h1>
<p>Select which settings should be remembered when restarting the browser</p>
<table id="save-settings-config-table">
</table>
</div>
</div>
<div id="modifier-settings-config" style="display:none">
<div>
<span id="modifier-settings-config-close-btn">X</span>
<h1>Modifier Settings</h1>
<p>Set your custom modifiers (one per line)</p>
<textarea id="custom-modifiers-input" placeholder="Enter your custom modifiers, one-per-line"></textarea>
<p><small><b>Tip:</b> You can include special characters like {} () [] and |. You can also put multiple comma-separated phrases in a single line, to make a single modifier that combines all of those.</small></p>
</div>
</div>
<div class="line-separator">&nbsp;</div>
<div id="footer" class="panel-box">
<p>If you found this project useful and want to help keep it alive, please <a href="https://ko-fi.com/cmdr2_stablediffusion_ui" target="_blank"><img src="media/kofi.png" id="coffeeButton"></a> to help cover the cost of development and maintenance! Thank you for your support!</p>
<p>If you found this project useful and want to help keep it alive, please <a href="https://ko-fi.com/cmdr2_stablediffusion_ui" target="_blank"><img src="/media/images/kofi.png" id="coffeeButton"></a> to help cover the cost of development and maintenance! Thank you for your support!</p>
<p>Please feel free to join the <a href="https://discord.com/invite/u9yhsFmEkB" target="_blank">discord community</a> or <a href="https://github.com/cmdr2/stable-diffusion-ui/issues" target="_blank">file an issue</a> if you have any problems or suggestions in using this interface.</p>
<div id="footer-legal">
<p><b>Disclaimer:</b> The authors of this project are not responsible for any content generated using this interface.</p>
@ -224,13 +272,21 @@
</div>
</body>
<script src="media/main.js?v=31"></script>
<script src="media/js/plugins.js?v=1"></script>
<script src="media/js/utils.js?v=5"></script>
<script src="media/js/inpainting-editor.js?v=1"></script>
<script src="media/js/image-modifiers.js?v=3"></script>
<script src="media/js/auto-save.js?v=2.3"></script>
<script src="media/js/main.js?v=5"></script>
<script src="media/js/themes.js?v=2"></script>
<script>
async function init() {
await loadModifiers()
await initSettings()
await getModels()
await getDiskPath()
await getAppConfig()
await getModels()
await loadModifiers()
await loadUIPlugins()
setInterval(healthCheck, HEALTH_PING_INTERVAL * 1000)
healthCheck()

View File

@ -0,0 +1,74 @@
/* Auto-Settings Styling */
#auto_save_settings ~ button {
margin: 5px;
}
#auto_save_settings:not(:checked) ~ button {
display: none;
}
#save-settings-config {
position: absolute;
background: rgba(32, 33, 36, 50%);
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
z-index: 1000;
}
#save-settings-config > div {
background: var(--background-color3);
max-width: 600px;
margin: auto;
margin-top: 50px;
border-radius: 6px;
padding: 30px;
text-align: center;
}
#save-settings-config-table {
margin: auto;
}
#save-settings-config-table th {
padding-top: 15px;
padding-bottom: 5px;
}
#save-settings-config-table td:first-child,
#save-settings-config-table th:first-child {
float: right;
}
#save-settings-config-table td:last-child,
#save-settings-config-table th:last-child {
float: left;
}
#save-settings-config-table td small {
color: rgb(153, 153, 153);
}
#save-settings-config-close-btn {
float: right;
cursor: pointer;
padding: 10px;
transform: translate(50%, -50%) scaleX(130%);
}
#reset-image-settings {
cursor: pointer;
float: right;
padding: 8px;
opacity: 1;
transition: opacity 0.5;
}
.collapsible:not(.active) #reset-image-settings {
display: none;
}
#reset-image-settings.hidden {
opacity: 0;
pointer-events: none;
}

6
ui/media/css/fontawesome-all.min.css vendored Normal file

File diff suppressed because one or more lines are too long

40
ui/media/css/fonts.css Normal file
View File

@ -0,0 +1,40 @@
/* work-sans-regular - latin */
@font-face {
font-family: 'Work Sans';
font-style: normal;
font-weight: 400;
src: local(''),
url('/media/fonts/work-sans-v18-latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
url('/media/fonts/work-sans-v18-latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
}
/* work-sans-600 - latin */
@font-face {
font-family: 'Work Sans';
font-style: normal;
font-weight: 600;
src: local(''),
url('/media/fonts/work-sans-v18-latin-600.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
url('/media/fonts/work-sans-v18-latin-600.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
}
/* work-sans-700 - latin */
@font-face {
font-family: 'Work Sans';
font-style: normal;
font-weight: 700;
src: local(''),
url('/media/fonts/work-sans-v18-latin-700.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
url('/media/fonts/work-sans-v18-latin-700.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
}
/* work-sans-800 - latin */
@font-face {
font-family: 'Work Sans';
font-style: normal;
font-weight: 800;
src: local(''),
url('/media/fonts/work-sans-v18-latin-800.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
url('/media/fonts/work-sans-v18-latin-800.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
}

View File

@ -1,8 +1,16 @@
* {
font-family: Work Sans, Verdana, Geneva, sans-serif;
box-sizing: border-box;
}
html {
position: relative;
}
body {
font-family: Arial, Helvetica, sans-serif;
font-size: 11pt;
background-color: rgb(32, 33, 36);
color: #eee;
background-color: var(--background-color1);
color: var(--text-color);
}
a {
color: rgb(0, 102, 204);
@ -16,12 +24,8 @@ label {
#prompt {
width: 100%;
height: 65pt;
box-sizing: border-box;
}
@media screen and (max-width: 600px) {
#prompt {
width: 95%;
}
font-size: 13px;
margin-bottom: 6px;
}
.image_preview_container {
/* display: none; */
@ -29,7 +33,7 @@ label {
}
.image_clear_btn {
position: absolute;
transform: translateX(-50%) translateY(-35%);
transform: translate(30%, -30%);
background: black;
color: white;
border: 2pt solid #ccc;
@ -41,6 +45,8 @@ label {
height: 16pt;
font-family: Verdana;
font-size: 8pt;
top: 0px;
right: 0px;
}
.settings-box ul {
font-size: 9pt;
@ -71,7 +77,7 @@ label {
}
.imgSeedLabel {
font-size: 0.8em;
background-color: rgb(44, 45, 48);
background-color: var(--background-color2);
border-radius: 3px;
padding: 5px;
}
@ -101,7 +107,7 @@ label {
margin-bottom: 7px;
}
#container {
width: 90%;
width: 95%;
margin-left: auto;
margin-right: auto;
}
@ -121,6 +127,7 @@ label {
}
.settings-box label small {
color: rgb(153, 153, 153);
margin-right: 10px;
}
#preview {
padding: 5px;
@ -143,14 +150,14 @@ label {
}
#makeImage {
flex: 0 0 70px;
background: rgb(80, 0, 185);
border: 2px solid rgb(40, 0, 78);
background: var(--accent-color);
border: var(--make-image-border);
color: rgb(255, 221, 255);
width: 100%;
height: 30pt;
}
#makeImage:hover {
background: rgb(93, 0, 214);
background: hsl(var(--accent-hue), 100%, calc(var(--accent-lightness) + 6%));
}
#stopImage {
flex: 0 0 70px;
@ -167,12 +174,13 @@ label {
}
.flex-container {
display: flex;
width: 100%;
}
.col-50 {
flex: 50%;
}
.col-fixed-10 {
flex: 0 0 380pt;
flex: 0 0 350pt;
}
.col-free {
flex: 1;
@ -194,8 +202,8 @@ label {
padding-right: 5px;
}
.panel-box {
background: rgb(44, 45, 48);
border: 1px solid rgb(47, 49, 53);
background: var(--background-color2);
border: 1px solid var(--background-color3);
border-radius: 7px;
padding: 5px;
margin-bottom: 15px;
@ -234,18 +242,18 @@ img {
height: 8pt;
border-radius: 4pt; */
font-size: 14pt;
color: rgb(128, 87, 0);
color: rgb(200, 139, 0);
/* background-color: rgb(197, 1, 1); */
/* transform: translateY(15%); */
display: inline;
}
#server-status-msg {
color: rgb(128, 87, 0);
color: rgb(200, 139, 0);
padding-left: 2pt;
font-size: 10pt;
}
.preview-prompt {
font-size: 16pt;
font-size: 13pt;
margin-bottom: 10pt;
}
#coffeeButton {
@ -261,6 +269,9 @@ img {
.drawing-board-canvas-wrapper {
background-size: 100% 100%;
}
.drawing-board-controls {
min-width: 273px;
}
.drawing-board-control > button {
background-color: #eee;
border-radius: 3pt;
@ -343,7 +354,7 @@ img {
padding-right: 2pt;
}
#community-links li a {
color: white;
color: var(--text-color);
text-decoration: none;
}
.dropdown {
@ -354,8 +365,8 @@ img {
position: absolute;
z-index: 2;
background: rgb(18, 18, 19);
border: 2px solid rgb(37, 38, 41);
background: var(--background-color4);
border: 2px solid var(--background-color2);
border-radius: 7px;
padding: 5px;
margin-bottom: 15px;
@ -366,7 +377,7 @@ img {
}
.imageTaskContainer {
border: 1px solid #333;
border: 1px solid var(--background-color2);
margin-bottom: 10pt;
padding: 5pt;
border-radius: 5pt;
@ -375,7 +386,7 @@ img {
.taskStatusLabel {
float: left;
font-size: 8pt;
background:rgb(44, 45, 48);
background:var(--background-color2);
border: 1px solid rgb(61, 62, 66);
padding: 2pt 4pt;
border-radius: 2pt;
@ -384,7 +395,12 @@ img {
.activeTaskLabel {
background:rgb(0, 90, 30);
border: 1px solid rgb(0, 75, 19);
color:rgb(204, 255, 217)
color:rgb(222, 253, 230)
}
.waitingTaskLabel {
background:rgb(128, 89, 0);
border: 1px solid rgb(107, 75, 0);
color:rgb(255, 242, 211)
}
.secondaryButton {
background: rgb(132, 8, 0);
@ -410,4 +426,218 @@ img {
}
.img-batch {
display: inline;
}
}
#prompt_from_file {
display: none;
}
#init_image_preview {
max-width: 150px;
max-height: 150px;
object-fit: contain;
border-radius: 6px;
transition: all 1s ease-in-out;
}
#init_image_preview:hover {
max-width: 500px;
max-height: 1000px;
transition: all 1s 0.5s ease-in-out;
}
#init_image_wrapper {
position: relative;
width: fit-content;
}
#init_image_size_box {
position: absolute;
right: 0px;
bottom: 3px;
padding: 3px;
background: black;
color: white;
text-shadow: 0px 0px 4px black;
opacity: 60%;
font-size: 12px;
border-radius: 6px 0px;
}
#editor-settings-entries table td {
padding: 0px;
line-height: 28px;
}
#editor-settings-entries table td:first-child {
float: right;
padding-right: 4px;
white-space: nowrap;
}
#negative_prompt {
width: 100%;
}
button,
input[type="file"],
input[type="checkbox"],
select,
option {
cursor: pointer;
}
input,
select,
textarea {
border-radius: var(--input-border-radius);
padding: 4px;
accent-color: var(--accent-color);
background: var(--input-background-color);
border: var(--input-border-size) solid var(--input-border-color);
color: var(--input-text-color);
font-size: 9pt;
}
input:hover {
accent-color: var(--accent-color-hover);
}
input {
padding: 4px 6px;
}
input:focus,
select:focus,
textarea:focus {
outline: 2px solid var(--accent-color);
}
input[disabled],
select[disabled],
textarea[disabled] {
opacity: 0.5;
}
input[type="file"] {
width: 100%;
padding: 2px;
}
button,
input::file-selector-button {
padding: 2px 4px;
border-radius: 4px;
background: var(--button-color);
color: var(--button-text-color);
border: var(--button-border);
}
input::file-selector-button {
padding: 0px 4px;
height: 19px;
}
@media screen and (max-width: 700px) {
body {
margin: 0px;
}
#container {
margin: 0px;
padding: 10px
}
.flex-container {
flex-direction: column;
}
#preview {
margin: 0px;
padding: 0px;
}
#preview .collapsible-content {
padding: 0px;
}
#preview .collapsible-content {
padding: 0px;
}
.imgItem {
margin-right: 0px;
}
.imgItem img {
height: 100%;
width: 100%;
object-fit: contain;
}
.dropdown-content {
width: auto !important;
transform: none !important;
left: 0px;
right: 0px;
}
}
#promptsFromFileBtn {
font-size: 9pt;
}
#reset-image-settings {
position: relative;
transform: translateY(-13%);
}
.simple-tooltip {
border-radius: 3px;
font-weight: bold;
font-size: 16px;
background-color: var(--background-color3);
visibility: hidden;
opacity: 0;
position: absolute;
white-space: nowrap;
padding: 8px 12px;
transition: 0.3s all;
pointer-events: none;
}
@media (hover: hover) {
:hover > .simple-tooltip {
opacity: 1;
visibility: visible;
}
}
/* position specific */
.simple-tooltip.right {
right: 0px;
top: 50%;
transform: translate(calc(100% - 15%), -50%);
}
:hover > .simple-tooltip.right {
transform: translate(100%, -50%);
}
.simple-tooltip.top {
top: 0px;
left: 50%;
transform: translate(-50%, calc(-100% + 15%));
}
:hover > .simple-tooltip.top {
transform: translate(-50%, -100%);
}
.simple-tooltip.left {
left: 0px;
top: 50%;
transform: translate(calc(-100% + 15%), -50%);
}
:hover > .simple-tooltip.left {
transform: translate(-100%, -50%);
}
.simple-tooltip.bottom {
bottom: 0px;
left: 50%;
transform: translate(-50%, calc(100% - 15%));
}
:hover > .simple-tooltip.bottom {
transform: translate(-50%, 100%);
}

View File

@ -214,3 +214,36 @@
margin-bottom: 0.5em;
vertical-align: middle;
}
#modifier-settings-btn {
float: right;
}
#modifier-settings-config {
position: fixed;
background: rgba(32, 33, 36, 50%);
top: 0px;
left: 0px;
width: 100vw;
height: 100vh;
z-index: 1000;
}
#modifier-settings-config > div {
background: var(--background-color2);
max-width: 600px;
margin: auto;
margin-top: 100px;
border-radius: 6px;
padding: 30px;
text-align: center;
}
#modifier-settings-config-close-btn {
float: right;
cursor: pointer;
padding: 10px;
transform: translate(50%, -50%) scaleX(130%);
}
#modifier-settings-config textarea {
width: 90%;
height: 150px;
}

146
ui/media/css/themes.css Normal file
View File

@ -0,0 +1,146 @@
:root {
--background-color1: rgb(32, 33, 36); /* main parts of the page */
--background-color2: rgb(44, 45, 48); /* main panels */
--background-color3: rgb(47, 49, 53);
--background-color4: rgb(18, 18, 19); /* settings dropdowns */
--accent-hue: 266;
--accent-lightness: 36%;
--accent-lightness-hover: 40%;
--text-color: #eee;
--input-text-color: black;
--input-background-color: #e9e9ed;
--input-border-color: #8f8f9d;
--button-text-color: var(--input-text-color);
--button-color: #e9e9ed;
--button-border: 1px solid #8f8f9d;
/* other */
--input-border-radius: 4px;
--input-border-size: 1px;
--accent-color: hsl(var(--accent-hue), 100%, var(--accent-lightness));
--accent-color-hover: hsl(var(--accent-hue), 100%, var(--accent-lightness-hover));
--make-image-border: 2px solid hsl(var(--accent-hue), 100%, calc(var(--accent-lightness) - 21%));
}
.theme-light {
--background-color1: white;
--background-color2: #dddddd;
--background-color3: #e7e9eb;
--background-color4: #cccccc;
--text-color: black;
--input-text-color: black;
--input-background-color: #f8f9fa;
--input-border-color: grey;
}
.theme-discord {
--background-color1: #36393f;
--background-color2: #2f3136;
--background-color3: #292b2f;
--background-color4: #202225;
--accent-hue: 235;
--accent-lightness: 65%;
--make-image-border: none;
--button-color: var(--accent-color);
--button-border: none;
--input-text-color: #ccc;
--input-border-size: 2px;
--input-background-color: #202225;
--input-border-color: var(--input-background-color);
}
.theme-cool-blue {
--main-hue: 222;
--main-saturation: 18%;
--value-base: 19%;
--value-step: 3%;
--background-color1: hsl(var(--main-hue), var(--main-saturation), var(--value-base));
--background-color2: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (1 * var(--value-step))));
--background-color3: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (2 * var(--value-step))));
--background-color4: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (3 * var(--value-step))));
--accent-hue: 212;
--make-image-border: none;
--button-color: var(--accent-color);
--button-border: none;
--input-border-size: 1px;
--input-background-color: var(--background-color3);
--input-text-color: #ccc;
--input-border-color: var(--background-color4);
}
.theme-blurple {
--main-hue: 235;
--main-saturation: 18%;
--value-base: 16%;
--value-step: 3%;
--background-color1: hsl(var(--main-hue), var(--main-saturation), var(--value-base));
--background-color2: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (1 * var(--value-step))));
--background-color3: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (2 * var(--value-step))));
--background-color4: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (3 * var(--value-step))));
--make-image-border: none;
--button-color: var(--accent-color);
--button-border: none;
--input-border-size: 1px;
--input-background-color: var(--background-color3);
--input-text-color: #ccc;
--input-border-color: var(--background-color4);
}
.theme-super-dark {
--main-hue: 222;
--main-saturation: 18%;
--value-base: 5%;
--value-step: 5%;
--background-color1: hsl(var(--main-hue), var(--main-saturation), var(--value-base));
--background-color2: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) + (1 * var(--value-step))));
--background-color3: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) + (2 * var(--value-step))));
--background-color4: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) + (3 * var(--value-step))));
--make-image-border: none;
--button-color: var(--accent-color);
--button-border: none;
--input-border-size: 0px;
--input-background-color: var(--background-color3);
--input-text-color: #ccc;
--input-border-color: var(--background-color4);
}
.theme-wild {
--main-hue: 128;
--main-saturation: 18%;
--value-base: 20%;
--value-step: 5%;
--background-color1: hsl(var(--main-hue), var(--main-saturation), var(--value-base));
--background-color2: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (1 * var(--value-step))));
--background-color3: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (2 * var(--value-step))));
--background-color4: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (3 * var(--value-step))));
--accent-hue: 212;
--make-image-border: none;
--button-color: var(--accent-color);
--button-border: none;
--input-border-size: 1px;
--input-background-color: hsl(222, var(--main-saturation), calc(var(--value-base) - (2 * var(--value-step))));
--input-text-color: red;
--input-border-color: green;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 466 B

After

Width:  |  Height:  |  Size: 466 B

View File

Before

Width:  |  Height:  |  Size: 973 B

After

Width:  |  Height:  |  Size: 973 B

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

291
ui/media/js/auto-save.js Normal file
View File

@ -0,0 +1,291 @@
// Saving settings
let saveSettingsConfigTable = document.getElementById("save-settings-config-table")
let saveSettingsConfigOverlay = document.getElementById("save-settings-config")
let resetImageSettingsButton = document.getElementById("reset-image-settings")
const SETTINGS_KEY = "user_settings_v2"
const SETTINGS = {} // key=id. dict initialized in initSettings. { element, default, value, ignore }
const SETTINGS_IDS_LIST = [
"prompt",
"seed",
"random_seed",
"num_outputs_total",
"num_outputs_parallel",
"stable_diffusion_model",
"sampler",
"width",
"height",
"num_inference_steps",
"guidance_scale",
"prompt_strength",
"output_format",
"negative_prompt",
"stream_image_progress",
"use_face_correction",
"use_upscale",
"show_only_filtered_image",
"upscale_model",
"preview-image",
"modifier-card-size-slider",
"theme",
"save_to_disk",
"diskPath",
"sound_toggle",
"turbo",
"use_cpu",
"use_full_precision",
"auto_save_settings"
]
const IGNORE_BY_DEFAULT = [
"prompt"
]
const SETTINGS_SECTIONS = [ // gets the "keys" property filled in with an ordered list of settings in this section via initSettings
{ id: "editor-inputs", name: "Prompt" },
{ id: "editor-settings", name: "Image Settings" },
{ id: "system-settings", name: "System Settings" },
{ id: "container", name: "Other" }
]
async function initSettings() {
SETTINGS_IDS_LIST.forEach(id => {
var element = document.getElementById(id)
var label = document.querySelector(`label[for='${element.id}']`)
SETTINGS[id] = {
key: id,
element: element,
label: getSettingLabel(element),
default: getSetting(element),
value: getSetting(element),
ignore: IGNORE_BY_DEFAULT.includes(id)
}
element.addEventListener("input", settingChangeHandler)
element.addEventListener("change", settingChangeHandler)
})
var unsorted_settings_ids = [...SETTINGS_IDS_LIST]
SETTINGS_SECTIONS.forEach(section => {
var name = section.name
var element = document.getElementById(section.id)
var children = Array.from(element.querySelectorAll(unsorted_settings_ids.map(id => `#${id}`).join(",")))
section.keys = []
children.forEach(e => {
section.keys.push(e.id)
})
unsorted_settings_ids = unsorted_settings_ids.filter(id => children.find(e => e.id == id) == undefined)
})
loadSettings()
}
function getSetting(element) {
if (typeof element === "string" || element instanceof String) {
element = SETTINGS[element].element
}
if (element.type == "checkbox") {
return element.checked
}
return element.value
}
function setSetting(element, value) {
if (typeof element === "string" || element instanceof String) {
element = SETTINGS[element].element
}
SETTINGS[element.id].value = value
if (getSetting(element) == value) {
return // no setting necessary
}
if (element.type == "checkbox") {
element.checked = value
}
else {
element.value = value
}
element.dispatchEvent(new Event("input"))
element.dispatchEvent(new Event("change"))
}
function saveSettings() {
var saved_settings = Object.values(SETTINGS).map(setting => {
return {
key: setting.key,
value: setting.value,
ignore: setting.ignore
}
})
localStorage.setItem(SETTINGS_KEY, JSON.stringify(saved_settings))
}
var CURRENTLY_LOADING_SETTINGS = false
function loadSettings() {
var saved_settings_text = localStorage.getItem(SETTINGS_KEY)
if (saved_settings_text) {
var saved_settings = JSON.parse(saved_settings_text)
if (saved_settings.find(s => s.key == "auto_save_settings").value == false) {
setSetting("auto_save_settings", false)
return
}
CURRENTLY_LOADING_SETTINGS = true
saved_settings.map(saved_setting => {
var setting = SETTINGS[saved_setting.key]
if (setting === undefined) {
return
}
setting.ignore = saved_setting.ignore
if (!setting.ignore) {
setting.value = saved_setting.value
setSetting(setting.element, setting.value)
}
})
CURRENTLY_LOADING_SETTINGS = false
}
else {
CURRENTLY_LOADING_SETTINGS = true
tryLoadOldSettings();
CURRENTLY_LOADING_SETTINGS = false
saveSettings()
}
}
function loadDefaultSettingsSection(section_id) {
CURRENTLY_LOADING_SETTINGS = true
var section = SETTINGS_SECTIONS.find(s => s.id == section_id);
section.keys.forEach(key => {
var setting = SETTINGS[key];
setting.value = setting.default
setSetting(setting.element, setting.value)
})
CURRENTLY_LOADING_SETTINGS = false
saveSettings()
}
function settingChangeHandler(event) {
if (!CURRENTLY_LOADING_SETTINGS) {
var element = event.target
var value = getSetting(element)
if (value != SETTINGS[element.id].value) {
SETTINGS[element.id].value = value
saveSettings()
}
}
}
function getSettingLabel(element) {
var labelElement = document.querySelector(`label[for='${element.id}']`)
var label = labelElement?.innerText || element.id
var truncate_length = 30
if (label.includes(" (")) {
label = label.substring(0, label.indexOf(" ("))
}
if (label.length > truncate_length) {
label = label.substring(0, truncate_length - 3) + "..."
}
label = label.replace("", "")
label = label.replace("", "")
return label
}
function fillSaveSettingsConfigTable() {
saveSettingsConfigTable.textContent = ""
SETTINGS_SECTIONS.forEach(section => {
var section_row = `<tr><th>${section.name}</th><td></td></tr>`
saveSettingsConfigTable.insertAdjacentHTML("beforeend", section_row)
section.keys.forEach(key => {
var setting = SETTINGS[key]
var element = setting.element
var checkbox_id = `shouldsave_${element.id}`
var is_checked = setting.ignore ? "" : "checked"
var value = setting.value
var value_truncate_length = 30
if ((typeof value === "string" || value instanceof String) && value.length > value_truncate_length) {
value = value.substring(0, value_truncate_length - 3) + "..."
}
var newrow = `<tr><td><label for="${checkbox_id}">${setting.label}</label></td><td><input id="${checkbox_id}" name="${checkbox_id}" ${is_checked} type="checkbox" ></td><td><small>(${value})</small></td></tr>`
saveSettingsConfigTable.insertAdjacentHTML("beforeend", newrow)
var checkbox = document.getElementById(checkbox_id)
checkbox.addEventListener("input", event => {
setting.ignore = !checkbox.checked
saveSettings()
})
})
})
}
document.getElementById("save-settings-config-close-btn").addEventListener('click', () => {
saveSettingsConfigOverlay.style.display = 'none'
})
document.getElementById("configureSettingsSaveBtn").addEventListener('click', () => {
fillSaveSettingsConfigTable()
saveSettingsConfigOverlay.style.display = 'block'
})
saveSettingsConfigOverlay.addEventListener('click', (event) => {
if (event.target.id == saveSettingsConfigOverlay.id) {
saveSettingsConfigOverlay.style.display = 'none'
}
})
document.getElementById("save-settings-config-close-btn").addEventListener('click', () => {
saveSettingsConfigOverlay.style.display = 'none'
})
resetImageSettingsButton.addEventListener('click', event => {
loadDefaultSettingsSection("editor-settings");
event.stopPropagation()
})
function tryLoadOldSettings() {
console.log("Loading old user settings")
// load v1 auto-save.js settings
var old_map = {
"guidance_scale_slider": "guidance_scale",
"prompt_strength_slider": "prompt_strength"
}
var settings_key_v1 = "user_settings"
var saved_settings_text = localStorage.getItem(settings_key_v1)
if (saved_settings_text) {
var saved_settings = JSON.parse(saved_settings_text)
Object.keys(saved_settings.should_save).forEach(key => {
key = key in old_map ? old_map[key] : key
SETTINGS[key].ignore = !saved_settings.should_save[key]
});
Object.keys(saved_settings.values).forEach(key => {
key = key in old_map ? old_map[key] : key
var setting = SETTINGS[key]
if (!setting.ignore) {
setting.value = saved_settings.values[key]
setSetting(setting.element, setting.value)
}
});
localStorage.removeItem(settings_key_v1)
}
// load old individually stored items
var individual_settings_map = { // maps old localStorage-key to new SETTINGS-key
"soundEnabled": "sound_toggle",
"saveToDisk": "save_to_disk",
"useCPU": "use_cpu",
"useFullPrecision": "use_full_precision",
"useTurboMode": "turbo",
"diskPath": "diskPath",
"useFaceCorrection": "use_face_correction",
"useUpscaling": "use_upscale",
"showOnlyFilteredImage": "show_only_filtered_image",
"streamImageProgress": "stream_image_progress",
"outputFormat": "output_format",
"autoSaveSettings": "auto_save_settings",
};
Object.keys(individual_settings_map).forEach(localStorageKey => {
var localStorageValue = localStorage.getItem(localStorageKey);
if (localStorageValue !== null) {
var setting = SETTINGS[individual_settings_map[localStorageKey]]
if (setting == null || setting == undefined) {
return
}
if (setting.element.type == "checkbox" && (typeof localStorageValue === "string" || localStorageValue instanceof String)) {
localStorageValue = localStorageValue == "true"
}
setting.value = localStorageValue
setSetting(setting.element, setting.value)
localStorage.removeItem(localStorageKey);
}
})
}

View File

@ -0,0 +1,294 @@
let activeTags = []
let modifiers = []
let customModifiersGroupElement = undefined
let editorModifierEntries = document.querySelector('#editor-modifiers-entries')
let editorModifierTagsList = document.querySelector('#editor-inputs-tags-list')
let editorTagsContainer = document.querySelector('#editor-inputs-tags-container')
let modifierCardSizeSlider = document.querySelector('#modifier-card-size-slider')
let previewImageField = document.querySelector('#preview-image')
let modifierSettingsBtn = document.querySelector('#modifier-settings-btn')
let modifierSettingsOverlay = document.querySelector('#modifier-settings-config')
let customModifiersTextBox = document.querySelector('#custom-modifiers-input')
let customModifierEntriesToolbar = document.querySelector('#editor-modifiers-entries-toolbar')
const modifierThumbnailPath = 'media/modifier-thumbnails'
const activeCardClass = 'modifier-card-active'
const CUSTOM_MODIFIERS_KEY = "customModifiers"
function createModifierCard(name, previews) {
const modifierCard = document.createElement('div')
modifierCard.className = 'modifier-card'
modifierCard.innerHTML = `
<div class="modifier-card-overlay"></div>
<div class="modifier-card-image-container">
<div class="modifier-card-image-overlay">+</div>
<p class="modifier-card-error-label"></p>
<img onerror="this.remove()" alt="Modifier Image" class="modifier-card-image">
</div>
<div class="modifier-card-container">
<div class="modifier-card-label"><p></p></div>
</div>`
const image = modifierCard.querySelector('.modifier-card-image')
const errorText = modifierCard.querySelector('.modifier-card-error-label')
const label = modifierCard.querySelector('.modifier-card-label')
errorText.innerText = 'No Image'
if (typeof previews == 'object') {
image.src = previews[0]; // portrait
image.setAttribute('preview-type', 'portrait')
} else {
image.remove()
}
const maxLabelLength = 30
const nameWithoutBy = name.replace('by ', '')
if(nameWithoutBy.length <= maxLabelLength) {
label.querySelector('p').innerText = nameWithoutBy
} else {
const tooltipText = document.createElement('span')
tooltipText.className = 'tooltip-text'
tooltipText.innerText = name
label.classList.add('tooltip')
label.appendChild(tooltipText)
label.querySelector('p').innerText = nameWithoutBy.substring(0, maxLabelLength) + '...'
}
return modifierCard
}
function createModifierGroup(modifierGroup, initiallyExpanded) {
const title = modifierGroup.category
const modifiers = modifierGroup.modifiers
const titleEl = document.createElement('h5')
titleEl.className = 'collapsible'
titleEl.innerText = title
const modifiersEl = document.createElement('div')
modifiersEl.classList.add('collapsible-content', 'editor-modifiers-leaf')
if (initiallyExpanded === true) {
titleEl.className += ' active'
modifiersEl.style.display = 'block'
}
modifiers.forEach(modObj => {
const modifierName = modObj.modifier
const modifierPreviews = modObj?.previews?.map(preview => `${modifierThumbnailPath}/${preview.path}`)
const modifierCard = createModifierCard(modifierName, modifierPreviews)
if(typeof modifierCard == 'object') {
modifiersEl.appendChild(modifierCard)
modifierCard.addEventListener('click', () => {
if (activeTags.map(x => x.name).includes(modifierName)) {
// remove modifier from active array
activeTags = activeTags.filter(x => x.name != modifierName)
modifierCard.classList.remove(activeCardClass)
modifierCard.querySelector('.modifier-card-image-overlay').innerText = '+'
} else {
// add modifier to active array
activeTags.push({
'name': modifierName,
'element': modifierCard.cloneNode(true),
'originElement': modifierCard,
'previews': modifierPreviews
})
modifierCard.classList.add(activeCardClass)
modifierCard.querySelector('.modifier-card-image-overlay').innerText = '-'
}
refreshTagsList()
})
}
})
let brk = document.createElement('br')
brk.style.clear = 'both'
modifiersEl.appendChild(brk)
let e = document.createElement('div')
e.appendChild(titleEl)
e.appendChild(modifiersEl)
editorModifierEntries.insertBefore(e, customModifierEntriesToolbar.nextSibling)
return e
}
async function loadModifiers() {
try {
let res = await fetch('/get/modifiers')
if (res.status === 200) {
res = await res.json()
modifiers = res; // update global variable
res.reverse()
res.forEach((modifierGroup, idx) => {
createModifierGroup(modifierGroup, idx === res.length - 1)
})
createCollapsibles(editorModifierEntries)
}
} catch (e) {
console.log('error fetching modifiers', e)
}
loadCustomModifiers()
}
function refreshTagsList() {
editorModifierTagsList.innerHTML = ''
if (activeTags.length == 0) {
editorTagsContainer.style.display = 'none'
return
} else {
editorTagsContainer.style.display = 'block'
}
activeTags.forEach((tag, index) => {
tag.element.querySelector('.modifier-card-image-overlay').innerText = '-'
tag.element.classList.add('modifier-card-tiny')
editorModifierTagsList.appendChild(tag.element)
tag.element.addEventListener('click', () => {
let idx = activeTags.indexOf(tag)
if (idx !== -1) {
activeTags[idx].originElement.classList.remove(activeCardClass)
activeTags[idx].originElement.querySelector('.modifier-card-image-overlay').innerText = '+'
activeTags.splice(idx, 1)
refreshTagsList()
}
})
})
let brk = document.createElement('br')
brk.style.clear = 'both'
editorModifierTagsList.appendChild(brk)
}
function changePreviewImages(val) {
const previewImages = document.querySelectorAll('.modifier-card-image-container img')
let previewArr = []
modifiers.map(x => x.modifiers).forEach(x => previewArr.push(...x.map(m => m.previews)))
previewArr = previewArr.map(x => {
let obj = {}
x.forEach(preview => {
obj[preview.name] = preview.path
})
return obj
})
previewImages.forEach(previewImage => {
const currentPreviewType = previewImage.getAttribute('preview-type')
const relativePreviewPath = previewImage.src.split(modifierThumbnailPath + '/').pop()
const previews = previewArr.find(preview => relativePreviewPath == preview[currentPreviewType])
if(typeof previews == 'object') {
let preview = null
if (val == 'portrait') {
preview = previews.portrait
}
else if (val == 'landscape') {
preview = previews.landscape
}
if(preview != null) {
previewImage.src = `${modifierThumbnailPath}/${preview}`
previewImage.setAttribute('preview-type', val)
}
}
})
}
function resizeModifierCards(val) {
const cardSizePrefix = 'modifier-card-size_'
const modifierCardClass = 'modifier-card'
const modifierCards = document.querySelectorAll(`.${modifierCardClass}`)
const cardSize = n => `${cardSizePrefix}${n}`
modifierCards.forEach(card => {
// remove existing size classes
const classes = card.className.split(' ').filter(c => !c.startsWith(cardSizePrefix))
card.className = classes.join(' ').trim()
if(val != 0) {
card.classList.add(cardSize(val))
}
})
}
modifierCardSizeSlider.onchange = () => resizeModifierCards(modifierCardSizeSlider.value)
previewImageField.onchange = () => changePreviewImages(previewImageField.value)
modifierSettingsBtn.addEventListener('click', function() {
modifierSettingsOverlay.style.display = 'block'
})
document.getElementById("modifier-settings-config-close-btn").addEventListener('click', () => {
modifierSettingsOverlay.style.display = 'none'
})
modifierSettingsOverlay.addEventListener('click', (event) => {
if (event.target.id == modifierSettingsOverlay.id) {
modifierSettingsOverlay.style.display = 'none'
}
})
function saveCustomModifiers() {
localStorage.setItem(CUSTOM_MODIFIERS_KEY, customModifiersTextBox.value.trim())
loadCustomModifiers()
}
function loadCustomModifiers() {
let customModifiers = localStorage.getItem(CUSTOM_MODIFIERS_KEY, '')
customModifiersTextBox.value = customModifiers
if (customModifiersGroupElement !== undefined) {
customModifiersGroupElement.remove()
}
if (customModifiers && customModifiers.trim() !== '') {
customModifiers = customModifiers.split('\n')
customModifiers = customModifiers.filter(m => m.trim() !== '')
customModifiers = customModifiers.map(function(m) {
return {
"modifier": m
}
})
let customGroup = {
'category': 'Custom Modifiers',
'modifiers': customModifiers
}
customModifiersGroupElement = createModifierGroup(customGroup, true)
createCollapsibles(customModifiersGroupElement)
}
}
customModifiersTextBox.addEventListener('change', saveCustomModifiers)

View File

@ -0,0 +1,41 @@
const INPAINTING_EDITOR_SIZE = 450
let inpaintingEditorContainer = document.querySelector('#inpaintingEditor')
let inpaintingEditor = new DrawingBoard.Board('inpaintingEditor', {
color: "#ffffff",
background: false,
size: 30,
webStorage: false,
controls: [{'DrawingMode': {'filler': false}}, 'Size', 'Navigation']
})
let inpaintingEditorCanvasBackground = document.querySelector('.drawing-board-canvas-wrapper')
function resizeInpaintingEditor(widthValue, heightValue) {
if (widthValue === heightValue) {
widthValue = INPAINTING_EDITOR_SIZE
heightValue = INPAINTING_EDITOR_SIZE
} else if (widthValue > heightValue) {
heightValue = (heightValue / widthValue) * INPAINTING_EDITOR_SIZE
widthValue = INPAINTING_EDITOR_SIZE
} else {
widthValue = (widthValue / heightValue) * INPAINTING_EDITOR_SIZE
heightValue = INPAINTING_EDITOR_SIZE
}
if (inpaintingEditor.opts.aspectRatio === (widthValue / heightValue).toFixed(3)) {
// Same ratio, don't reset the canvas.
return
}
inpaintingEditor.opts.aspectRatio = (widthValue / heightValue).toFixed(3)
inpaintingEditorContainer.style.width = widthValue + 'px'
inpaintingEditorContainer.style.height = heightValue + 'px'
inpaintingEditor.opts.enlargeYourContainer = true
inpaintingEditor.opts.size = inpaintingEditor.ctx.lineWidth
inpaintingEditor.resize()
inpaintingEditor.ctx.lineCap = "round"
inpaintingEditor.ctx.lineJoin = "round"
inpaintingEditor.ctx.lineWidth = inpaintingEditor.opts.size
inpaintingEditor.setColor(inpaintingEditor.opts.color)
}

1287
ui/media/js/main.js Normal file

File diff suppressed because it is too large Load Diff

47
ui/media/js/plugins.js Normal file
View File

@ -0,0 +1,47 @@
const PLUGIN_API_VERSION = "1.0"
const PLUGINS = {
/**
* Register new buttons to show on each output image.
*
* Example:
* PLUGINS['IMAGE_INFO_BUTTONS'].push({
* text: 'Make a Similar Image',
* on_click: function(origRequest, image) {
* let newTaskRequest = getCurrentUserRequest()
* newTaskRequest.reqBody = Object.assign({}, origRequest, {
* init_image: image.src,
* prompt_strength: 0.7,
* seed: Math.floor(Math.random() * 10000000)
* })
* newTaskRequest.seed = newTaskRequest.reqBody.seed
* createTask(newTaskRequest)
* },
* filter: function(origRequest, image) {
* // this is an optional function. return true/false to show/hide the button
* // if this function isn't set, the button will always be visible
* return true
* }
* })
*/
IMAGE_INFO_BUTTONS: []
}
async function loadUIPlugins() {
try {
let res = await fetch('/get/ui_plugins')
if (res.status === 200) {
res = await res.json()
res.forEach(pluginPath => {
let script = document.createElement('script')
script.src = pluginPath + '?t=' + Date.now()
console.log('loading plugin', pluginPath)
document.head.appendChild(script)
})
}
} catch (e) {
console.log('error fetching plugin paths', e)
}
}

73
ui/media/js/themes.js Normal file
View File

@ -0,0 +1,73 @@
const themeField = document.getElementById("theme");
var DEFAULT_THEME = {};
var THEMES = []; // initialized in initTheme from data in css
function getThemeName(theme) {
theme = theme.replace("theme-", "");
theme = theme.split("-").map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
return theme;
}
// init themefield
function initTheme() {
Array.from(document.styleSheets)
.filter(sheet => sheet.href?.startsWith(window.location.origin))
.flatMap(sheet => Array.from(sheet.cssRules))
.forEach(rule => {
var selector = rule.selectorText; // TODO: also do selector == ":root", re-run un-set props
if (selector && selector.startsWith(".theme-")) {
var theme_key = selector.substring(1);
THEMES.push({
key: theme_key,
name: getThemeName(theme_key),
rule: rule
})
}
if (selector && selector == ":root") {
DEFAULT_THEME = {
key: "theme-default",
name: "Default",
rule: rule
};
}
});
THEMES.forEach(theme => {
var new_option = document.createElement("option");
new_option.setAttribute("value", theme.key);
new_option.innerText = theme.name;
themeField.appendChild(new_option);
});
// setup the style transitions a second after app initializes, so initial style is instant
setTimeout(() => {
var body = document.querySelector("body");
var style = document.createElement('style');
style.innerHTML = "* { transition: background 0.5s, color 0.5s, background-color 0.5s; }";
body.appendChild(style);
}, 1000);
}
initTheme();
function themeFieldChanged() {
var theme_key = themeField.value;
var body = document.querySelector("body");
body.classList.remove(...THEMES.map(theme => theme.key));
body.classList.add(theme_key);
//
body.style = "";
var theme = THEMES.find(t => t.key == theme_key);
if (theme) {
// refresh variables incase they are back referencing
Array.from(DEFAULT_THEME.rule.style)
.filter(cssVariable => !Array.from(theme.rule.style).includes(cssVariable))
.forEach(cssVariable => {
body.style.setProperty(cssVariable, DEFAULT_THEME.rule.style.getPropertyValue(cssVariable));
});
}
}
themeField.addEventListener('change', themeFieldChanged);

356
ui/media/js/utils.js Normal file
View File

@ -0,0 +1,356 @@
// 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
}
}
/* Panel Stuff */
// true = open
var COLLAPSIBLES_INITIALIZED = false;
const COLLAPSIBLES_KEY = "collapsibles";
const COLLAPSIBLE_PANELS = []; // filled in by createCollapsibles with all the elements matching .collapsible
// on-init call this for any panels that are marked open
function toggleCollapsible(element) {
var collapsibleHeader = element.querySelector(".collapsible");
var handle = element.querySelector(".collapsible-handle");
collapsibleHeader.classList.toggle("active")
let content = getNextSibling(collapsibleHeader, '.collapsible-content')
if (content.style.display === "block") {
content.style.display = "none"
handle.innerHTML = '&#x2795;' // plus
} else {
content.style.display = "block"
handle.innerHTML = '&#x2796;' // minus
}
if (COLLAPSIBLES_INITIALIZED && COLLAPSIBLE_PANELS.includes(element)) {
saveCollapsibles()
}
}
function saveCollapsibles() {
var values = {}
COLLAPSIBLE_PANELS.forEach(element => {
var value = element.querySelector(".collapsible").className.indexOf("active") !== -1
values[element.id] = value
})
localStorage.setItem(COLLAPSIBLES_KEY, JSON.stringify(values))
}
function createCollapsibles(node) {
var save = false
if (!node) {
node = document
save = true
}
let collapsibles = node.querySelectorAll(".collapsible")
collapsibles.forEach(function(c) {
if (save && c.parentElement.id) {
COLLAPSIBLE_PANELS.push(c.parentElement)
}
let handle = document.createElement('span')
handle.className = 'collapsible-handle'
if (c.className.indexOf('active') !== -1) {
handle.innerHTML = '&#x2796;' // minus
} else {
handle.innerHTML = '&#x2795;' // plus
}
c.insertBefore(handle, c.firstChild)
c.addEventListener('click', function() {
toggleCollapsible(c.parentElement)
})
})
if (save) {
var saved = localStorage.getItem(COLLAPSIBLES_KEY)
if (!saved) {
saved = tryLoadOldCollapsibles();
}
if (!saved) {
saveCollapsibles()
saved = localStorage.getItem(COLLAPSIBLES_KEY)
}
var values = JSON.parse(saved)
COLLAPSIBLE_PANELS.forEach(element => {
var value = element.querySelector(".collapsible").className.indexOf("active") !== -1
if (values[element.id] != value) {
toggleCollapsible(element)
}
})
COLLAPSIBLES_INITIALIZED = true
}
}
function tryLoadOldCollapsibles() {
var old_map = {
"advancedPanelOpen": "editor-settings",
"modifiersPanelOpen": "editor-modifiers",
"negativePromptPanelOpen": "editor-inputs-prompt"
};
if (localStorage.getItem(Object.keys(old_map)[0])) {
var result = {};
Object.keys(old_map).forEach(key => {
var value = localStorage.getItem(key);
if (value !== null) {
result[old_map[key]] = value == true || value == "true"
localStorage.removeItem(key)
}
});
result = JSON.stringify(result)
localStorage.setItem(COLLAPSIBLES_KEY, result)
return result
}
return null;
}
function permute(arr) {
let permutations = []
let n = arr.length
let n_permutations = Math.pow(2, n)
for (let i = 0; i < n_permutations; i++) {
let perm = []
let mask = Number(i).toString(2).padStart(n, '0')
for (let idx = 0; idx < mask.length; idx++) {
if (mask[idx] === '1' && arr[idx].trim() !== '') {
perm.push(arr[idx])
}
}
if (perm.length > 0) {
permutations.push(perm)
}
}
return permutations
}
// https://stackoverflow.com/a/8212878
function millisecondsToStr(milliseconds) {
function numberEnding (number) {
return (number > 1) ? 's' : ''
}
var temp = Math.floor(milliseconds / 1000)
var hours = Math.floor((temp %= 86400) / 3600)
var s = ''
if (hours) {
s += hours + ' hour' + numberEnding(hours) + ' '
}
var minutes = Math.floor((temp %= 3600) / 60)
if (minutes) {
s += minutes + ' minute' + numberEnding(minutes) + ' '
}
var seconds = temp % 60
if (!hours && minutes < 4 && seconds) {
s += seconds + ' second' + numberEnding(seconds)
}
return s
}
// https://rosettacode.org/wiki/Brace_expansion#JavaScript
function BraceExpander() {
'use strict'
// Index of any closing brace matching the opening
// brace at iPosn,
// with the indices of any immediately-enclosed commas.
function bracePair(tkns, iPosn, iNest, lstCommas) {
if (iPosn >= tkns.length || iPosn < 0) return null;
var t = tkns[iPosn],
n = (t === '{') ? (
iNest + 1
) : (t === '}' ? (
iNest - 1
) : iNest),
lst = (t === ',' && iNest === 1) ? (
lstCommas.concat(iPosn)
) : lstCommas;
return n ? bracePair(tkns, iPosn + 1, n, lst) : {
close: iPosn,
commas: lst
};
}
// Parse of a SYNTAGM subtree
function andTree(dctSofar, tkns) {
if (!tkns.length) return [dctSofar, []];
var dctParse = dctSofar ? dctSofar : {
fn: and,
args: []
},
head = tkns[0],
tail = head ? tkns.slice(1) : [],
dctBrace = head === '{' ? bracePair(
tkns, 0, 0, []
) : null,
lstOR = dctBrace && (
dctBrace.close
) && dctBrace.commas.length ? (
splitAt(dctBrace.close + 1, tkns)
) : null;
return andTree({
fn: and,
args: dctParse.args.concat(
lstOR ? (
orTree(dctParse, lstOR[0], dctBrace.commas)
) : head
)
}, lstOR ? (
lstOR[1]
) : tail);
}
// Parse of a PARADIGM subtree
function orTree(dctSofar, tkns, lstCommas) {
if (!tkns.length) return [dctSofar, []];
var iLast = lstCommas.length;
return {
fn: or,
args: splitsAt(
lstCommas, tkns
).map(function (x, i) {
var ts = x.slice(
1, i === iLast ? (
-1
) : void 0
);
return ts.length ? ts : [''];
}).map(function (ts) {
return ts.length > 1 ? (
andTree(null, ts)[0]
) : ts[0];
})
};
}
// List of unescaped braces and commas, and remaining strings
function tokens(str) {
// Filter function excludes empty splitting artefacts
var toS = function (x) {
return x.toString();
};
return str.split(/(\\\\)/).filter(toS).reduce(function (a, s) {
return a.concat(s.charAt(0) === '\\' ? s : s.split(
/(\\*[{,}])/
).filter(toS));
}, []);
}
// PARSE TREE OPERATOR (1 of 2)
// Each possible head * each possible tail
function and(args) {
var lng = args.length,
head = lng ? args[0] : null,
lstHead = "string" === typeof head ? (
[head]
) : head;
return lng ? (
1 < lng ? lstHead.reduce(function (a, h) {
return a.concat(
and(args.slice(1)).map(function (t) {
return h + t;
})
);
}, []) : lstHead
) : [];
}
// PARSE TREE OPERATOR (2 of 2)
// Each option flattened
function or(args) {
return args.reduce(function (a, b) {
return a.concat(b);
}, []);
}
// One list split into two (first sublist length n)
function splitAt(n, lst) {
return n < lst.length + 1 ? [
lst.slice(0, n), lst.slice(n)
] : [lst, []];
}
// One list split into several (sublist lengths [n])
function splitsAt(lstN, lst) {
return lstN.reduceRight(function (a, x) {
return splitAt(x, a[0]).concat(a.slice(1));
}, [lst]);
}
// Value of the parse tree
function evaluated(e) {
return typeof e === 'string' ? e :
e.fn(e.args.map(evaluated));
}
// JSON prettyprint (for parse tree, token list etc)
function pp(e) {
return JSON.stringify(e, function (k, v) {
return typeof v === 'function' ? (
'[function ' + v.name + ']'
) : v;
}, 2)
}
// ----------------------- MAIN ------------------------
// s -> [s]
this.expand = function(s) {
// BRACE EXPRESSION PARSED
var dctParse = andTree(null, tokens(s))[0];
// ABSTRACT SYNTAX TREE LOGGED
// console.log(pp(dctParse));
// AST EVALUATED TO LIST OF STRINGS
return evaluated(dctParse);
}
}
function asyncDelay(timeout) {
return new Promise(function(resolve, reject) {
setTimeout(resolve, timeout, true)
})
}
function preventNonNumericalInput(e) {
e = e || window.event;
let charCode = (typeof e.which == "undefined") ? e.keyCode : e.which;
let charStr = String.fromCharCode(charCode);
let re = e.target.getAttribute('pattern') || '^[0-9]+$'
re = new RegExp(re)
if (!charStr.match(re)) {
e.preventDefault();
}
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -82,15 +82,16 @@ except:
def load_model_ckpt(ckpt_to_use, device_to_use='cuda', turbo=False, unet_bs_to_use=1, precision_to_use='autocast'):
global ckpt_file, model, modelCS, modelFS, model_is_half, device, unet_bs, precision, model_fs_is_half
ckpt_file = ckpt_to_use
device = device_to_use if has_valid_gpu else 'cpu'
precision = precision_to_use if not force_full_precision else 'full'
unet_bs = unet_bs_to_use
unload_model()
if device == 'cpu':
precision = 'full'
sd = load_model_from_config(f"{ckpt_file}.ckpt")
sd = load_model_from_config(f"{ckpt_to_use}.ckpt")
li, lo = [], []
for key, value in sd.items():
sp = key.split(".")
@ -137,8 +138,22 @@ def load_model_ckpt(ckpt_to_use, device_to_use='cuda', turbo=False, unet_bs_to_u
model_is_half = False
model_fs_is_half = False
ckpt_file = ckpt_to_use
print('loaded ', ckpt_file, 'to', device, 'precision', precision)
def unload_model():
global model, modelCS, modelFS
if model is not None:
del model
del modelCS
del modelFS
model = None
modelCS = None
modelFS = None
def load_model_gfpgan(gfpgan_to_use):
global gfpgan_file, model_gfpgan
@ -182,6 +197,35 @@ def load_model_real_esrgan(real_esrgan_to_use):
print('loaded ', real_esrgan_to_use, 'to', device, 'precision', precision)
def get_base_path(disk_path, session_id, prompt, img_id, ext, suffix=None):
if disk_path is None: return None
if session_id is None: return None
if ext is None: raise Exception('Missing ext')
session_out_path = os.path.join(disk_path, session_id)
os.makedirs(session_out_path, exist_ok=True)
prompt_flattened = filename_regex.sub('_', prompt)[:50]
if suffix is not None:
return os.path.join(session_out_path, f"{prompt_flattened}_{img_id}_{suffix}.{ext}")
return os.path.join(session_out_path, f"{prompt_flattened}_{img_id}.{ext}")
def apply_filters(filter_name, image_data):
print(f'Applying filter {filter_name}...')
gc()
if filter_name == 'gfpgan':
_, _, output = model_gfpgan.enhance(image_data[:,:,::-1], has_aligned=False, only_center_face=False, paste_back=True)
image_data = output[:,:,::-1]
if filter_name == 'real_esrgan':
output, _ = model_real_esrgan.enhance(image_data[:,:,::-1])
image_data = output[:,:,::-1]
return image_data
def mk_img(req: Request):
try:
yield from do_mk_img(req)
@ -223,8 +267,9 @@ def do_mk_img(req: Request):
# to the ckpt file (without the extension).
needs_model_reload = False
if ckpt_file != req.use_stable_diffusion_model:
ckpt_file = req.use_stable_diffusion_model
ckpt_to_use = ckpt_file
if ckpt_to_use != req.use_stable_diffusion_model:
ckpt_to_use = req.use_stable_diffusion_model
needs_model_reload = True
model.turbo = req.turbo
@ -233,8 +278,7 @@ def do_mk_img(req: Request):
device = 'cpu'
if model_is_half:
del model, modelCS, modelFS
load_model_ckpt(ckpt_file, device)
load_model_ckpt(ckpt_to_use, device)
needs_model_reload = False
load_model_gfpgan(gfpgan_file)
@ -247,8 +291,7 @@ def do_mk_img(req: Request):
if (precision == 'autocast' and (req.use_full_precision or not model_is_half)) or \
(precision == 'full' and not req.use_full_precision and not force_full_precision):
del model, modelCS, modelFS
load_model_ckpt(ckpt_file, device, req.turbo, unet_bs, ('full' if req.use_full_precision else 'autocast'))
load_model_ckpt(ckpt_to_use, device, req.turbo, unet_bs, ('full' if req.use_full_precision else 'autocast'))
needs_model_reload = False
if prev_device != device:
@ -256,7 +299,7 @@ def do_mk_img(req: Request):
load_model_real_esrgan(real_esrgan_file)
if needs_model_reload:
load_model_ckpt(ckpt_file, device, req.turbo, unet_bs, precision)
load_model_ckpt(ckpt_to_use, device, req.turbo, unet_bs, precision)
if req.use_face_correction != gfpgan_file:
load_model_gfpgan(req.use_face_correction)
@ -269,23 +312,11 @@ def do_mk_img(req: Request):
opt_prompt = req.prompt
opt_seed = req.seed
opt_n_samples = req.num_outputs
opt_n_iter = 1
opt_scale = req.guidance_scale
opt_C = 4
opt_H = req.height
opt_W = req.width
opt_f = 8
opt_ddim_steps = req.num_inference_steps
opt_ddim_eta = 0.0
opt_strength = req.prompt_strength
opt_save_to_disk_path = req.save_to_disk_path
opt_init_img = req.init_image
opt_use_face_correction = req.use_face_correction
opt_use_upscale = req.use_upscale
opt_show_only_filtered = req.show_only_filtered_image
opt_format = req.output_format
opt_sampler_name = req.sampler
print(req.to_string(), '\n device', device)
@ -293,7 +324,7 @@ def do_mk_img(req: Request):
seed_everything(opt_seed)
batch_size = opt_n_samples
batch_size = req.num_outputs
prompt = opt_prompt
assert prompt is not None
data = [batch_size * [prompt]]
@ -313,7 +344,7 @@ def do_mk_img(req: Request):
else:
handler = _img2img
init_image = load_img(req.init_image, opt_W, opt_H)
init_image = load_img(req.init_image, req.width, req.height)
init_image = init_image.to(device)
if device != "cpu" and precision == "autocast":
@ -325,7 +356,7 @@ def do_mk_img(req: Request):
init_latent = modelFS.get_first_stage_encoding(modelFS.encode_first_stage(init_image)) # move to latent space
if req.mask is not None:
mask = load_mask(req.mask, opt_W, opt_H, init_latent.shape[2], init_latent.shape[3], True).to(device)
mask = load_mask(req.mask, req.width, req.height, init_latent.shape[2], init_latent.shape[3], True).to(device)
mask = mask[0][0].unsqueeze(0).repeat(4, 1, 1).unsqueeze(0)
mask = repeat(mask, '1 ... -> b ...', b=batch_size)
@ -334,12 +365,12 @@ def do_mk_img(req: Request):
move_fs_to_cpu()
assert 0. <= opt_strength <= 1., 'can only work with strength in [0.0, 1.0]'
t_enc = int(opt_strength * opt_ddim_steps)
assert 0. <= req.prompt_strength <= 1., 'can only work with strength in [0.0, 1.0]'
t_enc = int(req.prompt_strength * req.num_inference_steps)
print(f"target t_enc is {t_enc} steps")
if opt_save_to_disk_path is not None:
session_out_path = os.path.join(opt_save_to_disk_path, req.session_id)
if req.save_to_disk_path is not None:
session_out_path = os.path.join(req.save_to_disk_path, req.session_id)
os.makedirs(session_out_path, exist_ok=True)
else:
session_out_path = None
@ -352,7 +383,7 @@ def do_mk_img(req: Request):
with precision_scope("cuda"):
modelCS.to(device)
uc = None
if opt_scale != 1.0:
if req.guidance_scale != 1.0:
uc = modelCS.get_learned_conditioning(batch_size * [req.negative_prompt])
if isinstance(prompts, tuple):
prompts = list(prompts)
@ -373,14 +404,18 @@ def do_mk_img(req: Request):
modelFS.to(device)
partial_x_samples = None
last_callback_time = -1
def img_callback(x_samples, i):
nonlocal partial_x_samples
nonlocal partial_x_samples, last_callback_time
partial_x_samples = x_samples
if req.stream_progress_updates:
n_steps = opt_ddim_steps if req.init_image is None else t_enc
progress = {"step": i, "total_steps": n_steps}
n_steps = req.num_inference_steps if req.init_image is None else t_enc
step_time = time.time() - last_callback_time if last_callback_time != -1 else -1
last_callback_time = time.time()
progress = {"step": i, "total_steps": n_steps, "step_time": step_time}
if req.stream_image_progress and i % 5 == 0:
partial_images = []
@ -411,9 +446,9 @@ def do_mk_img(req: Request):
# run the handler
try:
if handler == _txt2img:
x_samples = _txt2img(opt_W, opt_H, opt_n_samples, opt_ddim_steps, opt_scale, None, opt_C, opt_f, opt_ddim_eta, c, uc, opt_seed, img_callback, mask, opt_sampler_name)
x_samples = _txt2img(req.width, req.height, req.num_outputs, req.num_inference_steps, req.guidance_scale, None, opt_C, opt_f, opt_ddim_eta, c, uc, opt_seed, img_callback, mask, req.sampler)
else:
x_samples = _img2img(init_latent, t_enc, batch_size, opt_scale, c, uc, opt_ddim_steps, opt_ddim_eta, opt_seed, img_callback, mask)
x_samples = _img2img(init_latent, t_enc, batch_size, req.guidance_scale, c, uc, req.num_inference_steps, opt_ddim_eta, opt_seed, img_callback, mask)
yield from x_samples
@ -426,6 +461,8 @@ def do_mk_img(req: Request):
print("saving images")
for i in range(batch_size):
img_id = base64.b64encode(int(time.time()+i).to_bytes(8, 'big')).decode() # Generate unique ID based on time.
img_id = img_id.translate({43:None, 47:None, 61:None})[-8:] # Remove + / = and keep last 8 chars.
x_samples_ddim = modelFS.decode_first_stage(x_samples[i].unsqueeze(0))
x_sample = torch.clamp((x_samples_ddim + 1.0) / 2.0, min=0.0, max=1.0)
@ -433,69 +470,49 @@ def do_mk_img(req: Request):
x_sample = x_sample.astype(np.uint8)
img = Image.fromarray(x_sample)
has_filters = (opt_use_face_correction is not None and opt_use_face_correction.startswith('GFPGAN')) or \
(opt_use_upscale is not None and opt_use_upscale.startswith('RealESRGAN'))
has_filters = (req.use_face_correction is not None and req.use_face_correction.startswith('GFPGAN')) or \
(req.use_upscale is not None and req.use_upscale.startswith('RealESRGAN'))
return_orig_img = not has_filters or not opt_show_only_filtered
return_orig_img = not has_filters or not req.show_only_filtered_image
if stop_processing:
return_orig_img = True
if opt_save_to_disk_path is not None:
prompt_flattened = filename_regex.sub('_', prompts[0])
prompt_flattened = prompt_flattened[:50]
img_id = str(uuid.uuid4())[-8:]
file_path = f"{prompt_flattened}_{img_id}"
img_out_path = os.path.join(session_out_path, f"{file_path}.{opt_format}")
meta_out_path = os.path.join(session_out_path, f"{file_path}.txt")
if req.save_to_disk_path is not None:
if return_orig_img:
img_out_path = get_base_path(req.save_to_disk_path, req.session_id, prompts[0], img_id, req.output_format)
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, req.negative_prompt, ckpt_file)
meta_out_path = get_base_path(req.save_to_disk_path, req.session_id, prompts[0], img_id, 'txt')
save_metadata(meta_out_path, req, prompts[0], opt_seed)
if return_orig_img:
img_data = img_to_base64_str(img, opt_format)
img_data = img_to_base64_str(img, req.output_format)
res_image_orig = ResponseImage(data=img_data, seed=opt_seed)
res.images.append(res_image_orig)
if opt_save_to_disk_path is not None:
if req.save_to_disk_path is not None:
res_image_orig.path_abs = img_out_path
del img
if has_filters and not stop_processing:
print('Applying filters..')
gc()
filters_applied = []
if opt_use_face_correction:
_, _, output = model_gfpgan.enhance(x_sample[:,:,::-1], has_aligned=False, only_center_face=False, paste_back=True)
x_sample = output[:,:,::-1]
filters_applied.append(opt_use_face_correction)
if opt_use_upscale:
output, _ = model_real_esrgan.enhance(x_sample[:,:,::-1])
x_sample = output[:,:,::-1]
filters_applied.append(opt_use_upscale)
filtered_image = Image.fromarray(x_sample)
filtered_img_data = img_to_base64_str(filtered_image, opt_format)
res_image_filtered = ResponseImage(data=filtered_img_data, seed=opt_seed)
res.images.append(res_image_filtered)
filters_applied = "_".join(filters_applied)
if opt_save_to_disk_path is not None:
filtered_img_out_path = os.path.join(session_out_path, f"{file_path}_{filters_applied}.{opt_format}")
save_image(filtered_image, filtered_img_out_path)
res_image_filtered.path_abs = filtered_img_out_path
del filtered_image
if req.use_face_correction:
x_sample = apply_filters('gfpgan', x_sample)
filters_applied.append(req.use_face_correction)
if req.use_upscale:
x_sample = apply_filters('real_esrgan', x_sample)
filters_applied.append(req.use_upscale)
if (len(filters_applied) > 0):
filtered_image = Image.fromarray(x_sample)
filtered_img_data = img_to_base64_str(filtered_image, req.output_format)
response_image = ResponseImage(data=filtered_img_data, seed=opt_seed)
res.images.append(response_image)
if req.save_to_disk_path is not None:
filtered_img_out_path = get_base_path(req.save_to_disk_path, req.session_id, prompts[0], img_id, req.output_format, "_".join(filters_applied))
save_image(filtered_image, filtered_img_out_path)
response_image.path_abs = filtered_img_out_path
del filtered_image
seeds += str(opt_seed) + ","
opt_seed += 1
@ -515,11 +532,22 @@ def save_image(img, img_out_path):
except:
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, negative_prompt, ckpt_file):
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}\nStable Diffusion Model: {ckpt_file + '.ckpt'}"
def save_metadata(meta_out_path, req, prompt, opt_seed):
metadata = f"""{prompt}
Width: {req.width}
Height: {req.height}
Seed: {opt_seed}
Steps: {req.num_inference_steps}
Guidance Scale: {req.guidance_scale}
Prompt Strength: {req.prompt_strength}
Use Face Correction: {req.use_face_correction}
Use Upscaling: {req.use_upscale}
Sampler: {req.sampler}
Negative Prompt: {req.negative_prompt}
Stable Diffusion Model: {req.use_stable_diffusion_model + '.ckpt'}
"""
try:
with open(meta_out_path, 'w') as f:
with open(meta_out_path, 'w', encoding='utf-8') as f:
f.write(metadata)
except:
print('could not save the file', traceback.format_exc())
@ -657,11 +685,13 @@ def img_to_base64_str(img, output_format="PNG"):
img.save(buffered, format=output_format)
buffered.seek(0)
img_byte = buffered.getvalue()
img_str = "data:image/png;base64," + base64.b64encode(img_byte).decode()
mime_type = "image/png" if output_format.lower() == "png" else "image/jpeg"
img_str = f"data:{mime_type};base64," + base64.b64encode(img_byte).decode()
return img_str
def base64_str_to_img(img_str):
img_str = img_str[len("data:image/png;base64,"):]
mime_type = "image/png" if img_str.startswith("data:image/png;") else "image/jpeg"
img_str = img_str[len(f"data:{mime_type};base64,"):]
data = base64.b64decode(img_str)
buffered = BytesIO(data)
img = Image.open(buffered)

View File

@ -0,0 +1,299 @@
import json
import traceback
TASK_TTL = 15 * 60 # seconds, Discard last session's task timeout
import queue, threading, time
from typing import Any, Generator, Hashable, Optional, Union
from pydantic import BaseModel
from sd_internal import Request, Response
class SymbolClass(type): # Print nicely formatted Symbol names.
def __repr__(self): return self.__qualname__
def __str__(self): return self.__name__
class Symbol(metaclass=SymbolClass): pass
class ServerStates:
class Init(Symbol): pass
class LoadingModel(Symbol): pass
class Online(Symbol): pass
class Rendering(Symbol): pass
class Unavailable(Symbol): pass
class RenderTask(): # Task with output queue and completion lock.
def __init__(self, req: Request):
self.request: Request = req # Initial Request
self.response: Any = None # Copy of the last reponse
self.temp_images:[] = [None] * req.num_outputs * (1 if req.show_only_filtered_image else 2)
self.error: Exception = None
self.lock: threading.Lock = threading.Lock() # Locks at task start and unlocks when task is completed
self.buffer_queue: queue.Queue = queue.Queue() # Queue of JSON string segments
async def read_buffer_generator(self):
try:
while not self.buffer_queue.empty():
res = self.buffer_queue.get(block=False)
self.buffer_queue.task_done()
yield res
except queue.Empty as e: yield
# defaults from https://huggingface.co/blog/stable_diffusion
class ImageRequest(BaseModel):
session_id: str = "session"
prompt: str = ""
negative_prompt: str = ""
init_image: str = None # base64
mask: str = None # base64
num_outputs: int = 1
num_inference_steps: int = 50
guidance_scale: float = 7.5
width: int = 512
height: int = 512
seed: int = 42
prompt_strength: float = 0.8
sampler: str = None # "ddim", "plms", "heun", "euler", "euler_a", "dpm2", "dpm2_a", "lms"
# allow_nsfw: bool = False
save_to_disk_path: str = None
turbo: bool = True
use_cpu: bool = False
use_full_precision: bool = False
use_face_correction: str = None # or "GFPGANv1.3"
use_upscale: str = None # or "RealESRGAN_x4plus" or "RealESRGAN_x4plus_anime_6B"
use_stable_diffusion_model: str = "sd-v1-4"
show_only_filtered_image: bool = False
output_format: str = "jpeg" # or "png"
stream_progress_updates: bool = False
stream_image_progress: bool = False
# Temporary cache to allow to query tasks results for a short time after they are completed.
class TaskCache():
def __init__(self):
self._base = dict()
self._lock: threading.Lock = threading.RLock()
def _get_ttl_time(self, ttl: int) -> int:
return int(time.time()) + ttl
def _is_expired(self, timestamp: int) -> bool:
return int(time.time()) >= timestamp
def clean(self) -> None:
if not self._lock.acquire(blocking=True, timeout=10): raise Exception('TaskCache.clean failed to acquire lock within timeout.')
try:
# Create a list of expired keys to delete
to_delete = []
for key in self._base:
ttl, _ = self._base[key]
if self._is_expired(ttl):
to_delete.append(key)
# Remove Items
for key in to_delete:
del self._base[key]
print(f'Session {key} expired. Data removed.')
finally:
self._lock.release()
def clear(self) -> None:
if not self._lock.acquire(blocking=True, timeout=10): raise Exception('TaskCache.clear failed to acquire lock within timeout.')
try: self._base.clear()
finally: self._lock.release()
def delete(self, key: Hashable) -> bool:
if not self._lock.acquire(blocking=True, timeout=10): raise Exception('TaskCache.delete failed to acquire lock within timeout.')
try:
if key not in self._base:
return False
del self._base[key]
return True
finally:
self._lock.release()
def keep(self, key: Hashable, ttl: int) -> bool:
if not self._lock.acquire(blocking=True, timeout=10): raise Exception('TaskCache.keep failed to acquire lock within timeout.')
try:
if key in self._base:
_, value = self._base.get(key)
self._base[key] = (self._get_ttl_time(ttl), value)
return True
return False
finally:
self._lock.release()
def put(self, key: Hashable, value: Any, ttl: int) -> bool:
if not self._lock.acquire(blocking=True, timeout=10): raise Exception('TaskCache.put failed to acquire lock within timeout.')
try:
self._base[key] = (
self._get_ttl_time(ttl), value
)
except Exception as e:
print(str(e))
print(traceback.format_exc())
return False
else:
return True
finally:
self._lock.release()
def tryGet(self, key: Hashable) -> Any:
if not self._lock.acquire(blocking=True, timeout=10): raise Exception('TaskCache.tryGet failed to acquire lock within timeout.')
try:
ttl, value = self._base.get(key, (None, None))
if ttl is not None and self._is_expired(ttl):
print(f'Session {key} expired. Discarding data.')
self.delete(key)
return None
return value
finally:
self._lock.release()
current_state = ServerStates.Init
current_state_error:Exception = None
current_model_path = None
tasks_queue = queue.Queue()
task_cache = TaskCache()
default_model_to_load = None
def preload_model(file_path=None):
global current_state, current_state_error, current_model_path
if file_path == None:
file_path = default_model_to_load
if file_path == current_model_path:
return
current_state = ServerStates.LoadingModel
try:
from . import runtime
runtime.load_model_ckpt(ckpt_to_use=file_path)
current_model_path = file_path
current_state_error = None
current_state = ServerStates.Online
except Exception as e:
current_model_path = None
current_state_error = e
current_state = ServerStates.Unavailable
print(traceback.format_exc())
def thread_render():
global current_state, current_state_error, current_model_path
from . import runtime
current_state = ServerStates.Online
preload_model()
while True:
task_cache.clean()
if isinstance(current_state_error, SystemExit):
current_state = ServerStates.Unavailable
return
task = None
try:
task = tasks_queue.get(timeout=1)
except queue.Empty as e:
if isinstance(current_state_error, SystemExit):
current_state = ServerStates.Unavailable
return
else: continue
#if current_model_path != task.request.use_stable_diffusion_model:
# preload_model(task.request.use_stable_diffusion_model)
if current_state_error:
task.error = current_state_error
continue
print(f'Session {task.request.session_id} starting task {id(task)}')
try:
task.lock.acquire(blocking=False)
res = runtime.mk_img(task.request)
if current_model_path == task.request.use_stable_diffusion_model:
current_state = ServerStates.Rendering
else:
current_state = ServerStates.LoadingModel
except Exception as e:
task.error = e
task.lock.release()
tasks_queue.task_done()
print(traceback.format_exc())
continue
dataQueue = None
if task.request.stream_progress_updates:
dataQueue = task.buffer_queue
for result in res:
if current_state == ServerStates.LoadingModel:
current_state = ServerStates.Rendering
current_model_path = task.request.use_stable_diffusion_model
if isinstance(current_state_error, SystemExit) or isinstance(current_state_error, StopAsyncIteration) or isinstance(task.error, StopAsyncIteration):
runtime.stop_processing = True
if isinstance(current_state_error, StopAsyncIteration):
task.error = current_state_error
current_state_error = None
print(f'Session {task.request.session_id} sent cancel signal for task {id(task)}')
if dataQueue:
dataQueue.put(result)
if isinstance(result, str):
result = json.loads(result)
task.response = result
if 'output' in result:
for out_obj in result['output']:
if 'path' in out_obj:
img_id = out_obj['path'][out_obj['path'].rindex('/') + 1:]
task.temp_images[int(img_id)] = runtime.temp_images[out_obj['path'][11:]]
elif 'data' in out_obj:
task.temp_images[result['output'].index(out_obj)] = out_obj['data']
task_cache.keep(task.request.session_id, TASK_TTL)
# Task completed
task.lock.release()
tasks_queue.task_done()
task_cache.keep(task.request.session_id, TASK_TTL)
if isinstance(task.error, StopAsyncIteration):
print(f'Session {task.request.session_id} task {id(task)} cancelled!')
elif task.error is not None:
print(f'Session {task.request.session_id} task {id(task)} failed!')
else:
print(f'Session {task.request.session_id} task {id(task)} completed.')
current_state = ServerStates.Online
render_thread = threading.Thread(target=thread_render)
def start_render_thread():
# Start Rendering Thread
render_thread.daemon = True
render_thread.start()
def shutdown_event(): # Signal render thread to close on shutdown
global current_state_error
current_state_error = SystemExit('Application shutting down.')
def render(req : ImageRequest):
if not render_thread.is_alive(): # Render thread is dead
raise ChildProcessError('Rendering thread has died.')
# Alive, check if task in cache
task = task_cache.tryGet(req.session_id)
if task and not task.response and not task.error and not task.lock.locked():
# Unstarted task pending, deny queueing more than one.
raise ConnectionRefusedError(f'Session {req.session_id} has an already pending task.')
#
from . import runtime
r = Request()
r.session_id = req.session_id
r.prompt = req.prompt
r.negative_prompt = req.negative_prompt
r.init_image = req.init_image
r.mask = req.mask
r.num_outputs = req.num_outputs
r.num_inference_steps = req.num_inference_steps
r.guidance_scale = req.guidance_scale
r.width = req.width
r.height = req.height
r.seed = req.seed
r.prompt_strength = req.prompt_strength
r.sampler = req.sampler
# r.allow_nsfw = req.allow_nsfw
r.turbo = req.turbo
r.use_cpu = req.use_cpu
r.use_full_precision = req.use_full_precision
r.save_to_disk_path = req.save_to_disk_path
r.use_upscale: str = req.use_upscale
r.use_face_correction = req.use_face_correction
r.use_stable_diffusion_model = req.use_stable_diffusion_model
r.show_only_filtered_image = req.show_only_filtered_image
r.output_format = req.output_format
r.stream_progress_updates = True # the underlying implementation only supports streaming
r.stream_image_progress = req.stream_image_progress
if not req.stream_progress_updates:
r.stream_image_progress = False
new_task = RenderTask(r)
if task_cache.put(r.session_id, new_task, TASK_TTL):
tasks_queue.put(new_task, block=True, timeout=30)
return new_task
raise RuntimeError('Failed to add task to cache.')

View File

@ -12,92 +12,39 @@ sys.path.append(os.path.dirname(SD_UI_DIR))
CONFIG_DIR = os.path.abspath(os.path.join(SD_UI_DIR, '..', 'scripts'))
MODELS_DIR = os.path.abspath(os.path.join(SD_DIR, '..', 'models'))
UI_PLUGINS_DIR = os.path.abspath(os.path.join(SD_DIR, '..', 'plugins', 'ui'))
OUTPUT_DIRNAME = "Stable Diffusion UI" # in the user's home folder
TASK_TTL = 15 * 60 # Discard last session's task timeout
from fastapi import FastAPI, HTTPException
from fastapi.staticfiles import StaticFiles
from starlette.responses import FileResponse, StreamingResponse
from starlette.responses import FileResponse, JSONResponse, StreamingResponse
from pydantic import BaseModel
import logging
import queue, threading, time
from typing import Any, Generator, Hashable, Optional, Union
from sd_internal import Request, Response
from sd_internal import Request, Response, task_manager
app = FastAPI()
model_loaded = False
model_is_loading = False
modifiers_cache = None
outpath = os.path.join(os.path.expanduser("~"), OUTPUT_DIRNAME)
os.makedirs(UI_PLUGINS_DIR, exist_ok=True)
# don't show access log entries for URLs that start with the given prefix
ACCESS_LOG_SUPPRESS_PATH_PREFIXES = ['/ping', '/modifier-thumbnails']
ACCESS_LOG_SUPPRESS_PATH_PREFIXES = ['/ping', '/image', '/modifier-thumbnails']
app.mount('/media', StaticFiles(directory=os.path.join(SD_UI_DIR, 'media/')), name="media")
NOCACHE_HEADERS={"Cache-Control": "no-cache, no-store, must-revalidate", "Pragma": "no-cache", "Expires": "0"}
# defaults from https://huggingface.co/blog/stable_diffusion
class ImageRequest(BaseModel):
session_id: str = "session"
prompt: str = ""
negative_prompt: str = ""
init_image: str = None # base64
mask: str = None # base64
num_outputs: int = 1
num_inference_steps: int = 50
guidance_scale: float = 7.5
width: int = 512
height: int = 512
seed: int = 42
prompt_strength: float = 0.8
sampler: str = None # "ddim", "plms", "heun", "euler", "euler_a", "dpm2", "dpm2_a", "lms"
# allow_nsfw: bool = False
save_to_disk_path: str = None
turbo: bool = True
use_cpu: bool = False
use_full_precision: bool = False
use_face_correction: str = None # or "GFPGANv1.3"
use_upscale: str = None # or "RealESRGAN_x4plus" or "RealESRGAN_x4plus_anime_6B"
use_stable_diffusion_model: str = "sd-v1-4"
show_only_filtered_image: bool = False
output_format: str = "jpeg" # or "png"
stream_progress_updates: bool = False
stream_image_progress: bool = False
app.mount('/media', StaticFiles(directory=os.path.join(SD_UI_DIR, 'media')), name="media")
app.mount('/plugins', StaticFiles(directory=UI_PLUGINS_DIR), name="plugins")
class SetAppConfigRequest(BaseModel):
update_branch: str = "main"
@app.get('/')
def read_root():
headers = {"Cache-Control": "no-cache, no-store, must-revalidate", "Pragma": "no-cache", "Expires": "0"}
return FileResponse(os.path.join(SD_UI_DIR, 'index.html'), headers=headers)
@app.get('/ping')
async def ping():
global model_loaded, model_is_loading
try:
if model_loaded:
return {'OK'}
if model_is_loading:
return {'ERROR'}
model_is_loading = True
from sd_internal import runtime
runtime.load_model_ckpt(ckpt_to_use=get_initial_model_to_load())
model_loaded = True
model_is_loading = False
return {'OK'}
except Exception as e:
print(traceback.format_exc())
return HTTPException(status_code=500, detail=str(e))
# needs to support the legacy installations
def get_initial_model_to_load():
custom_weight_path = os.path.join(SD_DIR, 'custom-model.ckpt')
@ -114,7 +61,6 @@ def get_initial_model_to_load():
ckpt_to_use = model_path
else:
print('Could not find the configured custom model at:', model_path + '.ckpt', '. Using the default one:', ckpt_to_use + '.ckpt')
return ckpt_to_use
def resolve_model_to_use(model_name):
@ -126,92 +72,110 @@ def resolve_model_to_use(model_name):
model_path = legacy_model_path
else:
model_path = os.path.join(MODELS_DIR, 'stable-diffusion', model_name)
return model_path
@app.on_event("shutdown")
def shutdown_event(): # Signal render thread to close on shutdown
task_manager.current_state_error = SystemExit('Application shutting down.')
@app.get('/')
def read_root():
return FileResponse(os.path.join(SD_UI_DIR, 'index.html'), headers=NOCACHE_HEADERS)
@app.get('/ping') # Get server and optionally session status.
def ping(session_id:str=None):
if not task_manager.render_thread.is_alive(): # Render thread is dead.
if task_manager.current_state_error: raise HTTPException(status_code=500, detail=str(task_manager.current_state_error))
raise HTTPException(status_code=500, detail='Render thread is dead.')
if task_manager.current_state_error and not isinstance(task_manager.current_state_error, StopAsyncIteration): raise HTTPException(status_code=500, detail=str(task_manager.current_state_error))
# Alive
response = {'status': str(task_manager.current_state)}
if session_id:
task = task_manager.task_cache.tryGet(session_id)
if task:
response['task'] = id(task)
if task.lock.locked():
response['session'] = 'running'
elif isinstance(task.error, StopAsyncIteration):
response['session'] = 'stopped'
elif task.error:
response['session'] = 'error'
elif not task.buffer_queue.empty():
response['session'] = 'buffer'
elif task.response:
response['session'] = 'completed'
else:
response['session'] = 'pending'
return JSONResponse(response, headers=NOCACHE_HEADERS)
def save_model_to_config(model_name):
config = getConfig()
if 'model' not in config:
config['model'] = {}
config['model']['stable-diffusion'] = model_name
setConfig(config)
@app.post('/image')
def image(req : ImageRequest):
from sd_internal import runtime
r = Request()
r.session_id = req.session_id
r.prompt = req.prompt
r.negative_prompt = req.negative_prompt
r.init_image = req.init_image
r.mask = req.mask
r.num_outputs = req.num_outputs
r.num_inference_steps = req.num_inference_steps
r.guidance_scale = req.guidance_scale
r.width = req.width
r.height = req.height
r.seed = req.seed
r.prompt_strength = req.prompt_strength
r.sampler = req.sampler
# r.allow_nsfw = req.allow_nsfw
r.turbo = req.turbo
r.use_cpu = req.use_cpu
r.use_full_precision = req.use_full_precision
r.save_to_disk_path = req.save_to_disk_path
r.use_upscale: str = req.use_upscale
r.use_face_correction = req.use_face_correction
r.show_only_filtered_image = req.show_only_filtered_image
r.output_format = req.output_format
r.stream_progress_updates = True # the underlying implementation only supports streaming
r.stream_image_progress = req.stream_image_progress
r.use_stable_diffusion_model = resolve_model_to_use(req.use_stable_diffusion_model)
save_model_to_config(req.use_stable_diffusion_model)
@app.post('/render')
def render(req : task_manager.ImageRequest):
try:
if not req.stream_progress_updates:
r.stream_image_progress = False
res = runtime.mk_img(r)
if req.stream_progress_updates:
return StreamingResponse(res, media_type='application/json')
else: # compatibility mode: buffer the streaming responses, and return the last one
last_result = None
for result in res:
last_result = result
return json.loads(last_result)
save_model_to_config(req.use_stable_diffusion_model)
req.use_stable_diffusion_model = resolve_model_to_use(req.use_stable_diffusion_model)
new_task = task_manager.render(req)
response = {
'status': str(task_manager.current_state),
'queue': task_manager.tasks_queue.qsize(),
'stream': f'/image/stream/{req.session_id}/{id(new_task)}',
'task': id(new_task)
}
return JSONResponse(response, headers=NOCACHE_HEADERS)
except ChildProcessError as e: # Render thread is dead
raise HTTPException(status_code=500, detail=f'Rendering thread has died.') # HTTP500 Internal Server Error
except ConnectionRefusedError as e: # Unstarted task pending, deny queueing more than one.
raise HTTPException(status_code=503, detail=f'Session {req.session_id} has an already pending task.') # HTTP503 Service Unavailable
except Exception as e:
print(traceback.format_exc())
return HTTPException(status_code=500, detail=str(e))
raise HTTPException(status_code=500, detail=str(e))
@app.get('/image/stream/{session_id:str}/{task_id:int}')
def stream(session_id:str, task_id:int):
#TODO Move to WebSockets ??
task = task_manager.task_cache.tryGet(session_id)
if not task: raise HTTPException(status_code=410, detail='No request received.') # HTTP410 Gone
if (id(task) != task_id): raise HTTPException(status_code=409, detail=f'Wrong task id received. Expected:{id(task)}, Received:{task_id}') # HTTP409 Conflict
if task.buffer_queue.empty() and not task.lock.locked():
if task.response:
#print(f'Session {session_id} sending cached response')
return JSONResponse(task.response, headers=NOCACHE_HEADERS)
raise HTTPException(status_code=425, detail='Too Early, task not started yet.') # HTTP425 Too Early
#print(f'Session {session_id} opened live render stream {id(task.buffer_queue)}')
return StreamingResponse(task.read_buffer_generator(), media_type='application/json')
@app.get('/image/stop')
def stop():
try:
if model_is_loading:
return {'ERROR'}
from sd_internal import runtime
runtime.stop_processing = True
def stop(session_id:str=None):
if not session_id:
if task_manager.current_state == task_manager.ServerStates.Online or task_manager.current_state == task_manager.ServerStates.Unavailable:
raise HTTPException(status_code=409, detail='Not currently running any tasks.') # HTTP409 Conflict
task_manager.current_state_error = StopAsyncIteration('')
return {'OK'}
except Exception as e:
print(traceback.format_exc())
return HTTPException(status_code=500, detail=str(e))
task = task_manager.task_cache.tryGet(session_id)
if not task: raise HTTPException(status_code=404, detail=f'Session {session_id} has no active task.') # HTTP404 Not Found
if isinstance(task.error, StopAsyncIteration): raise HTTPException(status_code=409, detail=f'Session {session_id} task is already stopped.') # HTTP409 Conflict
task.error = StopAsyncIteration('')
return {'OK'}
@app.get('/image/tmp/{session_id}/{img_id}')
@app.get('/image/tmp/{session_id}/{img_id:int}')
def get_image(session_id, img_id):
from sd_internal import runtime
buf = runtime.temp_images[session_id + '/' + img_id]
buf.seek(0)
return StreamingResponse(buf, media_type='image/jpeg')
task = task_manager.task_cache.tryGet(session_id)
if not task: raise HTTPException(status_code=410, detail=f'Session {session_id} has not submitted a task.') # HTTP410 Gone
if not task.temp_images[img_id]: raise HTTPException(status_code=425, detail='Too Early, task data is not available yet.') # HTTP425 Too Early
try:
img_data = task.temp_images[img_id]
if isinstance(img_data, str):
return img_data
img_data.seek(0)
return StreamingResponse(img_data, media_type='image/jpeg')
except KeyError as e:
raise HTTPException(status_code=500, detail=str(e))
@app.post('/app_config')
async def setAppConfig(req : SetAppConfigRequest):
@ -228,56 +192,41 @@ async def setAppConfig(req : SetAppConfigRequest):
config_bat_path = os.path.join(CONFIG_DIR, 'config.bat')
config_sh_path = os.path.join(CONFIG_DIR, 'config.sh')
with open(config_json_path, 'w') as f:
with open(config_json_path, 'w', encoding='utf-8') as f:
f.write(config_json_str)
with open(config_bat_path, 'w') as f:
with open(config_bat_path, 'w', encoding='utf-8') as f:
f.write(config_bat_str)
with open(config_sh_path, 'w') as f:
with open(config_sh_path, 'w', encoding='utf-8') as f:
f.write(config_sh_str)
return {'OK'}
except Exception as e:
print(traceback.format_exc())
return HTTPException(status_code=500, detail=str(e))
raise HTTPException(status_code=500, detail=str(e))
@app.get('/app_config')
def getAppConfig():
def getConfig(default_val={}):
try:
config_json_path = os.path.join(CONFIG_DIR, 'config.json')
if not os.path.exists(config_json_path):
return HTTPException(status_code=500, detail="No config file")
with open(config_json_path, 'r') as f:
return default_val
with open(config_json_path, 'r', encoding='utf-8') as f:
return json.load(f)
except Exception as e:
print(str(e))
print(traceback.format_exc())
return HTTPException(status_code=500, detail=str(e))
def getConfig():
try:
config_json_path = os.path.join(CONFIG_DIR, 'config.json')
if not os.path.exists(config_json_path):
return {}
with open(config_json_path, 'r') as f:
return json.load(f)
except Exception as e:
return {}
return default_val
def setConfig(config):
try:
config_json_path = os.path.join(CONFIG_DIR, 'config.json')
with open(config_json_path, 'w') as f:
with open(config_json_path, 'w', encoding='utf-8') as f:
return json.dump(config, f)
except:
except Exception as e:
print(str(e))
print(traceback.format_exc())
@app.get('/models')
def getModels():
models = {
'active': {
@ -307,14 +256,31 @@ def getModels():
return models
@app.get('/modifiers.json')
def read_modifiers():
headers = {"Cache-Control": "no-cache, no-store, must-revalidate", "Pragma": "no-cache", "Expires": "0"}
return FileResponse(os.path.join(SD_UI_DIR, 'modifiers.json'), headers=headers)
def getUIPlugins():
plugins = []
@app.get('/output_dir')
def read_home_dir():
return {outpath}
for file in os.listdir(UI_PLUGINS_DIR):
if file.endswith('.plugin.js'):
plugins.append(f'/plugins/{file}')
return plugins
@app.get('/get/{key:path}')
def read_web_data(key:str=None):
if not key: # /get without parameters, stable-diffusion easter egg.
raise HTTPException(status_code=418, detail="StableDiffusion is drawing a teapot!") # HTTP418 I'm a teapot
elif key == 'app_config':
config = getConfig(default_val=None)
if config is None:
raise HTTPException(status_code=500, detail="Config file is missing or unreadable")
return JSONResponse(config, headers=NOCACHE_HEADERS)
elif key == 'models':
return JSONResponse(getModels(), headers=NOCACHE_HEADERS)
elif key == 'modifiers': return FileResponse(os.path.join(SD_UI_DIR, 'modifiers.json'), headers=NOCACHE_HEADERS)
elif key == 'output_dir': return JSONResponse({ 'output_dir': outpath }, headers=NOCACHE_HEADERS)
elif key == 'ui_plugins': return JSONResponse(getUIPlugins(), headers=NOCACHE_HEADERS)
else:
raise HTTPException(status_code=404, detail=f'Request for unknown {key}') # HTTP404 Not Found
# don't log certain requests
class LogSuppressFilter(logging.Filter):
@ -323,10 +289,11 @@ class LogSuppressFilter(logging.Filter):
for prefix in ACCESS_LOG_SUPPRESS_PATH_PREFIXES:
if path.find(prefix) != -1:
return False
return True
logging.getLogger('uvicorn.access').addFilter(LogSuppressFilter())
task_manager.default_model_to_load = get_initial_model_to_load()
task_manager.start_render_thread()
# start the browser ui
import webbrowser; webbrowser.open('http://localhost:9000')