Compare commits

...

1113 Commits

Author SHA1 Message Date
5b47da67f6 Merge pull request #582 from cmdr2/beta
Beta
2022-12-01 13:59:13 +05:30
292f68ff97 Typo in css path 2022-12-01 13:57:38 +05:30
3b554d881a Styling changes for the confirm dialog 2022-12-01 13:54:49 +05:30
4bc6e51862 Merge pull request #580 from JeLuF/patch-5
Add Quadro T2000 to force_full_precision list.
2022-12-01 10:35:32 +05:30
427861cf13 Add Quadro T2000 to force_full_precision list. 2022-12-01 00:59:12 +01:00
da3e7a2eb8 Fix the broken image close button 2022-11-30 21:14:18 +05:30
2979f04c82 Use socket.gethostname() instead of socket.getfqdn() 2022-11-30 20:17:18 +05:30
1949d8a50c Tweak modifiers help msg 2022-11-30 16:32:43 +05:30
ee66c799e0 Merge pull request #563 from patriceac/Mouse-wheel-behavior-fixes
Improved Mouse Wheel UX with Image Modifiers
2022-11-30 16:24:05 +05:30
7c50b8bf94 Merge branch 'beta' into Mouse-wheel-behavior-fixes 2022-11-30 16:22:45 +05:30
141ff74ece Merge pull request #557 from madrang/webmanifest
Added web manifest to allow installing the Url as a web app.
2022-11-30 16:19:04 +05:30
321e5f1ed6 Merge pull request #564 from patriceac/Fix-UI-display-when-removing-the-last-task
Fix UI display when removing the last task
2022-11-30 16:14:59 +05:30
6d131d9d8e Merge branch 'beta' into Fix-UI-display-when-removing-the-last-task 2022-11-30 16:14:28 +05:30
7e69b8eb31 Merge branch 'beta' of github.com:cmdr2/stable-diffusion-ui into beta 2022-11-30 16:11:22 +05:30
4e0b33e6a4 Merge pull request #566 from patriceac/Visual-feedback-on-buttons
Visual feedback on button click
2022-11-30 16:11:08 +05:30
54f7e6fcb8 SD2 fix - register buffer on the correct device 2022-11-30 16:05:06 +05:30
529169c4da Merge pull request #541 from patriceac/patch-2
Fix restoration of parallel output setting
2022-11-30 15:54:04 +05:30
a2c8c99215 Merge pull request #541 from patriceac/patch-2
Fix restoration of parallel output setting
2022-11-30 15:53:30 +05:30
e8bf3fd009 Merge pull request #542 from patriceac/patch-1
Fix restoration of model and VAE
2022-11-30 15:52:26 +05:30
465676e9ea Merge pull request #542 from patriceac/patch-1
Fix restoration of model and VAE
2022-11-30 15:51:31 +05:30
af53b57047 Changelog 2022-11-30 15:49:47 +05:30
54b5f75905 Rename auto-scroll to reflect its purpose 2022-11-30 15:47:24 +05:30
4348333497 Don't register listeners for an autosave setting, if they've already been registered 2022-11-30 15:45:30 +05:30
cc31110bcf Merge pull request #537 from patriceac/Generate-screen-layout
Auto-scroll plugin
2022-11-30 15:44:31 +05:30
f7c04bf7a6 bump version 2022-11-30 14:34:42 +05:30
029509ebad Unify IP info with devices, into a system_info table 2022-11-30 14:34:24 +05:30
65102bb64d Merge pull request #536 from JeLuF/serverip
Show network addresses in system settings
2022-11-30 14:00:18 +05:30
b96b55c5ce Merge branch 'beta' into serverip 2022-11-30 14:00:12 +05:30
1f5aba010e Merge branch 'beta' of https://github.com/cmdr2/stable-diffusion-ui.git into webmanifest
# Conflicts:
#	ui/index.html
2022-11-30 03:29:46 -05:00
f0b3bea4e3 Also confirm before the 'Stop All' button acts; Tweak wording of confirm dialog 2022-11-30 13:54:42 +05:30
84fae2d9e0 Merge pull request #531 from JeLuF/confirm
Confirm 'Clear All' and 'Stop Task'
2022-11-30 13:48:14 +05:30
0b96fa112d Merge branch 'beta' into confirm 2022-11-30 13:47:08 +05:30
c64bcd23d3 Picklescanner is mandatory 2022-11-30 13:38:22 +05:30
efd9a22bb5 Merge pull request #530 from madrang/list-models
Scan model once as start, then only if changed.
2022-11-30 13:37:27 +05:30
159c3edfe3 Simplify the logic for toggling modifier cards, no need to loop through the cards, since we already have the card object in hand 2022-11-30 13:33:20 +05:30
f74fa8657b Merge pull request #518 from patriceac/patch-6
Fix duplicate custom modifiers activation states
2022-11-30 13:27:14 +05:30
648b142a4b Merge pull request #571 from madrang/tabs-css
Add a new css rule for screens smaller than 500px.
2022-11-30 13:24:38 +05:30
426f92595e Merge pull request #520 from madrang/fix-gfpgan
Fix the gfpgan fix for multi-gpu
2022-11-30 13:08:10 +05:30
82a8d9b644 Merge pull request #577 from cmdr2/beta
Beta
2022-11-30 12:19:44 +05:30
ff9430b8a2 Tabs to 4 spaces 2022-11-30 12:18:34 +05:30
2e69ffcb5e Merge pull request #576 from cmdr2/beta
v2.4.16 - Remove the use of git-apply
2022-11-30 12:12:17 +05:30
0ea38db7ef Show the SD 2.0 setting only to beta users 2022-11-30 12:05:46 +05:30
2706149399 Tweak left padding of editor panel 2022-11-29 15:27:13 +05:30
3d0cdc1cb6 Bump version 2022-11-29 13:32:29 +05:30
ac605e9352 Typos and minor fixes for sd 2 2022-11-29 13:30:08 +05:30
5432297691 Default to sd-v1-4 when trying to use a SD2 model with SD 1.4, and warn the user. This will eventually be unnecessary 2022-11-29 13:14:58 +05:30
e37be0f954 Remove the need to use yield in the core loop for streaming results. This removes the need to patch the Stable Diffusion code, which can be fragile 2022-11-29 13:03:57 +05:30
a99209b674 Add a new css rule for screens smaller than 500px. 2022-11-28 20:23:17 -05:00
cb02b5ba18 Merge pull request #567 from madrang/tabs-css
Improved tabs flow on small screens.
2022-11-28 18:27:29 +05:30
14714b950d Slight improvement of detection logic 2022-11-28 00:14:12 -08:00
13654cb8c0 Make on_sd_start.sh executable 2022-11-28 13:00:02 +05:30
00276228cf Make on_sd_start.sh executable 2022-11-28 12:59:33 +05:30
8583bb8d7b Improved tabs flow on small screens. 2022-11-27 20:37:20 -05:00
d48951fe00 Visual feedback on button click
When there are too many tasks and the top of the list is not visible, there is no visual feedback that a task has been successfully added to the queue.

Adding a subtle visual feedback on buttons upon click to reflect that the mouse event was taken into account.
2022-11-27 16:26:01 -08:00
99bdcfa0a5 Set theme-color from the current selected theme. 2022-11-27 15:49:54 -05:00
e64e1a92e6 Fix UI display when removing the last task
Clear All button properly shows the "welcome message", but Remove the last task would just result in a blank Preview pane.
2022-11-27 12:42:51 -08:00
e278e639a3 Fix removal of image modifiers with non-zero weights
Properly handles removal of image modifiers that had (((modifiers))) or [[[modifiers]]] updated at runtime.
2022-11-27 03:00:19 -08:00
c4bad5c454 Conciseness
Shortening the sentence.
2022-11-27 01:42:39 -08:00
da41a74efc Require Ctrl+Mouse Wheel for modifier weight adjustment
The current behavior is just too annoying, and scrolling the page is a much more frequent activity than tweaking the weights.
2022-11-27 01:35:47 -08:00
9c91f57b19 Added web manifest to allow installing the Url as a web app. 2022-11-26 15:51:26 -05:00
f14afcd129 Update README.md 2022-11-26 12:44:19 +05:30
5c1a3d82d7 Update README.md 2022-11-26 12:23:03 +05:30
e02a917569 Improved logic for auto-scroll toggle insertion
Updating the insertion logic to prepare for future UI improvements.
2022-11-25 22:51:49 -08:00
347fa0fda1 Update on_sd_start.bat 2022-11-26 01:50:30 +05:30
6510d4cb02 Merge pull request #553 from cmdr2/revert-552-beta
Revert "Patching patch again"
2022-11-26 01:45:57 +05:30
91e4ccf6f8 Update on_sd_start.bat 2022-11-26 01:43:41 +05:30
36249874bc Revert "Patching patch again" 2022-11-26 01:42:16 +05:30
d2b5d6cce9 Merge pull request #552 from jsuelwald/beta
Patching patch again
2022-11-26 01:40:02 +05:30
b2922741c9 Patching patch again 2022-11-25 21:06:19 +01:00
300f3e27db Merge pull request #551 from cmdr2/revert-549-patch-2
Revert "Update ddim_callback_sd2.patch"
2022-11-26 01:25:17 +05:30
d7330b80a9 Revert "Update ddim_callback_sd2.patch" 2022-11-26 01:22:35 +05:30
acdd7667b7 Merge pull request #549 from jsuelwald/patch-2
Update ddim_callback_sd2.patch
2022-11-26 01:19:08 +05:30
8114fa3f5d Update ddim_callback_sd2.patch 2022-11-25 20:46:24 +01:00
4bc5508f38 Rollback 2022-11-26 01:07:55 +05:30
e503c6092e Ddim decode for img2img 2022-11-26 00:55:39 +05:30
6a8985d8dd Update ddim_callback_sd2.patch 2022-11-26 00:49:15 +05:30
bee67fd883 Shape 2022-11-25 23:54:08 +05:30
a1d75d40aa Update runtime.py 2022-11-25 23:36:43 +05:30
29484867ca Typo 2022-11-25 23:32:56 +05:30
7fa983b971 Img2img sd2 attempt 2 2022-11-25 23:28:31 +05:30
617a8b2814 Fix for make_schedule error in sd2 2022-11-25 23:15:22 +05:30
b924d323d4 img2img attempt for sd2 2022-11-25 22:36:02 +05:30
a2efda41d3 Cleaning up the code 2022-11-25 03:50:47 -08:00
642c114501 Working txt2img 2022-11-25 14:29:24 +05:30
02dd3e457d Tweaks to load sd1 models in sd2 code, typos 2022-11-25 13:57:15 +05:30
ea7b28c9d5 Placeholder changes for SD 2.0 support, haven't tested yet 2022-11-25 12:17:44 +05:30
472ab4a9ce Fix restoration of parallel output setting 2022-11-24 14:15:27 -08:00
fca84e3edf Fix restoration of model and VAE
😅
2022-11-24 13:47:35 -08:00
b70235ff92 Set the PYTHONPATH in the developer console, before the prompt shows up 2022-11-24 11:48:27 +05:30
6eff591df7 System settings to disable the 'Are you sure?'-dialogs 2022-11-23 23:05:30 +01:00
d0b2bf736e Auto-scroll off by default 2022-11-23 03:23:51 -08:00
6b6443406d Create Autoscroll.plugin.js 2022-11-23 02:57:07 -08:00
3452d7852a Merge branch 'beta' into serverip 2022-11-23 11:28:05 +01:00
f1fa10badd Show network addresses in system settings
Users sometimes struggle to get the IP address of their PC. This PR adds a button to the system settings pane that will list the server's IP
addresses.
2022-11-23 11:25:36 +01:00
1267621424 Merge pull request #535 from cmdr2/beta
Switch to new custom backend
2022-11-23 15:09:09 +05:30
8a0ec95fe1 Merge branch 'main' into beta 2022-11-23 15:08:34 +05:30
2de96d4dc9 Scan model once as start, then only if changed. 2022-11-22 20:41:08 -05:00
a486f20892 Merge branch 'beta' into confirm 2022-11-22 21:33:18 +01:00
49535deb2e Confirm 'Clear All' and 'Stop Task'
Ask for a confimation before clearing the results pane or stopping a render task. The dialog can be skipped by holding down the shift key while clicking on the button.
2022-11-22 21:27:36 +01:00
7cbf62cf12 Revert whitespace fix 2022-11-22 23:30:03 +05:30
3b0ace3410 Revert whitespace fix 2022-11-22 23:27:46 +05:30
5a9c8e1d87 Warn but don't fix whitespaces in a patch 2022-11-22 23:21:11 +05:30
daaa65dc0a Warn but don't fix whitespaces in a patch 2022-11-22 23:20:24 +05:30
ab4e371524 Fix whitespace during git apply 2022-11-22 22:25:36 +05:30
927fd304b0 Merge branch 'beta' of github.com:cmdr2/stable-diffusion-ui into beta 2022-11-22 22:22:07 +05:30
5af84b8e90 Fix whitespace during git apply 2022-11-22 22:21:54 +05:30
d425dac499 Merge pull request #529 from madrang/dragNdrop
Fixing file drag and drop.
2022-11-22 21:57:34 +05:30
d056459e76 Merge pull request #529 from madrang/dragNdrop
Fixing file drag and drop.
2022-11-22 21:56:07 +05:30
3169485f33 Fixing file drag and drop. 2022-11-22 11:11:06 -05:00
d9b9f80a93 diffusion-kit upgrade 2022-11-22 17:39:51 +05:30
d429505b71 Update version of diffusion-kit 2022-11-22 17:14:20 +05:30
72ee708917 Remove the need to install realesrgan, gfpgan and certain specific package versions, since the new backend should install them directly 2022-11-22 16:50:10 +05:30
93bbfac29a Change the backend to a custom fork of SD, since basujindal's fork is no longer under development. This fork is intended to include the common models/tools used like RealESRGAN, GFPGAN, Codeformer etc, and is meant to be a community-developed project 2022-11-22 16:38:39 +05:30
040d7a6563 Merge pull request #528 from patriceac/patch-1
Add support for custom modifiers to d&d and clipboard
2022-11-22 16:06:26 +05:30
e8dd930a50 Add support for custom modifiers to d&d and clipboard
Add support for custom modifiers to d&d and clipboard and remove now-redundant code in restoreTaskToUI.
2022-11-22 00:06:43 -08:00
31c049ebfe Version css 2022-11-22 11:09:01 +05:30
d343a37fb2 Merge branch 'beta' of github.com:cmdr2/stable-diffusion-ui into beta 2022-11-22 11:08:07 +05:30
7097175c6f CSS tweak for logo and version 2022-11-22 11:07:50 +05:30
8e57c49043 Merge pull request #527 from cmdr2/beta
Beta
2022-11-22 11:00:25 +05:30
9f036ceefd Merge branch 'main' into beta 2022-11-22 10:59:51 +05:30
ff3ca8b36b link to new downloads 2022-11-22 10:48:43 +05:30
87a7b70a27 Shell error code check 2022-11-22 10:40:20 +05:30
9c71c966ca Shell error code check 2022-11-22 10:39:47 +05:30
6dc99e676e Reduce the width of the editor sidebar, regression 2022-11-21 18:45:37 +05:30
80ecb82cc2 Reduce the width of the editor sidebar, regression 2022-11-21 18:42:07 +05:30
7fc9509d4d Nowarn for fresh installation (git apply whitespace) 2022-11-21 17:20:09 +05:30
3bf5e11f94 Nowarn for fresh installation (git apply whitespace) 2022-11-21 17:19:55 +05:30
eef9af2266 Typo 2022-11-21 17:14:54 +05:30
fabdf5fe30 Typo 2022-11-21 17:14:34 +05:30
1cc27e524b Don't warn about whitespace in the git patch application 2022-11-21 17:11:57 +05:30
8316a002da Don't warn about whitespace in the git patch application 2022-11-21 17:11:38 +05:30
888c637f71 Merge pull request #432 from JeLuF/JeLuF-nsis
NSIS Installer
2022-11-21 16:30:49 +05:30
48b7d2587e bump version 2022-11-21 16:21:22 +05:30
923c889de8 Merge pull request #495 from madrang/pasteFix
Fix pasting in Firefox.
2022-11-21 16:15:24 +05:30
8ae575d67a Merge pull request #508 from patriceac/patch-4
Modifier weight via mouse wheel plugin
2022-11-21 16:10:23 +05:30
b51407486a Merge pull request #517 from patriceac/patch-5
Fix duplicate custom modifiers restoration
2022-11-21 16:05:17 +05:30
a689b34ed1 Merge pull request #506 from patriceac/patch-2
VAE support in Use Settings
2022-11-21 16:02:51 +05:30
aa98e60243 Merge pull request #507 from patriceac/patch-3
Modifier drag-and-drop plugin
2022-11-21 16:02:04 +05:30
c3bf767024 Merge pull request #525 from cmdr2/beta
Beta
2022-11-21 14:08:47 +05:30
b641f1a230 Bump version 2022-11-21 14:08:12 +05:30
9499685dda Check for enqueued tasks more frequently 2022-11-21 14:06:26 +05:30
80d23cbbbf Merge pull request #523 from cmdr2/main
Merge main
2022-11-21 12:43:23 +05:30
efa684c5e8 Merge pull request #522 from cmdr2/beta
v2.4.11 updates
2022-11-21 12:43:03 +05:30
2edf64985d Update CHANGES.md 2022-11-21 12:41:53 +05:30
5fe7807462 ERRORLEVEL is unreliable when conda is run 2022-11-21 12:38:46 +05:30
e96b9005ca Merge pull request #514 from JeLuF/checkinput
Prevent empty fields in make image request
2022-11-21 12:36:23 +05:30
8c29e735e7 Merge pull request #513 from JeLuF/ipconfig
CHANGE.md change for IP config
2022-11-21 12:35:15 +05:30
497e073a8c Merge pull request #480 from JeLuF/patch-3
Handle %TMP% and %TEMP%
2022-11-21 12:34:31 +05:30
d4ce54a3c2 Merge pull request #521 from JeLuF/patch-4
Add --whitespace=fix to git apply
2022-11-21 12:33:04 +05:30
de37a81902 Merge pull request #519 from JeLuF/relocate2
Rewrite easy_install.pth on each start
2022-11-21 12:15:15 +05:30
d6b8cb718a Merge pull request #519 from JeLuF/relocate2
Rewrite easy_install.pth on each start
2022-11-21 12:13:43 +05:30
ed435d2b72 Add --whitespace=fix also on Linux 2022-11-20 23:09:27 +01:00
2b1f8533b0 Add --whitespace=fix to git apply
For some users who have git preinstalled, `git apply` fails due to whitespace errors.

Aracon found that applying `--whitespace=fix` to the `git apply` invocation fixes the problem.
https://discord.com/channels/1014774730907209781/1036679816713359471/1037025435491516548

ryz confirmed that `--reject` wasn't needed for him to make it work, and this explanation from the "git apply" manpage suggests 
that we shouldn't include `--reject`:

> For atomicity, git apply by default fails the whole patch and does not touch the working tree when some 
> of the hunks do not apply. This option makes it apply the parts of the patch that are applicable, and leave 
> the rejected hunks in corresponding *.rej files.

After having a look at https://github.com/git/git/blob/master/apply.c, I think that they only check for `correct_ws_error` if they couldn't apply the patch. It doesn't impact 'normal' patching. If the patch can be applied, it will be done, and only if the apply fails, they'll check whether adding or removing WS might help. It should thus be save to be added and didn't produce any errors on my installation using SDUI-provided git.
2022-11-20 23:07:44 +01:00
0a21a69a9f Updated facexlib fix for usage on multi-gpu. 2022-11-20 13:04:22 -05:00
5ebc6b698c Rewrite easy_install.pth on each start
Fixes GFPGANer errors when the env has been moved.
2022-11-20 18:48:48 +01:00
cbc48e31e1 Fix duplicate custom modifiers activation states
Fixing activation state for custom modifier cards sharing the same tag where only one of the cards gets (de)activated.
2022-11-19 19:25:28 -08:00
577dd9048f Fix duplicate custom modifiers restoration
Fix for duplicate image modifiers when restoring a task in which several custom modifier cards share the same tag.
2022-11-19 19:21:36 -08:00
ae409dd0ec Prevent empty fields in make image request
Prevent render jobs to fail with HTTP 422 due to empty fields in the image settings.
https://discord.com/channels/1014774730907209781/1043481789706031215/1043481789706031215
https://discord.com/channels/1014774730907209781/1014774732018683927/1042768986871443516

minor change, no CHANGE.md entry
2022-11-19 21:00:41 +01:00
cde855e1dc Change note 2022-11-19 20:31:36 +01:00
adcd4368e7 Merge pull request #510 from JeLuF/ipconfig
Add network settings to the UI
2022-11-20 00:55:42 +05:30
8bcdb205ed Merge pull request #512 from cmdr2/beta
Use the correct device name when moving the model to cpu
2022-11-20 00:50:58 +05:30
2cf8b2a453 Use the correct device name when moving the model to cpu 2022-11-20 00:43:38 +05:30
6c156380f9 Add network settings to the UI
Allow users to choose the uvicorn port
Allow users to restrict uvicorn to only listen on localhost
2022-11-19 17:10:45 +01:00
369d0ee502 Modifier weight via mouse wheel plugin 2022-11-19 01:17:24 -08:00
4971a212e9 Modifier drag-and-drop plugin 2022-11-19 01:09:59 -08:00
2111a81d18 Proper PR for VAE support in Use Settings 2022-11-19 00:56:44 -08:00
6799b3d7da Merge pull request #505 from cmdr2/beta
v2.4.11
2022-11-19 13:54:55 +05:30
a3463274ee changelog 2022-11-19 12:02:52 +05:30
c10e773401 Speed up the model move, by using the earlier function to move modelCS and modelFS to the cpu 2022-11-19 11:53:33 +05:30
f7af259576 Scan only the model files (check by extension), minor refactoring of the
scanning code
2022-11-19 10:44:32 +05:30
87c6a54634 changelog 2022-11-18 21:11:59 +05:30
d03521bf12 Use as Input -> Use these settings 2022-11-18 21:11:34 +05:30
3eb1919c81 Fix the missing (beta) label next to the version number 2022-11-18 19:38:16 +05:30
e53d6dbd5c changelog 2022-11-18 19:33:34 +05:30
01d2db8e96 Changelog 2022-11-18 17:36:23 +05:30
b18c2aea05 Don't cache css and js files, it's really annoying after merging every PR to have to update the version number in index.html. Disabling this until we figure out a better way 2022-11-18 17:31:20 +05:30
a6e3c272e2 Tweak CSS for button press color 2022-11-18 17:14:58 +05:30
4000f98ba4 Merge pull request #490 from JeLuF/ui1
Visual feedback for the save button in the system settings
2022-11-18 17:10:04 +05:30
d06fd404ae Font size of negative prompt textbox 2022-11-18 17:09:42 +05:30
c6f0e19e2f Merge pull request #493 from JeLuF/negative
Textarea for negative prompts
2022-11-18 17:07:37 +05:30
462af9989a Merge pull request #491 from JeLuF/inst1
Fix typo in the installer's error messages
2022-11-18 17:07:06 +05:30
eedea2fdcd Bump version 2022-11-18 17:06:43 +05:30
9c3d946de0 Theme tweaks 2022-11-18 17:01:20 +05:30
ace3102601 Reduce the size of the toggle switches 2022-11-18 16:24:49 +05:30
48946100e9 Bump version 2022-11-18 16:21:12 +05:30
0067e46192 Merge pull request #501 from mdiller/mdiller_fancyswitches
Better Toggle Inputs & Updated Settings UI
2022-11-18 16:17:54 +05:30
921711a679 Don't crash if an invalid model file is beign scanned 2022-11-18 16:12:45 +05:30
32dfb765dd Bump JS version 2022-11-18 16:04:26 +05:30
8482f12909 Bump version 2022-11-18 16:03:15 +05:30
306a56124c Merge pull request #492 from JeLuF/scanner
Picklescan of model files
2022-11-18 16:02:23 +05:30
1f815d7562 Merge branch 'beta' into scanner 2022-11-18 16:01:50 +05:30
f25d35fad8 changelog 2022-11-18 15:55:53 +05:30
f74c57449e Cosmetic changes to Use Settings 2022-11-18 15:54:47 +05:30
a697bd935a Refactor the Use Settings code, and move that to the common restoreTask() function 2022-11-18 15:38:17 +05:30
ec294227bd Bump version 2022-11-18 15:14:35 +05:30
f67758eaf3 Bring back some styling that was removed accidentally by the PR merge 2022-11-18 14:58:21 +05:30
f7ed65d749 Bump version 2022-11-18 14:51:05 +05:30
7ffeb3964b Merge pull request #463 from patriceac/beta
Adding Use Settings
2022-11-18 14:40:04 +05:30
025d4df774 Don't crash if a VAE file fails to load 2022-11-18 13:11:48 +05:30
45086a4b6e updated hamunii theme name to gnomie 2022-11-17 22:25:55 -08:00
2db0023653 updated themes to work nicely with the new stuff 2022-11-17 20:15:39 -08:00
bfc21220a7 added hamunii theme 2022-11-17 18:13:08 -08:00
507491fbec added fancy switches and updated the ui of the settings tab 2022-11-17 17:58:09 -08:00
c890ef6917 Merge pull request #497 from cmdr2/beta
Beta
2022-11-17 13:40:26 +05:30
6756fb4fe7 Merge branch 'beta' of github.com:cmdr2/stable-diffusion-ui into beta 2022-11-17 13:39:40 +05:30
6c089c0a78 Link to Multi GPU wiki page 2022-11-17 13:39:29 +05:30
b2ab3f987c Merge pull request #496 from cmdr2/beta
v2.4.7
2022-11-17 13:20:20 +05:30
c99b2edf98 Update CHANGES.md 2022-11-17 13:17:20 +05:30
e052610184 Removed debugging log calls. 2022-11-17 02:45:09 -05:00
13f1725105 Merge branch 'beta' of github.com:cmdr2/stable-diffusion-ui into beta 2022-11-17 13:13:12 +05:30
f2367932e1 Style code tags in the What's New markdown 2022-11-17 13:13:01 +05:30
7e94ec986e Update CHANGES.md 2022-11-17 13:07:35 +05:30
7bda3e6994 Release summary and detailed changelog 2022-11-17 13:06:36 +05:30
3a18606385 Disable when targeting input elements. 2022-11-17 02:36:14 -05:00
e25a94e815 Bug fix, forgot to await promise. 2022-11-17 02:20:01 -05:00
c13f662e2d Use the document paste event for pasting json and text data. 2022-11-17 02:16:20 -05:00
97ee085f30 Fix a bug where Face Correction (GFPGAN) would fail on cuda:N (i.e. GPUs other than cuda:0), as well as fail on CPU if the system had an incompatible GPU. 2022-11-17 12:27:06 +05:30
1364fd5c45 Fix pasting in Firefox.
Should not display button.
https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/readText#browser_compatibility
2022-11-17 01:44:11 -05:00
cc3186a683 Highlight the Save settings button when pressed 2022-11-17 11:01:10 +05:30
0c93c4754d Tabs to spaces 2022-11-17 10:49:22 +05:30
7b4cfbeeaa Update CHANGES.md 2022-11-16 23:47:24 +01:00
8cebb53147 Textarea for negative prompts 2022-11-16 23:35:27 +01:00
3e18f2f09c Picklescan of model files
During getModel(), the server picklescans the model files for potential
malicious code in the pickled python objects. If a malicious file is
found, the web UI will show a big red error message, the makeImage
button will be disabled, and the user must remove the malicious file
and reload the UI page.
2022-11-16 22:34:02 +01:00
add09e52ef Fix typo in the installer's error messages 2022-11-16 20:56:11 +01:00
5429a509c6 Visual feedback for the save button in the system settings 2022-11-16 20:52:40 +01:00
3555fa36aa Update CHANGES.md 2022-11-16 19:40:33 +05:30
ee31519552 Merge pull request #489 from cmdr2/main
v2.4.6 - merge hotfix from main - bring back the VRAM usage (during startup) to what it was in the previous main version (v2.3.5)
2022-11-16 19:36:49 +05:30
06b41aee58 Fix - reduce the amount of VRAM occupied when the program starts up, this caused a regression and failures on GPUs with 4 gb or less of VRAM 2022-11-16 19:29:04 +05:30
cd19d50e1d Update CHANGES.md 2022-11-16 17:00:31 +05:30
a5e4eea5ca Smaller version numbers in CHANGES 2022-11-16 16:56:35 +05:30
c6a6270e16 Typo 2022-11-16 16:55:11 +05:30
18d9d2602a Add a 'What's New?' tab as a core plugin, which fetches the contents of CHANGES.md from the app's release branch 2022-11-16 16:54:28 +05:30
f7ec9f2073 Merge pull request #488 from JeLuF/beta
Add Change history
2022-11-16 16:05:24 +05:30
4c5f66185d Add Change history 2022-11-16 10:44:56 +01:00
105c1893cb Merge branch 'beta' of https://github.com/patriceac/stable-diffusion-ui into beta 2022-11-16 00:40:00 -08:00
061cee207f Delete modifiers-dnd.plugin.js 2022-11-16 00:39:41 -08:00
af4a925b54 Delete modifiers-dnd.plugin.js 2022-11-16 00:38:17 -08:00
a6f3e87921 Image modifiers drag-and-drop plugin 2022-11-16 00:35:02 -08:00
9764d9109f Merge remote-tracking branch 'upstream/main' into beta 2022-11-16 00:29:52 -08:00
46dfa57ee0 Allow the core project to ship UI plugins 2022-11-16 13:30:40 +05:30
2c861c65d4 Merge pull request #485 from cmdr2/beta
UI setting for preventing browser autostart
2022-11-16 12:45:51 +05:30
a59bac4b40 UI setting for preventing browser autostart 2022-11-16 12:43:46 +05:30
cf214bf367 Merge pull request #484 from cmdr2/main
Merge main
2022-11-16 12:29:09 +05:30
75724797f7 Don't show a 500 error when the config json file doesn't exist 2022-11-16 12:20:25 +05:30
d04aeb55ad Fix default render device 2022-11-16 12:16:46 +05:30
47bd6dc6b8 Fix render devices auto 2022-11-16 12:14:06 +05:30
5e0f525932 Merge pull request #483 from cmdr2/beta
v2.4.4
2022-11-16 12:10:01 +05:30
1f66daf2f3 Write the config script files only if necessary 2022-11-16 11:40:51 +05:30
ded9cb0358 Check if config contains update_branch before trying to write it to a script file 2022-11-16 11:36:04 +05:30
04f201933b space apart the stop button 2022-11-16 11:33:05 +05:30
f5ec1cb3a4 Don't show the list of files that have been copied on startup 2022-11-16 11:31:16 +05:30
6c23e3f534 Bump version 2022-11-16 11:19:42 +05:30
e99d54d1f6 Merge main 2022-11-16 11:19:10 +05:30
7f436061b8 RFC: how to handle %TMP% and %TEMP% - UNTESTED
`conda activate` fails if %TMP% or %TEMP% contains spaces. So instead of setting the temp variables in the installer steps, we need to set it at the beginning of the script. 

Would this break anything? 
https://discord.com/channels/1014774730907209781/1042190192049668106/1042190192049668106
2022-11-15 23:29:32 +01:00
3c71200eb4 Update index.html 2022-11-15 16:06:50 +05:30
f124cf8318 Make the task config summary labels bold 2022-11-15 16:06:35 +05:30
9d2b944063 Remove unused variable 2022-11-15 13:18:00 +05:30
8e1ec5903b Don't throw an exception when an invalid device is being checked for compatibility. Report and return false 2022-11-15 12:41:10 +05:30
5cf763d51f Add a 'Save' button in settings, to avoid starting/stopping threads while a user is still modifying their GPU settings 2022-11-15 12:22:55 +05:30
3546859fe5 Bump version 2022-11-15 11:05:39 +05:30
6530e45178 Merge pull request #478 from madrang/beta
Changed update_render_threads to use SetAppConfigRequest.
2022-11-15 11:04:52 +05:30
07f0036b2b Merge pull request #476 from JeLuF/patch-2
Incr. Server State Validtiy to 90s
2022-11-15 10:19:45 +05:30
5237f55a71 Removed extra line, use only save_render_devices_to_config 2022-11-14 22:29:55 -05:00
a108e5067d Typos in comments. 2022-11-14 22:20:21 -05:00
a4a24b1a1a Fixed calling get_device_delta with a single cuda device inside config.json at boot. 2022-11-14 22:14:03 -05:00
ffe0eb1544 Changed update_render_threads to use SetAppConfigRequest to set which devices are active.
Keep ImageRequest.render_device for affinity only. (Send a task to an already active device.)
2022-11-14 21:54:24 -05:00
288e8a65f3 Incr. Server State Validtiy to 90s
By default, healthCheck() is run every 5s. On background tabs, this may get extended. My tests have shown pings every 60s. The ping was older than 10s, so the condition in line 490 evaluates to `false` and the client tries to access the stream before the server is ready. By increasing the validity this can be avoided - at least until the browser runs the healthcheck even less often.

See https://discord.com/channels/1014774730907209781/1041811939380178964/1041812021018120262 for the analysis.
2022-11-14 23:18:03 +01:00
0ebfbca93e Merge pull request #475 from JeLuF/beta
🔥Fix system info for CPU mode
2022-11-14 22:41:38 +05:30
f22f57495e Fix system info for CPU mode 2022-11-14 17:55:36 +01:00
8786a9d21d Fix border color of the image task container 2022-11-14 21:25:57 +05:30
f06a97d30b Move system info into settings 2022-11-14 21:21:48 +05:30
2329c47faf Bump version 2022-11-14 21:13:38 +05:30
2967261acb Ensure that we only pick better GPUs than the current one, during the subsequent tasks 2022-11-14 21:13:24 +05:30
64ff1ecbb6 Formatting for mem free 2022-11-14 21:02:17 +05:30
8707f88c07 Show mem free info 2022-11-14 20:35:47 +05:30
36846618ec Allow configuring whether the browser is opened by default 2022-11-14 20:15:54 +05:30
0cb2f19e29 Mark multi GPU as experimental in the UI 2022-11-14 20:06:20 +05:30
125a50ae87 Include the gpu id in the gpu list and system info 2022-11-14 20:01:57 +05:30
9d37ea23f8 Bump version 2022-11-14 19:53:55 +05:30
31617ae340 Show a system info tab, which shows the active GPUs 2022-11-14 19:53:40 +05:30
950614fb81 Bump version 2022-11-14 19:42:57 +05:30
14bbd7b7ae Merge pull request #474 from JeLuF/beta
Add paste button next to copy button
2022-11-14 19:06:52 +05:30
257cd34101 Merge branch 'beta' into beta 2022-11-14 19:06:35 +05:30
ab6ec3a9b7 Fix - setting can be null sometimes (autosave) 2022-11-14 18:10:23 +05:30
39814a89b6 Fix - setting can be null sometimes (autosave) 2022-11-14 18:09:25 +05:30
24fbbf8aa8 Remove unused variables 2022-11-14 16:26:16 +05:30
338ceffa6d Use 'auto' as the default render_device 2022-11-14 15:14:58 +05:30
371e104b00 Pick the device id 2022-11-14 13:43:37 +05:30
d5aba8eaf1 Show free/total mem while starting up 2022-11-14 13:40:55 +05:30
1d2b3a4ed8 Hide/show the GPUs list depending on whether auto is selected 2022-11-14 13:14:33 +05:30
f904945d40 Disable the GPU list if auto is enabled 2022-11-14 13:02:36 +05:30
027b2e1b88 Use the 65 percentile of free_mem for GPU selection, instead of 75 percentile 2022-11-14 12:26:21 +05:30
d79eb5e1a6 Typo 2022-11-14 11:51:56 +05:30
f6651b03b5 Workaround to run gfpgan on cuda:0 even if it's not enabled in the multi-gpu setup 2022-11-14 11:51:18 +05:30
5f880a179c Remove idle CPU unloading (when GPUs are active), because now a CPU can never be used along with GPUs 2022-11-14 11:24:30 +05:30
ea03fd22db Start on multiple GPUs by default (top 75 percentile by free_mem); UI selection for 'cpu' or 'auto' or a list of specific GPUs, which is now linked to the backend; Dynamically start/stop render threads for the devices, without requiring a full program restart 2022-11-14 11:23:22 +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
e561e4de0b Visual feedback for the copy and paste icons 2022-11-14 01:58:24 +01:00
1c3d5cd851 Add paste button next to copy button 2022-11-14 01:23:04 +01:00
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
332f2b0678 Hotfix for CSS layout regression 2022-11-12 19:04:23 -08: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
a19ba40672 Typo 2022-11-12 13:31:59 +05:30
3983cb001f Save the VAE model to the metadata text file 2022-11-12 13:29:24 +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
78b464b404 Merge pull request #464 from madrang/beta
Always return a byte buffer. Sending the picture as URL text fails in some browsers.
2022-11-12 11:51:52 +05:30
aa21115e26 Always return a byte buffer. Sending the picture as URL text fails in some browsers. 2022-11-11 20:44:39 -05:00
a39f845835 current_vae_path needs to be global 2022-11-11 19:30:33 +05:30
3fdd8d91e2 Handle device init failures and record that as an error, if the GPU has less than 3 gb of VRAM 2022-11-11 16:13:27 +05:30
c13bccc7ae Fix the error where a device named 'None' would get assigned for incompatible GPUs 2022-11-11 15:43:20 +05:30
b4f7d6bf25 Bump js version 2022-11-11 15:12:04 +05:30
fa0c2f7138 Temp change to get beta working and use a single GPU until the rest of the changes come through 2022-11-11 15:09:25 +05:30
453cc2a951 Bump version 2022-11-11 14:46:27 +05:30
bd56795c62 Switch to using cuda:N instead of N (integer device ids) 2022-11-11 14:46:05 +05:30
2c54b7f289 Remove the WIP line for render devices 2022-11-11 14:43:14 +05:30
cd5f847b55 Merge branch 'beta' of github.com:cmdr2/stable-diffusion-ui into beta 2022-11-11 12:03:14 +05:30
a25544baea Fix the editor width on Chrome 2022-11-11 12:02:58 +05:30
39b6c5d6f4 Merge remote-tracking branch 'upstream/beta' into beta 2022-11-10 22:30:28 -08:00
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
f954542dda Merge pull request #461 from JeLuF/dontleave
Add event listener beforeunload
2022-11-11 10:58:15 +05:30
9fec7d236c Merge branch 'beta' of github.com:cmdr2/stable-diffusion-ui into beta 2022-11-11 10:48:47 +05:30
67656accf8 Bump css version. This is annoying 2022-11-11 10:48:30 +05:30
64952a536c Merge branch 'beta' of github.com:cmdr2/stable-diffusion-ui into beta 2022-11-11 10:47:52 +05:30
65e0d5f511 Attempt to fix horizontal resizing of the prompt textbox, thanks @Bilbo 2022-11-11 10:44:52 +05:30
903acff924 Adding Use Settings 2022-11-10 18:36:39 -08:00
5a06946469 Add event listener beforeunload
When closing the window, a warning is shown if there are any render results.
2022-11-10 23:23:20 +01:00
baef31b2c7 Send 'auto' as the render_device from the UI
, if no GPU is selected and CPU is unchecked)
2022-11-10 22:23:15 +05:30
b9a12d1562 Restrict device selection id to 'cpu' or integers (and 'auto' in the initial device selection functions) 2022-11-10 20:03:11 +05:30
3f26d03166 Show GPU list in the UI only if the PC has more than 1 GPU 2022-11-10 16:34:01 +05:30
1fed3ad532 Don't propagate events in the Stop Task button 2022-11-10 15:33:39 +05:30
929b245f5f Merge branch 'beta' of github.com:cmdr2/stable-diffusion-ui into beta 2022-11-10 14:59:11 +05:30
0da6354825 Press Ctrl+Enter to start a task 2022-11-10 14:59:01 +05:30
716a28891d Merge pull request #460 from JeLuF/helppage
Add Wiki TOC to the Help&Community tab
2022-11-10 13:17:26 +05:30
93a2e91694 Use theme variable for bottom border design 2022-11-10 00:44:42 +01:00
4913dc1aad Replace hr by border-bottom 2022-11-09 23:57:48 +01:00
087df18fea Add Wiki links to help&community page 2022-11-09 23:42:56 +01:00
058ce6fe82 UI-side changes for selecting multiple GPUs, and keeping the Use CPU option synchronized with the backend. This change isn't ready to be shipped, it still needs python-side changes to support the req.render_device config 2022-11-09 19:17:44 +05:30
087c10d52d Sort models by name 2022-11-09 17:35:55 +05:30
18292e447c Make the models dir if required 2022-11-09 16:28:58 +05:30
6c1dda47c0 Don't change the page when something other than an image or text file is dropped into the page (or an image is dropped outside the init image box) 2022-11-09 15:21:41 +05:30
ad1fc8f3d8 Bump version 2022-11-09 13:47:21 +05:30
bca98269bb Fix a bug where the custom image modifiers button would close the modifiers panel 2022-11-09 13:46:50 +05:30
1bebaf933d Bring back the old style panels for image settings and modifiers 2022-11-09 13:43:43 +05:30
166eb996a9 Bump versions 2022-11-09 12:26:27 +05:30
10fae34754 Bump js/css versions 2022-11-09 12:25:16 +05:30
aa4d97e8df Merge pull request #458 from mdiller/mdiller_ui_reorganize
UI Reorganization & Adding Tabs
2022-11-09 12:22:38 +05:30
dbbb9d7877 Temporarily remove the default-on behavior for GFPGAN, until the CPU version is fixed 2022-11-09 11:25:50 +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
3ff213b3e8 removed status on mobile 2022-11-08 21:51:12 -08:00
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
69c7f22053 Merge branch 'beta' into mdiller_ui_reorganize 2022-11-08 21:22:22 -08:00
75a964167a hid the now shown collapsible handle 2022-11-08 21:00:56 -08:00
c5768c81e1 Merge pull request #453 from patriceac/beta
Fix modifier and system settings popup position
2022-11-09 10:23:12 +05:30
4eb2b818e7 shrank system settings a bit so it fits on monible 2022-11-08 20:47:55 -08:00
f742aad810 Merge pull request #446 from JeLuF/sd-ui-bind
Protect SD_UI_BIND_PORT and SD_UI_BIND_IP in config files
2022-11-09 10:09:28 +05:30
e22b171b7b Merge pull request #445 from JeLuF/err-handle
Improve error handling
2022-11-09 10:08:55 +05:30
d061eb2c64 updated to work decently for mobile 2022-11-08 20:37:49 -08:00
69aa115178 updated the about tab to be help and community, and fixed footer to act nicely 2022-11-08 20:19:31 -08:00
e175b87384 updated so tabs work now, and we have a settings tab and an about tab 2022-11-08 19:54:41 -08:00
f216ee739a updated with latest updates for this support 2022-11-08 19:22:14 -08:00
16d6644573 Merge pull request #455 from JeLuF/util-js
Fix: Uncaught TypeError: Cannot set properties of null
2022-11-09 08:22:46 +05:30
38afc6e6f8 Fix: Uncaught TypeError: Cannot set properties of null 2022-11-08 19:05:28 +01:00
8f1d214b12 Bring back CPU unloading of models when idle for a while (applies only when GPUs are present) 2022-11-08 19:23:35 +05:30
51fb1a43de Temporarily disable the idle CPU unloading behavior, since it's not clear whether it'll reload the model if a future request for the CPU is received after it has unloaded the model 2022-11-08 19:02:21 +05:30
a86b6bfbd6 Fix a bug with drag-and-drop where the upscale dropdown would not get enabled/disabled based on the setting 2022-11-08 18:46:55 +05:30
1176ddcc85 Fix a bug in drag-and-drop where an empty Negative Prompt line would result in the next line getting assigned to negative prompts; Simplify the drag-and-drop text file parsing logic to use a single algorithm, the files are small enough that we don't need over-optimization and confuse new developers 2022-11-08 18:44:11 +05:30
fa080e380c Fix a bug where images could no longer be dragged and dropped onto the initial image box 2022-11-08 18:14:26 +05:30
57c3acd9d8 Single line comment for Live Preview 2022-11-08 17:51:51 +05:30
302cf5b10b Show a tooltip over the ? help buttons 2022-11-08 17:49:46 +05:30
e2a9e81dbc Show tooltips on 'Copy Image Settings' 2022-11-08 17:40:47 +05:30
b1cf7391ce Add links to help docs for certain UI elements 2022-11-08 17:19:20 +05:30
9bc7521de0 Make custom VAE an Image Setting, rather than a System Setting; Don't load a VAE into memory by default 2022-11-08 16:54:15 +05:30
a68ebd2b76 Fixing the popup position on larger screens
Fixing the popup position on larger screens; Smaller screens still get the current rendering experience.
2022-11-08 02:17:26 -08:00
47f7c938ae Update main.css 2022-11-07 23:15:59 -08:00
842e7e559e Update bootstrap.bat 2022-11-08 10:30:26 +05:30
bd5a6e6fb3 FS check, CV2.DLL fix, cleanup
- Only install on NTFS (FAT installations fail)
- Ask the user to install the Media Feature Pack on Windows 10 N (fixes python cv2 errors)
- Code cleanup
2022-11-08 00:20:36 +01:00
67cca3bc00 Print the devices for which rendering threads have started; Prettier print of the model data 2022-11-07 18:26:10 +05:30
90b1609d4e device_selection is already a string, since we've used string functions before this line 2022-11-07 18:08:43 +05:30
abbfae2fc0 Simplify the logic used for displaying the GFPGAN warning 2022-11-07 17:55:27 +05:30
b52b854270 Merge pull request #444 from madrang/beta
Remove prompt_strength and init_image when not using in-painting
2022-11-07 14:43:48 +05:30
58b759f652 Fix tabs to spaces 2022-11-06 16:50:23 +01:00
74ca756a53 Protect SD_UI_BIND_PORT and SD_UI_BIND_IP in config files 2022-11-06 00:27:11 +01:00
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
3576214920 Remove prompt_strength and init_image when not using in-painting 2022-11-05 13:39:19 -04:00
f964fe3750 Add on/off support for parsing boolean. 2022-11-05 13:33:38 -04: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
749c72e6a6 Fix https://github.com/cmdr2/stable-diffusion-ui/issues/441 - numerical validation 2022-11-04 19:48:34 +05:30
c3129a40f1 Merge pull request #440 from madrang/dragNdrop
Drag&Drop Fixes
2022-11-04 09:13:14 +05:30
d04aa89812 Fix 'Use Upscaling' dropdown getting blank on False. 2022-11-03 20:34:51 -04:00
d5f854d376 Fix use_face_correction not disabling on false 2022-11-03 20:34:12 -04:00
63dcb8cfe1 Add a link to the wiki to the "Help & Community" dropdown. 2022-11-03 20:39:08 +01:00
6c57fa078b Merge pull request #437 from madrang/dragNdrop
Requested fixes for Drag&Drop
2022-11-03 13:13:41 +05:30
c3cc75feff Adds a list of properties to not export by default. 2022-11-03 03:16:20 -04:00
d2e6011089 Windows paths... 2022-11-03 03:12:11 -04:00
5a18144366 Enable/disable seedField when updating randomSeedField.checked 2022-11-03 03:11:58 -04:00
8a0a22bfb0 Merge pull request #427 from madrang/dragNdrop
Add support for drag&drop for the text files made by the backend
2022-11-03 11:41:21 +05:30
950b226374 Moved copy icon css to main.css 2022-11-03 02:09:42 -04:00
74e64a4387 Merge pull request #435 from JeLuF/sanitize
Sanitize session id's before using them as path components
2022-11-03 10:57:12 +05:30
59e4c1cf79 Sanitize session id's before using them as path components 2022-11-03 00:43:44 +01:00
9b89ede9c4 Only require 8GB instead of 80GB
80GB was a leftover from the code test
2022-11-03 00:28:47 +01:00
bf205de3a1 NSIS script enhancements
- Enable Unicode support
- Activate LongPathsEnabled if the user tries to install into a directory 
  with more than 30 characters length
- Change welcome text page. No need to close other programs during our setup
- Warn if the user has less than 8GB of RAM
- Formatting, comments
2022-11-02 21:12:20 +01:00
045ad78bb9 Added calls to update sliders. 2022-11-02 10:53:48 -04:00
c0350e5be7 Moved file ext to a var. 2022-11-02 10:45:51 -04: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
2b3e38f77e Merge pull request #421 from madrang/beta
Fix plugins needing to specify many params or they would be missing in the render request.
2022-11-02 12:34:45 +05:30
d04fe5d582 Increase CSS version 2022-11-02 12:23:36 +05:30
17ab4caa5e Merge pull request #426 from ayunami2000/beta
Improve UI on mobile devices
2022-11-02 12:22:18 +05:30
976bc727dd Merge pull request #422 from madrang/device-select
Implement complete device selection in the backend.
2022-11-02 12:05:59 +05:30
484e53cc08 made first large swathe of changes for ui reorganization 2022-11-01 23:03:05 -07:00
b09b80933d Print device name on task start and complete to avoid doubt from users on what device selected the task. 2022-11-01 22:28:10 -04:00
8165086d02 NSIS scripts 2022-11-02 01:07:52 +01:00
82f14b087a NSIS Readme 2022-11-02 01:07:23 +01:00
93b3419737 Better human formatted JSON 2022-11-01 04:54:38 -04:00
19290fe467 Merge pull request #431 from JeLuF/patch-8
Copy CUDA_VISIBLE_DEVICES to config.*, it it has been set
2022-11-01 13:40:11 +05:30
d2f679030b Don't put CUDA_VISIBLE_DEVICES hints if it's already set 2022-11-01 01:16:29 +01:00
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
268d7495cc Naming... 2022-10-31 01:13:04 -04:00
ce16e61e63 Adds a copy as JSON button. 2022-10-31 01:02:23 -04:00
f92bca58fa Lines endings... 2022-10-31 01:01:56 -04:00
83d541b60d Fixed model parsing... 2022-10-30 23:41:26 -04:00
965efc3a13 Restore old values if invalid values for the dropdown was used. 2022-10-30 23:35:42 -04:00
d656c34bd4 Add support for drag&drop for the text files made by the backend and also supports JSON. 2022-10-30 23:21:39 -04:00
7f151cbeba Copy CUDA_VISIBLE_DEVICES to config.*, it it has been set
Don't delete CUDA_VISIBLE_DEVICES settings when generating a new config file
2022-10-31 00:48:18 +01:00
bc2f9204e9 Improve UI on mobile devices 2022-10-30 18:16:31 -04:00
a922a93016 Can work with one or more params, don't need a minimum of two.
Still works just the same.
2022-10-30 14:09:12 -04:00
eb596ba866 Allow start_render_thread to proceed faster in case of failure. 2022-10-30 06:04:06 -04:00
2208545612 Don't display this warning if on CPU. 2022-10-30 05:39:45 -04:00
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
c687091ce9 Only return valid data for alive threads. 2022-10-30 01:38:32 -04:00
eb994716e6 Indentation... 2022-10-30 01:33:17 -04:00
70acc8a7c0 Syntax... 2022-10-29 19:02:07 -04:00
bf97781232 Don't let users register the same device twice. 2022-10-29 18:57:31 -04:00
099727d671 Added auto unload to CPU if GPUs are active. 2022-10-29 18:57:10 -04:00
6229cdb1ba Added a missing device_name 2022-10-29 17:47:45 -04:00
b7a663ed20 Implement complete device selection in the backend. 2022-10-29 17:34:53 -04:00
3bd97352ba Don't reset reqBody, only replace using req as we use a new task object created from UI inputs.
Fix plugins needing to specify many params or they would be missing in the render request.
2022-10-29 14:47:58 -04: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
5e22360cb1 Change the JS/CSS version 2022-10-29 18:10:23 +05:30
840348b4eb 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:09:04 +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
cf04738594 Merge pull request #420 from madrang/beta
Missing .lower() cause CUDA:0 to fail check where cuda:0 works.
2022-10-29 15:01:13 +05:30
03757632cf Missing .lower() cause CUDA:0 to fail check where cuda:0 works. 2022-10-29 04:33:14 -04:00
e818f5a93f Bump version 2022-10-29 12:29:28 +05:30
ab9b08770a Merge pull request #417 from mdiller/mdiller_parameters
Moved System Settings & Reworked into "Parameters"
2022-10-29 12:04:21 +05:30
40df8b68ad Merge pull request #418 from madrang/beta
Changed failure in start_render_thread to return false instead of throwing exception
2022-10-29 11:33:36 +05:30
9f5202fee3 Improved readability and comments. 2022-10-29 00:43:02 -04:00
902ccbd203 Don't try to start cuda:0 if auto used cpu mode. 2022-10-29 00:36:26 -04:00
4675da4d16 Display warning on start failure.
Removes spam from exception and continue starting other devices.
2022-10-28 22:53:55 -04:00
86da27a7a1 Moved wait outside lock and now returns false on failure. 2022-10-28 22:52:00 -04:00
fc2a6567da Moved import before use of runtime.thread_data.device 2022-10-28 22:51:04 -04:00
7c611d9b62 added some shadow and animation to popups 2022-10-28 18:41:41 -07:00
784c7465d1 updated settings labels 2022-10-28 18:31:46 -07:00
301af7bd7a added parameters 2022-10-28 18:25:54 -07:00
09c11a385d normalized popups 2022-10-28 16:48:32 -07:00
ef6f491d94 Write lines, please 2022-10-28 22:42:11 +05:30
9dcef00fbb New lines for config.sh 2022-10-28 22:35:04 +05:30
e781e5dd43 Need to wrap the filter() output in a list 2022-10-28 22:30:05 +05:30
d3e672d811 Replace os-specific newlines with writelines() 2022-10-28 22:23:52 +05:30
dad1554ec2 Fix a bug where config.bat would not get written properly 2022-10-28 21:07:18 +05:30
30bf96c6cd Fix a bug where beta wouldn't switch properly because the config.bat/sh files weren't being written 2022-10-28 21:00:25 +05:30
a8c16e39b8 Support custom VAE files; Use vae-ft-mse-840000-ema-pruned as the default VAE, which can be overridden by putting a .vae.pt file inside models/stable-diffusion with the same name as the ckpt model file. The UI / System Settings allows setting the default VAE model to use 2022-10-28 20:06:44 +05:30
79a7cd2938 Merge pull request #414 from madrang/beta
Set online after preload. Move ident to include in if check.
2022-10-28 13:54:44 +05:30
26562e445f Set online after preload. Move ident to include in if check. 2022-10-28 04:09:34 -04:00
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
2432491bfc Merge pull request #411 from madrang/beta
Apply force_full_precision if was set on device_select.
2022-10-28 11:50:16 +05:30
a09ce3e026 Merge pull request #412 from mdiller/mdiller_progressbar
Quick Fix for Progressbar Behavior
2022-10-28 11:49:42 +05:30
c52fc843f6 Comment... 2022-10-28 02:09:11 -04:00
02240bda25 Moved up to not duplicate if statement. 2022-10-28 02:05:48 -04:00
0185ef7c83 Apply force_full_precision if was set on device_select. 2022-10-28 02:02:09 -04:00
7d29b9901c updated progressbar to end more consistently 2022-10-27 22:47:08 -07:00
ae553dfed3 Merge pull request #410 from madrang/beta
Only default to cpu on auto or current when cuda not available.
2022-10-28 10:43:28 +05:30
71c6beadb4 Only default to cpu on auto or current.
Not when a specific device was requested.
2022-10-28 01:09:38 -04:00
d939629c09 Bump version 2022-10-28 10:39:23 +05:30
0a569146a8 Merge pull request #406 from mdiller/mdiller_progressbar
Fixed/Implemented Progressbar
2022-10-28 10:34:03 +05:30
d5a012d49f Merge pull request #407 from madrang/beta
Wait until device is fully ready before proceeding.
2022-10-28 10:28:16 +05:30
22a11769fa Enable preload on cpu when no other devices are alive. 2022-10-27 21:57:50 -04:00
7dc7ba9977 Removed old comments. 2022-10-27 21:47:44 -04:00
fa4059a4b9 Removed all async code since now start_render_thread wait for init to complete making this useless. 2022-10-27 21:40:16 -04:00
7f4786f9dd Wait until device is fully ready before proceding. 2022-10-27 20:27:21 -04:00
5a6e7a46d1 added progressbar 2022-10-27 17:03:09 -07:00
9f90749f99 Merge pull request #405 from JeLuF/patch-6
Add disk space requirements
2022-10-28 00:22:08 +05:30
0dfaf9159d Put back the check to only preload on GPU 2022-10-28 00:04:33 +05:30
5d8bda1178 Merge pull request #404 from cmdr2/multi-gpu
Support for multiple GPUs, and improvements to RAM and VRAM usage
2022-10-27 23:52:11 +05:30
9ad1e0d529 Allow the user to specify any disk path to the model, in the config 2022-10-27 23:39:29 +05:30
389e3397ec Preload the model even in the CPU mode 2022-10-27 23:17:41 +05:30
284b95213e Fix a bug where the device wouldn't get set if no cuda-compatible hardware was found 2022-10-27 22:59:55 +05:30
952854f64e Revert 554650c18d 2022-10-27 22:59:17 +05:30
554650c18d Fix a bug where the device wouldn't get set if no cuda-compatible hardware was found 2022-10-27 22:51:45 +05:30
01a2fa7c2d Fix a bug where the default model would not load if the user hadn't already configured a custom model (e.g. in a fresh installation); Check for the model in the models/stable-diffusion folder first, before checking in the direct folder 2022-10-27 22:34:23 +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
7d03719816 Merge pull request #403 from cmdr2/main
Merge main
2022-10-27 20:50:09 +05:30
7c5bbca2fa Bump version 2022-10-27 20:49:05 +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
3fb5d886dc Merge pull request #398 from madrang/mGpu-crashHandling
mGpu crash handling
2022-10-27 13:44:26 +05:30
b57cd8d5c2 Merge pull request #397 from madrang/mGpu-fixtype
Fix TypeError: string indices must be integers
2022-10-27 13:44:19 +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
d3df113fb0 When reduced_memory is True, on crash only move model back to Cpu. 2022-10-26 16:52:31 -04:00
06c2ab045a Fix TypeError: string indices must be integers 2022-10-26 16:14:29 -04:00
6d43e0951c Update on_sd_start.sh 2022-10-27 00:49:32 +05:30
ec14429238 Merge pull request #348 from madrang/multi-gpu
Multi gpu
2022-10-26 19:33:44 +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
ae40b6ba8c Missed a is_alive check in the conversion. 2022-10-25 03:00:50 -04:00
d482427e0d Merge branch 'beta' of https://github.com/cmdr2/stable-diffusion-ui.git into multi-gpu 2022-10-25 02:51:31 -04:00
c41baf3aeb Moved img_id creation inside save image loop. 2022-10-25 02:10:52 -04:00
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
189d31cc29 Specify update_ttl on all get_cached_task calls. 2022-10-24 05:12:08 -04:00
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
fc875651d3 Removed unused vars 2022-10-23 05:00:21 -04:00
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
0d62123a0b Replaced missing gpu_name by device_name 2022-10-22 21:28:12 -04:00
28fed6281f Merge branch 'beta' into multi-gpu 2022-10-22 21:20:02 -04:00
1ec95d42ba Missing '?' in case renderRequest is ever undefined. 2022-10-22 21:19:42 -04:00
8adf965d0b Formatting changes. 2022-10-22 19:02:02 -04:00
026dd38480 Merge branch 'beta' of https://github.com/cmdr2/stable-diffusion-ui.git into multi-gpu 2022-10-22 18:07:22 -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
364e364429 Added get_cached_task to replace task_cache.tryGet in server.py
Now updated cache TTL on /stream and temp images endpoints.
Keep images alive longer when browser keeps reading the endpoints.
2022-10-22 13:52:13 -04:00
46a46877ed Missing model_path replaced by model_name 2022-10-22 13:49:23 -04:00
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
2c1a897c4e Missing newline. 2022-10-22 12:50:53 -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
344dd92c85 Improved checks on '/render' requests 2022-10-22 12:29:01 -04:00
4167c65acf Merge branch 'beta' of https://github.com/cmdr2/stable-diffusion-ui.git into multi-gpu 2022-10-22 12:17:12 -04:00
cd6d49860f Missing a 'r' in progress 2022-10-22 01:23:39 -04:00
8a10fcf7ea updated print statement. 2022-10-22 00:34:33 -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
3b5f96a133 Fixed stopping tasks and more cleaning. 2022-10-21 22:45:19 -04:00
ce2b711b1f Newlines... 2022-10-21 21:44:15 -04:00
667fb438cb Merge branch 'beta' of https://github.com/cmdr2/stable-diffusion-ui.git into multi-gpu
# Conflicts:
#	ui/media/js/main.js
2022-10-21 21:10:02 -04:00
7befa94e6d More comments and cleanup. 2022-10-21 20:56:24 -04:00
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
88ef1a3c5b Moved time before model.to 2022-10-21 20:22:34 -04: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
ccb7a553c2 Memory improvements 2022-10-21 19:34:29 -04: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
1442748f58 When starting with profiler cuda devices are slower to init. 2022-10-21 03:53:26 -04:00
d17e216f91 Replace the thumbnail image for glass caustics image modifier 2022-10-21 13:08:23 +05:30
56ed4fe6f2 Fix VisualStudio Type Warning. 2022-10-21 01:30:49 -04:00
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
849d1d7ebd Merge branch 'beta' of https://github.com/cmdr2/stable-diffusion-ui.git into multi-gpu
# Conflicts:
#	ui/media/js/main.js
#	ui/sd_internal/runtime.py
#	ui/server.py
2022-10-20 20:08:23 -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
fc8660df78 Faster response on invalid settings when CPU was specified with GFPGANer. 2022-10-19 05:19:16 -04:00
4e5ddca3bd Display the failure detail when there is one at that step.
Was checking the json object, not the server response.
2022-10-19 05:10:37 -04:00
3bdc90451a Dont preload on cpu. 2022-10-19 04:34:54 -04:00
a036b2981a Removed forgotten mention of CPU in message to user. 2022-10-19 04:31:57 -04:00
8fae83dab7 Print value to console for better debug from logs. 2022-10-19 04:26:09 -04:00
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
ef68e5b13d Added warning about validating config. 2022-10-19 04:16:46 -04:00
21afe077d7 Removed Cpu from the devices allowed to run GFPGANer.
Added clear error for the user.
2022-10-19 03:02:26 -04:00
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
3fc66ec525 Removed empty lines left over from merge. 2022-10-19 00:27:51 -04:00
44191cd908 Merge pull request #357 from rbertus2000/beta
fixed img_id for parallel renders
2022-10-19 09:57:05 +05:30
0da0c6bd77 Merge branch 'beta' of https://github.com/cmdr2/stable-diffusion-ui.git into multi-gpu 2022-10-19 00:26:09 -04:00
b5f6e9d01b Merge pull request #357 from rbertus2000/beta
fixed img_id for parallel renders
2022-10-19 09:52:58 +05:30
6098b196dc Text header, comments and better validations. 2022-10-18 23:58:55 -04:00
0922349344 made some updates and moved some stuff to auto-save js 2022-10-18 20:49:58 -07:00
53cdeeff03 More fixes to devices changing names. 2022-10-18 21:08:04 -04:00
fcdb086daf Fixed is_alive to work with devices that can change name after init. 2022-10-18 20:33:37 -04: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
cfd6751777 Merge branch 'beta' of https://github.com/cmdr2/stable-diffusion-ui.git into multi-gpu 2022-10-18 13:21:26 -04:00
5e461e9b6b Fixed is_alive with render_threads that can update the device name after starting. 2022-10-18 13:21:15 -04: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
940236b4a4 Merge branch 'beta' of https://github.com/cmdr2/stable-diffusion-ui.git into multi-gpu 2022-10-18 03:23:42 -04:00
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
3c8692d06c Merge branch 'beta' of https://github.com/cmdr2/stable-diffusion-ui.git into multi-gpu 2022-10-18 02:52:50 -04:00
efffca83fe Merge pull request #353 from mdiller/mdiller_themes
Theme Selection
2022-10-18 12:11:19 +05:30
04fe81e001 Merge branch 'HTTPException-fix' into multi-gpu
# Conflicts:
#	ui/server.py
2022-10-18 02:36:57 -04:00
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
578b3ba4f4 Force encoding to utf-8 on text file operations Fixes #332
# Conflicts:
#	ui/server.py
2022-10-17 23:15:36 -04:00
5b0b582039 Force encoding to utf-8 on text file operations Fixes #332 2022-10-17 22:38:29 -04:00
e24be913e5 Merge branch 'beta' into multi-gpu 2022-10-17 21:35:24 -04:00
4d3358ba66 Fixed file path bugs introduced by mistake and made img_id sequential based on time for better sorting of renders. 2022-10-17 21:29:14 -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
87f93b34a3 Fixed a typo when adding a comment. 2022-10-17 14:44:53 -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
c92129ac63 Improved detection of missing cuda:0 and added warning to console about how to fix. 2022-10-17 03:32:23 -04:00
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
554b67a2f0 Fixing bug in is_alive. 2022-10-17 01:05:51 -04:00
012243a880 Process GPU tasks on CPU when there are no cuda devices at all. 2022-10-17 01:05:27 -04:00
d4a348a2b2 Process GFPGANer on cuda:0 when possible, otherwise use cpu. 2022-10-16 23:12:46 -04:00
1d4c5cc96f Added clear error response when submitting tasks that requires GFPGANer if cuda:0 and cpu rendering is disabled. 2022-10-16 23:07:55 -04:00
41bfb96b6b Fixed bug in task_manager.is_alive and added way to check for first device. 2022-10-16 23:06:41 -04:00
994d62ac65 Added a clear error message when targeting CPU if not enabled in config. 2022-10-16 22:26:05 -04:00
7c72608e1c First draft for Multi-GPU support 2022-10-16 21:41:39 -04:00
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
10bcfdd6b2 Revert "Merge branch 'react' into main"
This reverts commit 41ea9814e8, reversing
changes made to 06c8a004d8.
2022-10-07 20:01:15 +05:30
41ea9814e8 Merge branch 'react' into main 2022-10-07 20:00:27 +05:30
bccf7e3f69 Merge pull request #293 from cmdr2/main
Merge from main
2022-10-07 19:58:49 +05:30
06c8a004d8 Remove the old dev console scripts 2022-10-07 19:52:31 +05:30
4ab90fb14d Merge branch 'main' of github.com:cmdr2/stable-diffusion-ui 2022-10-07 19:48:40 +05:30
54d8feeaf0 Rename dev console script 2022-10-07 19:48:24 +05:30
23d20c918f Merge pull request #292 from cmdr2/beta
Custom Models; Reduce RAM usage; JPG/PNG option
2022-10-07 19:45:17 +05:30
10012d7125 Merge branch 'main' into beta 2022-10-07 19:38:53 +05:30
d70ea854b1 Create the custom model instruction file even on existing installations 2022-10-07 19:36:18 +05:30
8c576ece28 Instructions for where to place the custom ckpt file 2022-10-07 19:33:52 +05:30
e0c0935d3a Merge pull request #275 from caranicas/react-base-tag-upgrade
React base Big Update
2022-10-07 19:14:24 +05:30
ab987e73c6 Copy the dev console script for linux on the first restart 2022-10-07 18:50:07 +05:30
cec203a6db Allow saving in jpeg or png format; Default to saving in jpeg 2022-10-06 15:05:34 +05:30
cf8bb9efb0 Don't reload the model when using an initial image; Work in half-precision for txt2img as well, no change in the output image noticed 2022-10-06 14:42:47 +05:30
201a053025 Support an arbitrary number of custom models, placed in the models/stable-diffusion folder. Shows an option in the UI to select which model to use 2022-10-06 14:28:02 +05:30
703f987825 Copy the dev console script on the first update. Temporary until enough people have this update 2022-10-06 11:58:32 +05:30
4e3d677d8e Developer console, to enter the activated conda environment easily for debugging and fixing the environnment 2022-10-06 11:58:27 +05:30
aab90130d2 Copy the dev console script on the first update. Temporary until enough people have this update 2022-10-06 11:25:14 +05:30
9321dfdd89 Developer console, to enter the activated conda environment easily for debugging and fixing the environnment 2022-10-06 10:37:41 +05:30
2607ef5fe0 working positive and negative prompts 2022-10-02 18:18:35 -04:00
84b291a57a built 2022-10-01 20:30:46 -04:00
3271c5a60b react-base-history-tab 2022-10-01 20:25:27 -04:00
79bb66f535 better layout grid 2022-10-01 18:46:22 -04:00
1616885e7f hide history 2022-10-01 17:01:20 -04:00
85045c3e9c wip 2022-10-01 08:19:24 -04:00
4710d18e33 slight adjustment 2022-09-30 19:07:16 -04:00
3da75494b0 type fixes and build 2022-09-30 17:17:22 -04:00
ac021f38da build 2022-09-30 16:51:03 -04:00
d0a2c36f6c tightened up themeing and cards more and more 2022-09-30 16:48:20 -04:00
9facc9379f getting the cards and tabs sorted out 2022-09-30 14:52:21 -04:00
a0f4e2659b working on cards and backgrounds 2022-09-30 12:54:23 -04:00
4dfa3d8372 cleaned and built 2022-09-30 12:29:42 -04:00
30563ee04c all buttons are a recipe now 2022-09-30 12:23:18 -04:00
3fa7594fcc move to hsl color system 2022-09-30 11:33:39 -04:00
ccfa32ce93 Report the error in the UI. Regression after switching to the task queue 2022-09-30 10:53:30 +05:30
fcb41e30dc Fix a bug with the linux script, where the file size check would fail if the group name had spaces 2022-09-30 10:45:08 +05:30
5ed6bba412 clean build 2022-09-29 14:26:06 -04:00
50e929eb0c working queue 2022-09-29 14:23:12 -04:00
129839ce21 decent queue display 2022-09-29 12:54:13 -04:00
fd2961ecb9 Merge branch 'react-base' into react-base-queue 2022-09-29 09:03:52 -04:00
e506d988e2 wip 2022-09-29 09:02:43 -04:00
196649c0e9 Use the correct seed from the response 2022-09-29 13:55:09 +05:30
12182ee04f Newer images go on top 2022-09-29 13:52:48 +05:30
5db64526cc Fix a bug where batches would overwrite the previous images inside a task 2022-09-29 13:43:25 +05:30
5c2ec70eb4 Hide the sampler field when an output image is used as the new input 2022-09-29 13:12:01 +05:30
24a2c6251f Remove log statement 2022-09-29 13:08:58 +05:30
0d035d9ae9 Remove unnecessary semicolons 2022-09-29 13:08:42 +05:30
a28f1294e2 Integrate with beta; Use the outputContainer for the task; Don't show the info while a live preview is generating; Use the local task container reference instead of a seed-based identifier (will fail if the seed is same across two tasks) 2022-09-29 13:01:18 +05:30
a3b0cde59d Merge pull request #242 from Hakorr/main
Image item refactor
2022-09-29 12:03:45 +05:30
c2dec9eac4 Merge branch 'haka-fix' into main 2022-09-29 12:00:44 +05:30
0fdb49f168 Merge pull request #260 from caranicas/react-base-nav
React base - Nav, Audio, Display,
2022-09-29 11:58:04 +05:30
e86d02765f properly styled buttons 2022-09-28 18:38:47 -04:00
6e877aea02 added stop and queue clear 2022-09-28 18:14:18 -04:00
330f1577fd tightened up center display 2022-09-28 16:29:11 -04:00
ff980591c3 tightened up center display 2022-09-28 15:40:43 -04:00
60992ae492 fix up types, and display id 2022-09-28 13:34:00 -04:00
1b439c15f6 added audio ding 2022-09-28 12:54:15 -04:00
f58c16ab03 commented 2022-09-28 12:23:33 -04:00
b560d2953f updated nav and removed ts comments 2022-09-28 12:19:44 -04:00
2c52c8efb7 better nav 2022-09-28 11:58:47 -04:00
5375166f04 moved the settings 2022-09-28 11:22:17 -04:00
5e85cae9ce Merge branch 'react-base' into react-base-nav 2022-09-28 09:14:28 -04:00
0ae449fd44 Merge pull request #257 from caranicas/react-base-inpainting
React base inpainting
2022-09-28 18:39:50 +05:30
4f5b4f387a Merge pull request #258 from cmdr2/main
Merge main
2022-09-28 18:39:37 +05:30
a8d3d613b0 Merge branch 'react-base' into react-base-inpainting 2022-09-28 09:01:21 -04:00
c680fbe834 clean 2022-09-28 08:52:12 -04:00
286c77778f Merge pull request #247 from caranicas/react-base-streaming-test
React base streaming test
2022-09-28 11:10:48 +05:30
10c4bee1e5 Fix for show all images 2022-09-28 00:05:34 +03:00
f26b8ee224 build 2022-09-27 14:51:51 -04:00
1961567ebd got the inpainting mask sent to the server 2022-09-27 14:50:05 -04:00
094687717d external changes 2022-09-27 13:45:29 -04:00
e5844c926b tags working 2022-09-27 13:37:28 -04:00
96ad8c823a wokring checkmark, cleaner time adn translation 2022-09-27 11:02:58 -04:00
de2977284c fixed time remaining and progress display 2022-09-27 10:45:36 -04:00
c1dea44fa6 Fix for live preview 2022-09-27 17:23:19 +03:00
5a105eb2b3 fix timestamp 2022-09-27 09:46:32 -04:00
7a076f7304 clean ups 2022-09-27 09:28:04 -04:00
986b303f2f reselct and delete working 2022-09-26 17:36:21 -04:00
afd8717c21 poc streaming image response 2022-09-26 17:06:42 -04:00
6effd783c0 wip 2022-09-26 16:53:13 -04:00
b8f47545ed fix ordering 2022-09-26 16:50:34 -04:00
a6394b2dce history displaying 2022-09-26 11:15:13 -04:00
5ba802dc68 Overlaid info 2022-09-26 17:50:27 +03:00
76c72c1a7f get a bit closer, and add some notes 2022-09-25 19:21:09 -04:00
1c1cf58409 fix shift 2022-09-25 11:00:53 -04:00
8155e3ef7a actual displaying 2022-09-25 10:57:37 -04:00
62048c68f0 Image item refactor and redesign 2022-09-25 02:55:11 +03:00
f32df2ac9c Merge branch 'react-base' into react-base-streaming-test 2022-09-24 13:50:20 -04:00
22a0b3be45 workable plan 2022-09-24 13:47:30 -04:00
3490d0d743 Merge pull request #239 from cmdr2/main
Merge main
2022-09-24 22:51:06 +05:30
fbe829def7 Merge from main 2022-09-24 18:55:53 +05:30
161eea3e9e Merge pull request #232 from caranicas/react-base-sampler
sampler fix
2022-09-24 11:19:12 +05:30
d1e792686e added some options to test 2022-09-23 13:31:56 -04:00
62fe380520 add default values to false 2022-09-23 13:20:15 -04:00
319f08c4c9 sampler fix 2022-09-23 12:49:37 -04:00
0d13fe67b0 Merge pull request #227 from cmdr2/beta
Merge beta
2022-09-23 17:59:31 +05:30
a0c6e9e490 Merge branch 'beta' into react 2022-09-22 23:04:48 +05:30
56960d6da9 Merge branch 'beta' into react 2022-09-22 22:56:45 +05:30
2590dc690e Merge pull request #191 from caranicas/beta-react
Beta react
2022-09-21 23:18:00 +05:30
e2545b3d34 Merge branch 'react' into beta-react 2022-09-21 23:17:33 +05:30
bf4d920fb4 Merge pull request #33 from caranicas/beta-react-linting-pt2
Beta react linting pt2
2022-09-20 14:22:17 -04:00
d84fb244d3 fix all the linting errors i can 2022-09-20 14:21:21 -04:00
f04b5244fa cleaning up type issues 2022-09-20 12:35:44 -04:00
6f3829fa91 remove debug 2022-09-20 09:55:33 -04:00
a5ae3545d5 Merge pull request #32 from caranicas/react-beta-linting-clean
React beta linting clean
2022-09-20 09:52:02 -04:00
63b658ac50 linting and some type fixes 2022-09-20 09:50:50 -04:00
e8544be30a hide inert ui for now 2022-09-20 09:49:50 -04:00
39090451f0 fix the linting issue and index error 2022-09-20 09:36:12 -04:00
12fc6e6354 Merge pull request #31 from mrbusysky/beta-react
Updates for translations
2022-09-20 09:09:12 -04:00
154326061d Translation update part 2 2022-09-19 18:39:44 -07:00
0bbfd574b3 pretty fixes 2022-09-19 17:52:01 -07:00
eff3887f35 updates for static words part 1 2022-09-19 17:49:03 -07:00
34cb532e6b adjust footer to center 2022-09-19 19:02:01 -04:00
cf1d1a97f3 Merge pull request #30 from caranicas/beta-react-translation
language switcher
2022-09-19 15:57:18 -04:00
e0a4f0bc4c language switcher 2022-09-19 15:52:51 -04:00
1ac8eba1b8 clean and pretty 2022-09-19 15:40:34 -04:00
82f8c31b81 fix some linting issues 2022-09-19 15:37:21 -04:00
9f2ae75fa2 Merge pull request #29 from caranicas/beta-react-loading-and-cache
Beta react loading and cache
2022-09-19 15:08:37 -04:00
9d220c482d loading and cache are better 2022-09-19 15:07:47 -04:00
c4718bd302 add basic loading 2022-09-19 14:05:01 -04:00
e1e2a90498 fix build 2022-09-19 13:40:17 -04:00
40a48954c3 Merge pull request #28 from caranicas/beta-react-style-clean-pt2
Beta react style clean pt2
2022-09-19 13:34:39 -04:00
e81068f528 footer looking better 2022-09-19 13:32:20 -04:00
0591487cfd creation ui is better 2022-09-19 13:19:19 -04:00
737ed7ba5d clean up font ambiguity 2022-09-19 12:47:55 -04:00
27fd1f39f0 css clean 2022-09-19 12:04:14 -04:00
1210313e7f Merge pull request #27 from caranicas/beta-react-i18n-lint
Beta react i18n lint
2022-09-19 11:37:56 -04:00
4733c8fb75 add linting rules to help out with i18n 2022-09-19 11:36:56 -04:00
8777e65996 work on identical keys 2022-09-19 10:57:31 -04:00
330fa10935 i18n linting 2022-09-19 10:30:33 -04:00
1bd4a0f4ee basic linting 2022-09-19 10:14:50 -04:00
bea8ae55de remove space 2022-09-19 10:05:52 -04:00
b99cd49091 lf line endings 2022-09-19 10:03:08 -04:00
35f3b70968 Merge pull request #26 from mrbusysky/beta-react
Translation added
2022-09-19 09:07:27 -04:00
e33f3231d0 matching pre merge issue translation 2022-09-18 18:57:17 -07:00
b6cf6ee94a Translation Update
Still need to replace all the static words in pages.
2022-09-18 18:40:34 -07:00
6118518b1b Updating to match
there was to many merge conflicts
2022-09-18 18:33:03 -07:00
f77d5ebfd2 fix cache time 2022-09-18 20:53:18 -04:00
fcf5c41709 fix undefined bug 2022-09-18 20:40:17 -04:00
7f3279f20f Merge pull request #25 from caranicas/beta-react-filter-fix
fix filter and some styling
2022-09-18 19:25:42 -04:00
c23de50f3e fix filter and some styling 2022-09-18 19:24:35 -04:00
51f1759323 Merge pull request #24 from caranicas/beta-react-display-loading
Beta react display loading
2022-09-18 15:44:31 -04:00
cedc634933 display clean 2022-09-18 15:21:39 -04:00
c7b89a1126 current and cache history 2022-09-18 15:19:31 -04:00
bad015de9a Merge pull request #23 from caranicas/beta-react-prompt-and-beta
Beta react prompt gate, beta checkmark, styling iteration
2022-09-18 11:18:51 -04:00
21057759de remove logs 2022-09-18 11:16:09 -04:00
d027352d79 disabled beta check for now 2022-09-18 11:14:17 -04:00
fd8c568d75 working beta 2022-09-18 11:12:41 -04:00
85292ca1b4 adding recipe 2022-09-17 20:26:24 -04:00
1ab90e76d1 solidifed the styles 2022-09-17 17:23:14 -04:00
1e9e9daeb3 wip 2022-09-17 16:30:47 -04:00
65682a8130 Merge pull request #21 from caranicas/beta-react-theme
theme scaffold
2022-09-17 14:18:51 -04:00
bca225e692 theme scaffold 2022-09-17 14:18:05 -04:00
4fbc46b3b3 Merge pull request #20 from caranicas/beta-react-draw
Beta react draw
2022-09-17 12:47:00 -04:00
4b3806fb9a clean 2022-09-17 12:38:19 -04:00
5abbec94c4 working 2022-09-17 12:23:50 -04:00
346d1dddba decent drawing tools 2022-09-17 11:58:21 -04:00
8b48ad77e8 organize the inpainting display 2022-09-16 21:07:42 -04:00
64d97a3232 build and pretty 2022-09-16 18:35:48 -04:00
94a208bd91 drawing basics 2022-09-16 18:32:48 -04:00
b15ac8b13e wip 2022-09-16 16:58:05 -04:00
0ddff9d551 organized draw image 2022-09-16 16:41:30 -04:00
7c31dbb3d6 Merge pull request #19 from caranicas/beta-react-app-config
new config route and tighter header
2022-09-16 15:25:58 -04:00
6ee995afaa new config route and tighter header 2022-09-16 14:34:10 -04:00
691acb647e Merge pull request #18 from caranicas/beta-react-display
Beta react display
2022-09-16 13:31:11 -04:00
80d9d88de1 persistent state and reduced unneeded boolean logic 2022-09-16 13:29:32 -04:00
cf12abfc7f better store and disabling 2022-09-16 12:56:57 -04:00
b21ec7a302 patching cors issue with modifcations 2022-09-16 11:32:36 -04:00
972473f1af drawing in progress 2022-09-15 20:25:48 -04:00
ee8e0b46a2 letter box image 2022-09-15 19:48:12 -04:00
1c3d270402 Merge pull request #15 from caranicas/beta-react-router
basic routing
2022-09-15 16:39:38 -04:00
9d09d2042a properly installed and clean 2022-09-15 16:36:08 -04:00
b8823ade29 basic routing 2022-09-15 16:25:02 -04:00
0e5b01f897 Merge pull request #13 from caranicas/beta-react-advanced-settings
Beta react advanced settings
2022-09-15 15:38:46 -04:00
87f221290f pretty and build 2022-09-15 15:37:36 -04:00
fd3b0c20b6 advanced panels 2022-09-15 15:35:41 -04:00
93e71027fd advanced settings organaized and dropdowns 2022-09-15 15:16:42 -04:00
c6852c70fd new build 2022-09-15 13:45:23 -04:00
953773aaa8 pretty 2022-09-15 13:44:08 -04:00
e0a139d083 Merge pull request #12 from caranicas/beta-react-ui
Beta react UI
2022-09-15 13:37:22 -04:00
867140df30 creation ui soldified 2022-09-15 13:34:54 -04:00
8a354e6187 using vanilla extract for main and app 2022-09-15 10:19:09 -04:00
6afd4b0dc7 Merge pull request #11 from caranicas/beta-react-style-cleanup
working display panel
2022-09-14 19:03:48 -04:00
e2517ef50e remove unneeded 2022-09-14 19:03:26 -04:00
ad6798eaad fixed most of the big css issues 2022-09-14 19:00:51 -04:00
2a5fcc0846 working display panel 2022-09-14 18:38:31 -04:00
37592a876e fix the image preview display 2022-09-14 17:56:38 -04:00
4979e176c7 updated dist 2022-09-14 17:25:50 -04:00
f3fdac2762 tidy and pretty 2022-09-14 17:24:18 -04:00
9a67617cef Merge pull request #10 from caranicas/beta-react-audio
Beta react audio
2022-09-14 17:20:14 -04:00
96e43cbb65 audio component and gated 2022-09-14 17:19:40 -04:00
458dc5b232 Merge branch 'beta-react' into beta-react-audio 2022-09-14 16:59:36 -04:00
28a7c6d3aa wip 2022-09-14 16:59:14 -04:00
d3c241d283 Merge pull request #9 from caranicas/beta-react-creation-options
Beta react creation options
2022-09-14 16:50:17 -04:00
445959abbd fix issue with upsclaing checkbox 2022-09-14 16:49:27 -04:00
62842968cb upscaling and face fixing passing thru 2022-09-14 16:45:12 -04:00
2dda683aa6 face correctiona and scaling passing thru properly 2022-09-14 16:33:56 -04:00
616167e08c Merge pull request #8 from caranicas/beta-react-asset-fix
moved assets
2022-09-14 15:42:29 -04:00
acd74c60c8 moved assets 2022-09-14 15:35:39 -04:00
c1c4a2933e make pretty 2022-09-14 14:49:23 -04:00
8158ead1a2 fix testing values 2022-09-14 14:32:01 -04:00
fcc196f452 Merge pull request #7 from caranicas/beta-react-file-responses
file metadata and saveing
2022-09-14 14:28:10 -04:00
d55e2492d4 file metadata and saveing 2022-09-14 14:23:55 -04:00
45e05b0891 Merge pull request #6 from caranicas/beta-react-parallel-logic
updated parallel logic
2022-09-14 13:25:53 -04:00
eb53739c95 fix modifiers path 2022-09-14 13:20:19 -04:00
4a35059711 comments 2022-09-14 13:07:27 -04:00
a1ad1147e6 adjust server 2022-09-14 12:57:03 -04:00
eefa7d53c5 updated parallel logic 2022-09-14 12:53:28 -04:00
716491a68e clean build, and moved assets 2022-09-14 11:16:36 -04:00
29e5263fcc add a comment 2022-09-14 11:05:50 -04:00
4df61d7efc hide original dom 2022-09-14 10:52:19 -04:00
34aa60d47b inital push 2022-09-14 10:48:46 -04:00
85 changed files with 8351 additions and 2984 deletions

27
3rd-PARTY-LICENSES Normal file
View File

@ -0,0 +1,27 @@
jquery-confirm
==============
https://craftpip.github.io/jquery-confirm/
jquery-confirm is licensed under the MIT license:
The MIT License (MIT)
Copyright (c) 2019 Boniface Pereira
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

48
CHANGES.md Normal file
View File

@ -0,0 +1,48 @@
# What's new?
## v2.4
### Major Changes
- **Automatic scanning for malicious model files** - using `picklescan`. Thanks @JeLuf
- **Support for custom VAE models**. You can place your VAE files in the `models/vae` folder, and refresh the browser page to use them. More info: https://github.com/cmdr2/stable-diffusion-ui/wiki/VAE-Variational-Auto-Encoder
- **Experimental support for multiple GPUs!** It should work automatically. Just open one browser tab per GPU, and spread your tasks across your GPUs. For e.g. open our UI in two browser tabs if you have two GPUs. You can customize which GPUs it should use in the "Settings" tab, otherwise let it automatically pick the best GPUs. Thanks @madrang . More info: https://github.com/cmdr2/stable-diffusion-ui/wiki/Run-on-Multiple-GPUs
- **Cleaner UI design** - Show settings and help in new tabs, instead of dropdown popups (which were buggy). Thanks @mdiller
- **Progress bar.** Thanks @mdiller
- **Custom Image Modifiers** - You can now save your custom image modifiers! Your saved modifiers can include special characters like `{}, (), [], |`
- Drag and Drop **text files generated from previously saved images**, and copy settings to clipboard. Thanks @madrang
- Paste settings from clipboard. Thanks @JeLuf
- Bug fixes to reduce the chances of tasks crashing during long multi-hour runs (chrome can put long-running background tabs to sleep). Thanks @JeLuf and @madrang
- **Improved documentation.** Thanks @JeLuf and @jsuelwald
- Improved the codebase for dealing with system settings and UI settings. Thanks @mdiller
- Help instructions next to some setttings, and in the tab
- Show system info in the settings tab
- Keyboard shortcut: Ctrl+Enter to start a task
- Configuration to prevent the browser from opening on startup
- Lots of minor bug fixes
- A `What's New?` tab in the UI
- Ask for a confimation before clearing the results pane or stopping a render task. The dialog can be skipped by holding down the shift key while clicking on the button.
- Show the network addresses of the server in the systems setting dialog
### Detailed changelog
* 2.4.17 - 30 Nov 2022 - Scroll to generated image. Thanks @patriceac
* 2.4.17 - 30 Nov 2022 - Show the network addresses of the server in the systems setting dialog. Thanks @JeLuf
* 2.4.17 - 30 Nov 2022 - Fix a bug where GFPGAN wouldn't work properly when multiple GPUs tried to run it at the same time. Thanks @madrang
* 2.4.17 - 30 Nov 2022 - Confirm before stopping or clearing all the tasks. Thanks @JeLuf
* 2.4.16 - 29 Nov 2022 - Bug fixes for SD 2.0 - remove the need for patching, default to SD 1.4 model if trying to load an SD2 model in SD1.4.
* 2.4.15 - 25 Nov 2022 - Experimental support for SD 2.0. Uses lots of memory, not optimized, probably GPU-only.
* 2.4.14 - 22 Nov 2022 - Change the backend to a custom fork of Stable Diffusion
* 2.4.13 - 21 Nov 2022 - Change the modifier weight via mouse wheel, drag to reorder selected modifiers, and some more modifier-related fixes. Thanks @patriceac
* 2.4.12 - 21 Nov 2022 - Another fix for improving how long images take to generate. Reduces the time taken for an enqueued task to start processing.
* 2.4.11 - 21 Nov 2022 - Installer improvements: avoid crashing if the username contains a space or special characters, allow moving/renaming the folder after installation on Windows, whitespace fix on git apply
* 2.4.11 - 21 Nov 2022 - Validate inputs before submitting the Image request
* 2.4.11 - 19 Nov 2022 - New system settings to manage the network config (port number and whether to only listen on localhost)
* 2.4.11 - 19 Nov 2022 - Address a regression in how long images take to generate. Use the previous code for moving a model to CPU. This improves things by a second or two per image, but we still have a regression (investigating).
* 2.4.10 - 18 Nov 2022 - Textarea for negative prompts. Thanks @JeLuf
* 2.4.10 - 18 Nov 2022 - Improved design for Settings, and rounded toggle buttons instead of checkboxes for a more modern look. Thanks @mdiller
* 2.4.9 - 18 Nov 2022 - Add Picklescan - a scanner for malicious model files. If it finds a malicious file, it will halt the web application and alert the user. Thanks @JeLuf
* 2.4.8 - 18 Nov 2022 - A `Use these settings` button to use the settings from a previously generated image task. Thanks @patriceac
* 2.4.7 - 18 Nov 2022 - Don't crash if a VAE file fails to load
* 2.4.7 - 17 Nov 2022 - Fix a bug where Face Correction (GFPGAN) would fail on cuda:N (i.e. GPUs other than cuda:0), as well as fail on CPU if the system had an incompatible GPU.
* 2.4.6 - 16 Nov 2022 - Fix a regression in VRAM usage during startup, which caused 'Out of Memory' errors when starting on GPUs with 4gb (or less) VRAM
* 2.4.5 - 16 Nov 2022 - Add checkbox for "Open browser on startup".
* 2.4.5 - 16 Nov 2022 - Add a directory for core plugins that ship with Stable Diffusion UI by default.
* 2.4.5 - 16 Nov 2022 - Add a "What's New?" tab as a core plugin, which fetches the contents of CHANGES.md from the app's release branch.

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,23 +32,20 @@ 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.
11) Please update CHANGES.md in your pull requests.
Check the `ui/frontend/build/README.md` for instructions on running and building the React code.
## Development environment for Installer changes
Build the Windows installer using Windows, and the Linux installer using Linux. Don't mix the two, and don't use WSL. An Ubuntu VM is fine for building the Linux installer on a Windows host.
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.

1
NSIS/README.md Normal file
View File

@ -0,0 +1 @@
Scripts to be used with the Nullsoft Scriptable Installation System

BIN
NSIS/astro.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 KiB

BIN
NSIS/sd.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 KiB

265
NSIS/sdui.nsi Normal file
View File

@ -0,0 +1,265 @@
; Script generated by the HM NIS Edit Script Wizard.
Target x86-unicode
Unicode True
!AddPluginDir /x86-unicode "."
; HM NIS Edit Wizard helper defines
!define PRODUCT_NAME "Stable Diffusion UI"
!define PRODUCT_VERSION "Installer 2.35"
!define PRODUCT_PUBLISHER "cmdr2 and contributors"
!define PRODUCT_WEB_SITE "https://stable-diffusion-ui.github.io"
!define PRODUCT_DIR_REGKEY "Software\Microsoft\Cmdr2\App Paths\installer.exe"
; MUI 1.67 compatible ------
!include "MUI.nsh"
!include "LogicLib.nsh"
!include "nsDialogs.nsh"
Var Dialog
Var Label
Var Button
Var InstDirLen
Var LongPathsEnabled
Var AccountType
;---------------------------------------------------------------------------------------------------------
; This function returns the number of spaces in a string.
; The string is passed on the stack (using Push $STRING)
; The result is also returned on the stack and can be consumed with Pop $var
; https://nsis.sourceforge.io/Check_for_spaces_in_a_directory_path
Function CheckForSpaces
Exch $R0
Push $R1
Push $R2
Push $R3
StrCpy $R1 -1
StrCpy $R3 $R0
StrCpy $R0 0
loop:
StrCpy $R2 $R3 1 $R1
IntOp $R1 $R1 - 1
StrCmp $R2 "" done
StrCmp $R2 " " 0 loop
IntOp $R0 $R0 + 1
Goto loop
done:
Pop $R3
Pop $R2
Pop $R1
Exch $R0
FunctionEnd
;---------------------------------------------------------------------------------------------------------
; The function DirectoryLeave is called after the user chose the installation directory.
; If it calls "abort", the user is sent back to choose a different directory.
Function DirectoryLeave
; check whether the installation directory path is longer than 30 characters.
; If yes, we suggest to the user to enable long filename support
;----------------------------------------------------------------------------
StrLen $InstDirLen "$INSTDIR"
; Check whether the registry key that allows for >260 characters in a path name is set
ReadRegStr $LongPathsEnabled HKLM "SYSTEM\CurrentControlSet\Control\FileSystem" "LongPathsEnabled"
${If} $InstDirLen > 30
${AndIf} $LongPathsEnabled == "0"
; Check whether we're in the Admin group
UserInfo::GetAccountType
Pop $AccountType
${If} $AccountType == "Admin"
${AndIf} ${Cmd} `MessageBox MB_YESNO|MB_ICONQUESTION 'The path name is too long. $\n$\nYou can either enable long file name support in Windows,$\nor you can go back and choose a different path.$\n$\nFor details see: shorturl.at/auBD1$\n$\nEnable long path name support in Windows?' IDYES`
; Enable long path names
WriteRegDWORD HKLM "SYSTEM\CurrentControlSet\Control\FileSystem" "LongPathsEnabled" 1
${Else}
MessageBox MB_OK|MB_ICONEXCLAMATION "Installation path name too long. The installation path must not have more than 30 characters."
abort
${EndIf}
${EndIf}
; Check for spaces in the installation directory path.
; ----------------------------------------------------
; $R0 = CheckForSpaces( $INSTDIR )
Push $INSTDIR # Input string (install path).
Call CheckForSpaces
Pop $R0 # The function returns the number of spaces found in the input string.
; Check if any spaces exist in $INSTDIR.
${If} $R0 != 0
; Plural if more than 1 space in $INSTDIR.
; If $R0 == 1: $R1 = ""; else: $R1 = "s"
StrCmp $R0 1 0 +3
StrCpy $R1 ""
Goto +2
StrCpy $R1 "s"
; Show message box then take the user back to the Directory page.
MessageBox MB_OK|MB_ICONEXCLAMATION "Error: The Installaton directory \
has $R0 space character$R1.$\nPlease choose an installation directory without space characters."
Abort
${EndIf}
; Check for NTFS filesystem. Installations on FAT fail.
; -----------------------------------------------------
StrCpy $5 $INSTDIR 3
System::Call 'Kernel32::GetVolumeInformation(t "$5",t,i ${NSIS_MAX_STRLEN},*i,*i,*i,t.r1,i ${NSIS_MAX_STRLEN})i.r0'
${If} $0 <> 0
${AndIf} $1 == "NTFS"
MessageBox mb_ok "$5 has filesystem type '$1'.$\nOnly NTFS filesystems are supported.$\nPlease choose a different drive."
Abort
${EndIf}
FunctionEnd
;---------------------------------------------------------------------------------------------------------
; Open the MS download page in a browser and enable the [Next] button
Function MSMediaFeaturepack
ExecShell "open" "https://www.microsoft.com/en-us/software-download/mediafeaturepack"
GetDlgItem $0 $HWNDPARENT 1
EnableWindow $0 1
FunctionEnd
;---------------------------------------------------------------------------------------------------------
; Install the MS Media Feature Pack, if it is missing (e.g. on Windows 10 N)
Function MediaPackDialog
!insertmacro MUI_HEADER_TEXT "Windows Media Feature Pack" "Required software module is missing"
; Skip this dialog if mf.dll is installed
${If} ${FileExists} "$WINDIR\system32\mf.dll"
Abort
${EndIf}
nsDialogs::Create 1018
Pop $Dialog
${If} $Dialog == error
Abort
${EndIf}
${NSD_CreateLabel} 0 0 100% 48u "The Windows Media Feature Pack is missing on this computer. It is required for the Stable Diffusion UI.$\nYou can continue the installation after installing the Windows Media Feature Pack."
Pop $Label
${NSD_CreateButton} 10% 49u 80% 12u "Download Meda Feature Pack from Microsoft"
Pop $Button
GetFunctionAddress $0 MSMediaFeaturePack
nsDialogs::OnClick $Button $0
GetDlgItem $0 $HWNDPARENT 1
EnableWindow $0 0
nsDialogs::Show
FunctionEnd
;---------------------------------------------------------------------------------------------------------
; MUI Settings
;---------------------------------------------------------------------------------------------------------
!define MUI_ABORTWARNING
!define MUI_ICON "sd.ico"
!define MUI_WELCOMEFINISHPAGE_BITMAP "astro.bmp"
; Welcome page
!define MUI_WELCOMEPAGE_TEXT "This installer will guide you through the installation of Stable Diffusion UI.$\n$\n\
Click Next to continue."
!insertmacro MUI_PAGE_WELCOME
Page custom MediaPackDialog
; License page
!insertmacro MUI_PAGE_LICENSE "..\LICENSE"
!insertmacro MUI_PAGE_LICENSE "..\CreativeML Open RAIL-M License"
; Directory page
!define MUI_PAGE_CUSTOMFUNCTION_LEAVE "DirectoryLeave"
!insertmacro MUI_PAGE_DIRECTORY
; Instfiles page
!insertmacro MUI_PAGE_INSTFILES
; Finish page
!define MUI_FINISHPAGE_RUN "$INSTDIR\Start Stable Diffusion UI.cmd"
!insertmacro MUI_PAGE_FINISH
; Language files
!insertmacro MUI_LANGUAGE "English"
;---------------------------------------------------------------------------------------------------------
; MUI end
;---------------------------------------------------------------------------------------------------------
Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
OutFile "Install Stable Diffusion UI.exe"
InstallDir "C:\Stable-Diffusion-UI\"
InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" ""
ShowInstDetails show
;---------------------------------------------------------------------------------------------------------
; List of files to be installed
Section "MainSection" SEC01
SetOutPath "$INSTDIR"
File "..\CreativeML Open RAIL-M License"
File "..\How to install and run.txt"
File "..\LICENSE"
File "..\Start Stable Diffusion UI.cmd"
SetOutPath "$INSTDIR\scripts"
File "..\scripts\bootstrap.bat"
File "..\scripts\install_status.txt"
File "..\scripts\on_env_start.bat"
File "C:\windows\system32\curl.exe"
CreateDirectory "$INSTDIR\profile"
CreateDirectory "$SMPROGRAMS\Stable Diffusion UI"
CreateShortCut "$SMPROGRAMS\Stable Diffusion UI\Start Stable Diffusion UI.lnk" "$INSTDIR\Start Stable Diffusion UI.cmd"
SectionEnd
;---------------------------------------------------------------------------------------------------------
; Our installer only needs 25 KB, but once it has run, we need 25 GB
; So we need to overwrite the automatically detected space requirements.
; https://nsis.sourceforge.io/Docs/Chapter4.html#4.9.13.7
; The example in section 4.9.13.7 seems to be wrong: the number
; needs to be provided in Kilobytes.
Function .onInit
; Set required size of section 'SEC01' to 25 Gigabytes
SectionSetSize ${SEC01} 26214400
; Check system meory size. We need at least 8GB
; ----------------------------------------------------
; allocate a few bytes of memory
System::Alloc 64
Pop $1
; Retrieve HW info from the Windows Kernel
System::Call "*$1(i64)"
System::Call "Kernel32::GlobalMemoryStatusEx(i r1)"
; unpack the data into $R2 - $R10
System::Call "*$1(i.r2, i.r3, l.r4, l.r5, l.r6, l.r7, l.r8, l.r9, l.r10)"
# free up the memory
System::Free $1
; Result mapping:
; "Structure size: $2 bytes"
; "Memory load: $3%"
; "Total physical memory: $4 bytes"
; "Free physical memory: $5 bytes"
; "Total page file: $6 bytes"
; "Free page file: $7 bytes"
; "Total virtual: $8 bytes"
; "Free virtual: $9 bytes"
; Mem size in MB
System::Int64Op $4 / 1048576
Pop $4
${If} $4 < "8000"
MessageBox MB_OK|MB_ICONEXCLAMATION "Warning!$\n$\nYour system has less than 8GB of memory (RAM).$\n$\n\
You can still try to install Stable Diffusion UI,$\nbut it might have problems to start, or run$\nvery slowly."
${EndIf}
FunctionEnd
;Section -Post
; WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\installer.exe"
;SectionEnd

118
README.md
View File

@ -1,49 +1,81 @@
# 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)
New! Experimental support for Stable Diffusion 2.0 is available in beta!
----
## 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*"
- **Stable Diffusion 2.0 support (experimental)** - available in beta channel
- **Custom Models**: Use your own `.ckpt` file, by placing it inside the `models/stable-diffusion` folder!
- **Auto scan for malicious models** - uses picklescan to prevent malicious models
- **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.4.13/stable-diffusion-ui-windows.zip) or [for Linux](https://github.com/cmdr2/stable-diffusion-ui/releases/download/v2.4.13/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 +89,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

@ -0,0 +1,46 @@
@echo off
echo "Opening Stable Diffusion UI - Developer Console.." & echo.
set PATH=C:\Windows\System32;%PATH%
@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%
set PYTHONPATH=%cd%\installer;%cd%\installer_files\env
@rem activate the installer env
call conda activate
@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
@rem set the PYTHONPATH
cd stable-diffusion
set SD_DIR=%cd%
cd env\lib\site-packages
set PYTHONPATH=%SD_DIR%;%cd%
cd ..\..\..
echo PYTHONPATH=%PYTHONPATH%
cd ..
@rem done
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"
if "%ERRORLEVEL%" NEQ "0" (
echo "There was a problem downloading micromamba. Cannot continue."
pause
exit /b
)
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

51
scripts/developer_console.sh Executable file
View File

@ -0,0 +1,51 @@
#!/bin/bash
cd "$(dirname "${BASH_SOURCE[0]}")"
if [ "$0" == "bash" ]; then
echo "Opening Stable Diffusion UI - Developer Console.."
echo ""
# 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
# activate the installer env
CONDA_BASEPATH=$(conda info --base)
source "$CONDA_BASEPATH/etc/profile.d/conda.sh" # avoids the 'shell not initialized' error
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
# set the PYTHONPATH
cd stable-diffusion
SD_PATH=`pwd`
export PYTHONPATH="$SD_PATH:$SD_PATH/env/lib/python3.8/site-packages"
echo "PYTHONPATH=$PYTHONPATH"
cd ..
# done
echo ""
else
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,16 +44,18 @@ 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
)
)
@xcopy sd-ui-files\ui ui /s /i /Y
@xcopy sd-ui-files\ui ui /s /i /Y /q
@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,16 +29,16 @@ 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 .
./scripts/on_sd_start.sh

View File

@ -1,49 +1,73 @@
@echo off
@copy sd-ui-files\scripts\on_env_start.bat scripts\ /Y
@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\on_env_start.bat scripts\ /Y
@copy sd-ui-files\scripts\bootstrap.bat scripts\ /Y
if exist "%cd%\profile" (
set USERPROFILE=%cd%\profile
)
@mkdir tmp
@set TMP=%cd%\tmp
@set TEMP=%cd%\tmp
@rem activate the installer env
call conda activate
@if "%ERRORLEVEL%" NEQ "0" (
@echo. & echo "Error activating conda 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
)
@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
if NOT DEFINED test_sd2 set test_sd2=N
@>nul findstr /m "sd_git_cloned" scripts\install_status.txt
@if "%ERRORLEVEL%" EQU "0" (
@echo "Stable Diffusion's git repository was already installed. Updating.."
@cd stable-diffusion
@call git remote set-url origin https://github.com/easydiffusion/diffusion-kit.git
@call git reset --hard
@call git pull
@call git checkout f6cfebffa752ee11a7b07497b8529d5971de916c
@call git apply ..\ui\sd_internal\ddim_callback.patch
@call git apply ..\ui\sd_internal\env_yaml.patch
if "%test_sd2%" == "N" (
@call git -c advice.detachedHead=false checkout 7f32368ed1030a6e710537047bacd908adea183a
)
if "%test_sd2%" == "Y" (
@call git -c advice.detachedHead=false checkout 5d647c5459f4cd790672512222bc41903c01bb71
)
@cd ..
) else (
@echo. & echo "Downloading Stable Diffusion.." & echo.
@call git clone https://github.com/basujindal/stable-diffusion.git && (
@call git clone https://github.com/easydiffusion/diffusion-kit.git stable-diffusion && (
@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 apply ..\ui\sd_internal\ddim_callback.patch
@call git apply ..\ui\sd_internal\env_yaml.patch
@call git -c advice.detachedHead=false checkout 7f32368ed1030a6e710537047bacd908adea183a
@cd ..
)
@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"
@ -56,22 +80,20 @@
@REM prevent conda from using packages from the user's home directory, to avoid conflicts
@set PYTHONNOUSERSITE=1
set USERPROFILE=%cd%\profile
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
)
@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.
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
)
@ -81,7 +103,7 @@
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 (
@ -89,20 +111,12 @@ set PATH=C:\Windows\System32;%PATH%
@set PYTHONNOUSERSITE=1
@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.
pause
exit /b
)
set USERPROFILE=%cd%\profile
@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.
pause
exit /b
)
set PYTHONPATH=%cd%;%cd%\env\lib\site-packages
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
)
@ -110,7 +124,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 (
@ -118,14 +132,12 @@ set PATH=C:\Windows\System32;%PATH%
@set PYTHONNOUSERSITE=1
@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.
pause
exit /b
)
set USERPROFILE=%cd%\profile
set PYTHONPATH=%cd%;%cd%\env\lib\site-packages
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
)
@ -133,7 +145,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 (
@ -141,28 +153,47 @@ set PATH=C:\Windows\System32;%PATH%
@set PYTHONNOUSERSITE=1
set USERPROFILE=%cd%\profile
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 2>nul call python -m picklescan --help
@if "%ERRORLEVEL%" NEQ "0" (
@echo. & echo Picklescan not found. Installing
@call pip install picklescan || (
echo "Error installing the picklescan package 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
)
)
@>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
)
if not exist "..\models\stable-diffusion" mkdir "..\models\stable-diffusion"
if not exist "..\models\vae" mkdir "..\models\vae"
echo. > "..\models\stable-diffusion\Put your custom ckpt files here.txt"
echo. > "..\models\vae\Put your VAE files here.txt"
@if exist "sd-v1-4.ckpt" (
for %%I in ("sd-v1-4.ckpt") do if "%%~zI" EQU "4265380512" (
echo "Data files (weights) necessary for Stable Diffusion were already downloaded. Using the HuggingFace 4 GB Model."
@ -188,12 +219,12 @@ call WHERE uvicorn > .tmp
@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
)
@ -218,12 +249,12 @@ call WHERE uvicorn > .tmp
@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
)
@ -235,7 +266,7 @@ call WHERE uvicorn > .tmp
for %%I in ("RealESRGAN_x4plus.pth") do if "%%~zI" EQU "67040989" (
echo "Data files (weights) necessary for ESRGAN (Resolution Upscaling) x4plus were already downloaded"
) else (
echo. & echo "The GFPGAN model file present at %cd%\RealESRGAN_x4plus.pth is invalid. It is only %%~zI bytes in size. Re-downloading.." & echo.
echo. & echo "The RealESRGAN model file present at %cd%\RealESRGAN_x4plus.pth is invalid. It is only %%~zI bytes in size. Re-downloading.." & echo.
del "RealESRGAN_x4plus.pth"
)
)
@ -248,12 +279,12 @@ call WHERE uvicorn > .tmp
@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
)
@ -265,7 +296,7 @@ call WHERE uvicorn > .tmp
for %%I in ("RealESRGAN_x4plus_anime_6B.pth") do if "%%~zI" EQU "17938799" (
echo "Data files (weights) necessary for ESRGAN (Resolution Upscaling) x4plus_anime were already downloaded"
) else (
echo. & echo "The GFPGAN model file present at %cd%\RealESRGAN_x4plus_anime_6B.pth is invalid. It is only %%~zI bytes in size. Re-downloading.." & echo.
echo. & echo "The RealESRGAN model file present at %cd%\RealESRGAN_x4plus_anime_6B.pth is invalid. It is only %%~zI bytes in size. Re-downloading.." & echo.
del "RealESRGAN_x4plus_anime_6B.pth"
)
)
@ -278,12 +309,12 @@ call WHERE uvicorn > .tmp
@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
)
@ -291,7 +322,39 @@ call WHERE uvicorn > .tmp
@>nul grep -c "sd_install_complete" ..\scripts\install_status.txt
@if exist "..\models\vae\vae-ft-mse-840000-ema-pruned.ckpt" (
for %%I in ("..\models\vae\vae-ft-mse-840000-ema-pruned.ckpt") do if "%%~zI" EQU "334695179" (
echo "Data files (weights) necessary for the default VAE (sd-vae-ft-mse-original) were already downloaded"
) else (
echo. & echo "The default VAE (sd-vae-ft-mse-original) file present at models\vae\vae-ft-mse-840000-ema-pruned.ckpt is invalid. It is only %%~zI bytes in size. Re-downloading.." & echo.
del "..\models\vae\vae-ft-mse-840000-ema-pruned.ckpt"
)
)
@if not exist "..\models\vae\vae-ft-mse-840000-ema-pruned.ckpt" (
@echo. & echo "Downloading data files (weights) for the default VAE (sd-vae-ft-mse-original).." & echo.
@call curl -L -k https://huggingface.co/stabilityai/sd-vae-ft-mse-original/resolve/main/vae-ft-mse-840000-ema-pruned.ckpt > ..\models\vae\vae-ft-mse-840000-ema-pruned.ckpt
@if exist "..\models\vae\vae-ft-mse-840000-ema-pruned.ckpt" (
for %%I in ("..\models\vae\vae-ft-mse-840000-ema-pruned.ckpt") do if "%%~zI" NEQ "334695179" (
echo. & echo "Error: The downloaded default VAE (sd-vae-ft-mse-original) file was invalid! Bytes downloaded: %%~zI" & echo.
echo. & echo "Error downloading the data files (weights) for the default VAE (sd-vae-ft-mse-original). 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 the default VAE (sd-vae-ft-mse-original). 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
)
)
if "%test_sd2%" == "Y" (
@call pip install open_clip_torch==2.0.2
)
@>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
@ -306,12 +369,24 @@ call WHERE uvicorn > .tmp
@cd ..\..\..
@echo PYTHONPATH=%PYTHONPATH%
call where python
call python --version
@cd ..
@set SD_UI_PATH=%cd%\ui
@cd stable-diffusion
@call python --version
@rem
@rem Rewrite easy-install.pth. This fixes the installation if the user has relocated the SDUI installation
@rem
>env\Lib\site-packages\easy-install.pth echo %cd%\src\taming-transformers
>>env\Lib\site-packages\easy-install.pth echo %cd%\src\clip
>>env\Lib\site-packages\easy-install.pth echo %cd%\src\gfpgan
>>env\Lib\site-packages\easy-install.pth echo %cd%\src\realesrgan
@uvicorn server:app --app-dir "%SD_UI_PATH%" --port 9000 --host 0.0.0.0
@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%
@pause
@pause

View File

@ -1,43 +1,58 @@
#!/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
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');"
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');"
# 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.
if [ "$test_sd2" == "" ]; then
export test_sd2="N"
fi
if [ -e "scripts/install_status.txt" ] && [ `grep -c sd_git_cloned scripts/install_status.txt` -gt "0" ]; then
echo "Stable Diffusion's git repository was already installed. Updating.."
cd stable-diffusion
git remote set-url origin https://github.com/easydiffusion/diffusion-kit.git
git reset --hard
git pull
git checkout f6cfebffa752ee11a7b07497b8529d5971de916c
git apply ../ui/sd_internal/ddim_callback.patch
git apply ../ui/sd_internal/env_yaml.patch
if [ "$test_sd2" == "N" ]; then
git -c advice.detachedHead=false checkout 7f32368ed1030a6e710537047bacd908adea183a
elif [ "$test_sd2" == "Y" ]; then
git -c advice.detachedHead=false checkout 5d647c5459f4cd790672512222bc41903c01bb71
fi
cd ..
else
printf "\n\nDownloading Stable Diffusion..\n\n"
if git clone https://github.com/basujindal/stable-diffusion.git ; then
if git clone https://github.com/easydiffusion/diffusion-kit.git stable-diffusion ; 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 apply ../ui/sd_internal/ddim_callback.patch
git apply ../ui/sd_internal/env_yaml.patch
git -c advice.detachedHead=false checkout 7f32368ed1030a6e710537047bacd908adea183a
cd ..
fi
@ -47,37 +62,26 @@ 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
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
fi
conda activate ./env || fail "conda activate failed"
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
@ -89,20 +93,14 @@ else
printf "\n\nDownloading packages necessary for GFPGAN (Face Correction)..\n"
export PYTHONNOUSERSITE=1
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
fi
export PYTHONPATH="$(pwd):$(pwd)/env/lib/site-packages"
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
@ -114,20 +112,11 @@ else
printf "\n\nDownloading packages necessary for ESRGAN (Resolution Upscaling)..\n"
export PYTHONNOUSERSITE=1
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
fi
export PYTHONPATH="$(pwd):$(pwd)/env/lib/site-packages"
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
@ -139,26 +128,35 @@ 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
fi
if python -m picklescan --help >/dev/null 2>&1; then
echo "Picklescan is already installed."
else
echo "Picklescan not found, installing."
pip install picklescan || fail "Picklescan installation failed."
fi
mkdir -p "../models/stable-diffusion"
mkdir -p "../models/vae"
echo "" > "../models/stable-diffusion/Put your custom ckpt files here.txt"
echo "" > "../models/vae/Put your VAE files here.txt"
if [ -f "sd-v1-4.ckpt" ]; then
model_size=`find "sd-v1-4.ckpt" -printf "%s"`
@ -178,15 +176,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
@ -210,15 +203,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
@ -242,15 +230,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
@ -274,18 +257,48 @@ 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"
fail "The downloaded ESRGAN x4plus_anime model file was invalid! Bytes downloaded: $model_size"
fi
else
fail "Error downloading the data files (weights) for ESRGAN (Resolution Upscaling) x4plus_anime."
fi
fi
if [ -f "../models/vae/vae-ft-mse-840000-ema-pruned.ckpt" ]; then
model_size=`find ../models/vae/vae-ft-mse-840000-ema-pruned.ckpt -printf "%s"`
if [ "$model_size" -eq "334695179" ]; then
echo "Data files (weights) necessary for the default VAE (sd-vae-ft-mse-original) were already downloaded"
else
printf "\n\nThe model file present at models/vae/vae-ft-mse-840000-ema-pruned.ckpt is invalid. It is only $model_size bytes in size. Re-downloading.."
rm ../models/vae/vae-ft-mse-840000-ema-pruned.ckpt
fi
fi
if [ ! -f "../models/vae/vae-ft-mse-840000-ema-pruned.ckpt" ]; then
echo "Downloading data files (weights) for the default VAE (sd-vae-ft-mse-original).."
curl -L -k https://huggingface.co/stabilityai/sd-vae-ft-mse-original/resolve/main/vae-ft-mse-840000-ema-pruned.ckpt > ../models/vae/vae-ft-mse-840000-ema-pruned.ckpt
if [ -f "../models/vae/vae-ft-mse-840000-ema-pruned.ckpt" ]; then
model_size=`find ../models/vae/vae-ft-mse-840000-ema-pruned.ckpt -printf "%s"`
if [ ! "$model_size" -eq "334695179" ]; then
printf "\n\nError: The downloaded default VAE (sd-vae-ft-mse-original) file was invalid! Bytes downloaded: $model_size\n\n"
printf "\n\nError downloading the data files (weights) for the default VAE (sd-vae-ft-mse-original). 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/wiki/Troubleshooting\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
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"
printf "\n\nError downloading the data files (weights) for the default VAE (sd-vae-ft-mse-original). 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/wiki/Troubleshooting\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
fi
fi
if [ "$test_sd2" == "Y" ]; then
pip install open_clip_torch==2.0.2
fi
if [ `grep -c sd_install_complete ../scripts/install_status.txt` -gt "0" ]; then
echo sd_weights_downloaded >> ../scripts/install_status.txt
@ -295,15 +308,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

@ -1,107 +1,141 @@
<!DOCTYPE html>
<html>
<head>
<title>Stable Diffusion UI</title>
<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=10">
<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>
<meta name="theme-color" content="#673AB6">
<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">
<link rel="stylesheet" href="/media/css/themes.css">
<link rel="stylesheet" href="/media/css/main.css">
<link rel="stylesheet" href="/media/css/auto-save.css">
<link rel="stylesheet" href="/media/css/modifier-thumbnails.css">
<link rel="stylesheet" href="/media/css/fontawesome-all.min.css">
<link rel="stylesheet" href="/media/css/drawingboard.min.css">
<link rel="stylesheet" href="/media/css/jquery-confirm.min.css">
<link rel="manifest" href="/media/manifest.webmanifest">
<script src="/media/js/jquery-3.6.1.min.js"></script>
<script src="/media/js/jquery-confirm.min.js"></script>
<script src="/media/js/drawingboard.min.js"></script>
<script src="/media/js/marked.min.js"></script>
</head>
<body>
<div id="container">
<div id="top-nav">
<div id="logo">
<h1>Stable Diffusion UI <small>v2.195 <span id="updateBranchLabel"></span></small></h1>
<h1>
Stable Diffusion UI
<small>v2.4.17 <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://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>
</ul>
</li>
<li class="dropdown">
<div id="server-status">
<div id="server-status-color"></div>
<span id="server-status-msg">Stable Diffusion is starting..</span>
</div>
<div id="tab-container">
<span id="tab-main" class="tab active">
<span><i class="fa fa-image icon"></i> Generate</span>
</span>
<span id="tab-settings" class="tab">
<span><i class="fa fa-gear icon"></i> Settings</span>
<div id="system-settings" class="panel-box settings-box dropdown-content">
<ul id="system-settings-entries">
<li><b class="settings-subheader">System Settings</b></li>
<br/>
<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="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>
</ul>
</div>
</li>
</ul>
</span>
<span id="tab-about" class="tab">
<span><i class="fa fa-comments icon"></i> Help & Community</span>
</span>
</div>
</div>
<div class="flex-container">
<div id="editor" class="col-fixed-10">
<div id="server-status">
<div id="server-status-color"></div>
<span id="server-status-msg">Stable Diffusion is starting..</span>
</div>
<div id="tab-content-wrapper">
<div id="tab-content-main" class="tab-content active flex-container">
<div id="editor">
<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
<a href="https://github.com/cmdr2/stable-diffusion-ui/wiki/Writing-prompts#negative-prompts" target="_blank"><i class="fa-solid fa-circle-question help-btn"><span class="simple-tooltip right">Click to learn more about Negative Prompts</span></i></a>
<small>(optional)</small>
</label>
<div class="collapsible-content">
<textarea id="negative_prompt" name="negative_prompt" placeholder="list the things to remove from the image (e.g. fog, green)"></textarea>
</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"><i class="fa-solid fa-xmark"></i></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>
<input id="enable_mask" name="enable_mask" type="checkbox">
<label for="enable_mask">
In-Painting (beta)
<a href="https://github.com/cmdr2/stable-diffusion-ui/wiki/Inpainting" target="_blank"><i class="fa-solid fa-circle-question help-btn"><span class="simple-tooltip right">Click to learn more about InPainting</span></i></a>
<small>(select the area which the AI will paint into)</small>
</label>
<div id="inpaintingEditor"></div>
</div>
</div>
<div id="editor-inputs-tags-container" class="row">
<label>Image Modifiers: <small>(click an Image Modifier to remove it)</small></label>
<label>Image Modifiers <i class="fa-solid fa-circle-question help-btn"><span class="simple-tooltip right">click an Image Modifier to remove it, use Ctrl+Mouse Wheel to adjust its weight</span></i>:</label>
<div id="editor-inputs-tags-list"></div>
</div>
<button id="makeImage">Make Image</button>
<button id="makeImage" class="primaryButton">Make Image</button>
<button id="stopImage" class="secondaryButton">Stop All</button>
</div>
<div class="line-separator">&nbsp;</div>
<span class="line-separator"></span>
<div id="editor-settings" class="panel-box settings-box">
<h4 class="collapsible">Image Settings</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 id="samplerSelection" class="pl-5"><label for="sampler">Sampler:</label>
<div id="editor-settings" class="settings-box panel-box">
<h4 class="collapsible">
Image Settings
<i id="reset-image-settings" class="fa-solid fa-arrow-rotate-left section-button">
<span class="simple-tooltip right">
Reset Image Settings
</span>
</i>
</h4>
<div id="editor-settings-entries" class="collapsible-content">
<div><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>
<a href="https://github.com/cmdr2/stable-diffusion-ui/wiki/Custom-Models" target="_blank"><i class="fa-solid fa-circle-question help-btn"><span class="simple-tooltip right">Click to learn more about custom models</span></i></a>
</td></tr>
<tr class="pl-5"><td><label for="vae_model">Custom VAE:</i></label></td><td>
<select id="vae_model" name="vae_model">
<!-- <option value="" selected>None</option> -->
</select>
<a href="https://github.com/cmdr2/stable-diffusion-ui/wiki/VAE-Variational-Auto-Encoder" target="_blank"><i class="fa-solid fa-circle-question help-btn"><span class="simple-tooltip right">Click to learn more about VAEs</span></i></a>
</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>
<a href="https://github.com/cmdr2/stable-diffusion-ui/wiki/How-to-Use#samplers" target="_blank"><i class="fa-solid fa-circle-question help-btn"><span class="simple-tooltip right">Click to learn more about samplers</span></i></a>
</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>
@ -146,63 +180,160 @@
<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>
<br/>
<li><b class="settings-subheader">Prompt Settings</b></li>
<li class="pl-5"><label for="negative_prompt">Negative Prompt:</label> <input id="negative_prompt" name="negative_prompt" size="55"></li>
<br/>
</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>
</td></tr>
</table></div>
<div><ul>
<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, and 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>
</ul></div>
</div>
</div>
<div id="editor-modifiers" class="panel-box">
<h4 class="collapsible">Image Modifiers (art styles, tags etc)</h4>
<h4 class="collapsible">
Image Modifiers (art styles, tags etc)
<i id="modifier-settings-btn" class="fa-solid fa-gear section-button">
<span class="simple-tooltip left">
Add Custom Modifiers
</span>
</i>
</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>
</div>
</div>
</div>
<div id="tab-content-settings" class="tab-content">
<div id="system-settings" class="tab-content-inner">
<h1>System Settings</h1>
<div class="parameters-table"></div>
<br/>
<button id="save-system-settings-btn" class="primaryButton">Save</button>
<br/><br/>
<div>
<h3><i class="fa fa-microchip icon"></i> System Info</h3>
<div id="system-info">
<table>
<tr><td><label>Processor:</label></td><td id="system-info-cpu" class="value"></td></tr>
<tr><td><label>Compatible Graphics Cards (all):</label></td><td id="system-info-gpus-all" class="value"></td></tr>
<tr><td></td><td>&nbsp;</td></tr>
<tr><td><label>Used for rendering 🔥:</label></td><td id="system-info-rendering-devices" class="value"></td></tr>
<tr><td><label>Server Addresses <i class="fa-solid fa-circle-question help-btn"><span class="simple-tooltip right">You can access Stable Diffusion UI from other devices using these addresses</span></i> :</label></td><td id="system-info-server-hosts" class="value"></td></tr>
</table>
</div>
</div>
</div>
</div>
<div id="tab-content-about" class="tab-content">
<div class="tab-content-inner">
<div class="float-container">
<div class="float-child">
<h1>Help</h1>
<ul id="help-links">
<li><span class="help-section">Using the software</span>
<ul>
<li> <a href="https://github.com/cmdr2/stable-diffusion-ui/wiki/How-To-Use" target="_blank"><i class="fa-solid fa-book fa-fw"></i> How to use</a>
<li> <a href="https://github.com/cmdr2/stable-diffusion-ui/wiki/UI-Overview" target="_blank"><i class="fa-solid fa-list fa-fw"></i> UI Overview</a>
<li> <a href="https://github.com/cmdr2/stable-diffusion-ui/wiki/Writing-Prompts" target="_blank"><i class="fa-solid fa-pen-to-square fa-fw"></i> Writing prompts</a>
<li> <a href="https://github.com/cmdr2/stable-diffusion-ui/wiki/Inpainting" target="_blank"><i class="fa-solid fa-paintbrush fa-fw"></i> Inpainting</a>
<li> <a href="https://github.com/cmdr2/stable-diffusion-ui/wiki/Run-on-Multiple-GPUs" target="_blank"><i class="fa-solid fa-paintbrush fa-fw"></i> Run on Multiple GPUs</a>
</ul>
<li><span class="help-section">Installation</span>
<ul>
<li> <a href="https://github.com/cmdr2/stable-diffusion-ui/wiki/Troubleshooting" target="_blank"><i class="fa-solid fa-circle-question fa-fw"></i> Troubleshooting</a>
</ul>
<li><span class="help-section">Downloadable Content</span>
<ul>
<li> <a href="https://github.com/cmdr2/stable-diffusion-ui/wiki/Custom-Models" target="_blank"><i class="fa-solid fa-images fa-fw"></i> Custom Models</a>
<li> <a href="https://github.com/cmdr2/stable-diffusion-ui/wiki/UI-Plugins" target="_blank"><i class="fa-solid fa-puzzle-piece fa-fw"></i> UI Plugins</a>
<li> <a href="https://github.com/cmdr2/stable-diffusion-ui/wiki/VAE-Variational-Auto-Encoder" target="_blank"><i class="fa-solid fa-hand-sparkles fa-fw"></i> VAE Variational Auto Encoder</a>
</ul>
</ul>
</div>
<div class="float-child">
<h1>Community</h1>
<ul id="community-links">
<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>
</ul>
</div>
</div>
</div>
</div>
</div>
<div id="save-settings-config" class="popup">
<div>
<i class="close-button fa-solid fa-xmark"></i>
<h1>Save Settings Configuration</h1>
<p>Select which settings should be remembered when restarting the browser</p>
<table id="save-settings-config-table" class="form-table">
</table>
</div>
</div>
<div class="line-separator">&nbsp;</div>
<div id="modifier-settings-config" class="popup">
<div>
<i class="close-button fa-solid fa-xmark"></i>
<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 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>
<div id="footer-spacer"></div>
<div id="footer">
<div class="line-separator">&nbsp;</div>
<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>
@ -213,12 +344,24 @@
</div>
</body>
<script src="media/main.js?v=15"></script>
<script src="media/js/utils.js"></script>
<script src="media/js/parameters.js"></script>
<script src="media/js/plugins.js"></script>
<script src="media/js/inpainting-editor.js"></script>
<script src="media/js/image-modifiers.js"></script>
<script src="media/js/auto-save.js"></script>
<script src="media/js/main.js"></script>
<script src="media/js/themes.js"></script>
<script src="media/js/dnd.js"></script>
<script>
async function init() {
await loadModifiers()
await initSettings()
await getModels()
await getDiskPath()
await getAppConfig()
await loadModifiers()
await loadUIPlugins()
await getSystemInfo()
setInterval(healthCheck, HEALTH_PING_INTERVAL * 1000)
healthCheck()

View File

@ -0,0 +1,81 @@
/* Auto-Settings Styling */
#auto_save_settings ~ button {
margin: 5px;
}
#auto_save_settings:not(:checked) ~ button {
display: none;
}
.form-table {
margin: auto;
}
.form-table th {
padding-top: 15px;
padding-bottom: 5px;
}
.form-table td:first-child > *,
.form-table th:first-child > * {
float: right;
white-space: nowrap;
}
.form-table td:last-child > *,
.form-table th:last-child > * {
float: left;
}
.parameters-table {
display: flex;
flex-direction: column;
gap: 1px;
}
.parameters-table > div {
background: var(--background-color2);
display: flex;
padding: 0px 4px;
}
.parameters-table > div > div {
padding: 10px;
display: flex;
align-items: center;
justify-content: center;
}
.parameters-table small {
color: rgb(153, 153, 153);
}
.parameters-table > div > div:nth-child(1) {
font-size: 20px;
width: 45px;
}
.parameters-table > div > div:nth-child(2) {
flex: 1;
flex-direction: column;
text-align: left;
justify-content: center;
align-items: start;
gap: 4px;
}
.parameters-table > div > div:nth-child(3) {
text-align: right;
}
.parameters-table > div:first-child {
border-radius: 12px 12px 0px 0px;
}
.parameters-table > div:last-child {
border-radius: 0px 0px 12px 12px;
}
.parameters-table .fa-fire {
color: #F7630C;
}

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+ */
}

9
ui/media/css/jquery-confirm.min.css vendored Normal file

File diff suppressed because one or more lines are too long

1031
ui/media/css/main.css Normal file

File diff suppressed because it is too large Load Diff

View File

@ -214,3 +214,10 @@
margin-bottom: 0.5em;
vertical-align: middle;
}
#modifier-settings-btn {
float: right;
}
#modifier-settings-config textarea {
width: 90%;
height: 150px;
}

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

@ -0,0 +1,161 @@
:root {
--main-hue: 222;
--main-saturation: 4%;
--value-base: 13%;
--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) - (0.5 * var(--value-step))));
--background-color4: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (1.5 * var(--value-step))));
--accent-hue: 267;
--accent-lightness: 36%;
--accent-lightness-hover: 40%;
--text-color: #eee;
--input-text-color: #eee;
--input-background-color: hsl(var(--main-hue), var(--main-saturation), calc(var(--value-base) - (0.7 * var(--value-step))));
--input-border-color: var(--background-color4);
--button-text-color: var(--input-text-color);
--button-color: var(--accent-color);
--button-border: none;
/* 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));
--primary-button-border: none;
--input-switch-padding: 1px;
--input-height: 18px;
/* Main theme color, hex color fallback. */
--theme-color-fallback: #673AB6;
}
.theme-light {
--background-color1: white;
--background-color2: #ececec;
--background-color3: #e7e9eb;
--background-color4: #cccccc;
--text-color: black;
--button-text-color: white;
--input-text-color: black;
--input-background-color: #f8f9fa;
--input-border-color: grey;
--theme-color-fallback: #aaaaaa;
}
.theme-discord {
--background-color1: #36393f;
--background-color2: #2f3136;
--background-color3: #292b2f;
--background-color4: #202225;
--accent-hue: 235;
--accent-lightness: 65%;
--input-border-size: 2px;
--input-background-color: #202225;
--input-border-color: var(--input-background-color);
--theme-color-fallback: #202225;
}
.theme-cool-blue {
--main-hue: 222;
--main-saturation: 18%;
--value-base: 18%;
--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))));
--input-background-color: var(--background-color3);
--accent-hue: 212;
--theme-color-fallback: #0056b8;
}
.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))));
--input-background-color: var(--background-color3);
--theme-color-fallback: #5300b8;
}
.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) + (1.4 * var(--value-step))));
--input-background-color: var(--background-color3);
--input-border-size: 0px;
--theme-color-fallback: #000000;
}
.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;
--input-border-size: 1px;
--input-background-color: hsl(222, var(--main-saturation), calc(var(--value-base) - (2 * var(--value-step))));
--input-text-color: #FF0000;
--input-border-color: #005E05;
}
.theme-gnomie {
--background-color1: #242424;
--background-color2: #353535;
--background-color3: #494949;
--background-color4: #000000;
--accent-hue: 213;
--accent-lightness: 55%;
--accent-color: #2168bf;
--input-border-radius: 6px;
--input-text-color: #ffffff;
--input-background-color: #2a2a2a;
--input-border-size: 0px;
--input-border-color: var(--input-background-color);
--theme-color-fallback: #2168bf;
}
.theme-gnomie .panel-box {
border: none;
box-shadow: 0px 1px 2px rgba(0, 0, 0, 0.25);
border-radius: 10px;
}

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

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

@ -0,0 +1,304 @@
// 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",
"vae_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_full_precision",
"confirm_dangerous_actions",
"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)
if (!element) {
console.error(`Missing settings element ${id}`)
}
if (id in SETTINGS) { // don't create it again
return
}
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 unsorted_ids = unsorted_settings_ids.map(id => `#${id}`).join(",")
var children = unsorted_ids == "" ? [] : Array.from(element.querySelectorAll(unsorted_ids));
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.forEach(saved_setting => {
var setting = SETTINGS[saved_setting.key]
if (!setting) {
console.warn(`Attempted to load setting ${saved_setting.key}, but no setting found`);
return null;
}
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()
})
})
})
prettifyInputs(saveSettingsConfigTable)
}
// configureSettingsSaveBtn
var autoSaveSettings = document.getElementById("auto_save_settings")
var configSettingsButton = document.createElement("button")
configSettingsButton.textContent = "Configure"
configSettingsButton.style.margin = "0px 5px"
autoSaveSettings.insertAdjacentElement("beforebegin", configSettingsButton)
autoSaveSettings.addEventListener("change", () => {
configSettingsButton.style.display = autoSaveSettings.checked ? "block" : "none"
})
configSettingsButton.addEventListener('click', () => {
fillSaveSettingsConfigTable()
saveSettingsConfigOverlay.classList.add("active")
})
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) {
let key = individual_settings_map[localStorageKey]
var setting = SETTINGS[key]
if (!setting) {
console.warn(`Attempted to map old setting ${key}, but no setting found`);
return null;
}
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);
}
})
}

535
ui/media/js/dnd.js Normal file
View File

@ -0,0 +1,535 @@
"use strict" // Opt in to a restricted variant of JavaScript
const EXT_REGEX = /(?:\.([^.]+))?$/
const TEXT_EXTENSIONS = ['txt', 'json']
const IMAGE_EXTENSIONS = ['jpg', 'jpeg', 'png', 'bmp', 'tiff', 'tif', 'tga']
function parseBoolean(stringValue) {
if (typeof stringValue === 'boolean') {
return stringValue
}
if (typeof stringValue === 'number') {
return stringValue !== 0
}
if (typeof stringValue !== 'string') {
return false
}
switch(stringValue?.toLowerCase()?.trim()) {
case "true":
case "yes":
case "on":
case "1":
return true;
case "false":
case "no":
case "off":
case "0":
case null:
case undefined:
return false;
}
try {
return Boolean(JSON.parse(stringValue));
} catch {
return Boolean(stringValue)
}
}
const TASK_MAPPING = {
prompt: { name: 'Prompt',
setUI: (prompt) => {
promptField.value = prompt
},
readUI: () => promptField.value,
parse: (val) => val
},
negative_prompt: { name: 'Negative Prompt',
setUI: (negative_prompt) => {
negativePromptField.value = negative_prompt
},
readUI: () => negativePromptField.value,
parse: (val) => val
},
active_tags: { name: "Image Modifiers",
setUI: (active_tags) => {
refreshModifiersState(active_tags)
},
readUI: () => activeTags.map(x => x.name),
parse: (val) => val
},
width: { name: 'Width',
setUI: (width) => {
const oldVal = widthField.value
widthField.value = width
if (!widthField.value) {
widthField.value = oldVal
}
},
readUI: () => parseInt(widthField.value),
parse: (val) => parseInt(val)
},
height: { name: 'Height',
setUI: (height) => {
const oldVal = heightField.value
heightField.value = height
if (!heightField.value) {
heightField.value = oldVal
}
},
readUI: () => parseInt(heightField.value),
parse: (val) => parseInt(val)
},
seed: { name: 'Seed',
setUI: (seed) => {
if (!seed) {
randomSeedField.checked = true
seedField.disabled = true
return
}
randomSeedField.checked = false
seedField.disabled = false
seedField.value = seed
},
readUI: () => (randomSeedField.checked ? Math.floor(Math.random() * 10000000) : parseInt(seedField.value)),
parse: (val) => parseInt(val)
},
num_inference_steps: { name: 'Steps',
setUI: (num_inference_steps) => {
numInferenceStepsField.value = num_inference_steps
},
readUI: () => parseInt(numInferenceStepsField.value),
parse: (val) => parseInt(val)
},
guidance_scale: { name: 'Guidance Scale',
setUI: (guidance_scale) => {
guidanceScaleField.value = guidance_scale
updateGuidanceScaleSlider()
},
readUI: () => parseFloat(guidanceScaleField.value),
parse: (val) => parseFloat(val)
},
prompt_strength: { name: 'Prompt Strength',
setUI: (prompt_strength) => {
promptStrengthField.value = prompt_strength
updatePromptStrengthSlider()
},
readUI: () => parseFloat(promptStrengthField.value),
parse: (val) => parseFloat(val)
},
init_image: { name: 'Initial Image',
setUI: (init_image) => {
initImagePreview.src = init_image
},
readUI: () => initImagePreview.src,
parse: (val) => val
},
mask: { name: 'Mask',
setUI: (mask) => {
inpaintingEditor.setImg(mask)
maskSetting.checked = Boolean(mask)
},
readUI: () => (maskSetting.checked ? inpaintingEditor.getImg() : undefined),
parse: (val) => val
},
use_face_correction: { name: 'Use Face Correction',
setUI: (use_face_correction) => {
useFaceCorrectionField.checked = parseBoolean(use_face_correction)
},
readUI: () => useFaceCorrectionField.checked,
parse: (val) => parseBoolean(val)
},
use_upscale: { name: 'Use Upscaling',
setUI: (use_upscale) => {
const oldVal = upscaleModelField.value
upscaleModelField.value = use_upscale
if (upscaleModelField.value) { // Is a valid value for the field.
useUpscalingField.checked = true
upscaleModelField.disabled = false
} else { // Not a valid value, restore the old value and disable the filter.
upscaleModelField.disabled = true
upscaleModelField.value = oldVal
useUpscalingField.checked = false
}
},
readUI: () => (useUpscalingField.checked ? upscaleModelField.value : undefined),
parse: (val) => val
},
sampler: { name: 'Sampler',
setUI: (sampler) => {
samplerField.value = sampler
},
readUI: () => samplerField.value,
parse: (val) => val
},
use_stable_diffusion_model: { name: 'Stable Diffusion model',
setUI: (use_stable_diffusion_model) => {
const oldVal = stableDiffusionModelField.value
use_stable_diffusion_model = getModelPath(use_stable_diffusion_model, ['.ckpt'])
stableDiffusionModelField.value = use_stable_diffusion_model
if (!stableDiffusionModelField.value) {
stableDiffusionModelField.value = oldVal
}
},
readUI: () => stableDiffusionModelField.value,
parse: (val) => val
},
use_vae_model: { name: 'VAE model',
setUI: (use_vae_model) => {
const oldVal = vaeModelField.value
if (use_vae_model !== '') {
use_vae_model = getModelPath(use_vae_model, ['.vae.pt', '.ckpt'])
use_vae_model = use_vae_model !== '' ? use_vae_model : oldVal
}
vaeModelField.value = use_vae_model
},
readUI: () => vaeModelField.value,
parse: (val) => val
},
num_outputs: { name: 'Parallel Images',
setUI: (num_outputs) => {
numOutputsParallelField.value = num_outputs
},
readUI: () => parseInt(numOutputsParallelField.value),
parse: (val) => val
},
use_cpu: { name: 'Use CPU',
setUI: (use_cpu) => {
useCPUField.checked = use_cpu
},
readUI: () => useCPUField.checked,
parse: (val) => val
},
turbo: { name: 'Turbo',
setUI: (turbo) => {
turboField.checked = turbo
},
readUI: () => turboField.checked,
parse: (val) => Boolean(val)
},
use_full_precision: { name: 'Use Full Precision',
setUI: (use_full_precision) => {
useFullPrecisionField.checked = use_full_precision
},
readUI: () => useFullPrecisionField.checked,
parse: (val) => Boolean(val)
},
stream_image_progress: { name: 'Stream Image Progress',
setUI: (stream_image_progress) => {
streamImageProgressField.checked = (parseInt(numOutputsTotalField.value) > 50 ? false : stream_image_progress)
},
readUI: () => streamImageProgressField.checked,
parse: (val) => Boolean(val)
},
show_only_filtered_image: { name: 'Show only the corrected/upscaled image',
setUI: (show_only_filtered_image) => {
showOnlyFilteredImageField.checked = show_only_filtered_image
},
readUI: () => showOnlyFilteredImageField.checked,
parse: (val) => Boolean(val)
},
output_format: { name: 'Output Format',
setUI: (output_format) => {
outputFormatField.value = output_format
},
readUI: () => outputFormatField.value,
parse: (val) => val
},
save_to_disk_path: { name: 'Save to disk path',
setUI: (save_to_disk_path) => {
saveToDiskField.checked = Boolean(save_to_disk_path)
diskPathField.value = save_to_disk_path
},
readUI: () => diskPathField.value,
parse: (val) => val
}
}
function restoreTaskToUI(task, fieldsToSkip) {
fieldsToSkip = fieldsToSkip || []
if ('numOutputsTotal' in task) {
numOutputsTotalField.value = task.numOutputsTotal
}
if ('seed' in task) {
randomSeedField.checked = false
seedField.value = task.seed
}
if (!('reqBody' in task)) {
return
}
for (const key in TASK_MAPPING) {
if (key in task.reqBody && !fieldsToSkip.includes(key)) {
TASK_MAPPING[key].setUI(task.reqBody[key])
}
}
// restore the original tag
promptField.value = task.reqBody.original_prompt || task.reqBody.prompt
// properly reset checkboxes
if (!('use_face_correction' in task.reqBody)) {
useFaceCorrectionField.checked = false
}
if (!('use_upscale' in task.reqBody)) {
useUpscalingField.checked = false
}
if (!('mask' in task.reqBody)) {
maskSetting.checked = false
}
upscaleModelField.disabled = !useUpscalingField.checked
// Show the source picture if present
initImagePreview.src = (task.reqBody.init_image == undefined ? '' : task.reqBody.init_image)
if (IMAGE_REGEX.test(initImagePreview.src)) {
Boolean(task.reqBody.mask) ? inpaintingEditor.setImg(task.reqBody.mask) : inpaintingEditor.resetBackground()
initImagePreviewContainer.style.display = 'block'
inpaintingEditorContainer.style.display = 'none'
promptStrengthContainer.style.display = 'table-row'
//samplerSelectionContainer.style.display = 'none'
// maskSetting.checked = false
inpaintingEditorContainer.style.display = maskSetting.checked ? 'block' : 'none'
} else {
initImagePreviewContainer.style.display = 'none'
// inpaintingEditorContainer.style.display = 'none'
promptStrengthContainer.style.display = 'none'
// maskSetting.style.display = 'none'
}
}
function readUI() {
const reqBody = {}
for (const key in TASK_MAPPING) {
reqBody[key] = TASK_MAPPING[key].readUI()
}
return {
'numOutputsTotal': parseInt(numOutputsTotalField.value),
'seed': TASK_MAPPING['seed'].readUI(),
'reqBody': reqBody
}
}
function getModelPath(filename, extensions)
{
let pathIdx = filename.lastIndexOf('/') // Linux, Mac paths
if (pathIdx < 0) {
pathIdx = filename.lastIndexOf('\\') // Windows paths.
}
if (pathIdx >= 0) {
filename = filename.slice(pathIdx + 1)
}
extensions.forEach(ext => {
if (filename.endsWith(ext)) {
filename = filename.slice(0, filename.length - ext.length)
}
})
return filename
}
const TASK_TEXT_MAPPING = {
width: 'Width',
height: 'Height',
seed: 'Seed',
num_inference_steps: 'Steps',
guidance_scale: 'Guidance Scale',
prompt_strength: 'Prompt Strength',
use_face_correction: 'Use Face Correction',
use_upscale: 'Use Upscaling',
sampler: 'Sampler',
negative_prompt: 'Negative Prompt',
use_stable_diffusion_model: 'Stable Diffusion model'
}
const afterPromptRe = /^\s*Width\s*:\s*\d+\s*(?:\r\n|\r|\n)+\s*Height\s*:\s*\d+\s*(\r\n|\r|\n)+Seed\s*:\s*\d+\s*$/igm
function parseTaskFromText(str) {
const taskReqBody = {}
// Prompt
afterPromptRe.lastIndex = 0
const match = afterPromptRe.exec(str)
if (match) {
let prompt = str.slice(0, match.index)
str = str.slice(prompt.length)
taskReqBody.prompt = prompt.trim()
console.log('Prompt:', taskReqBody.prompt)
}
for (const key in TASK_TEXT_MAPPING) {
const name = TASK_TEXT_MAPPING[key];
let val = undefined
const reName = new RegExp(`${name}\\ *:\\ *(.*)(?:\\r\\n|\\r|\\n)*`, 'igm')
const match = reName.exec(str);
if (match) {
str = str.slice(0, match.index) + str.slice(match.index + match[0].length)
val = match[1]
}
if (val !== undefined) {
taskReqBody[key] = TASK_MAPPING[key].parse(val.trim())
console.log(TASK_MAPPING[key].name + ':', taskReqBody[key])
if (!str) {
break
}
}
}
if (Object.keys(taskReqBody).length <= 0) {
return undefined
}
const task = { reqBody: taskReqBody }
if ('seed' in taskReqBody) {
task.seed = taskReqBody.seed
}
return task
}
async function parseContent(text) {
text = text.trim();
if (text.startsWith('{') && text.endsWith('}')) {
try {
const task = JSON.parse(text)
restoreTaskToUI(task)
return true
} catch (e) {
console.warn(`JSON text content couldn't be parsed.`, e)
}
return false
}
// Normal txt file.
const task = parseTaskFromText(text)
if (task) {
restoreTaskToUI(task)
return true
} else {
console.warn(`Raw text content couldn't be parsed.`)
return false
}
}
async function readFile(file, i) {
console.log(`Event %o reading file[${i}]:${file.name}...`)
const fileContent = (await file.text()).trim()
return await parseContent(fileContent)
}
function dropHandler(ev) {
console.log('Content dropped...')
let items = []
if (ev?.dataTransfer?.items) { // Use DataTransferItemList interface
items = Array.from(ev.dataTransfer.items)
items = items.filter(item => item.kind === 'file')
items = items.map(item => item.getAsFile())
} else if (ev?.dataTransfer?.files) { // Use DataTransfer interface
items = Array.from(ev.dataTransfer.files)
}
items.forEach(item => {item.file_ext = EXT_REGEX.exec(item.name.toLowerCase())[1]})
let text_items = items.filter(item => TEXT_EXTENSIONS.includes(item.file_ext))
let image_items = items.filter(item => IMAGE_EXTENSIONS.includes(item.file_ext))
if (image_items.length > 0 && ev.target == initImageSelector) {
return // let the event bubble up, so that the Init Image filepicker can receive this
}
ev.preventDefault() // Prevent default behavior (Prevent file/content from being opened)
text_items.forEach(readFile)
}
function dragOverHandler(ev) {
console.log('Content in drop zone')
// Prevent default behavior (Prevent file/content from being opened)
ev.preventDefault()
ev.dataTransfer.dropEffect = "copy"
let img = new Image()
img.src = location.host + '/media/images/favicon-32x32.png'
ev.dataTransfer.setDragImage(img, 16, 16)
}
document.addEventListener("drop", dropHandler)
document.addEventListener("dragover", dragOverHandler)
const TASK_REQ_NO_EXPORT = [
"use_cpu",
"turbo",
"use_full_precision",
"save_to_disk_path"
]
const resetSettings = document.getElementById('reset-image-settings')
function checkReadTextClipboardPermission (result) {
if (result.state != "granted" && result.state != "prompt") {
return
}
// PASTE ICON
const pasteIcon = document.createElement('i')
pasteIcon.className = 'fa-solid fa-paste section-button'
pasteIcon.innerHTML = `<span class="simple-tooltip right">Paste Image Settings</span>`
pasteIcon.addEventListener('click', async (event) => {
event.stopPropagation()
// Add css class 'active'
pasteIcon.classList.add('active')
// In 350 ms remove the 'active' class
asyncDelay(350).then(() => pasteIcon.classList.remove('active'))
// Retrieve clipboard content and try to parse it
const text = await navigator.clipboard.readText();
await parseContent(text)
})
resetSettings.parentNode.insertBefore(pasteIcon, resetSettings)
}
navigator.permissions.query({ name: "clipboard-read" }).then(checkReadTextClipboardPermission, (reason) => console.log('clipboard-read is not available. %o', reason))
document.addEventListener('paste', async (event) => {
if (event.target) {
const targetTag = event.target.tagName.toLowerCase()
// Disable when targeting input elements.
if (targetTag === 'input' || targetTag === 'textarea') {
return
}
}
const paste = (event.clipboardData || window.clipboardData).getData('text')
const selection = window.getSelection()
if (selection.toString().trim().length <= 0 && await parseContent(paste)) {
event.preventDefault()
return
}
})
// Adds a copy and a paste icon if the browser grants permission to write to clipboard.
function checkWriteToClipboardPermission (result) {
if (result.state != "granted" && result.state != "prompt") {
return
}
// COPY ICON
const copyIcon = document.createElement('i')
copyIcon.className = 'fa-solid fa-clipboard section-button'
copyIcon.innerHTML = `<span class="simple-tooltip right">Copy Image Settings</span>`
copyIcon.addEventListener('click', (event) => {
event.stopPropagation()
// Add css class 'active'
copyIcon.classList.add('active')
// In 350 ms remove the 'active' class
asyncDelay(350).then(() => copyIcon.classList.remove('active'))
const uiState = readUI()
TASK_REQ_NO_EXPORT.forEach((key) => delete uiState.reqBody[key])
if (uiState.reqBody.init_image && !IMAGE_REGEX.test(uiState.reqBody.init_image)) {
delete uiState.reqBody.init_image
delete uiState.reqBody.prompt_strength
}
navigator.clipboard.writeText(JSON.stringify(uiState, undefined, 4))
})
resetSettings.parentNode.insertBefore(copyIcon, resetSettings)
}
// Determine which access we have to the clipboard. Clipboard access is only available on localhost or via TLS.
navigator.permissions.query({ name: "clipboard-write" }).then(checkWriteToClipboardPermission, (e) => {
if (e instanceof TypeError && typeof navigator?.clipboard?.writeText === 'function') {
// Fix for firefox https://bugzilla.mozilla.org/show_bug.cgi?id=1560373
checkWriteToClipboardPermission({state:"granted"})
}
})

View File

@ -0,0 +1,349 @@
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'
}
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)
const trimmedName = trimModifiers(modifierName)
modifierCard.addEventListener('click', () => {
if (activeTags.map(x => trimModifiers(x.name)).includes(trimmedName)) {
// remove modifier from active array
activeTags = activeTags.filter(x => trimModifiers(x.name) != trimmedName)
toggleCardState(modifierCard, false)
} else {
// add modifier to active array
activeTags.push({
'name': modifierName,
'element': modifierCard.cloneNode(true),
'originElement': modifierCard,
'previews': modifierPreviews
})
toggleCardState(modifierCard, true)
}
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
}
function trimModifiers(tag) {
return tag.replace(/^\(+|\)+$/g, '').replace(/^\[+|\]+$/g, '')
}
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 refreshModifiersState(newTags) {
// clear existing modifiers
document.querySelector('#editor-modifiers').querySelectorAll('.modifier-card').forEach(modifierCard => {
const modifierName = modifierCard.querySelector('.modifier-card-label').innerText
if (activeTags.map(x => x.name).includes(modifierName)) {
modifierCard.classList.remove(activeCardClass)
modifierCard.querySelector('.modifier-card-image-overlay').innerText = '+'
}
})
activeTags = []
// set new modifiers
newTags.forEach(tag => {
let found = false
document.querySelector('#editor-modifiers').querySelectorAll('.modifier-card').forEach(modifierCard => {
const modifierName = modifierCard.querySelector('.modifier-card-label').innerText
if (tag == modifierName) {
// add modifier to active array
if (!activeTags.map(x => x.name).includes(tag)) { // only add each tag once even if several custom modifier cards share the same tag
activeTags.push({
'name': modifierName,
'element': modifierCard.cloneNode(true),
'originElement': modifierCard
})
}
modifierCard.classList.add(activeCardClass)
modifierCard.querySelector('.modifier-card-image-overlay').innerText = '-'
found = true
}
})
if (found == false) { // custom tag went missing, create one here
let modifierCard = createModifierCard(tag, undefined) // create a modifier card for the missing tag, no image
modifierCard.addEventListener('click', () => {
if (activeTags.map(x => x.name).includes(tag)) {
// remove modifier from active array
activeTags = activeTags.filter(x => x.name != tag)
modifierCard.classList.remove(activeCardClass)
modifierCard.querySelector('.modifier-card-image-overlay').innerText = '+'
}
refreshTagsList()
})
activeTags.push({
'name': tag,
'element': modifierCard,
'originElement': undefined // no origin element for missing tags
})
}
})
refreshTagsList()
}
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 !== undefined) {
toggleCardState(activeTags[idx].originElement, false)
activeTags.splice(idx, 1)
refreshTagsList()
}
})
})
let brk = document.createElement('br')
brk.style.clear = 'both'
editorModifierTagsList.appendChild(brk)
}
function toggleCardState(card, makeActive) {
if (makeActive) {
card.classList.add(activeCardClass)
card.querySelector('.modifier-card-image-overlay').innerText = '-'
} else {
card.classList.remove(activeCardClass)
card.querySelector('.modifier-card-image-overlay').innerText = '+'
}
}
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(e) {
modifierSettingsOverlay.classList.add("active")
e.stopPropagation()
})
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)
}

10
ui/media/js/jquery-confirm.min.js vendored Normal file

File diff suppressed because one or more lines are too long

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

File diff suppressed because it is too large Load Diff

6
ui/media/js/marked.min.js vendored Normal file

File diff suppressed because one or more lines are too long

440
ui/media/js/parameters.js Normal file
View File

@ -0,0 +1,440 @@
/**
* Enum of parameter types
* @readonly
* @enum {string}
*/
var ParameterType = {
checkbox: "checkbox",
select: "select",
select_multiple: "select_multiple",
custom: "custom",
};
/**
* JSDoc style
* @typedef {object} Parameter
* @property {string} id
* @property {ParameterType} type
* @property {string} label
* @property {?string} note
* @property {number|boolean|string} default
*/
/** @type {Array.<Parameter>} */
var PARAMETERS = [
{
id: "theme",
type: ParameterType.select,
label: "Theme",
default: "theme-default",
note: "customize the look and feel of the ui",
options: [ // Note: options expanded dynamically
{
value: "theme-default",
label: "Default"
}
],
icon: "fa-palette"
},
{
id: "save_to_disk",
type: ParameterType.checkbox,
label: "Auto-Save Images",
note: "automatically saves images to the specified location",
icon: "fa-download",
default: false,
},
{
id: "diskPath",
type: ParameterType.custom,
label: "Save Location",
render: (parameter) => {
return `<input id="${parameter.id}" name="${parameter.id}" size="30" disabled>`
}
},
{
id: "sound_toggle",
type: ParameterType.checkbox,
label: "Enable Sound",
note: "plays a sound on task completion",
icon: "fa-volume-low",
default: true,
},
{
id: "ui_open_browser_on_start",
type: ParameterType.checkbox,
label: "Open browser on startup",
note: "starts the default browser on startup",
icon: "fa-window-restore",
default: true,
},
{
id: "turbo",
type: ParameterType.checkbox,
label: "Turbo Mode",
note: "generates images faster, but uses an additional 1 GB of GPU memory",
icon: "fa-forward",
default: true,
},
{
id: "use_cpu",
type: ParameterType.checkbox,
label: "Use CPU (not GPU)",
note: "warning: this will be *very* slow",
icon: "fa-microchip",
default: false,
},
{
id: "auto_pick_gpus",
type: ParameterType.checkbox,
label: "Automatically pick the GPUs (experimental)",
default: false,
},
{
id: "use_gpus",
type: ParameterType.select_multiple,
label: "GPUs to use (experimental)",
note: "to process in parallel",
default: false,
},
{
id: "use_full_precision",
type: ParameterType.checkbox,
label: "Use Full Precision",
note: "for GPU-only. warning: this will consume more VRAM",
icon: "fa-crosshairs",
default: false,
},
{
id: "auto_save_settings",
type: ParameterType.checkbox,
label: "Auto-Save Settings",
note: "restores settings on browser load",
icon: "fa-gear",
default: true,
},
{
id: "confirm_dangerous_actions",
type: ParameterType.checkbox,
label: "Confirm dangerous actions",
note: "Actions that might lead to data loss must either be clicked with the shift key pressed, or confirmed in an 'Are you sure?' dialog",
icon: "fa-check-double",
default: true,
},
{
id: "listen_to_network",
type: ParameterType.checkbox,
label: "Make Stable Diffusion available on your network",
note: "Other devices on your network can access this web page",
icon: "fa-network-wired",
default: true,
},
{
id: "listen_port",
type: ParameterType.custom,
label: "Network port",
note: "Port that this server listens to. The '9000' part in 'http://localhost:9000'",
icon: "fa-anchor",
render: (parameter) => {
return `<input id="${parameter.id}" name="${parameter.id}" size="6" value="9000" onkeypress="preventNonNumericalInput(event)">`
}
},
{
id: "test_sd2",
type: ParameterType.checkbox,
label: "Test SD 2.0",
note: "Experimental! High memory usage! GPU-only! Not the final version! Please restart the program after changing this.",
icon: "fa-fire",
default: false,
},
{
id: "use_beta_channel",
type: ParameterType.checkbox,
label: "Beta channel",
note: "Get the latest features immediately (but could be less stable). Please restart the program after changing this.",
icon: "fa-fire",
default: false,
},
];
function getParameterSettingsEntry(id) {
let parameter = PARAMETERS.filter(p => p.id === id)
if (parameter.length === 0) {
return
}
return parameter[0].settingsEntry
}
function getParameterElement(parameter) {
switch (parameter.type) {
case ParameterType.checkbox:
var is_checked = parameter.default ? " checked" : "";
return `<input id="${parameter.id}" name="${parameter.id}"${is_checked} type="checkbox">`
case ParameterType.select:
case ParameterType.select_multiple:
var options = (parameter.options || []).map(option => `<option value="${option.value}">${option.label}</option>`).join("")
var multiple = (parameter.type == ParameterType.select_multiple ? 'multiple' : '')
return `<select id="${parameter.id}" name="${parameter.id}" ${multiple}>${options}</select>`
case ParameterType.custom:
return parameter.render(parameter)
default:
console.error(`Invalid type for parameter ${parameter.id}`);
return "ERROR: Invalid Type"
}
}
let parametersTable = document.querySelector("#system-settings .parameters-table")
/* fill in the system settings popup table */
function initParameters() {
PARAMETERS.forEach(parameter => {
var element = getParameterElement(parameter)
var note = parameter.note ? `<small>${parameter.note}</small>` : "";
var icon = parameter.icon ? `<i class="fa ${parameter.icon}"></i>` : "";
var newrow = document.createElement('div')
newrow.innerHTML = `
<div>${icon}</div>
<div><label for="${parameter.id}">${parameter.label}</label>${note}</div>
<div>${element}</div>`
parametersTable.appendChild(newrow)
parameter.settingsEntry = newrow
})
}
initParameters()
let turboField = document.querySelector('#turbo')
let useCPUField = document.querySelector('#use_cpu')
let autoPickGPUsField = document.querySelector('#auto_pick_gpus')
let useGPUsField = document.querySelector('#use_gpus')
let useFullPrecisionField = document.querySelector('#use_full_precision')
let saveToDiskField = document.querySelector('#save_to_disk')
let diskPathField = document.querySelector('#diskPath')
let listenToNetworkField = document.querySelector("#listen_to_network")
let listenPortField = document.querySelector("#listen_port")
let testSD2Field = document.querySelector("#test_sd2")
let useBetaChannelField = document.querySelector("#use_beta_channel")
let uiOpenBrowserOnStartField = document.querySelector("#ui_open_browser_on_start")
let confirmDangerousActionsField = document.querySelector("#confirm_dangerous_actions")
let saveSettingsBtn = document.querySelector('#save-system-settings-btn')
async function changeAppConfig(configDelta) {
try {
let res = await fetch('/app_config', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(configDelta)
})
res = await res.json()
console.log('set config status response', res)
} catch (e) {
console.log('set config status error', e)
}
}
async function getAppConfig() {
try {
let res = await fetch('/get/app_config')
const config = await res.json()
if (config.update_branch === 'beta') {
useBetaChannelField.checked = true
document.querySelector("#updateBranchLabel").innerText = "(beta)"
}
if (config.ui && config.ui.open_browser_on_start === false) {
uiOpenBrowserOnStartField.checked = false
}
if ('test_sd2' in config) {
testSD2Field.checked = config['test_sd2']
}
let testSD2SettingEntry = getParameterSettingsEntry('test_sd2')
testSD2SettingEntry.style.display = (config.update_branch === 'beta' ? '' : 'none')
if (config.net && config.net.listen_to_network === false) {
listenToNetworkField.checked = false
}
if (config.net && config.net.listen_port !== undefined) {
listenPortField.value = config.net.listen_port
}
console.log('get config status response', config)
} catch (e) {
console.log('get config status error', e)
}
}
saveToDiskField.addEventListener('change', function(e) {
diskPathField.disabled = !this.checked
})
function getCurrentRenderDeviceSelection() {
let selectedGPUs = $('#use_gpus').val()
if (useCPUField.checked && !autoPickGPUsField.checked) {
return 'cpu'
}
if (autoPickGPUsField.checked || selectedGPUs.length == 0) {
return 'auto'
}
return selectedGPUs.join(',')
}
useCPUField.addEventListener('click', function() {
let gpuSettingEntry = getParameterSettingsEntry('use_gpus')
let autoPickGPUSettingEntry = getParameterSettingsEntry('auto_pick_gpus')
if (this.checked) {
gpuSettingEntry.style.display = 'none'
autoPickGPUSettingEntry.style.display = 'none'
autoPickGPUsField.setAttribute('data-old-value', autoPickGPUsField.checked)
autoPickGPUsField.checked = false
} else if (useGPUsField.options.length >= MIN_GPUS_TO_SHOW_SELECTION) {
gpuSettingEntry.style.display = ''
autoPickGPUSettingEntry.style.display = ''
let oldVal = autoPickGPUsField.getAttribute('data-old-value')
if (oldVal === null || oldVal === undefined) { // the UI started with CPU selected by default
autoPickGPUsField.checked = true
} else {
autoPickGPUsField.checked = (oldVal === 'true')
}
gpuSettingEntry.style.display = (autoPickGPUsField.checked ? 'none' : '')
}
})
useGPUsField.addEventListener('click', function() {
let selectedGPUs = $('#use_gpus').val()
autoPickGPUsField.checked = (selectedGPUs.length === 0)
})
autoPickGPUsField.addEventListener('click', function() {
if (this.checked) {
$('#use_gpus').val([])
}
let gpuSettingEntry = getParameterSettingsEntry('use_gpus')
gpuSettingEntry.style.display = (this.checked ? 'none' : '')
})
async function getDiskPath() {
try {
var diskPath = getSetting("diskPath")
if (diskPath == '' || diskPath == undefined || diskPath == "undefined") {
let res = await fetch('/get/output_dir')
if (res.status === 200) {
res = await res.json()
res = res.output_dir
setSetting("diskPath", res)
}
}
} catch (e) {
console.log('error fetching output dir path', e)
}
}
function setDeviceInfo(devices) {
let cpu = devices.all.cpu.name
let allGPUs = Object.keys(devices.all).filter(d => d != 'cpu')
let activeGPUs = Object.keys(devices.active)
function ID_TO_TEXT(d) {
let info = devices.all[d]
if ("mem_free" in info && "mem_total" in info) {
return `${info.name} <small>(${d}) (${info.mem_free.toFixed(1)}Gb free / ${info.mem_total.toFixed(1)} Gb total)</small>`
} else {
return `${info.name} <small>(${d}) (no memory info)</small>`
}
}
allGPUs = allGPUs.map(ID_TO_TEXT)
activeGPUs = activeGPUs.map(ID_TO_TEXT)
let systemInfoEl = document.querySelector('#system-info')
systemInfoEl.querySelector('#system-info-cpu').innerText = cpu
systemInfoEl.querySelector('#system-info-gpus-all').innerHTML = allGPUs.join('</br>')
systemInfoEl.querySelector('#system-info-rendering-devices').innerHTML = activeGPUs.join('</br>')
}
function setHostInfo(hosts) {
let port = listenPortField.value
hosts = hosts.map(addr => `http://${addr}:${port}/`).map(url => `<div><a href="${url}">${url}</a></div>`)
document.querySelector('#system-info-server-hosts').innerHTML = hosts.join('')
}
async function getSystemInfo() {
try {
let res = await fetch('/get/system_info')
if (res.status === 200) {
res = await res.json()
let devices = res['devices']
let hosts = res['hosts']
let allDeviceIds = Object.keys(devices['all']).filter(d => d !== 'cpu')
let activeDeviceIds = Object.keys(devices['active']).filter(d => d !== 'cpu')
if (activeDeviceIds.length === 0) {
useCPUField.checked = true
}
if (allDeviceIds.length < MIN_GPUS_TO_SHOW_SELECTION || useCPUField.checked) {
let gpuSettingEntry = getParameterSettingsEntry('use_gpus')
gpuSettingEntry.style.display = 'none'
let autoPickGPUSettingEntry = getParameterSettingsEntry('auto_pick_gpus')
autoPickGPUSettingEntry.style.display = 'none'
}
if (allDeviceIds.length === 0) {
useCPUField.checked = true
useCPUField.disabled = true // no compatible GPUs, so make the CPU mandatory
}
autoPickGPUsField.checked = (devices['config'] === 'auto')
useGPUsField.innerHTML = ''
allDeviceIds.forEach(device => {
let deviceName = devices['all'][device]['name']
let deviceOption = `<option value="${device}">${deviceName} (${device})</option>`
useGPUsField.insertAdjacentHTML('beforeend', deviceOption)
})
if (autoPickGPUsField.checked) {
let gpuSettingEntry = getParameterSettingsEntry('use_gpus')
gpuSettingEntry.style.display = 'none'
} else {
$('#use_gpus').val(activeDeviceIds)
}
setDeviceInfo(devices)
setHostInfo(hosts)
}
} catch (e) {
console.log('error fetching devices', e)
}
}
saveSettingsBtn.addEventListener('click', function() {
let updateBranch = (useBetaChannelField.checked ? 'beta' : 'main')
if (listenPortField.value == '') {
alert('The network port field must not be empty.')
} else if (listenPortField.value<1 || listenPortField.value>65535) {
alert('The network port must be a number from 1 to 65535')
} else {
changeAppConfig({
'render_devices': getCurrentRenderDeviceSelection(),
'update_branch': updateBranch,
'ui_open_browser_on_start': uiOpenBrowserOnStartField.checked,
'listen_to_network': listenToNetworkField.checked,
'listen_port': listenPortField.value,
'test_sd2': testSD2Field.checked
})
}
saveSettingsBtn.classList.add('active')
asyncDelay(300).then(() => saveSettingsBtn.classList.remove('active'))
})

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)
}
}

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

@ -0,0 +1,81 @@
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-") && !selector.includes(" ")) {
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);
let borderColor = undefined
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));
});
borderColor = theme.rule.style.getPropertyValue('--input-border-color').trim()
if (!borderColor.startsWith('#')) {
borderColor = theme.rule.style.getPropertyValue('--theme-color-fallback')
}
} else {
borderColor = DEFAULT_THEME.rule.style.getPropertyValue('--theme-color-fallback')
}
document.querySelector('meta[name="theme-color"]').setAttribute("content", borderColor)
}
themeField.addEventListener('change', themeFieldChanged);

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

@ -0,0 +1,376 @@
// 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 (!collapsibleHeader.classList.contains("active")) {
content.style.display = "none"
if (handle != null) { // render results don't have a handle
handle.innerHTML = '&#x2795;' // plus
}
} else {
content.style.display = "block"
if (handle != null) { // render results don't have a handle
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.classList.contains("active")) {
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();
}
}
/* inserts custom html to allow prettifying of inputs */
function prettifyInputs(root_element) {
root_element.querySelectorAll(`input[type="checkbox"]`).forEach(element => {
var parent = element.parentNode;
if (!parent.classList.contains("input-toggle")) {
var wrapper = document.createElement("div");
wrapper.classList.add("input-toggle");
parent.replaceChild(wrapper, element);
wrapper.appendChild(element);
var label = document.createElement("label");
label.htmlFor = element.id;
wrapper.appendChild(label);
}
})
}

View File

@ -1,412 +0,0 @@
body {
font-family: Arial, Helvetica, sans-serif;
font-size: 11pt;
background-color: rgb(32, 33, 36);
color: #eee;
}
a {
color: rgb(0, 102, 204);
}
a:visited {
color: rgb(0, 102, 204);
}
label {
font-size: 10pt;
}
#prompt {
width: 100%;
height: 65pt;
box-sizing: border-box;
}
@media screen and (max-width: 600px) {
#prompt {
width: 95%;
}
}
.image_preview_container {
/* display: none; */
margin-top: 10pt;
}
.image_clear_btn {
position: absolute;
transform: translateX(-50%) translateY(-35%);
background: black;
color: white;
border: 2pt solid #ccc;
padding: 0;
cursor: pointer;
outline: inherit;
border-radius: 8pt;
width: 16pt;
height: 16pt;
font-family: Verdana;
font-size: 8pt;
}
.settings-box ul {
font-size: 9pt;
margin-bottom: 5px;
padding-left: 10px;
list-style-type: none;
}
.settings-box li {
padding-bottom: 4pt;
}
.editor-slider {
vertical-align: middle;
}
.outputMsg {
font-size: small;
padding-bottom: 3pt;
}
#progressBar {
font-size: small;
}
#footer {
font-size: small;
padding-left: 10pt;
background: none;
}
#footer-legal {
font-size: 8pt;
}
.imgSeedLabel {
position: absolute;
transform: translateX(-100%);
margin-top: 5pt;
margin-left: -5pt;
font-size: 10pt;
background-color: #333;
opacity: 0.8;
color: #ddd;
border-radius: 3pt;
padding: 1pt 3pt;
}
.imgUseBtn {
position: absolute;
transform: translateX(-100%);
margin-top: 30pt;
margin-left: -5pt;
}
.imgSaveBtn {
position: absolute;
transform: translateX(-100%);
margin-top: 55pt;
margin-left: -5pt;
}
.imgItem {
display: inline;
padding-right: 10px;
}
.imgItemInfo {
opacity: 0.5;
}
#container {
width: 90%;
margin-left: auto;
margin-right: auto;
}
@media screen and (max-width: 1800px) {
#container {
width: 100%;
}
}
#logo small {
font-size: 11pt;
}
#editor {
padding: 5px;
}
#editor label {
font-weight: normal;
}
.settings-box label small {
color: rgb(153, 153, 153);
}
#preview {
padding: 5px;
}
#editor-inputs {
margin-bottom: 20px;
}
#editor-inputs-prompt {
flex: 1;
}
#editor-inputs .row {
padding-bottom: 10px;
}
#makeImage {
border-radius: 6px;
}
#editor-modifiers h5 {
padding: 5pt 0;
margin: 0;
}
#makeImage {
flex: 0 0 70px;
background: rgb(80, 0, 185);
border: 2px solid rgb(40, 0, 78);
color: rgb(255, 221, 255);
width: 100%;
height: 30pt;
}
#makeImage:hover {
background: rgb(93, 0, 214);
}
#stopImage {
flex: 0 0 70px;
background: rgb(132, 8, 0);
border: 2px solid rgb(122, 29, 0);
color: rgb(255, 221, 255);
width: 100%;
height: 30pt;
border-radius: 6px;
display: none;
}
#stopImage:hover {
background: rgb(177, 27, 0);
}
.flex-container {
display: flex;
}
.col-50 {
flex: 50%;
}
.col-fixed-10 {
flex: 0 0 380pt;
}
.col-free {
flex: 1;
}
.collapsible {
cursor: pointer;
}
.collapsible-content {
display: none;
padding-left: 15px;
}
.collapsible-content h5 {
padding: 5pt 0pt;
margin: 0;
font-size: 10pt;
}
.collapsible-handle {
color: white;
padding-right: 5px;
}
.panel-box {
background: rgb(44, 45, 48);
border: 1px solid rgb(47, 49, 53);
border-radius: 7px;
padding: 5px;
margin-bottom: 15px;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.15), 0 6px 20px 0 rgba(0, 0, 0, 0.15);
}
.panel-box h4 {
margin: 0;
padding: 2px 0;
}
#editor-modifiers .editor-modifiers-leaf {
padding-top: 10pt;
padding-bottom: 10pt;
}
#preview {
margin-left: 10pt;
}
img {
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.15), 0 6px 20px 0 rgba(0, 0, 0, 0.15);
}
.line-separator {
background: rgb(56, 56, 56);
height: 1pt;
margin: 15pt 0;
}
#editor-inputs-tags-container {
margin-top: 5pt;
display: none;
}
#server-status {
display: inline;
float: right;
transform: translateY(-5pt);
}
#server-status-color {
/* width: 8pt;
height: 8pt;
border-radius: 4pt; */
font-size: 14pt;
color: rgb(128, 87, 0);
/* background-color: rgb(197, 1, 1); */
/* transform: translateY(15%); */
display: inline;
}
#server-status-msg {
color: rgb(128, 87, 0);
padding-left: 2pt;
font-size: 10pt;
}
.preview-prompt {
font-size: 16pt;
margin-bottom: 10pt;
}
#coffeeButton {
height: 23px;
transform: translateY(25%);
}
#inpaintingEditor {
width: 300pt;
height: 300pt;
margin-top: 5pt;
}
.drawing-board-canvas-wrapper {
background-size: 100% 100%;
}
.drawing-board-control > button {
background-color: #eee;
border-radius: 3pt;
}
.drawing-board-control-inner {
background-color: #eee;
border-radius: 3pt;
}
#inpaintingEditor canvas {
opacity: 0.6;
}
#enable_mask {
margin-top: 8pt;
}
#top-nav {
padding-top: 3pt;
padding-bottom: 15pt;
}
#top-nav .icon {
padding-right: 4pt;
font-size: 14pt;
transform: translateY(1pt);
}
#logo {
display: inline;
}
#logo h1 {
display: inline;
}
#top-nav-items {
list-style-type: none;
display: inline;
float: right;
}
#top-nav-items > li {
float: left;
display: inline;
padding-left: 20pt;
cursor: default;
}
#initial-text {
padding-top: 15pt;
padding-left: 4pt;
}
.settings-subheader {
font-size: 10pt;
font-weight: bold;
}
.pl-5 {
padding-left: 5pt;
}
#system-settings {
width: 360pt;
transform: translateX(-100%) translateX(70pt);
padding-top: 10pt;
padding-bottom: 10pt;
}
#system-settings ul {
margin: 0;
padding: 0;
}
#system-settings li {
padding-left: 5pt;
}
#community-links {
list-style-type: none;
margin: 0;
padding: 12pt;
padding-bottom: 0pt;
transform: translateX(-15%);
}
#community-links li {
padding-bottom: 12pt;
display: block;
font-size: 10pt;
}
#community-links li .fa-fw {
padding-right: 2pt;
}
#community-links li a {
color: white;
text-decoration: none;
}
.dropdown {
overflow: hidden;
}
.dropdown-content {
display: none;
position: absolute;
z-index: 2;
background: rgb(18, 18, 19);
border: 2px solid rgb(37, 38, 41);
border-radius: 7px;
padding: 5px;
margin-bottom: 15px;
box-shadow: 0 20px 28px 0 rgba(0, 0, 0, 0.15), 0 6px 20px 0 rgba(0, 0, 0, 0.15);
}
.dropdown:hover .dropdown-content {
display: block;
}
.imageTaskContainer {
border: 1px solid #333;
margin-bottom: 10pt;
padding: 5pt;
border-radius: 5pt;
box-shadow: 0 20px 28px 0 rgba(0, 0, 0, 0.15), 0 6px 20px 0 rgba(0, 0, 0, 0.15);
}
.taskStatusLabel {
float: left;
font-size: 8pt;
background:rgb(44, 45, 48);
border: 1px solid rgb(61, 62, 66);
padding: 2pt 4pt;
border-radius: 2pt;
margin-right: 5pt;
}
.activeTaskLabel {
background:rgb(0, 90, 30);
border: 1px solid rgb(0, 75, 19);
color:rgb(204, 255, 217)
}
.secondaryButton {
background: rgb(132, 8, 0);
border: 1px solid rgb(122, 29, 0);
color: rgb(255, 221, 255);
padding: 3pt 6pt;
border-radius: 5px;
}
.secondaryButton:hover {
background: rgb(177, 27, 0);
}
.stopTask {
float: right;
}
#preview-tools {
display: none;
padding: 4pt;
}
.taskConfig {
font-size: 10pt;
color: #aaa;
margin-bottom: 5pt;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
{
"name": "Stable Diffusion UI",
"display": "standalone",
"display_override": [
"window-controls-overlay"
],
"theme_color": "#000000"
}

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

@ -0,0 +1,42 @@
(function () {
"use strict"
var styleSheet = document.createElement("style");
styleSheet.textContent = `
.auto-scroll {
float: right;
}
`;
document.head.appendChild(styleSheet);
const autoScrollControl = document.createElement('div');
autoScrollControl.innerHTML = `<input id="auto_scroll" name="auto_scroll" type="checkbox">
<label for="auto_scroll">Scroll to generated image</label>`
autoScrollControl.className = "auto-scroll"
clearAllPreviewsBtn.parentNode.insertBefore(autoScrollControl, clearAllPreviewsBtn.nextSibling)
prettifyInputs(document);
let autoScroll = document.querySelector("#auto_scroll")
SETTINGS_IDS_LIST.push("auto_scroll")
initSettings()
// observe for changes in the preview pane
var observer = new MutationObserver(function (mutations) {
mutations.forEach(function (mutation) {
if (mutation.target.className == 'img-batch') {
Autoscroll(mutation.target)
}
})
})
observer.observe(document.getElementById('preview'), {
childList: true,
subtree: true
})
function Autoscroll(target) {
if (autoScroll.checked && target !== null) {
target.parentElement.parentElement.parentElement.scrollIntoView();
}
}
})()

View File

@ -0,0 +1,91 @@
(function () {
"use strict"
var styleSheet = document.createElement("style");
styleSheet.textContent = `
.modifier-card-tiny.drag-sort-active {
background: transparent;
border: 2px dashed white;
opacity:0.2;
}
`;
document.head.appendChild(styleSheet);
// observe for changes in tag list
var observer = new MutationObserver(function (mutations) {
// mutations.forEach(function (mutation) {
if (editorModifierTagsList.childNodes.length > 0) {
ModifierDragAndDrop(editorModifierTagsList)
}
// })
})
observer.observe(editorModifierTagsList, {
childList: true
})
let current
function ModifierDragAndDrop(target) {
let overlays = document.querySelector('#editor-inputs-tags-list').querySelectorAll('.modifier-card-overlay')
overlays.forEach (i => {
i.parentElement.draggable = true;
i.parentElement.ondragstart = (e) => {
current = i
i.parentElement.getElementsByClassName('modifier-card-image-overlay')[0].innerText = ''
i.parentElement.draggable = true
i.parentElement.classList.add('drag-sort-active')
for(let item of document.querySelector('#editor-inputs-tags-list').getElementsByClassName('modifier-card-image-overlay')) {
if (item.parentElement.parentElement.getElementsByClassName('modifier-card-overlay')[0] != current) {
item.parentElement.parentElement.getElementsByClassName('modifier-card-image-overlay')[0].style.opacity = 0
if(item.parentElement.getElementsByClassName('modifier-card-image').length > 0) {
item.parentElement.getElementsByClassName('modifier-card-image')[0].style.filter = 'none'
}
item.parentElement.parentElement.style.transform = 'none'
item.parentElement.parentElement.style.boxShadow = 'none'
}
item.innerText = ''
}
}
i.ondragenter = (e) => {
e.preventDefault()
if (i != current) {
let currentPos = 0, droppedPos = 0;
for (let it = 0; it < overlays.length; it++) {
if (current == overlays[it]) { currentPos = it; }
if (i == overlays[it]) { droppedPos = it; }
}
if (i.parentElement != current.parentElement) {
let currentPos = 0, droppedPos = 0
for (let it = 0; it < overlays.length; it++) {
if (current == overlays[it]) { currentPos = it }
if (i == overlays[it]) { droppedPos = it }
}
if (currentPos < droppedPos) {
current = i.parentElement.parentNode.insertBefore(current.parentElement, i.parentElement.nextSibling).getElementsByClassName('modifier-card-overlay')[0]
} else {
current = i.parentElement.parentNode.insertBefore(current.parentElement, i.parentElement).getElementsByClassName('modifier-card-overlay')[0]
}
// update activeTags
const tag = activeTags.splice(currentPos, 1)
activeTags.splice(droppedPos, 0, tag[0])
}
}
};
i.ondragover = (e) => {
e.preventDefault()
}
i.parentElement.ondragend = (e) => {
i.parentElement.classList.remove('drag-sort-active')
for(let item of document.querySelector('#editor-inputs-tags-list').getElementsByClassName('modifier-card-image-overlay')) {
item.style.opacity = ''
item.innerText = '-'
}
}
})
}
})()

View File

@ -0,0 +1,62 @@
(function () {
"use strict"
// observe for changes in tag list
var observer = new MutationObserver(function (mutations) {
// mutations.forEach(function (mutation) {
if (editorModifierTagsList.childNodes.length > 0) {
ModifierMouseWheel(editorModifierTagsList)
}
// })
})
observer.observe(editorModifierTagsList, {
childList: true
})
function ModifierMouseWheel(target) {
let overlays = document.querySelector('#editor-inputs-tags-list').querySelectorAll('.modifier-card-overlay')
overlays.forEach (i => {
i.onwheel = (e) => {
if (e.ctrlKey == true) {
e.preventDefault()
const delta = Math.sign(event.deltaY)
let s = i.parentElement.getElementsByClassName('modifier-card-label')[0].getElementsByTagName("p")[0].innerText
if (delta < 0) {
// wheel scrolling up
if (s.substring(0, 1) == '[' && s.substring(s.length-1) == ']') {
s = s.substring(1, s.length - 1)
}
else
{
if (s.substring(0, 10) !== '('.repeat(10) && s.substring(s.length-10) !== ')'.repeat(10)) {
s = '(' + s + ')'
}
}
}
else{
// wheel scrolling down
if (s.substring(0, 1) == '(' && s.substring(s.length-1) == ')') {
s = s.substring(1, s.length - 1)
}
else
{
if (s.substring(0, 10) !== '['.repeat(10) && s.substring(s.length-10) !== ']'.repeat(10)) {
s = '[' + s + ']'
}
}
}
i.parentElement.getElementsByClassName('modifier-card-label')[0].getElementsByTagName("p")[0].innerText = s
// update activeTags
for (let it = 0; it < overlays.length; it++) {
if (i == overlays[it]) {
activeTags[it].name = s
break
}
}
}
}
})
}
})()

View File

@ -0,0 +1,3 @@
Custom plugins in this folder will be shipped to all the users by default.
This allows UI features to be built as plugins (testing our Plugins API, and keeping our core lean and modular).

View File

@ -0,0 +1,47 @@
(function() {
document.querySelector('#tab-container').insertAdjacentHTML('beforeend', `
<span id="tab-news" class="tab">
<span><i class="fa fa-bolt icon"></i> What's new?</span>
</span>
`)
document.querySelector('#tab-content-wrapper').insertAdjacentHTML('beforeend', `
<div id="tab-content-news" class="tab-content">
<div id="news" class="tab-content-inner">
Loading..
</div>
</div>
`)
document.querySelector('body').insertAdjacentHTML('beforeend', `
<style>
#tab-content-news .tab-content-inner {
max-width: 100%;
text-align: left;
padding: 10pt;
}
</style>
`)
linkTabContents(document.querySelector('#tab-news'))
let markedScript = document.createElement('script')
markedScript.src = '/media/js/marked.min.js'
markedScript.onload = async function() {
let appConfig = await fetch('/get/app_config')
appConfig = await appConfig.json()
let updateBranch = appConfig.update_branch || 'main'
let news = document.querySelector('#news')
let releaseNotes = await fetch(`https://raw.githubusercontent.com/cmdr2/stable-diffusion-ui/${updateBranch}/CHANGES.md`)
if (releaseNotes.status != 200) {
return
}
releaseNotes = await releaseNotes.text()
news.innerHTML = marked.parse(releaseNotes)
}
document.querySelector('body').appendChild(markedScript)
})()

View File

@ -18,11 +18,13 @@ class Request:
precision: str = "autocast" # or "full"
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"
use_vae_model: str = None
show_only_filtered_image: bool = False
output_format: str = "jpeg" # or "png"
stream_progress_updates: bool = False
stream_image_progress: bool = False
@ -42,9 +44,12 @@ class Request:
"sampler": self.sampler,
"use_face_correction": self.use_face_correction,
"use_upscale": self.use_upscale,
"use_stable_diffusion_model": self.use_stable_diffusion_model,
"use_vae_model": self.use_vae_model,
"output_format": self.output_format,
}
def to_string(self):
def __str__(self):
return f'''
session_id: {self.session_id}
prompt: {self.prompt}
@ -58,11 +63,13 @@ class Request:
precision: {self.precision}
save_to_disk_path: {self.save_to_disk_path}
turbo: {self.turbo}
use_cpu: {self.use_cpu}
use_full_precision: {self.use_full_precision}
use_face_correction: {self.use_face_correction}
use_upscale: {self.use_upscale}
use_stable_diffusion_model: {self.use_stable_diffusion_model}
use_vae_model: {self.use_vae_model}
show_only_filtered_image: {self.show_only_filtered_image}
output_format: {self.output_format}
stream_progress_updates: {self.stream_progress_updates}
stream_image_progress: {self.stream_image_progress}'''

View File

@ -1,72 +1,13 @@
diff --git a/optimizedSD/ddpm.py b/optimizedSD/ddpm.py
index b967b55..35ef520 100644
index 79058bc..a473411 100644
--- a/optimizedSD/ddpm.py
+++ b/optimizedSD/ddpm.py
@@ -22,7 +22,7 @@ from ldm.util import exists, default, instantiate_from_config
from ldm.modules.diffusionmodules.util import make_beta_schedule
from ldm.modules.diffusionmodules.util import make_ddim_sampling_parameters, make_ddim_timesteps, noise_like
from ldm.modules.diffusionmodules.util import make_beta_schedule, extract_into_tensor, noise_like
-from samplers import CompVisDenoiser, get_ancestral_step, to_d, append_dims,linear_multistep_coeff
+from .samplers import CompVisDenoiser, get_ancestral_step, to_d, append_dims,linear_multistep_coeff
@@ -564,12 +564,12 @@ class UNet(DDPM):
unconditional_guidance_scale=unconditional_guidance_scale,
callback=callback, img_callback=img_callback)
def disabled_train(self):
"""Overwrite model.train with this function to make sure train/eval mode
@@ -506,6 +506,8 @@ class UNet(DDPM):
x_latent = noise if x0 is None else x0
# sampling
+ if sampler in ('ddim', 'dpm2', 'heun', 'dpm2_a', 'lms') and not hasattr(self, 'ddim_timesteps'):
+ self.make_schedule(ddim_num_steps=S, ddim_eta=eta, verbose=False)
if sampler == "plms":
self.make_schedule(ddim_num_steps=S, ddim_eta=eta, verbose=False)
@@ -528,39 +530,46 @@ class UNet(DDPM):
elif sampler == "ddim":
samples = self.ddim_sampling(x_latent, conditioning, S, unconditional_guidance_scale=unconditional_guidance_scale,
unconditional_conditioning=unconditional_conditioning,
- mask = mask,init_latent=x_T,use_original_steps=False)
+ mask = mask,init_latent=x_T,use_original_steps=False,
+ callback=callback, img_callback=img_callback)
elif sampler == "euler":
self.make_schedule(ddim_num_steps=S, ddim_eta=eta, verbose=False)
samples = self.euler_sampling(self.alphas_cumprod,x_latent, S, conditioning, unconditional_conditioning=unconditional_conditioning,
- unconditional_guidance_scale=unconditional_guidance_scale)
+ unconditional_guidance_scale=unconditional_guidance_scale,
+ img_callback=img_callback)
elif sampler == "euler_a":
self.make_schedule(ddim_num_steps=S, ddim_eta=eta, verbose=False)
samples = self.euler_ancestral_sampling(self.alphas_cumprod,x_latent, S, conditioning, unconditional_conditioning=unconditional_conditioning,
- unconditional_guidance_scale=unconditional_guidance_scale)
+ unconditional_guidance_scale=unconditional_guidance_scale,
+ img_callback=img_callback)
elif sampler == "dpm2":
samples = self.dpm_2_sampling(self.alphas_cumprod,x_latent, S, conditioning, unconditional_conditioning=unconditional_conditioning,
- unconditional_guidance_scale=unconditional_guidance_scale)
+ unconditional_guidance_scale=unconditional_guidance_scale,
+ img_callback=img_callback)
elif sampler == "heun":
samples = self.heun_sampling(self.alphas_cumprod,x_latent, S, conditioning, unconditional_conditioning=unconditional_conditioning,
- unconditional_guidance_scale=unconditional_guidance_scale)
+ unconditional_guidance_scale=unconditional_guidance_scale,
+ img_callback=img_callback)
elif sampler == "dpm2_a":
samples = self.dpm_2_ancestral_sampling(self.alphas_cumprod,x_latent, S, conditioning, unconditional_conditioning=unconditional_conditioning,
- unconditional_guidance_scale=unconditional_guidance_scale)
+ unconditional_guidance_scale=unconditional_guidance_scale,
+ img_callback=img_callback)
elif sampler == "lms":
samples = self.lms_sampling(self.alphas_cumprod,x_latent, S, conditioning, unconditional_conditioning=unconditional_conditioning,
- unconditional_guidance_scale=unconditional_guidance_scale)
+ unconditional_guidance_scale=unconditional_guidance_scale,
+ img_callback=img_callback)
+
+ yield from samples
+
if(self.turbo):
self.model1.to("cpu")
self.model2.to("cpu")
@ -76,7 +17,7 @@ index b967b55..35ef520 100644
@torch.no_grad()
def plms_sampling(self, cond,b, img,
ddim_use_original_steps=False,
@@ -599,10 +608,10 @@ class UNet(DDPM):
@@ -608,10 +608,10 @@ class UNet(DDPM):
old_eps.append(e_t)
if len(old_eps) >= 4:
old_eps.pop(0)
@ -90,23 +31,15 @@ index b967b55..35ef520 100644
@torch.no_grad()
def p_sample_plms(self, x, c, t, index, repeat_noise=False, use_original_steps=False, quantize_denoised=False,
@@ -706,7 +715,8 @@ class UNet(DDPM):
@torch.no_grad()
def ddim_sampling(self, x_latent, cond, t_start, unconditional_guidance_scale=1.0, unconditional_conditioning=None,
- mask = None,init_latent=None,use_original_steps=False):
+ mask = None,init_latent=None,use_original_steps=False,
+ callback=None, img_callback=None):
timesteps = self.ddim_timesteps
timesteps = timesteps[:t_start]
@@ -730,10 +740,13 @@ class UNet(DDPM):
@@ -740,13 +740,13 @@ class UNet(DDPM):
unconditional_guidance_scale=unconditional_guidance_scale,
unconditional_conditioning=unconditional_conditioning)
- if callback: callback(i)
- if img_callback: img_callback(x_dec, i)
+ if callback: yield from callback(i)
+ if img_callback: yield from img_callback(x_dec, i)
+
if mask is not None:
- return x0 * mask + (1. - mask) * x_dec
+ x_dec = x0 * mask + (1. - mask) * x_dec
@ -116,217 +49,114 @@ index b967b55..35ef520 100644
@torch.no_grad()
@@ -779,13 +792,16 @@ class UNet(DDPM):
@@ -820,12 +820,12 @@ class UNet(DDPM):
@torch.no_grad()
- def euler_sampling(self, ac, x, S, cond, unconditional_conditioning = None, unconditional_guidance_scale = 1,extra_args=None,callback=None, disable=None, s_churn=0., s_tmin=0., s_tmax=float('inf'), s_noise=1.):
+ def euler_sampling(self, ac, x, S, cond, unconditional_conditioning = None, unconditional_guidance_scale = 1,extra_args=None,callback=None, disable=None, s_churn=0., s_tmin=0., s_tmax=float('inf'), s_noise=1.,
+ img_callback=None):
"""Implements Algorithm 2 (Euler steps) from Karras et al. (2022)."""
extra_args = {} if extra_args is None else extra_args
cvd = CompVisDenoiser(ac)
sigmas = cvd.get_sigmas(S)
x = x*sigmas[0]
+ print(f"Running Euler Sampling with {len(sigmas) - 1} timesteps")
+
s_in = x.new_ones([x.shape[0]]).half()
for i in trange(len(sigmas) - 1, disable=disable):
gamma = min(s_churn / (len(sigmas) - 1), 2 ** 0.5 - 1) if s_tmin <= sigmas[i] <= s_tmax else 0.
@@ -807,13 +823,18 @@ class UNet(DDPM):
d = to_d(x, sigma_hat, denoised)
if callback is not None:
callback({'x': x, 'i': i, 'sigma': sigmas[i], 'sigma_hat': sigma_hat, 'denoised': denoised})
+
- if callback: callback(i)
- if img_callback: img_callback(x, i)
+ if callback: yield from callback(i)
+ if img_callback: yield from img_callback(x, i)
+
dt = sigmas[i + 1] - sigma_hat
# Euler method
x = x + d * dt
- return x
+
+ yield from img_callback(x, len(sigmas)-1)
@torch.no_grad()
- def euler_ancestral_sampling(self,ac,x, S, cond, unconditional_conditioning = None, unconditional_guidance_scale = 1,extra_args=None, callback=None, disable=None):
+ def euler_ancestral_sampling(self,ac,x, S, cond, unconditional_conditioning = None, unconditional_guidance_scale = 1,extra_args=None, callback=None, disable=None,
+ img_callback=None):
"""Ancestral sampling with Euler method steps."""
extra_args = {} if extra_args is None else extra_args
def euler_ancestral_sampling(self,ac,x, S, cond, unconditional_conditioning = None, unconditional_guidance_scale = 1,extra_args=None, callback=None, disable=None, img_callback=None):
@@ -852,14 +852,14 @@ class UNet(DDPM):
denoised = e_t_uncond + unconditional_guidance_scale * (e_t - e_t_uncond)
@@ -822,6 +843,8 @@ class UNet(DDPM):
sigmas = cvd.get_sigmas(S)
x = x*sigmas[0]
+ print(f"Running Euler Ancestral Sampling with {len(sigmas) - 1} timesteps")
+
s_in = x.new_ones([x.shape[0]]).half()
for i in trange(len(sigmas) - 1, disable=disable):
@@ -837,17 +860,22 @@ class UNet(DDPM):
sigma_down, sigma_up = get_ancestral_step(sigmas[i], sigmas[i + 1])
if callback is not None:
callback({'x': x, 'i': i, 'sigma': sigmas[i], 'sigma_hat': sigmas[i], 'denoised': denoised})
+
- if callback: callback(i)
- if img_callback: img_callback(x, i)
+ if callback: yield from callback(i)
+ if img_callback: yield from img_callback(x, i)
+
d = to_d(x, sigmas[i], denoised)
# Euler method
dt = sigma_down - sigmas[i]
x = x + d * dt
x = x + torch.randn_like(x) * sigma_up
- return x
+
+ yield from img_callback(x, len(sigmas)-1)
@torch.no_grad()
- def heun_sampling(self, ac, x, S, cond, unconditional_conditioning = None, unconditional_guidance_scale = 1, extra_args=None, callback=None, disable=None, s_churn=0., s_tmin=0., s_tmax=float('inf'), s_noise=1.):
+ def heun_sampling(self, ac, x, S, cond, unconditional_conditioning = None, unconditional_guidance_scale = 1, extra_args=None, callback=None, disable=None, s_churn=0., s_tmin=0., s_tmax=float('inf'), s_noise=1.,
+ img_callback=None):
"""Implements Algorithm 2 (Heun steps) from Karras et al. (2022)."""
extra_args = {} if extra_args is None else extra_args
@@ -892,8 +892,8 @@ class UNet(DDPM):
denoised = e_t_uncond + unconditional_guidance_scale * (e_t - e_t_uncond)
@@ -855,6 +883,8 @@ class UNet(DDPM):
sigmas = cvd.get_sigmas(S)
x = x*sigmas[0]
+ print(f"Running Heun Sampling with {len(sigmas) - 1} timesteps")
+
s_in = x.new_ones([x.shape[0]]).half()
for i in trange(len(sigmas) - 1, disable=disable):
@@ -876,6 +906,9 @@ class UNet(DDPM):
d = to_d(x, sigma_hat, denoised)
if callback is not None:
callback({'x': x, 'i': i, 'sigma': sigmas[i], 'sigma_hat': sigma_hat, 'denoised': denoised})
+
- if callback: callback(i)
- if img_callback: img_callback(x, i)
+ if callback: yield from callback(i)
+ if img_callback: yield from img_callback(x, i)
+
dt = sigmas[i + 1] - sigma_hat
if sigmas[i + 1] == 0:
# Euler method
@@ -895,11 +928,13 @@ class UNet(DDPM):
@@ -913,7 +913,7 @@ class UNet(DDPM):
d_2 = to_d(x_2, sigmas[i + 1], denoised_2)
d_prime = (d + d_2) / 2
x = x + d_prime * dt
- return x
+
+ yield from img_callback(x, len(sigmas)-1)
@torch.no_grad()
- def dpm_2_sampling(self,ac,x, S, cond, unconditional_conditioning = None, unconditional_guidance_scale = 1,extra_args=None, callback=None, disable=None, s_churn=0., s_tmin=0., s_tmax=float('inf'), s_noise=1.):
+ def dpm_2_sampling(self,ac,x, S, cond, unconditional_conditioning = None, unconditional_guidance_scale = 1,extra_args=None, callback=None, disable=None, s_churn=0., s_tmin=0., s_tmax=float('inf'), s_noise=1.,
+ img_callback=None):
"""A sampler inspired by DPM-Solver-2 and Algorithm 2 from Karras et al. (2022)."""
extra_args = {} if extra_args is None else extra_args
@@ -907,6 +942,8 @@ class UNet(DDPM):
sigmas = cvd.get_sigmas(S)
x = x*sigmas[0]
+ print(f"Running DPM2 Sampling with {len(sigmas) - 1} timesteps")
+
s_in = x.new_ones([x.shape[0]]).half()
for i in trange(len(sigmas) - 1, disable=disable):
gamma = min(s_churn / (len(sigmas) - 1), 2 ** 0.5 - 1) if s_tmin <= sigmas[i] <= s_tmax else 0.
@@ -924,7 +961,7 @@ class UNet(DDPM):
@@ -944,8 +944,8 @@ class UNet(DDPM):
e_t_uncond, e_t = (x_in + eps * c_out).chunk(2)
denoised = e_t_uncond + unconditional_guidance_scale * (e_t - e_t_uncond)
-
- if callback: callback(i)
- if img_callback: img_callback(x, i)
+ if callback: yield from callback(i)
+ if img_callback: yield from img_callback(x, i)
d = to_d(x, sigma_hat, denoised)
# Midpoint method, where the midpoint is chosen according to a rho=3 Karras schedule
@@ -945,11 +982,13 @@ class UNet(DDPM):
@@ -966,7 +966,7 @@ class UNet(DDPM):
d_2 = to_d(x_2, sigma_mid, denoised_2)
x = x + d_2 * dt_2
- return x
+
+ yield from img_callback(x, len(sigmas)-1)
@torch.no_grad()
- def dpm_2_ancestral_sampling(self,ac,x, S, cond, unconditional_conditioning = None, unconditional_guidance_scale = 1, extra_args=None, callback=None, disable=None):
+ def dpm_2_ancestral_sampling(self,ac,x, S, cond, unconditional_conditioning = None, unconditional_guidance_scale = 1, extra_args=None, callback=None, disable=None,
+ img_callback=None):
"""Ancestral sampling with DPM-Solver inspired second-order steps."""
extra_args = {} if extra_args is None else extra_args
@@ -994,8 +994,8 @@ class UNet(DDPM):
@@ -957,6 +996,8 @@ class UNet(DDPM):
sigmas = cvd.get_sigmas(S)
x = x*sigmas[0]
+ print(f"Running DPM2 Ancestral Sampling with {len(sigmas) - 1} timesteps")
+
s_in = x.new_ones([x.shape[0]]).half()
for i in trange(len(sigmas) - 1, disable=disable):
@@ -973,6 +1014,9 @@ class UNet(DDPM):
sigma_down, sigma_up = get_ancestral_step(sigmas[i], sigmas[i + 1])
if callback is not None:
callback({'x': x, 'i': i, 'sigma': sigmas[i], 'sigma_hat': sigmas[i], 'denoised': denoised})
+
- if callback: callback(i)
- if img_callback: img_callback(x, i)
+ if callback: yield from callback(i)
+ if img_callback: yield from img_callback(x, i)
+
d = to_d(x, sigmas[i], denoised)
# Midpoint method, where the midpoint is chosen according to a rho=3 Karras schedule
sigma_mid = ((sigmas[i] ** (1 / 3) + sigma_down ** (1 / 3)) / 2) ** 3
@@ -993,11 +1037,13 @@ class UNet(DDPM):
@@ -1016,7 +1016,7 @@ class UNet(DDPM):
d_2 = to_d(x_2, sigma_mid, denoised_2)
x = x + d_2 * dt_2
x = x + torch.randn_like(x) * sigma_up
- return x
+
+ yield from img_callback(x, len(sigmas)-1)
@torch.no_grad()
- def lms_sampling(self,ac,x, S, cond, unconditional_conditioning = None, unconditional_guidance_scale = 1, extra_args=None, callback=None, disable=None, order=4):
+ def lms_sampling(self,ac,x, S, cond, unconditional_conditioning = None, unconditional_guidance_scale = 1, extra_args=None, callback=None, disable=None, order=4,
+ img_callback=None):
extra_args = {} if extra_args is None else extra_args
s_in = x.new_ones([x.shape[0]])
@@ -1005,6 +1051,8 @@ class UNet(DDPM):
sigmas = cvd.get_sigmas(S)
x = x*sigmas[0]
+ print(f"Running LMS Sampling with {len(sigmas) - 1} timesteps")
+
ds = []
for i in trange(len(sigmas) - 1, disable=disable):
@@ -1017,6 +1065,7 @@ class UNet(DDPM):
@@ -1042,8 +1042,8 @@ class UNet(DDPM):
e_t_uncond, e_t = (x_in + eps * c_out).chunk(2)
denoised = e_t_uncond + unconditional_guidance_scale * (e_t - e_t_uncond)
- if callback: callback(i)
- if img_callback: img_callback(x, i)
+ if callback: yield from callback(i)
+ if img_callback: yield from img_callback(x, i)
d = to_d(x, sigmas[i], denoised)
ds.append(d)
@@ -1027,4 +1076,5 @@ class UNet(DDPM):
@@ -1054,4 +1054,4 @@ class UNet(DDPM):
cur_order = min(i + 1, order)
coeffs = [linear_multistep_coeff(cur_order, sigmas.cpu(), i, j) for j in range(cur_order)]
x = x + sum(coeff * d for coeff, d in zip(coeffs, reversed(ds)))
- return x
+
+ yield from img_callback(x, len(sigmas)-1)
diff --git a/optimizedSD/openaimodelSplit.py b/optimizedSD/openaimodelSplit.py
index abc3098..7a32ffe 100644
--- a/optimizedSD/openaimodelSplit.py
+++ b/optimizedSD/openaimodelSplit.py
@@ -13,7 +13,7 @@ from ldm.modules.diffusionmodules.util import (
normalization,
timestep_embedding,
)
-from splitAttention import SpatialTransformer
+from .splitAttention import SpatialTransformer
class AttentionPool2d(nn.Module):

View File

@ -0,0 +1,84 @@
diff --git a/ldm/models/diffusion/ddim.py b/ldm/models/diffusion/ddim.py
index 27ead0e..6215939 100644
--- a/ldm/models/diffusion/ddim.py
+++ b/ldm/models/diffusion/ddim.py
@@ -100,7 +100,7 @@ class DDIMSampler(object):
size = (batch_size, C, H, W)
print(f'Data shape for DDIM sampling is {size}, eta {eta}')
- samples, intermediates = self.ddim_sampling(conditioning, size,
+ samples = self.ddim_sampling(conditioning, size,
callback=callback,
img_callback=img_callback,
quantize_denoised=quantize_x0,
@@ -117,7 +117,8 @@ class DDIMSampler(object):
dynamic_threshold=dynamic_threshold,
ucg_schedule=ucg_schedule
)
- return samples, intermediates
+ # return samples, intermediates
+ yield from samples
@torch.no_grad()
def ddim_sampling(self, cond, shape,
@@ -168,14 +169,15 @@ class DDIMSampler(object):
unconditional_conditioning=unconditional_conditioning,
dynamic_threshold=dynamic_threshold)
img, pred_x0 = outs
- if callback: callback(i)
- if img_callback: img_callback(pred_x0, i)
+ if callback: yield from callback(i)
+ if img_callback: yield from img_callback(pred_x0, i)
if index % log_every_t == 0 or index == total_steps - 1:
intermediates['x_inter'].append(img)
intermediates['pred_x0'].append(pred_x0)
- return img, intermediates
+ # return img, intermediates
+ yield from img_callback(pred_x0, len(iterator)-1)
@torch.no_grad()
def p_sample_ddim(self, x, c, t, index, repeat_noise=False, use_original_steps=False, quantize_denoised=False,
diff --git a/ldm/models/diffusion/plms.py b/ldm/models/diffusion/plms.py
index 7002a36..0951f39 100644
--- a/ldm/models/diffusion/plms.py
+++ b/ldm/models/diffusion/plms.py
@@ -96,7 +96,7 @@ class PLMSSampler(object):
size = (batch_size, C, H, W)
print(f'Data shape for PLMS sampling is {size}')
- samples, intermediates = self.plms_sampling(conditioning, size,
+ samples = self.plms_sampling(conditioning, size,
callback=callback,
img_callback=img_callback,
quantize_denoised=quantize_x0,
@@ -112,7 +112,8 @@ class PLMSSampler(object):
unconditional_conditioning=unconditional_conditioning,
dynamic_threshold=dynamic_threshold,
)
- return samples, intermediates
+ #return samples, intermediates
+ yield from samples
@torch.no_grad()
def plms_sampling(self, cond, shape,
@@ -165,14 +166,15 @@ class PLMSSampler(object):
old_eps.append(e_t)
if len(old_eps) >= 4:
old_eps.pop(0)
- if callback: callback(i)
- if img_callback: img_callback(pred_x0, i)
+ if callback: yield from callback(i)
+ if img_callback: yield from img_callback(pred_x0, i)
if index % log_every_t == 0 or index == total_steps - 1:
intermediates['x_inter'].append(img)
intermediates['pred_x0'].append(pred_x0)
- return img, intermediates
+ # return img, intermediates
+ yield from img_callback(pred_x0, len(iterator)-1)
@torch.no_grad()
def p_sample_plms(self, x, c, t, index, repeat_noise=False, use_original_steps=False, quantize_denoised=False,

View File

@ -0,0 +1,168 @@
import os
import torch
import traceback
import re
COMPARABLE_GPU_PERCENTILE = 0.65 # if a GPU's free_mem is within this % of the GPU with the most free_mem, it will be picked
mem_free_threshold = 0
def get_device_delta(render_devices, active_devices):
'''
render_devices: 'cpu', or 'auto' or ['cuda:N'...]
active_devices: ['cpu', 'cuda:N'...]
'''
if render_devices in ('cpu', 'auto'):
render_devices = [render_devices]
elif render_devices is not None:
if isinstance(render_devices, str):
render_devices = [render_devices]
if isinstance(render_devices, list) and len(render_devices) > 0:
render_devices = list(filter(lambda x: x.startswith('cuda:'), render_devices))
if len(render_devices) == 0:
raise Exception('Invalid render_devices value in config.json. Valid: {"render_devices": ["cuda:0", "cuda:1"...]}, or {"render_devices": "cpu"} or {"render_devices": "auto"}')
render_devices = list(filter(lambda x: is_device_compatible(x), render_devices))
if len(render_devices) == 0:
raise Exception('Sorry, none of the render_devices configured in config.json are compatible with Stable Diffusion')
else:
raise Exception('Invalid render_devices value in config.json. Valid: {"render_devices": ["cuda:0", "cuda:1"...]}, or {"render_devices": "cpu"} or {"render_devices": "auto"}')
else:
render_devices = ['auto']
if 'auto' in render_devices:
render_devices = auto_pick_devices(active_devices)
if 'cpu' in render_devices:
print('WARNING: Could not find a compatible GPU. Using the CPU, but this will be very slow!')
active_devices = set(active_devices)
render_devices = set(render_devices)
devices_to_start = render_devices - active_devices
devices_to_stop = active_devices - render_devices
return devices_to_start, devices_to_stop
def auto_pick_devices(currently_active_devices):
global mem_free_threshold
if not torch.cuda.is_available(): return ['cpu']
device_count = torch.cuda.device_count()
if device_count == 1:
return ['cuda:0'] if is_device_compatible('cuda:0') else ['cpu']
print('Autoselecting GPU. Using most free memory.')
devices = []
for device in range(device_count):
device = f'cuda:{device}'
if not is_device_compatible(device):
continue
mem_free, mem_total = torch.cuda.mem_get_info(device)
mem_free /= float(10**9)
mem_total /= float(10**9)
device_name = torch.cuda.get_device_name(device)
print(f'{device} detected: {device_name} - Memory (free/total): {round(mem_free, 2)}Gb / {round(mem_total, 2)}Gb')
devices.append({'device': device, 'device_name': device_name, 'mem_free': mem_free})
devices.sort(key=lambda x:x['mem_free'], reverse=True)
max_mem_free = devices[0]['mem_free']
curr_mem_free_threshold = COMPARABLE_GPU_PERCENTILE * max_mem_free
mem_free_threshold = max(curr_mem_free_threshold, mem_free_threshold)
# Auto-pick algorithm:
# 1. Pick the top 75 percentile of the GPUs, sorted by free_mem.
# 2. Also include already-running devices (GPU-only), otherwise their free_mem will
# always be very low (since their VRAM contains the model).
# These already-running devices probably aren't terrible, since they were picked in the past.
# Worst case, the user can restart the program and that'll get rid of them.
devices = list(filter((lambda x: x['mem_free'] > mem_free_threshold or x['device'] in currently_active_devices), devices))
devices = list(map(lambda x: x['device'], devices))
return devices
def device_init(thread_data, device):
'''
This function assumes the 'device' has already been verified to be compatible.
`get_device_delta()` has already filtered out incompatible devices.
'''
validate_device_id(device, log_prefix='device_init')
if device == 'cpu':
thread_data.device = 'cpu'
thread_data.device_name = get_processor_name()
print('Render device CPU available as', thread_data.device_name)
return
thread_data.device_name = torch.cuda.get_device_name(device)
thread_data.device = device
# Force full precision on 1660 and 1650 NVIDIA cards to avoid creating green images
device_name = thread_data.device_name.lower()
thread_data.force_full_precision = (('nvidia' in device_name or 'geforce' in device_name) and (' 1660' in device_name or ' 1650' in device_name)) or ('Quadro T2000' in device_name)
if thread_data.force_full_precision:
print('forcing full precision on NVIDIA 16xx cards, to avoid green images. GPU detected: ', thread_data.device_name)
# Apply force_full_precision now before models are loaded.
thread_data.precision = 'full'
print(f'Setting {device} as active')
torch.cuda.device(device)
return
def validate_device_id(device, log_prefix=''):
def is_valid():
if not isinstance(device, str):
return False
if device == 'cpu':
return True
if not device.startswith('cuda:') or not device[5:].isnumeric():
return False
return True
if not is_valid():
raise EnvironmentError(f"{log_prefix}: device id should be 'cpu', or 'cuda:N' (where N is an integer index for the GPU). Got: {device}")
def is_device_compatible(device):
'''
Returns True/False, and prints any compatibility errors
'''
try:
validate_device_id(device, log_prefix='is_device_compatible')
except:
print(str(e))
return False
if device == 'cpu': return True
# Memory check
try:
_, mem_total = torch.cuda.mem_get_info(device)
mem_total /= float(10**9)
if mem_total < 3.0:
print(f'GPU {device} with less than 3 GB of VRAM is not compatible with Stable Diffusion')
return False
except RuntimeError as e:
print(str(e))
return False
return True
def get_processor_name():
try:
import platform, subprocess
if platform.system() == "Windows":
return platform.processor()
elif platform.system() == "Darwin":
os.environ['PATH'] = os.environ['PATH'] + os.pathsep + '/usr/sbin'
command = "sysctl -n machdep.cpu.brand_string"
return subprocess.check_output(command).strip()
elif platform.system() == "Linux":
command = "cat /proc/cpuinfo"
all_info = subprocess.check_output(command, shell=True).decode().strip()
for line in all_info.split("\n"):
if "model name" in line:
return re.sub(".*model name.*:", "", line, 1).strip()
except:
print(traceback.format_exc())
return "cpu"

View File

@ -1,13 +0,0 @@
diff --git a/environment.yaml b/environment.yaml
index 7f25da8..306750f 100644
--- a/environment.yaml
+++ b/environment.yaml
@@ -23,6 +23,8 @@ dependencies:
- torch-fidelity==0.3.0
- transformers==4.19.2
- torchmetrics==0.6.0
+ - pywavelets==1.3.0
+ - pandas==1.4.4
- kornia==0.6
- -e git+https://github.com/CompVis/taming-transformers.git@master#egg=taming-transformers
- -e git+https://github.com/openai/CLIP.git@main#egg=clip

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,525 @@
"""task_manager.py: manage tasks dispatching and render threads.
Notes:
render_threads should be the only hard reference held by the manager to the threads.
Use weak_thread_data to store all other data using weak keys.
This will allow for garbage collection after the thread dies.
"""
import json
import traceback
TASK_TTL = 15 * 60 # seconds, Discard last session's task timeout
import torch
import queue, threading, time, weakref
from typing import Any, Generator, Hashable, Optional, Union
from pydantic import BaseModel
from sd_internal import Request, Response, runtime, device_manager
THREAD_NAME_PREFIX = 'Runtime-Render/'
ERR_LOCK_FAILED = ' failed to acquire lock within timeout.'
LOCK_TIMEOUT = 15 # Maximum locking time in seconds before failing a task.
# It's better to get an exception than a deadlock... ALWAYS use timeout in critical paths.
DEVICE_START_TIMEOUT = 60 # seconds - Maximum time to wait for a render device to init.
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.render_device = None # Select the task affinity. (Not used to change active devices).
self.temp_images:list = [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 ##TODO Remove after UI and plugins transition.
render_device: str = None # Select the task affinity. (Not used to change active devices).
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"
use_vae_model: str = None
show_only_filtered_image: bool = False
output_format: str = "jpeg" # or "png"
stream_progress_updates: bool = False
stream_image_progress: bool = False
class FilterRequest(BaseModel):
session_id: str = "session"
model: str = None
name: str = ""
init_image: str = None # base64
width: int = 512
height: int = 512
save_to_disk_path: str = None
turbo: bool = True
render_device: str = None
use_full_precision: bool = False
output_format: str = "jpeg" # or "png"
# 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.Lock()
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=LOCK_TIMEOUT): raise Exception('TaskCache.clean' + ERR_LOCK_FAILED)
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=LOCK_TIMEOUT): raise Exception('TaskCache.clear' + ERR_LOCK_FAILED)
try: self._base.clear()
finally: self._lock.release()
def delete(self, key: Hashable) -> bool:
if not self._lock.acquire(blocking=True, timeout=LOCK_TIMEOUT): raise Exception('TaskCache.delete' + ERR_LOCK_FAILED)
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=LOCK_TIMEOUT): raise Exception('TaskCache.keep' + ERR_LOCK_FAILED)
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=LOCK_TIMEOUT): raise Exception('TaskCache.put' + ERR_LOCK_FAILED)
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=LOCK_TIMEOUT): raise Exception('TaskCache.tryGet' + ERR_LOCK_FAILED)
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.')
del self._base[key]
return None
return value
finally:
self._lock.release()
manager_lock = threading.RLock()
render_threads = []
current_state = ServerStates.Init
current_state_error:Exception = None
current_model_path = None
current_vae_path = None
tasks_queue = []
task_cache = TaskCache()
default_model_to_load = None
default_vae_to_load = None
weak_thread_data = weakref.WeakKeyDictionary()
def preload_model(ckpt_file_path=None, vae_file_path=None):
global current_state, current_state_error, current_model_path, current_vae_path
if ckpt_file_path == None:
ckpt_file_path = default_model_to_load
if vae_file_path == None:
vae_file_path = default_vae_to_load
if ckpt_file_path == current_model_path and vae_file_path == current_vae_path:
return
current_state = ServerStates.LoadingModel
try:
from . import runtime
runtime.thread_data.ckpt_file = ckpt_file_path
runtime.thread_data.vae_file = vae_file_path
runtime.load_model_ckpt()
current_model_path = ckpt_file_path
current_vae_path = vae_file_path
current_state_error = None
current_state = ServerStates.Online
except Exception as e:
current_model_path = None
current_vae_path = None
current_state_error = e
current_state = ServerStates.Unavailable
print(traceback.format_exc())
def thread_get_next_task():
from . import runtime
if not manager_lock.acquire(blocking=True, timeout=LOCK_TIMEOUT):
print('Render thread on device', runtime.thread_data.device, 'failed to acquire manager lock.')
return None
if len(tasks_queue) <= 0:
manager_lock.release()
return None
task = None
try: # Select a render task.
for queued_task in tasks_queue:
if queued_task.render_device and runtime.thread_data.device != queued_task.render_device:
# Is asking for a specific render device.
if is_alive(queued_task.render_device) > 0:
continue # requested device alive, skip current one.
else:
# Requested device is not active, return error to UI.
queued_task.error = Exception(queued_task.render_device + ' is not currently active.')
task = queued_task
break
if not queued_task.render_device and runtime.thread_data.device == 'cpu' and is_alive() > 1:
# not asking for any specific devices, cpu want to grab task but other render devices are alive.
continue # Skip Tasks, don't run on CPU unless there is nothing else or user asked for it.
task = queued_task
break
if task is not None:
del tasks_queue[tasks_queue.index(task)]
return task
finally:
manager_lock.release()
def thread_render(device):
global current_state, current_state_error, current_model_path, current_vae_path
from . import runtime
try:
runtime.thread_init(device)
except Exception as e:
print(traceback.format_exc())
weak_thread_data[threading.current_thread()] = {
'error': e
}
return
weak_thread_data[threading.current_thread()] = {
'device': runtime.thread_data.device,
'device_name': runtime.thread_data.device_name,
'alive': True
}
if runtime.thread_data.device != 'cpu' or is_alive() == 1:
preload_model()
current_state = ServerStates.Online
while True:
task_cache.clean()
if not weak_thread_data[threading.current_thread()]['alive']:
print(f'Shutting down thread for device {runtime.thread_data.device}')
runtime.unload_models()
runtime.unload_filters()
return
if isinstance(current_state_error, SystemExit):
current_state = ServerStates.Unavailable
return
task = thread_get_next_task()
if task is None:
time.sleep(0.05)
continue
if task.error is not None:
print(task.error)
task.response = {"status": 'failed', "detail": str(task.error)}
task.buffer_queue.put(json.dumps(task.response))
continue
if current_state_error:
task.error = current_state_error
task.response = {"status": 'failed', "detail": str(task.error)}
task.buffer_queue.put(json.dumps(task.response))
continue
print(f'Session {task.request.session_id} starting task {id(task)} on {runtime.thread_data.device_name}')
if not task.lock.acquire(blocking=False): raise Exception('Got locked task from queue.')
try:
if runtime.is_model_reload_necessary(task.request):
current_state = ServerStates.LoadingModel
runtime.reload_model()
current_model_path = task.request.use_stable_diffusion_model
current_vae_path = task.request.use_vae_model
def step_callback():
global current_state_error
if isinstance(current_state_error, SystemExit) or isinstance(current_state_error, StopAsyncIteration) or isinstance(task.error, StopAsyncIteration):
runtime.thread_data.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)}')
task_cache.keep(task.request.session_id, TASK_TTL)
current_state = ServerStates.Rendering
task.response = runtime.mk_img(task.request, task.buffer_queue, task.temp_images, step_callback)
except Exception as e:
task.error = e
print(traceback.format_exc())
continue
finally:
# Task completed
task.lock.release()
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 by {runtime.thread_data.device_name}.')
current_state = ServerStates.Online
def get_cached_task(session_id:str, update_ttl:bool=False):
# By calling keep before tryGet, wont discard if was expired.
if update_ttl and not task_cache.keep(session_id, TASK_TTL):
# Failed to keep task, already gone.
return None
return task_cache.tryGet(session_id)
def get_devices():
devices = {
'all': {},
'active': {},
}
def get_device_info(device):
if device == 'cpu':
return {'name': device_manager.get_processor_name()}
mem_free, mem_total = torch.cuda.mem_get_info(device)
mem_free /= float(10**9)
mem_total /= float(10**9)
return {
'name': torch.cuda.get_device_name(device),
'mem_free': mem_free,
'mem_total': mem_total,
}
# list the compatible devices
gpu_count = torch.cuda.device_count()
for device in range(gpu_count):
device = f'cuda:{device}'
if not device_manager.is_device_compatible(device):
continue
devices['all'].update({device: get_device_info(device)})
devices['all'].update({'cpu': get_device_info('cpu')})
# list the activated devices
if not manager_lock.acquire(blocking=True, timeout=LOCK_TIMEOUT): raise Exception('get_devices' + ERR_LOCK_FAILED)
try:
for rthread in render_threads:
if not rthread.is_alive():
continue
weak_data = weak_thread_data.get(rthread)
if not weak_data or not 'device' in weak_data or not 'device_name' in weak_data:
continue
device = weak_data['device']
devices['active'].update({device: get_device_info(device)})
finally:
manager_lock.release()
return devices
def is_alive(device=None):
if not manager_lock.acquire(blocking=True, timeout=LOCK_TIMEOUT): raise Exception('is_alive' + ERR_LOCK_FAILED)
nbr_alive = 0
try:
for rthread in render_threads:
if device is not None:
weak_data = weak_thread_data.get(rthread)
if weak_data is None or not 'device' in weak_data or weak_data['device'] is None:
continue
thread_device = weak_data['device']
if thread_device != device:
continue
if rthread.is_alive():
nbr_alive += 1
return nbr_alive
finally:
manager_lock.release()
def start_render_thread(device):
if not manager_lock.acquire(blocking=True, timeout=LOCK_TIMEOUT): raise Exception('start_render_thread' + ERR_LOCK_FAILED)
print('Start new Rendering Thread on device', device)
try:
rthread = threading.Thread(target=thread_render, kwargs={'device': device})
rthread.daemon = True
rthread.name = THREAD_NAME_PREFIX + device
rthread.start()
render_threads.append(rthread)
finally:
manager_lock.release()
timeout = DEVICE_START_TIMEOUT
while not rthread.is_alive() or not rthread in weak_thread_data or not 'device' in weak_thread_data[rthread]:
if rthread in weak_thread_data and 'error' in weak_thread_data[rthread]:
print(rthread, device, 'error:', weak_thread_data[rthread]['error'])
return False
if timeout <= 0:
return False
timeout -= 1
time.sleep(1)
return True
def stop_render_thread(device):
try:
device_manager.validate_device_id(device, log_prefix='stop_render_thread')
except:
print(traceback.format_exc())
return False
if not manager_lock.acquire(blocking=True, timeout=LOCK_TIMEOUT): raise Exception('stop_render_thread' + ERR_LOCK_FAILED)
print('Stopping Rendering Thread on device', device)
try:
thread_to_remove = None
for rthread in render_threads:
weak_data = weak_thread_data.get(rthread)
if weak_data is None or not 'device' in weak_data or weak_data['device'] is None:
continue
thread_device = weak_data['device']
if thread_device == device:
weak_data['alive'] = False
thread_to_remove = rthread
break
if thread_to_remove is not None:
render_threads.remove(rthread)
return True
finally:
manager_lock.release()
return False
def update_render_threads(render_devices, active_devices):
devices_to_start, devices_to_stop = device_manager.get_device_delta(render_devices, active_devices)
print('devices_to_start', devices_to_start)
print('devices_to_stop', devices_to_stop)
for device in devices_to_stop:
if is_alive(device) <= 0:
print(device, 'is not alive')
continue
if not stop_render_thread(device):
print(device, 'could not stop render thread')
for device in devices_to_start:
if is_alive(device) >= 1:
print(device, 'already registered.')
continue
if not start_render_thread(device):
print(device, 'failed to start.')
if is_alive() <= 0: # No running devices, probably invalid user config.
raise EnvironmentError('ERROR: No active render devices! Please verify the "render_devices" value in config.json')
print('active devices', get_devices()['active'])
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 is_alive() <= 0: # 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_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.use_vae_model = req.use_vae_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):
# Use twice the normal timeout for adding user requests.
# Tries to force task_cache.put to fail before tasks_queue.put would.
if manager_lock.acquire(blocking=True, timeout=LOCK_TIMEOUT * 2):
try:
tasks_queue.append(new_task)
return new_task
finally:
manager_lock.release()
raise RuntimeError('Failed to add task to cache.')

View File

@ -1,225 +1,457 @@
"""server.py: FastAPI SD-UI Web Host.
Notes:
async endpoints always run on the main thread. Without they run on the thread pool.
"""
import json
import traceback
import sys
import os
import socket
import picklescan.scanner
import rich
SCRIPT_DIR = os.getcwd()
print('started in ', SCRIPT_DIR)
SD_DIR = os.getcwd()
print('started in ', SD_DIR)
SD_UI_DIR = os.getenv('SD_UI_PATH', None)
sys.path.append(os.path.dirname(SD_UI_DIR))
CONFIG_DIR = os.path.join(SD_UI_DIR, '..', 'scripts')
CONFIG_DIR = os.path.abspath(os.path.join(SD_UI_DIR, '..', 'scripts'))
MODELS_DIR = os.path.abspath(os.path.join(SD_DIR, '..', 'models'))
USER_UI_PLUGINS_DIR = os.path.abspath(os.path.join(SD_DIR, '..', 'plugins', 'ui'))
CORE_UI_PLUGINS_DIR = os.path.abspath(os.path.join(SD_UI_DIR, 'plugins', 'ui'))
UI_PLUGINS_SOURCES = ((CORE_UI_PLUGINS_DIR, 'core'), (USER_UI_PLUGINS_DIR, 'user'))
STABLE_DIFFUSION_MODEL_EXTENSIONS = ['.ckpt']
VAE_MODEL_EXTENSIONS = ['.vae.pt', '.ckpt']
OUTPUT_DIRNAME = "Stable Diffusion UI" # in the user's home folder
TASK_TTL = 15 * 60 # Discard last session's task timeout
APP_CONFIG_DEFAULTS = {
# auto: selects the cuda device with the most free memory, cuda: use the currently active cuda device.
'render_devices': 'auto', # valid entries: 'auto', 'cpu' or 'cuda:N' (where N is a GPU index)
'update_branch': 'main',
'ui': {
'open_browser_on_start': True,
},
}
APP_CONFIG_DEFAULT_MODELS = [
# needed to support the legacy installations
'custom-model', # Check if user has a custom model, use it first.
'sd-v1-4', # Default fallback.
]
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, List, 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(USER_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"
show_only_filtered_image: bool = False
class NoCacheStaticFiles(StaticFiles):
def is_not_modified(self, response_headers, request_headers) -> bool:
if 'content-type' in response_headers and ('javascript' in response_headers['content-type'] or 'css' in response_headers['content-type']):
response_headers.update(NOCACHE_HEADERS)
return False
stream_progress_updates: bool = False
stream_image_progress: bool = False
return super().is_not_modified(response_headers, request_headers)
app.mount('/media', NoCacheStaticFiles(directory=os.path.join(SD_UI_DIR, 'media')), name="media")
for plugins_dir, dir_prefix in UI_PLUGINS_SOURCES:
app.mount(f'/plugins/{dir_prefix}', NoCacheStaticFiles(directory=plugins_dir), name=f"plugins-{dir_prefix}")
def getConfig(default_val=APP_CONFIG_DEFAULTS):
try:
config_json_path = os.path.join(CONFIG_DIR, 'config.json')
if not os.path.exists(config_json_path):
return default_val
with open(config_json_path, 'r', encoding='utf-8') as f:
config = json.load(f)
if 'net' not in config:
config['net'] = {}
if os.getenv('SD_UI_BIND_PORT') is not None:
config['net']['listen_port'] = int(os.getenv('SD_UI_BIND_PORT'))
if os.getenv('SD_UI_BIND_IP') is not None:
config['net']['listen_to_network'] = ( os.getenv('SD_UI_BIND_IP') == '0.0.0.0' )
return config
except Exception as e:
print(str(e))
print(traceback.format_exc())
return default_val
def setConfig(config):
print( json.dumps(config) )
try: # config.json
config_json_path = os.path.join(CONFIG_DIR, 'config.json')
with open(config_json_path, 'w', encoding='utf-8') as f:
json.dump(config, f)
except:
print(traceback.format_exc())
try: # config.bat
config_bat_path = os.path.join(CONFIG_DIR, 'config.bat')
config_bat = []
if 'update_branch' in config:
config_bat.append(f"@set update_branch={config['update_branch']}")
config_bat.append(f"@set SD_UI_BIND_PORT={config['net']['listen_port']}")
bind_ip = '0.0.0.0' if config['net']['listen_to_network'] else '127.0.0.1'
config_bat.append(f"@set SD_UI_BIND_IP={bind_ip}")
config_bat.append(f"@set test_sd2={'Y' if config.get('test_sd2', False) else 'N'}")
if len(config_bat) > 0:
with open(config_bat_path, 'w', encoding='utf-8') as f:
f.write('\r\n'.join(config_bat))
except:
print(traceback.format_exc())
try: # config.sh
config_sh_path = os.path.join(CONFIG_DIR, 'config.sh')
config_sh = ['#!/bin/bash']
if 'update_branch' in config:
config_sh.append(f"export update_branch={config['update_branch']}")
config_sh.append(f"export SD_UI_BIND_PORT={config['net']['listen_port']}")
bind_ip = '0.0.0.0' if config['net']['listen_to_network'] else '127.0.0.1'
config_sh.append(f"export SD_UI_BIND_IP={bind_ip}")
config_sh.append(f"export test_sd2=\"{'Y' if config.get('test_sd2', False) else 'N'}\"")
if len(config_sh) > 1:
with open(config_sh_path, 'w', encoding='utf-8') as f:
f.write('\n'.join(config_sh))
except:
print(traceback.format_exc())
def resolve_model_to_use(model_name:str, model_type:str, model_dir:str, model_extensions:list, default_models=[]):
config = getConfig()
model_dirs = [os.path.join(MODELS_DIR, model_dir), SD_DIR]
if not model_name: # When None try user configured model.
# config = getConfig()
if 'model' in config and model_type in config['model']:
model_name = config['model'][model_type]
if model_name:
is_sd2 = config.get('test_sd2', False)
if model_name.startswith('sd2_') and not is_sd2: # temp hack, until SD2 is unified with 1.4
print('ERROR: Cannot use SD 2.0 models with SD 1.0 code. Using the sd-v1-4 model instead!')
model_name = 'sd-v1-4'
# Check models directory
models_dir_path = os.path.join(MODELS_DIR, model_dir, model_name)
for model_extension in model_extensions:
if os.path.exists(models_dir_path + model_extension):
return models_dir_path
if os.path.exists(model_name + model_extension):
# Direct Path to file
model_name = os.path.abspath(model_name)
return model_name
# Default locations
if model_name in default_models:
default_model_path = os.path.join(SD_DIR, model_name)
for model_extension in model_extensions:
if os.path.exists(default_model_path + model_extension):
return default_model_path
# Can't find requested model, check the default paths.
for default_model in default_models:
for model_dir in model_dirs:
default_model_path = os.path.join(model_dir, default_model)
for model_extension in model_extensions:
if os.path.exists(default_model_path + model_extension):
if model_name is not None:
print(f'Could not find the configured custom model {model_name}{model_extension}. Using the default one: {default_model_path}{model_extension}')
return default_model_path
raise Exception('No valid models found.')
def resolve_ckpt_to_use(model_name:str=None):
return resolve_model_to_use(model_name, model_type='stable-diffusion', model_dir='stable-diffusion', model_extensions=STABLE_DIFFUSION_MODEL_EXTENSIONS, default_models=APP_CONFIG_DEFAULT_MODELS)
def resolve_vae_to_use(model_name:str=None):
try:
return resolve_model_to_use(model_name, model_type='vae', model_dir='vae', model_extensions=VAE_MODEL_EXTENSIONS, default_models=[])
except:
return None
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
custom_weight_path = os.path.join(SCRIPT_DIR, 'custom-model.ckpt')
ckpt_to_use = "sd-v1-4" if not os.path.exists(custom_weight_path) else "custom-model"
runtime.load_model_ckpt(ckpt_to_use=ckpt_to_use)
model_loaded = True
model_is_loading = False
return {'OK'}
except Exception as e:
print(traceback.format_exc())
return HTTPException(status_code=500, detail=str(e))
@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.stream_progress_updates = True # the underlying implementation only supports streaming
r.stream_image_progress = req.stream_image_progress
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)
except Exception as e:
print(traceback.format_exc())
return HTTPException(status_code=500, detail=str(e))
@app.get('/image/stop')
def stop():
try:
if model_is_loading:
return {'ERROR'}
from sd_internal import runtime
runtime.stop_processing = True
return {'OK'}
except Exception as e:
print(traceback.format_exc())
return HTTPException(status_code=500, detail=str(e))
@app.get('/image/tmp/{session_id}/{img_id}')
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')
update_branch: str = None
render_devices: Union[List[str], List[int], str, int] = None
model_vae: str = None
ui_open_browser_on_start: bool = None
listen_to_network: bool = None
listen_port: int = None
test_sd2: bool = None
@app.post('/app_config')
async def setAppConfig(req : SetAppConfigRequest):
config = getConfig()
if req.update_branch is not None:
config['update_branch'] = req.update_branch
if req.render_devices is not None:
update_render_devices_in_config(config, req.render_devices)
if req.ui_open_browser_on_start is not None:
if 'ui' not in config:
config['ui'] = {}
config['ui']['open_browser_on_start'] = req.ui_open_browser_on_start
if req.listen_to_network is not None:
if 'net' not in config:
config['net'] = {}
config['net']['listen_to_network'] = bool(req.listen_to_network)
if req.listen_port is not None:
if 'net' not in config:
config['net'] = {}
config['net']['listen_port'] = int(req.listen_port)
if req.test_sd2 is not None:
config['test_sd2'] = req.test_sd2
try:
config = {
'update_branch': req.update_branch
setConfig(config)
if req.render_devices:
update_render_threads()
return JSONResponse({'status': 'OK'}, headers=NOCACHE_HEADERS)
except Exception as e:
print(traceback.format_exc())
raise HTTPException(status_code=500, detail=str(e))
def is_malicious_model(file_path):
try:
scan_result = picklescan.scanner.scan_file_path(file_path)
if scan_result.issues_count > 0 or scan_result.infected_files > 0:
rich.print(":warning: [bold red]Scan %s: %d scanned, %d issue, %d infected.[/bold red]" % (file_path, scan_result.scanned_files, scan_result.issues_count, scan_result.infected_files))
return True
else:
rich.print("Scan %s: [green]%d scanned, %d issue, %d infected.[/green]" % (file_path, scan_result.scanned_files, scan_result.issues_count, scan_result.infected_files))
return False
except Exception as e:
print('error while scanning', file_path, 'error:', e)
return False
known_models = {}
def getModels():
models = {
'active': {
'stable-diffusion': 'sd-v1-4',
'vae': '',
},
'options': {
'stable-diffusion': ['sd-v1-4'],
'vae': [],
},
}
def listModels(models_dirname, model_type, model_extensions):
models_dir = os.path.join(MODELS_DIR, models_dirname)
if not os.path.exists(models_dir):
os.makedirs(models_dir)
for file in os.listdir(models_dir):
for model_extension in model_extensions:
if not file.endswith(model_extension):
continue
model_path = os.path.join(models_dir, file)
mtime = os.path.getmtime(model_path)
mod_time = known_models[model_path] if model_path in known_models else -1
if mod_time != mtime:
if is_malicious_model(model_path):
models['scan-error'] = file
return
known_models[model_path] = mtime
model_name = file[:-len(model_extension)]
models['options'][model_type].append(model_name)
models['options'][model_type] = [*set(models['options'][model_type])] # remove duplicates
models['options'][model_type].sort()
# custom models
listModels(models_dirname='stable-diffusion', model_type='stable-diffusion', model_extensions=STABLE_DIFFUSION_MODEL_EXTENSIONS)
listModels(models_dirname='vae', model_type='vae', model_extensions=VAE_MODEL_EXTENSIONS)
# legacy
custom_weight_path = os.path.join(SD_DIR, 'custom-model.ckpt')
if os.path.exists(custom_weight_path):
models['options']['stable-diffusion'].append('custom-model')
return models
def getUIPlugins():
plugins = []
for plugins_dir, dir_prefix in UI_PLUGINS_SOURCES:
for file in os.listdir(plugins_dir):
if file.endswith('.plugin.js'):
plugins.append(f'/plugins/{dir_prefix}/{file}')
return plugins
def getIPConfig():
ips = socket.gethostbyname_ex(socket.gethostname())
ips[2].append(ips[0])
return ips[2]
@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:
config = APP_CONFIG_DEFAULTS
return JSONResponse(config, headers=NOCACHE_HEADERS)
elif key == 'system_info':
config = getConfig()
system_info = {
'devices': task_manager.get_devices(),
'hosts': getIPConfig(),
}
system_info['devices']['config'] = config.get('render_devices', "auto")
return JSONResponse(system_info, 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
config_json_str = json.dumps(config)
config_bat_str = f'@set update_branch={req.update_branch}'
config_sh_str = f'export update_branch={req.update_branch}'
@app.get('/ping') # Get server and optionally session status.
def ping(session_id:str=None):
if task_manager.is_alive() <= 0: # Check that render threads are alive.
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.get_cached_task(session_id, update_ttl=True)
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'
response['devices'] = task_manager.get_devices()
return JSONResponse(response, headers=NOCACHE_HEADERS)
config_json_path = os.path.join(CONFIG_DIR, 'config.json')
config_bat_path = os.path.join(CONFIG_DIR, 'config.bat')
config_sh_path = os.path.join(CONFIG_DIR, 'config.sh')
def save_model_to_config(ckpt_model_name, vae_model_name):
config = getConfig()
if 'model' not in config:
config['model'] = {}
with open(config_json_path, 'w') as f:
f.write(config_json_str)
config['model']['stable-diffusion'] = ckpt_model_name
config['model']['vae'] = vae_model_name
with open(config_bat_path, 'w') as f:
f.write(config_bat_str)
if vae_model_name is None or vae_model_name == "":
del config['model']['vae']
with open(config_sh_path, 'w') as f:
f.write(config_sh_str)
setConfig(config)
return {'OK'}
except Exception as e:
print(traceback.format_exc())
return HTTPException(status_code=500, detail=str(e))
def update_render_devices_in_config(config, render_devices):
if render_devices not in ('cpu', 'auto') and not render_devices.startswith('cuda:'):
raise HTTPException(status_code=400, detail=f'Invalid render device requested: {render_devices}')
@app.get('/app_config')
def getAppConfig():
if render_devices.startswith('cuda:'):
render_devices = render_devices.split(',')
config['render_devices'] = render_devices
@app.post('/render')
def render(req : task_manager.ImageRequest):
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:
config_json_str = f.read()
config = json.loads(config_json_str)
return config
save_model_to_config(req.use_stable_diffusion_model, req.use_vae_model)
req.use_stable_diffusion_model = resolve_ckpt_to_use(req.use_stable_diffusion_model)
req.use_vae_model = resolve_vae_to_use(req.use_vae_model)
new_task = task_manager.render(req)
response = {
'status': str(task_manager.current_state),
'queue': len(task_manager.tasks_queue),
'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('/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)
@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.get_cached_task(session_id, update_ttl=True)
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('/output_dir')
def read_home_dir():
return {outpath}
@app.get('/image/stop')
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'}
task = task_manager.get_cached_task(session_id, update_ttl=False)
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:int}')
def get_image(session_id, img_id):
task = task_manager.get_cached_task(session_id, update_ttl=True)
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]
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.get('/')
def read_root():
return FileResponse(os.path.join(SD_UI_DIR, 'index.html'), headers=NOCACHE_HEADERS)
@app.on_event("shutdown")
def shutdown_event(): # Signal render thread to close on shutdown
task_manager.current_state_error = SystemExit('Application shutting down.')
# don't log certain requests
class LogSuppressFilter(logging.Filter):
@ -228,10 +460,33 @@ 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())
# Check models and prepare cache for UI open
getModels()
# Start the task_manager
task_manager.default_model_to_load = resolve_ckpt_to_use()
task_manager.default_vae_to_load = resolve_vae_to_use()
def update_render_threads():
config = getConfig()
render_devices = config.get('render_devices', 'auto')
active_devices = task_manager.get_devices()['active'].keys()
print('requesting for render_devices', render_devices)
task_manager.update_render_threads(render_devices, active_devices)
update_render_threads()
# start the browser ui
import webbrowser; webbrowser.open('http://localhost:9000')
def open_browser():
config = getConfig()
ui = config.get('ui', {})
net = config.get('net', {'listen_port':9000})
port = net.get('listen_port', 9000)
if ui.get('open_browser_on_start', True):
import webbrowser; webbrowser.open(f"http://localhost:{port}")
open_browser()