diff --git a/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs b/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs index 2a6fcb0832..4c3923c888 100644 --- a/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs +++ b/src/ImageSharp/ColorSpaces/Companding/SRgbCompanding.cs @@ -167,7 +167,7 @@ public static class SRgbCompanding [MethodImpl(MethodImplOptions.AggressiveInlining)] private static unsafe void CompandAvx2(Span vectors, float[] table) { - fixed (float* tablePointer = &table[0]) + fixed (float* tablePointer = &MemoryMarshal.GetArrayDataReference(table)) { var scale = Vector256.Create((float)Scale); Vector256 zero = Vector256.Zero; @@ -199,7 +199,7 @@ public static class SRgbCompanding [MethodImpl(MethodImplOptions.AggressiveInlining)] private static unsafe void CompandScalar(Span vectors, float[] table) { - fixed (float* tablePointer = &table[0]) + fixed (float* tablePointer = &MemoryMarshal.GetArrayDataReference(table)) { Vector4 zero = Vector4.Zero; var scale = new Vector4(Scale); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8.cs index d119a18c8b..01d112bd6f 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8.cs @@ -15,25 +15,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components; /// 8x8 matrix of coefficients. /// // ReSharper disable once InconsistentNaming -[StructLayout(LayoutKind.Explicit)] -internal unsafe partial struct Block8x8 +[StructLayout(LayoutKind.Explicit, Size = 2 * Size)] +internal partial struct Block8x8 { /// /// A number of scalar coefficients in a /// public const int Size = 64; -#pragma warning disable IDE0051 // Remove unused private member - /// - /// A placeholder buffer so the actual struct occupies exactly 64 * 2 bytes. - /// - /// - /// This is not used directly in the code. - /// - [FieldOffset(0)] - private fixed short data[Size]; -#pragma warning restore IDE0051 - /// /// Gets or sets a value at the given index /// @@ -74,9 +63,10 @@ internal unsafe partial struct Block8x8 public static Block8x8 Load(Span data) { - Unsafe.SkipInit(out Block8x8 result); - result.LoadFrom(data); - return result; + DebugGuard.MustBeGreaterThanOrEqualTo(data.Length, Size, "data is too small"); + + ref byte src = ref Unsafe.As(ref MemoryMarshal.GetReference(data)); + return Unsafe.ReadUnaligned(ref src); } /// @@ -104,9 +94,10 @@ internal unsafe partial struct Block8x8 /// public void CopyTo(Span destination) { - ref byte selfRef = ref Unsafe.As(ref this); - ref byte destRef = ref MemoryMarshal.GetReference(MemoryMarshal.Cast(destination)); - Unsafe.CopyBlockUnaligned(ref destRef, ref selfRef, Size * sizeof(short)); + DebugGuard.MustBeGreaterThanOrEqualTo(destination.Length, Size, "destination is too small"); + + ref byte destRef = ref Unsafe.As(ref MemoryMarshal.GetReference(destination)); + Unsafe.WriteUnaligned(ref destRef, this); } /// @@ -135,19 +126,6 @@ internal unsafe partial struct Block8x8 } } - /// - /// Load raw 16bit integers from source. - /// - /// Source - [MethodImpl(InliningOptions.ShortMethod)] - public void LoadFrom(Span source) - { - ref byte sourceRef = ref Unsafe.As(ref MemoryMarshal.GetReference(source)); - ref byte destRef = ref Unsafe.As(ref this); - - Unsafe.CopyBlockUnaligned(ref destRef, ref sourceRef, Size * sizeof(short)); - } - /// /// Cast and copy -s from the beginning of 'source' span. /// diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs index 21971a8c7d..d432e82d24 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs @@ -101,24 +101,17 @@ internal partial struct Block8x8F : IEquatable set => this[((uint)y * 8) + (uint)x] = value; } - public static Block8x8F Load(Span data) - { - Block8x8F result = default; - result.LoadFrom(data); - return result; - } - /// /// Load raw 32bit floating point data from source. /// - /// Source + /// Source [MethodImpl(InliningOptions.ShortMethod)] - public void LoadFrom(Span source) + public static Block8x8F Load(Span data) { - ref byte s = ref Unsafe.As(ref MemoryMarshal.GetReference(source)); - ref byte d = ref Unsafe.As(ref this); + DebugGuard.MustBeGreaterThanOrEqualTo(data.Length, Size, "data is too small"); - Unsafe.CopyBlock(ref d, ref s, Size * sizeof(float)); + ref byte src = ref Unsafe.As(ref MemoryMarshal.GetReference(data)); + return Unsafe.ReadUnaligned(ref src); } /// @@ -144,10 +137,10 @@ internal partial struct Block8x8F : IEquatable [MethodImpl(InliningOptions.ShortMethod)] public unsafe void ScaledCopyTo(float[] dest) { - fixed (void* ptr = &this.V0L) - { - Marshal.Copy((IntPtr)ptr, dest, 0, Size); - } + DebugGuard.MustBeGreaterThanOrEqualTo(dest.Length, Size, "dest is too small"); + + ref byte destRef = ref Unsafe.As(ref MemoryMarshal.GetArrayDataReference(dest)); + Unsafe.WriteUnaligned(ref destRef, this); } public float[] ToArray() diff --git a/src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs b/src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs index 8d64a09dfb..024adb7c23 100644 --- a/src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs +++ b/src/ImageSharp/Formats/Webp/Lossless/LosslessUtils.cs @@ -1474,8 +1474,7 @@ internal static unsafe class LosslessUtils { if (Sse2.IsSupported) { - Span output = scratch; - fixed (short* p = output) + fixed (short* ptr = &MemoryMarshal.GetReference(scratch)) { Vector128 a0 = Sse2.ConvertScalarToVector128UInt32(a).AsByte(); Vector128 b0 = Sse2.ConvertScalarToVector128UInt32(b).AsByte(); @@ -1489,8 +1488,8 @@ internal static unsafe class LosslessUtils Vector128 pa = Sse2.UnpackLow(ac, Vector128.Zero); // |a - c| Vector128 pb = Sse2.UnpackLow(bc, Vector128.Zero); // |b - c| Vector128 diff = Sse2.Subtract(pb.AsUInt16(), pa.AsUInt16()); - Sse2.Store((ushort*)p, diff); - int paMinusPb = output[3] + output[2] + output[1] + output[0]; + Sse2.Store((ushort*)ptr, diff); + int paMinusPb = ptr[3] + ptr[2] + ptr[1] + ptr[0]; return (paMinusPb <= 0) ? a : b; } } diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_MultiplyInPlaceBlock.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_MultiplyInPlaceBlock.cs index a5abeb3b66..722b095870 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_MultiplyInPlaceBlock.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_MultiplyInPlaceBlock.cs @@ -29,8 +29,6 @@ public class Block8x8F_MultiplyInPlaceBlock } } - var source = default(Block8x8F); - source.LoadFrom(result); - return source; + return Block8x8F.Load(result); } } diff --git a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs index 3e4bcae6b7..cde9e776b2 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs @@ -99,8 +99,7 @@ public partial class Block8x8FTests : JpegFixture Times, () => { - var b = default(Block8x8F); - b.LoadFrom(data); + Block8x8F b = Block8x8F.Load(data); b.ScaledCopyTo(mirror); }); @@ -117,8 +116,7 @@ public partial class Block8x8FTests : JpegFixture float[] expected = Create8x8FloatData(); ReferenceImplementations.Transpose8x8(expected); - var block8x8 = default(Block8x8F); - block8x8.LoadFrom(Create8x8FloatData()); + Block8x8F block8x8 = Block8x8F.Load(Create8x8FloatData()); block8x8.TransposeInplace(); @@ -153,9 +151,8 @@ public partial class Block8x8FTests : JpegFixture [Fact] public void NormalizeColors() { - var block = default(Block8x8F); float[] input = Create8x8ColorCropTestData(); - block.LoadFrom(input); + Block8x8F block = Block8x8F.Load(input); this.Output.WriteLine("Input:"); this.PrintLinearData(input); @@ -242,8 +239,7 @@ public partial class Block8x8FTests : JpegFixture { float[] data = Create8x8RandomFloatData(-1000, 1000); - var source = default(Block8x8F); - source.LoadFrom(data); + Block8x8F source = Block8x8F.Load(data); var dest = default(Block8x8); source.RoundInto(ref dest); diff --git a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8Tests.cs b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8Tests.cs index 798ea30407..b5d364dd38 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8Tests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8Tests.cs @@ -269,8 +269,7 @@ public class Block8x8Tests : JpegFixture short[] expected = Create8x8ShortData(); ReferenceImplementations.Transpose8x8(expected); - var block8x8 = default(Block8x8); - block8x8.LoadFrom(Create8x8ShortData()); + Block8x8 block8x8 = Block8x8.Load(Create8x8ShortData()); block8x8.TransposeInplace(); diff --git a/tests/ImageSharp.Tests/Formats/Jpg/DCTTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/DCTTests.cs index 5853ff37a5..5a1488c411 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/DCTTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/DCTTests.cs @@ -114,8 +114,7 @@ public static class DCTTests int seed = FeatureTestRunner.Deserialize(serialized); Span src = Create8x8RandomFloatData(MinInputValue, MaxInputValue, seed); - var srcBlock = default(Block8x8F); - srcBlock.LoadFrom(src); + Block8x8F srcBlock = Block8x8F.Load(src); float[] expectedDest = new float[64]; float[] temp = new float[64]; @@ -162,8 +161,7 @@ public static class DCTTests public void TranformIDCT_4x4(int seed) { Span src = Create8x8RandomFloatData(MinInputValue, MaxInputValue, seed, 4, 4); - var srcBlock = default(Block8x8F); - srcBlock.LoadFrom(src); + Block8x8F srcBlock = Block8x8F.Load(src); float[] expectedDest = new float[64]; float[] temp = new float[64]; @@ -224,8 +222,7 @@ public static class DCTTests public void TranformIDCT_2x2(int seed) { Span src = Create8x8RandomFloatData(MinInputValue, MaxInputValue, seed, 2, 2); - var srcBlock = default(Block8x8F); - srcBlock.LoadFrom(src); + Block8x8F srcBlock = Block8x8F.Load(src); float[] expectedDest = new float[64]; float[] temp = new float[64]; @@ -286,8 +283,7 @@ public static class DCTTests public void TranformIDCT_1x1(int seed) { Span src = Create8x8RandomFloatData(MinInputValue, MaxInputValue, seed, 1, 1); - var srcBlock = default(Block8x8F); - srcBlock.LoadFrom(src); + Block8x8F srcBlock = Block8x8F.Load(src); float[] expectedDest = new float[64]; float[] temp = new float[64]; @@ -330,8 +326,7 @@ public static class DCTTests int seed = FeatureTestRunner.Deserialize(serialized); Span src = Create8x8RandomFloatData(MinInputValue, MaxInputValue, seed); - var block = default(Block8x8F); - block.LoadFrom(src); + Block8x8F block = Block8x8F.Load(src); float[] expectedDest = new float[64]; float[] temp1 = new float[64]; diff --git a/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.AccurateDCT.cs b/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.AccurateDCT.cs index cd93adefd8..c593a029ab 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.AccurateDCT.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.AccurateDCT.cs @@ -25,8 +25,7 @@ public partial class ReferenceImplementationsTests { float[] data = Create8x8RandomFloatData(-1000, 1000, seed); - var b0 = default(Block8x8F); - b0.LoadFrom(data); + Block8x8F b0 = Block8x8F.Load(data); Block8x8F b1 = ReferenceImplementations.AccurateDCT.TransformFDCT(ref b0); Block8x8F b2 = ReferenceImplementations.AccurateDCT.TransformIDCT(ref b1); diff --git a/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.FastFloatingPointDCT.cs b/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.FastFloatingPointDCT.cs index 46c6ee2da6..f5d7c159ba 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.FastFloatingPointDCT.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.FastFloatingPointDCT.cs @@ -70,8 +70,7 @@ public partial class ReferenceImplementationsTests { float[] floatData = Create8x8RandomFloatData(-1000, 1000); - Block8x8F source = default; - source.LoadFrom(floatData); + Block8x8F source = Block8x8F.Load(floatData); Block8x8F expected = ReferenceImplementations.AccurateDCT.TransformFDCT(ref source); Block8x8F actual = ReferenceImplementations.LLM_FloatingPoint_DCT.TransformFDCT_UpscaleBy8(ref source); diff --git a/tests/ImageSharp.Tests/Formats/Jpg/Utils/ReferenceImplementations.LLM_FloatingPoint_DCT.cs b/tests/ImageSharp.Tests/Formats/Jpg/Utils/ReferenceImplementations.LLM_FloatingPoint_DCT.cs index 9e0c62d139..0d5f3114d1 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/Utils/ReferenceImplementations.LLM_FloatingPoint_DCT.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/Utils/ReferenceImplementations.LLM_FloatingPoint_DCT.cs @@ -36,8 +36,7 @@ internal static partial class ReferenceImplementations float[] temp = new float[64]; IDCT2D_llm(s, d, temp); - Block8x8F result = default; - result.LoadFrom(d); + Block8x8F result = Block8x8F.Load(d); return result; } @@ -49,8 +48,7 @@ internal static partial class ReferenceImplementations float[] temp = new float[64]; FDCT2D_llm(s, d, temp); - Block8x8F result = default; - result.LoadFrom(d); + Block8x8F result = Block8x8F.Load(d); return result; }