Convert raster imagery (orthomosaic, NDVI, NDRE) to PMTiles
Project description
raster2pm 🛰️
raster → PMTiles — Convert any GeoTIFF to web-optimized map tiles in one command.
Convert orthomosaics, NDVI, NDRE, and any raster imagery to PMTiles with automatic colormap application for vegetation indices.
📦 Installation
From PyPI
\\ash pip install raster2pm \\
From Source
\\ash git clone https://github.com/samuelappiah/raster2pm.git cd raster2pm pip install -e . \\
With Development Dependencies
\\ash pip install raster2pm[dev] \\
🚀 Quick Start
Basic RGB Orthomosaic
\\ash raster2pm ortho.tif -o tiles.pmtiles \\
NDVI with Auto-Stretch
\\ash raster2pm ndvi.tif --ndvi --auto-stretch -o ndvi.pmtiles \\
NDRE with Custom Colormap
\\ash raster2pm ndre.tif --ndre --colormap RdYlGn -o ndre.pmtiles \\
📖 Complete Usage Guide
Command-Line Interface
\\ash raster2pm INPUT_FILE [OPTIONS] \\
Input/Output Options
| Option | Description | Default |
|---|---|---|
| -o, --output PATH\ | Output PMTiles file | \output.pmtiles\ |
Tiling Options
| Option | Description | Default |
|---|---|---|
| --min-zoom INT\ | Minimum zoom level | \5\ |
| --max-zoom INT\ | Maximum zoom level | \20\ |
| --format FORMAT\ | Tile format: PNG, JPEG, WEBP | \PNG\ |
| --tile-size INT\ | Tile size in pixels | \256\ |
| --resampling METHOD\ | Resampling: nearest, bilinear, cubic, cubic_spline, lanczos, average | \cubic\ |
| --quality INT\ | JPEG/WEBP quality (0-100) | \75\ |
| --workers INT\ | Number of parallel workers | \4\ |
Metadata Options
| Option | Description | Default |
|---|---|---|
| --name TEXT\ | Layer name | "Raster Layer"\ |
| --description TEXT\ | Layer description | "Converted from GeoTIFF"\ |
Behavior Options
| Option | Description |
|---|---|
| --overlay / --no-overlay\ | Create overlay tiles (default: overlay) |
| --exclude-empty / --no-exclude-empty\ | Exclude empty tiles (default: exclude) |
Vegetation Index Options
| Option | Description | Default |
|---|---|---|
| --ndvi\ | Input is NDVI raster | - |
| --ndre\ | Input is NDRE raster | - |
| --colormap NAME\ | Matplotlib colormap: viridis, plasma, inferno, magma, RdYlGn, RdBu, ndvi_custom | \RdYlGn\ |
| --min-value FLOAT\ | Minimum value for colormap | -1.0\ |
| --max-value FLOAT\ | Maximum value for colormap | \1.0\ |
| --auto-stretch\ | Auto-stretch to p2-p98 data range | - |
| --stretch-percentile FLOAT\ | Percentile to clip at tails | \2.0\ |
Diagnostic Options
| Option | Description |
|---|---|
| --stats-only\ | Print statistics and exit |
| --keep-temp\ | Keep temporary files |
| -v, --verbose\ | Increase verbosity |
| --version\ | Show version |
📚 Examples
Example 1: Convert RGB Orthomosaic
\\ash raster2pm farm_ortho.tif -o farm_tiles.pmtiles \\
Example 2: NDVI with Auto-Stretch
\\ash
Automatically stretches colormap to actual data range
raster2pm ndvi_map.tif --ndvi --auto-stretch -o ndvi_tiles.pmtiles \\
Example 3: High-Quality WEBP Output
\\ash raster2pm ortho.tif --format WEBP --quality 90 -o tiles.pmtiles \\
Example 4: Custom Zoom Levels
\\ash
Only generate zoom levels 12-18 (faster, smaller file)
raster2pm ortho.tif --min-zoom 12 --max-zoom 18 -o tiles.pmtiles \\
Example 5: NDRE with Viridis Colormap
\\ash raster2pm ndre_map.tif --ndre --colormap viridis --auto-stretch -o ndre_tiles.pmtiles \\
Example 6: Check Statistics Before Converting
\\ash
See data distribution before choosing colormap range
raster2pm ndvi.tif --ndvi --stats-only \\
Output:
\
📈 Computing data statistics (sampling ~2000 rows)...
Valid pixels (sample) : 98.5% (196,834 pixels)
Range : [-0.45, 0.92]
Mean ± std : 0.34 ± 0.28
Percentiles p2=-0.32 p10=-0.05 p25=0.12 p50=0.34 p75=0.56 p90=0.72 p98=0.85
Value distribution:
[-0.45 → -0.31] ███ 2.3%
[-0.31 → -0.18] ██████ 5.1%
...
\\
Example 7: Manual Colormap Range
\\ash
Use statistics from above to set optimal range
raster2pm ndvi.tif --ndvi --min-value -0.32 --max-value 0.85 -o ndvi_tiles.pmtiles \\
Example 8: JPEG Output for Smaller Files
\\ash raster2pm ortho.tif --format JPEG --quality 75 -o tiles_jpg.pmtiles \\
Example 9: Parallel Processing
\\ash
Use 8 CPU cores for faster conversion
raster2pm large_ortho.tif --workers 8 -o tiles.pmtiles \\
Example 10: Custom Metadata
\\ash raster2pm field.tif \ --name "Farm Field 42 - July 2024" \ --description "RGB orthomosaic, 2cm/pixel, DJI Phantom 4" \ -o farm_july.pmtiles \\
🐍 Python API
Basic Usage
\\python from raster2pm import convert_to_pmtiles
Basic RGB conversion
convert_to_pmtiles("ortho.tif", "output.pmtiles") \\
NDVI with Auto-Stretch
\\python from raster2pm import convert_to_pmtiles
convert_to_pmtiles( "ndvi.tif", "ndvi.pmtiles", is_ndvi=True, auto_stretch=True, colormap="RdYlGn", ) \\
Custom Settings
\\python from raster2pm import convert_to_pmtiles
convert_to_pmtiles( input_file="large_ortho.tif", output_file="tiles.pmtiles", min_zoom=12, max_zoom=22, tile_format="WEBP", quality=85, resampling="lanczos", workers=8, name="Farm Orthomosaic", description="2cm resolution, captured July 2024", ) \\
Using Individual Components
\\python from raster2pm import get_raster_info, compute_vegetation_stats
Get raster metadata
info = get_raster_info("ndvi.tif") print(f"Size: {info['size']}") print(f"Bands: {info['bands']}") print(f"CRS: {info['crs']}")
Compute NDVI statistics
stats = compute_vegetation_stats("ndvi.tif") print(f"NDVI range: [{stats['min']:.2f}, {stats['max']:.2f}]") print(f"Mean NDVI: {stats['mean']:.2f}") print(f"P50 NDVI: {stats['p50']:.2f}") \\
Apply Colormap Manually
\\python from raster2pm import apply_colormap_to_rgb
Convert single-band NDVI to RGB GeoTIFF
rgb_file = apply_colormap_to_rgb( "ndvi.tif", colormap_name="RdYlGn", vmin=-1.0, vmax=1.0, ) print(f"RGB file created: {rgb_file}") \\
🎨 Available Colormaps
| Colormap | Description | Best For |
|---|---|---|
| \RdYlGn\ | Red-Yellow-Green | NDVI/NDRE (default) |
| \ | ||
| dvi_custom\ | Red → Yellow → Green | NDVI (custom gradient) |
| \iridis\ | Blue-Green-Yellow | General scientific |
| \plasma\ | Purple-Orange-Yellow | Elevation/heat |
| \inferno\ | Black-Red-Yellow | Intensity |
| \magma\ | Black-Purple-White | Topography |
| \RdBu\ | Red-White-Blue | Anomaly detection |
📊 Understanding the Output
Statistics
When using --stats-only\ or --ndvi/--ndre, raster2pm computes:
- Min/Max: Data range
- Mean ± Std: Central tendency and spread
- Percentiles: p2, p10, p25, p50 (median), p75, p90, p98
- Valid pixels: Percentage of non-NoData pixels
- ASCII histogram: Visual distribution
Colormap Warnings
If your data range doesn't match the colormap range, raster2pm warns you:
\
⚠️ Data spans 0.35 but colormap range is 2.00 — only 18% of colours used.
The map will look nearly one colour!
👉 Run with --auto-stretch or set:
--min-value -0.32 --max-value 0.85
\\
Auto-Stretch
--auto-stretch\ automatically sets the colormap range to your data's p2-p98 range, ensuring vibrant, informative visualizations.
🌐 Viewing PMTiles
Online (Easiest)
Drag and drop your .pmtiles\ file to pmtiles.io
Local Server
\\ash
Install pmtiles CLI
npm install -g pmtiles
Serve locally
pmtiles serve output.pmtiles
Open http://localhost:8081
\\
Web Maps
\\javascript // MapLibre GL JS const map = new maplibregl.Map({ container: 'map', style: { sources: { 'raster': { type: 'pmtiles', url: 'https://example.com/tiles.pmtiles', } } } }); \\
🔧 How It Works
- Reads GeoTIFF metadata (CRS, bounds, bands)
- For vegetation indices: Computes statistics, applies colormap
- Processes block-by-block for memory efficiency
- Builds overview pyramids for smooth zooming
- Converts to PMTiles using rio-pmtiles
- Outputs a single .pmtiles\ file
⚙️ Requirements
- Python 3.8+
- rio-pmtiles
- rasterio
- numpy
- matplotlib
All installed automatically with \pip install raster2pm.
🧪 Development
\\ash
Clone
git clone https://github.com/samuelappiah/raster2pm.git cd raster2pm
Install dev dependencies
pip install -e ".[dev]"
Run tests
pytest -v
Format code
black raster2pm/ ruff check raster2pm/
Type check
mypy raster2pm/ \\
🤝 Contributing
Contributions welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests
- Submit a pull request
📄 License
MIT © 2024 Samuel Appiah Kubi
🔗 Links
- PyPI: https://pypi.org/project/raster2pm/
- GitHub: https://github.com/samuelappiah/raster2pm
- Issues: https://github.com/samuelappiah/raster2pm/issues
- PMTiles Spec: https://github.com/protomaps/PMTiles
- Preview: https://pmtiles.io
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file raster2pm-0.1.1.tar.gz.
File metadata
- Download URL: raster2pm-0.1.1.tar.gz
- Upload date:
- Size: 24.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
acfe81bfc76f5f9200df0b704e330fb9ff8711c199a0bc789d0b498c0acb0da8
|
|
| MD5 |
b91b8aaaac1333382588c5b1097724e8
|
|
| BLAKE2b-256 |
52521ed1e72aac11e01494413b68c737c63b3e250dc731841299a5603254e289
|
File details
Details for the file raster2pm-0.1.1-py3-none-any.whl.
File metadata
- Download URL: raster2pm-0.1.1-py3-none-any.whl
- Upload date:
- Size: 19.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6bb4c39825ef7e3a844ef5fd23e4192a92cac2a71f41a40ecd18499833cf47eb
|
|
| MD5 |
7fa09cba2d666f65a08dd3fa03a838d9
|
|
| BLAKE2b-256 |
2da34535c944d3816cb745715780ea86d23ceb4bfbd84a9f9cd02992fb4b0077
|