Browse Source

Flatten pixel blender hierarchy

pull/3161/head
James Jackson-South 3 weeks ago
parent
commit
3c3d523954
  1. 1512
      src/ImageSharp/PixelFormats/PixelBlenders/AssociatedAlphaPixelBlenders.Generated.cs
  2. 14
      src/ImageSharp/PixelFormats/PixelBlenders/AssociatedAlphaPixelBlenders.Generated.tt
  3. 216
      src/ImageSharp/PixelFormats/PixelBlenders/AssociatedAlphaPixelBlenders.cs
  4. 49
      src/ImageSharp/PixelFormats/PixelBlenders/AssociatedAlphaPixelBlender{TPixel,TOperator}.cs
  5. 1512
      src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.cs
  6. 14
      src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.tt
  7. 5
      src/ImageSharp/PixelFormats/PixelBlenders/IPixelBlenderOperator.cs
  8. 86
      src/ImageSharp/PixelFormats/PixelBlenders/PixelBlender{TPixel,TOperator}.cs
  9. 216
      src/ImageSharp/PixelFormats/PixelOperations{TPixel}.PixelBenders.cs
  10. 278
      tests/ImageSharp.Tests/PixelFormats/PixelBlenderTests.cs
  11. 36
      tests/ImageSharp.Tests/PixelFormats/PixelBlenders/PorterDuffFunctionsTestsTPixel.cs

1512
src/ImageSharp/PixelFormats/PixelBlenders/AssociatedAlphaPixelBlenders.Generated.cs

File diff suppressed because it is too large

14
src/ImageSharp/PixelFormats/PixelBlenders/AssociatedAlphaPixelBlenders.Generated.tt

@ -61,6 +61,9 @@ foreach (var composer in composers)
/// </summary>
public readonly struct <#= blenderComposer #> : IPixelBlenderOperator
{
/// <inheritdoc />
public static bool IsAssociatedAlpha => true;
/// <inheritdoc />
public static Vector4 Invoke(Vector4 background, Vector4 source, float amount)
=> AssociatedAlphaPorterDuffFunctions.<#= blenderComposer #>(background, source, amount);
@ -95,16 +98,9 @@ foreach (var composer in composers)
var blenderComposer = $"{blender}{composer}";
#>
/// <summary>
/// Blends pixels with the "<#= blenderComposer #>" composition equation.
/// Gets the shared blender for the "<#= blenderComposer #>" composition equation.
/// </summary>
public sealed class <#= blenderComposer #> :
AssociatedAlphaPixelBlender<TPixel, AssociatedAlphaPixelBlenderOperators.<#= blenderComposer #>>
{
/// <summary>
/// Gets the shared blender instance.
/// </summary>
public static <#= blenderComposer #> Instance { get; } = new();
}
public static PixelBlender<TPixel> <#= blenderComposer #> => PixelBlender<TPixel, AssociatedAlphaPixelBlenderOperators.<#= blenderComposer #>>.Instance;
<#
}

216
src/ImageSharp/PixelFormats/PixelBlenders/AssociatedAlphaPixelBlenders.cs

@ -21,147 +21,147 @@ internal static partial class AssociatedAlphaPixelBlenders<TPixel>
{
PixelAlphaCompositionMode.Src => colorMode switch
{
PixelColorBlendingMode.Multiply => MultiplySrc.Instance,
PixelColorBlendingMode.Add => AddSrc.Instance,
PixelColorBlendingMode.Subtract => SubtractSrc.Instance,
PixelColorBlendingMode.Screen => ScreenSrc.Instance,
PixelColorBlendingMode.Darken => DarkenSrc.Instance,
PixelColorBlendingMode.Lighten => LightenSrc.Instance,
PixelColorBlendingMode.Overlay => OverlaySrc.Instance,
PixelColorBlendingMode.HardLight => HardLightSrc.Instance,
_ => NormalSrc.Instance,
PixelColorBlendingMode.Multiply => MultiplySrc,
PixelColorBlendingMode.Add => AddSrc,
PixelColorBlendingMode.Subtract => SubtractSrc,
PixelColorBlendingMode.Screen => ScreenSrc,
PixelColorBlendingMode.Darken => DarkenSrc,
PixelColorBlendingMode.Lighten => LightenSrc,
PixelColorBlendingMode.Overlay => OverlaySrc,
PixelColorBlendingMode.HardLight => HardLightSrc,
_ => NormalSrc,
},
PixelAlphaCompositionMode.SrcAtop => colorMode switch
{
PixelColorBlendingMode.Multiply => MultiplySrcAtop.Instance,
PixelColorBlendingMode.Add => AddSrcAtop.Instance,
PixelColorBlendingMode.Subtract => SubtractSrcAtop.Instance,
PixelColorBlendingMode.Screen => ScreenSrcAtop.Instance,
PixelColorBlendingMode.Darken => DarkenSrcAtop.Instance,
PixelColorBlendingMode.Lighten => LightenSrcAtop.Instance,
PixelColorBlendingMode.Overlay => OverlaySrcAtop.Instance,
PixelColorBlendingMode.HardLight => HardLightSrcAtop.Instance,
_ => NormalSrcAtop.Instance,
PixelColorBlendingMode.Multiply => MultiplySrcAtop,
PixelColorBlendingMode.Add => AddSrcAtop,
PixelColorBlendingMode.Subtract => SubtractSrcAtop,
PixelColorBlendingMode.Screen => ScreenSrcAtop,
PixelColorBlendingMode.Darken => DarkenSrcAtop,
PixelColorBlendingMode.Lighten => LightenSrcAtop,
PixelColorBlendingMode.Overlay => OverlaySrcAtop,
PixelColorBlendingMode.HardLight => HardLightSrcAtop,
_ => NormalSrcAtop,
},
PixelAlphaCompositionMode.SrcIn => colorMode switch
{
PixelColorBlendingMode.Multiply => MultiplySrcIn.Instance,
PixelColorBlendingMode.Add => AddSrcIn.Instance,
PixelColorBlendingMode.Subtract => SubtractSrcIn.Instance,
PixelColorBlendingMode.Screen => ScreenSrcIn.Instance,
PixelColorBlendingMode.Darken => DarkenSrcIn.Instance,
PixelColorBlendingMode.Lighten => LightenSrcIn.Instance,
PixelColorBlendingMode.Overlay => OverlaySrcIn.Instance,
PixelColorBlendingMode.HardLight => HardLightSrcIn.Instance,
_ => NormalSrcIn.Instance,
PixelColorBlendingMode.Multiply => MultiplySrcIn,
PixelColorBlendingMode.Add => AddSrcIn,
PixelColorBlendingMode.Subtract => SubtractSrcIn,
PixelColorBlendingMode.Screen => ScreenSrcIn,
PixelColorBlendingMode.Darken => DarkenSrcIn,
PixelColorBlendingMode.Lighten => LightenSrcIn,
PixelColorBlendingMode.Overlay => OverlaySrcIn,
PixelColorBlendingMode.HardLight => HardLightSrcIn,
_ => NormalSrcIn,
},
PixelAlphaCompositionMode.SrcOut => colorMode switch
{
PixelColorBlendingMode.Multiply => MultiplySrcOut.Instance,
PixelColorBlendingMode.Add => AddSrcOut.Instance,
PixelColorBlendingMode.Subtract => SubtractSrcOut.Instance,
PixelColorBlendingMode.Screen => ScreenSrcOut.Instance,
PixelColorBlendingMode.Darken => DarkenSrcOut.Instance,
PixelColorBlendingMode.Lighten => LightenSrcOut.Instance,
PixelColorBlendingMode.Overlay => OverlaySrcOut.Instance,
PixelColorBlendingMode.HardLight => HardLightSrcOut.Instance,
_ => NormalSrcOut.Instance,
PixelColorBlendingMode.Multiply => MultiplySrcOut,
PixelColorBlendingMode.Add => AddSrcOut,
PixelColorBlendingMode.Subtract => SubtractSrcOut,
PixelColorBlendingMode.Screen => ScreenSrcOut,
PixelColorBlendingMode.Darken => DarkenSrcOut,
PixelColorBlendingMode.Lighten => LightenSrcOut,
PixelColorBlendingMode.Overlay => OverlaySrcOut,
PixelColorBlendingMode.HardLight => HardLightSrcOut,
_ => NormalSrcOut,
},
PixelAlphaCompositionMode.Dest => colorMode switch
{
PixelColorBlendingMode.Multiply => MultiplyDest.Instance,
PixelColorBlendingMode.Add => AddDest.Instance,
PixelColorBlendingMode.Subtract => SubtractDest.Instance,
PixelColorBlendingMode.Screen => ScreenDest.Instance,
PixelColorBlendingMode.Darken => DarkenDest.Instance,
PixelColorBlendingMode.Lighten => LightenDest.Instance,
PixelColorBlendingMode.Overlay => OverlayDest.Instance,
PixelColorBlendingMode.HardLight => HardLightDest.Instance,
_ => NormalDest.Instance,
PixelColorBlendingMode.Multiply => MultiplyDest,
PixelColorBlendingMode.Add => AddDest,
PixelColorBlendingMode.Subtract => SubtractDest,
PixelColorBlendingMode.Screen => ScreenDest,
PixelColorBlendingMode.Darken => DarkenDest,
PixelColorBlendingMode.Lighten => LightenDest,
PixelColorBlendingMode.Overlay => OverlayDest,
PixelColorBlendingMode.HardLight => HardLightDest,
_ => NormalDest,
},
PixelAlphaCompositionMode.DestAtop => colorMode switch
{
PixelColorBlendingMode.Multiply => MultiplyDestAtop.Instance,
PixelColorBlendingMode.Add => AddDestAtop.Instance,
PixelColorBlendingMode.Subtract => SubtractDestAtop.Instance,
PixelColorBlendingMode.Screen => ScreenDestAtop.Instance,
PixelColorBlendingMode.Darken => DarkenDestAtop.Instance,
PixelColorBlendingMode.Lighten => LightenDestAtop.Instance,
PixelColorBlendingMode.Overlay => OverlayDestAtop.Instance,
PixelColorBlendingMode.HardLight => HardLightDestAtop.Instance,
_ => NormalDestAtop.Instance,
PixelColorBlendingMode.Multiply => MultiplyDestAtop,
PixelColorBlendingMode.Add => AddDestAtop,
PixelColorBlendingMode.Subtract => SubtractDestAtop,
PixelColorBlendingMode.Screen => ScreenDestAtop,
PixelColorBlendingMode.Darken => DarkenDestAtop,
PixelColorBlendingMode.Lighten => LightenDestAtop,
PixelColorBlendingMode.Overlay => OverlayDestAtop,
PixelColorBlendingMode.HardLight => HardLightDestAtop,
_ => NormalDestAtop,
},
PixelAlphaCompositionMode.DestOver => colorMode switch
{
PixelColorBlendingMode.Multiply => MultiplyDestOver.Instance,
PixelColorBlendingMode.Add => AddDestOver.Instance,
PixelColorBlendingMode.Subtract => SubtractDestOver.Instance,
PixelColorBlendingMode.Screen => ScreenDestOver.Instance,
PixelColorBlendingMode.Darken => DarkenDestOver.Instance,
PixelColorBlendingMode.Lighten => LightenDestOver.Instance,
PixelColorBlendingMode.Overlay => OverlayDestOver.Instance,
PixelColorBlendingMode.HardLight => HardLightDestOver.Instance,
_ => NormalDestOver.Instance,
PixelColorBlendingMode.Multiply => MultiplyDestOver,
PixelColorBlendingMode.Add => AddDestOver,
PixelColorBlendingMode.Subtract => SubtractDestOver,
PixelColorBlendingMode.Screen => ScreenDestOver,
PixelColorBlendingMode.Darken => DarkenDestOver,
PixelColorBlendingMode.Lighten => LightenDestOver,
PixelColorBlendingMode.Overlay => OverlayDestOver,
PixelColorBlendingMode.HardLight => HardLightDestOver,
_ => NormalDestOver,
},
PixelAlphaCompositionMode.DestIn => colorMode switch
{
PixelColorBlendingMode.Multiply => MultiplyDestIn.Instance,
PixelColorBlendingMode.Add => AddDestIn.Instance,
PixelColorBlendingMode.Subtract => SubtractDestIn.Instance,
PixelColorBlendingMode.Screen => ScreenDestIn.Instance,
PixelColorBlendingMode.Darken => DarkenDestIn.Instance,
PixelColorBlendingMode.Lighten => LightenDestIn.Instance,
PixelColorBlendingMode.Overlay => OverlayDestIn.Instance,
PixelColorBlendingMode.HardLight => HardLightDestIn.Instance,
_ => NormalDestIn.Instance,
PixelColorBlendingMode.Multiply => MultiplyDestIn,
PixelColorBlendingMode.Add => AddDestIn,
PixelColorBlendingMode.Subtract => SubtractDestIn,
PixelColorBlendingMode.Screen => ScreenDestIn,
PixelColorBlendingMode.Darken => DarkenDestIn,
PixelColorBlendingMode.Lighten => LightenDestIn,
PixelColorBlendingMode.Overlay => OverlayDestIn,
PixelColorBlendingMode.HardLight => HardLightDestIn,
_ => NormalDestIn,
},
PixelAlphaCompositionMode.DestOut => colorMode switch
{
PixelColorBlendingMode.Multiply => MultiplyDestOut.Instance,
PixelColorBlendingMode.Add => AddDestOut.Instance,
PixelColorBlendingMode.Subtract => SubtractDestOut.Instance,
PixelColorBlendingMode.Screen => ScreenDestOut.Instance,
PixelColorBlendingMode.Darken => DarkenDestOut.Instance,
PixelColorBlendingMode.Lighten => LightenDestOut.Instance,
PixelColorBlendingMode.Overlay => OverlayDestOut.Instance,
PixelColorBlendingMode.HardLight => HardLightDestOut.Instance,
_ => NormalDestOut.Instance,
PixelColorBlendingMode.Multiply => MultiplyDestOut,
PixelColorBlendingMode.Add => AddDestOut,
PixelColorBlendingMode.Subtract => SubtractDestOut,
PixelColorBlendingMode.Screen => ScreenDestOut,
PixelColorBlendingMode.Darken => DarkenDestOut,
PixelColorBlendingMode.Lighten => LightenDestOut,
PixelColorBlendingMode.Overlay => OverlayDestOut,
PixelColorBlendingMode.HardLight => HardLightDestOut,
_ => NormalDestOut,
},
PixelAlphaCompositionMode.Clear => colorMode switch
{
PixelColorBlendingMode.Multiply => MultiplyClear.Instance,
PixelColorBlendingMode.Add => AddClear.Instance,
PixelColorBlendingMode.Subtract => SubtractClear.Instance,
PixelColorBlendingMode.Screen => ScreenClear.Instance,
PixelColorBlendingMode.Darken => DarkenClear.Instance,
PixelColorBlendingMode.Lighten => LightenClear.Instance,
PixelColorBlendingMode.Overlay => OverlayClear.Instance,
PixelColorBlendingMode.HardLight => HardLightClear.Instance,
_ => NormalClear.Instance,
PixelColorBlendingMode.Multiply => MultiplyClear,
PixelColorBlendingMode.Add => AddClear,
PixelColorBlendingMode.Subtract => SubtractClear,
PixelColorBlendingMode.Screen => ScreenClear,
PixelColorBlendingMode.Darken => DarkenClear,
PixelColorBlendingMode.Lighten => LightenClear,
PixelColorBlendingMode.Overlay => OverlayClear,
PixelColorBlendingMode.HardLight => HardLightClear,
_ => NormalClear,
},
PixelAlphaCompositionMode.Xor => colorMode switch
{
PixelColorBlendingMode.Multiply => MultiplyXor.Instance,
PixelColorBlendingMode.Add => AddXor.Instance,
PixelColorBlendingMode.Subtract => SubtractXor.Instance,
PixelColorBlendingMode.Screen => ScreenXor.Instance,
PixelColorBlendingMode.Darken => DarkenXor.Instance,
PixelColorBlendingMode.Lighten => LightenXor.Instance,
PixelColorBlendingMode.Overlay => OverlayXor.Instance,
PixelColorBlendingMode.HardLight => HardLightXor.Instance,
_ => NormalXor.Instance,
PixelColorBlendingMode.Multiply => MultiplyXor,
PixelColorBlendingMode.Add => AddXor,
PixelColorBlendingMode.Subtract => SubtractXor,
PixelColorBlendingMode.Screen => ScreenXor,
PixelColorBlendingMode.Darken => DarkenXor,
PixelColorBlendingMode.Lighten => LightenXor,
PixelColorBlendingMode.Overlay => OverlayXor,
PixelColorBlendingMode.HardLight => HardLightXor,
_ => NormalXor,
},
_ => colorMode switch
{
PixelColorBlendingMode.Multiply => MultiplySrcOver.Instance,
PixelColorBlendingMode.Add => AddSrcOver.Instance,
PixelColorBlendingMode.Subtract => SubtractSrcOver.Instance,
PixelColorBlendingMode.Screen => ScreenSrcOver.Instance,
PixelColorBlendingMode.Darken => DarkenSrcOver.Instance,
PixelColorBlendingMode.Lighten => LightenSrcOver.Instance,
PixelColorBlendingMode.Overlay => OverlaySrcOver.Instance,
PixelColorBlendingMode.HardLight => HardLightSrcOver.Instance,
_ => NormalSrcOver.Instance,
PixelColorBlendingMode.Multiply => MultiplySrcOver,
PixelColorBlendingMode.Add => AddSrcOver,
PixelColorBlendingMode.Subtract => SubtractSrcOver,
PixelColorBlendingMode.Screen => ScreenSrcOver,
PixelColorBlendingMode.Darken => DarkenSrcOver,
PixelColorBlendingMode.Lighten => LightenSrcOver,
PixelColorBlendingMode.Overlay => OverlaySrcOver,
PixelColorBlendingMode.HardLight => HardLightSrcOver,
_ => NormalSrcOver,
},
};
}

49
src/ImageSharp/PixelFormats/PixelBlenders/AssociatedAlphaPixelBlender{TPixel,TOperator}.cs

@ -1,49 +0,0 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System.Numerics;
namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders;
/// <summary>
/// Provides the vector representation used to blend pixels that store associated alpha.
/// </summary>
/// <typeparam name="TPixel">The associated-alpha pixel format.</typeparam>
/// <typeparam name="TOperator">The Porter-Duff equation.</typeparam>
internal abstract class AssociatedAlphaPixelBlender<TPixel, TOperator> : PixelBlender<TPixel, TOperator>
where TPixel : unmanaged, IPixel<TPixel>
where TOperator : struct, IPixelBlenderOperator
{
private static readonly PixelOperations<TPixel> Operations = PixelOperations<TPixel>.Instance;
/// <inheritdoc />
public sealed override TPixel Blend(TPixel background, TPixel source, float amount)
{
// Associated RGB and alpha must remain in their stored representation throughout composition.
Vector4 result = TOperator.Invoke(background.ToAssociatedScaledVector4(), source.ToAssociatedScaledVector4(), Numerics.Clamp(amount, 0, 1F));
return TPixel.FromAssociatedScaledVector4(result);
}
/// <inheritdoc />
protected override void ToBlendVector4<TPixelSource>(
Configuration configuration,
ReadOnlySpan<TPixelSource> source,
Span<Vector4> destination)
{
// Selecting the source representation once per row avoids a format check for every blended pixel.
PixelOperations<TPixelSource>.Instance.ToVector4(configuration, source, destination, PixelConversionModifiers.Scale | PixelConversionModifiers.Premultiply);
}
/// <inheritdoc />
protected override Vector4 ToBlendVector4(TPixel source) => source.ToAssociatedScaledVector4();
/// <inheritdoc />
protected override void FromBlendVector4(
Configuration configuration,
Span<Vector4> source,
Span<TPixel> destination)
{
Operations.FromVector4Destructive(configuration, source, destination, PixelConversionModifiers.Scale | PixelConversionModifiers.Premultiply);
}
}

1512
src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.cs

File diff suppressed because it is too large

14
src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.tt

@ -61,6 +61,9 @@ foreach (var composer in composers)
/// </summary>
public readonly struct <#= blenderComposer #> : IPixelBlenderOperator
{
/// <inheritdoc />
public static bool IsAssociatedAlpha => false;
/// <inheritdoc />
public static Vector4 Invoke(Vector4 background, Vector4 source, float amount)
=> PorterDuffFunctions.<#= blenderComposer #>(background, source, amount);
@ -95,16 +98,9 @@ foreach (var composer in composers)
var blenderComposer = $"{blender}{composer}";
#>
/// <summary>
/// Blends pixels with the "<#= blenderComposer #>" composition equation.
/// Gets the shared blender for the "<#= blenderComposer #>" composition equation.
/// </summary>
public sealed class <#= blenderComposer #> :
DefaultPixelBlender<TPixel, DefaultPixelBlenderOperators.<#= blenderComposer #>>
{
/// <summary>
/// Gets the shared blender instance.
/// </summary>
public static <#= blenderComposer #> Instance { get; } = new();
}
public static PixelBlender<TPixel> <#= blenderComposer #> => PixelBlender<TPixel, DefaultPixelBlenderOperators.<#= blenderComposer #>>.Instance;
<#
}

5
src/ImageSharp/PixelFormats/PixelBlenders/IPixelBlenderOperator.cs

@ -11,6 +11,11 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders;
/// </summary>
internal interface IPixelBlenderOperator
{
/// <summary>
/// Gets a value indicating whether pixel conversion uses associated-alpha vectors.
/// </summary>
public static abstract bool IsAssociatedAlpha { get; }
/// <summary>
/// Blends one pixel represented by four RGBA lanes.
/// </summary>

86
src/ImageSharp/PixelFormats/PixelBlenders/PixelBlender{TPixel,TOperator}.cs

@ -13,10 +13,75 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders;
/// </summary>
/// <typeparam name="TPixel">The destination pixel format.</typeparam>
/// <typeparam name="TOperator">The Porter-Duff equation.</typeparam>
internal abstract class PixelBlender<TPixel, TOperator> : PixelBlender<TPixel>
internal sealed class PixelBlender<TPixel, TOperator> : PixelBlender<TPixel>
where TPixel : unmanaged, IPixel<TPixel>
where TOperator : struct, IPixelBlenderOperator
{
/// <summary>
/// Initializes a new instance of the <see cref="PixelBlender{TPixel, TOperator}"/> class.
/// </summary>
private PixelBlender()
{
}
/// <summary>
/// Gets the shared blender instance for this exact pixel and equation combination.
/// </summary>
// Keeping the singleton on the already-required closed blender type preserves per-mode lazy initialization
// without introducing another NativeAOT holder type or eagerly allocating every blender for a pixel format.
public static PixelBlender<TPixel> Instance { get; } = new PixelBlender<TPixel, TOperator>();
/// <inheritdoc />
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
// The operator type uniquely determines the alpha representation. NativeAOT therefore needs only the
// pixel/operator closure, while the JIT can remove this static choice from the generated hot path.
Vector4 backgroundVector = TOperator.IsAssociatedAlpha
? background.ToAssociatedScaledVector4()
: background.ToUnassociatedScaledVector4();
Vector4 sourceVector = TOperator.IsAssociatedAlpha
? source.ToAssociatedScaledVector4()
: source.ToUnassociatedScaledVector4();
Vector4 result = TOperator.Invoke(backgroundVector, sourceVector, Numerics.Clamp(amount, 0, 1F));
return TOperator.IsAssociatedAlpha
? TPixel.FromAssociatedScaledVector4(result)
: TPixel.FromUnassociatedScaledVector4(result);
}
/// <inheritdoc />
protected sealed override void ToBlendVector4<TPixelSource>(
Configuration configuration,
ReadOnlySpan<TPixelSource> source,
Span<Vector4> destination)
{
PixelConversionModifiers modifiers = TOperator.IsAssociatedAlpha
? PixelConversionModifiers.Scale | PixelConversionModifiers.Premultiply
: PixelConversionModifiers.Scale | PixelConversionModifiers.UnPremultiply;
PixelOperations<TPixelSource>.Instance.ToVector4(configuration, source, destination, modifiers);
}
/// <inheritdoc />
protected sealed override Vector4 ToBlendVector4(TPixel source)
=> TOperator.IsAssociatedAlpha
? source.ToAssociatedScaledVector4()
: source.ToUnassociatedScaledVector4();
/// <inheritdoc />
protected sealed override void FromBlendVector4(
Configuration configuration,
Span<Vector4> source,
Span<TPixel> destination)
{
PixelConversionModifiers modifiers = TOperator.IsAssociatedAlpha
? PixelConversionModifiers.Scale | PixelConversionModifiers.Premultiply
: PixelConversionModifiers.Scale | PixelConversionModifiers.UnPremultiply;
PixelOperations<TPixel>.Instance.FromVector4Destructive(configuration, source, destination, modifiers);
}
/// <inheritdoc />
protected sealed override void BlendFunction(Span<Vector4> destination, ReadOnlySpan<Vector4> background, ReadOnlySpan<Vector4> source, float amount)
{
@ -519,22 +584,3 @@ internal abstract class PixelBlender<TPixel, TOperator> : PixelBlender<TPixel>
return Vector512.Min(Vector512.Max(Vector512<float>.Zero, result), Vector512.Create(1F));
}
}
/// <summary>
/// Applies a statically selected Porter-Duff equation to straight-alpha pixels.
/// </summary>
/// <typeparam name="TPixel">The straight-alpha pixel format.</typeparam>
/// <typeparam name="TOperator">The Porter-Duff equation.</typeparam>
internal abstract class DefaultPixelBlender<TPixel, TOperator> : PixelBlender<TPixel, TOperator>
where TPixel : unmanaged, IPixel<TPixel>
where TOperator : struct, IPixelBlenderOperator
{
/// <inheritdoc />
public sealed override TPixel Blend(TPixel background, TPixel source, float amount)
{
// The operator consumes the same unassociated, scaled representation used by the bulk conversion path.
Vector4 result = TOperator.Invoke(background.ToUnassociatedScaledVector4(), source.ToUnassociatedScaledVector4(), Numerics.Clamp(amount, 0, 1F));
return TPixel.FromUnassociatedScaledVector4(result);
}
}

216
src/ImageSharp/PixelFormats/PixelOperations{TPixel}.PixelBenders.cs

@ -34,182 +34,182 @@ public partial class PixelOperations<TPixel>
case PixelAlphaCompositionMode.Clear:
switch (colorMode)
{
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplyClear.Instance;
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddClear.Instance;
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractClear.Instance;
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenClear.Instance;
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenClear.Instance;
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenClear.Instance;
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlayClear.Instance;
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightClear.Instance;
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplyClear;
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddClear;
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractClear;
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenClear;
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenClear;
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenClear;
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlayClear;
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightClear;
case PixelColorBlendingMode.Normal:
default: return DefaultPixelBlenders<TPixel>.NormalClear.Instance;
default: return DefaultPixelBlenders<TPixel>.NormalClear;
}
case PixelAlphaCompositionMode.Xor:
switch (colorMode)
{
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplyXor.Instance;
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddXor.Instance;
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractXor.Instance;
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenXor.Instance;
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenXor.Instance;
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenXor.Instance;
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlayXor.Instance;
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightXor.Instance;
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplyXor;
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddXor;
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractXor;
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenXor;
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenXor;
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenXor;
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlayXor;
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightXor;
case PixelColorBlendingMode.Normal:
default: return DefaultPixelBlenders<TPixel>.NormalXor.Instance;
default: return DefaultPixelBlenders<TPixel>.NormalXor;
}
case PixelAlphaCompositionMode.Src:
switch (colorMode)
{
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplySrc.Instance;
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddSrc.Instance;
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractSrc.Instance;
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenSrc.Instance;
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenSrc.Instance;
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenSrc.Instance;
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlaySrc.Instance;
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightSrc.Instance;
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplySrc;
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddSrc;
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractSrc;
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenSrc;
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenSrc;
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenSrc;
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlaySrc;
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightSrc;
case PixelColorBlendingMode.Normal:
default: return DefaultPixelBlenders<TPixel>.NormalSrc.Instance;
default: return DefaultPixelBlenders<TPixel>.NormalSrc;
}
case PixelAlphaCompositionMode.SrcAtop:
switch (colorMode)
{
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplySrcAtop.Instance;
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddSrcAtop.Instance;
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractSrcAtop.Instance;
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenSrcAtop.Instance;
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenSrcAtop.Instance;
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenSrcAtop.Instance;
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlaySrcAtop.Instance;
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightSrcAtop.Instance;
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplySrcAtop;
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddSrcAtop;
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractSrcAtop;
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenSrcAtop;
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenSrcAtop;
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenSrcAtop;
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlaySrcAtop;
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightSrcAtop;
case PixelColorBlendingMode.Normal:
default: return DefaultPixelBlenders<TPixel>.NormalSrcAtop.Instance;
default: return DefaultPixelBlenders<TPixel>.NormalSrcAtop;
}
case PixelAlphaCompositionMode.SrcIn:
switch (colorMode)
{
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplySrcIn.Instance;
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddSrcIn.Instance;
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractSrcIn.Instance;
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenSrcIn.Instance;
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenSrcIn.Instance;
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenSrcIn.Instance;
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlaySrcIn.Instance;
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightSrcIn.Instance;
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplySrcIn;
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddSrcIn;
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractSrcIn;
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenSrcIn;
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenSrcIn;
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenSrcIn;
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlaySrcIn;
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightSrcIn;
case PixelColorBlendingMode.Normal:
default: return DefaultPixelBlenders<TPixel>.NormalSrcIn.Instance;
default: return DefaultPixelBlenders<TPixel>.NormalSrcIn;
}
case PixelAlphaCompositionMode.SrcOut:
switch (colorMode)
{
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplySrcOut.Instance;
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddSrcOut.Instance;
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractSrcOut.Instance;
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenSrcOut.Instance;
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenSrcOut.Instance;
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenSrcOut.Instance;
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlaySrcOut.Instance;
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightSrcOut.Instance;
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplySrcOut;
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddSrcOut;
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractSrcOut;
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenSrcOut;
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenSrcOut;
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenSrcOut;
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlaySrcOut;
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightSrcOut;
case PixelColorBlendingMode.Normal:
default: return DefaultPixelBlenders<TPixel>.NormalSrcOut.Instance;
default: return DefaultPixelBlenders<TPixel>.NormalSrcOut;
}
case PixelAlphaCompositionMode.Dest:
switch (colorMode)
{
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplyDest.Instance;
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddDest.Instance;
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractDest.Instance;
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenDest.Instance;
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenDest.Instance;
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenDest.Instance;
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlayDest.Instance;
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightDest.Instance;
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplyDest;
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddDest;
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractDest;
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenDest;
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenDest;
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenDest;
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlayDest;
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightDest;
case PixelColorBlendingMode.Normal:
default: return DefaultPixelBlenders<TPixel>.NormalDest.Instance;
default: return DefaultPixelBlenders<TPixel>.NormalDest;
}
case PixelAlphaCompositionMode.DestAtop:
switch (colorMode)
{
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplyDestAtop.Instance;
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddDestAtop.Instance;
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractDestAtop.Instance;
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenDestAtop.Instance;
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenDestAtop.Instance;
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenDestAtop.Instance;
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlayDestAtop.Instance;
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightDestAtop.Instance;
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplyDestAtop;
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddDestAtop;
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractDestAtop;
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenDestAtop;
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenDestAtop;
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenDestAtop;
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlayDestAtop;
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightDestAtop;
case PixelColorBlendingMode.Normal:
default: return DefaultPixelBlenders<TPixel>.NormalDestAtop.Instance;
default: return DefaultPixelBlenders<TPixel>.NormalDestAtop;
}
case PixelAlphaCompositionMode.DestIn:
switch (colorMode)
{
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplyDestIn.Instance;
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddDestIn.Instance;
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractDestIn.Instance;
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenDestIn.Instance;
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenDestIn.Instance;
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenDestIn.Instance;
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlayDestIn.Instance;
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightDestIn.Instance;
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplyDestIn;
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddDestIn;
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractDestIn;
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenDestIn;
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenDestIn;
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenDestIn;
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlayDestIn;
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightDestIn;
case PixelColorBlendingMode.Normal:
default: return DefaultPixelBlenders<TPixel>.NormalDestIn.Instance;
default: return DefaultPixelBlenders<TPixel>.NormalDestIn;
}
case PixelAlphaCompositionMode.DestOut:
switch (colorMode)
{
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplyDestOut.Instance;
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddDestOut.Instance;
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractDestOut.Instance;
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenDestOut.Instance;
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenDestOut.Instance;
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenDestOut.Instance;
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlayDestOut.Instance;
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightDestOut.Instance;
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplyDestOut;
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddDestOut;
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractDestOut;
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenDestOut;
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenDestOut;
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenDestOut;
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlayDestOut;
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightDestOut;
case PixelColorBlendingMode.Normal:
default: return DefaultPixelBlenders<TPixel>.NormalDestOut.Instance;
default: return DefaultPixelBlenders<TPixel>.NormalDestOut;
}
case PixelAlphaCompositionMode.DestOver:
switch (colorMode)
{
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplyDestOver.Instance;
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddDestOver.Instance;
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractDestOver.Instance;
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenDestOver.Instance;
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenDestOver.Instance;
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenDestOver.Instance;
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlayDestOver.Instance;
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightDestOver.Instance;
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplyDestOver;
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddDestOver;
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractDestOver;
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenDestOver;
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenDestOver;
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenDestOver;
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlayDestOver;
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightDestOver;
case PixelColorBlendingMode.Normal:
default: return DefaultPixelBlenders<TPixel>.NormalDestOver.Instance;
default: return DefaultPixelBlenders<TPixel>.NormalDestOver;
}
case PixelAlphaCompositionMode.SrcOver:
default:
switch (colorMode)
{
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplySrcOver.Instance;
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddSrcOver.Instance;
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractSrcOver.Instance;
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenSrcOver.Instance;
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenSrcOver.Instance;
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenSrcOver.Instance;
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlaySrcOver.Instance;
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightSrcOver.Instance;
case PixelColorBlendingMode.Multiply: return DefaultPixelBlenders<TPixel>.MultiplySrcOver;
case PixelColorBlendingMode.Add: return DefaultPixelBlenders<TPixel>.AddSrcOver;
case PixelColorBlendingMode.Subtract: return DefaultPixelBlenders<TPixel>.SubtractSrcOver;
case PixelColorBlendingMode.Screen: return DefaultPixelBlenders<TPixel>.ScreenSrcOver;
case PixelColorBlendingMode.Darken: return DefaultPixelBlenders<TPixel>.DarkenSrcOver;
case PixelColorBlendingMode.Lighten: return DefaultPixelBlenders<TPixel>.LightenSrcOver;
case PixelColorBlendingMode.Overlay: return DefaultPixelBlenders<TPixel>.OverlaySrcOver;
case PixelColorBlendingMode.HardLight: return DefaultPixelBlenders<TPixel>.HardLightSrcOver;
case PixelColorBlendingMode.Normal:
default: return DefaultPixelBlenders<TPixel>.NormalSrcOver.Instance;
default: return DefaultPixelBlenders<TPixel>.NormalSrcOver;
}
}
}

278
tests/ImageSharp.Tests/PixelFormats/PixelBlenderTests.cs

@ -13,24 +13,24 @@ public class PixelBlenderTests
{
public static TheoryData<object, Type, PixelColorBlendingMode> BlenderMappings = new()
{
{ new TestPixel<Rgba32>(), typeof(DefaultPixelBlenders<Rgba32>.NormalSrcOver), PixelColorBlendingMode.Normal },
{ new TestPixel<Rgba32>(), typeof(DefaultPixelBlenders<Rgba32>.ScreenSrcOver), PixelColorBlendingMode.Screen },
{ new TestPixel<Rgba32>(), typeof(DefaultPixelBlenders<Rgba32>.HardLightSrcOver), PixelColorBlendingMode.HardLight },
{ new TestPixel<Rgba32>(), typeof(DefaultPixelBlenders<Rgba32>.OverlaySrcOver), PixelColorBlendingMode.Overlay },
{ new TestPixel<Rgba32>(), typeof(DefaultPixelBlenders<Rgba32>.DarkenSrcOver), PixelColorBlendingMode.Darken },
{ new TestPixel<Rgba32>(), typeof(DefaultPixelBlenders<Rgba32>.LightenSrcOver), PixelColorBlendingMode.Lighten },
{ new TestPixel<Rgba32>(), typeof(DefaultPixelBlenders<Rgba32>.AddSrcOver), PixelColorBlendingMode.Add },
{ new TestPixel<Rgba32>(), typeof(DefaultPixelBlenders<Rgba32>.SubtractSrcOver), PixelColorBlendingMode.Subtract },
{ new TestPixel<Rgba32>(), typeof(DefaultPixelBlenders<Rgba32>.MultiplySrcOver), PixelColorBlendingMode.Multiply },
{ new TestPixel<RgbaVector>(), typeof(DefaultPixelBlenders<RgbaVector>.NormalSrcOver), PixelColorBlendingMode.Normal },
{ new TestPixel<RgbaVector>(), typeof(DefaultPixelBlenders<RgbaVector>.ScreenSrcOver), PixelColorBlendingMode.Screen },
{ new TestPixel<RgbaVector>(), typeof(DefaultPixelBlenders<RgbaVector>.HardLightSrcOver), PixelColorBlendingMode.HardLight },
{ new TestPixel<RgbaVector>(), typeof(DefaultPixelBlenders<RgbaVector>.OverlaySrcOver), PixelColorBlendingMode.Overlay },
{ new TestPixel<RgbaVector>(), typeof(DefaultPixelBlenders<RgbaVector>.DarkenSrcOver), PixelColorBlendingMode.Darken },
{ new TestPixel<RgbaVector>(), typeof(DefaultPixelBlenders<RgbaVector>.LightenSrcOver), PixelColorBlendingMode.Lighten },
{ new TestPixel<RgbaVector>(), typeof(DefaultPixelBlenders<RgbaVector>.AddSrcOver), PixelColorBlendingMode.Add },
{ new TestPixel<RgbaVector>(), typeof(DefaultPixelBlenders<RgbaVector>.SubtractSrcOver), PixelColorBlendingMode.Subtract },
{ new TestPixel<RgbaVector>(), typeof(DefaultPixelBlenders<RgbaVector>.MultiplySrcOver), PixelColorBlendingMode.Multiply },
{ new TestPixel<Rgba32>(), DefaultPixelBlenders<Rgba32>.NormalSrcOver.GetType(), PixelColorBlendingMode.Normal },
{ new TestPixel<Rgba32>(), DefaultPixelBlenders<Rgba32>.ScreenSrcOver.GetType(), PixelColorBlendingMode.Screen },
{ new TestPixel<Rgba32>(), DefaultPixelBlenders<Rgba32>.HardLightSrcOver.GetType(), PixelColorBlendingMode.HardLight },
{ new TestPixel<Rgba32>(), DefaultPixelBlenders<Rgba32>.OverlaySrcOver.GetType(), PixelColorBlendingMode.Overlay },
{ new TestPixel<Rgba32>(), DefaultPixelBlenders<Rgba32>.DarkenSrcOver.GetType(), PixelColorBlendingMode.Darken },
{ new TestPixel<Rgba32>(), DefaultPixelBlenders<Rgba32>.LightenSrcOver.GetType(), PixelColorBlendingMode.Lighten },
{ new TestPixel<Rgba32>(), DefaultPixelBlenders<Rgba32>.AddSrcOver.GetType(), PixelColorBlendingMode.Add },
{ new TestPixel<Rgba32>(), DefaultPixelBlenders<Rgba32>.SubtractSrcOver.GetType(), PixelColorBlendingMode.Subtract },
{ new TestPixel<Rgba32>(), DefaultPixelBlenders<Rgba32>.MultiplySrcOver.GetType(), PixelColorBlendingMode.Multiply },
{ new TestPixel<RgbaVector>(), DefaultPixelBlenders<RgbaVector>.NormalSrcOver.GetType(), PixelColorBlendingMode.Normal },
{ new TestPixel<RgbaVector>(), DefaultPixelBlenders<RgbaVector>.ScreenSrcOver.GetType(), PixelColorBlendingMode.Screen },
{ new TestPixel<RgbaVector>(), DefaultPixelBlenders<RgbaVector>.HardLightSrcOver.GetType(), PixelColorBlendingMode.HardLight },
{ new TestPixel<RgbaVector>(), DefaultPixelBlenders<RgbaVector>.OverlaySrcOver.GetType(), PixelColorBlendingMode.Overlay },
{ new TestPixel<RgbaVector>(), DefaultPixelBlenders<RgbaVector>.DarkenSrcOver.GetType(), PixelColorBlendingMode.Darken },
{ new TestPixel<RgbaVector>(), DefaultPixelBlenders<RgbaVector>.LightenSrcOver.GetType(), PixelColorBlendingMode.Lighten },
{ new TestPixel<RgbaVector>(), DefaultPixelBlenders<RgbaVector>.AddSrcOver.GetType(), PixelColorBlendingMode.Add },
{ new TestPixel<RgbaVector>(), DefaultPixelBlenders<RgbaVector>.SubtractSrcOver.GetType(), PixelColorBlendingMode.Subtract },
{ new TestPixel<RgbaVector>(), DefaultPixelBlenders<RgbaVector>.MultiplySrcOver.GetType(), PixelColorBlendingMode.Multiply },
};
public static TheoryData<PixelColorBlendingMode, PixelAlphaCompositionMode, Type> BlenderModeMappings
@ -42,158 +42,158 @@ public class PixelBlenderTests
AddBlenderModeMappings(
data,
PixelAlphaCompositionMode.Clear,
typeof(DefaultPixelBlenders<Rgba32>.NormalClear),
typeof(DefaultPixelBlenders<Rgba32>.MultiplyClear),
typeof(DefaultPixelBlenders<Rgba32>.AddClear),
typeof(DefaultPixelBlenders<Rgba32>.SubtractClear),
typeof(DefaultPixelBlenders<Rgba32>.ScreenClear),
typeof(DefaultPixelBlenders<Rgba32>.DarkenClear),
typeof(DefaultPixelBlenders<Rgba32>.LightenClear),
typeof(DefaultPixelBlenders<Rgba32>.OverlayClear),
typeof(DefaultPixelBlenders<Rgba32>.HardLightClear));
DefaultPixelBlenders<Rgba32>.NormalClear.GetType(),
DefaultPixelBlenders<Rgba32>.MultiplyClear.GetType(),
DefaultPixelBlenders<Rgba32>.AddClear.GetType(),
DefaultPixelBlenders<Rgba32>.SubtractClear.GetType(),
DefaultPixelBlenders<Rgba32>.ScreenClear.GetType(),
DefaultPixelBlenders<Rgba32>.DarkenClear.GetType(),
DefaultPixelBlenders<Rgba32>.LightenClear.GetType(),
DefaultPixelBlenders<Rgba32>.OverlayClear.GetType(),
DefaultPixelBlenders<Rgba32>.HardLightClear.GetType());
AddBlenderModeMappings(
data,
PixelAlphaCompositionMode.Xor,
typeof(DefaultPixelBlenders<Rgba32>.NormalXor),
typeof(DefaultPixelBlenders<Rgba32>.MultiplyXor),
typeof(DefaultPixelBlenders<Rgba32>.AddXor),
typeof(DefaultPixelBlenders<Rgba32>.SubtractXor),
typeof(DefaultPixelBlenders<Rgba32>.ScreenXor),
typeof(DefaultPixelBlenders<Rgba32>.DarkenXor),
typeof(DefaultPixelBlenders<Rgba32>.LightenXor),
typeof(DefaultPixelBlenders<Rgba32>.OverlayXor),
typeof(DefaultPixelBlenders<Rgba32>.HardLightXor));
DefaultPixelBlenders<Rgba32>.NormalXor.GetType(),
DefaultPixelBlenders<Rgba32>.MultiplyXor.GetType(),
DefaultPixelBlenders<Rgba32>.AddXor.GetType(),
DefaultPixelBlenders<Rgba32>.SubtractXor.GetType(),
DefaultPixelBlenders<Rgba32>.ScreenXor.GetType(),
DefaultPixelBlenders<Rgba32>.DarkenXor.GetType(),
DefaultPixelBlenders<Rgba32>.LightenXor.GetType(),
DefaultPixelBlenders<Rgba32>.OverlayXor.GetType(),
DefaultPixelBlenders<Rgba32>.HardLightXor.GetType());
AddBlenderModeMappings(
data,
PixelAlphaCompositionMode.Src,
typeof(DefaultPixelBlenders<Rgba32>.NormalSrc),
typeof(DefaultPixelBlenders<Rgba32>.MultiplySrc),
typeof(DefaultPixelBlenders<Rgba32>.AddSrc),
typeof(DefaultPixelBlenders<Rgba32>.SubtractSrc),
typeof(DefaultPixelBlenders<Rgba32>.ScreenSrc),
typeof(DefaultPixelBlenders<Rgba32>.DarkenSrc),
typeof(DefaultPixelBlenders<Rgba32>.LightenSrc),
typeof(DefaultPixelBlenders<Rgba32>.OverlaySrc),
typeof(DefaultPixelBlenders<Rgba32>.HardLightSrc));
DefaultPixelBlenders<Rgba32>.NormalSrc.GetType(),
DefaultPixelBlenders<Rgba32>.MultiplySrc.GetType(),
DefaultPixelBlenders<Rgba32>.AddSrc.GetType(),
DefaultPixelBlenders<Rgba32>.SubtractSrc.GetType(),
DefaultPixelBlenders<Rgba32>.ScreenSrc.GetType(),
DefaultPixelBlenders<Rgba32>.DarkenSrc.GetType(),
DefaultPixelBlenders<Rgba32>.LightenSrc.GetType(),
DefaultPixelBlenders<Rgba32>.OverlaySrc.GetType(),
DefaultPixelBlenders<Rgba32>.HardLightSrc.GetType());
AddBlenderModeMappings(
data,
PixelAlphaCompositionMode.SrcAtop,
typeof(DefaultPixelBlenders<Rgba32>.NormalSrcAtop),
typeof(DefaultPixelBlenders<Rgba32>.MultiplySrcAtop),
typeof(DefaultPixelBlenders<Rgba32>.AddSrcAtop),
typeof(DefaultPixelBlenders<Rgba32>.SubtractSrcAtop),
typeof(DefaultPixelBlenders<Rgba32>.ScreenSrcAtop),
typeof(DefaultPixelBlenders<Rgba32>.DarkenSrcAtop),
typeof(DefaultPixelBlenders<Rgba32>.LightenSrcAtop),
typeof(DefaultPixelBlenders<Rgba32>.OverlaySrcAtop),
typeof(DefaultPixelBlenders<Rgba32>.HardLightSrcAtop));
DefaultPixelBlenders<Rgba32>.NormalSrcAtop.GetType(),
DefaultPixelBlenders<Rgba32>.MultiplySrcAtop.GetType(),
DefaultPixelBlenders<Rgba32>.AddSrcAtop.GetType(),
DefaultPixelBlenders<Rgba32>.SubtractSrcAtop.GetType(),
DefaultPixelBlenders<Rgba32>.ScreenSrcAtop.GetType(),
DefaultPixelBlenders<Rgba32>.DarkenSrcAtop.GetType(),
DefaultPixelBlenders<Rgba32>.LightenSrcAtop.GetType(),
DefaultPixelBlenders<Rgba32>.OverlaySrcAtop.GetType(),
DefaultPixelBlenders<Rgba32>.HardLightSrcAtop.GetType());
AddBlenderModeMappings(
data,
PixelAlphaCompositionMode.SrcIn,
typeof(DefaultPixelBlenders<Rgba32>.NormalSrcIn),
typeof(DefaultPixelBlenders<Rgba32>.MultiplySrcIn),
typeof(DefaultPixelBlenders<Rgba32>.AddSrcIn),
typeof(DefaultPixelBlenders<Rgba32>.SubtractSrcIn),
typeof(DefaultPixelBlenders<Rgba32>.ScreenSrcIn),
typeof(DefaultPixelBlenders<Rgba32>.DarkenSrcIn),
typeof(DefaultPixelBlenders<Rgba32>.LightenSrcIn),
typeof(DefaultPixelBlenders<Rgba32>.OverlaySrcIn),
typeof(DefaultPixelBlenders<Rgba32>.HardLightSrcIn));
DefaultPixelBlenders<Rgba32>.NormalSrcIn.GetType(),
DefaultPixelBlenders<Rgba32>.MultiplySrcIn.GetType(),
DefaultPixelBlenders<Rgba32>.AddSrcIn.GetType(),
DefaultPixelBlenders<Rgba32>.SubtractSrcIn.GetType(),
DefaultPixelBlenders<Rgba32>.ScreenSrcIn.GetType(),
DefaultPixelBlenders<Rgba32>.DarkenSrcIn.GetType(),
DefaultPixelBlenders<Rgba32>.LightenSrcIn.GetType(),
DefaultPixelBlenders<Rgba32>.OverlaySrcIn.GetType(),
DefaultPixelBlenders<Rgba32>.HardLightSrcIn.GetType());
AddBlenderModeMappings(
data,
PixelAlphaCompositionMode.SrcOut,
typeof(DefaultPixelBlenders<Rgba32>.NormalSrcOut),
typeof(DefaultPixelBlenders<Rgba32>.MultiplySrcOut),
typeof(DefaultPixelBlenders<Rgba32>.AddSrcOut),
typeof(DefaultPixelBlenders<Rgba32>.SubtractSrcOut),
typeof(DefaultPixelBlenders<Rgba32>.ScreenSrcOut),
typeof(DefaultPixelBlenders<Rgba32>.DarkenSrcOut),
typeof(DefaultPixelBlenders<Rgba32>.LightenSrcOut),
typeof(DefaultPixelBlenders<Rgba32>.OverlaySrcOut),
typeof(DefaultPixelBlenders<Rgba32>.HardLightSrcOut));
DefaultPixelBlenders<Rgba32>.NormalSrcOut.GetType(),
DefaultPixelBlenders<Rgba32>.MultiplySrcOut.GetType(),
DefaultPixelBlenders<Rgba32>.AddSrcOut.GetType(),
DefaultPixelBlenders<Rgba32>.SubtractSrcOut.GetType(),
DefaultPixelBlenders<Rgba32>.ScreenSrcOut.GetType(),
DefaultPixelBlenders<Rgba32>.DarkenSrcOut.GetType(),
DefaultPixelBlenders<Rgba32>.LightenSrcOut.GetType(),
DefaultPixelBlenders<Rgba32>.OverlaySrcOut.GetType(),
DefaultPixelBlenders<Rgba32>.HardLightSrcOut.GetType());
AddBlenderModeMappings(
data,
PixelAlphaCompositionMode.Dest,
typeof(DefaultPixelBlenders<Rgba32>.NormalDest),
typeof(DefaultPixelBlenders<Rgba32>.MultiplyDest),
typeof(DefaultPixelBlenders<Rgba32>.AddDest),
typeof(DefaultPixelBlenders<Rgba32>.SubtractDest),
typeof(DefaultPixelBlenders<Rgba32>.ScreenDest),
typeof(DefaultPixelBlenders<Rgba32>.DarkenDest),
typeof(DefaultPixelBlenders<Rgba32>.LightenDest),
typeof(DefaultPixelBlenders<Rgba32>.OverlayDest),
typeof(DefaultPixelBlenders<Rgba32>.HardLightDest));
DefaultPixelBlenders<Rgba32>.NormalDest.GetType(),
DefaultPixelBlenders<Rgba32>.MultiplyDest.GetType(),
DefaultPixelBlenders<Rgba32>.AddDest.GetType(),
DefaultPixelBlenders<Rgba32>.SubtractDest.GetType(),
DefaultPixelBlenders<Rgba32>.ScreenDest.GetType(),
DefaultPixelBlenders<Rgba32>.DarkenDest.GetType(),
DefaultPixelBlenders<Rgba32>.LightenDest.GetType(),
DefaultPixelBlenders<Rgba32>.OverlayDest.GetType(),
DefaultPixelBlenders<Rgba32>.HardLightDest.GetType());
AddBlenderModeMappings(
data,
PixelAlphaCompositionMode.DestAtop,
typeof(DefaultPixelBlenders<Rgba32>.NormalDestAtop),
typeof(DefaultPixelBlenders<Rgba32>.MultiplyDestAtop),
typeof(DefaultPixelBlenders<Rgba32>.AddDestAtop),
typeof(DefaultPixelBlenders<Rgba32>.SubtractDestAtop),
typeof(DefaultPixelBlenders<Rgba32>.ScreenDestAtop),
typeof(DefaultPixelBlenders<Rgba32>.DarkenDestAtop),
typeof(DefaultPixelBlenders<Rgba32>.LightenDestAtop),
typeof(DefaultPixelBlenders<Rgba32>.OverlayDestAtop),
typeof(DefaultPixelBlenders<Rgba32>.HardLightDestAtop));
DefaultPixelBlenders<Rgba32>.NormalDestAtop.GetType(),
DefaultPixelBlenders<Rgba32>.MultiplyDestAtop.GetType(),
DefaultPixelBlenders<Rgba32>.AddDestAtop.GetType(),
DefaultPixelBlenders<Rgba32>.SubtractDestAtop.GetType(),
DefaultPixelBlenders<Rgba32>.ScreenDestAtop.GetType(),
DefaultPixelBlenders<Rgba32>.DarkenDestAtop.GetType(),
DefaultPixelBlenders<Rgba32>.LightenDestAtop.GetType(),
DefaultPixelBlenders<Rgba32>.OverlayDestAtop.GetType(),
DefaultPixelBlenders<Rgba32>.HardLightDestAtop.GetType());
AddBlenderModeMappings(
data,
PixelAlphaCompositionMode.DestIn,
typeof(DefaultPixelBlenders<Rgba32>.NormalDestIn),
typeof(DefaultPixelBlenders<Rgba32>.MultiplyDestIn),
typeof(DefaultPixelBlenders<Rgba32>.AddDestIn),
typeof(DefaultPixelBlenders<Rgba32>.SubtractDestIn),
typeof(DefaultPixelBlenders<Rgba32>.ScreenDestIn),
typeof(DefaultPixelBlenders<Rgba32>.DarkenDestIn),
typeof(DefaultPixelBlenders<Rgba32>.LightenDestIn),
typeof(DefaultPixelBlenders<Rgba32>.OverlayDestIn),
typeof(DefaultPixelBlenders<Rgba32>.HardLightDestIn));
DefaultPixelBlenders<Rgba32>.NormalDestIn.GetType(),
DefaultPixelBlenders<Rgba32>.MultiplyDestIn.GetType(),
DefaultPixelBlenders<Rgba32>.AddDestIn.GetType(),
DefaultPixelBlenders<Rgba32>.SubtractDestIn.GetType(),
DefaultPixelBlenders<Rgba32>.ScreenDestIn.GetType(),
DefaultPixelBlenders<Rgba32>.DarkenDestIn.GetType(),
DefaultPixelBlenders<Rgba32>.LightenDestIn.GetType(),
DefaultPixelBlenders<Rgba32>.OverlayDestIn.GetType(),
DefaultPixelBlenders<Rgba32>.HardLightDestIn.GetType());
AddBlenderModeMappings(
data,
PixelAlphaCompositionMode.DestOut,
typeof(DefaultPixelBlenders<Rgba32>.NormalDestOut),
typeof(DefaultPixelBlenders<Rgba32>.MultiplyDestOut),
typeof(DefaultPixelBlenders<Rgba32>.AddDestOut),
typeof(DefaultPixelBlenders<Rgba32>.SubtractDestOut),
typeof(DefaultPixelBlenders<Rgba32>.ScreenDestOut),
typeof(DefaultPixelBlenders<Rgba32>.DarkenDestOut),
typeof(DefaultPixelBlenders<Rgba32>.LightenDestOut),
typeof(DefaultPixelBlenders<Rgba32>.OverlayDestOut),
typeof(DefaultPixelBlenders<Rgba32>.HardLightDestOut));
DefaultPixelBlenders<Rgba32>.NormalDestOut.GetType(),
DefaultPixelBlenders<Rgba32>.MultiplyDestOut.GetType(),
DefaultPixelBlenders<Rgba32>.AddDestOut.GetType(),
DefaultPixelBlenders<Rgba32>.SubtractDestOut.GetType(),
DefaultPixelBlenders<Rgba32>.ScreenDestOut.GetType(),
DefaultPixelBlenders<Rgba32>.DarkenDestOut.GetType(),
DefaultPixelBlenders<Rgba32>.LightenDestOut.GetType(),
DefaultPixelBlenders<Rgba32>.OverlayDestOut.GetType(),
DefaultPixelBlenders<Rgba32>.HardLightDestOut.GetType());
AddBlenderModeMappings(
data,
PixelAlphaCompositionMode.DestOver,
typeof(DefaultPixelBlenders<Rgba32>.NormalDestOver),
typeof(DefaultPixelBlenders<Rgba32>.MultiplyDestOver),
typeof(DefaultPixelBlenders<Rgba32>.AddDestOver),
typeof(DefaultPixelBlenders<Rgba32>.SubtractDestOver),
typeof(DefaultPixelBlenders<Rgba32>.ScreenDestOver),
typeof(DefaultPixelBlenders<Rgba32>.DarkenDestOver),
typeof(DefaultPixelBlenders<Rgba32>.LightenDestOver),
typeof(DefaultPixelBlenders<Rgba32>.OverlayDestOver),
typeof(DefaultPixelBlenders<Rgba32>.HardLightDestOver));
DefaultPixelBlenders<Rgba32>.NormalDestOver.GetType(),
DefaultPixelBlenders<Rgba32>.MultiplyDestOver.GetType(),
DefaultPixelBlenders<Rgba32>.AddDestOver.GetType(),
DefaultPixelBlenders<Rgba32>.SubtractDestOver.GetType(),
DefaultPixelBlenders<Rgba32>.ScreenDestOver.GetType(),
DefaultPixelBlenders<Rgba32>.DarkenDestOver.GetType(),
DefaultPixelBlenders<Rgba32>.LightenDestOver.GetType(),
DefaultPixelBlenders<Rgba32>.OverlayDestOver.GetType(),
DefaultPixelBlenders<Rgba32>.HardLightDestOver.GetType());
AddBlenderModeMappings(
data,
PixelAlphaCompositionMode.SrcOver,
typeof(DefaultPixelBlenders<Rgba32>.NormalSrcOver),
typeof(DefaultPixelBlenders<Rgba32>.MultiplySrcOver),
typeof(DefaultPixelBlenders<Rgba32>.AddSrcOver),
typeof(DefaultPixelBlenders<Rgba32>.SubtractSrcOver),
typeof(DefaultPixelBlenders<Rgba32>.ScreenSrcOver),
typeof(DefaultPixelBlenders<Rgba32>.DarkenSrcOver),
typeof(DefaultPixelBlenders<Rgba32>.LightenSrcOver),
typeof(DefaultPixelBlenders<Rgba32>.OverlaySrcOver),
typeof(DefaultPixelBlenders<Rgba32>.HardLightSrcOver));
DefaultPixelBlenders<Rgba32>.NormalSrcOver.GetType(),
DefaultPixelBlenders<Rgba32>.MultiplySrcOver.GetType(),
DefaultPixelBlenders<Rgba32>.AddSrcOver.GetType(),
DefaultPixelBlenders<Rgba32>.SubtractSrcOver.GetType(),
DefaultPixelBlenders<Rgba32>.ScreenSrcOver.GetType(),
DefaultPixelBlenders<Rgba32>.DarkenSrcOver.GetType(),
DefaultPixelBlenders<Rgba32>.LightenSrcOver.GetType(),
DefaultPixelBlenders<Rgba32>.OverlaySrcOver.GetType(),
DefaultPixelBlenders<Rgba32>.HardLightSrcOver.GetType());
return data;
}
@ -246,7 +246,7 @@ public class PixelBlenderTests
[Fact]
public void Blend_WithConstantSourceAndSingleAmount()
{
PixelBlender<Rgba32> blender = new DefaultPixelBlenders<Rgba32>.NormalSrcOver();
PixelBlender<Rgba32> blender = DefaultPixelBlenders<Rgba32>.NormalSrcOver;
Rgba32[] destination = new Rgba32[2];
Rgba32[] background =
[
@ -265,7 +265,7 @@ public class PixelBlenderTests
[Fact]
public void Blend_WithConstantSourceSingleAmountAndWorkingBuffer()
{
PixelBlender<Rgba32> blender = new DefaultPixelBlenders<Rgba32>.NormalSrcOver();
PixelBlender<Rgba32> blender = DefaultPixelBlenders<Rgba32>.NormalSrcOver;
Rgba32[] destination = new Rgba32[2];
Rgba32[] background =
[
@ -285,7 +285,7 @@ public class PixelBlenderTests
[Fact]
public void Blend_WithConstantSourceAndAmountSpan()
{
PixelBlender<Rgba32> blender = new DefaultPixelBlenders<Rgba32>.NormalSrcOver();
PixelBlender<Rgba32> blender = DefaultPixelBlenders<Rgba32>.NormalSrcOver;
Rgba32[] destination = new Rgba32[2];
Rgba32[] background =
[
@ -305,7 +305,7 @@ public class PixelBlenderTests
[Fact]
public void Blend_WithConstantSourceAmountSpanAndWorkingBuffer()
{
PixelBlender<Rgba32> blender = new DefaultPixelBlenders<Rgba32>.NormalSrcOver();
PixelBlender<Rgba32> blender = DefaultPixelBlenders<Rgba32>.NormalSrcOver;
Rgba32[] destination = new Rgba32[2];
Rgba32[] background =
[
@ -326,7 +326,7 @@ public class PixelBlenderTests
[Fact]
public void Blend_WithSourceSpanAmountSpanAndWorkingBuffer()
{
PixelBlender<Rgba32> blender = new DefaultPixelBlenders<Rgba32>.NormalSrcOver();
PixelBlender<Rgba32> blender = DefaultPixelBlenders<Rgba32>.NormalSrcOver;
Rgba32[] destination = new Rgba32[2];
Rgba32[] background =
[
@ -352,7 +352,7 @@ public class PixelBlenderTests
[Fact]
public void BlendWithCoverage_WithConstantSourceAndSingleAmount()
{
PixelBlender<Rgba32> blender = new DefaultPixelBlenders<Rgba32>.NormalSrc();
PixelBlender<Rgba32> blender = DefaultPixelBlenders<Rgba32>.NormalSrc;
Rgba32[] destination = new Rgba32[3];
Rgba32[] background =
[
@ -374,7 +374,7 @@ public class PixelBlenderTests
[Fact]
public void BlendWithCoverage_WithConstantSourceSingleAmountAndWorkingBuffer()
{
PixelBlender<Rgba32> blender = new DefaultPixelBlenders<Rgba32>.NormalSrc();
PixelBlender<Rgba32> blender = DefaultPixelBlenders<Rgba32>.NormalSrc;
Rgba32[] destination = new Rgba32[3];
Rgba32[] background =
[
@ -397,7 +397,7 @@ public class PixelBlenderTests
[Fact]
public void BlendWithCoverage_WithSourceSpanAndSingleAmount()
{
PixelBlender<Rgba32> blender = new DefaultPixelBlenders<Rgba32>.NormalSrc();
PixelBlender<Rgba32> blender = DefaultPixelBlenders<Rgba32>.NormalSrc;
Rgba32[] destination = new Rgba32[3];
Rgba32[] background =
[
@ -425,7 +425,7 @@ public class PixelBlenderTests
[Fact]
public void BlendWithCoverage_WithSourceSpanSingleAmountAndWorkingBuffer()
{
PixelBlender<Rgba32> blender = new DefaultPixelBlenders<Rgba32>.NormalSrc();
PixelBlender<Rgba32> blender = DefaultPixelBlenders<Rgba32>.NormalSrc;
Rgba32[] destination = new Rgba32[3];
Rgba32[] background =
[
@ -454,7 +454,7 @@ public class PixelBlenderTests
[Fact]
public void BlendWithCoverage_WithConstantSourceAndAmountSpan()
{
PixelBlender<Rgba32> blender = new DefaultPixelBlenders<Rgba32>.NormalSrc();
PixelBlender<Rgba32> blender = DefaultPixelBlenders<Rgba32>.NormalSrc;
Rgba32[] destination = new Rgba32[3];
Rgba32[] background =
[
@ -477,7 +477,7 @@ public class PixelBlenderTests
[Fact]
public void BlendWithCoverage_WithConstantSourceAmountSpanAndWorkingBuffer()
{
PixelBlender<Rgba32> blender = new DefaultPixelBlenders<Rgba32>.NormalSrc();
PixelBlender<Rgba32> blender = DefaultPixelBlenders<Rgba32>.NormalSrc;
Rgba32[] destination = new Rgba32[3];
Rgba32[] background =
[
@ -501,7 +501,7 @@ public class PixelBlenderTests
[Fact]
public void BlendWithCoverage_WithSourceSpanAndAmountSpan()
{
PixelBlender<Rgba32> blender = new DefaultPixelBlenders<Rgba32>.NormalSrc();
PixelBlender<Rgba32> blender = DefaultPixelBlenders<Rgba32>.NormalSrc;
Rgba32[] destination = new Rgba32[3];
Rgba32[] background =
[
@ -530,7 +530,7 @@ public class PixelBlenderTests
[Fact]
public void BlendWithCoverage_WithSourceSpanAmountSpanAndWorkingBuffer()
{
PixelBlender<Rgba32> blender = new DefaultPixelBlenders<Rgba32>.NormalSrc();
PixelBlender<Rgba32> blender = DefaultPixelBlenders<Rgba32>.NormalSrc;
Rgba32[] destination = new Rgba32[3];
Rgba32[] background =
[

36
tests/ImageSharp.Tests/PixelFormats/PixelBlenders/PorterDuffFunctionsTestsTPixel.cs

@ -46,7 +46,7 @@ public class PorterDuffFunctionsTestsTPixel
public void NormalBlendFunctionBlender<TPixel>(TestPixel<TPixel> back, TestPixel<TPixel> source, float amount, TestPixel<TPixel> expected)
where TPixel : unmanaged, IPixel<TPixel>
{
TPixel actual = new DefaultPixelBlenders<TPixel>.NormalSrcOver().Blend(back.AsPixel(), source.AsPixel(), amount);
TPixel actual = DefaultPixelBlenders<TPixel>.NormalSrcOver.Blend(back.AsPixel(), source.AsPixel(), amount);
VectorAssert.Equal(expected.AsPixel(), actual, 2);
}
@ -56,7 +56,7 @@ public class PorterDuffFunctionsTestsTPixel
where TPixel : unmanaged, IPixel<TPixel>
{
TPixel[] dest = new TPixel[BulkBlendCount];
new DefaultPixelBlenders<TPixel>.NormalSrcOver().Blend(this.Configuration, dest, CreateFilledArray(back.AsPixel()), CreateFilledArray(source.AsPixel()), CreateFilledArray(amount));
DefaultPixelBlenders<TPixel>.NormalSrcOver.Blend(this.Configuration, dest, CreateFilledArray(back.AsPixel()), CreateFilledArray(source.AsPixel()), CreateFilledArray(amount));
TPixel expectedPixel = expected.AsPixel();
foreach (TPixel pixel in dest)
@ -91,7 +91,7 @@ public class PorterDuffFunctionsTestsTPixel
public void MultiplyFunctionBlender<TPixel>(TestPixel<TPixel> back, TestPixel<TPixel> source, float amount, TestPixel<TPixel> expected)
where TPixel : unmanaged, IPixel<TPixel>
{
TPixel actual = new DefaultPixelBlenders<TPixel>.MultiplySrcOver().Blend(back.AsPixel(), source.AsPixel(), amount);
TPixel actual = DefaultPixelBlenders<TPixel>.MultiplySrcOver.Blend(back.AsPixel(), source.AsPixel(), amount);
VectorAssert.Equal(expected.AsPixel(), actual, 2);
}
@ -101,7 +101,7 @@ public class PorterDuffFunctionsTestsTPixel
where TPixel : unmanaged, IPixel<TPixel>
{
TPixel[] dest = new TPixel[BulkBlendCount];
new DefaultPixelBlenders<TPixel>.MultiplySrcOver().Blend(this.Configuration, dest, CreateFilledArray(back.AsPixel()), CreateFilledArray(source.AsPixel()), CreateFilledArray(amount));
DefaultPixelBlenders<TPixel>.MultiplySrcOver.Blend(this.Configuration, dest, CreateFilledArray(back.AsPixel()), CreateFilledArray(source.AsPixel()), CreateFilledArray(amount));
TPixel expectedPixel = expected.AsPixel();
foreach (TPixel pixel in dest)
@ -146,7 +146,7 @@ public class PorterDuffFunctionsTestsTPixel
public void AddFunctionBlender<TPixel>(TestPixel<TPixel> back, TestPixel<TPixel> source, float amount, TestPixel<TPixel> expected)
where TPixel : unmanaged, IPixel<TPixel>
{
TPixel actual = new DefaultPixelBlenders<TPixel>.AddSrcOver().Blend(back.AsPixel(), source.AsPixel(), amount);
TPixel actual = DefaultPixelBlenders<TPixel>.AddSrcOver.Blend(back.AsPixel(), source.AsPixel(), amount);
VectorAssert.Equal(expected.AsPixel(), actual, 2);
}
@ -156,7 +156,7 @@ public class PorterDuffFunctionsTestsTPixel
where TPixel : unmanaged, IPixel<TPixel>
{
TPixel[] dest = new TPixel[BulkBlendCount];
new DefaultPixelBlenders<TPixel>.AddSrcOver().Blend(this.Configuration, dest, CreateFilledArray(back.AsPixel()), CreateFilledArray(source.AsPixel()), CreateFilledArray(amount));
DefaultPixelBlenders<TPixel>.AddSrcOver.Blend(this.Configuration, dest, CreateFilledArray(back.AsPixel()), CreateFilledArray(source.AsPixel()), CreateFilledArray(amount));
TPixel expectedPixel = expected.AsPixel();
foreach (TPixel pixel in dest)
@ -191,7 +191,7 @@ public class PorterDuffFunctionsTestsTPixel
public void SubtractFunctionBlender<TPixel>(TestPixel<TPixel> back, TestPixel<TPixel> source, float amount, TestPixel<TPixel> expected)
where TPixel : unmanaged, IPixel<TPixel>
{
TPixel actual = new DefaultPixelBlenders<TPixel>.SubtractSrcOver().Blend(back.AsPixel(), source.AsPixel(), amount);
TPixel actual = DefaultPixelBlenders<TPixel>.SubtractSrcOver.Blend(back.AsPixel(), source.AsPixel(), amount);
VectorAssert.Equal(expected.AsPixel(), actual, 2);
}
@ -201,7 +201,7 @@ public class PorterDuffFunctionsTestsTPixel
where TPixel : unmanaged, IPixel<TPixel>
{
TPixel[] dest = new TPixel[BulkBlendCount];
new DefaultPixelBlenders<TPixel>.SubtractSrcOver().Blend(this.Configuration, dest, CreateFilledArray(back.AsPixel()), CreateFilledArray(source.AsPixel()), CreateFilledArray(amount));
DefaultPixelBlenders<TPixel>.SubtractSrcOver.Blend(this.Configuration, dest, CreateFilledArray(back.AsPixel()), CreateFilledArray(source.AsPixel()), CreateFilledArray(amount));
TPixel expectedPixel = expected.AsPixel();
foreach (TPixel pixel in dest)
@ -236,7 +236,7 @@ public class PorterDuffFunctionsTestsTPixel
public void ScreenFunctionBlender<TPixel>(TestPixel<TPixel> back, TestPixel<TPixel> source, float amount, TestPixel<TPixel> expected)
where TPixel : unmanaged, IPixel<TPixel>
{
TPixel actual = new DefaultPixelBlenders<TPixel>.ScreenSrcOver().Blend(back.AsPixel(), source.AsPixel(), amount);
TPixel actual = DefaultPixelBlenders<TPixel>.ScreenSrcOver.Blend(back.AsPixel(), source.AsPixel(), amount);
VectorAssert.Equal(expected.AsPixel(), actual, 2);
}
@ -246,7 +246,7 @@ public class PorterDuffFunctionsTestsTPixel
where TPixel : unmanaged, IPixel<TPixel>
{
TPixel[] dest = new TPixel[BulkBlendCount];
new DefaultPixelBlenders<TPixel>.ScreenSrcOver().Blend(this.Configuration, dest, CreateFilledArray(back.AsPixel()), CreateFilledArray(source.AsPixel()), CreateFilledArray(amount));
DefaultPixelBlenders<TPixel>.ScreenSrcOver.Blend(this.Configuration, dest, CreateFilledArray(back.AsPixel()), CreateFilledArray(source.AsPixel()), CreateFilledArray(amount));
TPixel expectedPixel = expected.AsPixel();
foreach (TPixel pixel in dest)
@ -281,7 +281,7 @@ public class PorterDuffFunctionsTestsTPixel
public void DarkenFunctionBlender<TPixel>(TestPixel<TPixel> back, TestPixel<TPixel> source, float amount, TestPixel<TPixel> expected)
where TPixel : unmanaged, IPixel<TPixel>
{
TPixel actual = new DefaultPixelBlenders<TPixel>.DarkenSrcOver().Blend(back.AsPixel(), source.AsPixel(), amount);
TPixel actual = DefaultPixelBlenders<TPixel>.DarkenSrcOver.Blend(back.AsPixel(), source.AsPixel(), amount);
VectorAssert.Equal(expected.AsPixel(), actual, 2);
}
@ -291,7 +291,7 @@ public class PorterDuffFunctionsTestsTPixel
where TPixel : unmanaged, IPixel<TPixel>
{
TPixel[] dest = new TPixel[BulkBlendCount];
new DefaultPixelBlenders<TPixel>.DarkenSrcOver().Blend(this.Configuration, dest, CreateFilledArray(back.AsPixel()), CreateFilledArray(source.AsPixel()), CreateFilledArray(amount));
DefaultPixelBlenders<TPixel>.DarkenSrcOver.Blend(this.Configuration, dest, CreateFilledArray(back.AsPixel()), CreateFilledArray(source.AsPixel()), CreateFilledArray(amount));
TPixel expectedPixel = expected.AsPixel();
foreach (TPixel pixel in dest)
@ -326,7 +326,7 @@ public class PorterDuffFunctionsTestsTPixel
public void LightenFunctionBlender<TPixel>(TestPixel<TPixel> back, TestPixel<TPixel> source, float amount, TestPixel<TPixel> expected)
where TPixel : unmanaged, IPixel<TPixel>
{
TPixel actual = new DefaultPixelBlenders<TPixel>.LightenSrcOver().Blend(back.AsPixel(), source.AsPixel(), amount);
TPixel actual = DefaultPixelBlenders<TPixel>.LightenSrcOver.Blend(back.AsPixel(), source.AsPixel(), amount);
VectorAssert.Equal(expected.AsPixel(), actual, 2);
}
@ -336,7 +336,7 @@ public class PorterDuffFunctionsTestsTPixel
where TPixel : unmanaged, IPixel<TPixel>
{
TPixel[] dest = new TPixel[BulkBlendCount];
new DefaultPixelBlenders<TPixel>.LightenSrcOver().Blend(this.Configuration, dest, CreateFilledArray(back.AsPixel()), CreateFilledArray(source.AsPixel()), CreateFilledArray(amount));
DefaultPixelBlenders<TPixel>.LightenSrcOver.Blend(this.Configuration, dest, CreateFilledArray(back.AsPixel()), CreateFilledArray(source.AsPixel()), CreateFilledArray(amount));
TPixel expectedPixel = expected.AsPixel();
foreach (TPixel pixel in dest)
@ -371,7 +371,7 @@ public class PorterDuffFunctionsTestsTPixel
public void OverlayFunctionBlender<TPixel>(TestPixel<TPixel> back, TestPixel<TPixel> source, float amount, TestPixel<TPixel> expected)
where TPixel : unmanaged, IPixel<TPixel>
{
TPixel actual = new DefaultPixelBlenders<TPixel>.OverlaySrcOver().Blend(back.AsPixel(), source.AsPixel(), amount);
TPixel actual = DefaultPixelBlenders<TPixel>.OverlaySrcOver.Blend(back.AsPixel(), source.AsPixel(), amount);
VectorAssert.Equal(expected.AsPixel(), actual, 2);
}
@ -381,7 +381,7 @@ public class PorterDuffFunctionsTestsTPixel
where TPixel : unmanaged, IPixel<TPixel>
{
TPixel[] dest = new TPixel[BulkBlendCount];
new DefaultPixelBlenders<TPixel>.OverlaySrcOver().Blend(this.Configuration, dest, CreateFilledArray(back.AsPixel()), CreateFilledArray(source.AsPixel()), CreateFilledArray(amount));
DefaultPixelBlenders<TPixel>.OverlaySrcOver.Blend(this.Configuration, dest, CreateFilledArray(back.AsPixel()), CreateFilledArray(source.AsPixel()), CreateFilledArray(amount));
TPixel expectedPixel = expected.AsPixel();
foreach (TPixel pixel in dest)
@ -416,7 +416,7 @@ public class PorterDuffFunctionsTestsTPixel
public void HardLightFunctionBlender<TPixel>(TestPixel<TPixel> back, TestPixel<TPixel> source, float amount, TestPixel<TPixel> expected)
where TPixel : unmanaged, IPixel<TPixel>
{
TPixel actual = new DefaultPixelBlenders<TPixel>.HardLightSrcOver().Blend(back.AsPixel(), source.AsPixel(), amount);
TPixel actual = DefaultPixelBlenders<TPixel>.HardLightSrcOver.Blend(back.AsPixel(), source.AsPixel(), amount);
VectorAssert.Equal(expected.AsPixel(), actual, 2);
}
@ -426,7 +426,7 @@ public class PorterDuffFunctionsTestsTPixel
where TPixel : unmanaged, IPixel<TPixel>
{
TPixel[] dest = new TPixel[BulkBlendCount];
new DefaultPixelBlenders<TPixel>.HardLightSrcOver().Blend(this.Configuration, dest, CreateFilledArray(back.AsPixel()), CreateFilledArray(source.AsPixel()), CreateFilledArray(amount));
DefaultPixelBlenders<TPixel>.HardLightSrcOver.Blend(this.Configuration, dest, CreateFilledArray(back.AsPixel()), CreateFilledArray(source.AsPixel()), CreateFilledArray(amount));
TPixel expectedPixel = expected.AsPixel();
foreach (TPixel pixel in dest)

Loading…
Cancel
Save