vorstcavry commited on
Commit
46ae391
·
verified ·
1 Parent(s): 0644821

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +15 -204
app.py CHANGED
@@ -3,11 +3,9 @@ from pathlib import Path
3
  import os
4
  import shutil
5
  from huggingface_hub import HfApi, snapshot_download
6
- from PIL import Image, ExifTags
7
- import base64
8
- import tempfile
9
 
10
- HF_TOKEN = os.environ.get("HF_TOKEN")
 
11
  if not HF_TOKEN:
12
  raise ValueError("HF_TOKEN not set")
13
 
@@ -16,14 +14,10 @@ username = api.whoami(token=HF_TOKEN)["name"]
16
  repo = "sd_out"
17
  user_repo = f"{username}/{repo}"
18
 
19
-
20
  def refresh_images():
21
- # hapus cache lama (jika ada) lalu download snapshot dataset dan salin ke folder local "images"
22
  try:
23
- old = os.environ.get("IMAGE_DIR", "")
24
- if old:
25
- shutil.rmtree(old)
26
- except Exception:
27
  pass
28
 
29
  image_dir = Path(
@@ -31,7 +25,7 @@ def refresh_images():
31
  )
32
  os.environ["IMAGE_DIR"] = str(image_dir)
33
 
34
- image_files = sorted(list(image_dir.rglob("*.[pjw]*[npjg]*[ge]*")))
35
 
36
  local_dir = Path("images")
37
  local_dir.mkdir(exist_ok=True)
@@ -39,205 +33,22 @@ def refresh_images():
39
  copied_files = []
40
  for img in image_files:
41
  dst = local_dir / img.name
42
- try:
43
- shutil.copy2(img, dst)
44
- copied_files.append(str(dst))
45
- except Exception:
46
- # kalau gagal salin, lewati
47
- continue
48
 
49
  return copied_files
50
 
51
 
52
- def _human_size(n):
53
- n = float(n)
54
- for unit in ["B", "KB", "MB", "GB", "TB"]:
55
- if n < 1024.0:
56
- return f"{n:.2f} {unit}"
57
- n /= 1024.0
58
- return f"{n:.2f} PB"
59
-
60
-
61
- def _extract_prompt_from_image_or_exif(img_path_or_b64):
62
- """
63
- Kembalikan tuple (prompt_text_or_None, source_description_or_None).
64
- Cek urutan: PNG tEXt/info keys (parameters, prompt, etc.) -> EXIF common tags.
65
- """
66
- tmp_file = None
67
- try:
68
- # Bila base64 data: simpan sementara
69
- if isinstance(img_path_or_b64, str) and img_path_or_b64.startswith("data:"):
70
- header, b64 = img_path_or_b64.split(",", 1)
71
- data = base64.b64decode(b64)
72
- tmpf = tempfile.NamedTemporaryFile(suffix=".png", delete=False)
73
- tmpf.write(data)
74
- tmpf.flush()
75
- tmpf.close()
76
- img_path = tmpf.name
77
- tmp_file = img_path
78
- else:
79
- img_path = str(img_path_or_b64)
80
-
81
- with Image.open(img_path) as im:
82
- info = im.info or {}
83
- # Periksa beberapa kunci umum di PNG tEXt / info
84
- for k in ("parameters", "prompt", "caption", "description", "Comment", "comment"):
85
- if k in info and info[k]:
86
- return info[k], f"PNG info ('{k}')"
87
- # kadang Pillow menempatkan text chunks di 'text' dict
88
- if "text" in info and isinstance(info["text"], dict) and info["text"]:
89
- lines = []
90
- for k, v in info["text"].items():
91
- lines.append(f"{k}: {v}")
92
- if lines:
93
- return "\n".join(lines), "PNG text chunks"
94
-
95
- # EXIF (umumnya untuk JPEG)
96
- try:
97
- exif_raw = im.getexif()
98
- if exif_raw:
99
- exif = {}
100
- for tag_id, val in exif_raw.items():
101
- tag = ExifTags.TAGS.get(tag_id, tag_id)
102
- # decode bytes jika perlu
103
- if isinstance(val, bytes):
104
- try:
105
- val = val.decode("utf-8", errors="ignore")
106
- except Exception:
107
- val = str(val)
108
- exif[tag] = val
109
- for tagname in ("ImageDescription", "UserComment", "XPComment"):
110
- if tagname in exif and exif[tagname]:
111
- return exif[tagname], f"EXIF '{tagname}'"
112
- except Exception:
113
- pass
114
-
115
- return None, None
116
- finally:
117
- if tmp_file:
118
- try:
119
- os.remove(tmp_file)
120
- except Exception:
121
- pass
122
-
123
-
124
- def get_image_info(selected):
125
- """
126
- Fungsi yang dipanggil saat user memilih item di Gallery.
127
- Bisa menerima nilai dalam beberapa bentuk (list, dict, path string, base64).
128
- Mengembalikan string yang akan ditampilkan di Textbox.
129
- """
130
- if not selected:
131
- return "No image selected."
132
-
133
- # Gallery kadang mengirim list berisi single path, handle itu:
134
- if isinstance(selected, list) and len(selected) > 0:
135
- selected = selected[0]
136
-
137
- # Gallery kadang mengirim dict dengan key 'name' atau 'image'
138
- if isinstance(selected, dict):
139
- for k in ("name", "image", "src", "path", "filename"):
140
- if k in selected:
141
- selected = selected[k]
142
- break
143
-
144
- # Jika selected adalah data URI (base64), kita akan simpan sementara untuk baca metadata
145
- is_data_uri = isinstance(selected, str) and selected.startswith("data:")
146
 
147
- tmp_path = None
148
- cleanup_tmp = False
149
- try:
150
- if is_data_uri:
151
- header, b64 = selected.split(",", 1)
152
- data = base64.b64decode(b64)
153
- tmpf = tempfile.NamedTemporaryFile(suffix=".png", delete=False)
154
- tmpf.write(data)
155
- tmpf.flush()
156
- tmpf.close()
157
- tmp_path = tmpf.name
158
- path = tmp_path
159
- cleanup_tmp = True
160
- else:
161
- path = str(selected)
162
-
163
- lines = []
164
- p = Path(path)
165
- lines.append(f"File: {p.name}")
166
-
167
- # ukuran file (jika ada path lokal)
168
- try:
169
- size_bytes = os.path.getsize(path)
170
- lines.append(f"Size: {_human_size(size_bytes)} ({size_bytes} bytes)")
171
- except Exception:
172
- # jika not a local file (mis. base64), skip
173
- pass
174
-
175
- # buka image untuk dapatkan dimensi/format/mode/dpi
176
- try:
177
- with Image.open(path) as im:
178
- lines.append(f"Format: {im.format}")
179
- lines.append(f"Mode: {im.mode}")
180
- lines.append(f"Dimensions: {im.width} x {im.height} px")
181
- dpi = im.info.get("dpi")
182
- if dpi:
183
- lines.append(f"DPI: {dpi}")
184
- except Exception as e:
185
- lines.append(f"(Could not open image: {e})")
186
-
187
- # cari prompt dari metadata/image info/exif
188
- prompt, src = _extract_prompt_from_image_or_exif(path if not is_data_uri else selected)
189
- if prompt:
190
- lines.append("")
191
- lines.append("--- Prompt ---")
192
- lines.append(f"Source: {src}")
193
- lines.append(prompt)
194
- else:
195
- # cek sidecar .png.txt atau .txt (prioritas)
196
- cand1 = p.with_suffix(p.suffix + ".txt") # e.g. image.png.txt
197
- cand2 = p.with_suffix(".txt") # e.g. image.txt
198
- found = False
199
- for c in (cand1, cand2):
200
- try:
201
- if c.exists():
202
- txt = c.read_text(encoding="utf-8")
203
- lines.append("")
204
- lines.append("--- Prompt (from sidecar) ---")
205
- lines.append(txt)
206
- found = True
207
- break
208
- except Exception:
209
- pass
210
- if not found:
211
- lines.append("")
212
- lines.append("Prompt: (not found)")
213
-
214
- return "\n".join(lines)
215
- finally:
216
- if cleanup_tmp and tmp_path:
217
- try:
218
- os.remove(tmp_path)
219
- except Exception:
220
- pass
221
-
222
-
223
- with gr.Blocks(analytics_enabled=False, title="Image Gallery", theme="NoCrypt/miku") as demo:
224
- gr.HTML("<center><h1>Image Gallery</h1></center>")
225
-
226
- with gr.Row():
227
- submit = gr.Button("Refresh", variant="primary")
228
-
229
- gallery = gr.Gallery(value=[], columns=4, show_label=False, height=800, object_fit="contain")
230
-
231
- info_box = gr.Textbox(
232
- label="Image Info / Prompt",
233
- lines=12,
234
- interactive=False,
235
- placeholder="Select an image to see its info...",
236
  )
237
 
238
  submit.click(refresh_images, outputs=[gallery])
239
 
240
- # Saat user memilih item di gallery -> panggil get_image_info
241
- gallery.select(fn=get_image_info, inputs=[gallery], outputs=[info_box])
242
-
243
- demo.launch(debug=True)
 
3
  import os
4
  import shutil
5
  from huggingface_hub import HfApi, snapshot_download
 
 
 
6
 
7
+ HF_TOKEN = os.environ["HF_TOKEN"]
8
+
9
  if not HF_TOKEN:
10
  raise ValueError("HF_TOKEN not set")
11
 
 
14
  repo = "sd_out"
15
  user_repo = f"{username}/{repo}"
16
 
 
17
  def refresh_images():
 
18
  try:
19
+ shutil.rmtree(os.environ["IMAGE_DIR"])
20
+ except:
 
 
21
  pass
22
 
23
  image_dir = Path(
 
25
  )
26
  os.environ["IMAGE_DIR"] = str(image_dir)
27
 
28
+ image_files = list(Path(image_dir).rglob("*.[pjw]*[npjg]*[ge]*"))
29
 
30
  local_dir = Path("images")
31
  local_dir.mkdir(exist_ok=True)
 
33
  copied_files = []
34
  for img in image_files:
35
  dst = local_dir / img.name
36
+ shutil.copy(img, dst)
37
+ copied_files.append(str(dst))
 
 
 
 
38
 
39
  return copied_files
40
 
41
 
42
+ with gr.Blocks(
43
+ analytics_enabled=False, title="Image Gallery", theme="NoCrypt/miku"
44
+ ) as demo:
45
+ gr.HTML("""<center><h1>Image Gallery</h1></center>""")
46
+ submit = gr.Button("Refresh", variant="primary")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
 
48
+ gallery = gr.Gallery(
49
+ value=[], columns=4, show_label=False, height=800, object_fit="contain"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  )
51
 
52
  submit.click(refresh_images, outputs=[gallery])
53
 
54
+ demo.launch(debug=True)