Pixel Art
Real dithering, real palettes, in your graph
- image
- palette
- IMAGE
Most "pixelate" nodes in ComfyUI are a lie - they just blur the image into big squares and call it a day. This one actually quantizes. The Pixel Art node in TrophiHunter's Photography Nodes pack does the real thing: it downsamples, builds a color palette from your image (or from a swatch file you feed it), then dithers the result so the limited colors blend into something that reads as intentional art instead of a crushed JPEG. If you've ever wanted a batch of generated images converted into game-asset sprites or a retro avatar set, this is the node you're looking for, and it's the most-searched node in the pack for a reason.
How it works
The pipeline is classic pixel-art quantization, done properly. The image gets divided down by scale (higher = chunkier pixels), optionally saturation-boosted beforehand, then a palette of num_colors is extracted. The trick is how the palette is made - that's palette_mode. "adaptive" builds a palette from your image's actual colors, "median_cut" is the classic box-splitting algorithm, "perceptual" tries to pick colors a human would agree matter, "uniform" gives you a fixed grid of colors, and "consolidate" merges similar colors down.
Then the dithering. The three big options:
- none - hard quantize, flat and clean
- floyd - Floyd–Steinberg error diffusion, the classic for smooth gradients.
floyd_dither_serpentinescans in alternating directions to cut the directional streaks, andfloyd_dither_threshold_jitterbreaks up banding in flat areas - ordered / noise / pattern - Bayer-matrix dithering (
matrix_size2–32,matrix_expand_negativewidens the threshold range for bigger palettes) and friends
If you pass a palette image in, the author's one requirement matters: every pixel must be a unique color, so 4x1 or 2x2 swatches are fine. That's how you force a specific 4-color Game Boy palette instead of trusting the algorithm.
Inputs that matter
- scale - your main dial. 1 is no downsampling, 2+ starts the pixel crunch
- num_colors - palette size, 1–256. Note the author's honest caveat: some palette modes ignore the exact number when it's very high
- palette_mode - "adaptive" is the safe default; reach for "median_cut" when gradients are banding
- dither + dither_strength - where 90% of the "wow, that looks good" difference lives
- palette_filepath - path to a
.ase,.aco, or.actswatch file. This is the Photoshop-import path, and it's the secret to consistent branding across a whole batch
Output is a single IMAGE, ready to wire into Save Image or upscale afterward.
Install
Install the pack once - every node in it rides the same dependency train, and this one has no special extras:
cd ComfyUI/custom_nodes
git clone https://github.com/TrophiHunter/ComfyUI_Photography_Nodes
Restart ComfyUI and you'll find everything under TrophiHunter/Photography in the node menu. ComfyUI Manager can do it too - search "Photography Nodes" (the pack title is "ComfyUI_Photography_Nodes"). The whole pack is pure torch/PIL/numpy with no requirements.txt, so there's nothing extra to pip install.
Where people get burned
The palette image gotcha above is the big one - a full-color photo as your palette input gives you garbage, because it expects one pixel per color. The other classic mistake: cranking scale to 16+ and then wondering why faces turn into noise. Pixel art reads better at moderate downsampling with strong dithering than at extreme downsampling with none. And if a swatch file isn't loading, double-check the path has no leading/trailing quotes. The node handles .ase, .aco, and .act - Photoshop, Illustrator, and the old Adobe color formats - so anything you've exported from a design tool should just work.
Inputs (13)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| scale | INT | 21–128 | — |
| num_colors | INT | 41–256 | — |
| saturation | FLOAT | 1.000.8–3 | — |
| dither | COMBO | none | 5 options: none, floyd, noise, ordered, pattern |
| matrix_size | COMBO | 4 | 5 options: 2, 4, 8, 16, 32 |
| palette_mode | COMBO | none | 6 options: none, adaptive, median_cut, perceptual, uniform, consolidate |
| dither_strength | FLOAT | 1.000–10 | — |
| matrix_expand_negative | BOOLEAN | true | — |
| floyd_dither_serpentine | BOOLEAN | false | — |
| floyd_dither_threshold_jitter | BOOLEAN | false | — |
| palette_filepath | STRING | — | |
| paletteopt | IMAGE | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |