mirror of https://github.com/SixLabors/ImageSharp
22 changed files with 358 additions and 1193 deletions
@ -1,254 +0,0 @@ |
|||
// <copyright file="Rgba32.Transforms.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; |
|||
|
|||
/// <content>
|
|||
/// Provides operators and composition algorithms.
|
|||
/// </content>
|
|||
public partial struct Rgba32 |
|||
{ |
|||
/// <summary>
|
|||
/// Adds the second color to the first.
|
|||
/// </summary>
|
|||
/// <param name="left">The first source color.</param>
|
|||
/// <param name="right">The second source color.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Rgba32"/>.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Rgba32 operator +(Rgba32 left, Rgba32 right) |
|||
{ |
|||
Vector4 add = left.ToVector4() + right.ToVector4(); |
|||
return PackNew(ref add); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Subtracts the second color from the first.
|
|||
/// </summary>
|
|||
/// <param name="left">The first source color.</param>
|
|||
/// <param name="right">The second source color.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Rgba32"/>.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Rgba32 operator -(Rgba32 left, Rgba32 right) |
|||
{ |
|||
Vector4 sub = left.ToVector4() - right.ToVector4(); |
|||
return PackNew(ref sub); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// The blending formula simply selects the source color.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop color.</param>
|
|||
/// <param name="source">The source color.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Rgba32"/>.
|
|||
/// </returns>
|
|||
public static Rgba32 Normal(Rgba32 backdrop, Rgba32 source) |
|||
{ |
|||
Vector4 normal = Vector4BlendTransforms.Normal(backdrop.ToVector4(), source.ToVector4()); |
|||
return PackNew(ref normal); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Blends two colors by multiplication.
|
|||
/// <remarks>
|
|||
/// The source color is multiplied by the destination color and replaces the destination.
|
|||
/// The resultant color is always at least as dark as either the source or destination color.
|
|||
/// Multiplying any color with black results in black. Multiplying any color with white preserves the
|
|||
/// original color.
|
|||
/// </remarks>
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop color.</param>
|
|||
/// <param name="source">The source color.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Rgba32"/>.
|
|||
/// </returns>
|
|||
public static Rgba32 Multiply(Rgba32 backdrop, Rgba32 source) |
|||
{ |
|||
Vector4 multiply = Vector4BlendTransforms.Multiply(backdrop.ToVector4(), source.ToVector4()); |
|||
return PackNew(ref multiply); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Multiplies the complements of the backdrop and source color values, then complements the result.
|
|||
/// <remarks>
|
|||
/// The result color is always at least as light as either of the two constituent colors. Screening any
|
|||
/// color with white produces white; screening with black leaves the original color unchanged.
|
|||
/// The effect is similar to projecting multiple photographic slides simultaneously onto a single screen.
|
|||
/// </remarks>
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop color.</param>
|
|||
/// <param name="source">The source color.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Rgba32"/>.
|
|||
/// </returns>
|
|||
public static Rgba32 Screen(Rgba32 backdrop, Rgba32 source) |
|||
{ |
|||
Vector4 subtract = Vector4BlendTransforms.Screen(backdrop.ToVector4(), source.ToVector4()); |
|||
return PackNew(ref subtract); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Multiplies or screens the colors, depending on the source color value. The effect is similar to
|
|||
/// shining a harsh spotlight on the backdrop.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop color.</param>
|
|||
/// <param name="source">The source color.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Rgba32"/>.
|
|||
/// </returns>
|
|||
public static Rgba32 HardLight(Rgba32 backdrop, Rgba32 source) |
|||
{ |
|||
Vector4 hardlight = Vector4BlendTransforms.HardLight(backdrop.ToVector4(), source.ToVector4()); |
|||
return PackNew(ref hardlight); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Multiplies or screens the colors, depending on the backdrop color value.
|
|||
/// <remarks>
|
|||
/// Source colors overlay the backdrop while preserving its highlights and shadows.
|
|||
/// The backdrop color is not replaced but is mixed with the source color to reflect the lightness or darkness
|
|||
/// of the backdrop.
|
|||
/// </remarks>
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop color.</param>
|
|||
/// <param name="source">The source color.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Rgba32"/>.
|
|||
/// </returns>
|
|||
public static Rgba32 Overlay(Rgba32 backdrop, Rgba32 source) |
|||
{ |
|||
Vector4 overlay = Vector4BlendTransforms.Overlay(backdrop.ToVector4(), source.ToVector4()); |
|||
return PackNew(ref overlay); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Selects the darker of the backdrop and source colors.
|
|||
/// The backdrop is replaced with the source where the source is darker; otherwise, it is left unchanged.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop color.</param>
|
|||
/// <param name="source">The source color.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Rgba32"/>.
|
|||
/// </returns>
|
|||
public static Rgba32 Darken(Rgba32 backdrop, Rgba32 source) |
|||
{ |
|||
Vector4 darken = Vector4BlendTransforms.Darken(backdrop.ToVector4(), source.ToVector4()); |
|||
return PackNew(ref darken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Selects the lighter of the backdrop and source colors.
|
|||
/// The backdrop is replaced with the source where the source is lighter; otherwise, it is left unchanged.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop color.</param>
|
|||
/// <param name="source">The source color.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Rgba32"/>.
|
|||
/// </returns>
|
|||
public static Rgba32 Lighten(Rgba32 backdrop, Rgba32 source) |
|||
{ |
|||
Vector4 lighten = Vector4BlendTransforms.Lighten(backdrop.ToVector4(), source.ToVector4()); |
|||
return PackNew(ref lighten); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Darkens or lightens the colors, depending on the source color value. The effect is similar to shining
|
|||
/// a diffused spotlight on the backdrop.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop color.</param>
|
|||
/// <param name="source">The source color.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Rgba32"/>.
|
|||
/// </returns>
|
|||
public static Rgba32 SoftLight(Rgba32 backdrop, Rgba32 source) |
|||
{ |
|||
Vector4 softlight = Vector4BlendTransforms.SoftLight(backdrop.ToVector4(), source.ToVector4()); |
|||
return PackNew(ref softlight); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Brightens the backdrop color to reflect the source color. Painting with black produces no changes.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop color.</param>
|
|||
/// <param name="source">The source color.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Rgba32"/>.
|
|||
/// </returns>
|
|||
public static Rgba32 ColorDodge(Rgba32 backdrop, Rgba32 source) |
|||
{ |
|||
Vector4 dodge = Vector4BlendTransforms.Dodge(backdrop.ToVector4(), source.ToVector4()); |
|||
return PackNew(ref dodge); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Darkens the backdrop color to reflect the source color. Painting with white produces no change.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop color.</param>
|
|||
/// <param name="source">The source color.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Rgba32"/>.
|
|||
/// </returns>
|
|||
public static Rgba32 ColorBurn(Rgba32 backdrop, Rgba32 source) |
|||
{ |
|||
Vector4 burn = Vector4BlendTransforms.Burn(backdrop.ToVector4(), source.ToVector4()); |
|||
return PackNew(ref burn); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Subtracts the darker of the two constituent colors from the lighter color.
|
|||
/// Painting with white inverts the backdrop color; painting with black produces no change.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop color.</param>
|
|||
/// <param name="source">The source color.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Rgba32"/>.
|
|||
/// </returns>
|
|||
public static Rgba32 Difference(Rgba32 backdrop, Rgba32 source) |
|||
{ |
|||
Vector4 difference = Vector4BlendTransforms.Difference(backdrop.ToVector4(), source.ToVector4()); |
|||
return PackNew(ref difference); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Produces an effect similar to that of the <see cref="Difference"/> mode but lower in contrast. Painting with white
|
|||
/// inverts the backdrop color; painting with black produces no change
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop color.</param>
|
|||
/// <param name="source">The source color.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Rgba32"/>.
|
|||
/// </returns>
|
|||
public static Rgba32 Exclusion(Rgba32 backdrop, Rgba32 source) |
|||
{ |
|||
Vector4 exclusion = Vector4BlendTransforms.Exclusion(backdrop.ToVector4(), source.ToVector4()); |
|||
return PackNew(ref exclusion); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Linearly interpolates from one color to another based on the given weighting.
|
|||
/// </summary>
|
|||
/// <param name="from">The first color value.</param>
|
|||
/// <param name="to">The second color value.</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 <see cref="Rgba32"/>
|
|||
/// </returns>
|
|||
public static Rgba32 Lerp(Rgba32 from, Rgba32 to, float amount) |
|||
{ |
|||
Vector4 lerp = Vector4.Lerp(from.ToVector4(), to.ToVector4(), amount); |
|||
return PackNew(ref lerp); |
|||
} |
|||
} |
|||
} |
|||
@ -1,251 +0,0 @@ |
|||
// <copyright file="RgbaVector.Transforms.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; |
|||
|
|||
/// <content>
|
|||
/// Provides operators and composition algorithms.
|
|||
/// </content>
|
|||
public partial struct RgbaVector |
|||
{ |
|||
/// <summary>
|
|||
/// Adds the second color to the first.
|
|||
/// </summary>
|
|||
/// <param name="left">The first source color.</param>
|
|||
/// <param name="right">The second source color.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="RgbaVector"/>.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static RgbaVector operator +(RgbaVector left, RgbaVector right) |
|||
{ |
|||
return new RgbaVector(left.backingVector + right.backingVector); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Subtracts the second color from the first.
|
|||
/// </summary>
|
|||
/// <param name="left">The first source color.</param>
|
|||
/// <param name="right">The second source color.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="RgbaVector"/>.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static RgbaVector operator -(RgbaVector left, RgbaVector right) |
|||
{ |
|||
return new RgbaVector(left.backingVector - right.backingVector); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// The blending formula simply selects the source color.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop color.</param>
|
|||
/// <param name="source">The source color.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="RgbaVector"/>.
|
|||
/// </returns>
|
|||
public static RgbaVector Normal(RgbaVector backdrop, RgbaVector source) |
|||
{ |
|||
Vector4 normal = Vector4BlendTransforms.Normal(backdrop.backingVector, source.backingVector); |
|||
return new RgbaVector(normal); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Blends two colors by multiplication.
|
|||
/// <remarks>
|
|||
/// The source color is multiplied by the destination color and replaces the destination.
|
|||
/// The resultant color is always at least as dark as either the source or destination color.
|
|||
/// Multiplying any color with black results in black. Multiplying any color with white preserves the
|
|||
/// original color.
|
|||
/// </remarks>
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop color.</param>
|
|||
/// <param name="source">The source color.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="RgbaVector"/>.
|
|||
/// </returns>
|
|||
public static RgbaVector Multiply(RgbaVector backdrop, RgbaVector source) |
|||
{ |
|||
Vector4 multiply = Vector4BlendTransforms.Multiply(backdrop.backingVector, source.backingVector); |
|||
return new RgbaVector(multiply); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Multiplies the complements of the backdrop and source color values, then complements the result.
|
|||
/// <remarks>
|
|||
/// The result color is always at least as light as either of the two constituent colors. Screening any
|
|||
/// color with white produces white; screening with black leaves the original color unchanged.
|
|||
/// The effect is similar to projecting multiple photographic slides simultaneously onto a single screen.
|
|||
/// </remarks>
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop color.</param>
|
|||
/// <param name="source">The source color.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="RgbaVector"/>.
|
|||
/// </returns>
|
|||
public static RgbaVector Screen(RgbaVector backdrop, RgbaVector source) |
|||
{ |
|||
Vector4 subtract = Vector4BlendTransforms.Screen(backdrop.backingVector, source.backingVector); |
|||
return new RgbaVector(subtract); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Multiplies or screens the colors, depending on the source color value. The effect is similar to
|
|||
/// shining a harsh spotlight on the backdrop.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop color.</param>
|
|||
/// <param name="source">The source color.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="RgbaVector"/>.
|
|||
/// </returns>
|
|||
public static RgbaVector HardLight(RgbaVector backdrop, RgbaVector source) |
|||
{ |
|||
Vector4 hardlight = Vector4BlendTransforms.HardLight(backdrop.backingVector, source.backingVector); |
|||
return new RgbaVector(hardlight); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Multiplies or screens the colors, depending on the backdrop color value.
|
|||
/// <remarks>
|
|||
/// Source colors overlay the backdrop while preserving its highlights and shadows.
|
|||
/// The backdrop color is not replaced but is mixed with the source color to reflect the lightness or darkness
|
|||
/// of the backdrop.
|
|||
/// </remarks>
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop color.</param>
|
|||
/// <param name="source">The source color.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="RgbaVector"/>.
|
|||
/// </returns>
|
|||
public static RgbaVector Overlay(RgbaVector backdrop, RgbaVector source) |
|||
{ |
|||
Vector4 overlay = Vector4BlendTransforms.Overlay(backdrop.backingVector, source.backingVector); |
|||
return new RgbaVector(overlay); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Selects the darker of the backdrop and source colors.
|
|||
/// The backdrop is replaced with the source where the source is darker; otherwise, it is left unchanged.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop color.</param>
|
|||
/// <param name="source">The source color.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="RgbaVector"/>.
|
|||
/// </returns>
|
|||
public static RgbaVector Darken(RgbaVector backdrop, RgbaVector source) |
|||
{ |
|||
Vector4 darken = Vector4BlendTransforms.Darken(backdrop.backingVector, source.backingVector); |
|||
return new RgbaVector(darken); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Selects the lighter of the backdrop and source colors.
|
|||
/// The backdrop is replaced with the source where the source is lighter; otherwise, it is left unchanged.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop color.</param>
|
|||
/// <param name="source">The source color.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="RgbaVector"/>.
|
|||
/// </returns>
|
|||
public static RgbaVector Lighten(RgbaVector backdrop, RgbaVector source) |
|||
{ |
|||
Vector4 lighten = Vector4BlendTransforms.Lighten(backdrop.backingVector, source.backingVector); |
|||
return new RgbaVector(lighten); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Darkens or lightens the colors, depending on the source color value. The effect is similar to shining
|
|||
/// a diffused spotlight on the backdrop.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop color.</param>
|
|||
/// <param name="source">The source color.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="RgbaVector"/>.
|
|||
/// </returns>
|
|||
public static RgbaVector SoftLight(RgbaVector backdrop, RgbaVector source) |
|||
{ |
|||
Vector4 softlight = Vector4BlendTransforms.SoftLight(backdrop.backingVector, source.backingVector); |
|||
return new RgbaVector(softlight); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Brightens the backdrop color to reflect the source color. Painting with black produces no changes.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop color.</param>
|
|||
/// <param name="source">The source color.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="RgbaVector"/>.
|
|||
/// </returns>
|
|||
public static RgbaVector ColorDodge(RgbaVector backdrop, RgbaVector source) |
|||
{ |
|||
Vector4 dodge = Vector4BlendTransforms.Dodge(backdrop.backingVector, source.backingVector); |
|||
return new RgbaVector(dodge); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Darkens the backdrop color to reflect the source color. Painting with white produces no change.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop color.</param>
|
|||
/// <param name="source">The source color.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="RgbaVector"/>.
|
|||
/// </returns>
|
|||
public static RgbaVector ColorBurn(RgbaVector backdrop, RgbaVector source) |
|||
{ |
|||
Vector4 burn = Vector4BlendTransforms.Burn(backdrop.backingVector, source.backingVector); |
|||
return new RgbaVector(burn); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Subtracts the darker of the two constituent colors from the lighter color.
|
|||
/// Painting with white inverts the backdrop color; painting with black produces no change.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop color.</param>
|
|||
/// <param name="source">The source color.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="RgbaVector"/>.
|
|||
/// </returns>
|
|||
public static RgbaVector Difference(RgbaVector backdrop, RgbaVector source) |
|||
{ |
|||
Vector4 difference = Vector4BlendTransforms.Difference(backdrop.backingVector, source.backingVector); |
|||
return new RgbaVector(difference); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Produces an effect similar to that of the <see cref="Difference"/> mode but lower in contrast. Painting with white
|
|||
/// inverts the backdrop color; painting with black produces no change
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop color.</param>
|
|||
/// <param name="source">The source color.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="RgbaVector"/>.
|
|||
/// </returns>
|
|||
public static RgbaVector Exclusion(RgbaVector backdrop, RgbaVector source) |
|||
{ |
|||
Vector4 exclusion = Vector4BlendTransforms.Exclusion(backdrop.backingVector, source.backingVector); |
|||
return new RgbaVector(exclusion); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Linearly interpolates from one color to another based on the given weighting.
|
|||
/// </summary>
|
|||
/// <param name="from">The first color value.</param>
|
|||
/// <param name="to">The second color value.</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 <see cref="RgbaVector"/>
|
|||
/// </returns>
|
|||
public static RgbaVector Lerp(RgbaVector from, RgbaVector to, float amount) |
|||
{ |
|||
return new RgbaVector(Vector4.Lerp(from.backingVector, to.backingVector, amount)); |
|||
} |
|||
} |
|||
} |
|||
@ -1,292 +0,0 @@ |
|||
// <copyright file="Vector4BlendTransforms.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; |
|||
|
|||
/// <summary>
|
|||
/// Transform algorithms that match the equations defined in the W3C Compositing and Blending Level 1 specification.
|
|||
/// <see href="https://www.w3.org/TR/compositing-1/"/>
|
|||
/// </summary>
|
|||
internal class Vector4BlendTransforms |
|||
{ |
|||
/// <summary>
|
|||
/// The blending formula simply selects the source vector.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop vector.</param>
|
|||
/// <param name="source">The source vector.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Vector4"/>.
|
|||
/// </returns>
|
|||
public static Vector4 Normal(Vector4 backdrop, Vector4 source) |
|||
{ |
|||
return new Vector4(source.X, source.Y, source.Z, source.W); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Blends two vectors by multiplication.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop vector.</param>
|
|||
/// <param name="source">The source vector.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Vector4"/>.
|
|||
/// </returns>
|
|||
public static Vector4 Multiply(Vector4 backdrop, Vector4 source) |
|||
{ |
|||
Vector4 multiply = backdrop * source; |
|||
multiply.W = backdrop.W; |
|||
return multiply; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Multiplies the complements of the backdrop and source vector values, then complements the result.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop vector.</param>
|
|||
/// <param name="source">The source vector.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Vector4"/>.
|
|||
/// </returns>
|
|||
public static Vector4 Screen(Vector4 backdrop, Vector4 source) |
|||
{ |
|||
Vector4 subtract = backdrop + source - (backdrop * source); |
|||
subtract.W = backdrop.W; |
|||
return subtract; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Multiplies or screens the colors, depending on the source vector value.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop vector.</param>
|
|||
/// <param name="source">The source vector.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Vector4"/>.
|
|||
/// </returns>
|
|||
public static Vector4 HardLight(Vector4 backdrop, Vector4 source) |
|||
{ |
|||
return new Vector4(BlendOverlay(source.X, backdrop.X), BlendOverlay(source.Y, backdrop.Y), BlendOverlay(source.Z, backdrop.Z), backdrop.W); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Multiplies or screens the vectors, depending on the backdrop vector value.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop vector.</param>
|
|||
/// <param name="source">The source vector.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Vector4"/>.
|
|||
/// </returns>
|
|||
public static Vector4 Overlay(Vector4 backdrop, Vector4 source) |
|||
{ |
|||
return new Vector4(BlendOverlay(backdrop.X, source.X), BlendOverlay(backdrop.Y, source.Y), BlendOverlay(backdrop.Z, source.Z), backdrop.W); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Selects the minimum of the backdrop and source vectors.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop vector.</param>
|
|||
/// <param name="source">The source vector.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Vector4"/>.
|
|||
/// </returns>
|
|||
public static Vector4 Darken(Vector4 backdrop, Vector4 source) |
|||
{ |
|||
Vector4 result = Vector4.Min(backdrop, source); |
|||
result.W = backdrop.W; |
|||
return result; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Selects the max of the backdrop and source vector.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop vector.</param>
|
|||
/// <param name="source">The source vector.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Vector4"/>.
|
|||
/// </returns>
|
|||
public static Vector4 Lighten(Vector4 backdrop, Vector4 source) |
|||
{ |
|||
Vector4 result = Vector4.Max(backdrop, source); |
|||
result.W = backdrop.W; |
|||
return result; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Selects the maximum or minimum of the vectors, depending on the source vector value.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop vector.</param>
|
|||
/// <param name="source">The source vector.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Vector4"/>.
|
|||
/// </returns>
|
|||
public static Vector4 SoftLight(Vector4 backdrop, Vector4 source) |
|||
{ |
|||
return new Vector4(BlendSoftLight(backdrop.X, source.X), BlendSoftLight(backdrop.Y, source.Y), BlendSoftLight(backdrop.Z, source.Z), backdrop.W); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Increases the backdrop vector to reflect the source vector.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop vector.</param>
|
|||
/// <param name="source">The source vector.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Vector4"/>.
|
|||
/// </returns>
|
|||
public static Vector4 Dodge(Vector4 backdrop, Vector4 source) |
|||
{ |
|||
return new Vector4(BlendDodge(backdrop.X, source.X), BlendDodge(backdrop.Y, source.Y), BlendDodge(backdrop.Z, source.Z), backdrop.W); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Decreases the backdrop vector to reflect the source vector.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop vector.</param>
|
|||
/// <param name="source">The source vector.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Vector4"/>.
|
|||
/// </returns>
|
|||
public static Vector4 Burn(Vector4 backdrop, Vector4 source) |
|||
{ |
|||
return new Vector4(BlendBurn(backdrop.X, source.X), BlendBurn(backdrop.Y, source.Y), BlendBurn(backdrop.Z, source.Z), backdrop.W); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Subtracts the minimum of the two constituent vectors from the maximum vector.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop vector.</param>
|
|||
/// <param name="source">The source vector.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Vector4"/>.
|
|||
/// </returns>
|
|||
public static Vector4 Difference(Vector4 backdrop, Vector4 source) |
|||
{ |
|||
Vector4 result = Vector4.Abs(backdrop - source); |
|||
result.W = backdrop.W; |
|||
return result; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Produces an effect similar to that of the <see cref="Difference"/> mode but lower in magnitude.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop vector.</param>
|
|||
/// <param name="source">The source vector.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Vector4"/>.
|
|||
/// </returns>
|
|||
public static Vector4 Exclusion(Vector4 backdrop, Vector4 source) |
|||
{ |
|||
return new Vector4(BlendExclusion(backdrop.X, source.X), BlendExclusion(backdrop.Y, source.Y), BlendExclusion(backdrop.Z, source.Z), backdrop.W); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Linearly interpolates from one vector to another based on the given weighting.
|
|||
/// The two vectors are premultiplied before operating.
|
|||
/// </summary>
|
|||
/// <param name="backdrop">The backdrop vector.</param>
|
|||
/// <param name="source">The source vector.</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 <see cref="Vector4"/>
|
|||
/// </returns>
|
|||
public static Vector4 PremultipliedLerp(Vector4 backdrop, Vector4 source, float amount) |
|||
{ |
|||
amount = amount.Clamp(0, 1); |
|||
|
|||
// Santize on zero alpha
|
|||
if (MathF.Abs(backdrop.W) < Constants.Epsilon) |
|||
{ |
|||
source.W *= amount; |
|||
return source; |
|||
} |
|||
|
|||
if (MathF.Abs(source.W) < Constants.Epsilon) |
|||
{ |
|||
return backdrop; |
|||
} |
|||
|
|||
// Premultiply the source vector.
|
|||
// Oddly premultiplying the background vector creates dark outlines when pixels
|
|||
// Have low alpha values.
|
|||
source = new Vector4(source.X, source.Y, source.Z, 1) * (source.W * amount); |
|||
|
|||
// This should be implementing the following formula
|
|||
// https://en.wikipedia.org/wiki/Alpha_compositing
|
|||
// Vout = Vs + Vb (1 - Vsa)
|
|||
// Aout = Vsa + Vsb (1 - Vsa)
|
|||
Vector3 inverseW = new Vector3(1 - source.W); |
|||
Vector3 xyzB = new Vector3(backdrop.X, backdrop.Y, backdrop.Z); |
|||
Vector3 xyzS = new Vector3(source.X, source.Y, source.Z); |
|||
|
|||
return new Vector4(xyzS + (xyzB * inverseW), source.W + (backdrop.W * (1 - source.W))); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Multiplies or screens the backdrop component, depending on the component value.
|
|||
/// </summary>
|
|||
/// <param name="b">The backdrop component.</param>
|
|||
/// <param name="s">The source component.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="float"/>.
|
|||
/// </returns>
|
|||
private static float BlendOverlay(float b, float s) |
|||
{ |
|||
return b <= .5F ? (2F * b * s) : (1F - (2F * (1F - b) * (1F - s))); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Darkens or lightens the backdrop component, depending on the source component value.
|
|||
/// </summary>
|
|||
/// <param name="b">The backdrop component.</param>
|
|||
/// <param name="s">The source component.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="float"/>.
|
|||
/// </returns>
|
|||
private static float BlendSoftLight(float b, float s) |
|||
{ |
|||
return s <= .5F ? ((2F * b * s) + (b * b * (1F - (2F * s)))) : (MathF.Sqrt(b) * ((2F * s) - 1F)) + (2F * b * (1F - s)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Brightens the backdrop component to reflect the source component.
|
|||
/// </summary>
|
|||
/// <param name="b">The backdrop component.</param>
|
|||
/// <param name="s">The source component.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="float"/>.
|
|||
/// </returns>
|
|||
private static float BlendDodge(float b, float s) |
|||
{ |
|||
return MathF.Abs(s - 1F) < Constants.Epsilon ? s : MathF.Min(b / (1F - s), 1F); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Darkens the backdrop component to reflect the source component.
|
|||
/// </summary>
|
|||
/// <param name="b">The backdrop component.</param>
|
|||
/// <param name="s">The source component.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="float"/>.
|
|||
/// </returns>
|
|||
private static float BlendBurn(float b, float s) |
|||
{ |
|||
return MathF.Abs(s) < Constants.Epsilon ? s : MathF.Max(1F - ((1F - b) / s), 0F); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Darkens the backdrop component to reflect the source component.
|
|||
/// </summary>
|
|||
/// <param name="b">The backdrop component.</param>
|
|||
/// <param name="s">The source component.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="float"/>.
|
|||
/// </returns>
|
|||
private static float BlendExclusion(float b, float s) |
|||
{ |
|||
return b + s - (2F * b * s); |
|||
} |
|||
} |
|||
} |
|||
@ -1,118 +0,0 @@ |
|||
// <copyright file="ColorTransformTests.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.Tests.Colors |
|||
{ |
|||
using ImageSharp.PixelFormats; |
|||
|
|||
using Xunit; |
|||
|
|||
/// <summary>
|
|||
/// Tests the color transform algorithms. Test results match the output of CSS equivalents.
|
|||
/// <see href="https://jsfiddle.net/jamessouth/L1v8r6kh/"/>
|
|||
/// </summary>
|
|||
public class ColorTransformTests |
|||
{ |
|||
/// <summary>
|
|||
/// Orange backdrop
|
|||
/// </summary>
|
|||
private static readonly Rgba32 Backdrop = new Rgba32(204, 102, 0); |
|||
|
|||
/// <summary>
|
|||
/// Blue source
|
|||
/// </summary>
|
|||
private static readonly Rgba32 Source = new Rgba32(0, 102, 153); |
|||
|
|||
[Fact] |
|||
public void Normal() |
|||
{ |
|||
Rgba32 normal = Rgba32.Normal(Backdrop, Source); |
|||
Assert.True(normal == Source); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Multiply() |
|||
{ |
|||
Assert.True(Rgba32.Multiply(Backdrop, Rgba32.Black) == Rgba32.Black); |
|||
Assert.True(Rgba32.Multiply(Backdrop, Rgba32.White) == Backdrop); |
|||
|
|||
Rgba32 multiply = Rgba32.Multiply(Backdrop, Source); |
|||
Assert.True(multiply == new Rgba32(0, 41, 0)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Screen() |
|||
{ |
|||
Assert.True(Rgba32.Screen(Backdrop, Rgba32.Black) == Backdrop); |
|||
Assert.True(Rgba32.Screen(Backdrop, Rgba32.White) == Rgba32.White); |
|||
|
|||
Rgba32 screen = Rgba32.Screen(Backdrop, Source); |
|||
Assert.True(screen == new Rgba32(204, 163, 153)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void HardLight() |
|||
{ |
|||
Rgba32 hardLight = Rgba32.HardLight(Backdrop, Source); |
|||
Assert.True(hardLight == new Rgba32(0, 82, 51)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Overlay() |
|||
{ |
|||
Rgba32 overlay = Rgba32.Overlay(Backdrop, Source); |
|||
Assert.True(overlay == new Rgba32(153, 82, 0)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Darken() |
|||
{ |
|||
Rgba32 darken = Rgba32.Darken(Backdrop, Source); |
|||
Assert.True(darken == new Rgba32(0, 102, 0)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Lighten() |
|||
{ |
|||
Rgba32 lighten = Rgba32.Lighten(Backdrop, Source); |
|||
Assert.True(lighten == new Rgba32(204, 102, 153)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void SoftLight() |
|||
{ |
|||
Rgba32 softLight = Rgba32.SoftLight(Backdrop, Source); |
|||
Assert.True(softLight == new Rgba32(163, 90, 0)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ColorDodge() |
|||
{ |
|||
Rgba32 colorDodge = Rgba32.ColorDodge(Backdrop, Source); |
|||
Assert.True(colorDodge == new Rgba32(204, 170, 0)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ColorBurn() |
|||
{ |
|||
Rgba32 colorBurn = Rgba32.ColorBurn(Backdrop, Source); |
|||
Assert.True(colorBurn == new Rgba32(0, 0, 0)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Difference() |
|||
{ |
|||
Rgba32 difference = Rgba32.Difference(Backdrop, Source); |
|||
Assert.True(difference == new Rgba32(204, 0, 153)); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Exclusion() |
|||
{ |
|||
Rgba32 exclusion = Rgba32.Exclusion(Backdrop, Source); |
|||
Assert.True(exclusion == new Rgba32(204, 122, 153)); |
|||
} |
|||
} |
|||
} |
|||
@ -1,120 +0,0 @@ |
|||
// <copyright file="RgbaVectorTransformTests.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.Tests.Colors |
|||
{ |
|||
using ImageSharp.PixelFormats; |
|||
using Xunit; |
|||
|
|||
/// <summary>
|
|||
/// Tests the color transform algorithms. Test results match the output of CSS equivalents.
|
|||
/// <see href="https://jsfiddle.net/jamessouth/L1v8r6kh/"/>
|
|||
/// </summary>
|
|||
public class RgbaVectorTransformTests |
|||
{ |
|||
private static readonly ApproximateFloatComparer FloatComparer = new ApproximateFloatComparer(0.01F); |
|||
|
|||
/// <summary>
|
|||
/// Orange backdrop
|
|||
/// </summary>
|
|||
private static readonly RgbaVector Backdrop = new RgbaVector(204, 102, 0); |
|||
|
|||
/// <summary>
|
|||
/// Blue source
|
|||
/// </summary>
|
|||
private static readonly RgbaVector Source = new RgbaVector(0, 102, 153); |
|||
|
|||
[Fact] |
|||
public void Normal() |
|||
{ |
|||
RgbaVector normal = RgbaVector.Normal(Backdrop, Source); |
|||
Assert.True(normal == Source); |
|||
} |
|||
|
|||
// TODO: These tests keep sporadically breaking our builds. Fins out why they work locally but not on the CI.
|
|||
// [Fact]
|
|||
// public void Multiply()
|
|||
// {
|
|||
// Assert.Equal(RgbaVector.Multiply(Backdrop, RgbaVector.Black).ToVector4(), RgbaVector.Black.ToVector4(), FloatComparer);
|
|||
// Assert.Equal(RgbaVector.Multiply(Backdrop, RgbaVector.White).ToVector4(), Backdrop.ToVector4(), FloatComparer);
|
|||
|
|||
// RgbaVector multiply = RgbaVector.Multiply(Backdrop, Source);
|
|||
// Assert.Equal(multiply.ToVector4(), new RgbaVector(0, 41, 0).ToVector4(), FloatComparer);
|
|||
// }
|
|||
|
|||
// [Fact]
|
|||
// public void Screen()
|
|||
// {
|
|||
// Assert.Equal(RgbaVector.Screen(Backdrop, RgbaVector.Black).ToVector4(), Backdrop.ToVector4(), FloatComparer);
|
|||
// Assert.Equal(RgbaVector.Screen(Backdrop, RgbaVector.White).ToVector4(), RgbaVector.White.ToVector4(), FloatComparer);
|
|||
|
|||
// RgbaVector screen = RgbaVector.Screen(Backdrop, Source);
|
|||
// Assert.Equal(screen.ToVector4(), new RgbaVector(204, 163, 153).ToVector4(), FloatComparer);
|
|||
// }
|
|||
|
|||
[Fact] |
|||
public void HardLight() |
|||
{ |
|||
RgbaVector hardLight = RgbaVector.HardLight(Backdrop, Source); |
|||
Assert.Equal(hardLight.ToVector4(), new RgbaVector(0, 82, 51).ToVector4(), FloatComparer); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Overlay() |
|||
{ |
|||
RgbaVector overlay = RgbaVector.Overlay(Backdrop, Source); |
|||
Assert.Equal(overlay.ToVector4(), new RgbaVector(153, 82, 0).ToVector4(), FloatComparer); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Darken() |
|||
{ |
|||
RgbaVector darken = RgbaVector.Darken(Backdrop, Source); |
|||
Assert.Equal(darken.ToVector4(), new RgbaVector(0, 102, 0).ToVector4(), FloatComparer); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Lighten() |
|||
{ |
|||
RgbaVector lighten = RgbaVector.Lighten(Backdrop, Source); |
|||
Assert.Equal(lighten.ToVector4(), new RgbaVector(204, 102, 153).ToVector4(), FloatComparer); |
|||
} |
|||
|
|||
[Fact] |
|||
public void SoftLight() |
|||
{ |
|||
RgbaVector softLight = RgbaVector.SoftLight(Backdrop, Source); |
|||
Assert.Equal(softLight.ToVector4(), new RgbaVector(163, 90, 0).ToVector4(), FloatComparer); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ColorDodge() |
|||
{ |
|||
RgbaVector colorDodge = RgbaVector.ColorDodge(Backdrop, Source); |
|||
Assert.Equal(colorDodge.ToVector4(), new RgbaVector(204, 170, 0).ToVector4(), FloatComparer); |
|||
} |
|||
|
|||
[Fact] |
|||
public void ColorBurn() |
|||
{ |
|||
RgbaVector colorBurn = RgbaVector.ColorBurn(Backdrop, Source); |
|||
Assert.Equal(colorBurn.ToVector4(), new RgbaVector(0, 0, 0).ToVector4(), FloatComparer); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Difference() |
|||
{ |
|||
RgbaVector difference = RgbaVector.Difference(Backdrop, Source); |
|||
Assert.Equal(difference.ToVector4(), new RgbaVector(204, 0, 153).ToVector4(), FloatComparer); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Exclusion() |
|||
{ |
|||
RgbaVector exclusion = RgbaVector.Exclusion(Backdrop, Source); |
|||
Assert.Equal(exclusion.ToVector4(), new RgbaVector(204, 122, 153).ToVector4(), FloatComparer); |
|||
} |
|||
} |
|||
} |
|||
@ -1,46 +0,0 @@ |
|||
// <copyright file="DrawImageEffectTest.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.Tests |
|||
{ |
|||
using System.IO; |
|||
using ImageSharp.Drawing; |
|||
using ImageSharp.PixelFormats; |
|||
using Xunit; |
|||
|
|||
public class DrawImageEffectTest : FileTestBase |
|||
{ |
|||
[Fact] |
|||
public void ImageShouldApplyDrawImageFilter() |
|||
{ |
|||
string path = this.CreateOutputDirectory("Drawing", "DrawImageEffect"); |
|||
|
|||
PixelBlenderMode[] modes = (PixelBlenderMode[])System.Enum.GetValues(typeof(PixelBlenderMode)); |
|||
|
|||
using (Image blend = TestFile.Create(TestImages.Png.Blur).CreateImage()) |
|||
{ |
|||
foreach (TestFile file in Files) |
|||
{ |
|||
using (Image image = file.CreateImage()) |
|||
{ |
|||
foreach (PixelBlenderMode mode in modes) |
|||
{ |
|||
using (FileStream output = File.OpenWrite($"{path}/{mode}.{file.FileName}")) |
|||
{ |
|||
Size size = new Size(image.Width / 2, image.Height / 2); |
|||
Point loc = new Point(image.Width / 4, image.Height / 4); |
|||
|
|||
image.DrawImage(blend, size, loc, new GraphicsOptions() { |
|||
BlenderMode = mode, |
|||
BlendPercentage = .75f |
|||
}).Save(output); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue