Browse Source

Merge pull request #902 from SixLabors/af/extend-processor-coverage

Validating tests for Image Processors
af/merge-core
Anton Firsov 7 years ago
committed by GitHub
parent
commit
22df8298f6
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      src/ImageSharp/Common/Helpers/Vector4Utils.cs
  2. 2
      src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor.cs
  3. 2
      tests/ImageSharp.Tests/FileTestBase.cs
  4. 56
      tests/ImageSharp.Tests/Processing/Processors/Convolution/Basic1ParameterConvolutionTests.cs
  5. 44
      tests/ImageSharp.Tests/Processing/Processors/Convolution/BoxBlurTest.cs
  6. 19
      tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs
  7. 35
      tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianBlurTest.cs
  8. 40
      tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianSharpenTest.cs
  9. 162
      tests/ImageSharp.Tests/Processing/Processors/Dithering/DitherTests.cs
  10. 35
      tests/ImageSharp.Tests/Processing/Processors/Effects/BackgroundColorTest.cs
  11. 42
      tests/ImageSharp.Tests/Processing/Processors/Effects/OilPaintTest.cs
  12. 70
      tests/ImageSharp.Tests/Processing/Processors/Effects/PixelateTest.cs
  13. 57
      tests/ImageSharp.Tests/Processing/Processors/Overlays/GlowTest.cs
  14. 70
      tests/ImageSharp.Tests/Processing/Processors/Overlays/OverlayTestBase.cs
  15. 61
      tests/ImageSharp.Tests/Processing/Processors/Overlays/VignetteTest.cs
  16. 58
      tests/ImageSharp.Tests/Processing/Processors/Transforms/AutoOrientTests.cs
  17. 2
      tests/ImageSharp.Tests/Processing/Processors/Transforms/CropTest.cs
  18. 27
      tests/ImageSharp.Tests/Processing/Processors/Transforms/EntropyCropTest.cs
  19. 72
      tests/ImageSharp.Tests/Processing/Processors/Transforms/SkewTest.cs
  20. 67
      tests/ImageSharp.Tests/Processing/Processors/Transforms/SkewTests.cs
  21. 2
      tests/Images/External

2
src/ImageSharp/Common/Helpers/Vector4Utils.cs

@ -92,7 +92,7 @@ namespace SixLabors.ImageSharp
}
/// <summary>
/// Bulk variant of <see cref="Transform(ref Vector4, ref ColorMatrix)"/>
/// Bulk variant of <see cref="Transform(ref Vector4, ref ColorMatrix)"/>.
/// </summary>
/// <param name="vectors">The span of vectors</param>
/// <param name="matrix">The transformation matrix.</param>

2
src/ImageSharp/Processing/Processors/Convolution/EdgeDetector2DProcessor.cs

@ -40,7 +40,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
public DenseMatrix<float> KernelY { get; }
/// <inheritdoc/>
public bool Grayscale { get; set; }
public bool Grayscale { get; }
/// <inheritdoc />
protected override void OnFrameApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration)

2
tests/ImageSharp.Tests/FileTestBase.cs

@ -1,6 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Collections.Generic;
namespace SixLabors.ImageSharp.Tests
@ -8,6 +9,7 @@ namespace SixLabors.ImageSharp.Tests
/// <summary>
/// The test base class for reading and writing to files.
/// </summary>
[Obsolete("See: https://github.com/SixLabors/ImageSharp/issues/868")]
public abstract class FileTestBase
{
/// <summary>

56
tests/ImageSharp.Tests/Processing/Processors/Convolution/Basic1ParameterConvolutionTests.cs

@ -0,0 +1,56 @@
// // Copyright (c) Six Labors and contributors.
// // Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
using SixLabors.Primitives;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution
{
[GroupOutput("Convolution")]
public abstract class Basic1ParameterConvolutionTests
{
private static readonly ImageComparer ValidatorComparer = ImageComparer.TolerantPercentage(0.05F);
public static readonly TheoryData<int> Values = new TheoryData<int> { 3, 5 };
public static readonly string[] InputImages =
{
TestImages.Bmp.Car,
TestImages.Png.CalliphoraPartial
};
[Theory]
[WithFileCollection(nameof(InputImages), nameof(Values), PixelTypes.Rgba32)]
public void OnFullImage<TPixel>(TestImageProvider<TPixel> provider, int value)
where TPixel : struct, IPixel<TPixel>
{
provider.Utility.TestGroupName = this.GetType().Name;
provider.RunValidatingProcessorTest(
x => this.Apply(x, value),
value,
ValidatorComparer);
}
[Theory]
[WithFileCollection(nameof(InputImages), nameof(Values), PixelTypes.Rgba32)]
public void InBox<TPixel>(TestImageProvider<TPixel> provider, int value)
where TPixel : struct, IPixel<TPixel>
{
provider.Utility.TestGroupName = this.GetType().Name;
provider.RunRectangleConstrainedValidatingProcessorTest(
(x, rect) => this.Apply(x, value, rect),
value,
ValidatorComparer);
}
protected abstract void Apply<TPixel>(IImageProcessingContext<TPixel> ctx, int value)
where TPixel : struct, IPixel<TPixel>;
protected abstract void Apply<TPixel>(IImageProcessingContext<TPixel> ctx, int value, Rectangle bounds)
where TPixel : struct, IPixel<TPixel>;
}
}

44
tests/ImageSharp.Tests/Processing/Processors/Convolution/BoxBlurTest.cs

@ -1,51 +1,17 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
using SixLabors.Primitives;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution
{
public class BoxBlurTest : FileTestBase
[GroupOutput("Convolution")]
public class BoxBlurTest : Basic1ParameterConvolutionTests
{
public static readonly TheoryData<int> BoxBlurValues
= new TheoryData<int>
{
3,
5
};
[Theory]
[WithFileCollection(nameof(DefaultFiles), nameof(BoxBlurValues), DefaultPixelType)]
public void ImageShouldApplyBoxBlurFilter<TPixel>(TestImageProvider<TPixel> provider, int value)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
{
image.Mutate(x => x.BoxBlur(value));
image.DebugSave(provider, value);
}
}
[Theory]
[WithFileCollection(nameof(DefaultFiles), nameof(BoxBlurValues), DefaultPixelType)]
public void ImageShouldApplyBoxBlurFilterInBox<TPixel>(TestImageProvider<TPixel> provider, int value)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> source = provider.GetImage())
using (Image<TPixel> image = source.Clone())
{
var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2);
image.Mutate(x => x.BoxBlur(value, bounds));
image.DebugSave(provider, value);
protected override void Apply<TPixel>(IImageProcessingContext<TPixel> ctx, int value) => ctx.BoxBlur(value);
ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds);
}
}
protected override void Apply<TPixel>(IImageProcessingContext<TPixel> ctx, int value, Rectangle bounds) =>
ctx.BoxBlur(value, bounds);
}
}

19
tests/ImageSharp.Tests/Processing/Processors/Convolution/DetectEdgesTest.cs

@ -10,13 +10,16 @@ using Xunit;
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution
{
public class DetectEdgesTest : FileTestBase
[GroupOutput("Convolution")]
public class DetectEdgesTest
{
// I think our comparison is not accurate enough (nor can be) for RgbaVector.
// The image pixels are identical according to BeyondCompare.
private static readonly ImageComparer ValidatorComparer = ImageComparer.TolerantPercentage(0.0456F);
public static readonly string[] CommonTestImages = { TestImages.Png.Bike };
public static readonly string[] TestImages = { Tests.TestImages.Png.Bike };
public const PixelTypes CommonNonDefaultPixelTypes = PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.RgbaVector;
public static readonly TheoryData<EdgeDetectionOperators> DetectEdgesFilters = new TheoryData<EdgeDetectionOperators>
{
@ -33,7 +36,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution
};
[Theory]
[WithFileCollection(nameof(CommonTestImages), DefaultPixelType)]
[WithFileCollection(nameof(TestImages), PixelTypes.Rgba32)]
public void DetectEdges_WorksOnWrappedMemoryImage<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
@ -49,8 +52,8 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution
}
[Theory]
[WithTestPatternImages(nameof(DetectEdgesFilters), 100, 100, DefaultPixelType)]
[WithFileCollection(nameof(CommonTestImages), nameof(DetectEdgesFilters), DefaultPixelType)]
[WithTestPatternImages(nameof(DetectEdgesFilters), 100, 100, PixelTypes.Rgba32)]
[WithFileCollection(nameof(TestImages), nameof(DetectEdgesFilters), PixelTypes.Rgba32)]
public void DetectEdges_WorksWithAllFilters<TPixel>(TestImageProvider<TPixel> provider, EdgeDetectionOperators detector)
where TPixel : struct, IPixel<TPixel>
{
@ -63,7 +66,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution
}
[Theory]
[WithFileCollection(nameof(CommonTestImages), CommonNonDefaultPixelTypes)]
[WithFileCollection(nameof(TestImages), CommonNonDefaultPixelTypes)]
public void DetectEdges_IsNotBoundToSinglePixelType<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
@ -76,7 +79,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution
}
[Theory]
[WithFile(TestImages.Gif.Giphy, DefaultPixelType)]
[WithFile(Tests.TestImages.Gif.Giphy, PixelTypes.Rgba32)]
public void DetectEdges_IsAppliedToAllFrames<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
@ -88,7 +91,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution
}
[Theory]
[WithFileCollection(nameof(CommonTestImages), DefaultPixelType)]
[WithFileCollection(nameof(TestImages), PixelTypes.Rgba32)]
public void DetectEdges_InBox<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{

35
tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianBlurTest.cs

@ -10,37 +10,12 @@ using Xunit;
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution
{
public class GaussianBlurTest : FileTestBase
[GroupOutput("Convolution")]
public class GaussianBlurTest : Basic1ParameterConvolutionTests
{
public static readonly TheoryData<int> GaussianBlurValues = new TheoryData<int> { 3, 5 };
protected override void Apply<TPixel>(IImageProcessingContext<TPixel> ctx, int value) => ctx.GaussianBlur(value);
[Theory]
[WithFileCollection(nameof(DefaultFiles), nameof(GaussianBlurValues), DefaultPixelType)]
public void ImageShouldApplyGaussianBlurFilter<TPixel>(TestImageProvider<TPixel> provider, int value)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
{
image.Mutate(x => x.GaussianBlur(value));
image.DebugSave(provider, value);
}
}
[Theory]
[WithFileCollection(nameof(DefaultFiles), nameof(GaussianBlurValues), DefaultPixelType)]
public void ImageShouldApplyGaussianBlurFilterInBox<TPixel>(TestImageProvider<TPixel> provider, int value)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> source = provider.GetImage())
using (Image<TPixel> image = source.Clone())
{
var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2);
image.Mutate(x => x.GaussianBlur(value, bounds));
image.DebugSave(provider, value);
ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds);
}
}
protected override void Apply<TPixel>(IImageProcessingContext<TPixel> ctx, int value, Rectangle bounds) =>
ctx.GaussianBlur(value, bounds);
}
}

40
tests/ImageSharp.Tests/Processing/Processors/Convolution/GaussianSharpenTest.cs

@ -9,42 +9,12 @@ using Xunit;
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Convolution
{
public class GaussianSharpenTest : FileTestBase
[GroupOutput("Convolution")]
public class GaussianSharpenTest : Basic1ParameterConvolutionTests
{
public static readonly TheoryData<int> GaussianSharpenValues
= new TheoryData<int>
{
3,
5
};
protected override void Apply<TPixel>(IImageProcessingContext<TPixel> ctx, int value) => ctx.GaussianSharpen(value);
[Theory]
[WithFileCollection(nameof(DefaultFiles), nameof(GaussianSharpenValues), DefaultPixelType)]
public void ImageShouldApplyGaussianSharpenFilter<TPixel>(TestImageProvider<TPixel> provider, int value)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
{
image.Mutate(x => x.GaussianSharpen(value));
image.DebugSave(provider, value);
}
}
[Theory]
[WithFileCollection(nameof(DefaultFiles), nameof(GaussianSharpenValues), DefaultPixelType)]
public void ImageShouldApplyGaussianSharpenFilterInBox<TPixel>(TestImageProvider<TPixel> provider, int value)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> source = provider.GetImage())
using (var image = source.Clone())
{
var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2);
image.Mutate(x => x.GaussianSharpen(value, bounds));
image.DebugSave(provider, value);
ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds);
}
}
protected override void Apply<TPixel>(IImageProcessingContext<TPixel> ctx, int value, Rectangle bounds) =>
ctx.GaussianSharpen(value, bounds);
}
}

162
tests/ImageSharp.Tests/Processing/Processors/Dithering/DitherTests.cs

@ -2,129 +2,153 @@
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
using SixLabors.ImageSharp.Primitives;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Processing.Dithering;
using SixLabors.ImageSharp.Processing.Processors.Dithering;
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
using SixLabors.Primitives;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Binarization
{
public class DitherTests : FileTestBase
public class DitherTests
{
public static readonly string[] CommonTestImages =
{
TestImages.Png.CalliphoraPartial, TestImages.Png.Bike
};
public static readonly TheoryData<string, IOrderedDither> OrderedDitherers = new TheoryData<string, IOrderedDither>
{
{ "Bayer8x8", KnownDitherers.BayerDither8x8 },
{ "Bayer4x4", KnownDitherers.BayerDither4x4 },
{ "Ordered3x3", KnownDitherers.OrderedDither3x3 },
{ "Bayer2x2", KnownDitherers.BayerDither2x2 }
};
public static readonly TheoryData<string, IErrorDiffuser> ErrorDiffusers = new TheoryData<string, IErrorDiffuser>
{
{ "Atkinson", KnownDiffusers.Atkinson },
{ "Burks", KnownDiffusers.Burks },
{ "FloydSteinberg", KnownDiffusers.FloydSteinberg },
{ "JarvisJudiceNinke", KnownDiffusers.JarvisJudiceNinke },
{ "Sierra2", KnownDiffusers.Sierra2 },
{ "Sierra3", KnownDiffusers.Sierra3 },
{ "SierraLite", KnownDiffusers.SierraLite },
{ "StevensonArce", KnownDiffusers.StevensonArce },
{ "Stucki", KnownDiffusers.Stucki },
};
public const PixelTypes CommonNonDefaultPixelTypes =
PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.Rgb24 | PixelTypes.RgbaVector;
public static readonly string[] CommonTestImages = { TestImages.Png.CalliphoraPartial, TestImages.Png.Bike };
public static readonly TheoryData<IErrorDiffuser> ErrorDiffusers = new TheoryData<IErrorDiffuser>
{
KnownDiffusers.Atkinson,
KnownDiffusers.Burks,
KnownDiffusers.FloydSteinberg,
KnownDiffusers.JarvisJudiceNinke,
KnownDiffusers.Sierra2,
KnownDiffusers.Sierra3,
KnownDiffusers.SierraLite,
KnownDiffusers.StevensonArce,
KnownDiffusers.Stucki,
};
public static readonly TheoryData<IOrderedDither> OrderedDitherers = new TheoryData<IOrderedDither>
{
KnownDitherers.BayerDither8x8,
KnownDitherers.BayerDither4x4,
KnownDitherers.OrderedDither3x3,
KnownDitherers.BayerDither2x2
};
private static readonly ImageComparer ValidatorComparer = ImageComparer.TolerantPercentage(0.05f);
private static IOrderedDither DefaultDitherer => KnownDitherers.BayerDither4x4;
private static IErrorDiffuser DefaultErrorDiffuser => KnownDiffusers.Atkinson;
/// <summary>
/// The output is visually correct old 32bit runtime,
/// but it is very different because of floating point inaccuracies.
/// </summary>
private static readonly bool SkipAllDitherTests =
!TestEnvironment.Is64BitProcess && string.IsNullOrEmpty(TestEnvironment.NetCoreVersion);
[Theory]
[WithFileCollection(nameof(CommonTestImages), nameof(OrderedDitherers), DefaultPixelType)]
[WithTestPatternImages(nameof(OrderedDitherers), 100, 100, DefaultPixelType)]
public void DitherFilter_WorksWithAllDitherers<TPixel>(TestImageProvider<TPixel> provider, string name, IOrderedDither ditherer)
[WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Rgba32)]
public void ApplyDiffusionFilterInBox<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
if (SkipAllDitherTests)
{
image.Mutate(x => x.Dither(ditherer));
image.DebugSave(provider, name);
return;
}
provider.RunRectangleConstrainedValidatingProcessorTest(
(x, rect) => x.Diffuse(DefaultErrorDiffuser, .5F, rect),
comparer: ValidatorComparer);
}
[Theory]
[WithFileCollection(nameof(CommonTestImages), nameof(ErrorDiffusers), DefaultPixelType)]
[WithTestPatternImages(nameof(ErrorDiffusers), 100, 100, DefaultPixelType)]
public void DiffusionFilter_WorksWithAllErrorDiffusers<TPixel>(TestImageProvider<TPixel> provider, string name, IErrorDiffuser diffuser)
[WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Rgba32)]
public void ApplyDitherFilterInBox<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
if (SkipAllDitherTests)
{
image.Mutate(x => x.Diffuse(diffuser, .5F));
image.DebugSave(provider, name);
return;
}
provider.RunRectangleConstrainedValidatingProcessorTest(
(x, rect) => x.Dither(DefaultDitherer, rect),
comparer: ValidatorComparer);
}
[Theory]
[WithFile(TestImages.Png.Filter0, CommonNonDefaultPixelTypes)]
public void DitherFilter_ShouldNotDependOnSinglePixelType<TPixel>(TestImageProvider<TPixel> provider)
public void DiffusionFilter_ShouldNotDependOnSinglePixelType<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
if (SkipAllDitherTests)
{
image.Mutate(x => x.Dither(DefaultDitherer));
image.DebugSave(provider);
return;
}
// Increased tolerance because of compatibility issues on .NET 4.6.2:
var comparer = ImageComparer.TolerantPercentage(1f);
provider.RunValidatingProcessorTest(x => x.Diffuse(DefaultErrorDiffuser, 0.5f), comparer: comparer);
}
[Theory]
[WithFile(TestImages.Png.Filter0, CommonNonDefaultPixelTypes)]
public void DiffusionFilter_ShouldNotDependOnSinglePixelType<TPixel>(TestImageProvider<TPixel> provider)
[WithFileCollection(nameof(CommonTestImages), nameof(ErrorDiffusers), PixelTypes.Rgba32)]
public void DiffusionFilter_WorksWithAllErrorDiffusers<TPixel>(
TestImageProvider<TPixel> provider,
IErrorDiffuser diffuser)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
if (SkipAllDitherTests)
{
image.Mutate(x => x.Diffuse(DefaultErrorDiffuser, 0.5f));
image.DebugSave(provider);
return;
}
provider.RunValidatingProcessorTest(
x => x.Diffuse(diffuser, 0.5f),
testOutputDetails: diffuser.GetType().Name,
comparer: ValidatorComparer,
appendPixelTypeToFileName: false);
}
[Theory]
[WithFile(TestImages.Png.CalliphoraPartial, DefaultPixelType)]
public void ApplyDitherFilterInBox<TPixel>(TestImageProvider<TPixel> provider)
[WithFile(TestImages.Png.Filter0, CommonNonDefaultPixelTypes)]
public void DitherFilter_ShouldNotDependOnSinglePixelType<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> source = provider.GetImage())
using (Image<TPixel> image = source.Clone())
if (SkipAllDitherTests)
{
var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2);
image.Mutate(x => x.Dither(DefaultDitherer, bounds));
image.DebugSave(provider);
ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds);
return;
}
provider.RunValidatingProcessorTest(
x => x.Dither(DefaultDitherer),
comparer: ValidatorComparer);
}
[Theory]
[WithFile(TestImages.Png.CalliphoraPartial, DefaultPixelType)]
public void ApplyDiffusionFilterInBox<TPixel>(TestImageProvider<TPixel> provider)
[WithFileCollection(nameof(CommonTestImages), nameof(OrderedDitherers), PixelTypes.Rgba32)]
public void DitherFilter_WorksWithAllDitherers<TPixel>(
TestImageProvider<TPixel> provider,
IOrderedDither ditherer)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> source = provider.GetImage())
using (Image<TPixel> image = source.Clone())
if (SkipAllDitherTests)
{
var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2);
image.Mutate(x => x.Diffuse(DefaultErrorDiffuser, .5F, bounds));
image.DebugSave(provider);
ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds);
return;
}
provider.RunValidatingProcessorTest(
x => x.Dither(ditherer),
testOutputDetails: ditherer.GetType().Name,
comparer: ValidatorComparer,
appendPixelTypeToFileName: false);
}
}
}

35
tests/ImageSharp.Tests/Processing/Processors/Effects/BackgroundColorTest.cs

@ -10,35 +10,30 @@ using Xunit;
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Effects
{
public class BackgroundColorTest : FileTestBase
[GroupOutput("Effects")]
public class BackgroundColorTest
{
public static readonly string[] InputImages =
{
TestImages.Png.Splash,
TestImages.Png.Ducky
};
[Theory]
[WithFileCollection(nameof(DefaultFiles), DefaultPixelType)]
public void ImageShouldApplyBackgroundColorFilter<TPixel>(TestImageProvider<TPixel> provider)
[WithFileCollection(nameof(InputImages), PixelTypes.Rgba32)]
public void FullImage<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
{
image.Mutate(x => x.BackgroundColor(NamedColors<TPixel>.HotPink));
image.DebugSave(provider);
}
provider.RunValidatingProcessorTest(x => x.BackgroundColor(NamedColors<TPixel>.HotPink));
}
[Theory]
[WithFileCollection(nameof(DefaultFiles), DefaultPixelType)]
public void ImageShouldApplyBackgroundColorFilterInBox<TPixel>(TestImageProvider<TPixel> provider)
[WithFileCollection(nameof(InputImages), PixelTypes.Rgba32)]
public void InBox<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> source = provider.GetImage())
using (var image = source.Clone())
{
var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2);
image.Mutate(x => x.BackgroundColor(NamedColors<TPixel>.HotPink, bounds));
image.DebugSave(provider);
ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds);
}
provider.RunRectangleConstrainedValidatingProcessorTest(
(x, rect) => x.BackgroundColor(NamedColors<TPixel>.HotPink, rect));
}
}
}

42
tests/ImageSharp.Tests/Processing/Processors/Effects/OilPaintTest.cs

@ -10,40 +10,40 @@ using Xunit;
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Effects
{
public class OilPaintTest : FileTestBase
[GroupOutput("Effects")]
public class OilPaintTest
{
public static readonly TheoryData<int, int> OilPaintValues = new TheoryData<int, int>
{
{ 15, 10 }, { 6, 5 }
{ 15, 10 },
{ 6, 5 }
};
public static readonly string[] InputImages =
{
TestImages.Png.CalliphoraPartial,
TestImages.Bmp.Car
};
[Theory]
[WithFileCollection(nameof(DefaultFiles), nameof(OilPaintValues), DefaultPixelType)]
public void ApplyOilPaintFilter<TPixel>(TestImageProvider<TPixel> provider, int levels, int brushSize)
[WithFileCollection(nameof(InputImages), nameof(OilPaintValues), PixelTypes.Rgba32)]
public void FullImage<TPixel>(TestImageProvider<TPixel> provider, int levels, int brushSize)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
{
image.Mutate(x => x.OilPaint(levels, brushSize));
image.DebugSave(provider, string.Join("-", levels, brushSize));
}
provider.RunValidatingProcessorTest(
x => x.OilPaint(levels, brushSize),
$"{levels}-{brushSize}",
appendPixelTypeToFileName: false);
}
[Theory]
[WithFileCollection(nameof(DefaultFiles), nameof(OilPaintValues), DefaultPixelType)]
public void ApplyOilPaintFilterInBox<TPixel>(TestImageProvider<TPixel> provider, int levels, int brushSize)
[WithFileCollection(nameof(InputImages), nameof(OilPaintValues), PixelTypes.Rgba32)]
[WithTestPatternImages(nameof(OilPaintValues), 100, 100, PixelTypes.Rgba32)]
public void InBox<TPixel>(TestImageProvider<TPixel> provider, int levels, int brushSize)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> source = provider.GetImage())
using (Image<TPixel> image = source.Clone())
{
var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2);
image.Mutate(x => x.OilPaint(levels, brushSize, bounds));
image.DebugSave(provider, string.Join("-", levels, brushSize));
ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds);
}
provider.RunRectangleConstrainedValidatingProcessorTest(
(x, rect) => x.OilPaint(levels, brushSize, rect),
$"{levels}-{brushSize}");
}
}
}

70
tests/ImageSharp.Tests/Processing/Processors/Effects/PixelateTest.cs

@ -4,82 +4,32 @@
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
using SixLabors.Primitives;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Effects
{
public class PixelateTest : FileTestBase
[GroupOutput("Effects")]
public class PixelateTest
{
public static readonly TheoryData<int> PixelateValues
= new TheoryData<int>
{
4 ,
8
};
public static readonly TheoryData<int> PixelateValues = new TheoryData<int> { 4, 8 };
[Theory]
[WithTestPatternImages(nameof(PixelateValues), 320, 240, PixelTypes.Rgba32)]
public void ImageShouldApplyPixelateFilter<TPixel>(TestImageProvider<TPixel> provider, int value)
[WithFile(TestImages.Png.Ducky, nameof(PixelateValues), PixelTypes.Rgba32)]
public void FullImage<TPixel>(TestImageProvider<TPixel> provider, int value)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
{
image.Mutate(x => x.Pixelate(value));
image.DebugSave(provider, value);
// Test the neigbouring pixels
for (int y = 0; y < image.Height; y += value)
{
for (int x = 0; x < image.Width; x += value)
{
TPixel source = image[x, y];
for (int pixY = y; pixY < y + value && pixY < image.Height; pixY++)
{
for (int pixX = x; pixX < x + value && pixX < image.Width; pixX++)
{
Assert.Equal(source, image[pixX, pixY]);
}
}
}
}
}
provider.RunValidatingProcessorTest(x => x.Pixelate(value), value, appendPixelTypeToFileName: false);
}
[Theory]
[WithTestPatternImages(nameof(PixelateValues), 320, 240, PixelTypes.Rgba32)]
public void ImageShouldApplyPixelateFilterInBox<TPixel>(TestImageProvider<TPixel> provider, int value)
[WithFile(TestImages.Png.CalliphoraPartial, nameof(PixelateValues), PixelTypes.Rgba32)]
public void InBox<TPixel>(TestImageProvider<TPixel> provider, int value)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> source = provider.GetImage())
using (var image = source.Clone())
{
var bounds = new Rectangle(image.Width / 4, image.Height / 4, image.Width / 2, image.Height / 2);
image.Mutate(x => x.Pixelate(value, bounds));
image.DebugSave(provider, value);
for (int y = 0; y < image.Height; y++)
{
for (int x = 0; x < image.Width; x++)
{
int tx = x;
int ty = y;
TPixel sourceColor = source[tx, ty];
if (bounds.Contains(tx, ty))
{
int sourceX = tx - ((tx - bounds.Left) % value) + (value / 2);
int sourceY = ty - ((ty - bounds.Top) % value) + (value / 2);
sourceColor = image[sourceX, sourceY];
}
Assert.Equal(sourceColor, image[tx, ty]);
}
}
ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds);
}
provider.RunRectangleConstrainedValidatingProcessorTest((x, rect) => x.Pixelate(value, rect), value);
}
}
}

57
tests/ImageSharp.Tests/Processing/Processors/Overlays/GlowTest.cs

@ -10,59 +10,14 @@ using Xunit;
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Overlays
{
public class GlowTest : FileTestBase
[GroupOutput("Overlays")]
public class GlowTest : OverlayTestBase
{
[Theory]
[WithFileCollection(nameof(DefaultFiles), DefaultPixelType)]
public void ImageShouldApplyGlowFilter<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
{
image.Mutate(x => x.Glow());
image.DebugSave(provider);
}
}
protected override void Apply<T>(IImageProcessingContext<T> ctx, T color) => ctx.Glow(color);
[Theory]
[WithFileCollection(nameof(DefaultFiles), DefaultPixelType)]
public void ImageShouldApplyGlowFilterColor<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
{
image.Mutate(x => x.Glow(NamedColors<TPixel>.Orange));
image.DebugSave(provider);
}
}
protected override void Apply<T>(IImageProcessingContext<T> ctx, float radiusX, float radiusY) =>
ctx.Glow(radiusX);
[Theory]
[WithFileCollection(nameof(DefaultFiles), DefaultPixelType)]
public void ImageShouldApplyGlowFilterRadius<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
{
image.Mutate(x => x.Glow(image.Width / 4F));
image.DebugSave(provider);
}
}
[Theory]
[WithFileCollection(nameof(DefaultFiles), DefaultPixelType)]
public void ImageShouldApplyGlowFilterInBox<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> source = provider.GetImage())
using (var image = source.Clone())
{
var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2);
image.Mutate(x => x.Glow(bounds));
image.DebugSave(provider);
ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds);
}
}
protected override void Apply<T>(IImageProcessingContext<T> ctx, Rectangle rect) => ctx.Glow(rect);
}
}

70
tests/ImageSharp.Tests/Processing/Processors/Overlays/OverlayTestBase.cs

@ -0,0 +1,70 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Reflection;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
using SixLabors.Primitives;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Overlays
{
[GroupOutput("Overlays")]
public abstract class OverlayTestBase
{
public static string[] ColorNames = { "Blue", "White" };
public static string[] InputImages = { TestImages.Png.Ducky, TestImages.Png.Splash };
private static readonly ImageComparer ValidatorComparer = ImageComparer.TolerantPercentage(0.05f);
[Theory]
[WithFileCollection(nameof(InputImages), nameof(ColorNames), PixelTypes.Rgba32)]
public void FullImage_ApplyColor<TPixel>(TestImageProvider<TPixel> provider, string colorName)
where TPixel : struct, IPixel<TPixel>
{
provider.Utility.TestGroupName = this.GetType().Name;
var f = (FieldInfo)typeof(NamedColors<TPixel>).GetMember(colorName)[0];
TPixel color = (TPixel)f.GetValue(null);
provider.RunValidatingProcessorTest(x => this.Apply(x, color), colorName, ValidatorComparer, appendPixelTypeToFileName: false);
}
[Theory]
[WithFileCollection(nameof(InputImages), PixelTypes.Rgba32)]
public void FullImage_ApplyRadius<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
provider.Utility.TestGroupName = this.GetType().Name;
provider.RunValidatingProcessorTest(
x =>
{
Size size = x.GetCurrentSize();
this.Apply(x, size.Width / 4f, size.Height / 4f);
},
comparer: ValidatorComparer,
appendPixelTypeToFileName: false);
}
[Theory]
[WithFileCollection(nameof(InputImages), PixelTypes.Rgba32)]
public void InBox<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
provider.Utility.TestGroupName = this.GetType().Name;
provider.RunRectangleConstrainedValidatingProcessorTest((x, rect) => this.Apply(x, rect));
}
protected abstract void Apply<T>(IImageProcessingContext<T> ctx, T color)
where T : struct, IPixel<T>;
protected abstract void Apply<T>(IImageProcessingContext<T> ctx, float radiusX, float radiusY)
where T : struct, IPixel<T>;
protected abstract void Apply<T>(IImageProcessingContext<T> ctx, Rectangle rect)
where T : struct, IPixel<T>;
}
}

61
tests/ImageSharp.Tests/Processing/Processors/Overlays/VignetteTest.cs

@ -1,68 +1,19 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
using SixLabors.Primitives;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Overlays
{
public class VignetteTest : FileTestBase
[GroupOutput("Overlays")]
public class VignetteTest : OverlayTestBase
{
[Theory]
[WithFileCollection(nameof(DefaultFiles), DefaultPixelType)]
public void ImageShouldApplyVignetteFilter<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
{
image.Mutate(x => x.Vignette());
image.DebugSave(provider);
}
}
[Theory]
[WithFileCollection(nameof(DefaultFiles), DefaultPixelType)]
public void ImageShouldApplyVignetteFilterColor<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
{
image.Mutate(x => x.Vignette(NamedColors<TPixel>.Orange));
image.DebugSave(provider);
}
}
[Theory]
[WithFileCollection(nameof(DefaultFiles), DefaultPixelType)]
public void ImageShouldApplyVignetteFilterRadius<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
{
image.Mutate(x => x.Vignette(image.Width / 4F, image.Height / 4F));
image.DebugSave(provider);
}
}
[Theory]
[WithFileCollection(nameof(DefaultFiles), DefaultPixelType)]
public void ImageShouldApplyVignetteFilterInBox<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> source = provider.GetImage())
using (var image = source.Clone())
{
var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2);
protected override void Apply<T>(IImageProcessingContext<T> ctx, T color) => ctx.Vignette(color);
image.Mutate(x => x.Vignette(bounds));
image.DebugSave(provider);
protected override void Apply<T>(IImageProcessingContext<T> ctx, float radiusX, float radiusY) =>
ctx.Vignette(radiusX, radiusY);
ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds);
}
}
protected override void Apply<T>(IImageProcessingContext<T> ctx, Rectangle rect) => ctx.Vignette(rect);
}
}

58
tests/ImageSharp.Tests/Processing/Processors/Transforms/AutoOrientTests.cs

@ -6,27 +6,16 @@ using SixLabors.ImageSharp.Metadata.Profiles.Exif;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder;
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms
{
public class AutoOrientTests : FileTestBase
[GroupOutput("Transforms")]
public class AutoOrientTests
{
public static readonly string[] FlipFiles = { TestImages.Bmp.F };
public static readonly TheoryData<RotateMode, FlipMode, ushort> OrientationValues
= new TheoryData<RotateMode, FlipMode, ushort>
{
{ RotateMode.None, FlipMode.None, 0 },
{ RotateMode.None, FlipMode.None, 1 },
{ RotateMode.None, FlipMode.Horizontal, 2 },
{ RotateMode.Rotate180, FlipMode.None, 3 },
{ RotateMode.Rotate180, FlipMode.Horizontal, 4 },
{ RotateMode.Rotate90, FlipMode.Horizontal, 5 },
{ RotateMode.Rotate270, FlipMode.None, 6 },
{ RotateMode.Rotate90, FlipMode.Vertical, 7 },
{ RotateMode.Rotate90, FlipMode.None, 8 },
};
public const string FlipTestFile = TestImages.Bmp.F;
public static readonly TheoryData<ExifDataType, byte[]> InvalidOrientationValues
= new TheoryData<ExifDataType, byte[]>
@ -38,27 +27,38 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms
{ ExifDataType.SignedLong, BitConverter.GetBytes((int) 5) }
};
public static readonly TheoryData<ushort> ExifOrientationValues = new TheoryData<ushort>()
{
0,
1,
2,
3,
4,
5,
6,
7,
8
};
[Theory]
[WithFileCollection(nameof(FlipFiles), nameof(OrientationValues), DefaultPixelType)]
public void ImageShouldAutoRotate<TPixel>(TestImageProvider<TPixel> provider, RotateMode rotateType, FlipMode flipType, ushort orientation)
[WithFile(FlipTestFile, nameof(ExifOrientationValues), PixelTypes.Rgba32)]
public void AutoOrient_WorksForAllExifOrientations<TPixel>(TestImageProvider<TPixel> provider, ushort orientation)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
{
image.Metadata.ExifProfile = new ExifProfile();
image.Metadata.ExifProfile.SetValue(ExifTag.Orientation, orientation);
image.Mutate(x => x.RotateFlip(rotateType, flipType));
image.DebugSave(provider, string.Join("_", rotateType, flipType, orientation, "1_before"));
image.Mutate(x => x.AutoOrient());
image.DebugSave(provider, string.Join("_", rotateType, flipType, orientation, "2_after"));
image.DebugSave(provider, orientation, appendPixelTypeToFileName: false);
image.CompareToReferenceOutput(provider, orientation, appendPixelTypeToFileName: false);
}
}
[Theory]
[WithFileCollection(nameof(FlipFiles), nameof(InvalidOrientationValues), DefaultPixelType)]
public void ImageShouldAutoRotateInvalidValues<TPixel>(TestImageProvider<TPixel> provider, ExifDataType dataType, byte[] orientation)
[WithFile(FlipTestFile, nameof(InvalidOrientationValues), PixelTypes.Rgba32)]
public void AutoOrient_WorksWithCorruptExifData<TPixel>(TestImageProvider<TPixel> provider, ExifDataType dataType, byte[] orientation)
where TPixel : struct, IPixel<TPixel>
{
var profile = new ExifProfile();
@ -72,11 +72,19 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms
bytes[18] = (byte)dataType;
// Change the number of components
bytes[20] = 1;
byte[] orientationCodeData = new byte[8];
Array.Copy(orientation, orientationCodeData, orientation.Length);
ulong orientationCode = BitConverter.ToUInt64(orientationCodeData, 0);
using (Image<TPixel> image = provider.GetImage())
using (Image<TPixel> reference = image.Clone())
{
image.Metadata.ExifProfile = new ExifProfile(bytes);
image.Mutate(x => x.AutoOrient());
image.DebugSave(provider, $"{dataType}-{orientationCode}", appendPixelTypeToFileName: false);
ImageComparer.Exact.VerifySimilarity(image, reference);
}
}
}

2
tests/ImageSharp.Tests/Processing/Processors/Transforms/CropTest.cs

@ -13,7 +13,7 @@ using Xunit;
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms
{
[GroupOutput("Transforms")]
public class CropTest : FileTestBase
public class CropTest
{
[Theory]
[WithTestPatternImages(70, 30, PixelTypes.Rgba32, 0, 0, 70, 30)]

27
tests/ImageSharp.Tests/Processing/Processors/Transforms/EntropyCropTest.cs

@ -7,25 +7,24 @@ using Xunit;
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms
{
public class EntropyCropTest : FileTestBase
[GroupOutput("Transforms")]
public class EntropyCropTest
{
public static readonly TheoryData<float> EntropyCropValues
= new TheoryData<float>
{
.25F,
.75F
};
public static readonly TheoryData<float> EntropyCropValues = new TheoryData<float> { .25F, .75F };
public static readonly string[] InputImages =
{
TestImages.Png.Ducky,
TestImages.Jpeg.Baseline.Jpeg400,
TestImages.Jpeg.Baseline.MultiScanBaselineCMYK
};
[Theory]
[WithFileCollection(nameof(DefaultFiles), nameof(EntropyCropValues), DefaultPixelType)]
public void ImageShouldEntropyCrop<TPixel>(TestImageProvider<TPixel> provider, float value)
[WithFileCollection(nameof(InputImages), nameof(EntropyCropValues), PixelTypes.Rgba32)]
public void EntropyCrop<TPixel>(TestImageProvider<TPixel> provider, float value)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
{
image.Mutate(x => x.EntropyCrop(value));
image.DebugSave(provider, value);
}
provider.RunValidatingProcessorTest(x => x.EntropyCrop(value), value, appendPixelTypeToFileName: false);
}
}
}

72
tests/ImageSharp.Tests/Processing/Processors/Transforms/SkewTest.cs

@ -1,72 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Collections.Generic;
using System.Reflection;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Processing.Processors.Transforms;
using SixLabors.ImageSharp.PixelFormats;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms
{
public class SkewTest : FileTestBase
{
public static readonly TheoryData<float, float> SkewValues
= new TheoryData<float, float>
{
{ 20, 10 },
{ -20, -10 }
};
public static readonly List<string> ResamplerNames
= new List<string>
{
nameof(KnownResamplers.Bicubic),
nameof(KnownResamplers.Box),
nameof(KnownResamplers.CatmullRom),
nameof(KnownResamplers.Hermite),
nameof(KnownResamplers.Lanczos2),
nameof(KnownResamplers.Lanczos3),
nameof(KnownResamplers.Lanczos5),
nameof(KnownResamplers.Lanczos8),
nameof(KnownResamplers.MitchellNetravali),
nameof(KnownResamplers.NearestNeighbor),
nameof(KnownResamplers.Robidoux),
nameof(KnownResamplers.RobidouxSharp),
nameof(KnownResamplers.Spline),
nameof(KnownResamplers.Triangle),
nameof(KnownResamplers.Welch),
};
[Theory]
[WithTestPatternImages(nameof(SkewValues), 100, 50, DefaultPixelType)]
public void ImageShouldSkew<TPixel>(TestImageProvider<TPixel> provider, float x, float y)
where TPixel : struct, IPixel<TPixel>
{
using (Image<TPixel> image = provider.GetImage())
{
image.Mutate(i => i.Skew(x, y));
image.DebugSave(provider, string.Join("_", x, y));
}
}
[Theory]
[WithTestPatternImages(nameof(SkewValues), 100, 50, DefaultPixelType)]
public void ImageShouldSkewWithSampler<TPixel>(TestImageProvider<TPixel> provider, float x, float y)
where TPixel : struct, IPixel<TPixel>
{
foreach (string resamplerName in ResamplerNames)
{
IResampler sampler = TestUtils.GetResampler(resamplerName);
using (Image<TPixel> image = provider.GetImage())
{
image.Mutate(i => i.Skew(x, y, sampler));
image.DebugSave(provider, string.Join("_", x, y, resamplerName));
}
}
}
}
}

67
tests/ImageSharp.Tests/Processing/Processors/Transforms/SkewTests.cs

@ -0,0 +1,67 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Processing.Processors.Transforms;
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms
{
[GroupOutput("Transforms")]
public class SkewTests
{
private const PixelTypes CommonPixelTypes = PixelTypes.Bgra32 | PixelTypes.Rgb24;
public static readonly string[] ResamplerNames = new[]
{
nameof(KnownResamplers.Bicubic),
nameof(KnownResamplers.Box),
nameof(KnownResamplers.CatmullRom),
nameof(KnownResamplers.Hermite),
nameof(KnownResamplers.Lanczos2),
nameof(KnownResamplers.Lanczos3),
nameof(KnownResamplers.Lanczos5),
nameof(KnownResamplers.Lanczos8),
nameof(KnownResamplers.MitchellNetravali),
nameof(KnownResamplers.NearestNeighbor),
nameof(KnownResamplers.Robidoux),
nameof(KnownResamplers.RobidouxSharp),
nameof(KnownResamplers.Spline),
nameof(KnownResamplers.Triangle),
nameof(KnownResamplers.Welch),
};
public static readonly TheoryData<float, float> SkewValues = new TheoryData<float, float>
{
{ 20, 10 },
{ -20, -10 }
};
private static readonly ImageComparer ValidatorComparer = ImageComparer.TolerantPercentage(0.01f);
[Theory]
[WithTestPatternImages(nameof(SkewValues), 100, 50, CommonPixelTypes)]
public void Skew_IsNotBoundToSinglePixelType<TPixel>(TestImageProvider<TPixel> provider, float x, float y)
where TPixel : struct, IPixel<TPixel>
{
provider.RunValidatingProcessorTest(ctx => ctx.Skew(x, y), $"{x}_{y}", ValidatorComparer);
}
[Theory]
[WithFile(TestImages.Png.Ducky, nameof(ResamplerNames), PixelTypes.Rgba32)]
public void Skew_WorksWithAllResamplers<TPixel>(TestImageProvider<TPixel> provider, string resamplerName)
where TPixel : struct, IPixel<TPixel>
{
IResampler sampler = TestUtils.GetResampler(resamplerName);
provider.RunValidatingProcessorTest(
x => x.Skew(21, 32, sampler),
resamplerName,
comparer: ValidatorComparer,
appendPixelTypeToFileName: false);
}
}
}

2
tests/Images/External

@ -1 +1 @@
Subproject commit 1ca515499663e8b0b7c924a49b8d212f7447bdb0
Subproject commit c057090b4402120a83a8efe251aa5b691db9c0dc
Loading…
Cancel
Save