Image math
Per-pixel image math, written as one expression
- a
- b
- c
- d
- IMAGE
Image math runs a math expression over every pixel of up to four images at once. The default expression, a*(1-w)+b*w, is a weighted blend - which means this single node replaces the "Image Blend" node you'd otherwise add, with the bonus that you can write a*b, abs(a-b), 1-a, or whatever your effect actually needs instead of hunting for a node that does it. It's the same idea as WAS Node Suite's image math, delivered as a programmable expression rather than a fixed set of blend modes.
How it works
In ComfyUI an image is a (batch, height, width, channel) float tensor, values 0–1. This node evaluates your expression elementwise on that tensor. The expression language gives you more than the four inputs: inside it you have a, b, c, d (the images), w, x, y, z (float sliders), and positional variables - X/Y (pixel coordinates), W/H (dimensions), C (channel), B (batch), T/N (batch count / channel count). So you can build gradients from coordinates, or grade a single color channel with C.
The function library extends into image territory too: blur, edge, dilate, erode, morph_open, morph_close are all callable inside the expression, so feathering or a quick edge pass doesn't need a separate filter node.
The inputs that matter
a- required image.b,c,doptional.Image- the expression. Defaulta*(1-w)+b*w.length_mismatch- how to handle different batch sizes:tile(repeat),error(default, fail loudly),pad(zero-fill).w,x,y,z- the float knobs your expression uses.
Output is a single IMAGE.
Installing it
Part of More Math (mcDandy/more_math). Fastest: ComfyUI Manager, search "More Math". Or:
cd ComfyUI/custom_nodes
git clone https://github.com/mcDandy/more_math
cd more_math
pip install -r requirements.txt
Then restart. Dependencies are antlr4-python3-runtime and torch - no model files. The pack uses ComfyUI's newer node API, so keep ComfyUI updated or the nodes simply won't register.
Where people get burned
The big one: pixel values must stay in 0–1. Write a+b on two full-brightness images and you get blown-out whites because 1+1=2, and a viewer will clip or just show you garbage. Wrap it: clamp(a+b, 0, 1). clamp is your friend here, and a * for intersection or a 1-a for inversion are the operations you'll use most.
Second, length_mismatch defaults to error. Feeding images with different batch counts (say a 1-frame image against a 24-frame batch) throws a ValueError instead of silently doing something weird - which is good, but you'll hit it the first time you wire a single reference image into a video expression. Switch to tile when you mean "repeat this one across the batch."
Also note: like most of the pack's per-type math nodes, the classic form here is deprecated in favor of an autogrow variant with the same "Image math" display name. Both ship and both work; the newer one just takes more image inputs. If you're writing a new workflow and see two "Image math" entries in the menu, the autogrow one is the future-proof pick.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| a | IMAGE | — | |
| Image | STRING | a*(1-w)+b*w | Expression to apply on input images |
| length_mismatch | COMBO | error | How to handle mismatched image batch sizes. tile: repeat shorter inputs; error: raise error on mismatch; pad: treat missing frames as zero. |
| bopt | IMAGE | — | |
| copt | IMAGE | — | |
| dopt | IMAGE | — | |
| wopt | FLOAT | 0.00 | — |
| xopt | FLOAT | 0.00 | — |
| yopt | FLOAT | 0.00 | — |
| zopt | FLOAT | 0.00 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |