Browse Source

DCT.cs -> FastFloatingPointDCT.cs

pull/322/head
Anton Firszov 9 years ago
parent
commit
905931fbe7
  1. 2
      src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/JpegBlockProcessor.cs
  2. 4
      src/ImageSharp/Formats/Jpeg/GolangPort/Components/FastFloatingPointDCT.cs
  3. 2
      src/ImageSharp/Formats/Jpeg/GolangPort/JpegEncoderCore.cs
  4. 12
      tests/ImageSharp.Tests/Formats/Jpg/DCTTests.cs
  5. 81
      tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.FastFloatingPointDCT.cs
  6. 24
      tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.StandardIntegerDCT.cs
  7. 4
      tests/ImageSharp.Tests/Formats/Jpg/Utils/JpegUtilityTestFixture.cs

2
src/ImageSharp/Formats/Jpeg/GolangPort/Components/Decoder/JpegBlockProcessor.cs

@ -77,7 +77,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components.Decoder
Block8x8F.UnZigAndQuantize(b, this.pointers.QuantiazationTable, this.pointers.Unzig); Block8x8F.UnZigAndQuantize(b, this.pointers.QuantiazationTable, this.pointers.Unzig);
DCT.TransformIDCT(ref *b, ref *this.pointers.Temp1, ref *this.pointers.Temp2); FastFloatingPointDCT.TransformIDCT(ref *b, ref *this.pointers.Temp1, ref *this.pointers.Temp2);
OldJpegPixelArea destChannel = decoder.GetDestinationChannel(this.componentIndex); OldJpegPixelArea destChannel = decoder.GetDestinationChannel(this.componentIndex);
OldJpegPixelArea destArea = destChannel.GetOffsetedSubAreaForBlock(bx, by); OldJpegPixelArea destArea = destChannel.GetOffsetedSubAreaForBlock(bx, by);

4
src/ImageSharp/Formats/Jpeg/GolangPort/Components/DCT.cs → src/ImageSharp/Formats/Jpeg/GolangPort/Components/FastFloatingPointDCT.cs

@ -9,9 +9,9 @@ using Block8x8F = SixLabors.ImageSharp.Formats.Jpeg.Common.Block8x8F;
namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort.Components
{ {
/// <summary> /// <summary>
/// Contains forward and inverse DCT implementations /// Contains inaccurate, but fast forward and inverse DCT implementations.
/// </summary> /// </summary>
internal static class DCT internal static class FastFloatingPointDCT
{ {
#pragma warning disable SA1310 // FieldNamesMustNotContainUnderscore #pragma warning disable SA1310 // FieldNamesMustNotContainUnderscore
private static readonly float C_1_175876 = 1.175876f; private static readonly float C_1_175876 = 1.175876f;

2
src/ImageSharp/Formats/Jpeg/GolangPort/JpegEncoderCore.cs

@ -562,7 +562,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.GolangPort
Block8x8F* quant, Block8x8F* quant,
int* unzigPtr) int* unzigPtr)
{ {
DCT.TransformFDCT(ref *src, ref *tempDest1, ref *tempDest2); FastFloatingPointDCT.TransformFDCT(ref *src, ref *tempDest1, ref *tempDest2);
Block8x8F.UnzigDivRound(tempDest1, tempDest2, quant, unzigPtr); Block8x8F.UnzigDivRound(tempDest1, tempDest2, quant, unzigPtr);
float* unziggedDestPtr = (float*)tempDest2; float* unziggedDestPtr = (float*)tempDest2;

12
tests/ImageSharp.Tests/Formats/Jpg/DCTTests.cs

@ -33,7 +33,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
Block8x8F dest = new Block8x8F(); Block8x8F dest = new Block8x8F();
DCT.IDCT8x4_LeftPart(ref source, ref dest); FastFloatingPointDCT.IDCT8x4_LeftPart(ref source, ref dest);
float[] actualDestArray = new float[64]; float[] actualDestArray = new float[64];
dest.CopyTo(actualDestArray); dest.CopyTo(actualDestArray);
@ -58,7 +58,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
Block8x8F dest = new Block8x8F(); Block8x8F dest = new Block8x8F();
DCT.IDCT8x4_RightPart(ref source, ref dest); FastFloatingPointDCT.IDCT8x4_RightPart(ref source, ref dest);
float[] actualDestArray = new float[64]; float[] actualDestArray = new float[64];
dest.CopyTo(actualDestArray); dest.CopyTo(actualDestArray);
@ -89,7 +89,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
Block8x8F dest = new Block8x8F(); Block8x8F dest = new Block8x8F();
Block8x8F tempBuffer = new Block8x8F(); Block8x8F tempBuffer = new Block8x8F();
DCT.TransformIDCT(ref source, ref dest, ref tempBuffer); FastFloatingPointDCT.TransformIDCT(ref source, ref dest, ref tempBuffer);
float[] actualDestArray = new float[64]; float[] actualDestArray = new float[64];
dest.CopyTo(actualDestArray); dest.CopyTo(actualDestArray);
@ -116,7 +116,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
float[] expectedDest = new float[64]; float[] expectedDest = new float[64];
ReferenceImplementations.FastFloatingPointDCT.fDCT2D8x4_32f(src, expectedDest); ReferenceImplementations.FastFloatingPointDCT.fDCT2D8x4_32f(src, expectedDest);
DCT.FDCT8x4_LeftPart(ref srcBlock, ref destBlock); FastFloatingPointDCT.FDCT8x4_LeftPart(ref srcBlock, ref destBlock);
float[] actualDest = new float[64]; float[] actualDest = new float[64];
destBlock.CopyTo(actualDest); destBlock.CopyTo(actualDest);
@ -138,7 +138,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
float[] expectedDest = new float[64]; float[] expectedDest = new float[64];
ReferenceImplementations.FastFloatingPointDCT.fDCT2D8x4_32f(src.Slice(4), expectedDest.AsSpan().Slice(4)); ReferenceImplementations.FastFloatingPointDCT.fDCT2D8x4_32f(src.Slice(4), expectedDest.AsSpan().Slice(4));
DCT.FDCT8x4_RightPart(ref srcBlock, ref destBlock); FastFloatingPointDCT.FDCT8x4_RightPart(ref srcBlock, ref destBlock);
float[] actualDest = new float[64]; float[] actualDest = new float[64];
destBlock.CopyTo(actualDest); destBlock.CopyTo(actualDest);
@ -162,7 +162,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
Block8x8F temp2 = new Block8x8F(); Block8x8F temp2 = new Block8x8F();
ReferenceImplementations.FastFloatingPointDCT.fDCT2D_llm(src, expectedDest, temp1, downscaleBy8: true); ReferenceImplementations.FastFloatingPointDCT.fDCT2D_llm(src, expectedDest, temp1, downscaleBy8: true);
DCT.TransformFDCT(ref srcBlock, ref destBlock, ref temp2, false); FastFloatingPointDCT.TransformFDCT(ref srcBlock, ref destBlock, ref temp2, false);
float[] actualDest = new float[64]; float[] actualDest = new float[64];
destBlock.CopyTo(actualDest); destBlock.CopyTo(actualDest);

81
tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.FastFloatingPointDCT.cs

@ -35,32 +35,35 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
this.CompareBlocks(data.ConvertAllToFloat(), src, 2f); this.CompareBlocks(data.ConvertAllToFloat(), src, 2f);
} }
[Theory(Skip = "Sandboxing only! (Incorrect reference implementation)")] //[Theory(Skip = "Sandboxing only! (Incorrect reference implementation)")]
[InlineData(42)] //[InlineData(42)]
[InlineData(1)] //[InlineData(1)]
[InlineData(2)] //[InlineData(2)]
public void IDCT_IsEquivalentTo_StandardIntegerImplementation(int seed) //public void IDCT_IsEquivalentTo_StandardIntegerImplementation(int seed)
{ //{
int[] intData = JpegUtilityTestFixture.Create8x8RandomIntData(-1000, 1000, seed); // int[] intData = JpegUtilityTestFixture.Create8x8RandomIntData(-1000, 1000, seed);
Span<float> floatSrc = intData.ConvertAllToFloat(); // Span<float> floatSrc = intData.ConvertAllToFloat();
ReferenceImplementations.StandardIntegerDCT.TransformIDCTInplace(intData); // ReferenceImplementations.StandardIntegerDCT.TransformIDCTInplace(intData);
float[] dest = new float[64]; // float[] dest = new float[64];
float[] temp = new float[64]; // float[] temp = new float[64];
ReferenceImplementations.FastFloatingPointDCT.iDCT2D_llm(floatSrc, dest, temp); // ReferenceImplementations.FastFloatingPointDCT.iDCT2D_llm(floatSrc, dest, temp);
this.CompareBlocks(intData.ConvertAllToFloat(), dest, 1f); // this.CompareBlocks(intData.ConvertAllToFloat(), dest, 1f);
} //}
[Theory] [Theory]
[InlineData(42)] [InlineData(42, 1000)]
[InlineData(1)] [InlineData(1, 1000)]
[InlineData(2)] [InlineData(2, 1000)]
public void IDCT_IsEquivalentTo_AccurateImplementation(int seed) [InlineData(42, 200)]
[InlineData(1, 200)]
[InlineData(2, 200)]
public void IDCT_IsEquivalentTo_AccurateImplementation(int seed, int range)
{ {
int[] intData = JpegUtilityTestFixture.Create8x8RandomIntData(-1000, 1000, seed); int[] intData = JpegUtilityTestFixture.Create8x8RandomIntData(-range, range, seed);
float[] floatSrc = intData.ConvertAllToFloat(); float[] floatSrc = intData.ConvertAllToFloat();
ReferenceImplementations.AccurateDCT.TransformIDCTInplace(intData); ReferenceImplementations.AccurateDCT.TransformIDCTInplace(intData);
@ -73,24 +76,24 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
this.CompareBlocks(intData.ConvertAllToFloat(), dest, 1f); this.CompareBlocks(intData.ConvertAllToFloat(), dest, 1f);
} }
[Theory] //[Theory]
[InlineData(42)] //[InlineData(42)]
[InlineData(1)] //[InlineData(1)]
[InlineData(2)] //[InlineData(2)]
public void FDCT_IsEquivalentTo_StandardIntegerImplementation(int seed) //public void FDCT_IsEquivalentTo_StandardIntegerImplementation(int seed)
{ //{
int[] intData = JpegUtilityTestFixture.Create8x8RandomIntData(-1000, 1000, seed); // int[] intData = JpegUtilityTestFixture.Create8x8RandomIntData(-1000, 1000, seed);
float[] floatSrc = intData.ConvertAllToFloat(); // float[] floatSrc = intData.ConvertAllToFloat();
ReferenceImplementations.StandardIntegerDCT.Subtract128_TransformFDCT_Upscale8_Inplace(intData); // ReferenceImplementations.StandardIntegerDCT.Subtract128_TransformFDCT_Upscale8_Inplace(intData);
float[] dest = new float[64]; // float[] dest = new float[64];
float[] temp = new float[64]; // float[] temp = new float[64];
ReferenceImplementations.FastFloatingPointDCT.fDCT2D_llm(floatSrc, dest, temp, subtract128FromSource: true); // ReferenceImplementations.FastFloatingPointDCT.fDCT2D_llm(floatSrc, dest, temp, subtract128FromSource: true);
this.CompareBlocks(intData.ConvertAllToFloat(), dest, 2f); // this.CompareBlocks(intData.ConvertAllToFloat(), dest, 2f);
} //}
[Theory] [Theory]
[InlineData(42)] [InlineData(42)]
@ -108,18 +111,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
actual /= 8; actual /= 8;
this.CompareBlocks(expected, actual, 1f); this.CompareBlocks(expected, actual, 1f);
//int[] intData = JpegUtilityTestFixture.Create8x8RandomIntData(-1000, 1000, seed);
//float[] floatSrc = intData.ConvertAllToFloat();
//ReferenceImplementations.AccurateDCT.TransformFDCTInplace(intData);
//float[] dest = new float[64];
//float[] temp = new float[64];
//ReferenceImplementations.FastFloatingPointDCT.fDCT2D_llm(floatSrc, dest, temp, offsetSourceByNeg128: false);
//this.CompareBlocks(intData.ConvertAllToFloat(), dest, 1f);
} }

24
tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.StandardIntegerDCT.cs

@ -18,13 +18,13 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
{ {
} }
[Theory(Skip = "Sandboxing only! (Incorrect reference implementation)")] [Theory]
[InlineData(42)] [InlineData(42, 200)]
[InlineData(1)] [InlineData(1, 200)]
[InlineData(2)] [InlineData(2, 200)]
public void IDCT_IsEquivalentTo_AccurateImplementation(int seed) public void IDCT_IsEquivalentTo_AccurateImplementation(int seed, int range)
{ {
int[] data = Create8x8RandomIntData(-1000, 1000, seed); int[] data = Create8x8RandomIntData(-range, range, seed);
Block8x8 source = default(Block8x8); Block8x8 source = default(Block8x8);
source.LoadFrom(data); source.LoadFrom(data);
@ -32,17 +32,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
Block8x8 expected = ReferenceImplementations.AccurateDCT.TransformIDCT(ref source); Block8x8 expected = ReferenceImplementations.AccurateDCT.TransformIDCT(ref source);
Block8x8 actual = ReferenceImplementations.StandardIntegerDCT.TransformIDCT(ref source); Block8x8 actual = ReferenceImplementations.StandardIntegerDCT.TransformIDCT(ref source);
Block8x8F sourceF = source.AsFloatBlock(); this.CompareBlocks(expected, actual, 1);
Block8x8F wut0 = ReferenceImplementations.FastFloatingPointDCT.TransformIDCT(ref sourceF);
Block8x8 wut1 = wut0.RoundAsInt16Block();
long diff = Block8x8.TotalDifference(ref expected, ref actual);
this.Output.WriteLine(expected.ToString());
this.Output.WriteLine(actual.ToString());
this.Output.WriteLine(wut1.ToString());
this.Output.WriteLine("DIFFERENCE: "+diff);
Assert.True(diff < 4);
} }
[Theory] [Theory]

4
tests/ImageSharp.Tests/Formats/Jpg/Utils/JpegUtilityTestFixture.cs

@ -137,8 +137,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg.Utils
this.Output.WriteLine(msg); this.Output.WriteLine(msg);
} }
internal void CompareBlocks(Block8x8 a, Block8x8 b, float tolerance) => internal void CompareBlocks(Block8x8 a, Block8x8 b, int tolerance) =>
this.CompareBlocks(a.AsFloatBlock(), b.AsFloatBlock(), tolerance); this.CompareBlocks(a.AsFloatBlock(), b.AsFloatBlock(), (float)tolerance + 1e-5f);
internal void CompareBlocks(Block8x8F a, Block8x8F b, float tolerance) internal void CompareBlocks(Block8x8F a, Block8x8F b, float tolerance)
=> this.CompareBlocks(a.ToArray(), b.ToArray(), tolerance); => this.CompareBlocks(a.ToArray(), b.ToArray(), tolerance);

Loading…
Cancel
Save