From 1421500a18cc51ce8f510c77f3586e07c79a7a5a Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Fri, 20 Dec 2019 14:20:23 +0100 Subject: [PATCH] Added PositionAwarePixelShader types --- .../Delegates/PositionAwarePixelShader.cs | 14 ++++ .../DelegatePixelShaderProcessor{TPixel}.cs | 2 +- .../PositionAwarePixelShaderProcessor.cs | 38 +++++++++++ ...sitionAwarePixelShaderProcessor{TPixel}.cs | 65 +++++++++++++++++++ 4 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 src/ImageSharp/Processing/Delegates/PositionAwarePixelShader.cs create mode 100644 src/ImageSharp/Processing/Processors/PixelShading/PositionAwarePixelShaderProcessor.cs create mode 100644 src/ImageSharp/Processing/Processors/PixelShading/PositionAwarePixelShaderProcessor{TPixel}.cs diff --git a/src/ImageSharp/Processing/Delegates/PositionAwarePixelShader.cs b/src/ImageSharp/Processing/Delegates/PositionAwarePixelShader.cs new file mode 100644 index 000000000..08314600a --- /dev/null +++ b/src/ImageSharp/Processing/Delegates/PositionAwarePixelShader.cs @@ -0,0 +1,14 @@ +using System; +using System.Numerics; + +namespace SixLabors.ImageSharp.Processing.Delegates +{ + /// + /// A representing a user defined pixel shader. + /// + /// The target row of pixels to process. + /// The initial vertical offset for the input pixels to process. + /// The initial horizontal offset for the input pixels to process. + /// The , , , and fields map the RGBA channels respectively. + public delegate void PositionAwarePixelShader(Span span, int offsetY, int offsetX); +} diff --git a/src/ImageSharp/Processing/Processors/PixelShading/DelegatePixelShaderProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/PixelShading/DelegatePixelShaderProcessor{TPixel}.cs index c773e8b80..d15614cc4 100644 --- a/src/ImageSharp/Processing/Processors/PixelShading/DelegatePixelShaderProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/PixelShading/DelegatePixelShaderProcessor{TPixel}.cs @@ -13,7 +13,7 @@ using SixLabors.Primitives; namespace SixLabors.ImageSharp.Processing.Processors.PixelShading { /// - /// Performs simple binary threshold filtering against an image. + /// Applies a user defined pixel shader effect through a given delegate. /// /// The pixel format. internal class DelegatePixelShaderProcessor : ImageProcessor diff --git a/src/ImageSharp/Processing/Processors/PixelShading/PositionAwarePixelShaderProcessor.cs b/src/ImageSharp/Processing/Processors/PixelShading/PositionAwarePixelShaderProcessor.cs new file mode 100644 index 000000000..60125b2e2 --- /dev/null +++ b/src/ImageSharp/Processing/Processors/PixelShading/PositionAwarePixelShaderProcessor.cs @@ -0,0 +1,38 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing.Delegates; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.PixelShading +{ + /// + /// Applies a user defined pixel shader effect through a given delegate. + /// + public sealed class PositionAwarePixelShaderProcessor : IImageProcessor + { + /// + /// Initializes a new instance of the class. + /// + /// + /// The user defined pixel shader to use to modify images. + /// + public PositionAwarePixelShaderProcessor(PositionAwarePixelShader pixelShader) + { + this.PixelShader = pixelShader; + } + + /// + /// Gets the user defined pixel shader. + /// + public PositionAwarePixelShader PixelShader { get; } + + /// + public IImageProcessor CreatePixelSpecificProcessor(Image source, Rectangle sourceRectangle) + where TPixel : struct, IPixel + { + return new PositionAwarePixelShader(this, source, sourceRectangle); + } + } +} diff --git a/src/ImageSharp/Processing/Processors/PixelShading/PositionAwarePixelShaderProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/PixelShading/PositionAwarePixelShaderProcessor{TPixel}.cs new file mode 100644 index 000000000..55ad325ad --- /dev/null +++ b/src/ImageSharp/Processing/Processors/PixelShading/PositionAwarePixelShaderProcessor{TPixel}.cs @@ -0,0 +1,65 @@ +// Copyright (c) Six Labors and contributors. +// Licensed under the Apache License, Version 2.0. + +using System; +using System.Numerics; + +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Advanced.ParallelUtils; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing.Delegates; +using SixLabors.Primitives; + +namespace SixLabors.ImageSharp.Processing.Processors.PixelShading +{ + /// + /// Applies a user defined pixel shader effect through a given delegate. + /// + /// The pixel format. + internal class PositionAwarePixelShaderProcessor : ImageProcessor + where TPixel : struct, IPixel + { + /// + /// The user defined pixel shader. + /// + private readonly PositionAwarePixelShader pixelShader; + + /// + /// Initializes a new instance of the class. + /// + /// The defining the processor parameters. + /// The source for the current processor instance. + /// The source area to process for the current processor instance. + public PositionAwarePixelShaderProcessor(PositionAwarePixelShaderProcessor definition, Image source, Rectangle sourceRectangle) + : base(source, sourceRectangle) + { + this.pixelShader = definition.PixelShader; + } + + /// + protected override void OnFrameApply(ImageFrame source) + { + var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds()); + int startX = interest.X; + PositionAwarePixelShader pixelShader = this.pixelShader; + + ParallelHelper.IterateRowsWithTempBuffer( + interest, + this.Configuration, + (rows, vectorBuffer) => + { + for (int y = rows.Min; y < rows.Max; y++) + { + Span vectorSpan = vectorBuffer.Span; + int length = vectorSpan.Length; + Span rowSpan = source.GetPixelRowSpan(y).Slice(startX, length); + PixelOperations.Instance.ToVector4(this.Configuration, rowSpan, vectorSpan); + + pixelShader(vectorSpan, y, startX); + + PixelOperations.Instance.FromVector4Destructive(this.Configuration, vectorSpan, rowSpan); + } + }); + } + } +}