CMK Image Compare
Press and Hold to See What Your Edit Actually Did
- image_a
- image_b
- image
Every before/after judgement in this hobby is unreliable, because you look at the after, then try to remember the before. A slider or a hold-to-compare isn't a luxury feature - it's the difference between "I think that's better" and "that is better".
What it is
A dependency-free two-image preview that ships inside CMK's published flows. It takes image_a and image_b, both optional, and does two things at once: it returns one of them as a usable output, and it publishes both to the frontend as a comparison pair.
The frontend half is the point. It writes both descriptors into the standard images UI field and into a cmk_compare_images field, which is what the surrounding subgraph reads to offer the press-and-hold comparison in the node UI. Both get pushed through ComfyUI's preview path, so they land in the temp preview area like any other preview.
Which image comes back
There's a convention here and it's worth getting right, because it's easy to wire backwards. The pack's flows consistently connect the processed result to A and the unprocessed source to B. So the returned image is A when A exists, falling back to B, and ultimately to a 64×64 black tensor if neither input is connected.
That last fallback exists so the node can never break a graph by being unconnected - it always produces something. It also means a mis-wired compare gives you a small black square instead of a crash, which is the sort of thing you notice immediately (good) rather than at the end of a long run (bad).
Only the first frame of each input is previewed. Batches are truncated to frame 0 for the comparison, while the returned output carries whatever you passed in.
Why it exists at all
Because the pack would otherwise need Impact Pack for a preview. CMK's stated design goal is a clean install with no chain of unrelated custom-node dependencies, and the core detection, SEGS, detailer, paste-back and face-process nodes are dependency-free by design. A comparer is a small enough thing to write than to depend on. If you've ever audited a workflow and found it needed four packs to display two images next to each other, that'll land.
The node is also marked as an output node in the graph sense, which has a real consequence: ComfyUI's cache works backward from output nodes, and output nodes always execute. So dropping this into a graph makes everything upstream of it run every time. That's what you want for a comparison - and it's also why you shouldn't leave a stray one wired in behind an expensive branch if you're trying to benefit from the cache.
When you'd reach for it
Judging a post-process. A face swap, a restore pass, a detailer run - all of them are subtle enough that you can't evaluate them from memory. Two images side by side is the only honest test.
Checking a swap did anything. Paired with a <input> from the source, the hold-compare is how you catch the case where the module silently passed the target through.
Sharing a result. A before/after is a much more useful post than a finished image, and this gives you the pair without leaving ComfyUI.
Install
Manager: search CMK Flow, install the CMKFlow entry, restart. Manually, from your ComfyUI root:
git clone https://github.com/CMKFlow/cmk_nodes.git custom_nodes/cmk_nodes
python3 custom_nodes/cmk_nodes/scripts/install_cmk_requirements.py
python3 custom_nodes/cmk_nodes/scripts/check_cmk_resources.py --models-root "/path/to/ComfyUI-Shared"
This node needs no models and no extra Python packages - it's a preview utility - so it's a clean way to confirm the pack registered. If it works and the swap nodes don't, your problem is a weight file or insightface, not the install. Do run the resource check anyway for the pack as a whole: the Python dependencies deliberately exclude model weights, and the checker reports each required file as FOUND or MISSING with its intended use.
One pack-level requirement: CMK expects ComfyUI's Nodes 2.0 / Vue frontend setting to be on and warns at startup when it isn't. Preview behaviour and the dynamic node rendering both degrade without it.
Gotchas
The convention - result in A, source in B - is not enforced. Wire them the other way and the comparison still renders, just with the labels the wrong way round in your head, which is a genuinely confusing five minutes.
And remember previews go to ComfyUI/temp/, which is a scratch directory. This node is for looking at things, not keeping them. If a comparison produced something you want, that's what the save path is for.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| image_aopt | IMAGE | — | |
| image_bopt | IMAGE | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |