root commited on
Commit
7f68ca3
1 Parent(s): cc5da85

add img2img

Browse files
Files changed (2) hide show
  1. app.py +291 -50
  2. ui_functions.py +219 -0
app.py CHANGED
@@ -5,6 +5,7 @@ import base64
5
  import requests
6
  import json
7
  from PIL import Image
 
8
 
9
  def read_content(file_path: str) -> str:
10
  """read the content of target file
@@ -79,59 +80,299 @@ if __name__ == "__main__":
79
  with block:
80
  gr.HTML(read_content("header.html"))
81
 
82
- with gr.Group():
83
- with gr.Box():
84
- with gr.Row().style(mobile_collapse=False, equal_height=True):
85
- text = gr.Textbox(
86
- label="Prompt",
87
- show_label=False,
88
- max_lines=1,
89
- placeholder="Input text(输入文字)",
90
- interactive=True,
91
- ).style(
92
- border=(True, False, True, True),
93
- rounded=(True, False, False, True),
94
- container=False,
95
- )
96
-
97
- btn = gr.Button("Generate image").style(
98
- margin=False,
99
- rounded=(True, True, True, True),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
  )
101
- with gr.Row().style(mobile_collapse=False, equal_height=True):
102
- class_draw = gr.Dropdown(["通用(general)", "国画(traditional Chinese painting)",
103
- "照片,摄影(picture photography)", "油画(oil painting)",
104
- "铅笔素描(pencil sketch)", "CG",
105
- "水彩画(watercolor painting)", "水墨画(ink and wash)",
106
- "插画(illustrations)", "3D", "图生图(img2img)"],
107
- label="生成类型(type)",
108
- show_label=True,
109
- value="通用(general)")
110
- with gr.Row().style(mobile_collapse=False, equal_height=True):
111
- style_draw = gr.CheckboxGroup(["蒸汽朋克(steampunk)", "电影摄影风格(film photography)",
112
- "概念艺术(concept art)", "Warming lighting",
113
- "Dramatic lighting", "Natural lighting",
114
- "虚幻引擎(unreal engine)", "4k", "8k",
115
- "充满细节(full details)"],
116
- label="画面风格(style)",
117
- show_label=True,
118
- )
119
- with gr.Row().style(mobile_collapse=False, equal_height=True):
120
- sample_size = gr.Slider(minimum=1,
121
- maximum=4,
122
- step=1,
123
- label="生成数量(number)",
124
- show_label=True,
125
- interactive=True,
126
- )
127
 
128
- gallery = gr.Gallery(
129
- label="Generated images", show_label=False, elem_id="gallery"
130
- ).style(grid=[2], height="auto")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
 
132
- gr.Examples(examples=examples, fn=request_images, inputs=text, outputs=gallery, examples_per_page=100)
133
- text.submit(request_images, inputs=[text, class_draw, style_draw, sample_size], outputs=gallery)
134
- btn.click(request_images, inputs=[text, class_draw, style_draw, sample_size], outputs=gallery)
 
135
 
136
  gr.HTML(read_content("footer.html"))
137
  # gr.Image('./contributors.png')
 
5
  import requests
6
  import json
7
  from PIL import Image
8
+ import ui_functions as uifn
9
 
10
  def read_content(file_path: str) -> str:
11
  """read the content of target file
 
80
  with block:
81
  gr.HTML(read_content("header.html"))
82
 
83
+ with gr.Tabs():
84
+
85
+ with gr.TabItem("文生图(Text-to-img)"):
86
+
87
+ with gr.Group():
88
+ with gr.Box():
89
+ with gr.Row().style(mobile_collapse=False, equal_height=True):
90
+ text = gr.Textbox(
91
+ label="Prompt",
92
+ show_label=False,
93
+ max_lines=1,
94
+ placeholder="Input text(输入文字)",
95
+ interactive=True,
96
+ ).style(
97
+ border=(True, False, True, True),
98
+ rounded=(True, False, False, True),
99
+ container=False,
100
+ )
101
+
102
+ btn = gr.Button("Generate image").style(
103
+ margin=False,
104
+ rounded=(True, True, True, True),
105
+ )
106
+ with gr.Row().style(mobile_collapse=False, equal_height=True):
107
+ class_draw = gr.Dropdown(["通用(general)", "国画(traditional Chinese painting)",
108
+ "照片,摄影(picture photography)", "油画(oil painting)",
109
+ "铅笔素描(pencil sketch)", "CG",
110
+ "水彩画(watercolor painting)", "水墨画(ink and wash)",
111
+ "插画(illustrations)", "3D", "图生图(img2img)"],
112
+ label="生成类型(type)",
113
+ show_label=True,
114
+ value="通用(general)")
115
+ with gr.Row().style(mobile_collapse=False, equal_height=True):
116
+ style_draw = gr.CheckboxGroup(["蒸汽朋克(steampunk)", "电影摄影风格(film photography)",
117
+ "概念艺术(concept art)", "Warming lighting",
118
+ "Dramatic lighting", "Natural lighting",
119
+ "虚幻引擎(unreal engine)", "4k", "8k",
120
+ "充满细节(full details)"],
121
+ label="画面风格(style)",
122
+ show_label=True,
123
+ )
124
+ with gr.Row().style(mobile_collapse=False, equal_height=True):
125
+ sample_size = gr.Slider(minimum=1,
126
+ maximum=4,
127
+ step=1,
128
+ label="生成数量(number)",
129
+ show_label=True,
130
+ interactive=True,
131
+ )
132
+
133
+ gallery = gr.Gallery(
134
+ label="Generated images", show_label=False, elem_id="gallery"
135
+ ).style(grid=[2], height="auto")
136
+
137
+ gr.Examples(examples=examples, fn=request_images, inputs=text, outputs=gallery, examples_per_page=100)
138
+ text.submit(request_images, inputs=[text, class_draw, style_draw, sample_size], outputs=gallery)
139
+ btn.click(request_images, inputs=[text, class_draw, style_draw, sample_size], outputs=gallery)
140
+
141
+ with gr.TabItem("图生图(Img-to-Img)", id="img2img_tab"):
142
+ with gr.Row(elem_id="prompt_row"):
143
+ img2img_prompt = gr.Textbox(label="Prompt",
144
+ elem_id='img2img_prompt_input',
145
+ placeholder="神奇的森林,流淌的河流.",
146
+ lines=1,
147
+ max_lines=1 if txt2img_defaults['submit_on_enter'] == 'Yes' else 25,
148
+ value=img2img_defaults['prompt'],
149
+ show_label=False).style()
150
+
151
+ img2img_btn_mask = gr.Button("Generate", variant="primary", visible=False,
152
+ elem_id="img2img_mask_btn")
153
+ img2img_btn_editor = gr.Button("Generate", variant="primary", elem_id="img2img_edit_btn")
154
+ with gr.Row().style(equal_height=False):
155
+ with gr.Column():
156
+ gr.Markdown('#### 输入图像')
157
+ img2img_image_mask = gr.Image(
158
+ value=sample_img2img,
159
+ source="upload",
160
+ interactive=True,
161
+ type="pil", tool="sketch",
162
+ elem_id="img2img_mask",
163
+ image_mode="RGBA"
164
+ )
165
+ img2img_image_editor = gr.Image(
166
+ value=sample_img2img,
167
+ source="upload",
168
+ interactive=True,
169
+ type="pil",
170
+ tool="select",
171
+ visible=False,
172
+ image_mode="RGBA",
173
+ elem_id="img2img_editor"
174
+ )
175
+
176
+ with gr.Tabs():
177
+ with gr.TabItem("编辑设置"):
178
+ with gr.Row():
179
+ # disable Uncrop for now
180
+ choices=["Mask", "Crop", "Uncrop"]
181
+ img2img_image_editor_mode = gr.Radio(choices=["Mask"],
182
+ label="编辑模式",
183
+ value="Mask", elem_id='edit_mode_select',
184
+ visible=True)
185
+ img2img_mask = gr.Radio(choices=["保留mask区域", "生成mask区域"],
186
+ label="Mask 方式", type="index",
187
+ #value=img2img_mask_modes[img2img_defaults['mask_mode']],
188
+ value = "生成mask区域",
189
+ visible=True)
190
+
191
+ img2img_mask_blur_strength = gr.Slider(minimum=1, maximum=10, step=1,
192
+ label="How much blurry should the mask be? (to avoid hard edges)",
193
+ value=3, visible=False)
194
+
195
+ img2img_resize = gr.Radio(label="Resize mode",
196
+ choices=["Just resize", "Crop and resize",
197
+ "Resize and fill"],
198
+ type="index",
199
+ value=img2img_resize_modes[
200
+ img2img_defaults['resize_mode']], visible=False)
201
+
202
+ img2img_painterro_btn = gr.Button("Advanced Editor",visible=False)
203
+ # with gr.TabItem("Hints",visible=False):
204
+ # img2img_help = gr.Markdown(visible=False, value=uifn.help_text)
205
+
206
+ with gr.Column():
207
+ gr.Markdown('#### 编辑后的图片')
208
+ output_img2img_gallery = gr.Gallery(label="Images", elem_id="img2img_gallery_output").style(
209
+ grid=[4, 4, 4])
210
+ img2img_job_ui = job_manager.draw_gradio_ui() if job_manager else None
211
+ with gr.Column(visible=False):
212
+ with gr.Tabs(visible=False):
213
+ with gr.TabItem("", id="img2img_actions_tab",visible=False):
214
+ gr.Markdown("Select an image, then press one of the buttons below")
215
+ with gr.Row():
216
+ output_img2img_copy_to_clipboard_btn = gr.Button("Copy to clipboard")
217
+ output_img2img_copy_to_input_btn = gr.Button("Push to img2img input")
218
+ output_img2img_copy_to_mask_btn = gr.Button("Push to img2img input mask")
219
+
220
+ gr.Markdown("Warning: This will clear your current image and mask settings!")
221
+ with gr.TabItem("", id="img2img_output_info_tab",visible=False):
222
+ output_img2img_params = gr.Textbox(label="Generation parameters")
223
+ with gr.Row():
224
+ output_img2img_copy_params = gr.Button("Copy full parameters").click(
225
+ inputs=output_img2img_params, outputs=[],
226
+ _js='(x) => {navigator.clipboard.writeText(x.replace(": ",":"))}', fn=None,
227
+ show_progress=False)
228
+ output_img2img_seed = gr.Number(label='Seed', interactive=False, visible=False)
229
+ output_img2img_copy_seed = gr.Button("Copy only seed").click(
230
+ inputs=output_img2img_seed, outputs=[],
231
+ _js=call_JS("gradioInputToClipboard"), fn=None, show_progress=False)
232
+ output_img2img_stats = gr.HTML(label='Stats')
233
+
234
+ gr.Markdown('# 编辑设置')
235
+
236
+ with gr.Row():
237
+ with gr.Column():
238
+ img2img_width = gr.Slider(minimum=64, maximum=2048, step=64, label="图片宽度",
239
+ value=img2img_defaults["width"])
240
+ img2img_height = gr.Slider(minimum=64, maximum=2048, step=64, label="图片高度",
241
+ value=img2img_defaults["height"])
242
+ img2img_cfg = gr.Slider(minimum=-40.0, maximum=30.0, step=0.5,
243
+ label='文本引导强度',
244
+ value=img2img_defaults['cfg_scale'], elem_id='cfg_slider')
245
+ img2img_seed = gr.Textbox(label="随机种子", lines=1, max_lines=1,
246
+ value=img2img_defaults["seed"])
247
+ img2img_batch_count = gr.Slider(minimum=1, maximum=50, step=1,
248
+ label='生成数量',
249
+ value=img2img_defaults['n_iter'])
250
+ img2img_dimensions_info_text_box = gr.Textbox(
251
+ label="长宽比设置")
252
+ with gr.Column():
253
+ img2img_steps = gr.Slider(minimum=1, maximum=250, step=1, label="采样步数",
254
+ value=img2img_defaults['ddim_steps'])
255
+
256
+ img2img_sampling = gr.Dropdown(label='采样方式',
257
+ choices=["DDIM", 'k_dpm_2_a', 'k_dpm_2', 'k_euler_a', 'k_euler',
258
+ 'k_heun', 'k_lms'],
259
+ value=img2img_defaults['sampler_name'])
260
+
261
+ img2img_denoising = gr.Slider(minimum=0.0, maximum=1.0, step=0.01, label='Denoising Strength',
262
+ value=img2img_defaults['denoising_strength'],visible=False)
263
+
264
+ img2img_toggles = gr.CheckboxGroup(label='', choices=img2img_toggles,
265
+ value=img2img_toggle_defaults, type="index",visible=False)
266
+
267
+ img2img_realesrgan_model_name = gr.Dropdown(label='RealESRGAN model',
268
+ choices=['RealESRGAN_x4plus',
269
+ 'RealESRGAN_x4plus_anime_6B'],
270
+ value='RealESRGAN_x4plus',
271
+ visible=RealESRGAN is not None) # TODO: Feels like I shouldnt slot it in here.
272
+
273
+ img2img_embeddings = gr.File(label="Embeddings file for textual inversion",
274
+ visible=show_embeddings)
275
+
276
+ img2img_image_editor_mode.change(
277
+ uifn.change_image_editor_mode,
278
+ [img2img_image_editor_mode,
279
+ img2img_image_editor,
280
+ img2img_image_mask,
281
+ img2img_resize,
282
+ img2img_width,
283
+ img2img_height
284
+ ],
285
+ [img2img_image_editor, img2img_image_mask, img2img_btn_editor, img2img_btn_mask,
286
+ img2img_painterro_btn, img2img_mask, img2img_mask_blur_strength]
287
+ )
288
+
289
+ # img2img_image_editor_mode.change(
290
+ # uifn.update_image_mask,
291
+ # [img2img_image_editor, img2img_resize, img2img_width, img2img_height],
292
+ # img2img_image_mask
293
+ # )
294
+
295
+ output_txt2img_copy_to_input_btn.click(
296
+ uifn.copy_img_to_input,
297
+ [output_txt2img_gallery],
298
+ [img2img_image_editor, img2img_image_mask, tabs],
299
+ _js=call_JS("moveImageFromGallery",
300
+ fromId="txt2img_gallery_output",
301
+ toId="img2img_editor")
302
+ )
303
+
304
+ output_img2img_copy_to_input_btn.click(
305
+ uifn.copy_img_to_edit,
306
+ [output_img2img_gallery],
307
+ [img2img_image_editor, tabs, img2img_image_editor_mode],
308
+ _js=call_JS("moveImageFromGallery",
309
+ fromId="img2img_gallery_output",
310
+ toId="img2img_editor")
311
+ )
312
+ output_img2img_copy_to_mask_btn.click(
313
+ uifn.copy_img_to_mask,
314
+ [output_img2img_gallery],
315
+ [img2img_image_mask, tabs, img2img_image_editor_mode],
316
+ _js=call_JS("moveImageFromGallery",
317
+ fromId="img2img_gallery_output",
318
+ toId="img2img_editor")
319
+ )
320
+
321
+ output_img2img_copy_to_clipboard_btn.click(fn=None, inputs=output_img2img_gallery, outputs=[],
322
+ _js=call_JS("copyImageFromGalleryToClipboard",
323
+ fromId="img2img_gallery_output")
324
+ )
325
+
326
+ img2img_func = img2img
327
+ img2img_inputs = [img2img_prompt, img2img_image_editor_mode, img2img_mask,
328
+ img2img_mask_blur_strength, img2img_steps, img2img_sampling, img2img_toggles,
329
+ img2img_realesrgan_model_name, img2img_batch_count, img2img_cfg,
330
+ img2img_denoising, img2img_seed, img2img_height, img2img_width, img2img_resize,
331
+ img2img_image_editor, img2img_image_mask, img2img_embeddings]
332
+ img2img_outputs = [output_img2img_gallery, output_img2img_seed, output_img2img_params,
333
+ output_img2img_stats]
334
+
335
+ # If a JobManager was passed in then wrap the Generate functions
336
+ if img2img_job_ui:
337
+ img2img_func, img2img_inputs, img2img_outputs = img2img_job_ui.wrap_func(
338
+ func=img2img_func,
339
+ inputs=img2img_inputs,
340
+ outputs=img2img_outputs,
341
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
342
 
343
+ img2img_btn_mask.click(
344
+ img2img_func,
345
+ img2img_inputs,
346
+ img2img_outputs
347
+ )
348
+
349
+ def img2img_submit_params():
350
+ # print([img2img_prompt, img2img_image_editor_mode, img2img_mask,
351
+ # img2img_mask_blur_strength, img2img_steps, img2img_sampling, img2img_toggles,
352
+ # img2img_realesrgan_model_name, img2img_batch_count, img2img_cfg,
353
+ # img2img_denoising, img2img_seed, img2img_height, img2img_width, img2img_resize,
354
+ # img2img_image_editor, img2img_image_mask, img2img_embeddings])
355
+ return (img2img_func,
356
+ img2img_inputs,
357
+ img2img_outputs)
358
+
359
+ img2img_btn_editor.click(*img2img_submit_params())
360
+
361
+ # GENERATE ON ENTER
362
+ img2img_prompt.submit(None, None, None,
363
+ _js=call_JS("clickFirstVisibleButton",
364
+ rowId="prompt_row"))
365
+
366
+ img2img_painterro_btn.click(None,
367
+ [img2img_image_editor, img2img_image_mask, img2img_image_editor_mode],
368
+ [img2img_image_editor, img2img_image_mask],
369
+ _js=call_JS("Painterro.init", toId="img2img_editor")
370
+ )
371
 
372
+ img2img_width.change(fn=uifn.update_dimensions_info, inputs=[img2img_width, img2img_height],
373
+ outputs=img2img_dimensions_info_text_box)
374
+ img2img_height.change(fn=uifn.update_dimensions_info, inputs=[img2img_width, img2img_height],
375
+ outputs=img2img_dimensions_info_text_box)
376
 
377
  gr.HTML(read_content("footer.html"))
378
  # gr.Image('./contributors.png')
ui_functions.py ADDED
@@ -0,0 +1,219 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+ import gradio as gr
3
+ from PIL import Image, ImageFont, ImageDraw, ImageFilter, ImageOps
4
+ from io import BytesIO
5
+ import base64
6
+ import re
7
+
8
+
9
+ def change_image_editor_mode(choice, cropped_image, masked_image, resize_mode, width, height):
10
+ if choice == "Mask":
11
+ update_image_result = update_image_mask(cropped_image, resize_mode, width, height)
12
+ return [gr.update(visible=False), update_image_result, gr.update(visible=False), gr.update(visible=True), gr.update(visible=False), gr.update(visible=True), gr.update(visible=True)]
13
+
14
+ update_image_result = update_image_mask(masked_image["image"] if masked_image is not None else None, resize_mode, width, height)
15
+ return [update_image_result, gr.update(visible=False), gr.update(visible=True), gr.update(visible=False), gr.update(visible=True), gr.update(visible=False), gr.update(visible=False)]
16
+
17
+ def update_image_mask(cropped_image, resize_mode, width, height):
18
+ resized_cropped_image = resize_image(resize_mode, cropped_image, width, height) if cropped_image else None
19
+ return gr.update(value=resized_cropped_image, visible=True)
20
+
21
+ def toggle_options_gfpgan(selection):
22
+ if 0 in selection:
23
+ return gr.update(visible=True)
24
+ else:
25
+ return gr.update(visible=False)
26
+
27
+ def toggle_options_upscalers(selection):
28
+ if 1 in selection:
29
+ return gr.update(visible=True)
30
+ else:
31
+ return gr.update(visible=False)
32
+
33
+ def toggle_options_realesrgan(selection):
34
+ if selection == 0 or selection == 1 or selection == 3:
35
+ return gr.update(visible=True)
36
+ else:
37
+ return gr.update(visible=False)
38
+
39
+ def toggle_options_gobig(selection):
40
+ if selection == 1:
41
+ #print(selection)
42
+ return gr.update(visible=True)
43
+ if selection == 3:
44
+ return gr.update(visible=True)
45
+ else:
46
+ return gr.update(visible=False)
47
+
48
+ def toggle_options_ldsr(selection):
49
+ if selection == 2 or selection == 3:
50
+ return gr.update(visible=True)
51
+ else:
52
+ return gr.update(visible=False)
53
+
54
+ def increment_down(value):
55
+ return value - 1
56
+
57
+ def increment_up(value):
58
+ return value + 1
59
+
60
+ def copy_img_to_lab(img):
61
+ try:
62
+ image_data = re.sub('^data:image/.+;base64,', '', img)
63
+ processed_image = Image.open(BytesIO(base64.b64decode(image_data)))
64
+ tab_update = gr.update(selected='imgproc_tab')
65
+ img_update = gr.update(value=processed_image)
66
+ return processed_image, tab_update,
67
+ except IndexError:
68
+ return [None, None]
69
+ def copy_img_params_to_lab(params):
70
+ try:
71
+ prompt = params[0][0].replace('\n', ' ').replace('\r', '')
72
+ seed = int(params[1][1])
73
+ steps = int(params[7][1])
74
+ cfg_scale = float(params[9][1])
75
+ sampler = params[11][1]
76
+ return prompt,seed,steps,cfg_scale,sampler
77
+ except IndexError:
78
+ return [None, None]
79
+ def copy_img_to_input(img):
80
+ try:
81
+ image_data = re.sub('^data:image/.+;base64,', '', img)
82
+ processed_image = Image.open(BytesIO(base64.b64decode(image_data)))
83
+ tab_update = gr.update(selected='img2img_tab')
84
+ img_update = gr.update(value=processed_image)
85
+ return processed_image, processed_image , tab_update
86
+ except IndexError:
87
+ return [None, None]
88
+
89
+ def copy_img_to_edit(img):
90
+ try:
91
+ image_data = re.sub('^data:image/.+;base64,', '', img)
92
+ processed_image = Image.open(BytesIO(base64.b64decode(image_data)))
93
+ tab_update = gr.update(selected='img2img_tab')
94
+ img_update = gr.update(value=processed_image)
95
+ mode_update = gr.update(value='Crop')
96
+ return processed_image, tab_update, mode_update
97
+ except IndexError:
98
+ return [None, None]
99
+
100
+ def copy_img_to_mask(img):
101
+ try:
102
+ image_data = re.sub('^data:image/.+;base64,', '', img)
103
+ processed_image = Image.open(BytesIO(base64.b64decode(image_data)))
104
+ tab_update = gr.update(selected='img2img_tab')
105
+ img_update = gr.update(value=processed_image)
106
+ mode_update = gr.update(value='Mask')
107
+ return processed_image, tab_update, mode_update
108
+ except IndexError:
109
+ return [None, None]
110
+
111
+
112
+
113
+ def copy_img_to_upscale_esrgan(img):
114
+ tabs_update = gr.update(selected='realesrgan_tab')
115
+ image_data = re.sub('^data:image/.+;base64,', '', img)
116
+ processed_image = Image.open(BytesIO(base64.b64decode(image_data)))
117
+ return processed_image, tabs_update
118
+
119
+
120
+ help_text = """
121
+ ## Mask/Crop
122
+ * Masking is not inpainting. You will probably get better results manually masking your images in photoshop instead.
123
+ * Built-in masking/cropping is very temperamental.
124
+ * It may take some time for the image to show when switching from Crop to Mask.
125
+ * If the image doesn't appear after switching to Mask, switch back to Crop and then back again to Mask
126
+ * If the mask appears distorted (the brush is weirdly shaped instead of round), switch back to Crop and then back again to Mask.
127
+
128
+ ## Advanced Editor
129
+ * Click 💾 Save to send your editor changes to the img2img workflow
130
+ * Click ❌ Clear to discard your editor changes
131
+
132
+ If anything breaks, try switching modes again, switch tabs, clear the image, or reload.
133
+ """
134
+
135
+ def resize_image(resize_mode, im, width, height):
136
+ LANCZOS = (Image.Resampling.LANCZOS if hasattr(Image, 'Resampling') else Image.LANCZOS)
137
+ if resize_mode == 0:
138
+ res = im.resize((width, height), resample=LANCZOS)
139
+ elif resize_mode == 1:
140
+ ratio = width / height
141
+ src_ratio = im.width / im.height
142
+
143
+ src_w = width if ratio > src_ratio else im.width * height // im.height
144
+ src_h = height if ratio <= src_ratio else im.height * width // im.width
145
+
146
+ resized = im.resize((src_w, src_h), resample=LANCZOS)
147
+ res = Image.new("RGBA", (width, height))
148
+ res.paste(resized, box=(width // 2 - src_w // 2, height // 2 - src_h // 2))
149
+ else:
150
+ ratio = width / height
151
+ src_ratio = im.width / im.height
152
+
153
+ src_w = width if ratio < src_ratio else im.width * height // im.height
154
+ src_h = height if ratio >= src_ratio else im.height * width // im.width
155
+
156
+ resized = im.resize((src_w, src_h), resample=LANCZOS)
157
+ res = Image.new("RGBA", (width, height))
158
+ res.paste(resized, box=(width // 2 - src_w // 2, height // 2 - src_h // 2))
159
+
160
+ if ratio < src_ratio:
161
+ fill_height = height // 2 - src_h // 2
162
+ res.paste(resized.resize((width, fill_height), box=(0, 0, width, 0)), box=(0, 0))
163
+ res.paste(resized.resize((width, fill_height), box=(0, resized.height, width, resized.height)), box=(0, fill_height + src_h))
164
+ elif ratio > src_ratio:
165
+ fill_width = width // 2 - src_w // 2
166
+ res.paste(resized.resize((fill_width, height), box=(0, 0, 0, height)), box=(0, 0))
167
+ res.paste(resized.resize((fill_width, height), box=(resized.width, 0, resized.width, height)), box=(fill_width + src_w, 0))
168
+
169
+ return res
170
+
171
+ def update_dimensions_info(width, height):
172
+ pixel_count_formated = "{:,.0f}".format(width * height)
173
+ return f"Aspect ratio: {round(width / height, 5)}\nTotal pixel count: {pixel_count_formated}"
174
+
175
+ def get_png_nfo( image: Image ):
176
+ info_text = ""
177
+ visible = bool(image and any(image.info))
178
+ if visible:
179
+ for key,value in image.info.items():
180
+ info_text += f"{key}: {value}\n"
181
+ info_text = info_text.rstrip('\n')
182
+ return gr.Textbox.update(value=info_text, visible=visible)
183
+
184
+ def load_settings(*values):
185
+ new_settings, key_names, checkboxgroup_info = values[-3:]
186
+ values = list(values[:-3])
187
+
188
+ if new_settings:
189
+ if type(new_settings) is str:
190
+ if os.path.exists(new_settings):
191
+ with open(new_settings, "r", encoding="utf8") as f:
192
+ new_settings = yaml.safe_load(f)
193
+ elif new_settings.startswith("file://") and os.path.exists(new_settings[7:]):
194
+ with open(new_settings[7:], "r", encoding="utf8") as f:
195
+ new_settings = yaml.safe_load(f)
196
+ else:
197
+ new_settings = yaml.safe_load(new_settings)
198
+ if type(new_settings) is not dict:
199
+ new_settings = {"prompt": new_settings}
200
+ if "txt2img" in new_settings:
201
+ new_settings = new_settings["txt2img"]
202
+ target = new_settings.pop("target", "txt2img")
203
+ if target != "txt2img":
204
+ print(f"Warning: applying settings to txt2img even though {target} is specified as target.", file=sys.stderr)
205
+
206
+ skipped_settings = {}
207
+ for key in new_settings.keys():
208
+ if key in key_names:
209
+ values[key_names.index(key)] = new_settings[key]
210
+ else:
211
+ skipped_settings[key] = new_settings[key]
212
+ if skipped_settings:
213
+ print(f"Settings could not be applied: {skipped_settings}", file=sys.stderr)
214
+
215
+ # Convert lists of checkbox indices to lists of checkbox labels:
216
+ for (cbg_index, cbg_choices) in checkboxgroup_info:
217
+ values[cbg_index] = [cbg_choices[i] for i in values[cbg_index]]
218
+
219
+ return values