fn parse(arg: std::ffi::OsString) -> Result<u32, String> {
let arg = arg.into_string().map_err(|arg| {
format!("{}: not valid Unicode", arg.to_string_lossy())
})?;
if arg.len() != 7 ||
arg.as_bytes()[0] != '#' as u8 ||
arg.as_bytes()[1] == '+' as u8
{
Err(format!("{}: expected argument in #RRGGBB format", arg))
} else {
u32::from_str_radix(&arg[1..], 16)
.map_err(|err| format!("{}: {}", arg, err))
}
}
fn parse_args() -> Result<(u32, u32), (std::ffi::OsString, String)> {
let mut argv0 = "example".into();
let mut colours = [0, 0];
let mut n = 0;
for arg in std::env::args_os() {
if n == 0 {
argv0 = arg;
} else if n < 3 {
colours[n - 1] = match parse(arg) {
Ok(colour) => colour,
Err(msg) => return Err((argv0, msg)),
};
} else {
break;
}
n += 1;
}
if n != 3 {
Err((argv0, String::from("Expected two arguments")))
} else {
Ok((colours[0], colours[1]))
}
}
fn from_rgb(rgb: u32) -> (f32, f32, f32) {
let lab =
lab::Lab::from_rgb(&[(rgb >> 16) as u8, (rgb >> 8) as u8, rgb as u8]);
(lab.l, lab.a, lab.b)
}
pub fn main() {
use empfindung::*;
let (a, b) = match parse_args() {
Ok(colours) => colours,
Err((argv0, msg)) => {
eprintln!(
"{}\nusage: {} #RRGGBB #RRGGBB",
msg,
argv0.to_string_lossy()
);
std::process::exit(1);
}
};
let a = from_rgb(a);
let b = from_rgb(b);
println!("ΔE_76 = {:>11.7} (Euclidean distance)", cie76::diff(a, b));
println!(
"ΔE_94g = {:>11.7} (parameters for graphic arts)",
cie94::diff(a, b, cie94::KSubParams::graphic())
);
println!(
"ΔE_94t = {:>11.7} (parameters for textiles)",
cie94::diff(a, b, cie94::KSubParams::textiles())
);
println!("ΔE_00 = {:>11.7} (default parameters", cie00::diff(a, b));
println!(
"ΔE_00y = {:>11.7} (parameters by Yang et al)",
cie00::diff_with_params(a, b, cie00::KSubParams::yang2012())
);
println!("ΔE_1:1 = {:>11.7} (CMC 1:1)", cmc::diff(a, b, cmc::LC11));
println!("ΔE_1:1 = {:>11.7} (CMC 2:1)", cmc::diff(a, b, cmc::LC21));
}