Browse Source

more cleanup + more tests

af/merge-core
Anton Firszov 9 years ago
parent
commit
63e574cdb2
  1. 3
      src/ImageSharp/Formats/Jpeg/Common/Block8x8F.Generated.cs
  2. 1
      src/ImageSharp/Formats/Jpeg/Common/Block8x8F.Generated.tt
  3. 2
      src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs
  4. 2
      src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegBlockPostProcessor.cs
  5. 68
      src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegColorConverter.FromYCbCr.cs
  6. 28
      tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs

3
src/ImageSharp/Formats/Jpeg/Common/Block8x8F.Generated.cs

@ -146,6 +146,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
ref Vector<float> row7 = ref Unsafe.As<Vector4, Vector<float>>(ref this.V7L);
row7 = NormalizeAndRound(row7, off, max);
}
}
}
}

1
src/ImageSharp/Formats/Jpeg/Common/Block8x8F.Generated.tt

@ -96,6 +96,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
<#
}
#>
}
}
}

2
src/ImageSharp/Formats/Jpeg/Common/Block8x8F.cs

@ -241,7 +241,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common
/// </summary>
/// <param name="dest">Destination</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe void CopyTo(Span<float> dest)
public void CopyTo(Span<float> dest)
{
ref byte d = ref Unsafe.As<float, byte>(ref dest.DangerousGetPinnableReference());
ref byte s = ref Unsafe.As<Block8x8F, byte>(ref this);

2
src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegBlockPostProcessor.cs

@ -11,7 +11,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder
/// Encapsulates the implementation of processing "raw" <see cref="Buffer{T}"/>-s into Jpeg image channels.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct JpegBlockPostProcessor
internal struct JpegBlockPostProcessor
{
/// <summary>
/// Source block

68
src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegColorConverter.FromYCbCr.cs

@ -1,6 +1,7 @@
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Common.Tuples;
namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder
{
@ -124,9 +125,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder
if (Vector<float>.Count == 4)
{
// TODO: Find a way to properly run & test this path on AVX2 PC-s! (Have I already mentioned that Vector<T> is terrible?)
r.RoundAndDownscaleBasic();
g.RoundAndDownscaleBasic();
b.RoundAndDownscaleBasic();
r.RoundAndDownscalePreAvx2();
g.RoundAndDownscalePreAvx2();
b.RoundAndDownscalePreAvx2();
}
else if (SimdUtils.IsAvx2CompatibleArchitecture)
{
@ -147,67 +148,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder
}
}
/// <summary>
/// Its faster to process multiple Vector4-s together
/// </summary>
private struct Vector4Pair
{
public Vector4 A;
public Vector4 B;
private static readonly Vector4 Scale = new Vector4(1 / 255f);
private static readonly Vector4 Half = new Vector4(0.5f);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RoundAndDownscaleBasic()
{
ref Vector<float> a = ref Unsafe.As<Vector4, Vector<float>>(ref this.A);
a = a.FastRound();
ref Vector<float> b = ref Unsafe.As<Vector4, Vector<float>>(ref this.B);
b = b.FastRound();
// Downscale by 1/255
this.A *= Scale;
this.B *= Scale;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void RoundAndDownscaleAvx2()
{
ref Vector<float> self = ref Unsafe.As<Vector4Pair, Vector<float>>(ref this);
Vector<float> v = self;
v = v.FastRound();
// Downscale by 1/255
v *= new Vector<float>(1 / 255f);
self = v;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void MultiplyInplace(float value)
{
this.A *= value;
this.B *= value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AddInplace(Vector4 value)
{
this.A += value;
this.B += value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AddInplace(ref Vector4Pair other)
{
this.A += other.A;
this.B += other.B;
}
}
private struct Vector4Octet
{
#pragma warning disable SA1132 // Do not combine fields

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

@ -32,6 +32,16 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
{
}
private bool SkipOnNonAvx2Runner()
{
if (!SimdUtils.IsAvx2CompatibleArchitecture)
{
this.Output.WriteLine("AVX2 not supported, skipping!");
return true;
}
return false;
}
[Fact]
public void Indexer()
{
@ -263,9 +273,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[InlineData(2)]
public void NormalizeColorsAndRoundAvx2(int seed)
{
if (!SimdUtils.IsAvx2CompatibleArchitecture)
if (this.SkipOnNonAvx2Runner())
{
this.Output.WriteLine("AVX2 not supported, skipping!");
return;
}
@ -283,6 +292,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
this.CompareBlocks(expected, actual, 0);
}
[Theory]
[InlineData(1)]
[InlineData(2)]
@ -413,5 +423,19 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
this.CompareBlocks(expected, actual, 0);
}
[Fact]
public void MultiplyInplace_ByScalar()
{
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]);
}
}
}
}
Loading…
Cancel
Save