Expand description
§OxiGeo — Pure Rust Geospatial Data Abstraction Library
OxiGeo is the Rust-native alternative to GDAL, providing a comprehensive geospatial data abstraction layer with zero C/Fortran dependencies. 100% Pure Rust.
§Quick Start
[dependencies]
oxigeo = "0.2" # includes GeoTIFF, GeoJSON, Shapefile by defaultuse oxigeo::Dataset;
let drivers = oxigeo::drivers();
println!("Enabled drivers: {:?}", drivers);
println!("OxiGeo version: {}", oxigeo::version());§Reading raster pixels — the fast path
The idiomatic way to get a band’s pixels into memory is to allocate the
destination once and let the driver decode straight into it, converting
the element type on the way. This is the equivalent of GDAL’s
RasterBand::read_into_slice, and it is what Dataset::read_band_into
does:
use oxigeo::Dataset;
let ds = Dataset::open("dem.tif")?;
// 1. The on-disk element type comes from the header — no pixel is read yet,
// so the destination can be sized and typed before any I/O.
println!("on-disk type: {:?}", ds.data_type()); // e.g. Some(Float32)
// 2. One allocation, of the type you actually want to compute in.
let (width, height) = (ds.width() as usize, ds.height() as usize);
let mut dem = vec![0.0f64; width * height];
// 3. Decode + Float32 → f64 conversion, fused into a single pass.
ds.read_band_into(0, &mut dem)?;dem is row-major, so it maps onto an
ndarray::Array2
with no copy — or you can decode directly into an array you already own:
use ndarray::Array2;
let mut grid = Array2::<f64>::zeros((height, width));
ds.read_band_into(0, grid.as_slice_mut().expect("standard layout"))?;§What each reader costs
| Method | Bands | Allocates | Reads | Converts |
|---|---|---|---|---|
Dataset::read_band | one | one RasterBuffer | every block of the band (or clip window) | no |
Dataset::read_window | one | one RasterBuffer | only the blocks the window overlaps | no |
Dataset::read_band_into | one | nothing — you own dst | every block of the band (or clip window) | yes, fused |
Dataset::read_window_into | one | nothing — you own dst | only the blocks the window overlaps | yes, fused |
Dataset::read_interleaved | many | one Vec<T> + fixed scratch | every block once, whatever the band count | yes, fused |
Dataset::read_interleaved_into | many | fixed scratch — you own dst | every block once, whatever the band count | yes, fused |
Dataset::read_window_interleaved | many | one Vec<T> + fixed scratch | only the blocks the window overlaps, once each | yes, fused |
Dataset::read_window_interleaved_into | many | fixed scratch — you own dst | only the blocks the window overlaps, once each | yes, fused |
The *_into readers keep peak extra memory at one tile/strip no matter how
large the raster is, which also makes them the right primitive for walking a
big file window by window with a reusable buffer. The interleaved readers
hold to the same bound — their scratch is sized by the file’s blocks and the
band count, never by the raster — and ask for all the bands together, so a
chunky file’s blocks are decompressed once rather than once per band. On a
dataset returned by Dataset::clip every reader works in the clipped pixel
grid and reads only the clipped blocks.
§Several bands at once
Dataset::read_band returns one band — as of 0.2.2, where it used to
return the whole pixel-interleaved image no matter which band was asked for.
When you want the interleaved image, ask for it:
use oxigeo::Dataset;
let ds = Dataset::open("scene.tif")?;
let (width, height) = (ds.width() as usize, ds.height() as usize);
// `None` = every band in file order; `Some(&[..])` picks and orders them.
let mut rgb = vec![0u8; width * height * 3];
ds.read_interleaved_into(Some(&[2, 1, 0]), &mut rgb)?;§Turn on parallel for large rasters
Block decoding is single-threaded by default (the crate is also compiled to
wasm32, which has no OS threads). Enable the parallel feature to spread
the per-tile decode — and the fused element conversion with it — across rayon
workers:
oxigeo = { version = "0.2", features = ["parallel"] }The result is bit-identical to the serial path; on a multi-megapixel DEM it
is what makes Dataset::read_band_into beat the decode-then-convert
workaround outright rather than merely halving its memory.
§Reading vector features
Vector datasets are read through layers, the same way GDAL’s OGR side
works: Dataset::layers enumerates them, and Layer::features yields
Features carrying a Geometry and a map of attribute FieldValues.
use oxigeo::Dataset;
let ds = Dataset::open("cities.gpkg")?; // or .shp, or .geojson
println!("{} layer(s)", ds.layer_count());
let layer = ds.layer(0)?; // also: ds.layer_by_name("cities")
println!("{}: {:?}, {:?} features, fields {:?}",
layer.name(), layer.geometry_type(), layer.feature_count(),
layer.field_names());
for feature in layer.features()? {
println!("{:?} — {:?}", feature.geometry, feature.properties);
}Layer reading is implemented for ESRI Shapefile and GeoJSON (both
default features) and for GeoPackage (feature gpkg, not on by
default — oxigeo = { version = "0.2", features = ["gpkg"] }). Any other
format returns OxiGeoError::NotSupported naming the driver rather than
silently reporting zero layers. For the remaining vector formats
(FlatGeobuf, GeoParquet, STAC) the streaming API
(streaming::StreamingExt) yields features with WKB geometry and JSON
properties.
§Feature Flags
| Feature | Default | Description |
|---|---|---|
geotiff | ✅ | GeoTIFF raster format (COG support) |
geojson | ✅ | GeoJSON vector format |
shapefile | ✅ | ESRI Shapefile |
geoparquet | ❌ | GeoParquet (Apache Arrow columnar) |
netcdf | ❌ | NetCDF scientific data format |
hdf5 | ❌ | HDF5 hierarchical data format |
zarr | ❌ | Zarr cloud-native arrays |
grib | ❌ | GRIB meteorological data format |
stac | ❌ | SpatioTemporal Asset Catalog |
terrain | ❌ | Terrain/elevation data |
vrt | ❌ | Virtual Raster Tiles |
flatgeobuf | ❌ | FlatGeobuf vector format |
jpeg2000 | ❌ | JPEG2000 raster format |
gpkg | ❌ | GeoPackage (SQLite) — vector layers and tiles |
pmtiles | ❌ | PMTiles v3 tile archive |
mbtiles | ❌ | MBTiles tile archive |
copc | ❌ | COPC / LAS / LAZ point clouds |
index | ❌ | Spatial indexing (R-tree, grid) |
full | ❌ | All formats above |
parallel | ❌ | Multi-threaded (rayon) block decoding for raster reads |
cloud | ❌ | Cloud storage (S3, GCS, Azure) |
proj | ❌ | CRS transformations (Pure Rust proj) |
algorithms | ❌ | Raster/vector algorithms |
analytics | ❌ | Geospatial analytics |
streaming | ❌ | Stream processing |
ml | ❌ | Machine learning integration |
gpu | ❌ | GPU-accelerated processing |
server | ❌ | OGC-compliant tile server |
temporal | ❌ | Temporal/time-series analysis |
§GDAL Compatibility
OxiGeo aims to provide familiar concepts for GDAL users:
| GDAL (C/C++) | OxiGeo (Rust) |
|---|---|
GDALOpen() | Dataset::open() |
GDALGetRasterBand() | dataset.raster_band(n) |
GDALDatasetGetLayerCount() | Dataset::layer_count() |
GDALDatasetGetLayer() | Dataset::layer() / Dataset::layer_by_name() |
OGRLayer::GetNextFeature() | Layer::features() |
OGR_F_GetFieldAsString() | feature.properties.get(name) |
GDALGetGeoTransform() | Dataset::geotransform() |
GDALGetProjectionRef() | Dataset::crs() |
GDALAllRegister() | drivers() |
GDALVersionInfo() | version() |
GDALWarp() | oxigeo::algorithms::warp() (feature algorithms) |
ogr2ogr | oxigeo-cli convert (crate oxigeo-cli) |
§Architecture
┌──────────────────────────────────────────────────┐
│ oxigeo (this crate) — Unified API │
│ Dataset::open() → auto-detect format │
├──────────────────────────────────────────────────┤
│ Drivers (feature-gated) │
│ ┌──────────┐ ┌──────────┐ ┌─────────────┐ │
│ │ GeoTIFF │ │ GeoJSON │ │ Shapefile │ ... │
│ └──────────┘ └──────────┘ └─────────────┘ │
├──────────────────────────────────────────────────┤
│ oxigeo-core — Types, Buffers, Error, I/O │
└──────────────────────────────────────────────────┘§Crate Ecosystem
OxiGeo is a workspace of 65+ crates. This oxigeo crate serves as
the unified entry point. Individual crates can also be used directly:
# Use the unified API (recommended for most users)
oxigeo = { version = "0.2", features = ["full", "cloud", "proj"] }
# Or pick individual crates for minimal dependencies
oxigeo-core = "0.2"
oxigeo-geotiff = "0.2"§Pure Rust — No C/Fortran Dependencies
Unlike the original GDAL which requires C/C++ compilation and system libraries (PROJ, GEOS, etc.), OxiGeo is 100% Pure Rust:
- No
bindgen, nocc, nocmake - Cross-compiles to WASM, embedded, mobile
cargo add oxigeo— that’s it
Part of the COOLJAPAN ecosystem.
Re-exports§
pub use layer::Layer;pub use layer::LayerFeatures;pub use cloud_detect::is_cloud_uri;pub use builder::CompressionType;pub use builder::CreateOptions;pub use builder::DatasetCreateBuilder;pub use builder::DatasetOpenBuilder;pub use builder::DatasetWriter;pub use builder::OutputFormat;pub use open::CloudScheme;pub use open::OpenedDataset;pub use open::open;pub use streaming::FeatureStream;pub use streaming::RasterTile;pub use streaming::StreamingExt;pub use streaming::StreamingFeature;pub use streaming::TileStream;pub use oxigeo_core as core_types;pub use oxigeo_geotiff as geotiff;geotiffpub use oxigeo_geojson as geojson;geojsonpub use oxigeo_shapefile as shapefile;shapefilepub use oxigeo_geoparquet as geoparquet;geoparquetpub use oxigeo_netcdf as netcdf;netcdfpub use oxigeo_hdf5 as hdf5;hdf5pub use oxigeo_zarr as zarr;zarrpub use oxigeo_grib as grib;gribpub use oxigeo_stac as stac;stacpub use oxigeo_terrain as terrain;terrainpub use oxigeo_vrt as vrt;vrtpub use oxigeo_flatgeobuf as flatgeobuf;flatgeobufpub use oxigeo_jpeg2000 as jpeg2000;jpeg2000pub use oxigeo_cloud as cloud;cloudpub use oxigeo_proj as proj;projpub use oxigeo_algorithms as algorithms;algorithmspub use oxigeo_analytics as analytics;analyticspub use oxigeo_streaming as streaming_ext;streamingpub use oxigeo_ml as ml;mlpub use oxigeo_gpu as gpu;gpupub use oxigeo_server as server;serverpub use oxigeo_temporal as temporal;temporalpub use oxigeo_gpkg as gpkg;gpkgpub use oxigeo_pmtiles as pmtiles;pmtilespub use oxigeo_mbtiles as mbtiles;mbtilespub use oxigeo_copc as copc;copcpub use oxigeo_index as index;indexpub use oxigeo_noalloc as noalloc;noallocpub use oxigeo_services as services;services
Modules§
- builder
- Builder patterns for dataset creation and opening. Builder patterns for ergonomic dataset creation and opening.
- cloud_
detect - Cloud URI detection and transparent dispatch for
Dataset::open. Cloud URI detection and transparent dispatch forcrate::Dataset::open. - convert
- Format conversion planning and detection utilities. Format conversion planning and detection utilities.
- layer
- Vector layer access:
Dataset::layers,Layerand its features. Vector layer access — the OGR half of theDatasetAPI. - open
- Universal dataset opener with automatic format detection. Universal dataset opener with automatic format detection.
- streaming
- Streaming / iterator API for large datasets. Streaming / iterator APIs for large geospatial datasets.
- vrt_
builder - Virtual Raster construction from multiple source datasets. Virtual Raster (VRT) construction from multiple source datasets.
Structs§
- Band
Iter - Lazy iterator over raster bands of a
Dataset. - Band
Statistics - Statistics for a single raster band.
- Bounding
Box - A 2D bounding box in any coordinate system
- Conversion
Options - Options controlling
Dataset::convert. - Dataset
- Unified dataset handle — the central abstraction (analogous to
GDALDataset). - Dataset
Info - Basic dataset metadata — analogous to
GDALDatasetinfo. - Feature
- Vector feature model — the currency of the layer API (
Dataset::layers,Layer::features). - GeoTransform
- An affine transformation matrix for converting between pixel and world coordinates
- Raster
Metadata - Raster metadata
Enums§
- Compression
- Output compression codec for
Dataset::convert. - Dataset
Format - Detected format of a geospatial dataset.
- Feature
Id - Vector feature model — the currency of the layer API (
Dataset::layers,Layer::features). - Field
Value - Vector feature model — the currency of the layer API (
Dataset::layers,Layer::features). - Geometry
- Vector feature model — the currency of the layer API (
Dataset::layers,Layer::features). - OxiGeo
Error - The main error type for
OxiGeo - Raster
Data Type - Raster data types representing pixel values
Traits§
- Raster
Element - Element types a raster can be read into — the bound on
Dataset::read_band_intoandDataset::read_window_into.
Functions§
- driver_
count - Number of registered (enabled) format drivers.
- drivers
- List all enabled format drivers.
- version
- OxiGeo version string.
Type Aliases§
- Result
- The main result type for
OxiGeooperations