ImageMask_Align
Reach the divisible-by-N size without squashing your pixels
- image
- mask
- image
- mask
- align_data
You have a 1000x1400 crop and the model insists on multiples of 16. Three choices: resize it and watch the proportions bend, crop it and lose the edges, or pad it. ImageMask_Align is the third option, done properly. It grows the canvas outward to the next multiple, leaves every original pixel exactly where it was, and hands you a receipt so you can undo the padding later.
That receipt is the whole point. Very few models agree on a number. An 8x VAE (SD 1.5, SDXL) is happy with 8. Flux.1 Kontext and SD3 patchify at 2x2 before that same VAE, so they want 16. Qwen-Image and HunyuanVideo want 32. The video DiTs with 3D VAEs - Wan 2.1, CogVideoX - want 64. The node's own description is that table, which is unusually honest documentation for a utility node.
Why not just resize to 1024x1024?
Because resampling is lossy, and you knew that already. Every pixel in a scaled image becomes a weighted average of its neighbours and the geometry shifts. Survivable for a fresh generation. Not survivable when the job is keep this exact image, change one thing, because you just blurred the region you promised not to touch.
It's the same instinct as crop-and-stitch inpainting: pixels you didn't ask the model to touch shouldn't pass through a destructive step. That pattern applies the rule to VAE encode/decode. This node applies it to geometry.
How it works
Straightforward maths, which is why it's reliable. The node rounds width and height up to the next multiple of your chosen number with integer ceil, allocates a canvas that size, and copies the original in at the centre - pad offsets are (target - original) // 2 on each side. No scaling filter, no resampling, no edge extension. The new border is literal zeros.
It then stashes the original dimensions in an align_data value. Not decoration: that's how the second half of the pair, ImageMask_AlignRestore, knows what to cut back to.
Two edges worth knowing, because they're in the code and not the docs. If the image is already a multiple of the target it comes back untouched. And if your mask is a different height/width than the image, or is entirely zero, the node silently treats it as "no mask" and returns a placeholder. Silent is doing a lot of work in that sentence.
Inputs and outputs
Three things on the front, one of them disposable:
- image - the picture you want aligned.
- round_to_multiple - a dropdown:
8,16,32,64, defaulting to32. Pick the number your model actually wants. 64 is divisible by everything below it, so it's "safe", but you pay for that in black bars; for Kontext or SDXL, 16 or 8 is the cheaper correct answer. - mask (optional) - feed it your mask and it pads in the same place. Skip it if you don't have one.
Outputs are image, mask and align_data. The image goes wherever the model needs it - a VAE Encode, Kontext, a video loader. align_data goes into ImageMask_AlignRestore and nowhere else. And the mask output carries a warning: with no valid mask provided it returns a meaningless 64x64 zero tensor as a "no mask" flag. The restore node understands that convention; a composite or SetLatentNoiseMask node won't, and will quietly do something unhelpful with a wrong-shaped black mask.
Installing it
Search ComfyPanel in ComfyUI Manager (it's on the registry, publisher ginolazy) and install it. Or by hand:
cd ComfyUI/custom_nodes
git clone https://github.com/Ginolazy/ComfyPanel
cd ComfyPanel && pip install -r requirements.txt
then restart. Don't skip the pip step: the loader skips the whole image.py module - where both of these nodes live - if opencv-python or kornia aren't importable.
ComfyPanel is mostly a Photoshop UXP plugin, so the README is long on Photoshop 2025+, cloud GPU routing and a free-vs-Pro split. These nodes are plain MIT backend code in /modules/ and need none of it: no Photoshop, no license, no API key.
Common issues
The nodes don't show up at all. Check the console at startup: the loader prints [ComfyPanel] Skipping module image: missing cv2, kornia, then carries on without telling the UI anything.
Nothing runs. This node isn't an output node. Until the image output reaches a SaveImage, PreviewImage or the panel's output node, ComfyUI skips the whole branch.
Black bars bleeding into your border pixels. The padding is literal black, not mirrored or edge-extended - there's no option for that. Usually harmless, since edit models re-emit the frame and you crop the bars off afterwards. More of a risk on a heavy-denoise pass that treats the black band as real content.
One thing this won't fix. Qwen-Image-Edit's slight output misalignment wants an input that's a multiple of 112, and 112 is 16 x 7 - no setting on this dropdown produces it. That quirk is a different constraint.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| round_to_multiple | COMBO | 32 | 5 options: 8, 16, 32, 64, 112 |
| maskopt | MASK | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| mask | MASK | — |
| align_data | ALIGN_DATA | — |