mirror of https://github.com/SixLabors/ImageSharp
29 changed files with 539 additions and 469 deletions
@ -0,0 +1,89 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Companding |
|||
{ |
|||
/// <summary>
|
|||
/// Implements sRGB companding
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// For more info see:
|
|||
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html"/>
|
|||
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_RGB.html"/>
|
|||
/// </remarks>
|
|||
public static class SRgbCompanding |
|||
{ |
|||
/// <summary>
|
|||
/// Expands the companded vectors to their linear equivalents with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="vectors">The span of vectors.</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static void Expand(Span<Vector4> vectors) |
|||
{ |
|||
ref Vector4 baseRef = ref MemoryMarshal.GetReference(vectors); |
|||
|
|||
for (int i = 0; i < vectors.Length; i++) |
|||
{ |
|||
ref Vector4 v = ref Unsafe.Add(ref baseRef, i); |
|||
v.X = Expand(v.X); |
|||
v.Y = Expand(v.Y); |
|||
v.Z = Expand(v.Z); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compresses the uncompanded vectors to their nonlinear equivalents with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="vectors">The span of vectors.</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static void Compress(Span<Vector4> vectors) |
|||
{ |
|||
ref Vector4 baseRef = ref MemoryMarshal.GetReference(vectors); |
|||
|
|||
for (int i = 0; i < vectors.Length; i++) |
|||
{ |
|||
ref Vector4 v = ref Unsafe.Add(ref baseRef, i); |
|||
v.X = Compress(v.X); |
|||
v.Y = Compress(v.Y); |
|||
v.Z = Compress(v.Z); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Expands a companded vector to its linear equivalent with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector.</param>
|
|||
/// <returns>The <see cref="Vector4"/> representing the linear channel values.</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static Vector4 Expand(Vector4 vector) => new Vector4(Expand(vector.X), Expand(vector.Y), Expand(vector.Z), vector.W); |
|||
|
|||
/// <summary>
|
|||
/// Compresses an uncompanded vector (linear) to its nonlinear equivalent.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector.</param>
|
|||
/// <returns>The <see cref="Vector4"/> representing the nonlinear channel values.</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static Vector4 Compress(Vector4 vector) => new Vector4(Compress(vector.X), Compress(vector.Y), Compress(vector.Z), vector.W); |
|||
|
|||
/// <summary>
|
|||
/// Expands a companded channel to its linear equivalent with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="channel">The channel value.</param>
|
|||
/// <returns>The <see cref="float"/> representing the linear channel value.</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static float Expand(float channel) => channel <= 0.04045F ? channel / 12.92F : MathF.Pow((channel + 0.055F) / 1.055F, 2.4F); |
|||
|
|||
/// <summary>
|
|||
/// Compresses an uncompanded channel (linear) to its nonlinear equivalent.
|
|||
/// </summary>
|
|||
/// <param name="channel">The channel value.</param>
|
|||
/// <returns>The <see cref="float"/> representing the nonlinear channel value.</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static float Compress(float channel) => channel <= 0.0031308F ? 12.92F * channel : (1.055F * MathF.Pow(channel, 0.416666666666667F)) - 0.055F; |
|||
} |
|||
} |
|||
@ -1,35 +0,0 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation |
|||
{ |
|||
/// <summary>
|
|||
/// Implements sRGB companding
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// For more info see:
|
|||
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html"/>
|
|||
/// <see href="http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_RGB.html"/>
|
|||
/// </remarks>
|
|||
public static class SRgbCompanding |
|||
{ |
|||
/// <summary>
|
|||
/// Expands a companded channel to its linear equivalent with respect to the energy.
|
|||
/// </summary>
|
|||
/// <param name="channel">The channel value</param>
|
|||
/// <returns>The <see cref="float"/> representing the linear channel value.</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static float Expand(float channel) => channel <= 0.04045F ? channel / 12.92F : MathF.Pow((channel + 0.055F) / 1.055F, 2.4F); |
|||
|
|||
/// <summary>
|
|||
/// Compresses an uncompanded channel (linear) to its nonlinear equivalent.
|
|||
/// </summary>
|
|||
/// <param name="channel">The channel value</param>
|
|||
/// <returns>The <see cref="float"/> representing the nonlinear channel value.</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static float Compress(float channel) => channel <= 0.0031308F ? 12.92F * channel : (1.055F * MathF.Pow(channel, 0.416666666666667F)) - 0.055F; |
|||
} |
|||
} |
|||
@ -1,156 +0,0 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
|
|||
namespace SixLabors.ImageSharp |
|||
{ |
|||
/// <summary>
|
|||
/// Extension methods for the <see cref="Vector4"/> struct.
|
|||
/// </summary>
|
|||
internal static class Vector4Extensions |
|||
{ |
|||
/// <summary>
|
|||
/// Pre-multiplies the "x", "y", "z" components of a vector by its "w" component leaving the "w" component intact.
|
|||
/// </summary>
|
|||
/// <param name="source">The <see cref="Vector4"/> to premultiply</param>
|
|||
/// <returns>The <see cref="Vector4"/></returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static Vector4 Premultiply(this Vector4 source) |
|||
{ |
|||
float w = source.W; |
|||
Vector4 premultiplied = source * w; |
|||
premultiplied.W = w; |
|||
return premultiplied; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Reverses the result of premultiplying a vector via <see cref="Premultiply(Vector4)"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The <see cref="Vector4"/> to premultiply</param>
|
|||
/// <returns>The <see cref="Vector4"/></returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static Vector4 UnPremultiply(this Vector4 source) |
|||
{ |
|||
float w = source.W; |
|||
Vector4 unpremultiplied = source / w; |
|||
unpremultiplied.W = w; |
|||
return unpremultiplied; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Bulk variant of <see cref="Premultiply(System.Numerics.Vector4)"/>
|
|||
/// </summary>
|
|||
/// <param name="vectors">The span of vectors</param>
|
|||
public static void Premultiply(Span<Vector4> vectors) |
|||
{ |
|||
// TODO: This method can be AVX2 optimized using Vector<float>
|
|||
ref Vector4 baseRef = ref MemoryMarshal.GetReference(vectors); |
|||
|
|||
for (int i = 0; i < vectors.Length; i++) |
|||
{ |
|||
ref Vector4 v = ref Unsafe.Add(ref baseRef, i); |
|||
var s = new Vector4(v.W) |
|||
{ |
|||
W = 1 |
|||
}; |
|||
v *= s; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Bulk variant of <see cref="UnPremultiply(System.Numerics.Vector4)"/>
|
|||
/// </summary>
|
|||
/// <param name="vectors">The span of vectors</param>
|
|||
public static void UnPremultiply(Span<Vector4> vectors) |
|||
{ |
|||
// TODO: This method can be AVX2 optimized using Vector<float>
|
|||
ref Vector4 baseRef = ref MemoryMarshal.GetReference(vectors); |
|||
|
|||
for (int i = 0; i < vectors.Length; i++) |
|||
{ |
|||
ref Vector4 v = ref Unsafe.Add(ref baseRef, i); |
|||
var s = new Vector4(1 / v.W) |
|||
{ |
|||
W = 1 |
|||
}; |
|||
v *= s; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Compresses a linear color signal to its sRGB equivalent.
|
|||
/// <see href="http://www.4p8.com/eric.brasseur/gamma.html#formulas"/>
|
|||
/// <see href="http://entropymine.com/imageworsener/srgbformula/"/>
|
|||
/// </summary>
|
|||
/// <param name="linear">The <see cref="Vector4"/> whose signal to compress.</param>
|
|||
/// <returns>The <see cref="Vector4"/>.</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static Vector4 Compress(this Vector4 linear) |
|||
{ |
|||
// TODO: Is there a faster way to do this?
|
|||
return new Vector4( |
|||
SRgbCompanding.Compress(linear.X), |
|||
SRgbCompanding.Compress(linear.Y), |
|||
SRgbCompanding.Compress(linear.Z), |
|||
linear.W); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Expands an sRGB color signal to its linear equivalent.
|
|||
/// <see href="http://www.4p8.com/eric.brasseur/gamma.html#formulas"/>
|
|||
/// <see href="http://entropymine.com/imageworsener/srgbformula/"/>
|
|||
/// </summary>
|
|||
/// <param name="gamma">The <see cref="Rgba32"/> whose signal to expand.</param>
|
|||
/// <returns>The <see cref="Vector4"/>.</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static Vector4 Expand(this Vector4 gamma) |
|||
{ |
|||
// TODO: Is there a faster way to do this?
|
|||
return new Vector4( |
|||
SRgbCompanding.Expand(gamma.X), |
|||
SRgbCompanding.Expand(gamma.Y), |
|||
SRgbCompanding.Expand(gamma.Z), |
|||
gamma.W); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Bulk variant of <see cref="Compress(System.Numerics.Vector4)"/>
|
|||
/// </summary>
|
|||
/// <param name="vectors">The span of vectors</param>
|
|||
public static void Compress(Span<Vector4> vectors) |
|||
{ |
|||
ref Vector4 baseRef = ref MemoryMarshal.GetReference(vectors); |
|||
|
|||
for (int i = 0; i < vectors.Length; i++) |
|||
{ |
|||
ref Vector4 v = ref Unsafe.Add(ref baseRef, i); |
|||
v.X = SRgbCompanding.Compress(v.X); |
|||
v.Y = SRgbCompanding.Compress(v.Y); |
|||
v.Z = SRgbCompanding.Compress(v.Z); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Bulk variant of <see cref="Expand(System.Numerics.Vector4)"/>
|
|||
/// </summary>
|
|||
/// <param name="vectors">The span of vectors</param>
|
|||
public static void Expand(Span<Vector4> vectors) |
|||
{ |
|||
ref Vector4 baseRef = ref MemoryMarshal.GetReference(vectors); |
|||
|
|||
for (int i = 0; i < vectors.Length; i++) |
|||
{ |
|||
ref Vector4 v = ref Unsafe.Add(ref baseRef, i); |
|||
v.X = SRgbCompanding.Expand(v.X); |
|||
v.Y = SRgbCompanding.Expand(v.Y); |
|||
v.Z = SRgbCompanding.Expand(v.Z); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,124 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Numerics; |
|||
using SixLabors.ImageSharp.Memory; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
using SixLabors.ImageSharp.Primitives; |
|||
|
|||
namespace SixLabors.ImageSharp |
|||
{ |
|||
/// <summary>
|
|||
/// Extension methods for <see cref="DenseMatrix{T}"/>.
|
|||
/// </summary>
|
|||
internal static class DenseMatrixUtils |
|||
{ |
|||
/// <summary>
|
|||
/// Computes the sum of vectors in <paramref name="targetRow"/> weighted by the kernel weight values.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <param name="matrix">The dense matrix.</param>
|
|||
/// <param name="sourcePixels">The source frame.</param>
|
|||
/// <param name="targetRow">The target row.</param>
|
|||
/// <param name="row">The current row.</param>
|
|||
/// <param name="column">The current column.</param>
|
|||
/// <param name="maxRow">The maximum working area row.</param>
|
|||
/// <param name="maxColumn">The maximum working area column.</param>
|
|||
/// <param name="offsetColumn">The column offset to apply to source sampling.</param>
|
|||
public static void Convolve<TPixel>( |
|||
in DenseMatrix<float> matrix, |
|||
Buffer2D<TPixel> sourcePixels, |
|||
Span<Vector4> targetRow, |
|||
int row, |
|||
int column, |
|||
int maxRow, |
|||
int maxColumn, |
|||
int offsetColumn) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
Vector4 vector = default; |
|||
int matrixHeight = matrix.Rows; |
|||
int matrixWidth = matrix.Columns; |
|||
int radiusY = matrixHeight >> 1; |
|||
int radiusX = matrixWidth >> 1; |
|||
int sourceOffsetColumnBase = column + offsetColumn; |
|||
|
|||
for (int y = 0; y < matrixHeight; y++) |
|||
{ |
|||
int offsetY = (row + y - radiusY).Clamp(0, maxRow); |
|||
Span<TPixel> sourceRowSpan = sourcePixels.GetRowSpan(offsetY); |
|||
|
|||
for (int x = 0; x < matrixWidth; x++) |
|||
{ |
|||
int offsetX = (sourceOffsetColumnBase + x - radiusX).Clamp(offsetColumn, maxColumn); |
|||
var currentColor = sourceRowSpan[offsetX].ToVector4(); |
|||
Vector4Utils.Premultiply(ref currentColor); |
|||
|
|||
vector += matrix[y, x] * currentColor; |
|||
} |
|||
} |
|||
|
|||
ref Vector4 target = ref targetRow[column]; |
|||
vector.W = target.W; |
|||
Vector4Utils.UnPremultiply(ref vector); |
|||
target = vector; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Computes the sum of vectors in <paramref name="targetRow"/> weighted by the two kernel weight values.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <param name="matrixY">The vertical dense matrix.</param>
|
|||
/// <param name="matrixX">The horizontal dense matrix.</param>
|
|||
/// <param name="sourcePixels">The source frame.</param>
|
|||
/// <param name="targetRow">The target row.</param>
|
|||
/// <param name="row">The current row.</param>
|
|||
/// <param name="column">The current column.</param>
|
|||
/// <param name="maxRow">The maximum working area row.</param>
|
|||
/// <param name="maxColumn">The maximum working area column.</param>
|
|||
/// <param name="offsetColumn">The column offset to apply to source sampling.</param>
|
|||
public static void Convolve2D<TPixel>( |
|||
in DenseMatrix<float> matrixY, |
|||
in DenseMatrix<float> matrixX, |
|||
Buffer2D<TPixel> sourcePixels, |
|||
Span<Vector4> targetRow, |
|||
int row, |
|||
int column, |
|||
int maxRow, |
|||
int maxColumn, |
|||
int offsetColumn) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
Vector4 vectorY = default; |
|||
Vector4 vectorX = default; |
|||
int matrixHeight = matrixY.Rows; |
|||
int matrixWidth = matrixY.Columns; |
|||
int radiusY = matrixHeight >> 1; |
|||
int radiusX = matrixWidth >> 1; |
|||
int sourceOffsetColumnBase = column + offsetColumn; |
|||
|
|||
for (int y = 0; y < matrixHeight; y++) |
|||
{ |
|||
int offsetY = (row + y - radiusY).Clamp(0, maxRow); |
|||
Span<TPixel> sourceRowSpan = sourcePixels.GetRowSpan(offsetY); |
|||
|
|||
for (int x = 0; x < matrixWidth; x++) |
|||
{ |
|||
int offsetX = (sourceOffsetColumnBase + x - radiusX).Clamp(offsetColumn, maxColumn); |
|||
var currentColor = sourceRowSpan[offsetX].ToVector4(); |
|||
Vector4Utils.Premultiply(ref currentColor); |
|||
|
|||
vectorX += matrixX[y, x] * currentColor; |
|||
vectorY += matrixY[y, x] * currentColor; |
|||
} |
|||
} |
|||
|
|||
var vector = Vector4.SquareRoot((vectorX * vectorX) + (vectorY * vectorY)); |
|||
ref Vector4 target = ref targetRow[column]; |
|||
vector.W = target.W; |
|||
Vector4Utils.UnPremultiply(ref vector); |
|||
target = vector; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,74 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp |
|||
{ |
|||
/// <summary>
|
|||
/// Utility methods for the <see cref="Vector4"/> struct.
|
|||
/// </summary>
|
|||
internal static class Vector4Utils |
|||
{ |
|||
/// <summary>
|
|||
/// Pre-multiplies the "x", "y", "z" components of a vector by its "w" component leaving the "w" component intact.
|
|||
/// </summary>
|
|||
/// <param name="source">The <see cref="Vector4"/> to premultiply</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static void Premultiply(ref Vector4 source) |
|||
{ |
|||
float w = source.W; |
|||
source *= w; |
|||
source.W = w; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Reverses the result of premultiplying a vector via <see cref="Premultiply(ref Vector4)"/>.
|
|||
/// </summary>
|
|||
/// <param name="source">The <see cref="Vector4"/> to premultiply</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static void UnPremultiply(ref Vector4 source) |
|||
{ |
|||
float w = source.W; |
|||
source /= w; |
|||
source.W = w; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Bulk variant of <see cref="Premultiply(ref Vector4)"/>
|
|||
/// </summary>
|
|||
/// <param name="vectors">The span of vectors</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static void Premultiply(Span<Vector4> vectors) |
|||
{ |
|||
// TODO: This method can be AVX2 optimized using Vector<float>
|
|||
ref Vector4 baseRef = ref MemoryMarshal.GetReference(vectors); |
|||
|
|||
for (int i = 0; i < vectors.Length; i++) |
|||
{ |
|||
ref Vector4 v = ref Unsafe.Add(ref baseRef, i); |
|||
Premultiply(ref v); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Bulk variant of <see cref="UnPremultiply(ref Vector4)"/>
|
|||
/// </summary>
|
|||
/// <param name="vectors">The span of vectors</param>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static void UnPremultiply(Span<Vector4> vectors) |
|||
{ |
|||
// TODO: This method can be AVX2 optimized using Vector<float>
|
|||
ref Vector4 baseRef = ref MemoryMarshal.GetReference(vectors); |
|||
|
|||
for (int i = 0; i < vectors.Length; i++) |
|||
{ |
|||
ref Vector4 v = ref Unsafe.Add(ref baseRef, i); |
|||
UnPremultiply(ref v); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,59 @@ |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using BenchmarkDotNet.Attributes; |
|||
|
|||
namespace SixLabors.ImageSharp.Benchmarks.General.Vectorization |
|||
{ |
|||
public class Premultiply |
|||
{ |
|||
[Benchmark(Baseline = true)] |
|||
public Vector4 PremultiplyByVal() |
|||
{ |
|||
var input = new Vector4(.5F); |
|||
return Vector4Utils.Premultiply(input); |
|||
} |
|||
|
|||
[Benchmark] |
|||
public Vector4 PremultiplyByRef() |
|||
{ |
|||
var input = new Vector4(.5F); |
|||
Vector4Utils.PremultiplyRef(ref input); |
|||
return input; |
|||
} |
|||
|
|||
[Benchmark] |
|||
public Vector4 PremultiplyRefWithPropertyAssign() |
|||
{ |
|||
var input = new Vector4(.5F); |
|||
Vector4Utils.PremultiplyRefWithPropertyAssign(ref input); |
|||
return input; |
|||
} |
|||
} |
|||
|
|||
internal static class Vector4Utils |
|||
{ |
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static Vector4 Premultiply(Vector4 source) |
|||
{ |
|||
float w = source.W; |
|||
Vector4 premultiplied = source * w; |
|||
premultiplied.W = w; |
|||
return premultiplied; |
|||
} |
|||
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static void PremultiplyRef(ref Vector4 source) |
|||
{ |
|||
float w = source.W; |
|||
source *= w; |
|||
source.W = w; |
|||
} |
|||
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public static void PremultiplyRefWithPropertyAssign(ref Vector4 source) |
|||
{ |
|||
float w = source.W; |
|||
source *= new Vector4(w) { W = 1 }; |
|||
} |
|||
} |
|||
} |
|||
@ -1,74 +0,0 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Linq; |
|||
using System.Numerics; |
|||
|
|||
using Xunit; |
|||
|
|||
namespace SixLabors.ImageSharp.Tests.Helpers |
|||
{ |
|||
public class Vector4ExtensionsTests |
|||
{ |
|||
[Theory] |
|||
[InlineData(0)] |
|||
[InlineData(1)] |
|||
[InlineData(30)] |
|||
public void Premultiply_VectorSpan(int length) |
|||
{ |
|||
var rnd = new Random(42); |
|||
Vector4[] source = rnd.GenerateRandomVectorArray(length, 0, 1); |
|||
Vector4[] expected = source.Select(v => v.Premultiply()).ToArray(); |
|||
|
|||
Vector4Extensions.Premultiply(source); |
|||
|
|||
Assert.Equal(expected, source, new ApproximateFloatComparer(1e-6f)); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(0)] |
|||
[InlineData(1)] |
|||
[InlineData(30)] |
|||
public void UnPremultiply_VectorSpan(int length) |
|||
{ |
|||
var rnd = new Random(42); |
|||
Vector4[] source = rnd.GenerateRandomVectorArray(length, 0, 1); |
|||
Vector4[] expected = source.Select(v => v.UnPremultiply()).ToArray(); |
|||
|
|||
Vector4Extensions.UnPremultiply(source); |
|||
|
|||
Assert.Equal(expected, source, new ApproximateFloatComparer(1e-6f)); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(0)] |
|||
[InlineData(1)] |
|||
[InlineData(30)] |
|||
public void Expand_VectorSpan(int length) |
|||
{ |
|||
var rnd = new Random(42); |
|||
Vector4[] source = rnd.GenerateRandomVectorArray(length, 0, 1); |
|||
Vector4[] expected = source.Select(v => v.Expand()).ToArray(); |
|||
|
|||
Vector4Extensions.Expand(source); |
|||
|
|||
Assert.Equal(expected, source, new ApproximateFloatComparer(1e-6f)); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(0)] |
|||
[InlineData(1)] |
|||
[InlineData(30)] |
|||
public void Compress_VectorSpan(int length) |
|||
{ |
|||
var rnd = new Random(42); |
|||
Vector4[] source = rnd.GenerateRandomVectorArray(length, 0, 1); |
|||
Vector4[] expected = source.Select(v => v.Compress()).ToArray(); |
|||
|
|||
Vector4Extensions.Compress(source); |
|||
|
|||
Assert.Equal(expected, source, new ApproximateFloatComparer(1e-6f)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,44 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Linq; |
|||
using System.Numerics; |
|||
|
|||
using Xunit; |
|||
|
|||
namespace SixLabors.ImageSharp.Tests.Helpers |
|||
{ |
|||
public class Vector4UtilsTests |
|||
{ |
|||
[Theory] |
|||
[InlineData(0)] |
|||
[InlineData(1)] |
|||
[InlineData(30)] |
|||
public void Premultiply_VectorSpan(int length) |
|||
{ |
|||
var rnd = new Random(42); |
|||
Vector4[] source = rnd.GenerateRandomVectorArray(length, 0, 1); |
|||
Vector4[] expected = source.Select(v => { Vector4Utils.Premultiply(ref v); return v; }).ToArray(); |
|||
|
|||
Vector4Utils.Premultiply(source); |
|||
|
|||
Assert.Equal(expected, source, new ApproximateFloatComparer(1e-6f)); |
|||
} |
|||
|
|||
[Theory] |
|||
[InlineData(0)] |
|||
[InlineData(1)] |
|||
[InlineData(30)] |
|||
public void UnPremultiply_VectorSpan(int length) |
|||
{ |
|||
var rnd = new Random(42); |
|||
Vector4[] source = rnd.GenerateRandomVectorArray(length, 0, 1); |
|||
Vector4[] expected = source.Select(v => { Vector4Utils.UnPremultiply(ref v); return v; }).ToArray(); |
|||
|
|||
Vector4Utils.UnPremultiply(source); |
|||
|
|||
Assert.Equal(expected, source, new ApproximateFloatComparer(1e-6f)); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue