Nodes/NO8D-controls/NO8D-image-size
ComfyUI Node

NO8D-image-size

Fix your image dimensions, and see the crop before you commit to it

By no8d·Created 4 months ago·Updated a day ago· 308
NO8D-image-size
  • image
  • crop_canvas
  • image
  • width
  • height
◄auto_outputtrue►
◄aspect_ratio1:1►
◄short_side512►
◄long_side512►
◄multiple_of8►
◄interpolationlanczos►
◄methodstretch►
◄invert_ratiofalse►
◄fill_color#000000►
◄width0►
◄height0►
◄conditionalways►
◄force_sizefalse►

Every workflow has that moment: you've got an image from somewhere - a photo, a download, a frame grabbed out of a video - and your model wants numbers that are a multiple of 64 at a ratio it was trained on. So you open a calculator, scale to 1024 on the long side, discover 683 isn't divisible by anything useful, and either round it or let the VAE complain. NO8D-image-size ends that ritual.

It's a size normaliser with three behaviours and one nice feature: instead of guessing where a ratio-locked crop should land, you drag it on the node and look at it before anything runs.

What it does to your pixels

The target box comes from two things you pick and two you mostly don't. aspect_ratio gives you original or a preset - 1:1, 1:2, 2:3, 3:4, 4:5, 9:16, 9:21 - and short_side is the dial you actually turn. long_side is the other half of that box, and although it exists on the node, the frontend hides it and recomputes it from the ratio whenever you touch short_side, so in practice you set one number and get a correctly proportioned pair. Both then snap to multiple_of (8, 16, 32 or 64), and the node reports the result through its width and height outputs.

Then method decides what happens to the image.

  • stretch resamples the whole frame into the box, no opinions. Reel a 4:3 photo into 1:1 and faces get quietly wider - usually fine, occasionally not.
  • crop cuts a ratio-locked window out of the source at whatever position and scale you set on the canvas. When the source and target ratios already match, the crop is exact: no resampling, pure slicing.
  • pad fits the whole image inside the canvas, centred and scaled to fit by default, with fill_color filling the rest - black unless you change it via the colour button in the pad editor; the widget itself is hidden. This is the right move before outpainting: "remove the sky and paint it back" beats "chop it off".

interpolation only matters when something is resampled. lanczos is the default and correct for growing or modestly shrinking an image - plain interpolation that adds pixels and invents nothing. Reach for area when you're going down hard, nearest for pixel art or when resizing masks and latents for zero blending.

One input that gets asked about and shouldn't: invert_ratio is only honoured for crop and pad. Set it on stretch and it's silently ignored, frontend and backend both - stretching into the box already decides orientation by way of the ratio. The width, height, condition and force_size fields are legacy leftovers that the frontend hides and the backend deletes on sight; load an old workflow and you may see them flicker past.

The preview trick nobody expects

The node is an output node, and what it previews is the source image at its original size - not your result. That's what auto_output is really for. Leave it on and image, width and height pass downstream normally; switch it off and all three outputs are blocked, so nothing behind the node executes at all. That turns a resize node into a "just show me what I'm feeding in" node - handy when hunting whichever node in a chain is mangling an image. When you do want output with it off, the editor's Send button pushes the processed image downstream manually, so you can eyeball a crop and then commit it without re-queueing.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/no8d/ComfyUI-NO8D-controls.git
python -m pip install -r ComfyUI-NO8D-controls/requirements.txt

ComfyUI Manager installs by searching the pack name; on Windows Portable, run pip with python_embeded\python.exe from the portable root. Restart, then hard-refresh the browser - the crop and fill canvases are JavaScript, and a stale frontend shows you a raw JSON widget instead of a draggable frame. Fair warning: requirements.txt pulls rembg[cpu] for the pack's Image Composer, so onnxruntime comes along and the download is far bigger than a resize node has any right to be.

Where people get burned

The crop preview is empty. The editor needs the source image, which only exists after the node has run once - it says so itself: "Run once to load the crop preview".

The output doesn't match the aspect ratio you typed. short_side and long_side are a pair, not a single size. Drive short_side and let the node derive the long side; set both by hand in an API workflow and you can build a box that isn't your ratio at all.

The model complains about dimensions. 8 is a safe default, but Flux-family models want multiples of 64, and SDXL's trained ratios are a fixed list (1152x896, 1216x832 and friends). Match multiple_of to the model, not the vibe.

Everything downstream is dead. You flipped auto_output off while inspecting and forgot. Blame the toggle, not your sampler.

CategoryNO8D-control

Inputs (15)

NameTypeDefaultDescription
imageIMAGE—
auto_outputBOOLEANtrue—
aspect_ratioCOMBO1:110 options: original, 原图比例, Original, 1:1, 1:2, 2:3, +4
short_sideINT5128–16384—
long_sideINT5128–16384—
multiple_ofCOMBO84 options: 8, 16, 32, 64
interpolationCOMBOlanczos18 options: nearest, bilinear, bicubic, area, nearest-exact, lanczos, +12
methodCOMBOstretch15 options: stretch, crop, pad, 拉伸, 裁切, 填充, +9
invert_ratioBOOLEANfalse—
crop_canvasNO8D_IMAGE_SIZE_CANVAS{"crop":{"x":0.5,"y":0.5,"scale":1},"fill":{"x":0.5,"y":0.5,"scale":1}}—
fill_colorSTRING#000000—
widthINT00–16384—
heightINT00–16384—
conditionCOMBOalways15 options: always, downscale if bigger, upscale if smaller, if bigger area, if smaller area, 总是, +9
force_sizeBOOLEANfalse—

Outputs (3)

NameTypeDescription
imageIMAGE—
widthINT—
heightINT—