Files
Tera-Dark-ComfyUI-Universal…/scripts/preview.py
T

106 lines
4.7 KiB
Python

"""Isolated Gallery preview. NOT a ComfyUI inference server.
python scripts/preview.py --port 8189
Creates demo images/state in a temporary directory, never in real ComfyUI paths.
Bind to localhost outside a sandbox; --host 0.0.0.0 is only for controlled preview.
"""
from __future__ import annotations
import argparse
import json
import os
from pathlib import Path
import random
import re
import sys
import tempfile
import time
import types
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--host", default="127.0.0.1")
parser.add_argument("--port", type=int, default=8189)
args = parser.parse_args()
root = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(root))
temporary = tempfile.TemporaryDirectory(prefix="universal-preview-")
base = Path(temporary.name)
for name in ("output", "input", "data"):
(base / name).mkdir()
os.environ["UNIVERSAL_EXTRACTOR_DATA_DIR"] = str(base / "data")
folder_paths = types.ModuleType("folder_paths")
folder_paths.base_path = str(base)
folder_paths.get_output_directory = lambda: str(base / "output")
folder_paths.get_input_directory = lambda: str(base / "input")
sys.modules["folder_paths"] = folder_paths
from PIL import Image, ImageDraw, PngImagePlugin
from aiohttp import web
from py.gallery import routes
palettes = [
("#efe9df", "#c3c6b3", "#677c68", "#ddd2b7"),
("#e9ddd3", "#dba890", "#ad705b", "#f2cfc0"),
("#dce4e7", "#b0c5c8", "#556f7c", "#d4d6c0"),
("#efe8d8", "#d7c09b", "#958267", "#e0c697"),
]
folders = ["01 · Landscapes", "02 · Color studies", "03 · Architecture"]
for folder in folders:
(base / "output" / folder).mkdir()
for index in range(18):
width, height = [(600, 760), (600, 600), (600, 460)][index % 3]
colors = palettes[index % len(palettes)]
image = Image.new("RGB", (width, height), colors[0])
draw = ImageDraw.Draw(image)
rng = random.Random(index)
if index % 3 == 0:
draw.ellipse((360, 100, 460, 200), fill=colors[3])
for layer in range(3):
y = height * (.44 + .17 * layer)
points = [(0, height), (0, y)] + [(x, y + rng.randrange(-65, 65)) for x in range(0, 660, 60)] + [(width, height)]
draw.polygon(points, fill=colors[(layer + 1) % 4])
elif index % 3 == 1:
for ring in range(8, 0, -1):
radius = ring * 32
draw.ellipse((300-radius, 300-radius, 300+radius, 300+radius), fill=colors[ring % 4])
else:
draw.rectangle((120, 110, 480, 460), fill=colors[1])
draw.rounded_rectangle((215, 160, 385, 500), radius=85, fill=colors[2])
draw.rectangle((0, 370, 600, 460), fill=colors[3])
draw.polygon([(390, 280), (600, 390), (600, 460), (390, 460)], fill=colors[2])
prompt = f"Demo study {index+1}, minimal composition, soft daylight"
graph = {"1": {"class_type": "CLIPTextEncode", "inputs": {"text": prompt}},
"2": {"class_type": "KSampler", "inputs": {"steps": 24, "cfg": 6, "seed": index, "positive": ["1", 0]}}}
metadata = PngImagePlugin.PngInfo()
metadata.add_text("prompt", json.dumps(graph))
image.save(base / "output" / folders[index % 3] / f"Study_{index+1:03}.png", pnginfo=metadata)
(base / "data" / "Demo prompts.json").write_text(json.dumps([
{"name": "Soft daylight", "tags": ["natural light", "minimal composition"]},
{"name": "Quiet landscapes", "tags": ["landscape", "muted colors"]},
], ensure_ascii=False))
async def preview_updates(force=False):
version = re.search(r'^version\s*=\s*"([^"]+)"', (root / "pyproject.toml").read_text(), re.M)[1]
return {"current_version": version, "latest_version": version, "update_available": False,
"published_at": None, "release_notes": "", "has_remote_check": False,
"checked_at": int(time.time()), "error": None, "repository_url": "https://github.com/Tera-Dark/ComfyUI-Universal-Extractor", "release_url": ""}
routes.check_update_status = preview_updates
app = web.Application()
routes.register_routes(app)
# ComfyUI normally provides /view. The isolated fixture supplies it only for its own samples.
async def preview_image(request):
kind = request.query.get("type", "output")
if kind not in ("input", "output"):
raise web.HTTPNotFound()
image_root = (base / kind).resolve()
image_path = (image_root / request.query.get("subfolder", "") / request.query.get("filename", "")).resolve()
if not image_path.is_relative_to(image_root) or not image_path.is_file():
raise web.HTTPNotFound()
return web.FileResponse(image_path)
app.router.add_get("/view", preview_image)
async def home(request):
raise web.HTTPFound("/gallery/")
app.router.add_get("/", home)
print("ISOLATED DEMO: procedural sample images, no ComfyUI/GPU inference; state is temporary.")
web.run_app(app, host=args.host, port=args.port)