73 lines
1.8 KiB
Rust
73 lines
1.8 KiB
Rust
|
#![cfg(feature = "ogp_images")]
|
||
|
|
||
|
use image::{Pixel, Rgb, Rgba};
|
||
|
use pronouns_today::util::pcg64;
|
||
|
|
||
|
pub fn generate_color_pair(state: &mut u128) -> ([u8; 3], [u8; 3]) {
|
||
|
let mut background = random_color(state);
|
||
|
let mut foreground;
|
||
|
loop {
|
||
|
foreground = random_color(state);
|
||
|
if meets_criteria(&foreground, &background) {
|
||
|
break;
|
||
|
}
|
||
|
background = random_color(state);
|
||
|
if meets_criteria(&foreground, &background) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
(foreground, background)
|
||
|
}
|
||
|
|
||
|
pub fn generate_color_pair_rgba(state: &mut u128) -> (Rgba<u8>, Rgba<u8>) {
|
||
|
let (color1, color2) = generate_color_pair(state);
|
||
|
|
||
|
let (color1, color2): (Rgb<u8>, Rgb<u8>) = (
|
||
|
color1.into(),
|
||
|
color2.into(),
|
||
|
);
|
||
|
|
||
|
(color1.to_rgba(), color2.to_rgba())
|
||
|
}
|
||
|
|
||
|
pub fn relative_lum(color: &[u8; 3]) -> f32 {
|
||
|
let color_mapped: Vec<f32> = color.iter()
|
||
|
.map(|val| {
|
||
|
let val = *val as f32 / 255.0;
|
||
|
if val < 0.03928 {
|
||
|
val / 12.92
|
||
|
} else {
|
||
|
((val+0.055)/1.055).powf(2.4)
|
||
|
}
|
||
|
})
|
||
|
.collect();
|
||
|
return 0.2126 * color_mapped[0] + 0.7152 * color_mapped[1] + 0.0722 * color_mapped[2]
|
||
|
}
|
||
|
|
||
|
pub fn check_contrast(color1: &[u8; 3], color2: &[u8; 3]) -> f32 {
|
||
|
let a = 0.05 + relative_lum(color1);
|
||
|
let b = 0.05 + relative_lum(color2);
|
||
|
(a / b).max(b / a)
|
||
|
}
|
||
|
|
||
|
pub fn get_saturation(color: &[u8; 3]) -> f32 {
|
||
|
let chroma_max = *(color.iter().max().unwrap());
|
||
|
let chroma_min = *(color.iter().min().unwrap());
|
||
|
return ((chroma_max - chroma_min) as f32) / chroma_max as f32;
|
||
|
}
|
||
|
|
||
|
pub fn random_color(state: &mut u128) -> [u8; 3] {
|
||
|
let random = pcg64(state).to_le_bytes();
|
||
|
return [
|
||
|
random[0],
|
||
|
random[1],
|
||
|
random[2],
|
||
|
]
|
||
|
}
|
||
|
|
||
|
pub fn meets_criteria(foreground: &[u8; 3], background: &[u8; 3]) -> bool {
|
||
|
return check_contrast(foreground, background) >= 5.0 &&
|
||
|
get_saturation(background) < 0.65 &&
|
||
|
get_saturation(foreground) < 0.65
|
||
|
}
|