From 3ef4bc7b500927ddd40bb76071c4af95613593b0 Mon Sep 17 00:00:00 2001 From: Vladyslav Vladinov <111443297+SalOne22@users.noreply.github.com> Date: Sat, 2 Dec 2023 19:56:05 +0100 Subject: [PATCH 01/30] Updated .gitignore --- .gitignore | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 24095a1a..bbe44925 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,3 @@ /target /.vscode -cachegrind.* -dhat.* -heaptrack.* \ No newline at end of file +/.idea \ No newline at end of file From 9f3cb75606ea9ced7791fc88482c2cde7682ae27 Mon Sep 17 00:00:00 2001 From: Vladyslav Vladinov <111443297+SalOne22@users.noreply.github.com> Date: Sun, 3 Dec 2023 00:16:16 +0100 Subject: [PATCH 02/30] Added integration with image crate ! With Bugs --- Cargo.lock | 871 ++++++++++++++++++++++++++++++++++++++++++- Cargo.toml | 12 +- src/decoder/mod.rs | 293 +++++---------- src/decoder/tests.rs | 16 +- src/encoder/mod.rs | 164 ++++---- src/encoder/tests.rs | 19 +- src/lib.rs | 16 +- 7 files changed, 1091 insertions(+), 300 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a1f816fb..52cf5446 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,36 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + [[package]] name = "anstream" version = "0.6.4" @@ -43,7 +73,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" dependencies = [ - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -53,7 +83,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" dependencies = [ "anstyle", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -88,6 +118,17 @@ dependencies = [ "serde", ] +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -119,12 +160,56 @@ dependencies = [ "arrayvec", ] +[[package]] +name = "bindgen" +version = "0.59.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bd2a9a458e8f4304c52c43ebb0cfbd520289f8379a52e329a38afda99bf8eb8" +dependencies = [ + "bitflags 1.3.2", + "cexpr", + "clang-sys", + "clap 2.34.0", + "env_logger", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "which", +] + +[[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" + [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" + +[[package]] +name = "bitreader" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdd859c9d97f7c468252795b35aeccc412bdbb1e90ee6969c4fa6328272eaeff" +dependencies = [ + "cfg-if", +] + [[package]] name = "bitstream-io" version = "1.7.0" @@ -192,6 +277,15 @@ dependencies = [ "libc", ] +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfg-expr" version = "0.15.5" @@ -208,6 +302,32 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clang-sys" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "ansi_term", + "atty", + "bitflags 1.3.2", + "strsim 0.8.0", + "textwrap", + "unicode-width", + "vec_map", +] + [[package]] name = "clap" version = "4.4.6" @@ -226,7 +346,7 @@ dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim", + "strsim 0.10.0", ] [[package]] @@ -244,6 +364,12 @@ dependencies = [ "cc", ] +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + [[package]] name = "colorchoice" version = "1.0.0" @@ -328,7 +454,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim", + "strsim 0.10.0", "syn 1.0.109", ] @@ -343,6 +469,35 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "dav1d" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7284148338177cb1cd0d0cdd7bf26440f8326999063eed294aa7d77b46a7e263" +dependencies = [ + "dav1d-sys", +] + +[[package]] +name = "dav1d-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88e40c4c77d141a3b70113ee45a1502b9c80e24f176958d39a8361abcf30c883" +dependencies = [ + "bindgen", + "system-deps", +] + +[[package]] +name = "dcv-color-primitives" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1457f4dd8395fef9f61996b5783b82ed7b234b4b55e1843d04e07fded0538005" +dependencies = [ + "paste", + "wasm-bindgen", +] + [[package]] name = "derive_builder" version = "0.12.0" @@ -386,12 +541,60 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +[[package]] +name = "env_logger" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + [[package]] name = "equivalent" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "exr" +version = "1.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "279d3efcc55e19917fff7ab3ddd6c14afb6a90881a0078465196fe2f99d08c56" +dependencies = [ + "bit_field", + "flume", + "half", + "lebe", + "miniz_oxide", + "rayon-core", + "smallvec", + "zune-inflate", +] + +[[package]] +name = "fallible_collections" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a88c69768c0a15262df21899142bc6df9b9b823546d4b4b9a7bc2d6c448ec6fd" +dependencies = [ + "hashbrown 0.13.2", +] + [[package]] name = "fdeflate" version = "0.3.0" @@ -410,7 +613,7 @@ dependencies = [ "cfg-if", "libc", "redox_syscall", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -423,6 +626,19 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "flume" +version = "0.10.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577" +dependencies = [ + "futures-core", + "futures-sink", + "nanorand", + "pin-project", + "spin", +] + [[package]] name = "fnv" version = "1.0.7" @@ -444,6 +660,18 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" +[[package]] +name = "futures-core" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" + +[[package]] +name = "futures-sink" +version = "0.3.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" + [[package]] name = "getrandom" version = "0.2.10" @@ -451,8 +679,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", +] + +[[package]] +name = "gif" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045" +dependencies = [ + "color_quant", + "weezl", ] [[package]] @@ -471,6 +711,15 @@ dependencies = [ "crunchy", ] +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + [[package]] name = "hashbrown" version = "0.14.1" @@ -483,6 +732,30 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "home" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + [[package]] name = "ident_case" version = "1.0.1" @@ -499,6 +772,28 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "image" +version = "0.24.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f3dfdbdd72063086ff443e297b61695500514b1e41095b6fb9a5ab48a70a711" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", + "dav1d", + "dcv-color-primitives", + "exr", + "gif", + "jpeg-decoder", + "mp4parse", + "num-rational", + "num-traits", + "png", + "qoi", + "tiff", +] + [[package]] name = "imagequant" version = "4.2.2" @@ -525,7 +820,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.14.1", "rayon", ] @@ -558,6 +853,15 @@ dependencies = [ "libc", ] +[[package]] +name = "jpeg-decoder" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e" +dependencies = [ + "rayon", +] + [[package]] name = "jpegxl-rs" version = "0.8.3+libjxl-0.8.2" @@ -590,6 +894,150 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "js-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "jxl-bitstream" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32ae9d8f3dfbef298b8357a283fad85da9c59027229e28beafcfc9d2a810a398" +dependencies = [ + "tracing", +] + +[[package]] +name = "jxl-coding" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "851149f14415943e525e6259ddff212a1f507e0b12ee6f9fc0fa5266bea88891" +dependencies = [ + "jxl-bitstream", +] + +[[package]] +name = "jxl-color" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320b54db472711efc56c8b257207b91772277e926b21e686cb23d10daf2c7f8f" +dependencies = [ + "jxl-bitstream", + "jxl-coding", + "jxl-grid", +] + +[[package]] +name = "jxl-frame" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "694f9d1d3f6addabf74ad9ca664ef0e760e85a66558dc348d03137a7adda620c" +dependencies = [ + "jxl-bitstream", + "jxl-coding", + "jxl-grid", + "jxl-image", + "jxl-modular", + "jxl-threadpool", + "jxl-vardct", + "tracing", +] + +[[package]] +name = "jxl-grid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93164539f6339d98341835684b5c8458dafd9a5dfb2fdbd3c821ea00f58a86d" + +[[package]] +name = "jxl-image" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c33911f1240386e4d0f874b313a4d27b68c5f67d4a7a418990b6605543c08a39" +dependencies = [ + "jxl-bitstream", + "jxl-color", + "jxl-grid", + "tracing", +] + +[[package]] +name = "jxl-modular" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3aa0fd75ed9e7101c1dcf7172ccac722705f6e75cc0b44721154765846a2d70" +dependencies = [ + "jxl-bitstream", + "jxl-coding", + "jxl-grid", + "jxl-threadpool", + "tracing", +] + +[[package]] +name = "jxl-oxide" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e986fe957d42be34043ed5b089c34c35a182524509e6cfee87d86527f61f9623" +dependencies = [ + "jxl-bitstream", + "jxl-color", + "jxl-frame", + "jxl-grid", + "jxl-image", + "jxl-render", + "jxl-threadpool", + "tracing", +] + +[[package]] +name = "jxl-render" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b862f98f83049febe65feb40d75493638386721ff5dff4c6a5ad267035881bf" +dependencies = [ + "jxl-bitstream", + "jxl-coding", + "jxl-color", + "jxl-frame", + "jxl-grid", + "jxl-image", + "jxl-modular", + "jxl-threadpool", + "jxl-vardct", + "tracing", +] + +[[package]] +name = "jxl-threadpool" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcd3e9cf51745c0f4e86cd728c2725d62f0d1c8611a10307e96c2af6226db291" +dependencies = [ + "rayon", + "rayon-core", + "tracing", +] + +[[package]] +name = "jxl-vardct" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "027bacaccf80849dfa4513354c8c41e8e4e1a112efeb682f6b3e9aeb4b4db481" +dependencies = [ + "jxl-bitstream", + "jxl-coding", + "jxl-grid", + "jxl-modular", + "jxl-threadpool", + "tracing", +] + [[package]] name = "kamadak-exif" version = "0.5.5" @@ -599,6 +1047,24 @@ dependencies = [ "mutate_once", ] +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "lebe" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" + [[package]] name = "libaom-sys" version = "0.14.0" @@ -653,6 +1119,16 @@ dependencies = [ "cc", ] +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + [[package]] name = "libwebp-sys" version = "0.9.4" @@ -663,6 +1139,22 @@ dependencies = [ "glob", ] +[[package]] +name = "linux-raw-sys" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" + +[[package]] +name = "lock_api" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "log" version = "0.4.20" @@ -743,12 +1235,35 @@ dependencies = [ "nasm-rs", ] +[[package]] +name = "mp4parse" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63a35203d3c6ce92d5251c77520acb2e57108c88728695aa883f70023624c570" +dependencies = [ + "bitreader", + "byteorder", + "fallible_collections", + "log", + "num-traits", + "static_assertions", +] + [[package]] name = "mutate_once" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "16cf681a23b4d0a43fc35024c176437f9dcd818db34e0f42ab456a0ee5ad497b" +[[package]] +name = "nanorand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" +dependencies = [ + "getrandom", +] + [[package]] name = "nasm-rs" version = "0.2.5" @@ -875,12 +1390,44 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + [[package]] name = "percent-encoding" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +[[package]] +name = "pin-project" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + [[package]] name = "pkg-config" version = "0.3.27" @@ -893,7 +1440,7 @@ version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64" dependencies = [ - "bitflags", + "bitflags 1.3.2", "crc32fast", "fdeflate", "flate2", @@ -915,6 +1462,15 @@ dependencies = [ "unicode-ident", ] +[[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" @@ -1045,9 +1601,38 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags", + "bitflags 1.3.2", +] + +[[package]] +name = "regex" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", ] +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + [[package]] name = "resize" version = "0.8.2" @@ -1071,10 +1656,12 @@ dependencies = [ name = "rimage" version = "0.9.1" dependencies = [ - "clap", + "clap 4.4.6", "glob", + "image", "imagequant", "jpegxl-rs", + "jxl-oxide", "kamadak-exif", "libavif-sys", "mozjpeg", @@ -1126,6 +1713,19 @@ dependencies = [ "semver", ] +[[package]] +name = "rustix" +version = "0.38.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" +dependencies = [ + "bitflags 2.4.1", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.48.0", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -1170,6 +1770,12 @@ dependencies = [ "serde", ] +[[package]] +name = "shlex" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" + [[package]] name = "simd-adler32" version = "0.3.7" @@ -1191,12 +1797,33 @@ version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "strength_reduce" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + [[package]] name = "strsim" version = "0.10.0" @@ -1250,6 +1877,24 @@ version = "0.12.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d0e916b1148c8e263850e1ebcbd046f333e0683c724876bb0da63ea4373dc8a" +[[package]] +name = "termcolor" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + [[package]] name = "thiserror" version = "1.0.49" @@ -1280,6 +1925,17 @@ dependencies = [ "once_cell", ] +[[package]] +name = "tiff" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d172b0f4d3fba17ba89811858b9d3d97f928aece846475bbda076ca46736211" +dependencies = [ + "flate2", + "jpeg-decoder", + "weezl", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -1338,6 +1994,25 @@ dependencies = [ "winnow", ] +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + [[package]] name = "transpose" version = "0.2.2" @@ -1375,6 +2050,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-width" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" + [[package]] name = "url" version = "2.4.1" @@ -1405,12 +2086,24 @@ dependencies = [ "rust_hawktracer", ] +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + [[package]] name = "version-compare" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -1480,13 +2173,71 @@ dependencies = [ "libwebp-sys", ] +[[package]] +name = "weezl" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", ] [[package]] @@ -1495,13 +2246,28 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", ] [[package]] @@ -1510,42 +2276,84 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + [[package]] name = "winnow" version = "0.5.17" @@ -1564,6 +2372,26 @@ dependencies = [ "tap", ] +[[package]] +name = "zerocopy" +version = "0.7.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d6f15f7ade05d2a4935e34a457b936c23dc70a05cc1d97133dc99e7a3fe0f0e" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbbad221e3f78500350ecbd7dfa4e63ef945c05f4c61cb7f4d3f84cd0bba649b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.38", +] + [[package]] name = "zopfli" version = "0.8.0" @@ -1575,3 +2403,12 @@ dependencies = [ "simd-adler32", "typed-arena", ] + +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +dependencies = [ + "simd-adler32", +] diff --git a/Cargo.toml b/Cargo.toml index 7a0cc80f..901fac14 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,17 +23,18 @@ codegen-units = 1 [features] default = ["cli", "parallel", "quantization", "resizing", "exif", "oxipng"] -parallel = ["mozjpeg/parallel", "imagequant?/threads", "oxipng?/parallel", "jpegxl-rs?/threads", "dep:rayon"] +parallel = ["mozjpeg/parallel", "imagequant?/threads", "oxipng?/parallel", "jxl-oxide?/rayon", "dep:rayon"] quantization = ["dep:imagequant"] resizing = ["dep:resize"] transform = ["dep:transpose"] -avif = ["dep:libavif-sys", "dep:ravif"] +avif = ["dep:libavif-sys", "dep:ravif", "image/avif-decoder"] exif = ["dep:kamadak-exif", "transform"] -jxl = ["dep:jpegxl-rs"] +jxl = ["dep:jxl-oxide"] cli = ["dep:clap", "dep:glob", "quantization", "resizing", "exif"] [dependencies] +image = "0.24.7" rgb = "0.8.36" thiserror = "1.0.49" png = "0.17.10" @@ -44,6 +45,11 @@ ravif = { version = "0.11.2", optional = true } kamadak-exif = { version = "0.5.5", optional = true } clap = { version = "4.4.2", optional = true } +[dependencies.jxl-oxide] +version = "0.5.1" +default-features = false +optional = true + [dependencies.imagequant] version = "4.2.1" default-features = false diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index 64611b84..5c127d52 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -1,30 +1,33 @@ +use image::error::{DecodingError, ImageFormatHint, UnsupportedError, UnsupportedErrorKind}; +use image::DynamicImage::{ImageLuma8, ImageLumaA8, ImageRgb8, ImageRgba8}; +use image::{ + DynamicImage, GrayAlphaImage, GrayImage, ImageError, ImageResult, RgbImage, RgbaImage, +}; +use std::io::Seek; use std::{ fs::File, io::{BufRead, BufReader}, path::Path, }; -use rgb::{ - alt::{GRAY8, GRAYA8}, - AsPixels, FromSlice, RGB8, RGBA8, -}; +use image::io::Reader as ImageReader; -use crate::{config::ImageFormat, error::DecoderError, Image}; +use crate::config::ImageFormat; /// Decoder for reading and decoding images from various formats. -pub struct Decoder { - r: R, +pub struct Decoder { + r: ImageReader, format: Option, #[cfg(feature = "transform")] fix_orientation: Option, } -impl Decoder { +impl Decoder { /// Creates a new [`Decoder`] with the specified input reader. /// /// # Parameters /// - /// - `r`: The input reader implementing [`BufRead`] from which image data will be read. + /// - `r`: The input reader implementing [`Read`] from which image data will be read. /// /// # Returns /// @@ -32,7 +35,7 @@ impl Decoder { #[inline] pub fn new(r: R) -> Self { Self { - r, + r: ImageReader::new(r), format: None, #[cfg(feature = "transform")] fix_orientation: None, @@ -92,196 +95,104 @@ impl Decoder { /// # Returns /// /// Returns a [`Result`] containing the decoded [`Image`] on success or a [`DecoderError`] on failure. - pub fn decode(self) -> Result { - #[cfg(feature = "transform")] - let orientation = self.fix_orientation; - - #[allow(unused_mut)] - let mut image = match self.format { - Some(ImageFormat::Jpeg) => self.decode_jpeg(), - Some(ImageFormat::Png) => self.decode_png(), - #[cfg(feature = "avif")] - Some(ImageFormat::Avif) => unsafe { self.decode_avif() }, + pub fn decode(self) -> ImageResult { + let image = match self.format { #[cfg(feature = "jxl")] Some(ImageFormat::JpegXl) => self.decode_jpegxl(), - #[cfg(feature = "webp")] - Some(ImageFormat::WebP) => self.decode_webp(), - None => Err(DecoderError::Format( - crate::error::ImageFormatError::Missing, - )), + _ => self.r.with_guessed_format()?.decode(), }?; - #[cfg(feature = "transform")] - if let Some(orientation) = orientation { - image.fix_orientation(orientation) - } - Ok(image) } - fn decode_jpeg(self) -> Result { - std::panic::catch_unwind(|| -> Result { - let decoder = - mozjpeg::Decompress::with_markers(mozjpeg::ALL_MARKERS).from_reader(self.r)?; - - let mut image = decoder.rgba()?; - - let pixels = image.read_scanlines()?; - - Ok(Image::new(pixels, image.width(), image.height())) - }) - .map_err(|_| DecoderError::MozJpeg)? - } - - fn decode_png(self) -> Result { - let mut decoder = png::Decoder::new(self.r); - - decoder.set_transformations(png::Transformations::normalize_to_color8()); - - let mut reader = decoder.read_info()?; - - let info = reader.info(); - - let buf_size = (info.width * info.height * 4) as usize; - - let mut buf: Vec = vec![0; buf_size]; - - let info = reader.next_frame(&mut buf)?; - - match info.color_type { - png::ColorType::Grayscale => Self::expand_pixels(&mut buf, GRAY8::into), - png::ColorType::GrayscaleAlpha => Self::expand_pixels(&mut buf, GRAYA8::into), - png::ColorType::Rgb => Self::expand_pixels(&mut buf, RGB8::into), - png::ColorType::Rgba => {} - png::ColorType::Indexed => { - unreachable!("Indexed color type is expected to be expanded") - } - }; - - Ok(Image::new( - buf.as_rgba().to_owned(), - info.width as usize, - info.height as usize, - )) - } - - #[cfg(feature = "avif")] - unsafe fn decode_avif(mut self) -> Result { - use libavif_sys::*; - - let image = avifImageCreateEmpty(); - let decoder = avifDecoderCreate(); - - let mut buf = Vec::new(); - - self.r.read_to_end(&mut buf)?; - - let decode_result = avifDecoderReadMemory(decoder, image, buf.as_ptr(), buf.len()); - avifDecoderDestroy(decoder); - - if decode_result == AVIF_RESULT_OK { - let mut rgb = avifRGBImage::default(); - avifRGBImageSetDefaults(&mut rgb, image); - - rgb.depth = 8; - - avifRGBImageAllocatePixels(&mut rgb); - avifImageYUVToRGB(image, &mut rgb); - - let pixels = - std::slice::from_raw_parts(rgb.pixels, (rgb.rowBytes * rgb.height) as usize) - .as_rgba() - .to_owned(); - - let result = Image::new(pixels, rgb.width as usize, rgb.height as usize); - - avifRGBImageFreePixels(&mut rgb); - - Ok(result) - } else { - Err(DecoderError::Avif(decode_result)) - } - } - #[cfg(feature = "jxl")] - fn decode_jpegxl(mut self) -> Result { - #[cfg(feature = "parallel")] - let runner = jpegxl_rs::ThreadsRunner::default(); - - #[cfg(feature = "parallel")] - let decoder = jpegxl_rs::decoder_builder() - .parallel_runner(&runner) - .pixel_format(jpegxl_rs::decode::PixelFormat { - num_channels: 4, - endianness: jpegxl_rs::Endianness::Native, - align: 0, - }) - .build()?; - - #[cfg(not(feature = "parallel"))] - let decoder = jpegxl_rs::decoder_builder() - .pixel_format(jpegxl_rs::decode::PixelFormat { - num_channels: 4, - endianness: jpegxl_rs::Endianness::Native, - align: 0, - }) - .build()?; - - let mut buf = Vec::new(); - - self.r.read_to_end(&mut buf)?; - - let (info, pixels) = decoder.decode_with::(&buf)?; - - Ok(Image::new( - pixels.as_rgba().to_owned(), - info.width as usize, - info.height as usize, - )) - } - - #[cfg(feature = "webp")] - fn decode_webp(mut self) -> Result { - let mut buf = Vec::new(); - - self.r.read_to_end(&mut buf)?; - - let decoder = webp::Decoder::new(&buf); - - let image = decoder.decode().ok_or(DecoderError::WebP)?; - - let mut buf = image.to_vec(); - - if !image.is_alpha() { - let buf_size = (image.width() * image.height() * 4) as usize; - buf.resize(buf_size, 0); - - Self::expand_pixels(&mut buf, RGB8::into); - } - - Ok(Image::new( - buf.as_rgba().to_vec(), - image.width() as usize, - image.height() as usize, - )) - } - - fn expand_pixels(buf: &mut [u8], to_rgba: impl Fn(T) -> RGBA8) - where - [u8]: AsPixels + FromSlice, - { - assert!(std::mem::size_of::() <= std::mem::size_of::()); - for i in (0..buf.len() / 4).rev() { - let src_pix = buf.as_pixels()[i]; - buf.as_rgba_mut()[i] = to_rgba(src_pix); - } + fn decode_jpegxl(self) -> ImageResult { + use jxl_oxide::{JxlImage, PixelFormat}; + + let image = JxlImage::from_reader(self.r.into_inner()).map_err(|e| { + ImageError::Decoding(DecodingError::new( + ImageFormatHint::Name("JpegXL".to_string()), + e, + )) + })?; + let render = image.render_frame(0).map_err(|e| { + ImageError::Decoding(DecodingError::new( + ImageFormatHint::Name("JpegXL".to_string()), + e, + )) + })?; + + let format = image.pixel_format(); + + let framebuffer = render.image(); + + Ok(match format { + PixelFormat::Gray => ImageLuma8( + GrayImage::from_raw( + framebuffer.width() as u32, + framebuffer.height() as u32, + framebuffer + .buf() + .iter() + .map(|x| x * 255. + 0.5) + .map(|x| x as u8) + .collect::>(), + ) + .unwrap(), + ), + PixelFormat::Graya => ImageLumaA8( + GrayAlphaImage::from_raw( + framebuffer.width() as u32, + framebuffer.height() as u32, + framebuffer + .buf() + .iter() + .map(|x| x * 255. + 0.5) + .map(|x| x as u8) + .collect::>(), + ) + .unwrap(), + ), + PixelFormat::Rgb => ImageRgb8( + RgbImage::from_raw( + framebuffer.width() as u32, + framebuffer.height() as u32, + framebuffer + .buf() + .iter() + .map(|x| x * 255. + 0.5) + .map(|x| x as u8) + .collect::>(), + ) + .unwrap(), + ), + PixelFormat::Rgba => ImageRgba8( + RgbaImage::from_raw( + framebuffer.width() as u32, + framebuffer.height() as u32, + framebuffer + .buf() + .iter() + .map(|x| x * 255. + 0.5) + .map(|x| x as u8) + .collect::>(), + ) + .unwrap(), + ), + _ => Err(ImageError::Unsupported( + UnsupportedError::from_format_and_kind( + ImageFormatHint::Name("JpegXL".to_string()), + UnsupportedErrorKind::GenericFeature("CMYK Colorspace".to_string()), + ), + ))?, + }) } } impl Decoder> { /// Creates a new [`Decoder`] from a file specified by the given path. /// - /// This method opens the file at the specified path, sets up a `BufReader` for reading, and + /// This method opens the file at the specified path, sets up a `Reader` for reading, and /// determines the image format based on the file extension. /// /// # Parameters @@ -298,12 +209,14 @@ impl Decoder> { /// This method may return a [`DecoderError`] if there are issues with opening the file, determining /// the image format, or other I/O-related errors. #[inline] - pub fn from_path(path: &Path) -> Result { + pub fn from_path(path: impl AsRef) -> ImageResult { Ok(Self { - r: BufReader::new(File::open(path)?), - format: Some(ImageFormat::from_path(path)?), + r: ImageReader::open(path.as_ref())?, + format: Some(ImageFormat::from_path(path.as_ref()).map_err(|e| { + ImageError::Unsupported(UnsupportedError::from(ImageFormatHint::Unknown)) + })?), #[cfg(feature = "transform")] - fix_orientation: Self::get_orientation(path), + fix_orientation: Self::get_orientation(path.as_ref()), }) } diff --git a/src/decoder/tests.rs b/src/decoder/tests.rs index 3f95a819..861ef897 100644 --- a/src/decoder/tests.rs +++ b/src/decoder/tests.rs @@ -7,7 +7,7 @@ fn new_decoder() { let cursor = Cursor::new(Vec::new()); let decoder = Decoder::new(cursor.clone()); - assert_eq!(decoder.r, cursor); + assert_eq!(decoder.r.into_inner(), cursor); assert_eq!(decoder.format, None); #[cfg(feature = "transform")] assert_eq!(decoder.fix_orientation, None); @@ -18,7 +18,7 @@ fn new_decoder_with_format() { let cursor = Cursor::new(Vec::new()); let decoder = Decoder::new(cursor.clone()).with_format(ImageFormat::Jpeg); - assert_eq!(decoder.r, cursor); + assert_eq!(decoder.r.into_inner(), cursor); assert_eq!(decoder.format, Some(ImageFormat::Jpeg)); #[cfg(feature = "transform")] assert_eq!(decoder.fix_orientation, None); @@ -29,14 +29,16 @@ fn decode_without_format() { let cursor = Cursor::new(Vec::new()); let decoder = Decoder::new(cursor.clone()); - assert_eq!(decoder.r, cursor); assert_eq!(decoder.format, None); #[cfg(feature = "transform")] assert_eq!(decoder.fix_orientation, None); let result = decoder.decode(); assert!(result.is_err()); - assert_eq!(result.unwrap_err().to_string(), "Can't find image format"); + assert_eq!( + result.unwrap_err().to_string(), + "The image format could not be determined" + ); } #[test] @@ -45,15 +47,17 @@ fn new_decoder_with_fixed_orientation() { let cursor = Cursor::new(Vec::new()); let decoder = Decoder::new(cursor.clone()).with_fixed_orientation(4); - assert_eq!(decoder.r, cursor); + assert_eq!(decoder.r.into_inner(), cursor); assert_eq!(decoder.format, None); #[cfg(feature = "transform")] assert_eq!(decoder.fix_orientation, Some(4)); } #[test] +#[ignore = "needed fixes"] #[cfg(feature = "exif")] fn fix_orientation() -> Result<(), Box> { + // TODO: Add transform when exif tag is present let files = fs::read_dir("tests/files/exif")?; for entry in files { @@ -73,8 +77,10 @@ fn fix_orientation() -> Result<(), Box> { } #[test] +#[ignore = "dav1d can't decode avif yet..."] #[cfg(feature = "avif")] fn decode_avif() -> Result<(), Box> { + // TODO: Add decoding of avif images let files = fs::read_dir("tests/files/avif")?; for entry in files { diff --git a/src/encoder/mod.rs b/src/encoder/mod.rs index 105b88f6..05753fc0 100644 --- a/src/encoder/mod.rs +++ b/src/encoder/mod.rs @@ -1,13 +1,14 @@ +use image::{DynamicImage, ImageBuffer}; +use rgb::FromSlice; use std::io::Write; -use rgb::ComponentBytes; - -use crate::{config::EncoderConfig, error::EncoderError, image::Image}; +use crate::config::ResizeType; +use crate::{config::EncoderConfig, error::EncoderError}; /// A struct for encoding images using various codecs. pub struct Encoder { w: W, - data: Image, + data: DynamicImage, conf: EncoderConfig, } @@ -22,19 +23,19 @@ impl Encoder { /// # Examples /// /// ``` - /// # use rimage::rgb::RGBA8; - /// use rimage::{Encoder, Image}; + /// use rimage::Encoder; /// # use std::fs::File; - /// # let image_data = vec![RGBA8::new(0, 0, 0, 0); 800 * 600]; + /// use image::{DynamicImage, RgbaImage}; + /// # let image_data = vec![0; 800 * 600 * 4]; /// - /// let image = Image::new(image_data, 800, 600); + /// let image = RgbaImage::from_raw(800, 600, image_data).unwrap(); /// /// let file = File::create("output.jpg").expect("Failed to create file"); /// - /// let encoder = Encoder::new(file, image); // uses default config + /// let encoder = Encoder::new(file, DynamicImage::ImageRgba8(image)); // uses default config /// ``` #[inline] - pub fn new(w: W, data: Image) -> Self { + pub fn new(w: W, data: DynamicImage) -> Self { Self { w, data, @@ -56,12 +57,13 @@ impl Encoder { /// /// ``` /// # use rimage::rgb::RGBA8; - /// use rimage::{Encoder, Image, config::{EncoderConfig, Codec}}; + /// use rimage::{Encoder, config::{EncoderConfig, Codec}}; /// # use std::fs::File; /// # use std::fs; - /// # let image_data = vec![RGBA8::new(0, 0, 0, 0); 800 * 600]; + /// use image::{DynamicImage, RgbaImage}; + /// # let image_data = vec![0; 800 * 600 * 4]; /// - /// let image = Image::new(image_data, 800, 600); + /// let image = RgbaImage::from_raw(800, 600, image_data).unwrap(); /// /// let file = File::create("output.png").expect("Failed to create file"); /// @@ -69,7 +71,7 @@ impl Encoder { /// .with_quality(90.0) /// .unwrap(); /// - /// let encoder = Encoder::new(file, image).with_config(config); + /// let encoder = Encoder::new(file, DynamicImage::ImageRgba8(image)).with_config(config); /// /// # fs::remove_file("output.png").unwrap_or(()); /// # Ok::<(), rimage::error::EncoderError>(()) @@ -89,19 +91,19 @@ impl Encoder { /// # Examples /// /// ``` - /// use rimage::rgb::RGBA8; - /// use rimage::{Encoder, Image, config::EncoderConfig}; + /// use rimage::{Encoder, config::EncoderConfig}; /// # use std::fs; /// use std::fs::File; + /// use image::{DynamicImage, RgbaImage}; /// - /// let image_data = vec![RGBA8::new(0, 0, 0, 0); 800 * 600]; - /// let image = Image::new(image_data, 800, 600); + /// let image_data = vec![0; 800 * 600 * 4]; + /// let image = RgbaImage::from_raw(800, 600, image_data).unwrap(); /// /// let file = File::create("output.jpg").expect("Failed to create file"); /// /// let config = EncoderConfig::default(); /// - /// let encoder = Encoder::new(file, image).with_config(config); + /// let encoder = Encoder::new(file, DynamicImage::ImageRgba8(image)).with_config(config); /// /// encoder.encode()?; /// # fs::remove_file("output.jpg")?; @@ -109,14 +111,71 @@ impl Encoder { /// ``` #[allow(unused_mut)] pub fn encode(mut self) -> Result<(), EncoderError> { + // TODO: Move resize out from encoder to operations #[cfg(feature = "resizing")] if let Some(resize_config) = self.conf.resize_config() { - self.data.resize(resize_config)?; + let aspect_ratio = self.data.width() as f64 / self.data.height() as f64; + + let width = resize_config.width().unwrap_or( + resize_config + .height() + .map(|h| (h as f64 * aspect_ratio) as usize) + .unwrap_or(self.data.width() as usize), + ); + let height = resize_config.height().unwrap_or( + resize_config + .width() + .map(|w| (w as f64 / aspect_ratio) as usize) + .unwrap_or(self.data.height() as usize), + ); + + let filter = match resize_config.filter_type() { + ResizeType::Point => image::imageops::Nearest, + ResizeType::Triangle => image::imageops::Triangle, + ResizeType::CatmullRom => image::imageops::CatmullRom, + ResizeType::Mitchell => image::imageops::Gaussian, // TODO: rename Mitchell to Gaussian + ResizeType::Lanczos3 => image::imageops::Lanczos3, + }; + + self.data.resize(width as u32, height as u32, filter); } + // TODO: Move quantization out from encoder to operations #[cfg(feature = "quantization")] if let Some(quantization_config) = self.conf.quantization_config() { - self.data.quantize(quantization_config)?; + let mut image = self.data.to_rgba8(); + + let pixels = image.as_raw(); + + let mut liq = imagequant::new(); + + liq.set_speed(5)?; + liq.set_quality(0, quantization_config.quality())?; + + let mut img = liq.new_image_borrowed( + pixels.as_rgba(), + image.width() as usize, + image.height() as usize, + 0.0, + )?; + + let mut res = liq.quantize(&mut img)?; + + res.set_dithering_level(quantization_config.dithering_level())?; + + let (palette, pixels) = res.remapped(&mut img)?; + + self.data = DynamicImage::ImageRgba8( + ImageBuffer::from_raw( + image.width(), + image.height(), + pixels + .iter() + .flat_map(|pix| palette[*pix as usize].iter()) + .collect::>(), + ) + .ok_or(EncoderError::General)?, + ); } match self.conf.codec() { @@ -141,13 +200,13 @@ impl Encoder { std::panic::catch_unwind(|| -> Result<(), EncoderError> { let mut comp = mozjpeg::Compress::new(mozjpeg::ColorSpace::JCS_EXT_RGBA); - comp.set_size(width, height); + comp.set_size(width as usize, height as usize); comp.set_quality(quality); comp.set_progressive_mode(); let mut comp = comp.start_compress(self.w)?; - comp.write_scanlines(self.data.data().as_bytes())?; + comp.write_scanlines(self.data.as_bytes())?; comp.finish()?; @@ -157,8 +216,8 @@ impl Encoder { } fn encode_png(self) -> Result<(), EncoderError> { - let width: u32 = self.data.width().try_into()?; - let height: u32 = self.data.height().try_into()?; + let width = self.data.width(); + let height = self.data.height(); let mut encoder = png::Encoder::new(self.w, width, height); @@ -167,7 +226,7 @@ impl Encoder { let mut writer = encoder.write_header()?; - writer.write_image_data(self.data.data().as_bytes())?; + writer.write_image_data(self.data.as_bytes())?; writer.finish()?; Ok(()) @@ -175,46 +234,13 @@ impl Encoder { #[cfg(feature = "jxl")] fn encode_jpegxl(mut self) -> Result<(), EncoderError> { - #[cfg(feature = "parallel")] - let runner = jpegxl_rs::ThreadsRunner::default(); - use std::f32::consts::E; - - let quality = 15.0 * E.powf(-0.1 * self.conf.quality()); - - #[cfg(feature = "parallel")] - let mut encoder = jpegxl_rs::encoder_builder() - .parallel_runner(&runner) - .quality(quality) - .speed(jpegxl_rs::encode::EncoderSpeed::Falcon) - .build()?; - - #[cfg(not(feature = "parallel"))] - let mut encoder = jpegxl_rs::encoder_builder() - .quality(quality) - .speed(jpegxl_rs::encode::EncoderSpeed::Falcon) - .build()?; - - let buf: jpegxl_rs::encode::EncoderResult = encoder.encode( - self.data - .data() - .iter() - .map(|pix| pix.rgb()) - .collect::>() - .as_bytes(), - self.data.width().try_into()?, - self.data.height().try_into()?, - )?; - - self.w.write_all(&buf)?; - self.w.flush()?; - - Ok(()) + unimplemented!() } #[cfg(feature = "oxipng")] fn encode_oxipng(mut self) -> Result<(), EncoderError> { - let width: u32 = self.data.width().try_into()?; - let height: u32 = self.data.height().try_into()?; + let width = self.data.width(); + let height = self.data.height(); let options = oxipng::Options::default(); @@ -223,7 +249,7 @@ impl Encoder { height, oxipng::ColorType::RGBA, oxipng::BitDepth::Eight, - self.data.data().as_bytes().to_vec(), + self.data.as_bytes().to_vec(), )?; self.w.write_all(&img.create_optimized_png(&options)?)?; @@ -233,10 +259,10 @@ impl Encoder { #[cfg(feature = "webp")] fn encode_webp(mut self) -> Result<(), EncoderError> { - let width: u32 = self.data.width().try_into()?; - let height: u32 = self.data.height().try_into()?; + let width = self.data.width(); + let height = self.data.height(); - let encoder = webp::Encoder::from_rgba(self.data.data().as_bytes(), width, height); + let encoder = webp::Encoder::from_rgba(self.data.as_bytes(), width, height); self.w.write_all(&encoder.encode(self.conf.quality()))?; self.w.flush()?; @@ -252,7 +278,11 @@ impl Encoder { let img = ravif::Encoder::new() .with_quality(self.conf.quality()) .with_speed(4) - .encode_rgba(ravif::Img::new(self.data.data(), width, height))?; + .encode_rgba(ravif::Img::new( + self.data.into_rgba8().as_rgba(), + width as usize, + height as usize, + ))?; self.w.write_all(&img.avif_file)?; self.w.flush()?; diff --git a/src/encoder/tests.rs b/src/encoder/tests.rs index 3de5bf93..9470870f 100644 --- a/src/encoder/tests.rs +++ b/src/encoder/tests.rs @@ -1,7 +1,6 @@ +use image::RgbaImage; use std::io::Cursor; -use rgb::RGBA8; - // Import the necessary dependencies from the code use super::*; use crate::config::Codec; @@ -9,35 +8,35 @@ use crate::config::Codec; #[test] fn encoder_new() { // Create a mock image and writer - let image_data = vec![RGBA8::new(0, 0, 0, 0); 100 * 50]; - let image = Image::new(image_data.clone(), 100, 50); + let image_data = vec![0; 100 * 50 * 4]; + let image = RgbaImage::from_raw(100, 50, image_data).unwrap(); let writer = Cursor::new(Vec::new()); // Create an Encoder with default config - let encoder = Encoder::new(writer.clone(), image); + let encoder = Encoder::new(writer.clone(), DynamicImage::ImageRgba8(image)); // Verify that the Encoder was created with the correct properties assert_eq!(encoder.w, writer); - assert_eq!(encoder.data.data(), &[RGBA8::new(0, 0, 0, 0); 100 * 50]); + assert_eq!(encoder.data.as_bytes(), &[0; 100 * 50 * 4]); assert_eq!(encoder.conf.codec(), &Codec::MozJpeg); } #[test] fn encoder_with_config() { // Create a mock image and writer - let image_data = vec![RGBA8::new(0, 0, 0, 0); 100 * 50]; - let image = Image::new(image_data.clone(), 100, 50); + let image_data = vec![0; 100 * 50 * 4]; + let image = RgbaImage::from_raw(100, 50, image_data).unwrap(); let writer = Cursor::new(Vec::new()); // Create an Encoder with a custom config let config = EncoderConfig::new(Codec::MozJpeg) .with_quality(90.0) .unwrap(); - let encoder = Encoder::new(writer.clone(), image).with_config(config); + let encoder = Encoder::new(writer.clone(), DynamicImage::ImageRgba8(image)).with_config(config); // Verify that the Encoder was created with the correct properties assert_eq!(encoder.w, writer); - assert_eq!(encoder.data.data(), &[RGBA8::new(0, 0, 0, 0); 100 * 50]); + assert_eq!(encoder.data.as_bytes(), &[0; 100 * 50 * 4]); assert_eq!(encoder.conf.codec(), &Codec::MozJpeg); assert_eq!(encoder.conf.quality(), 90.0); } diff --git a/src/lib.rs b/src/lib.rs index 9a806737..13a8ac99 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,7 +25,7 @@ let decoder = Decoder::from_path(&path)?; let image = decoder.decode()?; // do something with the image data... -# Ok::<(), rimage::error::DecoderError>(()) +# Ok::<(), image::error::ImageError>(()) ``` From memory: @@ -41,7 +41,7 @@ let decoder = Decoder::new(reader).with_format(ImageFormat::Jpeg); let image = decoder.decode()?; // do something with the image data... -# Ok::<(), rimage::error::DecoderError>(()) +# Ok::<(), image::error::ImageError>(()) ``` ## Encoding @@ -49,15 +49,16 @@ let image = decoder.decode()?; ``` use std::fs::File; -use rimage::{rgb::RGBA8, Encoder, Image, config::{EncoderConfig, Codec}}; +use rimage::{rgb::RGBA8, Encoder, config::{EncoderConfig, Codec}}; +use image::{RgbaImage, DynamicImage}; -let image_data = vec![RGBA8::new(0, 0, 0, 0); 100 * 50]; -let image = Image::new(image_data, 100, 50); +let image_data = vec![0; 100 * 50 * 4]; +let image = RgbaImage::from_raw(100, 50, image_data).unwrap(); let config = EncoderConfig::new(Codec::MozJpeg).with_quality(80.0).unwrap(); let file = File::create("output.jpg").expect("Failed to create file"); -let encoder = Encoder::new(file, image).with_config(config); +let encoder = Encoder::new(file, DynamicImage::ImageRgba8(image)).with_config(config); encoder.encode()?; @@ -74,11 +75,10 @@ mod decoder; mod encoder; /// Module for library errors. pub mod error; -mod image; pub use decoder::Decoder; pub use encoder::Encoder; -pub use image::Image; +pub use image; #[cfg(feature = "resizing")] pub use resize; From ef8710fbe439193ea0e911bfa0b570b8d989d171 Mon Sep 17 00:00:00 2001 From: Vladyslav Vladinov <111443297+SalOne22@users.noreply.github.com> Date: Sun, 3 Dec 2023 14:34:40 +0100 Subject: [PATCH 03/30] Added decoding of avif images --- Cargo.lock | 564 +++++-------------------------------------- Cargo.toml | 8 +- src/decoder/mod.rs | 18 ++ src/decoder/tests.rs | 2 - 4 files changed, 85 insertions(+), 507 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 52cf5446..85ba861f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,36 +8,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" -[[package]] -name = "ahash" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" -dependencies = [ - "cfg-if", - "once_cell", - "version_check", - "zerocopy", -] - -[[package]] -name = "aho-corasick" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" -dependencies = [ - "memchr", -] - -[[package]] -name = "ansi_term" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" -dependencies = [ - "winapi", -] - [[package]] name = "anstream" version = "0.6.4" @@ -73,7 +43,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" dependencies = [ - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -83,7 +53,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" dependencies = [ "anstyle", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -118,17 +88,6 @@ dependencies = [ "serde", ] -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - [[package]] name = "autocfg" version = "1.1.0" @@ -160,29 +119,6 @@ dependencies = [ "arrayvec", ] -[[package]] -name = "bindgen" -version = "0.59.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bd2a9a458e8f4304c52c43ebb0cfbd520289f8379a52e329a38afda99bf8eb8" -dependencies = [ - "bitflags 1.3.2", - "cexpr", - "clang-sys", - "clap 2.34.0", - "env_logger", - "lazy_static", - "lazycell", - "log", - "peeking_take_while", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "which", -] - [[package]] name = "bit_field" version = "0.10.2" @@ -195,21 +131,6 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "bitflags" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" - -[[package]] -name = "bitreader" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdd859c9d97f7c468252795b35aeccc412bdbb1e90ee6969c4fa6328272eaeff" -dependencies = [ - "cfg-if", -] - [[package]] name = "bitstream-io" version = "1.7.0" @@ -277,15 +198,6 @@ dependencies = [ "libc", ] -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] - [[package]] name = "cfg-expr" version = "0.15.5" @@ -302,32 +214,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "clang-sys" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" -dependencies = [ - "glob", - "libc", - "libloading", -] - -[[package]] -name = "clap" -version = "2.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" -dependencies = [ - "ansi_term", - "atty", - "bitflags 1.3.2", - "strsim 0.8.0", - "textwrap", - "unicode-width", - "vec_map", -] - [[package]] name = "clap" version = "4.4.6" @@ -346,7 +232,7 @@ dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim 0.10.0", + "strsim", ] [[package]] @@ -454,7 +340,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim 0.10.0", + "strsim", "syn 1.0.109", ] @@ -469,35 +355,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "dav1d" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7284148338177cb1cd0d0cdd7bf26440f8326999063eed294aa7d77b46a7e263" -dependencies = [ - "dav1d-sys", -] - -[[package]] -name = "dav1d-sys" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88e40c4c77d141a3b70113ee45a1502b9c80e24f176958d39a8361abcf30c883" -dependencies = [ - "bindgen", - "system-deps", -] - -[[package]] -name = "dcv-color-primitives" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1457f4dd8395fef9f61996b5783b82ed7b234b4b55e1843d04e07fded0538005" -dependencies = [ - "paste", - "wasm-bindgen", -] - [[package]] name = "derive_builder" version = "0.12.0" @@ -541,35 +398,12 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" -[[package]] -name = "env_logger" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" -dependencies = [ - "atty", - "humantime", - "log", - "regex", - "termcolor", -] - [[package]] name = "equivalent" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" -[[package]] -name = "errno" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - [[package]] name = "exr" version = "1.6.4" @@ -586,15 +420,6 @@ dependencies = [ "zune-inflate", ] -[[package]] -name = "fallible_collections" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a88c69768c0a15262df21899142bc6df9b9b823546d4b4b9a7bc2d6c448ec6fd" -dependencies = [ - "hashbrown 0.13.2", -] - [[package]] name = "fdeflate" version = "0.3.0" @@ -613,7 +438,7 @@ dependencies = [ "cfg-if", "libc", "redox_syscall", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -711,15 +536,6 @@ dependencies = [ "crunchy", ] -[[package]] -name = "hashbrown" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" -dependencies = [ - "ahash", -] - [[package]] name = "hashbrown" version = "0.14.1" @@ -732,30 +548,6 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "home" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" -dependencies = [ - "windows-sys 0.48.0", -] - -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - [[package]] name = "ident_case" version = "1.0.1" @@ -781,12 +573,9 @@ dependencies = [ "bytemuck", "byteorder", "color_quant", - "dav1d", - "dcv-color-primitives", "exr", "gif", "jpeg-decoder", - "mp4parse", "num-rational", "num-traits", "png", @@ -820,7 +609,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" dependencies = [ "equivalent", - "hashbrown 0.14.1", + "hashbrown", "rayon", ] @@ -1047,18 +836,6 @@ dependencies = [ "mutate_once", ] -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - [[package]] name = "lebe" version = "0.5.2" @@ -1074,6 +851,25 @@ dependencies = [ "cmake", ] +[[package]] +name = "libavif" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de9e3e4b3d7207b3e3a5e88292b304d4daf2d018e4cdc57ec28a6757ab75235c" +dependencies = [ + "libavif-sys 0.15.0", +] + +[[package]] +name = "libavif-image" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00adf2185dbfd6555c2a428b6ab13d1839c58dd9fdf409569ed244c2f54f99a5" +dependencies = [ + "image", + "libavif", +] + [[package]] name = "libavif-sys" version = "0.14.3" @@ -1085,12 +881,32 @@ dependencies = [ "libc", ] +[[package]] +name = "libavif-sys" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baaae0ec93359268f49b6659a7505ba224f0e8f7885535f6a8d14c4aa2a544da" +dependencies = [ + "cmake", + "libc", + "libdav1d-sys", +] + [[package]] name = "libc" version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +[[package]] +name = "libdav1d-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12c9cc342dc258130a727ad15f48d01ebb181aafec30dd65338d8e51db930572" +dependencies = [ + "libc", +] + [[package]] name = "libdeflate-sys" version = "1.19.0" @@ -1119,16 +935,6 @@ dependencies = [ "cc", ] -[[package]] -name = "libloading" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" -dependencies = [ - "cfg-if", - "winapi", -] - [[package]] name = "libwebp-sys" version = "0.9.4" @@ -1139,12 +945,6 @@ dependencies = [ "glob", ] -[[package]] -name = "linux-raw-sys" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" - [[package]] name = "lock_api" version = "0.4.11" @@ -1235,20 +1035,6 @@ dependencies = [ "nasm-rs", ] -[[package]] -name = "mp4parse" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63a35203d3c6ce92d5251c77520acb2e57108c88728695aa883f70023624c570" -dependencies = [ - "bitreader", - "byteorder", - "fallible_collections", - "log", - "num-traits", - "static_assertions", -] - [[package]] name = "mutate_once" version = "0.1.1" @@ -1390,12 +1176,6 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" -[[package]] -name = "peeking_take_while" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" - [[package]] name = "percent-encoding" version = "2.3.0" @@ -1440,7 +1220,7 @@ version = "0.17.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64" dependencies = [ - "bitflags 1.3.2", + "bitflags", "crc32fast", "fdeflate", "flate2", @@ -1601,38 +1381,9 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "regex" -version = "1.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", + "bitflags", ] -[[package]] -name = "regex-automata" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" - [[package]] name = "resize" version = "0.8.2" @@ -1656,14 +1407,15 @@ dependencies = [ name = "rimage" version = "0.9.1" dependencies = [ - "clap 4.4.6", + "clap", "glob", "image", "imagequant", "jpegxl-rs", "jxl-oxide", "kamadak-exif", - "libavif-sys", + "libavif-image", + "libavif-sys 0.14.3", "mozjpeg", "oxipng", "png", @@ -1713,19 +1465,6 @@ dependencies = [ "semver", ] -[[package]] -name = "rustix" -version = "0.38.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" -dependencies = [ - "bitflags 2.4.1", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.48.0", -] - [[package]] name = "scopeguard" version = "1.2.0" @@ -1770,12 +1509,6 @@ dependencies = [ "serde", ] -[[package]] -name = "shlex" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" - [[package]] name = "simd-adler32" version = "0.3.7" @@ -1806,24 +1539,12 @@ dependencies = [ "lock_api", ] -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - [[package]] name = "strength_reduce" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" -[[package]] -name = "strsim" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - [[package]] name = "strsim" version = "0.10.0" @@ -1854,9 +1575,9 @@ dependencies = [ [[package]] name = "system-deps" -version = "6.1.2" +version = "6.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94af52f9402f94aac4948a2518b43359be8d9ce6cd9efc1c4de3b2f7b7e897d6" +checksum = "2a2d580ff6a20c55dfb86be5f9c238f67835d0e81cbdea8bf5680e0897320331" dependencies = [ "cfg-expr", "heck", @@ -1877,24 +1598,6 @@ version = "0.12.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d0e916b1148c8e263850e1ebcbd046f333e0683c724876bb0da63ea4373dc8a" -[[package]] -name = "termcolor" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - [[package]] name = "thiserror" version = "1.0.49" @@ -2050,12 +1753,6 @@ dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-width" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" - [[package]] name = "url" version = "2.4.1" @@ -2086,24 +1783,12 @@ dependencies = [ "rust_hawktracer", ] -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - [[package]] name = "version-compare" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29" -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -2179,65 +1864,13 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" -[[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - [[package]] name = "windows-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-sys" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.0", + "windows-targets", ] [[package]] @@ -2246,28 +1879,13 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" -dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] @@ -2276,84 +1894,42 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" - [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" - [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" -[[package]] -name = "windows_i686_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" - [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" -[[package]] -name = "windows_i686_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" - [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" - [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" - [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" - [[package]] name = "winnow" version = "0.5.17" @@ -2372,26 +1948,6 @@ dependencies = [ "tap", ] -[[package]] -name = "zerocopy" -version = "0.7.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d6f15f7ade05d2a4935e34a457b936c23dc70a05cc1d97133dc99e7a3fe0f0e" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbbad221e3f78500350ecbd7dfa4e63ef945c05f4c61cb7f4d3f84cd0bba649b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.38", -] - [[package]] name = "zopfli" version = "0.8.0" diff --git a/Cargo.toml b/Cargo.toml index 901fac14..718f060a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ parallel = ["mozjpeg/parallel", "imagequant?/threads", "oxipng?/parallel", "jxl- quantization = ["dep:imagequant"] resizing = ["dep:resize"] transform = ["dep:transpose"] -avif = ["dep:libavif-sys", "dep:ravif", "image/avif-decoder"] +avif = ["dep:ravif", "dep:libavif-image"] exif = ["dep:kamadak-exif", "transform"] jxl = ["dep:jxl-oxide"] cli = ["dep:clap", "dep:glob", "quantization", "resizing", "exif"] @@ -45,6 +45,12 @@ ravif = { version = "0.11.2", optional = true } kamadak-exif = { version = "0.5.5", optional = true } clap = { version = "4.4.2", optional = true } +[dependencies.libavif-image] +version = "0.11.0" +optional = true +default-features = false +features = ["codec-dav1d"] + [dependencies.jxl-oxide] version = "0.5.1" default-features = false diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index 5c127d52..7d4b65dd 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -99,6 +99,8 @@ impl Decoder { let image = match self.format { #[cfg(feature = "jxl")] Some(ImageFormat::JpegXl) => self.decode_jpegxl(), + #[cfg(feature = "avif")] + Some(ImageFormat::Avif) => self.decode_avif(), _ => self.r.with_guessed_format()?.decode(), }?; @@ -187,6 +189,22 @@ impl Decoder { ))?, }) } + + #[cfg(feature = "avif")] + fn decode_avif(self) -> ImageResult { + let mut r = self.r.into_inner(); + + let mut buf: Vec = vec![]; + + r.read_to_end(&mut buf)?; + + libavif_image::read(&buf).map_err(|e| { + ImageError::Decoding(DecodingError::new( + ImageFormatHint::Exact(image::ImageFormat::Avif), + e, + )) + }) + } } impl Decoder> { diff --git a/src/decoder/tests.rs b/src/decoder/tests.rs index 861ef897..65cc9237 100644 --- a/src/decoder/tests.rs +++ b/src/decoder/tests.rs @@ -77,10 +77,8 @@ fn fix_orientation() -> Result<(), Box> { } #[test] -#[ignore = "dav1d can't decode avif yet..."] #[cfg(feature = "avif")] fn decode_avif() -> Result<(), Box> { - // TODO: Add decoding of avif images let files = fs::read_dir("tests/files/avif")?; for entry in files { From cf5c5cbeafb682402e850b74fcf1416a7f24f5ab Mon Sep 17 00:00:00 2001 From: Vladyslav Vladinov <111443297+SalOne22@users.noreply.github.com> Date: Sun, 3 Dec 2023 15:06:37 +0100 Subject: [PATCH 04/30] Fixed encoding for mozjpeg --- src/encoder/mod.rs | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/encoder/mod.rs b/src/encoder/mod.rs index 05753fc0..5ed9e58a 100644 --- a/src/encoder/mod.rs +++ b/src/encoder/mod.rs @@ -1,4 +1,4 @@ -use image::{DynamicImage, ImageBuffer}; +use image::{ColorType, DynamicImage, ImageBuffer, ImageResult}; use rgb::FromSlice; use std::io::Write; @@ -110,6 +110,7 @@ impl Encoder { /// # Ok::<(), rimage::error::EncoderError>(()) /// ``` #[allow(unused_mut)] + // TODO: Change Error type to ImageError pub fn encode(mut self) -> Result<(), EncoderError> { // TODO: Move resize out from encoder to operations #[cfg(feature = "resizing")] @@ -198,7 +199,26 @@ impl Encoder { let quality = self.conf.quality(); std::panic::catch_unwind(|| -> Result<(), EncoderError> { - let mut comp = mozjpeg::Compress::new(mozjpeg::ColorSpace::JCS_EXT_RGBA); + let format = match self.data.color() { + ColorType::L8 | ColorType::L16 => mozjpeg::ColorSpace::JCS_GRAYSCALE, + ColorType::La8 | ColorType::La16 => mozjpeg::ColorSpace::JCS_GRAYSCALE, + ColorType::Rgb8 | ColorType::Rgb16 | ColorType::Rgb32F => { + mozjpeg::ColorSpace::JCS_RGB + } + ColorType::Rgba8 | ColorType::Rgba16 | ColorType::Rgba32F => { + mozjpeg::ColorSpace::JCS_EXT_RGBA + } + _ => mozjpeg::ColorSpace::JCS_EXT_RGBA, + }; + + let data = match self.data.color() { + ColorType::La8 | ColorType::La16 => { + DynamicImage::ImageLuma8(self.data.into_luma8()) + } + _ => self.data, + }; + + let mut comp = mozjpeg::Compress::new(format); comp.set_size(width as usize, height as usize); comp.set_quality(quality); @@ -206,7 +226,7 @@ impl Encoder { let mut comp = comp.start_compress(self.w)?; - comp.write_scanlines(self.data.as_bytes())?; + comp.write_scanlines(data.as_bytes())?; comp.finish()?; From 343c4ab4b1c1dc1a275e582dc6d34492c47f77d7 Mon Sep 17 00:00:00 2001 From: Vladyslav Vladinov <111443297+SalOne22@users.noreply.github.com> Date: Tue, 5 Dec 2023 17:17:34 +0100 Subject: [PATCH 05/30] Make all tests passing --- src/decoder/mod.rs | 27 ++++++- src/decoder/tests.rs | 1 - src/encoder/mod.rs | 182 ++++++++++++++++++++++++++++++------------- src/lib.rs | 2 +- 4 files changed, 154 insertions(+), 58 deletions(-) diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index 7d4b65dd..2ee447a8 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -96,7 +96,10 @@ impl Decoder { /// /// Returns a [`Result`] containing the decoded [`Image`] on success or a [`DecoderError`] on failure. pub fn decode(self) -> ImageResult { - let image = match self.format { + #[cfg(feature = "transform")] + let orientation = self.fix_orientation; + + let mut image = match self.format { #[cfg(feature = "jxl")] Some(ImageFormat::JpegXl) => self.decode_jpegxl(), #[cfg(feature = "avif")] @@ -104,6 +107,26 @@ impl Decoder { _ => self.r.with_guessed_format()?.decode(), }?; + #[cfg(feature = "transform")] + if let Some(orientation) = orientation { + if orientation <= 8 { + let orientation = orientation - 1; + + if orientation & 0b100 != 0 { + image = image.rotate90(); + image = image.fliph(); + } + + if orientation & 0b010 != 0 { + image = image.rotate180(); + } + + if orientation & 0b001 != 0 { + image = image.fliph(); + } + } + } + Ok(image) } @@ -230,7 +253,7 @@ impl Decoder> { pub fn from_path(path: impl AsRef) -> ImageResult { Ok(Self { r: ImageReader::open(path.as_ref())?, - format: Some(ImageFormat::from_path(path.as_ref()).map_err(|e| { + format: Some(ImageFormat::from_path(path.as_ref()).map_err(|_| { ImageError::Unsupported(UnsupportedError::from(ImageFormatHint::Unknown)) })?), #[cfg(feature = "transform")] diff --git a/src/decoder/tests.rs b/src/decoder/tests.rs index 65cc9237..825713c4 100644 --- a/src/decoder/tests.rs +++ b/src/decoder/tests.rs @@ -54,7 +54,6 @@ fn new_decoder_with_fixed_orientation() { } #[test] -#[ignore = "needed fixes"] #[cfg(feature = "exif")] fn fix_orientation() -> Result<(), Box> { // TODO: Add transform when exif tag is present diff --git a/src/encoder/mod.rs b/src/encoder/mod.rs index 5ed9e58a..d2d5f467 100644 --- a/src/encoder/mod.rs +++ b/src/encoder/mod.rs @@ -1,18 +1,22 @@ -use image::{ColorType, DynamicImage, ImageBuffer, ImageResult}; +use image::error::ImageFormatHint; +use image::{ + error::EncodingError, ColorType, DynamicImage, ImageBuffer, ImageError, ImageFormat, + ImageResult, +}; use rgb::FromSlice; -use std::io::Write; +use std::io::{Seek, Write}; +use crate::config::EncoderConfig; use crate::config::ResizeType; -use crate::{config::EncoderConfig, error::EncoderError}; /// A struct for encoding images using various codecs. -pub struct Encoder { +pub struct Encoder { w: W, data: DynamicImage, conf: EncoderConfig, } -impl Encoder { +impl Encoder { /// Creates a new [`Encoder`] instance with the specified writer and image data. /// /// # Parameters @@ -107,11 +111,11 @@ impl Encoder { /// /// encoder.encode()?; /// # fs::remove_file("output.jpg")?; - /// # Ok::<(), rimage::error::EncoderError>(()) + /// # Ok::<(), image::ImageError>(()) /// ``` #[allow(unused_mut)] // TODO: Change Error type to ImageError - pub fn encode(mut self) -> Result<(), EncoderError> { + pub fn encode(mut self) -> ImageResult<()> { // TODO: Move resize out from encoder to operations #[cfg(feature = "resizing")] if let Some(resize_config) = self.conf.resize_config() { @@ -150,21 +154,49 @@ impl Encoder { let mut liq = imagequant::new(); - liq.set_speed(5)?; - liq.set_quality(0, quantization_config.quality())?; - - let mut img = liq.new_image_borrowed( - pixels.as_rgba(), - image.width() as usize, - image.height() as usize, - 0.0, - )?; - - let mut res = liq.quantize(&mut img)?; - - res.set_dithering_level(quantization_config.dithering_level())?; - - let (palette, pixels) = res.remapped(&mut img)?; + liq.set_quality(0, quantization_config.quality()) + .map_err(|e| { + ImageError::Encoding(EncodingError::new( + ImageFormatHint::Name("Quantization".to_string()), + e, + )) + })?; + + let mut img = liq + .new_image_borrowed( + pixels.as_rgba(), + image.width() as usize, + image.height() as usize, + 0.0, + ) + .map_err(|e| { + ImageError::Encoding(EncodingError::new( + ImageFormatHint::Name("Quantization".to_string()), + e, + )) + })?; + + let mut res = liq.quantize(&mut img).map_err(|e| { + ImageError::Encoding(EncodingError::new( + ImageFormatHint::Name("Quantization".to_string()), + e, + )) + })?; + + res.set_dithering_level(quantization_config.dithering_level()) + .map_err(|e| { + ImageError::Encoding(EncodingError::new( + ImageFormatHint::Name("Quantization".to_string()), + e, + )) + })?; + + let (palette, pixels) = res.remapped(&mut img).map_err(|e| { + ImageError::Encoding(EncodingError::new( + ImageFormatHint::Name("Quantization".to_string()), + e, + )) + })?; self.data = DynamicImage::ImageRgba8( ImageBuffer::from_raw( @@ -175,30 +207,57 @@ impl Encoder { .flat_map(|pix| palette[*pix as usize].iter()) .collect::>(), ) - .ok_or(EncoderError::General)?, + .ok_or(ImageError::Encoding(EncodingError::from_format_hint( + ImageFormatHint::Name("Quantization".to_string()), + )))?, ); } match self.conf.codec() { - crate::config::Codec::MozJpeg => self.encode_mozjpeg(), + crate::config::Codec::MozJpeg => self.encode_mozjpeg().map_err(|e| { + ImageError::Encoding(EncodingError::new( + ImageFormatHint::Exact(ImageFormat::Jpeg), + e, + )) + }), crate::config::Codec::Png => self.encode_png(), #[cfg(feature = "jxl")] - crate::config::Codec::JpegXl => self.encode_jpegxl(), + crate::config::Codec::JpegXl => self.encode_jpegxl().map_err(|e| { + ImageError::Encoding(EncodingError::new( + ImageFormatHint::Name("JpegXL".to_string()), + e, + )) + }), #[cfg(feature = "oxipng")] - crate::config::Codec::OxiPng => self.encode_oxipng(), + crate::config::Codec::OxiPng => self.encode_oxipng().map_err(|e| { + ImageError::Encoding(EncodingError::new( + ImageFormatHint::Exact(ImageFormat::Png), + e, + )) + }), #[cfg(feature = "webp")] - crate::config::Codec::WebP => self.encode_webp(), + crate::config::Codec::WebP => self.encode_webp().map_err(|e| { + ImageError::Encoding(EncodingError::new( + ImageFormatHint::Exact(ImageFormat::WebP), + e, + )) + }), #[cfg(feature = "avif")] - crate::config::Codec::Avif => self.encode_avif(), + crate::config::Codec::Avif => self.encode_avif().map_err(|e| { + ImageError::Encoding(EncodingError::new( + ImageFormatHint::Exact(ImageFormat::Avif), + e, + )) + }), } } - fn encode_mozjpeg(self) -> Result<(), EncoderError> { + fn encode_mozjpeg(self) -> ImageResult<()> { let width = self.data.width(); let height = self.data.height(); let quality = self.conf.quality(); - std::panic::catch_unwind(|| -> Result<(), EncoderError> { + std::panic::catch_unwind(|| -> ImageResult<()> { let format = match self.data.color() { ColorType::L8 | ColorType::L16 => mozjpeg::ColorSpace::JCS_GRAYSCALE, ColorType::La8 | ColorType::La16 => mozjpeg::ColorSpace::JCS_GRAYSCALE, @@ -232,33 +291,24 @@ impl Encoder { Ok(()) }) - .map_err(|_| EncoderError::General)? + .map_err(|_| { + ImageError::Encoding(EncodingError::from_format_hint(ImageFormatHint::Exact( + ImageFormat::Jpeg, + ))) + })? } - fn encode_png(self) -> Result<(), EncoderError> { - let width = self.data.width(); - let height = self.data.height(); - - let mut encoder = png::Encoder::new(self.w, width, height); - - encoder.set_color(png::ColorType::Rgba); - encoder.set_depth(png::BitDepth::Eight); - - let mut writer = encoder.write_header()?; - - writer.write_image_data(self.data.as_bytes())?; - writer.finish()?; - - Ok(()) + fn encode_png(mut self) -> ImageResult<()> { + self.data.write_to(&mut self.w, ImageFormat::Png) } #[cfg(feature = "jxl")] - fn encode_jpegxl(mut self) -> Result<(), EncoderError> { + fn encode_jpegxl(mut self) -> ImageResult<()> { unimplemented!() } #[cfg(feature = "oxipng")] - fn encode_oxipng(mut self) -> Result<(), EncoderError> { + fn encode_oxipng(mut self) -> ImageResult<()> { let width = self.data.width(); let height = self.data.height(); @@ -270,15 +320,33 @@ impl Encoder { oxipng::ColorType::RGBA, oxipng::BitDepth::Eight, self.data.as_bytes().to_vec(), - )?; - - self.w.write_all(&img.create_optimized_png(&options)?)?; + ) + .map_err(|e| { + ImageError::Encoding(EncodingError::new( + ImageFormatHint::Exact(ImageFormat::Png), + e, + )) + })?; + + self.w + .write_all(&img.create_optimized_png(&options).map_err(|e| { + ImageError::Encoding(EncodingError::new( + ImageFormatHint::Exact(ImageFormat::Png), + e, + )) + })?) + .map_err(|e| { + ImageError::Encoding(EncodingError::new( + ImageFormatHint::Exact(ImageFormat::Png), + e, + )) + })?; Ok(()) } #[cfg(feature = "webp")] - fn encode_webp(mut self) -> Result<(), EncoderError> { + fn encode_webp(mut self) -> ImageResult<()> { let width = self.data.width(); let height = self.data.height(); @@ -291,7 +359,7 @@ impl Encoder { } #[cfg(feature = "avif")] - fn encode_avif(mut self) -> Result<(), EncoderError> { + fn encode_avif(mut self) -> ImageResult<()> { let width = self.data.width(); let height = self.data.height(); @@ -302,7 +370,13 @@ impl Encoder { self.data.into_rgba8().as_rgba(), width as usize, height as usize, - ))?; + )) + .map_err(|e| { + ImageError::Encoding(EncodingError::new( + ImageFormatHint::Exact(ImageFormat::Avif), + e, + )) + })?; self.w.write_all(&img.avif_file)?; self.w.flush()?; diff --git a/src/lib.rs b/src/lib.rs index 13a8ac99..56c4e3d6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -63,7 +63,7 @@ let encoder = Encoder::new(file, DynamicImage::ImageRgba8(image)).with_config(co encoder.encode()?; # std::fs::remove_file("output.jpg").unwrap_or(()); -# Ok::<(), rimage::error::EncoderError>(()) +# Ok::<(), image::ImageError>(()) ``` */ From 7208aa2894ea854929217f7e7511cc9967853ac1 Mon Sep 17 00:00:00 2001 From: Vladyslav Vladinov <111443297+SalOne22@users.noreply.github.com> Date: Tue, 5 Dec 2023 18:24:57 +0100 Subject: [PATCH 06/30] Removed direct webp dependecy --- Cargo.lock | 2 +- Cargo.toml | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 85ba861f..f8057410 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -581,6 +581,7 @@ dependencies = [ "png", "qoi", "tiff", + "webp", ] [[package]] @@ -1425,7 +1426,6 @@ dependencies = [ "rgb", "thiserror", "transpose", - "webp", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 718f060a..f79783cf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,7 @@ transform = ["dep:transpose"] avif = ["dep:ravif", "dep:libavif-image"] exif = ["dep:kamadak-exif", "transform"] jxl = ["dep:jxl-oxide"] +webp = ["image/webp-encoder"] cli = ["dep:clap", "dep:glob", "quantization", "resizing", "exif"] @@ -72,11 +73,6 @@ features = ["zopfli", "filetime"] default-features = false optional = true -[dependencies.webp] -version = "0.2.6" -default-features = false -optional = true - [dependencies.libavif-sys] version = "0.14.3" features = ["codec-aom"] From a9dbcf0d7416ad78b30f575daff41f99dc15991b Mon Sep 17 00:00:00 2001 From: Vladyslav Vladinov <111443297+SalOne22@users.noreply.github.com> Date: Tue, 5 Dec 2023 18:25:23 +0100 Subject: [PATCH 07/30] Added encoder implementation for webp --- src/encoder/mod.rs | 102 ++++++++++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 44 deletions(-) diff --git a/src/encoder/mod.rs b/src/encoder/mod.rs index d2d5f467..40882015 100644 --- a/src/encoder/mod.rs +++ b/src/encoder/mod.rs @@ -1,4 +1,5 @@ -use image::error::ImageFormatHint; +use image::codecs::webp::WebPQuality; +use image::error::{ImageFormatHint, UnsupportedError, UnsupportedErrorKind}; use image::{ error::EncodingError, ColorType, DynamicImage, ImageBuffer, ImageError, ImageFormat, ImageResult, @@ -114,7 +115,6 @@ impl Encoder { /// # Ok::<(), image::ImageError>(()) /// ``` #[allow(unused_mut)] - // TODO: Change Error type to ImageError pub fn encode(mut self) -> ImageResult<()> { // TODO: Move resize out from encoder to operations #[cfg(feature = "resizing")] @@ -214,41 +214,16 @@ impl Encoder { } match self.conf.codec() { - crate::config::Codec::MozJpeg => self.encode_mozjpeg().map_err(|e| { - ImageError::Encoding(EncodingError::new( - ImageFormatHint::Exact(ImageFormat::Jpeg), - e, - )) - }), + crate::config::Codec::MozJpeg => self.encode_mozjpeg(), crate::config::Codec::Png => self.encode_png(), #[cfg(feature = "jxl")] - crate::config::Codec::JpegXl => self.encode_jpegxl().map_err(|e| { - ImageError::Encoding(EncodingError::new( - ImageFormatHint::Name("JpegXL".to_string()), - e, - )) - }), + crate::config::Codec::JpegXl => self.encode_jpegxl(), #[cfg(feature = "oxipng")] - crate::config::Codec::OxiPng => self.encode_oxipng().map_err(|e| { - ImageError::Encoding(EncodingError::new( - ImageFormatHint::Exact(ImageFormat::Png), - e, - )) - }), + crate::config::Codec::OxiPng => self.encode_oxipng(), #[cfg(feature = "webp")] - crate::config::Codec::WebP => self.encode_webp().map_err(|e| { - ImageError::Encoding(EncodingError::new( - ImageFormatHint::Exact(ImageFormat::WebP), - e, - )) - }), + crate::config::Codec::WebP => self.encode_webp(), #[cfg(feature = "avif")] - crate::config::Codec::Avif => self.encode_avif().map_err(|e| { - ImageError::Encoding(EncodingError::new( - ImageFormatHint::Exact(ImageFormat::Avif), - e, - )) - }), + crate::config::Codec::Avif => self.encode_avif(), } } @@ -314,11 +289,48 @@ impl Encoder { let options = oxipng::Options::default(); + let (color_type, bit_depth) = match self.data.color() { + ColorType::L8 => ( + oxipng::ColorType::Grayscale { + transparent_shade: None, + }, + oxipng::BitDepth::Eight, + ), + ColorType::La8 => (oxipng::ColorType::GrayscaleAlpha, oxipng::BitDepth::Eight), + ColorType::Rgb8 => ( + oxipng::ColorType::RGB { + transparent_color: None, + }, + oxipng::BitDepth::Eight, + ), + ColorType::Rgba8 => (oxipng::ColorType::RGBA, oxipng::BitDepth::Eight), + ColorType::L16 => ( + oxipng::ColorType::Grayscale { + transparent_shade: None, + }, + oxipng::BitDepth::Sixteen, + ), + ColorType::La16 => (oxipng::ColorType::GrayscaleAlpha, oxipng::BitDepth::Sixteen), + ColorType::Rgb16 => ( + oxipng::ColorType::RGB { + transparent_color: None, + }, + oxipng::BitDepth::Sixteen, + ), + ColorType::Rgba16 => (oxipng::ColorType::RGBA, oxipng::BitDepth::Sixteen), + color => Err(ImageError::Unsupported( + UnsupportedError::from_format_and_kind( + ImageFormatHint::Exact(ImageFormat::Png), + UnsupportedErrorKind::Color(color.into()), + ), + ))?, + }; + let img = oxipng::RawImage::new( width, height, - oxipng::ColorType::RGBA, - oxipng::BitDepth::Eight, + color_type, + bit_depth, self.data.as_bytes().to_vec(), ) .map_err(|e| { @@ -346,16 +358,18 @@ impl Encoder { } #[cfg(feature = "webp")] - fn encode_webp(mut self) -> ImageResult<()> { - let width = self.data.width(); - let height = self.data.height(); - - let encoder = webp::Encoder::from_rgba(self.data.as_bytes(), width, height); - - self.w.write_all(&encoder.encode(self.conf.quality()))?; - self.w.flush()?; - - Ok(()) + fn encode_webp(self) -> ImageResult<()> { + let image = match self.data.color() { + ColorType::Rgb8 | ColorType::Rgba8 => self.data, + _ => DynamicImage::ImageRgba8(self.data.into_rgba8()), + }; + + let encoder = image::codecs::webp::WebPEncoder::new_with_quality( + self.w, + WebPQuality::lossy(self.conf.quality().round() as u8), + ); + + image.write_with_encoder(encoder) } #[cfg(feature = "avif")] From de71004714df477fa11212de4f8de29d86665353 Mon Sep 17 00:00:00 2001 From: Vladyslav Vladinov <111443297+SalOne22@users.noreply.github.com> Date: Tue, 5 Dec 2023 19:05:50 +0100 Subject: [PATCH 08/30] Added encoder implementation for jxl (only lossless) --- Cargo.lock | 175 ++++++++------------------------------------- Cargo.toml | 33 ++++----- src/encoder/mod.rs | 53 +++++++++++--- src/error.rs | 18 ++--- 4 files changed, 97 insertions(+), 182 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f8057410..cf5df77a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -320,72 +320,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" -[[package]] -name = "darling" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 1.0.109", -] - -[[package]] -name = "darling_macro" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" -dependencies = [ - "darling_core", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "derive_builder" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8" -dependencies = [ - "derive_builder_macro", -] - -[[package]] -name = "derive_builder_core" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "derive_builder_macro" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e" -dependencies = [ - "derive_builder_core", - "syn 1.0.109", -] - [[package]] name = "dunce" version = "1.0.4" @@ -464,12 +398,6 @@ dependencies = [ "spin", ] -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - [[package]] name = "form_urlencoded" version = "1.2.0" @@ -548,12 +476,6 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - [[package]] name = "idna" version = "0.4.0" @@ -652,43 +574,11 @@ dependencies = [ "rayon", ] -[[package]] -name = "jpegxl-rs" -version = "0.8.3+libjxl-0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35d93499577a4b5072cc59b6c45436f42854209152ecbcfd1e88aa1b45883d70" -dependencies = [ - "byteorder", - "derive_builder", - "half", - "jpegxl-sys", - "thiserror", -] - -[[package]] -name = "jpegxl-src" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81048fc7b31ebcf4393527f70d211824359a4a266f63fee50a5e5ba5fee18579" -dependencies = [ - "cmake", -] - -[[package]] -name = "jpegxl-sys" -version = "0.8.2+libjxl-0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b907f540220390b54d9845eb5fe6a8f0453a0ea4f1e2e306cdbdbe8ee027d540" -dependencies = [ - "jpegxl-src", - "pkg-config", -] - [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" dependencies = [ "wasm-bindgen", ] @@ -843,22 +733,13 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" -[[package]] -name = "libaom-sys" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "610241493fe5178968c3d3b27b6c397dd873244ca17539bb488ade05690fcd71" -dependencies = [ - "cmake", -] - [[package]] name = "libavif" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de9e3e4b3d7207b3e3a5e88292b304d4daf2d018e4cdc57ec28a6757ab75235c" dependencies = [ - "libavif-sys 0.15.0", + "libavif-sys", ] [[package]] @@ -871,17 +752,6 @@ dependencies = [ "libavif", ] -[[package]] -name = "libavif-sys" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c7b9293d221c7d4b4290d4479c491a09b877943208593f1563d8521c4b55930" -dependencies = [ - "cmake", - "libaom-sys", - "libc", -] - [[package]] name = "libavif-sys" version = "0.15.0" @@ -1412,11 +1282,9 @@ dependencies = [ "glob", "image", "imagequant", - "jpegxl-rs", "jxl-oxide", "kamadak-exif", "libavif-image", - "libavif-sys 0.14.3", "mozjpeg", "oxipng", "png", @@ -1426,6 +1294,8 @@ dependencies = [ "rgb", "thiserror", "transpose", + "zune-core", + "zune-jpegxl", ] [[package]] @@ -1797,9 +1667,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1807,9 +1677,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" dependencies = [ "bumpalo", "log", @@ -1822,9 +1692,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1832,9 +1702,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" dependencies = [ "proc-macro2", "quote", @@ -1845,9 +1715,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" [[package]] name = "webp" @@ -1960,6 +1830,12 @@ dependencies = [ "typed-arena", ] +[[package]] +name = "zune-core" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aae122f32a8e2a653acb430c9af5e79e7056c519fa8bac46e51e670868e5c0f2" + [[package]] name = "zune-inflate" version = "0.2.54" @@ -1968,3 +1844,12 @@ checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" dependencies = [ "simd-adler32", ] + +[[package]] +name = "zune-jpegxl" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71ffee484384b15f99ed4768bfdb3fa186d63e1f8c3aafba1d6d141a7b9e3674" +dependencies = [ + "zune-core", +] diff --git a/Cargo.toml b/Cargo.toml index f79783cf..773c7055 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,13 +23,13 @@ codegen-units = 1 [features] default = ["cli", "parallel", "quantization", "resizing", "exif", "oxipng"] -parallel = ["mozjpeg/parallel", "imagequant?/threads", "oxipng?/parallel", "jxl-oxide?/rayon", "dep:rayon"] +parallel = ["mozjpeg/parallel", "imagequant?/threads", "oxipng?/parallel", "jxl-oxide?/rayon", "zune-jpegxl?/threads", "dep:rayon"] quantization = ["dep:imagequant"] resizing = ["dep:resize"] transform = ["dep:transpose"] avif = ["dep:ravif", "dep:libavif-image"] exif = ["dep:kamadak-exif", "transform"] -jxl = ["dep:jxl-oxide"] +jxl = ["dep:jxl-oxide", "dep:zune-jpegxl", "dep:zune-core"] webp = ["image/webp-encoder"] cli = ["dep:clap", "dep:glob", "quantization", "resizing", "exif"] @@ -57,6 +57,17 @@ version = "0.5.1" default-features = false optional = true +[dependencies.zune-core] +version = "0.4.11" +default-features = false +optional = true + +[dependencies.zune-jpegxl] +version = "0.4.0" +default-features = false +features = ["std"] +optional = true + [dependencies.imagequant] version = "4.2.1" default-features = false @@ -73,24 +84,6 @@ features = ["zopfli", "filetime"] default-features = false optional = true -[dependencies.libavif-sys] -version = "0.14.3" -features = ["codec-aom"] -default-features = false -optional = true - -# Because libjxl cant be build on x86_64 macos -[target.'cfg(not(all(target_os = "macos", target_arch = "x86_64")))'.dependencies.jpegxl-rs] -version = "0.8.2+libjxl-0.8.2" -default-features = false -features = ["vendored"] -optional = true - -[target.'cfg(all(target_os = "macos", target_arch = "x86_64"))'.dependencies.jpegxl-rs] -version = "0.8.2+libjxl-0.8.2" -default-features = false -optional = true - [target.'cfg(windows)'.dependencies.glob] optional = true version = "0.3.1" diff --git a/src/encoder/mod.rs b/src/encoder/mod.rs index 40882015..012f177e 100644 --- a/src/encoder/mod.rs +++ b/src/encoder/mod.rs @@ -1,4 +1,3 @@ -use image::codecs::webp::WebPQuality; use image::error::{ImageFormatHint, UnsupportedError, UnsupportedErrorKind}; use image::{ error::EncodingError, ColorType, DynamicImage, ImageBuffer, ImageError, ImageFormat, @@ -279,7 +278,47 @@ impl Encoder { #[cfg(feature = "jxl")] fn encode_jpegxl(mut self) -> ImageResult<()> { - unimplemented!() + use crate::error::JxlEncodingError; + use zune_core::bit_depth::BitDepth; + use zune_core::colorspace::ColorSpace; + use zune_core::options::EncoderOptions; + use zune_jpegxl::JxlSimpleEncoder; + + let width = self.data.width(); + let height = self.data.height(); + + let (color_space, bit_depth) = match self.data.color() { + ColorType::L8 => (ColorSpace::Luma, BitDepth::Eight), + ColorType::La8 => (ColorSpace::LumaA, BitDepth::Eight), + ColorType::Rgb8 => (ColorSpace::RGB, BitDepth::Eight), + ColorType::Rgba8 => (ColorSpace::RGBA, BitDepth::Eight), + ColorType::L16 => (ColorSpace::Luma, BitDepth::Sixteen), + ColorType::La16 => (ColorSpace::LumaA, BitDepth::Sixteen), + ColorType::Rgb16 => (ColorSpace::RGB, BitDepth::Sixteen), + ColorType::Rgba16 => (ColorSpace::RGBA, BitDepth::Sixteen), + ColorType::Rgb32F => (ColorSpace::RGB, BitDepth::Float32), + ColorType::Rgba32F => (ColorSpace::RGBA, BitDepth::Float32), + color => Err(ImageError::Unsupported( + UnsupportedError::from_format_and_kind( + ImageFormatHint::Name("JpegXL".to_string()), + UnsupportedErrorKind::Color(color.into()), + ), + ))?, + }; + + let options = EncoderOptions::new(width as usize, height as usize, color_space, bit_depth); + let encoder = JxlSimpleEncoder::new(self.data.as_bytes(), options); + + let data = encoder.encode().map_err(|e| { + ImageError::Encoding(EncodingError::new( + ImageFormatHint::Name("JpegXL".to_string()), + JxlEncodingError(e), + )) + })?; + + self.w.write_all(&data)?; + + Ok(()) } #[cfg(feature = "oxipng")] @@ -346,19 +385,15 @@ impl Encoder { ImageFormatHint::Exact(ImageFormat::Png), e, )) - })?) - .map_err(|e| { - ImageError::Encoding(EncodingError::new( - ImageFormatHint::Exact(ImageFormat::Png), - e, - )) - })?; + })?)?; Ok(()) } #[cfg(feature = "webp")] fn encode_webp(self) -> ImageResult<()> { + use image::codecs::webp::WebPQuality; + let image = match self.data.color() { ColorType::Rgb8 | ColorType::Rgba8 => self.data, _ => DynamicImage::ImageRgba8(self.data.into_rgba8()), diff --git a/src/error.rs b/src/error.rs index ca75dfff..e60a58a2 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,6 +1,8 @@ use std::io; use thiserror::Error; +#[cfg(feature = "jxl")] +use zune_jpegxl::JxlEncodeErrors; /// Error type for invalid quantization configuration. /// @@ -43,7 +45,7 @@ pub enum ImageFormatError { pub enum EncoderError { /// Error indicating an I/O (input/output) operation failure. #[error(transparent)] - Io(#[from] std::io::Error), + Io(#[from] io::Error), /// Error indicating an overflow or conversion error. #[error(transparent)] @@ -64,9 +66,9 @@ pub enum EncoderError { Png(#[from] png::EncodingError), /// Error indicating an encoding failure for the JPEG XL format. - #[error(transparent)] + #[error("{0:?}")] #[cfg(feature = "jxl")] - JpegXl(#[from] jpegxl_rs::EncodeError), + JpegXl(JxlEncodeErrors), /// Error indicating an error during the encoding of PNG images with oxipng. #[error(transparent)] @@ -107,17 +109,17 @@ pub enum DecoderError { #[cfg(feature = "avif")] Avif(u32), - /// An error occurred during JPEG XL image decoding. - #[error(transparent)] - #[cfg(feature = "jxl")] - JpegXl(#[from] jpegxl_rs::DecodeError), - /// An error occurred when decoding WebP image format with libwebp. #[error("Failed to decode WebP with libwebp")] #[cfg(feature = "webp")] WebP, } +#[cfg(feature = "jxl")] +#[derive(Error, Debug)] +#[error("{0:?}")] +pub struct JxlEncodingError(pub JxlEncodeErrors); + #[cfg(test)] mod tests { // Import the necessary dependencies from the code From 6ea26aaa09cb02fa1c6d130ba98679cf4adb43ca Mon Sep 17 00:00:00 2001 From: Vladyslav Vladinov <111443297+SalOne22@users.noreply.github.com> Date: Tue, 5 Dec 2023 19:14:33 +0100 Subject: [PATCH 09/30] Updated workflow --- .github/workflows/rimage.yml | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/.github/workflows/rimage.yml b/.github/workflows/rimage.yml index 9c3913ab..07b26072 100644 --- a/.github/workflows/rimage.yml +++ b/.github/workflows/rimage.yml @@ -79,9 +79,8 @@ jobs: - name: Setup nasm ๐Ÿง‘โ€๐Ÿ’ป uses: ilammy/setup-nasm@v1 - - name: Setup libjxl ๐Ÿง‘โ€๐Ÿ’ป (x86_64 macos) - if: matrix.target == 'x86_64-apple-darwin' - run: brew install jpeg-xl + - name: Setup meson + ninja ๐Ÿง‘โ€๐Ÿ’ป + run: pip3 install --user meson ninja - name: Setup rust toolchain ๐Ÿฆ€ uses: actions-rs/toolchain@v1 @@ -90,22 +89,12 @@ jobs: toolchain: stable target: ${{ matrix.target }} - - name: Build ๐Ÿ— (not msvc) - if: matrix.target != 'x86_64-pc-windows-msvc' + - name: Build ๐Ÿ— uses: actions-rs/cargo@v1 with: command: build args: --all-features --release - - name: Build ๐Ÿ— (msvc) - if: matrix.target == 'x86_64-pc-windows-msvc' - shell: cmd - run: | - call "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Auxiliary/Build/vcvars64.bat" - set CC=C:/Program Files/LLVM/bin/clang.exe - set CXX=C:/Program Files/LLVM/bin/clang++.exe - cargo build --all-features --release - - name: Test ๐Ÿงช if: matrix.target == 'x86_64-unknown-linux-gnu' || matrix.target == 'x86_64-apple-darwin' uses: actions-rs/cargo@v1 @@ -143,6 +132,9 @@ jobs: - name: Setup nasm ๐Ÿง‘โ€๐Ÿ’ป uses: ilammy/setup-nasm@v1 + - name: Setup meson + ninja ๐Ÿง‘โ€๐Ÿ’ป + run: pip3 install --user meson ninja + - name: Setup rust toolchain ๐Ÿฆ€ uses: actions-rs/toolchain@v1 with: From 0a2856718496ed5a835fba1c0111d2a7c7b714e8 Mon Sep 17 00:00:00 2001 From: Vladyslav Vladinov <111443297+SalOne22@users.noreply.github.com> Date: Tue, 5 Dec 2023 19:28:38 +0100 Subject: [PATCH 10/30] Added wasm target to workflow, fixed dependencies --- .github/workflows/rimage.yml | 61 ++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/.github/workflows/rimage.yml b/.github/workflows/rimage.yml index 07b26072..49e38d82 100644 --- a/.github/workflows/rimage.yml +++ b/.github/workflows/rimage.yml @@ -34,9 +34,11 @@ jobs: target-apt-arch: amd64 - target: aarch64-unknown-linux-gnu os: ubuntu-latest + - target: wasm32-unknown-unknown + os: ubuntu-latest target-apt-arch: arm64 - target: x86_64-pc-windows-gnu - os: windows-latest + os: windows-2019 - target: x86_64-pc-windows-msvc os: windows-2019 - target: x86_64-apple-darwin @@ -76,11 +78,30 @@ jobs: target/ key: ${{ matrix.target }}-cargo-${{ hashFiles('**/Cargo.lock') }} - - name: Setup nasm ๐Ÿง‘โ€๐Ÿ’ป - uses: ilammy/setup-nasm@v1 + - name: Install dependencies (linux) + if: matrix.os == 'ubuntu-latest' + run: | + DEBIAN_FRONTEND=noninteractive sudo apt-get update + DEBIAN_FRONTEND=noninteractive sudo apt-get install -y ninja-build nasm meson - - name: Setup meson + ninja ๐Ÿง‘โ€๐Ÿ’ป - run: pip3 install --user meson ninja + - name: Install dependencies (macos) + if: matrix.os == 'macos-latest' + run: | + brew install ninja nasm meson + + - name: Install emcc + if: matrix.target == 'wasm32-unknown-unknown' + run: brew install emscripten + + - name: Install dependencies (windows) + if: matrix.os == 'windows-2019' + run: | + choco install -y ninja + pip install meson + + - name: Install nasm (windows) + if: matrix.os == 'windows-2019' + uses: ilammy/setup-nasm@v1 - name: Setup rust toolchain ๐Ÿฆ€ uses: actions-rs/toolchain@v1 @@ -89,18 +110,26 @@ jobs: toolchain: stable target: ${{ matrix.target }} - - name: Build ๐Ÿ— - uses: actions-rs/cargo@v1 - with: - command: build - args: --all-features --release + - name: Test ๐Ÿงช (windows) + if: matrix.os == 'windows-2019' + shell: cmd + run: | + call "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Auxiliary/Build/vcvars64.bat" + cargo test ${{ matrix.features }} --target ${{ matrix.target }} - - name: Test ๐Ÿงช - if: matrix.target == 'x86_64-unknown-linux-gnu' || matrix.target == 'x86_64-apple-darwin' - uses: actions-rs/cargo@v1 - with: - command: test - args: --all-features --release + - name: Test ๐Ÿงช (unix) + if: ${{ matrix.os != 'windows-2019' && matrix.target != 'wasm32-unknown-unknown' }} + run: | + cargo test ${{ matrix.features }} --target ${{ matrix.target }} + + - name: Check wasm + if: matrix.target == 'wasm32-unknown-unknown' + run: | + export EMSCRIPTEN_CMAKE_FILE="$(brew --cellar emscripten)/$(brew list --versions emscripten | tr ' ' '\n' | tail -1)/libexec/cmake/Modules/Platform/Emscripten.cmake" + cargo check ${{ matrix.features }} --target ${{ matrix.target }} + env: + CC: 'emcc' + CXX: 'emcc' - name: Upload CLI binary as artifact ๐Ÿ’พ uses: actions/upload-artifact@v3 From bccb20772f6274227e91cd1345ff29b288e98bd4 Mon Sep 17 00:00:00 2001 From: Vladyslav Vladinov <111443297+SalOne22@users.noreply.github.com> Date: Tue, 5 Dec 2023 19:39:45 +0100 Subject: [PATCH 11/30] Fix workflow --- .github/workflows/rimage.yml | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/.github/workflows/rimage.yml b/.github/workflows/rimage.yml index 49e38d82..69670edb 100644 --- a/.github/workflows/rimage.yml +++ b/.github/workflows/rimage.yml @@ -91,7 +91,7 @@ jobs: - name: Install emcc if: matrix.target == 'wasm32-unknown-unknown' - run: brew install emscripten + run: DEBIAN_FRONTEND=noninteractive sudo apt-get install -y emscripten - name: Install dependencies (windows) if: matrix.os == 'windows-2019' @@ -110,23 +110,35 @@ jobs: toolchain: stable target: ${{ matrix.target }} + - name: Build ๐Ÿ—๏ธ (windows) + if: matrix.os == 'windows-2019' + shell: cmd + run: | + call "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Auxiliary/Build/vcvars64.bat" + cargo build --all-features --target ${{ matrix.target }} + + - name: Build ๐Ÿ—๏ธ (unix) + if: ${{ matrix.os != 'windows-2019' && matrix.target != 'wasm32-unknown-unknown' }} + run: | + cargo build --all-features --target ${{ matrix.target }} + - name: Test ๐Ÿงช (windows) if: matrix.os == 'windows-2019' shell: cmd run: | call "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Auxiliary/Build/vcvars64.bat" - cargo test ${{ matrix.features }} --target ${{ matrix.target }} + cargo test --all-features --target ${{ matrix.target }} - name: Test ๐Ÿงช (unix) - if: ${{ matrix.os != 'windows-2019' && matrix.target != 'wasm32-unknown-unknown' }} + if: ${{ matrix.os != 'windows-2019' && matrix.target != 'wasm32-unknown-unknown' && matrix.target != 'aarch64-apple-darwin' && matrix.target != 'aarch64-unknown-linux-gnu' }} run: | - cargo test ${{ matrix.features }} --target ${{ matrix.target }} + cargo test --all-features --target ${{ matrix.target }} - name: Check wasm if: matrix.target == 'wasm32-unknown-unknown' run: | export EMSCRIPTEN_CMAKE_FILE="$(brew --cellar emscripten)/$(brew list --versions emscripten | tr ' ' '\n' | tail -1)/libexec/cmake/Modules/Platform/Emscripten.cmake" - cargo check ${{ matrix.features }} --target ${{ matrix.target }} + cargo check --all-features --target ${{ matrix.target }} env: CC: 'emcc' CXX: 'emcc' From f2ead669420ba5006e6a8c00a895a45245dbb6e1 Mon Sep 17 00:00:00 2001 From: Vladyslav Vladinov <111443297+SalOne22@users.noreply.github.com> Date: Wed, 13 Dec 2023 12:43:21 +0100 Subject: [PATCH 12/30] Fix workflow --- .github/workflows/rimage.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/rimage.yml b/.github/workflows/rimage.yml index 69670edb..b9aa5fde 100644 --- a/.github/workflows/rimage.yml +++ b/.github/workflows/rimage.yml @@ -34,9 +34,10 @@ jobs: target-apt-arch: amd64 - target: aarch64-unknown-linux-gnu os: ubuntu-latest + target-apt-arch: arm64 - target: wasm32-unknown-unknown os: ubuntu-latest - target-apt-arch: arm64 + target-apt-arch: amd64 - target: x86_64-pc-windows-gnu os: windows-2019 - target: x86_64-pc-windows-msvc From d065d0d84ddef903e7e0fd762c5d30b54e6ccec5 Mon Sep 17 00:00:00 2001 From: Vladyslav Vladinov <111443297+SalOne22@users.noreply.github.com> Date: Wed, 13 Dec 2023 12:56:34 +0100 Subject: [PATCH 13/30] Used aom codec instead of the dav1d codec --- Cargo.lock | 20 ++++++++++---------- Cargo.toml | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cf5df77a..1cd6c6a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -733,6 +733,15 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" +[[package]] +name = "libaom-sys" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0d9c253ce9c1915ad89563d19d0b9011b937891d7b9361e831de8e4ebe2fb50" +dependencies = [ + "cmake", +] + [[package]] name = "libavif" version = "0.12.0" @@ -759,8 +768,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baaae0ec93359268f49b6659a7505ba224f0e8f7885535f6a8d14c4aa2a544da" dependencies = [ "cmake", + "libaom-sys", "libc", - "libdav1d-sys", ] [[package]] @@ -769,15 +778,6 @@ version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" -[[package]] -name = "libdav1d-sys" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12c9cc342dc258130a727ad15f48d01ebb181aafec30dd65338d8e51db930572" -dependencies = [ - "libc", -] - [[package]] name = "libdeflate-sys" version = "1.19.0" diff --git a/Cargo.toml b/Cargo.toml index 773c7055..e622e673 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,7 +50,7 @@ clap = { version = "4.4.2", optional = true } version = "0.11.0" optional = true default-features = false -features = ["codec-dav1d"] +features = ["codec-aom"] [dependencies.jxl-oxide] version = "0.5.1" From 468088b53f244c9e9277e5ed5fa2380962c69632 Mon Sep 17 00:00:00 2001 From: Vladyslav Vladinov <111443297+SalOne22@users.noreply.github.com> Date: Wed, 13 Dec 2023 13:09:59 +0100 Subject: [PATCH 14/30] Fixed emcc installation --- .github/workflows/rimage.yml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/.github/workflows/rimage.yml b/.github/workflows/rimage.yml index b9aa5fde..0b2b0d86 100644 --- a/.github/workflows/rimage.yml +++ b/.github/workflows/rimage.yml @@ -36,7 +36,7 @@ jobs: os: ubuntu-latest target-apt-arch: arm64 - target: wasm32-unknown-unknown - os: ubuntu-latest + os: macos-latest target-apt-arch: amd64 - target: x86_64-pc-windows-gnu os: windows-2019 @@ -92,18 +92,14 @@ jobs: - name: Install emcc if: matrix.target == 'wasm32-unknown-unknown' - run: DEBIAN_FRONTEND=noninteractive sudo apt-get install -y emscripten + run: brew install emscripten - name: Install dependencies (windows) if: matrix.os == 'windows-2019' run: | - choco install -y ninja + choco install -y ninja nasm pip install meson - - name: Install nasm (windows) - if: matrix.os == 'windows-2019' - uses: ilammy/setup-nasm@v1 - - name: Setup rust toolchain ๐Ÿฆ€ uses: actions-rs/toolchain@v1 with: From 927439e6b2500a054758aa06fad682e658627397 Mon Sep 17 00:00:00 2001 From: Vladyslav Vladinov <111443297+SalOne22@users.noreply.github.com> Date: Wed, 13 Dec 2023 13:22:15 +0100 Subject: [PATCH 15/30] Update wasm target --- .github/workflows/rimage.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rimage.yml b/.github/workflows/rimage.yml index 0b2b0d86..126514e7 100644 --- a/.github/workflows/rimage.yml +++ b/.github/workflows/rimage.yml @@ -23,6 +23,7 @@ jobs: target: - x86_64-unknown-linux-gnu - aarch64-unknown-linux-gnu + - wasm32-unknown-emscripten - x86_64-pc-windows-gnu - x86_64-pc-windows-msvc - x86_64-apple-darwin @@ -35,9 +36,8 @@ jobs: - target: aarch64-unknown-linux-gnu os: ubuntu-latest target-apt-arch: arm64 - - target: wasm32-unknown-unknown + - target: wasm32-unknown-emscripten os: macos-latest - target-apt-arch: amd64 - target: x86_64-pc-windows-gnu os: windows-2019 - target: x86_64-pc-windows-msvc From fe5b57707c550580ce0ce14901cc82159b6fb0f8 Mon Sep 17 00:00:00 2001 From: Vladyslav Vladinov <111443297+SalOne22@users.noreply.github.com> Date: Wed, 13 Dec 2023 13:24:29 +0100 Subject: [PATCH 16/30] Changed wasm32-unknown-unknown to wasm32-unknown-emscripten --- .github/workflows/rimage.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/rimage.yml b/.github/workflows/rimage.yml index 126514e7..a8699b45 100644 --- a/.github/workflows/rimage.yml +++ b/.github/workflows/rimage.yml @@ -91,7 +91,7 @@ jobs: brew install ninja nasm meson - name: Install emcc - if: matrix.target == 'wasm32-unknown-unknown' + if: matrix.target == 'wasm32-unknown-emscripten' run: brew install emscripten - name: Install dependencies (windows) @@ -115,7 +115,7 @@ jobs: cargo build --all-features --target ${{ matrix.target }} - name: Build ๐Ÿ—๏ธ (unix) - if: ${{ matrix.os != 'windows-2019' && matrix.target != 'wasm32-unknown-unknown' }} + if: ${{ matrix.os != 'windows-2019' && matrix.target != 'wasm32-unknown-emscripten' }} run: | cargo build --all-features --target ${{ matrix.target }} @@ -127,12 +127,12 @@ jobs: cargo test --all-features --target ${{ matrix.target }} - name: Test ๐Ÿงช (unix) - if: ${{ matrix.os != 'windows-2019' && matrix.target != 'wasm32-unknown-unknown' && matrix.target != 'aarch64-apple-darwin' && matrix.target != 'aarch64-unknown-linux-gnu' }} + if: ${{ matrix.os != 'windows-2019' && matrix.target != 'wasm32-unknown-emscripten' && matrix.target != 'aarch64-apple-darwin' && matrix.target != 'aarch64-unknown-linux-gnu' }} run: | cargo test --all-features --target ${{ matrix.target }} - name: Check wasm - if: matrix.target == 'wasm32-unknown-unknown' + if: matrix.target == 'wasm32-unknown-emscripten' run: | export EMSCRIPTEN_CMAKE_FILE="$(brew --cellar emscripten)/$(brew list --versions emscripten | tr ' ' '\n' | tail -1)/libexec/cmake/Modules/Platform/Emscripten.cmake" cargo check --all-features --target ${{ matrix.target }} From d1a6ce5dfe03302458b184883b52de0d9ad7ea2e Mon Sep 17 00:00:00 2001 From: Vladyslav Vladinov <111443297+SalOne22@users.noreply.github.com> Date: Wed, 13 Dec 2023 13:44:37 +0100 Subject: [PATCH 17/30] Updated windows gnu target build --- .github/workflows/rimage.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/rimage.yml b/.github/workflows/rimage.yml index a8699b45..aaa402d3 100644 --- a/.github/workflows/rimage.yml +++ b/.github/workflows/rimage.yml @@ -107,27 +107,27 @@ jobs: toolchain: stable target: ${{ matrix.target }} - - name: Build ๐Ÿ—๏ธ (windows) - if: matrix.os == 'windows-2019' + - name: Build ๐Ÿ—๏ธ (windows msvc) + if: matrix.target == 'x86_64-pc-windows-msvc' shell: cmd run: | call "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Auxiliary/Build/vcvars64.bat" cargo build --all-features --target ${{ matrix.target }} - - name: Build ๐Ÿ—๏ธ (unix) - if: ${{ matrix.os != 'windows-2019' && matrix.target != 'wasm32-unknown-emscripten' }} + - name: Build ๐Ÿ—๏ธ (unix / windows gnu) + if: ${{ matrix.target != 'x86_64-pc-windows-msvc' && matrix.target != 'wasm32-unknown-emscripten' }} run: | cargo build --all-features --target ${{ matrix.target }} - - name: Test ๐Ÿงช (windows) - if: matrix.os == 'windows-2019' + - name: Test ๐Ÿงช (windows msvc) + if: matrix.target == 'x86_64-pc-windows-msvc' shell: cmd run: | call "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Auxiliary/Build/vcvars64.bat" cargo test --all-features --target ${{ matrix.target }} - - name: Test ๐Ÿงช (unix) - if: ${{ matrix.os != 'windows-2019' && matrix.target != 'wasm32-unknown-emscripten' && matrix.target != 'aarch64-apple-darwin' && matrix.target != 'aarch64-unknown-linux-gnu' }} + - name: Test ๐Ÿงช (unix / windows gnu) + if: ${{ matrix.target != 'x86_64-pc-windows-msvc' && matrix.target != 'wasm32-unknown-emscripten' && matrix.target != 'aarch64-apple-darwin' && matrix.target != 'aarch64-unknown-linux-gnu' }} run: | cargo test --all-features --target ${{ matrix.target }} From 68c4b8ede081c2204fd4674f3ff7fd9b0ef57033 Mon Sep 17 00:00:00 2001 From: Vladyslav Vladinov <111443297+SalOne22@users.noreply.github.com> Date: Wed, 13 Dec 2023 13:57:31 +0100 Subject: [PATCH 18/30] Added verification of nasm installation --- .github/workflows/rimage.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/rimage.yml b/.github/workflows/rimage.yml index aaa402d3..3694f82a 100644 --- a/.github/workflows/rimage.yml +++ b/.github/workflows/rimage.yml @@ -107,6 +107,11 @@ jobs: toolchain: stable target: ${{ matrix.target }} + - name: Verify NASM Installation + if: matrix.target == 'x86_64-pc-windows-gnu' + run: | + nasm -v + - name: Build ๐Ÿ—๏ธ (windows msvc) if: matrix.target == 'x86_64-pc-windows-msvc' shell: cmd From ef0d4023147be7914dca41d5e2a7cc058787593f Mon Sep 17 00:00:00 2001 From: Vladyslav Vladinov <111443297+SalOne22@users.noreply.github.com> Date: Wed, 13 Dec 2023 14:03:27 +0100 Subject: [PATCH 19/30] Moved nasm to separate installation step --- .github/workflows/rimage.yml | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/.github/workflows/rimage.yml b/.github/workflows/rimage.yml index 3694f82a..ba31d7d6 100644 --- a/.github/workflows/rimage.yml +++ b/.github/workflows/rimage.yml @@ -79,16 +79,18 @@ jobs: target/ key: ${{ matrix.target }}-cargo-${{ hashFiles('**/Cargo.lock') }} + - uses: ilammy/setup-nasm@v1 + - name: Install dependencies (linux) if: matrix.os == 'ubuntu-latest' run: | DEBIAN_FRONTEND=noninteractive sudo apt-get update - DEBIAN_FRONTEND=noninteractive sudo apt-get install -y ninja-build nasm meson + DEBIAN_FRONTEND=noninteractive sudo apt-get install -y ninja-build meson - name: Install dependencies (macos) if: matrix.os == 'macos-latest' run: | - brew install ninja nasm meson + brew install ninja meson - name: Install emcc if: matrix.target == 'wasm32-unknown-emscripten' @@ -97,7 +99,7 @@ jobs: - name: Install dependencies (windows) if: matrix.os == 'windows-2019' run: | - choco install -y ninja nasm + choco install -y ninja pip install meson - name: Setup rust toolchain ๐Ÿฆ€ @@ -107,11 +109,6 @@ jobs: toolchain: stable target: ${{ matrix.target }} - - name: Verify NASM Installation - if: matrix.target == 'x86_64-pc-windows-gnu' - run: | - nasm -v - - name: Build ๐Ÿ—๏ธ (windows msvc) if: matrix.target == 'x86_64-pc-windows-msvc' shell: cmd From da66caabb6e3314f34e6eab9fad9ee6659322dbd Mon Sep 17 00:00:00 2001 From: Vladyslav Vladinov <111443297+SalOne22@users.noreply.github.com> Date: Wed, 13 Dec 2023 15:25:41 +0100 Subject: [PATCH 20/30] Fixed clippy errors --- src/decoder/mod.rs | 15 +++++++++------ src/error.rs | 1 + 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index 2ee447a8..97f0d69a 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -1,15 +1,12 @@ -use image::error::{DecodingError, ImageFormatHint, UnsupportedError, UnsupportedErrorKind}; -use image::DynamicImage::{ImageLuma8, ImageLumaA8, ImageRgb8, ImageRgba8}; -use image::{ - DynamicImage, GrayAlphaImage, GrayImage, ImageError, ImageResult, RgbImage, RgbaImage, -}; -use std::io::Seek; use std::{ fs::File, io::{BufRead, BufReader}, path::Path, }; +use std::io::Seek; +use image::{DynamicImage, ImageError, ImageResult}; +use image::error::{ImageFormatHint, UnsupportedError}; use image::io::Reader as ImageReader; use crate::config::ImageFormat; @@ -132,6 +129,10 @@ impl Decoder { #[cfg(feature = "jxl")] fn decode_jpegxl(self) -> ImageResult { + use image::error::{DecodingError, UnsupportedErrorKind}; + use image::DynamicImage::{ImageLuma8, ImageLumaA8, ImageRgb8, ImageRgba8}; + use image::{GrayAlphaImage, GrayImage, RgbaImage, RgbImage}; + use jxl_oxide::{JxlImage, PixelFormat}; let image = JxlImage::from_reader(self.r.into_inner()).map_err(|e| { @@ -215,6 +216,8 @@ impl Decoder { #[cfg(feature = "avif")] fn decode_avif(self) -> ImageResult { + use image::error::DecodingError; + let mut r = self.r.into_inner(); let mut buf: Vec = vec![]; diff --git a/src/error.rs b/src/error.rs index e60a58a2..7f2d51b9 100644 --- a/src/error.rs +++ b/src/error.rs @@ -115,6 +115,7 @@ pub enum DecoderError { WebP, } +/// An error occurred when encoding JpegXL image #[cfg(feature = "jxl")] #[derive(Error, Debug)] #[error("{0:?}")] From 869461cfeb8bb9e6f438bef8fed1943f3d68c5f0 Mon Sep 17 00:00:00 2001 From: Vladyslav Vladinov <111443297+SalOne22@users.noreply.github.com> Date: Wed, 13 Dec 2023 15:47:14 +0100 Subject: [PATCH 21/30] Formatted code --- src/decoder/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index 97f0d69a..5a14e770 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -1,13 +1,13 @@ +use std::io::Seek; use std::{ fs::File, io::{BufRead, BufReader}, path::Path, }; -use std::io::Seek; -use image::{DynamicImage, ImageError, ImageResult}; use image::error::{ImageFormatHint, UnsupportedError}; use image::io::Reader as ImageReader; +use image::{DynamicImage, ImageError, ImageResult}; use crate::config::ImageFormat; @@ -131,7 +131,7 @@ impl Decoder { fn decode_jpegxl(self) -> ImageResult { use image::error::{DecodingError, UnsupportedErrorKind}; use image::DynamicImage::{ImageLuma8, ImageLumaA8, ImageRgb8, ImageRgba8}; - use image::{GrayAlphaImage, GrayImage, RgbaImage, RgbImage}; + use image::{GrayAlphaImage, GrayImage, RgbImage, RgbaImage}; use jxl_oxide::{JxlImage, PixelFormat}; From 80ef219711037476b2d631d43341755e355f2aca Mon Sep 17 00:00:00 2001 From: Vladyslav Vladinov <111443297+SalOne22@users.noreply.github.com> Date: Thu, 14 Dec 2023 14:36:26 +0100 Subject: [PATCH 22/30] Updated workflows --- .github/workflows/combine-prs.yml | 2 +- .github/workflows/deploy.yml | 19 ++-- .github/workflows/rimage.yml | 169 ++++++++++++++---------------- 3 files changed, 91 insertions(+), 99 deletions(-) diff --git a/.github/workflows/combine-prs.yml b/.github/workflows/combine-prs.yml index 0281b46c..b1328dab 100644 --- a/.github/workflows/combine-prs.yml +++ b/.github/workflows/combine-prs.yml @@ -1,4 +1,4 @@ -name: Combine PRs +name: combine pr's on: workflow_dispatch: diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index d52b3846..76753a43 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -3,7 +3,7 @@ name: deploy on: push: tags: - - 'v*.*.*' + - "v*.*.*" workflow_dispatch: permissions: @@ -21,23 +21,24 @@ jobs: matrix: target: - x86_64-unknown-linux-gnu + - x86_64-unknown-linux-musl - aarch64-unknown-linux-gnu - - x86_64-pc-windows-gnu + - aarch64-unknown-linux-musl - x86_64-pc-windows-msvc + - i686-pc-windows-msvc - x86_64-apple-darwin - aarch64-apple-darwin steps: - - name: Checkout ๐Ÿ›Ž๏ธ - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - - name: Get the rimage version ๐Ÿชถ + - name: get the rimage version id: rimage-meta run: echo "version=$(cargo metadata --format-version 1 --no-deps | jq -r '.packages[] | select(.name == "rimage").version')" >> "$GITHUB_OUTPUT" - - name: Retrieve ${{ matrix.target }} binary ๐Ÿ”ƒ + - name: retrieve ${{ matrix.target }} binary uses: dawidd6/action-download-artifact@v2 with: workflow: rimage.yml @@ -45,7 +46,7 @@ jobs: name: rimage binary (${{ matrix.target }}) path: target - - name: Build archives ๐Ÿ— + - name: build archives working-directory: target run: | ARCHIVE_NAME="rimage-${{ steps.rimage-meta.outputs.version }}-${{ matrix.target }}" @@ -65,10 +66,10 @@ jobs: tar -vczf "${ARCHIVE_NAME}.tar.gz" "$ARCHIVE_NAME"/*;; esac - - name: Create release notes ๐Ÿ“‘ + - name: create release notes run: tail -n +5 CHANGELOG.md | sed -e '/## \[v/,$d' > RELEASE_NOTES.txt - - name: Create release + - name: create release uses: softprops/action-gh-release@v1 with: name: v${{ steps.rimage-meta.outputs.version }} diff --git a/.github/workflows/rimage.yml b/.github/workflows/rimage.yml index ba31d7d6..95a424dc 100644 --- a/.github/workflows/rimage.yml +++ b/.github/workflows/rimage.yml @@ -2,59 +2,66 @@ name: rimage on: push: - branches: - - main - paths-ignore: - - '**/*.md' pull_request: - branches: - - main - paths-ignore: - - '**/*.md' + types: + - opened + - synchronize + workflow_dispatch: jobs: test: name: test + runs-on: ${{ matrix.os }} + timeout-minutes: 60 + + if: github.ref_type != 'tag' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.fork) strategy: fail-fast: false matrix: target: - x86_64-unknown-linux-gnu + - x86_64-unknown-linux-musl - aarch64-unknown-linux-gnu - - wasm32-unknown-emscripten - - x86_64-pc-windows-gnu + - aarch64-unknown-linux-musl - x86_64-pc-windows-msvc + - i686-pc-windows-msvc - x86_64-apple-darwin - aarch64-apple-darwin + - wasm32-unknown-emscripten include: - target: x86_64-unknown-linux-gnu os: ubuntu-latest target-apt-arch: amd64 + - target: x86_64-unknown-linux-musl + os: ubuntu-latest + target-apt-arch: amd64 - target: aarch64-unknown-linux-gnu os: ubuntu-latest target-apt-arch: arm64 - - target: wasm32-unknown-emscripten - os: macos-latest - - target: x86_64-pc-windows-gnu - os: windows-2019 + - target: aarch64-unknown-linux-musl + os: ubuntu-latest + target-apt-arch: arm64 - target: x86_64-pc-windows-msvc - os: windows-2019 + os: windows-latest + - target: i686-pc-windows-msvc + os: windows-latest - target: x86_64-apple-darwin os: macos-latest - target: aarch64-apple-darwin os: macos-latest + - target: wasm32-unknown-emscripten + os: macos-latest env: CARGO_BUILD_TARGET: ${{ matrix.target }} steps: - - name: Checkout ๐Ÿ›Ž๏ธ - uses: actions/checkout@v4 + - uses: actions/checkout@v4 - - name: Set up Ubuntu multiarch โš™๏ธ + - name: set up ubuntu multiarch if: startsWith(matrix.os, 'ubuntu') && matrix.target-apt-arch != 'amd64' run: | readonly DISTRO_CODENAME=jammy @@ -65,84 +72,85 @@ jobs: echo "deb [arch=${{ matrix.target-apt-arch }}] http://ports.ubuntu.com/ $DISTRO_CODENAME$suite main universe multiverse" | \ sudo tee -a /etc/apt/sources.list >/dev/null done + + - name: install musl development files + if: endsWith(matrix.target, '-musl') + run: | + sudo apt-get -yq update + sudo apt-get -yq install musl-tools musl-dev:${{ matrix.target-apt-arch }} + + - name: install qemu and aarch64 cross compiler + if: startsWith(matrix.target, 'aarch64-unknown-linux') + run: | sudo apt-get -yq update - sudo apt-get -yq install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu + sudo apt-get -yq install qemu-user gcc-aarch64-linux-gnu libc6:arm64 + + - uses: Swatinem/rust-cache@v2 - - name: Setup cache ๐Ÿ’พ - uses: actions/cache@v3 + - name: install rust toolchain + uses: actions-rs/toolchain@v1 with: - path: | - ~/.cargo/bin/ - ~/.cargo/registry/index/ - ~/.cargo/registry/cache/ - ~/.cargo/git/db/ - target/ - key: ${{ matrix.target }}-cargo-${{ hashFiles('**/Cargo.lock') }} + profile: minimal + toolchain: stable + target: ${{ matrix.target }} - uses: ilammy/setup-nasm@v1 - - name: Install dependencies (linux) + - name: install dependencies (linux) if: matrix.os == 'ubuntu-latest' run: | - DEBIAN_FRONTEND=noninteractive sudo apt-get update - DEBIAN_FRONTEND=noninteractive sudo apt-get install -y ninja-build meson + sudo apt-get -yq update + sudo apt-get -yq install ninja-build meson - - name: Install dependencies (macos) + - name: install dependencies (macos) if: matrix.os == 'macos-latest' run: | brew install ninja meson - - name: Install emcc - if: matrix.target == 'wasm32-unknown-emscripten' - run: brew install emscripten - - - name: Install dependencies (windows) - if: matrix.os == 'windows-2019' + - name: install dependencies (windows) + if: matrix.os == 'windows-latest' run: | choco install -y ninja pip install meson - - name: Setup rust toolchain ๐Ÿฆ€ - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - target: ${{ matrix.target }} + - name: install emcc + if: matrix.target == 'wasm32-unknown-emscripten' + run: brew install emscripten - - name: Build ๐Ÿ—๏ธ (windows msvc) - if: matrix.target == 'x86_64-pc-windows-msvc' + - name: build (windows msvc) + if: contains('msvc', matrix.target) shell: cmd run: | call "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Auxiliary/Build/vcvars64.bat" - cargo build --all-features --target ${{ matrix.target }} + cargo build --all-features --release - - name: Build ๐Ÿ—๏ธ (unix / windows gnu) - if: ${{ matrix.target != 'x86_64-pc-windows-msvc' && matrix.target != 'wasm32-unknown-emscripten' }} + - name: build (unix / windows gnu) + if: ${{ !contains('msvc', matrix.target) && matrix.target != 'wasm32-unknown-emscripten' }} run: | - cargo build --all-features --target ${{ matrix.target }} + cargo build --all-features --release - - name: Test ๐Ÿงช (windows msvc) - if: matrix.target == 'x86_64-pc-windows-msvc' + - name: test ๐Ÿงช (windows msvc) + if: contains('msvc', matrix.target) shell: cmd run: | call "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Auxiliary/Build/vcvars64.bat" - cargo test --all-features --target ${{ matrix.target }} + cargo test --all-features - - name: Test ๐Ÿงช (unix / windows gnu) - if: ${{ matrix.target != 'x86_64-pc-windows-msvc' && matrix.target != 'wasm32-unknown-emscripten' && matrix.target != 'aarch64-apple-darwin' && matrix.target != 'aarch64-unknown-linux-gnu' }} + - name: test ๐Ÿงช (unix / windows gnu) + if: ${{ !contains('msvc', matrix.target) && matrix.target != 'wasm32-unknown-emscripten' }} run: | - cargo test --all-features --target ${{ matrix.target }} + cargo test --all-features - - name: Check wasm + - name: check wasm if: matrix.target == 'wasm32-unknown-emscripten' run: | export EMSCRIPTEN_CMAKE_FILE="$(brew --cellar emscripten)/$(brew list --versions emscripten | tr ' ' '\n' | tail -1)/libexec/cmake/Modules/Platform/Emscripten.cmake" - cargo check --all-features --target ${{ matrix.target }} + cargo check --all-features env: - CC: 'emcc' - CXX: 'emcc' + CC: "emcc" + CXX: "emcc" - - name: Upload CLI binary as artifact ๐Ÿ’พ + - name: upload cli binary as artifact uses: actions/upload-artifact@v3 with: name: rimage binary (${{ matrix.target }}) @@ -155,41 +163,24 @@ jobs: runs-on: ubuntu-latest steps: - - name: Checkout ๐Ÿ›Ž๏ธ - uses: actions/checkout@v4 - - - name: Setup cache ๐Ÿ’พ - uses: actions/cache@v3 - with: - path: | - ~/.cargo/bin/ - ~/.cargo/registry/index/ - ~/.cargo/registry/cache/ - ~/.cargo/git/db/ - target/ - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + - uses: actions/checkout@v4 - - name: Setup nasm ๐Ÿง‘โ€๐Ÿ’ป - uses: ilammy/setup-nasm@v1 + - name: install dependencies + run: | + sudo apt-get -yq update + sudo apt-get -yq install ninja-build meson nasm - - name: Setup meson + ninja ๐Ÿง‘โ€๐Ÿ’ป - run: pip3 install --user meson ninja + - uses: Swatinem/rust-cache@v2 - - name: Setup rust toolchain ๐Ÿฆ€ + - name: setup rust toolchain uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: stable components: rustfmt, clippy - - name: Formatting check ๐Ÿช„ - uses: actions-rs/cargo@v1 - with: - command: fmt - args: --all -- --check + - name: formatting check + run: cargo fmt --all -- --check - - name: Clippy check ๐Ÿ”Ž - uses: actions-rs/cargo@v1 - with: - command: clippy - args: --all-features -- -D warnings + - name: clippy check + run: cargo clippy --all-features -- -D warnings From 6eb17a8589310efc72b5e3426ebb0688cd52046e Mon Sep 17 00:00:00 2001 From: Vladyslav Vladinov <111443297+SalOne22@users.noreply.github.com> Date: Thu, 14 Dec 2023 14:59:27 +0100 Subject: [PATCH 23/30] update for aarch64 target --- .github/workflows/rimage.yml | 31 +++++++------------------------ 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/.github/workflows/rimage.yml b/.github/workflows/rimage.yml index 95a424dc..0029bf26 100644 --- a/.github/workflows/rimage.yml +++ b/.github/workflows/rimage.yml @@ -79,11 +79,11 @@ jobs: sudo apt-get -yq update sudo apt-get -yq install musl-tools musl-dev:${{ matrix.target-apt-arch }} - - name: install qemu and aarch64 cross compiler + - name: install aarch64 cross compiler if: startsWith(matrix.target, 'aarch64-unknown-linux') run: | sudo apt-get -yq update - sudo apt-get -yq install qemu-user gcc-aarch64-linux-gnu libc6:arm64 + sudo apt-get -yq install gcc-aarch64-linux-gnu libc6:arm64 g++:arm64 - uses: Swatinem/rust-cache@v2 @@ -117,29 +117,12 @@ jobs: if: matrix.target == 'wasm32-unknown-emscripten' run: brew install emscripten - - name: build (windows msvc) - if: contains('msvc', matrix.target) - shell: cmd - run: | - call "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Auxiliary/Build/vcvars64.bat" - cargo build --all-features --release - - - name: build (unix / windows gnu) - if: ${{ !contains('msvc', matrix.target) && matrix.target != 'wasm32-unknown-emscripten' }} - run: | - cargo build --all-features --release + - name: build + run: cargo build --all-features --release - - name: test ๐Ÿงช (windows msvc) - if: contains('msvc', matrix.target) - shell: cmd - run: | - call "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Auxiliary/Build/vcvars64.bat" - cargo test --all-features - - - name: test ๐Ÿงช (unix / windows gnu) - if: ${{ !contains('msvc', matrix.target) && matrix.target != 'wasm32-unknown-emscripten' }} - run: | - cargo test --all-features + - name: test + if: ! contains('aarch64', matrix.target) + run: cargo test --all-features - name: check wasm if: matrix.target == 'wasm32-unknown-emscripten' From 39e68baa1a4dfa4da067af893e5d09d27d0fd2ed Mon Sep 17 00:00:00 2001 From: Vladyslav Vladinov <111443297+SalOne22@users.noreply.github.com> Date: Thu, 14 Dec 2023 15:03:12 +0100 Subject: [PATCH 24/30] Update workflow --- .github/workflows/rimage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rimage.yml b/.github/workflows/rimage.yml index 0029bf26..50803427 100644 --- a/.github/workflows/rimage.yml +++ b/.github/workflows/rimage.yml @@ -121,7 +121,7 @@ jobs: run: cargo build --all-features --release - name: test - if: ! contains('aarch64', matrix.target) + if: contains('aarch64', matrix.target) == false run: cargo test --all-features - name: check wasm From a81b069ec73199c41297f91b276da70817f57fd1 Mon Sep 17 00:00:00 2001 From: Vladyslav Vladinov <111443297+SalOne22@users.noreply.github.com> Date: Thu, 14 Dec 2023 15:09:53 +0100 Subject: [PATCH 25/30] Fixed g++ cross installation --- .github/workflows/rimage.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/rimage.yml b/.github/workflows/rimage.yml index 50803427..3e26d591 100644 --- a/.github/workflows/rimage.yml +++ b/.github/workflows/rimage.yml @@ -83,7 +83,7 @@ jobs: if: startsWith(matrix.target, 'aarch64-unknown-linux') run: | sudo apt-get -yq update - sudo apt-get -yq install gcc-aarch64-linux-gnu libc6:arm64 g++:arm64 + sudo apt-get -yq install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libc6:arm64 - uses: Swatinem/rust-cache@v2 @@ -118,6 +118,7 @@ jobs: run: brew install emscripten - name: build + if: matrix.target != 'wasm32-unknown-emscripten' run: cargo build --all-features --release - name: test From 3a80db1e3d8fb5b65c9364198807642a3ebf40d1 Mon Sep 17 00:00:00 2001 From: Vladyslav Vladinov <111443297+SalOne22@users.noreply.github.com> Date: Thu, 14 Dec 2023 15:13:46 +0100 Subject: [PATCH 26/30] Added musl-g++ as g++ link --- .github/workflows/rimage.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/rimage.yml b/.github/workflows/rimage.yml index 3e26d591..810a5622 100644 --- a/.github/workflows/rimage.yml +++ b/.github/workflows/rimage.yml @@ -78,6 +78,7 @@ jobs: run: | sudo apt-get -yq update sudo apt-get -yq install musl-tools musl-dev:${{ matrix.target-apt-arch }} + sudo ln -s /bin/g++ /bin/musl-g++ - name: install aarch64 cross compiler if: startsWith(matrix.target, 'aarch64-unknown-linux') From c66f05d13b348c02e9dfd511873da42d1954f0ad Mon Sep 17 00:00:00 2001 From: Vladyslav Vladinov <111443297+SalOne22@users.noreply.github.com> Date: Thu, 14 Dec 2023 15:16:37 +0100 Subject: [PATCH 27/30] Added aarch64 musl-g++ --- .github/workflows/rimage.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/rimage.yml b/.github/workflows/rimage.yml index 810a5622..81915935 100644 --- a/.github/workflows/rimage.yml +++ b/.github/workflows/rimage.yml @@ -78,7 +78,6 @@ jobs: run: | sudo apt-get -yq update sudo apt-get -yq install musl-tools musl-dev:${{ matrix.target-apt-arch }} - sudo ln -s /bin/g++ /bin/musl-g++ - name: install aarch64 cross compiler if: startsWith(matrix.target, 'aarch64-unknown-linux') @@ -86,6 +85,14 @@ jobs: sudo apt-get -yq update sudo apt-get -yq install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu libc6:arm64 + - name: set musl-g++ + if: matrix.target == 'x86_64-unknown-linux-musl' + run: sudo ln -s /bin/g++ /bin/musl-g++ + + - name: set aarch64-linux-musl-g++ + if: matrix.target == 'aarch64-unknown-linux-musl' + run: sudo ln -s /bin/aarch64-linux-gnu-g++ /bin/aarch64-linux-musl-g++ + - uses: Swatinem/rust-cache@v2 - name: install rust toolchain From feebc03aaba26e0f253375f034af0e96003a7bc9 Mon Sep 17 00:00:00 2001 From: Vladyslav Vladinov <111443297+SalOne22@users.noreply.github.com> Date: Thu, 14 Dec 2023 15:48:34 +0100 Subject: [PATCH 28/30] fixed startsWith function --- .github/workflows/rimage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rimage.yml b/.github/workflows/rimage.yml index 81915935..4d9b7bb1 100644 --- a/.github/workflows/rimage.yml +++ b/.github/workflows/rimage.yml @@ -130,7 +130,7 @@ jobs: run: cargo build --all-features --release - name: test - if: contains('aarch64', matrix.target) == false + if: ! startsWith(matrix.target, 'aarch64') && matrix.target != 'wasm32-unknown-emscripten' run: cargo test --all-features - name: check wasm From fbe259945954bb0131ebab224ef541c509d94d13 Mon Sep 17 00:00:00 2001 From: Vladyslav Vladinov <111443297+SalOne22@users.noreply.github.com> Date: Thu, 14 Dec 2023 15:54:35 +0100 Subject: [PATCH 29/30] updated startsWith --- .github/workflows/rimage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rimage.yml b/.github/workflows/rimage.yml index 4d9b7bb1..e78d3885 100644 --- a/.github/workflows/rimage.yml +++ b/.github/workflows/rimage.yml @@ -130,7 +130,7 @@ jobs: run: cargo build --all-features --release - name: test - if: ! startsWith(matrix.target, 'aarch64') && matrix.target != 'wasm32-unknown-emscripten' + if: startsWith(matrix.target, 'aarch64') != true && matrix.target != 'wasm32-unknown-emscripten' run: cargo test --all-features - name: check wasm From d7dc43709ebac80f4100ecb9e5ffbcbabdc668d1 Mon Sep 17 00:00:00 2001 From: Vladyslav Vladinov <111443297+SalOne22@users.noreply.github.com> Date: Thu, 14 Dec 2023 16:10:47 +0100 Subject: [PATCH 30/30] Added linker for aarch64 musl target --- .cargo/config.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.cargo/config.toml b/.cargo/config.toml index 33c70b57..659c8517 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,5 +1,7 @@ [target.aarch64-unknown-linux-gnu] linker="aarch64-linux-gnu-gcc" +[target.aarch64-unknown-linux-musl] +linker="aarch64-linux-musl-gcc" [target.x86_64-pc-windows-msvc] rustflags = ["-C", "target-feature=+crt-static"] \ No newline at end of file