diff --git a/Cargo.lock b/Cargo.lock
index b1f2f33..bfb2345 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -304,6 +304,12 @@ dependencies = [
"libc",
]
+[[package]]
+name = "hex"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+
[[package]]
name = "image"
version = "0.23.14"
@@ -954,8 +960,10 @@ name = "yew-app"
version = "0.1.0"
dependencies = [
"gloo-utils",
+ "hex",
"image",
"imageproc",
+ "lazy_static",
"log",
"wasm-bindgen",
"wasm-logger",
diff --git a/Cargo.toml b/Cargo.toml
index b2bccab..991092e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -27,4 +27,6 @@ web-sys = {version = "0.3.56", features = [
]}
yew = "0.19"
image = "0.23.14"
-imageproc="0.22.0"
\ No newline at end of file
+imageproc="0.22.0"
+lazy_static="1.4.0"
+hex="0.4.3"
\ No newline at end of file
diff --git a/index.html b/index.html
index d553e16..711f95d 100644
--- a/index.html
+++ b/index.html
@@ -2,7 +2,7 @@
-
+
Spiegel
diff --git a/src/app.rs b/src/app.rs
index 0f41c61..433ea69 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -1,24 +1,33 @@
use gloo_utils::document;
-use wasm_bindgen::JsCast;
+use image::RgbImage;
+use wasm_bindgen::{Clamped, JsCast};
use web_sys::{DragEvent, HtmlImageElement};
use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement, ImageData};
use web_sys::Url;
use yew::{Component, Context, html, Html};
+use crate::transform;
+use crate::transform::ColorSample;
+
pub enum Msg {
Dropped(DragEvent),
Dragged(DragEvent),
ImageLoaded,
}
-pub struct DropPhoto {}
+pub struct DropPhoto {
+ // color_samples: Vec
+}
impl Component for DropPhoto {
type Message = Msg;
type Properties = ();
fn create(_ctx: &Context) -> Self {
- Self {}
+ transform::init();
+ Self {
+ // color_samples: transform::init().expect("")
+ }
}
fn update(&mut self, _ctx: &Context, msg: Self::Message) -> bool {
@@ -44,7 +53,6 @@ impl Component for DropPhoto {
let img = document().get_element_by_id("source-image").expect("cannot get #source-image").dyn_into::().unwrap();
img.set_src(&url);
}
-
}
true
}
@@ -64,6 +72,17 @@ impl Component for DropPhoto {
if let Some(drop_zone) = document().get_element_by_id("drop-zone") {
drop_zone.set_attribute("style", "display:none").expect("Cannot update attribute");
}
+
+ let imgdata = ctx
+ .get_image_data(0.0, 0.0, canvas.width() as f64, canvas.height() as f64)
+ .unwrap();
+ let raw_pixels: Vec = imgdata.data().to_vec();
+ let rgb_src = RgbImage::from_raw(canvas.width(), canvas.height(), raw_pixels).unwrap();
+ // let transformed = transform::apply(rgb_src, &self.color_samples).expect("Cannot transform image");
+ let image_data = ImageData::new_with_u8_clamped_array_and_sh(Clamped(&rgb_src.to_vec()),
+ canvas.width(), canvas.height());
+
+ ctx.put_image_data(&image_data.expect(""), 0.0, 0.0);
}
true
}
diff --git a/src/main.rs b/src/main.rs
index 7909bb2..c3ce883 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,6 +1,7 @@
mod app;
mod transform;
mod quantizer;
+mod samples;
fn main() {
wasm_logger::init(wasm_logger::Config::default());
diff --git a/src/transform.rs b/src/transform.rs
index 40b85ec..28a5e0f 100644
--- a/src/transform.rs
+++ b/src/transform.rs
@@ -1,37 +1,38 @@
use std::{error::Error, fs, result::Result};
+use std::collections::HashMap;
use image::{GenericImageView, ImageBuffer, Pixel, Rgb, RgbImage};
use imageproc::point::Point;
-use crate::quantizer;
-pub fn run(image_filename: &String) -> Result<(), Box> {
- println!("reading image samples");
- let color_samples = read_color_samples()?;
+use crate::{quantizer, samples};
- let src: RgbImage = image::open(image_filename).unwrap().into_rgb8();
-
- println!("applying gaussian blur filter");
- let gauss = imageproc::filter::gaussian_blur_f32(&src, 2.0);
- println!("applying median filter");
- let median = imageproc::filter::median_filter(&gauss, 2, 2);
- println!("applying color quantization filter");
- let quantized = quantizer::quantize(&median, 256);
-
- println!("applying samples");
- let out = apply_samples_to_image(quantized, &color_samples);
- out.save_with_format("output.jpg", image::ImageFormat::Jpeg)?;
-
- Ok(())
+struct Transformer {
+ color_samples: HashMap, //cache
}
-fn apply_samples_to_image(mut src: RgbImage, color_samples: &Vec) -> RgbImage{
+impl Transformer {
+ fn new() -> Self {
+ Self { color_samples: HashMap::new() }
+ }
+
+
+ pub fn apply(&mut self, src: RgbImage, color_samples: &mut HashMap) -> Result> {
+ let gauss = imageproc::filter::gaussian_blur_f32(&src, 2.0);
+ let median = imageproc::filter::median_filter(&gauss, 2, 2);
+ let quantized = quantizer::quantize(&median, 256);
+ let out = apply_samples_to_image(quantized, color_samples);
+
+ Ok(out)
+ }
+}
+fn apply_samples_to_image(mut src: RgbImage, color_samples: &mut HashMap) -> RgbImage {
let mut imgbuf = RgbImage::new(src.width(), src.height());
unsafe {
for y in 0..src.height() {
for x in 0..src.width() {
let pixel = &src.unsafe_get_pixel(x, y);
if imgbuf.unsafe_get_pixel(x, y).channels() == [0, 0, 0] {
- if let Some(sample) = get_closest(&color_samples, pixel) {
+ if let Some(sample) = get_closest(olor_samples, pixel) {
fill(&mut src, sample, &mut imgbuf, pixel, x, y);
}
}
@@ -105,21 +106,31 @@ fn is_same(p1: &Rgb, p2: &Rgb) -> bool {
&& i16::abs(p1[2] as i16 - p2[2] as i16) < 4
}
-fn get_closest<'a>(
- color_samples: &'a Vec,
+fn get_closest(
+ color_samples: &mut HashMap,
pixel: &Rgb,
-) -> Option<&'a ColorSample> {
+) -> Option<&ColorSample> {
let mut closest = None;
let mut min_diff: f32 = 4294967295.0; //0xFFFFFFFF
- for sample in color_samples {
- let diff = get_distance(sample.r, sample.g, sample.b, pixel);
+ for sample in samples::SAMPLES {
+ let r = hex::decode(sample[0..2], ).unwrap()[0];
+ let g = hex::decode(sample[2..4], ).unwrap()[0];
+ let b = hex::decode(sample[4..6], ).unwrap()[0];
+ let diff = get_distance(r,g,b, pixel);
if diff < min_diff {
closest = Some(sample);
min_diff = diff;
}
}
- closest
+ if color_samples.contains(&closest){
+ return color_samples.get(&closest);
+ } else {
+ //download image
+ let image = ColorSample{r,g,b, image: RgbImage::from_raw(0,0,vec![]).unwrap()};
+ color_samples.insert(sample.to_owned(), image);
+ }
+ None
}
fn get_distance(r: u8, g: u8, b: u8, c2: &Rgb) -> f32 {
@@ -129,36 +140,46 @@ fn get_distance(r: u8, g: u8, b: u8, c2: &Rgb) -> f32 {
return f32::sqrt(red_dif * red_dif + green_dif * green_dif + blue_dif * blue_dif);
}
-fn read_color_samples() -> Result, Box> {
- let paths = fs::read_dir("samples")?;
- let mut color_samples: Vec = Vec::new();
- for path in paths {
- let path = path?.path();
- let filename = path.to_str().unwrap().to_owned();
+// fn read_color_samples() -> Result, Box> {
+// let paths = fs::read_dir("samples")?;
+// let mut color_samples: Vec = Vec::new();
+// for path in paths {
+// let path = path?.path();
+// let filename = path.to_str().unwrap().to_owned();
+//
+// if filename.ends_with(".jpg") {
+// let sample_image: RgbImage = image::open(&filename).unwrap().into_rgb8();
+// let hex_r = &filename[8..10];
+// let hex_g = &filename[10..12];
+// let hex_b = &filename[12..14];
+// color_samples.push(ColorSample {
+// r: u8::from_str_radix(&hex_r, 16).unwrap(),
+// g: u8::from_str_radix(&hex_g, 16).unwrap(),
+// b: u8::from_str_radix(&hex_b, 16).unwrap(),
+// image: sample_image,
+// });
+// }
+// }
+// Ok(color_samples)
+// }
- if filename.ends_with(".jpg") {
- let sample_image: RgbImage = image::open(&filename).unwrap().into_rgb8();
- let hex_r = &filename[8..10];
- let hex_g = &filename[10..12];
- let hex_b = &filename[12..14];
- color_samples.push(ColorSample {
- r: u8::from_str_radix(&hex_r, 16).unwrap(),
- g: u8::from_str_radix(&hex_g, 16).unwrap(),
- b: u8::from_str_radix(&hex_b, 16).unwrap(),
- image: sample_image,
- });
- }
- }
- Ok(color_samples)
-}
-
-struct ColorSample {
+pub struct ColorSample {
r: u8,
g: u8,
b: u8,
image: RgbImage,
}
+impl PartialEq for ColorSample{
+ fn eq(&self, other: &Self) -> bool {
+ self.name == other.name
+ }
+
+ fn ne(&self, other: &Self) -> bool {
+ self.name != other.name
+ }
+}
+
#[derive(Debug)]
struct List {
head: Option>,
@@ -197,7 +218,6 @@ struct Node {
#[cfg(test)]
mod test {
-
use super::*;
#[test]