My omnium-gatherom of scripts and source code.
at main 159 lines 3.4 kB view raw
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}