Create Morph Image
Crossfade two images into a GIF
- image_a
- image_b
- image_a_pass
- image_b_pass
- filepath_text
- filename_text
Give it two images and it spits out an animated GIF (or APNG) that fades from the first into the second. That's the whole pitch, and it's a fun one. Create Morph Image is the quick way to turn a before/after pair into a little looping transition without opening a video editor.
Set expectations first, because the name oversells it slightly: this is a crossfade, not a real morph. It doesn't warp features or track landmarks the way morphing software from the 90s did - it blends the two frames' pixels over a sequence of steps. Feed it two wildly different compositions and you get a ghostly dissolve, not a smooth face-melt. Feed it two images that share a layout - same subject, different style, or two steps of an edit - and it looks genuinely slick.
How it works
The node interpolates between image A and image B across a number of in-between frames, writing each blended frame into an animated file. You control roughly two things: how many frames it generates (more frames = smoother, longer, bigger file) and how long each frame is held (the timing). It assembles those into a GIF or APNG and saves it to your output folder, which makes this an output node - the file lands on disk when the graph runs.
Because it's pixel blending, the two inputs really should be the same dimensions. Mismatched sizes are where the results get ugly.
Inputs and outputs that matter
The two inputs that matter are simply the two IMAGE inputs - the start frame and the end frame. Beyond that you're setting the frame count and the per-frame duration to trade smoothness against file size and speed. The node produces the animation file directly; it's a terminal "save"-style node rather than something you chain deeper into a graph.
If you want to build the transition from more than two stills, its sibling Create Morph Image by Path does the same thing across a whole directory of images, fading through them in sequence. Reach for that when you've got a series rather than a pair.
How to install it
ComfyUI Manager: search was-node-suite-comfyui, install, restart. Manually:
cd ComfyUI/custom_nodes
git clone https://github.com/WASasquatch/was-node-suite-comfyui
then install the pack's requirements.txt in your ComfyUI venv (or the python_embeded route on portable) and restart. GIF/APNG writing leans on Pillow, which comes along with the pack's requirements, so there's no separate FFmpeg install needed for this one - that's only the WAS video nodes, which are a different, Windows-oriented story.
Common issues & troubleshooting
The morph is a muddy cross-dissolve, not a clean transition. That's the tool being honest about what it is. It blends pixels; it doesn't warp geometry. To make it look like a real morph, feed it two images that are already aligned - same framing, same subject position - so the blend has something coherent to move through.
The output looks jerky. Too few in-between frames. Bump the frame count up for a smoother fade; the trade is a larger file and a slightly longer run.
The file is enormous. GIF is not an efficient format and frame count multiplies it fast. Keep the resolution modest and the frame count reasonable, or accept that a smooth high-res morph GIF is going to be a chunky file by nature.
Nothing shows up / it errors on save. Check the two inputs are the same size and are actual IMAGE tensors. And remember this is the WAS Node Suite, which has been maintenance-only since late 2023 - if the whole pack throws "Import Failed" after a ComfyUI update, re-run its requirements against the activated venv, that's the usual fix.
Inputs (13)
| Name | Type | Default | Description |
|---|---|---|---|
| image_a | IMAGE | The image the animation starts on, and returns to at the end. A batch here becomes one a-to-b pair per frame, all in one animation. | |
| image_b | IMAGE | The image the animation fades into. It does not have to match image_a's size: both are letterboxed onto a canvas big enough for the larger of the two. A single image here fades in from every frame of a batched image_a. | |
| transition_frames | INT | 302–60 | How many blended frames are drawn between the two images. 2 is almost a hard cut, 30 is a smooth fade, and every extra frame adds to the file size. |
| still_image_delay_ms | FLOAT | 2500.00.1–60000 | How long each of the two images is held before it starts to fade, in milliseconds. 2500 holds it for two and a half seconds. |
| duration_ms | FLOAT | 0.10.1–60000 | How long each blended frame is shown, in milliseconds. The default 0.1 asks for the shortest frame the format allows, which most players round up to about 10ms; raise it to slow the fade down. |
| loops | INT | 00–100 | How many times the animation plays before it stops. 0 means play forever, which is what most viewers expect from a GIF. |
| max_size | INT | 512128–1280 | Longest edge of the animation, in pixels. The canvas is otherwise as large as the largest source, so 512 holds a 4000x3000 photograph down to 512x384 and cuts the file and the memory with it. A source already smaller than this is left alone. |
| root | COMBO | Which folder the file lands in: ComfyUI's own 'output' or 'temp', or any folder added under paths.allow_write in config.yaml, listed by its own name. filename names the part below it, so '[time(%Y-%m-%d)]/clip' files each day's under a dated folder. | |
| filename | STRING | morph | Name of the file, without an extension, the format below adds one. Tokens are expanded here too, so '[time(%H-%M-%S)]_morph' gives every run its own file instead of overwriting the last one. |
| filetype | COMBO | Which format to write. `GIF` plays anywhere but bands gradients at 256 colours; `APNG`, `WEBP` and `WEBP_LOSSLESS` keep full colour and alpha. | |
| palette_mode | COMBO | How the palette is chosen when colours are reduced. `per_frame` fits one per frame, `global` one to the whole animation, so a still area stays put. | |
| max_colors | INT | 2562–256 | How many colours the palette holds. 256 is the most a .gif can carry. Lower values shrink the file and give a flatter, posterised look, and below about 64 the choice of palette_mode starts to show. The full-colour formats ignore this at 256 and honour it below that, so it doubles as a posterise control for them. |
| dither | BOOLEAN | true | Scatter the rounding error between neighbouring pixels so a gradient stays smooth instead of breaking into bands. Turn it off for flat, poster-like colour, which also compresses smaller. |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| image_a_pass | IMAGE | image_a exactly as it arrived, so this node can sit mid-chain. |
| image_b_pass | IMAGE | image_b exactly as it arrived. |
| filepath_text | STRING | Full path of the file that was written, extension included. |
| filename_text | STRING | The filename widget as it was typed, with no folder and no extension, for feeding a caption or a log. |