//! Color palate generator. use palette::rgb::Rgb; use palette::FromColor; use palette::Hsl; use palette::Hsv; use palette::IntoColor; use rand::prelude::*; /// The palette that is used /// to generate the image. pub struct Palette { pub background_color: Rgb, pub fill_color: Rgb, } impl Palette { /// generate a random color that is not to dark /// and to color less. #[allow(dead_code)] pub fn random_color(mut rng: StdRng) -> Rgb { //let mut rng = rand::thread_rng(); let y: f32 = rng.gen(); // generates a float between 0 and 1 let hue: f32 = y * 360.0; let saturation: f32 = f32::max(rng.gen(), 0.6); let value: f32 = f32::max(rng.gen(), 0.6); //Rgb::from_linear(Hsv::new(hue, saturation, value).into_rgb()) Palette::color(hue, saturation, value) } pub fn color(hue: f32, saturation: f32, value: f32) -> Rgb { Rgb::from_linear(Hsv::new(hue, saturation, value).into_rgb()) } /// generate a palette from the tint and shade palette /// algorithm. choose a dark background and a bright filling color #[allow(dead_code)] pub fn bright_on_dark(input: Rgb) -> Palette { let tint_and_shade_palette = TintAndShadePalette::create(input); Palette { background_color: tint_and_shade_palette.base_shade_30, fill_color: tint_and_shade_palette.inverse_saturation_tint_30, } } /// generate a palette from the tint and shade palette /// algorithm. choose a bright background and a dark filling color pub fn dark_on_bright(input: Rgb) -> Palette { let tint_and_shade_palette = TintAndShadePalette::create(input); Palette { background_color: tint_and_shade_palette.base_tint_30, fill_color: tint_and_shade_palette.inverse_saturation_shade_30, } } } /// The Tint and Shade Palette from https://gitlab.com/cameralibre/tint-and-shade /// Thank you Sam #[allow(dead_code)] struct TintAndShadePalette { base_color: Rgb, base_tint_30: Rgb, base_tint_15: Rgb, base_shade_15: Rgb, base_shade_30: Rgb, complement_tint_30: Rgb, complement_tint_15: Rgb, complement_color: Rgb, complement_shade_15: Rgb, complement_shade_30: Rgb, inverse_saturation_tint_30: Rgb, inverse_saturation_tint_15: Rgb, inverse_saturation_color: Rgb, inverse_saturation_shade_15: Rgb, inverse_saturation_shade_30: Rgb, } impl TintAndShadePalette { /// create a Palette based on one input color pub fn create(input: Rgb) -> TintAndShadePalette { let hsl: Hsl = Hsl::from_rgb(input.into_linear()); let h = hsl.hue; let s = hsl.saturation; let l = hsl.lightness; let complement = h + 180.0 % 360.0; let tint_15 = l + 0.15; let tint_30 = l + 0.30; let shade_15 = l - 0.15; let shade_30 = l - 0.30; let inverse_saturation = 1.0 - s; TintAndShadePalette { base_color: Rgb::from_linear(Hsl::new(h, s, l).into_rgb()), base_tint_15: Rgb::from_linear(Hsl::new(h, s, tint_15).into_rgb()), base_tint_30: Rgb::from_linear(Hsl::new(h, s, tint_30).into_rgb()), base_shade_15: Rgb::from_linear(Hsl::new(h, s, shade_15).into_rgb()), base_shade_30: Rgb::from_linear(Hsl::new(h, s, shade_30).into_rgb()), complement_color: Rgb::from_linear(Hsl::new(complement, s, l).into_rgb()), complement_tint_15: Rgb::from_linear(Hsl::new(complement, s, tint_15).into_rgb()), complement_tint_30: Rgb::from_linear(Hsl::new(complement, s, tint_30).into_rgb()), complement_shade_15: Rgb::from_linear(Hsl::new(complement, s, shade_15).into_rgb()), complement_shade_30: Rgb::from_linear(Hsl::new(complement, s, shade_30).into_rgb()), inverse_saturation_color: Rgb::from_linear( Hsl::new(complement, inverse_saturation, l).into_rgb(), ), inverse_saturation_tint_15: Rgb::from_linear( Hsl::new(complement, inverse_saturation, tint_15).into_rgb(), ), inverse_saturation_tint_30: Rgb::from_linear( Hsl::new(complement, inverse_saturation, tint_30).into_rgb(), ), inverse_saturation_shade_15: Rgb::from_linear( Hsl::new(complement, inverse_saturation, shade_15).into_rgb(), ), inverse_saturation_shade_30: Rgb::from_linear( Hsl::new(complement, inverse_saturation, shade_30).into_rgb(), ), } } }