My omnium-gatherom of scripts and source code.
1use lerp::Lerp;
2
3#[derive(Debug, Clone, Copy)]
4enum Extension {
5 PPM,
6 PNG,
7 BMP
8}
9
10struct RGB {
11 red: u8,
12 green: u8,
13 blue: u8,
14}
15
16impl RGB {
17 fn new(r: u8, g: u8, b: u8) -> RGB {
18 RGB {
19 red: r,
20 green: g,
21 blue: b,
22 }
23 }
24
25}
26
27#[derive(Debug, Copy, Clone)]
28struct HSV {
29 hue: f64,
30 saturation: f64,
31 value: f64,
32}
33
34trait ToU8 {
35 fn tou8(&self) -> u8;
36}
37
38impl ToU8 for f64 {
39 fn tou8(&self) -> u8 {
40 if self <= &0.0 {
41 return 0_u8;
42 }
43 if self <= &255.0 {
44 #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
45 return self.trunc() as u8;
46 }
47 return 255_u8;
48 }
49}
50
51impl HSV {
52 fn new(h: f64, s: f64, v: f64) -> HSV {
53 HSV {
54 hue: h,
55 saturation: s,
56 value: v,
57 }
58 }
59
60 fn to_rgb(&self) -> RGB {
61 let chroma = self.saturation * self.value * 255.0;
62 let cube_hue = self.hue / 60.0;
63 let tmp = chroma * (1.0 - (cube_hue.rem_euclid(2.0) - 1.0).abs());
64 let m = (self.value - chroma) * 255.0;
65
66 let c: (f64, f64, f64) = if cube_hue <= 1.0 {
67 (chroma + m, tmp + m, m)
68 } else if cube_hue <= 2.0 {
69 (tmp + m, chroma + m, m)
70 } else if cube_hue <= 3.0 {
71 (m, chroma + m, tmp + m)
72 } else if cube_hue <= 4.0 {
73 (m, tmp + m, chroma + m)
74 } else if cube_hue <= 5.0 {
75 (tmp + m, m, chroma + m)
76 } else {
77 (chroma + m, m, tmp + m)
78 };
79
80 RGB::new(c.0.tou8(), c.1.tou8(), c.2.tou8())
81 }
82
83 fn lerp(&self, rhs: &HSV, t: f64) -> HSV {
84 HSV::new(self.hue.lerp(rhs.hue, t),
85 self.saturation.lerp(rhs.saturation, t),
86 self.value.lerp(rhs.value, t)
87 )
88 }
89}
90
91struct Point {
92 x: f64,
93 y: f64,
94}
95
96impl Point {
97 fn new(x: f64, y: f64) -> Point {
98 Point {
99 x: x,
100 y: y,
101 }
102 }
103}
104
105struct Canvas {
106 x_max: f64,
107 y_max: f64,
108 x_min: f64,
109 y_min: f64,
110 w: usize,
111 h: usize,
112
113 pixels: Vec<HSV>,
114}
115
116impl Canvas {
117 fn new<const width: usize, const height: usize>(p: &Point, size: f64) -> Canvas {
118 Canvas {
119 x_max: p.x + (size / 2.0),
120 y_max: p.y + (size / 2.0),
121 x_min: p.x - (size / 2.0),
122 y_min: p.y - (size / 2.0),
123 w: width,
124 h: height,
125
126 pixels: Vec::new(),
127 }
128 }
129
130 fn export(file_type: Extension, file_path: String) {
131 match file_type {
132 Extension::PPM => { },
133 Extension::PNG => { },
134 Extension::BMP => { }
135 }
136 }
137
138 fn coordinate(&self, idx: usize) -> Point {
139 Point {
140 x: self.x_min.lerp(self.x_max, (idx % self.w) as f64 / self.w as f64),
141 y: self.y_min.lerp(self.x_max, (idx / self.h) as f64 / self.h as f64)
142 }
143 }
144
145 fn construct<F>(&self, op: F) where F: Fn(Point) -> HSV {
146 // parellelize here
147 for (idx, mut pixel) in self.pixels.iter().enumerate() {
148 pixel = &op(self.coordinate(idx));
149 }
150 }
151
152 fn at(&self, idx: usize) -> HSV {
153 self.pixels[idx]
154 }
155
156 fn index(&self, row: usize, col: usize) -> HSV {
157 self.pixels[row + col * self.w]
158 }
159}