Skip to content

Commit

Permalink
Add RasterBand::write_block
Browse files Browse the repository at this point in the history
  • Loading branch information
lnicola committed Dec 10, 2023
1 parent 0527371 commit 74ffd57
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 1 deletion.
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

- Added `RasterBand::write_block`.

- <https://github.com/georust/gdal/pull/490>

- `RasterBand::read_block` now checks that the requested type matches the band type.

- <https://github.com/georust/gdal/pull/489>
Expand Down
35 changes: 35 additions & 0 deletions src/raster/rasterband.rs
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,41 @@ impl<'a> RasterBand<'a> {
Array2::from_shape_vec((size.1, size.0), data).map_err(Into::into)
}

#[cfg(feature = "ndarray")]
#[cfg_attr(docsrs, doc(cfg(feature = "array")))]
/// Read a [`Array2<T>`] from a [`Dataset`] block, where `T` implements [`GdalType`].
///
/// # Arguments
/// * `block_index` - the block index
///
/// # Notes
/// The Matrix shape is (rows, cols) and raster shape is (cols in x-axis, rows in y-axis).
pub fn write_block<T: Copy + GdalType>(
&mut self,
block_index: (usize, usize),
block: Array2<T>,
) -> Result<()> {
if T::gdal_ordinal() != self.band_type() as u32 {
return Err(GdalError::BadArgument(
"array type must match band data type".to_string(),
));
}

let mut data = block.into_raw_vec();
let rv = unsafe {
gdal_sys::GDALWriteBlock(
self.c_rasterband,
block_index.0 as c_int,
block_index.1 as c_int,
data.as_mut_ptr() as GDALRasterBandH,
)
};
if rv != CPLErr::CE_None {
return Err(_last_cpl_err(rv));
}
Ok(())
}

/// Write a [`Buffer<T>`] into a [`Dataset`].
///
/// # Arguments
Expand Down
52 changes: 51 additions & 1 deletion src/raster/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use std::path::Path;
use std::str::FromStr;

#[cfg(feature = "ndarray")]
use ndarray::arr2;
use ndarray::{arr2, Array2, Axis};

#[test]
fn test_open() {
Expand Down Expand Up @@ -393,6 +393,56 @@ fn test_read_block_data() {
assert_eq!(array[[0, 99]], 51);
}

#[test]
#[cfg(feature = "ndarray")]
fn test_write_block() {
let driver = DriverManager::get_driver_by_name("GTiff").unwrap();
let options = [
RasterCreationOption {
key: "TILED",
value: "YES",
},
RasterCreationOption {
key: "BLOCKXSIZE",
value: "16",
},
RasterCreationOption {
key: "BLOCKYSIZE",
value: "16",
},
];
let dataset = driver
.create_with_band_type_with_options::<u16, _>(
"/vsimem/test_write_block.tif",
32,
32,
1,
&options,
)
.unwrap();

let mut block_11 = Array2::from_shape_fn((16, 16), |(y, x)| y as u16 * 16 + x as u16 + 1000u16);
let mut block_12 = Array2::from_shape_fn((16, 16), |(y, x)| y as u16 * 16 + x as u16 + 3000u16);
let block_21 = Array2::from_shape_fn((16, 16), |(y, x)| y as u16 * 16 + x as u16 + 2000u16);
let block_22 = Array2::from_shape_fn((16, 16), |(y, x)| y as u16 * 16 + x as u16 + 4000u16);

let mut band = dataset.rasterband(1).unwrap();
band.write_block((0, 0), block_11.clone()).unwrap();
band.write_block((1, 0), block_21.clone()).unwrap();
band.write_block((0, 1), block_12.clone()).unwrap();
band.write_block((1, 1), block_22.clone()).unwrap();

block_11.append(Axis(1), block_21.view()).unwrap();
block_12.append(Axis(1), block_22.view()).unwrap();
block_11.append(Axis(0), block_12.view()).unwrap();

let buf = band
.read_as::<u16>((0, 0), (32, 32), (32, 32), None)
.unwrap();
let arr = ndarray::Array2::from_shape_vec((32, 32), buf.data).unwrap();
assert_eq!(arr, block_11);
}

#[test]
fn test_get_band_type() {
let driver = DriverManager::get_driver_by_name("MEM").unwrap();
Expand Down

0 comments on commit 74ffd57

Please sign in to comment.