aboutsummaryrefslogtreecommitdiff
path: root/src/embedders.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/embedders.rs')
-rw-r--r--src/embedders.rs59
1 files changed, 48 insertions, 11 deletions
diff --git a/src/embedders.rs b/src/embedders.rs
index 7310a58..94fc122 100644
--- a/src/embedders.rs
+++ b/src/embedders.rs
@@ -1,3 +1,4 @@
+use rayon::prelude::*;
use std::path::PathBuf;
pub trait MetricElem {
@@ -22,7 +23,7 @@ impl EmbedderT for BrightnessEmbedder {
fn embed(&mut self, paths: &[PathBuf]) -> Result<Vec<f64>, String> {
paths
- .iter()
+ .par_iter()
.map(|p| {
let im = image::open(p).map_err(|e| e.to_string())?;
let num_bytes = 3 * (im.height() * im.width());
@@ -36,11 +37,14 @@ impl EmbedderT for BrightnessEmbedder {
.map(|e| *e as u64)
.sum::<u64>() as f64 / num_bytes as f64)
})
+ .collect::<Vec<_>>()
+ .into_iter()
.try_collect()
}
}
-struct Hue (f64);
+#[repr(transparent)]
+pub struct Hue (f64);
impl MetricElem for Hue {
fn dist(&self, b: &Hue) -> f64 {
let d = self.0.dist(&b.0);
@@ -50,11 +54,11 @@ impl MetricElem for Hue {
pub struct HueEmbedder;
impl EmbedderT for HueEmbedder {
- type Embedding = f64; // TODO anderes Ding was Winkel vergleicht
+ type Embedding = Hue;
- fn embed(&mut self, paths: &[PathBuf]) -> Result<Vec<f64>, String> {
+ fn embed(&mut self, paths: &[PathBuf]) -> Result<Vec<Hue>, String> {
paths
- .iter()
+ .par_iter()
.map(|p| {
let im = image::open(p).map_err(|e| e.to_string())?;
let num_pixels = im.height() * im.width();
@@ -67,7 +71,7 @@ impl EmbedderT for HueEmbedder {
})
.map(|e| e as f64 / 255. / num_pixels as f64);
- let mut hue =
+ let hue =
if sr >= sg && sr >= sb {
(sg - sb) / (sr - sg.min(sb))
}
@@ -78,16 +82,49 @@ impl EmbedderT for HueEmbedder {
4. + (sr - sg) / (sb - sr.min(sg))
};
- if hue < 0. {
- hue += 6.;
- }
-
if hue.is_nan() {
Err("Encountered NaN hue, possibly because of a colorless or empty image")?;
}
- Ok(hue)
+ Ok(Hue(hue))
+ })
+ .collect::<Vec<_>>()
+ .into_iter()
+ .try_collect()
+ }
+}
+
+impl MetricElem for (f64, f64, f64) {
+ fn dist(&self, o: &(f64, f64, f64)) -> f64 {
+ let (dr, dg, db) =
+ ((self.0 - o.0), (self.1 - o.1), (self.2 - o.2));
+ (dr*dr + dg*dg + db*db).sqrt()
+ }
+}
+
+pub struct ColorEmbedder;
+impl EmbedderT for ColorEmbedder {
+ type Embedding = (f64, f64, f64);
+
+ fn embed(&mut self, paths: &[PathBuf]) -> Result<Vec<(f64, f64, f64)>, String> {
+ paths
+ .par_iter()
+ .map(|p| {
+ let im = image::open(p).map_err(|e| e.to_string())?;
+ let num_pixels = im.height() * im.width();
+ let [sr, sg, sb] = im
+ .to_rgb8()
+ .pixels()
+ .fold([0, 0, 0], |[or, og, ob], n| {
+ let [nr, ng, nb] = n.0;
+ [or + nr as u64, og + ng as u64, ob + nb as u64]
+ })
+ .map(|e| e as f64 / num_pixels as f64);
+
+ Ok((sr, sg, sb))
})
+ .collect::<Vec<_>>()
+ .into_iter()
.try_collect()
}
}