Browse Source

Base implementation for new converters

pull/1864/head
Dmitry Pentin 5 years ago
parent
commit
7617b38fec
  1. 18
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.Avx2JpegColorConverter.cs
  2. 18
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.BasicJpegColorConverter.cs
  3. 28
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx.cs
  4. 9
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykScalar.cs
  5. 25
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykVector8.cs
  6. 22
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleAvx.cs
  7. 53
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleBasic.cs
  8. 34
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleScalar.cs
  9. 38
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleVector8.cs
  10. 28
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbAvx.cs
  11. 32
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbBasic.cs
  12. 26
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbScalar.cs
  13. 11
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbVector8.cs
  14. 33
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrAvx.cs
  15. 42
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs
  16. 50
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrScalar.cs
  17. 88
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector4.cs
  18. 22
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector8.cs
  19. 30
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKAvx.cs
  20. 13
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKScalar.cs
  21. 28
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKVector8.cs
  22. 18
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.Vector8JpegColorConverter.cs
  23. 32
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverterAvx.cs
  24. 104
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverterBase.cs
  25. 22
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverterScalar.cs
  26. 27
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverterVector.cs
  27. 2
      src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter.cs
  28. 4
      src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs
  29. 2
      src/ImageSharp/Formats/Tiff/Compression/Decompressors/RgbJpegSpectralConverter.cs
  30. 12
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/CmykColorConversion.cs
  31. 8
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/GrayscaleColorConversion.cs
  32. 12
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/RgbColorConversion.cs
  33. 16
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/YCbCrColorConversion.cs
  34. 12
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/YccKColorConverter.cs
  35. 76
      tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs

18
src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.Avx2JpegColorConverter.cs

@ -1,18 +0,0 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
internal abstract partial class JpegColorConverter
{
internal abstract class Avx2JpegColorConverter : VectorizedJpegColorConverter
{
protected Avx2JpegColorConverter(JpegColorSpace colorSpace, int precision)
: base(colorSpace, precision, 8)
{
}
protected sealed override bool IsAvailable => SimdUtils.HasAvx2;
}
}
}

18
src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.BasicJpegColorConverter.cs

@ -1,18 +0,0 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
internal abstract partial class JpegColorConverter
{
internal abstract class BasicJpegColorConverter : JpegColorConverter
{
protected BasicJpegColorConverter(JpegColorSpace colorSpace, int precision)
: base(colorSpace, precision)
{
}
protected override bool IsAvailable => true;
}
}
}

28
src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx2.cs → src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx.cs

@ -1,38 +1,33 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
#if SUPPORTS_RUNTIME_INTRINSICS
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
#if SUPPORTS_RUNTIME_INTRINSICS
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
using static SixLabors.ImageSharp.SimdUtils;
#endif
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
internal abstract partial class JpegColorConverter
internal abstract partial class JpegColorConverterBase
{
internal sealed class FromCmykAvx2 : Avx2JpegColorConverter
internal sealed class FromCmykAvx : AvxColorConverter
{
public FromCmykAvx2(int precision)
public FromCmykAvx(int precision)
: base(JpegColorSpace.Cmyk, precision)
{
}
protected override void ConvertCoreVectorizedInplace(in ComponentValues values)
public override void ConvertToRgbInplace(in ComponentValues values)
{
#if SUPPORTS_RUNTIME_INTRINSICS
ref Vector256<float> c0Base =
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component0));
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component0));
ref Vector256<float> c1Base =
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component1));
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component1));
ref Vector256<float> c2Base =
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component2));
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component2));
ref Vector256<float> c3Base =
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component3));
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component3));
// Used for the color conversion
var scale = Vector256.Create(1 / this.MaximumValue);
@ -50,11 +45,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
m = Avx.Multiply(Avx.Multiply(m, k), scale);
y = Avx.Multiply(Avx.Multiply(y, k), scale);
}
#endif
}
protected override void ConvertCoreInplace(in ComponentValues values) =>
FromCmykBasic.ConvertCoreInplace(values, this.MaximumValue);
}
}
}
#endif

9
src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykBasic.cs → src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykScalar.cs

@ -1,16 +1,15 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
internal abstract partial class JpegColorConverter
internal abstract partial class JpegColorConverterBase
{
internal sealed class FromCmykBasic : BasicJpegColorConverter
internal sealed class FromCmykScalar : ScalarJpegColorConverter
{
public FromCmykBasic(int precision)
public FromCmykScalar(int precision)
: base(JpegColorSpace.Cmyk, precision)
{
}

25
src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykVector8.cs

@ -1,17 +1,15 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Tuples;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
internal abstract partial class JpegColorConverter
internal abstract partial class JpegColorConverterBase
{
internal sealed class FromCmykVector8 : Vector8JpegColorConverter
internal sealed class FromCmykVector8 : VectorizedJpegColorConverter
{
public FromCmykVector8(int precision)
: base(JpegColorSpace.Cmyk, precision)
@ -21,17 +19,16 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
protected override void ConvertCoreVectorizedInplace(in ComponentValues values)
{
ref Vector<float> cBase =
ref Unsafe.As<float, Vector<float>>(ref MemoryMarshal.GetReference(values.Component0));
ref Unsafe.As<float, Vector<float>>(ref MemoryMarshal.GetReference(values.Component0));
ref Vector<float> mBase =
ref Unsafe.As<float, Vector<float>>(ref MemoryMarshal.GetReference(values.Component1));
ref Unsafe.As<float, Vector<float>>(ref MemoryMarshal.GetReference(values.Component1));
ref Vector<float> yBase =
ref Unsafe.As<float, Vector<float>>(ref MemoryMarshal.GetReference(values.Component2));
ref Unsafe.As<float, Vector<float>>(ref MemoryMarshal.GetReference(values.Component2));
ref Vector<float> kBase =
ref Unsafe.As<float, Vector<float>>(ref MemoryMarshal.GetReference(values.Component3));
ref Unsafe.As<float, Vector<float>>(ref MemoryMarshal.GetReference(values.Component3));
var scale = new Vector<float>(1 / this.MaximumValue);
// Walking 8 elements at one step:
nint n = values.Component0.Length / 8;
for (nint i = 0; i < n; i++)
{
@ -40,14 +37,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
ref Vector<float> y = ref Unsafe.Add(ref yBase, i);
Vector<float> k = Unsafe.Add(ref kBase, i) * scale;
c = (c * k) * scale;
m = (m * k) * scale;
y = (y * k) * scale;
c = c * k * scale;
m = m * k * scale;
y = y * k * scale;
}
}
protected override void ConvertCoreInplace(in ComponentValues values) =>
FromCmykBasic.ConvertCoreInplace(values, this.MaximumValue);
FromCmykScalar.ConvertCoreInplace(values, this.MaximumValue);
}
}
}

22
src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleAvx2.cs → src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleAvx.cs

@ -1,30 +1,25 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
#if SUPPORTS_RUNTIME_INTRINSICS
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
#if SUPPORTS_RUNTIME_INTRINSICS
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
using static SixLabors.ImageSharp.SimdUtils;
#endif
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
internal abstract partial class JpegColorConverter
internal abstract partial class JpegColorConverterBase
{
internal sealed class FromGrayscaleAvx2 : Avx2JpegColorConverter
internal sealed class FromGrayscaleAvx : AvxColorConverter
{
public FromGrayscaleAvx2(int precision)
public FromGrayscaleAvx(int precision)
: base(JpegColorSpace.Grayscale, precision)
{
}
protected override void ConvertCoreVectorizedInplace(in ComponentValues values)
public override void ConvertToRgbInplace(in ComponentValues values)
{
#if SUPPORTS_RUNTIME_INTRINSICS
ref Vector256<float> c0Base =
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component0));
@ -37,11 +32,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
ref Vector256<float> c0 = ref Unsafe.Add(ref c0Base, i);
c0 = Avx.Multiply(c0, scale);
}
#endif
}
protected override void ConvertCoreInplace(in ComponentValues values) =>
FromGrayscaleBasic.ScaleValues(values.Component0, this.MaximumValue);
}
}
}
#endif

53
src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleBasic.cs

@ -1,53 +0,0 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
internal abstract partial class JpegColorConverter
{
internal sealed class FromGrayscaleBasic : BasicJpegColorConverter
{
public FromGrayscaleBasic(int precision)
: base(JpegColorSpace.Grayscale, precision)
{
}
public override void ConvertToRgbInplace(in ComponentValues values) =>
ScaleValues(values.Component0, this.MaximumValue);
internal static void ScaleValues(Span<float> values, float maxValue)
{
Span<Vector4> vecValues = MemoryMarshal.Cast<float, Vector4>(values);
var scaleVector = new Vector4(1 / maxValue);
for (int i = 0; i < vecValues.Length; i++)
{
vecValues[i] *= scaleVector;
}
values = values.Slice(vecValues.Length * 4);
if (!values.IsEmpty)
{
float scaleValue = 1f / maxValue;
values[0] *= scaleValue;
if ((uint)values.Length > 1)
{
values[1] *= scaleValue;
if ((uint)values.Length > 2)
{
values[2] *= scaleValue;
}
}
}
}
}
}
}

34
src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleScalar.cs

@ -0,0 +1,34 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
internal abstract partial class JpegColorConverterBase
{
internal sealed class FromGrayscaleScalar : ScalarJpegColorConverter
{
public FromGrayscaleScalar(int precision)
: base(JpegColorSpace.Grayscale, precision)
{
}
public override void ConvertToRgbInplace(in ComponentValues values) =>
ConvertCoreInplace(values.Component0, this.MaximumValue);
internal static void ConvertCoreInplace(Span<float> values, float maxValue)
{
ref float valuesRef = ref MemoryMarshal.GetReference(values);
float scale = 1 / maxValue;
for (nint i = 0; i < values.Length; i++)
{
Unsafe.Add(ref valuesRef, i) *= scale;
}
}
}
}
}

38
src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleVector8.cs

@ -0,0 +1,38 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
internal abstract partial class JpegColorConverterBase
{
internal sealed class FromGrayScaleVector8 : VectorizedJpegColorConverter
{
public FromGrayScaleVector8(int precision)
: base(JpegColorSpace.Grayscale, precision)
{
}
protected override void ConvertCoreVectorizedInplace(in ComponentValues values)
{
ref Vector<float> cBase =
ref Unsafe.As<float, Vector<float>>(ref MemoryMarshal.GetReference(values.Component0));
var scale = new Vector<float>(1 / this.MaximumValue);
nint n = values.Component0.Length / 8;
for (nint i = 0; i < n; i++)
{
ref Vector<float> c0 = ref Unsafe.Add(ref cBase, i);
c0 *= scale;
}
}
protected override void ConvertCoreInplace(in ComponentValues values) =>
FromGrayscaleScalar.ConvertCoreInplace(values.Component0, this.MaximumValue);
}
}
}

28
src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbAvx2.cs → src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbAvx.cs

@ -1,36 +1,31 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
#if SUPPORTS_RUNTIME_INTRINSICS
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
#if SUPPORTS_RUNTIME_INTRINSICS
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
using static SixLabors.ImageSharp.SimdUtils;
#endif
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
internal abstract partial class JpegColorConverter
internal abstract partial class JpegColorConverterBase
{
internal sealed class FromRgbAvx2 : Avx2JpegColorConverter
internal sealed class FromRgbAvx : AvxColorConverter
{
public FromRgbAvx2(int precision)
public FromRgbAvx(int precision)
: base(JpegColorSpace.RGB, precision)
{
}
protected override void ConvertCoreVectorizedInplace(in ComponentValues values)
public override void ConvertToRgbInplace(in ComponentValues values)
{
#if SUPPORTS_RUNTIME_INTRINSICS
ref Vector256<float> rBase =
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component0));
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component0));
ref Vector256<float> gBase =
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component1));
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component1));
ref Vector256<float> bBase =
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component2));
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component2));
// Used for the color conversion
var scale = Vector256.Create(1 / this.MaximumValue);
@ -44,11 +39,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
g = Avx.Multiply(g, scale);
b = Avx.Multiply(b, scale);
}
#endif
}
protected override void ConvertCoreInplace(in ComponentValues values) =>
FromRgbBasic.ConvertCoreInplace(values, this.MaximumValue);
}
}
}
#endif

32
src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbBasic.cs

@ -1,32 +0,0 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
using System.Runtime.InteropServices;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
internal abstract partial class JpegColorConverter
{
internal sealed class FromRgbBasic : BasicJpegColorConverter
{
public FromRgbBasic(int precision)
: base(JpegColorSpace.RGB, precision)
{
}
public override void ConvertToRgbInplace(in ComponentValues values)
{
ConvertCoreInplace(values, this.MaximumValue);
}
internal static void ConvertCoreInplace(ComponentValues values, float maxValue)
{
FromGrayscaleBasic.ScaleValues(values.Component0, maxValue);
FromGrayscaleBasic.ScaleValues(values.Component1, maxValue);
FromGrayscaleBasic.ScaleValues(values.Component2, maxValue);
}
}
}
}

26
src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbScalar.cs

@ -0,0 +1,26 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
internal abstract partial class JpegColorConverterBase
{
internal sealed class FromRgbScalar : ScalarJpegColorConverter
{
public FromRgbScalar(int precision)
: base(JpegColorSpace.RGB, precision)
{
}
public override void ConvertToRgbInplace(in ComponentValues values) =>
ConvertCoreInplace(values, this.MaximumValue);
internal static void ConvertCoreInplace(ComponentValues values, float maxValue)
{
FromGrayscaleScalar.ConvertCoreInplace(values.Component0, maxValue);
FromGrayscaleScalar.ConvertCoreInplace(values.Component1, maxValue);
FromGrayscaleScalar.ConvertCoreInplace(values.Component2, maxValue);
}
}
}
}

11
src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbVector8.cs

@ -1,17 +1,15 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Tuples;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
internal abstract partial class JpegColorConverter
internal abstract partial class JpegColorConverterBase
{
internal sealed class FromRgbVector8 : Vector8JpegColorConverter
internal sealed class FromRgbVector8 : VectorizedJpegColorConverter
{
public FromRgbVector8(int precision)
: base(JpegColorSpace.RGB, precision)
@ -29,7 +27,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
var scale = new Vector<float>(1 / this.MaximumValue);
// Walking 8 elements at one step:
nint n = values.Component0.Length / 8;
for (nint i = 0; i < n; i++)
{
@ -43,7 +40,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
}
protected override void ConvertCoreInplace(in ComponentValues values) =>
FromRgbBasic.ConvertCoreInplace(values, this.MaximumValue);
FromRgbScalar.ConvertCoreInplace(values, this.MaximumValue);
}
}
}

33
src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrAvx2.cs → src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrAvx.cs

@ -1,31 +1,27 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
#if SUPPORTS_RUNTIME_INTRINSICS
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
#if SUPPORTS_RUNTIME_INTRINSICS
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
using static SixLabors.ImageSharp.SimdUtils;
#endif
// ReSharper disable ImpureMethodCallOnReadonlyValueField
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
internal abstract partial class JpegColorConverter
internal abstract partial class JpegColorConverterBase
{
internal sealed class FromYCbCrAvx2 : Avx2JpegColorConverter
internal sealed class FromYCbCrAvx : AvxColorConverter
{
public FromYCbCrAvx2(int precision)
public FromYCbCrAvx(int precision)
: base(JpegColorSpace.YCbCr, precision)
{
}
protected override void ConvertCoreVectorizedInplace(in ComponentValues values)
public override void ConvertToRgbInplace(in ComponentValues values)
{
#if SUPPORTS_RUNTIME_INTRINSICS
ref Vector256<float> c0Base =
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component0));
ref Vector256<float> c1Base =
@ -36,15 +32,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
// Used for the color conversion
var chromaOffset = Vector256.Create(-this.HalfValue);
var scale = Vector256.Create(1 / this.MaximumValue);
var rCrMult = Vector256.Create(1.402F);
var gCbMult = Vector256.Create(-0.344136F);
var gCrMult = Vector256.Create(-0.714136F);
var bCbMult = Vector256.Create(1.772F);
// Used for packing.
var va = Vector256.Create(1F);
ref byte control = ref MemoryMarshal.GetReference(HwIntrinsics.PermuteMaskEvenOdd8x32);
Vector256<int> vcontrol = Unsafe.As<byte, Vector256<int>>(ref control);
var rCrMult = Vector256.Create(FromYCbCrScalar.RCrMult);
var gCbMult = Vector256.Create(-FromYCbCrScalar.GCbMult);
var gCrMult = Vector256.Create(-FromYCbCrScalar.GCrMult);
var bCbMult = Vector256.Create(FromYCbCrScalar.BCbMult);
// Walking 8 elements at one step:
nint n = values.Component0.Length / 8;
@ -64,7 +55,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
// r = y + (1.402F * cr);
// g = y - (0.344136F * cb) - (0.714136F * cr);
// b = y + (1.772F * cb);
// Adding & multiplying 8 elements at one time:
Vector256<float> r = HwIntrinsics.MultiplyAdd(y, cr, rCrMult);
Vector256<float> g = HwIntrinsics.MultiplyAdd(HwIntrinsics.MultiplyAdd(y, cb, gCbMult), cr, gCrMult);
Vector256<float> b = HwIntrinsics.MultiplyAdd(y, cb, bCbMult);
@ -77,11 +67,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
c1 = g;
c2 = b;
}
#endif
}
protected override void ConvertCoreInplace(in ComponentValues values) =>
FromYCbCrBasic.ConvertCoreInplace(values, this.MaximumValue, this.HalfValue);
}
}
}
#endif

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

@ -1,42 +0,0 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
internal abstract partial class JpegColorConverter
{
internal sealed class FromYCbCrBasic : BasicJpegColorConverter
{
public FromYCbCrBasic(int precision)
: base(JpegColorSpace.YCbCr, precision)
{
}
public override void ConvertToRgbInplace(in ComponentValues values)
=> ConvertCoreInplace(values, this.MaximumValue, this.HalfValue);
internal static void ConvertCoreInplace(in ComponentValues values, float maxValue, float halfValue)
{
Span<float> c0 = values.Component0;
Span<float> c1 = values.Component1;
Span<float> c2 = values.Component2;
var scale = 1 / maxValue;
for (int i = 0; i < c0.Length; i++)
{
float y = c0[i];
float cb = c1[i] - halfValue;
float cr = c2[i] - halfValue;
c0[i] = MathF.Round(y + (1.402F * cr), MidpointRounding.AwayFromZero) * scale;
c1[i] = MathF.Round(y - (0.344136F * cb) - (0.714136F * cr), MidpointRounding.AwayFromZero) * scale;
c2[i] = MathF.Round(y + (1.772F * cb), MidpointRounding.AwayFromZero) * scale;
}
}
}
}
}

50
src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrScalar.cs

@ -0,0 +1,50 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
internal abstract partial class JpegColorConverterBase
{
internal sealed class FromYCbCrScalar : ScalarJpegColorConverter
{
// TODO: comments, derived from ITU-T Rec. T.871
internal const float RCrMult = 1.402f;
internal const float GCbMult = (float)(0.114 * 1.772 / 0.587);
internal const float GCrMult = (float)(0.299 * 1.402 / 0.587);
internal const float BCbMult = 1.772f;
public FromYCbCrScalar(int precision)
: base(JpegColorSpace.YCbCr, precision)
{
}
public override void ConvertToRgbInplace(in ComponentValues values)
=> ConvertCoreInplace(values, this.MaximumValue, this.HalfValue);
internal static void ConvertCoreInplace(in ComponentValues values, float maxValue, float halfValue)
{
Span<float> c0 = values.Component0;
Span<float> c1 = values.Component1;
Span<float> c2 = values.Component2;
float scale = 1 / maxValue;
for (int i = 0; i < c0.Length; i++)
{
float y = c0[i];
float cb = c1[i] - halfValue;
float cr = c2[i] - halfValue;
// r = y + (1.402F * cr);
// g = y - (0.344136F * cb) - (0.714136F * cr);
// b = y + (1.772F * cb);
c0[i] = MathF.Round(y + (RCrMult * cr), MidpointRounding.AwayFromZero) * scale;
c1[i] = MathF.Round(y - (GCbMult * cb) - (GCrMult * cr), MidpointRounding.AwayFromZero) * scale;
c2[i] = MathF.Round(y + (BCbMult * cb), MidpointRounding.AwayFromZero) * scale;
}
}
}
}
}

88
src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector4.cs

@ -1,88 +0,0 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Tuples;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
internal abstract partial class JpegColorConverter
{
internal sealed class FromYCbCrVector4 : VectorizedJpegColorConverter
{
public FromYCbCrVector4(int precision)
: base(JpegColorSpace.YCbCr, precision, 8)
{
}
protected override bool IsAvailable => SimdUtils.HasVector4;
protected override void ConvertCoreVectorizedInplace(in ComponentValues values)
{
DebugGuard.IsTrue(values.Component0.Length % 8 == 0, nameof(values), "Length should be divisible by 8!");
ref Vector4Pair c0Base =
ref Unsafe.As<float, Vector4Pair>(ref MemoryMarshal.GetReference(values.Component0));
ref Vector4Pair c1Base =
ref Unsafe.As<float, Vector4Pair>(ref MemoryMarshal.GetReference(values.Component1));
ref Vector4Pair c2Base =
ref Unsafe.As<float, Vector4Pair>(ref MemoryMarshal.GetReference(values.Component2));
var chromaOffset = new Vector4(-this.HalfValue);
var maxValue = this.MaximumValue;
// Walking 8 elements at one step:
nint n = values.Component0.Length / 8;
for (nint i = 0; i < n; i++)
{
// y = yVals[i];
ref Vector4Pair c0 = ref Unsafe.Add(ref c0Base, i);
// cb = cbVals[i] - halfValue);
ref Vector4Pair c1 = ref Unsafe.Add(ref c1Base, i);
c1.AddInplace(chromaOffset);
// cr = crVals[i] - halfValue;
ref Vector4Pair c2 = ref Unsafe.Add(ref c2Base, i);
c2.AddInplace(chromaOffset);
// r = y + (1.402F * cr);
Vector4Pair r = c0;
Vector4Pair tmp = c2;
tmp.MultiplyInplace(1.402F);
r.AddInplace(ref tmp);
// g = y - (0.344136F * cb) - (0.714136F * cr);
Vector4Pair g = c0;
tmp = c1;
tmp.MultiplyInplace(-0.344136F);
g.AddInplace(ref tmp);
tmp = c2;
tmp.MultiplyInplace(-0.714136F);
g.AddInplace(ref tmp);
// b = y + (1.772F * cb);
Vector4Pair b = c0;
tmp = c1;
tmp.MultiplyInplace(1.772F);
b.AddInplace(ref tmp);
r.RoundAndDownscalePreVector8(maxValue);
g.RoundAndDownscalePreVector8(maxValue);
b.RoundAndDownscalePreVector8(maxValue);
c0 = r;
c1 = g;
c2 = b;
}
}
protected override void ConvertCoreInplace(in ComponentValues values)
=> FromYCbCrBasic.ConvertCoreInplace(values, this.MaximumValue, this.HalfValue);
}
}
}

22
src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector8.cs

@ -1,18 +1,16 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Tuples;
// ReSharper disable ImpureMethodCallOnReadonlyValueField
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
internal abstract partial class JpegColorConverter
internal abstract partial class JpegColorConverterBase
{
internal sealed class FromYCbCrVector8 : Vector8JpegColorConverter
internal sealed class FromYCbCrVector8 : VectorizedJpegColorConverter
{
public FromYCbCrVector8(int precision)
: base(JpegColorSpace.YCbCr, precision)
@ -30,10 +28,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
var chromaOffset = new Vector<float>(-this.HalfValue);
// Walking 8 elements at one step:
nint n = values.Component0.Length / 8;
var scale = new Vector<float>(1 / this.MaximumValue);
var rCrMult = new Vector<float>(FromYCbCrScalar.RCrMult);
var gCbMult = new Vector<float>(-FromYCbCrScalar.GCbMult);
var gCrMult = new Vector<float>(-FromYCbCrScalar.GCrMult);
var bCbMult = new Vector<float>(FromYCbCrScalar.BCbMult);
nint n = values.Component0.Length / 8;
for (nint i = 0; i < n; i++)
{
// y = yVals[i];
@ -49,10 +50,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
// r = y + (1.402F * cr);
// g = y - (0.344136F * cb) - (0.714136F * cr);
// b = y + (1.772F * cb);
// Adding & multiplying 8 elements at one time:
Vector<float> r = y + (cr * new Vector<float>(1.402F));
Vector<float> g = y - (cb * new Vector<float>(0.344136F)) - (cr * new Vector<float>(0.714136F));
Vector<float> b = y + (cb * new Vector<float>(1.772F));
Vector<float> r = y + (cr * rCrMult);
Vector<float> g = y + (cb * gCbMult) + (cr * gCrMult);
Vector<float> b = y + (cb * bCbMult);
r = r.FastRound();
g = g.FastRound();
@ -68,7 +68,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
}
protected override void ConvertCoreInplace(in ComponentValues values) =>
FromYCbCrBasic.ConvertCoreInplace(values, this.MaximumValue, this.HalfValue);
FromYCbCrScalar.ConvertCoreInplace(values, this.MaximumValue, this.HalfValue);
}
}
}

30
src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKAvx2.cs → src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKAvx.cs

@ -1,30 +1,26 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
#if SUPPORTS_RUNTIME_INTRINSICS
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
#if SUPPORTS_RUNTIME_INTRINSICS
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
using static SixLabors.ImageSharp.SimdUtils;
#endif
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
internal abstract partial class JpegColorConverter
internal abstract partial class JpegColorConverterBase
{
internal sealed class FromYccKAvx2 : Avx2JpegColorConverter
internal sealed class FromYccKAvx : AvxColorConverter
{
public FromYccKAvx2(int precision)
public FromYccKAvx(int precision)
: base(JpegColorSpace.Ycck, precision)
{
}
protected override void ConvertCoreVectorizedInplace(in ComponentValues values)
public override void ConvertToRgbInplace(in ComponentValues values)
{
#if SUPPORTS_RUNTIME_INTRINSICS
ref Vector256<float> c0Base =
ref Unsafe.As<float, Vector256<float>>(ref MemoryMarshal.GetReference(values.Component0));
ref Vector256<float> c1Base =
@ -38,10 +34,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
var chromaOffset = Vector256.Create(-this.HalfValue);
var scale = Vector256.Create(1 / (this.MaximumValue * this.MaximumValue));
var max = Vector256.Create(this.MaximumValue);
var rCrMult = Vector256.Create(1.402F);
var gCbMult = Vector256.Create(-0.344136F);
var gCrMult = Vector256.Create(-0.714136F);
var bCbMult = Vector256.Create(1.772F);
var rCrMult = Vector256.Create(FromYCbCrScalar.RCrMult);
var gCbMult = Vector256.Create(-FromYCbCrScalar.GCbMult);
var gCrMult = Vector256.Create(-FromYCbCrScalar.GCrMult);
var bCbMult = Vector256.Create(FromYCbCrScalar.BCbMult);
// Walking 8 elements at one step:
nint n = values.Component0.Length / 8;
@ -62,7 +58,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
// r = y + (1.402F * cr);
// g = y - (0.344136F * cb) - (0.714136F * cr);
// b = y + (1.772F * cb);
// Adding & multiplying 8 elements at one time:
Vector256<float> r = HwIntrinsics.MultiplyAdd(y, cr, rCrMult);
Vector256<float> g =
HwIntrinsics.MultiplyAdd(HwIntrinsics.MultiplyAdd(y, cb, gCbMult), cr, gCrMult);
@ -80,11 +75,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
c1 = g;
c2 = b;
}
#endif
}
protected override void ConvertCoreInplace(in ComponentValues values) =>
FromYccKBasic.ConvertCoreInplace(values, this.MaximumValue, this.HalfValue);
}
}
}
#endif

13
src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKBasic.cs → src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKScalar.cs

@ -1,16 +1,15 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
internal abstract partial class JpegColorConverter
internal abstract partial class JpegColorConverterBase
{
internal sealed class FromYccKBasic : BasicJpegColorConverter
internal sealed class FromYccKScalar : ScalarJpegColorConverter
{
public FromYccKBasic(int precision)
public FromYccKScalar(int precision)
: base(JpegColorSpace.Ycck, precision)
{
}
@ -25,9 +24,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
Span<float> c2 = values.Component2;
Span<float> c3 = values.Component3;
var v = new Vector4(0, 0, 0, 1F);
var scale = 1 / (maxValue * maxValue);
float scale = 1 / (maxValue * maxValue);
for (int i = 0; i < values.Component0.Length; i++)
{

28
src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKVector8.cs

@ -1,17 +1,15 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Tuples;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
internal abstract partial class JpegColorConverter
internal abstract partial class JpegColorConverterBase
{
internal sealed class FromYccKVector8 : Vector8JpegColorConverter
internal sealed class FromYccKVector8 : VectorizedJpegColorConverter
{
public FromYccKVector8(int precision)
: base(JpegColorSpace.Ycck, precision)
@ -30,13 +28,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
ref Unsafe.As<float, Vector<float>>(ref MemoryMarshal.GetReference(values.Component3));
var chromaOffset = new Vector<float>(-this.HalfValue);
// Walking 8 elements at one step:
nint n = values.Component0.Length / 8;
var scale = new Vector<float>(1 / (this.MaximumValue * this.MaximumValue));
var max = new Vector<float>(this.MaximumValue);
var scale = new Vector<float>(1f) / (max * max);
var rCrMult = new Vector<float>(FromYCbCrScalar.RCrMult);
var gCbMult = new Vector<float>(-FromYCbCrScalar.GCbMult);
var gCrMult = new Vector<float>(-FromYCbCrScalar.GCrMult);
var bCbMult = new Vector<float>(FromYCbCrScalar.BCbMult);
nint n = values.Component0.Length / 8;
for (nint i = 0; i < n; i++)
{
// y = yVals[i];
@ -55,10 +54,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
// r = y + (1.402F * cr);
// g = y - (0.344136F * cb) - (0.714136F * cr);
// b = y + (1.772F * cb);
// Adding & multiplying 8 elements at one time:
Vector<float> r = y + (cr * new Vector<float>(1.402F));
Vector<float> g = y - (cb * new Vector<float>(0.344136F)) - (cr * new Vector<float>(0.714136F));
Vector<float> b = y + (cb * new Vector<float>(1.772F));
Vector<float> r = y + (cr * rCrMult);
Vector<float> g = y + (cb * gCbMult) + (cr * gCrMult);
Vector<float> b = y + (cb * bCbMult);
r = (max - r.FastRound()) * scaledK;
g = (max - g.FastRound()) * scaledK;
@ -71,7 +69,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
}
protected override void ConvertCoreInplace(in ComponentValues values) =>
FromYccKBasic.ConvertCoreInplace(values, this.MaximumValue, this.HalfValue);
FromYccKScalar.ConvertCoreInplace(values, this.MaximumValue, this.HalfValue);
}
}
}

18
src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.Vector8JpegColorConverter.cs

@ -1,18 +0,0 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
internal abstract partial class JpegColorConverter
{
internal abstract class Vector8JpegColorConverter : VectorizedJpegColorConverter
{
protected Vector8JpegColorConverter(JpegColorSpace colorSpace, int precision)
: base(colorSpace, precision, 8)
{
}
protected sealed override bool IsAvailable => SimdUtils.HasVector8;
}
}
}

32
src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverterAvx.cs

@ -0,0 +1,32 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
#if SUPPORTS_RUNTIME_INTRINSICS
using System.Runtime.Intrinsics.X86;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
internal abstract partial class JpegColorConverterBase
{
/// <summary>
/// <see cref="JpegColorConverterBase"/> abstract base for implementations
/// based on <see cref="Avx"/> instructions.
/// </summary>
/// <remarks>
/// Converters of this family would expect input buffers lengths to be
/// divisible by 8 without a remainder.
/// This is guaranteed by real-life data as jpeg stores pixels via 8x8 blocks.
/// DO NOT pass test data of invalid size to these converters as they
/// potentially won't do a bound check and return a false positive result.
/// </remarks>
internal abstract class AvxColorConverter : JpegColorConverterBase
{
protected AvxColorConverter(JpegColorSpace colorSpace, int precision)
: base(colorSpace, precision)
{
}
protected override bool IsAvailable => Avx.IsSupported;
}
}
}
#endif

104
src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs → src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverterBase.cs

@ -4,26 +4,24 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Tuples;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
/// <summary>
/// Encapsulates the conversion of Jpeg channels to RGBA values packed in <see cref="Vector4"/> buffer.
/// Encapsulates the conversion of color channels from jpeg image to RGB channels.
/// </summary>
internal abstract partial class JpegColorConverter
internal abstract partial class JpegColorConverterBase
{
/// <summary>
/// The available converters
/// </summary>
private static readonly JpegColorConverter[] Converters = CreateConverters();
private static readonly JpegColorConverterBase[] Converters = CreateConverters();
/// <summary>
/// Initializes a new instance of the <see cref="JpegColorConverter"/> class.
/// Initializes a new instance of the <see cref="JpegColorConverterBase"/> class.
/// </summary>
protected JpegColorConverter(JpegColorSpace colorSpace, int precision)
protected JpegColorConverterBase(JpegColorSpace colorSpace, int precision)
{
this.ColorSpace = colorSpace;
this.Precision = precision;
@ -32,7 +30,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
}
/// <summary>
/// Gets a value indicating whether this <see cref="JpegColorConverter"/> is available
/// Gets a value indicating whether this <see cref="JpegColorConverterBase"/> is available
/// on the current runtime and CPU architecture.
/// </summary>
protected abstract bool IsAvailable { get; }
@ -58,11 +56,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
private float HalfValue { get; }
/// <summary>
/// Returns the <see cref="JpegColorConverter"/> corresponding to the given <see cref="JpegColorSpace"/>
/// Returns the <see cref="JpegColorConverterBase"/> corresponding to the given <see cref="JpegColorSpace"/>
/// </summary>
public static JpegColorConverter GetConverter(JpegColorSpace colorSpace, int precision)
public static JpegColorConverterBase GetConverter(JpegColorSpace colorSpace, int precision)
{
JpegColorConverter converter = Array.Find(
JpegColorConverterBase converter = Array.Find(
Converters,
c => c.ColorSpace == colorSpace
&& c.Precision == precision);
@ -82,11 +80,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
public abstract void ConvertToRgbInplace(in ComponentValues values);
/// <summary>
/// Returns the <see cref="JpegColorConverter"/>s for all supported colorspaces and precisions.
/// Returns the <see cref="JpegColorConverterBase"/>s for all supported colorspaces and precisions.
/// </summary>
private static JpegColorConverter[] CreateConverters()
private static JpegColorConverterBase[] CreateConverters()
{
var converters = new List<JpegColorConverter>();
var converters = new List<JpegColorConverterBase>();
// 8-bit converters
converters.AddRange(GetYCbCrConverters(8));
@ -106,63 +104,63 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
}
/// <summary>
/// Returns the <see cref="JpegColorConverter"/>s for the YCbCr colorspace.
/// Returns the <see cref="JpegColorConverterBase"/>s for the YCbCr colorspace.
/// </summary>
private static IEnumerable<JpegColorConverter> GetYCbCrConverters(int precision)
private static IEnumerable<JpegColorConverterBase> GetYCbCrConverters(int precision)
{
#if SUPPORTS_RUNTIME_INTRINSICS
yield return new FromYCbCrAvx2(precision);
yield return new FromYCbCrAvx(precision);
#endif
yield return new FromYCbCrVector8(precision);
yield return new FromYCbCrVector4(precision);
yield return new FromYCbCrBasic(precision);
yield return new FromYCbCrScalar(precision);
}
/// <summary>
/// Returns the <see cref="JpegColorConverter"/>s for the YccK colorspace.
/// Returns the <see cref="JpegColorConverterBase"/>s for the YccK colorspace.
/// </summary>
private static IEnumerable<JpegColorConverter> GetYccKConverters(int precision)
private static IEnumerable<JpegColorConverterBase> GetYccKConverters(int precision)
{
#if SUPPORTS_RUNTIME_INTRINSICS
yield return new FromYccKAvx2(precision);
yield return new FromYccKAvx(precision);
#endif
yield return new FromYccKVector8(precision);
yield return new FromYccKBasic(precision);
yield return new FromYccKScalar(precision);
}
/// <summary>
/// Returns the <see cref="JpegColorConverter"/>s for the CMYK colorspace.
/// Returns the <see cref="JpegColorConverterBase"/>s for the CMYK colorspace.
/// </summary>
private static IEnumerable<JpegColorConverter> GetCmykConverters(int precision)
private static IEnumerable<JpegColorConverterBase> GetCmykConverters(int precision)
{
#if SUPPORTS_RUNTIME_INTRINSICS
yield return new FromCmykAvx2(precision);
yield return new FromCmykAvx(precision);
#endif
yield return new FromCmykVector8(precision);
yield return new FromCmykBasic(precision);
yield return new FromCmykScalar(precision);
}
/// <summary>
/// Returns the <see cref="JpegColorConverter"/>s for the gray scale colorspace.
/// Returns the <see cref="JpegColorConverterBase"/>s for the gray scale colorspace.
/// </summary>
private static IEnumerable<JpegColorConverter> GetGrayScaleConverters(int precision)
private static IEnumerable<JpegColorConverterBase> GetGrayScaleConverters(int precision)
{
#if SUPPORTS_RUNTIME_INTRINSICS
yield return new FromGrayscaleAvx2(precision);
yield return new FromGrayscaleAvx(precision);
#endif
yield return new FromGrayscaleBasic(precision);
yield return new FromGrayScaleVector8(precision);
yield return new FromGrayscaleScalar(precision);
}
/// <summary>
/// Returns the <see cref="JpegColorConverter"/>s for the RGB colorspace.
/// Returns the <see cref="JpegColorConverterBase"/>s for the RGB colorspace.
/// </summary>
private static IEnumerable<JpegColorConverter> GetRgbConverters(int precision)
private static IEnumerable<JpegColorConverterBase> GetRgbConverters(int precision)
{
#if SUPPORTS_RUNTIME_INTRINSICS
yield return new FromRgbAvx2(precision);
yield return new FromRgbAvx(precision);
#endif
yield return new FromRgbVector8(precision);
yield return new FromRgbBasic(precision);
yield return new FromRgbScalar(precision);
}
/// <summary>
@ -200,35 +198,39 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
/// <summary>
/// Initializes a new instance of the <see cref="ComponentValues"/> struct.
/// </summary>
/// <param name="componentProcessors">The 1-4 sized list of component post processors.</param>
/// <param name="row">The row to convert</param>
public ComponentValues(IReadOnlyList<JpegComponentPostProcessor> componentProcessors, int row)
/// <param name="componentBuffers">List of component buffers.</param>
/// <param name="row">Row to convert</param>
public ComponentValues(IReadOnlyList<Buffer2D<float>> componentBuffers, int row)
{
this.ComponentCount = componentProcessors.Count;
DebugGuard.MustBeGreaterThan(componentBuffers.Count, 0, nameof(componentBuffers));
this.ComponentCount = componentBuffers.Count;
this.Component0 = componentProcessors[0].GetColorBufferRowSpan(row);
this.Component0 = componentBuffers[0].GetRowSpan(row);
// In case of grayscale, Component1 and Component2 point to Component0 memory area
this.Component1 = this.ComponentCount > 1 ? componentProcessors[1].GetColorBufferRowSpan(row) : this.Component0;
this.Component2 = this.ComponentCount > 2 ? componentProcessors[2].GetColorBufferRowSpan(row) : this.Component0;
this.Component3 = this.ComponentCount > 3 ? componentProcessors[3].GetColorBufferRowSpan(row) : Span<float>.Empty;
this.Component1 = this.ComponentCount > 1 ? componentBuffers[1].GetRowSpan(row) : this.Component0;
this.Component2 = this.ComponentCount > 2 ? componentBuffers[2].GetRowSpan(row) : this.Component0;
this.Component3 = this.ComponentCount > 3 ? componentBuffers[3].GetRowSpan(row) : Span<float>.Empty;
}
/// <summary>
/// Initializes a new instance of the <see cref="ComponentValues"/> struct.
/// </summary>
/// <param name="componentBuffers">The 1-4 sized list of component buffers.</param>
/// <param name="row">The row to convert</param>
public ComponentValues(IReadOnlyList<Buffer2D<float>> componentBuffers, int row)
/// <param name="processors">List of component color processors.</param>
/// <param name="row">Row to convert</param>
public ComponentValues(IReadOnlyList<JpegComponentPostProcessor> processors, int row)
{
this.ComponentCount = componentBuffers.Count;
DebugGuard.MustBeGreaterThan(processors.Count, 0, nameof(processors));
this.Component0 = componentBuffers[0].GetRowSpan(row);
this.ComponentCount = processors.Count;
this.Component0 = processors[0].ColorBuffer.GetRowSpan(row);
// In case of grayscale, Component1 and Component2 point to Component0 memory area
this.Component1 = this.ComponentCount > 1 ? componentBuffers[1].GetRowSpan(row) : this.Component0;
this.Component2 = this.ComponentCount > 2 ? componentBuffers[2].GetRowSpan(row) : this.Component0;
this.Component3 = this.ComponentCount > 3 ? componentBuffers[3].GetRowSpan(row) : Span<float>.Empty;
this.Component1 = this.ComponentCount > 1 ? processors[1].ColorBuffer.GetRowSpan(row) : this.Component0;
this.Component2 = this.ComponentCount > 2 ? processors[2].ColorBuffer.GetRowSpan(row) : this.Component0;
this.Component3 = this.ComponentCount > 3 ? processors[3].ColorBuffer.GetRowSpan(row) : Span<float>.Empty;
}
internal ComponentValues(

22
src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverterScalar.cs

@ -0,0 +1,22 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
internal abstract partial class JpegColorConverterBase
{
/// <summary>
/// <see cref="JpegColorConverterBase"/> abstract base for implementations
/// based on scalar instructions.
/// </summary>
internal abstract class ScalarJpegColorConverter : JpegColorConverterBase
{
protected ScalarJpegColorConverter(JpegColorSpace colorSpace, int precision)
: base(colorSpace, precision)
{
}
protected override bool IsAvailable => true;
}
}
}

27
src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.VectorizedJpegColorConverter.cs → src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverterVector.cs

@ -1,27 +1,36 @@
// Copyright (c) Six Labors.
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Numerics;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
internal abstract partial class JpegColorConverter
internal abstract partial class JpegColorConverterBase
{
internal abstract class VectorizedJpegColorConverter : JpegColorConverter
/// <summary>
/// <see cref="JpegColorConverterBase"/> abstract base for implementations
/// based on <see cref="System.Numerics.Vector"/> API.
/// </summary>
/// <remarks>
/// Converters of this family can work with data of any size.
/// Even though real life data is guaranteed to be of size
/// divisible by 8 newer SIMD instructions like AVX512 won't work with
/// such data out of the box. These converters have fallback code
/// for 'remainder' data.
/// </remarks>
internal abstract class VectorizedJpegColorConverter : JpegColorConverterBase
{
private readonly int vectorSize;
protected VectorizedJpegColorConverter(JpegColorSpace colorSpace, int precision, int vectorSize)
protected VectorizedJpegColorConverter(JpegColorSpace colorSpace, int precision)
: base(colorSpace, precision)
{
this.vectorSize = vectorSize;
}
protected sealed override bool IsAvailable => SimdUtils.HasVector8;
public override void ConvertToRgbInplace(in ComponentValues values)
{
int length = values.Component0.Length;
int remainder = values.Component0.Length % this.vectorSize;
int remainder = values.Component0.Length % 8;
int simdCount = length - remainder;
if (simdCount > 0)
{

2
src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter.cs

@ -57,6 +57,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
/// <param name="frame">The jpeg frame with the color space to convert to.</param>
/// <param name="jpegData">The raw JPEG data.</param>
/// <returns>The color converter.</returns>
protected virtual JpegColorConverter GetColorConverter(JpegFrame frame, IRawJpegData jpegData) => JpegColorConverter.GetConverter(jpegData.ColorSpace, frame.Precision);
protected virtual JpegColorConverterBase GetColorConverter(JpegFrame frame, IRawJpegData jpegData) => JpegColorConverterBase.GetConverter(jpegData.ColorSpace, frame.Precision);
}
}

4
src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs

@ -39,7 +39,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
/// <summary>
/// Color converter from jpeg color space to target pixel color space.
/// </summary>
private JpegColorConverter colorConverter;
private JpegColorConverterBase colorConverter;
/// <summary>
/// Intermediate buffer of RGB components used in color conversion.
@ -163,7 +163,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
{
int y = yy - this.pixelRowCounter;
var values = new JpegColorConverter.ComponentValues(this.componentProcessors, y);
var values = new JpegColorConverterBase.ComponentValues(this.componentProcessors, y);
this.colorConverter.ConvertToRgbInplace(values);
values = values.Slice(0, width); // slice away Jpeg padding

2
src/ImageSharp/Formats/Tiff/Compression/Decompressors/RgbJpegSpectralConverter.cs

@ -27,6 +27,6 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Compression.Decompressors
}
/// <inheritdoc/>
protected override JpegColorConverter GetColorConverter(JpegFrame frame, IRawJpegData jpegData) => JpegColorConverter.GetConverter(JpegColorSpace.RGB, frame.Precision);
protected override JpegColorConverterBase GetColorConverter(JpegFrame frame, IRawJpegData jpegData) => JpegColorConverterBase.GetConverter(JpegColorSpace.RGB, frame.Precision);
}
}

12
tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/CmykColorConversion.cs

@ -17,25 +17,25 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
[Benchmark(Baseline = true)]
public void Scalar()
{
var values = new JpegColorConverter.ComponentValues(this.Input, 0);
var values = new JpegColorConverterBase.ComponentValues(this.Input, 0);
new JpegColorConverter.FromCmykBasic(8).ConvertToRgbInplace(values);
new JpegColorConverterBase.FromCmykBasic(8).ConvertToRgbInplace(values);
}
[Benchmark]
public void SimdVector8()
{
var values = new JpegColorConverter.ComponentValues(this.Input, 0);
var values = new JpegColorConverterBase.ComponentValues(this.Input, 0);
new JpegColorConverter.FromCmykVector8(8).ConvertToRgbInplace(values);
new JpegColorConverterBase.FromCmykVector8(8).ConvertToRgbInplace(values);
}
[Benchmark]
public void SimdVectorAvx2()
{
var values = new JpegColorConverter.ComponentValues(this.Input, 0);
var values = new JpegColorConverterBase.ComponentValues(this.Input, 0);
new JpegColorConverter.FromCmykAvx2(8).ConvertToRgbInplace(values);
new JpegColorConverterBase.FromCmykAvx2(8).ConvertToRgbInplace(values);
}
}
}

8
tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/GrayscaleColorConversion.cs

@ -17,17 +17,17 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
[Benchmark(Baseline = true)]
public void Scalar()
{
var values = new JpegColorConverter.ComponentValues(this.Input, 0);
var values = new JpegColorConverterBase.ComponentValues(this.Input, 0);
new JpegColorConverter.FromGrayscaleBasic(8).ConvertToRgbInplace(values);
new JpegColorConverterBase.FromGrayscaleBasic(8).ConvertToRgbInplace(values);
}
[Benchmark]
public void SimdVectorAvx2()
{
var values = new JpegColorConverter.ComponentValues(this.Input, 0);
var values = new JpegColorConverterBase.ComponentValues(this.Input, 0);
new JpegColorConverter.FromGrayscaleAvx2(8).ConvertToRgbInplace(values);
new JpegColorConverterBase.FromGrayscaleAvx2(8).ConvertToRgbInplace(values);
}
}
}

12
tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/RgbColorConversion.cs

@ -17,25 +17,25 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
[Benchmark(Baseline = true)]
public void Scalar()
{
var values = new JpegColorConverter.ComponentValues(this.Input, 0);
var values = new JpegColorConverterBase.ComponentValues(this.Input, 0);
new JpegColorConverter.FromRgbBasic(8).ConvertToRgbInplace(values);
new JpegColorConverterBase.FromRgbBasic(8).ConvertToRgbInplace(values);
}
[Benchmark]
public void SimdVector8()
{
var values = new JpegColorConverter.ComponentValues(this.Input, 0);
var values = new JpegColorConverterBase.ComponentValues(this.Input, 0);
new JpegColorConverter.FromRgbVector8(8).ConvertToRgbInplace(values);
new JpegColorConverterBase.FromRgbVector8(8).ConvertToRgbInplace(values);
}
[Benchmark]
public void SimdVectorAvx2()
{
var values = new JpegColorConverter.ComponentValues(this.Input, 0);
var values = new JpegColorConverterBase.ComponentValues(this.Input, 0);
new JpegColorConverter.FromRgbAvx2(8).ConvertToRgbInplace(values);
new JpegColorConverterBase.FromRgbAvx2(8).ConvertToRgbInplace(values);
}
}
}

16
tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/YCbCrColorConversion.cs

@ -17,33 +17,33 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
[Benchmark]
public void Scalar()
{
var values = new JpegColorConverter.ComponentValues(this.Input, 0);
var values = new JpegColorConverterBase.ComponentValues(this.Input, 0);
new JpegColorConverter.FromYCbCrBasic(8).ConvertToRgbInplace(values);
new JpegColorConverterBase.FromYCbCrBasic(8).ConvertToRgbInplace(values);
}
[Benchmark(Baseline = true)]
public void SimdVector()
{
var values = new JpegColorConverter.ComponentValues(this.Input, 0);
var values = new JpegColorConverterBase.ComponentValues(this.Input, 0);
new JpegColorConverter.FromYCbCrVector4(8).ConvertToRgbInplace(values);
new JpegColorConverterBase.FromYCbCrVector4(8).ConvertToRgbInplace(values);
}
[Benchmark]
public void SimdVector8()
{
var values = new JpegColorConverter.ComponentValues(this.Input, 0);
var values = new JpegColorConverterBase.ComponentValues(this.Input, 0);
new JpegColorConverter.FromYCbCrVector8(8).ConvertToRgbInplace(values);
new JpegColorConverterBase.FromYCbCrVector8(8).ConvertToRgbInplace(values);
}
[Benchmark]
public void SimdVectorAvx2()
{
var values = new JpegColorConverter.ComponentValues(this.Input, 0);
var values = new JpegColorConverterBase.ComponentValues(this.Input, 0);
new JpegColorConverter.FromYCbCrAvx2(8).ConvertToRgbInplace(values);
new JpegColorConverterBase.FromYCbCrAvx2(8).ConvertToRgbInplace(values);
}
}
}

12
tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversion/YccKColorConverter.cs

@ -17,25 +17,25 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg
[Benchmark(Baseline = true)]
public void Scalar()
{
var values = new JpegColorConverter.ComponentValues(this.Input, 0);
var values = new JpegColorConverterBase.ComponentValues(this.Input, 0);
new JpegColorConverter.FromYccKBasic(8).ConvertToRgbInplace(values);
new JpegColorConverterBase.FromYccKBasic(8).ConvertToRgbInplace(values);
}
[Benchmark]
public void SimdVector8()
{
var values = new JpegColorConverter.ComponentValues(this.Input, 0);
var values = new JpegColorConverterBase.ComponentValues(this.Input, 0);
new JpegColorConverter.FromYccKVector8(8).ConvertToRgbInplace(values);
new JpegColorConverterBase.FromYccKVector8(8).ConvertToRgbInplace(values);
}
[Benchmark]
public void SimdVectorAvx2()
{
var values = new JpegColorConverter.ComponentValues(this.Input, 0);
var values = new JpegColorConverterBase.ComponentValues(this.Input, 0);
new JpegColorConverter.FromYccKAvx2(8).ConvertToRgbInplace(values);
new JpegColorConverterBase.FromYccKAvx2(8).ConvertToRgbInplace(values);
}
}
}

76
tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs

@ -45,25 +45,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public void FromYCbCrBasic(int inputBufferLength, int resultBufferLength, int seed)
{
ValidateConversion(
new JpegColorConverter.FromYCbCrBasic(8),
3,
inputBufferLength,
resultBufferLength,
seed);
}
[Theory]
[MemberData(nameof(CommonConversionData))]
public void FromYCbCrVector4(int inputBufferLength, int resultBufferLength, int seed)
{
if (!SimdUtils.HasVector4)
{
this.Output.WriteLine("No SSE present, skipping test!");
return;
}
ValidateConversion(
new JpegColorConverter.FromYCbCrVector4(8),
new JpegColorConverterBase.FromYCbCrScalar(8),
3,
inputBufferLength,
resultBufferLength,
@ -81,7 +63,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
}
ValidateConversion(
new JpegColorConverter.FromYCbCrVector8(8),
new JpegColorConverterBase.FromYCbCrVector8(8),
3,
inputBufferLength,
resultBufferLength,
@ -99,7 +81,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
}
ValidateConversion(
new JpegColorConverter.FromYCbCrAvx2(8),
new JpegColorConverterBase.FromYCbCrAvx(8),
3,
inputBufferLength,
resultBufferLength,
@ -123,7 +105,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public void FromCmykBasic(int inputBufferLength, int resultBufferLength, int seed)
{
ValidateConversion(
new JpegColorConverter.FromCmykBasic(8),
new JpegColorConverterBase.FromCmykScalar(8),
4,
inputBufferLength,
resultBufferLength,
@ -141,7 +123,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
}
ValidateConversion(
new JpegColorConverter.FromCmykVector8(8),
new JpegColorConverterBase.FromCmykVector8(8),
4,
inputBufferLength,
resultBufferLength,
@ -159,7 +141,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
}
ValidateConversion(
new JpegColorConverter.FromCmykAvx2(8),
new JpegColorConverterBase.FromCmykAvx(8),
4,
inputBufferLength,
resultBufferLength,
@ -183,7 +165,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public void FromGrayscaleBasic(int inputBufferLength, int resultBufferLength, int seed)
{
ValidateConversion(
new JpegColorConverter.FromGrayscaleBasic(8),
new JpegColorConverterBase.FromGrayscaleScalar(8),
1,
inputBufferLength,
resultBufferLength,
@ -201,7 +183,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
}
ValidateConversion(
new JpegColorConverter.FromGrayscaleAvx2(8),
new JpegColorConverterBase.FromGrayscaleAvx(8),
1,
inputBufferLength,
resultBufferLength,
@ -225,7 +207,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public void FromRgbBasic(int inputBufferLength, int resultBufferLength, int seed)
{
ValidateConversion(
new JpegColorConverter.FromRgbBasic(8),
new JpegColorConverterBase.FromRgbScalar(8),
3,
inputBufferLength,
resultBufferLength,
@ -243,7 +225,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
}
ValidateConversion(
new JpegColorConverter.FromRgbVector8(8),
new JpegColorConverterBase.FromRgbVector8(8),
3,
inputBufferLength,
resultBufferLength,
@ -261,7 +243,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
}
ValidateConversion(
new JpegColorConverter.FromRgbAvx2(8),
new JpegColorConverterBase.FromRgbAvx(8),
3,
inputBufferLength,
resultBufferLength,
@ -285,7 +267,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
public void FromYccKBasic(int inputBufferLength, int resultBufferLength, int seed)
{
ValidateConversion(
new JpegColorConverter.FromYccKBasic(8),
new JpegColorConverterBase.FromYccKScalar(8),
4,
inputBufferLength,
resultBufferLength,
@ -303,7 +285,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
}
ValidateConversion(
new JpegColorConverter.FromYccKVector8(8),
new JpegColorConverterBase.FromYccKVector8(8),
4,
inputBufferLength,
resultBufferLength,
@ -321,7 +303,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
}
ValidateConversion(
new JpegColorConverter.FromYccKAvx2(8),
new JpegColorConverterBase.FromYccKAvx(8),
4,
inputBufferLength,
resultBufferLength,
@ -340,7 +322,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
seed);
}
private static JpegColorConverter.ComponentValues CreateRandomValues(
private static JpegColorConverterBase.ComponentValues CreateRandomValues(
int componentCount,
int inputBufferLength,
int seed,
@ -365,7 +347,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
buffers[i] = new Buffer2D<float>(source, values.Length, 1);
}
return new JpegColorConverter.ComponentValues(buffers, 0);
return new JpegColorConverterBase.ComponentValues(buffers, 0);
}
private static void ValidateConversion(
@ -376,7 +358,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
int seed)
{
ValidateConversion(
JpegColorConverter.GetConverter(colorSpace, 8),
JpegColorConverterBase.GetConverter(colorSpace, 8),
componentCount,
inputBufferLength,
resultBufferLength,
@ -384,14 +366,14 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
}
private static void ValidateConversion(
JpegColorConverter converter,
JpegColorConverterBase converter,
int componentCount,
int inputBufferLength,
int resultBufferLength,
int seed)
{
JpegColorConverter.ComponentValues original = CreateRandomValues(componentCount, inputBufferLength, seed);
JpegColorConverter.ComponentValues values = Copy(original);
JpegColorConverterBase.ComponentValues original = CreateRandomValues(componentCount, inputBufferLength, seed);
JpegColorConverterBase.ComponentValues values = Copy(original);
converter.ConvertToRgbInplace(values);
@ -400,20 +382,20 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
Validate(converter.ColorSpace, original, values, i);
}
static JpegColorConverter.ComponentValues Copy(JpegColorConverter.ComponentValues values)
static JpegColorConverterBase.ComponentValues Copy(JpegColorConverterBase.ComponentValues values)
{
Span<float> c0 = values.Component0.ToArray();
Span<float> c1 = values.ComponentCount > 1 ? values.Component1.ToArray().AsSpan() : c0;
Span<float> c2 = values.ComponentCount > 2 ? values.Component2.ToArray().AsSpan() : c0;
Span<float> c3 = values.ComponentCount > 3 ? values.Component3.ToArray().AsSpan() : Span<float>.Empty;
return new JpegColorConverter.ComponentValues(values.ComponentCount, c0, c1, c2, c3);
return new JpegColorConverterBase.ComponentValues(values.ComponentCount, c0, c1, c2, c3);
}
}
private static void Validate(
JpegColorSpace colorSpace,
in JpegColorConverter.ComponentValues original,
in JpegColorConverter.ComponentValues result,
in JpegColorConverterBase.ComponentValues original,
in JpegColorConverterBase.ComponentValues result,
int i)
{
switch (colorSpace)
@ -439,7 +421,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
}
}
private static void ValidateYCbCr(in JpegColorConverter.ComponentValues values, in JpegColorConverter.ComponentValues result, int i)
private static void ValidateYCbCr(in JpegColorConverterBase.ComponentValues values, in JpegColorConverterBase.ComponentValues result, int i)
{
float y = values.Component0[i];
float cb = values.Component1[i];
@ -452,7 +434,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
Assert.Equal(expected, actual, ColorSpaceComparer);
}
private static void ValidateCyyK(in JpegColorConverter.ComponentValues values, in JpegColorConverter.ComponentValues result, int i)
private static void ValidateCyyK(in JpegColorConverterBase.ComponentValues values, in JpegColorConverterBase.ComponentValues result, int i)
{
var v = new Vector4(0, 0, 0, 1F);
var scale = new Vector4(1 / 255F, 1 / 255F, 1 / 255F, 1F);
@ -477,7 +459,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
Assert.Equal(expected, actual, ColorSpaceComparer);
}
private static void ValidateRgb(in JpegColorConverter.ComponentValues values, in JpegColorConverter.ComponentValues result, int i)
private static void ValidateRgb(in JpegColorConverterBase.ComponentValues values, in JpegColorConverterBase.ComponentValues result, int i)
{
float r = values.Component0[i];
float g = values.Component1[i];
@ -489,7 +471,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
Assert.Equal(expected, actual, ColorSpaceComparer);
}
private static void ValidateGrayScale(in JpegColorConverter.ComponentValues values, in JpegColorConverter.ComponentValues result, int i)
private static void ValidateGrayScale(in JpegColorConverterBase.ComponentValues values, in JpegColorConverterBase.ComponentValues result, int i)
{
float y = values.Component0[i];
var actual = new Rgb(result.Component0[i], result.Component0[i], result.Component0[i]);
@ -498,7 +480,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
Assert.Equal(expected, actual, ColorSpaceComparer);
}
private static void ValidateCmyk(in JpegColorConverter.ComponentValues values, in JpegColorConverter.ComponentValues result, int i)
private static void ValidateCmyk(in JpegColorConverterBase.ComponentValues values, in JpegColorConverterBase.ComponentValues result, int i)
{
var v = new Vector4(0, 0, 0, 1F);
var scale = new Vector4(1 / 255F, 1 / 255F, 1 / 255F, 1F);

Loading…
Cancel
Save