Comparison Gate
Make before/after images arrive at the same moment, every run
- source_image
- image_a
- image_b
- image_c
- final_image
- source_image
If you've ever tried to A/B two versions of a render, you know the frustration: the two branches finish at different times, the save nodes write them in random order, and the side-by-side comparison you wanted comes out with the new version on top of yesterday's file. ComparisonGate is the pack's answer to that - a tiny rendezvous point that holds whatever arrives until a source image and at least one comparison image are both present, then lets them through together.
It has four optional image inputs - source_image, image_a, image_b, and image_c - and two outputs: final_image and source_image. The logic is simple: the first comparison input (image_a/b/c) that actually has data becomes final_image, and source_image passes through to the other output. If either side is still missing, it returns nothing rather than erroring - the code literally mirrors the behavior of an unplugged preview widget, so your graph keeps running while it waits. That's the "pauses the workflow until both are ready" behavior from the README, and it's why this node feels like glue instead of a real stage.
What you're actually getting is determinism. On a batch, final_image is always the first ready comparison, source_image is the designated reference, and both pop out of the pipeline in the same execution so your downstream saver or comparison view gets them in lockstep. Pair it with SimpleImageSaver or a side-by-side preview and your QA pass stops being a game of "which file is the new one."
Install
Standard PortraitUtils install - Manager → search "PortraitUtils", or:
cd ComfyUI/custom_nodes
git clone https://github.com/heyburns/PortraitUtils
Restart. No dependencies beyond what the pack already pulls in.
Common issues
- Outputs are empty / node returns nothing - that's by design while one side hasn't fired yet. It's not broken; it's waiting. Check that both branches actually reach it.
- Only one of
image_a/b/cis connected - the gate only needs one, so the second and third inputs are genuinely optional. Use them only when you're comparing three candidates. - You expected the gate to pick the better image - it doesn't judge, it synchronizes. Comparison is still your job; this just makes the timing sane.
It's a small node, but it quietly removes one of the most annoying failure modes in iterative work: comparing two runs when the files were saved seconds apart and you can't trust the ordering. If you do before/after passes at all, this is the one that'll earn its place in the graph.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| source_imageopt | IMAGE | — | |
| image_aopt | IMAGE | — | |
| image_bopt | IMAGE | — | |
| image_copt | IMAGE | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| final_image | IMAGE | — |
| source_image | IMAGE | — |