From 814c9f98d19cba8c5cd2cc292ae16ca87ea63335 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Padarian?= Date: Sun, 3 Dec 2023 20:47:42 +1100 Subject: [PATCH 1/2] Add method to set default histogram for RasterBand --- CHANGES.md | 6 ++++-- src/raster/rasterband.rs | 28 +++++++++++++++++++++++++++- src/raster/tests.rs | 34 +++++++++++++++++++++++++++++++++- 3 files changed, 64 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 7e7a8e4a..bfb4f8e2 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -50,9 +50,11 @@ - -- Added histogram calculation +- Added raster histogram methods (setter and getter) + + - Getter: + - Setter: - - ## 0.16 diff --git a/src/raster/rasterband.rs b/src/raster/rasterband.rs index 92c0d4fd..a0ab457b 100644 --- a/src/raster/rasterband.rs +++ b/src/raster/rasterband.rs @@ -8,7 +8,7 @@ use gdal_sys::{ GDALCreateColorRamp, GDALCreateColorTable, GDALDestroyColorTable, GDALGetDefaultHistogramEx, GDALGetPaletteInterpretation, GDALGetRasterHistogramEx, GDALGetRasterStatistics, GDALMajorObjectH, GDALPaletteInterp, GDALRIOResampleAlg, GDALRWFlag, GDALRasterBandH, - GDALRasterIOExtraArg, GDALSetColorEntry, GDALSetRasterColorTable, + GDALRasterIOExtraArg, GDALSetColorEntry, GDALSetDefaultHistogramEx, GDALSetRasterColorTable, }; use libc::c_int; use std::ffi::CString; @@ -884,6 +884,32 @@ impl<'a> RasterBand<'a> { } } + /// Set default raster histogram. + /// + /// # Arguments + /// + /// * `min` - Histogram lower bound + /// * `max` - Histogram upper bound + /// * `n_buckets` - Number of buckets in the histogram + /// * `counts` - Histogram values for each bucket + pub fn set_default_histogram(&self, min: f64, max: f64, counts: &mut [u64]) -> Result<()> { + let n_buckets = counts.len(); + let rv = unsafe { + GDALSetDefaultHistogramEx( + self.c_rasterband, + min, + max, + n_buckets as i32, + counts.as_mut_ptr(), + ) + }; + + match CplErrType::from(rv) { + CplErrType::None => Ok(()), + _ => Err(_last_cpl_err(rv)), + } + } + /// Compute raster histogram. /// /// # Arguments diff --git a/src/raster/tests.rs b/src/raster/tests.rs index bbfc4e7f..7e605b5f 100644 --- a/src/raster/tests.rs +++ b/src/raster/tests.rs @@ -752,7 +752,7 @@ fn test_raster_stats() { } #[test] -fn test_raster_histogram() { +fn test_raster_get_histogram() { let fixture = TempFixture::fixture("tinymarble.tif"); let dataset = Dataset::open(&fixture).unwrap(); @@ -788,6 +788,38 @@ fn test_raster_histogram() { hist.expect_err("histogram with 0 buckets should panic"); } +#[test] +fn test_raster_set_histogram() { + let fixture = TempFixture::fixture("tinymarble.tif"); + + let dataset = Dataset::open(&fixture).unwrap(); + let rb = dataset.rasterband(1).unwrap(); + + let hist = rb.default_histogram(false).unwrap(); + assert!(hist.is_none()); + + let mut expected = [ + 548, 104, 133, 127, 141, 125, 156, 129, 130, 117, 94, 94, 80, 81, 78, 63, 50, 66, 48, 48, + 33, 38, 41, 35, 41, 39, 32, 40, 26, 27, 25, 24, 18, 25, 29, 27, 20, 34, 17, 24, 29, 11, 20, + 21, 12, 19, 16, 16, 11, 10, 19, 5, 11, 10, 6, 9, 7, 12, 13, 6, 8, 7, 8, 14, 9, 14, 4, 8, 5, + 12, 6, 10, 7, 9, 8, 6, 3, 7, 5, 8, 9, 5, 4, 8, 3, 9, 3, 6, 11, 7, 6, 3, 9, 9, 7, 6, 9, 10, + 10, 4, 7, 2, 4, 7, 2, 12, 7, 10, 4, 6, 5, 2, 4, 5, 7, 3, 5, 7, 7, 14, 9, 12, 6, 6, 8, 5, 8, + 3, 3, 5, 11, 4, 9, 7, 14, 7, 10, 11, 6, 6, 5, 4, 9, 6, 6, 9, 5, 12, 11, 9, 3, 8, 5, 6, 4, + 2, 9, 7, 9, 9, 9, 6, 6, 8, 5, 9, 13, 4, 9, 4, 7, 13, 10, 5, 7, 8, 11, 12, 5, 17, 9, 11, 9, + 8, 9, 5, 8, 9, 5, 6, 9, 11, 8, 7, 7, 6, 7, 8, 8, 8, 5, 6, 7, 5, 8, 5, 6, 8, 7, 4, 8, 6, 5, + 11, 8, 8, 5, 4, 6, 4, 9, 7, 6, 6, 7, 7, 12, 6, 9, 17, 12, 20, 18, 17, 21, 24, 30, 29, 57, + 72, 83, 21, 11, 9, 18, 7, 13, 10, 2, 4, 0, 1, 3, 4, 1, 1, + ]; + + // This values come from test_raster_get_histogram + rb.set_default_histogram(-0.5, 255.5, &mut expected) + .unwrap(); + + let hist = rb.default_histogram(false).unwrap(); + assert!(hist.is_some()); + assert_eq!(hist.unwrap().counts(), expected); +} + #[test] fn test_resample_str() { assert!(ResampleAlg::from_str("foobar").is_err()); From fc38d023acb0a4e28a6c23aeef03413d17624cfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Padarian?= Date: Mon, 4 Dec 2023 14:40:23 +1100 Subject: [PATCH 2/2] Add assertion to histogram setter and getter --- src/raster/rasterband.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/raster/rasterband.rs b/src/raster/rasterband.rs index a0ab457b..04605150 100644 --- a/src/raster/rasterband.rs +++ b/src/raster/rasterband.rs @@ -890,10 +890,14 @@ impl<'a> RasterBand<'a> { /// /// * `min` - Histogram lower bound /// * `max` - Histogram upper bound - /// * `n_buckets` - Number of buckets in the histogram /// * `counts` - Histogram values for each bucket + /// + /// # Panics + /// Panics if the `counts.len()` is greater than `i32::MAX`. pub fn set_default_histogram(&self, min: f64, max: f64, counts: &mut [u64]) -> Result<()> { let n_buckets = counts.len(); + assert!(n_buckets <= i32::MAX as usize); + let rv = unsafe { GDALSetDefaultHistogramEx( self.c_rasterband, @@ -933,6 +937,8 @@ impl<'a> RasterBand<'a> { )); } + assert!(n_buckets <= i32::MAX as usize); + let mut counts = vec![0; n_buckets]; let rv = unsafe {