Skip to content

Commit

Permalink
Implemented RasterBand::read_block using the Buffer API, enabling…
Browse files Browse the repository at this point in the history
… block reading without `array` feature.

`Rasterband::read_block` renamed `Rasterband::read_block_as_array` to be consistent with `read_as` vs. `read_as_array`.
  • Loading branch information
metasim committed Dec 17, 2023
1 parent 4d035df commit 9095de2
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 9 deletions.
5 changes: 5 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## Unreleased

- **Breaking**: `Rasterband::read_block` renamed `Rasterband::read_block_as_array` to be consistent with `read_as` vs. `read_as_array`.
- Implemented `RasterBand::read_block` using the `Buffer` API, enabling block reading without `array` feature.

- <>

- Defers the gdal_i.lib missing message until after the pkg-config check and outputs pkg-config metadata in case of a static build.

- <https://github.com/georust/gdal/pull/492>
Expand Down
2 changes: 1 addition & 1 deletion src/raster/mdarray.rs
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ impl<'a> MDArray<'a> {

#[cfg(feature = "ndarray")]
#[cfg_attr(docsrs, doc(cfg(feature = "array")))]
/// Read a 'Array2<T>' from this band. T implements 'GdalType'.
/// Read a [`ArrayD<T>`] from this band. T implements [`GdalType`].
///
/// # Arguments
/// * `window` - the window position from top left
Expand Down
48 changes: 43 additions & 5 deletions src/raster/rasterband.rs
Original file line number Diff line number Diff line change
Expand Up @@ -522,9 +522,7 @@ impl<'a> RasterBand<'a> {
self.read_as::<T>((0, 0), (size.0, size.1), (size.0, size.1), None)
}

#[cfg(feature = "ndarray")]
#[cfg_attr(docsrs, doc(cfg(feature = "array")))]
/// Read a [`Array2<T>`] from a [`Dataset`] block, where `T` implements [`GdalType`].
/// Read a [`Buffer<T>`] from a [`Dataset`] block, where `T` implements [`GdalType`].
///
/// # Arguments
/// * `block_index` - the block index
Expand All @@ -550,11 +548,11 @@ impl<'a> RasterBand<'a> {
/// let dataset = Dataset::open("fixtures/m_3607824_se_17_1_20160620_sub.tif")?;
/// let band1 = dataset.rasterband(1)?;
/// let arr = band1.read_block::<u8>((0, 0))?;
/// assert_eq!(arr.shape(), &[300, 6]);
/// assert_eq!(arr.size, (300, 6));
/// # Ok(())
/// # }
/// ```
pub fn read_block<T: Copy + GdalType>(&self, block_index: (usize, usize)) -> Result<Array2<T>> {
pub fn read_block<T: Copy + GdalType>(&self, block_index: (usize, usize)) -> Result<Buffer<T>> {
if T::gdal_ordinal() != self.band_type() as u32 {
return Err(GdalError::BadArgument(
"result array type must match band data type".to_string(),
Expand Down Expand Up @@ -582,6 +580,46 @@ impl<'a> RasterBand<'a> {
data.set_len(pixels);
};

Ok(Buffer::new(size, data))
}

#[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
/// Blocks indexes start from 0 and are of form (x, y), where x grows in the horizontal direction.
///
/// The matrix shape is (rows, cols) and raster shape is (cols in x-axis, rows in y-axis).
///
/// The block size of the band can be determined using [`RasterBand::block_size`].
/// The last blocks in both directions can be smaller.
/// [`RasterBand::actual_block_size`] will report the correct dimensions of a block.
///
/// # Errors
/// If the block index is not valid, GDAL will return an error.
///
/// # Example
///
/// ```rust, no_run
/// # fn main() -> gdal::errors::Result<()> {
/// use gdal::Dataset;
///
/// let dataset = Dataset::open("fixtures/m_3607824_se_17_1_20160620_sub.tif")?;
/// let band1 = dataset.rasterband(1)?;
/// let arr = band1.read_block_as_array::<u8>((0, 0))?;
/// assert_eq!(arr.shape(), &[300, 6]);
/// # Ok(())
/// # }
/// ```
pub fn read_block_as_array<T: Copy + GdalType>(
&self,
block_index: (usize, usize),
) -> Result<Array2<T>> {
let Buffer { size, data } = self.read_block(block_index)?;
Array2::from_shape_vec((size.1, size.0), data).map_err(Into::into)
}

Expand Down
6 changes: 3 additions & 3 deletions src/raster/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ fn test_read_block_as_array() {
let block_index = (0, 0);
let dataset = Dataset::open(fixture("tinymarble.tif")).unwrap();
let rasterband = dataset.rasterband(band_index).unwrap();
let result = rasterband.read_block::<u8>(block_index);
let result = rasterband.read_block_as_array::<u8>(block_index);
assert!(result.is_ok());
}

Expand All @@ -375,7 +375,7 @@ fn test_read_block_dimension() {
let block = (0, 0);
let dataset = Dataset::open(fixture("tinymarble.tif")).unwrap();
let rasterband = dataset.rasterband(band_index).unwrap();
let array = rasterband.read_block::<u8>(block).unwrap();
let array = rasterband.read_block_as_array::<u8>(block).unwrap();
assert_eq!(array.dim(), (27, 100));
}

Expand All @@ -386,7 +386,7 @@ fn test_read_block_data() {
let block = (0, 0);
let dataset = Dataset::open(fixture("tinymarble.tif")).unwrap();
let rasterband = dataset.rasterband(band_index).unwrap();
let array = rasterband.read_block::<u8>(block).unwrap();
let array = rasterband.read_block_as_array::<u8>(block).unwrap();
assert_eq!(array[[0, 0]], 0);
assert_eq!(array[[0, 1]], 9);
assert_eq!(array[[0, 98]], 24);
Expand Down

0 comments on commit 9095de2

Please sign in to comment.