@@ -32,11 +32,6 @@ pub struct FileEntry {
32
32
pub modified_date : u64 ,
33
33
pub similarity : Similarity ,
34
34
}
35
- #[ derive( Clone ) ]
36
- pub struct StructSimilar {
37
- pub base_image : FileEntry ,
38
- pub similar_images : Vec < FileEntry > ,
39
- }
40
35
41
36
/// Type to store for each entry in the similarity BK-tree.
42
37
type Node = [ u8 ; 8 ] ;
@@ -57,11 +52,12 @@ pub struct SimilarImages {
57
52
directories : Directories ,
58
53
excluded_items : ExcludedItems ,
59
54
bktree : BKTree < Node , Hamming > ,
60
- similar_vectors : Vec < StructSimilar > ,
55
+ similar_vectors : Vec < Vec < FileEntry > > ,
61
56
recursive_search : bool ,
62
57
minimal_file_size : u64 ,
63
58
image_hashes : HashMap < Node , Vec < FileEntry > > , // Hashmap with image hashes and Vector with names of files
64
59
stopped_search : bool ,
60
+ similarity : Similarity ,
65
61
}
66
62
67
63
/// Info struck with helpful information's about results
@@ -98,6 +94,7 @@ impl SimilarImages {
98
94
minimal_file_size : 1024 * 16 , // 16 KB should be enough to exclude too small images from search
99
95
image_hashes : Default :: default ( ) ,
100
96
stopped_search : false ,
97
+ similarity : Similarity :: High ,
101
98
}
102
99
}
103
100
@@ -109,7 +106,7 @@ impl SimilarImages {
109
106
& self . text_messages
110
107
}
111
108
112
- pub const fn get_similar_images ( & self ) -> & Vec < StructSimilar > {
109
+ pub const fn get_similar_images ( & self ) -> & Vec < Vec < FileEntry > > {
113
110
& self . similar_vectors
114
111
}
115
112
@@ -127,6 +124,9 @@ impl SimilarImages {
127
124
t => t,
128
125
} ;
129
126
}
127
+ pub fn set_similarity ( & mut self , similarity : Similarity ) {
128
+ self . similarity = similarity;
129
+ }
130
130
131
131
/// Public function used by CLI to search for empty folders
132
132
pub fn find_similar_images ( & mut self , stop_receiver : Option < & Receiver < ( ) > > ) {
@@ -135,6 +135,10 @@ impl SimilarImages {
135
135
self . stopped_search = true ;
136
136
return ;
137
137
}
138
+ if !self . sort_images ( stop_receiver) {
139
+ self . stopped_search = true ;
140
+ return ;
141
+ }
138
142
// if self.delete_folders {
139
143
// self.delete_empty_folders();
140
144
// }
@@ -275,37 +279,51 @@ impl SimilarImages {
275
279
}
276
280
}
277
281
}
282
+ Common :: print_time ( start_time, SystemTime :: now ( ) , "check_for_similar_images" . to_string ( ) ) ;
283
+ true
284
+ }
278
285
286
+ fn sort_images ( & mut self , stop_receiver : Option < & Receiver < ( ) > > ) -> bool {
279
287
let hash_map_modification = SystemTime :: now ( ) ;
280
288
281
- let mut new_vector: Vec < StructSimilar > = Vec :: new ( ) ;
289
+ //let hash_map_modification = SystemTime::now();
290
+ let similarity: u64 = match self . similarity {
291
+ Similarity :: VeryHigh => 0 ,
292
+ Similarity :: High => 1 ,
293
+ Similarity :: Medium => 2 ,
294
+ Similarity :: Small => 3 ,
295
+ _ => panic ! ( "0-3 similarity levels are allowed, check if not added more." ) ,
296
+ } ;
297
+
298
+ // TODO
299
+ // Now is A is similar to B with VeryHigh and C with Medium
300
+ // And D is similar with C with High
301
+ // And Similarity is set to Medium(or lower)
302
+ // And A is checked before D
303
+ // Then C is shown that is similar group A, not D
304
+
305
+ let mut new_vector: Vec < Vec < FileEntry > > = Vec :: new ( ) ;
306
+ let mut hashes_to_check = self . image_hashes . clone ( ) ;
282
307
for ( hash, vec_file_entry) in & self . image_hashes {
283
308
if stop_receiver. is_some ( ) && stop_receiver. unwrap ( ) . try_recv ( ) . is_ok ( ) {
284
309
return false ;
285
310
}
286
- let vector_with_found_similar_hashes = self . bktree . find ( hash, 3 ) . collect :: < Vec < _ > > ( ) ;
311
+ let vector_with_found_similar_hashes = self . bktree . find ( hash, similarity ) . collect :: < Vec < _ > > ( ) ;
287
312
if vector_with_found_similar_hashes. len ( ) == 1 && vec_file_entry. len ( ) == 1 {
288
- // Exists only 1 unique picture , so there is no need to use it
313
+ // This one picture doesn't have similar pictures , so there is no go
289
314
continue ;
290
315
}
291
316
292
- let mut vec_similarity_struct: Vec < StructSimilar > = Vec :: new ( ) ;
293
-
294
- for file_entry in vec_file_entry. iter ( ) {
295
- let similar_struct = StructSimilar {
296
- base_image : file_entry. clone ( ) ,
297
- similar_images : vec_file_entry
298
- . iter ( )
299
- . filter ( |x| x. path != file_entry. path )
300
- . map ( |x| {
301
- let mut y = x. clone ( ) ;
302
- y. similarity = Similarity :: VeryHigh ;
303
- y
304
- } )
305
- . collect :: < Vec < FileEntry > > ( ) ,
306
- } ;
307
- vec_similarity_struct. push ( similar_struct) ;
308
- }
317
+ let mut vector_of_similar_images: Vec < FileEntry > = vec_file_entry
318
+ . iter ( )
319
+ . map ( |fe| FileEntry {
320
+ path : fe. path . clone ( ) ,
321
+ size : fe. size ,
322
+ dimensions : fe. dimensions . clone ( ) ,
323
+ modified_date : fe. modified_date ,
324
+ similarity : Similarity :: VeryHigh ,
325
+ } )
326
+ . collect ( ) ;
309
327
310
328
for ( similarity, similar_hash) in vector_with_found_similar_hashes. iter ( ) {
311
329
if * similarity == 0 && hash == * similar_hash {
@@ -315,31 +333,34 @@ impl SimilarImages {
315
333
panic ! ( "I'm not sure if same hash can have distance > 0" ) ;
316
334
}
317
335
318
- for file_entry in self . image_hashes . get ( * similar_hash) . unwrap ( ) {
319
- let mut file_entry = file_entry. clone ( ) ;
320
- file_entry. similarity = match similarity {
321
- 0 => Similarity :: VeryHigh ,
322
- 1 => Similarity :: High ,
323
- 2 => Similarity :: Medium ,
324
- 3 => Similarity :: Small ,
325
- _ => panic ! ( "0-3 similarity levels are allowed, check if not added more." ) ,
326
- } ;
327
- for similarity_struct in vec_similarity_struct. iter_mut ( ) {
328
- similarity_struct. similar_images . push ( file_entry. clone ( ) ) ;
329
- }
336
+ if let Some ( vec_file_entry) = hashes_to_check. get ( * similar_hash) {
337
+ vector_of_similar_images. append (
338
+ & mut ( vec_file_entry
339
+ . iter ( )
340
+ . map ( |fe| FileEntry {
341
+ path : fe. path . clone ( ) ,
342
+ size : fe. size ,
343
+ dimensions : fe. dimensions . clone ( ) ,
344
+ modified_date : fe. modified_date ,
345
+ similarity : match similarity {
346
+ 0 => Similarity :: VeryHigh ,
347
+ 1 => Similarity :: High ,
348
+ 2 => Similarity :: Medium ,
349
+ 3 => Similarity :: Small ,
350
+ _ => panic ! ( "0-3 similarity levels are allowed, check if not added more." ) ,
351
+ } ,
352
+ } )
353
+ . collect :: < Vec < _ > > ( ) ) ,
354
+ ) ;
355
+ hashes_to_check. remove ( * similar_hash) ;
330
356
}
331
357
}
332
- for similarity_struct in vec_similarity_struct. iter_mut ( ) {
333
- similarity_struct. similar_images . sort_by ( |x, y| y. similarity . cmp ( & x. similarity ) ) ;
334
- }
335
- new_vector. append ( & mut vec_similarity_struct) ;
358
+ new_vector. push ( ( * vector_of_similar_images) . to_owned ( ) ) ;
336
359
}
337
360
338
361
self . similar_vectors = new_vector;
339
362
340
- #[ allow( clippy:: blocks_in_if_conditions) ]
341
- Common :: print_time ( hash_map_modification, SystemTime :: now ( ) , "hash_map_modification(internal)" . to_string ( ) ) ;
342
- Common :: print_time ( start_time, SystemTime :: now ( ) , "check_for_similar_images" . to_string ( ) ) ;
363
+ Common :: print_time ( hash_map_modification, SystemTime :: now ( ) , "sort_images" . to_string ( ) ) ;
343
364
true
344
365
}
345
366
@@ -413,13 +434,13 @@ impl SaveResults for SimilarImages {
413
434
if !self . similar_vectors . is_empty ( ) {
414
435
write ! ( file, "{} images which have similar friends\n \n " , self . similar_vectors. len( ) ) . unwrap ( ) ;
415
436
416
- for struct_similar in self . similar_vectors . iter ( ) {
417
- writeln ! ( file, "Image {:?} have {} similar images" , struct_similar. base_image. path, struct_similar. similar_images. len( ) ) . unwrap ( ) ;
418
- for similar_picture in struct_similar. similar_images . iter ( ) {
419
- writeln ! ( file, "{:?} - Similarity Level: {}" , similar_picture. path, get_string_from_similarity( & similar_picture. similarity) ) . unwrap ( ) ;
420
- }
421
- writeln ! ( file) . unwrap ( ) ;
422
- }
437
+ // for struct_similar in self.similar_vectors.iter() {
438
+ // writeln!(file, "Image {:?} have {} similar images", struct_similar.base_image.path, struct_similar.similar_images.len()).unwrap();
439
+ // for similar_picture in struct_similar.similar_images.iter() {
440
+ // writeln!(file, "{:?} - Similarity Level: {}", similar_picture.path, get_string_from_similarity(&similar_picture.similarity)).unwrap();
441
+ // }
442
+ // writeln!(file).unwrap();
443
+ // }
423
444
} else {
424
445
write ! ( file, "Not found any similar images." ) . unwrap ( ) ;
425
446
}
@@ -432,6 +453,19 @@ impl PrintResults for SimilarImages {
432
453
fn print_results ( & self ) {
433
454
if !self . similar_vectors . is_empty ( ) {
434
455
println ! ( "Found {} images which have similar friends" , self . similar_vectors. len( ) ) ;
456
+
457
+ for vec_file_entry in & self . similar_vectors {
458
+ for file_entry in vec_file_entry {
459
+ println ! (
460
+ "{} - {} - {} - {}" ,
461
+ file_entry. path. display( ) ,
462
+ file_entry. dimensions,
463
+ file_entry. size. file_size( options:: BINARY ) . unwrap( ) ,
464
+ get_string_from_similarity( & file_entry. similarity)
465
+ ) ;
466
+ }
467
+ println ! ( ) ;
468
+ }
435
469
}
436
470
}
437
471
}
0 commit comments