Browse Source

Introduce Bounce mode

pull/2060/head
Ynse Hoornenborg 4 years ago
parent
commit
8dd9d392be
  1. 10
      src/ImageSharp/Processing/Processors/Convolution/BorderWrappingMode.cs
  2. 22
      src/ImageSharp/Processing/Processors/Convolution/KernelSamplingMap.cs
  3. 117
      tests/ImageSharp.Tests/Processing/Convolution/KernelSamplingMapTest.cs

10
src/ImageSharp/Processing/Processors/Convolution/BorderWrappingMode.cs

@ -14,8 +14,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
/// <summary>Take values from the opposite edge: cdefgh|abcdefgh|abcdefg</summary>
Wrap = 1,
/// <summary>Mirror the last few border values: fedcb|abcdefgh|gfedcb</summary>
/// <remarks>Please note this mode does not repeat the very border pixel, as this gives better image quality.</remarks>
Mirror = 2
/// <summary>Mirror the last few border values: fedcba|abcdefgh|hgfedcb</summary>
/// <remarks>This Mode is similar to <see cref="Bounce"/>, but here the very border pixel is repeated.</remarks>
Mirror = 2,
/// <summary>Bounce off the border: fedcb|abcdefgh|gfedcb</summary>
/// <remarks>This Mode is similar to <see cref="Mirror"/>, but here the very border pixel is not repeated.</remarks>
Bounce = 3
}
}

22
src/ImageSharp/Processing/Processors/Convolution/KernelSamplingMap.cs

@ -114,6 +114,28 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
Numerics.Clamp(span.Slice(span.Length - affectedSize), min, max);
break;
case BorderWrappingMode.Mirror:
var min2dec = min + min - 1;
for (int i = 0; i < affectedSize; i++)
{
var value = span[i];
if (value < min)
{
span[i] = min2dec - value;
}
}
var max2inc = max + max + 1;
for (int i = span.Length - affectedSize; i < span.Length; i++)
{
var value = span[i];
if (value > max)
{
span[i] = max2inc - value;
}
}
break;
case BorderWrappingMode.Bounce:
var min2 = min + min;
for (int i = 0; i < affectedSize; i++)
{

117
tests/ImageSharp.Tests/Processing/Convolution/KernelSamplingMapTest.cs

@ -29,11 +29,11 @@ namespace SixLabors.ImageSharp.Tests.Processing.Convolution
}
[Fact]
public void KernalSamplingMap_Kernel5Image7x7MirrorBorder()
public void KernalSamplingMap_Kernel5Image7x7BounceBorder()
{
var kernelSize = new Size(5, 5);
var bounds = new Rectangle(0, 0, 7, 7);
var mode = BorderWrappingMode.Mirror;
var mode = BorderWrappingMode.Bounce;
int[] expected =
{
2, 1, 0, 1, 2,
@ -47,6 +47,25 @@ namespace SixLabors.ImageSharp.Tests.Processing.Convolution
this.AssertOffsets(kernelSize, bounds, mode, mode, expected, expected);
}
[Fact]
public void KernalSamplingMap_Kernel5Image7x7MirrorBorder()
{
var kernelSize = new Size(5, 5);
var bounds = new Rectangle(0, 0, 7, 7);
var mode = BorderWrappingMode.Mirror;
int[] expected =
{
1, 0, 0, 1, 2,
0, 0, 1, 2, 3,
0, 1, 2, 3, 4,
1, 2, 3, 4, 5,
2, 3, 4, 5, 6,
3, 4, 5, 6, 6,
4, 5, 6, 6, 5,
};
this.AssertOffsets(kernelSize, bounds, mode, mode, expected, expected);
}
[Fact]
public void KernalSamplingMap_Kernel5Image7x7WrapBorder()
{
@ -67,11 +86,11 @@ namespace SixLabors.ImageSharp.Tests.Processing.Convolution
}
[Fact]
public void KernalSamplingMap_Kernel5Image9x9MirrorBorder()
public void KernalSamplingMap_Kernel5Image9x9BounceBorder()
{
var kernelSize = new Size(5, 5);
var bounds = new Rectangle(1, 1, 9, 9);
var mode = BorderWrappingMode.Mirror;
var mode = BorderWrappingMode.Bounce;
int[] expected =
{
3, 2, 1, 2, 3,
@ -87,6 +106,27 @@ namespace SixLabors.ImageSharp.Tests.Processing.Convolution
this.AssertOffsets(kernelSize, bounds, mode, mode, expected, expected);
}
[Fact]
public void KernalSamplingMap_Kernel5Image9x9MirrorBorder()
{
var kernelSize = new Size(5, 5);
var bounds = new Rectangle(1, 1, 9, 9);
var mode = BorderWrappingMode.Mirror;
int[] expected =
{
2, 1, 1, 2, 3,
1, 1, 2, 3, 4,
1, 2, 3, 4, 5,
2, 3, 4, 5, 6,
3, 4, 5, 6, 7,
4, 5, 6, 7, 8,
5, 6, 7, 8, 9,
6, 7, 8, 9, 9,
7, 8, 9, 9, 8,
};
this.AssertOffsets(kernelSize, bounds, mode, mode, expected, expected);
}
[Fact]
public void KernalSamplingMap_Kernel5Image9x9WrapBorder()
{
@ -128,11 +168,11 @@ namespace SixLabors.ImageSharp.Tests.Processing.Convolution
}
[Fact]
public void KernalSamplingMap_Kernel5Image7x7MirrorBorderTile()
public void KernalSamplingMap_Kernel5Image7x7BounceBorderTile()
{
var kernelSize = new Size(5, 5);
var bounds = new Rectangle(2, 2, 7, 7);
var mode = BorderWrappingMode.Mirror;
var mode = BorderWrappingMode.Bounce;
int[] expected =
{
4, 3, 2, 3, 4,
@ -146,6 +186,25 @@ namespace SixLabors.ImageSharp.Tests.Processing.Convolution
this.AssertOffsets(kernelSize, bounds, mode, mode, expected, expected);
}
[Fact]
public void KernalSamplingMap_Kernel5Image7x7MirrorBorderTile()
{
var kernelSize = new Size(5, 5);
var bounds = new Rectangle(2, 2, 7, 7);
var mode = BorderWrappingMode.Mirror;
int[] expected =
{
3, 2, 2, 3, 4,
2, 2, 3, 4, 5,
2, 3, 4, 5, 6,
3, 4, 5, 6, 7,
4, 5, 6, 7, 8,
5, 6, 7, 8, 8,
6, 7, 8, 8, 7,
};
this.AssertOffsets(kernelSize, bounds, mode, mode, expected, expected);
}
[Fact]
public void KernalSamplingMap_Kernel5Image7x7WrapBorderTile()
{
@ -185,11 +244,11 @@ namespace SixLabors.ImageSharp.Tests.Processing.Convolution
}
[Fact]
public void KernalSamplingMap_Kernel3Image7x7MirrorBorder()
public void KernalSamplingMap_Kernel3Image7x7BounceBorder()
{
var kernelSize = new Size(3, 3);
var bounds = new Rectangle(0, 0, 7, 7);
var mode = BorderWrappingMode.Mirror;
var mode = BorderWrappingMode.Bounce;
int[] expected =
{
1, 0, 1,
@ -203,6 +262,25 @@ namespace SixLabors.ImageSharp.Tests.Processing.Convolution
this.AssertOffsets(kernelSize, bounds, mode, mode, expected, expected);
}
[Fact]
public void KernalSamplingMap_Kernel3Image7x7MirrorBorder()
{
var kernelSize = new Size(3, 3);
var bounds = new Rectangle(0, 0, 7, 7);
var mode = BorderWrappingMode.Mirror;
int[] expected =
{
0, 0, 1,
0, 1, 2,
1, 2, 3,
2, 3, 4,
3, 4, 5,
4, 5, 6,
5, 6, 6,
};
this.AssertOffsets(kernelSize, bounds, mode, mode, expected, expected);
}
[Fact]
public void KernalSamplingMap_Kernel3Image7x7WrapBorder()
{
@ -242,11 +320,11 @@ namespace SixLabors.ImageSharp.Tests.Processing.Convolution
}
[Fact]
public void KernalSamplingMap_Kernel3Image7MirrorBorderTile()
public void KernalSamplingMap_Kernel3Image7BounceBorderTile()
{
var kernelSize = new Size(3, 3);
var bounds = new Rectangle(2, 2, 7, 7);
var mode = BorderWrappingMode.Mirror;
var mode = BorderWrappingMode.Bounce;
int[] expected =
{
3, 2, 3,
@ -260,6 +338,25 @@ namespace SixLabors.ImageSharp.Tests.Processing.Convolution
this.AssertOffsets(kernelSize, bounds, mode, mode, expected, expected);
}
[Fact]
public void KernalSamplingMap_Kernel3Image7MirrorBorderTile()
{
var kernelSize = new Size(3, 3);
var bounds = new Rectangle(2, 2, 7, 7);
var mode = BorderWrappingMode.Mirror;
int[] expected =
{
2, 2, 3,
2, 3, 4,
3, 4, 5,
4, 5, 6,
5, 6, 7,
6, 7, 8,
7, 8, 8,
};
this.AssertOffsets(kernelSize, bounds, mode, mode, expected, expected);
}
[Fact]
public void KernalSamplingMap_Kernel3Image7x7WrapBorderTile()
{

Loading…
Cancel
Save