Browse Source

Merge pull request #35 from JimBobSquarePants/remove-samplers

Remove samplers
af/merge-core
James Jackson-South 9 years ago
committed by GitHub
parent
commit
abcef38470
  1. 6
      src/ImageSharp/Colors/Vector4BlendTransforms.cs
  2. 29
      src/ImageSharp/Common/Extensions/ArrayExtensions.cs
  3. 4
      src/ImageSharp/Common/Extensions/ByteExtensions.cs
  4. 0
      src/ImageSharp/Filters/Convolution/BoxBlur.cs
  5. 2
      src/ImageSharp/Filters/Convolution/DetectEdges.cs
  6. 14
      src/ImageSharp/Filters/Convolution/GaussianBlur.cs
  7. 14
      src/ImageSharp/Filters/Convolution/GaussianSharpen.cs
  8. 0
      src/ImageSharp/Filters/Convolution/Options/EdgeDetection.cs
  9. 0
      src/ImageSharp/Filters/Effects/OilPainting.cs
  10. 0
      src/ImageSharp/Filters/Effects/Pixelate.cs
  11. 6
      src/ImageSharp/Filters/Processors/Convolution/BoxBlurProcessor.cs
  12. 12
      src/ImageSharp/Filters/Processors/Convolution/Convolution2DProcessor.cs
  13. 28
      src/ImageSharp/Filters/Processors/Convolution/Convolution2PassProcessor.cs
  14. 12
      src/ImageSharp/Filters/Processors/Convolution/ConvolutionProcessor.cs
  15. 8
      src/ImageSharp/Filters/Processors/Convolution/EdgeDetection/EdgeDetector2DProcessor.cs
  16. 18
      src/ImageSharp/Filters/Processors/Convolution/EdgeDetection/EdgeDetectorCompassProcessor.cs
  17. 10
      src/ImageSharp/Filters/Processors/Convolution/EdgeDetection/EdgeDetectorProcessor.cs
  18. 2
      src/ImageSharp/Filters/Processors/Convolution/EdgeDetection/IEdgeDetectorProcessor.cs
  19. 2
      src/ImageSharp/Filters/Processors/Convolution/EdgeDetection/KayyaliProcessor.cs
  20. 0
      src/ImageSharp/Filters/Processors/Convolution/EdgeDetection/KirschProcessor.cs
  21. 0
      src/ImageSharp/Filters/Processors/Convolution/EdgeDetection/Laplacian3X3Processor.cs
  22. 0
      src/ImageSharp/Filters/Processors/Convolution/EdgeDetection/Laplacian5X5Processor.cs
  23. 0
      src/ImageSharp/Filters/Processors/Convolution/EdgeDetection/LaplacianOfGaussianProcessor.cs
  24. 0
      src/ImageSharp/Filters/Processors/Convolution/EdgeDetection/PrewittProcessor.cs
  25. 0
      src/ImageSharp/Filters/Processors/Convolution/EdgeDetection/RobertsCrossProcessor.cs
  26. 0
      src/ImageSharp/Filters/Processors/Convolution/EdgeDetection/RobinsonProcessor.cs
  27. 0
      src/ImageSharp/Filters/Processors/Convolution/EdgeDetection/ScharrProcessor.cs
  28. 0
      src/ImageSharp/Filters/Processors/Convolution/EdgeDetection/SobelProcessor.cs
  29. 20
      src/ImageSharp/Filters/Processors/Convolution/GaussianBlurProcessor.cs
  30. 20
      src/ImageSharp/Filters/Processors/Convolution/GaussianSharpenProcessor.cs
  31. 16
      src/ImageSharp/Filters/Processors/Effects/OilPaintingProcessor.cs
  32. 17
      src/ImageSharp/Filters/Processors/Effects/PixelateProcessor.cs
  33. 77
      src/ImageSharp/Filters/Processors/Transforms/CompandingResizeProcessor.cs
  34. 68
      src/ImageSharp/Filters/Processors/Transforms/CropProcessor.cs
  35. 59
      src/ImageSharp/Filters/Processors/Transforms/EntropyCropProcessor.cs
  36. 56
      src/ImageSharp/Filters/Processors/Transforms/FlipProcessor.cs
  37. 25
      src/ImageSharp/Filters/Processors/Transforms/Matrix3x2Processor.cs
  38. 47
      src/ImageSharp/Filters/Processors/Transforms/ResamplingWeightedProcessor.cs
  39. 77
      src/ImageSharp/Filters/Processors/Transforms/ResizeProcessor.cs
  40. 62
      src/ImageSharp/Filters/Processors/Transforms/RotateProcessor.cs
  41. 17
      src/ImageSharp/Filters/Processors/Transforms/SkewProcessor.cs
  42. 2
      src/ImageSharp/Filters/Transforms/AutoOrient.cs
  43. 32
      src/ImageSharp/Filters/Transforms/Crop.cs
  44. 4
      src/ImageSharp/Filters/Transforms/EntropyCrop.cs
  45. 2
      src/ImageSharp/Filters/Transforms/Flip.cs
  46. 0
      src/ImageSharp/Filters/Transforms/Options/AnchorPosition.cs
  47. 0
      src/ImageSharp/Filters/Transforms/Options/FlipType.cs
  48. 0
      src/ImageSharp/Filters/Transforms/Options/Orientation.cs
  49. 0
      src/ImageSharp/Filters/Transforms/Options/ResizeHelper.cs
  50. 0
      src/ImageSharp/Filters/Transforms/Options/ResizeMode.cs
  51. 0
      src/ImageSharp/Filters/Transforms/Options/ResizeOptions.cs
  52. 0
      src/ImageSharp/Filters/Transforms/Options/RotateType.cs
  53. 0
      src/ImageSharp/Filters/Transforms/Pad.cs
  54. 0
      src/ImageSharp/Filters/Transforms/Resamplers/BicubicResampler.cs
  55. 0
      src/ImageSharp/Filters/Transforms/Resamplers/BoxResampler.cs
  56. 0
      src/ImageSharp/Filters/Transforms/Resamplers/CatmullRomResampler.cs
  57. 0
      src/ImageSharp/Filters/Transforms/Resamplers/HermiteResampler.cs
  58. 0
      src/ImageSharp/Filters/Transforms/Resamplers/IResampler.cs
  59. 0
      src/ImageSharp/Filters/Transforms/Resamplers/Lanczos2Resampler.cs
  60. 0
      src/ImageSharp/Filters/Transforms/Resamplers/Lanczos3Resampler.cs
  61. 0
      src/ImageSharp/Filters/Transforms/Resamplers/Lanczos5Resampler.cs
  62. 0
      src/ImageSharp/Filters/Transforms/Resamplers/Lanczos8Resampler.cs
  63. 0
      src/ImageSharp/Filters/Transforms/Resamplers/MitchellNetravaliResampler.cs
  64. 0
      src/ImageSharp/Filters/Transforms/Resamplers/NearestNeighborResampler.cs
  65. 0
      src/ImageSharp/Filters/Transforms/Resamplers/RobidouxResampler.cs
  66. 0
      src/ImageSharp/Filters/Transforms/Resamplers/RobidouxSharpResampler.cs
  67. 0
      src/ImageSharp/Filters/Transforms/Resamplers/SplineResampler.cs
  68. 0
      src/ImageSharp/Filters/Transforms/Resamplers/TriangleResampler.cs
  69. 0
      src/ImageSharp/Filters/Transforms/Resamplers/WelchResampler.cs
  70. 6
      src/ImageSharp/Filters/Transforms/Resize.cs
  71. 2
      src/ImageSharp/Filters/Transforms/Rotate.cs
  72. 0
      src/ImageSharp/Filters/Transforms/RotateFlip.cs
  73. 2
      src/ImageSharp/Filters/Transforms/Skew.cs
  74. 12
      src/ImageSharp/IO/EndianBinaryReader.cs
  75. 130
      src/ImageSharp/Image/ImageProcessingExtensions.cs
  76. 26
      src/ImageSharp/Image/PixelAccessor.cs
  77. 55
      src/ImageSharp/Samplers/Effects/Pixelate.cs
  78. 58
      src/ImageSharp/Samplers/Processors/IImageSamplingProcessor.cs
  79. 119
      src/ImageSharp/Samplers/Processors/ImageSamplingProcessor.cs
  80. 49
      src/ImageSharp/Samplers/Processors/Transforms/CropProcessor.cs
  81. 107
      src/ImageSharp/Samplers/Processors/Transforms/EntropyCropProcessor.cs
  82. 0
      tests/ImageSharp.Tests/Processors/Filters/AutoOrientTests.cs
  83. 0
      tests/ImageSharp.Tests/Processors/Filters/CropTest.cs
  84. 6
      tests/ImageSharp.Tests/Processors/Filters/DetectEdgesTest.cs
  85. 0
      tests/ImageSharp.Tests/Processors/Filters/EntropyCropTest.cs
  86. 0
      tests/ImageSharp.Tests/Processors/Filters/FlipTests.cs
  87. 14
      tests/ImageSharp.Tests/Processors/Filters/GaussianBlurTest.cs
  88. 14
      tests/ImageSharp.Tests/Processors/Filters/GaussianSharpenTest.cs
  89. 0
      tests/ImageSharp.Tests/Processors/Filters/OilPaintTest.cs
  90. 0
      tests/ImageSharp.Tests/Processors/Filters/PadTest.cs
  91. 0
      tests/ImageSharp.Tests/Processors/Filters/PixelateTest.cs
  92. 5
      tests/ImageSharp.Tests/Processors/Filters/ResizeTests.cs
  93. 0
      tests/ImageSharp.Tests/Processors/Filters/RotateFlipTest.cs
  94. 0
      tests/ImageSharp.Tests/Processors/Filters/RotateTest.cs
  95. 0
      tests/ImageSharp.Tests/Processors/Filters/SkewTest.cs
  96. 60
      tests/ImageSharp.Tests/Processors/Samplers/OilPaintTest.cs
  97. 59
      tests/ImageSharp.Tests/Processors/Samplers/PixelateTest.cs

6
src/ImageSharp/Colors/Vector4BlendTransforms.cs

@ -186,7 +186,7 @@ namespace ImageSharp
}
/// <summary>
/// Linearly interpolates from one vector to another based on the given weighting.
/// Linearly interpolates from one vector to another based on the given weighting.
/// The two vectors are premultiplied before operating.
/// </summary>
/// <param name="backdrop">The backdrop vector.</param>
@ -195,7 +195,7 @@ namespace ImageSharp
/// A value between 0 and 1 indicating the weight of the second source vector.
/// At amount = 0, "from" is returned, at amount = 1, "to" is returned.
/// </param>
/// <returns>
/// <returns>
/// The <see cref="Vector4"/>
/// </returns>
public static Vector4 PremultipliedLerp(Vector4 backdrop, Vector4 source, float amount)
@ -216,7 +216,7 @@ namespace ImageSharp
// Premultiply the source vector.
// Oddly premultiplying the background vector creates dark outlines when pixels
// Have low alpha values.
// Have low alpha values.
source = new Vector4(source.X, source.Y, source.Z, 1) * (source.W * amount);
// This should be implementing the following formula

29
src/ImageSharp/Common/Extensions/ArrayExtensions.cs

@ -0,0 +1,29 @@
// <copyright file="ArrayExtensions.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
/// <summary>
/// Extension methods for arrays.
/// </summary>
public static class ArrayExtensions
{
/// <summary>
/// Locks the pixel buffer providing access to the pixels.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
/// <param name="pixels">The pixel buffer.</param>
/// <param name="width">Gets the width of the image represented by the pixel buffer.</param>
/// <param name="height">The height of the image represented by the pixel buffer.</param>
/// <returns>The <see cref="PixelAccessor{TColor,TPacked}"/></returns>
public static PixelAccessor<TColor, TPacked> Lock<TColor, TPacked>(this TColor[] pixels, int width, int height)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
return new PixelAccessor<TColor, TPacked>(width, height, pixels);
}
}
}

4
src/ImageSharp/Common/Extensions/ByteExtensions.cs

@ -5,8 +5,6 @@
namespace ImageSharp
{
using System;
/// <summary>
/// Extension methods for the <see cref="byte"/> struct.
/// </summary>
@ -44,4 +42,4 @@ namespace ImageSharp
}
}
}
}
}

0
src/ImageSharp/Samplers/Convolution/BoxBlur.cs → src/ImageSharp/Filters/Convolution/BoxBlur.cs

2
src/ImageSharp/Samplers/Convolution/DetectEdges.cs → 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:

14
src/ImageSharp/Samplers/Convolution/GuassianBlur.cs → src/ImageSharp/Filters/Convolution/GaussianBlur.cs

@ -1,4 +1,4 @@
// <copyright file="GuassianBlur.cs" company="James Jackson-South">
// <copyright file="GaussianBlur.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
@ -13,22 +13,22 @@ namespace ImageSharp
public static partial class ImageExtensions
{
/// <summary>
/// Applies a Guassian blur to the image.
/// Applies a Gaussian blur to the image.
/// </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="sigma">The 'sigma' value representing the weight of the blur.</param>
/// <returns>The <see cref="Image{TColor, TPacked}"/>.</returns>
public static Image<TColor, TPacked> GuassianBlur<TColor, TPacked>(this Image<TColor, TPacked> source, float sigma = 3f)
public static Image<TColor, TPacked> GaussianBlur<TColor, TPacked>(this Image<TColor, TPacked> source, float sigma = 3f)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
return GuassianBlur(source, sigma, source.Bounds);
return GaussianBlur(source, sigma, source.Bounds);
}
/// <summary>
/// Applies a Guassian blur to the image.
/// Applies a Gaussian blur to the image.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
@ -38,11 +38,11 @@ namespace ImageSharp
/// 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> GuassianBlur<TColor, TPacked>(this Image<TColor, TPacked> source, float sigma, Rectangle rectangle)
public static Image<TColor, TPacked> GaussianBlur<TColor, TPacked>(this Image<TColor, TPacked> source, float sigma, Rectangle rectangle)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
return source.Process(rectangle, new GuassianBlurProcessor<TColor, TPacked>(sigma));
return source.Process(rectangle, new GaussianBlurProcessor<TColor, TPacked>(sigma));
}
}
}

14
src/ImageSharp/Samplers/Convolution/GuassianSharpen.cs → src/ImageSharp/Filters/Convolution/GaussianSharpen.cs

@ -1,4 +1,4 @@
// <copyright file="GuassianSharpen.cs" company="James Jackson-South">
// <copyright file="GaussianSharpen.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
@ -13,22 +13,22 @@ namespace ImageSharp
public static partial class ImageExtensions
{
/// <summary>
/// Applies a Guassian sharpening filter to the image.
/// Applies a Gaussian sharpening filter to the image.
/// </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="sigma">The 'sigma' value representing the weight of the blur.</param>
/// <returns>The <see cref="Image{TColor, TPacked}"/>.</returns>
public static Image<TColor, TPacked> GuassianSharpen<TColor, TPacked>(this Image<TColor, TPacked> source, float sigma = 3f)
public static Image<TColor, TPacked> GaussianSharpen<TColor, TPacked>(this Image<TColor, TPacked> source, float sigma = 3f)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
return GuassianSharpen(source, sigma, source.Bounds);
return GaussianSharpen(source, sigma, source.Bounds);
}
/// <summary>
/// Applies a Guassian sharpening filter to the image.
/// Applies a Gaussian sharpening filter to the image.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
@ -38,11 +38,11 @@ namespace ImageSharp
/// 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> GuassianSharpen<TColor, TPacked>(this Image<TColor, TPacked> source, float sigma, Rectangle rectangle)
public static Image<TColor, TPacked> GaussianSharpen<TColor, TPacked>(this Image<TColor, TPacked> source, float sigma, Rectangle rectangle)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
return source.Process(rectangle, new GuassianSharpenProcessor<TColor, TPacked>(sigma));
return source.Process(rectangle, new GaussianSharpenProcessor<TColor, TPacked>(sigma));
}
}
}

0
src/ImageSharp/Samplers/Convolution/Options/EdgeDetection.cs → src/ImageSharp/Filters/Convolution/Options/EdgeDetection.cs

0
src/ImageSharp/Samplers/Effects/OilPainting.cs → src/ImageSharp/Filters/Effects/OilPainting.cs

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

6
src/ImageSharp/Samplers/Processors/Convolution/BoxBlurProcessor.cs → src/ImageSharp/Filters/Processors/Convolution/BoxBlurProcessor.cs

@ -10,7 +10,7 @@ namespace ImageSharp.Processors
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
public class BoxBlurProcessor<TColor, TPacked> : ImageSamplingProcessor<TColor, TPacked>
public class BoxBlurProcessor<TColor, TPacked> : ImageFilteringProcessor<TColor, TPacked>
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
@ -43,9 +43,9 @@ namespace ImageSharp.Processors
public float[][] KernelY { get; }
/// <inheritdoc/>
public override void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
protected override void Apply(ImageBase<TColor, TPacked> source, Rectangle sourceRectangle, int startY, int endY)
{
new Convolution2PassProcessor<TColor, TPacked>(this.KernelX, this.KernelY).Apply(target, source, targetRectangle, sourceRectangle, startY, endY);
new Convolution2PassProcessor<TColor, TPacked>(this.KernelX, this.KernelY).Apply(source, sourceRectangle);
}
/// <summary>

12
src/ImageSharp/Samplers/Processors/Convolution/Convolution2DProcessor.cs → src/ImageSharp/Filters/Processors/Convolution/Convolution2DProcessor.cs

@ -14,7 +14,7 @@ namespace ImageSharp.Processors
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
public class Convolution2DProcessor<TColor, TPacked> : ImageSamplingProcessor<TColor, TPacked>
public class Convolution2DProcessor<TColor, TPacked> : ImageFilteringProcessor<TColor, TPacked>
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
@ -40,7 +40,7 @@ namespace ImageSharp.Processors
public float[][] KernelY { get; }
/// <inheritdoc/>
public override void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
protected override void Apply(ImageBase<TColor, TPacked> source, Rectangle sourceRectangle, int startY, int endY)
{
int kernelYHeight = this.KernelY.Length;
int kernelYWidth = this.KernelY[0].Length;
@ -56,8 +56,9 @@ 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())
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock<TColor, TPacked>(source.Width, source.Height))
{
Parallel.For(
startY,
@ -116,14 +117,15 @@ namespace ImageSharp.Processors
float green = (float)Math.Sqrt((gX * gX) + (gY * gY));
float blue = (float)Math.Sqrt((bX * bX) + (bY * bY));
Vector4 targetColor = targetPixels[x, y].ToVector4();
TColor packed = default(TColor);
packed.PackFromVector4(new Vector4(red, green, blue, targetColor.Z));
packed.PackFromVector4(new Vector4(red, green, blue, sourcePixels[x, y].ToVector4().W));
targetPixels[x, y] = packed;
}
}
});
}
source.SetPixels(source.Width, source.Height, target);
}
}
}

28
src/ImageSharp/Samplers/Processors/Convolution/Convolution2PassProcessor.cs → src/ImageSharp/Filters/Processors/Convolution/Convolution2PassProcessor.cs

@ -13,7 +13,7 @@ namespace ImageSharp.Processors
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
public class Convolution2PassProcessor<TColor, TPacked> : ImageSamplingProcessor<TColor, TPacked>
public class Convolution2PassProcessor<TColor, TPacked> : ImageFilteringProcessor<TColor, TPacked>
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
@ -39,29 +39,37 @@ namespace ImageSharp.Processors
public float[][] KernelY { get; }
/// <inheritdoc/>
public override void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
protected override void Apply(ImageBase<TColor, TPacked> source, Rectangle sourceRectangle, int startY, int endY)
{
float[][] kernelX = this.KernelX;
float[][] kernelY = this.KernelY;
int width = source.Width;
int height = source.Height;
ImageBase<TColor, TPacked> firstPass = new Image<TColor, TPacked>(source.Width, source.Height);
this.ApplyConvolution(firstPass, source, sourceRectangle, startY, endY, kernelX);
this.ApplyConvolution(target, firstPass, sourceRectangle, startY, endY, kernelY);
TColor[] target = new TColor[width * height];
TColor[] firstPass = new TColor[width * height];
this.ApplyConvolution(width, height, firstPass, source.Pixels, sourceRectangle, startY, endY, kernelX);
this.ApplyConvolution(width, height, target, firstPass, sourceRectangle, startY, endY, kernelY);
source.SetPixels(width, height, target);
}
/// <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="width">The image width.</param>
/// <param name="height">The image height.</param>
/// <param name="target">The target pixels to apply the process to.</param>
/// <param name="source">The source pixels. Cannot be null.</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>
/// <param name="kernel">The kernel operator.</param>
private void ApplyConvolution(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle sourceRectangle, int startY, int endY, float[][] kernel)
private void ApplyConvolution(int width, int height, TColor[] target, TColor[] source, Rectangle sourceRectangle, int startY, int endY, float[][] kernel)
{
int kernelHeight = kernel.Length;
int kernelWidth = kernel[0].Length;
@ -74,8 +82,8 @@ namespace ImageSharp.Processors
int maxY = sourceBottom - 1;
int maxX = endX - 1;
using (PixelAccessor<TColor, TPacked> sourcePixels = source.Lock())
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock())
using (PixelAccessor<TColor, TPacked> sourcePixels = source.Lock<TColor, TPacked>(width, height))
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock<TColor, TPacked>(width, height))
{
Parallel.For(
startY,

12
src/ImageSharp/Samplers/Processors/Convolution/ConvolutionProcessor.cs → src/ImageSharp/Filters/Processors/Convolution/ConvolutionProcessor.cs

@ -13,7 +13,7 @@ namespace ImageSharp.Processors
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
public class ConvolutionProcessor<TColor, TPacked> : ImageSamplingProcessor<TColor, TPacked>
public class ConvolutionProcessor<TColor, TPacked> : ImageFilteringProcessor<TColor, TPacked>
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
@ -32,7 +32,7 @@ namespace ImageSharp.Processors
public virtual float[][] KernelXY { get; }
/// <inheritdoc/>
public override void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
protected override void Apply(ImageBase<TColor, TPacked> source, Rectangle sourceRectangle, int startY, int endY)
{
float[][] kernelX = this.KernelXY;
int kernelLength = kernelX.GetLength(0);
@ -45,8 +45,9 @@ 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())
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock<TColor, TPacked>(source.Width, source.Height))
{
Parallel.For(
startY,
@ -92,14 +93,15 @@ namespace ImageSharp.Processors
float green = gX;
float blue = bX;
Vector4 targetColor = targetPixels[x, y].ToVector4();
TColor packed = default(TColor);
packed.PackFromVector4(new Vector4(red, green, blue, targetColor.Z));
packed.PackFromVector4(new Vector4(red, green, blue, sourcePixels[x, y].ToVector4().W));
targetPixels[x, y] = packed;
}
}
});
}
source.SetPixels(source.Width, source.Height, target);
}
}
}

8
src/ImageSharp/Samplers/Processors/Convolution/EdgeDetection/EdgeDetector2DProcessor.cs → src/ImageSharp/Filters/Processors/Convolution/EdgeDetection/EdgeDetector2DProcessor.cs

@ -10,7 +10,7 @@ namespace ImageSharp.Processors
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
public abstract class EdgeDetector2DProcessor<TColor, TPacked> : ImageSamplingProcessor<TColor, TPacked>, IEdgeDetectorProcessor<TColor, TPacked>
public abstract class EdgeDetector2DProcessor<TColor, TPacked> : ImageFilteringProcessor<TColor, TPacked>, IEdgeDetectorProcessor<TColor, TPacked>
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
@ -28,13 +28,13 @@ namespace ImageSharp.Processors
public bool Grayscale { get; set; }
/// <inheritdoc />
public override void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
protected override void Apply(ImageBase<TColor, TPacked> source, Rectangle sourceRectangle, int startY, int endY)
{
new Convolution2DProcessor<TColor, TPacked>(this.KernelX, this.KernelY).Apply(target, source, targetRectangle, sourceRectangle, startY, endY);
new Convolution2DProcessor<TColor, TPacked>(this.KernelX, this.KernelY).Apply(source, sourceRectangle);
}
/// <inheritdoc/>
protected override void OnApply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle)
protected override void OnApply(ImageBase<TColor, TPacked> source, Rectangle sourceRectangle)
{
if (this.Grayscale)
{

18
src/ImageSharp/Samplers/Processors/Convolution/EdgeDetection/EdgeDetectorCompassProcessor.cs → src/ImageSharp/Filters/Processors/Convolution/EdgeDetection/EdgeDetectorCompassProcessor.cs

@ -14,7 +14,7 @@ namespace ImageSharp.Processors
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
public abstract class EdgeDetectorCompassProcessor<TColor, TPacked> : ImageSamplingProcessor<TColor, TPacked>, IEdgeDetectorProcessor<TColor, TPacked>
public abstract class EdgeDetectorCompassProcessor<TColor, TPacked> : ImageFilteringProcessor<TColor, TPacked>, IEdgeDetectorProcessor<TColor, TPacked>
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
@ -62,7 +62,7 @@ namespace ImageSharp.Processors
public bool Grayscale { get; set; }
/// <inheritdoc />
public override void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
protected override void Apply(ImageBase<TColor, TPacked> source, Rectangle sourceRectangle, int startY, int endY)
{
float[][][] kernels = { this.North, this.NorthWest, this.West, this.SouthWest, this.South, this.SouthEast, this.East, this.NorthEast };
@ -76,7 +76,9 @@ namespace ImageSharp.Processors
int maxY = Math.Min(source.Height, endY);
// First run.
new ConvolutionProcessor<TColor, TPacked>(kernels[0]).Apply(target, source, targetRectangle, sourceRectangle, startY, endY);
ImageBase<TColor, TPacked> target = new Image<TColor, TPacked>(source.Width, source.Height);
target.ClonePixels(source.Width, source.Height, source.Pixels);
new ConvolutionProcessor<TColor, TPacked>(kernels[0]).Apply(target, sourceRectangle);
if (kernels.Length == 1)
{
@ -98,10 +100,14 @@ namespace ImageSharp.Processors
}
// Additional runs.
// ReSharper disable once ForCanBeConvertedToForeach
for (int i = 1; i < kernels.Length; i++)
{
// Create a clone for each pass and copy the offset pixels across.
ImageBase<TColor, TPacked> pass = new Image<TColor, TPacked>(source.Width, source.Height);
new ConvolutionProcessor<TColor, TPacked>(kernels[i]).Apply(pass, source, sourceRectangle, targetRectangle, startY, endY);
pass.ClonePixels(source.Width, source.Height, source.Pixels);
new ConvolutionProcessor<TColor, TPacked>(kernels[i]).Apply(pass, sourceRectangle);
using (PixelAccessor<TColor, TPacked> passPixels = pass.Lock())
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock())
@ -125,10 +131,12 @@ namespace ImageSharp.Processors
});
}
}
source.SetPixels(source.Width, source.Height, target.Pixels);
}
/// <inheritdoc/>
protected override void OnApply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle)
protected override void OnApply(ImageBase<TColor, TPacked> source, Rectangle sourceRectangle)
{
if (this.Grayscale)
{

10
src/ImageSharp/Samplers/Processors/Convolution/EdgeDetection/EdgeDetectorProcessor.cs → src/ImageSharp/Filters/Processors/Convolution/EdgeDetection/EdgeDetectorProcessor.cs

@ -10,7 +10,7 @@ namespace ImageSharp.Processors
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
public abstract class EdgeDetectorProcessor<TColor, TPacked> : ImageSamplingProcessor<TColor, TPacked>, IEdgeDetectorProcessor<TColor, TPacked>
public abstract class EdgeDetectorProcessor<TColor, TPacked> : ImageFilteringProcessor<TColor, TPacked>, IEdgeDetectorProcessor<TColor, TPacked>
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
@ -23,13 +23,13 @@ namespace ImageSharp.Processors
public abstract float[][] KernelXY { get; }
/// <inheritdoc/>
public override void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
protected override void Apply(ImageBase<TColor, TPacked> source, Rectangle sourceRectangle, int startY, int endY)
{
new ConvolutionProcessor<TColor, TPacked>(this.KernelXY).Apply(target, source, targetRectangle, sourceRectangle, startY, endY);
new ConvolutionProcessor<TColor, TPacked>(this.KernelXY).Apply(source, sourceRectangle);
}
/// <inheritdoc/>
protected override void OnApply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle)
protected override void OnApply(ImageBase<TColor, TPacked> source, Rectangle sourceRectangle)
{
if (this.Grayscale)
{
@ -37,4 +37,4 @@ namespace ImageSharp.Processors
}
}
}
}
}

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

@ -10,7 +10,7 @@ namespace ImageSharp.Processors
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
public interface IEdgeDetectorProcessor<TColor, TPacked> : IImageSamplingProcessor<TColor, TPacked>, IEdgeDetectorProcessor
public interface IEdgeDetectorProcessor<TColor, TPacked> : IImageFilteringProcessor<TColor, TPacked>, IEdgeDetectorProcessor
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{

2
src/ImageSharp/Samplers/Processors/Convolution/EdgeDetection/KayyaliProcessor.cs → 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
{

0
src/ImageSharp/Samplers/Processors/Convolution/EdgeDetection/KirschProcessor.cs → src/ImageSharp/Filters/Processors/Convolution/EdgeDetection/KirschProcessor.cs

0
src/ImageSharp/Samplers/Processors/Convolution/EdgeDetection/Laplacian3X3Processor.cs → src/ImageSharp/Filters/Processors/Convolution/EdgeDetection/Laplacian3X3Processor.cs

0
src/ImageSharp/Samplers/Processors/Convolution/EdgeDetection/Laplacian5X5Processor.cs → src/ImageSharp/Filters/Processors/Convolution/EdgeDetection/Laplacian5X5Processor.cs

0
src/ImageSharp/Samplers/Processors/Convolution/EdgeDetection/LaplacianOfGaussianProcessor.cs → src/ImageSharp/Filters/Processors/Convolution/EdgeDetection/LaplacianOfGaussianProcessor.cs

0
src/ImageSharp/Samplers/Processors/Convolution/EdgeDetection/PrewittProcessor.cs → src/ImageSharp/Filters/Processors/Convolution/EdgeDetection/PrewittProcessor.cs

0
src/ImageSharp/Samplers/Processors/Convolution/EdgeDetection/RobertsCrossProcessor.cs → src/ImageSharp/Filters/Processors/Convolution/EdgeDetection/RobertsCrossProcessor.cs

0
src/ImageSharp/Samplers/Processors/Convolution/EdgeDetection/RobinsonProcessor.cs → src/ImageSharp/Filters/Processors/Convolution/EdgeDetection/RobinsonProcessor.cs

0
src/ImageSharp/Samplers/Processors/Convolution/EdgeDetection/ScharrProcessor.cs → src/ImageSharp/Filters/Processors/Convolution/EdgeDetection/ScharrProcessor.cs

0
src/ImageSharp/Samplers/Processors/Convolution/EdgeDetection/SobelProcessor.cs → src/ImageSharp/Filters/Processors/Convolution/EdgeDetection/SobelProcessor.cs

20
src/ImageSharp/Samplers/Processors/Convolution/GuassianBlurProcessor.cs → src/ImageSharp/Filters/Processors/Convolution/GaussianBlurProcessor.cs

@ -1,4 +1,4 @@
// <copyright file="GuassianBlurProcessor.cs" company="James Jackson-South">
// <copyright file="GaussianBlurProcessor.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
@ -12,7 +12,7 @@ namespace ImageSharp.Processors
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
public class GuassianBlurProcessor<TColor, TPacked> : ImageSamplingProcessor<TColor, TPacked>
public class GaussianBlurProcessor<TColor, TPacked> : ImageFilteringProcessor<TColor, TPacked>
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
@ -27,10 +27,10 @@ namespace ImageSharp.Processors
private readonly float sigma;
/// <summary>
/// Initializes a new instance of the <see cref="GuassianBlurProcessor{TColor, TPacked}"/> class.
/// Initializes a new instance of the <see cref="GaussianBlurProcessor{TColor, TPacked}"/> class.
/// </summary>
/// <param name="sigma">The 'sigma' value representing the weight of the blur.</param>
public GuassianBlurProcessor(float sigma = 3f)
public GaussianBlurProcessor(float sigma = 3f)
{
this.kernelSize = ((int)Math.Ceiling(sigma) * 2) + 1;
this.sigma = sigma;
@ -39,12 +39,12 @@ namespace ImageSharp.Processors
}
/// <summary>
/// Initializes a new instance of the <see cref="GuassianBlurProcessor{TColor, TPacked}"/> class.
/// Initializes a new instance of the <see cref="GaussianBlurProcessor{TColor, TPacked}"/> class.
/// </summary>
/// <param name="radius">
/// The 'radius' value representing the size of the area to sample.
/// </param>
public GuassianBlurProcessor(int radius)
public GaussianBlurProcessor(int radius)
{
this.kernelSize = (radius * 2) + 1;
this.sigma = radius;
@ -53,7 +53,7 @@ namespace ImageSharp.Processors
}
/// <summary>
/// Initializes a new instance of the <see cref="GuassianBlurProcessor{TColor, TPacked}"/> class.
/// Initializes a new instance of the <see cref="GaussianBlurProcessor{TColor, TPacked}"/> class.
/// </summary>
/// <param name="sigma">
/// The 'sigma' value representing the weight of the blur.
@ -62,7 +62,7 @@ namespace ImageSharp.Processors
/// The 'radius' value representing the size of the area to sample.
/// This should be at least twice the sigma value.
/// </param>
public GuassianBlurProcessor(float sigma, int radius)
public GaussianBlurProcessor(float sigma, int radius)
{
this.kernelSize = (radius * 2) + 1;
this.sigma = sigma;
@ -81,9 +81,9 @@ namespace ImageSharp.Processors
public float[][] KernelY { get; }
/// <inheritdoc/>
public override void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
protected override void Apply(ImageBase<TColor, TPacked> source, Rectangle sourceRectangle, int startY, int endY)
{
new Convolution2PassProcessor<TColor, TPacked>(this.KernelX, this.KernelY).Apply(target, source, targetRectangle, sourceRectangle, startY, endY);
new Convolution2PassProcessor<TColor, TPacked>(this.KernelX, this.KernelY).Apply(source, sourceRectangle);
}
/// <summary>

20
src/ImageSharp/Samplers/Processors/Convolution/GuassianSharpenProcessor.cs → src/ImageSharp/Filters/Processors/Convolution/GaussianSharpenProcessor.cs

@ -1,4 +1,4 @@
// <copyright file="GuassianSharpenProcessor.cs" company="James Jackson-South">
// <copyright file="GaussianSharpenProcessor.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
@ -12,7 +12,7 @@ namespace ImageSharp.Processors
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
public class GuassianSharpenProcessor<TColor, TPacked> : ImageSamplingProcessor<TColor, TPacked>
public class GaussianSharpenProcessor<TColor, TPacked> : ImageFilteringProcessor<TColor, TPacked>
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
@ -27,12 +27,12 @@ namespace ImageSharp.Processors
private readonly float sigma;
/// <summary>
/// Initializes a new instance of the <see cref="GuassianSharpenProcessor{TColor, TPacked}"/> class.
/// Initializes a new instance of the <see cref="GaussianSharpenProcessor{TColor, TPacked}"/> class.
/// </summary>
/// <param name="sigma">
/// The 'sigma' value representing the weight of the sharpening.
/// </param>
public GuassianSharpenProcessor(float sigma = 3f)
public GaussianSharpenProcessor(float sigma = 3f)
{
this.kernelSize = ((int)Math.Ceiling(sigma) * 2) + 1;
this.sigma = sigma;
@ -41,12 +41,12 @@ namespace ImageSharp.Processors
}
/// <summary>
/// Initializes a new instance of the <see cref="GuassianSharpenProcessor{TColor, TPacked}"/> class.
/// Initializes a new instance of the <see cref="GaussianSharpenProcessor{TColor, TPacked}"/> class.
/// </summary>
/// <param name="radius">
/// The 'radius' value representing the size of the area to sample.
/// </param>
public GuassianSharpenProcessor(int radius)
public GaussianSharpenProcessor(int radius)
{
this.kernelSize = (radius * 2) + 1;
this.sigma = radius;
@ -55,7 +55,7 @@ namespace ImageSharp.Processors
}
/// <summary>
/// Initializes a new instance of the <see cref="GuassianSharpenProcessor{TColor, TPacked}"/> class.
/// Initializes a new instance of the <see cref="GaussianSharpenProcessor{TColor, TPacked}"/> class.
/// </summary>
/// <param name="sigma">
/// The 'sigma' value representing the weight of the sharpen.
@ -64,7 +64,7 @@ namespace ImageSharp.Processors
/// The 'radius' value representing the size of the area to sample.
/// This should be at least twice the sigma value.
/// </param>
public GuassianSharpenProcessor(float sigma, int radius)
public GaussianSharpenProcessor(float sigma, int radius)
{
this.kernelSize = (radius * 2) + 1;
this.sigma = sigma;
@ -83,9 +83,9 @@ namespace ImageSharp.Processors
public float[][] KernelY { get; }
/// <inheritdoc/>
public override void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
protected override void Apply(ImageBase<TColor, TPacked> source, Rectangle sourceRectangle, int startY, int endY)
{
new Convolution2PassProcessor<TColor, TPacked>(this.KernelX, this.KernelY).Apply(target, source, targetRectangle, sourceRectangle, startY, endY);
new Convolution2PassProcessor<TColor, TPacked>(this.KernelX, this.KernelY).Apply(source, sourceRectangle);
}
/// <summary>

16
src/ImageSharp/Samplers/Processors/Effects/OilPaintingProcessor.cs → src/ImageSharp/Filters/Processors/Effects/OilPaintingProcessor.cs

@ -10,17 +10,17 @@ 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>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
public class OilPaintingProcessor<TColor, TPacked> : ImageSamplingProcessor<TColor, TPacked>
public class OilPaintingProcessor<TColor, TPacked> : ImageFilteringProcessor<TColor, TPacked>
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
/// <summary>
/// Initializes a new instance of the <see cref="OilPaintingProcessor{TColor,TPacked}"/> class.
/// Initializes a new instance of the <see cref="OilPaintingProcessor{TColor,TPacked}"/> class.
/// </summary>
/// <param name="levels">
/// The number of intensity levels. Higher values result in a broader range of color intensities forming part of the result image.
@ -48,7 +48,7 @@ namespace ImageSharp.Processors
public int BrushSize { get; }
/// <inheritdoc/>
public override void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
protected override void Apply(ImageBase<TColor, TPacked> source, Rectangle sourceRectangle, int startY, int endY)
{
int startX = sourceRectangle.X;
int endX = sourceRectangle.Right;
@ -67,8 +67,9 @@ namespace ImageSharp.Processors
startX = 0;
}
TColor[] target = new TColor[source.Width * source.Height];
using (PixelAccessor<TColor, TPacked> sourcePixels = source.Lock())
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock())
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock<TColor, TPacked>(source.Width, source.Height))
{
Parallel.For(
minY,
@ -142,14 +143,15 @@ namespace ImageSharp.Processors
float green = Math.Abs(greenBin[maxIndex] / maxIntensity);
float blue = Math.Abs(blueBin[maxIndex] / maxIntensity);
Vector4 targetColor = targetPixels[x, y].ToVector4();
TColor packed = default(TColor);
packed.PackFromVector4(new Vector4(red, green, blue, targetColor.Z));
packed.PackFromVector4(new Vector4(red, green, blue, sourcePixels[x, y].ToVector4().W));
targetPixels[x, y] = packed;
}
}
});
}
source.SetPixels(source.Width, source.Height, target);
}
}
}

17
src/ImageSharp/Samplers/Processors/Effects/PixelateProcesso.cs → src/ImageSharp/Filters/Processors/Effects/PixelateProcessor.cs

@ -1,4 +1,4 @@
// <copyright file="PixelateProcesso.cs" company="James Jackson-South">
// <copyright file="PixelateProcessor.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
@ -10,22 +10,22 @@ 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>
public class PixelateProcesso<TColor, TPacked> : ImageSamplingProcessor<TColor, TPacked>
public class PixelateProcessor<TColor, TPacked> : ImageFilteringProcessor<TColor, TPacked>
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
/// <summary>
/// Initializes a new instance of the <see cref="PixelateProcesso{TColor,TPacked}"/> class.
/// Initializes a new instance of the <see cref="PixelateProcessor{TColor,TPacked}"/> class.
/// </summary>
/// <param name="size">The size of the pixels. Must be greater than 0.</param>
/// <exception cref="System.ArgumentException">
/// <paramref name="size"/> is less than 0 or equal to 0.
/// </exception>
public PixelateProcesso(int size)
public PixelateProcessor(int size)
{
Guard.MustBeGreaterThan(size, 0, nameof(size));
this.Value = size;
@ -37,7 +37,7 @@ namespace ImageSharp.Processors
public int Value { get; }
/// <inheritdoc/>
public override void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
protected override void Apply(ImageBase<TColor, TPacked> source, Rectangle sourceRectangle, int startY, int endY)
{
int startX = sourceRectangle.X;
int endX = sourceRectangle.Right;
@ -63,9 +63,10 @@ namespace ImageSharp.Processors
// Get the range on the y-plane to choose from.
IEnumerable<int> range = EnumerableExtensions.SteppedRange(minY, i => i < maxY, size);
TColor[] target = new TColor[source.Width * source.Height];
using (PixelAccessor<TColor, TPacked> sourcePixels = source.Lock())
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock())
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock<TColor, TPacked>(source.Width, source.Height))
{
Parallel.ForEach(
range,
@ -105,6 +106,8 @@ namespace ImageSharp.Processors
}
}
});
source.SetPixels(source.Width, source.Height, target);
}
}
}

77
src/ImageSharp/Samplers/Processors/Transforms/CompandingResizeProcessor.cs → src/ImageSharp/Filters/Processors/Transforms/CompandingResizeProcessor.cs

@ -22,11 +22,25 @@ namespace ImageSharp.Processors
/// <summary>
/// Initializes a new instance of the <see cref="CompandingResizeProcessor{TColor,TPacked}"/> class.
/// </summary>
/// <param name="sampler">
/// The sampler to perform the resize operation.
/// <param name="sampler">The sampler to perform the resize operation.</param>
/// <param name="width">The target width.</param>
/// <param name="height">The target height.</param>
public CompandingResizeProcessor(IResampler sampler, int width, int height)
: base(sampler, width, height, new Rectangle(0, 0, width, height))
{
}
/// <summary>
/// Initializes a new instance of the <see cref="CompandingResizeProcessor{TColor,TPacked}"/> class.
/// </summary>
/// <param name="sampler">The sampler to perform the resize operation.</param>
/// <param name="width">The target width.</param>
/// <param name="height">The target height.</param>
/// <param name="resizeRectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the target image object to draw to.
/// </param>
public CompandingResizeProcessor(IResampler sampler)
: base(sampler)
public CompandingResizeProcessor(IResampler sampler, int width, int height, Rectangle resizeRectangle)
: base(sampler, width, height, resizeRectangle)
{
}
@ -34,37 +48,38 @@ namespace ImageSharp.Processors
public override bool Compand { get; set; } = true;
/// <inheritdoc/>
public override void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
protected override void Apply(ImageBase<TColor, TPacked> source, Rectangle sourceRectangle, int startY, int endY)
{
// Jump out, we'll deal with that later.
if (source.Bounds == target.Bounds && sourceRectangle == targetRectangle)
if (source.Width == this.Width && source.Height == this.Height && sourceRectangle == this.ResizeRectangle)
{
return;
}
int width = target.Width;
int height = target.Height;
int sourceHeight = sourceRectangle.Height;
int targetX = target.Bounds.X;
int targetY = target.Bounds.Y;
int targetRight = target.Bounds.Right;
int targetBottom = target.Bounds.Bottom;
int startX = targetRectangle.X;
int endX = targetRectangle.Right;
int minX = Math.Max(targetX, startX);
int maxX = Math.Min(targetRight, endX);
int minY = Math.Max(targetY, startY);
int maxY = Math.Min(targetBottom, endY);
// Reset the values as the rectangle can be altered by ResizeRectangle.
startY = this.ResizeRectangle.Y;
endY = this.ResizeRectangle.Bottom;
int width = this.Width;
int height = this.Height;
int startX = this.ResizeRectangle.X;
int endX = this.ResizeRectangle.Right;
int minX = Math.Max(0, startX);
int maxX = Math.Min(width, endX);
int minY = Math.Max(0, startY);
int maxY = Math.Min(height, endY);
TColor[] target = new TColor[width * height];
if (this.Sampler is NearestNeighborResampler)
{
// Scaling factors
float widthFactor = sourceRectangle.Width / (float)targetRectangle.Width;
float heightFactor = sourceRectangle.Height / (float)targetRectangle.Height;
float widthFactor = sourceRectangle.Width / (float)this.ResizeRectangle.Width;
float heightFactor = sourceRectangle.Height / (float)this.ResizeRectangle.Height;
using (PixelAccessor<TColor, TPacked> sourcePixels = source.Lock())
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock())
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock<TColor, TPacked>(width, height))
{
Parallel.For(
minY,
@ -84,6 +99,7 @@ namespace ImageSharp.Processors
}
// Break out now.
source.SetPixels(width, height, target);
return;
}
@ -91,19 +107,14 @@ namespace ImageSharp.Processors
// A 2-pass 1D algorithm appears to be faster than splitting a 1-pass 2D algorithm
// First process the columns. Since we are not using multiple threads startY and endY
// are the upper and lower bounds of the source rectangle.
Image<TColor, TPacked> firstPass = new Image<TColor, TPacked>(target.Width, source.Height);
TColor[] firstPass = new TColor[width * source.Height];
using (PixelAccessor<TColor, TPacked> sourcePixels = source.Lock())
using (PixelAccessor<TColor, TPacked> firstPassPixels = firstPass.Lock())
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock())
using (PixelAccessor<TColor, TPacked> firstPassPixels = firstPass.Lock<TColor, TPacked>(width, source.Height))
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock<TColor, TPacked>(width, height))
{
minX = Math.Max(0, startX);
maxX = Math.Min(width, endX);
minY = Math.Max(0, startY);
maxY = Math.Min(height, endY);
Parallel.For(
0,
sourceHeight,
sourceRectangle.Height,
this.ParallelOptions,
y =>
{
@ -154,6 +165,8 @@ namespace ImageSharp.Processors
}
});
}
source.SetPixels(width, height, target);
}
}
}

68
src/ImageSharp/Filters/Processors/Transforms/CropProcessor.cs

@ -0,0 +1,68 @@
// <copyright file="CropProcessor.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;
using System.Threading.Tasks;
/// <summary>
/// Provides methods to allow the cropping of an image.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
public class CropProcessor<TColor, TPacked> : ImageFilteringProcessor<TColor, TPacked>
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
/// <summary>
/// Initializes a new instance of the <see cref="CropProcessor{TColor,TPacked}"/> class.
/// </summary>
/// <param name="cropRectangle">The target cropped rectangle.</param>
public CropProcessor(Rectangle cropRectangle)
{
this.CropRectangle = cropRectangle;
}
/// <summary>
/// Gets the width.
/// </summary>
public Rectangle CropRectangle { get; }
/// <inheritdoc/>
protected override void Apply(ImageBase<TColor, TPacked> source, Rectangle sourceRectangle, int startY, int endY)
{
if (this.CropRectangle == sourceRectangle)
{
return;
}
int minY = Math.Max(this.CropRectangle.Y, startY);
int maxY = Math.Min(this.CropRectangle.Bottom, endY);
int minX = Math.Max(this.CropRectangle.X, sourceRectangle.X);
int maxX = Math.Min(this.CropRectangle.Right, sourceRectangle.Right);
TColor[] target = new TColor[this.CropRectangle.Width * this.CropRectangle.Height];
using (PixelAccessor<TColor, TPacked> sourcePixels = source.Lock())
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock<TColor, TPacked>(this.CropRectangle.Width, this.CropRectangle.Height))
{
Parallel.For(
minY,
maxY,
this.ParallelOptions,
y =>
{
for (int x = minX; x < maxX; x++)
{
targetPixels[x - minX, y - minY] = sourcePixels[x, y];
}
});
}
source.SetPixels(this.CropRectangle.Width, this.CropRectangle.Height, target);
}
}
}

59
src/ImageSharp/Filters/Processors/Transforms/EntropyCropProcessor.cs

@ -0,0 +1,59 @@
// <copyright file="EntropyCropProcessor.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>
/// Provides methods to allow the cropping of an image to preserve areas of highest
/// entropy.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
public class EntropyCropProcessor<TColor, TPacked> : ImageFilteringProcessor<TColor, TPacked>
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
/// <summary>
/// Initializes a new instance of the <see cref="EntropyCropProcessor{TColor, TPacked}"/> class.
/// </summary>
/// <param name="threshold">The threshold to split the image. Must be between 0 and 1.</param>
/// <exception cref="System.ArgumentException">
/// <paramref name="threshold"/> is less than 0 or is greater than 1.
/// </exception>
public EntropyCropProcessor(float threshold)
{
Guard.MustBeBetweenOrEqualTo(threshold, 0, 1, nameof(threshold));
this.Value = threshold;
}
/// <summary>
/// Gets the threshold value.
/// </summary>
public float Value { get; }
/// <inheritdoc/>
protected override void Apply(ImageBase<TColor, TPacked> source, Rectangle sourceRectangle, int startY, int endY)
{
ImageBase<TColor, TPacked> temp = new Image<TColor, TPacked>(source.Width, source.Height);
temp.ClonePixels(source.Width, source.Height, source.Pixels);
// Detect the edges.
new SobelProcessor<TColor, TPacked>().Apply(temp, sourceRectangle);
// Apply threshold binarization filter.
new BinaryThresholdProcessor<TColor, TPacked>(this.Value).Apply(temp, sourceRectangle);
// Search for the first white pixels
Rectangle rectangle = ImageMaths.GetFilteredBoundingRectangle(temp, 0);
if (rectangle == sourceRectangle)
{
return;
}
new CropProcessor<TColor, TPacked>(rectangle).Apply(source, sourceRectangle);
}
}
}

56
src/ImageSharp/Samplers/Processors/Transforms/FlipProcessor.cs → src/ImageSharp/Filters/Processors/Transforms/FlipProcessor.cs

@ -13,7 +13,7 @@ namespace ImageSharp.Processors
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
public class FlipProcessor<TColor, TPacked> : ImageSamplingProcessor<TColor, TPacked>
public class FlipProcessor<TColor, TPacked> : ImageFilteringProcessor<TColor, TPacked>
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
@ -32,18 +32,16 @@ namespace ImageSharp.Processors
public FlipType FlipType { get; }
/// <inheritdoc/>
public override void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
protected override void Apply(ImageBase<TColor, TPacked> source, Rectangle sourceRectangle, int startY, int endY)
{
target.ClonePixels(target.Width, target.Height, source.Pixels);
switch (this.FlipType)
{
// No default needed as we have already set the pixels.
case FlipType.Vertical:
this.FlipX(target);
this.FlipX(source);
break;
case FlipType.Horizontal:
this.FlipY(target);
this.FlipY(source);
break;
}
}
@ -52,17 +50,17 @@ namespace ImageSharp.Processors
/// Swaps the image at the X-axis, which goes horizontally through the middle
/// at half the height of the image.
/// </summary>
/// <param name="target">Target image to apply the process to.</param>
private void FlipX(ImageBase<TColor, TPacked> target)
/// <param name="source">The source image to apply the process to.</param>
private void FlipX(ImageBase<TColor, TPacked> source)
{
int width = target.Width;
int height = target.Height;
int halfHeight = (int)Math.Ceiling(target.Height * .5F);
Image<TColor, TPacked> temp = new Image<TColor, TPacked>(width, height);
temp.ClonePixels(width, height, target.Pixels);
int width = source.Width;
int height = source.Height;
int halfHeight = (int)Math.Ceiling(source.Height * .5F);
TColor[] target = new TColor[width * height];
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock())
using (PixelAccessor<TColor, TPacked> tempPixels = temp.Lock())
using (PixelAccessor<TColor, TPacked> sourcePixels = source.Lock())
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock<TColor, TPacked>(width, height))
{
Parallel.For(
0,
@ -73,28 +71,30 @@ namespace ImageSharp.Processors
for (int x = 0; x < width; x++)
{
int newY = height - y - 1;
targetPixels[x, y] = tempPixels[x, newY];
targetPixels[x, newY] = tempPixels[x, y];
targetPixels[x, y] = sourcePixels[x, newY];
targetPixels[x, newY] = sourcePixels[x, y];
}
});
}
source.SetPixels(width, height, target);
}
/// <summary>
/// Swaps the image at the Y-axis, which goes vertically through the middle
/// at half of the width of the image.
/// </summary>
/// <param name="target">Target image to apply the process to.</param>
private void FlipY(ImageBase<TColor, TPacked> target)
/// <param name="source">The source image to apply the process to.</param>
private void FlipY(ImageBase<TColor, TPacked> source)
{
int width = target.Width;
int height = target.Height;
int width = source.Width;
int height = source.Height;
int halfWidth = (int)Math.Ceiling(width * .5F);
Image<TColor, TPacked> temp = new Image<TColor, TPacked>(width, height);
temp.ClonePixels(width, height, target.Pixels);
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock())
using (PixelAccessor<TColor, TPacked> tempPixels = temp.Lock())
TColor[] target = new TColor[width * height];
using (PixelAccessor<TColor, TPacked> sourcePixels = source.Lock())
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock<TColor, TPacked>(width, height))
{
Parallel.For(
0,
@ -105,11 +105,13 @@ namespace ImageSharp.Processors
for (int x = 0; x < halfWidth; x++)
{
int newX = width - x - 1;
targetPixels[x, y] = tempPixels[newX, y];
targetPixels[newX, y] = tempPixels[x, y];
targetPixels[x, y] = sourcePixels[newX, y];
targetPixels[newX, y] = sourcePixels[x, y];
}
});
}
source.SetPixels(width, height, target);
}
}
}

25
src/ImageSharp/Samplers/Processors/Transforms/Matrix3x2Processor.cs → src/ImageSharp/Filters/Processors/Transforms/Matrix3x2Processor.cs

@ -12,38 +12,39 @@ namespace ImageSharp.Processors
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
public abstract class Matrix3x2Processor<TColor, TPacked> : ImageSamplingProcessor<TColor, TPacked>
public abstract class Matrix3x2Processor<TColor, TPacked> : ImageFilteringProcessor<TColor, TPacked>
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
/// <summary>
/// Creates a new target to contain the results of the matrix transform.
/// Gets the rectangle designating the target canvas.
/// </summary>
protected Rectangle CanvasRectangle { get; private set; }
/// <summary>
/// Creates a new target canvas to contain the results of the matrix transform.
/// </summary>
/// <param name="target">Target image to apply the process to.</param>
/// <param name="sourceRectangle">The source rectangle.</param>
/// <param name="processMatrix">The processing matrix.</param>
protected static void CreateNewTarget(ImageBase<TColor, TPacked> target, Rectangle sourceRectangle, Matrix3x2 processMatrix)
protected void CreateNewCanvas(Rectangle sourceRectangle, Matrix3x2 processMatrix)
{
Matrix3x2 sizeMatrix;
if (Matrix3x2.Invert(processMatrix, out sizeMatrix))
{
Rectangle rectangle = ImageMaths.GetBoundingRectangle(sourceRectangle, sizeMatrix);
target.SetPixels(rectangle.Width, rectangle.Height, new TColor[rectangle.Width * rectangle.Height]);
}
this.CanvasRectangle = Matrix3x2.Invert(processMatrix, out sizeMatrix)
? ImageMaths.GetBoundingRectangle(sourceRectangle, sizeMatrix)
: sourceRectangle;
}
/// <summary>
/// Gets a transform matrix adjusted to center upon the target image bounds.
/// </summary>
/// <param name="target">Target image to apply the process to.</param>
/// <param name="source">The source image.</param>
/// <param name="matrix">The transform matrix.</param>
/// <returns>
/// The <see cref="Matrix3x2"/>.
/// </returns>
protected static Matrix3x2 GetCenteredMatrix(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Matrix3x2 matrix)
protected Matrix3x2 GetCenteredMatrix(ImageBase<TColor, TPacked> source, Matrix3x2 matrix)
{
Matrix3x2 translationToTargetCenter = Matrix3x2.CreateTranslation(-target.Width * .5F, -target.Height * .5F);
Matrix3x2 translationToTargetCenter = Matrix3x2.CreateTranslation(-this.CanvasRectangle.Width * .5F, -this.CanvasRectangle.Height * .5F);
Matrix3x2 translateToSourceCenter = Matrix3x2.CreateTranslation(source.Width * .5F, source.Height * .5F);
return (translationToTargetCenter * matrix) * translateToSourceCenter;
}

47
src/ImageSharp/Samplers/Processors/Transforms/ResamplingWeightedProcessor.cs → src/ImageSharp/Filters/Processors/Transforms/ResamplingWeightedProcessor.cs

@ -13,21 +13,29 @@ namespace ImageSharp.Processors
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
public abstract class ResamplingWeightedProcessor<TColor, TPacked> : ImageSamplingProcessor<TColor, TPacked>
public abstract class ResamplingWeightedProcessor<TColor, TPacked> : ImageFilteringProcessor<TColor, TPacked>
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
/// <summary>
/// Initializes a new instance of the <see cref="ResamplingWeightedProcessor{TColor, TPacked}"/> class.
/// </summary>
/// <param name="sampler">
/// The sampler to perform the resize operation.
/// <param name="sampler">The sampler to perform the resize operation.</param>
/// <param name="width">The target width.</param>
/// <param name="height">The target height.</param>
/// <param name="resizeRectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the target image object to draw to.
/// </param>
protected ResamplingWeightedProcessor(IResampler sampler)
protected ResamplingWeightedProcessor(IResampler sampler, int width, int height, Rectangle resizeRectangle)
{
Guard.NotNull(sampler, nameof(sampler));
Guard.MustBeGreaterThan(width, 0, nameof(width));
Guard.MustBeGreaterThan(height, 0, nameof(height));
this.Sampler = sampler;
this.Width = width;
this.Height = height;
this.ResizeRectangle = resizeRectangle;
}
/// <summary>
@ -35,6 +43,21 @@ namespace ImageSharp.Processors
/// </summary>
public IResampler Sampler { get; }
/// <summary>
/// Gets the width.
/// </summary>
public int Width { get; }
/// <summary>
/// Gets the height.
/// </summary>
public int Height { get; }
/// <summary>
/// Gets the resize rectangle.
/// </summary>
public Rectangle ResizeRectangle { get; }
/// <summary>
/// Gets or sets the horizontal weights.
/// </summary>
@ -46,22 +69,12 @@ namespace ImageSharp.Processors
protected Weights[] VerticalWeights { get; set; }
/// <inheritdoc/>
protected override void OnApply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle)
protected override void OnApply(ImageBase<TColor, TPacked> source, Rectangle sourceRectangle)
{
if (!(this.Sampler is NearestNeighborResampler))
{
this.HorizontalWeights = this.PrecomputeWeights(targetRectangle.Width, sourceRectangle.Width);
this.VerticalWeights = this.PrecomputeWeights(targetRectangle.Height, sourceRectangle.Height);
}
}
/// <inheritdoc/>
protected override void AfterApply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle)
{
// Copy the pixels over.
if (source.Bounds == target.Bounds && sourceRectangle == targetRectangle)
{
target.ClonePixels(target.Width, target.Height, source.Pixels);
this.HorizontalWeights = this.PrecomputeWeights(this.ResizeRectangle.Width, sourceRectangle.Width);
this.VerticalWeights = this.PrecomputeWeights(this.ResizeRectangle.Height, sourceRectangle.Height);
}
}

77
src/ImageSharp/Samplers/Processors/Transforms/ResizeProcessor.cs → src/ImageSharp/Filters/Processors/Transforms/ResizeProcessor.cs

@ -24,46 +24,61 @@ namespace ImageSharp.Processors
/// <summary>
/// Initializes a new instance of the <see cref="ResizeProcessor{TColor, TPacked}"/> class.
/// </summary>
/// <param name="sampler">
/// The sampler to perform the resize operation.
/// <param name="sampler">The sampler to perform the resize operation.</param>
/// <param name="width">The target width.</param>
/// <param name="height">The target height.</param>
public ResizeProcessor(IResampler sampler, int width, int height)
: base(sampler, width, height, new Rectangle(0, 0, width, height))
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ResizeProcessor{TColor, TPacked}"/> class.
/// </summary>
/// <param name="sampler">The sampler to perform the resize operation.</param>
/// <param name="width">The target width.</param>
/// <param name="height">The target height.</param>
/// <param name="resizeRectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the target image object to draw to.
/// </param>
public ResizeProcessor(IResampler sampler)
: base(sampler)
public ResizeProcessor(IResampler sampler, int width, int height, Rectangle resizeRectangle)
: base(sampler, width, height, resizeRectangle)
{
}
/// <inheritdoc/>
public override void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
protected override void Apply(ImageBase<TColor, TPacked> source, Rectangle sourceRectangle, int startY, int endY)
{
// Jump out, we'll deal with that later.
if (source.Bounds == target.Bounds && sourceRectangle == targetRectangle)
if (source.Width == this.Width && source.Height == this.Height && sourceRectangle == this.ResizeRectangle)
{
return;
}
int width = target.Width;
int height = target.Height;
int sourceHeight = sourceRectangle.Height;
int targetX = target.Bounds.X;
int targetY = target.Bounds.Y;
int targetRight = target.Bounds.Right;
int targetBottom = target.Bounds.Bottom;
int startX = targetRectangle.X;
int endX = targetRectangle.Right;
int minX = Math.Max(targetX, startX);
int maxX = Math.Min(targetRight, endX);
int minY = Math.Max(targetY, startY);
int maxY = Math.Min(targetBottom, endY);
// Reset the values as the rectangle can be altered by ResizeRectangle.
startY = this.ResizeRectangle.Y;
endY = this.ResizeRectangle.Bottom;
int width = this.Width;
int height = this.Height;
int startX = this.ResizeRectangle.X;
int endX = this.ResizeRectangle.Right;
int minX = Math.Max(0, startX);
int maxX = Math.Min(width, endX);
int minY = Math.Max(0, startY);
int maxY = Math.Min(height, endY);
TColor[] target = new TColor[width * height];
if (this.Sampler is NearestNeighborResampler)
{
// Scaling factors
float widthFactor = sourceRectangle.Width / (float)targetRectangle.Width;
float heightFactor = sourceRectangle.Height / (float)targetRectangle.Height;
float widthFactor = sourceRectangle.Width / (float)this.ResizeRectangle.Width;
float heightFactor = sourceRectangle.Height / (float)this.ResizeRectangle.Height;
using (PixelAccessor<TColor, TPacked> sourcePixels = source.Lock())
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock())
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock<TColor, TPacked>(width, height))
{
Parallel.For(
minY,
@ -83,6 +98,7 @@ namespace ImageSharp.Processors
}
// Break out now.
source.SetPixels(width, height, target);
return;
}
@ -90,19 +106,14 @@ namespace ImageSharp.Processors
// A 2-pass 1D algorithm appears to be faster than splitting a 1-pass 2D algorithm
// First process the columns. Since we are not using multiple threads startY and endY
// are the upper and lower bounds of the source rectangle.
Image<TColor, TPacked> firstPass = new Image<TColor, TPacked>(target.Width, source.Height);
TColor[] firstPass = new TColor[width * source.Height];
using (PixelAccessor<TColor, TPacked> sourcePixels = source.Lock())
using (PixelAccessor<TColor, TPacked> firstPassPixels = firstPass.Lock())
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock())
using (PixelAccessor<TColor, TPacked> firstPassPixels = firstPass.Lock<TColor, TPacked>(width, source.Height))
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock<TColor, TPacked>(width, height))
{
minX = Math.Max(0, startX);
maxX = Math.Min(width, endX);
minY = Math.Max(0, startY);
maxY = Math.Min(height, endY);
Parallel.For(
0,
sourceHeight,
sourceRectangle.Height,
this.ParallelOptions,
y =>
{
@ -153,6 +164,8 @@ namespace ImageSharp.Processors
}
});
}
source.SetPixels(width, height, target);
}
}
}

62
src/ImageSharp/Samplers/Processors/Transforms/RotateProcessor.cs → src/ImageSharp/Filters/Processors/Transforms/RotateProcessor.cs

@ -19,7 +19,7 @@ namespace ImageSharp.Processors
where TPacked : struct
{
/// <summary>
/// The tranform matrix to apply.
/// The transform matrix to apply.
/// </summary>
private Matrix3x2 processMatrix;
@ -34,19 +34,20 @@ namespace ImageSharp.Processors
public bool Expand { get; set; } = true;
/// <inheritdoc/>
public override void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
protected override void Apply(ImageBase<TColor, TPacked> source, Rectangle sourceRectangle, int startY, int endY)
{
if (this.OptimizedApply(target, source))
if (this.OptimizedApply(source))
{
return;
}
int height = target.Height;
int width = target.Width;
Matrix3x2 matrix = GetCenteredMatrix(target, source, this.processMatrix);
int height = this.CanvasRectangle.Height;
int width = this.CanvasRectangle.Width;
Matrix3x2 matrix = this.GetCenteredMatrix(source, this.processMatrix);
TColor[] target = new TColor[width * height];
using (PixelAccessor<TColor, TPacked> sourcePixels = source.Lock())
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock())
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock<TColor, TPacked>(width, height))
{
Parallel.For(
0,
@ -64,10 +65,12 @@ namespace ImageSharp.Processors
}
});
}
source.SetPixels(width, height, target);
}
/// <inheritdoc/>
protected override void OnApply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle)
protected override void OnApply(ImageBase<TColor, TPacked> source, Rectangle sourceRectangle)
{
const float Epsilon = .0001F;
@ -79,40 +82,39 @@ namespace ImageSharp.Processors
this.processMatrix = Point.CreateRotation(new Point(0, 0), -this.Angle);
if (this.Expand)
{
CreateNewTarget(target, sourceRectangle, this.processMatrix);
this.CreateNewCanvas(sourceRectangle, this.processMatrix);
}
}
/// <summary>
/// Rotates the images with an optimized method when the angle is 90, 180 or 270 degrees.
/// </summary>
/// <param name="target">The target image.</param>
/// <param name="source">The source image.</param>
/// <returns>The <see cref="bool"/></returns>
private bool OptimizedApply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source)
private bool OptimizedApply(ImageBase<TColor, TPacked> source)
{
const float Epsilon = .0001F;
if (Math.Abs(this.Angle) < Epsilon)
{
target.ClonePixels(target.Width, target.Height, source.Pixels);
// No need to do anything so return.
return true;
}
if (Math.Abs(this.Angle - 90) < Epsilon)
{
this.Rotate90(target, source);
this.Rotate90(source);
return true;
}
if (Math.Abs(this.Angle - 180) < Epsilon)
{
this.Rotate180(target, source);
this.Rotate180(source);
return true;
}
if (Math.Abs(this.Angle - 270) < Epsilon)
{
this.Rotate270(target, source);
this.Rotate270(source);
return true;
}
@ -122,16 +124,15 @@ namespace ImageSharp.Processors
/// <summary>
/// Rotates the image 270 degrees clockwise at the centre point.
/// </summary>
/// <param name="target">The target image.</param>
/// <param name="source">The source image.</param>
private void Rotate270(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source)
private void Rotate270(ImageBase<TColor, TPacked> source)
{
int width = source.Width;
int height = source.Height;
Image<TColor, TPacked> temp = new Image<TColor, TPacked>(height, width);
TColor[] target = new TColor[width * height];
using (PixelAccessor<TColor, TPacked> sourcePixels = source.Lock())
using (PixelAccessor<TColor, TPacked> tempPixels = temp.Lock())
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock<TColor, TPacked>(height, width))
{
Parallel.For(
0,
@ -144,26 +145,26 @@ namespace ImageSharp.Processors
int newX = height - y - 1;
newX = height - newX - 1;
int newY = width - x - 1;
tempPixels[newX, newY] = sourcePixels[x, y];
targetPixels[newX, newY] = sourcePixels[x, y];
}
});
}
target.SetPixels(height, width, temp.Pixels);
source.SetPixels(height, width, target);
}
/// <summary>
/// Rotates the image 180 degrees clockwise at the centre point.
/// </summary>
/// <param name="target">The target image.</param>
/// <param name="source">The source image.</param>
private void Rotate180(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source)
private void Rotate180(ImageBase<TColor, TPacked> source)
{
int width = source.Width;
int height = source.Height;
TColor[] target = new TColor[width * height];
using (PixelAccessor<TColor, TPacked> sourcePixels = source.Lock())
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock())
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock<TColor, TPacked>(width, height))
{
Parallel.For(
0,
@ -179,21 +180,22 @@ namespace ImageSharp.Processors
}
});
}
source.SetPixels(width, height, target);
}
/// <summary>
/// Rotates the image 90 degrees clockwise at the centre point.
/// </summary>
/// <param name="target">The target image.</param>
/// <param name="source">The source image.</param>
private void Rotate90(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source)
private void Rotate90(ImageBase<TColor, TPacked> source)
{
int width = source.Width;
int height = source.Height;
Image<TColor, TPacked> temp = new Image<TColor, TPacked>(height, width);
TColor[] target = new TColor[width * height];
using (PixelAccessor<TColor, TPacked> sourcePixels = source.Lock())
using (PixelAccessor<TColor, TPacked> tempPixels = temp.Lock())
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock<TColor, TPacked>(height, width))
{
Parallel.For(
0,
@ -204,12 +206,12 @@ namespace ImageSharp.Processors
for (int x = 0; x < width; x++)
{
int newX = height - y - 1;
tempPixels[newX, x] = sourcePixels[x, y];
targetPixels[newX, x] = sourcePixels[x, y];
}
});
}
target.SetPixels(height, width, temp.Pixels);
source.SetPixels(height, width, target);
}
}
}

17
src/ImageSharp/Samplers/Processors/Transforms/SkewProcessor.cs → src/ImageSharp/Filters/Processors/Transforms/SkewProcessor.cs

@ -39,14 +39,15 @@ namespace ImageSharp.Processors
public bool Expand { get; set; } = true;
/// <inheritdoc/>
public override void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
protected override void Apply(ImageBase<TColor, TPacked> source, Rectangle sourceRectangle, int startY, int endY)
{
int height = target.Height;
int width = target.Width;
Matrix3x2 matrix = GetCenteredMatrix(target, source, this.processMatrix);
int height = this.CanvasRectangle.Height;
int width = this.CanvasRectangle.Width;
Matrix3x2 matrix = this.GetCenteredMatrix(source, this.processMatrix);
TColor[] target = new TColor[width * height];
using (PixelAccessor<TColor, TPacked> sourcePixels = source.Lock())
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock())
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock<TColor, TPacked>(width, height))
{
Parallel.For(
0,
@ -64,15 +65,17 @@ namespace ImageSharp.Processors
}
});
}
source.SetPixels(width, height, target);
}
/// <inheritdoc/>
protected override void OnApply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle)
protected override void OnApply(ImageBase<TColor, TPacked> source, Rectangle sourceRectangle)
{
this.processMatrix = Point.CreateSkew(new Point(0, 0), -this.AngleX, -this.AngleY);
if (this.Expand)
{
CreateNewTarget(target, sourceRectangle, this.processMatrix);
this.CreateNewCanvas(sourceRectangle, this.processMatrix);
}
}
}

2
src/ImageSharp/Samplers/Transforms/AutoOrient.cs → src/ImageSharp/Filters/Transforms/AutoOrient.cs

@ -11,7 +11,7 @@ namespace ImageSharp
public static partial class ImageExtensions
{
/// <summary>
/// Adjusts an image so that its orientation is suitable for viewing.
/// Adjusts an image so that its orientation is suitable for viewing. Adjustments are based on EXIF metadata embedded in the image.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>

32
src/ImageSharp/Samplers/Transforms/Crop.cs → src/ImageSharp/Filters/Transforms/Crop.cs

@ -25,41 +25,25 @@ namespace ImageSharp
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
return Crop(source, width, height, source.Bounds);
return Crop(source, new Rectangle(0, 0, width, height));
}
/// <summary>
/// Crops an image to the given width and height with the given source rectangle.
/// <remarks>
/// If the source rectangle is smaller than the target dimensions then the
/// area within the source is resized performing a zoomed crop.
/// </remarks>
/// Crops an image to the given rectangle.
/// </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 to crop.</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 name="cropRectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to retain.
/// </param>
/// <returns>The <see cref="Image"/></returns>
public static Image<TColor, TPacked> Crop<TColor, TPacked>(this Image<TColor, TPacked> source, int width, int height, Rectangle sourceRectangle)
public static Image<TColor, TPacked> Crop<TColor, TPacked>(this Image<TColor, TPacked> source, Rectangle cropRectangle)
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
Guard.MustBeGreaterThan(width, 0, nameof(width));
Guard.MustBeGreaterThan(height, 0, nameof(height));
if (sourceRectangle.Width < width || sourceRectangle.Height < height)
{
// If the source rectangle is smaller than the target perform a
// cropped zoom.
source = source.Resize(sourceRectangle.Width, sourceRectangle.Height);
}
CropProcessor<TColor, TPacked> processor = new CropProcessor<TColor, TPacked>();
return source.Process(width, height, sourceRectangle, new Rectangle(0, 0, width, height), processor);
CropProcessor<TColor, TPacked> processor = new CropProcessor<TColor, TPacked>(cropRectangle);
return source.Process(source.Bounds, processor);
}
}
}
}

4
src/ImageSharp/Samplers/Transforms/EntropyCrop.cs → src/ImageSharp/Filters/Transforms/EntropyCrop.cs

@ -1,4 +1,4 @@
// <copyright file="EntropyCrop.cs" company="James Jackson-South">
// <copyright file="EntropyCrop.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
@ -25,7 +25,7 @@ namespace ImageSharp
where TPacked : struct
{
EntropyCropProcessor<TColor, TPacked> processor = new EntropyCropProcessor<TColor, TPacked>(threshold);
return source.Process(source.Width, source.Height, source.Bounds, Rectangle.Empty, processor);
return source.Process(source.Bounds, processor);
}
}
}

2
src/ImageSharp/Samplers/Transforms/Flip.cs → src/ImageSharp/Filters/Transforms/Flip.cs

@ -25,7 +25,7 @@ namespace ImageSharp
where TPacked : struct
{
FlipProcessor<TColor, TPacked> processor = new FlipProcessor<TColor, TPacked>(flipType);
return source.Process(source.Width, source.Height, source.Bounds, source.Bounds, processor);
return source.Process(source.Bounds, processor);
}
}
}

0
src/ImageSharp/Samplers/Transforms/Options/AnchorPosition.cs → src/ImageSharp/Filters/Transforms/Options/AnchorPosition.cs

0
src/ImageSharp/Samplers/Transforms/Options/FlipType.cs → src/ImageSharp/Filters/Transforms/Options/FlipType.cs

0
src/ImageSharp/Samplers/Transforms/Options/Orientation.cs → src/ImageSharp/Filters/Transforms/Options/Orientation.cs

0
src/ImageSharp/Samplers/Transforms/Options/ResizeHelper.cs → src/ImageSharp/Filters/Transforms/Options/ResizeHelper.cs

0
src/ImageSharp/Samplers/Transforms/Options/ResizeMode.cs → src/ImageSharp/Filters/Transforms/Options/ResizeMode.cs

0
src/ImageSharp/Samplers/Transforms/Options/ResizeOptions.cs → src/ImageSharp/Filters/Transforms/Options/ResizeOptions.cs

0
src/ImageSharp/Samplers/Transforms/Options/RotateType.cs → src/ImageSharp/Filters/Transforms/Options/RotateType.cs

0
src/ImageSharp/Samplers/Transforms/Pad.cs → src/ImageSharp/Filters/Transforms/Pad.cs

0
src/ImageSharp/Samplers/Transforms/Resamplers/BicubicResampler.cs → src/ImageSharp/Filters/Transforms/Resamplers/BicubicResampler.cs

0
src/ImageSharp/Samplers/Transforms/Resamplers/BoxResampler.cs → src/ImageSharp/Filters/Transforms/Resamplers/BoxResampler.cs

0
src/ImageSharp/Samplers/Transforms/Resamplers/CatmullRomResampler.cs → src/ImageSharp/Filters/Transforms/Resamplers/CatmullRomResampler.cs

0
src/ImageSharp/Samplers/Transforms/Resamplers/HermiteResampler.cs → src/ImageSharp/Filters/Transforms/Resamplers/HermiteResampler.cs

0
src/ImageSharp/Samplers/Transforms/Resamplers/IResampler.cs → src/ImageSharp/Filters/Transforms/Resamplers/IResampler.cs

0
src/ImageSharp/Samplers/Transforms/Resamplers/Lanczos2Resampler.cs → src/ImageSharp/Filters/Transforms/Resamplers/Lanczos2Resampler.cs

0
src/ImageSharp/Samplers/Transforms/Resamplers/Lanczos3Resampler.cs → src/ImageSharp/Filters/Transforms/Resamplers/Lanczos3Resampler.cs

0
src/ImageSharp/Samplers/Transforms/Resamplers/Lanczos5Resampler.cs → src/ImageSharp/Filters/Transforms/Resamplers/Lanczos5Resampler.cs

0
src/ImageSharp/Samplers/Transforms/Resamplers/Lanczos8Resampler.cs → src/ImageSharp/Filters/Transforms/Resamplers/Lanczos8Resampler.cs

0
src/ImageSharp/Samplers/Transforms/Resamplers/MitchellNetravaliResampler.cs → src/ImageSharp/Filters/Transforms/Resamplers/MitchellNetravaliResampler.cs

0
src/ImageSharp/Samplers/Transforms/Resamplers/NearestNeighborResampler.cs → src/ImageSharp/Filters/Transforms/Resamplers/NearestNeighborResampler.cs

0
src/ImageSharp/Samplers/Transforms/Resamplers/RobidouxResampler.cs → src/ImageSharp/Filters/Transforms/Resamplers/RobidouxResampler.cs

0
src/ImageSharp/Samplers/Transforms/Resamplers/RobidouxSharpResampler.cs → src/ImageSharp/Filters/Transforms/Resamplers/RobidouxSharpResampler.cs

0
src/ImageSharp/Samplers/Transforms/Resamplers/SplineResampler.cs → src/ImageSharp/Filters/Transforms/Resamplers/SplineResampler.cs

0
src/ImageSharp/Samplers/Transforms/Resamplers/TriangleResampler.cs → src/ImageSharp/Filters/Transforms/Resamplers/TriangleResampler.cs

0
src/ImageSharp/Samplers/Transforms/Resamplers/WelchResampler.cs → src/ImageSharp/Filters/Transforms/Resamplers/WelchResampler.cs

6
src/ImageSharp/Samplers/Transforms/Resize.cs → src/ImageSharp/Filters/Transforms/Resize.cs

@ -155,14 +155,14 @@ namespace ImageSharp
if (compand)
{
processor = new CompandingResizeProcessor<TColor, TPacked>(sampler);
processor = new CompandingResizeProcessor<TColor, TPacked>(sampler, width, height, targetRectangle);
}
else
{
processor = new ResizeProcessor<TColor, TPacked>(sampler);
processor = new ResizeProcessor<TColor, TPacked>(sampler, width, height, targetRectangle);
}
return source.Process(width, height, sourceRectangle, targetRectangle, processor);
return source.Process(sourceRectangle, processor);
}
}
}

2
src/ImageSharp/Samplers/Transforms/Rotate.cs → src/ImageSharp/Filters/Transforms/Rotate.cs

@ -56,7 +56,7 @@ namespace ImageSharp
where TPacked : struct
{
RotateProcessor<TColor, TPacked> processor = new RotateProcessor<TColor, TPacked> { Angle = degrees, Expand = expand };
return source.Process(source.Width, source.Height, source.Bounds, source.Bounds, processor);
return source.Process(source.Bounds, processor);
}
}
}

0
src/ImageSharp/Samplers/Transforms/RotateFlip.cs → src/ImageSharp/Filters/Transforms/RotateFlip.cs

2
src/ImageSharp/Samplers/Transforms/Skew.cs → src/ImageSharp/Filters/Transforms/Skew.cs

@ -43,7 +43,7 @@ namespace ImageSharp
where TPacked : struct
{
SkewProcessor<TColor, TPacked> processor = new SkewProcessor<TColor, TPacked> { AngleX = degreesX, AngleY = degreesY, Expand = expand };
return source.Process(source.Width, source.Height, source.Bounds, source.Bounds, processor);
return source.Process(source.Bounds, 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;
}
}
}

26
src/ImageSharp/Image/PixelAccessor.cs

@ -64,6 +64,32 @@ namespace ImageSharp
this.RowStride = this.Width * this.PixelSize;
}
/// <summary>
/// Initializes a new instance of the <see cref="PixelAccessor{TColor,TPacked}"/> class.
/// </summary>
/// <param name="width">Gets the width of the image represented by the pixel buffer.</param>
/// <param name="height">The height of the image represented by the pixel buffer.</param>
/// <param name="pixels">The pixel buffer.</param>
public PixelAccessor(int width, int height, TColor[] pixels)
{
Guard.NotNull(pixels, nameof(pixels));
Guard.MustBeGreaterThan(width, 0, nameof(width));
Guard.MustBeGreaterThan(height, 0, nameof(height));
if (pixels.Length != width * height)
{
throw new ArgumentException("Pixel array must have the length of Width * Height.");
}
this.Width = width;
this.Height = height;
this.pixelsHandle = GCHandle.Alloc(pixels, GCHandleType.Pinned);
this.dataPointer = this.pixelsHandle.AddrOfPinnedObject();
this.pixelsBase = (byte*)this.dataPointer.ToPointer();
this.PixelSize = Unsafe.SizeOf<TPacked>();
this.RowStride = this.Width * this.PixelSize;
}
/// <summary>
/// Finalizes an instance of the <see cref="PixelAccessor{TColor,TPacked}"/> class.
/// </summary>

55
src/ImageSharp/Samplers/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 PixelateProcesso<TColor, TPacked>(size));
}
}
}

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)
{
}
}
}

49
src/ImageSharp/Samplers/Processors/Transforms/CropProcessor.cs

@ -1,49 +0,0 @@
// <copyright file="CropProcessor.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.Threading.Tasks;
/// <summary>
/// Provides methods to allow the cropping of an image.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
public class CropProcessor<TColor, TPacked> : ImageSamplingProcessor<TColor, TPacked>
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
/// <inheritdoc/>
public override void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
{
int startX = targetRectangle.X;
int endX = targetRectangle.Right;
int sourceX = sourceRectangle.X;
int sourceY = sourceRectangle.Y;
Guard.MustBeGreaterThanOrEqualTo(startX, sourceX, nameof(targetRectangle));
Guard.MustBeGreaterThanOrEqualTo(startY, sourceY, nameof(targetRectangle));
Guard.MustBeLessThanOrEqualTo(endX, sourceRectangle.Right, nameof(targetRectangle));
Guard.MustBeLessThanOrEqualTo(endY, sourceRectangle.Bottom, nameof(targetRectangle));
using (PixelAccessor<TColor, TPacked> sourcePixels = source.Lock())
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock())
{
Parallel.For(
startY,
endY,
this.ParallelOptions,
y =>
{
for (int x = startX; x < endX; x++)
{
targetPixels[x, y] = sourcePixels[x + sourceX, y + sourceY];
}
});
}
}
}
}

107
src/ImageSharp/Samplers/Processors/Transforms/EntropyCropProcessor.cs

@ -1,107 +0,0 @@
// <copyright file="EntropyCropProcessor.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;
using System.Threading.Tasks;
/// <summary>
/// Provides methods to allow the cropping of an image to preserve areas of highest
/// entropy.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
public class EntropyCropProcessor<TColor, TPacked> : ImageSamplingProcessor<TColor, TPacked>
where TColor : struct, IPackedPixel<TPacked>
where TPacked : struct
{
/// <summary>
/// The rectangle for cropping
/// </summary>
private Rectangle cropRectangle;
/// <summary>
/// Initializes a new instance of the <see cref="EntropyCropProcessor{TColor, TPacked}"/> class.
/// </summary>
/// <param name="threshold">The threshold to split the image. Must be between 0 and 1.</param>
/// <exception cref="System.ArgumentException">
/// <paramref name="threshold"/> is less than 0 or is greater than 1.
/// </exception>
public EntropyCropProcessor(float threshold)
{
Guard.MustBeBetweenOrEqualTo(threshold, 0, 1, nameof(threshold));
this.Value = threshold;
}
/// <summary>
/// Gets the threshold value.
/// </summary>
public float Value { get; }
/// <inheritdoc/>
public override void Apply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
{
// Jump out, we'll deal with that later.
if (source.Bounds == target.Bounds)
{
return;
}
int targetY = this.cropRectangle.Y;
int targetBottom = this.cropRectangle.Bottom;
int startX = this.cropRectangle.X;
int endX = this.cropRectangle.Right;
int minY = Math.Max(targetY, startY);
int maxY = Math.Min(targetBottom, endY);
using (PixelAccessor<TColor, TPacked> sourcePixels = source.Lock())
using (PixelAccessor<TColor, TPacked> targetPixels = target.Lock())
{
Parallel.For(
minY,
maxY,
this.ParallelOptions,
y =>
{
for (int x = startX; x < endX; x++)
{
targetPixels[x - startX, y - targetY] = sourcePixels[x, y];
}
});
}
}
/// <inheritdoc/>
protected override void OnApply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle)
{
ImageBase<TColor, TPacked> temp = new Image<TColor, TPacked>(source.Width, source.Height);
// Detect the edges.
new SobelProcessor<TColor, TPacked>().Apply(temp, source, sourceRectangle);
// Apply threshold binarization filter.
new BinaryThresholdProcessor<TColor, TPacked>(.5f).Apply(temp, sourceRectangle);
// Search for the first white pixels
Rectangle rectangle = ImageMaths.GetFilteredBoundingRectangle(temp, 0);
// Reset the target pixel to the correct size.
target.SetPixels(rectangle.Width, rectangle.Height, new TColor[rectangle.Width * rectangle.Height]);
this.cropRectangle = rectangle;
}
/// <inheritdoc/>
protected override void AfterApply(ImageBase<TColor, TPacked> target, ImageBase<TColor, TPacked> source, Rectangle targetRectangle, Rectangle sourceRectangle)
{
// Copy the pixels over.
if (source.Bounds == target.Bounds)
{
target.ClonePixels(target.Width, target.Height, source.Pixels);
}
}
}
}

0
tests/ImageSharp.Tests/Processors/Samplers/AutoOrientTests.cs → tests/ImageSharp.Tests/Processors/Filters/AutoOrientTests.cs

0
tests/ImageSharp.Tests/Processors/Samplers/CropTest.cs → tests/ImageSharp.Tests/Processors/Filters/CropTest.cs

6
tests/ImageSharp.Tests/Processors/Samplers/DetectEdgesTest.cs → tests/ImageSharp.Tests/Processors/Filters/DetectEdgesTest.cs

@ -23,7 +23,7 @@ namespace ImageSharp.Tests
EdgeDetection.RobertsCross,
EdgeDetection.Robinson,
EdgeDetection.Scharr,
EdgeDetection.Sobel,
EdgeDetection.Sobel
};
[Theory]
@ -40,7 +40,7 @@ namespace ImageSharp.Tests
using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{
image.DetectEdges(detector)
.Save(output);
.Save(output);
}
}
}
@ -59,7 +59,7 @@ namespace ImageSharp.Tests
using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{
image.DetectEdges(detector, new Rectangle(image.Width / 4, image.Height / 4, image.Width / 2, image.Height / 2))
.Save(output);
.Save(output);
}
}
}

0
tests/ImageSharp.Tests/Processors/Samplers/EntropyCropTest.cs → tests/ImageSharp.Tests/Processors/Filters/EntropyCropTest.cs

0
tests/ImageSharp.Tests/Processors/Samplers/FlipTests.cs → tests/ImageSharp.Tests/Processors/Filters/FlipTests.cs

14
tests/ImageSharp.Tests/Processors/Samplers/GuassianBlurTest.cs → tests/ImageSharp.Tests/Processors/Filters/GaussianBlurTest.cs

@ -1,4 +1,4 @@
// <copyright file="GuassianBlurTest.cs" company="James Jackson-South">
// <copyright file="GaussianBlurTest.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
@ -9,9 +9,9 @@ namespace ImageSharp.Tests
using Xunit;
public class GuassianBlurTest : FileTestBase
public class GaussianBlurTest : FileTestBase
{
public static readonly TheoryData<int> GuassianBlurValues
public static readonly TheoryData<int> GaussianBlurValues
= new TheoryData<int>
{
3 ,
@ -19,10 +19,10 @@ namespace ImageSharp.Tests
};
[Theory]
[MemberData("GuassianBlurValues")]
public void ImageShouldApplyGuassianBlurFilter(int value)
[MemberData("GaussianBlurValues")]
public void ImageShouldApplyGaussianBlurFilter(int value)
{
string path = CreateOutputDirectory("GuassianBlur");
string path = CreateOutputDirectory("GaussianBlur");
foreach (TestFile file in Files)
{
@ -31,7 +31,7 @@ namespace ImageSharp.Tests
using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{
image.GuassianBlur(value)
image.GaussianBlur(value)
.Save(output);
}
}

14
tests/ImageSharp.Tests/Processors/Samplers/GuassianSharpenTest.cs → tests/ImageSharp.Tests/Processors/Filters/GaussianSharpenTest.cs

@ -1,4 +1,4 @@
// <copyright file="GuassianSharpenTest.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>
@ -9,9 +9,9 @@ namespace ImageSharp.Tests
using Xunit;
public class GuassianSharpenTest : FileTestBase
public class GaussianSharpenTest : FileTestBase
{
public static readonly TheoryData<int> GuassianSharpenValues
public static readonly TheoryData<int> GaussianSharpenValues
= new TheoryData<int>
{
3 ,
@ -19,10 +19,10 @@ namespace ImageSharp.Tests
};
[Theory]
[MemberData("GuassianSharpenValues")]
public void ImageShouldApplyGuassianSharpenFilter(int value)
[MemberData("GaussianSharpenValues")]
public void ImageShouldApplyGaussianSharpenFilter(int value)
{
string path = CreateOutputDirectory("GuassianSharpen");
string path = CreateOutputDirectory("GaussianSharpen");
foreach (TestFile file in Files)
{
@ -31,7 +31,7 @@ namespace ImageSharp.Tests
using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{
image.GuassianSharpen(value)
image.GaussianSharpen(value)
.Save(output);
}
}

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

0
tests/ImageSharp.Tests/Processors/Samplers/PadTest.cs → tests/ImageSharp.Tests/Processors/Filters/PadTest.cs

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

5
tests/ImageSharp.Tests/Processors/Samplers/ResizeTests.cs → tests/ImageSharp.Tests/Processors/Filters/ResizeTests.cs

@ -5,6 +5,7 @@
namespace ImageSharp.Tests
{
using System;
using System.IO;
using Xunit;
@ -248,7 +249,7 @@ namespace ImageSharp.Tests
ResizeOptions options = new ResizeOptions()
{
Sampler = sampler,
Size = new Size(image.Width - 50, image.Height - 25),
Size = new Size((int)Math.Round(image.Width * .75F), (int)Math.Round(image.Height * 95F)),
Mode = ResizeMode.Min
};
@ -276,7 +277,7 @@ namespace ImageSharp.Tests
ResizeOptions options = new ResizeOptions()
{
Sampler = sampler,
Size = new Size(image.Width - 200, image.Height),
Size = new Size(image.Width / 2, image.Height),
Mode = ResizeMode.Stretch
};

0
tests/ImageSharp.Tests/Processors/Samplers/RotateFlipTest.cs → tests/ImageSharp.Tests/Processors/Filters/RotateFlipTest.cs

0
tests/ImageSharp.Tests/Processors/Samplers/RotateTest.cs → tests/ImageSharp.Tests/Processors/Filters/RotateTest.cs

0
tests/ImageSharp.Tests/Processors/Samplers/SkewTest.cs → tests/ImageSharp.Tests/Processors/Filters/SkewTest.cs

60
tests/ImageSharp.Tests/Processors/Samplers/OilPaintTest.cs

@ -1,60 +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>(6,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}"))
{
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}"))
{
image.OilPaint(value.Item1, value.Item2, new Rectangle(10, 10, image.Width / 2, image.Height / 2))
.Save(output);
}
}
}
}
}

59
tests/ImageSharp.Tests/Processors/Samplers/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