Pixelate
Turn AI slop into actual pixel art in one node
- image
- palette_image
- IMAGE
Pixel art is the one style diffusion is genuinely bad at. Models don't understand "chunky" - they give you soft blobs that read as pixel art from across the room and fall apart the second you zoom in. The fix has always been post-processing: downscale hard, shrink the color palette, then upscale back up. That's exactly the recipe sd-webui-pixelart gave A1111 users for years, and ComfyUI-Pixelate is the same trick as a single native ComfyUI node. No model, no API key, no VRAM pressure - it's pure image math running on CPU.
What it actually does
Feed it an image and it runs a four-stage pipeline. First it downscales by an integer factor (OpenCV interpolation, nearest through lanczos). If you flip rescale_to_original, it scales back up to the original dimensions with nearest-neighbor, which is what gives you those hard blocky edges instead of mush. Next it optionally converts to grayscale or binary. Then it builds a color palette and snaps every pixel to the nearest palette color. Optionally it adds Floyd–Steinberg dithering - the classic error-diffusion trick that fakes extra tones by scattering colored dots, the thing that makes 16-color images look like they have 40.
The inputs that matter
There are ten knobs but you'll realistically touch these:
image- anything: a generated image, a screenshot, a low-res render you want to gamesify.downscale_factor(1–32, default 4) - the block size. 4 gives you that classic chunky SNES feel.colors(2–256, default 16) - target palette size. 16 is the retro sweet spot.rescale_to_original- leave it off if you want small pixel output, on if your downstream nodes expect the original resolution.dithering-nonefor clean flat colors,floyd-steinbergfor that dithered Game Boy look.quantization_method- set toautountil you have a reason not to.
Two optional inputs, palette_image and palette_size, let you extract a palette from a reference image instead of the input - handy if you want to force your output into, say, the actual Game Boy palette.
The single output is an IMAGE with the same batch/alpha shape it went in with. Wire it straight to Save Image, or run it through a VAE encode and feed it back into img2img for a "stylize my render as pixel art" workflow.
Installing it
It's a one-node pack with no requirements.txt, so install is painless:
cd ComfyUI/custom_nodes
git clone https://github.com/flycarl/ComfyUI-Pixelate
Restart ComfyUI and search for "Pixelate" in the node menu. Or just use ComfyUI Manager and search "ComfyUI-Pixelate". That's the whole install - it leans on OpenCV, Pillow, numpy and torch, all of which ship with ComfyUI. No weights to download.
Where people get burned
A few things the README glosses over that the source code tells you plainly:
- It only processes the first image in a batch. The node reads
image[0]and drops the rest. Fine for a single generated image, a trap if you feed it a batch grid or video frames - you'll silently get one frame back. scale_mode: autoisn't smart. It just maps to OpenCV'sINTER_AREA, which is honestly the right default for downscaling anyway. "Auto" is marketing, not magic.- The GPU k-means is fiction. Stock OpenCV has no CUDA build, so that path always throws and falls back to CPU k-means on a random 10,000-pixel sample. Worse, k-means is capped at 32 colors no matter what you put in
colors. If you want the full palette, picklibimagequantorauto(which routes big images there). - Floyd–Steinberg is slow. It's pure-Python, pixel-by-pixel, and it runs after any rescale - so dithering a 1024² image with
rescale_to_originalon will make you wait. Keepdownscale_factorhigh or skip dithering on big images. - Wire
palette_imageandcolorsis ignored - the reference image owns the palette, andpalette_sizedecides how many colors it extracts. - Output dimensions change unless
rescale_to_originalis on, so make sure whatever you plug it into accepts arbitrary sizes.
Realistic take: it's a small, occasionally rough port, not a polished piece of infrastructure - there's a single commit stream and it doesn't get much community chatter. But for "I want this render to look like a sprite," it does the job in one node and costs you nothing to try.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| downscale_factor | INT | 41–32 | — |
| scale_mode | COMBO | 6 options: auto, nearest, area, linear, cubic, lanczos | |
| rescale_to_original | BOOLEAN | false | — |
| color_mode | COMBO | 3 options: rgb, grayscale, bw | |
| colors | INT | 162–256 | — |
| quantization_method | COMBO | 7 options: auto, kmeans, mediancut, maxcoverage, fastoctree, libimagequant, +1 | |
| dithering | COMBO | 2 options: none, floyd-steinberg | |
| palette_imageopt | IMAGE | — | |
| palette_sizeopt | INT | 322–256 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |