From 033ed8e1b83b99aebfab84b77032440cbf917fb8 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 2 Oct 2021 20:26:28 +0200 Subject: [PATCH 01/24] Inplace JpegColorConverter basic infra --- .../JpegColorConverter.FromRgbAvx2.cs | 28 ++++ .../JpegColorConverter.FromRgbBasic.cs | 43 ++++++ .../JpegColorConverter.FromRgbVector8.cs | 27 ++++ ...rConverter.VectorizedJpegColorConverter.cs | 25 ++++ .../ColorConverters/JpegColorConverter.cs | 28 ++-- .../Formats/Jpg/JpegColorConverterTests.cs | 140 ++++++++++++++++-- 6 files changed, 268 insertions(+), 23 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbAvx2.cs index 8f04c91528..505e1ca224 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbAvx2.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbAvx2.cs @@ -65,8 +65,36 @@ protected override void ConvertCoreVectorized(in ComponentValues values, Span rBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0)); + ref Vector256 gBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1)); + ref Vector256 bBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2)); + + // Used for the color conversion + var scale = Vector256.Create(1 / this.MaximumValue); + int n = values.Component0.Length / 8; + for (int i = 0; i < n; i++) + { + ref Vector256 r = ref Unsafe.Add(ref rBase, i); + ref Vector256 g = ref Unsafe.Add(ref gBase, i); + ref Vector256 b = ref Unsafe.Add(ref bBase, i); + r = Avx.Multiply(r, scale); + g = Avx.Multiply(g, scale); + b = Avx.Multiply(b, scale); + } +#endif + } + protected override void ConvertCore(in ComponentValues values, Span result) => FromRgbBasic.ConvertCore(values, result, this.MaximumValue); + + protected override void ConvertCoreInplace(in ComponentValues values) => + FromRgbBasic.ConvertCoreInplace(values, this.MaximumValue); } } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbBasic.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbBasic.cs index ddca3fe2f6..497c943a36 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbBasic.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbBasic.cs @@ -3,6 +3,7 @@ using System; using System.Numerics; +using System.Runtime.InteropServices; namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters { @@ -20,6 +21,48 @@ public override void ConvertToRgba(in ComponentValues values, Span resu ConvertCore(values, result, this.MaximumValue); } + public override void ConvertToRgbInplace(in ComponentValues values) + { + ConvertCoreInplace(values, this.MaximumValue); + } + + internal static void ConvertCoreInplace(ComponentValues values, float maxValue) + { + // TODO: Optimize this + ConvertComponent(values.Component0, maxValue); + ConvertComponent(values.Component1, maxValue); + ConvertComponent(values.Component2, maxValue); + + static void ConvertComponent(Span values, float maxValue) + { + Span vecValues = MemoryMarshal.Cast(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.Length > 0) + { + float scaleValue = 1f / maxValue; + values[0] *= scaleValue; + + if (values.Length > 1) + { + values[1] *= scaleValue; + + if (values.Length > 2) + { + values[2] *= scaleValue; + } + } + } + } + } + internal static void ConvertCore(in ComponentValues values, Span result, float maxValue) { ReadOnlySpan rVals = values.Component0; diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbVector8.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbVector8.cs index 763064d1e0..0db568217b 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbVector8.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbVector8.cs @@ -60,8 +60,35 @@ protected override void ConvertCoreVectorized(in ComponentValues values, Span rBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0)); + ref Vector gBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1)); + ref Vector bBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2)); + + var scale = new Vector(1 / this.MaximumValue); + + // Walking 8 elements at one step: + int n = values.Component0.Length / 8; + for (int i = 0; i < n; i++) + { + ref Vector r = ref Unsafe.Add(ref rBase, i); + ref Vector g = ref Unsafe.Add(ref gBase, i); + ref Vector b = ref Unsafe.Add(ref bBase, i); + r *= scale; + g *= scale; + b *= scale; + } + } + protected override void ConvertCore(in ComponentValues values, Span result) => FromRgbBasic.ConvertCore(values, result, this.MaximumValue); + + protected override void ConvertCoreInplace(in ComponentValues values) => + FromRgbBasic.ConvertCoreInplace(values, this.MaximumValue); } } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.VectorizedJpegColorConverter.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.VectorizedJpegColorConverter.cs index 522be82c2d..046416847b 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.VectorizedJpegColorConverter.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.VectorizedJpegColorConverter.cs @@ -38,9 +38,34 @@ public sealed override void ConvertToRgba(in ComponentValues values, Span 0) + { + // This implementation is actually AVX specific. + // An AVX register is capable of storing 8 float-s. + if (!this.IsAvailable) + { + throw new InvalidOperationException( + "This converter can be used only on architecture having 256 byte floating point SIMD registers!"); + } + + this.ConvertCoreVectorizedInplace(values.Slice(0, simdCount)); + } + + this.ConvertCoreInplace(values.Slice(simdCount, remainder)); + } + protected abstract void ConvertCoreVectorized(in ComponentValues values, Span result); + protected virtual void ConvertCoreVectorizedInplace(in ComponentValues values) => throw new NotImplementedException(); + protected abstract void ConvertCore(in ComponentValues values, Span result); + + protected virtual void ConvertCoreInplace(in ComponentValues values) => throw new NotImplementedException(); } } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs index 2d24f01dd8..4c07783d7f 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs @@ -82,6 +82,8 @@ public static JpegColorConverter GetConverter(JpegColorSpace colorSpace, int pre /// The destination buffer of values public abstract void ConvertToRgba(in ComponentValues values, Span result); + public virtual void ConvertToRgbInplace(in ComponentValues values) => throw new NotImplementedException(); + /// /// Returns the s for all supported colorspaces and precisions. /// @@ -181,22 +183,22 @@ public readonly ref struct ComponentValues /// /// The component 0 (eg. Y) /// - public readonly ReadOnlySpan Component0; + public readonly Span Component0; /// /// The component 1 (eg. Cb) /// - public readonly ReadOnlySpan Component1; + public readonly Span Component1; /// /// The component 2 (eg. Cr) /// - public readonly ReadOnlySpan Component2; + public readonly Span Component2; /// /// The component 4 /// - public readonly ReadOnlySpan Component3; + public readonly Span Component3; /// /// Initializes a new instance of the struct. @@ -226,12 +228,12 @@ public ComponentValues(IReadOnlyList> componentBuffers, int row) } } - private ComponentValues( + internal ComponentValues( int componentCount, - ReadOnlySpan c0, - ReadOnlySpan c1, - ReadOnlySpan c2, - ReadOnlySpan c3) + Span c0, + Span c1, + Span c2, + Span c3) { this.ComponentCount = componentCount; this.Component0 = c0; @@ -242,10 +244,10 @@ private ComponentValues( public ComponentValues Slice(int start, int length) { - ReadOnlySpan c0 = this.Component0.Slice(start, length); - ReadOnlySpan c1 = this.ComponentCount > 1 ? this.Component1.Slice(start, length) : ReadOnlySpan.Empty; - ReadOnlySpan c2 = this.ComponentCount > 2 ? this.Component2.Slice(start, length) : ReadOnlySpan.Empty; - ReadOnlySpan c3 = this.ComponentCount > 3 ? this.Component3.Slice(start, length) : ReadOnlySpan.Empty; + Span c0 = this.Component0.Slice(start, length); + Span c1 = this.ComponentCount > 1 ? this.Component1.Slice(start, length) : Span.Empty; + Span c2 = this.ComponentCount > 2 ? this.Component2.Slice(start, length) : Span.Empty; + Span c3 = this.ComponentCount > 3 ? this.Component3.Slice(start, length) : Span.Empty; return new ComponentValues(this.ComponentCount, c0, c1, c2, c3); } diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs index 5f05621466..e275bf50cc 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs @@ -416,39 +416,77 @@ private static void ValidateConversion( int resultBufferLength, int seed) { - JpegColorConverter.ComponentValues values = CreateRandomValues(componentCount, inputBufferLength, seed); - var result = new Vector4[resultBufferLength]; + JpegColorConverter.ComponentValues original = CreateRandomValues(componentCount, inputBufferLength, seed); + JpegColorConverter.ComponentValues values = Copy(original); - converter.ConvertToRgba(values, result); + converter.ConvertToRgbInplace(values); for (int i = 0; i < resultBufferLength; i++) { - Validate(converter.ColorSpace, values, result, i); + Validate(converter.ColorSpace, original, values, i); + } + + static JpegColorConverter.ComponentValues Copy(JpegColorConverter.ComponentValues values) + { + Span c0 = values.Component0.ToArray(); + Span c1 = values.ComponentCount > 1 ? values.Component1.ToArray().AsSpan() : default; + Span c2 = values.ComponentCount > 2 ? values.Component2.ToArray().AsSpan() : default; + Span c3 = values.ComponentCount > 3 ? values.Component3.ToArray().AsSpan() : default; + return new JpegColorConverter.ComponentValues(values.ComponentCount, c0, c1, c2, c3); } } private static void Validate( JpegColorSpace colorSpace, - in JpegColorConverter.ComponentValues values, + in JpegColorConverter.ComponentValues original, Vector4[] result, int i) { switch (colorSpace) { case JpegColorSpace.Grayscale: - ValidateGrayScale(values, result, i); + ValidateGrayScale(original, result, i); break; case JpegColorSpace.Ycck: - ValidateCyyK(values, result, i); + ValidateCyyK(original, result, i); break; case JpegColorSpace.Cmyk: - ValidateCmyk(values, result, i); + ValidateCmyk(original, result, i); break; case JpegColorSpace.RGB: - ValidateRgb(values, result, i); + ValidateRgb(original, result, i); break; case JpegColorSpace.YCbCr: - ValidateYCbCr(values, result, i); + ValidateYCbCr(original, result, i); + break; + default: + Assert.True(false, $"Colorspace {colorSpace} not supported!"); + break; + } + } + + private static void Validate( + JpegColorSpace colorSpace, + in JpegColorConverter.ComponentValues original, + in JpegColorConverter.ComponentValues result, + int i) + { + switch (colorSpace) + { + case JpegColorSpace.Grayscale: + ValidateGrayScale(original, result, i); + break; + case JpegColorSpace.Ycck: + ValidateCyyK(original, result, i); + break; + case JpegColorSpace.Cmyk: + ValidateCmyk(original, result, i); + break; + case JpegColorSpace.RGB: + ValidateRgb(original, result, i); + break; + case JpegColorSpace.YCbCr: + ValidateYCbCr(original, result, i); break; default: Assert.True(false, $"Colorspace {colorSpace} not supported!"); @@ -471,6 +509,19 @@ private static void ValidateYCbCr(in JpegColorConverter.ComponentValues values, Assert.Equal(1, rgba.W); } + private static void ValidateYCbCr(in JpegColorConverter.ComponentValues values, in JpegColorConverter.ComponentValues result, int i) + { + float y = values.Component0[i]; + float cb = values.Component1[i]; + float cr = values.Component2[i]; + var ycbcr = new YCbCr(y, cb, cr); + + var actual = new Rgb(result.Component0[i], result.Component1[i], result.Component2[i]); + var expected = ColorSpaceConverter.ToRgb(ycbcr); + + Assert.Equal(expected, actual, ColorSpaceComparer); + } + private static void ValidateCyyK(in JpegColorConverter.ComponentValues values, Vector4[] result, int i) { var v = new Vector4(0, 0, 0, 1F); @@ -498,6 +549,31 @@ private static void ValidateCyyK(in JpegColorConverter.ComponentValues values, V Assert.Equal(1, rgba.W); } + private static void ValidateCyyK(in JpegColorConverter.ComponentValues values, in JpegColorConverter.ComponentValues result, int i) + { + var v = new Vector4(0, 0, 0, 1F); + var scale = new Vector4(1 / 255F, 1 / 255F, 1 / 255F, 1F); + + float y = values.Component0[i]; + float cb = values.Component1[i] - 128F; + float cr = values.Component2[i] - 128F; + float k = values.Component3[i] / 255F; + + v.X = (255F - (float)Math.Round(y + (1.402F * cr), MidpointRounding.AwayFromZero)) * k; + v.Y = (255F - (float)Math.Round( + y - (0.344136F * cb) - (0.714136F * cr), + MidpointRounding.AwayFromZero)) * k; + v.Z = (255F - (float)Math.Round(y + (1.772F * cb), MidpointRounding.AwayFromZero)) * k; + v.W = 1F; + + v *= scale; + + var actual = new Rgb(result.Component0[i], result.Component1[i], result.Component2[i]); + var expected = new Rgb(v.X, v.Y, v.Z); + + Assert.Equal(expected, actual, ColorSpaceComparer); + } + private static void ValidateRgb(in JpegColorConverter.ComponentValues values, Vector4[] result, int i) { float r = values.Component0[i]; @@ -511,6 +587,18 @@ private static void ValidateRgb(in JpegColorConverter.ComponentValues values, Ve Assert.Equal(1, rgba.W); } + private static void ValidateRgb(in JpegColorConverter.ComponentValues values, in JpegColorConverter.ComponentValues result, int i) + { + float r = values.Component0[i]; + float g = values.Component1[i]; + float b = values.Component2[i]; + + var actual = new Rgb(result.Component0[i], result.Component1[i], result.Component2[i]); + var expected = new Rgb(r / 255F, g / 255F, b / 255F); + + Assert.Equal(expected, actual, ColorSpaceComparer); + } + private static void ValidateGrayScale(in JpegColorConverter.ComponentValues values, Vector4[] result, int i) { float y = values.Component0[i]; @@ -522,6 +610,15 @@ private static void ValidateGrayScale(in JpegColorConverter.ComponentValues valu Assert.Equal(1, rgba.W); } + private static void ValidateGrayScale(in JpegColorConverter.ComponentValues values, in JpegColorConverter.ComponentValues result, int i) + { + float y = values.Component0[i]; + var actual = new Rgb(result.Component0[i], result.Component0[i], result.Component0[i]); + var expected = new Rgb(y / 255F, y / 255F, y / 255F); + + Assert.Equal(expected, actual, ColorSpaceComparer); + } + private static void ValidateCmyk(in JpegColorConverter.ComponentValues values, Vector4[] result, int i) { var v = new Vector4(0, 0, 0, 1F); @@ -546,5 +643,28 @@ private static void ValidateCmyk(in JpegColorConverter.ComponentValues values, V Assert.Equal(expected, actual, ColorSpaceComparer); Assert.Equal(1, rgba.W); } + + private static void ValidateCmyk(in JpegColorConverter.ComponentValues values, in JpegColorConverter.ComponentValues result, int i) + { + var v = new Vector4(0, 0, 0, 1F); + var scale = new Vector4(1 / 255F, 1 / 255F, 1 / 255F, 1F); + + float c = values.Component0[i]; + float m = values.Component1[i]; + float y = values.Component2[i]; + float k = values.Component3[i] / 255F; + + v.X = c * k; + v.Y = m * k; + v.Z = y * k; + v.W = 1F; + + v *= scale; + + var actual = new Rgb(result.Component0[i], result.Component1[i], result.Component2[i]); + var expected = new Rgb(v.X, v.Y, v.Z); + + Assert.Equal(expected, actual, ColorSpaceComparer); + } } } From 8599caaff4541a685948d9c7730fabcf44b71c39 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 2 Oct 2021 20:51:30 +0200 Subject: [PATCH 02/24] convert YCbCr inplace --- .../JpegColorConverter.FromYCbCrAvx2.cs | 62 +++++++++++++++++- .../JpegColorConverter.FromYCbCrBasic.cs | 23 +++++++ .../JpegColorConverter.FromYCbCrVector4.cs | 64 +++++++++++++++++++ .../JpegColorConverter.FromYCbCrVector8.cs | 51 +++++++++++++++ 4 files changed, 199 insertions(+), 1 deletion(-) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrAvx2.cs index f3a0636200..83d4024447 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrAvx2.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrAvx2.cs @@ -25,7 +25,7 @@ public FromYCbCrAvx2(int precision) protected override void ConvertCoreVectorized(in ComponentValues values, Span result) { - #if SUPPORTS_RUNTIME_INTRINSICS +#if SUPPORTS_RUNTIME_INTRINSICS ref Vector256 yBase = ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0)); ref Vector256 cbBase = @@ -94,8 +94,68 @@ protected override void ConvertCoreVectorized(in ComponentValues values, Span c0Base = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0)); + ref Vector256 c1Base = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1)); + ref Vector256 c2Base = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2)); + + // 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 vcontrol = Unsafe.As>(ref control); + + // Walking 8 elements at one step: + int n = values.Component0.Length / 8; + for (int i = 0; i < n; i++) + { + // y = yVals[i]; + // cb = cbVals[i] - 128F; + // cr = crVals[i] - 128F; + ref Vector256 c0 = ref Unsafe.Add(ref c0Base, i); + ref Vector256 c1 = ref Unsafe.Add(ref c1Base, i); + ref Vector256 c2 = ref Unsafe.Add(ref c2Base, i); + + Vector256 y = c0; + Vector256 cb = Avx.Add(c1, chromaOffset); + Vector256 cr = Avx.Add(c2, chromaOffset); + + // 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 r = HwIntrinsics.MultiplyAdd(y, cr, rCrMult); + Vector256 g = HwIntrinsics.MultiplyAdd(HwIntrinsics.MultiplyAdd(y, cb, gCbMult), cr, gCrMult); + Vector256 b = HwIntrinsics.MultiplyAdd(y, cb, bCbMult); + + r = Avx.Multiply(Avx.RoundToNearestInteger(r), scale); + g = Avx.Multiply(Avx.RoundToNearestInteger(g), scale); + b = Avx.Multiply(Avx.RoundToNearestInteger(b), scale); + + c0 = r; + c1 = g; + c2 = b; + } +#endif + } + protected override void ConvertCore(in ComponentValues values, Span result) => FromYCbCrBasic.ConvertCore(values, result, this.MaximumValue, this.HalfValue); + + protected override void ConvertCoreInplace(in ComponentValues values) => + FromYCbCrBasic.ConvertCoreInplace(values, this.MaximumValue, this.HalfValue); } } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs index 352e4acb7e..cc37e4e7dc 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs @@ -20,6 +20,9 @@ public override void ConvertToRgba(in ComponentValues values, Span resu ConvertCore(values, result, this.MaximumValue, this.HalfValue); } + public override void ConvertToRgbInplace(in ComponentValues values) + => ConvertCoreInplace(values, this.MaximumValue, this.HalfValue); + internal static void ConvertCore(in ComponentValues values, Span result, float maxValue, float halfValue) { // TODO: We can optimize a lot here with Vector and SRCS.Unsafe()! @@ -46,6 +49,26 @@ internal static void ConvertCore(in ComponentValues values, Span result result[i] = v; } } + + internal static void ConvertCoreInplace(in ComponentValues values, float maxValue, float halfValue) + { + Span c0 = values.Component0; + Span c1 = values.Component1; + Span 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; + } + } } } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector4.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector4.cs index 42f8eef5a1..c770111cf7 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector4.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector4.cs @@ -85,8 +85,72 @@ protected override void ConvertCoreVectorized(in ComponentValues values, Span(ref MemoryMarshal.GetReference(values.Component0)); + ref Vector4Pair c1Base = + ref Unsafe.As(ref MemoryMarshal.GetReference(values.Component1)); + ref Vector4Pair c2Base = + ref Unsafe.As(ref MemoryMarshal.GetReference(values.Component2)); + + var chromaOffset = new Vector4(-this.HalfValue); + var maxValue = this.MaximumValue; + + // Walking 8 elements at one step: + int n = values.Component0.Length / 8; + + for (int 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 ConvertCore(in ComponentValues values, Span result) => FromYCbCrBasic.ConvertCore(values, result, this.MaximumValue, this.HalfValue); + + protected override void ConvertCoreInplace(in ComponentValues values) + => FromYCbCrBasic.ConvertCoreInplace(values, this.MaximumValue, this.HalfValue); } } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector8.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector8.cs index abacf7161b..f6015447b8 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector8.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector8.cs @@ -80,8 +80,59 @@ protected override void ConvertCoreVectorized(in ComponentValues values, Span c0Base = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0)); + ref Vector c1Base = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1)); + ref Vector c2Base = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2)); + + var chromaOffset = new Vector(-this.HalfValue); + + // Walking 8 elements at one step: + int n = values.Component0.Length / 8; + var scale = new Vector(1 / this.MaximumValue); + + for (int i = 0; i < n; i++) + { + // y = yVals[i]; + // cb = cbVals[i] - 128F; + // cr = crVals[i] - 128F; + ref Vector c0 = ref Unsafe.Add(ref c0Base, i); + ref Vector c1 = ref Unsafe.Add(ref c1Base, i); + ref Vector c2 = ref Unsafe.Add(ref c2Base, i); + Vector y = Unsafe.Add(ref c0Base, i); + Vector cb = Unsafe.Add(ref c1Base, i) + chromaOffset; + Vector cr = Unsafe.Add(ref c2Base, i) + chromaOffset; + + // 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 r = y + (cr * new Vector(1.402F)); + Vector g = y - (cb * new Vector(0.344136F)) - (cr * new Vector(0.714136F)); + Vector b = y + (cb * new Vector(1.772F)); + + r = r.FastRound(); + g = g.FastRound(); + b = b.FastRound(); + r *= scale; + g *= scale; + b *= scale; + + c0 = r; + c1 = g; + c2 = b; + } + } + protected override void ConvertCore(in ComponentValues values, Span result) => FromYCbCrBasic.ConvertCore(values, result, this.MaximumValue, this.HalfValue); + + protected override void ConvertCoreInplace(in ComponentValues values) => + FromYCbCrBasic.ConvertCoreInplace(values, this.MaximumValue, this.HalfValue); } } } From ef767cc9051530b579ea0e40f582b4bb452ff966 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 2 Oct 2021 21:53:56 +0200 Subject: [PATCH 03/24] Cmyk & Grayscale inplace conversion --- .../JpegColorConverter.FromCmykAvx2.cs | 34 ++++++++++++++++++ .../JpegColorConverter.FromCmykBasic.cs | 24 +++++++++++++ .../JpegColorConverter.FromCmykVector8.cs | 31 ++++++++++++++++ .../JpegColorConverter.FromGrayScaleAvx2.cs | 21 +++++++++++ .../JpegColorConverter.FromGrayScaleBasic.cs | 33 +++++++++++++++++ .../JpegColorConverter.FromRgbBasic.cs | 36 ++----------------- .../ColorConverters/JpegColorConverter.cs | 25 ++++--------- .../Formats/Jpg/JpegColorConverterTests.cs | 7 ++-- 8 files changed, 157 insertions(+), 54 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx2.cs index f9334de73b..634e0faaf3 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx2.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx2.cs @@ -74,8 +74,42 @@ protected override void ConvertCoreVectorized(in ComponentValues values, Span c0Base = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0)); + ref Vector256 c1Base = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1)); + ref Vector256 c2Base = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2)); + ref Vector256 c3Base = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component3)); + + // Used for the color conversion + var scale = Vector256.Create(1 / this.MaximumValue); + + int n = values.Component0.Length / 8; + for (int i = 0; i < n; i++) + { + ref Vector256 c = ref Unsafe.Add(ref c0Base, i); + ref Vector256 m = ref Unsafe.Add(ref c1Base, i); + ref Vector256 y = ref Unsafe.Add(ref c2Base, i); + Vector256 k = Unsafe.Add(ref c3Base, i); + + k = Avx.Multiply(k, scale); + c = Avx.Multiply(Avx.Multiply(c, k), scale); + m = Avx.Multiply(Avx.Multiply(m, k), scale); + y = Avx.Multiply(Avx.Multiply(y, k), scale); + } +#endif + } + protected override void ConvertCore(in ComponentValues values, Span result) => FromCmykBasic.ConvertCore(values, result, this.MaximumValue); + + protected override void ConvertCoreInplace(in ComponentValues values) => + FromCmykBasic.ConvertCoreInplace(values, this.MaximumValue); } } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykBasic.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykBasic.cs index 6cbd52ec3d..f4a9529e10 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykBasic.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykBasic.cs @@ -20,6 +20,9 @@ public override void ConvertToRgba(in ComponentValues values, Span resu ConvertCore(values, result, this.MaximumValue); } + public override void ConvertToRgbInplace(in ComponentValues values) => + ConvertCoreInplace(values, this.MaximumValue); + internal static void ConvertCore(in ComponentValues values, Span result, float maxValue) { ReadOnlySpan cVals = values.Component0; @@ -49,6 +52,27 @@ internal static void ConvertCore(in ComponentValues values, Span result result[i] = v; } } + + internal static void ConvertCoreInplace(in ComponentValues values, float maxValue) + { + Span c0 = values.Component0; + Span c1 = values.Component1; + Span c2 = values.Component2; + Span c3 = values.Component3; + + float scale = 1 / maxValue; + for (int i = 0; i < c0.Length; i++) + { + float c = c0[i]; + float m = c1[i]; + float y = c2[i]; + float k = c3[i] / maxValue; + + c0[i] = c * k * scale; + c1[i] = m * k * scale; + c2[i] = y * k * scale; + } + } } } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykVector8.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykVector8.cs index e75634b0fa..b55ec2e0f4 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykVector8.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykVector8.cs @@ -64,8 +64,39 @@ protected override void ConvertCoreVectorized(in ComponentValues values, Span cBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0)); + ref Vector mBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1)); + ref Vector yBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2)); + ref Vector kBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component3)); + + var scale = new Vector(1 / this.MaximumValue); + + // Walking 8 elements at one step: + int n = values.Component0.Length / 8; + for (int i = 0; i < n; i++) + { + ref Vector c = ref Unsafe.Add(ref cBase, i); + ref Vector m = ref Unsafe.Add(ref mBase, i); + ref Vector y = ref Unsafe.Add(ref yBase, i); + Vector k = Unsafe.Add(ref kBase, i) * scale; + + c = (c * k) * scale; + m = (m * k) * scale; + y = (y * k) * scale; + } + } + protected override void ConvertCore(in ComponentValues values, Span result) => FromCmykBasic.ConvertCore(values, result, this.MaximumValue); + + protected override void ConvertCoreInplace(in ComponentValues values) => + FromCmykBasic.ConvertCoreInplace(values, this.MaximumValue); } } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleAvx2.cs index 45846a6b56..4efabf64a6 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleAvx2.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleAvx2.cs @@ -56,8 +56,29 @@ protected override void ConvertCoreVectorized(in ComponentValues values, Span c0Base = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0)); + + // Used for the color conversion + var scale = Vector256.Create(1 / this.MaximumValue); + + int n = values.Component0.Length / 8; + for (int i = 0; i < n; i++) + { + ref Vector256 c0 = ref Unsafe.Add(ref c0Base, i); + c0 = Avx.Multiply(c0, scale); + } +#endif + } + protected override void ConvertCore(in ComponentValues values, Span result) => FromGrayscaleBasic.ConvertCore(values, result, this.MaximumValue); + + protected override void ConvertCoreInplace(in ComponentValues values) => + FromGrayscaleBasic.ScaleValues(values.Component0, this.MaximumValue); } } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleBasic.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleBasic.cs index 0b7a220d94..faf6f203f9 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleBasic.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleBasic.cs @@ -22,6 +22,9 @@ public override void ConvertToRgba(in ComponentValues values, Span resu ConvertCore(values, result, this.MaximumValue); } + public override void ConvertToRgbInplace(in ComponentValues values) => + ScaleValues(values.Component0, this.MaximumValue); + internal static void ConvertCore(in ComponentValues values, Span result, float maxValue) { var maximum = 1 / maxValue; @@ -38,6 +41,36 @@ internal static void ConvertCore(in ComponentValues values, Span result Unsafe.Add(ref dBase, i) = v; } } + + internal static void ScaleValues(Span values, float maxValue) + { + // TODO: Optimize this + Span vecValues = MemoryMarshal.Cast(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.Length > 0) + { + float scaleValue = 1f / maxValue; + values[0] *= scaleValue; + + if (values.Length > 1) + { + values[1] *= scaleValue; + + if (values.Length > 2) + { + values[2] *= scaleValue; + } + } + } + } } } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbBasic.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbBasic.cs index 497c943a36..313583f4a8 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbBasic.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbBasic.cs @@ -28,39 +28,9 @@ public override void ConvertToRgbInplace(in ComponentValues values) internal static void ConvertCoreInplace(ComponentValues values, float maxValue) { - // TODO: Optimize this - ConvertComponent(values.Component0, maxValue); - ConvertComponent(values.Component1, maxValue); - ConvertComponent(values.Component2, maxValue); - - static void ConvertComponent(Span values, float maxValue) - { - Span vecValues = MemoryMarshal.Cast(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.Length > 0) - { - float scaleValue = 1f / maxValue; - values[0] *= scaleValue; - - if (values.Length > 1) - { - values[1] *= scaleValue; - - if (values.Length > 2) - { - values[2] *= scaleValue; - } - } - } - } + FromGrayscaleBasic.ScaleValues(values.Component0, maxValue); + FromGrayscaleBasic.ScaleValues(values.Component1, maxValue); + FromGrayscaleBasic.ScaleValues(values.Component2, maxValue); } internal static void ConvertCore(in ComponentValues values, Span result, float maxValue) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs index 4c07783d7f..8efbf92b64 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs @@ -186,12 +186,12 @@ public readonly ref struct ComponentValues public readonly Span Component0; /// - /// The component 1 (eg. Cb) + /// The component 1 (eg. Cb). In case of grayscale, it points to . /// public readonly Span Component1; /// - /// The component 2 (eg. Cr) + /// The component 2 (eg. Cr). In case of grayscale, it points to . /// public readonly Span Component2; @@ -210,22 +210,11 @@ public ComponentValues(IReadOnlyList> componentBuffers, int row) this.ComponentCount = componentBuffers.Count; this.Component0 = componentBuffers[0].GetRowSpan(row); - this.Component1 = Span.Empty; - this.Component2 = Span.Empty; - this.Component3 = Span.Empty; - - if (this.ComponentCount > 1) - { - this.Component1 = componentBuffers[1].GetRowSpan(row); - if (this.ComponentCount > 2) - { - this.Component2 = componentBuffers[2].GetRowSpan(row); - if (this.ComponentCount > 3) - { - this.Component3 = componentBuffers[3].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.Empty; } internal ComponentValues( diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs index e275bf50cc..6354d1e196 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs @@ -375,6 +375,7 @@ private static JpegColorConverter.ComponentValues CreateRandomValues( float maxVal = 255f) { var rnd = new Random(seed); + var buffers = new Buffer2D[componentCount]; for (int i = 0; i < componentCount; i++) { @@ -429,9 +430,9 @@ private static void ValidateConversion( static JpegColorConverter.ComponentValues Copy(JpegColorConverter.ComponentValues values) { Span c0 = values.Component0.ToArray(); - Span c1 = values.ComponentCount > 1 ? values.Component1.ToArray().AsSpan() : default; - Span c2 = values.ComponentCount > 2 ? values.Component2.ToArray().AsSpan() : default; - Span c3 = values.ComponentCount > 3 ? values.Component3.ToArray().AsSpan() : default; + Span c1 = values.ComponentCount > 1 ? values.Component1.ToArray().AsSpan() : c0; + Span c2 = values.ComponentCount > 2 ? values.Component2.ToArray().AsSpan() : c0; + Span c3 = values.ComponentCount > 3 ? values.Component3.ToArray().AsSpan() : Span.Empty; return new JpegColorConverter.ComponentValues(values.ComponentCount, c0, c1, c2, c3); } } From 0a6189d74c574ad0ce10b75109a8d08366dcebc8 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 2 Oct 2021 22:22:21 +0200 Subject: [PATCH 04/24] inplace ycck conversion --- .../JpegColorConverter.FromYccKAvx2.cs | 64 +++++++++++++++++++ .../JpegColorConverter.FromYccKBasic.cs | 27 ++++++++ .../JpegColorConverter.FromYccKVector8.cs | 55 ++++++++++++++++ 3 files changed, 146 insertions(+) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKAvx2.cs index ea0132e1e9..bd786b826c 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKAvx2.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKAvx2.cs @@ -103,8 +103,72 @@ protected override void ConvertCoreVectorized(in ComponentValues values, Span c0Base = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0)); + ref Vector256 c1Base = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1)); + ref Vector256 c2Base = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2)); + ref Vector256 kBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component3)); + + // Used for the color conversion + 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); + + // Walking 8 elements at one step: + int n = values.Component0.Length / 8; + for (int i = 0; i < n; i++) + { + // y = yVals[i]; + // cb = cbVals[i] - 128F; + // cr = crVals[i] - 128F; + // k = kVals[i] / 256F; + ref Vector256 c0 = ref Unsafe.Add(ref c0Base, i); + ref Vector256 c1 = ref Unsafe.Add(ref c1Base, i); + ref Vector256 c2 = ref Unsafe.Add(ref c2Base, i); + Vector256 y = c0; + Vector256 cb = Avx.Add(c1, chromaOffset); + Vector256 cr = Avx.Add(c2, chromaOffset); + Vector256 scaledK = Avx.Multiply(Unsafe.Add(ref kBase, i), scale); + + // 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 r = HwIntrinsics.MultiplyAdd(y, cr, rCrMult); + Vector256 g = + HwIntrinsics.MultiplyAdd(HwIntrinsics.MultiplyAdd(y, cb, gCbMult), cr, gCrMult); + Vector256 b = HwIntrinsics.MultiplyAdd(y, cb, bCbMult); + + r = Avx.Subtract(max, Avx.RoundToNearestInteger(r)); + g = Avx.Subtract(max, Avx.RoundToNearestInteger(g)); + b = Avx.Subtract(max, Avx.RoundToNearestInteger(b)); + + r = Avx.Multiply(r, scaledK); + g = Avx.Multiply(g, scaledK); + b = Avx.Multiply(b, scaledK); + + c0 = r; + c1 = g; + c2 = b; + } +#endif + } + protected override void ConvertCore(in ComponentValues values, Span result) => FromYccKBasic.ConvertCore(values, result, this.MaximumValue, this.HalfValue); + + protected override void ConvertCoreInplace(in ComponentValues values) => + FromYccKBasic.ConvertCoreInplace(values, this.MaximumValue, this.HalfValue); } } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKBasic.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKBasic.cs index 778e5325ff..b0cde69712 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKBasic.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKBasic.cs @@ -20,6 +20,9 @@ public override void ConvertToRgba(in ComponentValues values, Span resu ConvertCore(values, result, this.MaximumValue, this.HalfValue); } + public override void ConvertToRgbInplace(in ComponentValues values) => + ConvertCoreInplace(values, this.MaximumValue, this.HalfValue); + internal static void ConvertCore(in ComponentValues values, Span result, float maxValue, float halfValue) { // TODO: We can optimize a lot here with Vector and SRCS.Unsafe()! @@ -50,6 +53,30 @@ internal static void ConvertCore(in ComponentValues values, Span result result[i] = v; } } + + internal static void ConvertCoreInplace(in ComponentValues values, float maxValue, float halfValue) + { + Span c0 = values.Component0; + Span c1 = values.Component1; + Span c2 = values.Component2; + Span c3 = values.Component3; + + var v = new Vector4(0, 0, 0, 1F); + + var scale = 1 / (maxValue * maxValue); + + for (int i = 0; i < values.Component0.Length; i++) + { + float y = c0[i]; + float cb = c1[i] - halfValue; + float cr = c2[i] - halfValue; + float scaledK = c3[i] * scale; + + c0[i] = (maxValue - MathF.Round(y + (1.402F * cr), MidpointRounding.AwayFromZero)) * scaledK; + c1[i] = (maxValue - MathF.Round(y - (0.344136F * cb) - (0.714136F * cr), MidpointRounding.AwayFromZero)) * scaledK; + c2[i] = (maxValue - MathF.Round(y + (1.772F * cb), MidpointRounding.AwayFromZero)) * scaledK; + } + } } } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKVector8.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKVector8.cs index c360392de8..64f29f1f89 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKVector8.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKVector8.cs @@ -84,8 +84,63 @@ protected override void ConvertCoreVectorized(in ComponentValues values, Span c0Base = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0)); + ref Vector c1Base = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1)); + ref Vector c2Base = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2)); + ref Vector kBase = + ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component3)); + + var chromaOffset = new Vector(-this.HalfValue); + + // Walking 8 elements at one step: + int n = values.Component0.Length / 8; + + var scale = new Vector(1 / (this.MaximumValue * this.MaximumValue)); + var max = new Vector(this.MaximumValue); + + for (int i = 0; i < n; i++) + { + // y = yVals[i]; + // cb = cbVals[i] - 128F; + // cr = crVals[i] - 128F; + // k = kVals[i] / 256F; + ref Vector c0 = ref Unsafe.Add(ref c0Base, i); + ref Vector c1 = ref Unsafe.Add(ref c1Base, i); + ref Vector c2 = ref Unsafe.Add(ref c2Base, i); + + Vector y = c0; + Vector cb = c1 + chromaOffset; + Vector cr = c2 + chromaOffset; + Vector scaledK = Unsafe.Add(ref kBase, i) * scale; + + // 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 r = y + (cr * new Vector(1.402F)); + Vector g = y - (cb * new Vector(0.344136F)) - (cr * new Vector(0.714136F)); + Vector b = y + (cb * new Vector(1.772F)); + + r = (max - r.FastRound()) * scaledK; + g = (max - g.FastRound()) * scaledK; + b = (max - b.FastRound()) * scaledK; + + c0 = r; + c1 = g; + c2 = b; + } + } + protected override void ConvertCore(in ComponentValues values, Span result) => FromYccKBasic.ConvertCore(values, result, this.MaximumValue, this.HalfValue); + + protected override void ConvertCoreInplace(in ComponentValues values) => + FromYccKBasic.ConvertCoreInplace(values, this.MaximumValue, this.HalfValue); } } } From 5f90e020fc5eeb6c7a826c0fd30b9fc27ec35d47 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 3 Oct 2021 00:26:56 +0200 Subject: [PATCH 05/24] Change SpectralConverter to use inplace converters and PackFromRgbPlanes --- .../ColorConverters/JpegColorConverter.cs | 6 +- .../Decoder/SpectralConverter{TPixel}.cs | 64 +++++++++++++------ .../Formats/Jpeg/JpegDecoderCore.cs | 2 +- .../Decompressors/JpegTiffCompression.cs | 2 +- src/ImageSharp/Memory/Buffer2D{T}.cs | 31 +++++++++ .../MemoryGroupExtensions.cs | 29 +++++++++ .../PixelOperations/Rgb24.PixelOperations.cs | 4 +- .../PixelOperations/Rgba32.PixelOperations.cs | 4 +- .../PixelFormats/PixelOperations{TPixel}.cs | 14 ++-- .../Jpg/SpectralToPixelConversionTests.cs | 2 +- .../ImageSharp.Tests/Memory/Buffer2DTests.cs | 26 ++++++++ 11 files changed, 147 insertions(+), 37 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs index 8efbf92b64..95829e8109 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs @@ -234,9 +234,9 @@ internal ComponentValues( public ComponentValues Slice(int start, int length) { Span c0 = this.Component0.Slice(start, length); - Span c1 = this.ComponentCount > 1 ? this.Component1.Slice(start, length) : Span.Empty; - Span c2 = this.ComponentCount > 2 ? this.Component2.Slice(start, length) : Span.Empty; - Span c3 = this.ComponentCount > 3 ? this.Component3.Slice(start, length) : Span.Empty; + Span c1 = this.Component1.Length > 0 ? this.Component1.Slice(start, length) : Span.Empty; + Span c2 = this.Component2.Length > 0 ? this.Component2.Slice(start, length) : Span.Empty; + Span c3 = this.Component3.Length > 0 ? this.Component3.Slice(start, length) : Span.Empty; return new ComponentValues(this.ComponentCount, c0, c1, c2, c3); } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs index 313a132b81..313457ea26 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs @@ -22,7 +22,10 @@ internal class SpectralConverter : SpectralConverter, IDisposable private JpegColorConverter colorConverter; - private IMemoryOwner rgbaBuffer; + // private IMemoryOwner rgbaBuffer; + private IMemoryOwner rgbBuffer; + + private IMemoryOwner paddedProxyPixelRow; private Buffer2D pixelBuffer; @@ -40,23 +43,20 @@ public SpectralConverter(Configuration configuration, CancellationToken cancella private bool Converted => this.pixelRowCounter >= this.pixelBuffer.Height; - public Buffer2D PixelBuffer + public Buffer2D GetPixelBuffer() { - get + if (!this.Converted) { - if (!this.Converted) - { - int steps = (int)Math.Ceiling(this.pixelBuffer.Height / (float)this.pixelRowsPerStep); + int steps = (int) Math.Ceiling(this.pixelBuffer.Height / (float) this.pixelRowsPerStep); - for (int step = 0; step < steps; step++) - { - this.cancellationToken.ThrowIfCancellationRequested(); - this.ConvertNextStride(step); - } + for (int step = 0; step < steps; step++) + { + this.cancellationToken.ThrowIfCancellationRequested(); + this.ConvertNextStride(step); } - - return this.pixelBuffer; } + + return this.pixelBuffer; } /// @@ -72,7 +72,8 @@ public override void InjectFrameData(JpegFrame frame, IRawJpegData jpegData) this.pixelRowsPerStep = this.blockRowsPerStep * blockPixelHeight; // pixel buffer for resulting image - this.pixelBuffer = allocator.Allocate2D(frame.PixelWidth, frame.PixelHeight, AllocationOptions.Clean); + this.pixelBuffer = allocator.Allocate2D(frame.PixelWidth, frame.PixelHeight); + this.paddedProxyPixelRow = allocator.Allocate(frame.PixelWidth + 3); // component processors from spectral to Rgba32 var postProcessorBufferSize = new Size(c0.SizeInBlocks.Width * 8, this.pixelRowsPerStep); @@ -83,7 +84,8 @@ public override void InjectFrameData(JpegFrame frame, IRawJpegData jpegData) } // single 'stride' rgba32 buffer for conversion between spectral and TPixel - this.rgbaBuffer = allocator.Allocate(frame.PixelWidth); + // this.rgbaBuffer = allocator.Allocate(frame.PixelWidth); + this.rgbBuffer = allocator.Allocate(frame.PixelWidth * 3); // color converter from Rgba32 to TPixel this.colorConverter = this.GetColorConverter(frame, jpegData); @@ -115,7 +117,8 @@ public void Dispose() } } - this.rgbaBuffer?.Dispose(); + this.rgbBuffer?.Dispose(); + this.paddedProxyPixelRow?.Dispose(); } private void ConvertNextStride(int spectralStep) @@ -129,17 +132,38 @@ private void ConvertNextStride(int spectralStep) buffers[i] = this.componentProcessors[i].ColorBuffer; } + int width = this.pixelBuffer.Width; + for (int yy = this.pixelRowCounter; yy < maxY; yy++) { int y = yy - this.pixelRowCounter; var values = new JpegColorConverter.ComponentValues(buffers, y); - this.colorConverter.ConvertToRgba(values, this.rgbaBuffer.GetSpan()); - Span destRow = this.pixelBuffer.GetRowSpan(yy); + this.colorConverter.ConvertToRgbInplace(values); + values = values.Slice(0, width); // slice away Jpeg padding - // TODO: Investigate if slicing is actually necessary - PixelOperations.Instance.FromVector4Destructive(this.configuration, this.rgbaBuffer.GetSpan().Slice(0, destRow.Length), destRow); + Span r = this.rgbBuffer.Slice(0, width); + Span g = this.rgbBuffer.Slice(width, width); + Span b = this.rgbBuffer.Slice(width * 2, width); + + SimdUtils.NormalizedFloatToByteSaturate(values.Component0, r); + SimdUtils.NormalizedFloatToByteSaturate(values.Component1, g); + SimdUtils.NormalizedFloatToByteSaturate(values.Component2, b); + + // PackFromRgbPlanes expects the destination to be padded, so try to get padded span containing extra elements from the next row. + // If we can't get such a padded row because we are on a MemoryGroup boundary or at the last row, + // pack pixels to a temporary, padded proxy buffer, then copy the relevant values to the destination row. + if (this.pixelBuffer.TryGetPaddedRowSpan(yy, 3, out Span destRow)) + { + PixelOperations.Instance.PackFromRgbPlanes(this.configuration, r, g, b, destRow); + } + else + { + Span proxyRow = this.paddedProxyPixelRow.GetSpan(); + PixelOperations.Instance.PackFromRgbPlanes(this.configuration, r, g, b, proxyRow); + proxyRow.Slice(0, width).CopyTo(this.pixelBuffer.GetRowSpan(yy)); + } } this.pixelRowCounter += this.pixelRowsPerStep; diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs index a0f69bb7bf..9a9e5eb799 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs @@ -185,7 +185,7 @@ public Image Decode(BufferedReadStream stream, CancellationToken this.InitIptcProfile(); this.InitDerivedMetadataProperties(); - return new Image(this.Configuration, spectralConverter.PixelBuffer, this.Metadata); + return new Image(this.Configuration, spectralConverter.GetPixelBuffer(), this.Metadata); } /// diff --git a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/JpegTiffCompression.cs b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/JpegTiffCompression.cs index e764c014d3..9a0607584e 100644 --- a/src/ImageSharp/Formats/Tiff/Compression/Decompressors/JpegTiffCompression.cs +++ b/src/ImageSharp/Formats/Tiff/Compression/Decompressors/JpegTiffCompression.cs @@ -65,7 +65,7 @@ protected override void Decompress(BufferedReadStream stream, int byteCount, int scanDecoder.ResetInterval = 0; jpegDecoder.ParseStream(stream, scanDecoder, CancellationToken.None); - CopyImageBytesToBuffer(buffer, spectralConverter.PixelBuffer); + CopyImageBytesToBuffer(buffer, spectralConverter.GetPixelBuffer()); } else { diff --git a/src/ImageSharp/Memory/Buffer2D{T}.cs b/src/ImageSharp/Memory/Buffer2D{T}.cs index 21c19f5d52..4f7aa3419c 100644 --- a/src/ImageSharp/Memory/Buffer2D{T}.cs +++ b/src/ImageSharp/Memory/Buffer2D{T}.cs @@ -116,6 +116,36 @@ public Span GetRowSpan(int y) : this.GetRowMemorySlow(y).Span; } + internal bool TryGetPaddedRowSpan(int y, int padding, out Span paddedSpan) + { + DebugGuard.MustBeGreaterThanOrEqualTo(y, 0, nameof(y)); + DebugGuard.MustBeLessThan(y, this.Height, nameof(y)); + + int stride = this.Width + padding; + if (this.cachedMemory.Length > 0) + { + paddedSpan = this.cachedMemory.Span.Slice(y * this.Width); + if (paddedSpan.Length < stride) + { + return false; + } + + paddedSpan = paddedSpan.Slice(0, stride); + return true; + } + + Memory memory = this.FastMemoryGroup.GetRemainingSliceOfBuffer(y * (long)this.Width); + + if (memory.Length < stride) + { + paddedSpan = default; + return false; + } + + paddedSpan = memory.Span.Slice(0, stride); + return true; + } + [MethodImpl(InliningOptions.ShortMethod)] internal ref T GetElementUnsafe(int x, int y) { @@ -202,6 +232,7 @@ internal static void SwapOrCopyContent(Buffer2D destination, Buffer2D sour [MethodImpl(InliningOptions.ColdPath)] private Memory GetRowMemorySlow(int y) => this.FastMemoryGroup.GetBoundedSlice(y * (long)this.Width, this.Width); + [MethodImpl(InliningOptions.ColdPath)] private Memory DangerousGetSingleMemorySlow() => this.FastMemoryGroup.Single(); diff --git a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupExtensions.cs b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupExtensions.cs index da42b30ad8..319c72af52 100644 --- a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupExtensions.cs +++ b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupExtensions.cs @@ -61,6 +61,35 @@ internal static Memory GetBoundedSlice(this IMemoryGroup group, long st return memory.Slice(bufferStart, length); } + /// + /// Returns the slice of the buffer starting at global index that goes until the end of the buffer. + /// + internal static Memory GetRemainingSliceOfBuffer(this IMemoryGroup group, long start) + where T : struct + { + Guard.NotNull(group, nameof(group)); + Guard.IsTrue(group.IsValid, nameof(group), "Group must be valid!"); + Guard.MustBeLessThan(start, group.TotalLength, nameof(start)); + + int bufferIdx = (int)(start / group.BufferLength); + + if (bufferIdx < 0) + { + throw new ArgumentOutOfRangeException(nameof(start)); + } + + if (bufferIdx >= group.Count) + { + throw new ArgumentOutOfRangeException(nameof(start)); + } + + int bufferStart = (int)(start % group.BufferLength); + + Memory memory = group[bufferIdx]; + + return memory.Slice(bufferStart); + } + internal static void CopyTo(this IMemoryGroup source, Span target) where T : struct { diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgb24.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgb24.PixelOperations.cs index f345f58bcd..0f1ea6b815 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgb24.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgb24.PixelOperations.cs @@ -32,9 +32,7 @@ internal override void PackFromRgbPlanes( { Guard.NotNull(configuration, nameof(configuration)); int count = redChannel.Length; - Guard.IsTrue(greenChannel.Length == count, nameof(greenChannel), "Channels must be of same size!"); - Guard.IsTrue(blueChannel.Length == count, nameof(blueChannel), "Channels must be of same size!"); - Guard.IsTrue(destination.Length > count + 2, nameof(destination), "'destination' must contain a padding of 3 elements!"); + GuardPackFromRgbPlanes(greenChannel, blueChannel, destination, count); SimdUtils.PackFromRgbPlanes(configuration, redChannel, greenChannel, blueChannel, destination); } diff --git a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgba32.PixelOperations.cs b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgba32.PixelOperations.cs index 9633059774..d937da98fd 100644 --- a/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgba32.PixelOperations.cs +++ b/src/ImageSharp/PixelFormats/PixelImplementations/PixelOperations/Rgba32.PixelOperations.cs @@ -67,9 +67,7 @@ internal override void PackFromRgbPlanes( { Guard.NotNull(configuration, nameof(configuration)); int count = redChannel.Length; - Guard.IsTrue(greenChannel.Length == count, nameof(greenChannel), "Channels must be of same size!"); - Guard.IsTrue(blueChannel.Length == count, nameof(blueChannel), "Channels must be of same size!"); - Guard.IsTrue(destination.Length > count, nameof(destination), "'destination' span should not be shorter than the source channels!"); + GuardPackFromRgbPlanes(greenChannel, blueChannel, destination, count); SimdUtils.PackFromRgbPlanes(configuration, redChannel, greenChannel, blueChannel, destination); } diff --git a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs index c5450538e4..f748a4b574 100644 --- a/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs +++ b/src/ImageSharp/PixelFormats/PixelOperations{TPixel}.cs @@ -181,11 +181,7 @@ internal virtual void PackFromRgbPlanes( Guard.NotNull(configuration, nameof(configuration)); int count = redChannel.Length; - Guard.IsTrue(greenChannel.Length == count, nameof(greenChannel), "Channels must be of same size!"); - Guard.IsTrue(blueChannel.Length == count, nameof(blueChannel), "Channels must be of same size!"); - Guard.IsTrue(destination.Length > count + 2, nameof(destination), "'destination' must contain a padding of 3 elements!"); - - Guard.DestinationShouldNotBeTooShort(redChannel, destination, nameof(destination)); + GuardPackFromRgbPlanes(greenChannel, blueChannel, destination, count); Rgb24 rgb24 = default; ref byte r = ref MemoryMarshal.GetReference(redChannel); @@ -201,5 +197,13 @@ internal virtual void PackFromRgbPlanes( Unsafe.Add(ref d, i).FromRgb24(rgb24); } } + + [MethodImpl(InliningOptions.ShortMethod)] + internal static void GuardPackFromRgbPlanes(ReadOnlySpan greenChannel, ReadOnlySpan blueChannel, Span destination, int count) + { + Guard.IsTrue(greenChannel.Length == count, nameof(greenChannel), "Channels must be of same size!"); + Guard.IsTrue(blueChannel.Length == count, nameof(blueChannel), "Channels must be of same size!"); + Guard.IsTrue(destination.Length > count + 2, nameof(destination), "'destination' must contain a padding of 3 elements!"); + } } } diff --git a/tests/ImageSharp.Tests/Formats/Jpg/SpectralToPixelConversionTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/SpectralToPixelConversionTests.cs index 353ae39f0f..f0f92d763e 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/SpectralToPixelConversionTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/SpectralToPixelConversionTests.cs @@ -53,7 +53,7 @@ public void Decoder_PixelBufferComparison(TestImageProvider prov provider.Utility.TestName = JpegDecoderTests.DecodeBaselineJpegOutputName; // Comparison - using (Image image = new Image(Configuration.Default, converter.PixelBuffer, new ImageMetadata())) + using (Image image = new Image(Configuration.Default, converter.GetPixelBuffer(), new ImageMetadata())) using (Image referenceImage = provider.GetReferenceOutputImage(appendPixelTypeToFileName: false)) { ImageSimilarityReport report = ImageComparer.Exact.CompareImagesOrFrames(referenceImage, image); diff --git a/tests/ImageSharp.Tests/Memory/Buffer2DTests.cs b/tests/ImageSharp.Tests/Memory/Buffer2DTests.cs index 015b3617bc..4e097f3f13 100644 --- a/tests/ImageSharp.Tests/Memory/Buffer2DTests.cs +++ b/tests/ImageSharp.Tests/Memory/Buffer2DTests.cs @@ -118,6 +118,32 @@ public unsafe void GetRowSpanY(int bufferCapacity, int width, int height, int y, } } + [Theory] + [InlineData(10, 0, 0, 0)] + [InlineData(10, 0, 2, 0)] + [InlineData(10, 1, 2, 0)] + [InlineData(10, 1, 3, 0)] + [InlineData(10, 1, 5, -1)] + [InlineData(10, 2, 2, -1)] + [InlineData(10, 3, 2, 1)] + [InlineData(10, 4, 2, -1)] + [InlineData(30, 3, 2, 0)] + [InlineData(30, 4, 1, -1)] + public void TryGetPaddedRowSpanY(int bufferCapacity, int y, int padding, int expectedBufferIndex) + { + this.MemoryAllocator.BufferCapacityInBytes = bufferCapacity; + using Buffer2D buffer = this.MemoryAllocator.Allocate2D(3, 5); + + bool expectSuccess = expectedBufferIndex >= 0; + bool success = buffer.TryGetPaddedRowSpan(y, padding, out Span paddedSpan); + Xunit.Assert.Equal(expectSuccess, success); + if (success) + { + int expectedSubBufferOffset = (3 * y) - (expectedBufferIndex * buffer.FastMemoryGroup.BufferLength); + Assert.SpanPointsTo(paddedSpan, buffer.FastMemoryGroup[expectedBufferIndex], expectedSubBufferOffset); + } + } + public static TheoryData GetRowSpanY_OutOfRange_Data = new TheoryData() { { Big, 10, 8, -1 }, From c9d6556bf7bff2e6344c7140eda74b1a61979ad3 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 3 Oct 2021 01:07:11 +0200 Subject: [PATCH 06/24] simplify DecodeJpeg_ImageSpecific benchmark --- .../Codecs/Jpeg/DecodeJpeg_ImageSpecific.cs | 10 +++++----- tests/ImageSharp.Benchmarks/Config.cs | 2 -- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg_ImageSpecific.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg_ImageSpecific.cs index b0ac1c0fc0..da2c81f869 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg_ImageSpecific.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/DecodeJpeg_ImageSpecific.cs @@ -44,8 +44,8 @@ public void ReadImages() } } - [Benchmark(Baseline = true, Description = "Decode Jpeg - System.Drawing")] - public SDSize JpegSystemDrawing() + [Benchmark(Baseline = true)] + public SDSize SystemDrawing() { using (var memoryStream = new MemoryStream(this.jpegBytes)) { @@ -56,12 +56,12 @@ public SDSize JpegSystemDrawing() } } - [Benchmark(Description = "Decode Jpeg - ImageSharp")] - public Size JpegImageSharp() + [Benchmark] + public Size ImageSharp() { using (var memoryStream = new MemoryStream(this.jpegBytes)) { - using (var image = Image.Load(memoryStream, new JpegDecoder { IgnoreMetadata = true })) + using (var image = Image.Load(memoryStream, new JpegDecoder { IgnoreMetadata = true })) { return new Size(image.Width, image.Height); } diff --git a/tests/ImageSharp.Benchmarks/Config.cs b/tests/ImageSharp.Benchmarks/Config.cs index 63064eec5b..ccc4a7b9f6 100644 --- a/tests/ImageSharp.Benchmarks/Config.cs +++ b/tests/ImageSharp.Benchmarks/Config.cs @@ -33,7 +33,6 @@ public class MultiFramework : Config { public MultiFramework() => this.AddJob( Job.Default.WithRuntime(ClrRuntime.Net472), - Job.Default.WithRuntime(CoreRuntime.Core21), Job.Default.WithRuntime(CoreRuntime.Core31)); } @@ -41,7 +40,6 @@ public class ShortMultiFramework : Config { public ShortMultiFramework() => this.AddJob( Job.Default.WithRuntime(ClrRuntime.Net472).WithLaunchCount(1).WithWarmupCount(3).WithIterationCount(3), - Job.Default.WithRuntime(CoreRuntime.Core21).WithLaunchCount(1).WithWarmupCount(3).WithIterationCount(3), Job.Default.WithRuntime(CoreRuntime.Core31).WithLaunchCount(1).WithWarmupCount(3).WithIterationCount(3)); } From d798450ef6cb2bc831b636b7565a10b83c6eea60 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 3 Oct 2021 01:26:20 +0200 Subject: [PATCH 07/24] Decode into Rgb24 by default --- src/ImageSharp/Formats/Jpeg/JpegDecoder.cs | 2 +- .../Formats/Jpg/JpegDecoderTests.Baseline.cs | 8 ++++---- .../Formats/Jpg/JpegDecoderTests.Metadata.cs | 14 +++++++------- .../Formats/Jpg/JpegDecoderTests.Progressive.cs | 12 ++++++------ .../Formats/Jpg/JpegDecoderTests.cs | 10 +++++++++- 5 files changed, 27 insertions(+), 19 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs index b0bdbf0ed2..be03a7e7bb 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegDecoder.cs @@ -28,7 +28,7 @@ public Image Decode(Configuration configuration, Stream stream) /// public Image Decode(Configuration configuration, Stream stream) - => this.Decode(configuration, stream); + => this.Decode(configuration, stream); /// public Task> DecodeAsync(Configuration configuration, Stream stream, CancellationToken cancellationToken) diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs index 7002bfd65e..021e3d2726 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs @@ -13,9 +13,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg public partial class JpegDecoderTests { [Theory] - [WithFileCollection(nameof(BaselineTestJpegs), PixelTypes.Rgba32, false)] - [WithFile(TestImages.Jpeg.Baseline.Calliphora, PixelTypes.Rgba32, true)] - [WithFile(TestImages.Jpeg.Baseline.Turtle420, PixelTypes.Rgba32, true)] + [WithFileCollection(nameof(BaselineTestJpegs), PixelTypes.Rgb24, false)] + [WithFile(TestImages.Jpeg.Baseline.Calliphora, PixelTypes.Rgb24, true)] + [WithFile(TestImages.Jpeg.Baseline.Turtle420, PixelTypes.Rgb24, true)] public void DecodeBaselineJpeg(TestImageProvider provider, bool enforceDiscontiguousBuffers) where TPixel : unmanaged, IPixel { @@ -26,7 +26,7 @@ static void RunTest(string providerDump, string nonContiguousBuffersStr) if (!string.IsNullOrEmpty(nonContiguousBuffersStr)) { - provider.LimitAllocatorBufferCapacity().InPixels(1000 * 8); + provider.LimitAllocatorBufferCapacity().InPixels(16_000); } using Image image = provider.GetImage(JpegDecoder); diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs index e5f8989c5c..e4fa137191 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Metadata.cs @@ -83,7 +83,7 @@ public void Decode_VerifyRatio(string imagePath, int xResolution, int yResolutio using (var stream = new MemoryStream(testFile.Bytes, false)) { var decoder = new JpegDecoder(); - using (Image image = decoder.Decode(Configuration.Default, stream)) + using (Image image = decoder.Decode(Configuration.Default, stream)) { ImageMetadata meta = image.Metadata; Assert.Equal(xResolution, meta.HorizontalResolution); @@ -130,7 +130,7 @@ public void Decode_VerifyQuality(string imagePath, int quality) var testFile = TestFile.Create(imagePath); using (var stream = new MemoryStream(testFile.Bytes, false)) { - using (Image image = JpegDecoder.Decode(Configuration.Default, stream)) + using (Image image = JpegDecoder.Decode(Configuration.Default, stream)) { JpegMetadata meta = image.Metadata.GetJpegMetadata(); Assert.Equal(quality, meta.Quality); @@ -159,11 +159,11 @@ public void Identify_DetectsCorrectColorType(string imagePath, JpegColorType exp } [Theory] - [WithFile(TestImages.Jpeg.Baseline.Floorplan, PixelTypes.Rgba32, JpegColorType.Luminance)] - [WithFile(TestImages.Jpeg.Baseline.Jpeg420Small, PixelTypes.Rgba32, JpegColorType.YCbCrRatio420)] - [WithFile(TestImages.Jpeg.Baseline.Jpeg444, PixelTypes.Rgba32, JpegColorType.YCbCrRatio444)] - [WithFile(TestImages.Jpeg.Baseline.JpegRgb, PixelTypes.Rgba32, JpegColorType.Rgb)] - [WithFile(TestImages.Jpeg.Baseline.Cmyk, PixelTypes.Rgba32, JpegColorType.Cmyk)] + [WithFile(TestImages.Jpeg.Baseline.Floorplan, PixelTypes.Rgb24, JpegColorType.Luminance)] + [WithFile(TestImages.Jpeg.Baseline.Jpeg420Small, PixelTypes.Rgb24, JpegColorType.YCbCrRatio420)] + [WithFile(TestImages.Jpeg.Baseline.Jpeg444, PixelTypes.Rgb24, JpegColorType.YCbCrRatio444)] + [WithFile(TestImages.Jpeg.Baseline.JpegRgb, PixelTypes.Rgb24, JpegColorType.Rgb)] + [WithFile(TestImages.Jpeg.Baseline.Cmyk, PixelTypes.Rgb24, JpegColorType.Cmyk)] public void Decode_DetectsCorrectColorType(TestImageProvider provider, JpegColorType expectedColorType) where TPixel : unmanaged, IPixel { diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs index 9beb8358c6..e8533b9bca 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs @@ -15,7 +15,7 @@ public partial class JpegDecoderTests public const string DecodeProgressiveJpegOutputName = "DecodeProgressiveJpeg"; [Theory] - [WithFileCollection(nameof(ProgressiveTestJpegs), PixelTypes.Rgba32)] + [WithFileCollection(nameof(ProgressiveTestJpegs), PixelTypes.Rgb24)] public void DecodeProgressiveJpeg(TestImageProvider provider) where TPixel : unmanaged, IPixel { @@ -30,17 +30,17 @@ public void DecodeProgressiveJpeg(TestImageProvider provider) } [Theory] - [WithFile(TestImages.Jpeg.Progressive.Progress, PixelTypes.Rgba32)] - public void DecodeProgressiveJpeg_WithLimitedAllocatorBufferCapacity(TestImageProvider provider) + [WithFile(TestImages.Jpeg.Progressive.Progress, PixelTypes.Rgb24)] + public void DecodeProgressiveJpeg_WithLimitedAllocatorBufferCapacity(TestImageProvider provider) { static void RunTest(string providerDump, string nonContiguousBuffersStr) { - TestImageProvider provider = - BasicSerializer.Deserialize>(providerDump); + TestImageProvider provider = + BasicSerializer.Deserialize>(providerDump); provider.LimitAllocatorBufferCapacity().InBytesSqrt(200); - using Image image = provider.GetImage(JpegDecoder); + using Image image = provider.GetImage(JpegDecoder); image.DebugSave(provider, nonContiguousBuffersStr); provider.Utility.TestName = DecodeProgressiveJpegOutputName; diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs index 2a18a2c103..2cbc290273 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.cs @@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg [Trait("Format", "Jpg")] public partial class JpegDecoderTests { - public const PixelTypes CommonNonDefaultPixelTypes = PixelTypes.Rgba32 | PixelTypes.Argb32 | PixelTypes.RgbaVector; + public const PixelTypes CommonNonDefaultPixelTypes = PixelTypes.Rgba32 | PixelTypes.Argb32 | PixelTypes.Bgr24 | PixelTypes.RgbaVector; private const float BaselineTolerance = 0.001F / 100; @@ -85,6 +85,14 @@ public void ParseStream_BasicPropertiesAreCorrect() public const string DecodeBaselineJpegOutputName = "DecodeBaselineJpeg"; + [Fact] + public void Decode_NonGeneric_CreatesRgb24Image() + { + string file = Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, TestImages.Jpeg.Baseline.Jpeg420Small); + using var image = Image.Load(file); + Assert.IsType>(image); + } + [Theory] [WithFile(TestImages.Jpeg.Baseline.Calliphora, CommonNonDefaultPixelTypes)] public void JpegDecoder_IsNotBoundToSinglePixelType(TestImageProvider provider) From 06566c5ab3bd0bfc367266989dfe8c24ade3d0e0 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 3 Oct 2021 03:03:36 +0200 Subject: [PATCH 08/24] Resize: do not premultiply pixels with no alpha --- .../PixelFormats/Utils/Vector4Converters.cs | 4 +- .../Resize/ResizeProcessor{TPixel}.cs | 3 + .../Processing/Resize.cs | 31 ++++++ .../Processors/Transforms/ResizeTests.cs | 102 +++++++++--------- ...thCropMode_issue1006-incorrect-resize.png} | 0 ...FromSourceRectangle_CalliphoraPartial.png} | 0 ...HeightAndKeepAspect_CalliphoraPartial.png} | 0 ...eWidthAndKeepAspect_CalliphoraPartial.png} | 0 ...esizeWithBoxPadMode_CalliphoraPartial.png} | 0 ...eWithCropHeightMode_CalliphoraPartial.png} | 0 ...zeWithCropWidthMode_CalliphoraPartial.png} | 0 ...> ResizeWithMaxMode_CalliphoraPartial.png} | 0 ...> ResizeWithMinMode_CalliphoraPartial.png} | 0 ...> ResizeWithPadMode_CalliphoraPartial.png} | 0 ...sizeWithStretchMode_CalliphoraPartial.png} | 0 ...SinglePixelType_Bgr24_TestPattern50x50.png | 3 + 16 files changed, 88 insertions(+), 55 deletions(-) rename tests/Images/External/ReferenceOutput/ResizeTests/{CanResizeLargeImageWithCropMode_Rgba32_issue1006-incorrect-resize.png => CanResizeLargeImageWithCropMode_issue1006-incorrect-resize.png} (100%) rename tests/Images/External/ReferenceOutput/ResizeTests/{ResizeFromSourceRectangle_Rgba32_CalliphoraPartial.png => ResizeFromSourceRectangle_CalliphoraPartial.png} (100%) rename tests/Images/External/ReferenceOutput/ResizeTests/{ResizeHeightAndKeepAspect_Rgba32_CalliphoraPartial.png => ResizeHeightAndKeepAspect_CalliphoraPartial.png} (100%) rename tests/Images/External/ReferenceOutput/ResizeTests/{ResizeWidthAndKeepAspect_Rgba32_CalliphoraPartial.png => ResizeWidthAndKeepAspect_CalliphoraPartial.png} (100%) rename tests/Images/External/ReferenceOutput/ResizeTests/{ResizeWithBoxPadMode_Rgba32_CalliphoraPartial.png => ResizeWithBoxPadMode_CalliphoraPartial.png} (100%) rename tests/Images/External/ReferenceOutput/ResizeTests/{ResizeWithCropHeightMode_Rgba32_CalliphoraPartial.png => ResizeWithCropHeightMode_CalliphoraPartial.png} (100%) rename tests/Images/External/ReferenceOutput/ResizeTests/{ResizeWithCropWidthMode_Rgba32_CalliphoraPartial.png => ResizeWithCropWidthMode_CalliphoraPartial.png} (100%) rename tests/Images/External/ReferenceOutput/ResizeTests/{ResizeWithMaxMode_Rgba32_CalliphoraPartial.png => ResizeWithMaxMode_CalliphoraPartial.png} (100%) rename tests/Images/External/ReferenceOutput/ResizeTests/{ResizeWithMinMode_Rgba32_CalliphoraPartial.png => ResizeWithMinMode_CalliphoraPartial.png} (100%) rename tests/Images/External/ReferenceOutput/ResizeTests/{ResizeWithPadMode_Rgba32_CalliphoraPartial.png => ResizeWithPadMode_CalliphoraPartial.png} (100%) rename tests/Images/External/ReferenceOutput/ResizeTests/{ResizeWithStretchMode_Rgba32_CalliphoraPartial.png => ResizeWithStretchMode_CalliphoraPartial.png} (100%) create mode 100644 tests/Images/External/ReferenceOutput/ResizeTests/Resize_IsNotBoundToSinglePixelType_Bgr24_TestPattern50x50.png diff --git a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.cs b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.cs index 7af2662765..8335d2fd9a 100644 --- a/src/ImageSharp/PixelFormats/Utils/Vector4Converters.cs +++ b/src/ImageSharp/PixelFormats/Utils/Vector4Converters.cs @@ -14,7 +14,7 @@ internal static partial class Vector4Converters /// /// Apply modifiers used requested by ToVector4() conversion. /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(InliningOptions.ShortMethod)] internal static void ApplyForwardConversionModifiers(Span vectors, PixelConversionModifiers modifiers) { if (modifiers.IsDefined(PixelConversionModifiers.SRgbCompand)) @@ -31,7 +31,7 @@ internal static void ApplyForwardConversionModifiers(Span vectors, Pixe /// /// Apply modifiers used requested by FromVector4() conversion. /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] + [MethodImpl(InliningOptions.ShortMethod)] internal static void ApplyBackwardConversionModifiers(Span vectors, PixelConversionModifiers modifiers) { if (modifiers.IsDefined(PixelConversionModifiers.Premultiply)) diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs index ec238608e9..1daed9ee63 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs @@ -4,6 +4,7 @@ using System; using System.Runtime.CompilerServices; using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Formats; using SixLabors.ImageSharp.Memory; using SixLabors.ImageSharp.PixelFormats; @@ -187,6 +188,8 @@ private static void ApplyResizeFrameTransform( bool compand, bool premultiplyAlpha) { + bool pixelHasNoAlpha = PixelOperations.Instance.GetPixelTypeInfo()?.AlphaRepresentation == PixelAlphaRepresentation.None; + premultiplyAlpha &= !pixelHasNoAlpha; PixelConversionModifiers conversionModifiers = GetModifiers(compand, premultiplyAlpha); Buffer2DRegion sourceRegion = source.PixelBuffer.GetRegion(sourceRectangle); diff --git a/tests/ImageSharp.Benchmarks/Processing/Resize.cs b/tests/ImageSharp.Benchmarks/Processing/Resize.cs index 571c92cc87..81fdbfb314 100644 --- a/tests/ImageSharp.Benchmarks/Processing/Resize.cs +++ b/tests/ImageSharp.Benchmarks/Processing/Resize.cs @@ -215,4 +215,35 @@ protected override void ExecuteResizeOperation(IImageProcessingContext ctx) // SystemDrawing | Core | Core | 3032 | 400 | 118.3 ms | 6.899 ms | 0.3781 ms | 1.00 | 0.00 | - | - | - | 96 B | // 'ImageSharp, MaxDegreeOfParallelism = 1' | Core | Core | 3032 | 400 | 122.4 ms | 15.069 ms | 0.8260 ms | 1.03 | 0.01 | - | - | - | 15712 B | } + + public class Resize_Bicubic_Compare_Rgba32_Rgb24 + { + private Resize_Bicubic_Rgb24 rgb24; + private Resize_Bicubic_Rgba32 rgba32; + + [GlobalSetup] + public void Setup() + { + this.rgb24 = new Resize_Bicubic_Rgb24(); + this.rgb24.Setup(); + this.rgba32 = new Resize_Bicubic_Rgba32(); + this.rgba32.Setup(); + } + + [GlobalCleanup] + public void Cleanup() + { + this.rgb24.Cleanup(); + this.rgba32.Cleanup(); + } + + [Benchmark] + public void SystemDrawing() => this.rgba32.SystemDrawing(); + + [Benchmark(Baseline = true)] + public void Rgba32() => this.rgba32.ImageSharp_P1(); + + [Benchmark] + public void Rgb24() => this.rgb24.ImageSharp_P1(); + } } diff --git a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs index 42cf1e3c12..3c0faf4991 100644 --- a/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs +++ b/tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs @@ -19,9 +19,7 @@ namespace SixLabors.ImageSharp.Tests.Processing.Processors.Transforms public class ResizeTests { private const PixelTypes CommonNonDefaultPixelTypes = - PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.RgbaVector; - - private const PixelTypes DefaultPixelType = PixelTypes.Rgba32; + PixelTypes.Rgba32 | PixelTypes.Bgra32 | PixelTypes.Bgr24 | PixelTypes.RgbaVector; public static readonly string[] AllResamplerNames = TestUtils.GetAllResamplerNames(); @@ -188,7 +186,7 @@ public void WorksWithDiscoBuffers( } [Theory] - [WithTestPatternImages(100, 100, DefaultPixelType)] + [WithTestPatternImages(100, 100, PixelTypes.Rgba32)] public void Resize_Compand(TestImageProvider provider) where TPixel : unmanaged, IPixel { @@ -202,8 +200,8 @@ public void Resize_Compand(TestImageProvider provider) } [Theory] - [WithFile(TestImages.Png.Kaboom, DefaultPixelType, false)] - [WithFile(TestImages.Png.Kaboom, DefaultPixelType, true)] + [WithFile(TestImages.Png.Kaboom, PixelTypes.Rgba32, false)] + [WithFile(TestImages.Png.Kaboom, PixelTypes.Rgba32, true)] public void Resize_DoesNotBleedAlphaPixels(TestImageProvider provider, bool compand) where TPixel : unmanaged, IPixel { @@ -217,8 +215,8 @@ public void Resize_DoesNotBleedAlphaPixels(TestImageProvider pro } [Theory] - [WithFile(TestImages.Png.Kaboom, DefaultPixelType, false)] - [WithFile(TestImages.Png.Kaboom, DefaultPixelType, true)] + [WithFile(TestImages.Png.Kaboom, PixelTypes.Rgba32, false)] + [WithFile(TestImages.Png.Kaboom, PixelTypes.Rgba32, true)] public void Resize_PremultiplyAlpha(TestImageProvider provider, bool premultiplyAlpha) where TPixel : unmanaged, IPixel { @@ -243,7 +241,7 @@ public void Resize_PremultiplyAlpha(TestImageProvider provider, } [Theory] - [WithFile(TestImages.Gif.Giphy, DefaultPixelType)] + [WithFile(TestImages.Gif.Giphy, PixelTypes.Rgba32)] public void Resize_IsAppliedToAllFrames(TestImageProvider provider) where TPixel : unmanaged, IPixel { @@ -265,7 +263,7 @@ public void Resize_IsNotBoundToSinglePixelType(TestImageProvider } [Theory] - [WithFileCollection(nameof(CommonTestImages), DefaultPixelType)] + [WithFileCollection(nameof(CommonTestImages), PixelTypes.Rgba32)] public void Resize_ThrowsForWrappedMemoryImage(TestImageProvider provider) where TPixel : unmanaged, IPixel { @@ -283,10 +281,10 @@ public void Resize_ThrowsForWrappedMemoryImage(TestImageProvider } [Theory] - [WithFileCollection(nameof(CommonTestImages), DefaultPixelType, 1)] - [WithFileCollection(nameof(CommonTestImages), DefaultPixelType, 4)] - [WithFileCollection(nameof(CommonTestImages), DefaultPixelType, 8)] - [WithFileCollection(nameof(CommonTestImages), DefaultPixelType, -1)] + [WithFileCollection(nameof(CommonTestImages), PixelTypes.Rgba32 | PixelTypes.Rgb24, 1)] + [WithFileCollection(nameof(CommonTestImages), PixelTypes.Rgba32 | PixelTypes.Rgb24, 4)] + [WithFileCollection(nameof(CommonTestImages), PixelTypes.Rgba32 | PixelTypes.Rgb24, 8)] + [WithFileCollection(nameof(CommonTestImages), PixelTypes.Rgba32 | PixelTypes.Rgb24, -1)] public void Resize_WorksWithAllParallelismLevels( TestImageProvider provider, int maxDegreeOfParallelism) @@ -305,27 +303,27 @@ public void Resize_WorksWithAllParallelismLevels( } [Theory] - [WithFileCollection(nameof(CommonTestImages), nameof(AllResamplerNames), DefaultPixelType, 0.5f, null, null)] + [WithFileCollection(nameof(CommonTestImages), nameof(AllResamplerNames), PixelTypes.Rgba32 | PixelTypes.Rgb24, 0.5f, null, null)] [WithFileCollection( nameof(CommonTestImages), nameof(SmokeTestResamplerNames), - DefaultPixelType, + PixelTypes.Rgba32 | PixelTypes.Rgb24, 0.3f, null, null)] [WithFileCollection( nameof(CommonTestImages), nameof(SmokeTestResamplerNames), - DefaultPixelType, + PixelTypes.Rgba32 | PixelTypes.Rgb24, 1.8f, null, null)] - [WithTestPatternImages(nameof(SmokeTestResamplerNames), 100, 100, DefaultPixelType, 0.5f, null, null)] - [WithTestPatternImages(nameof(SmokeTestResamplerNames), 100, 100, DefaultPixelType, 1f, null, null)] - [WithTestPatternImages(nameof(SmokeTestResamplerNames), 50, 50, DefaultPixelType, 8f, null, null)] - [WithTestPatternImages(nameof(SmokeTestResamplerNames), 201, 199, DefaultPixelType, null, 100, 99)] - [WithTestPatternImages(nameof(SmokeTestResamplerNames), 301, 1180, DefaultPixelType, null, 300, 480)] - [WithTestPatternImages(nameof(SmokeTestResamplerNames), 49, 80, DefaultPixelType, null, 301, 100)] + [WithTestPatternImages(nameof(SmokeTestResamplerNames), 100, 100, PixelTypes.Rgba32, 0.5f, null, null)] + [WithTestPatternImages(nameof(SmokeTestResamplerNames), 100, 100, PixelTypes.Rgba32, 1f, null, null)] + [WithTestPatternImages(nameof(SmokeTestResamplerNames), 50, 50, PixelTypes.Rgba32, 8f, null, null)] + [WithTestPatternImages(nameof(SmokeTestResamplerNames), 201, 199, PixelTypes.Rgba32, null, 100, 99)] + [WithTestPatternImages(nameof(SmokeTestResamplerNames), 301, 1180, PixelTypes.Rgba32, null, 300, 480)] + [WithTestPatternImages(nameof(SmokeTestResamplerNames), 49, 80, PixelTypes.Rgba32, null, 301, 100)] public void Resize_WorksWithAllResamplers( TestImageProvider provider, string samplerName, @@ -382,7 +380,7 @@ public void Resize_WorksWithAllResamplers( } [Theory] - [WithFileCollection(nameof(CommonTestImages), DefaultPixelType)] + [WithFileCollection(nameof(CommonTestImages), PixelTypes.Rgba32 | PixelTypes.Rgb24)] public void ResizeFromSourceRectangle(TestImageProvider provider) where TPixel : unmanaged, IPixel { @@ -405,12 +403,12 @@ public void ResizeFromSourceRectangle(TestImageProvider provider false)); image.DebugSave(provider); - image.CompareToReferenceOutput(ValidatorComparer, provider); + image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false); } } [Theory] - [WithFileCollection(nameof(CommonTestImages), DefaultPixelType)] + [WithFileCollection(nameof(CommonTestImages), PixelTypes.Rgba32 | PixelTypes.Rgb24)] public void ResizeHeightAndKeepAspect(TestImageProvider provider) where TPixel : unmanaged, IPixel { @@ -419,12 +417,12 @@ public void ResizeHeightAndKeepAspect(TestImageProvider provider image.Mutate(x => x.Resize(0, image.Height / 3, false)); image.DebugSave(provider); - image.CompareToReferenceOutput(ValidatorComparer, provider); + image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false); } } [Theory] - [WithTestPatternImages(10, 100, DefaultPixelType)] + [WithTestPatternImages(10, 100, PixelTypes.Rgba32 | PixelTypes.Rgb24)] public void ResizeHeightCannotKeepAspectKeepsOnePixel(TestImageProvider provider) where TPixel : unmanaged, IPixel { @@ -437,7 +435,7 @@ public void ResizeHeightCannotKeepAspectKeepsOnePixel(TestImageProvider< } [Theory] - [WithFileCollection(nameof(CommonTestImages), DefaultPixelType)] + [WithFileCollection(nameof(CommonTestImages), PixelTypes.Rgba32 | PixelTypes.Rgb24)] public void ResizeWidthAndKeepAspect(TestImageProvider provider) where TPixel : unmanaged, IPixel { @@ -446,12 +444,12 @@ public void ResizeWidthAndKeepAspect(TestImageProvider provider) image.Mutate(x => x.Resize(image.Width / 3, 0, false)); image.DebugSave(provider); - image.CompareToReferenceOutput(ValidatorComparer, provider); + image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false); } } [Theory] - [WithTestPatternImages(100, 10, DefaultPixelType)] + [WithTestPatternImages(100, 10, PixelTypes.Rgba32 | PixelTypes.Rgb24)] public void ResizeWidthCannotKeepAspectKeepsOnePixel(TestImageProvider provider) where TPixel : unmanaged, IPixel { @@ -464,7 +462,7 @@ public void ResizeWidthCannotKeepAspectKeepsOnePixel(TestImageProvider(TestImageProvider provider) where TPixel : unmanaged, IPixel { @@ -479,12 +477,12 @@ public void ResizeWithBoxPadMode(TestImageProvider provider) image.Mutate(x => x.Resize(options)); image.DebugSave(provider); - image.CompareToReferenceOutput(ValidatorComparer, provider); + image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false); } } [Theory] - [WithFileCollection(nameof(CommonTestImages), DefaultPixelType)] + [WithFileCollection(nameof(CommonTestImages), PixelTypes.Rgba32 | PixelTypes.Rgb24)] public void ResizeWithCropHeightMode(TestImageProvider provider) where TPixel : unmanaged, IPixel { @@ -495,12 +493,12 @@ public void ResizeWithCropHeightMode(TestImageProvider provider) image.Mutate(x => x.Resize(options)); image.DebugSave(provider); - image.CompareToReferenceOutput(ValidatorComparer, provider); + image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false); } } [Theory] - [WithFileCollection(nameof(CommonTestImages), DefaultPixelType)] + [WithFileCollection(nameof(CommonTestImages), PixelTypes.Rgba32 | PixelTypes.Rgb24)] public void ResizeWithCropWidthMode(TestImageProvider provider) where TPixel : unmanaged, IPixel { @@ -511,12 +509,12 @@ public void ResizeWithCropWidthMode(TestImageProvider provider) image.Mutate(x => x.Resize(options)); image.DebugSave(provider); - image.CompareToReferenceOutput(ValidatorComparer, provider); + image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false); } } [Theory] - [WithFile(TestImages.Jpeg.Issues.IncorrectResize1006, DefaultPixelType)] + [WithFile(TestImages.Jpeg.Issues.IncorrectResize1006, PixelTypes.Rgba32 | PixelTypes.Rgb24)] public void CanResizeLargeImageWithCropMode(TestImageProvider provider) where TPixel : unmanaged, IPixel { @@ -531,12 +529,12 @@ public void CanResizeLargeImageWithCropMode(TestImageProvider pr image.Mutate(x => x.Resize(options)); image.DebugSave(provider); - image.CompareToReferenceOutput(ValidatorComparer, provider); + image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false); } } [Theory] - [WithFileCollection(nameof(CommonTestImages), DefaultPixelType)] + [WithFileCollection(nameof(CommonTestImages), PixelTypes.Rgba32 | PixelTypes.Rgb24)] public void ResizeWithMaxMode(TestImageProvider provider) where TPixel : unmanaged, IPixel { @@ -547,12 +545,12 @@ public void ResizeWithMaxMode(TestImageProvider provider) image.Mutate(x => x.Resize(options)); image.DebugSave(provider); - image.CompareToReferenceOutput(ValidatorComparer, provider); + image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false); } } [Theory] - [WithFileCollection(nameof(CommonTestImages), DefaultPixelType)] + [WithFileCollection(nameof(CommonTestImages), PixelTypes.Rgba32 | PixelTypes.Rgb24)] public void ResizeWithMinMode(TestImageProvider provider) where TPixel : unmanaged, IPixel { @@ -560,21 +558,19 @@ public void ResizeWithMinMode(TestImageProvider provider) { var options = new ResizeOptions { - Size = new Size( - (int)Math.Round(image.Width * .75F), - (int)Math.Round(image.Height * .95F)), + Size = new Size((int)Math.Round(image.Width * .75F), (int)Math.Round(image.Height * .95F)), Mode = ResizeMode.Min }; image.Mutate(x => x.Resize(options)); image.DebugSave(provider); - image.CompareToReferenceOutput(ValidatorComparer, provider); + image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false); } } [Theory] - [WithFileCollection(nameof(CommonTestImages), DefaultPixelType)] + [WithFileCollection(nameof(CommonTestImages), PixelTypes.Rgba32 | PixelTypes.Rgb24)] public void ResizeWithPadMode(TestImageProvider provider) where TPixel : unmanaged, IPixel { @@ -589,12 +585,12 @@ public void ResizeWithPadMode(TestImageProvider provider) image.Mutate(x => x.Resize(options)); image.DebugSave(provider); - image.CompareToReferenceOutput(ValidatorComparer, provider); + image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false); } } [Theory] - [WithFileCollection(nameof(CommonTestImages), DefaultPixelType)] + [WithFileCollection(nameof(CommonTestImages), PixelTypes.Rgba32 | PixelTypes.Rgb24)] public void ResizeWithStretchMode(TestImageProvider provider) where TPixel : unmanaged, IPixel { @@ -609,14 +605,14 @@ public void ResizeWithStretchMode(TestImageProvider provider) image.Mutate(x => x.Resize(options)); image.DebugSave(provider); - image.CompareToReferenceOutput(ValidatorComparer, provider); + image.CompareToReferenceOutput(ValidatorComparer, provider, appendPixelTypeToFileName: false); } } [Theory] - [WithFile(TestImages.Jpeg.Issues.ExifDecodeOutOfRange694, DefaultPixelType)] - [WithFile(TestImages.Jpeg.Issues.ExifGetString750Transform, DefaultPixelType)] - [WithFile(TestImages.Jpeg.Issues.ExifResize1049, DefaultPixelType)] + [WithFile(TestImages.Jpeg.Issues.ExifDecodeOutOfRange694, PixelTypes.Rgb24)] + [WithFile(TestImages.Jpeg.Issues.ExifGetString750Transform, PixelTypes.Rgb24)] + [WithFile(TestImages.Jpeg.Issues.ExifResize1049, PixelTypes.Rgb24)] public void CanResizeExifIssueImages(TestImageProvider provider) where TPixel : unmanaged, IPixel { diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/CanResizeLargeImageWithCropMode_Rgba32_issue1006-incorrect-resize.png b/tests/Images/External/ReferenceOutput/ResizeTests/CanResizeLargeImageWithCropMode_issue1006-incorrect-resize.png similarity index 100% rename from tests/Images/External/ReferenceOutput/ResizeTests/CanResizeLargeImageWithCropMode_Rgba32_issue1006-incorrect-resize.png rename to tests/Images/External/ReferenceOutput/ResizeTests/CanResizeLargeImageWithCropMode_issue1006-incorrect-resize.png diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/ResizeFromSourceRectangle_Rgba32_CalliphoraPartial.png b/tests/Images/External/ReferenceOutput/ResizeTests/ResizeFromSourceRectangle_CalliphoraPartial.png similarity index 100% rename from tests/Images/External/ReferenceOutput/ResizeTests/ResizeFromSourceRectangle_Rgba32_CalliphoraPartial.png rename to tests/Images/External/ReferenceOutput/ResizeTests/ResizeFromSourceRectangle_CalliphoraPartial.png diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/ResizeHeightAndKeepAspect_Rgba32_CalliphoraPartial.png b/tests/Images/External/ReferenceOutput/ResizeTests/ResizeHeightAndKeepAspect_CalliphoraPartial.png similarity index 100% rename from tests/Images/External/ReferenceOutput/ResizeTests/ResizeHeightAndKeepAspect_Rgba32_CalliphoraPartial.png rename to tests/Images/External/ReferenceOutput/ResizeTests/ResizeHeightAndKeepAspect_CalliphoraPartial.png diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWidthAndKeepAspect_Rgba32_CalliphoraPartial.png b/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWidthAndKeepAspect_CalliphoraPartial.png similarity index 100% rename from tests/Images/External/ReferenceOutput/ResizeTests/ResizeWidthAndKeepAspect_Rgba32_CalliphoraPartial.png rename to tests/Images/External/ReferenceOutput/ResizeTests/ResizeWidthAndKeepAspect_CalliphoraPartial.png diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithBoxPadMode_Rgba32_CalliphoraPartial.png b/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithBoxPadMode_CalliphoraPartial.png similarity index 100% rename from tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithBoxPadMode_Rgba32_CalliphoraPartial.png rename to tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithBoxPadMode_CalliphoraPartial.png diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithCropHeightMode_Rgba32_CalliphoraPartial.png b/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithCropHeightMode_CalliphoraPartial.png similarity index 100% rename from tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithCropHeightMode_Rgba32_CalliphoraPartial.png rename to tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithCropHeightMode_CalliphoraPartial.png diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithCropWidthMode_Rgba32_CalliphoraPartial.png b/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithCropWidthMode_CalliphoraPartial.png similarity index 100% rename from tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithCropWidthMode_Rgba32_CalliphoraPartial.png rename to tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithCropWidthMode_CalliphoraPartial.png diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithMaxMode_Rgba32_CalliphoraPartial.png b/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithMaxMode_CalliphoraPartial.png similarity index 100% rename from tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithMaxMode_Rgba32_CalliphoraPartial.png rename to tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithMaxMode_CalliphoraPartial.png diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithMinMode_Rgba32_CalliphoraPartial.png b/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithMinMode_CalliphoraPartial.png similarity index 100% rename from tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithMinMode_Rgba32_CalliphoraPartial.png rename to tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithMinMode_CalliphoraPartial.png diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithPadMode_Rgba32_CalliphoraPartial.png b/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithPadMode_CalliphoraPartial.png similarity index 100% rename from tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithPadMode_Rgba32_CalliphoraPartial.png rename to tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithPadMode_CalliphoraPartial.png diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithStretchMode_Rgba32_CalliphoraPartial.png b/tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithStretchMode_CalliphoraPartial.png similarity index 100% rename from tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithStretchMode_Rgba32_CalliphoraPartial.png rename to tests/Images/External/ReferenceOutput/ResizeTests/ResizeWithStretchMode_CalliphoraPartial.png diff --git a/tests/Images/External/ReferenceOutput/ResizeTests/Resize_IsNotBoundToSinglePixelType_Bgr24_TestPattern50x50.png b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_IsNotBoundToSinglePixelType_Bgr24_TestPattern50x50.png new file mode 100644 index 0000000000..674639d482 --- /dev/null +++ b/tests/Images/External/ReferenceOutput/ResizeTests/Resize_IsNotBoundToSinglePixelType_Bgr24_TestPattern50x50.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4a9940410cca3fe98a6d7aaf0e2184779f908c569a5a34f9965fb3a4f9e6fa8f +size 1066 From 5ba6461c6df9b4f05df4231c8e38e2994eaee0e0 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 3 Oct 2021 03:30:42 +0200 Subject: [PATCH 09/24] fix whitespace issues --- .../Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs | 2 +- src/ImageSharp/Memory/Buffer2D{T}.cs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs index 313457ea26..ec7f3e5c30 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/SpectralConverter{TPixel}.cs @@ -47,7 +47,7 @@ public Buffer2D GetPixelBuffer() { if (!this.Converted) { - int steps = (int) Math.Ceiling(this.pixelBuffer.Height / (float) this.pixelRowsPerStep); + int steps = (int)Math.Ceiling(this.pixelBuffer.Height / (float)this.pixelRowsPerStep); for (int step = 0; step < steps; step++) { diff --git a/src/ImageSharp/Memory/Buffer2D{T}.cs b/src/ImageSharp/Memory/Buffer2D{T}.cs index 4f7aa3419c..b62c9beb54 100644 --- a/src/ImageSharp/Memory/Buffer2D{T}.cs +++ b/src/ImageSharp/Memory/Buffer2D{T}.cs @@ -232,7 +232,6 @@ internal static void SwapOrCopyContent(Buffer2D destination, Buffer2D sour [MethodImpl(InliningOptions.ColdPath)] private Memory GetRowMemorySlow(int y) => this.FastMemoryGroup.GetBoundedSlice(y * (long)this.Width, this.Width); - [MethodImpl(InliningOptions.ColdPath)] private Memory DangerousGetSingleMemorySlow() => this.FastMemoryGroup.Single(); From adcc6d48ed64f711059e9c0869b0b23e7d77e51d Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 3 Oct 2021 03:48:05 +0200 Subject: [PATCH 10/24] remove old JpegColorConverter methods --- .../JpegColorConverter.FromCmykAvx2.cs | 55 ------------ .../JpegColorConverter.FromCmykBasic.cs | 5 -- .../JpegColorConverter.FromCmykVector8.cs | 49 ----------- .../JpegColorConverter.FromGrayScaleAvx2.cs | 37 -------- .../JpegColorConverter.FromGrayScaleBasic.cs | 5 -- .../JpegColorConverter.FromRgbAvx2.cs | 46 ---------- .../JpegColorConverter.FromRgbBasic.cs | 5 -- .../JpegColorConverter.FromRgbVector8.cs | 45 ---------- .../JpegColorConverter.FromYCbCrAvx2.cs | 74 ---------------- .../JpegColorConverter.FromYCbCrBasic.cs | 5 -- .../JpegColorConverter.FromYCbCrVector4.cs | 68 --------------- .../JpegColorConverter.FromYCbCrVector8.cs | 64 -------------- .../JpegColorConverter.FromYccKAvx2.cs | 84 ------------------- .../JpegColorConverter.FromYccKBasic.cs | 5 -- .../JpegColorConverter.FromYccKVector8.cs | 69 --------------- ...rConverter.VectorizedJpegColorConverter.cs | 24 ------ .../ColorConverters/JpegColorConverter.cs | 9 +- 17 files changed, 3 insertions(+), 646 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx2.cs index 634e0faaf3..ad5f9acd24 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx2.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx2.cs @@ -22,58 +22,6 @@ public FromCmykAvx2(int precision) { } - protected override void ConvertCoreVectorized(in ComponentValues values, Span result) - { -#if SUPPORTS_RUNTIME_INTRINSICS - ref Vector256 cBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0)); - ref Vector256 mBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1)); - ref Vector256 yBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2)); - ref Vector256 kBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component3)); - - ref Vector256 resultBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(result)); - - // Used for the color conversion - var scale = Vector256.Create(1 / this.MaximumValue); - var one = Vector256.Create(1F); - - // Used for packing - ref byte control = ref MemoryMarshal.GetReference(HwIntrinsics.PermuteMaskEvenOdd8x32); - Vector256 vcontrol = Unsafe.As>(ref control); - - int n = result.Length / 8; - for (int i = 0; i < n; i++) - { - Vector256 k = Avx2.PermuteVar8x32(Unsafe.Add(ref kBase, i), vcontrol); - Vector256 c = Avx2.PermuteVar8x32(Unsafe.Add(ref cBase, i), vcontrol); - Vector256 m = Avx2.PermuteVar8x32(Unsafe.Add(ref mBase, i), vcontrol); - Vector256 y = Avx2.PermuteVar8x32(Unsafe.Add(ref yBase, i), vcontrol); - - k = Avx.Multiply(k, scale); - - c = Avx.Multiply(Avx.Multiply(c, k), scale); - m = Avx.Multiply(Avx.Multiply(m, k), scale); - y = Avx.Multiply(Avx.Multiply(y, k), scale); - - Vector256 cmLo = Avx.UnpackLow(c, m); - Vector256 yoLo = Avx.UnpackLow(y, one); - Vector256 cmHi = Avx.UnpackHigh(c, m); - Vector256 yoHi = Avx.UnpackHigh(y, one); - - ref Vector256 destination = ref Unsafe.Add(ref resultBase, i * 4); - - destination = Avx.Shuffle(cmLo, yoLo, 0b01_00_01_00); - Unsafe.Add(ref destination, 1) = Avx.Shuffle(cmLo, yoLo, 0b11_10_11_10); - Unsafe.Add(ref destination, 2) = Avx.Shuffle(cmHi, yoHi, 0b01_00_01_00); - Unsafe.Add(ref destination, 3) = Avx.Shuffle(cmHi, yoHi, 0b11_10_11_10); - } -#endif - } - protected override void ConvertCoreVectorizedInplace(in ComponentValues values) { #if SUPPORTS_RUNTIME_INTRINSICS @@ -105,9 +53,6 @@ protected override void ConvertCoreVectorizedInplace(in ComponentValues values) #endif } - protected override void ConvertCore(in ComponentValues values, Span result) => - FromCmykBasic.ConvertCore(values, result, this.MaximumValue); - protected override void ConvertCoreInplace(in ComponentValues values) => FromCmykBasic.ConvertCoreInplace(values, this.MaximumValue); } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykBasic.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykBasic.cs index f4a9529e10..72d1735999 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykBasic.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykBasic.cs @@ -15,11 +15,6 @@ public FromCmykBasic(int precision) { } - public override void ConvertToRgba(in ComponentValues values, Span result) - { - ConvertCore(values, result, this.MaximumValue); - } - public override void ConvertToRgbInplace(in ComponentValues values) => ConvertCoreInplace(values, this.MaximumValue); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykVector8.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykVector8.cs index b55ec2e0f4..7a272d148d 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykVector8.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykVector8.cs @@ -18,52 +18,6 @@ public FromCmykVector8(int precision) { } - protected override void ConvertCoreVectorized(in ComponentValues values, Span result) - { - ref Vector cBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0)); - ref Vector mBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1)); - ref Vector yBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2)); - ref Vector kBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component3)); - - ref Vector4Octet resultBase = - ref Unsafe.As(ref MemoryMarshal.GetReference(result)); - - Vector4Pair cc = default; - Vector4Pair mm = default; - Vector4Pair yy = default; - ref Vector ccRefAsVector = ref Unsafe.As>(ref cc); - ref Vector mmRefAsVector = ref Unsafe.As>(ref mm); - ref Vector yyRefAsVector = ref Unsafe.As>(ref yy); - - var scale = new Vector(1 / this.MaximumValue); - - // Walking 8 elements at one step: - int n = result.Length / 8; - for (int i = 0; i < n; i++) - { - Vector c = Unsafe.Add(ref cBase, i); - Vector m = Unsafe.Add(ref mBase, i); - Vector y = Unsafe.Add(ref yBase, i); - Vector k = Unsafe.Add(ref kBase, i) * scale; - - c = (c * k) * scale; - m = (m * k) * scale; - y = (y * k) * scale; - - ccRefAsVector = c; - mmRefAsVector = m; - yyRefAsVector = y; - - // Collect (c0,c1...c8) (m0,m1...m8) (y0,y1...y8) vector values in the expected (r0,g0,g1,1), (r1,g1,g2,1) ... order: - ref Vector4Octet destination = ref Unsafe.Add(ref resultBase, i); - destination.Pack(ref cc, ref mm, ref yy); - } - } - protected override void ConvertCoreVectorizedInplace(in ComponentValues values) { ref Vector cBase = @@ -92,9 +46,6 @@ protected override void ConvertCoreVectorizedInplace(in ComponentValues values) } } - protected override void ConvertCore(in ComponentValues values, Span result) => - FromCmykBasic.ConvertCore(values, result, this.MaximumValue); - protected override void ConvertCoreInplace(in ComponentValues values) => FromCmykBasic.ConvertCoreInplace(values, this.MaximumValue); } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleAvx2.cs index 4efabf64a6..c54ecdedcc 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleAvx2.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleAvx2.cs @@ -22,40 +22,6 @@ public FromGrayscaleAvx2(int precision) { } - protected override void ConvertCoreVectorized(in ComponentValues values, Span result) - { -#if SUPPORTS_RUNTIME_INTRINSICS - ref Vector256 gBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0)); - - ref Vector256 resultBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(result)); - - // Used for the color conversion - var scale = Vector256.Create(1 / this.MaximumValue); - var one = Vector256.Create(1F); - - // Used for packing - ref byte control = ref MemoryMarshal.GetReference(HwIntrinsics.PermuteMaskEvenOdd8x32); - Vector256 vcontrol = Unsafe.As>(ref control); - - int n = result.Length / 8; - for (int i = 0; i < n; i++) - { - Vector256 g = Avx.Multiply(Unsafe.Add(ref gBase, i), scale); - - g = Avx2.PermuteVar8x32(g, vcontrol); - - ref Vector256 destination = ref Unsafe.Add(ref resultBase, i * 4); - - destination = Avx.Blend(Avx.Permute(g, 0b00_00_00_00), one, 0b1000_1000); - Unsafe.Add(ref destination, 1) = Avx.Blend(Avx.Shuffle(g, g, 0b01_01_01_01), one, 0b1000_1000); - Unsafe.Add(ref destination, 2) = Avx.Blend(Avx.Shuffle(g, g, 0b10_10_10_10), one, 0b1000_1000); - Unsafe.Add(ref destination, 3) = Avx.Blend(Avx.Shuffle(g, g, 0b11_11_11_11), one, 0b1000_1000); - } -#endif - } - protected override void ConvertCoreVectorizedInplace(in ComponentValues values) { #if SUPPORTS_RUNTIME_INTRINSICS @@ -74,9 +40,6 @@ protected override void ConvertCoreVectorizedInplace(in ComponentValues values) #endif } - protected override void ConvertCore(in ComponentValues values, Span result) => - FromGrayscaleBasic.ConvertCore(values, result, this.MaximumValue); - protected override void ConvertCoreInplace(in ComponentValues values) => FromGrayscaleBasic.ScaleValues(values.Component0, this.MaximumValue); } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleBasic.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleBasic.cs index faf6f203f9..28735a61f9 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleBasic.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleBasic.cs @@ -17,11 +17,6 @@ public FromGrayscaleBasic(int precision) { } - public override void ConvertToRgba(in ComponentValues values, Span result) - { - ConvertCore(values, result, this.MaximumValue); - } - public override void ConvertToRgbInplace(in ComponentValues values) => ScaleValues(values.Component0, this.MaximumValue); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbAvx2.cs index 505e1ca224..2ec78c5273 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbAvx2.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbAvx2.cs @@ -22,49 +22,6 @@ public FromRgbAvx2(int precision) { } - protected override void ConvertCoreVectorized(in ComponentValues values, Span result) - { -#if SUPPORTS_RUNTIME_INTRINSICS - ref Vector256 rBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0)); - ref Vector256 gBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1)); - ref Vector256 bBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2)); - - ref Vector256 resultBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(result)); - - // Used for the color conversion - var scale = Vector256.Create(1 / this.MaximumValue); - var one = Vector256.Create(1F); - - // Used for packing - ref byte control = ref MemoryMarshal.GetReference(HwIntrinsics.PermuteMaskEvenOdd8x32); - Vector256 vcontrol = Unsafe.As>(ref control); - - int n = result.Length / 8; - for (int i = 0; i < n; i++) - { - Vector256 r = Avx.Multiply(Avx2.PermuteVar8x32(Unsafe.Add(ref rBase, i), vcontrol), scale); - Vector256 g = Avx.Multiply(Avx2.PermuteVar8x32(Unsafe.Add(ref gBase, i), vcontrol), scale); - Vector256 b = Avx.Multiply(Avx2.PermuteVar8x32(Unsafe.Add(ref bBase, i), vcontrol), scale); - - Vector256 rgLo = Avx.UnpackLow(r, g); - Vector256 boLo = Avx.UnpackLow(b, one); - Vector256 rgHi = Avx.UnpackHigh(r, g); - Vector256 boHi = Avx.UnpackHigh(b, one); - - ref Vector256 destination = ref Unsafe.Add(ref resultBase, i * 4); - - destination = Avx.Shuffle(rgLo, boLo, 0b01_00_01_00); - Unsafe.Add(ref destination, 1) = Avx.Shuffle(rgLo, boLo, 0b11_10_11_10); - Unsafe.Add(ref destination, 2) = Avx.Shuffle(rgHi, boHi, 0b01_00_01_00); - Unsafe.Add(ref destination, 3) = Avx.Shuffle(rgHi, boHi, 0b11_10_11_10); - } -#endif - } - protected override void ConvertCoreVectorizedInplace(in ComponentValues values) { #if SUPPORTS_RUNTIME_INTRINSICS @@ -90,9 +47,6 @@ protected override void ConvertCoreVectorizedInplace(in ComponentValues values) #endif } - protected override void ConvertCore(in ComponentValues values, Span result) => - FromRgbBasic.ConvertCore(values, result, this.MaximumValue); - protected override void ConvertCoreInplace(in ComponentValues values) => FromRgbBasic.ConvertCoreInplace(values, this.MaximumValue); } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbBasic.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbBasic.cs index 313583f4a8..0159b9c741 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbBasic.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbBasic.cs @@ -16,11 +16,6 @@ public FromRgbBasic(int precision) { } - public override void ConvertToRgba(in ComponentValues values, Span result) - { - ConvertCore(values, result, this.MaximumValue); - } - public override void ConvertToRgbInplace(in ComponentValues values) { ConvertCoreInplace(values, this.MaximumValue); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbVector8.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbVector8.cs index 0db568217b..3def60186e 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbVector8.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbVector8.cs @@ -18,48 +18,6 @@ public FromRgbVector8(int precision) { } - protected override void ConvertCoreVectorized(in ComponentValues values, Span result) - { - ref Vector rBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0)); - ref Vector gBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1)); - ref Vector bBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2)); - - ref Vector4Octet resultBase = - ref Unsafe.As(ref MemoryMarshal.GetReference(result)); - - Vector4Pair rr = default; - Vector4Pair gg = default; - Vector4Pair bb = default; - ref Vector rrRefAsVector = ref Unsafe.As>(ref rr); - ref Vector ggRefAsVector = ref Unsafe.As>(ref gg); - ref Vector bbRefAsVector = ref Unsafe.As>(ref bb); - - var scale = new Vector(1 / this.MaximumValue); - - // Walking 8 elements at one step: - int n = result.Length / 8; - for (int i = 0; i < n; i++) - { - Vector r = Unsafe.Add(ref rBase, i); - Vector g = Unsafe.Add(ref gBase, i); - Vector b = Unsafe.Add(ref bBase, i); - r *= scale; - g *= scale; - b *= scale; - - rrRefAsVector = r; - ggRefAsVector = g; - bbRefAsVector = b; - - // Collect (r0,r1...r8) (g0,g1...g8) (b0,b1...b8) vector values in the expected (r0,g0,g1,1), (r1,g1,g2,1) ... order: - ref Vector4Octet destination = ref Unsafe.Add(ref resultBase, i); - destination.Pack(ref rr, ref gg, ref bb); - } - } - protected override void ConvertCoreVectorizedInplace(in ComponentValues values) { ref Vector rBase = @@ -84,9 +42,6 @@ protected override void ConvertCoreVectorizedInplace(in ComponentValues values) } } - protected override void ConvertCore(in ComponentValues values, Span result) => - FromRgbBasic.ConvertCore(values, result, this.MaximumValue); - protected override void ConvertCoreInplace(in ComponentValues values) => FromRgbBasic.ConvertCoreInplace(values, this.MaximumValue); } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrAvx2.cs index 83d4024447..67447aae5e 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrAvx2.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrAvx2.cs @@ -23,77 +23,6 @@ public FromYCbCrAvx2(int precision) { } - protected override void ConvertCoreVectorized(in ComponentValues values, Span result) - { -#if SUPPORTS_RUNTIME_INTRINSICS - ref Vector256 yBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0)); - ref Vector256 cbBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1)); - ref Vector256 crBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2)); - - ref Vector256 resultBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(result)); - - // 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 vcontrol = Unsafe.As>(ref control); - - // Walking 8 elements at one step: - int n = result.Length / 8; - for (int i = 0; i < n; i++) - { - // y = yVals[i]; - // cb = cbVals[i] - 128F; - // cr = crVals[i] - 128F; - Vector256 y = Unsafe.Add(ref yBase, i); - Vector256 cb = Avx.Add(Unsafe.Add(ref cbBase, i), chromaOffset); - Vector256 cr = Avx.Add(Unsafe.Add(ref crBase, i), chromaOffset); - - y = Avx2.PermuteVar8x32(y, vcontrol); - cb = Avx2.PermuteVar8x32(cb, vcontrol); - cr = Avx2.PermuteVar8x32(cr, vcontrol); - - // 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 r = HwIntrinsics.MultiplyAdd(y, cr, rCrMult); - Vector256 g = HwIntrinsics.MultiplyAdd(HwIntrinsics.MultiplyAdd(y, cb, gCbMult), cr, gCrMult); - Vector256 b = HwIntrinsics.MultiplyAdd(y, cb, bCbMult); - - // TODO: We should be saving to RGBA not Vector4 - r = Avx.Multiply(Avx.RoundToNearestInteger(r), scale); - g = Avx.Multiply(Avx.RoundToNearestInteger(g), scale); - b = Avx.Multiply(Avx.RoundToNearestInteger(b), scale); - - Vector256 vte = Avx.UnpackLow(r, b); - Vector256 vto = Avx.UnpackLow(g, va); - - ref Vector256 destination = ref Unsafe.Add(ref resultBase, i * 4); - - destination = Avx.UnpackLow(vte, vto); - Unsafe.Add(ref destination, 1) = Avx.UnpackHigh(vte, vto); - - vte = Avx.UnpackHigh(r, b); - vto = Avx.UnpackHigh(g, va); - - Unsafe.Add(ref destination, 2) = Avx.UnpackLow(vte, vto); - Unsafe.Add(ref destination, 3) = Avx.UnpackHigh(vte, vto); - } -#endif - } - protected override void ConvertCoreVectorizedInplace(in ComponentValues values) { #if SUPPORTS_RUNTIME_INTRINSICS @@ -151,9 +80,6 @@ protected override void ConvertCoreVectorizedInplace(in ComponentValues values) #endif } - protected override void ConvertCore(in ComponentValues values, Span result) => - FromYCbCrBasic.ConvertCore(values, result, this.MaximumValue, this.HalfValue); - protected override void ConvertCoreInplace(in ComponentValues values) => FromYCbCrBasic.ConvertCoreInplace(values, this.MaximumValue, this.HalfValue); } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs index cc37e4e7dc..040aaac2b0 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs @@ -15,11 +15,6 @@ public FromYCbCrBasic(int precision) { } - public override void ConvertToRgba(in ComponentValues values, Span result) - { - ConvertCore(values, result, this.MaximumValue, this.HalfValue); - } - public override void ConvertToRgbInplace(in ComponentValues values) => ConvertCoreInplace(values, this.MaximumValue, this.HalfValue); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector4.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector4.cs index c770111cf7..f65ba30260 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector4.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector4.cs @@ -20,71 +20,6 @@ public FromYCbCrVector4(int precision) protected override bool IsAvailable => SimdUtils.HasVector4; - protected override void ConvertCoreVectorized(in ComponentValues values, Span result) - { - // TODO: Find a way to properly run & test this path on AVX2 PC-s! (Have I already mentioned that Vector is terrible?) - DebugGuard.IsTrue(result.Length % 8 == 0, nameof(result), "result.Length should be divisible by 8!"); - - ref Vector4Pair yBase = - ref Unsafe.As(ref MemoryMarshal.GetReference(values.Component0)); - ref Vector4Pair cbBase = - ref Unsafe.As(ref MemoryMarshal.GetReference(values.Component1)); - ref Vector4Pair crBase = - ref Unsafe.As(ref MemoryMarshal.GetReference(values.Component2)); - - ref Vector4Octet resultBase = - ref Unsafe.As(ref MemoryMarshal.GetReference(result)); - - var chromaOffset = new Vector4(-this.HalfValue); - var maxValue = this.MaximumValue; - - // Walking 8 elements at one step: - int n = result.Length / 8; - - for (int i = 0; i < n; i++) - { - // y = yVals[i]; - Vector4Pair y = Unsafe.Add(ref yBase, i); - - // cb = cbVals[i] - halfValue); - Vector4Pair cb = Unsafe.Add(ref cbBase, i); - cb.AddInplace(chromaOffset); - - // cr = crVals[i] - halfValue; - Vector4Pair cr = Unsafe.Add(ref crBase, i); - cr.AddInplace(chromaOffset); - - // r = y + (1.402F * cr); - Vector4Pair r = y; - Vector4Pair tmp = cr; - tmp.MultiplyInplace(1.402F); - r.AddInplace(ref tmp); - - // g = y - (0.344136F * cb) - (0.714136F * cr); - Vector4Pair g = y; - tmp = cb; - tmp.MultiplyInplace(-0.344136F); - g.AddInplace(ref tmp); - tmp = cr; - tmp.MultiplyInplace(-0.714136F); - g.AddInplace(ref tmp); - - // b = y + (1.772F * cb); - Vector4Pair b = y; - tmp = cb; - tmp.MultiplyInplace(1.772F); - b.AddInplace(ref tmp); - - r.RoundAndDownscalePreVector8(maxValue); - g.RoundAndDownscalePreVector8(maxValue); - b.RoundAndDownscalePreVector8(maxValue); - - // Collect (r0,r1...r8) (g0,g1...g8) (b0,b1...b8) vector values in the expected (r0,g0,g1,1), (r1,g1,g2,1) ... order: - ref Vector4Octet destination = ref Unsafe.Add(ref resultBase, i); - destination.Pack(ref r, ref g, ref b); - } - } - protected override void ConvertCoreVectorizedInplace(in ComponentValues values) { DebugGuard.IsTrue(values.Component0.Length % 8 == 0, nameof(values), "Length should be divisible by 8!"); @@ -146,9 +81,6 @@ protected override void ConvertCoreVectorizedInplace(in ComponentValues values) } } - protected override void ConvertCore(in ComponentValues values, Span result) => - FromYCbCrBasic.ConvertCore(values, result, this.MaximumValue, this.HalfValue); - protected override void ConvertCoreInplace(in ComponentValues values) => FromYCbCrBasic.ConvertCoreInplace(values, this.MaximumValue, this.HalfValue); } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector8.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector8.cs index f6015447b8..633c7f41d9 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector8.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector8.cs @@ -19,67 +19,6 @@ public FromYCbCrVector8(int precision) { } - protected override void ConvertCoreVectorized(in ComponentValues values, Span result) - { - ref Vector yBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0)); - ref Vector cbBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1)); - ref Vector crBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2)); - - ref Vector4Octet resultBase = - ref Unsafe.As(ref MemoryMarshal.GetReference(result)); - - var chromaOffset = new Vector(-this.HalfValue); - - // Walking 8 elements at one step: - int n = result.Length / 8; - - Vector4Pair rr = default; - Vector4Pair gg = default; - Vector4Pair bb = default; - - ref Vector rrRefAsVector = ref Unsafe.As>(ref rr); - ref Vector ggRefAsVector = ref Unsafe.As>(ref gg); - ref Vector bbRefAsVector = ref Unsafe.As>(ref bb); - - var scale = new Vector(1 / this.MaximumValue); - - for (int i = 0; i < n; i++) - { - // y = yVals[i]; - // cb = cbVals[i] - 128F; - // cr = crVals[i] - 128F; - Vector y = Unsafe.Add(ref yBase, i); - Vector cb = Unsafe.Add(ref cbBase, i) + chromaOffset; - Vector cr = Unsafe.Add(ref crBase, i) + chromaOffset; - - // 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 r = y + (cr * new Vector(1.402F)); - Vector g = y - (cb * new Vector(0.344136F)) - (cr * new Vector(0.714136F)); - Vector b = y + (cb * new Vector(1.772F)); - - r = r.FastRound(); - g = g.FastRound(); - b = b.FastRound(); - r *= scale; - g *= scale; - b *= scale; - - rrRefAsVector = r; - ggRefAsVector = g; - bbRefAsVector = b; - - // Collect (r0,r1...r8) (g0,g1...g8) (b0,b1...b8) vector values in the expected (r0,g0,g1,1), (r1,g1,g2,1) ... order: - ref Vector4Octet destination = ref Unsafe.Add(ref resultBase, i); - destination.Pack(ref rr, ref gg, ref bb); - } - } - protected override void ConvertCoreVectorizedInplace(in ComponentValues values) { ref Vector c0Base = @@ -128,9 +67,6 @@ protected override void ConvertCoreVectorizedInplace(in ComponentValues values) } } - protected override void ConvertCore(in ComponentValues values, Span result) => - FromYCbCrBasic.ConvertCore(values, result, this.MaximumValue, this.HalfValue); - protected override void ConvertCoreInplace(in ComponentValues values) => FromYCbCrBasic.ConvertCoreInplace(values, this.MaximumValue, this.HalfValue); } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKAvx2.cs index bd786b826c..5fc2fe75b6 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKAvx2.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKAvx2.cs @@ -22,87 +22,6 @@ public FromYccKAvx2(int precision) { } - protected override void ConvertCoreVectorized(in ComponentValues values, Span result) - { -#if SUPPORTS_RUNTIME_INTRINSICS - ref Vector256 yBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0)); - ref Vector256 cbBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1)); - ref Vector256 crBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2)); - ref Vector256 kBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component3)); - - ref Vector256 resultBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(result)); - - // Used for the color conversion - var chromaOffset = Vector256.Create(-this.HalfValue); - var scale = Vector256.Create(1 / 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); - - // Used for packing. - var va = Vector256.Create(1F); - ref byte control = ref MemoryMarshal.GetReference(HwIntrinsics.PermuteMaskEvenOdd8x32); - Vector256 vcontrol = Unsafe.As>(ref control); - - // Walking 8 elements at one step: - int n = result.Length / 8; - for (int i = 0; i < n; i++) - { - // y = yVals[i]; - // cb = cbVals[i] - 128F; - // cr = crVals[i] - 128F; - // k = kVals[i] / 256F; - Vector256 y = Unsafe.Add(ref yBase, i); - Vector256 cb = Avx.Add(Unsafe.Add(ref cbBase, i), chromaOffset); - Vector256 cr = Avx.Add(Unsafe.Add(ref crBase, i), chromaOffset); - Vector256 k = Avx.Divide(Unsafe.Add(ref kBase, i), max); - - y = Avx2.PermuteVar8x32(y, vcontrol); - cb = Avx2.PermuteVar8x32(cb, vcontrol); - cr = Avx2.PermuteVar8x32(cr, vcontrol); - k = Avx2.PermuteVar8x32(k, vcontrol); - - // 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 r = HwIntrinsics.MultiplyAdd(y, cr, rCrMult); - Vector256 g = - HwIntrinsics.MultiplyAdd(HwIntrinsics.MultiplyAdd(y, cb, gCbMult), cr, gCrMult); - Vector256 b = HwIntrinsics.MultiplyAdd(y, cb, bCbMult); - - r = Avx.Subtract(max, Avx.RoundToNearestInteger(r)); - g = Avx.Subtract(max, Avx.RoundToNearestInteger(g)); - b = Avx.Subtract(max, Avx.RoundToNearestInteger(b)); - - r = Avx.Multiply(Avx.Multiply(r, k), scale); - g = Avx.Multiply(Avx.Multiply(g, k), scale); - b = Avx.Multiply(Avx.Multiply(b, k), scale); - - Vector256 vte = Avx.UnpackLow(r, b); - Vector256 vto = Avx.UnpackLow(g, va); - - ref Vector256 destination = ref Unsafe.Add(ref resultBase, i * 4); - - destination = Avx.UnpackLow(vte, vto); - Unsafe.Add(ref destination, 1) = Avx.UnpackHigh(vte, vto); - - vte = Avx.UnpackHigh(r, b); - vto = Avx.UnpackHigh(g, va); - - Unsafe.Add(ref destination, 2) = Avx.UnpackLow(vte, vto); - Unsafe.Add(ref destination, 3) = Avx.UnpackHigh(vte, vto); - } -#endif - } - protected override void ConvertCoreVectorizedInplace(in ComponentValues values) { #if SUPPORTS_RUNTIME_INTRINSICS @@ -164,9 +83,6 @@ protected override void ConvertCoreVectorizedInplace(in ComponentValues values) #endif } - protected override void ConvertCore(in ComponentValues values, Span result) => - FromYccKBasic.ConvertCore(values, result, this.MaximumValue, this.HalfValue); - protected override void ConvertCoreInplace(in ComponentValues values) => FromYccKBasic.ConvertCoreInplace(values, this.MaximumValue, this.HalfValue); } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKBasic.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKBasic.cs index b0cde69712..138697ce12 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKBasic.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKBasic.cs @@ -15,11 +15,6 @@ public FromYccKBasic(int precision) { } - public override void ConvertToRgba(in ComponentValues values, Span result) - { - ConvertCore(values, result, this.MaximumValue, this.HalfValue); - } - public override void ConvertToRgbInplace(in ComponentValues values) => ConvertCoreInplace(values, this.MaximumValue, this.HalfValue); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKVector8.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKVector8.cs index 64f29f1f89..de516980e7 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKVector8.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKVector8.cs @@ -18,72 +18,6 @@ public FromYccKVector8(int precision) { } - protected override void ConvertCoreVectorized(in ComponentValues values, Span result) - { - ref Vector yBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0)); - ref Vector cbBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component1)); - ref Vector crBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component2)); - ref Vector kBase = - ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component3)); - - ref Vector4Octet resultBase = - ref Unsafe.As(ref MemoryMarshal.GetReference(result)); - - var chromaOffset = new Vector(-this.HalfValue); - - // Walking 8 elements at one step: - int n = result.Length / 8; - - Vector4Pair rr = default; - Vector4Pair gg = default; - Vector4Pair bb = default; - - ref Vector rrRefAsVector = ref Unsafe.As>(ref rr); - ref Vector ggRefAsVector = ref Unsafe.As>(ref gg); - ref Vector bbRefAsVector = ref Unsafe.As>(ref bb); - - var scale = new Vector(1 / this.MaximumValue); - var max = new Vector(this.MaximumValue); - - for (int i = 0; i < n; i++) - { - // y = yVals[i]; - // cb = cbVals[i] - 128F; - // cr = crVals[i] - 128F; - // k = kVals[i] / 256F; - Vector y = Unsafe.Add(ref yBase, i); - Vector cb = Unsafe.Add(ref cbBase, i) + chromaOffset; - Vector cr = Unsafe.Add(ref crBase, i) + chromaOffset; - Vector k = Unsafe.Add(ref kBase, i) / max; - - // 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 r = y + (cr * new Vector(1.402F)); - Vector g = y - (cb * new Vector(0.344136F)) - (cr * new Vector(0.714136F)); - Vector b = y + (cb * new Vector(1.772F)); - - r = (max - r.FastRound()) * k; - g = (max - g.FastRound()) * k; - b = (max - b.FastRound()) * k; - r *= scale; - g *= scale; - b *= scale; - - rrRefAsVector = r; - ggRefAsVector = g; - bbRefAsVector = b; - - // Collect (r0,r1...r8) (g0,g1...g8) (b0,b1...b8) vector values in the expected (r0,g0,g1,1), (r1,g1,g2,1) ... order: - ref Vector4Octet destination = ref Unsafe.Add(ref resultBase, i); - destination.Pack(ref rr, ref gg, ref bb); - } - } - protected override void ConvertCoreVectorizedInplace(in ComponentValues values) { ref Vector c0Base = @@ -136,9 +70,6 @@ protected override void ConvertCoreVectorizedInplace(in ComponentValues values) } } - protected override void ConvertCore(in ComponentValues values, Span result) => - FromYccKBasic.ConvertCore(values, result, this.MaximumValue, this.HalfValue); - protected override void ConvertCoreInplace(in ComponentValues values) => FromYccKBasic.ConvertCoreInplace(values, this.MaximumValue, this.HalfValue); } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.VectorizedJpegColorConverter.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.VectorizedJpegColorConverter.cs index 046416847b..fc4fb77860 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.VectorizedJpegColorConverter.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.VectorizedJpegColorConverter.cs @@ -18,26 +18,6 @@ protected VectorizedJpegColorConverter(JpegColorSpace colorSpace, int precision, this.vectorSize = vectorSize; } - public sealed override void ConvertToRgba(in ComponentValues values, Span result) - { - int remainder = result.Length % this.vectorSize; - int simdCount = result.Length - remainder; - if (simdCount > 0) - { - // This implementation is actually AVX specific. - // An AVX register is capable of storing 8 float-s. - if (!this.IsAvailable) - { - throw new InvalidOperationException( - "This converter can be used only on architecture having 256 byte floating point SIMD registers!"); - } - - this.ConvertCoreVectorized(values.Slice(0, simdCount), result.Slice(0, simdCount)); - } - - this.ConvertCore(values.Slice(simdCount, remainder), result.Slice(simdCount, remainder)); - } - public override void ConvertToRgbInplace(in ComponentValues values) { int length = values.Component0.Length; @@ -59,12 +39,8 @@ public override void ConvertToRgbInplace(in ComponentValues values) this.ConvertCoreInplace(values.Slice(simdCount, remainder)); } - protected abstract void ConvertCoreVectorized(in ComponentValues values, Span result); - protected virtual void ConvertCoreVectorizedInplace(in ComponentValues values) => throw new NotImplementedException(); - protected abstract void ConvertCore(in ComponentValues values, Span result); - protected virtual void ConvertCoreInplace(in ComponentValues values) => throw new NotImplementedException(); } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs index 95829e8109..fd701334e1 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs @@ -76,13 +76,10 @@ public static JpegColorConverter GetConverter(JpegColorSpace colorSpace, int pre } /// - /// He implementation of the conversion. + /// Converts planar jpeg component values in to RGB color space inplace. /// - /// The input as a stack-only struct - /// The destination buffer of values - public abstract void ConvertToRgba(in ComponentValues values, Span result); - - public virtual void ConvertToRgbInplace(in ComponentValues values) => throw new NotImplementedException(); + /// The input/ouptut as a stack-only struct + public abstract void ConvertToRgbInplace(in ComponentValues values); /// /// Returns the s for all supported colorspaces and precisions. From 179e43a060ef71c38465ce93d6e343ae2e3ba698 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 3 Oct 2021 04:03:45 +0200 Subject: [PATCH 11/24] delete more unused methods --- .../JpegColorConverter.FromCmykAvx2.cs | 2 +- .../JpegColorConverter.FromCmykBasic.cs | 30 ------------------ .../JpegColorConverter.FromGrayScaleBasic.cs | 18 ----------- .../JpegColorConverter.FromRgbBasic.cs | 27 ---------------- .../JpegColorConverter.FromYCbCrBasic.cs | 27 ---------------- .../JpegColorConverter.FromYccKBasic.cs | 31 ------------------- .../Formats/Jpg/JpegColorConverterTests.cs | 26 ---------------- 7 files changed, 1 insertion(+), 160 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx2.cs index ad5f9acd24..2c77a42a06 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx2.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx2.cs @@ -24,7 +24,7 @@ public FromCmykAvx2(int precision) protected override void ConvertCoreVectorizedInplace(in ComponentValues values) { - #if SUPPORTS_RUNTIME_INTRINSICS +#if SUPPORTS_RUNTIME_INTRINSICS ref Vector256 c0Base = ref Unsafe.As>(ref MemoryMarshal.GetReference(values.Component0)); ref Vector256 c1Base = diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykBasic.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykBasic.cs index 72d1735999..b0ad50301b 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykBasic.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykBasic.cs @@ -18,36 +18,6 @@ public FromCmykBasic(int precision) public override void ConvertToRgbInplace(in ComponentValues values) => ConvertCoreInplace(values, this.MaximumValue); - internal static void ConvertCore(in ComponentValues values, Span result, float maxValue) - { - ReadOnlySpan cVals = values.Component0; - ReadOnlySpan mVals = values.Component1; - ReadOnlySpan yVals = values.Component2; - ReadOnlySpan kVals = values.Component3; - - var v = new Vector4(0, 0, 0, 1F); - - var maximum = 1 / maxValue; - var scale = new Vector4(maximum, maximum, maximum, 1F); - - for (int i = 0; i < result.Length; i++) - { - float c = cVals[i]; - float m = mVals[i]; - float y = yVals[i]; - float k = kVals[i] / maxValue; - - v.X = c * k; - v.Y = m * k; - v.Z = y * k; - v.W = 1F; - - v *= scale; - - result[i] = v; - } - } - internal static void ConvertCoreInplace(in ComponentValues values, float maxValue) { Span c0 = values.Component0; diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleBasic.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleBasic.cs index 28735a61f9..92a21a4380 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleBasic.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleBasic.cs @@ -20,26 +20,8 @@ public FromGrayscaleBasic(int precision) public override void ConvertToRgbInplace(in ComponentValues values) => ScaleValues(values.Component0, this.MaximumValue); - internal static void ConvertCore(in ComponentValues values, Span result, float maxValue) - { - var maximum = 1 / maxValue; - var scale = new Vector4(maximum, maximum, maximum, 1F); - - ref float sBase = ref MemoryMarshal.GetReference(values.Component0); - ref Vector4 dBase = ref MemoryMarshal.GetReference(result); - - for (int i = 0; i < result.Length; i++) - { - var v = new Vector4(Unsafe.Add(ref sBase, i)); - v.W = 1f; - v *= scale; - Unsafe.Add(ref dBase, i) = v; - } - } - internal static void ScaleValues(Span values, float maxValue) { - // TODO: Optimize this Span vecValues = MemoryMarshal.Cast(values); var scaleVector = new Vector4(1 / maxValue); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbBasic.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbBasic.cs index 0159b9c741..1425e7b584 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbBasic.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbBasic.cs @@ -27,33 +27,6 @@ internal static void ConvertCoreInplace(ComponentValues values, float maxValue) FromGrayscaleBasic.ScaleValues(values.Component1, maxValue); FromGrayscaleBasic.ScaleValues(values.Component2, maxValue); } - - internal static void ConvertCore(in ComponentValues values, Span result, float maxValue) - { - ReadOnlySpan rVals = values.Component0; - ReadOnlySpan gVals = values.Component1; - ReadOnlySpan bVals = values.Component2; - - var v = new Vector4(0, 0, 0, 1); - - var maximum = 1 / maxValue; - var scale = new Vector4(maximum, maximum, maximum, 1F); - - for (int i = 0; i < result.Length; i++) - { - float r = rVals[i]; - float g = gVals[i]; - float b = bVals[i]; - - v.X = r; - v.Y = g; - v.Z = b; - - v *= scale; - - result[i] = v; - } - } } } } diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs index 040aaac2b0..990d29aa01 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs @@ -18,33 +18,6 @@ public FromYCbCrBasic(int precision) public override void ConvertToRgbInplace(in ComponentValues values) => ConvertCoreInplace(values, this.MaximumValue, this.HalfValue); - internal static void ConvertCore(in ComponentValues values, Span result, float maxValue, float halfValue) - { - // TODO: We can optimize a lot here with Vector and SRCS.Unsafe()! - ReadOnlySpan yVals = values.Component0; - ReadOnlySpan cbVals = values.Component1; - ReadOnlySpan crVals = values.Component2; - - var v = new Vector4(0, 0, 0, 1); - - 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] - 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); - v.Z = MathF.Round(y + (1.772F * cb), MidpointRounding.AwayFromZero); - - v *= scale; - - result[i] = v; - } - } - internal static void ConvertCoreInplace(in ComponentValues values, float maxValue, float halfValue) { Span c0 = values.Component0; diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKBasic.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKBasic.cs index 138697ce12..4833f48683 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKBasic.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKBasic.cs @@ -18,37 +18,6 @@ public FromYccKBasic(int precision) public override void ConvertToRgbInplace(in ComponentValues values) => ConvertCoreInplace(values, this.MaximumValue, this.HalfValue); - internal static void ConvertCore(in ComponentValues values, Span result, float maxValue, float halfValue) - { - // TODO: We can optimize a lot here with Vector and SRCS.Unsafe()! - ReadOnlySpan yVals = values.Component0; - ReadOnlySpan cbVals = values.Component1; - ReadOnlySpan crVals = values.Component2; - ReadOnlySpan kVals = values.Component3; - - var v = new Vector4(0, 0, 0, 1F); - - var maximum = 1 / maxValue; - var scale = new Vector4(maximum, maximum, maximum, 1F); - - for (int i = 0; i < result.Length; i++) - { - float y = yVals[i]; - float cb = cbVals[i] - halfValue; - float cr = crVals[i] - halfValue; - float k = kVals[i] / maxValue; - - v.X = (maxValue - MathF.Round(y + (1.402F * cr), MidpointRounding.AwayFromZero)) * k; - v.Y = (maxValue - MathF.Round(y - (0.344136F * cb) - (0.714136F * cr), MidpointRounding.AwayFromZero)) * k; - v.Z = (maxValue - MathF.Round(y + (1.772F * cb), MidpointRounding.AwayFromZero)) * k; - v.W = 1F; - - v *= scale; - - result[i] = v; - } - } - internal static void ConvertCoreInplace(in ComponentValues values, float maxValue, float halfValue) { Span c0 = values.Component0; diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs index 6354d1e196..f2bc8a7338 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs @@ -341,32 +341,6 @@ public void FromYcck_WithDefaultConverter(int inputBufferLength, int resultBuffe seed); } - // Benchmark, for local execution only - // [Theory] - // [InlineData(false)] - // [InlineData(true)] - public void BenchmarkYCbCr(bool simd) - { - int count = 2053; - int times = 50000; - - JpegColorConverter.ComponentValues values = CreateRandomValues(3, count, 1); - var result = new Vector4[count]; - - JpegColorConverter converter = simd ? (JpegColorConverter)new JpegColorConverter.FromYCbCrVector4(8) : new JpegColorConverter.FromYCbCrBasic(8); - - // Warm up: - converter.ConvertToRgba(values, result); - - using (new MeasureGuard(this.Output, $"{converter.GetType().Name} x {times}")) - { - for (int i = 0; i < times; i++) - { - converter.ConvertToRgba(values, result); - } - } - } - private static JpegColorConverter.ComponentValues CreateRandomValues( int componentCount, int inputBufferLength, From d2989d8b06ef483da6187a4c8e2afd86c46cc32b Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 3 Oct 2021 04:10:41 +0200 Subject: [PATCH 12/24] fix ImageSharp.Benchmarks build --- .../Codecs/Jpeg/CmykColorConversion.cs | 6 +++--- .../Codecs/Jpeg/ColorConversionBenchmark.cs | 3 --- .../Codecs/Jpeg/GrayscaleColorConversion.cs | 4 ++-- .../Codecs/Jpeg/RgbColorConversion.cs | 6 +++--- .../Codecs/Jpeg/YCbCrColorConversion.cs | 8 ++++---- .../Codecs/Jpeg/YccKColorConverter.cs | 6 +++--- 6 files changed, 15 insertions(+), 18 deletions(-) diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/CmykColorConversion.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/CmykColorConversion.cs index d17882adf6..490beec6fb 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/CmykColorConversion.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/CmykColorConversion.cs @@ -19,7 +19,7 @@ public void Scalar() { var values = new JpegColorConverter.ComponentValues(this.Input, 0); - new JpegColorConverter.FromCmykBasic(8).ConvertToRgba(values, this.Output); + new JpegColorConverter.FromCmykBasic(8).ConvertToRgbInplace(values); } [Benchmark] @@ -27,7 +27,7 @@ public void SimdVector8() { var values = new JpegColorConverter.ComponentValues(this.Input, 0); - new JpegColorConverter.FromCmykVector8(8).ConvertToRgba(values, this.Output); + new JpegColorConverter.FromCmykVector8(8).ConvertToRgbInplace(values); } [Benchmark] @@ -35,7 +35,7 @@ public void SimdVectorAvx2() { var values = new JpegColorConverter.ComponentValues(this.Input, 0); - new JpegColorConverter.FromCmykAvx2(8).ConvertToRgba(values, this.Output); + new JpegColorConverter.FromCmykAvx2(8).ConvertToRgbInplace(values); } } } diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversionBenchmark.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversionBenchmark.cs index e93ad474b7..caed0e4e58 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversionBenchmark.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/ColorConversionBenchmark.cs @@ -19,13 +19,10 @@ protected ColorConversionBenchmark(int componentCount) protected Buffer2D[] Input { get; private set; } - protected Vector4[] Output { get; private set; } - [GlobalSetup] public void Setup() { this.Input = CreateRandomValues(this.componentCount, Count); - this.Output = new Vector4[Count]; } [GlobalCleanup] diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/GrayscaleColorConversion.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/GrayscaleColorConversion.cs index 1eba1571da..7b62e14340 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/GrayscaleColorConversion.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/GrayscaleColorConversion.cs @@ -19,7 +19,7 @@ public void Scalar() { var values = new JpegColorConverter.ComponentValues(this.Input, 0); - new JpegColorConverter.FromGrayscaleBasic(8).ConvertToRgba(values, this.Output); + new JpegColorConverter.FromGrayscaleBasic(8).ConvertToRgbInplace(values); } [Benchmark] @@ -27,7 +27,7 @@ public void SimdVectorAvx2() { var values = new JpegColorConverter.ComponentValues(this.Input, 0); - new JpegColorConverter.FromGrayscaleAvx2(8).ConvertToRgba(values, this.Output); + new JpegColorConverter.FromGrayscaleAvx2(8).ConvertToRgbInplace(values); } } } diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/RgbColorConversion.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/RgbColorConversion.cs index c1598be043..af03b31e54 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/RgbColorConversion.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/RgbColorConversion.cs @@ -19,7 +19,7 @@ public void Scalar() { var values = new JpegColorConverter.ComponentValues(this.Input, 0); - new JpegColorConverter.FromRgbBasic(8).ConvertToRgba(values, this.Output); + new JpegColorConverter.FromRgbBasic(8).ConvertToRgbInplace(values); } [Benchmark] @@ -27,7 +27,7 @@ public void SimdVector8() { var values = new JpegColorConverter.ComponentValues(this.Input, 0); - new JpegColorConverter.FromRgbVector8(8).ConvertToRgba(values, this.Output); + new JpegColorConverter.FromRgbVector8(8).ConvertToRgbInplace(values); } [Benchmark] @@ -35,7 +35,7 @@ public void SimdVectorAvx2() { var values = new JpegColorConverter.ComponentValues(this.Input, 0); - new JpegColorConverter.FromRgbAvx2(8).ConvertToRgba(values, this.Output); + new JpegColorConverter.FromRgbAvx2(8).ConvertToRgbInplace(values); } } } diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/YCbCrColorConversion.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/YCbCrColorConversion.cs index 6c5732c99e..18daa364cf 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/YCbCrColorConversion.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/YCbCrColorConversion.cs @@ -19,7 +19,7 @@ public void Scalar() { var values = new JpegColorConverter.ComponentValues(this.Input, 0); - new JpegColorConverter.FromYCbCrBasic(8).ConvertToRgba(values, this.Output); + new JpegColorConverter.FromYCbCrBasic(8).ConvertToRgbInplace(values); } [Benchmark(Baseline = true)] @@ -27,7 +27,7 @@ public void SimdVector() { var values = new JpegColorConverter.ComponentValues(this.Input, 0); - new JpegColorConverter.FromYCbCrVector4(8).ConvertToRgba(values, this.Output); + new JpegColorConverter.FromYCbCrVector4(8).ConvertToRgbInplace(values); } [Benchmark] @@ -35,7 +35,7 @@ public void SimdVector8() { var values = new JpegColorConverter.ComponentValues(this.Input, 0); - new JpegColorConverter.FromYCbCrVector8(8).ConvertToRgba(values, this.Output); + new JpegColorConverter.FromYCbCrVector8(8).ConvertToRgbInplace(values); } [Benchmark] @@ -43,7 +43,7 @@ public void SimdVectorAvx2() { var values = new JpegColorConverter.ComponentValues(this.Input, 0); - new JpegColorConverter.FromYCbCrAvx2(8).ConvertToRgba(values, this.Output); + new JpegColorConverter.FromYCbCrAvx2(8).ConvertToRgbInplace(values); } } } diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/YccKColorConverter.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/YccKColorConverter.cs index 0a9bdb8fdd..08e5e50d19 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/YccKColorConverter.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/YccKColorConverter.cs @@ -19,7 +19,7 @@ public void Scalar() { var values = new JpegColorConverter.ComponentValues(this.Input, 0); - new JpegColorConverter.FromYccKBasic(8).ConvertToRgba(values, this.Output); + new JpegColorConverter.FromYccKBasic(8).ConvertToRgbInplace(values); } [Benchmark] @@ -27,7 +27,7 @@ public void SimdVector8() { var values = new JpegColorConverter.ComponentValues(this.Input, 0); - new JpegColorConverter.FromYccKVector8(8).ConvertToRgba(values, this.Output); + new JpegColorConverter.FromYccKVector8(8).ConvertToRgbInplace(values); } [Benchmark] @@ -35,7 +35,7 @@ public void SimdVectorAvx2() { var values = new JpegColorConverter.ComponentValues(this.Input, 0); - new JpegColorConverter.FromYccKAvx2(8).ConvertToRgba(values, this.Output); + new JpegColorConverter.FromYccKAvx2(8).ConvertToRgbInplace(values); } } } From 387bdfa53341eb7afecc1864001852b71c74daf8 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 3 Oct 2021 04:19:14 +0200 Subject: [PATCH 13/24] fix ProfilingSandbox --- .../Formats/Jpg/JpegColorConverterTests.cs | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs index f2bc8a7338..1504684ae3 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs @@ -341,6 +341,32 @@ public void FromYcck_WithDefaultConverter(int inputBufferLength, int resultBuffe seed); } + // Benchmark, for local execution only + // [Theory] + // [InlineData(false)] + // [InlineData(true)] + public void BenchmarkYCbCr(bool simd) + { + int count = 2053; + int times = 50000; + + JpegColorConverter.ComponentValues values = CreateRandomValues(3, count, 1); + var result = new Vector4[count]; + + JpegColorConverter converter = simd ? (JpegColorConverter)new JpegColorConverter.FromYCbCrVector4(8) : new JpegColorConverter.FromYCbCrBasic(8); + + // Warm up: + converter.ConvertToRgbInplace(values); + + using (new MeasureGuard(this.Output, $"{converter.GetType().Name} x {times}")) + { + for (int i = 0; i < times; i++) + { + converter.ConvertToRgbInplace(values); + } + } + } + private static JpegColorConverter.ComponentValues CreateRandomValues( int componentCount, int inputBufferLength, From a4cf70fac9bf7429e497479da29e1773960d5577 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 3 Oct 2021 04:27:00 +0200 Subject: [PATCH 14/24] remove unused test methods --- .../Formats/Jpg/JpegColorConverterTests.cs | 120 ------------------ 1 file changed, 120 deletions(-) diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs index 1504684ae3..560a2e462b 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs @@ -437,35 +437,6 @@ static JpegColorConverter.ComponentValues Copy(JpegColorConverter.ComponentValue } } - private static void Validate( - JpegColorSpace colorSpace, - in JpegColorConverter.ComponentValues original, - Vector4[] result, - int i) - { - switch (colorSpace) - { - case JpegColorSpace.Grayscale: - ValidateGrayScale(original, result, i); - break; - case JpegColorSpace.Ycck: - ValidateCyyK(original, result, i); - break; - case JpegColorSpace.Cmyk: - ValidateCmyk(original, result, i); - break; - case JpegColorSpace.RGB: - ValidateRgb(original, result, i); - break; - case JpegColorSpace.YCbCr: - ValidateYCbCr(original, result, i); - break; - default: - Assert.True(false, $"Colorspace {colorSpace} not supported!"); - break; - } - } - private static void Validate( JpegColorSpace colorSpace, in JpegColorConverter.ComponentValues original, @@ -495,21 +466,6 @@ private static void Validate( } } - private static void ValidateYCbCr(in JpegColorConverter.ComponentValues values, Vector4[] result, int i) - { - float y = values.Component0[i]; - float cb = values.Component1[i]; - float cr = values.Component2[i]; - var ycbcr = new YCbCr(y, cb, cr); - - Vector4 rgba = result[i]; - var actual = new Rgb(rgba.X, rgba.Y, rgba.Z); - var expected = ColorSpaceConverter.ToRgb(ycbcr); - - Assert.Equal(expected, actual, ColorSpaceComparer); - Assert.Equal(1, rgba.W); - } - private static void ValidateYCbCr(in JpegColorConverter.ComponentValues values, in JpegColorConverter.ComponentValues result, int i) { float y = values.Component0[i]; @@ -523,33 +479,6 @@ private static void ValidateYCbCr(in JpegColorConverter.ComponentValues values, Assert.Equal(expected, actual, ColorSpaceComparer); } - private static void ValidateCyyK(in JpegColorConverter.ComponentValues values, Vector4[] result, int i) - { - var v = new Vector4(0, 0, 0, 1F); - var scale = new Vector4(1 / 255F, 1 / 255F, 1 / 255F, 1F); - - float y = values.Component0[i]; - float cb = values.Component1[i] - 128F; - float cr = values.Component2[i] - 128F; - float k = values.Component3[i] / 255F; - - v.X = (255F - (float)Math.Round(y + (1.402F * cr), MidpointRounding.AwayFromZero)) * k; - v.Y = (255F - (float)Math.Round( - y - (0.344136F * cb) - (0.714136F * cr), - MidpointRounding.AwayFromZero)) * k; - v.Z = (255F - (float)Math.Round(y + (1.772F * cb), MidpointRounding.AwayFromZero)) * k; - v.W = 1F; - - v *= scale; - - Vector4 rgba = result[i]; - var actual = new Rgb(rgba.X, rgba.Y, rgba.Z); - var expected = new Rgb(v.X, v.Y, v.Z); - - Assert.Equal(expected, actual, ColorSpaceComparer); - Assert.Equal(1, rgba.W); - } - private static void ValidateCyyK(in JpegColorConverter.ComponentValues values, in JpegColorConverter.ComponentValues result, int i) { var v = new Vector4(0, 0, 0, 1F); @@ -575,19 +504,6 @@ private static void ValidateCyyK(in JpegColorConverter.ComponentValues values, i Assert.Equal(expected, actual, ColorSpaceComparer); } - private static void ValidateRgb(in JpegColorConverter.ComponentValues values, Vector4[] result, int i) - { - float r = values.Component0[i]; - float g = values.Component1[i]; - float b = values.Component2[i]; - Vector4 rgba = result[i]; - var actual = new Rgb(rgba.X, rgba.Y, rgba.Z); - var expected = new Rgb(r / 255F, g / 255F, b / 255F); - - Assert.Equal(expected, actual, ColorSpaceComparer); - Assert.Equal(1, rgba.W); - } - private static void ValidateRgb(in JpegColorConverter.ComponentValues values, in JpegColorConverter.ComponentValues result, int i) { float r = values.Component0[i]; @@ -600,17 +516,6 @@ private static void ValidateRgb(in JpegColorConverter.ComponentValues values, in Assert.Equal(expected, actual, ColorSpaceComparer); } - private static void ValidateGrayScale(in JpegColorConverter.ComponentValues values, Vector4[] result, int i) - { - float y = values.Component0[i]; - Vector4 rgba = result[i]; - var actual = new Rgb(rgba.X, rgba.Y, rgba.Z); - var expected = new Rgb(y / 255F, y / 255F, y / 255F); - - Assert.Equal(expected, actual, ColorSpaceComparer); - Assert.Equal(1, rgba.W); - } - private static void ValidateGrayScale(in JpegColorConverter.ComponentValues values, in JpegColorConverter.ComponentValues result, int i) { float y = values.Component0[i]; @@ -620,31 +525,6 @@ private static void ValidateGrayScale(in JpegColorConverter.ComponentValues valu Assert.Equal(expected, actual, ColorSpaceComparer); } - private static void ValidateCmyk(in JpegColorConverter.ComponentValues values, Vector4[] result, int i) - { - var v = new Vector4(0, 0, 0, 1F); - var scale = new Vector4(1 / 255F, 1 / 255F, 1 / 255F, 1F); - - float c = values.Component0[i]; - float m = values.Component1[i]; - float y = values.Component2[i]; - float k = values.Component3[i] / 255F; - - v.X = c * k; - v.Y = m * k; - v.Z = y * k; - v.W = 1F; - - v *= scale; - - Vector4 rgba = result[i]; - var actual = new Rgb(rgba.X, rgba.Y, rgba.Z); - var expected = new Rgb(v.X, v.Y, v.Z); - - Assert.Equal(expected, actual, ColorSpaceComparer); - Assert.Equal(1, rgba.W); - } - private static void ValidateCmyk(in JpegColorConverter.ComponentValues values, in JpegColorConverter.ComponentValues result, int i) { var v = new Vector4(0, 0, 0, 1F); From cf4c3fb3608f00e2314883d3ca5016e7896a3049 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 3 Oct 2021 22:43:49 +0200 Subject: [PATCH 15/24] Delete Vector4Octet --- .../ColorConverters/JpegColorConverter.cs | 98 ------------------- 1 file changed, 98 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs index fd701334e1..11ea4cda8c 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.cs @@ -238,103 +238,5 @@ public ComponentValues Slice(int start, int length) return new ComponentValues(this.ComponentCount, c0, c1, c2, c3); } } - - internal struct Vector4Octet - { -#pragma warning disable SA1132 // Do not combine fields - public Vector4 V0, V1, V2, V3, V4, V5, V6, V7; - - /// - /// Pack (r0,r1...r7) (g0,g1...g7) (b0,b1...b7) vector values as (r0,g0,b0,1), (r1,g1,b1,1) ... - /// - public void Pack(ref Vector4Pair r, ref Vector4Pair g, ref Vector4Pair b) - { - this.V0.X = r.A.X; - this.V0.Y = g.A.X; - this.V0.Z = b.A.X; - this.V0.W = 1f; - - this.V1.X = r.A.Y; - this.V1.Y = g.A.Y; - this.V1.Z = b.A.Y; - this.V1.W = 1f; - - this.V2.X = r.A.Z; - this.V2.Y = g.A.Z; - this.V2.Z = b.A.Z; - this.V2.W = 1f; - - this.V3.X = r.A.W; - this.V3.Y = g.A.W; - this.V3.Z = b.A.W; - this.V3.W = 1f; - - this.V4.X = r.B.X; - this.V4.Y = g.B.X; - this.V4.Z = b.B.X; - this.V4.W = 1f; - - this.V5.X = r.B.Y; - this.V5.Y = g.B.Y; - this.V5.Z = b.B.Y; - this.V5.W = 1f; - - this.V6.X = r.B.Z; - this.V6.Y = g.B.Z; - this.V6.Z = b.B.Z; - this.V6.W = 1f; - - this.V7.X = r.B.W; - this.V7.Y = g.B.W; - this.V7.Z = b.B.W; - this.V7.W = 1f; - } - - /// - /// Pack (g0,g1...g7) vector values as (g0,g0,g0,1), (g1,g1,g1,1) ... - /// - public void Pack(ref Vector4Pair g) - { - this.V0.X = g.A.X; - this.V0.Y = g.A.X; - this.V0.Z = g.A.X; - this.V0.W = 1f; - - this.V1.X = g.A.Y; - this.V1.Y = g.A.Y; - this.V1.Z = g.A.Y; - this.V1.W = 1f; - - this.V2.X = g.A.Z; - this.V2.Y = g.A.Z; - this.V2.Z = g.A.Z; - this.V2.W = 1f; - - this.V3.X = g.A.W; - this.V3.Y = g.A.W; - this.V3.Z = g.A.W; - this.V3.W = 1f; - - this.V4.X = g.B.X; - this.V4.Y = g.B.X; - this.V4.Z = g.B.X; - this.V4.W = 1f; - - this.V5.X = g.B.Y; - this.V5.Y = g.B.Y; - this.V5.Z = g.B.Y; - this.V5.W = 1f; - - this.V6.X = g.B.Z; - this.V6.Y = g.B.Z; - this.V6.Z = g.B.Z; - this.V6.W = 1f; - - this.V7.X = g.B.W; - this.V7.Y = g.B.W; - this.V7.Z = g.B.W; - this.V7.W = 1f; - } - } } } From 2537547ae40557dcbeca89b87d74af81d8551aeb Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 3 Oct 2021 22:50:29 +0200 Subject: [PATCH 16/24] use AggressiveInlining in some methods regardless of PROFILING --- src/ImageSharp/Common/Helpers/InliningOptions.cs | 4 ++++ src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs | 2 +- .../Formats/Jpeg/Components/Decoder/HuffmanScanBuffer.cs | 6 +++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/ImageSharp/Common/Helpers/InliningOptions.cs b/src/ImageSharp/Common/Helpers/InliningOptions.cs index 4bc8ef3c87..1ae880787e 100644 --- a/src/ImageSharp/Common/Helpers/InliningOptions.cs +++ b/src/ImageSharp/Common/Helpers/InliningOptions.cs @@ -12,6 +12,10 @@ namespace SixLabors.ImageSharp /// internal static class InliningOptions { + /// + /// regardless of the build conditions. + /// + public const MethodImplOptions AlwaysInline = MethodImplOptions.AggressiveInlining; #if PROFILING public const MethodImplOptions HotPath = MethodImplOptions.NoInlining; public const MethodImplOptions ShortMethod = MethodImplOptions.NoInlining; diff --git a/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs b/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs index b530a37e77..574ca35bb3 100644 --- a/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs +++ b/src/ImageSharp/Common/Helpers/SimdUtils.HwIntrinsics.cs @@ -537,7 +537,7 @@ private static void Shuffle4Slice3( /// The first vector to multiply. /// The second vector to multiply. /// The . - [MethodImpl(InliningOptions.ShortMethod)] + [MethodImpl(InliningOptions.AlwaysInline)] public static Vector256 MultiplyAdd( in Vector256 va, in Vector256 vm0, diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanBuffer.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanBuffer.cs index 12ea39e37b..3664cb4eb3 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanBuffer.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/HuffmanScanBuffer.cs @@ -80,7 +80,7 @@ public void Reset() [MethodImpl(InliningOptions.ShortMethod)] public bool HasBadMarker() => this.Marker != JpegConstants.Markers.XFF && !this.HasRestartMarker(); - [MethodImpl(InliningOptions.ShortMethod)] + [MethodImpl(InliningOptions.AlwaysInline)] public void FillBuffer() { // Attempt to load at least the minimum number of required bits into the buffer. @@ -130,7 +130,7 @@ private static bool HasRestart(byte marker) [MethodImpl(InliningOptions.ShortMethod)] public int PeekBits(int nbits) => (int)ExtractBits(this.data, this.remainingBits - nbits, nbits); - [MethodImpl(InliningOptions.ShortMethod)] + [MethodImpl(InliningOptions.AlwaysInline)] private static ulong ExtractBits(ulong value, int offset, int size) => (value >> offset) & (ulong)((1 << size) - 1); [MethodImpl(InliningOptions.ShortMethod)] @@ -207,7 +207,7 @@ public bool FindNextMarker() } } - [MethodImpl(InliningOptions.ShortMethod)] + [MethodImpl(InliningOptions.AlwaysInline)] private int ReadStream() { int value = this.badData ? 0 : this.stream.ReadByte(); From 6e136ecc3bd3760e95b28c9478db86fe038ef946 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 3 Oct 2021 22:50:49 +0200 Subject: [PATCH 17/24] LoadResizeSaveStressRunner.ThumbnailSize as a parameter --- .../LoadResizeSave/LoadResizeSaveStressRunner.cs | 3 ++- .../LoadResizeSaveParallelMemoryStress.cs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/ImageSharp.Benchmarks/LoadResizeSave/LoadResizeSaveStressRunner.cs b/tests/ImageSharp.Benchmarks/LoadResizeSave/LoadResizeSaveStressRunner.cs index c15f641b4a..f36ae8b4cf 100644 --- a/tests/ImageSharp.Benchmarks/LoadResizeSave/LoadResizeSaveStressRunner.cs +++ b/tests/ImageSharp.Benchmarks/LoadResizeSave/LoadResizeSaveStressRunner.cs @@ -31,7 +31,6 @@ public enum JpegKind public class LoadResizeSaveStressRunner { - private const int ThumbnailSize = 150; private const int Quality = 75; private const string ImageSharp = nameof(ImageSharp); private const string SystemDrawing = nameof(SystemDrawing); @@ -58,6 +57,8 @@ public class LoadResizeSaveStressRunner public JpegKind Filter { get; set; } + public int ThumbnailSize { get; set; } = 150; + private static readonly string[] ProgressiveFiles = { "ancyloscelis-apiformis-m-paraguay-face_2014-08-08-095255-zs-pmax_15046500892_o.jpg", diff --git a/tests/ImageSharp.Tests.ProfilingSandbox/LoadResizeSaveParallelMemoryStress.cs b/tests/ImageSharp.Tests.ProfilingSandbox/LoadResizeSaveParallelMemoryStress.cs index 2aadf02eb9..ad46731c7f 100644 --- a/tests/ImageSharp.Tests.ProfilingSandbox/LoadResizeSaveParallelMemoryStress.cs +++ b/tests/ImageSharp.Tests.ProfilingSandbox/LoadResizeSaveParallelMemoryStress.cs @@ -18,7 +18,7 @@ private LoadResizeSaveParallelMemoryStress() this.benchmarks = new LoadResizeSaveStressRunner() { // MaxDegreeOfParallelism = 10, - // Filter = JpegKind.Baseline + Filter = JpegKind.Baseline, }; this.benchmarks.Init(); } @@ -58,6 +58,7 @@ 6. ImageMagick lrs.SystemDrawingBenchmarkParallel(); break; case ConsoleKey.D2: + Console.WriteLine($"Images: {lrs.benchmarks.Images.Length}"); lrs.ImageSharpBenchmarkParallel(); break; case ConsoleKey.D3: From a421d6e804438b4bad7d7f834b8e43c0d3529632 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 3 Oct 2021 22:57:27 +0200 Subject: [PATCH 18/24] !values.IsEmpty MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Günther Foidl --- .../ColorConverters/JpegColorConverter.FromGrayScaleBasic.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleBasic.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleBasic.cs index 92a21a4380..146b1c130f 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleBasic.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleBasic.cs @@ -32,7 +32,7 @@ internal static void ScaleValues(Span values, float maxValue) } values = values.Slice(vecValues.Length * 4); - if (values.Length > 0) + if (!values.IsEmpty) { float scaleValue = 1f / maxValue; values[0] *= scaleValue; From bcfd3f3ca48fb3b73eb4d6f73b183398350f0ee4 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 3 Oct 2021 23:02:35 +0200 Subject: [PATCH 19/24] use nint with Unsafe.Add --- .../ColorConverters/JpegColorConverter.FromCmykAvx2.cs | 4 ++-- .../ColorConverters/JpegColorConverter.FromCmykVector8.cs | 4 ++-- .../ColorConverters/JpegColorConverter.FromGrayScaleAvx2.cs | 4 ++-- .../Decoder/ColorConverters/JpegColorConverter.FromRgbAvx2.cs | 4 ++-- .../ColorConverters/JpegColorConverter.FromRgbVector8.cs | 4 ++-- .../ColorConverters/JpegColorConverter.FromYCbCrAvx2.cs | 4 ++-- .../ColorConverters/JpegColorConverter.FromYCbCrVector4.cs | 4 ++-- .../ColorConverters/JpegColorConverter.FromYCbCrVector8.cs | 4 ++-- .../ColorConverters/JpegColorConverter.FromYccKAvx2.cs | 4 ++-- .../ColorConverters/JpegColorConverter.FromYccKVector8.cs | 4 ++-- 10 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx2.cs index 2c77a42a06..216c12735f 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx2.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykAvx2.cs @@ -37,8 +37,8 @@ protected override void ConvertCoreVectorizedInplace(in ComponentValues values) // Used for the color conversion var scale = Vector256.Create(1 / this.MaximumValue); - int n = values.Component0.Length / 8; - for (int i = 0; i < n; i++) + nint n = values.Component0.Length / 8; + for (nint i = 0; i < n; i++) { ref Vector256 c = ref Unsafe.Add(ref c0Base, i); ref Vector256 m = ref Unsafe.Add(ref c1Base, i); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykVector8.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykVector8.cs index 7a272d148d..0da4c9ec23 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykVector8.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromCmykVector8.cs @@ -32,8 +32,8 @@ protected override void ConvertCoreVectorizedInplace(in ComponentValues values) var scale = new Vector(1 / this.MaximumValue); // Walking 8 elements at one step: - int n = values.Component0.Length / 8; - for (int i = 0; i < n; i++) + nint n = values.Component0.Length / 8; + for (nint i = 0; i < n; i++) { ref Vector c = ref Unsafe.Add(ref cBase, i); ref Vector m = ref Unsafe.Add(ref mBase, i); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleAvx2.cs index c54ecdedcc..eca6b62920 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleAvx2.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleAvx2.cs @@ -31,8 +31,8 @@ protected override void ConvertCoreVectorizedInplace(in ComponentValues values) // Used for the color conversion var scale = Vector256.Create(1 / this.MaximumValue); - int n = values.Component0.Length / 8; - for (int i = 0; i < n; i++) + nint n = values.Component0.Length / 8; + for (nint i = 0; i < n; i++) { ref Vector256 c0 = ref Unsafe.Add(ref c0Base, i); c0 = Avx.Multiply(c0, scale); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbAvx2.cs index 2ec78c5273..557e4e4173 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbAvx2.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbAvx2.cs @@ -34,8 +34,8 @@ protected override void ConvertCoreVectorizedInplace(in ComponentValues values) // Used for the color conversion var scale = Vector256.Create(1 / this.MaximumValue); - int n = values.Component0.Length / 8; - for (int i = 0; i < n; i++) + nint n = values.Component0.Length / 8; + for (nint i = 0; i < n; i++) { ref Vector256 r = ref Unsafe.Add(ref rBase, i); ref Vector256 g = ref Unsafe.Add(ref gBase, i); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbVector8.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbVector8.cs index 3def60186e..a00361d970 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbVector8.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromRgbVector8.cs @@ -30,8 +30,8 @@ protected override void ConvertCoreVectorizedInplace(in ComponentValues values) var scale = new Vector(1 / this.MaximumValue); // Walking 8 elements at one step: - int n = values.Component0.Length / 8; - for (int i = 0; i < n; i++) + nint n = values.Component0.Length / 8; + for (nint i = 0; i < n; i++) { ref Vector r = ref Unsafe.Add(ref rBase, i); ref Vector g = ref Unsafe.Add(ref gBase, i); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrAvx2.cs index 67447aae5e..5aae1faa27 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrAvx2.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrAvx2.cs @@ -47,8 +47,8 @@ protected override void ConvertCoreVectorizedInplace(in ComponentValues values) Vector256 vcontrol = Unsafe.As>(ref control); // Walking 8 elements at one step: - int n = values.Component0.Length / 8; - for (int i = 0; i < n; i++) + nint n = values.Component0.Length / 8; + for (nint i = 0; i < n; i++) { // y = yVals[i]; // cb = cbVals[i] - 128F; diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector4.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector4.cs index f65ba30260..1ebc3e879d 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector4.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector4.cs @@ -35,9 +35,9 @@ protected override void ConvertCoreVectorizedInplace(in ComponentValues values) var maxValue = this.MaximumValue; // Walking 8 elements at one step: - int n = values.Component0.Length / 8; + nint n = values.Component0.Length / 8; - for (int i = 0; i < n; i++) + for (nint i = 0; i < n; i++) { // y = yVals[i]; ref Vector4Pair c0 = ref Unsafe.Add(ref c0Base, i); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector8.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector8.cs index 633c7f41d9..a077b9ed82 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector8.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrVector8.cs @@ -31,10 +31,10 @@ protected override void ConvertCoreVectorizedInplace(in ComponentValues values) var chromaOffset = new Vector(-this.HalfValue); // Walking 8 elements at one step: - int n = values.Component0.Length / 8; + nint n = values.Component0.Length / 8; var scale = new Vector(1 / this.MaximumValue); - for (int i = 0; i < n; i++) + for (nint i = 0; i < n; i++) { // y = yVals[i]; // cb = cbVals[i] - 128F; diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKAvx2.cs index 5fc2fe75b6..a3500a096a 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKAvx2.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKAvx2.cs @@ -44,8 +44,8 @@ protected override void ConvertCoreVectorizedInplace(in ComponentValues values) var bCbMult = Vector256.Create(1.772F); // Walking 8 elements at one step: - int n = values.Component0.Length / 8; - for (int i = 0; i < n; i++) + nint n = values.Component0.Length / 8; + for (nint i = 0; i < n; i++) { // y = yVals[i]; // cb = cbVals[i] - 128F; diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKVector8.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKVector8.cs index de516980e7..0a4c3f5284 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKVector8.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKVector8.cs @@ -32,12 +32,12 @@ protected override void ConvertCoreVectorizedInplace(in ComponentValues values) var chromaOffset = new Vector(-this.HalfValue); // Walking 8 elements at one step: - int n = values.Component0.Length / 8; + nint n = values.Component0.Length / 8; var scale = new Vector(1 / (this.MaximumValue * this.MaximumValue)); var max = new Vector(this.MaximumValue); - for (int i = 0; i < n; i++) + for (nint i = 0; i < n; i++) { // y = yVals[i]; // cb = cbVals[i] - 128F; From 4803b455db9fafa0375f2cc58899dd9745723031 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 3 Oct 2021 23:04:59 +0200 Subject: [PATCH 20/24] "less ceremony" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Günther Foidl --- .../ColorConverters/JpegColorConverter.FromYccKVector8.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKVector8.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKVector8.cs index 0a4c3f5284..f830e5042c 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKVector8.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYccKVector8.cs @@ -34,8 +34,8 @@ protected override void ConvertCoreVectorizedInplace(in ComponentValues values) // Walking 8 elements at one step: nint n = values.Component0.Length / 8; - var scale = new Vector(1 / (this.MaximumValue * this.MaximumValue)); var max = new Vector(this.MaximumValue); + var scale = new Vector(1f) / (max * max); for (nint i = 0; i < n; i++) { From ed576227f55d3d06fb4cffd93c7f18c2527bf481 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 3 Oct 2021 23:13:32 +0200 Subject: [PATCH 21/24] ((uint)bufferIdx >= group.Count) trick --- .../MemoryGroupExtensions.cs | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupExtensions.cs b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupExtensions.cs index 319c72af52..8e6f38d145 100644 --- a/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupExtensions.cs +++ b/src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupExtensions.cs @@ -39,12 +39,8 @@ internal static Memory GetBoundedSlice(this IMemoryGroup group, long st int bufferIdx = (int)(start / group.BufferLength); - if (bufferIdx < 0) - { - throw new ArgumentOutOfRangeException(nameof(start)); - } - - if (bufferIdx >= group.Count) + // if (bufferIdx < 0 || bufferIdx >= group.Count) + if ((uint)bufferIdx >= group.Count) { throw new ArgumentOutOfRangeException(nameof(start)); } @@ -73,12 +69,8 @@ internal static Memory GetRemainingSliceOfBuffer(this IMemoryGroup grou int bufferIdx = (int)(start / group.BufferLength); - if (bufferIdx < 0) - { - throw new ArgumentOutOfRangeException(nameof(start)); - } - - if (bufferIdx >= group.Count) + // if (bufferIdx < 0 || bufferIdx >= group.Count) + if ((uint)bufferIdx >= group.Count) { throw new ArgumentOutOfRangeException(nameof(start)); } From ad976f12d831dd7e6912e48dc4c14ddd1b0c9e01 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Tue, 5 Oct 2021 12:53:27 +0200 Subject: [PATCH 22/24] elide further bound checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Günther Foidl --- .../ColorConverters/JpegColorConverter.FromGrayScaleBasic.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleBasic.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleBasic.cs index 146b1c130f..76d57bf069 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleBasic.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromGrayScaleBasic.cs @@ -37,11 +37,11 @@ internal static void ScaleValues(Span values, float maxValue) float scaleValue = 1f / maxValue; values[0] *= scaleValue; - if (values.Length > 1) + if ((uint)values.Length > 1) { values[1] *= scaleValue; - if (values.Length > 2) + if ((uint)values.Length > 2) { values[2] *= scaleValue; } From 6d9a04d38cec01db10ff9197a92489adbe33ad81 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Tue, 5 Oct 2021 14:27:27 +0200 Subject: [PATCH 23/24] Premultiply only if alpha representation is unknown or Unassociated --- .../Transforms/Resize/ResizeProcessor{TPixel}.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs index 1daed9ee63..c5e53318d2 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs @@ -188,8 +188,11 @@ private static void ApplyResizeFrameTransform( bool compand, bool premultiplyAlpha) { - bool pixelHasNoAlpha = PixelOperations.Instance.GetPixelTypeInfo()?.AlphaRepresentation == PixelAlphaRepresentation.None; - premultiplyAlpha &= !pixelHasNoAlpha; + PixelAlphaRepresentation? alphaRepresentation = PixelOperations.Instance.GetPixelTypeInfo()?.PixelAlphaRepresentation; + + // Premultiply only if alpha representation is unknown or Unassociated: + bool needsPremultiplication = alphaRepresentation == null || alphaRepresentation.Value == PixelAlphaRepresentation.Unassociated; + premultiplyAlpha &= needsPremultiplication; PixelConversionModifiers conversionModifiers = GetModifiers(compand, premultiplyAlpha); Buffer2DRegion sourceRegion = source.PixelBuffer.GetRegion(sourceRectangle); From 4323c8d1754273b271d88068c2b68887c733f62f Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Tue, 5 Oct 2021 23:42:04 +1100 Subject: [PATCH 24/24] Update src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs --- .../Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs index c5e53318d2..1b93d01a18 100644 --- a/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs +++ b/src/ImageSharp/Processing/Processors/Transforms/Resize/ResizeProcessor{TPixel}.cs @@ -188,7 +188,7 @@ private static void ApplyResizeFrameTransform( bool compand, bool premultiplyAlpha) { - PixelAlphaRepresentation? alphaRepresentation = PixelOperations.Instance.GetPixelTypeInfo()?.PixelAlphaRepresentation; + PixelAlphaRepresentation? alphaRepresentation = PixelOperations.Instance.GetPixelTypeInfo()?.AlphaRepresentation; // Premultiply only if alpha representation is unknown or Unassociated: bool needsPremultiplication = alphaRepresentation == null || alphaRepresentation.Value == PixelAlphaRepresentation.Unassociated;