Badge Studio Color Lock V1 (DAELab)
The free, boring step that makes it look expensive
- editable_master
- studio_candidate
- flat_image
- foreground_mask
- presentation_image
- color_locked_badge
- subject_geometry_max_diff
- report
Here's the thing about generative product photography: the model gives you a gorgeous light on your object, and then quietly repaints the object. The metal comes back twenty points too warm. The enamel's chroma drifts. On a single fun image nobody notices. On a catalogue of two hundred badges with a brand palette, it's the whole problem.
Badge Studio Color Lock V1 is the deterministic answer, and it's my favourite node in this pack for a simple reason: it does no generation at all. It's free, instant, and completely repeatable, and it's the difference between "AI product shot" and "render".
What it computes
Three inputs carry the information: editable_master (your badge, ideally after the local edits, with its geometry and texture intact), studio_candidate (the GPT output with the generated background), and flat_image (the untouched flat artwork - the colour authority). Plus foreground_mask.
Both master and flat artwork get converted to OKLab. That's the right space for this because its chroma axes are roughly perceptually uniform - moving a colour along them toward a reference is a much better-behaved "pull the hue back" than doing arithmetic in sRGB.
The foreground's chroma is then interpolated toward the flat artwork's chroma by color_lock_strength (default 0.65). Lightness is not touched, so every bit of shading, bevel highlight and surface texture that the generative step produced survives. Only the colour axis gets pulled home.
Then the studio composite: outside the foreground, take studio_candidate; inside it, take the colour-locked master. The geometry of the subject is reinserted exactly - not warped, not blended, not resized. The report literally calls this policy editable_master_foreground_reinserted_exactly_after_chroma_lock, and subject_geometry_max_diff should come back 0.0 when the compositing did what it claims.
The dial nobody expects: neutral material protection
neutral_material_protection (default 0.75) is the clever bit, and the reason this node isn't just a saturation lerp. Silver and gold metals, and neutral greys generally, have almost no chroma to lock. If you apply full colour lock to them you drag them toward whatever faint tint your flat artwork happened to have, and the brushed silver goes slightly mauve.
So the node measures the flat artwork's local chroma; below a threshold (0.08 in OKLab terms) it scales the lock effect down. At 0.75, a fully neutral region keeps only a quarter of the lock strength. Raise it toward 1.0 if your metals are drifting; lower it if your skin-tone-ish enamels aren't coming back far enough.
color_lock_strength at 0.65 pulls most of the drift out without going flat. Push it to 1.0 and the badge's colour is effectively the artwork's colour - maximum brand fidelity, minimum "photographed" feel. Below 0.4 you're mostly trusting the model. 0.6–0.8 is the useful band.
Outputs
presentation_image- the finished composition: locked badge over the generated studio background. This is your deliverable.color_locked_badge- the foreground-only locked subject, still on the transparent/zeroed surroundings. Useful when you want to composite onto a different background or drop it into a template.subject_geometry_max_diff- a FLOAT, should be exactly 0.0. If it's not, the "geometry is preserved" promise has failed and you should suspect a shape mismatch upstream.report- JSON with the colour space, both strengths used, and the policy flags. Cheap to log, handy when a colleague asks why the badge looks different from the source.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/TeutonicMepheles/ComfyUI-DAELab-Custom-Nodes-Library.git
Restart ComfyUI, refresh the browser tab. It's registered under DAELab/Badge/PP; ComfyUI Manager users can find it by searching the pack title. Because it's pure tensor maths, installing it costs you nothing to experiment with - no credits, no model downloads, no API key.
Gotchas
All four inputs must share identical batch and canvas dimensions. The node raises rather than broadcasting a 1024 base onto a 512 mask, and it's right to. If you're getting that error, the usual culprit is a candidate from a differently-sized GPT call - the pack's canvas normaliser exists for exactly that.
Feed it a foreground mask with a little margin, not a razor-thin silhouette. The composite is a hard swap at 0.5, so a mask that's off by a pixel shows as a one-pixel halo of the old background around the badge. The studio-background node's protection_px is the tool for that; use both.
And resist the urge to use this as a general colour-grading node. It's not a saturation slider - it pulls chroma toward this specific flat artwork, which is why it works. Run it on an image with no corresponding flat reference and you'll get a slow drift to muddy.
Finally: it needs a real generative candidate to be worth running. If you skip the studio-background step, the "outside foreground" pixels come from whatever studio_candidate you wired in, and if that's the master itself you've built an expensive no-op.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| editable_master | IMAGE | — | |
| studio_candidate | IMAGE | — | |
| flat_image | IMAGE | — | |
| foreground_mask | MASK | — | |
| color_lock_strength | FLOAT | 0.650–1 | — |
| neutral_material_protection | FLOAT | 0.750–1 | — |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| presentation_image | IMAGE | — |
| color_locked_badge | IMAGE | — |
| subject_geometry_max_diff | FLOAT | — |
| report | STRING | — |