This commit is contained in:
orion 2024-05-22 12:16:45 -05:00
parent 127cb4c76d
commit 57fe2cc37d
Signed by: orion
GPG Key ID: 6D4165AE4C928719

View File

@ -60,6 +60,10 @@ pub struct Args {
/// (1) Only the first frame of animated images will be considered. /// (1) Only the first frame of animated images will be considered.
#[arg(verbatim_doc_comment, short = 'f', long = "file")] #[arg(verbatim_doc_comment, short = 'f', long = "file")]
file: String, file: String,
/// Palette size to generate
#[arg(default_value = "9", short = 'n', long = "num-colors")]
num_colors: usize,
} }
fn main() { fn main() {
@ -168,7 +172,7 @@ fn main_impl() -> Result<(), String> {
let proximity_to_true_red = let proximity_to_true_red =
|h: Hue| ((h.degrees() - 30.0).abs()).min((h.degrees() - 390.0).abs()); |h: Hue| ((h.degrees() - 30.0).abs()).min((h.degrees() - 390.0).abs());
let red = colors let mut red = colors
.iter() .iter()
.fold(None, |o, (h, (s, l))| { .fold(None, |o, (h, (s, l))| {
let (h, s, l) = (*h, *s, *l); let (h, s, l) = (*h, *s, *l);
@ -182,6 +186,9 @@ fn main_impl() -> Result<(), String> {
}) })
.unwrap(); .unwrap();
red.2 = red.2.max(0.7);
red.1 = red.1.max(0.6);
colors.remove(&red.0); colors.remove(&red.0);
let to_hex = |h: Hue, s: f64, l: f64| { let to_hex = |h: Hue, s: f64, l: f64| {
@ -198,7 +205,7 @@ fn main_impl() -> Result<(), String> {
format!("#{:0>2x}{:0>2x}{:0>2x}", red, green, blue) format!("#{:0>2x}{:0>2x}{:0>2x}", red, green, blue)
}; };
if colors.len() < 6 { if colors.len() < (args.num_colors - 3) {
colors.clone().into_iter().for_each(|(h, (s, l))| { colors.clone().into_iter().for_each(|(h, (s, l))| {
colors.insert(Hue::from_degrees(h.degrees() + 350.0), (s, l)); colors.insert(Hue::from_degrees(h.degrees() + 350.0), (s, l));
colors.insert(Hue::from_degrees(h.degrees() + 10.0), (s, l)); colors.insert(Hue::from_degrees(h.degrees() + 10.0), (s, l));
@ -206,17 +213,10 @@ fn main_impl() -> Result<(), String> {
}) })
} }
let colors_hex = once(white).chain(once(black)).chain(once(red)) while colors.len() > (args.num_colors - 3) {
.chain(colors.iter().map(|(h, (s, l))| (*h, *s, *l)))
.map(|(h, s, l)| {
serde_json::json!({"okhsl": format!("({:.2}, {:.2}, {:.2})", h.degrees(), s, l), "hex": to_hex(h, s, l)})
})
.collect::<Vec<_>>();
while colors.len() > 5 {
let mut most_similar = Option::<(f64, Hue)>::None; let mut most_similar = Option::<(f64, Hue)>::None;
for (h, (_, l)) in colors.iter() { for (h, (s, l)) in colors.iter() {
for (h_, (_, l_)) in colors.iter() { for (h_, (s_, l_)) in colors.iter() {
if h == h_ { if h == h_ {
continue; continue;
} }
@ -225,7 +225,7 @@ fn main_impl() -> Result<(), String> {
.abs() .abs()
.min(((h_.degrees() + 360.0) - h.degrees()).abs()) .min(((h_.degrees() + 360.0) - h.degrees()).abs())
.min((h_.degrees() - (h.degrees() + 360.0)).abs()); .min((h_.degrees() - (h.degrees() + 360.0)).abs());
let to_remove = if l_ > l { *h } else { *h_ }; let to_remove = if s_ > s || lightness_ideal_delta(*l_) < lightness_ideal_delta(*l) { *h } else { *h_ };
if let Some((sd, sh)) = most_similar { if let Some((sd, sh)) = most_similar {
if (sd == diff && h.ratio() > sh.ratio()) || sd > diff { if (sd == diff && h.ratio() > sh.ratio()) || sd > diff {
most_similar = Some((diff, to_remove)); most_similar = Some((diff, to_remove));
@ -241,7 +241,7 @@ fn main_impl() -> Result<(), String> {
let colors = colors let colors = colors
.into_iter() .into_iter()
.map(|(h, (s, l))| (h, s, l.max(0.4))) .map(|(h, (s, l))| (h, s, l.max(0.7)))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let colors_hex = once(white).chain(once(black)).chain(once(red)) let colors_hex = once(white).chain(once(black)).chain(once(red))