laichaoyi commited on
Commit
3a7c74e
·
verified ·
1 Parent(s): 34c5a71

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +314 -316
app.py CHANGED
@@ -1,316 +1,314 @@
1
- import pyperclip
2
- import os
3
- from PIL import Image
4
- from sd_parsers import ParserManager
5
- import gradio as gr
6
- import re
7
- import json
8
-
9
-
10
- parser_manager = ParserManager()
11
-
12
- TITLE = "<h1><center>Workflow Info Reader - By Andy N Le 0908 23 11 81 </center></h1>\n"
13
-
14
- def extract_lora_info(prompt):
15
- lora_pattern = r"<lora:(.*?):(.*?)>"
16
- loras = re.findall(lora_pattern, prompt)
17
- if not loras:
18
- return "Không xác định"
19
- lora_info = [f" {name} - Weight: {weight}" for name, weight in loras]
20
- return "\n".join(lora_info)
21
-
22
- def generate_workflow_from_metadata(metadata):
23
- nodes = []
24
- connections = []
25
-
26
- if 'nodes' in metadata:
27
- for node in metadata['nodes']:
28
- nodes.append({
29
- 'id': node['id'],
30
- 'title': node.get('title', 'Unnamed Node'),
31
- 'pos': node.get('pos', [0, 0]),
32
- 'type': node.get('type', 'basic/node')
33
- })
34
-
35
- if 'connections' in metadata:
36
- for conn in metadata['connections']:
37
- connections.append({
38
- 'from': conn['from'],
39
- 'to': conn['to']
40
- })
41
-
42
- return {
43
- 'nodes': nodes,
44
- 'connections': connections
45
- }
46
-
47
- def format_sampler_params(sampler_params):
48
- try:
49
- params = json.loads(sampler_params)
50
- except (json.JSONDecodeError, TypeError):
51
- return "Không xác định"
52
-
53
- scheduler = params.get("scheduler", "Không xác định")
54
- cfg_scale = params.get("cfg_scale", "Không xác định")
55
- steps = params.get("steps", "Không xác định")
56
- return f"scheduler: {scheduler}\nCFG: {cfg_scale}\nSteps: {steps}"
57
-
58
- def read_image_metadata(image_path):
59
- try:
60
- if not image_path:
61
- raise ValueError("Không có ảnh được tải lên.")
62
-
63
- with Image.open(image_path) as img:
64
- prompt_info = parser_manager.parse(img)
65
-
66
- if not prompt_info:
67
- raise ValueError("Không thể đọc thông tin từ ảnh.")
68
-
69
- # Kiểm tra loại generator
70
- if prompt_info.generator == "AUTOMATIC1111":
71
- return handle_automatic1111(prompt_info)
72
- elif prompt_info.generator == "ComfyUI":
73
- return handle_comfyui(prompt_info)
74
- else:
75
- raise ValueError("Loại generator không được hỗ trợ.")
76
-
77
- except Exception as e:
78
- print(f"Lỗi khi xử lý ảnh: {str(e)}")
79
- return "Không tìm thấy thông tin!", "", "", "", "", "", "", ""
80
-
81
-
82
- def handle_automatic1111(prompt_info):
83
- prompt = prompt_info.full_prompt
84
- negative_prompt = prompt_info.full_negative_prompt if prompt_info.full_negative_prompt else "N/A"
85
-
86
- models_list = list(prompt_info.models) if isinstance(prompt_info.models, set) else prompt_info.models
87
- model = models_list[0].name if models_list else "Không xác định"
88
-
89
- loras = extract_lora_info(prompt)
90
-
91
- samplers_list = list(prompt_info.samplers) if isinstance(prompt_info.samplers, set) else prompt_info.samplers
92
- if samplers_list and len(samplers_list) > 0:
93
- sampler = samplers_list[0].name if samplers_list[0].name else "N/A"
94
- sampler_params = json.dumps(samplers_list[0].parameters) if samplers_list[0].parameters else "N/A"
95
- seed = samplers_list[0].parameters.get('seed', 'Không xác định')
96
- else:
97
- sampler = "N/A"
98
- sampler_params = "N/A"
99
- seed = "Không xác định"
100
-
101
- formatted_sampler_params = format_sampler_params(sampler_params)
102
-
103
- other_metadata = "\n".join([
104
- f"{key}: {value}" for key, value in prompt_info.metadata.items()
105
- if isinstance(key, str) and not key.startswith("Module")
106
- ])
107
-
108
- return prompt, negative_prompt, model, loras, seed, sampler, formatted_sampler_params, other_metadata
109
-
110
- def format_metadata(metadata):
111
- formatted_output = ""
112
- for key, value in metadata.items():
113
- node_title, node_id = key
114
- formatted_output += f"Node '{node_title}'\n"
115
- for prop_key, prop_value in value.items():
116
- formatted_output += f" {prop_key}: {prop_value}\n"
117
- return formatted_output
118
-
119
- def handle_comfyui(prompt_info):
120
- prompt = prompt_info.full_prompt or "Không xác định"
121
- negative_prompt = prompt_info.full_negative_prompt if prompt_info.full_negative_prompt else "N/A"
122
-
123
- models_list = list(prompt_info.models) if isinstance(prompt_info.models, set) else prompt_info.models
124
- model = models_list[0].name if models_list else "Không xác định"
125
-
126
- samplers_list = list(prompt_info.samplers) if isinstance(prompt_info.samplers, set) else prompt_info.samplers
127
- if samplers_list and len(samplers_list) > 0:
128
- sampler = samplers_list[0].name if samplers_list[0].name else "N/A"
129
- sampler_params = json.dumps(samplers_list[0].parameters) if samplers_list[0].parameters else "N/A"
130
- seed = samplers_list[0].parameters.get('seed', 'Không xác định')
131
- else:
132
- sampler = "N/A"
133
- sampler_params = "N/A"
134
- seed = "Không xác định"
135
-
136
- formatted_sampler_params = format_sampler_params(sampler_params)
137
-
138
-
139
- converted_metadata = {}
140
- for key, value in prompt_info.metadata.items():
141
- if isinstance(key, tuple):
142
- key = str(key)
143
- converted_metadata[key] = value
144
-
145
- other_metadata = format_metadata(prompt_info.metadata)
146
-
147
- if not other_metadata:
148
- other_metadata = "Không có metadata bổ sung."
149
-
150
- return prompt, negative_prompt, model, None, seed, sampler, formatted_sampler_params, other_metadata
151
-
152
- output_dir = "outputs"
153
- if not os.path.exists(output_dir):
154
- os.mkdir(output_dir)
155
-
156
- def copy_to_clipboard(prompt, neg_prompt, seed, copy_prompt, copy_neg_prompt, copy_seed):
157
- copied_text = ""
158
- if copy_prompt:
159
- copied_text += f"Prompt: {prompt}\n"
160
- if copy_neg_prompt:
161
- copied_text += f"Negative Prompt: {neg_prompt}\n"
162
- if copy_seed:
163
- copied_text += f"Seed: {seed}\n"
164
-
165
- if copied_text:
166
- pyperclip.copy(copied_text)
167
- return gr.Info("Sao chép thành công!", duration=2)
168
- else:
169
- return gr.Info("Không có gì để sao chép!", duration=2)
170
-
171
- # Hàm hủy bỏ sao chép
172
- def cancel_copy():
173
- pyperclip.copy("")
174
- return (
175
- gr.update(value=False), # Uncheck all checkboxes
176
- gr.update(value=False),
177
- gr.update(value=False),
178
- gr.Info("Đã hủy bỏ sao chép!", duration=2)
179
- )
180
-
181
- def save_metadata_to_file(image_input, prompt, neg_prompt, model, loras, seed, sampler, sampler_params, metadata):
182
- if not any([prompt, neg_prompt, model, loras, seed, sampler, sampler_params, metadata]):
183
- return gr.Info("Không thông tin để lưu!", duration=2)
184
- if image_input is None:
185
- return gr.Info("Không thể lưu tệp: Không có ảnh nào được tải lên.", duration=2)
186
-
187
-
188
- image_filename = os.path.basename(image_input)
189
- txt_filename = os.path.splitext(image_filename)[0] + ".txt"
190
- txt_filepath = os.path.join(output_dir, txt_filename)
191
-
192
-
193
- with open(txt_filepath, "w", encoding="utf-8") as f:
194
- f.write(f"Prompt: {prompt}\n")
195
- f.write(f"Negative Prompt: {neg_prompt}\n")
196
- f.write(f"Model: {model}\n")
197
- f.write(f"Loras: {loras}\n")
198
- f.write(f"Seed: {seed}\n")
199
- f.write(f"Sampler: {sampler}\n")
200
- f.write(f"Sampler Parameters: {sampler_params}\n")
201
- f.write(f"Other Metadata:\n{metadata}\n")
202
-
203
- return gr.Info(f"Đã lưu thông tin vào file: {txt_filename}", duration=2)
204
-
205
- def check_image_size(image_input):
206
- try:
207
- if not image_input:
208
- raise ValueError("Không có ảnh được tải lên.")
209
-
210
- with Image.open(image_input) as img:
211
- width, height = img.size
212
- if width > 5000 or height > 5000:
213
- raise ValueError("Kích thước ảnh vượt quá 5000 px ở chiều ngang hoặc chiều dọc.")
214
- return image_input, gr.Info("Ảnh hợp lệ.", duration=1)
215
- except Exception as e:
216
- return None, gr.Info(f"Lỗi khi xử ảnh: {str(e)}", duration=2)
217
-
218
-
219
- def gradio_interface(image_input):
220
- try:
221
- # Đọc dữ liệu từ ảnh
222
- prompt, negative_prompt, model, loras, seed, sampler, formatted_sampler_params, other_metadata = read_image_metadata(image_input)
223
-
224
- # Kiểm tra xem dữ liệu có bị thiếu không cho từng trường hợp
225
- if prompt == "Không thể đọc thông tin" or not any([prompt, negative_prompt, model, seed]):
226
- raise ValueError("Thiếu dữ liệu khi xử ảnh.")
227
-
228
- return prompt, negative_prompt, model, loras, seed, sampler, formatted_sampler_params, other_metadata
229
- except Exception as e:
230
- # In ra lỗi trả về nội dung lỗi
231
- print(f"Lỗi trong gradio_interface: {str(e)}")
232
- return "Không tìm thấy thông tin ", "", "", "", "", "", "", ""
233
-
234
-
235
- js_func = """
236
- function refresh() {
237
- const url = new URL(window.location);
238
-
239
- if (url.searchParams.get('__theme') !== 'dark') {
240
- url.searchParams.set('__theme', 'dark');
241
- window.location.href = url.href;
242
- }
243
- }
244
-
245
- """
246
- with gr.Blocks(js = js_func) as demo:
247
- gr.HTML(TITLE)
248
- with gr.Row():
249
- with gr.Column():
250
- image_input = gr.Image(type="filepath", label="Tải lên hình ảnh")
251
- read_button = gr.Button("Đọc thông tin")
252
- copy_prompt = gr.Checkbox(label="Sao chép lời mô tả", value=False)
253
- copy_neg_prompt = gr.Checkbox(label="Sao chép mô tả loại trừ", value=False)
254
- copy_seed = gr.Checkbox(label="Sao Chép Seed", value=False)
255
- with gr.Row():
256
- copy_button = gr.Button("Sao chép")
257
- cancel_button = gr.Button("Hủy sao chép")
258
- download_button = gr.Button("Lưu file .txt")
259
- message_output = gr.HTML()
260
-
261
-
262
- with gr.Column():
263
- prompt_output = gr.Textbox(label="Lời mô tả (prompt)")
264
- negative_prompt_output = gr.Textbox(label="Mô tả loại trừ (Negative Prompt)")
265
- model_output = gr.Textbox(label="Mô hình (Model)")
266
- lora_output = gr.Textbox(label="Lora (Tên & Trọng số)")
267
- seed_output = gr.Textbox(label="Seed")
268
- sampler_output = gr.Textbox(label="Phương pháp lấy mẫu")
269
- sampler_params_output = gr.Textbox(label="Thông số lấy mẫu")
270
- other_metadata_output = gr.Textbox(label="Thông tin khác", lines=10)
271
-
272
- read_button.click(
273
- fn=check_image_size,
274
- inputs=image_input,
275
- outputs=[image_input, message_output],
276
- show_progress=False
277
- )
278
-
279
- # Sau khi kiểm tra kích thước, nếu hợp lệ, đọc metadata từ ảnh
280
- read_button.click(
281
- fn=gradio_interface,
282
- inputs=image_input,
283
- outputs=[prompt_output, negative_prompt_output, model_output, lora_output, seed_output, sampler_output, sampler_params_output, other_metadata_output]
284
- )
285
- copy_button.click(
286
- copy_to_clipboard,
287
- inputs=[prompt_output, negative_prompt_output, seed_output, copy_prompt, copy_neg_prompt, copy_seed],
288
- outputs=message_output
289
- )
290
-
291
- # Gắn sự kiện click cho nút hủy sao chép
292
- cancel_button.click(
293
- cancel_copy,
294
- inputs=None,
295
- outputs=[copy_prompt, copy_neg_prompt, copy_seed, message_output]
296
- )
297
- download_button.click(
298
- save_metadata_to_file,
299
- inputs=[
300
- image_input,
301
- prompt_output,
302
- negative_prompt_output,
303
- model_output,
304
- lora_output,
305
- seed_output,
306
- sampler_output,
307
- sampler_params_output,
308
- other_metadata_output
309
- ],
310
- outputs=message_output
311
- )
312
-
313
-
314
-
315
- if __name__ == "__main__":
316
- demo.launch(inbrowser=True)
 
1
+ import pyperclip
2
+ import os
3
+ from PIL import Image
4
+ from sd_parsers import ParserManager
5
+ import gradio as gr
6
+ import re
7
+ import json
8
+
9
+
10
+ parser_manager = ParserManager()
11
+
12
+ TITLE = "<h1><center>Workflow Info Reader - By Andy N Le 0908 23 11 81 </center></h1>\n"
13
+
14
+ def extract_lora_info(prompt):
15
+ lora_pattern = r"<lora:(.*?):(.*?)>"
16
+ loras = re.findall(lora_pattern, prompt)
17
+ if not loras:
18
+ return "Không xác định"
19
+ lora_info = [f" {name} - Weight: {weight}" for name, weight in loras]
20
+ return "\n".join(lora_info)
21
+
22
+ def generate_workflow_from_metadata(metadata):
23
+ nodes = []
24
+ connections = []
25
+
26
+ if 'nodes' in metadata:
27
+ for node in metadata['nodes']:
28
+ nodes.append({
29
+ 'id': node['id'],
30
+ 'title': node.get('title', 'Unnamed Node'),
31
+ 'pos': node.get('pos', [0, 0]),
32
+ 'type': node.get('type', 'basic/node')
33
+ })
34
+
35
+ if 'connections' in metadata:
36
+ for conn in metadata['connections']:
37
+ connections.append({
38
+ 'from': conn['from'],
39
+ 'to': conn['to']
40
+ })
41
+
42
+ return {
43
+ 'nodes': nodes,
44
+ 'connections': connections
45
+ }
46
+
47
+ def format_sampler_params(sampler_params):
48
+ try:
49
+ params = json.loads(sampler_params)
50
+ except (json.JSONDecodeError, TypeError):
51
+ return "Không xác định"
52
+
53
+ scheduler = params.get("scheduler", "Không xác định")
54
+ cfg_scale = params.get("cfg_scale", "Không xác định")
55
+ steps = params.get("steps", "Không xác định")
56
+ return f"scheduler: {scheduler}\nCFG: {cfg_scale}\nSteps: {steps}"
57
+
58
+ def read_image_metadata(image_path):
59
+ try:
60
+ if not image_path:
61
+ raise ValueError("Không có ảnh được tải lên.")
62
+
63
+ with Image.open(image_path) as img:
64
+ prompt_info = parser_manager.parse(img)
65
+
66
+ if not prompt_info:
67
+ raise ValueError("Không thể đọc thông tin từ ảnh.")
68
+
69
+ # Kiểm tra loại generator
70
+ if prompt_info.generator == "AUTOMATIC1111":
71
+ return handle_automatic1111(prompt_info)
72
+ elif prompt_info.generator == "ComfyUI":
73
+ return handle_comfyui(prompt_info)
74
+ else:
75
+ raise ValueError("Loại generator không được hỗ trợ.")
76
+
77
+ except Exception as e:
78
+ print(f"Lỗi khi xử lý ảnh: {str(e)}")
79
+ return "Không tìm thấy thông tin!", "", "", "", "", "", "", ""
80
+
81
+
82
+ def handle_automatic1111(prompt_info):
83
+ prompt = prompt_info.full_prompt
84
+ negative_prompt = prompt_info.full_negative_prompt if prompt_info.full_negative_prompt else "N/A"
85
+
86
+ models_list = list(prompt_info.models) if isinstance(prompt_info.models, set) else prompt_info.models
87
+ model = models_list[0].name if models_list else "Không xác định"
88
+
89
+ loras = extract_lora_info(prompt)
90
+
91
+ samplers_list = list(prompt_info.samplers) if isinstance(prompt_info.samplers, set) else prompt_info.samplers
92
+ if samplers_list and len(samplers_list) > 0:
93
+ sampler = samplers_list[0].name if samplers_list[0].name else "N/A"
94
+ sampler_params = json.dumps(samplers_list[0].parameters) if samplers_list[0].parameters else "N/A"
95
+ seed = samplers_list[0].parameters.get('seed', 'Không xác định')
96
+ else:
97
+ sampler = "N/A"
98
+ sampler_params = "N/A"
99
+ seed = "Không xác định"
100
+
101
+ formatted_sampler_params = format_sampler_params(sampler_params)
102
+
103
+ other_metadata = "\n".join([
104
+ f"{key}: {value}" for key, value in prompt_info.metadata.items()
105
+ if isinstance(key, str) and not key.startswith("Module")
106
+ ])
107
+
108
+ return prompt, negative_prompt, model, loras, seed, sampler, formatted_sampler_params, other_metadata
109
+
110
+ def format_metadata(metadata):
111
+ formatted_output = ""
112
+ for key, value in metadata.items():
113
+ node_title, node_id = key
114
+ formatted_output += f"Node '{node_title}'\n"
115
+ for prop_key, prop_value in value.items():
116
+ formatted_output += f" {prop_key}: {prop_value}\n"
117
+ return formatted_output
118
+
119
+ def handle_comfyui(prompt_info):
120
+ prompt = prompt_info.full_prompt or "Không xác định"
121
+ negative_prompt = prompt_info.full_negative_prompt if prompt_info.full_negative_prompt else "N/A"
122
+
123
+ models_list = list(prompt_info.models) if isinstance(prompt_info.models, set) else prompt_info.models
124
+ model = models_list[0].name if models_list else "Không xác định"
125
+
126
+ samplers_list = list(prompt_info.samplers) if isinstance(prompt_info.samplers, set) else prompt_info.samplers
127
+ if samplers_list and len(samplers_list) > 0:
128
+ sampler = samplers_list[0].name if samplers_list[0].name else "N/A"
129
+ sampler_params = json.dumps(samplers_list[0].parameters) if samplers_list[0].parameters else "N/A"
130
+ seed = samplers_list[0].parameters.get('seed', 'Không xác định')
131
+ else:
132
+ sampler = "N/A"
133
+ sampler_params = "N/A"
134
+ seed = "Không xác định"
135
+
136
+ formatted_sampler_params = format_sampler_params(sampler_params)
137
+
138
+
139
+ converted_metadata = {}
140
+ for key, value in prompt_info.metadata.items():
141
+ if isinstance(key, tuple):
142
+ key = str(key)
143
+ converted_metadata[key] = value
144
+
145
+ other_metadata = format_metadata(prompt_info.metadata)
146
+
147
+ if not other_metadata:
148
+ other_metadata = "Không có metadata bổ sung."
149
+
150
+ return prompt, negative_prompt, model, None, seed, sampler, formatted_sampler_params, other_metadata
151
+
152
+ output_dir = "outputs"
153
+ if not os.path.exists(output_dir):
154
+ os.mkdir(output_dir)
155
+
156
+ def copy_to_clipboard(prompt, neg_prompt, seed, copy_prompt, copy_neg_prompt, copy_seed):
157
+ copied_text = ""
158
+ if copy_prompt:
159
+ copied_text += f"Prompt: {prompt}\n"
160
+ if copy_neg_prompt:
161
+ copied_text += f"Negative Prompt: {neg_prompt}\n"
162
+ if copy_seed:
163
+ copied_text += f"Seed: {seed}\n"
164
+
165
+ if copied_text:
166
+ pyperclip.copy(copied_text)
167
+ return gr.Info("Sao chép thành công!", duration=2)
168
+ else:
169
+ return gr.Info("Không có gì để sao chép!", duration=2)
170
+
171
+ # Hàm hủy bỏ sao chép
172
+ def cancel_copy():
173
+ pyperclip.copy("")
174
+ return (
175
+ gr.update(value=False), # Uncheck all checkboxes
176
+ gr.update(value=False),
177
+ gr.update(value=False),
178
+ gr.Info("Đã hủy bỏ sao chép!", duration=2)
179
+ )
180
+
181
+ def save_metadata_to_file(image_input, prompt, neg_prompt, model, loras, seed, sampler, sampler_params, metadata):
182
+ # Kiểm tra nếu không dữ liệu để lưu
183
+ if not any([prompt, neg_prompt, model, loras, seed, sampler, sampler_params, metadata]):
184
+ return None, gr.Info("Không có thông tin để lưu!", duration=2)
185
+
186
+ if image_input is None:
187
+ return None, gr.Info("Không thể lưu tệp: Không có ảnh nào được tải lên.", duration=2)
188
+
189
+ # Tạo nội dung file txt từ metadata
190
+ file_content = (
191
+ f"Prompt: {prompt}\n"
192
+ f"Negative Prompt: {neg_prompt}\n"
193
+ f"Model: {model}\n"
194
+ f"Loras: {loras}\n"
195
+ f"Seed: {seed}\n"
196
+ f"Sampler: {sampler}\n"
197
+ f"Sampler Parameters: {sampler_params}\n"
198
+ f"Other Metadata:\n{metadata}\n"
199
+ )
200
+
201
+ # Tạo tệp tin tạm thời để người dùng tải xuống
202
+ txt_filename = "metadata_info.txt"
203
+ with open(txt_filename, "w", encoding="utf-8") as f:
204
+ f.write(file_content)
205
+
206
+ # Trả về đường dẫn tệp tin để tự động tải xuống
207
+ return txt_filename, gr.Info(f"Đang tải file {txt_filename}...", duration=2)
208
+
209
+ def check_image_size(image_input):
210
+ try:
211
+ if not image_input:
212
+ raise ValueError("Không ảnh được tải lên.")
213
+
214
+ with Image.open(image_input) as img:
215
+ width, height = img.size
216
+ if width > 5000 or height > 5000:
217
+ raise ValueError("Kích thước ảnh vượt quá 5000 px ở chiều ngang hoặc chiều dọc.")
218
+ return image_input, gr.Info("Ảnh hợp lệ.", duration=1)
219
+ except Exception as e:
220
+ return None, gr.Info(f"Lỗi khi xử lý ảnh: {str(e)}", duration=2)
221
+
222
+
223
+ def gradio_interface(image_input):
224
+ try:
225
+ # Đọc dữ liệu từ ảnh
226
+ prompt, negative_prompt, model, loras, seed, sampler, formatted_sampler_params, other_metadata = read_image_metadata(image_input)
227
+
228
+ # Kiểm tra xem dữ liệu bị thiếu không cho từng trường hợp
229
+ if prompt == "Không thể đọc thông tin" or not any([prompt, negative_prompt, model, seed]):
230
+ raise ValueError("Thiếu dữ liệu khi xử ảnh.")
231
+
232
+ return prompt, negative_prompt, model, loras, seed, sampler, formatted_sampler_params, other_metadata
233
+ except Exception as e:
234
+ # In ra lỗi và trả về nội dung lỗi
235
+ print(f"Lỗi trong gradio_interface: {str(e)}")
236
+ return "Không tìm thấy thông tin ", "", "", "", "", "", "", ""
237
+
238
+
239
+ js_func = """
240
+ function refresh() {
241
+ const url = new URL(window.location);
242
+
243
+ if (url.searchParams.get('__theme') !== 'dark') {
244
+ url.searchParams.set('__theme', 'dark');
245
+ window.location.href = url.href;
246
+ }
247
+ }
248
+
249
+ """
250
+ with gr.Blocks(js = js_func) as demo:
251
+ gr.HTML(TITLE)
252
+ with gr.Row():
253
+ with gr.Column():
254
+ image_input = gr.Image(type="filepath", label="Tải lên hình ảnh")
255
+ read_button = gr.Button("Đọc thông tin")
256
+ copy_prompt = gr.Checkbox(label="Sao chép lời mô tả", value=False)
257
+ copy_neg_prompt = gr.Checkbox(label="Sao chép mô tả loại trừ", value=False)
258
+ copy_seed = gr.Checkbox(label="Sao Chép Seed", value=False)
259
+ with gr.Row():
260
+ copy_button = gr.Button("Sao chép")
261
+ cancel_button = gr.Button("Hủy sao chép")
262
+ download_button = gr.Button("Lưu file .txt")
263
+ message_output = gr.HTML()
264
+
265
+
266
+ with gr.Column():
267
+ prompt_output = gr.Textbox(label="Lời mô tả (prompt)")
268
+ negative_prompt_output = gr.Textbox(label=" tả loại trừ (Negative Prompt)")
269
+ model_output = gr.Textbox(label=" hình (Model)")
270
+ lora_output = gr.Textbox(label="Lora (Tên & Trọng số)")
271
+ seed_output = gr.Textbox(label="Seed")
272
+ sampler_output = gr.Textbox(label="Phương pháp lấy mẫu")
273
+ sampler_params_output = gr.Textbox(label="Thông số lấy mẫu")
274
+ other_metadata_output = gr.Textbox(label="Thông tin khác", lines=10)
275
+
276
+ read_button.click(
277
+ fn=check_image_size,
278
+ inputs=image_input,
279
+ outputs=[image_input, message_output],
280
+ show_progress=False
281
+ )
282
+
283
+ # Sau khi kiểm tra kích thước, nếu hợp lệ, đọc metadata từ ảnh
284
+ read_button.click(
285
+ fn=gradio_interface,
286
+ inputs=image_input,
287
+ outputs=[prompt_output, negative_prompt_output, model_output, lora_output, seed_output, sampler_output, sampler_params_output, other_metadata_output]
288
+ )
289
+ copy_button.click(
290
+ copy_to_clipboard,
291
+ inputs=[prompt_output, negative_prompt_output, seed_output, copy_prompt, copy_neg_prompt, copy_seed],
292
+ outputs=message_output
293
+ )
294
+
295
+ # Gắn sự kiện click cho nút hủy sao chép
296
+ cancel_button.click(
297
+ cancel_copy,
298
+ inputs=None,
299
+ outputs=[copy_prompt, copy_neg_prompt, copy_seed, message_output]
300
+ )
301
+ download_button.click(
302
+ fn=save_metadata_to_file,
303
+ inputs=[
304
+ image_input, prompt_output, negative_prompt_output,
305
+ model_output, lora_output, seed_output,
306
+ sampler_output, sampler_params_output, other_metadata_output
307
+ ],
308
+ outputs=None
309
+ )
310
+
311
+
312
+
313
+ if __name__ == "__main__":
314
+ demo.launch(inbrowser=True)