mirror of https://github.com/SixLabors/ImageSharp
23 changed files with 1608 additions and 750 deletions
@ -1,57 +0,0 @@ |
|||
// <copyright file="DefaultAddPixelBlender{TPixel}.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.PixelFormats.PixelBlenders |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
|
|||
using ImageSharp.Memory; |
|||
using ImageSharp.PixelFormats; |
|||
|
|||
/// <summary>
|
|||
/// Applies an "Add" blending to pixels.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the pixel</typeparam>
|
|||
internal class DefaultAddPixelBlender<TPixel> : PixelBlender<TPixel> |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the static instance of this blender.
|
|||
/// </summary>
|
|||
public static DefaultAddPixelBlender<TPixel> Instance { get; } = new DefaultAddPixelBlender<TPixel>(); |
|||
|
|||
/// <inheritdoc />
|
|||
public override TPixel Blend(TPixel background, TPixel source, float amount) |
|||
{ |
|||
return PorterDuffFunctions<TPixel>.AddFunction(background, source, amount); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Blend(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
|||
|
|||
using (Buffer<Vector4> buffer = new Buffer<Vector4>(destination.Length * 3)) |
|||
{ |
|||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
|||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
|||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
|||
|
|||
PixelOperations<TPixel>.Instance.ToVector4(background, backgroundSpan, destination.Length); |
|||
PixelOperations<TPixel>.Instance.ToVector4(source, sourceSpan, destination.Length); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
destinationSpan[i] = PorterDuffFunctions.AddFunction(backgroundSpan[i], sourceSpan[i], amount[i]); |
|||
} |
|||
|
|||
PixelOperations<TPixel>.Instance.PackFromVector4(destinationSpan, destination, destination.Length); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,57 +0,0 @@ |
|||
// <copyright file="DefaultDarkenPixelBlender{TPixel}.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.PixelFormats.PixelBlenders |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
|
|||
using ImageSharp.Memory; |
|||
using ImageSharp.PixelFormats; |
|||
|
|||
/// <summary>
|
|||
/// Applies an "Darken" blending to pixels.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the pixel</typeparam>
|
|||
internal class DefaultDarkenPixelBlender<TPixel> : PixelBlender<TPixel> |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the static instance of this blender.
|
|||
/// </summary>
|
|||
public static DefaultDarkenPixelBlender<TPixel> Instance { get; } = new DefaultDarkenPixelBlender<TPixel>(); |
|||
|
|||
/// <inheritdoc />
|
|||
public override TPixel Blend(TPixel background, TPixel source, float amount) |
|||
{ |
|||
return PorterDuffFunctions<TPixel>.DarkenFunction(background, source, amount); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Blend(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
|||
|
|||
using (Buffer<Vector4> buffer = new Buffer<Vector4>(destination.Length * 3)) |
|||
{ |
|||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
|||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
|||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
|||
|
|||
PixelOperations<TPixel>.Instance.ToVector4(background, backgroundSpan, destination.Length); |
|||
PixelOperations<TPixel>.Instance.ToVector4(source, sourceSpan, destination.Length); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
destinationSpan[i] = PorterDuffFunctions.DarkenFunction(backgroundSpan[i], sourceSpan[i], amount[i]); |
|||
} |
|||
|
|||
PixelOperations<TPixel>.Instance.PackFromVector4(destinationSpan, destination, destination.Length); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,57 +0,0 @@ |
|||
// <copyright file="DefaultHardLightPixelBlender{TPixel}.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.PixelFormats.PixelBlenders |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
|
|||
using ImageSharp.Memory; |
|||
using ImageSharp.PixelFormats; |
|||
|
|||
/// <summary>
|
|||
/// Applies an "Hard Light" blending to pixels.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the pixel</typeparam>
|
|||
internal class DefaultHardLightPixelBlender<TPixel> : PixelBlender<TPixel> |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the static instance of this blender.
|
|||
/// </summary>
|
|||
public static DefaultHardLightPixelBlender<TPixel> Instance { get; } = new DefaultHardLightPixelBlender<TPixel>(); |
|||
|
|||
/// <inheritdoc />
|
|||
public override TPixel Blend(TPixel background, TPixel source, float amount) |
|||
{ |
|||
return PorterDuffFunctions<TPixel>.HardLightFunction(background, source, amount); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Blend(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
|||
|
|||
using (Buffer<Vector4> buffer = new Buffer<Vector4>(destination.Length * 3)) |
|||
{ |
|||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
|||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
|||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
|||
|
|||
PixelOperations<TPixel>.Instance.ToVector4(background, backgroundSpan, destination.Length); |
|||
PixelOperations<TPixel>.Instance.ToVector4(source, sourceSpan, destination.Length); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
destinationSpan[i] = PorterDuffFunctions.HardLightFunction(backgroundSpan[i], sourceSpan[i], amount[i]); |
|||
} |
|||
|
|||
PixelOperations<TPixel>.Instance.PackFromVector4(destinationSpan, destination, destination.Length); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,57 +0,0 @@ |
|||
// <copyright file="DefaultLightenPixelBlender{TPixel}.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.PixelFormats.PixelBlenders |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
|
|||
using ImageSharp.Memory; |
|||
using ImageSharp.PixelFormats; |
|||
|
|||
/// <summary>
|
|||
/// Applies an "Lighten" blending to pixels.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the pixel</typeparam>
|
|||
internal class DefaultLightenPixelBlender<TPixel> : PixelBlender<TPixel> |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the static instance of this blender.
|
|||
/// </summary>
|
|||
public static DefaultLightenPixelBlender<TPixel> Instance { get; } = new DefaultLightenPixelBlender<TPixel>(); |
|||
|
|||
/// <inheritdoc />
|
|||
public override TPixel Blend(TPixel background, TPixel source, float amount) |
|||
{ |
|||
return PorterDuffFunctions<TPixel>.LightenFunction(background, source, amount); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Blend(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
|||
|
|||
using (Buffer<Vector4> buffer = new Buffer<Vector4>(destination.Length * 3)) |
|||
{ |
|||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
|||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
|||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
|||
|
|||
PixelOperations<TPixel>.Instance.ToVector4(background, backgroundSpan, destination.Length); |
|||
PixelOperations<TPixel>.Instance.ToVector4(source, sourceSpan, destination.Length); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
destinationSpan[i] = PorterDuffFunctions.LightenFunction(backgroundSpan[i], sourceSpan[i], amount[i]); |
|||
} |
|||
|
|||
PixelOperations<TPixel>.Instance.PackFromVector4(destinationSpan, destination, destination.Length); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,57 +0,0 @@ |
|||
// <copyright file="DefaultMultiplyPixelBlender{TPixel}.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.PixelFormats.PixelBlenders |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
|
|||
using ImageSharp.Memory; |
|||
using ImageSharp.PixelFormats; |
|||
|
|||
/// <summary>
|
|||
/// Applies an "Multiply" blending to pixels.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the pixel</typeparam>
|
|||
internal class DefaultMultiplyPixelBlender<TPixel> : PixelBlender<TPixel> |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the static instance of this blender.
|
|||
/// </summary>
|
|||
public static DefaultMultiplyPixelBlender<TPixel> Instance { get; } = new DefaultMultiplyPixelBlender<TPixel>(); |
|||
|
|||
/// <inheritdoc />
|
|||
public override TPixel Blend(TPixel background, TPixel source, float amount) |
|||
{ |
|||
return PorterDuffFunctions<TPixel>.MultiplyFunction(background, source, amount); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Blend(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
|||
|
|||
using (Buffer<Vector4> buffer = new Buffer<Vector4>(destination.Length * 3)) |
|||
{ |
|||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
|||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
|||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
|||
|
|||
PixelOperations<TPixel>.Instance.ToVector4(background, backgroundSpan, destination.Length); |
|||
PixelOperations<TPixel>.Instance.ToVector4(source, sourceSpan, destination.Length); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
destinationSpan[i] = PorterDuffFunctions.MultiplyFunction(backgroundSpan[i], sourceSpan[i], amount[i]); |
|||
} |
|||
|
|||
PixelOperations<TPixel>.Instance.PackFromVector4(destinationSpan, destination, destination.Length); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,57 +0,0 @@ |
|||
// <copyright file="DefaultNormalPixelBlender{TPixel}.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.PixelFormats.PixelBlenders |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
|
|||
using ImageSharp.Memory; |
|||
using ImageSharp.PixelFormats; |
|||
|
|||
/// <summary>
|
|||
/// Applies a "Normal" otherwise nown as "Alpha Blending" blending to pixels.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the pixel</typeparam>
|
|||
internal class DefaultNormalPixelBlender<TPixel> : PixelBlender<TPixel> |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the static instance of this blender.
|
|||
/// </summary>
|
|||
public static DefaultNormalPixelBlender<TPixel> Instance { get; } = new DefaultNormalPixelBlender<TPixel>(); |
|||
|
|||
/// <inheritdoc />
|
|||
public override TPixel Blend(TPixel background, TPixel source, float amount) |
|||
{ |
|||
return PorterDuffFunctions<TPixel>.NormalBlendFunction(background, source, amount); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Blend(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
|||
|
|||
using (Buffer<Vector4> buffer = new Buffer<Vector4>(destination.Length * 3)) |
|||
{ |
|||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
|||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
|||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
|||
|
|||
PixelOperations<TPixel>.Instance.ToVector4(background, backgroundSpan, destination.Length); |
|||
PixelOperations<TPixel>.Instance.ToVector4(source, sourceSpan, destination.Length); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
destinationSpan[i] = PorterDuffFunctions.NormalBlendFunction(backgroundSpan[i], sourceSpan[i], amount[i]); |
|||
} |
|||
|
|||
PixelOperations<TPixel>.Instance.PackFromVector4(destinationSpan, destination, destination.Length); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,57 +0,0 @@ |
|||
// <copyright file="DefaultOverlayPixelBlender{TPixel}.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.PixelFormats.PixelBlenders |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
|
|||
using ImageSharp.Memory; |
|||
using ImageSharp.PixelFormats; |
|||
|
|||
/// <summary>
|
|||
/// Applies an "Overlay" blending to pixels.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the pixel</typeparam>
|
|||
internal class DefaultOverlayPixelBlender<TPixel> : PixelBlender<TPixel> |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the static instance of this blender.
|
|||
/// </summary>
|
|||
public static DefaultOverlayPixelBlender<TPixel> Instance { get; } = new DefaultOverlayPixelBlender<TPixel>(); |
|||
|
|||
/// <inheritdoc />
|
|||
public override TPixel Blend(TPixel background, TPixel source, float amount) |
|||
{ |
|||
return PorterDuffFunctions<TPixel>.OverlayFunction(background, source, amount); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Blend(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
|||
|
|||
using (Buffer<Vector4> buffer = new Buffer<Vector4>(destination.Length * 3)) |
|||
{ |
|||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
|||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
|||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
|||
|
|||
PixelOperations<TPixel>.Instance.ToVector4(background, backgroundSpan, destination.Length); |
|||
PixelOperations<TPixel>.Instance.ToVector4(source, sourceSpan, destination.Length); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
destinationSpan[i] = PorterDuffFunctions.OverlayFunction(backgroundSpan[i], sourceSpan[i], amount[i]); |
|||
} |
|||
|
|||
PixelOperations<TPixel>.Instance.PackFromVector4(destinationSpan, destination, destination.Length); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,849 @@ |
|||
// <autogenerated />
|
|||
// <copyright file="PorterDuffFunctions.Generated.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.PixelFormats.PixelBlenders |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
using ImageSharp.Memory; |
|||
|
|||
|
|||
/// <summary>
|
|||
/// Collection of Porter Duff alpha blending functions applying different composition models.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// These functions are designed to be a general solution for all color cases,
|
|||
/// that is, they take in account the alpha value of both the backdrop
|
|||
/// and source, and there's no need to alpha-premultiply neither the backdrop
|
|||
/// nor the source.
|
|||
/// Note there are faster functions for when the backdrop color is known
|
|||
/// to be opaque
|
|||
/// </remarks>
|
|||
internal static class DefaultPixelBlenders<TPixel> |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
|
|||
internal class Normal : PixelBlender<TPixel> |
|||
{ |
|||
|
|||
/// <summary>
|
|||
/// Gets the static instance of this blender.
|
|||
/// </summary>
|
|||
public static Normal Instance { get; } = new Normal(); |
|||
|
|||
/// <inheritdoc />
|
|||
public override TPixel Blend(TPixel background, TPixel source, float amount) |
|||
{ |
|||
return PorterDuffFunctions.Normal(background, source, amount); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Blend(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
|||
|
|||
using (Buffer<Vector4> buffer = new Buffer<Vector4>(destination.Length * 3)) |
|||
{ |
|||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
|||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
|||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
|||
|
|||
PixelOperations<TPixel>.Instance.ToVector4(background, backgroundSpan, destination.Length); |
|||
PixelOperations<TPixel>.Instance.ToVector4(source, sourceSpan, destination.Length); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
destinationSpan[i] = PorterDuffFunctions.Normal(backgroundSpan[i], sourceSpan[i], amount[i]); |
|||
} |
|||
|
|||
PixelOperations<TPixel>.Instance.PackFromVector4(destinationSpan, destination, destination.Length); |
|||
} |
|||
} |
|||
} |
|||
internal class Multiply : PixelBlender<TPixel> |
|||
{ |
|||
|
|||
/// <summary>
|
|||
/// Gets the static instance of this blender.
|
|||
/// </summary>
|
|||
public static Multiply Instance { get; } = new Multiply(); |
|||
|
|||
/// <inheritdoc />
|
|||
public override TPixel Blend(TPixel background, TPixel source, float amount) |
|||
{ |
|||
return PorterDuffFunctions.Multiply(background, source, amount); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Blend(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
|||
|
|||
using (Buffer<Vector4> buffer = new Buffer<Vector4>(destination.Length * 3)) |
|||
{ |
|||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
|||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
|||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
|||
|
|||
PixelOperations<TPixel>.Instance.ToVector4(background, backgroundSpan, destination.Length); |
|||
PixelOperations<TPixel>.Instance.ToVector4(source, sourceSpan, destination.Length); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
destinationSpan[i] = PorterDuffFunctions.Multiply(backgroundSpan[i], sourceSpan[i], amount[i]); |
|||
} |
|||
|
|||
PixelOperations<TPixel>.Instance.PackFromVector4(destinationSpan, destination, destination.Length); |
|||
} |
|||
} |
|||
} |
|||
internal class Add : PixelBlender<TPixel> |
|||
{ |
|||
|
|||
/// <summary>
|
|||
/// Gets the static instance of this blender.
|
|||
/// </summary>
|
|||
public static Add Instance { get; } = new Add(); |
|||
|
|||
/// <inheritdoc />
|
|||
public override TPixel Blend(TPixel background, TPixel source, float amount) |
|||
{ |
|||
return PorterDuffFunctions.Add(background, source, amount); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Blend(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
|||
|
|||
using (Buffer<Vector4> buffer = new Buffer<Vector4>(destination.Length * 3)) |
|||
{ |
|||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
|||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
|||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
|||
|
|||
PixelOperations<TPixel>.Instance.ToVector4(background, backgroundSpan, destination.Length); |
|||
PixelOperations<TPixel>.Instance.ToVector4(source, sourceSpan, destination.Length); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
destinationSpan[i] = PorterDuffFunctions.Add(backgroundSpan[i], sourceSpan[i], amount[i]); |
|||
} |
|||
|
|||
PixelOperations<TPixel>.Instance.PackFromVector4(destinationSpan, destination, destination.Length); |
|||
} |
|||
} |
|||
} |
|||
internal class Substract : PixelBlender<TPixel> |
|||
{ |
|||
|
|||
/// <summary>
|
|||
/// Gets the static instance of this blender.
|
|||
/// </summary>
|
|||
public static Substract Instance { get; } = new Substract(); |
|||
|
|||
/// <inheritdoc />
|
|||
public override TPixel Blend(TPixel background, TPixel source, float amount) |
|||
{ |
|||
return PorterDuffFunctions.Substract(background, source, amount); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Blend(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
|||
|
|||
using (Buffer<Vector4> buffer = new Buffer<Vector4>(destination.Length * 3)) |
|||
{ |
|||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
|||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
|||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
|||
|
|||
PixelOperations<TPixel>.Instance.ToVector4(background, backgroundSpan, destination.Length); |
|||
PixelOperations<TPixel>.Instance.ToVector4(source, sourceSpan, destination.Length); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
destinationSpan[i] = PorterDuffFunctions.Substract(backgroundSpan[i], sourceSpan[i], amount[i]); |
|||
} |
|||
|
|||
PixelOperations<TPixel>.Instance.PackFromVector4(destinationSpan, destination, destination.Length); |
|||
} |
|||
} |
|||
} |
|||
internal class Screen : PixelBlender<TPixel> |
|||
{ |
|||
|
|||
/// <summary>
|
|||
/// Gets the static instance of this blender.
|
|||
/// </summary>
|
|||
public static Screen Instance { get; } = new Screen(); |
|||
|
|||
/// <inheritdoc />
|
|||
public override TPixel Blend(TPixel background, TPixel source, float amount) |
|||
{ |
|||
return PorterDuffFunctions.Screen(background, source, amount); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Blend(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
|||
|
|||
using (Buffer<Vector4> buffer = new Buffer<Vector4>(destination.Length * 3)) |
|||
{ |
|||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
|||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
|||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
|||
|
|||
PixelOperations<TPixel>.Instance.ToVector4(background, backgroundSpan, destination.Length); |
|||
PixelOperations<TPixel>.Instance.ToVector4(source, sourceSpan, destination.Length); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
destinationSpan[i] = PorterDuffFunctions.Screen(backgroundSpan[i], sourceSpan[i], amount[i]); |
|||
} |
|||
|
|||
PixelOperations<TPixel>.Instance.PackFromVector4(destinationSpan, destination, destination.Length); |
|||
} |
|||
} |
|||
} |
|||
internal class Darken : PixelBlender<TPixel> |
|||
{ |
|||
|
|||
/// <summary>
|
|||
/// Gets the static instance of this blender.
|
|||
/// </summary>
|
|||
public static Darken Instance { get; } = new Darken(); |
|||
|
|||
/// <inheritdoc />
|
|||
public override TPixel Blend(TPixel background, TPixel source, float amount) |
|||
{ |
|||
return PorterDuffFunctions.Darken(background, source, amount); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Blend(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
|||
|
|||
using (Buffer<Vector4> buffer = new Buffer<Vector4>(destination.Length * 3)) |
|||
{ |
|||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
|||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
|||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
|||
|
|||
PixelOperations<TPixel>.Instance.ToVector4(background, backgroundSpan, destination.Length); |
|||
PixelOperations<TPixel>.Instance.ToVector4(source, sourceSpan, destination.Length); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
destinationSpan[i] = PorterDuffFunctions.Darken(backgroundSpan[i], sourceSpan[i], amount[i]); |
|||
} |
|||
|
|||
PixelOperations<TPixel>.Instance.PackFromVector4(destinationSpan, destination, destination.Length); |
|||
} |
|||
} |
|||
} |
|||
internal class Lighten : PixelBlender<TPixel> |
|||
{ |
|||
|
|||
/// <summary>
|
|||
/// Gets the static instance of this blender.
|
|||
/// </summary>
|
|||
public static Lighten Instance { get; } = new Lighten(); |
|||
|
|||
/// <inheritdoc />
|
|||
public override TPixel Blend(TPixel background, TPixel source, float amount) |
|||
{ |
|||
return PorterDuffFunctions.Lighten(background, source, amount); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Blend(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
|||
|
|||
using (Buffer<Vector4> buffer = new Buffer<Vector4>(destination.Length * 3)) |
|||
{ |
|||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
|||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
|||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
|||
|
|||
PixelOperations<TPixel>.Instance.ToVector4(background, backgroundSpan, destination.Length); |
|||
PixelOperations<TPixel>.Instance.ToVector4(source, sourceSpan, destination.Length); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
destinationSpan[i] = PorterDuffFunctions.Lighten(backgroundSpan[i], sourceSpan[i], amount[i]); |
|||
} |
|||
|
|||
PixelOperations<TPixel>.Instance.PackFromVector4(destinationSpan, destination, destination.Length); |
|||
} |
|||
} |
|||
} |
|||
internal class Overlay : PixelBlender<TPixel> |
|||
{ |
|||
|
|||
/// <summary>
|
|||
/// Gets the static instance of this blender.
|
|||
/// </summary>
|
|||
public static Overlay Instance { get; } = new Overlay(); |
|||
|
|||
/// <inheritdoc />
|
|||
public override TPixel Blend(TPixel background, TPixel source, float amount) |
|||
{ |
|||
return PorterDuffFunctions.Overlay(background, source, amount); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Blend(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
|||
|
|||
using (Buffer<Vector4> buffer = new Buffer<Vector4>(destination.Length * 3)) |
|||
{ |
|||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
|||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
|||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
|||
|
|||
PixelOperations<TPixel>.Instance.ToVector4(background, backgroundSpan, destination.Length); |
|||
PixelOperations<TPixel>.Instance.ToVector4(source, sourceSpan, destination.Length); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
destinationSpan[i] = PorterDuffFunctions.Overlay(backgroundSpan[i], sourceSpan[i], amount[i]); |
|||
} |
|||
|
|||
PixelOperations<TPixel>.Instance.PackFromVector4(destinationSpan, destination, destination.Length); |
|||
} |
|||
} |
|||
} |
|||
internal class HardLight : PixelBlender<TPixel> |
|||
{ |
|||
|
|||
/// <summary>
|
|||
/// Gets the static instance of this blender.
|
|||
/// </summary>
|
|||
public static HardLight Instance { get; } = new HardLight(); |
|||
|
|||
/// <inheritdoc />
|
|||
public override TPixel Blend(TPixel background, TPixel source, float amount) |
|||
{ |
|||
return PorterDuffFunctions.HardLight(background, source, amount); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Blend(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
|||
|
|||
using (Buffer<Vector4> buffer = new Buffer<Vector4>(destination.Length * 3)) |
|||
{ |
|||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
|||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
|||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
|||
|
|||
PixelOperations<TPixel>.Instance.ToVector4(background, backgroundSpan, destination.Length); |
|||
PixelOperations<TPixel>.Instance.ToVector4(source, sourceSpan, destination.Length); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
destinationSpan[i] = PorterDuffFunctions.HardLight(backgroundSpan[i], sourceSpan[i], amount[i]); |
|||
} |
|||
|
|||
PixelOperations<TPixel>.Instance.PackFromVector4(destinationSpan, destination, destination.Length); |
|||
} |
|||
} |
|||
} |
|||
internal class Src : PixelBlender<TPixel> |
|||
{ |
|||
|
|||
/// <summary>
|
|||
/// Gets the static instance of this blender.
|
|||
/// </summary>
|
|||
public static Src Instance { get; } = new Src(); |
|||
|
|||
/// <inheritdoc />
|
|||
public override TPixel Blend(TPixel background, TPixel source, float amount) |
|||
{ |
|||
return PorterDuffFunctions.Src(background, source, amount); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Blend(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
|||
|
|||
using (Buffer<Vector4> buffer = new Buffer<Vector4>(destination.Length * 3)) |
|||
{ |
|||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
|||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
|||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
|||
|
|||
PixelOperations<TPixel>.Instance.ToVector4(background, backgroundSpan, destination.Length); |
|||
PixelOperations<TPixel>.Instance.ToVector4(source, sourceSpan, destination.Length); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
destinationSpan[i] = PorterDuffFunctions.Src(backgroundSpan[i], sourceSpan[i], amount[i]); |
|||
} |
|||
|
|||
PixelOperations<TPixel>.Instance.PackFromVector4(destinationSpan, destination, destination.Length); |
|||
} |
|||
} |
|||
} |
|||
internal class Atop : PixelBlender<TPixel> |
|||
{ |
|||
|
|||
/// <summary>
|
|||
/// Gets the static instance of this blender.
|
|||
/// </summary>
|
|||
public static Atop Instance { get; } = new Atop(); |
|||
|
|||
/// <inheritdoc />
|
|||
public override TPixel Blend(TPixel background, TPixel source, float amount) |
|||
{ |
|||
return PorterDuffFunctions.Atop(background, source, amount); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Blend(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
|||
|
|||
using (Buffer<Vector4> buffer = new Buffer<Vector4>(destination.Length * 3)) |
|||
{ |
|||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
|||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
|||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
|||
|
|||
PixelOperations<TPixel>.Instance.ToVector4(background, backgroundSpan, destination.Length); |
|||
PixelOperations<TPixel>.Instance.ToVector4(source, sourceSpan, destination.Length); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
destinationSpan[i] = PorterDuffFunctions.Atop(backgroundSpan[i], sourceSpan[i], amount[i]); |
|||
} |
|||
|
|||
PixelOperations<TPixel>.Instance.PackFromVector4(destinationSpan, destination, destination.Length); |
|||
} |
|||
} |
|||
} |
|||
internal class Over : PixelBlender<TPixel> |
|||
{ |
|||
|
|||
/// <summary>
|
|||
/// Gets the static instance of this blender.
|
|||
/// </summary>
|
|||
public static Over Instance { get; } = new Over(); |
|||
|
|||
/// <inheritdoc />
|
|||
public override TPixel Blend(TPixel background, TPixel source, float amount) |
|||
{ |
|||
return PorterDuffFunctions.Over(background, source, amount); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Blend(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
|||
|
|||
using (Buffer<Vector4> buffer = new Buffer<Vector4>(destination.Length * 3)) |
|||
{ |
|||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
|||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
|||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
|||
|
|||
PixelOperations<TPixel>.Instance.ToVector4(background, backgroundSpan, destination.Length); |
|||
PixelOperations<TPixel>.Instance.ToVector4(source, sourceSpan, destination.Length); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
destinationSpan[i] = PorterDuffFunctions.Over(backgroundSpan[i], sourceSpan[i], amount[i]); |
|||
} |
|||
|
|||
PixelOperations<TPixel>.Instance.PackFromVector4(destinationSpan, destination, destination.Length); |
|||
} |
|||
} |
|||
} |
|||
internal class In : PixelBlender<TPixel> |
|||
{ |
|||
|
|||
/// <summary>
|
|||
/// Gets the static instance of this blender.
|
|||
/// </summary>
|
|||
public static In Instance { get; } = new In(); |
|||
|
|||
/// <inheritdoc />
|
|||
public override TPixel Blend(TPixel background, TPixel source, float amount) |
|||
{ |
|||
return PorterDuffFunctions.In(background, source, amount); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Blend(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
|||
|
|||
using (Buffer<Vector4> buffer = new Buffer<Vector4>(destination.Length * 3)) |
|||
{ |
|||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
|||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
|||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
|||
|
|||
PixelOperations<TPixel>.Instance.ToVector4(background, backgroundSpan, destination.Length); |
|||
PixelOperations<TPixel>.Instance.ToVector4(source, sourceSpan, destination.Length); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
destinationSpan[i] = PorterDuffFunctions.In(backgroundSpan[i], sourceSpan[i], amount[i]); |
|||
} |
|||
|
|||
PixelOperations<TPixel>.Instance.PackFromVector4(destinationSpan, destination, destination.Length); |
|||
} |
|||
} |
|||
} |
|||
internal class Out : PixelBlender<TPixel> |
|||
{ |
|||
|
|||
/// <summary>
|
|||
/// Gets the static instance of this blender.
|
|||
/// </summary>
|
|||
public static Out Instance { get; } = new Out(); |
|||
|
|||
/// <inheritdoc />
|
|||
public override TPixel Blend(TPixel background, TPixel source, float amount) |
|||
{ |
|||
return PorterDuffFunctions.Out(background, source, amount); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Blend(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
|||
|
|||
using (Buffer<Vector4> buffer = new Buffer<Vector4>(destination.Length * 3)) |
|||
{ |
|||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
|||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
|||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
|||
|
|||
PixelOperations<TPixel>.Instance.ToVector4(background, backgroundSpan, destination.Length); |
|||
PixelOperations<TPixel>.Instance.ToVector4(source, sourceSpan, destination.Length); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
destinationSpan[i] = PorterDuffFunctions.Out(backgroundSpan[i], sourceSpan[i], amount[i]); |
|||
} |
|||
|
|||
PixelOperations<TPixel>.Instance.PackFromVector4(destinationSpan, destination, destination.Length); |
|||
} |
|||
} |
|||
} |
|||
internal class Dest : PixelBlender<TPixel> |
|||
{ |
|||
|
|||
/// <summary>
|
|||
/// Gets the static instance of this blender.
|
|||
/// </summary>
|
|||
public static Dest Instance { get; } = new Dest(); |
|||
|
|||
/// <inheritdoc />
|
|||
public override TPixel Blend(TPixel background, TPixel source, float amount) |
|||
{ |
|||
return PorterDuffFunctions.Dest(background, source, amount); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Blend(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
|||
|
|||
using (Buffer<Vector4> buffer = new Buffer<Vector4>(destination.Length * 3)) |
|||
{ |
|||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
|||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
|||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
|||
|
|||
PixelOperations<TPixel>.Instance.ToVector4(background, backgroundSpan, destination.Length); |
|||
PixelOperations<TPixel>.Instance.ToVector4(source, sourceSpan, destination.Length); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
destinationSpan[i] = PorterDuffFunctions.Dest(backgroundSpan[i], sourceSpan[i], amount[i]); |
|||
} |
|||
|
|||
PixelOperations<TPixel>.Instance.PackFromVector4(destinationSpan, destination, destination.Length); |
|||
} |
|||
} |
|||
} |
|||
internal class DestAtop : PixelBlender<TPixel> |
|||
{ |
|||
|
|||
/// <summary>
|
|||
/// Gets the static instance of this blender.
|
|||
/// </summary>
|
|||
public static DestAtop Instance { get; } = new DestAtop(); |
|||
|
|||
/// <inheritdoc />
|
|||
public override TPixel Blend(TPixel background, TPixel source, float amount) |
|||
{ |
|||
return PorterDuffFunctions.DestAtop(background, source, amount); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Blend(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
|||
|
|||
using (Buffer<Vector4> buffer = new Buffer<Vector4>(destination.Length * 3)) |
|||
{ |
|||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
|||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
|||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
|||
|
|||
PixelOperations<TPixel>.Instance.ToVector4(background, backgroundSpan, destination.Length); |
|||
PixelOperations<TPixel>.Instance.ToVector4(source, sourceSpan, destination.Length); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
destinationSpan[i] = PorterDuffFunctions.DestAtop(backgroundSpan[i], sourceSpan[i], amount[i]); |
|||
} |
|||
|
|||
PixelOperations<TPixel>.Instance.PackFromVector4(destinationSpan, destination, destination.Length); |
|||
} |
|||
} |
|||
} |
|||
internal class DestOver : PixelBlender<TPixel> |
|||
{ |
|||
|
|||
/// <summary>
|
|||
/// Gets the static instance of this blender.
|
|||
/// </summary>
|
|||
public static DestOver Instance { get; } = new DestOver(); |
|||
|
|||
/// <inheritdoc />
|
|||
public override TPixel Blend(TPixel background, TPixel source, float amount) |
|||
{ |
|||
return PorterDuffFunctions.DestOver(background, source, amount); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Blend(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
|||
|
|||
using (Buffer<Vector4> buffer = new Buffer<Vector4>(destination.Length * 3)) |
|||
{ |
|||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
|||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
|||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
|||
|
|||
PixelOperations<TPixel>.Instance.ToVector4(background, backgroundSpan, destination.Length); |
|||
PixelOperations<TPixel>.Instance.ToVector4(source, sourceSpan, destination.Length); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
destinationSpan[i] = PorterDuffFunctions.DestOver(backgroundSpan[i], sourceSpan[i], amount[i]); |
|||
} |
|||
|
|||
PixelOperations<TPixel>.Instance.PackFromVector4(destinationSpan, destination, destination.Length); |
|||
} |
|||
} |
|||
} |
|||
internal class DestIn : PixelBlender<TPixel> |
|||
{ |
|||
|
|||
/// <summary>
|
|||
/// Gets the static instance of this blender.
|
|||
/// </summary>
|
|||
public static DestIn Instance { get; } = new DestIn(); |
|||
|
|||
/// <inheritdoc />
|
|||
public override TPixel Blend(TPixel background, TPixel source, float amount) |
|||
{ |
|||
return PorterDuffFunctions.DestIn(background, source, amount); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Blend(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
|||
|
|||
using (Buffer<Vector4> buffer = new Buffer<Vector4>(destination.Length * 3)) |
|||
{ |
|||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
|||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
|||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
|||
|
|||
PixelOperations<TPixel>.Instance.ToVector4(background, backgroundSpan, destination.Length); |
|||
PixelOperations<TPixel>.Instance.ToVector4(source, sourceSpan, destination.Length); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
destinationSpan[i] = PorterDuffFunctions.DestIn(backgroundSpan[i], sourceSpan[i], amount[i]); |
|||
} |
|||
|
|||
PixelOperations<TPixel>.Instance.PackFromVector4(destinationSpan, destination, destination.Length); |
|||
} |
|||
} |
|||
} |
|||
internal class DestOut : PixelBlender<TPixel> |
|||
{ |
|||
|
|||
/// <summary>
|
|||
/// Gets the static instance of this blender.
|
|||
/// </summary>
|
|||
public static DestOut Instance { get; } = new DestOut(); |
|||
|
|||
/// <inheritdoc />
|
|||
public override TPixel Blend(TPixel background, TPixel source, float amount) |
|||
{ |
|||
return PorterDuffFunctions.DestOut(background, source, amount); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Blend(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
|||
|
|||
using (Buffer<Vector4> buffer = new Buffer<Vector4>(destination.Length * 3)) |
|||
{ |
|||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
|||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
|||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
|||
|
|||
PixelOperations<TPixel>.Instance.ToVector4(background, backgroundSpan, destination.Length); |
|||
PixelOperations<TPixel>.Instance.ToVector4(source, sourceSpan, destination.Length); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
destinationSpan[i] = PorterDuffFunctions.DestOut(backgroundSpan[i], sourceSpan[i], amount[i]); |
|||
} |
|||
|
|||
PixelOperations<TPixel>.Instance.PackFromVector4(destinationSpan, destination, destination.Length); |
|||
} |
|||
} |
|||
} |
|||
internal class Clear : PixelBlender<TPixel> |
|||
{ |
|||
|
|||
/// <summary>
|
|||
/// Gets the static instance of this blender.
|
|||
/// </summary>
|
|||
public static Clear Instance { get; } = new Clear(); |
|||
|
|||
/// <inheritdoc />
|
|||
public override TPixel Blend(TPixel background, TPixel source, float amount) |
|||
{ |
|||
return PorterDuffFunctions.Clear(background, source, amount); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Blend(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
|||
|
|||
using (Buffer<Vector4> buffer = new Buffer<Vector4>(destination.Length * 3)) |
|||
{ |
|||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
|||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
|||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
|||
|
|||
PixelOperations<TPixel>.Instance.ToVector4(background, backgroundSpan, destination.Length); |
|||
PixelOperations<TPixel>.Instance.ToVector4(source, sourceSpan, destination.Length); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
destinationSpan[i] = PorterDuffFunctions.Clear(backgroundSpan[i], sourceSpan[i], amount[i]); |
|||
} |
|||
|
|||
PixelOperations<TPixel>.Instance.PackFromVector4(destinationSpan, destination, destination.Length); |
|||
} |
|||
} |
|||
} |
|||
internal class Xor : PixelBlender<TPixel> |
|||
{ |
|||
|
|||
/// <summary>
|
|||
/// Gets the static instance of this blender.
|
|||
/// </summary>
|
|||
public static Xor Instance { get; } = new Xor(); |
|||
|
|||
/// <inheritdoc />
|
|||
public override TPixel Blend(TPixel background, TPixel source, float amount) |
|||
{ |
|||
return PorterDuffFunctions.Xor(background, source, amount); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Blend(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
|||
|
|||
using (Buffer<Vector4> buffer = new Buffer<Vector4>(destination.Length * 3)) |
|||
{ |
|||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
|||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
|||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
|||
|
|||
PixelOperations<TPixel>.Instance.ToVector4(background, backgroundSpan, destination.Length); |
|||
PixelOperations<TPixel>.Instance.ToVector4(source, sourceSpan, destination.Length); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
destinationSpan[i] = PorterDuffFunctions.Xor(backgroundSpan[i], sourceSpan[i], amount[i]); |
|||
} |
|||
|
|||
PixelOperations<TPixel>.Instance.PackFromVector4(destinationSpan, destination, destination.Length); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,118 @@ |
|||
<# |
|||
// <copyright file="DefaultPixelBlenders.Generated.tt" company="James Jackson-South"> |
|||
// Copyright (c) James Jackson-South and contributors. |
|||
// Licensed under the Apache License, Version 2.0. |
|||
// </copyright> |
|||
#> |
|||
<#@ template debug="false" hostspecific="false" language="C#" #> |
|||
<#@ assembly name="System.Core" #> |
|||
<#@ import namespace="System.Linq" #> |
|||
<#@ import namespace="System.Text" #> |
|||
<#@ import namespace="System.Collections.Generic" #> |
|||
<#@ output extension=".cs" #> |
|||
// <autogenerated /> |
|||
// <copyright file="PorterDuffFunctions.Generated.cs" company="James Jackson-South"> |
|||
// Copyright (c) James Jackson-South and contributors. |
|||
// Licensed under the Apache License, Version 2.0. |
|||
// </copyright> |
|||
|
|||
namespace ImageSharp.PixelFormats.PixelBlenders |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
using ImageSharp.Memory; |
|||
|
|||
|
|||
/// <summary> |
|||
/// Collection of Porter Duff alpha blending functions applying different composition models. |
|||
/// </summary> |
|||
/// <remarks> |
|||
/// These functions are designed to be a general solution for all color cases, |
|||
/// that is, they take in account the alpha value of both the backdrop |
|||
/// and source, and there's no need to alpha-premultiply neither the backdrop |
|||
/// nor the source. |
|||
/// Note there are faster functions for when the backdrop color is known |
|||
/// to be opaque |
|||
/// </remarks> |
|||
internal static class DefaultPixelBlenders<TPixel> |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
|
|||
<# |
|||
|
|||
|
|||
|
|||
string[] blenders = new []{ |
|||
"Normal", |
|||
"Multiply", |
|||
"Add", |
|||
"Substract", |
|||
"Screen", |
|||
"Darken", |
|||
"Lighten", |
|||
"Overlay", |
|||
"HardLight", |
|||
"Src" , |
|||
"Atop" , |
|||
"Over" , |
|||
"In" , |
|||
"Out" , |
|||
"Dest" , |
|||
"DestAtop" , |
|||
"DestOver" , |
|||
"DestIn" , |
|||
"DestOut" , |
|||
"Clear" , |
|||
"Xor" , |
|||
}; |
|||
|
|||
|
|||
|
|||
foreach(var blender in blenders) { |
|||
#> |
|||
internal class <#=blender#> : PixelBlender<TPixel> |
|||
{ |
|||
|
|||
/// <summary> |
|||
/// Gets the static instance of this blender. |
|||
/// </summary> |
|||
public static <#=blender#> Instance { get; } = new <#=blender#>(); |
|||
|
|||
/// <inheritdoc /> |
|||
public override TPixel Blend(TPixel background, TPixel source, float amount) |
|||
{ |
|||
return PorterDuffFunctions.<#=blender#>(background, source, amount); |
|||
} |
|||
|
|||
/// <inheritdoc /> |
|||
public override void Blend(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
|||
|
|||
using (Buffer<Vector4> buffer = new Buffer<Vector4>(destination.Length * 3)) |
|||
{ |
|||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
|||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
|||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
|||
|
|||
PixelOperations<TPixel>.Instance.ToVector4(background, backgroundSpan, destination.Length); |
|||
PixelOperations<TPixel>.Instance.ToVector4(source, sourceSpan, destination.Length); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
destinationSpan[i] = PorterDuffFunctions.<#=blender#>(backgroundSpan[i], sourceSpan[i], amount[i]); |
|||
} |
|||
|
|||
PixelOperations<TPixel>.Instance.PackFromVector4(destinationSpan, destination, destination.Length); |
|||
} |
|||
} |
|||
} |
|||
<# |
|||
|
|||
} |
|||
|
|||
#> |
|||
} |
|||
} |
|||
@ -1,57 +0,0 @@ |
|||
// <copyright file="DefaultScreenPixelBlender{TPixel}.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.PixelFormats.PixelBlenders |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
|
|||
using ImageSharp.Memory; |
|||
using ImageSharp.PixelFormats; |
|||
|
|||
/// <summary>
|
|||
/// Applies an "Screen" blending to pixels.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the pixel</typeparam>
|
|||
internal class DefaultScreenPixelBlender<TPixel> : PixelBlender<TPixel> |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the static instance of this blender.
|
|||
/// </summary>
|
|||
public static DefaultScreenPixelBlender<TPixel> Instance { get; } = new DefaultScreenPixelBlender<TPixel>(); |
|||
|
|||
/// <inheritdoc />
|
|||
public override TPixel Blend(TPixel background, TPixel source, float amount) |
|||
{ |
|||
return PorterDuffFunctions<TPixel>.ScreenFunction(background, source, amount); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Blend(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
|||
|
|||
using (Buffer<Vector4> buffer = new Buffer<Vector4>(destination.Length * 3)) |
|||
{ |
|||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
|||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
|||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
|||
|
|||
PixelOperations<TPixel>.Instance.ToVector4(background, backgroundSpan, destination.Length); |
|||
PixelOperations<TPixel>.Instance.ToVector4(source, sourceSpan, destination.Length); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
destinationSpan[i] = PorterDuffFunctions.ScreenFunction(backgroundSpan[i], sourceSpan[i], amount[i]); |
|||
} |
|||
|
|||
PixelOperations<TPixel>.Instance.PackFromVector4(destinationSpan, destination, destination.Length); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,57 +0,0 @@ |
|||
// <copyright file="DefaultSubstractPixelBlender{TPixel}.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.PixelFormats.PixelBlenders |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
|
|||
using ImageSharp.Memory; |
|||
using ImageSharp.PixelFormats; |
|||
|
|||
/// <summary>
|
|||
/// Applies an "Subtract" blending to pixels.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the pixel</typeparam>
|
|||
internal class DefaultSubstractPixelBlender<TPixel> : PixelBlender<TPixel> |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the static instance of this blender.
|
|||
/// </summary>
|
|||
public static DefaultSubstractPixelBlender<TPixel> Instance { get; } = new DefaultSubstractPixelBlender<TPixel>(); |
|||
|
|||
/// <inheritdoc />
|
|||
public override TPixel Blend(TPixel background, TPixel source, float amount) |
|||
{ |
|||
return PorterDuffFunctions<TPixel>.SubstractFunction(background, source, amount); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Blend(Span<TPixel> destination, Span<TPixel> background, Span<TPixel> source, Span<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(background.Length, destination.Length, nameof(background.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length)); |
|||
|
|||
using (Buffer<Vector4> buffer = new Buffer<Vector4>(destination.Length * 3)) |
|||
{ |
|||
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length); |
|||
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length); |
|||
Span<Vector4> sourceSpan = buffer.Slice(destination.Length * 2, destination.Length); |
|||
|
|||
PixelOperations<TPixel>.Instance.ToVector4(background, backgroundSpan, destination.Length); |
|||
PixelOperations<TPixel>.Instance.ToVector4(source, sourceSpan, destination.Length); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
destinationSpan[i] = PorterDuffFunctions.SubstractFunction(backgroundSpan[i], sourceSpan[i], amount[i]); |
|||
} |
|||
|
|||
PixelOperations<TPixel>.Instance.PackFromVector4(destinationSpan, destination, destination.Length); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,314 @@ |
|||
// <autogenerated />
|
|||
// <copyright file="PorterDuffFunctions.Generated.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.PixelFormats.PixelBlenders |
|||
{ |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
|
|||
internal static partial class PorterDuffFunctions |
|||
{ |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Vector4 Src(Vector4 backdrop, Vector4 source, float amount) |
|||
{ |
|||
source.W *= amount; |
|||
if (source.W == 0) |
|||
{ |
|||
return Vector4.Zero; |
|||
} |
|||
|
|||
return Compose(Vector4.Zero, source, source); |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Vector4 Atop(Vector4 backdrop, Vector4 source, float amount) |
|||
{ |
|||
return backdrop; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Vector4 Over(Vector4 backdrop, Vector4 source, float amount) |
|||
{ |
|||
source.W *= amount; |
|||
if (source.W == 0) |
|||
{ |
|||
return backdrop; |
|||
} |
|||
|
|||
return Compose(backdrop, source, source); |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Vector4 In(Vector4 backdrop, Vector4 source, float amount) |
|||
{ |
|||
return Vector4.Zero; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Vector4 Out(Vector4 backdrop, Vector4 source, float amount) |
|||
{ |
|||
source.W *= amount; |
|||
if (source.W == 0) |
|||
{ |
|||
return Vector4.Zero; |
|||
} |
|||
|
|||
return Compose(Vector4.Zero, source, Vector4.Zero); |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Vector4 Dest(Vector4 backdrop, Vector4 source, float amount) |
|||
{ |
|||
return backdrop; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Vector4 DestAtop(Vector4 backdrop, Vector4 source, float amount) |
|||
{ |
|||
source.W *= amount; |
|||
if (source.W == 0) |
|||
{ |
|||
return Vector4.Zero; |
|||
} |
|||
|
|||
return Compose(Vector4.Zero, source, backdrop); |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Vector4 DestOver(Vector4 backdrop, Vector4 source, float amount) |
|||
{ |
|||
source.W *= amount; |
|||
if (source.W == 0) |
|||
{ |
|||
return backdrop; |
|||
} |
|||
|
|||
return Compose(backdrop, source, backdrop); |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Vector4 DestIn(Vector4 backdrop, Vector4 source, float amount) |
|||
{ |
|||
return Vector4.Zero; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Vector4 DestOut(Vector4 backdrop, Vector4 source, float amount) |
|||
{ |
|||
return backdrop; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Vector4 Clear(Vector4 backdrop, Vector4 source, float amount) |
|||
{ |
|||
return Vector4.Zero; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Vector4 Xor(Vector4 backdrop, Vector4 source, float amount) |
|||
{ |
|||
source.W *= amount; |
|||
if (source.W == 0) |
|||
{ |
|||
return backdrop; |
|||
} |
|||
|
|||
return Compose(backdrop, source, Vector4.Zero); |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static TPixel Normal<TPixel>(TPixel backdrop, TPixel source, float amount) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
TPixel dest = default(TPixel); |
|||
dest.PackFromVector4(Normal(backdrop.ToVector4(), source.ToVector4(), amount)); |
|||
return dest; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static TPixel Multiply<TPixel>(TPixel backdrop, TPixel source, float amount) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
TPixel dest = default(TPixel); |
|||
dest.PackFromVector4(Multiply(backdrop.ToVector4(), source.ToVector4(), amount)); |
|||
return dest; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static TPixel Add<TPixel>(TPixel backdrop, TPixel source, float amount) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
TPixel dest = default(TPixel); |
|||
dest.PackFromVector4(Add(backdrop.ToVector4(), source.ToVector4(), amount)); |
|||
return dest; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static TPixel Substract<TPixel>(TPixel backdrop, TPixel source, float amount) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
TPixel dest = default(TPixel); |
|||
dest.PackFromVector4(Substract(backdrop.ToVector4(), source.ToVector4(), amount)); |
|||
return dest; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static TPixel Screen<TPixel>(TPixel backdrop, TPixel source, float amount) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
TPixel dest = default(TPixel); |
|||
dest.PackFromVector4(Screen(backdrop.ToVector4(), source.ToVector4(), amount)); |
|||
return dest; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static TPixel Darken<TPixel>(TPixel backdrop, TPixel source, float amount) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
TPixel dest = default(TPixel); |
|||
dest.PackFromVector4(Darken(backdrop.ToVector4(), source.ToVector4(), amount)); |
|||
return dest; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static TPixel Lighten<TPixel>(TPixel backdrop, TPixel source, float amount) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
TPixel dest = default(TPixel); |
|||
dest.PackFromVector4(Lighten(backdrop.ToVector4(), source.ToVector4(), amount)); |
|||
return dest; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static TPixel Overlay<TPixel>(TPixel backdrop, TPixel source, float amount) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
TPixel dest = default(TPixel); |
|||
dest.PackFromVector4(Overlay(backdrop.ToVector4(), source.ToVector4(), amount)); |
|||
return dest; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static TPixel HardLight<TPixel>(TPixel backdrop, TPixel source, float amount) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
TPixel dest = default(TPixel); |
|||
dest.PackFromVector4(HardLight(backdrop.ToVector4(), source.ToVector4(), amount)); |
|||
return dest; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static TPixel Src<TPixel>(TPixel backdrop, TPixel source, float amount) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
TPixel dest = default(TPixel); |
|||
dest.PackFromVector4(Src(backdrop.ToVector4(), source.ToVector4(), amount)); |
|||
return dest; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static TPixel Atop<TPixel>(TPixel backdrop, TPixel source, float amount) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
TPixel dest = default(TPixel); |
|||
dest.PackFromVector4(Atop(backdrop.ToVector4(), source.ToVector4(), amount)); |
|||
return dest; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static TPixel Over<TPixel>(TPixel backdrop, TPixel source, float amount) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
TPixel dest = default(TPixel); |
|||
dest.PackFromVector4(Over(backdrop.ToVector4(), source.ToVector4(), amount)); |
|||
return dest; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static TPixel In<TPixel>(TPixel backdrop, TPixel source, float amount) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
TPixel dest = default(TPixel); |
|||
dest.PackFromVector4(In(backdrop.ToVector4(), source.ToVector4(), amount)); |
|||
return dest; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static TPixel Out<TPixel>(TPixel backdrop, TPixel source, float amount) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
TPixel dest = default(TPixel); |
|||
dest.PackFromVector4(Out(backdrop.ToVector4(), source.ToVector4(), amount)); |
|||
return dest; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static TPixel Dest<TPixel>(TPixel backdrop, TPixel source, float amount) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
TPixel dest = default(TPixel); |
|||
dest.PackFromVector4(Dest(backdrop.ToVector4(), source.ToVector4(), amount)); |
|||
return dest; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static TPixel DestAtop<TPixel>(TPixel backdrop, TPixel source, float amount) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
TPixel dest = default(TPixel); |
|||
dest.PackFromVector4(DestAtop(backdrop.ToVector4(), source.ToVector4(), amount)); |
|||
return dest; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static TPixel DestOver<TPixel>(TPixel backdrop, TPixel source, float amount) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
TPixel dest = default(TPixel); |
|||
dest.PackFromVector4(DestOver(backdrop.ToVector4(), source.ToVector4(), amount)); |
|||
return dest; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static TPixel DestIn<TPixel>(TPixel backdrop, TPixel source, float amount) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
TPixel dest = default(TPixel); |
|||
dest.PackFromVector4(DestIn(backdrop.ToVector4(), source.ToVector4(), amount)); |
|||
return dest; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static TPixel DestOut<TPixel>(TPixel backdrop, TPixel source, float amount) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
TPixel dest = default(TPixel); |
|||
dest.PackFromVector4(DestOut(backdrop.ToVector4(), source.ToVector4(), amount)); |
|||
return dest; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static TPixel Clear<TPixel>(TPixel backdrop, TPixel source, float amount) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
TPixel dest = default(TPixel); |
|||
dest.PackFromVector4(Clear(backdrop.ToVector4(), source.ToVector4(), amount)); |
|||
return dest; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static TPixel Xor<TPixel>(TPixel backdrop, TPixel source, float amount) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
TPixel dest = default(TPixel); |
|||
dest.PackFromVector4(Xor(backdrop.ToVector4(), source.ToVector4(), amount)); |
|||
return dest; |
|||
} |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,126 @@ |
|||
<# |
|||
// <copyright file="PorterDuffFunctions.Generated.tt" company="James Jackson-South"> |
|||
// Copyright (c) James Jackson-South and contributors. |
|||
// Licensed under the Apache License, Version 2.0. |
|||
// </copyright> |
|||
#> |
|||
<#@ template debug="false" hostspecific="false" language="C#" #> |
|||
<#@ assembly name="System.Core" #> |
|||
<#@ import namespace="System.Linq" #> |
|||
<#@ import namespace="System.Text" #> |
|||
<#@ import namespace="System.Collections.Generic" #> |
|||
<#@ output extension=".cs" #> |
|||
// <autogenerated /> |
|||
// <copyright file="PorterDuffFunctions.Generated.cs" company="James Jackson-South"> |
|||
// Copyright (c) James Jackson-South and contributors. |
|||
// Licensed under the Apache License, Version 2.0. |
|||
// </copyright> |
|||
|
|||
namespace ImageSharp.PixelFormats.PixelBlenders |
|||
{ |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
|
|||
internal static partial class PorterDuffFunctions |
|||
{ |
|||
|
|||
<# |
|||
|
|||
void GeneratePixelBlender (string blender) |
|||
{ |
|||
#> |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static TPixel <#=blender#><TPixel>(TPixel backdrop, TPixel source, float amount) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
TPixel dest = default(TPixel); |
|||
dest.PackFromVector4(<#=blender#>(backdrop.ToVector4(), source.ToVector4(), amount)); |
|||
return dest; |
|||
} |
|||
|
|||
<# |
|||
} |
|||
|
|||
void GenerateVectorCompositor(string name, string sourceVar, string destVar, string blendVar) |
|||
{ |
|||
if(sourceVar == "0") sourceVar= "Vector4.Zero"; |
|||
if(destVar == "0") destVar= "Vector4.Zero"; |
|||
if(blendVar == "0") blendVar= "Vector4.Zero"; |
|||
|
|||
if(sourceVar == "s") sourceVar= "source"; |
|||
if(destVar == "s") destVar= "source"; |
|||
if(blendVar == "s") blendVar= "source"; |
|||
|
|||
if(sourceVar == "d") sourceVar= "backdrop"; |
|||
if(destVar == "d") destVar= "backdrop"; |
|||
if(blendVar == "d") blendVar= "backdrop"; |
|||
#> |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Vector4 <#=name#>(Vector4 backdrop, Vector4 source, float amount) |
|||
{ |
|||
<# |
|||
if(sourceVar == "Vector4.Zero") |
|||
{ |
|||
#> |
|||
return <#=destVar#>; |
|||
<# |
|||
}else{ |
|||
#> |
|||
<#=sourceVar#>.W *= amount; |
|||
if (<#=sourceVar#>.W == 0) |
|||
{ |
|||
return <#=destVar#>; |
|||
} |
|||
|
|||
return Compose(<#=destVar#>, <#=sourceVar#>, <#=blendVar#>); |
|||
<# |
|||
} |
|||
#> |
|||
} |
|||
|
|||
<# |
|||
} |
|||
|
|||
|
|||
GenerateVectorCompositor("Src", "s", "0", "s"); |
|||
GenerateVectorCompositor("Atop", "0", "d", "s"); |
|||
GenerateVectorCompositor("Over", "s", "d", "s"); |
|||
GenerateVectorCompositor("In", "0", "0", "s"); |
|||
GenerateVectorCompositor("Out", "s", "0", "0"); |
|||
GenerateVectorCompositor("Dest", "0", "d", "d"); |
|||
GenerateVectorCompositor("DestAtop", "s", "0", "d"); |
|||
GenerateVectorCompositor("DestOver", "s", "d", "d"); |
|||
GenerateVectorCompositor("DestIn", "0", "0", "d"); |
|||
GenerateVectorCompositor("DestOut", "0", "d", "0"); |
|||
GenerateVectorCompositor("Clear", "0", "0", "0"); |
|||
GenerateVectorCompositor("Xor", "s", "d", "0"); |
|||
|
|||
|
|||
GeneratePixelBlender("Normal"); |
|||
GeneratePixelBlender("Multiply"); |
|||
GeneratePixelBlender("Add"); |
|||
GeneratePixelBlender("Substract"); |
|||
GeneratePixelBlender("Screen"); |
|||
GeneratePixelBlender("Darken"); |
|||
GeneratePixelBlender("Lighten"); |
|||
GeneratePixelBlender("Overlay"); |
|||
GeneratePixelBlender("HardLight"); |
|||
|
|||
GeneratePixelBlender("Src"); |
|||
GeneratePixelBlender("Atop"); |
|||
GeneratePixelBlender("Over"); |
|||
GeneratePixelBlender("In"); |
|||
GeneratePixelBlender("Out"); |
|||
GeneratePixelBlender("Dest"); |
|||
GeneratePixelBlender("DestAtop"); |
|||
GeneratePixelBlender("DestOver"); |
|||
GeneratePixelBlender("DestIn"); |
|||
GeneratePixelBlender("DestOut"); |
|||
GeneratePixelBlender("Clear"); |
|||
GeneratePixelBlender("Xor"); |
|||
|
|||
|
|||
#> |
|||
} |
|||
} |
|||
@ -1,151 +0,0 @@ |
|||
// <copyright file="PorterDuffFunctions.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.PixelFormats.PixelBlenders |
|||
{ |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <summary>
|
|||
/// Collection of Porter Duff alpha blending functions
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">Pixel Format</typeparam>
|
|||
/// <remarks>
|
|||
/// These functions are designed to be a general solution for all color cases,
|
|||
/// that is, they take in account the alpha value of both the backdrop
|
|||
/// and source, and there's no need to alpha-premultiply neither the backdrop
|
|||
/// nor the source.
|
|||
/// Note there are faster functions for when the backdrop color is known
|
|||
/// to be opaque
|
|||
/// </remarks>
|
|||
internal static class PorterDuffFunctions<TPixel> |
|||
where TPixel : IPixel |
|||
{ |
|||
/// <summary>
|
|||
/// Source over backdrop
|
|||
/// </summary>
|
|||
/// <param name="backdrop">Backgrop color</param>
|
|||
/// <param name="source">Source color</param>
|
|||
/// <param name="opacity">Opacity applied to Source Alpha</param>
|
|||
/// <returns>Output color</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static TPixel NormalBlendFunction(TPixel backdrop, TPixel source, float opacity) |
|||
{ |
|||
return ToPixel(PorterDuffFunctions.NormalBlendFunction(backdrop.ToVector4(), source.ToVector4(), opacity)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Source multiplied by backdrop
|
|||
/// </summary>
|
|||
/// <param name="backdrop">Backgrop color</param>
|
|||
/// <param name="source">Source color</param>
|
|||
/// <param name="opacity">Opacity applied to Source Alpha</param>
|
|||
/// <returns>Output color</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static TPixel MultiplyFunction(TPixel backdrop, TPixel source, float opacity) |
|||
{ |
|||
return ToPixel(PorterDuffFunctions.MultiplyFunction(backdrop.ToVector4(), source.ToVector4(), opacity)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Source added to backdrop
|
|||
/// </summary>
|
|||
/// <param name="backdrop">Backgrop color</param>
|
|||
/// <param name="source">Source color</param>
|
|||
/// <param name="opacity">Opacity applied to Source Alpha</param>
|
|||
/// <returns>Output color</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static TPixel AddFunction(TPixel backdrop, TPixel source, float opacity) |
|||
{ |
|||
return ToPixel(PorterDuffFunctions.AddFunction(backdrop.ToVector4(), source.ToVector4(), opacity)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Source substracted from backdrop
|
|||
/// </summary>
|
|||
/// <param name="backdrop">Backgrop color</param>
|
|||
/// <param name="source">Source color</param>
|
|||
/// <param name="opacity">Opacity applied to Source Alpha</param>
|
|||
/// <returns>Output color</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static TPixel SubstractFunction(TPixel backdrop, TPixel source, float opacity) |
|||
{ |
|||
return ToPixel(PorterDuffFunctions.SubstractFunction(backdrop.ToVector4(), source.ToVector4(), opacity)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Complement of source multiplied by the complement of backdrop
|
|||
/// </summary>
|
|||
/// <param name="backdrop">Backgrop color</param>
|
|||
/// <param name="source">Source color</param>
|
|||
/// <param name="opacity">Opacity applied to Source Alpha</param>
|
|||
/// <returns>Output color</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static TPixel ScreenFunction(TPixel backdrop, TPixel source, float opacity) |
|||
{ |
|||
return ToPixel(PorterDuffFunctions.ScreenFunction(backdrop.ToVector4(), source.ToVector4(), opacity)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Per element, chooses the smallest value of source and backdrop
|
|||
/// </summary>
|
|||
/// <param name="backdrop">Backgrop color</param>
|
|||
/// <param name="source">Source color</param>
|
|||
/// <param name="opacity">Opacity applied to Source Alpha</param>
|
|||
/// <returns>Output color</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static TPixel DarkenFunction(TPixel backdrop, TPixel source, float opacity) |
|||
{ |
|||
return ToPixel(PorterDuffFunctions.DarkenFunction(backdrop.ToVector4(), source.ToVector4(), opacity)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Per element, chooses the largest value of source and backdrop
|
|||
/// </summary>
|
|||
/// <param name="backdrop">Backgrop color</param>
|
|||
/// <param name="source">Source color</param>
|
|||
/// <param name="opacity">Opacity applied to Source Alpha</param>
|
|||
/// <returns>Output color</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static TPixel LightenFunction(TPixel backdrop, TPixel source, float opacity) |
|||
{ |
|||
return ToPixel(PorterDuffFunctions.LightenFunction(backdrop.ToVector4(), source.ToVector4(), opacity)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Overlays source over backdrop
|
|||
/// </summary>
|
|||
/// <param name="backdrop">Backgrop color</param>
|
|||
/// <param name="source">Source color</param>
|
|||
/// <param name="opacity">Opacity applied to Source Alpha</param>
|
|||
/// <returns>Output color</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static TPixel OverlayFunction(TPixel backdrop, TPixel source, float opacity) |
|||
{ |
|||
return ToPixel(PorterDuffFunctions.OverlayFunction(backdrop.ToVector4(), source.ToVector4(), opacity)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Hard light effect
|
|||
/// </summary>
|
|||
/// <param name="backdrop">Backgrop color</param>
|
|||
/// <param name="source">Source color</param>
|
|||
/// <param name="opacity">Opacity applied to Source Alpha</param>
|
|||
/// <returns>Output color</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static TPixel HardLightFunction(TPixel backdrop, TPixel source, float opacity) |
|||
{ |
|||
return ToPixel(PorterDuffFunctions.HardLightFunction(backdrop.ToVector4(), source.ToVector4(), opacity)); |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
private static TPixel ToPixel(Vector4 vector) |
|||
{ |
|||
TPixel p = default(TPixel); |
|||
p.PackFromVector4(vector); |
|||
return p; |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue