mirror of https://github.com/SixLabors/ImageSharp
committed by
GitHub
10 changed files with 522 additions and 1 deletions
@ -0,0 +1,103 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
using SixLabors.ImageSharp.Processing.Processors.Effects; |
||||
|
using SixLabors.Primitives; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Processing |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Defines extension methods that allow the application of user defined pixel shaders to an <see cref="Image"/>.
|
||||
|
/// </summary>
|
||||
|
public static class PixelShaderExtensions |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Applies a user defined pixel shader to the image.
|
||||
|
/// </summary>
|
||||
|
/// <param name="source">The image this method extends.</param>
|
||||
|
/// <param name="pixelShader">The user defined pixel shader to use to modify images.</param>
|
||||
|
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
|
||||
|
public static IImageProcessingContext ApplyPixelShaderProcessor(this IImageProcessingContext source, PixelShader pixelShader) |
||||
|
=> source.ApplyProcessor(new PixelShaderProcessor(pixelShader)); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Applies a user defined pixel shader to the image.
|
||||
|
/// </summary>
|
||||
|
/// <param name="source">The image this method extends.</param>
|
||||
|
/// <param name="pixelShader">The user defined pixel shader to use to modify images.</param>
|
||||
|
/// <param name="modifiers">The <see cref="PixelConversionModifiers"/> to apply during the pixel conversions.</param>
|
||||
|
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
|
||||
|
public static IImageProcessingContext ApplyPixelShaderProcessor(this IImageProcessingContext source, PixelShader pixelShader, PixelConversionModifiers modifiers) |
||||
|
=> source.ApplyProcessor(new PixelShaderProcessor(pixelShader, modifiers)); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Applies a user defined pixel shader to the image.
|
||||
|
/// </summary>
|
||||
|
/// <param name="source">The image this method extends.</param>
|
||||
|
/// <param name="pixelShader">The user defined pixel shader to use to modify images.</param>
|
||||
|
/// <param name="rectangle">
|
||||
|
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
|
||||
|
/// </param>
|
||||
|
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
|
||||
|
public static IImageProcessingContext ApplyPixelShaderProcessor(this IImageProcessingContext source, PixelShader pixelShader, Rectangle rectangle) |
||||
|
=> source.ApplyProcessor(new PixelShaderProcessor(pixelShader), rectangle); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Applies a user defined pixel shader to the image.
|
||||
|
/// </summary>
|
||||
|
/// <param name="source">The image this method extends.</param>
|
||||
|
/// <param name="pixelShader">The user defined pixel shader to use to modify images.</param>
|
||||
|
/// <param name="rectangle">
|
||||
|
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
|
||||
|
/// </param>
|
||||
|
/// <param name="modifiers">The <see cref="PixelConversionModifiers"/> to apply during the pixel conversions.</param>
|
||||
|
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
|
||||
|
public static IImageProcessingContext ApplyPixelShaderProcessor(this IImageProcessingContext source, PixelShader pixelShader, Rectangle rectangle, PixelConversionModifiers modifiers) |
||||
|
=> source.ApplyProcessor(new PixelShaderProcessor(pixelShader, modifiers), rectangle); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Applies a user defined pixel shader to the image.
|
||||
|
/// </summary>
|
||||
|
/// <param name="source">The image this method extends.</param>
|
||||
|
/// <param name="pixelShader">The user defined pixel shader to use to modify images.</param>
|
||||
|
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
|
||||
|
public static IImageProcessingContext ApplyPixelShaderProcessor(this IImageProcessingContext source, PositionAwarePixelShader pixelShader) |
||||
|
=> source.ApplyProcessor(new PositionAwarePixelShaderProcessor(pixelShader)); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Applies a user defined pixel shader to the image.
|
||||
|
/// </summary>
|
||||
|
/// <param name="source">The image this method extends.</param>
|
||||
|
/// <param name="pixelShader">The user defined pixel shader to use to modify images.</param>
|
||||
|
/// <param name="modifiers">The <see cref="PixelConversionModifiers"/> to apply during the pixel conversions.</param>
|
||||
|
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
|
||||
|
public static IImageProcessingContext ApplyPixelShaderProcessor(this IImageProcessingContext source, PositionAwarePixelShader pixelShader, PixelConversionModifiers modifiers) |
||||
|
=> source.ApplyProcessor(new PositionAwarePixelShaderProcessor(pixelShader, modifiers)); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Applies a user defined pixel shader to the image.
|
||||
|
/// </summary>
|
||||
|
/// <param name="source">The image this method extends.</param>
|
||||
|
/// <param name="pixelShader">The user defined pixel shader to use to modify images.</param>
|
||||
|
/// <param name="rectangle">
|
||||
|
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
|
||||
|
/// </param>
|
||||
|
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
|
||||
|
public static IImageProcessingContext ApplyPixelShaderProcessor(this IImageProcessingContext source, PositionAwarePixelShader pixelShader, Rectangle rectangle) |
||||
|
=> source.ApplyProcessor(new PositionAwarePixelShaderProcessor(pixelShader), rectangle); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Applies a user defined pixel shader to the image.
|
||||
|
/// </summary>
|
||||
|
/// <param name="source">The image this method extends.</param>
|
||||
|
/// <param name="pixelShader">The user defined pixel shader to use to modify images.</param>
|
||||
|
/// <param name="rectangle">
|
||||
|
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
|
||||
|
/// </param>
|
||||
|
/// <param name="modifiers">The <see cref="PixelConversionModifiers"/> to apply during the pixel conversions.</param>
|
||||
|
/// <returns>The <see cref="IImageProcessingContext"/> to allow chaining of operations.</returns>
|
||||
|
public static IImageProcessingContext ApplyPixelShaderProcessor(this IImageProcessingContext source, PositionAwarePixelShader pixelShader, Rectangle rectangle, PixelConversionModifiers modifiers) |
||||
|
=> source.ApplyProcessor(new PositionAwarePixelShaderProcessor(pixelShader, modifiers), rectangle); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,15 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using System; |
||||
|
using System.Numerics; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Processing |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// A <see langword="delegate"/> representing a user defined pixel shader.
|
||||
|
/// </summary>
|
||||
|
/// <param name="span">The target row of <see cref="Vector4"/> pixels to process.</param>
|
||||
|
/// <remarks>The <see cref="Vector4.X"/>, <see cref="Vector4.Y"/>, <see cref="Vector4.Z"/>, and <see cref="Vector4.W"/> fields map the RGBA channels respectively.</remarks>
|
||||
|
public delegate void PixelShader(Span<Vector4> span); |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using System; |
||||
|
using System.Numerics; |
||||
|
using SixLabors.Primitives; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Processing |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// A <see langword="delegate"/> representing a user defined pixel shader.
|
||||
|
/// </summary>
|
||||
|
/// <param name="span">The target row of <see cref="Vector4"/> pixels to process.</param>
|
||||
|
/// <param name="offset">The initial horizontal and vertical offset for the input pixels to process.</param>
|
||||
|
/// <remarks>The <see cref="Vector4.X"/>, <see cref="Vector4.Y"/>, <see cref="Vector4.Z"/>, and <see cref="Vector4.W"/> fields map the RGBA channels respectively.</remarks>
|
||||
|
public delegate void PositionAwarePixelShader(Span<Vector4> span, Point offset); |
||||
|
} |
||||
@ -0,0 +1,61 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
using SixLabors.Primitives; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Processing.Processors.Effects |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Applies a user defined pixel shader effect through a given delegate.
|
||||
|
/// </summary>
|
||||
|
public sealed class PixelShaderProcessor : IImageProcessor |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The default <see cref="PixelConversionModifiers"/> to apply during the pixel conversions.
|
||||
|
/// </summary>
|
||||
|
public const PixelConversionModifiers DefaultModifiers = PixelConversionModifiers.None; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="PixelShaderProcessor"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="pixelShader">
|
||||
|
/// The user defined pixel shader to use to modify images.
|
||||
|
/// </param>
|
||||
|
public PixelShaderProcessor(PixelShader pixelShader) |
||||
|
{ |
||||
|
this.PixelShader = pixelShader; |
||||
|
this.Modifiers = DefaultModifiers; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="PixelShaderProcessor"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="pixelShader">
|
||||
|
/// The user defined pixel shader to use to modify images.
|
||||
|
/// </param>
|
||||
|
/// <param name="modifiers">The <see cref="PixelConversionModifiers"/> to apply during the pixel conversions.</param>
|
||||
|
public PixelShaderProcessor(PixelShader pixelShader, PixelConversionModifiers modifiers) |
||||
|
{ |
||||
|
this.PixelShader = pixelShader; |
||||
|
this.Modifiers = modifiers; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the user defined pixel shader.
|
||||
|
/// </summary>
|
||||
|
public PixelShader PixelShader { get; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the <see cref="PixelConversionModifiers"/> to apply during the pixel conversions.
|
||||
|
/// </summary>
|
||||
|
public PixelConversionModifiers Modifiers { get; } |
||||
|
|
||||
|
/// <inheritdoc />
|
||||
|
public IImageProcessor<TPixel> CreatePixelSpecificProcessor<TPixel>(Image<TPixel> source, Rectangle sourceRectangle) |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
return new PixelShaderProcessor<TPixel>(this, source, sourceRectangle); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,73 @@ |
|||||
|
// 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.Primitives; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Processing.Processors.Effects |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Applies a user defined pixel shader effect through a given delegate.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
||||
|
internal abstract class PixelShaderProcessorBase<TPixel> : ImageProcessor<TPixel> |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The <see cref="PixelConversionModifiers"/> to apply during the pixel conversions.
|
||||
|
/// </summary>
|
||||
|
private readonly PixelConversionModifiers modifiers; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="PixelShaderProcessorBase{TPixel}"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="modifiers">The <see cref="PixelConversionModifiers"/> to apply during the pixel conversions.</param>
|
||||
|
/// <param name="source">The source <see cref="Image{TPixel}"/> for the current processor instance.</param>
|
||||
|
/// <param name="sourceRectangle">The source area to process for the current processor instance.</param>
|
||||
|
protected PixelShaderProcessorBase(PixelConversionModifiers modifiers, Image<TPixel> source, Rectangle sourceRectangle) |
||||
|
: base(source, sourceRectangle) |
||||
|
{ |
||||
|
this.modifiers = modifiers; |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
protected override void OnFrameApply(ImageFrame<TPixel> source) |
||||
|
{ |
||||
|
var interest = Rectangle.Intersect(this.SourceRectangle, source.Bounds()); |
||||
|
int startX = interest.X; |
||||
|
Configuration configuration = this.Configuration; |
||||
|
PixelConversionModifiers modifiers = this.modifiers; |
||||
|
|
||||
|
ParallelHelper.IterateRowsWithTempBuffer<Vector4>( |
||||
|
interest, |
||||
|
this.Configuration, |
||||
|
(rows, vectorBuffer) => |
||||
|
{ |
||||
|
for (int y = rows.Min; y < rows.Max; y++) |
||||
|
{ |
||||
|
Span<Vector4> vectorSpan = vectorBuffer.Span; |
||||
|
int length = vectorSpan.Length; |
||||
|
Span<TPixel> rowSpan = source.GetPixelRowSpan(y).Slice(startX, length); |
||||
|
PixelOperations<TPixel>.Instance.ToVector4(configuration, rowSpan, vectorSpan, modifiers); |
||||
|
|
||||
|
// Run the user defined pixel shader on the current row of pixels
|
||||
|
this.ApplyPixelShader(vectorSpan, new Point(startX, y)); |
||||
|
|
||||
|
PixelOperations<TPixel>.Instance.FromVector4Destructive(configuration, vectorSpan, rowSpan, modifiers); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Applies the current pixel shader effect on a target row of preprocessed pixels.
|
||||
|
/// </summary>
|
||||
|
/// <param name="span">The target row of <see cref="Vector4"/> pixels to process.</param>
|
||||
|
/// <param name="offset">The initial horizontal and vertical offset for the input pixels to process.</param>
|
||||
|
protected abstract void ApplyPixelShader(Span<Vector4> span, Point offset); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,39 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using System; |
||||
|
using System.Numerics; |
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
using SixLabors.Primitives; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Processing.Processors.Effects |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Applies a user defined pixel shader effect through a given delegate.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
||||
|
internal sealed class PixelShaderProcessor<TPixel> : PixelShaderProcessorBase<TPixel> |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The user defined pixel shader.
|
||||
|
/// </summary>
|
||||
|
private readonly PixelShader pixelShader; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="PixelShaderProcessor{TPixel}"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="definition">The <see cref="PixelShaderProcessor"/> defining the processor parameters.</param>
|
||||
|
/// <param name="source">The source <see cref="Image{TPixel}"/> for the current processor instance.</param>
|
||||
|
/// <param name="sourceRectangle">The source area to process for the current processor instance.</param>
|
||||
|
public PixelShaderProcessor(PixelShaderProcessor definition, Image<TPixel> source, Rectangle sourceRectangle) |
||||
|
: base(definition.Modifiers, source, sourceRectangle) |
||||
|
{ |
||||
|
this.pixelShader = definition.PixelShader; |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
protected override void ApplyPixelShader(Span<Vector4> span, Point offset) => this.pixelShader(span); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,61 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
using SixLabors.Primitives; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Processing.Processors.Effects |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Applies a user defined pixel shader effect through a given delegate.
|
||||
|
/// </summary>
|
||||
|
public sealed class PositionAwarePixelShaderProcessor : IImageProcessor |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The default <see cref="PixelConversionModifiers"/> to apply during the pixel conversions.
|
||||
|
/// </summary>
|
||||
|
public const PixelConversionModifiers DefaultModifiers = PixelConversionModifiers.None; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="PositionAwarePixelShaderProcessor"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="pixelShader">
|
||||
|
/// The user defined pixel shader to use to modify images.
|
||||
|
/// </param>
|
||||
|
public PositionAwarePixelShaderProcessor(PositionAwarePixelShader pixelShader) |
||||
|
{ |
||||
|
this.PixelShader = pixelShader; |
||||
|
this.Modifiers = DefaultModifiers; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="PositionAwarePixelShaderProcessor"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="pixelShader">
|
||||
|
/// The user defined pixel shader to use to modify images.
|
||||
|
/// </param>
|
||||
|
/// <param name="modifiers">The <see cref="PixelConversionModifiers"/> to apply during the pixel conversions.</param>
|
||||
|
public PositionAwarePixelShaderProcessor(PositionAwarePixelShader pixelShader, PixelConversionModifiers modifiers) |
||||
|
{ |
||||
|
this.PixelShader = pixelShader; |
||||
|
this.Modifiers = modifiers; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the user defined pixel shader.
|
||||
|
/// </summary>
|
||||
|
public PositionAwarePixelShader PixelShader { get; } |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the <see cref="PixelConversionModifiers"/> to apply during the pixel conversions.
|
||||
|
/// </summary>
|
||||
|
public PixelConversionModifiers Modifiers { get; } |
||||
|
|
||||
|
/// <inheritdoc />
|
||||
|
public IImageProcessor<TPixel> CreatePixelSpecificProcessor<TPixel>(Image<TPixel> source, Rectangle sourceRectangle) |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
return new PositionAwarePixelShaderProcessor<TPixel>(this, source, sourceRectangle); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,39 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using System; |
||||
|
using System.Numerics; |
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
using SixLabors.Primitives; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Processing.Processors.Effects |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Applies a user defined pixel shader effect through a given delegate.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
||||
|
internal sealed class PositionAwarePixelShaderProcessor<TPixel> : PixelShaderProcessorBase<TPixel> |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The user defined pixel shader.
|
||||
|
/// </summary>
|
||||
|
private readonly PositionAwarePixelShader pixelShader; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="PositionAwarePixelShaderProcessor{TPixel}"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="definition">The <see cref="PositionAwarePixelShaderProcessor"/> defining the processor parameters.</param>
|
||||
|
/// <param name="source">The source <see cref="Image{TPixel}"/> for the current processor instance.</param>
|
||||
|
/// <param name="sourceRectangle">The source area to process for the current processor instance.</param>
|
||||
|
public PositionAwarePixelShaderProcessor(PositionAwarePixelShaderProcessor definition, Image<TPixel> source, Rectangle sourceRectangle) |
||||
|
: base(definition.Modifiers, source, sourceRectangle) |
||||
|
{ |
||||
|
this.pixelShader = definition.PixelShader; |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
protected override void ApplyPixelShader(Span<Vector4> span, Point offset) => this.pixelShader(span, offset); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,113 @@ |
|||||
|
// Copyright (c) Six Labors and contributors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using System; |
||||
|
using System.Numerics; |
||||
|
|
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
using SixLabors.ImageSharp.Processing; |
||||
|
|
||||
|
using Xunit; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Tests.Processing.Processors.Effects |
||||
|
{ |
||||
|
[GroupOutput("Effects")] |
||||
|
public class PixelShaderTest |
||||
|
{ |
||||
|
[Theory] |
||||
|
[WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Rgba32)] |
||||
|
public void FullImage<TPixel>(TestImageProvider<TPixel> provider) |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
provider.RunValidatingProcessorTest( |
||||
|
x => x.ApplyPixelShaderProcessor( |
||||
|
span => |
||||
|
{ |
||||
|
for (int i = 0; i < span.Length; i++) |
||||
|
{ |
||||
|
Vector4 v4 = span[i]; |
||||
|
float avg = (v4.X + v4.Y + v4.Z) / 3f; |
||||
|
span[i] = new Vector4(avg); |
||||
|
} |
||||
|
}), |
||||
|
appendPixelTypeToFileName: false); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Rgba32)] |
||||
|
public void InBox<TPixel>(TestImageProvider<TPixel> provider) |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
provider.RunRectangleConstrainedValidatingProcessorTest( |
||||
|
(x, rect) => x.ApplyPixelShaderProcessor( |
||||
|
span => |
||||
|
{ |
||||
|
for (int i = 0; i < span.Length; i++) |
||||
|
{ |
||||
|
Vector4 v4 = span[i]; |
||||
|
float avg = (v4.X + v4.Y + v4.Z) / 3f; |
||||
|
span[i] = new Vector4(avg); |
||||
|
} |
||||
|
}, rect)); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Rgba32)] |
||||
|
public void PositionAwareFullImage<TPixel>(TestImageProvider<TPixel> provider) |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
provider.RunValidatingProcessorTest( |
||||
|
c => c.ApplyPixelShaderProcessor( |
||||
|
(span, offset) => |
||||
|
{ |
||||
|
int y = offset.Y; |
||||
|
int x = offset.X; |
||||
|
for (int i = 0; i < span.Length; i++) |
||||
|
{ |
||||
|
float |
||||
|
sine = MathF.Sin(y), |
||||
|
cosine = MathF.Cos(x + i), |
||||
|
sum = sine + cosine, |
||||
|
abs = MathF.Abs(sum), |
||||
|
a = 0.5f + (abs / 2); // Max value for sin(y) + cos(x) is 2
|
||||
|
|
||||
|
Vector4 v4 = span[i]; |
||||
|
float avg = (v4.X + v4.Y + v4.Z) / 3f; |
||||
|
var gray = new Vector4(avg, avg, avg, a); |
||||
|
|
||||
|
span[i] = Vector4.Clamp(gray, Vector4.Zero, Vector4.One); |
||||
|
} |
||||
|
}), |
||||
|
appendPixelTypeToFileName: false); |
||||
|
} |
||||
|
|
||||
|
[Theory] |
||||
|
[WithFile(TestImages.Png.CalliphoraPartial, PixelTypes.Rgba32)] |
||||
|
public void PositionAwareInBox<TPixel>(TestImageProvider<TPixel> provider) |
||||
|
where TPixel : struct, IPixel<TPixel> |
||||
|
{ |
||||
|
provider.RunRectangleConstrainedValidatingProcessorTest( |
||||
|
(c, rect) => c.ApplyPixelShaderProcessor( |
||||
|
(span, offset) => |
||||
|
{ |
||||
|
int y = offset.Y; |
||||
|
int x = offset.X; |
||||
|
for (int i = 0; i < span.Length; i++) |
||||
|
{ |
||||
|
float |
||||
|
sine = MathF.Sin(y), |
||||
|
cosine = MathF.Cos(x + i), |
||||
|
sum = sine + cosine, |
||||
|
abs = MathF.Abs(sum), |
||||
|
a = 0.5f + (abs / 2); |
||||
|
|
||||
|
Vector4 v4 = span[i]; |
||||
|
float avg = (v4.X + v4.Y + v4.Z) / 3f; |
||||
|
var gray = new Vector4(avg, avg, avg, a); |
||||
|
|
||||
|
span[i] = Vector4.Clamp(gray, Vector4.Zero, Vector4.One); |
||||
|
} |
||||
|
}, rect)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1 +1 @@ |
|||||
Subproject commit d7c099cebd58f1d3ff997383351d52d28a29df3d |
Subproject commit d8ea82085ac39a6aa6ca8e0806a9518d3a7d3337 |
||||
Loading…
Reference in new issue