q6 commited on
Commit
09814ae
·
1 Parent(s): e087d85

Preserve workflow metadata in archives

Browse files
Files changed (2) hide show
  1. app.py +9 -2
  2. workflow_api.py +27 -0
app.py CHANGED
@@ -23,6 +23,7 @@ from fastapi.middleware.cors import CORSMiddleware
23
  from fastapi.responses import FileResponse
24
  from gradio.routes import App
25
  from PIL import Image
 
26
  from pydantic import BaseModel, Field
27
 
28
 
@@ -227,13 +228,16 @@ def generate_core(prompt, width=1152, height=896, steps=16):
227
  positive = state["encode"].encode(clip=state["clip"], text=f"{prompt},{SUFFIX}")[0]
228
  negative = state["encode"].encode(clip=state["negative_clip"], text=NEGATIVE)[0]
229
  latent = state["latent"].generate(width=width, height=height, batch_size=1)[0]
 
230
  samples = state["sample"].sample(
231
- model=state["model"], seed=random.randrange(2**64), steps=steps, cfg=4,
232
  sampler_name="euler_ancestral", scheduler="karras", positive=positive,
233
  negative=negative, latent_image=latent, denoise=1,
234
  )[0]
235
  image = state["decode"].decode(vae=state["vae"], samples=samples)[0][0]
236
  result = Image.fromarray(np.clip(image.detach().cpu().numpy() * 255, 0, 255).astype(np.uint8))
 
 
237
  backup_pool.submit(archive_image, result)
238
  return result
239
 
@@ -249,7 +253,10 @@ def archive_image(image):
249
  shutil.copy2(path, local)
250
  mode = "a" if local.is_file() else "w"
251
  data = BytesIO()
252
- image.save(data, format="PNG")
 
 
 
253
  with py7zr.SevenZipFile(local, mode=mode, password=PASSWORD) as archive:
254
  archive.set_encrypted_header(True)
255
  name = f"{len(archive.getnames()) + 1}ST.png"
 
23
  from fastapi.responses import FileResponse
24
  from gradio.routes import App
25
  from PIL import Image
26
+ from PIL.PngImagePlugin import PngInfo
27
  from pydantic import BaseModel, Field
28
 
29
 
 
228
  positive = state["encode"].encode(clip=state["clip"], text=f"{prompt},{SUFFIX}")[0]
229
  negative = state["encode"].encode(clip=state["negative_clip"], text=NEGATIVE)[0]
230
  latent = state["latent"].generate(width=width, height=height, batch_size=1)[0]
231
+ seed = random.randrange(2**64)
232
  samples = state["sample"].sample(
233
+ model=state["model"], seed=seed, steps=steps, cfg=4,
234
  sampler_name="euler_ancestral", scheduler="karras", positive=positive,
235
  negative=negative, latent_image=latent, denoise=1,
236
  )[0]
237
  image = state["decode"].decode(vae=state["vae"], samples=samples)[0][0]
238
  result = Image.fromarray(np.clip(image.detach().cpu().numpy() * 255, 0, 255).astype(np.uint8))
239
+ from workflow_api import image_metadata
240
+ result.info.update(image_metadata(prompt, width, height, steps, seed))
241
  backup_pool.submit(archive_image, result)
242
  return result
243
 
 
253
  shutil.copy2(path, local)
254
  mode = "a" if local.is_file() else "w"
255
  data = BytesIO()
256
+ pnginfo = PngInfo()
257
+ for key in ("prompt", "workflow"):
258
+ pnginfo.add_text(key, image.info[key])
259
+ image.save(data, format="PNG", pnginfo=pnginfo)
260
  with py7zr.SevenZipFile(local, mode=mode, password=PASSWORD) as archive:
261
  archive.set_encrypted_header(True)
262
  name = f"{len(archive.getnames()) + 1}ST.png"
workflow_api.py CHANGED
@@ -588,6 +588,33 @@ def build_extra_pnginfo() -> dict[str, Any] | None:
588
  }
589
 
590
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
591
  workflow = build_workflow()
592
  prompt = json.loads(json.dumps(workflow))
593
  extra_pnginfo = build_extra_pnginfo()
 
588
  }
589
 
590
 
591
+ def image_metadata(text, width, height, steps, seed):
592
+ api = build_workflow()
593
+ api["118"]["inputs"]["string_a"] = text
594
+ api["27"]["inputs"].update(width=width, height=height)
595
+ api["5"]["inputs"].update(seed=seed, steps=steps)
596
+ api["28"]["inputs"].update(model=["10", 0], clip=["10", 1])
597
+ api.pop("38")
598
+
599
+ workflow = build_extra_pnginfo()["workflow"]
600
+ nodes = {node["id"]: node for node in workflow["nodes"]}
601
+ nodes[118]["widgets_values"][0] = text
602
+ nodes[27]["widgets_values"][:2] = [width, height]
603
+ nodes[5]["widgets_values"][0] = seed
604
+ nodes[5]["widgets_values"][2] = steps
605
+ nodes[10]["outputs"][0]["links"] = [27]
606
+ nodes[10]["outputs"][1]["links"] = [28]
607
+ workflow["nodes"] = [node for node in workflow["nodes"] if node["id"] != 38]
608
+ workflow["links"] = [
609
+ [link[0], 10, *link[2:]] if link[0] in {27, 28} else link
610
+ for link in workflow["links"] if link[0] not in {29, 30}
611
+ ]
612
+ return {
613
+ "prompt": json.dumps(api, separators=(",", ":")),
614
+ "workflow": json.dumps(workflow, separators=(",", ":")),
615
+ }
616
+
617
+
618
  workflow = build_workflow()
619
  prompt = json.loads(json.dumps(workflow))
620
  extra_pnginfo = build_extra_pnginfo()