Nodes/ComfyUI API Toolkit/Pixel Art Resize
ComfyUI Node

Pixel Art Resize

The local node that actually makes pixel art

By IxMxAMAR·Created 5 months ago·Updated 2 months ago· 1
Pixel Art Resize
  • image
  • image
  • small_image
  • palette_json
downscale_factor8
upscale_factor8
palette_modeshared_batch
max_palette_size32
ditheringnone

Here's a position the community holds and holds correctly: diffusion models don't produce pixel art. They produce soft, full-color, off-grid pixels that look like pixel art from a distance and fall apart when you zoom in - inconsistent pixel sizes, stray noise, hundreds of colors. The real pixel art is made by a deterministic post-process: downscale to chunky blocks, lock the colors to a small palette, upscale back up with nearest-neighbor. That post-process is exactly what this node does, and it's the whole reason it sits in an "API Toolkit" pack: it's the one node here that runs locally, free, no API key, no network - the utility that cleans up after the API generation.

The pack name is a lie for this one in the best way. If you generate a "pixel art" image with Kling or any other model, run it through this node and it becomes actually pixelated: a real grid, a real limited palette, no blur.

The inputs that matter

Four of them do the real work:

  • downscale_factor (default 8) - how much to shrink. 8 means each output pixel represents an 8×8 block of the original. Higher = chunkier, more retro.
  • upscale_factor (default 8) - how much to blow it back up. Equal to downscale and the output matches the original size, just pixelated. Set to 1 for the raw small sprite.
  • palette_mode - the important one. shared_batch builds one palette from frame 0 and applies it to every frame - this is the setting for animations, because it stops colors from shimmering between frames. per_frame gives each frame its own palette (richer, but shimmery). none skips color reduction entirely.
  • max_palette_size (default 32) - how many colors you allow. The tooltip has the real guidance: 16–32 for a classic SNES look, 64+ for richer art.
  • dithering - floyd_steinberg adds error diffusion so small palettes get smoother gradients instead of banding. Slower, prettier, worth it below ~32 colors.

What comes out

image is the final upscaled pixel art; small_image is the raw downscaled version before the display upscale; palette_json is the actual locked palette as JSON - size plus a hex color list, useful if you're keeping palette consistency across separate generations.

How it actually works (briefly)

Nearest-neighbor downscale to make the blocks, palette quantization (the pack's own octree step) to lock the colors, per-pixel snapping to the nearest palette color - accelerated by a scipy KD-tree when scipy is installed, pure numpy otherwise - then nearest-neighbor upscale. Which is a reminder: the README's pip install -r requirements.txt covers it, but if you skip dependencies the KD-tree just won't be there and palette matching gets slower, not broken.

Installing and gotchas

ComfyUI Manager, search "API Toolkit", install, restart:

cd ComfyUI/custom_nodes
git clone https://github.com/IxMxAMAR/ComfyUI-API-Toolkit
cd ComfyUI-API-Toolkit
pip install -r requirements.txt

Two practical notes. First, if your image dimensions aren't evenly divisible by the downscale factor, the node uses a slightly smaller block grid and logs a notice - you'll get e.g. a 512→64 grid with a tiny 8px leftover, so size your inputs to clean multiples. Second, for a single image this is instant; for a long animation batch, shared_batch is the mode that keeps it stable frame-to-frame, which is the one setting people get wrong and then blame the node for. The tooltip says it, the source does it, and it's the difference between a coherent sprite animation and a color-flicker mess.

CategoryAPI Toolkit/Utils/Image

Inputs (6)

NameTypeDefaultDescription
imageIMAGESource image or batch to pixelate.
downscale_factorINT81–64How much to shrink. 8 = each output pixel represents an 8x8 block of the original.
upscale_factorINT81–64How much to scale back up. Same as downscale = output matches original size but pixelated. Set to 1 for raw pixelated output.
palette_modeCOMBOshared_batchnone = no color quantization. shared_batch = palette from frame 0 applied to all (best for animations, prevents color shimmer). per_frame = each frame gets its own palette.
max_palette_sizeINT322–256Max distinct colors in palette. 16-32 for classic SNES look, 64+ for richer art.
ditheringoptCOMBOnoneFloyd-Steinberg adds error diffusion for smoother color gradients at small palette sizes. Slower but prettier.

Outputs (3)

NameTypeDescription
imageIMAGE
small_imageIMAGE
palette_jsonSTRING