wbraster
A Rust library for reading and writing common raster GIS formats intended to serve as the raster engine for Whitebox.
Table of Contents
- Mission
- The Whitebox Project
- Is wbraster Only for Whitebox?
- What wbraster Is Not
- Installation
- Quick Start
- Examples
- Supported Formats
- SAFE Bundle Support
- Landsat Collection Bundle Support
- ICEYE Bundle Support
- PlanetScope Bundle Support
- SPOT/Pleiades DIMAP Bundle Support
- Maxar/WorldView Bundle Support
- RADARSAT-2 Bundle Support
- RCM Bundle Support
- Unified Sensor Bundle Detection
- Real-Sample Smoke Tests (Opt-In)
- Bundle Canonical Key Reference
- Coordinate Reference System (CRS)
- Common GeoTIFF / COG Workflows
- Architecture
- Data Type Support Per Format
- GeoTIFF / COG Notes
- JPEG2000 / GeoJP2 Notes
- ENVI Metadata Key Reference
- Zarr Notes
- Compilation Features
- Performance
- Benchmarking
- Known Limitations
- License
Mission
- Provide multi-format raster GIS I/O for Whitebox applications and workflows.
- Support the broadest practical range of raster formats in a single pure-Rust library.
- Maintain correct coordinate registration, CRS propagation, and data-type fidelity across all formats.
- Minimize external C/native dependencies by delegating to purpose-built pure-Rust codecs where possible.
The Whitebox Project
Whitebox is a suite of open-source geospatial data analysis software with roots at the University of Guelph, Canada, where Dr. John Lindsay began the project in 2009. Over more than fifteen years it has grown into a widely used platform for geomorphometry, spatial hydrology, LiDAR processing, and remote sensing research. In 2021 Dr. Lindsay and Anthony Francioni founded Whitebox Geospatial Inc. to ensure the project's long-term, sustainable development. Whitebox Next Gen is the current major iteration of that work, and this crate is part of that larger effort.
Whitebox Next Gen is a ground-up redesign that improves on its predecessor in nearly every dimension:
- CRS & reprojection — Full read/write of coordinate reference system metadata across raster, vector, and LiDAR data, with multiple resampling methods for raster reprojection.
- Raster I/O — More robust GeoTIFF handling (including Cloud-Optimized GeoTIFFs), plus newly supported formats such as GeoPackage Raster and JPEG2000.
- Vector I/O — Expanded from Esri Shapefile-only to 11 formats, including GeoPackage, FlatGeobuf, GeoParquet, and other modern interchange formats.
- Vector topology — A new, dedicated topology engine (
wbtopology) enabling robust overlay, buffering, and related operations. - LiDAR I/O — Full support for LAS 1.0–1.5, LAZ, COPC, E57, and PLY via
wblidar, a high-performance, modern LiDAR I/O engine. - Frontends — Whitebox Workflows for Python (WbW-Python), Whitebox Workflows for R (WbW-R), and a QGIS 4-compliant plugin are in active development.
Is wbraster Only for Whitebox?
No. wbraster is developed primarily to support Whitebox, but it is not restricted to Whitebox projects.
- Whitebox-first: API and roadmap decisions prioritize Whitebox raster I/O needs.
- General-purpose: the crate is usable as a standalone multi-format raster library in other Rust geospatial applications.
- Format-complete: 13 supported formats with full round-trip read/write, typed band access, and CRS propagation make it broadly useful.
What wbraster Is Not
wbraster is a format I/O and CRS layer. It is not a full raster analysis framework.
- Not a raster processing or analysis library (filtering, terrain analysis, histogram operations belong in Whitebox tooling).
- Not a rendering or visualization engine.
- Not a remote sensing pipeline (radiometric correction, band math, and similar operations belong in the tooling layer).
- Not a distributed or chunked processing framework (Zarr MVP support is focused on local filesystem stores).
Installation
Crates.io dependency:
[]
= "0.1"
wbraster enables zstd-native by default. If you prefer pure-Rust decode-only Zstandard support, disable default features and enable zstd-pure-rust-decode instead:
[]
= { = "0.1", = false, = ["zstd-pure-rust-decode"] }
Local workspace/path dependency:
[]
= { = "../wbraster" }
Quick Start
use ;
let mut r = new;
r.set.unwrap;
r.set.unwrap;
r.write.unwrap;
r.write_cog.unwrap;
let cog_opts = CogWriteOptions ;
r.write_cog_with_options.unwrap;
let jp2_opts = Jpeg2000WriteOptions ;
r.write_jpeg2000_with_options.unwrap;
let r2 = read.unwrap;
assert_eq!;
assert!;
assert_eq!;
let = r2.world_to_pixel.unwrap;
println!;
Note: pixel accessors use (band, row, col) with signed row/col (isize).
For single-band data use band=0. Out-of-bounds queries return the nodata
sentinel for get; use get_opt for valid-only optional access.
Examples
The crate includes runnable examples in examples/:
raster_basics(core create/read/write/sampling)esri_ascii_iogeotiff_cog_iogeopackage_iozarr_io(v2 and v3)reproject_io
Run with:
Supported Formats
| Format | Extension(s) | Read | Write | Notes |
|---|---|---|---|---|
| ENVI HDR Labelled | .hdr + sidecar data |
✓ | ✓ | Multi-band (BSQ/BIL/BIP) |
| ER Mapper | .ers + data |
✓ | ✓ | Hierarchical header; reg-coord aware |
| Esri ASCII Grid | .asc, .grd |
✓ | ✓ | Handles xllcorner and xllcenter |
| Esri Binary Grid | workspace dir / .adf |
✓ | ✓ | Single-band float32, big-endian |
| GeoTIFF / BigTIFF / COG | .tif, .tiff |
✓ | ✓ | Stripped/tiled GeoTIFF + BigTIFF + COG writer |
| GeoPackage Raster (Phase 4) | .gpkg |
✓ | ✓ | Multi-band tiled raster; native-type raw tiles + PNG/JPEG options + extension registration |
| GRASS ASCII Raster | .asc, .txt |
✓ | ✓ | Header with north/south/east/west, rows/cols |
| Idrisi/TerrSet Raster | .rdc / .rst |
✓ | ✓ | byte, integer, real, RGB24 |
| JPEG 2000 / GeoJP2 | .jp2 |
✓ | ✓ | Pure-Rust JP2/GeoJP2 reader + writer |
| PCRaster | .map |
✓ | ✓ | CSF parser + value-scale aware writer (UINT1/INT4/REAL4/REAL8) |
| SAGA GIS Binary | .sgrd / .sdat |
✓ | ✓ | All SAGA data types; row-flip handled |
| Surfer GRD | .grd |
✓ | ✓ | Reads DSAA (ASCII) + DSRB (Surfer 7); writes DSAA by default, DSRB with surfer_format=dsrb |
| Zarr v2/v3 (MVP) | .zarr |
✓ | ✓ | 2D + 3D (band,y,x) chunked arrays |
SAFE Bundle Support
wbraster includes package-level SAFE readers for Sentinel missions and a
mission auto-detection API.
Sentinel-2 (Sentinel2SafePackage):
use Sentinel2SafePackage;
let pkg = open?;
println!;
println!;
println!;
println!;
println!;
println!;
println!; // AOT, WVP, TCI (L2A)
// resolve a spectral band path
if let Some = pkg.band_path
// resolve a QA layer
if let Some = pkg.qa_path
// resolve L2A auxiliary layers (Aerosol Optical Thickness, Water Vapour Pressure)
if let Some = pkg.aux_path
if let Some = pkg.aux_path
Sentinel-1 (Sentinel1SafePackage):
use Sentinel1SafePackage;
let pkg = open?;
println!;
println!;
println!;
println!;
println!;
println!;
// resolve a measurement raster — key is MODE_PRODUCT_POL
if let Some = pkg.measurement_path
// read VV measurement directly as a Raster
let raster = pkg.read_measurement?;
// read a calibrated raster in linear sigma0 units
let sigma0 = pkg.read_calibrated_measurement?;
// or immediately in dB
let sigma0_db = pkg.read_calibrated_measurement_db?;
// apply thermal-noise correction in linear units after calibration
let sigma0_nc = pkg.read_noise_corrected_calibrated_measurement?;
// or noise-corrected directly in dB
let sigma0_nc_db = pkg.read_noise_corrected_calibrated_measurement_db?;
// parse ECEF orbit state vectors from the annotation XML
let orbits = pkg.read_orbit_vectors?;
println!;
println!;
println!;
// bilinearly-interpolated geolocation grid (lat/lon/height/incidence angle)
let grid = pkg.read_geolocation_grid?;
let = grid.interpolated_lat_lon.unwrap;
let inc_angle = grid.interpolated_incidence_angle.unwrap;
// SLC TOPS burst metadata (returns Err for GRD products)
if let Ok = pkg.read_burst_list
// multi-polarization batch operations
let pols = pkg.list_polarizations; // e.g. ["VH", "VV"]
let vv_rasters = pkg.read_measurements_for_polarization?;
let vv_calibrated = pkg.read_calibrated_measurements_for_polarization?;
Unified mission detection (detect_safe_mission / open_safe_bundle):
use ;
// inspect mission type without opening the full package
match detect_safe_mission?
// open and dispatch on variant
match open_safe_bundle?
This is package-level support (metadata + band/QA/measurement discovery), which complements the raster I/O support for JPEG2000/GeoJP2 and GeoTIFF.
Landsat Collection Bundle Support
wbraster also includes package-level Landsat Collection bundle support based on
MTL metadata plus GeoTIFF scene assets.
use LandsatBundle;
let bundle = open?;
println!;
println!;
println!;
println!;
println!;
println!;
println!;
println!;
if let Some = bundle.band_path
if let Some = bundle.qa_path
let red = bundle.read_band?;
let qa = bundle.read_qa_layer?;
ICEYE Bundle Support
wbraster includes an initial ICEYE bundle reader for COG/GeoTIFF assets with
XML metadata.
use IceyeBundle;
let bundle = open?;
println!;
println!;
println!;
println!;
println!;
println!;
println!;
println!;
println!;
if let Some = bundle.asset_path
let vv = bundle.read_asset?;
let vv_assets = bundle.read_assets_for_polarization?;
PlanetScope Bundle Support
wbraster includes package-level PlanetScope support for common GeoTIFF assets
with JSON/XML sidecars.
use PlanetScopeBundle;
let bundle = open?;
println!;
println!;
println!;
println!;
println!;
let red = bundle.read_band?;
if let Some = bundle.qa_path
SPOT/Pleiades DIMAP Bundle Support
wbraster includes package-level DIMAP support for SPOT/Pleiades products
(DIM_*.XML plus JP2/GeoTIFF assets).
use DimapBundle;
let bundle = open?;
println!;
println!;
println!;
let pan = bundle.read_band?;
Maxar/WorldView Bundle Support
wbraster includes package-level Maxar/WorldView support for .IMD/XML
metadata and JP2/GeoTIFF assets.
use MaxarWorldViewBundle;
let bundle = open?;
println!;
println!;
println!;
let blue = bundle.read_band?;
RADARSAT-2 Bundle Support
wbraster includes an initial RADARSAT-2 bundle reader for GeoTIFF imagery and
product.xml metadata.
use Radarsat2Bundle;
let bundle = open?;
println!;
println!;
println!;
println!;
println!;
println!;
println!;
let hh = bundle.read_measurement?;
let hh_set = bundle.read_measurements_for_polarization?;
RCM Bundle Support
wbraster includes an initial RCM bundle reader for GeoTIFF imagery and XML
metadata.
use RcmBundle;
let bundle = open?;
println!;
println!;
println!;
println!;
println!;
println!;
println!;
let vv = bundle.read_measurement?;
let vv_set = bundle.read_measurements_for_polarization?;
Unified Sensor Bundle Detection
Use a single entrypoint to detect and open a supported bundle family (Sentinel SAFE, Landsat, ICEYE, PlanetScope, DIMAP, Maxar/WorldView, RADARSAT-2, RCM):
use ;
match detect_sensor_bundle_family?
match open_sensor_bundle?
// Also supports archive paths (.zip, .tar, .tar.gz, .tgz)
let opened = open_sensor_bundle_path?;
match opened.bundle
// If opened from archive, you can optionally clean up the extracted temp tree:
if let Some = opened.extracted_root
Bundle Canonical Key Reference
PlanetScope canonical keys:
- Bands:
B1,B2,B3,B4,B5,B6,B7,B8,ANALYTIC - QA:
UDM,UDM2
DIMAP canonical keys:
- Bands:
PAN,B0,B1,B2,B3,B4,B5,SWIR,SWIR1,SWIR2
Maxar/WorldView canonical keys:
- Bands:
PAN,B1,B2,B3,B4,B5,RE,Y,N2,SWIR,SWIR1,SWIR2
Real-Sample Smoke Tests (Opt-In)
The package readers include opt-in smoke tests that open local real datasets when environment variables are set.
Set one or both variables to a local dataset path:
WBRASTER_LANDSAT_SAMPLE: path to a Landsat scene directory.WBRASTER_LANDSAT_SAMPLE_EXPECT_KEYS: optional comma-separated expected canonical keys present in the sample (bands/QA/aux; e.g.B2,B3,B4,QA_PIXEL).WBRASTER_S2_SAFE_SAMPLE: path to a Sentinel-2.SAFEroot directory.WBRASTER_S2_SAFE_SAMPLE_EXPECT_KEYS: optional comma-separated expected canonical keys present in the sample (bands/QA/aux; e.g.B02,B03,B04,MSK_CLDPRB).WBRASTER_ICEYE_SAMPLE: path to an ICEYE scene directory.WBRASTER_ICEYE_SAMPLE_EXPECT_KEYS: optional comma-separated expected canonical asset keys present in the sample (e.g.VVorVV_2).WBRASTER_ICEYE_OPEN_DATA_SAMPLE: path to a local ICEYE Open Data scene directory (e.g. downloaded from the public STAC catalog).WBRASTER_ICEYE_OPEN_DATA_SAMPLE_EXPECT_KEYS: optional comma-separated expected canonical asset keys present in the sample.WBRASTER_PLANETSCOPE_SAMPLE: path to a PlanetScope scene directory.WBRASTER_PLANETSCOPE_SAMPLE_EXPECT_PROFILES: optional comma-separated expected PlanetScope profiles (e.g.ANALYTIC,ANALYTIC_SR).WBRASTER_DIMAP_SAMPLE: path to a SPOT/Pleiades DIMAP scene directory.WBRASTER_DIMAP_SAMPLE_EXPECT_PROFILES: optional comma-separated expected DIMAP profiles (e.g.MS,PAN).WBRASTER_MAXAR_SAMPLE: path to a Maxar/WorldView scene directory.WBRASTER_MAXAR_SAMPLE_EXPECT_PROFILES: optional comma-separated expected Maxar profiles (e.g.MS,PAN).WBRASTER_RADARSAT2_SAMPLE: path to a RADARSAT-2 scene directory.WBRASTER_RADARSAT2_SAMPLE_EXPECT_KEYS: optional comma-separated expected canonical measurement keys present in the sample (e.g.HH,HV).WBRASTER_RCM_SAMPLE: path to an RCM scene directory.WBRASTER_RCM_SAMPLE_EXPECT_KEYS: optional comma-separated expected canonical measurement keys present in the sample (e.g.VV,VH).
Run the smoke tests:
If a variable is unset (or points to a missing directory), its smoke test returns early and is treated as a no-op.
For ICEYE Open Data, point the variable at a local directory containing at
least one product .tif and one metadata .json sidecar from the same scene.
One way to build that directory is:
Public Sample Sources (Recommended)
These links are useful for obtaining legal/public sample scenes for local smoke tests:
- Sentinel-2 SAFE: Copernicus Data Space Ecosystem and related Sentinel distribution mirrors.
- Landsat Collection: USGS EarthExplorer and USGS/Cloud public mirrors for Collection 2 products.
- ICEYE Open Data: ICEYE public STAC catalog/object storage (example command shown above).
- PlanetScope: Planet documentation and sample/data-access portals for account holders.
- SPOT/Pleiades DIMAP: Airbus sample/data portals for account holders and trial datasets.
- Maxar/WorldView: Maxar Open Data program and account-based sample data portals.
- RADARSAT-2 and RCM: typically license-gated; use organizationally licensed sample scenes where available.
CRS support matrix
| Format | EPSG | WKT | PROJ4 | Notes |
|---|---|---|---|---|
| ENVI HDR Labelled | – | ✓ | – | Uses ENVI coordinate system string; preserves map info CRS tokens in metadata |
| ER Mapper | – | ~ | – | Preserves CoordinateSpace tokens (er_datum/er_projection/er_coordinate_type); WKT set only for WKT-like legacy datum values |
| Esri ASCII Grid | – | ~ | – | Reads/writes optional .prj sidecar; WKT is used when .prj content is WKT-like |
| Esri Binary Grid | – | ✓ | – | Reads/writes prj.adf |
| GeoTIFF / BigTIFF / COG | ✓ | – | – | Uses raster.crs.epsg |
| GeoPackage Raster (Phase 4) | ✓ | – | – | Uses srs_id in GeoPackage metadata tables |
| GRASS ASCII Raster | – | ~ | – | Reads/writes optional .prj sidecar; WKT is used when .prj content is WKT-like |
| Idrisi/TerrSet Raster | – | ~ | – | Reads/writes optional .ref sidecar; WKT is used when .ref content is WKT-like |
| JPEG 2000 / GeoJP2 | ✓ | – | – | Uses raster.crs.epsg |
| PCRaster | – | ~ | – | Reads/writes optional .prj sidecar; WKT is used when .prj content is WKT-like |
| SAGA GIS Binary | – | ✓ | – | Reads/writes optional .prj sidecar WKT (metadata key saga_prj_text, legacy alias saga_prj_wkt) |
| Surfer GRD | – | ~ | – | Reads/writes optional .prj sidecar; WKT is used when .prj content is WKT-like |
| Zarr v2/v3 (MVP) | ✓ | ✓ | ✓ | Uses metadata keys (crs_epsg/epsg, crs_wkt/spatial_ref, crs_proj4/proj4) |
Legend: ✓ supported, – not currently supported, ~ limited/custom representation.
See CRS / spatial reference (CRS) for setup/read-back examples and workflow guidance. See Sidecar metadata keys for format-specific sidecar CRS metadata names.
Coordinate Reference System (CRS)
Raster stores CRS metadata in raster.crs using CrsInfo:
epsg: Option<u32>wkt: Option<String>proj4: Option<String>
CrsInfo helpers:
CrsInfo::from_epsg(code)setsepsgand also populates canonical OGC WKT when available.CrsInfo::from_wkt(text)storeswktand infersepsgusing adaptive matching (lenient default), including many legacy WKT cases without explicit authority tokens.CrsInfo::from_wkt_with_policy(text, policy)selects inference policy explicitly.CrsInfo::from_wkt_strict(text)rejects ambiguous matches (keepsepsg=Nonewhen no single best candidate exists).
wbraster stores and propagates CRS metadata and includes built-in
EPSG-to-EPSG reprojection/resampling APIs.
use ;
let mut r = new;
// Set CRS before writing (method 1: direct field assignment with CrsInfo helper)
r.crs = from_epsg;
r.write.unwrap;
// Alternative: use convenience methods for CRS assignment
r.assign_crs_epsg; // Sets EPSG code
r.assign_crs_wkt; // Sets WKT definition
r.write.unwrap;
// Read CRS back
let r2 = read.unwrap;
println!;
println!;
println!;
CRS Assignment Methods:
Raster provides convenience methods for assigning CRS metadata:
raster.assign_crs_epsg(epsg_code)— Replaces the entire CRS with a newCrsInfocontaining only the EPSG code. Any existing WKT or PROJ4 fields are cleared to ensure consistency.raster.assign_crs_wkt(wkt_string)— Replaces the entire CRS with a newCrsInfocontaining only the WKT definition. Any existing EPSG or PROJ4 fields are cleared to ensure consistency.
These methods ensure CRS consistency by preventing conflicting metadata (e.g., EPSG:4326 with WKT for EPSG:3857). They are useful when discovering CRS metadata after raster creation or when overriding existing CRS information. Remember to call write() after assignment to persist changes to file.
Format CRS behavior (current):
- GeoTIFF / COG: reads/writes EPSG via
raster.crs.epsg. - JPEG 2000 / GeoJP2: reads/writes EPSG via
raster.crs.epsg. - ENVI: reads/writes WKT via
coordinate system string; also preserves/writesmap infoCRS tokens via metadata keys (envi_map_projection,envi_map_datum,envi_map_units). - ER Mapper: preserves
CoordinateSpacefields as metadata (er_datum,er_projection,er_coordinate_type); only WKT-like legacyDatumvalues populateraster.crs.wkt. - Esri ASCII Grid: reads/writes optional
.prjsidecar text via metadata keyesri_ascii_prj_text; WKT-like content populatesraster.crs.wkt. - Esri Binary Grid: reads/writes WKT via
prj.adf. - GRASS ASCII Raster: reads/writes optional
.prjsidecar text via metadata keygrass_ascii_prj_text; WKT-like content populatesraster.crs.wkt. - Idrisi/TerrSet: reads/writes optional
.refsidecar text via metadata keyidrisi_ref_text; WKT-like content populatesraster.crs.wkt. - PCRaster: reads/writes optional
.prjsidecar text via metadata keypcraster_prj_text; WKT-like content populatesraster.crs.wkt. - SAGA GIS Binary: reads/writes WKT via optional
.prjsidecar using metadata keysaga_prj_text(legacy aliassaga_prj_wktalso accepted). - Surfer GRD: reads/writes optional
.prjsidecar text via metadata keysurfer_prj_text; WKT-like content populatesraster.crs.wkt. - Zarr v2/v3: reads/writes EPSG/WKT/PROJ4 metadata (
crs_epsg/epsg,crs_wkt/spatial_ref,crs_proj4/proj4). - Other formats: typically no dedicated CRS field; preserve CRS externally when needed.
Reprojection
wbraster includes EPSG-to-EPSG raster reprojection using wbprojection with nearest-neighbor, bilinear, cubic, Lanczos-3, and thematic 3x3 resampling:
use ;
let input = read?;
// Requires input.crs.epsg to be set
let out_3857 = input.reproject_to_epsg?;
// Convenience aliases
let out_4326 = out_3857.reproject_to_epsg_nearest?;
let out_3857_bilinear = input.reproject_to_epsg_bilinear?;
let out_3857_cubic = input.reproject_to_epsg_cubic?;
let out_3857_lanczos = input.reproject_to_epsg_lanczos?;
let out_3857_average = input.reproject_to_epsg_average?;
let out_3857_min = input.reproject_to_epsg_min?;
let out_3857_max = input.reproject_to_epsg_max?;
let out_3857_mode = input.reproject_to_epsg_mode?;
let out_3857_median = input.reproject_to_epsg_median?;
let out_3857_stddev = input.reproject_to_epsg_stddev?;
// Explicit output grid controls + nodata policy helper (fluent)
let opts = new
.with_size
// or resolution-first sizing:
// .with_resolution(30.0, 30.0)
// .with_square_resolution(30.0)
// optional snap alignment for resolution-derived grids:
// .with_snap_origin(0.0, 0.0)
// choose resolution sizing behavior: Expand (default) or FitInside
.with_grid_size_policy
// optionally mask cells outside transformed source footprint:
.with_destination_footprint
.with_nodata_policy
// optional for EPSG:4326 default extent derivation:
// .with_antimeridian_policy(AntimeridianPolicy::Wrap)
;
// optionally: .with_extent(Extent { x_min: ..., y_min: ..., x_max: ..., y_max: ... })
let out_custom = input.reproject_with_options?;
// Antimeridian policy comparison for EPSG:4326 outputs
let out_auto = input.reproject_with_options?;
let out_linear = input.reproject_with_options?;
let out_wrap = input.reproject_with_options?;
// Match an existing reference grid exactly (CRS + extent + rows/cols)
let reference = read?;
let aligned = input.reproject_to_match_grid?;
// Match reference CRS + resolution + snap origin, but keep auto-derived extent
let aligned_res = input.reproject_to_match_resolution?;
// Match reference resolution/snap but force a different destination EPSG
let aligned_res_3857 = input.reproject_to_match_resolution_in_epsg?;
// Advanced: explicit CRS objects (bypasses source `raster.crs.epsg` requirement)
let src_crs = from_epsg?;
let dst_crs = from_epsg?;
let out_custom_crs = input.reproject_with_crs?;
Quick helper matrix:
| Helper | Destination CRS | Destination extent | Destination rows/cols | Resolution/snap source |
|---|---|---|---|---|
reproject_to_match_grid |
target_grid.crs.epsg |
target_grid.extent() |
target_grid.cols/rows |
implied by target grid |
reproject_to_match_resolution |
reference_grid.crs.epsg |
auto-derived from source footprint | derived from extent + resolution | reference_grid.cell_size_* + reference_grid.(x_min,y_min) |
reproject_to_match_resolution_in_epsg |
explicit dst_epsg |
auto-derived from source footprint | derived from extent + resolution | reference resolution/snap transformed (if needed) to destination CRS |
Current capabilities (production-ready core):
- Standard convenience APIs are EPSG-based (source
raster.crs.epsg+ destination EPSG). - Advanced custom-CRS path is available via
reproject_with_crs. - Includes
reproject_to_match_gridfor exact reference-grid alignment when target raster has EPSG. - Includes
reproject_to_match_resolutionfor reference resolution/snap alignment with auto-derived extent. - Includes
reproject_to_match_resolution_in_epsgfor cross-CRS resolution/snap alignment using local transform at reference origin. - Default output
rows/colsequals input unless overridden inReprojectOptions. - Default output extent is derived from transformed sampled source-boundary points (corners + edge densification) unless overridden in
ReprojectOptions. - Optional resolution controls (
x_res,y_res) can derivecols/rowsfrom extent. - Optional snap origin (
snap_x,snap_y) aligns resolution-derived output grid bounds to a shared origin. - If both size and resolution are provided, explicit
cols/rowstake precedence. - For geographic outputs (EPSG:4326), antimeridian handling policy is configurable:
Auto(default): choose wrapped bounds only when narrower than linear bounds.Linear: always use linear min/max longitude bounds.Wrap: always use wrapped minimal-arc longitude bounds.- Practical guidance:
- Use
Autofor most workflows (safe default). - Use
Linearwhen downstream tooling expects conventional min/max longitudes. - Use
Wrapwhen working with dateline-crossing regions and you want the tightest longitude span.
- Use
- Resampling methods: nearest-neighbor (
Nearest), bilinear (Bilinear), cubic (Cubic), Lanczos-3 (Lanczos), and thematic 3x3 (Average,Min,Max,Mode,Median,StdDev). - Resolution-derived grid sizing policy (
ReprojectOptions.grid_size_policy):Expand(default): expands to fully cover requested extent.FitInside: keeps generated grid within requested extent.
- Destination footprint handling (
ReprojectOptions.destination_footprint):None(default): no transformed-footprint masking.SourceBoundary: masks destination cells outside transformed source boundary ring.
- Interpolation nodata policy (
ReprojectOptions.nodata_policy):Strict: requires full valid interpolation kernel.PartialKernel(default): renormalizes over available valid kernel samples.Fill: uses strict interpolation, then falls back to nearest-neighbor.
Sidecar metadata keys
| Format | Sidecar | Preferred metadata key | Compatibility alias(es) |
|---|---|---|---|
| Esri ASCII Grid | .prj |
esri_ascii_prj_text |
– |
| GRASS ASCII Raster | .prj |
grass_ascii_prj_text |
– |
| Idrisi/TerrSet Raster | .ref |
idrisi_ref_text |
– |
| PCRaster | .prj |
pcraster_prj_text |
– |
| SAGA GIS Binary | .prj |
saga_prj_text |
saga_prj_wkt |
| Surfer GRD | .prj |
surfer_prj_text |
– |
Common GeoTIFF / COG Workflows
use ;
// Read any GeoTIFF-family input (GeoTIFF, BigTIFF, COG)
let input = read.unwrap;
// Or use convenience defaults (deflate + tile 512)
input.write_cog.unwrap;
// Or choose a custom tile size while keeping convenience defaults
input.write_cog_with_tile_size.unwrap;
// Or use COG-focused options without full GeoTIFF layout types
let cog_opts = CogWriteOptions ;
input.write_cog_with_options.unwrap;
For non-COG GeoTIFF layouts (e.g., stripped/tiled non-COG output), use the
full GeoTiffWriteOptions + Raster::write_geotiff_with_options(...) API.
If you specifically need the lower-level TIFF / GeoTIFF / BigTIFF / COG engine rather than the higher-level multi-format raster abstraction, see wbgeotiff.
Architecture
wbraster/
├── Cargo.toml
├── README.md
├── src/
│ ├── lib.rs ← public API + crate docs
│ ├── raster.rs ← Raster core, typed storage, band helpers, iterators
│ ├── error.rs ← RasterError, Result
│ ├── io_utils.rs ← byte-order primitives, text helpers
│ ├── crs_info.rs ← CrsInfo (WKT / EPSG / PROJ4)
│ └── formats/
│ ├── mod.rs ← RasterFormat enum + auto-detect/dispatch
│ ├── envi.rs ← ENVI HDR Labelled Raster (BSQ/BIL/BIP)
│ ├── er_mapper.rs ← ER Mapper
│ ├── esri_ascii.rs ← Esri ASCII Grid
│ ├── esri_binary.rs ← Esri Binary Grid
│ ├── geopackage.rs ← GeoPackage raster Phase 4 (multi-band tiled)
│ ├── geopackage_sqlite.rs ← low-level SQLite helpers for GeoPackage
│ ├── geotiff.rs ← GeoTIFF / BigTIFF / COG adapter; delegates to `wbgeotiff` crate
│ ├── jpeg2000.rs ← JPEG 2000 / GeoJP2 adapter for Raster
│ ├── jpeg2000_core/ ← integrated JPEG2000/GeoJP2 engine
│ │ ├── mod.rs
│ │ ├── reader.rs
│ │ ├── writer.rs
│ │ ├── boxes.rs
│ │ ├── codestream.rs
│ │ ├── wavelet.rs
│ │ ├── entropy.rs
│ │ ├── geo_meta.rs
│ │ ├── types.rs
│ │ └── error.rs
│ ├── grass_ascii.rs ← GRASS ASCII Raster
│ ├── idrisi.rs ← Idrisi/TerrSet Raster
│ ├── pcraster.rs ← PCRaster (CSF)
│ ├── saga.rs ← SAGA GIS Binary
│ ├── surfer.rs ← Surfer GRD (DSAA/DSRB)
│ ├── zarr.rs ← Zarr v2 + v3 dispatch
│ └── zarr_v3.rs ← Zarr v3 implementation
├── tests/
│ └── integration.rs ← cross-format round-trip integration tests
├── benches/
│ └── raster_access.rs ← typed vs generic access benchmarks
Design principles
- Small dependency surface — GeoTIFF I/O delegates to the standalone
wbgeotiffcrate; CRS reprojection delegates towbprojection; Zarr support usesserde_jsonplus compression crates (flate2,lz4_flex, and optional zstd backend viazstd-nativeorzstd-pure-rust-decode). - Typed internal representation — raster cells are stored in native typed
buffers (
u8,u16,f32, etc.) viaRasterData, while convenience APIs still exposef64access where needed. - Performance — buffered I/O (
BufReader/BufWriterwith 512 KiB buffers), row-level slicing, and in-placemap_validmutation. - Correctness — each format correctly handles coordinate conventions (corner vs. center registration, top-to-bottom vs. bottom-to-top row order, byte-order flags).
Data Type Support Per Format
| Format | U8 | I16 | I32 | F32 | F64 |
|---|---|---|---|---|---|
| ENVI HDR Labelled | ✓ | ✓ | ✓ | ✓ | ✓ |
| ER Mapper | ✓ | ✓ | ✓ | ✓ | ✓ |
| Esri ASCII Grid | ✓¹ | ✓¹ | ✓¹ | ✓ | ✓ |
| Esri Binary Grid | – | – | – | ✓ | – |
| GeoTIFF / COG | ✓ | ✓ | ✓ | ✓ | ✓ |
| GeoPackage Raster (Phase 4) | ✓ | ✓ | ✓ | ✓ | ✓ |
| GRASS ASCII Raster | ✓¹ | ✓¹ | ✓¹ | ✓ | ✓ |
| Idrisi/TerrSet Raster | ✓ | ✓ | – | ✓ | – |
| JPEG 2000 / GeoJP2 | ✓ | ✓ | – | ✓ | ✓ |
| PCRaster | ✓ | ✓ | ✓ | ✓ | ✓ |
| SAGA GIS Binary | ✓ | ✓ | ✓ | ✓ | ✓ |
| Surfer GRD | – | – | – | ✓ | ✓ |
| Zarr v2/v3 (MVP) | ✓ | ✓ | ✓ | ✓ | ✓ |
¹ ASCII stores all types as text; write uses the data_type field for hint only.
Auto-detect Notes
.grdis signature-sniffed:DSAA/DSRBroutes toSurferGrd, otherwiseEsriAscii..asc/.txtare header-sniffed betweenGrassAsciiandEsriAscii..mapis signature-sniffed for PCRaster CSF (RUU CROSS SYSTEM MAP FORMAT)..gpkgroutes toGeoPackageraster Phase 4.
GeoPackage Phase 4 Notes
- Writer defaults: single zoom (
0); tile encoding defaults to PNG forU8and raw native tiles for non-U8data. - Optional write-time metadata keys:
gpkg_max_zoom: non-negative integer (number of additional pyramid levels)gpkg_tile_size: tile width/height in pixels (16..4096, default256)gpkg_tile_format:pngorjpeg/jpg(image-encoded/quantized tiles)gpkg_tile_encoding:raw,png, orjpeg(overrides default encoding selection)gpkg_raw_compression:noneordeflate(applies whengpkg_tile_encoding=raw; default isdeflateunless explicitly overridden)gpkg_jpeg_quality:1..100(used whengpkg_tile_format=jpeg)gpkg_dataset_name: SQL identifier override for internal dataset name (defaultwbraster_dataset)gpkg_base_table_name: SQL identifier override for tile table base name (defaultraster_tiles)
- Reader selects the finest available zoom level from
gpkg_tile_matrixand supports both raw native tiles and PNG/JPEG tile blobs. - Writer registers
gpkg_extensionsrows for custom wbraster raw-tile and metadata extensions. - When multiple
wbraster_gpkg_raster_metadatadataset rows are present, reader selection can be overridden using environment variableWBRASTER_GPKG_DATASET=<dataset_name>. - Programmatic dataset helpers are available via
geopackage::list_datasets(path)andgeopackage::read_dataset(path, dataset_name).
GeoPackage phase progression
| Phase | Key capabilities |
|---|---|
| Phase 1 | Multi-band read/write, native dtype-preserving raw tiles, PNG/JPEG tile options, metadata side tables |
| Phase 2 | Tiling/compression policy controls (gpkg_tile_size, gpkg_raw_compression) with tested defaults and overrides |
| Phase 3 | Interoperability hardening: gpkg_extensions registration, configurable/sanitized dataset/table naming, robust multi-dataset selection and metadata consistency validation |
| Phase 4 | Explicit multi-dataset APIs (geopackage::list_datasets, geopackage::read_dataset) with strict named-dataset reads |
PCRaster Notes
- Reader supports core CSF cell representations:
CR_UINT1,CR_INT4,CR_REAL4,CR_REAL8. - Writer supports:
VS_BOOLEAN/VS_LDDasCR_UINT1VS_NOMINAL/VS_ORDINALasCR_UINT1orCR_INT4VS_SCALAR/VS_DIRECTIONasCR_REAL4orCR_REAL8
- Optional metadata overrides on write:
pcraster_valuescale:boolean|nominal|ordinal|scalar|direction|lddpcraster_cellrepr:uint1|int4|real4|real8
GeoTIFF / COG Notes
RasterFormat::GeoTiffreads GeoTIFF, BigTIFF, and COG files.- GeoTIFF / COG support in
wbrasteris implemented on top of the standalone wbgeotiff crate. - Write mode defaults to deflate-compressed GeoTIFF.
Raster::write_cog(path)writes a COG with convenience defaults (deflate compression, tile size 512, BigTIFF disabled).Raster::write_cog_with_tile_size(path, tile_size)does the same with a caller-specified COG tile size.Raster::write_cog_with_options(path, &CogWriteOptions)exposes only COG-relevant knobs (compression,bigtiff,tile_size).
Preferred typed write API
- For COG output, prefer
Raster::write_cog_with_options(path, &CogWriteOptions). - GeoTIFF/COG metadata write controls are no longer consumed.
- Leaving an option as
Noneuses built-in defaults.
| COG typed field | Type | Effect | Default |
|---|---|---|---|
compression |
Option<GeoTiffCompression> |
Compression codec | deflate |
bigtiff |
Option<bool> |
Force BigTIFF container | false |
tile_size |
Option<u32> |
COG tile size (pixels) | 512 |
Notes:
- For full GeoTIFF control beyond COG-focused fields, use
Raster::write_geotiff_with_options(path, &GeoTiffWriteOptions).
| Advanced GeoTIFF field | Type | Effect | Default |
|---|---|---|---|
compression |
Option<GeoTiffCompression> |
Compression codec | deflate |
bigtiff |
Option<bool> |
Force BigTIFF container | false |
layout |
Option<GeoTiffLayout> |
Writer mode/layout | GeoTiffLayout::Standard |
GeoTIFF/COG metadata key reference
The GeoTIFF adapter populates read-back metadata descriptors for input files.
The keys below are read-back descriptors only; writer configuration now
uses GeoTiffWriteOptions exclusively.
| Metadata key | Direction | Purpose | Accepted values / default | Notes |
|---|---|---|---|---|
geotiff_compression |
Read | Source compression codec descriptor | none, lzw, deflate, packbits, jpeg, webp, jpeg-xl |
Populated by reader; informational. |
geotiff_is_bigtiff |
Read | Source file container type | true / false |
Populated by reader; informational. |
geotiff_is_cog_candidate |
Read | Source compression suggests COG-friendly profile | true / false (or omitted) |
Populated by reader; informational hint only. |
Notes:
- CRS/EPSG on write is taken from
raster.crs.epsg. - Configure write behavior with
GeoTiffWriteOptions(compression,bigtiff,layout).
JPEG2000 / GeoJP2 Notes
RasterFormat::Jpeg2000reads and writes.jp2files.- Default write mode is lossy (
Jpeg2000Compression::Lossy { quality_db: JPEG2000_DEFAULT_LOSSY_QUALITY_DB }). - Current integration is focused on adapter wiring and typed write options; treat production decode compatibility as evolving.
Preferred typed write API
Raster::write_jpeg2000_with_options(path, &Jpeg2000WriteOptions)configures JPEG2000 output.- Leaving an option as
Noneuses built-in defaults.
| Typed field | Type | Effect | Default |
|---|---|---|---|
compression |
Option<Jpeg2000Compression> |
Lossless/lossy mode | Lossy { quality_db: JPEG2000_DEFAULT_LOSSY_QUALITY_DB } |
decomp_levels |
Option<u8> |
Number of wavelet decomposition levels | writer default (5) |
color_space |
Option<ColorSpace> |
Output JP2 color space | inferred from band count |
ENVI Metadata Key Reference
| Metadata key | Direction | Purpose | Accepted values / default | Notes |
|---|---|---|---|---|
envi_interleave |
Read + Write | Interleave mode | bsq, bil, bip / default bsq |
Reader writes this key into Raster.metadata; writer consumes it for both header and data layout. |
description |
Read + Write | ENVI header description string | any string / default write: Created by gis_raster |
Reader populates from description = {...} if present; writer emits it to header. |
envi_map_projection |
Read + Write | ENVI map info projection token |
any string / default write: Geographic Lat/Lon |
Preserved from map info first field when present. |
envi_map_datum |
Read + Write | ENVI map info datum token |
any string / optional | Parsed from map info datum position when present; used on write if supplied. |
envi_map_units |
Read + Write | ENVI map info units hint |
any string / optional | Parsed from map info units slot when present; written as units=<value>. |
envi_coordinate_system_string |
Read + Write | ENVI coordinate system string raw WKT |
WKT string / optional | Reader mirrors this value; writer uses raster.crs.wkt first, then this key as fallback. |
Notes:
- ENVI header field
data fileis parsed internally on read for sidecar resolution, but is not persisted as aRaster.metadatakey.
Zarr Notes
- Zarr support targets local filesystem stores for both v2 and v3.
- Reads and writes 2D arrays and 3D arrays in
(band, y, x)form. - Supported compressors:
zlib,gzip,zstd,lz4, or none. zstdbehavior is feature-gated:zstd-native(default): read + write via nativezstdbindings.zstd-pure-rust-decode: read-only zstd decode viaruzstd; zstd encoding is unavailable.
- Default write uses
zliblevel 6 and Zarr v2. - Select write version with metadata key
zarr_version(2default,3for v3).
Validation mode
Both readers support explicit validation strictness via the zarr_validation_mode attribute in .zattrs
(v2) or in the attributes block of zarr.json (v3):
strict(default): fails on conflicting or invalid geospatial metadata.lenient: performs best-effort reads, ignoring non-critical metadata conflicts (e.g., aGeoTransformstring that disagrees with explicit origin/cell-size keys).
Nodata conventions
Nodata is resolved in this precedence order:
- explicit
nodataattribute _FillValue(CF convention, used byxarray,rioxarray)missing_value- Zarr
fill_value - default −9999
Zarr stores produced by CF-convention tools that write only _FillValue are therefore read correctly
without any extra configuration.
CRS interoperability
The readers recognize a broad set of CRS representations:
| Source convention | Recognized attribute key(s) |
|---|---|
| Whitebox native | crs_epsg, crs_wkt, crs_proj4 |
| Common aliases | epsg, spatial_ref, proj4 |
Plain "EPSG:NNNN" string |
crs |
| OGC URN / URL | crs (e.g., urn:ogc:def:crs:EPSG::4326, https://www.opengis.net/def/crs/EPSG/0/4326) |
Object with properties.name |
crs (e.g., {"properties": {"name": "EPSG:4326"}}) |
Object with id.authority/code |
crs (e.g., {"id": {"authority": "EPSG", "code": "4326"}}) |
CF grid_mapping named object |
grid_mapping key referencing an object; extracts EPSG, WKT, or proj4 |
GDAL-style GeoTransform |
six-element affine string; origin and cell size are recovered from it |
Affine transform array |
[x_min, cell_x, 0, y_min, 0, cell_y] |
Multi-scale group support (OME-NGFF)
Raster::read("store.zarr") automatically detects OME-NGFF multi-scale groups for both v2 and v3.
When the path points to a group root:
- OME-NGFF
multiscalesattribute present — levels are read frommultiscales[0].datasets[].path; level 0 (finest resolution) is opened by default. - No OME attributes — consecutive numeric sub-directories (
0/,1/,2/, …) are scanned; the first valid array is opened.
To open a specific resolution level, point the path directly at the sub-array directory:
// Default: opens finest resolution (level 0)
let full_res = read?;
// Direct path: opens coarser level 1
let half_res = read?;
Zarr v3 transpose codec
The v3 reader supports the transpose codec for F-order and custom-permutation arrays:
"F"order reverses the natural axis order.- A numeric permutation array (e.g.,
[2, 1, 0]) specifies the exact axis mapping. - C-order arrays (including those with an explicit
"C"transpose entry) are read without remapping.
dimension_names validation (v3)
In strict mode, the v3 reader rejects 3D arrays whose dimension_names place spatial axes before the
band axis (e.g., ["y", "x", "band"]) with an actionable error. Users can resolve this by adding a
transpose codec in the producer or setting zarr_validation_mode = "lenient" in the store attributes.
Standard 2D layouts and unrecognized dimension names are always accepted.
v2 specifics
- Set chunk-key style by adding metadata key
zarr_dimension_separator(/or.) before writing. - Geospatial metadata is written to
.zattrs(_ARRAY_DIMENSIONS,transform,x_min,y_min,cell_size_x,cell_size_y,nodata,crs_epsg,crs_wkt,crs_proj4). - Chunk controls:
zarr_chunk_rows,zarr_chunk_cols,zarr_chunk_bands.
v3 specifics
- Supports regular chunk grids with C-order traversal (multi-chunk included).
- Supports chunk key encoding
defaultandv2with.or/separators. - Supports
bytescodec pipeline with optionaltransposecodec plus compressor. - Compressors:
zlib,gzip,zstd,lz4. - Geospatial metadata/CRS is stored in
zarr.jsonunderattributes. - Chunk controls:
zarr_chunk_rows,zarr_chunk_cols,zarr_chunk_bands.
Zarr v3 write example
use ;
let mut r = new;
// Request Zarr v3 output with custom chunking and key encoding.
r.metadata.push;
r.metadata.push;
r.metadata.push;
r.metadata.push;
r.metadata.push;
r.metadata.push;
r.metadata.push;
r.write.unwrap;
Zarr v2 advanced write example
use ;
let mut r = new;
// Optional v2 controls for chunk key style.
r.metadata.push;
r.metadata.push;
r.write.unwrap;
Zarr metadata key quick reference
| Metadata key | Version | Purpose | Accepted values / default |
|---|---|---|---|
zarr_version |
v2 + v3 | Select writer implementation / read descriptor | 2 (default), 3 |
zarr_dimension_separator |
v2 + v3 | Chunk key separator | . or / |
zarr_chunk_separator |
v2 + v3 | Alias for separator key | . or / |
zarr_chunk_bands |
v2 + v3 | Band chunk depth for 3D (band,y,x) writes |
positive integer, clamped to [1, bands], default 1 |
zarr_chunk_rows |
v2 + v3 | Chunk height for writes | positive integer, clamped to [1, rows], default min(rows, 256) |
zarr_chunk_cols |
v2 + v3 | Chunk width for writes | positive integer, clamped to [1, cols], default min(cols, 256) |
zarr_chunk_key_encoding |
v3 | Chunk key encoding style | default (default), v2 |
zarr_compressor |
v3 | Compression algorithm | zlib (default), gzip, gz, zstd, lz4, none |
zarr_compression_level |
v3 | Compression level hint | integer; optional |
zarr_validation_mode |
v2 + v3 | Read-time validation strictness | strict (default), lenient |
Zarr Implementation Status
What is currently supported:
- Local filesystem stores, v2 and v3
- 2D and 3D
(band, y, x)arrays, including multi-chunk bytescodec + optional compressor (zlib,gzip,zstd,lz4)- v3
transposecodec (F-order, C-order, and explicit permutation) - Chunk key encoding
defaultandv2with.or/separators - Write-time chunk controls (
zarr_chunk_rows,zarr_chunk_cols,zarr_chunk_bands) for both v2 and v3 - Strict and lenient validation modes via
zarr_validation_mode - CF-convention nodata fallbacks (
_FillValue,missing_value) - Broad CRS representation interoperability (aliases, object-style, OGC URN/URL, CF
grid_mapping,GeoTransform, affinetransform) dimension_namessemantic validation for 3D v3 arrays- OME-NGFF multi-scale group detection and automatic level-0 selection (v2 and v3)
- External fixture smoke tests (env-gated) for parity verification
Not currently supported:
- Remote / cloud stores (S3, HTTP) — use
rclonemount or pre-download as a workaround - Arbitrary N-dimensional arrays (only 2D and 3D
band,y,xlayouts) - Zarr v3 codec extensions beyond
bytes,transpose, and the listed compressors
See also: SIMD guardrail check for a script you can run locally to verify speedup and correctness.
Performance
This library uses the wide crate to provide SIMD optimizations for selected raster-processing hot paths. The current coverage includes:
- statistics accumulation over raster ranges, with explicit scalar and SIMD benchmark modes
- the strict bicubic 4x4 kernel reduction used during reprojection sampling
The wide crate offers portable SIMD abstractions that work across x86-64, ARM, WebAssembly, and other platforms without requiring unsafe code in end-user applications.
SIMD is enabled by default in this crate. There is currently no feature flag required to turn SIMD paths on.
This is a temporary implementation strategy until Portable SIMD stabilizes in Rust. Once portable SIMD is available in stable Rust, wbraster will transparently migrate to that standard approach while maintaining the same performance characteristics.
You can run the current statistics benchmark example with:
That example compares scalar and SIMD statistics paths directly and validates that both modes return matching results.
Benchmarking
Run the raster access benchmark suite:
Save results to a timestamped file:
&& |
If your shell does not support that date format, use:
&& |
Current benchmark groups:
f32_access— sequential scan:iter_f64vs directf32typed-slice access.u16_access— sequential scan:iter_f64vs directu16typed-slice access.random_access— scattered reads:get_raw(band,col,row)vs direct typed indexing with precomputed probe indices.
Interpretation tips:
- Compare
typed_*vsiter_f64to estimate conversion overhead during full-array scans. - Compare
typed_*_directvsget_raw_*to isolate bounds/indexing overhead in random-access workloads. - Use relative speedup in your target data type as the decision signal for choosing generic vs typed code paths.
Results template
Record representative medians from your local run (same machine/config for fair comparison):
| Benchmark ID | Baseline (ns/iter) | Current (ns/iter) | Speedup (baseline/current) |
Notes |
|---|---|---|---|---|
f32_access/iter_f64/512x512 |
||||
f32_access/typed_f32_slice/512x512 |
||||
f32_access/iter_f64/2048x2048 |
||||
f32_access/typed_f32_slice/2048x2048 |
||||
u16_access/iter_f64/512x512 |
||||
u16_access/typed_u16_slice/512x512 |
||||
u16_access/iter_f64/2048x2048 |
||||
u16_access/typed_u16_slice/2048x2048 |
||||
random_access/get_raw_f32/2048x2048 |
||||
random_access/typed_f32_direct/2048x2048 |
||||
random_access/get_raw_u16/2048x2048 |
||||
random_access/typed_u16_direct/2048x2048 |
Compilation Features
| Feature | Default | Purpose |
|---|---|---|
zstd-native |
yes | Native-linked Zstandard bindings for read + write. Best throughput on most platforms. |
zstd-pure-rust-decode |
no | Pure-Rust ruzstd-backed Zstandard decode only. Cannot write zstd. Suitable for WebAssembly or environments where native linking is unavailable. |
At most one zstd variant should be enabled at a time. Example — disable native, enable pure-Rust decode:
[]
= { = "0.1", = false, = ["zstd-pure-rust-decode"] }
Example — no zstd at all:
[]
= { = "0.1", = false }
All other codecs (Deflate/zlib, LZ4, LZW, JPEG, WebP, PNG, JPEG XL) are unconditionally included and require no feature flag.
Known Limitations
wbrasterfocuses on format I/O; raster analysis and processing operations belong in higher-level Whitebox tooling.- Zarr support targets local filesystem stores and 2D/3D
(band, y, x)arrays; remote/cloud stores (S3, HTTP) are not natively supported — use arcloneFUSE mount or pre-download as a workaround; arbitrary N-dimensional arrays are not supported. - GeoPackage Raster (Phase 4) supports single-dataset read by default; multi-dataset disambiguation is handled via explicit API or the
WBRASTER_GPKG_DATASETenvironment variable. - JPEG 2000 / GeoJP2 codec compatibility is evolving; treat production decode compatibility as active work.
- Reprojection uses EPSG-based source CRS metadata; formats that store CRS only as WKT require adaptive EPSG identification which may fail for uncommon or authority-marker-free WKT strings.
- BigTIFF write produces valid BigTIFF files but downstream tool compatibility (when consuming from non-GDAL tools) may vary.
License
Licensed under either of Apache License 2.0 or MIT License at your option.