Skip to content

Commit 8dc1030

Browse files
committed
2 parents 59f91bd + 5447455 commit 8dc1030

8 files changed

+830
-10
lines changed

localizations/zh_CN.json

+1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
"Prompt matrix": "提示词矩阵",
8585
"Prompts from file or textbox": "从文本框或文件载入提示词",
8686
"X/Y plot": "X/Y 图表",
87+
"X/Y/Z plot": "X/Y/Z 图表",
8788
"Source embedding to convert": "用于转换的源 Embedding",
8889
"Embedding token": "Embedding 的 token (关键词)",
8990
"Output directory": "输出目录",

modules/generation_parameters_copypaste.py

+9-6
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@
22
import io
33
import os
44
import re
5-
from pathlib import Path
65

76
import gradio as gr
87
from modules.shared import script_path
9-
from modules import shared
10-
import tempfile
8+
from modules import shared, ui_tempdir
119
from PIL import Image
1210

1311
re_param_code = r'\s*([\w ]+):\s*("(?:\\|\"|[^\"])+"|[^,]*)(?:,|$)'
@@ -35,9 +33,15 @@ def quote(text):
3533

3634

3735
def image_from_url_text(filedata):
38-
if type(filedata) == dict and filedata["is_file"]:
36+
if filedata is None:
37+
return None
38+
39+
if type(filedata) == list and len(filedata) > 0 and type(filedata[0]) == dict and filedata[0].get("is_file", False):
40+
filedata = filedata[0]
41+
42+
if type(filedata) == dict and filedata.get("is_file", False):
3943
filename = filedata["name"]
40-
is_in_right_dir = any(Path(temp_dir).resolve() in Path(filename).resolve().parents for temp_dir in shared.demo.temp_dirs)
44+
is_in_right_dir = ui_tempdir.check_tmp_file(shared.demo, filename)
4145
assert is_in_right_dir, 'trying to open image file outside of allowed directories'
4246

4347
return Image.open(filename)
@@ -55,7 +59,6 @@ def image_from_url_text(filedata):
5559
image = Image.open(io.BytesIO(filedata))
5660
return image
5761

58-
5962
def add_paste_fields(tabname, init_img, fields):
6063
paste_fields[tabname] = {"init_img": init_img, "fields": fields}
6164

modules/images.py

+91-1
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,98 @@ def __init__(self, text='', is_active=True):
124124
self.is_active = is_active
125125
self.size = None
126126

127+
def draw_grid_annotations(im, width, height, hor_texts, ver_texts, margin=0):
128+
def wrap(drawing, text, font, line_length):
129+
lines = ['']
130+
for word in text.split():
131+
line = f'{lines[-1]} {word}'.strip()
132+
if drawing.textlength(line, font=font) <= line_length:
133+
lines[-1] = line
134+
else:
135+
lines.append(word)
136+
return lines
137+
138+
def get_font(fontsize):
139+
try:
140+
return ImageFont.truetype(opts.font or Roboto, fontsize)
141+
except Exception:
142+
return ImageFont.truetype(Roboto, fontsize)
143+
144+
def draw_texts(drawing, draw_x, draw_y, lines, initial_fnt, initial_fontsize):
145+
for i, line in enumerate(lines):
146+
fnt = initial_fnt
147+
fontsize = initial_fontsize
148+
while drawing.multiline_textsize(line.text, font=fnt)[0] > line.allowed_width and fontsize > 0:
149+
fontsize -= 1
150+
fnt = get_font(fontsize)
151+
drawing.multiline_text((draw_x, draw_y + line.size[1] / 2), line.text, font=fnt, fill=color_active if line.is_active else color_inactive, anchor="mm", align="center")
152+
153+
if not line.is_active:
154+
drawing.line((draw_x - line.size[0] // 2, draw_y + line.size[1] // 2, draw_x + line.size[0] // 2, draw_y + line.size[1] // 2), fill=color_inactive, width=4)
155+
156+
draw_y += line.size[1] + line_spacing
157+
158+
fontsize = (width + height) // 25
159+
line_spacing = fontsize // 2
160+
161+
fnt = get_font(fontsize)
162+
163+
color_active = (0, 0, 0)
164+
color_inactive = (153, 153, 153)
165+
166+
pad_left = 0 if sum([sum([len(line.text) for line in lines]) for lines in ver_texts]) == 0 else width * 3 // 4
167+
168+
cols = im.width // width
169+
rows = im.height // height
170+
171+
assert cols == len(hor_texts), f'bad number of horizontal texts: {len(hor_texts)}; must be {cols}'
172+
assert rows == len(ver_texts), f'bad number of vertical texts: {len(ver_texts)}; must be {rows}'
173+
174+
calc_img = Image.new("RGB", (1, 1), "white")
175+
calc_d = ImageDraw.Draw(calc_img)
176+
177+
for texts, allowed_width in zip(hor_texts + ver_texts, [width] * len(hor_texts) + [pad_left] * len(ver_texts)):
178+
items = [] + texts
179+
texts.clear()
180+
181+
for line in items:
182+
wrapped = wrap(calc_d, line.text, fnt, allowed_width)
183+
texts += [GridAnnotation(x, line.is_active) for x in wrapped]
184+
185+
for line in texts:
186+
bbox = calc_d.multiline_textbbox((0, 0), line.text, font=fnt)
187+
line.size = (bbox[2] - bbox[0], bbox[3] - bbox[1])
188+
line.allowed_width = allowed_width
189+
190+
hor_text_heights = [sum([line.size[1] + line_spacing for line in lines]) - line_spacing for lines in hor_texts]
191+
ver_text_heights = [sum([line.size[1] + line_spacing for line in lines]) - line_spacing * len(lines) for lines in ver_texts]
192+
193+
pad_top = 0 if sum(hor_text_heights) == 0 else max(hor_text_heights) + line_spacing * 2
194+
195+
result = Image.new("RGB", (im.width + pad_left + margin * (cols-1), im.height + pad_top + margin * (rows-1)), "white")
196+
197+
for row in range(rows):
198+
for col in range(cols):
199+
cell = im.crop((width * col, height * row, width * (col+1), height * (row+1)))
200+
result.paste(cell, (pad_left + (width + margin) * col, pad_top + (height + margin) * row))
201+
202+
d = ImageDraw.Draw(result)
203+
204+
for col in range(cols):
205+
x = pad_left + (width + margin) * col + width / 2
206+
y = pad_top / 2 - hor_text_heights[col] / 2
207+
208+
draw_texts(d, x, y, hor_texts[col], fnt, fontsize)
209+
210+
for row in range(rows):
211+
x = pad_left / 2
212+
y = pad_top + (height + margin) * row + height / 2 - ver_text_heights[row] / 2
213+
214+
draw_texts(d, x, y, ver_texts[row], fnt, fontsize)
215+
216+
return result
127217

128-
def draw_grid_annotations(im, width, height, hor_texts, ver_texts):
218+
def draw_grid_annotations_old(im, width, height, hor_texts, ver_texts):
129219
def wrap(drawing, text, font, line_length):
130220
lines = ['']
131221
for word in text.split():

modules/scripts.py

+9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import os
22
import sys
33
import traceback
4+
import re
45
from collections import namedtuple
56

67
import gradio as gr
@@ -116,7 +117,15 @@ def after_component(self, component, **kwargs):
116117
def describe(self):
117118
"""unused"""
118119
return ""
120+
121+
def elem_id(self, item_id):
122+
"""helper function to generate id for a HTML element, constructs final id out of script name, tab and user-supplied item_id"""
119123

124+
need_tabname = self.show(True) == self.show(False)
125+
tabname = ('img2img' if self.is_img2img else 'txt2txt') + "_" if need_tabname else ""
126+
title = re.sub(r'[^a-z_0-9]', '', re.sub(r'\s', '_', self.title().lower()))
127+
128+
return f'script_{tabname}{title}_{item_id}'
120129

121130
current_basedir = paths.script_path
122131

modules/ui_components.py

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import gradio as gr
2+
3+
4+
class ToolButton(gr.Button, gr.components.FormComponent):
5+
"""Small button with single emoji as text, fits inside gradio forms"""
6+
7+
def __init__(self, **kwargs):
8+
super().__init__(variant="tool", **kwargs)
9+
10+
def get_block_name(self):
11+
return "button"
12+
13+
14+
class ToolButtonTop(gr.Button, gr.components.FormComponent):
15+
"""Small button with single emoji as text, with extra margin at top, fits inside gradio forms"""
16+
17+
def __init__(self, **kwargs):
18+
super().__init__(variant="tool-top", **kwargs)
19+
20+
def get_block_name(self):
21+
return "button"
22+
23+
24+
class FormRow(gr.Row, gr.components.FormComponent):
25+
"""Same as gr.Row but fits inside gradio forms"""
26+
27+
def get_block_name(self):
28+
return "row"
29+
30+
31+
class FormGroup(gr.Group, gr.components.FormComponent):
32+
"""Same as gr.Row but fits inside gradio forms"""
33+
34+
def get_block_name(self):
35+
return "group"
36+
37+
38+
class FormHTML(gr.HTML, gr.components.FormComponent):
39+
"""Same as gr.HTML but fits inside gradio forms"""
40+
41+
def get_block_name(self):
42+
return "html"
43+
44+
45+
class FormColorPicker(gr.ColorPicker, gr.components.FormComponent):
46+
"""Same as gr.ColorPicker but fits inside gradio forms"""
47+
48+
def get_block_name(self):
49+
return "colorpicker"
50+
51+
52+
class DropdownMulti(gr.Dropdown):
53+
"""Same as gr.Dropdown but always multiselect"""
54+
def __init__(self, **kwargs):
55+
super().__init__(multiselect=True, **kwargs)
56+
57+
def get_block_name(self):
58+
return "dropdown"

modules/ui_tempdir.py

+22-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import os
22
import tempfile
33
from collections import namedtuple
4+
from pathlib import Path
45

56
import gradio as gr
67

@@ -12,10 +13,29 @@
1213
Savedfile = namedtuple("Savedfile", ["name"])
1314

1415

16+
def register_tmp_file(gradio, filename):
17+
if hasattr(gradio, 'temp_file_sets'): # gradio 3.15
18+
gradio.temp_file_sets[0] = gradio.temp_file_sets[0] | {os.path.abspath(filename)}
19+
20+
if hasattr(gradio, 'temp_dirs'): # gradio 3.9
21+
gradio.temp_dirs = gradio.temp_dirs | {os.path.abspath(os.path.dirname(filename))}
22+
23+
24+
def check_tmp_file(gradio, filename):
25+
if hasattr(gradio, 'temp_file_sets'):
26+
return any([filename in fileset for fileset in gradio.temp_file_sets])
27+
28+
if hasattr(gradio, 'temp_dirs'):
29+
return any(Path(temp_dir).resolve() in Path(filename).resolve().parents for temp_dir in gradio.temp_dirs)
30+
31+
return False
32+
33+
1534
def save_pil_to_file(pil_image, dir=None):
1635
already_saved_as = getattr(pil_image, 'already_saved_as', None)
1736
if already_saved_as and os.path.isfile(already_saved_as):
18-
shared.demo.temp_dirs = shared.demo.temp_dirs | {os.path.abspath(os.path.dirname(already_saved_as))}
37+
register_tmp_file(shared.demo, already_saved_as)
38+
1939
file_obj = Savedfile(already_saved_as)
2040
return file_obj
2141

@@ -44,7 +64,7 @@ def on_tmpdir_changed():
4464

4565
os.makedirs(shared.opts.temp_dir, exist_ok=True)
4666

47-
shared.demo.temp_dirs = shared.demo.temp_dirs | {os.path.abspath(shared.opts.temp_dir)}
67+
register_tmp_file(shared.demo, os.path.join(shared.opts.temp_dir, "x"))
4868

4969

5070
def cleanup_tmpdr():

0 commit comments

Comments
 (0)