Audit-driven correctness pass over the whole node.
Crashes:
- Masks are resized and clamped to the image instead of raising a
RuntimeError when resolutions differ (e.g. a mask made before an upscale).
- RGBA input is handled; alpha is split off before lighting and passed
through untouched.
Correctness:
- Occlusion and compositing are computed per batch item. Every frame
previously reused the first image's mask, silently wrong for video.
- The mask output is always the normalised (batch, height, width) mask. It
returned black when both mask consumers were off, and echoed the input's
rank otherwise.
- Colour correction runs in float32 on-device rather than round-tripping
through uint8 PIL. Identity settings shifted pixels by 1/255 and the error
compounded across lights and chained nodes; blending now works on deltas so
a no-op correction is bit-exact.
- Mask blurring moved to a separable float convolution, removing banding and
a device round-trip per light.
- effect_strength scales gamma, so 0.0 is a true no-op.
- remove_background is honoured when apply_3d_lighting is off.
Behaviour changes:
- remove_background defaults off; it silently confined all lighting to the
subject whenever a mask was connected.
- preserve_positioning defaults off, so presets apply their own geometry.
- Preset gamma values corrected. Gamma follows the Photoshop/ImageMagick
convention where >1 brightens, but presets paired dimmed outer zones with
gamma above 1.0, undoing their own shading.
Packaging and docs:
- Secondary inputs marked advanced where ComfyUI supports it, feature-detected
so older builds still load. Input order unchanged.
- Declares requires-comfyui >=0.3.48; missing comfy_api gives a readable error.
- Example workflow moved to example_workflows/.
- Test suite with a comfy_api stub, plus lint and test CI.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BoCXQ1LeDc9ArKMWVAiwyC