Docs / Workflows / Pixel-perfect output
Workflows
Pixel-perfect output
Why an AI upscaler is usually the wrong tool for pixel art, and what to do instead.
The framing matters more than the model
The obvious move — generate small, then run an AI upscaler — produces bad pixel art. ESRGAN-family and diffusion upscalers invent detail, and between the hard edges of a pixel grid what they invent is grey fringing and softened corners. The result looks like pixel art that has been photographed through a smudged lens.
The correct operation for genuine pixel art is not learned upscaling at all:
Detect the pixel grid → downscale to true native resolution → quantise the palette → nearest-neighbour upscale.
Every step there is deterministic. Nothing is invented. The output has exactly the palette you asked for and exactly the grid you asked for, which is what makes it pixel art rather than a picture of some.
The tools for it
These are ComfyUI custom nodes, not models. ComfyUI-PixelArt-Detector is installed and provides
the whole pipeline on its own:
| Node | What it does |
|---|---|
PixelArtDetectorToImage | Detects the pixel grid and reduces the palette — the one-node version |
PixelArtDetectorConverter | Full control: resize mode, quantisation algorithm, dithering, palette swap |
PixelArtPaletteGenerator / PixelArtLoadPalettes | Build or load a palette to share across an asset set |
PixelArtAddDitherPattern | Floyd–Steinberg and Bayer dithering |
PixelArtDetectorSave | Writes optimised, palette-indexed PNG/WebP |
Proof it works, measured on a real generation:
| Resolution | Unique colours | |
|---|---|---|
| Raw SDXL output | 1024×1024 | 58,325 |
Through PixelArtDetectorToImage | 341×341 | 20 |
Grid detection recovered the native scale (1024 ÷ 3) and quantised to a 20-colour palette. Run it
yourself with comfy-smoke.py pixel.
Other node packs exist (PixelArt Processing Nodes, Pixelate, Unfaker). They are deliberately not installed — the one above covers the same ground, and the alternatives are small, low-traffic repositories that would be running arbitrary code inside ComfyUI for no added capability. Add them only if you hit a specific limitation.
The palette step is the one people skip and then miss. Quantising to a deliberate palette — ideally one lifted from a reference image so a whole asset set matches — is most of what makes generated art look like it belongs in one game.
When a learned upscaler is right
For illustrated game art — backgrounds, splash art, painted UI, anything not on a pixel grid — a
learned upscaler is exactly right. That is what RealESRGAN_x4plus_anime_6B is installed for.
The licence trap
This one is worth stating plainly because the two models most often recommended for pixel upscaling cannot be used in a game you sell:
| Upscaler | Licence | Shippable commercially |
|---|---|---|
| RealESRGAN x4plus anime 6B | BSD-3-Clause | Yes — installed |
| 4x PixelPerfectV4 | WTFPL | Yes — installed (16.7M-param ESRGAN, 63.9 MB) |
| 4x Fatal Pixels | CC-BY-NC-SA-4.0 | No |
| 4x xbrz | CC-BY-NC-4.0 | No |
Fatal Pixels and xbrz are the two you will find recommended most often. Both are non-commercial. Only the BSD-3 model is installed here, deliberately.
Note
Background removal
Cutting a sprite out cleanly is its own step, unless the transparent-background LoRA handled it for
you. ComfyUI has native background-removal/matting support; the model directory is
models/background_removal/.
Do the cut-out before quantisation. Matting against a quantised image produces ragged edges, because there are no intermediate values left for the matte to use.
Source: content/workflows/pixel-perfect-output.md · maintained in the nuilab-aigaming repository.