ComfyUI Node

Perceptual Palette Reduce

Your AI Pixel Art Has 40,000 Colors. This Node Cuts It To 24.

By envy-ai·Created 8 days ago·Updated a day ago· 13
Perceptual Palette Reduce
  • image
  • IMAGE
colors24

Diffusion models don't make pixel art. They make something that reads as pixel art from across the room: inconsistent pseudo-pixel sizes, off-grid edges, and a "limited" palette that is secretly a few thousand colors. Everyone who does this properly ends up at the same two-step fix - snap the image to a grid, then cut the color count hard. Perceptual Palette Reduce is the second half of that, and it's the half that decides whether your output looks like a deliberately restricted sprite or like a JPEG that fell in a puddle.

What it actually does

It's a quantizer with taste. You hand it an image batch and a maximum palette size, and it finds that many colors perceptually - weighted so colors covering the most pixels get selected first, and measured in OKLab rather than RGB.

That last part is the whole point. In sRGB, doubling the numeric distance between two dark blues is a huge visible jump; the same numeric distance near white is invisible. OKLab is built so equal distances look roughly equally different, which is why a 24-color palette picked in OKLab gives you the colors you'd have chosen by hand instead of burning six slots on near-black.

Mechanically: the node rounds everything to 8-bit, counts the unique colors, converts them to OKLab, then runs weighted k-means - farthest-point initialization weighted by the square root of each color's pixel count (so popular colors claim the early slots), followed by a dozen mean-recomputation passes. Every unique color is then snapped to its nearest palette entry, and the palette colors are rounded back to exact 8-bit RGB. There's no dithering option, and the palette is chosen per image, not per batch.

Inputs and output

Two inputs, which is the whole appeal:

  • image - a single image or a batch. Alpha is preserved if present; a tensor with fewer than 3 channels raises rather than guessing.
  • colors - 2 to 256, default 24. It's a maximum, not a target: if the image only holds 11 distinct colors, you get 11.

One output, IMAGE, at the same dimensions as the input. Wire it into Save Image, a preview, or the video node downstream.

Where it fits in the pipeline

The order people get wrong: run this after Pixel Grid Collapse, not before. Collapse first and every remaining color is a real block color, so your palette slots go to actual sprite colors. Reduce first and the clustering trains on anti-aliased in-between pixels that vanish the moment you snap to a grid - wasted slots, muddier picks. Collapse alone gives you crisp blocks in 900 colors; reduce alone gives you 24 blurry ones. You want both, in that order.

For animation, there's a real limitation: because the palette is auto-selected per image, a batch of frames gets subtly different palettes and flickers on playback. The pack's MiniMax H3 nodes expose a shared_palette switch for exactly that reason. The standalone node doesn't.

Install

No models, no API key, nothing to download. ComfyUI Manager → search Krea 2 and MiniMax H3 Pixel Art Refiners (the registry name) or the repo name. Or do it by hand:

cd ComfyUI/custom_nodes
git clone https://github.com/envy-ai/ComfyUI-Krea2-Pixel-Art-Refiner.git krea2_pixel_art_refiner

Restart ComfyUI, then find it under image/color or by searching the node name. The only declared dependency is opencv-python-headless>=4.8 in pyproject.toml - note there's no requirements.txt in that repo, so a manual clone may not install anything for you.

Common issues

The node isn't there at all. The pack targets the newer comfy_api node API (comfy_entrypoint + ComfyExtension), so it needs a reasonably current ComfyUI. And nodes.py imports cv2 at the top of the file: if opencv is missing, the entire pack fails to import - including this node, which never touches opencv itself. Fix: pip install opencv-python-headless into ComfyUI's Python environment.

"Perceptual palette reduction requires at least 3 image channels." You fed it a mask or grayscale. Convert to RGB first - the core MaskToImage node does it.

Output still reads as "AI". Palette reduction fixes color count, not block size. If the pseudo-pixels are different sizes, no quantizer will save you; that's the grid step's job.

Blobby, banded mush. You went too low. 24 is a sane default, 16 gets you into PICO-8 territory, and 8 turns faces into stains.

Not much to google. Search the usual subreddits for this node and you'll find nothing - the pack comes from a one-person CivitAI model account (the same handle as the Envy Starlight and Envy Flux Greebles checkpoints), so the README and the source are the documentation. Nothing here is exotic, though. It's k-means in a perceptual color space, and that's a well-trodden path.

Categoryimage/color

Inputs (2)

NameTypeDefaultDescription
imageIMAGE
colorsINT242–256Maximum number of colors in each image's palette.

Outputs (1)

NameTypeDescription
IMAGEIMAGE