图像水印
Watermarking inside the workflow, instead of exporting to Photoshop
- base_image
- watermark_image
- mask
- IMAGE
If you post generations anywhere, your options have historically been a batch action in an image editor or a node that sort of works. 图像水印 (QG_ImageWatermark) is the "sort of works" problem solved: paste one image onto another, positioned by anchor plus offset, scaled four different ways, rotatable, fadeable, maskable, and applied to every frame of a batch.
It's not glamorous and it's the kind of node you install for one job. But the fact that it happens inside the graph means the watermark is present in the file that gets saved, including on automated runs where nobody's opening Photoshop.
How it works
Two inputs matter: base_image (the picture) and watermark_image (the logo). The watermark gets scaled according to scale_mode:
- 不缩放 - leave it at native size. Fine if you generated it at the right dimensions.
- 等比适配 - shrink to fit inside the base image, aspect preserved. For a big logo on a small render.
- 按倍数缩放 - multiply native size by
scale_factor(0.01–16). - 按指定宽高缩放 - force
target_width×target_height, ignoring aspect. This one will squish your logo if the numbers aren't proportional; that's on purpose, sometimes you want exactly 512×64.
Then position picks one of nine anchors - 居中, 上, 下, 左, 右, and the four corners - and offset_x / offset_y nudge from there in pixels. Both default to 32, which is a sane bottom-right corner inset, and offsets can be negative (range is ±48000, so no realistic excuse to be limited).
rotation is an integer in degrees, clockwise, and the canvas expands around the watermark rather than clipping the corners - the pack notes this as a bug fix over the version it was ported from. opacity is the field to read the tooltip on: 0 is fully opaque, 100 is fully transparent. That's inverted from intuition and from most software, and it's the thing people get wrong first. A value of 25 means you're seeing three quarters of your logo.
The optional mask input is subtler than it looks. White in the mask means hide the watermark, black means show it. And the mask is resized to the watermark's dimensions, not the base image's - so it's a cutout for the logo itself, not a keep-out zone on the picture. Use it to knock out a portion of the logo (a shape you want it to sit behind, a soft fade), not to restrict where on the image the watermark lands.
Batches work the way you'd hope: base_image applies the watermark to every frame, watermark_image uses only its first frame, and the mask uses its first frame too.
Inputs and outputs
Required, in practice: base_image, watermark_image, scale_mode, position, offset_x, offset_y, rotation, opacity, plus scale_method, scale_factor, target_width, target_height for the scaling modes. Optional: mask. Output: IMAGE, same frame count as your base.
Wire the output into SaveImage and you're done, or into a 图像对比 node first to check the placement at full size rather than squinting at a node preview.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/live1617/ComfyUI-QG-tools
Full restart; console prints [QG-tools] v0.9.2 加载完成 | 节点数 24. Manager search for ComfyUI-QG-Tools covers the Registry case. Nothing to pip install - the requirements file is deliberately all comments so Manager skips pip entirely.
Ported from ComfyUI_Muye (MIT), searchable as watermark, logo, stamp or 水印.
Where people get burned
Opacity inverted, again. 0 = solid. If your watermark seems to be missing, check whether it's sitting at 50 thinking you asked for half strength - you did, you're getting half. If it's invisible, it's near 100.
The watermark has to be an IMAGE, not a path. There's no file picker here; feed it through a LoadImage. A common build is LoadImage → watermark → done, and it's worth grouping that pair so you don't accidentally delete the loader.
Transparent PNGs used to be broken. The pack's changelog calls this out explicitly: upstream's paste ignored the alpha channel, so a logo with transparency got pasted as an opaque rectangle. It's fixed here, and rotated corners now composite correctly. If you're comparing against the original node in another pack, that's the difference.
Rotation and offsets interact. Rotation happens before the anchor placement, so a 45° rotated logo whose bounding box is now bigger may poke outside the base image. The canvas expands to keep the watermark whole, not to keep it on the picture - offset it inward or scale it down.
Inputs (13)
| Name | Type | Default | Description |
|---|---|---|---|
| base_image | IMAGE | 底图(可以是批次,水印会贴到每一帧上) | |
| watermark_image | IMAGE | 水印图;接批次时只用第一帧 | |
| scale_mode | COMBO | 不缩放 | 不缩放:保持原尺寸;等比适配:缩到能放进底图;按倍数缩放:原尺寸乘以倍数;按指定宽高缩放:直接用下面填的宽高 |
| scale_method | COMBO | bilinear | 缩放水印图用的重采样方法(不缩放时无效果) |
| scale_factor | FLOAT | 1.00.01–16 | 缩放模式选「按倍数缩放」时生效 |
| target_width | INT | 5120–16384 | 缩放模式选「按指定宽高缩放」时的宽度 |
| target_height | INT | 5120–16384 | 缩放模式选「按指定宽高缩放」时的高度 |
| position | COMBO | 右下 | 水印在底图上的锚点位置 |
| offset_x | INT | 32-48000–48000 | 在锚点基础上的横向像素偏移(正数往右) |
| offset_y | INT | 32-48000–48000 | 在锚点基础上的纵向像素偏移(正数往下) |
| rotation | INT | 0-180–180 | 旋转角度(顺时针为正),画布会随旋转扩大 |
| opacity | FLOAT | 00–100 | 0 = 完全不透明,100 = 完全透明 |
| maskopt | MASK | 可选遮罩:白色区域不透出水印,黑色区域正常显示 |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | 贴好水印的图像(与底图同样张数)。 |