Skip to content

Commit 74edd48

Browse files
committed
Scaffolding for GDALWarp binding.
1 parent 616c954 commit 74edd48

File tree

3 files changed

+140
-16
lines changed

3 files changed

+140
-16
lines changed

src/raster/mod.rs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
//! ```
7676
7777
pub use buffer::{Buffer, ByteBuffer};
78+
pub use create_options::RasterCreationOptions;
7879
#[cfg(all(major_ge_3, minor_ge_1))]
7980
pub use mdarray::{
8081
Attribute, Dimension, ExtendedDataType, ExtendedDataTypeClass, Group, MDArray, MdStatisticsAll,
@@ -87,6 +88,7 @@ pub use rasterize::{rasterize, BurnSource, MergeAlgorithm, OptimizeMode, Rasteri
8788
pub use types::{AdjustedValue, GdalDataType, GdalType};
8889

8990
mod buffer;
91+
mod create_options;
9092
pub mod dem;
9193
#[cfg(all(major_ge_3, minor_ge_1))]
9294
mod mdarray;
@@ -96,13 +98,3 @@ mod rasterize;
9698
mod tests;
9799
mod types;
98100
pub mod warp;
99-
100-
/// Key/value pair for passing driver-specific creation options to
101-
/// [`Driver::create_with_band_type_wth_options`](crate::Driver::create_with_band_type_with_options`).
102-
///
103-
/// See `papszOptions` in [GDAL's `Create(...)` API documentation](https://gdal.org/api/gdaldriver_cpp.html#_CPPv4N10GDALDriver6CreateEPKciii12GDALDataType12CSLConstList).
104-
#[derive(Debug)]
105-
pub struct RasterCreationOption<'a> {
106-
pub key: &'a str,
107-
pub value: &'a str,
108-
}

src/raster/warp/mod.rs

Lines changed: 93 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ mod reproject_options;
99
mod resample;
1010
mod warp_options;
1111

12-
use gdal_sys::CPLErr;
12+
use gdal_sys::{CPLErr, GDALDatasetH, GDALWarp};
1313
pub use reproject_options::*;
1414
pub use resample::*;
1515
use std::ffi::CString;
16-
use std::path::Path;
16+
use std::path::{Path, PathBuf};
1717
use std::ptr;
1818
pub use warp_options::*;
1919

@@ -22,7 +22,7 @@ use crate::DriverManager;
2222

2323
use crate::errors::*;
2424
use crate::spatial_ref::SpatialRef;
25-
use crate::utils::{_last_cpl_err, _path_to_c_string};
25+
use crate::utils::{_last_cpl_err, _last_null_pointer_err, _path_to_c_string};
2626

2727
/// Reproject raster dataset into the given [`SpatialRef`] and save result to `dst_file`.
2828
pub fn create_and_reproject<P: AsRef<Path>>(
@@ -163,6 +163,79 @@ pub fn reproject_into(
163163
Ok(())
164164
}
165165

166+
pub fn warp<D>(source: &Dataset, dest: D, options: &GdalWarpOptions) -> Result<Dataset>
167+
where
168+
D: Into<WarpDestination>,
169+
{
170+
warp_multiple(&[source], dest, options)
171+
}
172+
173+
pub fn warp_multiple<D>(source: &[&Dataset], dest: D, options: &GdalWarpOptions) -> Result<Dataset>
174+
where
175+
D: Into<WarpDestination>,
176+
{
177+
let app_opts = GdalWarpAppOptions::default();
178+
179+
if true {
180+
todo!("how the hell do you go from {options:?} to GdalWarpAppOptions?");
181+
}
182+
183+
let mut source = source.iter().map(|ds| ds.c_dataset()).collect::<Vec<_>>();
184+
185+
let dest = dest.into();
186+
match dest {
187+
WarpDestination::Dataset(ds) => {
188+
let ds_c = unsafe {
189+
GDALWarp(
190+
ptr::null_mut(),
191+
ds.c_dataset(),
192+
source.len() as libc::c_int,
193+
source.as_mut_ptr(),
194+
app_opts.as_ptr(),
195+
ptr::null_mut(),
196+
)
197+
};
198+
if ds_c.is_null() {
199+
Err(_last_null_pointer_err("GDALWarp"))
200+
} else {
201+
Ok(ds)
202+
}
203+
}
204+
WarpDestination::Path(p) => {
205+
let path = _path_to_c_string(&p)?;
206+
let ds_c = unsafe {
207+
GDALWarp(
208+
path.as_ptr(),
209+
ptr::null_mut(),
210+
source.len() as libc::c_int,
211+
source.as_ptr() as *mut GDALDatasetH,
212+
app_opts.as_ptr(),
213+
ptr::null_mut(),
214+
)
215+
};
216+
Ok(unsafe { Dataset::from_c_dataset(ds_c) })
217+
}
218+
}
219+
}
220+
221+
#[derive(Debug)]
222+
pub enum WarpDestination {
223+
Dataset(Dataset),
224+
Path(PathBuf),
225+
}
226+
227+
impl From<Dataset> for WarpDestination {
228+
fn from(ds: Dataset) -> Self {
229+
WarpDestination::Dataset(ds)
230+
}
231+
}
232+
233+
impl From<PathBuf> for WarpDestination {
234+
fn from(path: PathBuf) -> Self {
235+
WarpDestination::Path(path)
236+
}
237+
}
238+
166239
#[cfg(test)]
167240
mod tests {
168241
use super::*;
@@ -251,4 +324,21 @@ mod tests {
251324

252325
Ok(())
253326
}
327+
328+
#[test]
329+
#[ignore]
330+
fn test_warp() -> Result<()> {
331+
let source = TempFixture::fixture("labels.tif");
332+
let source_ds = Dataset::open(&source)?;
333+
let dest = Path::new("target").join("labels-warp.tif");
334+
335+
let mut options = GdalWarpOptions::default();
336+
options
337+
.with_band_count(source_ds.raster_count())
338+
.with_initial_value(InitValue::NoData)
339+
.with_resampling_alg(WarpResampleAlg::NearestNeighbour);
340+
341+
warp(&source_ds, dest, &options)?;
342+
Ok(())
343+
}
254344
}

src/raster/warp/warp_options.rs

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::fmt::{Debug, Display, Formatter};
2+
use std::ptr;
23
use std::ptr::NonNull;
34

45
use crate::cpl::CslStringList;
@@ -9,9 +10,9 @@ use crate::utils::_last_null_pointer_err;
910
use crate::xml::GdalXmlNode;
1011
use gdal_sys::{
1112
GDALCloneWarpOptions, GDALCreateWarpOptions, GDALDeserializeWarpOptions,
12-
GDALDestroyWarpOptions, GDALSerializeWarpOptions, GDALWarpInitDefaultBandMapping,
13-
GDALWarpInitDstNoDataReal, GDALWarpInitSrcNoDataReal, GDALWarpOptions,
14-
GDALWarpResolveWorkingDataType,
13+
GDALDestroyWarpOptions, GDALSerializeWarpOptions, GDALWarpAppOptions, GDALWarpAppOptionsFree,
14+
GDALWarpAppOptionsNew, GDALWarpInitDefaultBandMapping, GDALWarpInitDstNoDataReal,
15+
GDALWarpInitSrcNoDataReal, GDALWarpOptions, GDALWarpResolveWorkingDataType,
1516
};
1617
use libc::c_char;
1718

@@ -246,6 +247,47 @@ impl Debug for GdalWarpOptions {
246247
}
247248
}
248249

250+
#[derive(Debug)]
251+
pub struct GdalWarpAppOptions(NonNull<GDALWarpAppOptions>);
252+
253+
impl GdalWarpAppOptions {
254+
/// Instatiate and empty set of warp options.
255+
pub fn new() -> Self {
256+
unsafe { Self::from_ptr(GDALWarpAppOptionsNew(ptr::null_mut(), ptr::null_mut())) }
257+
}
258+
259+
/// Create Self from a raw pointer.
260+
///
261+
/// # Safety
262+
/// Caller is responsible for ensuring `ptr` is not null, and
263+
/// ownership of `ptr` is properly transferred
264+
pub unsafe fn from_ptr(ptr: *mut GDALWarpAppOptions) -> Self {
265+
Self(NonNull::new_unchecked(ptr))
266+
}
267+
268+
/// Get a immutable pointer to C API options.
269+
pub fn as_ptr(&self) -> *const GDALWarpAppOptions {
270+
self.0.as_ptr()
271+
}
272+
273+
/// Get a mutable pointer to C API options.
274+
pub fn as_ptr_mut(&mut self) -> *mut GDALWarpAppOptions {
275+
self.0.as_ptr()
276+
}
277+
}
278+
279+
impl Drop for GdalWarpAppOptions {
280+
fn drop(&mut self) {
281+
unsafe { GDALWarpAppOptionsFree(self.as_ptr_mut()) }
282+
}
283+
}
284+
285+
impl Default for GdalWarpAppOptions {
286+
fn default() -> Self {
287+
Self::new()
288+
}
289+
}
290+
249291
/// Specifies the initial value cells in the destination dataset during a warp operation.
250292
///
251293
/// See [`GdalWarpOptions::with_initial_value`].

0 commit comments

Comments
 (0)