Image Waveform
The scope that tells you why your grade went wrong
- image
- red_waveform
- green_waveform
- blue_waveform
- rgb_parade
Everything else in ComfyUI is a node that produces pictures. This one inspects them. That makes it feel out of place in a workflow, and it's also the reason it's worth knowing about: you cannot grade what you can't measure, and eyeballing a finished render against your monitor's idea of black is how people end up exporting crushed shadows.
Image Waveform plots a broadcast-style waveform scope for each of the red, green and blue channels, plus the three side by side as an RGB parade. Each column of the plot is a column of the picture, so the display shows where in the frame the brightness sits, not just how much of it there is.
Reading it, briefly
Height is brightness, left to right is left to right in the frame. A bright sky shows as a trace parked near the top on the left; a dark foreground as a trace down at the bottom on the right. Two things become obvious immediately that no histogram can tell you.
A colour cast reads as the three traces sitting at different heights - red high and blue low means warm, and now you can see whether it's the whole frame or one corner. Clipping reads as a trace pinned flat against the top of the grid, and you can see which side of the image is doing it. Highlights that look "fine" on an OLED preview and are actually clipped in 8-bit get caught here in one glance.
Below each plot there's a statistics line: min, max, mean, deviation and median for that channel. That's your numeric answer to "is this frame darker than the last one", which matters for a sequence.
waveform_height (128 to 2048, default 512) is how finely the brightness scale is divided. 512 separates levels a 256-step scale would merge; go to 1024 when you're hunting banding, drop it for a compact scope to park on the canvas.
Inputs and outputs
One input, image, and every frame of a batch gets its own set of plots - so you can wire a whole rendered sequence in and check it for drift frame by frame rather than spot-checking the first and last.
Four outputs: red_waveform, green_waveform, blue_waveform and rgb_parade, all IMAGE type. The parade is what the node itself previews, since it's an output node. Send any of them to a Preview or Save Image node if you want the scope in the file, and note that the scope images are pictures of measurements, so they're perfectly reasonable to screenshot into a review note.
The node also inspects the batch values themselves and reports channels that leave the 0–1 range anywhere, along with which frames do it - which is the fastest way to discover that the "crushed" look you liked is actually clipped data.
When to reach for it
After a grade. Apply LUT is deterministic, so if a look came out wrong you want to know whether it clipped on the way in or shifted the whole trace up and lost your blacks. This tells you which.
Across a batch. Drop it on a sequence and compare the statistics lines between the first and last frames; if the mean has climbed, that's the drift you've been perceiving in the encodes.
Before delivering anything for print or a client. It's a ten-second sanity check that catches the one thing eyes adapt to - your own render, on your own screen, gradually normalised.
Installing it
Part of WAS Node Suite v3 - MIT, by WASasquatch, 468 nodes. Install the pack:
cd ComfyUI/custom_nodes
git clone https://github.com/WASasquatch/was-node-suite-comfyui.git
Or ComfyUI Manager, searching WAS Node Suite v3, which is the README's recommended route. ComfyUI 0.14.0+ and Python 3.10+; the pack installs no Python packages, downloads nothing and never runs pip, and this node is pure torch so there's no plotting library involved. First start after install is a second slower while it writes its config and folders under <ComfyUI user dir>/was-node-suite/. The analysis nodes live in the extras feature group - on by default - so if it's not in your menu, that setting in config.yaml is where to look rather than a reinstall.
Two neighbours worth wiring next: Apply LUT to fix what the scope just showed you, and Save LUT (.cube) to keep the table that fixed it.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | The pictures to measure. Each frame of a batch gets its own set of plots, so a sequence can be checked for drift frame by frame. | |
| waveform_height | INT | 512128–2048 | Height of the plots in pixels, which is how finely the brightness scale is divided. 512 separates levels that a 256-step scale would merge; raise it to 1024 to see fine banding, lower it for a compact on-screen scope. |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| red_waveform | IMAGE | The red channel's scope, with its own IRE grid and statistics line. |
| green_waveform | IMAGE | The green channel's scope, with its own IRE grid and statistics line. |
| blue_waveform | IMAGE | The blue channel's scope, with its own IRE grid and statistics line. |
| rgb_parade | IMAGE | All three scopes side by side under one grid, which is the view a colour cast or a channel clipping early shows up in. This is also what the node previews. |