206 lines
6.8 KiB
Markdown
206 lines
6.8 KiB
Markdown
# Documentation
|
|
- Class name: SimpleTextImage
|
|
- Category: 😺dzNodes/LayerUtility
|
|
- Output node: False
|
|
- Repo Ref: https://github.com/chflame163/ComfyUI_LayerStyle
|
|
|
|
从文字生成简单排版的图片以及遮罩。这个节点参考了[ZHO-ZHO-ZHO/ComfyUI-Text_Image-Composite](https://github.com/ZHO-ZHO-ZHO/ComfyUI-Text_Image-Composite)的部分功能和代码,感谢原作者。
|
|
|
|
*仅限输入image和mask, 如果强制接入其他类型输入,将导致节点错误。 **font文件夹在resource_dir.ini中定义,这个文件位于插件根目录下, 默认名字是resource_dir.ini.example, 初次使用这个文件需将文件后缀改为.ini。用文本编辑软件打开,找到“FONT_dir=”开头的这一行,编辑“=”之后为自定义文件夹路径名。这个文件夹里面所有的.ttf和.otf文件将在ComfyUI初始化时被收集并显示在节点的列表中。如果ini中设定的文件夹无效,将启用插件自带的font文件夹。
|
|
|
|
# Input types
|
|
|
|
## Required
|
|
|
|
- text
|
|
- 文本。
|
|
- Comfy dtype: STRING
|
|
- Python dtype: str
|
|
|
|
- font_file
|
|
- 字体文件。
|
|
- Comfy dtype: FONT_LIST
|
|
- Python dtype: str
|
|
|
|
- align
|
|
- 对齐方式。
|
|
- Comfy dtype: STRING_ONEOF
|
|
- Python dtype: str
|
|
|
|
- char_per_line
|
|
- 每行字符数。
|
|
- Comfy dtype: INT
|
|
- Python dtype: int
|
|
|
|
- leading
|
|
- 行距。
|
|
- Comfy dtype: INT
|
|
- Python dtype: int
|
|
|
|
- font_size
|
|
- 字体大小。
|
|
- Comfy dtype: INT
|
|
- Python dtype: int
|
|
|
|
- text_color
|
|
- 文本颜色。
|
|
- Comfy dtype: STRING
|
|
- Python dtype: str
|
|
|
|
- stroke_width
|
|
- 描边宽度。
|
|
- Comfy dtype: INT
|
|
- Python dtype: int
|
|
|
|
- stroke_color
|
|
- 描边颜色。
|
|
- Comfy dtype: STRING
|
|
- Python dtype: str
|
|
|
|
- x_offset
|
|
- x偏移量。
|
|
- Comfy dtype: INT
|
|
- Python dtype: int
|
|
|
|
- y_offset
|
|
- y偏移量。
|
|
- Comfy dtype: INT
|
|
- Python dtype: int
|
|
|
|
- width
|
|
- 画面的宽度。如果有size_as输入,此设置将被忽略。
|
|
- Comfy dtype: INT
|
|
- Python dtype: int
|
|
|
|
- height
|
|
- 画面的高度。如果有size_as输入,此设置将被忽略。
|
|
- Comfy dtype: INT
|
|
- Python dtype: int
|
|
|
|
## Optional
|
|
|
|
- size_as
|
|
- 此处输入图像或遮罩,将按照其尺寸生成输出图像和遮罩。注意,此输入优先级高于下面的width和height。
|
|
- Comfy dtype: ANY
|
|
- Python dtype: torch.Tensor
|
|
|
|
# Output types
|
|
|
|
- image
|
|
- 图片。
|
|
- Comfy dtype: IMAGE
|
|
- Python dtype: torch.Tensor
|
|
|
|
- mask
|
|
- 蒙版。
|
|
- Comfy dtype: MASK
|
|
- Python dtype: torch.Tensor
|
|
|
|
# Usage tips
|
|
- Infra type: CPU
|
|
|
|
# Source code
|
|
|
|
```python
|
|
class SimpleTextImage:
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
@classmethod
|
|
def INPUT_TYPES(self):
|
|
|
|
return {
|
|
"required": {
|
|
"text": ("STRING",{"default": "text", "multiline": True},
|
|
),
|
|
"font_file": (FONT_LIST,),
|
|
"align": (["center", "left", "right"],),
|
|
"char_per_line": ("INT", {"default": 80, "min": 1, "max": 8096, "step": 1},),
|
|
"leading": ("INT",{"default": 8, "min": 0, "max": 8096, "step": 1},),
|
|
"font_size": ("INT",{"default": 72, "min": 1, "max": 2500, "step": 1},),
|
|
"text_color": ("STRING", {"default": "#FFFFFF"},),
|
|
"stroke_width": ("INT",{"default": 0, "min": 0, "max": 8096, "step": 1},),
|
|
"stroke_color": ("STRING",{"default": "#FF8000"},),
|
|
"x_offset": ("INT", {"default": 0, "min": 0, "max": 8096, "step": 1},),
|
|
"y_offset": ("INT", {"default": 0, "min": 0, "max": 8096, "step": 1},),
|
|
"width": ("INT", {"default": 512, "min": 1, "max": 8096, "step": 1},),
|
|
"height": ("INT", {"default": 512, "min": 1, "max": 8096, "step": 1},),
|
|
},
|
|
"optional": {
|
|
"size_as": (any, {}),
|
|
}
|
|
}
|
|
|
|
RETURN_TYPES = ("IMAGE", "MASK",)
|
|
RETURN_NAMES = ("image", "mask",)
|
|
FUNCTION = 'simple_text_image'
|
|
CATEGORY = '😺dzNodes/LayerUtility'
|
|
|
|
def simple_text_image(self, text, font_file, align, char_per_line,
|
|
leading, font_size, text_color,
|
|
stroke_width, stroke_color, x_offset, y_offset,
|
|
width, height, size_as=None
|
|
):
|
|
|
|
ret_images = []
|
|
ret_masks = []
|
|
if size_as is not None:
|
|
if size_as.dim() == 2:
|
|
size_as_image = torch.unsqueeze(mask, 0)
|
|
if size_as.shape[0] > 0:
|
|
size_as_image = torch.unsqueeze(size_as[0], 0)
|
|
else:
|
|
size_as_image = copy.deepcopy(size_as)
|
|
width, height = tensor2pil(size_as_image).size
|
|
font_path = FONT_DICT.get(font_file)
|
|
(_, top, _, _) = ImageFont.truetype(font=font_path, size=font_size, encoding='unic').getbbox(text)
|
|
font = cast(ImageFont.FreeTypeFont, ImageFont.truetype(font_path, font_size))
|
|
if char_per_line == 0:
|
|
char_per_line = int(width / font_size)
|
|
paragraphs = text.split('\n')
|
|
|
|
img_height = height # line_height * len(lines)
|
|
img_width = width # max(font.getsize(line)[0] for line in lines)
|
|
|
|
img = Image.new("RGBA", size=(img_width, img_height), color=(0, 0, 0, 0))
|
|
draw = ImageDraw.Draw(img)
|
|
y_text = y_offset + stroke_width
|
|
for paragraph in paragraphs:
|
|
lines = textwrap.wrap(paragraph, width=char_per_line, expand_tabs=False,
|
|
replace_whitespace=False, drop_whitespace=False)
|
|
for line in lines:
|
|
width = font.getbbox(line)[2] - font.getbbox(line)[0]
|
|
height = font.getbbox(line)[3] - font.getbbox(line)[1]
|
|
# 根据 align 参数重新计算 x 坐标
|
|
if align == "left":
|
|
x_text = x_offset
|
|
elif align == "center":
|
|
x_text = (img_width - width) // 2
|
|
elif align == "right":
|
|
x_text = img_width - width - x_offset
|
|
else:
|
|
x_text = x_offset # 默认为左对齐
|
|
|
|
draw.text(
|
|
xy=(x_text, y_text),
|
|
text=line,
|
|
fill=text_color,
|
|
font=font,
|
|
stroke_width=stroke_width,
|
|
stroke_fill=stroke_color,
|
|
)
|
|
y_text += height + leading
|
|
y_text += leading * 2
|
|
|
|
if size_as is not None:
|
|
for i in size_as:
|
|
ret_images.append(pil2tensor(img))
|
|
ret_masks.append(image2mask(img.split()[3]))
|
|
else:
|
|
ret_images.append(pil2tensor(img))
|
|
ret_masks.append(image2mask(img.split()[3]))
|
|
|
|
log(f"{NODE_NAME} Processed.", message_type='finish')
|
|
return (torch.cat(ret_images, dim=0),torch.cat(ret_masks, dim=0),)
|
|
``` |