From c0b31a9b31699589d2d19f91c5c7e106e2550bd6 Mon Sep 17 00:00:00 2001 From: Piyush Mishra Date: Thu, 24 Mar 2022 20:28:29 +0530 Subject: [PATCH] Lots of changes!!! Note: Still in alpha because we are using git as dependency Change Log: 1) Added support for webp 2) Added result ext to show error and warning dialogs 3) Image save extension is stored as enum now 4) Mime of image is also stored with the name of image 5) Different mime type images are being loaded with own loaders --- Cargo.lock | 367 ++++++++++++++++++++++++++++++++++++------- Cargo.toml | 8 +- src/about_window.rs | 18 +-- src/config.rs | 40 +---- src/config_window.rs | 12 +- src/crop_window.rs | 5 +- src/draw_thread.rs | 28 ++-- src/main.rs | 1 + src/main_window.rs | 38 +++-- src/result_ext.rs | 39 +++++ src/utils.rs | 194 +++++++++++++---------- 11 files changed, 513 insertions(+), 237 deletions(-) create mode 100644 src/result_ext.rs diff --git a/Cargo.lock b/Cargo.lock index 3485eff..ea70ae2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,6 +29,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "approx" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" +dependencies = [ + "num-traits", +] + [[package]] name = "atty" version = "0.2.14" @@ -46,6 +55,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +[[package]] +name = "bit_field" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4" + [[package]] name = "bitflags" version = "1.3.2" @@ -75,6 +90,19 @@ name = "cc" version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" +dependencies = [ + "jobserver", +] + +[[package]] +name = "cfb" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74f89d248799e3f15f91b70917f65381062a01bb8e222700ea0e5a7ff9785f9c" +dependencies = [ + "byteorder", + "uuid", +] [[package]] name = "cfg-if" @@ -228,12 +256,11 @@ checksum = "ef8ae57c4978a2acd8b869ce6b9ca1dfe817bff704c220209fdef2c0b75a01b9" [[package]] name = "deflate" -version = "0.8.6" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174" +checksum = "c86f7e25f518f4b81808a2cf1c50996a61f5c2eb394b2393bd87f2a4780a432f" dependencies = [ "adler32", - "byteorder", ] [[package]] @@ -262,6 +289,34 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +[[package]] +name = "exr" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4badb9489a465cb2c555af1f00f0bfd8cecd6fc12ac11da9d5b40c5dd5f0200" +dependencies = [ + "bit_field", + "deflate", + "flume", + "half", + "inflate", + "lebe", + "smallvec", + "threadpool", +] + +[[package]] +name = "flate2" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" +dependencies = [ + "cfg-if", + "crc32fast", + "libc", + "miniz_oxide 0.4.4", +] + [[package]] name = "fltk" version = "1.2.26" @@ -295,6 +350,31 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "flume" +version = "0.10.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b279436a715a9de95dcd26b151db590a71961cc06e54918b24fe0dd5b7d3fc4" +dependencies = [ + "futures-core", + "futures-sink", + "nanorand", + "pin-project", + "spin", +] + +[[package]] +name = "futures-core" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" + +[[package]] +name = "futures-sink" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" + [[package]] name = "getrandom" version = "0.1.16" @@ -313,8 +393,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi 0.10.2+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] @@ -327,6 +409,12 @@ dependencies = [ "weezl", ] +[[package]] +name = "half" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" + [[package]] name = "hashbrown" version = "0.11.2" @@ -350,15 +438,16 @@ dependencies = [ [[package]] name = "image" -version = "0.23.14" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1" +checksum = "db207d030ae38f1eb6f240d5a1c1c88ff422aa005d10f8c6c6fc5e75286ab30e" dependencies = [ "bytemuck", "byteorder", "color_quant", + "exr", "gif", - "jpeg-decoder", + "jpeg-decoder 0.2.2", "num-iter", "num-rational", "num-traits", @@ -370,17 +459,17 @@ dependencies = [ [[package]] name = "imageproc" version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7923654f3ce7cb6849d5dc9e544aaeab49c508a90b56c721b046e7234c74ab53" +source = "git+https://github.com/image-rs/imageproc#b7942657b1a370fc485507693ed4df1f8a116cb7" dependencies = [ + "approx", "conv", "image", "itertools", - "num 0.3.1", + "nalgebra", + "num", "rand", "rand_distr", "rayon", - "rulinalg", "rusttype", ] @@ -395,10 +484,28 @@ dependencies = [ ] [[package]] -name = "itertools" -version = "0.9.0" +name = "infer" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" +checksum = "20b2b533137b9cad970793453d4f921c2e91312a6d88b1085c07bc15fc51bb3b" +dependencies = [ + "cfb", +] + +[[package]] +name = "inflate" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff" +dependencies = [ + "adler32", +] + +[[package]] +name = "itertools" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" dependencies = [ "either", ] @@ -409,11 +516,26 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +[[package]] +name = "jobserver" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" +dependencies = [ + "libc", +] + [[package]] name = "jpeg-decoder" version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2" + +[[package]] +name = "jpeg-decoder" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "105fb082d64e2100074587f59a74231f771750c664af903f1f9f76c9dedfc6f1" dependencies = [ "rayon", ] @@ -433,12 +555,36 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lebe" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7efd1d698db0759e6ef11a7cd44407407399a910c774dd804c64c032da7826ff" + [[package]] name = "libc" version = "0.2.112" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" +[[package]] +name = "libwebp-sys" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439fd1885aa28937e7edcd68d2e793cb4a22f8733460d2519fbafd2b215672bf" +dependencies = [ + "cc", +] + +[[package]] +name = "lock_api" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" +dependencies = [ + "scopeguard", +] + [[package]] name = "log" version = "0.4.14" @@ -450,9 +596,9 @@ dependencies = [ [[package]] name = "matrixmultiply" -version = "0.1.15" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcad67dcec2d58ff56f6292582377e6921afdf3bfbd533e26fb8900ae575e002" +checksum = "add85d4dd35074e6fedc608f8c8f513a3548619a9024b751949ef0e8e45a4d84" dependencies = [ "rawpointer", ] @@ -472,15 +618,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "miniz_oxide" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435" -dependencies = [ - "adler32", -] - [[package]] name = "miniz_oxide" version = "0.4.4" @@ -492,21 +629,43 @@ dependencies = [ ] [[package]] -name = "num" -version = "0.1.42" +name = "miniz_oxide" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" +checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082" dependencies = [ - "num-integer", - "num-iter", + "adler", +] + +[[package]] +name = "nalgebra" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb2d0de08694bed883320212c18ee3008576bfe8c306f4c3c4a58b4876998be" +dependencies = [ + "approx", + "matrixmultiply", + "num-complex", + "num-rational", "num-traits", + "simba", + "typenum", +] + +[[package]] +name = "nanorand" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "729eb334247daa1803e0a094d0a5c55711b85571179f5ec6e53eccfdf7008958" +dependencies = [ + "getrandom 0.2.3", ] [[package]] name = "num" -version = "0.3.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b7a8e9be5e039e2ff869df49155f1c06bd01ade2117ec783e56ab0932b67a8f" +checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" dependencies = [ "num-bigint", "num-complex", @@ -518,9 +677,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.3.3" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" dependencies = [ "autocfg", "num-integer", @@ -529,9 +688,9 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.3.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "747d632c0c558b87dbabbe6a82f3b4ae03720d0646ac5b7b4dae89394be5f2c5" +checksum = "26873667bbbb7c5182d4a37c1add32cdf09f841af72da53318fdb81543c15085" dependencies = [ "num-traits", ] @@ -559,9 +718,9 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.3.2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" +checksum = "d41702bd167c2df5520b384281bc111a4b5efcf7fbc4c9c222c815b07e0a6a6a" dependencies = [ "autocfg", "num-bigint", @@ -613,20 +772,40 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5" [[package]] -name = "png" -version = "0.16.8" +name = "pin-project" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6" +checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "png" +version = "0.17.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc38c0ad57efb786dd57b9864e5b18bae478c00c824dc55a38bbc9da95dde3ba" dependencies = [ "bitflags", "crc32fast", "deflate", - "miniz_oxide 0.3.7", + "miniz_oxide 0.5.1", ] [[package]] name = "post_maker" -version = "0.3.0" +version = "0.4.0-alpha.1" dependencies = [ "clap", "dirs", @@ -634,6 +813,7 @@ dependencies = [ "fltk-theme", "image", "imageproc", + "infer", "lazy_static", "log", "rusttype", @@ -642,6 +822,7 @@ dependencies = [ "simplelog", "textwrap", "webbrowser", + "webp", ] [[package]] @@ -744,9 +925,9 @@ dependencies = [ [[package]] name = "rawpointer" -version = "0.1.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebac11a9d2e11f2af219b8b8d833b76b1ea0e054aa0e8d8e9e4cbde353bdf019" +checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" [[package]] name = "rayon" @@ -809,16 +990,6 @@ version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" -[[package]] -name = "rulinalg" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04ada202c9685e1d72a7420c578e92b358dbf807d3dfabb676a3dab9cc3bb12f" -dependencies = [ - "matrixmultiply", - "num 0.1.42", -] - [[package]] name = "rusttype" version = "0.9.2" @@ -835,6 +1006,15 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" +[[package]] +name = "safe_arch" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "794821e4ccb0d9f979512f9c1973480123f9bd62a90d74ab0f9426fcf8f4a529" +dependencies = [ + "bytemuck", +] + [[package]] name = "scoped_threadpool" version = "0.1.9" @@ -878,6 +1058,19 @@ dependencies = [ "serde", ] +[[package]] +name = "simba" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13a2609e876d4f77f6ab7ff5254fc39b4f1927ba8e6db3d18be7c32534d3725e" +dependencies = [ + "approx", + "num-complex", + "num-traits", + "paste", + "wide", +] + [[package]] name = "simplelog" version = "0.11.2" @@ -889,12 +1082,27 @@ dependencies = [ "termcolor", ] +[[package]] +name = "smallvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" + [[package]] name = "smawk" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f67ad224767faa3c7d8b6d91985b78e70a1324408abcb1cfcc2be4c06bc06043" +[[package]] +name = "spin" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "511254be0c5bcf062b019a6c89c01a664aa359ded62f78aa72c6fc137c0590e5" +dependencies = [ + "lock_api", +] + [[package]] name = "strsim" version = "0.10.0" @@ -933,13 +1141,22 @@ dependencies = [ ] [[package]] -name = "tiff" -version = "0.6.1" +name = "threadpool" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a53f4706d65497df0c4349241deddf35f84cee19c87ed86ea8ca590f4464437" +checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" dependencies = [ - "jpeg-decoder", - "miniz_oxide 0.4.4", + "num_cpus", +] + +[[package]] +name = "tiff" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0247608e998cb6ce39dfc8f4a16c50361ce71e5b52e6d24ea1227ea8ea8ee0b2" +dependencies = [ + "flate2", + "jpeg-decoder 0.1.22", "weezl", ] @@ -959,6 +1176,12 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e5d7cd7ab3e47dda6e56542f4bbf3824c15234958c6e1bd6aaa347e93499fdc" +[[package]] +name = "typenum" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" + [[package]] name = "unicode-linebreak" version = "0.1.2" @@ -980,6 +1203,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +[[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" + [[package]] name = "version_check" version = "0.9.4" @@ -1073,12 +1302,32 @@ dependencies = [ "winapi", ] +[[package]] +name = "webp" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf022f821f166079a407d000ab57e84de020e66ffbbf4edde999bc7d6e371cae" +dependencies = [ + "image", + "libwebp-sys", +] + [[package]] name = "weezl" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b77fdfd5a253be4ab714e4ffa3c49caf146b4de743e97510c0656cf90f1e8e" +[[package]] +name = "wide" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3aba2d1dac31ac7cae82847ac5b8be822aee8f99a4e100f279605016b185c5f" +dependencies = [ + "bytemuck", + "safe_arch", +] + [[package]] name = "widestring" version = "0.4.3" diff --git a/Cargo.toml b/Cargo.toml index 5288833..6dfe953 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "post_maker" -version = "0.3.0" +version = "0.4.0-alpha.1" edition = "2021" description = "Post Maker helps you to make post for Instagram and other Social Media apps easily." authors = ["PiyushXCoder "] @@ -16,12 +16,14 @@ log = "0.4" simplelog = "0.11" fltk = "1.2" fltk-theme = "0.4" -image = "0.23" -imageproc = "0.22" +image = "0.24.1" +imageproc = { git = "https://github.com/image-rs/imageproc"} +webp = "0.2" rusttype = "0.9" serde_json = "1.0" serde = { version = "1.0", features = ["derive"] } lazy_static = "1.4" dirs = "4.0" +infer = "0.7.0" textwrap = "0.14" webbrowser = "0.5" diff --git a/src/about_window.rs b/src/about_window.rs index 90e3d5e..0cea209 100644 --- a/src/about_window.rs +++ b/src/about_window.rs @@ -13,11 +13,10 @@ */ //! About Window -use crate::{config, globals}; +use crate::{config, globals, result_ext::ResultExt}; use fltk::{ app, button::Button, - dialog, enums::{self, Align, Event}, frame::Frame, group::Flex, @@ -152,10 +151,7 @@ impl About { // Repository Link self.repo_link.handle(|_, ev| { if ev == Event::Push { - if let Err(e) = webbrowser::open(env!("CARGO_PKG_REPOSITORY")) { - dialog::alert_default("Failed to open the link!"); - warn!("Failed to open the link!\n{:?}", e); - } + webbrowser::open(env!("CARGO_PKG_REPOSITORY")).warn_log("Failed to open the link!"); } true }); @@ -163,10 +159,7 @@ impl About { // Developer's Link self.dev_link.handle(|_, ev| { if ev == Event::Push { - if let Err(e) = webbrowser::open("https://piyushxcoder.in") { - dialog::alert_default("Failed to open the link!"); - warn!("Failed to open the link!\n{:?}", e); - } + webbrowser::open("https://piyushxcoder.in").warn_log("Failed to open the link!"); } true }); @@ -174,10 +167,7 @@ impl About { // License Link self.license_link.handle(|_, ev| { if ev == Event::Push { - if let Err(e) = webbrowser::open("https://www.gnu.org/licenses/gpl-3.0.html") { - dialog::alert_default("Failed to open the link!"); - warn!("Failed to open the link!\n{:?}", e); - } + webbrowser::open("https://www.gnu.org/licenses/gpl-3.0.html").warn_log("Failed to open the link!"); } true }); diff --git a/src/config.rs b/src/config.rs index e03260a..fc837b0 100644 --- a/src/config.rs +++ b/src/config.rs @@ -13,7 +13,7 @@ */ //! load, save configuration and parse cli args -use crate::{config_picker::ConfigPicker, globals}; +use crate::{config_picker::ConfigPicker, globals, result_ext::ResultExt, utils::ImageType}; use clap::{ArgEnum, Parser}; use fltk::dialog; use fltk_theme::ThemeType; @@ -128,7 +128,7 @@ pub(crate) struct ConfigFile { pub(crate) tag2_position_ratio: f64, pub(crate) image_ratio: (f64, f64), pub(crate) color_layer: [u8; 4], - pub(crate) image_format: String, + pub(crate) image_format: ImageType, } impl Default for ConfigFile { @@ -151,7 +151,7 @@ impl Default for ConfigFile { tag2_position_ratio: 0.95, image_ratio: (4.0, 5.0), color_layer: [20, 22, 25, 197], - image_format: "png".to_owned(), + image_format: ImageType::Png, } } } @@ -207,28 +207,10 @@ pub(crate) fn get_configs() -> Option> { /// Save configs pub(crate) fn save_configs(configs: HashMap) { - if let Err(e) = std::fs::write(&*CONFIG_FILE, serde_json::to_string(&configs).unwrap()) { - dialog::alert_default("Can't write config!"); - error!("Can't write config!\n{:?}", e); - panic!("Can't write config!\n{:?}", e); - } + std::fs::write(&*CONFIG_FILE, serde_json::to_string(&configs).unwrap()).expect_log("Can't write config!"); } pub(crate) fn log_file() -> File { - // match File::open(&*LOG_FILE) { - // Ok(mut file) => { - // if is_file_30_days_old(&file) { - // match File::create(&*LOG_FILE) { - // Ok(f) => file = f, - // Err(e) => { - // dialog::alert_default("Can't open log file!"); - // panic!("{:?}", e); - // } - // } - // } - // file - // } - // Err(_) => match File::create(&*LOG_FILE) { Ok(f) => f, Err(e) => { @@ -236,18 +218,4 @@ pub(crate) fn log_file() -> File { panic!("{:?}", e); } } - // } } - -// pub(crate) fn is_file_30_days_old(file: &File) -> bool { -// if let Ok(meta) = file.metadata() { -// if let Ok(time) = meta.created() { -// if let Ok(dur) = SystemTime::now().duration_since(time) { -// if dur > Duration::from_secs(60 * 60 * 24 * 30) { -// return true; -// } -// } -// } -// } -// false -// } diff --git a/src/config_window.rs b/src/config_window.rs index 7e2f689..8460693 100644 --- a/src/config_window.rs +++ b/src/config_window.rs @@ -33,7 +33,7 @@ use fltk::{ use crate::{ config::{self, ConfigFile}, - globals, utils, + globals, utils::{self, ImageType}, }; pub(crate) struct ConfigWindow { @@ -505,12 +505,12 @@ impl ConfigWindow { self.translucent_layer_alpha .set_value(config.color_layer[3] as f64); - match config.image_format.as_str() { - "png" => { + match config.image_format { + utils::ImageType::Png => { self.png_format.set_value(true); self.jpeg_format.set_value(false) } - "jpg" => { + utils::ImageType::Jpeg => { self.png_format.set_value(false); self.jpeg_format.set_value(true) } @@ -1063,7 +1063,7 @@ impl ConfigWindow { .borrow_mut() .get_mut(&browse.selected_text().unwrap()) { - conf.image_format = "png".to_owned(); + conf.image_format = ImageType::Png; } }); @@ -1075,7 +1075,7 @@ impl ConfigWindow { .borrow_mut() .get_mut(&browse.selected_text().unwrap()) { - conf.image_format = "jpg".to_owned(); + conf.image_format = ImageType::Jpeg; } }); diff --git a/src/crop_window.rs b/src/crop_window.rs index 7670ec4..f54481f 100644 --- a/src/crop_window.rs +++ b/src/crop_window.rs @@ -15,7 +15,7 @@ //! Window to change Crop properties of image use crate::{ globals, - utils::{self, Coord, ImageContainer, ImageProperties}, + utils::{self, Coord, ImageContainer, ImageProperties, ImageInfo}, }; use fltk::{ app, button::Button, draw, enums::Event, frame::Frame, group::Flex, image::SvgImage, @@ -24,7 +24,6 @@ use fltk::{ use image::GenericImageView; use std::{ cell::RefCell, - path::PathBuf, rc::Rc, sync::{Arc, RwLock}, }; @@ -108,7 +107,7 @@ impl CropWindow { /// Call it to show window to crop image pub(crate) fn load_to_crop( &mut self, - path: &PathBuf, + path: &ImageInfo, crop_pos: Option<(f64, f64)>, ) -> Option<(f64, f64)> { let mut container = diff --git a/src/draw_thread.rs b/src/draw_thread.rs index ed187c0..e88ac22 100644 --- a/src/draw_thread.rs +++ b/src/draw_thread.rs @@ -14,7 +14,8 @@ //! Thread to manage drawing in background -use crate::utils::{ImageContainer, ImageProperties}; +use crate::result_ext::ResultExt; +use crate::utils::{ImageContainer, ImageProperties, ImageInfo}; use crate::{ main_window::{MainWindow, Page}, utils::{self, ImagePropertiesFile}, @@ -33,7 +34,7 @@ use fltk::{ }; use std::{ fs, - path::{Path, PathBuf}, + path::{Path}, sync::{mpsc, Arc, RwLock}, }; @@ -85,7 +86,7 @@ pub(crate) fn spawn_image_thread( let mut status = main_win.status.clone(); let mut count = main_win.count.clone(); let mut dimension = main_win.dimension.clone(); - let images_path = Arc::clone(&main_win.images_path); + let images_path = Arc::clone(&main_win.images_list); let mut _container: Option = None; std::thread::spawn(move || loop { @@ -179,13 +180,13 @@ pub(crate) fn spawn_image_thread( if let Some(cont) = &mut _container { status.set_label("Cloning..."); win.deactivate(); - if let Some(path) = cont.clone_img() { + if let Some(image_info) = cont.clone_img() { let idx = file_choice.value(); let mut imgs = images_path.write().unwrap(); - imgs.insert(idx as usize, path.clone()); + imgs.insert(idx as usize, image_info.clone()); file_choice.insert( idx, - path.file_name().unwrap().to_str().unwrap(), + image_info.path.file_name().unwrap().to_str().unwrap(), enums::Shortcut::None, menu::MenuFlag::Normal, |a| a.do_callback(), @@ -225,7 +226,7 @@ pub(crate) fn spawn_image_thread( /// Loads the selected image in file_choice to ImageContainer to edit fn load_image( file_choice: &mut menu::Choice, - images_path: Arc>>, + images_list: Arc>>, crop: Option<(f64, f64)>, quote: &mut MultilineInput, subquote: &mut MultilineInput, @@ -251,19 +252,19 @@ fn load_image( properties: Arc>, container: &mut Option, ) { - let imgs = images_path.read().unwrap(); + let imgs = images_list.read().unwrap(); if imgs.len() == 0 { *container = None; flush_buffer(app_sender, container); return; } count.set_label(&format!("[{}/{}]", file_choice.value() + 1, imgs.len())); - let file = imgs.get(file_choice.value() as usize).unwrap(); + let image_info = imgs.get(file_choice.value() as usize).unwrap(); - *container = Some(ImageContainer::new(&file, Arc::clone(&properties))); + *container = Some(ImageContainer::new(&image_info, Arc::clone(&properties))); if let Some(cont) = container { - let file = Path::new(&file); + let file = Path::new(&image_info.path); let properties_file = file.with_extension("prop"); let read = fs::read_to_string(&properties_file).unwrap_or("{}".to_owned()); @@ -273,10 +274,7 @@ fn load_image( warn!("Config is corrupt\n{:?}", e); match dialog::choice_default("Config is corrupt, fix??", "yes", "no", "") { 1 => { - if let Err(e) = fs::remove_file(&properties_file) { - dialog::alert_default("Failed to delete image properties file!"); - warn!("Failed to delete image properties file!\n{:?}", e); - } + fs::remove_file(&properties_file).warn_log("Failed to delete image properties file!"); ImagePropertiesFile::default() } _ => return, diff --git a/src/main.rs b/src/main.rs index a1b481e..b98796b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -26,6 +26,7 @@ mod draw_thread; mod globals; mod main_window; mod utils; +mod result_ext; use fltk::{ app::{channel, App}, diff --git a/src/main_window.rs b/src/main_window.rs index c47ea85..13eea25 100644 --- a/src/main_window.rs +++ b/src/main_window.rs @@ -16,7 +16,10 @@ use crate::about_window::About; use crate::crop_window::CropWindow; use crate::draw_thread::*; +use crate::result_ext::ResultExt; use crate::utils; +use crate::utils::ImageInfo; +use crate::utils::ImageType; use crate::utils::ImageProperties; use crate::{config_window::ConfigWindow, globals}; use fltk::{ @@ -38,7 +41,7 @@ use fltk::{ }; use std::path::PathBuf; use std::sync::{mpsc, RwLock}; -use std::{ffi::OsStr, fs, sync::Arc}; +use std::{ fs, sync::Arc}; pub(crate) struct MainWindow { pub(crate) win: Window, @@ -81,7 +84,7 @@ pub(crate) struct MainWindow { pub(crate) count: Frame, pub(crate) dimension: Frame, pub(crate) page: Page, - pub(crate) images_path: Arc>>, + pub(crate) images_list: Arc>>, pub(crate) draw_buff: Arc>>>, pub(crate) properties: Arc>, pub(crate) sender: mpsc::Sender, @@ -380,7 +383,7 @@ impl MainWindow { status, count, dimension, - images_path: Arc::new(RwLock::new(vec![])), + images_list: Arc::new(RwLock::new(vec![])), draw_buff, properties: Arc::clone(&properties), page: Page { @@ -401,7 +404,7 @@ impl MainWindow { fn menu(&mut self) { let mut file_choice = self.file_choice.clone(); let sender = self.sender.clone(); - let imgs = Arc::clone(&self.images_path); + let imgs = Arc::clone(&self.images_list); self.menubar.add( "&File/Open Folder...\t", Shortcut::Ctrl | 'o', @@ -418,8 +421,7 @@ impl MainWindow { let expost_dir = path.join("export"); if !expost_dir.exists() { if let Err(e) = fs::create_dir(expost_dir) { - fltk::dialog::alert_default("Failed to create export folder!"); - warn!("Failed to create export folder!\n{:?}", e); + Result::<(), _>::Err(e).warn_log("Failed to create export folder!"); return; } } @@ -492,10 +494,10 @@ impl MainWindow { // Resest Button for FileChoice let mut file_choice = self.file_choice.clone(); let sender = self.sender.clone(); - let imgs = Arc::clone(&self.images_path); + let imgs = Arc::clone(&self.images_list); self.reset_file_choice.set_callback(move |_| { let path = match imgs.read().unwrap().first() { - Some(path) => path.parent().unwrap().to_path_buf(), + Some(image_info) => image_info.path.parent().unwrap().to_path_buf(), None => return, }; load_dir(&path, Arc::clone(&imgs), &mut file_choice, &sender); @@ -662,8 +664,8 @@ impl MainWindow { let sender = self.sender.clone(); self.crop_btn.set_callback(move |_| { let mut prop = properties.write().unwrap(); - if let Some(path) = &prop.path { - if let Some((x, y)) = crop_win.load_to_crop(path, prop.crop_position) { + if let Some(image_info) = &prop.image_info { + if let Some((x, y)) = crop_win.load_to_crop(&image_info, prop.crop_position) { sender.send(DrawMessage::ChangeCrop((x, y))).unwrap(); prop.is_saved = false; } @@ -1004,7 +1006,7 @@ impl MainWindow { /// Load all iamges in a directory fn load_dir( path: &PathBuf, - imgs: Arc>>, + imgs: Arc>>, file_choice: &mut menu::Choice, sender: &mpsc::Sender, ) { @@ -1018,11 +1020,15 @@ fn load_dir( *imgs_b = vec![]; for file in files { let path = file.path(); - if path.extension() == Some(OsStr::new("jpg")) - || path.extension() == Some(OsStr::new("png")) - { - text = format!("{}|{}", text, path.file_name().unwrap().to_str().unwrap()); - imgs_b.push(path); + if let Ok(Some(ty)) = infer::get_from_path(&path) { + let mime = ty.mime_type(); + match ImageType::from_mime(mime) { + ImageType::None => (), + _ => { + text = format!("{}|{}", text, path.file_name().unwrap().to_str().unwrap()); + imgs_b.push(ImageInfo { path, image_type: ImageType::from_mime(mime) }); + } + } } } if text.len() == 0 { diff --git a/src/result_ext.rs b/src/result_ext.rs new file mode 100644 index 0000000..dadb603 --- /dev/null +++ b/src/result_ext.rs @@ -0,0 +1,39 @@ +use std::fmt::Debug; +use std::panic::Location; +use fltk::dialog; + +pub trait ResultExt { + fn expect_log(self, msg: &str) -> T; + fn error_log(&self, msg: &str); + fn warn_log(&self, msg: &str); +} + +impl ResultExt for Result { + #[track_caller] + fn expect_log(self, msg: &str) -> T { + match self { + Ok(v) => v, + Err(e) => { + dialog::alert_default(msg); + error!("{}\n{:?}\n{}", msg, e, Location::caller()); + std::process::exit(1); + } + } + } + + #[track_caller] + fn error_log(&self, msg: &str) { + if let Err(e) = self { + dialog::alert_default(msg); + error!("{}\n{:?}\n{}", msg, e, Location::caller()); + } + } + + #[track_caller] + fn warn_log(&self, msg: &str) { + if let Err(e) = self { + dialog::alert_default(msg); + warn!("{}\n{:?}", msg, e); + } + } +} \ No newline at end of file diff --git a/src/utils.rs b/src/utils.rs index cf5358b..483be13 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -15,13 +15,14 @@ use std::{ fs::{self, File}, path::{Path, PathBuf}, - sync::{Arc, RwLock}, + sync::{Arc, RwLock}, io::Read }; -use fltk::{button::Button, dialog, enums, prelude::*}; +use fltk::{button::Button, enums, prelude::*}; use image::{DynamicImage, GenericImageView, ImageBuffer, ImageEncoder}; use serde::{Deserialize, Serialize}; +use crate::result_ext::ResultExt; use crate::globals; /// helps cast tupels to f64 @@ -63,6 +64,40 @@ impl Into<(i32, i32)> for Coord { } } +#[derive(Serialize, Deserialize, Debug, Clone)] +pub(crate) struct ImageInfo { + pub(crate) path: PathBuf, + pub(crate) image_type: ImageType +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub(crate) enum ImageType { + Jpeg, + Png, + Webp, + None +} + +impl ImageType { + pub(crate) fn from_mime(v: &str) -> Self { + match v { + "image/jpeg" | "image/jpg" => Self::Jpeg, + "image/png" => Self::Png, + "image/webp" => Self::Webp, + _ => Self::None + } + } + + pub(crate) fn as_extension(&self) -> String { + match self { + Self::Jpeg => "jpg", + Self::Png => "png", + Self::Webp => "webp", + Self::None => "none" + }.to_owned() + } +} + /// Contains Image and its buffer(edited image) #[derive(Debug, Clone)] pub(crate) struct ImageContainer { @@ -72,22 +107,13 @@ pub(crate) struct ImageContainer { } impl ImageContainer { - pub(crate) fn new(path: &PathBuf, properties: Arc>) -> Self { - let img = match image::open(path) { - Ok(i) => i, - Err(e) => { - dialog::alert_default("Failed to open image!"); - error!("Failed to open image\n{:?}", e); - panic!("Failed to open image\n{:?}", e); - } - }; - - let img = DynamicImage::ImageRgb8(img.into_rgb8()); + pub(crate) fn new(image_info: &ImageInfo, properties: Arc>) -> Self { + let img = load_image(&image_info); let (width, height): (f64, f64) = Coord::from(img.dimensions()).into(); let config = globals::CONFIG.read().unwrap(); let mut prop = properties.write().unwrap(); - prop.path = Some(path.to_owned()); + prop.image_info = Some(image_info.to_owned()); prop.original_dimension = (width, height); prop.quote_position = height * config.quote_position_ratio; prop.subquote_position = height * config.subquote_position_ratio; @@ -185,16 +211,16 @@ impl ImageContainer { pub(crate) fn save(&self) { let prop = self.properties.read().unwrap(); - let path_original = match &prop.path { - Some(p) => Path::new(p), + let (path_original, mut original_image) = match &prop.image_info { + Some(p) => (Path::new(&p.path), load_image(p)), None => return, }; let path_properties = path_original.with_extension("prop"); let config = globals::CONFIG.read().unwrap(); - let export_format = config.image_format.as_str(); + let export_format = &config.image_format; let export = path_original.parent().unwrap().join("export").join( path_original - .with_extension(export_format) + .with_extension(export_format.as_extension()) .file_name() .unwrap() .to_str() @@ -202,20 +228,13 @@ impl ImageContainer { ); let mut prop = prop.clone(); - prop.path = None; - if let Err(e) = fs::write( - &path_properties, - serde_json::to_string(&ImagePropertiesFile::from(&prop)).unwrap(), - ) { - dialog::alert_default("Failed to save properties!"); - warn!("Failed to save properties!\n{:?}", e); - } + prop.image_info = None; + fs::write(&path_properties, serde_json::to_string(&ImagePropertiesFile::from(&prop)).unwrap()).warn_log("Failed to save properties!"); - let mut img = image::open(&path_original).unwrap(); - let (width, height): (f64, f64) = Coord::from(img.dimensions()).into(); + let (width, height): (f64, f64) = Coord::from(original_image.dimensions()).into(); let (crop_x, crop_y) = prop.crop_position.unwrap(); let (crop_width, crop_height) = croped_ratio(width, height); - let mut img = img.crop( + let mut img = original_image.crop( crop_x as u32, crop_y as u32, crop_width as u32, @@ -241,75 +260,62 @@ impl ImageContainer { let mut output = match File::create(&export) { Ok(a) => a, Err(e) => { - dialog::alert_default("Failed to write to disk!"); - warn!("Failed to write to disk!\n{:?}", e); + Result::<(), _>::Err(e).warn_log("Failed to write to disk!"); return; } }; match export_format { - "png" => { + ImageType::Png => { let encoder = image::codecs::png::PngEncoder::new_with_quality( &mut output, - image::png::CompressionType::Default, - image::png::FilterType::NoFilter, + image::codecs::png::CompressionType::Best, + image::codecs::png::FilterType::Sub ); let (w, h) = img.dimensions(); - if let Err(e) = - encoder.write_image(&img.into_rgba8(), w, h, image::ColorType::Rgba8) - { - dialog::alert_default("Failed to export Image!"); - warn!("Failed to export Image!\n{:?}", e); - } + encoder.write_image(&img.into_rgba8(), w, h, image::ColorType::Rgba8).warn_log("Failed to export Image!"); } - "jpg" => { + ImageType::Jpeg => { let mut encoder = image::codecs::jpeg::JpegEncoder::new_with_quality(&mut output, 100); encoder.set_pixel_density(image::codecs::jpeg::PixelDensity::dpi(300)); - if let Err(e) = encoder.encode_image(&img) { - dialog::alert_default("Failed to export Image!"); - warn!("Failed to export Image!\n{:?}", e); - } + encoder.encode_image(&img).warn_log("Failed to export Image!"); } _ => (), } } - pub(crate) fn clone_img(&self) -> Option { + pub(crate) fn clone_img(&self) -> Option { let prop = self.properties.read().unwrap(); - match &prop.path { - Some(path) => { - let name = path.file_stem().unwrap().to_string_lossy(); - let ext = path.extension().unwrap().to_string_lossy(); + match &prop.image_info { + Some(image_info) => { + let name = image_info.path.file_stem().unwrap().to_string_lossy(); + let ext = image_info.path.extension().unwrap().to_string_lossy(); let mut i = 1; - let mut new_path = path.clone(); + let mut new_path = image_info.path.clone(); while new_path.exists() { let new_file = format!("{}{}.{}", name, "-copy".repeat(i), ext); - new_path = path.with_file_name(&new_file); + new_path = image_info.path.with_file_name(&new_file); i += 1; } - let path_properties = path.with_extension("prop"); + let path_properties = image_info.path.with_extension("prop"); let path_properties_new = new_path.with_extension("prop"); - if path.exists() { - if let Err(e) = fs::copy(path, &new_path) { - dialog::alert_default("Failed to clone image!"); - warn!("Failed to clone image!\n{:?}", e); - return None; - } + if image_info.path.exists() { + fs::copy(&image_info.path, &new_path).warn_log("Failed to clone image!"); } if path_properties.exists() { - if let Err(e) = fs::copy(path_properties, &path_properties_new) { - dialog::alert_default("Failed to clone image properties!"); - warn!("Failed to clone image properties!\n{:?}", e); - } + fs::copy(path_properties, &path_properties_new).warn_log("Failed to clone image properties!"); } - Some(new_path) + Some(ImageInfo { + path: new_path, + image_type: image_info.image_type.clone() + }) } None => None, } @@ -318,10 +324,10 @@ impl ImageContainer { pub(crate) fn delete(&self) { let prop = self.properties.read().unwrap(); let config = globals::CONFIG.read().unwrap(); - let export_format = config.image_format.as_str(); + let export_format = config.image_format.as_extension(); - let path_original = match &prop.path { - Some(p) => Path::new(p), + let path_original = match &prop.image_info { + Some(p) => Path::new(&p.path), None => return, }; let path_properties = path_original.with_extension("prop"); @@ -335,24 +341,15 @@ impl ImageContainer { ); if path_original.exists() { - if let Err(e) = fs::remove_file(path_original) { - dialog::alert_default("Failed to delete image!"); - warn!("Failed to delete image!\n{:?}", e); - } + fs::remove_file(path_original).warn_log("Failed to delete image!"); } if path_properties.exists() { - if let Err(e) = fs::remove_file(path_properties) { - dialog::alert_default("Failed to delete image properties!"); - warn!("Failed to delete image properties!\n{:?}", e); - } + fs::remove_file(path_properties).warn_log("Failed to delete image properties!"); } if export.exists() { - if let Err(e) = fs::remove_file(export) { - dialog::alert_default("Failed to delete exported image!"); - warn!("Failed to delete exported image!\n{:?}", e); - } + fs::remove_file(export).warn_log("Failed to delete exported image!"); } } } @@ -415,7 +412,7 @@ impl From<&ImageProperties> for ImagePropertiesFile { /// Properties of loaded image #[derive(Serialize, Deserialize, Debug, Clone)] pub(crate) struct ImageProperties { - pub(crate) path: Option, + pub(crate) image_info: Option, pub(crate) dimension: (f64, f64), pub(crate) original_dimension: (f64, f64), pub(crate) crop_position: Option<(f64, f64)>, @@ -436,7 +433,7 @@ pub(crate) struct ImageProperties { impl Default for ImageProperties { fn default() -> Self { Self { - path: None, + image_info: None, dimension: (0.0, 0.0), original_dimension: (0.0, 0.0), crop_position: None, @@ -480,6 +477,33 @@ impl ImageProperties { } } +/// Load image as Dynamic Image +fn load_image(image_info: &ImageInfo) -> DynamicImage { + let img = match image_info.image_type { + ImageType::Webp => { + let mut f = File::open(&image_info.path).expect_log("Failed to open image!"); + let mut buf = vec![]; + f.read_to_end(&mut buf).unwrap(); + let a = webp::Decoder::new(&buf).decode().unwrap(); + a.to_image() + } + ImageType::Jpeg => { + let dec = image::codecs::jpeg::JpegDecoder::new(File::open(&image_info.path).expect_log("Failed to open image!")).expect_log("Failed to decode image!"); + DynamicImage::from_decoder(dec).expect_log("Failed to open image!") + } + ImageType::Png => { + let dec = image::codecs::png::PngDecoder::new(File::open(&image_info.path).expect_log("Failed to open image!")).expect_log("Failed to decode image!"); + DynamicImage::from_decoder(dec).expect_log("Failed to open image!") + } + ImageType::None => { + Result::<(), _>::Err("Failed to open image!").expect_log(""); + std::process::exit(1); + } + }; + + DynamicImage::ImageRgb8(img.into_rgb8()) +} + /// Draw text and stuffs on image fn draw_layer_and_text( tmp: &mut DynamicImage, @@ -552,8 +576,8 @@ fn draw_layer_and_text( imageproc::drawing::draw_text_mut( tmp, image::Rgba([255, 255, 255, 255]), - (width * 0.99 - text_width) as u32, - ((tag_position * height) / original_height + index as f64 * (text_height * 1.2)) as u32, + (width * 0.99 - text_width) as i32, + ((tag_position * height) / original_height + index as f64 * (text_height * 1.2)) as i32, rusttype::Scale::uniform(size as f32), &globals::FONT_TAG, line, @@ -578,8 +602,8 @@ pub(crate) fn draw_multiline_mid_string( imageproc::drawing::draw_text_mut( tmp, image::Rgba([255, 255, 255, 255]), - ((width - text_width) / 2.0) as u32, - ((position * height) / original_height + index as f64 * (text_height * 1.15)) as u32, + ((width - text_width) / 2.0) as i32, + ((position * height) / original_height + index as f64 * (text_height * 1.15)) as i32, rusttype::Scale::uniform(size as f32), font, line,