Przeglądaj źródła

put pixel indexing into an iterator

Getty Ritter 2 lat temu
rodzic
commit
9f2593d9f4
1 zmienionych plików z 43 dodań i 14 usunięć
  1. 43 14
      src/main.rs

+ 43 - 14
src/main.rs

@@ -2,9 +2,11 @@ use std::fs::File;
 
 use serde::Deserialize;
 
+type Pixel = (u8, u8, u8);
+
 #[derive(Deserialize, Debug)]
 struct ColorEntry {
-    color: (u8, u8, u8),
+    color: Pixel,
     symbol: String,
 }
 
@@ -16,7 +18,7 @@ impl Mapping {
         Ok(serde_yaml::from_reader(File::open(path)?)?)
     }
 
-    fn lookup(&self, color: (u8, u8, u8)) -> &str {
+    fn lookup(&self, color: Pixel) -> &str {
         let found = self.0.iter().find(|entry| entry.color == color);
         match found {
             Some(entry) => &entry.symbol,
@@ -28,7 +30,7 @@ impl Mapping {
 struct Image {
     width: u32,
     height: u32,
-    data: Vec<(u8, u8, u8)>,
+    data: Vec<Pixel>,
 }
 
 impl Image {
@@ -60,6 +62,41 @@ impl Image {
             data,
         })
     }
+
+    fn iter(&self) -> ImageIterator {
+        ImageIterator {
+            width: self.width,
+            x: 0,
+            y: 0,
+            values: self.data.iter(),
+        }
+    }
+}
+
+struct ImageIterator<'a> {
+    width: u32,
+    x: u32,
+    y: u32,
+    values: std::slice::Iter<'a, Pixel>,
+}
+
+impl<'a> Iterator for ImageIterator<'a> {
+    type Item = ((u32, u32), Pixel);
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let px = self.values.next();
+        if let Some(px) = px {
+            let ret = ((self.x, self.y), *px);
+            self.x += 1;
+            if self.x == self.width {
+                self.x = 0;
+                self.y += 1;
+            }
+            Some(ret)
+        } else {
+            None
+        }
+    }
 }
 
 #[derive(Deserialize)]
@@ -92,8 +129,6 @@ impl Default for Config {
 fn main() -> Result<(), Box<dyn std::error::Error>> {
     let img = Image::load("sample.png")?;
     let mapping = Mapping::load("colors.yaml")?;
-    let mut x = 0;
-    let mut y = 0;
 
     let config = Config::default();
 
@@ -136,17 +171,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
 
     ctx.set_source_rgb(0.0, 0.0, 0.0);
 
-    for (r, g, b) in img.data.iter() {
-        let l = mapping.lookup((*r, *g, *b));
-
-        x += 1;
-        if x == img.width {
-            x = 0;
-            y += 1;
-        }
+    for ((x, y), pixel) in img.iter() {
+        let l = mapping.lookup(pixel);
 
         if !l.is_empty() {
-            ctx.move_to(config.scale(x - 1) + 5.0, config.scale(y) + 3.0);
+            ctx.move_to(config.scale(x) + 5.0, config.scale(y) + 3.0);
             layout.set_text(l);
             pangocairo::functions::show_layout(&ctx, &layout);
         }