|
|
|
@ -19,11 +19,10 @@ use serde::{Deserialize, Serialize};
|
|
|
|
|
#[cfg(feature = "heif")]
|
|
|
|
|
use crate::common::get_dynamic_image_from_heic;
|
|
|
|
|
use crate::common::{
|
|
|
|
|
check_folder_children, create_crash_message, get_dynamic_image_from_raw_image, load_cache_from_file_generalized, open_cache_folder, prepare_thread_handler_common,
|
|
|
|
|
check_folder_children, create_crash_message, get_dynamic_image_from_raw_image, load_cache_from_file_generalized, prepare_thread_handler_common, save_cache_to_file_generalized,
|
|
|
|
|
send_info_and_wait_for_ending_all_threads, HEIC_EXTENSIONS, IMAGE_RS_SIMILAR_IMAGES_EXTENSIONS, RAW_IMAGE_EXTENSIONS,
|
|
|
|
|
};
|
|
|
|
|
use crate::common_dir_traversal::{common_get_entry_data_metadata, common_read_dir, get_lowercase_name, get_modified_time, CheckingMethod, ProgressData, ToolType};
|
|
|
|
|
use crate::common_messages::Messages;
|
|
|
|
|
use crate::common_tool::{CommonData, CommonToolData};
|
|
|
|
|
use crate::common_traits::{DebugPrint, PrintResults, ResultEntry, SaveResults};
|
|
|
|
|
use crate::flc;
|
|
|
|
@ -51,6 +50,12 @@ impl ResultEntry for FileEntry {
|
|
|
|
|
fn get_path(&self) -> &Path {
|
|
|
|
|
&self.path
|
|
|
|
|
}
|
|
|
|
|
fn get_modified_date(&self) -> u64 {
|
|
|
|
|
self.modified_date
|
|
|
|
|
}
|
|
|
|
|
fn get_size(&self) -> u64 {
|
|
|
|
|
self.size
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Used by CLI tool when we cannot use directly values
|
|
|
|
@ -375,15 +380,13 @@ impl SimilarImages {
|
|
|
|
|
for (file_entry, _hash) in vec_file_entry {
|
|
|
|
|
all_results.insert(file_entry.path.to_string_lossy().to_string(), file_entry);
|
|
|
|
|
}
|
|
|
|
|
let save_also_as_json = self.get_save_also_as_json();
|
|
|
|
|
save_hashes_to_file(
|
|
|
|
|
|
|
|
|
|
let messages = save_cache_to_file_generalized(
|
|
|
|
|
&get_cache_file(&self.hash_size, &self.hash_alg, &self.image_filter),
|
|
|
|
|
&all_results,
|
|
|
|
|
&mut self.common_data.text_messages,
|
|
|
|
|
save_also_as_json,
|
|
|
|
|
self.hash_size,
|
|
|
|
|
self.hash_alg,
|
|
|
|
|
self.image_filter,
|
|
|
|
|
self.common_data.save_also_as_json,
|
|
|
|
|
);
|
|
|
|
|
self.get_text_messages_mut().extend_with_another_messages(messages);
|
|
|
|
|
}
|
|
|
|
|
debug!("save_to_cache - end");
|
|
|
|
|
}
|
|
|
|
@ -940,92 +943,9 @@ impl PrintResults for SimilarImages {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn save_hashes_to_file(
|
|
|
|
|
hashmap: &BTreeMap<String, FileEntry>,
|
|
|
|
|
text_messages: &mut Messages,
|
|
|
|
|
save_also_as_json: bool,
|
|
|
|
|
hash_size: u8,
|
|
|
|
|
hash_alg: HashAlg,
|
|
|
|
|
image_filter: FilterType,
|
|
|
|
|
) {
|
|
|
|
|
if let Some(((file_handler, cache_file), (file_handler_json, cache_file_json))) =
|
|
|
|
|
open_cache_folder(&get_cache_file(&hash_size, &hash_alg, &image_filter), true, save_also_as_json, &mut text_messages.warnings)
|
|
|
|
|
{
|
|
|
|
|
{
|
|
|
|
|
let writer = BufWriter::new(file_handler.unwrap()); // Unwrap because cannot fail here
|
|
|
|
|
if let Err(e) = bincode::serialize_into(writer, hashmap) {
|
|
|
|
|
text_messages
|
|
|
|
|
.warnings
|
|
|
|
|
.push(format!("Cannot write data to cache file {}, reason {}", cache_file.display(), e));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if save_also_as_json {
|
|
|
|
|
if let Some(file_handler_json) = file_handler_json {
|
|
|
|
|
let writer = BufWriter::new(file_handler_json);
|
|
|
|
|
if let Err(e) = serde_json::to_writer(writer, hashmap) {
|
|
|
|
|
text_messages
|
|
|
|
|
.warnings
|
|
|
|
|
.push(format!("Cannot write data to cache file {}, reason {}", cache_file_json.display(), e));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
text_messages.messages.push(format!("Properly saved to file {} cache entries.", hashmap.len()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn load_hashes_from_file(
|
|
|
|
|
text_messages: &mut Messages,
|
|
|
|
|
delete_outdated_cache: bool,
|
|
|
|
|
hash_size: u8,
|
|
|
|
|
hash_alg: HashAlg,
|
|
|
|
|
image_filter: FilterType,
|
|
|
|
|
) -> Option<HashMap<String, FileEntry>> {
|
|
|
|
|
if let Some(((file_handler, cache_file), (file_handler_json, cache_file_json))) =
|
|
|
|
|
open_cache_folder(&get_cache_file(&hash_size, &hash_alg, &image_filter), false, true, &mut text_messages.warnings)
|
|
|
|
|
{
|
|
|
|
|
let mut hashmap_loaded_entries: HashMap<String, FileEntry>;
|
|
|
|
|
if let Some(file_handler) = file_handler {
|
|
|
|
|
let reader = BufReader::new(file_handler);
|
|
|
|
|
hashmap_loaded_entries = match bincode::deserialize_from(reader) {
|
|
|
|
|
Ok(t) => t,
|
|
|
|
|
Err(e) => {
|
|
|
|
|
text_messages
|
|
|
|
|
.warnings
|
|
|
|
|
.push(format!("Failed to load data from cache file {}, reason {}", cache_file.display(), e));
|
|
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
} else {
|
|
|
|
|
let reader = BufReader::new(file_handler_json.unwrap()); // Unwrap cannot fail, because at least one file must be valid
|
|
|
|
|
hashmap_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 {}, reason {}", cache_file_json.display(), e));
|
|
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Don't load cache data if destination file not exists
|
|
|
|
|
if delete_outdated_cache {
|
|
|
|
|
hashmap_loaded_entries.retain(|src_path, _file_entry| Path::new(src_path).exists());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
text_messages.messages.push(format!("Properly loaded {} cache entries.", hashmap_loaded_entries.len()));
|
|
|
|
|
|
|
|
|
|
return Some(hashmap_loaded_entries);
|
|
|
|
|
}
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_cache_file(hash_size: &u8, hash_alg: &HashAlg, image_filter: &FilterType) -> String {
|
|
|
|
|
format!(
|
|
|
|
|
"cache_similar_images_{}_{}_{}_50.bin",
|
|
|
|
|
"cache_similar_images_{}_{}_{}_61.bin",
|
|
|
|
|
hash_size,
|
|
|
|
|
convert_algorithm_to_string(hash_alg),
|
|
|
|
|
convert_filters_to_string(image_filter),
|
|
|
|
|