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); ref Vector<float> row7 = ref Unsafe.As<Vector4, Vector<float>>(ref this.V7L);
row7 = NormalizeAndRound(row7, off, max); 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> /// </summary>
/// <param name="dest">Destination</param> /// <param name="dest">Destination</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [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 d = ref Unsafe.As<float, byte>(ref dest.DangerousGetPinnableReference());
ref byte s = ref Unsafe.As<Block8x8F, byte>(ref this); 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. /// Encapsulates the implementation of processing "raw" <see cref="Buffer{T}"/>-s into Jpeg image channels.
/// </summary> /// </summary>
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
internal unsafe struct JpegBlockPostProcessor internal struct JpegBlockPostProcessor
{ {
/// <summary> /// <summary>
/// Source block /// Source block

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

@ -1,6 +1,7 @@
using System; using System;
using System.Numerics; using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Common.Tuples;
namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder
{ {
@ -124,9 +125,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Common.Decoder
if (Vector<float>.Count == 4) 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?) // 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(); r.RoundAndDownscalePreAvx2();
g.RoundAndDownscaleBasic(); g.RoundAndDownscalePreAvx2();
b.RoundAndDownscaleBasic(); b.RoundAndDownscalePreAvx2();
} }
else if (SimdUtils.IsAvx2CompatibleArchitecture) 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 private struct Vector4Octet
{ {
#pragma warning disable SA1132 // Do not combine fields #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] [Fact]
public void Indexer() public void Indexer()
{ {
@ -263,9 +273,8 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[InlineData(2)] [InlineData(2)]
public void NormalizeColorsAndRoundAvx2(int seed) public void NormalizeColorsAndRoundAvx2(int seed)
{ {
if (!SimdUtils.IsAvx2CompatibleArchitecture) if (this.SkipOnNonAvx2Runner())
{ {
this.Output.WriteLine("AVX2 not supported, skipping!");
return; return;
} }
@ -283,6 +292,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
this.CompareBlocks(expected, actual, 0); this.CompareBlocks(expected, actual, 0);
} }
[Theory] [Theory]
[InlineData(1)] [InlineData(1)]
[InlineData(2)] [InlineData(2)]
@ -413,5 +423,19 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
this.CompareBlocks(expected, actual, 0); 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