Klein Tiled Upscaler
The 'vibecoded' Klein tiler that fixes what Ultimate SD Upscale couldn't
- guider
- positive
- negative
- sampler
- sigmas
- vae
- image
- upscale_model
- IMAGE
- LATENT
If you've tried to tile-upscale a Flux2.Klein image with the usual tricks, you know the failure mode: Ultimate SD Upscale leaves grid seams, and SDXL tile ControlNet doesn't exist for Klein. This node is the community answer - a self-contained, inpainting-based tiler built specifically for Flux2.Klein, by an author who cheerfully admits in the README that the whole thing is "100% vibecoded" and doesn't know how to code. It sounds like a red flag. It's actually one of the better first-generation Klein upscalers, because the concept is right even if the code is LLM-scrubbed.
Let's be clear about what it is and isn't. This is creative upscaling - the "invent detail that wasn't there" rung, not the "add pixels" rung. On an already-sharp image, an ESRGAN model is the right tool and this is the wrong one. But when you want Klein to reimagine texture, skin grain, and surface detail at 2x and beyond, it runs rings around the manual reference-latent workflows people were hand-wiring before it.
How it works
The node is a full sampling pipeline, not a drop-in upscaler. It bicubically upscales your image to scale_factor, optionally through an ESRGAN model first, then splits the canvas into equal tiles (Auto mode divides evenly so there's no odd partial tile at the edges). Two things make it work:
- Laplacian detail analysis. It runs a 3x3 Laplacian edge convolution over the grayscale low-res input (with a pre-blur to kill JPEG noise) and scores each tile's detail. Flat sky drops to ~2 steps; textured regions run the full sampler. This drives everything else.
- Per-tile reference latents. Each tile's own local crop of the original is patched into Klein's
reference_latentsconditioning. That's the trick the earlier manual workflows botched - it's what stops each tile from drifting into a different image. The README's own warning that "a complex prompt describing specific objects in one corner can cause those objects to hallucinate in other tiles" is the flip side of this: each tile gets the whole prompt, so keep it generic.
Tiles are sampled with your guider/sampler/sigmas, blended into a latent canvas and a pixel canvas through blurred masks, and each one is linearly histogram-matched back against the original upscaled canvas (color_match) - which incidentally is the same fix the community landed on for Klein's warm color-shift-on-edit problem.
The inputs that matter
First, the gotcha: this is a custom-sampling node. It needs guider, positive, negative, sampler, sigmas, and vae wired up - this is the price of Klein tiling. Don't hand-wire it; load the repo's workflow with comments.json and swap your model in. The settings a beginner actually touches:
scale_factor(2.0 default) - 2x is the sweet spot the author tested everything at; 4x works but is slow (over 10 minutes for a ~2.5MP source on a 3090, per the author).core_anchor(1.0 default) - your creativity dial. Lower keeps more of the original structure; 0.85 is already subtle. Elbow-turned-into-a-finger? Drop this.color_match- leave it on. It's the seams fix.adaptive_tiling(False default) - turn on for flat/anime images; it cuts steps on low-detail tiles.tiling_strategy(Detail-First default) - builds textured tiles first so flat zones anchor to finished edges.
Outputs are IMAGE and a LATENT - the latent is only useful in a two-stage workflow; otherwise ignore it. The optional upscale_model input takes a standard ESRGAN model (like 4x-UltraSharp) from ComfyUI's models/upscale_models; without it, bicubic.
Install
ComfyUI Manager (search "Klein Tiled Upscaler") or:
cd ComfyUI/custom_nodes
git clone https://github.com/Gavr728/ComfyUI_KleinTiledUpscaler
Restart ComfyUI. No dependencies, no bundled model downloads - it runs on the Klein checkpoint you already have (MIT licensed, by the way).
Troubleshooting
- Visible seams: color_match on,
mask_blurup to 48–64, Detail-First strategy. That's the author's own checklist. - Tile drift / hallucinated objects: your prompt is too specific. "upscale image, subtle material texture, natural surface complexity" beats "extreme macro skin pores in the top-left corner".
- 3x upscale factor: a known bug - the author reports the model loses the reference context and hallucinates with the Q8 quant but behaves with the INT8 model. If 3x is your number, try INT8.
- Contrast jump between tiles: that's
adaptive_tiling's step-count shift; disable it for uniform rendering.
Want more restraint overall? Consistency LoRAs (like dx8152/Flux2-Klein-9B-Consistency) work and tame drift at the cost of upscale strength. One honest caveat: it's a first-version vibecoded node, so treat unusual settings as "author never tested this" territory - the tested config is 4 steps, Euler, CFG 1.0, 1024 tiles, 2x.
Inputs (21)
| Name | Type | Default | Description |
|---|---|---|---|
| guider | GUIDER | — | |
| positive | CONDITIONING | — | |
| negative | CONDITIONING | — | |
| sampler | SAMPLER | — | |
| sigmas | SIGMAS | — | |
| vae | VAE | — | |
| image | IMAGE | — | |
| seed | INT | 00–18446744073709550000 | — |
| scale_factor | FLOAT | 2.001–8 | Upscale ratio applied before tiling refine. |
| tiling_strategy | COMBO | Detail-First | Tile sequence order (Detail-First analyzes variance). |
| tile_size_mode | COMBO | Auto | Auto divides canvas evenly; Manual allows custom height/width below. |
| tile_width | INT | 1024512–4096 | Width of individual tiles when Manual mode is selected. |
| tile_height | INT | 1024512–4096 | Height of individual tiles when Manual mode is selected. |
| padding | INT | 1280–512 | — |
| color_match | BOOLEAN | true | Matches colors dynamically against original image to avoid color drift. |
| mask_blur | INT | 320–64 | Blur radius applied to blend masks to remove seams. |
| adaptive_tiling | BOOLEAN | false | Dynamically scales down sampling steps on flatter tiles to optimize speed and reduce hallucinations |
| skip_threshold | FLOAT | 0.000–1 | Only works with Detail-First. Skip tiles whose detail variance is below this fraction of the reference variance (keeps bicubic content). 0.0 = never skip. |
| core_anchor | FLOAT | 1.000.5–1 | Lower = keep more original structure in tile core. 1.0 = full regen. 0.85 is subtle, 1.0-0.95 is the sweet spot. |
| consistent_noise | BOOLEAN | true | Sample all tiles from one shared full-canvas noise field. Overlapping regions get identical noise. Off = independent per-tile noise. |
| upscale_modelopt | UPSCALE_MODEL | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |
| LATENT | LATENT | — |