QuickImage – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 using QuickImage.Database;
2 using Shipwreck.Phash;
3 using System;
4 using System.Collections;
5 using System.Collections.Generic;
6 using System.Linq;
7 using System.Text;
8 using System.Threading;
9 using System.Threading.Tasks;
10 using System.Windows.Forms;
11  
12 namespace QuickImage.ImageListViewSorters
13 {
14 public class PerceptionImageListViewItemSorter : IComparer, IComparer<ListViewItem>
15 {
16 private readonly Dictionary<string, double> _score;
17 private readonly Dictionary<string, Digest> _digest;
18 private readonly QuickImageDatabase _quickImageDatabase;
19 private readonly CancellationToken _cancellationToken;
20 private readonly IReadOnlyList<ListViewItem> _listViewItems;
21 private readonly TaskCompletionSource<object> _initializedTaskCompletionSource;
22  
23 private PerceptionImageListViewItemSorter()
24 {
25 _score = new Dictionary<string, double>(StringComparer.Ordinal);
26 _digest = new Dictionary<string, Digest>();
27 _initializedTaskCompletionSource = new TaskCompletionSource<object>();
28 }
29 public PerceptionImageListViewItemSorter(IReadOnlyList<ListViewItem> items, QuickImageDatabase quickImageDatabase, CancellationToken cancellationToken) : this()
30 {
31 _listViewItems = items;
32 _quickImageDatabase = quickImageDatabase;
33 _cancellationToken = cancellationToken;
34  
35 Task.Run(RetrieveDigests)
36 .ContinueWith(ComputeScores)
37 .ContinueWith(task => _initializedTaskCompletionSource.TrySetResult(new { }));
38 }
39  
40 private async void RetrieveDigests()
41 {
42 await foreach (var item in _quickImageDatabase.GetAll(_cancellationToken).WithCancellation(_cancellationToken))
43 {
44 _digest.Add(item.File, item.Hash);
45 }
46 }
47  
48 private void ComputeScores(Task _)
49 {
50 var collection = new List<(ListViewItem A, ListViewItem B, double Score)>();
51  
52 foreach (var a in _listViewItems)
53 {
54 foreach (var b in _listViewItems)
55 {
56 if (a.Name == b.Name)
57 {
58 continue;
59 }
60  
61 if (!_digest.TryGetValue(a.Name, out var p) || !(p is { }) ||
62 !_digest.TryGetValue(b.Name, out var q) || !(q is { }))
63 {
64 continue;
65 }
66  
67 var score = ImagePhash.GetCrossCorrelation(p, q);
68  
69 collection.Add((a, b, score));
70 }
71 }
72  
73 collection.Sort((a, b) => b.Score.CompareTo(a.Score));
74  
75 var visit = new HashSet<string>(collection.Count);
76 foreach (var (a, b, score) in collection)
77 {
78 foreach (var imageListViewItem in new[] { a, b })
79 {
80 if (visit.Contains(imageListViewItem.Name))
81 {
82 continue;
83 }
84  
85 visit.Add(imageListViewItem.Name);
86  
87 _score.Add(imageListViewItem.Name, score);
88 }
89 }
90 }
91  
92 public int Compare(ListViewItem x, ListViewItem y)
93 {
94 _initializedTaskCompletionSource.Task.Wait(_cancellationToken);
95  
96 if (!_score.TryGetValue(x.Name, out var scoreA) || !_score.TryGetValue(y.Name, out var scoreB))
97 {
98 return 0;
99 }
100  
101 return scoreB.CompareTo(scoreA);
102 }
103  
104 public int Compare(object x, object y)
105 {
106 return Compare(x as ListViewItem, y as ListViewItem);
107 }
108 }
109 }