文字叠加图像
Draw text into the pixels — and get a text-shaped mask out
- image
- color_rgb
- IMAGE
- MASK
Diffusion models are famously bad at text. Even when the model can spell, kerning it correctly and placing it exactly where you want is a losing game - which is why the sane workflow for anything with real typography in it is to generate the image clean and composite the type afterwards. 文字叠加图像 (QG_TextOverlayImage) is that composite step, living inside the graph instead of in an editor.
It draws a string onto an image with a real system font, at a real size, in a real colour. And it hands you a second output that most text tools don't: a mask of exactly where the letters are.
How it works
The interesting design decision is positioning. x and y are the centre of the text block, not the top-left corner. So "put the title in the middle of the frame" is the natural input rather than something you work out from bounding boxes. It also means the layout doesn't shift when the string gets longer - it grows outward from the same anchor.
layout is horizontal or vertical. Horizontal wraps by the newlines in your text. Vertical splits every character onto its own line, which is the correct way to typeset a vertical Japanese or Chinese title and a surprisingly fun way to typeset an English one badly.
Fonts come from the operating system's font directories - C:\Windows\Fonts on Windows, /System/Library/Fonts and ~/Library/Fonts on macOS, /usr/share/fonts and ~/.fonts on Linux - filtered to .ttf and .otf. The list is built from file names, so what you pick is the font file, not its display name. font_size is in pixels and goes up to 1024, which you'll need: a readable caption on a 2048px render wants a large number, and people consistently under-guess it by a factor of three on their first try.
Colour is color_name, one of six built-ins, or the optional color_rgb wildcard taking a [R, G, B] triple at 0–255 or 0–1. The wildcard wins when connected.
The mask output is white where the glyphs are, black everywhere else. That's the piece that makes this more than a paste node - you can feed it into an inpaint to re-render behind the type, use it as a colour-restriction region, or composite with it later. Batches draw the same text on every frame, which is right for video and wrong if you wanted per-frame captions; for that, run it per image or split the batch first.
Inputs and outputs
image(required, IMAGE) - the picture.text(required, multiline STRING) - newlines preserved.font(required, enum) - the installed fonts it found.font_size(required, INT, 1–1024, default 128).color_name(required, enum) /color_rgb(optional, wildcard).layout(required, enum: 横向 / 纵向).x,y(required, INT, −8192 to 16384) - centre point.- Outputs:
IMAGE(composited) andMASK(text shape, white = glyph).
Send the image to SaveImage or a 图像对比 to check placement at full size; send the mask wherever you need a text-shaped region.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/live1617/ComfyUI-QG-tools
Full restart; the console prints [QG-tools] v0.9.2 加载完成 | 节点数 24. Manager search ComfyUI-QG-Tools where the registry listing is live. No pip installs - the pack's requirements file is comments only, and this node uses PIL, which ComfyUI already ships.
Ported from ComfyUI_Muye (MIT). Search text overlay, draw text, caption or 文字叠加.
Where people get burned
No CJK glyphs. Pick a Latin-only font and your Chinese renders as empty boxes - that's PIL faithfully reporting a missing glyph, not a node bug. Install a font with the coverage you need (Noto Sans SC and friends; the pack's default is that family when it's present) and restart so the font list picks it up.
Font list looks stale after installing a font. The directories are resolved once when the module loads. Drop a new TTF in and restart ComfyUI, then the choice appears.
Font size in pixels means size relative to the canvas. The same 128 renders tiny on a 4K image and enormous on a 512 thumbnail. If you're templating one overlay across two resolutions, scale font_size with the image size - which is what 图像或 Latent 尺寸's numbers are for.
Hard-edged type. This is PIL text rendering: crisp pixels, no anti-aliased beauty filtering, no drop shadow. For clean graphic type that's ideal. For type that should feel in the photo you'll be compositing separately with blending.
Inputs (9)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | 底图(批次时每一帧都画同样的字) | |
| text | STRING | 要画的文字;换行会被保留,纵向排版时逐字换行 | |
| font | COMBO | Arial | 系统字体(读的是操作系统字体目录) |
| font_size | INT | 1281–1024 | 字号(像素) |
| color_name | COMBO | 白 | 文字颜色;接了「自定义 RGB」时以它为准 |
| layout | COMBO | 横向 | 横向逐行排;纵向把每个字拆成一行 |
| x | INT | 384-8192–16384 | 文字中心点的横坐标(像素) |
| y | INT | 512-8192–16384 | 文字中心点的纵坐标(像素) |
| color_rgbopt | * | 可选自定义颜色:接 [R, G, B] 三元组(0-255 或 0-1),接了就不看上面的内置颜色 |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | 画好字的图像。 |
| MASK | MASK | 文字形状的遮罩(白=有字,黑=空白)。 |