Image Minimum Area
Upscale to a floor, never below it, and branch on whether it fired
- image
- mask
- image
- mask
- resize_bool
What it's for
A lot of models have a resolution floor and are rude about it. Small img2img crops come back as mush because the latent has no budget. Edit endpoints and hosted APIs reject or quietly degrade inputs below roughly a megapixel. And the KB's detailing doc makes the same point from the other end: give a region its own pass at a resolution the model can actually resolve detail at, or you've wasted the pass.
Image Minimum Area is the deterministic version of that rule. Tell it a reference square of N, and it upscales the image until its area reaches N² - then stops. If your image is already at or above the floor, it passes the pixels through untouched. That asymmetry is the point: this is not an upscaler, it's a threshold with a Lanczos filter attached.
How it works
The math is refreshingly literal. length_to_sq_area is the side of a reference square, so the target area is N² - default 1024 means "at least 1024×1024 worth of pixels", not "1024 pixels wide". If width × height already meets that, everything passes through and resize_bool comes back False.
Otherwise the scale factor is sqrt(N² / area), both sides get ceil'd, and then each dimension rounds up to a multiple of divisible_by. That last knob exists for the reason you'd guess: a VAE- or latent-friendly size. divisible_by: 8 costs you a few stray pixels of area but keeps you on a size the model doesn't pad internally.
The actual resize then runs through the same fit engine as the pack's Image Resize Universal node, which matters if you've used those nodes - same sampler list (nearest, bilinear, lanczos, bicubic, hamming, box, default lanczos), same crop / pad / stretch behaviour. crop scales to cover and centre-crops; pad scales to fit and fills the remainder with pad_color. And because it's the same engine, an RGBA input keeps its alpha through the whole thing.
pad_color is a string, and the parser is generous: "1.0" (the default) is mid-gray scaled as a 0–1 value - i.e. white - "0.0" is black, "0.5,0.7,0.9" is 0–1 RGB, "128,192,255" is 0–255 RGB, and names, hex and single-letter shorthands (k for black, w for white) all resolve.
Inputs and outputs
image in, optional mask alongside it, and three outputs: image, mask, resize_bool.
The mask output is the nice part. Feed a mask in and it goes through the identical fit as the image, so it still lines up - that's what keeps a detailing or inpainting chain honest after a resize. Leave it disconnected and the node synthesises a matching default (white for stretch, a padded or cropped shape that matches the fit mode), so the output is always wire-able.
resize_bool is a BOOLEAN that says whether an actual upscale happened. Wire it into Any Switch Bool to take the original path when the image was already big enough, or use it in a logic chain to log which images in a batch needed help. It's a small thing that saves you from upscaling twice.
One behaviour worth internalising: the batch scales as a unit, because the decision is made from the image's dimensions. You get one resize_bool per execution, not per frame.
Install
ComfyUI Manager → search 1hewNodes, or:
cd ComfyUI/custom_nodes
git clone https://github.com/1hew/ComfyUI-1hewNodes
Restart. This node is pure PIL + torch and needs nothing exotic. (The pack's requirements.txt is heavy - ultralytics, rembg, onnxruntime, av - but those belong to its detection and video nodes; the resize and utility nodes don't touch them.) It's written against the current comfy_api.latest schema, so it wants a reasonably recent ComfyUI.
Common issues
"Nothing happened." Your image was already at or above the floor, and passing through is correct behaviour - check resize_bool. A 900×900 input is 810k pixels, just under a 1024 floor, so it will fire; a 1200×800 is 960k, also under. Do the arithmetic rather than eyeballing it.
The output got wider than you expected. divisible_by only rounds up. With divisible_by: 64 and a computed 1000-pixel side, you get 1024.
Pad color came out wrong. "1.0" is white and "0.0" is black, because the parser reads a lone value as a 0–1 gray. If you meant a 0–255 gray, write it as three components or use a name.
You want a target size, not a floor. Wrong node. Image Resize Universal in the same pack does explicit targets, ratio inference and the same fit modes; Image Minimum Area is deliberately one-directional.
Inputs (7)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| length_to_sq_area | INT | 10241–65536 | — |
| method | COMBO | lanczos | 6 options: nearest, bilinear, lanczos, bicubic, hamming, box |
| divisible_by | INT | 11–1024 | — |
| fit | COMBO | crop | 3 options: crop, pad, stretch |
| pad_color | STRING | 1.0 | — |
| maskopt | MASK | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| mask | MASK | — |
| resize_bool | BOOLEAN | — |