mirror of https://github.com/SixLabors/ImageSharp
55 changed files with 372 additions and 316 deletions
@ -0,0 +1,47 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using System.Numerics; |
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
using SixLabors.ImageSharp.Processing.Processors; |
||||
|
using SixLabors.Primitives; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Extension methods for the <see cref="Image{TPixel}"/> type.
|
||||
|
/// </summary>
|
||||
|
public static partial class ImageExtensions |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Filters an image but the given color matrix
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
||||
|
/// <param name="source">The image this method extends.</param>
|
||||
|
/// <param name="matrix">The filter color matrix</param>
|
||||
|
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
|
||||
|
public static IImageProcessingContext<TPixel> Filter<TPixel>(this IImageProcessingContext<TPixel> source, Matrix4x4 matrix) |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
source.ApplyProcessor(new FilterProcessor<TPixel>(matrix)); |
||||
|
return source; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Filters an image but the given color matrix
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
||||
|
/// <param name="source">The image this method extends.</param>
|
||||
|
/// <param name="matrix">The filter color matrix</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{TPixel}"/>.</returns>
|
||||
|
public static IImageProcessingContext<TPixel> Filter<TPixel>(this IImageProcessingContext<TPixel> source, Matrix4x4 matrix, Rectangle rectangle) |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
source.ApplyProcessor(new FilterProcessor<TPixel>(matrix), rectangle); |
||||
|
return source; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,34 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using System.Numerics; |
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Processing.Processors |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Converts the colors of the image recreating Achromatomaly (Color desensitivity) color blindness.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
||||
internal class AchromatomalyProcessor<TPixel> : ColorMatrixProcessor<TPixel> |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
/// <inheritdoc/>
|
|
||||
public override Matrix4x4 Matrix => new Matrix4x4 |
|
||||
{ |
|
||||
M11 = .618F, |
|
||||
M12 = .163F, |
|
||||
M13 = .163F, |
|
||||
M21 = .320F, |
|
||||
M22 = .775F, |
|
||||
M23 = .320F, |
|
||||
M31 = .062F, |
|
||||
M32 = .062F, |
|
||||
M33 = .516F, |
|
||||
M44 = 1 |
|
||||
}; |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override bool Compand => false; |
|
||||
} |
|
||||
} |
|
||||
@ -1,34 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using System.Numerics; |
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Processing.Processors |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Converts the colors of the image recreating Achromatopsia (Monochrome) color blindness.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
||||
internal class AchromatopsiaProcessor<TPixel> : ColorMatrixProcessor<TPixel> |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
/// <inheritdoc/>
|
|
||||
public override Matrix4x4 Matrix => new Matrix4x4 |
|
||||
{ |
|
||||
M11 = .299F, |
|
||||
M12 = .299F, |
|
||||
M13 = .299F, |
|
||||
M21 = .587F, |
|
||||
M22 = .587F, |
|
||||
M23 = .587F, |
|
||||
M31 = .114F, |
|
||||
M32 = .114F, |
|
||||
M33 = .114F, |
|
||||
M44 = 1 |
|
||||
}; |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override bool Compand => false; |
|
||||
} |
|
||||
} |
|
||||
@ -1,31 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using System.Numerics; |
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Processing.Processors |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Converts the colors of the image recreating Protanopia (Red-Weak) color blindness.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
||||
internal class ProtanomalyProcessor<TPixel> : ColorMatrixProcessor<TPixel> |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
/// <inheritdoc/>
|
|
||||
public override Matrix4x4 Matrix => new Matrix4x4 |
|
||||
{ |
|
||||
M11 = 0.817F, |
|
||||
M12 = 0.333F, |
|
||||
M21 = 0.183F, |
|
||||
M22 = 0.667F, |
|
||||
M23 = 0.125F, |
|
||||
M33 = 0.875F, |
|
||||
M44 = 1 |
|
||||
}; |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public override bool Compand => false; |
|
||||
} |
|
||||
} |
|
||||
@ -1,78 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using System; |
|
||||
using System.Numerics; |
|
||||
using System.Threading.Tasks; |
|
||||
using SixLabors.ImageSharp.Advanced; |
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
using SixLabors.Primitives; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Processing.Processors |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// The color matrix filter. Inherit from this class to perform operation involving color matrices.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
||||
internal abstract class ColorMatrixProcessor<TPixel> : ImageProcessor<TPixel>, IColorMatrixProcessor<TPixel> |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
/// <inheritdoc/>
|
|
||||
public abstract Matrix4x4 Matrix { get; } |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
public virtual bool Compand { get; set; } = true; |
|
||||
|
|
||||
/// <inheritdoc/>
|
|
||||
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration) |
|
||||
{ |
|
||||
int startY = sourceRectangle.Y; |
|
||||
int endY = sourceRectangle.Bottom; |
|
||||
int startX = sourceRectangle.X; |
|
||||
int endX = sourceRectangle.Right; |
|
||||
|
|
||||
// Align start/end positions.
|
|
||||
int minX = Math.Max(0, startX); |
|
||||
int maxX = Math.Min(source.Width, endX); |
|
||||
int minY = Math.Max(0, startY); |
|
||||
int maxY = Math.Min(source.Height, endY); |
|
||||
|
|
||||
// Reset offset if necessary.
|
|
||||
if (minX > 0) |
|
||||
{ |
|
||||
startX = 0; |
|
||||
} |
|
||||
|
|
||||
if (minY > 0) |
|
||||
{ |
|
||||
startY = 0; |
|
||||
} |
|
||||
|
|
||||
Matrix4x4 matrix = this.Matrix; |
|
||||
bool compand = this.Compand; |
|
||||
|
|
||||
Parallel.For( |
|
||||
minY, |
|
||||
maxY, |
|
||||
configuration.ParallelOptions, |
|
||||
y => |
|
||||
{ |
|
||||
Span<TPixel> row = source.GetPixelRowSpan(y - startY); |
|
||||
|
|
||||
for (int x = minX; x < maxX; x++) |
|
||||
{ |
|
||||
ref TPixel pixel = ref row[x - startX]; |
|
||||
var vector = pixel.ToVector4(); |
|
||||
|
|
||||
if (compand) |
|
||||
{ |
|
||||
vector = vector.Expand(); |
|
||||
} |
|
||||
|
|
||||
vector = Vector4.Transform(vector, matrix); |
|
||||
pixel.PackFromVector4(compand ? vector.Compress() : vector); |
|
||||
} |
|
||||
}); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,27 +0,0 @@ |
|||||
// Copyright (c) Six Labors and contributors.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
|
|
||||
using System.Numerics; |
|
||||
using SixLabors.ImageSharp.PixelFormats; |
|
||||
|
|
||||
namespace SixLabors.ImageSharp.Processing.Processors |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Encapsulates properties and methods for creating processors that utilize a matrix to
|
|
||||
/// alter the image pixels.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|
||||
internal interface IColorMatrixProcessor<TPixel> : IImageProcessor<TPixel> |
|
||||
where TPixel : struct, IPixel<TPixel> |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Gets the <see cref="Matrix4x4"/> used to alter the image.
|
|
||||
/// </summary>
|
|
||||
Matrix4x4 Matrix { get; } |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Gets or sets a value indicating whether to compress or expand individual pixel color values on processing.
|
|
||||
/// </summary>
|
|
||||
bool Compand { get; set; } |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,23 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Processing.Processors |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Converts the colors of the image recreating Achromatomaly (Color desensitivity) color blindness.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
||||
|
internal class AchromatomalyProcessor<TPixel> : FilterProcessor<TPixel> |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="AchromatomalyProcessor{TPixel}"/> class.
|
||||
|
/// </summary>
|
||||
|
public AchromatomalyProcessor() |
||||
|
: base(MatrixFilters.AchromatomalyFilter) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Processing.Processors |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Converts the colors of the image recreating Achromatopsia (Monochrome) color blindness.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
||||
|
internal class AchromatopsiaProcessor<TPixel> : FilterProcessor<TPixel> |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="AchromatopsiaProcessor{TPixel}"/> class.
|
||||
|
/// </summary>
|
||||
|
public AchromatopsiaProcessor() |
||||
|
: base(MatrixFilters.AchromatopsiaFilter) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Processing.Processors |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Converts the colors of the image recreating Protanomaly (Red-Weak) color blindness.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
||||
|
internal class ProtanomalyProcessor<TPixel> : FilterProcessor<TPixel> |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="ProtanomalyProcessor{TPixel}"/> class.
|
||||
|
/// </summary>
|
||||
|
public ProtanomalyProcessor() |
||||
|
: base(MatrixFilters.ProtanomalyFilter) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,26 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.Processing; |
||||
|
using SixLabors.ImageSharp.Processing.Processors; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Tests.Processing.Filters |
||||
|
{ |
||||
|
public class FilterTest : BaseImageOperationsExtensionTest |
||||
|
{ |
||||
|
[Fact] |
||||
|
public void Filter_CorrectProcessor() |
||||
|
{ |
||||
|
this.operations.Filter(MatrixFilters.AchromatomalyFilter * MatrixFilters.CreateHueFilter(90F)); |
||||
|
FilterProcessor<Rgba32> p = this.Verify<FilterProcessor<Rgba32>>(); |
||||
|
} |
||||
|
|
||||
|
[Fact] |
||||
|
public void Filter_rect_CorrectProcessor() |
||||
|
{ |
||||
|
this.operations.Filter(MatrixFilters.AchromatomalyFilter * MatrixFilters.CreateHueFilter(90F), this.rect); |
||||
|
FilterProcessor<Rgba32> p = this.Verify<FilterProcessor<Rgba32>>(this.rect); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,44 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
using SixLabors.ImageSharp.Processing; |
||||
|
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; |
||||
|
|
||||
|
using SixLabors.Primitives; |
||||
|
using Xunit; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Filters |
||||
|
{ |
||||
|
public class FilterTest : FileTestBase |
||||
|
{ |
||||
|
[Theory] |
||||
|
[WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] |
||||
|
public void ImageShouldApplyFilter<TPixel>(TestImageProvider<TPixel> provider) |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
using (Image<TPixel> image = provider.GetImage()) |
||||
|
{ |
||||
|
image.Mutate(x => x.Filter(MatrixFilters.CreateBrightnessFilter(1.2F) * MatrixFilters.CreateContrastFilter(1.2F))); |
||||
|
image.DebugSave(provider); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[WithFileCollection(nameof(DefaultFiles), DefaultPixelType)] |
||||
|
public void ImageShouldApplyFilterInBox<TPixel>(TestImageProvider<TPixel> provider) |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
using (Image<TPixel> source = provider.GetImage()) |
||||
|
using (Image<TPixel> image = source.Clone()) |
||||
|
{ |
||||
|
var bounds = new Rectangle(10, 10, image.Width / 2, image.Height / 2); |
||||
|
|
||||
|
image.Mutate(x => x.Filter(MatrixFilters.CreateBrightnessFilter(1.2F) * MatrixFilters.CreateContrastFilter(1.2F), bounds)); |
||||
|
image.DebugSave(provider); |
||||
|
|
||||
|
ImageComparer.Tolerant().VerifySimilarityIgnoreRegion(source, image, bounds); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue