Nodes/ComfyUI-ResizeToCanvasSize/Resize To Canvas Size (COI)
ComfyUI Node

Resize To Canvas Size (COI)

The portrait-crop node that frames the subject, not the middle

By Carasibana·Created 5 months ago·Updated 5 months ago· 3
Resize To Canvas Size (COI)
  • image
  • mask
  • IMAGE
  • padding_mask
width512
height512
anchor_grid3,3
anchor_modemanual
scale_methodFit to Canvas short edge
fill_methodcrop
padding_fillblack
custom_color_hex#000000
noise_seed0
custom_color_hex_input

Center-cropping a portrait is a lottery. The subject is rarely dead centre, so you crop to the middle and get a canvas full of shoulder while the face stares at you from the edge. Resize To Canvas Size (COI) - the mask variant in the same pack - fixes that by making the placement target the actual subject. "COI" is Centre of Interest, and it's the whole game here.

It's the same resize engine as the base Resize To Canvas Size node: same five scale methods, same crop/stretch choice, same six padding fills, same padding_mask output. The difference is how the image gets positioned. Instead of a 3×3 anchor grid that says "keep this edge," this node takes an optional mask, computes a Centre of Interest from it, and then uses a 7×7 target grid to pick exactly where that COI lands on the canvas.

How the COI is computed

Three anchor_modes, straight from the source:

  • manual - the COI is just the image centre. If you connect no mask, or pick this mode, you're effectively using the base node with a finer grid.
  • mask_bbox_centre - the centre of the bounding box of all non-zero mask pixels. Predictable, single-subject framing.
  • mask_weighted_centre - a true weighted centroid (centre of mass). Big contiguous masked areas dominate the pull, and a few stray pixels are negligible. This is the mode for "frame everyone in the group shot."

If the mask size doesn't match the image, it's auto-resized (nearest-neighbour) to fit, so you can feed masks from any source.

The 7×7 grid maps to canvas fractions in steps of 1/6 - so the 49 dots cover every third-boundary, midpoint, and centre. Default 3,3 places the COI at canvas centre. Remember the semantics: the grid means "put the COI here."

The inputs that matter

  • mask (optional) - what drives everything. A face-detection mask via UltralyticsDetectorProviderBboxDetectorSEGSSAMDetectorCombined is the classic setup; any subject mask works.
  • anchor_grid - a plain STRING like "3,3". The clickable widget writes it, but because it's a string you can also drive it from any node that outputs col,row text. Neat automation trick.
  • anchor_mode - the three options above.
  • width / height, scale_method, fill_method, padding_fill - same meaning as the base node.

Outputs: IMAGE (RGBA) and padding_mask (1 = padding, 0 = original pixels).

The recipe that made this node exist

Face-centred portrait crop: feed in a face-detection mask, set anchor_mode: mask_bbox_centre, grid 3,3, scale_method: Fit to Canvas width. The detected face lands dead centre on the canvas no matter where it sat in the source. With two subjects, switch to mask_weighted_centre and the node finds the centre of gravity across both regions - everyone gets framed instead of whoever was luckiest.

Where it trips people up

  • No mask connected, or manual mode, and the node quietly behaves like a centre-crop. If your framing looks wrong, check the mask first - a black or empty mask gives you image-centre placement with zero warning.
  • mask_weighted_centre is biased by blob size. A big background region will yank the COI toward it. Single clean subject: use mask_bbox_centre. Multiple subjects to balance: weighted. Don't use weighted with a sloppy mask.
  • Garbage in, garbage out. The node is only as smart as the mask; a coarse detection mask produces coarse framing. This isn't a bug, it's the design.

Install is the same as the rest of the pack - ComfyUI Manager search "ComfyUI-ResizeToCanvasSize", or git clone into custom_nodes/ and restart. No extra Python packages, no model downloads. If you do a lot of portrait work at fixed canvas sizes, this is the node in the pack you'll actually reach for.

Categoryimage/transform

Inputs (12)

NameTypeDefaultDescription
imageIMAGE
widthINT5121–8192
heightINT5121–8192
anchor_gridSTRING3,3
anchor_modeCOMBOmanual3 options: manual, mask_bbox_centre, mask_weighted_centre
scale_methodCOMBOFit to Canvas short edge5 options: None – use original size, Fit to Canvas short edge, Fit to Canvas long edge, Fit to Canvas height, Fit to Canvas width
fill_methodCOMBOcrop2 options: crop, stretch
padding_fillCOMBOblack6 options: black, white, gray_50, transparent, custom, noise
custom_color_hexSTRING#000000
noise_seedINT00–18446744073709550000
maskoptMASK
custom_color_hex_inputoptSTRING

Outputs (2)

NameTypeDescription
IMAGEIMAGE
padding_maskMASK