diff options
author | metamuffin <yvchraiqi@protonmail.com> | 2022-06-05 16:17:11 +0200 |
---|---|---|
committer | metamuffin <yvchraiqi@protonmail.com> | 2022-06-05 16:17:11 +0200 |
commit | 963c729bcdc1e5f82890f96bc55f1532f6eaf763 (patch) | |
tree | 07656d74aee13d075faba4cc13ca28e13dcb7c4a | |
parent | 1b70d7d654bef22661cf3184806175fcb17e1bd6 (diff) | |
download | blubcat-963c729bcdc1e5f82890f96bc55f1532f6eaf763.tar blubcat-963c729bcdc1e5f82890f96bc55f1532f6eaf763.tar.bz2 blubcat-963c729bcdc1e5f82890f96bc55f1532f6eaf763.tar.zst |
thing
-rw-r--r-- | src/lib.rs | 9 | ||||
-rw-r--r-- | src/main.rs | 182 | ||||
-rw-r--r-- | src/pattern.rs | 40 | ||||
-rw-r--r-- | src/transform.rs | 24 |
4 files changed, 136 insertions, 119 deletions
diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..76b35c9 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,9 @@ +use color::Color; + +pub mod color; +pub mod transform; +pub mod pattern; + +pub trait Sample { + fn sample(&mut self, x: f64, y: f64) -> Color; +} diff --git a/src/main.rs b/src/main.rs index d8c4a21..a0f7e9f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,12 @@ #![feature(box_syntax)] -pub mod color; use anyhow::Result; -use color::Color; +use blubcat::{ + color::Color, + pattern::{Rainbow, Sequence, Solid, Gradient}, + transform::{Matrix, Polar}, + Sample, +}; use std::{ env, f64::consts::PI, @@ -12,17 +16,17 @@ use std::{ }; static HELP: &str = " -Usage: blubcat [PATTERN] [FILE]... +Usage: blubcat [PATTERN] [FILE...] Concatenate FILE(s) to standard output, colorizing the output according to PATTERN. With no FILE, or when FILE is -, the standard input is read. If PATTERN is repeated only the last one will be used. PATTERN: - -R --rainbow Rainbow + -R --rainbow Sinebow -S --sequence <c1,c2,c3,...> Sequences colors on the X-axis -G --gradient <c1,c2,c3,...> Interpolates the colors on the X-axis - <PATTERN> <TRANSFORM> + <PATTERN...> <TRANSFORM> Push mulple patterns to a stack, then process them with transform <PRESET> TRANSFORM: @@ -31,7 +35,9 @@ TRANSFORM: -m --matrix <x> <y> <z> <w> PRESET: - -P --pride Pride flag + --zebra + --pride --trans + --ukraine ofc the this needed :) COLOR: <rrggbb> @@ -42,7 +48,7 @@ COLOR: fn main() -> Result<()> { let mut args = env::args().skip(1); - let mut pat: Box<dyn Sample2D> = box Solid(Color::WHITE); + let mut pat: Vec<Box<dyn Sample>> = vec![]; loop { let a = args.next(); @@ -58,6 +64,7 @@ fn main() -> Result<()> { if !a.starts_with("-") || a == "--" || a == "-" { break; } + let mut push_queue: Vec<Box<dyn Sample>> = vec![]; match a.as_str() { "-?" | "--help" => { println!("{}", HELP); @@ -65,70 +72,62 @@ fn main() -> Result<()> { } /* PRESETS */ - "-P" | "--pride" => { - pat = box Transform { - matrix: ((1.0 / 12.0, 1.0 / 12.0), (0.0, 0.0)), - inner: box Extend(box Sequence(vec![ - Color::parse("e50000").unwrap(), - Color::parse("ff8d00").unwrap(), - Color::parse("ffee00").unwrap(), - Color::parse("028121").unwrap(), - Color::parse("004cff").unwrap(), - Color::parse("770088").unwrap(), - ])), - } - } + "--pride" => pat.push(flag_helper(&[ + "e50000", "ff8d00", "ffee00", "028121", "004cff", "770088", + ])), + "--zebra" => pat.push(flag_helper(&["000000", "ffffff"])), + "--trans" => pat.push(flag_helper(&[ + "5bcffb", "f5abb9", "ffffff", "f5abb9", "5bcffb", + ])), + "--ukraine" => pat.push(flag_helper(&["0057B8", "FFD700"])), /* PATTERNS */ - "-R" | "--rainbow" => pat = box Extend(box Rainbow), - "-S" | "--sequence" => { - pat = box Extend(box Sequence( - arg_next() - .unwrap() - .split(",") - .map(|e| Color::parse(e).expect("color invalid")) - .collect::<Vec<_>>(), - )) - } - "-G" | "--gradient" => { - pat = box Extend(box Gradient( - arg_next() - .unwrap() - .split(",") - .map(|e| Color::parse(e).expect("color invalid")) - .collect::<Vec<_>>(), - )) - } + "-R" | "--rainbow" => pat.push(box Rainbow), + "-S" | "--sequence" => pat.push(box Sequence( + arg_next() + .unwrap() + .split(",") + .map(|e| Color::parse(e).expect("color invalid")) + .collect::<Vec<_>>(), + )), + "-G" | "--gradient" => pat.push(box Gradient( + arg_next() + .unwrap() + .split(",") + .map(|e| Color::parse(e).expect("color invalid")) + .collect::<Vec<_>>(), + )), /* TRANSFORMS */ "-s" | "--scale" => { let fac = arg_num(); - pat = box Transform { - inner: pat, + push_queue.push(box Matrix { + inner: pat.pop().unwrap(), matrix: ((fac, 0.0), (0.0, fac)), - } + }) } "-r" | "--rotate" => { let angle = arg_num() * PI * 2.0; - pat = box Transform { - inner: pat, + push_queue.push(box Matrix { + inner: pat.pop().unwrap(), matrix: ((angle.cos(), -angle.sin()), (angle.sin(), angle.cos())), - } - } - "-m" | "--matrix" => { - pat = box Transform { - inner: pat, - matrix: ((arg_num(), arg_num()), (arg_num(), arg_num())), - } + }) } + "-m" | "--matrix" => push_queue.push(box Matrix { + inner: pat.pop().unwrap(), + matrix: ((arg_num(), arg_num()), (arg_num(), arg_num())), + }), + "-p" | "--polar" => push_queue.push(box Polar(pat.pop().unwrap())), _ => panic!("unknown option {}", &a), } + pat.extend(push_queue.drain(..)) } else { break; } } let inputs = args.collect::<Vec<String>>(); + let mut pat = pat.pop().unwrap_or_else(|| box Solid(Color::WHITE)); if inputs.len() == 0 { colorize(stdin(), &mut pat)? @@ -141,7 +140,19 @@ fn main() -> Result<()> { Ok(()) } -fn colorize(file: impl Read, sampler: &mut Box<dyn Sample2D>) -> Result<()> { +fn flag_helper(colors: &[&str]) -> Box<dyn Sample> { + box Matrix { + matrix: ((1.0 / 12.0, 1.0 / 12.0), (0.0, 0.0)), + inner: box Sequence( + colors + .into_iter() + .map(|e| Color::parse(e).unwrap()) + .collect(), + ), + } +} + +fn colorize(file: impl Read, sampler: &mut Box<dyn Sample>) -> Result<()> { let mut file = BufReader::new(file); let mut line = String::new(); for y in 0.. { @@ -156,70 +167,3 @@ fn colorize(file: impl Read, sampler: &mut Box<dyn Sample2D>) -> Result<()> { } Ok(()) } - -trait Sample2D { - fn sample(&mut self, x: f64, y: f64) -> Color; -} -trait Sample1D { - fn sample(&mut self, x: f64) -> Color; -} - -struct Extend(Box<dyn Sample1D>); -impl Sample2D for Extend { - fn sample(&mut self, x: f64, _y: f64) -> Color { - self.0.sample(x) - } -} - -struct Transform { - pub inner: Box<dyn Sample2D>, - pub matrix: ((f64, f64), (f64, f64)), -} -impl Sample2D for Transform { - fn sample(&mut self, x: f64, y: f64) -> Color { - let (x, y) = ( - x * self.matrix.0 .0 + y * self.matrix.0 .1, - x * self.matrix.1 .0 + y * self.matrix.1 .1, - ); - self.inner.sample(x, y) - } -} - -struct Rainbow; -impl Sample1D for Rainbow { - fn sample(&mut self, x: f64) -> Color { - static PI: f64 = 3.14; - let x = x * PI * 2.0; - return Color { - r: (x + PI / 3.0 * 0.0).sin() * 0.5 + 0.5, - g: (x + PI / 3.0 * 2.0).sin() * 0.5 + 0.5, - b: (x + PI / 3.0 * 4.0).sin() * 0.5 + 0.5, - }; - } -} - -struct Sequence(pub Vec<Color>); -impl Sample1D for Sequence { - fn sample(&mut self, x: f64) -> Color { - self.0[(x * self.0.len() as f64).floor() as usize % self.0.len()] - } -} - -struct Gradient(pub Vec<Color>); -impl Sample1D for Gradient { - fn sample(&mut self, x: f64) -> Color { - let index = x * self.0.len() as f64; - let index_int = index.floor() as usize; - let index_error = index % 1.0; - let a = self.0[index_int % self.0.len()]; - let b = self.0[(index_int + 1) % self.0.len()]; - Color::mix(a, b, index_error) - } -} - -struct Solid(Color); -impl Sample2D for Solid { - fn sample(&mut self, _x: f64, _y: f64) -> Color { - self.0 - } -} diff --git a/src/pattern.rs b/src/pattern.rs new file mode 100644 index 0000000..ba9899e --- /dev/null +++ b/src/pattern.rs @@ -0,0 +1,40 @@ +use crate::{color::Color, Sample}; + +pub struct Rainbow; +impl Sample for Rainbow { + fn sample(&mut self, x: f64, _y: f64) -> Color { + static PI: f64 = 3.14; + let x = x * PI * 2.0; + return Color { + r: (x + PI / 3.0 * 0.0).sin() * 0.5 + 0.5, + g: (x + PI / 3.0 * 2.0).sin() * 0.5 + 0.5, + b: (x + PI / 3.0 * 4.0).sin() * 0.5 + 0.5, + }; + } +} + +pub struct Sequence(pub Vec<Color>); +impl Sample for Sequence { + fn sample(&mut self, x: f64, _y: f64) -> Color { + self.0[(x * self.0.len() as f64).floor() as usize % self.0.len()] + } +} + +pub struct Gradient(pub Vec<Color>); +impl Sample for Gradient { + fn sample(&mut self, x: f64, _y: f64) -> Color { + let index = x * self.0.len() as f64; + let index_int = index.floor() as usize; + let index_error = index % 1.0; + let a = self.0[index_int % self.0.len()]; + let b = self.0[(index_int + 1) % self.0.len()]; + Color::mix(a, b, index_error) + } +} + +pub struct Solid(pub Color); +impl Sample for Solid { + fn sample(&mut self, _x: f64, _y: f64) -> Color { + self.0 + } +} diff --git a/src/transform.rs b/src/transform.rs new file mode 100644 index 0000000..8b555d1 --- /dev/null +++ b/src/transform.rs @@ -0,0 +1,24 @@ +use crate::{color::Color, Sample}; + +pub struct Matrix { + pub inner: Box<dyn Sample>, + pub matrix: ((f64, f64), (f64, f64)), +} +impl Sample for Matrix { + fn sample(&mut self, x: f64, y: f64) -> Color { + let (x, y) = ( + x * self.matrix.0 .0 + y * self.matrix.0 .1, + x * self.matrix.1 .0 + y * self.matrix.1 .1, + ); + self.inner.sample(x, y) + } +} + +pub struct Polar(pub Box<dyn Sample>); +impl Sample for Polar { + fn sample(&mut self, x: f64, y: f64) -> Color { + let ang = x.atan2(y); + let dist = (x * x + y * y).sqrt(); + self.0.sample(ang, dist) + } +} |