Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
603678ba34 |
|||
|
db457fc4e7 |
|||
|
e57c1c9322 |
|||
|
d3bc84769e |
|||
|
cb5e1d837a |
|||
|
1f909904c2 |
|||
|
808a8bf31d |
|||
|
6fa0e29eae |
|||
|
18de039e77 |
|||
|
9d4e24e809 |
|||
|
94c905db38 |
|||
|
754dd6126d |
|||
|
26c17d5cf9 |
|||
|
5a84b56025 |
|||
|
e98f268e59 |
|||
|
973703726f |
|||
|
fca4577c0f |
|||
|
57ad7dfb1e |
|||
|
b8b4d8698c |
|||
|
13976b91ea |
|||
|
101adc7a89 |
|||
|
c96a1cbdd1 |
|||
|
fc92ff60e0 |
|||
|
2e8a6c8546 |
|||
|
50b5ed58b0 |
|||
|
b1157474c9 |
|||
|
9bdd556c9d |
|||
|
7ce87e2870 |
|||
|
97ce6754dd |
|||
|
f279c3aa15 |
|||
|
e7e1400c3a |
|||
|
5a83fe39e9 |
8 changed files with 953 additions and 343 deletions
720
Cargo.lock
generated
720
Cargo.lock
generated
|
|
@ -24,6 +24,17 @@ version = "2.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aes"
|
||||||
|
version = "0.9.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8eb277bec05f56a0e0591f155a484cbd0f4f07ff2905051a48c72f004f7ed58"
|
||||||
|
dependencies = [
|
||||||
|
"cipher",
|
||||||
|
"cpubits",
|
||||||
|
"cpufeatures",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ahash"
|
name = "ahash"
|
||||||
version = "0.8.12"
|
version = "0.8.12"
|
||||||
|
|
@ -55,6 +66,21 @@ dependencies = [
|
||||||
"equator",
|
"equator",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "alloc-no-stdlib"
|
||||||
|
version = "2.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "alloc-stdlib"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0e76a019e91224d279006ff972f1e984179a6e9feb050adba6ce8274aef23195"
|
||||||
|
dependencies = [
|
||||||
|
"alloc-no-stdlib",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "android-activity"
|
name = "android-activity"
|
||||||
version = "0.6.1"
|
version = "0.6.1"
|
||||||
|
|
@ -110,6 +136,27 @@ version = "1.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1"
|
checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "arboard"
|
||||||
|
version = "3.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0348a1c054491f4bfe6ab86a7b6ab1e44e45d899005de92f58b3df180b36ddaf"
|
||||||
|
dependencies = [
|
||||||
|
"clipboard-win",
|
||||||
|
"image",
|
||||||
|
"log",
|
||||||
|
"objc2 0.6.4",
|
||||||
|
"objc2-app-kit 0.3.2",
|
||||||
|
"objc2-core-foundation",
|
||||||
|
"objc2-core-graphics",
|
||||||
|
"objc2-foundation 0.3.2",
|
||||||
|
"parking_lot",
|
||||||
|
"percent-encoding",
|
||||||
|
"windows-sys 0.59.0",
|
||||||
|
"wl-clipboard-rs",
|
||||||
|
"x11rb",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arg_enum_proc_macro"
|
name = "arg_enum_proc_macro"
|
||||||
version = "0.3.4"
|
version = "0.3.4"
|
||||||
|
|
@ -413,6 +460,16 @@ version = "0.1.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
|
checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block-buffer"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa"
|
||||||
|
dependencies = [
|
||||||
|
"hybrid-array",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block2"
|
name = "block2"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
|
|
@ -445,28 +502,13 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bon"
|
name = "brotli-decompressor"
|
||||||
version = "3.9.3"
|
version = "5.0.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a602c73c7b0148ec6d12af6fd5cc7a46e2eacc8878271a999abac56eed12f561"
|
checksum = "3a32acac15fe1967bc3986b2a6347dffc965602354ea6f450ad07e8bfd253583"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bon-macros",
|
"alloc-no-stdlib",
|
||||||
"rustversion",
|
"alloc-stdlib",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bon-macros"
|
|
||||||
version = "3.9.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6dee98b0db6a962de883bf5d20362dee4d7ca0d12fe39a7c6c73c844e1cd7c1f"
|
|
||||||
dependencies = [
|
|
||||||
"darling",
|
|
||||||
"ident_case",
|
|
||||||
"prettyplease",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"rustversion",
|
|
||||||
"syn",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -525,6 +567,15 @@ version = "1.12.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8ae3f5d315924270530207e2a68396c3cc547f6dca3fbdca317cfb1a51edb593"
|
checksum = "8ae3f5d315924270530207e2a68396c3cc547f6dca3fbdca317cfb1a51edb593"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bzip2"
|
||||||
|
version = "0.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f3a53fac24f34a81bc9954b5d6cfce0c21e18ec6959f44f56e8e90e4bb7c346c"
|
||||||
|
dependencies = [
|
||||||
|
"libbz2-rs-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "calloop"
|
name = "calloop"
|
||||||
version = "0.13.0"
|
version = "0.13.0"
|
||||||
|
|
@ -610,6 +661,16 @@ version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cipher"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e8cf2a2c93cd704877c0858356ed03480ff301ee950b43f1cbe4573b088bfa6c"
|
||||||
|
dependencies = [
|
||||||
|
"crypto-common",
|
||||||
|
"inout",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clipboard-win"
|
name = "clipboard-win"
|
||||||
version = "5.4.1"
|
version = "5.4.1"
|
||||||
|
|
@ -649,6 +710,12 @@ dependencies = [
|
||||||
"x11rb",
|
"x11rb",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cmov"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "codespan-reporting"
|
name = "codespan-reporting"
|
||||||
version = "0.12.0"
|
version = "0.12.0"
|
||||||
|
|
@ -685,6 +752,18 @@ dependencies = [
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "const-oid"
|
||||||
|
version = "0.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "constant_time_eq"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "core-foundation"
|
name = "core-foundation"
|
||||||
version = "0.9.4"
|
version = "0.9.4"
|
||||||
|
|
@ -779,6 +858,21 @@ dependencies = [
|
||||||
"unicode-segmentation",
|
"unicode-segmentation",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cpubits"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "15b85f9c39137c3a891689859392b1bd49812121d0d61c9caf00d46ed5ce06ae"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cpufeatures"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crc32fast"
|
name = "crc32fast"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
|
|
@ -832,6 +926,15 @@ dependencies = [
|
||||||
"wgpu",
|
"wgpu",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crypto-common"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453"
|
||||||
|
dependencies = [
|
||||||
|
"hybrid-array",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ctor"
|
name = "ctor"
|
||||||
version = "0.10.1"
|
version = "0.10.1"
|
||||||
|
|
@ -841,46 +944,21 @@ dependencies = [
|
||||||
"dtor",
|
"dtor",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ctutils"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e"
|
||||||
|
dependencies = [
|
||||||
|
"cmov",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cursor-icon"
|
name = "cursor-icon"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f"
|
checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "darling"
|
|
||||||
version = "0.23.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d"
|
|
||||||
dependencies = [
|
|
||||||
"darling_core",
|
|
||||||
"darling_macro",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "darling_core"
|
|
||||||
version = "0.23.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0"
|
|
||||||
dependencies = [
|
|
||||||
"ident_case",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"strsim",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "darling_macro"
|
|
||||||
version = "0.23.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d"
|
|
||||||
dependencies = [
|
|
||||||
"darling_core",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dav1d"
|
name = "dav1d"
|
||||||
version = "0.11.1"
|
version = "0.11.1"
|
||||||
|
|
@ -903,6 +981,31 @@ dependencies = [
|
||||||
"system-deps",
|
"system-deps",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "deflate64"
|
||||||
|
version = "0.1.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac6b926516df9c60bfa16e107b21086399f8285a44ca9711344b9e553c5146e2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "deranged"
|
||||||
|
version = "0.5.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "digest"
|
||||||
|
version = "0.11.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2"
|
||||||
|
dependencies = [
|
||||||
|
"block-buffer",
|
||||||
|
"const-oid",
|
||||||
|
"crypto-common",
|
||||||
|
"ctutils",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dirs"
|
name = "dirs"
|
||||||
version = "6.0.0"
|
version = "6.0.0"
|
||||||
|
|
@ -1144,6 +1247,12 @@ version = "0.1.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fixedbitset"
|
||||||
|
version = "0.5.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "flate2"
|
name = "flate2"
|
||||||
version = "1.1.9"
|
version = "1.1.9"
|
||||||
|
|
@ -1152,6 +1261,7 @@ checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crc32fast",
|
"crc32fast",
|
||||||
"miniz_oxide",
|
"miniz_oxide",
|
||||||
|
"zlib-rs",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1375,8 +1485,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
|
checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
|
"js-sys",
|
||||||
"libc",
|
"libc",
|
||||||
"r-efi 6.0.0",
|
"r-efi 6.0.0",
|
||||||
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1570,6 +1682,24 @@ version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
|
checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hmac"
|
||||||
|
version = "0.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f"
|
||||||
|
dependencies = [
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hybrid-array"
|
||||||
|
version = "0.4.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "707114b52a152fa7bdb290cd7cd5912d9467273b6d74e21b8d81aca1f8533f6b"
|
||||||
|
dependencies = [
|
||||||
|
"typenum",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iced"
|
name = "iced"
|
||||||
version = "0.14.0"
|
version = "0.14.0"
|
||||||
|
|
@ -1757,12 +1887,6 @@ dependencies = [
|
||||||
"winit",
|
"winit",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ident_case"
|
|
||||||
version = "1.0.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "image"
|
name = "image"
|
||||||
version = "0.25.10"
|
version = "0.25.10"
|
||||||
|
|
@ -1803,11 +1927,15 @@ dependencies = [
|
||||||
name = "imagey"
|
name = "imagey"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"arboard",
|
||||||
"dirs",
|
"dirs",
|
||||||
"iced",
|
"iced",
|
||||||
"image",
|
"image",
|
||||||
"jpegxl-rs",
|
"jxl-oxide",
|
||||||
|
"kra-image-integration",
|
||||||
"rfd",
|
"rfd",
|
||||||
|
"size",
|
||||||
|
"zip",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1826,6 +1954,15 @@ dependencies = [
|
||||||
"hashbrown 0.17.1",
|
"hashbrown 0.17.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "inout"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4250ce6452e92010fdf7268ccc5d14faa80bb12fc741938534c58f16804e03c7"
|
||||||
|
dependencies = [
|
||||||
|
"hybrid-array",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "interpolate_name"
|
name = "interpolate_name"
|
||||||
version = "0.2.4"
|
version = "0.2.4"
|
||||||
|
|
@ -1914,29 +2051,6 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "jpegxl-rs"
|
|
||||||
version = "0.14.0+libjxl-0.11.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9b7d16fe73fb6d2e16b986392b716409c6ae6fabd35769d66bea391b016cdbc9"
|
|
||||||
dependencies = [
|
|
||||||
"bon",
|
|
||||||
"byteorder",
|
|
||||||
"half",
|
|
||||||
"image",
|
|
||||||
"jpegxl-sys",
|
|
||||||
"thiserror 2.0.18",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "jpegxl-sys"
|
|
||||||
version = "0.12.1+libjxl-0.11.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "00cb4f7ffb45ee4327e9ec6ca1a732f3abef470ee008f7d4be3afb414075cd7d"
|
|
||||||
dependencies = [
|
|
||||||
"pkg-config",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.103"
|
version = "0.3.103"
|
||||||
|
|
@ -1948,6 +2062,186 @@ dependencies = [
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jxl-bitstream"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b480e752277e29eb4054f69546887a9b84656fe78c08f54ba5850ced98a378fe"
|
||||||
|
dependencies = [
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jxl-coding"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cd972bcd125e776f1eb241ac50e39f956095a1c2770c64736c968f8946bd9a3c"
|
||||||
|
dependencies = [
|
||||||
|
"jxl-bitstream",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jxl-color"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f316b1358c1711755b3ee8e8cb5c4a1dad12e796233088a7a513440782de80b2"
|
||||||
|
dependencies = [
|
||||||
|
"jxl-bitstream",
|
||||||
|
"jxl-coding",
|
||||||
|
"jxl-grid",
|
||||||
|
"jxl-image",
|
||||||
|
"jxl-oxide-common",
|
||||||
|
"jxl-threadpool",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jxl-frame"
|
||||||
|
version = "0.13.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2d967c6fd669c7c01060b5022d8835fa82fd46b06ffc98b549f17600a097c2b3"
|
||||||
|
dependencies = [
|
||||||
|
"jxl-bitstream",
|
||||||
|
"jxl-coding",
|
||||||
|
"jxl-grid",
|
||||||
|
"jxl-image",
|
||||||
|
"jxl-modular",
|
||||||
|
"jxl-oxide-common",
|
||||||
|
"jxl-threadpool",
|
||||||
|
"jxl-vardct",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jxl-grid"
|
||||||
|
version = "0.6.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "01671307879a033bfa52e6e8784b941aca770b3f3a7d33830b455b6844f793fb"
|
||||||
|
dependencies = [
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jxl-image"
|
||||||
|
version = "0.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c5f752d62577c702a94dbbce4045caf08cb58639e8a4d56464b40ecf33ffe565"
|
||||||
|
dependencies = [
|
||||||
|
"jxl-bitstream",
|
||||||
|
"jxl-grid",
|
||||||
|
"jxl-oxide-common",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jxl-jbr"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e35d032bcec660647828527ff42c6f5776d2fd44b8357f9f6d9ac6dc07218e46"
|
||||||
|
dependencies = [
|
||||||
|
"brotli-decompressor",
|
||||||
|
"jxl-bitstream",
|
||||||
|
"jxl-frame",
|
||||||
|
"jxl-grid",
|
||||||
|
"jxl-image",
|
||||||
|
"jxl-modular",
|
||||||
|
"jxl-oxide-common",
|
||||||
|
"jxl-threadpool",
|
||||||
|
"jxl-vardct",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jxl-modular"
|
||||||
|
version = "0.11.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2a2f045b24c738dd91d482be385512b512721ae08a671bd4b27bf1c47f215235"
|
||||||
|
dependencies = [
|
||||||
|
"jxl-bitstream",
|
||||||
|
"jxl-coding",
|
||||||
|
"jxl-grid",
|
||||||
|
"jxl-oxide-common",
|
||||||
|
"jxl-threadpool",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jxl-oxide"
|
||||||
|
version = "0.12.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d36c662923f47586880211f3bc7c0d83fb3a9b410d278c7bde93450748abeef3"
|
||||||
|
dependencies = [
|
||||||
|
"brotli-decompressor",
|
||||||
|
"bytemuck",
|
||||||
|
"image",
|
||||||
|
"jxl-bitstream",
|
||||||
|
"jxl-color",
|
||||||
|
"jxl-frame",
|
||||||
|
"jxl-grid",
|
||||||
|
"jxl-image",
|
||||||
|
"jxl-jbr",
|
||||||
|
"jxl-oxide-common",
|
||||||
|
"jxl-render",
|
||||||
|
"jxl-threadpool",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jxl-oxide-common"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b62394c5021b3a9e7e0dbb2d639d555d019090c9946c39f6d3b09d390db4157b"
|
||||||
|
dependencies = [
|
||||||
|
"jxl-bitstream",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jxl-render"
|
||||||
|
version = "0.12.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d34386bfdb6a19b5a30cc9beb4d475d537422c31ae8c39bb69640fcce3fcaf19"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
"jxl-bitstream",
|
||||||
|
"jxl-coding",
|
||||||
|
"jxl-color",
|
||||||
|
"jxl-frame",
|
||||||
|
"jxl-grid",
|
||||||
|
"jxl-image",
|
||||||
|
"jxl-modular",
|
||||||
|
"jxl-oxide-common",
|
||||||
|
"jxl-threadpool",
|
||||||
|
"jxl-vardct",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jxl-threadpool"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "25f15eb830aa77a7f21148d72e153562a26bfe570139bd4922eab1908dd499d3"
|
||||||
|
dependencies = [
|
||||||
|
"rayon",
|
||||||
|
"rayon-core",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jxl-vardct"
|
||||||
|
version = "0.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ce72a18c6d3a47172ab6c479be2bdb56f22066b5d7092663f03b4490820b4511"
|
||||||
|
dependencies = [
|
||||||
|
"jxl-bitstream",
|
||||||
|
"jxl-coding",
|
||||||
|
"jxl-grid",
|
||||||
|
"jxl-modular",
|
||||||
|
"jxl-oxide-common",
|
||||||
|
"jxl-threadpool",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kamadak-exif"
|
name = "kamadak-exif"
|
||||||
version = "0.6.1"
|
version = "0.6.1"
|
||||||
|
|
@ -1974,6 +2268,16 @@ version = "3.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
|
checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "kra-image-integration"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9ab1db0e6caced9f4b26057c10ea190c447a8be4fcac03afd7213e35168ad700"
|
||||||
|
dependencies = [
|
||||||
|
"image",
|
||||||
|
"zip",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kurbo"
|
name = "kurbo"
|
||||||
version = "0.10.4"
|
version = "0.10.4"
|
||||||
|
|
@ -1990,6 +2294,12 @@ version = "0.5.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8"
|
checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libbz2-rs-sys"
|
||||||
|
version = "0.2.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34b357333733e8260735ba5894eb928c02ecc69c78715f01a8019e7fa7f2db4c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.186"
|
version = "0.2.186"
|
||||||
|
|
@ -2097,6 +2407,15 @@ version = "0.16.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7f66e8d5d03f609abc3a39e6f08e4164ebf1447a732906d39eb9b99b7919ef39"
|
checksum = "7f66e8d5d03f609abc3a39e6f08e4164ebf1447a732906d39eb9b99b7919ef39"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lzma-rust2"
|
||||||
|
version = "0.16.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ca93e534d1142d1d0dcca6d25fe302508a5dfb40b302802904577725ea0b695b"
|
||||||
|
dependencies = [
|
||||||
|
"sha2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "malloc_buf"
|
name = "malloc_buf"
|
||||||
version = "0.0.6"
|
version = "0.0.6"
|
||||||
|
|
@ -2316,6 +2635,12 @@ dependencies = [
|
||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-conv"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-derive"
|
name = "num-derive"
|
||||||
version = "0.4.2"
|
version = "0.4.2"
|
||||||
|
|
@ -2779,6 +3104,16 @@ dependencies = [
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "os_pipe"
|
||||||
|
version = "1.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"windows-sys 0.61.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "owned_ttf_parser"
|
name = "owned_ttf_parser"
|
||||||
version = "0.25.1"
|
version = "0.25.1"
|
||||||
|
|
@ -2829,12 +3164,33 @@ version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec"
|
checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pbkdf2"
|
||||||
|
version = "0.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "112d82ceb8c5bf524d9af484d4e4970c9fd5a0cc15ba14ad93dccd28873b0629"
|
||||||
|
dependencies = [
|
||||||
|
"digest",
|
||||||
|
"hmac",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "percent-encoding"
|
name = "percent-encoding"
|
||||||
version = "2.3.2"
|
version = "2.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
|
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "petgraph"
|
||||||
|
version = "0.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455"
|
||||||
|
dependencies = [
|
||||||
|
"fixedbitset",
|
||||||
|
"hashbrown 0.15.5",
|
||||||
|
"indexmap",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project"
|
name = "pin-project"
|
||||||
version = "1.1.13"
|
version = "1.1.13"
|
||||||
|
|
@ -2938,6 +3294,18 @@ dependencies = [
|
||||||
"portable-atomic",
|
"portable-atomic",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "powerfmt"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ppmd-rust"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "efca4c95a19a79d1c98f791f10aebd5c1363b473244630bb7dbde1dc98455a24"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ppv-lite86"
|
name = "ppv-lite86"
|
||||||
version = "0.2.21"
|
version = "0.2.21"
|
||||||
|
|
@ -2953,16 +3321,6 @@ version = "0.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa"
|
checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "prettyplease"
|
|
||||||
version = "0.2.37"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-crate"
|
name = "proc-macro-crate"
|
||||||
version = "3.5.0"
|
version = "3.5.0"
|
||||||
|
|
@ -3421,6 +3779,28 @@ dependencies = [
|
||||||
"serde_core",
|
"serde_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha1"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha2"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shlex"
|
name = "shlex"
|
||||||
version = "2.0.1"
|
version = "2.0.1"
|
||||||
|
|
@ -3468,6 +3848,12 @@ version = "0.1.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
|
checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "size"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b6709c7b6754dca1311b3c73e79fcce40dd414c782c66d88e8823030093b02b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "skrifa"
|
name = "skrifa"
|
||||||
version = "0.37.0"
|
version = "0.37.0"
|
||||||
|
|
@ -3639,12 +4025,6 @@ version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731"
|
checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "strsim"
|
|
||||||
version = "0.11.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "svg_fmt"
|
name = "svg_fmt"
|
||||||
version = "0.4.5"
|
version = "0.4.5"
|
||||||
|
|
@ -3777,6 +4157,26 @@ dependencies = [
|
||||||
"zune-jpeg",
|
"zune-jpeg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time"
|
||||||
|
version = "0.3.54"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3e1d5e639ff6bab73cb6885cc7e7b1de96c3f32c68ec55f3952614bec1092244"
|
||||||
|
dependencies = [
|
||||||
|
"deranged",
|
||||||
|
"js-sys",
|
||||||
|
"num-conv",
|
||||||
|
"powerfmt",
|
||||||
|
"serde_core",
|
||||||
|
"time-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "time-core"
|
||||||
|
version = "0.1.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tiny-skia"
|
name = "tiny-skia"
|
||||||
version = "0.11.4"
|
version = "0.11.4"
|
||||||
|
|
@ -3913,6 +4313,17 @@ dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tree_magic_mini"
|
||||||
|
version = "3.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b8765b90061cba6c22b5831f675da109ae5561588290f9fa2317adab2714d5a6"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
"nom",
|
||||||
|
"petgraph",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ttf-parser"
|
name = "ttf-parser"
|
||||||
version = "0.25.1"
|
version = "0.25.1"
|
||||||
|
|
@ -3922,6 +4333,18 @@ dependencies = [
|
||||||
"core_maths",
|
"core_maths",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typed-path"
|
||||||
|
version = "0.12.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e28f89b80c87b8fb0cf04ab448d5dd0dd0ade2f8891bae878de66a75a28600e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typenum"
|
||||||
|
version = "1.20.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uds_windows"
|
name = "uds_windows"
|
||||||
version = "1.2.1"
|
version = "1.2.1"
|
||||||
|
|
@ -4764,6 +5187,24 @@ version = "0.57.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
|
checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wl-clipboard-rs"
|
||||||
|
version = "0.9.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e9651471a32e87d96ef3a127715382b2d11cc7c8bb9822ded8a7cc94072eb0a3"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"log",
|
||||||
|
"os_pipe",
|
||||||
|
"rustix 1.1.4",
|
||||||
|
"thiserror 2.0.18",
|
||||||
|
"tree_magic_mini",
|
||||||
|
"wayland-backend",
|
||||||
|
"wayland-client",
|
||||||
|
"wayland-protocols",
|
||||||
|
"wayland-protocols-wlr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "x11-dl"
|
name = "x11-dl"
|
||||||
version = "2.21.0"
|
version = "2.21.0"
|
||||||
|
|
@ -4926,6 +5367,85 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zeroize"
|
||||||
|
version = "1.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zip"
|
||||||
|
version = "8.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2d04a6b5381502aa6087c94c669499eb1602eb9c5e8198e534de571f7154809b"
|
||||||
|
dependencies = [
|
||||||
|
"aes",
|
||||||
|
"bzip2",
|
||||||
|
"constant_time_eq",
|
||||||
|
"crc32fast",
|
||||||
|
"deflate64",
|
||||||
|
"flate2",
|
||||||
|
"getrandom 0.4.3",
|
||||||
|
"hmac",
|
||||||
|
"indexmap",
|
||||||
|
"lzma-rust2",
|
||||||
|
"memchr",
|
||||||
|
"pbkdf2",
|
||||||
|
"ppmd-rust",
|
||||||
|
"sha1",
|
||||||
|
"time",
|
||||||
|
"typed-path",
|
||||||
|
"zeroize",
|
||||||
|
"zopfli",
|
||||||
|
"zstd",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zlib-rs"
|
||||||
|
version = "0.6.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b142a20ec14a91d5bc708c1dc21b080c550113d8aa77afa29635673a65dd02c5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zopfli"
|
||||||
|
version = "0.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f05cd8797d63865425ff89b5c4a48804f35ba0ce8d125800027ad6017d2b5249"
|
||||||
|
dependencies = [
|
||||||
|
"bumpalo",
|
||||||
|
"crc32fast",
|
||||||
|
"log",
|
||||||
|
"simd-adler32",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zstd"
|
||||||
|
version = "0.13.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a"
|
||||||
|
dependencies = [
|
||||||
|
"zstd-safe",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zstd-safe"
|
||||||
|
version = "7.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d"
|
||||||
|
dependencies = [
|
||||||
|
"zstd-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zstd-sys"
|
||||||
|
version = "2.0.16+zstd.1.5.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
"pkg-config",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zune-core"
|
name = "zune-core"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
|
|
|
||||||
18
Cargo.toml
18
Cargo.toml
|
|
@ -5,11 +5,25 @@ edition = "2024"
|
||||||
license = "AGPL-3.0-or-later"
|
license = "AGPL-3.0-or-later"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
iced = { version = "0.14.0", features = [ "image" ] }
|
|
||||||
dirs = "6.0.0"
|
dirs = "6.0.0"
|
||||||
|
kra-image-integration = "0.1.0"
|
||||||
rfd = "0.17.2"
|
rfd = "0.17.2"
|
||||||
jpegxl-rs = "0.14.0"
|
size = "0.5.0"
|
||||||
|
zip = "8.6.0"
|
||||||
|
|
||||||
|
[dependencies.iced]
|
||||||
|
version = "0.14.0"
|
||||||
|
features = [ "image" ]
|
||||||
|
|
||||||
[dependencies.image]
|
[dependencies.image]
|
||||||
version = "0.25.10"
|
version = "0.25.10"
|
||||||
features = [ "avif-native" ]
|
features = [ "avif-native" ]
|
||||||
|
|
||||||
|
[dependencies.jxl-oxide]
|
||||||
|
version = "0.12.6"
|
||||||
|
# I really wish the image crate was named better
|
||||||
|
features = [ "image" ]
|
||||||
|
|
||||||
|
[dependencies.arboard]
|
||||||
|
version = "3.6.1"
|
||||||
|
features = [ "wayland-data-control" ]
|
||||||
|
|
|
||||||
41
README.md
Normal file
41
README.md
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
# imagey
|
||||||
|
|
||||||
|
image viewer and maybe editor; inspired by mpv's simplicity
|
||||||
|
|
||||||
|
name is subject to change, suggestions welcome :)
|
||||||
|
|
||||||
|
## usage
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# try it out!
|
||||||
|
nix run git+https://git.federated.nexus/electria/imagey
|
||||||
|
|
||||||
|
# install it imperatively
|
||||||
|
nix profile install git+https://git.federated.nexus/electria/imagey
|
||||||
|
```
|
||||||
|
|
||||||
|
keybinds are shown on startup if you didn't start it with an image
|
||||||
|
|
||||||
|
## known issues
|
||||||
|
|
||||||
|
### JXL
|
||||||
|
|
||||||
|
1. encoding is not implemented (jxl-oxide is decoding-only)
|
||||||
|
2. oreintation is incorrect in some cases
|
||||||
|
|
||||||
|
if the image has metadata oreintation AND
|
||||||
|
|
||||||
|
it's a jxl without the right extension OR
|
||||||
|
it's a jpeg with the jxl extension
|
||||||
|
|
||||||
|
this is due to the JXL decoder automatically rotating the image,
|
||||||
|
while the JPEG decoder (for instance) requires the extra step.
|
||||||
|
|
||||||
|
my workaround is to check the path of the input file,
|
||||||
|
not changing the oreintation if it has the jxl extension;
|
||||||
|
causing these caveats for cases where the extension is wrong.
|
||||||
|
|
||||||
|
### clipboard
|
||||||
|
|
||||||
|
1. large images (eg photos) don't seem to copy on linux/wayland,
|
||||||
|
(despite set_image not returning any error)
|
||||||
38
flake.nix
38
flake.nix
|
|
@ -19,18 +19,24 @@
|
||||||
cargoToml = fromTOML (builtins.readFile ./Cargo.toml);
|
cargoToml = fromTOML (builtins.readFile ./Cargo.toml);
|
||||||
name = cargoToml.package.name;
|
name = cargoToml.package.name;
|
||||||
|
|
||||||
dlDeps = with pkgs; [
|
dlDeps =
|
||||||
|
with pkgs;
|
||||||
|
[
|
||||||
# needed for both x11 and wayland
|
# needed for both x11 and wayland
|
||||||
libxkbcommon
|
libxkbcommon
|
||||||
libGL
|
libGL
|
||||||
vulkan-loader
|
|
||||||
|
|
||||||
wayland
|
|
||||||
|
|
||||||
libx11
|
libx11
|
||||||
libxcursor
|
libxcursor
|
||||||
libxi
|
libxi
|
||||||
libxcb
|
libxcb
|
||||||
|
]
|
||||||
|
++ lib.optionals stdenv.hostPlatform.isLinux [
|
||||||
|
# libdbus, for rfd
|
||||||
|
dbus.lib
|
||||||
|
|
||||||
|
vulkan-loader
|
||||||
|
wayland
|
||||||
];
|
];
|
||||||
|
|
||||||
commonArgs = {
|
commonArgs = {
|
||||||
|
|
@ -39,15 +45,12 @@
|
||||||
pkg-config
|
pkg-config
|
||||||
];
|
];
|
||||||
buildInputs = with pkgs; [
|
buildInputs = with pkgs; [
|
||||||
libjxl
|
|
||||||
dav1d
|
dav1d
|
||||||
];
|
];
|
||||||
|
|
||||||
src = ./.;
|
src = ./.;
|
||||||
};
|
};
|
||||||
|
|
||||||
LD_LIBRARY_PATH = lib.makeLibraryPath dlDeps;
|
|
||||||
|
|
||||||
# Build *just* the cargo dependencies,
|
# Build *just* the cargo dependencies,
|
||||||
# to reuse them for build and test derivations.
|
# to reuse them for build and test derivations.
|
||||||
cargoArtifacts = craneLib.buildDepsOnly commonArgs;
|
cargoArtifacts = craneLib.buildDepsOnly commonArgs;
|
||||||
|
|
@ -71,6 +74,7 @@
|
||||||
"image/tiff"
|
"image/tiff"
|
||||||
"image/bmp"
|
"image/bmp"
|
||||||
"image/vnd.microsoft.icon" # .ico
|
"image/vnd.microsoft.icon" # .ico
|
||||||
|
"application/x-krita"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
|
|
@ -79,19 +83,13 @@
|
||||||
// {
|
// {
|
||||||
inherit cargoArtifacts;
|
inherit cargoArtifacts;
|
||||||
|
|
||||||
nativeBuildInputs =
|
nativeBuildInputs = commonArgs.nativeBuildInputs ++ [
|
||||||
commonArgs.nativeBuildInputs
|
|
||||||
++ [
|
|
||||||
pkgs.autoPatchelfHook
|
pkgs.autoPatchelfHook
|
||||||
]
|
];
|
||||||
++ lib.optional pkgs.stdenv.hostPlatform.isLinux pkgs.makeBinaryWrapper;
|
|
||||||
|
|
||||||
buildInputs =
|
buildInputs = commonArgs.buildInputs ++ [
|
||||||
commonArgs.buildInputs
|
|
||||||
++ [
|
|
||||||
pkgs.libgcc
|
pkgs.libgcc
|
||||||
]
|
];
|
||||||
++ lib.optional pkgs.stdenv.hostPlatform.isLinux pkgs.zenity;
|
|
||||||
|
|
||||||
runtimeDependencies = dlDeps;
|
runtimeDependencies = dlDeps;
|
||||||
|
|
||||||
|
|
@ -100,10 +98,6 @@
|
||||||
postFixup = ''
|
postFixup = ''
|
||||||
mkdir -p "$out/share/applications"
|
mkdir -p "$out/share/applications"
|
||||||
ln -s "${desktopItem}"/share/applications/* "$out/share/applications/"
|
ln -s "${desktopItem}"/share/applications/* "$out/share/applications/"
|
||||||
''
|
|
||||||
+ lib.optionalString pkgs.stdenv.hostPlatform.isLinux /* sh */ ''
|
|
||||||
wrapProgram $out/bin/${name} --inherit-argv0 \
|
|
||||||
--prefix PATH : ${lib.makeBinPath [ pkgs.zenity ]}
|
|
||||||
'';
|
'';
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
@ -123,7 +117,7 @@
|
||||||
};
|
};
|
||||||
|
|
||||||
devShells.default = craneLib.devShell {
|
devShells.default = craneLib.devShell {
|
||||||
inherit LD_LIBRARY_PATH;
|
LD_LIBRARY_PATH = lib.makeLibraryPath dlDeps;
|
||||||
|
|
||||||
inputsFrom = [ crate ];
|
inputsFrom = [ crate ];
|
||||||
packages = [ pkgs.rust-analyzer ];
|
packages = [ pkgs.rust-analyzer ];
|
||||||
|
|
|
||||||
22
src/jxl.rs
22
src/jxl.rs
|
|
@ -1,22 +0,0 @@
|
||||||
pub struct JxlDecoder<'a> {
|
|
||||||
metadata: jpegxl_rs::decode::Metadata,
|
|
||||||
inner: jpegxl_rs::decode::JxlDecoder<'a, 'a>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> image::ImageDecoder for JxlDecoder<'a> {
|
|
||||||
fn color_type(&self) -> image::ColorType {
|
|
||||||
image::ColorType::Rgba8
|
|
||||||
}
|
|
||||||
fn icc_profile(&mut self) -> image::ImageResult<Option<Vec<u8>>> {
|
|
||||||
Ok(self.metadata.icc_profile.clone())
|
|
||||||
}
|
|
||||||
fn dimensions(&self) -> (u32, u32) {}
|
|
||||||
fn read_image(self, buf: &mut [u8]) -> image::ImageResult<()>
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
{
|
|
||||||
}
|
|
||||||
fn read_image_boxed(self: Box<Self>, buf: &mut [u8]) -> image::ImageResult<()> {
|
|
||||||
self.read_image(buf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
242
src/main.rs
242
src/main.rs
|
|
@ -1,50 +1,59 @@
|
||||||
use std::{env, path::Path};
|
use std::{
|
||||||
|
borrow::Cow,
|
||||||
|
env,
|
||||||
|
ffi::OsStr,
|
||||||
|
os::unix::fs::MetadataExt,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
|
||||||
|
use arboard::Clipboard;
|
||||||
use iced::{
|
use iced::{
|
||||||
Alignment, Color, Element, Length, Renderer, Subscription, Task, Theme, color, event,
|
Alignment, Color, Element, Length, Renderer, Subscription, Task, Theme, event,
|
||||||
keyboard::{self, Key, key},
|
keyboard::{self, Key, key},
|
||||||
theme, widget, window,
|
theme, widget, window,
|
||||||
};
|
};
|
||||||
use image::{EncodableLayout, RgbaImage, imageops};
|
use image::{EncodableLayout, RgbaImage, imageops};
|
||||||
|
use size::Size;
|
||||||
|
|
||||||
mod jxl;
|
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
enum Message {
|
enum Message {
|
||||||
|
ImagePicked(Result<PathBuf, String>),
|
||||||
ImageDisplayReady(Result<widget::image::Allocation, widget::image::Error>),
|
ImageDisplayReady(Result<widget::image::Allocation, widget::image::Error>),
|
||||||
|
SavePathPicked(Result<PathBuf, String>),
|
||||||
|
|
||||||
Event(iced::Event),
|
Event(iced::Event),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Default)]
|
||||||
struct State {
|
struct State {
|
||||||
image: Option<RgbaImage>,
|
image: Option<RgbaImage>,
|
||||||
image_display: Option<widget::image::Allocation>,
|
image_display: Option<widget::image::Allocation>,
|
||||||
|
image_filter: widget::image::FilterMethod,
|
||||||
|
|
||||||
error: Option<String>,
|
error: Option<String>,
|
||||||
|
info: Option<String>,
|
||||||
|
infobar_shown: bool,
|
||||||
|
|
||||||
|
clipboard: Option<Clipboard>,
|
||||||
}
|
}
|
||||||
impl State {
|
impl State {
|
||||||
fn new() -> (Self, Task<Message>) {
|
fn new() -> (Self, Task<Message>) {
|
||||||
let mut state = State::default();
|
let mut state = Self::default();
|
||||||
|
|
||||||
state.error = env::args().nth(1).and_then(|path| {
|
if let Some(path) = env::args().nth(1) {
|
||||||
utils::load_image(path)
|
match state.load_image(path) {
|
||||||
.map(|image| state.image = Some(image))
|
Err(e) => state.error = Some(e),
|
||||||
.err()
|
Ok(task) => return (state, task),
|
||||||
});
|
}
|
||||||
let allocate_image = state.allocate_image();
|
}
|
||||||
|
|
||||||
(state, allocate_image)
|
(state, Task::none())
|
||||||
}
|
}
|
||||||
fn view(&self) -> Element<'_, Message, Theme, Renderer> {
|
fn view(&self) -> Element<'_, Message, Theme, Renderer> {
|
||||||
widget::column([
|
let main = self.image_display.as_ref().map_or_else(
|
||||||
if let Some(allocation) = self.image_display.as_ref() {
|
|| {
|
||||||
widget::image::viewer(allocation.handle().clone())
|
|
||||||
.width(Length::Fill)
|
|
||||||
.height(Length::Fill)
|
|
||||||
.into()
|
|
||||||
} else {
|
|
||||||
widget::container(widget::text(include_str!("usage.txt")))
|
widget::container(widget::text(include_str!("usage.txt")))
|
||||||
.height(Length::Fill)
|
.height(Length::Fill)
|
||||||
.width(Length::Fill)
|
.width(Length::Fill)
|
||||||
|
|
@ -52,19 +61,59 @@ impl State {
|
||||||
.align_y(Alignment::Center)
|
.align_y(Alignment::Center)
|
||||||
.into()
|
.into()
|
||||||
},
|
},
|
||||||
if let Some(error) = self.error.as_ref() {
|
|allocation| {
|
||||||
widget::text(error).style(widget::text::danger).into()
|
widget::image::viewer(allocation.handle().clone())
|
||||||
} else {
|
.filter_method(self.image_filter)
|
||||||
widget::space().into()
|
.max_scale(50.)
|
||||||
},
|
.min_scale(1.)
|
||||||
])
|
.width(Length::Fill)
|
||||||
|
.height(Length::Fill)
|
||||||
.into()
|
.into()
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut bar = Vec::new();
|
||||||
|
if let Some(error) = self.error.as_ref() {
|
||||||
|
bar.push(
|
||||||
|
widget::container(widget::text(error).style(widget::text::danger))
|
||||||
|
.align_x(Alignment::Start)
|
||||||
|
.width(Length::Fill)
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if self.infobar_shown && self.info.is_some() {
|
||||||
|
bar.push(
|
||||||
|
widget::container(widget::text(self.title()))
|
||||||
|
.align_x(Alignment::End)
|
||||||
|
.width(Length::Fill)
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
widget::column([main, widget::row(bar).into()]).into()
|
||||||
}
|
}
|
||||||
fn update(&mut self, message: Message) -> Task<Message> {
|
fn update(&mut self, message: Message) -> Task<Message> {
|
||||||
match message {
|
match message {
|
||||||
|
Message::ImagePicked(result) => match result.and_then(|path| self.load_image(path)) {
|
||||||
|
Err(e) => self.error = Some(e),
|
||||||
|
Ok(task) => {
|
||||||
|
self.error = None;
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
},
|
||||||
Message::ImageDisplayReady(result) => {
|
Message::ImageDisplayReady(result) => {
|
||||||
self.image_display = Some(result.unwrap());
|
self.image_display = Some(result.unwrap());
|
||||||
}
|
}
|
||||||
|
Message::SavePathPicked(result) => {
|
||||||
|
self.error = result
|
||||||
|
.and_then(|path| {
|
||||||
|
self.image.as_ref().map_or_else(
|
||||||
|
|| Err("no image to save".into()),
|
||||||
|
|image| image.save(path).map_err(|e| e.to_string()),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.err();
|
||||||
|
}
|
||||||
|
|
||||||
Message::Event(iced::Event::Keyboard(keyboard::Event::KeyPressed {
|
Message::Event(iced::Event::Keyboard(keyboard::Event::KeyPressed {
|
||||||
key,
|
key,
|
||||||
|
|
@ -75,46 +124,93 @@ impl State {
|
||||||
Key::Named(key::Named::Tab) => {
|
Key::Named(key::Named::Tab) => {
|
||||||
if modifiers.shift() {
|
if modifiers.shift() {
|
||||||
return widget::operation::focus_previous();
|
return widget::operation::focus_previous();
|
||||||
} else {
|
}
|
||||||
return widget::operation::focus_next();
|
return widget::operation::focus_next();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Key::Character("o") => {
|
||||||
|
return Task::perform(utils::pick_image(), Message::ImagePicked);
|
||||||
}
|
}
|
||||||
|
|
||||||
Key::Character("o") => match self.pick_and_load_image() {
|
Key::Character("r") => match self.image.as_ref() {
|
||||||
Ok(task) => {
|
|
||||||
self.error = None;
|
|
||||||
return task;
|
|
||||||
}
|
|
||||||
Err(e) => self.error = Some(e),
|
|
||||||
},
|
|
||||||
|
|
||||||
Key::Character("r") => {
|
|
||||||
match self.image.as_ref() {
|
|
||||||
None => self.error = Some("no image to rotate".into()),
|
None => self.error = Some("no image to rotate".into()),
|
||||||
Some(image) => {
|
Some(image) => {
|
||||||
self.error = None;
|
self.error = None;
|
||||||
self.image = Some(imageops::rotate90(image));
|
self.image = Some(imageops::rotate90(image));
|
||||||
return self.allocate_image();
|
return self.allocate_image();
|
||||||
}
|
}
|
||||||
};
|
},
|
||||||
}
|
Key::Character("i") => match self.image.as_mut() {
|
||||||
Key::Character("i") => {
|
|
||||||
match self.image.as_mut() {
|
|
||||||
None => self.error = Some("no image to invert".into()),
|
None => self.error = Some("no image to invert".into()),
|
||||||
Some(image) => {
|
Some(image) => {
|
||||||
self.error = None;
|
self.error = None;
|
||||||
imageops::invert(image);
|
imageops::invert(image);
|
||||||
return self.allocate_image();
|
return self.allocate_image();
|
||||||
}
|
}
|
||||||
};
|
},
|
||||||
|
Key::Character("f") => {
|
||||||
|
self.image_filter = match self.image_filter {
|
||||||
|
widget::image::FilterMethod::Linear => widget::image::FilterMethod::Nearest,
|
||||||
|
widget::image::FilterMethod::Nearest => widget::image::FilterMethod::Linear,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Key::Character("b") => {
|
||||||
|
self.infobar_shown = !self.infobar_shown;
|
||||||
}
|
}
|
||||||
|
|
||||||
Key::Character("s") => {
|
Key::Character("s") => {
|
||||||
self.save_image();
|
if self.image.is_some() {
|
||||||
|
self.error = None;
|
||||||
|
return Task::perform(utils::pick_save_path(), Message::SavePathPicked);
|
||||||
|
}
|
||||||
|
self.error = Some("no image to save".into());
|
||||||
}
|
}
|
||||||
|
|
||||||
Key::Character("q") => return window::latest().and_then(window::close),
|
Key::Character("q") => return window::latest().and_then(window::close),
|
||||||
|
|
||||||
|
Key::Character("y") | Key::Character("c") => {
|
||||||
|
if let Some(image) = self.image.as_ref() {
|
||||||
|
match match self.clipboard.take() {
|
||||||
|
Some(c) => Ok(c),
|
||||||
|
None => Clipboard::new(),
|
||||||
|
} {
|
||||||
|
Ok(mut clipboard) => {
|
||||||
|
self.error = clipboard
|
||||||
|
.set_image(utils::arboard_from_rgbaimage(image))
|
||||||
|
.map_err(|e| e.to_string())
|
||||||
|
.err();
|
||||||
|
self.clipboard = Some(clipboard);
|
||||||
|
}
|
||||||
|
Err(e) => self.error = Some(e.to_string()),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.error = Some("no image to yank".into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Key::Character("p") | Key::Character("v") => {
|
||||||
|
match match self.clipboard.take() {
|
||||||
|
Some(c) => Ok(c),
|
||||||
|
None => Clipboard::new(),
|
||||||
|
} {
|
||||||
|
Ok(mut clipboard) => {
|
||||||
|
let result = clipboard.get_image().map(utils::rgbaimage_from_arboard);
|
||||||
|
|
||||||
|
self.error = result.as_ref().map_err(|e| e.to_string()).err();
|
||||||
|
self.clipboard = Some(clipboard);
|
||||||
|
|
||||||
|
if let Ok(image) = result {
|
||||||
|
self.info = Some(format!("{}x{}", image.width(), image.height(),));
|
||||||
|
if image.dimensions() < (100, 100) {
|
||||||
|
self.image_filter = widget::image::FilterMethod::Nearest;
|
||||||
|
}
|
||||||
|
self.image = Some(image);
|
||||||
|
return self.allocate_image();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => self.error = Some(e.to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ignore unused keys
|
// ignore unused keys
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
|
|
@ -137,18 +233,29 @@ impl State {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_image(&mut self, path: impl AsRef<Path>) -> Result<Task<Message>, String> {
|
fn load_image(&mut self, path: impl AsRef<Path>) -> Result<Task<Message>, String> {
|
||||||
utils::load_image(path).map(|image| {
|
utils::load_image(&path).map(|image| {
|
||||||
|
self.info = Some(format!(
|
||||||
|
"{} {} {}x{}",
|
||||||
|
path.as_ref()
|
||||||
|
.file_name()
|
||||||
|
.map_or(Cow::Borrowed("[no file]"), OsStr::to_string_lossy),
|
||||||
|
path.as_ref().metadata().map_or_else(
|
||||||
|
|e| {
|
||||||
|
eprintln!("failed to read metadata: {e}");
|
||||||
|
Cow::Borrowed("[no size]")
|
||||||
|
},
|
||||||
|
|m| Cow::Owned(Size::from_bytes(m.size()).to_string())
|
||||||
|
),
|
||||||
|
image.width(),
|
||||||
|
image.height(),
|
||||||
|
));
|
||||||
|
if image.dimensions() < (100, 100) {
|
||||||
|
self.image_filter = widget::image::FilterMethod::Nearest;
|
||||||
|
}
|
||||||
self.image = Some(image);
|
self.image = Some(image);
|
||||||
self.allocate_image()
|
self.allocate_image()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fn pick_and_load_image(&mut self) -> Result<Task<Message>, String> {
|
|
||||||
utils::pick_image().and_then(|path| self.load_image(path))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn save_image(&mut self) {
|
|
||||||
self.error = utils::save_image(self.image.as_ref()).err();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn allocate_image(&self) -> Task<Message> {
|
fn allocate_image(&self) -> Task<Message> {
|
||||||
let Some(image) = self.image.as_ref() else {
|
let Some(image) = self.image.as_ref() else {
|
||||||
|
|
@ -159,6 +266,18 @@ impl State {
|
||||||
widget::image::allocate(widget::image::Handle::from_rgba(
|
widget::image::allocate(widget::image::Handle::from_rgba(
|
||||||
image.width(),
|
image.width(),
|
||||||
image.height(),
|
image.height(),
|
||||||
|
// SAFETY: this is a sort of race condition;
|
||||||
|
// will cause panics with large enough images,
|
||||||
|
// when they are edited consecutively.
|
||||||
|
//
|
||||||
|
// this can be reproduced by holding down 'i' with a 10k by 10k px image,
|
||||||
|
// which will invert the colors rapidly and eventually crash the app.
|
||||||
|
//
|
||||||
|
// however, that is not such a problem in this case,
|
||||||
|
// and I don't know a different way of doing this that doesn't copy
|
||||||
|
// (performance loss, which is can be pretty big)
|
||||||
|
// or likely cause flickering instead in such cases
|
||||||
|
// (like using Handle over Allocation to immediately drop the last one)
|
||||||
unsafe { std::mem::transmute::<&[u8], &'static [u8]>(image.as_bytes()) },
|
unsafe { std::mem::transmute::<&[u8], &'static [u8]>(image.as_bytes()) },
|
||||||
))
|
))
|
||||||
.map(Message::ImageDisplayReady)
|
.map(Message::ImageDisplayReady)
|
||||||
|
|
@ -168,26 +287,31 @@ impl State {
|
||||||
event::listen().map(Message::Event)
|
event::listen().map(Message::Event)
|
||||||
}
|
}
|
||||||
fn title(&self) -> String {
|
fn title(&self) -> String {
|
||||||
match self.image.as_ref() {
|
self.info.as_ref().map_or_else(
|
||||||
Some(image) => format!("imagey {}x{}", image.width(), image.height()),
|
|| "imagey".into(),
|
||||||
None => "imagey".into(),
|
|info| {
|
||||||
}
|
format!(
|
||||||
|
"imagey {info} {}",
|
||||||
|
utils::string_from_filter_type(self.image_filter),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<(), iced::Error> {
|
fn main() -> Result<(), iced::Error> {
|
||||||
|
jxl_oxide::integration::register_image_decoding_hook();
|
||||||
|
kra_image_integration::register();
|
||||||
|
|
||||||
iced::application(State::new, State::update, State::view)
|
iced::application(State::new, State::update, State::view)
|
||||||
.subscription(State::subscription)
|
.subscription(State::subscription)
|
||||||
.title(State::title)
|
.title(State::title)
|
||||||
.theme(Theme::custom(
|
.theme(Theme::custom(
|
||||||
"custom",
|
"custom",
|
||||||
theme::Palette {
|
theme::Palette {
|
||||||
background: color!(0x080808),
|
background: Color::BLACK,
|
||||||
text: Color::WHITE,
|
text: Color::WHITE,
|
||||||
primary: color!(0xff00ff),
|
..theme::Palette::DARK
|
||||||
success: color!(0x00ff00),
|
|
||||||
warning: color!(0x880000),
|
|
||||||
danger: color!(0xff0000),
|
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
.run()
|
.run()
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,10 @@
|
||||||
"o" to open a new image
|
'o' to open a new image
|
||||||
"r" to rotate
|
'r' to rotate
|
||||||
"i" to invert colors
|
'i' to invert colors
|
||||||
"s" to save the image
|
'f' to switch filter
|
||||||
"q" to quit
|
'b' to toggle the bar
|
||||||
|
's' to save the image
|
||||||
|
'q' to quit
|
||||||
|
|
||||||
|
'y' or 'c' to yank
|
||||||
|
'p' or 'v' to put
|
||||||
|
|
|
||||||
160
src/utils.rs
160
src/utils.rs
|
|
@ -1,150 +1,84 @@
|
||||||
use std::{
|
use std::{
|
||||||
|
borrow::Cow,
|
||||||
ffi::OsStr,
|
ffi::OsStr,
|
||||||
fs,
|
|
||||||
io::Write,
|
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
use image::{DynamicImage, ImageDecoder, ImageReader, RgbaImage};
|
use iced::widget;
|
||||||
use jpegxl_rs::image::ToDynamic;
|
use image::{DynamicImage, ImageDecoder, ImageReader, ImageResult, RgbaImage};
|
||||||
use rfd::FileDialog;
|
use rfd::AsyncFileDialog;
|
||||||
|
|
||||||
pub fn load_image(path: impl AsRef<Path>) -> Result<RgbaImage, String> {
|
pub fn load_image(path: impl AsRef<Path>) -> Result<RgbaImage, String> {
|
||||||
let path = path.as_ref();
|
load_image_impl(path).map_err(|e| e.to_string())
|
||||||
|
|
||||||
let decoded_image = match path.extension().map(OsStr::to_string_lossy).as_deref() {
|
|
||||||
Some("jxl") => {
|
|
||||||
let data = match std::fs::read(path) {
|
|
||||||
Ok(d) => d,
|
|
||||||
Err(e) => {
|
|
||||||
return Err(format!(
|
|
||||||
"failed to read data from '{}': {e}",
|
|
||||||
path.display()
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
};
|
fn load_image_impl(path: impl AsRef<Path>) -> ImageResult<RgbaImage> {
|
||||||
|
let mut decoder = ImageReader::open(&path)?
|
||||||
|
.with_guessed_format()?
|
||||||
|
.into_decoder()?;
|
||||||
|
|
||||||
match jpegxl_rs::decoder_builder()
|
let oreintation = decoder.orientation()?;
|
||||||
.build()
|
|
||||||
.unwrap()
|
let mut decoded_image = DynamicImage::from_decoder(decoder)?;
|
||||||
.decode_to_image(&data)
|
|
||||||
|
// the condition is a workaround to not rotate JXL images twice;
|
||||||
|
// since they are already rotated by the decoder
|
||||||
|
// (while jpegs for instance aren't)
|
||||||
|
if !path
|
||||||
|
.as_ref()
|
||||||
|
.extension()
|
||||||
|
.map(OsStr::to_string_lossy)
|
||||||
|
.is_some_and(|s| s == "jxl")
|
||||||
{
|
{
|
||||||
Ok(Some(decoded_image)) => decoded_image,
|
|
||||||
Ok(None) => {
|
|
||||||
return Err(format!(
|
|
||||||
"failed to convert jxl '{}' to DynamicImage",
|
|
||||||
path.display()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
return Err(format!("failed to decode jxl '{}': {e}", path.display()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => {
|
|
||||||
let reader = match ImageReader::open(path) {
|
|
||||||
Ok(r) => r,
|
|
||||||
Err(e) => {
|
|
||||||
return Err(format!(
|
|
||||||
"failed to create reader for '{}': {e}",
|
|
||||||
path.display()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut decoder = match reader.into_decoder() {
|
|
||||||
Ok(d) => d,
|
|
||||||
Err(e) => {
|
|
||||||
return Err(format!(
|
|
||||||
"failed to create decoder for '{}': {e}",
|
|
||||||
path.display()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let oreintation = match decoder.orientation() {
|
|
||||||
Ok(o) => o,
|
|
||||||
Err(e) => {
|
|
||||||
return Err(format!(
|
|
||||||
"failed to get oreintation of '{}': {e}",
|
|
||||||
path.display()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut decoded_image = match DynamicImage::from_decoder(decoder) {
|
|
||||||
Ok(i) => i,
|
|
||||||
Err(e) => {
|
|
||||||
return Err(format!("failed to decode image '{}': {e}", path.display()));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
decoded_image.apply_orientation(oreintation);
|
decoded_image.apply_orientation(oreintation);
|
||||||
|
|
||||||
decoded_image
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
Ok(decoded_image.into_rgba8())
|
Ok(decoded_image.into_rgba8())
|
||||||
}
|
}
|
||||||
pub fn pick_image() -> Result<PathBuf, String> {
|
pub async fn pick_image() -> Result<PathBuf, String> {
|
||||||
let Some(path) = FileDialog::new()
|
let Some(filehandle) = AsyncFileDialog::new()
|
||||||
.add_filter(
|
.add_filter(
|
||||||
"image",
|
"image",
|
||||||
&[
|
&[
|
||||||
"png", "PNG", "jpg", "JPG", "jpeg", "JPEG", "avif", "jxl", "bmp", "exr", "ff",
|
"png", "PNG", "jpg", "JPG", "jpeg", "JPEG", "avif", "jxl", "bmp", "exr", "ff",
|
||||||
"gif", "hdr", "ico", "pnm", "qoi", "tga", "tiff", "webp",
|
"gif", "hdr", "ico", "pnm", "qoi", "tga", "tiff", "webp", "kra",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
.pick_file()
|
.pick_file()
|
||||||
|
.await
|
||||||
else {
|
else {
|
||||||
return Err("no path to open provided".into());
|
return Err("no path to open provided".into());
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(path)
|
Ok(filehandle.path().to_owned())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save_image(image: Option<&RgbaImage>) -> Result<(), String> {
|
pub async fn pick_save_path() -> Result<PathBuf, String> {
|
||||||
let Some(image) = image else {
|
let Some(filehandle) = AsyncFileDialog::new().save_file().await else {
|
||||||
return Err("no image to save".into());
|
|
||||||
};
|
|
||||||
|
|
||||||
let Some(path) = FileDialog::new().save_file() else {
|
|
||||||
return Err("no path to save provided".into());
|
return Err("no path to save provided".into());
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut file = match fs::File::create(&path) {
|
Ok(filehandle.path().to_owned())
|
||||||
Ok(f) => f,
|
}
|
||||||
Err(e) => return Err(format!("failed to create file '{}': {e}", path.display())),
|
|
||||||
};
|
|
||||||
|
|
||||||
match path.extension().map(OsStr::to_string_lossy).as_deref() {
|
pub const fn string_from_filter_type(f: widget::image::FilterMethod) -> &'static str {
|
||||||
Some("jxl") => {
|
match f {
|
||||||
let mut encoder = jpegxl_rs::encoder_builder()
|
widget::image::FilterMethod::Linear => "bilinear",
|
||||||
.speed(jpegxl_rs::encode::EncoderSpeed::Glacier)
|
widget::image::FilterMethod::Nearest => "nearest neighbor",
|
||||||
.lossless(true)
|
}
|
||||||
.build()
|
|
||||||
.unwrap();
|
|
||||||
let rgb_image = DynamicImage::from(image.to_owned()).into_rgb8();
|
|
||||||
let jxl =
|
|
||||||
match encoder.encode::<u8, u8>(&rgb_image, rgb_image.width(), rgb_image.height()) {
|
|
||||||
Ok(j) => j,
|
|
||||||
Err(e) => {
|
|
||||||
return Err(format!("failed to encode jxl '{}': {e}", path.display()));
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
if let Err(e) = file.write(&jxl.data) {
|
pub fn arboard_from_rgbaimage<'a>(image: &'a RgbaImage) -> arboard::ImageData<'a> {
|
||||||
return Err(format!("failed to write jxl to '{}': {e}", path.display()));
|
arboard::ImageData {
|
||||||
};
|
width: image.width() as usize,
|
||||||
|
height: image.height() as usize,
|
||||||
|
bytes: Cow::Borrowed(image.as_ref()),
|
||||||
}
|
}
|
||||||
_ => {
|
|
||||||
if let Err(e) = image.save(&path) {
|
|
||||||
return Err(format!("failed to save '{}': {e}", path.display()));
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
};
|
pub fn rgbaimage_from_arboard(image: arboard::ImageData) -> RgbaImage {
|
||||||
|
RgbaImage::from_raw(
|
||||||
Ok(())
|
image.width as u32,
|
||||||
|
image.height as u32,
|
||||||
|
image.bytes.into_owned(),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue