1
1
use ptr:: null_mut;
2
2
use std:: convert:: TryInto ;
3
- use std:: mem:: MaybeUninit ;
3
+ use std:: mem:: { size_of , MaybeUninit } ;
4
4
use std:: {
5
5
ffi:: NulError ,
6
6
ffi:: { CStr , CString } ,
@@ -12,6 +12,7 @@ use std::{
12
12
use crate :: cpl:: CslStringList ;
13
13
use crate :: errors:: * ;
14
14
use crate :: raster:: RasterCreationOption ;
15
+ use crate :: raster:: { Buffer3D , GdalType , RasterIOExtraArg , ResampleAlg } ;
15
16
use crate :: utils:: { _last_cpl_err, _last_null_pointer_err, _path_to_c_string, _string} ;
16
17
use crate :: vector:: { sql, Geometry , OwnedLayer } ;
17
18
use crate :: {
@@ -20,10 +21,11 @@ use crate::{
20
21
} ;
21
22
22
23
use gdal_sys:: {
23
- self , CPLErr , GDALAccess , GDALDatasetH , GDALMajorObjectH , OGRErr , OGRLayerH , OGRwkbGeometryType ,
24
+ self , CPLErr , GDALAccess , GDALDatasetH , GDALMajorObjectH , GDALRWFlag , GDALRasterIOExtraArg ,
25
+ OGRErr , OGRLayerH , OGRwkbGeometryType ,
24
26
} ;
25
27
use gdal_sys:: { GDALFlushCache , OGRGeometryH } ;
26
- use libc:: { c_double, c_int, c_uint} ;
28
+ use libc:: { c_double, c_int, c_uint, c_void } ;
27
29
28
30
#[ cfg( all( major_ge_3, minor_ge_1) ) ]
29
31
use crate :: raster:: Group ;
@@ -702,6 +704,94 @@ impl Dataset {
702
704
Ok ( self . child_layer ( c_layer) )
703
705
}
704
706
707
+ /// Read a [`Buffer<T>`] from this dataset, where `T` implements [`GdalType`].
708
+ ///
709
+ /// # Arguments
710
+ /// * `window` - the window position from top left
711
+ /// * `window_size` - the window size (GDAL will interpolate data if `window_size` != `buffer_size`)
712
+ /// * `buffer_size` - the desired size of the 'Buffer'
713
+ /// * `e_resample_alg` - the resample algorithm used for the interpolation. Default: `NearestNeighbor`.
714
+ ///
715
+ /// The returned buffer contains the image data in HWC order.
716
+ ///
717
+ /// # Example
718
+ ///
719
+ /// ```rust
720
+ /// # fn main() -> gdal::errors::Result<()> {
721
+ /// use gdal::Dataset;
722
+ /// use gdal::raster::ResampleAlg;
723
+ /// let dataset = Dataset::open("fixtures/m_3607824_se_17_1_20160620_sub.tif")?;
724
+ /// let size = 2;
725
+ /// let buf = dataset.read_as::<u8>((0, 0), dataset.raster_size(), (size, size), Some(ResampleAlg::Bilinear))?;
726
+ /// assert_eq!(buf.size, (size, size, dataset.raster_count() as usize));
727
+ /// assert_eq!(buf.data, [103, 116, 101, 169, 92, 108, 94, 163, 92, 112, 93, 179, 89, 109, 91, 181]);
728
+ /// # Ok(())
729
+ /// # }
730
+ /// ```
731
+ pub fn read_as < T : Copy + GdalType > (
732
+ & self ,
733
+ window : ( isize , isize ) ,
734
+ window_size : ( usize , usize ) ,
735
+ buffer_size : ( usize , usize ) ,
736
+ e_resample_alg : Option < ResampleAlg > ,
737
+ ) -> Result < Buffer3D < T > > {
738
+ let band_count = self . raster_count ( ) as usize ;
739
+ let pixels = buffer_size. 0 * buffer_size. 1 * band_count;
740
+ let mut data: Vec < T > = Vec :: with_capacity ( pixels) ;
741
+
742
+ let resample_alg = e_resample_alg. unwrap_or ( ResampleAlg :: NearestNeighbour ) ;
743
+
744
+ let mut options: GDALRasterIOExtraArg = RasterIOExtraArg {
745
+ e_resample_alg : resample_alg,
746
+ ..Default :: default ( )
747
+ }
748
+ . into ( ) ;
749
+
750
+ let options_ptr: * mut GDALRasterIOExtraArg = & mut options;
751
+
752
+ let mut bands: Vec < i32 > = ( 1_i32 ..band_count as i32 + 1_i32 ) . collect ( ) ;
753
+
754
+ let size_t = size_of :: < T > ( ) as i64 ;
755
+ // Safety: the GDALDatasetRasterIOEx writes
756
+ // exactly pixel elements into the slice, before we
757
+ // read from this slice. This paradigm is suggested
758
+ // in the rust std docs
759
+ // (https://doc.rust-lang.org/std/vec/struct.Vec.html#examples-18)
760
+ let rv = unsafe {
761
+ gdal_sys:: GDALDatasetRasterIOEx (
762
+ self . c_dataset ,
763
+ GDALRWFlag :: GF_Read ,
764
+ window. 0 as c_int ,
765
+ window. 1 as c_int ,
766
+ window_size. 0 as c_int ,
767
+ window_size. 1 as c_int ,
768
+ data. as_mut_ptr ( ) as * mut c_void ,
769
+ buffer_size. 0 as c_int ,
770
+ buffer_size. 1 as c_int ,
771
+ T :: gdal_ordinal ( ) ,
772
+ band_count as i32 ,
773
+ bands. as_mut_ptr ( ) as * mut c_int ,
774
+ // We want to read a HWC
775
+ size_t * band_count as i64 ,
776
+ buffer_size. 1 as i64 * size_t * band_count as i64 ,
777
+ size_t,
778
+ options_ptr,
779
+ )
780
+ } ;
781
+ if rv != CPLErr :: CE_None {
782
+ return Err ( _last_cpl_err ( rv) ) ;
783
+ }
784
+
785
+ unsafe {
786
+ data. set_len ( pixels) ;
787
+ } ;
788
+
789
+ Ok ( Buffer3D {
790
+ size : ( buffer_size. 0 , buffer_size. 1 , band_count) ,
791
+ data,
792
+ } )
793
+ }
794
+
705
795
/// Set the [`Dataset`]'s affine transformation; also called a _geo-transformation_.
706
796
///
707
797
/// This is like a linear transformation preserves points, straight lines and planes.
@@ -1288,4 +1378,42 @@ mod tests {
1288
1378
let mut ds = Dataset :: open ( fixture ( "roads.geojson" ) ) . unwrap ( ) ;
1289
1379
assert ! ( ds. start_transaction( ) . is_err( ) ) ;
1290
1380
}
1381
+
1382
+ #[ test]
1383
+ fn test_dataset_read_as ( ) {
1384
+ let ds = Dataset :: open ( fixture ( "m_3607824_se_17_1_20160620_sub.tif" ) ) . unwrap ( ) ;
1385
+ let size: usize = 4 ;
1386
+ let band_count = ds. raster_count ( ) as usize ;
1387
+ // Compare reading the whole dataset at once to reading each band individually
1388
+ let ds_buf = ds
1389
+ . read_as :: < u8 > (
1390
+ ( 0 , 0 ) ,
1391
+ ds. raster_size ( ) ,
1392
+ ( size, size) ,
1393
+ Some ( ResampleAlg :: Bilinear ) ,
1394
+ )
1395
+ . unwrap ( ) ;
1396
+ assert_eq ! ( ds_buf. size, ( size, size, band_count) ) ;
1397
+
1398
+ for band_index in 0 ..band_count {
1399
+ let band = ds. rasterband ( band_index as isize + 1 ) . unwrap ( ) ;
1400
+ let band_buf = band
1401
+ . read_as :: < u8 > (
1402
+ ( 0 , 0 ) ,
1403
+ ds. raster_size ( ) ,
1404
+ ( size, size) ,
1405
+ Some ( ResampleAlg :: Bilinear ) ,
1406
+ )
1407
+ . unwrap ( ) ;
1408
+ assert_eq ! ( band_buf. size, ( size, size) ) ;
1409
+ for i in 0 ..size {
1410
+ for j in 0 ..size {
1411
+ assert_eq ! (
1412
+ band_buf. data[ i * size + j] ,
1413
+ ds_buf. data[ i * size * band_count + j * band_count + band_index] ,
1414
+ ) ;
1415
+ }
1416
+ }
1417
+ }
1418
+ }
1291
1419
}
0 commit comments