diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs index 15fbb83d96..1f47de594c 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs @@ -1,6 +1,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Numerics; using System.Runtime.CompilerServices; @@ -96,7 +97,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components { Vector4 CMin4 = new Vector4(0F); Vector4 CMax4 = new Vector4(maximum); - Vector4 COff4 = new Vector4(maximum/2 + 1); + Vector4 COff4 = new Vector4((float)Math.Ceiling(maximum/2)); this.V0L = Vector4.Clamp(this.V0L + COff4, CMin4, CMax4); this.V0R = Vector4.Clamp(this.V0R + COff4, CMin4, CMax4); @@ -122,7 +123,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components [MethodImpl(InliningOptions.ShortMethod)] public void NormalizeColorsAndRoundInplaceAvx2(float maximum) { - Vector off = new Vector(maximum/2 +1); + Vector off = new Vector((float)Math.Ceiling(maximum/2)); Vector max = new Vector(maximum); ref Vector row0 = ref Unsafe.As>(ref this.V0L); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt index 431ba86b03..ec4e06e429 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt +++ b/src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt @@ -11,6 +11,7 @@ // Copyright (c) Six Labors and contributors. // Licensed under the Apache License, Version 2.0. +using System; using System.Numerics; using System.Runtime.CompilerServices; @@ -61,7 +62,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components { Vector4 CMin4 = new Vector4(0F); Vector4 CMax4 = new Vector4(maximum); - Vector4 COff4 = new Vector4(maximum/2 + 1); + Vector4 COff4 = new Vector4((float)Math.Ceiling(maximum/2)); <# @@ -85,7 +86,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components [MethodImpl(InliningOptions.ShortMethod)] public void NormalizeColorsAndRoundInplaceAvx2(float maximum) { - Vector off = new Vector(maximum/2 +1); + Vector off = new Vector((float)Math.Ceiling(maximum/2)); Vector max = new Vector(maximum); <# 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 2cab95ff09..124aac1224 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrBasic.cs @@ -17,10 +17,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters public override void ConvertToRgba(in ComponentValues values, Span result) { - ConvertCore(values, result); + ConvertCore(values, result, this.MaximumValue, this.HalfValue); } - internal static void ConvertCore(in ComponentValues values, Span result) + 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; @@ -29,13 +29,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters var v = new Vector4(0, 0, 0, 1); - var scale = new Vector4(1 / 255F, 1 / 255F, 1 / 255F, 1F); + var scale = new Vector4(1 / maxValue, 1 / maxValue, 1 / maxValue, 1F); for (int i = 0; i < result.Length; i++) { float y = yVals[i]; - float cb = cbVals[i] - 128F; - float cr = crVals[i] - 128F; + float cb = cbVals[i] - halfValue; + float cr = crVals[i] - halfValue; v.X = MathF.Round(y + (1.402F * cr), MidpointRounding.AwayFromZero); v.Y = MathF.Round(y - (0.344136F * cb) - (0.714136F * cr), MidpointRounding.AwayFromZero); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs index 1047957100..5de6f2ffb0 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs @@ -28,7 +28,8 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters ConvertCore(values.Slice(0, simdCount), result.Slice(0, simdCount), this.MaximumValue, this.HalfValue); } - FromYCbCrBasic.ConvertCore(values.Slice(simdCount, remainder), result.Slice(simdCount, remainder)); + FromYCbCrBasic.ConvertCore(values.Slice(simdCount, remainder), result.Slice(simdCount, remainder), + this.MaximumValue, this.HalfValue); } /// diff --git a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs index 4696959950..c34bc17ad5 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimdAvx2.cs @@ -28,16 +28,18 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters int simdCount = result.Length - remainder; if (simdCount > 0) { - ConvertCore(values.Slice(0, simdCount), result.Slice(0, simdCount)); + ConvertCore(values.Slice(0, simdCount), result.Slice(0, simdCount), + this.MaximumValue, this.HalfValue); } - FromYCbCrBasic.ConvertCore(values.Slice(simdCount, remainder), result.Slice(simdCount, remainder)); + FromYCbCrBasic.ConvertCore(values.Slice(simdCount, remainder), result.Slice(simdCount, remainder), + this.MaximumValue, this.HalfValue);; } /// /// SIMD convert using buffers of sizes divisible by 8. /// - internal static void ConvertCore(in ComponentValues values, Span result) + internal static void ConvertCore(in ComponentValues values, Span result, float maxValue, float halfValue) { // This implementation is actually AVX specific. // An AVX register is capable of storing 8 float-s. @@ -57,7 +59,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters ref Vector4Octet resultBase = ref Unsafe.As(ref MemoryMarshal.GetReference(result)); - var chromaOffset = new Vector(-128f); + var chromaOffset = new Vector(-halfValue); // Walking 8 elements at one step: int n = result.Length / 8; @@ -70,7 +72,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters ref Vector ggRefAsVector = ref Unsafe.As>(ref gg); ref Vector bbRefAsVector = ref Unsafe.As>(ref bb); - var scale = new Vector(1 / 255f); + var scale = new Vector(1 / maxValue); for (int i = 0; i < n; i++) { diff --git a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/YCbCrColorConversion.cs b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/YCbCrColorConversion.cs index 05edd27919..8417b32f27 100644 --- a/tests/ImageSharp.Benchmarks/Codecs/Jpeg/YCbCrColorConversion.cs +++ b/tests/ImageSharp.Benchmarks/Codecs/Jpeg/YCbCrColorConversion.cs @@ -41,7 +41,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg { var values = new JpegColorConverter.ComponentValues(this.input, 0); - JpegColorConverter.FromYCbCrBasic.ConvertCore(values, this.output); + JpegColorConverter.FromYCbCrBasic.ConvertCore(values, this.output, 255F, 128F); } [Benchmark] @@ -49,7 +49,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg { var values = new JpegColorConverter.ComponentValues(this.input, 0); - JpegColorConverter.FromYCbCrSimd.ConvertCore(values, this.output); + JpegColorConverter.FromYCbCrSimd.ConvertCore(values, this.output, 255F, 128F); } [Benchmark] @@ -57,7 +57,7 @@ namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg { var values = new JpegColorConverter.ComponentValues(this.input, 0); - JpegColorConverter.FromYCbCrSimdAvx2.ConvertCore(values, this.output); + JpegColorConverter.FromYCbCrSimdAvx2.ConvertCore(values, this.output, 255F, 128F); } private static Buffer2D[] CreateRandomValues(