diff --git a/src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs b/src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs index 233cc0580b..5d30e345f2 100644 --- a/src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs +++ b/src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs @@ -141,6 +141,20 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common return result; } + public static Block8x8F Load(Span data) + { + var result = default(Block8x8F); + result.LoadFrom(data); + return result; + } + + public static Block8x8F Load(Span data) + { + var result = default(Block8x8F); + result.LoadFrom(data); + return result; + } + /// /// Pointer-based "Indexer" (getter part) /// @@ -348,13 +362,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common } /// - /// Un-zig + /// Quantize the block. /// /// Block pointer /// Qt pointer /// Unzig pointer [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static unsafe void UnZigAndQuantize(Block8x8F* blockPtr, Block8x8F* qtPtr, int* unzigPtr) + public static unsafe void QuantizeBlock(Block8x8F* blockPtr, Block8x8F* qtPtr, int* unzigPtr) { float* b = (float*)blockPtr; float* qtp = (float*)qtPtr; diff --git a/src/ImageSharp/Formats/Jpeg/Common/FastFloatingPointDCT.cs b/src/ImageSharp/Formats/Jpeg/Common/FastFloatingPointDCT.cs index 2debbb23b6..8b86261795 100644 --- a/src/ImageSharp/Formats/Jpeg/Common/FastFloatingPointDCT.cs +++ b/src/ImageSharp/Formats/Jpeg/Common/FastFloatingPointDCT.cs @@ -59,6 +59,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common IDCT8x4_LeftPart(ref temp, ref dest); IDCT8x4_RightPart(ref temp, ref dest); + // TODO: What if we leave the blocks in a scaled-by-x8 state until final color packing? dest.MultiplyAllInplace(C_0_125); } diff --git a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/JpegBlockProcessor.cs b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/JpegBlockProcessor.cs index 2520735b1b..77ad268ed3 100644 --- a/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/JpegBlockProcessor.cs +++ b/src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/JpegBlockProcessor.cs @@ -75,7 +75,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder Block8x8F* b = this.pointers.Block; - Block8x8F.UnZigAndQuantize(b, this.pointers.QuantiazationTable, this.pointers.Unzig); + Block8x8F.QuantizeBlock(b, this.pointers.QuantiazationTable, this.pointers.Unzig); FastFloatingPointDCT.TransformIDCT(ref *b, ref *this.pointers.Temp1, ref *this.pointers.Temp2); diff --git a/tests/ImageSharp.Tests/Formats/Jpg/DCTTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/DCTTests.cs index ca9b62639c..5776361f1c 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/DCTTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/DCTTests.cs @@ -74,7 +74,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg [InlineData(1)] [InlineData(2)] [InlineData(3)] - public void TransformIDCT(int seed) + public void LLM_TransformIDCT_CompareToNonOptimized(int seed) { Span sourceArray = JpegUtilityTestFixture.Create8x8RoundedRandomFloatData(-200, 200, seed); float[] expectedDestArray = new float[64]; @@ -82,14 +82,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg ReferenceImplementations.LLM_FloatingPoint_DCT.iDCT2D_llm(sourceArray, expectedDestArray, tempArray); - // ReferenceImplementations.iDCT8x8_llm_sse(sourceArray, expectedDestArray, tempArray); - Block8x8F source = new Block8x8F(); - source.LoadFrom(sourceArray); - - Block8x8F dest = new Block8x8F(); - Block8x8F tempBuffer = new Block8x8F(); + var source = Block8x8F.Load(sourceArray); + var dest = default(Block8x8F); + var temp = default(Block8x8F); - FastFloatingPointDCT.TransformIDCT(ref source, ref dest, ref tempBuffer); + FastFloatingPointDCT.TransformIDCT(ref source, ref dest, ref temp); float[] actualDestArray = new float[64]; dest.CopyTo(actualDestArray); @@ -101,6 +98,25 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg Assert.Equal(expectedDestArray, actualDestArray, new ApproximateFloatComparer(1f)); } + [Theory] + [InlineData(1)] + [InlineData(2)] + [InlineData(3)] + public void LLM_TransformIDCT_CompareToAccurate(int seed) + { + float[] sourceArray = JpegUtilityTestFixture.Create8x8RoundedRandomFloatData(-1000, 1000, seed); + + var source = Block8x8F.Load(sourceArray); + + Block8x8F expected = ReferenceImplementations.AccurateDCT.TransformIDCT(ref source); + + var temp = default(Block8x8F); + var actual = default(Block8x8F); + FastFloatingPointDCT.TransformIDCT(ref source, ref actual, ref temp); + + this.CompareBlocks(expected, actual, 1f); + } + [Theory] [InlineData(1)]