aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormetamuffin <yvchraiqi@protonmail.com>2022-06-05 16:17:11 +0200
committermetamuffin <yvchraiqi@protonmail.com>2022-06-05 16:17:11 +0200
commit963c729bcdc1e5f82890f96bc55f1532f6eaf763 (patch)
tree07656d74aee13d075faba4cc13ca28e13dcb7c4a /src
parent1b70d7d654bef22661cf3184806175fcb17e1bd6 (diff)
downloadblubcat-963c729bcdc1e5f82890f96bc55f1532f6eaf763.tar
blubcat-963c729bcdc1e5f82890f96bc55f1532f6eaf763.tar.bz2
blubcat-963c729bcdc1e5f82890f96bc55f1532f6eaf763.tar.zst
thing
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs9
-rw-r--r--src/main.rs182
-rw-r--r--src/pattern.rs40
-rw-r--r--src/transform.rs24
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)
+ }
+}