use crate::{util, colorspace, error};
use crate::enums::{Tone, White};
use crate::image::Image;
use crate::error::{ImgProcError, ImgProcResult};
use std::collections::HashMap;
pub fn brightness(input: &Image<u8>, bias: i32, method: Tone) -> ImgProcResult<Image<u8>> {
if bias < 0 || bias > 255 {
return Err(ImgProcError::InvalidArgError("bias is not in range 0 to 255".to_string()));
}
match method {
Tone::Rgb => {
let mut lookup_table: [u8; 256] = [0; 256];
util::create_lookup_table(&mut lookup_table, |i| {
(i as i32 + bias) as u8
});
Ok(input.map_channels_if_alpha(|channel| lookup_table[channel as usize], |a| a))
},
Tone::Xyz => {
let mut xyz = colorspace::srgb_to_xyz(input);
xyz.edit_channel(|num| num + (bias as f64 / 255.0), 1);
Ok(colorspace::xyz_to_srgb(&xyz))
},
}
}
pub fn contrast(input: &Image<u8>, gain: f64, method: Tone) -> ImgProcResult<Image<u8>> {
error::check_non_neg(gain, "gain")?;
match method {
Tone::Rgb => {
let mut lookup_table: [u8; 256] = [0; 256];
util::create_lookup_table(&mut lookup_table, |i| {
(i as f64 * gain).round() as u8
});
Ok(input.map_channels_if_alpha(|channel| lookup_table[channel as usize], |a| a))
},
Tone::Xyz => {
let mut xyz = colorspace::srgb_to_xyz(input);
xyz.edit_channel(|num| num * gain, 1);
Ok(colorspace::xyz_to_srgb(&xyz))
},
}
}
pub fn saturation(input: &Image<u8>, saturation: i32) -> ImgProcResult<Image<u8>> {
let mut hsv = colorspace::rgb_to_hsv(input);
hsv.edit_channel(|s| (s + (saturation as f64 / 255.0)) as f64, 1);
Ok(colorspace::hsv_to_rgb(&hsv))
}
pub fn gamma(input: &Image<u8>, gamma: f64, max: u8) -> ImgProcResult<Image<u8>> {
error::check_non_neg(gamma, "gamma")?;
Ok(input.map_channels_if_alpha(|channel| {
((channel as f64 / max as f64).powf(gamma) * (max as f64)).round() as u8
}, |a| a))
}
pub fn histogram_equalization(input: &Image<u8>, alpha: f64, ref_white: &White, precision: f64) -> ImgProcResult<Image<u8>> {
error::check_non_neg(precision, "precision")?;
if alpha < 0.0 || alpha > 1.0 {
return Err(ImgProcError::InvalidArgError("alpha is not in range 0 to 1".to_string()));
}
let mut lab = colorspace::srgb_to_lab(input, ref_white);
let mut percentiles = HashMap::new();
util::generate_histogram_percentiles(&lab, &mut percentiles, precision);
lab.edit_channel(|num| {
let key = (num * precision).round() as i32;
(alpha * percentiles.get(&key).unwrap() * 100.0) + ((1.0 - alpha) * num)
}, 0);
Ok(colorspace::lab_to_srgb(&lab, ref_white))
}