initial commit
4
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
node_modules/
|
||||
target/
|
||||
pkg/
|
||||
.DS_Store
|
||||
7
README.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
_Spiegel_ image filter project (WIP)
|
||||
|
||||
- rust
|
||||
- wasm
|
||||
|
||||
sample output
|
||||

|
||||
BIN
dist/11dc9380193954aac8c4.module.wasm
vendored
Normal file
BIN
dist/630027c604733df47374e4f5adb1b7c5.jpg
vendored
Normal file
|
After Width: | Height: | Size: 349 KiB |
BIN
dist/66d531fb4651c57454ae.module.wasm
vendored
Normal file
1
dist/796.bundle.js
vendored
Normal file
BIN
dist/93be161a4640fe100e05af248fa4c52e.png
vendored
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
dist/95cc0985b7bd6242de9b9665261616a3.jpg
vendored
Normal file
|
After Width: | Height: | Size: 192 KiB |
523
dist/bundle.js
vendored
Normal file
42
dist/crate_pkg_photon_rs_js.bundle.js
vendored
Normal file
42
dist/crate_pkg_spiegel_client_js.bundle.js
vendored
Normal file
BIN
dist/df3fbe72e3ad368ae5bf.module.wasm
vendored
Normal file
BIN
dist/ea872833a419652a23b47d50be7fe0ef.jpg
vendored
Normal file
|
After Width: | Height: | Size: 224 KiB |
BIN
dist/f49f7893ad0a3ad10176.module.wasm
vendored
Normal file
29
dist/index.html
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
|
||||
<title>Spiegel</title>
|
||||
<script defer src="bundle.js"></script></head>
|
||||
|
||||
<body>
|
||||
<div class="default">
|
||||
<div class="main">
|
||||
<label>
|
||||
<h2>Blur factor</h2< /label>
|
||||
<div class="slidecontainer">
|
||||
<input type="range" id="slider" value="0" min="0" max="100" class="slider" />
|
||||
</div>
|
||||
</label>
|
||||
<div class="main_content">
|
||||
<div class="content" id="images">
|
||||
<div id="image_container"></div>
|
||||
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
30
index.html
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
|
||||
<title>Spiegel</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="main">
|
||||
<label>
|
||||
<h2>Blur factor</h2>
|
||||
<h4 id="msg">(blurring can take up to 15 seconds, please be patient)</h4>
|
||||
</label>
|
||||
<div class="slidecontainer">
|
||||
<input type="range" id="slider" value="0" min="0" max="100" class="slider" />
|
||||
</div>
|
||||
</label>
|
||||
<div class="main_content">
|
||||
<div id="progress"></div>
|
||||
<div class="content" id="images">
|
||||
<div id="image_container"></div>
|
||||
|
||||
<canvas id="canvas"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
6753
package-lock.json
generated
Normal file
25
package.json
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"author": "Silvia O'Dwyer <silviaodwyerdev@gmail.com>",
|
||||
"name": "photon-wasm",
|
||||
"version": "0.1.0",
|
||||
"repository": "https://github.com/silvia-odwyer/photon",
|
||||
"license": "Apache-2.0",
|
||||
"scripts": {
|
||||
"start": "webpack-dev-server",
|
||||
"build": "webpack"
|
||||
},
|
||||
"bin": {
|
||||
"create-rust-webpack": ".bin/create-rust-webpack.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@wasm-tool/wasm-pack-plugin": "0.1.6",
|
||||
"clean-webpack-plugin": "^4.0.0",
|
||||
"css-loader": "^6.10.0",
|
||||
"file-loader": "^6.2.0",
|
||||
"html-webpack-plugin": "^5.6.0",
|
||||
"style-loader": "^3.3.4",
|
||||
"webpack": "^5.91.0",
|
||||
"webpack-cli": "^5.1.4",
|
||||
"webpack-dev-server": "^5.0.4"
|
||||
}
|
||||
}
|
||||
1353
server/Cargo.lock
generated
Normal file
20
server/Cargo.toml
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
[package]
|
||||
edition = "2021"
|
||||
name = "spiegel-server"
|
||||
version = "0.1.0"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
axum = { version = "0.7" }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
tokio = { version = "1.36", features = ["full"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
image = "0.24.1"
|
||||
anyhow = "1.0"
|
||||
include_dir = "0.7.3"
|
||||
tokio-util = { version = "0.7", features = ["io"] }
|
||||
tower = { version = "0.4", features = ["util"] }
|
||||
tower-http = { version = "0.5.0", features = ["fs", "trace"] }
|
||||
74
server/src/lib.rs
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
use std::sync::OnceLock;
|
||||
|
||||
use include_dir::{include_dir, Dir, DirEntry};
|
||||
|
||||
static SAMPLES: OnceLock<Vec<ColorSample>> = OnceLock::new();
|
||||
static SAMPLES_DIR: Dir = include_dir!("src/samples");
|
||||
|
||||
pub fn init() {
|
||||
SAMPLES.get_or_init(|| {
|
||||
println!("reading image samples");
|
||||
read_color_samples().unwrap()
|
||||
});
|
||||
}
|
||||
|
||||
pub fn get_closest_color<'a>(color: &String) -> &'a ColorSample {
|
||||
let color_samples = SAMPLES.get().unwrap();
|
||||
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, color);
|
||||
if diff < min_diff {
|
||||
closest = Some(sample);
|
||||
min_diff = diff;
|
||||
}
|
||||
}
|
||||
|
||||
closest.unwrap()
|
||||
}
|
||||
|
||||
/// returns squared euclidian color distance
|
||||
/// as if colors were points in 3d space
|
||||
fn get_distance(r1: u8, g1: u8, b1: u8, rgb: &String) -> f32 {
|
||||
let r2 = u8::from_str_radix(&rgb[0..2], 16).unwrap();
|
||||
let g2 = u8::from_str_radix(&rgb[2..4], 16).unwrap();
|
||||
let b2 = u8::from_str_radix(&rgb[4..6], 16).unwrap();
|
||||
let red_dif = r1 as f32 - r2 as f32;
|
||||
let green_dif = g1 as f32 - g2 as f32;
|
||||
let blue_dif = b1 as f32 - b2 as f32;
|
||||
return red_dif * red_dif + green_dif * green_dif + blue_dif * blue_dif;
|
||||
}
|
||||
|
||||
/// read all sample jpegs into memory
|
||||
pub fn read_color_samples() -> anyhow::Result<Vec<ColorSample>> {
|
||||
let mut color_samples: Vec<ColorSample> = Vec::new();
|
||||
|
||||
for entry in SAMPLES_DIR.entries() {
|
||||
if let DirEntry::File(f) = entry {
|
||||
let sample_image = f.contents();
|
||||
|
||||
let filename = entry.path().file_name().unwrap().to_str().unwrap();
|
||||
let hex_r = &filename[0..2];
|
||||
let hex_g = &filename[2..4];
|
||||
let hex_b = &filename[4..6];
|
||||
color_samples.push(ColorSample {
|
||||
filename: filename.into(),
|
||||
r: u8::from_str_radix(&hex_r, 16)?,
|
||||
g: u8::from_str_radix(&hex_g, 16)?,
|
||||
b: u8::from_str_radix(&hex_b, 16)?,
|
||||
image: sample_image,
|
||||
});
|
||||
}
|
||||
}
|
||||
println!("Done reading image samples");
|
||||
Ok(color_samples)
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ColorSample {
|
||||
pub filename: String,
|
||||
pub r: u8,
|
||||
pub g: u8,
|
||||
pub b: u8,
|
||||
pub image: &'static [u8],
|
||||
}
|
||||
32
server/src/main.rs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
use axum::extract::Path;
|
||||
use axum::http::{header, StatusCode};
|
||||
use axum::response::IntoResponse;
|
||||
use axum::{routing::get, Router};
|
||||
use spiegel_server::{get_closest_color, init};
|
||||
|
||||
/// serves images from memory
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
tracing_subscriber::fmt::init();
|
||||
init();
|
||||
let app = Router::new().route("/color/:rgb_hex", get(fetch_nearest_color));
|
||||
|
||||
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||
axum::serve(listener, app).await.unwrap();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn fetch_nearest_color(
|
||||
Path(rgb_hex): Path<String>,
|
||||
) -> Result<impl IntoResponse, (StatusCode, String)> {
|
||||
if rgb_hex.len() != 6 {
|
||||
return Err((
|
||||
StatusCode::BAD_REQUEST,
|
||||
"input should be color hex, eg AA11CC".into(),
|
||||
));
|
||||
}
|
||||
let closest = get_closest_color(&rgb_hex);
|
||||
|
||||
let headers = [(header::CONTENT_TYPE, "image/jpeg")];
|
||||
Ok((headers, closest.image))
|
||||
}
|
||||
BIN
server/src/samples/12110f.jpg
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
server/src/samples/131211.jpg
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
server/src/samples/21201b.jpg
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
server/src/samples/21201d.jpg
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
server/src/samples/212213.jpg
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
server/src/samples/22211b.jpg
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
server/src/samples/23221d.jpg
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
server/src/samples/23221f.jpg
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
server/src/samples/24231d.jpg
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
server/src/samples/252520.jpg
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
server/src/samples/262527.jpg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
server/src/samples/262628.jpg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
server/src/samples/272826.jpg
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
server/src/samples/291f19.jpg
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
server/src/samples/292927.jpg
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
server/src/samples/292a29.jpg
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
server/src/samples/2a2a28.jpg
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
server/src/samples/2a3960.jpg
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
server/src/samples/2b3a5f.jpg
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
server/src/samples/2c2c24.jpg
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
server/src/samples/2c3b64.jpg
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
server/src/samples/2c3c40.jpg
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
server/src/samples/2e2d26.jpg
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
server/src/samples/2e2d28.jpg
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
server/src/samples/30301c.jpg
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
server/src/samples/303030.jpg
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
server/src/samples/303131.jpg
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
server/src/samples/303632.jpg
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
server/src/samples/31302b.jpg
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
server/src/samples/313131.jpg
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
server/src/samples/32373a.jpg
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
server/src/samples/32373b.jpg
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
server/src/samples/333a73.jpg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
server/src/samples/334840.jpg
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
server/src/samples/343a6f.jpg
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
server/src/samples/343b73.jpg
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
server/src/samples/344845.jpg
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
server/src/samples/353420.jpg
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
server/src/samples/35342f.jpg
Normal file
|
After Width: | Height: | Size: 63 KiB |
BIN
server/src/samples/353a39.jpg
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
server/src/samples/353b43.jpg
Normal file
|
After Width: | Height: | Size: 53 KiB |
BIN
server/src/samples/363531.jpg
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
server/src/samples/363c71.jpg
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
server/src/samples/36414c.jpg
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
server/src/samples/364968.jpg
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
server/src/samples/373530.jpg
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
server/src/samples/373a54.jpg
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
server/src/samples/373b46.jpg
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
server/src/samples/373d2f.jpg
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
server/src/samples/373d47.jpg
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
server/src/samples/373d71.jpg
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
server/src/samples/382f1f.jpg
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
server/src/samples/383732.jpg
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
server/src/samples/383831.jpg
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
server/src/samples/383832.jpg
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
server/src/samples/383a46.jpg
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
server/src/samples/383c4f.jpg
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
server/src/samples/383d48.jpg
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
server/src/samples/384142.jpg
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
server/src/samples/38495a.jpg
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
server/src/samples/384b51.jpg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
server/src/samples/393b39.jpg
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
server/src/samples/394235.jpg
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
server/src/samples/3a4042.jpg
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
server/src/samples/3a4242.jpg
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
server/src/samples/3b4435.jpg
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
server/src/samples/3b4a6b.jpg
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
server/src/samples/3b4f6b.jpg
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
server/src/samples/3c3b34.jpg
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
server/src/samples/3c4d5f.jpg
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
server/src/samples/3d342a.jpg
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
server/src/samples/3d4343.jpg
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
server/src/samples/3d4a63.jpg
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
server/src/samples/3e3524.jpg
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
server/src/samples/3e3830.jpg
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
server/src/samples/3e3e32.jpg
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
server/src/samples/3e3e4a.jpg
Normal file
|
After Width: | Height: | Size: 46 KiB |
BIN
server/src/samples/3e3f27.jpg
Normal file
|
After Width: | Height: | Size: 48 KiB |