Nodes/EsesImageResize/Eses Image Resize
ComfyUI Node

Eses Image Resize

One node for every resizing job, mask included

By quasiblob·Created about a year ago·Updated 11 months ago· 50
Eses Image Resize
  • image
  • upscale_model
  • mask
  • ref_image
  • ref_mask
  • IMAGE
  • MASK
  • width
  • height
  • metadata
scale_mode
interpolation_method
multiplier1.00
megapixels2.00
target_width512
target_height512
ar_width16
ar_height9
keep_aspect_ratiotrue
crop_to_fitfalse
fit_to_framefalse
letterbox_color0,0,0
letterbox_mask_is_whitefalse
divisible_by8

Every ComfyUI graph ends up with a pile of resize nodes. There's the one that scales by ratio, the one that scales to megapixels, the one that letterboxes, the one that handles masks - and you can never remember which is which. Eses Image Resize is the answer to that specific annoyance: one node that does pretty much every resizing task you'll hit, plus it hands you a matching mask and the final dimensions on the side. The author's own pitch in the r/comfyui release thread nailed it: "a single node that doesn't do anything new, but does everything in a single node." It's not clever. It's convenient - after a week you'll have quietly stopped reaching for three other nodes.

Where it fits: right after VAE decode when you're prepping an image for img2img at a model-native resolution, before a ControlNet preprocessor that wants specific dimensions, or as the front end of an upscale pass. The default divisible_by of 8 points at the same thing - models like latents on clean multiples.

How it works

The mechanism is unglamorous in the best way: a thin Pillow wrapper. It takes your IMAGE tensor, converts it to a PIL image, does the resize / crop / letterbox math with Pillow's resampling filters, and converts back. That's exactly why it's so light - PyTorch, Pillow, and numpy, all of which ComfyUI already ships. No model files, no downloads, no API keys.

The one non-trivial piece is the optional upscale_model input. Wire one in and, if the target is bigger than your source, the node runs the model iteratively via ComfyUI's tiled_scale (512px tiles, halving automatically if you run out of VRAM), stopping just before it would overshoot the target and finishing with an interpolation pass to the exact size. Without a model it just interpolates, which is fine for most things.

The mask output deserves a shout-out. Lots of resize nodes drop the mask on the floor, which bites you later when you're feeding a resized image+mask pair into inpaint or compositing. Here the MASK output is always populated: a connected mask gets resized with the image (nearest-neighbor), and if you didn't connect one you get a black mask of the new dimensions.

The inputs that actually matter

scale_mode is the boss of this node. Six modes: multiplier (0.01–100x), megapixels (target total pixel count), megapixels_with_ar (target megapixels at a specific aspect ratio via ar_width/ar_height, e.g. 16:9), target_width, target_height, and both_dimensions. Keep an eye on keep_aspect_ratio - in the width/height modes it's on by default, and flipping it off lets the image distort to hit the target.

The other two you'll actually touch:

  • crop_to_fit vs fit_to_frame - leave both off and a mismatched aspect ratio just distorts; crop_to_fit fills the target frame and crops the excess from the center (no distortion), while fit_to_frame letterboxes instead. The bars take letterbox_color (hex like 000000 or 255,0,0), and letterbox_mask_is_white decides whether the padded area reads as active or inactive in the mask.
  • divisible_by (default 8) - rounds final dimensions to a multiple; set to 0 to disable.

And ref_image / ref_mask are a nice touch: connect an image and the node just uses its dimensions as the target - a built-in replacement for plumbing a "get size" node. Added within a day of someone asking for it in the release thread.

Outputs are IMAGE, MASK, width, height, and a metadata JSON string documenting what it did. Those width/height INTs are handy to wire into other nodes without a separate size node.

Installing

Easiest is ComfyUI Manager - search "EsesImageResize" and install. Or the manual route:

cd ComfyUI/custom_nodes
git clone https://github.com/quasiblob/ComfyUI-EsesImageResize

Restart ComfyUI and it shows up under "Eses Nodes/Image". No requirements.txt to babysit, nothing to download - that's the selling point.

Where people trip up

The most common confusion is baked into the design. keep_aspect_ratio and crop_to_fit look contradictory, but they're not: content never distorts by default, and crop_to_fit is how you hit a target aspect ratio. Set megapixels_with_ar to 3:4 with crop_to_fit on, and you get a 3:4 canvas with the original content undistorted inside it. That exact exchange happened in the node's release thread, so you're not alone if it took you a minute.

Two things the docs don't lead with: it processes only the first image in a batch (with a warning if you feed it more), and if your mask's dimensions don't match the image it silently resizes the mask to match. Also worth knowing: the default interpolation is area, which is great for downscaling but not the crispiest for upscaling - switch to lanczos or bicubic when you're going bigger. And the pack ships under a custom "My ComfyUI Nodes" license: free to use, but no rebranding and no redistributing modifications. Fine for personal use.

It's a small, niche tool - almost no search traffic, updated every few months by someone who built it for themselves. But it's honest work: no bloat, one job, done well, with a mask in hand at the end.

CategoryEses Nodes/Image

Inputs (19)

NameTypeDefaultDescription
imageIMAGE
scale_modeCOMBO6 options: multiplier, megapixels, target_width, target_height, both_dimensions, megapixels_with_ar
interpolation_methodCOMBO5 options: area, bilinear, bicubic, lanczos, nearest-neighbor
upscale_modeloptUPSCALE_MODEL
maskoptMASK
ref_imageoptIMAGEIf connected, use this image's dimensions as the target width and height.
ref_maskoptMASKIf connected, use this mask's dimensions as the target. Overridden by Reference Image.
multiplieroptFLOAT1.000.01–100Multiplies original dimensions by this factor (Scale Mode: ratio)
megapixelsoptFLOAT2.000.01–100Sets target total pixels in megapixels (Scale Mode: megapixels/megapixels_with_ar)
target_widthoptINT5128–8192Target width in pixels (Scale Mode: target_width/both_dimensions)
target_heightoptINT5128–8192Target height in pixels (Scale Mode: target_height/both_dimensions)
ar_widthoptINT161–4096Aspect ratio width component (Scale Mode: megapixels_with_ar)
ar_heightoptINT91–4096Aspect ratio height component (Scale Mode: megapixels_with_ar)
keep_aspect_ratiooptBOOLEANtrueIf true, preserves original aspect ratio when using target_width/height modes (otherwise may distort)
crop_to_fitoptBOOLEANfalseScales and crops the image to fill the target dimensions (no letterboxing). Takes priority over 'Fit to Frame'.
fit_to_frameoptBOOLEANfalseScales the image to fit entirely within the target dimensions, adding colored bars (letterboxing). Overridden by 'Crop to Fit'.
letterbox_coloroptSTRING0,0,0Color for letterboxing/padding (Hex: RRGGBB, RRGGBBAA; or RGB/RGBA: 255,255,255,255). Default: Black.
letterbox_mask_is_whiteoptBOOLEANfalseIf 'Fit to Frame' is active, sets the padded area in the output mask to white (255); otherwise, it's black (0).
divisible_byoptINT80–64Rounds final dimensions to be divisible by this number. Set to 0 to disable.

Outputs (5)

NameTypeDescription
IMAGEIMAGE
MASKMASK
widthINT
heightINT
metadataSTRING