Browse Source

Merge pull request #1436 from SixLabors/js/clamp-utils

Introduce Numerics class and Refactor Clamp Utils
js/color-alpha-handling
James Jackson-South 6 years ago
committed by GitHub
parent
commit
c1cb2f1420
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 14
      src/ImageSharp/Color/Color.cs
  2. 2
      src/ImageSharp/ColorSpaces/Cmyk.cs
  3. 2
      src/ImageSharp/ColorSpaces/Companding/LCompanding.cs
  4. 6
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLabToCieXyzConverter.cs
  5. 6
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/CieLuvToCieXyzConverter.cs
  6. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/Converters/HunterLabToCieXyzConverter.cs
  7. 140
      src/ImageSharp/Common/Extensions/ComparableExtensions.cs
  8. 8
      src/ImageSharp/Common/Helpers/Buffer2DUtils.cs
  9. 177
      src/ImageSharp/Common/Helpers/ColorNumerics.cs
  10. 20
      src/ImageSharp/Common/Helpers/DenseMatrixUtils.cs
  11. 379
      src/ImageSharp/Common/Helpers/ImageMaths.cs
  12. 551
      src/ImageSharp/Common/Helpers/Numerics.cs
  13. 2
      src/ImageSharp/Common/Helpers/Shuffle/IShuffle4Slice3.cs
  14. 4
      src/ImageSharp/Common/Helpers/SimdUtils.BasicIntrinsics256.cs
  15. 4
      src/ImageSharp/Common/Helpers/SimdUtils.ExtendedIntrinsics.cs
  16. 6
      src/ImageSharp/Common/Helpers/SimdUtils.FallbackIntrinsics128.cs
  17. 24
      src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs
  18. 8
      src/ImageSharp/Common/Helpers/SimdUtils.cs
  19. 181
      src/ImageSharp/Common/Helpers/Vector4Utilities.cs
  20. 4
      src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
  21. 6
      src/ImageSharp/Formats/Gif/GifEncoderCore.cs
  22. 32
      src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs
  23. 2
      src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt
  24. 2
      src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs
  25. 4
      src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
  26. 8
      src/ImageSharp/Formats/Png/Filters/AverageFilter.cs
  27. 14
      src/ImageSharp/Formats/Png/Filters/PaethFilter.cs
  28. 4
      src/ImageSharp/Formats/Png/Filters/SubFilter.cs
  29. 2
      src/ImageSharp/Formats/Png/Filters/UpFilter.cs
  30. 6
      src/ImageSharp/Formats/Png/PngEncoderCore.cs
  31. 4
      src/ImageSharp/Formats/Png/PngEncoderOptionsHelpers.cs
  32. 4
      src/ImageSharp/Formats/Png/PngScanlineProcessor.cs
  33. 2
      src/ImageSharp/Formats/Tga/TgaEncoderCore.cs
  34. 2
      src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.cs
  35. 10
      src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Lut.cs
  36. 6
      src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.NonPrimitives.cs
  37. 10
      src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.Primitives.cs
  38. 2
      src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.TagDataEntry.cs
  39. 648
      src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.cs
  40. 6
      src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.tt
  41. 216
      src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.cs
  42. 2
      src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.tt
  43. 4
      src/ImageSharp/PixelFormats/PixelImplementations/A8.cs
  44. 22
      src/ImageSharp/PixelFormats/PixelImplementations/Argb32.cs
  45. 16
      src/ImageSharp/PixelFormats/PixelImplementations/Bgr24.cs
  46. 22
      src/ImageSharp/PixelFormats/PixelImplementations/Bgra32.cs
  47. 2
      src/ImageSharp/PixelFormats/PixelImplementations/Bgra4444.cs
  48. 2
      src/ImageSharp/PixelFormats/PixelImplementations/Bgra5551.cs
  49. 2
      src/ImageSharp/PixelFormats/PixelImplementations/Byte4.cs
  50. 54
      src/ImageSharp/PixelFormats/PixelImplementations/L16.cs
  51. 34
      src/ImageSharp/PixelFormats/PixelImplementations/L8.cs
  52. 38
      src/ImageSharp/PixelFormats/PixelImplementations/La16.cs
  53. 64
      src/ImageSharp/PixelFormats/PixelImplementations/La32.cs
  54. 2
      src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte4.cs
  55. 2
      src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort4.cs
  56. 18
      src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs
  57. 42
      src/ImageSharp/PixelFormats/PixelImplementations/Rgb48.cs
  58. 2
      src/ImageSharp/PixelFormats/PixelImplementations/Rgba1010102.cs
  59. 24
      src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs
  60. 126
      src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs
  61. 2
      src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs
  62. 2
      src/ImageSharp/PixelFormats/PixelImplementations/Short4.cs
  63. 4
      src/ImageSharp/PixelFormats/Utils/Vector4Converters.cs
  64. 2
      src/ImageSharp/Primitives/ComplexVector4.cs
  65. 8
      src/ImageSharp/Primitives/Number.cs
  66. 14
      src/ImageSharp/Processing/AffineTransformBuilder.cs
  67. 4
      src/ImageSharp/Processing/Extensions/Transforms/TransformExtensions.cs
  68. 2
      src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs
  69. 2
      src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs
  70. 6
      src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessorHelpers.cs
  71. 12
      src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs
  72. 2
      src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor.cs
  73. 5
      src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor{TPixel}.cs
  74. 2
      src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs
  75. 8
      src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationSlidingWindowProcessor{TPixel}.cs
  76. 4
      src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs
  77. 2
      src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationProcessor{TPixel}.cs
  78. 2
      src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs
  79. 2
      src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor{TPixel}.cs
  80. 2
      src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer{TPixel}.cs
  81. 4
      src/ImageSharp/Processing/Processors/Quantization/QuantizerOptions.cs
  82. 135
      src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor{TPixel}.cs
  83. 6
      src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs
  84. 8
      src/ImageSharp/Processing/Processors/Transforms/Linear/LinearTransformUtils.cs
  85. 10
      src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs
  86. 4
      src/ImageSharp/Processing/Processors/Transforms/Linear/RotateProcessor.cs
  87. 4
      src/ImageSharp/Processing/Processors/Transforms/Linear/SkewProcessor.cs
  88. 2
      src/ImageSharp/Processing/Processors/Transforms/Resamplers/LanczosResampler.cs
  89. 2
      src/ImageSharp/Processing/Processors/Transforms/Resamplers/WelchResampler.cs
  90. 2
      src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.cs
  91. 2
      src/ImageSharp/Processing/Processors/Transforms/TransformUtils.cs
  92. 14
      src/ImageSharp/Processing/ProjectiveTransformBuilder.cs
  93. 2
      tests/ImageSharp.Benchmarks/Color/Bulk/PremultiplyVector4.cs
  94. 2
      tests/ImageSharp.Benchmarks/Color/Bulk/UnPremultiplyVector4.cs
  95. 19
      tests/ImageSharp.Benchmarks/Color/YcbCrToRgb.cs
  96. 57
      tests/ImageSharp.Benchmarks/General/BasicMath/ClampSpan.cs
  97. 2
      tests/ImageSharp.Benchmarks/General/BasicMath/ModuloPowerOfTwoConstant.cs
  98. 2
      tests/ImageSharp.Benchmarks/General/BasicMath/ModuloPowerOfTwoVariable.cs
  99. 2
      tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs
  100. 31
      tests/ImageSharp.Tests/Helpers/ColorNumericsTests.cs

14
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);
}

2
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;

2
src/ImageSharp/ColorSpaces/Companding/LCompanding.cs

@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Companding
/// <returns>The <see cref="float"/> representing the linear channel value.</returns>
[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);
/// <summary>
/// Compresses an uncompanded channel (linear) to its nonlinear equivalent.

6
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);

6
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));
}
}
}

2
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;

140
src/ImageSharp/Common/Extensions/ComparableExtensions.cs

@ -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
{
/// <summary>
/// Extension methods for classes that implement <see cref="IComparable{T}"/>.
/// </summary>
internal static class ComparableExtensions
{
/// <summary>
/// Restricts a <see cref="byte"/> to be within a specified range.
/// </summary>
/// <param name="value">The value to clamp.</param>
/// <param name="min">The minimum value. If value is less than min, min will be returned.</param>
/// <param name="max">The maximum value. If value is greater than max, max will be returned.</param>
/// <returns>
/// The <see cref="byte"/> representing the clamped value.
/// </returns>
[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;
}
/// <summary>
/// Restricts a <see cref="uint"/> to be within a specified range.
/// </summary>
/// <param name="value">The The value to clamp.</param>
/// <param name="min">The minimum value. If value is less than min, min will be returned.</param>
/// <param name="max">The maximum value. If value is greater than max, max will be returned.</param>
/// <returns>
/// The <see cref="int"/> representing the clamped value.
/// </returns>
[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;
}
/// <summary>
/// Restricts a <see cref="int"/> to be within a specified range.
/// </summary>
/// <param name="value">The The value to clamp.</param>
/// <param name="min">The minimum value. If value is less than min, min will be returned.</param>
/// <param name="max">The maximum value. If value is greater than max, max will be returned.</param>
/// <returns>
/// The <see cref="int"/> representing the clamped value.
/// </returns>
[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;
}
/// <summary>
/// Restricts a <see cref="float"/> to be within a specified range.
/// </summary>
/// <param name="value">The The value to clamp.</param>
/// <param name="min">The minimum value. If value is less than min, min will be returned.</param>
/// <param name="max">The maximum value. If value is greater than max, max will be returned.</param>
/// <returns>
/// The <see cref="float"/> representing the clamped value.
/// </returns>
[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;
}
/// <summary>
/// Restricts a <see cref="double"/> to be within a specified range.
/// </summary>
/// <param name="value">The The value to clamp.</param>
/// <param name="min">The minimum value. If value is less than min, min will be returned.</param>
/// <param name="max">The maximum value. If value is greater than max, max will be returned.</param>
/// <returns>
/// The <see cref="double"/> representing the clamped value.
/// </returns>
[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;
}
}
}

8
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<TPixel> 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));
}

177
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
{
/// <summary>
/// Provides optimized static methods for common mathematical functions specific
/// to color processing.
/// </summary>
internal static class ColorNumerics
{
/// <summary>
/// Vector for converting pixel to gray value as specified by
/// ITU-R Recommendation BT.709.
/// </summary>
private static readonly Vector4 Bt709 = new Vector4(.2126f, .7152f, .0722f, 0.0f);
/// <summary>
/// Convert a pixel value to grayscale using ITU-R Recommendation BT.709.
/// </summary>
/// <param name="vector">The vector to get the luminance from.</param>
/// <param name="luminanceLevels">
/// The number of luminance levels (256 for 8 bit, 65536 for 16 bit grayscale images).
/// </param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GetBT709Luminance(ref Vector4 vector, int luminanceLevels)
=> (int)MathF.Round(Vector4.Dot(vector, Bt709) * (luminanceLevels - 1));
/// <summary>
/// Gets the luminance from the rgb components using the formula
/// as specified by ITU-R Recommendation BT.709.
/// </summary>
/// <param name="r">The red component.</param>
/// <param name="g">The green component.</param>
/// <param name="b">The blue component.</param>
/// <returns>The <see cref="byte"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte Get8BitBT709Luminance(byte r, byte g, byte b)
=> (byte)((r * .2126F) + (g * .7152F) + (b * .0722F) + 0.5F);
/// <summary>
/// Gets the luminance from the rgb components using the formula as
/// specified by ITU-R Recommendation BT.709.
/// </summary>
/// <param name="r">The red component.</param>
/// <param name="g">The green component.</param>
/// <param name="b">The blue component.</param>
/// <returns>The <see cref="ushort"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ushort Get16BitBT709Luminance(ushort r, ushort g, ushort b)
=> (ushort)((r * .2126F) + (g * .7152F) + (b * .0722F) + 0.5F);
/// <summary>
/// Gets the luminance from the rgb components using the formula as specified
/// by ITU-R Recommendation BT.709.
/// </summary>
/// <param name="r">The red component.</param>
/// <param name="g">The green component.</param>
/// <param name="b">The blue component.</param>
/// <returns>The <see cref="ushort"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ushort Get16BitBT709Luminance(float r, float g, float b)
=> (ushort)((r * .2126F) + (g * .7152F) + (b * .0722F) + 0.5F);
/// <summary>
/// Scales a value from a 16 bit <see cref="ushort"/> to an
/// 8 bit <see cref="byte"/> equivalent.
/// </summary>
/// <param name="component">The 8 bit component value.</param>
/// <returns>The <see cref="byte"/></returns>
[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);
}
/// <summary>
/// Scales a value from an 8 bit <see cref="byte"/> to
/// an 16 bit <see cref="ushort"/> equivalent.
/// </summary>
/// <param name="component">The 8 bit component value.</param>
/// <returns>The <see cref="ushort"/></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ushort UpscaleFrom8BitTo16Bit(byte component)
=> (ushort)(component * 257);
/// <summary>
/// Returns how many bits are required to store the specified number of colors.
/// Performs a Log2() on the value.
/// </summary>
/// <param name="colors">The number of colors.</param>
/// <returns>
/// The <see cref="int"/>
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GetBitsNeededForColorDepth(int colors)
=> Math.Max(1, (int)Math.Ceiling(Math.Log(colors, 2)));
/// <summary>
/// Returns how many colors will be created by the specified number of bits.
/// </summary>
/// <param name="bitDepth">The bit depth.</param>
/// <returns>The <see cref="int"/></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GetColorCountForBitDepth(int bitDepth)
=> 1 << bitDepth;
/// <summary>
/// Transforms a vector by the given color matrix.
/// </summary>
/// <param name="vector">The source vector.</param>
/// <param name="matrix">The transformation color matrix.</param>
[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;
}
/// <summary>
/// Bulk variant of <see cref="Transform(ref Vector4, ref ColorMatrix)"/>.
/// </summary>
/// <param name="vectors">The span of vectors</param>
/// <param name="matrix">The transformation color matrix.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Transform(Span<Vector4> 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);
}
}
}
}

20
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<TPixel> 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<TPixel> 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;
}
}

379
src/ImageSharp/Common/Helpers/ImageMaths.cs

@ -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
{
/// <summary>
/// Provides common mathematical methods.
/// </summary>
internal static class ImageMaths
{
/// <summary>
/// Vector for converting pixel to gray value as specified by ITU-R Recommendation BT.709.
/// </summary>
private static readonly Vector4 Bt709 = new Vector4(.2126f, .7152f, .0722f, 0.0f);
/// <summary>
/// Convert a pixel value to grayscale using ITU-R Recommendation BT.709.
/// </summary>
/// <param name="vector">The vector to get the luminance from.</param>
/// <param name="luminanceLevels">The number of luminance levels (256 for 8 bit, 65536 for 16 bit grayscale images)</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static int GetBT709Luminance(ref Vector4 vector, int luminanceLevels)
=> (int)MathF.Round(Vector4.Dot(vector, Bt709) * (luminanceLevels - 1));
/// <summary>
/// Gets the luminance from the rgb components using the formula as specified by ITU-R Recommendation BT.709.
/// </summary>
/// <param name="r">The red component.</param>
/// <param name="g">The green component.</param>
/// <param name="b">The blue component.</param>
/// <returns>The <see cref="byte"/>.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static byte Get8BitBT709Luminance(byte r, byte g, byte b) =>
(byte)((r * .2126F) + (g * .7152F) + (b * .0722F) + 0.5F);
/// <summary>
/// Gets the luminance from the rgb components using the formula as specified by ITU-R Recommendation BT.709.
/// </summary>
/// <param name="r">The red component.</param>
/// <param name="g">The green component.</param>
/// <param name="b">The blue component.</param>
/// <returns>The <see cref="ushort"/>.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static ushort Get16BitBT709Luminance(ushort r, ushort g, ushort b) =>
(ushort)((r * .2126F) + (g * .7152F) + (b * .0722F) + 0.5F);
/// <summary>
/// Gets the luminance from the rgb components using the formula as specified by ITU-R Recommendation BT.709.
/// </summary>
/// <param name="r">The red component.</param>
/// <param name="g">The green component.</param>
/// <param name="b">The blue component.</param>
/// <returns>The <see cref="ushort"/>.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static ushort Get16BitBT709Luminance(float r, float g, float b) =>
(ushort)((r * .2126F) + (g * .7152F) + (b * .0722F) + 0.5F);
/// <summary>
/// Scales a value from a 16 bit <see cref="ushort"/> to it's 8 bit <see cref="byte"/> equivalent.
/// </summary>
/// <param name="component">The 8 bit component value.</param>
/// <returns>The <see cref="byte"/></returns>
[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);
}
/// <summary>
/// Scales a value from an 8 bit <see cref="byte"/> to it's 16 bit <see cref="ushort"/> equivalent.
/// </summary>
/// <param name="component">The 8 bit component value.</param>
/// <returns>The <see cref="ushort"/></returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static ushort UpscaleFrom8BitTo16Bit(byte component) => (ushort)(component * 257);
/// <summary>
/// Determine the Greatest CommonDivisor (GCD) of two numbers.
/// </summary>
public static int GreatestCommonDivisor(int a, int b)
{
while (b != 0)
{
int temp = b;
b = a % b;
a = temp;
}
return a;
}
/// <summary>
/// Determine the Least Common Multiple (LCM) of two numbers.
/// </summary>
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;
}
/// <summary>
/// Calculates <paramref name="x"/> % 2
/// </summary>
[MethodImpl(InliningOptions.ShortMethod)]
public static int Modulo2(int x) => x & 1;
/// <summary>
/// Calculates <paramref name="x"/> % 4
/// </summary>
[MethodImpl(InliningOptions.ShortMethod)]
public static int Modulo4(int x) => x & 3;
/// <summary>
/// Calculates <paramref name="x"/> % 8
/// </summary>
[MethodImpl(InliningOptions.ShortMethod)]
public static int Modulo8(int x) => x & 7;
/// <summary>
/// Fast (x mod m) calculator, with the restriction that
/// <paramref name="m"/> should be power of 2.
/// </summary>
[MethodImpl(InliningOptions.ShortMethod)]
public static int ModuloP2(int x, int m) => x & (m - 1);
/// <summary>
/// Returns the absolute value of a 32-bit signed integer. Uses bit shifting to speed up the operation.
/// </summary>
/// <param name="x">
/// A number that is greater than <see cref="int.MinValue"/>, but less than or equal to <see cref="int.MaxValue"/>
/// </param>
/// <returns>The <see cref="int"/></returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static int FastAbs(int x)
{
int y = x >> 31;
return (x ^ y) - y;
}
/// <summary>
/// Returns a specified number raised to the power of 2
/// </summary>
/// <param name="x">A single-precision floating-point number</param>
/// <returns>The number <paramref name="x" /> raised to the power of 2.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static float Pow2(float x) => x * x;
/// <summary>
/// Returns a specified number raised to the power of 3
/// </summary>
/// <param name="x">A single-precision floating-point number</param>
/// <returns>The number <paramref name="x" /> raised to the power of 3.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static float Pow3(float x) => x * x * x;
/// <summary>
/// Returns how many bits are required to store the specified number of colors.
/// Performs a Log2() on the value.
/// </summary>
/// <param name="colors">The number of colors.</param>
/// <returns>
/// The <see cref="int"/>
/// </returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static int GetBitsNeededForColorDepth(int colors) => Math.Max(1, (int)Math.Ceiling(Math.Log(colors, 2)));
/// <summary>
/// Returns how many colors will be created by the specified number of bits.
/// </summary>
/// <param name="bitDepth">The bit depth.</param>
/// <returns>The <see cref="int"/></returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static int GetColorCountForBitDepth(int bitDepth) => 1 << bitDepth;
/// <summary>
/// Implementation of 1D Gaussian G(x) function
/// </summary>
/// <param name="x">The x provided to G(x).</param>
/// <param name="sigma">The spread of the blur.</param>
/// <returns>The Gaussian G(x)</returns>
[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;
}
/// <summary>
/// Returns the result of a normalized sine cardinal function for the given value.
/// SinC(x) = sin(pi*x)/(pi*x).
/// </summary>
/// <param name="f">A single-precision floating-point number to calculate the result for.</param>
/// <returns>
/// The sine cardinal of <paramref name="f" />.
/// </returns>
[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;
}
/// <summary>
/// Gets the bounding <see cref="Rectangle"/> from the given points.
/// </summary>
/// <param name="topLeft">
/// The <see cref="Point"/> designating the top left position.
/// </param>
/// <param name="bottomRight">
/// The <see cref="Point"/> designating the bottom right position.
/// </param>
/// <returns>
/// The bounding <see cref="Rectangle"/>.
/// </returns>
[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);
/// <summary>
/// Finds the bounding rectangle based on the first instance of any color component other
/// than the given one.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="bitmap">The <see cref="Image{TPixel}"/> to search within.</param>
/// <param name="componentValue">The color component value to remove.</param>
/// <param name="channel">The <see cref="RgbaComponent"/> channel to test against.</param>
/// <returns>
/// The <see cref="Rectangle"/>.
/// </returns>
public static Rectangle GetFilteredBoundingRectangle<TPixel>(ImageFrame<TPixel> bitmap, float componentValue, RgbaComponent channel = RgbaComponent.B)
where TPixel : unmanaged, IPixel<TPixel>
{
int width = bitmap.Width;
int height = bitmap.Height;
Point topLeft = default;
Point bottomRight = default;
Func<ImageFrame<TPixel>, 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<TPixel> 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<TPixel> 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<TPixel> 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<TPixel> 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);
}
}
}

551
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
{
/// <summary>
/// Provides optimized static methods for trigonometric, logarithmic,
/// and other common mathematical functions.
/// </summary>
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
/// <summary>
/// Determine the Greatest CommonDivisor (GCD) of two numbers.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GreatestCommonDivisor(int a, int b)
{
while (b != 0)
{
int temp = b;
b = a % b;
a = temp;
}
return a;
}
/// <summary>
/// Determine the Least Common Multiple (LCM) of two numbers.
/// </summary>
[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;
}
/// <summary>
/// Calculates <paramref name="x"/> % 2
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Modulo2(int x) => x & 1;
/// <summary>
/// Calculates <paramref name="x"/> % 4
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Modulo4(int x) => x & 3;
/// <summary>
/// Calculates <paramref name="x"/> % 8
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Modulo8(int x) => x & 7;
/// <summary>
/// Fast (x mod m) calculator, with the restriction that
/// <paramref name="m"/> should be power of 2.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int ModuloP2(int x, int m) => x & (m - 1);
/// <summary>
/// Returns the absolute value of a 32-bit signed integer.
/// Uses bit shifting to speed up the operation compared to <see cref="Math"/>.
/// </summary>
/// <param name="x">
/// A number that is greater than <see cref="int.MinValue"/>, but less than
/// or equal to <see cref="int.MaxValue"/>
/// </param>
/// <returns>The <see cref="int"/></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Abs(int x)
{
int y = x >> 31;
return (x ^ y) - y;
}
/// <summary>
/// Returns a specified number raised to the power of 2
/// </summary>
/// <param name="x">A single-precision floating-point number</param>
/// <returns>The number <paramref name="x" /> raised to the power of 2.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float Pow2(float x) => x * x;
/// <summary>
/// Returns a specified number raised to the power of 3
/// </summary>
/// <param name="x">A single-precision floating-point number</param>
/// <returns>The number <paramref name="x" /> raised to the power of 3.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float Pow3(float x) => x * x * x;
/// <summary>
/// Implementation of 1D Gaussian G(x) function
/// </summary>
/// <param name="x">The x provided to G(x).</param>
/// <param name="sigma">The spread of the blur.</param>
/// <returns>The Gaussian G(x)</returns>
[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;
}
/// <summary>
/// Returns the result of a normalized sine cardinal function for the given value.
/// SinC(x) = sin(pi*x)/(pi*x).
/// </summary>
/// <param name="f">A single-precision floating-point number to calculate the result for.</param>
/// <returns>
/// The sine cardinal of <paramref name="f" />.
/// </returns>
[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;
}
/// <summary>
/// Returns the value clamped to the inclusive range of min and max.
/// </summary>
/// <param name="value">The value to clamp.</param>
/// <param name="min">The minimum inclusive value.</param>
/// <param name="max">The maximum inclusive value.</param>
/// <returns>The clamped <see cref="byte"/>.</returns>
[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;
}
/// <summary>
/// Returns the value clamped to the inclusive range of min and max.
/// </summary>
/// <param name="value">The value to clamp.</param>
/// <param name="min">The minimum inclusive value.</param>
/// <param name="max">The maximum inclusive value.</param>
/// <returns>The clamped <see cref="uint"/>.</returns>
[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;
}
/// <summary>
/// Returns the value clamped to the inclusive range of min and max.
/// </summary>
/// <param name="value">The value to clamp.</param>
/// <param name="min">The minimum inclusive value.</param>
/// <param name="max">The maximum inclusive value.</param>
/// <returns>The clamped <see cref="uint"/>.</returns>
[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;
}
/// <summary>
/// Returns the value clamped to the inclusive range of min and max.
/// </summary>
/// <param name="value">The value to clamp.</param>
/// <param name="min">The minimum inclusive value.</param>
/// <param name="max">The maximum inclusive value.</param>
/// <returns>The clamped <see cref="float"/>.</returns>
[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;
}
/// <summary>
/// Returns the value clamped to the inclusive range of min and max.
/// </summary>
/// <param name="value">The value to clamp.</param>
/// <param name="min">The minimum inclusive value.</param>
/// <param name="max">The maximum inclusive value.</param>
/// <returns>The clamped <see cref="double"/>.</returns>
[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;
}
/// <summary>
/// Returns the value clamped to the inclusive range of min and max.
/// 5x Faster than <see cref="Vector4.Clamp(Vector4, Vector4, Vector4)"/>
/// on platforms &lt; NET 5.
/// </summary>
/// <param name="value">The value to clamp.</param>
/// <param name="min">The minimum inclusive value.</param>
/// <param name="max">The maximum inclusive value.</param>
/// <returns>The clamped <see cref="Vector4"/>.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4 Clamp(Vector4 value, Vector4 min, Vector4 max)
=> Vector4.Min(Vector4.Max(value, min), max);
/// <summary>
/// Clamps the span values to the inclusive range of min and max.
/// </summary>
/// <param name="span">The span containing the values to clamp.</param>
/// <param name="min">The minimum inclusive value.</param>
/// <param name="max">The maximum inclusive value.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Clamp(Span<byte> span, byte min, byte max)
{
Span<byte> 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);
}
}
}
/// <summary>
/// Clamps the span values to the inclusive range of min and max.
/// </summary>
/// <param name="span">The span containing the values to clamp.</param>
/// <param name="min">The minimum inclusive value.</param>
/// <param name="max">The maximum inclusive value.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Clamp(Span<uint> span, uint min, uint max)
{
Span<uint> 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);
}
}
}
/// <summary>
/// Clamps the span values to the inclusive range of min and max.
/// </summary>
/// <param name="span">The span containing the values to clamp.</param>
/// <param name="min">The minimum inclusive value.</param>
/// <param name="max">The maximum inclusive value.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Clamp(Span<int> span, int min, int max)
{
Span<int> 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);
}
}
}
/// <summary>
/// Clamps the span values to the inclusive range of min and max.
/// </summary>
/// <param name="span">The span containing the values to clamp.</param>
/// <param name="min">The minimum inclusive value.</param>
/// <param name="max">The maximum inclusive value.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Clamp(Span<float> span, float min, float max)
{
Span<float> 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);
}
}
}
/// <summary>
/// Clamps the span values to the inclusive range of min and max.
/// </summary>
/// <param name="span">The span containing the values to clamp.</param>
/// <param name="min">The minimum inclusive value.</param>
/// <param name="max">The maximum inclusive value.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Clamp(Span<double> span, double min, double max)
{
Span<double> 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<T>(Span<T> span, T min, T max)
where T : unmanaged
{
if (Vector.IsHardwareAccelerated && span.Length >= Vector<T>.Count)
{
int remainder = ModuloP2(span.Length, Vector<T>.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<T>(Span<T> span, T min, T max)
where T : unmanaged
{
ref T sRef = ref MemoryMarshal.GetReference(span);
ref Vector<T> vsBase = ref Unsafe.As<T, Vector<T>>(ref MemoryMarshal.GetReference(span));
var vmin = new Vector<T>(min);
var vmax = new Vector<T>(max);
int n = span.Length / Vector<T>.Count;
int m = Modulo4(n);
int u = n - m;
for (int i = 0; i < u; i += 4)
{
ref Vector<T> vs0 = ref Unsafe.Add(ref vsBase, i);
ref Vector<T> vs1 = ref Unsafe.Add(ref vs0, 1);
ref Vector<T> vs2 = ref Unsafe.Add(ref vs0, 2);
ref Vector<T> 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<T> vs0 = ref Unsafe.Add(ref vsBase, i);
vs0 = Vector.Min(Vector.Max(vmin, vs0), vmax);
}
}
}
/// <summary>
/// Pre-multiplies the "x", "y", "z" components of a vector by its "w" component leaving the "w" component intact.
/// </summary>
/// <param name="source">The <see cref="Vector4"/> to premultiply</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Premultiply(ref Vector4 source)
{
float w = source.W;
source *= w;
source.W = w;
}
/// <summary>
/// Reverses the result of premultiplying a vector via <see cref="Premultiply(ref Vector4)"/>.
/// </summary>
/// <param name="source">The <see cref="Vector4"/> to premultiply</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void UnPremultiply(ref Vector4 source)
{
float w = source.W;
source /= w;
source.W = w;
}
/// <summary>
/// Bulk variant of <see cref="Premultiply(ref Vector4)"/>
/// </summary>
/// <param name="vectors">The span of vectors</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Premultiply(Span<Vector4> vectors)
{
#if SUPPORTS_RUNTIME_INTRINSICS
if (Avx2.IsSupported && vectors.Length >= 2)
{
ref Vector256<float> vectorsBase =
ref Unsafe.As<Vector4, Vector256<float>>(ref MemoryMarshal.GetReference(vectors));
// Divide by 2 as 4 elements per Vector4 and 8 per Vector256<float>
ref Vector256<float> vectorsLast = ref Unsafe.Add(ref vectorsBase, (IntPtr)((uint)vectors.Length / 2u));
while (Unsafe.IsAddressLessThan(ref vectorsBase, ref vectorsLast))
{
Vector256<float> source = vectorsBase;
Vector256<float> 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);
}
}
}
/// <summary>
/// Bulk variant of <see cref="UnPremultiply(ref Vector4)"/>
/// </summary>
/// <param name="vectors">The span of vectors</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void UnPremultiply(Span<Vector4> vectors)
{
#if SUPPORTS_RUNTIME_INTRINSICS
if (Avx2.IsSupported && vectors.Length >= 2)
{
ref Vector256<float> vectorsBase =
ref Unsafe.As<Vector4, Vector256<float>>(ref MemoryMarshal.GetReference(vectors));
// Divide by 2 as 4 elements per Vector4 and 8 per Vector256<float>
ref Vector256<float> vectorsLast = ref Unsafe.Add(ref vectorsBase, (IntPtr)((uint)vectors.Length / 2u));
while (Unsafe.IsAddressLessThan(ref vectorsBase, ref vectorsLast))
{
Vector256<float> source = vectorsBase;
Vector256<float> 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);
}
}
}
}
}

2
src/ImageSharp/Common/Helpers/Shuffle/IShuffle4Slice3.cs

@ -67,7 +67,7 @@ namespace SixLabors.ImageSharp
ref Byte3 dBase = ref Unsafe.As<byte, Byte3>(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);

4
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)

4
src/ImageSharp/Common/Helpers/SimdUtils.ExtendedIntrinsics.cs

@ -57,7 +57,7 @@ namespace SixLabors.ImageSharp
return;
}
int remainder = ImageMaths.ModuloP2(source.Length, Vector<byte>.Count);
int remainder = Numerics.ModuloP2(source.Length, Vector<byte>.Count);
int adjustedCount = source.Length - remainder;
if (adjustedCount > 0)
@ -84,7 +84,7 @@ namespace SixLabors.ImageSharp
return;
}
int remainder = ImageMaths.ModuloP2(source.Length, Vector<byte>.Count);
int remainder = Numerics.ModuloP2(source.Length, Vector<byte>.Count);
int adjustedCount = source.Length - remainder;
if (adjustedCount > 0)

6
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;

24
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<float>.Count)
: ImageMaths.ModuloP2(source.Length, Vector128<float>.Count);
? Numerics.ModuloP2(source.Length, Vector256<float>.Count)
: Numerics.ModuloP2(source.Length, Vector128<float>.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<byte>.Count)
: ImageMaths.ModuloP2(source.Length, Vector128<byte>.Count);
? Numerics.ModuloP2(source.Length, Vector256<byte>.Count)
: Numerics.ModuloP2(source.Length, Vector128<byte>.Count);
int adjustedCount = source.Length - remainder;
@ -203,7 +203,7 @@ namespace SixLabors.ImageSharp
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(dest));
int n = dest.Length / Vector256<float>.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<float, Vector128<float>>(ref MemoryMarshal.GetReference(dest));
int n = dest.Length / Vector128<float>.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<byte, Vector256<byte>>(ref MemoryMarshal.GetReference(dest));
int n = dest.Length / Vector256<byte>.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<byte, Vector128<byte>>(ref MemoryMarshal.GetReference(dest));
int n = dest.Length / Vector128<byte>.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<byte>.Count);
remainder = Numerics.ModuloP2(source.Length, Vector256<byte>.Count);
}
else
{
remainder = ImageMaths.ModuloP2(source.Length, Vector128<byte>.Count);
remainder = Numerics.ModuloP2(source.Length, Vector128<byte>.Count);
}
int adjustedCount = source.Length - remainder;
@ -683,11 +683,11 @@ namespace SixLabors.ImageSharp
int remainder;
if (Avx2.IsSupported)
{
remainder = ImageMaths.ModuloP2(source.Length, Vector256<byte>.Count);
remainder = Numerics.ModuloP2(source.Length, Vector256<byte>.Count);
}
else
{
remainder = ImageMaths.ModuloP2(source.Length, Vector128<byte>.Count);
remainder = Numerics.ModuloP2(source.Length, Vector128<byte>.Count);
}
int adjustedCount = source.Length - remainder;

8
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}!");
}

181
src/ImageSharp/Common/Helpers/Vector4Utilities.cs

@ -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
{
/// <summary>
/// Utility methods for the <see cref="Vector4"/> struct.
/// </summary>
internal static class Vector4Utilities
{
private const int BlendAlphaControl = 0b_10_00_10_00;
private const int ShuffleAlphaControl = 0b_11_11_11_11;
/// <summary>
/// Restricts a vector between a minimum and a maximum value.
/// 5x Faster then <see cref="Vector4.Clamp(Vector4, Vector4, Vector4)"/>.
/// </summary>
/// <param name="x">The vector to restrict.</param>
/// <param name="min">The minimum value.</param>
/// <param name="max">The maximum value.</param>
/// <returns>The <see cref="Vector4"/>.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
public static Vector4 FastClamp(Vector4 x, Vector4 min, Vector4 max)
=> Vector4.Min(Vector4.Max(x, min), max);
/// <summary>
/// Pre-multiplies the "x", "y", "z" components of a vector by its "w" component leaving the "w" component intact.
/// </summary>
/// <param name="source">The <see cref="Vector4"/> to premultiply</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void Premultiply(ref Vector4 source)
{
float w = source.W;
source *= w;
source.W = w;
}
/// <summary>
/// Reverses the result of premultiplying a vector via <see cref="Premultiply(ref Vector4)"/>.
/// </summary>
/// <param name="source">The <see cref="Vector4"/> to premultiply</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void UnPremultiply(ref Vector4 source)
{
float w = source.W;
source /= w;
source.W = w;
}
/// <summary>
/// Bulk variant of <see cref="Premultiply(ref Vector4)"/>
/// </summary>
/// <param name="vectors">The span of vectors</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void Premultiply(Span<Vector4> vectors)
{
#if SUPPORTS_RUNTIME_INTRINSICS
if (Avx2.IsSupported && vectors.Length >= 2)
{
ref Vector256<float> vectorsBase =
ref Unsafe.As<Vector4, Vector256<float>>(ref MemoryMarshal.GetReference(vectors));
// Divide by 2 as 4 elements per Vector4 and 8 per Vector256<float>
ref Vector256<float> vectorsLast = ref Unsafe.Add(ref vectorsBase, (IntPtr)((uint)vectors.Length / 2u));
while (Unsafe.IsAddressLessThan(ref vectorsBase, ref vectorsLast))
{
Vector256<float> source = vectorsBase;
Vector256<float> 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);
}
}
}
/// <summary>
/// Bulk variant of <see cref="UnPremultiply(ref Vector4)"/>
/// </summary>
/// <param name="vectors">The span of vectors</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void UnPremultiply(Span<Vector4> vectors)
{
#if SUPPORTS_RUNTIME_INTRINSICS
if (Avx2.IsSupported && vectors.Length >= 2)
{
ref Vector256<float> vectorsBase =
ref Unsafe.As<Vector4, Vector256<float>>(ref MemoryMarshal.GetReference(vectors));
// Divide by 2 as 4 elements per Vector4 and 8 per Vector256<float>
ref Vector256<float> vectorsLast = ref Unsafe.Add(ref vectorsBase, (IntPtr)((uint)vectors.Length / 2u));
while (Unsafe.IsAddressLessThan(ref vectorsBase, ref vectorsLast))
{
Vector256<float> source = vectorsBase;
Vector256<float> 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);
}
}
}
/// <summary>
/// Transforms a vector by the given matrix.
/// </summary>
/// <param name="vector">The source vector.</param>
/// <param name="matrix">The transformation matrix.</param>
[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;
}
/// <summary>
/// Bulk variant of <see cref="Transform(ref Vector4, ref ColorMatrix)"/>.
/// </summary>
/// <param name="vectors">The span of vectors</param>
/// <param name="matrix">The transformation matrix.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void Transform(Span<Vector4> 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);
}
}
}
}

4
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;
}
}

6
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<TPixel>
{
// The maximum number of colors for the bit depth
int colorTableLength = ImageMaths.GetColorCountForBitDepth(this.bitDepth) * Unsafe.SizeOf<Rgb24>();
int colorTableLength = ColorNumerics.GetColorCountForBitDepth(this.bitDepth) * Unsafe.SizeOf<Rgb24>();
using IManagedByteBuffer colorTable = this.memoryAllocator.AllocateManagedByteBuffer(colorTableLength, AllocationOptions.Clean);
PixelOperations<TPixel>.Instance.ToRgb24Bytes(

32
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);
}
/// <summary>

2
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();

2
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);

4
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;

8
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;
}
}
}

14
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;
}
}
}
}

4
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;

2
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;

6
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<byte> 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;
}
}

4
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

4
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)
{

2
src/ImageSharp/Formats/Tga/TgaEncoderCore.cs

@ -365,7 +365,7 @@ namespace SixLabors.ImageSharp.Formats.Tga
where TPixel : unmanaged, IPixel<TPixel>
{
var vector = sourcePixel.ToVector4();
return ImageMaths.GetBT709Luminance(ref vector, 256);
return ColorNumerics.GetBT709Luminance(ref vector, 256);
}
}
}

2
src/ImageSharp/Metadata/Profiles/ICC/DataReader/IccDataReader.cs

@ -40,7 +40,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc
/// <param name="index">The new index position</param>
public void SetIndex(int index)
{
this.currentIndex = index.Clamp(0, this.data.Length);
this.currentIndex = Numerics.Clamp(index, 0, this.data.Length);
}
/// <summary>

10
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));
}
}

6
src/ImageSharp/Metadata/Profiles/ICC/DataWriter/IccDataWriter.NonPrimitives.cs

@ -33,9 +33,9 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Icc
/// <returns>the number of bytes written</returns>
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);

10
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));

2
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));
}
}

648
src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.cs

File diff suppressed because it is too large

6
src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.tt

@ -79,14 +79,14 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public override TPixel Blend(TPixel background, TPixel source, float amount)
{
TPixel dest = default;
dest.FromScaledVector4(PorterDuffFunctions.<#=blender_composer#>(background.ToScaledVector4(), source.ToScaledVector4(), amount.Clamp(0, 1)));
dest.FromScaledVector4(PorterDuffFunctions.<#=blender_composer#>(background.ToScaledVector4(), source.ToScaledVector4(), Numerics.Clamp(amount, 0, 1)));
return dest;
}
/// <inheritdoc />
protected override void BlendFunction(Span<Vector4> destination, ReadOnlySpan<Vector4> background, ReadOnlySpan<Vector4> 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.<#=blender_composer#>(background[i], source[i], amount);
@ -98,7 +98,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
for (int i = 0; i < destination.Length; i++)
{
destination[i] = PorterDuffFunctions.<#=blender_composer#>(background[i], source[i], amount[i].Clamp(0, 1));
destination[i] = PorterDuffFunctions.<#=blender_composer#>(background[i], source[i], Numerics.Clamp(amount[i], 0, 1));
}
}
}

216
src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.cs

@ -203,7 +203,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel NormalSrc<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(NormalSrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -222,7 +222,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel NormalSrcAtop<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(NormalSrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -241,7 +241,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel NormalSrcOver<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(NormalSrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -260,7 +260,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel NormalSrcIn<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(NormalSrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -279,7 +279,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel NormalSrcOut<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(NormalSrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -298,7 +298,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel NormalDest<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(NormalDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -317,7 +317,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel NormalDestAtop<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(NormalDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -336,7 +336,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel NormalDestOver<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(NormalDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -355,7 +355,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel NormalDestIn<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(NormalDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -374,7 +374,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel NormalDestOut<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(NormalDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -393,7 +393,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel NormalClear<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(NormalClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -412,7 +412,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel NormalXor<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(NormalXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -608,7 +608,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel MultiplySrc<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(MultiplySrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -627,7 +627,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel MultiplySrcAtop<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(MultiplySrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -646,7 +646,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel MultiplySrcOver<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(MultiplySrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -665,7 +665,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel MultiplySrcIn<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(MultiplySrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -684,7 +684,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel MultiplySrcOut<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(MultiplySrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -703,7 +703,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel MultiplyDest<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(MultiplyDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -722,7 +722,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel MultiplyDestAtop<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(MultiplyDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -741,7 +741,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel MultiplyDestOver<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(MultiplyDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -760,7 +760,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel MultiplyDestIn<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(MultiplyDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -779,7 +779,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel MultiplyDestOut<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(MultiplyDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -798,7 +798,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel MultiplyClear<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(MultiplyClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -817,7 +817,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel MultiplyXor<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(MultiplyXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1013,7 +1013,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel AddSrc<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(AddSrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1032,7 +1032,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel AddSrcAtop<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(AddSrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1051,7 +1051,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel AddSrcOver<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(AddSrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1070,7 +1070,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel AddSrcIn<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(AddSrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1089,7 +1089,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel AddSrcOut<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(AddSrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1108,7 +1108,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel AddDest<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(AddDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1127,7 +1127,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel AddDestAtop<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(AddDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1146,7 +1146,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel AddDestOver<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(AddDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1165,7 +1165,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel AddDestIn<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(AddDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1184,7 +1184,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel AddDestOut<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(AddDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1203,7 +1203,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel AddClear<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(AddClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1222,7 +1222,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel AddXor<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(AddXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1418,7 +1418,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel SubtractSrc<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(SubtractSrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1437,7 +1437,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel SubtractSrcAtop<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(SubtractSrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1456,7 +1456,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel SubtractSrcOver<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(SubtractSrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1475,7 +1475,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel SubtractSrcIn<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(SubtractSrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1494,7 +1494,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel SubtractSrcOut<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(SubtractSrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1513,7 +1513,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel SubtractDest<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(SubtractDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1532,7 +1532,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel SubtractDestAtop<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(SubtractDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1551,7 +1551,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel SubtractDestOver<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(SubtractDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1570,7 +1570,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel SubtractDestIn<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(SubtractDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1589,7 +1589,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel SubtractDestOut<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(SubtractDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1608,7 +1608,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel SubtractClear<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(SubtractClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1627,7 +1627,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel SubtractXor<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(SubtractXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1823,7 +1823,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel ScreenSrc<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(ScreenSrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1842,7 +1842,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel ScreenSrcAtop<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(ScreenSrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1861,7 +1861,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel ScreenSrcOver<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(ScreenSrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1880,7 +1880,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel ScreenSrcIn<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(ScreenSrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1899,7 +1899,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel ScreenSrcOut<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(ScreenSrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1918,7 +1918,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel ScreenDest<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(ScreenDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1937,7 +1937,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel ScreenDestAtop<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(ScreenDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1956,7 +1956,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel ScreenDestOver<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(ScreenDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1975,7 +1975,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel ScreenDestIn<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(ScreenDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -1994,7 +1994,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel ScreenDestOut<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(ScreenDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -2013,7 +2013,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel ScreenClear<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(ScreenClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -2032,7 +2032,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel ScreenXor<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(ScreenXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -2228,7 +2228,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel DarkenSrc<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(DarkenSrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -2247,7 +2247,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel DarkenSrcAtop<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(DarkenSrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -2266,7 +2266,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel DarkenSrcOver<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(DarkenSrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -2285,7 +2285,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel DarkenSrcIn<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(DarkenSrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -2304,7 +2304,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel DarkenSrcOut<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(DarkenSrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -2323,7 +2323,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel DarkenDest<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(DarkenDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -2342,7 +2342,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel DarkenDestAtop<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(DarkenDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -2361,7 +2361,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel DarkenDestOver<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(DarkenDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -2380,7 +2380,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel DarkenDestIn<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(DarkenDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -2399,7 +2399,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel DarkenDestOut<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(DarkenDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -2418,7 +2418,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel DarkenClear<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(DarkenClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -2437,7 +2437,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel DarkenXor<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(DarkenXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -2633,7 +2633,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel LightenSrc<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(LightenSrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -2652,7 +2652,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel LightenSrcAtop<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(LightenSrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -2671,7 +2671,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel LightenSrcOver<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(LightenSrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -2690,7 +2690,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel LightenSrcIn<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(LightenSrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -2709,7 +2709,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel LightenSrcOut<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(LightenSrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -2728,7 +2728,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel LightenDest<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(LightenDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -2747,7 +2747,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel LightenDestAtop<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(LightenDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -2766,7 +2766,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel LightenDestOver<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(LightenDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -2785,7 +2785,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel LightenDestIn<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(LightenDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -2804,7 +2804,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel LightenDestOut<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(LightenDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -2823,7 +2823,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel LightenClear<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(LightenClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -2842,7 +2842,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel LightenXor<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(LightenXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -3038,7 +3038,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel OverlaySrc<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(OverlaySrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -3057,7 +3057,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel OverlaySrcAtop<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(OverlaySrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -3076,7 +3076,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel OverlaySrcOver<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(OverlaySrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -3095,7 +3095,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel OverlaySrcIn<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(OverlaySrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -3114,7 +3114,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel OverlaySrcOut<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(OverlaySrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -3133,7 +3133,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel OverlayDest<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(OverlayDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -3152,7 +3152,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel OverlayDestAtop<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(OverlayDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -3171,7 +3171,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel OverlayDestOver<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(OverlayDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -3190,7 +3190,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel OverlayDestIn<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(OverlayDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -3209,7 +3209,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel OverlayDestOut<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(OverlayDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -3228,7 +3228,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel OverlayClear<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(OverlayClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -3247,7 +3247,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel OverlayXor<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(OverlayXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -3443,7 +3443,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel HardLightSrc<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(HardLightSrc(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -3462,7 +3462,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel HardLightSrcAtop<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(HardLightSrcAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -3481,7 +3481,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel HardLightSrcOver<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(HardLightSrcOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -3500,7 +3500,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel HardLightSrcIn<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(HardLightSrcIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -3519,7 +3519,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel HardLightSrcOut<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(HardLightSrcOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -3538,7 +3538,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel HardLightDest<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(HardLightDest(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -3557,7 +3557,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel HardLightDestAtop<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(HardLightDestAtop(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -3576,7 +3576,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel HardLightDestOver<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(HardLightDestOver(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -3595,7 +3595,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel HardLightDestIn<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(HardLightDestIn(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -3614,7 +3614,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel HardLightDestOut<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(HardLightDestOut(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -3633,7 +3633,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel HardLightClear<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(HardLightClear(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;
@ -3652,7 +3652,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel HardLightXor<TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(HardLightXor(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;

2
src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.tt

@ -219,7 +219,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static TPixel <#=blender#><#=composer#><TPixel>(TPixel backdrop, TPixel source, float opacity)
where TPixel : unmanaged, IPixel<TPixel>
{
opacity = opacity.Clamp(0, 1);
opacity = Numerics.Clamp(opacity, 0, 1);
TPixel dest = default;
dest.FromScaledVector4(<#=blender#><#=composer#>(backdrop.ToScaledVector4(), source.ToScaledVector4(), opacity));
return dest;

4
src/ImageSharp/PixelFormats/PixelImplementations/A8.cs

@ -105,7 +105,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void FromLa32(La32 source) => this.PackedValue = ImageMaths.DownScaleFrom16BitTo8Bit(source.A);
public void FromLa32(La32 source) => this.PackedValue = ColorNumerics.DownScaleFrom16BitTo8Bit(source.A);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
@ -162,6 +162,6 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <param name="alpha">The float containing the value to pack.</param>
/// <returns>The <see cref="byte"/> containing the packed values.</returns>
[MethodImpl(InliningOptions.ShortMethod)]
private static byte Pack(float alpha) => (byte)Math.Round(alpha.Clamp(0, 1F) * 255F);
private static byte Pack(float alpha) => (byte)Math.Round(Numerics.Clamp(alpha, 0, 1F) * 255F);
}
}

22
src/ImageSharp/PixelFormats/PixelImplementations/Argb32.cs

@ -244,7 +244,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromL16(L16 source)
{
byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(source.PackedValue);
byte rgb = ColorNumerics.DownScaleFrom16BitTo8Bit(source.PackedValue);
this.R = rgb;
this.G = rgb;
this.B = rgb;
@ -265,11 +265,11 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromLa32(La32 source)
{
byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(source.L);
byte rgb = ColorNumerics.DownScaleFrom16BitTo8Bit(source.L);
this.R = rgb;
this.G = rgb;
this.B = rgb;
this.A = ImageMaths.DownScaleFrom16BitTo8Bit(source.A);
this.A = ColorNumerics.DownScaleFrom16BitTo8Bit(source.A);
}
/// <inheritdoc/>
@ -306,9 +306,9 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromRgb48(Rgb48 source)
{
this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R);
this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G);
this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B);
this.R = ColorNumerics.DownScaleFrom16BitTo8Bit(source.R);
this.G = ColorNumerics.DownScaleFrom16BitTo8Bit(source.G);
this.B = ColorNumerics.DownScaleFrom16BitTo8Bit(source.B);
this.A = byte.MaxValue;
}
@ -316,10 +316,10 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromRgba64(Rgba64 source)
{
this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R);
this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G);
this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B);
this.A = ImageMaths.DownScaleFrom16BitTo8Bit(source.A);
this.R = ColorNumerics.DownScaleFrom16BitTo8Bit(source.R);
this.G = ColorNumerics.DownScaleFrom16BitTo8Bit(source.G);
this.B = ColorNumerics.DownScaleFrom16BitTo8Bit(source.B);
this.A = ColorNumerics.DownScaleFrom16BitTo8Bit(source.A);
}
/// <inheritdoc/>
@ -373,7 +373,7 @@ namespace SixLabors.ImageSharp.PixelFormats
{
vector *= MaxBytes;
vector += Half;
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, MaxBytes);
vector = Numerics.Clamp(vector, Vector4.Zero, MaxBytes);
this.R = (byte)vector.X;
this.G = (byte)vector.Y;

16
src/ImageSharp/PixelFormats/PixelImplementations/Bgr24.cs

@ -151,7 +151,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromL16(L16 source)
{
byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(source.PackedValue);
byte rgb = ColorNumerics.DownScaleFrom16BitTo8Bit(source.PackedValue);
this.R = rgb;
this.G = rgb;
this.B = rgb;
@ -170,7 +170,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromLa32(La32 source)
{
byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(source.L);
byte rgb = ColorNumerics.DownScaleFrom16BitTo8Bit(source.L);
this.R = rgb;
this.G = rgb;
this.B = rgb;
@ -203,18 +203,18 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromRgb48(Rgb48 source)
{
this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R);
this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G);
this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B);
this.R = ColorNumerics.DownScaleFrom16BitTo8Bit(source.R);
this.G = ColorNumerics.DownScaleFrom16BitTo8Bit(source.G);
this.B = ColorNumerics.DownScaleFrom16BitTo8Bit(source.B);
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void FromRgba64(Rgba64 source)
{
this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R);
this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G);
this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B);
this.R = ColorNumerics.DownScaleFrom16BitTo8Bit(source.R);
this.G = ColorNumerics.DownScaleFrom16BitTo8Bit(source.G);
this.B = ColorNumerics.DownScaleFrom16BitTo8Bit(source.B);
}
/// <inheritdoc/>

22
src/ImageSharp/PixelFormats/PixelImplementations/Bgra32.cs

@ -197,7 +197,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromL16(L16 source)
{
byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(source.PackedValue);
byte rgb = ColorNumerics.DownScaleFrom16BitTo8Bit(source.PackedValue);
this.R = rgb;
this.G = rgb;
this.B = rgb;
@ -218,11 +218,11 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromLa32(La32 source)
{
byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(source.L);
byte rgb = ColorNumerics.DownScaleFrom16BitTo8Bit(source.L);
this.R = rgb;
this.G = rgb;
this.B = rgb;
this.A = ImageMaths.DownScaleFrom16BitTo8Bit(source.A);
this.A = ColorNumerics.DownScaleFrom16BitTo8Bit(source.A);
}
/// <inheritdoc/>
@ -259,9 +259,9 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromRgb48(Rgb48 source)
{
this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R);
this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G);
this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B);
this.R = ColorNumerics.DownScaleFrom16BitTo8Bit(source.R);
this.G = ColorNumerics.DownScaleFrom16BitTo8Bit(source.G);
this.B = ColorNumerics.DownScaleFrom16BitTo8Bit(source.B);
this.A = byte.MaxValue;
}
@ -269,10 +269,10 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromRgba64(Rgba64 source)
{
this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R);
this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G);
this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B);
this.A = ImageMaths.DownScaleFrom16BitTo8Bit(source.A);
this.R = ColorNumerics.DownScaleFrom16BitTo8Bit(source.R);
this.G = ColorNumerics.DownScaleFrom16BitTo8Bit(source.G);
this.B = ColorNumerics.DownScaleFrom16BitTo8Bit(source.B);
this.A = ColorNumerics.DownScaleFrom16BitTo8Bit(source.A);
}
/// <inheritdoc/>
@ -296,7 +296,7 @@ namespace SixLabors.ImageSharp.PixelFormats
{
vector *= MaxBytes;
vector += Half;
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, MaxBytes);
vector = Numerics.Clamp(vector, Vector4.Zero, MaxBytes);
this.R = (byte)vector.X;
this.G = (byte)vector.Y;

2
src/ImageSharp/PixelFormats/PixelImplementations/Bgra4444.cs

@ -162,7 +162,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
private static ushort Pack(ref Vector4 vector)
{
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One);
vector = Numerics.Clamp(vector, Vector4.Zero, Vector4.One);
return (ushort)((((int)Math.Round(vector.W * 15F) & 0x0F) << 12)
| (((int)Math.Round(vector.X * 15F) & 0x0F) << 8)
| (((int)Math.Round(vector.Y * 15F) & 0x0F) << 4)

2
src/ImageSharp/PixelFormats/PixelImplementations/Bgra5551.cs

@ -163,7 +163,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
private static ushort Pack(ref Vector4 vector)
{
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One);
vector = Numerics.Clamp(vector, Vector4.Zero, Vector4.One);
return (ushort)(
(((int)Math.Round(vector.X * 31F) & 0x1F) << 10)
| (((int)Math.Round(vector.Y * 31F) & 0x1F) << 5)

2
src/ImageSharp/PixelFormats/PixelImplementations/Byte4.cs

@ -171,7 +171,7 @@ namespace SixLabors.ImageSharp.PixelFormats
const float Max = 255F;
// Clamp the value between min and max values
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, new Vector4(Max));
vector = Numerics.Clamp(vector, Vector4.Zero, new Vector4(Max));
uint byte4 = (uint)Math.Round(vector.X) & 0xFF;
uint byte3 = ((uint)Math.Round(vector.Y) & 0xFF) << 0x8;

54
src/ImageSharp/PixelFormats/PixelImplementations/L16.cs

@ -74,30 +74,30 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromArgb32(Argb32 source)
{
this.PackedValue = ImageMaths.Get16BitBT709Luminance(
ImageMaths.UpscaleFrom8BitTo16Bit(source.R),
ImageMaths.UpscaleFrom8BitTo16Bit(source.G),
ImageMaths.UpscaleFrom8BitTo16Bit(source.B));
this.PackedValue = ColorNumerics.Get16BitBT709Luminance(
ColorNumerics.UpscaleFrom8BitTo16Bit(source.R),
ColorNumerics.UpscaleFrom8BitTo16Bit(source.G),
ColorNumerics.UpscaleFrom8BitTo16Bit(source.B));
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void FromBgr24(Bgr24 source)
{
this.PackedValue = ImageMaths.Get16BitBT709Luminance(
ImageMaths.UpscaleFrom8BitTo16Bit(source.R),
ImageMaths.UpscaleFrom8BitTo16Bit(source.G),
ImageMaths.UpscaleFrom8BitTo16Bit(source.B));
this.PackedValue = ColorNumerics.Get16BitBT709Luminance(
ColorNumerics.UpscaleFrom8BitTo16Bit(source.R),
ColorNumerics.UpscaleFrom8BitTo16Bit(source.G),
ColorNumerics.UpscaleFrom8BitTo16Bit(source.B));
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void FromBgra32(Bgra32 source)
{
this.PackedValue = ImageMaths.Get16BitBT709Luminance(
ImageMaths.UpscaleFrom8BitTo16Bit(source.R),
ImageMaths.UpscaleFrom8BitTo16Bit(source.G),
ImageMaths.UpscaleFrom8BitTo16Bit(source.B));
this.PackedValue = ColorNumerics.Get16BitBT709Luminance(
ColorNumerics.UpscaleFrom8BitTo16Bit(source.R),
ColorNumerics.UpscaleFrom8BitTo16Bit(source.G),
ColorNumerics.UpscaleFrom8BitTo16Bit(source.B));
}
/// <inheritdoc/>
@ -106,7 +106,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public void FromL8(L8 source) => this.PackedValue = ImageMaths.UpscaleFrom8BitTo16Bit(source.PackedValue);
public void FromL8(L8 source) => this.PackedValue = ColorNumerics.UpscaleFrom8BitTo16Bit(source.PackedValue);
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
@ -114,7 +114,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void FromLa16(La16 source) => this.PackedValue = ImageMaths.UpscaleFrom8BitTo16Bit(source.L);
public void FromLa16(La16 source) => this.PackedValue = ColorNumerics.UpscaleFrom8BitTo16Bit(source.L);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
@ -124,27 +124,27 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromRgb24(Rgb24 source)
{
this.PackedValue = ImageMaths.Get16BitBT709Luminance(
ImageMaths.UpscaleFrom8BitTo16Bit(source.R),
ImageMaths.UpscaleFrom8BitTo16Bit(source.G),
ImageMaths.UpscaleFrom8BitTo16Bit(source.B));
this.PackedValue = ColorNumerics.Get16BitBT709Luminance(
ColorNumerics.UpscaleFrom8BitTo16Bit(source.R),
ColorNumerics.UpscaleFrom8BitTo16Bit(source.G),
ColorNumerics.UpscaleFrom8BitTo16Bit(source.B));
}
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public void FromRgba32(Rgba32 source)
{
this.PackedValue = ImageMaths.Get16BitBT709Luminance(
ImageMaths.UpscaleFrom8BitTo16Bit(source.R),
ImageMaths.UpscaleFrom8BitTo16Bit(source.G),
ImageMaths.UpscaleFrom8BitTo16Bit(source.B));
this.PackedValue = ColorNumerics.Get16BitBT709Luminance(
ColorNumerics.UpscaleFrom8BitTo16Bit(source.R),
ColorNumerics.UpscaleFrom8BitTo16Bit(source.G),
ColorNumerics.UpscaleFrom8BitTo16Bit(source.B));
}
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public void ToRgba32(ref Rgba32 dest)
{
byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(this.PackedValue);
byte rgb = ColorNumerics.DownScaleFrom16BitTo8Bit(this.PackedValue);
dest.R = rgb;
dest.G = rgb;
dest.B = rgb;
@ -153,11 +153,11 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void FromRgb48(Rgb48 source) => this.PackedValue = ImageMaths.Get16BitBT709Luminance(source.R, source.G, source.B);
public void FromRgb48(Rgb48 source) => this.PackedValue = ColorNumerics.Get16BitBT709Luminance(source.R, source.G, source.B);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void FromRgba64(Rgba64 source) => this.PackedValue = ImageMaths.Get16BitBT709Luminance(source.R, source.G, source.B);
public void FromRgba64(Rgba64 source) => this.PackedValue = ColorNumerics.Get16BitBT709Luminance(source.R, source.G, source.B);
/// <inheritdoc />
public override readonly bool Equals(object obj) => obj is L16 other && this.Equals(other);
@ -176,8 +176,8 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
internal void ConvertFromRgbaScaledVector4(Vector4 vector)
{
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One) * Max;
this.PackedValue = ImageMaths.Get16BitBT709Luminance(
vector = Numerics.Clamp(vector, Vector4.Zero, Vector4.One) * Max;
this.PackedValue = ColorNumerics.Get16BitBT709Luminance(
vector.X,
vector.Y,
vector.Z);

34
src/ImageSharp/PixelFormats/PixelImplementations/L8.cs

@ -73,15 +73,15 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void FromArgb32(Argb32 source) => this.PackedValue = ImageMaths.Get8BitBT709Luminance(source.R, source.G, source.B);
public void FromArgb32(Argb32 source) => this.PackedValue = ColorNumerics.Get8BitBT709Luminance(source.R, source.G, source.B);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void FromBgr24(Bgr24 source) => this.PackedValue = ImageMaths.Get8BitBT709Luminance(source.R, source.G, source.B);
public void FromBgr24(Bgr24 source) => this.PackedValue = ColorNumerics.Get8BitBT709Luminance(source.R, source.G, source.B);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void FromBgra32(Bgra32 source) => this.PackedValue = ImageMaths.Get8BitBT709Luminance(source.R, source.G, source.B);
public void FromBgra32(Bgra32 source) => this.PackedValue = ColorNumerics.Get8BitBT709Luminance(source.R, source.G, source.B);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
@ -93,7 +93,7 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void FromL16(L16 source) => this.PackedValue = ImageMaths.DownScaleFrom16BitTo8Bit(source.PackedValue);
public void FromL16(L16 source) => this.PackedValue = ColorNumerics.DownScaleFrom16BitTo8Bit(source.PackedValue);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
@ -101,15 +101,15 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void FromLa32(La32 source) => this.PackedValue = ImageMaths.DownScaleFrom16BitTo8Bit(source.L);
public void FromLa32(La32 source) => this.PackedValue = ColorNumerics.DownScaleFrom16BitTo8Bit(source.L);
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void FromRgb24(Rgb24 source) => this.PackedValue = ImageMaths.Get8BitBT709Luminance(source.R, source.G, source.B);
public void FromRgb24(Rgb24 source) => this.PackedValue = ColorNumerics.Get8BitBT709Luminance(source.R, source.G, source.B);
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public void FromRgba32(Rgba32 source) => this.PackedValue = ImageMaths.Get8BitBT709Luminance(source.R, source.G, source.B);
public void FromRgba32(Rgba32 source) => this.PackedValue = ColorNumerics.Get8BitBT709Luminance(source.R, source.G, source.B);
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
@ -124,18 +124,18 @@ namespace SixLabors.ImageSharp.PixelFormats
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void FromRgb48(Rgb48 source)
=> this.PackedValue = ImageMaths.Get8BitBT709Luminance(
ImageMaths.DownScaleFrom16BitTo8Bit(source.R),
ImageMaths.DownScaleFrom16BitTo8Bit(source.G),
ImageMaths.DownScaleFrom16BitTo8Bit(source.B));
=> this.PackedValue = ColorNumerics.Get8BitBT709Luminance(
ColorNumerics.DownScaleFrom16BitTo8Bit(source.R),
ColorNumerics.DownScaleFrom16BitTo8Bit(source.G),
ColorNumerics.DownScaleFrom16BitTo8Bit(source.B));
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void FromRgba64(Rgba64 source)
=> this.PackedValue = ImageMaths.Get8BitBT709Luminance(
ImageMaths.DownScaleFrom16BitTo8Bit(source.R),
ImageMaths.DownScaleFrom16BitTo8Bit(source.G),
ImageMaths.DownScaleFrom16BitTo8Bit(source.B));
=> this.PackedValue = ColorNumerics.Get8BitBT709Luminance(
ColorNumerics.DownScaleFrom16BitTo8Bit(source.R),
ColorNumerics.DownScaleFrom16BitTo8Bit(source.G),
ColorNumerics.DownScaleFrom16BitTo8Bit(source.B));
/// <inheritdoc />
public override readonly bool Equals(object obj) => obj is L8 other && this.Equals(other);
@ -156,8 +156,8 @@ namespace SixLabors.ImageSharp.PixelFormats
{
vector *= MaxBytes;
vector += Half;
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, MaxBytes);
this.PackedValue = ImageMaths.Get8BitBT709Luminance((byte)vector.X, (byte)vector.Y, (byte)vector.Z);
vector = Numerics.Clamp(vector, Vector4.Zero, MaxBytes);
this.PackedValue = ColorNumerics.Get8BitBT709Luminance((byte)vector.X, (byte)vector.Y, (byte)vector.Z);
}
}
}

38
src/ImageSharp/PixelFormats/PixelImplementations/La16.cs

@ -92,7 +92,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromArgb32(Argb32 source)
{
this.L = ImageMaths.Get8BitBT709Luminance(source.R, source.G, source.B);
this.L = ColorNumerics.Get8BitBT709Luminance(source.R, source.G, source.B);
this.A = source.A;
}
@ -100,7 +100,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromBgr24(Bgr24 source)
{
this.L = ImageMaths.Get8BitBT709Luminance(source.R, source.G, source.B);
this.L = ColorNumerics.Get8BitBT709Luminance(source.R, source.G, source.B);
this.A = byte.MaxValue;
}
@ -108,7 +108,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromBgra32(Bgra32 source)
{
this.L = ImageMaths.Get8BitBT709Luminance(source.R, source.G, source.B);
this.L = ColorNumerics.Get8BitBT709Luminance(source.R, source.G, source.B);
this.A = source.A;
}
@ -120,7 +120,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromL16(L16 source)
{
this.L = ImageMaths.DownScaleFrom16BitTo8Bit(source.PackedValue);
this.L = ColorNumerics.DownScaleFrom16BitTo8Bit(source.PackedValue);
this.A = byte.MaxValue;
}
@ -140,15 +140,15 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromLa32(La32 source)
{
this.L = ImageMaths.DownScaleFrom16BitTo8Bit(source.L);
this.A = ImageMaths.DownScaleFrom16BitTo8Bit(source.A);
this.L = ColorNumerics.DownScaleFrom16BitTo8Bit(source.L);
this.A = ColorNumerics.DownScaleFrom16BitTo8Bit(source.A);
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void FromRgb24(Rgb24 source)
{
this.L = ImageMaths.Get8BitBT709Luminance(source.R, source.G, source.B);
this.L = ColorNumerics.Get8BitBT709Luminance(source.R, source.G, source.B);
this.A = byte.MaxValue;
}
@ -156,10 +156,10 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromRgb48(Rgb48 source)
{
this.L = ImageMaths.Get8BitBT709Luminance(
ImageMaths.DownScaleFrom16BitTo8Bit(source.R),
ImageMaths.DownScaleFrom16BitTo8Bit(source.G),
ImageMaths.DownScaleFrom16BitTo8Bit(source.B));
this.L = ColorNumerics.Get8BitBT709Luminance(
ColorNumerics.DownScaleFrom16BitTo8Bit(source.R),
ColorNumerics.DownScaleFrom16BitTo8Bit(source.G),
ColorNumerics.DownScaleFrom16BitTo8Bit(source.B));
this.A = byte.MaxValue;
}
@ -168,19 +168,19 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromRgba32(Rgba32 source)
{
this.L = ImageMaths.Get8BitBT709Luminance(source.R, source.G, source.B);
this.L = ColorNumerics.Get8BitBT709Luminance(source.R, source.G, source.B);
this.A = source.A;
}
/// <inheritdoc/>
public void FromRgba64(Rgba64 source)
{
this.L = ImageMaths.Get8BitBT709Luminance(
ImageMaths.DownScaleFrom16BitTo8Bit(source.R),
ImageMaths.DownScaleFrom16BitTo8Bit(source.G),
ImageMaths.DownScaleFrom16BitTo8Bit(source.B));
this.L = ColorNumerics.Get8BitBT709Luminance(
ColorNumerics.DownScaleFrom16BitTo8Bit(source.R),
ColorNumerics.DownScaleFrom16BitTo8Bit(source.G),
ColorNumerics.DownScaleFrom16BitTo8Bit(source.B));
this.A = ImageMaths.DownScaleFrom16BitTo8Bit(source.A);
this.A = ColorNumerics.DownScaleFrom16BitTo8Bit(source.A);
}
/// <inheritdoc/>
@ -219,8 +219,8 @@ namespace SixLabors.ImageSharp.PixelFormats
{
vector *= MaxBytes;
vector += Half;
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, MaxBytes);
this.L = ImageMaths.Get8BitBT709Luminance((byte)vector.X, (byte)vector.Y, (byte)vector.Z);
vector = Numerics.Clamp(vector, Vector4.Zero, MaxBytes);
this.L = ColorNumerics.Get8BitBT709Luminance((byte)vector.X, (byte)vector.Y, (byte)vector.Z);
this.A = (byte)vector.W;
}
}

64
src/ImageSharp/PixelFormats/PixelImplementations/La32.cs

@ -95,22 +95,22 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromArgb32(Argb32 source)
{
this.L = ImageMaths.Get16BitBT709Luminance(
ImageMaths.UpscaleFrom8BitTo16Bit(source.R),
ImageMaths.UpscaleFrom8BitTo16Bit(source.G),
ImageMaths.UpscaleFrom8BitTo16Bit(source.B));
this.L = ColorNumerics.Get16BitBT709Luminance(
ColorNumerics.UpscaleFrom8BitTo16Bit(source.R),
ColorNumerics.UpscaleFrom8BitTo16Bit(source.G),
ColorNumerics.UpscaleFrom8BitTo16Bit(source.B));
this.A = ImageMaths.UpscaleFrom8BitTo16Bit(source.A);
this.A = ColorNumerics.UpscaleFrom8BitTo16Bit(source.A);
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void FromBgr24(Bgr24 source)
{
this.L = ImageMaths.Get16BitBT709Luminance(
ImageMaths.UpscaleFrom8BitTo16Bit(source.R),
ImageMaths.UpscaleFrom8BitTo16Bit(source.G),
ImageMaths.UpscaleFrom8BitTo16Bit(source.B));
this.L = ColorNumerics.Get16BitBT709Luminance(
ColorNumerics.UpscaleFrom8BitTo16Bit(source.R),
ColorNumerics.UpscaleFrom8BitTo16Bit(source.G),
ColorNumerics.UpscaleFrom8BitTo16Bit(source.B));
this.A = ushort.MaxValue;
}
@ -119,12 +119,12 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromBgra32(Bgra32 source)
{
this.L = ImageMaths.Get16BitBT709Luminance(
ImageMaths.UpscaleFrom8BitTo16Bit(source.R),
ImageMaths.UpscaleFrom8BitTo16Bit(source.G),
ImageMaths.UpscaleFrom8BitTo16Bit(source.B));
this.L = ColorNumerics.Get16BitBT709Luminance(
ColorNumerics.UpscaleFrom8BitTo16Bit(source.R),
ColorNumerics.UpscaleFrom8BitTo16Bit(source.G),
ColorNumerics.UpscaleFrom8BitTo16Bit(source.B));
this.A = ImageMaths.UpscaleFrom8BitTo16Bit(source.A);
this.A = ColorNumerics.UpscaleFrom8BitTo16Bit(source.A);
}
/// <inheritdoc/>
@ -143,7 +143,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromL8(L8 source)
{
this.L = ImageMaths.UpscaleFrom8BitTo16Bit(source.PackedValue);
this.L = ColorNumerics.UpscaleFrom8BitTo16Bit(source.PackedValue);
this.A = ushort.MaxValue;
}
@ -151,8 +151,8 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromLa16(La16 source)
{
this.L = ImageMaths.UpscaleFrom8BitTo16Bit(source.L);
this.A = ImageMaths.UpscaleFrom8BitTo16Bit(source.A);
this.L = ColorNumerics.UpscaleFrom8BitTo16Bit(source.L);
this.A = ColorNumerics.UpscaleFrom8BitTo16Bit(source.A);
}
/// <inheritdoc/>
@ -163,10 +163,10 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromRgb24(Rgb24 source)
{
this.L = ImageMaths.Get16BitBT709Luminance(
ImageMaths.UpscaleFrom8BitTo16Bit(source.R),
ImageMaths.UpscaleFrom8BitTo16Bit(source.G),
ImageMaths.UpscaleFrom8BitTo16Bit(source.B));
this.L = ColorNumerics.Get16BitBT709Luminance(
ColorNumerics.UpscaleFrom8BitTo16Bit(source.R),
ColorNumerics.UpscaleFrom8BitTo16Bit(source.G),
ColorNumerics.UpscaleFrom8BitTo16Bit(source.B));
this.A = ushort.MaxValue;
}
@ -175,7 +175,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromRgb48(Rgb48 source)
{
this.L = ImageMaths.Get16BitBT709Luminance(source.R, source.G, source.B);
this.L = ColorNumerics.Get16BitBT709Luminance(source.R, source.G, source.B);
this.A = ushort.MaxValue;
}
@ -183,19 +183,19 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromRgba32(Rgba32 source)
{
this.L = ImageMaths.Get16BitBT709Luminance(
ImageMaths.UpscaleFrom8BitTo16Bit(source.R),
ImageMaths.UpscaleFrom8BitTo16Bit(source.G),
ImageMaths.UpscaleFrom8BitTo16Bit(source.B));
this.L = ColorNumerics.Get16BitBT709Luminance(
ColorNumerics.UpscaleFrom8BitTo16Bit(source.R),
ColorNumerics.UpscaleFrom8BitTo16Bit(source.G),
ColorNumerics.UpscaleFrom8BitTo16Bit(source.B));
this.A = ImageMaths.UpscaleFrom8BitTo16Bit(source.A);
this.A = ColorNumerics.UpscaleFrom8BitTo16Bit(source.A);
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void FromRgba64(Rgba64 source)
{
this.L = ImageMaths.Get16BitBT709Luminance(source.R, source.G, source.B);
this.L = ColorNumerics.Get16BitBT709Luminance(source.R, source.G, source.B);
this.A = source.A;
}
@ -211,11 +211,11 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void ToRgba32(ref Rgba32 dest)
{
byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(this.L);
byte rgb = ColorNumerics.DownScaleFrom16BitTo8Bit(this.L);
dest.R = rgb;
dest.G = rgb;
dest.B = rgb;
dest.A = ImageMaths.DownScaleFrom16BitTo8Bit(this.A);
dest.A = ColorNumerics.DownScaleFrom16BitTo8Bit(this.A);
}
/// <inheritdoc/>
@ -233,8 +233,8 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
internal void ConvertFromRgbaScaledVector4(Vector4 vector)
{
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One) * Max;
this.L = ImageMaths.Get16BitBT709Luminance(
vector = Numerics.Clamp(vector, Vector4.Zero, Vector4.One) * Max;
this.L = ColorNumerics.Get16BitBT709Luminance(
vector.X,
vector.Y,
vector.Z);

2
src/ImageSharp/PixelFormats/PixelImplementations/NormalizedByte4.cs

@ -174,7 +174,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
private static uint Pack(ref Vector4 vector)
{
vector = Vector4Utilities.FastClamp(vector, MinusOne, Vector4.One) * Half;
vector = Numerics.Clamp(vector, MinusOne, Vector4.One) * Half;
uint byte4 = ((uint)MathF.Round(vector.X) & 0xFF) << 0;
uint byte3 = ((uint)MathF.Round(vector.Y) & 0xFF) << 8;

2
src/ImageSharp/PixelFormats/PixelImplementations/NormalizedShort4.cs

@ -177,7 +177,7 @@ namespace SixLabors.ImageSharp.PixelFormats
private static ulong Pack(ref Vector4 vector)
{
vector *= Max;
vector = Vector4Utilities.FastClamp(vector, Min, Max);
vector = Numerics.Clamp(vector, Min, Max);
// Round rather than truncate.
ulong word4 = ((ulong)MathF.Round(vector.X) & 0xFFFF) << 0x00;

18
src/ImageSharp/PixelFormats/PixelImplementations/Rgb24.cs

@ -166,7 +166,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromL16(L16 source)
{
byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(source.PackedValue);
byte rgb = ColorNumerics.DownScaleFrom16BitTo8Bit(source.PackedValue);
this.R = rgb;
this.G = rgb;
this.B = rgb;
@ -185,7 +185,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromLa32(La32 source)
{
byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(source.L);
byte rgb = ColorNumerics.DownScaleFrom16BitTo8Bit(source.L);
this.R = rgb;
this.G = rgb;
this.B = rgb;
@ -227,18 +227,18 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromRgb48(Rgb48 source)
{
this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R);
this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G);
this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B);
this.R = ColorNumerics.DownScaleFrom16BitTo8Bit(source.R);
this.G = ColorNumerics.DownScaleFrom16BitTo8Bit(source.G);
this.B = ColorNumerics.DownScaleFrom16BitTo8Bit(source.B);
}
/// <inheritdoc/>
[MethodImpl(InliningOptions.ShortMethod)]
public void FromRgba64(Rgba64 source)
{
this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R);
this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G);
this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B);
this.R = ColorNumerics.DownScaleFrom16BitTo8Bit(source.R);
this.G = ColorNumerics.DownScaleFrom16BitTo8Bit(source.G);
this.B = ColorNumerics.DownScaleFrom16BitTo8Bit(source.B);
}
/// <inheritdoc/>
@ -264,7 +264,7 @@ namespace SixLabors.ImageSharp.PixelFormats
{
vector *= MaxBytes;
vector += Half;
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, MaxBytes);
vector = Numerics.Clamp(vector, Vector4.Zero, MaxBytes);
this.R = (byte)vector.X;
this.G = (byte)vector.Y;

42
src/ImageSharp/PixelFormats/PixelImplementations/Rgb48.cs

@ -85,7 +85,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromVector4(Vector4 vector)
{
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One) * Max;
vector = Numerics.Clamp(vector, Vector4.Zero, Vector4.One) * Max;
this.R = (ushort)MathF.Round(vector.X);
this.G = (ushort)MathF.Round(vector.Y);
this.B = (ushort)MathF.Round(vector.Z);
@ -99,27 +99,27 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromArgb32(Argb32 source)
{
this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R);
this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G);
this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B);
this.R = ColorNumerics.UpscaleFrom8BitTo16Bit(source.R);
this.G = ColorNumerics.UpscaleFrom8BitTo16Bit(source.G);
this.B = ColorNumerics.UpscaleFrom8BitTo16Bit(source.B);
}
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public void FromBgr24(Bgr24 source)
{
this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R);
this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G);
this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B);
this.R = ColorNumerics.UpscaleFrom8BitTo16Bit(source.R);
this.G = ColorNumerics.UpscaleFrom8BitTo16Bit(source.G);
this.B = ColorNumerics.UpscaleFrom8BitTo16Bit(source.B);
}
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public void FromBgra32(Bgra32 source)
{
this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R);
this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G);
this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B);
this.R = ColorNumerics.UpscaleFrom8BitTo16Bit(source.R);
this.G = ColorNumerics.UpscaleFrom8BitTo16Bit(source.G);
this.B = ColorNumerics.UpscaleFrom8BitTo16Bit(source.B);
}
/// <inheritdoc/>
@ -134,7 +134,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromL8(L8 source)
{
ushort rgb = ImageMaths.UpscaleFrom8BitTo16Bit(source.PackedValue);
ushort rgb = ColorNumerics.UpscaleFrom8BitTo16Bit(source.PackedValue);
this.R = rgb;
this.G = rgb;
this.B = rgb;
@ -153,7 +153,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromLa16(La16 source)
{
ushort rgb = ImageMaths.UpscaleFrom8BitTo16Bit(source.L);
ushort rgb = ColorNumerics.UpscaleFrom8BitTo16Bit(source.L);
this.R = rgb;
this.G = rgb;
this.B = rgb;
@ -172,27 +172,27 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromRgb24(Rgb24 source)
{
this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R);
this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G);
this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B);
this.R = ColorNumerics.UpscaleFrom8BitTo16Bit(source.R);
this.G = ColorNumerics.UpscaleFrom8BitTo16Bit(source.G);
this.B = ColorNumerics.UpscaleFrom8BitTo16Bit(source.B);
}
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public void FromRgba32(Rgba32 source)
{
this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R);
this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G);
this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B);
this.R = ColorNumerics.UpscaleFrom8BitTo16Bit(source.R);
this.G = ColorNumerics.UpscaleFrom8BitTo16Bit(source.G);
this.B = ColorNumerics.UpscaleFrom8BitTo16Bit(source.B);
}
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public void ToRgba32(ref Rgba32 dest)
{
dest.R = ImageMaths.DownScaleFrom16BitTo8Bit(this.R);
dest.G = ImageMaths.DownScaleFrom16BitTo8Bit(this.G);
dest.B = ImageMaths.DownScaleFrom16BitTo8Bit(this.B);
dest.R = ColorNumerics.DownScaleFrom16BitTo8Bit(this.R);
dest.G = ColorNumerics.DownScaleFrom16BitTo8Bit(this.G);
dest.B = ColorNumerics.DownScaleFrom16BitTo8Bit(this.B);
dest.A = byte.MaxValue;
}

2
src/ImageSharp/PixelFormats/PixelImplementations/Rgba1010102.cs

@ -163,7 +163,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
private static uint Pack(ref Vector4 vector)
{
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One) * Multiplier;
vector = Numerics.Clamp(vector, Vector4.Zero, Vector4.One) * Multiplier;
return (uint)(
(((int)Math.Round(vector.X) & 0x03FF) << 0)

24
src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.cs

@ -351,7 +351,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromL16(L16 source)
{
byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(source.PackedValue);
byte rgb = ColorNumerics.DownScaleFrom16BitTo8Bit(source.PackedValue);
this.R = rgb;
this.G = rgb;
this.B = rgb;
@ -372,11 +372,11 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromLa32(La32 source)
{
byte rgb = ImageMaths.DownScaleFrom16BitTo8Bit(source.L);
byte rgb = ColorNumerics.DownScaleFrom16BitTo8Bit(source.L);
this.R = rgb;
this.G = rgb;
this.B = rgb;
this.A = ImageMaths.DownScaleFrom16BitTo8Bit(source.A);
this.A = ColorNumerics.DownScaleFrom16BitTo8Bit(source.A);
}
/// <inheritdoc/>
@ -402,9 +402,9 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromRgb48(Rgb48 source)
{
this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R);
this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G);
this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B);
this.R = ColorNumerics.DownScaleFrom16BitTo8Bit(source.R);
this.G = ColorNumerics.DownScaleFrom16BitTo8Bit(source.G);
this.B = ColorNumerics.DownScaleFrom16BitTo8Bit(source.B);
this.A = byte.MaxValue;
}
@ -412,10 +412,10 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromRgba64(Rgba64 source)
{
this.R = ImageMaths.DownScaleFrom16BitTo8Bit(source.R);
this.G = ImageMaths.DownScaleFrom16BitTo8Bit(source.G);
this.B = ImageMaths.DownScaleFrom16BitTo8Bit(source.B);
this.A = ImageMaths.DownScaleFrom16BitTo8Bit(source.A);
this.R = ColorNumerics.DownScaleFrom16BitTo8Bit(source.R);
this.G = ColorNumerics.DownScaleFrom16BitTo8Bit(source.G);
this.B = ColorNumerics.DownScaleFrom16BitTo8Bit(source.B);
this.A = ColorNumerics.DownScaleFrom16BitTo8Bit(source.A);
}
/// <summary>
@ -452,7 +452,7 @@ namespace SixLabors.ImageSharp.PixelFormats
{
vector *= MaxBytes;
vector += Half;
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, MaxBytes);
vector = Numerics.Clamp(vector, Vector4.Zero, MaxBytes);
return new Rgba32((byte)vector.X, (byte)vector.Y, (byte)vector.Z, (byte)vector.W);
}
@ -491,7 +491,7 @@ namespace SixLabors.ImageSharp.PixelFormats
{
vector *= MaxBytes;
vector += Half;
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, MaxBytes);
vector = Numerics.Clamp(vector, Vector4.Zero, MaxBytes);
this.R = (byte)vector.X;
this.G = (byte)vector.Y;

126
src/ImageSharp/PixelFormats/PixelImplementations/Rgba64.cs

@ -62,10 +62,10 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba64(Rgba32 source)
{
this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R);
this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G);
this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B);
this.A = ImageMaths.UpscaleFrom8BitTo16Bit(source.A);
this.R = ColorNumerics.UpscaleFrom8BitTo16Bit(source.R);
this.G = ColorNumerics.UpscaleFrom8BitTo16Bit(source.G);
this.B = ColorNumerics.UpscaleFrom8BitTo16Bit(source.B);
this.A = ColorNumerics.UpscaleFrom8BitTo16Bit(source.A);
}
/// <summary>
@ -75,10 +75,10 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba64(Bgra32 source)
{
this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R);
this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G);
this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B);
this.A = ImageMaths.UpscaleFrom8BitTo16Bit(source.A);
this.R = ColorNumerics.UpscaleFrom8BitTo16Bit(source.R);
this.G = ColorNumerics.UpscaleFrom8BitTo16Bit(source.G);
this.B = ColorNumerics.UpscaleFrom8BitTo16Bit(source.B);
this.A = ColorNumerics.UpscaleFrom8BitTo16Bit(source.A);
}
/// <summary>
@ -88,10 +88,10 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba64(Argb32 source)
{
this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R);
this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G);
this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B);
this.A = ImageMaths.UpscaleFrom8BitTo16Bit(source.A);
this.R = ColorNumerics.UpscaleFrom8BitTo16Bit(source.R);
this.G = ColorNumerics.UpscaleFrom8BitTo16Bit(source.G);
this.B = ColorNumerics.UpscaleFrom8BitTo16Bit(source.B);
this.A = ColorNumerics.UpscaleFrom8BitTo16Bit(source.A);
}
/// <summary>
@ -101,9 +101,9 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba64(Rgb24 source)
{
this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R);
this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G);
this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B);
this.R = ColorNumerics.UpscaleFrom8BitTo16Bit(source.R);
this.G = ColorNumerics.UpscaleFrom8BitTo16Bit(source.G);
this.B = ColorNumerics.UpscaleFrom8BitTo16Bit(source.B);
this.A = ushort.MaxValue;
}
@ -114,9 +114,9 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba64(Bgr24 source)
{
this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R);
this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G);
this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B);
this.R = ColorNumerics.UpscaleFrom8BitTo16Bit(source.R);
this.G = ColorNumerics.UpscaleFrom8BitTo16Bit(source.G);
this.B = ColorNumerics.UpscaleFrom8BitTo16Bit(source.B);
this.A = ushort.MaxValue;
}
@ -127,7 +127,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public Rgba64(Vector4 vector)
{
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One) * Max;
vector = Numerics.Clamp(vector, Vector4.Zero, Vector4.One) * Max;
this.R = (ushort)MathF.Round(vector.X);
this.G = (ushort)MathF.Round(vector.Y);
this.B = (ushort)MathF.Round(vector.Z);
@ -209,7 +209,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromVector4(Vector4 vector)
{
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One) * Max;
vector = Numerics.Clamp(vector, Vector4.Zero, Vector4.One) * Max;
this.R = (ushort)MathF.Round(vector.X);
this.G = (ushort)MathF.Round(vector.Y);
this.B = (ushort)MathF.Round(vector.Z);
@ -224,19 +224,19 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromArgb32(Argb32 source)
{
this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R);
this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G);
this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B);
this.A = ImageMaths.UpscaleFrom8BitTo16Bit(source.A);
this.R = ColorNumerics.UpscaleFrom8BitTo16Bit(source.R);
this.G = ColorNumerics.UpscaleFrom8BitTo16Bit(source.G);
this.B = ColorNumerics.UpscaleFrom8BitTo16Bit(source.B);
this.A = ColorNumerics.UpscaleFrom8BitTo16Bit(source.A);
}
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public void FromBgr24(Bgr24 source)
{
this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R);
this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G);
this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B);
this.R = ColorNumerics.UpscaleFrom8BitTo16Bit(source.R);
this.G = ColorNumerics.UpscaleFrom8BitTo16Bit(source.G);
this.B = ColorNumerics.UpscaleFrom8BitTo16Bit(source.B);
this.A = ushort.MaxValue;
}
@ -244,10 +244,10 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromBgra32(Bgra32 source)
{
this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R);
this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G);
this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B);
this.A = ImageMaths.UpscaleFrom8BitTo16Bit(source.A);
this.R = ColorNumerics.UpscaleFrom8BitTo16Bit(source.R);
this.G = ColorNumerics.UpscaleFrom8BitTo16Bit(source.G);
this.B = ColorNumerics.UpscaleFrom8BitTo16Bit(source.B);
this.A = ColorNumerics.UpscaleFrom8BitTo16Bit(source.A);
}
/// <inheritdoc/>
@ -258,7 +258,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromL8(L8 source)
{
ushort rgb = ImageMaths.UpscaleFrom8BitTo16Bit(source.PackedValue);
ushort rgb = ColorNumerics.UpscaleFrom8BitTo16Bit(source.PackedValue);
this.R = rgb;
this.G = rgb;
this.B = rgb;
@ -279,11 +279,11 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromLa16(La16 source)
{
ushort rgb = ImageMaths.UpscaleFrom8BitTo16Bit(source.L);
ushort rgb = ColorNumerics.UpscaleFrom8BitTo16Bit(source.L);
this.R = rgb;
this.G = rgb;
this.B = rgb;
this.A = ImageMaths.UpscaleFrom8BitTo16Bit(source.A);
this.A = ColorNumerics.UpscaleFrom8BitTo16Bit(source.A);
}
/// <inheritdoc/>
@ -300,9 +300,9 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromRgb24(Rgb24 source)
{
this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R);
this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G);
this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B);
this.R = ColorNumerics.UpscaleFrom8BitTo16Bit(source.R);
this.G = ColorNumerics.UpscaleFrom8BitTo16Bit(source.G);
this.B = ColorNumerics.UpscaleFrom8BitTo16Bit(source.B);
this.A = ushort.MaxValue;
}
@ -310,20 +310,20 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromRgba32(Rgba32 source)
{
this.R = ImageMaths.UpscaleFrom8BitTo16Bit(source.R);
this.G = ImageMaths.UpscaleFrom8BitTo16Bit(source.G);
this.B = ImageMaths.UpscaleFrom8BitTo16Bit(source.B);
this.A = ImageMaths.UpscaleFrom8BitTo16Bit(source.A);
this.R = ColorNumerics.UpscaleFrom8BitTo16Bit(source.R);
this.G = ColorNumerics.UpscaleFrom8BitTo16Bit(source.G);
this.B = ColorNumerics.UpscaleFrom8BitTo16Bit(source.B);
this.A = ColorNumerics.UpscaleFrom8BitTo16Bit(source.A);
}
/// <inheritdoc />
[MethodImpl(InliningOptions.ShortMethod)]
public void ToRgba32(ref Rgba32 dest)
{
dest.R = ImageMaths.DownScaleFrom16BitTo8Bit(this.R);
dest.G = ImageMaths.DownScaleFrom16BitTo8Bit(this.G);
dest.B = ImageMaths.DownScaleFrom16BitTo8Bit(this.B);
dest.A = ImageMaths.DownScaleFrom16BitTo8Bit(this.A);
dest.R = ColorNumerics.DownScaleFrom16BitTo8Bit(this.R);
dest.G = ColorNumerics.DownScaleFrom16BitTo8Bit(this.G);
dest.B = ColorNumerics.DownScaleFrom16BitTo8Bit(this.B);
dest.A = ColorNumerics.DownScaleFrom16BitTo8Bit(this.A);
}
/// <inheritdoc/>
@ -345,10 +345,10 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public readonly Rgba32 ToRgba32()
{
byte r = ImageMaths.DownScaleFrom16BitTo8Bit(this.R);
byte g = ImageMaths.DownScaleFrom16BitTo8Bit(this.G);
byte b = ImageMaths.DownScaleFrom16BitTo8Bit(this.B);
byte a = ImageMaths.DownScaleFrom16BitTo8Bit(this.A);
byte r = ColorNumerics.DownScaleFrom16BitTo8Bit(this.R);
byte g = ColorNumerics.DownScaleFrom16BitTo8Bit(this.G);
byte b = ColorNumerics.DownScaleFrom16BitTo8Bit(this.B);
byte a = ColorNumerics.DownScaleFrom16BitTo8Bit(this.A);
return new Rgba32(r, g, b, a);
}
@ -359,10 +359,10 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public readonly Bgra32 ToBgra32()
{
byte r = ImageMaths.DownScaleFrom16BitTo8Bit(this.R);
byte g = ImageMaths.DownScaleFrom16BitTo8Bit(this.G);
byte b = ImageMaths.DownScaleFrom16BitTo8Bit(this.B);
byte a = ImageMaths.DownScaleFrom16BitTo8Bit(this.A);
byte r = ColorNumerics.DownScaleFrom16BitTo8Bit(this.R);
byte g = ColorNumerics.DownScaleFrom16BitTo8Bit(this.G);
byte b = ColorNumerics.DownScaleFrom16BitTo8Bit(this.B);
byte a = ColorNumerics.DownScaleFrom16BitTo8Bit(this.A);
return new Bgra32(r, g, b, a);
}
@ -373,10 +373,10 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public readonly Argb32 ToArgb32()
{
byte r = ImageMaths.DownScaleFrom16BitTo8Bit(this.R);
byte g = ImageMaths.DownScaleFrom16BitTo8Bit(this.G);
byte b = ImageMaths.DownScaleFrom16BitTo8Bit(this.B);
byte a = ImageMaths.DownScaleFrom16BitTo8Bit(this.A);
byte r = ColorNumerics.DownScaleFrom16BitTo8Bit(this.R);
byte g = ColorNumerics.DownScaleFrom16BitTo8Bit(this.G);
byte b = ColorNumerics.DownScaleFrom16BitTo8Bit(this.B);
byte a = ColorNumerics.DownScaleFrom16BitTo8Bit(this.A);
return new Argb32(r, g, b, a);
}
@ -387,9 +387,9 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public readonly Rgb24 ToRgb24()
{
byte r = ImageMaths.DownScaleFrom16BitTo8Bit(this.R);
byte g = ImageMaths.DownScaleFrom16BitTo8Bit(this.G);
byte b = ImageMaths.DownScaleFrom16BitTo8Bit(this.B);
byte r = ColorNumerics.DownScaleFrom16BitTo8Bit(this.R);
byte g = ColorNumerics.DownScaleFrom16BitTo8Bit(this.G);
byte b = ColorNumerics.DownScaleFrom16BitTo8Bit(this.B);
return new Rgb24(r, g, b);
}
@ -400,9 +400,9 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public readonly Bgr24 ToBgr24()
{
byte r = ImageMaths.DownScaleFrom16BitTo8Bit(this.R);
byte g = ImageMaths.DownScaleFrom16BitTo8Bit(this.G);
byte b = ImageMaths.DownScaleFrom16BitTo8Bit(this.B);
byte r = ColorNumerics.DownScaleFrom16BitTo8Bit(this.R);
byte g = ColorNumerics.DownScaleFrom16BitTo8Bit(this.G);
byte b = ColorNumerics.DownScaleFrom16BitTo8Bit(this.B);
return new Bgr24(r, g, b);
}

2
src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.cs

@ -111,7 +111,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
public void FromVector4(Vector4 vector)
{
vector = Vector4Utilities.FastClamp(vector, Vector4.Zero, Vector4.One);
vector = Numerics.Clamp(vector, Vector4.Zero, Vector4.One);
this.R = vector.X;
this.G = vector.Y;
this.B = vector.Z;

2
src/ImageSharp/PixelFormats/PixelImplementations/Short4.cs

@ -183,7 +183,7 @@ namespace SixLabors.ImageSharp.PixelFormats
[MethodImpl(InliningOptions.ShortMethod)]
private static ulong Pack(ref Vector4 vector)
{
vector = Vector4Utilities.FastClamp(vector, Min, Max);
vector = Numerics.Clamp(vector, Min, Max);
// Clamp the value between min and max values
ulong word4 = ((ulong)Math.Round(vector.X) & 0xFFFF) << 0x00;

4
src/ImageSharp/PixelFormats/Utils/Vector4Converters.cs

@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils
if (modifiers.IsDefined(PixelConversionModifiers.Premultiply))
{
Vector4Utilities.Premultiply(vectors);
Numerics.Premultiply(vectors);
}
}
@ -36,7 +36,7 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils
{
if (modifiers.IsDefined(PixelConversionModifiers.Premultiply))
{
Vector4Utilities.UnPremultiply(vectors);
Numerics.UnPremultiply(vectors);
}
if (modifiers.IsDefined(PixelConversionModifiers.SRgbCompand))

2
src/ImageSharp/Primitives/ComplexVector4.cs

@ -27,7 +27,7 @@ namespace SixLabors.ImageSharp
/// </summary>
/// <param name="value">The input <see cref="ComplexVector4"/> to sum</param>
[MethodImpl(InliningOptions.ShortMethod)]
public void Sum(in ComplexVector4 value)
public void Sum(ComplexVector4 value)
{
this.Real += value.Real;
this.Imaginary += value.Imaginary;

8
src/ImageSharp/Primitives/Number.cs

@ -70,7 +70,7 @@ namespace SixLabors.ImageSharp
{
return number.isSigned
? number.signedValue
: (int)number.unsignedValue.Clamp(0, int.MaxValue);
: (int)Numerics.Clamp(number.unsignedValue, 0, int.MaxValue);
}
/// <summary>
@ -80,7 +80,7 @@ namespace SixLabors.ImageSharp
public static explicit operator uint(Number number)
{
return number.isSigned
? (uint)number.signedValue.Clamp(0, int.MaxValue)
? (uint)Numerics.Clamp(number.signedValue, 0, int.MaxValue)
: number.unsignedValue;
}
@ -91,8 +91,8 @@ namespace SixLabors.ImageSharp
public static explicit operator ushort(Number number)
{
return number.isSigned
? (ushort)number.signedValue.Clamp(ushort.MinValue, ushort.MaxValue)
: (ushort)number.unsignedValue.Clamp(ushort.MinValue, ushort.MaxValue);
? (ushort)Numerics.Clamp(number.signedValue, ushort.MinValue, ushort.MaxValue)
: (ushort)Numerics.Clamp(number.unsignedValue, ushort.MinValue, ushort.MaxValue);
}
/// <summary>

14
src/ImageSharp/Processing/AffineTransformBuilder.cs

@ -31,7 +31,7 @@ namespace SixLabors.ImageSharp.Processing
/// <param name="radians">The amount of rotation, in radians.</param>
/// <returns>The <see cref="AffineTransformBuilder"/>.</returns>
public AffineTransformBuilder PrependRotationRadians(float radians)
=> this.Prepend(size => TransformUtilities.CreateRotationMatrixRadians(radians, size));
=> this.Prepend(size => TransformUtils.CreateRotationMatrixRadians(radians, size));
/// <summary>
/// Prepends a rotation matrix using the given rotation in degrees at the given origin.
@ -67,7 +67,7 @@ namespace SixLabors.ImageSharp.Processing
/// <param name="radians">The amount of rotation, in radians.</param>
/// <returns>The <see cref="AffineTransformBuilder"/>.</returns>
public AffineTransformBuilder AppendRotationRadians(float radians)
=> this.Append(size => TransformUtilities.CreateRotationMatrixRadians(radians, size));
=> this.Append(size => TransformUtils.CreateRotationMatrixRadians(radians, size));
/// <summary>
/// Appends a rotation matrix using the given rotation in degrees at the given origin.
@ -142,7 +142,7 @@ namespace SixLabors.ImageSharp.Processing
/// <param name="degreesY">The Y angle, in degrees.</param>
/// <returns>The <see cref="AffineTransformBuilder"/>.</returns>
public AffineTransformBuilder PrependSkewDegrees(float degreesX, float degreesY)
=> this.Prepend(size => TransformUtilities.CreateSkewMatrixDegrees(degreesX, degreesY, size));
=> this.Prepend(size => TransformUtils.CreateSkewMatrixDegrees(degreesX, degreesY, size));
/// <summary>
/// Prepends a centered skew matrix from the give angles in radians.
@ -151,7 +151,7 @@ namespace SixLabors.ImageSharp.Processing
/// <param name="radiansY">The Y angle, in radians.</param>
/// <returns>The <see cref="AffineTransformBuilder"/>.</returns>
public AffineTransformBuilder PrependSkewRadians(float radiansX, float radiansY)
=> this.Prepend(size => TransformUtilities.CreateSkewMatrixRadians(radiansX, radiansY, size));
=> this.Prepend(size => TransformUtils.CreateSkewMatrixRadians(radiansX, radiansY, size));
/// <summary>
/// Prepends a skew matrix using the given angles in degrees at the given origin.
@ -180,7 +180,7 @@ namespace SixLabors.ImageSharp.Processing
/// <param name="degreesY">The Y angle, in degrees.</param>
/// <returns>The <see cref="AffineTransformBuilder"/>.</returns>
public AffineTransformBuilder AppendSkewDegrees(float degreesX, float degreesY)
=> this.Append(size => TransformUtilities.CreateSkewMatrixDegrees(degreesX, degreesY, size));
=> this.Append(size => TransformUtils.CreateSkewMatrixDegrees(degreesX, degreesY, size));
/// <summary>
/// Appends a centered skew matrix from the give angles in radians.
@ -189,7 +189,7 @@ namespace SixLabors.ImageSharp.Processing
/// <param name="radiansY">The Y angle, in radians.</param>
/// <returns>The <see cref="AffineTransformBuilder"/>.</returns>
public AffineTransformBuilder AppendSkewRadians(float radiansX, float radiansY)
=> this.Append(size => TransformUtilities.CreateSkewMatrixRadians(radiansX, radiansY, size));
=> this.Append(size => TransformUtils.CreateSkewMatrixRadians(radiansX, radiansY, size));
/// <summary>
/// Appends a skew matrix using the given angles in degrees at the given origin.
@ -314,7 +314,7 @@ namespace SixLabors.ImageSharp.Processing
private static void CheckDegenerate(Matrix3x2 matrix)
{
if (TransformUtilities.IsDegenerate(matrix))
if (TransformUtils.IsDegenerate(matrix))
{
throw new DegenerateTransformException("Matrix is degenerate. Check input values.");
}

4
src/ImageSharp/Processing/Extensions/Transforms/TransformExtensions.cs

@ -52,7 +52,7 @@ namespace SixLabors.ImageSharp.Processing
IResampler sampler)
{
Matrix3x2 transform = builder.BuildMatrix(sourceRectangle);
Size targetDimensions = TransformUtilities.GetTransformedSize(sourceRectangle.Size, transform);
Size targetDimensions = TransformUtils.GetTransformedSize(sourceRectangle.Size, transform);
return ctx.Transform(sourceRectangle, transform, targetDimensions, sampler);
}
@ -116,7 +116,7 @@ namespace SixLabors.ImageSharp.Processing
IResampler sampler)
{
Matrix4x4 transform = builder.BuildMatrix(sourceRectangle);
Size targetDimensions = TransformUtilities.GetTransformedSize(sourceRectangle.Size, transform);
Size targetDimensions = TransformUtils.GetTransformedSize(sourceRectangle.Size, transform);
return ctx.Transform(sourceRectangle, transform, targetDimensions, sampler);
}

2
src/ImageSharp/Processing/Processors/Binarization/BinaryThresholdProcessor{TPixel}.cs

@ -96,7 +96,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Binarization
color.ToRgba32(ref rgba);
// Convert to grayscale using ITU-R Recommendation BT.709 if required
byte luminance = this.isAlphaOnly ? rgba.A : ImageMaths.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B);
byte luminance = this.isAlphaOnly ? rgba.A : ColorNumerics.Get8BitBT709Luminance(rgba.R, rgba.G, rgba.B);
color = luminance >= this.threshold ? this.upper : this.lower;
}
}

2
src/ImageSharp/Processing/Processors/Convolution/BokehBlurProcessor{TPixel}.cs

@ -304,7 +304,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
for (int x = 0; x < this.bounds.Width; x++)
{
ref Vector4 v = ref Unsafe.Add(ref sourceRef, x);
var clamp = Vector4Utilities.FastClamp(v, low, high);
var clamp = Numerics.Clamp(v, low, high);
v.X = MathF.Pow(clamp.X, this.inverseGamma);
v.Y = MathF.Pow(clamp.Y, this.inverseGamma);
v.Z = MathF.Pow(clamp.Z, this.inverseGamma);

6
src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessorHelpers.cs

@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
for (int i = 0; i < size; i++)
{
float x = i - midpoint;
float gx = ImageMaths.Gaussian(x, weight);
float gx = Numerics.Gaussian(x, weight);
sum += gx;
kernel[0, i] = gx;
}
@ -58,7 +58,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
for (int i = 0; i < size; i++)
{
float x = i - midpoint;
float gx = ImageMaths.Gaussian(x, weight);
float gx = Numerics.Gaussian(x, weight);
sum += gx;
kernel[0, i] = gx;
}
@ -88,4 +88,4 @@ namespace SixLabors.ImageSharp.Processing.Processors.Convolution
return kernel;
}
}
}
}

12
src/ImageSharp/Processing/Processors/Dithering/OrderedDither.cs

@ -165,10 +165,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
int spread = 256 / bitDepth;
float factor = spread * this.thresholdMatrix[y % this.modulusY, x % this.modulusX] * scale;
attempt.R = (byte)(rgba.R + factor).Clamp(byte.MinValue, byte.MaxValue);
attempt.G = (byte)(rgba.G + factor).Clamp(byte.MinValue, byte.MaxValue);
attempt.B = (byte)(rgba.B + factor).Clamp(byte.MinValue, byte.MaxValue);
attempt.A = (byte)(rgba.A + factor).Clamp(byte.MinValue, byte.MaxValue);
attempt.R = (byte)Numerics.Clamp(rgba.R + factor, byte.MinValue, byte.MaxValue);
attempt.G = (byte)Numerics.Clamp(rgba.G + factor, byte.MinValue, byte.MaxValue);
attempt.B = (byte)Numerics.Clamp(rgba.B + factor, byte.MinValue, byte.MaxValue);
attempt.A = (byte)Numerics.Clamp(rgba.A + factor, byte.MinValue, byte.MaxValue);
TPixel result = default;
result.FromRgba32(attempt);
@ -218,7 +218,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
this.source = source;
this.destination = destination;
this.bounds = bounds;
this.bitDepth = ImageMaths.GetBitsNeededForColorDepth(destination.Palette.Length);
this.bitDepth = ColorNumerics.GetBitsNeededForColorDepth(destination.Palette.Length);
}
[MethodImpl(InliningOptions.ShortMethod)]
@ -262,7 +262,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
this.source = source;
this.bounds = bounds;
this.scale = processor.DitherScale;
this.bitDepth = ImageMaths.GetBitsNeededForColorDepth(processor.Palette.Length);
this.bitDepth = ColorNumerics.GetBitsNeededForColorDepth(processor.Palette.Length);
}
[MethodImpl(InliningOptions.ShortMethod)]

2
src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessor.cs

@ -52,7 +52,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Dithering
Guard.MustBeGreaterThan(palette.Length, 0, nameof(palette));
Guard.NotNull(dither, nameof(dither));
this.Dither = dither;
this.DitherScale = ditherScale.Clamp(QuantizerConstants.MinDitherScale, QuantizerConstants.MaxDitherScale);
this.DitherScale = Numerics.Clamp(ditherScale, QuantizerConstants.MinDitherScale, QuantizerConstants.MaxDitherScale);
this.Palette = palette;
}

5
src/ImageSharp/Processing/Processors/Effects/OilPaintingProcessor{TPixel}.cs

@ -137,8 +137,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
{
int fyr = fy - this.radius;
int offsetY = y + fyr;
offsetY = offsetY.Clamp(0, maxY);
offsetY = Numerics.Clamp(offsetY, 0, maxY);
Span<TPixel> sourceOffsetRow = this.source.GetPixelRowSpan(offsetY);
@ -146,7 +145,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Effects
{
int fxr = fx - this.radius;
int offsetX = x + fxr;
offsetX = offsetX.Clamp(0, maxX);
offsetX = Numerics.Clamp(offsetX, 0, maxX);
var vector = sourceOffsetRow[offsetX].ToVector4();

2
src/ImageSharp/Processing/Processors/Filters/FilterProcessor{TPixel}.cs

@ -74,7 +74,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Filters
Span<TPixel> rowSpan = this.source.GetPixelRowSpan(y).Slice(this.startX, span.Length);
PixelOperations<TPixel>.Instance.ToVector4(this.configuration, rowSpan, span);
Vector4Utilities.Transform(span, ref Unsafe.AsRef(this.matrix));
ColorNumerics.Transform(span, ref Unsafe.AsRef(this.matrix));
PixelOperations<TPixel>.Instance.FromVector4Destructive(this.configuration, span, rowSpan);
}

8
src/ImageSharp/Processing/Processors/Normalization/AdaptiveHistogramEqualizationSlidingWindowProcessor{TPixel}.cs

@ -182,7 +182,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
{
if (y < 0)
{
y = ImageMaths.FastAbs(y);
y = Numerics.Abs(y);
}
else if (y >= source.Height)
{
@ -197,7 +197,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
int idx = 0;
for (int dx = x; dx < x + tileWidth; dx++)
{
rowPixels[idx] = source[ImageMaths.FastAbs(dx), y].ToVector4();
rowPixels[idx] = source[Numerics.Abs(dx), y].ToVector4();
idx++;
}
@ -259,7 +259,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
{
for (int idx = 0; idx < length; idx++)
{
int luminance = ImageMaths.GetBT709Luminance(ref Unsafe.Add(ref greyValuesBase, idx), luminanceLevels);
int luminance = ColorNumerics.GetBT709Luminance(ref Unsafe.Add(ref greyValuesBase, idx), luminanceLevels);
Unsafe.Add(ref histogramBase, luminance)++;
}
}
@ -276,7 +276,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
{
for (int idx = 0; idx < length; idx++)
{
int luminance = ImageMaths.GetBT709Luminance(ref Unsafe.Add(ref greyValuesBase, idx), luminanceLevels);
int luminance = ColorNumerics.GetBT709Luminance(ref Unsafe.Add(ref greyValuesBase, idx), luminanceLevels);
Unsafe.Add(ref histogramBase, luminance)--;
}
}

4
src/ImageSharp/Processing/Processors/Normalization/GlobalHistogramEqualizationProcessor{TPixel}.cs

@ -123,7 +123,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
{
// TODO: We should bulk convert here.
var vector = pixelRow[x].ToVector4();
int luminance = ImageMaths.GetBT709Luminance(ref vector, levels);
int luminance = ColorNumerics.GetBT709Luminance(ref vector, levels);
Interlocked.Increment(ref Unsafe.Add(ref histogramBase, luminance));
}
}
@ -174,7 +174,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
// TODO: We should bulk convert here.
ref TPixel pixel = ref pixelRow[x];
var vector = pixel.ToVector4();
int luminance = ImageMaths.GetBT709Luminance(ref vector, levels);
int luminance = ColorNumerics.GetBT709Luminance(ref vector, levels);
float luminanceEqualized = Unsafe.Add(ref cdfBase, luminance) / noOfPixelsMinusCdfMin;
pixel.FromVector4(new Vector4(luminanceEqualized, luminanceEqualized, luminanceEqualized, vector.W));
}

2
src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationProcessor{TPixel}.cs

@ -143,7 +143,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
public static int GetLuminance(TPixel sourcePixel, int luminanceLevels)
{
var vector = sourcePixel.ToVector4();
return ImageMaths.GetBT709Luminance(ref vector, luminanceLevels);
return ColorNumerics.GetBT709Luminance(ref vector, luminanceLevels);
}
}
}

2
src/ImageSharp/Processing/Processors/Overlays/GlowProcessor{TPixel}.cs

@ -102,7 +102,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
for (int i = 0; i < this.bounds.Width; i++)
{
float distance = Vector2.Distance(this.center, new Vector2(i + this.bounds.X, y));
span[i] = (this.blendPercent * (1 - (.95F * (distance / this.maxDistance)))).Clamp(0, 1);
span[i] = Numerics.Clamp(this.blendPercent * (1 - (.95F * (distance / this.maxDistance))), 0, 1F);
}
Span<TPixel> destination = this.source.GetPixelRowSpan(y).Slice(this.bounds.X, this.bounds.Width);

2
src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor{TPixel}.cs

@ -110,7 +110,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
for (int i = 0; i < this.bounds.Width; i++)
{
float distance = Vector2.Distance(this.center, new Vector2(i + this.bounds.X, y));
span[i] = (this.blendPercent * (.9F * (distance / this.maxDistance))).Clamp(0, 1);
span[i] = Numerics.Clamp(this.blendPercent * (.9F * (distance / this.maxDistance)), 0, 1F);
}
Span<TPixel> destination = this.source.GetPixelRowSpan(y).Slice(this.bounds.X, this.bounds.Width);

2
src/ImageSharp/Processing/Processors/Quantization/OctreeQuantizer{TPixel}.cs

@ -43,7 +43,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
this.Options = options;
this.maxColors = this.Options.MaxColors;
this.octree = new Octree(ImageMaths.GetBitsNeededForColorDepth(this.maxColors).Clamp(1, 8));
this.octree = new Octree(Numerics.Clamp(ColorNumerics.GetBitsNeededForColorDepth(this.maxColors), 1, 8));
this.paletteOwner = configuration.MemoryAllocator.Allocate<TPixel>(this.maxColors, AllocationOptions.Clean);
this.palette = default;
this.pixelMap = default;

4
src/ImageSharp/Processing/Processors/Quantization/QuantizerOptions.cs

@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
public float DitherScale
{
get { return this.ditherScale; }
set { this.ditherScale = value.Clamp(QuantizerConstants.MinDitherScale, QuantizerConstants.MaxDitherScale); }
set { this.ditherScale = Numerics.Clamp(value, QuantizerConstants.MinDitherScale, QuantizerConstants.MaxDitherScale); }
}
/// <summary>
@ -36,7 +36,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
public int MaxColors
{
get { return this.maxColors; }
set { this.maxColors = value.Clamp(QuantizerConstants.MinColors, QuantizerConstants.MaxColors); }
set { this.maxColors = Numerics.Clamp(value, QuantizerConstants.MinColors, QuantizerConstants.MaxColors); }
}
}
}

135
src/ImageSharp/Processing/Processors/Transforms/EntropyCropProcessor{TPixel}.cs

@ -1,6 +1,8 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing.Processors.Binarization;
@ -48,7 +50,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
new BinaryThresholdProcessor(this.definition.Threshold).Execute(this.Configuration, temp, this.SourceRectangle);
// Search for the first white pixels
rectangle = ImageMaths.GetFilteredBoundingRectangle(temp.Frames.RootFrame, 0);
rectangle = GetFilteredBoundingRectangle(temp.Frames.RootFrame, 0);
}
new CropProcessor(rectangle, this.Source.Size()).Execute(this.Configuration, this.Source, this.SourceRectangle);
@ -61,5 +63,136 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
{
// All processing happens at the image level within BeforeImageApply();
}
/// <summary>
/// Gets the bounding <see cref="Rectangle"/> from the given points.
/// </summary>
/// <param name="topLeft">
/// The <see cref="Point"/> designating the top left position.
/// </param>
/// <param name="bottomRight">
/// The <see cref="Point"/> designating the bottom right position.
/// </param>
/// <returns>
/// The bounding <see cref="Rectangle"/>.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static Rectangle GetBoundingRectangle(Point topLeft, Point bottomRight)
=> new Rectangle(
topLeft.X,
topLeft.Y,
bottomRight.X - topLeft.X,
bottomRight.Y - topLeft.Y);
/// <summary>
/// Finds the bounding rectangle based on the first instance of any color component other
/// than the given one.
/// </summary>
/// <param name="bitmap">The <see cref="Image{TPixel}"/> to search within.</param>
/// <param name="componentValue">The color component value to remove.</param>
/// <param name="channel">The <see cref="RgbaComponent"/> channel to test against.</param>
/// <returns>
/// The <see cref="Rectangle"/>.
/// </returns>
private static Rectangle GetFilteredBoundingRectangle(ImageFrame<TPixel> bitmap, float componentValue, RgbaComponent channel = RgbaComponent.B)
{
int width = bitmap.Width;
int height = bitmap.Height;
Point topLeft = default;
Point bottomRight = default;
Func<ImageFrame<TPixel>, 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<TPixel> 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<TPixel> 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<TPixel> 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<TPixel> 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 = Numerics.Clamp(GetMaxY(bitmap) + 1, 0, height);
bottomRight.X = Numerics.Clamp(GetMaxX(bitmap) + 1, 0, width);
return GetBoundingRectangle(topLeft, bottomRight);
}
}
}

6
src/ImageSharp/Processing/Processors/Transforms/Linear/AffineTransformProcessor{TPixel}.cs

@ -80,8 +80,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
return;
}
int yRadius = LinearTransformUtilities.GetSamplingRadius(in sampler, source.Height, destination.Height);
int xRadius = LinearTransformUtilities.GetSamplingRadius(in sampler, source.Width, destination.Width);
int yRadius = LinearTransformUtils.GetSamplingRadius(in sampler, source.Height, destination.Height);
int xRadius = LinearTransformUtils.GetSamplingRadius(in sampler, source.Width, destination.Width);
var radialExtents = new Vector2(xRadius, yRadius);
int yLength = (yRadius * 2) + 1;
int xLength = (xRadius * 2) + 1;
@ -207,7 +207,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
// Use the single precision position to calculate correct bounding pixels
// otherwise we get rogue pixels outside of the bounds.
var point = Vector2.Transform(new Vector2(x, y), this.matrix);
LinearTransformUtilities.Convolve(
LinearTransformUtils.Convolve(
in this.sampler,
point,
sourceBuffer,

8
src/ImageSharp/Processing/Processors/Transforms/Linear/LinearTransformUtilities.cs → src/ImageSharp/Processing/Processors/Transforms/Linear/LinearTransformUtils.cs

@ -12,7 +12,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
/// <summary>
/// Utility methods for affine and projective transforms.
/// </summary>
internal static class LinearTransformUtilities
internal static class LinearTransformUtils
{
[MethodImpl(InliningOptions.ShortMethod)]
internal static int GetSamplingRadius<TResampler>(in TResampler sampler, int sourceSize, int destinationSize)
@ -52,7 +52,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
MathF.Floor(maxXY.X),
MathF.Floor(maxXY.Y));
sourceExtents = Vector4Utilities.FastClamp(sourceExtents, Vector4.Zero, maxSourceExtents);
sourceExtents = Numerics.Clamp(sourceExtents, Vector4.Zero, maxSourceExtents);
int left = (int)sourceExtents.X;
int top = (int)sourceExtents.Y;
@ -78,13 +78,13 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
// Values are first premultiplied to prevent darkening of edge pixels.
var current = sourcePixels[x, y].ToVector4();
Vector4Utilities.Premultiply(ref current);
Numerics.Premultiply(ref current);
sum += current * xWeight * yWeight;
}
}
// Reverse the premultiplication
Vector4Utilities.UnPremultiply(ref sum);
Numerics.UnPremultiply(ref sum);
targetRow[column] = sum;
}

10
src/ImageSharp/Processing/Processors/Transforms/Linear/ProjectiveTransformProcessor{TPixel}.cs

@ -80,8 +80,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
return;
}
int yRadius = LinearTransformUtilities.GetSamplingRadius(in sampler, source.Height, destination.Height);
int xRadius = LinearTransformUtilities.GetSamplingRadius(in sampler, source.Width, destination.Width);
int yRadius = LinearTransformUtils.GetSamplingRadius(in sampler, source.Height, destination.Height);
int xRadius = LinearTransformUtils.GetSamplingRadius(in sampler, source.Width, destination.Width);
var radialExtents = new Vector2(xRadius, yRadius);
int yLength = (yRadius * 2) + 1;
int xLength = (xRadius * 2) + 1;
@ -139,7 +139,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
for (int x = 0; x < this.maxX; x++)
{
Vector2 point = TransformUtilities.ProjectiveTransform2D(x, y, this.matrix);
Vector2 point = TransformUtils.ProjectiveTransform2D(x, y, this.matrix);
int px = (int)MathF.Round(point.X);
int py = (int)MathF.Round(point.Y);
@ -206,8 +206,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
{
// Use the single precision position to calculate correct bounding pixels
// otherwise we get rogue pixels outside of the bounds.
Vector2 point = TransformUtilities.ProjectiveTransform2D(x, y, this.matrix);
LinearTransformUtilities.Convolve(
Vector2 point = TransformUtils.ProjectiveTransform2D(x, y, this.matrix);
LinearTransformUtils.Convolve(
in this.sampler,
point,
sourceBuffer,

4
src/ImageSharp/Processing/Processors/Transforms/Linear/RotateProcessor.cs

@ -28,14 +28,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
/// <param name="sourceSize">The source image size</param>
public RotateProcessor(float degrees, IResampler sampler, Size sourceSize)
: this(
TransformUtilities.CreateRotationMatrixDegrees(degrees, sourceSize),
TransformUtils.CreateRotationMatrixDegrees(degrees, sourceSize),
sampler,
sourceSize)
=> this.Degrees = degrees;
// Helper constructor
private RotateProcessor(Matrix3x2 rotationMatrix, IResampler sampler, Size sourceSize)
: base(rotationMatrix, sampler, TransformUtilities.GetTransformedSize(sourceSize, rotationMatrix))
: base(rotationMatrix, sampler, TransformUtils.GetTransformedSize(sourceSize, rotationMatrix))
{
}

4
src/ImageSharp/Processing/Processors/Transforms/Linear/SkewProcessor.cs

@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
/// <param name="sourceSize">The source image size</param>
public SkewProcessor(float degreesX, float degreesY, IResampler sampler, Size sourceSize)
: this(
TransformUtilities.CreateSkewMatrixDegrees(degreesX, degreesY, sourceSize),
TransformUtils.CreateSkewMatrixDegrees(degreesX, degreesY, sourceSize),
sampler,
sourceSize)
{
@ -40,7 +40,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
// Helper constructor:
private SkewProcessor(Matrix3x2 skewMatrix, IResampler sampler, Size sourceSize)
: base(skewMatrix, sampler, TransformUtilities.GetTransformedSize(sourceSize, skewMatrix))
: base(skewMatrix, sampler, TransformUtils.GetTransformedSize(sourceSize, skewMatrix))
{
}

2
src/ImageSharp/Processing/Processors/Transforms/Resamplers/LanczosResampler.cs

@ -53,7 +53,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
float radius = this.Radius;
if (x < radius)
{
return ImageMaths.SinC(x) * ImageMaths.SinC(x / radius);
return Numerics.SinC(x) * Numerics.SinC(x / radius);
}
return 0F;

2
src/ImageSharp/Processing/Processors/Transforms/Resamplers/WelchResampler.cs

@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
if (x < 3F)
{
return ImageMaths.SinC(x) * (1F - (x * x / 9F));
return Numerics.SinC(x) * (1F - (x * x / 9F));
}
return 0F;

2
src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeKernelMap.cs

@ -132,7 +132,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
// 'ratio' is a rational number.
// Multiplying it by LCM(sourceSize, destSize)/sourceSize will result in a whole number "again".
// This value is determining the length of the periods in repeating kernel map rows.
int period = ImageMaths.LeastCommonMultiple(sourceSize, destinationSize) / sourceSize;
int period = Numerics.LeastCommonMultiple(sourceSize, destinationSize) / sourceSize;
// the center position at i == 0:
double center0 = (ratio - 1) * 0.5;

2
src/ImageSharp/Processing/Processors/Transforms/TransformUtilities.cs → src/ImageSharp/Processing/Processors/Transforms/TransformUtils.cs

@ -10,7 +10,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
/// <summary>
/// Contains utility methods for working with transforms.
/// </summary>
internal static class TransformUtilities
internal static class TransformUtils
{
/// <summary>
/// Returns a value that indicates whether the specified matrix is degenerate

14
src/ImageSharp/Processing/ProjectiveTransformBuilder.cs

@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.Processing
/// <param name="fraction">The amount to taper.</param>
/// <returns>The <see cref="ProjectiveTransformBuilder"/>.</returns>
public ProjectiveTransformBuilder PrependTaper(TaperSide side, TaperCorner corner, float fraction)
=> this.Prepend(size => TransformUtilities.CreateTaperMatrix(size, side, corner, fraction));
=> this.Prepend(size => TransformUtils.CreateTaperMatrix(size, side, corner, fraction));
/// <summary>
/// Appends a matrix that performs a tapering projective transform.
@ -34,7 +34,7 @@ namespace SixLabors.ImageSharp.Processing
/// <param name="fraction">The amount to taper.</param>
/// <returns>The <see cref="ProjectiveTransformBuilder"/>.</returns>
public ProjectiveTransformBuilder AppendTaper(TaperSide side, TaperCorner corner, float fraction)
=> this.Append(size => TransformUtilities.CreateTaperMatrix(size, side, corner, fraction));
=> this.Append(size => TransformUtils.CreateTaperMatrix(size, side, corner, fraction));
/// <summary>
/// Prepends a centered rotation matrix using the given rotation in degrees.
@ -50,7 +50,7 @@ namespace SixLabors.ImageSharp.Processing
/// <param name="radians">The amount of rotation, in radians.</param>
/// <returns>The <see cref="ProjectiveTransformBuilder"/>.</returns>
public ProjectiveTransformBuilder PrependRotationRadians(float radians)
=> this.Prepend(size => new Matrix4x4(TransformUtilities.CreateRotationMatrixRadians(radians, size)));
=> this.Prepend(size => new Matrix4x4(TransformUtils.CreateRotationMatrixRadians(radians, size)));
/// <summary>
/// Prepends a centered rotation matrix using the given rotation in degrees at the given origin.
@ -84,7 +84,7 @@ namespace SixLabors.ImageSharp.Processing
/// <param name="radians">The amount of rotation, in radians.</param>
/// <returns>The <see cref="ProjectiveTransformBuilder"/>.</returns>
public ProjectiveTransformBuilder AppendRotationRadians(float radians)
=> this.Append(size => new Matrix4x4(TransformUtilities.CreateRotationMatrixRadians(radians, size)));
=> this.Append(size => new Matrix4x4(TransformUtils.CreateRotationMatrixRadians(radians, size)));
/// <summary>
/// Appends a centered rotation matrix using the given rotation in degrees at the given origin.
@ -168,7 +168,7 @@ namespace SixLabors.ImageSharp.Processing
/// <param name="radiansY">The Y angle, in radians.</param>
/// <returns>The <see cref="ProjectiveTransformBuilder"/>.</returns>
public ProjectiveTransformBuilder PrependSkewRadians(float radiansX, float radiansY)
=> this.Prepend(size => new Matrix4x4(TransformUtilities.CreateSkewMatrixRadians(radiansX, radiansY, size)));
=> this.Prepend(size => new Matrix4x4(TransformUtils.CreateSkewMatrixRadians(radiansX, radiansY, size)));
/// <summary>
/// Prepends a skew matrix using the given angles in degrees at the given origin.
@ -206,7 +206,7 @@ namespace SixLabors.ImageSharp.Processing
/// <param name="radiansY">The Y angle, in radians.</param>
/// <returns>The <see cref="ProjectiveTransformBuilder"/>.</returns>
public ProjectiveTransformBuilder AppendSkewRadians(float radiansX, float radiansY)
=> this.Append(size => new Matrix4x4(TransformUtilities.CreateSkewMatrixRadians(radiansX, radiansY, size)));
=> this.Append(size => new Matrix4x4(TransformUtils.CreateSkewMatrixRadians(radiansX, radiansY, size)));
/// <summary>
/// Appends a skew matrix using the given angles in degrees at the given origin.
@ -332,7 +332,7 @@ namespace SixLabors.ImageSharp.Processing
private static void CheckDegenerate(Matrix4x4 matrix)
{
if (TransformUtilities.IsDegenerate(matrix))
if (TransformUtils.IsDegenerate(matrix))
{
throw new DegenerateTransformException("Matrix is degenerate. Check input values.");
}

2
tests/ImageSharp.Benchmarks/Color/Bulk/PremultiplyVector4.cs

@ -29,7 +29,7 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk
[Benchmark]
public void Premultiply()
{
Vector4Utilities.Premultiply(Vectors);
Numerics.Premultiply(Vectors);
}
[MethodImpl(InliningOptions.ShortMethod)]

2
tests/ImageSharp.Benchmarks/Color/Bulk/UnPremultiplyVector4.cs

@ -29,7 +29,7 @@ namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk
[Benchmark]
public void UnPremultiply()
{
Vector4Utilities.UnPremultiply(Vectors);
Numerics.UnPremultiply(Vectors);
}
[MethodImpl(InliningOptions.ShortMethod)]

19
tests/ImageSharp.Benchmarks/Color/YcbCrToRgb.cs

@ -1,12 +1,11 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System.Numerics;
using BenchmarkDotNet.Attributes;
namespace SixLabors.ImageSharp.Benchmarks
{
using System.Numerics;
using BenchmarkDotNet.Attributes;
public class YcbCrToRgb
{
[Benchmark(Baseline = true, Description = "Floating Point Conversion")]
@ -19,9 +18,9 @@ namespace SixLabors.ImageSharp.Benchmarks
int ccb = cb - 128;
int ccr = cr - 128;
byte r = (byte)(y + (1.402F * ccr)).Clamp(0, 255);
byte g = (byte)(y - (0.34414F * ccb) - (0.71414F * ccr)).Clamp(0, 255);
byte b = (byte)(y + (1.772F * ccb)).Clamp(0, 255);
byte r = (byte)Numerics.Clamp(y + (1.402F * ccr), 0, 255);
byte g = (byte)Numerics.Clamp(y - (0.34414F * ccb) - (0.71414F * ccr), 0, 255);
byte b = (byte)Numerics.Clamp(y + (1.772F * ccb), 0, 255);
return new Vector3(r, g, b);
}
@ -42,9 +41,9 @@ namespace SixLabors.ImageSharp.Benchmarks
int g1 = 731 * ccr; // (0.71414F * 1024) + .5F
int b0 = 1815 * ccb; // (1.772F * 1024) + .5F
byte r = (byte)(y + (r0 >> 10)).Clamp(0, 255);
byte g = (byte)(y - (g0 >> 10) - (g1 >> 10)).Clamp(0, 255);
byte b = (byte)(y + (b0 >> 10)).Clamp(0, 255);
byte r = (byte)Numerics.Clamp(y + (r0 >> 10), 0, 255);
byte g = (byte)Numerics.Clamp(y - (g0 >> 10) - (g1 >> 10), 0, 255);
byte b = (byte)Numerics.Clamp(y + (b0 >> 10), 0, 255);
return new Vector3(r, g, b);
}

57
tests/ImageSharp.Benchmarks/General/BasicMath/ClampSpan.cs

@ -0,0 +1,57 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
using BenchmarkDotNet.Attributes;
namespace SixLabors.ImageSharp.Benchmarks.General.BasicMath
{
public class ClampSpan
{
private static readonly int[] A = new int[2048];
private static readonly int[] B = new int[2048];
public void Setup()
{
var r = new Random();
for (int i = 0; i < A.Length; i++)
{
int x = r.Next();
A[i] = x;
B[i] = x;
}
}
[Benchmark(Baseline = true)]
public void ClampNoIntrinsics()
{
for (int i = 0; i < A.Length; i++)
{
ref int x = ref A[i];
x = Numerics.Clamp(x, 64, 128);
}
}
[Benchmark]
public void ClampVectorIntrinsics()
{
Numerics.Clamp(B, 64, 128);
}
}
}
// 23-11-2020
// ##########
//
// BenchmarkDotNet = v0.12.1, OS = Windows 10.0.19041.630(2004 /?/ 20H1)
// Intel Core i7-8650U CPU 1.90GHz (Kaby Lake R), 1 CPU, 8 logical and 4 physical cores
// .NET Core SDK=5.0.100
// [Host] : .NET Core 3.1.10 (CoreCLR 4.700.20.51601, CoreFX 4.700.20.51901), X64 RyuJIT
// DefaultJob : .NET Core 3.1.10 (CoreCLR 4.700.20.51601, CoreFX 4.700.20.51901), X64 RyuJIT
//
//
// | Method | Mean | Error | StdDev | Ratio |
// |---------------------- |-----------:| ---------:| ----------:| ------:|
// | ClampNoIntrinsics | 3,629.9 ns | 70.80 ns | 129.47 ns | 1.00 |
// | ClampVectorIntrinsics | 131.9 ns | 2.68 ns | 6.66 ns | 0.04 |

2
tests/ImageSharp.Benchmarks/General/BasicMath/ModuloPowerOfTwoConstant.cs

@ -19,7 +19,7 @@ namespace SixLabors.ImageSharp.Benchmarks.General.BasicMath
[Benchmark]
public int Bitwise()
{
return ImageMaths.Modulo8(this.value);
return Numerics.Modulo8(this.value);
}
}
}

2
tests/ImageSharp.Benchmarks/General/BasicMath/ModuloPowerOfTwoVariable.cs

@ -21,7 +21,7 @@ namespace SixLabors.ImageSharp.Benchmarks.General.BasicMath
[Benchmark]
public int Bitwise()
{
return ImageMaths.ModuloP2(this.value, this.m);
return Numerics.ModuloP2(this.value, this.m);
}
// RESULTS:

2
tests/ImageSharp.Tests/Formats/Png/PngEncoderTests.cs

@ -435,7 +435,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
Rgba32 expectedColor = Color.Blue;
if (colorType == PngColorType.Grayscale || colorType == PngColorType.GrayscaleWithAlpha)
{
var luminance = ImageMaths.Get8BitBT709Luminance(expectedColor.R, expectedColor.G, expectedColor.B);
var luminance = ColorNumerics.Get8BitBT709Luminance(expectedColor.R, expectedColor.G, expectedColor.B);
expectedColor = new Rgba32(luminance, luminance, luminance);
}

31
tests/ImageSharp.Tests/Helpers/ColorNumericsTests.cs

@ -0,0 +1,31 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System.Numerics;
using Xunit;
namespace SixLabors.ImageSharp.Tests.Helpers
{
public class ColorNumericsTests
{
[Theory]
[InlineData(0.2f, 0.7f, 0.1f, 256, 140)]
[InlineData(0.5f, 0.5f, 0.5f, 256, 128)]
[InlineData(0.5f, 0.5f, 0.5f, 65536, 32768)]
[InlineData(0.2f, 0.7f, 0.1f, 65536, 36069)]
public void GetBT709Luminance_WithVector4(float x, float y, float z, int luminanceLevels, int expected)
{
// arrange
var vector = new Vector4(x, y, z, 0.0f);
// act
int actual = ColorNumerics.GetBT709Luminance(ref vector, luminanceLevels);
// assert
Assert.Equal(expected, actual);
}
// TODO: We need to test all ColorNumerics methods!
}
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save