diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs index 6a336ad2b4..0efefc06b5 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs @@ -13,7 +13,7 @@ internal partial struct Block8x8F /// /// Level shift by +maximum/2, clip to [0, maximum] /// - public void NormalizeColorsInplace(float maximum) + public void NormalizeColorsInPlace(float maximum) { var CMin4 = new Vector4(0F); var CMax4 = new Vector4(maximum); @@ -38,10 +38,10 @@ public void NormalizeColorsInplace(float maximum) } /// - /// AVX2-only variant for executing and in one step. + /// AVX2-only variant for executing and in one step. /// [MethodImpl(InliningOptions.ShortMethod)] - public void NormalizeColorsAndRoundInplaceVector8(float maximum) + public void NormalizeColorsAndRoundInPlaceVector8(float maximum) { var off = new Vector(MathF.Ceiling(maximum / 2)); var max = new Vector(maximum); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt index 26cd5c2ac4..e5a62dc075 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt @@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components /// /// Level shift by +maximum/2, clip to [0, maximum] /// - public void NormalizeColorsInplace(float maximum) + public void NormalizeColorsInPlace(float maximum) { var CMin4 = new Vector4(0F); var CMax4 = new Vector4(maximum); @@ -49,10 +49,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components } /// - /// AVX2-only variant for executing and in one step. + /// AVX2-only variant for executing and in one step. /// [MethodImpl(InliningOptions.ShortMethod)] - public void NormalizeColorsAndRoundInplaceVector8(float maximum) + public void NormalizeColorsAndRoundInPlaceVector8(float maximum) { var off = new Vector(MathF.Ceiling(maximum / 2)); var max = new Vector(maximum); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs index ccdba48857..0dbdadbeb4 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs @@ -281,73 +281,156 @@ public float[] ToArray() /// /// The value to multiply by. [MethodImpl(InliningOptions.ShortMethod)] - public void MultiplyInplace(float value) - { - this.V0L *= value; - this.V0R *= value; - this.V1L *= value; - this.V1R *= value; - this.V2L *= value; - this.V2R *= value; - this.V3L *= value; - this.V3R *= value; - this.V4L *= value; - this.V4R *= value; - this.V5L *= value; - this.V5R *= value; - this.V6L *= value; - this.V6R *= value; - this.V7L *= value; - this.V7R *= value; + public void MultiplyInPlace(float value) + { +#if SUPPORTS_RUNTIME_INTRINSICS + if (Avx.IsSupported) + { + var valueVec = Vector256.Create(value); + Unsafe.As>(ref this.V0L) = Avx.Multiply(Unsafe.As>(ref this.V0L), valueVec); + Unsafe.As>(ref this.V1L) = Avx.Multiply(Unsafe.As>(ref this.V1L), valueVec); + Unsafe.As>(ref this.V2L) = Avx.Multiply(Unsafe.As>(ref this.V2L), valueVec); + Unsafe.As>(ref this.V3L) = Avx.Multiply(Unsafe.As>(ref this.V3L), valueVec); + Unsafe.As>(ref this.V4L) = Avx.Multiply(Unsafe.As>(ref this.V4L), valueVec); + Unsafe.As>(ref this.V5L) = Avx.Multiply(Unsafe.As>(ref this.V5L), valueVec); + Unsafe.As>(ref this.V6L) = Avx.Multiply(Unsafe.As>(ref this.V6L), valueVec); + Unsafe.As>(ref this.V7L) = Avx.Multiply(Unsafe.As>(ref this.V7L), valueVec); + } + else +#endif + { + var valueVec = new Vector4(value); + this.V0L *= valueVec; + this.V0R *= valueVec; + this.V1L *= valueVec; + this.V1R *= valueVec; + this.V2L *= valueVec; + this.V2R *= valueVec; + this.V3L *= valueVec; + this.V3R *= valueVec; + this.V4L *= valueVec; + this.V4R *= valueVec; + this.V5L *= valueVec; + this.V5R *= valueVec; + this.V6L *= valueVec; + this.V6R *= valueVec; + this.V7L *= valueVec; + this.V7R *= valueVec; + } } /// /// Multiply all elements of the block by the corresponding elements of 'other'. /// [MethodImpl(InliningOptions.ShortMethod)] - public void MultiplyInplace(ref Block8x8F other) - { - this.V0L *= other.V0L; - this.V0R *= other.V0R; - this.V1L *= other.V1L; - this.V1R *= other.V1R; - this.V2L *= other.V2L; - this.V2R *= other.V2R; - this.V3L *= other.V3L; - this.V3R *= other.V3R; - this.V4L *= other.V4L; - this.V4R *= other.V4R; - this.V5L *= other.V5L; - this.V5R *= other.V5R; - this.V6L *= other.V6L; - this.V6R *= other.V6R; - this.V7L *= other.V7L; - this.V7R *= other.V7R; + public unsafe void MultiplyInPlace(ref Block8x8F other) + { +#if SUPPORTS_RUNTIME_INTRINSICS + if (Avx.IsSupported) + { + Unsafe.As>(ref this.V0L) + = Avx.Multiply( + Unsafe.As>(ref this.V0L), + Unsafe.As>(ref other.V0L)); + + Unsafe.As>(ref this.V1L) + = Avx.Multiply( + Unsafe.As>(ref this.V1L), + Unsafe.As>(ref other.V1L)); + + Unsafe.As>(ref this.V2L) + = Avx.Multiply( + Unsafe.As>(ref this.V2L), + Unsafe.As>(ref other.V2L)); + + Unsafe.As>(ref this.V3L) + = Avx.Multiply( + Unsafe.As>(ref this.V3L), + Unsafe.As>(ref other.V3L)); + + Unsafe.As>(ref this.V4L) + = Avx.Multiply( + Unsafe.As>(ref this.V4L), + Unsafe.As>(ref other.V4L)); + + Unsafe.As>(ref this.V5L) + = Avx.Multiply( + Unsafe.As>(ref this.V5L), + Unsafe.As>(ref other.V5L)); + + Unsafe.As>(ref this.V6L) + = Avx.Multiply( + Unsafe.As>(ref this.V6L), + Unsafe.As>(ref other.V6L)); + + Unsafe.As>(ref this.V7L) + = Avx.Multiply( + Unsafe.As>(ref this.V7L), + Unsafe.As>(ref other.V7L)); + } + else +#endif + { + this.V0L *= other.V0L; + this.V0R *= other.V0R; + this.V1L *= other.V1L; + this.V1R *= other.V1R; + this.V2L *= other.V2L; + this.V2R *= other.V2R; + this.V3L *= other.V3L; + this.V3R *= other.V3R; + this.V4L *= other.V4L; + this.V4R *= other.V4R; + this.V5L *= other.V5L; + this.V5R *= other.V5R; + this.V6L *= other.V6L; + this.V6R *= other.V6R; + this.V7L *= other.V7L; + this.V7R *= other.V7R; + } } /// /// Adds a vector to all elements of the block. /// - /// The added vector + /// The added vector. [MethodImpl(InliningOptions.ShortMethod)] - public void AddToAllInplace(Vector4 diff) - { - this.V0L += diff; - this.V0R += diff; - this.V1L += diff; - this.V1R += diff; - this.V2L += diff; - this.V2R += diff; - this.V3L += diff; - this.V3R += diff; - this.V4L += diff; - this.V4R += diff; - this.V5L += diff; - this.V5R += diff; - this.V6L += diff; - this.V6R += diff; - this.V7L += diff; - this.V7R += diff; + public void AddInPlace(float value) + { +#if SUPPORTS_RUNTIME_INTRINSICS + if (Avx.IsSupported) + { + var valueVec = Vector256.Create(value); + Unsafe.As>(ref this.V0L) = Avx.Add(Unsafe.As>(ref this.V0L), valueVec); + Unsafe.As>(ref this.V1L) = Avx.Add(Unsafe.As>(ref this.V1L), valueVec); + Unsafe.As>(ref this.V2L) = Avx.Add(Unsafe.As>(ref this.V2L), valueVec); + Unsafe.As>(ref this.V3L) = Avx.Add(Unsafe.As>(ref this.V3L), valueVec); + Unsafe.As>(ref this.V4L) = Avx.Add(Unsafe.As>(ref this.V4L), valueVec); + Unsafe.As>(ref this.V5L) = Avx.Add(Unsafe.As>(ref this.V5L), valueVec); + Unsafe.As>(ref this.V6L) = Avx.Add(Unsafe.As>(ref this.V6L), valueVec); + Unsafe.As>(ref this.V7L) = Avx.Add(Unsafe.As>(ref this.V7L), valueVec); + } + else +#endif + { + var valueVec = new Vector4(value); + this.V0L += valueVec; + this.V0R += valueVec; + this.V1L += valueVec; + this.V1R += valueVec; + this.V2L += valueVec; + this.V2R += valueVec; + this.V3L += valueVec; + this.V3R += valueVec; + this.V4L += valueVec; + this.V4R += valueVec; + this.V5L += valueVec; + this.V5R += valueVec; + this.V6L += valueVec; + this.V6R += valueVec; + this.V7L += valueVec; + this.V7R += valueVec; + } } /// @@ -468,23 +551,23 @@ public Block8x8 RoundAsInt16Block() /// /// Level shift by +maximum/2, clip to [0..maximum], and round all the values in the block. /// - public void NormalizeColorsAndRoundInplace(float maximum) + public void NormalizeColorsAndRoundInPlace(float maximum) { if (SimdUtils.HasVector8) { - this.NormalizeColorsAndRoundInplaceVector8(maximum); + this.NormalizeColorsAndRoundInPlaceVector8(maximum); } else { - this.NormalizeColorsInplace(maximum); - this.RoundInplace(); + this.NormalizeColorsInPlace(maximum); + this.RoundInPlace(); } } /// /// Rounds all values in the block. /// - public void RoundInplace() + public void RoundInPlace() { for (int i = 0; i < Size; i++) { diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs index 40683e25a9..e0311dafef 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs @@ -81,14 +81,14 @@ public void ProcessBlockColorsInto( b.LoadFrom(ref sourceBlock); // Dequantize: - b.MultiplyInplace(ref this.DequantiazationTable); + b.MultiplyInPlace(ref this.DequantiazationTable); FastFloatingPointDCT.TransformIDCT(ref b, ref this.WorkspaceBlock1, ref this.WorkspaceBlock2); // To conform better to libjpeg we actually NEED TO loose precision here. // This is because they store blocks as Int16 between all the operations. // To be "more accurate", we need to emulate this by rounding! - this.WorkspaceBlock1.NormalizeColorsAndRoundInplace(maximumValue); + this.WorkspaceBlock1.NormalizeColorsAndRoundInPlace(maximumValue); this.WorkspaceBlock1.ScaledCopyTo( ref destAreaOrigin, diff --git a/src/ImageSharp/Formats/Jpeg/Components/FastFloatingPointDCT.cs b/src/ImageSharp/Formats/Jpeg/Components/FastFloatingPointDCT.cs index d0b373609b..a6d0622dd8 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/FastFloatingPointDCT.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/FastFloatingPointDCT.cs @@ -61,7 +61,7 @@ public static void TransformIDCT(ref Block8x8F src, ref Block8x8F dest, ref Bloc IDCT8x4_RightPart(ref temp, ref dest); // TODO: What if we leave the blocks in a scaled-by-x8 state until final color packing? - dest.MultiplyInplace(C_0_125); + dest.MultiplyInPlace(C_0_125); } /// @@ -324,7 +324,7 @@ public static void TransformFDCT( src.TransposeInto(ref temp); if (offsetSourceByNeg128) { - temp.AddToAllInplace(new Vector4(-128)); + temp.AddInPlace(-128F); } FDCT8x4_LeftPart(ref temp, ref dest); @@ -335,7 +335,7 @@ public static void TransformFDCT( FDCT8x4_LeftPart(ref temp, ref dest); FDCT8x4_RightPart(ref temp, ref dest); - dest.MultiplyInplace(C_0_125); + dest.MultiplyInPlace(C_0_125); } } } diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_AddInPlace.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_AddInPlace.cs new file mode 100644 index 0000000000..61fb2745b9 --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_AddInPlace.cs @@ -0,0 +1,21 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using BenchmarkDotNet.Attributes; +using SixLabors.ImageSharp.Formats.Jpeg.Components; + +namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg.BlockOperations +{ + [Config(typeof(Config.HwIntrinsics_SSE_AVX))] + public class Block8x8F_AddInPlace + { + [Benchmark] + public float AddInplace() + { + float f = 42F; + Block8x8F b = default; + b.AddInPlace(f); + return f; + } + } +} diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_MultiplyInPlaceBlock.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_MultiplyInPlaceBlock.cs new file mode 100644 index 0000000000..0d1e67112f --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_MultiplyInPlaceBlock.cs @@ -0,0 +1,37 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using BenchmarkDotNet.Attributes; +using SixLabors.ImageSharp.Formats.Jpeg.Components; + +namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg.BlockOperations +{ + [Config(typeof(Config.HwIntrinsics_SSE_AVX))] + public class Block8x8F_MultiplyInPlaceBlock + { + private static readonly Block8x8F Source = Create8x8FloatData(); + + [Benchmark] + public void MultiplyInPlaceBlock() + { + Block8x8F dest = default; + Source.MultiplyInPlace(ref dest); + } + + private static Block8x8F Create8x8FloatData() + { + var result = new float[64]; + for (int i = 0; i < 8; i++) + { + for (int j = 0; j < 8; j++) + { + result[(i * 8) + j] = (i * 10) + j; + } + } + + var source = default(Block8x8F); + source.LoadFrom(result); + return source; + } + } +} diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_MultiplyInPlaceScalar.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_MultiplyInPlaceScalar.cs new file mode 100644 index 0000000000..31a6ca713f --- /dev/null +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_MultiplyInPlaceScalar.cs @@ -0,0 +1,21 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +using BenchmarkDotNet.Attributes; +using SixLabors.ImageSharp.Formats.Jpeg.Components; + +namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg.BlockOperations +{ + [Config(typeof(Config.HwIntrinsics_SSE_AVX))] + public class Block8x8F_MultiplyInPlaceScalar + { + [Benchmark] + public float MultiplyInPlaceScalar() + { + float f = 42F; + Block8x8F b = default; + b.MultiplyInPlace(f); + return f; + } + } +} diff --git a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs index 5482380885..927d7c2528 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs @@ -5,6 +5,7 @@ // #define BENCHMARKING using System; using System.Diagnostics; + using SixLabors.ImageSharp.Formats.Jpeg.Components; using SixLabors.ImageSharp.Tests.Formats.Jpg.Utils; using SixLabors.ImageSharp.Tests.TestUtilities; @@ -44,20 +45,20 @@ public void Indexer() this.Measure( Times, () => + { + var block = default(Block8x8F); + + for (int i = 0; i < Block8x8F.Size; i++) { - var block = default(Block8x8F); - - for (int i = 0; i < Block8x8F.Size; i++) - { - block[i] = i; - } - - sum = 0; - for (int i = 0; i < Block8x8F.Size; i++) - { - sum += block[i]; - } - }); + block[i] = i; + } + + sum = 0; + for (int i = 0; i < Block8x8F.Size; i++) + { + sum += block[i]; + } + }); Assert.Equal(sum, 64f * 63f * 0.5f); } @@ -69,20 +70,20 @@ public void Indexer_ReferenceBenchmarkWithArray() this.Measure( Times, () => + { + // Block8x8F block = new Block8x8F(); + float[] block = new float[64]; + for (int i = 0; i < Block8x8F.Size; i++) { - // Block8x8F block = new Block8x8F(); - float[] block = new float[64]; - for (int i = 0; i < Block8x8F.Size; i++) - { - block[i] = i; - } - - sum = 0; - for (int i = 0; i < Block8x8F.Size; i++) - { - sum += block[i]; - } - }); + block[i] = i; + } + + sum = 0; + for (int i = 0; i < Block8x8F.Size; i++) + { + sum += block[i]; + } + }); Assert.Equal(sum, 64f * 63f * 0.5f); } @@ -100,11 +101,11 @@ public void Load_Store_FloatArray() this.Measure( Times, () => - { - var b = default(Block8x8F); - b.LoadFrom(data); - b.ScaledCopyTo(mirror); - }); + { + var b = default(Block8x8F); + b.LoadFrom(data); + b.ScaledCopyTo(mirror); + }); Assert.Equal(data, mirror); @@ -125,11 +126,11 @@ public unsafe void Load_Store_FloatArray_Ptr() this.Measure( Times, () => - { - var b = default(Block8x8F); - Block8x8F.LoadFrom(&b, data); - Block8x8F.ScaledCopyTo(&b, mirror); - }); + { + var b = default(Block8x8F); + Block8x8F.LoadFrom(&b, data); + Block8x8F.ScaledCopyTo(&b, mirror); + }); Assert.Equal(data, mirror); @@ -150,11 +151,11 @@ public void Load_Store_IntArray() this.Measure( Times, () => - { - var v = default(Block8x8F); - v.LoadFrom(data); - v.ScaledCopyTo(mirror); - }); + { + var v = default(Block8x8F); + v.LoadFrom(data); + v.ScaledCopyTo(mirror); + }); Assert.Equal(data, mirror); @@ -234,7 +235,7 @@ public void NormalizeColors() this.PrintLinearData(input); Block8x8F dest = block; - dest.NormalizeColorsInplace(255); + dest.NormalizeColorsInPlace(255); float[] array = new float[64]; dest.ScaledCopyTo(array); @@ -259,11 +260,11 @@ public void NormalizeColorsAndRoundAvx2(int seed) Block8x8F source = CreateRandomFloatBlock(-200, 200, seed); Block8x8F expected = source; - expected.NormalizeColorsInplace(255); - expected.RoundInplace(); + expected.NormalizeColorsInPlace(255); + expected.RoundInPlace(); Block8x8F actual = source; - actual.NormalizeColorsAndRoundInplaceVector8(255); + actual.NormalizeColorsAndRoundInPlaceVector8(255); this.Output.WriteLine(expected.ToString()); this.Output.WriteLine(actual.ToString()); @@ -324,12 +325,12 @@ public void RoundInto() [InlineData(1)] [InlineData(2)] [InlineData(3)] - public void RoundInplaceSlow(int seed) + public void RoundInPlaceSlow(int seed) { Block8x8F s = CreateRandomFloatBlock(-500, 500, seed); Block8x8F d = s; - d.RoundInplace(); + d.RoundInPlace(); this.Output.WriteLine(s.ToString()); this.Output.WriteLine(d.ToString()); @@ -344,19 +345,26 @@ public void RoundInplaceSlow(int seed) } [Fact] - public void MultiplyInplace_ByOtherBlock() + public void MultiplyInPlace_ByOtherBlock() { - Block8x8F original = CreateRandomFloatBlock(-500, 500, 42); - Block8x8F m = CreateRandomFloatBlock(-500, 500, 42); + static void RunTest() + { + Block8x8F original = CreateRandomFloatBlock(-500, 500, 42); + Block8x8F m = CreateRandomFloatBlock(-500, 500, 42); - Block8x8F actual = original; + Block8x8F actual = original; - actual.MultiplyInplace(ref m); + actual.MultiplyInPlace(ref m); - for (int i = 0; i < Block8x8F.Size; i++) - { - Assert.Equal(original[i] * m[i], actual[i]); + for (int i = 0; i < Block8x8F.Size; i++) + { + Assert.Equal(original[i] * m[i], actual[i]); + } } + + FeatureTestRunner.RunWithHwIntrinsicsFeature( + RunTest, + HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX); } [Theory] @@ -396,23 +404,51 @@ public unsafe void ZigZag_CreateDequantizationTable_MultiplicationShouldQuantize ReferenceImplementations.DequantizeBlock(&expected, &qt, unzig.Data); - actual.MultiplyInplace(ref zigQt); + actual.MultiplyInPlace(ref zigQt); this.CompareBlocks(expected, actual, 0); } [Fact] - public void MultiplyInplace_ByScalar() + public void AddToAllInPlace() { - Block8x8F original = CreateRandomFloatBlock(-500, 500); + static void RunTest() + { + Block8x8F original = CreateRandomFloatBlock(-500, 500); - Block8x8F actual = original; - actual.MultiplyInplace(42f); + Block8x8F actual = original; + actual.AddInPlace(42f); - for (int i = 0; i < 64; i++) + for (int i = 0; i < 64; i++) + { + Assert.Equal(original[i] + 42f, actual[i]); + } + } + + FeatureTestRunner.RunWithHwIntrinsicsFeature( + RunTest, + HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX); + } + + [Fact] + public void MultiplyInPlace_ByScalar() + { + static void RunTest() { - Assert.Equal(original[i] * 42f, actual[i]); + Block8x8F original = CreateRandomFloatBlock(-500, 500); + + Block8x8F actual = original; + actual.MultiplyInPlace(42f); + + for (int i = 0; i < 64; i++) + { + Assert.Equal(original[i] * 42f, actual[i]); + } } + + FeatureTestRunner.RunWithHwIntrinsicsFeature( + RunTest, + HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX); } [Fact] diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs index 98421ca5d4..cc23a45fcb 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs @@ -54,8 +54,7 @@ static void RunTest(string providerDump, string nonContiguousBuffersStr) RemoteExecutor.Invoke( RunTest, providerDump, - "Disco") - .Dispose(); + "Disco").Dispose(); } } }