first commit
This commit is contained in:
commit
6b90f1b054
12 changed files with 1732 additions and 0 deletions
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
/target
|
||||||
|
/dist
|
||||||
|
*.iml
|
||||||
|
.idea/
|
||||||
978
Cargo.lock
generated
Normal file
978
Cargo.lock
generated
Normal file
|
|
@ -0,0 +1,978 @@
|
||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ab_glyph_rasterizer"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a13739d7177fbd22bb0ed28badfff9f372f8bef46c863db4e1c6248f6b223b6e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "adler"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "adler32"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "boolinator"
|
||||||
|
version = "2.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cfa8873f51c92e232f9bac4065cddef41b714152812bfc5f7672ba16d6ef8cd9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bumpalo"
|
||||||
|
version = "3.9.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytemuck"
|
||||||
|
version = "1.7.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "439989e6b8c38d1b6570a384ef1e49c8848128f5a97f3914baef02920842712f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder"
|
||||||
|
version = "1.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "color_quant"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "console_error_panic_hook"
|
||||||
|
version = "0.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "conv"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "78ff10625fd0ac447827aa30ea8b861fead473bb60aeb73af6c1c58caf0d1299"
|
||||||
|
dependencies = [
|
||||||
|
"custom_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crc32fast"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-channel"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e54ea8bc3fb1ee042f5aace6e3c6e025d3874866da222930f70ce62aceba0bfa"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-deque"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-epoch",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-epoch"
|
||||||
|
version = "0.9.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c00d6d2ea26e8b151d99093005cb442fb9a37aeaca582a03ec70946f49ab5ed9"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"lazy_static",
|
||||||
|
"memoffset",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.8.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b5e5bed1f1c269533fa816a0a5492b3545209a205ca1a54842be180eb63a16a6"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"lazy_static",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "custom_derive"
|
||||||
|
version = "0.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ef8ae57c4978a2acd8b869ce6b9ca1dfe817bff704c220209fdef2c0b75a01b9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "deflate"
|
||||||
|
version = "0.8.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174"
|
||||||
|
dependencies = [
|
||||||
|
"adler32",
|
||||||
|
"byteorder",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.1.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"wasi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gif"
|
||||||
|
version = "0.11.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c3a7187e78088aead22ceedeee99779455b23fc231fe13ec443f99bb71694e5b"
|
||||||
|
dependencies = [
|
||||||
|
"color_quant",
|
||||||
|
"weezl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gloo"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "23947965eee55e3e97a5cd142dd4c10631cc349b48cecca0ed230fd296f568cd"
|
||||||
|
dependencies = [
|
||||||
|
"gloo-console",
|
||||||
|
"gloo-dialogs",
|
||||||
|
"gloo-events",
|
||||||
|
"gloo-file",
|
||||||
|
"gloo-render",
|
||||||
|
"gloo-storage",
|
||||||
|
"gloo-timers",
|
||||||
|
"gloo-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gloo-console"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3907f786f65bbb4f419e918b0c5674175ef1c231ecda93b2dbd65fd1e8882637"
|
||||||
|
dependencies = [
|
||||||
|
"js-sys",
|
||||||
|
"serde",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"web-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gloo-dialogs"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4ffb557a2ea2ed283f1334423d303a336fad55fb8572d51ae488f828b1464b40"
|
||||||
|
dependencies = [
|
||||||
|
"wasm-bindgen",
|
||||||
|
"web-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gloo-events"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "088514ec8ef284891c762c88a66b639b3a730134714692ee31829765c5bc814f"
|
||||||
|
dependencies = [
|
||||||
|
"wasm-bindgen",
|
||||||
|
"web-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gloo-file"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aa5d6084efa4a2b182ef3a8649cb6506cb4843f22cf907c6e0a799944248ae90"
|
||||||
|
dependencies = [
|
||||||
|
"gloo-events",
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"web-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gloo-render"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b4cda6e149df3bb4a3c6a343873903e5bcc2448a9877d61bb8274806ad67f6e"
|
||||||
|
dependencies = [
|
||||||
|
"wasm-bindgen",
|
||||||
|
"web-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gloo-storage"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b5057761927af1b1929d02b1f49cf83553dd347a473ee7c8bb08420f2673ffc"
|
||||||
|
dependencies = [
|
||||||
|
"gloo-utils",
|
||||||
|
"js-sys",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"thiserror",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"web-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gloo-timers"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4d12a7f4e95cfe710f1d624fb1210b7d961a5fb05c4fd942f4feab06e61f590e"
|
||||||
|
dependencies = [
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gloo-utils"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "05c77af6f96a4f9e27c8ac23a88407381a31f4a74c3fb985c85aa79b8d898136"
|
||||||
|
dependencies = [
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"web-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.11.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.1.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "image"
|
||||||
|
version = "0.23.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
"byteorder",
|
||||||
|
"color_quant",
|
||||||
|
"gif",
|
||||||
|
"jpeg-decoder",
|
||||||
|
"num-iter",
|
||||||
|
"num-rational",
|
||||||
|
"num-traits",
|
||||||
|
"png",
|
||||||
|
"scoped_threadpool",
|
||||||
|
"tiff",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "imageproc"
|
||||||
|
version = "0.22.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7923654f3ce7cb6849d5dc9e544aaeab49c508a90b56c721b046e7234c74ab53"
|
||||||
|
dependencies = [
|
||||||
|
"conv",
|
||||||
|
"image",
|
||||||
|
"itertools",
|
||||||
|
"num 0.3.1",
|
||||||
|
"rand",
|
||||||
|
"rand_distr",
|
||||||
|
"rayon",
|
||||||
|
"rulinalg",
|
||||||
|
"rusttype",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "1.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"hashbrown",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itoa"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jpeg-decoder"
|
||||||
|
version = "0.1.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2"
|
||||||
|
dependencies = [
|
||||||
|
"rayon",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "js-sys"
|
||||||
|
version = "0.3.56"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04"
|
||||||
|
dependencies = [
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.118"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "06e509672465a0504304aa87f9f176f2b2b716ed8fb105ebe5c02dc6dce96a94"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "matrixmultiply"
|
||||||
|
version = "0.1.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dcad67dcec2d58ff56f6292582377e6921afdf3bfbd533e26fb8900ae575e002"
|
||||||
|
dependencies = [
|
||||||
|
"rawpointer",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memoffset"
|
||||||
|
version = "0.6.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miniz_oxide"
|
||||||
|
version = "0.3.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435"
|
||||||
|
dependencies = [
|
||||||
|
"adler32",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miniz_oxide"
|
||||||
|
version = "0.4.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
|
||||||
|
dependencies = [
|
||||||
|
"adler",
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num"
|
||||||
|
version = "0.1.42"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e"
|
||||||
|
dependencies = [
|
||||||
|
"num-integer",
|
||||||
|
"num-iter",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f"
|
||||||
|
dependencies = [
|
||||||
|
"num-bigint",
|
||||||
|
"num-complex",
|
||||||
|
"num-integer",
|
||||||
|
"num-iter",
|
||||||
|
"num-rational",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-bigint"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-complex"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-integer"
|
||||||
|
version = "0.1.44"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-iter"
|
||||||
|
version = "0.1.42"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-rational"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-bigint",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num_cpus"
|
||||||
|
version = "1.13.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "owned_ttf_parser"
|
||||||
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9f923fb806c46266c02ab4a5b239735c144bdeda724a50ed058e5226f594cde3"
|
||||||
|
dependencies = [
|
||||||
|
"ttf-parser",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "png"
|
||||||
|
version = "0.16.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"crc32fast",
|
||||||
|
"deflate",
|
||||||
|
"miniz_oxide 0.3.7",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ppv-lite86"
|
||||||
|
version = "0.2.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro-error"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro-error-attr",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro-error-attr"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.36"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-xid",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.7.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
"libc",
|
||||||
|
"rand_chacha",
|
||||||
|
"rand_core",
|
||||||
|
"rand_hc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
|
||||||
|
dependencies = [
|
||||||
|
"ppv-lite86",
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_distr"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "96977acbdd3a6576fb1d27391900035bf3863d4a16422973a409b488cf29ffb2"
|
||||||
|
dependencies = [
|
||||||
|
"rand",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_hc"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rawpointer"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ebac11a9d2e11f2af219b8b8d833b76b1ea0e054aa0e8d8e9e4cbde353bdf019"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon"
|
||||||
|
version = "1.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"crossbeam-deque",
|
||||||
|
"either",
|
||||||
|
"rayon-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon-core"
|
||||||
|
version = "1.9.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-channel",
|
||||||
|
"crossbeam-deque",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"lazy_static",
|
||||||
|
"num_cpus",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rulinalg"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "04ada202c9685e1d72a7420c578e92b358dbf807d3dfabb676a3dab9cc3bb12f"
|
||||||
|
dependencies = [
|
||||||
|
"matrixmultiply",
|
||||||
|
"num 0.1.42",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rusttype"
|
||||||
|
version = "0.9.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc7c727aded0be18c5b80c1640eae0ac8e396abf6fa8477d96cb37d18ee5ec59"
|
||||||
|
dependencies = [
|
||||||
|
"ab_glyph_rasterizer",
|
||||||
|
"owned_ttf_parser",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ryu"
|
||||||
|
version = "1.0.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scoped-tls-hkt"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c2e9d7eaddb227e8fbaaa71136ae0e1e913ca159b86c7da82f3e8f0044ad3a63"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scoped_threadpool"
|
||||||
|
version = "0.1.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.136"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.136"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.78"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d23c1ba4cf0efd44be32017709280b32d1cea5c3f1275c3b6d9e8bc54f758085"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"ryu",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "slab"
|
||||||
|
version = "0.4.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.86"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-xid",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "1.0.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "1.0.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tiff"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a53f4706d65497df0c4349241deddf35f84cee19c87ed86ea8ca590f4464437"
|
||||||
|
dependencies = [
|
||||||
|
"jpeg-decoder",
|
||||||
|
"miniz_oxide 0.4.4",
|
||||||
|
"weezl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ttf-parser"
|
||||||
|
version = "0.6.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3e5d7cd7ab3e47dda6e56542f4bbf3824c15234958c6e1bd6aaa347e93499fdc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-xid"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "version_check"
|
||||||
|
version = "0.9.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.9.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen"
|
||||||
|
version = "0.2.79"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"wasm-bindgen-macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-backend"
|
||||||
|
version = "0.2.79"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca"
|
||||||
|
dependencies = [
|
||||||
|
"bumpalo",
|
||||||
|
"lazy_static",
|
||||||
|
"log",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-futures"
|
||||||
|
version = "0.4.29"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2eb6ec270a31b1d3c7e266b999739109abce8b6c87e4b31fcfcd788b65267395"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"web-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro"
|
||||||
|
version = "0.2.79"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"wasm-bindgen-macro-support",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro-support"
|
||||||
|
version = "0.2.79"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"wasm-bindgen-backend",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-shared"
|
||||||
|
version = "0.2.79"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-logger"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "074649a66bb306c8f2068c9016395fa65d8e08d2affcbf95acf3c24c3ab19718"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"web-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "web-sys"
|
||||||
|
version = "0.3.56"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb"
|
||||||
|
dependencies = [
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "weezl"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d8b77fdfd5a253be4ab714e4ffa3c49caf146b4de743e97510c0656cf90f1e8e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "yew"
|
||||||
|
version = "0.19.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2a1ccb53e57d3f7d847338cf5758befa811cabe207df07f543c06f502f9998cd"
|
||||||
|
dependencies = [
|
||||||
|
"console_error_panic_hook",
|
||||||
|
"gloo",
|
||||||
|
"gloo-utils",
|
||||||
|
"indexmap",
|
||||||
|
"js-sys",
|
||||||
|
"scoped-tls-hkt",
|
||||||
|
"slab",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"wasm-bindgen-futures",
|
||||||
|
"web-sys",
|
||||||
|
"yew-macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "yew-app"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"gloo-utils",
|
||||||
|
"image",
|
||||||
|
"imageproc",
|
||||||
|
"log",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"wasm-logger",
|
||||||
|
"web-sys",
|
||||||
|
"yew",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "yew-macro"
|
||||||
|
version = "0.19.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5fab79082b556d768d6e21811869c761893f0450e1d550a67892b9bce303b7bb"
|
||||||
|
dependencies = [
|
||||||
|
"boolinator",
|
||||||
|
"lazy_static",
|
||||||
|
"proc-macro-error",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
30
Cargo.toml
Normal file
30
Cargo.toml
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
[package]
|
||||||
|
edition = "2021"
|
||||||
|
name = "yew-app"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
gloo-utils = "0.1.2"
|
||||||
|
log = "0.4.6"
|
||||||
|
wasm-bindgen = "0.2.79"
|
||||||
|
wasm-logger = "0.2.0"
|
||||||
|
web-sys = {version = "0.3.56", features = [
|
||||||
|
"DataTransfer",
|
||||||
|
"DataTransferItemList",
|
||||||
|
"DataTransferItem",
|
||||||
|
"Document",
|
||||||
|
"Element",
|
||||||
|
"Node",
|
||||||
|
"HtmlElement",
|
||||||
|
"HtmlImageElement",
|
||||||
|
"Url",
|
||||||
|
'Blob',
|
||||||
|
'HtmlCanvasElement',
|
||||||
|
'ImageData',
|
||||||
|
'CanvasRenderingContext2d'
|
||||||
|
]}
|
||||||
|
yew = "0.19"
|
||||||
|
image = "0.23.14"
|
||||||
|
imageproc="0.22.0"
|
||||||
3
README.md
Normal file
3
README.md
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
work in progress
|
||||||
|
Goal: image filters, running clientside
|
||||||
|
 => 
|
||||||
BIN
destination.jpg
Normal file
BIN
destination.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 928 KiB |
10
index.html
Normal file
10
index.html
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<link data-trunk rel="copy-dir" href="/static"/>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<title>Spiegel</title>
|
||||||
|
<link rel="stylesheet" href="static/css/style.css">
|
||||||
|
</head>
|
||||||
|
</html>
|
||||||
BIN
source.jpg
Normal file
BIN
source.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 353 KiB |
113
src/app.rs
Normal file
113
src/app.rs
Normal file
|
|
@ -0,0 +1,113 @@
|
||||||
|
use gloo_utils::document;
|
||||||
|
use wasm_bindgen::JsCast;
|
||||||
|
use web_sys::{DragEvent, HtmlImageElement};
|
||||||
|
use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement, ImageData};
|
||||||
|
use web_sys::Url;
|
||||||
|
use yew::{Component, Context, html, Html};
|
||||||
|
|
||||||
|
pub enum Msg {
|
||||||
|
Dropped(DragEvent),
|
||||||
|
Dragged(DragEvent),
|
||||||
|
ImageLoaded,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DropPhoto {}
|
||||||
|
|
||||||
|
impl Component for DropPhoto {
|
||||||
|
type Message = Msg;
|
||||||
|
type Properties = ();
|
||||||
|
|
||||||
|
fn create(_ctx: &Context<Self>) -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
|
||||||
|
match msg {
|
||||||
|
Msg::Dragged(event) => {
|
||||||
|
event.prevent_default();
|
||||||
|
false
|
||||||
|
}
|
||||||
|
Msg::Dropped(event) => {
|
||||||
|
event.prevent_default();
|
||||||
|
let data_transfer = event
|
||||||
|
.data_transfer()
|
||||||
|
.expect("Event should have DataTransfer");
|
||||||
|
let item_list = data_transfer.items();
|
||||||
|
for i in 0..item_list.length() {
|
||||||
|
let item = item_list.get(i).expect("Should find an item");
|
||||||
|
if item.kind() == "file" {
|
||||||
|
let file = item
|
||||||
|
.get_as_file()
|
||||||
|
.expect("Should find a file here")
|
||||||
|
.unwrap();
|
||||||
|
let url = Url::create_object_url_with_blob(&file).expect("Cannot create url");
|
||||||
|
let img = document().get_element_by_id("source-image").expect("cannot get #source-image").dyn_into::<HtmlImageElement>().unwrap();
|
||||||
|
img.set_src(&url);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
Msg::ImageLoaded => {
|
||||||
|
if let Some(canvas) = document().get_element_by_id("source").and_then(|e| e.dyn_into::<HtmlCanvasElement>().ok()) {
|
||||||
|
let ctx: CanvasRenderingContext2d = canvas
|
||||||
|
.get_context("2d")
|
||||||
|
.unwrap()
|
||||||
|
.unwrap()
|
||||||
|
.dyn_into::<CanvasRenderingContext2d>()
|
||||||
|
.unwrap();
|
||||||
|
if let Some(img) = document().get_element_by_id("source-image").and_then(|e| e.dyn_into::<HtmlImageElement>().ok()) {
|
||||||
|
canvas.set_width(img.width());
|
||||||
|
canvas.set_height(img.height());
|
||||||
|
ctx.draw_image_with_html_image_element(&img, 0.0, 0.0).expect("Cannot draw image on canvas");
|
||||||
|
}
|
||||||
|
if let Some(drop_zone) = document().get_element_by_id("drop-zone") {
|
||||||
|
drop_zone.set_attribute("style", "display:none").expect("Cannot update attribute");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn view(&self, ctx: &Context<Self>) -> Html {
|
||||||
|
let link = ctx.link();
|
||||||
|
html! {
|
||||||
|
<>
|
||||||
|
<div id="drop-zone" class="drop-zone"
|
||||||
|
ondragover={link.callback(|e| Msg::Dragged(e))}
|
||||||
|
ondrop={link.callback(|e| Msg::Dropped(e))}>
|
||||||
|
<p>{ "drag your photos here" }</p>
|
||||||
|
</div>
|
||||||
|
<img id="source-image" style="display:none" onload={link.callback(|_| Msg::ImageLoaded)}/>
|
||||||
|
<canvas id="source"></canvas>
|
||||||
|
<canvas id="dest"></canvas>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//make generic for element type
|
||||||
|
// fn with_element<F>(id: &str, action: F)
|
||||||
|
// where
|
||||||
|
// F: Fn(Element),
|
||||||
|
// {
|
||||||
|
// if let Some(element) = document()
|
||||||
|
// .get_element_by_id(id) {
|
||||||
|
// action(element);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
fn create_element<'a, T>(element_type: &str) -> T
|
||||||
|
where
|
||||||
|
T: JsCast,
|
||||||
|
{
|
||||||
|
let element = document().create_element(element_type).unwrap();
|
||||||
|
element
|
||||||
|
.dyn_into::<T>()
|
||||||
|
.expect(&format!("Cannot create element {}", element_type))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn _get_image_data(canvas: &HtmlCanvasElement, ctx: &CanvasRenderingContext2d) -> ImageData {
|
||||||
|
ctx.get_image_data(0.0, 0.0, canvas.width() as f64, canvas.height() as f64).unwrap()
|
||||||
|
}
|
||||||
8
src/main.rs
Normal file
8
src/main.rs
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
mod app;
|
||||||
|
mod transform;
|
||||||
|
mod quantizer;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
wasm_logger::init(wasm_logger::Config::default());
|
||||||
|
yew::start_app::<crate::app::DropPhoto>();
|
||||||
|
}
|
||||||
347
src/quantizer.rs
Normal file
347
src/quantizer.rs
Normal file
|
|
@ -0,0 +1,347 @@
|
||||||
|
use std::{cell::RefCell, rc::Rc};
|
||||||
|
|
||||||
|
use image::{Pixel, Rgb, RgbImage};
|
||||||
|
|
||||||
|
const MAX_LEVEL: usize = 5;
|
||||||
|
|
||||||
|
pub(crate) fn quantize(image: &RgbImage, num_colors: usize) -> RgbImage {
|
||||||
|
let mut quantizer = OctTreeQuantizer::new(num_colors);
|
||||||
|
quantizer.quantize(image)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct OctTreeQuantizer {
|
||||||
|
root: Rc<RefCell<OctTreeNode>>,
|
||||||
|
reduce_colors: usize,
|
||||||
|
maximum_colors: usize,
|
||||||
|
colors: usize,
|
||||||
|
color_list: Vec<Vec<Option<Rc<RefCell<OctTreeNode>>>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OctTreeQuantizer {
|
||||||
|
fn new(num_colors: usize) -> Self {
|
||||||
|
let mut new_quantizer = Self {
|
||||||
|
root: Rc::new(RefCell::new(OctTreeNode::new())),
|
||||||
|
reduce_colors: usize::max(512, num_colors * 2),
|
||||||
|
maximum_colors: num_colors,
|
||||||
|
color_list: vec![],
|
||||||
|
colors: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
for _ in 0..=MAX_LEVEL {
|
||||||
|
new_quantizer.color_list.push(Vec::new());
|
||||||
|
}
|
||||||
|
new_quantizer
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn quantize(&mut self, image: &RgbImage) -> RgbImage {
|
||||||
|
for pixel in image.pixels() {
|
||||||
|
self.insert_color(pixel, Rc::clone(&self.root));
|
||||||
|
|
||||||
|
if self.colors > self.reduce_colors {
|
||||||
|
self.reduce_tree(self.reduce_colors);
|
||||||
|
//reduce sets to None and the code below actually removes nodes from the list
|
||||||
|
for level in &mut self.color_list {
|
||||||
|
level.retain(|c| c.is_some());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let table = self.build_color_table();
|
||||||
|
|
||||||
|
let mut imgbuf = RgbImage::new(image.width(), image.height());
|
||||||
|
for (x, y, pixel) in image.enumerate_pixels() {
|
||||||
|
if let Some(index) = self.get_index_for_color(pixel, &self.root) {
|
||||||
|
let color = &table[index];
|
||||||
|
if let Some(color) = color {
|
||||||
|
imgbuf.put_pixel(x, y, *color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
imgbuf
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_index_for_color<P>(&self, color: &P, node: &Rc<RefCell<OctTreeNode>>) -> Option<usize>
|
||||||
|
where
|
||||||
|
P: Pixel<Subpixel = u8> + 'static,
|
||||||
|
{
|
||||||
|
fn get_index_for_color<P>(
|
||||||
|
quantizer: &OctTreeQuantizer,
|
||||||
|
color: &P,
|
||||||
|
level: usize,
|
||||||
|
node: &Rc<RefCell<OctTreeNode>>,
|
||||||
|
) -> Option<usize>
|
||||||
|
where
|
||||||
|
P: Pixel<Subpixel = u8> + 'static,
|
||||||
|
{
|
||||||
|
if level > MAX_LEVEL {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let node = Rc::clone(node);
|
||||||
|
let index = get_bitmask(color, &level);
|
||||||
|
|
||||||
|
let node_b = node.borrow();
|
||||||
|
let child = &node_b.leaf[index];
|
||||||
|
|
||||||
|
if let Some(child) = child {
|
||||||
|
let child_b = child.borrow();
|
||||||
|
if child_b.is_leaf {
|
||||||
|
return Some(child_b.index);
|
||||||
|
} else {
|
||||||
|
return get_index_for_color(quantizer, color, level + 1, child);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Some(node_b.index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get_index_for_color(&self, color, 0, node)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_color_table(&mut self) -> Vec<Option<Rgb<u8>>> {
|
||||||
|
//nested function that is called recursively
|
||||||
|
fn build_color_table(
|
||||||
|
quantizer: &mut OctTreeQuantizer,
|
||||||
|
node: &Rc<RefCell<OctTreeNode>>,
|
||||||
|
table: &mut Vec<Option<Rgb<u8>>>,
|
||||||
|
index: usize,
|
||||||
|
) -> usize {
|
||||||
|
if quantizer.colors > quantizer.maximum_colors {
|
||||||
|
quantizer.reduce_tree(quantizer.maximum_colors);
|
||||||
|
}
|
||||||
|
if node.borrow().is_leaf {
|
||||||
|
{
|
||||||
|
let node = node.borrow();
|
||||||
|
let count = node.count;
|
||||||
|
table[index] = Some(Rgb::from([
|
||||||
|
(node.total_red / count as u32) as u8,
|
||||||
|
(node.total_green / count as u32) as u8,
|
||||||
|
(node.total_blue / count as u32) as u8,
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
node.borrow_mut().index = index;
|
||||||
|
|
||||||
|
index + 1
|
||||||
|
} else {
|
||||||
|
let mut result = index;
|
||||||
|
for i in 0..8 {
|
||||||
|
// cannot iterate leaf, because that widens the scope of the borrow (of node)
|
||||||
|
let mut node = node.borrow_mut();
|
||||||
|
if let Some(leaf) = &node.leaf[i] {
|
||||||
|
//could be immutable borrow
|
||||||
|
let new_index = build_color_table(quantizer, leaf, table, result);
|
||||||
|
node.index = index; //but also need mutable borrow here
|
||||||
|
result = new_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut table: Vec<Option<Rgb<u8>>> = vec![None; self.colors];
|
||||||
|
let node = Rc::clone(&self.root);
|
||||||
|
build_color_table(self, &node, &mut table, 0);
|
||||||
|
table
|
||||||
|
}
|
||||||
|
|
||||||
|
fn insert_color<P>(&mut self, rgb: &P, node: Rc<RefCell<OctTreeNode>>)
|
||||||
|
where
|
||||||
|
P: Pixel<Subpixel = u8> + 'static,
|
||||||
|
{
|
||||||
|
//nested function that is called recursively
|
||||||
|
fn insert_color<P>(
|
||||||
|
quantizer: &mut OctTreeQuantizer,
|
||||||
|
color: &P,
|
||||||
|
level: usize,
|
||||||
|
node: Rc<RefCell<OctTreeNode>>,
|
||||||
|
) where
|
||||||
|
P: Pixel<Subpixel = u8> + 'static,
|
||||||
|
{
|
||||||
|
if level > MAX_LEVEL {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let index = get_bitmask(color, &level);
|
||||||
|
|
||||||
|
if node.borrow().leaf[index].is_none() {
|
||||||
|
let mut child = OctTreeNode::new();
|
||||||
|
child.parent = Some(Rc::clone(&node));
|
||||||
|
child.p_index = quantizer.color_list[level].len();
|
||||||
|
|
||||||
|
if level == MAX_LEVEL {
|
||||||
|
child.is_leaf = true;
|
||||||
|
child.count = 1;
|
||||||
|
child.total_red = color.channels()[0] as u32;
|
||||||
|
child.total_green = color.channels()[1] as u32;
|
||||||
|
child.total_blue = color.channels()[2] as u32;
|
||||||
|
child.level = level;
|
||||||
|
quantizer.colors += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let child = Rc::new(RefCell::new(child));
|
||||||
|
quantizer.color_list[level].push(Some(Rc::clone(&child)));
|
||||||
|
let clone = Rc::clone(&child);
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut mutnode = node.borrow_mut();
|
||||||
|
mutnode.children += 1;
|
||||||
|
mutnode.is_leaf = false;
|
||||||
|
mutnode.leaf[index] = Some(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
if level < MAX_LEVEL {
|
||||||
|
insert_color(quantizer, color, level + 1, clone);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if node
|
||||||
|
.borrow()
|
||||||
|
.leaf
|
||||||
|
.get(index)
|
||||||
|
.unwrap()
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.borrow()
|
||||||
|
.is_leaf
|
||||||
|
{
|
||||||
|
let mut node = node.borrow_mut();
|
||||||
|
let mut child = node
|
||||||
|
.leaf
|
||||||
|
.get_mut(index)
|
||||||
|
.unwrap()
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.borrow_mut();
|
||||||
|
child.count += 1;
|
||||||
|
child.total_red += color.channels()[0] as u32;
|
||||||
|
child.total_green += color.channels()[1] as u32;
|
||||||
|
child.total_blue += color.channels()[2] as u32;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
insert_color(
|
||||||
|
quantizer,
|
||||||
|
color,
|
||||||
|
level + 1,
|
||||||
|
Rc::clone(&(node.borrow().leaf[index]).as_ref().unwrap()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
insert_color(self, rgb, 0, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reduce_tree(&mut self, num_colors: usize) {
|
||||||
|
// Nested function that is called recursively
|
||||||
|
fn reduce_tree(quantizer: &mut OctTreeQuantizer, num_colors: usize, level: isize) {
|
||||||
|
if level < 0 {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
let mut removals = Vec::new();
|
||||||
|
let list = &quantizer.color_list[level as usize];
|
||||||
|
for node in list {
|
||||||
|
if let Some(node) = node {
|
||||||
|
if node.borrow().children > 0 {
|
||||||
|
for i in 0..8 {
|
||||||
|
let mut color: Option<(usize, u32, u32, u32, usize)> = None;
|
||||||
|
|
||||||
|
if let Some(child) = node.borrow().leaf.get(i) {
|
||||||
|
if let Some(child) = child {
|
||||||
|
let child = child.borrow();
|
||||||
|
color = Some((
|
||||||
|
child.count,
|
||||||
|
child.total_red,
|
||||||
|
child.total_green,
|
||||||
|
child.total_blue,
|
||||||
|
child.p_index,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// need to mutate node, which conflicts with previous borrow to retrieve the child
|
||||||
|
if let Some(color) = color {
|
||||||
|
let mut node = node.borrow_mut();
|
||||||
|
node.count += color.0;
|
||||||
|
node.total_red += color.1;
|
||||||
|
node.total_green += color.2;
|
||||||
|
node.total_blue += color.3;
|
||||||
|
node.leaf[i] = None;
|
||||||
|
node.children -= 1;
|
||||||
|
quantizer.colors -= 1;
|
||||||
|
|
||||||
|
removals.push(color.4); //save for further processing outside loop (and borrow of colorlist)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
node.borrow_mut().is_leaf = true;
|
||||||
|
quantizer.colors += 1;
|
||||||
|
if quantizer.colors <= num_colors {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let color_list = &mut quantizer.color_list[(level as usize + 1)];
|
||||||
|
for index in removals {
|
||||||
|
color_list[index] = None; //set to None here, Option removed later
|
||||||
|
}
|
||||||
|
|
||||||
|
reduce_tree(quantizer, num_colors, level - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// call to nested function
|
||||||
|
reduce_tree(self, num_colors, (MAX_LEVEL - 1) as isize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct OctTreeNode {
|
||||||
|
children: usize,
|
||||||
|
level: usize,
|
||||||
|
parent: Option<Rc<RefCell<OctTreeNode>>>,
|
||||||
|
leaf: Vec<Option<Rc<RefCell<OctTreeNode>>>>,
|
||||||
|
is_leaf: bool,
|
||||||
|
count: usize,
|
||||||
|
total_red: u32,
|
||||||
|
total_green: u32,
|
||||||
|
total_blue: u32,
|
||||||
|
index: usize,
|
||||||
|
p_index: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OctTreeNode {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
children: 0,
|
||||||
|
level: 0,
|
||||||
|
parent: None,
|
||||||
|
leaf: vec![None; 8],
|
||||||
|
is_leaf: false,
|
||||||
|
count: 0,
|
||||||
|
total_red: 0,
|
||||||
|
total_green: 0,
|
||||||
|
total_blue: 0,
|
||||||
|
index: 0,
|
||||||
|
p_index: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_bitmask<P>(color: &P, level: &usize) -> usize
|
||||||
|
where
|
||||||
|
P: Pixel<Subpixel = u8> + 'static,
|
||||||
|
{
|
||||||
|
let bit = 0x80 >> level;
|
||||||
|
|
||||||
|
let mut index = 0;
|
||||||
|
if (color.channels()[0] & bit) != 0 {
|
||||||
|
index += 4;
|
||||||
|
}
|
||||||
|
if (color.channels()[1] & bit) != 0 {
|
||||||
|
index += 2;
|
||||||
|
}
|
||||||
|
if (color.channels()[2] & bit) != 0 {
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
index
|
||||||
|
}
|
||||||
212
src/transform.rs
Normal file
212
src/transform.rs
Normal file
|
|
@ -0,0 +1,212 @@
|
||||||
|
use std::{error::Error, fs, result::Result};
|
||||||
|
|
||||||
|
use image::{GenericImageView, ImageBuffer, Pixel, Rgb, RgbImage};
|
||||||
|
use imageproc::point::Point;
|
||||||
|
use crate::quantizer;
|
||||||
|
|
||||||
|
pub fn run(image_filename: &String) -> Result<(), Box<dyn Error>> {
|
||||||
|
println!("reading image samples");
|
||||||
|
let color_samples = read_color_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(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply_samples_to_image(mut src: RgbImage, color_samples: &Vec<ColorSample>) -> 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) {
|
||||||
|
fill(&mut src, sample, &mut imgbuf, pixel, x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
imgbuf
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fill(
|
||||||
|
src: &mut ImageBuffer<Rgb<u8>, Vec<u8>>,
|
||||||
|
sample: &ColorSample,
|
||||||
|
dest: &mut ImageBuffer<Rgb<u8>, Vec<u8>>,
|
||||||
|
color: &Rgb<u8>,
|
||||||
|
px: u32,
|
||||||
|
py: u32,
|
||||||
|
) {
|
||||||
|
if color.channels() == [0, 0, 0] {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let height = sample.image.height();
|
||||||
|
let width = sample.image.width();
|
||||||
|
let mut points = List::new();
|
||||||
|
if is_same(src.get_pixel(px, py), &color) {
|
||||||
|
points.push(Point { x: px, y: py });
|
||||||
|
}
|
||||||
|
|
||||||
|
while !points.is_empty() {
|
||||||
|
if let Some(point) = points.pop() {
|
||||||
|
let orig_pixel = src.get_pixel(point.x, point.y);
|
||||||
|
let x = point.x;
|
||||||
|
let y = point.y;
|
||||||
|
if src.get_pixel(x, y).channels() != [0, 0, 0] {
|
||||||
|
if is_same(orig_pixel, &color) {
|
||||||
|
let mut xx = x;
|
||||||
|
let mut yy = y;
|
||||||
|
while xx >= width {
|
||||||
|
xx -= width;
|
||||||
|
}
|
||||||
|
while yy >= height {
|
||||||
|
yy -= height;
|
||||||
|
}
|
||||||
|
dest.put_pixel(x, y, *sample.image.get_pixel(xx, yy));
|
||||||
|
src.put_pixel(x, y, Rgb([0, 0, 0]));
|
||||||
|
if x > 1 {
|
||||||
|
points.push(Point::new(x - 1, y));
|
||||||
|
}
|
||||||
|
if y > 1 {
|
||||||
|
points.push(Point::new(x, y - 1));
|
||||||
|
}
|
||||||
|
if x < src.width() - 1 {
|
||||||
|
points.push(Point::new(x + 1, y));
|
||||||
|
}
|
||||||
|
if y < src.height() - 1 {
|
||||||
|
points.push(Point::new(x, y + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println!("break");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_same(p1: &Rgb<u8>, p2: &Rgb<u8>) -> bool {
|
||||||
|
let p1 = p1.channels();
|
||||||
|
let p2 = p2.channels();
|
||||||
|
i16::abs(p1[0] as i16 - p2[0] as i16) < 4
|
||||||
|
&& i16::abs(p1[1] as i16 - p2[1] as i16) < 4
|
||||||
|
&& i16::abs(p1[2] as i16 - p2[2] as i16) < 4
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_closest<'a>(
|
||||||
|
color_samples: &'a Vec<ColorSample>,
|
||||||
|
pixel: &Rgb<u8>,
|
||||||
|
) -> Option<&'a 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);
|
||||||
|
if diff < min_diff {
|
||||||
|
closest = Some(sample);
|
||||||
|
min_diff = diff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closest
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_distance(r: u8, g: u8, b: u8, c2: &Rgb<u8>) -> f32 {
|
||||||
|
let red_dif = r as f32 - c2.channels()[0] as f32;
|
||||||
|
let green_dif = g as f32 - c2.channels()[1] as f32;
|
||||||
|
let blue_dif = b as f32 - c2.channels()[2] as f32;
|
||||||
|
return f32::sqrt(red_dif * red_dif + green_dif * green_dif + blue_dif * blue_dif);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_color_samples() -> Result<Vec<ColorSample>, Box<dyn Error>> {
|
||||||
|
let paths = fs::read_dir("samples")?;
|
||||||
|
let mut color_samples: Vec<ColorSample> = 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ColorSample {
|
||||||
|
r: u8,
|
||||||
|
g: u8,
|
||||||
|
b: u8,
|
||||||
|
image: RgbImage,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct List {
|
||||||
|
head: Option<Box<Node>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl List {
|
||||||
|
fn new() -> Self {
|
||||||
|
Self { head: None }
|
||||||
|
}
|
||||||
|
fn push(&mut self, point: Point<u32>) {
|
||||||
|
let new_node = Box::new(Node {
|
||||||
|
value: point,
|
||||||
|
next: self.head.take(),
|
||||||
|
});
|
||||||
|
|
||||||
|
self.head = Some(new_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pop(&mut self) -> Option<Point<u32>> {
|
||||||
|
self.head.take().map(|node| {
|
||||||
|
self.head = node.next;
|
||||||
|
node.value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_empty(&self) -> bool {
|
||||||
|
self.head.is_none()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct Node {
|
||||||
|
value: Point<u32>,
|
||||||
|
next: Option<Box<Node>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test() {
|
||||||
|
let mut list = List::new();
|
||||||
|
|
||||||
|
list.push(Point::new(1, 1));
|
||||||
|
list.push(Point::new(2, 2));
|
||||||
|
assert_eq!(2, list.pop().unwrap().x);
|
||||||
|
assert_eq!(1, list.pop().unwrap().x);
|
||||||
|
}
|
||||||
|
}
|
||||||
27
static/css/style.css
Normal file
27
static/css/style.css
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
html {
|
||||||
|
font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;
|
||||||
|
color: rgb(20, 20, 104);
|
||||||
|
}
|
||||||
|
|
||||||
|
.drop-zone {
|
||||||
|
border: 4px dashed rgb(17, 122, 184);
|
||||||
|
width: 200px;
|
||||||
|
height: 100px;
|
||||||
|
background-color: rgb(202, 202, 238);
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
display: table;
|
||||||
|
margin: 0 auto;
|
||||||
|
transform: translateY(50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.body > img {
|
||||||
|
width: 25%;
|
||||||
|
border: rgb(17, 122, 184) solid 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.photo > canvas {
|
||||||
|
width: 25%;
|
||||||
|
border: rgb(17, 122, 184) solid 3px;
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue