diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs
index 0b1292b64..3f48d2acc 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Argb32.PixelOperations.Generated.cs
@@ -53,66 +53,58 @@ namespace SixLabors.ImageSharp.PixelFormats
Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, modifiers.Remove(PixelConversionModifiers.Scale));
}
///
- public override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels)
+ public override void ToRgba32(
+ Configuration configuration,
+ ReadOnlySpan sourcePixels,
+ Span destinationPixels)
{
Guard.NotNull(configuration, nameof(configuration));
Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels));
- ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels));
- ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destinationPixels));
-
- for (int i = 0; i < sourcePixels.Length; i++)
- {
- uint sp = Unsafe.Add(ref sourceRef, i);
- Unsafe.Add(ref destRef, i) = PixelConverter.FromArgb32.ToRgba32(sp);
- }
+ ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels);
+ Span dest = MemoryMarshal.Cast(destinationPixels);
+ PixelConverter.FromArgb32.ToRgba32(source, dest);
}
///
- public override void FromRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels)
+ public override void FromRgba32(
+ Configuration configuration,
+ ReadOnlySpan sourcePixels,
+ Span destinationPixels)
{
Guard.NotNull(configuration, nameof(configuration));
Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels));
- ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels));
- ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destinationPixels));
-
- for (int i = 0; i < sourcePixels.Length; i++)
- {
- uint sp = Unsafe.Add(ref sourceRef, i);
- Unsafe.Add(ref destRef, i) = PixelConverter.FromRgba32.ToArgb32(sp);
- }
+ ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels);
+ Span dest = MemoryMarshal.Cast(destinationPixels);
+ PixelConverter.FromRgba32.ToArgb32(source, dest);
}
///
- public override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels)
+ public override void ToBgra32(
+ Configuration configuration,
+ ReadOnlySpan sourcePixels,
+ Span destinationPixels)
{
Guard.NotNull(configuration, nameof(configuration));
Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels));
- ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels));
- ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destinationPixels));
-
- for (int i = 0; i < sourcePixels.Length; i++)
- {
- uint sp = Unsafe.Add(ref sourceRef, i);
- Unsafe.Add(ref destRef, i) = PixelConverter.FromArgb32.ToBgra32(sp);
- }
+ ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels);
+ Span dest = MemoryMarshal.Cast(destinationPixels);
+ PixelConverter.FromArgb32.ToBgra32(source, dest);
}
///
- public override void FromBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels)
+ public override void FromBgra32(
+ Configuration configuration,
+ ReadOnlySpan sourcePixels,
+ Span destinationPixels)
{
Guard.NotNull(configuration, nameof(configuration));
Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels));
- ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels));
- ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destinationPixels));
-
- for (int i = 0; i < sourcePixels.Length; i++)
- {
- uint sp = Unsafe.Add(ref sourceRef, i);
- Unsafe.Add(ref destRef, i) = PixelConverter.FromBgra32.ToArgb32(sp);
- }
+ ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels);
+ Span dest = MemoryMarshal.Cast(destinationPixels);
+ PixelConverter.FromBgra32.ToArgb32(source, dest);
}
///
diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs
index 5bdd10404..8cf2d5850 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Bgra32.PixelOperations.Generated.cs
@@ -53,66 +53,58 @@ namespace SixLabors.ImageSharp.PixelFormats
Vector4Converters.RgbaCompatible.ToVector4(configuration, this, sourcePixels, destVectors, modifiers.Remove(PixelConversionModifiers.Scale));
}
///
- public override void ToRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels)
+ public override void ToRgba32(
+ Configuration configuration,
+ ReadOnlySpan sourcePixels,
+ Span destinationPixels)
{
Guard.NotNull(configuration, nameof(configuration));
Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels));
- ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels));
- ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destinationPixels));
-
- for (int i = 0; i < sourcePixels.Length; i++)
- {
- uint sp = Unsafe.Add(ref sourceRef, i);
- Unsafe.Add(ref destRef, i) = PixelConverter.FromBgra32.ToRgba32(sp);
- }
+ ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels);
+ Span dest = MemoryMarshal.Cast(destinationPixels);
+ PixelConverter.FromBgra32.ToRgba32(source, dest);
}
///
- public override void FromRgba32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels)
+ public override void FromRgba32(
+ Configuration configuration,
+ ReadOnlySpan sourcePixels,
+ Span destinationPixels)
{
Guard.NotNull(configuration, nameof(configuration));
Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels));
- ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels));
- ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destinationPixels));
-
- for (int i = 0; i < sourcePixels.Length; i++)
- {
- uint sp = Unsafe.Add(ref sourceRef, i);
- Unsafe.Add(ref destRef, i) = PixelConverter.FromRgba32.ToBgra32(sp);
- }
+ ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels);
+ Span dest = MemoryMarshal.Cast(destinationPixels);
+ PixelConverter.FromRgba32.ToBgra32(source, dest);
}
///
- public override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels)
+ public override void ToArgb32(
+ Configuration configuration,
+ ReadOnlySpan sourcePixels,
+ Span destinationPixels)
{
Guard.NotNull(configuration, nameof(configuration));
Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels));
- ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels));
- ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destinationPixels));
-
- for (int i = 0; i < sourcePixels.Length; i++)
- {
- uint sp = Unsafe.Add(ref sourceRef, i);
- Unsafe.Add(ref destRef, i) = PixelConverter.FromBgra32.ToArgb32(sp);
- }
+ ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels);
+ Span dest = MemoryMarshal.Cast(destinationPixels);
+ PixelConverter.FromBgra32.ToArgb32(source, dest);
}
///
- public override void FromArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels)
+ public override void FromArgb32(
+ Configuration configuration,
+ ReadOnlySpan sourcePixels,
+ Span destinationPixels)
{
Guard.NotNull(configuration, nameof(configuration));
Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels));
- ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels));
- ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destinationPixels));
-
- for (int i = 0; i < sourcePixels.Length; i++)
- {
- uint sp = Unsafe.Add(ref sourceRef, i);
- Unsafe.Add(ref destRef, i) = PixelConverter.FromArgb32.ToBgra32(sp);
- }
+ ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels);
+ Span dest = MemoryMarshal.Cast(destinationPixels);
+ PixelConverter.FromArgb32.ToBgra32(source, dest);
}
///
diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.cs b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.cs
index b05c62f1f..9a36ec29a 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.cs
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/Rgba32.PixelOperations.Generated.cs
@@ -42,66 +42,58 @@ namespace SixLabors.ImageSharp.PixelFormats
}
///
- public override void ToArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels)
+ public override void ToArgb32(
+ Configuration configuration,
+ ReadOnlySpan sourcePixels,
+ Span destinationPixels)
{
Guard.NotNull(configuration, nameof(configuration));
Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels));
- ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels));
- ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destinationPixels));
-
- for (int i = 0; i < sourcePixels.Length; i++)
- {
- uint sp = Unsafe.Add(ref sourceRef, i);
- Unsafe.Add(ref destRef, i) = PixelConverter.FromRgba32.ToArgb32(sp);
- }
+ ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels);
+ Span dest = MemoryMarshal.Cast(destinationPixels);
+ PixelConverter.FromRgba32.ToArgb32(source, dest);
}
///
- public override void FromArgb32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels)
+ public override void FromArgb32(
+ Configuration configuration,
+ ReadOnlySpan sourcePixels,
+ Span destinationPixels)
{
Guard.NotNull(configuration, nameof(configuration));
Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels));
- ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels));
- ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destinationPixels));
-
- for (int i = 0; i < sourcePixels.Length; i++)
- {
- uint sp = Unsafe.Add(ref sourceRef, i);
- Unsafe.Add(ref destRef, i) = PixelConverter.FromArgb32.ToRgba32(sp);
- }
+ ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels);
+ Span dest = MemoryMarshal.Cast(destinationPixels);
+ PixelConverter.FromArgb32.ToRgba32(source, dest);
}
///
- public override void ToBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels)
+ public override void ToBgra32(
+ Configuration configuration,
+ ReadOnlySpan sourcePixels,
+ Span destinationPixels)
{
Guard.NotNull(configuration, nameof(configuration));
Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels));
- ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels));
- ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destinationPixels));
-
- for (int i = 0; i < sourcePixels.Length; i++)
- {
- uint sp = Unsafe.Add(ref sourceRef, i);
- Unsafe.Add(ref destRef, i) = PixelConverter.FromRgba32.ToBgra32(sp);
- }
+ ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels);
+ Span dest = MemoryMarshal.Cast(destinationPixels);
+ PixelConverter.FromRgba32.ToBgra32(source, dest);
}
///
- public override void FromBgra32(Configuration configuration, ReadOnlySpan sourcePixels, Span destinationPixels)
+ public override void FromBgra32(
+ Configuration configuration,
+ ReadOnlySpan sourcePixels,
+ Span destinationPixels)
{
Guard.NotNull(configuration, nameof(configuration));
Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels));
- ref uint sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(sourcePixels));
- ref uint destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destinationPixels));
-
- for (int i = 0; i < sourcePixels.Length; i++)
- {
- uint sp = Unsafe.Add(ref sourceRef, i);
- Unsafe.Add(ref destRef, i) = PixelConverter.FromBgra32.ToRgba32(sp);
- }
+ ReadOnlySpan source = MemoryMarshal.Cast(sourcePixels);
+ Span dest = MemoryMarshal.Cast(destinationPixels);
+ PixelConverter.FromBgra32.ToRgba32(source, dest);
}
///
diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude
index 5d56731ba..d8b5286cd 100644
--- a/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude
+++ b/src/ImageSharp/PixelFormats/PixelImplementations/Generated/_Common.ttinclude
@@ -88,35 +88,31 @@ using System.Runtime.InteropServices;
{
#>
///
- public override void To<#=otherPixelType#>(Configuration configuration, ReadOnlySpan<<#=thisPixelType#>> sourcePixels, Span<<#=otherPixelType#>> destinationPixels)
+ public override void To<#=otherPixelType#>(
+ Configuration configuration,
+ ReadOnlySpan<<#=thisPixelType#>> sourcePixels,
+ Span<<#=otherPixelType#>> destinationPixels)
{
Guard.NotNull(configuration, nameof(configuration));
Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels));
- ref uint sourceRef = ref Unsafe.As<<#=thisPixelType#>,uint>(ref MemoryMarshal.GetReference(sourcePixels));
- ref uint destRef = ref Unsafe.As<<#=otherPixelType#>, uint>(ref MemoryMarshal.GetReference(destinationPixels));
-
- for (int i = 0; i < sourcePixels.Length; i++)
- {
- uint sp = Unsafe.Add(ref sourceRef, i);
- Unsafe.Add(ref destRef, i) = PixelConverter.From<#=thisPixelType#>.To<#=otherPixelType#>(sp);
- }
+ ReadOnlySpan source = MemoryMarshal.Cast<<#=thisPixelType#>, byte>(sourcePixels);
+ Span dest = MemoryMarshal.Cast<<#=otherPixelType#>, byte>(destinationPixels);
+ PixelConverter.From<#=thisPixelType#>.To<#=otherPixelType#>(source, dest);
}
///
- public override void From<#=otherPixelType#>(Configuration configuration, ReadOnlySpan<<#=otherPixelType#>> sourcePixels, Span<<#=thisPixelType#>> destinationPixels)
+ public override void From<#=otherPixelType#>(
+ Configuration configuration,
+ ReadOnlySpan<<#=otherPixelType#>> sourcePixels,
+ Span<<#=thisPixelType#>> destinationPixels)
{
Guard.NotNull(configuration, nameof(configuration));
Guard.DestinationShouldNotBeTooShort(sourcePixels, destinationPixels, nameof(destinationPixels));
- ref uint sourceRef = ref Unsafe.As<<#=otherPixelType#>,uint>(ref MemoryMarshal.GetReference(sourcePixels));
- ref uint destRef = ref Unsafe.As<<#=thisPixelType#>, uint>(ref MemoryMarshal.GetReference(destinationPixels));
-
- for (int i = 0; i < sourcePixels.Length; i++)
- {
- uint sp = Unsafe.Add(ref sourceRef, i);
- Unsafe.Add(ref destRef, i) = PixelConverter.From<#=otherPixelType#>.To<#=thisPixelType#>(sp);
- }
+ ReadOnlySpan source = MemoryMarshal.Cast<<#=otherPixelType#>, byte>(sourcePixels);
+ Span dest = MemoryMarshal.Cast<<#=thisPixelType#>, byte>(destinationPixels);
+ PixelConverter.From<#=otherPixelType#>.To<#=thisPixelType#>(source, dest);
}
<#+
}
diff --git a/src/ImageSharp/PixelFormats/Utils/PixelConverter.cs b/src/ImageSharp/PixelFormats/Utils/PixelConverter.cs
index 814264084..bc24258c9 100644
--- a/src/ImageSharp/PixelFormats/Utils/PixelConverter.cs
+++ b/src/ImageSharp/PixelFormats/Utils/PixelConverter.cs
@@ -1,6 +1,7 @@
-// Copyright (c) Six Labors.
+// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
+using System;
using System.Buffers.Binary;
using System.Runtime.CompilerServices;
@@ -21,88 +22,64 @@ namespace SixLabors.ImageSharp.PixelFormats.Utils
public static class FromRgba32
{
///
- /// Converts a packed to .
+ /// Converts a representing a collection of
+ /// pixels to a representing
+ /// a collection of pixels.
///
[MethodImpl(InliningOptions.ShortMethod)]
- public static uint ToArgb32(uint packedRgba)
- {
- // packedRgba = [aa bb gg rr]
- // ROTL(8, packedRgba) = [bb gg rr aa]
- return (packedRgba << 8) | (packedRgba >> 24);
- }
+ public static void ToArgb32(ReadOnlySpan source, Span dest)
+ => SimdUtils.Shuffle4Channel(source, dest, SimdUtils.Shuffle.WXYZ);
///
- /// Converts a packed to .
+ /// Converts a representing a collection of
+ /// pixels to a representing
+ /// a collection of pixels.
///
[MethodImpl(InliningOptions.ShortMethod)]
- public static uint ToBgra32(uint packedRgba)
- {
- // packedRgba = [aa bb gg rr]
- // tmp1 = [aa 00 gg 00]
- // tmp2 = [00 bb 00 rr]
- // tmp3=ROTL(16, tmp2) = [00 rr 00 bb]
- // tmp1 + tmp3 = [aa rr gg bb]
- uint tmp1 = packedRgba & 0xFF00FF00;
- uint tmp2 = packedRgba & 0x00FF00FF;
- uint tmp3 = (tmp2 << 16) | (tmp2 >> 16);
- return tmp1 + tmp3;
- }
+ public static void ToBgra32(ReadOnlySpan source, Span dest)
+ => SimdUtils.Shuffle4Channel(source, dest, SimdUtils.Shuffle.ZYXW);
}
public static class FromArgb32
{
///
- /// Converts a packed to .
+ /// Converts a representing a collection of
+ /// pixels to a representing
+ /// a collection of pixels.
///
[MethodImpl(InliningOptions.ShortMethod)]
- public static uint ToRgba32(uint packedArgb)
- {
- // packedArgb = [bb gg rr aa]
- // ROTR(8, packedArgb) = [aa bb gg rr]
- return (packedArgb >> 8) | (packedArgb << 24);
- }
+ public static void ToRgba32(ReadOnlySpan source, Span dest)
+ => SimdUtils.Shuffle4Channel(source, dest, SimdUtils.Shuffle.YZWX);
///
- /// Converts a packed to .
+ /// Converts a representing a collection of
+ /// pixels to a representing
+ /// a collection of pixels.
///
[MethodImpl(InliningOptions.ShortMethod)]
- public static uint ToBgra32(uint packedArgb)
- {
- // packedArgb = [bb gg rr aa]
- // REVERSE(packedArgb) = [aa rr gg bb]
- return BinaryPrimitives.ReverseEndianness(packedArgb);
- }
+ public static void ToBgra32(ReadOnlySpan source, Span dest)
+ => SimdUtils.Shuffle4Channel(source, dest, SimdUtils.Shuffle.WZYX);
}
public static class FromBgra32
{
///
- /// Converts a packed to .
+ /// Converts a representing a collection of
+ /// pixels to a representing
+ /// a collection of pixels.
///
[MethodImpl(InliningOptions.ShortMethod)]
- public static uint ToArgb32(uint packedBgra)
- {
- // packedBgra = [aa rr gg bb]
- // REVERSE(packedBgra) = [bb gg rr aa]
- return BinaryPrimitives.ReverseEndianness(packedBgra);
- }
+ public static void ToArgb32(ReadOnlySpan source, Span dest)
+ => SimdUtils.Shuffle4Channel(source, dest, SimdUtils.Shuffle.WZYX);
///
- /// Converts a packed to .
+ /// Converts a representing a collection of
+ /// pixels to a representing
+ /// a collection of pixels.
///
[MethodImpl(InliningOptions.ShortMethod)]
- public static uint ToRgba32(uint packedBgra)
- {
- // packedRgba = [aa rr gg bb]
- // tmp1 = [aa 00 gg 00]
- // tmp2 = [00 rr 00 bb]
- // tmp3=ROTL(16, tmp2) = [00 bb 00 rr]
- // tmp1 + tmp3 = [aa bb gg rr]
- uint tmp1 = packedBgra & 0xFF00FF00;
- uint tmp2 = packedBgra & 0x00FF00FF;
- uint tmp3 = (tmp2 << 16) | (tmp2 >> 16);
- return tmp1 + tmp3;
- }
+ public static void ToRgba32(ReadOnlySpan source, Span dest)
+ => SimdUtils.Shuffle4Channel(source, dest, SimdUtils.Shuffle.ZYXW);
}
}
-}
\ No newline at end of file
+}
diff --git a/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertFromRgba32.cs b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertFromRgba32.cs
index 7d6c2efed..a933f890f 100644
--- a/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertFromRgba32.cs
+++ b/tests/ImageSharp.Benchmarks/General/PixelConversion/PixelConversion_ConvertFromRgba32.cs
@@ -168,49 +168,27 @@ namespace SixLabors.ImageSharp.Benchmarks.General.PixelConversion
[Benchmark]
public void PixelConverter_Rgba32_ToArgb32()
{
- ref uint sBase = ref Unsafe.As(ref this.PermutedRunnerRgbaToArgb.Source[0]);
- ref uint dBase = ref Unsafe.As(ref this.PermutedRunnerRgbaToArgb.Dest[0]);
+ Span source = MemoryMarshal.Cast(this.PermutedRunnerRgbaToArgb.Source);
+ Span dest = MemoryMarshal.Cast(this.PermutedRunnerRgbaToArgb.Dest);
- for (int i = 0; i < this.Count; i++)
- {
- uint s = Unsafe.Add(ref sBase, i);
- Unsafe.Add(ref dBase, i) = PixelConverter.FromRgba32.ToArgb32(s);
- }
- }
-
- [Benchmark]
- public void PixelConverter_Rgba32_ToArgb32_CopyThenWorkOnSingleBuffer()
- {
- Span source = MemoryMarshal.Cast(this.PermutedRunnerRgbaToArgb.Source);
- Span dest = MemoryMarshal.Cast(this.PermutedRunnerRgbaToArgb.Dest);
- source.CopyTo(dest);
-
- ref uint dBase = ref MemoryMarshal.GetReference(dest);
-
- for (int i = 0; i < this.Count; i++)
- {
- uint s = Unsafe.Add(ref dBase, i);
- Unsafe.Add(ref dBase, i) = PixelConverter.FromRgba32.ToArgb32(s);
- }
+ PixelConverter.FromRgba32.ToArgb32(source, dest);
}
/*
RESULTS:
- Method | Count | Mean | Error | StdDev | Scaled | ScaledSD |
- ---------------------------------------------------------- |------ |-----------:|-----------:|-----------:|-------:|---------:|
- ByRef | 256 | 328.7 ns | 6.6141 ns | 6.1868 ns | 1.00 | 0.00 |
- ByVal | 256 | 322.0 ns | 4.3541 ns | 4.0728 ns | 0.98 | 0.02 |
- FromBytes | 256 | 321.5 ns | 3.3499 ns | 3.1335 ns | 0.98 | 0.02 |
- InlineShuffle | 256 | 330.7 ns | 4.2525 ns | 3.9778 ns | 1.01 | 0.02 |
- PixelConverter_Rgba32_ToArgb32 | 256 | 167.4 ns | 0.6357 ns | 0.5309 ns | 0.51 | 0.01 |
- PixelConverter_Rgba32_ToArgb32_CopyThenWorkOnSingleBuffer | 256 | 196.6 ns | 0.8929 ns | 0.7915 ns | 0.60 | 0.01 |
- | | | | | | |
- ByRef | 2048 | 2,534.4 ns | 8.2947 ns | 6.9265 ns | 1.00 | 0.00 |
- ByVal | 2048 | 2,638.5 ns | 52.6843 ns | 70.3320 ns | 1.04 | 0.03 |
- FromBytes | 2048 | 2,517.2 ns | 40.8055 ns | 38.1695 ns | 0.99 | 0.01 |
- InlineShuffle | 2048 | 2,546.5 ns | 21.2506 ns | 19.8778 ns | 1.00 | 0.01 |
- PixelConverter_Rgba32_ToArgb32 | 2048 | 1,265.7 ns | 5.1397 ns | 4.5562 ns | 0.50 | 0.00 |
- PixelConverter_Rgba32_ToArgb32_CopyThenWorkOnSingleBuffer | 2048 | 1,410.3 ns | 11.1939 ns | 9.9231 ns | 0.56 | 0.00 |
- */
+ | Method | Count | Mean | Error | StdDev | Median | Ratio | RatioSD |
+ |------------------------------- |------ |------------:|----------:|----------:|------------:|------:|--------:|
+ | ByRef | 256 | 288.84 ns | 19.601 ns | 52.319 ns | 268.10 ns | 1.00 | 0.00 |
+ | ByVal | 256 | 267.97 ns | 1.831 ns | 1.713 ns | 267.85 ns | 0.77 | 0.18 |
+ | FromBytes | 256 | 266.81 ns | 2.427 ns | 2.270 ns | 266.47 ns | 0.76 | 0.18 |
+ | InlineShuffle | 256 | 291.41 ns | 5.820 ns | 5.444 ns | 290.17 ns | 0.83 | 0.19 |
+ | PixelConverter_Rgba32_ToArgb32 | 256 | 38.62 ns | 0.431 ns | 0.403 ns | 38.68 ns | 0.11 | 0.03 |
+ | | | | | | | | |
+ | ByRef | 2048 | 2,197.69 ns | 15.826 ns | 14.804 ns | 2,197.25 ns | 1.00 | 0.00 |
+ | ByVal | 2048 | 2,226.81 ns | 44.266 ns | 62.054 ns | 2,197.17 ns | 1.03 | 0.04 |
+ | FromBytes | 2048 | 2,181.35 ns | 18.033 ns | 16.868 ns | 2,185.97 ns | 0.99 | 0.01 |
+ | InlineShuffle | 2048 | 2,233.10 ns | 27.673 ns | 24.531 ns | 2,229.78 ns | 1.02 | 0.01 |
+ | PixelConverter_Rgba32_ToArgb32 | 2048 | 139.90 ns | 2.152 ns | 3.825 ns | 138.70 ns | 0.06 | 0.00 |
+ */
}
}
diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.ReferenceImplementations.cs b/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.ReferenceImplementations.cs
index 6fda9dbba..9d0d09a98 100644
--- a/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.ReferenceImplementations.cs
+++ b/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.ReferenceImplementations.cs
@@ -13,34 +13,49 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
{
public static class ReferenceImplementations
{
- public static Rgba32 MakeRgba32(byte r, byte g, byte b, byte a)
+ public static byte[] MakeRgba32ByteArray(byte r, byte g, byte b, byte a)
{
- Rgba32 d = default;
- d.R = r;
- d.G = g;
- d.B = b;
- d.A = a;
- return d;
+ var buffer = new byte[256];
+
+ for (int i = 0; i < buffer.Length; i += 4)
+ {
+ buffer[i] = r;
+ buffer[i + 1] = g;
+ buffer[i + 2] = b;
+ buffer[i + 3] = a;
+ }
+
+ return buffer;
}
- public static Argb32 MakeArgb32(byte r, byte g, byte b, byte a)
+ public static byte[] MakeArgb32ByteArray(byte r, byte g, byte b, byte a)
{
- Argb32 d = default;
- d.R = r;
- d.G = g;
- d.B = b;
- d.A = a;
- return d;
+ var buffer = new byte[256];
+
+ for (int i = 0; i < buffer.Length; i += 4)
+ {
+ buffer[i] = a;
+ buffer[i + 1] = r;
+ buffer[i + 2] = g;
+ buffer[i + 3] = b;
+ }
+
+ return buffer;
}
- public static Bgra32 MakeBgra32(byte r, byte g, byte b, byte a)
+ public static byte[] MakeBgra32ByteArray(byte r, byte g, byte b, byte a)
{
- Bgra32 d = default;
- d.R = r;
- d.G = g;
- d.B = b;
- d.A = a;
- return d;
+ var buffer = new byte[256];
+
+ for (int i = 0; i < buffer.Length; i += 4)
+ {
+ buffer[i] = b;
+ buffer[i + 1] = g;
+ buffer[i + 2] = r;
+ buffer[i + 3] = a;
+ }
+
+ return buffer;
}
internal static void To(
@@ -83,8 +98,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
if (typeof(TDestinationPixel) == typeof(L8))
{
- ref L8 l8Ref = ref MemoryMarshal.GetReference(
- MemoryMarshal.Cast(destinationPixels));
+ ref L8 l8Ref = ref MemoryMarshal.GetReference(MemoryMarshal.Cast(destinationPixels));
for (int i = 0; i < count; i++)
{
ref TSourcePixel sp = ref Unsafe.Add(ref sourceRef, i);
diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.cs
index 3de6804dc..6eed875f3 100644
--- a/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.cs
+++ b/tests/ImageSharp.Tests/PixelFormats/PixelConverterTests.cs
@@ -1,6 +1,7 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
+using System;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.PixelFormats.Utils;
@@ -33,30 +34,28 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
[MemberData(nameof(RgbaData))]
public void ToArgb32(byte r, byte g, byte b, byte a)
{
- Rgba32 s = ReferenceImplementations.MakeRgba32(r, g, b, a);
+ byte[] source = ReferenceImplementations.MakeRgba32ByteArray(r, g, b, a);
+ var actual = new byte[source.Length];
- // Act:
- uint actualPacked = PixelConverter.FromRgba32.ToArgb32(s.PackedValue);
+ PixelConverter.FromRgba32.ToArgb32(source, actual);
- // Assert:
- uint expectedPacked = ReferenceImplementations.MakeArgb32(r, g, b, a).PackedValue;
+ byte[] expected = ReferenceImplementations.MakeArgb32ByteArray(r, g, b, a);
- Assert.Equal(expectedPacked, actualPacked);
+ Assert.Equal(expected, actual);
}
[Theory]
[MemberData(nameof(RgbaData))]
public void ToBgra32(byte r, byte g, byte b, byte a)
{
- Rgba32 s = ReferenceImplementations.MakeRgba32(r, g, b, a);
+ byte[] source = ReferenceImplementations.MakeRgba32ByteArray(r, g, b, a);
+ var actual = new byte[source.Length];
- // Act:
- uint actualPacked = PixelConverter.FromRgba32.ToBgra32(s.PackedValue);
+ PixelConverter.FromRgba32.ToBgra32(source, actual);
- // Assert:
- uint expectedPacked = ReferenceImplementations.MakeBgra32(r, g, b, a).PackedValue;
+ byte[] expected = ReferenceImplementations.MakeBgra32ByteArray(r, g, b, a);
- Assert.Equal(expectedPacked, actualPacked);
+ Assert.Equal(expected, actual);
}
}
@@ -66,30 +65,28 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
[MemberData(nameof(RgbaData))]
public void ToRgba32(byte r, byte g, byte b, byte a)
{
- Argb32 s = ReferenceImplementations.MakeArgb32(r, g, b, a);
+ byte[] source = ReferenceImplementations.MakeArgb32ByteArray(r, g, b, a);
+ var actual = new byte[source.Length];
- // Act:
- uint actualPacked = PixelConverter.FromArgb32.ToRgba32(s.PackedValue);
+ PixelConverter.FromArgb32.ToRgba32(source, actual);
- // Assert:
- uint expectedPacked = ReferenceImplementations.MakeRgba32(r, g, b, a).PackedValue;
+ byte[] expected = ReferenceImplementations.MakeRgba32ByteArray(r, g, b, a);
- Assert.Equal(expectedPacked, actualPacked);
+ Assert.Equal(expected, actual);
}
[Theory]
[MemberData(nameof(RgbaData))]
public void ToBgra32(byte r, byte g, byte b, byte a)
{
- Argb32 s = ReferenceImplementations.MakeArgb32(r, g, b, a);
+ byte[] source = ReferenceImplementations.MakeArgb32ByteArray(r, g, b, a);
+ var actual = new byte[source.Length];
- // Act:
- uint actualPacked = PixelConverter.FromArgb32.ToBgra32(s.PackedValue);
+ PixelConverter.FromArgb32.ToBgra32(source, actual);
- // Assert:
- uint expectedPacked = ReferenceImplementations.MakeBgra32(r, g, b, a).PackedValue;
+ byte[] expected = ReferenceImplementations.MakeBgra32ByteArray(r, g, b, a);
- Assert.Equal(expectedPacked, actualPacked);
+ Assert.Equal(expected, actual);
}
}
@@ -99,30 +96,28 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
[MemberData(nameof(RgbaData))]
public void ToArgb32(byte r, byte g, byte b, byte a)
{
- Bgra32 s = ReferenceImplementations.MakeBgra32(r, g, b, a);
+ byte[] source = ReferenceImplementations.MakeBgra32ByteArray(r, g, b, a);
+ var actual = new byte[source.Length];
- // Act:
- uint actualPacked = PixelConverter.FromBgra32.ToArgb32(s.PackedValue);
+ PixelConverter.FromBgra32.ToArgb32(source, actual);
- // Assert:
- uint expectedPacked = ReferenceImplementations.MakeArgb32(r, g, b, a).PackedValue;
+ byte[] expected = ReferenceImplementations.MakeArgb32ByteArray(r, g, b, a);
- Assert.Equal(expectedPacked, actualPacked);
+ Assert.Equal(expected, actual);
}
[Theory]
[MemberData(nameof(RgbaData))]
public void ToRgba32(byte r, byte g, byte b, byte a)
{
- Bgra32 s = ReferenceImplementations.MakeBgra32(r, g, b, a);
+ byte[] source = ReferenceImplementations.MakeBgra32ByteArray(r, g, b, a);
+ var actual = new byte[source.Length];
- // Act:
- uint actualPacked = PixelConverter.FromBgra32.ToRgba32(s.PackedValue);
+ PixelConverter.FromBgra32.ToRgba32(source, actual);
- // Assert:
- uint expectedPacked = ReferenceImplementations.MakeRgba32(r, g, b, a).PackedValue;
+ byte[] expected = ReferenceImplementations.MakeRgba32ByteArray(r, g, b, a);
- Assert.Equal(expectedPacked, actualPacked);
+ Assert.Equal(expected, actual);
}
}
}