adds drone pipeline #1
Generated
+685
-26
@@ -8,12 +8,91 @@ version = "1.0.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "1.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ansi_colours"
|
||||||
|
version = "1.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6a1558bd2075d341b9ca698ec8eb6fcc55a746b1fc4255585aad5b141d918a80"
|
||||||
|
dependencies = [
|
||||||
|
"rgb",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstream"
|
||||||
|
version = "0.6.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"anstyle-parse",
|
||||||
|
"anstyle-query",
|
||||||
|
"anstyle-wincon",
|
||||||
|
"colorchoice",
|
||||||
|
"is_terminal_polyfill",
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle"
|
||||||
|
version = "1.0.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-parse"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4"
|
||||||
|
dependencies = [
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-query"
|
||||||
|
version = "1.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-wincon"
|
||||||
|
version = "3.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.21.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.22.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bit_field"
|
name = "bit_field"
|
||||||
version = "0.10.1"
|
version = "0.10.1"
|
||||||
@@ -26,6 +105,21 @@ version = "1.3.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bktree"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0bb1e744816f6a3b9e962186091867f3e5959d4dac995777ec254631cb00b21c"
|
||||||
|
dependencies = [
|
||||||
|
"num",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.11.1"
|
version = "3.11.1"
|
||||||
@@ -50,12 +144,70 @@ version = "1.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap"
|
||||||
|
version = "4.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0"
|
||||||
|
dependencies = [
|
||||||
|
"clap_builder",
|
||||||
|
"clap_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_builder"
|
||||||
|
version = "4.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4"
|
||||||
|
dependencies = [
|
||||||
|
"anstream",
|
||||||
|
"anstyle",
|
||||||
|
"clap_lex",
|
||||||
|
"strsim",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_derive"
|
||||||
|
version = "4.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.64",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_lex"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "color_quant"
|
name = "color_quant"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "colorchoice"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "console"
|
||||||
|
version = "0.15.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb"
|
||||||
|
dependencies = [
|
||||||
|
"encode_unicode",
|
||||||
|
"lazy_static",
|
||||||
|
"libc",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crc32fast"
|
name = "crc32fast"
|
||||||
version = "1.3.2"
|
version = "1.3.2"
|
||||||
@@ -108,6 +260,31 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossterm"
|
||||||
|
version = "0.27.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.5.0",
|
||||||
|
"crossterm_winapi",
|
||||||
|
"libc",
|
||||||
|
"mio",
|
||||||
|
"parking_lot",
|
||||||
|
"signal-hook",
|
||||||
|
"signal-hook-mio",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossterm_winapi"
|
||||||
|
version = "0.9.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crunchy"
|
name = "crunchy"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
@@ -120,6 +297,45 @@ version = "1.8.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
|
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "encode_unicode"
|
||||||
|
version = "0.3.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "env_filter"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"regex",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "env_logger"
|
||||||
|
version = "0.11.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9"
|
||||||
|
dependencies = [
|
||||||
|
"anstream",
|
||||||
|
"anstyle",
|
||||||
|
"env_filter",
|
||||||
|
"humantime",
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "errno"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "exr"
|
name = "exr"
|
||||||
version = "1.5.2"
|
version = "1.5.2"
|
||||||
@@ -135,6 +351,12 @@ dependencies = [
|
|||||||
"threadpool",
|
"threadpool",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fastrand"
|
||||||
|
version = "2.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flate2"
|
name = "flate2"
|
||||||
version = "1.0.24"
|
version = "1.0.24"
|
||||||
@@ -202,6 +424,12 @@ dependencies = [
|
|||||||
"crunchy",
|
"crunchy",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heck"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.1.19"
|
version = "0.1.19"
|
||||||
@@ -211,6 +439,12 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "humantime"
|
||||||
|
version = "2.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "image"
|
name = "image"
|
||||||
version = "0.24.4"
|
version = "0.24.4"
|
||||||
@@ -231,14 +465,26 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "image-similarity"
|
name = "image_similarity"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"base64 0.22.1",
|
||||||
|
"bktree",
|
||||||
|
"clap",
|
||||||
|
"env_logger",
|
||||||
"image",
|
"image",
|
||||||
|
"log",
|
||||||
"rmp-serde",
|
"rmp-serde",
|
||||||
"serde",
|
"serde",
|
||||||
|
"viuer",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "is_terminal_polyfill"
|
||||||
|
version = "1.70.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jpeg-decoder"
|
name = "jpeg-decoder"
|
||||||
version = "0.2.6"
|
version = "0.2.6"
|
||||||
@@ -257,6 +503,12 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lebe"
|
name = "lebe"
|
||||||
version = "0.5.2"
|
version = "0.5.2"
|
||||||
@@ -265,9 +517,15 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.137"
|
version = "0.2.154"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
|
checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linux-raw-sys"
|
||||||
|
version = "0.4.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
@@ -281,12 +539,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.17"
|
version = "0.4.21"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
|
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
[[package]]
|
||||||
]
|
name = "memchr"
|
||||||
|
version = "2.7.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memoffset"
|
name = "memoffset"
|
||||||
@@ -315,6 +576,18 @@ dependencies = [
|
|||||||
"adler",
|
"adler",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mio"
|
||||||
|
version = "0.8.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"log",
|
||||||
|
"wasi",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nanorand"
|
name = "nanorand"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
@@ -325,20 +598,52 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-integer"
|
name = "num"
|
||||||
version = "0.1.45"
|
version = "0.4.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
|
checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"num-bigint",
|
||||||
|
"num-complex",
|
||||||
|
"num-integer",
|
||||||
|
"num-iter",
|
||||||
|
"num-rational",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-rational"
|
name = "num-bigint"
|
||||||
version = "0.4.1"
|
version = "0.4.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
|
checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7"
|
||||||
|
dependencies = [
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-complex"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-integer"
|
||||||
|
version = "0.1.46"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-iter"
|
||||||
|
version = "0.1.45"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"num-integer",
|
"num-integer",
|
||||||
@@ -346,10 +651,21 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-rational"
|
||||||
version = "0.2.15"
|
version = "0.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
|
checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
|
||||||
|
dependencies = [
|
||||||
|
"num-bigint",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
@@ -370,6 +686,29 @@ version = "1.16.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
|
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot"
|
||||||
|
version = "0.12.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
"parking_lot_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot_core"
|
||||||
|
version = "0.9.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall",
|
||||||
|
"smallvec",
|
||||||
|
"windows-targets 0.52.5",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "paste"
|
name = "paste"
|
||||||
version = "1.0.9"
|
version = "1.0.9"
|
||||||
@@ -393,7 +732,7 @@ checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 1.0.103",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -402,7 +741,7 @@ version = "0.17.7"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5d708eaf860a19b19ce538740d2b4bdeeb8337fa53f7738455e706623ad5c638"
|
checksum = "5d708eaf860a19b19ce538740d2b4bdeeb8337fa53f7738455e706623ad5c638"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 1.3.2",
|
||||||
"crc32fast",
|
"crc32fast",
|
||||||
"flate2",
|
"flate2",
|
||||||
"miniz_oxide 0.6.2",
|
"miniz_oxide 0.6.2",
|
||||||
@@ -410,18 +749,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.47"
|
version = "1.0.82"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
|
checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.21"
|
version = "1.0.36"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
|
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
@@ -450,6 +789,53 @@ dependencies = [
|
|||||||
"num_cpus",
|
"num_cpus",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.5.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.10.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-automata",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-automata"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rgb"
|
||||||
|
version = "0.8.37"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "05aaa8004b64fd573fc9d002f4e632d51ad4f026c2b5ba95fcb6c2f32c2c47d8"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rmp"
|
name = "rmp"
|
||||||
version = "0.8.11"
|
version = "0.8.11"
|
||||||
@@ -472,6 +858,19 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustix"
|
||||||
|
version = "0.38.34"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.5.0",
|
||||||
|
"errno",
|
||||||
|
"libc",
|
||||||
|
"linux-raw-sys",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scoped_threadpool"
|
name = "scoped_threadpool"
|
||||||
version = "0.1.9"
|
version = "0.1.9"
|
||||||
@@ -490,6 +889,36 @@ version = "1.0.147"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"
|
checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "signal-hook"
|
||||||
|
version = "0.3.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"signal-hook-registry",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "signal-hook-mio"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"mio",
|
||||||
|
"signal-hook",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "signal-hook-registry"
|
||||||
|
version = "1.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "1.10.0"
|
version = "1.10.0"
|
||||||
@@ -505,6 +934,12 @@ dependencies = [
|
|||||||
"lock_api",
|
"lock_api",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.103"
|
version = "1.0.103"
|
||||||
@@ -516,6 +951,38 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.64"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7ad3dee41f36859875573074334c200d1add8e4a87bb37113ebd31d926b7b11f"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tempfile"
|
||||||
|
version = "3.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"fastrand",
|
||||||
|
"rustix",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "termcolor"
|
||||||
|
version = "1.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "threadpool"
|
name = "threadpool"
|
||||||
version = "1.8.1"
|
version = "1.8.1"
|
||||||
@@ -542,6 +1009,28 @@ version = "1.0.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
|
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utf8parse"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "viuer"
|
||||||
|
version = "0.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ec2ede5c8814363f92f862892dfe71a266f6816b649ca435aed1ff5e2cf3454e"
|
||||||
|
dependencies = [
|
||||||
|
"ansi_colours",
|
||||||
|
"base64 0.21.7",
|
||||||
|
"console",
|
||||||
|
"crossterm",
|
||||||
|
"image",
|
||||||
|
"lazy_static",
|
||||||
|
"tempfile",
|
||||||
|
"termcolor",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.11.0+wasi-snapshot-preview1"
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
@@ -569,7 +1058,7 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 1.0.103",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -591,7 +1080,7 @@ checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn 1.0.103",
|
||||||
"wasm-bindgen-backend",
|
"wasm-bindgen-backend",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
@@ -607,3 +1096,173 @@ name = "weezl"
|
|||||||
version = "0.1.7"
|
version = "0.1.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb"
|
checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-i686-pc-windows-gnu",
|
||||||
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-util"
|
||||||
|
version = "0.1.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.48.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.48.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.52.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm 0.48.5",
|
||||||
|
"windows_aarch64_msvc 0.48.5",
|
||||||
|
"windows_i686_gnu 0.48.5",
|
||||||
|
"windows_i686_msvc 0.48.5",
|
||||||
|
"windows_x86_64_gnu 0.48.5",
|
||||||
|
"windows_x86_64_gnullvm 0.48.5",
|
||||||
|
"windows_x86_64_msvc 0.48.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm 0.52.5",
|
||||||
|
"windows_aarch64_msvc 0.52.5",
|
||||||
|
"windows_i686_gnu 0.52.5",
|
||||||
|
"windows_i686_gnullvm",
|
||||||
|
"windows_i686_msvc 0.52.5",
|
||||||
|
"windows_x86_64_gnu 0.52.5",
|
||||||
|
"windows_x86_64_gnullvm 0.52.5",
|
||||||
|
"windows_x86_64_msvc 0.52.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnullvm"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.48.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.52.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
|
||||||
|
|||||||
+7
-1
@@ -1,5 +1,5 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "image-similarity"
|
name = "image_similarity"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
@@ -9,3 +9,9 @@ edition = "2021"
|
|||||||
image = "0.24.4"
|
image = "0.24.4"
|
||||||
serde = "1.0.147"
|
serde = "1.0.147"
|
||||||
rmp-serde = "1.1.1"
|
rmp-serde = "1.1.1"
|
||||||
|
base64 = "0.22.1"
|
||||||
|
log = "0.4.21"
|
||||||
|
env_logger = "0.11.3"
|
||||||
|
bktree = "1.0.1"
|
||||||
|
viuer = "0.7.1"
|
||||||
|
clap = { version = "4.5.4", features = ["derive"] }
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
use std::env;
|
||||||
|
use std::f64::consts::{PI, SQRT_2};
|
||||||
|
use image::{save_buffer, GenericImageView, GrayImage};
|
||||||
|
|
||||||
|
fn dct(img: &image::DynamicImage) -> GrayImage {
|
||||||
|
//let mut dct_values: = [0.0; img.width() * img.height()];
|
||||||
|
let w = img.width();
|
||||||
|
let h = img.height();
|
||||||
|
let mut dct_img = GrayImage::new(w, h);
|
||||||
|
|
||||||
|
//let mut dct_values: Vec<f64> = Vec::new();
|
||||||
|
for u in 0..w {
|
||||||
|
for v in 0..h {
|
||||||
|
let w = w as f64;
|
||||||
|
let h = h as f64;
|
||||||
|
//let k = (v*img.width())+u;
|
||||||
|
let mut alpha = 0.25;
|
||||||
|
if u == 0 {
|
||||||
|
alpha = alpha / SQRT_2
|
||||||
|
}
|
||||||
|
if v == 0 {
|
||||||
|
alpha = alpha / SQRT_2
|
||||||
|
}
|
||||||
|
let v: f64 = v as f64;
|
||||||
|
let u: f64 = u as f64;
|
||||||
|
let mut sum: f64 = 0.0;
|
||||||
|
for (x, y, pix) in img.pixels() {
|
||||||
|
let x: f64 = x as f64;
|
||||||
|
let y: f64 = y as f64;
|
||||||
|
let pixel = pix[0] as f64;
|
||||||
|
// sum +=
|
||||||
|
// pixel *
|
||||||
|
// (x*u*PI/16.0).cos() *
|
||||||
|
// (y*v*PI/16.0).cos()
|
||||||
|
sum +=
|
||||||
|
pixel *
|
||||||
|
(
|
||||||
|
PI/w*
|
||||||
|
(x+0.5)*u
|
||||||
|
).cos()
|
||||||
|
*
|
||||||
|
(
|
||||||
|
PI/h*
|
||||||
|
(y+0.5)*v
|
||||||
|
).cos()
|
||||||
|
}
|
||||||
|
//dct_values[k] = alpha * sum;
|
||||||
|
//dct_values.push(alpha * sum);
|
||||||
|
print!("{sum}\t");
|
||||||
|
//sum = (sum + 200000.0)/784.0;
|
||||||
|
print!("{}\n", sum * alpha);
|
||||||
|
let pixel = (sum).abs() as u8;
|
||||||
|
println!("{u}, {v}:\t {sum}");
|
||||||
|
dct_img.put_pixel(u as u32, v as u32, image::Luma([pixel]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dct_img
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let args: Vec<String> = env::args().collect();
|
||||||
|
let path = args[1].clone();
|
||||||
|
let img = image::open(&path).unwrap();
|
||||||
|
let dct = dct(&img);
|
||||||
|
dct.save("dct.png").unwrap();
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
//use image_similarity::descriptors::dct::DCT;
|
||||||
|
use image_similarity::descriptors::{DCT, Descriptor};
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine as _};
|
||||||
|
use log::debug;
|
||||||
|
use clap::Parser;
|
||||||
|
|
||||||
|
#[derive(Parser)]
|
||||||
|
#[command(version, about, long_about = None)]
|
||||||
|
struct Cfg {
|
||||||
|
path: PathBuf
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
env_logger::init();
|
||||||
|
let cfg = Cfg::parse();
|
||||||
|
|
||||||
|
let desc = DCT::new().with_quality(50);
|
||||||
|
|
||||||
|
let img = image::open(cfg.path)
|
||||||
|
.expect("Unable to open file");
|
||||||
|
let phash: u64 = desc.describe(&img);
|
||||||
|
debug!("Phash integer:\n{phash}");
|
||||||
|
debug!("Phash binary:\n{phash:064b}");
|
||||||
|
let output = URL_SAFE_NO_PAD.encode(phash.to_be_bytes());
|
||||||
|
println!("{output}")
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
//use image_similarity::descriptors::dct::DCT;
|
||||||
|
use image_similarity::descriptors::{DCT, Descriptor};
|
||||||
|
use image_similarity::store::DescriptorStore;
|
||||||
|
use std::env;
|
||||||
|
use log::{info, debug, error};
|
||||||
|
|
||||||
|
struct Cfg {
|
||||||
|
path: String
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Cfg{
|
||||||
|
fn load(args: &[String]) -> Result<Cfg, &'static str> {
|
||||||
|
if args.len() < 2 {
|
||||||
|
return Err("Filename argument required");
|
||||||
|
}
|
||||||
|
let path = args[1].clone();
|
||||||
|
Ok(Cfg { path })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
env_logger::init();
|
||||||
|
|
||||||
|
//Init all descriptors:
|
||||||
|
let desc = DCT::new().with_quality(50);
|
||||||
|
|
||||||
|
let args: Vec<String> = env::args().collect();
|
||||||
|
|
||||||
|
let cfg = Cfg::load(&args)
|
||||||
|
.expect("Error loading config");
|
||||||
|
|
||||||
|
let img = image::open(cfg.path)
|
||||||
|
.expect("Unable to open file");
|
||||||
|
println!("Iamge");
|
||||||
|
let conf = viuer::Config {
|
||||||
|
width: Some(16),
|
||||||
|
height: Some(8),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
viuer::print(&img, &conf).expect("Image printing failed.");
|
||||||
|
println!("Iamge");
|
||||||
|
let store =
|
||||||
|
DescriptorStore::new()
|
||||||
|
.with_file("store.messagepack");
|
||||||
|
//info!("{}", store);
|
||||||
|
let phash: u64 = desc.describe(&img);
|
||||||
|
info!("Phash integer:\n{phash}");
|
||||||
|
info!("Phash binary:\n{phash:064b}");
|
||||||
|
store.knn(phash, 10);
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
use image_similarity::descriptors::{Descriptor, DCT};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::fs;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
env_logger::init();
|
||||||
|
|
||||||
|
let desc = DCT::new();
|
||||||
|
|
||||||
|
//Initialize hashmap, empty or from cached file:
|
||||||
|
let count = fs::read_dir("img").unwrap().count();
|
||||||
|
let map_file = fs::read("map.messagepack");
|
||||||
|
let mut map: HashMap<String, u64> = match map_file {
|
||||||
|
Ok(f) => rmp_serde::from_slice(&f).unwrap(),
|
||||||
|
Err(_e) => HashMap::with_capacity(count),
|
||||||
|
};
|
||||||
|
|
||||||
|
//Calculate phashes for all images
|
||||||
|
for node in fs::read_dir("img").unwrap() {
|
||||||
|
let file = node.expect("Error walking directory");
|
||||||
|
let name = file.file_name().into_string().expect("Issue with filename");
|
||||||
|
if !map.contains_key(&name) {
|
||||||
|
let img = image::open(file.path()).expect("Unable to open file");
|
||||||
|
let phash = desc.describe(&img);
|
||||||
|
map.insert(name, phash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (key, val) in map.iter() {
|
||||||
|
println!("{key: >15}: {val}\t {val:b}");
|
||||||
|
}
|
||||||
|
|
||||||
|
//Serialize hashmap with MessagePack:
|
||||||
|
let _serialized: Vec<u8> = rmp_serde::to_vec(&map).unwrap();
|
||||||
|
//fs::write("map.messagepack",&serialized).unwrap();
|
||||||
|
}
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
use image::GenericImageView;
|
|
||||||
|
|
||||||
pub trait Descriptor {
|
|
||||||
fn info(&self) -> String {
|
|
||||||
"Descriptor".to_string()
|
|
||||||
}
|
|
||||||
fn describe(&self, img: image::DynamicImage) -> u64;
|
|
||||||
fn distance(&self, a: u64, b: u64) -> u64 {
|
|
||||||
(a^b).count_ones().into()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Median;
|
|
||||||
|
|
||||||
impl Descriptor for Median {
|
|
||||||
fn describe(&self, img: image::DynamicImage) -> u64 {
|
|
||||||
let mut median: u64 = 0; //Average for now while i figure out sorting in rust
|
|
||||||
let img = img.grayscale().thumbnail_exact(8, 8);
|
|
||||||
for (_, _, pix) in img.pixels() {
|
|
||||||
median += pix[0] as u64;
|
|
||||||
}
|
|
||||||
let median: u8 = (median/64) as u8;
|
|
||||||
let mut mask: u64 = 0;
|
|
||||||
img.save("debug.png").unwrap();
|
|
||||||
for (_, _, pix) in img.pixels() {
|
|
||||||
if pix[0] > median {
|
|
||||||
mask += 1;
|
|
||||||
}
|
|
||||||
mask = mask << 1;
|
|
||||||
}
|
|
||||||
mask
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -0,0 +1,202 @@
|
|||||||
|
use image::{save_buffer, GenericImageView};
|
||||||
|
use std::f64::consts::{PI, SQRT_2};
|
||||||
|
use crate::descriptors::{Descriptor, DCT, print_matrix};
|
||||||
|
use log::{debug, log_enabled, Level};
|
||||||
|
|
||||||
|
|
||||||
|
impl DCT {
|
||||||
|
/// Returns a new DCT instance with a base quality DCT matrix.
|
||||||
|
pub fn new() -> DCT {
|
||||||
|
let quantization_matrix: [u8; 64] = [
|
||||||
|
16, 11, 10, 16, 24, 40, 51, 61,
|
||||||
|
12, 12, 14, 19, 26, 58, 60, 55,
|
||||||
|
14, 13, 16, 24, 40, 57, 69, 56,
|
||||||
|
14, 17, 22, 29, 51, 87, 80, 62,
|
||||||
|
18, 22, 37, 56, 6, 10, 103, 77,
|
||||||
|
24, 35, 55, 64, 8, 10, 113, 92,
|
||||||
|
49, 64, 78, 8, 10, 12, 12, 101,
|
||||||
|
72, 92, 95, 9, 11, 10, 103, 99,
|
||||||
|
];
|
||||||
|
DCT { quantization_matrix }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Builds DCT with given quality value
|
||||||
|
/// quality
|
||||||
|
pub fn with_quality(mut self, quality: u8) -> Self {
|
||||||
|
let mut quantization_matrix: [u8; 64] = [0; 64];
|
||||||
|
let scalar: f32 = match quality {
|
||||||
|
1..=49 => 5000.0/quality as f32,
|
||||||
|
50..=100 => 200.0 - 2.0*quality as f32,
|
||||||
|
_ => 100.0 // Invalid input: set to base quality
|
||||||
|
};
|
||||||
|
for i in 0..64 {
|
||||||
|
quantization_matrix[i] = ((scalar * self.quantization_matrix[i] as f32 + 50.0) / 100.0).floor() as u8;
|
||||||
|
if quantization_matrix[i] == 0 {
|
||||||
|
quantization_matrix[i] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.quantization_matrix = quantization_matrix;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
fn dct(&self, img: &image::DynamicImage) -> [f64; 64] {
|
||||||
|
let mut dct_values: [f64; 64] = [0.0; 64];
|
||||||
|
for u in 0..8 {
|
||||||
|
for v in 0..8 {
|
||||||
|
let k = (v*8)+u;
|
||||||
|
let mut alpha = 0.25;
|
||||||
|
if u == 0 {
|
||||||
|
alpha = alpha / SQRT_2
|
||||||
|
}
|
||||||
|
if v == 0 {
|
||||||
|
alpha = alpha / SQRT_2
|
||||||
|
}
|
||||||
|
let v: f64 = v as f64;
|
||||||
|
let u: f64 = u as f64;
|
||||||
|
let mut sum: f64 = 0.0;
|
||||||
|
for (x, y, pix) in img.pixels() {
|
||||||
|
let x: f64 = 1.0 + 2.0 * x as f64;
|
||||||
|
let y: f64 = 1.0 + 2.0 * y as f64;
|
||||||
|
let pixel = (pix[0] as i16 - 127) as f64;
|
||||||
|
sum +=
|
||||||
|
pixel *
|
||||||
|
(x*u*PI/16.0).cos() *
|
||||||
|
(y*v*PI/16.0).cos()
|
||||||
|
}
|
||||||
|
dct_values[k] = alpha * sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dct_values
|
||||||
|
}
|
||||||
|
|
||||||
|
fn idct(&self, dct_values: [f64; 64]) -> [u8; 64] {
|
||||||
|
let mut reconstructed: [u8; 64] = [0; 64];
|
||||||
|
for k in 0..64 {
|
||||||
|
let x = (k%8) as f64;
|
||||||
|
let y = (k/8) as f64;
|
||||||
|
let mut sum = 0.0;
|
||||||
|
for u in 0..8 {
|
||||||
|
for v in 0..8 {
|
||||||
|
let mut alpha = 1.0;
|
||||||
|
if u == 0 {
|
||||||
|
alpha = alpha / SQRT_2
|
||||||
|
}
|
||||||
|
if v == 0 {
|
||||||
|
alpha = alpha / SQRT_2
|
||||||
|
}
|
||||||
|
let uv = (v*8)+u;
|
||||||
|
let v = v as f64;
|
||||||
|
let u = u as f64;
|
||||||
|
sum +=
|
||||||
|
alpha *
|
||||||
|
dct_values[uv] *
|
||||||
|
((2.0 * x + 1.0) * u * PI / 16.0).cos() *
|
||||||
|
((2.0 * y + 1.0) * v * PI / 16.0).cos();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sum = 127.0 + (0.25 * sum).round();
|
||||||
|
reconstructed[k] = std::cmp::min(255_u8, sum as u8);
|
||||||
|
}
|
||||||
|
reconstructed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Descriptor for DCT {
|
||||||
|
fn info(&self) -> String {
|
||||||
|
"DCT".to_string()
|
||||||
|
}
|
||||||
|
fn describe(&self, img: &image::DynamicImage) -> u64 {
|
||||||
|
let resized = self.resize(img);
|
||||||
|
let mut dct_values = self.dct(&resized);
|
||||||
|
debug!("DCT-coefficients:\n {}", print_matrix(dct_values));
|
||||||
|
|
||||||
|
// Quantization:
|
||||||
|
//debug!("Using quantization matrix:\n{}", print_matrix(self.quantization_matrix));
|
||||||
|
for i in 0..64 {
|
||||||
|
dct_values[i] = (dct_values[i] / self.quantization_matrix[i] as f64).round();
|
||||||
|
}
|
||||||
|
debug!("DCT-coefficients, quantized:\n {}", print_matrix(dct_values));
|
||||||
|
|
||||||
|
if log_enabled!(Level::Debug) {
|
||||||
|
resized.save("resize.png").expect("Error saving file");
|
||||||
|
// De-quantization:
|
||||||
|
for i in 0..64 {
|
||||||
|
dct_values[i] = dct_values[i] * self.quantization_matrix[i] as f64;
|
||||||
|
}
|
||||||
|
//debug!("DCT-coefficients, de-quantized:\n {}", print_matrix(dct_values));
|
||||||
|
|
||||||
|
// Reconstruction original pixel values:
|
||||||
|
let reconstructed = self.idct(dct_values);
|
||||||
|
|
||||||
|
save_buffer(
|
||||||
|
"reconstructed.png",
|
||||||
|
&reconstructed,
|
||||||
|
8,
|
||||||
|
8,
|
||||||
|
image::ColorType::L8
|
||||||
|
).expect("Error saving buffer");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculating descriptor from dct values:
|
||||||
|
|
||||||
|
// Zigzag order for our flattened array,
|
||||||
|
// first 28 elements only
|
||||||
|
let zigzag: [usize; 28] = [
|
||||||
|
0,
|
||||||
|
1, 8,
|
||||||
|
16, 9, 2,
|
||||||
|
3, 10, 17, 24,
|
||||||
|
32, 25, 18, 11, 4,
|
||||||
|
5, 12, 19, 26, 33, 40,
|
||||||
|
48, 41, 34, 27, 20, 13, 6,
|
||||||
|
];
|
||||||
|
|
||||||
|
// Mask that indicates if a dct coefficient is positive or negative
|
||||||
|
// By convention, when sign bit is 1, number is negative
|
||||||
|
let mut sign_mask: u64 = 0;
|
||||||
|
// If first horizontal AC coefficient is negative
|
||||||
|
// This might account for horizontal flips when applied to all horizontal coefficients.
|
||||||
|
let sign_mult = dct_values[1].signum();
|
||||||
|
|
||||||
|
// Mask that indicates if a coefficient is bigger or smaller than previous in order
|
||||||
|
let mut pearson_mask: u64 = 0;
|
||||||
|
let mut prev = dct_values[0];
|
||||||
|
|
||||||
|
|
||||||
|
for i in zigzag {
|
||||||
|
let cur = dct_values[i];
|
||||||
|
if cur > prev {
|
||||||
|
pearson_mask += 1;
|
||||||
|
}
|
||||||
|
prev = cur;
|
||||||
|
|
||||||
|
let signum = dct_values[i].signum();
|
||||||
|
// Only multiply sign if dct-coefficient contains a horizontal component.
|
||||||
|
if
|
||||||
|
//i % 8 != 0 && sign_mult * signum < 0.0
|
||||||
|
// ||
|
||||||
|
signum < 0.0
|
||||||
|
{
|
||||||
|
sign_mask += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shift masks
|
||||||
|
sign_mask = sign_mask << 1;
|
||||||
|
pearson_mask = pearson_mask << 1;
|
||||||
|
}
|
||||||
|
debug!("Sign mask: {:028b}", sign_mask);
|
||||||
|
debug!("Pearson mask: {:028b}", pearson_mask);
|
||||||
|
|
||||||
|
let mut mask = sign_mask;
|
||||||
|
debug!("Mask: {:064b}", mask);
|
||||||
|
mask = mask << 28;
|
||||||
|
debug!("Mask: {:064b}", mask);
|
||||||
|
mask += pearson_mask;
|
||||||
|
debug!("Mask: {:064b}", mask);
|
||||||
|
mask = mask << 8;
|
||||||
|
debug!("Mask: {:064b}", mask);
|
||||||
|
// TODO: Do something with these last 8 bits.
|
||||||
|
mask
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
//! Descriptors that can be used to describe an image.
|
||||||
|
//! If two images are (almost) the same, their descriptions will be the same.
|
||||||
|
|
||||||
|
pub trait Descriptor {
|
||||||
|
/// Print the name of the descriptor,
|
||||||
|
fn info(&self) -> String;
|
||||||
|
fn resize(&self, img: &image::DynamicImage) -> image::DynamicImage {
|
||||||
|
img.grayscale().thumbnail_exact(8, 8)
|
||||||
|
}
|
||||||
|
fn describe(&self, img: &image::DynamicImage) -> u64;
|
||||||
|
fn distance(&self, a: u64, b: u64) -> u64 {
|
||||||
|
(a^b).count_ones().into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Interprets a 64-element array as an 8x8 matrix
|
||||||
|
/// returns a nicely printable string
|
||||||
|
fn print_matrix<T: ToString + std::fmt::Display>(array: [T; 64]) -> String {
|
||||||
|
let mut output = String::new();
|
||||||
|
for x in 0..8 {
|
||||||
|
for y in 0..8 {
|
||||||
|
let element = format!("{:.2}", &array[x*8+y]);
|
||||||
|
let element = format!("{:8}\t", element);
|
||||||
|
output.push_str(&element);
|
||||||
|
}
|
||||||
|
output.push('\n');
|
||||||
|
}
|
||||||
|
output
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A struct representing a Discrete Cosine Transform descriptor
|
||||||
|
/// Transforms an image into an 8x8 grayscale version, and transforms it
|
||||||
|
/// into the frequency domain
|
||||||
|
pub struct DCT {
|
||||||
|
quantization_matrix: [u8; 64]
|
||||||
|
}
|
||||||
|
pub mod dct;
|
||||||
|
|
||||||
|
// fn median64<T: Ord + Copy>(values: &[T]) -> T {
|
||||||
|
// let mut sorted_values = values.to_vec();
|
||||||
|
// sorted_values.sort();
|
||||||
|
// let len = sorted_values.len();
|
||||||
|
// sorted_values[len/2]
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// pub struct Median;
|
||||||
|
|
||||||
|
// impl Descriptor for Median {
|
||||||
|
// fn describe(&self, img: image::DynamicImage) -> u64 {
|
||||||
|
// let img = self.resize(img);
|
||||||
|
// let mut values: [u8; 64] = [0; 64];
|
||||||
|
// let mut i: usize = 0;
|
||||||
|
// for (_, _, pix) in img.pixels() {
|
||||||
|
// values[i] = pix[0];
|
||||||
|
// i = i+1;
|
||||||
|
// }
|
||||||
|
// let median = median64(&values);
|
||||||
|
// let mut mask: u64 = 0;
|
||||||
|
// img.save("debug.png").unwrap();
|
||||||
|
// for (_, _, pix) in img.pixels() {
|
||||||
|
// if pix[0] > median {
|
||||||
|
// mask += 1;
|
||||||
|
// }
|
||||||
|
// mask = mask << 1;
|
||||||
|
// }
|
||||||
|
// mask
|
||||||
|
// }
|
||||||
|
// }
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
//! Near-copy image similarity detection.
|
||||||
|
|
||||||
|
//! Descriptors that can be used to describe an image.
|
||||||
|
//! If two images are (almost) the same, their descriptions will be the same.
|
||||||
|
pub mod descriptors;
|
||||||
|
pub mod store;
|
||||||
+52
-30
@@ -1,37 +1,59 @@
|
|||||||
use descriptors::{Descriptor, Median};
|
use image_similarity::store::DescriptorStore;
|
||||||
use std::collections::HashMap;
|
use image_similarity::descriptors::{Descriptor, DCT};
|
||||||
use std::fs;
|
use log::info;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::thread;
|
||||||
|
use clap::Parser;
|
||||||
|
|
||||||
pub mod descriptors;
|
#[derive(Parser)]
|
||||||
|
#[command(version, about, long_about = None)]
|
||||||
|
struct Cfg {
|
||||||
|
/// Path that contains the input images. Will not traverse directories.
|
||||||
|
path: PathBuf
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_store<T: Descriptor>(descriptor: T, input_path: PathBuf, save_path: PathBuf) -> () {
|
||||||
|
let mut store =
|
||||||
|
DescriptorStore::new()
|
||||||
|
.with_file(save_path);
|
||||||
|
info!("{}", store);
|
||||||
|
store.insert_directory(input_path, descriptor);
|
||||||
|
info!("{}", store);
|
||||||
|
store.save().expect("Error saving");
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
//Init all descriptors:
|
env_logger::init();
|
||||||
let desc = Median;
|
let cfg = Cfg::parse();
|
||||||
|
|
||||||
//Initialize hashmap, empty or from cached file:
|
let mut threads = vec![];
|
||||||
let count = fs::read_dir("img").unwrap().count();
|
|
||||||
let map_file = fs::read("map.messagepack");
|
|
||||||
let mut map: HashMap<String, u64> = match map_file {
|
|
||||||
Ok(f) => rmp_serde::from_slice(&f).unwrap(),
|
|
||||||
Err(_e) => HashMap::with_capacity(count),
|
|
||||||
};
|
|
||||||
|
|
||||||
//Calculate phashes for all images
|
let dct_50 =
|
||||||
for node in fs::read_dir("img").unwrap() {
|
DCT::new()
|
||||||
let file = node.expect("Error walking directory");
|
.with_quality(50);
|
||||||
let name = file.file_name().into_string().expect("Issue with filename");
|
let dct_30 =
|
||||||
if !map.contains_key(&name) {
|
DCT::new()
|
||||||
let img = image::open(file.path()).expect("Unable to open file");
|
.with_quality(30);
|
||||||
let phash = desc.describe(img);
|
let dct_10 =
|
||||||
map.insert(name, phash);
|
DCT::new()
|
||||||
}
|
.with_quality(10);
|
||||||
|
|
||||||
|
threads.push(
|
||||||
|
thread::spawn(move || {
|
||||||
|
make_store(dct_50, "data".into(), "dct50.messagepack".into());
|
||||||
|
})
|
||||||
|
);
|
||||||
|
threads.push(
|
||||||
|
thread::spawn(move || {
|
||||||
|
make_store(dct_30, "data".into(), "dct30.messagepack".into());
|
||||||
|
})
|
||||||
|
);
|
||||||
|
threads.push(
|
||||||
|
thread::spawn(move || {
|
||||||
|
make_store(dct_10, "data".into(), "dct10.messagepack".into());
|
||||||
|
})
|
||||||
|
);
|
||||||
|
for thread in threads {
|
||||||
|
let _ = thread.join();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (key, val) in map.iter() {
|
|
||||||
println!("{key}: {val}");
|
|
||||||
}
|
|
||||||
|
|
||||||
//Serialize hashmap with MessagePack:
|
|
||||||
let serialized: Vec<u8> = rmp_serde::to_vec(&map).unwrap();
|
|
||||||
fs::write("map.messagepack",&serialized).unwrap();
|
|
||||||
}
|
}
|
||||||
|
|||||||
+146
@@ -0,0 +1,146 @@
|
|||||||
|
//! Persistent store of all calculated image descriptions.
|
||||||
|
//! Can be queried to find identical or similar images.
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use crate::descriptors::Descriptor;
|
||||||
|
use std::fs;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::fmt;
|
||||||
|
use log::{info, debug, error};
|
||||||
|
use bktree::*;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum SaveError {
|
||||||
|
Serialization,
|
||||||
|
File,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DescriptorStore {
|
||||||
|
map: HashMap<u64, String>,
|
||||||
|
save_location: std::path::PathBuf,
|
||||||
|
bktree: BkTree<u64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DescriptorStore {
|
||||||
|
/// Makes a new empty DescriptorStore with default settings
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let map: HashMap<u64, String> = HashMap::new();
|
||||||
|
DescriptorStore {
|
||||||
|
map,
|
||||||
|
save_location: std::path::PathBuf::from("store.messagepack"),
|
||||||
|
bktree: BkTree::new(hamming_distance)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the file location and loads data from file (if available)
|
||||||
|
pub fn with_file<P: AsRef<Path>>(mut self, path: P) -> Self {
|
||||||
|
self.save_location = std::path::PathBuf::from(path.as_ref());
|
||||||
|
let map_file = fs::read(&self.save_location);
|
||||||
|
match map_file {
|
||||||
|
Ok(f) => self.map = rmp_serde::from_slice(&f).unwrap(),
|
||||||
|
Err(_) => info!("{} not found, starting from empty store.", self.save_location.display()),
|
||||||
|
};
|
||||||
|
for i in self.map.keys() {
|
||||||
|
self.bktree.insert(*i);
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn save(&self) -> Result<(), SaveError> {
|
||||||
|
let serialized: Vec<u8> = match rmp_serde::to_vec(&self.map) {
|
||||||
|
Ok(value) => value,
|
||||||
|
Err(_e) => return Err(SaveError::Serialization),
|
||||||
|
};
|
||||||
|
match fs::write(&self.save_location, &serialized) {
|
||||||
|
Ok(_) => Ok(()),
|
||||||
|
Err(_e) => Err(SaveError::File),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true iff the store already contains the key
|
||||||
|
pub fn contains(&self, key: u64) -> bool {
|
||||||
|
self.map.contains_key(&key)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Inserts a single value into the store
|
||||||
|
pub fn insert(&mut self, key: u64, value: String) {
|
||||||
|
self.map.insert(key, value);
|
||||||
|
self.bktree.insert(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Calculates all descriptions with a given descriptor
|
||||||
|
pub fn insert_directory<T: Descriptor, U: AsRef<Path>>(&mut self, dir: U, desc: T) {
|
||||||
|
for node in fs::read_dir(dir).unwrap() {
|
||||||
|
let file = node.expect("Error walking directory");
|
||||||
|
let name = match file.file_name().into_string() {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
error!("Error reading {}: {:?}:", file.path().to_string_lossy(), e);
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if true { // !self.contains(name.to_string()) {
|
||||||
|
info!("Processing {}", name);
|
||||||
|
let img = match image::open(file.path()) {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
error!("Failed to process {}: {}", name, e);
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let phash = desc.describe(&img);
|
||||||
|
if self.contains(phash) {
|
||||||
|
println!("{} duplicate of {:?}", name, self.map.get(&phash));
|
||||||
|
}
|
||||||
|
self.map.insert(phash, name);
|
||||||
|
} else {
|
||||||
|
debug!("{} already known, skipping.", name);
|
||||||
|
}
|
||||||
|
self.save().expect("error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// K-nearest neighbors
|
||||||
|
pub fn knn(&self, from: u64, k: isize) {
|
||||||
|
println!("{from:b}");
|
||||||
|
let mut x = 0;
|
||||||
|
let mut y = 8;
|
||||||
|
let (term_width, _) = viuer::terminal_size();
|
||||||
|
println!("\t\t\t\t\tTERMWIDTH {term_width}");
|
||||||
|
for (element, distance) in self.bktree.find(from, k) {
|
||||||
|
let name = self.map.get(element);
|
||||||
|
match name {
|
||||||
|
Some(n) => {
|
||||||
|
println!("{element:b}: {n} (distance: {distance})");
|
||||||
|
if x+16 >= term_width {
|
||||||
|
x = 0;
|
||||||
|
y += 8;
|
||||||
|
}
|
||||||
|
let conf = viuer::Config {
|
||||||
|
width: Some(16),
|
||||||
|
height: Some(8),
|
||||||
|
x: x,
|
||||||
|
y: y,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
x += 16;
|
||||||
|
let path = "data/".to_string() + &n;
|
||||||
|
let img = image::open(&path).unwrap();
|
||||||
|
viuer::print(&img, &conf).expect("Image printing failed.");
|
||||||
|
},
|
||||||
|
None => ()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for DescriptorStore {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
let mut output = String::new();
|
||||||
|
for (key, val) in self.map.iter() {
|
||||||
|
let entry = format!("{key:064b}: {val}\t {val:020}\n");
|
||||||
|
output.push_str(&entry);
|
||||||
|
}
|
||||||
|
write!(f, "DescriptorStore:\n{}Total: {}", output, self.map.len())
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user