File size: 4,197 Bytes
bb94a34 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | import io
import json
import os
import sys
import time
from pathlib import Path
from PIL import Image
from backend.providers.black_forest_image import generate_image
ROOT = Path(__file__).resolve().parent.parent
IMAGE_DIR = ROOT / "frontend" / "public" / "fallbacks"
ASCII_DIR = ROOT / "backend" / "fallback_ascii"
MANIFEST = ROOT / "assets" / "fallback-manifest.json"
SUBJECTS = [
("antique-key", "an oversized antique key with a circular bow and three distinct teeth"),
("lighthouse", "a solitary lighthouse projecting two sharp triangular beams"),
("watchful-eye", "a single watchful human eye with a bold iris and clean eyelid contour"),
("open-door", "an open doorway with one bright geometric ray emerging through it"),
("hourglass", "a large hourglass with clearly separated falling grains"),
("broken-chain", "two heavy broken chain links pulling apart at the center"),
("broadcast-microphone", "a vintage broadcast microphone with a simple circular signal halo"),
("burning-match", "one upright match with a large graphic flame"),
("theatrical-mask", "a single cracked theatrical mask with one strong diagonal fracture"),
("compass", "a large compass face with one bold needle pointing northeast"),
("raised-hand", "one open human hand reaching upward with clearly separated fingers"),
("spiral-shell", "a single nautilus shell with a bold geometric spiral"),
("alarm-clock", "a classic twin-bell alarm clock with clear hands near midnight"),
("paper-boat", "one folded paper boat riding on a single curved wave"),
("mountain-flag", "one steep triangular mountain peak with a flag at the summit"),
("sealed-letter", "a single closed envelope with a large circular wax seal"),
("labyrinth", "a simple circular labyrinth with one visible route toward the center"),
("fallen-crown", "one tilted crown with three tall points and a single missing jewel"),
("sprouting-seed", "one seed split open with a strong sprout and two leaves"),
("satellite-dish", "one satellite dish angled upward with three concentric signal arcs"),
]
STYLE = (
"Create a terminal-screen pseudo-ASCII illustration. Faithfully preserve the "
"object's defining geometry before adding stylistic detail. The image itself "
"must visibly be made only from evenly spaced glowing green monospace terminal "
"glyphs on pure black: Unicode Braille dots, block characters, box-drawing "
"lines, slashes and punctuation. Preserve circles, ovals, straight rails, "
"symmetry, gaps and radial lines where required. Use large readable glyph cells "
"with visible black gaps between characters. Center one complete object. Crisp "
"bitmap terminal screenshot, no photorealism, no smooth painted surfaces, no "
"solid vector fills, no caption, no labels, no border, no interface chrome, "
"no watermark."
)
def main() -> None:
if not os.getenv("BFL_API_KEY", "").strip():
raise SystemExit("BFL_API_KEY is not configured")
IMAGE_DIR.mkdir(parents=True, exist_ok=True)
MANIFEST.parent.mkdir(parents=True, exist_ok=True)
records = []
force = "--force" in sys.argv
for index, (slug, description) in enumerate(SUBJECTS, start=1):
image_path = IMAGE_DIR / f"fallback-{index:02d}.webp"
prompt = f"{description}. {STYLE}"
if not force and image_path.exists():
print(f"[{index:02d}/20] skip {slug}")
else:
print(f"[{index:02d}/20] generate {slug}", flush=True)
result = generate_image(prompt, width=768, height=512)
with Image.open(io.BytesIO(result)) as image:
image.convert("RGB").save(image_path, "WEBP", quality=88, method=6)
time.sleep(0.35)
records.append(
{
"index": index,
"slug": slug,
"description": description,
"image": f"/fallbacks/fallback-{index:02d}.webp",
}
)
MANIFEST.write_text(json.dumps(records, indent=2) + "\n", encoding="utf-8")
print(f"Wrote {len(records)} BFL fallback objects and manifest")
if __name__ == "__main__":
main()
|