pub(crate) trait Pixel: Copy + Default + Send + Sync + PartialEq + 'static {
const SIZE: usize;
fn to_f64(self) -> f64;
fn from_f64(v: f64) -> Self;
fn put_le(self, out: &mut [u8]);
}
macro_rules! int_pixel {
($($t:ty),*) => {$(
impl Pixel for $t {
const SIZE: usize = std::mem::size_of::<$t>();
#[inline]
fn to_f64(self) -> f64 {
self as f64
}
#[inline]
fn from_f64(v: f64) -> Self {
v.round() as $t
}
#[inline]
fn put_le(self, out: &mut [u8]) {
out.copy_from_slice(&self.to_le_bytes());
}
}
)*};
}
int_pixel!(u8, i8, u16, i16, u32, i32, u64, i64);
impl Pixel for f32 {
const SIZE: usize = 4;
#[inline]
fn to_f64(self) -> f64 {
self as f64
}
#[inline]
fn from_f64(v: f64) -> Self {
v as f32
}
#[inline]
fn put_le(self, out: &mut [u8]) {
out.copy_from_slice(&self.to_le_bytes());
}
}
impl Pixel for f64 {
const SIZE: usize = 8;
#[inline]
fn to_f64(self) -> f64 {
self
}
#[inline]
fn from_f64(v: f64) -> Self {
v
}
#[inline]
fn put_le(self, out: &mut [u8]) {
out.copy_from_slice(&self.to_le_bytes());
}
}
macro_rules! with_data {
($data:expr, $v:ident => $body:expr) => {
match $data {
RasterData::U8($v) => $body,
RasterData::I8($v) => $body,
RasterData::U16($v) => $body,
RasterData::I16($v) => $body,
RasterData::U32($v) => $body,
RasterData::I32($v) => $body,
RasterData::U64($v) => $body,
RasterData::I64($v) => $body,
RasterData::F32($v) => $body,
RasterData::F64($v) => $body,
}
};
}
pub(crate) use with_data;
macro_rules! map_data {
($data:expr, $v:ident => $body:expr) => {
match $data {
RasterData::U8($v) => RasterData::U8($body),
RasterData::I8($v) => RasterData::I8($body),
RasterData::U16($v) => RasterData::U16($body),
RasterData::I16($v) => RasterData::I16($body),
RasterData::U32($v) => RasterData::U32($body),
RasterData::I32($v) => RasterData::I32($body),
RasterData::U64($v) => RasterData::U64($body),
RasterData::I64($v) => RasterData::I64($body),
RasterData::F32($v) => RasterData::F32($body),
RasterData::F64($v) => RasterData::F64($body),
}
};
}
pub(crate) use map_data;
pub(crate) fn raster_from_data(cfg: wbraster::RasterConfig, data: wbraster::raster::RasterData) -> crate::Result<wbraster::Raster> {
let bands = cfg.bands.max(1);
if data.len() != cfg.cols * cfg.rows * bands || cfg.data_type != data.data_type() {
return Ok(wbraster::Raster::from_data_native(cfg, data)?);
}
Ok(wbraster::Raster {
cols: cfg.cols,
rows: cfg.rows,
bands,
x_min: cfg.x_min,
y_min: cfg.y_min,
cell_size_x: cfg.cell_size,
cell_size_y: cfg.cell_size_y.map(|v| v.abs()).unwrap_or(cfg.cell_size),
nodata: cfg.nodata,
data_type: cfg.data_type,
crs: cfg.crs,
metadata: cfg.metadata,
data,
})
}