Nodes/m9-prompts-comfyui/CalcScaleFactor [m9]
ComfyUI Node

CalcScaleFactor [m9]

Stop guessing upscale factors, target megapixels instead

By MarcusNyne·Created 3 years ago·Updated 16 days ago· 2
CalcScaleFactor [m9]
  • image
  • scale_factor
  • width
  • height
◄megapixels1.00►
◄width—►
◄height—►

The problem it solves

Upscale nodes want a number. Upscale Image By wants a multiplier, Upscale Image wants exact pixel dimensions, and neither of them knows what size your image actually is right now. So you do what everyone does: you type 2.0, run it, and hope.

That's a bad deal when the input size is not something you chose. A face crop from a detector is whatever shape the bounding box was - 431×688 on one image, 512×702 on the next. Hit that with a flat 2× and you get a batch of crops that are all different sizes, some of them 2 megapixels, some of them 3.5. What you actually wanted was "about 1.2 megapixels, please."

That's the entire job of CalcScaleFactor [m9]. It reads a size, does the arithmetic, and hands you a scale factor and a target size. It touches no pixels. There is no image output on this node - it's a calculator with wires on it.

The math, and why your number is never exact

Given source dimensions and a megapixel target, it computes sqrt(target_pixels / (width × height)), applies that to the width, and snaps the result to the nearest multiple of 32. Then it derives the factor from that snapped width, so scaling by the returned factor lands the width exactly on the returned width.

The catch: one uniform factor can't put both sides on a 32-grid for most aspect ratios, so the grid wins over the megapixel target. A 1920×1080 image at megapixels: 1.0 comes back as factor 0.7, size 1344×768 - that's 1.03 MP, not 1.00. Fine. More useful for the reverse case: set 0.35 and you get a factor that downsizes to roughly 0.35 MP, which is the trick Comfy Org's own handbook recommends before feeding a soft image to a generative restorer, since there's no detail at full resolution to recover anyway (see upscaling.md § the counterintuitive setting).

width is the side that's guaranteed. height is the multiple of 32 nearest where the factor actually puts it - never more than 16 px off. If both sides must be exact, feed the width/height outputs into a resize node instead of using scale_factor, and accept that the aspect ratio shifts by a few pixels.

Inputs and outputs that matter

Only one input is required: megapixels (FLOAT, default 1.0, range 0.01–64). Everything else is optional, and the priority is simple - connect image and its size is used, ignoring the rest; leave it off and feed width and height instead. Both of those are forceInput, so they're sockets, not typeable widgets.

Three outputs: scale_factor (FLOAT), and width / height (INT, both multiples of 32).

scale_factor is the one you'll wire most often. In the pack's own example workflow (examples/StepReplace_ScaleFactor_m9.png) it goes straight into UltimateSDUpscale's upscale_by, with megapixels set to 1.2, on a crop that's already been ratio-matched by CropToRatio [m9]. That's the canonical detail-pass shape from masking-detection-detailing.md: UltralyticsDetectorProvider finds the face, SEGSPreview hands you the region, CropToRatio [m9] squares it up, and this node works out how much to blow it up before the low-denoise re-render. The width/height outputs are for the other flavour - an exact-size Upscale Image, or an EmptyLatentImage you want to keep in sync with the crop.

There's a silent failure here, which is the annoying part. With no image and no width/height there's no size to work from at all, so you get scale_factor 1.0 and both dimensions 0, and your upscale quietly does nothing.

Install

ComfyUI Manager → search m9-prompts-comfyui, or by hand:

cd ComfyUI/custom_nodes
git clone https://github.com/MarcusNyne/m9-prompts-comfyui

Restart, and it's under image/upscaling, next to the stock scale nodes.

Worth saying plainly: there is no requirements.txt in this repo and no model downloads. The arithmetic lives in a separate module with no torch or PIL imports at all, so there's nothing to pip install and nothing that can fail on a dependency. It's about as safe an install as custom nodes get.

Where people get burned

  • Nothing connected → factor 1.0, size 0, silent no-op. Connect the image.
  • Expecting exactly your megapixel target. You get close, not exact, because 32 wins.
  • Assuming height is exact. It isn't, it's the nearest 32-multiple. Use the output sockets in a resize node if you need both sides locked.
  • Pointing it at a tiny source. A 512×512 image at megapixels: 1.0 returns factor 1.9375 and 992×992 - that's an upscale, and it's the node doing what you asked, not it being broken.

One wider note: this is a small single-author pack, and community discussion of it is roughly nil - the author's earlier bit of fame is the A1111 sd-scramble-prompts-m9 extension. Treat it as a tidy utility you'll either adopt immediately or never need.

Categoryimage/upscaling

Inputs (4)

NameTypeDefaultDescription
megapixelsFLOAT1.000.01–64—
imageoptIMAGE—
widthoptINT—
heightoptINT—

Outputs (3)

NameTypeDescription
scale_factorFLOAT—
widthINT—
heightINT—