diff --git a/ImageSharp.sln.DotSettings b/ImageSharp.sln.DotSettings
index 432f4524a0..8e7b5dd488 100644
--- a/ImageSharp.sln.DotSettings
+++ b/ImageSharp.sln.DotSettings
@@ -382,6 +382,7 @@
True
True
True
+ True
True
True
True
diff --git a/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs b/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs
index 5ae4629137..bbd454fbe8 100644
--- a/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs
+++ b/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs
@@ -30,9 +30,7 @@ public static void Expand(Span vectors)
for (int i = 0; i < vectors.Length; i++)
{
ref Vector4 v = ref Unsafe.Add(ref baseRef, i);
- v.X = Expand(v.X);
- v.Y = Expand(v.Y);
- v.Z = Expand(v.Z);
+ Expand(ref v);
}
}
@@ -48,9 +46,7 @@ public static void Compress(Span vectors)
for (int i = 0; i < vectors.Length; i++)
{
ref Vector4 v = ref Unsafe.Add(ref baseRef, i);
- v.X = Compress(v.X);
- v.Y = Compress(v.Y);
- v.Z = Compress(v.Z);
+ Compress(ref v);
}
}
@@ -58,17 +54,25 @@ public static void Compress(Span vectors)
/// Expands a companded vector to its linear equivalent with respect to the energy.
///
/// The vector.
- /// The representing the linear channel values.
[MethodImpl(InliningOptions.ShortMethod)]
- public static Vector4 Expand(Vector4 vector) => new Vector4(Expand(vector.X), Expand(vector.Y), Expand(vector.Z), vector.W);
+ public static void Expand(ref Vector4 vector)
+ {
+ vector.X = Expand(vector.X);
+ vector.Y = Expand(vector.Y);
+ vector.Z = Expand(vector.Z);
+ }
///
/// Compresses an uncompanded vector (linear) to its nonlinear equivalent.
///
/// The vector.
- /// The representing the nonlinear channel values.
[MethodImpl(InliningOptions.ShortMethod)]
- public static Vector4 Compress(Vector4 vector) => new Vector4(Compress(vector.X), Compress(vector.Y), Compress(vector.Z), vector.W);
+ public static void Compress(ref Vector4 vector)
+ {
+ vector.X = Compress(vector.X);
+ vector.Y = Compress(vector.Y);
+ vector.Z = Compress(vector.Z);
+ }
///
/// Expands a companded channel to its linear equivalent with respect to the energy.
diff --git a/src/ImageSharp/Common/Helpers/Guard.cs b/src/ImageSharp/Common/Helpers/Guard.cs
index d8cf69a52e..e86da78e30 100644
--- a/src/ImageSharp/Common/Helpers/Guard.cs
+++ b/src/ImageSharp/Common/Helpers/Guard.cs
@@ -257,6 +257,26 @@ public static void DestinationShouldNotBeTooShort(
}
}
+ ///
+ /// Verifies that the 'destination' span is not shorter than 'source'.
+ ///
+ /// The source element type
+ /// The destination element type
+ /// The source span
+ /// The destination span
+ /// The name of the argument for 'destination'
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static void DestinationShouldNotBeTooShort(
+ Span source,
+ Span destination,
+ string destinationParamName)
+ {
+ if (destination.Length < source.Length)
+ {
+ ThrowArgumentException($"Destination span is too short!", destinationParamName);
+ }
+ }
+
///
/// Verifies, that the `source` span has the length of 'minLength', or longer.
///
diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs
index 438749abf9..2c81908843 100644
--- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs
+++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs
@@ -173,7 +173,7 @@ private void ConvertColorsInto(ImageFrame destination)
Span destRow = destination.GetPixelRowSpan(yy);
// TODO: Investigate if slicing is actually necessary
- PixelOperations.Instance.FromVector4(this.configuration, this.rgbaBuffer.GetSpan().Slice(0, destRow.Length), destRow);
+ PixelOperations.Instance.FromVector4Destructive(this.configuration, this.rgbaBuffer.GetSpan().Slice(0, destRow.Length), destRow);
}
}
}
diff --git a/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs
index 5c8e506ae1..d2a6fbf501 100644
--- a/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs
+++ b/src/ImageSharp/PixelFormats/PixelBlender{TPixel}.cs
@@ -112,21 +112,15 @@ public void Blend(
Span backgroundSpan = buffer.Slice(destination.Length, destination.Length);
Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length);
- PixelOperations.Instance.ToScaledVector4(
- configuration,
- background.Slice(0, background.Length),
- backgroundSpan);
- PixelOperations.Instance.ToScaledVector4(
- configuration,
- source.Slice(0, background.Length),
- sourceSpan);
+ ReadOnlySpan sourcePixels = background.Slice(0, background.Length);
+ PixelOperations.Instance.ToVector4(configuration, sourcePixels, backgroundSpan, PixelConversionModifiers.Scale);
+ ReadOnlySpan sourcePixels1 = source.Slice(0, background.Length);
+ PixelOperations.Instance.ToVector4(configuration, sourcePixels1, sourceSpan, PixelConversionModifiers.Scale);
this.BlendFunction(destinationSpan, backgroundSpan, sourceSpan, amount);
- PixelOperations.Instance.FromScaledVector4(
- configuration,
- destinationSpan.Slice(0, background.Length),
- destination);
+ Span sourceVectors = destinationSpan.Slice(0, background.Length);
+ PixelOperations.Instance.FromVector4Destructive(configuration, sourceVectors, destination, PixelConversionModifiers.Scale);
}
}
@@ -161,21 +155,15 @@ public void Blend(
Span backgroundSpan = buffer.Slice(destination.Length, destination.Length);
Span sourceSpan = buffer.Slice(destination.Length * 2, destination.Length);
- PixelOperations.Instance.ToScaledVector4(
- configuration,
- background.Slice(0, background.Length),
- backgroundSpan);
- PixelOperations.Instance.ToScaledVector4(
- configuration,
- source.Slice(0, background.Length),
- sourceSpan);
+ ReadOnlySpan sourcePixels = background.Slice(0, background.Length);
+ PixelOperations.Instance.ToVector4(configuration, sourcePixels, backgroundSpan, PixelConversionModifiers.Scale);
+ ReadOnlySpan sourcePixels1 = source.Slice(0, background.Length);
+ PixelOperations.Instance.ToVector4(configuration, sourcePixels1, sourceSpan, PixelConversionModifiers.Scale);
this.BlendFunction(destinationSpan, backgroundSpan, sourceSpan, amount);
- PixelOperations.Instance.FromScaledVector4(
- configuration,
- destinationSpan.Slice(0, background.Length),
- destination);
+ Span sourceVectors = destinationSpan.Slice(0, background.Length);
+ PixelOperations.Instance.FromVector4Destructive(configuration, sourceVectors, destination, PixelConversionModifiers.Scale);
}
}
}
diff --git a/src/ImageSharp/PixelFormats/PixelConversionModifiers.cs b/src/ImageSharp/PixelFormats/PixelConversionModifiers.cs
new file mode 100644
index 0000000000..5df5dc62bc
--- /dev/null
+++ b/src/ImageSharp/PixelFormats/PixelConversionModifiers.cs
@@ -0,0 +1,40 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
+
+using SixLabors.ImageSharp.ColorSpaces.Companding;
+
+namespace SixLabors.ImageSharp.PixelFormats
+{
+ ///
+ /// Flags responsible to select additional operations which could be effitiently applied in
+ ///
+ /// or
+ ///
+ /// knowing the pixel type.
+ ///
+ [Flags]
+ internal enum PixelConversionModifiers
+ {
+ ///
+ /// No special operation is selected
+ ///
+ None = 0,
+
+ ///
+ /// Select and instead the standard (non scaled) variants.
+ ///
+ Scale = 1 << 0,
+
+ ///
+ /// Enable alpha premultiplication / unpremultiplication
+ ///
+ Premultiply = 1 << 1,
+
+ ///
+ /// Enable SRGB companding (defined in ).
+ ///
+ SRgbCompand = 1 << 2,
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/PixelFormats/PixelConversionModifiersExtensions.cs b/src/ImageSharp/PixelFormats/PixelConversionModifiersExtensions.cs
new file mode 100644
index 0000000000..bf77f85114
--- /dev/null
+++ b/src/ImageSharp/PixelFormats/PixelConversionModifiersExtensions.cs
@@ -0,0 +1,20 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using System.Runtime.CompilerServices;
+
+namespace SixLabors.ImageSharp.PixelFormats
+{
+ internal static class PixelConversionModifiersExtensions
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static bool IsDefined(this PixelConversionModifiers modifiers, PixelConversionModifiers expected) =>
+ (modifiers & expected) == expected;
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static PixelConversionModifiers Remove(
+ this PixelConversionModifiers modifiers,
+ PixelConversionModifiers removeThis) =>
+ modifiers & ~removeThis;
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs
index 2ec965dfb0..4cff1f8c10 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs
@@ -42,29 +42,16 @@ internal override void ToArgb32(Configuration configuration, ReadOnlySpan
- internal override void FromVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span destPixels)
+ internal override void FromVector4Destructive(Configuration configuration, Span sourceVectors, Span destPixels, PixelConversionModifiers modifiers)
{
- Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, false);
+ Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, modifiers.Remove(PixelConversionModifiers.Scale));
}
///
- internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors)
+ internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors, PixelConversionModifiers modifiers)
{
- Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, false);
+ Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, modifiers.Remove(PixelConversionModifiers.Scale));
}
-
- ///
- internal override void FromScaledVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span destPixels)
- {
- Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, true);
- }
-
- ///
- internal override void ToScaledVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors)
- {
- Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, true);
- }
-
///
internal override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels)
{
diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs
index 711a9d1c16..225e4b5e01 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgr24.PixelOperations.Generated.cs
@@ -42,30 +42,17 @@ internal override void ToBgr24(Configuration configuration, ReadOnlySpan
}
///
- internal override void FromVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span destPixels)
+ internal override void FromVector4Destructive(Configuration configuration, Span sourceVectors, Span destPixels, PixelConversionModifiers modifiers)
{
- Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, false);
+ Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, modifiers.Remove(PixelConversionModifiers.Scale | PixelConversionModifiers.Premultiply));
}
///
- internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors)
+ internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors, PixelConversionModifiers modifiers)
{
- Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, false);
+ Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, modifiers.Remove(PixelConversionModifiers.Scale | PixelConversionModifiers.Premultiply));
}
- ///
- internal override void FromScaledVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span destPixels)
- {
- Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, true);
- }
-
- ///
- internal override void ToScaledVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors)
- {
- Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, true);
- }
-
-
///
internal override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels)
{
diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs
index b669dd5348..ce049115ea 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs
@@ -42,29 +42,16 @@ internal override void ToBgra32(Configuration configuration, ReadOnlySpan
- internal override void FromVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span destPixels)
+ internal override void FromVector4Destructive(Configuration configuration, Span sourceVectors, Span destPixels, PixelConversionModifiers modifiers)
{
- Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, false);
+ Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, modifiers.Remove(PixelConversionModifiers.Scale));
}
///
- internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors)
+ internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors, PixelConversionModifiers modifiers)
{
- Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, false);
+ Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, modifiers.Remove(PixelConversionModifiers.Scale));
}
-
- ///
- internal override void FromScaledVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span destPixels)
- {
- Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, true);
- }
-
- ///
- internal override void ToScaledVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors)
- {
- Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, true);
- }
-
///
internal override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels)
{
diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs
index dbf3102c4a..02a8869ecc 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgb24.PixelOperations.Generated.cs
@@ -42,30 +42,17 @@ internal override void ToRgb24(Configuration configuration, ReadOnlySpan
}
///
- internal override void FromVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span destPixels)
+ internal override void FromVector4Destructive(Configuration configuration, Span sourceVectors, Span destPixels, PixelConversionModifiers modifiers)
{
- Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, false);
+ Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, modifiers.Remove(PixelConversionModifiers.Scale | PixelConversionModifiers.Premultiply));
}
///
- internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors)
+ internal override void ToVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors, PixelConversionModifiers modifiers)
{
- Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, false);
+ Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, modifiers.Remove(PixelConversionModifiers.Scale | PixelConversionModifiers.Premultiply));
}
- ///
- internal override void FromScaledVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span destPixels)
- {
- Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, true);
- }
-
- ///
- internal override void ToScaledVector4(Configuration configuration, ReadOnlySpan sourcePixels, Span destVectors)
- {
- Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, true);
- }
-
-
///
internal override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destPixels)
{
diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude
index f0675cb5b3..584615532d 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude
@@ -22,6 +22,7 @@ using System.Runtime.InteropServices;
// Types with Rgba32-combatible to/from Vector4 conversion
static readonly string[] Rgba32CompatibleTypes = { "Argb32", "Bgra32", "Rgb24", "Bgr24" };
+
void GenerateDefaultSelfConversionMethods(string pixelType)
{
#>
@@ -107,33 +108,25 @@ using System.Runtime.InteropServices;
<#+
}
- void GenerateRgba32CompatibleVector4ConversionMethods(string pixelType)
+ void GenerateRgba32CompatibleVector4ConversionMethods(string pixelType, bool hasAlpha)
{
+ string removeTheseModifiers = "PixelConversionModifiers.Scale";
+ if (!hasAlpha)
+ {
+ removeTheseModifiers += " | PixelConversionModifiers.Premultiply";
+ }
#>
///
- internal override void FromVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span<<#=pixelType#>> destPixels)
- {
- Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, false);
- }
-
- ///
- internal override void ToVector4(Configuration configuration, ReadOnlySpan<<#=pixelType#>> sourcePixels, Span destVectors)
+ internal override void FromVector4(Configuration configuration, Span sourceVectors, Span<<#=pixelType#>> destPixels, PixelConversionModifiers modifiers)
{
- Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, false);
+ Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, modifiers.Remove(<#=removeTheseModifiers#>));
}
///
- internal override void FromScaledVector4(Configuration configuration, ReadOnlySpan sourceVectors, Span<<#=pixelType#>> destPixels)
+ internal override void ToVector4(Configuration configuration, ReadOnlySpan<<#=pixelType#>> sourcePixels, Span destVectors, PixelConversionModifiers modifiers)
{
- Vector4Converters.RgbaCompatible.FromVector4(configuration, this, sourceVectors, destPixels, true);
+ Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, modifiers.Remove(<#=removeTheseModifiers#>));
}
-
- ///
- internal override void ToScaledVector4(Configuration configuration, ReadOnlySpan<<#=pixelType#>> sourcePixels, Span destVectors)
- {
- Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, true);
- }
-
<#+
}
@@ -143,7 +136,7 @@ using System.Runtime.InteropServices;
if (Rgba32CompatibleTypes.Contains(pixelType))
{
- GenerateRgba32CompatibleVector4ConversionMethods(pixelType);
+ GenerateRgba32CompatibleVector4ConversionMethods(pixelType, pixelType.EndsWith("32"));
}
var matching32BitTypes = Optimized32BitTypes.Contains(pixelType) ?
@@ -164,4 +157,4 @@ using System.Runtime.InteropServices;
GenerateDefaultConvertToMethod(pixelType, destPixelType);
}
}
-#>
\ No newline at end of file
+#>
diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs
index 004b25cd33..3da5d1855b 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/Rgba32.PixelOperations.cs
@@ -4,6 +4,8 @@
using System;
using System.Numerics;
using System.Runtime.InteropServices;
+
+using SixLabors.ImageSharp.PixelFormats.Utils;
using SixLabors.Memory;
namespace SixLabors.ImageSharp.PixelFormats
@@ -22,49 +24,33 @@ internal partial class PixelOperations : PixelOperations
internal override void ToVector4(
Configuration configuration,
ReadOnlySpan sourcePixels,
- Span destVectors)
+ Span destVectors,
+ PixelConversionModifiers modifiers)
{
Guard.DestinationShouldNotBeTooShort(sourcePixels, destVectors, nameof(destVectors));
destVectors = destVectors.Slice(0, sourcePixels.Length);
-
SimdUtils.BulkConvertByteToNormalizedFloat(
MemoryMarshal.Cast(sourcePixels),
MemoryMarshal.Cast(destVectors));
+ Vector4Converters.ApplyForwardConversionModifiers(destVectors, modifiers);
}
///
- internal override void FromVector4(
+ internal override void FromVector4Destructive(
Configuration configuration,
- ReadOnlySpan sourceVectors,
- Span destPixels)
+ Span sourceVectors,
+ Span destPixels,
+ PixelConversionModifiers modifiers)
{
Guard.DestinationShouldNotBeTooShort(sourceVectors, destPixels, nameof(destPixels));
destPixels = destPixels.Slice(0, sourceVectors.Length);
-
+ Vector4Converters.ApplyBackwardConversionModifiers(sourceVectors, modifiers);
SimdUtils.BulkConvertNormalizedFloatToByteClampOverflows(
MemoryMarshal.Cast(sourceVectors),
MemoryMarshal.Cast(destPixels));
}
-
- ///
- internal override void ToScaledVector4(
- Configuration configuration,
- ReadOnlySpan sourceColors,
- Span destinationVectors)
- {
- this.ToVector4(configuration, sourceColors, destinationVectors);
- }
-
- ///
- internal override void FromScaledVector4(
- Configuration configuration,
- ReadOnlySpan sourceVectors,
- Span destinationColors)
- {
- this.FromVector4(configuration, sourceVectors, destinationColors);
- }
}
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs
index bffaf57ddd..3112126e76 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/RgbaVector.PixelOperations.cs
@@ -5,6 +5,8 @@
using System.Numerics;
using System.Runtime.InteropServices;
+using SixLabors.ImageSharp.PixelFormats.Utils;
+
namespace SixLabors.ImageSharp.PixelFormats
{
///
@@ -18,32 +20,29 @@ public partial struct RgbaVector
internal class PixelOperations : PixelOperations
{
///
- internal override void FromScaledVector4(
+ internal override void FromVector4Destructive(
Configuration configuration,
- ReadOnlySpan sourceVectors,
- Span destinationColors)
+ Span sourceVectors,
+ Span destinationColors,
+ PixelConversionModifiers modifiers)
{
Guard.DestinationShouldNotBeTooShort(sourceVectors, destinationColors, nameof(destinationColors));
+ Vector4Converters.ApplyBackwardConversionModifiers(sourceVectors, modifiers);
MemoryMarshal.Cast(sourceVectors).CopyTo(destinationColors);
}
- ///
- internal override void ToScaledVector4(
- Configuration configuration,
- ReadOnlySpan sourceColors,
- Span destinationVectors)
- => this.ToVector4(configuration, sourceColors, destinationVectors);
-
///
internal override void ToVector4(
Configuration configuration,
ReadOnlySpan sourcePixels,
- Span destVectors)
+ Span destVectors,
+ PixelConversionModifiers modifiers)
{
Guard.DestinationShouldNotBeTooShort(sourcePixels, destVectors, nameof(destVectors));
MemoryMarshal.Cast(sourcePixels).CopyTo(destVectors);
+ Vector4Converters.ApplyForwardConversionModifiers(destVectors, modifiers);
}
}
}
diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs
index 115dd7a43d..d009822e80 100644
--- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs
+++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs
@@ -24,71 +24,70 @@ public partial class PixelOperations
///
/// Bulk version of converting 'sourceVectors.Length' pixels into 'destinationColors'.
+ /// The method is DESTRUCTIVE altering the contents of .
///
+ ///
+ /// The destructive behavior is a design choice for performance reasons.
+ /// In a typical use case the contents of are abandoned after the conversion.
+ ///
/// A to configure internal operations
/// The to the source vectors.
/// The to the destination colors.
- internal virtual void FromVector4(
+ /// The to apply during the conversion
+ internal virtual void FromVector4Destructive(
Configuration configuration,
- ReadOnlySpan sourceVectors,
- Span destPixels)
+ Span sourceVectors,
+ Span destPixels,
+ PixelConversionModifiers modifiers)
{
Guard.NotNull(configuration, nameof(configuration));
- Guard.DestinationShouldNotBeTooShort(sourceVectors, destPixels, nameof(destPixels));
- Utils.Vector4Converters.Default.DangerousFromVector4(sourceVectors, destPixels);
+ Utils.Vector4Converters.Default.FromVector4(sourceVectors, destPixels, modifiers);
}
+ ///
+ /// Bulk version of converting 'sourceVectors.Length' pixels into 'destinationColors'.
+ /// The method is DESTRUCTIVE altering the contents of .
+ ///
+ ///
+ /// The destructive behavior is a design choice for performance reasons.
+ /// In a typical use case the contents of are abandoned after the conversion.
+ ///
+ /// A to configure internal operations
+ /// The to the source vectors.
+ /// The to the destination colors.
+ internal void FromVector4Destructive(Configuration configuration, Span sourceVectors, Span destPixels) =>
+ this.FromVector4Destructive(configuration, sourceVectors, destPixels, PixelConversionModifiers.None);
+
///
/// Bulk version of converting 'sourceColors.Length' pixels into 'destinationVectors'.
///
/// A to configure internal operations
/// The to the source colors.
/// The to the destination vectors.
+ /// The to apply during the conversion
internal virtual void ToVector4(
Configuration configuration,
ReadOnlySpan sourcePixels,
- Span destVectors)
+ Span destVectors,
+ PixelConversionModifiers modifiers)
{
Guard.NotNull(configuration, nameof(configuration));
- Guard.DestinationShouldNotBeTooShort(sourcePixels, destVectors, nameof(destVectors));
- Utils.Vector4Converters.Default.DangerousToVector4(sourcePixels, destVectors);
+ Utils.Vector4Converters.Default.ToVector4(sourcePixels, destVectors, modifiers);
}
///
- /// Bulk version of converting 'sourceVectors.Length' pixels into 'destinationColors'.
- ///
- /// A to configure internal operations
- /// The to the source vectors.
- /// The to the destination colors.
- internal virtual void FromScaledVector4(
- Configuration configuration,
- ReadOnlySpan sourceVectors,
- Span destinationColors)
- {
- Guard.NotNull(configuration, nameof(configuration));
- Guard.DestinationShouldNotBeTooShort(sourceVectors, destinationColors, nameof(destinationColors));
-
- Utils.Vector4Converters.Default.DangerousFromScaledVector4(sourceVectors, destinationColors);
- }
-
- ///
- /// Bulk version of converting 'sourceColors.Length' pixels into 'destinationVectors'.
+ /// Bulk version of converting 'sourceColors.Length' pixels into 'destinationVectors'.
///
/// A to configure internal operations
- /// The to the source colors.
- /// The to the destination vectors.
- internal virtual void ToScaledVector4(
+ /// The to the source colors.
+ /// The to the destination vectors.
+ internal virtual void ToVector4(
Configuration configuration,
- ReadOnlySpan sourceColors,
- Span destinationVectors)
- {
- Guard.NotNull(configuration, nameof(configuration));
- Guard.DestinationShouldNotBeTooShort(sourceColors, destinationVectors, nameof(destinationVectors));
-
- Utils.Vector4Converters.Default.DangerousToScaledVector4(sourceColors, destinationVectors);
- }
+ ReadOnlySpan sourcePixels,
+ Span destVectors) =>
+ this.ToVector4(configuration, sourcePixels, destVectors, PixelConversionModifiers.None);
///
/// Converts 'sourceColors.Length' pixels from 'sourceColors' into 'destinationColors'.
diff --git a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.Default.cs b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.Default.cs
index e784e3b5a6..4c4e60276d 100644
--- a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.Default.cs
+++ b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.Default.cs
@@ -6,6 +6,8 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
+using SixLabors.ImageSharp.ColorSpaces.Companding;
+
namespace SixLabors.ImageSharp.PixelFormats.Utils
{
///
@@ -15,13 +17,75 @@ internal static partial class Vector4Converters
{
///
/// Provides default implementations for batched to/from conversion.
- /// WARNING: The methods are operating without bounds checking and input validation!
+ /// WARNING: The methods prefixed with "Unsafe" are operating without bounds checking and input validation!
/// Input validation is the responsibility of the caller!
///
public static class Default
{
[MethodImpl(InliningOptions.ShortMethod)]
- internal static void DangerousFromVector4(
+ public static void FromVector4(
+ Span sourceVectors,
+ Span destPixels,
+ PixelConversionModifiers modifiers)
+ where TPixel : struct, IPixel
+ {
+ Guard.DestinationShouldNotBeTooShort(sourceVectors, destPixels, nameof(destPixels));
+
+ UnsafeFromVector4(sourceVectors, destPixels, modifiers);
+ }
+
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static void ToVector4(
+ ReadOnlySpan sourcePixels,
+ Span destVectors,
+ PixelConversionModifiers modifiers)
+ where TPixel : struct, IPixel
+ {
+ Guard.DestinationShouldNotBeTooShort(sourcePixels, destVectors, nameof(destVectors));
+
+ UnsafeToVector4(sourcePixels, destVectors, modifiers);
+ }
+
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static void UnsafeFromVector4(
+ Span sourceVectors,
+ Span destPixels,
+ PixelConversionModifiers modifiers)
+ where TPixel : struct, IPixel
+ {
+ ApplyBackwardConversionModifiers(sourceVectors, modifiers);
+
+ if (modifiers.IsDefined(PixelConversionModifiers.Scale))
+ {
+ UnsafeFromScaledVector4Core(sourceVectors, destPixels);
+ }
+ else
+ {
+ UnsafeFromVector4Core(sourceVectors, destPixels);
+ }
+ }
+
+ [MethodImpl(InliningOptions.ShortMethod)]
+ public static void UnsafeToVector4(
+ ReadOnlySpan sourcePixels,
+ Span destVectors,
+ PixelConversionModifiers modifiers)
+ where TPixel : struct, IPixel
+ {
+ if (modifiers.IsDefined(PixelConversionModifiers.Scale))
+ {
+ UnsafeToScaledVector4Core(sourcePixels, destVectors);
+ }
+ else
+ {
+ UnsafeToVector4Core(sourcePixels, destVectors);
+ }
+
+ ApplyForwardConversionModifiers(destVectors, modifiers);
+ }
+
+ [MethodImpl(InliningOptions.ShortMethod)]
+ private static void UnsafeFromVector4Core(
ReadOnlySpan sourceVectors,
Span destPixels)
where TPixel : struct, IPixel
@@ -38,7 +102,7 @@ internal static void DangerousFromVector4(
}
[MethodImpl(InliningOptions.ShortMethod)]
- internal static void DangerousToVector4(
+ private static void UnsafeToVector4Core(
ReadOnlySpan sourcePixels,
Span destVectors)
where TPixel : struct, IPixel
@@ -55,7 +119,7 @@ internal static void DangerousToVector4(
}
[MethodImpl(InliningOptions.ShortMethod)]
- internal static void DangerousFromScaledVector4(
+ private static void UnsafeFromScaledVector4Core(
ReadOnlySpan sourceVectors,
Span destinationColors)
where TPixel : struct, IPixel
@@ -72,7 +136,7 @@ internal static void DangerousFromScaledVector4(
}
[MethodImpl(InliningOptions.ShortMethod)]
- internal static void DangerousToScaledVector4(
+ private static void UnsafeToScaledVector4Core(
ReadOnlySpan sourceColors,
Span destinationVectors)
where TPixel : struct, IPixel
diff --git a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs
index 06c33d79c7..fe8d7dec3b 100644
--- a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs
+++ b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.RgbaCompatible.cs
@@ -7,6 +7,8 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
+using SixLabors.ImageSharp.ColorSpaces.Companding;
+
namespace SixLabors.ImageSharp.PixelFormats.Utils
{
///
@@ -29,11 +31,8 @@ public static class RgbaCompatible
private static readonly int Vector4ConversionThreshold = CalculateVector4ConversionThreshold();
///
- /// Provides an efficient default implementation for
- /// and
- /// which is applicable for -compatible pixel types where
- /// returns the same scaled result as .
- /// The method is works by internally converting to a therefore it's not applicable for that type!
+ /// Provides an efficient default implementation for
+ /// The method works by internally converting to a therefore it's not applicable for that type!
///
[MethodImpl(InliningOptions.ShortMethod)]
internal static void ToVector4(
@@ -41,7 +40,7 @@ internal static void ToVector4(
PixelOperations pixelOperations,
ReadOnlySpan sourcePixels,
Span destVectors,
- bool scaled)
+ PixelConversionModifiers modifiers)
where TPixel : struct, IPixel
{
Guard.NotNull(configuration, nameof(configuration));
@@ -52,7 +51,7 @@ internal static void ToVector4(
// Not worth for small buffers:
if (count < Vector4ConversionThreshold)
{
- ToVector4Fallback(sourcePixels, destVectors, scaled);
+ Default.UnsafeToVector4(sourcePixels, destVectors, modifiers);
return;
}
@@ -70,22 +69,22 @@ internal static void ToVector4(
MemoryMarshal.Cast(destVectors.Slice(0, countWithoutLastItem)));
destVectors[countWithoutLastItem] = sourcePixels[countWithoutLastItem].ToVector4();
+
+ // TODO: Investigate optimized 1-pass approach!
+ ApplyForwardConversionModifiers(destVectors, modifiers);
}
///
- /// Provides an efficient default implementation for
- /// and
- /// which is applicable for -compatible pixel types where
- /// returns the same scaled result as .
+ /// Provides an efficient default implementation for
/// The method is works by internally converting to a therefore it's not applicable for that type!
///
[MethodImpl(InliningOptions.ShortMethod)]
internal static void FromVector4(
Configuration configuration,
PixelOperations pixelOperations,
- ReadOnlySpan sourceVectors,
+ Span sourceVectors,
Span destPixels,
- bool scaled)
+ PixelConversionModifiers modifiers)
where TPixel : struct, IPixel
{
Guard.NotNull(configuration, nameof(configuration));
@@ -96,11 +95,14 @@ internal static void FromVector4(
// Not worth for small buffers:
if (count < Vector4ConversionThreshold)
{
- FromVector4Fallback(sourceVectors, destPixels, scaled);
+ Default.UnsafeFromVector4(sourceVectors, destPixels, modifiers);
return;
}
+ // TODO: Investigate optimized 1-pass approach!
+ ApplyBackwardConversionModifiers(sourceVectors, modifiers);
+
// For the opposite direction it's not easy to implement the trick used in RunRgba32CompatibleToVector4Conversion,
// so let's allocate a temporary buffer as usually:
using (IMemoryOwner tempBuffer = configuration.MemoryAllocator.Allocate(count))
@@ -115,34 +117,6 @@ internal static void FromVector4(
}
}
- [MethodImpl(InliningOptions.ColdPath)]
- private static void ToVector4Fallback(ReadOnlySpan sourcePixels, Span destVectors, bool scaled)
- where TPixel : struct, IPixel
- {
- if (scaled)
- {
- Default.DangerousToScaledVector4(sourcePixels, destVectors);
- }
- else
- {
- Default.DangerousToVector4(sourcePixels, destVectors);
- }
- }
-
- [MethodImpl(InliningOptions.ColdPath)]
- private static void FromVector4Fallback(ReadOnlySpan sourceVectors, Span destPixels, bool scaled)
- where TPixel : struct, IPixel
- {
- if (scaled)
- {
- Default.DangerousFromScaledVector4(sourceVectors, destPixels);
- }
- else
- {
- Default.DangerousFromVector4(sourceVectors, destPixels);
- }
- }
-
private static int CalculateVector4ConversionThreshold()
{
if (!Vector.IsHardwareAccelerated)
diff --git a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.cs b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.cs
new file mode 100644
index 0000000000..447869a7d5
--- /dev/null
+++ b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.cs
@@ -0,0 +1,48 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
+using System.Numerics;
+using System.Runtime.CompilerServices;
+
+using SixLabors.ImageSharp.ColorSpaces.Companding;
+
+namespace SixLabors.ImageSharp.PixelFormats.Utils
+{
+ internal static partial class Vector4Converters
+ {
+ ///
+ /// Apply modifiers used requested by ToVector4() conversion.
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal static void ApplyForwardConversionModifiers(Span vectors, PixelConversionModifiers modifiers)
+ {
+ if (modifiers.IsDefined(PixelConversionModifiers.SRgbCompand))
+ {
+ SRgbCompanding.Expand(vectors);
+ }
+
+ if (modifiers.IsDefined(PixelConversionModifiers.Premultiply))
+ {
+ Vector4Utils.Premultiply(vectors);
+ }
+ }
+
+ ///
+ /// Apply modifiers used requested by FromVector4() conversion.
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal static void ApplyBackwardConversionModifiers(Span vectors, PixelConversionModifiers modifiers)
+ {
+ if (modifiers.IsDefined(PixelConversionModifiers.Premultiply))
+ {
+ Vector4Utils.UnPremultiply(vectors);
+ }
+
+ if (modifiers.IsDefined(PixelConversionModifiers.SRgbCompand))
+ {
+ SRgbCompanding.Compress(vectors);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs
index bd1419e4bb..341a26ae84 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs
@@ -82,7 +82,7 @@ protected override void OnFrameApply(
DenseMatrixUtils.Convolve2D(in matrixY, in matrixX, source.PixelBuffer, vectorSpan, y, x, maxY, maxX, startX);
}
- PixelOperations.Instance.FromVector4(configuration, vectorSpan.Slice(0, length), targetRowSpan);
+ PixelOperations.Instance.FromVector4Destructive(configuration, vectorSpan.Slice(0, length), targetRowSpan);
}
});
diff --git a/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs
index 05007c3706..9de4673289 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs
@@ -100,7 +100,7 @@ private void ApplyConvolution(
DenseMatrixUtils.Convolve(in matrix, sourcePixels, vectorSpan, y, x, maxY, maxX, startX);
}
- PixelOperations.Instance.FromVector4(configuration, vectorSpan.Slice(0, length), targetRowSpan);
+ PixelOperations.Instance.FromVector4Destructive(configuration, vectorSpan.Slice(0, length), targetRowSpan);
}
});
}
diff --git a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs
index 8ef64bdacc..7e003cb03e 100644
--- a/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs
@@ -66,7 +66,7 @@ protected override void OnFrameApply(ImageFrame source, Rectangle source
DenseMatrixUtils.Convolve(in matrix, source.PixelBuffer, vectorSpan, y, x, maxY, maxX, startX);
}
- PixelOperations.Instance.FromVector4(configuration, vectorSpan.Slice(0, length), targetRowSpan);
+ PixelOperations.Instance.FromVector4Destructive(configuration, vectorSpan.Slice(0, length), targetRowSpan);
}
});
diff --git a/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessorBase.cs b/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessorBase.cs
index 43f6c8a454..6313b74c94 100644
--- a/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessorBase.cs
+++ b/src/ImageSharp/Processing/Processors/Dithering/PaletteDitherProcessorBase.cs
@@ -98,7 +98,7 @@ protected override void BeforeFrameApply(ImageFrame source, Rectangle so
if (this.paletteVector is null)
{
this.paletteVector = new Vector4[this.Palette.Length];
- PixelOperations.Instance.ToScaledVector4(configuration, this.Palette, this.paletteVector);
+ PixelOperations.Instance.ToVector4(configuration, (ReadOnlySpan)this.Palette, (Span)this.paletteVector, PixelConversionModifiers.Scale);
}
}
}
diff --git a/src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs b/src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs
index d6a32d8899..dbd8433410 100644
--- a/src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Filters/FilterProcessor.cs
@@ -51,7 +51,7 @@ protected override void OnFrameApply(ImageFrame source, Rectangle source
Vector4Utils.Transform(vectorSpan, ref matrix);
- PixelOperations.Instance.FromVector4(configuration, vectorSpan, rowSpan);
+ PixelOperations.Instance.FromVector4Destructive(configuration, vectorSpan, rowSpan);
}
});
}
diff --git a/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerBase{TPixel}.cs b/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerBase{TPixel}.cs
index 3b9b046a00..a70cfb6601 100644
--- a/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerBase{TPixel}.cs
+++ b/src/ImageSharp/Processing/Processors/Quantization/FrameQuantizerBase{TPixel}.cs
@@ -79,7 +79,7 @@ public virtual QuantizedFrame QuantizeFrame(ImageFrame image)
// Collect the palette. Required before the second pass runs.
TPixel[] palette = this.GetPalette();
this.paletteVector = new Vector4[palette.Length];
- PixelOperations.Instance.ToScaledVector4(image.Configuration, palette, this.paletteVector);
+ PixelOperations.Instance.ToVector4(image.Configuration, (ReadOnlySpan)palette, (Span)this.paletteVector, PixelConversionModifiers.Scale);
var quantizedFrame = new QuantizedFrame(image.MemoryAllocator, width, height, palette);
if (this.Dither)
diff --git a/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs
index 5a3b5943b7..0f71c732dd 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/AffineTransformProcessor.cs
@@ -129,7 +129,7 @@ protected override void OnFrameApply(
kernel.Convolve(point, x, ref ySpanRef, ref xSpanRef, source.PixelBuffer, vectorSpan);
}
- PixelOperations.Instance.FromVector4(configuration, vectorSpan, targetRowSpan);
+ PixelOperations.Instance.FromVector4Destructive(configuration, vectorSpan, targetRowSpan);
}
});
}
diff --git a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs
index 0b5627e19b..8a5d7563f4 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/ProjectiveTransformProcessor.cs
@@ -128,7 +128,7 @@ protected override void OnFrameApply(ImageFrame source, ImageFrame.Instance.FromVector4(configuration, vectorSpan, targetRowSpan);
+ PixelOperations.Instance.FromVector4Destructive(configuration, vectorSpan, targetRowSpan);
}
});
}
diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs
index 189e21de7a..2c186a276b 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor.cs
@@ -9,7 +9,6 @@
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Advanced;
-using SixLabors.ImageSharp.ColorSpaces.Companding;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.ParallelUtils;
using SixLabors.ImageSharp.PixelFormats;
@@ -216,27 +215,33 @@ protected override void OnFrameApply(ImageFrame source, ImageFrame
+ {
+ for (int y = rows.Min; y < rows.Max; y++)
{
- for (int y = rows.Min; y < rows.Max; y++)
+ // Y coordinates of source points
+ Span sourceRow =
+ source.GetPixelRowSpan((int)(((y - startY) * heightFactor) + sourceY));
+ Span targetRow = destination.GetPixelRowSpan(y);
+
+ for (int x = minX; x < maxX; x++)
{
- // Y coordinates of source points
- Span sourceRow =
- source.GetPixelRowSpan((int)(((y - startY) * heightFactor) + sourceY));
- Span targetRow = destination.GetPixelRowSpan(y);
-
- for (int x = minX; x < maxX; x++)
- {
- // X coordinates of source points
- targetRow[x] = sourceRow[(int)(((x - startX) * widthFactor) + sourceX)];
- }
+ // X coordinates of source points
+ targetRow[x] = sourceRow[(int)(((x - startX) * widthFactor) + sourceX)];
}
- });
+ }
+ });
return;
}
int sourceHeight = source.Height;
+ PixelConversionModifiers conversionModifiers = PixelConversionModifiers.Premultiply;
+ if (this.Compand)
+ {
+ conversionModifiers |= PixelConversionModifiers.Scale | PixelConversionModifiers.SRgbCompand;
+ }
+
// Interpolate the image using the calculated weights.
// A 2-pass 1D algorithm appears to be faster than splitting a 1-pass 2D algorithm
// First process the columns. Since we are not using multiple threads startY and endY
@@ -251,30 +256,23 @@ protected override void OnFrameApply(ImageFrame source, ImageFrame
+ {
+ for (int y = rows.Min; y < rows.Max; y++)
{
- for (int y = rows.Min; y < rows.Max; y++)
- {
- Span sourceRow = source.GetPixelRowSpan(y).Slice(sourceX);
- Span tempRowSpan = tempRowBuffer.Span.Slice(sourceX);
-
- PixelOperations