diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/Component.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/Component.cs index 59c5c69c80..cf02865241 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/Component.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/Component.cs @@ -84,11 +84,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder /// Maximal vertical subsampling factor among all the components. public void Init(JpegFrame frame, int maxSubFactorH, int maxSubFactorV) { + uint widthInBlocks = ((uint)frame.PixelWidth + 7) / 8; + uint heightInBlocks = ((uint)frame.PixelHeight + 7) / 8; + this.WidthInBlocks = (int)MathF.Ceiling( - ((uint)frame.PixelWidth + 7) / 8 * this.HorizontalSamplingFactor / maxSubFactorH); + (float)widthInBlocks * this.HorizontalSamplingFactor / maxSubFactorH); this.HeightInBlocks = (int)MathF.Ceiling( - ((uint)frame.PixelHeight + 7) / 8 * this.VerticalSamplingFactor / maxSubFactorV); + (float)heightInBlocks * this.VerticalSamplingFactor / maxSubFactorV); int blocksPerLineForMcu = frame.McusPerLine * this.HorizontalSamplingFactor; int blocksPerColumnForMcu = frame.McusPerColumn * this.VerticalSamplingFactor; diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/ComponentProcessor.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/ComponentProcessor.cs index 8c9f826a10..9795ab9534 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/ComponentProcessor.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/ComponentProcessor.cs @@ -157,18 +157,24 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder static void SumHorizontal(Span target, int factor) { + Span source = target; if (Avx2.IsSupported) { ref Vector256 targetRef = ref Unsafe.As>(ref MemoryMarshal.GetReference(target)); // Ideally we need to use log2: Numerics.Log2((uint)factor) // but division by 2 works just fine in this case - // because factor value range is [1, 2, 4] - // log2(1) == 1 / 2 == 0 - // log2(2) == 2 / 2 == 1 - // log2(4) == 4 / 2 == 2 int haddIterationsCount = (int)((uint)factor / 2); - uint length = (uint)target.Length / (uint)Vector256.Count; + + // Transform spans so that it only contains 'remainder' + // values for the scalar fallback code + int scalarRemainder = target.Length % (Vector.Count * factor); + int touchedCount = target.Length - scalarRemainder; + source = source.Slice(touchedCount); + target = target.Slice(touchedCount / factor); + + uint length = (uint)touchedCount / (uint)Vector256.Count; + for (int i = 0; i < haddIterationsCount; i++) { length /= 2; @@ -181,18 +187,15 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder Unsafe.Add(ref targetRef, j) = Avx2.Permute4x64(sum.AsDouble(), 0b11_01_10_00).AsSingle(); } } - - int summedCount = (int)(length * factor * Vector256.Count); - target = target.Slice(summedCount); } // scalar remainder - for (int i = 0; i < target.Length / factor; i++) + for (int i = 0; i < source.Length / factor; i++) { - target[i] = target[i * factor]; + target[i] = source[i * factor]; for (int j = 1; j < factor; j++) { - target[i] += target[(i * factor) + j]; + target[i] += source[(i * factor) + j]; } } } diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs index 5e38f4455c..52bddd27f1 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs @@ -143,7 +143,6 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg [WithSolidFilledImages(nameof(BitsPerPixel_Quality), 1, 1, 100, 100, 100, 255, PixelTypes.L8)] [WithSolidFilledImages(nameof(BitsPerPixel_Quality), 1, 1, 255, 100, 50, 255, PixelTypes.Rgba32)] [WithTestPatternImages(nameof(BitsPerPixel_Quality), 143, 81, PixelTypes.Rgba32)] - [WithTestPatternImages(nameof(BitsPerPixel_Quality), 7, 5, PixelTypes.Rgba32)] [WithTestPatternImages(nameof(BitsPerPixel_Quality), 96, 48, PixelTypes.Rgba32)] [WithTestPatternImages(nameof(BitsPerPixel_Quality), 73, 71, PixelTypes.Rgba32)] [WithTestPatternImages(nameof(BitsPerPixel_Quality), 48, 24, PixelTypes.Rgba32)]