Nodes/ComfyUI-DAELab-Custom-Nodes-Library/Badge Material Canvas Normalize V1 (DAELab)
ComfyUI Node

Badge Material Canvas Normalize V1 (DAELab)

Make everything agree on the same canvas

By TeutonicMepheles·Created 4 months ago·Updated 3 days ago· 0
Badge Material Canvas Normalize V1 (DAELab)
  • base_image
  • flat_image
  • height_map
  • foreground_mask
  • normalized_flat_image
  • normalized_height_map
  • normalized_foreground_mask
  • report

What this is for

A masked edit with a paid image model has three things that must line up to the pixel: the image, the mask, and whatever structural reference you're feeding it. In a real badge graph they arrive from three different places at three different sizes - the flat artwork might be 3000×3000, the height map came out of a 1024 stage, the foreground mask was made from the render. Paste them together and the model gets a mask that's nearly right, which is the worst kind.

Badge Material Canvas Normalize V1 fixes the alignment before any money is spent. You tell it what the authoritative canvas is - the actual baked-enamel base render - and it conforms the flat art, height map and foreground mask to that exact size, nearest-neighbour, batch-aware, with a report saying what it resized from where.

It's a boring node and it exists because of one specific reason: label-bearing inputs. A height map is a discrete six-level field and a foreground mask is binary. Resize either one with bicubic interpolation and you've manufactured values - a bevel where there wasn't one, a semi-transparent edge around a hard silhouette. Nearest-neighbour can't do that.

How it works

base_image is the authority, and it must be exactly one image - the batch dimension is a hard check, because a "canvas authority" that's four different canvases isn't one. Its height and width become the target for everything else.

The other three inputs broadcast against that batch. The flat image and both masks get resized to the base canvas only if they aren't already the right size; the flat image uses nearest-exact interpolation, the masks use nearest-neighbour - the deliberate choice, and the one that makes this node worth having. The foreground mask is then binarised at 0.5 so nothing downstream has to guess whether it's soft.

Then it validates its own output: the normalised flat must be [batch, H, W, 3], the two masks must be [batch, H, W]. If either check fails you get a RuntimeError rather than a subtly wrong tensor, which is the behaviour you want in a stage that feeds a paid call.

The report string is JSON: a version number, the base canvas size, the source size of each input, the output sizes, and which ones were actually resampled. When a result looks off, that's the first thing to read - if flat_image reports a source size of 512 and an output of 1024, you now know your artwork was upscaled 2× with nearest-neighbour and will look like it.

The inputs and outputs

Four required inputs, no widgets at all: base_image, flat_image, height_map, foreground_mask. Nothing to configure, which is the correct amount of configuration for a normalisation step.

Outputs: normalized_flat_image, normalized_height_map, normalized_foreground_mask, report. Wire the three images forward into your masked edit and the report into a text/preview node if you want to see it - or into a Show Text and forget about it, which is what most people do until something looks wrong.

Install

cd ComfyUI/custom_nodes
git clone https://github.com/TeutonicMepheles/ComfyUI-DAELab-Custom-Nodes-Library.git
# restart ComfyUI

Pure PyTorch plus the pack's own helpers; no models, no extra packages. It's part of the "strict" building-block family aimed at the 8.5-era deterministic badge workflow, so if you're on 8.7 you may find the stages do this for you - check before you rebuild it manually.

Where people get burned

Batch mismatch. A base of one image and a flat artwork of four (say, four design variants) works because it broadcasts. A base of four and a flat of three doesn't, and the error names the batch - good, but it's an easy mistake when you're batching variants against a single master.

Nearest-neighbour on purpose, then complaining about it. If your flat art needs to come down from 3000px, nearest-neighbour will alias thin lines. Better: resize the artwork deliberately upstream with a proper resample, and use this node only to guarantee the sizes agree. The node's job is consistency, not quality.

Resizing the height map with a smooth filter somewhere else. The whole contract breaks if an upstream node produced a bilinear height map - you now have continuous values where the pack assumes six discrete levels, and every downstream stage (relief geometry, structure transfer) will treat those in-between values as real geometry. Keep height maps nearest all the way through.

Assuming it also fixes registration. It normalises canvas size, not position. A mask that's the right resolution but drawn on a shifted render passes straight through this node and fails later. Registration is a different node's job.

CategoryDAELab/Badge/Strict

Inputs (4)

NameTypeDefaultDescription
base_imageIMAGE—
flat_imageIMAGE—
height_mapMASK—
foreground_maskMASK—

Outputs (4)

NameTypeDescription
normalized_flat_imageIMAGE—
normalized_height_mapMASK—
normalized_foreground_maskMASK—
reportSTRING—