ComfyUI LatLong - Equirectangular Image Processing Nodes
Advanced equirectangular (360°) image processing nodes for ComfyUI, enabling precise rotation, horizon adjustment, and specialized cropping operations for panoramic images.
Nodes (34)
Pull cube faces out of a 360° image
The return trip, no hassle
Convert any cubemap layout back to a panorama
Cut a 180° window out of a 360° panorama — the social-media money crop
Cut the panorama down to the middle
The final polish every panorama needs
Mirror or flip a panorama without breaking the sphere
Point a virtual camera at your panorama and pull out a real-looking photo
Rotate, then crop to 180° or square, in a single node
1 ratio — no stretched poles
Spin a 360° image in all three axes — the node this pack is built around
Front, back, up, down — point your panorama at the standard views instantly
Turn a 360° panorama into a 3x2 cubemap atlas
Cubemaps in dice, strip, or stack — pick your poison
Turn one equirectangular still into a camera move
Circular padding for seam-safe generation
Wrap padding on encode and decode
A before/after wipe that works inside the sphere
Mask the top and bottom of your 360°
Mask the seam so the model can fix what blending can't
Get your panorama into the layout your renderer wants
Find the seam before a viewer does
Cut a flat camera view out of your 360
Rotate an HDR panorama without clipping it to mush
Turn one flat image into a 360° outpainting starting point
Put your crisp source image back over the generation
Put the retouched view back on the sphere
Shove the 360° seam out of your way without resampling a single pixel
Roll your seam mask in lockstep with the image — or everything drifts
Unpack a cubemap face stack into named faces — without guessing the order
Pack six cube faces into one batch tensor — the tidy cubemap carrier
Actually see your HDR panorama in ComfyUI
Actually step inside your 360° video before you export it
Check your equirectangular renders before you trust them
ComfyUI LatLong
Equirectangular image transforms, cubemap conversion, perspective editing, outpainting, and interactive panorama previews for ComfyUI.
Install
Clone into ComfyUI/custom_nodes/comfyui-LatLong, install requirements.txt with ComfyUI's Python, and restart ComfyUI. Python 3.10 or later is required. Three.js r172 is bundled, so previewing does not require a CDN connection.
git clone https://github.com/cedarconnor/comfyui-LatLong.git
cd comfyui-LatLong
python -m pip install -r requirements.txt
For portable ComfyUI, replace python with its embedded Python executable. A Python wheel is also buildable; normal ComfyUI discovery still requires installing the extension in custom_nodes.
Changes in 2.1
- CPU and GPU now use the same mixed-angle rotation convention. Neutral and integer-pixel yaw rotations preserve pixels.
- Perspective extraction faces the equator at zero angles and shares the insertion camera basis.
- Sampling wraps longitude without wrapping the north and south poles together.
- Bicubic/Lanczos use CPU; requesting them explicitly with GPU produces a clear error. Auto considers filter support and available VRAM.
- Rotation uses bounded working bands; CPU source tiles also avoid OpenCV's 32767-pixel source limit.
- Cubemap reconstruction is vectorized and honors all four interpolation modes.
- Edge blending tapers to the untouched interior and matches both wrap edges.
- Outpaint perspective scale changes angular coverage. Stitch supports alpha, overlay, and hard blending. 2D patches wrap horizontally.
- Viewers release textures and WebGL resources, discard stale loads, pause rendering while hidden, and provide play/pause/scrubbing.
- Eight workflow nodes add float processing, preview tone mapping, reusable projections, diagnostics, comparison, animation, and cubemap presets.
Existing workflow changes
Node names and output sockets are retained. Corrected GPU mixed-angle rotations and perspective extraction can change old results. CPU extrinsic zyx rotation order remains the reference. Perspective scale changes projected FOV rather than resampling source resolution. The overlay stitch option now performs the standard overlay blend; hard disables feathering.
Circular-padding nodes now register changes through ComfyUI's model patcher. inplace=False clones the patcher instead of duplicating all model weights. inplace=True modifies the supplied patcher. This affects Conv2d layers only; it does not make transformer models, all VAE architectures, or every downstream operation seam-free.
Geometry contract
- World +X: front / longitude 0; +Y: longitude +90; +Z: north.
- Angles are degrees. Rotation uses SciPy extrinsic
zyx: yaw around Z, pitch around Y, roll around X. Positive pitch follows that right-handed rotation and points the forward direction downward. - An equirectangular pixel
(x,y)maps to longitude360*x/W-180and latitude90-180*y/H. Integer coordinates are pixel centers. - A perspective camera faces world +X at zero angles, with image-right +Y and image-down -Z. FOV is horizontal; pixels are square.
- Longitude is periodic; latitude clamps at the first/last row. Cubemap faces clamp at their own borders during reconstruction; no cross-face high-order filtering is claimed.
- Legacy 3x2 atlas:
[left, front, right] / [back, top, bottom]. Legacy face raster v increases toward its defined positive face-v direction. Presets retain this convention and offer an explicit reversible vertical flip. - Original transform nodes return float32 IMAGE values clipped to [0,1]. Use LatLong Float Processor for scene-linear/HDR data. Masks are BHW, with 1 meaning selected/inpaint unless an output is explicitly called coverage.
Nodes
Transforms and cubemaps
| Node | Behavior | |---|---| | Equirectangular Rotate | Yaw/pitch/roll and horizon offset, CPU/GPU and tiling controls | | Equirectangular Rotate (Preset) | Front/back/left/right/up/down with offsets | | Equirectangular Processor (All-in-One) | Rotate and optionally crop; square takes precedence | | Equirectangular Crop 180 | Seam-safe longitude window with adjustable FOV and center | | Equirectangular Crop Square | Center width crop to input height | | Equirectangular Perspective Extract | Rectilinear camera view | | Equirectangular Mirror/Flip | Horizontal and/or vertical image flip | | Equirectangular Resize | Optional 2:1 output aspect | | Equirectangular to/from Cubemap | Legacy 3x2 atlas | | Cubemap Faces Extract | Left, front, right, back, top, bottom outputs | | Flexible cubemap converters | 3x2, cross/dice, horizontal strip, or B*6 face stack | | Stack / Split Cubemap Faces | Reversible face stack with explicit face order | | LatLong Cubemap Preset | Export/import known layouts with a reversible face vertical flip |
Flexible list/dict choices remain aliases of stack for old workflows. Face names accept F/R/B/L/U/D and full names. Presets describe layouts, not undocumented Unreal/Unity/OpenGL axis conversions.
Masks and seam editing
- Create Seam Mask: centered strip with optional feather and half-width roll.
- Create Pole Mask: circular face masks or north/south coverage in equirectangular space.
- Roll Image / Roll Mask: wrap without resampling.
- Apply Circular Padding Model / VAE: patch Conv2d padding in x only or both axes.
- Equirectangular Edge Blender: match the wrap boundary while tapering corrections into both edge bands.
- LatLong Diagnostics: RGB overlay plus JSON measurements for wrap mismatch, both selected band joins, and polar row variation. Red marks wrap edges, amber band joins, cyan poles. Metrics locate potential defects; they do not establish visual quality.
Outpaint and projection editing
Outpaint Setup → inpaint → Outpaint Stitch
Setup returns a placed image, outpaint mask (1=inpaint), and stitch context. In 2D mode, scale is a source-pixel multiplier and x placement wraps across ±180°. Y is clipped. At sizes wider than the panorama, the first wrapped source span is sampled once. In perspective mode, scale multiplies tan(FOV/2); source pixels are not enlarged. Increasing angular coverage changes perspective geometry. Feather is measured in source pixels for perspective placement.
Stitch regenerates the layer at the output resolution. Alpha blends normally, overlay uses the overlay color formula under the mask, and hard pastes without feathering. Contexts are versioned; original contexts without a version are accepted as version 1.
LatLong Extract Projection → edit patch → LatLong Reinsert Projection
Extraction returns an image patch, full-panorama coverage mask, and versioned projection context. Reinsertion uses the saved yaw/pitch/roll/FOV and source aspect. Upscaling the patch is supported if its aspect ratio is unchanged. Contexts contain geometry metadata rather than a hidden copy of the panorama. Values are not clipped in this path.
HDR, animation, and preview
- LatLong Float Processor: rotate, perspective, cubemap conversion, or resize without clipping negative or above-one values. For
to_cubemap, width is face size; for rotate, source dimensions are retained. CPU filters preserve floating values; export encoding is handled downstream. - LatLong Tone Map Preview: exposure, Reinhard tone mapping, then linear-to-sRGB display conversion. Connect this to preview nodes while preserving the original HDR branch for output.
- LatLong Animated Rotation: JSON keyframes with frame/yaw/pitch/roll. Uses shortest-path quaternion interpolation, clamps outside the keyframe time range, and cycles the input batch when producing more frames than inputs. Example:
[{"frame":0,"yaw":0},{"frame":29,"yaw":90}]. - Preview 360 Panorama: first image of a batch, including grayscale; drag to look, wheel to zoom.
- Preview 360 Video Panorama: decoded textures are limited to the displayed frame; play/pause and an exact frame-index slider. Playback waits for decoding and can run below the requested FPS. Encoded frame URLs remain in the UI payload; very long/high-resolution batches can still use substantial host memory.
- LatLong Compare Panorama: before/after images or matching batches, shared camera, frame index, and wipe slider. Both images finish loading before the displayed comparison frame changes. A single image on either side is held across the other sequence.
Memory and performance
Tiling bounds geometry/source working buffers, not the full IMAGE tensors. A 16384×8192 RGB float32 image is 1.5 GiB; input plus output alone require 3 GiB. Node batch stacking and upstream/downstream tensors add memory. There is no persistent map cache.
CPU rotation automatically tiles above one megapixel or an 8192-pixel dimension. tile_size is an upper bound; working bands are further capped to approximately 262144 pixels. Source tiles include the interpolation halo. Independent inverse samples need no overlap blending. GPU rotation also uses bounded bands; disabling tiling permits a full-height grid. Auto falls back to CPU when the estimated image working set exceeds its available-VRAM budget.
Run python tests/benchmark.py 2048 4096 16384 for elapsed time and sampled process peak RSS on your hardware (psutil is a benchmark-only dependency). See VALIDATION.md for measured results and limits. No universal 16K/32K timing or sub-gigabyte memory guarantee is made.
Development
python -m unittest discover -s tests -p "test_*.py"
python tests/run_node_smoke_tests.py
npm test
python -m pip wheel --no-deps --no-build-isolation --wheel-dir output/dist .
CPU tests run in CI on Python 3.10 and 3.12. CUDA checks run when available. Publishing depends on tests passing and requires the actual Comfy Registry publisher ID plus REGISTRY_ACCESS_TOKEN; the publisher ID must be supplied by the maintainer.
Regression tests cover geometry, filters, large-source sampling, outpainting, HDR, projection context, animation, layouts, and viewer lifecycle. Tests do not qualify every diffusion model or VAE.
License
Apache-2.0. See LICENSE and NOTICE. Bundled Three.js retains its MIT license.