Files
2026-07-13 13:19:52 +08:00

154 lines
4.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""MetaStyle T8 节点核心逻辑
输入:
- style_key (string): 选中的风格 key,前端 widget 写入
- output_size (combo): 输出尺寸 original / 512 / 1024
- seed (int): 预留
输出:
- IMAGE 风格代表图 (BHWC float32 0~1)
- style_name 风格全名
- category 大类(中文)
- sample_prompt 示例提示词(可直接接 CLIPTextEncode
- sample_id 数据集原始 id
- meta_json 全量元数据 JSON 字符串
"""
import json
import os
from pathlib import Path
import numpy as np
import torch
from PIL import Image
ROOT = Path(__file__).resolve().parent
DATA = ROOT / "data"
_meta_cache = None
_catalog_cache = None
_lite_cache = None
def load_meta() -> dict:
global _meta_cache
if _meta_cache is None:
p = DATA / "styles_meta.json"
_meta_cache = json.loads(p.read_text(encoding="utf-8")) if p.exists() else {}
return _meta_cache
def load_catalog() -> dict:
global _catalog_cache
if _catalog_cache is None:
p = DATA / "catalog.json"
_catalog_cache = json.loads(p.read_text(encoding="utf-8")) if p.exists() else {}
return _catalog_cache
def load_lite() -> list:
global _lite_cache
if _lite_cache is None:
p = DATA / "styles_lite.json"
_lite_cache = json.loads(p.read_text(encoding="utf-8")) if p.exists() else []
return _lite_cache
def pil_to_tensor(im: Image.Image) -> torch.Tensor:
"""PIL -> ComfyUI 标准 IMAGE tensor: shape (1, H, W, 3), float32 0~1"""
if im.mode != "RGB":
im = im.convert("RGB")
arr = np.asarray(im).astype(np.float32) / 255.0
return torch.from_numpy(arr)[None, ...]
def empty_image(w: int = 512, h: int = 512) -> torch.Tensor:
return torch.zeros((1, h, w, 3), dtype=torch.float32)
class MetaStyleT8Picker:
"""T8 风格选择器:按风格挑选代表图与示例提示词。"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
# 由前端 widget 维护的字符串:选中的 style key
"style_key": ("STRING", {
"default": "",
"multiline": False,
"metastyle_picker": True, # 给前端 JS 识别用
}),
"output_size": (["original", "512", "768", "1024"],
{"default": "original"}),
},
"optional": {
"seed": ("INT", {
"default": 0, "min": 0, "max": 0xFFFFFFFF
}),
},
}
RETURN_TYPES = (
"IMAGE", "STRING", "STRING", "STRING", "STRING", "STRING",
)
RETURN_NAMES = (
"image", "style_name", "category",
"sample_prompt", "sample_id", "meta_json",
)
FUNCTION = "pick"
CATEGORY = "T8/Style"
def pick(self, style_key: str, output_size: str, seed: int = 0):
meta = load_meta()
style_key = (style_key or "").strip()
info = meta.get(style_key)
if not info:
# 未选中或 key 无效 → 返回空图,提示文字
return (
empty_image(),
style_key,
"",
"",
"",
json.dumps({"error": "style_key not found", "key": style_key},
ensure_ascii=False),
)
img_path = ROOT / "data" / info["image"]
try:
with Image.open(img_path) as im:
im.load()
if output_size != "original":
target = int(output_size)
im = im.copy()
im.thumbnail((target, target), Image.LANCZOS)
tensor = pil_to_tensor(im)
except Exception as e:
return (
empty_image(),
style_key,
info.get("category", ""),
info.get("sample_content", ""),
info.get("sample_id", ""),
json.dumps({"error": str(e), "key": style_key},
ensure_ascii=False),
)
return (
tensor,
info.get("style_full", style_key),
info.get("category", ""),
info.get("sample_content", ""),
info.get("sample_id", ""),
json.dumps(info, ensure_ascii=False),
)
NODE_CLASS_MAPPINGS = {
"MetaStyleT8Picker": MetaStyleT8Picker,
}
NODE_DISPLAY_NAME_MAPPINGS = {
"MetaStyleT8Picker": "MetaStyle T8 风格选择器",
}