|  | @@ -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);
 | 
	
		
			
				|  |  |          }
 |