Changelog
All notable changes to rwarp. Dates are when the change reached main.
Unreleased
Added
- A spherical measure for conservative weights (stage 3a of
design/conservative.md):WeightOptions::with_measurewithweights::lonlat_measure(src_gt)measures areas on the sphere for a source on a regular longitude/latitude grid, through controlledburn'sMeasure::CosLatitude(closed-form edge integrals ofcos(lat); the cell partition and conservation are unchanged).Weightsrecords themeasure,Weights::src_area(k)gives an entry's source cell measure, andnormalised,dst_coveredandapplyweight overlaps by it; for the default planar measure every cell is 1 and results are unchanged, bit for bit. Exact against closed-form lon/lat box overlaps on the sphere (to 1e-14). Needs controlledburn 0.2.4. (2026-10-29) - ESMF oracle suite (stage 2 of
design/conservative.md,tests/esmf.rs): six cases, each against ESMPy 8.9.1's first-order conservative weights in Cartesian source pixel space (rwarp's cell definition: equal to about 1e-12) and on the sphere with great-circle edges (differences recorded as ceilings to shrink). Fixtures fromtests/fixtures/esmf/gen.py, run inghcr.io/hypertidy/gdal-r-esmfby.github/workflows/esmf-fixtures.yml. (2026-10-29)
Changed
- The
serdefeature also enables controlledburn's, forMeasureinWeightOptionsandWeights. (2026-10-29)
0.3.1 (2026-10-28)
Added
- Longitude wrapping of a geographic source, GDAL's
CENTER_LONG:GenImgProjTransformer::with_source_sizelets the transformer wrap source longitudes around the source raster's centre as gdalwarp does (InsertCenterLong,OGRProjCT), so a source stored as 170..190, -190..-170 or 0..360 is found by a target crossing 180 degrees.CenterLong(Auto, the default;Off;At(lon),#[non_exhaustive]) withwith_center_long,with_target_extentfor gdalwarp's-te,center_long(),source_center_longfor GDAL's centre, andcrs::is_geographic_degrees. A transformer built withoutwith_source_sizewraps nothing, as before. Checked against GDAL 3.14.0dev on 11 cases across 180 degrees (LAEA, Mercator, polar stereographic, lon/lat targets; chunked and whole): centres, exact transformer points, chunk lists and every output pixel, with both CRS backends. The LAEA chunk fixtures are back across 180 degrees. Theprojfeature now also depends onproj-sys(already a dependency ofproj), to ask PROJ whether a CRS is geographic. weightsmodule: conservative remapping weights from the exact footprint, as values (stage 1 ofdesign/conservative.md).exact_weightsreturnsWeights, one entry per overlapping (target cell, source cell) pair with full-grid indices and the overlap as an unroundedf64fraction of the source cell, plus each target cell's outline area in source pixel space (dst_area,NaNwhere it failed).Weights::normalisedgives ESMF'sSunderNormalization::FracAreaorDestArea;Weights::applyapplies the weights to one or more bands, skipping source nodata;Weights::esmf_row_colgives ESMF/SCRIP's 1-based flattened indices.exact_weights_withstreams them per target cell.WeightOptions(densify, target offset for tiling, drop and snap tolerances,f32rounding;WeightOptions::warp_compatible),ApplyOptionsandGridWindow, all#[non_exhaustive]with builders; serde derives behindserde.apply(FracArea)with warp-compatible weights reproduceswarp()withFootprint::ExactandAveragebit for bit.warp()shares the lattice and per-pixel coverage step and its output is unchanged. (2026-10-28)- GDAL's backmap geolocation inverse, as an option beside the quad index:
GeolocOptions::with_inverse(GeolocInverse::Backmap)(GeolocInverse:QuadIndex, the default;Backmap;BackmapEstimateforGDAL_GEOLOC_USE_MAX_ACCURACY=NO;#[non_exhaustive]), withwith_backmap_oversample(GEOLOC_BACKMAP_OVERSAMPLE_FACTOR) andGeolocArrays::backmap_grid. Ported from GDAL 3.14 in its arithmetic order (float32 backmap,GDALFillNodatahole filling, the spiral search), by way of wxylib'swxy-warp(geoloc.rs, GDAL 3.12; the geolocation code is unchanged since), addingPIXEL_OFFSET/STEP. Checked against GDAL 3.14.0dev on 9 new cases (swath by centres and by corners, lon/lat and polar stereographic targets, a polar ring and a swath across the antimeridian, holes in the arrays with source nodata, overlapping scans): success and position at every target pixel, the backmap's estimate, and 24 warps (near, bilinear, cubic;-et 0and0.125) identical to gdalwarp, every pixel, with proj4rs and the fixtures' PROJ (with an older libproj, nearest identical and interpolated values within 2e-8 relative). Where the two inverses differ, and why, is in the curvilinear guide. (2026-10-28)
Changed
- The chunk fixtures' special points are computed as GDAL computes them for
a geographic source (not reprojected; see
ChunkOptions::special_points). No chunk list changes. warp()does GDAL'sGWKAdjustSrcOffsetOnEdge: when a corner of the source buffer fails to transform forward and a sample point lands on an invalid source pixel whose corners fail too, a valid neighbour (right, below, left, above) is used instead. This changes output only where the transformer has holes or edges inside the source, as geolocation arrays with missing samples do (12 of 4560 pixels in the holes test case, now identical to gdalwarp).warp()therefore calls the transformer source to destination too, for such pixels only. Point methods; GDAL's variant for alpha and cutline densities is not reproduced. (2026-10-28)- The geolocation swath fixture is regenerated with GDAL 3.14.0dev (was 3.8.4): positions moved by up to 3e-8 pixels (PROJ), nothing else.
- controlledburn 0.2.3 (corner passes, near-coincident edges, exact centre
ties). The cutline centre rule now matches gdalwarp on centres exactly on
diagonal edges: 5 pixels of the
mask_diamond_tiefixture that differed now agree. They came from controlledburn 0.2.2's rounded intercepts; the parity page had put them down to GDAL.
0.3.0 (2026-10-28)
This release changes the API: options types are #[non_exhaustive].
Changed
warp()retries a sample point that lands less than one pixel outside the source buffer by transforming it again on its own, as GDAL does (GWKCheckAndComputeSrcOffsets). ThroughApproxTransformerthat is exact, so interpolation error no longer drops pixels at the edge of a chunk's source window; with an exact transformer nothing changes. Point methods only (nearest, bilinear, cubic, cubic spline, lanczos), as in GDAL. (2026-10-28)WarpOptions,GeolocOptionsandAverageThresholdsare#[non_exhaustive], as areResampleAlg,KernelScaling,Footprint,BandNodata,Nodata,DstNodata,DataTypeandGeolocConvention. New options and methods can then come in minor releases. Outside rwarp, build options withWarpOptions::new(alg)and thewith_methods (GeolocOptions::default().with_convention(..), and so on) instead of struct literals, and add a_arm when matching on the enums. Fields stay public for reading and assignment.
Added
WarpOptions::newandwith_builder methods onWarpOptions,GeolocOptionsandAverageThresholds.planmodule:plan_chunksandChunkPlannergive gdalwarp's chunk list as values (WarpPlanofChunks: target window, source window, fill ratio, kernel scale), following GDAL 3.14'sCollectChunkListandComputeSourceWindowexactly: warp memory limit (-wm) and per-pixel cost, fill ratio splits,OPTIMIZE_SIZEon target blocks, special points, the forward probe,SAMPLE_GRID,SAMPLE_STEPS,SOURCE_EXTRA.ChunkOptions(builders,#[non_exhaustive]);ChunkOptions::gdalwarpfor gdalwarp's planning exactly; an optional round-trip check for backends that do not fail at a projection's antipode; the antimeridian split of 0.2'scollect_chunk_listassplit_antimeridian.warp_chunkswarps a plan from a source buffer in memory. Ported from wxylib'swxy-warp(chunked.rs). (2026-10-28)serdefeature:Serialize/DeserializeforWarpPlanandChunk. (2026-10-28)- Parity fixtures for whole rasters warped in many chunks
(
tests/chunks.rs,tests/fixtures/chunks/): seven gdalwarp cases, chunk lists and output identical. (2026-10-28) - Cutlines (gdalwarp
-cutline):WarpOptions::cutline/with_cutline, and thecutlinemodule withCutline(polygons in source pixel/line),CutlineRule::Centre(GDAL's default, with its tie rules),CutlineRule::AllTouched(CUTLINE_ALL_TOUCHED), blend distance (-cblend), andCutlineRule::Exact, which weights each source pixel by the fraction of it the cutline covers (not a GDAL mode).Cutline::from_geotransformandCutline::from_transformer(densified as gdalwarp does) map world geometry to source pixels;Cutline::densityis the per-pixel density the warp uses. The cutline is rasterized over the source buffer only, withcontrolledburn.
Removed
source_window::collect_chunk_listandChunkPlan: useplan::plan_chunks(withChunkOptions::split_antimeridianfor the same split at the antimeridian).compute_source_windowstays. (2026-10-28)
0.2.0 (2026-10-28)
This release changes the API: warp() with WarpOptions and
SourceBuffer replaces the warp entry points of 0.1, and ResampleAlg
gains variants.
Added
-
geoloc_transform: geolocation-array transformers, for a curvilinear source (gdalwarp -geoloc), a curvilinear target (DST_METHOD=GEOLOC_ARRAY), or both. Both of GDAL's georeferencing conventions; offsets and steps; nodata; antimeridian handling. (2026-10-28) -
warp(),WarpOptions,SourceBuffer: one entry point for every sample type, method and option.WarpOptionscarries a destination offset for warping one tile of a larger grid. (2026-10-28) -
KernelScaling: GDAL's kernel widening when downsampling, now the default;FixedandPointalternatives.estimate_scaleis public. (2026-10-28) -
ResampleAlg::Average, withFootprint::GdalBox(gdalwarp's) andFootprint::Exact(first-order conservative).controlledburnis a new dependency. (2026-10-28) -
ResampleAlg::ModewithModeTies(MODE_TIES). (2026-10-28) -
BandNodata(UNIFIED_SRC_NODATA) andAverageThresholds(NODATA_VALUES_PCT_THRESHOLD,EXCLUDED_VALUES). (2026-10-28) -
ResampleAlg::CubicSpline,Min,Max,Med,Q1,Q3andRms, andResampleAlg::is_area(). (2026-10-28) -
Samplefori64,u64, andhalf::f16behind a newf16feature. (2026-10-28) -
warp_to::<S, D>: a different output type from the source's, through GDAL's working type (DataType::working) andGDALCopyWordsconversion. (2026-10-28) -
NodataandDstNodata: source and destination nodata per band, as gdalwarp's-srcnodataand-dstnodata. (2026-10-28) -
Examples:
tile_laea,curvilinear_swath. -
A documentation site, with the browser demo under
/demo/.
Changed
- Integer outputs round half up and clamp, and a resampled value equal to nodata is moved off it, as gdalwarp does with an integer working type.
- Sample points outside
[0, n)of the source are off the source for every point method, as in GDAL. - Lanczos clips its window and renormalises at edges and nodata, and a target pixel whose centre lands on nodata gets no value, for every interpolating kernel. Some edge and nodata pixels change compared with 0.1.
- Multi-band nodata follows GDAL's default (a pixel is nodata only where
every band is); the 0.1 rule is
BandNodata::AnyBand. SamplerequiresPartialOrd.Footprint::Exactis 2 to 6x faster. The destination pixel lattice is transformed once per row band (shared corners and edge points) instead of four points per pixel, and coverage comes fromcontrolledburn::CoverageWindow(0.2.2) instead of oneburncall per pixel. With an exact transformer the output is unchanged, except for pixels straddling the antimeridian, which the exact footprint does not handle (it gave a different wrong answer before). The lattice's row lines go to the transformer as scanlines, so anApproxTransformernow approximates them, as for the box footprint; before, it transformed the exact footprint's points exactly.WarpOptionsis not generic:nodata: Option<T>is replaced bysrc_nodata: Nodataanddst_nodata: DstNodata.- Bilinear uses GDAL's general formula for types and cases where GDAL does, which can change the last bit (and so integer rounding near 2^40 for 64-bit values).
Deprecated
warp_resample_tandwarp_resample_u8, kept as shims with the 0.1 point-kernel behaviour. Usewarp().
Fixed
- Nearest neighbour mapped source coordinates in (-1, 0) to pixel 0.
ApproxTransformerleft one point untransformed and reported it failed when subdivision reached a left half of two points, which happens on strongly curved transforms or with a small error threshold (whole columns of a polar warp came out as nodata). GDAL transforms it.
0.1.2 (2026-03-11, not on crates.io)
- Use the system libproj through
proj0.31.
Not released to crates.io. On main after it (2026-09 to 2026-10):
rwarp-wasm: browser shim and demo (OSM, WMTS, ArcGIS tile services, COG sources),Warper.withTransformsfor JavaScript CRS transforms.- A generic
Samplekernel overu8tof64, interleaved bands, nodata as a value or an alpha band. - The
CrsTransformtrait withprojandproj4rsbackends; builds forwasm32-unknown-unknown.
0.1.1 (2026-03-06)
GcpTransformer: polynomial transformer from ground control points, order 1 to 3.- Use the published
vastercrate; crate documentation.
0.1.0 (2026-03-06)
- First release, extracted from cogcache:
GenImgProjTransformer,ApproxTransformer,compute_source_window,collect_chunk_listand the nearest, bilinear, cubic and lanczos kernels.