diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/ComponentProcessor.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/ComponentProcessor.cs index 9795ab953..5d858f84d 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/ComponentProcessor.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/ComponentProcessor.cs @@ -43,13 +43,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder public void CopyColorBufferToBlocks(int spectralStep) { Buffer2D spectralBuffer = this.component.SpectralBlocks; - - // should be this.frame.MaxColorChannelValue - // but 12-bit jpegs are not supported currently - float normalizationValue = -128f; - int destAreaStride = this.ColorBuffer.Width; - int yBlockStart = spectralStep * this.component.SamplingFactors.Height; Block8x8F workspaceBlock = default; @@ -77,7 +71,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder destAreaStride); // level shift via -128f - workspaceBlock.AddInPlace(normalizationValue); + workspaceBlock.AddInPlace(-128f); // FDCT FastFloatingPointDCT.TransformFDCT(ref workspaceBlock); diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/SpectralConverter{TPixel}.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/SpectralConverter{TPixel}.cs index 44271248f..a1c335b4f 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/SpectralConverter{TPixel}.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/SpectralConverter{TPixel}.cs @@ -98,9 +98,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder int pixelBufferLastVerticalIndex = this.pixelBuffer.Height - 1; + // Pixel strides must be padded with the last pixel of the stride + int paddingStartIndex = this.pixelBuffer.Width; + int paddedPixelsCount = this.alignedPixelWidth - this.pixelBuffer.Width; + Span rLane = this.redLane.GetSpan(); Span gLane = this.greenLane.GetSpan(); Span bLane = this.blueLane.GetSpan(); + for (int yy = start; yy < end; yy++) { int y = yy - this.pixelRowCounter; @@ -110,6 +115,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder Span sourceRow = this.pixelBuffer.DangerousGetRowSpan(srcIndex); PixelOperations.Instance.UnpackIntoRgbPlanes(rLane, gLane, bLane, sourceRow); + rLane.Slice(paddingStartIndex).Fill(rLane[paddingStartIndex - 1]); + gLane.Slice(paddingStartIndex).Fill(gLane[paddingStartIndex - 1]); + bLane.Slice(paddingStartIndex).Fill(bLane[paddingStartIndex - 1]); + // Convert from rgb24 to target pixel type var values = new JpegColorConverterBase.ComponentValues(this.componentProcessors, y); this.colorConverter.ConvertFromRgb(values, rLane, gLane, bLane); diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs index 52bddd27f..d9097ed16 100644 --- a/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs +++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegEncoderTests.cs @@ -148,6 +148,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg [WithTestPatternImages(nameof(BitsPerPixel_Quality), 48, 24, PixelTypes.Rgba32)] [WithTestPatternImages(nameof(BitsPerPixel_Quality), 46, 8, PixelTypes.Rgba32)] [WithTestPatternImages(nameof(BitsPerPixel_Quality), 51, 7, PixelTypes.Rgba32)] + [WithTestPatternImages(nameof(BitsPerPixel_Quality), 7, 5, PixelTypes.Rgba32)] public void EncodeBaseline_WithSmallImages_WorksWithDifferentSizes(TestImageProvider provider, JpegEncodingColor colorType, int quality) where TPixel : unmanaged, IPixel => TestJpegEncoderCore(provider, colorType, quality, comparer: ImageComparer.Tolerant(0.15f));