use crate::{util, colorspace, error};
use crate::enums::{Tone, White};
use crate::image::Image;
use crate::error::ImgProcResult;
use std::collections::HashMap;
pub fn brightness(input: &Image<u8>, bias: i32, method: Tone) -> ImgProcResult<Image<u8>> {
error::check_in_range(bias, 0, 255, "bias")?;
match method {
Tone::Rgb => {
let mut lookup_table: [u8; 256] = [0; 256];
util::generate_lookup_table(&mut lookup_table, |i| {
(i as i32 + bias).clamp(0, 255) as u8
});
Ok(input.map_channels_if_alpha(|channel| lookup_table[channel as usize], |a| a))
},
Tone::Lab => {
let mut lab = colorspace::srgb_to_lab(input, &White::D50);
lab.edit_channel(|num| num + (bias as f64) * 255.0 / 100.0, 0);
Ok(colorspace::lab_to_srgb(&lab, &White::D50))
},
}
}
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::generate_lookup_table(&mut lookup_table, |i| {
(i as f64 * gain).round().clamp(0.0, 255.0) as u8
});
Ok(input.map_channels_if_alpha(|channel| lookup_table[channel as usize], |a| a))
},
Tone::Lab => {
let mut lab = colorspace::srgb_to_lab(input, &White::D50);
lab.edit_channel(|num| num * gain, 0);
Ok(colorspace::lab_to_srgb(&lab, &White::D50))
},
}
}
pub fn saturation(input: &Image<u8>, saturation: i32) -> ImgProcResult<Image<u8>> {
error::check_in_range(saturation, 0, 255, "saturation")?;
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")?;
error::check_in_range(alpha, 0.0, 1.0, "alpha")?;
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))
}