Files
EnragedAntelope-comfyui-rel…/example_workflows/relight_basic.json
T
Claude 47c08afe60 v3.0.0: fix crashes, batch masks, and 8-bit precision loss; add tests
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
2026-07-24 21:16:49 +00:00

383 lines
6.1 KiB
JSON

{
"id": "deca62b2-6f4f-4720-bdc5-7d23c2f67b5b",
"revision": 0,
"last_node_id": 41,
"last_link_id": 149,
"nodes": [
{
"id": 2,
"type": "LoadImage",
"pos": [
-239.72842407226562,
-95.34012603759766
],
"size": [
315,
314
],
"flags": {},
"order": 0,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": [
32,
144
]
},
{
"name": "MASK",
"type": "MASK",
"links": null
}
],
"properties": {
"Node name for S&R": "LoadImage"
},
"widgets_values": [
"flux1DevFp8_v10_Ossum_Possum_679077792491536.png",
"image",
""
]
},
{
"id": 14,
"type": "MaskPreview+",
"pos": [
568.0902099609375,
204.9829864501953
],
"size": [
352.767822265625,
300.72760009765625
],
"flags": {},
"order": 5,
"mode": 0,
"inputs": [
{
"name": "mask",
"type": "MASK",
"link": 147
}
],
"outputs": [],
"properties": {
"Node name for S&R": "MaskPreview+"
},
"widgets_values": [
""
]
},
{
"id": 10,
"type": "PreviewImage",
"pos": [
582.1401977539062,
563.9623413085938
],
"size": [
329.576171875,
338.90484619140625
],
"flags": {},
"order": 6,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 148
}
],
"outputs": [],
"properties": {
"Node name for S&R": "PreviewImage"
},
"widgets_values": [
""
]
},
{
"id": 41,
"type": "SaveImage",
"pos": [
595.3690795898438,
-111.95968627929688
],
"size": [
315,
270
],
"flags": {},
"order": 4,
"mode": 0,
"inputs": [
{
"name": "images",
"type": "IMAGE",
"link": 149
}
],
"outputs": [],
"properties": {},
"widgets_values": [
"Relight",
""
]
},
{
"id": 16,
"type": "ImageRemoveBackground+",
"pos": [
-267.90655517578125,
340.4074401855469
],
"size": [
327.5999755859375,
46
],
"flags": {},
"order": 2,
"mode": 0,
"inputs": [
{
"name": "rembg_session",
"type": "REMBG_SESSION",
"link": 31
},
{
"name": "image",
"type": "IMAGE",
"link": 32
}
],
"outputs": [
{
"name": "IMAGE",
"type": "IMAGE",
"links": []
},
{
"name": "MASK",
"type": "MASK",
"links": [
145
]
}
],
"properties": {
"Node name for S&R": "ImageRemoveBackground+"
},
"widgets_values": []
},
{
"id": 8,
"type": "RemBGSession+",
"pos": [
-607.244140625,
341.5400695800781
],
"size": [
315,
82
],
"flags": {},
"order": 1,
"mode": 0,
"inputs": [],
"outputs": [
{
"name": "REMBG_SESSION",
"type": "REMBG_SESSION",
"links": [
31
]
}
],
"properties": {
"Node name for S&R": "RemBGSession+"
},
"widgets_values": [
"isnet-general-use: general purpose",
"CPU"
]
},
{
"id": 40,
"type": "ReLight",
"pos": [
143.11851501464844,
-21.831321716308594
],
"size": [
317.4000244140625,
1226
],
"flags": {},
"order": 3,
"mode": 0,
"inputs": [
{
"name": "image",
"type": "IMAGE",
"link": 144
},
{
"name": "mask",
"type": "MASK",
"link": 145
}
],
"outputs": [
{
"name": "image",
"type": "IMAGE",
"links": [
149
]
},
{
"name": "mask",
"type": "MASK",
"links": [
147
]
},
{
"name": "debug_image",
"type": "IMAGE",
"links": [
148
]
}
],
"properties": {
"Node name for S&R": "ReLight"
},
"widgets_values": [
"Warm Sunset Glow",
1,
true,
true,
false,
false,
true,
"Behind Subject",
true,
1,
50,
2,
0.26000000000000006,
0.31000000000000005,
0.4,
0.7,
255,
255,
255,
1,
10,
5,
5,
0,
0,
1,
-10,
0,
-10,
0,
0,
1.1,
0.8,
0.2,
0.3,
0.6,
180,
180,
255,
0.7,
0.3,
0.8,
0.25,
0.5,
255,
150,
120,
0.5
]
}
],
"links": [
[
31,
8,
0,
16,
0,
"REMBG_SESSION"
],
[
32,
2,
0,
16,
1,
"IMAGE"
],
[
144,
2,
0,
40,
0,
"IMAGE"
],
[
145,
16,
1,
40,
1,
"MASK"
],
[
147,
40,
1,
14,
0,
"MASK"
],
[
148,
40,
2,
10,
0,
"IMAGE"
],
[
149,
40,
0,
41,
0,
"IMAGE"
]
],
"groups": [],
"config": {},
"extra": {
"ds": {
"scale": 0.7627768444385813,
"offset": [
1799.079848930125,
266.1060250604858
]
}
},
"version": 0.4
}