trappy commited on
Commit
b050681
·
1 Parent(s): 8efbb9a

Upload 41 files

Browse files
Files changed (42) hide show
  1. .gitattributes +2 -0
  2. SD-catppuccin-main/LICENSE +21 -0
  3. SD-catppuccin-main/README.md +97 -0
  4. SD-catppuccin-main/assets/.gitkeep +0 -0
  5. SD-catppuccin-main/assets/frappe.webp +0 -0
  6. SD-catppuccin-main/assets/latte.webp +0 -0
  7. SD-catppuccin-main/assets/macchiato.webp +0 -0
  8. SD-catppuccin-main/assets/mocha.webp +0 -0
  9. SD-catppuccin-main/assets/res.webp +0 -0
  10. SD-catppuccin-main/flavors/frappe.css +565 -0
  11. SD-catppuccin-main/flavors/latte.css +565 -0
  12. SD-catppuccin-main/flavors/macchiato.css +565 -0
  13. SD-catppuccin-main/flavors/mocha.css +567 -0
  14. SD-catppuccin-main/scripts/main.py +50 -0
  15. SD-catppuccin-main/style.css +565 -0
  16. SD-huggingface-main/.github/FUNDING.yml +13 -0
  17. SD-huggingface-main/LICENSE +24 -0
  18. SD-huggingface-main/README.md +12 -0
  19. SD-huggingface-main/install.py +4 -0
  20. SD-huggingface-main/scripts/huggingface.py +121 -0
  21. SD-images-browser-main/.DS_Store +0 -0
  22. SD-images-browser-main/.gitignore +1 -0
  23. SD-images-browser-main/README.md +32 -0
  24. SD-images-browser-main/install.py +4 -0
  25. SD-images-browser-main/javascript/images_history.js +234 -0
  26. SD-images-browser-main/scripts/images_history.py +776 -0
  27. SD-images-browser-main/scripts/wib/wib_db.py +340 -0
  28. SD-rembg-master/.gitignore +1 -0
  29. SD-rembg-master/LICENSE +21 -0
  30. SD-rembg-master/README.md +15 -0
  31. SD-rembg-master/install.py +8 -0
  32. SD-rembg-master/preview.png +3 -0
  33. SD-rembg-master/scripts/postprocessing_rembg.py +61 -0
  34. SD-two-shot-main/.gitignore +129 -0
  35. SD-two-shot-main/LICENSE +21 -0
  36. SD-two-shot-main/README.md +76 -0
  37. SD-two-shot-main/gradio-3.16.2-py3-none-any.whl +3 -0
  38. SD-two-shot-main/screenshots/20230213.png +0 -0
  39. SD-two-shot-main/screenshots/20230303.png +0 -0
  40. SD-two-shot-main/scripts/sketch_helper.py +99 -0
  41. SD-two-shot-main/scripts/two_shot.py +594 -0
  42. SD-two-shot-main/style.css +36 -0
.gitattributes CHANGED
@@ -34,3 +34,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
34
  *tfevents* filter=lfs diff=lfs merge=lfs -text
35
  extensions/SD-rembg-master/preview.png filter=lfs diff=lfs merge=lfs -text
36
  extensions/SD-two-shot-main/gradio-3.16.2-py3-none-any.whl filter=lfs diff=lfs merge=lfs -text
 
 
 
34
  *tfevents* filter=lfs diff=lfs merge=lfs -text
35
  extensions/SD-rembg-master/preview.png filter=lfs diff=lfs merge=lfs -text
36
  extensions/SD-two-shot-main/gradio-3.16.2-py3-none-any.whl filter=lfs diff=lfs merge=lfs -text
37
+ SD-rembg-master/preview.png filter=lfs diff=lfs merge=lfs -text
38
+ SD-two-shot-main/gradio-3.16.2-py3-none-any.whl filter=lfs diff=lfs merge=lfs -text
SD-catppuccin-main/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Catppuccin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
SD-catppuccin-main/README.md ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <h3 align="center">
2
+ <img src="https://raw.githubusercontent.com/catppuccin/catppuccin/main/assets/logos/exports/1544x1544_circle.png" width="100" alt="Logo"/><br/>
3
+ <img src="https://raw.githubusercontent.com/catppuccin/catppuccin/main/assets/misc/transparent.png" height="30" width="0px"/>
4
+ Catppuccin for <a href="https://github.com/AUTOMATIC1111/stable-diffusion-webui">Stable Diffusion Web UI</a>
5
+ <img src="https://raw.githubusercontent.com/catppuccin/catppuccin/main/assets/misc/transparent.png" height="30" width="0px"/>
6
+ </h3>
7
+
8
+ <p align="center">
9
+ <a href="https://github.com/catppuccin/Stable-Diffusion-Web-Ui/stargazers"><img src="https://img.shields.io/github/stars/catppuccin/Stable-Diffusion-Web-Ui?colorA=363a4f&colorB=b7bdf8&style=for-the-badge"></a>
10
+ <a href="https://github.com/catppuccin/Stable-Diffusion-Web-Ui/issues"><img src="https://img.shields.io/github/issues/catppuccin/Stable-Diffusion-Web-Ui?colorA=363a4f&colorB=f5a97f&style=for-the-badge"></a>
11
+ <a href="https://github.com/catppuccin/Stable-Diffusion-Web-Ui/contributors"><img src="https://img.shields.io/github/contributors/catppuccin/Stable-Diffusion-Web-Ui?colorA=363a4f&colorB=a6da95&style=for-the-badge"></a>
12
+ </p>
13
+
14
+ <p align="center">
15
+ <img src="/assets/res.webp"/>
16
+ </p>
17
+
18
+ ## Previews
19
+
20
+ <details>
21
+ <summary>🌻 Latte</summary>
22
+ <img src="/assets/latte.webp"/>
23
+ </details>
24
+ <details>
25
+ <summary>🪴 Frappé</summary>
26
+ <img src="/assets/frappe.webp"/>
27
+ </details>
28
+ <details>
29
+ <summary>🌺 Macchiato</summary>
30
+ <img src="/assets/macchiato.webp"/>
31
+ </details>
32
+ <details>
33
+ <summary>🌿 Mocha</summary>
34
+ <img src="/assets/mocha.webp"/>
35
+ </details>
36
+
37
+ ## Usage
38
+ ### Extension (Recommended)
39
+ 1. Open WebUI
40
+ 2. Click on the "Extensions" tab
41
+ 3. Click on the "Install from URL" subsection
42
+ 4. Paste `https://github.com/catppuccin/stable-diffusion-webui` into the URL spot, set the local directory name to `Catppuccin Theme`, and install
43
+ 5. Go to "Installed" subsection and click "Apply and restart UI"
44
+ 6. Configure the theme from the "Settings" tab under "Catppuccin Theme", afterwards you must "Apply Settings" and "Reload UI"
45
+
46
+ ### Extension (Extension index)
47
+ NOTE: This method will install the theme under the name "stable-diffusion-webui". You can read more about this issue in the next section.
48
+ 1. Open WebUI
49
+ 2. Click on the "Extensions" tab and navigate to "Available"
50
+ 3. Click "Load From:" and find and install "Catppuccin Theme" from the list
51
+ 4. Go to "Installed" subsection and click "Apply and restart UI"
52
+ 5. Configure the theme from the "Settings" tab under "Catppuccin Theme", afterwards you must "Apply Settings" and "Reload UI"
53
+
54
+ ### Add directly
55
+ 1. Clone this repository locally
56
+ 2. Create the file `user.css` in your stable-diffusion-webui directory
57
+ 3. Copy the contents of the desired flavor into `user.css`
58
+ 4. Restart the Web UI or click "Reload UI" at the bottom of the screen
59
+
60
+ ## NOTE
61
+ Due to catppuccin naming conventions and limitations in webui's extension names, this extension will come up as "stable-diffusion-webui" in the extension update section. I have proposed a solution to WebUI [here](https://github.com/catppuccin/stable-diffusion-webui/issues/5#issuecomment-1420599298), feel free to upvote it increase the chances of this issue being resolved.
62
+
63
+ ## 🙋 FAQ
64
+
65
+ - Q: **_"I decided not to use the extennsion, how do I change the accent color?"_**\
66
+ A: Open `user.css` and set the variavble `--accent: var(--{preferred color});`
67
+
68
+ - Q: **_"The theme isn't being applied???"_**\
69
+ A: Sometimes Web UI doesn't automatically figure out your preferred theme. Try adding `/?__theme=dark` to the url and see if the theme is applied. Below are the steps to make this change persistent on different systems:
70
+ - **Linux / MacOS**: Edit `webui-user.sh` and uncomment and set this variable as `export COMMANDLINE_ARGS="--theme=dark $COMMANDLINE_ARGS"`
71
+ - **Windows**: Edit `webui-user.bat` and set this variable by `set COMMANDLINE_ARGS=--theme=dark`.
72
+
73
+ If you are still having trouble then consult the relevant part of the [webui wiki](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Features#usercss).
74
+
75
+ - Q: **_"Why doesn't the theme look like the previews?"_**\
76
+ A: The main UI is constantly being changed upstream, so our previews may not match what the theme will look like for you. Though the previews may be behind, we are frequently updating the themes whenever there is a change in the Web UI repo. Though if you notice a style issue with a recent version of webui, feel free to open an issue on this repo.
77
+
78
+ - Q: **_"Why isn't {extension} themed?"_**\
79
+ A: Some extensions use their own style sheets that don't play nice with `user.css`.
80
+
81
+ ## 💝 Thanks to
82
+
83
+ - [Kettukaa](https://github.com/Kettukaa)
84
+
85
+ &nbsp;
86
+
87
+ <p align="center">
88
+ <img src="https://raw.githubusercontent.com/catppuccin/catppuccin/main/assets/footers/gray0_ctp_on_line.svg?sanitize=true" />
89
+ </p>
90
+
91
+ <p align="center">
92
+ Copyright &copy; 2021-present <a href="https://github.com/catppuccin" target="_blank">Catppuccin Org</a>
93
+ </p>
94
+
95
+ <p align="center">
96
+ <a href="https://github.com/catppuccin/catppuccin/blob/main/LICENSE"><img src="https://img.shields.io/static/v1.svg?style=for-the-badge&label=License&message=MIT&logoColor=d9e0ee&colorA=363a4f&colorB=b7bdf8"/></a>
97
+ </p>
SD-catppuccin-main/assets/.gitkeep ADDED
File without changes
SD-catppuccin-main/assets/frappe.webp ADDED
SD-catppuccin-main/assets/latte.webp ADDED
SD-catppuccin-main/assets/macchiato.webp ADDED
SD-catppuccin-main/assets/mocha.webp ADDED
SD-catppuccin-main/assets/res.webp ADDED
SD-catppuccin-main/flavors/frappe.css ADDED
@@ -0,0 +1,565 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :root, *, #context-menu {
2
+ --rosewater: #f2d5cf;
3
+ --flamingo: #eebebe;
4
+ --pink: #f4b8e4;
5
+ --mauve: #ca9ee6;
6
+ --red: #e78284;
7
+ --maroon: #ea999c;
8
+ --peach: #ef9f76;
9
+ --yellow: #e5c890;
10
+ --green: #a6d189;
11
+ --teal: #81c8be;
12
+ --sky: #99d1db;
13
+ --sapphire: #85c1dc;
14
+ --blue: #8caaee;
15
+ --lavender: #babbf1;
16
+ --text: #c6d0f5;
17
+ --subtext1: #b5bfe2;
18
+ --subtext0: #a5adce;
19
+ --overlay2: #949cbb;
20
+ --overlay1: #838ba7;
21
+ --overlay0: #737994;
22
+ --surface2: #626880;
23
+ --surface1: #51576d;
24
+ --surface0: #414559;
25
+ --base: #303446;
26
+ --mantle: #292c3c;
27
+ --crust: #232634;
28
+ --shadow: #010409;
29
+ --accent: var(--maroon);
30
+ color-scheme: light;
31
+ }
32
+
33
+ select, option {
34
+ background-color: var(--base);
35
+ }
36
+
37
+ #setting_sd_model_checkpoint > :first-child{
38
+ background-color: var(--base);
39
+ }
40
+
41
+ #txt2img_prompt_container,
42
+ #img2img_prompt_container {
43
+ background-color: var(--mantle);
44
+ }
45
+
46
+
47
+ .dark .bg-white\/90, .bg-white\/90 {
48
+ background-color: var(--base);
49
+ }
50
+
51
+ .dark fieldset span.text-gray-500, fieldset span.text-gray-500,
52
+ .dark .gr-block.gr-box span.text-gray-500, .gr-block.gr-box span.text-gray-500,
53
+ .dark label.block span, label.block span {
54
+ background-color: var(--base);
55
+ border: transparent;
56
+ }
57
+
58
+ .dark .dark\:text-gray-200, .\:text-gray-200{
59
+ color: var(--text);
60
+ }
61
+
62
+ .dark .dark\:bg-gray-950, .\:bg-gray-950 {
63
+ background-color: var(--crust);
64
+ }
65
+
66
+ .dark .dark\:bg-gray-900, .\:bg-gray-900 {
67
+ background-color: var(--base);
68
+ border-radius: 10px;
69
+ }
70
+
71
+ .dark .dark\:border-gray-700, .\:border-gray-700 {
72
+ border-color: var(--surface0);
73
+ }
74
+
75
+ .dark .gr-panel, .gr-panel {
76
+ background-color: var(--mantle);
77
+ }
78
+
79
+
80
+ textarea, .gr-text-input {
81
+ background-color: var(--base) !important;
82
+ }
83
+
84
+ .dark .bg-white, .bg-white {
85
+ background-color: var(--mantle);
86
+ }
87
+
88
+ .dark .gr-compact, .gr-compact {
89
+ background-color: var(--base);
90
+ }
91
+
92
+ .dark .gr-input, .gr-input {
93
+ border-color: var(--surface0);
94
+ }
95
+ .dark .gr-form, .gr-form,
96
+ .dark .gr-box, .gr-box {
97
+ background-color: transparent;
98
+ color: var(--text);
99
+ }
100
+ .dark .gr-check-radio, .gr-check-radio {
101
+ background-color: var(--base);
102
+ }
103
+
104
+ .dark .gr-check-radio:focus, .gr-check-radio:focus,
105
+ .dark .gr-check-radio:checked, .gr-check-radio:checked {
106
+ background-color: var(--accent);
107
+ }
108
+
109
+ .dark .gr-button-primary:hover, .gr-button-primary:hover {
110
+ filter: brightness(130%);
111
+ }
112
+ .dark .gr-button-primary, .gr-button-primary {
113
+ background-color: var(--accent) !important;
114
+ color: var(--shadow)
115
+ }
116
+
117
+
118
+ .dark .gr-button-secondary:hover, .gr-button-secondary:hover {
119
+ filter: brightness(120%);
120
+ }
121
+
122
+ button, input, optgroup, select, textarea {
123
+ color: var(--accent);
124
+ }
125
+
126
+ .dark .gr-input-label, .gr-input-label,
127
+ .dark .gr-button-secondary,.gr-button-secondary,
128
+ .gr-input-label,
129
+ .gr-button-secondary {
130
+ --tw-gradient-from: none;
131
+ --tw-gradient-to: none;
132
+ --tw-gradient-stops: none;
133
+ background-color: var(--base);
134
+ color: var(--text)
135
+ }
136
+
137
+ .gr-button,
138
+ .dark .gr-button {
139
+ border-color:var(--surface0);
140
+ background-color: var(--base);
141
+ background-image: unset;
142
+ }
143
+
144
+
145
+ .livePreview {
146
+ background-color: var(--base) !important;
147
+ height: 60vh !important;
148
+ width: 100% !important;
149
+ border-radius: 10px !important;
150
+ }
151
+
152
+ .gr-padded {
153
+ padding: .825rem .75rem;
154
+ }
155
+
156
+
157
+ #mode_extras > :first-child > .bg-white {
158
+ background-color: var(--base);
159
+ }
160
+
161
+ #interrogate_col {
162
+ justify-content: center;
163
+ gap: 10px;
164
+ /* background: var(--base); */
165
+ /* border-top-left-radius: 10px !important; */
166
+ /* border-top-right-radius: 10px !important; */
167
+ /* padding-top: 20px; */
168
+ }
169
+
170
+ #txt2img_toprow,
171
+ #img2img_toprow {
172
+ background-color: unset;
173
+ }
174
+
175
+ #txt2img_actions_column, #img2img_actions_column {
176
+ padding: 10px;
177
+ margin: 5px;
178
+ border-radius: 10px !important;
179
+ background-color: var(--base);
180
+ }
181
+
182
+ #img_inpaint_mask > div:nth-child(3),
183
+ #img_inpaint_base > div:nth-child(3){
184
+ border-width: 1px;
185
+ border-color:var(--surface0);
186
+
187
+ }
188
+
189
+ #img2img_settings {
190
+ border-radius: 10px;
191
+ }
192
+
193
+ #mode_img2img > :not(:first-child) {
194
+ border-width: 0px;
195
+ }
196
+
197
+
198
+ #txt2img_gallery,
199
+ #img2img_gallery,
200
+ #extras_gallery {
201
+ background-color: var(--base) !important;
202
+ }
203
+
204
+ #img2img_copy_to_img2img > :not(:first-child) {
205
+ border-width: 1px !important;
206
+ border-color: var(--surface0) !important;
207
+ border-radius: 10px !important;
208
+ margin-left: 10px;
209
+ }
210
+
211
+ #txt2img_interrupt, #img2img_interrupt {
212
+ background-color: var(--red) !important;
213
+ color: var(--mantle);
214
+ }
215
+
216
+ #txt2img_skip, #img2img_skip {
217
+ background-color: var(--maroon) !important;
218
+ color: var(--mantle);
219
+ }
220
+
221
+ #txt2img_batch_count,
222
+ #txt2img_width {
223
+ margin-bottom: 0.625vw;
224
+ }
225
+
226
+ #txt2img_script_container > div > div {
227
+ margin: 0px 1vh 0.9vw 1vh;
228
+ }
229
+
230
+ #txt2img_script_container:last-child > div{
231
+ margin: unset;
232
+ }
233
+
234
+ .boder,
235
+ .dark .border, .border,
236
+ .dark .border-gray-100, .border-gray-100,
237
+ .dark .border-gray-200, .border-gray-200,
238
+ .dark .border-gray-300, .border-gray-300,
239
+ .dark .\!border, .\!border,
240
+ .dark .\!border-gray-300, .\!border-gray-300 {
241
+ border-color: var(--surface0);
242
+ }
243
+
244
+
245
+ .container {
246
+ background-color: var(--crust);
247
+ }
248
+
249
+ fieldset span.text-gray-500,
250
+ .gr-block.gr-box span.text-gray-500,
251
+ label.block span {
252
+ box-shadow: unset;
253
+ }
254
+
255
+ .dark .text-gray-500, .text-gray-500 {
256
+ color: var(--text);
257
+ }
258
+
259
+ .dark fieldset span.text-gray-500, fieldset span.text-gray-500,
260
+ .dark .gr-block.gr-box, .gr-block.gr-box,
261
+ span.text-gray-500,
262
+ .dark label.block span, label.block span {
263
+ background-color: transparent;
264
+ border: transparent;
265
+ }
266
+
267
+ .dark .text-gray-700, .text-gray-700,
268
+ .dark .text-gray-800, .text-gray-800,
269
+ .dark .text-gray-900, .text-gray-900,
270
+ .dark .\!text-gray-700, .\!text-gray-700,
271
+ .dark .\!text-gray-800, .\!text-gray-800 {
272
+ color: var(--text);
273
+ }
274
+
275
+ #txt2img_settings > div {
276
+ margin-top: 2vh;
277
+ flex-grow: 0;
278
+ min-width: 30%;
279
+ }
280
+
281
+ #tabs > :first-child {
282
+ background-color: var(--crust);
283
+ }
284
+
285
+ #tabs{
286
+ background-color: var(--mantle);
287
+ }
288
+
289
+ #tab_txt2img > div {
290
+ background-color: var(--mantle);
291
+ }
292
+
293
+ #tabs > div{
294
+ border-width: 0px !important;
295
+ border-color:var(--surface0);
296
+ }
297
+
298
+ #tabs > div:nth-child(1) {
299
+ flex-wrap: wrap-reverse;
300
+ background-color: var(--crust);
301
+ }
302
+ .tabs > :first-child {
303
+ border: none !important;
304
+ margin-bottom: -1px;
305
+ gap: 3px 0px;
306
+ background-color: var(--mantle);
307
+ padding-top: 5px;
308
+ z-index: 10;
309
+ }
310
+
311
+ #img2img_img2img_tab {
312
+ border-width: 0px !important;
313
+ }
314
+
315
+ #mode_img2img > div:nth-child(1) > .bg-white {
316
+ background-color: var(--base);
317
+ }
318
+
319
+ #tab_extensions table td, #tab_extensions table th {
320
+ border: 1px solid var(--surface0);
321
+ }
322
+
323
+ #extras_resize_mode > :first-child {
324
+ background-color: var(--base);
325
+ }
326
+
327
+ #extras_resize_mode > :not(:first-child) {
328
+ background-color: var(--mantle) !important;
329
+ padding-top: 20px;
330
+ border-color: transparent;
331
+ border-radius: 0px 10px 10px 10px;
332
+ margin-bottom: 20px;
333
+
334
+ }
335
+
336
+ .tabs > :first-child > button {
337
+ border-radius: 8px 8px 0px 0px;
338
+ /* outline: 1px solid var(--base) !important; */
339
+ border-color: var(--surface0);
340
+ border-width: 0px;
341
+ border-bottom-width: 0px;
342
+ }
343
+
344
+
345
+ #quicksettings {
346
+ background-color: transparent;
347
+ }
348
+
349
+ input[type="range"]::-ms-track {
350
+ background: transparent;
351
+ }
352
+
353
+ input[type="range"]::-ms-fill-lower {
354
+ background: var(--accent);
355
+ border-radius: 10px;
356
+ }
357
+ input[type="range"]::-ms-fill-upper {
358
+ background: var(--overlay0);
359
+ border-radius: 10px;
360
+ }
361
+
362
+ input[type="range"]:focus::-ms-fill-lower {
363
+ background: var(--accent);
364
+ }
365
+ input[type="range"]:focus::-ms-fill-upper {
366
+ background: var(--overlay0);
367
+ }
368
+
369
+ /* Chrome, Safari, Edge, Opera */
370
+ input::-webkit-outer-spin-button,
371
+ input::-webkit-inner-spin-button {
372
+ -webkit-appearance: none;
373
+ margin: 0;
374
+ }
375
+
376
+ /* Firefox */
377
+ input[type="number"] {
378
+ -moz-appearance: textfield;
379
+ }
380
+ .gr-box > div > div > input.gr-text-input {
381
+ width: 4em;
382
+ }
383
+
384
+ .progressDiv .progress {
385
+ background: var(--accent);
386
+ color: var(--shadow);
387
+ }
388
+
389
+ .dark .progressDiv, .progressDiv {
390
+ background-color: var(--surface0);
391
+ }
392
+
393
+ input[type="range"] {
394
+ font-size: 1.5rem;
395
+ }
396
+
397
+ input[type="range"] {
398
+ color: var(--accent);
399
+ --thumb-height: 0.5em;
400
+ --track-height: 0.125em;
401
+ --track-color: var(--surface0);
402
+ --brightness-hover: 130%;
403
+ --brightness-down: 80%;
404
+ --clip-edges: 0.125em;
405
+ }
406
+
407
+ input[type="range"].win10-thumb {
408
+ color: var(--accent);
409
+
410
+ --thumb-height: 0.5em;
411
+ --thumb-width: 0.5em;
412
+ --clip-edges: 0.0125em;
413
+ }
414
+
415
+ @media (prefers-color-scheme: dark) {
416
+ input[type="range"] {
417
+ color: var(--accent);
418
+ --track-color: var(--surface0);
419
+ }
420
+
421
+ input[type="range"].win10-thumb {
422
+ color: var(--accent);
423
+ }
424
+ }
425
+
426
+ /* === range commons === */
427
+ input[type="range"] {
428
+ position: relative;
429
+ background: #fff0;
430
+ overflow: hidden;
431
+ }
432
+
433
+ input[type="range"]:active {
434
+ cursor: grabbing;
435
+ }
436
+
437
+ input[type="range"]:disabled {
438
+ filter: grayscale(1);
439
+ opacity: 0.3;
440
+ cursor: not-allowed;
441
+ }
442
+
443
+ /* === WebKit specific styles === */
444
+ input[type="range"],
445
+ input[type="range"]::-webkit-slider-runnable-track,
446
+ input[type="range"]::-webkit-slider-thumb {
447
+ -webkit-appearance: none;
448
+ transition: all ease 100ms;
449
+ height: var(--thumb-height);
450
+ }
451
+
452
+ input[type="range"]::-webkit-slider-runnable-track,
453
+ input[type="range"]::-webkit-slider-thumb {
454
+ position: relative;
455
+ }
456
+
457
+ input[type="range"]::-webkit-slider-thumb {
458
+ --thumb-radius: calc((var(--thumb-height) * 0.5) - 1px);
459
+ --clip-top: calc((var(--thumb-height) - var(--track-height)) * 0.5 - 0.5px);
460
+ --clip-bottom: calc(var(--thumb-height) - var(--clip-top));
461
+ --clip-further: calc(100% + 1px);
462
+ --box-fill: calc(-100vmax - var(--thumb-width, var(--thumb-height))) 0 0 100vmax currentColor;
463
+
464
+ width: var(--thumb-width, var(--thumb-height));
465
+ background: linear-gradient(currentColor 0 0) scroll no-repeat left center / 50% calc(var(--track-height) + 1px);
466
+ background-color: currentColor;
467
+ box-shadow: var(--box-fill);
468
+ border-radius: var(--thumb-width, var(--thumb-height));
469
+
470
+ filter: brightness(100%);
471
+ clip-path: polygon(
472
+ 100% -1px,
473
+ var(--clip-edges) -1px,
474
+ 0 var(--clip-top),
475
+ -100vmax var(--clip-top),
476
+ -100vmax var(--clip-bottom),
477
+ 0 var(--clip-bottom),
478
+ var(--clip-edges) 100%,
479
+ var(--clip-further) var(--clip-further)
480
+ );
481
+ }
482
+
483
+ input[type="range"]:hover::-webkit-slider-thumb {
484
+ filter: brightness(var(--brightness-hover));
485
+ cursor: grab;
486
+ }
487
+
488
+ input[type="range"]:active::-webkit-slider-thumb {
489
+ filter: brightness(var(--brightness-down));
490
+ cursor: grabbing;
491
+ }
492
+
493
+ input[type="range"]::-webkit-slider-runnable-track {
494
+ background: linear-gradient(var(--track-color) 0 0) scroll no-repeat center / 100% calc(var(--track-height) + 1px);
495
+ }
496
+
497
+ input[type="range"]:disabled::-webkit-slider-thumb {
498
+ cursor: not-allowed;
499
+ }
500
+
501
+ /* === Firefox specific styles === */
502
+ input[type="range"],
503
+ input[type="range"]::-moz-range-track,
504
+ input[type="range"]::-moz-range-thumb {
505
+ appearance: none;
506
+ transition: all ease 100ms;
507
+ height: var(--thumb-height);
508
+ }
509
+
510
+ input[type="range"]::-moz-range-track,
511
+ input[type="range"]::-moz-range-thumb,
512
+ input[type="range"]::-moz-range-progress {
513
+ background: #fff0;
514
+ }
515
+
516
+ input[type="range"]::-moz-range-thumb {
517
+ background: currentColor;
518
+ border: 0;
519
+ width: var(--thumb-width, var(--thumb-height));
520
+ border-radius: var(--thumb-width, var(--thumb-height));
521
+ cursor: grab;
522
+ }
523
+
524
+ input[type="range"]:active::-moz-range-thumb {
525
+ cursor: grabbing;
526
+ }
527
+
528
+ input[type="range"]::-moz-range-track {
529
+ width: 100%;
530
+ background: var(--track-color);
531
+ }
532
+
533
+ input[type="range"]::-moz-range-progress {
534
+ appearance: none;
535
+ background: currentColor;
536
+ transition-delay: 30ms;
537
+ }
538
+
539
+ input[type="range"]::-moz-range-track,
540
+ input[type="range"]::-moz-range-progress {
541
+ height: calc(var(--track-height) + 1px);
542
+ border-radius: var(--track-height);
543
+ }
544
+
545
+ input[type="range"]::-moz-range-thumb,
546
+ input[type="range"]::-moz-range-progress {
547
+ filter: brightness(100%);
548
+ }
549
+
550
+ input[type="range"]:hover::-moz-range-thumb,
551
+ input[type="range"]:hover::-moz-range-progress {
552
+ filter: brightness(var(--brightness-hover));
553
+ }
554
+
555
+ input[type="range"]:active::-moz-range-thumb,
556
+ input[type="range"]:active::-moz-range-progress {
557
+ filter: brightness(var(--brightness-down));
558
+ }
559
+
560
+ input[type="range"]:disabled::-moz-range-thumb {
561
+ cursor: not-allowed;
562
+ }
563
+
564
+ /* all of the input range stuff is from this guy*/
565
+ /* Shout out to them https://codepen.io/ShadowShahriar/pen/zYPPYrQ */
SD-catppuccin-main/flavors/latte.css ADDED
@@ -0,0 +1,565 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :root, *, #context-menu{
2
+ --rosewater: #dc8a78;
3
+ --flamingo: #dd7878;
4
+ --pink: #ea76cb;
5
+ --mauve: #8839ef;
6
+ --red: #d20f39;
7
+ --maroon: #e64553;
8
+ --peach: #fe640b;
9
+ --yellow: #df8e1d;
10
+ --green: #40a02b;
11
+ --teal: #179299;
12
+ --sky: #04a5e5;
13
+ --sapphire: #209fb5;
14
+ --blue: #1e66f5;
15
+ --lavender: #7287fd;
16
+ --text: #4c4f69;
17
+ --subtext1: #5c5f77;
18
+ --subtext0: #6c6f85;
19
+ --overlay2: #7c7f93;
20
+ --overlay1: #8c8fa1;
21
+ --overlay0: #9ca0b0;
22
+ --surface2: #acb0be;
23
+ --surface1: #bcc0cc;
24
+ --surface0: #ccd0da;
25
+ --base: #eff1f5;
26
+ --mantle: #e6e9ef;
27
+ --crust: #dce0e8;
28
+ --shadow: #dbdfef;
29
+ --accent: var(--maroon);
30
+ color-scheme: light;
31
+ }
32
+
33
+ select, option {
34
+ background-color: var(--base);
35
+ }
36
+
37
+ #setting_sd_model_checkpoint > :first-child{
38
+ background-color: var(--base);
39
+ }
40
+
41
+ #txt2img_prompt_container,
42
+ #img2img_prompt_container {
43
+ background-color: var(--mantle);
44
+ }
45
+
46
+
47
+ .dark .bg-white\/90, .bg-white\/90 {
48
+ background-color: var(--base);
49
+ }
50
+
51
+ .dark fieldset span.text-gray-500, fieldset span.text-gray-500,
52
+ .dark .gr-block.gr-box span.text-gray-500, .gr-block.gr-box span.text-gray-500,
53
+ .dark label.block span, label.block span {
54
+ background-color: var(--base);
55
+ border: transparent;
56
+ }
57
+
58
+ .dark .dark\:text-gray-200, .\:text-gray-200{
59
+ color: var(--text);
60
+ }
61
+
62
+ .dark .dark\:bg-gray-950, .\:bg-gray-950 {
63
+ background-color: var(--crust);
64
+ }
65
+
66
+ .dark .dark\:bg-gray-900, .\:bg-gray-900 {
67
+ background-color: var(--base);
68
+ border-radius: 10px;
69
+ }
70
+
71
+ .dark .dark\:border-gray-700, .\:border-gray-700 {
72
+ border-color: var(--surface0);
73
+ }
74
+
75
+ .dark .gr-panel, .gr-panel {
76
+ background-color: var(--mantle);
77
+ }
78
+
79
+
80
+ textarea, .gr-text-input {
81
+ background-color: var(--base) !important;
82
+ }
83
+
84
+ .dark .bg-white, .bg-white {
85
+ background-color: var(--mantle);
86
+ }
87
+
88
+ .dark .gr-compact, .gr-compact {
89
+ background-color: var(--base);
90
+ }
91
+
92
+ .dark .gr-input, .gr-input {
93
+ border-color: var(--surface0);
94
+ }
95
+ .dark .gr-form, .gr-form,
96
+ .dark .gr-box, .gr-box {
97
+ background-color: transparent;
98
+ color: var(--text);
99
+ }
100
+ .dark .gr-check-radio, .gr-check-radio {
101
+ background-color: var(--base);
102
+ }
103
+
104
+ .dark .gr-check-radio:focus, .gr-check-radio:focus,
105
+ .dark .gr-check-radio:checked, .gr-check-radio:checked {
106
+ background-color: var(--accent);
107
+ }
108
+
109
+ .dark .gr-button-primary:hover, .gr-button-primary:hover {
110
+ filter: brightness(130%);
111
+ }
112
+ .dark .gr-button-primary, .gr-button-primary {
113
+ background-color: var(--accent) !important;
114
+ color: var(--shadow)
115
+ }
116
+
117
+
118
+ .dark .gr-button-secondary:hover, .gr-button-secondary:hover {
119
+ filter: brightness(120%);
120
+ }
121
+
122
+ button, input, optgroup, select, textarea {
123
+ color: var(--accent);
124
+ }
125
+
126
+ .dark .gr-input-label, .gr-input-label,
127
+ .dark .gr-button-secondary,.gr-button-secondary,
128
+ .gr-input-label,
129
+ .gr-button-secondary {
130
+ --tw-gradient-from: none;
131
+ --tw-gradient-to: none;
132
+ --tw-gradient-stops: none;
133
+ background-color: var(--base);
134
+ color: var(--text)
135
+ }
136
+
137
+ .gr-button,
138
+ .dark .gr-button {
139
+ border-color:var(--surface0);
140
+ background-color: var(--base);
141
+ background-image: unset;
142
+ }
143
+
144
+
145
+ .livePreview {
146
+ background-color: var(--base) !important;
147
+ height: 60vh !important;
148
+ width: 100% !important;
149
+ border-radius: 10px !important;
150
+ }
151
+
152
+ .gr-padded {
153
+ padding: .825rem .75rem;
154
+ }
155
+
156
+
157
+ #mode_extras > :first-child > .bg-white {
158
+ background-color: var(--base);
159
+ }
160
+
161
+ #interrogate_col {
162
+ justify-content: center;
163
+ gap: 10px;
164
+ /* background: var(--base); */
165
+ /* border-top-left-radius: 10px !important; */
166
+ /* border-top-right-radius: 10px !important; */
167
+ /* padding-top: 20px; */
168
+ }
169
+
170
+ #txt2img_toprow,
171
+ #img2img_toprow {
172
+ background-color: unset;
173
+ }
174
+
175
+ #txt2img_actions_column, #img2img_actions_column {
176
+ padding: 10px;
177
+ margin: 5px;
178
+ border-radius: 10px !important;
179
+ background-color: var(--base);
180
+ }
181
+
182
+ #img_inpaint_mask > div:nth-child(3),
183
+ #img_inpaint_base > div:nth-child(3){
184
+ border-width: 1px;
185
+ border-color:var(--surface0);
186
+
187
+ }
188
+
189
+ #img2img_settings {
190
+ border-radius: 10px;
191
+ }
192
+
193
+ #mode_img2img > :not(:first-child) {
194
+ border-width: 0px;
195
+ }
196
+
197
+
198
+ #txt2img_gallery,
199
+ #img2img_gallery,
200
+ #extras_gallery {
201
+ background-color: var(--base) !important;
202
+ }
203
+
204
+ #img2img_copy_to_img2img > :not(:first-child) {
205
+ border-width: 1px !important;
206
+ border-color: var(--surface0) !important;
207
+ border-radius: 10px !important;
208
+ margin-left: 10px;
209
+ }
210
+
211
+ #txt2img_interrupt, #img2img_interrupt {
212
+ background-color: var(--red) !important;
213
+ color: var(--mantle);
214
+ }
215
+
216
+ #txt2img_skip, #img2img_skip {
217
+ background-color: var(--maroon) !important;
218
+ color: var(--mantle);
219
+ }
220
+
221
+ #txt2img_batch_count,
222
+ #txt2img_width {
223
+ margin-bottom: 0.625vw;
224
+ }
225
+
226
+ #txt2img_script_container > div > div {
227
+ margin: 0px 1vh 0.9vw 1vh;
228
+ }
229
+
230
+ #txt2img_script_container:last-child > div{
231
+ margin: unset;
232
+ }
233
+
234
+ .boder,
235
+ .dark .border, .border,
236
+ .dark .border-gray-100, .border-gray-100,
237
+ .dark .border-gray-200, .border-gray-200,
238
+ .dark .border-gray-300, .border-gray-300,
239
+ .dark .\!border, .\!border,
240
+ .dark .\!border-gray-300, .\!border-gray-300 {
241
+ border-color: var(--surface0);
242
+ }
243
+
244
+
245
+ .container {
246
+ background-color: var(--crust);
247
+ }
248
+
249
+ fieldset span.text-gray-500,
250
+ .gr-block.gr-box span.text-gray-500,
251
+ label.block span {
252
+ box-shadow: unset;
253
+ }
254
+
255
+ .dark .text-gray-500, .text-gray-500 {
256
+ color: var(--text);
257
+ }
258
+
259
+ .dark fieldset span.text-gray-500, fieldset span.text-gray-500,
260
+ .dark .gr-block.gr-box, .gr-block.gr-box,
261
+ span.text-gray-500,
262
+ .dark label.block span, label.block span {
263
+ background-color: transparent;
264
+ border: transparent;
265
+ }
266
+
267
+ .dark .text-gray-700, .text-gray-700,
268
+ .dark .text-gray-800, .text-gray-800,
269
+ .dark .text-gray-900, .text-gray-900,
270
+ .dark .\!text-gray-700, .\!text-gray-700,
271
+ .dark .\!text-gray-800, .\!text-gray-800 {
272
+ color: var(--text);
273
+ }
274
+
275
+ #txt2img_settings > div {
276
+ margin-top: 2vh;
277
+ flex-grow: 0;
278
+ min-width: 30%;
279
+ }
280
+
281
+ #tabs > :first-child {
282
+ background-color: var(--crust);
283
+ }
284
+
285
+ #tabs{
286
+ background-color: var(--mantle);
287
+ }
288
+
289
+ #tab_txt2img > div {
290
+ background-color: var(--mantle);
291
+ }
292
+
293
+ #tabs > div{
294
+ border-width: 0px !important;
295
+ border-color:var(--surface0);
296
+ }
297
+
298
+ #tabs > div:nth-child(1) {
299
+ flex-wrap: wrap-reverse;
300
+ background-color: var(--crust);
301
+ }
302
+ .tabs > :first-child {
303
+ border: none !important;
304
+ margin-bottom: -1px;
305
+ gap: 3px 0px;
306
+ background-color: var(--mantle);
307
+ padding-top: 5px;
308
+ z-index: 10;
309
+ }
310
+
311
+ #img2img_img2img_tab {
312
+ border-width: 0px !important;
313
+ }
314
+
315
+ #mode_img2img > div:nth-child(1) > .bg-white {
316
+ background-color: var(--base);
317
+ }
318
+
319
+ #tab_extensions table td, #tab_extensions table th {
320
+ border: 1px solid var(--surface0);
321
+ }
322
+
323
+ #extras_resize_mode > :first-child {
324
+ background-color: var(--base);
325
+ }
326
+
327
+ #extras_resize_mode > :not(:first-child) {
328
+ background-color: var(--mantle) !important;
329
+ padding-top: 20px;
330
+ border-color: transparent;
331
+ border-radius: 0px 10px 10px 10px;
332
+ margin-bottom: 20px;
333
+
334
+ }
335
+
336
+ .tabs > :first-child > button {
337
+ border-radius: 8px 8px 0px 0px;
338
+ /* outline: 1px solid var(--base) !important; */
339
+ border-color: var(--surface0);
340
+ border-width: 0px;
341
+ border-bottom-width: 0px;
342
+ }
343
+
344
+
345
+ #quicksettings {
346
+ background-color: transparent;
347
+ }
348
+
349
+ input[type="range"]::-ms-track {
350
+ background: transparent;
351
+ }
352
+
353
+ input[type="range"]::-ms-fill-lower {
354
+ background: var(--accent);
355
+ border-radius: 10px;
356
+ }
357
+ input[type="range"]::-ms-fill-upper {
358
+ background: var(--overlay0);
359
+ border-radius: 10px;
360
+ }
361
+
362
+ input[type="range"]:focus::-ms-fill-lower {
363
+ background: var(--accent);
364
+ }
365
+ input[type="range"]:focus::-ms-fill-upper {
366
+ background: var(--overlay0);
367
+ }
368
+
369
+ /* Chrome, Safari, Edge, Opera */
370
+ input::-webkit-outer-spin-button,
371
+ input::-webkit-inner-spin-button {
372
+ -webkit-appearance: none;
373
+ margin: 0;
374
+ }
375
+
376
+ /* Firefox */
377
+ input[type="number"] {
378
+ -moz-appearance: textfield;
379
+ }
380
+ .gr-box > div > div > input.gr-text-input {
381
+ width: 4em;
382
+ }
383
+
384
+ .progressDiv .progress {
385
+ background: var(--accent);
386
+ color: var(--shadow);
387
+ }
388
+
389
+ .dark .progressDiv, .progressDiv {
390
+ background-color: var(--surface0);
391
+ }
392
+
393
+ input[type="range"] {
394
+ font-size: 1.5rem;
395
+ }
396
+
397
+ input[type="range"] {
398
+ color: var(--accent);
399
+ --thumb-height: 0.5em;
400
+ --track-height: 0.125em;
401
+ --track-color: var(--surface0);
402
+ --brightness-hover: 130%;
403
+ --brightness-down: 80%;
404
+ --clip-edges: 0.125em;
405
+ }
406
+
407
+ input[type="range"].win10-thumb {
408
+ color: var(--accent);
409
+
410
+ --thumb-height: 0.5em;
411
+ --thumb-width: 0.5em;
412
+ --clip-edges: 0.0125em;
413
+ }
414
+
415
+ @media (prefers-color-scheme: dark) {
416
+ input[type="range"] {
417
+ color: var(--accent);
418
+ --track-color: var(--surface0);
419
+ }
420
+
421
+ input[type="range"].win10-thumb {
422
+ color: var(--accent);
423
+ }
424
+ }
425
+
426
+ /* === range commons === */
427
+ input[type="range"] {
428
+ position: relative;
429
+ background: #fff0;
430
+ overflow: hidden;
431
+ }
432
+
433
+ input[type="range"]:active {
434
+ cursor: grabbing;
435
+ }
436
+
437
+ input[type="range"]:disabled {
438
+ filter: grayscale(1);
439
+ opacity: 0.3;
440
+ cursor: not-allowed;
441
+ }
442
+
443
+ /* === WebKit specific styles === */
444
+ input[type="range"],
445
+ input[type="range"]::-webkit-slider-runnable-track,
446
+ input[type="range"]::-webkit-slider-thumb {
447
+ -webkit-appearance: none;
448
+ transition: all ease 100ms;
449
+ height: var(--thumb-height);
450
+ }
451
+
452
+ input[type="range"]::-webkit-slider-runnable-track,
453
+ input[type="range"]::-webkit-slider-thumb {
454
+ position: relative;
455
+ }
456
+
457
+ input[type="range"]::-webkit-slider-thumb {
458
+ --thumb-radius: calc((var(--thumb-height) * 0.5) - 1px);
459
+ --clip-top: calc((var(--thumb-height) - var(--track-height)) * 0.5 - 0.5px);
460
+ --clip-bottom: calc(var(--thumb-height) - var(--clip-top));
461
+ --clip-further: calc(100% + 1px);
462
+ --box-fill: calc(-100vmax - var(--thumb-width, var(--thumb-height))) 0 0 100vmax currentColor;
463
+
464
+ width: var(--thumb-width, var(--thumb-height));
465
+ background: linear-gradient(currentColor 0 0) scroll no-repeat left center / 50% calc(var(--track-height) + 1px);
466
+ background-color: currentColor;
467
+ box-shadow: var(--box-fill);
468
+ border-radius: var(--thumb-width, var(--thumb-height));
469
+
470
+ filter: brightness(100%);
471
+ clip-path: polygon(
472
+ 100% -1px,
473
+ var(--clip-edges) -1px,
474
+ 0 var(--clip-top),
475
+ -100vmax var(--clip-top),
476
+ -100vmax var(--clip-bottom),
477
+ 0 var(--clip-bottom),
478
+ var(--clip-edges) 100%,
479
+ var(--clip-further) var(--clip-further)
480
+ );
481
+ }
482
+
483
+ input[type="range"]:hover::-webkit-slider-thumb {
484
+ filter: brightness(var(--brightness-hover));
485
+ cursor: grab;
486
+ }
487
+
488
+ input[type="range"]:active::-webkit-slider-thumb {
489
+ filter: brightness(var(--brightness-down));
490
+ cursor: grabbing;
491
+ }
492
+
493
+ input[type="range"]::-webkit-slider-runnable-track {
494
+ background: linear-gradient(var(--track-color) 0 0) scroll no-repeat center / 100% calc(var(--track-height) + 1px);
495
+ }
496
+
497
+ input[type="range"]:disabled::-webkit-slider-thumb {
498
+ cursor: not-allowed;
499
+ }
500
+
501
+ /* === Firefox specific styles === */
502
+ input[type="range"],
503
+ input[type="range"]::-moz-range-track,
504
+ input[type="range"]::-moz-range-thumb {
505
+ appearance: none;
506
+ transition: all ease 100ms;
507
+ height: var(--thumb-height);
508
+ }
509
+
510
+ input[type="range"]::-moz-range-track,
511
+ input[type="range"]::-moz-range-thumb,
512
+ input[type="range"]::-moz-range-progress {
513
+ background: #fff0;
514
+ }
515
+
516
+ input[type="range"]::-moz-range-thumb {
517
+ background: currentColor;
518
+ border: 0;
519
+ width: var(--thumb-width, var(--thumb-height));
520
+ border-radius: var(--thumb-width, var(--thumb-height));
521
+ cursor: grab;
522
+ }
523
+
524
+ input[type="range"]:active::-moz-range-thumb {
525
+ cursor: grabbing;
526
+ }
527
+
528
+ input[type="range"]::-moz-range-track {
529
+ width: 100%;
530
+ background: var(--track-color);
531
+ }
532
+
533
+ input[type="range"]::-moz-range-progress {
534
+ appearance: none;
535
+ background: currentColor;
536
+ transition-delay: 30ms;
537
+ }
538
+
539
+ input[type="range"]::-moz-range-track,
540
+ input[type="range"]::-moz-range-progress {
541
+ height: calc(var(--track-height) + 1px);
542
+ border-radius: var(--track-height);
543
+ }
544
+
545
+ input[type="range"]::-moz-range-thumb,
546
+ input[type="range"]::-moz-range-progress {
547
+ filter: brightness(100%);
548
+ }
549
+
550
+ input[type="range"]:hover::-moz-range-thumb,
551
+ input[type="range"]:hover::-moz-range-progress {
552
+ filter: brightness(var(--brightness-hover));
553
+ }
554
+
555
+ input[type="range"]:active::-moz-range-thumb,
556
+ input[type="range"]:active::-moz-range-progress {
557
+ filter: brightness(var(--brightness-down));
558
+ }
559
+
560
+ input[type="range"]:disabled::-moz-range-thumb {
561
+ cursor: not-allowed;
562
+ }
563
+
564
+ /* all of the input range stuff is from this guy*/
565
+ /* Shout out to them https://codepen.io/ShadowShahriar/pen/zYPPYrQ */
SD-catppuccin-main/flavors/macchiato.css ADDED
@@ -0,0 +1,565 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :root, *, #context-menu{
2
+ --rosewater: #f4dbd6;
3
+ --flamingo: #f0c6c6;
4
+ --pink: #f5bde6;
5
+ --mauve: #c6a0f6;
6
+ --red: #ed8796;
7
+ --maroon: #ee99a0;
8
+ --peach: #f5a97f;
9
+ --yellow: #eed49f;
10
+ --green: #a6da95;
11
+ --teal: #8bd5ca;
12
+ --sky: #91d7e3;
13
+ --sapphire: #7dc4e4;
14
+ --blue: #8aadf4;
15
+ --lavender: #b7bdf8;
16
+ --text: #cad3f5;
17
+ --subtext1: #b8c0e0;
18
+ --subtext0: #a5adcb;
19
+ --overlay2: #939ab7;
20
+ --overlay1: #8087a2;
21
+ --overlay0: #6e738d;
22
+ --surface2: #5b6078;
23
+ --surface1: #494d64;
24
+ --surface0: #363a4f;
25
+ --base: #24273a;
26
+ --mantle: #1e2030;
27
+ --crust: #181926;
28
+ --shadow: #010409;
29
+ --accent: var(--maroon);
30
+ color-scheme: dark;
31
+ }
32
+
33
+ select, option {
34
+ background-color: var(--base);
35
+ }
36
+
37
+ #setting_sd_model_checkpoint > :first-child{
38
+ background-color: var(--base);
39
+ }
40
+
41
+ #txt2img_prompt_container,
42
+ #img2img_prompt_container {
43
+ background-color: var(--mantle);
44
+ }
45
+
46
+
47
+ .dark .bg-white\/90, .bg-white\/90 {
48
+ background-color: var(--base);
49
+ }
50
+
51
+ .dark fieldset span.text-gray-500, fieldset span.text-gray-500,
52
+ .dark .gr-block.gr-box span.text-gray-500, .gr-block.gr-box span.text-gray-500,
53
+ .dark label.block span, label.block span {
54
+ background-color: var(--base);
55
+ border: transparent;
56
+ }
57
+
58
+ .dark .dark\:text-gray-200, .\:text-gray-200{
59
+ color: var(--text);
60
+ }
61
+
62
+ .dark .dark\:bg-gray-950, .\:bg-gray-950 {
63
+ background-color: var(--crust);
64
+ }
65
+
66
+ .dark .dark\:bg-gray-900, .\:bg-gray-900 {
67
+ background-color: var(--base);
68
+ border-radius: 10px;
69
+ }
70
+
71
+ .dark .dark\:border-gray-700, .\:border-gray-700 {
72
+ border-color: var(--surface0);
73
+ }
74
+
75
+ .dark .gr-panel, .gr-panel {
76
+ background-color: var(--mantle);
77
+ }
78
+
79
+
80
+ textarea, .gr-text-input {
81
+ background-color: var(--base) !important;
82
+ }
83
+
84
+ .dark .bg-white, .bg-white {
85
+ background-color: var(--mantle);
86
+ }
87
+
88
+ .dark .gr-compact, .gr-compact {
89
+ background-color: var(--base);
90
+ }
91
+
92
+ .dark .gr-input, .gr-input {
93
+ border-color: var(--surface0);
94
+ }
95
+ .dark .gr-form, .gr-form,
96
+ .dark .gr-box, .gr-box {
97
+ background-color: transparent;
98
+ color: var(--text);
99
+ }
100
+ .dark .gr-check-radio, .gr-check-radio {
101
+ background-color: var(--base);
102
+ }
103
+
104
+ .dark .gr-check-radio:focus, .gr-check-radio:focus,
105
+ .dark .gr-check-radio:checked, .gr-check-radio:checked {
106
+ background-color: var(--accent);
107
+ }
108
+
109
+ .dark .gr-button-primary:hover, .gr-button-primary:hover {
110
+ filter: brightness(130%);
111
+ }
112
+ .dark .gr-button-primary, .gr-button-primary {
113
+ background-color: var(--accent) !important;
114
+ color: var(--shadow)
115
+ }
116
+
117
+
118
+ .dark .gr-button-secondary:hover, .gr-button-secondary:hover {
119
+ filter: brightness(120%);
120
+ }
121
+
122
+ button, input, optgroup, select, textarea {
123
+ color: var(--accent);
124
+ }
125
+
126
+ .dark .gr-input-label, .gr-input-label,
127
+ .dark .gr-button-secondary,.gr-button-secondary,
128
+ .gr-input-label,
129
+ .gr-button-secondary {
130
+ --tw-gradient-from: none;
131
+ --tw-gradient-to: none;
132
+ --tw-gradient-stops: none;
133
+ background-color: var(--base);
134
+ color: var(--text)
135
+ }
136
+
137
+ .gr-button,
138
+ .dark .gr-button {
139
+ border-color:var(--surface0);
140
+ background-color: var(--base);
141
+ background-image: unset;
142
+ }
143
+
144
+
145
+ .livePreview {
146
+ background-color: var(--base) !important;
147
+ height: 60vh !important;
148
+ width: 100% !important;
149
+ border-radius: 10px !important;
150
+ }
151
+
152
+ .gr-padded {
153
+ padding: .825rem .75rem;
154
+ }
155
+
156
+
157
+ #mode_extras > :first-child > .bg-white {
158
+ background-color: var(--base);
159
+ }
160
+
161
+ #interrogate_col {
162
+ justify-content: center;
163
+ gap: 10px;
164
+ /* background: var(--base); */
165
+ /* border-top-left-radius: 10px !important; */
166
+ /* border-top-right-radius: 10px !important; */
167
+ /* padding-top: 20px; */
168
+ }
169
+
170
+ #txt2img_toprow,
171
+ #img2img_toprow {
172
+ background-color: unset;
173
+ }
174
+
175
+ #txt2img_actions_column, #img2img_actions_column {
176
+ padding: 10px;
177
+ margin: 5px;
178
+ border-radius: 10px !important;
179
+ background-color: var(--base);
180
+ }
181
+
182
+ #img_inpaint_mask > div:nth-child(3),
183
+ #img_inpaint_base > div:nth-child(3){
184
+ border-width: 1px;
185
+ border-color:var(--surface0);
186
+
187
+ }
188
+
189
+ #img2img_settings {
190
+ border-radius: 10px;
191
+ }
192
+
193
+ #mode_img2img > :not(:first-child) {
194
+ border-width: 0px;
195
+ }
196
+
197
+
198
+ #txt2img_gallery,
199
+ #img2img_gallery,
200
+ #extras_gallery {
201
+ background-color: var(--base) !important;
202
+ }
203
+
204
+ #img2img_copy_to_img2img > :not(:first-child) {
205
+ border-width: 1px !important;
206
+ border-color: var(--surface0) !important;
207
+ border-radius: 10px !important;
208
+ margin-left: 10px;
209
+ }
210
+
211
+ #txt2img_interrupt, #img2img_interrupt {
212
+ background-color: var(--red) !important;
213
+ color: var(--mantle);
214
+ }
215
+
216
+ #txt2img_skip, #img2img_skip {
217
+ background-color: var(--maroon) !important;
218
+ color: var(--mantle);
219
+ }
220
+
221
+ #txt2img_batch_count,
222
+ #txt2img_width {
223
+ margin-bottom: 0.625vw;
224
+ }
225
+
226
+ #txt2img_script_container > div > div {
227
+ margin: 0px 1vh 0.9vw 1vh;
228
+ }
229
+
230
+ #txt2img_script_container:last-child > div{
231
+ margin: unset;
232
+ }
233
+
234
+ .boder,
235
+ .dark .border, .border,
236
+ .dark .border-gray-100, .border-gray-100,
237
+ .dark .border-gray-200, .border-gray-200,
238
+ .dark .border-gray-300, .border-gray-300,
239
+ .dark .\!border, .\!border,
240
+ .dark .\!border-gray-300, .\!border-gray-300 {
241
+ border-color: var(--surface0);
242
+ }
243
+
244
+
245
+ .container {
246
+ background-color: var(--crust);
247
+ }
248
+
249
+ fieldset span.text-gray-500,
250
+ .gr-block.gr-box span.text-gray-500,
251
+ label.block span {
252
+ box-shadow: unset;
253
+ }
254
+
255
+ .dark .text-gray-500, .text-gray-500 {
256
+ color: var(--text);
257
+ }
258
+
259
+ .dark fieldset span.text-gray-500, fieldset span.text-gray-500,
260
+ .dark .gr-block.gr-box, .gr-block.gr-box,
261
+ span.text-gray-500,
262
+ .dark label.block span, label.block span {
263
+ background-color: transparent;
264
+ border: transparent;
265
+ }
266
+
267
+ .dark .text-gray-700, .text-gray-700,
268
+ .dark .text-gray-800, .text-gray-800,
269
+ .dark .text-gray-900, .text-gray-900,
270
+ .dark .\!text-gray-700, .\!text-gray-700,
271
+ .dark .\!text-gray-800, .\!text-gray-800 {
272
+ color: var(--text);
273
+ }
274
+
275
+ #txt2img_settings > div {
276
+ margin-top: 2vh;
277
+ flex-grow: 0;
278
+ min-width: 30%;
279
+ }
280
+
281
+ #tabs > :first-child {
282
+ background-color: var(--crust);
283
+ }
284
+
285
+ #tabs{
286
+ background-color: var(--mantle);
287
+ }
288
+
289
+ #tab_txt2img > div {
290
+ background-color: var(--mantle);
291
+ }
292
+
293
+ #tabs > div{
294
+ border-width: 0px !important;
295
+ border-color:var(--surface0);
296
+ }
297
+
298
+ #tabs > div:nth-child(1) {
299
+ flex-wrap: wrap-reverse;
300
+ background-color: var(--crust);
301
+ }
302
+ .tabs > :first-child {
303
+ border: none !important;
304
+ margin-bottom: -1px;
305
+ gap: 3px 0px;
306
+ background-color: var(--mantle);
307
+ padding-top: 5px;
308
+ z-index: 10;
309
+ }
310
+
311
+ #img2img_img2img_tab {
312
+ border-width: 0px !important;
313
+ }
314
+
315
+ #mode_img2img > div:nth-child(1) > .bg-white {
316
+ background-color: var(--base);
317
+ }
318
+
319
+ #tab_extensions table td, #tab_extensions table th {
320
+ border: 1px solid var(--surface0);
321
+ }
322
+
323
+ #extras_resize_mode > :first-child {
324
+ background-color: var(--base);
325
+ }
326
+
327
+ #extras_resize_mode > :not(:first-child) {
328
+ background-color: var(--mantle) !important;
329
+ padding-top: 20px;
330
+ border-color: transparent;
331
+ border-radius: 0px 10px 10px 10px;
332
+ margin-bottom: 20px;
333
+
334
+ }
335
+
336
+ .tabs > :first-child > button {
337
+ border-radius: 8px 8px 0px 0px;
338
+ /* outline: 1px solid var(--base) !important; */
339
+ border-color: var(--surface0);
340
+ border-width: 0px;
341
+ border-bottom-width: 0px;
342
+ }
343
+
344
+
345
+ #quicksettings {
346
+ background-color: transparent;
347
+ }
348
+
349
+ input[type="range"]::-ms-track {
350
+ background: transparent;
351
+ }
352
+
353
+ input[type="range"]::-ms-fill-lower {
354
+ background: var(--accent);
355
+ border-radius: 10px;
356
+ }
357
+ input[type="range"]::-ms-fill-upper {
358
+ background: var(--overlay0);
359
+ border-radius: 10px;
360
+ }
361
+
362
+ input[type="range"]:focus::-ms-fill-lower {
363
+ background: var(--accent);
364
+ }
365
+ input[type="range"]:focus::-ms-fill-upper {
366
+ background: var(--overlay0);
367
+ }
368
+
369
+ /* Chrome, Safari, Edge, Opera */
370
+ input::-webkit-outer-spin-button,
371
+ input::-webkit-inner-spin-button {
372
+ -webkit-appearance: none;
373
+ margin: 0;
374
+ }
375
+
376
+ /* Firefox */
377
+ input[type="number"] {
378
+ -moz-appearance: textfield;
379
+ }
380
+ .gr-box > div > div > input.gr-text-input {
381
+ width: 4em;
382
+ }
383
+
384
+ .progressDiv .progress {
385
+ background: var(--accent);
386
+ color: var(--shadow);
387
+ }
388
+
389
+ .dark .progressDiv, .progressDiv {
390
+ background-color: var(--surface0);
391
+ }
392
+
393
+ input[type="range"] {
394
+ font-size: 1.5rem;
395
+ }
396
+
397
+ input[type="range"] {
398
+ color: var(--accent);
399
+ --thumb-height: 0.5em;
400
+ --track-height: 0.125em;
401
+ --track-color: var(--surface0);
402
+ --brightness-hover: 130%;
403
+ --brightness-down: 80%;
404
+ --clip-edges: 0.125em;
405
+ }
406
+
407
+ input[type="range"].win10-thumb {
408
+ color: var(--accent);
409
+
410
+ --thumb-height: 0.5em;
411
+ --thumb-width: 0.5em;
412
+ --clip-edges: 0.0125em;
413
+ }
414
+
415
+ @media (prefers-color-scheme: dark) {
416
+ input[type="range"] {
417
+ color: var(--accent);
418
+ --track-color: var(--surface0);
419
+ }
420
+
421
+ input[type="range"].win10-thumb {
422
+ color: var(--accent);
423
+ }
424
+ }
425
+
426
+ /* === range commons === */
427
+ input[type="range"] {
428
+ position: relative;
429
+ background: #fff0;
430
+ overflow: hidden;
431
+ }
432
+
433
+ input[type="range"]:active {
434
+ cursor: grabbing;
435
+ }
436
+
437
+ input[type="range"]:disabled {
438
+ filter: grayscale(1);
439
+ opacity: 0.3;
440
+ cursor: not-allowed;
441
+ }
442
+
443
+ /* === WebKit specific styles === */
444
+ input[type="range"],
445
+ input[type="range"]::-webkit-slider-runnable-track,
446
+ input[type="range"]::-webkit-slider-thumb {
447
+ -webkit-appearance: none;
448
+ transition: all ease 100ms;
449
+ height: var(--thumb-height);
450
+ }
451
+
452
+ input[type="range"]::-webkit-slider-runnable-track,
453
+ input[type="range"]::-webkit-slider-thumb {
454
+ position: relative;
455
+ }
456
+
457
+ input[type="range"]::-webkit-slider-thumb {
458
+ --thumb-radius: calc((var(--thumb-height) * 0.5) - 1px);
459
+ --clip-top: calc((var(--thumb-height) - var(--track-height)) * 0.5 - 0.5px);
460
+ --clip-bottom: calc(var(--thumb-height) - var(--clip-top));
461
+ --clip-further: calc(100% + 1px);
462
+ --box-fill: calc(-100vmax - var(--thumb-width, var(--thumb-height))) 0 0 100vmax currentColor;
463
+
464
+ width: var(--thumb-width, var(--thumb-height));
465
+ background: linear-gradient(currentColor 0 0) scroll no-repeat left center / 50% calc(var(--track-height) + 1px);
466
+ background-color: currentColor;
467
+ box-shadow: var(--box-fill);
468
+ border-radius: var(--thumb-width, var(--thumb-height));
469
+
470
+ filter: brightness(100%);
471
+ clip-path: polygon(
472
+ 100% -1px,
473
+ var(--clip-edges) -1px,
474
+ 0 var(--clip-top),
475
+ -100vmax var(--clip-top),
476
+ -100vmax var(--clip-bottom),
477
+ 0 var(--clip-bottom),
478
+ var(--clip-edges) 100%,
479
+ var(--clip-further) var(--clip-further)
480
+ );
481
+ }
482
+
483
+ input[type="range"]:hover::-webkit-slider-thumb {
484
+ filter: brightness(var(--brightness-hover));
485
+ cursor: grab;
486
+ }
487
+
488
+ input[type="range"]:active::-webkit-slider-thumb {
489
+ filter: brightness(var(--brightness-down));
490
+ cursor: grabbing;
491
+ }
492
+
493
+ input[type="range"]::-webkit-slider-runnable-track {
494
+ background: linear-gradient(var(--track-color) 0 0) scroll no-repeat center / 100% calc(var(--track-height) + 1px);
495
+ }
496
+
497
+ input[type="range"]:disabled::-webkit-slider-thumb {
498
+ cursor: not-allowed;
499
+ }
500
+
501
+ /* === Firefox specific styles === */
502
+ input[type="range"],
503
+ input[type="range"]::-moz-range-track,
504
+ input[type="range"]::-moz-range-thumb {
505
+ appearance: none;
506
+ transition: all ease 100ms;
507
+ height: var(--thumb-height);
508
+ }
509
+
510
+ input[type="range"]::-moz-range-track,
511
+ input[type="range"]::-moz-range-thumb,
512
+ input[type="range"]::-moz-range-progress {
513
+ background: #fff0;
514
+ }
515
+
516
+ input[type="range"]::-moz-range-thumb {
517
+ background: currentColor;
518
+ border: 0;
519
+ width: var(--thumb-width, var(--thumb-height));
520
+ border-radius: var(--thumb-width, var(--thumb-height));
521
+ cursor: grab;
522
+ }
523
+
524
+ input[type="range"]:active::-moz-range-thumb {
525
+ cursor: grabbing;
526
+ }
527
+
528
+ input[type="range"]::-moz-range-track {
529
+ width: 100%;
530
+ background: var(--track-color);
531
+ }
532
+
533
+ input[type="range"]::-moz-range-progress {
534
+ appearance: none;
535
+ background: currentColor;
536
+ transition-delay: 30ms;
537
+ }
538
+
539
+ input[type="range"]::-moz-range-track,
540
+ input[type="range"]::-moz-range-progress {
541
+ height: calc(var(--track-height) + 1px);
542
+ border-radius: var(--track-height);
543
+ }
544
+
545
+ input[type="range"]::-moz-range-thumb,
546
+ input[type="range"]::-moz-range-progress {
547
+ filter: brightness(100%);
548
+ }
549
+
550
+ input[type="range"]:hover::-moz-range-thumb,
551
+ input[type="range"]:hover::-moz-range-progress {
552
+ filter: brightness(var(--brightness-hover));
553
+ }
554
+
555
+ input[type="range"]:active::-moz-range-thumb,
556
+ input[type="range"]:active::-moz-range-progress {
557
+ filter: brightness(var(--brightness-down));
558
+ }
559
+
560
+ input[type="range"]:disabled::-moz-range-thumb {
561
+ cursor: not-allowed;
562
+ }
563
+
564
+ /* all of the input range stuff is from this guy*/
565
+ /* Shout out to them https://codepen.io/ShadowShahriar/pen/zYPPYrQ */
SD-catppuccin-main/flavors/mocha.css ADDED
@@ -0,0 +1,567 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :root,
2
+ *,
3
+ #context-menu {
4
+ --rosewater: #f5e0dc;
5
+ --flamingo: #f2cdcd;
6
+ --pink: #f5c2e7;
7
+ --mauve: #cba6f7;
8
+ --red: #f38ba8;
9
+ --maroon: #eba0ac;
10
+ --peach: #fab387;
11
+ --yellow: #f9e2af;
12
+ --green: #a6e3a1;
13
+ --teal: #94e2d5;
14
+ --sky: #89dceb;
15
+ --sapphire: #74c7ec;
16
+ --lavender: #b4befe;
17
+ --blue: #89b4fa;
18
+ --text: #cdd6f4;
19
+ --subtext1: #bac2de;
20
+ --subtext0: #a6adc8;
21
+ --overlay2: #9399b2;
22
+ --overlay1: #7f849c;
23
+ --overlay0: #6c7086;
24
+ --surface2: #585b70;
25
+ --surface1: #45475a;
26
+ --surface0: #313244;
27
+ --base: #1e1e2e;
28
+ --mantle: #181825;
29
+ --crust: #11111b;
30
+ --shadow: #010409;
31
+ --accent: var(--maroon);
32
+ color-scheme: dark;
33
+ }
34
+
35
+ select, option {
36
+ background-color: var(--base);
37
+ }
38
+
39
+ #setting_sd_model_checkpoint > :first-child{
40
+ background-color: var(--base);
41
+ }
42
+
43
+ #txt2img_prompt_container,
44
+ #img2img_prompt_container {
45
+ background-color: var(--mantle);
46
+ }
47
+
48
+
49
+ .dark .bg-white\/90, .bg-white\/90 {
50
+ background-color: var(--base);
51
+ }
52
+
53
+ .dark fieldset span.text-gray-500, fieldset span.text-gray-500,
54
+ .dark .gr-block.gr-box span.text-gray-500, .gr-block.gr-box span.text-gray-500,
55
+ .dark label.block span, label.block span {
56
+ background-color: var(--base);
57
+ border: transparent;
58
+ }
59
+
60
+ .dark .dark\:text-gray-200, .\:text-gray-200{
61
+ color: var(--text);
62
+ }
63
+
64
+ .dark .dark\:bg-gray-950, .\:bg-gray-950 {
65
+ background-color: var(--crust);
66
+ }
67
+
68
+ .dark .dark\:bg-gray-900, .\:bg-gray-900 {
69
+ background-color: var(--base);
70
+ border-radius: 10px;
71
+ }
72
+
73
+ .dark .dark\:border-gray-700, .\:border-gray-700 {
74
+ border-color: var(--surface0);
75
+ }
76
+
77
+ .dark .gr-panel, .gr-panel {
78
+ background-color: var(--mantle);
79
+ }
80
+
81
+
82
+ textarea, .gr-text-input {
83
+ background-color: var(--base) !important;
84
+ }
85
+
86
+ .dark .bg-white, .bg-white {
87
+ background-color: var(--mantle);
88
+ }
89
+
90
+ .dark .gr-compact, .gr-compact {
91
+ background-color: var(--base);
92
+ }
93
+
94
+ .dark .gr-input, .gr-input {
95
+ border-color: var(--surface0);
96
+ }
97
+ .dark .gr-form, .gr-form,
98
+ .dark .gr-box, .gr-box {
99
+ background-color: transparent;
100
+ color: var(--text);
101
+ }
102
+ .dark .gr-check-radio, .gr-check-radio {
103
+ background-color: var(--base);
104
+ }
105
+
106
+ .dark .gr-check-radio:focus, .gr-check-radio:focus,
107
+ .dark .gr-check-radio:checked, .gr-check-radio:checked {
108
+ background-color: var(--accent);
109
+ }
110
+
111
+ .dark .gr-button-primary:hover, .gr-button-primary:hover {
112
+ filter: brightness(130%);
113
+ }
114
+ .dark .gr-button-primary, .gr-button-primary {
115
+ background-color: var(--accent) !important;
116
+ color: var(--shadow)
117
+ }
118
+
119
+
120
+ .dark .gr-button-secondary:hover, .gr-button-secondary:hover {
121
+ filter: brightness(120%);
122
+ }
123
+
124
+ button, input, optgroup, select, textarea {
125
+ color: var(--accent);
126
+ }
127
+
128
+ .dark .gr-input-label, .gr-input-label,
129
+ .dark .gr-button-secondary,.gr-button-secondary,
130
+ .gr-input-label,
131
+ .gr-button-secondary {
132
+ --tw-gradient-from: none;
133
+ --tw-gradient-to: none;
134
+ --tw-gradient-stops: none;
135
+ background-color: var(--base);
136
+ color: var(--text)
137
+ }
138
+
139
+ .gr-button,
140
+ .dark .gr-button {
141
+ border-color:var(--surface0);
142
+ background-color: var(--base);
143
+ background-image: unset;
144
+ }
145
+
146
+
147
+ .livePreview {
148
+ background-color: var(--base) !important;
149
+ height: 60vh !important;
150
+ width: 100% !important;
151
+ border-radius: 10px !important;
152
+ }
153
+
154
+ .gr-padded {
155
+ padding: .825rem .75rem;
156
+ }
157
+
158
+
159
+ #mode_extras > :first-child > .bg-white {
160
+ background-color: var(--base);
161
+ }
162
+
163
+ #interrogate_col {
164
+ justify-content: center;
165
+ gap: 10px;
166
+ /* background: var(--base); */
167
+ /* border-top-left-radius: 10px !important; */
168
+ /* border-top-right-radius: 10px !important; */
169
+ /* padding-top: 20px; */
170
+ }
171
+
172
+ #txt2img_toprow,
173
+ #img2img_toprow {
174
+ background-color: unset;
175
+ }
176
+
177
+ #txt2img_actions_column, #img2img_actions_column {
178
+ padding: 10px;
179
+ margin: 5px;
180
+ border-radius: 10px !important;
181
+ background-color: var(--base);
182
+ }
183
+
184
+ #img_inpaint_mask > div:nth-child(3),
185
+ #img_inpaint_base > div:nth-child(3){
186
+ border-width: 1px;
187
+ border-color:var(--surface0);
188
+
189
+ }
190
+
191
+ #img2img_settings {
192
+ border-radius: 10px;
193
+ }
194
+
195
+ #mode_img2img > :not(:first-child) {
196
+ border-width: 0px;
197
+ }
198
+
199
+
200
+ #txt2img_gallery,
201
+ #img2img_gallery,
202
+ #extras_gallery {
203
+ background-color: var(--base) !important;
204
+ }
205
+
206
+ #img2img_copy_to_img2img > :not(:first-child) {
207
+ border-width: 1px !important;
208
+ border-color: var(--surface0) !important;
209
+ border-radius: 10px !important;
210
+ margin-left: 10px;
211
+ }
212
+
213
+ #txt2img_interrupt, #img2img_interrupt {
214
+ background-color: var(--red) !important;
215
+ color: var(--mantle);
216
+ }
217
+
218
+ #txt2img_skip, #img2img_skip {
219
+ background-color: var(--maroon) !important;
220
+ color: var(--mantle);
221
+ }
222
+
223
+ #txt2img_batch_count,
224
+ #txt2img_width {
225
+ margin-bottom: 0.625vw;
226
+ }
227
+
228
+ #txt2img_script_container > div > div {
229
+ margin: 0px 1vh 0.9vw 1vh;
230
+ }
231
+
232
+ #txt2img_script_container:last-child > div{
233
+ margin: unset;
234
+ }
235
+
236
+ .boder,
237
+ .dark .border, .border,
238
+ .dark .border-gray-100, .border-gray-100,
239
+ .dark .border-gray-200, .border-gray-200,
240
+ .dark .border-gray-300, .border-gray-300,
241
+ .dark .\!border, .\!border,
242
+ .dark .\!border-gray-300, .\!border-gray-300 {
243
+ border-color: var(--surface0);
244
+ }
245
+
246
+
247
+ .container {
248
+ background-color: var(--crust);
249
+ }
250
+
251
+ fieldset span.text-gray-500,
252
+ .gr-block.gr-box span.text-gray-500,
253
+ label.block span {
254
+ box-shadow: unset;
255
+ }
256
+
257
+ .dark .text-gray-500, .text-gray-500 {
258
+ color: var(--text);
259
+ }
260
+
261
+ .dark fieldset span.text-gray-500, fieldset span.text-gray-500,
262
+ .dark .gr-block.gr-box, .gr-block.gr-box,
263
+ span.text-gray-500,
264
+ .dark label.block span, label.block span {
265
+ background-color: transparent;
266
+ border: transparent;
267
+ }
268
+
269
+ .dark .text-gray-700, .text-gray-700,
270
+ .dark .text-gray-800, .text-gray-800,
271
+ .dark .text-gray-900, .text-gray-900,
272
+ .dark .\!text-gray-700, .\!text-gray-700,
273
+ .dark .\!text-gray-800, .\!text-gray-800 {
274
+ color: var(--text);
275
+ }
276
+
277
+ #txt2img_settings > div {
278
+ margin-top: 2vh;
279
+ flex-grow: 0;
280
+ min-width: 30%;
281
+ }
282
+
283
+ #tabs > :first-child {
284
+ background-color: var(--crust);
285
+ }
286
+
287
+ #tabs{
288
+ background-color: var(--mantle);
289
+ }
290
+
291
+ #tab_txt2img > div {
292
+ background-color: var(--mantle);
293
+ }
294
+
295
+ #tabs > div{
296
+ border-width: 0px !important;
297
+ border-color:var(--surface0);
298
+ }
299
+
300
+ #tabs > div:nth-child(1) {
301
+ flex-wrap: wrap-reverse;
302
+ background-color: var(--crust);
303
+ }
304
+ .tabs > :first-child {
305
+ border: none !important;
306
+ margin-bottom: -1px;
307
+ gap: 3px 0px;
308
+ background-color: var(--mantle);
309
+ padding-top: 5px;
310
+ z-index: 10;
311
+ }
312
+
313
+ #img2img_img2img_tab {
314
+ border-width: 0px !important;
315
+ }
316
+
317
+ #mode_img2img > div:nth-child(1) > .bg-white {
318
+ background-color: var(--base);
319
+ }
320
+
321
+ #tab_extensions table td, #tab_extensions table th {
322
+ border: 1px solid var(--surface0);
323
+ }
324
+
325
+ #extras_resize_mode > :first-child {
326
+ background-color: var(--base);
327
+ }
328
+
329
+ #extras_resize_mode > :not(:first-child) {
330
+ background-color: var(--mantle) !important;
331
+ padding-top: 20px;
332
+ border-color: transparent;
333
+ border-radius: 0px 10px 10px 10px;
334
+ margin-bottom: 20px;
335
+
336
+ }
337
+
338
+ .tabs > :first-child > button {
339
+ border-radius: 8px 8px 0px 0px;
340
+ /* outline: 1px solid var(--base) !important; */
341
+ border-color: var(--surface0);
342
+ border-width: 0px;
343
+ border-bottom-width: 0px;
344
+ }
345
+
346
+
347
+ #quicksettings {
348
+ background-color: transparent;
349
+ }
350
+
351
+ input[type="range"]::-ms-track {
352
+ background: transparent;
353
+ }
354
+
355
+ input[type="range"]::-ms-fill-lower {
356
+ background: var(--accent);
357
+ border-radius: 10px;
358
+ }
359
+ input[type="range"]::-ms-fill-upper {
360
+ background: var(--overlay0);
361
+ border-radius: 10px;
362
+ }
363
+
364
+ input[type="range"]:focus::-ms-fill-lower {
365
+ background: var(--accent);
366
+ }
367
+ input[type="range"]:focus::-ms-fill-upper {
368
+ background: var(--overlay0);
369
+ }
370
+
371
+ /* Chrome, Safari, Edge, Opera */
372
+ input::-webkit-outer-spin-button,
373
+ input::-webkit-inner-spin-button {
374
+ -webkit-appearance: none;
375
+ margin: 0;
376
+ }
377
+
378
+ /* Firefox */
379
+ input[type="number"] {
380
+ -moz-appearance: textfield;
381
+ }
382
+ .gr-box > div > div > input.gr-text-input {
383
+ width: 4em;
384
+ }
385
+
386
+ .progressDiv .progress {
387
+ background: var(--accent);
388
+ color: var(--shadow);
389
+ }
390
+
391
+ .dark .progressDiv, .progressDiv {
392
+ background-color: var(--surface0);
393
+ }
394
+
395
+ input[type="range"] {
396
+ font-size: 1.5rem;
397
+ }
398
+
399
+ input[type="range"] {
400
+ color: var(--accent);
401
+ --thumb-height: 0.5em;
402
+ --track-height: 0.125em;
403
+ --track-color: var(--surface0);
404
+ --brightness-hover: 130%;
405
+ --brightness-down: 80%;
406
+ --clip-edges: 0.125em;
407
+ }
408
+
409
+ input[type="range"].win10-thumb {
410
+ color: var(--accent);
411
+
412
+ --thumb-height: 0.5em;
413
+ --thumb-width: 0.5em;
414
+ --clip-edges: 0.0125em;
415
+ }
416
+
417
+ @media (prefers-color-scheme: dark) {
418
+ input[type="range"] {
419
+ color: var(--accent);
420
+ --track-color: var(--surface0);
421
+ }
422
+
423
+ input[type="range"].win10-thumb {
424
+ color: var(--accent);
425
+ }
426
+ }
427
+
428
+ /* === range commons === */
429
+ input[type="range"] {
430
+ position: relative;
431
+ background: #fff0;
432
+ overflow: hidden;
433
+ }
434
+
435
+ input[type="range"]:active {
436
+ cursor: grabbing;
437
+ }
438
+
439
+ input[type="range"]:disabled {
440
+ filter: grayscale(1);
441
+ opacity: 0.3;
442
+ cursor: not-allowed;
443
+ }
444
+
445
+ /* === WebKit specific styles === */
446
+ input[type="range"],
447
+ input[type="range"]::-webkit-slider-runnable-track,
448
+ input[type="range"]::-webkit-slider-thumb {
449
+ -webkit-appearance: none;
450
+ transition: all ease 100ms;
451
+ height: var(--thumb-height);
452
+ }
453
+
454
+ input[type="range"]::-webkit-slider-runnable-track,
455
+ input[type="range"]::-webkit-slider-thumb {
456
+ position: relative;
457
+ }
458
+
459
+ input[type="range"]::-webkit-slider-thumb {
460
+ --thumb-radius: calc((var(--thumb-height) * 0.5) - 1px);
461
+ --clip-top: calc((var(--thumb-height) - var(--track-height)) * 0.5 - 0.5px);
462
+ --clip-bottom: calc(var(--thumb-height) - var(--clip-top));
463
+ --clip-further: calc(100% + 1px);
464
+ --box-fill: calc(-100vmax - var(--thumb-width, var(--thumb-height))) 0 0 100vmax currentColor;
465
+
466
+ width: var(--thumb-width, var(--thumb-height));
467
+ background: linear-gradient(currentColor 0 0) scroll no-repeat left center / 50% calc(var(--track-height) + 1px);
468
+ background-color: currentColor;
469
+ box-shadow: var(--box-fill);
470
+ border-radius: var(--thumb-width, var(--thumb-height));
471
+
472
+ filter: brightness(100%);
473
+ clip-path: polygon(
474
+ 100% -1px,
475
+ var(--clip-edges) -1px,
476
+ 0 var(--clip-top),
477
+ -100vmax var(--clip-top),
478
+ -100vmax var(--clip-bottom),
479
+ 0 var(--clip-bottom),
480
+ var(--clip-edges) 100%,
481
+ var(--clip-further) var(--clip-further)
482
+ );
483
+ }
484
+
485
+ input[type="range"]:hover::-webkit-slider-thumb {
486
+ filter: brightness(var(--brightness-hover));
487
+ cursor: grab;
488
+ }
489
+
490
+ input[type="range"]:active::-webkit-slider-thumb {
491
+ filter: brightness(var(--brightness-down));
492
+ cursor: grabbing;
493
+ }
494
+
495
+ input[type="range"]::-webkit-slider-runnable-track {
496
+ background: linear-gradient(var(--track-color) 0 0) scroll no-repeat center / 100% calc(var(--track-height) + 1px);
497
+ }
498
+
499
+ input[type="range"]:disabled::-webkit-slider-thumb {
500
+ cursor: not-allowed;
501
+ }
502
+
503
+ /* === Firefox specific styles === */
504
+ input[type="range"],
505
+ input[type="range"]::-moz-range-track,
506
+ input[type="range"]::-moz-range-thumb {
507
+ appearance: none;
508
+ transition: all ease 100ms;
509
+ height: var(--thumb-height);
510
+ }
511
+
512
+ input[type="range"]::-moz-range-track,
513
+ input[type="range"]::-moz-range-thumb,
514
+ input[type="range"]::-moz-range-progress {
515
+ background: #fff0;
516
+ }
517
+
518
+ input[type="range"]::-moz-range-thumb {
519
+ background: currentColor;
520
+ border: 0;
521
+ width: var(--thumb-width, var(--thumb-height));
522
+ border-radius: var(--thumb-width, var(--thumb-height));
523
+ cursor: grab;
524
+ }
525
+
526
+ input[type="range"]:active::-moz-range-thumb {
527
+ cursor: grabbing;
528
+ }
529
+
530
+ input[type="range"]::-moz-range-track {
531
+ width: 100%;
532
+ background: var(--track-color);
533
+ }
534
+
535
+ input[type="range"]::-moz-range-progress {
536
+ appearance: none;
537
+ background: currentColor;
538
+ transition-delay: 30ms;
539
+ }
540
+
541
+ input[type="range"]::-moz-range-track,
542
+ input[type="range"]::-moz-range-progress {
543
+ height: calc(var(--track-height) + 1px);
544
+ border-radius: var(--track-height);
545
+ }
546
+
547
+ input[type="range"]::-moz-range-thumb,
548
+ input[type="range"]::-moz-range-progress {
549
+ filter: brightness(100%);
550
+ }
551
+
552
+ input[type="range"]:hover::-moz-range-thumb,
553
+ input[type="range"]:hover::-moz-range-progress {
554
+ filter: brightness(var(--brightness-hover));
555
+ }
556
+
557
+ input[type="range"]:active::-moz-range-thumb,
558
+ input[type="range"]:active::-moz-range-progress {
559
+ filter: brightness(var(--brightness-down));
560
+ }
561
+
562
+ input[type="range"]:disabled::-moz-range-thumb {
563
+ cursor: not-allowed;
564
+ }
565
+
566
+ /* all of the input range stuff is from this guy*/
567
+ /* Shout out to them https://codepen.io/ShadowShahriar/pen/zYPPYrQ */
SD-catppuccin-main/scripts/main.py ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import re
3
+ import shutil
4
+ import gradio as gr
5
+ from modules import script_callbacks
6
+ from modules import shared, scripts
7
+ import modules.scripts as scripts
8
+
9
+ accents = ['rosewater', 'flamingo', 'pink' , 'mauve' ,'red', 'maroon' ,'peach', 'yellow', 'green', 'teal', 'sky', 'blue', 'sapphire', 'lavender']
10
+ flavors = ['latte', 'frappe', 'macchiato', 'mocha']
11
+ script_path = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
12
+
13
+ def on_ui_settings():
14
+ section = ('ctp', 'Catppuccin Theme')
15
+ shared.opts.add_option("ctp_flavor",
16
+ shared.OptionInfo(
17
+ default='mocha',
18
+ label="Catppuccin Flavor",
19
+ component=gr.Radio,
20
+ component_args={"choices": flavors},
21
+ onchange=on_ui_settings_change,
22
+ section=section))
23
+
24
+ shared.opts.add_option("accent_color",
25
+ shared.OptionInfo(
26
+ default='maroon',
27
+ label='Accent',
28
+ component=gr.Radio,
29
+ component_args={"choices": accents},
30
+ onchange=on_accent_color_change,
31
+ section=section
32
+ ))
33
+
34
+ def on_accent_color_change():
35
+ pattern = re.compile(r"--accent:\s*(.*)")
36
+ # replace the accent color
37
+ with open(os.path.join(script_path,'style.css'), "r+") as file:
38
+ text = re.sub(pattern, f'--accent: var(--{shared.opts.accent_color});', file.read(), count=1)
39
+ file.seek(0)
40
+ file.write(text)
41
+ file.truncate()
42
+
43
+ def on_ui_settings_change():
44
+ # Move css over
45
+ shutil.copy(os.path.join(script_path,f'flavors/{shared.opts.ctp_flavor}.css'), os.path.join(script_path, 'style.css'))
46
+
47
+ # reappply accent color
48
+ on_accent_color_change()
49
+
50
+ script_callbacks.on_ui_settings(on_ui_settings)
SD-catppuccin-main/style.css ADDED
@@ -0,0 +1,565 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ :root,
2
+ *,
3
+ #context-menu {
4
+ --rosewater: #f5e0dc;
5
+ --flamingo: #f2cdcd;
6
+ --pink: #f5c2e7;
7
+ --mauve: #cba6f7;
8
+ --red: #f38ba8;
9
+ --maroon: #eba0ac;
10
+ --peach: #fab387;
11
+ --yellow: #f9e2af;
12
+ --green: #a6e3a1;
13
+ --teal: #94e2d5;
14
+ --sky: #89dceb;
15
+ --sapphire: #74c7ec;
16
+ --lavender: #b4befe;
17
+ --blue: #89b4fa;
18
+ --text: #cdd6f4;
19
+ --subtext1: #bac2de;
20
+ --subtext0: #a6adc8;
21
+ --overlay2: #9399b2;
22
+ --overlay1: #7f849c;
23
+ --overlay0: #6c7086;
24
+ --surface2: #585b70;
25
+ --surface1: #45475a;
26
+ --surface0: #313244;
27
+ --base: #1e1e2e;
28
+ --mantle: #181825;
29
+ --crust: #11111b;
30
+ --shadow: #010409;
31
+ --accent: var(--maroon);
32
+ color-scheme: dark;
33
+ }
34
+ select, option {
35
+ background-color: var(--base);
36
+ }
37
+
38
+ #setting_sd_model_checkpoint > :first-child{
39
+ background-color: var(--base);
40
+ }
41
+
42
+ #txt2img_prompt_container,
43
+ #img2img_prompt_container {
44
+ background-color: var(--mantle);
45
+ }
46
+
47
+
48
+ .dark .bg-white\/90, .bg-white\/90 {
49
+ background-color: var(--base);
50
+ }
51
+
52
+ .dark fieldset span.text-gray-500, fieldset span.text-gray-500,
53
+ .dark .gr-block.gr-box span.text-gray-500, .gr-block.gr-box span.text-gray-500,
54
+ .dark label.block span, label.block span {
55
+ background-color: var(--base);
56
+ border: transparent;
57
+ }
58
+
59
+ .dark .dark\:text-gray-200, .\:text-gray-200{
60
+ color: var(--text);
61
+ }
62
+
63
+ .dark .dark\:bg-gray-950, .\:bg-gray-950 {
64
+ background-color: var(--crust);
65
+ }
66
+
67
+ .dark .dark\:bg-gray-900, .\:bg-gray-900 {
68
+ background-color: var(--base);
69
+ border-radius: 10px;
70
+ }
71
+
72
+ .dark .dark\:border-gray-700, .\:border-gray-700 {
73
+ border-color: var(--surface0);
74
+ }
75
+
76
+ .dark .gr-panel, .gr-panel {
77
+ background-color: var(--mantle);
78
+ }
79
+
80
+
81
+ textarea, .gr-text-input {
82
+ background-color: var(--base) !important;
83
+ }
84
+
85
+ .dark .bg-white, .bg-white {
86
+ background-color: var(--mantle);
87
+ }
88
+
89
+ .dark .gr-compact, .gr-compact {
90
+ background-color: var(--base);
91
+ }
92
+
93
+ .dark .gr-input, .gr-input {
94
+ border-color: var(--surface0);
95
+ }
96
+ .dark .gr-form, .gr-form,
97
+ .dark .gr-box, .gr-box {
98
+ background-color: transparent;
99
+ color: var(--text);
100
+ }
101
+ .dark .gr-check-radio, .gr-check-radio {
102
+ background-color: var(--base);
103
+ }
104
+
105
+ .dark .gr-check-radio:checked, .gr-check-radio:checked {
106
+ background-color: var(--accent);
107
+ }
108
+
109
+ .dark .gr-button-primary:hover, .gr-button-primary:hover {
110
+ filter: brightness(130%);
111
+ }
112
+ .dark .gr-button-primary, .gr-button-primary {
113
+ background-color: var(--accent) !important;
114
+ color: var(--shadow)
115
+ }
116
+
117
+
118
+ .dark .gr-button-secondary:hover, .gr-button-secondary:hover {
119
+ filter: brightness(120%);
120
+ }
121
+
122
+ button, input, optgroup, select, textarea {
123
+ color: var(--accent);
124
+ }
125
+
126
+ .dark .gr-input-label, .gr-input-label,
127
+ .dark .gr-button-secondary,.gr-button-secondary,
128
+ .gr-input-label,
129
+ .gr-button-secondary {
130
+ --tw-gradient-from: none;
131
+ --tw-gradient-to: none;
132
+ --tw-gradient-stops: none;
133
+ background-color: var(--base);
134
+ color: var(--text)
135
+ }
136
+
137
+ .gr-button,
138
+ .dark .gr-button {
139
+ border-color:var(--surface0);
140
+ background-color: var(--base);
141
+ background-image: unset;
142
+ }
143
+
144
+
145
+ .livePreview {
146
+ background-color: var(--base) !important;
147
+ height: 60vh !important;
148
+ width: 100% !important;
149
+ border-radius: 10px !important;
150
+ }
151
+
152
+ .gr-padded {
153
+ padding: .825rem .75rem;
154
+ }
155
+
156
+
157
+ #mode_extras > :first-child > .bg-white {
158
+ background-color: var(--base);
159
+ }
160
+
161
+ #interrogate_col {
162
+ justify-content: center;
163
+ gap: 10px;
164
+ /* background: var(--base); */
165
+ /* border-top-left-radius: 10px !important; */
166
+ /* border-top-right-radius: 10px !important; */
167
+ /* padding-top: 20px; */
168
+ }
169
+
170
+ #txt2img_toprow,
171
+ #img2img_toprow {
172
+ background-color: unset;
173
+ }
174
+
175
+ #txt2img_actions_column, #img2img_actions_column {
176
+ padding: 10px;
177
+ margin: 5px;
178
+ border-radius: 10px !important;
179
+ background-color: var(--base);
180
+ }
181
+
182
+ #img_inpaint_mask > div:nth-child(3),
183
+ #img_inpaint_base > div:nth-child(3){
184
+ border-width: 1px;
185
+ border-color:var(--surface0);
186
+
187
+ }
188
+
189
+ #img2img_settings {
190
+ border-radius: 10px;
191
+ }
192
+
193
+ #mode_img2img > :not(:first-child) {
194
+ border-width: 0px;
195
+ }
196
+
197
+
198
+ #txt2img_gallery,
199
+ #img2img_gallery,
200
+ #extras_gallery {
201
+ background-color: var(--base) !important;
202
+ }
203
+
204
+ #img2img_copy_to_img2img > :not(:first-child) {
205
+ border-width: 1px !important;
206
+ border-color: var(--surface0) !important;
207
+ border-radius: 10px !important;
208
+ margin-left: 10px;
209
+ }
210
+
211
+ #txt2img_interrupt, #img2img_interrupt {
212
+ background-color: var(--red) !important;
213
+ color: var(--mantle);
214
+ }
215
+
216
+ #txt2img_skip, #img2img_skip {
217
+ background-color: var(--maroon) !important;
218
+ color: var(--mantle);
219
+ }
220
+
221
+ #txt2img_batch_count,
222
+ #txt2img_width {
223
+ margin-bottom: 0.625vw;
224
+ }
225
+
226
+ #txt2img_script_container > div > div {
227
+ margin: 0px 1vh 0.9vw 1vh;
228
+ }
229
+
230
+ #txt2img_script_container:last-child > div{
231
+ margin: unset;
232
+ }
233
+
234
+ .boder,
235
+ .dark .border, .border,
236
+ .dark .border-gray-100, .border-gray-100,
237
+ .dark .border-gray-200, .border-gray-200,
238
+ .dark .border-gray-300, .border-gray-300,
239
+ .dark .\!border, .\!border,
240
+ .dark .\!border-gray-300, .\!border-gray-300 {
241
+ border-color: var(--surface0);
242
+ }
243
+
244
+
245
+ .container {
246
+ background-color: var(--crust);
247
+ }
248
+
249
+ fieldset span.text-gray-500,
250
+ .gr-block.gr-box span.text-gray-500,
251
+ label.block span {
252
+ box-shadow: unset;
253
+ }
254
+
255
+ .dark .text-gray-500, .text-gray-500 {
256
+ color: var(--text);
257
+ }
258
+
259
+ .dark fieldset span.text-gray-500, fieldset span.text-gray-500,
260
+ .dark .gr-block.gr-box, .gr-block.gr-box,
261
+ span.text-gray-500,
262
+ .dark label.block span, label.block span {
263
+ background-color: transparent;
264
+ border: transparent;
265
+ }
266
+
267
+ .dark .text-gray-700, .text-gray-700,
268
+ .dark .text-gray-800, .text-gray-800,
269
+ .dark .text-gray-900, .text-gray-900,
270
+ .dark .\!text-gray-700, .\!text-gray-700,
271
+ .dark .\!text-gray-800, .\!text-gray-800 {
272
+ color: var(--text);
273
+ }
274
+
275
+ #txt2img_settings > div {
276
+ margin-top: 2vh;
277
+ flex-grow: 0;
278
+ min-width: 30%;
279
+ }
280
+
281
+ #tabs > :first-child {
282
+ background-color: var(--crust);
283
+ }
284
+
285
+ #tabs{
286
+ background-color: var(--mantle);
287
+ }
288
+
289
+ #tab_txt2img > div {
290
+ background-color: var(--mantle);
291
+ }
292
+
293
+ #tabs > div{
294
+ border-width: 0px !important;
295
+ border-color:var(--surface0);
296
+ }
297
+
298
+ #tabs > div:nth-child(1) {
299
+ flex-wrap: wrap-reverse;
300
+ background-color: var(--crust);
301
+ }
302
+ .tabs > :first-child {
303
+ border: none !important;
304
+ margin-bottom: -1px;
305
+ gap: 3px 0px;
306
+ background-color: var(--mantle);
307
+ padding-top: 5px;
308
+ z-index: 10;
309
+ }
310
+
311
+ #img2img_img2img_tab {
312
+ border-width: 0px !important;
313
+ }
314
+
315
+ #mode_img2img > div:nth-child(1) > .bg-white {
316
+ background-color: var(--base);
317
+ }
318
+
319
+ #tab_extensions table td, #tab_extensions table th {
320
+ border: 1px solid var(--surface0);
321
+ }
322
+
323
+ #extras_resize_mode > :first-child {
324
+ background-color: var(--base);
325
+ }
326
+
327
+ #extras_resize_mode > :not(:first-child) {
328
+ background-color: var(--mantle) !important;
329
+ padding-top: 20px;
330
+ border-color: transparent;
331
+ border-radius: 0px 10px 10px 10px;
332
+ margin-bottom: 20px;
333
+
334
+ }
335
+
336
+ .tabs > :first-child > button {
337
+ border-radius: 8px 8px 0px 0px;
338
+ /* outline: 1px solid var(--base) !important; */
339
+ border-color: var(--surface0);
340
+ border-width: 0px;
341
+ border-bottom-width: 0px;
342
+ }
343
+
344
+
345
+ #quicksettings {
346
+ background-color: transparent;
347
+ }
348
+
349
+ input[type="range"]::-ms-track {
350
+ background: transparent;
351
+ }
352
+
353
+ input[type="range"]::-ms-fill-lower {
354
+ background: var(--accent);
355
+ border-radius: 10px;
356
+ }
357
+ input[type="range"]::-ms-fill-upper {
358
+ background: var(--overlay0);
359
+ border-radius: 10px;
360
+ }
361
+
362
+ input[type="range"]:focus::-ms-fill-lower {
363
+ background: var(--accent);
364
+ }
365
+ input[type="range"]:focus::-ms-fill-upper {
366
+ background: var(--overlay0);
367
+ }
368
+
369
+ /* Chrome, Safari, Edge, Opera */
370
+ input::-webkit-outer-spin-button,
371
+ input::-webkit-inner-spin-button {
372
+ -webkit-appearance: none;
373
+ margin: 0;
374
+ }
375
+
376
+ /* Firefox */
377
+ input[type="number"] {
378
+ -moz-appearance: textfield;
379
+ }
380
+ .gr-box > div > div > input.gr-text-input {
381
+ width: 4em;
382
+ }
383
+
384
+ .progressDiv .progress {
385
+ background: var(--accent);
386
+ color: var(--shadow);
387
+ }
388
+
389
+ .dark .progressDiv, .progressDiv {
390
+ background-color: var(--surface0);
391
+ }
392
+
393
+ input[type="range"] {
394
+ font-size: 1.5rem;
395
+ }
396
+
397
+ input[type="range"] {
398
+ color: var(--accent);
399
+ --thumb-height: 0.5em;
400
+ --track-height: 0.125em;
401
+ --track-color: var(--surface0);
402
+ --brightness-hover: 130%;
403
+ --brightness-down: 80%;
404
+ --clip-edges: 0.125em;
405
+ }
406
+
407
+ input[type="range"].win10-thumb {
408
+ color: var(--accent);
409
+
410
+ --thumb-height: 0.5em;
411
+ --thumb-width: 0.5em;
412
+ --clip-edges: 0.0125em;
413
+ }
414
+
415
+ @media (prefers-color-scheme: dark) {
416
+ input[type="range"] {
417
+ color: var(--accent);
418
+ --track-color: var(--surface0);
419
+ }
420
+
421
+ input[type="range"].win10-thumb {
422
+ color: var(--accent);
423
+ }
424
+ }
425
+
426
+ /* === range commons === */
427
+ input[type="range"] {
428
+ position: relative;
429
+ background: #fff0;
430
+ overflow: hidden;
431
+ }
432
+
433
+ input[type="range"]:active {
434
+ cursor: grabbing;
435
+ }
436
+
437
+ input[type="range"]:disabled {
438
+ filter: grayscale(1);
439
+ opacity: 0.3;
440
+ cursor: not-allowed;
441
+ }
442
+
443
+ /* === WebKit specific styles === */
444
+ input[type="range"],
445
+ input[type="range"]::-webkit-slider-runnable-track,
446
+ input[type="range"]::-webkit-slider-thumb {
447
+ -webkit-appearance: none;
448
+ transition: all ease 100ms;
449
+ height: var(--thumb-height);
450
+ }
451
+
452
+ input[type="range"]::-webkit-slider-runnable-track,
453
+ input[type="range"]::-webkit-slider-thumb {
454
+ position: relative;
455
+ }
456
+
457
+ input[type="range"]::-webkit-slider-thumb {
458
+ --thumb-radius: calc((var(--thumb-height) * 0.5) - 1px);
459
+ --clip-top: calc((var(--thumb-height) - var(--track-height)) * 0.5 - 0.5px);
460
+ --clip-bottom: calc(var(--thumb-height) - var(--clip-top));
461
+ --clip-further: calc(100% + 1px);
462
+ --box-fill: calc(-100vmax - var(--thumb-width, var(--thumb-height))) 0 0 100vmax currentColor;
463
+
464
+ width: var(--thumb-width, var(--thumb-height));
465
+ background: linear-gradient(currentColor 0 0) scroll no-repeat left center / 50% calc(var(--track-height) + 1px);
466
+ background-color: currentColor;
467
+ box-shadow: var(--box-fill);
468
+ border-radius: var(--thumb-width, var(--thumb-height));
469
+
470
+ filter: brightness(100%);
471
+ clip-path: polygon(
472
+ 100% -1px,
473
+ var(--clip-edges) -1px,
474
+ 0 var(--clip-top),
475
+ -100vmax var(--clip-top),
476
+ -100vmax var(--clip-bottom),
477
+ 0 var(--clip-bottom),
478
+ var(--clip-edges) 100%,
479
+ var(--clip-further) var(--clip-further)
480
+ );
481
+ }
482
+
483
+ input[type="range"]:hover::-webkit-slider-thumb {
484
+ filter: brightness(var(--brightness-hover));
485
+ cursor: grab;
486
+ }
487
+
488
+ input[type="range"]:active::-webkit-slider-thumb {
489
+ filter: brightness(var(--brightness-down));
490
+ cursor: grabbing;
491
+ }
492
+
493
+ input[type="range"]::-webkit-slider-runnable-track {
494
+ background: linear-gradient(var(--track-color) 0 0) scroll no-repeat center / 100% calc(var(--track-height) + 1px);
495
+ }
496
+
497
+ input[type="range"]:disabled::-webkit-slider-thumb {
498
+ cursor: not-allowed;
499
+ }
500
+
501
+ /* === Firefox specific styles === */
502
+ input[type="range"],
503
+ input[type="range"]::-moz-range-track,
504
+ input[type="range"]::-moz-range-thumb {
505
+ appearance: none;
506
+ transition: all ease 100ms;
507
+ height: var(--thumb-height);
508
+ }
509
+
510
+ input[type="range"]::-moz-range-track,
511
+ input[type="range"]::-moz-range-thumb,
512
+ input[type="range"]::-moz-range-progress {
513
+ background: #fff0;
514
+ }
515
+
516
+ input[type="range"]::-moz-range-thumb {
517
+ background: currentColor;
518
+ border: 0;
519
+ width: var(--thumb-width, var(--thumb-height));
520
+ border-radius: var(--thumb-width, var(--thumb-height));
521
+ cursor: grab;
522
+ }
523
+
524
+ input[type="range"]:active::-moz-range-thumb {
525
+ cursor: grabbing;
526
+ }
527
+
528
+ input[type="range"]::-moz-range-track {
529
+ width: 100%;
530
+ background: var(--track-color);
531
+ }
532
+
533
+ input[type="range"]::-moz-range-progress {
534
+ appearance: none;
535
+ background: currentColor;
536
+ transition-delay: 30ms;
537
+ }
538
+
539
+ input[type="range"]::-moz-range-track,
540
+ input[type="range"]::-moz-range-progress {
541
+ height: calc(var(--track-height) + 1px);
542
+ border-radius: var(--track-height);
543
+ }
544
+
545
+ input[type="range"]::-moz-range-thumb,
546
+ input[type="range"]::-moz-range-progress {
547
+ filter: brightness(100%);
548
+ }
549
+
550
+ input[type="range"]:hover::-moz-range-thumb,
551
+ input[type="range"]:hover::-moz-range-progress {
552
+ filter: brightness(var(--brightness-hover));
553
+ }
554
+
555
+ input[type="range"]:active::-moz-range-thumb,
556
+ input[type="range"]:active::-moz-range-progress {
557
+ filter: brightness(var(--brightness-down));
558
+ }
559
+
560
+ input[type="range"]:disabled::-moz-range-thumb {
561
+ cursor: not-allowed;
562
+ }
563
+
564
+ /* all of the input range stuff is from this guy*/
565
+ /* Shout out to them https://codepen.io/ShadowShahriar/pen/zYPPYrQ */
SD-huggingface-main/.github/FUNDING.yml ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # These are supported funding model platforms
2
+
3
+ github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4
+ patreon: camenduru
5
+ open_collective: # Replace with a single Open Collective username
6
+ ko_fi: camenduru
7
+ tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8
+ community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9
+ liberapay: # Replace with a single Liberapay username
10
+ issuehunt: # Replace with a single IssueHunt username
11
+ otechie: # Replace with a single Otechie username
12
+ lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
13
+ custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
SD-huggingface-main/LICENSE ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ This is free and unencumbered software released into the public domain.
2
+
3
+ Anyone is free to copy, modify, publish, use, compile, sell, or
4
+ distribute this software, either in source code form or as a compiled
5
+ binary, for any purpose, commercial or non-commercial, and by any
6
+ means.
7
+
8
+ In jurisdictions that recognize copyright laws, the author or authors
9
+ of this software dedicate any and all copyright interest in the
10
+ software to the public domain. We make this dedication for the benefit
11
+ of the public at large and to the detriment of our heirs and
12
+ successors. We intend this dedication to be an overt act of
13
+ relinquishment in perpetuity of all present and future rights to this
14
+ software under copyright law.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ For more information, please refer to <https://unlicense.org>
SD-huggingface-main/README.md ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 🐣 Please follow me for new updates https://twitter.com/camenduru <br />
2
+ 🔥 Please join our discord server https://discord.gg/k5BwmmvJJU
3
+
4
+ # Push to 🤗 Hugging Face
5
+
6
+ ![Push Folder to Hugging Face](https://user-images.githubusercontent.com/54370274/216768707-4efb8a30-6826-409e-8bf1-6e74fc26fdab.jpg)
7
+
8
+ To install it, clone the repo into the `extensions` directory and restart the web ui:
9
+
10
+ `git clone https://github.com/camenduru/stable-diffusion-webui-huggingface`
11
+
12
+ `pip install huggingface-hub==0.11.1`
SD-huggingface-main/install.py ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ import launch
2
+
3
+ if not launch.is_installed("huggingface_hub"):
4
+ launch.run_pip("install huggingface-hub==0.11.0", "requirements for Push to Hugging Face extension")
SD-huggingface-main/scripts/huggingface.py ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import numpy as np
3
+ import gradio as gr
4
+ from huggingface_hub import model_info, create_repo, create_branch, upload_folder, upload_file
5
+ from huggingface_hub.utils import RepositoryNotFoundError, RevisionNotFoundError
6
+ from modules import scripts, script_callbacks
7
+ from subprocess import getoutput
8
+
9
+ def run(command):
10
+ out = getoutput(f"{command}")
11
+ return out
12
+
13
+ def push_folder(folder_from, folder_to, branch, token):
14
+ try:
15
+ repo_exists = True
16
+ r_info = model_info(folder_to, token=token)
17
+ except RepositoryNotFoundError:
18
+ repo_exists = False
19
+ finally:
20
+ if repo_exists:
21
+ print(r_info)
22
+ else:
23
+ create_repo(folder_to, private=True, token=token)
24
+ try:
25
+ branch_exists = True
26
+ b_info = model_info(folder_to, revision=branch, token=token)
27
+ except RevisionNotFoundError:
28
+ branch_exists = False
29
+ finally:
30
+ if branch_exists:
31
+ print(b_info)
32
+ else:
33
+ create_branch(folder_to, branch=branch, token=token)
34
+ upload_folder(folder_path=folder_from, path_in_repo="", revision=branch, repo_id=folder_to, commit_message=f"folder", token=token)
35
+ return "push folder done!"
36
+
37
+ def push_file(file_from, file_to, file_name, branch, token):
38
+ try:
39
+ repo_exists = True
40
+ r_info = model_info(file_to, token=token)
41
+ except RepositoryNotFoundError:
42
+ repo_exists = False
43
+ finally:
44
+ if repo_exists:
45
+ print(r_info)
46
+ else:
47
+ create_repo(file_to, private=True, token=token)
48
+ try:
49
+ branch_exists = True
50
+ b_info = model_info(file_to, revision=branch, token=token)
51
+ except RevisionNotFoundError:
52
+ branch_exists = False
53
+ finally:
54
+ if branch_exists:
55
+ print(b_info)
56
+ else:
57
+ create_branch(file_to, branch=branch, token=token)
58
+ upload_file(path_or_fileobj=file_from, path_in_repo=file_name, revision=branch, repo_id=file_to, commit_message=f"file", token=token)
59
+ return "push file done!"
60
+
61
+ def on_ui_tabs():
62
+ with gr.Blocks() as huggingface:
63
+ gr.Markdown(
64
+ """
65
+ ### Push Folder to 🤗 Hugging Face
66
+ folder_from = 🖼 Windows: C:\\Users\\PC\\Desktop\\MyModelFolder 🐧 Linux: /home/user/app/stable-diffusion-webui/my-model-folder<br />
67
+ folder_to = camenduru/mymodel <br />
68
+ branch = main <br />
69
+ token = get from [https://huggingface.co/settings/tokens](https://huggingface.co/settings/tokens) new token role=write
70
+ """)
71
+ with gr.Group():
72
+ with gr.Box():
73
+ with gr.Row().style(equal_height=True):
74
+ text_folder_from = gr.Textbox(show_label=False, max_lines=1, placeholder="folder_from")
75
+ text_folder_to = gr.Textbox(show_label=False, max_lines=1, placeholder="folder_to")
76
+ text_folder_branch = gr.Textbox(show_label=False, value="main", max_lines=1, placeholder="branch")
77
+ text_folder_token = gr.Textbox(show_label=False, max_lines=1, placeholder="🤗 token")
78
+ out_folder = gr.Textbox(show_label=False)
79
+ with gr.Row().style(equal_height=True):
80
+ btn_push_folder = gr.Button("Push Folder To 🤗")
81
+ btn_push_folder.click(push_folder, inputs=[text_folder_from, text_folder_to, text_folder_branch, text_folder_token], outputs=out_folder)
82
+ gr.Markdown(
83
+ """
84
+ ### Push File to 🤗 Hugging Face
85
+ file_from = 🖼 Windows: C:\\Users\\PC\\Desktop\\MyModelFolder\\model.ckpt 🐧 Linux: /home/user/app/stable-diffusion-webui/my-model-folder/model.ckpt<br />
86
+ file_to = camenduru/mymodel <br />
87
+ file_name = model.ckpt <br />
88
+ branch = main <br />
89
+ token = get from [https://huggingface.co/settings/tokens](https://huggingface.co/settings/tokens) new token role=write
90
+ """)
91
+ with gr.Group():
92
+ with gr.Box():
93
+ with gr.Row().style(equal_height=True):
94
+ text_file_from = gr.Textbox(show_label=False, max_lines=1, placeholder="file_from")
95
+ text_file_to = gr.Textbox(show_label=False, max_lines=1, placeholder="file_to")
96
+ text_file_name = gr.Textbox(show_label=False, max_lines=1, placeholder="file_name")
97
+ text_file_branch = gr.Textbox(show_label=False, value="main", max_lines=1, placeholder="branch")
98
+ text_file_token = gr.Textbox(show_label=False, max_lines=1, placeholder="🤗 token")
99
+ out_file = gr.Textbox(show_label=False)
100
+ with gr.Row().style(equal_height=True):
101
+ btn_push_file = gr.Button("Push File To 🤗")
102
+ btn_push_file.click(push_file, inputs=[text_file_from, text_file_to, text_file_name, text_file_branch, text_file_token], outputs=out_file)
103
+ gr.Markdown(
104
+ """
105
+ ### 🦒 Colab Run Command
106
+ ```py
107
+ model: wget https://huggingface.co/ckpt/anything-v4.5-vae-swapped/resolve/main/anything-v4.5-vae-swapped.safetensors -O /content/stable-diffusion-webui/models/Stable-diffusion/anything-v4.5-vae-swapped.safetensors
108
+ lora: wget https://huggingface.co/embed/Sakimi-Chan_LoRA/resolve/main/Sakimi-Chan_LoRA.safetensors -O /content/stable-diffusion-webui/extensions/sd-webui-additional-networks/models/lora/Sakimi-Chan_LoRA.safetensors
109
+ embed: wget https://huggingface.co/embed/bad_prompt/resolve/main/bad_prompt_version2.pt -O /content/stable-diffusion-webui/embeddings/bad_prompt_version2.pt
110
+ vae: wget https://huggingface.co/ckpt/trinart_characters_19.2m_stable_diffusion_v1/resolve/main/autoencoder_fix_kl-f8-trinart_characters.ckpt -O /content/stable-diffusion-webui/models/VAE/autoencoder_fix_kl-f8-trinart_characters.vae.pt
111
+ zip outputs folder: zip -r /content/outputs.zip /content/stable-diffusion-webui/outputs
112
+ ```
113
+ """)
114
+ with gr.Group():
115
+ with gr.Box():
116
+ command = gr.Textbox(show_label=False, max_lines=1, placeholder="command")
117
+ out_text = gr.Textbox(show_label=False)
118
+ btn_run = gr.Button("run command")
119
+ btn_run.click(run, inputs=command, outputs=out_text)
120
+ return (huggingface, "Hugging Face", "huggingface"),
121
+ script_callbacks.on_ui_tabs(on_ui_tabs)
SD-images-browser-main/.DS_Store ADDED
Binary file (6.15 kB). View file
 
SD-images-browser-main/.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ path_recorder.txt
SD-images-browser-main/README.md ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## stable-diffusion-webui-images-browser
2
+
3
+ A custom extension for [AUTOMATIC1111/stable-diffusion-webui](https://github.com/AUTOMATIC1111/stable-diffusion-webui).
4
+
5
+ This is an image browser for browsing past generated pictures, view their generated informations, send that information to txt2img, img2img and others, collect images to your "favorites" folder and delete the images you no longer need.
6
+
7
+ ## Installation
8
+
9
+ The extension can be installed directly from within the **Extensions** tab within the Webui.
10
+
11
+ You can also install it manually by running the following command from within the webui directory:
12
+
13
+ git clone https://github.com/AlUlkesh/stable-diffusion-webui-images-browser/ extensions/stable-diffusion-webui-images-browser
14
+
15
+ and restart your stable-diffusion-webui, then you can see the new tab "Image Browser".
16
+
17
+ Please be aware that when scanning a directory for the first time, the png-cache will be built. This can take several minutes, depending on the amount of images.
18
+
19
+ ## Recent updates
20
+ - Additional sorting and filtering by EXIF data including .txt file information
21
+ - Recyle bin option
22
+ - Add/Remove from saved directories, via buttons
23
+ - New dropdown with subdirs
24
+ - Option to not show the images from subdirs
25
+ - Refresh button
26
+ - Sort order
27
+ - View and save favorites with individual folder depth
28
+ - Now also supports jpg
29
+
30
+ ## Credit
31
+
32
+ Credit goes to the original maintainer of this extension: https://github.com/yfszzx and to major contributor https://github.com/Klace
SD-images-browser-main/install.py ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ import launch
2
+
3
+ if not launch.is_installed("send2trash"):
4
+ launch.run_pip("install Send2Trash", "requirement for images-browser")
SD-images-browser-main/javascript/images_history.js ADDED
@@ -0,0 +1,234 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var images_history_click_image = function(){
2
+ if (!this.classList?.contains("transform")){
3
+ var gallery = images_history_get_parent_by_class(this, "images_history_cantainor");
4
+ var buttons = gallery.querySelectorAll(".gallery-item");
5
+ var i = 0;
6
+ var hidden_list = [];
7
+ buttons.forEach(function(e){
8
+ if (e.style.display == "none"){
9
+ hidden_list.push(i);
10
+ }
11
+ i += 1;
12
+ })
13
+ if (hidden_list.length > 0){
14
+ setTimeout(images_history_hide_buttons, 10, hidden_list, gallery);
15
+ }
16
+ }
17
+ images_history_set_image_info(this);
18
+ }
19
+
20
+ function images_history_get_parent_by_class(item, class_name){
21
+ var parent = item.parentElement;
22
+ while(!parent.classList.contains(class_name)){
23
+ parent = parent.parentElement;
24
+ }
25
+ return parent;
26
+ }
27
+
28
+ function images_history_get_parent_by_tagname(item, tagname){
29
+ var parent = item.parentElement;
30
+ tagname = tagname.toUpperCase()
31
+ while(parent.tagName != tagname){
32
+ parent = parent.parentElement;
33
+ }
34
+ return parent;
35
+ }
36
+
37
+ function images_history_hide_buttons(hidden_list, gallery){
38
+ var buttons = gallery.querySelectorAll(".gallery-item");
39
+ var num = 0;
40
+ buttons.forEach(function(e){
41
+ if (e.style.display == "none"){
42
+ num += 1;
43
+ }
44
+ });
45
+ if (num == hidden_list.length){
46
+ setTimeout(images_history_hide_buttons, 10, hidden_list, gallery);
47
+ }
48
+ for( i in hidden_list){
49
+ buttons[hidden_list[i]].style.display = "none";
50
+ }
51
+ }
52
+
53
+ function images_history_set_image_info(button){
54
+ var buttons = images_history_get_parent_by_tagname(button, "DIV").querySelectorAll(".gallery-item");
55
+ var index = -1;
56
+ var i = 0;
57
+ buttons.forEach(function(e){
58
+ if(e == button){
59
+ index = i;
60
+ }
61
+ if(e.style.display != "none"){
62
+ i += 1;
63
+ }
64
+ });
65
+ var gallery = images_history_get_parent_by_class(button, "images_history_cantainor");
66
+ var set_btn = gallery.querySelector(".images_history_set_index");
67
+ var curr_idx = set_btn.getAttribute("img_index", index);
68
+ if (curr_idx != index) {
69
+ set_btn.setAttribute("img_index", index);
70
+ }
71
+ set_btn.click();
72
+
73
+ }
74
+
75
+ function images_history_get_current_img(tabname, img_index, page_index){
76
+ return [
77
+ tabname,
78
+ gradioApp().getElementById(tabname + '_images_history_set_index').getAttribute("img_index"),
79
+ page_index
80
+ ];
81
+ }
82
+
83
+ function images_history_delete(del_num, tabname, image_index){
84
+ image_index = parseInt(image_index);
85
+ var tab = gradioApp().getElementById(tabname + '_images_history');
86
+ var set_btn = tab.querySelector(".images_history_set_index");
87
+ var buttons = [];
88
+ tab.querySelectorAll(".gallery-item").forEach(function(e){
89
+ if (e.style.display != 'none'){
90
+ buttons.push(e);
91
+ }
92
+ });
93
+ var img_num = buttons.length / 2;
94
+ del_num = Math.min(img_num - image_index, del_num)
95
+ if (img_num <= del_num){
96
+ setTimeout(function(tabname){
97
+ gradioApp().getElementById(tabname + '_images_history_renew_page').click();
98
+ }, 30, tabname);
99
+ } else {
100
+ var next_img
101
+ for (var i = 0; i < del_num; i++){
102
+ buttons[image_index + i].style.display = 'none';
103
+ buttons[image_index + i + img_num].style.display = 'none';
104
+ next_img = image_index + i + 1
105
+ }
106
+ var btn;
107
+ if (next_img >= img_num){
108
+ btn = buttons[image_index - 1];
109
+ } else {
110
+ btn = buttons[next_img];
111
+ }
112
+ setTimeout(function(btn){btn.click()}, 30, btn);
113
+ }
114
+
115
+ }
116
+
117
+ function images_history_turnpage(tabname){
118
+ var buttons = gradioApp().getElementById(tabname + '_images_history').querySelectorAll(".gallery-item");
119
+ buttons.forEach(function(elem) {
120
+ elem.style.display = 'block';
121
+ });
122
+ }
123
+
124
+ function images_history_init(){
125
+ var tabnames = gradioApp().getElementById("images_history_tabnames_list")
126
+ if (tabnames){
127
+ images_history_tab_list = tabnames.querySelector("textarea").value.split(",")
128
+ for (var i in images_history_tab_list ){
129
+ var tab = images_history_tab_list[i];
130
+ gradioApp().getElementById(tab + '_images_history').classList.add("images_history_cantainor");
131
+ gradioApp().getElementById(tab + '_images_history_set_index').classList.add("images_history_set_index");
132
+ gradioApp().getElementById(tab + '_images_history_del_button').classList.add("images_history_del_button");
133
+ gradioApp().getElementById(tab + '_images_history_gallery').classList.add("images_history_gallery");
134
+ }
135
+
136
+ //preload
137
+ var tab_btns = gradioApp().getElementById("images_history_tab").querySelector("div").querySelectorAll("button");
138
+ for (var i in images_history_tab_list){
139
+ var tabname = images_history_tab_list[i]
140
+ tab_btns[i].setAttribute("tabname", tabname);
141
+ tab_btns[i].addEventListener('click', function(){
142
+ var tabs_box = gradioApp().getElementById("images_history_tab");
143
+ if (!tabs_box.classList.contains(this.getAttribute("tabname"))) {
144
+ gradioApp().getElementById(this.getAttribute("tabname") + "_images_history_renew_page").click();
145
+ tabs_box.classList.add(this.getAttribute("tabname"))
146
+ }
147
+ });
148
+ }
149
+ if (gradioApp().getElementById("images_history_preload").querySelector("input").checked ){
150
+ setTimeout(function(){tab_btns[0].click()}, 100);
151
+ }
152
+
153
+ } else {
154
+ setTimeout(images_history_init, 500);
155
+ }
156
+ }
157
+
158
+ let timer
159
+ var images_history_tab_list = "";
160
+ setTimeout(images_history_init, 500);
161
+ document.addEventListener("DOMContentLoaded", function() {
162
+ var mutationObserver = new MutationObserver(function(m){
163
+ if (images_history_tab_list != ""){
164
+
165
+ for (var i in images_history_tab_list ){
166
+ let tabname = images_history_tab_list[i]
167
+ var buttons = gradioApp().querySelectorAll('#' + tabname + '_images_history .gallery-item');
168
+ buttons.forEach(function(button){
169
+ button.addEventListener('click', images_history_click_image, true);
170
+ document.onkeyup = function(e) {
171
+ if (!checkImageBrowserActive()) {
172
+ return;
173
+ }
174
+ clearTimeout(timer)
175
+ timer = setTimeout(() => {
176
+ var gallery_btn = gradioApp().getElementById(getCurrentTabName() +"_images_history_gallery").getElementsByClassName('gallery-item !flex-none !h-9 !w-9 transition-all duration-75 !ring-2 !ring-orange-500 hover:!ring-orange-500 svelte-1g9btlg');
177
+ gallery_btn = gallery_btn && gallery_btn.length > 0 ? gallery_btn[0] : null;
178
+ if (gallery_btn) {
179
+ images_history_click_image.call(gallery_btn)
180
+ }
181
+ }, 500);
182
+ }
183
+ });
184
+
185
+ var cls_btn = gradioApp().getElementById(tabname + '_images_history_gallery').querySelector("svg");
186
+ if (cls_btn){
187
+ cls_btn.addEventListener('click', function(){
188
+ gradioApp().getElementById(tabname + '_images_history_renew_page').click();
189
+ }, false);
190
+ }
191
+
192
+ }
193
+ }
194
+ });
195
+ mutationObserver.observe(gradioApp(), { childList:true, subtree:true });
196
+ });
197
+
198
+ function getCurrentTabName() {
199
+ var tabs = gradioApp().getElementById("images_history_tab").querySelectorAll('[id$="_images_history_container"]');
200
+
201
+ for (const element of tabs) {
202
+ if (element.style.display === "block") {
203
+ const id = element.id;
204
+ const index = id.indexOf("_images_history_container");
205
+ const tabname = id.substring(0, index);
206
+ return tabname;
207
+ }
208
+ }
209
+ }
210
+
211
+ function checkImageBrowserActive() {
212
+ var ext_active = gradioApp().getElementById("tab_images_history");
213
+ return ext_active && ext_active.style.display !== "none";
214
+ }
215
+
216
+ gradioApp().addEventListener("keydown", function(event) {
217
+ // If we are not on the Image Browser Extension, dont listen for keypresses
218
+ if (!checkImageBrowserActive()) {
219
+ return;
220
+ }
221
+
222
+ // Listens for keypresses 0-5 and updates the corresponding ranking (0 is the last option, None)
223
+ if (event.code >= "Digit0" && event.code <= "Digit5") {
224
+ var selectedValue = event.code.charAt(event.code.length - 1);
225
+ var radioInputs = gradioApp().getElementById( getCurrentTabName() + "_images_ranking").getElementsByTagName("input");
226
+ for (const input of radioInputs) {
227
+ if (input.value === selectedValue || (selectedValue === '0' && input === radioInputs[radioInputs.length - 1])) {
228
+ input.checked = true;
229
+ input.dispatchEvent(new Event("change"));
230
+ break;
231
+ }
232
+ }
233
+ }
234
+ });
SD-images-browser-main/scripts/images_history.py ADDED
@@ -0,0 +1,776 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import json
3
+ import logging
4
+ import os
5
+ import random
6
+ import re
7
+ import shutil
8
+ import stat
9
+ import time
10
+ import modules.extras
11
+ import modules.ui
12
+ from modules import script_callbacks
13
+ from modules import shared, scripts, images
14
+ from modules.shared import opts, cmd_opts
15
+ from modules.ui_common import plaintext_to_html
16
+ from modules.ui_components import ToolButton
17
+ from scripts.wib import wib_db
18
+ from PIL import Image
19
+ from PIL.ExifTags import TAGS
20
+ from PIL.JpegImagePlugin import JpegImageFile
21
+ from PIL.PngImagePlugin import PngImageFile
22
+ from pathlib import Path
23
+ from send2trash import send2trash
24
+ from typing import List, Tuple
25
+
26
+ yappi_do = False
27
+ favorite_tab_name = "Favorites"
28
+ tabs_list = ["txt2img", "img2img", "txt2img-grids", "img2img-grids", "Extras", favorite_tab_name, "Others"] #txt2img-grids and img2img-grids added by HaylockGrant
29
+ num_of_imgs_per_page = 0
30
+ loads_files_num = 0
31
+ image_ext_list = [".png", ".jpg", ".jpeg", ".bmp", ".gif", ".webp"]
32
+ cur_ranking_value="0"
33
+ finfo_aes = {}
34
+ exif_cache = {}
35
+ finfo_exif = {}
36
+ aes_cache = {}
37
+ none_select = "Nothing selected"
38
+ refresh_symbol = '\U0001f504' # 🔄
39
+ up_symbol = '\U000025b2' # ▲
40
+ down_symbol = '\U000025bc' # ▼
41
+ current_depth = 0
42
+ init = True
43
+
44
+ logger = logging.getLogger(__name__)
45
+ logger_mode = logging.ERROR
46
+ if hasattr(opts, "images_logger_warning"):
47
+ if opts.images_logger_warning:
48
+ logger_mode = logging.WARNING
49
+ if hasattr(opts, "images_logger_debug"):
50
+ if opts.images_logger_debug:
51
+ logger_mode = logging.DEBUG
52
+ logger.setLevel(logger_mode)
53
+ console_handler = logging.StreamHandler()
54
+ console_handler.setLevel(logger_mode)
55
+ logger.addHandler(console_handler)
56
+
57
+ def delete_recycle(filename):
58
+ if opts.images_delete_recycle:
59
+ send2trash(filename)
60
+ else:
61
+ os.remove(filename)
62
+ return
63
+
64
+ def img_path_subdirs_get(img_path):
65
+ subdirs = []
66
+ subdirs.append(none_select)
67
+ for item in os.listdir(img_path):
68
+ item_path = os.path.join(img_path, item)
69
+ if os.path.isdir(item_path):
70
+ subdirs.append(item_path)
71
+ return gr.update(choices=subdirs)
72
+
73
+ def img_path_add_remove(img_dir, path_recorder, add_remove, img_path_depth):
74
+ if add_remove == "add" or (add_remove == "remove" and img_dir in path_recorder):
75
+ if add_remove == "add":
76
+ path_recorder[img_dir] = {
77
+ "depth": int(img_path_depth),
78
+ "path_display": f"{img_dir} [{int(img_path_depth)}]"
79
+ }
80
+ wib_db.update_path_recorder(img_dir, path_recorder[img_dir]["depth"], path_recorder[img_dir]["path_display"])
81
+ else:
82
+ del path_recorder[img_dir]
83
+ wib_db.delete_path_recorder(img_dir)
84
+ path_recorder_formatted = [value.get("path_display") for key, value in path_recorder.items()]
85
+ path_recorder_formatted = sorted(path_recorder_formatted, key=lambda x: natural_keys(x.lower()))
86
+
87
+ if add_remove == "remove":
88
+ selected = None
89
+ else:
90
+ selected = path_recorder[img_dir]["path_display"]
91
+ return path_recorder, gr.update(choices=path_recorder_formatted, value=selected)
92
+
93
+ def sort_order_flip(turn_page_switch, sort_order):
94
+ if sort_order == up_symbol:
95
+ sort_order = down_symbol
96
+ else:
97
+ sort_order = up_symbol
98
+ return 1, -turn_page_switch, sort_order
99
+
100
+ def read_path_recorder(path_recorder, path_recorder_formatted):
101
+ path_recorder = wib_db.load_path_recorder()
102
+ path_recorder_formatted = [value.get("path_display") for key, value in path_recorder.items()]
103
+ path_recorder_formatted = sorted(path_recorder_formatted, key=lambda x: natural_keys(x.lower()))
104
+
105
+ return path_recorder, path_recorder_formatted
106
+
107
+ def pure_path(path):
108
+ if path == []:
109
+ return path, 0
110
+ match = re.search(r" \[(\d+)\]$", path)
111
+ if match:
112
+ path = path[:match.start()]
113
+ depth = int(match.group(1))
114
+ else:
115
+ depth = 0
116
+ return path, depth
117
+
118
+ def history2path(img_path_history):
119
+ img_path, _ = pure_path(img_path_history)
120
+ return img_path
121
+
122
+ def totxt(file):
123
+ base, _ = os.path.splitext(file)
124
+ file_txt = base + '.txt'
125
+
126
+ return file_txt
127
+
128
+ def reduplicative_file_move(src, dst):
129
+ def same_name_file(basename, path):
130
+ name, ext = os.path.splitext(basename)
131
+ f_list = os.listdir(path)
132
+ max_num = 0
133
+ for f in f_list:
134
+ if len(f) <= len(basename):
135
+ continue
136
+ f_ext = f[-len(ext):] if len(ext) > 0 else ""
137
+ if f[:len(name)] == name and f_ext == ext:
138
+ if f[len(name)] == "(" and f[-len(ext)-1] == ")":
139
+ number = f[len(name)+1:-len(ext)-1]
140
+ if number.isdigit():
141
+ if int(number) > max_num:
142
+ max_num = int(number)
143
+ return f"{name}({max_num + 1}){ext}"
144
+ name = os.path.basename(src)
145
+ save_name = os.path.join(dst, name)
146
+ src_txt_exists = False
147
+ if opts.images_txt_files:
148
+ src_txt = totxt(src)
149
+ if os.path.exists(src_txt):
150
+ src_txt_exists = True
151
+ if not os.path.exists(save_name):
152
+ if opts.images_copy_image:
153
+ shutil.copy2(src, dst)
154
+ if opts.images_txt_files and src_txt_exists:
155
+ shutil.copy2(src_txt, dst)
156
+ else:
157
+ shutil.move(src, dst)
158
+ if opts.images_txt_files and src_txt_exists:
159
+ shutil.move(src_txt, dst)
160
+ else:
161
+ name = same_name_file(name, dst)
162
+ if opts.images_copy_image:
163
+ shutil.copy2(src, os.path.join(dst, name))
164
+ if opts.images_txt_files and src_txt_exists:
165
+ shutil.copy2(src_txt, totxt(os.path.join(dst, name)))
166
+ else:
167
+ shutil.move(src, os.path.join(dst, name))
168
+ if opts.images_txt_files and src_txt_exists:
169
+ shutil.move(src_txt, totxt(os.path.join(dst, name)))
170
+
171
+ def save_image(file_name, filenames, page_index, turn_page_switch):
172
+ if file_name is not None and os.path.exists(file_name):
173
+ reduplicative_file_move(file_name, opts.outdir_save)
174
+ if opts.images_copy_image:
175
+ message = "<div style='color:#999'>Copied to favorites</div>"
176
+ else:
177
+ message = "<div style='color:#999'>Moved to favorites</div>"
178
+ # Force page refresh with checking filenames
179
+ filenames = []
180
+ turn_page_switch = -turn_page_switch
181
+ else:
182
+ message = "<div style='color:#999'>Image not found (may have been already moved)</div>"
183
+
184
+ return message, filenames, page_index, turn_page_switch
185
+
186
+ def delete_image(delete_num, name, filenames, image_index, visible_num):
187
+ if name == "":
188
+ return filenames, delete_num
189
+ else:
190
+ delete_num = int(delete_num)
191
+ visible_num = int(visible_num)
192
+ image_index = int(image_index)
193
+ index = list(filenames).index(name)
194
+ i = 0
195
+ new_file_list = []
196
+ for name in filenames:
197
+ if i >= index and i < index + delete_num:
198
+ if os.path.exists(name):
199
+ if visible_num == image_index:
200
+ new_file_list.append(name)
201
+ i += 1
202
+ continue
203
+ if opts.images_delete_message:
204
+ print(f"Deleting file {name}")
205
+ delete_recycle(name)
206
+ visible_num -= 1
207
+ if opts.images_txt_files:
208
+ txt_file = totxt(name)
209
+ if os.path.exists(txt_file):
210
+ delete_recycle(txt_file)
211
+ else:
212
+ print(f"File does not exist {name}")
213
+ else:
214
+ new_file_list.append(name)
215
+ i += 1
216
+ return new_file_list, 1, visible_num
217
+
218
+ def traverse_all_files(curr_path, image_list, tabname_box, img_path_depth) -> List[Tuple[str, os.stat_result, str, int]]:
219
+ global current_depth
220
+ if curr_path == "":
221
+ return image_list
222
+ f_list = [(os.path.join(curr_path, entry.name), entry.stat()) for entry in os.scandir(curr_path)]
223
+ for f_info in f_list:
224
+ fname, fstat = f_info
225
+ if os.path.splitext(fname)[1] in image_ext_list:
226
+ image_list.append(f_info)
227
+ elif stat.S_ISDIR(fstat.st_mode):
228
+ if opts.images_history_with_subdirs or (tabname_box == "Others" and img_path_depth != 0 and (current_depth < img_path_depth or img_path_depth < 0)):
229
+ current_depth = current_depth + 1
230
+ image_list = traverse_all_files(fname, image_list, tabname_box, img_path_depth)
231
+ current_depth = current_depth - 1
232
+ return image_list
233
+
234
+ def cache_exif(fileinfos):
235
+ global finfo_exif, exif_cache, finfo_aes, aes_cache
236
+
237
+ if yappi_do:
238
+ import yappi
239
+ import pandas as pd
240
+ yappi.set_clock_type("wall")
241
+ yappi.start()
242
+
243
+ cache_exif_start = time.time()
244
+ new_exif = 0
245
+ new_aes = 0
246
+ conn, cursor = wib_db.transaction_begin()
247
+ for fi_info in fileinfos:
248
+ if any(fi_info[0].endswith(ext) for ext in image_ext_list):
249
+ found_exif = False
250
+ found_aes = False
251
+ if fi_info[0] in exif_cache:
252
+ finfo_exif[fi_info[0]] = exif_cache[fi_info[0]]
253
+ found_exif = True
254
+ if fi_info[0] in aes_cache:
255
+ finfo_aes[fi_info[0]] = aes_cache[fi_info[0]]
256
+ found_aes = True
257
+ if not found_exif or not found_aes:
258
+ finfo_exif[fi_info[0]] = "0"
259
+ exif_cache[fi_info[0]] = "0"
260
+ finfo_aes[fi_info[0]] = "0"
261
+ aes_cache[fi_info[0]] = "0"
262
+ if fi_info[0].endswith(image_ext_list[0]):
263
+ image = PngImageFile(fi_info[0])
264
+ else:
265
+ image = JpegImageFile(fi_info[0])
266
+ allExif = modules.extras.run_pnginfo(image)[1]
267
+ if allExif:
268
+ finfo_exif[fi_info[0]] = allExif
269
+ exif_cache[fi_info[0]] = allExif
270
+ wib_db.update_exif_data(conn, fi_info[0], allExif)
271
+ new_exif = new_exif + 1
272
+ m = re.search("(?:aesthetic_score:|Score:) (\d+.\d+)", allExif)
273
+ if m:
274
+ aes_value = m.group(1)
275
+ else:
276
+ aes_value = "0"
277
+ finfo_aes[fi_info[0]] = aes_value
278
+ aes_cache[fi_info[0]] = aes_value
279
+ wib_db.update_aes_data(conn, fi_info[0], aes_value)
280
+ new_aes = new_aes + 1
281
+ else:
282
+ try:
283
+ filename = os.path.splitext(fi_info[0])[0] + ".txt"
284
+ geninfo = ""
285
+ with open(filename) as f:
286
+ for line in f:
287
+ geninfo += line
288
+ finfo_exif[fi_info[0]] = geninfo
289
+ exif_cache[fi_info[0]] = geninfo
290
+ wib_db.update_exif_data(conn, fi_info[0], geninfo)
291
+ new_exif = new_exif + 1
292
+ m = re.search("(?:aesthetic_score:|Score:) (\d+.\d+)", geninfo)
293
+ if m:
294
+ aes_value = m.group(1)
295
+ else:
296
+ aes_value = "0"
297
+ finfo_aes[fi_info[0]] = aes_value
298
+ aes_cache[fi_info[0]] = aes_value
299
+ wib_db.update_aes_data(conn, fi_info[0], aes_value)
300
+ new_aes = new_aes + 1
301
+ except Exception:
302
+ logger.warning(f"No EXIF in PNG/JPG or txt file for {fi_info[0]}")
303
+ # Saved with defaults to not scan it again next time
304
+ finfo_exif[fi_info[0]] = "0"
305
+ exif_cache[fi_info[0]] = "0"
306
+ allExif = "0"
307
+ wib_db.update_exif_data(conn, fi_info[0], allExif)
308
+ new_exif = new_exif + 1
309
+ aes_value = "0"
310
+ finfo_aes[fi_info[0]] = aes_value
311
+ aes_cache[fi_info[0]] = aes_value
312
+ wib_db.update_aes_data(conn, fi_info[0], aes_value)
313
+ new_aes = new_aes + 1
314
+
315
+ wib_db.transaction_end(conn, cursor)
316
+
317
+ if yappi_do:
318
+ yappi.stop()
319
+ pd.set_option('display.float_format', lambda x: '%.6f' % x)
320
+ yappi_stats = yappi.get_func_stats().strip_dirs()
321
+ data = [(s.name, s.ncall, s.tsub, s.ttot, s.ttot/s.ncall) for s in yappi_stats]
322
+ df = pd.DataFrame(data, columns=['name', 'ncall', 'tsub', 'ttot', 'tavg'])
323
+ print(df.to_string(index=False))
324
+ yappi.get_thread_stats().print_all()
325
+
326
+ cache_exif_end = time.time()
327
+ logger.debug(f"cache_exif: {new_exif}/{len(fileinfos)} cache_aes: {new_aes}/{len(fileinfos)} {round(cache_exif_end - cache_exif_start, 1)} seconds")
328
+
329
+ def atof(text):
330
+ try:
331
+ retval = float(text)
332
+ except ValueError:
333
+ retval = text
334
+ return retval
335
+
336
+ def natural_keys(text):
337
+ '''
338
+ alist.sort(key=natural_keys) sorts in human order
339
+ http://nedbatchelder.com/blog/200712/human_sorting.html
340
+ (See Toothy's implementation in the comments)
341
+ float regex comes from https://stackoverflow.com/a/12643073/190597
342
+ '''
343
+ return [ atof(c) for c in re.split(r'[+-]?([0-9]+(?:[.][0-9]*)?|[.][0-9]+)', text) ]
344
+
345
+
346
+ def get_all_images(dir_name, sort_by, sort_order, keyword, tabname_box, img_path_depth, ranking_filter, aes_filter, exif_keyword, negative_prompt_search):
347
+ global current_depth
348
+ current_depth = 0
349
+ fileinfos = traverse_all_files(dir_name, [], tabname_box, img_path_depth)
350
+ keyword = keyword.strip(" ")
351
+
352
+ if opts.images_scan_exif:
353
+ cache_exif(fileinfos)
354
+
355
+ if len(keyword) != 0:
356
+ fileinfos = [x for x in fileinfos if keyword.lower() in x[0].lower()]
357
+ filenames = [finfo[0] for finfo in fileinfos]
358
+ if len(exif_keyword) != 0:
359
+ if negative_prompt_search == "Yes":
360
+ fileinfos = [x for x in fileinfos if exif_keyword.lower() in finfo_exif[x[0]].lower()]
361
+ else:
362
+ result = []
363
+ for file_info in fileinfos:
364
+ file_name = file_info[0]
365
+ file_exif = finfo_exif[file_name].lower()
366
+ start_index = file_exif.find("negative prompt: ")
367
+ end_index = file_exif.find("\n", start_index)
368
+ if negative_prompt_search == "Only":
369
+ sub_string = file_exif[start_index:end_index].split("negative prompt: ")[-1].strip()
370
+ if exif_keyword.lower() in sub_string:
371
+ result.append(file_info)
372
+ else:
373
+ sub_string = file_exif[start_index:end_index].strip()
374
+ file_exif = file_exif.replace(sub_string, "")
375
+
376
+ if exif_keyword.lower() in file_exif:
377
+ result.append(file_info)
378
+ fileinfos = result
379
+ filenames = [finfo[0] for finfo in fileinfos]
380
+ if len(aes_filter) != 0:
381
+ fileinfos = [x for x in fileinfos if finfo_aes[x[0]] >= aes_filter]
382
+ filenames = [finfo[0] for finfo in fileinfos]
383
+ if ranking_filter != "All":
384
+ fileinfos = [x for x in fileinfos if get_ranking(x[0]) in ranking_filter]
385
+ filenames = [finfo[0] for finfo in fileinfos]
386
+ if sort_by == "date":
387
+ if sort_order == up_symbol:
388
+ fileinfos = sorted(fileinfos, key=lambda x: x[1].st_mtime)
389
+ else:
390
+ fileinfos = sorted(fileinfos, key=lambda x: -x[1].st_mtime)
391
+ filenames = [finfo[0] for finfo in fileinfos]
392
+ elif sort_by == "path name":
393
+ if sort_order == up_symbol:
394
+ fileinfos = sorted(fileinfos)
395
+ else:
396
+ fileinfos = sorted(fileinfos, reverse=True)
397
+ filenames = [finfo[0] for finfo in fileinfos]
398
+ elif sort_by == "random":
399
+ random.shuffle(fileinfos)
400
+ filenames = [finfo[0] for finfo in fileinfos]
401
+ elif sort_by == "ranking":
402
+ finfo_ranked = {}
403
+ for fi_info in fileinfos:
404
+ finfo_ranked[fi_info[0]] = get_ranking(fi_info[0])
405
+ if not down_symbol:
406
+ fileinfos = dict(sorted(finfo_ranked.items(), key=lambda x: (x[1], x[0])))
407
+ else:
408
+ fileinfos = dict(reversed(sorted(finfo_ranked.items(), key=lambda x: (x[1], x[0]))))
409
+ filenames = [finfo for finfo in fileinfos]
410
+ elif sort_by == "aesthetic_score":
411
+ fileinfo_aes = {}
412
+ for finfo in fileinfos:
413
+ fileinfo_aes[finfo[0]] = finfo_aes[finfo[0]]
414
+ if down_symbol:
415
+ fileinfos = dict(reversed(sorted(fileinfo_aes.items(), key=lambda x: (x[1], x[0]))))
416
+ else:
417
+ fileinfos = dict(sorted(fileinfo_aes.items(), key=lambda x: (x[1], x[0])))
418
+ filenames = [finfo for finfo in fileinfos]
419
+ else:
420
+ sort_values = {}
421
+ exif_info = dict(finfo_exif)
422
+ if exif_info:
423
+ for k, v in exif_info.items():
424
+ match = re.search(r'(?<='+ sort_by.lower() + ":" ').*?(?=(,|$))', v.lower())
425
+ if match:
426
+ sort_values[k] = match.group()
427
+ else:
428
+ sort_values[k] = "0"
429
+ if down_symbol:
430
+ fileinfos = dict(reversed(sorted(fileinfos, key=lambda x: natural_keys(sort_values[x[0]]))))
431
+ else:
432
+ fileinfos = dict(sorted(fileinfos, key=lambda x: natural_keys(sort_values[x[0]])))
433
+ filenames = [finfo for finfo in fileinfos]
434
+ else:
435
+ filenames = [finfo for finfo in fileinfos]
436
+ return filenames
437
+
438
+ def get_image_page(img_path, page_index, filenames, keyword, sort_by, sort_order, tabname_box, img_path_depth, ranking_filter, aes_filter, exif_keyword, negative_prompt_search):
439
+ if img_path == "":
440
+ return [], page_index, [], "", "", "", 0, ""
441
+
442
+ img_path, _ = pure_path(img_path)
443
+ if page_index == 1 or page_index == 0 or len(filenames) == 0:
444
+ filenames = get_all_images(img_path, sort_by, sort_order, keyword, tabname_box, img_path_depth, ranking_filter, aes_filter, exif_keyword, negative_prompt_search)
445
+ page_index = int(page_index)
446
+ length = len(filenames)
447
+ max_page_index = length // num_of_imgs_per_page + 1
448
+ page_index = max_page_index if page_index == -1 else page_index
449
+ page_index = 1 if page_index < 1 else page_index
450
+ page_index = max_page_index if page_index > max_page_index else page_index
451
+ idx_frm = (page_index - 1) * num_of_imgs_per_page
452
+ image_list = filenames[idx_frm:idx_frm + num_of_imgs_per_page]
453
+
454
+ visible_num = num_of_imgs_per_page if idx_frm + num_of_imgs_per_page < length else length % num_of_imgs_per_page
455
+ visible_num = num_of_imgs_per_page if visible_num == 0 else visible_num
456
+
457
+ load_info = "<div style='color:#999' align='center'>"
458
+ load_info += f"{length} images in this directory, divided into {int((length + 1) // num_of_imgs_per_page + 1)} pages"
459
+ load_info += "</div>"
460
+ return filenames, gr.update(value=page_index, label=f"Page Index (of {max_page_index} pages)"), image_list, "", "", "", visible_num, load_info
461
+
462
+ def get_current_file(tabname_box, num, page_index, filenames):
463
+ file = filenames[int(num) + int((page_index - 1) * num_of_imgs_per_page)]
464
+ return file
465
+
466
+ def show_image_info(tabname_box, num, page_index, filenames):
467
+ file = filenames[int(num) + int((page_index - 1) * num_of_imgs_per_page)]
468
+ tm = "<div style='color:#999' align='right'>" + time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(os.path.getmtime(file))) + "</div>"
469
+ return file, tm, num, file, ""
470
+
471
+ def show_next_image_info(tabname_box, num, page_index, filenames, auto_next):
472
+ file = filenames[int(num) + int((page_index - 1) * num_of_imgs_per_page)]
473
+ tm = "<div style='color:#999' align='right'>" + time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(os.path.getmtime(file))) + "</div>"
474
+ if auto_next:
475
+ num = int(num) + 1
476
+ return file, tm, num, file, ""
477
+
478
+ def change_dir(img_dir, path_recorder, load_switch, img_path_history, img_path_depth, img_path):
479
+ warning = None
480
+ img_path, _ = pure_path(img_path)
481
+ img_path_depth_org = img_path_depth
482
+ if img_dir == none_select:
483
+ return warning, gr.update(visible=False), img_path_history, path_recorder, load_switch, img_path, img_path_depth
484
+ else:
485
+ img_dir, img_path_depth = pure_path(img_dir)
486
+ if warning is None:
487
+ try:
488
+ if os.path.exists(img_dir):
489
+ try:
490
+ f = os.listdir(img_dir)
491
+ except:
492
+ warning = f"'{img_dir} is not a directory"
493
+ else:
494
+ warning = "The directory does not exist"
495
+ except:
496
+ warning = "The format of the directory is incorrect"
497
+ if warning is None:
498
+ return "", gr.update(visible=True), img_path_history, path_recorder, img_dir, img_dir, img_path_depth
499
+ else:
500
+ return warning, gr.update(visible=False), img_path_history, path_recorder, load_switch, img_path, img_path_depth_org
501
+
502
+ def update_move_text(unused):
503
+ return f'{"Move" if not opts.images_copy_image else "Copy"} to favorites'
504
+
505
+ def get_ranking(filename):
506
+ ranking_value = wib_db.select_ranking(filename)
507
+ return ranking_value
508
+
509
+ def create_tab(tabname):
510
+ global init, exif_cache, aes_cache
511
+ custom_dir = False
512
+ path_recorder = {}
513
+ path_recorder_formatted = []
514
+
515
+ if init:
516
+ wib_db.check()
517
+ exif_cache = wib_db.load_exif_data(exif_cache)
518
+ aes_cache = wib_db.load_aes_data(aes_cache)
519
+ init = False
520
+
521
+ if tabname == "txt2img":
522
+ dir_name = opts.outdir_txt2img_samples
523
+ elif tabname == "img2img":
524
+ dir_name = opts.outdir_img2img_samples
525
+ elif tabname == "txt2img-grids": #added by HaylockGrant to add a new tab for grid images
526
+ dir_name = opts.outdir_txt2img_grids
527
+ elif tabname == "img2img-grids": #added by HaylockGrant to add a new tab for grid images
528
+ dir_name = opts.outdir_img2img_grids
529
+ elif tabname == "Extras":
530
+ dir_name = opts.outdir_extras_samples
531
+ elif tabname == favorite_tab_name:
532
+ dir_name = opts.outdir_save
533
+ else:
534
+ custom_dir = True
535
+ dir_name = None
536
+ path_recorder, path_recorder_formatted = read_path_recorder(path_recorder, path_recorder_formatted)
537
+
538
+ if not custom_dir:
539
+ dir_name = str(Path(dir_name))
540
+ if not os.path.exists(dir_name):
541
+ os.makedirs(dir_name)
542
+
543
+ with gr.Row():
544
+ warning_box = gr.HTML("<p>&nbsp")
545
+
546
+ with gr.Row(visible= custom_dir):
547
+ with gr.Column(scale=10):
548
+ img_path = gr.Textbox(dir_name, label="Images directory", placeholder="Input images directory", interactive=custom_dir)
549
+ with gr.Column(scale=1):
550
+ img_path_depth = gr.Number(value="0", label="Sub directory depth")
551
+ with gr.Column(scale=1):
552
+ img_path_save_button = gr.Button(value="Add to / replace in saved directories")
553
+
554
+ with gr.Row(visible= custom_dir):
555
+ with gr.Column(scale=10):
556
+ img_path_history = gr.Dropdown(choices=path_recorder_formatted, label="Saved directories")
557
+ with gr.Column(scale=1):
558
+ img_path_remove_button = gr.Button(value="Remove from saved directories")
559
+ path_recorder = gr.State(path_recorder)
560
+
561
+ with gr.Row(visible= custom_dir):
562
+ with gr.Column(scale=10):
563
+ img_path_subdirs = gr.Dropdown(choices=[none_select], value=none_select, label="Sub directories", interactive=True, elem_id="img_path_subdirs")
564
+ with gr.Column(scale=1):
565
+ img_path_subdirs_button = gr.Button(value="Get sub directories")
566
+
567
+ with gr.Row(visible= not custom_dir, elem_id=tabname + "_images_history") as main_panel:
568
+ with gr.Column():
569
+ with gr.Row():
570
+ with gr.Column(scale=2):
571
+ with gr.Row():
572
+ first_page = gr.Button('First Page')
573
+ prev_page = gr.Button('Prev Page')
574
+ page_index = gr.Number(value=1, label="Page Index")
575
+ refresh_index_button = ToolButton(value=refresh_symbol)
576
+ next_page = gr.Button('Next Page')
577
+ end_page = gr.Button('End Page')
578
+ with gr.Column(scale=10):
579
+ ranking = gr.Radio(value="None", choices=["1", "2", "3", "4", "5", "None"], label="ranking", elem_id=f"{tabname}_images_ranking", interactive=True, visible=False)
580
+ auto_next = gr.Checkbox(label="Next Image After Ranking (To be implemented)", interactive=False, visible=False)
581
+ history_gallery = gr.Gallery(show_label=False, elem_id=tabname + "_images_history_gallery").style(grid=opts.images_history_page_columns)
582
+ with gr.Row() as delete_panel:
583
+ with gr.Column(scale=1):
584
+ delete_num = gr.Number(value=1, interactive=True, label="delete next")
585
+ with gr.Column(scale=3):
586
+ delete = gr.Button('Delete', elem_id=tabname + "_images_history_del_button")
587
+
588
+ with gr.Column(scale=1):
589
+ with gr.Row(scale=0.5):
590
+ sort_by = gr.Dropdown(value="date", choices=["path name", "date", "aesthetic_score", "random", "cfg scale", "steps", "seed", "sampler", "size", "model", "model hash", "ranking"], label="sort by")
591
+ sort_order = ToolButton(value=down_symbol)
592
+ with gr.Row():
593
+ keyword = gr.Textbox(value="", label="filename keyword")
594
+ with gr.Row():
595
+ exif_keyword = gr.Textbox(value="", label="exif keyword")
596
+ negative_prompt_search = gr.Radio(value="No", choices=["No", "Yes", "Only"], label="Include negative prompt in exif search", interactive=True)
597
+ with gr.Column():
598
+ ranking_filter = gr.Radio(value="All", choices=["All", "1", "2", "3", "4", "5", "None"], label="ranking filter", interactive=True)
599
+ with gr.Row():
600
+ aes_filter = gr.Textbox(value="", label="minimum aesthetic_score")
601
+ with gr.Row():
602
+ with gr.Column():
603
+ img_file_info = gr.Textbox(label="Generate Info", interactive=False, lines=6)
604
+ img_file_name = gr.Textbox(value="", label="File Name", interactive=False)
605
+ img_file_time= gr.HTML()
606
+ with gr.Row(elem_id=tabname + "_images_history_button_panel") as button_panel:
607
+ if tabname != favorite_tab_name:
608
+ save_btn = gr.Button(f'{"Move" if not opts.images_copy_image else "Copy"} to favorites')
609
+ try:
610
+ send_to_buttons = modules.generation_parameters_copypaste.create_buttons(["txt2img", "img2img", "inpaint", "extras"])
611
+ except:
612
+ pass
613
+ with gr.Row():
614
+ collected_warning = gr.HTML()
615
+
616
+
617
+ # hidden items
618
+ with gr.Row(visible=False):
619
+ renew_page = gr.Button("Renew Page", elem_id=tabname + "_images_history_renew_page")
620
+ visible_img_num = gr.Number()
621
+ tabname_box = gr.Textbox(tabname)
622
+ image_index = gr.Textbox(value=-1)
623
+ set_index = gr.Button('set_index', elem_id=tabname + "_images_history_set_index")
624
+ filenames = gr.State([])
625
+ all_images_list = gr.State()
626
+ hidden = gr.Image(type="pil")
627
+ info1 = gr.Textbox()
628
+ info2 = gr.Textbox()
629
+ load_switch = gr.Textbox(value="load_switch", label="load_switch")
630
+ turn_page_switch = gr.Number(value=1, label="turn_page_switch")
631
+ img_path_add = gr.Textbox(value="add")
632
+ img_path_remove = gr.Textbox(value="remove")
633
+
634
+ change_dir_outputs = [warning_box, main_panel, img_path_history, path_recorder, load_switch, img_path, img_path_depth]
635
+ img_path.submit(change_dir, inputs=[img_path, path_recorder, load_switch, img_path_history, img_path_depth, img_path], outputs=change_dir_outputs)
636
+ img_path_history.change(change_dir, inputs=[img_path_history, path_recorder, load_switch, img_path_history, img_path_depth, img_path], outputs=change_dir_outputs)
637
+ # img_path_history.change(history2path, inputs=[img_path_history], outputs=[img_path])
638
+
639
+ #delete
640
+ delete.click(delete_image, inputs=[delete_num, img_file_name, filenames, image_index, visible_img_num], outputs=[filenames, delete_num, visible_img_num])
641
+ delete.click(fn=None, _js="images_history_delete", inputs=[delete_num, tabname_box, image_index], outputs=None)
642
+ if tabname != favorite_tab_name:
643
+ save_btn.click(save_image, inputs=[img_file_name, filenames, page_index, turn_page_switch], outputs=[collected_warning, filenames, page_index, turn_page_switch])
644
+ img_file_name.change(fn=update_move_text, inputs=[img_file_name], outputs=[save_btn])
645
+
646
+ #turn page
647
+ first_page.click(lambda s:(1, -s) , inputs=[turn_page_switch], outputs=[page_index, turn_page_switch])
648
+ next_page.click(lambda p, s: (p + 1, -s), inputs=[page_index, turn_page_switch], outputs=[page_index, turn_page_switch])
649
+ prev_page.click(lambda p, s: (p - 1, -s), inputs=[page_index, turn_page_switch], outputs=[page_index, turn_page_switch])
650
+ end_page.click(lambda s: (-1, -s), inputs=[turn_page_switch], outputs=[page_index, turn_page_switch])
651
+ load_switch.change(lambda s:(1, -s), inputs=[turn_page_switch], outputs=[page_index, turn_page_switch])
652
+ keyword.submit(lambda s:(1, -s), inputs=[turn_page_switch], outputs=[page_index, turn_page_switch])
653
+ exif_keyword.submit(lambda s:(1, -s), inputs=[turn_page_switch], outputs=[page_index, turn_page_switch])
654
+ aes_filter.submit(lambda s:(1, -s), inputs=[turn_page_switch], outputs=[page_index, turn_page_switch])
655
+ sort_by.change(lambda s:(1, -s), inputs=[turn_page_switch], outputs=[page_index, turn_page_switch])
656
+ ranking_filter.change(lambda s:(1, -s), inputs=[turn_page_switch], outputs=[page_index, turn_page_switch])
657
+ page_index.submit(lambda s: -s, inputs=[turn_page_switch], outputs=[turn_page_switch])
658
+ renew_page.click(lambda s: -s, inputs=[turn_page_switch], outputs=[turn_page_switch])
659
+ refresh_index_button.click(lambda p, s:(p, -s), inputs=[page_index, turn_page_switch], outputs=[page_index, turn_page_switch])
660
+ img_path_depth.change(lambda s: -s, inputs=[turn_page_switch], outputs=[turn_page_switch])
661
+
662
+ turn_page_switch.change(
663
+ fn=get_image_page,
664
+ inputs=[img_path, page_index, filenames, keyword, sort_by, sort_order, tabname_box, img_path_depth, ranking_filter, aes_filter, exif_keyword, negative_prompt_search],
665
+ outputs=[filenames, page_index, history_gallery, img_file_name, img_file_time, img_file_info, visible_img_num, warning_box]
666
+ )
667
+ turn_page_switch.change(fn=None, inputs=[tabname_box], outputs=None, _js="images_history_turnpage")
668
+ turn_page_switch.change(fn=lambda:(gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)), inputs=None, outputs=[delete_panel, button_panel, ranking])
669
+
670
+ sort_order.click(
671
+ fn=sort_order_flip,
672
+ inputs=[turn_page_switch, sort_order],
673
+ outputs=[page_index, turn_page_switch, sort_order]
674
+ )
675
+
676
+ # Others
677
+ img_path_subdirs_button.click(
678
+ fn=img_path_subdirs_get,
679
+ inputs=[img_path],
680
+ outputs=[img_path_subdirs]
681
+ )
682
+ img_path_subdirs.change(
683
+ fn=change_dir,
684
+ inputs=[img_path_subdirs, path_recorder, load_switch, img_path_history, img_path_depth, img_path],
685
+ outputs=change_dir_outputs
686
+ )
687
+ img_path_save_button.click(
688
+ fn=img_path_add_remove,
689
+ inputs=[img_path, path_recorder, img_path_add, img_path_depth],
690
+ outputs=[path_recorder, img_path_history]
691
+ )
692
+ img_path_remove_button.click(
693
+ fn=img_path_add_remove,
694
+ inputs=[img_path, path_recorder, img_path_remove],
695
+ outputs=[path_recorder, img_path_history]
696
+ )
697
+
698
+ # other functions
699
+ set_index.click(show_image_info, _js="images_history_get_current_img", inputs=[tabname_box, image_index, page_index, filenames], outputs=[img_file_name, img_file_time, image_index, hidden])
700
+ set_index.click(fn=lambda:(gr.update(visible=True), gr.update(visible=True), gr.update(visible=True)), inputs=None, outputs=[delete_panel, button_panel, ranking])
701
+ img_file_name.change(fn=lambda : "", inputs=None, outputs=[collected_warning])
702
+ img_file_name.change(get_ranking, inputs=img_file_name, outputs=ranking)
703
+
704
+
705
+ hidden.change(fn=run_pnginfo, inputs=[hidden, img_path, img_file_name], outputs=[info1, img_file_info, info2])
706
+
707
+ #ranking
708
+ ranking.change(wib_db.update_ranking, inputs=[img_file_name, ranking])
709
+ #ranking.change(show_next_image_info, _js="images_history_get_current_img", inputs=[tabname_box, image_index, page_index, auto_next], outputs=[img_file_name, img_file_time, image_index, hidden])
710
+
711
+ try:
712
+ modules.generation_parameters_copypaste.bind_buttons(send_to_buttons, hidden, img_file_info)
713
+ except:
714
+ pass
715
+
716
+ def run_pnginfo(image, image_path, image_file_name):
717
+ if image is None:
718
+ return '', '', ''
719
+ geninfo, items = images.read_info_from_image(image)
720
+ items = {**{'parameters': geninfo}, **items}
721
+
722
+ info = ''
723
+ for key, text in items.items():
724
+ info += f"""
725
+ <div>
726
+ <p><b>{plaintext_to_html(str(key))}</b></p>
727
+ <p>{plaintext_to_html(str(text))}</p>
728
+ </div>
729
+ """.strip()+"\n"
730
+
731
+ if geninfo is None:
732
+ try:
733
+ filename = os.path.splitext(image_file_name)[0] + ".txt"
734
+ geninfo = ""
735
+ with open(filename) as f:
736
+ for line in f:
737
+ geninfo += line
738
+ except Exception:
739
+ logger.warning(f"No EXIF in PNG or txt file")
740
+ return '', geninfo, info
741
+
742
+
743
+ def on_ui_tabs():
744
+ global num_of_imgs_per_page
745
+ global loads_files_num
746
+ num_of_imgs_per_page = int(opts.images_history_page_columns * opts.images_history_page_rows)
747
+ loads_files_num = int(opts.images_history_pages_perload * num_of_imgs_per_page)
748
+ with gr.Blocks(analytics_enabled=False) as images_history:
749
+ with gr.Tabs(elem_id="images_history_tab") as tabs:
750
+ for tab in tabs_list:
751
+ with gr.Tab(tab, elem_id=f"{tab}_images_history_container"):
752
+ with gr.Blocks(analytics_enabled=False) :
753
+ create_tab(tab)
754
+ gr.Checkbox(opts.images_history_preload, elem_id="images_history_preload", visible=False)
755
+ gr.Textbox(",".join(tabs_list), elem_id="images_history_tabnames_list", visible=False)
756
+ return (images_history , "Image Browser", "images_history"),
757
+
758
+ def on_ui_settings():
759
+ section = ('images-history', "Images Browser")
760
+ shared.opts.add_option("images_history_with_subdirs", shared.OptionInfo(True, "Include images in sub directories", section=section))
761
+ shared.opts.add_option("images_history_preload", shared.OptionInfo(False, "Preload images at startup", section=section))
762
+ shared.opts.add_option("images_copy_image", shared.OptionInfo(False, "Move to favorites button copies instead of moving", section=section))
763
+ shared.opts.add_option("images_delete_message", shared.OptionInfo(True, "Print image deletion messages to the console", section=section))
764
+ shared.opts.add_option("images_txt_files", shared.OptionInfo(True, "Move/Copy/Delete matching .txt files", section=section))
765
+ shared.opts.add_option("images_logger_warning", shared.OptionInfo(False, "Print warning logs to the console", section=section))
766
+ shared.opts.add_option("images_logger_debug", shared.OptionInfo(False, "Print debug logs to the console", section=section))
767
+ shared.opts.add_option("images_delete_recycle", shared.OptionInfo(False, "Use recycle bin when deleting images", section=section))
768
+ shared.opts.add_option("images_scan_exif", shared.OptionInfo(True, "Scan Exif-/.txt-data (slower, but required for exif-keyword-search)", section=section))
769
+
770
+ shared.opts.add_option("images_history_page_columns", shared.OptionInfo(6, "Number of columns on the page", section=section))
771
+ shared.opts.add_option("images_history_page_rows", shared.OptionInfo(6, "Number of rows on the page", section=section))
772
+ shared.opts.add_option("images_history_pages_perload", shared.OptionInfo(20, "Minimum number of pages per load", section=section))
773
+
774
+
775
+ script_callbacks.on_ui_settings(on_ui_settings)
776
+ script_callbacks.on_ui_tabs(on_ui_tabs)
SD-images-browser-main/scripts/wib/wib_db.py ADDED
@@ -0,0 +1,340 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import os
3
+ import sqlite3
4
+ from modules import scripts
5
+
6
+ path_recorder_file = os.path.join(scripts.basedir(), "path_recorder.txt")
7
+ aes_cache_file = os.path.join(scripts.basedir(), "aes_scores.json")
8
+ exif_cache_file = os.path.join(scripts.basedir(), "exif_data.json")
9
+ ranking_file = os.path.join(scripts.basedir(), "ranking.json")
10
+ archive = os.path.join(scripts.basedir(), "archive")
11
+ db_file = os.path.join(scripts.basedir(), "wib.sqlite3")
12
+ np = "Negative prompt: "
13
+ st = "Steps: "
14
+
15
+ def create_db(cursor):
16
+ cursor.execute('''
17
+ CREATE TABLE IF NOT EXISTS db_data (
18
+ key TEXT PRIMARY KEY,
19
+ value TEXT
20
+ )
21
+ ''')
22
+
23
+ cursor.execute('''
24
+ CREATE TABLE IF NOT EXISTS path_recorder (
25
+ path TEXT PRIMARY KEY,
26
+ depth INT,
27
+ path_display TEXT,
28
+ created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
29
+ updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP
30
+ )
31
+ ''')
32
+
33
+ cursor.execute('''
34
+ CREATE TRIGGER path_recorder_tr
35
+ AFTER UPDATE ON path_recorder
36
+ BEGIN
37
+ UPDATE path_recorder SET updated = CURRENT_TIMESTAMP WHERE path = OLD.path;
38
+ END;
39
+ ''')
40
+
41
+ cursor.execute('''
42
+ CREATE TABLE IF NOT EXISTS exif_data (
43
+ file TEXT,
44
+ key TEXT,
45
+ value TEXT,
46
+ created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
47
+ updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
48
+ PRIMARY KEY (file, key)
49
+ )
50
+ ''')
51
+
52
+ cursor.execute('''
53
+ CREATE INDEX IF NOT EXISTS exif_data_key ON exif_data (key)
54
+ ''')
55
+
56
+ cursor.execute('''
57
+ CREATE TRIGGER exif_data_tr
58
+ AFTER UPDATE ON exif_data
59
+ BEGIN
60
+ UPDATE exif_data SET updated = CURRENT_TIMESTAMP WHERE file = OLD.file AND key = OLD.key;
61
+ END;
62
+ ''')
63
+
64
+ cursor.execute('''
65
+ CREATE TABLE IF NOT EXISTS ranking (
66
+ file TEXT PRIMARY KEY,
67
+ ranking TEXT,
68
+ created TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
69
+ updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP
70
+ )
71
+ ''')
72
+
73
+ cursor.execute('''
74
+ CREATE TRIGGER ranking_tr
75
+ AFTER UPDATE ON ranking
76
+ BEGIN
77
+ UPDATE ranking SET updated = CURRENT_TIMESTAMP WHERE file = OLD.file;
78
+ END;
79
+ ''')
80
+
81
+ return
82
+
83
+ def migrate_path_recorder(cursor):
84
+ if os.path.exists(path_recorder_file):
85
+ try:
86
+ with open(path_recorder_file) as f:
87
+ # json-version
88
+ path_recorder = json.load(f)
89
+ for path, values in path_recorder.items():
90
+ depth = values["depth"]
91
+ path_display = values["path_display"]
92
+ cursor.execute('''
93
+ INSERT INTO path_recorder (path, depth, path_display)
94
+ VALUES (?, ?, ?)
95
+ ''', (path, depth, path_display))
96
+ except json.JSONDecodeError:
97
+ with open(path_recorder_file) as f:
98
+ # old txt-version
99
+ path = f.readline().rstrip("\n")
100
+ while len(path) > 0:
101
+ cursor.execute('''
102
+ INSERT INTO path_recorder (path, depth, path_display)
103
+ VALUES (?, ?, ?)
104
+ ''', (path, 0, f"{path} [0]"))
105
+ path = f.readline().rstrip("\n")
106
+
107
+ return
108
+
109
+ def update_exif_data(cursor, file, info):
110
+ prompt = "0"
111
+ negative_prompt = "0"
112
+ key_values = "0: 0"
113
+ if info != "0":
114
+ info_list = info.split("\n")
115
+ prompt = ""
116
+ negative_prompt = ""
117
+ key_values = ""
118
+ for info_item in info_list:
119
+ if info_item.startswith(st):
120
+ key_values = info_item
121
+ elif info_item.startswith(np):
122
+ negative_prompt = info_item.replace(np, "")
123
+ else:
124
+ prompt = info_item
125
+ if key_values != "":
126
+ key_value_pairs = []
127
+ key_value = ""
128
+ quote_open = False
129
+ for char in key_values + ",":
130
+ key_value += char
131
+ if char == '"':
132
+ quote_open = not quote_open
133
+ if char == "," and not quote_open:
134
+ try:
135
+ k, v = key_value.strip(" ,").split(": ")
136
+ except ValueError:
137
+ k = key_value.strip(" ,").split(": ")[0]
138
+ v = ""
139
+ key_value_pairs.append((k, v))
140
+ key_value = ""
141
+
142
+ try:
143
+ cursor.execute('''
144
+ INSERT INTO exif_data (file, key, value)
145
+ VALUES (?, ?, ?)
146
+ ''', (file, "prompt", prompt))
147
+ except sqlite3.IntegrityError:
148
+ # Duplicate, delete all "file" entries and try again
149
+ cursor.execute('''
150
+ DELETE FROM exif_data
151
+ WHERE file = ?
152
+ ''', (file,))
153
+
154
+ cursor.execute('''
155
+ INSERT INTO exif_data (file, key, value)
156
+ VALUES (?, ?, ?)
157
+ ''', (file, "prompt", prompt))
158
+
159
+ cursor.execute('''
160
+ INSERT INTO exif_data (file, key, value)
161
+ VALUES (?, ?, ?)
162
+ ''', (file, "negative_prompt", negative_prompt))
163
+
164
+ for (key, value) in key_value_pairs:
165
+ try:
166
+ cursor.execute('''
167
+ INSERT INTO exif_data (file, key, value)
168
+ VALUES (?, ?, ?)
169
+ ''', (file, key, value))
170
+ except sqlite3.IntegrityError:
171
+ pass
172
+
173
+ return
174
+
175
+ def migrate_exif_data(cursor):
176
+ if os.path.exists(exif_cache_file):
177
+ with open(exif_cache_file, 'r') as file:
178
+ #with open("c:\\tools\\ai\\stable-diffusion-webui\\extensions\\stable-diffusion-webui-images-browser\\test.json ", 'r') as file:
179
+ exif_cache = json.load(file)
180
+
181
+ for file, info in exif_cache.items():
182
+ update_exif_data(cursor, file, info)
183
+
184
+ return
185
+
186
+ def migrate_ranking(cursor):
187
+ if os.path.exists(ranking_file):
188
+ with open(ranking_file, 'r') as file:
189
+ ranking = json.load(file)
190
+ for file, info in ranking.items():
191
+ if info != "None":
192
+ cursor.execute('''
193
+ INSERT INTO ranking (file, ranking)
194
+ VALUES (?, ?)
195
+ ''', (file, info))
196
+
197
+ return
198
+
199
+ def update_db_data(cursor, key, value):
200
+ cursor.execute('''
201
+ INSERT OR REPLACE
202
+ INTO db_data (key, value)
203
+ VALUES (?, ?)
204
+ ''', (key, value))
205
+
206
+ return
207
+
208
+ def check():
209
+ if not os.path.exists(db_file):
210
+ conn, cursor = transaction_begin()
211
+ create_db(cursor)
212
+ update_db_data(cursor, "version", "1")
213
+ migrate_path_recorder(cursor)
214
+ migrate_exif_data(cursor)
215
+ migrate_ranking(cursor)
216
+ transaction_end(conn, cursor)
217
+
218
+ return
219
+
220
+ def load_path_recorder():
221
+ with sqlite3.connect(db_file) as conn:
222
+ cursor = conn.cursor()
223
+ cursor.execute('''
224
+ SELECT path, depth, path_display
225
+ FROM path_recorder
226
+ ''')
227
+ path_recorder = {path: {"depth": depth, "path_display": path_display} for path, depth, path_display in cursor.fetchall()}
228
+
229
+ return path_recorder
230
+
231
+ def select_ranking(filename):
232
+ with sqlite3.connect(db_file) as conn:
233
+ cursor = conn.cursor()
234
+ cursor.execute('''
235
+ SELECT ranking
236
+ FROM ranking
237
+ WHERE file = ?
238
+ ''', (filename,))
239
+ ranking_value = cursor.fetchone()
240
+
241
+ if ranking_value is None:
242
+ ranking_value = ["0"]
243
+ return ranking_value[0]
244
+
245
+ def update_ranking(file, ranking):
246
+ if ranking != "0":
247
+ with sqlite3.connect(db_file) as conn:
248
+ cursor = conn.cursor()
249
+ cursor.execute('''
250
+ INSERT OR REPLACE
251
+ INTO ranking (file, ranking)
252
+ VALUES (?, ?)
253
+ ''', (file, ranking))
254
+
255
+ return
256
+
257
+ def update_path_recorder(path, depth, path_display):
258
+ with sqlite3.connect(db_file) as conn:
259
+ cursor = conn.cursor()
260
+ cursor.execute('''
261
+ INSERT OR REPLACE
262
+ INTO path_recorder (path, depth, path_display)
263
+ VALUES (?, ?, ?)
264
+ ''', (path, depth, path_display))
265
+
266
+ return
267
+
268
+ def delete_path_recorder(path):
269
+ with sqlite3.connect(db_file) as conn:
270
+ cursor = conn.cursor()
271
+ cursor.execute('''
272
+ DELETE FROM path_recorder
273
+ WHERE path = ?
274
+ ''', (path,))
275
+
276
+ return
277
+
278
+ def transaction_begin():
279
+ conn = sqlite3.connect(db_file)
280
+ conn.isolation_level = None
281
+ cursor = conn.cursor()
282
+ cursor.execute("BEGIN")
283
+ return conn, cursor
284
+
285
+ def transaction_end(conn, cursor):
286
+ cursor.execute("COMMIT")
287
+ conn.close()
288
+ return
289
+
290
+ def update_aes_data(cursor, file, value):
291
+ key = "aesthetic_score"
292
+
293
+ cursor.execute('''
294
+ INSERT OR REPLACE
295
+ INTO exif_data (file, key, value)
296
+ VALUES (?, ?, ?)
297
+ ''', (file, key, value))
298
+
299
+ return
300
+
301
+ def load_exif_data(exif_cache):
302
+ with sqlite3.connect(db_file) as conn:
303
+ cursor = conn.cursor()
304
+ cursor.execute('''
305
+ SELECT file, group_concat(
306
+ case when key = 'prompt' or key = 'negative_prompt' then key || ': ' || value || '\n'
307
+ else key || ': ' || value
308
+ end, ', ') AS string
309
+ FROM (
310
+ SELECT *
311
+ FROM exif_data
312
+ ORDER BY
313
+ CASE WHEN key = 'prompt' THEN 0
314
+ WHEN key = 'negative_prompt' THEN 1
315
+ ELSE 2 END,
316
+ key
317
+ )
318
+ GROUP BY file
319
+ ''')
320
+
321
+ rows = cursor.fetchall()
322
+ for row in rows:
323
+ exif_cache[row[0]] = row[1]
324
+
325
+ return exif_cache
326
+
327
+ def load_aes_data(aes_cache):
328
+ with sqlite3.connect(db_file) as conn:
329
+ cursor = conn.cursor()
330
+ cursor.execute('''
331
+ SELECT file, value
332
+ FROM exif_data
333
+ WHERE key in ("aesthetic_score", "Score")
334
+ ''')
335
+
336
+ rows = cursor.fetchall()
337
+ for row in rows:
338
+ aes_cache[row[0]] = row[1]
339
+
340
+ return aes_cache
SD-rembg-master/.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ __pycache__
SD-rembg-master/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2023 AUTOMATIC1111
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
SD-rembg-master/README.md ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Rembg
2
+
3
+ Extension for [webui](https://github.com/AUTOMATIC1111/stable-diffusion-webui). Removes backgrounds from pictures.
4
+
5
+ ![](preview.png)
6
+
7
+ Find the UI for rembg in the Extras tab after installing the extension.
8
+
9
+ # Installation
10
+
11
+ Install from webui's Extensions tab.
12
+
13
+ # Credits
14
+
15
+ * rembg library that does all the work: https://github.com/danielgatis/rembg
SD-rembg-master/install.py ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ import launch
2
+
3
+ if not launch.is_installed("rembg"):
4
+ launch.run_pip("install rembg==2.0.30 --no-deps", "rembg")
5
+
6
+ for dep in ['onnxruntime', 'pymatting', 'pooch']:
7
+ if not launch.is_installed(dep):
8
+ launch.run_pip(f"install {dep}", f"{dep} for REMBG extension")
SD-rembg-master/preview.png ADDED

Git LFS Details

  • SHA256: 19dd965b7cda2542e2711bbedb873e29d89187d307480b9d64a9ee9c6d5f0a54
  • Pointer size: 132 Bytes
  • Size of remote file: 1.04 MB
SD-rembg-master/scripts/postprocessing_rembg.py ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from modules import scripts_postprocessing
2
+ import gradio as gr
3
+
4
+ from modules.ui_components import FormRow
5
+ import rembg
6
+
7
+ models = [
8
+ "None",
9
+ "u2net",
10
+ "u2netp",
11
+ "u2net_human_seg",
12
+ "u2net_cloth_seg",
13
+ "silueta",
14
+ ]
15
+
16
+ class ScriptPostprocessingUpscale(scripts_postprocessing.ScriptPostprocessing):
17
+ name = "Rembg"
18
+ order = 20000
19
+ model = None
20
+
21
+ def ui(self):
22
+ with FormRow():
23
+ model = gr.Dropdown(label="Remove background", choices=models, value="None")
24
+ return_mask = gr.Checkbox(label="Return mask", value=False)
25
+ alpha_matting = gr.Checkbox(label="Alpha matting", value=False)
26
+
27
+ with FormRow(visible=False) as alpha_mask_row:
28
+ alpha_matting_erode_size = gr.Slider(label="Erode size", minimum=0, maximum=40, step=1, value=10)
29
+ alpha_matting_foreground_threshold = gr.Slider(label="Foreground threshold", minimum=0, maximum=255, step=1, value=240)
30
+ alpha_matting_background_threshold = gr.Slider(label="Background threshold", minimum=0, maximum=255, step=1, value=10)
31
+
32
+ alpha_matting.change(
33
+ fn=lambda x: gr.update(visible=x),
34
+ inputs=[alpha_matting],
35
+ outputs=[alpha_mask_row],
36
+ )
37
+
38
+ return {
39
+ "model": model,
40
+ "return_mask": return_mask,
41
+ "alpha_matting": alpha_matting,
42
+ "alpha_matting_foreground_threshold": alpha_matting_foreground_threshold,
43
+ "alpha_matting_background_threshold": alpha_matting_background_threshold,
44
+ "alpha_matting_erode_size": alpha_matting_erode_size,
45
+ }
46
+
47
+ def process(self, pp: scripts_postprocessing.PostprocessedImage, model, return_mask, alpha_matting, alpha_matting_foreground_threshold, alpha_matting_background_threshold, alpha_matting_erode_size):
48
+ if model == "None":
49
+ return
50
+
51
+ pp.image = rembg.remove(
52
+ pp.image,
53
+ session=rembg.new_session(model),
54
+ only_mask=return_mask,
55
+ alpha_matting=alpha_matting,
56
+ alpha_matting_foreground_threshold=alpha_matting_foreground_threshold,
57
+ alpha_matting_background_threshold=alpha_matting_background_threshold,
58
+ alpha_matting_erode_size=alpha_matting_erode_size,
59
+ )
60
+
61
+ pp.info["Rembg"] = model
SD-two-shot-main/.gitignore ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ pip-wheel-metadata/
24
+ share/python-wheels/
25
+ *.egg-info/
26
+ .installed.cfg
27
+ *.egg
28
+ MANIFEST
29
+
30
+ # PyInstaller
31
+ # Usually these files are written by a python script from a template
32
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
33
+ *.manifest
34
+ *.spec
35
+
36
+ # Installer logs
37
+ pip-log.txt
38
+ pip-delete-this-directory.txt
39
+
40
+ # Unit test / coverage reports
41
+ htmlcov/
42
+ .tox/
43
+ .nox/
44
+ .coverage
45
+ .coverage.*
46
+ .cache
47
+ nosetests.xml
48
+ coverage.xml
49
+ *.cover
50
+ *.py,cover
51
+ .hypothesis/
52
+ .pytest_cache/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ target/
76
+
77
+ # Jupyter Notebook
78
+ .ipynb_checkpoints
79
+
80
+ # IPython
81
+ profile_default/
82
+ ipython_config.py
83
+
84
+ # pyenv
85
+ .python-version
86
+
87
+ # pipenv
88
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
89
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
90
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
91
+ # install all needed dependencies.
92
+ #Pipfile.lock
93
+
94
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow
95
+ __pypackages__/
96
+
97
+ # Celery stuff
98
+ celerybeat-schedule
99
+ celerybeat.pid
100
+
101
+ # SageMath parsed files
102
+ *.sage.py
103
+
104
+ # Environments
105
+ .env
106
+ .venv
107
+ env/
108
+ venv/
109
+ ENV/
110
+ env.bak/
111
+ venv.bak/
112
+
113
+ # Spyder project settings
114
+ .spyderproject
115
+ .spyproject
116
+
117
+ # Rope project settings
118
+ .ropeproject
119
+
120
+ # mkdocs documentation
121
+ /site
122
+
123
+ # mypy
124
+ .mypy_cache/
125
+ .dmypy.json
126
+ dmypy.json
127
+
128
+ # Pyre type checker
129
+ .pyre/
SD-two-shot-main/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2023 opparco
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
SD-two-shot-main/README.md ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Latent Couple extension (two shot diffusion port)
2
+ This extension is an extension of the built-in Composable Diffusion.
3
+ This allows you to determine the region of the latent space that reflects your subprompts.
4
+
5
+ ## How to use
6
+ ![20230303.png](./screenshots/20230303.png)
7
+ ![20230213.png](./screenshots/20230213.png)
8
+
9
+
10
+ ### Enabled
11
+ The effect of Latent Couple appears only when Enabled is checked.
12
+
13
+ ### Divisions, Positions, and Weights
14
+ Regions are created based on these parameters.
15
+
16
+ ### end at this step
17
+ The processing of Latent Couple is performed until the specified step is reached.
18
+
19
+ ### Visualize button and Regions
20
+ Press the Visualize button and you will get an image grid that visualizes the regions represented by the parameters.
21
+
22
+ ### Extra generation params and Apply button
23
+ When you press the Send to button in PNG Info, the parameters of the saved Latent Couple are set to Extra generation params.
24
+ Press the Apply button to actually apply the parameters.
25
+
26
+ ## Extra generation params
27
+ Extra generation params provided by this extension are saved as PNG Info in the output file.
28
+ ```
29
+ Latent Couple: "divisions=1:1,1:2,1:2 positions=0:0,0:0,0:1 weights=0.2,0.8,0.8 end at step=20"
30
+ ```
31
+
32
+ ## Examples
33
+ parameters
34
+ ```
35
+ ((ultra-detailed)), ((illustration)), 2girls
36
+ AND ((ultra-detailed)), ((illustration)), 2girls, black hair
37
+ AND ((ultra-detailed)), ((illustration)), 2girls, blonde hair
38
+ Negative prompt: (low quality, worst quality:1.4)
39
+ Steps: 28, Sampler: Euler a, CFG scale: 5, Seed: 722014241, Size: 512x512, Model hash: 3f64f3baf5, Model: Anything-v3.0-fp16, ENSD: 31337, Latent Couple: "divisions=1:1,1:2,1:2 positions=0:0,0:0,0:1 weights=0.2,0.8,0.8 end at step=20", Eta: 0.67
40
+ ```
41
+ outputs
42
+ - end at step=20 https://imgur.com/OEaRFgh
43
+ - end at step=4 https://imgur.com/a1kyvhX
44
+ - end at step=0 https://imgur.com/yhGF7g8
45
+
46
+
47
+ ## ~~Prerequisite for prompt pasting~~
48
+ ## ~~Prerequisite for gradio Image and Sketch component bug fix~~
49
+ This fix is no longer suitable for latest webui commit at 22bcc7be, with gradio dependency upgraded to 3.23.
50
+
51
+ I'll keep the fix here for people still using older versions of webui.
52
+
53
+ Activate your venv in webui root directory
54
+
55
+ For Windows, in cmd
56
+ ```
57
+ venv\Scripts\activate.bat
58
+ ```
59
+ For Linux
60
+ ```
61
+ source venv/bin/activate
62
+ ```
63
+ Then, install wheel distribution with bugfix applied
64
+ ```
65
+ pip install --force-reinstall --no-deps extensions/stable-diffusion-webui-two-shot/gradio-3.16.2-py3-none-any.whl
66
+ ```
67
+ For bugfix related modifications, see https://github.com/ashen-sensored/gradio/tree/3.16.2
68
+
69
+
70
+ ## Issues
71
+ - ~~The extension's mask color sketching function does not work well with chrome(extreme stuttering) due to gradio's Image component bug.~~ Please keep the browser scaling at 100% while creating blank canvas to avoid the bug.
72
+ See prerequisite above. The fix is no longer suitable for latest webui version at 22bcc7be, with gradio dependency upgraded to 3.23.
73
+
74
+
75
+ ## Credits
76
+ - two shot diffusion.ipynb https://colab.research.google.com/drive/1UdElpQfKFjY5luch9v_LlmSdH7AmeiDe?usp=sharing
SD-two-shot-main/gradio-3.16.2-py3-none-any.whl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ac6dc3848a5b5663cd276d22eff80f7d36e06eb9889aace1ec54f502ebc70933
3
+ size 14174626
SD-two-shot-main/screenshots/20230213.png ADDED
SD-two-shot-main/screenshots/20230303.png ADDED
SD-two-shot-main/scripts/sketch_helper.py ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import cv2
3
+ import base64
4
+
5
+
6
+ def count_high_freq_colors(image):
7
+ im = image.getcolors(maxcolors=1024*1024)
8
+ sorted_colors = sorted(im, key=lambda x: x[0], reverse=True)
9
+
10
+ freqs = [c[0] for c in sorted_colors]
11
+ mean_freq = sum(freqs) / len(freqs)
12
+
13
+ high_freq_colors = [c for c in sorted_colors if c[0] > max(2, mean_freq*1.25)]
14
+ return high_freq_colors
15
+
16
+ def get_high_freq_colors(image, similarity_threshold=30):
17
+ image_copy = image.copy()
18
+ high_freq_colors = count_high_freq_colors(image)
19
+ # Check for similar colors and replace the lower frequency color with the higher frequency color in the image
20
+ for i, (freq1, color1) in enumerate(high_freq_colors):
21
+ for j, (freq2, color2) in enumerate(high_freq_colors):
22
+ if (color_distance(color1, color2) < similarity_threshold) or (color_distance(color1, opaque_color_on_white(color2, 0.5)) < 5):
23
+ if(freq2 > freq1):
24
+ replace_color(image_copy, color1, color2)
25
+
26
+ high_freq_colors = count_high_freq_colors(image_copy)
27
+ print(high_freq_colors)
28
+ return [high_freq_colors, image_copy]
29
+
30
+ def color_quantization(image, color_frequency_list):
31
+ # Convert the color frequency list to a set of unique colors
32
+ unique_colors = set([color for _, color in color_frequency_list])
33
+
34
+ # Create a mask for the image with True where the color is in the unique colors set
35
+ mask = np.any(np.all(image.reshape(-1, 1, 3) == np.array(list(unique_colors)), axis=2), axis=1).reshape(image.shape[:2])
36
+
37
+ # Create a new image with all pixels set to white
38
+ new_image = np.full_like(image, 255)
39
+
40
+ # Copy the pixels from the original image that have a color in the color frequency list
41
+ new_image[mask] = image[mask]
42
+ return new_image
43
+
44
+
45
+ def create_binary_mask(img_arr, target_color):
46
+ # Create mask of pixels with target color
47
+ mask = np.all(img_arr == target_color, axis=-1)
48
+
49
+ # Convert mask to binary matrix
50
+ binary_matrix = mask.astype(int)
51
+
52
+ return binary_matrix
53
+
54
+
55
+ def create_binary_matrix_base64(img_arr, target_color):
56
+ # Create mask of pixels with target color
57
+ mask = np.all(img_arr == target_color, axis=-1)
58
+
59
+ # Convert mask to binary matrix
60
+ binary_matrix = mask.astype(int)
61
+ from datetime import datetime
62
+ binary_file_name = f'mask-{datetime.now().timestamp()}.png'
63
+ _, im_arr = cv2.imencode('.png', binary_matrix * 255)
64
+
65
+ im_bytes = im_arr.tobytes()
66
+ im_b64 = base64.b64encode(im_bytes).decode('ascii')
67
+ # binary_matrix = torch.from_numpy(binary_matrix).unsqueeze(0).unsqueeze(0)
68
+ return mask, im_b64
69
+
70
+ def create_binary_matrix_img(img_arr, target_color):
71
+ # Create mask of pixels with target color
72
+ mask = np.all(img_arr == target_color, axis=-1)
73
+
74
+ # Convert mask to binary matrix
75
+ binary_matrix = mask.astype(int)
76
+ from datetime import datetime
77
+ binary_file_name = f'mask-{datetime.now().timestamp()}.png'
78
+ cv2.imwrite(binary_file_name, binary_matrix * 255)
79
+
80
+ #binary_matrix = torch.from_numpy(binary_matrix).unsqueeze(0).unsqueeze(0)
81
+ return binary_file_name
82
+
83
+ def color_distance(color1, color2):
84
+ return sum((a - b) ** 2 for a, b in zip(color1, color2)) ** 0.5
85
+
86
+ def replace_color(image, old_color, new_color):
87
+ pixels = image.load()
88
+ width, height = image.size
89
+ for x in range(width):
90
+ for y in range(height):
91
+ if pixels[x, y] == old_color:
92
+ pixels[x, y] = new_color
93
+
94
+ def opaque_color_on_white(color, a):
95
+ r, g, b = color
96
+ opaque_red = int((1 - a) * 255 + a * r)
97
+ opaque_green = int((1 - a) * 255 + a * g)
98
+ opaque_blue = int((1 - a) * 255 + a * b)
99
+ return (opaque_red, opaque_green, opaque_blue)
SD-two-shot-main/scripts/two_shot.py ADDED
@@ -0,0 +1,594 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import base64
2
+ from typing import List, Dict, Optional, Tuple
3
+ from dataclasses import dataclass
4
+
5
+ import torch
6
+
7
+ from scripts.sketch_helper import get_high_freq_colors, color_quantization, create_binary_matrix_base64, create_binary_mask
8
+ import numpy as np
9
+ import cv2
10
+
11
+ from modules import devices, script_callbacks
12
+
13
+ import modules.scripts as scripts
14
+ import gradio as gr
15
+
16
+ from modules.script_callbacks import CFGDenoisedParams, on_cfg_denoised
17
+
18
+ from modules.processing import StableDiffusionProcessing
19
+
20
+ MAX_COLORS = 12
21
+ switch_values_symbol = '\U000021C5' # ⇅
22
+
23
+
24
+ class ToolButton(gr.Button, gr.components.FormComponent):
25
+ """Small button with single emoji as text, fits inside gradio forms"""
26
+
27
+ def __init__(self, **kwargs):
28
+ super().__init__(variant="tool", **kwargs)
29
+
30
+ def get_block_name(self):
31
+ return "button"
32
+
33
+
34
+ # abstract base class for filters
35
+ from abc import ABC, abstractmethod
36
+
37
+
38
+
39
+
40
+ class Filter(ABC):
41
+
42
+ @abstractmethod
43
+ def create_tensor(self):
44
+ pass
45
+
46
+
47
+
48
+ @dataclass
49
+ class Division:
50
+ y: float
51
+ x: float
52
+
53
+
54
+ @dataclass
55
+ class Position:
56
+ y: float
57
+ x: float
58
+ ey: float
59
+ ex: float
60
+
61
+
62
+
63
+ class RectFilter(Filter):
64
+ def __init__(self, division: Division, position: Position, weight: float):
65
+ self.division = division
66
+ self.position = position
67
+ self.weight = weight
68
+
69
+ def create_tensor(self, num_channels: int, height_b: int, width_b: int) -> torch.Tensor:
70
+
71
+ x = torch.zeros(num_channels, height_b, width_b).to(devices.device)
72
+
73
+ division_height = height_b / self.division.y
74
+ division_width = width_b / self.division.x
75
+ y1 = int(division_height * self.position.y)
76
+ y2 = int(division_height * self.position.ey)
77
+ x1 = int(division_width * self.position.x)
78
+ x2 = int(division_width * self.position.ex)
79
+
80
+ x[:, y1:y2, x1:x2] = self.weight
81
+
82
+ return x
83
+
84
+
85
+ class MaskFilter:
86
+ def __init__(self, binary_mask: np.array = None, weight: float = None, float_mask: np.array = None):
87
+ if float_mask is None:
88
+ self.mask = binary_mask.astype(np.float32) * weight
89
+ elif binary_mask is None and weight is None:
90
+ self.mask = float_mask
91
+ else:
92
+ raise ValueError('Either float_mask or binary_mask and weight must be provided')
93
+ self.tensor_mask = torch.tensor(self.mask).to(devices.device)
94
+
95
+ def create_tensor(self, num_channels: int, height_b: int, width_b: int) -> torch.Tensor:
96
+
97
+
98
+ # x = torch.zeros(num_channels, height_b, width_b).to(devices.device)
99
+ # mask = torch.tensor(self.mask).to(devices.device)
100
+ # downsample mask to x size
101
+ # mask_bicubic = torch.nn.functional.interpolate(mask.unsqueeze(0).unsqueeze(0), size=(height_b, width_b), mode='bicubic').squeeze(0).squeeze(0).cpu().numpy()
102
+ #
103
+ # mask_nearest_exact = torch.nn.functional.interpolate(mask.unsqueeze(0).unsqueeze(0), size=(height_b, width_b), mode='nearest-exact').squeeze(0).squeeze(0).cpu().numpy()
104
+ #
105
+ # mask_nearest = torch.nn.functional.interpolate(mask.unsqueeze(0).unsqueeze(0), size=(height_b, width_b), mode='nearest').squeeze(0).squeeze(0).cpu().numpy()
106
+ #
107
+ # mask_area = torch.nn.functional.interpolate(mask.unsqueeze(0).unsqueeze(0), size=(height_b, width_b), mode='area').squeeze(0).squeeze(0).cpu().numpy()
108
+
109
+ mask = torch.nn.functional.interpolate(self.tensor_mask.unsqueeze(0).unsqueeze(0), size=(height_b, width_b), mode='nearest-exact').squeeze(0).squeeze(0)
110
+ mask = mask.unsqueeze(0).repeat(num_channels, 1, 1)
111
+
112
+ return mask
113
+
114
+
115
+ class PastePromptTextboxTracker:
116
+ def __init__(self):
117
+ self.scripts = []
118
+ return
119
+
120
+ def set_script(self, script):
121
+ self.scripts.append(script)
122
+
123
+ def on_after_component_callback(self, component, **_kwargs):
124
+
125
+ if not self.scripts:
126
+ return
127
+ if type(component) is gr.State:
128
+ return
129
+
130
+ script = None
131
+ if type(component) is gr.Textbox and component.elem_id == 'txt2img_prompt':
132
+ # select corresponding script
133
+ script = next(x for x in self.scripts if x.is_txt2img)
134
+ self.scripts.remove(script)
135
+
136
+ if type(component) is gr.Textbox and component.elem_id == 'img2img_prompt':
137
+ # select corresponding script
138
+ script = next(x for x in self.scripts if x.is_img2img)
139
+ self.scripts.remove(script)
140
+
141
+ if script is None:
142
+ return
143
+
144
+ script.target_paste_prompt = component
145
+
146
+
147
+ prompt_textbox_tracker = PastePromptTextboxTracker()
148
+
149
+
150
+ class Script(scripts.Script):
151
+
152
+ def __init__(self):
153
+ self.ui_root = None
154
+ self.num_batches: int = 0
155
+ self.end_at_step: int = 20
156
+ self.filters: List[Filter] = []
157
+ self.debug: bool = False
158
+ self.selected_twoshot_tab = 0
159
+ self.ndmasks = []
160
+ self.area_colors = []
161
+ self.mask_denoise = False
162
+ prompt_textbox_tracker.set_script(self)
163
+ self.target_paste_prompt = None
164
+
165
+
166
+ def title(self):
167
+ return "Latent Couple extension"
168
+
169
+ def show(self, is_img2img):
170
+ return scripts.AlwaysVisible
171
+
172
+ def create_rect_filters_from_ui_params(self, raw_divisions: str, raw_positions: str, raw_weights: str):
173
+
174
+ divisions = []
175
+ for division in raw_divisions.split(','):
176
+ y, x = division.split(':')
177
+ divisions.append(Division(float(y), float(x)))
178
+
179
+ def start_and_end_position(raw: str):
180
+ nums = [float(num) for num in raw.split('-')]
181
+ if len(nums) == 1:
182
+ return nums[0], nums[0] + 1.0
183
+ else:
184
+ return nums[0], nums[1]
185
+
186
+ positions = []
187
+ for position in raw_positions.split(','):
188
+ y, x = position.split(':')
189
+ y1, y2 = start_and_end_position(y)
190
+ x1, x2 = start_and_end_position(x)
191
+ positions.append(Position(y1, x1, y2, x2))
192
+
193
+ weights = []
194
+ for w in raw_weights.split(','):
195
+ weights.append(float(w))
196
+
197
+ # todo: assert len
198
+
199
+ return [RectFilter(division, position, weight) for division, position, weight in zip(divisions, positions, weights)]
200
+
201
+ def create_mask_filters_from_ui_params(self, raw_divisions: str, raw_positions: str, raw_weights: str):
202
+
203
+ divisions = []
204
+ for division in raw_divisions.split(','):
205
+ y, x = division.split(':')
206
+ divisions.append(Division(float(y), float(x)))
207
+
208
+ def start_and_end_position(raw: str):
209
+ nums = [float(num) for num in raw.split('-')]
210
+ if len(nums) == 1:
211
+ return nums[0], nums[0] + 1.0
212
+ else:
213
+ return nums[0], nums[1]
214
+
215
+ positions = []
216
+ for position in raw_positions.split(','):
217
+ y, x = position.split(':')
218
+ y1, y2 = start_and_end_position(y)
219
+ x1, x2 = start_and_end_position(x)
220
+ positions.append(Position(y1, x1, y2, x2))
221
+
222
+ weights = []
223
+ for w in raw_weights.split(','):
224
+ weights.append(float(w))
225
+
226
+ # todo: assert len
227
+
228
+ return [Filter(division, position, weight) for division, position, weight in zip(divisions, positions, weights)]
229
+
230
+ def do_visualize(self, raw_divisions: str, raw_positions: str, raw_weights: str):
231
+
232
+ self.filters = self.create_rect_filters_from_ui_params(raw_divisions, raw_positions, raw_weights)
233
+
234
+ return [f.create_tensor(1, 128, 128).squeeze(dim=0).cpu().numpy() for f in self.filters]
235
+
236
+ def do_apply(self, extra_generation_params: str):
237
+ #
238
+ # parse "Latent Couple" extra_generation_params
239
+ #
240
+ raw_params = {}
241
+
242
+ for assignment in extra_generation_params.split(' '):
243
+ pair = assignment.split('=', 1)
244
+ if len(pair) != 2:
245
+ continue
246
+ raw_params[pair[0]] = pair[1]
247
+
248
+ return raw_params.get('divisions', '1:1,1:2,1:2'), raw_params.get('positions', '0:0,0:0,0:1'), raw_params.get('weights', '0.2,0.8,0.8'), int(raw_params.get('step', '20'))
249
+
250
+ def ui(self, is_img2img):
251
+ process_script_params = []
252
+ id_part = "img2img" if is_img2img else "txt2img"
253
+ canvas_html = "<div id='canvas-root' style='max-width:400px; margin: 0 auto'></div>"
254
+ # get_js_colors = """
255
+ # async (canvasData) => {
256
+ # const canvasEl = document.getElementById("canvas-root");
257
+ # return [canvasEl._data]
258
+ # }
259
+ # """
260
+
261
+ def create_canvas(h, w):
262
+ return np.zeros(shape=(h, w, 3), dtype=np.uint8) + 255
263
+
264
+ def process_sketch(img_arr, input_binary_matrixes):
265
+ input_binary_matrixes.clear()
266
+ # base64_img = canvas_data['image']
267
+ # image_data = base64.b64decode(base64_img.split(',')[1])
268
+ # image = Image.open(BytesIO(image_data)).convert("RGB")
269
+ im2arr = img_arr
270
+ # colors = [tuple(map(int, rgb[4:-1].split(','))) for rgb in
271
+ # ['colors']]
272
+ sketch_colors, color_counts = np.unique(im2arr.reshape(-1, im2arr.shape[2]), axis=0, return_counts=True)
273
+ colors_fixed = []
274
+ # if color count is less than 0.001 of total pixel count, collect it for edge color correction
275
+ edge_color_correction_arr = []
276
+ for sketch_color_idx, color in enumerate(sketch_colors[:-1]): # exclude white
277
+ if color_counts[sketch_color_idx] < im2arr.shape[0] * im2arr.shape[1] * 0.002:
278
+ edge_color_correction_arr.append(sketch_color_idx)
279
+
280
+ edge_fix_dict = {}
281
+ # TODO:for every non area color pixel in img_arr, find the nearest area color pixel and replace it with that color
282
+
283
+ area_colors = np.delete(sketch_colors, edge_color_correction_arr, axis=0)
284
+ if self.mask_denoise:
285
+ for edge_color_idx in edge_color_correction_arr:
286
+ edge_color = sketch_colors[edge_color_idx]
287
+ # find the nearest area_color
288
+
289
+ color_distances = np.linalg.norm(area_colors - edge_color, axis=1)
290
+ nearest_index = np.argmin(color_distances)
291
+ nearest_color = area_colors[nearest_index]
292
+ edge_fix_dict[edge_color_idx] = nearest_color
293
+ # replace edge color with the nearest area_color
294
+ cur_color_mask = np.all(im2arr == edge_color, axis=2)
295
+ im2arr[cur_color_mask] = nearest_color
296
+
297
+ # recalculate area colors
298
+ sketch_colors, color_counts = np.unique(im2arr.reshape(-1, im2arr.shape[2]), axis=0, return_counts=True)
299
+ area_colors = sketch_colors
300
+
301
+ # create binary matrix for each area_color
302
+ area_color_maps = []
303
+ self.ndmasks = []
304
+ self.area_colors = area_colors
305
+ for color in area_colors:
306
+ r, g, b = color
307
+ mask, binary_matrix = create_binary_matrix_base64(im2arr, color)
308
+ self.ndmasks.append(mask)
309
+ input_binary_matrixes.append(binary_matrix)
310
+ colors_fixed.append(gr.update(
311
+ value=f'<div style="display:flex;justify-content:center;max-height: 94px;"><img width="20%" style="object-fit: contain;flex-grow:1;margin-right: 1em;" src="data:image/png;base64,{binary_matrix}" /><div class="color-bg-item" style="background-color: rgb({r},{g},{b});width:10%;height:auto;"></div></div>'))
312
+
313
+
314
+
315
+ visibilities = []
316
+ sketch_colors = []
317
+
318
+ for sketch_color_idx in range(MAX_COLORS):
319
+ visibilities.append(gr.update(visible=False))
320
+ sketch_colors.append(gr.update(value=f'<div class="color-bg-item" style="background-color: black"></div>'))
321
+ for j in range(len(colors_fixed)-1):
322
+ visibilities[j] = gr.update(visible=True)
323
+ sketch_colors[j] = colors_fixed[j]
324
+
325
+ alpha_mask_visibility = gr.update(visible=True)
326
+ alpha_mask_html = colors_fixed[-1]
327
+ return [gr.update(visible=True), input_binary_matrixes, alpha_mask_visibility, alpha_mask_html, *visibilities, *sketch_colors]
328
+
329
+ def update_mask_filters(alpha_blend_val, general_prompt_str, *cur_weights_and_prompts):
330
+ cur_weight_slider_vals = cur_weights_and_prompts[:MAX_COLORS]
331
+ cur_prompts = cur_weights_and_prompts[MAX_COLORS:]
332
+ general_mask = self.ndmasks[-1]
333
+ final_filter_list = []
334
+ for m in range(len(self.ndmasks) - 1):
335
+ cur_float_mask = self.ndmasks[m].astype(np.float32) * float(cur_weight_slider_vals[m]) * float(1.0-alpha_blend_val)
336
+ mask_filter = MaskFilter(float_mask=cur_float_mask)
337
+ final_filter_list.append(mask_filter)
338
+ # subtract the sum of all masks from the general mask to get the alpha blend mask
339
+ initial_general_mask = np.ones(shape=general_mask.shape, dtype=np.float32)
340
+ alpha_blend_mask = initial_general_mask.astype(np.float32) - np.sum([f.mask for f in final_filter_list], axis=0)
341
+ alpha_blend_filter = MaskFilter(float_mask=alpha_blend_mask)
342
+ final_filter_list.insert(0, alpha_blend_filter)
343
+ self.filters = final_filter_list
344
+
345
+
346
+ sketch_colors = []
347
+ colors_fixed = []
348
+ for area_idx, color in enumerate(self.area_colors):
349
+ r, g, b = color
350
+ final_list_idx = area_idx + 1
351
+ if final_list_idx == len(final_filter_list):
352
+ final_list_idx = 0
353
+ # get shape of current mask
354
+ height_b, width_b = final_filter_list[final_list_idx].mask.shape
355
+ current_mask = torch.nn.functional.interpolate(final_filter_list[final_list_idx].tensor_mask.unsqueeze(0).unsqueeze(0),
356
+ size=(int(height_b/8), int(width_b/8)), mode='nearest-exact').squeeze(0).squeeze(0).cpu().numpy()
357
+ adjusted_mask = current_mask * 255
358
+ _, adjusted_mask_arr = cv2.imencode('.png', adjusted_mask)
359
+
360
+ adjusted_mask_b64 = base64.b64encode(adjusted_mask_arr.tobytes()).decode('ascii')
361
+ colors_fixed.append(gr.update(
362
+ value=f'<div style="display:flex;justify-content:center;max-height: 94px;"><img width="20%" style="object-fit: contain;flex-grow:1;margin-right: 1em;" src="data:image/png;base64,{adjusted_mask_b64}" /><div class="color-bg-item" style="background-color: rgb({r},{g},{b});width:10%;height:auto;"></div></div>'))
363
+ for sketch_color_idx in range(MAX_COLORS):
364
+
365
+ sketch_colors.append(
366
+ gr.update(value=f'<div class="color-bg-item" style="background-color: black"></div>'))
367
+ for j in range(len(colors_fixed)-1):
368
+
369
+ sketch_colors[j] = colors_fixed[j]
370
+ alpha_mask_visibility = gr.update(visible=True)
371
+ alpha_mask_html = colors_fixed[-1]
372
+ final_prompt_update = gr.update(value='\nAND '.join([general_prompt_str, *cur_prompts[:len(colors_fixed)-1]]))
373
+ return [final_prompt_update, alpha_mask_visibility, alpha_mask_html, *sketch_colors]
374
+
375
+
376
+
377
+ cur_weight_sliders = []
378
+
379
+ with gr.Group() as group_two_shot_root:
380
+ binary_matrixes = gr.State([])
381
+ with gr.Accordion("Latent Couple", open=False):
382
+ enabled = gr.Checkbox(value=False, label="Enabled")
383
+ with gr.Tabs(elem_id="script_twoshot_tabs") as twoshot_tabs:
384
+
385
+ with gr.TabItem("Mask", elem_id="tab_twoshot_mask") as twoshot_tab_mask:
386
+
387
+ canvas_data = gr.JSON(value={}, visible=False)
388
+ # model = gr.Textbox(label="The id of any Hugging Face model in the diffusers format",
389
+ # value="stabilityai/stable-diffusion-2-1-base",
390
+ # visible=False if is_shared_ui else True)
391
+ mask_denoise_checkbox = gr.Checkbox(value=False, label="Denoise Mask")
392
+
393
+ def update_mask_denoise_flag(flag):
394
+ self.mask_denoise = flag
395
+
396
+ mask_denoise_checkbox.change(fn=update_mask_denoise_flag, inputs=[mask_denoise_checkbox], outputs=None)
397
+ canvas_image = gr.Image(source='upload', mirror_webcam=False, type='numpy', tool='color-sketch',
398
+ elem_id='twoshot_canvas_sketch', interactive=True).style(height=480)
399
+ # aspect = gr.Radio(["square", "horizontal", "vertical"], value="square", label="Aspect Ratio",
400
+ # visible=False if is_shared_ui else True)
401
+ button_run = gr.Button("I've finished my sketch", elem_id="main_button", interactive=True)
402
+
403
+ prompts = []
404
+ colors = []
405
+ color_row = [None] * MAX_COLORS
406
+ with gr.Column(visible=False) as post_sketch:
407
+ with gr.Row(visible=False) as alpha_mask_row:
408
+ # general_mask_label_span = gr.HTML(
409
+ # '<span class="text-gray-500 text-[0.855rem] mb-2 block dark:text-gray-200 relative z-40">General Mask</span>',
410
+ # elem_id='general_mask_label_span')
411
+ with gr.Box(elem_id="alpha_mask"):
412
+ alpha_color = gr.HTML(
413
+ '<div class="alpha-mask-item" style="background-color: black"></div>')
414
+ general_prompt = gr.Textbox(label="General Prompt")
415
+ alpha_blend = gr.Slider(label="Alpha Blend", minimum=0.0, maximum=1.0, value=0.2, step=0.01, interactive=True)
416
+
417
+ for n in range(MAX_COLORS):
418
+ with gr.Row(visible=False) as color_row[n]:
419
+
420
+ with gr.Box(elem_id="color-bg"):
421
+ colors.append(gr.HTML(
422
+ '<div class="color-bg-item" style="background-color: black"></div>'))
423
+ with gr.Column():
424
+ with gr.Row():
425
+ prompts.append(gr.Textbox(label="Prompt for this mask"))
426
+
427
+ with gr.Row():
428
+ weight_slider = gr.Slider(label=f"Area {n+1} Weight", minimum=0.0, maximum=1.0,
429
+ value=1.0, step=0.01, interactive=True, elem_id=f"weight_{n+1}_slider")
430
+ cur_weight_sliders.append(weight_slider)
431
+
432
+ button_update = gr.Button("Prompt Info Update", elem_id="update_button", interactive=True)
433
+ final_prompt = gr.Textbox(label="Final Prompt", interactive=False)
434
+
435
+ button_run.click(process_sketch, inputs=[canvas_image, binary_matrixes],
436
+ outputs=[post_sketch, binary_matrixes, alpha_mask_row, alpha_color, *color_row, *colors],
437
+ queue=False)
438
+
439
+ button_update.click(fn=update_mask_filters, inputs=[alpha_blend, general_prompt, *cur_weight_sliders, *prompts], outputs=[final_prompt, alpha_mask_row, alpha_color, *colors])
440
+
441
+ def paste_prompt(*input_prompts):
442
+ final_prompts = input_prompts[:len(self.area_colors)]
443
+ final_prompt_str = '\nAND '.join(final_prompts)
444
+ return final_prompt_str
445
+ source_prompts = [general_prompt, *prompts]
446
+ button_update.click(fn=paste_prompt, inputs=source_prompts,
447
+ outputs=self.target_paste_prompt)
448
+
449
+
450
+
451
+ with gr.Column():
452
+ canvas_width = gr.Slider(label="Canvas Width", minimum=256, maximum=1024, value=512, step=64)
453
+ canvas_height = gr.Slider(label="Canvas Height", minimum=256, maximum=1024, value=512, step=64)
454
+
455
+
456
+ canvas_swap_res = ToolButton(value=switch_values_symbol)
457
+ canvas_swap_res.click(lambda w, h: (h, w), inputs=[canvas_width, canvas_height],
458
+ outputs=[canvas_width, canvas_height])
459
+ create_button = gr.Button(value="Create blank canvas")
460
+ create_button.click(fn=create_canvas, inputs=[canvas_height, canvas_width], outputs=[canvas_image])
461
+
462
+ with gr.TabItem("Rectangular", elem_id="tab_twoshot_rect") as twoshot_tab_rect:
463
+ with gr.Row():
464
+ divisions = gr.Textbox(label="Divisions", elem_id=f"cd_{id_part}_divisions", value="1:1,1:2,1:2")
465
+ positions = gr.Textbox(label="Positions", elem_id=f"cd_{id_part}_positions", value="0:0,0:0,0:1")
466
+ with gr.Row():
467
+ weights = gr.Textbox(label="Weights", elem_id=f"cd_{id_part}_weights", value="0.2,0.8,0.8")
468
+ end_at_step = gr.Slider(minimum=0, maximum=150, step=1, label="end at this step", elem_id=f"cd_{id_part}_end_at_this_step", value=150)
469
+
470
+ visualize_button = gr.Button(value="Visualize")
471
+ visual_regions = gr.Gallery(label="Regions").style(grid=(4, 4, 4, 8), height="auto")
472
+
473
+ visualize_button.click(fn=self.do_visualize, inputs=[divisions, positions, weights], outputs=[visual_regions])
474
+
475
+ extra_generation_params = gr.Textbox(label="Extra generation params")
476
+ apply_button = gr.Button(value="Apply")
477
+
478
+ apply_button.click(fn=self.do_apply, inputs=[extra_generation_params], outputs=[divisions, positions, weights, end_at_step])
479
+
480
+ def select_twosoht_tab(tab_id):
481
+ self.selected_twoshot_tab = tab_id
482
+ for i, elem in enumerate(
483
+ [twoshot_tab_mask, twoshot_tab_rect]):
484
+ elem.select(
485
+ fn=lambda tab=i: select_twosoht_tab(tab),
486
+ inputs=[],
487
+ outputs=[],
488
+ )
489
+
490
+ self.ui_root = group_two_shot_root
491
+
492
+ self.infotext_fields = [
493
+ (extra_generation_params, "Latent Couple")
494
+ ]
495
+ process_script_params.append(enabled)
496
+ process_script_params.append(divisions)
497
+ process_script_params.append(positions)
498
+ process_script_params.append(weights)
499
+ process_script_params.append(end_at_step)
500
+ process_script_params.append(alpha_blend)
501
+ process_script_params.extend(cur_weight_sliders)
502
+ return process_script_params
503
+
504
+ def denoised_callback(self, params: CFGDenoisedParams):
505
+
506
+ if self.enabled and params.sampling_step < self.end_at_step:
507
+
508
+ x = params.x
509
+ # x.shape = [batch_size, C, H // 8, W // 8]
510
+
511
+ num_batches = self.num_batches
512
+ num_prompts = x.shape[0] // num_batches
513
+ # ex. num_batches = 3
514
+ # ex. num_prompts = 3 (tensor) + 1 (uncond)
515
+
516
+ if self.debug:
517
+ print(f"### Latent couple ###")
518
+ print(f"denoised_callback x.shape={x.shape} num_batches={num_batches} num_prompts={num_prompts}")
519
+
520
+ filters = [
521
+ f.create_tensor(x.shape[1], x.shape[2], x.shape[3]) for f in self.filters
522
+ ]
523
+ neg_filters = [1.0 - f for f in filters]
524
+
525
+ """
526
+ batch #1
527
+ subprompt #1
528
+ subprompt #2
529
+ subprompt #3
530
+ batch #2
531
+ subprompt #1
532
+ subprompt #2
533
+ subprompt #3
534
+ uncond
535
+ batch #1
536
+ batch #2
537
+ """
538
+
539
+ tensor_off = 0
540
+ uncond_off = num_batches * num_prompts - num_batches
541
+ for b in range(num_batches):
542
+ uncond = x[uncond_off, :, :, :]
543
+
544
+ for p in range(num_prompts - 1):
545
+ if self.debug:
546
+ print(f"b={b} p={p}")
547
+ if p < len(filters):
548
+ tensor = x[tensor_off, :, :, :]
549
+ x[tensor_off, :, :, :] = tensor * filters[p] + uncond * neg_filters[p]
550
+
551
+ tensor_off += 1
552
+
553
+ uncond_off += 1
554
+
555
+ def process(self, p: StableDiffusionProcessing, *args, **kwargs):
556
+
557
+ enabled, raw_divisions, raw_positions, raw_weights, raw_end_at_step, alpha_blend, *cur_weight_sliders = args
558
+
559
+ self.enabled = enabled
560
+
561
+ if not self.enabled:
562
+ return
563
+
564
+ self.num_batches = p.batch_size
565
+
566
+ if self.selected_twoshot_tab == 0:
567
+ pass
568
+ elif self.selected_twoshot_tab == 1:
569
+ self.filters = self.create_rect_filters_from_ui_params(raw_divisions, raw_positions, raw_weights)
570
+ else:
571
+ raise ValueError(f"Unknown filter mode")
572
+
573
+ self.end_at_step = raw_end_at_step
574
+
575
+ # TODO: handle different cases for generation info: 'mask' and 'rect'
576
+ # if self.end_at_step != 0:
577
+ # p.extra_generation_params["Latent Couple"] = f"divisions={raw_divisions} positions={raw_positions} weights={raw_weights} end at step={raw_end_at_step}"
578
+
579
+
580
+ if self.debug:
581
+ print(f"### Latent couple ###")
582
+ print(f"process num_batches={self.num_batches} end_at_step={self.end_at_step}")
583
+
584
+ if not hasattr(self, 'callbacks_added'):
585
+ on_cfg_denoised(self.denoised_callback)
586
+ self.callbacks_added = True
587
+
588
+ return
589
+
590
+ def postprocess(self, *args):
591
+ return
592
+
593
+
594
+ script_callbacks.on_after_component(prompt_textbox_tracker.on_after_component_callback)
SD-two-shot-main/style.css ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ #twoshot_canvas_sketch, #twoshot_canvas_sketch > .h-60, #twoshot_canvas_sketch > .h-60 > div, #twoshot_canvas_sketch > .h-60 > div > img
3
+ {
4
+ height: 480px !important;
5
+ max-height: 480px !important;
6
+ /*min-height: 480px !important;*/
7
+ }
8
+
9
+ #color-bg > .gr-box, #color-bg > .gr-box > .transition, #color-bg > .gr-box > .transition > .output-html
10
+ {
11
+ height: 100%;
12
+ }
13
+
14
+ #color-bg{
15
+ max-height: 110px;
16
+ }
17
+
18
+ #alpha_mask{
19
+ max-height: 110px;
20
+ }
21
+
22
+ #general_mask_label_span{
23
+ position: absolute;
24
+ }
25
+
26
+ #script_twoshot_tabs .output-html{
27
+ display: flex;
28
+ justify-content: center;
29
+ align-items: center;
30
+ }
31
+
32
+ #script_twoshot_tabs .gradio-image > div.fixed-height, #script_twoshot_tabs .gradio-image > div.fixed-height img {
33
+ height: 480px !important;
34
+ max-height: 480px !important;
35
+ min-height: 480px !important;
36
+ }