Browse Source

Cleanup sampler methods.

pull/35/head
James Jackson-South 9 years ago
parent
commit
9ca337acad
  1. 2
      src/ImageSharp/Filters/Convolution/DetectEdges.cs
  2. 55
      src/ImageSharp/Filters/Effects/Pixelate.cs
  3. 1
      src/ImageSharp/Filters/Processors/Convolution/Convolution2DProcessor.cs
  4. 0
      src/ImageSharp/Filters/Processors/Convolution/EdgeDetection/IEdgeDetectorProcessor.cs
  5. 2
      src/ImageSharp/Filters/Processors/Convolution/EdgeDetection/KayyaliProcessor.cs
  6. 2
      src/ImageSharp/Filters/Processors/Effects/OilPaintingProcessor.cs
  7. 2
      src/ImageSharp/Filters/Processors/Effects/PixelateProcessor.cs
  8. 1
      src/ImageSharp/Filters/Transforms/EntropyCrop.cs
  9. 12
      src/ImageSharp/IO/EndianBinaryReader.cs
  10. 130
      src/ImageSharp/Image/ImageProcessingExtensions.cs
  11. 58
      src/ImageSharp/Samplers/Processors/IImageSamplingProcessor.cs
  12. 119
      src/ImageSharp/Samplers/Processors/ImageSamplingProcessor.cs
  13. 2
      tests/ImageSharp.Tests/Processors/Filters/GaussianSharpenTest.cs
  14. 66
      tests/ImageSharp.Tests/Processors/Filters/OilPaintTest.cs
  15. 59
      tests/ImageSharp.Tests/Processors/Filters/PixelateTest.cs

2
src/ImageSharp/Filters/Convolution/DetectEdges.cs

@ -82,7 +82,7 @@ namespace ImageSharp
switch (filter)
{
case EdgeDetection.Kayyali:
processor = new KayyaliSampler<TColor, TPacked> { Grayscale = grayscale };
processor = new KayyaliProcessor<TColor, TPacked> { Grayscale = grayscale };
break;
case EdgeDetection.Kirsch:

55
src/ImageSharp/Filters/Effects/Pixelate.cs

@ -1,55 +0,0 @@
// <copyright file="Pixelate.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
using System;
using Processors;
/// <summary>
/// Extension methods for the <see cref="Image{TColor, TPacked}"/> type.
/// </summary>
public static partial class ImageExtensions
{
/// <summary>
/// Pixelates an image with the given pixel size.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="size">The size of the pixels.</param>
/// <returns>The <see cref="Image{TColor, TPacked}"/>.</returns>
public static Image<TColor, TPacked> Pixelate<TColor, TPacked>(this Image<TColor, TPacked> source, int size = 4)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
return Pixelate(source, size, source.Bounds);
}
/// <summary>
/// Pixelates an image with the given pixel size.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="size">The size of the pixels.</param>
/// <param name="rectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
/// </param>
/// <returns>The <see cref="Image{TColor, TPacked}"/>.</returns>
public static Image<TColor, TPacked> Pixelate<TColor, TPacked>(this Image<TColor, TPacked> source, int size, Rectangle rectangle)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
if (size <= 0 || size > source.Height || size > source.Width)
{
throw new ArgumentOutOfRangeException(nameof(size));
}
return source.Process(rectangle, new PixelateProcessor<TColor, TPacked>(size));
}
}
}

1
src/ImageSharp/Filters/Processors/Convolution/Convolution2DProcessor.cs

@ -56,7 +56,6 @@ namespace ImageSharp.Processors
int maxY = sourceBottom - 1;
int maxX = endX - 1;
TColor[] target = new TColor[source.Width * source.Height];
using (PixelAccessor<TColor, TPacked> sourcePixels = source.Lock())
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock<TColor, TPacked>(source.Width, source.Height))

0
src/ImageSharp/Filters/Processors/Convolution/EdgeDetection/IEdgeDetectorSampler.cs → src/ImageSharp/Filters/Processors/Convolution/EdgeDetection/IEdgeDetectorProcessor.cs

2
src/ImageSharp/Filters/Processors/Convolution/EdgeDetection/KayyaliProcessor.cs

@ -14,7 +14,7 @@ namespace ImageSharp.Processors
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
[SuppressMessage("ReSharper", "StaticMemberInGenericType", Justification = "We want to use only one instance of each array field for each generic type.")]
public class KayyaliSampler<TColor, TPacked> : EdgeDetector2DProcessor<TColor, TPacked>
public class KayyaliProcessor<TColor, TPacked> : EdgeDetector2DProcessor<TColor, TPacked>
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{

2
src/ImageSharp/Filters/Processors/Effects/OilPaintingProcessor.cs

@ -10,7 +10,7 @@ namespace ImageSharp.Processors
using System.Threading.Tasks;
/// <summary>
/// An <see cref="IImageSamplingProcessor{TColor,TPacked}"/> to apply an oil painting effect to an <see cref="Image{TColor, TPacked}"/>.
/// An <see cref="IImageFilteringProcessor{TColor,TPacked}"/> to apply an oil painting effect to an <see cref="Image{TColor, TPacked}"/>.
/// </summary>
/// <remarks>Adapted from <see href="https://softwarebydefault.com/2013/06/29/oil-painting-cartoon-filter/"/> by Dewald Esterhuizen.</remarks>
/// <typeparam name="TColor">The pixel format.</typeparam>

2
src/ImageSharp/Filters/Processors/Effects/PixelateProcessor.cs

@ -10,7 +10,7 @@ namespace ImageSharp.Processors
using System.Threading.Tasks;
/// <summary>
/// An <see cref="ImageSamplingProcessor{TColor,TPacked}"/> to pixelate the colors of an <see cref="Image{TColor, TPacked}"/>.
/// An <see cref="IImageFilteringProcessor{TColor,TPacked}"/> to pixelate the colors of an <see cref="Image{TColor, TPacked}"/>.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>

1
src/ImageSharp/Filters/Transforms/EntropyCrop.cs

@ -26,7 +26,6 @@ namespace ImageSharp
{
EntropyCropProcessor<TColor, TPacked> processor = new EntropyCropProcessor<TColor, TPacked>(threshold);
return source.Process(source.Bounds, processor);
// return source.Process(source.Width, source.Height, source.Bounds, Rectangle.Empty, processor);
}
}
}

12
src/ImageSharp/IO/EndianBinaryReader.cs

@ -42,17 +42,23 @@ namespace ImageSharp.IO
private bool disposed;
/// <summary>
/// Equivalent of System.IO.BinaryWriter, but with either endianness, depending on
/// Initializes a new instance of the <see cref="EndianBinaryReader"/> class.
/// Equivalent of <see cref="System.IO.BinaryWriter"/>, but with either endianness, depending on
/// the EndianBitConverter it is constructed with.
/// </summary>
/// <param name="bitConverter">Converter to use when reading data</param>
/// <param name="stream">Stream to read data from</param>
/// <param name="bitConverter">
/// Converter to use when reading data
/// </param>
/// <param name="stream">
/// Stream to read data from
/// </param>
public EndianBinaryReader(EndianBitConverter bitConverter, Stream stream)
: this(bitConverter, stream, Encoding.UTF8)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="EndianBinaryReader"/> class.
/// Constructs a new binary reader with the given bit converter, reading
/// to the given stream, using the given encoding.
/// </summary>

130
src/ImageSharp/Image/ImageProcessingExtensions.cs

@ -48,88 +48,6 @@ namespace ImageSharp
return PerformAction(source, (sourceImage) => processor.Apply(sourceImage, sourceRectangle));
}
/// <summary>
/// Applies the processor to the image.
/// <remarks>This method does not resize the target image.</remarks>
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="processor">The processor to apply to the image.</param>
/// <returns>The <see cref="Image{TColor, TPacked}"/>.</returns>
internal static Image<TColor, TPacked> Process<TColor, TPacked>(this Image<TColor, TPacked> source, IImageSamplingProcessor<TColor, TPacked> processor)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
return Process(source, source.Bounds, processor);
}
/// <summary>
/// Applies the processor to the image.
/// <remarks>This method does not resize the target image.</remarks>
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="sourceRectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to draw.
/// </param>
/// <param name="processor">The processors to apply to the image.</param>
/// <returns>The <see cref="Image{TColor, TPacked}"/>.</returns>
internal static Image<TColor, TPacked> Process<TColor, TPacked>(this Image<TColor, TPacked> source, Rectangle sourceRectangle, IImageSamplingProcessor<TColor, TPacked> processor)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
return PerformAction(source, true, (sourceImage, targetImage) => processor.Apply(targetImage, sourceImage, sourceRectangle));
}
/// <summary>
/// Applies the processor to the image.
/// <remarks>
/// This method resizes the image.
/// </remarks>
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>long, float.</example></typeparam>
/// <param name="source">The source image. Cannot be null.</param>
/// <param name="width">The target image width.</param>
/// <param name="height">The target image height.</param>
/// <param name="sampler">The processor to apply to the image.</param>
/// <returns>The <see cref="Image{TColor, TPacked}"/>.</returns>
internal static Image<TColor, TPacked> Process<TColor, TPacked>(this Image<TColor, TPacked> source, int width, int height, IImageSamplingProcessor<TColor, TPacked> sampler)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
return Process(source, width, height, source.Bounds, default(Rectangle), sampler);
}
/// <summary>
/// Applies the processor to the image.
/// <remarks>
/// This method does will resize the target image if the source and target rectangles are different.
/// </remarks>
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>long, float.</example></typeparam>
/// <param name="source">The source image. Cannot be null.</param>
/// <param name="width">The target image width.</param>
/// <param name="height">The target image height.</param>
/// <param name="sourceRectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to draw.
/// </param>
/// <param name="targetRectangle">
/// The <see cref="Rectangle"/> structure that specifies the location and size of the drawn image.
/// The image is scaled to fit the rectangle.
/// </param>
/// <param name="sampler">The processor to apply to the image.</param>
/// <returns>The <see cref="Image{TColor, TPacked}"/>.</returns>
internal static Image<TColor, TPacked> Process<TColor, TPacked>(this Image<TColor, TPacked> source, int width, int height, Rectangle sourceRectangle, Rectangle targetRectangle, IImageSamplingProcessor<TColor, TPacked> sampler)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
return PerformAction(source, false, (sourceImage, targetImage) => sampler.Apply(targetImage, sourceImage, width, height, targetRectangle, sourceRectangle));
}
/// <summary>
/// Performs the given action on the source image.
/// </summary>
@ -151,53 +69,5 @@ namespace ImageSharp
return source;
}
/// <summary>
/// Performs the given action on the source image.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>long, float.</example></typeparam>
/// <param name="source">The image to perform the action against.</param>
/// <param name="clone">Whether to clone the image.</param>
/// <param name="action">The <see cref="Action"/> to perform against the image.</param>
/// <returns>The <see cref="Image{TColor, TPacked}"/>.</returns>
private static Image<TColor, TPacked> PerformAction<TColor, TPacked>(Image<TColor, TPacked> source, bool clone, Action<ImageBase<TColor, TPacked>, ImageBase<TColor, TPacked>> action)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
Image<TColor, TPacked> transformedImage = clone
? new Image<TColor, TPacked>(source)
: new Image<TColor, TPacked>();
// Several properties still require copying
if (!clone)
{
transformedImage.CopyProperties(source);
}
action(source, transformedImage);
for (int i = 0; i < source.Frames.Count; i++)
{
ImageFrame<TColor, TPacked> sourceFrame = source.Frames[i];
ImageFrame<TColor, TPacked> tranformedFrame = clone
? new ImageFrame<TColor, TPacked>(sourceFrame)
: new ImageFrame<TColor, TPacked> { FrameDelay = sourceFrame.FrameDelay };
action(sourceFrame, tranformedFrame);
if (!clone)
{
transformedImage.Frames.Add(tranformedFrame);
}
else
{
transformedImage.Frames[i] = tranformedFrame;
}
}
source = transformedImage;
return source;
}
}
}

58
src/ImageSharp/Samplers/Processors/IImageSamplingProcessor.cs

@ -1,58 +0,0 @@
// <copyright file="IImageSamplingProcessor.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Processors
{
/// <summary>
/// Encapsulates methods to alter the pixels of an image. The processor creates a copy of the original image to operate on.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
public interface IImageSamplingProcessor<TColor, TPacked> : IImageProcessor
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
/// <summary>
/// Applies the process to the specified portion of the specified <see cref="ImageBase{T, TP}"/>.
/// </summary>
/// <param name="target">Target image to apply the process to.</param>
/// <param name="source">The source image. Cannot be null.</param>
/// <param name="sourceRectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to draw.
/// </param>
/// <remarks>
/// The method keeps the source image unchanged and returns the
/// the result of image processing filter as new image.
/// </remarks>
/// <exception cref="System.ArgumentNullException">
/// <paramref name="target"/> is null or <paramref name="source"/> is null.
/// </exception>
/// <exception cref="System.ArgumentException">
/// <paramref name="sourceRectangle"/> doesnt fit the dimension of the image.
/// </exception>
void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle sourceRectangle);
/// <summary>
/// Applies the process to the specified portion of the specified <see cref="ImageBase{T, TP}"/> at the specified
/// location and with the specified size.
/// </summary>
/// <param name="target">Target image to apply the process to.</param>
/// <param name="source">The source image. Cannot be null.</param>
/// <param name="width">The target width.</param>
/// <param name="height">The target height.</param>
/// <param name="targetRectangle">
/// The <see cref="Rectangle"/> structure that specifies the location and size of the drawn image.
/// The image is scaled to fit the rectangle.
/// </param>
/// <param name="sourceRectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to draw.
/// </param>
/// <remarks>
/// The method keeps the source image unchanged and returns the
/// the result of image process as new image.
/// </remarks>
void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, int width, int height, Rectangle targetRectangle, Rectangle sourceRectangle);
}
}

119
src/ImageSharp/Samplers/Processors/ImageSamplingProcessor.cs

@ -1,119 +0,0 @@
// <copyright file="ImageSamplingProcessor.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Processors
{
using System;
/// <summary>
/// Encapsulates methods to alter the pixels of an image. The processor creates a copy of the original image to operate on.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
public abstract class ImageSamplingProcessor<TColor, TPacked> : ImageProcessor<TColor, TPacked>, IImageSamplingProcessor<TColor, TPacked>
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
/// <inheritdoc/>
public void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle sourceRectangle)
{
try
{
this.OnApply(target, source, target.Bounds, sourceRectangle);
this.Apply(target, source, target.Bounds, sourceRectangle, sourceRectangle.Y, sourceRectangle.Bottom);
this.AfterApply(target, source, target.Bounds, sourceRectangle);
}
catch (Exception ex)
{
throw new ImageProcessingException($"An error occured when processing the image using {this.GetType().Name}. See the inner exception for more detail.", ex);
}
}
/// <inheritdoc/>
public void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, int width, int height, Rectangle targetRectangle = default(Rectangle), Rectangle sourceRectangle = default(Rectangle))
{
try
{
TColor[] pixels = new TColor[width * height];
target.SetPixels(width, height, pixels);
// Ensure we always have bounds.
if (sourceRectangle == Rectangle.Empty)
{
sourceRectangle = source.Bounds;
}
if (targetRectangle == Rectangle.Empty)
{
targetRectangle = target.Bounds;
}
this.OnApply(target, source, targetRectangle, sourceRectangle);
this.Apply(target, source, targetRectangle, sourceRectangle, targetRectangle.Y, targetRectangle.Bottom);
this.AfterApply(target, source, target.Bounds, sourceRectangle);
}
catch (Exception ex)
{
throw new ImageProcessingException($"An error occured when processing the image using {this.GetType().Name}. See the inner exception for more detail.", ex);
}
}
/// <summary>
/// Applies the process to the specified portion of the specified <see cref="ImageBase{TColor, TPacked}"/> at the specified location
/// and with the specified size.
/// </summary>
/// <param name="target">Target image to apply the process to.</param>
/// <param name="source">The source image. Cannot be null.</param>
/// <param name="targetRectangle">
/// The <see cref="Rectangle"/> structure that specifies the location and size of the drawn image.
/// The image is scaled to fit the rectangle.
/// </param>
/// <param name="sourceRectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to draw.
/// </param>
/// <param name="startY">The index of the row within the source image to start processing.</param>
/// <param name="endY">The index of the row within the source image to end processing.</param>
/// <remarks>
/// The method keeps the source image unchanged and returns the the result of image process as new image.
/// </remarks>
public abstract void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY);
/// <summary>
/// This method is called before the process is applied to prepare the processor.
/// </summary>
/// <param name="target">Target image to apply the process to.</param>
/// <param name="source">The source image. Cannot be null.</param>
/// <param name="targetRectangle">
/// The <see cref="Rectangle"/> structure that specifies the location and size of the drawn image.
/// The image is scaled to fit the rectangle.
/// </param>
/// <param name="sourceRectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to draw.
/// </param>
protected virtual void OnApply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle)
{
}
/// <summary>
/// This method is called after the process is applied to prepare the processor.
/// </summary>
/// <param name="target">Target image to apply the process to.</param>
/// <param name="source">The source image. Cannot be null.</param>
/// <param name="targetRectangle">
/// The <see cref="Rectangle"/> structure that specifies the location and size of the drawn image.
/// The image is scaled to fit the rectangle.
/// </param>
/// <param name="sourceRectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to draw.
/// </param>
protected virtual void AfterApply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle)
{
}
}
}

2
tests/ImageSharp.Tests/Processors/Filters/GaussianSharpenTest.cs

@ -1,4 +1,4 @@
// <copyright file="GaussianSharpenTest.cs" company="James Jackson-South">
// <copyright file="GaussianSharpenTest.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>

66
tests/ImageSharp.Tests/Processors/Filters/OilPaintTest.cs

@ -1,66 +0,0 @@
// <copyright file="OilPaintTest.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Tests
{
using System;
using System.IO;
using Xunit;
public class OilPaintTest : FileTestBase
{
public static readonly TheoryData<Tuple<int, int>> OilPaintValues
= new TheoryData<Tuple<int, int>>
{
new Tuple<int, int>(15, 10),
new Tuple<int, int>(8, 5)
};
[Theory]
[MemberData(nameof(OilPaintValues))]
public void ImageShouldApplyOilPaintFilter(Tuple<int, int> value)
{
string path = CreateOutputDirectory("OilPaint");
foreach (TestFile file in Files)
{
string filename = file.GetFileName(value);
Image image = file.CreateImage();
using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{
if (value.Item2 < image.Width && value.Item2 < image.Height)
{
image.OilPaint(value.Item1, value.Item2)
.Save(output);
}
}
}
}
[Theory]
[MemberData(nameof(OilPaintValues))]
public void ImageShouldApplyOilPaintFilterInBox(Tuple<int, int> value)
{
string path = CreateOutputDirectory("OilPaint");
foreach (TestFile file in Files)
{
string filename = file.GetFileName(value + "-InBox");
Image image = file.CreateImage();
using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{
if (value.Item2 < image.Width && value.Item2 < image.Height)
{
image.OilPaint(value.Item1, value.Item2, new Rectangle(image.Width / 4, image.Width / 4, image.Width / 2, image.Height / 2))
.Save(output);
}
}
}
}
}
}

59
tests/ImageSharp.Tests/Processors/Filters/PixelateTest.cs

@ -1,59 +0,0 @@
// <copyright file="PixelateTest.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp.Tests
{
using System.IO;
using Xunit;
public class PixelateTest : FileTestBase
{
public static readonly TheoryData<int> PixelateValues
= new TheoryData<int>
{
4 ,
8
};
[Theory]
[MemberData(nameof(PixelateValues))]
public void ImageShouldApplyPixelateFilter(int value)
{
string path = CreateOutputDirectory("Pixelate");
foreach (TestFile file in Files)
{
string filename = file.GetFileName(value);
Image image = file.CreateImage();
using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{
image.Pixelate(value)
.Save(output);
}
}
}
[Theory]
[MemberData(nameof(PixelateValues))]
public void ImageShouldApplyPixelateFilterInBox(int value)
{
string path = CreateOutputDirectory("Pixelate");
foreach (TestFile file in Files)
{
string filename = file.GetFileName(value + "-InBox");
Image image = file.CreateImage();
using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{
image.Pixelate(value, new Rectangle(10, 10, image.Width / 2, image.Height / 2))
.Save(output);
}
}
}
}
}
Loading…
Cancel
Save