Repository: qarmin/czkawka (language: rust)

Issue:
6.1.0 can't load preview of webp image - Windows 10
**Desktop (please complete the following information):**

- Czkawka version<!--  e.g. 6.1.0 cli/gui -->: 6.1.0
- OS version<!--  e.g Ubuntu 22.04, Windows 11, Mac 15.1 ARM -->: Windows 10


<!--
Add terminal output only if needed - if there are some errors or warnings or you have performance/freeze issues.  
Very helpful in this situation will be logs from czkawka run with RUST_LOG environment variable set e.g. 
`RUST_LOG=debug ./czkawka` which will print more detailed info about executed function
-->

**Bug Description**
Preview image doesn't load for webp image type. It gives an error: 
Failed to open image example.webp, reason Couldn’t recognize the image file format for file “example.webp”



Discussion / hints:
This worked in 5.1.0 because used image-rs image loading instead gdk-pixbuf.

I tried to use https://packages.msys2.org/package/mingw-w64-x86_64-webp-pixbuf-loader?repo=mingw64 and manually put there webp loader, but shows instead error
```
Failed to open image ⁨C:\users\vboxuser\desktop\e563993b91a5c430e96e58ae5adbe4dd.webp⁩, reason ⁨Unable to load image-loading module: C:\Users\vboxuser\Desktop\czkawka-windows-8460f29c3a729c9c1bb05c58a2c4a94759a53f30-non_heif\lib\gdk-pixbuf-2.0\2.10.0\loaders\libpixbufloader-webp.dll: 'C:\Users\vboxuser\Desktop\czkawka-windows-8460f29c3a729c9c1bb05c58a2c4a94759a53f30-non_heif\lib\gdk-pixbuf-2.0\2.10.0\loaders\libpixbufloader-webp.dll': Nie można odnaleźć określonego modułu.⁩
```
Also seeing this in 6.1.0 on Win11 64 Pro. I have the "WebP Extensions" installed from the Windows Store but there's just zero preview for any WebP files.
App uses native gtk libraries for loading previews, so installing other apps will not fix this problem.
Krokiet - new frontent - uses rust native image loader and all tested files should show proper preview
I see, is Krokiet compile-it-yourself-only at the moment? Looks like the built releases are only the GTK version so I compiled the Krokiet version and I assume it's still very WIP.

That said, I do like the default styling of this Slint toolkit, and it fixes both this WebP issue as well as the DPI scaling issue on Windows (on the GTK version, I needed the gtk.css tweak to scale things up to a usable size), and it seems very performant. I might just keep using this version since the Image Dupe search seems to be working and that was the main thing I was using it for.

Best of luck porting everything over, I'd help if I had the time or Rust knowledge!
Sorry for the noob question, but is Krokiet currently only meant to be tested by people who know how to compile? 'Cause I'm completely clueless about that, and the read-me didn't help. 😖

Thank you for your work in creating Czkawka, it's really nice.
> Sorry for the noob question, but is Krokiet currently only meant to be tested by people who know how to compile? 'Cause I'm completely clueless about that, and the read-me didn't help. 😖
> 
> Thank you for your work in creating Czkawka, it's really nice.

@softlypink I believe that's the case since it's still missing a bunch of functionality from the current release version. Someone correct me if compiled binaries for Krokiet are being hosted anywhere.
Binaries for mac/linux/windows are build each time new commit is added to repo, and can be downloaded from - https://github.com/qarmin/czkawka/actions 

For now app only have 3 modes, missing a lot of features like selecting items and might be a little unstable
Anyone have a workaround for this? Would downgrading to an earlier version help? Any way to patch the install (without recompiling the whole thing) to get this working?

Fix patch:
diff --git a/.github/workflows/linux_cli.yml b/.github/workflows/linux_cli.yml
index 3360f2847..2a60a4611 100644
--- a/.github/workflows/linux_cli.yml
+++ b/.github/workflows/linux_cli.yml
@@ -19,7 +19,7 @@ jobs:
       - uses: actions/checkout@v4
 
       - name: Install basic libraries
-        run: sudo apt update || true; sudo apt install libheif-dev ffmpeg -y
+        run: sudo apt update || true; sudo apt install libheif-dev libraw-dev ffmpeg -y
 
       - name: Setup rust version
         run: rustup default ${{ matrix.toolchain }}
diff --git a/.github/workflows/linux_gui.yml b/.github/workflows/linux_gui.yml
index 89a228909..025cec24b 100644
--- a/.github/workflows/linux_gui.yml
+++ b/.github/workflows/linux_gui.yml
@@ -118,7 +118,7 @@ jobs:
       - uses: actions/checkout@v4
 
       - name: Install Dependencies
-        run: sudo apt update || true; sudo apt install libgtk-4-dev libheif-dev librsvg2-dev wget fuse libfuse2 desktop-file-utils -y
+        run: sudo apt update || true; sudo apt install libgtk-4-dev libheif-dev libraw-dev librsvg2-dev wget fuse libfuse2 desktop-file-utils -y
 
       - name: Setup rust version
         run: rustup default ${{ matrix.toolchain }}
@@ -186,7 +186,7 @@ jobs:
       - uses: actions/checkout@v4
 
       - name: Install Dependencies
-        run: sudo apt update || true; sudo apt install libgtk-4-dev libheif-dev librsvg2-dev wget fuse libfuse2 -y xvfb
+        run: sudo apt update || true; sudo apt install libgtk-4-dev libheif-dev libraw-dev librsvg2-dev wget fuse libfuse2 -y xvfb
 
       - name: Setup rust version
         run: rustup default ${{ matrix.toolchain }}
diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml
index 90093c435..8858ca275 100644
--- a/.github/workflows/mac.yml
+++ b/.github/workflows/mac.yml
@@ -59,7 +59,7 @@ jobs:
           path: target/release/krokiet
         if: ${{ matrix.type == 'release' }}
 
-# TODO - compilation is broken, not sure why
+#      # TODO - compilation is broken, not sure why
 #      - name: Build Release Heif
 #        run: cargo build --release --features heif
 #        if: ${{ matrix.type == 'release'}}
diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml
index c864a3afc..a18c80edf 100644
--- a/.github/workflows/quality.yml
+++ b/.github/workflows/quality.yml
@@ -10,12 +10,12 @@ env:
 
 jobs:
   quality:
-    runs-on: ubuntu-22.04
+    runs-on: ubuntu-24.04
     steps:
       - uses: actions/checkout@v4
 
       - name: Install Gtk 4
-        run: sudo apt update || true; sudo apt install -y libgtk-4-dev libraw-dev libheif-dev -y
+        run: sudo apt update || true; sudo apt install -y libgtk-4-dev libraw-dev libheif-dev libavif-dev libdav1d-dev -y
 
       - name: Check the format
         run: cargo fmt --all -- --check
diff --git a/.rustfmt.toml b/.rustfmt.toml
index 62a8e231b..de1cf8c1e 100644
--- a/.rustfmt.toml
+++ b/.rustfmt.toml
@@ -3,4 +3,5 @@ max_width = 180
 remove_nested_parens = true
 
 # Enable only with nightly channel via - cargo +nightly fmt
-imports_granularity = "Module"
\ No newline at end of file
+imports_granularity = "Module"
+group_imports = "StdExternalCrate"
\ No newline at end of file
diff --git a/Cargo.lock b/Cargo.lock
index d74acdbf5..4ad3752fe 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -201,7 +201,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -369,7 +369,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -404,7 +404,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -431,14 +431,28 @@ dependencies = [
  "derive_utils",
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
 name = "autocfg"
-version = "1.3.0"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
+
+[[package]]
+name = "av-data"
+version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
+checksum = "124ae24335161b3d2226594640a67903da0866e2591312591fc8ddad64c1b38c"
+dependencies = [
+ "byte-slice-cast",
+ "bytes",
+ "num-derive",
+ "num-rational",
+ "num-traits",
+ "thiserror",
+]
 
 [[package]]
 name = "av1-grain"
@@ -506,7 +520,7 @@ dependencies = [
  "regex",
  "rustc-hash",
  "shlex",
- "syn 2.0.77",
+ "syn 2.0.79",
  "which",
 ]
 
@@ -528,6 +542,15 @@ version = "2.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
 
+[[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 = "2.5.3"
@@ -630,6 +653,12 @@ version = "1.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06"
 
+[[package]]
+name = "byte-slice-cast"
+version = "1.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c"
+
 [[package]]
 name = "bytemuck"
 version = "1.18.0"
@@ -647,7 +676,7 @@ checksum = "0cc8b54b395f2fcfbb3d90c47b01c7f444d94d05bdeb775811dec868ac3bbc26"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -762,9 +791,9 @@ dependencies = [
 
 [[package]]
 name = "cc"
-version = "1.1.21"
+version = "1.1.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0"
+checksum = "812acba72f0a070b003d3697490d2b55b837230ae7c6c6497f05cc2ddbb8d938"
 dependencies = [
  "jobserver",
  "libc",
@@ -875,9 +904,9 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "4.5.18"
+version = "4.5.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b0956a43b323ac1afaffc053ed5c4b7c1f1800bacd1683c353aabbb752515dd3"
+checksum = "7be5744db7978a28d9df86a214130d106a89ce49644cbc4e3f0c22c3fba30615"
 dependencies = [
  "clap_builder",
  "clap_derive",
@@ -885,9 +914,9 @@ dependencies = [
 
 [[package]]
 name = "clap_builder"
-version = "4.5.18"
+version = "4.5.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d72166dd41634086d5803a47eb71ae740e61d84709c36f3c34110173db3961b"
+checksum = "a5fbc17d3ef8278f55b282b2a2e75ae6f6c7d4bb70ed3d0382375104bfafdb4b"
 dependencies = [
  "anstream",
  "anstyle",
@@ -904,7 +933,7 @@ dependencies = [
  "heck 0.5.0",
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -1037,7 +1066,7 @@ checksum = "5387f5bbc9e9e6c96436ea125afa12614cebf8ac67f49abc08c1e7a891466c90"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -1319,6 +1348,7 @@ dependencies = [
  "imagepipe",
  "infer",
  "itertools 0.13.0",
+ "jxl-oxide",
  "libheif-rs",
  "libheif-sys",
  "libraw-rs",
@@ -1460,6 +1490,38 @@ dependencies = [
  "syn 1.0.109",
 ]
 
+[[package]]
+name = "dav1d"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0d4b54a40baf633a71c6f0fb49494a7e4ee7bc26f3e727212b6cb915aa1ea1e1"
+dependencies = [
+ "av-data",
+ "bitflags 2.6.0",
+ "dav1d-sys",
+ "static_assertions",
+]
+
+[[package]]
+name = "dav1d-sys"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ecb1c5e8f4dc438eedc1b534a54672fb0e0a56035dae6b50162787bd2c50e95"
+dependencies = [
+ "libc",
+ "system-deps 6.2.2",
+]
+
+[[package]]
+name = "dcv-color-primitives"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07ad62edfed069700a5b33af6babd29c498d7e33eb01d96ffa8841ee1841634c"
+dependencies = [
+ "paste",
+ "wasm-bindgen",
+]
+
 [[package]]
 name = "deflate"
 version = "1.0.0"
@@ -1486,7 +1548,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -1499,7 +1561,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "rustc_version",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -1510,7 +1572,7 @@ checksum = "65f152f4b8559c4da5d574bafc7af85454d706b4c5fe8b530d508cacbb6807ea"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -1559,7 +1621,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -1687,7 +1749,7 @@ checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -1698,7 +1760,7 @@ checksum = "2f9ed6b3789237c8a0c1c505af1c7eb2c560df6186f01b098c3a1064ea532f38"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -1769,6 +1831,15 @@ version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "af9673d8203fcb076b19dfd17e38b3d4ae9f44959416ea532ce72415a6020365"
 
+[[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 = "fastrand"
 version = "2.1.1"
@@ -1882,9 +1953,9 @@ dependencies = [
 
 [[package]]
 name = "flate2"
-version = "1.0.33"
+version = "1.0.34"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253"
+checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0"
 dependencies = [
  "crc32fast",
  "miniz_oxide 0.8.0",
@@ -2007,7 +2078,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -2113,7 +2184,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -2160,9 +2231,9 @@ dependencies = [
 
 [[package]]
 name = "gbm-sys"
-version = "0.3.0"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6fd2d6bf7c0143b38beece05f9a5c4c851a49a8434f62bf58ff28da92b0ddc58"
+checksum = "a9cc2f64de9fa707b5c6b2d2f10d7a7e49e845018a9f5685891eb40d3bab2538"
 dependencies = [
  "libc",
 ]
@@ -2194,9 +2265,9 @@ dependencies = [
 
 [[package]]
 name = "gdk4"
-version = "0.9.0"
+version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b7d7237c1487ed4b300aac7744efcbf1319e12d60d7afcd6f505414bd5b5dea"
+checksum = "c121aeeb0cf7545877ae615dac6bfd088b739d8abee4d55e7143b06927d16a31"
 dependencies = [
  "cairo-rs",
  "gdk-pixbuf",
@@ -2209,9 +2280,9 @@ dependencies = [
 
 [[package]]
 name = "gdk4-sys"
-version = "0.9.0"
+version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a67576c8ec012156d7f680e201a807b4432a77babb3157e0555e990ab6bcd878"
+checksum = "7d3c03d1ea9d5199f14f060890fde68a3b5ec5699144773d1fa6abf337bfbc9c"
 dependencies = [
  "cairo-sys-rs",
  "gdk-pixbuf-sys",
@@ -2350,7 +2421,7 @@ dependencies = [
  "proc-macro-crate",
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -2494,9 +2565,9 @@ dependencies = [
 
 [[package]]
 name = "gsk4"
-version = "0.9.0"
+version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f3cf2091e1af185b347b3450817d93dea6fe435df7abd4c2cd7fb5bcb4cfda8"
+checksum = "aa21a2f7c51ee1c6cc1242c2faf3aae2b7566138f182696759987bde8219e922"
 dependencies = [
  "cairo-rs",
  "gdk4",
@@ -2509,9 +2580,9 @@ dependencies = [
 
 [[package]]
 name = "gsk4-sys"
-version = "0.9.0"
+version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6aa69614a26d8760c186c3690f1b0fbb917572ca23ef83137445770ceddf8cde"
+checksum = "0f9fb607554f9f4e8829eb7ea301b0fde051e1dbfd5d16b143a8a9c2fac6c01b"
 dependencies = [
  "cairo-sys-rs",
  "gdk4-sys",
@@ -2525,9 +2596,9 @@ dependencies = [
 
 [[package]]
 name = "gtk4"
-version = "0.9.1"
+version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4fe572bf318e5dbc6f5a2f8a25d853f1ae3f42768c0b08af6ca20a18f4057e1"
+checksum = "31e2d105ce672f5cdcb5af2602e91c2901e91c72da15ab76f613ad57ecf04c6d"
 dependencies = [
  "cairo-rs",
  "field-offset",
@@ -2553,14 +2624,14 @@ dependencies = [
  "proc-macro-crate",
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
 name = "gtk4-sys"
-version = "0.9.0"
+version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1114a207af8ada02cf4658a76692f4190f06f093380d5be07e3ca8b43aa7c666"
+checksum = "cbe4325908b1c1642dbb48e9f49c07a73185babf43e8b2065b0f881a589f55b8"
 dependencies = [
  "cairo-sys-rs",
  "gdk-pixbuf-sys",
@@ -2610,6 +2681,15 @@ version = "0.12.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
 
+[[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.5"
@@ -2621,6 +2701,12 @@ dependencies = [
  "rayon",
 ]
 
+[[package]]
+name = "hashbrown"
+version = "0.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb"
+
 [[package]]
 name = "heck"
 version = "0.4.1"
@@ -2844,7 +2930,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "17c4f06e2ccbf6e7381abd64e8716767e97b5fdf15280decf8f08f8d58cde25c"
 dependencies = [
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -2968,7 +3054,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "strsim 0.11.1",
- "syn 2.0.77",
+ "syn 2.0.79",
  "unic-langid",
 ]
 
@@ -2982,7 +3068,7 @@ dependencies = [
  "i18n-config",
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -3051,9 +3137,12 @@ dependencies = [
  "bytemuck",
  "byteorder-lite",
  "color_quant",
+ "dav1d",
+ "dcv-color-primitives",
  "exr",
  "gif",
  "image-webp",
+ "mp4parse",
  "num-traits",
  "png",
  "qoi",
@@ -3132,12 +3221,12 @@ dependencies = [
 
 [[package]]
 name = "indexmap"
-version = "2.5.0"
+version = "2.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5"
+checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
 dependencies = [
  "equivalent",
- "hashbrown 0.14.5",
+ "hashbrown 0.15.0",
 ]
 
 [[package]]
@@ -3174,13 +3263,12 @@ dependencies = [
 
 [[package]]
 name = "input"
-version = "0.9.0"
+version = "0.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7911ce3db9c10c5ab4a35c49af778a5f9a827bd0f7371d9be56175d8dd2740d0"
+checksum = "fbdc09524a91f9cacd26f16734ff63d7dc650daffadd2b6f84d17a285bd875a9"
 dependencies = [
  "bitflags 2.6.0",
  "input-sys",
- "io-lifetimes",
  "libc",
  "log",
  "udev",
@@ -3218,7 +3306,7 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -3367,6 +3455,145 @@ dependencies = [
  "wasm-bindgen",
 ]
 
+[[package]]
+name = "jxl-bitstream"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5855ff16398ffbcf81fee52c41ca65326499c8764b21bb9952c367ace98995fb"
+dependencies = [
+ "tracing",
+]
+
+[[package]]
+name = "jxl-coding"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da5b5093904e940bc11ef50e872c7bdf7b6e88653f012b925f8479daf212b5c9"
+dependencies = [
+ "jxl-bitstream",
+ "tracing",
+]
+
+[[package]]
+name = "jxl-color"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97f0dd548fabf9c094f9f2304059c86764f606b9040c0bfcfac55f155f423b55"
+dependencies = [
+ "jxl-bitstream",
+ "jxl-coding",
+ "jxl-grid",
+ "jxl-threadpool",
+ "tracing",
+]
+
+[[package]]
+name = "jxl-frame"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4719f285ebfff5e64f352d0ef149a5244aef4f8e6b5aa666ba6241e90b50632f"
+dependencies = [
+ "jxl-bitstream",
+ "jxl-coding",
+ "jxl-grid",
+ "jxl-image",
+ "jxl-modular",
+ "jxl-threadpool",
+ "jxl-vardct",
+ "tracing",
+]
+
+[[package]]
+name = "jxl-grid"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e941628e8de1dc6ba1d2bba8ebc68a69f8ff50cc7ddce5bc821658d1f4ea6e59"
+dependencies = [
+ "tracing",
+]
+
+[[package]]
+name = "jxl-image"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e3824c81613c05c19a9e4329d569145d3f460c0fcadb3965bd8418162d43f7f4"
+dependencies = [
+ "jxl-bitstream",
+ "jxl-color",
+ "jxl-grid",
+ "tracing",
+]
+
+[[package]]
+name = "jxl-modular"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9f48a5d003627f380004c29d35e51672da06ae343a2e6fe8d9c84295b9a3e843"
+dependencies = [
+ "jxl-bitstream",
+ "jxl-coding",
+ "jxl-grid",
+ "jxl-threadpool",
+ "tracing",
+]
+
+[[package]]
+name = "jxl-oxide"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7c209f66ef0fe72df77b44ee6aae98eb87bc2dd236d6981e44e143cc37f33f6e"
+dependencies = [
+ "jxl-bitstream",
+ "jxl-color",
+ "jxl-frame",
+ "jxl-grid",
+ "jxl-image",
+ "jxl-render",
+ "jxl-threadpool",
+ "tracing",
+]
+
+[[package]]
+name = "jxl-render"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aec53c004c9171e89f15ad1f029d6b638cbd70d3a70276746bb8c75f9393bb64"
+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.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9d2860c68899a3c6266044fc26c6a0041e9f27145f58cc69b6eedc1b77f5ee13"
+dependencies = [
+ "tracing",
+]
+
+[[package]]
+name = "jxl-vardct"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "15da4b49b832b3d8a67329f47e2a1732e0847667938bb9b4a37d99a4668775c2"
+dependencies = [
+ "jxl-bitstream",
+ "jxl-coding",
+ "jxl-grid",
+ "jxl-modular",
+ "jxl-threadpool",
+ "tracing",
+]
+
 [[package]]
 name = "khronos_api"
 version = "3.1.0"
@@ -3562,7 +3789,7 @@ checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
 dependencies = [
  "bitflags 2.6.0",
  "libc",
- "redox_syscall 0.5.6",
+ "redox_syscall 0.5.7",
 ]
 
 [[package]]
@@ -3654,7 +3881,7 @@ checksum = "28bd4b9d8a5af74808932492521cdd272019b056f75fcc70056bd2c09fceb550"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -3835,7 +4062,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
 dependencies = [
  "adler",
- "simd-adler32",
 ]
 
 [[package]]
@@ -3845,6 +4071,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1"
 dependencies = [
  "adler2",
+ "simd-adler32",
+]
+
+[[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]]
@@ -3973,7 +4214,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -4024,7 +4265,7 @@ dependencies = [
  "proc-macro-crate",
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -4295,9 +4536,9 @@ dependencies = [
 
 [[package]]
 name = "once_cell"
-version = "1.19.0"
+version = "1.20.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
+checksum = "82881c4be219ab5faaf2ad5e5e5ecdff8c66bd7402ca3160975c93b24961afd1"
 dependencies = [
  "critical-section",
  "portable-atomic",
@@ -4406,7 +4647,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
 dependencies = [
  "cfg-if",
  "libc",
- "redox_syscall 0.5.6",
+ "redox_syscall 0.5.7",
  "smallvec",
  "windows-targets 0.52.6",
 ]
@@ -4446,7 +4687,7 @@ dependencies = [
  "deflate",
  "fax",
  "globalcache",
- "indexmap 2.5.0",
+ "indexmap 2.6.0",
  "istring",
  "itertools 0.10.5",
  "jpeg-decoder",
@@ -4501,7 +4742,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -4541,15 +4782,15 @@ checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
 
 [[package]]
 name = "png"
-version = "0.17.13"
+version = "0.17.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1"
+checksum = "52f9d46a34a05a6a57566bc2bfae066ef07585a6e3fa30fbbdff5936380623f0"
 dependencies = [
  "bitflags 1.3.2",
  "crc32fast",
  "fdeflate",
  "flate2",
- "miniz_oxide 0.7.4",
+ "miniz_oxide 0.8.0",
 ]
 
 [[package]]
@@ -4575,9 +4816,9 @@ checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2"
 
 [[package]]
 name = "portable-atomic"
-version = "1.8.0"
+version = "1.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d30538d42559de6b034bc76fd6dd4c38961b1ee5c6c56e3808c50128fdbc22ce"
+checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2"
 dependencies = [
  "critical-section",
 ]
@@ -4604,7 +4845,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba"
 dependencies = [
  "proc-macro2",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -4674,7 +4915,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd"
 dependencies = [
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -4849,9 +5090,9 @@ dependencies = [
 
 [[package]]
 name = "realfft"
-version = "3.3.0"
+version = "3.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "953d9f7e5cdd80963547b456251296efc2626ed4e3cbf36c869d9564e0220571"
+checksum = "390252372b7f2aac8360fc5e72eba10136b166d6faeed97e6d0c8324eb99b2b1"
 dependencies = [
  "rustfft 6.2.0",
 ]
@@ -4867,9 +5108,9 @@ dependencies = [
 
 [[package]]
 name = "redox_syscall"
-version = "0.5.6"
+version = "0.5.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "355ae415ccd3a04315d3f8246e86d67689ea74d88d915576e1589a351062a13b"
+checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f"
 dependencies = [
  "bitflags 2.6.0",
 ]
@@ -4887,14 +5128,14 @@ dependencies = [
 
 [[package]]
 name = "regex"
-version = "1.10.6"
+version = "1.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
+checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8"
 dependencies = [
  "aho-corasick",
  "memchr",
- "regex-automata 0.4.7",
- "regex-syntax 0.8.4",
+ "regex-automata 0.4.8",
+ "regex-syntax 0.8.5",
 ]
 
 [[package]]
@@ -4908,13 +5149,13 @@ dependencies = [
 
 [[package]]
 name = "regex-automata"
-version = "0.4.7"
+version = "0.4.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
+checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3"
 dependencies = [
  "aho-corasick",
  "memchr",
- "regex-syntax 0.8.4",
+ "regex-syntax 0.8.5",
 ]
 
 [[package]]
@@ -4925,9 +5166,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
 
 [[package]]
 name = "regex-syntax"
-version = "0.8.4"
+version = "0.8.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
+checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
 
 [[package]]
 name = "resvg"
@@ -5030,7 +5271,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "rust-embed-utils",
- "syn 2.0.77",
+ "syn 2.0.79",
  "walkdir",
 ]
 
@@ -5235,7 +5476,7 @@ checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -5258,7 +5499,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -5360,9 +5601,9 @@ checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
 
 [[package]]
 name = "skia-bindings"
-version = "0.78.0"
+version = "0.78.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a5ac1da945f92ee2c5ae7999bc679d682fd976ef524b09cc80b5aae971d3e557"
+checksum = "29880a81b088de322e9c5306236c70761a61b5fa4df3c15c93bad3ce890ce34c"
 dependencies = [
  "bindgen",
  "cc",
@@ -5377,9 +5618,9 @@ dependencies = [
 
 [[package]]
 name = "skia-safe"
-version = "0.78.0"
+version = "0.78.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "80a2993ab98e8f01c874fc35cfec9a8d216d968b80f7e9b1cb9ac1bf4f6a2f3a"
+checksum = "4f15700ac678c06649077495acbba07e7ae01e5ca46b7dc18213f2c3477ada71"
 dependencies = [
  "bitflags 2.6.0",
  "lazy_static",
@@ -5549,7 +5790,7 @@ dependencies = [
  "objc2-foundation",
  "objc2-quartz-core",
  "raw-window-handle 0.6.2",
- "redox_syscall 0.5.6",
+ "redox_syscall 0.5.7",
  "rustix",
  "tiny-xlib",
  "wasm-bindgen",
@@ -5657,7 +5898,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "rustversion",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -5884,9 +6125,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.77"
+version = "2.0.79"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed"
+checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -5938,9 +6179,9 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
 
 [[package]]
 name = "tempfile"
-version = "3.12.0"
+version = "3.13.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64"
+checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b"
 dependencies = [
  "cfg-if",
  "fastrand",
@@ -5981,7 +6222,7 @@ checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -6137,7 +6378,7 @@ version = "0.22.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5"
 dependencies = [
- "indexmap 2.5.0",
+ "indexmap 2.6.0",
  "serde",
  "serde_spanned",
  "toml_datetime",
@@ -6164,7 +6405,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -6287,9 +6528,9 @@ dependencies = [
 
 [[package]]
 name = "udev"
-version = "0.8.0"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50051c6e22be28ee6f217d50014f3bc29e81c20dc66ff7ca0d5c5226e1dcc5a1"
+checksum = "8ba005bcd5b1158ae3cd815905990e8b6ee4ba9ee7adbab6d7b58d389ad09c93"
 dependencies = [
  "io-lifetimes",
  "libc",
@@ -6338,9 +6579,9 @@ dependencies = [
 
 [[package]]
 name = "unicode-bidi"
-version = "0.3.15"
+version = "0.3.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
+checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893"
 
 [[package]]
 name = "unicode-bidi-mirroring"
@@ -6377,9 +6618,9 @@ dependencies = [
 
 [[package]]
 name = "unicode-properties"
-version = "0.1.2"
+version = "0.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52ea75f83c0137a9b98608359a5f1af8144876eb67bcb1ce837368e906a9f524"
+checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0"
 
 [[package]]
 name = "unicode-script"
@@ -6537,7 +6778,7 @@ checksum = "68c1b85ec843d3bc60e9d65fa7e00ce6549416a25c267b5ea93e6c81e3aa66e5"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -6553,7 +6794,7 @@ dependencies = [
  "crossbeam-queue",
  "half",
  "heck 0.4.1",
- "indexmap 2.5.0",
+ "indexmap 2.6.0",
  "libloading 0.8.5",
  "objc",
  "once_cell",
@@ -6607,7 +6848,7 @@ dependencies = [
  "once_cell",
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
  "wasm-bindgen-shared",
 ]
 
@@ -6641,7 +6882,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
@@ -6901,7 +7142,7 @@ checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -6912,7 +7153,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -6923,7 +7164,7 @@ checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -6934,7 +7175,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -7422,7 +7663,7 @@ dependencies = [
  "proc-macro-crate",
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
  "zvariant_utils",
 ]
 
@@ -7455,7 +7696,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -7475,7 +7716,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
 
 [[package]]
@@ -7493,7 +7734,7 @@ dependencies = [
  "displaydoc",
  "flate2",
  "hmac",
- "indexmap 2.5.0",
+ "indexmap 2.6.0",
  "memchr",
  "pbkdf2",
  "rand",
@@ -7565,7 +7806,7 @@ dependencies = [
  "proc-macro-crate",
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
  "zvariant_utils",
 ]
 
@@ -7577,5 +7818,5 @@ checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.77",
+ "syn 2.0.79",
 ]
diff --git a/Cargo.toml b/Cargo.toml
index 8cfa2d0b0..0184c4abd 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -17,6 +17,11 @@ resolver = "2"
 # until you are ready to occasional crashes
 panic = "unwind"
 
+# Should find more panics, that now are hidden from user
+# There is one big disadvantage - in case of overflow/underflow entire app crashes and panic cannot be catched and app aborts
+# So feel free to disable it, if you want
+overflow-checks = true
+
 # LTO setting is disabled by default, because release mode is usually needed to develop app and compilation with LTO would take a lot of time
 # But it is used to optimize release builds(and probably also in CI, where time is not so important as in local development)
 #lto = "thin"
diff --git a/Changelog.md b/Changelog.md
index f3ff8ee2a..c8a698589 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,5 +1,10 @@
 ## Version 8.0.0 - ?
 
+### Breaking changes
+
+- Due removing image_type from image struct, old cache files are incompatible with new version and should be regenerated
+  from scratch(it uses new name)
+
 ### Core
 
 - Removed some unnecessary panics - [#1354](https://github.com/qarmin/czkawka/pull/1354)
@@ -14,18 +19,33 @@
 - Printing to file/console no longer uses two backslashes in windows
   paths - [#1354](https://github.com/qarmin/czkawka/pull/1354)
 - Fixed panic when failed to decode raw picture - [#1355](https://github.com/qarmin/czkawka/pull/1355)
+- Remove useless saving/loading cache when there is no files to
+  check - [#1358](https://github.com/qarmin/czkawka/pull/1358)
+- Filtering hard links on windows - [#1316](https://github.com/qarmin/czkawka/pull/1316)
+- Added jxl support - [#1358](https://github.com/qarmin/czkawka/pull/1358)
+- Added avif support(via external C library, not enabled by
+  default) - [#1358](https://github.com/qarmin/czkawka/pull/1358)
+- Integer overflow are enabled by default(prepare for reporting bugs, slower performance and
+  unstability) - [#1358](https://github.com/qarmin/czkawka/pull/1358)
+- Fixed crash when loading invalid image cache - [#1230](https://github.com/qarmin/czkawka/pull/1230)
 
 ### Krokiet
 
 - Fixed invalid default hash size in similar images - [#1354](https://github.com/qarmin/czkawka/pull/1354)
 - Fixed and added more input parameters to the application - [#1354](https://github.com/qarmin/czkawka/pull/1354)
+- Fixed problem with loading invalid preset - [#1226](https://github.com/qarmin/czkawka/pull/1226)
 
 ### GTK GUI
 
 - Fixed and added more input parameters to the application - [#1355](https://github.com/qarmin/czkawka/pull/1355)
+- Added option to use external libraries instead gtk pixbuf loader for
+  previews - [#1358](https://github.com/qarmin/czkawka/pull/1358)
+- Using static runtime with zstd compression in appimage - [#1350](https://github.com/qarmin/czkawka/pull/1355)
+- [External] Mac homebrew version of app - https://formulae.brew.sh/formula/czkawka
 
 ### CLI
 
+- Added options to find/remove images by size - [#1255](https://github.com/qarmin/czkawka/pull/1255)
 - Fixed and added more input parameters to the application - [#1354](https://github.com/qarmin/czkawka/pull/1354)
 - Fixed crash when stopping scan mutliple times - [#1355](https://github.com/qarmin/czkawka/pull/1355)
 - Print results also in debug build - [#1355](https://github.com/qarmin/czkawka/pull/1355)
diff --git a/czkawka_cli/Cargo.toml b/czkawka_cli/Cargo.toml
index 58884fc82..40337cdbd 100644
--- a/czkawka_cli/Cargo.toml
+++ b/czkawka_cli/Cargo.toml
@@ -27,3 +27,4 @@ ctrlc = { version = "3.4", features = ["termination"] }
 default = []
 heif = ["czkawka_core/heif"]
 libraw = ["czkawka_core/libraw"]
+libavif = ["czkawka_core/libavif"]
diff --git a/czkawka_cli/README.md b/czkawka_cli/README.md
index 4e8c156d2..e5a5cd120 100644
--- a/czkawka_cli/README.md
+++ b/czkawka_cli/README.md
@@ -12,11 +12,12 @@ Windows 7.
 
 On linux it is even possible with eyra to avoid entirely libc and using fully static rust binary.
 
-If you want to use similar videos tool, you need to install ffmpeg(runtime dependency) or use heif/libraw(build/runtime
-dependency) you need to install required packages.
+If you want to use similar videos tool, you need to install ffmpeg(runtime dependency).  
+If you want to use heif/libraw/libavif(build/runtime dependency) you need to install required packages(may require
+bigger os version than czkawka).
 
-- mac - `brew install ffmpeg libraw libheif` - https://formulae.brew.sh/formula/ffmpeg
-- linux - `sudo apt install ffmpeg libraw-dev libheif-dev`
+- mac - `brew install ffmpeg libraw libheif libavif` - https://formulae.brew.sh/formula/ffmpeg
+- linux - `sudo apt install ffmpeg libraw-dev libheif-dev libavif-dev libdav1d-dev`
 - windows - `choco install ffmpeg` - or if not working, download from https://ffmpeg.org/download.html#build-windows and
   unpack to location with `czkawka_cli.exe`, heif and libraw are not supported on windows
 
@@ -31,7 +32,7 @@ cargo run --release --bin czkawka_cli
 you can enable additional features via
 
 ```shell
-cargo run --release --bin czkawka_cli --features "heif,libraw"
+cargo run --release --bin czkawka_cli --features "heif,libraw,libavif"
 ```
 
 on linux to build fully static binary with eyra you need to use (this is only for crazy people, so just use command
@@ -53,7 +54,6 @@ Not all available features in core are available in CLI.
 List of not available features:
 
 - Ability to use/choose referenced directories
-- See progress of scanning
 
 ## LICENSE
 
diff --git a/czkawka_cli/src/main.rs b/czkawka_cli/src/main.rs
index 39320d9ff..8a580ef6d 100644
--- a/czkawka_cli/src/main.rs
+++ b/czkawka_cli/src/main.rs
@@ -4,10 +4,8 @@
 use std::thread;
 
 use clap::Parser;
-use crossbeam_channel::{bounded, unbounded, Receiver, Sender};
-use log::error;
-
 use commands::Commands;
+use crossbeam_channel::{bounded, unbounded, Receiver, Sender};
 use czkawka_core::bad_extensions::{BadExtensions, BadExtensionsParameters};
 use czkawka_core::big_file::{BigFile, BigFileParameters, SearchMode};
 use czkawka_core::broken_files::{BrokenFiles, BrokenFilesParameters, CheckedTypes};
@@ -24,6 +22,7 @@ use czkawka_core::same_music::{SameMusic, SameMusicParameters};
 use czkawka_core::similar_images::{return_similarity_from_similarity_preset, test_image_conversion_speed, SimilarImages, SimilarImagesParameters};
 use czkawka_core::similar_videos::{SimilarVideos, SimilarVideosParameters};
 use czkawka_core::temporary::Temporary;
+use log::error;
 
 use crate::commands::{
     Args, BadExtensionsArgs, BiggestFilesArgs, BrokenFilesArgs, CommonCliItems, DuplicatesArgs, EmptyFilesArgs, EmptyFoldersArgs, InvalidSymlinksArgs, SameMusicArgs,
diff --git a/czkawka_cli/src/progress.rs b/czkawka_cli/src/progress.rs
index 526014b2e..1377d0b92 100644
--- a/czkawka_cli/src/progress.rs
+++ b/czkawka_cli/src/progress.rs
@@ -1,10 +1,9 @@
 use std::time::Duration;
 
 use crossbeam_channel::Receiver;
-use indicatif::{ProgressBar, ProgressStyle};
-
 use czkawka_core::common_dir_traversal::ToolType;
 use czkawka_core::progress_data::{CurrentStage, ProgressData};
+use indicatif::{ProgressBar, ProgressStyle};
 
 pub fn connect_progress(progress_receiver: &Receiver<ProgressData>) {
     let mut pb = ProgressBar::new(1);
diff --git a/czkawka_core/Cargo.toml b/czkawka_core/Cargo.toml
index eeb0c9617..e5ca18007 100644
--- a/czkawka_core/Cargo.toml
+++ b/czkawka_core/Cargo.toml
@@ -21,7 +21,7 @@ directories-next = "2.0"
 # Needed by similar images
 image_hasher = "2.0"
 bk-tree = "0.5"
-image = { version = "0.25", default-features = false, features = ["gif", "jpeg", "ico", "png", "pnm", "tga", "tiff", "webp", "bmp", "hdr", "dds", "qoi"] }
+image = { version = "0.25", default-features = false, features = ["bmp", "dds", "exr", "ff", "gif", "hdr", "ico", "jpeg", "png", "pnm", "qoi", "tga", "tiff", "webp"] }
 hamming = "0.1"
 
 # Needed by same music
@@ -42,7 +42,7 @@ blake3 = "1.5"
 crc32fast = "1.4"
 xxhash-rust = { version = "0.8", features = ["xxh3"] }
 
-tempfile = "3.12"
+tempfile = "3.13"
 
 # Video Duplicates
 vid_dup_finder_lib = "0.1"
@@ -57,12 +57,13 @@ serde_json = "1.0"
 i18n-embed = { version = "0.15", features = ["fluent-system", "desktop-requester"] }
 i18n-embed-fl = "0.9"
 rust-embed = { version = "8.5", features = ["debug-embed"] }
-once_cell = "1.19"
+once_cell = "1.20"
 
 # Raw image files
 rawloader = "0.37"
 imagepipe = "0.5"
 libraw-rs = { version = "0.0.4", optional = true }
+jxl-oxide = { version = "0.9.0", default-features = false }
 
 # Checking for invalid extensions
 mime_guess = "2.0"
@@ -95,3 +96,4 @@ rustc_version = "0.4"
 default = []
 heif = ["dep:libheif-rs", "dep:libheif-sys"]
 libraw = ["dep:libraw-rs"]
+libavif = ["image/avif-native", "image/avif"]
diff --git a/czkawka_core/src/bad_extensions.rs b/czkawka_core/src/bad_extensions.rs
index 1ead2f571..124417a8d 100644
--- a/czkawka_core/src/bad_extensions.rs
+++ b/czkawka_core/src/bad_extensions.rs
@@ -263,6 +263,10 @@ impl BadExtensions {
 
     #[fun_time(message = "look_for_bad_extensions_files", level = "debug")]
     fn look_for_bad_extensions_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&Sender<ProgressData>>) -> bool {
+        if self.files_to_check.is_empty() {
+            return true;
+        }
+
         let (progress_thread_handle, progress_thread_run, atomic_counter, check_was_stopped) =
             prepare_thread_handler_common(progress_sender, CurrentStage::BadExtensionsChecking, self.files_to_check.len(), self.get_test_type());
 
diff --git a/czkawka_core/src/big_file.rs b/czkawka_core/src/big_file.rs
index addbaf4d3..b5e9fa34a 100644
--- a/czkawka_core/src/big_file.rs
+++ b/czkawka_core/src/big_file.rs
@@ -1,16 +1,17 @@
 use std::fs;
 use std::io::Write;
 
-use crate::common_dir_traversal::{DirTraversalBuilder, DirTraversalResult, FileEntry, ToolType};
-use crate::common_tool::{CommonData, CommonToolData, DeleteMethod};
-use crate::common_traits::{DebugPrint, PrintResults};
-use crate::progress_data::ProgressData;
 use crossbeam_channel::{Receiver, Sender};
 use fun_time::fun_time;
 use humansize::{format_size, BINARY};
 use log::debug;
 use rayon::prelude::*;
 
+use crate::common_dir_traversal::{DirTraversalBuilder, DirTraversalResult, FileEntry, ToolType};
+use crate::common_tool::{CommonData, CommonToolData, DeleteMethod};
+use crate::common_traits::{DebugPrint, PrintResults};
+use crate::progress_data::ProgressData;
+
 #[derive(Copy, Clone, Eq, PartialEq)]
 pub enum SearchMode {
     BiggestFiles,
@@ -65,7 +66,7 @@ impl BigFile {
         self.debug_print();
     }
 
-    // #[fun_time(message = "look_for_big_files", level = "debug")]
+    #[fun_time(message = "look_for_big_files", level = "debug")]
     fn look_for_big_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&Sender<ProgressData>>) -> bool {
         let result = DirTraversalBuilder::new()
             .group_by(|_fe| ())
diff --git a/czkawka_core/src/broken_files.rs b/czkawka_core/src/broken_files.rs
index 72cd15266..b493c2fe5 100644
--- a/czkawka_core/src/broken_files.rs
+++ b/czkawka_core/src/broken_files.rs
@@ -5,15 +5,6 @@ use std::path::{Path, PathBuf};
 use std::sync::atomic::Ordering;
 use std::{fs, mem, panic};
 
-use crate::common::{
-    check_if_stop_received, create_crash_message, prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads, AUDIO_FILES_EXTENSIONS,
-    IMAGE_RS_BROKEN_FILES_EXTENSIONS, PDF_FILES_EXTENSIONS, ZIP_FILES_EXTENSIONS,
-};
-use crate::common_cache::{extract_loaded_cache, get_broken_files_cache_file, load_cache_from_file_generalized_by_path, save_cache_to_file_generalized};
-use crate::common_dir_traversal::{DirTraversalBuilder, DirTraversalResult, FileEntry, ToolType};
-use crate::common_tool::{CommonData, CommonToolData, DeleteMethod};
-use crate::common_traits::*;
-use crate::progress_data::{CurrentStage, ProgressData};
 use crossbeam_channel::{Receiver, Sender};
 use fun_time::fun_time;
 use log::debug;
@@ -24,6 +15,16 @@ use pdf::PdfError::Try;
 use rayon::prelude::*;
 use serde::{Deserialize, Serialize};
 
+use crate::common::{
+    check_if_stop_received, create_crash_message, prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads, AUDIO_FILES_EXTENSIONS,
+    IMAGE_RS_BROKEN_FILES_EXTENSIONS, PDF_FILES_EXTENSIONS, ZIP_FILES_EXTENSIONS,
+};
+use crate::common_cache::{extract_loaded_cache, get_broken_files_cache_file, load_cache_from_file_generalized_by_path, save_cache_to_file_generalized};
+use crate::common_dir_traversal::{DirTraversalBuilder, DirTraversalResult, FileEntry, ToolType};
+use crate::common_tool::{CommonData, CommonToolData, DeleteMethod};
+use crate::common_traits::*;
+use crate::progress_data::{CurrentStage, ProgressData};
+
 #[derive(Clone, Serialize, Deserialize, Debug)]
 pub struct BrokenEntry {
     pub path: PathBuf,
@@ -294,6 +295,10 @@ impl BrokenFiles {
 
     #[fun_time(message = "look_for_broken_files", level = "debug")]
     fn look_for_broken_files(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&Sender<ProgressData>>) -> bool {
+        if self.files_to_check.is_empty() {
+            return true;
+        }
+
         let (loaded_hash_map, records_already_cached, non_cached_files_to_check) = self.load_cache();
 
         let (progress_thread_handle, progress_thread_run, atomic_counter, _check_was_stopped) =
diff --git a/czkawka_core/src/common.rs b/czkawka_core/src/common.rs
index 807265238..0d8ea1a92 100644
--- a/czkawka_core/src/common.rs
+++ b/czkawka_core/src/common.rs
@@ -1,6 +1,3 @@
-#![allow(unused_imports)]
-// I don't wanna fight with unused(heif) imports in this file, so simply ignore it to avoid too much complexity
-
 use std::cmp::Ordering;
 use std::ffi::OsString;
 use std::fs::{DirEntry, File, OpenOptions};
@@ -8,24 +5,14 @@ use std::path::{Path, PathBuf};
 use std::sync::atomic::{AtomicBool, AtomicUsize};
 use std::sync::{atomic, Arc};
 use std::thread::{sleep, JoinHandle};
-use std::time::{Duration, Instant, SystemTime};
+use std::time::{Duration, SystemTime};
 use std::{fs, thread};
 
-#[cfg(feature = "heif")]
-use anyhow::Result;
 use crossbeam_channel::Sender;
 use directories_next::ProjectDirs;
 use fun_time::fun_time;
 use handsome_logger::{ColorChoice, ConfigBuilder, TerminalMode};
-use image::{DynamicImage, ImageBuffer, Rgb};
-use imagepipe::{ImageSource, Pipeline};
-#[cfg(feature = "heif")]
-use libheif_rs::{ColorSpace, HeifContext, RgbChroma};
-#[cfg(feature = "libraw")]
-use libraw::Processor;
-use log::{debug, error, info, warn, LevelFilter, Record};
-use rawloader::RawLoader;
-use symphonia::core::conv::IntoSample;
+use log::{debug, info, warn, LevelFilter, Record};
 
 // #[cfg(feature = "heif")]
 // use libheif_rs::LibHeif;
@@ -33,7 +20,7 @@ use crate::common_dir_traversal::{CheckingMethod, ToolType};
 use crate::common_directory::Directories;
 use crate::common_items::{ExcludedItems, SingleExcludedItem};
 use crate::common_messages::Messages;
-use crate::common_tool::{CommonData, DeleteMethod};
+use crate::common_tool::DeleteMethod;
 use crate::common_traits::ResultEntry;
 use crate::duplicate::make_hard_link;
 use crate::progress_data::{CurrentStage, ProgressData};
@@ -76,6 +63,7 @@ pub fn get_all_available_threads() -> usize {
     })
 }
 
+#[allow(clippy::vec_init_then_push)]
 pub fn print_version_mode() {
     let rust_version = env!("RUST_VERSION_INTERNAL");
     let debug_release = if cfg!(debug_assertions) { "debug" } else { "release" };
@@ -83,12 +71,24 @@ pub fn print_version_mode() {
     let processors = get_all_available_threads();
 
     let info = os_info::get();
+
+    #[allow(unused_mut)]
+    let mut features: Vec<&str> = vec![];
+    #[cfg(feature = "heif")]
+    features.push("heif");
+    #[cfg(feature = "libavif")]
+    features.push("libavif");
+    #[cfg(feature = "libraw")]
+    features.push("libraw");
+
     info!(
-        "App version: {CZKAWKA_VERSION}, {debug_release} mode, rust {rust_version}, os {} {} [{} {}], {processors} cpu/threads",
+        "App version: {CZKAWKA_VERSION}, {debug_release} mode, rust {rust_version}, os {} {} [{} {}], {processors} cpu/threads, features({}): [{}]",
         info.os_type(),
         info.version(),
         std::env::consts::ARCH,
         info.bitness(),
+        features.len(),
+        features.join(", ")
     );
     if cfg!(debug_assertions) {
         warn!("You are running debug version of app which is a lot of slower than release version.");
@@ -123,14 +123,31 @@ pub fn set_number_of_threads(thread_number: usize) {
 pub const RAW_IMAGE_EXTENSIONS: &[&str] = &[
     "mrw", "arw", "srf", "sr2", "mef", "orf", "srw", "erf", "kdc", "kdc", "dcs", "rw2", "raf", "dcr", "dng", "pef", "crw", "iiq", "3fr", "nrw", "nef", "mos", "cr2", "ari",
 ];
+
+pub const JXL_IMAGE_EXTENSIONS: &[&str] = &["jxl"];
+
+#[cfg(feature = "libavif")]
+pub const IMAGE_RS_EXTENSIONS: &[&str] = &[
+    "jpg", "jpeg", "png", "bmp", "tiff", "tif", "tga", "ff", "jif", "jfi", "webp", "gif", "ico", "exr", "qoi", "avif",
+];
+#[cfg(not(feature = "libavif"))]
 pub const IMAGE_RS_EXTENSIONS: &[&str] = &["jpg", "jpeg", "png", "bmp", "tiff", "tif", "tga", "ff", "jif", "jfi", "webp", "gif", "ico", "exr", "qoi"];
 
+#[cfg(feature = "libavif")]
+pub const IMAGE_RS_SIMILAR_IMAGES_EXTENSIONS: &[&str] = &["jpg", "jpeg", "png", "tiff", "tif", "tga", "ff", "jif", "jfi", "bmp", "webp", "exr", "qoi", "avif"];
+#[cfg(not(feature = "libavif"))]
 pub const IMAGE_RS_SIMILAR_IMAGES_EXTENSIONS: &[&str] = &["jpg", "jpeg", "png", "tiff", "tif", "tga", "ff", "jif", "jfi", "bmp", "webp", "exr", "qoi"];
 
+#[cfg(feature = "libavif")]
+pub const IMAGE_RS_BROKEN_FILES_EXTENSIONS: &[&str] = &[
+    "jpg", "jpeg", "png", "tiff", "tif", "tga", "ff", "jif", "jfi", "gif", "bmp", "ico", "jfif", "jpe", "pnz", "dib", "webp", "exr", "avif",
+];
+#[cfg(not(feature = "libavif"))]
 pub const IMAGE_RS_BROKEN_FILES_EXTENSIONS: &[&str] = &[
     "jpg", "jpeg", "png", "tiff", "tif", "tga", "ff", "jif", "jfi", "gif", "bmp", "ico", "jfif", "jpe", "pnz", "dib", "webp", "exr",
 ];
-pub const HEIC_EXTENSIONS: &[&str] = &["heif", "heifs", "heic", "heics", "avci", "avcs", "avifs"];
+
+pub const HEIC_EXTENSIONS: &[&str] = &["heif", "heifs", "heic", "heics", "avci", "avcs"];
 
 pub const ZIP_FILES_EXTENSIONS: &[&str] = &["zip", "jar"];
 
@@ -259,83 +276,6 @@ pub fn open_cache_folder(cache_file_name: &str, save_to_cache: bool, use_json: b
     None
 }
 
-#[cfg(feature = "heif")]
-pub fn get_dynamic_image_from_heic(path: &str) -> Result<DynamicImage> {
-    // let libheif = LibHeif::new();
-    let im = HeifContext::read_from_file(path)?;
-    let handle = im.primary_image_handle()?;
-    // let image = libheif.decode(&handle, ColorSpace::Rgb(RgbChroma::Rgb), None)?; // Enable when using libheif 0.19
-    let image = handle.decode(ColorSpace::Rgb(RgbChroma::Rgb), None)?;
-    let width = image.width();
-    let height = image.height();
-    let planes = image.planes();
-    let interleaved_plane = planes.interleaved.ok_or_else(|| anyhow::anyhow!("Failed to get interleaved plane"))?;
-    ImageBuffer::from_raw(width, height, interleaved_plane.data.to_owned())
-        .map(DynamicImage::ImageRgb8)
-        .ok_or_else(|| anyhow::anyhow!("Failed to create image buffer"))
-}
-
-#[cfg(feature = "libraw")]
-pub fn get_dynamic_image_from_raw_image(path: impl AsRef<Path>) -> Result<DynamicImage> {
-    let buf = fs::read(path.as_ref())?;
-
-    let processor = Processor::new();
-    let start_timer = Instant::now();
-    let processed = processor.process_8bit(&buf)?;
-    println!("Processing took {:?}", start_timer.elapsed());
-
-    let width = processed.width();
-    let height = processed.height();
-
-    let data = processed.to_vec();
-    let data_len = data.len();
-
-    let buffer = ImageBuffer::from_raw(width, height, data).ok_or(anyhow::anyhow!(format!(
-        "Cannot create ImageBuffer from raw image with width: {width} and height: {height} and data length: {data_len}",
-    )))?;
-
-    Ok(DynamicImage::ImageRgb8(buffer))
-}
-
-#[cfg(not(feature = "libraw"))]
-pub fn get_dynamic_image_from_raw_image(path: impl AsRef<Path> + std::fmt::Debug) -> Result<DynamicImage, String> {
-    let mut start_timer = Instant::now();
-    let mut times = Vec::new();
-
-    let loader = RawLoader::new();
-    let raw = loader.decode_file(path.as_ref()).map_err(|e| format!("Error decoding file: {e:?}"))?;
-
-    times.push(("After decoding", start_timer.elapsed()));
-    start_timer = Instant::now();
-
-    let source = ImageSource::Raw(raw);
-
-    times.push(("After creating source", start_timer.elapsed()));
-    start_timer = Instant::now();
-
-    let mut pipeline = Pipeline::new_from_source(source).map_err(|e| format!("Error creating pipeline: {e:?}"))?;
-
-    times.push(("After creating pipeline", start_timer.elapsed()));
-    start_timer = Instant::now();
-
-    pipeline.run(None);
-    let image = pipeline.output_8bit(None).map_err(|e| format!("Error running pipeline: {e:?}"))?;
-
-    times.push(("After creating image", start_timer.elapsed()));
-    start_timer = Instant::now();
-
-    let image = ImageBuffer::<Rgb<u8>, Vec<u8>>::from_raw(image.width as u32, image.height as u32, image.data).ok_or_else(|| "Failed to create image buffer".to_string())?;
-
-    times.push(("After creating image buffer", start_timer.elapsed()));
-    start_timer = Instant::now();
-    let res = DynamicImage::ImageRgb8(image);
-    times.push(("After creating dynamic image", start_timer.elapsed()));
-
-    let str_timer = times.into_iter().map(|(name, time)| format!("{name}: {time:?}")).collect::<Vec<_>>().join(", ");
-    debug!("Loading raw image --- {str_timer}");
-    Ok(res)
-}
-
 pub fn split_path(path: &Path) -> (String, String) {
     match (path.parent(), path.file_name()) {
         (Some(dir), Some(file)) => (dir.to_string_lossy().to_string(), file.to_string_lossy().into_owned()),
diff --git a/czkawka_core/src/common_cache.rs b/czkawka_core/src/common_cache.rs
index d4367d57b..77b80c4c9 100644
--- a/czkawka_core/src/common_cache.rs
+++ b/czkawka_core/src/common_cache.rs
@@ -4,7 +4,7 @@ use std::io::{BufReader, BufWriter};
 use fun_time::fun_time;
 use image::imageops::FilterType;
 use image_hasher::HashAlg;
-use log::debug;
+use log::{debug, error};
 use rayon::iter::{IntoParallelIterator, ParallelIterator};
 use serde::{Deserialize, Serialize};
 
@@ -15,6 +15,7 @@ use crate::duplicate::HashType;
 use crate::similar_images::{convert_algorithm_to_string, convert_filters_to_string};
 
 const CACHE_VERSION: &str = "70";
+const CACHE_IMAGE_VERSION: &str = "80";
 
 pub fn get_broken_files_cache_file() -> String {
     format!("cache_broken_files_{CACHE_VERSION}.bin")
@@ -22,7 +23,7 @@ pub fn get_broken_files_cache_file() -> String {
 
 pub fn get_similar_images_cache_file(hash_size: &u8, hash_alg: &HashAlg, image_filter: &FilterType) -> String {
     format!(
-        "cache_similar_images_{hash_size}_{}_{}_{CACHE_VERSION}.bin",
+        "cache_similar_images_{hash_size}_{}_{}_{CACHE_IMAGE_VERSION}.bin",
         convert_algorithm_to_string(hash_alg),
         convert_filters_to_string(image_filter),
     )
@@ -195,11 +196,18 @@ where
         if let Some(file_handler) = file_handler {
             let reader = BufReader::new(file_handler);
 
+            // TODO cannot use limits
+            // Probably also save function needs to be updated
+            // Without it loading not working
+
+            // let options = bincode::DefaultOptions::new().with_limit(4 * 1024 * 1024 * 1024);
+            // vec_loaded_entries = match options.deserialize_from(reader) {
+
             vec_loaded_entries = match bincode::deserialize_from(reader) {
                 Ok(t) => t,
                 Err(e) => {
                     text_messages.warnings.push(format!("Failed to load data from cache file {cache_file:?}, reason {e}"));
-                    debug!("Failed to load cache from file {cache_file:?}");
+                    error!("Failed to load cache from file {cache_file:?}");
                     return (text_messages, None);
                 }
             };
@@ -208,7 +216,9 @@ where
             vec_loaded_entries = match serde_json::from_reader(reader) {
                 Ok(t) => t,
                 Err(e) => {
-                    text_messages.warnings.push(format!("Failed to load data from cache file {cache_file_json:?}, reason {e}"));
+                    text_messages
+                        .warnings
+                        .push(format!("Failed to load data from json cache file {cache_file_json:?}, reason {e}"));
                     debug!("Failed to load cache from file {cache_file:?}");
                     return (text_messages, None);
                 }
diff --git a/czkawka_core/src/common_dir_traversal.rs b/czkawka_core/src/common_dir_traversal.rs
index b07f16001..3ebceaaec 100644
--- a/czkawka_core/src/common_dir_traversal.rs
+++ b/czkawka_core/src/common_dir_traversal.rs
@@ -645,16 +645,18 @@ pub fn take_1_per_inode((k, mut v): (Option<u64>, Vec<FileEntry>)) -> Vec<FileEn
 
 #[cfg(test)]
 mod tests {
-    use super::*;
-    use crate::common_tool::*;
-    use once_cell::sync::Lazy;
     use std::collections::HashSet;
     use std::fs::File;
     use std::io::prelude::*;
     use std::time::{Duration, SystemTime};
     use std::{fs, io};
+
+    use once_cell::sync::Lazy;
     use tempfile::TempDir;
 
+    use super::*;
+    use crate::common_tool::*;
+
     impl CommonData for CommonToolData {
         fn get_cd(&self) -> &CommonToolData {
             self
diff --git a/czkawka_core/src/common_image.rs b/czkawka_core/src/common_image.rs
new file mode 100644
index 000000000..d0fdbc482
--- /dev/null
+++ b/czkawka_core/src/common_image.rs
@@ -0,0 +1,173 @@
+#![allow(unused_imports)]
+// I don't wanna fight with unused(heif) imports in this file, so simply ignore it to avoid too much complexity
+
+use std::cmp::Ordering;
+use std::ffi::OsString;
+use std::fs::{DirEntry, File, OpenOptions};
+use std::path::{Path, PathBuf};
+use std::sync::atomic::{AtomicBool, AtomicUsize};
+use std::sync::{atomic, Arc};
+use std::thread::{sleep, JoinHandle};
+use std::time::{Duration, Instant, SystemTime};
+use std::{fs, panic, thread};
+
+use anyhow::anyhow;
+use crossbeam_channel::Sender;
+use directories_next::ProjectDirs;
+use fun_time::fun_time;
+use handsome_logger::{ColorChoice, ConfigBuilder, TerminalMode};
+use image::{DynamicImage, ImageBuffer, Rgb, Rgba};
+use imagepipe::{ImageSource, Pipeline};
+use jxl_oxide::image::BitDepth;
+use jxl_oxide::{JxlImage, PixelFormat};
+#[cfg(feature = "heif")]
+use libheif_rs::{ColorSpace, HeifContext, RgbChroma};
+#[cfg(feature = "libraw")]
+use libraw::Processor;
+use log::{debug, error, info, warn, LevelFilter, Record};
+use rawloader::RawLoader;
+use symphonia::core::conv::IntoSample;
+
+use crate::common;
+use crate::common::{create_crash_message, HEIC_EXTENSIONS, JXL_IMAGE_EXTENSIONS, RAW_IMAGE_EXTENSIONS};
+// #[cfg(feature = "heif")]
+// use libheif_rs::LibHeif;
+
+// TODO this code is ugly - this should exists in image-rs or be taken from official example of jxl-oxide
+// Its presence offends everything good in this world
+pub fn get_jxl_image(path: &str) -> anyhow::Result<DynamicImage> {
+    let buf_reader = std::io::BufReader::new(File::open(path)?);
+
+    let decoder = JxlImage::builder().read(buf_reader).map_err(|e| anyhow::anyhow!("Failed to read jxl file {e}"))?;
+    let width = decoder.width();
+    let height = decoder.height();
+    let frame = decoder.render_frame(0).map_err(|e| anyhow::anyhow!("Failed to render jxl frame {e}"))?;
+    let planar = &frame.image_planar();
+    let pixfmt = decoder.pixel_format();
+    let bits_per_sample = decoder.image_header().metadata.bit_depth;
+
+    if bits_per_sample.bits_per_sample() == 8 && pixfmt == PixelFormat::Rgb && planar.len() == 3 {
+        let zips = planar[0].buf().iter().zip(planar[1].buf().iter()).zip(planar[2].buf().iter());
+        let pixels = zips.flat_map(|((r, g), b)| [(r * 255.0) as u8, (g * 255.0) as u8, (b * 255.0) as u8]).collect::<Vec<_>>();
+        let data = ImageBuffer::<Rgb<u8>, Vec<u8>>::from_vec(width, height, pixels).ok_or_else(|| anyhow::anyhow!("Failed to create rgb image buffer from jxl data"))?;
+        Ok(DynamicImage::ImageRgb8(data))
+    } else if bits_per_sample.bits_per_sample() == 8 && pixfmt == PixelFormat::Rgba && planar.len() == 4 {
+        let zips = planar[0].buf().iter().zip(planar[1].buf().iter()).zip(planar[2].buf().iter()).zip(planar[3].buf().iter());
+        let pixels = zips
+            .flat_map(|(((r, g), b), a)| [(r * 255.0) as u8, (g * 255.0) as u8, (b * 255.0) as u8, (a * 255.0) as u8])
+            .collect::<Vec<_>>();
+        let data = ImageBuffer::<Rgba<u8>, Vec<u8>>::from_vec(width, height, pixels).ok_or_else(|| anyhow::anyhow!("Failed to create rgba image buffer from jxl data"))?;
+        Ok(DynamicImage::ImageRgba8(data))
+    } else {
+        return Err(anyhow::anyhow!("Unsupported number of planes: {}", planar.len()));
+    }
+}
+
+pub fn get_dynamic_image_from_path(path: &str) -> Result<DynamicImage, String> {
+    let path_lower = Path::new(path).extension().unwrap_or_default().to_string_lossy().to_lowercase();
+
+    let res = panic::catch_unwind(|| {
+        if HEIC_EXTENSIONS.iter().any(|ext| path_lower.ends_with(ext)) {
+            #[cfg(feature = "heif")]
+            {
+                get_dynamic_image_from_heic(path).map_err(|e| format!("Cannot open heic file \"{path}\": {e}"))
+            }
+            #[cfg(not(feature = "heif"))]
+            {
+                image::open(path).map_err(|e| format!("Cannot open image file \"{path}\": {e}"))
+            }
+        } else if JXL_IMAGE_EXTENSIONS.iter().any(|ext| path_lower.ends_with(ext)) {
+            get_jxl_image(path).map_err(|e| format!("Cannot open jxl image file \"{path}\": {e}"))
+        } else if RAW_IMAGE_EXTENSIONS.iter().any(|ext| path_lower.ends_with(ext)) {
+            get_raw_image(path).map_err(|e| format!("Cannot open raw image file \"{path}\": {e}"))
+        } else {
+            image::open(path).map_err(|e| format!("Cannot open image file \"{path}\": {e}"))
+        }
+    });
+
+    if let Ok(res) = res {
+        match res {
+            Ok(t) => Ok(t),
+            Err(e) => Err(format!("Cannot open image file \"{path}\": {e}")),
+        }
+    } else {
+        let message = create_crash_message("Image-rs or libraw-rs or jxl-oxide", path, "https://github.com/image-rs/image/issues");
+        println!("{message}");
+        Err(message)
+    }
+}
+
+#[cfg(feature = "heif")]
+pub fn get_dynamic_image_from_heic(path: &str) -> anyhow::Result<DynamicImage> {
+    // let libheif = LibHeif::new();
+    let im = HeifContext::read_from_file(path)?;
+    let handle = im.primary_image_handle()?;
+    // let image = libheif.decode(&handle, ColorSpace::Rgb(RgbChroma::Rgb), None)?; // Enable when using libheif 0.19
+    let image = handle.decode(ColorSpace::Rgb(RgbChroma::Rgb), None)?;
+    let width = image.width();
+    let height = image.height();
+    let planes = image.planes();
+    let interleaved_plane = planes.interleaved.ok_or_else(|| anyhow::anyhow!("Failed to get interleaved plane"))?;
+    ImageBuffer::from_raw(width, height, interleaved_plane.data.to_owned())
+        .map(DynamicImage::ImageRgb8)
+        .ok_or_else(|| anyhow::anyhow!("Failed to create image buffer"))
+}
+
+#[cfg(feature = "libraw")]
+pub fn get_raw_image(path: impl AsRef<Path>) -> anyhow::Result<DynamicImage> {
+    let buf = fs::read(path.as_ref())?;
+
+    let processor = Processor::new();
+    let processed = processor.process_8bit(&buf)?;
+
+    let width = processed.width();
+    let height = processed.height();
+
+    let data = processed.to_vec();
+    let data_len = data.len();
+
+    let buffer = ImageBuffer::from_raw(width, height, data).ok_or(anyhow::anyhow!(format!(
+        "Cannot create ImageBuffer from raw image with width: {width} and height: {height} and data length: {data_len}",
+    )))?;
+
+    Ok(DynamicImage::ImageRgb8(buffer))
+}
+
+#[cfg(not(feature = "libraw"))]
+pub fn get_raw_image(path: impl AsRef<Path> + std::fmt::Debug) -> Result<DynamicImage, String> {
+    let mut start_timer = Instant::now();
+    let mut times = Vec::new();
+
+    let loader = RawLoader::new();
+    let raw = loader.decode_file(path.as_ref()).map_err(|e| format!("Error decoding file: {e:?}"))?;
+
+    times.push(("After decoding", start_timer.elapsed()));
+    start_timer = Instant::now();
+
+    let source = ImageSource::Raw(raw);
+
+    times.push(("After creating source", start_timer.elapsed()));
+    start_timer = Instant::now();
+
+    let mut pipeline = Pipeline::new_from_source(source).map_err(|e| format!("Error creating pipeline: {e:?}"))?;
+
+    times.push(("After creating pipeline", start_timer.elapsed()));
+    start_timer = Instant::now();
+
+    pipeline.run(None);
+    let image = pipeline.output_8bit(None).map_err(|e| format!("Error running pipeline: {e:?}"))?;
+
+    times.push(("After creating image", start_timer.elapsed()));
+    start_timer = Instant::now();
+
+    let image = ImageBuffer::<Rgb<u8>, Vec<u8>>::from_raw(image.width as u32, image.height as u32, image.data).ok_or_else(|| "Failed to create image buffer".to_string())?;
+
+    times.push(("After creating image buffer", start_timer.elapsed()));
+    start_timer = Instant::now();
+    let res = DynamicImage::ImageRgb8(image);
+    times.push(("After creating dynamic image", start_timer.elapsed()));
+
+    let str_timer = times.into_iter().map(|(name, time)| format!("{name}: {time:?}")).collect::<Vec<_>>().join(", ");
+    debug!("Loading raw image --- {str_timer}");
+    Ok(res)
+}
diff --git a/czkawka_core/src/duplicate.rs b/czkawka_core/src/duplicate.rs
index bc755ac51..c5fb70e75 100644
--- a/czkawka_core/src/duplicate.rs
+++ b/czkawka_core/src/duplicate.rs
@@ -10,12 +10,6 @@ use std::path::{Path, PathBuf};
 use std::sync::atomic::Ordering;
 use std::{fs, mem};
 
-use crate::common::{check_if_stop_received, delete_files_custom, prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads};
-use crate::common_cache::{get_duplicate_cache_file, load_cache_from_file_generalized_by_size, save_cache_to_file_generalized};
-use crate::common_dir_traversal::{CheckingMethod, DirTraversalBuilder, DirTraversalResult, FileEntry, ToolType};
-use crate::common_tool::{CommonData, CommonToolData, DeleteMethod};
-use crate::common_traits::*;
-use crate::progress_data::{CurrentStage, ProgressData};
 use crossbeam_channel::{Receiver, Sender};
 use fun_time::fun_time;
 use humansize::{format_size, BINARY};
@@ -24,6 +18,13 @@ use rayon::prelude::*;
 use serde::{Deserialize, Serialize};
 use xxhash_rust::xxh3::Xxh3;
 
+use crate::common::{check_if_stop_received, delete_files_custom, prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads};
+use crate::common_cache::{get_duplicate_cache_file, load_cache_from_file_generalized_by_size, save_cache_to_file_generalized};
+use crate::common_dir_traversal::{CheckingMethod, DirTraversalBuilder, DirTraversalResult, FileEntry, ToolType};
+use crate::common_tool::{CommonData, CommonToolData, DeleteMethod};
+use crate::common_traits::*;
+use crate::progress_data::{CurrentStage, ProgressData};
+
 const TEMP_HARDLINK_FILE: &str = "rzeczek.rxrxrxl";
 
 #[derive(PartialEq, Eq, Clone, Debug, Copy, Default)]
@@ -544,7 +545,11 @@ impl DuplicateFinder {
         stop_receiver: Option<&Receiver<()>>,
         progress_sender: Option<&Sender<ProgressData>>,
         pre_checked_map: &mut BTreeMap<u64, Vec<DuplicateEntry>>,
-    ) -> Option<()> {
+    ) -> bool {
+        if self.files_with_identical_size.is_empty() {
+            return true;
+        }
+
         let check_type = self.get_params().hash_type;
         let (progress_thread_handle, progress_thread_run, _atomic_counter, _check_was_stopped) =
             prepare_thread_handler_common(progress_sender, CurrentStage::DuplicatePreHashCacheLoading, 0, self.get_test_type());
@@ -553,7 +558,7 @@ impl DuplicateFinder {
 
         send_info_and_wait_for_ending_all_threads(&progress_thread_run, progress_thread_handle);
         if check_if_stop_received(stop_receiver) {
-            return None;
+            return false;
         }
         let (progress_thread_handle, progress_thread_run, atomic_counter, check_was_stopped) = prepare_thread_handler_common(
             progress_sender,
@@ -618,10 +623,10 @@ impl DuplicateFinder {
 
         send_info_and_wait_for_ending_all_threads(&progress_thread_run, progress_thread_handle);
         if check_was_stopped.load(Ordering::Relaxed) || check_if_stop_received(stop_receiver) {
-            return None;
+            return false;
         }
 
-        Some(())
+        true
     }
 
     fn diff_loaded_and_prechecked_files(
@@ -747,12 +752,11 @@ impl DuplicateFinder {
     }
 
     #[fun_time(message = "full_hashing", level = "debug")]
-    fn full_hashing(
-        &mut self,
-        stop_receiver: Option<&Receiver<()>>,
-        progress_sender: Option<&Sender<ProgressData>>,
-        pre_checked_map: BTreeMap<u64, Vec<DuplicateEntry>>,
-    ) -> Option<()> {
+    fn full_hashing(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&Sender<ProgressData>>, pre_checked_map: BTreeMap<u64, Vec<DuplicateEntry>>) -> bool {
+        if pre_checked_map.is_empty() {
+            return true;
+        }
+
         let (progress_thread_handle, progress_thread_run, _atomic_counter, _check_was_stopped) =
             prepare_thread_handler_common(progress_sender, CurrentStage::DuplicateCacheLoading, 0, self.get_test_type());
 
@@ -760,7 +764,7 @@ impl DuplicateFinder {
 
         send_info_and_wait_for_ending_all_threads(&progress_thread_run, progress_thread_handle);
         if check_if_stop_received(stop_receiver) {
-            return None;
+            return false;
         }
 
         let (progress_thread_handle, progress_thread_run, atomic_counter, check_was_stopped) = prepare_thread_handler_common(
@@ -818,7 +822,7 @@ impl DuplicateFinder {
             }
         }
 
-        Some(())
+        true
     }
 
     #[fun_time(message = "hash_reference_folders", level = "debug")]
@@ -877,13 +881,11 @@ impl DuplicateFinder {
         assert_eq!(self.get_params().check_method, CheckingMethod::Hash);
 
         let mut pre_checked_map: BTreeMap<u64, Vec<DuplicateEntry>> = Default::default();
-        let ret = self.prehashing(stop_receiver, progress_sender, &mut pre_checked_map);
-        if ret.is_none() {
+        if !self.prehashing(stop_receiver, progress_sender, &mut pre_checked_map) {
             return false;
         }
 
-        let ret = self.full_hashing(stop_receiver, progress_sender, pre_checked_map);
-        if ret.is_none() {
+        if !self.full_hashing(stop_receiver, progress_sender, pre_checked_map) {
             return false;
         }
 
@@ -977,9 +979,9 @@ impl DuplicateFinder {
 
 impl DebugPrint for DuplicateFinder {
     fn debug_print(&self) {
-        if !cfg!(debug_assertions) {
-            return;
-        }
+        // if !cfg!(debug_assertions) {
+        //     return;
+        // }
         println!("---------------DEBUG PRINT---------------");
         println!(
             "Number of duplicated files by size(in groups) - {} ({})",
@@ -1008,6 +1010,12 @@ impl DebugPrint for DuplicateFinder {
 
         println!("Files list size - {}", self.files_with_identical_size.len());
         println!("Hashed Files list size - {}", self.files_with_identical_hashes.len());
+        println!("Files with identical names - {}", self.files_with_identical_names.len());
+        println!("Files with identical size names - {}", self.files_with_identical_size_names.len());
+        println!("Files with identical names referenced - {}", self.files_with_identical_names_referenced.len());
+        println!("Files with identical size names referenced - {}", self.files_with_identical_size_names_referenced.len());
+        println!("Files with identical size referenced - {}", self.files_with_identical_size_referenced.len());
+        println!("Files with identical hashes referenced - {}", self.files_with_identical_hashes_referenced.len());
         println!("Checking Method - {:?}", self.get_params().check_method);
         self.debug_print_common();
         println!("-----------------------------------------");
@@ -1183,7 +1191,7 @@ impl PrintResults for DuplicateFinder {
                     for (size, vectors_vector) in self.files_with_identical_hashes_referenced.iter().rev() {
                         for (file_entry, vector) in vectors_vector {
                             writeln!(writer, "\n---- Size {} ({}) - {} files", format_size(*size, BINARY), size, vector.len())?;
-                            writeln!(writer, "Reference file - {:?}", file_entry.path)?;
+                            writeln!(writer, "Reference file - \"{}\"", file_entry.path.to_string_lossy())?;
                             for file_entry in vector {
                                 writeln!(writer, "\"{}\"", file_entry.path.to_string_lossy())?;
                             }
diff --git a/czkawka_core/src/lib.rs b/czkawka_core/src/lib.rs
index 5d4479ade..c4007e662 100644
--- a/czkawka_core/src/lib.rs
+++ b/czkawka_core/src/lib.rs
@@ -24,6 +24,7 @@ pub mod common_cache;
 pub mod common_dir_traversal;
 pub mod common_directory;
 pub mod common_extensions;
+pub mod common_image;
 pub mod common_items;
 pub mod common_messages;
 pub mod common_tool;
diff --git a/czkawka_core/src/same_music.rs b/czkawka_core/src/same_music.rs
index 599fc9ba5..ab5f24802 100644
--- a/czkawka_core/src/same_music.rs
+++ b/czkawka_core/src/same_music.rs
@@ -284,6 +284,10 @@ impl SameMusic {
 
     #[fun_time(message = "calculate_fingerprint", level = "debug")]
     fn calculate_fingerprint(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&Sender<ProgressData>>) -> bool {
+        if self.music_entries.is_empty() {
+            return true;
+        }
+
         // We only calculate fingerprints, for files with similar titles
         // This saves a lot of time, because we don't need to calculate and later compare fingerprints for files with different titles
 
@@ -360,6 +364,10 @@ impl SameMusic {
 
     #[fun_time(message = "read_tags", level = "debug")]
     fn read_tags(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&Sender<ProgressData>>) -> bool {
+        if self.music_to_check.is_empty() {
+            return true;
+        }
+
         let (progress_thread_handle, progress_thread_run, _atomic_counter, _check_was_stopped) =
             prepare_thread_handler_common(progress_sender, CurrentStage::SameMusicCacheLoadingTags, 0, self.get_test_type());
 
@@ -383,7 +391,7 @@ impl SameMusic {
                     check_was_stopped.store(true, Ordering::Relaxed);
                     return None;
                 }
-                if read_single_file_tag(&path, &mut music_entry) {
+                if read_single_file_tags(&path, &mut music_entry) {
                     Some(Some(music_entry))
                 } else {
                     Some(None)
@@ -529,6 +537,10 @@ impl SameMusic {
         let mut entries_grouped_by_title: BTreeMap<String, Vec<MusicEntry>> = BTreeMap::new();
         for entry in music_data {
             let simplified_track_title = get_simplified_name(&entry.track_title);
+            // TODO maybe add as option to check for empty titles?
+            if simplified_track_title.is_empty() {
+                continue;
+            }
             entries_grouped_by_title.entry(simplified_track_title).or_default().push(entry);
         }
         entries_grouped_by_title
@@ -543,7 +555,13 @@ impl SameMusic {
                 .filter_map(|(_title, entries)| {
                     let (base_files, files_to_compare) = self.split_fingerprints_to_base_and_files_to_compare(entries);
 
-                    if base_files.is_empty() || files_to_compare.is_empty() {
+                    // When there is 0 files in base files or files to compare there will be no comparison, so removing it from the list
+                    // Also when there is only one file in base files and files to compare and they are the same file, there will be no comparison
+
+                    if base_files.is_empty()
+                        || files_to_compare.is_empty()
+                        || (base_files.len() == 1 && files_to_compare.len() == 1 && (base_files[0].path == files_to_compare[0].path))
+                    {
                         return None;
                     }
 
@@ -628,6 +646,10 @@ impl SameMusic {
 
     #[fun_time(message = "check_for_duplicate_fingerprints", level = "debug")]
     fn check_for_duplicate_fingerprints(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&Sender<ProgressData>>) -> bool {
+        if self.music_entries.is_empty() {
+            return true;
+        }
+
         let grouped_files_to_check = self.split_fingerprints_to_check();
         let base_files_number = grouped_files_to_check.iter().map(|g| g.base_files.len()).sum::<usize>();
 
@@ -811,7 +833,7 @@ fn calc_fingerprint_helper(path: impl AsRef<Path>, config: &Configuration) -> an
     Ok(printer.fingerprint().to_vec())
 }
 
-fn read_single_file_tag(path: &str, music_entry: &mut MusicEntry) -> bool {
+fn read_single_file_tags(path: &str, music_entry: &mut MusicEntry) -> bool {
     let Ok(mut file) = File::open(path) else {
         return false;
     };
@@ -920,17 +942,7 @@ impl PrintResults for SameMusic {
             for vec_file_entry in &self.duplicated_music_entries {
                 writeln!(writer, "Found {} music files which have similar friends", vec_file_entry.len())?;
                 for file_entry in vec_file_entry {
-                    writeln!(
-                        writer,
-                        "TT: {}  -  TA: {}  -  Y: {}  -  L: {}  -  G: {}  -  B: {}  -  P: \"{}\"",
-                        file_entry.track_title,
-                        file_entry.track_artist,
-                        file_entry.year,
-                        file_entry.length,
-                        file_entry.genre,
-                        file_entry.bitrate,
-                        file_entry.path.to_string_lossy()
-                    )?;
+                    write_music_entry(writer, file_entry)?;
                 }
                 writeln!(writer)?;
             }
@@ -939,29 +951,9 @@ impl PrintResults for SameMusic {
             for (file_entry, vec_file_entry) in &self.duplicated_music_entries_referenced {
                 writeln!(writer, "Found {} music files which have similar friends", vec_file_entry.len())?;
                 writeln!(writer)?;
-                writeln!(
-                    writer,
-                    "TT: {}  -  TA: {}  -  Y: {}  -  L: {}  -  G: {}  -  B: {}  -  P: \"{}\"",
-                    file_entry.track_title,
-                    file_entry.track_artist,
-                    file_entry.year,
-                    file_entry.length,
-                    file_entry.genre,
-                    file_entry.bitrate,
-                    file_entry.path.to_string_lossy()
-                )?;
+                write_music_entry(writer, file_entry)?;
                 for file_entry in vec_file_entry {
-                    writeln!(
-                        writer,
-                        "TT: {}  -  TA: {}  -  Y: {}  -  L: {}  -  G: {}  -  B: {}  -  P: \"{}\"",
-                        file_entry.track_title,
-                        file_entry.track_artist,
-                        file_entry.year,
-                        file_entry.length,
-                        file_entry.genre,
-                        file_entry.bitrate,
-                        file_entry.path.to_string_lossy()
-                    )?;
+                    write_music_entry(writer, file_entry)?;
                 }
                 writeln!(writer)?;
             }
@@ -981,6 +973,20 @@ impl PrintResults for SameMusic {
     }
 }
 
+fn write_music_entry<T: Write>(writer: &mut T, file_entry: &MusicEntry) -> std::io::Result<()> {
+    writeln!(
+        writer,
+        "TT: {}  -  TA: {}  -  Y: {}  -  L: {}  -  G: {}  -  B: {}  -  P: \"{}\"",
+        file_entry.track_title,
+        file_entry.track_artist,
+        file_entry.year,
+        file_entry.length,
+        file_entry.genre,
+        file_entry.bitrate,
+        file_entry.path.to_string_lossy()
+    )
+}
+
 fn get_simplified_name(what: &str) -> String {
     let mut new_what = String::with_capacity(what.len());
     let mut tab_number = 0;
diff --git a/czkawka_core/src/similar_images.rs b/czkawka_core/src/similar_images.rs
index 6aeaa3c62..77c8a1143 100644
--- a/czkawka_core/src/similar_images.rs
+++ b/czkawka_core/src/similar_images.rs
@@ -9,20 +9,19 @@ use bk_tree::BKTree;
 use crossbeam_channel::{Receiver, Sender};
 use fun_time::fun_time;
 use humansize::{format_size, BINARY};
-use image::{DynamicImage, GenericImageView};
+use image::GenericImageView;
 use image_hasher::{FilterType, HashAlg, HasherConfig};
 use log::debug;
 use rayon::prelude::*;
 use serde::{Deserialize, Serialize};
 
-#[cfg(feature = "heif")]
-use crate::common::get_dynamic_image_from_heic;
 use crate::common::{
-    check_if_stop_received, create_crash_message, delete_files_custom, get_dynamic_image_from_raw_image, prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads,
-    HEIC_EXTENSIONS, IMAGE_RS_SIMILAR_IMAGES_EXTENSIONS, RAW_IMAGE_EXTENSIONS,
+    check_if_stop_received, delete_files_custom, prepare_thread_handler_common, send_info_and_wait_for_ending_all_threads, HEIC_EXTENSIONS, IMAGE_RS_SIMILAR_IMAGES_EXTENSIONS,
+    JXL_IMAGE_EXTENSIONS, RAW_IMAGE_EXTENSIONS,
 };
 use crate::common_cache::{extract_loaded_cache, get_similar_images_cache_file, load_cache_from_file_generalized_by_path, save_cache_to_file_generalized};
 use crate::common_dir_traversal::{inode, take_1_per_inode, DirTraversalBuilder, DirTraversalResult, FileEntry, ToolType};
+use crate::common_image::get_dynamic_image_from_path;
 use crate::common_tool::{CommonData, CommonToolData, DeleteMethod};
 use crate::common_traits::{DebugPrint, PrintResults, ResultEntry};
 use crate::flc;
@@ -46,7 +45,6 @@ pub struct ImagesEntry {
     pub modified_date: u64,
     pub hash: ImHash,
     pub similarity: u32,
-    pub image_type: ImageType,
 }
 
 impl ResultEntry for ImagesEntry {
@@ -71,19 +69,10 @@ impl FileEntry {
             height: 0,
             hash: Vec::new(),
             similarity: 0,
-            image_type: ImageType::Unknown,
         }
     }
 }
 
-#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
-pub enum ImageType {
-    Normal,
-    Raw,
-    Heic,
-    Unknown,
-}
-
 #[derive(Clone, Debug, Copy)]
 pub enum SimilarityPreset {
     Original,
@@ -183,25 +172,22 @@ impl SimilarImages {
         self.debug_print();
     }
 
-    // #[fun_time(message = "check_for_similar_images", level = "debug")]
+    #[fun_time(message = "check_for_similar_images", level = "debug")]
     fn check_for_similar_images(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&Sender<ProgressData>>) -> bool {
         if cfg!(feature = "heif") {
             self.common_data
                 .extensions
-                .set_and_validate_allowed_extensions(&[IMAGE_RS_SIMILAR_IMAGES_EXTENSIONS, RAW_IMAGE_EXTENSIONS, HEIC_EXTENSIONS].concat());
+                .set_and_validate_allowed_extensions(&[IMAGE_RS_SIMILAR_IMAGES_EXTENSIONS, RAW_IMAGE_EXTENSIONS, JXL_IMAGE_EXTENSIONS, HEIC_EXTENSIONS].concat());
         } else {
             self.common_data
                 .extensions
-                .set_and_validate_allowed_extensions(&[IMAGE_RS_SIMILAR_IMAGES_EXTENSIONS, RAW_IMAGE_EXTENSIONS].concat());
+                .set_and_validate_allowed_extensions(&[IMAGE_RS_SIMILAR_IMAGES_EXTENSIONS, RAW_IMAGE_EXTENSIONS, JXL_IMAGE_EXTENSIONS].concat());
         }
+
         if !self.common_data.extensions.set_any_extensions() {
             return true;
         }
 
-        let normal_image_extensions = IMAGE_RS_SIMILAR_IMAGES_EXTENSIONS.iter().collect::<HashSet<_>>();
-        let raw_image_extensions = RAW_IMAGE_EXTENSIONS.iter().collect::<HashSet<_>>();
-        let heic_extensions = HEIC_EXTENSIONS.iter().collect::<HashSet<_>>();
-
         let result = DirTraversalBuilder::new()
             .group_by(inode)
             .stop_receiver(stop_receiver)
@@ -217,17 +203,8 @@ impl SimilarImages {
                     .flat_map(if self.get_params().ignore_hard_links { |(_, fes)| fes } else { take_1_per_inode })
                     .map(|fe| {
                         let fe_str = fe.path.to_string_lossy().to_string();
-                        let extension_lowercase = fe.path.extension().unwrap_or_default().to_string_lossy().to_lowercase();
-                        let mut image_entry = fe.into_images_entry();
-                        if normal_image_extensions.contains(&extension_lowercase.as_str()) {
-                            image_entry.image_type = ImageType::Normal;
-                        } else if raw_image_extensions.contains(&extension_lowercase.as_str()) {
-                            image_entry.image_type = ImageType::Raw;
-                        } else if heic_extensions.contains(&extension_lowercase.as_str()) {
-                            image_entry.image_type = ImageType::Heic;
-                        } else {
-                            panic!("Unrecognized extension")
-                        }
+                        let image_entry = fe.into_images_entry();
+
                         (fe_str, image_entry)
                     })
                     .collect();
@@ -286,6 +263,10 @@ impl SimilarImages {
 
     #[fun_time(message = "hash_images", level = "debug")]
     fn hash_images(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&Sender<ProgressData>>) -> bool {
+        if self.images_to_check.is_empty() {
+            return true;
+        }
+
         let (loaded_hash_map, records_already_cached, non_cached_files_to_check) = self.hash_images_load_cache();
 
         let (progress_thread_handle, progress_thread_run, atomic_counter, check_was_stopped) = prepare_thread_handler_common(
@@ -295,12 +276,6 @@ impl SimilarImages {
             self.get_test_type(),
         );
 
-        // Throw out images with not proper type - TODO why this happens, only broken cache?
-        let non_cached_files_to_check = non_cached_files_to_check
-            .into_iter()
-            .filter(|(_, file_entry)| file_entry.image_type != ImageType::Unknown)
-            .collect::<BTreeMap<_, _>>();
-
         debug!("hash_images - start hashing images");
         let (mut vec_file_entry, errors): (Vec<ImagesEntry>, Vec<String>) = non_cached_files_to_check
             .into_par_iter()
@@ -370,38 +345,7 @@ impl SimilarImages {
     }
 
     fn collect_image_file_entry(&self, file_entry: &mut ImagesEntry) -> Result<(), String> {
-        let img;
-
-        if file_entry.image_type == ImageType::Heic {
-            #[cfg(feature = "heif")]
-            {
-                img = match get_dynamic_image_from_heic(&file_entry.path.to_string_lossy()) {
-                    Ok(t) => t,
-                    Err(e) => {
-                        return Err(format!("Cannot open HEIC file \"{}\": {}", file_entry.path.to_string_lossy(), e));
-                    }
-                };
-            }
-            #[cfg(not(feature = "heif"))]
-            {
-                img = Self::get_normal_heif_image(file_entry)?;
-            }
-        } else {
-            match file_entry.image_type {
-                ImageType::Normal | ImageType::Heic => {
-                    img = Self::get_normal_heif_image(file_entry)?;
-                }
-                ImageType::Raw => {
-                    img = match get_dynamic_image_from_raw_image(&file_entry.path) {
-                        Ok(t) => t,
-                        Err(e) => return Err(format!("Cannot open RAW file \"{}\": {}", file_entry.path.to_string_lossy(), e)),
-                    };
-                }
-                _ => {
-                    unreachable!();
-                }
-            }
-        }
+        let img = get_dynamic_image_from_path(&file_entry.path.to_string_lossy())?;
 
         let dimensions = img.dimensions();
 
@@ -420,19 +364,6 @@ impl SimilarImages {
         Ok(())
     }
 
-    fn get_normal_heif_image(file_entry: &ImagesEntry) -> Result<DynamicImage, String> {
-        if let Ok(image_result) = panic::catch_unwind(|| image::open(&file_entry.path)) {
-            match image_result {
-                Ok(image) => Ok(image),
-                Err(e) => Err(format!("Cannot open image file \"{}\": {}", file_entry.path.to_string_lossy(), e)),
-            }
-        } else {
-            let message = create_crash_message("Image-rs", &file_entry.path.to_string_lossy(), "https://github.com/image-rs/image/issues");
-            println!("{message}");
-            Err(message)
-        }
-    }
-
     // Split hashes at 2 parts, base hashes and hashes to compare, 3 argument is set of hashes with multiple images
     #[fun_time(message = "split_hashes", level = "debug")]
     fn split_hashes(&mut self, all_hashed_images: &HashMap<ImHash, Vec<ImagesEntry>>) -> (Vec<ImHash>, HashSet<ImHash>) {
@@ -1087,12 +1018,13 @@ mod tests {
     use std::collections::HashMap;
     use std::path::PathBuf;
 
-    use crate::common_tool::CommonData;
-    use crate::similar_images::{Hamming, ImHash, ImageType, ImagesEntry, SimilarImages, SimilarImagesParameters};
     use bk_tree::BKTree;
     use image::imageops::FilterType;
     use image_hasher::HashAlg;
 
+    use crate::common_tool::CommonData;
+    use crate::similar_images::{Hamming, ImHash, ImagesEntry, SimilarImages, SimilarImagesParameters};
+
     fn get_default_parameters() -> SimilarImagesParameters {
         SimilarImagesParameters {
             hash_alg: HashAlg::Gradient,
@@ -1463,7 +1395,6 @@ mod tests {
             modified_date: 0,
             hash,
             similarity: 0,
-            image_type: ImageType::Normal,
         }
     }
 }
diff --git a/czkawka_core/src/similar_videos.rs b/czkawka_core/src/similar_videos.rs
index e366ecf66..c8773f696 100644
--- a/czkawka_core/src/similar_videos.rs
+++ b/czkawka_core/src/similar_videos.rs
@@ -140,7 +140,7 @@ impl SimilarVideos {
         self.debug_print();
     }
 
-    // #[fun_time(message = "check_for_similar_videos", level = "debug")]
+    #[fun_time(message = "check_for_similar_videos", level = "debug")]
     fn check_for_similar_videos(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&Sender<ProgressData>>) -> bool {
         self.common_data.extensions.set_and_validate_allowed_extensions(VIDEO_FILES_EXTENSIONS);
         if !self.common_data.extensions.set_any_extensions() {
@@ -198,6 +198,10 @@ impl SimilarVideos {
 
     #[fun_time(message = "sort_videos", level = "debug")]
     fn sort_videos(&mut self, stop_receiver: Option<&Receiver<()>>, progress_sender: Option<&Sender<ProgressData>>) -> bool {
+        if self.videos_to_check.is_empty() {
+            return true;
+        }
+
         let (loaded_hash_map, records_already_cached, non_cached_files_to_check) = self.load_cache_at_start();
 
         let (progress_thread_handle, progress_thread_run, atomic_counter, check_was_stopped) = prepare_thread_handler_common(
diff --git a/czkawka_gui/Cargo.toml b/czkawka_gui/Cargo.toml
index db0262357..6ffce9a87 100644
--- a/czkawka_gui/Cargo.toml
+++ b/czkawka_gui/Cargo.toml
@@ -30,7 +30,7 @@ open = "5.3"
 image = "0.25"
 
 # To be able to use custom select
-regex = "1.10"
+regex = "1.11"
 
 # To get image_hasher types
 image_hasher = "2.0"
@@ -45,7 +45,7 @@ fs_extra = "1.3"
 i18n-embed = { version = "0.15", features = ["fluent-system", "desktop-requester"] }
 i18n-embed-fl = "0.9"
 rust-embed = { version = "8.5", features = ["debug-embed"] }
-once_cell = "1.19"
+once_cell = "1.20"
 
 log = "0.4.22"
 handsome_logger = "0.8"
@@ -61,3 +61,4 @@ winapi = { version = "0.3.9", features = ["combaseapi", "objbase", "shobjidl_cor
 default = []
 heif = ["czkawka_core/heif"]
 libraw = ["czkawka_core/libraw"]
+libavif = ["czkawka_core/libavif"]
diff --git a/czkawka_gui/README.md b/czkawka_gui/README.md
index 5db5f1487..90e8d486c 100644
--- a/czkawka_gui/README.md
+++ b/czkawka_gui/README.md
@@ -10,6 +10,8 @@ Requirements depend on your platform.
 
 Prebuilt binaries are available here - https://github.com/qarmin/czkawka/releases/
 
+Additional features like heif, libraw, libavif require additional libraries to be installed, and may increase
+
 ### Linux
 
 #### Prebuild binaries
@@ -27,9 +29,21 @@ none - all needed libraries are bundled - https://flathub.org/apps/com.github.qa
 
 ### Mac
 
+### Homebrew
+
+Czkawka gui is available in homebrew - https://formulae.brew.sh/formula/czkawka and can be installed via
+
 ```
+brew install czkawka
+```
+
+### Manual installation requirements
+
+```
+
 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
 brew install gtk4 adwaita-icon-theme ffmpeg librsvg libheif libraw
+
 ```
 
 ### Windows
@@ -41,7 +55,9 @@ You can also install the app via msys2 (webp and heif should work here) - https:
 package - https://packages.msys2.org/base/mingw-w64-czkawka)
 
 ```
+
 pacman -S mingw-w64-x86_64-czkawka-gui
+
 ```
 
 and you can create a shortcut to `C:\msys64\mingw64\bin\czkawka_gui.exe`
@@ -61,10 +77,11 @@ lot build and runtime dependencies.
 ### Linux (Ubuntu, but on other OS should work similar)
 
 ```shell
-sudo apt install libgtk-4-dev libheif-dev libraw-dev -y
+sudo apt install libgtk-4-dev -y # Base
+sudo apt install libgtk-4-dev libheif-dev libraw-dev libavif-dev libdav1d-dev -y # With features
 cargo run --release --bin czkawka_gui
-# Or with support for heif and libraw
-cargo run --release --bin czkawka_gui --features "heif,libraw"
+# Or with support for heif, libraw, libavif
+cargo run --release --bin czkawka_gui --features "heif,libraw,libavif"
 ```
 
 ### Mac
@@ -74,8 +91,8 @@ cargo run --release --bin czkawka_gui --features "heif,libraw"
 brew install rustup gtk4 adwaita-icon-theme ffmpeg librsvg libheif libraw pkg-config
 rustup-init
 cargo run --release --bin czkawka_gui
-# Or with support for heif and libraw
-cargo run --release --bin czkawka_gui --features "heif,libraw"
+# Or with support for heif, libraw, libavif
+cargo run --release --bin czkawka_gui --features "heif,libraw,libavif"
 ```
 
 ### Windows
@@ -91,7 +108,7 @@ purposes - https://github.com/msys2/MINGW-packages/blob/master/mingw-w64-czkawka
 Not all available features and/or components implemented here, this is the list of limitations:
 
 - Snap versions does not allow to use the similar videos feature
-- Windows version does not support heif and webp files with prebuilt binaries
+- Windows version does not support heif and webp files with prebuilt binaries(msys2 version support them)
 - Prebuilt binaries for mac arm do not exist
 - On Windows, text may appear very small on high resolution displays, a solution is to manually change DPI scaling for
   this app, see :
diff --git a/czkawka_gui/i18n/en/czkawka_gui.ftl b/czkawka_gui/i18n/en/czkawka_gui.ftl
index 6d6ec9576..121fe51f0 100644
--- a/czkawka_gui/i18n/en/czkawka_gui.ftl
+++ b/czkawka_gui/i18n/en/czkawka_gui.ftl
@@ -21,6 +21,12 @@ music_checking_by_content = Content
 same_music_seconds_label = Minimal fragment second duration
 same_music_similarity_label = Maximum difference
 
+music_compare_only_in_title_group = Compare only in title
+music_compare_only_in_title_group_tooltip =
+        When enabled, files are grouped by title and then compared to each other.
+
+        With 10000 files, instead almost 100 million comparisons usually there will be around 20000 comparisons.
+
 same_music_tooltip =
         Searching for similar music files by its content can be configured by setting:
 
@@ -332,6 +338,14 @@ header_about_button_tooltip = Opens dialog with info about app.
 settings_number_of_threads = Number of used threads
 settings_number_of_threads_tooltip = Number of used threads, 0 means that all available threads will be used.
 
+settings_use_rust_preview = Use external libraries instead gtk to load previews
+settings_use_rust_preview_tooltip =
+        Using gtk previews will sometimes be faster and support more formats, but sometimes this could be exactly the opposite.
+
+        If you have problems with loading previews, you may can to try to change this setting.
+
+        On non-linux systems, it is recommended to use this option, because gtk-pixbuf are not always available there so disabling this option will not load previews of some images.
+
 settings_label_restart = You need to restart app to apply settings!
 
 settings_ignore_other_filesystems = Ignore other filesystems (only Linux)
diff --git a/czkawka_gui/src/compute_results.rs b/czkawka_gui/src/compute_results.rs
index 4ff2205aa..ae60b5246 100644
--- a/czkawka_gui/src/compute_results.rs
+++ b/czkawka_gui/src/compute_results.rs
@@ -5,12 +5,6 @@ use std::time::Duration;
 
 use chrono::DateTime;
 use crossbeam_channel::Receiver;
-use fun_time::fun_time;
-use gtk4::prelude::*;
-use gtk4::{Entry, ListStore, TextView, TreeView, Widget};
-use humansize::{format_size, BINARY};
-use rayon::prelude::*;
-
 use czkawka_core::bad_extensions::BadExtensions;
 use czkawka_core::big_file::BigFile;
 use czkawka_core::broken_files::BrokenFiles;
@@ -27,6 +21,11 @@ use czkawka_core::similar_images;
 use czkawka_core::similar_images::{ImagesEntry, SimilarImages};
 use czkawka_core::similar_videos::SimilarVideos;
 use czkawka_core::temporary::Temporary;
+use fun_time::fun_time;
+use gtk4::prelude::*;
+use gtk4::{Entry, ListStore, TextView, TreeView, Widget};
+use humansize::{format_size, BINARY};
+use rayon::prelude::*;
 
 use crate::flg;
 use crate::gui_structs::gui_data::GuiData;
diff --git a/czkawka_gui/src/connect_things/connect_button_compare.rs b/czkawka_gui/src/connect_things/connect_button_compare.rs
index d1c8fb976..7985574d7 100644
--- a/czkawka_gui/src/connect_things/connect_button_compare.rs
+++ b/czkawka_gui/src/connect_things/connect_button_compare.rs
@@ -1,15 +1,12 @@
 use std::cell::RefCell;
 use std::rc::Rc;
 
+use czkawka_core::common_image::get_dynamic_image_from_path;
 use gdk4::gdk_pixbuf::{InterpType, Pixbuf};
 use gtk4::prelude::*;
 use gtk4::{Align, CheckButton, Image, ListStore, Orientation, ScrolledWindow, TreeIter, TreeModel, TreePath, TreeSelection, Widget};
 use image::DynamicImage;
 
-#[cfg(feature = "heif")]
-use czkawka_core::common::get_dynamic_image_from_heic;
-use czkawka_core::common::HEIC_EXTENSIONS;
-
 use crate::flg;
 use crate::gui_structs::gui_data::GuiData;
 use crate::help_functions::{
@@ -44,6 +41,8 @@ pub fn connect_button_compare(gui_data: &GuiData) {
     let image_compare_left = gui_data.compare_images.image_compare_left.clone();
     let image_compare_right = gui_data.compare_images.image_compare_right.clone();
 
+    let check_button_settings_use_rust_preview = gui_data.settings.check_button_settings_use_rust_preview.clone();
+
     window_compare.set_default_size(700, 700);
 
     button_compare.connect_clicked(move |_| {
@@ -81,6 +80,7 @@ pub fn connect_button_compare(gui_data: &GuiData) {
             &shared_using_for_preview,
             &button_go_previous_compare_group,
             &button_go_next_compare_group,
+            &check_button_settings_use_rust_preview,
         );
 
         window_compare.show();
@@ -125,6 +125,8 @@ pub fn connect_button_compare(gui_data: &GuiData) {
     let image_compare_left = gui_data.compare_images.image_compare_left.clone();
     let image_compare_right = gui_data.compare_images.image_compare_right.clone();
 
+    let check_button_settings_use_rust_preview = gui_data.settings.check_button_settings_use_rust_preview.clone();
+
     button_go_previous_compare_group.connect_clicked(move |button_go_previous_compare_group| {
         let nb_number = notebook_main.current_page().expect("Current page not set");
         let tree_view = &main_tree_views[nb_number as usize];
@@ -160,6 +162,7 @@ pub fn connect_button_compare(gui_data: &GuiData) {
             &shared_using_for_preview,
             button_go_previous_compare_group,
             &button_go_next_compare_group,
+            &check_button_settings_use_rust_preview,
         );
     });
 
@@ -182,6 +185,8 @@ pub fn connect_button_compare(gui_data: &GuiData) {
     let image_compare_left = gui_data.compare_images.image_compare_left.clone();
     let image_compare_right = gui_data.compare_images.image_compare_right.clone();
 
+    let check_button_settings_use_rust_preview = gui_data.settings.check_button_settings_use_rust_preview.clone();
+
     button_go_next_compare_group.connect_clicked(move |button_go_next_compare_group| {
         let nb_number = notebook_main.current_page().expect("Current page not set");
         let tree_view = &main_tree_views[nb_number as usize];
@@ -217,6 +222,7 @@ pub fn connect_button_compare(gui_data: &GuiData) {
             &shared_using_for_preview,
             &button_go_previous_compare_group,
             button_go_next_compare_group,
+            &check_button_settings_use_rust_preview,
         );
     });
 
@@ -299,6 +305,7 @@ fn populate_groups_at_start(
     shared_using_for_preview: &Rc<RefCell<(Option<TreePath>, Option<TreePath>)>>,
     button_go_previous_compare_group: &gtk4::Button,
     button_go_next_compare_group: &gtk4::Button,
+    check_button_settings_use_rust_preview: &CheckButton,
 ) {
     if current_group == 1 {
         button_go_previous_compare_group.set_sensitive(false);
@@ -320,7 +327,7 @@ fn populate_groups_at_start(
     );
     *shared_current_path.borrow_mut() = Some(tree_path);
 
-    let cache_all_images = generate_cache_for_results(all_vec);
+    let cache_all_images = generate_cache_for_results(all_vec, check_button_settings_use_rust_preview.is_active());
 
     // This is safe, because cache have at least 2 results
     image_compare_left.set_paintable(cache_all_images[0].2.paintable().as_ref());
@@ -379,7 +386,7 @@ fn populate_groups_at_start(
     check_button_right_preview_text.set_active(is_active);
 }
 
-fn generate_cache_for_results(vector_with_path: Vec<(String, String, TreePath)>) -> Vec<(String, String, Image, Image, TreePath)> {
+fn generate_cache_for_results(vector_with_path: Vec<(String, String, TreePath)>, use_rust_loader: bool) -> Vec<(String, String, Image, Image, TreePath)> {
     // TODO use here threads,
     // For now threads cannot be used because Image and TreeIter cannot be used in threads
     let mut cache_all_images = Vec::new();
@@ -388,36 +395,23 @@ fn generate_cache_for_results(vector_with_path: Vec<(String, String, TreePath)>)
         let big_img = Image::new();
 
         let mut pixbuf = get_pixbuf_from_dynamic_image(&DynamicImage::new_rgb8(1, 1)).expect("Failed to create pixbuf");
-        let extension_lowercase = full_path.split('.').last().map(str::to_lowercase);
-        let is_heic = match extension_lowercase {
-            Some(extension) => HEIC_EXTENSIONS.iter().any(|e| e == &extension),
-            None => false,
-        };
-
-        if is_heic {
-            #[allow(clippy::never_loop)]
-            'czystka: loop {
-                #[cfg(feature = "heif")]
-                if is_heic {
-                    match get_dynamic_image_from_heic(&full_path) {
+
+        if use_rust_loader {
+            match get_dynamic_image_from_path(&full_path) {
+                Ok(t) => {
+                    match get_pixbuf_from_dynamic_image(&t) {
                         Ok(t) => {
-                            match get_pixbuf_from_dynamic_image(&t) {
-                                Ok(t) => {
-                                    pixbuf = t;
-                                }
-                                Err(e) => {
-                                    println!("Failed to open image {full_path}, reason {e}");
-                                }
-                            };
+                            pixbuf = t;
                         }
                         Err(e) => {
                             println!("Failed to open image {full_path}, reason {e}");
                         }
                     };
-                    break 'czystka;
                 }
-                break 'czystka;
-            }
+                Err(e) => {
+                    println!("Failed to open image {full_path}, reason {e}");
+                }
+            };
         } else {
             match Pixbuf::from_file(&full_path) {
                 Ok(t) => {
diff --git a/czkawka_gui/src/connect_things/connect_button_hardlink.rs b/czkawka_gui/src/connect_things/connect_button_hardlink.rs
index 12007e5ad..2cba3af66 100644
--- a/czkawka_gui/src/connect_things/connect_button_hardlink.rs
+++ b/czkawka_gui/src/connect_things/connect_button_hardlink.rs
@@ -1,11 +1,10 @@
 use std::fs;
 use std::path::PathBuf;
 
+use czkawka_core::duplicate::make_hard_link;
 use gtk4::prelude::*;
 use gtk4::{Align, CheckButton, Dialog, Orientation, ResponseType, TextView, TreeIter, TreePath};
 
-use czkawka_core::duplicate::make_hard_link;
-
 use crate::flg;
 use crate::gui_structs::gui_data::GuiData;
 use crate::help_functions::*;
diff --git a/czkawka_gui/src/connect_things/connect_button_save.rs b/czkawka_gui/src/connect_things/connect_button_save.rs
index 7fbc7b961..552d84b0a 100644
--- a/czkawka_gui/src/connect_things/connect_button_save.rs
+++ b/czkawka_gui/src/connect_things/connect_button_save.rs
@@ -3,11 +3,10 @@ use std::collections::HashMap;
 use std::env;
 use std::rc::Rc;
 
+use czkawka_core::common_traits::PrintResults;
 use gtk4::prelude::*;
 use gtk4::{Button, Entry};
 
-use czkawka_core::common_traits::PrintResults;
-
 use crate::flg;
 use crate::gui_structs::gui_data::GuiData;
 use crate::help_functions::BottomButtonsEnum;
diff --git a/czkawka_gui/src/connect_things/connect_button_search.rs b/czkawka_gui/src/connect_things/connect_button_search.rs
index ef30c445f..3ff8831f4 100644
--- a/czkawka_gui/src/connect_things/connect_button_search.rs
+++ b/czkawka_gui/src/connect_things/connect_button_search.rs
@@ -4,10 +4,6 @@ use std::sync::Arc;
 use std::thread;
 
 use crossbeam_channel::{Receiver, Sender};
-use fun_time::fun_time;
-use gtk4::prelude::*;
-use gtk4::Grid;
-
 use czkawka_core::bad_extensions::{BadExtensions, BadExtensionsParameters};
 use czkawka_core::big_file::{BigFile, BigFileParameters};
 use czkawka_core::broken_files::{BrokenFiles, BrokenFilesParameters, CheckedTypes};
@@ -23,6 +19,9 @@ use czkawka_core::same_music::{MusicSimilarity, SameMusic, SameMusicParameters};
 use czkawka_core::similar_images::{SimilarImages, SimilarImagesParameters};
 use czkawka_core::similar_videos::{SimilarVideos, SimilarVideosParameters};
 use czkawka_core::temporary::Temporary;
+use fun_time::fun_time;
+use gtk4::prelude::*;
+use gtk4::Grid;
 
 use crate::gui_structs::gui_data::GuiData;
 use crate::help_combo_box::{
diff --git a/czkawka_gui/src/connect_things/connect_duplicate_buttons.rs b/czkawka_gui/src/connect_things/connect_duplicate_buttons.rs
index 4b88d15a1..f5e7775ac 100644
--- a/czkawka_gui/src/connect_things/connect_duplicate_buttons.rs
+++ b/czkawka_gui/src/connect_things/connect_duplicate_buttons.rs
@@ -1,6 +1,5 @@
-use gtk4::prelude::*;
-
 use czkawka_core::common_dir_traversal::CheckingMethod;
+use gtk4::prelude::*;
 
 use crate::gui_structs::gui_data::GuiData;
 use crate::help_combo_box::DUPLICATES_CHECK_METHOD_COMBO_BOX;
diff --git a/czkawka_gui/src/connect_things/connect_popovers_select.rs b/czkawka_gui/src/connect_things/connect_popovers_select.rs
index fd173d115..26f225ccd 100644
--- a/czkawka_gui/src/connect_things/connect_popovers_select.rs
+++ b/czkawka_gui/src/connect_things/connect_popovers_select.rs
@@ -1,10 +1,9 @@
+use czkawka_core::common::regex_check;
+use czkawka_core::common_items::new_excluded_item;
 use gtk4::prelude::*;
 use gtk4::{ResponseType, TreeIter, Window};
 use regex::Regex;
 
-use czkawka_core::common::regex_check;
-use czkawka_core::common_items::new_excluded_item;
-
 use crate::flg;
 use crate::gui_structs::gui_data::GuiData;
 use crate::help_functions::*;
diff --git a/czkawka_gui/src/connect_things/connect_progress_window.rs b/czkawka_gui/src/connect_things/connect_progress_window.rs
index 474e10274..63a0d99e1 100644
--- a/czkawka_gui/src/connect_things/connect_progress_window.rs
+++ b/czkawka_gui/src/connect_things/connect_progress_window.rs
@@ -4,6 +4,8 @@ use std::rc::Rc;
 use std::time::Duration;
 
 use crossbeam_channel::Receiver;
+use czkawka_core::common_dir_traversal::ToolType;
+use czkawka_core::progress_data::{CurrentStage, ProgressData};
 use glib::MainContext;
 use gtk4::prelude::*;
 use gtk4::ProgressBar;
@@ -13,8 +15,6 @@ use crate::gui_structs::gui_data::GuiData;
 use crate::localizer_core::generate_translation_hashmap;
 use crate::taskbar_progress::tbp_flags::TBPF_INDETERMINATE;
 use crate::taskbar_progress::TaskbarProgress;
-use czkawka_core::common_dir_traversal::ToolType;
-use czkawka_core::progress_data::{CurrentStage, ProgressData};
 
 #[allow(clippy::too_many_arguments)]
 pub fn connect_progress_window(gui_data: &GuiData, progress_receiver: Receiver<ProgressData>) {
diff --git a/czkawka_gui/src/connect_things/connect_same_music_mode_changed.rs b/czkawka_gui/src/connect_things/connect_same_music_mode_changed.rs
index 2d8747aff..40ba7326e 100644
--- a/czkawka_gui/src/connect_things/connect_same_music_mode_changed.rs
+++ b/czkawka_gui/src/connect_things/connect_same_music_mode_changed.rs
@@ -1,8 +1,7 @@
+use czkawka_core::common_dir_traversal::CheckingMethod;
 use gtk4::prelude::*;
 use gtk4::{CheckButton, Widget};
 
-use czkawka_core::common_dir_traversal::CheckingMethod;
-
 use crate::gui_structs::gui_data::GuiData;
 use crate::help_combo_box::AUDIO_TYPE_CHECK_METHOD_COMBO_BOX;
 use crate::help_functions::scale_set_min_max_values;
diff --git a/czkawka_gui/src/connect_things/connect_selection_of_directories.rs b/czkawka_gui/src/connect_things/connect_selection_of_directories.rs
index 8bc3b1ebf..e710848d7 100644
--- a/czkawka_gui/src/connect_things/connect_selection_of_directories.rs
+++ b/czkawka_gui/src/connect_things/connect_selection_of_directories.rs
@@ -1,13 +1,12 @@
 use std::collections::HashSet;
 use std::path::PathBuf;
 
+#[cfg(target_family = "windows")]
+use czkawka_core::common::normalize_windows_path;
 use gdk4::{DragAction, FileList};
 use gtk4::prelude::*;
 use gtk4::{DropTarget, FileChooserNative, Notebook, Orientation, ResponseType, TreeView, Window};
 
-#[cfg(target_family = "windows")]
-use czkawka_core::common::normalize_windows_path;
-
 use crate::flg;
 use crate::gui_structs::gui_data::GuiData;
 use crate::help_functions::{check_if_value_is_in_list_store, get_list_store, ColumnsExcludedDirectory, ColumnsIncludedDirectory};
diff --git a/czkawka_gui/src/connect_things/connect_settings.rs b/czkawka_gui/src/connect_things/connect_settings.rs
index e6e361c32..4c511cdbd 100644
--- a/czkawka_gui/src/connect_things/connect_settings.rs
+++ b/czkawka_gui/src/connect_things/connect_settings.rs
@@ -1,18 +1,17 @@
 use std::collections::BTreeMap;
 use std::default::Default;
 
-use directories_next::ProjectDirs;
-use gtk4::prelude::*;
-use gtk4::{Label, ResponseType, Window};
-use image::imageops::FilterType;
-use image_hasher::HashAlg;
-
 use czkawka_core::common_cache::{
     get_duplicate_cache_file, get_similar_images_cache_file, get_similar_videos_cache_file, load_cache_from_file_generalized_by_path, load_cache_from_file_generalized_by_size,
     save_cache_to_file_generalized,
 };
 use czkawka_core::common_messages::Messages;
 use czkawka_core::duplicate::HashType;
+use directories_next::ProjectDirs;
+use gtk4::prelude::*;
+use gtk4::{Label, ResponseType, Window};
+use image::imageops::FilterType;
+use image_hasher::HashAlg;
 
 use crate::flg;
 use crate::gui_structs::gui_data::GuiData;
diff --git a/czkawka_gui/src/connect_things/connect_similar_image_size_change.rs b/czkawka_gui/src/connect_things/connect_similar_image_size_change.rs
index a5c209b2d..64258ea38 100644
--- a/czkawka_gui/src/connect_things/connect_similar_image_size_change.rs
+++ b/czkawka_gui/src/connect_things/connect_similar_image_size_change.rs
@@ -1,6 +1,5 @@
-use gtk4::prelude::*;
-
 use czkawka_core::similar_images::{get_string_from_similarity, SIMILAR_VALUES};
+use gtk4::prelude::*;
 
 use crate::gui_structs::gui_data::GuiData;
 use crate::help_combo_box::IMAGES_HASH_SIZE_COMBO_BOX;
diff --git a/czkawka_gui/src/gui_structs/gui_bottom_buttons.rs b/czkawka_gui/src/gui_structs/gui_bottom_buttons.rs
index 7389985d5..f391afe74 100644
--- a/czkawka_gui/src/gui_structs/gui_bottom_buttons.rs
+++ b/czkawka_gui/src/gui_structs/gui_bottom_buttons.rs
@@ -147,11 +147,12 @@ impl GuiBottomButtons {
 
 #[cfg(target_family = "windows")]
 fn test_hardlinks() -> bool {
-    use directories_next::ProjectDirs;
     use std::fs;
     use std::io::Write;
     use std::path::Path;
 
+    use directories_next::ProjectDirs;
+
     let mut hardlinked = false;
 
     if let Some(proj_dirs) = ProjectDirs::from("pl", "Qarmin", "Czkawka") {
diff --git a/czkawka_gui/src/gui_structs/gui_data.rs b/czkawka_gui/src/gui_structs/gui_data.rs
index 64d5966db..90a553e89 100644
--- a/czkawka_gui/src/gui_structs/gui_data.rs
+++ b/czkawka_gui/src/gui_structs/gui_data.rs
@@ -4,10 +4,6 @@ use std::io::BufReader;
 use std::rc::Rc;
 
 use crossbeam_channel::bounded;
-use gdk4::gdk_pixbuf::Pixbuf;
-use gtk4::prelude::*;
-use gtk4::{Builder, FileChooserNative};
-
 use czkawka_core::bad_extensions::BadExtensions;
 use czkawka_core::big_file::BigFile;
 use czkawka_core::broken_files::BrokenFiles;
@@ -19,6 +15,9 @@ use czkawka_core::same_music::SameMusic;
 use czkawka_core::similar_images::SimilarImages;
 use czkawka_core::similar_videos::SimilarVideos;
 use czkawka_core::temporary::Temporary;
+use gdk4::gdk_pixbuf::Pixbuf;
+use gtk4::prelude::*;
+use gtk4::{Builder, FileChooserNative};
 
 use crate::flg;
 use crate::gui_structs::gui_about::GuiAbout;
diff --git a/czkawka_gui/src/gui_structs/gui_main_notebook.rs b/czkawka_gui/src/gui_structs/gui_main_notebook.rs
index 89bdea1e4..2b89637ba 100644
--- a/czkawka_gui/src/gui_structs/gui_main_notebook.rs
+++ b/czkawka_gui/src/gui_structs/gui_main_notebook.rs
@@ -1,10 +1,9 @@
-use gtk4::prelude::*;
-use gtk4::{Builder, CheckButton, ComboBoxText, Entry, EventControllerKey, GestureClick, Image, Label, Notebook, Scale, ScrolledWindow, TreeView, Widget};
-
 use czkawka_core::big_file::SearchMode;
 use czkawka_core::common_dir_traversal::CheckingMethod;
 use czkawka_core::localizer_core::{fnc_get_similarity_minimal, fnc_get_similarity_very_high};
 use czkawka_core::similar_images::{get_string_from_similarity, SIMILAR_VALUES};
+use gtk4::prelude::*;
+use gtk4::{Builder, CheckButton, ComboBoxText, Entry, EventControllerKey, GestureClick, Image, Label, Notebook, Scale, ScrolledWindow, TreeView, Widget};
 
 use crate::flg;
 use crate::help_combo_box::{AUDIO_TYPE_CHECK_METHOD_COMBO_BOX, BIG_FILES_CHECK_METHOD_COMBO_BOX, DUPLICATES_CHECK_METHOD_COMBO_BOX, IMAGES_HASH_SIZE_COMBO_BOX};
@@ -382,6 +381,8 @@ impl GuiMainNotebook {
         self.check_button_music_genre.set_label(Some(&flg!("music_genre_checkbox")));
         self.check_button_music_length.set_label(Some(&flg!("music_length_checkbox")));
         self.check_button_music_approximate_comparison.set_label(Some(&flg!("music_comparison_checkbox")));
+        self.check_button_music_compare_only_in_title_group
+            .set_label(Some(&flg!("music_compare_only_in_title_group")));
 
         self.check_button_music_approximate_comparison
             .set_tooltip_text(Some(&flg!("music_comparison_checkbox_tooltip")));
@@ -404,6 +405,8 @@ impl GuiMainNotebook {
         self.combo_box_duplicate_hash_type.set_tooltip_text(Some(&flg!("duplicate_hash_type_tooltip")));
         self.check_button_duplicate_case_sensitive_name
             .set_tooltip_text(Some(&flg!("duplicate_case_sensitive_name_tooltip")));
+        self.check_button_music_compare_only_in_title_group
+            .set_tooltip_text(Some(&flg!("music_compare_only_in_title_group_tooltip")));
 
         self.combo_box_image_hash_size.set_tooltip_text(Some(&flg!("image_hash_size_tooltip")));
         self.label_image_hash_size.set_tooltip_text(Some(&flg!("image_hash_size_tooltip")));
diff --git a/czkawka_gui/src/gui_structs/gui_settings.rs b/czkawka_gui/src/gui_structs/gui_settings.rs
index 95795625b..67dcf82ae 100644
--- a/czkawka_gui/src/gui_structs/gui_settings.rs
+++ b/czkawka_gui/src/gui_structs/gui_settings.rs
@@ -26,6 +26,7 @@ pub struct GuiSettings {
     pub label_settings_number_of_threads: gtk4::Label,
     pub scale_settings_number_of_threads: gtk4::Scale,
     pub label_restart_needed: gtk4::Label,
+    pub check_button_settings_use_rust_preview: gtk4::CheckButton,
 
     // Duplicates
     pub check_button_settings_hide_hard_links: gtk4::CheckButton,
@@ -84,6 +85,7 @@ impl GuiSettings {
         let label_settings_number_of_threads: gtk4::Label = builder.object("label_settings_number_of_threads").expect("Cambalache");
         let scale_settings_number_of_threads: gtk4::Scale = builder.object("scale_settings_number_of_threads").expect("Cambalache");
         let label_restart_needed: gtk4::Label = builder.object("label_restart_needed").expect("Cambalache");
+        let check_button_settings_use_rust_preview: gtk4::CheckButton = builder.object("check_button_settings_use_rust_preview").expect("Cambalache");
 
         // Duplicates
         let check_button_settings_hide_hard_links: gtk4::CheckButton = builder.object("check_button_settings_hide_hard_links").expect("Cambalache");
@@ -134,6 +136,7 @@ impl GuiSettings {
             label_settings_number_of_threads,
             scale_settings_number_of_threads,
             label_restart_needed,
+            check_button_settings_use_rust_preview,
             check_button_settings_hide_hard_links,
             entry_settings_cache_file_minimal_size,
             entry_settings_prehash_cache_file_minimal_size,
@@ -176,6 +179,7 @@ impl GuiSettings {
         self.label_settings_general_language.set_label(&flg!("settings_language_label"));
         self.check_button_settings_one_filesystem.set_label(Some(&flg!("settings_ignore_other_filesystems")));
         self.label_settings_number_of_threads.set_label(&flg!("settings_number_of_threads"));
+        self.check_button_settings_use_rust_preview.set_label(Some(&flg!("settings_use_rust_preview")));
 
         self.check_button_settings_save_at_exit
             .set_tooltip_text(Some(&flg!("settings_save_at_exit_button_tooltip")));
@@ -197,6 +201,8 @@ impl GuiSettings {
         self.check_button_settings_one_filesystem
             .set_tooltip_text(Some(&flg!("settings_ignore_other_filesystems_tooltip")));
         self.scale_settings_number_of_threads.set_tooltip_text(Some(&flg!("settings_number_of_threads_tooltip")));
+        self.check_button_settings_use_rust_preview
+            .set_tooltip_text(Some(&flg!("settings_use_rust_preview_tooltip")));
 
         self.check_button_settings_hide_hard_links
             .set_label(Some(&flg!("settings_duplicates_hide_hard_link_button")));
diff --git a/czkawka_gui/src/help_combo_box.rs b/czkawka_gui/src/help_combo_box.rs
index 17ba2c6c8..ddecc4a8f 100644
--- a/czkawka_gui/src/help_combo_box.rs
+++ b/czkawka_gui/src/help_combo_box.rs
@@ -1,8 +1,7 @@
-use image_hasher::{FilterType, HashAlg};
-
 use czkawka_core::big_file::SearchMode;
 use czkawka_core::common_dir_traversal::CheckingMethod;
 use czkawka_core::duplicate::HashType;
+use image_hasher::{FilterType, HashAlg};
 
 pub struct HashTypeStruct {
     pub eng_name: &'static str,
diff --git a/czkawka_gui/src/help_functions.rs b/czkawka_gui/src/help_functions.rs
index 60009468b..0fa7a0ac1 100644
--- a/czkawka_gui/src/help_functions.rs
+++ b/czkawka_gui/src/help_functions.rs
@@ -1,10 +1,3 @@
-use gdk4::gdk_pixbuf::{InterpType, Pixbuf};
-use glib::Error;
-use gtk4::prelude::*;
-use gtk4::{ListStore, Scale, ScrollType, TextView, TreeView, Widget};
-use image::codecs::jpeg::JpegEncoder;
-use image::{DynamicImage, EncodableLayout};
-use once_cell::sync::OnceCell;
 use std::cell::RefCell;
 use std::cmp::Ordering;
 use std::collections::HashMap;
@@ -25,6 +18,13 @@ use czkawka_core::same_music::SameMusic;
 use czkawka_core::similar_images::SimilarImages;
 use czkawka_core::similar_videos::SimilarVideos;
 use czkawka_core::temporary::Temporary;
+use gdk4::gdk_pixbuf::{InterpType, Pixbuf};
+use glib::Error;
+use gtk4::prelude::*;
+use gtk4::{ListStore, Scale, ScrollType, TextView, TreeView, Widget};
+use image::codecs::jpeg::JpegEncoder;
+use image::{DynamicImage, EncodableLayout};
+use once_cell::sync::OnceCell;
 
 use crate::flg;
 use crate::notebook_enums::{NotebookMainEnum, NotebookUpperEnum};
diff --git a/czkawka_gui/src/initialize_gui.rs b/czkawka_gui/src/initialize_gui.rs
index cd96a58d9..2e39d0287 100644
--- a/czkawka_gui/src/initialize_gui.rs
+++ b/czkawka_gui/src/initialize_gui.rs
@@ -1,19 +1,15 @@
 use std::cell::RefCell;
-use std::path::Path;
 use std::rc::Rc;
 
+use czkawka_core::common_image::get_dynamic_image_from_path;
+use czkawka_core::similar_images::SIMILAR_VALUES;
+use czkawka_core::similar_videos::MAX_TOLERANCE;
 use gdk4::gdk_pixbuf::Pixbuf;
 use glib::types::Type;
 use gtk4::gdk_pixbuf::InterpType;
 use gtk4::prelude::*;
 use gtk4::{CheckButton, Image, ScrolledWindow, SelectionMode, TextView, TreeModel, TreePath, TreeSelection, TreeView};
 
-#[cfg(feature = "heif")]
-use czkawka_core::common::get_dynamic_image_from_heic;
-use czkawka_core::common::{HEIC_EXTENSIONS, IMAGE_RS_EXTENSIONS, RAW_IMAGE_EXTENSIONS};
-use czkawka_core::similar_images::SIMILAR_VALUES;
-use czkawka_core::similar_videos::MAX_TOLERANCE;
-
 use crate::create_tree_view::*;
 use crate::gui_structs::gui_data::*;
 use crate::help_combo_box::{
@@ -335,6 +331,7 @@ fn connect_event_mouse(gui_data: &GuiData) {
         let image_preview = gui_data.main_notebook.image_preview_duplicates.clone();
         let preview_path = gui_data.preview_path.clone();
         let tree_view = gui_data.main_notebook.tree_view_duplicate_finder.clone();
+        let check_button_settings_use_rust_preview = gui_data.settings.check_button_settings_use_rust_preview.clone();
 
         tree_view.set_property("activate-on-single-click", true);
 
@@ -351,6 +348,7 @@ fn connect_event_mouse(gui_data: &GuiData) {
                 &preview_path,
                 nb_object.column_path,
                 nb_object.column_name,
+                check_button_settings_use_rust_preview.is_active(),
             );
         });
     }
@@ -361,6 +359,7 @@ fn connect_event_mouse(gui_data: &GuiData) {
         let preview_path = gui_data.preview_path.clone();
         let image_preview = gui_data.main_notebook.image_preview_similar_images.clone();
         let tree_view = gui_data.main_notebook.tree_view_similar_images_finder.clone();
+        let check_button_settings_use_rust_preview = gui_data.settings.check_button_settings_use_rust_preview.clone();
 
         tree_view.set_property("activate-on-single-click", true);
 
@@ -376,6 +375,7 @@ fn connect_event_mouse(gui_data: &GuiData) {
                 &preview_path,
                 nb_object.column_path,
                 nb_object.column_name,
+                check_button_settings_use_rust_preview.is_active(),
             );
         });
     }
@@ -412,6 +412,7 @@ fn connect_event_buttons(gui_data: &GuiData) {
         let image_preview = gui_data.main_notebook.image_preview_duplicates.clone();
         let preview_path = gui_data.preview_path.clone();
         let evk = gui_data.main_notebook.evk_tree_view_duplicate_finder.clone();
+        let check_button_settings_use_rust_preview = gui_data.settings.check_button_settings_use_rust_preview.clone();
 
         evk.connect_key_pressed(opening_enter_function_ported);
 
@@ -433,6 +434,7 @@ fn connect_event_buttons(gui_data: &GuiData) {
                 &preview_path,
                 nb_object.column_path,
                 nb_object.column_name,
+                check_button_settings_use_rust_preview.is_active(),
             );
         });
     }
@@ -444,6 +446,7 @@ fn connect_event_buttons(gui_data: &GuiData) {
         let gui_data_clone = gui_data.clone();
         let preview_path = gui_data.preview_path.clone();
         let evk = gui_data.main_notebook.evk_tree_view_similar_images_finder.clone();
+        let check_button_settings_use_rust_preview = gui_data.settings.check_button_settings_use_rust_preview.clone();
 
         evk.connect_key_pressed(opening_enter_function_ported);
 
@@ -465,6 +468,7 @@ fn connect_event_buttons(gui_data: &GuiData) {
                 &preview_path,
                 nb_object.column_path,
                 nb_object.column_name,
+                check_button_settings_use_rust_preview.is_active(),
             );
         });
     }
@@ -478,6 +482,7 @@ fn show_preview(
     preview_path: &Rc<RefCell<String>>,
     column_path: i32,
     column_name: i32,
+    use_rust_preview: bool,
 ) {
     let (selected_rows, tree_model) = tree_view.selection().selected_rows();
 
@@ -493,29 +498,13 @@ fn show_preview(
             let name = tree_model.get::<String>(&tree_model.iter(&tree_path).expect("Invalid tree_path"), column_name);
 
             let file_name = get_full_name_from_path_name(&path, &name);
-            let file_name = file_name.as_str();
 
-            {
-                let preview_path = preview_path.borrow();
-                let preview_path = &*preview_path;
-                if file_name == preview_path {
-                    return; // Preview is already created, no need to recreate it
-                }
+            if file_name == preview_path.borrow().as_str() {
+                return; // Preview is already created, no need to recreate it
             }
 
-            let is_heic;
-            if let Some(extension) = Path::new(&name).extension() {
-                let extension_lowercase = extension.to_string_lossy().to_lowercase();
-                is_heic = HEIC_EXTENSIONS.contains(&extension_lowercase.as_str());
-                if !RAW_IMAGE_EXTENSIONS.contains(&extension_lowercase.as_str()) && !IMAGE_RS_EXTENSIONS.contains(&extension_lowercase.as_str()) && !is_heic {
-                    break 'dir;
-                }
-            } else {
-                break 'dir;
-            }
-            let mut pixbuf = if cfg!(feature = "heif") && is_heic {
-                #[cfg(feature = "heif")]
-                let image = match get_dynamic_image_from_heic(file_name) {
+            let mut pixbuf = if use_rust_preview {
+                let image = match get_dynamic_image_from_path(&file_name) {
                     Ok(t) => t,
                     Err(e) => {
                         add_text_to_text_view(text_view_errors, flg!("preview_image_opening_failure", name = file_name, reason = e.to_string()).as_str());
@@ -523,7 +512,6 @@ fn show_preview(
                     }
                 };
 
-                #[cfg(feature = "heif")]
                 match get_pixbuf_from_dynamic_image(&image) {
                     Ok(t) => t,
                     Err(e) => {
@@ -531,18 +519,15 @@ fn show_preview(
                         break 'dir;
                     }
                 }
-
-                #[cfg(not(feature = "heif"))]
-                unreachable!()
             } else {
-                match Pixbuf::from_file(file_name) {
+                match Pixbuf::from_file(&file_name) {
                     Ok(pixbuf) => pixbuf,
                     Err(e) => {
                         add_text_to_text_view(
                             text_view_errors,
                             flg!(
                                 "preview_image_opening_failure",
-                                generate_translation_hashmap(vec![("name", file_name.to_string()), ("reason", e.to_string())])
+                                generate_translation_hashmap(vec![("name", file_name), ("reason", e.to_string())])
                             )
                             .as_str(),
                         );
@@ -550,7 +535,6 @@ fn show_preview(
                     }
                 }
             };
-
             pixbuf = match resize_pixbuf_dimension(&pixbuf, (800, 800), InterpType::Bilinear) {
                 None => {
                     add_text_to_text_view(text_view_errors, flg!("preview_image_resize_failure", name = file_name).as_str());
@@ -562,7 +546,7 @@ fn show_preview(
             image_preview.set_from_pixbuf(Some(&pixbuf));
             {
                 let mut preview_path = preview_path.borrow_mut();
-                *preview_path = file_name.to_string();
+                *preview_path = file_name;
             }
 
             created_image = true;
diff --git a/czkawka_gui/src/main.rs b/czkawka_gui/src/main.rs
index bdeeaffd1..551920e36 100644
--- a/czkawka_gui/src/main.rs
+++ b/czkawka_gui/src/main.rs
@@ -9,12 +9,6 @@
 use std::env;
 use std::ffi::OsString;
 
-use crossbeam_channel::{unbounded, Receiver, Sender};
-use gtk4::gio::ApplicationFlags;
-use gtk4::prelude::*;
-use gtk4::Application;
-use log::info;
-
 use connect_things::connect_about_buttons::*;
 use connect_things::connect_button_compare::*;
 use connect_things::connect_button_delete::*;
@@ -33,10 +27,15 @@ use connect_things::connect_selection_of_directories::*;
 use connect_things::connect_settings::*;
 use connect_things::connect_show_hide_ui::*;
 use connect_things::connect_similar_image_size_change::*;
+use crossbeam_channel::{unbounded, Receiver, Sender};
 use czkawka_core::common::{get_number_of_threads, print_version_mode, set_number_of_threads, setup_logger};
 use czkawka_core::progress_data::ProgressData;
 use czkawka_core::*;
+use gtk4::gio::ApplicationFlags;
+use gtk4::prelude::*;
+use gtk4::Application;
 use gui_structs::gui_data::*;
+use log::info;
 
 use crate::compute_results::*;
 use crate::connect_things::connect_button_sort::connect_button_sort;
diff --git a/czkawka_gui/src/saving_loading.rs b/czkawka_gui/src/saving_loading.rs
index 354998558..8fa27c350 100644
--- a/czkawka_gui/src/saving_loading.rs
+++ b/czkawka_gui/src/saving_loading.rs
@@ -5,14 +5,13 @@ use std::io::{Read, Write};
 use std::path::{Path, PathBuf};
 use std::{env, fs};
 
-use directories_next::ProjectDirs;
-use gtk4::prelude::*;
-use gtk4::{ComboBoxText, ScrolledWindow, TextView, TreeView};
-
 use czkawka_core::common::get_all_available_threads;
 use czkawka_core::common_dir_traversal::CheckingMethod;
 use czkawka_core::common_items::DEFAULT_EXCLUDED_ITEMS;
 use czkawka_core::similar_images::SIMILAR_VALUES;
+use directories_next::ProjectDirs;
+use gtk4::prelude::*;
+use gtk4::{ComboBoxText, ScrolledWindow, TextView, TreeView};
 
 use crate::flg;
 use crate::gui_structs::gui_main_notebook::GuiMainNotebook;
@@ -43,9 +42,10 @@ const DEFAULT_IMAGE_REMOVE_AUTO_OUTDATED_CACHE: bool = true;
 const DEFAULT_DUPLICATE_REMOVE_AUTO_OUTDATED_CACHE: bool = true;
 const DEFAULT_DUPLICATE_CASE_SENSITIVE_NAME_CHECKING: bool = false;
 const DEFAULT_GENERAL_IGNORE_OTHER_FILESYSTEMS: bool = false;
+const DEFUALT_USING_RUST_LIBRARIES_TO_SHOW_PREVIEW: bool = true;
 
 const DEFAULT_MUSIC_APPROXIMATE_COMPARISON: bool = false;
-const DEFAULT_MUSIC_COMPARE_BY_TITLE: bool = false;
+const DEFAULT_MUSIC_GROUP_CONTENT_BY_TITLE: bool = false;
 
 const DEFAULT_BROKEN_FILES_PDF: bool = true;
 const DEFAULT_BROKEN_FILES_AUDIO: bool = true;
@@ -391,6 +391,7 @@ enum LoadText {
     BrokenFilesImage,
     BrokenFilesArchive,
     ThreadNumber,
+    GeneralUseRustLibrariesToPreview,
 }
 
 fn create_hash_map() -> (HashMap<LoadText, String>, HashMap<String, LoadText>) {
@@ -439,6 +440,7 @@ fn create_hash_map() -> (HashMap<LoadText, String>, HashMap<String, LoadText>) {
         (LoadText::GeneralIgnoreOtherFilesystems, "ignore_other_filesystems"),
         (LoadText::ThreadNumber, "thread_number"),
         (LoadText::MusicCompareByTitle, "music_compare_by_title"),
+        (LoadText::GeneralUseRustLibrariesToPreview, "use_rust_libraries_to_preview"),
     ];
     let mut hashmap_ls: HashMap<LoadText, String> = Default::default();
     let mut hashmap_sl: HashMap<String, LoadText> = Default::default();
@@ -529,6 +531,10 @@ pub fn save_configuration(manual_execution: bool, upper_notebook: &GuiUpperNoteb
         hashmap_ls[&LoadText::GeneralIgnoreOtherFilesystems].clone(),
         &settings.check_button_settings_one_filesystem.is_active(),
     );
+    saving_struct.save_var(
+        hashmap_ls[&LoadText::GeneralUseRustLibrariesToPreview].clone(),
+        &settings.check_button_settings_use_rust_preview.is_active(),
+    );
 
     saving_struct.save_var(
         hashmap_ls[&LoadText::BrokenFilesArchive].clone(),
@@ -656,6 +662,11 @@ pub fn load_configuration(
     let use_json_cache: bool = loaded_entries.get_bool(hashmap_ls[&LoadText::UseJsonCacheFile].clone(), DEFAULT_SAVE_ALSO_AS_JSON);
     let use_trash: bool = loaded_entries.get_bool(hashmap_ls[&LoadText::DeleteToTrash].clone(), DEFAULT_USE_TRASH);
     let ignore_other_fs: bool = loaded_entries.get_bool(hashmap_ls[&LoadText::GeneralIgnoreOtherFilesystems].clone(), DEFAULT_GENERAL_IGNORE_OTHER_FILESYSTEMS);
+    let use_rust_libraries_to_preview: bool = loaded_entries.get_bool(
+        hashmap_ls[&LoadText::GeneralUseRustLibrariesToPreview].clone(),
+        DEFUALT_USING_RUST_LIBRARIES_TO_SHOW_PREVIEW,
+    );
+
     let delete_outdated_cache_duplicates: bool = loaded_entries.get_bool(
         hashmap_ls[&LoadText::DuplicateDeleteOutdatedCacheEntries].clone(),
         DEFAULT_DUPLICATE_REMOVE_AUTO_OUTDATED_CACHE,
@@ -685,7 +696,7 @@ pub fn load_configuration(
     let similar_videos_ignore_same_size = loaded_entries.get_bool(hashmap_ls[&LoadText::SimilarVideosIgnoreSameSize].clone(), DEFAULT_SIMILAR_VIDEOS_IGNORE_SAME_SIZE);
     let check_button_case_sensitive_name = loaded_entries.get_object(hashmap_ls[&LoadText::DuplicateNameCaseSensitive].clone(), DEFAULT_DUPLICATE_CASE_SENSITIVE_NAME_CHECKING);
     let check_button_music_approximate_comparison = loaded_entries.get_object(hashmap_ls[&LoadText::MusicApproximateComparison].clone(), DEFAULT_MUSIC_APPROXIMATE_COMPARISON);
-    let check_button_music_compare_by_title = loaded_entries.get_object(hashmap_ls[&LoadText::MusicCompareByTitle].clone(), DEFAULT_MUSIC_COMPARE_BY_TITLE);
+    let check_button_music_compare_by_title = loaded_entries.get_object(hashmap_ls[&LoadText::MusicCompareByTitle].clone(), DEFAULT_MUSIC_GROUP_CONTENT_BY_TITLE);
 
     let check_button_broken_files_archive = loaded_entries.get_object(hashmap_ls[&LoadText::BrokenFilesArchive].clone(), DEFAULT_BROKEN_FILES_ARCHIVE);
     let check_button_broken_files_pdf = loaded_entries.get_object(hashmap_ls[&LoadText::BrokenFilesPdf].clone(), DEFAULT_BROKEN_FILES_PDF);
@@ -800,6 +811,7 @@ pub fn load_configuration(
         settings.entry_settings_cache_file_minimal_size.set_text(&cache_minimal_size);
         settings.entry_settings_prehash_cache_file_minimal_size.set_text(&cache_prehash_minimal_size);
         settings.check_button_settings_one_filesystem.set_active(ignore_other_fs);
+        settings.check_button_settings_use_rust_preview.set_active(use_rust_libraries_to_preview);
 
         save_proper_value_to_combo_box(&main_notebook.combo_box_duplicate_hash_type, combo_box_duplicate_hash_type);
         save_proper_value_to_combo_box(&main_notebook.combo_box_duplicate_check_method, combo_box_duplicate_checking_method);
@@ -966,6 +978,7 @@ pub fn reset_configuration(manual_clearing: bool, upper_notebook: &GuiUpperNoteb
         settings.entry_settings_prehash_cache_file_minimal_size.set_text(DEFAULT_PREHASH_MINIMAL_CACHE_SIZE);
         settings.combo_box_settings_language.set_active(Some(0));
         settings.check_button_settings_one_filesystem.set_active(DEFAULT_GENERAL_IGNORE_OTHER_FILESYSTEMS);
+        settings.check_button_settings_use_rust_preview.set_active(DEFUALT_USING_RUST_LIBRARIES_TO_SHOW_PREVIEW);
 
         main_notebook.combo_box_duplicate_hash_type.set_active(Some(0));
         main_notebook.combo_box_duplicate_check_method.set_active(Some(0));
@@ -982,6 +995,12 @@ pub fn reset_configuration(manual_clearing: bool, upper_notebook: &GuiUpperNoteb
         main_notebook.scale_similarity_similar_images.set_range(0_f64, SIMILAR_VALUES[0][5] as f64); // DEFAULT FOR MAX of 8
         main_notebook.scale_similarity_similar_images.set_fill_level(SIMILAR_VALUES[0][5] as f64);
 
+        main_notebook
+            .check_button_music_compare_only_in_title_group
+            .set_active(DEFAULT_MUSIC_GROUP_CONTENT_BY_TITLE);
+
+        main_notebook.check_button_music_approximate_comparison.set_active(DEFAULT_MUSIC_APPROXIMATE_COMPARISON);
+
         main_notebook.entry_big_files_number.set_text(DEFAULT_NUMBER_OF_BIGGEST_FILES);
         main_notebook.scale_similarity_similar_images.set_value(DEFAULT_SIMILAR_IMAGES_SIMILARITY as f64);
         main_notebook.check_button_image_ignore_same_size.set_active(DEFAULT_SIMILAR_IMAGES_IGNORE_SAME_SIZE);
diff --git a/czkawka_gui/ui/about_dialog.ui b/czkawka_gui/ui/about_dialog.ui
index 5b3581f73..1f9320a35 100644
--- a/czkawka_gui/ui/about_dialog.ui
+++ b/czkawka_gui/ui/about_dialog.ui
@@ -1,5 +1,5 @@
 <?xml version='1.0' encoding='UTF-8'?>
-<!-- Created with Cambalache 0.90.4 -->
+<!-- Created with Cambalache 0.92.0 -->
 <interface>
   <!-- interface-name about_dialog.ui -->
   <requires lib="gtk" version="4.6"/>
diff --git a/czkawka_gui/ui/compare_images.ui b/czkawka_gui/ui/compare_images.ui
index 210067924..f0edba028 100644
--- a/czkawka_gui/ui/compare_images.ui
+++ b/czkawka_gui/ui/compare_images.ui
@@ -1,5 +1,5 @@
 <?xml version='1.0' encoding='UTF-8'?>
-<!-- Created with Cambalache 0.90.4 -->
+<!-- Created with Cambalache 0.92.0 -->
 <interface>
   <!-- interface-name compare_images.ui -->
   <requires lib="gtk" version="4.6"/>
diff --git a/czkawka_gui/ui/czkawka.cmb b/czkawka_gui/ui/czkawka.cmb
index c3e58692a..abc1e69a0 100755
--- a/czkawka_gui/ui/czkawka.cmb
+++ b/czkawka_gui/ui/czkawka.cmb
@@ -1,6 +1,6 @@
 <?xml version='1.0' encoding='UTF-8' standalone='no'?>
 <!DOCTYPE cambalache-project SYSTEM "cambalache-project.dtd">
-<cambalache-project version="0.17.3" target_tk="gtk-4.0">
+<cambalache-project version="0.92.0" target_tk="gtk-4.0">
   <ui>
 	(3,None,"about_dialog.ui","about_dialog.ui",None,None,None,None,None,None,None),
 	(4,None,"compare_images.ui","compare_images.ui",None,None,None,None,None,None,None),
@@ -22,139 +22,139 @@
 	(10,"gtk","4.6",None)
   </ui_library>
   <object>
-	(3,1,"GtkAboutDialog","about_dialog",None,None,None,None,None,None,None),
-	(4,1,"GtkDialog","window_compare",None,None,None,None,None,None,None),
-	(4,2,"GtkBox",None,1,None,None,None,None,None,None),
-	(4,3,"GtkBox",None,2,None,None,None,None,None,None),
+	(3,1,"GtkAboutDialog","about_dialog",None,None,None,None,0,None,None),
+	(4,1,"GtkDialog","window_compare",None,None,None,None,0,None,None),
+	(4,2,"GtkBox",None,1,None,None,None,0,None,None),
+	(4,3,"GtkBox",None,2,None,None,None,0,None,None),
 	(4,4,"GtkLabel","label_group_info",3,None,None,None,1,None,None),
 	(4,5,"GtkButton","button_go_next_compare_group",3,None,None,None,2,None,None),
-	(4,6,"GtkImage",None,5,None,None,None,None,None,None),
-	(4,7,"GtkButton","button_go_previous_compare_group",3,None,None,None,None,None,None),
-	(4,8,"GtkImage",None,7,None,None,None,None,None,None),
+	(4,6,"GtkImage",None,5,None,None,None,0,None,None),
+	(4,7,"GtkButton","button_go_previous_compare_group",3,None,None,None,0,None,None),
+	(4,8,"GtkImage",None,7,None,None,None,0,None,None),
 	(4,9,"GtkBox",None,2,None,None,None,1,None,None),
-	(4,10,"GtkCheckButton","check_button_left_preview_text",9,None,None,None,None,None,None),
+	(4,10,"GtkCheckButton","check_button_left_preview_text",9,None,None,None,0,None,None),
 	(4,11,"GtkCheckButton","check_button_right_preview_text",9,None,None,None,1,None,None),
 	(4,12,"GtkBox",None,2,None,None,None,2,None,None),
-	(4,13,"GtkImage","image_compare_left",12,None,None,None,None,None,None),
+	(4,13,"GtkImage","image_compare_left",12,None,None,None,0,None,None),
 	(4,14,"GtkImage","image_compare_right",12,None,None,None,1,None,None),
 	(4,15,"GtkScrolledWindow","scrolled_window_compare_choose_images",2,None,None,None,3,None,None),
-	(5,1,"GtkAdjustment","adjustment1",None,None,None,None,None,None,None),
-	(5,2,"GtkWindow","window_main",None,None,None,None,None,None,None),
-	(5,3,"GtkBox",None,2,None,None,None,None,None,None),
-	(5,4,"GtkPaned",None,3,None,None,None,None,None,None),
-	(5,5,"GtkNotebook","notebook_upper",4,None,None,None,None,None,None),
-	(5,6,"GtkNotebookPage",None,5,None,None,None,None,None,None),
-	(5,7,"GtkBox","notebook_upper_included_directories",6,None,None,None,None,None,None),
-	(5,8,"GtkBox",None,7,None,None,None,None,None,None),
-	(5,9,"GtkButton","buttons_add_included_directory",8,None,None,None,None,None,None),
-	(5,10,"GtkBox",None,9,None,None,None,None,None,None),
-	(5,11,"GtkImage",None,10,None,None,None,None,None,None),
+	(5,1,"GtkAdjustment","adjustment1",None,None,None,None,0,None,None),
+	(5,2,"GtkWindow","window_main",None,None,None,None,1,None,None),
+	(5,3,"GtkBox",None,2,None,None,None,0,None,None),
+	(5,4,"GtkPaned",None,3,None,None,None,0,None,None),
+	(5,5,"GtkNotebook","notebook_upper",4,None,None,None,0,None,None),
+	(5,6,"GtkNotebookPage",None,5,None,None,None,0,None,None),
+	(5,7,"GtkBox","notebook_upper_included_directories",6,None,None,None,0,None,None),
+	(5,8,"GtkBox",None,7,None,None,None,0,None,None),
+	(5,9,"GtkButton","buttons_add_included_directory",8,None,None,None,0,None,None),
+	(5,10,"GtkBox",None,9,None,None,None,0,None,None),
+	(5,11,"GtkImage",None,10,None,None,None,0,None,None),
 	(5,12,"GtkLabel",None,10,None,None,None,1,None,None),
 	(5,13,"GtkButton","buttons_remove_included_directory",8,None,None,None,1,None,None),
-	(5,14,"GtkBox",None,13,None,None,None,None,None,None),
-	(5,15,"GtkImage",None,14,None,None,None,None,None,None),
+	(5,14,"GtkBox",None,13,None,None,None,0,None,None),
+	(5,15,"GtkImage",None,14,None,None,None,0,None,None),
 	(5,16,"GtkLabel",None,14,None,None,None,1,None,None),
 	(5,17,"GtkButton","buttons_manual_add_included_directory",8,None,None,None,2,None,None),
-	(5,18,"GtkBox",None,17,None,None,None,None,None,None),
-	(5,19,"GtkImage",None,18,None,None,None,None,None,None),
+	(5,18,"GtkBox",None,17,None,None,None,0,None,None),
+	(5,19,"GtkImage",None,18,None,None,None,0,None,None),
 	(5,20,"GtkLabel",None,18,None,None,None,1,None,None),
 	(5,21,"GtkScrolledWindow","scrolled_window_included_directories",7,None,None,None,1,None,None),
 	(5,22,"GtkCheckButton","check_button_recursive",7,None,None,None,2,None,None),
-	(5,23,"GtkLabel",None,6,None,None,None,None,None,None),
+	(5,23,"GtkLabel",None,6,None,None,None,1,None,None),
 	(5,24,"GtkNotebookPage",None,5,None,None,None,1,None,None),
-	(5,25,"GtkBox","notebook_upper_excluded_directories",24,None,None,None,None,None,None),
-	(5,26,"GtkBox",None,25,None,None,None,None,None,None),
-	(5,27,"GtkButton","buttons_add_excluded_directory",26,None,None,None,None,None,None),
-	(5,28,"GtkBox",None,27,None,None,None,None,None,None),
-	(5,29,"GtkImage",None,28,None,None,None,None,None,None),
+	(5,25,"GtkBox","notebook_upper_excluded_directories",24,None,None,None,0,None,None),
+	(5,26,"GtkBox",None,25,None,None,None,0,None,None),
+	(5,27,"GtkButton","buttons_add_excluded_directory",26,None,None,None,0,None,None),
+	(5,28,"GtkBox",None,27,None,None,None,0,None,None),
+	(5,29,"GtkImage",None,28,None,None,None,0,None,None),
 	(5,30,"GtkLabel",None,28,None,None,None,1,None,None),
 	(5,31,"GtkButton","buttons_remove_excluded_directory",26,None,None,None,1,None,None),
-	(5,32,"GtkBox",None,31,None,None,None,None,None,None),
-	(5,33,"GtkImage",None,32,None,None,None,None,None,None),
+	(5,32,"GtkBox",None,31,None,None,None,0,None,None),
+	(5,33,"GtkImage",None,32,None,None,None,0,None,None),
 	(5,34,"GtkLabel",None,32,None,None,None,1,None,None),
 	(5,35,"GtkButton","buttons_manual_add_excluded_directory",26,None,None,None,2,None,None),
-	(5,36,"GtkBox",None,35,None,None,None,None,None,None),
-	(5,37,"GtkImage",None,36,None,None,None,None,None,None),
+	(5,36,"GtkBox",None,35,None,None,None,0,None,None),
+	(5,37,"GtkImage",None,36,None,None,None,0,None,None),
 	(5,38,"GtkLabel",None,36,None,None,None,1,None,None),
 	(5,39,"GtkScrolledWindow","scrolled_window_excluded_directories",25,None,None,None,1,None,None),
-	(5,40,"GtkLabel",None,24,None,None,None,None,None,None),
+	(5,40,"GtkLabel",None,24,None,None,None,1,None,None),
 	(5,41,"GtkNotebookPage",None,5,None,None,None,2,None,None),
-	(5,42,"GtkBox","notebook_upper_excluded_items",41,None,None,None,None,None,None),
-	(5,43,"GtkBox",None,42,None,None,None,None,None,None),
-	(5,44,"GtkLabel","label_excluded_items",43,None,None,None,None,None,None),
+	(5,42,"GtkBox","notebook_upper_excluded_items",41,None,None,None,0,None,None),
+	(5,43,"GtkBox",None,42,None,None,None,0,None,None),
+	(5,44,"GtkLabel","label_excluded_items",43,None,None,None,0,None,None),
 	(5,45,"GtkEntry","entry_excluded_items",43,None,None,None,1,None,None),
 	(5,46,"GtkBox",None,42,None,None,None,1,None,None),
-	(5,47,"GtkLabel","label_allowed_extensions",46,None,None,None,None,None,None),
+	(5,47,"GtkLabel","label_allowed_extensions",46,None,None,None,0,None,None),
 	(5,48,"GtkEntry","entry_allowed_extensions",46,None,None,None,1,None,None),
 	(5,49,"GtkBox",None,42,None,None,None,2,None,None),
-	(5,50,"GtkLabel","label_general_size_bytes",49,None,None,None,None,None,None),
+	(5,50,"GtkLabel","label_general_size_bytes",49,None,None,None,0,None,None),
 	(5,51,"GtkLabel","label_general_min_size",49,None,None,None,1,None,None),
 	(5,52,"GtkEntry","entry_general_minimal_size",49,None,None,None,2,None,None),
 	(5,53,"GtkLabel","label_general_max_size",49,None,None,None,3,None,None),
 	(5,54,"GtkEntry","entry_general_maximal_size",49,None,None,None,4,None,None),
-	(5,55,"GtkLabel",None,41,None,None,None,None,None,None),
+	(5,55,"GtkLabel",None,41,None,None,None,1,None,None),
 	(5,56,"GtkNotebook","notebook_main",4,None,None,None,1,None,None),
-	(5,57,"GtkNotebookPage",None,56,None,None,None,None,None,None),
-	(5,58,"GtkPaned",None,57,None,None,None,None,None,None),
-	(5,59,"GtkBox",None,58,None,None,None,None,None,None),
-	(5,60,"GtkBox",None,59,None,None,None,None,None,None),
-	(5,61,"GtkLabel","label_duplicate_check_method",60,None,None,None,None,None,None),
+	(5,57,"GtkNotebookPage",None,56,None,None,None,0,None,None),
+	(5,58,"GtkPaned",None,57,None,None,None,0,None,None),
+	(5,59,"GtkBox",None,58,None,None,None,0,None,None),
+	(5,60,"GtkBox",None,59,None,None,None,0,None,None),
+	(5,61,"GtkLabel","label_duplicate_check_method",60,None,None,None,0,None,None),
 	(5,62,"GtkComboBoxText","combo_box_duplicate_check_method",60,None,None,None,1,None,None),
 	(5,63,"GtkLabel","label_duplicate_hash_type",60,None,None,None,2,None,None),
 	(5,64,"GtkComboBoxText","combo_box_duplicate_hash_type",60,None,None,None,3,None,None),
 	(5,65,"GtkCheckButton","check_button_duplicate_case_sensitive_name",60,None,None,None,4,None,None),
 	(5,66,"GtkScrolledWindow","scrolled_window_duplicate_finder",59,None,None,None,1,None,None),
 	(5,67,"GtkImage","image_preview_duplicates",58,None,None,None,1,None,None),
-	(5,68,"GtkLabel",None,57,None,None,None,None,None,None),
+	(5,68,"GtkLabel",None,57,None,None,None,1,None,None),
 	(5,69,"GtkNotebookPage",None,56,None,None,None,1,None,None),
-	(5,70,"GtkScrolledWindow","scrolled_window_empty_folder_finder",69,None,None,None,None,None,None),
-	(5,71,"GtkLabel",None,69,None,None,None,None,None,None),
+	(5,70,"GtkScrolledWindow","scrolled_window_empty_folder_finder",69,None,None,None,0,None,None),
+	(5,71,"GtkLabel",None,69,None,None,None,1,None,None),
 	(5,72,"GtkNotebookPage",None,56,None,None,None,2,None,None),
-	(5,73,"GtkBox",None,72,None,None,None,None,None,None),
-	(5,74,"GtkBox",None,73,None,None,None,None,None,None),
+	(5,73,"GtkBox",None,72,None,None,None,0,None,None),
+	(5,74,"GtkBox",None,73,None,None,None,0,None,None),
 	(5,75,"GtkLabel","label_big_shown_files",74,None,None,None,2,None,None),
 	(5,76,"GtkEntry","entry_big_files_number",74,None,None,None,3,None,None),
 	(5,77,"GtkScrolledWindow","scrolled_window_big_files_finder",73,None,None,None,1,None,None),
-	(5,78,"GtkLabel",None,72,None,None,None,None,None,None),
+	(5,78,"GtkLabel",None,72,None,None,None,1,None,None),
 	(5,79,"GtkNotebookPage",None,56,None,None,None,3,None,None),
-	(5,80,"GtkScrolledWindow","scrolled_window_empty_files_finder",79,None,None,None,None,None,None),
-	(5,81,"GtkLabel",None,79,None,None,None,None,None,None),
+	(5,80,"GtkScrolledWindow","scrolled_window_empty_files_finder",79,None,None,None,0,None,None),
+	(5,81,"GtkLabel",None,79,None,None,None,1,None,None),
 	(5,82,"GtkNotebookPage",None,56,None,None,None,4,None,None),
-	(5,83,"GtkScrolledWindow","scrolled_window_temporary_files_finder",82,None,None,None,None,None,None),
-	(5,84,"GtkLabel",None,82,None,None,None,None,None,None),
+	(5,83,"GtkScrolledWindow","scrolled_window_temporary_files_finder",82,None,None,None,0,None,None),
+	(5,84,"GtkLabel",None,82,None,None,None,1,None,None),
 	(5,85,"GtkNotebookPage",None,56,None,None,None,5,None,None),
-	(5,86,"GtkPaned",None,85,None,None,None,None,None,None),
-	(5,87,"GtkBox",None,86,None,None,None,None,None,None),
-	(5,88,"GtkBox",None,87,None,None,None,None,None,None),
-	(5,89,"GtkLabel","label_image_resize_algorithm",88,None,None,None,None,None,None),
+	(5,86,"GtkPaned",None,85,None,None,None,0,None,None),
+	(5,87,"GtkBox",None,86,None,None,None,0,None,None),
+	(5,88,"GtkBox",None,87,None,None,None,0,None,None),
+	(5,89,"GtkLabel","label_image_resize_algorithm",88,None,None,None,0,None,None),
 	(5,90,"GtkComboBoxText","combo_box_image_resize_algorithm",88,None,None,None,1,None,None),
 	(5,91,"GtkLabel","label_image_hash_size",88,None,None,None,2,None,None),
 	(5,92,"GtkComboBoxText","combo_box_image_hash_size",88,None,None,None,3,None,None),
 	(5,93,"GtkLabel","label_image_hash_type",88,None,None,None,4,None,None),
 	(5,94,"GtkComboBoxText","combo_box_image_hash_algorithm",88,None,None,None,5,None,None),
 	(5,95,"GtkBox",None,87,None,None,None,1,None,None),
-	(5,96,"GtkLabel","label_image_similarity",95,None,None,None,None,None,None),
+	(5,96,"GtkLabel","label_image_similarity",95,None,None,None,0,None,None),
 	(5,97,"GtkLabel","label_image_similarity_max",95,None,None,None,1,None,None),
 	(5,98,"GtkScale","scale_similarity_similar_images",95,None,None,None,2,None,None),
 	(5,99,"GtkLabel","label_similar_images_minimal_similarity",95,None,None,None,3,None,None),
 	(5,100,"GtkCheckButton","check_button_image_ignore_same_size",95,None,None,None,4,None,None),
 	(5,102,"GtkScrolledWindow","scrolled_window_similar_images_finder",87,None,None,None,2,None,None),
 	(5,103,"GtkImage","image_preview_similar_images",86,None,None,None,1,None,None),
-	(5,104,"GtkLabel",None,85,None,None,None,None,None,None),
+	(5,104,"GtkLabel",None,85,None,None,None,1,None,None),
 	(5,105,"GtkNotebookPage",None,56,None,None,None,6,None,None),
-	(5,106,"GtkBox",None,105,None,None,None,None,None,None),
-	(5,107,"GtkBox",None,106,None,None,None,None,None,None),
-	(5,108,"GtkLabel","label_video_similarity",107,None,None,None,None,None,None),
+	(5,106,"GtkBox",None,105,None,None,None,0,None,None),
+	(5,107,"GtkBox",None,106,None,None,None,0,None,None),
+	(5,108,"GtkLabel","label_video_similarity",107,None,None,None,0,None,None),
 	(5,109,"GtkLabel","label_video_similarity_max",107,None,None,None,1,None,None),
 	(5,110,"GtkScale","scale_similarity_similar_videos",107,None,None,None,2,None,None),
 	(5,111,"GtkLabel","label_video_similarity_min",107,None,None,None,3,None,None),
 	(5,112,"GtkCheckButton","check_button_video_ignore_same_size",107,None,None,None,4,None,None),
 	(5,113,"GtkScrolledWindow","scrolled_window_similar_videos_finder",106,None,None,None,1,None,None),
-	(5,114,"GtkLabel",None,105,None,None,None,None,None,None),
+	(5,114,"GtkLabel",None,105,None,None,None,1,None,None),
 	(5,115,"GtkNotebookPage",None,56,None,None,None,7,None,None),
-	(5,116,"GtkBox",None,115,None,None,None,None,None,None),
-	(5,117,"GtkBox",None,116,None,None,None,None,None,None),
-	(5,118,"GtkCheckButton","check_button_music_title",117,None,None,None,None,None,None),
+	(5,116,"GtkBox",None,115,None,None,None,0,None,None),
+	(5,117,"GtkBox",None,116,None,None,None,0,None,None),
+	(5,118,"GtkCheckButton","check_button_music_title",117,None,None,None,0,None,None),
 	(5,119,"GtkCheckButton","check_button_music_artist",117,None,None,None,1,None,None),
 	(5,120,"GtkCheckButton","check_button_music_year",117,None,None,None,2,None,None),
 	(5,121,"GtkCheckButton","check_button_music_bitrate",117,None,None,None,3,None,None),
@@ -163,80 +163,80 @@
 	(5,124,"GtkBox",None,116,None,None,None,1,None,None),
 	(5,125,"GtkCheckButton","check_button_music_approximate_comparison",124,None,None,None,2,None,None),
 	(5,126,"GtkScrolledWindow","scrolled_window_same_music_finder",116,None,None,None,2,None,None),
-	(5,127,"GtkLabel",None,115,None,None,None,None,None,None),
+	(5,127,"GtkLabel",None,115,None,None,None,1,None,None),
 	(5,128,"GtkNotebookPage",None,56,None,None,None,8,None,None),
-	(5,129,"GtkScrolledWindow","scrolled_window_invalid_symlinks",128,None,None,None,None,None,None),
-	(5,130,"GtkLabel",None,128,None,None,None,None,None,None),
+	(5,129,"GtkScrolledWindow","scrolled_window_invalid_symlinks",128,None,None,None,0,None,None),
+	(5,130,"GtkLabel",None,128,None,None,None,1,None,None),
 	(5,131,"GtkNotebookPage",None,56,None,None,None,9,None,None),
-	(5,132,"GtkBox",None,131,None,None,None,None,None,None),
-	(5,133,"GtkLabel",None,131,None,None,None,None,None,None),
+	(5,132,"GtkBox",None,131,None,None,None,0,None,None),
+	(5,133,"GtkLabel",None,131,None,None,None,1,None,None),
 	(5,134,"GtkNotebookPage",None,56,None,None,None,10,None,None),
-	(5,135,"GtkScrolledWindow","scrolled_window_bad_extensions",134,None,None,None,None,None,None),
-	(5,136,"GtkLabel",None,134,None,None,None,None,None,None),
+	(5,135,"GtkScrolledWindow","scrolled_window_bad_extensions",134,None,None,None,0,None,None),
+	(5,136,"GtkLabel",None,134,None,None,None,1,None,None),
 	(5,137,"GtkBox","buttons",3,None,None,None,1,None,None),
-	(5,138,"GtkBox",None,137,None,None,None,None,None,None),
-	(5,139,"GtkButton","buttons_search",138,None,None,None,None,None,None),
-	(5,140,"GtkBox",None,139,None,None,None,None,None,None),
-	(5,141,"GtkImage",None,140,None,None,None,None,None,None),
+	(5,138,"GtkBox",None,137,None,None,None,0,None,None),
+	(5,139,"GtkButton","buttons_search",138,None,None,None,0,None,None),
+	(5,140,"GtkBox",None,139,None,None,None,0,None,None),
+	(5,141,"GtkImage",None,140,None,None,None,0,None,None),
 	(5,142,"GtkLabel",None,140,None,None,None,1,None,None),
 	(5,176,"GtkBox",None,3,None,None,None,2,None,None),
-	(5,177,"GtkEntry","entry_info",176,None,None,None,None,None,None),
+	(5,177,"GtkEntry","entry_info",176,None,None,None,0,None,None),
 	(5,178,"GtkEntry",None,176,None,None,None,1,None,None),
 	(5,179,"GtkScrolledWindow","scrolled_window_errors",3,None,None,None,3,None,None),
-	(5,180,"GtkTextView","text_view_errors",179,None,None,None,None,None,None),
-	(5,181,"GtkHeaderBar",None,2,None,"titlebar",None,None,None,None),
-	(5,182,"GtkBox",None,181,None,"end",None,None,None,None),
-	(5,183,"GtkButton","button_settings",182,None,None,None,None,None,None),
-	(5,184,"GtkImage",None,183,None,None,None,None,None,None),
+	(5,180,"GtkTextView","text_view_errors",179,None,None,None,0,None,None),
+	(5,181,"GtkHeaderBar",None,2,None,"titlebar",None,1,None,None),
+	(5,182,"GtkBox",None,181,None,"end",None,0,None,None),
+	(5,183,"GtkButton","button_settings",182,None,None,None,0,None,None),
+	(5,184,"GtkImage",None,183,None,None,None,0,None,None),
 	(5,185,"GtkButton","button_app_info",182,None,None,None,1,None,None),
-	(5,186,"GtkImage",None,185,None,None,None,None,None,None),
-	(5,187,"GtkBox",None,137,None,None,None,4,None,None),
-	(5,188,"GtkBox",None,187,None,None,None,1,None,None),
-	(5,189,"GtkMenuButton","buttons_select",188,None,None,None,None,None,None),
-	(5,190,"GtkBox",None,189,None,None,None,None,None,None),
-	(5,191,"GtkImage",None,190,None,None,None,None,None,None),
+	(5,186,"GtkImage",None,185,None,None,None,0,None,None),
+	(5,187,"GtkBox",None,137,None,None,None,1,None,None),
+	(5,188,"GtkBox",None,187,None,None,None,0,None,None),
+	(5,189,"GtkMenuButton","buttons_select",188,None,None,None,0,None,None),
+	(5,190,"GtkBox",None,189,None,None,None,0,None,None),
+	(5,191,"GtkImage",None,190,None,None,None,0,None,None),
 	(5,192,"GtkLabel","label_buttons_select",190,None,None,None,1,None,None),
 	(5,193,"GtkButton","buttons_compare",188,None,None,None,2,None,None),
-	(5,194,"GtkBox",None,193,None,None,None,None,None,None),
-	(5,195,"GtkImage",None,194,None,None,None,None,None,None),
+	(5,194,"GtkBox",None,193,None,None,None,0,None,None),
+	(5,195,"GtkImage",None,194,None,None,None,0,None,None),
 	(5,196,"GtkLabel",None,194,None,None,None,1,None,None),
 	(5,197,"GtkButton","buttons_delete",188,None,None,None,3,None,None),
-	(5,198,"GtkBox",None,197,None,None,None,None,None,None),
-	(5,199,"GtkImage",None,198,None,None,None,None,None,None),
+	(5,198,"GtkBox",None,197,None,None,None,0,None,None),
+	(5,199,"GtkImage",None,198,None,None,None,0,None,None),
 	(5,200,"GtkLabel",None,198,None,None,None,1,None,None),
 	(5,201,"GtkButton","buttons_move",188,None,None,None,4,None,None),
-	(5,202,"GtkBox",None,201,None,None,None,None,None,None),
-	(5,203,"GtkImage",None,202,None,None,None,None,None,None),
+	(5,202,"GtkBox",None,201,None,None,None,0,None,None),
+	(5,203,"GtkImage",None,202,None,None,None,0,None,None),
 	(5,204,"GtkLabel",None,202,None,None,None,1,None,None),
 	(5,205,"GtkButton","buttons_save",188,None,None,None,5,None,None),
-	(5,206,"GtkBox",None,205,None,None,None,None,None,None),
-	(5,207,"GtkImage",None,206,None,None,None,None,None,None),
+	(5,206,"GtkBox",None,205,None,None,None,0,None,None),
+	(5,207,"GtkImage",None,206,None,None,None,0,None,None),
 	(5,208,"GtkLabel",None,206,None,None,None,1,None,None),
 	(5,209,"GtkButton","buttons_symlink",188,None,None,None,6,None,None),
-	(5,210,"GtkBox",None,209,None,None,None,None,None,None),
-	(5,211,"GtkImage",None,210,None,None,None,None,None,None),
+	(5,210,"GtkBox",None,209,None,None,None,0,None,None),
+	(5,211,"GtkImage",None,210,None,None,None,0,None,None),
 	(5,212,"GtkLabel",None,210,None,None,None,1,None,None),
 	(5,213,"GtkButton","buttons_hardlink",188,None,None,None,7,None,None),
-	(5,214,"GtkBox",None,213,None,None,None,None,None,None),
-	(5,215,"GtkImage",None,214,None,None,None,None,None,None),
+	(5,214,"GtkBox",None,213,None,None,None,0,None,None),
+	(5,215,"GtkImage",None,214,None,None,None,0,None,None),
 	(5,216,"GtkLabel",None,214,None,None,None,1,None,None),
-	(5,217,"GtkButton","buttons_show_errors",187,None,None,None,2,None,None),
-	(5,218,"GtkImage",None,217,None,None,None,None,None,None),
-	(5,219,"GtkButton","buttons_show_upper_notebook",187,None,None,None,3,None,None),
-	(5,220,"GtkImage",None,219,None,None,None,None,None,None),
+	(5,217,"GtkButton","buttons_show_errors",187,None,None,None,1,None,None),
+	(5,218,"GtkImage",None,217,None,None,None,0,None,None),
+	(5,219,"GtkButton","buttons_show_upper_notebook",187,None,None,None,2,None,None),
+	(5,220,"GtkImage",None,219,None,None,None,0,None,None),
 	(5,221,"GtkComboBoxText","combo_box_big_files_mode",74,None,None,None,1,None,None),
-	(5,222,"GtkLabel","label_big_files_mode",74,None,None,None,None,None,None),
+	(5,222,"GtkLabel","label_big_files_mode",74,None,None,None,0,None,None),
 	(5,223,"GtkScrolledWindow","scrolled_window_broken_files",132,None,None,None,1,None,None),
-	(5,224,"GtkBox",None,132,None,None,None,None,None,None),
-	(5,225,"GtkCheckButton","check_button_broken_files_audio",224,None,None,None,None,None,None),
+	(5,224,"GtkBox",None,132,None,None,None,0,None,None),
+	(5,225,"GtkCheckButton","check_button_broken_files_audio",224,None,None,None,0,None,None),
 	(5,226,"GtkCheckButton","check_button_broken_files_pdf",224,None,None,None,1,None,None),
 	(5,227,"GtkCheckButton","check_button_broken_files_archive",224,None,None,None,2,None,None),
 	(5,228,"GtkCheckButton","check_button_broken_files_image",224,None,None,None,3,None,None),
 	(5,229,"GtkMenuButton","buttons_sort",188,None,None,None,1,None,None),
-	(5,230,"GtkBox",None,229,None,None,None,None,None,None),
-	(5,231,"GtkImage",None,230,None,None,None,None,None,None),
+	(5,230,"GtkBox",None,229,None,None,None,0,None,None),
+	(5,231,"GtkImage",None,230,None,None,None,0,None,None),
 	(5,232,"GtkLabel","label_buttons_sort",230,None,None,None,1,None,None),
-	(5,234,"GtkLabel","label_audio_check_type",124,None,None,None,None,None,None),
+	(5,234,"GtkLabel","label_audio_check_type",124,None,None,None,0,None,None),
 	(5,235,"GtkComboBoxText","combo_box_audio_check_type",124,None,None,None,1,None,None),
 	(5,236,"GtkScale","scale_seconds_same_music",117,None,None,None,7,None,None),
 	(5,237,"GtkScale","scale_similarity_same_music",117,None,None,None,9,None,None),
@@ -245,13 +245,13 @@
 	(5,240,"GtkLabel","label_excluded_extensions",46,None,None,None,2,None,None),
 	(5,241,"GtkEntry","entry_excluded_extensions",46,None,None,None,3,None,None),
 	(5,242,"GtkCheckButton","check_button_music_compare_only_in_title_group",124,None,None,None,3,None,None),
-	(6,1,"GtkPopover","popover_right_click",None,None,None,None,None,None,None),
-	(6,2,"GtkBox",None,1,None,None,None,None,None,None),
-	(6,3,"GtkButton","buttons_popover_right_click_open_file",2,None,None,None,None,None,None),
+	(6,1,"GtkPopover","popover_right_click",None,None,None,None,0,None,None),
+	(6,2,"GtkBox",None,1,None,None,None,0,None,None),
+	(6,3,"GtkButton","buttons_popover_right_click_open_file",2,None,None,None,0,None,None),
 	(6,4,"GtkButton","buttons_popover_right_click_open_folder",2,None,None,None,1,None,None),
-	(7,1,"GtkPopover","popover_select",None,None,None,None,None,None,None),
-	(7,2,"GtkBox",None,1,None,None,None,None,None,None),
-	(7,3,"GtkButton","buttons_popover_select_custom",2,None,None,None,None,None,None),
+	(7,1,"GtkPopover","popover_select",None,None,None,None,0,None,None),
+	(7,2,"GtkBox",None,1,None,None,None,0,None,None),
+	(7,3,"GtkButton","buttons_popover_select_custom",2,None,None,None,0,None,None),
 	(7,4,"GtkButton","buttons_popover_unselect_custom",2,None,None,None,1,None,None),
 	(7,5,"GtkSeparator","separator_select_custom",2,None,None,None,2,None,None),
 	(7,6,"GtkButton","buttons_popover_select_all_images_except_biggest",2,None,None,None,3,None,None),
@@ -266,26 +266,26 @@
 	(7,15,"GtkSeparator","separator_select_reverse",2,None,None,None,12,None,None),
 	(7,16,"GtkButton","buttons_popover_select_all",2,None,None,None,13,None,None),
 	(7,17,"GtkButton","buttons_popover_unselect_all",2,None,None,None,14,None,None),
-	(8,15,"GtkDialog","window_progress",None,None,None,None,None,None,None),
-	(8,16,"GtkBox",None,15,None,None,None,None,None,None),
-	(8,17,"GtkGrid","grid_progress",16,None,None,None,None,None,None),
-	(8,18,"GtkLabel","label_progress_all_stages",17,None,None,None,None,None,None),
+	(8,15,"GtkDialog","window_progress",None,None,None,None,0,None,None),
+	(8,16,"GtkBox",None,15,None,None,None,0,None,None),
+	(8,17,"GtkGrid","grid_progress",16,None,None,None,0,None,None),
+	(8,18,"GtkLabel","label_progress_all_stages",17,None,None,None,0,None,None),
 	(8,19,"GtkProgressBar","progress_bar_all_stages",17,None,None,None,1,None,None),
 	(8,20,"GtkLabel","label_progress_current_stage",17,None,None,None,2,None,None),
 	(8,21,"GtkProgressBar","progress_bar_current_stage",17,None,None,None,3,None,None),
 	(8,22,"GtkLabel","label_stage",16,None,None,None,1,None,None),
 	(8,23,"GtkButton","button_stop_in_dialog",16,None,None,None,2,None,None),
-	(8,24,"GtkBox",None,23,None,None,None,None,None,None),
-	(8,25,"GtkImage",None,24,None,None,None,None,None,None),
+	(8,24,"GtkBox",None,23,None,None,None,0,None,None),
+	(8,25,"GtkImage",None,24,None,None,None,0,None,None),
 	(8,26,"GtkLabel",None,24,None,None,None,1,None,None),
-	(9,1,"GtkDialog","window_settings",None,None,None,None,None,None,None),
-	(9,3,"GtkBox","potatoo",1,None,None,None,None,None,None),
-	(9,6,"GtkNotebook","notebook_settings",3,None,None,None,1,None,None),
-	(9,7,"GtkNotebookPage",None,6,None,None,None,None,None,None),
-	(9,8,"GtkBox",None,7,None,None,None,None,None,None),
-	(9,9,"GtkBox",None,8,None,None,None,None,None,None),
-	(9,10,"GtkBox",None,9,None,None,None,None,None,None),
-	(9,11,"GtkLabel","label_settings_general_language",10,None,None,None,None,None,None),
+	(9,1,"GtkDialog","window_settings",None,None,None,None,0,None,None),
+	(9,3,"GtkBox","potatoo",1,None,None,None,0,None,None),
+	(9,6,"GtkNotebook","notebook_settings",3,None,None,None,0,None,None),
+	(9,7,"GtkNotebookPage",None,6,None,None,None,0,None,None),
+	(9,8,"GtkBox",None,7,None,None,None,0,None,None),
+	(9,9,"GtkBox",None,8,None,None,None,0,None,None),
+	(9,10,"GtkBox",None,9,None,None,None,0,None,None),
+	(9,11,"GtkLabel","label_settings_general_language",10,None,None,None,0,None,None),
 	(9,12,"GtkComboBoxText","combo_box_settings_language",10,None,None,None,1,None,None),
 	(9,13,"GtkCheckButton","check_button_settings_load_at_start",9,None,None,None,1,None,None),
 	(9,14,"GtkCheckButton","check_button_settings_save_at_exit",9,None,None,None,2,None,None),
@@ -297,46 +297,47 @@
 	(9,20,"GtkCheckButton","check_button_settings_save_also_json",9,None,None,None,8,None,None),
 	(9,21,"GtkCheckButton","check_button_settings_use_trash",9,None,None,None,9,None,None),
 	(9,22,"GtkBox",None,8,None,None,None,2,None,None),
-	(9,23,"GtkButton","button_settings_open_cache_folder",22,None,None,None,None,None,None),
+	(9,23,"GtkButton","button_settings_open_cache_folder",22,None,None,None,0,None,None),
 	(9,24,"GtkButton","button_settings_open_settings_folder",22,None,None,None,1,None,None),
-	(9,25,"GtkLabel",None,7,None,None,None,None,None,None),
+	(9,25,"GtkLabel",None,7,None,None,None,1,None,None),
 	(9,26,"GtkNotebookPage",None,6,None,None,None,1,None,None),
-	(9,27,"GtkBox",None,26,None,None,None,None,None,None),
-	(9,28,"GtkCheckButton","check_button_settings_hide_hard_links",27,None,None,None,None,None,None),
+	(9,27,"GtkBox",None,26,None,None,None,0,None,None),
+	(9,28,"GtkCheckButton","check_button_settings_hide_hard_links",27,None,None,None,0,None,None),
 	(9,29,"GtkCheckButton","check_button_settings_show_preview_duplicates",27,None,None,None,1,None,None),
-	(9,30,"GtkCheckButton","check_button_settings_duplicates_delete_outdated_cache",27,None,None,None,8,None,None),
-	(9,31,"GtkBox",None,27,None,None,None,3,None,None),
-	(9,32,"GtkLabel","label_settings_duplicate_minimal_size_cache",31,None,None,None,None,None,None),
+	(9,30,"GtkCheckButton","check_button_settings_duplicates_delete_outdated_cache",27,None,None,None,5,None,None),
+	(9,31,"GtkBox",None,27,None,None,None,2,None,None),
+	(9,32,"GtkLabel","label_settings_duplicate_minimal_size_cache",31,None,None,None,0,None,None),
 	(9,33,"GtkEntry","entry_settings_cache_file_minimal_size",31,None,None,None,1,None,None),
-	(9,34,"GtkCheckButton","check_button_duplicates_use_prehash_cache",27,None,None,None,4,None,None),
-	(9,35,"GtkButton","button_settings_duplicates_clear_cache",27,None,None,None,9,None,None),
-	(9,36,"GtkBox",None,27,None,None,None,6,None,None),
-	(9,37,"GtkLabel","label_settings_duplicate_minimal_size_cache_prehash",36,None,None,None,None,None,None),
+	(9,34,"GtkCheckButton","check_button_duplicates_use_prehash_cache",27,None,None,None,3,None,None),
+	(9,35,"GtkButton","button_settings_duplicates_clear_cache",27,None,None,None,6,None,None),
+	(9,36,"GtkBox",None,27,None,None,None,4,None,None),
+	(9,37,"GtkLabel","label_settings_duplicate_minimal_size_cache_prehash",36,None,None,None,0,None,None),
 	(9,38,"GtkEntry","entry_settings_prehash_cache_file_minimal_size",36,None,None,None,1,None,None),
-	(9,39,"GtkLabel",None,26,None,None,None,None,None,None),
+	(9,39,"GtkLabel",None,26,None,None,None,1,None,None),
 	(9,40,"GtkNotebookPage",None,6,None,None,None,2,None,None),
-	(9,41,"GtkBox",None,40,None,None,None,None,None,None),
-	(9,42,"GtkCheckButton","check_button_settings_show_preview_similar_images",41,None,None,None,None,None,None),
+	(9,41,"GtkBox",None,40,None,None,None,0,None,None),
+	(9,42,"GtkCheckButton","check_button_settings_show_preview_similar_images",41,None,None,None,0,None,None),
 	(9,43,"GtkCheckButton","check_button_settings_similar_images_delete_outdated_cache",41,None,None,None,1,None,None),
 	(9,44,"GtkButton","button_settings_similar_images_clear_cache",41,None,None,None,2,None,None),
-	(9,45,"GtkLabel",None,40,None,None,None,None,None,None),
+	(9,45,"GtkLabel",None,40,None,None,None,1,None,None),
 	(9,46,"GtkNotebookPage",None,6,None,None,None,3,None,None),
-	(9,47,"GtkBox",None,46,None,None,None,None,None,None),
-	(9,48,"GtkButton","button_settings_similar_videos_clear_cache",47,None,None,None,3,None,None),
-	(9,49,"GtkCheckButton","check_button_settings_similar_videos_delete_outdated_cache",47,None,None,None,1,None,None),
-	(9,50,"GtkLabel",None,46,None,None,None,None,None,None),
-	(9,51,"GtkBox",None,3,None,None,None,2,None,None),
-	(9,52,"GtkButton","button_settings_load_configuration",51,None,None,None,None,None,None),
+	(9,47,"GtkBox",None,46,None,None,None,0,None,None),
+	(9,48,"GtkButton","button_settings_similar_videos_clear_cache",47,None,None,None,1,None,None),
+	(9,49,"GtkCheckButton","check_button_settings_similar_videos_delete_outdated_cache",47,None,None,None,0,None,None),
+	(9,50,"GtkLabel",None,46,None,None,None,1,None,None),
+	(9,51,"GtkBox",None,3,None,None,None,1,None,None),
+	(9,52,"GtkButton","button_settings_load_configuration",51,None,None,None,0,None,None),
 	(9,53,"GtkButton","button_settings_reset_configuration",51,None,None,None,1,None,None),
 	(9,54,"GtkButton","button_settings_save_configuration",51,None,None,None,2,None,None),
 	(9,55,"GtkCheckButton","check_button_settings_one_filesystem",9,None,None,None,10,None,None),
-	(9,56,"GtkBox",None,9,None,None,None,11,None,None),
-	(9,57,"GtkLabel","label_settings_number_of_threads",56,None,None,None,None,None,None),
+	(9,56,"GtkBox",None,9,None,None,None,12,None,None),
+	(9,57,"GtkLabel","label_settings_number_of_threads",56,None,None,None,0,None,None),
 	(9,58,"GtkScale","scale_settings_number_of_threads",56,None,None,None,1,None,None),
 	(9,59,"GtkLabel","label_restart_needed",8,None,None,None,1,None,None),
-	(10,1,"GtkPopover","popover_sort",None,None,None,None,None,None,None),
-	(10,2,"GtkBox",None,1,None,None,None,None,None,None),
-	(10,3,"GtkButton","buttons_popover_sort_file_name",2,None,None,None,None,None,None),
+	(9,60,"GtkCheckButton","check_button_settings_use_rust_preview",9,None,None,None,11,None,None),
+	(10,1,"GtkPopover","popover_sort",None,None,None,None,0,None,None),
+	(10,2,"GtkBox",None,1,None,None,None,0,None,None),
+	(10,3,"GtkButton","buttons_popover_sort_file_name",2,None,None,None,0,None,None),
 	(10,4,"GtkButton","buttons_popover_sort_folder_name",2,None,None,None,1,None,None),
 	(10,5,"GtkButton","buttons_popover_sort_full_name",2,None,None,None,2,None,None),
 	(10,6,"GtkButton","buttons_popover_sort_size",2,None,None,None,3,None,None),
@@ -1027,6 +1028,9 @@
 	(9,59,"GtkLabel","label","Restart Required",None,None,None,None,None,None,None,None,None),
 	(9,59,"GtkWidget","margin-bottom","4",None,None,None,None,None,None,None,None,None),
 	(9,59,"GtkWidget","margin-top","5",None,None,None,None,None,None,None,None,None),
+	(9,60,"GtkCheckButton","active","1",0,None,None,None,None,None,None,None,None),
+	(9,60,"GtkCheckButton","label","Use external libraries instead gtk to load previews",None,None,None,None,None,None,None,None,None),
+	(9,60,"GtkWidget","focusable","1",0,None,None,None,None,None,None,None,None),
 	(10,1,"GtkPopover","child",None,None,None,None,None,2,None,None,None,None),
 	(10,1,"GtkPopover","position","top",None,None,None,None,None,None,None,None,None),
 	(10,2,"GtkOrientable","orientation","vertical",None,None,None,None,None,None,None,None,None),
diff --git a/czkawka_gui/ui/main_window.ui b/czkawka_gui/ui/main_window.ui
index 04d3b8a12..a1492e865 100644
--- a/czkawka_gui/ui/main_window.ui
+++ b/czkawka_gui/ui/main_window.ui
@@ -1,5 +1,5 @@
 <?xml version='1.0' encoding='UTF-8'?>
-<!-- Created with Cambalache 0.90.4 -->
+<!-- Created with Cambalache 0.92.0 -->
 <interface>
   <!-- interface-name main_window.ui -->
   <requires lib="gtk" version="4.6"/>
diff --git a/czkawka_gui/ui/popover_right_click.ui b/czkawka_gui/ui/popover_right_click.ui
index 2646c7301..2edc5345e 100644
--- a/czkawka_gui/ui/popover_right_click.ui
+++ b/czkawka_gui/ui/popover_right_click.ui
@@ -1,5 +1,5 @@
 <?xml version='1.0' encoding='UTF-8'?>
-<!-- Created with Cambalache 0.90.4 -->
+<!-- Created with Cambalache 0.92.0 -->
 <interface>
   <!-- interface-name popover_right_click.ui -->
   <requires lib="gtk" version="4.6"/>
diff --git a/czkawka_gui/ui/popover_select.ui b/czkawka_gui/ui/popover_select.ui
index d7d44b138..ff5f6f959 100644
--- a/czkawka_gui/ui/popover_select.ui
+++ b/czkawka_gui/ui/popover_select.ui
@@ -1,5 +1,5 @@
 <?xml version='1.0' encoding='UTF-8'?>
-<!-- Created with Cambalache 0.90.4 -->
+<!-- Created with Cambalache 0.92.0 -->
 <interface>
   <!-- interface-name popover_select.ui -->
   <requires lib="gtk" version="4.6"/>
diff --git a/czkawka_gui/ui/popover_sort.ui b/czkawka_gui/ui/popover_sort.ui
index 061865583..0958c4ba6 100644
--- a/czkawka_gui/ui/popover_sort.ui
+++ b/czkawka_gui/ui/popover_sort.ui
@@ -1,5 +1,5 @@
 <?xml version='1.0' encoding='UTF-8'?>
-<!-- Created with Cambalache 0.90.4 -->
+<!-- Created with Cambalache 0.92.0 -->
 <interface>
   <!-- interface-name popover_sort.ui -->
   <requires lib="gtk" version="4.6"/>
diff --git a/czkawka_gui/ui/progress.ui b/czkawka_gui/ui/progress.ui
index c782b4896..af3a49a2d 100644
--- a/czkawka_gui/ui/progress.ui
+++ b/czkawka_gui/ui/progress.ui
@@ -1,5 +1,5 @@
 <?xml version='1.0' encoding='UTF-8'?>
-<!-- Created with Cambalache 0.90.4 -->
+<!-- Created with Cambalache 0.92.0 -->
 <interface>
   <!-- interface-name progress.ui -->
   <requires lib="gtk" version="4.6"/>
diff --git a/czkawka_gui/ui/settings.ui b/czkawka_gui/ui/settings.ui
index 75d2963bf..44d3d58f7 100644
--- a/czkawka_gui/ui/settings.ui
+++ b/czkawka_gui/ui/settings.ui
@@ -1,5 +1,5 @@
 <?xml version='1.0' encoding='UTF-8'?>
-<!-- Created with Cambalache 0.90.4 -->
+<!-- Created with Cambalache 0.92.0 -->
 <interface>
   <!-- interface-name settings.ui -->
   <requires lib="gtk" version="4.6"/>
@@ -114,6 +114,13 @@
                             <property name="label">Exclude other filesystems(Linux)</property>
                           </object>
                         </child>
+                        <child>
+                          <object class="GtkCheckButton" id="check_button_settings_use_rust_preview">
+                            <property name="active">1</property>
+                            <property name="focusable">1</property>
+                            <property name="label">Use external libraries instead gtk to load previews</property>
+                          </object>
+                        </child>
                         <child>
                           <object class="GtkBox">
                             <child>
diff --git a/justfile b/justfile
index 85730d149..d82ab850e 100644
--- a/justfile
+++ b/justfile
@@ -4,8 +4,28 @@ build_all:
     cargo clippy
     cargo test
 
-run:
-    cargo run --bin czkawka_gui
+## run
+
+czkawka:
+    RUST_BACKTRACE=1 cargo run --bin czkawka_gui
+czkawka_r:
+    RUST_BACKTRACE=1 cargo run --bin czkawka_gui --release
+
+krokiet:
+    RUST_BACKTRACE=1 cargo run --bin krokiet
+krokiet_r:
+    RUST_BACKTRACE=1 cargo run --bin krokiet --release
+krokiet_dark:
+    RUST_BACKTRACE=1 SLINT_STYLE=fluent-dark cargo run --bin krokiet
+
+cli:
+    RUST_BACKTRACE=1 cargo run --bin czkawka_cli
+cli_r:
+    RUST_BACKTRACE=1 cargo run --bin czkawka_cli --release
+cli_help:
+    cargo run --bin czkawka_cli -- --help
+
+## Other
 
 build:
     cargo build --bin czkawka_gui
@@ -16,26 +36,6 @@ check:
 check_all:
     cargo check
 
-krokiet:
-    cargo run --bin krokiet
-
-czkawka:
-    cargo run --bin czkawka_gui
-
-krokiet_r:
-    cargo run --bin krokiet --release
-
-krokiet_dark:
-    SLINT_STYLE=fluent-dark cargo run --bin krokiet
-
-czkawka_r:
-    cargo run --bin czkawka_gui --release
-
-cli:
-    cargo run --bin czkawka_cli
-
-cli_help:
-    cargo run --bin czkawka_cli -- --help
 
 build_krokiet:
     cargo build --bin krokiet
@@ -44,7 +44,7 @@ build_czkawka:
     cargo build --bin czkawka_gui
 
 upgrade:
-    cargo upgrade -i
+    cargo +nightly -Z unstable-options update --breaking
     cargo update
 
 fix:
diff --git a/krokiet/Cargo.toml b/krokiet/Cargo.toml
index ace99fa16..aae93f105 100644
--- a/krokiet/Cargo.toml
+++ b/krokiet/Cargo.toml
@@ -34,7 +34,7 @@ trash = "5.1"
 i18n-embed = { version = "0.15", features = ["fluent-system", "desktop-requester"] }
 i18n-embed-fl = "0.9"
 rust-embed = { version = "8.5", features = ["debug-embed"] }
-once_cell = "1.19"
+once_cell = "1.20"
 
 # Try to use only needed features from https://github.com/slint-ui/slint/blob/master/api/rs/slint/Cargo.toml#L23-L31
 #slint = { path = "/home/rafal/test/slint/api/rs/slint/", default-features = false, features = ["std",
@@ -62,3 +62,4 @@ winit_software = ["slint/renderer-winit-software"]
 
 heif = ["czkawka_core/heif"]
 libraw = ["czkawka_core/libraw"]
+libavif = ["czkawka_core/libavif"]
diff --git a/krokiet/src/common.rs b/krokiet/src/common.rs
index e8b20a3c2..d6ece412d 100644
--- a/krokiet/src/common.rs
+++ b/krokiet/src/common.rs
@@ -1,9 +1,10 @@
 #![allow(dead_code)]
 use std::path::PathBuf;
 
-use crate::{CurrentTab, ExcludedDirectoriesModel, IncludedDirectoriesModel, MainListModel, MainWindow, Settings};
 use slint::{ComponentHandle, Model, ModelRc, SharedString, VecModel};
 
+use crate::{CurrentTab, ExcludedDirectoriesModel, IncludedDirectoriesModel, MainListModel, MainWindow, Settings};
+
 // Int model is used to store data in unchanged(* except that we need to split u64 into two i32) form and is used to sort/select data
 // Str model is used to display data in gui
 
diff --git a/krokiet/src/connect_delete.rs b/krokiet/src/connect_delete.rs
index 428f411e3..db3a2ac46 100644
--- a/krokiet/src/connect_delete.rs
+++ b/krokiet/src/connect_delete.rs
@@ -1,8 +1,7 @@
-use rayon::prelude::*;
-use slint::{ComponentHandle, ModelRc, VecModel};
-
 use czkawka_core::common::remove_folder_if_contains_only_empty_folders;
 use czkawka_core::common_messages::Messages;
+use rayon::prelude::*;
+use slint::{ComponentHandle, ModelRc, VecModel};
 
 use crate::common::{get_is_header_mode, get_tool_model, set_tool_model};
 use crate::model_operations::{collect_full_path_from_model, deselect_all_items, filter_out_checked_items};
diff --git a/krokiet/src/connect_move.rs b/krokiet/src/connect_move.rs
index 528c7fed2..ff5e5d594 100644
--- a/krokiet/src/connect_move.rs
+++ b/krokiet/src/connect_move.rs
@@ -1,13 +1,14 @@
-use crate::common::{get_is_header_mode, get_tool_model, set_tool_model};
-use crate::model_operations::{collect_path_name_from_model, deselect_all_items, filter_out_checked_items};
-use crate::{Callabler, CurrentTab, GuiState, MainListModel, MainWindow};
+use std::path::{Path, PathBuf};
+use std::{fs, path};
 
 use czkawka_core::common_messages::Messages;
 use rayon::prelude::*;
 use rfd::FileDialog;
 use slint::{ComponentHandle, ModelRc, VecModel};
-use std::path::{Path, PathBuf};
-use std::{fs, path};
+
+use crate::common::{get_is_header_mode, get_tool_model, set_tool_model};
+use crate::model_operations::{collect_path_name_from_model, deselect_all_items, filter_out_checked_items};
+use crate::{Callabler, CurrentTab, GuiState, MainListModel, MainWindow};
 
 pub fn connect_move(app: &MainWindow) {
     let a = app.as_weak();
diff --git a/krokiet/src/connect_progress_receiver.rs b/krokiet/src/connect_progress_receiver.rs
index 14053db45..a3f9cdf2c 100644
--- a/krokiet/src/connect_progress_receiver.rs
+++ b/krokiet/src/connect_progress_receiver.rs
@@ -1,11 +1,11 @@
 use std::thread;
 
 use crossbeam_channel::Receiver;
+use czkawka_core::common_dir_traversal::ToolType;
+use czkawka_core::progress_data::{CurrentStage, ProgressData};
 use slint::ComponentHandle;
 
 use crate::{MainWindow, ProgressToSend};
-use czkawka_core::common_dir_traversal::ToolType;
-use czkawka_core::progress_data::{CurrentStage, ProgressData};
 
 pub fn connect_progress_gathering(app: &MainWindow, progress_receiver: Receiver<ProgressData>) {
     let a = app.as_weak();
diff --git a/krokiet/src/connect_scan.rs b/krokiet/src/connect_scan.rs
index 6d68dcf8f..05b63cefd 100644
--- a/krokiet/src/connect_scan.rs
+++ b/krokiet/src/connect_scan.rs
@@ -6,10 +6,6 @@ use crossbeam_channel::{Receiver, Sender};
 use czkawka_core::bad_extensions::{BadExtensions, BadExtensionsParameters, BadFileEntry};
 use czkawka_core::big_file::{BigFile, BigFileParameters, SearchMode};
 use czkawka_core::broken_files::{BrokenEntry, BrokenFiles, BrokenFilesParameters, CheckedTypes};
-use humansize::{format_size, BINARY};
-use rayon::prelude::*;
-use slint::{ComponentHandle, ModelRc, SharedString, VecModel, Weak};
-
 use czkawka_core::common::{split_path, split_path_compare, DEFAULT_THREAD_SIZE};
 use czkawka_core::common_dir_traversal::{CheckingMethod, FileEntry};
 use czkawka_core::common_tool::CommonData;
@@ -24,6 +20,9 @@ use czkawka_core::similar_images;
 use czkawka_core::similar_images::{ImagesEntry, SimilarImages, SimilarImagesParameters};
 use czkawka_core::similar_videos::{SimilarVideos, SimilarVideosParameters, VideosEntry};
 use czkawka_core::temporary::{Temporary, TemporaryFileEntry};
+use humansize::{format_size, BINARY};
+use rayon::prelude::*;
+use slint::{ComponentHandle, ModelRc, SharedString, VecModel, Weak};
 
 use crate::common::{check_if_all_included_dirs_are_referenced, split_u64_into_i32s};
 use crate::settings::{
diff --git a/krokiet/src/connect_select.rs b/krokiet/src/connect_select.rs
index 0509bd61e..856b742ae 100644
--- a/krokiet/src/connect_select.rs
+++ b/krokiet/src/connect_select.rs
@@ -1,8 +1,9 @@
+use slint::{ComponentHandle, Model, ModelRc, VecModel};
+
 use crate::common::{
     connect_i32_into_u64, get_int_height_idx, get_int_modification_date_idx, get_int_size_idx, get_int_width_idx, get_is_header_mode, get_tool_model, set_tool_model,
 };
 use crate::{Callabler, CurrentTab, GuiState, MainListModel, MainWindow, SelectMode, SelectModel};
-use slint::{ComponentHandle, Model, ModelRc, VecModel};
 
 // TODO optimize this, not sure if it is possible to not copy entire model to just select item
 // https://github.com/slint-ui/slint/discussions/4595
diff --git a/krokiet/src/connect_show_preview.rs b/krokiet/src/connect_show_preview.rs
index b96b54fac..b7d00aab9 100644
--- a/krokiet/src/connect_show_preview.rs
+++ b/krokiet/src/connect_show_preview.rs
@@ -1,13 +1,11 @@
-use std::panic;
 use std::path::Path;
 use std::time::{Duration, Instant};
 
+use czkawka_core::common_image::get_dynamic_image_from_path;
 use image::DynamicImage;
 use log::{debug, error};
 use slint::ComponentHandle;
 
-use czkawka_core::common::{get_dynamic_image_from_raw_image, IMAGE_RS_EXTENSIONS, RAW_IMAGE_EXTENSIONS};
-
 use crate::{Callabler, CurrentTab, GuiState, MainWindow, Settings};
 
 pub type ImageBufferRgba = image::ImageBuffer<image::Rgba<u8>, Vec<u8>>;
@@ -77,39 +75,15 @@ fn load_image(image_path: &Path) -> Option<(Duration, DynamicImage)> {
     if !image_path.is_file() {
         return None;
     }
-    let image_name = image_path.to_string_lossy().to_string();
-    let image_extension = image_path.extension()?.to_string_lossy().to_lowercase();
-
-    let is_raw_image = RAW_IMAGE_EXTENSIONS.contains(&image_extension.as_str());
-    let is_normal_image = IMAGE_RS_EXTENSIONS.contains(&image_extension.as_str());
 
     let load_img_start_timer = Instant::now();
 
-    let img = panic::catch_unwind(|| {
-        let int_img = if is_normal_image {
-            match image::open(image_name) {
-                Ok(img) => img,
-                Err(e) => {
-                    error!("Error while loading image: {}", e);
-                    return None;
-                }
-            }
-        } else if is_raw_image {
-            match get_dynamic_image_from_raw_image(image_name) {
-                Ok(img) => img,
-                Err(e) => {
-                    error!("Error while loading raw image: {}", e);
-                    return None;
-                }
-            }
-        } else {
+    let img = match get_dynamic_image_from_path(&image_path.to_string_lossy()) {
+        Ok(img) => img,
+        Err(e) => {
+            error!("{e}");
             return None;
-        };
-        Some(int_img)
-    })
-    .unwrap_or_else(|e| {
-        error!("Error while loading image: {e:?}");
-        None
-    })?;
+        }
+    };
     Some((load_img_start_timer.elapsed(), img))
 }
diff --git a/krokiet/src/main.rs b/krokiet/src/main.rs
index 78f7cdf9a..b0ffa6b5c 100644
--- a/krokiet/src/main.rs
+++ b/krokiet/src/main.rs
@@ -21,10 +21,9 @@
 use std::rc::Rc;
 
 use crossbeam_channel::{unbounded, Receiver, Sender};
-use slint::VecModel;
-
 use czkawka_core::common::{print_version_mode, setup_logger};
 use czkawka_core::progress_data::ProgressData;
+use slint::VecModel;
 
 use crate::connect_delete::connect_delete_button;
 use crate::connect_directories_changes::connect_add_remove_directories;
diff --git a/krokiet/src/model_operations.rs b/krokiet/src/model_operations.rs
index e48af7e18..c589a6f98 100644
--- a/krokiet/src/model_operations.rs
+++ b/krokiet/src/model_operations.rs
@@ -1,7 +1,9 @@
+use std::path::MAIN_SEPARATOR;
+
+use slint::{Model, ModelRc};
+
 use crate::common::{get_str_name_idx, get_str_path_idx};
 use crate::{CurrentTab, MainListModel};
-use slint::{Model, ModelRc};
-use std::path::MAIN_SEPARATOR;
 
 pub fn deselect_all_items(items: &mut [MainListModel]) {
     for item in items {
diff --git a/krokiet/src/set_initial_gui_info.rs b/krokiet/src/set_initial_gui_info.rs
index acdc48155..635322181 100644
--- a/krokiet/src/set_initial_gui_info.rs
+++ b/krokiet/src/set_initial_gui_info.rs
@@ -1,6 +1,5 @@
-use slint::{ComponentHandle, SharedString, VecModel};
-
 use czkawka_core::common::get_all_available_threads;
+use slint::{ComponentHandle, SharedString, VecModel};
 
 use crate::settings::{
     ALLOWED_BIG_FILE_SIZE_VALUES, ALLOWED_DUPLICATES_CHECK_METHOD_VALUES, ALLOWED_DUPLICATES_HASH_TYPE_VALUES, ALLOWED_HASH_SIZE_VALUES, ALLOWED_IMAGE_HASH_ALG_VALUES,
diff --git a/krokiet/src/settings.rs b/krokiet/src/settings.rs
index 73a2c8f29..c5cb2c202 100644
--- a/krokiet/src/settings.rs
+++ b/krokiet/src/settings.rs
@@ -3,6 +3,10 @@ use std::env;
 use std::path::PathBuf;
 
 use czkawka_core::big_file::SearchMode;
+use czkawka_core::common::{get_all_available_threads, set_number_of_threads};
+use czkawka_core::common_dir_traversal::CheckingMethod;
+use czkawka_core::common_items::{DEFAULT_EXCLUDED_DIRECTORIES, DEFAULT_EXCLUDED_ITEMS};
+use czkawka_core::duplicate::HashType;
 use directories_next::ProjectDirs;
 use home::home_dir;
 use image_hasher::{FilterType, HashAlg};
@@ -10,11 +14,6 @@ use log::{debug, error, info, warn};
 use serde::{Deserialize, Serialize};
 use slint::{ComponentHandle, Model, ModelRc, SharedString, VecModel};
 
-use czkawka_core::common::{get_all_available_threads, set_number_of_threads};
-use czkawka_core::common_dir_traversal::CheckingMethod;
-use czkawka_core::common_items::{DEFAULT_EXCLUDED_DIRECTORIES, DEFAULT_EXCLUDED_ITEMS};
-use czkawka_core::duplicate::HashType;
-
 use crate::common::{create_excluded_directories_model_from_pathbuf, create_included_directories_model_from_pathbuf, create_vec_model_from_vec_string};
 use crate::{Callabler, GuiState, MainWindow, Settings};
 


Test patch:
diff --git a/ci_tester/src/main.rs b/ci_tester/src/main.rs
index b0959d95f..04e473111 100644
--- a/ci_tester/src/main.rs
+++ b/ci_tester/src/main.rs
@@ -480,6 +480,17 @@ fn collect_all_files_and_dirs(dir: &str) -> std::io::Result<CollectedFiles> {
         }
     }
 
+    for dir in &folders_to_check {
+        println!("Folder \"{}\"", dir)
+    }
+    for symlink in &symlinks {
+        println!("Symlink \"{}\"", symlink)
+    }
+    for file in &files {
+        let metadata = fs::metadata(file)?;
+        println!("File \"{}\" with size {} bytes", file, metadata.len());
+    }
+
     folders.remove(dir);
     // println!("Found {} files, {} folders and {} symlinks", files.len(), folders.len(), symlinks.len());
     Ok(CollectedFiles { files, folders, symlinks })