Smart Image Quantize
ComfyUI's ImageQuantize keeps wrecking your palette — Smart Image Quantize is the fix
- image
- palette_image
- image
- palette
Cranking an image down to a handful of colors sounds like the easiest job in ComfyUI. You drop the built-in ImageQuantize on, type "32", and get back... mud. The vivid red stays roughly right, the bright highlights go brown, and anything saturated but rare vanishes entirely. That's the failure mode this node exists to fix. Smart Image Quantize is a color-count reduction that treats the palette as something worth curating: it keeps prominent colors, protects the hues you actually care about, and reserves slots for bright neutral highlights instead of letting them wash out. Same job as the stock node, one level of thought applied.
How it's smarter
Where the stock node does a single blunt color-count pass, this one works in stages. It converts the image to CIELAB - a perceptual color space where "distance" between colors roughly matches how different they look, not just how different their RGB numbers are - and buckets every pixel into coarse Lab bins. Each bin gets scored by frequency, coverage area, saturation, and local contrast, so a small but punchy detail beats a large boring one. That score sheet drives everything downstream.
The palette build itself is hybrid. A base palette comes from a plain Pillow quantize, and then three curated groups get injected into it: up to two priority hues you pick by name, accent colors (vivid, contrasty pixels that ordinary quantization drops), and neutral highlights (the low-saturation brights that flatten into gray if nobody's watching). Injected candidates have to stay min_dist apart in Lab, so you don't burn five slots on near-identical reds. The image is then remapped to the finished palette with none, floyd-steinberg, or ordered Bayer 2–16 dithering.
The inputs that matter
- colors - 2–256, default 32. Your actual target palette size.
- accent_hue_priority and accent_hue_2nd_priority -
none,red,yellow,green,blue,purple. This is the whole point of the node: tell it which hue must survive the cull. - accent_colors (0–1) - what fraction of palette space goes to vivid accents; neutral_highlights (0–0.3) reserves room for bright near-neutral tones.
- dither - start with
floyd-steinbergonce you're below ~32 colors; ordered Bayer gives a cleaner retro stipple. - palette_image + palette_fill_mode - optional.
strictuses only the colors in your swatch image;extendkeeps those and fills the rest from the input.
It outputs the quantized image plus a palette - a 256×256 swatch sheet you can preview or save as a reference. Nice touch: in strict mode one shared palette is used for the whole batch, which keeps sprite sheets and image sequences color-consistent.
Where it fits
This is the deterministic palette-quantize step in the pixel-art pipeline, and the community consensus is worth internalizing: the neural model gives you the composition, a deterministic pass like this gives you the actual pixels - nobody sane expects a diffusion model to produce a clean limited palette on its own. Reach for it for pixel art, game assets, retro posters, or any time you want a deliberate limited-color look rather than an accidental one.
Install
Zero friction. ComfyUI Manager → search comfyui_smart_image_quantize (or "Smart Image Quantize") → Install, restart. Or:
cd ComfyUI/custom_nodes
git clone https://github.com/palealloy2999-prog/comfyui_smart_image_quantize.git
Then restart ComfyUI. No model files, no GPU, and its dependency list is genuinely empty - it runs on the numpy/torch/Pillow ComfyUI already ships, so the README's "just clone it" is honest.
Gotchas
Feed palette_image an actual swatch strip, not a photo. In strict mode the output can only contain colors from that image, so a busy reference photo gives you a palette full of noise instead of your five brand colors. And if the quantized result looks muddy at very low color counts, that's usually dithering being off - few colors plus no dither means banding, so add Floyd-Steinberg before you start blaming the node. A brand-new solo pack like this one is light on battle-tested community wisdom, so expect to tune accent_colors and neutral_highlights by eye; the palette preview output makes that iteration fast.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| colors | INT | 322–256 | — |
| accent_colors | FLOAT | 0.500–1 | — |
| accent_hue_priority | COMBO | none | 6 options: none, red, yellow, green, blue, purple |
| accent_hue_2nd_priority | COMBO | none | 6 options: none, red, yellow, green, blue, purple |
| neutral_highlights | FLOAT | 0.050–0.3 | — |
| min_dist | FLOAT | 8.00–20 | — |
| dither | COMBO | none | 6 options: none, floyd-steinberg, bayer-2, bayer-4, bayer-8, bayer-16 |
| palette_fill_mode | COMBO | strict | 2 options: strict, extend |
| palette_imageopt | IMAGE | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| palette | IMAGE | — |