Browse Source

Refactor DefaultShuffleX to use constants.

pull/2365/head
James Jackson-South 3 years ago
parent
commit
b9e4810418
  1. 24
      src/ImageSharp/Common/Helpers/Shuffle/IComponentShuffle.cs
  2. 24
      src/ImageSharp/Common/Helpers/Shuffle/IPad3Shuffle4.cs
  3. 20
      src/ImageSharp/Common/Helpers/Shuffle/IShuffle3.cs
  4. 21
      src/ImageSharp/Common/Helpers/Shuffle/IShuffle4Slice3.cs
  5. 88
      src/ImageSharp/PixelFormats/Utils/PixelConverter.cs
  6. 26
      tests/ImageSharp.Tests/Common/SimdUtilsTests.Shuffle.cs

24
src/ImageSharp/Common/Helpers/Shuffle/IComponentShuffle.cs

@ -46,23 +46,10 @@ internal interface IShuffle4 : IComponentShuffle
internal readonly struct DefaultShuffle4 : IShuffle4
{
private readonly byte p3;
private readonly byte p2;
private readonly byte p1;
private readonly byte p0;
public DefaultShuffle4(byte p3, byte p2, byte p1, byte p0)
public DefaultShuffle4(byte control)
{
DebugGuard.MustBeBetweenOrEqualTo<byte>(p3, 0, 3, nameof(p3));
DebugGuard.MustBeBetweenOrEqualTo<byte>(p2, 0, 3, nameof(p2));
DebugGuard.MustBeBetweenOrEqualTo<byte>(p1, 0, 3, nameof(p1));
DebugGuard.MustBeBetweenOrEqualTo<byte>(p0, 0, 3, nameof(p0));
this.p3 = p3;
this.p2 = p2;
this.p1 = p1;
this.p0 = p0;
this.Control = Shuffle.MmShuffle(p3, p2, p1, p0);
DebugGuard.MustBeBetweenOrEqualTo<byte>(control, 0, 3, nameof(control));
this.Control = control;
}
public byte Control { get; }
@ -77,10 +64,7 @@ internal readonly struct DefaultShuffle4 : IShuffle4
ref byte sBase = ref MemoryMarshal.GetReference(source);
ref byte dBase = ref MemoryMarshal.GetReference(dest);
int p3 = this.p3;
int p2 = this.p2;
int p1 = this.p1;
int p0 = this.p0;
Shuffle.InverseMmShuffle(this.Control, out int p3, out int p2, out int p1, out int p0);
for (int i = 0; i < source.Length; i += 4)
{

24
src/ImageSharp/Common/Helpers/Shuffle/IPad3Shuffle4.cs

@ -14,23 +14,10 @@ internal interface IPad3Shuffle4 : IComponentShuffle
internal readonly struct DefaultPad3Shuffle4 : IPad3Shuffle4
{
private readonly byte p3;
private readonly byte p2;
private readonly byte p1;
private readonly byte p0;
public DefaultPad3Shuffle4(byte p3, byte p2, byte p1, byte p0)
public DefaultPad3Shuffle4(byte control)
{
DebugGuard.MustBeBetweenOrEqualTo<byte>(p3, 0, 3, nameof(p3));
DebugGuard.MustBeBetweenOrEqualTo<byte>(p2, 0, 3, nameof(p2));
DebugGuard.MustBeBetweenOrEqualTo<byte>(p1, 0, 3, nameof(p1));
DebugGuard.MustBeBetweenOrEqualTo<byte>(p0, 0, 3, nameof(p0));
this.p3 = p3;
this.p2 = p2;
this.p1 = p1;
this.p0 = p0;
this.Control = Shuffle.MmShuffle(p3, p2, p1, p0);
DebugGuard.MustBeBetweenOrEqualTo<byte>(control, 0, 3, nameof(control));
this.Control = control;
}
public byte Control { get; }
@ -45,10 +32,7 @@ internal readonly struct DefaultPad3Shuffle4 : IPad3Shuffle4
ref byte sBase = ref MemoryMarshal.GetReference(source);
ref byte dBase = ref MemoryMarshal.GetReference(dest);
int p3 = this.p3;
int p2 = this.p2;
int p1 = this.p1;
int p0 = this.p0;
Shuffle.InverseMmShuffle(this.Control, out int p3, out int p2, out int p1, out int p0);
Span<byte> temp = stackalloc byte[4];
ref byte t = ref MemoryMarshal.GetReference(temp);

20
src/ImageSharp/Common/Helpers/Shuffle/IShuffle3.cs

@ -14,20 +14,10 @@ internal interface IShuffle3 : IComponentShuffle
internal readonly struct DefaultShuffle3 : IShuffle3
{
private readonly byte p2;
private readonly byte p1;
private readonly byte p0;
public DefaultShuffle3(byte p2, byte p1, byte p0)
public DefaultShuffle3(byte control)
{
DebugGuard.MustBeBetweenOrEqualTo<byte>(p2, 0, 2, nameof(p2));
DebugGuard.MustBeBetweenOrEqualTo<byte>(p1, 0, 2, nameof(p1));
DebugGuard.MustBeBetweenOrEqualTo<byte>(p0, 0, 2, nameof(p0));
this.p2 = p2;
this.p1 = p1;
this.p0 = p0;
this.Control = Shuffle.MmShuffle(3, p2, p1, p0);
DebugGuard.MustBeBetweenOrEqualTo<byte>(control, 0, 3, nameof(control));
this.Control = control;
}
public byte Control { get; }
@ -42,9 +32,7 @@ internal readonly struct DefaultShuffle3 : IShuffle3
ref byte sBase = ref MemoryMarshal.GetReference(source);
ref byte dBase = ref MemoryMarshal.GetReference(dest);
int p2 = this.p2;
int p1 = this.p1;
int p0 = this.p0;
Shuffle.InverseMmShuffle(this.Control, out _, out int p2, out int p1, out int p0);
for (int i = 0; i < source.Length; i += 3)
{

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

@ -14,21 +14,10 @@ internal interface IShuffle4Slice3 : IComponentShuffle
internal readonly struct DefaultShuffle4Slice3 : IShuffle4Slice3
{
private readonly byte p2;
private readonly byte p1;
private readonly byte p0;
public DefaultShuffle4Slice3(byte p3, byte p2, byte p1, byte p0)
public DefaultShuffle4Slice3(byte control)
{
DebugGuard.MustBeBetweenOrEqualTo<byte>(p3, 0, 3, nameof(p3));
DebugGuard.MustBeBetweenOrEqualTo<byte>(p2, 0, 3, nameof(p2));
DebugGuard.MustBeBetweenOrEqualTo<byte>(p1, 0, 3, nameof(p1));
DebugGuard.MustBeBetweenOrEqualTo<byte>(p0, 0, 3, nameof(p0));
this.p2 = p2;
this.p1 = p1;
this.p0 = p0;
this.Control = Shuffle.MmShuffle(p3, p2, p1, p0);
DebugGuard.MustBeBetweenOrEqualTo<byte>(control, 0, 3, nameof(control));
this.Control = control;
}
public byte Control { get; }
@ -43,9 +32,7 @@ internal readonly struct DefaultShuffle4Slice3 : IShuffle4Slice3
ref byte sBase = ref MemoryMarshal.GetReference(source);
ref byte dBase = ref MemoryMarshal.GetReference(dest);
int p2 = this.p2;
int p1 = this.p1;
int p0 = this.p0;
Shuffle.InverseMmShuffle(this.Control, out _, out int p2, out int p1, out int p0);
for (int i = 0, j = 0; i < dest.Length; i += 3, j += 4)
{

88
src/ImageSharp/PixelFormats/Utils/PixelConverter.cs

@ -29,6 +29,8 @@ internal static class PixelConverter
/// <see cref="Rgba32"/> pixels to a <see cref="Span{Byte}"/> representing
/// a collection of <see cref="Argb32"/> pixels.
/// </summary>
/// <param name="source">The source span of bytes.</param>
/// <param name="dest">The destination span of bytes.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void ToArgb32(ReadOnlySpan<byte> source, Span<byte> dest)
=> SimdUtils.Shuffle4<WXYZShuffle4>(source, dest, default);
@ -38,6 +40,8 @@ internal static class PixelConverter
/// <see cref="Rgba32"/> pixels to a <see cref="Span{Byte}"/> representing
/// a collection of <see cref="Bgra32"/> pixels.
/// </summary>
/// <param name="source">The source span of bytes.</param>
/// <param name="dest">The destination span of bytes.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void ToBgra32(ReadOnlySpan<byte> source, Span<byte> dest)
=> SimdUtils.Shuffle4<ZYXWShuffle4>(source, dest, default);
@ -47,6 +51,8 @@ internal static class PixelConverter
/// <see cref="Argb32"/> pixels to a <see cref="Span{Byte}"/> representing
/// a collection of <see cref="Abgr32"/> pixels.
/// </summary>
/// <param name="source">The source span of bytes.</param>
/// <param name="dest">The destination span of bytes.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void ToAbgr32(ReadOnlySpan<byte> source, Span<byte> dest)
=> SimdUtils.Shuffle4<WZYXShuffle4>(source, dest, default);
@ -56,6 +62,8 @@ internal static class PixelConverter
/// <see cref="Rgba32"/> pixels to a <see cref="Span{Byte}"/> representing
/// a collection of <see cref="Rgb24"/> pixels.
/// </summary>
/// <param name="source">The source span of bytes.</param>
/// <param name="dest">The destination span of bytes.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void ToRgb24(ReadOnlySpan<byte> source, Span<byte> dest)
=> SimdUtils.Shuffle4Slice3<XYZWShuffle4Slice3>(source, dest, default);
@ -65,9 +73,11 @@ internal static class PixelConverter
/// <see cref="Rgba32"/> pixels to a <see cref="Span{Byte}"/> representing
/// a collection of <see cref="Bgr24"/> pixels.
/// </summary>
/// <param name="source">The source span of bytes.</param>
/// <param name="dest">The destination span of bytes.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void ToBgr24(ReadOnlySpan<byte> source, Span<byte> dest)
=> SimdUtils.Shuffle4Slice3(source, dest, new DefaultShuffle4Slice3(3, 0, 1, 2));
=> SimdUtils.Shuffle4Slice3(source, dest, new DefaultShuffle4Slice3(SimdUtils.Shuffle.MMShuffle3012));
}
/// <summary>
@ -82,6 +92,8 @@ internal static class PixelConverter
/// <see cref="Argb32"/> pixels to a <see cref="Span{Byte}"/> representing
/// a collection of <see cref="Rgba32"/> pixels.
/// </summary>
/// <param name="source">The source span of bytes.</param>
/// <param name="dest">The destination span of bytes.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void ToRgba32(ReadOnlySpan<byte> source, Span<byte> dest)
=> SimdUtils.Shuffle4<YZWXShuffle4>(source, dest, default);
@ -91,6 +103,8 @@ internal static class PixelConverter
/// <see cref="Argb32"/> pixels to a <see cref="Span{Byte}"/> representing
/// a collection of <see cref="Bgra32"/> pixels.
/// </summary>
/// <param name="source">The source span of bytes.</param>
/// <param name="dest">The destination span of bytes.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void ToBgra32(ReadOnlySpan<byte> source, Span<byte> dest)
=> SimdUtils.Shuffle4<WZYXShuffle4>(source, dest, default);
@ -100,6 +114,8 @@ internal static class PixelConverter
/// <see cref="Argb32"/> pixels to a <see cref="Span{Byte}"/> representing
/// a collection of <see cref="Abgr32"/> pixels.
/// </summary>
/// <param name="source">The source span of bytes.</param>
/// <param name="dest">The destination span of bytes.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void ToAbgr32(ReadOnlySpan<byte> source, Span<byte> dest)
=> SimdUtils.Shuffle4<XWZYShuffle4>(source, dest, default);
@ -109,18 +125,22 @@ internal static class PixelConverter
/// <see cref="Argb32"/> pixels to a <see cref="Span{Byte}"/> representing
/// a collection of <see cref="Rgb24"/> pixels.
/// </summary>
/// <param name="source">The source span of bytes.</param>
/// <param name="dest">The destination span of bytes.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void ToRgb24(ReadOnlySpan<byte> source, Span<byte> dest)
=> SimdUtils.Shuffle4Slice3(source, dest, new DefaultShuffle4Slice3(0, 3, 2, 1));
=> SimdUtils.Shuffle4Slice3(source, dest, new DefaultShuffle4Slice3(SimdUtils.Shuffle.MMShuffle0321));
/// <summary>
/// Converts a <see cref="ReadOnlySpan{Byte}"/> representing a collection of
/// <see cref="Argb32"/> pixels to a <see cref="Span{Byte}"/> representing
/// a collection of <see cref="Bgr24"/> pixels.
/// </summary>
/// <param name="source">The source span of bytes.</param>
/// <param name="dest">The destination span of bytes.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void ToBgr24(ReadOnlySpan<byte> source, Span<byte> dest)
=> SimdUtils.Shuffle4Slice3(source, dest, new DefaultShuffle4Slice3(0, 1, 2, 3));
=> SimdUtils.Shuffle4Slice3(source, dest, new DefaultShuffle4Slice3(SimdUtils.Shuffle.MMShuffle0123));
}
/// <summary>
@ -135,6 +155,8 @@ internal static class PixelConverter
/// <see cref="Bgra32"/> pixels to a <see cref="Span{Byte}"/> representing
/// a collection of <see cref="Argb32"/> pixels.
/// </summary>
/// <param name="source">The source span of bytes.</param>
/// <param name="dest">The destination span of bytes.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void ToArgb32(ReadOnlySpan<byte> source, Span<byte> dest)
=> SimdUtils.Shuffle4<WZYXShuffle4>(source, dest, default);
@ -144,6 +166,8 @@ internal static class PixelConverter
/// <see cref="Bgra32"/> pixels to a <see cref="Span{Byte}"/> representing
/// a collection of <see cref="Rgba32"/> pixels.
/// </summary>
/// <param name="source">The source span of bytes.</param>
/// <param name="dest">The destination span of bytes.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void ToRgba32(ReadOnlySpan<byte> source, Span<byte> dest)
=> SimdUtils.Shuffle4<ZYXWShuffle4>(source, dest, default);
@ -153,6 +177,8 @@ internal static class PixelConverter
/// <see cref="Bgra32"/> pixels to a <see cref="Span{Byte}"/> representing
/// a collection of <see cref="Abgr32"/> pixels.
/// </summary>
/// <param name="source">The source span of bytes.</param>
/// <param name="dest">The destination span of bytes.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void ToAbgr32(ReadOnlySpan<byte> source, Span<byte> dest)
=> SimdUtils.Shuffle4<WXYZShuffle4>(source, dest, default);
@ -162,15 +188,19 @@ internal static class PixelConverter
/// <see cref="Argb32"/> pixels to a <see cref="Span{Byte}"/> representing
/// a collection of <see cref="Rgb24"/> pixels.
/// </summary>
/// <param name="source">The source span of bytes.</param>
/// <param name="dest">The destination span of bytes.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void ToRgb24(ReadOnlySpan<byte> source, Span<byte> dest)
=> SimdUtils.Shuffle4Slice3(source, dest, new DefaultShuffle4Slice3(3, 0, 1, 2));
=> SimdUtils.Shuffle4Slice3(source, dest, new DefaultShuffle4Slice3(SimdUtils.Shuffle.MMShuffle3012));
/// <summary>
/// Converts a <see cref="ReadOnlySpan{Byte}"/> representing a collection of
/// <see cref="Argb32"/> pixels to a <see cref="Span{Byte}"/> representing
/// a collection of <see cref="Bgr24"/> pixels.
/// </summary>
/// <param name="source">The source span of bytes.</param>
/// <param name="dest">The destination span of bytes.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void ToBgr24(ReadOnlySpan<byte> source, Span<byte> dest)
=> SimdUtils.Shuffle4Slice3<XYZWShuffle4Slice3>(source, dest, default);
@ -188,6 +218,8 @@ internal static class PixelConverter
/// <see cref="Abgr32"/> pixels to a <see cref="Span{Byte}"/> representing
/// a collection of <see cref="Argb32"/> pixels.
/// </summary>
/// <param name="source">The source span of bytes.</param>
/// <param name="dest">The destination span of bytes.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void ToArgb32(ReadOnlySpan<byte> source, Span<byte> dest)
=> SimdUtils.Shuffle4<XWZYShuffle4>(source, dest, default);
@ -197,6 +229,8 @@ internal static class PixelConverter
/// <see cref="Abgr32"/> pixels to a <see cref="Span{Byte}"/> representing
/// a collection of <see cref="Bgra32"/> pixels.
/// </summary>
/// <param name="source">The source span of bytes.</param>
/// <param name="dest">The destination span of bytes.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void ToRgba32(ReadOnlySpan<byte> source, Span<byte> dest)
=> SimdUtils.Shuffle4<WZYXShuffle4>(source, dest, default);
@ -206,6 +240,8 @@ internal static class PixelConverter
/// <see cref="Abgr32"/> pixels to a <see cref="Span{Byte}"/> representing
/// a collection of <see cref="Bgra32"/> pixels.
/// </summary>
/// <param name="source">The source span of bytes.</param>
/// <param name="dest">The destination span of bytes.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void ToBgra32(ReadOnlySpan<byte> source, Span<byte> dest)
=> SimdUtils.Shuffle4<YZWXShuffle4>(source, dest, default);
@ -215,18 +251,22 @@ internal static class PixelConverter
/// <see cref="Abgr32"/> pixels to a <see cref="Span{Byte}"/> representing
/// a collection of <see cref="Rgb24"/> pixels.
/// </summary>
/// <param name="source">The source span of bytes.</param>
/// <param name="dest">The destination span of bytes.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void ToRgb24(ReadOnlySpan<byte> source, Span<byte> dest)
=> SimdUtils.Shuffle4Slice3(source, dest, new DefaultShuffle4Slice3(0, 1, 2, 3));
=> SimdUtils.Shuffle4Slice3(source, dest, new DefaultShuffle4Slice3(SimdUtils.Shuffle.MMShuffle0123));
/// <summary>
/// Converts a <see cref="ReadOnlySpan{Byte}"/> representing a collection of
/// <see cref="Abgr32"/> pixels to a <see cref="Span{Byte}"/> representing
/// a collection of <see cref="Bgr24"/> pixels.
/// </summary>
/// <param name="source">The source span of bytes.</param>
/// <param name="dest">The destination span of bytes.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void ToBgr24(ReadOnlySpan<byte> source, Span<byte> dest)
=> SimdUtils.Shuffle4Slice3(source, dest, new DefaultShuffle4Slice3(0, 3, 2, 1));
=> SimdUtils.Shuffle4Slice3(source, dest, new DefaultShuffle4Slice3(SimdUtils.Shuffle.MMShuffle0321));
}
/// <summary>
@ -241,6 +281,8 @@ internal static class PixelConverter
/// <see cref="Rgb24"/> pixels to a <see cref="Span{Byte}"/> representing
/// a collection of <see cref="Rgba32"/> pixels.
/// </summary>
/// <param name="source">The source span of bytes.</param>
/// <param name="dest">The destination span of bytes.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void ToRgba32(ReadOnlySpan<byte> source, Span<byte> dest)
=> SimdUtils.Pad3Shuffle4<XYZWPad3Shuffle4>(source, dest, default);
@ -250,36 +292,44 @@ internal static class PixelConverter
/// <see cref="Rgba32"/> pixels to a <see cref="Span{Byte}"/> representing
/// a collection of <see cref="Argb32"/> pixels.
/// </summary>
/// <param name="source">The source span of bytes.</param>
/// <param name="dest">The destination span of bytes.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void ToArgb32(ReadOnlySpan<byte> source, Span<byte> dest)
=> SimdUtils.Pad3Shuffle4(source, dest, new DefaultPad3Shuffle4(2, 1, 0, 3));
=> SimdUtils.Pad3Shuffle4(source, dest, new DefaultPad3Shuffle4(SimdUtils.Shuffle.MMShuffle2103));
/// <summary>
/// Converts a <see cref="ReadOnlySpan{Byte}"/> representing a collection of
/// <see cref="Rgba32"/> pixels to a <see cref="Span{Byte}"/> representing
/// a collection of <see cref="Bgra32"/> pixels.
/// </summary>
/// <param name="source">The source span of bytes.</param>
/// <param name="dest">The destination span of bytes.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void ToBgra32(ReadOnlySpan<byte> source, Span<byte> dest)
=> SimdUtils.Pad3Shuffle4(source, dest, new DefaultPad3Shuffle4(3, 0, 1, 2));
=> SimdUtils.Pad3Shuffle4(source, dest, new DefaultPad3Shuffle4(SimdUtils.Shuffle.MMShuffle3012));
/// <summary>
/// Converts a <see cref="ReadOnlySpan{Byte}"/> representing a collection of
/// <see cref="Rgba32"/> pixels to a <see cref="Span{Byte}"/> representing
/// a collection of <see cref="Bgra32"/> pixels.
/// </summary>
/// <param name="source">The source span of bytes.</param>
/// <param name="dest">The destination span of bytes.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void ToAbgr32(ReadOnlySpan<byte> source, Span<byte> dest)
=> SimdUtils.Pad3Shuffle4(source, dest, new DefaultPad3Shuffle4(0, 1, 2, 3));
=> SimdUtils.Pad3Shuffle4(source, dest, new DefaultPad3Shuffle4(SimdUtils.Shuffle.MMShuffle0123));
/// <summary>
/// Converts a <see cref="ReadOnlySpan{Byte}"/> representing a collection of
/// <see cref="Rgb24"/> pixels to a <see cref="Span{Byte}"/> representing
/// a collection of <see cref="Bgr24"/> pixels.
/// </summary>
/// <param name="source">The source span of bytes.</param>
/// <param name="dest">The destination span of bytes.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void ToBgr24(ReadOnlySpan<byte> source, Span<byte> dest)
=> SimdUtils.Shuffle3(source, dest, new DefaultShuffle3(0, 1, 2));
=> SimdUtils.Shuffle3(source, dest, new DefaultShuffle3(SimdUtils.Shuffle.MMShuffle3012));
}
/// <summary>
@ -294,24 +344,30 @@ internal static class PixelConverter
/// <see cref="Bgr24"/> pixels to a <see cref="Span{Byte}"/> representing
/// a collection of <see cref="Argb32"/> pixels.
/// </summary>
/// <param name="source">The source span of bytes.</param>
/// <param name="dest">The destination span of bytes.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void ToArgb32(ReadOnlySpan<byte> source, Span<byte> dest)
=> SimdUtils.Pad3Shuffle4(source, dest, new DefaultPad3Shuffle4(0, 1, 2, 3));
=> SimdUtils.Pad3Shuffle4(source, dest, new DefaultPad3Shuffle4(SimdUtils.Shuffle.MMShuffle0123));
/// <summary>
/// Converts a <see cref="ReadOnlySpan{Byte}"/> representing a collection of
/// <see cref="Bgr24"/> pixels to a <see cref="Span{Byte}"/> representing
/// a collection of <see cref="Bgra32"/> pixels.
/// </summary>
/// <param name="source">The source span of bytes.</param>
/// <param name="dest">The destination span of bytes.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void ToRgba32(ReadOnlySpan<byte> source, Span<byte> dest)
=> SimdUtils.Pad3Shuffle4(source, dest, new DefaultPad3Shuffle4(3, 0, 1, 2));
=> SimdUtils.Pad3Shuffle4(source, dest, new DefaultPad3Shuffle4(SimdUtils.Shuffle.MMShuffle3012));
/// <summary>
/// Converts a <see cref="ReadOnlySpan{Byte}"/> representing a collection of
/// <see cref="Bgr24"/> pixels to a <see cref="Span{Byte}"/> representing
/// a collection of <see cref="Bgra32"/> pixels.
/// </summary>
/// <param name="source">The source span of bytes.</param>
/// <param name="dest">The destination span of bytes.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void ToBgra32(ReadOnlySpan<byte> source, Span<byte> dest)
=> SimdUtils.Pad3Shuffle4<XYZWPad3Shuffle4>(source, dest, default);
@ -321,17 +377,21 @@ internal static class PixelConverter
/// <see cref="Bgr24"/> pixels to a <see cref="Span{Byte}"/> representing
/// a collection of <see cref="Abgr32"/> pixels.
/// </summary>
/// <param name="source">The source span of bytes.</param>
/// <param name="dest">The destination span of bytes.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void ToAbgr32(ReadOnlySpan<byte> source, Span<byte> dest)
=> SimdUtils.Pad3Shuffle4(source, dest, new DefaultPad3Shuffle4(2, 1, 0, 3));
=> SimdUtils.Pad3Shuffle4(source, dest, new DefaultPad3Shuffle4(SimdUtils.Shuffle.MMShuffle2103));
/// <summary>
/// Converts a <see cref="ReadOnlySpan{Byte}"/> representing a collection of
/// <see cref="Bgr24"/> pixels to a <see cref="Span{Byte}"/> representing
/// a collection of <see cref="Rgb24"/> pixels.
/// </summary>
/// <param name="source">The source span of bytes.</param>
/// <param name="dest">The destination span of bytes.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public static void ToRgb24(ReadOnlySpan<byte> source, Span<byte> dest)
=> SimdUtils.Shuffle3(source, dest, new DefaultShuffle3(0, 1, 2));
=> SimdUtils.Shuffle3(source, dest, new DefaultShuffle3(SimdUtils.Shuffle.MMShuffle3012));
}
}

26
tests/ImageSharp.Tests/Common/SimdUtilsTests.Shuffle.cs

@ -65,19 +65,19 @@ public partial class SimdUtilsTests
(s, d) => SimdUtils.Shuffle4(s.Span, d.Span, zyxw),
SimdUtils.Shuffle.MMShuffle3012);
DefaultShuffle4 xwyz = new(2, 1, 3, 0);
DefaultShuffle4 xwyz = new(SimdUtils.Shuffle.MMShuffle2130);
TestShuffleByte4Channel(
size,
(s, d) => SimdUtils.Shuffle4(s.Span, d.Span, xwyz),
xwyz.Control);
DefaultShuffle4 yyyy = new(1, 1, 1, 1);
DefaultShuffle4 yyyy = new(SimdUtils.Shuffle.MMShuffle1111);
TestShuffleByte4Channel(
size,
(s, d) => SimdUtils.Shuffle4(s.Span, d.Span, yyyy),
yyyy.Control);
DefaultShuffle4 wwww = new(3, 3, 3, 3);
DefaultShuffle4 wwww = new(SimdUtils.Shuffle.MMShuffle3333);
TestShuffleByte4Channel(
size,
(s, d) => SimdUtils.Shuffle4(s.Span, d.Span, wwww),
@ -101,25 +101,25 @@ public partial class SimdUtilsTests
// These cannot be expressed as a theory as you cannot
// use RemoteExecutor within generic methods nor pass
// IShuffle3 to the generic utils method.
DefaultShuffle3 zyx = new(0, 1, 2);
DefaultShuffle3 zyx = new(SimdUtils.Shuffle.MMShuffle3012);
TestShuffleByte3Channel(
size,
(s, d) => SimdUtils.Shuffle3(s.Span, d.Span, zyx),
zyx.Control);
DefaultShuffle3 xyz = new(2, 1, 0);
DefaultShuffle3 xyz = new(SimdUtils.Shuffle.MMShuffle3210);
TestShuffleByte3Channel(
size,
(s, d) => SimdUtils.Shuffle3(s.Span, d.Span, xyz),
xyz.Control);
DefaultShuffle3 yyy = new(1, 1, 1);
DefaultShuffle3 yyy = new(SimdUtils.Shuffle.MMShuffle3111);
TestShuffleByte3Channel(
size,
(s, d) => SimdUtils.Shuffle3(s.Span, d.Span, yyy),
yyy.Control);
DefaultShuffle3 zzz = new(2, 2, 2);
DefaultShuffle3 zzz = new(SimdUtils.Shuffle.MMShuffle3222);
TestShuffleByte3Channel(
size,
(s, d) => SimdUtils.Shuffle3(s.Span, d.Span, zzz),
@ -149,19 +149,19 @@ public partial class SimdUtilsTests
(s, d) => SimdUtils.Pad3Shuffle4(s.Span, d.Span, xyzw),
SimdUtils.Shuffle.MMShuffle3210);
DefaultPad3Shuffle4 xwyz = new(2, 1, 3, 0);
DefaultPad3Shuffle4 xwyz = new(SimdUtils.Shuffle.MMShuffle2130);
TestPad3Shuffle4Channel(
size,
(s, d) => SimdUtils.Pad3Shuffle4(s.Span, d.Span, xwyz),
xwyz.Control);
DefaultPad3Shuffle4 yyyy = new(1, 1, 1, 1);
DefaultPad3Shuffle4 yyyy = new(SimdUtils.Shuffle.MMShuffle1111);
TestPad3Shuffle4Channel(
size,
(s, d) => SimdUtils.Pad3Shuffle4(s.Span, d.Span, yyyy),
yyyy.Control);
DefaultPad3Shuffle4 wwww = new(3, 3, 3, 3);
DefaultPad3Shuffle4 wwww = new(SimdUtils.Shuffle.MMShuffle3333);
TestPad3Shuffle4Channel(
size,
(s, d) => SimdUtils.Pad3Shuffle4(s.Span, d.Span, wwww),
@ -191,19 +191,19 @@ public partial class SimdUtilsTests
(s, d) => SimdUtils.Shuffle4Slice3(s.Span, d.Span, xyzw),
SimdUtils.Shuffle.MMShuffle3210);
DefaultShuffle4Slice3 xwyz = new(2, 1, 3, 0);
DefaultShuffle4Slice3 xwyz = new(SimdUtils.Shuffle.MMShuffle2130);
TestShuffle4Slice3Channel(
size,
(s, d) => SimdUtils.Shuffle4Slice3(s.Span, d.Span, xwyz),
xwyz.Control);
DefaultShuffle4Slice3 yyyy = new(1, 1, 1, 1);
DefaultShuffle4Slice3 yyyy = new(SimdUtils.Shuffle.MMShuffle1111);
TestShuffle4Slice3Channel(
size,
(s, d) => SimdUtils.Shuffle4Slice3(s.Span, d.Span, yyyy),
yyyy.Control);
DefaultShuffle4Slice3 wwww = new(3, 3, 3, 3);
DefaultShuffle4Slice3 wwww = new(SimdUtils.Shuffle.MMShuffle3333);
TestShuffle4Slice3Channel(
size,
(s, d) => SimdUtils.Shuffle4Slice3(s.Span, d.Span, wwww),

Loading…
Cancel
Save