Empty Latent Resolution
Two nodes and two wires, collapsed into one
- preview
- latent
- width
- height
The stock way to pick a canvas size is slightly silly. Resolution Selector takes an aspect ratio and a megapixel target and hands you a width and a height. Then you drag two wires into Empty Latent Image so it can turn those numbers back into a latent. Two nodes, two wires, to do one thing.
This node does both. Pick a ratio, give it megapixels, get a latent out - and it still gives you width and height as integers, so anything downstream that needs the pixel numbers doesn't have to hang a second measuring node off the graph.
How it actually computes the size
Because "does it match the official nodes" is the only question that matters if you're swapping it into an existing workflow, here's the arithmetic, read from the source:
total_pixels = megapixels * 1024 * 1024
scale = sqrt(total_pixels / (w_ratio * h_ratio))
width = round(w_ratio * scale / multiple) * multiple
height = round(h_ratio * scale / multiple) * multiple
# then both are floored to a multiple of 8
Same sqrt scaling as the core Resolution Selector, same rounding to multiple, with one extra step at the end: both sides are floored to a multiple of 8. That step exists because a latent is stored at 1/8 scale. If the pixel number isn't a multiple of 8, the latent quietly drops the partial row or column - the node reports 1215 and the image comes out 1208. Flooring first means the width and height it hands you are the pixel range the latent genuinely covers. The latent itself is built exactly like core Empty Latent Image: 4 channels, the same intermediate device and dtype, and a declared downscale ratio of 8.
That's why the author's 128-parameter test matrix lines up with the core nodes step for step. Swap the two old nodes out for this one and your renders keep their exact dimensions.
The inputs
aspect_ratio - eight presets, written the way a photographer says them rather than the way a spreadsheet does: Square, Portrait Photo (2:3), Photo (3:2), Portrait Standard (3:4), Standard (4:3), Portrait Widescreen (9:16), Widescreen (16:9), Ultrawide (21:9). Anything labelled Portrait is vertical; the rest are horizontal.
megapixels - total pixels, 0.1 to 16, default 1.0. Roughly 1024×1024 at 1:1. The shape comes from the ratio and the size comes from here, so 1.0 MP at 3:4 lands at 888×1184 and 2.0 MP at 3:4 lands at 1256×1672 - the ratio holds, only the area changes.
batch_size - how many empties at once, 1 to 4096.
multiple - the alignment step, 8 to 128, default 8, in the advanced section. Leave it at 8 for anything that downsamples by 8, which is most things. 16, 32 and 64 exist because newer architectures like cleaner grids, and setting it higher is harmless for models that don't care.
There's also an optional preview input - a live resolution box that draws the shape as you drag the ratio and megapixels. It reads those three controls and never gets submitted with the prompt.
The outputs
latent goes into KSampler's latent_image. width and height are plain INTs and they feed anything that thinks in pixels: a resize, a math node computing a scale factor, a filename template, a mask generator. That second use is the quiet win - it's the same argument as the pack's "Image or Latent Size" node, except here the numbers come free with the latent you already needed.
Installing it
Manager → Install Custom Nodes → ComfyUI-QG-tools. If the registry listing isn't live yet, clone it:
cd ComfyUI/custom_nodes
git clone https://github.com/live1617/ComfyUI-QG-tools
Restart the whole app, not the browser tab, and confirm the banner:
QG-tools v0.9.7 | 38 nodes loaded | 8 categories
Nothing to install beyond that - requirements.txt in this pack is comments only, no pip packages and no model downloads. It sits at QG-tools/Image.
Where people get burned
"Why is my 1920×1080 not 1920×1080?" Because 1080 isn't a multiple of 8 in latent terms, and ComfyUI will not let you store a latent on a fractional grid. This confuses people badly enough to start threads asking why they got 960×536 instead of the size they typed. Here you don't type pixels at all - you get the nearest sensible size for the ratio you asked for, and the width output is the truth. Read it if you care.
The latent is 4-channel, full stop. Same limitation as the core empty latent. Flux, SD3 and most video models want 16 channels, and those need their own dedicated node - this one won't feed them, and pretending otherwise produces a shape error rather than a wrong image.
You may not see the preview box at all. The live resolution preview only draws under the Nodes 2.0 (Vue) renderer. On the classic canvas it isn't there, exactly like core's own resolver. That's a frontend thing, not a broken install.
Megapixels is area, not width. Going from 1.0 to 2.0 doesn't double the width, it doubles the pixel count - each side grows by about 1.41×. If you were hoping to double a linear dimension, you want 4.0 MP.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| aspect_ratio | COMBO | 1:1 (Square) | Aspect ratio of the result. Portrait entries are vertical, the rest are horizontal. |
| megapixels | FLOAT | 1.00.1–16 | Target total pixels in megapixels. 1.0 MP is about 1024x1024 at 1:1. |
| batch_size | INT | 11–4096 | How many empty latents to produce at once. |
| multiple | INT | 88–128 | Round both sides to this multiple before aligning them to the latent grid. 8 matches the 8x downscale; 16 / 32 / 64 suit newer models. |
| previewopt | RESOLUTION_PREVIEW | Live preview of the shape these settings produce. It reads the three controls above. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| latent | LATENT | Empty latent, ready for a sampler. |
| width | INT | Final width in pixels - the range the latent actually covers. |
| height | INT | Final height in pixels - the range the latent actually covers. |