use crate::error::{Result, RossbyError};
pub trait Colormap: Send + Sync {
fn map_normalized(&self, value: f32) -> [u8; 4];
fn map(&self, value: f32, min: f32, max: f32) -> [u8; 4] {
let normalized = if max > min {
((value - min) / (max - min)).clamp(0.0, 1.0)
} else {
0.5
};
self.map_normalized(normalized)
}
fn name(&self) -> &str;
}
pub fn get_colormap(name: &str) -> Result<Box<dyn Colormap>> {
use super::{diverging::*, sequential::*};
match name.to_lowercase().as_str() {
"viridis" => Ok(Box::new(Viridis)),
"plasma" => Ok(Box::new(Plasma)),
"inferno" => Ok(Box::new(Inferno)),
"magma" => Ok(Box::new(Magma)),
"cividis" => Ok(Box::new(Cividis)),
"coolwarm" => Ok(Box::new(Coolwarm)),
"rdbu" => Ok(Box::new(RdBu)),
"seismic" => Ok(Box::new(Seismic)),
_ => Err(RossbyError::InvalidParameter {
param: "colormap".to_string(),
message: format!("Unknown colormap: {}", name),
}),
}
}
pub fn lerp_color(c1: [u8; 3], c2: [u8; 3], t: f32) -> [u8; 3] {
[
(c1[0] as f32 * (1.0 - t) + c2[0] as f32 * t) as u8,
(c1[1] as f32 * (1.0 - t) + c2[1] as f32 * t) as u8,
(c1[2] as f32 * (1.0 - t) + c2[2] as f32 * t) as u8,
]
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_lerp_color() {
let black = [0, 0, 0];
let white = [255, 255, 255];
let mid = lerp_color(black, white, 0.5);
assert_eq!(mid[0], 127);
assert_eq!(mid[1], 127);
assert_eq!(mid[2], 127);
}
}