Andylehere commited on
Commit
6976426
1 Parent(s): f086a2f

Initial commit

Browse files
Files changed (5) hide show
  1. INSTALL.BAT +9 -0
  2. RUN.bat +7 -0
  3. Wf_Info.py +316 -0
  4. requirements.txt +4 -0
  5. screenshot.jpg +0 -0
INSTALL.BAT ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ @echo Chuong trinh doc thong tin prompt ho tro Automatic1111,sd-forge,ComfyUI,Fooocus,InvokeAI,NovelAI
2
+ @echo Lien he: Andy N Le 0908231181
3
+ pip install sd-parsers
4
+ pip install pyperclip
5
+ pip install gradio requests
6
+ pip install gradio --upgrade
7
+
8
+ @echo cai xong roi !!!
9
+ pause
RUN.bat ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ @echo Chuong trinh doc thong tin prompt ho tro Automatic1111,sd-forge,ComfyUI,Fooocus,InvokeAI,NovelAI
2
+ @echo Lien he: Andy N Le 0908231181
3
+ @echo .
4
+ @echo vui long doi ti....
5
+ python Wf_Info.py
6
+
7
+ pause
Wf_Info.py ADDED
@@ -0,0 +1,316 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 có 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ử lý ả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ử lý ả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 và 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)
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ gradio
2
+ Pillow
3
+ sd-parsers
4
+ pyperclip
screenshot.jpg ADDED