P01yH3dr0n commited on
Commit
05346f6
1 Parent(s): 201a961

director tools and send jump

Browse files
Files changed (4) hide show
  1. app.py +57 -43
  2. director_tools.py +98 -0
  3. images_history.py +9 -5
  4. utils.py +43 -8
app.py CHANGED
@@ -8,20 +8,14 @@ from huggingface_hub import HfApi, snapshot_download
8
 
9
  from pnginfo import read_info_from_image, send_paras
10
  from images_history import img_history_ui
 
11
  from utils import set_token, generate_novelai_image, image_from_bytes, get_remain_anlas, calculate_cost
12
 
13
  client_config = toml.load("config.toml")['client']
14
  today_count = 0
15
- anlas = -1
16
  today = datetime.date.today().strftime('%Y-%m-%d')
17
  api = HfApi()
18
 
19
- def refresh_anlas():
20
- global anlas
21
- set_token(os.environ.get('token'))
22
- anlas = get_remain_anlas()
23
- return anlas
24
-
25
  def get_count():
26
  global today_count, today
27
  now = datetime.date.today().strftime('%Y-%m-%d')
@@ -61,7 +55,7 @@ def control_ui():
61
  height = gr.Slider(label="高度", value=1024, minimum=64, maximum=2048, step=64)
62
  with gr.Row():
63
  with gr.Column():
64
- with gr.Accordion('风格迁移', open=False):
65
  ref_images = gr.Gallery(label="上传单(多)张图片", format="png", value=None, interactive=True, type="pil", show_share_button=False)
66
  info_extracts = gr.State([])
67
  ref_strs = gr.State([])
@@ -85,13 +79,13 @@ def control_ui():
85
  s.change(fn=dynparas, inputs=strs, outputs=ref_strs)
86
  ref_images.change(lambda l: ([], []) if l is None else ([1]*len(l), [0.6]*len(l)), inputs=ref_images, outputs=[info_extracts, ref_strs])
87
  ref_images.upload(lambda l: ([], []) if l is None else ([1]*len(l), [0.6]*len(l)), inputs=ref_images, outputs=[info_extracts, ref_strs])
88
- with gr.Accordion('附加输入', open=False):
89
- with gr.Tab('图生图') as i2i:
90
  i2i_image = gr.Image(label="上传图片", value=None, sources=["upload", "clipboard", "webcam"], interactive=True, type="pil", show_share_button=False)
91
  i2i_str = gr.Slider(label='去噪强度', value=0.7, minimum=0, maximum=0.99, step=0.01)
92
  i2i_noise = gr.Slider(label='噪声', value=0, minimum=0, maximum=1, step=0.1)
93
  reuse_img_i2i = gr.Button(value='使用上一次生成的图片')
94
- with gr.Tab('局部重绘') as inp:
95
  overlay = gr.Checkbox(label='覆盖原图', value=True)
96
  inp_img = gr.ImageMask(label="上传图片", value=None, sources=["upload", "clipboard", "webcam"], interactive=True, type="pil", eraser=False, transforms=None, brush=gr.Brush(colors=['#FFFFFF'], color_mode='fixed'), layers=False, show_share_button=False)
97
  reuse_img_inp = gr.Button(value='使用上一次生成的图片')
@@ -120,7 +114,7 @@ def control_ui():
120
  rand_seed.click(fn=lambda: -1, inputs=None, outputs=seed)
121
  i2i.select(lambda: 'i2i', inputs=None, outputs=selection)
122
  inp.select(lambda: 'inp', inputs=None, outputs=selection)
123
- return gen_btn, stop_btn, [prompt, quality_tags, neg_prompt, seed, scale, width, height, steps, sampler, scheduler, smea, dyn, dyn_threshold, cfg_rescale, ref_images, info_extracts, ref_strs, i2i_image, i2i_str, i2i_noise, overlay, inp_img, selection], [save, rand_seed, reuse_seed, reuse_img_i2i, reuse_img_inp]
124
 
125
  def generate(prompt, quality_tags, neg_prompt, seed, scale, width, height, steps, sampler, scheduler, smea, dyn, dyn_threshold, cfg_rescale, ref_images, info_extracts, ref_strs, i2i_image, i2i_str, i2i_noise, overlay, inp_img, selection):
126
  global today_count
@@ -140,8 +134,10 @@ def generate(prompt, quality_tags, neg_prompt, seed, scale, width, height, steps
140
  def preview_ui():
141
  with gr.Blocks(css='#preview_image { height: 100%;}'):
142
  image = gr.Image(format='png', elem_id='preview_image', interactive=False, type='filepath', show_share_button=False)
 
 
143
  info = gr.JSON(value={}, label="生成信息")
144
- return image, info
145
 
146
  def rename_save_img(path, payload, save):
147
  if path is None:
@@ -168,38 +164,39 @@ def update_btn_cost(w, h, s, sm, dyn, i2i_img, i2i_str, inp_img, selection):
168
  cost = calculate_cost(w, h, s, False, False)
169
  else:
170
  cost = calculate_cost(w, h, s, sm, dyn)
171
- return gr.Button(value=f"生成(消耗{cost}点数)")
172
 
173
  def main_ui():
174
- with gr.Blocks() as page:
175
  with gr.Row(variant="panel"):
176
  with gr.Column():
177
  gen_btn, stop_btn, paras, others = control_ui()
178
  with gr.Column():
179
- image, info = preview_ui()
180
  cost_list = paras[5:8] + paras[10:12] + paras[17:19] + paras[21:23]
181
  for component in cost_list:
182
  component.change(update_btn_cost, inputs=cost_list, outputs=gen_btn)
183
  gen_btn.click(lambda: (gr.Button(visible=False), gr.Button(visible=True)), inputs=None, outputs=[gen_btn, stop_btn])
184
- gen = gen_btn.click(generate, paras, [image, info], concurrency_limit=1)
185
  others[2].click(lambda o, s: o if len(s) == 0 else s['parameters']['seed'], inputs=[paras[3], info], outputs=paras[3])
186
  others[3].click(lambda i: i, inputs=image, outputs=paras[17])
187
  others[4].click(lambda i: gr.ImageEditor(value=i), inputs=image, outputs=paras[21])
188
  ren = image.change(rename_save_img, inputs=[image, info, others[0]], outputs=image, trigger_mode="once")
189
  image.change(lambda: (gr.Button(visible=True), gr.Button(visible=False)), inputs=None, outputs=[gen_btn, stop_btn])
190
  stop_btn.click(lambda: (gr.Button(visible=True), gr.Button(visible=False)), inputs=None, outputs=[gen_btn, stop_btn], cancels=[gen, ren])
191
- return page, paras[:14]
192
 
193
  def util_ui():
194
- with gr.Blocks(analytics_enabled=False) as page:
195
  with gr.Row(equal_height=False):
196
  with gr.Column(variant='panel'):
197
  image = gr.Image(label="上传图片", sources=["upload"], interactive=True, type="pil")
198
  with gr.Column(variant='panel'):
199
- info = gr.HTML()
200
  items = gr.JSON(value=None, visible=False)
201
- png2main = gr.Button('参数发送到文生图')
202
- return page, png2main, items, info, image
 
203
 
204
  def load_javascript():
205
  head = ''
@@ -215,22 +212,40 @@ def load_javascript():
215
  return res
216
 
217
  gr.routes.templates.TemplateResponse = template_response
218
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
219
  def ui():
220
  load_javascript()
221
- refresh_anlas()
222
- with gr.Blocks(title="NAI Client", theme=gr.themes.Base(), js="() => {document.body.classList.toggle('dark');}") as website:
223
  with gr.Row():
224
- remain_anlas = gr.Text(label="剩余点数", value=anlas)
225
  refresh = gr.Button("🔄")
226
- refresh.click(refresh_anlas, inputs=None, outputs=remain_anlas)
227
  with gr.Tabs():
228
  with gr.TabItem("图片生成", elem_id="client_ui_main"):
229
- _, paras = main_ui()
 
 
230
  with gr.TabItem("图片信息读取"):
231
- _, png2main, png_items, info, image = util_ui()
232
  with gr.TabItem("云端图片浏览") as tab:
233
- gal2main, gal_items = img_history_ui(tab)
234
  with gr.TabItem("设置"):
235
  switchLightDark = gr.Button(value="切换浅色/深色模式")
236
  switchLightDark.click(fn=None, js="() => {document.body.classList.toggle('dark');}")
@@ -238,19 +253,18 @@ def ui():
238
  loadTagComplete.click(fn=None, js="() => {run();}")
239
  clearTagCache = gr.Button(value="清除tag补全缓存")
240
  clearTagCache.click(fn=None, js="() => {localStorage.clear();}")
241
- png2main.click(fn=send_paras,
242
- inputs=[png_items] + paras,
243
- outputs=paras)
244
- png2main.click(fn=None,
245
- js="(x) => { if (x !== null) document.getElementById('client_ui_main-button').click(); return null; }",
246
- inputs=image)
247
- gal2main.click(fn=send_paras,
248
- inputs=[gal_items] + paras,
249
- outputs=paras)
250
- gal2main.click(fn=None,
251
- js="(x) => { if (x !== null) document.getElementById('client_ui_main-button').click(); return null; }",
252
- inputs=gal_items)
253
- image.change(read_info_from_image, inputs=image, outputs=[info, png_items])
254
  return website
255
 
256
 
 
8
 
9
  from pnginfo import read_info_from_image, send_paras
10
  from images_history import img_history_ui
11
+ from director_tools import director_ui, send_outputs
12
  from utils import set_token, generate_novelai_image, image_from_bytes, get_remain_anlas, calculate_cost
13
 
14
  client_config = toml.load("config.toml")['client']
15
  today_count = 0
 
16
  today = datetime.date.today().strftime('%Y-%m-%d')
17
  api = HfApi()
18
 
 
 
 
 
 
 
19
  def get_count():
20
  global today_count, today
21
  now = datetime.date.today().strftime('%Y-%m-%d')
 
55
  height = gr.Slider(label="高度", value=1024, minimum=64, maximum=2048, step=64)
56
  with gr.Row():
57
  with gr.Column():
58
+ with gr.Accordion('风格迁移', open=False) as vibe_tab:
59
  ref_images = gr.Gallery(label="上传单(多)张图片", format="png", value=None, interactive=True, type="pil", show_share_button=False)
60
  info_extracts = gr.State([])
61
  ref_strs = gr.State([])
 
79
  s.change(fn=dynparas, inputs=strs, outputs=ref_strs)
80
  ref_images.change(lambda l: ([], []) if l is None else ([1]*len(l), [0.6]*len(l)), inputs=ref_images, outputs=[info_extracts, ref_strs])
81
  ref_images.upload(lambda l: ([], []) if l is None else ([1]*len(l), [0.6]*len(l)), inputs=ref_images, outputs=[info_extracts, ref_strs])
82
+ with gr.Accordion('附加输入', open=False, elem_id="i2i_tab") as i2i_tab:
83
+ with gr.Tab('图生图', elem_id="i2i_block") as i2i:
84
  i2i_image = gr.Image(label="上传图片", value=None, sources=["upload", "clipboard", "webcam"], interactive=True, type="pil", show_share_button=False)
85
  i2i_str = gr.Slider(label='去噪强度', value=0.7, minimum=0, maximum=0.99, step=0.01)
86
  i2i_noise = gr.Slider(label='噪声', value=0, minimum=0, maximum=1, step=0.1)
87
  reuse_img_i2i = gr.Button(value='使用上一次生成的图片')
88
+ with gr.Tab('局部重绘', elem_id="inp_block") as inp:
89
  overlay = gr.Checkbox(label='覆盖原图', value=True)
90
  inp_img = gr.ImageMask(label="上传图片", value=None, sources=["upload", "clipboard", "webcam"], interactive=True, type="pil", eraser=False, transforms=None, brush=gr.Brush(colors=['#FFFFFF'], color_mode='fixed'), layers=False, show_share_button=False)
91
  reuse_img_inp = gr.Button(value='使用上一次生成的图片')
 
114
  rand_seed.click(fn=lambda: -1, inputs=None, outputs=seed)
115
  i2i.select(lambda: 'i2i', inputs=None, outputs=selection)
116
  inp.select(lambda: 'inp', inputs=None, outputs=selection)
117
+ return gen_btn, stop_btn, [prompt, quality_tags, neg_prompt, seed, scale, width, height, steps, sampler, scheduler, smea, dyn, dyn_threshold, cfg_rescale, ref_images, info_extracts, ref_strs, i2i_image, i2i_str, i2i_noise, overlay, inp_img, selection], [save, rand_seed, reuse_seed, reuse_img_i2i, reuse_img_inp, vibe_tab, i2i_tab]
118
 
119
  def generate(prompt, quality_tags, neg_prompt, seed, scale, width, height, steps, sampler, scheduler, smea, dyn, dyn_threshold, cfg_rescale, ref_images, info_extracts, ref_strs, i2i_image, i2i_str, i2i_noise, overlay, inp_img, selection):
120
  global today_count
 
134
  def preview_ui():
135
  with gr.Blocks(css='#preview_image { height: 100%;}'):
136
  image = gr.Image(format='png', elem_id='preview_image', interactive=False, type='filepath', show_share_button=False)
137
+ send_dtool = gr.Button(value="发送到引导工具", visible=False)
138
+ image.change(lambda i: gr.Button(visible=False) if i is None else gr.Button(visible=True), inputs=image, outputs=send_dtool)
139
  info = gr.JSON(value={}, label="生成信息")
140
+ return image, info, send_dtool
141
 
142
  def rename_save_img(path, payload, save):
143
  if path is None:
 
164
  cost = calculate_cost(w, h, s, False, False)
165
  else:
166
  cost = calculate_cost(w, h, s, sm, dyn)
167
+ return gr.Button(value=f"生成(预计消耗{cost}点数)")
168
 
169
  def main_ui():
170
+ with gr.Blocks():
171
  with gr.Row(variant="panel"):
172
  with gr.Column():
173
  gen_btn, stop_btn, paras, others = control_ui()
174
  with gr.Column():
175
+ image, info, send_dtool = preview_ui()
176
  cost_list = paras[5:8] + paras[10:12] + paras[17:19] + paras[21:23]
177
  for component in cost_list:
178
  component.change(update_btn_cost, inputs=cost_list, outputs=gen_btn)
179
  gen_btn.click(lambda: (gr.Button(visible=False), gr.Button(visible=True)), inputs=None, outputs=[gen_btn, stop_btn])
180
+ gen = gen_btn.click(generate, paras, [image, info], concurrency_limit=1, concurrency_id="generate")
181
  others[2].click(lambda o, s: o if len(s) == 0 else s['parameters']['seed'], inputs=[paras[3], info], outputs=paras[3])
182
  others[3].click(lambda i: i, inputs=image, outputs=paras[17])
183
  others[4].click(lambda i: gr.ImageEditor(value=i), inputs=image, outputs=paras[21])
184
  ren = image.change(rename_save_img, inputs=[image, info, others[0]], outputs=image, trigger_mode="once")
185
  image.change(lambda: (gr.Button(visible=True), gr.Button(visible=False)), inputs=None, outputs=[gen_btn, stop_btn])
186
  stop_btn.click(lambda: (gr.Button(visible=True), gr.Button(visible=False)), inputs=None, outputs=[gen_btn, stop_btn], cancels=[gen, ren])
187
+ return image, paras, others, send_dtool
188
 
189
  def util_ui():
190
+ with gr.Blocks():
191
  with gr.Row(equal_height=False):
192
  with gr.Column(variant='panel'):
193
  image = gr.Image(label="上传图片", sources=["upload"], interactive=True, type="pil")
194
  with gr.Column(variant='panel'):
195
+ info = gr.HTML('')
196
  items = gr.JSON(value=None, visible=False)
197
+ png2main = gr.Button('参数发送到文生图', visible=False)
198
+ items.change(lambda i: gr.Button(visible=False) if i is None else gr.Button(visible=True), inputs=items, outputs=png2main)
199
+ return png2main, items, info, image
200
 
201
  def load_javascript():
202
  head = ''
 
212
  return res
213
 
214
  gr.routes.templates.TemplateResponse = template_response
215
+
216
+ def send_and_jump(component, fn, inputs, outputs, tab, trigger):
217
+ component.click(fn, inputs=inputs, outputs=outputs)
218
+ component.click(fn=None,
219
+ js="(x) => { if (x !== null && x != 0) document.getElementById('" + tab + "-button').click(); return null; }",
220
+ inputs=trigger)
221
+
222
+ def send_jump_select(component, fn, inputs, outputs, tab, accordin, trigger, secondary=None):
223
+ component.click(fn, inputs=inputs, outputs=outputs)
224
+ extra_js = ''
225
+ if secondary is not None:
226
+ extra_js = "document.getElementById('" + secondary + "-button').click();"
227
+ component.click(fn=None,
228
+ js="(x) => { if (x !== null && x != 0) document.getElementById('" + tab + "-button').click();" + extra_js + " return null; }",
229
+ inputs=trigger)
230
+ component.click(lambda x: gr.Accordion(open=True) if x else gr.Accordion(), inputs=trigger, outputs=accordin)
231
+
232
  def ui():
233
  load_javascript()
234
+ set_token(os.environ.get('token'))
235
+ with gr.Blocks(title="NAI Client", theme=gr.themes.Base(), js="() => {document.body.classList.toggle('dark', true);}") as website:
236
  with gr.Row():
237
+ remain_anlas = gr.Textbox(label="剩余点数", value=get_remain_anlas, scale=3)
238
  refresh = gr.Button("🔄")
239
+ refresh.click(get_remain_anlas, inputs=None, outputs=remain_anlas)
240
  with gr.Tabs():
241
  with gr.TabItem("图片生成", elem_id="client_ui_main"):
242
+ image, paras, others, send_dtool = main_ui()
243
+ with gr.TabItem("引导工具", elem_id="client_ui_dtool"):
244
+ from_t2i, send_i2i, send_inp, send_vib, in_image, out_image, d_index = director_ui()
245
  with gr.TabItem("图片信息读取"):
246
+ png2main, png_items, info, read_image = util_ui()
247
  with gr.TabItem("云端图片浏览") as tab:
248
+ gallery, h_index, gal2main, gal_items, history2ref, history2i2i, history2inp, history2dtl = img_history_ui(tab)
249
  with gr.TabItem("设置"):
250
  switchLightDark = gr.Button(value="切换浅色/深色模式")
251
  switchLightDark.click(fn=None, js="() => {document.body.classList.toggle('dark');}")
 
253
  loadTagComplete.click(fn=None, js="() => {run();}")
254
  clearTagCache = gr.Button(value="清除tag补全缓存")
255
  clearTagCache.click(fn=None, js="() => {localStorage.clear();}")
256
+ send_and_jump(png2main, send_paras, [png_items] + paras[:14], paras[:14], "client_ui_main", read_image)
257
+ send_and_jump(gal2main, send_paras, [gal_items] + paras[:14], paras[:14], "client_ui_main", gal_items)
258
+ from_t2i.click(lambda x: x, inputs=image, outputs=in_image)
259
+ send_jump_select(send_i2i, send_outputs, [out_image, d_index], paras[17], "client_ui_main", others[6], out_image, "i2i_block")
260
+ send_jump_select(send_inp, send_outputs, [out_image, d_index], paras[21], "client_ui_main", others[6], out_image, "inp_block")
261
+ send_jump_select(send_vib, (lambda l, i: l if i == -1 else [l[i]]), [out_image, d_index], paras[14], "client_ui_main", others[5], out_image)
262
+ send_and_jump(send_dtool, (lambda x: x), image, in_image, "client_ui_dtool", image)
263
+ send_jump_select(history2i2i, send_outputs, [gallery, h_index], paras[17], "client_ui_main", others[6], gal_items, "i2i_block")
264
+ send_jump_select(history2inp, send_outputs, [gallery, h_index], paras[21], "client_ui_main", others[6], gal_items, "inp_block")
265
+ send_jump_select(history2ref, (lambda l, i: None if i == -1 else [l[i]]), [gallery, h_index], paras[14], "client_ui_main", others[5], gal_items)
266
+ send_and_jump(history2dtl, send_outputs, [gallery, h_index], in_image, "client_ui_dtool", gal_items)
267
+ read_image.change(read_info_from_image, inputs=read_image, outputs=[info, png_items])
 
268
  return website
269
 
270
 
director_tools.py ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from utils import calculate_cost, augment_image
3
+
4
+ def update_btn_cost(w, h, req_type, selection, l=''):
5
+ if selection == 'scale':
6
+ after = l.split()[-1]
7
+ w, h = map(int, after.split('x'))
8
+ cost = calculate_cost(w, h, rmbg=(req_type == "移除背景"))
9
+ return gr.Button(value=f"生成(预计消耗{cost}点数)")
10
+
11
+ def getWH(img, w, h, f):
12
+ if img is None:
13
+ return w, h, ''
14
+ w, h = img.width, img.height
15
+ l = f"{w}x{h} -> {int(w * f)}x{int(h * f)}"
16
+ return w, h, l
17
+
18
+ def refresh_hint(l, f):
19
+ if len(l) == 0:
20
+ return ''
21
+ before = l.split()[0]
22
+ w, h = map(int, before.split('x'))
23
+ l = f"{w}x{h} -> {int(w * f)}x{int(h * f)}"
24
+ return l
25
+
26
+ def set_index(evt: gr.SelectData):
27
+ return evt.index
28
+
29
+ def send_outputs(imgs, index):
30
+ if imgs is None or len(imgs) == 0:
31
+ return None
32
+ elif len(imgs) == 1:
33
+ return imgs[0][0]
34
+ elif index >= 0:
35
+ return imgs[index][0]
36
+ else:
37
+ return None
38
+
39
+ def director_ui():
40
+ with gr.Row():
41
+ with gr.Column():
42
+ input_image = gr.Image(label="上传图片", value=None, sources=["upload", "clipboard", "webcam"], interactive=True, type="pil", show_share_button=False)
43
+ with gr.Row():
44
+ from_t2i = gr.Button("使用文生图上一次生成的图片")
45
+ from_out = gr.Button("使用右侧生成的图片")
46
+ with gr.Column():
47
+ output_image = gr.Gallery(format='png', interactive=False, preview=True, show_share_button=False)
48
+ selected_index = gr.Number(value=-1, visible=False)
49
+ with gr.Row():
50
+ send_i2i = gr.Button("发送到图生图")
51
+ send_inp = gr.Button("发送到局部重绘")
52
+ send_vib = gr.Button("发送到风格迁移")
53
+ req_type = gr.Radio(["移除背景", "素描", "线稿", "上色", "更改表情", "去聊天框"], value="线稿", label="功能选择")
54
+ with gr.Tab("自由调整") as resize:
55
+ width = gr.Slider(label="调整宽度", value=1024, minimum=1, maximum=2048, step=1)
56
+ height = gr.Slider(label="调整高度", value=1024, minimum=1, maximum=2048, step=1)
57
+ with gr.Tab("等比例缩放") as scale:
58
+ hint = gr.HTML('', show_label=False)
59
+ factor = gr.Slider(label="缩放比例", minimum=0.1, maximum=2, step=0.1)
60
+ defry = gr.State(0)
61
+ prompt = gr.State('')
62
+ selection = gr.Radio(["resize", "scale"], visible=False)
63
+ resize.select(lambda: 'resize', inputs=None, outputs=selection)
64
+ scale.select(lambda: 'scale', inputs=None, outputs=selection)
65
+ @gr.render(inputs=req_type)
66
+ def extra_paras(r):
67
+ if r == "上色":
68
+ with gr.Row():
69
+ strength = gr.Radio(choices=range(6), value=0, label="强度")
70
+ text = gr.Textbox(label="提示词(可选)", value='')
71
+ strength.change(lambda x: x, inputs=strength, outputs=defry)
72
+ text.change(lambda x: x, inputs=text, outputs=prompt)
73
+ elif r == "更改表情":
74
+ with gr.Row():
75
+ emotion = gr.Dropdown(choices=["neutral", "happy", "sad", "angry", "scared", "surprised", "tired", "excited", "nervous", "thinking", "confused", "shy", "disgusted", "smug", "bored", "laughing", "irritated", "aroused", "embarrassed", "worried", "love", "determined", "hurt", "playful"], value="neutral", label="表情")
76
+ strength = gr.Dropdown(choices=["正常", "偏弱", "弱", "更弱", "很弱", "最弱"], value="正常", label="强度")
77
+ text = gr.Textbox(label="提示词(可选)", value='')
78
+ emotion.change(lambda e, t: f"{e};;{t}", inputs=[emotion, text], outputs=prompt)
79
+ text.change(lambda e, t: f"{e};;{t}", inputs=[emotion, text], outputs=prompt)
80
+ strength.change(lambda s: {"正常": 0, "偏弱": 1, "弱": 2, "更弱": 3, "很弱": 4, "最弱": 5}[s], inputs=strength, outputs=defry)
81
+ else:
82
+ return
83
+ output_image.select(set_index, inputs=None, outputs=selected_index)
84
+ from_out.click(send_outputs, inputs=[output_image, selected_index], outputs=input_image)
85
+ req_type.change(lambda r: "neutral;;" if r == "更改表情" else '', inputs=req_type, outputs=prompt)
86
+ input_image.change(getWH, inputs=[input_image, width, height, factor], outputs=[width, height, hint])
87
+ factor.change(refresh_hint, inputs=[hint, factor], outputs=[hint])
88
+ tool_btn = gr.Button(value="生成", variant="primary")
89
+ dtool_stop = gr.Button(value="取消", variant="stop", visible=False)
90
+ tool_btn.click(lambda: (gr.Button(visible=False), gr.Button(visible=True)), inputs=None, outputs=[tool_btn, dtool_stop])
91
+ dtool_gen = tool_btn.click(augment_image, inputs=[input_image, width, height, req_type, selection, factor, defry, prompt], outputs=output_image, concurrency_id="generate")
92
+ dtool_stop.click(lambda: (gr.Button(visible=True), gr.Button(visible=False)), inputs=None, outputs=[tool_btn, dtool_stop], cancels=[dtool_gen])
93
+ width.change(update_btn_cost, inputs=[width, height, req_type, selection, hint], outputs=tool_btn)
94
+ height.change(update_btn_cost, inputs=[width, height, req_type, selection, hint], outputs=tool_btn)
95
+ req_type.change(update_btn_cost, inputs=[width, height, req_type, selection, hint], outputs=tool_btn)
96
+ factor.change(update_btn_cost, inputs=[width, height, req_type, selection, hint], outputs=tool_btn)
97
+ selection.change(update_btn_cost, inputs=[width, height, req_type, selection, hint], outputs=tool_btn)
98
+ return from_t2i, send_i2i, send_inp, send_vib, input_image, output_image, selected_index
images_history.py CHANGED
@@ -61,14 +61,18 @@ def img_history_ui(tab):
61
  page_index = gr.Number(value=1, label="页码", precision=0)
62
  next_page = gr.Button('下一页')
63
  end_page = gr.Button('末尾页')
64
- history_gallery = gr.Gallery(show_label=False, columns=6, height=1024, show_share_button=False)
65
  with gr.Column(scale=1):
66
  info = gr.HTML()
67
  items = gr.JSON(value=None, visible=False)
68
  selected_index = gr.Number(value=-1, visible=False, precision=0)
69
  with gr.Row():
70
- send_btn = gr.Button('参数发送到文生图')
71
- del_btn = gr.Button('删除')
 
 
 
 
72
 
73
  img_dir_path.change(lambda path: get_img_list(path, 1) + ('', None), inputs=img_dir_path, outputs=[history_gallery, page_index, info, items])
74
  img_dir_path.blur(update_img_dir, inputs=None, outputs=img_dir_path)
@@ -80,5 +84,5 @@ def img_history_ui(tab):
80
  history_gallery.select(get_img_info, inputs=None, outputs=[selected_index, info, items])
81
  history_gallery.change(lambda: -1, outputs=selected_index)
82
  del_btn.click(del_img, inputs=[selected_index, img_dir_path, page_index], outputs=history_gallery)
83
-
84
- return send_btn, items
 
61
  page_index = gr.Number(value=1, label="页码", precision=0)
62
  next_page = gr.Button('下一页')
63
  end_page = gr.Button('末尾页')
64
+ history_gallery = gr.Gallery(show_label=False, format='png', columns=6, height=1024, interactive=False, show_share_button=False)
65
  with gr.Column(scale=1):
66
  info = gr.HTML()
67
  items = gr.JSON(value=None, visible=False)
68
  selected_index = gr.Number(value=-1, visible=False, precision=0)
69
  with gr.Row():
70
+ send_btn = gr.Button('参数发送到文生图', visible=False)
71
+ history2ref = gr.Button("图片发送到风格迁移", visible=False)
72
+ history2i2i = gr.Button("图片发送到图生图", visible=False)
73
+ history2inp = gr.Button("图片发送到局部重绘", visible=False)
74
+ history2dtl = gr.Button("图片发送到引导工具", visible=False)
75
+ del_btn = gr.Button('删除', visible=False)
76
 
77
  img_dir_path.change(lambda path: get_img_list(path, 1) + ('', None), inputs=img_dir_path, outputs=[history_gallery, page_index, info, items])
78
  img_dir_path.blur(update_img_dir, inputs=None, outputs=img_dir_path)
 
84
  history_gallery.select(get_img_info, inputs=None, outputs=[selected_index, info, items])
85
  history_gallery.change(lambda: -1, outputs=selected_index)
86
  del_btn.click(del_img, inputs=[selected_index, img_dir_path, page_index], outputs=history_gallery)
87
+ items.change(lambda s: [gr.Button(visible=False) for _ in range(6)] if s is None else [gr.Button(visible=True) for _ in range(6)], inputs=items, outputs=[send_btn, history2ref, history2i2i, history2inp, history2dtl, del_btn])
88
+ return history_gallery, selected_index, send_btn, items, history2ref, history2i2i, history2inp, history2dtl
utils.py CHANGED
@@ -5,15 +5,14 @@ import requests
5
  import json
6
  import base64
7
  import math
 
8
 
9
  from PIL import Image
10
 
11
-
12
  jwt_token = ''
13
  url = "https://image.novelai.net/ai/generate-image"
14
  headers = {}
15
 
16
-
17
  def set_token(token):
18
  global jwt_token, headers
19
  if jwt_token == token:
@@ -34,9 +33,9 @@ def get_remain_anlas():
34
  except:
35
  return '获取失败,err:' + str(data)
36
 
37
- def calculate_cost(width, height, steps, sm, dyn, strength=1, rmbg=False):
38
  pixels = width * height
39
- if pixels <= 1048576 and steps <= 28:
40
  return 0
41
  dyn = sm and dyn
42
  L = math.ceil(2951823174884865e-21 * pixels + 5.753298233447344e-7 * pixels * steps)
@@ -122,7 +121,7 @@ def generate_novelai_image(
122
  try:
123
  response = requests.post(url, json=payload, headers=headers, timeout=180)
124
  except:
125
- return None, {'message': 'NAI response timeout'}
126
 
127
  # Process the response
128
  if response.headers.get('Content-Type') == 'binary/octet-stream':
@@ -133,9 +132,11 @@ def generate_novelai_image(
133
  with zip_ref.open(file_names[0]) as file:
134
  return file.read(), payload
135
  else:
136
- return "NAI doesn't return any images", json.loads(response.content)
 
137
  else:
138
- return "Generation failed", json.loads(response.content)
 
139
 
140
  def image_from_bytes(data):
141
  img_file = io.BytesIO(data)
@@ -147,4 +148,38 @@ def image2base64(img):
147
  img.save(output_buffer, format='PNG' if img.mode=='RGBA' else 'JPEG')
148
  byte_data = output_buffer.getvalue()
149
  base64_str = base64.b64encode(byte_data).decode()
150
- return base64_str
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  import json
6
  import base64
7
  import math
8
+ import gradio as gr
9
 
10
  from PIL import Image
11
 
 
12
  jwt_token = ''
13
  url = "https://image.novelai.net/ai/generate-image"
14
  headers = {}
15
 
 
16
  def set_token(token):
17
  global jwt_token, headers
18
  if jwt_token == token:
 
33
  except:
34
  return '获取失败,err:' + str(data)
35
 
36
+ def calculate_cost(width, height, steps=28, sm=False, dyn=False, strength=1, rmbg=False):
37
  pixels = width * height
38
+ if pixels <= 1048576 and steps <= 28 and not rmbg:
39
  return 0
40
  dyn = sm and dyn
41
  L = math.ceil(2951823174884865e-21 * pixels + 5.753298233447344e-7 * pixels * steps)
 
121
  try:
122
  response = requests.post(url, json=payload, headers=headers, timeout=180)
123
  except:
124
+ raise gr.Error('NAI response timeout')
125
 
126
  # Process the response
127
  if response.headers.get('Content-Type') == 'binary/octet-stream':
 
132
  with zip_ref.open(file_names[0]) as file:
133
  return file.read(), payload
134
  else:
135
+ messages = json.loads(response.content)
136
+ raise gr.Error(messages["statusCode"] + ": " + messages["message"])
137
  else:
138
+ messages = json.loads(response.content)
139
+ raise gr.Error(messages["statusCode"] + ": " + messages["message"])
140
 
141
  def image_from_bytes(data):
142
  img_file = io.BytesIO(data)
 
148
  img.save(output_buffer, format='PNG' if img.mode=='RGBA' else 'JPEG')
149
  byte_data = output_buffer.getvalue()
150
  base64_str = base64.b64encode(byte_data).decode()
151
+ return base64_str
152
+
153
+ def augment_image(image, width, height, req_type, selection, factor=1, defry=0, prompt=''):
154
+ if selection == "scale":
155
+ width = int(width * factor)
156
+ height = int(height * factor)
157
+ image = image.resize((width, height))
158
+ req_type = {"移除背景": "bg-removal", "素描": "sketch", "线稿": "lineart", "上色": "colorize", "更改表情": "emotion", "去聊天框": "declutter"}[req_type]
159
+ base64img = image2base64(image)
160
+ payload = {"image": base64img, "width": width, "height": height, "req_type": req_type}
161
+ if req_type == "colorize" or req_type == "emotion":
162
+ payload["defry"] = defry
163
+ payload["prompt"] = prompt
164
+
165
+ try:
166
+ response = requests.post("https://image.novelai.net/ai/augment-image", json=payload, headers=headers, timeout=60)
167
+ except:
168
+ raise gr.Error('NAI response timeout')
169
+
170
+ # Process the response
171
+ if response.headers.get('Content-Type') == 'binary/octet-stream':
172
+ zipfile_in_memory = io.BytesIO(response.content)
173
+ with zipfile.ZipFile(zipfile_in_memory, 'r') as zip_ref:
174
+ if len(zip_ref.namelist()):
175
+ files = []
176
+ for file_name in zip_ref.namelist():
177
+ with zip_ref.open(file_name) as file:
178
+ files.append(file.read())
179
+ return files
180
+ else:
181
+ messages = json.loads(response.content)
182
+ raise gr.Error(messages["statusCode"] + ": " + messages["message"])
183
+ else:
184
+ messages = json.loads(response.content)
185
+ raise gr.Error(messages["statusCode"] + ": " + messages["message"])