mirror of
https://github.com/foo-dogsquared/wiki.git
synced 2025-02-07 15:19:04 +00:00
1 line
6.6 KiB
JSON
1 line
6.6 KiB
JSON
{"pageProps":{"metadata":{"date":"\"2020-09-19 18:43:07 +08:00\"","date_modified":"\"2021-05-04 20:52:07 +08:00\"","language":"en","source":""},"title":"Generating human-friendly color schemes","hast":{"type":"root","children":[{"type":"element","tagName":"nav","properties":{"className":"toc"},"children":[{"type":"element","tagName":"ol","properties":{"className":"toc-level toc-level-1"},"children":[]}]},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Though we already have "},{"type":"element","tagName":"a","properties":{"href":"/2020-09-11-04-08-34"},"children":[{"type":"text","value":"Human-friendly colorspaces"}]},{"type":"text","value":", it doesn't mean that we can simply generate human-friendly color schemes.\nCertain colors can be perceived as too bright or too dark and having them grouped in a color palette will look out-of-place and/or horrible.\n"}]},{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Color spaces such as "},{"type":"element","tagName":"a","properties":{"href":"https://www.hsluv.org/"},"children":[{"type":"text","value":"HSLuv"}]},{"type":"text","value":" and "},{"type":"element","tagName":"a","properties":{"href":"https://en.wikipedia.org/wiki/CIELUV"},"children":[{"type":"text","value":"CIELUV"}]},{"type":"text","value":" respects perceptual uniformity which approximates how human vision see things.\nWe can simply generate colors with the aforementioned color spaces.\nHere's an example of a "},{"type":"element","tagName":"a","properties":{"href":"http://chriskempson.com/projects/base16/"},"children":[{"type":"text","value":"Base16"}]},{"type":"text","value":" color scheme generation from "},{"type":"element","tagName":"a","properties":{"href":"https://terminal.sexy/"},"children":[{"type":"text","value":"terminal.sexy"}]},{"type":"text","value":" ported to Rust.\n"}]},{"type":"element","tagName":"pre","properties":{"className":["src-block"]},"children":[{"type":"element","tagName":"code","properties":{"className":["language-rust"]},"children":[{"type":"text","value":"use std::error::Error;\nuse std::collections::HashMap;\nuse std::env;\n\nuse hsluv;\nuse rand_chacha::ChaCha8Rng;\nuse rand::{Rng, SeedableRng};\n\n#[macro_use]\nuse serde::{Deserialize, Serialize};\n\n\n// Based from the implemention at terminal.sexy repo\n// at https://github.com/stayradiated/terminal.sexy/blob/2e2c9bec994723a657cce8bf708d83879a50c0ce/lib/stores/random.js\n// which in turn based from the demo example at https://www.hsluv.org/syntax/.\ntype Colors = HashMap<String, String>;\n\n#[derive(Serialize, Deserialize, Debug)]\nstruct SpecialColors {\n background: String,\n foreground: String,\n cursor: String,\n}\n\nimpl SpecialColors {\n pub fn new() -> Self {\n Self {\n background: String::from(\"#000000\"),\n foreground: String::from(\"#000000\"),\n cursor: String::from(\"#000000\")\n }\n }\n}\n\n#[derive(Serialize, Deserialize, Debug)]\nstruct PywalObject {\n #[serde(default)]\n alpha: u8,\n\n special: SpecialColors,\n\n colors: Colors,\n\n wallpaper: Option<String>,\n}\n\nimpl PywalObject {\n pub fn new() -> Self {\n Self {\n alpha: 255,\n special: SpecialColors::new(),\n colors: Colors::new(),\n wallpaper: None\n }\n }\n}\n\n/// The command-line interface simply needs a seed to be parsed as an unsigned 64-bit integer (`u64`).\nfn main() -> Result<(), Box<dyn Error>> {\n let args: Vec<String> = env::args().collect();\n let mut result = PywalObject::new();\n\n let mut rng = match args.get(1) {\n Some(arg) => ChaCha8Rng::seed_from_u64(arg.parse::<u64>()?),\n None => ChaCha8Rng::from_entropy()\n };\n\n // 6 hues to pick from\n let base_hue: f64 = rng.gen_range(0.0, 360.0);\n let hues: Vec<f64> = ([0.0, 60.0, 120.0, 180.0, 240.0, 300.0])\n .iter()\n .map(|offset| (base_hue + offset) % 360.0)\n .collect();\n\n // 8 shades of low-saturated color\n let base_saturation: f64 = rng.gen_range(8.0, 40.0);\n let base_lightness: f64 = rng.gen_range(0.0, 10.0);\n let range_lightness: f64 = 90.0 - base_lightness;\n\n result.special.background = hsluv::hsluv_to_hex(\n (hues[0],\n base_saturation,\n base_lightness / 2.0)\n );\n\n result.special.foreground = hsluv::hsluv_to_hex(\n (hues[0],\n base_saturation,\n range_lightness)\n );\n\n result.special.cursor = result.special.foreground.clone();\n\n // Setting the colors according to the Base16 spec at http://chriskempson.com/projects/base16.\n for i in 0..7 {\n result.colors.insert(format!(\"color{}\", i), hsluv::hsluv_to_hex(\n (hues[0], base_saturation, base_lightness + (range_lightness * ((i as f64)/7.0).powf(1.5)))\n ));\n }\n\n // 8 random shades\n let min_saturation: f64 = rng.gen_range(30.0, 70.0);\n let max_saturation: f64 = min_saturation + 30.0;\n let min_lightness: f64 = rng.gen_range(50.0, 70.0);\n let max_lightness: f64 = min_lightness + 20.0;\n\n for j in 8..16 {\n result.colors.insert(format!(\"color{}\", j), hsluv::hsluv_to_hex(\n (hues[rng.gen_range(0, hues.len() - 1)], rng.gen_range(min_saturation, max_saturation), rng.gen_range(min_lightness, max_lightness))\n ));\n }\n\n println!(\"{:?}\", result);\n Ok(())\n}\n"}]}]},{"type":"element","tagName":"ul","properties":{},"children":[{"type":"element","tagName":"li","properties":{},"children":[{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"a","properties":{"href":"https://www.hsluv.org/"},"children":[{"type":"text","value":"HSLuv"}]}]}]},{"type":"element","tagName":"li","properties":{},"children":[{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"a","properties":{"href":"https://www.kuon.ch/post/2020-03-08-hsluv/"},"children":[{"type":"text","value":"This introductory article is a great resource on HSLuv"}]}]}]},{"type":"element","tagName":"li","properties":{},"children":[{"type":"element","tagName":"p","properties":{},"children":[{"type":"element","tagName":"a","properties":{"href":"https://www.boronine.com/2012/03/26/Color-Spaces-for-Human-Beings/"},"children":[{"type":"text","value":"Color spaces for human beings"}]}]}]},{"type":"element","tagName":"li","properties":{},"children":[{"type":"element","tagName":"p","properties":{},"children":[{"type":"text","value":"Human-friendly color scheme generation implementation based on "},{"type":"element","tagName":"a","properties":{"href":"https://terminal.sexy/"},"children":[{"type":"text","value":"terminal.sexy"}]},{"type":"text","value":".\n"}]}]}]}]},"backlinks":[{"path":"/2020-11-05-17-21-58","title":"Generate a color scheme based from a single color"}]},"__N_SSG":true} |