From 672da457d340b2ae6df50d880dfdba0f12c9e2ec Mon Sep 17 00:00:00 2001 From: Dmitry Pentin Date: Sun, 30 May 2021 22:44:09 +0300 Subject: [PATCH] Finished 444 subsampling converter --- .../Components/Encoder/HuffmanScanEncoder.cs | 5 +- .../YCbCrForwardConverter444{TPixel}.cs | 53 +++++++++++++++---- 2 files changed, 47 insertions(+), 11 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs index 283a98fab..218b2b59c 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs @@ -71,11 +71,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder // ReSharper disable once InconsistentNaming int prevDCY = 0, prevDCCb = 0, prevDCCr = 0; - var pixelConverter = YCbCrForwardConverter444.Create(); ImageFrame frame = pixels.Frames.RootFrame; Buffer2D pixelBuffer = frame.PixelBuffer; RowOctet currentRows = default; + var pixelConverter = new YCbCrForwardConverter444(frame); + for (int y = 0; y < pixels.Height; y += 8) { cancellationToken.ThrowIfCancellationRequested(); @@ -83,7 +84,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder for (int x = 0; x < pixels.Width; x += 8) { - pixelConverter.Convert(frame, x, y, ref currentRows); + pixelConverter.Convert(x, y, ref currentRows); prevDCY = this.WriteBlock( QuantIndex.Luminance, diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrForwardConverter444{TPixel}.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrForwardConverter444{TPixel}.cs index 8fef55302..27f7e3ae9 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrForwardConverter444{TPixel}.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrForwardConverter444{TPixel}.cs @@ -16,10 +16,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder internal ref struct YCbCrForwardConverter444 where TPixel : unmanaged, IPixel { - // TODO: documentation - private const int RgbSpanByteSize = 8 * 8 * 3; - // TODO: documentation - private const int PixelSpanSize = 8 * 8; + // TODO: docs + private const int PixelsPerSample = 8 * 8; + + // TODO: docs + private const int RgbSpanByteSize = PixelsPerSample * 3; + + // TODO: docs + private static readonly Size SampleSize = new Size(8, 8); /// @@ -52,6 +56,38 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder /// private Span rgbSpan; + // TODO: docs + private Size samplingAreaSize; + + // TODO: docs + private readonly Configuration config; + + public YCbCrForwardConverter444(ImageFrame frame) + { + // matrices would be filled during convert calls + this.Y = default; + this.Cb = default; + this.Cr = default; + + // temporal pixel buffers + this.pixelSpan = new TPixel[PixelsPerSample].AsSpan(); + this.rgbSpan = MemoryMarshal.Cast(new byte[RgbSpanByteSize + RgbToYCbCrConverterVectorized.AvxRegisterRgbCompatibilityPadding].AsSpan()); + + // frame data + this.samplingAreaSize = new Size(frame.Width, frame.Height); + this.config = frame.GetConfiguration(); + + // conversion vector fallback data + if (!RgbToYCbCrConverterVectorized.IsSupported) + { + this.colorTables = RgbToYCbCrConverterLut.Create(); + } + else + { + this.colorTables = default; + } + } + public static YCbCrForwardConverter444 Create() { var result = default(YCbCrForwardConverter444); @@ -62,7 +98,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder result.rgbSpan = MemoryMarshal.Cast(new byte[RgbSpanByteSize + 8].AsSpan()); // TODO: this is subject to discuss - result.pixelSpan = new TPixel[PixelSpanSize].AsSpan(); + result.pixelSpan = new TPixel[PixelsPerSample].AsSpan(); // Avoid creating lookup tables, when vectorized converter is supported if (!RgbToYCbCrConverterVectorized.IsSupported) @@ -76,12 +112,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder /// /// Converts a 8x8 image area inside 'pixels' at position (x,y) placing the result members of the structure (, , ) /// - public void Convert(ImageFrame frame, int x, int y, ref RowOctet currentRows) + public void Convert(int x, int y, ref RowOctet currentRows) { - Memory.Buffer2D buffer = frame.PixelBuffer; - YCbCrForwardConverter.LoadAndStretchEdges(currentRows, this.pixelSpan, new Point(x, y), new Size(8), new Size(buffer.Width, buffer.Height)); + YCbCrForwardConverter.LoadAndStretchEdges(currentRows, this.pixelSpan, new Point(x, y), SampleSize, this.samplingAreaSize); - PixelOperations.Instance.ToRgb24(frame.GetConfiguration(), this.pixelSpan, this.rgbSpan); + PixelOperations.Instance.ToRgb24(this.config, this.pixelSpan, this.rgbSpan); ref Block8x8F yBlock = ref this.Y; ref Block8x8F cbBlock = ref this.Cb;