TRANSFORM (JOV) ποΈ
Move, spin, mirror and warp any image with one node
- πΎ
- π½πΎ
- π
- PIVOT
- TILE
- TL-TR
- BL-BR
- πΌπ
- πΌοΈ
- π·
TRANSFORM (JOV) is the node you reach for when an image needs to move, spin, shrink, mirror, tile or get re-projected into a sphere - all in one place, without stringing together half a dozen geometry nodes. If you've ever built a comp where you had to resize something, nudge it over by a few pixels, then flip it, this is the node that collapses that whole chain into a single box. It's part of Jovimetrix's COMPOSE family, and it's one of the workhorses of that pack.
Under the hood it's OpenCV doing the heavy lifting (via the cozy_comfyui library Jovimetrix is built on). The image gets translated and rotated around a PIVOT point, scaled, then handed to edge handling, mirroring and tiling before an optional re-projection. Order matters, and the node gets it right for you: transform first, then crop back to the source bounds, then mirror, then tile, then warp. The output always lands back in a target canvas you control, so you never have to chase drifting sizes downstream.
The inputs that actually matter
The node has a lot of knobs, but a beginner only sets a handful:
- Image (πΎ) - any IMAGE, MASK or RGBA input. Like the rest of Jovimetrix, it happily eats masks as images.
- XY (π½πΎ) - translate. A normalized offset from -1 to 1, where 1 is the full image dimension. Want to slide something a quarter of the way across? 0.25.
- ANGLE (π) - rotation in degrees, -180 to 180. Pair it with a WAVE GEN or TICK output to get slow swaying motion for animation.
- SIZE (π) - scale as a multiplier, default 1Γ1. 2 = twice as big, 0.5 = half.
- TILE - repeat count per axis. Set 3,3 and the image tiles into a grid. This is your go-to for seamless-texture contact sheets.
- MIRROR (πͺ) - none, X, Y, XY or YX flip.
- EDGE - what happens at the canvas edge: CLIP (cut off) or WRAP (wrap around). WRAP is what makes tiling actually look seamless.
- Projection (π½οΈ) - the fancy stuff: NORMAL, POLAR, SPHERICAL, FISHEYE or PERSPECTIVE. Sphere/fisheye warp is driven by STRENGTH (πͺπ½). For PERSPECTIVE you set the four corner points with TL-TR and BL-BR (each a VEC4 of x,y,x,y in 0β1 space) to define how the plane should be skewed.
The last three controls - output size (πΌπ), fit mode (π¦) (NONE/FIT/CROP/ASPECT) and the sampling method (ποΈ) (default LANCZOS4, the sharpest) - decide what canvas the result lands in.
Outputs
Two: IMAGE (πΌοΈ) and MASK (π·), both as lists. The mask is the alpha channel of the transformed result, so you can wire it straight into a BLEND or compositing step and keep everything cut out correctly even after rotations that would normally introduce edge artifacts.
Installing it
Jovimetrix is one pack that ships all these nodes together:
git clone https://github.com/Amorano/Jovimetrix.git
then install requirements into your ComfyUI environment (pip install -r requirements.txt; on the Windows portable build use .\python_embed\python.exe -s -m pip install -r requirements.txt). Easier still: ComfyUI Manager β search "Jovimetrix" β install. No model files to download - the deps are numpy, opencv-contrib-python, matplotlib and Pillow. It needs Python 3.10+ (3.11+ officially) and ComfyUI 0.1.3+.
One gotcha worth knowing before you click "update": the author warns DO NOT update Jovimetrix past 1.7.48 if you don't want to lose a bunch of nodes - since 2.0.0 the streaming, GLSL, MIDI and colorizer nodes were split out into separate Jovi_* packs. TRANSFORM isn't one of the ones that moved, so it's safe here either way.
Troubleshooting
The usual suspects: if a rotation or projection leaves the result smaller than expected, check the fit mode (π¦) - FIT forces the output back to the full WH canvas, NONE won't. If tiling looks wrong, make sure EDGE is set to WRAP, not CLIP. And if you're driving ANGLE or XY from another node and nothing seems to move, remember those inputs accept lists - a single disconnected value silently defaults, so confirm the wire is actually live. It's a busy node, but once the canvas-size logic clicks, it's hard to live without.
Inputs (16)
| Name | Type | Default | Description |
|---|---|---|---|
| πΎopt | * | β | |
| π½πΎopt | VEC2 | 0,0-1β1 | β |
| πopt | FLOAT | 0.00-180β180 | β |
| πopt | VEC2 | 1,1 | β |
| EDGEopt | COMBO | CLIP | 4 options: CLIP, WRAP, WRAPX, WRAPY |
| πͺopt | COMBO | NONE | 5 options: NONE, X, Y, XY, YX |
| PIVOTopt | VEC2 | 0.5,0.50β1 | β |
| TILEopt | VEC2 | 1,1 | β |
| TL-TRopt | VEC4 | 0,0,1,00β1 | β |
| BL-BRopt | VEC4 | 0,1,1,10β1 | β |
| π½οΈopt | COMBO | NORMAL | 4 options: NORMAL, POLAR, SPHERICAL, FISHEYE |
| πͺπ½opt | FLOAT | 1.000 | β |
| πΌπopt | VEC2 | 512,51232β8192 | β |
| π¦opt | COMBO | NONE | 4 options: NONE, FIT, CROP, ASPECT |
| ποΈopt | COMBO | LANCZOS4 | 7 options: NEAREST, LINEAR, CUBIC, AREA, LANCZOS4, LINEAR_EXACT, +1 |
| π³opt | FLOAT | 0.000β1 | β |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| πΌοΈ | IMAGE | β |
| π· | MASK | β |