mirror of https://github.com/SixLabors/ImageSharp
70 changed files with 1430 additions and 322 deletions
@ -0,0 +1,83 @@ |
|||
// <copyright file="PixelCompositor{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 |
|||
{ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Text; |
|||
|
|||
/// <summary>
|
|||
/// The various blending modes.
|
|||
/// </summary>
|
|||
public enum PixelBlenderMode |
|||
{ |
|||
/// <summary>
|
|||
/// The default composition mode.
|
|||
/// </summary>
|
|||
/// <remarks> uses PremultipliedLerpTransform </remarks>
|
|||
Default = 0, |
|||
|
|||
/// <summary>
|
|||
/// Normal transform.
|
|||
/// </summary>
|
|||
Normal, |
|||
|
|||
/// <summary>
|
|||
/// Multiply Transform.
|
|||
/// </summary>
|
|||
Multiply, |
|||
|
|||
/// <summary>
|
|||
/// Screen Transform.
|
|||
/// </summary>
|
|||
Screen, |
|||
|
|||
/// <summary>
|
|||
/// HardLight Transform.
|
|||
/// </summary>
|
|||
HardLight, |
|||
|
|||
/// <summary>
|
|||
/// Overlay Transform.
|
|||
/// </summary>
|
|||
Overlay, |
|||
|
|||
/// <summary>
|
|||
/// Darken Transform.
|
|||
/// </summary>
|
|||
Darken, |
|||
|
|||
/// <summary>
|
|||
/// Lighten Transform.
|
|||
/// </summary>
|
|||
Lighten, |
|||
|
|||
/// <summary>
|
|||
/// SoftLight Transform.
|
|||
/// </summary>
|
|||
SoftLight, |
|||
|
|||
/// <summary>
|
|||
/// Dodge Transform.
|
|||
/// </summary>
|
|||
Dodge, |
|||
|
|||
/// <summary>
|
|||
/// Burn Transform.
|
|||
/// </summary>
|
|||
Burn, |
|||
|
|||
/// <summary>
|
|||
/// Difference Transform.
|
|||
/// </summary>
|
|||
Difference, |
|||
|
|||
/// <summary>
|
|||
/// Exclusion Transform.
|
|||
/// </summary>
|
|||
Exclusion |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
// <copyright file="DefaultBurnPixelBlender{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.PixelFormats; |
|||
|
|||
/// <summary>
|
|||
/// Abstract base class for calling pixel composition functions
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the pixel</typeparam>
|
|||
internal class DefaultBurnPixelBlender<TPixel> : PixelBlender<TPixel> |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
/// <inheritdoc />
|
|||
public override TPixel Compose(TPixel background, TPixel source, float amount) |
|||
{ |
|||
Vector4 result = Vector4BlendTransforms.Burn(background.ToVector4(), source.ToVector4()); |
|||
TPixel resultPixel = default(TPixel); |
|||
resultPixel.PackFromVector4(result); |
|||
return resultPixel; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Compose(BufferSpan<TPixel> destination, BufferSpan<TPixel> background, BufferSpan<TPixel> source, BufferSpan<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(destination.Length, background.Length, nameof(destination)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, background.Length, nameof(destination)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, background.Length, nameof(destination)); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
Vector4 result = Vector4BlendTransforms.Burn(background[i].ToVector4(), source[i].ToVector4()); |
|||
destination[i].PackFromVector4(result); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
// <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.PixelFormats; |
|||
|
|||
/// <summary>
|
|||
/// Abstract base class for calling pixel composition functions
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the pixel</typeparam>
|
|||
internal class DefaultDarkenPixelBlender<TPixel> : PixelBlender<TPixel> |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
/// <inheritdoc />
|
|||
public override TPixel Compose(TPixel background, TPixel source, float amount) |
|||
{ |
|||
Vector4 result = Vector4BlendTransforms.Darken(background.ToVector4(), source.ToVector4()); |
|||
TPixel resultPixel = default(TPixel); |
|||
resultPixel.PackFromVector4(result); |
|||
return resultPixel; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Compose(BufferSpan<TPixel> destination, BufferSpan<TPixel> background, BufferSpan<TPixel> source, BufferSpan<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(destination.Length, background.Length, nameof(destination)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, background.Length, nameof(destination)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, background.Length, nameof(destination)); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
Vector4 result = Vector4BlendTransforms.Darken(background[i].ToVector4(), source[i].ToVector4()); |
|||
destination[i].PackFromVector4(result); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
// <copyright file="DefaultDifferencePixelBlender{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.PixelFormats; |
|||
|
|||
/// <summary>
|
|||
/// Abstract base class for calling pixel composition functions
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the pixel</typeparam>
|
|||
internal class DefaultDifferencePixelBlender<TPixel> : PixelBlender<TPixel> |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
/// <inheritdoc />
|
|||
public override TPixel Compose(TPixel background, TPixel source, float amount) |
|||
{ |
|||
Vector4 result = Vector4BlendTransforms.Difference(background.ToVector4(), source.ToVector4()); |
|||
TPixel resultPixel = default(TPixel); |
|||
resultPixel.PackFromVector4(result); |
|||
return resultPixel; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Compose(BufferSpan<TPixel> destination, BufferSpan<TPixel> background, BufferSpan<TPixel> source, BufferSpan<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(destination.Length, background.Length, nameof(destination)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, background.Length, nameof(destination)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, background.Length, nameof(destination)); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
Vector4 result = Vector4BlendTransforms.Difference(background[i].ToVector4(), source[i].ToVector4()); |
|||
destination[i].PackFromVector4(result); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
// <copyright file="DefaultDodgePixelBlender{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.PixelFormats; |
|||
|
|||
/// <summary>
|
|||
/// Abstract base class for calling pixel composition functions
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the pixel</typeparam>
|
|||
internal class DefaultDodgePixelBlender<TPixel> : PixelBlender<TPixel> |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
/// <inheritdoc />
|
|||
public override TPixel Compose(TPixel background, TPixel source, float amount) |
|||
{ |
|||
Vector4 result = Vector4BlendTransforms.Dodge(background.ToVector4(), source.ToVector4()); |
|||
TPixel resultPixel = default(TPixel); |
|||
resultPixel.PackFromVector4(result); |
|||
return resultPixel; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Compose(BufferSpan<TPixel> destination, BufferSpan<TPixel> background, BufferSpan<TPixel> source, BufferSpan<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(destination.Length, background.Length, nameof(destination)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, background.Length, nameof(destination)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, background.Length, nameof(destination)); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
Vector4 result = Vector4BlendTransforms.Dodge(background[i].ToVector4(), source[i].ToVector4()); |
|||
destination[i].PackFromVector4(result); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
// <copyright file="DefaultExclusionPixelBlender{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.PixelFormats; |
|||
|
|||
/// <summary>
|
|||
/// Abstract base class for calling pixel composition functions
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the pixel</typeparam>
|
|||
internal class DefaultExclusionPixelBlender<TPixel> : PixelBlender<TPixel> |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
/// <inheritdoc />
|
|||
public override TPixel Compose(TPixel background, TPixel source, float amount) |
|||
{ |
|||
Vector4 result = Vector4BlendTransforms.Exclusion(background.ToVector4(), source.ToVector4()); |
|||
TPixel resultPixel = default(TPixel); |
|||
resultPixel.PackFromVector4(result); |
|||
return resultPixel; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Compose(BufferSpan<TPixel> destination, BufferSpan<TPixel> background, BufferSpan<TPixel> source, BufferSpan<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(destination.Length, background.Length, nameof(destination)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, background.Length, nameof(destination)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, background.Length, nameof(destination)); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
Vector4 result = Vector4BlendTransforms.Exclusion(background[i].ToVector4(), source[i].ToVector4()); |
|||
destination[i].PackFromVector4(result); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
// <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.PixelFormats; |
|||
|
|||
/// <summary>
|
|||
/// Abstract base class for calling pixel composition functions
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the pixel</typeparam>
|
|||
internal class DefaultHardLightPixelBlender<TPixel> : PixelBlender<TPixel> |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
/// <inheritdoc />
|
|||
public override TPixel Compose(TPixel background, TPixel source, float amount) |
|||
{ |
|||
Vector4 result = Vector4BlendTransforms.HardLight(background.ToVector4(), source.ToVector4()); |
|||
TPixel resultPixel = default(TPixel); |
|||
resultPixel.PackFromVector4(result); |
|||
return resultPixel; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Compose(BufferSpan<TPixel> destination, BufferSpan<TPixel> background, BufferSpan<TPixel> source, BufferSpan<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(destination.Length, background.Length, nameof(destination)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, background.Length, nameof(destination)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, background.Length, nameof(destination)); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
Vector4 result = Vector4BlendTransforms.HardLight(background[i].ToVector4(), source[i].ToVector4()); |
|||
destination[i].PackFromVector4(result); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
// <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.PixelFormats; |
|||
|
|||
/// <summary>
|
|||
/// Abstract base class for calling pixel composition functions
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the pixel</typeparam>
|
|||
internal class DefaultLightenPixelBlender<TPixel> : PixelBlender<TPixel> |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
/// <inheritdoc />
|
|||
public override TPixel Compose(TPixel background, TPixel source, float amount) |
|||
{ |
|||
Vector4 result = Vector4BlendTransforms.Lighten(background.ToVector4(), source.ToVector4()); |
|||
TPixel resultPixel = default(TPixel); |
|||
resultPixel.PackFromVector4(result); |
|||
return resultPixel; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Compose(BufferSpan<TPixel> destination, BufferSpan<TPixel> background, BufferSpan<TPixel> source, BufferSpan<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(destination.Length, background.Length, nameof(destination)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, background.Length, nameof(destination)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, background.Length, nameof(destination)); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
Vector4 result = Vector4BlendTransforms.Lighten(background[i].ToVector4(), source[i].ToVector4()); |
|||
destination[i].PackFromVector4(result); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
// <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.PixelFormats; |
|||
|
|||
/// <summary>
|
|||
/// Abstract base class for calling pixel composition functions
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the pixel</typeparam>
|
|||
internal class DefaultMultiplyPixelBlender<TPixel> : PixelBlender<TPixel> |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
/// <inheritdoc />
|
|||
public override TPixel Compose(TPixel background, TPixel source, float amount) |
|||
{ |
|||
Vector4 result = Vector4BlendTransforms.Multiply(background.ToVector4(), source.ToVector4()); |
|||
TPixel resultPixel = default(TPixel); |
|||
resultPixel.PackFromVector4(result); |
|||
return resultPixel; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Compose(BufferSpan<TPixel> destination, BufferSpan<TPixel> background, BufferSpan<TPixel> source, BufferSpan<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(destination.Length, background.Length, nameof(destination)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, background.Length, nameof(destination)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, background.Length, nameof(destination)); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
Vector4 result = Vector4BlendTransforms.Multiply(background[i].ToVector4(), source[i].ToVector4()); |
|||
destination[i].PackFromVector4(result); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,37 @@ |
|||
// <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 ImageSharp.PixelFormats; |
|||
|
|||
/// <summary>
|
|||
/// Abstract base class for calling pixel composition functions
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the pixel</typeparam>
|
|||
internal class DefaultNormalPixelBlender<TPixel> : PixelBlender<TPixel> |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
/// <inheritdoc />
|
|||
public override TPixel Compose(TPixel background, TPixel source, float amount) |
|||
{ |
|||
return source; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Compose(BufferSpan<TPixel> destination, BufferSpan<TPixel> background, BufferSpan<TPixel> source, BufferSpan<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(destination.Length, background.Length, nameof(destination)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, background.Length, nameof(destination)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, background.Length, nameof(destination)); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
destination[i] = source[i]; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
// <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.PixelFormats; |
|||
|
|||
/// <summary>
|
|||
/// Abstract base class for calling pixel composition functions
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the pixel</typeparam>
|
|||
internal class DefaultOverlayPixelBlender<TPixel> : PixelBlender<TPixel> |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
/// <inheritdoc />
|
|||
public override TPixel Compose(TPixel background, TPixel source, float amount) |
|||
{ |
|||
Vector4 result = Vector4BlendTransforms.Overlay(background.ToVector4(), source.ToVector4()); |
|||
TPixel resultPixel = default(TPixel); |
|||
resultPixel.PackFromVector4(result); |
|||
return resultPixel; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Compose(BufferSpan<TPixel> destination, BufferSpan<TPixel> background, BufferSpan<TPixel> source, BufferSpan<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(destination.Length, background.Length, nameof(destination)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, background.Length, nameof(destination)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, background.Length, nameof(destination)); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
Vector4 result = Vector4BlendTransforms.Overlay(background[i].ToVector4(), source[i].ToVector4()); |
|||
destination[i].PackFromVector4(result); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
// <copyright file="DefaultDifferencePixelBlender{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.PixelFormats; |
|||
|
|||
/// <summary>
|
|||
/// Abstract base class for calling pixel composition functions
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the pixel</typeparam>
|
|||
internal class DefaultPremultipliedLerpPixelBlender<TPixel> : PixelBlender<TPixel> |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
/// <inheritdoc />
|
|||
public override TPixel Compose(TPixel background, TPixel source, float amount) |
|||
{ |
|||
Vector4 result = Vector4BlendTransforms.PremultipliedLerp(background.ToVector4(), source.ToVector4(), amount); |
|||
TPixel resultPixel = default(TPixel); |
|||
resultPixel.PackFromVector4(result); |
|||
return resultPixel; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Compose(BufferSpan<TPixel> destination, BufferSpan<TPixel> background, BufferSpan<TPixel> source, BufferSpan<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(destination.Length, background.Length, nameof(destination)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, background.Length, nameof(destination)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, background.Length, nameof(destination)); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
Vector4 result = Vector4BlendTransforms.PremultipliedLerp(background[i].ToVector4(), source[i].ToVector4(), amount[i]); |
|||
destination[i].PackFromVector4(result); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
// <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.PixelFormats; |
|||
|
|||
/// <summary>
|
|||
/// Abstract base class for calling pixel composition functions
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the pixel</typeparam>
|
|||
internal class DefaultScreenPixelBlender<TPixel> : PixelBlender<TPixel> |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
/// <inheritdoc />
|
|||
public override TPixel Compose(TPixel background, TPixel source, float amount) |
|||
{ |
|||
Vector4 result = Vector4BlendTransforms.Screen(background.ToVector4(), source.ToVector4()); |
|||
TPixel resultPixel = default(TPixel); |
|||
resultPixel.PackFromVector4(result); |
|||
return resultPixel; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Compose(BufferSpan<TPixel> destination, BufferSpan<TPixel> background, BufferSpan<TPixel> source, BufferSpan<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(destination.Length, background.Length, nameof(destination)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, background.Length, nameof(destination)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, background.Length, nameof(destination)); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
Vector4 result = Vector4BlendTransforms.Screen(background[i].ToVector4(), source[i].ToVector4()); |
|||
destination[i].PackFromVector4(result); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
// <copyright file="DefaultSoftLightPixelBlender{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.PixelFormats; |
|||
|
|||
/// <summary>
|
|||
/// Abstract base class for calling pixel composition functions
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the pixel</typeparam>
|
|||
internal class DefaultSoftLightPixelBlender<TPixel> : PixelBlender<TPixel> |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
/// <inheritdoc />
|
|||
public override TPixel Compose(TPixel background, TPixel source, float amount) |
|||
{ |
|||
Vector4 result = Vector4BlendTransforms.SoftLight(background.ToVector4(), source.ToVector4()); |
|||
TPixel resultPixel = default(TPixel); |
|||
resultPixel.PackFromVector4(result); |
|||
return resultPixel; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public override void Compose(BufferSpan<TPixel> destination, BufferSpan<TPixel> background, BufferSpan<TPixel> source, BufferSpan<float> amount) |
|||
{ |
|||
Guard.MustBeGreaterThanOrEqualTo(destination.Length, background.Length, nameof(destination)); |
|||
Guard.MustBeGreaterThanOrEqualTo(source.Length, background.Length, nameof(destination)); |
|||
Guard.MustBeGreaterThanOrEqualTo(amount.Length, background.Length, nameof(destination)); |
|||
|
|||
for (int i = 0; i < destination.Length; i++) |
|||
{ |
|||
Vector4 result = Vector4BlendTransforms.SoftLight(background[i].ToVector4(), source[i].ToVector4()); |
|||
destination[i].PackFromVector4(result); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,39 @@ |
|||
// <copyright file="PixelCompositor{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 |
|||
{ |
|||
/// <summary>
|
|||
/// Abstract base class for calling pixel composition functions
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the pixel</typeparam>
|
|||
internal abstract class PixelBlender<TPixel> |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
/// <summary>
|
|||
/// Composes 2 pixels together.
|
|||
/// </summary>
|
|||
/// <param name="background">The background color.</param>
|
|||
/// <param name="source">The source color.</param>
|
|||
/// <param name="amount">
|
|||
/// A value between 0 and 1 indicating the weight of the second source vector.
|
|||
/// At amount = 0, "from" is returned, at amount = 1, "to" is returned.
|
|||
/// </param>
|
|||
/// <returns>The final pixel value after composition</returns>
|
|||
public abstract TPixel Compose(TPixel background, TPixel source, float amount); |
|||
|
|||
/// <summary>
|
|||
/// Composes 2 pixels together.
|
|||
/// </summary>
|
|||
/// <param name="destination">The destination span.</param>
|
|||
/// <param name="background">The background span.</param>
|
|||
/// <param name="source">The source span.</param>
|
|||
/// <param name="amount">
|
|||
/// A value between 0 and 1 indicating the weight of the second source vector.
|
|||
/// At amount = 0, "from" is returned, at amount = 1, "to" is returned.
|
|||
/// </param>
|
|||
public abstract void Compose(BufferSpan<TPixel> destination, BufferSpan<TPixel> background, BufferSpan<TPixel> source, BufferSpan<float> amount); |
|||
} |
|||
} |
|||
@ -0,0 +1,125 @@ |
|||
// <copyright file="PixelOperations{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 |
|||
{ |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using ImageSharp.PixelFormats.PixelBlenders; |
|||
|
|||
#pragma warning disable CS1710 // XML comment has a duplicate typeparam tag
|
|||
/// <summary>
|
|||
/// A stateless class implementing Strategy Pattern for batched pixel-data conversion operations
|
|||
/// for pixel buffers of type <typeparamref name="TPixel"/>.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
public partial class PixelOperations<TPixel> |
|||
#pragma warning restore CS1710 // XML comment has a duplicate typeparam tag
|
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the NormalBlender.
|
|||
/// </summary>
|
|||
private PixelBlender<TPixel> normalBlender = new DefaultNormalPixelBlender<TPixel>(); |
|||
|
|||
/// <summary>
|
|||
/// Gets the MultiplyBlender.
|
|||
/// </summary>
|
|||
private PixelBlender<TPixel> multiplyBlender = new DefaultMultiplyPixelBlender<TPixel>(); |
|||
|
|||
/// <summary>
|
|||
/// Gets the ScreenBlender.
|
|||
/// </summary>
|
|||
private PixelBlender<TPixel> screenBlender = new DefaultScreenPixelBlender<TPixel>(); |
|||
|
|||
/// <summary>
|
|||
/// Gets the HardLightBlender.
|
|||
/// </summary>
|
|||
private PixelBlender<TPixel> hardLightBlender = new DefaultHardLightPixelBlender<TPixel>(); |
|||
|
|||
/// <summary>
|
|||
/// Gets the OverlayBlender.
|
|||
/// </summary>
|
|||
private PixelBlender<TPixel> overlayBlender = new DefaultOverlayPixelBlender<TPixel>(); |
|||
|
|||
/// <summary>
|
|||
/// Gets the DarkenBlender.
|
|||
/// </summary>
|
|||
private PixelBlender<TPixel> darkenBlender = new DefaultDarkenPixelBlender<TPixel>(); |
|||
|
|||
/// <summary>
|
|||
/// Gets the LightenBlender.
|
|||
/// </summary>
|
|||
private PixelBlender<TPixel> lightenBlender = new DefaultLightenPixelBlender<TPixel>(); |
|||
|
|||
/// <summary>
|
|||
/// Gets the SoftLightBlender.
|
|||
/// </summary>
|
|||
private PixelBlender<TPixel> softLightBlender = new DefaultSoftLightPixelBlender<TPixel>(); |
|||
|
|||
/// <summary>
|
|||
/// Gets the DodgeBlender.
|
|||
/// </summary>
|
|||
private PixelBlender<TPixel> dodgeBlender = new DefaultDodgePixelBlender<TPixel>(); |
|||
|
|||
/// <summary>
|
|||
/// Gets the BurnBlender.
|
|||
/// </summary>
|
|||
private PixelBlender<TPixel> burnBlender = new DefaultBurnPixelBlender<TPixel>(); |
|||
|
|||
/// <summary>
|
|||
/// Gets the DifferenceBlender.
|
|||
/// </summary>
|
|||
private PixelBlender<TPixel> differenceBlender = new DefaultDifferencePixelBlender<TPixel>(); |
|||
|
|||
/// <summary>
|
|||
/// Gets the DifferenceBlender.
|
|||
/// </summary>
|
|||
private PixelBlender<TPixel> exclusionBlender = new DefaultExclusionPixelBlender<TPixel>(); |
|||
|
|||
/// <summary>
|
|||
/// Gets the PremultipliedLerpBlender.
|
|||
/// </summary>
|
|||
private PixelBlender<TPixel> premultipliedLerpBlender = new DefaultPremultipliedLerpPixelBlender<TPixel>(); |
|||
|
|||
/// <summary>
|
|||
/// Find an instance of the pixel blender.
|
|||
/// </summary>
|
|||
/// <param name="mode">The blending mode to apply</param>
|
|||
/// <returns>A <see cref="PixelBlender{TPixel}"/>.</returns>
|
|||
internal virtual PixelBlender<TPixel> GetPixelBlender(PixelBlenderMode mode) |
|||
{ |
|||
switch (mode) |
|||
{ |
|||
case PixelBlenderMode.Normal: |
|||
return this.normalBlender; |
|||
case PixelBlenderMode.Multiply: |
|||
return this.multiplyBlender; |
|||
case PixelBlenderMode.Screen: |
|||
return this.screenBlender; |
|||
case PixelBlenderMode.HardLight: |
|||
return this.hardLightBlender; |
|||
case PixelBlenderMode.Overlay: |
|||
return this.overlayBlender; |
|||
case PixelBlenderMode.Darken: |
|||
return this.darkenBlender; |
|||
case PixelBlenderMode.Lighten: |
|||
return this.lightenBlender; |
|||
case PixelBlenderMode.SoftLight: |
|||
return this.softLightBlender; |
|||
case PixelBlenderMode.Dodge: |
|||
return this.dodgeBlender; |
|||
case PixelBlenderMode.Burn: |
|||
return this.burnBlender; |
|||
case PixelBlenderMode.Difference: |
|||
return this.differenceBlender; |
|||
case PixelBlenderMode.Exclusion: |
|||
return this.exclusionBlender; |
|||
default: |
|||
return this.premultipliedLerpBlender; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,100 @@ |
|||
// <copyright file="GlowProcessor.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.Processing.Processors |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
using System.Threading.Tasks; |
|||
|
|||
using ImageSharp.PixelFormats; |
|||
|
|||
/// <summary>
|
|||
/// An <see cref="IImageProcessor{TPixel}"/> that applies a radial glow effect an <see cref="Image{TPixel}"/>.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
internal class GlowProcessorParallel<TPixel> : ImageProcessor<TPixel> |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="GlowProcessorParallel{TPixel}" /> class.
|
|||
/// </summary>
|
|||
/// <param name="color">The color or the glow.</param>
|
|||
public GlowProcessorParallel(TPixel color) |
|||
{ |
|||
this.GlowColor = color; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the glow color to apply.
|
|||
/// </summary>
|
|||
public TPixel GlowColor { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the the radius.
|
|||
/// </summary>
|
|||
public float Radius { get; set; } |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override void OnApply(ImageBase<TPixel> source, Rectangle sourceRectangle) |
|||
{ |
|||
int startY = sourceRectangle.Y; |
|||
int endY = sourceRectangle.Bottom; |
|||
int startX = sourceRectangle.X; |
|||
int endX = sourceRectangle.Right; |
|||
TPixel glowColor = this.GlowColor; |
|||
Vector2 centre = Rectangle.Center(sourceRectangle).ToVector2(); |
|||
float maxDistance = this.Radius > 0 ? MathF.Min(this.Radius, sourceRectangle.Width * .5F) : sourceRectangle.Width * .5F; |
|||
|
|||
// Align start/end positions.
|
|||
int minX = Math.Max(0, startX); |
|||
int maxX = Math.Min(source.Width, endX); |
|||
int minY = Math.Max(0, startY); |
|||
int maxY = Math.Min(source.Height, endY); |
|||
|
|||
// Reset offset if necessary.
|
|||
if (minX > 0) |
|||
{ |
|||
startX = 0; |
|||
} |
|||
|
|||
if (minY > 0) |
|||
{ |
|||
startY = 0; |
|||
} |
|||
|
|||
int width = maxX - minX; |
|||
using (Buffer<TPixel> rowColors = new Buffer<TPixel>(width)) |
|||
using (PixelAccessor<TPixel> sourcePixels = source.Lock()) |
|||
{ |
|||
for (int i = 0; i < width; i++) |
|||
{ |
|||
rowColors[i] = glowColor; |
|||
} |
|||
|
|||
PixelBlender<TPixel> blender = PixelOperations<TPixel>.Instance.GetPixelBlender(PixelBlenderMode.Default); |
|||
|
|||
Parallel.For( |
|||
minY, |
|||
maxY, |
|||
this.ParallelOptions, |
|||
y => |
|||
{ |
|||
int offsetY = y - startY; |
|||
|
|||
for (int x = minX; x < maxX; x++) |
|||
{ |
|||
int offsetX = x - startX; |
|||
float distance = Vector2.Distance(centre, new Vector2(offsetX, offsetY)); |
|||
Vector4 sourceColor = sourcePixels[offsetX, offsetY].ToVector4(); |
|||
TPixel packed = default(TPixel); |
|||
packed.PackFromVector4(Vector4BlendTransforms.PremultipliedLerp(sourceColor, glowColor.ToVector4(), 1 - (.95F * (distance / maxDistance)))); |
|||
sourcePixels[offsetX, offsetY] = packed; |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,48 @@ |
|||
// <copyright file="Crop.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.Benchmarks |
|||
{ |
|||
|
|||
using BenchmarkDotNet.Attributes; |
|||
using ImageSharp.PixelFormats; |
|||
using ImageSharp.Drawing; |
|||
using ImageSharp.Processing.Processors; |
|||
using CoreImage = ImageSharp.Image; |
|||
using CoreSize = ImageSharp.Size; |
|||
|
|||
public class Glow : BenchmarkBase |
|||
{ |
|||
private GlowProcessor<Rgba32> bulk; |
|||
private GlowProcessorParallel<Rgba32> parallel; |
|||
|
|||
[Setup] |
|||
public void Setup() |
|||
{ |
|||
this.bulk = new GlowProcessor<Rgba32>(NamedColors<Rgba32>.Beige) { Radius = 800 * .5f, }; |
|||
this.parallel = new GlowProcessorParallel<Rgba32>(NamedColors<Rgba32>.Beige) { Radius = 800 * .5f, }; |
|||
|
|||
} |
|||
[Benchmark(Description = "ImageSharp Glow - Bulk")] |
|||
public CoreSize GlowBulk() |
|||
{ |
|||
using (CoreImage image = new CoreImage(800, 800)) |
|||
{ |
|||
image.ApplyProcessor(bulk, image.Bounds); |
|||
return new CoreSize(image.Width, image.Height); |
|||
} |
|||
} |
|||
|
|||
[Benchmark(Description = "ImageSharp Glow - Parallel")] |
|||
public CoreSize GLowSimple() |
|||
{ |
|||
using (CoreImage image = new CoreImage(800, 800)) |
|||
{ |
|||
image.ApplyProcessor(parallel, image.Bounds); |
|||
return new CoreSize(image.Width, image.Height); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,53 @@ |
|||
|
|||
|
|||
namespace ImageSharp.Tests.PixelFormats |
|||
{ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Text; |
|||
using ImageSharp.PixelFormats; |
|||
using ImageSharp.PixelFormats.PixelBlenders; |
|||
using ImageSharp.Tests.TestUtilities; |
|||
using Xunit; |
|||
|
|||
public class PixelOperations |
|||
{ |
|||
public static TheoryData<object, Type, PixelBlenderMode> blenderMappings = new TheoryData<object, Type, PixelBlenderMode>() |
|||
{ |
|||
{ new TestPixel<Rgba32>(), typeof(DefaultPremultipliedLerpPixelBlender<Rgba32>), PixelBlenderMode.Default }, |
|||
{ new TestPixel<Rgba32>(), typeof(DefaultNormalPixelBlender<Rgba32>), PixelBlenderMode.Normal }, |
|||
{ new TestPixel<Rgba32>(), typeof(DefaultScreenPixelBlender<Rgba32>), PixelBlenderMode.Screen }, |
|||
{ new TestPixel<Rgba32>(), typeof(DefaultHardLightPixelBlender<Rgba32>), PixelBlenderMode.HardLight }, |
|||
{ new TestPixel<Rgba32>(), typeof(DefaultOverlayPixelBlender<Rgba32>), PixelBlenderMode.Overlay }, |
|||
{ new TestPixel<Rgba32>(), typeof(DefaultDarkenPixelBlender<Rgba32>), PixelBlenderMode.Darken }, |
|||
{ new TestPixel<Rgba32>(), typeof(DefaultLightenPixelBlender<Rgba32>), PixelBlenderMode.Lighten }, |
|||
{ new TestPixel<Rgba32>(), typeof(DefaultSoftLightPixelBlender<Rgba32>), PixelBlenderMode.SoftLight }, |
|||
{ new TestPixel<Rgba32>(), typeof(DefaultDodgePixelBlender<Rgba32>), PixelBlenderMode.Dodge }, |
|||
{ new TestPixel<Rgba32>(), typeof(DefaultBurnPixelBlender<Rgba32>), PixelBlenderMode.Burn }, |
|||
{ new TestPixel<Rgba32>(), typeof(DefaultDifferencePixelBlender<Rgba32>), PixelBlenderMode.Difference }, |
|||
{ new TestPixel<Rgba32>(), typeof(DefaultExclusionPixelBlender<Rgba32>), PixelBlenderMode.Exclusion }, |
|||
|
|||
{ new TestPixel<RgbaVector>(), typeof(DefaultPremultipliedLerpPixelBlender<RgbaVector>), PixelBlenderMode.Default }, |
|||
{ new TestPixel<RgbaVector>(), typeof(DefaultNormalPixelBlender<RgbaVector>), PixelBlenderMode.Normal }, |
|||
{ new TestPixel<RgbaVector>(), typeof(DefaultScreenPixelBlender<RgbaVector>), PixelBlenderMode.Screen }, |
|||
{ new TestPixel<RgbaVector>(), typeof(DefaultHardLightPixelBlender<RgbaVector>), PixelBlenderMode.HardLight }, |
|||
{ new TestPixel<RgbaVector>(), typeof(DefaultOverlayPixelBlender<RgbaVector>), PixelBlenderMode.Overlay }, |
|||
{ new TestPixel<RgbaVector>(), typeof(DefaultDarkenPixelBlender<RgbaVector>), PixelBlenderMode.Darken }, |
|||
{ new TestPixel<RgbaVector>(), typeof(DefaultLightenPixelBlender<RgbaVector>), PixelBlenderMode.Lighten }, |
|||
{ new TestPixel<RgbaVector>(), typeof(DefaultSoftLightPixelBlender<RgbaVector>), PixelBlenderMode.SoftLight }, |
|||
{ new TestPixel<RgbaVector>(), typeof(DefaultDodgePixelBlender<RgbaVector>), PixelBlenderMode.Dodge }, |
|||
{ new TestPixel<RgbaVector>(), typeof(DefaultBurnPixelBlender<RgbaVector>), PixelBlenderMode.Burn }, |
|||
{ new TestPixel<RgbaVector>(), typeof(DefaultDifferencePixelBlender<RgbaVector>), PixelBlenderMode.Difference }, |
|||
{ new TestPixel<RgbaVector>(), typeof(DefaultExclusionPixelBlender<RgbaVector>), PixelBlenderMode.Exclusion } |
|||
}; |
|||
|
|||
[Theory] |
|||
[MemberData(nameof(blenderMappings))] |
|||
public void ReturnsCorrectBlender<TPixel>(TestPixel<TPixel> pixel, Type type, PixelBlenderMode mode) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
PixelBlender<TPixel> blender = PixelOperations<TPixel>.Instance.GetPixelBlender(mode); |
|||
Assert.IsType(type, blender); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,62 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Text; |
|||
using ImageSharp.PixelFormats; |
|||
using Xunit.Abstractions; |
|||
|
|||
namespace ImageSharp.Tests.TestUtilities |
|||
{ |
|||
public class TestPixel<TPixel> : IXunitSerializable |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
public TestPixel() |
|||
{ |
|||
} |
|||
|
|||
public TestPixel(float red, float green, float blue, float alpha) |
|||
{ |
|||
this.Red = red; |
|||
this.Green = green; |
|||
this.Blue = blue; |
|||
this.Alpha = alpha; |
|||
} |
|||
|
|||
public float Red { get; set; } |
|||
public float Green { get; set; } |
|||
public float Blue { get; set; } |
|||
public float Alpha { get; set; } |
|||
|
|||
public static implicit operator TPixel(TestPixel<TPixel> d) |
|||
{ |
|||
return d?.AsPixel() ?? default(TPixel); |
|||
} |
|||
|
|||
public TPixel AsPixel() |
|||
{ |
|||
TPixel pix = default(TPixel); |
|||
pix.PackFromVector4(new System.Numerics.Vector4( this.Red, this.Green, this.Blue, this.Alpha)); |
|||
return pix; |
|||
} |
|||
|
|||
public void Deserialize(IXunitSerializationInfo info) |
|||
{ |
|||
this.Red = info.GetValue<float>("red"); |
|||
this.Green = info.GetValue<float>("green"); |
|||
this.Blue = info.GetValue<float>("blue"); |
|||
this.Alpha = info.GetValue<float>("alpha"); |
|||
} |
|||
|
|||
public void Serialize(IXunitSerializationInfo info) |
|||
{ |
|||
info.AddValue("red", this.Red); |
|||
info.AddValue("green", this.Green); |
|||
info.AddValue("blue", this.Blue); |
|||
info.AddValue("alpha", this.Alpha); |
|||
} |
|||
|
|||
public override string ToString() |
|||
{ |
|||
return $"{typeof(TPixel).Name}{this.AsPixel().ToString()}"; |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue