Patch Upscale ๐
Upscale the patch, not the whole texture
- image
- mask
- upscaled_image
- upscaled_mask
- scale_data
- info
Seamless tiling is only half the battle - the seams themselves are usually garbage. When you make a texture tileable, the stitched edges need inpainting, and the classic fix is to upscale the seam area before running it through Stable Diffusion, because a 512px crop of a seam doesn't give the model enough pixels to work with. Patch Upscale is the "give the model more pixels" step, and it's the node that makes the rest of that workflow feel sane.
It takes a small cropped region, scales it up to a target resolution in megapixels, and - here's the clever part - hands you back a PATCH_SCALE_DATA object that remembers exactly how big the original was. That data is what lets its sibling node, Patch Fit, shrink the inpainted result back down and stitch it cleanly. Crop โ upscale โ inpaint โ fit โ stitch. One node each way, no bookkeeping by hand.
How it works
It keeps the aspect ratio, solves for the dimensions that hit your target megapixels, and rescales with torch's F.interpolate. A few details worth knowing:
- It never downscales. If your patch is already at or above the target megapixels, it just passes it through and records a scale factor of 1.0.
max_dimensionis your safety rail - it clamps the long edge so a weird aspect ratio can't produce a 16k monster that eats your VRAM.- If you feed it a mask, the mask gets upscaled right alongside the image (bilinear, always), so your inpaint region stays pixel-aligned.
The inputs
target_megapixels- the resolution you're aiming for. 1.0โ2.0 is the sweet spot for SD inpainting; the default of 2.0 works for most textures.max_dimension- caps the longest edge, default 2048.upscale_method- bicubic, bilinear, lanczos, or nearest. Here's the gotcha: torch doesn't actually have a lanczos implementation, so the "lanczos" option silently maps to bicubic. Pick bicubic and stop worrying about it.
Outputs: upscaled_image, upscaled_mask (zeroed if you didn't give one), scale_data (the PATCH_SCALE_DATA you feed into Patch Fit), and an info string that tells you the final dimensions and scale factor in plain text.
Where people get burned
The most common mistake is losing the scale_data. Patch Fit needs it - it's the record of the original dimensions. If you drop it and try to reconnect with a fresh node, you're guessing, and the fit will come back wrong. Keep the chain intact: Patch Upscale โ your inpainting โ Patch Fit, with scale_data wired straight through.
Second: don't set target_megapixels higher than you need. More pixels means a slower inpaint pass and no quality gain past a point. 2 MP is plenty for a seam region.
Installation
It's part of amtarr/ComfyUI-TextureAlchemy, found under Add Node โ Texture Alchemist โ Inpainting. Install via ComfyUI Manager (search "TextureAlchemy") or:
cd ComfyUI/custom_nodes
git clone https://github.com/amtarr/ComfyUI-TextureAlchemy
Restart and you're done. No extra dependencies - this pack runs entirely on ComfyUI's bundled PyTorch, so there's nothing to pip-install and no model files to fetch for this node.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | โ | |
| target_megapixels | FLOAT | 2.00.5โ16 | Target resolution in megapixels (e.g., 2.0 = 2MP) |
| max_dimension | INT | 2048512โ8192 | Maximum width/height (prevents extreme upscaling) |
| upscale_method | COMBO | bicubic | Interpolation method for upscaling |
| maskopt | MASK | Optional mask to upscale with image |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| upscaled_image | IMAGE | โ |
| upscaled_mask | MASK | โ |
| scale_data | PATCH_SCALE_DATA | โ |
| info | STRING | โ |