mirror of https://github.com/SixLabors/ImageSharp
committed by
GitHub
44 changed files with 1261 additions and 310 deletions
@ -0,0 +1,25 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
namespace SixLabors.ImageSharp.Processing.Processors.Convolution |
|||
{ |
|||
/// <summary>
|
|||
/// Wrapping mode for the border pixels in convolution processing.
|
|||
/// </summary>
|
|||
public enum BorderWrappingMode : byte |
|||
{ |
|||
/// <summary>Repeat the border pixel value: aaaaaa|abcdefgh|hhhhhhh</summary>
|
|||
Repeat = 0, |
|||
|
|||
/// <summary>Take values from the opposite edge: cdefgh|abcdefgh|abcdefg</summary>
|
|||
Wrap = 1, |
|||
|
|||
/// <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 |
|||
} |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.IO; |
|||
using SixLabors.ImageSharp.Formats.Jpeg; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
|
|||
using Xunit; |
|||
|
|||
namespace SixLabors.ImageSharp.Tests.Formats.Jpg |
|||
{ |
|||
[Trait("Format", "Jpg")] |
|||
public partial class JpegEncoderTests |
|||
{ |
|||
[Theory] |
|||
[WithFile(TestImages.Jpeg.Issues.ValidExifArgumentNullExceptionOnEncode, PixelTypes.Rgba32)] |
|||
public void Encode_WithValidExifProfile_DoesNotThrowException<TPixel>(TestImageProvider<TPixel> provider) |
|||
where TPixel : unmanaged, IPixel<TPixel> |
|||
{ |
|||
Exception ex = Record.Exception(() => |
|||
{ |
|||
var encoder = new JpegEncoder(); |
|||
var stream = new MemoryStream(); |
|||
|
|||
using Image<TPixel> image = provider.GetImage(JpegDecoder); |
|||
image.Save(stream, encoder); |
|||
}); |
|||
|
|||
Assert.Null(ex); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,421 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using SixLabors.ImageSharp.Processing.Processors.Convolution; |
|||
using Xunit; |
|||
|
|||
namespace SixLabors.ImageSharp.Tests.Processing.Convolution |
|||
{ |
|||
[Trait("Category", "Processors")] |
|||
public class KernelSamplingMapTest |
|||
{ |
|||
[Fact] |
|||
public void KernalSamplingMap_Kernel5Image7x7RepeatBorder() |
|||
{ |
|||
var kernelSize = new Size(5, 5); |
|||
var bounds = new Rectangle(0, 0, 7, 7); |
|||
var mode = BorderWrappingMode.Repeat; |
|||
int[] expected = |
|||
{ |
|||
0, 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, 6, |
|||
}; |
|||
this.AssertOffsets(kernelSize, bounds, mode, mode, expected, expected); |
|||
} |
|||
|
|||
[Fact] |
|||
public void KernalSamplingMap_Kernel5Image7x7BounceBorder() |
|||
{ |
|||
var kernelSize = new Size(5, 5); |
|||
var bounds = new Rectangle(0, 0, 7, 7); |
|||
var mode = BorderWrappingMode.Bounce; |
|||
int[] expected = |
|||
{ |
|||
2, 1, 0, 1, 2, |
|||
1, 0, 1, 2, 3, |
|||
0, 1, 2, 3, 4, |
|||
1, 2, 3, 4, 5, |
|||
2, 3, 4, 5, 6, |
|||
3, 4, 5, 6, 5, |
|||
4, 5, 6, 5, 4, |
|||
}; |
|||
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() |
|||
{ |
|||
var kernelSize = new Size(5, 5); |
|||
var bounds = new Rectangle(0, 0, 7, 7); |
|||
var mode = BorderWrappingMode.Wrap; |
|||
int[] expected = |
|||
{ |
|||
5, 6, 0, 1, 2, |
|||
6, 0, 1, 2, 3, |
|||
0, 1, 2, 3, 4, |
|||
1, 2, 3, 4, 5, |
|||
2, 3, 4, 5, 6, |
|||
3, 4, 5, 6, 0, |
|||
4, 5, 6, 0, 1, |
|||
}; |
|||
this.AssertOffsets(kernelSize, bounds, mode, mode, expected, expected); |
|||
} |
|||
|
|||
[Fact] |
|||
public void KernalSamplingMap_Kernel5Image9x9BounceBorder() |
|||
{ |
|||
var kernelSize = new Size(5, 5); |
|||
var bounds = new Rectangle(1, 1, 9, 9); |
|||
var mode = BorderWrappingMode.Bounce; |
|||
int[] expected = |
|||
{ |
|||
3, 2, 1, 2, 3, |
|||
2, 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, 8, |
|||
7, 8, 9, 8, 7, |
|||
}; |
|||
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() |
|||
{ |
|||
var kernelSize = new Size(5, 5); |
|||
var bounds = new Rectangle(1, 1, 9, 9); |
|||
var mode = BorderWrappingMode.Wrap; |
|||
int[] expected = |
|||
{ |
|||
8, 9, 1, 2, 3, |
|||
9, 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, 1, |
|||
7, 8, 9, 1, 2, |
|||
}; |
|||
this.AssertOffsets(kernelSize, bounds, mode, mode, expected, expected); |
|||
} |
|||
|
|||
[Fact] |
|||
public void KernalSamplingMap_Kernel5Image7x7RepeatBorderTile() |
|||
{ |
|||
var kernelSize = new Size(5, 5); |
|||
var bounds = new Rectangle(2, 2, 7, 7); |
|||
var mode = BorderWrappingMode.Repeat; |
|||
int[] expected = |
|||
{ |
|||
2, 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, 8, |
|||
}; |
|||
this.AssertOffsets(kernelSize, bounds, mode, mode, expected, expected); |
|||
} |
|||
|
|||
[Fact] |
|||
public void KernalSamplingMap_Kernel5Image7x7BounceBorderTile() |
|||
{ |
|||
var kernelSize = new Size(5, 5); |
|||
var bounds = new Rectangle(2, 2, 7, 7); |
|||
var mode = BorderWrappingMode.Bounce; |
|||
int[] expected = |
|||
{ |
|||
4, 3, 2, 3, 4, |
|||
3, 2, 3, 4, 5, |
|||
2, 3, 4, 5, 6, |
|||
3, 4, 5, 6, 7, |
|||
4, 5, 6, 7, 8, |
|||
5, 6, 7, 8, 7, |
|||
6, 7, 8, 7, 6, |
|||
}; |
|||
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() |
|||
{ |
|||
var kernelSize = new Size(5, 5); |
|||
var bounds = new Rectangle(2, 2, 7, 7); |
|||
var mode = BorderWrappingMode.Wrap; |
|||
int[] expected = |
|||
{ |
|||
7, 8, 2, 3, 4, |
|||
8, 2, 3, 4, 5, |
|||
2, 3, 4, 5, 6, |
|||
3, 4, 5, 6, 7, |
|||
4, 5, 6, 7, 8, |
|||
5, 6, 7, 8, 2, |
|||
6, 7, 8, 2, 3, |
|||
}; |
|||
this.AssertOffsets(kernelSize, bounds, mode, mode, expected, expected); |
|||
} |
|||
|
|||
[Fact] |
|||
public void KernalSamplingMap_Kernel3Image7x7RepeatBorder() |
|||
{ |
|||
var kernelSize = new Size(3, 3); |
|||
var bounds = new Rectangle(0, 0, 7, 7); |
|||
var mode = BorderWrappingMode.Repeat; |
|||
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_Kernel3Image7x7BounceBorder() |
|||
{ |
|||
var kernelSize = new Size(3, 3); |
|||
var bounds = new Rectangle(0, 0, 7, 7); |
|||
var mode = BorderWrappingMode.Bounce; |
|||
int[] expected = |
|||
{ |
|||
1, 0, 1, |
|||
0, 1, 2, |
|||
1, 2, 3, |
|||
2, 3, 4, |
|||
3, 4, 5, |
|||
4, 5, 6, |
|||
5, 6, 5, |
|||
}; |
|||
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() |
|||
{ |
|||
var kernelSize = new Size(3, 3); |
|||
var bounds = new Rectangle(0, 0, 7, 7); |
|||
var mode = BorderWrappingMode.Wrap; |
|||
int[] expected = |
|||
{ |
|||
6, 0, 1, |
|||
0, 1, 2, |
|||
1, 2, 3, |
|||
2, 3, 4, |
|||
3, 4, 5, |
|||
4, 5, 6, |
|||
5, 6, 0, |
|||
}; |
|||
this.AssertOffsets(kernelSize, bounds, mode, mode, expected, expected); |
|||
} |
|||
|
|||
[Fact] |
|||
public void KernalSamplingMap_Kernel3Image7x7RepeatBorderTile() |
|||
{ |
|||
var kernelSize = new Size(3, 3); |
|||
var bounds = new Rectangle(2, 2, 7, 7); |
|||
var mode = BorderWrappingMode.Repeat; |
|||
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_Kernel3Image7BounceBorderTile() |
|||
{ |
|||
var kernelSize = new Size(3, 3); |
|||
var bounds = new Rectangle(2, 2, 7, 7); |
|||
var mode = BorderWrappingMode.Bounce; |
|||
int[] expected = |
|||
{ |
|||
3, 2, 3, |
|||
2, 3, 4, |
|||
3, 4, 5, |
|||
4, 5, 6, |
|||
5, 6, 7, |
|||
6, 7, 8, |
|||
7, 8, 7, |
|||
}; |
|||
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() |
|||
{ |
|||
var kernelSize = new Size(3, 3); |
|||
var bounds = new Rectangle(2, 2, 7, 7); |
|||
var mode = BorderWrappingMode.Wrap; |
|||
int[] expected = |
|||
{ |
|||
8, 2, 3, |
|||
2, 3, 4, |
|||
3, 4, 5, |
|||
4, 5, 6, |
|||
5, 6, 7, |
|||
6, 7, 8, |
|||
7, 8, 2, |
|||
}; |
|||
this.AssertOffsets(kernelSize, bounds, mode, mode, expected, expected); |
|||
} |
|||
|
|||
[Fact] |
|||
public void KernalSamplingMap_Kernel3Image7x5WrapBorderTile() |
|||
{ |
|||
var kernelSize = new Size(3, 3); |
|||
var bounds = new Rectangle(2, 2, 7, 5); |
|||
var mode = BorderWrappingMode.Wrap; |
|||
int[] xExpected = |
|||
{ |
|||
8, 2, 3, |
|||
2, 3, 4, |
|||
3, 4, 5, |
|||
4, 5, 6, |
|||
5, 6, 7, |
|||
6, 7, 8, |
|||
7, 8, 2, |
|||
}; |
|||
int[] yExpected = |
|||
{ |
|||
6, 2, 3, |
|||
2, 3, 4, |
|||
3, 4, 5, |
|||
4, 5, 6, |
|||
5, 6, 2, |
|||
}; |
|||
this.AssertOffsets(kernelSize, bounds, mode, mode, xExpected, yExpected); |
|||
} |
|||
|
|||
private void AssertOffsets(Size kernelSize, Rectangle bounds, BorderWrappingMode xBorderMode, BorderWrappingMode yBorderMode, int[] xExpected, int[] yExpected) |
|||
{ |
|||
// Arrange
|
|||
var map = new KernelSamplingMap(Configuration.Default.MemoryAllocator); |
|||
|
|||
// Act
|
|||
map.BuildSamplingOffsetMap(kernelSize.Height, kernelSize.Width, bounds, xBorderMode, yBorderMode); |
|||
|
|||
// Assert
|
|||
var xOffsets = map.GetColumnOffsetSpan().ToArray(); |
|||
Assert.Equal(xExpected, xOffsets); |
|||
var yOffsets = map.GetRowOffsetSpan().ToArray(); |
|||
Assert.Equal(yExpected, yOffsets); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:4d41a41180a3371d0c4a724b40a4c86f6f975dab6be9da96964a484818770394 |
|||
size 30715 |
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:d478beff34179fda26238a44434607c276f55438ee96824c5af8c0188d358d8d |
|||
size 234 |
|||
@ -1,3 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:fdf4e9b20af4168f4177d33f7f502906343bbaaae2af9b90e1531bd4452b317b |
|||
size 40765 |
|||
oid sha256:5c53967bfefcfece8cd4411740c1c394e75864ca61a7a9751df3b28e727c0205 |
|||
size 68646 |
|||
|
|||
@ -0,0 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:fdf4e9b20af4168f4177d33f7f502906343bbaaae2af9b90e1531bd4452b317b |
|||
size 40765 |
|||
Loading…
Reference in new issue