diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml
index b618e1e65..04b1d745f 100644
--- a/.github/workflows/build-and-test.yml
+++ b/.github/workflows/build-and-test.yml
@@ -56,6 +56,14 @@ jobs:
git fetch --prune --unshallow
git submodule -q update --init --recursive
+ - name: Setup nuget cache
+ uses: actions/cache@v2
+ id: nuget-cache
+ with:
+ path: ~/.nuget
+ key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/*.props', '**/*.targets') }}
+ restore-keys: ${{ runner.os }}-nuget-
+
- name: Build
shell: pwsh
run: ./ci-build.ps1 "${{matrix.options.framework}}"
diff --git a/.gitignore b/.gitignore
index a89cfcf10..475d6e76b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -221,3 +221,4 @@ artifacts/
# Tests
**/Images/ActualOutput
**/Images/ReferenceOutput
+.DS_Store
diff --git a/src/ImageSharp/Color/Color.cs b/src/ImageSharp/Color/Color.cs
index 554fcb835..72f16528a 100644
--- a/src/ImageSharp/Color/Color.cs
+++ b/src/ImageSharp/Color/Color.cs
@@ -27,19 +27,19 @@ namespace SixLabors.ImageSharp
private Color(byte r, byte g, byte b, byte a)
{
this.data = new Rgba64(
- ImageMaths.UpscaleFrom8BitTo16Bit(r),
- ImageMaths.UpscaleFrom8BitTo16Bit(g),
- ImageMaths.UpscaleFrom8BitTo16Bit(b),
- ImageMaths.UpscaleFrom8BitTo16Bit(a));
+ ColorNumerics.UpscaleFrom8BitTo16Bit(r),
+ ColorNumerics.UpscaleFrom8BitTo16Bit(g),
+ ColorNumerics.UpscaleFrom8BitTo16Bit(b),
+ ColorNumerics.UpscaleFrom8BitTo16Bit(a));
}
[MethodImpl(InliningOptions.ShortMethod)]
private Color(byte r, byte g, byte b)
{
this.data = new Rgba64(
- ImageMaths.UpscaleFrom8BitTo16Bit(r),
- ImageMaths.UpscaleFrom8BitTo16Bit(g),
- ImageMaths.UpscaleFrom8BitTo16Bit(b),
+ ColorNumerics.UpscaleFrom8BitTo16Bit(r),
+ ColorNumerics.UpscaleFrom8BitTo16Bit(g),
+ ColorNumerics.UpscaleFrom8BitTo16Bit(b),
ushort.MaxValue);
}
diff --git a/src/ImageSharp/ColorSpaces/Cmyk.cs b/src/ImageSharp/ColorSpaces/Cmyk.cs
index 0aab29554..675f1f814 100644
--- a/src/ImageSharp/ColorSpaces/Cmyk.cs
+++ b/src/ImageSharp/ColorSpaces/Cmyk.cs
@@ -59,7 +59,7 @@ namespace SixLabors.ImageSharp.ColorSpaces
[MethodImpl(InliningOptions.ShortMethod)]
public Cmyk(Vector4 vector)
{
- vector = Vector4Utilities.FastClamp(vector, Min, Max);
+ vector = Numerics.Clamp(vector, Min, Max);
this.C = vector.X;
this.M = vector.Y;
this.Y = vector.Z;
diff --git a/src/ImageSharp/ColorSpaces/Companding/LCompanding.cs b/src/ImageSharp/ColorSpaces/Companding/LCompanding.cs
index 719565fd8..5cd89abfd 100644
--- a/src/ImageSharp/ColorSpaces/Companding/LCompanding.cs
+++ b/src/ImageSharp/ColorSpaces/Companding/LCompanding.cs
@@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding
/// The representing the linear channel value.
[MethodImpl(InliningOptions.ShortMethod)]
public static float Expand(float channel)
- => channel <= 0.08F ? (100F * channel) / CieConstants.Kappa : ImageMaths.Pow3((channel + 0.16F) / 1.16F);
+ => channel <= 0.08F ? (100F * channel) / CieConstants.Kappa : Numerics.Pow3((channel + 0.16F) / 1.16F);
///
/// Compresses an uncompanded channel (linear) to its nonlinear equivalent.
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieXyzConverter.cs
index 31c3f4633..34354efe5 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieXyzConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieXyzConverter.cs
@@ -25,11 +25,11 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
float fx = (a / 500F) + fy;
float fz = fy - (b / 200F);
- float fx3 = ImageMaths.Pow3(fx);
- float fz3 = ImageMaths.Pow3(fz);
+ float fx3 = Numerics.Pow3(fx);
+ float fz3 = Numerics.Pow3(fz);
float xr = fx3 > CieConstants.Epsilon ? fx3 : ((116F * fx) - 16F) / CieConstants.Kappa;
- float yr = l > CieConstants.Kappa * CieConstants.Epsilon ? ImageMaths.Pow3((l + 16F) / 116F) : l / CieConstants.Kappa;
+ float yr = l > CieConstants.Kappa * CieConstants.Epsilon ? Numerics.Pow3((l + 16F) / 116F) : l / CieConstants.Kappa;
float zr = fz3 > CieConstants.Epsilon ? fz3 : ((116F * fz) - 16F) / CieConstants.Kappa;
var wxyz = new Vector3(input.WhitePoint.X, input.WhitePoint.Y, input.WhitePoint.Z);
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieXyzConverter.cs
index 7f15fc77d..12c65105f 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieXyzConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieXyzConverter.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Six Labors.
+// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System.Runtime.CompilerServices;
@@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
float v0 = ComputeV0(input.WhitePoint);
float y = l > CieConstants.Kappa * CieConstants.Epsilon
- ? ImageMaths.Pow3((l + 16) / 116)
+ ? Numerics.Pow3((l + 16) / 116)
: l / CieConstants.Kappa;
float a = ((52 * l / (u + (13 * l * u0))) - 1) / 3;
@@ -71,4 +71,4 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
private static float ComputeV0(in CieXyz input)
=> (9 * input.Y) / (input.X + (15 * input.Y) + (3 * input.Z));
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HunterLabToCieXyzConverter.cs b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HunterLabToCieXyzConverter.cs
index 4c3cdba22..f120d6f3d 100644
--- a/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HunterLabToCieXyzConverter.cs
+++ b/src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HunterLabToCieXyzConverter.cs
@@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion
float ka = ComputeKa(input.WhitePoint);
float kb = ComputeKb(input.WhitePoint);
- float pow = ImageMaths.Pow2(l / 100F);
+ float pow = Numerics.Pow2(l / 100F);
float sqrtPow = MathF.Sqrt(pow);
float y = pow * yn;
diff --git a/src/ImageSharp/Common/Extensions/ComparableExtensions.cs b/src/ImageSharp/Common/Extensions/ComparableExtensions.cs
deleted file mode 100644
index ef3d1deac..000000000
--- a/src/ImageSharp/Common/Extensions/ComparableExtensions.cs
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using System.Runtime.CompilerServices;
-
-namespace SixLabors.ImageSharp
-{
- ///
- /// Extension methods for classes that implement .
- ///
- internal static class ComparableExtensions
- {
- ///
- /// Restricts a to be within a specified range.
- ///
- /// The value to clamp.
- /// The minimum value. If value is less than min, min will be returned.
- /// The maximum value. If value is greater than max, max will be returned.
- ///
- /// The representing the clamped value.
- ///
- [MethodImpl(InliningOptions.ShortMethod)]
- public static byte Clamp(this byte value, byte min, byte max)
- {
- // Order is important here as someone might set min to higher than max.
- if (value >= max)
- {
- return max;
- }
-
- if (value <= min)
- {
- return min;
- }
-
- return value;
- }
-
- ///
- /// Restricts a to be within a specified range.
- ///
- /// The The value to clamp.
- /// The minimum value. If value is less than min, min will be returned.
- /// The maximum value. If value is greater than max, max will be returned.
- ///
- /// The representing the clamped value.
- ///
- [MethodImpl(InliningOptions.ShortMethod)]
- public static uint Clamp(this uint value, uint min, uint max)
- {
- if (value >= max)
- {
- return max;
- }
-
- if (value <= min)
- {
- return min;
- }
-
- return value;
- }
-
- ///
- /// Restricts a to be within a specified range.
- ///
- /// The The value to clamp.
- /// The minimum value. If value is less than min, min will be returned.
- /// The maximum value. If value is greater than max, max will be returned.
- ///
- /// The representing the clamped value.
- ///
- [MethodImpl(InliningOptions.ShortMethod)]
- public static int Clamp(this int value, int min, int max)
- {
- if (value >= max)
- {
- return max;
- }
-
- if (value <= min)
- {
- return min;
- }
-
- return value;
- }
-
- ///
- /// Restricts a to be within a specified range.
- ///
- /// The The value to clamp.
- /// The minimum value. If value is less than min, min will be returned.
- /// The maximum value. If value is greater than max, max will be returned.
- ///
- /// The representing the clamped value.
- ///
- [MethodImpl(InliningOptions.ShortMethod)]
- public static float Clamp(this float value, float min, float max)
- {
- if (value >= max)
- {
- return max;
- }
-
- if (value <= min)
- {
- return min;
- }
-
- return value;
- }
-
- ///
- /// Restricts a to be within a specified range.
- ///
- /// The The value to clamp.
- /// The minimum value. If value is less than min, min will be returned.
- /// The maximum value. If value is greater than max, max will be returned.
- ///
- /// The representing the clamped value.
- ///
- [MethodImpl(InliningOptions.ShortMethod)]
- public static double Clamp(this double value, double min, double max)
- {
- if (value >= max)
- {
- return max;
- }
-
- if (value <= min)
- {
- return min;
- }
-
- return value;
- }
- }
-}
diff --git a/src/ImageSharp/Common/Helpers/Buffer2DUtils.cs b/src/ImageSharp/Common/Helpers/Buffer2DUtils.cs
index f4811d6ca..02a5afff7 100644
--- a/src/ImageSharp/Common/Helpers/Buffer2DUtils.cs
+++ b/src/ImageSharp/Common/Helpers/Buffer2DUtils.cs
@@ -50,8 +50,8 @@ namespace SixLabors.ImageSharp
for (int i = 0; i < kernelLength; i++)
{
- int offsetY = (row + i - radiusY).Clamp(minRow, maxRow);
- int offsetX = sourceOffsetColumnBase.Clamp(minColumn, maxColumn);
+ int offsetY = Numerics.Clamp(row + i - radiusY, minRow, maxRow);
+ int offsetX = Numerics.Clamp(sourceOffsetColumnBase, minColumn, maxColumn);
Span sourceRowSpan = sourcePixels.GetRowSpan(offsetY);
var currentColor = sourceRowSpan[offsetX].ToVector4();
@@ -93,13 +93,13 @@ namespace SixLabors.ImageSharp
int radiusX = kernelLength >> 1;
int sourceOffsetColumnBase = column + minColumn;
- int offsetY = row.Clamp(minRow, maxRow);
+ int offsetY = Numerics.Clamp(row, minRow, maxRow);
ref ComplexVector4 sourceRef = ref MemoryMarshal.GetReference(sourceValues.GetRowSpan(offsetY));
ref Complex64 baseRef = ref MemoryMarshal.GetReference(kernel);
for (int x = 0; x < kernelLength; x++)
{
- int offsetX = (sourceOffsetColumnBase + x - radiusX).Clamp(minColumn, maxColumn);
+ int offsetX = Numerics.Clamp(sourceOffsetColumnBase + x - radiusX, minColumn, maxColumn);
vector.Sum(Unsafe.Add(ref baseRef, x) * Unsafe.Add(ref sourceRef, offsetX));
}
diff --git a/src/ImageSharp/Common/Helpers/ColorNumerics.cs b/src/ImageSharp/Common/Helpers/ColorNumerics.cs
new file mode 100644
index 000000000..6f225b110
--- /dev/null
+++ b/src/ImageSharp/Common/Helpers/ColorNumerics.cs
@@ -0,0 +1,177 @@
+// Copyright (c) Six Labors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
+using System.Numerics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+namespace SixLabors.ImageSharp
+{
+ ///
+ /// Provides optimized static methods for common mathematical functions specific
+ /// to color processing.
+ ///
+ 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);
+
+ ///
+ /// Convert a pixel value to grayscale using ITU-R Recommendation BT.709.
+ ///
+ /// The vector to get the luminance from.
+ ///
+ /// The number of luminance levels (256 for 8 bit, 65536 for 16 bit grayscale images).
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int GetBT709Luminance(ref Vector4 vector, int luminanceLevels)
+ => (int)MathF.Round(Vector4.Dot(vector, Bt709) * (luminanceLevels - 1));
+
+ ///
+ /// Gets the luminance from the rgb components using the formula
+ /// as specified by ITU-R Recommendation BT.709.
+ ///
+ /// The red component.
+ /// The green component.
+ /// The blue component.
+ /// The .
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static byte Get8BitBT709Luminance(byte r, byte g, byte b)
+ => (byte)((r * .2126F) + (g * .7152F) + (b * .0722F) + 0.5F);
+
+ ///
+ /// Gets the luminance from the rgb components using the formula as
+ /// specified by ITU-R Recommendation BT.709.
+ ///
+ /// The red component.
+ /// The green component.
+ /// The blue component.
+ /// The .
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ushort Get16BitBT709Luminance(ushort r, ushort g, ushort b)
+ => (ushort)((r * .2126F) + (g * .7152F) + (b * .0722F) + 0.5F);
+
+ ///
+ /// Gets the luminance from the rgb components using the formula as specified
+ /// by ITU-R Recommendation BT.709.
+ ///
+ /// The red component.
+ /// The green component.
+ /// The blue component.
+ /// The .
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ushort Get16BitBT709Luminance(float r, float g, float b)
+ => (ushort)((r * .2126F) + (g * .7152F) + (b * .0722F) + 0.5F);
+
+ ///
+ /// Scales a value from a 16 bit to an
+ /// 8 bit equivalent.
+ ///
+ /// The 8 bit component value.
+ /// The
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static byte DownScaleFrom16BitTo8Bit(ushort component)
+ {
+ // To scale to 8 bits From a 16-bit value V the required value (from the PNG specification) is:
+ //
+ // (V * 255) / 65535
+ //
+ // This reduces to round(V / 257), or floor((V + 128.5)/257)
+ //
+ // Represent V as the two byte value vhi.vlo. Make a guess that the
+ // result is the top byte of V, vhi, then the correction to this value
+ // is:
+ //
+ // error = floor(((V-vhi.vhi) + 128.5) / 257)
+ // = floor(((vlo-vhi) + 128.5) / 257)
+ //
+ // This can be approximated using integer arithmetic (and a signed
+ // shift):
+ //
+ // error = (vlo-vhi+128) >> 8;
+ //
+ // The approximate differs from the exact answer only when (vlo-vhi) is
+ // 128; it then gives a correction of +1 when the exact correction is
+ // 0. This gives 128 errors. The exact answer (correct for all 16-bit
+ // input values) is:
+ //
+ // error = (vlo-vhi+128)*65535 >> 24;
+ //
+ // An alternative arithmetic calculation which also gives no errors is:
+ //
+ // (V * 255 + 32895) >> 16
+ return (byte)(((component * 255) + 32895) >> 16);
+ }
+
+ ///
+ /// Scales a value from an 8 bit to
+ /// an 16 bit equivalent.
+ ///
+ /// The 8 bit component value.
+ /// The
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ushort UpscaleFrom8BitTo16Bit(byte component)
+ => (ushort)(component * 257);
+
+ ///
+ /// Returns how many bits are required to store the specified number of colors.
+ /// Performs a Log2() on the value.
+ ///
+ /// The number of colors.
+ ///
+ /// The
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int GetBitsNeededForColorDepth(int colors)
+ => Math.Max(1, (int)Math.Ceiling(Math.Log(colors, 2)));
+
+ ///
+ /// Returns how many colors will be created by the specified number of bits.
+ ///
+ /// The bit depth.
+ /// The
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int GetColorCountForBitDepth(int bitDepth)
+ => 1 << bitDepth;
+
+ ///
+ /// Transforms a vector by the given color matrix.
+ ///
+ /// The source vector.
+ /// 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;
+ }
+
+ ///
+ /// Bulk variant of .
+ ///
+ /// The span of vectors
+ /// The transformation color matrix.
+ [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);
+ Transform(ref v, ref matrix);
+ }
+ }
+ }
+}
diff --git a/src/ImageSharp/Common/Helpers/DenseMatrixUtils.cs b/src/ImageSharp/Common/Helpers/DenseMatrixUtils.cs
index 61f90e23e..f265bdd51 100644
--- a/src/ImageSharp/Common/Helpers/DenseMatrixUtils.cs
+++ b/src/ImageSharp/Common/Helpers/DenseMatrixUtils.cs
@@ -59,7 +59,7 @@ namespace SixLabors.ImageSharp
ref Vector4 target = ref Unsafe.Add(ref targetRowRef, column);
vector.W = target.W;
- Vector4Utilities.UnPremultiply(ref vector);
+ Numerics.UnPremultiply(ref vector);
target = vector;
}
@@ -105,7 +105,7 @@ namespace SixLabors.ImageSharp
out Vector4 vector);
ref Vector4 target = ref Unsafe.Add(ref targetRowRef, column);
- Vector4Utilities.UnPremultiply(ref vector);
+ Numerics.UnPremultiply(ref vector);
target = vector;
}
@@ -133,14 +133,14 @@ namespace SixLabors.ImageSharp
for (int y = 0; y < matrixHeight; y++)
{
- int offsetY = (row + y - radiusY).Clamp(minRow, maxRow);
+ int offsetY = Numerics.Clamp(row + y - radiusY, minRow, maxRow);
Span sourceRowSpan = sourcePixels.GetRowSpan(offsetY);
for (int x = 0; x < matrixWidth; x++)
{
- int offsetX = (sourceOffsetColumnBase + x - radiusX).Clamp(minColumn, maxColumn);
+ int offsetX = Numerics.Clamp(sourceOffsetColumnBase + x - radiusX, minColumn, maxColumn);
var currentColor = sourceRowSpan[offsetX].ToVector4();
- Vector4Utilities.Premultiply(ref currentColor);
+ Numerics.Premultiply(ref currentColor);
vectorX += matrixX[y, x] * currentColor;
vectorY += matrixY[y, x] * currentColor;
@@ -193,7 +193,7 @@ namespace SixLabors.ImageSharp
ref Vector4 target = ref Unsafe.Add(ref targetRowRef, column);
vector.W = target.W;
- Vector4Utilities.UnPremultiply(ref vector);
+ Numerics.UnPremultiply(ref vector);
target = vector;
}
@@ -238,7 +238,7 @@ namespace SixLabors.ImageSharp
ref vector);
ref Vector4 target = ref Unsafe.Add(ref targetRowRef, column);
- Vector4Utilities.UnPremultiply(ref vector);
+ Numerics.UnPremultiply(ref vector);
target = vector;
}
@@ -263,14 +263,14 @@ namespace SixLabors.ImageSharp
for (int y = 0; y < matrixHeight; y++)
{
- int offsetY = (row + y - radiusY).Clamp(minRow, maxRow);
+ int offsetY = Numerics.Clamp(row + y - radiusY, minRow, maxRow);
Span sourceRowSpan = sourcePixels.GetRowSpan(offsetY);
for (int x = 0; x < matrixWidth; x++)
{
- int offsetX = (sourceOffsetColumnBase + x - radiusX).Clamp(minColumn, maxColumn);
+ int offsetX = Numerics.Clamp(sourceOffsetColumnBase + x - radiusX, minColumn, maxColumn);
var currentColor = sourceRowSpan[offsetX].ToVector4();
- Vector4Utilities.Premultiply(ref currentColor);
+ Numerics.Premultiply(ref currentColor);
vector += matrix[y, x] * currentColor;
}
}
diff --git a/src/ImageSharp/Common/Helpers/ImageMaths.cs b/src/ImageSharp/Common/Helpers/ImageMaths.cs
deleted file mode 100644
index d24230fe1..000000000
--- a/src/ImageSharp/Common/Helpers/ImageMaths.cs
+++ /dev/null
@@ -1,379 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using System.Numerics;
-using System.Runtime.CompilerServices;
-
-using SixLabors.ImageSharp.PixelFormats;
-
-namespace SixLabors.ImageSharp
-{
- ///
- /// Provides common mathematical methods.
- ///
- internal static class ImageMaths
- {
- ///
- /// 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);
-
- ///
- /// Convert a pixel value to grayscale using ITU-R Recommendation BT.709.
- ///
- /// The vector to get the luminance from.
- /// The number of luminance levels (256 for 8 bit, 65536 for 16 bit grayscale images)
- [MethodImpl(InliningOptions.ShortMethod)]
- public static int GetBT709Luminance(ref Vector4 vector, int luminanceLevels)
- => (int)MathF.Round(Vector4.Dot(vector, Bt709) * (luminanceLevels - 1));
-
- ///
- /// Gets the luminance from the rgb components using the formula as specified by ITU-R Recommendation BT.709.
- ///
- /// The red component.
- /// The green component.
- /// The blue component.
- /// The .
- [MethodImpl(InliningOptions.ShortMethod)]
- public static byte Get8BitBT709Luminance(byte r, byte g, byte b) =>
- (byte)((r * .2126F) + (g * .7152F) + (b * .0722F) + 0.5F);
-
- ///
- /// Gets the luminance from the rgb components using the formula as specified by ITU-R Recommendation BT.709.
- ///
- /// The red component.
- /// The green component.
- /// The blue component.
- /// The .
- [MethodImpl(InliningOptions.ShortMethod)]
- public static ushort Get16BitBT709Luminance(ushort r, ushort g, ushort b) =>
- (ushort)((r * .2126F) + (g * .7152F) + (b * .0722F) + 0.5F);
-
- ///
- /// Gets the luminance from the rgb components using the formula as specified by ITU-R Recommendation BT.709.
- ///
- /// The red component.
- /// The green component.
- /// The blue component.
- /// The .
- [MethodImpl(InliningOptions.ShortMethod)]
- public static ushort Get16BitBT709Luminance(float r, float g, float b) =>
- (ushort)((r * .2126F) + (g * .7152F) + (b * .0722F) + 0.5F);
-
- ///
- /// Scales a value from a 16 bit to it's 8 bit equivalent.
- ///
- /// The 8 bit component value.
- /// The
- [MethodImpl(InliningOptions.ShortMethod)]
- public static byte DownScaleFrom16BitTo8Bit(ushort component)
- {
- // To scale to 8 bits From a 16-bit value V the required value (from the PNG specification) is:
- //
- // (V * 255) / 65535
- //
- // This reduces to round(V / 257), or floor((V + 128.5)/257)
- //
- // Represent V as the two byte value vhi.vlo. Make a guess that the
- // result is the top byte of V, vhi, then the correction to this value
- // is:
- //
- // error = floor(((V-vhi.vhi) + 128.5) / 257)
- // = floor(((vlo-vhi) + 128.5) / 257)
- //
- // This can be approximated using integer arithmetic (and a signed
- // shift):
- //
- // error = (vlo-vhi+128) >> 8;
- //
- // The approximate differs from the exact answer only when (vlo-vhi) is
- // 128; it then gives a correction of +1 when the exact correction is
- // 0. This gives 128 errors. The exact answer (correct for all 16-bit
- // input values) is:
- //
- // error = (vlo-vhi+128)*65535 >> 24;
- //
- // An alternative arithmetic calculation which also gives no errors is:
- //
- // (V * 255 + 32895) >> 16
- return (byte)(((component * 255) + 32895) >> 16);
- }
-
- ///
- /// Scales a value from an 8 bit to it's 16 bit equivalent.
- ///
- /// The 8 bit component value.
- /// The
- [MethodImpl(InliningOptions.ShortMethod)]
- public static ushort UpscaleFrom8BitTo16Bit(byte component) => (ushort)(component * 257);
-
- ///
- /// Determine the Greatest CommonDivisor (GCD) of two numbers.
- ///
- public static int GreatestCommonDivisor(int a, int b)
- {
- while (b != 0)
- {
- int temp = b;
- b = a % b;
- a = temp;
- }
-
- return a;
- }
-
- ///
- /// Determine the Least Common Multiple (LCM) of two numbers.
- ///
- public static int LeastCommonMultiple(int a, int b)
- {
- // https://en.wikipedia.org/wiki/Least_common_multiple#Reduction_by_the_greatest_common_divisor
- return (a / GreatestCommonDivisor(a, b)) * b;
- }
-
- ///
- /// Calculates % 2
- ///
- [MethodImpl(InliningOptions.ShortMethod)]
- public static int Modulo2(int x) => x & 1;
-
- ///
- /// Calculates % 4
- ///
- [MethodImpl(InliningOptions.ShortMethod)]
- public static int Modulo4(int x) => x & 3;
-
- ///
- /// Calculates % 8
- ///
- [MethodImpl(InliningOptions.ShortMethod)]
- public static int Modulo8(int x) => x & 7;
-
- ///
- /// Fast (x mod m) calculator, with the restriction that
- /// should be power of 2.
- ///
- [MethodImpl(InliningOptions.ShortMethod)]
- public static int ModuloP2(int x, int m) => x & (m - 1);
-
- ///
- /// Returns the absolute value of a 32-bit signed integer. Uses bit shifting to speed up the operation.
- ///
- ///
- /// A number that is greater than , but less than or equal to
- ///
- /// The
- [MethodImpl(InliningOptions.ShortMethod)]
- public static int FastAbs(int x)
- {
- int y = x >> 31;
- return (x ^ y) - y;
- }
-
- ///
- /// Returns a specified number raised to the power of 2
- ///
- /// A single-precision floating-point number
- /// The number raised to the power of 2.
- [MethodImpl(InliningOptions.ShortMethod)]
- public static float Pow2(float x) => x * x;
-
- ///
- /// Returns a specified number raised to the power of 3
- ///
- /// A single-precision floating-point number
- /// The number raised to the power of 3.
- [MethodImpl(InliningOptions.ShortMethod)]
- public static float Pow3(float x) => x * x * x;
-
- ///
- /// Returns how many bits are required to store the specified number of colors.
- /// Performs a Log2() on the value.
- ///
- /// The number of colors.
- ///
- /// The
- ///
- [MethodImpl(InliningOptions.ShortMethod)]
- public static int GetBitsNeededForColorDepth(int colors) => Math.Max(1, (int)Math.Ceiling(Math.Log(colors, 2)));
-
- ///
- /// Returns how many colors will be created by the specified number of bits.
- ///
- /// The bit depth.
- /// The
- [MethodImpl(InliningOptions.ShortMethod)]
- public static int GetColorCountForBitDepth(int bitDepth) => 1 << bitDepth;
-
- ///
- /// Implementation of 1D Gaussian G(x) function
- ///
- /// The x provided to G(x).
- /// The spread of the blur.
- /// The Gaussian G(x)
- [MethodImpl(InliningOptions.ShortMethod)]
- public static float Gaussian(float x, float sigma)
- {
- const float Numerator = 1.0f;
- float denominator = MathF.Sqrt(2 * MathF.PI) * sigma;
-
- float exponentNumerator = -x * x;
- float exponentDenominator = 2 * Pow2(sigma);
-
- float left = Numerator / denominator;
- float right = MathF.Exp(exponentNumerator / exponentDenominator);
-
- return left * right;
- }
-
- ///
- /// Returns the result of a normalized sine cardinal function for the given value.
- /// SinC(x) = sin(pi*x)/(pi*x).
- ///
- /// A single-precision floating-point number to calculate the result for.
- ///
- /// The sine cardinal of .
- ///
- [MethodImpl(InliningOptions.ShortMethod)]
- public static float SinC(float f)
- {
- if (MathF.Abs(f) > Constants.Epsilon)
- {
- f *= MathF.PI;
- float result = MathF.Sin(f) / f;
- return MathF.Abs(result) < Constants.Epsilon ? 0F : result;
- }
-
- return 1F;
- }
-
- ///
- /// Gets the bounding from the given points.
- ///
- ///
- /// The designating the top left position.
- ///
- ///
- /// The designating the bottom right position.
- ///
- ///
- /// The bounding .
- ///
- [MethodImpl(InliningOptions.ShortMethod)]
- public static Rectangle GetBoundingRectangle(Point topLeft, Point bottomRight) => new Rectangle(topLeft.X, topLeft.Y, bottomRight.X - topLeft.X, bottomRight.Y - topLeft.Y);
-
- ///
- /// Finds the bounding rectangle based on the first instance of any color component other
- /// than the given one.
- ///
- /// The pixel format.
- /// The to search within.
- /// The color component value to remove.
- /// The channel to test against.
- ///
- /// The .
- ///
- public static Rectangle GetFilteredBoundingRectangle(ImageFrame bitmap, float componentValue, RgbaComponent channel = RgbaComponent.B)
- where TPixel : unmanaged, IPixel
- {
- int width = bitmap.Width;
- int height = bitmap.Height;
- Point topLeft = default;
- Point bottomRight = default;
-
- Func, int, int, float, bool> delegateFunc;
-
- // Determine which channel to check against
- switch (channel)
- {
- case RgbaComponent.R:
- delegateFunc = (pixels, x, y, b) => MathF.Abs(pixels[x, y].ToVector4().X - b) > Constants.Epsilon;
- break;
-
- case RgbaComponent.G:
- delegateFunc = (pixels, x, y, b) => MathF.Abs(pixels[x, y].ToVector4().Y - b) > Constants.Epsilon;
- break;
-
- case RgbaComponent.B:
- delegateFunc = (pixels, x, y, b) => MathF.Abs(pixels[x, y].ToVector4().Z - b) > Constants.Epsilon;
- break;
-
- default:
- delegateFunc = (pixels, x, y, b) => MathF.Abs(pixels[x, y].ToVector4().W - b) > Constants.Epsilon;
- break;
- }
-
- int GetMinY(ImageFrame pixels)
- {
- for (int y = 0; y < height; y++)
- {
- for (int x = 0; x < width; x++)
- {
- if (delegateFunc(pixels, x, y, componentValue))
- {
- return y;
- }
- }
- }
-
- return 0;
- }
-
- int GetMaxY(ImageFrame pixels)
- {
- for (int y = height - 1; y > -1; y--)
- {
- for (int x = 0; x < width; x++)
- {
- if (delegateFunc(pixels, x, y, componentValue))
- {
- return y;
- }
- }
- }
-
- return height;
- }
-
- int GetMinX(ImageFrame pixels)
- {
- for (int x = 0; x < width; x++)
- {
- for (int y = 0; y < height; y++)
- {
- if (delegateFunc(pixels, x, y, componentValue))
- {
- return x;
- }
- }
- }
-
- return 0;
- }
-
- int GetMaxX(ImageFrame pixels)
- {
- for (int x = width - 1; x > -1; x--)
- {
- for (int y = 0; y < height; y++)
- {
- if (delegateFunc(pixels, x, y, componentValue))
- {
- return x;
- }
- }
- }
-
- return width;
- }
-
- topLeft.Y = GetMinY(bitmap);
- topLeft.X = GetMinX(bitmap);
- bottomRight.Y = (GetMaxY(bitmap) + 1).Clamp(0, height);
- bottomRight.X = (GetMaxX(bitmap) + 1).Clamp(0, width);
-
- return GetBoundingRectangle(topLeft, bottomRight);
- }
- }
-}
diff --git a/src/ImageSharp/Common/Helpers/Numerics.cs b/src/ImageSharp/Common/Helpers/Numerics.cs
new file mode 100644
index 000000000..b2bedb87b
--- /dev/null
+++ b/src/ImageSharp/Common/Helpers/Numerics.cs
@@ -0,0 +1,551 @@
+// Copyright (c) Six Labors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
+using System.Numerics;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+#if SUPPORTS_RUNTIME_INTRINSICS
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+#endif
+
+namespace SixLabors.ImageSharp
+{
+ ///
+ /// Provides optimized static methods for trigonometric, logarithmic,
+ /// and other common mathematical functions.
+ ///
+ internal static class Numerics
+ {
+#if SUPPORTS_RUNTIME_INTRINSICS
+ private const int BlendAlphaControl = 0b_10_00_10_00;
+ private const int ShuffleAlphaControl = 0b_11_11_11_11;
+#endif
+
+ ///
+ /// Determine the Greatest CommonDivisor (GCD) of two numbers.
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int GreatestCommonDivisor(int a, int b)
+ {
+ while (b != 0)
+ {
+ int temp = b;
+ b = a % b;
+ a = temp;
+ }
+
+ return a;
+ }
+
+ ///
+ /// Determine the Least Common Multiple (LCM) of two numbers.
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int LeastCommonMultiple(int a, int b)
+ {
+ // https://en.wikipedia.org/wiki/Least_common_multiple#Reduction_by_the_greatest_common_divisor
+ return (a / GreatestCommonDivisor(a, b)) * b;
+ }
+
+ ///
+ /// Calculates % 2
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int Modulo2(int x) => x & 1;
+
+ ///
+ /// Calculates % 4
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int Modulo4(int x) => x & 3;
+
+ ///
+ /// Calculates % 8
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int Modulo8(int x) => x & 7;
+
+ ///
+ /// Fast (x mod m) calculator, with the restriction that
+ /// should be power of 2.
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int ModuloP2(int x, int m) => x & (m - 1);
+
+ ///
+ /// Returns the absolute value of a 32-bit signed integer.
+ /// Uses bit shifting to speed up the operation compared to .
+ ///
+ ///
+ /// A number that is greater than , but less than
+ /// or equal to
+ ///
+ /// The
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int Abs(int x)
+ {
+ int y = x >> 31;
+ return (x ^ y) - y;
+ }
+
+ ///
+ /// Returns a specified number raised to the power of 2
+ ///
+ /// A single-precision floating-point number
+ /// The number raised to the power of 2.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float Pow2(float x) => x * x;
+
+ ///
+ /// Returns a specified number raised to the power of 3
+ ///
+ /// A single-precision floating-point number
+ /// The number raised to the power of 3.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float Pow3(float x) => x * x * x;
+
+ ///
+ /// Implementation of 1D Gaussian G(x) function
+ ///
+ /// The x provided to G(x).
+ /// The spread of the blur.
+ /// The Gaussian G(x)
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float Gaussian(float x, float sigma)
+ {
+ const float Numerator = 1.0f;
+ float denominator = MathF.Sqrt(2 * MathF.PI) * sigma;
+
+ float exponentNumerator = -x * x;
+ float exponentDenominator = 2 * Pow2(sigma);
+
+ float left = Numerator / denominator;
+ float right = MathF.Exp(exponentNumerator / exponentDenominator);
+
+ return left * right;
+ }
+
+ ///
+ /// Returns the result of a normalized sine cardinal function for the given value.
+ /// SinC(x) = sin(pi*x)/(pi*x).
+ ///
+ /// A single-precision floating-point number to calculate the result for.
+ ///
+ /// The sine cardinal of .
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float SinC(float f)
+ {
+ if (MathF.Abs(f) > Constants.Epsilon)
+ {
+ f *= MathF.PI;
+ float result = MathF.Sin(f) / f;
+ return MathF.Abs(result) < Constants.Epsilon ? 0F : result;
+ }
+
+ return 1F;
+ }
+
+ ///
+ /// Returns the value clamped to the inclusive range of min and max.
+ ///
+ /// The value to clamp.
+ /// The minimum inclusive value.
+ /// The maximum inclusive value.
+ /// The clamped .
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static byte Clamp(byte value, byte min, byte max)
+ {
+ // Order is important here as someone might set min to higher than max.
+ if (value > max)
+ {
+ return max;
+ }
+
+ if (value < min)
+ {
+ return min;
+ }
+
+ return value;
+ }
+
+ ///
+ /// Returns the value clamped to the inclusive range of min and max.
+ ///
+ /// The value to clamp.
+ /// The minimum inclusive value.
+ /// The maximum inclusive value.
+ /// The clamped .
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static uint Clamp(uint value, uint min, uint max)
+ {
+ if (value > max)
+ {
+ return max;
+ }
+
+ if (value < min)
+ {
+ return min;
+ }
+
+ return value;
+ }
+
+ ///
+ /// Returns the value clamped to the inclusive range of min and max.
+ ///
+ /// The value to clamp.
+ /// The minimum inclusive value.
+ /// The maximum inclusive value.
+ /// The clamped .
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int Clamp(int value, int min, int max)
+ {
+ if (value > max)
+ {
+ return max;
+ }
+
+ if (value < min)
+ {
+ return min;
+ }
+
+ return value;
+ }
+
+ ///
+ /// Returns the value clamped to the inclusive range of min and max.
+ ///
+ /// The value to clamp.
+ /// The minimum inclusive value.
+ /// The maximum inclusive value.
+ /// The clamped .
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float Clamp(float value, float min, float max)
+ {
+ if (value > max)
+ {
+ return max;
+ }
+
+ if (value < min)
+ {
+ return min;
+ }
+
+ return value;
+ }
+
+ ///
+ /// Returns the value clamped to the inclusive range of min and max.
+ ///
+ /// The value to clamp.
+ /// The minimum inclusive value.
+ /// The maximum inclusive value.
+ /// The clamped .
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static double Clamp(double value, double min, double max)
+ {
+ if (value > max)
+ {
+ return max;
+ }
+
+ if (value < min)
+ {
+ return min;
+ }
+
+ return value;
+ }
+
+ ///
+ /// Returns the value clamped to the inclusive range of min and max.
+ /// 5x Faster than
+ /// on platforms < NET 5.
+ ///
+ /// The value to clamp.
+ /// The minimum inclusive value.
+ /// The maximum inclusive value.
+ /// The clamped .
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static Vector4 Clamp(Vector4 value, Vector4 min, Vector4 max)
+ => Vector4.Min(Vector4.Max(value, min), max);
+
+ ///
+ /// Clamps the span values to the inclusive range of min and max.
+ ///
+ /// The span containing the values to clamp.
+ /// The minimum inclusive value.
+ /// The maximum inclusive value.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void Clamp(Span span, byte min, byte max)
+ {
+ Span remainder = span.Slice(ClampReduce(span, min, max));
+
+ if (remainder.Length > 0)
+ {
+ for (int i = 0; i < remainder.Length; i++)
+ {
+ ref byte v = ref remainder[i];
+ v = Clamp(v, min, max);
+ }
+ }
+ }
+
+ ///
+ /// Clamps the span values to the inclusive range of min and max.
+ ///
+ /// The span containing the values to clamp.
+ /// The minimum inclusive value.
+ /// The maximum inclusive value.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void Clamp(Span span, uint min, uint max)
+ {
+ Span remainder = span.Slice(ClampReduce(span, min, max));
+
+ if (remainder.Length > 0)
+ {
+ for (int i = 0; i < remainder.Length; i++)
+ {
+ ref uint v = ref remainder[i];
+ v = Clamp(v, min, max);
+ }
+ }
+ }
+
+ ///
+ /// Clamps the span values to the inclusive range of min and max.
+ ///
+ /// The span containing the values to clamp.
+ /// The minimum inclusive value.
+ /// The maximum inclusive value.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void Clamp(Span span, int min, int max)
+ {
+ Span remainder = span.Slice(ClampReduce(span, min, max));
+
+ if (remainder.Length > 0)
+ {
+ for (int i = 0; i < remainder.Length; i++)
+ {
+ ref int v = ref remainder[i];
+ v = Clamp(v, min, max);
+ }
+ }
+ }
+
+ ///
+ /// Clamps the span values to the inclusive range of min and max.
+ ///
+ /// The span containing the values to clamp.
+ /// The minimum inclusive value.
+ /// The maximum inclusive value.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void Clamp(Span span, float min, float max)
+ {
+ Span remainder = span.Slice(ClampReduce(span, min, max));
+
+ if (remainder.Length > 0)
+ {
+ for (int i = 0; i < remainder.Length; i++)
+ {
+ ref float v = ref remainder[i];
+ v = Clamp(v, min, max);
+ }
+ }
+ }
+
+ ///
+ /// Clamps the span values to the inclusive range of min and max.
+ ///
+ /// The span containing the values to clamp.
+ /// The minimum inclusive value.
+ /// The maximum inclusive value.
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void Clamp(Span span, double min, double max)
+ {
+ Span remainder = span.Slice(ClampReduce(span, min, max));
+
+ if (remainder.Length > 0)
+ {
+ for (int i = 0; i < remainder.Length; i++)
+ {
+ ref double v = ref remainder[i];
+ v = Clamp(v, min, max);
+ }
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static int ClampReduce(Span span, T min, T max)
+ where T : unmanaged
+ {
+ if (Vector.IsHardwareAccelerated && span.Length >= Vector.Count)
+ {
+ int remainder = ModuloP2(span.Length, Vector.Count);
+ int adjustedCount = span.Length - remainder;
+
+ if (adjustedCount > 0)
+ {
+ ClampImpl(span.Slice(0, adjustedCount), min, max);
+ }
+
+ return adjustedCount;
+ }
+
+ return 0;
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static void ClampImpl(Span span, T min, T max)
+ where T : unmanaged
+ {
+ ref T sRef = ref MemoryMarshal.GetReference(span);
+ ref Vector vsBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(span));
+ var vmin = new Vector(min);
+ var vmax = new Vector(max);
+
+ int n = span.Length / Vector.Count;
+ int m = Modulo4(n);
+ int u = n - m;
+
+ for (int i = 0; i < u; i += 4)
+ {
+ ref Vector vs0 = ref Unsafe.Add(ref vsBase, i);
+ ref Vector vs1 = ref Unsafe.Add(ref vs0, 1);
+ ref Vector vs2 = ref Unsafe.Add(ref vs0, 2);
+ ref Vector vs3 = ref Unsafe.Add(ref vs0, 3);
+
+ vs0 = Vector.Min(Vector.Max(vmin, vs0), vmax);
+ vs1 = Vector.Min(Vector.Max(vmin, vs1), vmax);
+ vs2 = Vector.Min(Vector.Max(vmin, vs2), vmax);
+ vs3 = Vector.Min(Vector.Max(vmin, vs3), vmax);
+ }
+
+ if (m > 0)
+ {
+ for (int i = u; i < n; i++)
+ {
+ ref Vector vs0 = ref Unsafe.Add(ref vsBase, i);
+ vs0 = Vector.Min(Vector.Max(vmin, vs0), vmax);
+ }
+ }
+ }
+
+ ///
+ /// Pre-multiplies the "x", "y", "z" components of a vector by its "w" component leaving the "w" component intact.
+ ///
+ /// The to premultiply
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void Premultiply(ref Vector4 source)
+ {
+ float w = source.W;
+ source *= w;
+ source.W = w;
+ }
+
+ ///
+ /// Reverses the result of premultiplying a vector via .
+ ///
+ /// The to premultiply
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void UnPremultiply(ref Vector4 source)
+ {
+ float w = source.W;
+ source /= w;
+ source.W = w;
+ }
+
+ ///
+ /// Bulk variant of
+ ///
+ /// The span of vectors
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void Premultiply(Span vectors)
+ {
+#if SUPPORTS_RUNTIME_INTRINSICS
+ if (Avx2.IsSupported && vectors.Length >= 2)
+ {
+ ref Vector256 vectorsBase =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(vectors));
+
+ // Divide by 2 as 4 elements per Vector4 and 8 per Vector256
+ ref Vector256 vectorsLast = ref Unsafe.Add(ref vectorsBase, (IntPtr)((uint)vectors.Length / 2u));
+
+ while (Unsafe.IsAddressLessThan(ref vectorsBase, ref vectorsLast))
+ {
+ Vector256 source = vectorsBase;
+ Vector256 multiply = Avx.Shuffle(source, source, ShuffleAlphaControl);
+ vectorsBase = Avx.Blend(Avx.Multiply(source, multiply), source, BlendAlphaControl);
+ vectorsBase = ref Unsafe.Add(ref vectorsBase, 1);
+ }
+
+ if (Modulo2(vectors.Length) != 0)
+ {
+ // Vector4 fits neatly in pairs. Any overlap has to be equal to 1.
+ Premultiply(ref MemoryMarshal.GetReference(vectors.Slice(vectors.Length - 1)));
+ }
+ }
+ else
+#endif
+ {
+ 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);
+ }
+ }
+ }
+
+ ///
+ /// Bulk variant of
+ ///
+ /// The span of vectors
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void UnPremultiply(Span vectors)
+ {
+#if SUPPORTS_RUNTIME_INTRINSICS
+ if (Avx2.IsSupported && vectors.Length >= 2)
+ {
+ ref Vector256 vectorsBase =
+ ref Unsafe.As>(ref MemoryMarshal.GetReference(vectors));
+
+ // Divide by 2 as 4 elements per Vector4 and 8 per Vector256
+ ref Vector256 vectorsLast = ref Unsafe.Add(ref vectorsBase, (IntPtr)((uint)vectors.Length / 2u));
+
+ while (Unsafe.IsAddressLessThan(ref vectorsBase, ref vectorsLast))
+ {
+ Vector256 source = vectorsBase;
+ Vector256 multiply = Avx.Shuffle(source, source, ShuffleAlphaControl);
+ vectorsBase = Avx.Blend(Avx.Divide(source, multiply), source, BlendAlphaControl);
+ vectorsBase = ref Unsafe.Add(ref vectorsBase, 1);
+ }
+
+ if (Modulo2(vectors.Length) != 0)
+ {
+ // Vector4 fits neatly in pairs. Any overlap has to be equal to 1.
+ UnPremultiply(ref MemoryMarshal.GetReference(vectors.Slice(vectors.Length - 1)));
+ }
+ }
+ else
+#endif
+ {
+ 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);
+ }
+ }
+ }
+ }
+}
diff --git a/src/ImageSharp/Common/Helpers/Shuffle/IShuffle4Slice3.cs b/src/ImageSharp/Common/Helpers/Shuffle/IShuffle4Slice3.cs
index 86e4174f1..3ecad3c5d 100644
--- a/src/ImageSharp/Common/Helpers/Shuffle/IShuffle4Slice3.cs
+++ b/src/ImageSharp/Common/Helpers/Shuffle/IShuffle4Slice3.cs
@@ -67,7 +67,7 @@ namespace SixLabors.ImageSharp
ref Byte3 dBase = ref Unsafe.As(ref MemoryMarshal.GetReference(dest));
int n = source.Length / 4;
- int m = ImageMaths.Modulo4(n);
+ int m = Numerics.Modulo4(n);
int u = n - m;
ref uint sLoopEnd = ref Unsafe.Add(ref sBase, u);
diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.BasicIntrinsics256.cs b/src/ImageSharp/Common/Helpers/SimdUtils.BasicIntrinsics256.cs
index de6990db5..75555f88a 100644
--- a/src/ImageSharp/Common/Helpers/SimdUtils.BasicIntrinsics256.cs
+++ b/src/ImageSharp/Common/Helpers/SimdUtils.BasicIntrinsics256.cs
@@ -35,7 +35,7 @@ namespace SixLabors.ImageSharp
return;
}
- int remainder = ImageMaths.Modulo8(source.Length);
+ int remainder = Numerics.Modulo8(source.Length);
int adjustedCount = source.Length - remainder;
if (adjustedCount > 0)
@@ -64,7 +64,7 @@ namespace SixLabors.ImageSharp
return;
}
- int remainder = ImageMaths.Modulo8(source.Length);
+ int remainder = Numerics.Modulo8(source.Length);
int adjustedCount = source.Length - remainder;
if (adjustedCount > 0)
diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.ExtendedIntrinsics.cs b/src/ImageSharp/Common/Helpers/SimdUtils.ExtendedIntrinsics.cs
index bd35d1583..0abc0e26d 100644
--- a/src/ImageSharp/Common/Helpers/SimdUtils.ExtendedIntrinsics.cs
+++ b/src/ImageSharp/Common/Helpers/SimdUtils.ExtendedIntrinsics.cs
@@ -57,7 +57,7 @@ namespace SixLabors.ImageSharp
return;
}
- int remainder = ImageMaths.ModuloP2(source.Length, Vector.Count);
+ int remainder = Numerics.ModuloP2(source.Length, Vector.Count);
int adjustedCount = source.Length - remainder;
if (adjustedCount > 0)
@@ -84,7 +84,7 @@ namespace SixLabors.ImageSharp
return;
}
- int remainder = ImageMaths.ModuloP2(source.Length, Vector.Count);
+ int remainder = Numerics.ModuloP2(source.Length, Vector.Count);
int adjustedCount = source.Length - remainder;
if (adjustedCount > 0)
diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.FallbackIntrinsics128.cs b/src/ImageSharp/Common/Helpers/SimdUtils.FallbackIntrinsics128.cs
index 1e89aaeb8..15133770f 100644
--- a/src/ImageSharp/Common/Helpers/SimdUtils.FallbackIntrinsics128.cs
+++ b/src/ImageSharp/Common/Helpers/SimdUtils.FallbackIntrinsics128.cs
@@ -28,7 +28,7 @@ namespace SixLabors.ImageSharp
{
DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!");
- int remainder = ImageMaths.Modulo4(source.Length);
+ int remainder = Numerics.Modulo4(source.Length);
int adjustedCount = source.Length - remainder;
if (adjustedCount > 0)
@@ -52,7 +52,7 @@ namespace SixLabors.ImageSharp
{
DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!");
- int remainder = ImageMaths.Modulo4(source.Length);
+ int remainder = Numerics.Modulo4(source.Length);
int adjustedCount = source.Length - remainder;
if (adjustedCount > 0)
@@ -125,7 +125,7 @@ namespace SixLabors.ImageSharp
Vector4 s = Unsafe.Add(ref sBase, i);
s *= maxBytes;
s += half;
- s = Vector4Utilities.FastClamp(s, Vector4.Zero, maxBytes);
+ s = Numerics.Clamp(s, Vector4.Zero, maxBytes);
ref ByteVector4 d = ref Unsafe.Add(ref dBase, i);
d.X = (byte)s.X;
diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs b/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs
index 2ea7f2c9b..b76030116 100644
--- a/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs
+++ b/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs
@@ -38,8 +38,8 @@ namespace SixLabors.ImageSharp
if (Avx.IsSupported || Sse.IsSupported)
{
int remainder = Avx.IsSupported
- ? ImageMaths.ModuloP2(source.Length, Vector256.Count)
- : ImageMaths.ModuloP2(source.Length, Vector128.Count);
+ ? Numerics.ModuloP2(source.Length, Vector256.Count)
+ : Numerics.ModuloP2(source.Length, Vector128.Count);
int adjustedCount = source.Length - remainder;
@@ -72,8 +72,8 @@ namespace SixLabors.ImageSharp
if (Avx2.IsSupported || Ssse3.IsSupported)
{
int remainder = Avx2.IsSupported
- ? ImageMaths.ModuloP2(source.Length, Vector256.Count)
- : ImageMaths.ModuloP2(source.Length, Vector128.Count);
+ ? Numerics.ModuloP2(source.Length, Vector256.Count)
+ : Numerics.ModuloP2(source.Length, Vector128.Count);
int adjustedCount = source.Length - remainder;
@@ -203,7 +203,7 @@ namespace SixLabors.ImageSharp
ref Unsafe.As>(ref MemoryMarshal.GetReference(dest));
int n = dest.Length / Vector256.Count;
- int m = ImageMaths.Modulo4(n);
+ int m = Numerics.Modulo4(n);
int u = n - m;
for (int i = 0; i < u; i += 4)
@@ -235,7 +235,7 @@ namespace SixLabors.ImageSharp
ref Unsafe.As>(ref MemoryMarshal.GetReference(dest));
int n = dest.Length / Vector128.Count;
- int m = ImageMaths.Modulo4(n);
+ int m = Numerics.Modulo4(n);
int u = n - m;
for (int i = 0; i < u; i += 4)
@@ -288,7 +288,7 @@ namespace SixLabors.ImageSharp
ref Unsafe.As>(ref MemoryMarshal.GetReference(dest));
int n = dest.Length / Vector256.Count;
- int m = ImageMaths.Modulo4(n);
+ int m = Numerics.Modulo4(n);
int u = n - m;
for (int i = 0; i < u; i += 4)
@@ -324,7 +324,7 @@ namespace SixLabors.ImageSharp
ref Unsafe.As>(ref MemoryMarshal.GetReference(dest));
int n = dest.Length / Vector128.Count;
- int m = ImageMaths.Modulo4(n);
+ int m = Numerics.Modulo4(n);
int u = n - m;
for (int i = 0; i < u; i += 4)
@@ -550,11 +550,11 @@ namespace SixLabors.ImageSharp
int remainder;
if (Avx2.IsSupported)
{
- remainder = ImageMaths.ModuloP2(source.Length, Vector256.Count);
+ remainder = Numerics.ModuloP2(source.Length, Vector256.Count);
}
else
{
- remainder = ImageMaths.ModuloP2(source.Length, Vector128.Count);
+ remainder = Numerics.ModuloP2(source.Length, Vector128.Count);
}
int adjustedCount = source.Length - remainder;
@@ -683,11 +683,11 @@ namespace SixLabors.ImageSharp
int remainder;
if (Avx2.IsSupported)
{
- remainder = ImageMaths.ModuloP2(source.Length, Vector256.Count);
+ remainder = Numerics.ModuloP2(source.Length, Vector256.Count);
}
else
{
- remainder = ImageMaths.ModuloP2(source.Length, Vector128.Count);
+ remainder = Numerics.ModuloP2(source.Length, Vector128.Count);
}
int adjustedCount = source.Length - remainder;
diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.cs b/src/ImageSharp/Common/Helpers/SimdUtils.cs
index 7cbb5bfe3..aaf6d405c 100644
--- a/src/ImageSharp/Common/Helpers/SimdUtils.cs
+++ b/src/ImageSharp/Common/Helpers/SimdUtils.cs
@@ -51,7 +51,7 @@ namespace SixLabors.ImageSharp
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static Vector4 PseudoRound(this Vector4 v)
{
- Vector4 sign = Vector4Utilities.FastClamp(v, new Vector4(-1), new Vector4(1));
+ Vector4 sign = Numerics.Clamp(v, new Vector4(-1), new Vector4(1));
return v + (sign * 0.5f);
}
@@ -190,7 +190,7 @@ namespace SixLabors.ImageSharp
}
[MethodImpl(InliningOptions.ShortMethod)]
- private static byte ConvertToByte(float f) => (byte)ComparableExtensions.Clamp((f * 255f) + 0.5f, 0, 255f);
+ private static byte ConvertToByte(float f) => (byte)Numerics.Clamp((f * 255F) + 0.5F, 0, 255F);
[Conditional("DEBUG")]
private static void VerifyHasVector8(string operation)
@@ -206,7 +206,7 @@ namespace SixLabors.ImageSharp
{
DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!");
DebugGuard.IsTrue(
- ImageMaths.ModuloP2(dest.Length, shouldBeDivisibleBy) == 0,
+ Numerics.ModuloP2(dest.Length, shouldBeDivisibleBy) == 0,
nameof(source),
$"length should be divisible by {shouldBeDivisibleBy}!");
}
@@ -216,7 +216,7 @@ namespace SixLabors.ImageSharp
{
DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!");
DebugGuard.IsTrue(
- ImageMaths.ModuloP2(dest.Length, shouldBeDivisibleBy) == 0,
+ Numerics.ModuloP2(dest.Length, shouldBeDivisibleBy) == 0,
nameof(source),
$"length should be divisible by {shouldBeDivisibleBy}!");
}
diff --git a/src/ImageSharp/Common/Helpers/Vector4Utilities.cs b/src/ImageSharp/Common/Helpers/Vector4Utilities.cs
deleted file mode 100644
index f617e9a3e..000000000
--- a/src/ImageSharp/Common/Helpers/Vector4Utilities.cs
+++ /dev/null
@@ -1,181 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using System.Numerics;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-#if SUPPORTS_RUNTIME_INTRINSICS
-using System.Runtime.Intrinsics;
-using System.Runtime.Intrinsics.X86;
-#endif
-
-namespace SixLabors.ImageSharp
-{
- ///
- /// Utility methods for the struct.
- ///
- internal static class Vector4Utilities
- {
- private const int BlendAlphaControl = 0b_10_00_10_00;
- private const int ShuffleAlphaControl = 0b_11_11_11_11;
-
- ///
- /// Restricts a vector between a minimum and a maximum value.
- /// 5x Faster then .
- ///
- /// The vector to restrict.
- /// The minimum value.
- /// The maximum value.
- /// The .
- [MethodImpl(InliningOptions.ShortMethod)]
- public static Vector4 FastClamp(Vector4 x, Vector4 min, Vector4 max)
- => Vector4.Min(Vector4.Max(x, min), max);
-
- ///
- /// Pre-multiplies the "x", "y", "z" components of a vector by its "w" component leaving the "w" component intact.
- ///
- /// The to premultiply
- [MethodImpl(InliningOptions.ShortMethod)]
- public static void Premultiply(ref Vector4 source)
- {
- float w = source.W;
- source *= w;
- source.W = w;
- }
-
- ///
- /// Reverses the result of premultiplying a vector via .
- ///
- /// The to premultiply
- [MethodImpl(InliningOptions.ShortMethod)]
- public static void UnPremultiply(ref Vector4 source)
- {
- float w = source.W;
- source /= w;
- source.W = w;
- }
-
- ///
- /// Bulk variant of
- ///
- /// The span of vectors
- [MethodImpl(InliningOptions.ShortMethod)]
- public static void Premultiply(Span vectors)
- {
-#if SUPPORTS_RUNTIME_INTRINSICS
- if (Avx2.IsSupported && vectors.Length >= 2)
- {
- ref Vector256 vectorsBase =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(vectors));
-
- // Divide by 2 as 4 elements per Vector4 and 8 per Vector256
- ref Vector256 vectorsLast = ref Unsafe.Add(ref vectorsBase, (IntPtr)((uint)vectors.Length / 2u));
-
- while (Unsafe.IsAddressLessThan(ref vectorsBase, ref vectorsLast))
- {
- Vector256 source = vectorsBase;
- Vector256 multiply = Avx.Shuffle(source, source, ShuffleAlphaControl);
- vectorsBase = Avx.Blend(Avx.Multiply(source, multiply), source, BlendAlphaControl);
- vectorsBase = ref Unsafe.Add(ref vectorsBase, 1);
- }
-
- if (ImageMaths.Modulo2(vectors.Length) != 0)
- {
- // Vector4 fits neatly in pairs. Any overlap has to be equal to 1.
- Premultiply(ref MemoryMarshal.GetReference(vectors.Slice(vectors.Length - 1)));
- }
- }
- else
-#endif
- {
- 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);
- }
- }
- }
-
- ///
- /// Bulk variant of
- ///
- /// The span of vectors
- [MethodImpl(InliningOptions.ShortMethod)]
- public static void UnPremultiply(Span vectors)
- {
-#if SUPPORTS_RUNTIME_INTRINSICS
- if (Avx2.IsSupported && vectors.Length >= 2)
- {
- ref Vector256 vectorsBase =
- ref Unsafe.As>(ref MemoryMarshal.GetReference(vectors));
-
- // Divide by 2 as 4 elements per Vector4 and 8 per Vector256
- ref Vector256 vectorsLast = ref Unsafe.Add(ref vectorsBase, (IntPtr)((uint)vectors.Length / 2u));
-
- while (Unsafe.IsAddressLessThan(ref vectorsBase, ref vectorsLast))
- {
- Vector256 source = vectorsBase;
- Vector256 multiply = Avx.Shuffle(source, source, ShuffleAlphaControl);
- vectorsBase = Avx.Blend(Avx.Divide(source, multiply), source, BlendAlphaControl);
- vectorsBase = ref Unsafe.Add(ref vectorsBase, 1);
- }
-
- if (ImageMaths.Modulo2(vectors.Length) != 0)
- {
- // Vector4 fits neatly in pairs. Any overlap has to be equal to 1.
- UnPremultiply(ref MemoryMarshal.GetReference(vectors.Slice(vectors.Length - 1)));
- }
- }
- else
-#endif
- {
- 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);
- }
- }
- }
-
- ///
- /// Transforms a vector by the given matrix.
- ///
- /// The source vector.
- /// The transformation matrix.
- [MethodImpl(InliningOptions.ShortMethod)]
- 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;
- }
-
- ///
- /// Bulk variant of .
- ///
- /// The span of vectors
- /// The transformation matrix.
- [MethodImpl(InliningOptions.ShortMethod)]
- 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);
- Transform(ref v, ref matrix);
- }
- }
- }
-}
diff --git a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
index 6f9223637..0be038572 100644
--- a/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
@@ -1385,7 +1385,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
{
case BmpFileMarkerType.Bitmap:
colorMapSizeBytes = this.fileHeader.Offset - BmpFileHeader.Size - this.infoHeader.HeaderSize;
- int colorCountForBitDepth = ImageMaths.GetColorCountForBitDepth(this.infoHeader.BitsPerPixel);
+ int colorCountForBitDepth = ColorNumerics.GetColorCountForBitDepth(this.infoHeader.BitsPerPixel);
bytesPerColorMapEntry = colorMapSizeBytes / colorCountForBitDepth;
// Edge case for less-than-full-sized palette: bytesPerColorMapEntry should be at least 3.
@@ -1399,7 +1399,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
case BmpFileMarkerType.Pointer:
// OS/2 bitmaps always have 3 colors per color palette entry.
bytesPerColorMapEntry = 3;
- colorMapSizeBytes = ImageMaths.GetColorCountForBitDepth(this.infoHeader.BitsPerPixel) * bytesPerColorMapEntry;
+ colorMapSizeBytes = ColorNumerics.GetColorCountForBitDepth(this.infoHeader.BitsPerPixel) * bytesPerColorMapEntry;
break;
}
}
diff --git a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
index 01bdbd1c0..7819b1ebd 100644
--- a/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
+++ b/src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
@@ -262,7 +262,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp
private void Write24Bit(Stream stream, Buffer2D pixels)
where TPixel : unmanaged, IPixel
{
- using (IManagedByteBuffer row = this.AllocateRow(pixels.Width, 3))
+ int width = pixels.Width;
+ int rowBytesWithoutPadding = width * 3;
+ using (IManagedByteBuffer row = this.AllocateRow(width, 3))
{
for (int y = pixels.Height - 1; y >= 0; y--)
{
@@ -270,8 +272,8 @@ namespace SixLabors.ImageSharp.Formats.Bmp
PixelOperations.Instance.ToBgr24Bytes(
this.configuration,
pixelSpan,
- row.GetSpan(),
- pixelSpan.Length);
+ row.Slice(0, rowBytesWithoutPadding),
+ width);
stream.Write(row.Array, 0, row.Length());
}
}
@@ -286,7 +288,9 @@ namespace SixLabors.ImageSharp.Formats.Bmp
private void Write16Bit(Stream stream, Buffer2D pixels)
where TPixel : unmanaged, IPixel
{
- using (IManagedByteBuffer row = this.AllocateRow(pixels.Width, 2))
+ int width = pixels.Width;
+ int rowBytesWithoutPadding = width * 2;
+ using (IManagedByteBuffer row = this.AllocateRow(width, 2))
{
for (int y = pixels.Height - 1; y >= 0; y--)
{
@@ -295,7 +299,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
PixelOperations.Instance.ToBgra5551Bytes(
this.configuration,
pixelSpan,
- row.GetSpan(),
+ row.Slice(0, rowBytesWithoutPadding),
pixelSpan.Length);
stream.Write(row.Array, 0, row.Length());
@@ -341,7 +345,8 @@ namespace SixLabors.ImageSharp.Formats.Bmp
using IndexedImageFrame quantized = frameQuantizer.BuildPaletteAndQuantizeFrame(image, image.Bounds());
ReadOnlySpan quantizedColors = quantized.Palette.Span;
- PixelOperations.Instance.ToBgra32(this.configuration, quantizedColors, MemoryMarshal.Cast(colorPalette));
+ var quantizedColorBytes = quantizedColors.Length * 4;
+ PixelOperations.Instance.ToBgra32(this.configuration, quantizedColors, MemoryMarshal.Cast(colorPalette.Slice(0, quantizedColorBytes)));
Span colorPaletteAsUInt = MemoryMarshal.Cast(colorPalette);
for (int i = 0; i < colorPaletteAsUInt.Length; i++)
{
diff --git a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
index 070864e60..9c1e95285 100644
--- a/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
+++ b/src/ImageSharp/Formats/Gif/GifEncoderCore.cs
@@ -105,7 +105,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
}
// Get the number of bits.
- this.bitDepth = ImageMaths.GetBitsNeededForColorDepth(quantized.Palette.Length);
+ this.bitDepth = ColorNumerics.GetBitsNeededForColorDepth(quantized.Palette.Length);
// Write the header.
this.WriteHeader(stream);
@@ -212,7 +212,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
}
}
- this.bitDepth = ImageMaths.GetBitsNeededForColorDepth(quantized.Palette.Length);
+ this.bitDepth = ColorNumerics.GetBitsNeededForColorDepth(quantized.Palette.Length);
this.WriteGraphicalControlExtension(frameMetadata, this.GetTransparentIndex(quantized), stream);
this.WriteImageDescriptor(frame, true, stream);
this.WriteColorTable(quantized, stream);
@@ -468,7 +468,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
where TPixel : unmanaged, IPixel
{
// The maximum number of colors for the bit depth
- int colorTableLength = ImageMaths.GetColorCountForBitDepth(this.bitDepth) * Unsafe.SizeOf();
+ int colorTableLength = ColorNumerics.GetColorCountForBitDepth(this.bitDepth) * Unsafe.SizeOf();
using IManagedByteBuffer colorTable = this.memoryAllocator.AllocateManagedByteBuffer(colorTableLength, AllocationOptions.Clean);
PixelOperations.Instance.ToRgb24Bytes(
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs
index 0efefc06b..dd5d3f196 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs
@@ -19,22 +19,22 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
var CMax4 = new Vector4(maximum);
var COff4 = new Vector4(MathF.Ceiling(maximum / 2));
- this.V0L = Vector4Utilities.FastClamp(this.V0L + COff4, CMin4, CMax4);
- this.V0R = Vector4Utilities.FastClamp(this.V0R + COff4, CMin4, CMax4);
- this.V1L = Vector4Utilities.FastClamp(this.V1L + COff4, CMin4, CMax4);
- this.V1R = Vector4Utilities.FastClamp(this.V1R + COff4, CMin4, CMax4);
- this.V2L = Vector4Utilities.FastClamp(this.V2L + COff4, CMin4, CMax4);
- this.V2R = Vector4Utilities.FastClamp(this.V2R + COff4, CMin4, CMax4);
- this.V3L = Vector4Utilities.FastClamp(this.V3L + COff4, CMin4, CMax4);
- this.V3R = Vector4Utilities.FastClamp(this.V3R + COff4, CMin4, CMax4);
- this.V4L = Vector4Utilities.FastClamp(this.V4L + COff4, CMin4, CMax4);
- this.V4R = Vector4Utilities.FastClamp(this.V4R + COff4, CMin4, CMax4);
- this.V5L = Vector4Utilities.FastClamp(this.V5L + COff4, CMin4, CMax4);
- this.V5R = Vector4Utilities.FastClamp(this.V5R + COff4, CMin4, CMax4);
- this.V6L = Vector4Utilities.FastClamp(this.V6L + COff4, CMin4, CMax4);
- this.V6R = Vector4Utilities.FastClamp(this.V6R + COff4, CMin4, CMax4);
- this.V7L = Vector4Utilities.FastClamp(this.V7L + COff4, CMin4, CMax4);
- this.V7R = Vector4Utilities.FastClamp(this.V7R + COff4, CMin4, CMax4);
+ this.V0L = Numerics.Clamp(this.V0L + COff4, CMin4, CMax4);
+ this.V0R = Numerics.Clamp(this.V0R + COff4, CMin4, CMax4);
+ this.V1L = Numerics.Clamp(this.V1L + COff4, CMin4, CMax4);
+ this.V1R = Numerics.Clamp(this.V1R + COff4, CMin4, CMax4);
+ this.V2L = Numerics.Clamp(this.V2L + COff4, CMin4, CMax4);
+ this.V2R = Numerics.Clamp(this.V2R + COff4, CMin4, CMax4);
+ this.V3L = Numerics.Clamp(this.V3L + COff4, CMin4, CMax4);
+ this.V3R = Numerics.Clamp(this.V3R + COff4, CMin4, CMax4);
+ this.V4L = Numerics.Clamp(this.V4L + COff4, CMin4, CMax4);
+ this.V4R = Numerics.Clamp(this.V4R + COff4, CMin4, CMax4);
+ this.V5L = Numerics.Clamp(this.V5L + COff4, CMin4, CMax4);
+ this.V5R = Numerics.Clamp(this.V5R + COff4, CMin4, CMax4);
+ this.V6L = Numerics.Clamp(this.V6L + COff4, CMin4, CMax4);
+ this.V6R = Numerics.Clamp(this.V6R + COff4, CMin4, CMax4);
+ this.V7L = Numerics.Clamp(this.V7L + COff4, CMin4, CMax4);
+ this.V7R = Numerics.Clamp(this.V7R + COff4, CMin4, CMax4);
}
///
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt
index e5a62dc07..8897efbe0 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt
+++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt
@@ -41,7 +41,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
for (int j = 0; j < 2; j++)
{
char side = j == 0 ? 'L' : 'R';
- Write($"this.V{i}{side} = Vector4Utilities.FastClamp(this.V{i}{side} + COff4, CMin4, CMax4);\r\n");
+ Write($"this.V{i}{side} = Numerics.Clamp(this.V{i}{side} + COff4, CMin4, CMax4);\r\n");
}
}
PopIndent();
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs
index 0dbdadbeb..fd4748fa9 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs
@@ -671,7 +671,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
private static Vector4 DivideRound(Vector4 dividend, Vector4 divisor)
{
// sign(dividend) = max(min(dividend, 1), -1)
- Vector4 sign = Vector4Utilities.FastClamp(dividend, NegativeOne, Vector4.One);
+ Vector4 sign = Numerics.Clamp(dividend, NegativeOne, Vector4.One);
// AlmostRound(dividend/divisor) = dividend/divisor + 0.5*sign(dividend)
return (dividend / divisor) + (sign * Offset);
diff --git a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
index c4ff1c036..36766d05f 100644
--- a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
+++ b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
@@ -212,8 +212,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
ImageMetadata metadata = image.Metadata;
// System.Drawing produces identical output for jpegs with a quality parameter of 0 and 1.
- int qlty = (this.quality ?? metadata.GetJpegMetadata().Quality).Clamp(1, 100);
- this.subsample = this.subsample ?? (qlty >= 91 ? JpegSubsample.Ratio444 : JpegSubsample.Ratio420);
+ int qlty = Numerics.Clamp(this.quality ?? metadata.GetJpegMetadata().Quality, 1, 100);
+ this.subsample ??= qlty >= 91 ? JpegSubsample.Ratio444 : JpegSubsample.Ratio420;
// Convert from a quality rating to a scaling factor.
int scale;
diff --git a/src/ImageSharp/Formats/PixelTypeInfo.cs b/src/ImageSharp/Formats/PixelTypeInfo.cs
index d53d496fa..718b05e33 100644
--- a/src/ImageSharp/Formats/PixelTypeInfo.cs
+++ b/src/ImageSharp/Formats/PixelTypeInfo.cs
@@ -1,8 +1,7 @@
-// Copyright (c) Six Labors.
+// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System.Runtime.CompilerServices;
-
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats
@@ -16,9 +15,11 @@ namespace SixLabors.ImageSharp.Formats
/// Initializes a new instance of the class.
///
/// Color depth, in number of bits per pixel.
- internal PixelTypeInfo(int bitsPerPixel)
+ /// Tthe pixel alpha transparency behavior.
+ internal PixelTypeInfo(int bitsPerPixel, PixelAlphaRepresentation? alpha = null)
{
this.BitsPerPixel = bitsPerPixel;
+ this.AlphaRepresentation = alpha;
}
///
@@ -26,8 +27,20 @@ namespace SixLabors.ImageSharp.Formats
///
public int BitsPerPixel { get; }
+ ///
+ /// Gets the pixel alpha transparency behavior.
+ /// means unknown, unspecified.
+ ///
+ public PixelAlphaRepresentation? AlphaRepresentation { get; }
+
internal static PixelTypeInfo Create()
where TPixel : unmanaged, IPixel =>
new PixelTypeInfo(Unsafe.SizeOf() * 8);
+
+ internal static PixelTypeInfo Create(PixelAlphaRepresentation alpha)
+ where TPixel : unmanaged, IPixel
+ {
+ return new PixelTypeInfo(Unsafe.SizeOf() * 8, alpha);
+ }
}
}
diff --git a/src/ImageSharp/Formats/Png/Filters/AverageFilter.cs b/src/ImageSharp/Formats/Png/Filters/AverageFilter.cs
index 8d9f6e415..d1c214e3d 100644
--- a/src/ImageSharp/Formats/Png/Filters/AverageFilter.cs
+++ b/src/ImageSharp/Formats/Png/Filters/AverageFilter.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Six Labors.
+// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
@@ -76,7 +76,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters
++x;
ref byte res = ref Unsafe.Add(ref resultBaseRef, x);
res = (byte)(scan - (above >> 1));
- sum += ImageMaths.FastAbs(unchecked((sbyte)res));
+ sum += Numerics.Abs(unchecked((sbyte)res));
}
for (int xLeft = x - bytesPerPixel; x < scanline.Length; ++xLeft /* Note: ++x happens in the body to avoid one add operation */)
@@ -87,7 +87,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters
++x;
ref byte res = ref Unsafe.Add(ref resultBaseRef, x);
res = (byte)(scan - Average(left, above));
- sum += ImageMaths.FastAbs(unchecked((sbyte)res));
+ sum += Numerics.Abs(unchecked((sbyte)res));
}
sum -= 3;
@@ -102,4 +102,4 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static int Average(byte left, byte above) => (left + above) >> 1;
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/Formats/Png/Filters/PaethFilter.cs b/src/ImageSharp/Formats/Png/Filters/PaethFilter.cs
index 7b5c71a01..fab678806 100644
--- a/src/ImageSharp/Formats/Png/Filters/PaethFilter.cs
+++ b/src/ImageSharp/Formats/Png/Filters/PaethFilter.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Six Labors.
+// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
@@ -79,7 +79,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters
++x;
ref byte res = ref Unsafe.Add(ref resultBaseRef, x);
res = (byte)(scan - PaethPredictor(0, above, 0));
- sum += ImageMaths.FastAbs(unchecked((sbyte)res));
+ sum += Numerics.Abs(unchecked((sbyte)res));
}
for (int xLeft = x - bytesPerPixel; x < scanline.Length; ++xLeft /* Note: ++x happens in the body to avoid one add operation */)
@@ -91,7 +91,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters
++x;
ref byte res = ref Unsafe.Add(ref resultBaseRef, x);
res = (byte)(scan - PaethPredictor(left, above, upperLeft));
- sum += ImageMaths.FastAbs(unchecked((sbyte)res));
+ sum += Numerics.Abs(unchecked((sbyte)res));
}
sum -= 4;
@@ -111,9 +111,9 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters
private static byte PaethPredictor(byte left, byte above, byte upperLeft)
{
int p = left + above - upperLeft;
- int pa = ImageMaths.FastAbs(p - left);
- int pb = ImageMaths.FastAbs(p - above);
- int pc = ImageMaths.FastAbs(p - upperLeft);
+ int pa = Numerics.Abs(p - left);
+ int pb = Numerics.Abs(p - above);
+ int pc = Numerics.Abs(p - upperLeft);
if (pa <= pb && pa <= pc)
{
@@ -128,4 +128,4 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters
return upperLeft;
}
}
-}
\ No newline at end of file
+}
diff --git a/src/ImageSharp/Formats/Png/Filters/SubFilter.cs b/src/ImageSharp/Formats/Png/Filters/SubFilter.cs
index c448e71f4..cb4cfb471 100644
--- a/src/ImageSharp/Formats/Png/Filters/SubFilter.cs
+++ b/src/ImageSharp/Formats/Png/Filters/SubFilter.cs
@@ -61,7 +61,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters
++x;
ref byte res = ref Unsafe.Add(ref resultBaseRef, x);
res = scan;
- sum += ImageMaths.FastAbs(unchecked((sbyte)res));
+ sum += Numerics.Abs(unchecked((sbyte)res));
}
for (int xLeft = x - bytesPerPixel; x < scanline.Length; ++xLeft /* Note: ++x happens in the body to avoid one add operation */)
@@ -71,7 +71,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters
++x;
ref byte res = ref Unsafe.Add(ref resultBaseRef, x);
res = (byte)(scan - prev);
- sum += ImageMaths.FastAbs(unchecked((sbyte)res));
+ sum += Numerics.Abs(unchecked((sbyte)res));
}
sum -= 1;
diff --git a/src/ImageSharp/Formats/Png/Filters/UpFilter.cs b/src/ImageSharp/Formats/Png/Filters/UpFilter.cs
index 2a77bccb9..cf553cbb6 100644
--- a/src/ImageSharp/Formats/Png/Filters/UpFilter.cs
+++ b/src/ImageSharp/Formats/Png/Filters/UpFilter.cs
@@ -64,7 +64,7 @@ namespace SixLabors.ImageSharp.Formats.Png.Filters
++x;
ref byte res = ref Unsafe.Add(ref resultBaseRef, x);
res = (byte)(scan - above);
- sum += ImageMaths.FastAbs(unchecked((sbyte)res));
+ sum += Numerics.Abs(unchecked((sbyte)res));
}
sum -= 2;
diff --git a/src/ImageSharp/Formats/Png/PngEncoderCore.cs b/src/ImageSharp/Formats/Png/PngEncoderCore.cs
index 5cf11099c..5d2af8ec6 100644
--- a/src/ImageSharp/Formats/Png/PngEncoderCore.cs
+++ b/src/ImageSharp/Formats/Png/PngEncoderCore.cs
@@ -284,7 +284,7 @@ namespace SixLabors.ImageSharp.Formats.Png
rowSpan.Length,
AllocationOptions.Clean))
{
- int scaleFactor = 255 / (ImageMaths.GetColorCountForBitDepth(this.bitDepth) - 1);
+ int scaleFactor = 255 / (ColorNumerics.GetColorCountForBitDepth(this.bitDepth) - 1);
Span tempSpan = temp.GetSpan();
// We need to first create an array of luminance bytes then scale them down to the correct bit depth.
@@ -314,7 +314,7 @@ namespace SixLabors.ImageSharp.Formats.Png
for (int x = 0, o = 0; x < rgbaSpan.Length; x++, o += 4)
{
Rgba64 rgba = Unsafe.Add(ref rgbaRef, x);
- ushort luminance = ImageMaths.Get16BitBT709Luminance(rgba.R, rgba.G, rgba.B);
+ ushort luminance = ColorNumerics.Get16BitBT709Luminance(rgba.R, rgba.G, rgba.B);
BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o, 2), luminance);
BinaryPrimitives.WriteUInt16BigEndian(rawScanlineSpan.Slice(o + 2, 2), rgba.A);
}
@@ -329,7 +329,7 @@ namespace SixLabors.ImageSharp.Formats.Png
{
Unsafe.Add(ref rowSpanRef, x).ToRgba32(ref rgba);
Unsafe.Add(ref rawScanlineSpanRef, o) =
- ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B);
+ ColorNumerics.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B);
Unsafe.Add(ref rawScanlineSpanRef, o + 1) = rgba.A;
}
}
diff --git a/src/ImageSharp/Formats/Png/PngEncoderOptionsHelpers.cs b/src/ImageSharp/Formats/Png/PngEncoderOptionsHelpers.cs
index 9342e09df..23ca86993 100644
--- a/src/ImageSharp/Formats/Png/PngEncoderOptionsHelpers.cs
+++ b/src/ImageSharp/Formats/Png/PngEncoderOptionsHelpers.cs
@@ -75,7 +75,7 @@ namespace SixLabors.ImageSharp.Formats.Png
if (options.Quantizer is null)
{
byte bits = (byte)options.BitDepth;
- var maxColors = ImageMaths.GetColorCountForBitDepth(bits);
+ var maxColors = ColorNumerics.GetColorCountForBitDepth(bits);
options.Quantizer = new WuQuantizer(new QuantizerOptions { MaxColors = maxColors });
}
@@ -101,7 +101,7 @@ namespace SixLabors.ImageSharp.Formats.Png
byte bitDepth;
if (options.ColorType == PngColorType.Palette)
{
- byte quantizedBits = (byte)ImageMaths.GetBitsNeededForColorDepth(quantizedFrame.Palette.Length).Clamp(1, 8);
+ byte quantizedBits = (byte)Numerics.Clamp(ColorNumerics.GetBitsNeededForColorDepth(quantizedFrame.Palette.Length), 1, 8);
byte bits = Math.Max((byte)options.BitDepth, quantizedBits);
// Png only supports in four pixel depths: 1, 2, 4, and 8 bits when using the PLTE chunk
diff --git a/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs b/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs
index 48ec9bdcd..58fa5aca8 100644
--- a/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs
+++ b/src/ImageSharp/Formats/Png/PngScanlineProcessor.cs
@@ -27,7 +27,7 @@ namespace SixLabors.ImageSharp.Formats.Png
TPixel pixel = default;
ref byte scanlineSpanRef = ref MemoryMarshal.GetReference(scanlineSpan);
ref TPixel rowSpanRef = ref MemoryMarshal.GetReference(rowSpan);
- int scaleFactor = 255 / (ImageMaths.GetColorCountForBitDepth(header.BitDepth) - 1);
+ int scaleFactor = 255 / (ColorNumerics.GetColorCountForBitDepth(header.BitDepth) - 1);
if (!hasTrans)
{
@@ -96,7 +96,7 @@ namespace SixLabors.ImageSharp.Formats.Png
TPixel pixel = default;
ref byte scanlineSpanRef = ref MemoryMarshal.GetReference(scanlineSpan);
ref TPixel rowSpanRef = ref MemoryMarshal.GetReference(rowSpan);
- int scaleFactor = 255 / (ImageMaths.GetColorCountForBitDepth(header.BitDepth) - 1);
+ int scaleFactor = 255 / (ColorNumerics.GetColorCountForBitDepth(header.BitDepth) - 1);
if (!hasTrans)
{
diff --git a/src/ImageSharp/Formats/Tga/TgaEncoderCore.cs b/src/ImageSharp/Formats/Tga/TgaEncoderCore.cs
index d3a628531..1d31ea9f4 100644
--- a/src/ImageSharp/Formats/Tga/TgaEncoderCore.cs
+++ b/src/ImageSharp/Formats/Tga/TgaEncoderCore.cs
@@ -365,7 +365,7 @@ namespace SixLabors.ImageSharp.Formats.Tga
where TPixel : unmanaged, IPixel
{
var vector = sourcePixel.ToVector4();
- return ImageMaths.GetBT709Luminance(ref vector, 256);
+ return ColorNumerics.GetBT709Luminance(ref vector, 256);
}
}
}
diff --git a/src/ImageSharp/ImageSharp.csproj b/src/ImageSharp/ImageSharp.csproj
index 720d6c1b7..1ed113ad4 100644
--- a/src/ImageSharp/ImageSharp.csproj
+++ b/src/ImageSharp/ImageSharp.csproj
@@ -68,62 +68,62 @@
True
PixelOperations{TPixel}.Generated.tt
-
+
True
True
Argb32.PixelOperations.Generated.tt
-
+
True
True
Bgr24.PixelOperations.Generated.tt
-
+
True
True
Bgra32.PixelOperations.Generated.tt
-
+
True
True
Bgra5551.PixelOperations.Generated.tt
-
+
True
True
- L8.PixelOperations.Generated.tt
+ L16.PixelOperations.Generated.tt
-
+
True
True
- L16.PixelOperations.Generated.tt
+ L8.PixelOperations.Generated.tt
-
+
True
True
La16.PixelOperations.Generated.tt
-
+
True
True
La32.PixelOperations.Generated.tt
-
+
True
True
Rgb24.PixelOperations.Generated.tt
-
+
True
True
- Rgba32.PixelOperations.Generated.tt
+ Rgb48.PixelOperations.Generated.tt
-
+
True
True
- Rgb48.PixelOperations.Generated.tt
+ Rgba32.PixelOperations.Generated.tt
-
+
True
True
Rgba64.PixelOperations.Generated.tt
@@ -162,51 +162,51 @@
TextTemplatingFileGenerator
PixelOperations{TPixel}.Generated.cs
-
+
TextTemplatingFileGenerator
Argb32.PixelOperations.Generated.cs
-
+
TextTemplatingFileGenerator
Bgr24.PixelOperations.Generated.cs
-
+
TextTemplatingFileGenerator
Bgra32.PixelOperations.Generated.cs
-
+
TextTemplatingFileGenerator
Bgra5551.PixelOperations.Generated.cs
-
+
TextTemplatingFileGenerator
L8.PixelOperations.Generated.cs
-
+
TextTemplatingFileGenerator
L16.PixelOperations.Generated.cs
-
+
TextTemplatingFileGenerator
La16.PixelOperations.Generated.cs
-
+
TextTemplatingFileGenerator
La32.PixelOperations.Generated.cs
-
+
TextTemplatingFileGenerator
Rgb24.PixelOperations.Generated.cs
-
+
TextTemplatingFileGenerator
Rgba32.PixelOperations.Generated.cs
-
+
TextTemplatingFileGenerator
Rgb48.PixelOperations.Generated.cs
-
+
TextTemplatingFileGenerator
Rgba64.PixelOperations.Generated.cs
diff --git a/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.cs b/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.cs
index 925a86ac2..8e9cad563 100644
--- a/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.cs
+++ b/src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.cs
@@ -40,7 +40,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc
/// The new index position
public void SetIndex(int index)
{
- this.currentIndex = index.Clamp(0, this.data.Length);
+ this.currentIndex = Numerics.Clamp(index, 0, this.data.Length);
}
///
diff --git a/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Lut.cs b/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Lut.cs
index a5eef3d23..40a1792e2 100644
--- a/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Lut.cs
+++ b/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Lut.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Six Labors.
+// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.Metadata.Profiles.Icc
@@ -17,7 +17,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc
{
foreach (float item in value.Values)
{
- this.WriteByte((byte)((item * byte.MaxValue) + 0.5f).Clamp(0, byte.MaxValue));
+ this.WriteByte((byte)Numerics.Clamp((item * byte.MaxValue) + 0.5F, 0, byte.MaxValue));
}
return value.Values.Length;
@@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc
{
foreach (float item in value.Values)
{
- this.WriteUInt16((ushort)((item * ushort.MaxValue) + 0.5f).Clamp(0, ushort.MaxValue));
+ this.WriteUInt16((ushort)Numerics.Clamp((item * ushort.MaxValue) + 0.5F, 0, ushort.MaxValue));
}
return value.Values.Length * 2;
@@ -78,7 +78,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc
{
foreach (float item in inArray)
{
- count += this.WriteByte((byte)((item * byte.MaxValue) + 0.5f).Clamp(0, byte.MaxValue));
+ count += this.WriteByte((byte)Numerics.Clamp((item * byte.MaxValue) + 0.5F, 0, byte.MaxValue));
}
}
@@ -97,7 +97,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc
{
foreach (float item in inArray)
{
- count += this.WriteUInt16((ushort)((item * ushort.MaxValue) + 0.5f).Clamp(0, ushort.MaxValue));
+ count += this.WriteUInt16((ushort)Numerics.Clamp((item * ushort.MaxValue) + 0.5F, 0, ushort.MaxValue));
}
}
diff --git a/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.NonPrimitives.cs b/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.NonPrimitives.cs
index 53dd5f008..305fe47fd 100644
--- a/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.NonPrimitives.cs
+++ b/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.NonPrimitives.cs
@@ -33,9 +33,9 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc
/// the number of bytes written
public int WriteVersionNumber(in IccVersion value)
{
- int major = value.Major.Clamp(0, byte.MaxValue);
- int minor = value.Minor.Clamp(0, 15);
- int bugfix = value.Patch.Clamp(0, 15);
+ int major = Numerics.Clamp(value.Major, 0, byte.MaxValue);
+ int minor = Numerics.Clamp(value.Minor, 0, 15);
+ int bugfix = Numerics.Clamp(value.Patch, 0, 15);
int version = (major << 24) | (minor << 20) | (bugfix << 16);
return this.WriteInt32(version);
diff --git a/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Primitives.cs b/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Primitives.cs
index 5fb8e57d2..c58dd9656 100644
--- a/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Primitives.cs
+++ b/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Primitives.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Six Labors.
+// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
@@ -112,7 +112,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc
const double Max = short.MaxValue + (65535d / 65536d);
const double Min = short.MinValue;
- value = value.Clamp(Min, Max);
+ value = Numerics.Clamp(value, Min, Max);
value *= 65536d;
return this.WriteInt32((int)Math.Round(value, MidpointRounding.AwayFromZero));
@@ -128,7 +128,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc
const double Max = ushort.MaxValue + (65535d / 65536d);
const double Min = ushort.MinValue;
- value = value.Clamp(Min, Max);
+ value = Numerics.Clamp(value, Min, Max);
value *= 65536d;
return this.WriteUInt32((uint)Math.Round(value, MidpointRounding.AwayFromZero));
@@ -144,7 +144,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc
const double Max = 1 + (32767d / 32768d);
const double Min = 0;
- value = value.Clamp(Min, Max);
+ value = Numerics.Clamp(value, Min, Max);
value *= 32768d;
return this.WriteUInt16((ushort)Math.Round(value, MidpointRounding.AwayFromZero));
@@ -160,7 +160,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc
const double Max = byte.MaxValue + (255d / 256d);
const double Min = byte.MinValue;
- value = value.Clamp(Min, Max);
+ value = Numerics.Clamp(value, Min, Max);
value *= 256d;
return this.WriteUInt16((ushort)Math.Round(value, MidpointRounding.AwayFromZero));
diff --git a/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs b/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs
index fdbf2a477..25454fa95 100644
--- a/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs
+++ b/src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs
@@ -240,7 +240,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc
count += this.WriteUInt32((uint)value.CurveData.Length);
for (int i = 0; i < value.CurveData.Length; i++)
{
- count += this.WriteUInt16((ushort)((value.CurveData[i] * ushort.MaxValue) + 0.5f).Clamp(0, ushort.MaxValue));
+ count += this.WriteUInt16((ushort)Numerics.Clamp((value.CurveData[i] * ushort.MaxValue) + 0.5F, 0, ushort.MaxValue));
}
}
diff --git a/src/ImageSharp/PixelFormats/PixelAlphaRepresentation.cs b/src/ImageSharp/PixelFormats/PixelAlphaRepresentation.cs
new file mode 100644
index 000000000..4690fb66a
--- /dev/null
+++ b/src/ImageSharp/PixelFormats/PixelAlphaRepresentation.cs
@@ -0,0 +1,32 @@
+// Copyright (c) Six Labors.
+// Licensed under the Apache License, Version 2.0.
+
+namespace SixLabors.ImageSharp.PixelFormats
+{
+ ///
+ /// Provides enumeration of the alpha value transparency behavior of a pixel format.
+ ///
+ public enum PixelAlphaRepresentation
+ {
+ ///
+ /// Indicates that the pixel format does not contain an alpha channel.
+ ///
+ None,
+
+ ///
+ /// Indicates that the transparency behavior is premultiplied.
+ /// Each color is first scaled by the alpha value. The alpha value itself is the same
+ /// in both straight and premultiplied alpha. Typically, no color channel value is
+ /// greater than the alpha channel value.
+ /// If a color channel value in a premultiplied format is greater than the alpha
+ /// channel, the standard source-over blending math results in an additive blend.
+ ///
+ Associated,
+
+ ///
+ /// Indicates that the transparency behavior is not premultiplied.
+ /// The alpha channel indicates the transparency of the color.
+ ///
+ Unassociated
+ }
+}
diff --git a/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.cs b/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.cs
index 2cb528a03..db61d9383 100644
--- a/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.cs
+++ b/src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.cs
@@ -36,14 +36,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.NormalSrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.NormalSrc(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.NormalSrc(background[i], source[i], amount);
@@ -55,7 +55,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.NormalSrc(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.NormalSrc(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -74,14 +74,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.MultiplySrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.MultiplySrc(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.MultiplySrc(background[i], source[i], amount);
@@ -93,7 +93,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.MultiplySrc(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.MultiplySrc(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -112,14 +112,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.AddSrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.AddSrc(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.AddSrc(background[i], source[i], amount);
@@ -131,7 +131,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.AddSrc(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.AddSrc(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -150,14 +150,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.SubtractSrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.SubtractSrc(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.SubtractSrc(background[i], source[i], amount);
@@ -169,7 +169,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.SubtractSrc(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.SubtractSrc(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -188,14 +188,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.ScreenSrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.ScreenSrc(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.ScreenSrc(background[i], source[i], amount);
@@ -207,7 +207,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.ScreenSrc(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.ScreenSrc(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -226,14 +226,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.DarkenSrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.DarkenSrc(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.DarkenSrc(background[i], source[i], amount);
@@ -245,7 +245,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.DarkenSrc(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.DarkenSrc(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -264,14 +264,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.LightenSrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.LightenSrc(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.LightenSrc(background[i], source[i], amount);
@@ -283,7 +283,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.LightenSrc(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.LightenSrc(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -302,14 +302,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.OverlaySrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.OverlaySrc(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.OverlaySrc(background[i], source[i], amount);
@@ -321,7 +321,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.OverlaySrc(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.OverlaySrc(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -340,14 +340,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.HardLightSrc(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.HardLightSrc(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.HardLightSrc(background[i], source[i], amount);
@@ -359,7 +359,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.HardLightSrc(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.HardLightSrc(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -378,14 +378,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.NormalSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.NormalSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.NormalSrcAtop(background[i], source[i], amount);
@@ -397,7 +397,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.NormalSrcAtop(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.NormalSrcAtop(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -416,14 +416,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.MultiplySrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.MultiplySrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.MultiplySrcAtop(background[i], source[i], amount);
@@ -435,7 +435,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.MultiplySrcAtop(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.MultiplySrcAtop(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -454,14 +454,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.AddSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.AddSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.AddSrcAtop(background[i], source[i], amount);
@@ -473,7 +473,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.AddSrcAtop(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.AddSrcAtop(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -492,14 +492,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.SubtractSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.SubtractSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.SubtractSrcAtop(background[i], source[i], amount);
@@ -511,7 +511,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.SubtractSrcAtop(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.SubtractSrcAtop(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -530,14 +530,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.ScreenSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.ScreenSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.ScreenSrcAtop(background[i], source[i], amount);
@@ -549,7 +549,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.ScreenSrcAtop(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.ScreenSrcAtop(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -568,14 +568,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.DarkenSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.DarkenSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.DarkenSrcAtop(background[i], source[i], amount);
@@ -587,7 +587,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.DarkenSrcAtop(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.DarkenSrcAtop(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -606,14 +606,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.LightenSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.LightenSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.LightenSrcAtop(background[i], source[i], amount);
@@ -625,7 +625,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.LightenSrcAtop(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.LightenSrcAtop(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -644,14 +644,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.OverlaySrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.OverlaySrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.OverlaySrcAtop(background[i], source[i], amount);
@@ -663,7 +663,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.OverlaySrcAtop(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.OverlaySrcAtop(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -682,14 +682,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.HardLightSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.HardLightSrcAtop(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.HardLightSrcAtop(background[i], source[i], amount);
@@ -701,7 +701,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.HardLightSrcAtop(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.HardLightSrcAtop(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -720,14 +720,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.NormalSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.NormalSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.NormalSrcOver(background[i], source[i], amount);
@@ -739,7 +739,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.NormalSrcOver(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.NormalSrcOver(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -758,14 +758,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.MultiplySrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.MultiplySrcOver(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.MultiplySrcOver(background[i], source[i], amount);
@@ -777,7 +777,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.MultiplySrcOver(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.MultiplySrcOver(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -796,14 +796,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.AddSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.AddSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.AddSrcOver(background[i], source[i], amount);
@@ -815,7 +815,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.AddSrcOver(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.AddSrcOver(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -834,14 +834,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.SubtractSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.SubtractSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.SubtractSrcOver(background[i], source[i], amount);
@@ -853,7 +853,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.SubtractSrcOver(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.SubtractSrcOver(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -872,14 +872,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.ScreenSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.ScreenSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.ScreenSrcOver(background[i], source[i], amount);
@@ -891,7 +891,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.ScreenSrcOver(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.ScreenSrcOver(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -910,14 +910,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.DarkenSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.DarkenSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.DarkenSrcOver(background[i], source[i], amount);
@@ -929,7 +929,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.DarkenSrcOver(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.DarkenSrcOver(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -948,14 +948,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.LightenSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.LightenSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.LightenSrcOver(background[i], source[i], amount);
@@ -967,7 +967,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.LightenSrcOver(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.LightenSrcOver(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -986,14 +986,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.OverlaySrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.OverlaySrcOver(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.OverlaySrcOver(background[i], source[i], amount);
@@ -1005,7 +1005,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.OverlaySrcOver(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.OverlaySrcOver(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -1024,14 +1024,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.HardLightSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.HardLightSrcOver(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.HardLightSrcOver(background[i], source[i], amount);
@@ -1043,7 +1043,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.HardLightSrcOver(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.HardLightSrcOver(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -1062,14 +1062,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.NormalSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.NormalSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.NormalSrcIn(background[i], source[i], amount);
@@ -1081,7 +1081,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.NormalSrcIn(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.NormalSrcIn(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -1100,14 +1100,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.MultiplySrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.MultiplySrcIn(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.MultiplySrcIn(background[i], source[i], amount);
@@ -1119,7 +1119,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.MultiplySrcIn(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.MultiplySrcIn(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -1138,14 +1138,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.AddSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.AddSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.AddSrcIn(background[i], source[i], amount);
@@ -1157,7 +1157,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.AddSrcIn(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.AddSrcIn(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -1176,14 +1176,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.SubtractSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.SubtractSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.SubtractSrcIn(background[i], source[i], amount);
@@ -1195,7 +1195,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.SubtractSrcIn(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.SubtractSrcIn(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -1214,14 +1214,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.ScreenSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.ScreenSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.ScreenSrcIn(background[i], source[i], amount);
@@ -1233,7 +1233,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.ScreenSrcIn(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.ScreenSrcIn(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -1252,14 +1252,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.DarkenSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.DarkenSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.DarkenSrcIn(background[i], source[i], amount);
@@ -1271,7 +1271,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.DarkenSrcIn(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.DarkenSrcIn(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -1290,14 +1290,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.LightenSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.LightenSrcIn(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan background, ReadOnlySpan source, float amount)
{
- amount = amount.Clamp(0, 1);
+ amount = Numerics.Clamp(amount, 0, 1);
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.LightenSrcIn(background[i], source[i], amount);
@@ -1309,7 +1309,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
- destination[i] = PorterDuffFunctions.LightenSrcIn(background[i], source[i], amount[i].Clamp(0, 1));
+ destination[i] = PorterDuffFunctions.LightenSrcIn(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}
@@ -1328,14 +1328,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
- dest.FromScaledVector4(PorterDuffFunctions.OverlaySrcIn(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
+ dest.FromScaledVector4(PorterDuffFunctions.OverlaySrcIn(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
///
protected override void BlendFunction(Span destination, ReadOnlySpan