rustyphoenixpng 1.1.2

This project eases manipulation of ong image inside Phoenix ecosystem
Documentation
/***************************************
	Auteur : Pierre Aubert
	Mail : pierre.aubert@lapp.in2p3.fr
	Licence : CeCILL-C
****************************************/

///Color related to a value
#[derive(Debug)]
struct PColorValue{
	///Value of the color
	value: f32,
	///Red channel
	r: u8,
	///Green channel
	g: u8,
	///Blue channel
	b: u8,
	///Alpha channel
	a: u8,
}

impl PColorValue{
	///Constructor of a PColorValue
	/// # Parameters
	/// - `value` : 1d value
	/// - `r` : associated red component
	/// - `g` : associated green component
	/// - `b` : associated blue component
	/// - `a` : associated a component
	/// # Returns
	/// Initialised PColorValue
	pub fn new(value: f32, r: u8, g: u8, b: u8, a: u8) -> Self{
		PColorValue {
			value: value,
			r: r,
			g: g,
			b: b,
			a: a
		}
	}
	///Get a color tuple
	/// # Return
	/// Color tuple
	pub fn get_color(&self) -> (u8, u8, u8, u8){
		return (self.r, self.g, self.b, self.a);
	}
}

///Map which interpolates between colors
#[derive(Debug)]
pub struct PColorMap{
	///Vector of reference color for given values
	vec_value: Vec<PColorValue>,
}

impl PColorMap{
	///Constructor of the PColorMap
	pub fn new() -> Self{
		PColorMap {
			vec_value: vec![]
		}
	}
	///Create the Gray Scott PColorMap
	/// # Returns
	/// Gray Scott PColorMap
	pub fn gray_scott() -> Self{
		let mut colormap: PColorMap = PColorMap::new();
		colormap.add_color(0.0, 0, 0, 0, 255);
		colormap.add_color(0.2, 0, 255, 0, 255);
		colormap.add_color(0.21, 255, 255, 0, 255);
		colormap.add_color(0.4, 255, 0, 0, 255);
		colormap.add_color(0.6, 255, 255, 255, 255);
		return colormap;
	}
	///Add a color in the map
	/// # Parameters
	/// - `value` : 1d value
	/// - `r` : associated red component
	/// - `g` : associated green component
	/// - `b` : associated blue component
	/// - `a` : associated a component
	pub fn add_color(&mut self, value: f32, r: u8, g: u8, b: u8, a: u8){
		self.vec_value.push(PColorValue::new(value, r, g, b, a));
	}
	///Interpolate value in color
	/// # Parameters
	/// - `value` : value to be interpolated
	/// # Returns
	/// Interpolated (r,g,b,a) tuple
	pub fn interpolate(&self, value: f32) -> (u8, u8, u8, u8){
		if self.vec_value.len() == 0 {	//The vector is empty
			return (0,0,0,0);
		}else{
			//If the value is less than min
			let mincolor = self.vec_value.first().unwrap();
			if value <= mincolor.value {
				return mincolor.get_color();
			}
			//If the value is greater than the max
			let maxcolor = self.vec_value.last().unwrap();
			if value >= maxcolor.value {
				return maxcolor.get_color();
			}
			for (min, max) in self.vec_value.iter().zip(self.vec_value.iter().skip(1)) {
				if value >= min.value && value < max.value {
					let interp: PColorValue = self.interpolate_color(value, min, max);
					return interp.get_color();
				}
			}
			return (0,0,0,0);
		}
	}
	///Interpolate color
	/// # Parameters
	/// - `value` : value to be interpolated
	/// - `min_color` : color where value is smaller than the given value
	/// - `max_color` : color where value is greater than the given value
	/// # Returns
	/// Interpolated PColorValue
	fn interpolate_color(&self, value: f32, min_color: &PColorValue, max_color: &PColorValue) -> PColorValue{
		let ratio: f32 = (value - min_color.value)/(max_color.value - min_color.value);
		let color: PColorValue = PColorValue::new(value,
			((max_color.r as f32)*ratio + (min_color.r as f32)*(1.0 - ratio)) as u8,
			((max_color.g as f32)*ratio + (min_color.g as f32)*(1.0 - ratio)) as u8,
			((max_color.b as f32)*ratio + (min_color.b as f32)*(1.0 - ratio)) as u8,
			((max_color.a as f32)*ratio + (min_color.a as f32)*(1.0 - ratio)) as u8
		);
		return color;
	}
}

#[cfg(test)]
mod tests {
	use super::*;
	///Test the PColorMap
	#[test]
	fn test_pcolormap() {
		let colormap: PColorMap = PColorMap::gray_scott();
		println!("test_pcolormap : colormap = {:?}", colormap);
		assert_eq!(colormap.vec_value.get(0).unwrap().get_color(), (0, 0, 0, 255));
		assert_eq!(colormap.vec_value.first().unwrap().get_color(), (0, 0, 0, 255));
		assert_eq!(colormap.vec_value.get(1).unwrap().get_color(), (0, 255, 0, 255));
		assert_eq!(colormap.vec_value.get(2).unwrap().get_color(), (255, 255, 0, 255));
		assert_eq!(colormap.vec_value.get(3).unwrap().get_color(), (255, 0, 0, 255));
		assert_eq!(colormap.vec_value.get(4).unwrap().get_color(), (255, 255, 255, 255));
		assert_eq!(colormap.vec_value.last().unwrap().get_color(), (255, 255, 255, 255));
		
		assert_eq!(colormap.interpolate(-1.0), (0, 0, 0, 255));
		assert_eq!(colormap.interpolate(1.0), (255, 255, 255, 255));
		assert_eq!(colormap.interpolate(0.5), (255, 127, 127, 255));
	}
}