geotiff-rust
Pure-Rust TIFF/BigTIFF and GeoTIFF/COG readers and writers. No C libraries, no build scripts, no unsafe beyond memmap2.
Crates
| Crate | Description |
|---|---|
tiff-core |
Shared TIFF types: ByteOrder, tags, sample traits, compression/predictor enums, and color-model metadata |
tiff-reader |
TIFF/BigTIFF decoder with mmap, strip/tile reads, storage-domain reads, and explicit decoded pixel access |
tiff-writer |
TIFF/BigTIFF encoder with streaming writes, compression, predictors, and BigTIFF |
geotiff-core |
Shared GeoTIFF types: GeoKeyDirectory, CRS, GeoTransform, tag constants |
geotiff-reader |
GeoTIFF reader with CRS/transform extraction, overview discovery, and optional HTTP COG access |
geotiff-writer |
GeoTIFF/COG writer with fluent builder, tile-wise GeoTIFF writes, and overview generation |
Reading
use GeoTiffFile;
let file = open?;
println!;
let raster: ArrayD = file.read_raster?;
Use read_decoded_raster / read_decoded_window on GeoTiffFile and
read_decoded_image / read_decoded_window on TiffFile when you want
palette expansion or color-space conversion (for example palette TIFF,
YCbCr, or CMYK) instead of storage-domain samples.
Use read_band / read_band_window on GeoTiffFile and TiffFile when
you only need one storage-domain band as a [rows, cols] array.
Writing
use ;
use Array2;
let data = zeros;
new
.epsg
.pixel_scale
.origin
.nodata
.compression
.write_2d?;
For separate-planar multiband output, set
planar_configuration(PlanarConfiguration::Planar) on ImageBuilder or
GeoTiffBuilder.
Streaming tile writes
use GeoTiffBuilder;
use Array2;
let builder = new
.tile_size
.epsg;
let mut writer = builder.?;
for in tiles
writer.finish?;
COG with overviews
use ;
use Array2;
let data = zeros;
new
.overview_levels
.resampling
.write_2d?;
For multi-band COG output, use write_3d/write_3d_to or write_tile_3d
with bands(...) and optional
planar_configuration(PlanarConfiguration::Planar).
Features
Read
- Classic TIFF and BigTIFF
- Little-endian and big-endian byte orders
- Strip and tile data access with windowed reads
- Chunky and separate planar sample layouts
- Full-raster and windowed single-band reads, optimized for separate-planar rasters
- Compression: Deflate, LZW, PackBits, LERC, LERC+DEFLATE, JPEG (optional), ZSTD (optional), LERC+ZSTD (optional)
- Bounded IFD parsing and block decompression budgets for untrusted input
- Parallel decompression via Rayon
- Storage-domain typed sample reads via
read_*/read_*_samples - Explicit decoded pixel reads via
read_decoded_*for standard TIFF color models, including palette expansion, YCbCr/CMYK conversion, and sub-byte grayscale/palette decode - Structured photometric/color-model metadata: palette
ColorMap,ExtraSamples, CMYK, and YCbCr - GeoKey directory, structured CRS metadata (projected, geographic, geocentric, vertical, compound), transforms, NoData
- Overview discovery from both reduced-resolution top-level IFDs and recursive base-image SubIFD-backed overview trees
- Optional HTTP range-backed remote COG access
Write
- Classic TIFF and BigTIFF with auto-detection
- Strip and tile layouts
- Compression: Deflate, LZW, JPEG (optional), LERC, LERC+DEFLATE, ZSTD (optional), LERC+ZSTD (optional)
- Predictors: horizontal differencing, floating-point byte interleaving
- Chunky and separate planar multi-band layouts and all sample types (u8 through f64)
- Photometric/color-model tags: palette
ColorMap,ExtraSamplesalpha, CMYK (Separated+InkSet), and YCbCr 4:4:4 - Streaming tile-by-tile GeoTIFF writes for large rasters
- GeoTIFF metadata: GeoTIFF 1.1 key-directory emission, projected/geographic/geocentric/vertical compound CRS keys, pixel scale, origin, affine transforms, NoData
- COG output with GDAL-compatible ghost-area metadata, overview generation (nearest-neighbor, average), top-level or SubIFD-backed overview IFDs, and multi-band chunky/planar rasters
- Disk-backed tile-wise COG assembly via
CogTileWriter(base tiles are staged in a temporary raw tile store before final emission)
Codec Notes
JPEG-in-TIFF write uses standard compression code 7 with full JPEG
interchange streams per strip/tile. The supported interoperable layouts are
single-band chunky output and multi-band separate-planar output, which keeps
TIFF, GeoTIFF, and COG files compatible with GDAL/libtiff without requiring
TIFF-side shared JPEGTables.
TIFF LERC writing records the registered LERC2 2.4 parameter version used by
GDAL/libtiff. If the encoder produces a different LERC2 container version, the
writer rejects the block before writing incompatible TIFF metadata.
Robustness Notes
TiffFile::open_with_options, from_bytes_with_options, and
from_source_with_options accept OpenOptions with ParseBudgets for bounding
IFD chain length, tag counts, and metadata payload bytes. GeoTiffFile
exposes the same settings as GeoTiffOpenOptions, and HTTP COG opens pass them
through HttpOpenOptions::tiff_options. The reader also derives encoded
strip/tile read limits and decompressed output limits from the raster layout
before reading block payloads.
Feature flags
| Flag | Default | Description |
|---|---|---|
local |
yes | Local file reading via tiff-reader (geotiff-reader) |
rayon |
yes | Parallel strip/tile decompression (tiff-reader, geotiff-reader) |
jpeg |
yes | JPEG-in-TIFF read/write support (tiff-reader, tiff-writer) |
zstd |
yes | ZSTD compression, including TIFF LERC+ZSTD read/write support (tiff-reader, tiff-writer) |
cog |
no | HTTP range-backed remote COG open (geotiff-reader) |
Testing
Reference-library parity tests are included for tiff-reader and
geotiff-reader. They compare this workspace against GDAL/libtiff when those
tools are available locally; otherwise they self-skip. Lossless codecs use
exact byte and hash parity. The JPEG fixture uses a strict bounded-delta check
because compliant decoders can differ by +/-1 in a small number of samples.
For a reproducible reference environment, run the Docker harness:
For reference comparisons and current benchmark results against GDAL/libtiff, see docs/benchmark-report.md.
For the workspace release order and package verification notes, see docs/publishing.md.
License
MIT OR Apache-2.0