Nodes/comfyui-superside-nodes/Superside Crop to Size (anchored)
ComfyUI Node

Superside Crop to Size (anchored)

5 — This Node Cuts It Out of 3:4

By Superside·Created 3 months ago·Updated 6 days ago· 1
Superside Crop to Size (anchored)
  • image
  • mask
  • image
  • mask
  • width
  • height
◄target_width1536►
◄target_height1920►
◄anchorcenter►
◄fitcover - scale to fill, then crop►
◄resamplelanczos►

Every image model hands you a menu of sizes, not a text field. Grok Imagine's aspect_ratio list is a good example: 2:1, 20:9, 16:9, 4:3, 3:2, 1:1, 2:3, 3:4, 9:16 - and no 4:5. The model simply doesn't have that button. The local side is the same story: SDXL is trained on a fixed set of ratios, which is why the classic "my proportions look stretched" thread always ends with someone saying you generate at a trained ratio and crop afterward.

So you generate 3:4, the nearest taller ratio, and throw 6% of the height away. That's all this node does - without ever squashing the picture. Superside Crop to Size (anchored) runs entirely on your machine (no API key, no network call), and it's the last step of a pipeline rather than the first.

Cover first, then cut

The mechanism is one line of arithmetic, but it's the right line. In the default fit mode, cover - scale to fill, then crop, the node computes a single scale factor - max(target_width / source_width, target_height / source_height) - resizes the image by that one factor, and then crops the overflow. One factor means the horizontal and vertical are stretched by exactly the same amount, so nothing is ever distorted. The image always ends up covering the target, so the output is always exactly the size you asked for.

The alternative, crop only - no scaling, skips the resize and just cuts the pixel rectangle. Useful when the source is already bigger than the target and you don't want a resample softening it - but it never pads. A source smaller than the target comes out smaller, and the node logs a warning with the size it actually produced. If you want letterboxing, this isn't the node.

anchor picks which part survives. The full 3x3 grid is there - center, top-center, bottom-center, middle-left, middle-right, and the four corners - and it resolves to an offset along each axis, so top-center means zero pixels off the top and half the slack off each side. Going from 1536x2048 (3:4) to 1536x1920 (4:5) removes 128 pixels of height: top-center keeps the head, center takes 64 off the crown and 64 off the chin. Bare edge names like top and left are still accepted for anyone who saved a workflow before the grid names existed.

What you actually wire

Required: image, target_width (default 1536), target_height (default 1920), and anchor. Optional: fit, mask, and resample (lanczos by default, and lanczos is the right answer for photos).

mask is the one to know about if you're mid-composite. Feed a mask in and it's resized onto the same scaled grid as the image and cropped with the identical rectangle, so it can't drift out of alignment. But if that mask has a different shape than the image, the node resizes it to fit rather than complaining - silently stretched masks are a real hazard. Match them before you get here.

Outputs are image, mask, width, height. The two INTs are the size the node actually produced, which is not necessarily the target: in crop only mode they can be smaller. Wire them into whatever needs to know the final geometry downstream. And if you don't wire a mask in, the mask output is a full-frame black mask - all zeros, nothing selected. That's deliberate, but you can burn ten minutes wondering why a downstream composite pastes nothing.

Install

No models to download and no heavy dependencies - requirements.txt is fal-client, pillow, numpy, torch, requests, all of which a working ComfyUI already has except fal-client.

cd ComfyUI/custom_nodes
git clone https://github.com/Superside/comfyui-superside-nodes
cd comfyui-superside-nodes && pip install -r requirements.txt

Restart ComfyUI, then search "Superside" in the node menu - the whole pack registers under the Superside category. Manager can install by repo URL too. Updates are git pull origin main plus a restart - new nodes and changed widgets only load on restart - and if git pull complains about local changes, git stash → git pull → git stash pop.

Where people get burned

  • Setting the target to a ratio the source already has. Nothing happens, and that's correct - the crop window has no slack, so the anchor is a no-op. Don't go hunting for a bug.
  • Expecting the anchor to reposition the subject. It picks which edge of the frame is sacrificed, not where the face is. A portrait where the head is already near the bottom will lose the head with top-center; that's a framing problem upstream, not here.
  • Using cover on a small source. Cover upscales when it has to, so a 512px reference blown up to 1536x1920 looks exactly as soft as you'd expect. Crop first, upscale later if you care.
  • Assuming crop only means "crop to fit." A source smaller than the target comes out smaller, and the log warning is the tell.

Same arithmetic powers the region-crop pattern - cut the area, edit it, stitch it back - this node just handles the delivery format at the end.

CategorySuperside

Inputs (7)

NameTypeDefaultDescription
imageIMAGE—
target_widthINT15361–16384Output width in pixels.
target_heightINT19201–16384Output height in pixels. 1536x1920 is 4:5, the format Grok Imagine cannot generate natively.
anchorCOMBOcenterWhich part of the image is kept. 'top' keeps the head in a portrait; 'center' cuts equally from both sides.
fitoptCOMBOcover - scale to fill, then crop'cover' scales by a single factor until the image covers the target, then crops - the output is always exactly the target size and never distorted. 'crop only' cuts the pixel rectangle as-is and never scales, so a source smaller than the target comes out smaller.
maskoptMASKOptional mask cropped with the exact same geometry, so it stays aligned with the image.
resampleoptCOMBOlanczosResampling filter used by 'cover'. Lanczos is sharpest for photos.

Outputs (4)

NameTypeDescription
imageIMAGE—
maskMASK—
widthINT—
heightINT—