Browse Source

Update equality check and add ests. Fix #1116

af/octree-no-pixelmap
James Jackson-South 6 years ago
parent
commit
2e2c78b481
  1. 41
      src/ImageSharp/Primitives/DenseMatrix{T}.cs
  2. 60
      src/ImageSharp/Processing/Processors/Dithering/ErrorDither.cs
  3. 62
      src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs
  4. 20
      tests/ImageSharp.Tests/Primitives/DenseMatrixTests.cs
  5. 66
      tests/ImageSharp.Tests/Processing/Dithering/DitherTest.cs

41
src/ImageSharp/Primitives/DenseMatrix{T}.cs

@ -136,7 +136,7 @@ namespace SixLabors.ImageSharp
/// </returns>
[MethodImpl(InliningOptions.ShortMethod)]
#pragma warning disable SA1008 // Opening parenthesis should be spaced correctly
public static implicit operator T[,] (in DenseMatrix<T> data)
public static implicit operator T[,](in DenseMatrix<T> data)
#pragma warning restore SA1008 // Opening parenthesis should be spaced correctly
{
var result = new T[data.Rows, data.Columns];
@ -153,6 +153,24 @@ namespace SixLabors.ImageSharp
return result;
}
/// <summary>
/// Compares the two <see cref="DenseMatrix{T}"/> instances to determine whether they are unequal.
/// </summary>
/// <param name="left">The first source instance.</param>
/// <param name="right">The second source instance.</param>
/// <returns>The <see cref="bool"/>.</returns>
public static bool operator ==(DenseMatrix<T> left, DenseMatrix<T> right)
=> left.Equals(right);
/// <summary>
/// Compares the two <see cref="DenseMatrix{T}"/> instances to determine whether they are equal.
/// </summary>
/// <param name="left">The first source instance.</param>
/// <param name="right">The second source instance.</param>
/// <returns>The <see cref="bool"/>.</returns>
public static bool operator !=(DenseMatrix<T> left, DenseMatrix<T> right)
=> !(left == right);
/// <summary>
/// Transposes the rows and columns of the dense matrix.
/// </summary>
@ -210,15 +228,32 @@ namespace SixLabors.ImageSharp
}
/// <inheritdoc/>
public override bool Equals(object obj) => obj is DenseMatrix<T> other && this.Equals(other);
public override bool Equals(object obj)
=> obj is DenseMatrix<T> other && this.Equals(other);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(DenseMatrix<T> other) =>
this.Columns == other.Columns
&& this.Rows == other.Rows
&& this.Span.SequenceEqual(other.Span);
/// <inheritdoc/>
public override int GetHashCode() => this.Data.GetHashCode();
[MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode()
{
HashCode code = default;
code.Add(this.Columns);
code.Add(this.Rows);
Span<T> span = this.Span;
for (int i = 0; i < span.Length; i++)
{
code.Add(span[i]);
}
return code.ToHashCode();
}
}
}

60
src/ImageSharp/Processing/Processors/Dithering/ErrorDither.cs

@ -14,7 +14,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
/// An error diffusion dithering implementation.
/// <see href="http://www.efg2.com/Lab/Library/ImageProcessing/DHALF.TXT"/>
/// </summary>
public readonly partial struct ErrorDither : IDither, IEquatable<ErrorDither>
public readonly partial struct ErrorDither : IDither, IEquatable<ErrorDither>, IEquatable<IDither>
{
private readonly int offset;
private readonly DenseMatrix<float> matrix;
@ -31,6 +31,60 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
this.offset = offset;
}
/// <summary>
/// Compares the two <see cref="ErrorDither"/> instances to determine whether they are equal.
/// </summary>
/// <param name="left">The first source instance.</param>
/// <param name="right">The second source instance.</param>
/// <returns>The <see cref="bool"/>.</returns>
public static bool operator ==(IDither left, ErrorDither right)
=> right == left;
/// <summary>
/// Compares the two <see cref="ErrorDither"/> instances to determine whether they are unequal.
/// </summary>
/// <param name="left">The first source instance.</param>
/// <param name="right">The second source instance.</param>
/// <returns>The <see cref="bool"/>.</returns>
public static bool operator !=(IDither left, ErrorDither right)
=> !(right == left);
/// <summary>
/// Compares the two <see cref="ErrorDither"/> instances to determine whether they are equal.
/// </summary>
/// <param name="left">The first source instance.</param>
/// <param name="right">The second source instance.</param>
/// <returns>The <see cref="bool"/>.</returns>
public static bool operator ==(ErrorDither left, IDither right)
=> left.Equals(right);
/// <summary>
/// Compares the two <see cref="ErrorDither"/> instances to determine whether they are unequal.
/// </summary>
/// <param name="left">The first source instance.</param>
/// <param name="right">The second source instance.</param>
/// <returns>The <see cref="bool"/>.</returns>
public static bool operator !=(ErrorDither left, IDither right)
=> !(left == right);
/// <summary>
/// Compares the two <see cref="ErrorDither"/> instances to determine whether they are equal.
/// </summary>
/// <param name="left">The first source instance.</param>
/// <param name="right">The second source instance.</param>
/// <returns>The <see cref="bool"/>.</returns>
public static bool operator ==(ErrorDither left, ErrorDither right)
=> left.Equals(right);
/// <summary>
/// Compares the two <see cref="ErrorDither"/> instances to determine whether they are unequal.
/// </summary>
/// <param name="left">The first source instance.</param>
/// <param name="right">The second source instance.</param>
/// <returns>The <see cref="bool"/>.</returns>
public static bool operator !=(ErrorDither left, ErrorDither right)
=> !(left == right);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void ApplyQuantizationDither<TFrameQuantizer, TPixel>(
@ -155,6 +209,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
public bool Equals(ErrorDither other)
=> this.offset == other.offset && this.matrix.Equals(other.matrix);
/// <inheritdoc/>
public bool Equals(IDither other)
=> this.Equals((object)other);
/// <inheritdoc/>
public override int GetHashCode()
=> HashCode.Combine(this.offset, this.matrix);

62
src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs

@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
/// <summary>
/// An ordered dithering matrix with equal sides of arbitrary length
/// </summary>
public readonly partial struct OrderedDither : IDither, IEquatable<OrderedDither>
public readonly partial struct OrderedDither : IDither, IEquatable<OrderedDither>, IEquatable<IDither>
{
private readonly DenseMatrix<float> thresholdMatrix;
private readonly int modulusX;
@ -47,6 +47,60 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
this.thresholdMatrix = thresholdMatrix;
}
/// <summary>
/// Compares the two <see cref="OrderedDither"/> instances to determine whether they are equal.
/// </summary>
/// <param name="left">The first source instance.</param>
/// <param name="right">The second source instance.</param>
/// <returns>The <see cref="bool"/>.</returns>
public static bool operator ==(IDither left, OrderedDither right)
=> right == left;
/// <summary>
/// Compares the two <see cref="OrderedDither"/> instances to determine whether they are unequal.
/// </summary>
/// <param name="left">The first source instance.</param>
/// <param name="right">The second source instance.</param>
/// <returns>The <see cref="bool"/>.</returns>
public static bool operator !=(IDither left, OrderedDither right)
=> !(right == left);
/// <summary>
/// Compares the two <see cref="OrderedDither"/> instances to determine whether they are equal.
/// </summary>
/// <param name="left">The first source instance.</param>
/// <param name="right">The second source instance.</param>
/// <returns>The <see cref="bool"/>.</returns>
public static bool operator ==(OrderedDither left, IDither right)
=> left.Equals(right);
/// <summary>
/// Compares the two <see cref="OrderedDither"/> instances to determine whether they are unequal.
/// </summary>
/// <param name="left">The first source instance.</param>
/// <param name="right">The second source instance.</param>
/// <returns>The <see cref="bool"/>.</returns>
public static bool operator !=(OrderedDither left, IDither right)
=> !(left == right);
/// <summary>
/// Compares the two <see cref="OrderedDither"/> instances to determine whether they are equal.
/// </summary>
/// <param name="left">The first source instance.</param>
/// <param name="right">The second source instance.</param>
/// <returns>The <see cref="bool"/>.</returns>
public static bool operator ==(OrderedDither left, OrderedDither right)
=> left.Equals(right);
/// <summary>
/// Compares the two <see cref="OrderedDither"/> instances to determine whether they are unequal.
/// </summary>
/// <param name="left">The first source instance.</param>
/// <param name="right">The second source instance.</param>
/// <returns>The <see cref="bool"/>.</returns>
public static bool operator !=(OrderedDither left, OrderedDither right)
=> !(left == right);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void ApplyQuantizationDither<TFrameQuantizer, TPixel>(
@ -133,10 +187,16 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
=> obj is OrderedDither dither && this.Equals(dither);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public bool Equals(OrderedDither other)
=> this.thresholdMatrix.Equals(other.thresholdMatrix) && this.modulusX == other.modulusX && this.modulusY == other.modulusY;
/// <inheritdoc/>
public bool Equals(IDither other)
=> this.Equals((object)other);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public override int GetHashCode()
=> HashCode.Combine(this.thresholdMatrix, this.modulusX, this.modulusY);

20
tests/ImageSharp.Tests/Primitives/DenseMatrixTests.cs

@ -116,5 +116,25 @@ namespace SixLabors.ImageSharp.Tests.Primitives
Assert.Equal(2, transposed[1, 0]);
Assert.Equal(3, transposed[2, 0]);
}
[Fact]
public void DenseMatrixEquality()
{
var dense = new DenseMatrix<int>(3, 1);
var dense2 = new DenseMatrix<int>(3, 1);
var dense3 = new DenseMatrix<int>(1, 3);
Assert.True(dense == dense2);
Assert.False(dense != dense2);
Assert.Equal(dense, dense2);
Assert.Equal(dense, (object)dense2);
Assert.Equal(dense.GetHashCode(), dense2.GetHashCode());
Assert.False(dense == dense3);
Assert.True(dense != dense3);
Assert.NotEqual(dense, dense3);
Assert.NotEqual(dense, (object)dense3);
Assert.NotEqual(dense.GetHashCode(), dense3.GetHashCode());
}
}
}

66
tests/ImageSharp.Tests/Processing/Dithering/DitherTest.cs

@ -104,5 +104,71 @@ namespace SixLabors.ImageSharp.Tests.Processing.Binarization
Assert.Equal(this.errorDiffuser, p.Dither);
Assert.Equal(this.testPalette, p.Palette);
}
[Fact]
public void ErrorDitherEquality()
{
IDither dither = KnownDitherings.FloydSteinberg;
ErrorDither dither2 = ErrorDither.FloydSteinberg;
ErrorDither dither3 = ErrorDither.FloydSteinberg;
Assert.True(dither == dither2);
Assert.True(dither2 == dither);
Assert.False(dither != dither2);
Assert.False(dither2 != dither);
Assert.Equal(dither, dither2);
Assert.Equal(dither, (object)dither2);
Assert.Equal(dither.GetHashCode(), dither2.GetHashCode());
dither = null;
Assert.False(dither == dither2);
Assert.False(dither2 == dither);
Assert.True(dither != dither2);
Assert.True(dither2 != dither);
Assert.NotEqual(dither, dither2);
Assert.NotEqual(dither, (object)dither2);
Assert.NotEqual(dither?.GetHashCode(), dither2.GetHashCode());
Assert.True(dither2 == dither3);
Assert.True(dither3 == dither2);
Assert.False(dither2 != dither3);
Assert.False(dither3 != dither2);
Assert.Equal(dither2, dither3);
Assert.Equal(dither2, (object)dither3);
Assert.Equal(dither2.GetHashCode(), dither3.GetHashCode());
}
[Fact]
public void OrderedDitherEquality()
{
IDither dither = KnownDitherings.Bayer2x2;
OrderedDither dither2 = OrderedDither.Bayer2x2;
OrderedDither dither3 = OrderedDither.Bayer2x2;
Assert.True(dither == dither2);
Assert.True(dither2 == dither);
Assert.False(dither != dither2);
Assert.False(dither2 != dither);
Assert.Equal(dither, dither2);
Assert.Equal(dither, (object)dither2);
Assert.Equal(dither.GetHashCode(), dither2.GetHashCode());
dither = null;
Assert.False(dither == dither2);
Assert.False(dither2 == dither);
Assert.True(dither != dither2);
Assert.True(dither2 != dither);
Assert.NotEqual(dither, dither2);
Assert.NotEqual(dither, (object)dither2);
Assert.NotEqual(dither?.GetHashCode(), dither2.GetHashCode());
Assert.True(dither2 == dither3);
Assert.True(dither3 == dither2);
Assert.False(dither2 != dither3);
Assert.False(dither3 != dither2);
Assert.Equal(dither2, dither3);
Assert.Equal(dither2, (object)dither3);
Assert.Equal(dither2.GetHashCode(), dither3.GetHashCode());
}
}
}

Loading…
Cancel
Save