Vanillafag commited on
Commit
176b2bc
·
1 Parent(s): 0c1d314

New webui formatting and better json colors

Browse files
Files changed (2) hide show
  1. README.md +1 -1
  2. app.py +137 -21
README.md CHANGED
@@ -7,7 +7,7 @@ sdk: gradio
7
  sdk_version: 5.6.0
8
  app_file: app.py
9
  pinned: false
10
- short_description: Simple Stable Diffusion WebUI and NovelAI metadata reader
11
  ---
12
 
13
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
7
  sdk_version: 5.6.0
8
  app_file: app.py
9
  pinned: false
10
+ short_description: Stable Diffusion WebUI and NovelAI Metadata Reader
11
  ---
12
 
13
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py CHANGED
@@ -5,11 +5,97 @@ from io import BytesIO
5
  import json
6
  import html
7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  def process_nai(info_data):
9
- comment = json.loads(info_data.get("Comment", ""))
10
  html_data = f"""
11
- <p><span>Prompt:</span> {html.escape(comment.get('prompt', ''))}</p>
12
- <p><span>Undesired Content:</span> {html.escape(comment.get('uc', ''))}</p>
13
  <p><span>Resolution:</span> {comment.get('width', '')}x{comment.get('height', '')}</p>
14
  <p><span>Seed:</span> {comment.get('seed', '')}</p>
15
  <p><span>Steps:</span> {comment.get('steps', '')}</p>
@@ -18,7 +104,7 @@ def process_nai(info_data):
18
  <p><span>Prompt Guidance Rescale:</span> {comment.get('cfg_rescale', '')}</p>
19
  <p><span>Undesired Content Strength:</span> {comment.get('uncond_scale', '')}</p>
20
  <p><span>Request Type:</span> {comment.get('request_type', '')}</p>
21
- <p><span>Software:</span> {info_data.get('Software', '')}</p>
22
  <p><span>Source:</span> {info_data.get('Source', '')}</p>
23
  <p><span>Title:</span> {info_data.get('Title', '')}</p>
24
  <p><span>Generation Time:</span> {info_data.get('Generation time', info_data.get('Generation_time', ''))}</p>
@@ -35,49 +121,79 @@ def process_image(file=None, url=None):
35
  elif file:
36
  img = file
37
  else:
38
- return "No input provided.", {}, gr.update(visible=False)
 
 
 
 
 
39
 
40
- info_data = (img.info or None)
41
 
42
  if info_data:
43
  if "parameters" in info_data:
44
- html_data = info_data.get("parameters", "Error reading metadata.")
45
- html_data = html.escape(html_data).replace("\n", "<br>")
46
- html_data = f"<p>{html_data}</p>"
47
- return html_data, {}, gr.update(visible=True, value=img) if url else gr.update(visible=False)
48
- elif "Comment" in info_data and info_data.get("Software", None) == "NovelAI":
 
 
 
 
49
  simple, raw = process_nai(info_data)
50
- return simple, raw, gr.update(visible=True, value=img) if url else gr.update(visible=False)
 
 
 
 
 
51
  else:
52
- return "No metadata found.", {}, gr.update(visible=True, value=img) if url else gr.update(visible=False)
 
 
 
 
 
53
  else:
54
- return "No metadata found.", {}, gr.update(visible=True, value=img) if url else gr.update(visible=False)
 
 
 
 
 
55
  except Exception as e:
56
- return f"Error: {str(e)}", {}, gr.update(visible=False)
 
 
 
 
 
57
 
58
- with gr.Blocks(css="#html_data span {color: var(--color-accent)}") as demo:
59
  with gr.Row():
60
  with gr.Column():
61
  gr.Markdown("### Upload an Image or Provide a URL")
62
  input_url = gr.Textbox(label="Source Image URL")
63
  btn = gr.Button("Submit", variant="primary")
64
- input_img = gr.Image(label="Source Image", type='pil', height=240)
65
  with gr.Column():
66
  gr.Markdown("### Image Info")
67
  output_img = gr.Image(label="URL Image", interactive=False, visible=False, height=240)
68
  with gr.Tabs():
69
  with gr.Tab("Metadata"):
70
- output_html = gr.HTML(elem_id="html_data")
71
  with gr.Tab("Raw Parameters"):
72
- output_json = gr.JSON(container=False, show_indices=True)
 
73
 
74
  input_img.change(
75
  fn=process_image,
76
  inputs=input_img,
77
- outputs=[output_html, output_json, output_img],
78
  api_name="interrogate"
79
  )
80
 
81
- btn.click(process_image, inputs=[input_img, input_url], outputs=[output_html, output_json, output_img])
82
 
83
  demo.launch()
 
5
  import json
6
  import html
7
 
8
+ css = """
9
+ .html-container span {
10
+ color: var(--color-accent);
11
+ }
12
+ .json-node {
13
+ --string-color: #b5bd68;
14
+ --separator-color: var(--block-border-color);
15
+ }
16
+ .json-node .null {
17
+ color: var(--body-text-color-subdued);
18
+ }
19
+ .json-node .bool {
20
+ color: #cc99cc;
21
+ }
22
+ """
23
+
24
+ NL = "\n"
25
+
26
+ def parse_key_value_pairs(input_string):
27
+ pairs = []
28
+ key = None
29
+ value = ""
30
+ brace_count = 0
31
+ in_string = False
32
+ escaping = False
33
+
34
+ for i, char in enumerate(input_string):
35
+ if char == '"' and not escaping:
36
+ in_string = not in_string
37
+ elif char == "\\" and not escaping:
38
+ escaping = True
39
+ else:
40
+ escaping = False
41
+
42
+ if char == "{" and not in_string:
43
+ brace_count += 1
44
+ elif char == "}" and not in_string:
45
+ brace_count -= 1
46
+
47
+ if (char == "," and brace_count == 0 and not in_string) or i == len(input_string) - 1:
48
+ if i == len(input_string) - 1:
49
+ value += char
50
+ if key is not None and value:
51
+ pairs.append((key, value))
52
+ elif key is None and value and pairs:
53
+ prev_key, prev_value = pairs.pop()
54
+ pairs.append((prev_key, f"{prev_value},{value}"))
55
+ key, value = None, ""
56
+ elif char == ":" and brace_count == 0 and not in_string:
57
+ key, value = value, ""
58
+ else:
59
+ value += char
60
+
61
+ return [(k.strip(), v.strip()) for k, v in pairs]
62
+
63
+ def process_webui(info_data):
64
+ lines = info_data.split("\n")
65
+ positive_prompt = []
66
+ negative_prompt = []
67
+ settings_params = []
68
+ current_section = "positive"
69
+
70
+ for line in lines:
71
+ if current_section == "positive" and line.startswith("Negative prompt: "):
72
+ current_section = "negative"
73
+ line = line[len("Negative prompt: "):]
74
+ elif current_section != "settings" and line.startswith("Steps: "):
75
+ current_section = "settings"
76
+
77
+ if current_section == "positive":
78
+ positive_prompt.append(line)
79
+ elif current_section == "negative":
80
+ negative_prompt.append(line)
81
+ elif current_section == "settings":
82
+ settings_params.append(line)
83
+
84
+ html_data = f"""
85
+ <p><span>Prompt:</span> {html.escape(NL.join(positive_prompt)).replace(NL, '<br>')}</p>
86
+ <p><span>Negative prompt:</span> {html.escape(NL.join(negative_prompt)).replace(NL, '<br>')}</p>
87
+ """
88
+
89
+ for key, value in parse_key_value_pairs("\n".join(settings_params)):
90
+ html_data += f"<p><span>{html.escape(key).replace(NL, '<br>')}:</span> {html.escape(value).replace(NL, '<br>')}</p>"
91
+
92
+ return html_data
93
+
94
  def process_nai(info_data):
95
+ comment = json.loads(info_data["Comment"])
96
  html_data = f"""
97
+ <p><span>Prompt:</span> {html.escape(comment.get('prompt', '')).replace(NL, '<br>')}</p>
98
+ <p><span>Undesired Content:</span> {html.escape(comment.get('uc', '')).replace(NL, '<br>')}</p>
99
  <p><span>Resolution:</span> {comment.get('width', '')}x{comment.get('height', '')}</p>
100
  <p><span>Seed:</span> {comment.get('seed', '')}</p>
101
  <p><span>Steps:</span> {comment.get('steps', '')}</p>
 
104
  <p><span>Prompt Guidance Rescale:</span> {comment.get('cfg_rescale', '')}</p>
105
  <p><span>Undesired Content Strength:</span> {comment.get('uncond_scale', '')}</p>
106
  <p><span>Request Type:</span> {comment.get('request_type', '')}</p>
107
+ <p style="margin-top: 16px;"><span>Software:</span> {info_data.get('Software', '')}</p>
108
  <p><span>Source:</span> {info_data.get('Source', '')}</p>
109
  <p><span>Title:</span> {info_data.get('Title', '')}</p>
110
  <p><span>Generation Time:</span> {info_data.get('Generation time', info_data.get('Generation_time', ''))}</p>
 
121
  elif file:
122
  img = file
123
  else:
124
+ return (
125
+ "No input provided.",
126
+ gr.update(visible=False),
127
+ gr.update(visible=False),
128
+ gr.update(visible=False)
129
+ )
130
 
131
+ info_data = img.info
132
 
133
  if info_data:
134
  if "parameters" in info_data:
135
+ parameters = info_data["parameters"]
136
+ html_data = process_webui(parameters)
137
+ return (
138
+ html_data,
139
+ gr.update(visible=True, value=f"<p>{html.escape(parameters).replace(NL, '<br>')}</p>"),
140
+ gr.update(visible=False),
141
+ gr.update(visible=True, value=img) if url else gr.update(visible=False)
142
+ )
143
+ elif "Comment" in info_data and info_data.get("Software") == "NovelAI":
144
  simple, raw = process_nai(info_data)
145
+ return (
146
+ simple,
147
+ gr.update(visible=False),
148
+ gr.update(visible=True, value=raw),
149
+ gr.update(visible=True, value=img) if url else gr.update(visible=False)
150
+ )
151
  else:
152
+ return (
153
+ "No metadata found.",
154
+ gr.update(visible=False),
155
+ gr.update(visible=False),
156
+ gr.update(visible=True, value=img) if url else gr.update(visible=False)
157
+ )
158
  else:
159
+ return (
160
+ "No metadata found.",
161
+ gr.update(visible=False),
162
+ gr.update(visible=False),
163
+ gr.update(visible=True, value=img) if url else gr.update(visible=False)
164
+ )
165
  except Exception as e:
166
+ return (
167
+ f"Error: {str(e)}",
168
+ gr.update(visible=False),
169
+ gr.update(visible=False),
170
+ gr.update(visible=False)
171
+ )
172
 
173
+ with gr.Blocks(css=css) as demo:
174
  with gr.Row():
175
  with gr.Column():
176
  gr.Markdown("### Upload an Image or Provide a URL")
177
  input_url = gr.Textbox(label="Source Image URL")
178
  btn = gr.Button("Submit", variant="primary")
179
+ input_img = gr.Image(label="Source Image", type="pil", sources="upload", height=240)
180
  with gr.Column():
181
  gr.Markdown("### Image Info")
182
  output_img = gr.Image(label="URL Image", interactive=False, visible=False, height=240)
183
  with gr.Tabs():
184
  with gr.Tab("Metadata"):
185
+ output_html = gr.HTML()
186
  with gr.Tab("Raw Parameters"):
187
+ output_json = gr.JSON(container=False, visible=False)
188
+ output_params = gr.HTML(visible=False)
189
 
190
  input_img.change(
191
  fn=process_image,
192
  inputs=input_img,
193
+ outputs=[output_html, output_params, output_json, output_img],
194
  api_name="interrogate"
195
  )
196
 
197
+ btn.click(process_image, inputs=[input_img, input_url], outputs=[output_html, output_params, output_json, output_img])
198
 
199
  demo.launch()