panorama-tiler
Tiling and configuration generator for creating multi-resolution cubemap pyramids from equirectangular or cylindrical panoramas, designed for use with the Pannellum web viewer.
panorama-tiler transforms flat equirectangular or cylindrical panorama images into partitioned, multi-resolution zoom
levels and outputs a companion config.json configuration file. It supports both complete 360-degree spheres and
cropped/partial panoramas.
Features
- Projection Conversion: Converts equirectangular and cylindrical source projections into 6-faced cubemaps (
f,b,u,d,l,r). - Angle and Crop Extraction: Parses Google Photo Sphere (GPano) XMP tags and EXIF data to determine field of view ( HAOV/VAOV) and vertical alignment.
- High resolution: Pannellum multi-res supports high resolution panoramas by splitting the image into tiles, this crate does the tiling.
- Pyramid Downscaling: Generates multi-level zoom crops of the panorama that Pannellum loads dynamically.
- Fast: Over 10x faster than Pannellum's
generate.pyfor (almost) the same functionality. - No
Hugin/nonadependency: This is a pure rust implementation, no external dependencies needed.
What's this?
This crate acts as a pre-processing pipeline for Pannellum's Multi-resolution (multires) panorama type. Rather
than loading a single high-resolution image, which can degrade web client performance or hit browser texture limits,
this crate segments the panorama into smaller tiles (e.g., 512x512 pixels) across different resolution tiers. The tile
logic is similar to how map tiles work, given that it generates tiles for different zoom levels until the full
resolution of the panorama is reached.
What it can do:
- Generate directory hierarchies containing cropped tiles for each zoom tier (
/%l/%s%y_%x). - Generate flat, low-resolution fallback cubemaps for fallback paths (
/fallback/%s). - Compute and output structural constraints to
config.json, including:haov,minYaw,maxYawvaov,minPitch,maxPitch,vOffsetnorthOffsetmultiResobject parameters (tileResolution,maxLevel,cubeResolution,missingTiles,path,fallbackPath)
- Compress missing tile grids for partial views using Pannellum's Base83 character set specification.
What it cannot do:
- It does not generate a perceptual hash, like
generate.pydoes. This hash can be used to show a representation of the panorama while the web browser is loading it. - It does not stitch overlapping source images together. The input image must already be a fully stitched panorama.
Concepts
- Equirectangular vs. Cylindrical: Equirectangular projection maps coordinates linearly across latitude and longitude. Cylindrical projection maps coordinates onto a cylinder, requiring trigonometric scaling of vertical coordinates based on focal length. An equirectangular panorama anyone might be familiar with is Google StreetView.
- Direct vs. Recursive Downscaling:
Direct: Each pyramid tier is scaled down directly from the full-resolution cubemap face. This preserves image sharpness but takes longer.Recursive: Tiers are recursively generated from the level immediately above them. This is faster but can introduce minor interpolation errors over deep zoom pyramids.
- Base83 Missing Tiles String: For partial panoramas, tiles that contain purely background color are discarded
during processing. To prevent Pannellum from throwing 404 HTTP errors trying to fetch these non-existent tiles, their
absence is encoded into a Base83 string stored in
config.json.
Usage
Minimal config tile generation
If your input image contains Exif/XMP metadata for panoramas, you can run the auto-detect pipeline. The crate will look in the provided image file for panorama related Exif/XMP tags, and use it to automatically set the right configuration. If it can't find the tags it will do a best guess estimation to find the proper configuration.
use ;
use Path;
Manual Configuration
When metadata tags are absent or you need to supply manual field-of-view angles, you can define them explicitly.
use ;
use Path;
Minimal Frontend Example
Once the tile pyramid is generated, host the target directory containing your tiles and the config.json file. You can
then load it into Pannellum with the following HTML.
Multires Panorama
Cargo Features
| Feature | Default | Description | Dependencies |
|---|---|---|---|
metadata |
Yes | Enables metadata reading, parsing GPano and EXIF fields. | exif, xmpkit |
webp |
Yes | Enables saving processed tiles in WebP format. | webp |
Performance Measurements
Below is an indicative execution time comparison between the Pannellum's provided generate.py and this Rust
implementation on the same equirectangular source image:
| Metric | Python Script (generate.py) |
Rust Implementation |
|---|---|---|
| Mean Execution | 10.380 seconds | 1.031 seconds |
| Median Execution | 10.097 seconds | 1.028 seconds |
| Standard Deviation | 1.121 seconds | 0.008 seconds |