Nodes/Jovimetrix/TRANSFORM (JOV) 🏝️
ComfyUI Node

TRANSFORM (JOV) 🏝️

Move, spin, mirror and warp any image with one node

By AmoranoΒ·Created 3 years agoΒ·Updated 12 months agoΒ· 397
TRANSFORM (JOV) 🏝️
  • πŸ‘Ύ
  • πŸ‡½πŸ‡Ύ
  • πŸ“
  • PIVOT
  • TILE
  • TL-TR
  • BL-BR
  • πŸ‡ΌπŸ‡­
  • πŸ–ΌοΈ
  • 😷
β—„πŸ“0.00β–Ί
β—„EDGECLIPβ–Ί
β—„πŸͺžNONEβ–Ί
β—„πŸ“½οΈNORMALβ–Ί
β—„πŸ’ͺ🏽1.000β–Ί
β—„πŸš¦NONEβ–Ί
β—„πŸŽžοΈLANCZOS4β–Ί
β—„πŸ”³0.00β–Ί

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.

CategoryJOVIMETRIX πŸ”ΊπŸŸ©πŸ”΅/COMPOSE

Inputs (16)

NameTypeDefaultDescription
πŸ‘Ύopt*β€”
πŸ‡½πŸ‡ΎoptVEC20,0-1–1β€”
πŸ“optFLOAT0.00-180–180β€”
πŸ“optVEC21,1β€”
EDGEoptCOMBOCLIP4 options: CLIP, WRAP, WRAPX, WRAPY
πŸͺžoptCOMBONONE5 options: NONE, X, Y, XY, YX
PIVOToptVEC20.5,0.50–1β€”
TILEoptVEC21,1β€”
TL-TRoptVEC40,0,1,00–1β€”
BL-BRoptVEC40,1,1,10–1β€”
πŸ“½οΈoptCOMBONORMAL4 options: NORMAL, POLAR, SPHERICAL, FISHEYE
πŸ’ͺ🏽optFLOAT1.000β€”
πŸ‡ΌπŸ‡­optVEC2512,51232–8192β€”
🚦optCOMBONONE4 options: NONE, FIT, CROP, ASPECT
🎞️optCOMBOLANCZOS47 options: NEAREST, LINEAR, CUBIC, AREA, LANCZOS4, LINEAR_EXACT, +1
πŸ”³optFLOAT0.000–1β€”

Outputs (2)

NameTypeDescription
πŸ–ΌοΈIMAGEβ€”
😷MASKβ€”