Skip to content

Commit 2f0b794

Browse files
committed
Added IDistanceStrategy interface and replaced ComputeDistance with ComputeSimilarity
A normalized distance is really a measure of similarity, hence the name. The return value has been inverted, representing %-similar instead of %-different.
1 parent c13b807 commit 2f0b794

14 files changed

+65
-31
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using System;
2+
3+
namespace Gsemac.Core.Extensions {
4+
5+
public static class DistanceStrategyExtensions {
6+
7+
// Public members
8+
9+
public static double ComputeSimilarity<T>(this IDistanceStrategy<T> distanceStrategy, T first, T second) {
10+
11+
if (distanceStrategy is null)
12+
throw new ArgumentNullException(nameof(distanceStrategy));
13+
14+
double distance = distanceStrategy.ComputeDistance(first, second, normalizeResult: true);
15+
double similarity = 1.0 - distance;
16+
17+
return Math.Max(0.0, Math.Min(similarity, 1.0));
18+
19+
}
20+
21+
}
22+
23+
}

src/Gsemac.Core/IDistanceStrategy.cs

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
namespace Gsemac.Core {
2+
3+
public interface IDistanceStrategy<T> {
4+
5+
double ComputeDistance(T first, T second, bool normalizeResult = false);
6+
7+
}
8+
9+
}

src/Gsemac.Drawing/ColorUtilities.cs

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
1-
using System.Drawing;
1+
using Gsemac.Core.Extensions;
2+
using System.Drawing;
23

34
namespace Gsemac.Drawing {
45

56
public static class ColorUtilities {
67

78
// Public members
89

9-
public static double ComputeDistance(Color first, Color second, IColorDistanceStrategy strategy = null) {
10+
public static double ComputeSimilarity(Color first, Color second, IColorDistanceStrategy strategy = null) {
1011

1112
if (strategy is null)
1213
strategy = new DeltaEColorDistanceStrategy();
1314

14-
return strategy.ComputeDistance(first, second, normalizeResult: true);
15+
return strategy.ComputeSimilarity(first, second);
1516

1617
}
1718

src/Gsemac.Drawing/DeltaEColorDistanceStrategy.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace Gsemac.Drawing {
77
public class DeltaEColorDistanceStrategy :
88
IColorDistanceStrategy {
99

10-
public double ComputeDistance(Color first, Color second, bool normalizeResult = true) {
10+
public double ComputeDistance(Color first, Color second, bool normalizeResult = false) {
1111

1212
// Algorithm from https://www.easyrgb.com/en/math.php
1313

src/Gsemac.Drawing/Extensions/ColorExtensions.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public static XyzColor ToXyz(this Color color) {
4646

4747
public static double DistanceTo(this Color color, Color other) {
4848

49-
return ColorUtilities.ComputeDistance(color, other);
49+
return ColorUtilities.ComputeSimilarity(color, other);
5050

5151
}
5252

src/Gsemac.Drawing/GreyscaleRgbDifferenceColorDistanceStrategy.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace Gsemac.Drawing {
66
public class GreyscaleRgbDifferenceColorDistanceStrategy :
77
IColorDistanceStrategy {
88

9-
public double ComputeDistance(Color first, Color second, bool normalizeResult = true) {
9+
public double ComputeDistance(Color first, Color second, bool normalizeResult = false) {
1010

1111
int grayscaleFirst = ColorUtilities.ToGreyscale(first).R;
1212
int grayscaleSecond = ColorUtilities.ToGreyscale(second).R;
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
using System.Drawing;
1+
using Gsemac.Core;
2+
using System.Drawing;
23

34
namespace Gsemac.Drawing {
45

5-
public interface IColorDistanceStrategy {
6-
7-
double ComputeDistance(Color first, Color second, bool normalizeResult = true);
8-
6+
public interface IColorDistanceStrategy :
7+
IDistanceStrategy<Color> {
98
}
109

1110
}

src/Gsemac.Drawing/Imaging/TrimImageFilter.cs

+6-4
Original file line numberDiff line numberDiff line change
@@ -123,15 +123,17 @@ public IImage Apply(IImage image) {
123123
private readonly IColorDistanceStrategy distanceAlgorithm = new DeltaEColorDistanceStrategy();
124124
private readonly int tolerance = defaultTolerance;
125125

126-
private bool CompareColors(Color first, Color second) {
126+
private bool ColorIsMatch(Color first, Color second) {
127127

128-
return ColorUtilities.ComputeDistance(first, second, distanceAlgorithm) <= tolerance / 100.0;
128+
double requiredSimilarity = 1.0 - (tolerance / 100.0);
129+
130+
return ColorUtilities.ComputeSimilarity(first, second, distanceAlgorithm) >= requiredSimilarity;
129131

130132
}
131133
private bool RowIsColor(Bitmap bitmap, int row, Color trimColor) {
132134

133135
for (int x = 0; x < bitmap.Width; ++x)
134-
if (!CompareColors(bitmap.GetPixel(x, row), trimColor))
136+
if (!ColorIsMatch(bitmap.GetPixel(x, row), trimColor))
135137
return false;
136138

137139
return true;
@@ -140,7 +142,7 @@ private bool RowIsColor(Bitmap bitmap, int row, Color trimColor) {
140142
private bool ColumnIsColor(Bitmap bitmap, int column, Color trimColor) {
141143

142144
for (int y = 0; y < bitmap.Height; ++y)
143-
if (!CompareColors(bitmap.GetPixel(column, y), trimColor))
145+
if (!ColorIsMatch(bitmap.GetPixel(column, y), trimColor))
144146
return false;
145147

146148
return true;

src/Gsemac.Drawing/RgbDifferenceColorDistanceStrategy.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace Gsemac.Drawing {
66
public class RgbDifferenceColorDistanceStrategy :
77
IColorDistanceStrategy {
88

9-
public double ComputeDistance(Color first, Color second, bool normalizeResult = true) {
9+
public double ComputeDistance(Color first, Color second, bool normalizeResult = false) {
1010

1111
int rDiff = Math.Abs(first.R - second.R);
1212
int gDiff = Math.Abs(first.G - second.G);

src/Gsemac.Text/Gsemac.Text.csproj

+4
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818
<DebugSymbols>false</DebugSymbols>
1919
</PropertyGroup>
2020

21+
<ItemGroup>
22+
<ProjectReference Include="..\Gsemac.Core\Gsemac.Core.csproj" />
23+
</ItemGroup>
24+
2125
<ItemGroup>
2226
<Compile Update="Properties\ExceptionMessages.Designer.cs">
2327
<DesignTime>True</DesignTime>
+4-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
namespace Gsemac.Text {
1+
using Gsemac.Core;
22

3-
public interface IStringDistanceStrategy {
4-
5-
double ComputeDistance(string first, string second, bool normalizeResult = true);
3+
namespace Gsemac.Text {
64

5+
public interface IStringDistanceStrategy :
6+
IDistanceStrategy<string> {
77
}
88

99
}

src/Gsemac.Text/LevenshteinStringDistanceStrategy.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ public class LevenshteinStringDistanceStrategy :
77

88
// Public members
99

10-
public double ComputeDistance(string first, string second, bool normalizeResult = true) {
10+
public double ComputeDistance(string first, string second, bool normalizeResult = false) {
1111

1212
if (first is null)
1313
throw new ArgumentNullException(nameof(first));
@@ -22,7 +22,7 @@ public double ComputeDistance(string first, string second, bool normalizeResult
2222
int maxLength = Math.Max(first.Length, second.Length);
2323

2424
return normalizeResult ?
25-
1.0 - (distance / (double)maxLength) :
25+
distance / (double)maxLength :
2626
distance;
2727

2828
}
@@ -89,4 +89,4 @@ private static int ComputeLevenshteinDistance(string str1, string str2) {
8989

9090
}
9191

92-
}
92+
}

src/Gsemac.Text/StringUtilities.cs

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Gsemac.Text.Properties;
1+
using Gsemac.Core.Extensions;
2+
using Gsemac.Text.Properties;
23
using System;
34
using System.Collections.Generic;
45
using System.Globalization;
@@ -464,12 +465,12 @@ public static StringComparer GetStringComparer(StringComparison stringComparison
464465

465466
}
466467

467-
public static double ComputeDistance(string first, string second, IStringDistanceStrategy strategy = null) {
468+
public static double ComputeSimilarity(string first, string second, IStringDistanceStrategy strategy = null) {
468469

469470
if (strategy is null)
470471
strategy = new LevenshteinStringDistanceStrategy();
471472

472-
return strategy.ComputeDistance(first, second, normalizeResult: true);
473+
return strategy.ComputeSimilarity(first, second);
473474

474475
}
475476
public static string ComputeMD5Hash(string input, Encoding encoding = null) {

tests/Gsemac.Drawing.Tests/ColorDistanceStrategyTests.cs

-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
using Microsoft.VisualStudio.TestTools.UnitTesting;
2-
using System;
3-
using System.Collections.Generic;
42
using System.Drawing;
5-
using System.Linq;
6-
using System.Text;
7-
using System.Threading.Tasks;
83

94
namespace Gsemac.Drawing.Tests {
105

0 commit comments

Comments
 (0)