use std::fmt::{Display, Debug};
use num::{ToPrimitive, Unsigned, Integer};
use image::{Rgba, RgbaImage};
use failure::{err_msg, Error};
#[derive(Clone, Debug)]
pub enum Format {
Aperio,
Hamamatsu,
Leica,
Mirax,
Phillips,
Sakura,
Trestle,
Ventana,
GenericTiledTiff,
}
#[derive(Clone, Debug)]
pub enum WordRepresentation {
BigEndian,
LittleEndian,
}
pub fn decode_buffer<T: Unsigned + Integer + ToPrimitive + Debug + Display + Clone + Copy>(
buffer: &Vec<u32>,
height: T,
width: T,
word_representation: WordRepresentation
) -> Result<RgbaImage, Error> {
let (a_pos, r_pos, g_pos, b_pos) = match word_representation {
WordRepresentation::BigEndian => (0, 1, 2, 3),
WordRepresentation::LittleEndian => (3, 2, 1, 0),
};
let mut rgba_image = RgbaImage::new(
width.to_u32().ok_or(err_msg("Conversion to primitive error"))?,
height.to_u32().ok_or(err_msg("Conversion to primitive error"))?);
for (col, row, pixel) in rgba_image.enumerate_pixels_mut() {
let curr_pos = row * width.to_u32().ok_or(err_msg("Conversion to primitive error"))? + col;
let values = buffer[curr_pos as usize];
let bit_repr = format!("{:b}", values);
let alpha_bit_repr = String::from(&bit_repr[(8 * a_pos)..(8 * a_pos + 8)]);
let red_bit_repr = String::from(&bit_repr[(8 * r_pos)..(8 * r_pos + 8)]);
let green_bit_repr = String::from(&bit_repr[(8 * g_pos)..(8 * g_pos + 8)]);
let blue_bit_repr = String::from(&bit_repr[(8 * b_pos)..(8 * b_pos + 8)]);
let alpha = u8::from_str_radix(&alpha_bit_repr, 2)?;
let mut red = u8::from_str_radix(&red_bit_repr, 2)?;
let mut green = u8::from_str_radix(&green_bit_repr, 2)?;
let mut blue = u8::from_str_radix(&blue_bit_repr, 2)?;
if alpha != 0 && alpha != 255 {
red = (red as f32 * (255.0 / alpha as f32)).round().max(0.0).min(255.0) as u8;
green = (green as f32 * (255.0 / alpha as f32)).round().max(0.0).min(255.0) as u8;
blue = (blue as f32 * (255.0 / alpha as f32)).round().max(0.0).min(255.0) as u8;
}
*pixel = Rgba([red, green, blue, alpha]);
}
Ok(rgba_image)
}