Browse Source

Optimized Block8x8F

pull/2418/head
Günther Foidl 3 years ago
parent
commit
a534328dc4
  1. 25
      src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs
  2. 4
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_MultiplyInPlaceBlock.cs
  3. 12
      tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs
  4. 15
      tests/ImageSharp.Tests/Formats/Jpg/DCTTests.cs
  5. 3
      tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.AccurateDCT.cs
  6. 3
      tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.FastFloatingPointDCT.cs
  7. 6
      tests/ImageSharp.Tests/Formats/Jpg/Utils/ReferenceImplementations.LLM_FloatingPoint_DCT.cs

25
src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs

@ -101,24 +101,17 @@ internal partial struct Block8x8F : IEquatable<Block8x8F>
set => this[((uint)y * 8) + (uint)x] = value; set => this[((uint)y * 8) + (uint)x] = value;
} }
public static Block8x8F Load(Span<float> data)
{
Block8x8F result = default;
result.LoadFrom(data);
return result;
}
/// <summary> /// <summary>
/// Load raw 32bit floating point data from source. /// Load raw 32bit floating point data from source.
/// </summary> /// </summary>
/// <param name="source">Source</param> /// <param name="data">Source</param>
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public void LoadFrom(Span<float> source) public static Block8x8F Load(Span<float> data)
{ {
ref byte s = ref Unsafe.As<float, byte>(ref MemoryMarshal.GetReference(source)); DebugGuard.MustBeGreaterThanOrEqualTo(data.Length, Size, "data is too small");
ref byte d = ref Unsafe.As<Block8x8F, byte>(ref this);
Unsafe.CopyBlock(ref d, ref s, Size * sizeof(float)); ref byte src = ref Unsafe.As<float, byte>(ref MemoryMarshal.GetReference(data));
return Unsafe.ReadUnaligned<Block8x8F>(ref src);
} }
/// <summary> /// <summary>
@ -144,10 +137,10 @@ internal partial struct Block8x8F : IEquatable<Block8x8F>
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public unsafe void ScaledCopyTo(float[] dest) public unsafe void ScaledCopyTo(float[] dest)
{ {
fixed (void* ptr = &this.V0L) DebugGuard.MustBeGreaterThanOrEqualTo(dest.Length, Size, "dest is too small");
{
Marshal.Copy((IntPtr)ptr, dest, 0, Size); ref byte destRef = ref Unsafe.As<float, byte>(ref MemoryMarshal.GetArrayDataReference(dest));
} Unsafe.WriteUnaligned(ref destRef, this);
} }
public float[] ToArray() public float[] ToArray()

4
tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_MultiplyInPlaceBlock.cs

@ -29,8 +29,6 @@ public class Block8x8F_MultiplyInPlaceBlock
} }
} }
var source = default(Block8x8F); return Block8x8F.Load(result);
source.LoadFrom(result);
return source;
} }
} }

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

@ -99,8 +99,7 @@ public partial class Block8x8FTests : JpegFixture
Times, Times,
() => () =>
{ {
var b = default(Block8x8F); Block8x8F b = Block8x8F.Load(data);
b.LoadFrom(data);
b.ScaledCopyTo(mirror); b.ScaledCopyTo(mirror);
}); });
@ -117,8 +116,7 @@ public partial class Block8x8FTests : JpegFixture
float[] expected = Create8x8FloatData(); float[] expected = Create8x8FloatData();
ReferenceImplementations.Transpose8x8(expected); ReferenceImplementations.Transpose8x8(expected);
var block8x8 = default(Block8x8F); Block8x8F block8x8 = Block8x8F.Load(Create8x8FloatData());
block8x8.LoadFrom(Create8x8FloatData());
block8x8.TransposeInplace(); block8x8.TransposeInplace();
@ -153,9 +151,8 @@ public partial class Block8x8FTests : JpegFixture
[Fact] [Fact]
public void NormalizeColors() public void NormalizeColors()
{ {
var block = default(Block8x8F);
float[] input = Create8x8ColorCropTestData(); float[] input = Create8x8ColorCropTestData();
block.LoadFrom(input); Block8x8F block = Block8x8F.Load(input);
this.Output.WriteLine("Input:"); this.Output.WriteLine("Input:");
this.PrintLinearData(input); this.PrintLinearData(input);
@ -242,8 +239,7 @@ public partial class Block8x8FTests : JpegFixture
{ {
float[] data = Create8x8RandomFloatData(-1000, 1000); float[] data = Create8x8RandomFloatData(-1000, 1000);
var source = default(Block8x8F); Block8x8F source = Block8x8F.Load(data);
source.LoadFrom(data);
var dest = default(Block8x8); var dest = default(Block8x8);
source.RoundInto(ref dest); source.RoundInto(ref dest);

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

@ -114,8 +114,7 @@ public static class DCTTests
int seed = FeatureTestRunner.Deserialize<int>(serialized); int seed = FeatureTestRunner.Deserialize<int>(serialized);
Span<float> src = Create8x8RandomFloatData(MinInputValue, MaxInputValue, seed); Span<float> src = Create8x8RandomFloatData(MinInputValue, MaxInputValue, seed);
var srcBlock = default(Block8x8F); Block8x8F srcBlock = Block8x8F.Load(src);
srcBlock.LoadFrom(src);
float[] expectedDest = new float[64]; float[] expectedDest = new float[64];
float[] temp = new float[64]; float[] temp = new float[64];
@ -162,8 +161,7 @@ public static class DCTTests
public void TranformIDCT_4x4(int seed) public void TranformIDCT_4x4(int seed)
{ {
Span<float> src = Create8x8RandomFloatData(MinInputValue, MaxInputValue, seed, 4, 4); Span<float> src = Create8x8RandomFloatData(MinInputValue, MaxInputValue, seed, 4, 4);
var srcBlock = default(Block8x8F); Block8x8F srcBlock = Block8x8F.Load(src);
srcBlock.LoadFrom(src);
float[] expectedDest = new float[64]; float[] expectedDest = new float[64];
float[] temp = new float[64]; float[] temp = new float[64];
@ -224,8 +222,7 @@ public static class DCTTests
public void TranformIDCT_2x2(int seed) public void TranformIDCT_2x2(int seed)
{ {
Span<float> src = Create8x8RandomFloatData(MinInputValue, MaxInputValue, seed, 2, 2); Span<float> src = Create8x8RandomFloatData(MinInputValue, MaxInputValue, seed, 2, 2);
var srcBlock = default(Block8x8F); Block8x8F srcBlock = Block8x8F.Load(src);
srcBlock.LoadFrom(src);
float[] expectedDest = new float[64]; float[] expectedDest = new float[64];
float[] temp = new float[64]; float[] temp = new float[64];
@ -286,8 +283,7 @@ public static class DCTTests
public void TranformIDCT_1x1(int seed) public void TranformIDCT_1x1(int seed)
{ {
Span<float> src = Create8x8RandomFloatData(MinInputValue, MaxInputValue, seed, 1, 1); Span<float> src = Create8x8RandomFloatData(MinInputValue, MaxInputValue, seed, 1, 1);
var srcBlock = default(Block8x8F); Block8x8F srcBlock = Block8x8F.Load(src);
srcBlock.LoadFrom(src);
float[] expectedDest = new float[64]; float[] expectedDest = new float[64];
float[] temp = new float[64]; float[] temp = new float[64];
@ -330,8 +326,7 @@ public static class DCTTests
int seed = FeatureTestRunner.Deserialize<int>(serialized); int seed = FeatureTestRunner.Deserialize<int>(serialized);
Span<float> src = Create8x8RandomFloatData(MinInputValue, MaxInputValue, seed); Span<float> src = Create8x8RandomFloatData(MinInputValue, MaxInputValue, seed);
var block = default(Block8x8F); Block8x8F block = Block8x8F.Load(src);
block.LoadFrom(src);
float[] expectedDest = new float[64]; float[] expectedDest = new float[64];
float[] temp1 = new float[64]; float[] temp1 = new float[64];

3
tests/ImageSharp.Tests/Formats/Jpg/ReferenceImplementationsTests.AccurateDCT.cs

@ -25,8 +25,7 @@ public partial class ReferenceImplementationsTests
{ {
float[] data = Create8x8RandomFloatData(-1000, 1000, seed); float[] data = Create8x8RandomFloatData(-1000, 1000, seed);
var b0 = default(Block8x8F); Block8x8F b0 = Block8x8F.Load(data);
b0.LoadFrom(data);
Block8x8F b1 = ReferenceImplementations.AccurateDCT.TransformFDCT(ref b0); Block8x8F b1 = ReferenceImplementations.AccurateDCT.TransformFDCT(ref b0);
Block8x8F b2 = ReferenceImplementations.AccurateDCT.TransformIDCT(ref b1); Block8x8F b2 = ReferenceImplementations.AccurateDCT.TransformIDCT(ref b1);

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

@ -70,8 +70,7 @@ public partial class ReferenceImplementationsTests
{ {
float[] floatData = Create8x8RandomFloatData(-1000, 1000); float[] floatData = Create8x8RandomFloatData(-1000, 1000);
Block8x8F source = default; Block8x8F source = Block8x8F.Load(floatData);
source.LoadFrom(floatData);
Block8x8F expected = ReferenceImplementations.AccurateDCT.TransformFDCT(ref source); Block8x8F expected = ReferenceImplementations.AccurateDCT.TransformFDCT(ref source);
Block8x8F actual = ReferenceImplementations.LLM_FloatingPoint_DCT.TransformFDCT_UpscaleBy8(ref source); Block8x8F actual = ReferenceImplementations.LLM_FloatingPoint_DCT.TransformFDCT_UpscaleBy8(ref source);

6
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]; float[] temp = new float[64];
IDCT2D_llm(s, d, temp); IDCT2D_llm(s, d, temp);
Block8x8F result = default; Block8x8F result = Block8x8F.Load(d);
result.LoadFrom(d);
return result; return result;
} }
@ -49,8 +48,7 @@ internal static partial class ReferenceImplementations
float[] temp = new float[64]; float[] temp = new float[64];
FDCT2D_llm(s, d, temp); FDCT2D_llm(s, d, temp);
Block8x8F result = default; Block8x8F result = Block8x8F.Load(d);
result.LoadFrom(d);
return result; return result;
} }

Loading…
Cancel
Save