Skip to content

Commit

Permalink
Added no_data_value_u64, set_no_data_value_u64, `no_data_value_i6…
Browse files Browse the repository at this point in the history
…4` and `set_no_data_value_i64` to `RasterBand` (georust#520)

* Added bindings for `GetNoDataValueAsInt64` and `GetNoDataValueAsUInt64`

* Added bindings for `GDALSetRasterNoDataValueAsInt64` and `GDALSetRasterNoDataValueAsUInt64`

* More interesting nodata values.

* Use "MEM" driver for tests.
  • Loading branch information
metasim committed Feb 1, 2024
1 parent 66d3485 commit 3c5eb45
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 8 deletions.
3 changes: 3 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Unreleased

- Added `no_data_value_u64`, `set_no_data_value_u64`, `no_data_value_i64` and `set_no_data_value_i64` to `RasterBand`.
- <https://github.com/georust/gdal/pull/520>

- **Breaking** Removed `RasterCreationOption`and replaced usages of `[RasterCreationOption]` with `RasterCreationOptions`, a type alias for `CplStringList`.

- <https://github.com/georust/gdal/pull/519>
Expand Down
97 changes: 96 additions & 1 deletion src/raster/rasterband.rs
Original file line number Diff line number Diff line change
Expand Up @@ -685,7 +685,7 @@ impl<'a> RasterBand<'a> {
None
}

/// Set the no data value of this band.
/// Sets the no-data value of this band.
///
/// If `no_data` is `None`, any existing no-data value is deleted.
pub fn set_no_data_value(&mut self, no_data: Option<f64>) -> Result<()> {
Expand All @@ -702,6 +702,101 @@ impl<'a> RasterBand<'a> {
}
}

/// Fetch the no-data value for this band.
///
/// This method should ONLY be called on bands whose data type is `UInt64`.
///
/// The no data value returned is 'raw', meaning that it has no offset and scale applied.
///
/// # Returns
/// No-data value as `Some(i64)` if no-data value exists, `None` otherwise.
///
/// # Notes
/// See also: [`GDALGetRasterNoDataValueAsUInt64`](https://gdal.org/api/raster_c_api.html#_CPPv432GDALGetRasterNoDataValueAsUInt6415GDALRasterBandHPi)
#[cfg(all(major_ge_3, minor_ge_5))]
pub fn no_data_value_u64(&self) -> Option<u64> {
let mut pb_success = 1;
let no_data = unsafe {
gdal_sys::GDALGetRasterNoDataValueAsUInt64(self.c_rasterband, &mut pb_success)
};
if pb_success == 1 {
return Some(no_data);
}
None
}

/// Sets the no-data value for a `UInt64` band.
///
/// This method should ONLY be called on bands whose data type is `UInt64`.
///
/// If `no_data` is `None`, any existing no-data value is deleted.
///
/// # Notes
/// See also:
/// [`GDALSetRasterNoDataValueAsUInt64`](https://gdal.org/api/raster_c_api.html#_CPPv432GDALSetRasterNoDataValueAsUInt6415GDALRasterBandH8uint64_t),
/// [`GDALDeleteRasterNoDataValue`](https://gdal.org/api/raster_c_api.html#_CPPv427GDALDeleteRasterNoDataValue15GDALRasterBandH)
#[cfg(all(major_ge_3, minor_ge_5))]
pub fn set_no_data_value_u64(&mut self, no_data: Option<u64>) -> Result<()> {
let rv = if let Some(no_data) = no_data {
unsafe { gdal_sys::GDALSetRasterNoDataValueAsUInt64(self.c_rasterband, no_data) }
} else {
unsafe { gdal_sys::GDALDeleteRasterNoDataValue(self.c_rasterband) }
};

if rv != CPLErr::CE_None {
Err(_last_cpl_err(rv))
} else {
Ok(())
}
}

/// Fetch the no-data value for this band.
///
/// This method should ONLY be called on bands whose data type is `Int64`.
///
/// The no data value returned is 'raw', meaning that it has no offset and scale applied.
///
/// # Returns
/// No-data value as `Some(i64)` if no-data value exists, `None` otherwise.
///
/// # Notes
/// See also: [`GDALGetRasterNoDataValueAsInt64`](https://gdal.org/api/gdalrasterband_cpp.html#_CPPv4N14GDALRasterBand21GetNoDataValueAsInt64EPi)
#[cfg(all(major_ge_3, minor_ge_5))]
pub fn no_data_value_i64(&self) -> Option<i64> {
let mut pb_success = 1;
let no_data = unsafe {
gdal_sys::GDALGetRasterNoDataValueAsInt64(self.c_rasterband, &mut pb_success)
};
if pb_success == 1 {
return Some(no_data);
}
None
}

/// Sets the no-data value for a `Int64` band.
///
/// This method should ONLY be called on bands whose data type is `Int64`.
///
/// If `no_data` is `None`, any existing no-data value is deleted.
///
/// # Notes
/// See also:
/// [`GDALSetRasterNoDataValueAsInt64`](https://gdal.org/api/raster_c_api.html#_CPPv431GDALSetRasterNoDataValueAsInt6415GDALRasterBandH7int64_t),
/// [`GDALDeleteRasterNoDataValue`](https://gdal.org/api/raster_c_api.html#_CPPv427GDALDeleteRasterNoDataValue15GDALRasterBandH)
#[cfg(all(major_ge_3, minor_ge_5))]
pub fn set_no_data_value_i64(&mut self, no_data: Option<i64>) -> Result<()> {
let rv = if let Some(no_data) = no_data {
unsafe { gdal_sys::GDALSetRasterNoDataValueAsInt64(self.c_rasterband, no_data) }
} else {
unsafe { gdal_sys::GDALDeleteRasterNoDataValue(self.c_rasterband) }
};

if rv != CPLErr::CE_None {
Err(_last_cpl_err(rv))
} else {
Ok(())
}
}
/// Returns the color interpretation of this band.
pub fn color_interpretation(&self) -> ColorInterpretation {
let interp_index = unsafe { gdal_sys::GDALGetRasterColorInterpretation(self.c_rasterband) };
Expand Down
42 changes: 35 additions & 7 deletions src/raster/tests.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::dataset::Dataset;
use crate::errors::Result;
use crate::metadata::Metadata;
use crate::raster::rasterband::ResampleAlg;
use crate::raster::{
Expand Down Expand Up @@ -424,16 +425,43 @@ fn test_get_rasterband() {
}

#[test]
fn test_get_no_data_value() {
let dataset = Dataset::open(fixture("tinymarble.tif")).unwrap();
let rasterband = dataset.rasterband(1).unwrap();
fn test_get_no_data_value() -> Result<()> {
let dataset = Dataset::open(fixture("tinymarble.tif"))?;
let rasterband = dataset.rasterband(1)?;
let no_data_value = rasterband.no_data_value();
assert!(no_data_value.is_none());

// let dataset = Dataset::open(fixture!("bluemarble.tif")).unwrap();
// let rasterband = dataset.get_rasterband(1).unwrap();
// let no_data_value = rasterband.get_no_data_value();
// assert_eq!(no_data_value, Some(0.0));
let dataset = Dataset::open(fixture("labels.tif"))?;
let rasterband = dataset.rasterband(1)?;
let no_data_value = rasterband.no_data_value();
assert_eq!(no_data_value, Some(255.0));
Ok(())
}

#[test]
#[cfg(all(major_ge_3, minor_ge_5))]
fn test_no_data_value_i64() -> Result<()> {
let driver = DriverManager::get_driver_by_name("MEM")?;
let ds = driver.create_with_band_type::<i64, _>("test_no_data_value_i64", 1, 1, 1)?;
let mut rasterband = ds.rasterband(1)?;
assert_eq!(rasterband.no_data_value_i64(), None);
rasterband.set_no_data_value_i64(Some(i64::MIN))?;
assert_eq!(rasterband.no_data_value_i64(), Some(i64::MIN));

Ok(())
}

#[test]
#[cfg(all(major_ge_3, minor_ge_5))]
fn test_no_data_value_u64() -> Result<()> {
let driver = DriverManager::get_driver_by_name("MEM")?;
let ds = driver.create_with_band_type::<u64, _>("test_no_data_value_u64", 1, 1, 1)?;
let mut rasterband = ds.rasterband(1)?;
assert_eq!(rasterband.no_data_value_u64(), None);
rasterband.set_no_data_value_u64(Some(u64::MAX))?;
assert_eq!(rasterband.no_data_value_u64(), Some(u64::MAX));

Ok(())
}

#[test]
Expand Down

0 comments on commit 3c5eb45

Please sign in to comment.