diff --git a/src/ImageSharp/Common/Helpers/ColorNumerics.cs b/src/ImageSharp/Common/Helpers/ColorNumerics.cs index 47c4b296b..553a7c2e8 100644 --- a/src/ImageSharp/Common/Helpers/ColorNumerics.cs +++ b/src/ImageSharp/Common/Helpers/ColorNumerics.cs @@ -3,7 +3,6 @@ using System.Numerics; using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; namespace SixLabors.ImageSharp; @@ -17,7 +16,7 @@ internal static class ColorNumerics /// Vector for converting pixel to gray value as specified by /// ITU-R Recommendation BT.709. /// - private static readonly Vector4 Bt709 = new Vector4(.2126f, .7152f, .0722f, 0.0f); + private static readonly Vector4 Bt709 = new(.2126f, .7152f, .0722f, 0.0f); /// /// Convert a pixel value to grayscale using ITU-R Recommendation BT.709. @@ -137,6 +136,19 @@ internal static class ColorNumerics public static int GetColorCountForBitDepth(int bitDepth) => 1 << bitDepth; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static Vector4 Transform(Vector4 vector, in ColorMatrix.Impl matrix) + { + Vector4 result = matrix.X * vector.X; + + result += matrix.Y * vector.Y; + result += matrix.Z * vector.Z; + result += matrix.W * vector.W; + result += matrix.V; + + return result; + } + /// /// Transforms a vector by the given color matrix. /// @@ -144,17 +156,7 @@ internal static class ColorNumerics /// The transformation color matrix. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Transform(ref Vector4 vector, ref ColorMatrix matrix) - { - float x = vector.X; - float y = vector.Y; - float z = vector.Z; - float w = vector.W; - - vector.X = (x * matrix.M11) + (y * matrix.M21) + (z * matrix.M31) + (w * matrix.M41) + matrix.M51; - vector.Y = (x * matrix.M12) + (y * matrix.M22) + (z * matrix.M32) + (w * matrix.M42) + matrix.M52; - vector.Z = (x * matrix.M13) + (y * matrix.M23) + (z * matrix.M33) + (w * matrix.M43) + matrix.M53; - vector.W = (x * matrix.M14) + (y * matrix.M24) + (z * matrix.M34) + (w * matrix.M44) + matrix.M54; - } + => vector = Transform(vector, matrix.AsImpl()); /// /// Bulk variant of . @@ -164,11 +166,9 @@ internal static class ColorNumerics [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Transform(Span vectors, ref ColorMatrix matrix) { - ref Vector4 baseRef = ref MemoryMarshal.GetReference(vectors); - for (int i = 0; i < vectors.Length; i++) { - ref Vector4 v = ref Unsafe.Add(ref baseRef, i); + ref Vector4 v = ref vectors[i]; Transform(ref v, ref matrix); } } diff --git a/src/ImageSharp/Diagnostics/CodeAnalysis/UnscopedRefAttribute.cs b/src/ImageSharp/Diagnostics/CodeAnalysis/UnscopedRefAttribute.cs new file mode 100644 index 000000000..dc2c7bd19 --- /dev/null +++ b/src/ImageSharp/Diagnostics/CodeAnalysis/UnscopedRefAttribute.cs @@ -0,0 +1,42 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. +#if NET6_0 +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +namespace System.Diagnostics.CodeAnalysis +{ + /// + /// Used to indicate a byref escapes and is not scoped. + /// + /// + /// + /// There are several cases where the C# compiler treats a as implicitly + /// - where the compiler does not allow the to escape the method. + /// + /// + /// For example: + /// + /// for instance methods. + /// parameters that refer to types. + /// parameters. + /// + /// + /// + /// This attribute is used in those instances where the should be allowed to escape. + /// + /// + /// Applying this attribute, in any form, has impact on consumers of the applicable API. It is necessary for + /// API authors to understand the lifetime implications of applying this attribute and how it may impact their users. + /// + /// + [global::System.AttributeUsage( + global::System.AttributeTargets.Method | + global::System.AttributeTargets.Property | + global::System.AttributeTargets.Parameter, + AllowMultiple = false, + Inherited = false)] + internal sealed class UnscopedRefAttribute : global::System.Attribute + { + } +} +#endif diff --git a/src/ImageSharp/Primitives/ColorMatrix.Impl.cs b/src/ImageSharp/Primitives/ColorMatrix.Impl.cs new file mode 100644 index 000000000..559fcdde0 --- /dev/null +++ b/src/ImageSharp/Primitives/ColorMatrix.Impl.cs @@ -0,0 +1,208 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +#pragma warning disable SA1117 // Parameters should be on same line or separate lines +using System.Diagnostics.CodeAnalysis; +using System.Numerics; +using System.Runtime.CompilerServices; + +namespace SixLabors.ImageSharp; + +/// +/// A structure encapsulating a 5x4 matrix used for transforming the color and alpha components of an image. +/// +public partial struct ColorMatrix +{ + [UnscopedRef] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal ref Impl AsImpl() => ref Unsafe.As(ref this); + + [UnscopedRef] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal readonly ref readonly Impl AsROImpl() => ref Unsafe.As(ref Unsafe.AsRef(in this)); + + internal struct Impl : IEquatable + { + public Vector4 X; + public Vector4 Y; + public Vector4 Z; + public Vector4 W; + public Vector4 V; + + public static Impl Identity + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get + { + Impl result; + + result.X = Vector4.UnitX; + result.Y = Vector4.UnitY; + result.Z = Vector4.UnitZ; + result.W = Vector4.UnitW; + result.V = Vector4.Zero; + + return result; + } + } + + public readonly bool IsIdentity + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => + (this.X == Vector4.UnitX) + && (this.Y == Vector4.UnitY) + && (this.Z == Vector4.UnitZ) + && (this.W == Vector4.UnitW) + && (this.V == Vector4.Zero); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Impl operator +(in Impl left, in Impl right) + { + Impl result; + + result.X = left.X + right.X; + result.Y = left.Y + right.Y; + result.Z = left.Z + right.Z; + result.W = left.W + right.W; + result.V = left.V + right.V; + + return result; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Impl operator -(in Impl left, in Impl right) + { + Impl result; + + result.X = left.X - right.X; + result.Y = left.Y - right.Y; + result.Z = left.Z - right.Z; + result.W = left.W - right.W; + result.V = left.V - right.V; + + return result; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Impl operator -(in Impl value) + { + Impl result; + + result.X = -value.X; + result.Y = -value.Y; + result.Z = -value.Z; + result.W = -value.W; + result.V = -value.V; + + return result; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Impl operator *(in Impl left, in Impl right) + { + Impl result; + + // result.X = Transform(left.X, in right); + result.X = right.X * left.X.X; + result.X += right.Y * left.X.Y; + result.X += right.Z * left.X.Z; + result.X += right.W * left.X.W; + + // result.Y = Transform(left.Y, in right); + result.Y = right.X * left.Y.X; + result.Y += right.Y * left.Y.Y; + result.Y += right.Z * left.Y.Z; + result.Y += right.W * left.Y.W; + + // result.Z = Transform(left.Z, in right); + result.Z = right.X * left.Z.X; + result.Z += right.Y * left.Z.Y; + result.Z += right.Z * left.Z.Z; + result.Z += right.W * left.Z.W; + + // result.W = Transform(left.W, in right); + result.W = right.X * left.W.X; + result.W += right.Y * left.W.Y; + result.W += right.Z * left.W.Z; + result.W += right.W * left.W.W; + + // result.V = Transform(left.V, in right); + result.V = right.X * left.V.X; + result.V += right.Y * left.V.Y; + result.V += right.Z * left.V.Z; + result.V += right.W * left.V.W; + + result.V += right.V; + + return result; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Impl operator *(in Impl left, float right) + { + Impl result; + + result.X = left.X * right; + result.Y = left.Y * right; + result.Z = left.Z * right; + result.W = left.W * right; + result.V = left.V * right; + + return result; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool operator ==(in Impl left, in Impl right) => + (left.X == right.X) + && (left.Y == right.Y) + && (left.Z == right.Z) + && (left.W == right.W) + && (left.V == right.V); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool operator !=(in Impl left, in Impl right) => + (left.X != right.X) + && (left.Y != right.Y) + && (left.Z != right.Z) + && (left.W != right.W) + && (left.V != right.V); + + [UnscopedRef] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public ref ColorMatrix AsColorMatrix() => ref Unsafe.As(ref this); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Init( + float m11, float m12, float m13, float m14, + float m21, float m22, float m23, float m24, + float m31, float m32, float m33, float m34, + float m41, float m42, float m43, float m44, + float m51, float m52, float m53, float m54) + { + this.X = new Vector4(m11, m12, m13, m14); + this.Y = new Vector4(m21, m22, m23, m24); + this.Z = new Vector4(m31, m32, m33, m34); + this.W = new Vector4(m41, m42, m43, m44); + this.V = new Vector4(m51, m52, m53, m54); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override readonly bool Equals([NotNullWhen(true)] object? obj) + => (obj is ColorMatrix other) && this.Equals(in other.AsImpl()); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly bool Equals(in Impl other) => + this.X.Equals(other.X) + && this.Y.Equals(other.Y) + && this.Z.Equals(other.Z) + && this.W.Equals(other.W) + && this.V.Equals(other.V); + + bool IEquatable.Equals(Impl other) => this.Equals(in other); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override readonly int GetHashCode() => HashCode.Combine(this.X, this.Y, this.Z, this.W, this.V); + } +} diff --git a/src/ImageSharp/Primitives/ColorMatrix.cs b/src/ImageSharp/Primitives/ColorMatrix.cs index e06dc1f6a..9f8b09e4b 100644 --- a/src/ImageSharp/Primitives/ColorMatrix.cs +++ b/src/ImageSharp/Primitives/ColorMatrix.cs @@ -2,7 +2,10 @@ // Licensed under the Six Labors Split License. #pragma warning disable SA1117 // Parameters should be on same line or separate lines + +using System.Diagnostics.CodeAnalysis; using System.Globalization; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace SixLabors.ImageSharp; @@ -11,7 +14,7 @@ namespace SixLabors.ImageSharp; /// A structure encapsulating a 5x4 matrix used for transforming the color and alpha components of an image. /// [StructLayout(LayoutKind.Sequential)] -public struct ColorMatrix : IEquatable +public partial struct ColorMatrix : IEquatable { /// /// Value at row 1, column 1 of the matrix. @@ -137,62 +140,33 @@ public struct ColorMatrix : IEquatable /// The value at row 5, column 3 of the matrix. /// The value at row 5, column 4 of the matrix. public ColorMatrix(float m11, float m12, float m13, float m14, - float m21, float m22, float m23, float m24, - float m31, float m32, float m33, float m34, - float m41, float m42, float m43, float m44, - float m51, float m52, float m53, float m54) + float m21, float m22, float m23, float m24, + float m31, float m32, float m33, float m34, + float m41, float m42, float m43, float m44, + float m51, float m52, float m53, float m54) { - this.M11 = m11; - this.M12 = m12; - this.M13 = m13; - this.M14 = m14; - - this.M21 = m21; - this.M22 = m22; - this.M23 = m23; - this.M24 = m24; - - this.M31 = m31; - this.M32 = m32; - this.M33 = m33; - this.M34 = m34; - - this.M41 = m41; - this.M42 = m42; - this.M43 = m43; - this.M44 = m44; - - this.M51 = m51; - this.M52 = m52; - this.M53 = m53; - this.M54 = m54; + Unsafe.SkipInit(out this); + + this.AsImpl().Init(m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44, m51, m52, m53, + m54); } /// /// Gets the multiplicative identity matrix. /// - public static ColorMatrix Identity { get; } = - new ColorMatrix(1F, 0F, 0F, 0F, - 0F, 1F, 0F, 0F, - 0F, 0F, 1F, 0F, - 0F, 0F, 0F, 1F, - 0F, 0F, 0F, 0F); + public static ColorMatrix Identity + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => Impl.Identity.AsColorMatrix(); + } /// /// Gets a value indicating whether the matrix is the identity matrix. /// public bool IsIdentity { - get - { - // Check diagonal element first for early out. - return this.M11 == 1F && this.M22 == 1F && this.M33 == 1F && this.M44 == 1F - && this.M12 == 0F && this.M13 == 0F && this.M14 == 0F - && this.M21 == 0F && this.M23 == 0F && this.M24 == 0F - && this.M31 == 0F && this.M32 == 0F && this.M34 == 0F - && this.M41 == 0F && this.M42 == 0F && this.M43 == 0F - && this.M51 == 0F && this.M52 == 0F && this.M53 == 0F && this.M54 == 0F; - } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => this.AsROImpl().IsIdentity; } /// @@ -202,32 +176,7 @@ public struct ColorMatrix : IEquatable /// The second source matrix. /// The resulting matrix. public static ColorMatrix operator +(ColorMatrix value1, ColorMatrix value2) - { - var m = default(ColorMatrix); - - m.M11 = value1.M11 + value2.M11; - m.M12 = value1.M12 + value2.M12; - m.M13 = value1.M13 + value2.M13; - m.M14 = value1.M14 + value2.M14; - m.M21 = value1.M21 + value2.M21; - m.M22 = value1.M22 + value2.M22; - m.M23 = value1.M23 + value2.M23; - m.M24 = value1.M24 + value2.M24; - m.M31 = value1.M31 + value2.M31; - m.M32 = value1.M32 + value2.M32; - m.M33 = value1.M33 + value2.M33; - m.M34 = value1.M34 + value2.M34; - m.M41 = value1.M41 + value2.M41; - m.M42 = value1.M42 + value2.M42; - m.M43 = value1.M43 + value2.M43; - m.M44 = value1.M44 + value2.M44; - m.M51 = value1.M51 + value2.M51; - m.M52 = value1.M52 + value2.M52; - m.M53 = value1.M53 + value2.M53; - m.M54 = value1.M54 + value2.M54; - - return m; - } + => (value1.AsImpl() + value2.AsImpl()).AsColorMatrix(); /// /// Subtracts the second matrix from the first. @@ -236,32 +185,7 @@ public struct ColorMatrix : IEquatable /// The second source matrix. /// The result of the subtraction. public static ColorMatrix operator -(ColorMatrix value1, ColorMatrix value2) - { - var m = default(ColorMatrix); - - m.M11 = value1.M11 - value2.M11; - m.M12 = value1.M12 - value2.M12; - m.M13 = value1.M13 - value2.M13; - m.M14 = value1.M14 - value2.M14; - m.M21 = value1.M21 - value2.M21; - m.M22 = value1.M22 - value2.M22; - m.M23 = value1.M23 - value2.M23; - m.M24 = value1.M24 - value2.M24; - m.M31 = value1.M31 - value2.M31; - m.M32 = value1.M32 - value2.M32; - m.M33 = value1.M33 - value2.M33; - m.M34 = value1.M34 - value2.M34; - m.M41 = value1.M41 - value2.M41; - m.M42 = value1.M42 - value2.M42; - m.M43 = value1.M43 - value2.M43; - m.M44 = value1.M44 - value2.M44; - m.M51 = value1.M51 - value2.M51; - m.M52 = value1.M52 - value2.M52; - m.M53 = value1.M53 - value2.M53; - m.M54 = value1.M54 - value2.M54; - - return m; - } + => (value1.AsImpl() - value2.AsImpl()).AsColorMatrix(); /// /// Returns a new matrix with the negated elements of the given matrix. @@ -269,32 +193,7 @@ public struct ColorMatrix : IEquatable /// The source matrix. /// The negated matrix. public static ColorMatrix operator -(ColorMatrix value) - { - var m = default(ColorMatrix); - - m.M11 = -value.M11; - m.M12 = -value.M12; - m.M13 = -value.M13; - m.M14 = -value.M14; - m.M21 = -value.M21; - m.M22 = -value.M22; - m.M23 = -value.M23; - m.M24 = -value.M24; - m.M31 = -value.M31; - m.M32 = -value.M32; - m.M33 = -value.M33; - m.M34 = -value.M34; - m.M41 = -value.M41; - m.M42 = -value.M42; - m.M43 = -value.M43; - m.M44 = -value.M44; - m.M51 = -value.M51; - m.M52 = -value.M52; - m.M53 = -value.M53; - m.M54 = -value.M54; - - return m; - } + => (-value.AsImpl()).AsColorMatrix(); /// /// Multiplies a matrix by another matrix. @@ -303,41 +202,7 @@ public struct ColorMatrix : IEquatable /// The second source matrix. /// The result of the multiplication. public static ColorMatrix operator *(ColorMatrix value1, ColorMatrix value2) - { - var m = default(ColorMatrix); - - // First row - m.M11 = (value1.M11 * value2.M11) + (value1.M12 * value2.M21) + (value1.M13 * value2.M31) + (value1.M14 * value2.M41); - m.M12 = (value1.M11 * value2.M12) + (value1.M12 * value2.M22) + (value1.M13 * value2.M32) + (value1.M14 * value2.M42); - m.M13 = (value1.M11 * value2.M13) + (value1.M12 * value2.M23) + (value1.M13 * value2.M33) + (value1.M14 * value2.M43); - m.M14 = (value1.M11 * value2.M14) + (value1.M12 * value2.M24) + (value1.M13 * value2.M34) + (value1.M14 * value2.M44); - - // Second row - m.M21 = (value1.M21 * value2.M11) + (value1.M22 * value2.M21) + (value1.M23 * value2.M31) + (value1.M24 * value2.M41); - m.M22 = (value1.M21 * value2.M12) + (value1.M22 * value2.M22) + (value1.M23 * value2.M32) + (value1.M24 * value2.M42); - m.M23 = (value1.M21 * value2.M13) + (value1.M22 * value2.M23) + (value1.M23 * value2.M33) + (value1.M24 * value2.M43); - m.M24 = (value1.M21 * value2.M14) + (value1.M22 * value2.M24) + (value1.M23 * value2.M34) + (value1.M24 * value2.M44); - - // Third row - m.M31 = (value1.M31 * value2.M11) + (value1.M32 * value2.M21) + (value1.M33 * value2.M31) + (value1.M34 * value2.M41); - m.M32 = (value1.M31 * value2.M12) + (value1.M32 * value2.M22) + (value1.M33 * value2.M32) + (value1.M34 * value2.M42); - m.M33 = (value1.M31 * value2.M13) + (value1.M32 * value2.M23) + (value1.M33 * value2.M33) + (value1.M34 * value2.M43); - m.M34 = (value1.M31 * value2.M14) + (value1.M32 * value2.M24) + (value1.M33 * value2.M34) + (value1.M34 * value2.M44); - - // Fourth row - m.M41 = (value1.M41 * value2.M11) + (value1.M42 * value2.M21) + (value1.M43 * value2.M31) + (value1.M44 * value2.M41); - m.M42 = (value1.M41 * value2.M12) + (value1.M42 * value2.M22) + (value1.M43 * value2.M32) + (value1.M44 * value2.M42); - m.M43 = (value1.M41 * value2.M13) + (value1.M42 * value2.M23) + (value1.M43 * value2.M33) + (value1.M44 * value2.M43); - m.M44 = (value1.M41 * value2.M14) + (value1.M42 * value2.M24) + (value1.M43 * value2.M34) + (value1.M44 * value2.M44); - - // Fifth row - m.M51 = (value1.M51 * value2.M11) + (value1.M52 * value2.M21) + (value1.M53 * value2.M31) + (value1.M54 * value2.M41) + value2.M51; - m.M52 = (value1.M51 * value2.M12) + (value1.M52 * value2.M22) + (value1.M53 * value2.M32) + (value1.M54 * value2.M52) + value2.M52; - m.M53 = (value1.M51 * value2.M13) + (value1.M52 * value2.M23) + (value1.M53 * value2.M33) + (value1.M54 * value2.M53) + value2.M53; - m.M54 = (value1.M51 * value2.M14) + (value1.M52 * value2.M24) + (value1.M53 * value2.M34) + (value1.M54 * value2.M54) + value2.M54; - - return m; - } + => (value1.AsImpl() * value2.AsImpl()).AsColorMatrix(); /// /// Multiplies a matrix by a scalar value. @@ -346,32 +211,7 @@ public struct ColorMatrix : IEquatable /// The scaling factor. /// The scaled matrix. public static ColorMatrix operator *(ColorMatrix value1, float value2) - { - var m = default(ColorMatrix); - - m.M11 = value1.M11 * value2; - m.M12 = value1.M12 * value2; - m.M13 = value1.M13 * value2; - m.M14 = value1.M14 * value2; - m.M21 = value1.M21 * value2; - m.M22 = value1.M22 * value2; - m.M23 = value1.M23 * value2; - m.M24 = value1.M24 * value2; - m.M31 = value1.M31 * value2; - m.M32 = value1.M32 * value2; - m.M33 = value1.M33 * value2; - m.M34 = value1.M34 * value2; - m.M41 = value1.M41 * value2; - m.M42 = value1.M42 * value2; - m.M43 = value1.M43 * value2; - m.M44 = value1.M44 * value2; - m.M51 = value1.M51 * value2; - m.M52 = value1.M52 * value2; - m.M53 = value1.M53 * value2; - m.M54 = value1.M54 * value2; - - return m; - } + => (value1.AsImpl() * value2).AsColorMatrix(); /// /// Returns a boolean indicating whether the given two matrices are equal. @@ -379,7 +219,8 @@ public struct ColorMatrix : IEquatable /// The first matrix to compare. /// The second matrix to compare. /// True if the given matrices are equal; False otherwise. - public static bool operator ==(ColorMatrix value1, ColorMatrix value2) => value1.Equals(value2); + public static bool operator ==(ColorMatrix value1, ColorMatrix value2) + => value1.AsImpl() == value2.AsImpl(); /// /// Returns a boolean indicating whether the given two matrices are not equal. @@ -387,71 +228,35 @@ public struct ColorMatrix : IEquatable /// The first matrix to compare. /// The second matrix to compare. /// True if the given matrices are equal; False otherwise. - public static bool operator !=(ColorMatrix value1, ColorMatrix value2) => !value1.Equals(value2); + public static bool operator !=(ColorMatrix value1, ColorMatrix value2) + => value1.AsImpl() != value2.AsImpl(); /// - public override bool Equals(object? obj) => obj is ColorMatrix matrix && this.Equals(matrix); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public override readonly bool Equals([NotNullWhen(true)] object? obj) + => this.AsROImpl().Equals(obj); /// - public bool Equals(ColorMatrix other) => - this.M11 == other.M11 - && this.M12 == other.M12 - && this.M13 == other.M13 - && this.M14 == other.M14 - && this.M21 == other.M21 - && this.M22 == other.M22 - && this.M23 == other.M23 - && this.M24 == other.M24 - && this.M31 == other.M31 - && this.M32 == other.M32 - && this.M33 == other.M33 - && this.M34 == other.M34 - && this.M41 == other.M41 - && this.M42 == other.M42 - && this.M43 == other.M43 - && this.M44 == other.M44 - && this.M51 == other.M51 - && this.M52 == other.M52 - && this.M53 == other.M53 - && this.M54 == other.M54; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public readonly bool Equals(ColorMatrix other) + => this.AsROImpl().Equals(in other.AsImpl()); /// public override int GetHashCode() - { - HashCode hash = default; - hash.Add(this.M11); - hash.Add(this.M12); - hash.Add(this.M13); - hash.Add(this.M14); - hash.Add(this.M21); - hash.Add(this.M22); - hash.Add(this.M23); - hash.Add(this.M24); - hash.Add(this.M31); - hash.Add(this.M32); - hash.Add(this.M33); - hash.Add(this.M34); - hash.Add(this.M41); - hash.Add(this.M42); - hash.Add(this.M43); - hash.Add(this.M44); - hash.Add(this.M51); - hash.Add(this.M52); - hash.Add(this.M53); - hash.Add(this.M54); - return hash.ToHashCode(); - } + => this.AsROImpl().GetHashCode(); /// public override string ToString() { CultureInfo ci = CultureInfo.CurrentCulture; - return string.Format(ci, "{{ {{M11:{0} M12:{1} M13:{2} M14:{3}}} {{M21:{4} M22:{5} M23:{6} M24:{7}}} {{M31:{8} M32:{9} M33:{10} M34:{11}}} {{M41:{12} M42:{13} M43:{14} M44:{15}}} {{M51:{16} M52:{17} M53:{18} M54:{19}}} }}", - this.M11.ToString(ci), this.M12.ToString(ci), this.M13.ToString(ci), this.M14.ToString(ci), - this.M21.ToString(ci), this.M22.ToString(ci), this.M23.ToString(ci), this.M24.ToString(ci), - this.M31.ToString(ci), this.M32.ToString(ci), this.M33.ToString(ci), this.M34.ToString(ci), - this.M41.ToString(ci), this.M42.ToString(ci), this.M43.ToString(ci), this.M44.ToString(ci), - this.M51.ToString(ci), this.M52.ToString(ci), this.M53.ToString(ci), this.M54.ToString(ci)); + return string.Format( + ci, + "{{ {{M11:{0} M12:{1} M13:{2} M14:{3}}} {{M21:{4} M22:{5} M23:{6} M24:{7}}} {{M31:{8} M32:{9} M33:{10} M34:{11}}} {{M41:{12} M42:{13} M43:{14} M44:{15}}} {{M51:{16} M52:{17} M53:{18} M54:{19}}} }}", + this.M11.ToString(ci), this.M12.ToString(ci), this.M13.ToString(ci), this.M14.ToString(ci), + this.M21.ToString(ci), this.M22.ToString(ci), this.M23.ToString(ci), this.M24.ToString(ci), + this.M31.ToString(ci), this.M32.ToString(ci), this.M33.ToString(ci), this.M34.ToString(ci), + this.M41.ToString(ci), this.M42.ToString(ci), this.M43.ToString(ci), this.M44.ToString(ci), + this.M51.ToString(ci), this.M52.ToString(ci), this.M53.ToString(ci), this.M54.ToString(ci)); } } diff --git a/tests/ImageSharp.Benchmarks/Bulk/ColorMatrixTransforms.cs b/tests/ImageSharp.Benchmarks/Bulk/ColorMatrixTransforms.cs new file mode 100644 index 000000000..9147e3649 --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Bulk/ColorMatrixTransforms.cs @@ -0,0 +1,31 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +using System.Numerics; +using BenchmarkDotNet.Attributes; +using SixLabors.ImageSharp.Processing; + +namespace SixLabors.ImageSharp.Benchmarks.Bulk; + +public class ColorMatrixTransforms +{ + private static readonly Vector4[] Vectors = Vector4Factory.CreateVectors(); + + [Benchmark(Baseline = true)] + public void Transform() + { + ColorMatrix matrix = KnownFilterMatrices.CreateHueFilter(45F); + for (int i = 0; i < Vectors.Length; i++) + { + ref Vector4 input = ref Vectors[i]; + ColorNumerics.Transform(ref input, ref matrix); + } + } + + [Benchmark] + public void Transform_Span() + { + ColorMatrix matrix = KnownFilterMatrices.CreateHueFilter(45F); + ColorNumerics.Transform(Vectors.AsSpan(), ref matrix); + } +} diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/FromRgba32Bytes.cs b/tests/ImageSharp.Benchmarks/Bulk/FromRgba32Bytes.cs similarity index 92% rename from tests/ImageSharp.Benchmarks/Color/Bulk/FromRgba32Bytes.cs rename to tests/ImageSharp.Benchmarks/Bulk/FromRgba32Bytes.cs index e27bf07e9..bd938c9da 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/FromRgba32Bytes.cs +++ b/tests/ImageSharp.Benchmarks/Bulk/FromRgba32Bytes.cs @@ -8,7 +8,7 @@ using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; // ReSharper disable InconsistentNaming -namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk; +namespace SixLabors.ImageSharp.Benchmarks.Bulk; public abstract class FromRgba32Bytes where TPixel : unmanaged, IPixel @@ -64,7 +64,7 @@ public abstract class FromRgba32Bytes [Benchmark] public void OptimizedBulk() { - PixelOperations.Instance.FromRgba32Bytes(this.configuration, this.source.GetSpan(), this.destination.GetSpan(), this.Count); + PixelOperations.Instance.FromRgba32Bytes(this.configuration, this.source.GetSpan(), this.destination.GetSpan(), this.Count); } } diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/FromVector4.cs b/tests/ImageSharp.Benchmarks/Bulk/FromVector4.cs similarity index 99% rename from tests/ImageSharp.Benchmarks/Color/Bulk/FromVector4.cs rename to tests/ImageSharp.Benchmarks/Bulk/FromVector4.cs index d1cb61678..dd3fb8ac8 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/FromVector4.cs +++ b/tests/ImageSharp.Benchmarks/Bulk/FromVector4.cs @@ -12,7 +12,7 @@ using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; // ReSharper disable InconsistentNaming -namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk; +namespace SixLabors.ImageSharp.Benchmarks.Bulk; [Config(typeof(Config.ShortCore31))] public abstract class FromVector4 diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/FromVector4_Rgb24.cs b/tests/ImageSharp.Benchmarks/Bulk/FromVector4_Rgb24.cs similarity index 98% rename from tests/ImageSharp.Benchmarks/Color/Bulk/FromVector4_Rgb24.cs rename to tests/ImageSharp.Benchmarks/Bulk/FromVector4_Rgb24.cs index 2effbd1d5..fe0d2a10a 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/FromVector4_Rgb24.cs +++ b/tests/ImageSharp.Benchmarks/Bulk/FromVector4_Rgb24.cs @@ -4,7 +4,7 @@ using BenchmarkDotNet.Attributes; using SixLabors.ImageSharp.PixelFormats; -namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk; +namespace SixLabors.ImageSharp.Benchmarks.Bulk; [Config(typeof(Config.ShortMultiFramework))] public class FromVector4_Rgb24 : FromVector4 diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/Pad3Shuffle4Channel.cs b/tests/ImageSharp.Benchmarks/Bulk/Pad3Shuffle4Channel.cs similarity index 99% rename from tests/ImageSharp.Benchmarks/Color/Bulk/Pad3Shuffle4Channel.cs rename to tests/ImageSharp.Benchmarks/Bulk/Pad3Shuffle4Channel.cs index 73dcf55a1..1b6663e70 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/Pad3Shuffle4Channel.cs +++ b/tests/ImageSharp.Benchmarks/Bulk/Pad3Shuffle4Channel.cs @@ -3,7 +3,7 @@ using BenchmarkDotNet.Attributes; -namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk; +namespace SixLabors.ImageSharp.Benchmarks.Bulk; [Config(typeof(Config.HwIntrinsics_SSE_AVX))] public class Pad3Shuffle4Channel diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/PremultiplyVector4.cs b/tests/ImageSharp.Benchmarks/Bulk/PremultiplyVector4.cs similarity index 55% rename from tests/ImageSharp.Benchmarks/Color/Bulk/PremultiplyVector4.cs rename to tests/ImageSharp.Benchmarks/Bulk/PremultiplyVector4.cs index 44496a249..d22fc18ac 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/PremultiplyVector4.cs +++ b/tests/ImageSharp.Benchmarks/Bulk/PremultiplyVector4.cs @@ -6,11 +6,11 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using BenchmarkDotNet.Attributes; -namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk; +namespace SixLabors.ImageSharp.Benchmarks.Bulk; public class PremultiplyVector4 { - private static readonly Vector4[] Vectors = CreateVectors(); + private static readonly Vector4[] Vectors = Vector4Factory.CreateVectors(); [Benchmark(Baseline = true)] public void PremultiplyBaseline() @@ -46,29 +46,4 @@ public class PremultiplyVector4 source *= w; source.W = w; } - - private static Vector4[] CreateVectors() - { - Random rnd = new(42); - return GenerateRandomVectorArray(rnd, 2048, 0, 1); - } - - private static Vector4[] GenerateRandomVectorArray(Random rnd, int length, float minVal, float maxVal) - { - Vector4[] values = new Vector4[length]; - - for (int i = 0; i < length; i++) - { - ref Vector4 v = ref values[i]; - v.X = GetRandomFloat(rnd, minVal, maxVal); - v.Y = GetRandomFloat(rnd, minVal, maxVal); - v.Z = GetRandomFloat(rnd, minVal, maxVal); - v.W = GetRandomFloat(rnd, minVal, maxVal); - } - - return values; - } - - private static float GetRandomFloat(Random rnd, float minVal, float maxVal) - => ((float)rnd.NextDouble() * (maxVal - minVal)) + minVal; } diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/Rgb24Bytes.cs b/tests/ImageSharp.Benchmarks/Bulk/Rgb24Bytes.cs similarity index 96% rename from tests/ImageSharp.Benchmarks/Color/Bulk/Rgb24Bytes.cs rename to tests/ImageSharp.Benchmarks/Bulk/Rgb24Bytes.cs index 1795ac30b..8dd2edf00 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/Rgb24Bytes.cs +++ b/tests/ImageSharp.Benchmarks/Bulk/Rgb24Bytes.cs @@ -7,7 +7,7 @@ using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; // ReSharper disable InconsistentNaming -namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk; +namespace SixLabors.ImageSharp.Benchmarks.Bulk; public abstract class Rgb24Bytes where TPixel : unmanaged, IPixel diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/Shuffle3Channel.cs b/tests/ImageSharp.Benchmarks/Bulk/Shuffle3Channel.cs similarity index 99% rename from tests/ImageSharp.Benchmarks/Color/Bulk/Shuffle3Channel.cs rename to tests/ImageSharp.Benchmarks/Bulk/Shuffle3Channel.cs index fcde0ea1b..8b7b89eb3 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/Shuffle3Channel.cs +++ b/tests/ImageSharp.Benchmarks/Bulk/Shuffle3Channel.cs @@ -3,7 +3,7 @@ using BenchmarkDotNet.Attributes; -namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk; +namespace SixLabors.ImageSharp.Benchmarks.Bulk; [Config(typeof(Config.HwIntrinsics_SSE_AVX))] public class Shuffle3Channel diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/Shuffle4Slice3Channel.cs b/tests/ImageSharp.Benchmarks/Bulk/Shuffle4Slice3Channel.cs similarity index 99% rename from tests/ImageSharp.Benchmarks/Color/Bulk/Shuffle4Slice3Channel.cs rename to tests/ImageSharp.Benchmarks/Bulk/Shuffle4Slice3Channel.cs index ef01185f9..5ade55c73 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/Shuffle4Slice3Channel.cs +++ b/tests/ImageSharp.Benchmarks/Bulk/Shuffle4Slice3Channel.cs @@ -3,7 +3,7 @@ using BenchmarkDotNet.Attributes; -namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk; +namespace SixLabors.ImageSharp.Benchmarks.Bulk; [Config(typeof(Config.HwIntrinsics_SSE_AVX))] public class Shuffle4Slice3Channel diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/ShuffleByte4Channel.cs b/tests/ImageSharp.Benchmarks/Bulk/ShuffleByte4Channel.cs similarity index 99% rename from tests/ImageSharp.Benchmarks/Color/Bulk/ShuffleByte4Channel.cs rename to tests/ImageSharp.Benchmarks/Bulk/ShuffleByte4Channel.cs index 8e740743b..911c4e0a5 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/ShuffleByte4Channel.cs +++ b/tests/ImageSharp.Benchmarks/Bulk/ShuffleByte4Channel.cs @@ -3,7 +3,7 @@ using BenchmarkDotNet.Attributes; -namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk; +namespace SixLabors.ImageSharp.Benchmarks.Bulk; [Config(typeof(Config.HwIntrinsics_SSE_AVX))] public class ShuffleByte4Channel diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/ShuffleFloat4Channel.cs b/tests/ImageSharp.Benchmarks/Bulk/ShuffleFloat4Channel.cs similarity index 99% rename from tests/ImageSharp.Benchmarks/Color/Bulk/ShuffleFloat4Channel.cs rename to tests/ImageSharp.Benchmarks/Bulk/ShuffleFloat4Channel.cs index 1c338e1a6..5bb3cf916 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/ShuffleFloat4Channel.cs +++ b/tests/ImageSharp.Benchmarks/Bulk/ShuffleFloat4Channel.cs @@ -4,7 +4,7 @@ using BenchmarkDotNet.Attributes; using SixLabors.ImageSharp.Tests; -namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk; +namespace SixLabors.ImageSharp.Benchmarks.Bulk; [Config(typeof(Config.HwIntrinsics_SSE_AVX))] public class ShuffleFloat4Channel diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/ToRgba32Bytes.cs b/tests/ImageSharp.Benchmarks/Bulk/ToRgba32Bytes.cs similarity index 97% rename from tests/ImageSharp.Benchmarks/Color/Bulk/ToRgba32Bytes.cs rename to tests/ImageSharp.Benchmarks/Bulk/ToRgba32Bytes.cs index b6e069673..6d3f8f952 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/ToRgba32Bytes.cs +++ b/tests/ImageSharp.Benchmarks/Bulk/ToRgba32Bytes.cs @@ -8,7 +8,7 @@ using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; // ReSharper disable InconsistentNaming -namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk; +namespace SixLabors.ImageSharp.Benchmarks.Bulk; public abstract class ToRgba32Bytes where TPixel : unmanaged, IPixel diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4.cs b/tests/ImageSharp.Benchmarks/Bulk/ToVector4.cs similarity index 96% rename from tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4.cs rename to tests/ImageSharp.Benchmarks/Bulk/ToVector4.cs index 31dfd0be9..3b4360b16 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4.cs +++ b/tests/ImageSharp.Benchmarks/Bulk/ToVector4.cs @@ -9,7 +9,7 @@ using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; // ReSharper disable InconsistentNaming -namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk; +namespace SixLabors.ImageSharp.Benchmarks.Bulk; public abstract class ToVector4 where TPixel : unmanaged, IPixel diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Bgra32.cs b/tests/ImageSharp.Benchmarks/Bulk/ToVector4_Bgra32.cs similarity index 98% rename from tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Bgra32.cs rename to tests/ImageSharp.Benchmarks/Bulk/ToVector4_Bgra32.cs index b2f12cf9d..2f1064439 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Bgra32.cs +++ b/tests/ImageSharp.Benchmarks/Bulk/ToVector4_Bgra32.cs @@ -6,7 +6,7 @@ using BenchmarkDotNet.Attributes; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; -namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk; +namespace SixLabors.ImageSharp.Benchmarks.Bulk; [Config(typeof(Config.ShortMultiFramework))] public class ToVector4_Bgra32 : ToVector4 diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Rgb24.cs b/tests/ImageSharp.Benchmarks/Bulk/ToVector4_Rgb24.cs similarity index 98% rename from tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Rgb24.cs rename to tests/ImageSharp.Benchmarks/Bulk/ToVector4_Rgb24.cs index f22868335..2c700a733 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Rgb24.cs +++ b/tests/ImageSharp.Benchmarks/Bulk/ToVector4_Rgb24.cs @@ -6,7 +6,7 @@ using BenchmarkDotNet.Attributes; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; -namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk; +namespace SixLabors.ImageSharp.Benchmarks.Bulk; [Config(typeof(Config.ShortMultiFramework))] public class ToVector4_Rgb24 : ToVector4 diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Rgba32.cs b/tests/ImageSharp.Benchmarks/Bulk/ToVector4_Rgba32.cs similarity index 99% rename from tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Rgba32.cs rename to tests/ImageSharp.Benchmarks/Bulk/ToVector4_Rgba32.cs index 6c2860516..b0eb6b46d 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4_Rgba32.cs +++ b/tests/ImageSharp.Benchmarks/Bulk/ToVector4_Rgba32.cs @@ -9,7 +9,7 @@ using BenchmarkDotNet.Attributes; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; -namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk; +namespace SixLabors.ImageSharp.Benchmarks.Bulk; [Config(typeof(Config.ShortCore31))] public class ToVector4_Rgba32 : ToVector4 diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/UnPremultiplyVector4.cs b/tests/ImageSharp.Benchmarks/Bulk/UnPremultiplyVector4.cs similarity index 55% rename from tests/ImageSharp.Benchmarks/Color/Bulk/UnPremultiplyVector4.cs rename to tests/ImageSharp.Benchmarks/Bulk/UnPremultiplyVector4.cs index c2b371b8a..3dc8fdc9c 100644 --- a/tests/ImageSharp.Benchmarks/Color/Bulk/UnPremultiplyVector4.cs +++ b/tests/ImageSharp.Benchmarks/Bulk/UnPremultiplyVector4.cs @@ -6,11 +6,11 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using BenchmarkDotNet.Attributes; -namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk; +namespace SixLabors.ImageSharp.Benchmarks.Bulk; public class UnPremultiplyVector4 { - private static readonly Vector4[] Vectors = CreateVectors(); + private static readonly Vector4[] Vectors = Vector4Factory.CreateVectors(); [Benchmark(Baseline = true)] public void UnPremultiplyBaseline() @@ -47,29 +47,4 @@ public class UnPremultiplyVector4 source /= w; source.W = w; } - - private static Vector4[] CreateVectors() - { - Random rnd = new(42); - return GenerateRandomVectorArray(rnd, 2048, 0, 1); - } - - private static Vector4[] GenerateRandomVectorArray(Random rnd, int length, float minVal, float maxVal) - { - Vector4[] values = new Vector4[length]; - - for (int i = 0; i < length; i++) - { - ref Vector4 v = ref values[i]; - v.X = GetRandomFloat(rnd, minVal, maxVal); - v.Y = GetRandomFloat(rnd, minVal, maxVal); - v.Z = GetRandomFloat(rnd, minVal, maxVal); - v.W = GetRandomFloat(rnd, minVal, maxVal); - } - - return values; - } - - private static float GetRandomFloat(Random rnd, float minVal, float maxVal) - => ((float)rnd.NextDouble() * (maxVal - minVal)) + minVal; } diff --git a/tests/ImageSharp.Benchmarks/Bulk/Vector4Factory.cs b/tests/ImageSharp.Benchmarks/Bulk/Vector4Factory.cs new file mode 100644 index 000000000..aa555f5c4 --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Bulk/Vector4Factory.cs @@ -0,0 +1,34 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +using System.Numerics; + +namespace SixLabors.ImageSharp.Benchmarks.Bulk; + +internal static class Vector4Factory +{ + public static Vector4[] CreateVectors(int length = 2048, int min = 0, int max = 1) + { + Random rnd = new(42); + return GenerateRandomVectorArray(rnd, length, min, max); + } + + private static Vector4[] GenerateRandomVectorArray(Random rnd, int length, float minVal, float maxVal) + { + Vector4[] values = new Vector4[length]; + + for (int i = 0; i < length; i++) + { + ref Vector4 v = ref values[i]; + v.X = GetRandomFloat(rnd, minVal, maxVal); + v.Y = GetRandomFloat(rnd, minVal, maxVal); + v.Z = GetRandomFloat(rnd, minVal, maxVal); + v.W = GetRandomFloat(rnd, minVal, maxVal); + } + + return values; + } + + private static float GetRandomFloat(Random rnd, float minVal, float maxVal) + => (float)rnd.NextDouble() * (maxVal - minVal) + minVal; +} diff --git a/tests/ImageSharp.Benchmarks/General/GetSetPixel.cs b/tests/ImageSharp.Benchmarks/General/GetSetPixel.cs index 50a628ee3..a6aac20c3 100644 --- a/tests/ImageSharp.Benchmarks/General/GetSetPixel.cs +++ b/tests/ImageSharp.Benchmarks/General/GetSetPixel.cs @@ -12,7 +12,7 @@ public class GetSetPixel [Benchmark(Baseline = true, Description = "System.Drawing GetSet pixel")] public System.Drawing.Color GetSetSystemDrawing() { - using var source = new Bitmap(400, 400); + using Bitmap source = new(400, 400); source.SetPixel(200, 200, System.Drawing.Color.White); return source.GetPixel(200, 200); } @@ -20,7 +20,7 @@ public class GetSetPixel [Benchmark(Description = "ImageSharp GetSet pixel")] public Rgba32 GetSetImageSharp() { - using var image = new Image(400, 400); + using Image image = new(400, 400); image[200, 200] = Color.White; return image[200, 200]; } diff --git a/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj b/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj index 24f618d11..0ba2f4b94 100644 --- a/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj +++ b/tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj @@ -11,7 +11,13 @@ false Debug;Release - + + + + + + + CA1822 @@ -53,7 +59,7 @@ - + diff --git a/tests/ImageSharp.Benchmarks/Processing/BokehBlur.cs b/tests/ImageSharp.Benchmarks/Processing/BokehBlur.cs index 2bfc43758..441500c88 100644 --- a/tests/ImageSharp.Benchmarks/Processing/BokehBlur.cs +++ b/tests/ImageSharp.Benchmarks/Processing/BokehBlur.cs @@ -13,7 +13,7 @@ public class BokehBlur [Benchmark] public void Blur() { - using var image = new Image(Configuration.Default, 400, 400, Color.White); + using Image image = new(Configuration.Default, 400, 400, Color.White); image.Mutate(c => c.BokehBlur()); } } diff --git a/tests/ImageSharp.Tests/Primitives/ColorMatrixTests.cs b/tests/ImageSharp.Tests/Primitives/ColorMatrixTests.cs index 94309d200..9c0e83a7f 100644 --- a/tests/ImageSharp.Tests/Primitives/ColorMatrixTests.cs +++ b/tests/ImageSharp.Tests/Primitives/ColorMatrixTests.cs @@ -2,6 +2,7 @@ // Licensed under the Six Labors Split License. using System.Globalization; +using System.Numerics; using SixLabors.ImageSharp.Processing; namespace SixLabors.ImageSharp.Tests.Primitives; @@ -115,27 +116,21 @@ public class ColorMatrixTests public void ColorMatrixHashCode() { ColorMatrix m = KnownFilterMatrices.CreateBrightnessFilter(.5F); + HashCode hash = default; - hash.Add(m.M11); - hash.Add(m.M12); - hash.Add(m.M13); - hash.Add(m.M14); - hash.Add(m.M21); - hash.Add(m.M22); - hash.Add(m.M23); - hash.Add(m.M24); - hash.Add(m.M31); - hash.Add(m.M32); - hash.Add(m.M33); - hash.Add(m.M34); - hash.Add(m.M41); - hash.Add(m.M42); - hash.Add(m.M43); - hash.Add(m.M44); - hash.Add(m.M51); - hash.Add(m.M52); - hash.Add(m.M53); - hash.Add(m.M54); + + Vector4 x = new(m.M11, m.M12, m.M13, m.M14); + Vector4 y = new(m.M21, m.M22, m.M23, m.M24); + Vector4 z = new(m.M31, m.M32, m.M33, m.M34); + Vector4 w = new(m.M41, m.M42, m.M43, m.M44); + Vector4 v = new(m.M51, m.M52, m.M53, m.M54); + + hash.Add(x); + hash.Add(y); + hash.Add(z); + hash.Add(w); + hash.Add(v); + Assert.Equal(hash.ToHashCode(), m.GetHashCode()); }