From 5d3dcc0cf0fa40e6e8ac192150de8178155fe62e Mon Sep 17 00:00:00 2001 From: Dmitry Pentin Date: Tue, 10 May 2022 16:09:00 +0300 Subject: [PATCH] Implemented single component scan encoding --- .../Components/Encoder/HuffmanScanEncoder.cs | 44 +++++++++++++++++-- .../Formats/Jpeg/JpegEncoderCore.cs | 10 ++++- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs index 1dde766e78..3c606d6e06 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs @@ -138,7 +138,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder tables[tableConfig.DestinationIndex] = new HuffmanLut(tableConfig.Table); } - public void EncodeInterleavedBaselineScan(JpegFrame frame, SpectralConverter converter, CancellationToken cancellationToken) + public void EncodeScanBaselineInterleaved(JpegFrame frame, SpectralConverter converter, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel { // DEBUG INITIALIZATION SETUP @@ -156,7 +156,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder // Convert from pixels to spectral via given converter converter.ConvertStrideBaseline(); - // decode from binary to spectral + // Encode spectral to binary for (int i = 0; i < mcusPerLine; i++) { // Scan an interleaved mcu... process components in order @@ -203,9 +203,47 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder this.FlushRemainingBytes(); } - public void EncodeSingleComponentScan(JpegFrame frame, Image image, Block8x8F[] quantTables, Configuration configuration, CancellationToken cancellationToken) + public void EncodeScanBaselineSingleComponent(JpegFrame frame, SpectralConverter converter, CancellationToken cancellationToken) where TPixel : unmanaged, IPixel { + // DEBUG INITIALIZATION SETUP + frame.AllocateComponents(fullScan: false); + + JpegComponent component = frame.Components[0]; + int mcuLines = frame.McusPerColumn; + int w = component.WidthInBlocks; + int h = component.SamplingFactors.Height; + ref HuffmanLut dcHuffmanTable = ref this.dcHuffmanTables[component.DcTableId]; + ref HuffmanLut acHuffmanTable = ref this.acHuffmanTables[component.AcTableId]; + + for (int i = 0; i < mcuLines; i++) + { + cancellationToken.ThrowIfCancellationRequested(); + + // Convert from pixels to spectral via given converter + converter.ConvertStrideBaseline(); + + // Encode spectral to binary + for (int j = 0; j < h; j++) + { + Span blockSpan = component.SpectralBlocks.DangerousGetRowSpan(j); + ref Block8x8 blockRef = ref MemoryMarshal.GetReference(blockSpan); + + for (int k = 0; k < w; k++) + { + this.WriteBlock( + component, + ref Unsafe.Add(ref blockRef, k), + ref dcHuffmanTable, + ref acHuffmanTable); + + if (this.IsStreamFlushNeeded) + { + this.FlushToStream(); + } + } + } + } } private HuffmanLut[] huffmanTables; diff --git a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs index 452dae4e5f..a8e4dc2a17 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs @@ -128,7 +128,15 @@ namespace SixLabors.ImageSharp.Formats.Jpeg this.WriteStartOfScan(this.frameConfig.Components.Length, this.frameConfig.Components); var spectralConverter = new SpectralConverter(frame, image, this.QuantizationTables, Configuration.Default); - this.scanEncoder.EncodeInterleavedBaselineScan(frame, spectralConverter, cancellationToken); + + if (frame.ComponentCount > 1) + { + this.scanEncoder.EncodeScanBaselineInterleaved(frame, spectralConverter, cancellationToken); + } + else + { + this.scanEncoder.EncodeScanBaselineSingleComponent(frame, spectralConverter, cancellationToken); + } // Write the End Of Image marker. this.WriteEndOfImageMarker();