Safe Chunked Image Blend
The blend node that stops silently cooking your CPU
- image1
- image2
- IMAGE
You've got a 4K upscale on one branch and the original on the other, you hit that blend node, and suddenly your CPU fan sounds like a jet engine - or worse, ComfyUI just wedges. Safe Chunked Image Blend is a small pack written for that moment: a replacement-style ImageBlend for large, batched tensors that makes the resize-and-device dance explicit instead of letting some hidden path decide it.
The problem it attacks is real. ComfyUI image tensors usually arrive at post-processing nodes as CPU float32. A lot of blend nodes follow the device of the first input, so if image1 is on CPU, the resize and the blend happen on CPU too - and if the two inputs have different spatial sizes, some of them silently resize one to match the other first. For a (2, 5464, 3800, 3) upscaled batch against a half-res original, that's a full-batch CPU resize you never asked for, and on WSL setups it can freeze hard enough to wedge the whole thing. The author hit this in exactly those upscale/video workflows and built the fix (released r/StableDiffusion, May 2026).
How it works
The node takes two IMAGE tensors, validates them, and processes them in chunks instead of one giant operation. Per chunk it moves the frames to your chosen device, resizes the mismatched input explicitly, blends, clamps to [0,1], and copies the finished chunk into a preallocated output buffer. No concatenating big temporary chunks, no surprise full-batch resize. The CUDA path uses torch's F.interpolate; if you force CPU, resize runs through OpenCV.
The inputs that actually matter
resize_policy- the star of the show. Default iserror_if_mismatch, which just throws if the sizes differ. That's a feature: it catches accidental mismatches instead of papering over them. The other two areresize_image2_to_image1(upscale the smaller branch to match - the usual case) andresize_image1_to_image2(when you deliberately want to match the second input).compute_device-cuda,cpu,image1, orimage2. Defaultcuda, and it will raise if CUDA isn't available, which is honest behavior for a node built to escape CPU-bound resizes.chunk_size- frames per chunk,1to16. Default1. For the big-resize case, leave it at 1.blend_factor- 0.0 keepsimage1, 1.0 fully replaces it with the blended result. Default 0.35.blend_mode- normal, multiply, screen, add, subtract, difference, darken, lighten.log_progress- prints per-step logs so you can see exactly where a hang happens.
The single output is a normal IMAGE tensor. By default output_cpu_float32 is on, so you get back the standard CPU float32 tensor every save/preview node expects - turn it off only if the next node genuinely wants CUDA.
The author's recommended starting settings for a big upscale blend:
resize_policy = resize_image2_to_image1
resize_method = bilinear
chunk_size = 1
compute_device = cuda
output_cpu_float32 = true
synchronize_each_chunk = true
empty_cuda_cache_each_chunk = false
log_progress = true
Start with bilinear. bicubic is heavier; only switch once the workflow runs clean.
Installing it
ComfyUI Manager has it - search "Safe Chunked Image Blend". Or clone it yourself:
cd ComfyUI/custom_nodes
git clone https://github.com/xmarre/ComfyUI-Safe-Chunked-Image-Blend
Restart ComfyUI. No model downloads. The only dependencies are numpy and opencv-python-headless (declared in pyproject.toml), and cv2 is only touched on the CPU resize path - the code imports it lazily, so a pure-CUDA workflow runs fine without it. Worth knowing: the README's own install block still has a placeholder YOUR_USERNAME URL, so trust the repo link above.
Where people get burned
- The default throws. If you wire two mismatched images in and get "Spatial mismatch", that's the node doing its job - read the error, pick a resize policy. It even tells you which policy fixes it.
- CPU resize needs cv2. If you set
compute_device=cpuwith mismatched sizes and it errors about OpenCV,pip install opencv-python-headlessand restart. - Batches must match. It won't repeat, truncate, or align frames for you; a
(3, ...)against(2, ...)is an error, not a silent fix. - Chunks can still OOM. chunking helps a lot, but a giant frame with
bicubicon a tight card can still blow up. That's whatsynchronize_each_chunkandempty_cuda_cache_each_chunkare for when debugging.
Honest take: for a 1MP normal blend, the stock nodes are fine and this is overkill. Where it earns its keep is 4K+ batches and video frames, where one hidden CPU resize is the difference between finishing and cooking your RAM. Niche, but it fixes a genuinely miserable failure mode.
Inputs (12)
| Name | Type | Default | Description |
|---|---|---|---|
| image1 | IMAGE | — | |
| image2 | IMAGE | — | |
| blend_factor | FLOAT | 0.350–1 | — |
| blend_mode | COMBO | normal | 8 options: normal, multiply, screen, add, subtract, difference, +2 |
| resize_policy | COMBO | error_if_mismatch | 3 options: error_if_mismatch, resize_image2_to_image1, resize_image1_to_image2 |
| resize_method | COMBO | bilinear | 4 options: bilinear, bicubic, nearest, area |
| chunk_size | INT | 11–16 | — |
| compute_device | COMBO | cuda | 4 options: cuda, cpu, image1, image2 |
| output_cpu_float32 | BOOLEAN | true | — |
| synchronize_each_chunk | BOOLEAN | true | — |
| empty_cuda_cache_each_chunk | BOOLEAN | false | — |
| log_progress | BOOLEAN | true | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |