use regex::Regex;
use color::{Color, Error};
use handles::map;
use utils;
pub fn handle_rgb(color: &Color) -> Result<Vec<f32>, Error> {
let re = Regex::new(r"(?i)rgba?\(\s*(?P<r>\d{1,3}\.?\d*%?)\s*,\s*(?P<g>\d{1,3}\.?\d*%?)\s*,\s*(?P<b>\d{1,3}\.?\d*%?)\s*,?\s*(?P<alpha>\.?\d{1,3}\.?\d*%?)?\s*\)").expect("Parse rgb value error");
let cap = re.captures(color.to_str());
if let Some(value) = cap {
let r = utils::convert_rgb_value_to_number(&value["r"]);
let g = utils::convert_rgb_value_to_number(&value["g"]);
let b = utils::convert_rgb_value_to_number(&value["b"]);
let match_alpha = value.get(4);
if let Some(value) = match_alpha {
let a = utils::convert_alpha_value_to_number(value.as_str());
return Ok(vec![utils::round(r, 4), utils::round(g, 4), utils::round(b, 4), a]);
}
return Ok(vec![utils::round(r, 4), utils::round(g, 4), utils::round(b, 4)])
}
Err(Error::Format)
}
pub fn rgb2hex(color: &Color) -> Result<String, Error> {
let cap = handle_rgb(color)?;
let mut value: Vec<f32> = vec![];
let mut hex = String::from("#");
for n in &cap {
value.push(n * 255f32);
}
for n in 0..3usize {
if value[n] == 0f32 {
hex.push_str("00");
continue;
}
let low = (value[n] / 16f32) as usize;
let high = (value[n] % 16f32) as usize;
hex.push_str(map::map_rgb(&low));
hex.push_str(map::map_rgb(&high));
}
if color.alpha {
let mut alpha = 1f32;
if cap.len() == 4 {
alpha = cap[3];
}
let hexadecimal = &utils::handel_alpha_to_hexadecimal(alpha);
if color.android {
hex.insert_str(1, hexadecimal);
} else {
hex.push_str(hexadecimal);
}
}
if color.upper {
Ok(hex)
} else {
Ok(hex.to_lowercase())
}
}
pub fn rgb2hsl(color: &Color) -> Result<String, Error> {
let cap: Vec<f32> = handle_rgb(&color)?;
let rgb = &cap.clone()[0..3];
let max = *rgb.iter().max_by(|x, y| x.partial_cmp(y).unwrap()).unwrap();
let min = *rgb.iter().min_by(|x, y| x.partial_cmp(y).unwrap()).unwrap();
let mut h = 0f32;
let mut s = 0f32;
let l = (max + min) / 2f32;
if max == min {
h = 0f32;
s = 0f32;
} else {
let mid = max - min;
if l > 0.5f32 {
s = mid / (2f32 - max - min);
} else if l <= 0.5f32 && l > 0f32 {
s = mid /(max + min);
} else if l == 0f32 {
s = 0f32;
}
if max == cap[0] && cap[1] >= cap[2] {
h = 60f32 * (cap[1] - cap[2]) / mid;
} else if max == cap[0] && cap[1] < cap[1] {
h = 60f32 * (cap[1] - cap[2]) / mid + 360f32;
} else if max == cap[1] || max == cap[2] {
h = 60f32 * (cap[2] - cap[0]) / mid + 120f32;
}
}
let mut hsl = format!("({},{},{}", utils::convert_f32_to_string(h), utils::convert_f32_to_percent(s), utils::convert_f32_to_percent(l));
if color.alpha {
hsl.push_str(",");
if cap.len() == 4usize {
hsl.push_str(&cap[3].to_string());
hsl.push_str(")");
} else {
hsl.push_str("1)");
}
hsl.insert_str(0, "hsla");
} else {
hsl.push_str(")");
hsl.insert_str(0, "hsl");
}
if color.upper {
hsl = hsl.to_uppercase()
}
Ok(hsl)
}
pub fn rgb2cmyk(color: &Color) -> Result<String, Error> {
let cap: Vec<f32> = handle_rgb(&color)?;
let r = cap[0];
let g = cap[1];
let b = cap[2];
let max = *cap.iter().max_by(|x, y| x.partial_cmp(y).unwrap()).unwrap();
let k = ((1f32 - max) * 100f32).round() / 100f32;
if k == 1f32 {
if color.upper {
return Ok(String::from("CMYK(0,0,0,1)"));
} else {
return Ok(String::from("cmyk(0,0,0,1)"));
}
}
let c = ((1f32 - r - k) / (1f32 - k) * 100f32).round() / 100f32;
let m = ((1f32 - g - k) / (1f32 - k) * 100f32).round() / 100f32;
let y = ((1f32 - b - k) / (1f32 - k) * 100f32).round() / 100f32;
let mut cmyk = vec![c, m, y, k];
for index in 0..4 {
if cmyk[index] < 0f32 {
cmyk[index] = 0f32;
}
}
if color.upper {
Ok(format!("CMYK({},{},{},{})", cmyk[0], cmyk[1], cmyk[2], cmyk[3]))
} else {
Ok(format!("cmyk({},{},{},{})", cmyk[0], cmyk[1], cmyk[2], cmyk[3]))
}
}
pub fn rgb2hsv(color: &Color) -> Result<String, Error> {
let cap: Vec<f32> = handle_rgb(&color)?;
let rgb = &cap.clone()[0..3];
let r = rgb[0];
let g = rgb[1];
let b = rgb[2];
let mut h = 0f32;
let s;
let v;
let max = *rgb.iter().max_by(|x, y| x.partial_cmp(y).unwrap()).unwrap();
let min = *rgb.iter().min_by(|x, y| x.partial_cmp(y).unwrap()).unwrap();
let mid = max - min;
if mid == 0f32 {
h = 0f32;
} else if max == r {
h = 60f32 * (((g - b) / mid) % 6f32);
} else if max == g {
h = 60f32 * ((b - r) / mid + 2f32);
} else if max == b {
h = 60f32 * ((r - g) / mid + 4f32);
}
if max == 0f32 {
s = 0f32;
} else {
s = (mid / max * 10000f32).round() / 100f32; }
v = (max * 10000f32).round() / 100f32;
if color.upper {
Ok(format!("HSV({},{}%,{}%)", (h * 100f32).round() / 100f32, s, v))
} else {
Ok(format!("hsv({},{}%,{}%)", (h * 100f32).round() / 100f32, s, v))
}
}
pub fn rgb2rgb(color: &Color) -> Result<String, Error> {
let cap: Vec<f32> = handle_rgb(&color)?;
let mut alpha = 1f32;
if cap.len() == 4 {
alpha = cap[3];
}
let r = utils::decimal_to_percent(cap[0]);
let g = utils::decimal_to_percent(cap[1]);
let b = utils::decimal_to_percent(cap[2]);
let rgb;
if color.upper {
if color.alpha {
rgb = format!("RGBA({},{},{},{})", r, g, b, if alpha > 1f32 {1f32} else {alpha});
} else {
rgb = format!("RGB({},{},{})", r, g, b);
}
} else {
if color.alpha {
rgb = format!("rgba({},{},{},{})", r, g, b, if alpha > 1f32 {1f32} else {alpha});
} else {
rgb = format!("rgb({},{},{})", r, g, b);
}
}
Ok(rgb)
}