use ratatui::style::Color;
pub fn rgb(hex: u32) -> Color {
Color::Rgb(
((hex >> 16) & 0xff) as u8,
((hex >> 8) & 0xff) as u8,
(hex & 0xff) as u8,
)
}
pub fn blend(a: Color, b: Color, t: f32) -> Color {
match (a, b) {
(Color::Rgb(ar, ag, ab), Color::Rgb(br, bg, bb)) => {
let mix = |x: u8, y: u8| {
(x as f32 * (1.0 - t) + y as f32 * t)
.round()
.clamp(0.0, 255.0) as u8
};
Color::Rgb(mix(ar, br), mix(ag, bg), mix(ab, bb))
}
_ => a,
}
}
pub fn saturate(c: Color, amount: f32) -> Color {
let Color::Rgb(r, g, b) = c else { return c };
let avg = (r as f32 + g as f32 + b as f32) / 3.0;
let push = |x: u8| {
let d = x as f32 - avg;
(avg + d * (1.0 + amount)).round().clamp(0.0, 255.0) as u8
};
Color::Rgb(push(r), push(g), push(b))
}
pub fn luminance(c: Color) -> Option<f32> {
let Color::Rgb(r, g, b) = c else { return None };
Some((0.2126 * r as f32 + 0.7152 * g as f32 + 0.0722 * b as f32) / 255.0)
}
pub fn best_contrast(bg: Color, a: Color, b: Color) -> Color {
match (luminance(bg), luminance(a), luminance(b)) {
(Some(l_bg), Some(l_a), Some(l_b)) => {
if (l_a - l_bg).abs() >= (l_b - l_bg).abs() {
a
} else {
b
}
}
_ => a,
}
}
const CHROME_SATURATION_BOOST: f32 = 1.0;
pub fn chrome(bg: Color, ink: Color, t: f32) -> Color {
saturate(blend(bg, ink, t), CHROME_SATURATION_BOOST)
}