Browse Source

Add missing Non-SIMD implementation

pull/784/head
Stephan Vedder 8 years ago
parent
commit
5ef3f19c1f
  1. 5
      src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs
  2. 5
      src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt
  3. 10
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs
  4. 3
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs
  5. 12
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs
  6. 6
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/YCbCrColorConversion.cs

5
src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs

@ -1,6 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
@ -96,7 +97,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
{
Vector4 CMin4 = new Vector4(0F);
Vector4 CMax4 = new Vector4(maximum);
Vector4 COff4 = new Vector4(maximum/2 + 1);
Vector4 COff4 = new Vector4((float)Math.Ceiling(maximum/2));
this.V0L = Vector4.Clamp(this.V0L + COff4, CMin4, CMax4);
this.V0R = Vector4.Clamp(this.V0R + COff4, CMin4, CMax4);
@ -122,7 +123,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
[MethodImpl(InliningOptions.ShortMethod)]
public void NormalizeColorsAndRoundInplaceAvx2(float maximum)
{
Vector<float> off = new Vector<float>(maximum/2 +1);
Vector<float> off = new Vector<float>((float)Math.Ceiling(maximum/2));
Vector<float> max = new Vector<float>(maximum);
ref Vector<float> row0 = ref Unsafe.As<Vector4, Vector<float>>(ref this.V0L);

5
src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt

@ -11,6 +11,7 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
@ -61,7 +62,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
{
Vector4 CMin4 = new Vector4(0F);
Vector4 CMax4 = new Vector4(maximum);
Vector4 COff4 = new Vector4(maximum/2 + 1);
Vector4 COff4 = new Vector4((float)Math.Ceiling(maximum/2));
<#
@ -85,7 +86,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
[MethodImpl(InliningOptions.ShortMethod)]
public void NormalizeColorsAndRoundInplaceAvx2(float maximum)
{
Vector<float> off = new Vector<float>(maximum/2 +1);
Vector<float> off = new Vector<float>((float)Math.Ceiling(maximum/2));
Vector<float> max = new Vector<float>(maximum);
<#

10
src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs

@ -17,10 +17,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
public override void ConvertToRgba(in ComponentValues values, Span<Vector4> result)
{
ConvertCore(values, result);
ConvertCore(values, result, this.MaximumValue, this.HalfValue);
}
internal static void ConvertCore(in ComponentValues values, Span<Vector4> result)
internal static void ConvertCore(in ComponentValues values, Span<Vector4> result, float maxValue, float halfValue)
{
// TODO: We can optimize a lot here with Vector<float> and SRCS.Unsafe()!
ReadOnlySpan<float> yVals = values.Component0;
@ -29,13 +29,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
var v = new Vector4(0, 0, 0, 1);
var scale = new Vector4(1 / 255F, 1 / 255F, 1 / 255F, 1F);
var scale = new Vector4(1 / maxValue, 1 / maxValue, 1 / maxValue, 1F);
for (int i = 0; i < result.Length; i++)
{
float y = yVals[i];
float cb = cbVals[i] - 128F;
float cr = crVals[i] - 128F;
float cb = cbVals[i] - halfValue;
float cr = crVals[i] - halfValue;
v.X = MathF.Round(y + (1.402F * cr), MidpointRounding.AwayFromZero);
v.Y = MathF.Round(y - (0.344136F * cb) - (0.714136F * cr), MidpointRounding.AwayFromZero);

3
src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs

@ -28,7 +28,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
ConvertCore(values.Slice(0, simdCount), result.Slice(0, simdCount), this.MaximumValue, this.HalfValue);
}
FromYCbCrBasic.ConvertCore(values.Slice(simdCount, remainder), result.Slice(simdCount, remainder));
FromYCbCrBasic.ConvertCore(values.Slice(simdCount, remainder), result.Slice(simdCount, remainder),
this.MaximumValue, this.HalfValue);
}
/// <summary>

12
src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs

@ -28,16 +28,18 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
int simdCount = result.Length - remainder;
if (simdCount > 0)
{
ConvertCore(values.Slice(0, simdCount), result.Slice(0, simdCount));
ConvertCore(values.Slice(0, simdCount), result.Slice(0, simdCount),
this.MaximumValue, this.HalfValue);
}
FromYCbCrBasic.ConvertCore(values.Slice(simdCount, remainder), result.Slice(simdCount, remainder));
FromYCbCrBasic.ConvertCore(values.Slice(simdCount, remainder), result.Slice(simdCount, remainder),
this.MaximumValue, this.HalfValue);;
}
/// <summary>
/// SIMD convert using buffers of sizes divisible by 8.
/// </summary>
internal static void ConvertCore(in ComponentValues values, Span<Vector4> result)
internal static void ConvertCore(in ComponentValues values, Span<Vector4> result, float maxValue, float halfValue)
{
// This implementation is actually AVX specific.
// An AVX register is capable of storing 8 float-s.
@ -57,7 +59,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
ref Vector4Octet resultBase =
ref Unsafe.As<Vector4, Vector4Octet>(ref MemoryMarshal.GetReference(result));
var chromaOffset = new Vector<float>(-128f);
var chromaOffset = new Vector<float>(-halfValue);
// Walking 8 elements at one step:
int n = result.Length / 8;
@ -70,7 +72,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
ref Vector<float> ggRefAsVector = ref Unsafe.As<Vector4Pair, Vector<float>>(ref gg);
ref Vector<float> bbRefAsVector = ref Unsafe.As<Vector4Pair, Vector<float>>(ref bb);
var scale = new Vector<float>(1 / 255f);
var scale = new Vector<float>(1 / maxValue);
for (int i = 0; i < n; i++)
{

6
tests/ImageSharp.Benchmarks/Codecs/Jpeg/YCbCrColorConversion.cs

@ -41,7 +41,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
{
var values = new JpegColorConverter.ComponentValues(this.input, 0);
JpegColorConverter.FromYCbCrBasic.ConvertCore(values, this.output);
JpegColorConverter.FromYCbCrBasic.ConvertCore(values, this.output, 255F, 128F);
}
[Benchmark]
@ -49,7 +49,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
{
var values = new JpegColorConverter.ComponentValues(this.input, 0);
JpegColorConverter.FromYCbCrSimd.ConvertCore(values, this.output);
JpegColorConverter.FromYCbCrSimd.ConvertCore(values, this.output, 255F, 128F);
}
[Benchmark]
@ -57,7 +57,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
{
var values = new JpegColorConverter.ComponentValues(this.input, 0);
JpegColorConverter.FromYCbCrSimdAvx2.ConvertCore(values, this.output);
JpegColorConverter.FromYCbCrSimdAvx2.ConvertCore(values, this.output, 255F, 128F);
}
private static Buffer2D<float>[] CreateRandomValues(

Loading…
Cancel
Save