Nodes/ꘇ Genereti/ꘇ top.cleanup
ComfyUI Node

ꘇ top.cleanup

Resize and tidy pixels without touching a model

By languel·Created about a month ago·Updated 3 days ago· 1
ꘇ top.cleanup
  • image
  • image
◄width1024►
◄height1024►
◄methodbicubic►
◄smoothing0.00►
◄color_threshold0.12►
◄antialias0.00►
◄sharpen0.00►

First, the thing everyone gets wrong: top.cleanup is not an upscaler. It resizes and tidies; it does not invent detail. If you feed it a 256px image and ask for 2048, you get a smooth 2048px image, not a detailed one. Reaching for this when you wanted ESRGAN or SeedVR2 is the classic misread, and the pack's own docs are blunt about it - "spatial filtering, not learned restoration or reconstruction of missing detail."

So what is it for? The job that sits between a real upscaler and a blur: explicit dimensions, a pre-resize edge-preserving smoothing pass, cheap antialiasing on hard edges, and a mild sharpen that doesn't halo. It's a TOP in ꘇ Genereti (languel/genereti, by Liuboto, MIT), the realtime creative-coding layer for ComfyUI, and it's model-free by design - no downloads, no checkerboarding, milliseconds per frame.

The stages, in the order they run

The implementation reads in a straight line, which makes it easy to reason about:

  1. Bilateral smoothing (if smoothing > 0) - a 3×3 blend where each neighbour's weight falls off both by colour distance (controlled by color_threshold) and spatial distance. Edge-preserving, so it smooths flat regions and leaves boundaries. Runs before the resize, which is why it's good at killing grime before you enlarge it.
  2. Resize to width × height with method: bilinear or bicubic. The bicubic coefficient is -0.75, and interpolation is premultiplied so transparent edges don't pick up fringes. Downsampling here is plain resampling - not a dedicated antialiased reduction filter, so don't expect area-averaging quality.
  3. Antialiasing (if antialias > 0) - a short edge-direction filter driven by the luminance gradient, taking two taps at half a pixel along the tangent. The strength per pixel is scaled by local contrast, so flat areas aren't blurred. The author is careful about the name: it's FXAA-style, "not full NVIDIA FXAA."
  4. Sharpen (if sharpen > 0) - an unsharp pass whose result is clamped to the local envelope (the min/max of the pixel and its four neighbours), which is what keeps it from producing halos.

Each optional stage is skipped at zero, so plain bicubic resize and the full chain cost very different amounts.

The controls that matter

width and height are independent INTs, 1–4096, defaulting to 1024×1024. They do not preserve aspect ratio for you - the docs say this twice, and defaulting to a square is exactly how you smear a 16:9 frame. Set them to match the source.

method picks bicubic (default) or bilinear. Then the three amount dials, and the tooltips are the author's own guidance: smoothing starts around 0.2 (raise it and thin lines start to disappear), color_threshold at 0.12 with lower values protecting boundaries, antialias around 0.3, sharpen around 0.1. The docs give a recipe worth starting from: bicubic, smoothing 0.25, color_threshold 0.12, antialias 0.3, sharpen 0.1.

Output is a single image (IMAGE).

Live versus Queue

Live, the whole chain runs in the browser on WebGPU; the pack measured a full bilateral + bicubic + AA + sharpen chain from 512→1024 at roughly 0.8 ms p50 in a small browser fixture (their numbers, their Mac, their caveat that this isn't full graph FPS). On Queue, the same spatial stages run in PyTorch on the input tensor's device, and a synthetic CPU/GPU comparison differed by at most one 8-bit colour level. That equivalence is the point: you can dial it in live and trust the queued frame.

Install

Manager → search "Genereti" → install ꘇ Genereti → restart ComfyUI → refresh the browser page. Manual:

git clone https://github.com/languel/genereti.git custom_nodes/genereti
./.venv/bin/python -m pip install -r custom_nodes/genereti/requirements.txt

The pinned requirement is only comfyui-frontend-package>=1.53.6 - no models, no Core ML, no extra servers. ComfyUI 0.38.2+, Python 3.11+, WebGPU-capable browser for the live path. The bundled ꘇ-Realtime-Cleanup workflow shows a 256px source against a 512px bilinear baseline and a 512px cleanup branch, which is the fastest way to see the difference.

Gotchas

Batches broadcast but must otherwise match. A single B image broadcasts across A's batch; mismatched batch sizes raise instead of guessing.

Premultiplication is doing work you don't see. If you're compositing cutouts over new backgrounds, the premultiplied sampling is why edges stay clean - but it also means an image with garbage colours in fully transparent pixels will sample as transparent, not as garbage. That's correct behaviour, occasionally surprising.

Rabbit hole alert. The pack's notes list FSR1 EASU/RCAS and SMAA as future comparison options and explicitly say neither is implemented. Don't go looking for upscaler-grade output in this node; it isn't claiming to be one.

CategoryGenereti / TOP

Inputs (8)

NameTypeDefaultDescription
imageIMAGE—
widthINT10241–4096—
heightINT10241–4096—
methodCOMBObicubic2 options: bilinear, bicubic
smoothingFLOAT0.000–13×3 edge-preserving bilateral blend, before enlargement. Start around 0.2.
color_thresholdFLOAT0.120.001–1Bilateral color/alpha threshold. Lower values protect boundaries.
antialiasFLOAT0.000–1Short luminance-edge directional filter after resize; FXAA-style, not full NVIDIA FXAA.
sharpenFLOAT0.000–1Local-envelope-clamped sharpening after antialiasing. Start around 0.1.

Outputs (1)

NameTypeDescription
imageIMAGE—