Crop Image to Aspect Ratio
Stop hand-cropping every frame
- images
- image
- width
- height
Every serious ComfyUI workflow eventually hits the same wall: your source image is 1024×896, but the model you're feeding wants 16:9, or the video model needs a ratio it was trained on. You can reach for a Resize, but that squeezes pixels and the anatomy knows. CropToAspectRatio (from the tiny comfyui_gvf pack, shown as "Crop Image to Aspect Ratio") is the smarter default - it center-crops your image to a target aspect ratio instead of stretching it, and it does it without a single dependency or model download.
The mechanism is about as simple as it gets, which is why it's reliable. It reads the image as a [B, H, W, C] tensor and computes aspect = width / height. If that already equals your target, the image passes through untouched. If the image is too wide, it crops the width down to height × target_aspect; if it's too tall, it crops the height to width / target_aspect. Either way the slice is centered (offset = (w - new_w) // 2), so you lose an even strip off each side instead of a lump off one edge. Because it's a single tensor slice, not a loop, the whole batch crops in one go - feed it a batch of frames and they all get the same treatment.
The inputs are exactly two. images is any IMAGE tensor, batch included. target_aspect is the ratio you want, as a float with min 0.1, max 10, step 0.01 (default 0.666…). The one thing that bites everyone: this pack reads aspect as width ÷ height, so portrait ratios are less than 1 (0.6667 ≈ 2:3, 0.5625 ≈ 16:9) and landscape ratios are greater than 1 (1.5 = 3:2). That's the same convention the core models use, but it's worth saying out loud because the sibling SizeFromAspect node in this same pack uses the opposite convention. Don't copy numbers between them.
It outputs image (the cropped tensor), plus width and height as ints. Here's the trap: those two ints report the dimensions of the image you put in, not the cropped one you get out. Look at the source - it captures w, h before cropping and returns them unchanged. So if you wire width/height into an EmptyLatentImage expecting your new crop size, you'll silently get the old one. Treat those outputs as informational, or ignore them.
Install is the easy part, and it's the same for every node in this pack: ComfyUI Manager → search "comfyui_gvf" (the pack title is ComfyUI_gvf) and install, or clone it manually:
cd ComfyUI/custom_nodes
git clone https://github.com/gvfarns/comfyui_gvf
Then restart ComfyUI. There's no requirements.txt and pyproject.toml declares zero dependencies - the whole pack is a single ~200-line gvf.py. Nothing to download, nothing that can break your Python environment.
Where you'll actually want this: feeding frames to ControlNet preprocessors or video models that expect a fixed ratio, prepping mixed-size inputs for a batch, or post-cropping a generation that you ran at a native trained ratio. Pair it with the "generate at a trained ratio, then crop" workflow the community swears by for SDXL and Flux. One slider, no per-image guesswork.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | — | |
| target_aspect | FLOAT | 0.670.1–10 | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| width | INT | — |
| height | INT | — |