|
@@ -2,9 +2,11 @@ use std::fs::File;
|
|
|
|
|
|
use serde::Deserialize;
|
|
use serde::Deserialize;
|
|
|
|
|
|
|
|
+type Pixel = (u8, u8, u8);
|
|
|
|
+
|
|
#[derive(Deserialize, Debug)]
|
|
#[derive(Deserialize, Debug)]
|
|
struct ColorEntry {
|
|
struct ColorEntry {
|
|
- color: (u8, u8, u8),
|
|
|
|
|
|
+ color: Pixel,
|
|
symbol: String,
|
|
symbol: String,
|
|
}
|
|
}
|
|
|
|
|
|
@@ -16,7 +18,7 @@ impl Mapping {
|
|
Ok(serde_yaml::from_reader(File::open(path)?)?)
|
|
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);
|
|
let found = self.0.iter().find(|entry| entry.color == color);
|
|
match found {
|
|
match found {
|
|
Some(entry) => &entry.symbol,
|
|
Some(entry) => &entry.symbol,
|
|
@@ -28,7 +30,7 @@ impl Mapping {
|
|
struct Image {
|
|
struct Image {
|
|
width: u32,
|
|
width: u32,
|
|
height: u32,
|
|
height: u32,
|
|
- data: Vec<(u8, u8, u8)>,
|
|
|
|
|
|
+ data: Vec<Pixel>,
|
|
}
|
|
}
|
|
|
|
|
|
impl Image {
|
|
impl Image {
|
|
@@ -60,6 +62,41 @@ impl Image {
|
|
data,
|
|
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)]
|
|
#[derive(Deserialize)]
|
|
@@ -92,8 +129,6 @@ impl Default for Config {
|
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
let img = Image::load("sample.png")?;
|
|
let img = Image::load("sample.png")?;
|
|
let mapping = Mapping::load("colors.yaml")?;
|
|
let mapping = Mapping::load("colors.yaml")?;
|
|
- let mut x = 0;
|
|
|
|
- let mut y = 0;
|
|
|
|
|
|
|
|
let config = Config::default();
|
|
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);
|
|
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() {
|
|
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);
|
|
layout.set_text(l);
|
|
pangocairo::functions::show_layout(&ctx, &layout);
|
|
pangocairo::functions::show_layout(&ctx, &layout);
|
|
}
|
|
}
|