116 lines
8.5 KiB
Markdown
116 lines
8.5 KiB
Markdown
> "Do one thing and do it well." _— Peter H. Salus / Doug McIlroy, [core Unix principle](https://en.wikipedia.org/wiki/Unix_philosophy)_
|
|
|
|
> "Simple is better than complex." _— Zen of Python_
|
|
|
|
# `Best Resolution` ComfyUI nodes [UX/QoL]
|
|
|
|
A small modular pack — nodes for semi-automatic calculation of the best (most optimal) sampling resolution:
|
|
- ... model-agnostic — i.e., compatible with **ANY** model (from now **or** the future),
|
|
- ... accounting for upscale,
|
|
- ... and for (the essential) pixel-step.
|
|
|
|
[🔄 Updates ChangeLog](CHANGELOG.md)
|
|
|
|
> [!NOTE]
|
|
> Almost all the nodes from this pack do **nothing** with actual images on their own — they only calculate the optimal **values** for the resolution.
|
|
|
|
Read any further only if you feel you need to.
|
|
|
|
## The purpose
|
|
|
|
In case you didn't know, you can't just choose **any** arbitrary resolution for sampling. You need to ensure:
|
|
- both width and height are divisible by a latent scale factor, pre-defined by a model family _(`8` for both SD1.5 and SDXL)_ - and they **must** remain multiples of it both in initial generation **AND** after further upscales;
|
|
- the overall resolution _(aka megapixels, total pixel count)_ is as close as possible to the model's "view window" _(the resolution it was trained on)_ - so if you increase one side of the image, you need to proportionally decrease the other.
|
|
|
|
... and choosing the right resolution is your responsibility. 🤷🏻♂️
|
|
|
|
This pack lets you forget about crunching numbers and handles the calculation of optimal width/height for you, while still leaving control of the image size/proportions/orientation to you. It provides...
|
|
|
|
## 3 main nodes
|
|
|
|

|
|
|
|
### Simple
|
|
|
|
Just rounds width/height to the given step, ensuring the image **CAN** be converted to latent - both in initial generation and after some upscales.
|
|
|
|
### From Aspect-Ratio
|
|
|
|
As the name suggests, you control the resolution indirectly - by specifying the desired aspect ratio, one of the sides, and orientation (landscape/portrait).
|
|
The node detects the actual width/height to match those as close as posible.
|
|
|
|
### From Area
|
|
|
|
To my taste, **THE** way to select the optimal resolution for diffusion models.
|
|
|
|
All you need to know is a size (one side) of square images the model was trained on _(512 for SD1.5, 1024 for SDXL)_. The node handles the rest to meet all the restrictions:
|
|
- match the total resolution (i.e., image area, number of pixels) as close to the training one as possible,
|
|
- ... while still respecting aspect ratio, image orientation and step size.
|
|
|
|
## Helper node - `Upscale Image By (with Model)`
|
|
|
|

|
|
|
|
This is the **only** node in the pack which does more than some resolution calculation, and actually scales an image. But it's nothing more than a wrapper over the built-in `Upscale Image (using Model)` and `Upscale Image By` nodes used in sequence.
|
|
|
|
Like the built-in `Upscale Image (using Model)` node, this one scales with a specialized model, **but also** does it to a desired upscale factor, like `Upscale Image By` does. This factor should be below the model's native one. And, depending on the value you set this factor to, you get different results.
|
|
|
|
For a `x4` model, you could expect the following:
|
|
|
|
| Target `scale` factor | Resulting image |
|
|
|-----------------------|------------------------------------------------------------------------------------------------------------------------------------|
|
|
| Below `x0.5` | ❔ Perfect, crisp, but... 🤔 the model-upscale won't even be performed. Why using this node at all and not just `Upscale Image By`? |
|
|
| `x0.5+` - `x1.0` | 👍🏻 Perfect, downscale-only, but the result might be slightly different (and crisper) from using just `Upscale Image By`. |
|
|
| `x1.0+` - `x3.5` | 👍🏻 **Perfect. The upscale range this node was made for.** |
|
|
| `x3.5+` - `x4.0` | ⚠️ **Image starts getting blurry, but still better than just using `Upscale Image By`.** |
|
|
| `x4.0` exactly | 👍🏻 Perfect. Just the same result as from `Upscale Image (using Model)`. Second scaling isn't even performed. |
|
|
| `x4.0+` | ‼️ **VERY** blurry |
|
|
|
|
For a `x2` model, the middle two ranges (the most important ones, with **bold text**) would be, respectively:
|
|
- `x1.0+` - `x1.5`
|
|
- `x1.5+` - `x2.0`
|
|
|
|
So, to get the best result, your upscale factor should be between `1.0` and `(model_scale - 0.5)`. The node won't stop you from getting a subpar result, but it will warn you (if the `show_status` toggle is enabled).
|
|
|
|
## Advanced: Upscale support (aka "HD-fix")
|
|
|
|

|
|
|
|
`Best-Res` nodes have a special version _(currently, only `area` node has one)_, which also account for very first upscale aka HD-fix - to ensure the upscaled resolution is also divisible by the step value.
|
|
|
|
Additionally, they're accompanied by utility node to also auto-detect any necessary cropping/padding (for out-paint) to perform on the upscaled image before second KSampler (the "HD-fix" itself).
|
|
|
|
## Tooltips
|
|
|
|
Each parameter is self-documented in the shortest possible, yet exhaustive detail - just hover mouse over it. If you're new to Comfy and Stable Diffusion, this might be especially helpful.
|
|
|
|
## A note on `step` value to choose
|
|
|
|
This parameter has the highest priority. A desired resolution is slightly tweaked to **always** adhere to it **strictly**. The nodes do their best to match all other criteria, but no matter what, in the end both width and height **must** remain a multiple of this value. This means two things:
|
|
1. If you don't plan processing the image with diffusion model but otherwise like these nodes for image-size selection, you can still use them - just set `step` to `1` (effectively disabling any rounding).
|
|
2. The right `step` value can single-handedly save you from unnecessary cropping or out-painting later.
|
|
|
|
> In my workflows, I usually generate images like this:
|
|
> - initial draft generation, exactly in the resolution the model was trained on - only composition and overall silhouettes matter here.
|
|
> - "HD fix": immediate first 1.5x upscale in latent space, followed by sampling with high denoise (0.5+) - this becomes the actual base image to improve upon.
|
|
> - some tweaking/inpainting is done in this resolution.
|
|
> - at least one more upscale, still sampling the whole image at once if GPU has VRAM for that (with a lower denoise, though).
|
|
> - subsequent upscales with [USDU](https://github.com/ssitu/ComfyUI_UltimateSDUpscale).
|
|
|
|
So, this imposes a few restrictions on the initial gen if we want to avoid cropping/outpainting later:
|
|
- The initial image must be a multiple of `8`
|
|
- After 1.5x upscale it must also be a multiple of `8` - so a +0.5 of size must be divisible by 8, or the initial step must be `8*2`.
|
|
- After the first 1.5x upscale _(with the original `step` being `8*2`, or `16`)_ our image became divisible by `8*2*1.5`, or `8*3`, so the second upscale could be +1/3 aka 1.333x. And if we do so, we actually reach the total size of 2x of the original gen.
|
|
- However, if we do so, at the very next step our divisibility would be `8*3*1.333`, or `8*4`.
|
|
- This is good since the third upscale could be either 1.5x or 1.25x... but it can't be another +1/3.
|
|
- So, to workaround it, it's safer to include another multiple of `3` into the original `step` _(so, together it becomes `8*2*3`)_.
|
|
- With it, we can do the previous 1.5x > 1.333x, followed by either 1.5x/1.25x **or 1.333x**.
|
|
- If instead we did 1.5x > **2x** - then we end up with a triple of the original size **AND** we have another multiple of 3 built-in, so the image has become divisible by `9`. This is not at all necessary for "regular"-sized HD images, but it might become **very** handy for later ultra-upscales (6k+) with USDU.
|
|
|
|
Summarizing all of the above, our lowest common denominator to be safe during first few upscales is `8*2*3`.
|
|
|
|
**Thus, `48` by default.**
|
|
|
|
Additionally, if you prefer to always upscale by 1.5, you might look into `8*2*2` = `32`.
|
|
Or, to allow a few more of 1.5x upscales (or a 1.25x one), or to get the resolution closer to the ones we used to (1080p, 1440p, etc), you might want to increase it by a power of 2, getting `64`, `96`, `128`, `192`, `256`, etc.
|