Image Push Pull Lens
A Cheap Dolly Zoom, Without the Depth Map
- image
- frames
- masks
The dolly zoom - the "Vertigo effect," that unsettling push-in-where-the-background-shifts - is one of those shots people ask about constantly, and the honest answer is that the flashy versions (depthflow, depth-map parallax) are doing real 3D reprojection. Image Push Pull Lens is not that. It's the cheap version: a center crop that grows or shrinks across your frames, resized back to full frame. And for a lot of uses, cheap is exactly right.
This node is the signature move of the SwiftCut pack, and the reason the pack's example workflow exists. Give it a still image and it generates a whole camera move; give it an existing frame sequence and it applies a move to each frame. It's the "motion" in your "image to video with camera movement" recipe that doesn't need a video model at all.
How it works
For each frame it crops a centered rectangle, resizes that crop back up to the original dimensions with Lanczos, and emits both the resulting frames batch and a masks output showing exactly which region survived the crop. The crop size follows a three-stage ramp:
start_crop_ratioat frame 0middle_crop_ratioatmiddle_frameend_crop_ratioat the last frame
Here's the mental model that matters: crop ratio is the fraction of the frame you keep, and a smaller fraction zoomed back up looks bigger. So start_crop_ratio 0.3 → end_crop_ratio 0.8 (the defaults) starts tight and pulls OUT - the classic push-pull reveal. Reverse the numbers and you push IN. Center-based cropping means the subject stays put while the frame seems to breathe around it.
Two modes:
single_to_multi- one image becomesframesframes (2–120, default 30), a generated camera move from a still. This is the headline feature.multi_to_multi- takes an existing batch and applies the three-stage crop across it; theframesinput is ignored here, your batch length decides.
The honest comparison
If you came here from a "dolly zoom in ComfyUI" search, know what you're getting. depthflow and the depth-based nodes give you true parallax - foreground and background moving at different rates, because they use a depth map. This node gives you a pure scale ramp, which reads as a zoom with extra steps, not a 3D push. But it's also instant, deterministic, and runs on any machine - no depth model, no ControlNet, no VRAM spike. For title cards, logo reveals, and "make my still image feel alive" jobs, the cheap zoom is often the better tool. The masks output is the sleeper feature: wire it into compositing and you can drive a second effect (blur, color grade) off the same crop region the whole way through.
Installing it
Same as every node in this pack:
cd ComfyUI/custom_nodes
git clone https://github.com/yichengup/ComfyUI_SwiftCut
Restart ComfyUI, or use ComfyUI Manager and search "ComfyUI_SwiftCut." It lands under YC_VideoCutHelper → Image. Dependencies are just torch, Pillow, and numpy - no models to download, nothing heavy, which is exactly why the cheap dolly zoom beats the fancy one on a low-spec box.
Where it bites
Two gotchas. First, middle_frame past the batch length gets clamped, and in multi_to_multi the whole frames input is dead weight - set your stage ratios and let the input decide. Second, because everything is a resize of a crop, heavy zoom-ins (ratios below ~0.2) visibly soften the frame. The result is a deliberate "film look" or just mushy, depending on your tolerance. Keep ratios above 0.3 and you'll rarely notice. This pack has basically no reddit footprint, so you won't find a tutorial - but the defaults (30 frames, 0.3→0.8) produce a perfectly usable shot on the first try, which is more than most camera-move nodes can claim.
Inputs (7)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| frames | INT | 302–120 | — |
| start_crop_ratio | FLOAT | 0.300.1–1 | — |
| middle_crop_ratio | FLOAT | 0.500.1–1 | — |
| end_crop_ratio | FLOAT | 0.800.1–1 | — |
| middle_frame | INT | 151–120 | — |
| input_mode | COMBO | single_to_multi | 2 options: single_to_multi, multi_to_multi |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| frames | IMAGE | — |
| masks | MASK | — |