Nodes/DNF Pixel Perfect Color Lock/DNF 原图调色板优先限色
ComfyUI Node

DNF 原图调色板优先限色

Your 64 colors, chosen by the original painting

By yifu23333·Created 11 days ago·Updated 9 days ago· 0
DNF 原图调色板优先限色
  • image
  • reference
  • final_image
  • nearest_preview
  • reference_palette
target_width256
target_height256
fit_mode
background
downscale
palette_colors
chroma_colors48
chroma_threshold0.06
dither
preview_scale4

Real pixel art isn't made by the diffusion model - it's made by the deterministic pass that runs after it: downscale, reduce to a fixed palette, and only then nearest-neighbor your way back up to a viewable size. The community has been saying this for years and it's still correct. DNFReferencePaletteFinalize is the "reduce to a fixed palette" step, with a genuinely smart twist: the palette is stolen from your original key art instead of being some generic 64-color guess, and it reserves slots for colorful pixels so a big gray background can't eat the whole budget.

Here's the mechanics. The node looks at your reference image and splits every pixel into two piles by raw chroma - how far apart its R, G and B values are (max minus min). Pixels above chroma_threshold are "chromatic", the rest are near-neutral grays. It runs Pillow's median-cut quantization separately on each pile: chroma_colors slots go to the colorful pixels, the remaining slots to the neutrals, and the two lists merge into one palette your image gets quantized against. That reservation is the whole point - naively median-cutting a character-on-gray-background painting just spends almost every slot on gray steps, and your character ends up with five colors. Here the character is protected by construction.

Inputs that matter:

  • image and reference - your generated pixel candidate and the source painting that owns the palette.
  • target_width / target_height (default 256) - the actual pixel-art resolution. This is where you downscale.
  • palette_colors (16/32/64/128/256) - your total color budget. 64 is the sweet spot for the pack's intended style.
  • chroma_colors (default 48) - how many of those slots are reserved for color. The README's default workflow keeps 48 of 64 for chroma.
  • dither - none or floyd. Floyd–Steinberg error diffusion fakes extra shades with a scattered dot pattern, which reads as classic pixel-art texture on gradients; none gives clean hard blocks.
  • background - green/gray/white/black, only visible when fit_mode: contain letterboxes your image to the target aspect.

Three outputs: final_image is the quantized result at target resolution; nearest_preview is it scaled back up preview_scale× with integer nearest-neighbor so you can actually look at it; reference_palette is a swatch grid of the exact colors used - the output to eyeball when you suspect the palette went wrong.

Where people get burned: forgetting that final_image is genuinely tiny (256×256) and Previewing it raw looks like mush - display the nearest_preview output instead, or upscale final_image yourself with nearest-neighbor only, never a smooth filter. And if your character's colors come out flat, check whether chroma_colors is high enough and chroma_threshold isn't wrongly classifying the subject's mid-saturation tones as neutral.

Install is painless: ComfyUI Manager → search DNF Pixel Perfect Color Lock (registry dnf-pixel-perfect), or

cd ComfyUI/custom_nodes
git clone https://github.com/yifu23333/ComfyUI-DNF-ColorLock

then restart. It has zero external dependencies beyond NumPy/Pillow/torch and downloads no models - everything runs on CPU-side image math in seconds. Find it under DNF/Color Lock. It's the node you wire between your generated art and the final sprite sheet, and it's the reason the whole pack works: a palette the source painting chose, rather than one a generic quantizer invented.

CategoryDNF/Color Lock

Inputs (12)

NameTypeDefaultDescription
imageIMAGE
referenceIMAGE
target_widthINT25616–2048
target_heightINT25616–2048
fit_modeCOMBO2 options: contain, stretch
backgroundCOMBO4 options: green, gray, white, black
downscaleCOMBO2 options: nearest, lanczos
palette_colorsCOMBO5 options: 16, 32, 64, 128, 256
chroma_colorsINT481–255
chroma_thresholdFLOAT0.060–1
ditherCOMBO2 options: none, floyd
preview_scaleINT41–16

Outputs (3)

NameTypeDescription
final_imageIMAGE
nearest_previewIMAGE
reference_paletteIMAGE