mirror of https://github.com/SixLabors/ImageSharp
15 changed files with 14 additions and 497 deletions
@ -1,55 +0,0 @@ |
|||||
// <copyright file="Pixelate.cs" company="James Jackson-South">
|
|
||||
// Copyright (c) James Jackson-South and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
// </copyright>
|
|
||||
|
|
||||
namespace ImageSharp |
|
||||
{ |
|
||||
using System; |
|
||||
|
|
||||
using Processors; |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Extension methods for the <see cref="Image{TColor, TPacked}"/> type.
|
|
||||
/// </summary>
|
|
||||
public static partial class ImageExtensions |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Pixelates an image with the given pixel size.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TColor">The pixel format.</typeparam>
|
|
||||
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
|
|
||||
/// <param name="source">The image this method extends.</param>
|
|
||||
/// <param name="size">The size of the pixels.</param>
|
|
||||
/// <returns>The <see cref="Image{TColor, TPacked}"/>.</returns>
|
|
||||
public static Image<TColor, TPacked> Pixelate<TColor, TPacked>(this Image<TColor, TPacked> source, int size = 4) |
|
||||
where TColor : struct, IPackedPixel<TPacked> |
|
||||
where TPacked : struct |
|
||||
{ |
|
||||
return Pixelate(source, size, source.Bounds); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Pixelates an image with the given pixel size.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TColor">The pixel format.</typeparam>
|
|
||||
/// <typeparam name="TPacked">The packed format. <example>uint, long, float.</example></typeparam>
|
|
||||
/// <param name="source">The image this method extends.</param>
|
|
||||
/// <param name="size">The size of the pixels.</param>
|
|
||||
/// <param name="rectangle">
|
|
||||
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
|
|
||||
/// </param>
|
|
||||
/// <returns>The <see cref="Image{TColor, TPacked}"/>.</returns>
|
|
||||
public static Image<TColor, TPacked> Pixelate<TColor, TPacked>(this Image<TColor, TPacked> source, int size, Rectangle rectangle) |
|
||||
where TColor : struct, IPackedPixel<TPacked> |
|
||||
where TPacked : struct |
|
||||
{ |
|
||||
if (size <= 0 || size > source.Height || size > source.Width) |
|
||||
{ |
|
||||
throw new ArgumentOutOfRangeException(nameof(size)); |
|
||||
} |
|
||||
|
|
||||
return source.Process(rectangle, new PixelateProcessor<TColor, TPacked>(size)); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,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); |
|
||||
} |
|
||||
} |
|
||||
@ -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) |
|
||||
{ |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,66 +0,0 @@ |
|||||
// <copyright file="OilPaintTest.cs" company="James Jackson-South">
|
|
||||
// Copyright (c) James Jackson-South and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
// </copyright>
|
|
||||
|
|
||||
namespace ImageSharp.Tests |
|
||||
{ |
|
||||
using System; |
|
||||
using System.IO; |
|
||||
|
|
||||
using Xunit; |
|
||||
|
|
||||
public class OilPaintTest : FileTestBase |
|
||||
{ |
|
||||
public static readonly TheoryData<Tuple<int, int>> OilPaintValues |
|
||||
= new TheoryData<Tuple<int, int>> |
|
||||
{ |
|
||||
new Tuple<int, int>(15, 10), |
|
||||
new Tuple<int, int>(8, 5) |
|
||||
}; |
|
||||
|
|
||||
[Theory] |
|
||||
[MemberData(nameof(OilPaintValues))] |
|
||||
public void ImageShouldApplyOilPaintFilter(Tuple<int, int> value) |
|
||||
{ |
|
||||
string path = CreateOutputDirectory("OilPaint"); |
|
||||
|
|
||||
foreach (TestFile file in Files) |
|
||||
{ |
|
||||
string filename = file.GetFileName(value); |
|
||||
Image image = file.CreateImage(); |
|
||||
|
|
||||
using (FileStream output = File.OpenWrite($"{path}/{filename}")) |
|
||||
{ |
|
||||
if (value.Item2 < image.Width && value.Item2 < image.Height) |
|
||||
{ |
|
||||
image.OilPaint(value.Item1, value.Item2) |
|
||||
.Save(output); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
[Theory] |
|
||||
[MemberData(nameof(OilPaintValues))] |
|
||||
public void ImageShouldApplyOilPaintFilterInBox(Tuple<int, int> value) |
|
||||
{ |
|
||||
string path = CreateOutputDirectory("OilPaint"); |
|
||||
|
|
||||
foreach (TestFile file in Files) |
|
||||
{ |
|
||||
string filename = file.GetFileName(value + "-InBox"); |
|
||||
Image image = file.CreateImage(); |
|
||||
|
|
||||
using (FileStream output = File.OpenWrite($"{path}/{filename}")) |
|
||||
{ |
|
||||
if (value.Item2 < image.Width && value.Item2 < image.Height) |
|
||||
{ |
|
||||
image.OilPaint(value.Item1, value.Item2, new Rectangle(image.Width / 4, image.Width / 4, image.Width / 2, image.Height / 2)) |
|
||||
.Save(output); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -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…
Reference in new issue