From 0d7e4b13f2df0a33bb9e1b36aa7878cf1c82f4a9 Mon Sep 17 00:00:00 2001 From: Dmitry Pentin Date: Fri, 21 May 2021 08:27:41 +0300 Subject: [PATCH] Removed unrelevant code from JpegDecoderCore --- .../Formats/Jpeg/JpegEncoderCore.cs | 473 ------------------ 1 file changed, 473 deletions(-) diff --git a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs index f1dd7f6bf1..019be629bb 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs @@ -92,67 +92,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg this.colorType = options.ColorType; } - /// - /// Gets the counts the number of bits needed to hold an integer. - /// - // The C# compiler emits this as a compile-time constant embedded in the PE file. - // This is effectively compiled down to: return new ReadOnlySpan(&data, length) - // More details can be found: https://github.com/dotnet/roslyn/pull/24621 - private static ReadOnlySpan BitCountLut => new byte[] - { - 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, - }; - - /// - /// Gets the unscaled quantization tables in zig-zag order. Each - /// encoder copies and scales the tables according to its quality parameter. - /// The values are derived from section K.1 after converting from natural to - /// zig-zag order. - /// - // The C# compiler emits this as a compile-time constant embedded in the PE file. - // This is effectively compiled down to: return new ReadOnlySpan(&data, length) - // More details can be found: https://github.com/dotnet/roslyn/pull/24621 - private static ReadOnlySpan UnscaledQuant_Luminance => new byte[] - { - // Luminance. - 16, 11, 12, 14, 12, 10, 16, 14, 13, 14, 18, 17, 16, 19, 24, - 40, 26, 24, 22, 22, 24, 49, 35, 37, 29, 40, 58, 51, 61, 60, - 57, 51, 56, 55, 64, 72, 92, 78, 64, 68, 87, 69, 55, 56, 80, - 109, 81, 87, 95, 98, 103, 104, 103, 62, 77, 113, 121, 112, - 100, 120, 92, 101, 103, 99, - }; - - /// - /// Gets the unscaled quantization tables in zig-zag order. Each - /// encoder copies and scales the tables according to its quality parameter. - /// The values are derived from section K.1 after converting from natural to - /// zig-zag order. - /// - // The C# compiler emits this as a compile-time constant embedded in the PE file. - // This is effectively compiled down to: return new ReadOnlySpan(&data, length) - // More details can be found: https://github.com/dotnet/roslyn/pull/24621 - private static ReadOnlySpan UnscaledQuant_Chrominance => new byte[] - { - // Chrominance. - 17, 18, 18, 24, 21, 24, 47, 26, 26, 47, 99, 66, 56, 66, - 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, - 99, 99, 99, 99, 99, 99, 99, 99, - }; - /// /// Encode writes the image to the jpeg baseline format with the given options. /// @@ -228,248 +167,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg } } - /// - /// Initializes quantization table. - /// - /// The quantization index. - /// The scaling factor. - /// The quantization table. - private static void InitQuantizationTable(int i, int scale, ref Block8x8F quant) - { - DebugGuard.MustBeBetweenOrEqualTo(i, 0, 1, nameof(i)); - ReadOnlySpan unscaledQuant = (i == 0) ? UnscaledQuant_Luminance : UnscaledQuant_Chrominance; - - for (int j = 0; j < Block8x8F.Size; j++) - { - int x = unscaledQuant[j]; - x = ((x * scale) + 50) / 100; - if (x < 1) - { - x = 1; - } - - if (x > 255) - { - x = 255; - } - - quant[j] = x; - } - } - - /// - /// Emits the least significant count of bits of bits to the bit-stream. - /// The precondition is bits - /// - /// < 1<<nBits && nBits <= 16 - /// - /// . - /// - /// The packed bits. - /// The number of bits - /// The reference to the emitBuffer. - [MethodImpl(InliningOptions.ShortMethod)] - private void Emit(uint bits, uint count, ref byte emitBufferBase) - { - count += this.bitCount; - bits <<= (int)(32 - count); - bits |= this.accumulatedBits; - - // Only write if more than 8 bits. - if (count >= 8) - { - // Track length - int len = 0; - while (count >= 8) - { - byte b = (byte)(bits >> 24); - Unsafe.Add(ref emitBufferBase, len++) = b; - if (b == byte.MaxValue) - { - Unsafe.Add(ref emitBufferBase, len++) = byte.MinValue; - } - - bits <<= 8; - count -= 8; - } - - if (len > 0) - { - this.outputStream.Write(this.emitBuffer, 0, len); - } - } - - this.accumulatedBits = bits; - this.bitCount = count; - } - - /// - /// Emits the given value with the given Huffman encoder. - /// - /// The index of the Huffman encoder - /// The value to encode. - /// The reference to the emit buffer. - [MethodImpl(InliningOptions.ShortMethod)] - private void EmitHuff(HuffIndex index, int value, ref byte emitBufferBase) - { - uint x = HuffmanLut.TheHuffmanLut[(int)index].Values[value]; - this.Emit(x & ((1 << 24) - 1), x >> 24, ref emitBufferBase); - } - - /// - /// Emits a run of runLength copies of value encoded with the given Huffman encoder. - /// - /// The index of the Huffman encoder - /// The number of copies to encode. - /// The value to encode. - /// The reference to the emit buffer. - [MethodImpl(InliningOptions.ShortMethod)] - private void EmitHuffRLE(HuffIndex index, int runLength, int value, ref byte emitBufferBase) - { - int a = value; - int b = value; - if (a < 0) - { - a = -value; - b = value - 1; - } - - uint bt; - if (a < 0x100) - { - bt = BitCountLut[a]; - } - else - { - bt = 8 + (uint)BitCountLut[a >> 8]; - } - - this.EmitHuff(index, (int)((uint)(runLength << 4) | bt), ref emitBufferBase); - if (bt > 0) - { - this.Emit((uint)b & (uint)((1 << ((int)bt)) - 1), bt, ref emitBufferBase); - } - } - - /// - /// Encodes the image with no subsampling. - /// - /// The pixel format. - /// The pixel accessor providing access to the image pixels. - /// The token to monitor for cancellation. - /// The reference to the emit buffer. - private void Encode444(Image pixels, CancellationToken cancellationToken, ref byte emitBufferBase) - where TPixel : unmanaged, IPixel - { - // TODO: Need a JpegScanEncoder class or struct that encapsulates the scan-encoding implementation. (Similar to JpegScanDecoder.) - // (Partially done with YCbCrForwardConverter) - Block8x8F temp1 = default; - Block8x8F temp2 = default; - - Block8x8F onStackLuminanceQuantTable = this.luminanceQuantTable; - Block8x8F onStackChrominanceQuantTable = this.chrominanceQuantTable; - - var unzig = ZigZag.CreateUnzigTable(); - - // ReSharper disable once InconsistentNaming - int prevDCY = 0, prevDCCb = 0, prevDCCr = 0; - - var pixelConverter = YCbCrForwardConverter.Create(); - ImageFrame frame = pixels.Frames.RootFrame; - Buffer2D pixelBuffer = frame.PixelBuffer; - RowOctet currentRows = default; - - for (int y = 0; y < pixels.Height; y += 8) - { - cancellationToken.ThrowIfCancellationRequested(); - currentRows.Update(pixelBuffer, y); - - for (int x = 0; x < pixels.Width; x += 8) - { - pixelConverter.Convert(frame, x, y, ref currentRows); - - prevDCY = this.WriteBlock( - QuantIndex.Luminance, - prevDCY, - ref pixelConverter.Y, - ref temp1, - ref temp2, - ref onStackLuminanceQuantTable, - ref unzig, - ref emitBufferBase); - - prevDCCb = this.WriteBlock( - QuantIndex.Chrominance, - prevDCCb, - ref pixelConverter.Cb, - ref temp1, - ref temp2, - ref onStackChrominanceQuantTable, - ref unzig, - ref emitBufferBase); - - prevDCCr = this.WriteBlock( - QuantIndex.Chrominance, - prevDCCr, - ref pixelConverter.Cr, - ref temp1, - ref temp2, - ref onStackChrominanceQuantTable, - ref unzig, - ref emitBufferBase); - } - } - } - - /// - /// Encodes the image with no chroma, just luminance. - /// - /// The pixel format. - /// The pixel accessor providing access to the image pixels. - /// The token to monitor for cancellation. - /// The reference to the emit buffer. - private void EncodeGrayscale(Image pixels, CancellationToken cancellationToken, ref byte emitBufferBase) - where TPixel : unmanaged, IPixel - { - // TODO: Need a JpegScanEncoder class or struct that encapsulates the scan-encoding implementation. (Similar to JpegScanDecoder.) - // (Partially done with YCbCrForwardConverter) - Block8x8F temp1 = default; - Block8x8F temp2 = default; - - Block8x8F onStackLuminanceQuantTable = this.luminanceQuantTable; - - var unzig = ZigZag.CreateUnzigTable(); - - // ReSharper disable once InconsistentNaming - int prevDCY = 0; - - var pixelConverter = LuminanceForwardConverter.Create(); - ImageFrame frame = pixels.Frames.RootFrame; - Buffer2D pixelBuffer = frame.PixelBuffer; - RowOctet currentRows = default; - - for (int y = 0; y < pixels.Height; y += 8) - { - cancellationToken.ThrowIfCancellationRequested(); - currentRows.Update(pixelBuffer, y); - - for (int x = 0; x < pixels.Width; x += 8) - { - pixelConverter.Convert(frame, x, y, ref currentRows); - - prevDCY = this.WriteBlock( - QuantIndex.Luminance, - prevDCY, - ref pixelConverter.Y, - ref temp1, - ref temp2, - ref onStackLuminanceQuantTable, - ref unzig, - ref emitBufferBase); - } - } - } - /// /// Writes the application header containing the JFIF identifier plus extra data. /// @@ -519,72 +216,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg this.outputStream.Write(this.buffer, 0, 20); } - /// - /// Writes a block of pixel data using the given quantization table, - /// returning the post-quantized DC value of the DCT-transformed block. - /// The block is in natural (not zig-zag) order. - /// - /// The quantization table index. - /// The previous DC value. - /// Source block - /// Temporal block to be used as FDCT Destination - /// Temporal block 2 - /// Quantization table - /// The 8x8 Unzig block. - /// The reference to the emit buffer. - /// The . - private int WriteBlock( - QuantIndex index, - int prevDC, - ref Block8x8F src, - ref Block8x8F tempDest1, - ref Block8x8F tempDest2, - ref Block8x8F quant, - ref ZigZag unZig, - ref byte emitBufferBase) - { - FastFloatingPointDCT.TransformFDCT(ref src, ref tempDest1, ref tempDest2); - - Block8x8F.Quantize(ref tempDest1, ref tempDest2, ref quant, ref unZig); - - int dc = (int)tempDest2[0]; - - // Emit the DC delta. - this.EmitHuffRLE((HuffIndex)((2 * (int)index) + 0), 0, dc - prevDC, ref emitBufferBase); - - // Emit the AC components. - var h = (HuffIndex)((2 * (int)index) + 1); - int runLength = 0; - - for (int zig = 1; zig < Block8x8F.Size; zig++) - { - int ac = (int)tempDest2[zig]; - - if (ac == 0) - { - runLength++; - } - else - { - while (runLength > 15) - { - this.EmitHuff(h, 0xf0, ref emitBufferBase); - runLength -= 16; - } - - this.EmitHuffRLE(h, runLength, ac, ref emitBufferBase); - runLength = 0; - } - } - - if (runLength > 0) - { - this.EmitHuff(h, 0x00, ref emitBufferBase); - } - - return dc; - } - /// /// Writes the Define Huffman Table marker and tables. /// @@ -1017,110 +648,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg scanEncoder.WriteStartOfScan(image, this.colorType, this.subsample, cancellationToken); - //ref byte emitBufferBase = ref MemoryMarshal.GetReference(this.emitBuffer); - //if (this.colorType == JpegColorType.Luminance) - //{ - // scanEncoder.EncodeGrayscale(image, cancellationToken); - //} - //else - //{ - // switch (this.subsample) - // { - // case JpegSubsample.Ratio444: - // scanEncoder.Encode444(image, cancellationToken); - // break; - // case JpegSubsample.Ratio420: - // scanEncoder.Encode420(image, cancellationToken); - // break; - // } - //} - - //// Pad the last byte with 1's. - //this.Emit(0x7f, 7, ref emitBufferBase); - } - - /// - /// Encodes the image with subsampling. The Cb and Cr components are each subsampled - /// at a factor of 2 both horizontally and vertically. - /// - /// The pixel format. - /// The pixel accessor providing access to the image pixels. - /// The token to monitor for cancellation. - /// The reference to the emit buffer. - private void Encode420(Image pixels, CancellationToken cancellationToken, ref byte emitBufferBase) - where TPixel : unmanaged, IPixel - { - // TODO: Need a JpegScanEncoder class or struct that encapsulates the scan-encoding implementation. (Similar to JpegScanDecoder.) - Block8x8F b = default; - Span cb = stackalloc Block8x8F[4]; - Span cr = stackalloc Block8x8F[4]; - - Block8x8F temp1 = default; - Block8x8F temp2 = default; - - Block8x8F onStackLuminanceQuantTable = this.luminanceQuantTable; - Block8x8F onStackChrominanceQuantTable = this.chrominanceQuantTable; - - var unzig = ZigZag.CreateUnzigTable(); - - var pixelConverter = YCbCrForwardConverter.Create(); - - // ReSharper disable once InconsistentNaming - int prevDCY = 0, prevDCCb = 0, prevDCCr = 0; - ImageFrame frame = pixels.Frames.RootFrame; - Buffer2D pixelBuffer = frame.PixelBuffer; - RowOctet currentRows = default; - - for (int y = 0; y < pixels.Height; y += 16) - { - cancellationToken.ThrowIfCancellationRequested(); - for (int x = 0; x < pixels.Width; x += 16) - { - for (int i = 0; i < 4; i++) - { - int xOff = (i & 1) * 8; - int yOff = (i & 2) * 4; - - currentRows.Update(pixelBuffer, y + yOff); - pixelConverter.Convert(frame, x + xOff, y + yOff, ref currentRows); - - cb[i] = pixelConverter.Cb; - cr[i] = pixelConverter.Cr; - - prevDCY = this.WriteBlock( - QuantIndex.Luminance, - prevDCY, - ref pixelConverter.Y, - ref temp1, - ref temp2, - ref onStackLuminanceQuantTable, - ref unzig, - ref emitBufferBase); - } - - Block8x8F.Scale16X16To8X8(ref b, cb); - prevDCCb = this.WriteBlock( - QuantIndex.Chrominance, - prevDCCb, - ref b, - ref temp1, - ref temp2, - ref onStackChrominanceQuantTable, - ref unzig, - ref emitBufferBase); - - Block8x8F.Scale16X16To8X8(ref b, cr); - prevDCCr = this.WriteBlock( - QuantIndex.Chrominance, - prevDCCr, - ref b, - ref temp1, - ref temp2, - ref onStackChrominanceQuantTable, - ref unzig, - ref emitBufferBase); - } - } } ///