commit d8086a1e4398d125081c654a61eeaca69cc71844 Author: xiangyuanmeng Date: Tue Dec 5 10:57:27 2023 +0800 # feat: 可行性测试 diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..377526c --- /dev/null +++ b/__init__.py @@ -0,0 +1,3 @@ +from .mexx_poster import NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS + +__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS'] diff --git a/asset/blood.png b/asset/blood.png new file mode 100644 index 0000000..895a923 Binary files /dev/null and b/asset/blood.png differ diff --git a/asset/font/NotoSansHans-DemiLight.otf b/asset/font/NotoSansHans-DemiLight.otf new file mode 100644 index 0000000..6a5ae0c Binary files /dev/null and b/asset/font/NotoSansHans-DemiLight.otf differ diff --git a/asset/font/gaoduanhei.ttf b/asset/font/gaoduanhei.ttf new file mode 100644 index 0000000..ee49dea Binary files /dev/null and b/asset/font/gaoduanhei.ttf differ diff --git a/asset/font/xintangren.ttf b/asset/font/xintangren.ttf new file mode 100644 index 0000000..2039fea Binary files /dev/null and b/asset/font/xintangren.ttf differ diff --git a/card/poster.css b/card/poster.css new file mode 100644 index 0000000..683cde1 --- /dev/null +++ b/card/poster.css @@ -0,0 +1,146 @@ +@font-face { + font-family: 'gaoduanhei'; + src: url('file:///{mexx_path}/asset/font/gaoduanhei.ttf'); +} +@font-face { + font-family: 'NotoSansHans-DemiLight'; + src: url('file:///{mexx_path}/asset/font/NotoSansHans-DemiLight.otf'); +} +@font-face { + font-family: 'xintangren'; + src: url('file:///{mexx_path}/asset/font/xintangren.ttf'); +} +skill-description { + font-size: 0.8em; +} +.card { + position: relative; + width: 400px; + height: 560px; + border-radius: 15px; + border: 1px solid black; + background-color: white; +} + +.frame-top { + position: absolute; + top: 70px; + right: 1%; + width: 90%; + height: 5%; + border-color: {color1}; + border-style: solid; + border-width: 3px 0px 0px 0px; +} + +.frame-right { + position: absolute; + top: 20px; + right: 9%; + width: 5%; + height: 450px; + border-color: {color2}; + border-style: solid; + border-width: 0px 4px 0px 0px; +} + +.card-image { + position: relative; + width: 76%; + height: 80%; + margin: 18% 11% 12% 13%; + background-size: cover; + background-color: #cccccc; + background-repeat: no-repeat; + background-position: center; + box-shadow: 0 0 10px 10px white inset; +} + +.blur-background { + position: absolute; + top: 0; + -webkit-filter: blur(5px); + -moz-filter: blur(5px); + -o-filter: blur(5px); + -ms-filter: blur(5px); + filter: blur(5px); + width: 100%; + height: 100px; + background-color: white; + opacity: 0.4; +} +.card-header { + position: absolute; + top: 0px; + width: 100%; +} +.clan { + font-size: 3.6em; + margin: 1% 2% 2% 3%; + display: inline-block; + vertical-align: top; + font-family: 'gaoduanhei'; + color: black; +} +.blood { + display: inline-block; + vertical-align: top; + margin-top: 6%; + width: 30px; + height: 30px; + background-size: auto 100%; + background-image: url("file:///{mexx_path}/asset/blood.png"); + background-repeat: no-repeat; + background-position: center; +} +.profile-section { + position: absolute; + top: 100px; + left: 2%; + width: 96%; + opacity: 0.9; + border-radius: 5px; +} +.nickname { + font-family: 'xintangren'; + font-size: 1.7em; + margin: 2%; + width: 5%; + color: {color3}; + text-shadow: 2px 2px 2px white; +} +.name { + font-family: 'xintangren'; + font-size: 3.0em; + margin: 20px 0px 0px 0px; + width: 5%; + color: {color3}; + text-shadow: 0px 0px 0px white; +} +.skill-section { + position: absolute; + bottom: 1%; + left: 4%; + width: 92%; + margin-bottom: 2%; + background-color: #E2ECFA; + opacity: 0.9; + border-radius: 5px; +} +.skill-block { + margin: 10px; +} +.skill-block div { + display: inline-block; + vertical-align: top; +} +.skill-title-content { + font-family: 'gaoduanhei'; + font-size: 1.6em; + width: 15%; +} +.skill-description-content { + font-family: 'NotoSansHans-DemiLight'; + font-size: 0.8em; + width: 83%; +} \ No newline at end of file diff --git a/card/poster.html b/card/poster.html new file mode 100644 index 0000000..bb5f41f --- /dev/null +++ b/card/poster.html @@ -0,0 +1,47 @@ +
+ +
+
+ +
+
+ +
+
+ +
{clan}
+ + + +
+
+
+ +
+ + +
+
+ {nickname} +
+
+ {name} +
+
+ + + +
+
+
+ {title1} +
+
+ + {description1} + +
+
+
+ +
\ No newline at end of file diff --git a/mexx_poster.py b/mexx_poster.py new file mode 100644 index 0000000..a71f5cd --- /dev/null +++ b/mexx_poster.py @@ -0,0 +1,137 @@ +import folder_paths +from comfy.cli_args import args + +from html2image import Html2Image +from PIL import Image +from PIL.PngImagePlugin import PngInfo + +import numpy as np +import json +import os +import shutil +import random + + +class ComfyUI_Mexx_Poster: + def __init__(self): + self.output_dir = folder_paths.get_output_directory() + self.type = "output" + self.prefix_append = "" + + @classmethod + def INPUT_TYPES(s): + styles = ["card"] + return { + "required": + {"images": ("IMAGE",), + "filename_prefix": ("STRING", {"default": "ComfyUI"}), + "fps": ("FLOAT", {"default": 6.0, "min": 0.01, "max": 1000.0, "step": 0.01}), + "compress_level": ("INT", {"default": 4, "min": 0, "max": 9}), + "style": (styles,), + }, + "hidden": {"prompt": "PROMPT", "extra_pnginfo": "EXTRA_PNGINFO"}, + } + + RETURN_TYPES = () + + FUNCTION = "poster" + + OUTPUT_NODE = True + + CATEGORY = "ComfyUI_Mexx_Poster" + + def poster(self, + images, + fps, + compress_level, + filename_prefix="ComfyUI", + style="card", + prompt=None, + extra_pnginfo=None): + filename_prefix += self.prefix_append + full_output_folder, filename, counter, subfolder, filename_prefix = folder_paths.get_save_image_path( + filename_prefix, self.output_dir, images[0].shape[1], images[0].shape[0]) + results = list() + pil_images = [] + for image in images: + i = 255. * image.cpu().numpy() + img = Image.fromarray(np.clip(i, 0, 255).astype(np.uint8)) + pil_images.append(img) + + metadata = None + if not args.disable_metadata: + metadata = PngInfo() + if prompt is not None: + metadata.add(b"comf", + "prompt".encode("latin-1", "strict") + b"\0" + json.dumps(prompt).encode("latin-1", + "strict"), + after_idat=True) + if extra_pnginfo is not None: + for x in extra_pnginfo: + metadata.add(b"comf", + x.encode("latin-1", "strict") + b"\0" + json.dumps(extra_pnginfo[x]).encode("latin-1", + "strict"), + after_idat=True) + + file = f"{filename}_{counter:05}_.png" + os_path_join_file = os.path.join(full_output_folder, file) + pil_images[0].save(os_path_join_file, pnginfo=metadata, compress_level=compress_level, + save_all=True, duration=int(1000.0 / fps), append_images=pil_images[1:]) + print(f'file:{file}') + hti = Html2Image() + current_directory = os.path.dirname(os.path.realpath(__file__)) + print(f'current_directory:{current_directory}') + + css_file = open(f"{current_directory}/{style}/poster.css") + css_template = css_file.read() + colors = ['#0094DF', '#FF6B20', '#D53B2A', '#FF6B20', '#8E1580', '#76368C', '#1DEAFF', '#FFA500', + '#960309', '#086AAA', '#22625E', '#F9A1D0', '#273268', '#547443'] + color1 = random.choice(colors) + color2 = random.choice(colors) + color3 = random.choice(colors) + color4 = random.choice(colors) + css = css_template.replace("{mexx_path}", current_directory) + css = css.replace("{color1}", color1) + css = css.replace("{color2}", color2) + css = css.replace("{color3}", color3) + css = css.replace("{color4}", color4) + html_file = open(f"{current_directory}/{style}/poster.html") + html_template = html_file.read() + clans = ['机娘', '女妖', '神秘', '巫师', '骑士', '战士', '兽族', '帝国', + '联盟', '部落', '五行', '高塔', '星灵'] + clan = random.choice(clans) + nicknames = ['機械女', '弓腰姬', '使者', '万法', '女帝', '垣法', '行走', '逍遥', ] + nickname = random.choice(nicknames) + names = ['富江', '春春', '富春', '希仔', '幺幺', '湾仔', '花花', '襄垣'] + name = random.choice(names) + titles = ['雞湯', '心灵', '行舟', '侧畔', '春晓', '执着', '卷子', '慎独'] + title1 = random.choice(titles) + descriptions = ['員工技,作為一名優秀的員工,当老闆給妳灌了一口雞湯,妳的血量-1。', + '主公技,作為一名優秀的老闆,当給員工灌了一口雞湯时,妳的金钱+2。'] + description1 = random.choice(descriptions) + html = html_template.format(os_path_join_file=os_path_join_file, + clan=clan, + nickname=nickname, + name=name, + title1=title1, + description1=description1 + ) + poster = f"{filename}_{counter:05}_Poster.png" + print(f'poster:{poster}') + hti.screenshot(html_str=html, css_str=css, save_as=poster, size=(425, 585)) + shutil.move(poster, full_output_folder) + results.append({ + "filename": poster, + "subfolder": subfolder, + "type": self.type + }) + return {"ui": {"images": results, "animated": (False,)}} + + +NODE_CLASS_MAPPINGS = { + "ComfyUI_Mexx_Poster": ComfyUI_Mexx_Poster +} + +NODE_DISPLAY_NAME_MAPPINGS = { + "ComfyUI_Mexx_Poster": "ComfyUI_Mexx_Poster" +} diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..a95d94a --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +html2image \ No newline at end of file