# feat: 可行性测试
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
from .mexx_poster import NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS
|
||||
|
||||
__all__ = ['NODE_CLASS_MAPPINGS', 'NODE_DISPLAY_NAME_MAPPINGS']
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
+146
@@ -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%;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<div id="card" class="card">
|
||||
<!-- 角色图片 见CSS部分 -->
|
||||
<div class="card-image" style="background-image: url('file:///{os_path_join_file}')">
|
||||
</div>
|
||||
|
||||
<div class="frame-top"></div>
|
||||
<div class="frame-right"></div>
|
||||
|
||||
<div class="blur-background"></div>
|
||||
<div class="card-header">
|
||||
<!-- 部落 开始 -->
|
||||
<div class="clan">{clan}</div>
|
||||
<!-- 部落 结束 -->
|
||||
|
||||
<!-- 调节血量 开始 -->
|
||||
<div class="blood"></div>
|
||||
<div class="blood"></div>
|
||||
<div class="blood"></div>
|
||||
<!-- 调节血量 结束 -->
|
||||
</div>
|
||||
|
||||
<!-- 角色描述 开始 -->
|
||||
<div class="profile-section">
|
||||
<div class="nickname">
|
||||
<b>{nickname}</b>
|
||||
</div>
|
||||
<div class="name">
|
||||
{name}
|
||||
</div>
|
||||
</div>
|
||||
<!-- 角色描述 结束 -->
|
||||
|
||||
<!-- 技能描述 开始 -->
|
||||
<div class="skill-section">
|
||||
<div class="skill-block">
|
||||
<div class="skill-title-content">
|
||||
<b>{title1}</b>
|
||||
</div>
|
||||
<div class="skill-description-content">
|
||||
<skill-description>
|
||||
{description1}
|
||||
</skill-description>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 技能描述 结束 -->
|
||||
</div>
|
||||
+137
@@ -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"
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
html2image
|
||||
Reference in New Issue
Block a user