From de11767d3b4f5aa7c3380c7af1615097bfaf7e1a Mon Sep 17 00:00:00 2001 From: inorishio Date: Mon, 25 May 2026 23:15:00 +0200 Subject: [PATCH] zshell-img-tools crate reduction to 53, process release fix, blur-passes, scale impl, settings passes setting, scale only avail in config --- Config/Config.qml | 2 + Config/Screenshot.qml | 2 + Modules/Settings/Categories/Screenshot.qml | 13 + zshell-img-tools/Cargo.lock | 810 +-------------------- zshell-img-tools/Cargo.toml | 8 +- zshell-img-tools/README.md | 6 - zshell-img-tools/src/config.rs | 6 +- zshell-img-tools/src/effects.rs | 61 +- zshell-img-tools/src/main.rs | 119 +-- 9 files changed, 143 insertions(+), 884 deletions(-) delete mode 100644 zshell-img-tools/README.md diff --git a/Config/Config.qml b/Config/Config.qml index 2f6686e..6122fd5 100644 --- a/Config/Config.qml +++ b/Config/Config.qml @@ -293,10 +293,12 @@ Singleton { return { enable_pp: screenshot.enable_pp, mode: screenshot.mode, + scale: screenshot.scale, corner_radius: screenshot.corner_radius, drop_shadow: screenshot.drop_shadow, rounded_corners: screenshot.rounded_corners, shadow_blur_radius: screenshot.shadow_blur_radius, + shadow_blur_passes: screenshot.shadow_blur_passes, shadow_color: screenshot.shadow_color, shadow_offset_x: screenshot.shadow_offset_x, shadow_offset_y: screenshot.shadow_offset_y diff --git a/Config/Screenshot.qml b/Config/Screenshot.qml index 7ea47bc..793e1a8 100644 --- a/Config/Screenshot.qml +++ b/Config/Screenshot.qml @@ -6,6 +6,8 @@ JsonObject { property bool enable_pp: true property string mode: "manual" property bool rounded_corners: false + property real scale: 1.0 + property int shadow_blur_passes: 1 property real shadow_blur_radius: 22.0 property list shadow_color: [0, 0, 0, 160] property real shadow_offset_x: 5.0 diff --git a/Modules/Settings/Categories/Screenshot.qml b/Modules/Settings/Categories/Screenshot.qml index 3d69d93..ec7f3a5 100644 --- a/Modules/Settings/Categories/Screenshot.qml +++ b/Modules/Settings/Categories/Screenshot.qml @@ -105,6 +105,19 @@ SettingsPage { visible: Config.screenshot.mode === "manual" } + SettingSpinBox { + min: 1 + name: "Shadow passes" + object: Config.screenshot + setting: "shadow_blur_passes" + step: 1 + visible: Config.screenshot.mode === "manual" + } + + Separator { + visible: Config.screenshot.mode === "manual" + } + SettingSpinBox { min: 0 name: "Shadow offset X" diff --git a/zshell-img-tools/Cargo.lock b/zshell-img-tools/Cargo.lock index 85359cd..8c7321e 100644 --- a/zshell-img-tools/Cargo.lock +++ b/zshell-img-tools/Cargo.lock @@ -8,47 +8,12 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" -[[package]] -name = "aligned" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee4508988c62edf04abd8d92897fca0c2995d907ce1dfeaf369dac3716a40685" -dependencies = [ - "as-slice", -] - -[[package]] -name = "aligned-vec" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" -dependencies = [ - "equator", -] - [[package]] name = "anyhow" version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" -[[package]] -name = "arbitrary" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" - -[[package]] -name = "arg_enum_proc_macro" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "arrayref" version = "0.3.9" @@ -61,103 +26,18 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" -[[package]] -name = "as-slice" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" -dependencies = [ - "stable_deref_trait", -] - [[package]] name = "autocfg" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" -[[package]] -name = "av-scenechange" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f321d77c20e19b92c39e7471cf986812cbb46659d2af674adc4331ef3f18394" -dependencies = [ - "aligned", - "anyhow", - "arg_enum_proc_macro", - "arrayvec", - "log", - "num-rational", - "num-traits", - "pastey", - "rayon", - "thiserror", - "v_frame", - "y4m", -] - -[[package]] -name = "av1-grain" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cfddb07216410377231960af4fcab838eaa12e013417781b78bd95ee22077f8" -dependencies = [ - "anyhow", - "arrayvec", - "log", - "nom", - "num-rational", - "v_frame", -] - -[[package]] -name = "avif-serialize" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375082f007bd67184fb9c0374614b29f9aaa604ec301635f72338bb65386a53d" -dependencies = [ - "arrayvec", -] - -[[package]] -name = "bit_field" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bitflags" version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" -[[package]] -name = "bitstream-io" -version = "4.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eff00be299a18769011411c9def0d827e8f2d7bf0c3dbf53633147a8867fd1f" -dependencies = [ - "no_std_io2", -] - -[[package]] -name = "built" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4ad8f11f288f48ca24471bbd51ac257aaeaaa07adae295591266b792902ae64" - -[[package]] -name = "bumpalo" -version = "3.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" - [[package]] name = "bytemuck" version = "1.25.0" @@ -170,30 +50,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" -[[package]] -name = "cc" -version = "1.2.61" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" -dependencies = [ - "find-msvc-tools", - "jobserver", - "libc", - "shlex", -] - [[package]] name = "cfg-if" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" -[[package]] -name = "color_quant" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" - [[package]] name = "crc32fast" version = "1.5.0" @@ -203,84 +65,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "crossbeam-deque" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - -[[package]] -name = "crunchy" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" - -[[package]] -name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" - -[[package]] -name = "equator" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" -dependencies = [ - "equator-macro", -] - -[[package]] -name = "equator-macro" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "exr" -version = "1.74.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4300e043a56aa2cb633c01af81ca8f699a321879a7854d3896a0ba89056363be" -dependencies = [ - "bit_field", - "half", - "lebe", - "miniz_oxide", - "rayon-core", - "smallvec", - "zune-inflate", -] - -[[package]] -name = "fax" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caf1079563223d5d59d83c85886a56e586cfd5c1a26292e971a0fa266531ac5a" - [[package]] name = "fdeflate" version = "0.3.7" @@ -290,12 +74,6 @@ dependencies = [ "simd-adler32", ] -[[package]] -name = "find-msvc-tools" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" - [[package]] name = "flate2" version = "1.1.9" @@ -306,39 +84,6 @@ dependencies = [ "miniz_oxide", ] -[[package]] -name = "getrandom" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" -dependencies = [ - "cfg-if", - "libc", - "r-efi", - "wasip2", -] - -[[package]] -name = "gif" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee8cfcc411d9adbbaba82fb72661cc1bcca13e8bba98b364e62b2dba8f960159" -dependencies = [ - "color_quant", - "weezl", -] - -[[package]] -name = "half" -version = "2.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" -dependencies = [ - "cfg-if", - "crunchy", - "zerocopy", -] - [[package]] name = "image" version = "0.25.10" @@ -347,56 +92,9 @@ checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" dependencies = [ "bytemuck", "byteorder-lite", - "color_quant", - "exr", - "gif", - "image-webp", "moxcms", "num-traits", - "png 0.18.1", - "qoi", - "ravif", - "rayon", - "rgb", - "tiff", - "zune-core", - "zune-jpeg", -] - -[[package]] -name = "image-webp" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3" -dependencies = [ - "byteorder-lite", - "quick-error", -] - -[[package]] -name = "imgref" -version = "1.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40fac9d56ed6437b198fddba683305e8e2d651aa42647f00f5ae542e7f5c94a2" - -[[package]] -name = "interpolate_name" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "itertools" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" -dependencies = [ - "either", + "png", ] [[package]] @@ -405,63 +103,12 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" -[[package]] -name = "jobserver" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" -dependencies = [ - "getrandom", - "libc", -] - -[[package]] -name = "lebe" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" - -[[package]] -name = "libc" -version = "0.2.186" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" - -[[package]] -name = "libfuzzer-sys" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f12a681b7dd8ce12bff52488013ba614b869148d54dd79836ab85aafdd53f08d" -dependencies = [ - "arbitrary", - "cc", -] - [[package]] name = "log" version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" -[[package]] -name = "loop9" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" -dependencies = [ - "imgref", -] - -[[package]] -name = "maybe-rayon" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" -dependencies = [ - "cfg-if", - "rayon", -] - [[package]] name = "memchr" version = "2.8.0" @@ -488,77 +135,6 @@ dependencies = [ "pxfm", ] -[[package]] -name = "new_debug_unreachable" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" - -[[package]] -name = "no_std_io2" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b51ed7824b6e07d354605f4abb3d9d300350701299da96642ee084f5ce631550" -dependencies = [ - "memchr", -] - -[[package]] -name = "nom" -version = "8.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" -dependencies = [ - "memchr", -] - -[[package]] -name = "noop_proc_macro" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-derive" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[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-rational" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -568,59 +144,19 @@ dependencies = [ "autocfg", ] -[[package]] -name = "once_cell" -version = "1.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" - -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - -[[package]] -name = "pastey" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec" - -[[package]] -name = "png" -version = "0.17.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" -dependencies = [ - "bitflags 1.3.2", - "crc32fast", - "fdeflate", - "flate2", - "miniz_oxide", -] - [[package]] name = "png" version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" dependencies = [ - "bitflags 2.11.1", + "bitflags", "crc32fast", "fdeflate", "flate2", "miniz_oxide", ] -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] - [[package]] name = "proc-macro2" version = "1.0.106" @@ -630,46 +166,12 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "profiling" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" -dependencies = [ - "profiling-procmacros", -] - -[[package]] -name = "profiling-procmacros" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b" -dependencies = [ - "quote", - "syn", -] - [[package]] name = "pxfm" version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0c5ccf5294c6ccd63a74f1565028353830a9c2f5eb0c682c355c471726a6e3f" -[[package]] -name = "qoi" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "quick-error" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" - [[package]] name = "quote" version = "1.0.45" @@ -679,123 +181,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "r-efi" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" - -[[package]] -name = "rand" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" -dependencies = [ - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rav1e" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43b6dd56e85d9483277cde964fd1bdb0428de4fec5ebba7540995639a21cb32b" -dependencies = [ - "aligned-vec", - "arbitrary", - "arg_enum_proc_macro", - "arrayvec", - "av-scenechange", - "av1-grain", - "bitstream-io", - "built", - "cfg-if", - "interpolate_name", - "itertools", - "libc", - "libfuzzer-sys", - "log", - "maybe-rayon", - "new_debug_unreachable", - "noop_proc_macro", - "num-derive", - "num-traits", - "paste", - "profiling", - "rand", - "rand_chacha", - "simd_helpers", - "thiserror", - "v_frame", - "wasm-bindgen", -] - -[[package]] -name = "ravif" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e52310197d971b0f5be7fe6b57530dcd27beb35c1b013f29d66c1ad73fbbcc45" -dependencies = [ - "avif-serialize", - "imgref", - "loop9", - "quick-error", - "rav1e", - "rayon", - "rgb", -] - -[[package]] -name = "rayon" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "rgb" -version = "0.8.53" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b34b781b31e5d73e9fbc8689c70551fd1ade9a19e3e28cfec8580a79290cc4" - -[[package]] -name = "rustversion" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" - [[package]] name = "serde" version = "1.0.228" @@ -839,39 +224,12 @@ dependencies = [ "zmij", ] -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - [[package]] name = "simd-adler32" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" -[[package]] -name = "simd_helpers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" -dependencies = [ - "quote", -] - -[[package]] -name = "smallvec" -version = "1.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" - -[[package]] -name = "stable_deref_trait" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" - [[package]] name = "strict-num" version = "0.1.1" @@ -889,40 +247,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "thiserror" -version = "2.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "2.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tiff" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b63feaf3343d35b6ca4d50483f94843803b0f51634937cc2ec519fc32232bc52" -dependencies = [ - "fax", - "flate2", - "half", - "quick-error", - "weezl", - "zune-jpeg", -] - [[package]] name = "tiny-skia" version = "0.11.4" @@ -934,7 +258,6 @@ dependencies = [ "bytemuck", "cfg-if", "log", - "png 0.17.16", "tiny-skia-path", ] @@ -955,109 +278,6 @@ version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" -[[package]] -name = "v_frame" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "666b7727c8875d6ab5db9533418d7c764233ac9c0cff1d469aec8fa127597be2" -dependencies = [ - "aligned-vec", - "num-traits", - "wasm-bindgen", -] - -[[package]] -name = "wasip2" -version = "1.0.3+wasi-0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" -dependencies = [ - "wit-bindgen", -] - -[[package]] -name = "wasm-bindgen" -version = "0.2.120" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df52b6d9b87e0c74c9edfa1eb2d9bf85e5d63515474513aa50fa181b3c4f5db1" -dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.120" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b1041f495fb322e64aca85f5756b2172e35cd459376e67f2a6c9dffcedb103" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.120" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dcd0ff20416988a18ac686d4d4d0f6aae9ebf08a389ff5d29012b05af2a1b41" -dependencies = [ - "bumpalo", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.120" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49757b3c82ebf16c57d69365a142940b384176c24df52a087fb748e2085359ea" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "weezl" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" - -[[package]] -name = "wit-bindgen" -version = "0.57.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" - -[[package]] -name = "y4m" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5a4b21e1a62b67a2970e6831bc091d7b87e119e7f9791aef9702e3bef04448" - -[[package]] -name = "zerocopy" -version = "0.8.48" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.48" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "zmij" version = "1.0.21" @@ -1066,7 +286,7 @@ checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" [[package]] name = "zshell-img-tools" -version = "0.1.0" +version = "0.2.0" dependencies = [ "anyhow", "image", @@ -1074,27 +294,3 @@ dependencies = [ "serde_json", "tiny-skia", ] - -[[package]] -name = "zune-core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" - -[[package]] -name = "zune-inflate" -version = "0.2.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" -dependencies = [ - "simd-adler32", -] - -[[package]] -name = "zune-jpeg" -version = "0.5.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296" -dependencies = [ - "zune-core", -] diff --git a/zshell-img-tools/Cargo.toml b/zshell-img-tools/Cargo.toml index 95a19e1..52fde40 100644 --- a/zshell-img-tools/Cargo.toml +++ b/zshell-img-tools/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zshell-img-tools" -version = "0.1.0" +version = "0.2.0" edition = "2024" [[bin]] @@ -8,10 +8,10 @@ name = "zshell-img-tools" path = "src/main.rs" [dependencies] -image = { version = "0.25", features = ["png"] } -tiny-skia = "0.11" +image = { version = "0.25", default-features = false, features = ["png"] } +tiny-skia = { version = "0.11", default-features = false, features = ["std", "simd"] } serde = { version = "1", features = ["derive"] } -anyhow = "1" +anyhow = "1.0" serde_json = "1.0.149" [profile.release] diff --git a/zshell-img-tools/README.md b/zshell-img-tools/README.md deleted file mode 100644 index bbe4940..0000000 --- a/zshell-img-tools/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# What_That_Claude_DO? - -What That Claude Do? (WTCD) -A repository of random things I ask Claude to do for me. - -In this case it is creating a screenshot tool diff --git a/zshell-img-tools/src/config.rs b/zshell-img-tools/src/config.rs index 3b502f1..f9bcbb3 100644 --- a/zshell-img-tools/src/config.rs +++ b/zshell-img-tools/src/config.rs @@ -11,13 +11,15 @@ pub struct Config { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct EffectsConfig { pub mode: String, - pub rounded_corners: bool, pub corner_radius: f32, pub drop_shadow: bool, + pub rounded_corners: bool, + pub scale: f32, pub shadow_blur_radius: f32, + pub shadow_blur_passes: u32, + pub shadow_color: [u8; 4], pub shadow_offset_x: f32, pub shadow_offset_y: f32, - pub shadow_color: [u8; 4], } impl Config { diff --git a/zshell-img-tools/src/effects.rs b/zshell-img-tools/src/effects.rs index f79726f..fcdd236 100644 --- a/zshell-img-tools/src/effects.rs +++ b/zshell-img-tools/src/effects.rs @@ -16,6 +16,7 @@ pub fn apply_effects(img: RgbaImage, cfg: &EffectsConfig) -> RgbaImage { cfg.shadow_blur_radius, cfg.shadow_offset_x, cfg.shadow_offset_y, + cfg.shadow_blur_passes, cfg.shadow_color, ) } else { @@ -52,11 +53,16 @@ pub fn apply_drop_shadow( blur_radius: f32, offset_x: f32, offset_y: f32, + blur_passes: u32, shadow_color: [u8; 4], ) -> RgbaImage { let (iw, ih) = img.dimensions(); let br = blur_radius.ceil() as u32; - let spread = br * 2; + let bp = blur_passes; + // Original idea + // let spread = br * bp; + // Claude is hallucinating but let's try it **Worked btw** + let spread = (br as f32 * (bp as f32).sqrt() * 2.0).ceil() as u32; let extra_left = spread + (-offset_x).max(0.0).ceil() as u32; let extra_top = spread + (-offset_y).max(0.0).ceil() as u32; @@ -86,8 +92,11 @@ pub fn apply_drop_shadow( tint_pixmap_as_shadow(&mut shadow_pixmap, shadow_color); + // Shadow let shadow_img = pixmap_to_rgba_image(shadow_pixmap); - let blurred = box_blur_rgba(&shadow_img, br); + // Shadow blur + let blurred = box_blur_rgba(&shadow_img, br, bp); + // Shadow pos let blurred_pixmap = rgba_image_to_pixmap(&blurred); let mut canvas = Pixmap::new(canvas_w, canvas_h).expect("canvas pixmap"); @@ -136,6 +145,7 @@ fn rounded_rect_path(x: f32, y: f32, w: f32, h: f32, r: f32) -> Path { pb.finish().expect("rounded rect path") } +// Shadow pos fn rgba_image_to_pixmap(img: &RgbaImage) -> Pixmap { let (w, h) = img.dimensions(); let mut pixmap = Pixmap::new(w, h).expect("pixmap alloc"); @@ -154,6 +164,7 @@ fn rgba_image_to_pixmap(img: &RgbaImage) -> Pixmap { pixmap } +// Shadow fn pixmap_to_rgba_image(pixmap: Pixmap) -> RgbaImage { let (w, h) = (pixmap.width(), pixmap.height()); let mut out = RgbaImage::new(w, h); @@ -176,31 +187,16 @@ fn pixmap_to_rgba_image(pixmap: Pixmap) -> RgbaImage { out } -fn tint_pixmap_as_shadow(pixmap: &mut Pixmap, color: [u8; 4]) { - let [sr, sg, sb, _] = color; - for px in pixmap.pixels_mut() { - let a = px.alpha(); - if a > 0 { - let af = a as f32 / 255.0; - *px = tiny_skia::PremultipliedColorU8::from_rgba( - (sr as f32 * af) as u8, - (sg as f32 * af) as u8, - (sb as f32 * af) as u8, - a, - ) - .unwrap_or(tiny_skia::PremultipliedColorU8::TRANSPARENT); - } - } -} - -fn box_blur_rgba(img: &RgbaImage, radius: u32) -> RgbaImage { +// Shadow blur +fn box_blur_rgba(img: &RgbaImage, radius: u32, bp: u32) -> RgbaImage { if radius == 0 { return img.clone(); } - let mut buf = sliding_horizontal(img, radius); - buf = sliding_vertical(&buf, radius); - buf = sliding_horizontal(&buf, radius); - buf = sliding_vertical(&buf, radius); + let mut buf = img.clone(); + for _ in 0..bp { + buf = sliding_horizontal(&buf, radius); + buf = sliding_vertical(&buf, radius); + } buf } @@ -250,6 +246,23 @@ fn sliding_horizontal(img: &RgbaImage, radius: u32) -> RgbaImage { out } +fn tint_pixmap_as_shadow(pixmap: &mut Pixmap, color: [u8; 4]) { + let [sr, sg, sb, _] = color; + for px in pixmap.pixels_mut() { + let a = px.alpha(); + if a > 0 { + let af = a as f32 / 255.0; + *px = tiny_skia::PremultipliedColorU8::from_rgba( + (sr as f32 * af) as u8, + (sg as f32 * af) as u8, + (sb as f32 * af) as u8, + a, + ) + .unwrap_or(tiny_skia::PremultipliedColorU8::TRANSPARENT); + } + } +} + fn sliding_vertical(img: &RgbaImage, radius: u32) -> RgbaImage { let (w, h) = img.dimensions(); let r = radius as i32; diff --git a/zshell-img-tools/src/main.rs b/zshell-img-tools/src/main.rs index 73c8d30..12c24d9 100644 --- a/zshell-img-tools/src/main.rs +++ b/zshell-img-tools/src/main.rs @@ -1,21 +1,21 @@ mod config; mod effects; -use anyhow::{Context, Result, bail}; +use anyhow::{bail, Context, Result}; use std::io::Write as _; use std::process::{Command, Stdio}; -/// CLI overrides that map 1:1 to `EffectsConfig` fields. -/// All fields are `Option` so we can tell "not supplied" from any concrete value. #[derive(Default)] struct CliOverrides { rounded_corners: Option, corner_radius: Option, drop_shadow: Option, + scale: Option, shadow_blur_radius: Option, + shadow_blur_passes: Option, shadow_offset_x: Option, shadow_offset_y: Option, - /// Accepted as four comma-separated u8 values, e.g. `255,0,0,200` + // Accepted as four comma-separated u8 values, e.g. `255,0,0,200` shadow_color: Option<[u8; 4]>, } @@ -30,24 +30,24 @@ fn parse_bool(s: &str) -> Result { fn parse_shadow_color(s: &str) -> Result<[u8; 4]> { let parts: Vec<&str> = s.split(',').collect(); if parts.len() != 4 { - bail!("--shadow_color expects four comma-separated u8 values, e.g. 255,0,0,200"); + bail!("--shadow-color expects four comma-separated u8 values, e.g. 255,0,0,200"); } let r = parts[0] .trim() .parse::() - .context("shadow_color red channel")?; + .context("shadow-color red channel")?; let g = parts[1] .trim() .parse::() - .context("shadow_color green channel")?; + .context("shadow-color green channel")?; let b = parts[2] .trim() .parse::() - .context("shadow_color blue channel")?; + .context("shadow-color blue channel")?; let a = parts[3] .trim() .parse::() - .context("shadow_color alpha channel")?; + .context("shadow-color alpha channel")?; Ok([r, g, b, a]) } @@ -68,67 +68,82 @@ fn main() -> Result<()> { .context("Expected a path after --image")?, ); } - "--rounded_corners" => { + "--rounded-corners" => { i += 1; let val = args .get(i) - .context("Expected true/false after --rounded_corners")?; + .context("Expected true/false after --rounded-corners")?; overrides.rounded_corners = Some(parse_bool(val)?); } - "--corner_radius" => { + "--corner-radius" => { i += 1; let val = args .get(i) - .context("Expected a number after --corner_radius")?; + .context("Expected a number after --corner-radius")?; overrides.corner_radius = Some( val.parse::() - .context("--corner_radius must be a number")?, + .context("--corner-radius must be a number")?, ); } - "--drop_shadow" => { + "--drop-shadow" => { i += 1; let val = args .get(i) - .context("Expected true/false after --drop_shadow")?; + .context("Expected true/false after --drop-shadow")?; overrides.drop_shadow = Some(parse_bool(val)?); } - "--shadow_blur_radius" => { + "--shadow-blur-radius" => { i += 1; let val = args .get(i) - .context("Expected a number after --shadow_blur_radius")?; + .context("Expected a number after --shadow-blur-radius")?; overrides.shadow_blur_radius = Some( val.parse::() - .context("--shadow_blur_radius must be a number")?, + .context("--shadow-blur-radius must be a number")?, ); } - "--shadow_offset_x" => { + "--shadow-offset-x" => { i += 1; let val = args .get(i) - .context("Expected a number after --shadow_offset_x")?; + .context("Expected a number after --shadow-offset-x")?; overrides.shadow_offset_x = Some( val.parse::() - .context("--shadow_offset_x must be a number")?, + .context("--shadow-offset-x must be a number")?, ); } - "--shadow_offset_y" => { + "--shadow-offset-y" => { i += 1; let val = args .get(i) - .context("Expected a number after --shadow_offset_y")?; + .context("Expected a number after --shadow-offset-y")?; overrides.shadow_offset_y = Some( val.parse::() - .context("--shadow_offset_y must be a number")?, + .context("--shadow-offset-y must be a number")?, ); } - "--shadow_color" => { + "--shadow-blur-passes" => { i += 1; let val = args .get(i) - .context("Expected r,g,b,a after --shadow_color")?; + .context("Expected a number after --shadow-blur-passes")?; + overrides.shadow_blur_passes = Some( + val.parse::() + .context("--shadow-blur-passes must be a number")?, + ); + } + "--shadow-color" => { + i += 1; + let val = args + .get(i) + .context("Expected r,g,b,a after --shadow-color")?; overrides.shadow_color = Some(parse_shadow_color(val)?); } + "--scale" => { + i += 1; + let val = args.get(i).context("Expected a number after --scale")?; + overrides.scale = Some(val.parse::().context("--scale must be a number")?); + } unknown => bail!("Unknown argument: {unknown}"), } i += 1; @@ -158,9 +173,22 @@ fn main() -> Result<()> { if let Some(v) = overrides.shadow_offset_y { effects.shadow_offset_y = v; } + if let Some(v) = overrides.shadow_blur_passes { + effects.shadow_blur_passes = v; + } if let Some(v) = overrides.shadow_color { effects.shadow_color = v; } + if let Some(v) = overrides.scale { + effects.scale = v; + } + } + + if effects.scale != 1.0 { + effects.corner_radius *= effects.scale; + effects.shadow_blur_radius *= effects.scale; + effects.shadow_offset_x *= effects.scale; + effects.shadow_offset_y *= effects.scale; } if let Err(e) = process_image(&image_path, &effects) { @@ -191,21 +219,30 @@ fn process_image(path: &str, effects: &config::EffectsConfig) -> Result<()> { .spawn() .context("Failed to spawn swappy. Is it installed and in PATH?")?; - child - .stdin - .take() - .context("Failed to get swappy stdin")? - .write_all(&png_bytes) - .context("Failed to write image data to swappy")?; - - let status = child.wait().context("Failed to wait for swappy")?; - - if !status.success() { - eprintln!( - "swappy exited with non-zero status for '{}': {}", - path, status - ); + // Writes the PNG bytes to swappy's stdin and then closes + if let Some(mut stdin) = child.stdin.take() { + stdin + .write_all(&png_bytes) + .context("Failed to write image data to swappy")?; } + // Writes the PNG bytes to swappy's stdin and waits for swappy to close + // child + // .stdin + // .take() + // .context("Failed to get swappy stdin")? + // .write_all(&png_bytes) + // .context("Failed to write image data to swappy")? + // .spawn(); + // + // let status = child.await().context("Failed to wait for swappy")?; + // + // if !status.success() { + // eprintln!( + // "swappy exited with non-zero status for '{}': {}", + // path, status + // ); + // } + Ok(()) }