Nodes/ComfyUI-GameDev/Resize + Dither
ComfyUI Node

Resize + Dither

The fastest way to make AI art look like a real game sprite

By ecalot·Created 5 months ago·Updated 5 months ago· 0
Resize + Dither
  • images
  • images
width0
height200
dither_modepositional
palette_modevga_256
palette_colors24

AI images are smooth, high-res, and full of gradient mush - which is exactly the opposite of what a pixel-art sprite looks like. Resize + Dither (class resize and dither) is the two-step pipeline that fixes that: scale down with nearest-neighbor sampling so you get hard, crisp pixels instead of bilinear blur, then dither down to a fixed palette so you get that classic ordered-dither texture instead of banding. It runs on a whole batch, so you can crunch all your frames at once. It's part of the ComfyUI-GameDev pack, and honestly it's the node I'd reach for outside game dev too - it's a fast way to give anything a retro look.

How it works

Three steps, in order: quantize the batch to clean RGB, resize with nearest-neighbor (a torch index_select using floor-scaled indices - no interpolation, ever), then snap every pixel to the nearest color in a palette.

The dithering is where you have a real choice:

  • dither_mode = positional - ordered Bayer 8×8 dithering: each pixel gets nudged by a fixed threshold pattern before snapping to the nearest palette color. Fast, pure torch, chunky like a SNES texture. This is the one I'd default to.
  • dither_mode = floyd - Floyd-Steinberg error diffusion. Smoother, preserves gradients better, but it's a per-pixel triple loop over numpy arrays on the CPU. On a large batch you will feel it. Use it for final renders, not iteration.

The palette is a second choice:

  • palette_mode = vga_256 - a fixed 256-color palette: a 6×6×6 RGB cube plus a 40-step gray ramp, deduplicated. The code credits GlitchNodes' Pixel8Bit for the recipe, so if you've used that node you know exactly what you're getting.
  • palette_mode = optimized_x_colors - builds an adaptive palette from your actual image with deterministic k-means (10 iterations, sampling up to 20,000 pixels), sorted by luminance. palette_colors (2–256, default 24) sets how many colors you get. Usually looks better for real sprites, at the cost of a quick clustering pass.

The inputs that matter

  • width / height - set to 0 for auto. (0,0) keeps the original size; (0,200) derives width to match; (200,0) derives height. Defaults are width 0, height 200 - a 200px-tall sprite.
  • dither_mode - positional or floyd (above).
  • palette_mode and palette_colors - the palette choice; palette_colors is ignored in vga_256 mode.
  • Output: images, the resized, dithered RGB batch - same order and length as the input batch.

Bonus: after the first run the node draws before/after previews inside itself, and widget changes recompute the preview locally in the browser using the same algorithm. You can scrub palette_colors and dither_mode without re-running - then run once to bake your choice into the graph.

Install

Via ComfyUI Manager (search "ComfyUI-GameDev") or:

cd ComfyUI/custom_nodes
git clone https://github.com/ecalot/ComfyUI-GameDev
cd ComfyUI-GameDev
pip install .

Restart ComfyUI. No models to fetch; the deps are torch>=2.6, numpy, and pillow, which you already have. Like the rest of this young pack (one maintainer, Enrique Calot), expect small rough edges rather than a long issue tracker.

Common issues

  • Blurry pixels instead of crisp ones - the node never interpolates, so if your output looks soft, something after this node - or your viewer - is upscaling it. Don't blame the resize.
  • Floyd taking forever - expected on big batches; that's the CPU loop. Use positional for iteration and flip to floyd for the final pass.
  • Preview not showing - it needs one run first. And if you're on the Nodes 2.0 (Vue) frontend, custom in-node canvases from this pack may not render; fall back to the legacy canvas. Restart + hard-refresh after installing.
CategoryGame Development/Image Adjustments

Inputs (6)

NameTypeDefaultDescription
imagesIMAGE
widthINT00–8192
heightINT2000–8192
dither_modeCOMBOpositional2 options: positional, floyd
palette_modeCOMBOvga_2562 options: vga_256, optimized_x_colors
palette_colorsINT242–256

Outputs (1)

NameTypeDescription
imagesIMAGE