mod bicubic;
mod bilinear;
mod kernel;
mod lanczos;
mod nearest;
pub use bicubic::BicubicResampler;
pub use bilinear::BilinearResampler;
pub use lanczos::LanczosResampler;
pub use nearest::NearestResampler;
use crate::error::Result;
use oxigdal_core::buffer::RasterBuffer;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum ResamplingMethod {
Nearest,
#[default]
Bilinear,
Bicubic,
Lanczos,
}
impl ResamplingMethod {
#[must_use]
pub const fn name(&self) -> &'static str {
match self {
Self::Nearest => "Nearest Neighbor",
Self::Bilinear => "Bilinear",
Self::Bicubic => "Bicubic",
Self::Lanczos => "Lanczos",
}
}
#[must_use]
pub const fn kernel_radius(&self) -> usize {
match self {
Self::Nearest => 0,
Self::Bilinear => 1,
Self::Bicubic => 2,
Self::Lanczos => 3,
}
}
}
pub struct Resampler {
method: ResamplingMethod,
}
impl Resampler {
#[must_use]
pub const fn new(method: ResamplingMethod) -> Self {
Self { method }
}
pub fn resample(
&self,
src: &RasterBuffer,
dst_width: u64,
dst_height: u64,
) -> Result<RasterBuffer> {
if dst_width == 0 || dst_height == 0 {
return Err(crate::error::AlgorithmError::InvalidParameter {
parameter: "dimensions",
message: "Target dimensions must be non-zero".to_string(),
});
}
match self.method {
ResamplingMethod::Nearest => {
let resampler = NearestResampler;
resampler.resample(src, dst_width, dst_height)
}
ResamplingMethod::Bilinear => {
let resampler = BilinearResampler;
resampler.resample(src, dst_width, dst_height)
}
ResamplingMethod::Bicubic => {
let resampler = BicubicResampler::new();
resampler.resample(src, dst_width, dst_height)
}
ResamplingMethod::Lanczos => {
let resampler = LanczosResampler::new(3);
resampler.resample(src, dst_width, dst_height)
}
}
}
#[must_use]
pub const fn method(&self) -> ResamplingMethod {
self.method
}
}
impl Default for Resampler {
fn default() -> Self {
Self::new(ResamplingMethod::default())
}
}
#[cfg(test)]
mod tests {
use super::*;
use oxigdal_core::types::RasterDataType;
#[test]
fn test_resampling_method_names() {
assert_eq!(ResamplingMethod::Nearest.name(), "Nearest Neighbor");
assert_eq!(ResamplingMethod::Bilinear.name(), "Bilinear");
assert_eq!(ResamplingMethod::Bicubic.name(), "Bicubic");
assert_eq!(ResamplingMethod::Lanczos.name(), "Lanczos");
}
#[test]
fn test_kernel_radius() {
assert_eq!(ResamplingMethod::Nearest.kernel_radius(), 0);
assert_eq!(ResamplingMethod::Bilinear.kernel_radius(), 1);
assert_eq!(ResamplingMethod::Bicubic.kernel_radius(), 2);
assert_eq!(ResamplingMethod::Lanczos.kernel_radius(), 3);
}
#[test]
fn test_resampler_creation() {
let resampler = Resampler::new(ResamplingMethod::Bilinear);
assert_eq!(resampler.method(), ResamplingMethod::Bilinear);
}
#[test]
fn test_resample_zero_dimensions() {
let src = RasterBuffer::zeros(100, 100, RasterDataType::Float32);
let resampler = Resampler::new(ResamplingMethod::Nearest);
assert!(resampler.resample(&src, 0, 100).is_err());
assert!(resampler.resample(&src, 100, 0).is_err());
}
}