diff --git a/src/ImageSharp/Formats/Jpg/JpegEncoderCore.cs b/src/ImageSharp/Formats/Jpg/JpegEncoderCore.cs index 9e502cfcb..371e71522 100644 --- a/src/ImageSharp/Formats/Jpg/JpegEncoderCore.cs +++ b/src/ImageSharp/Formats/Jpg/JpegEncoderCore.cs @@ -145,32 +145,35 @@ namespace ImageSharp.Formats }) }; - // w is the writer to write to. err is the first error encountered during - // writing. All attempted writes after the first error become no-ops. - private Stream outputStream; - /// /// A scratch buffer to reduce allocations. /// private readonly byte[] buffer = new byte[16]; /// - /// The accumulated bits to write to the stream. + /// The scaled quantization tables, in zig-zag order. /// - private uint bits; + private readonly byte[][] quant = new byte[NQuantIndex][]; // [Block.blockSize]; + + /// + /// The compiled representations of theHuffmanSpec. + /// + private readonly HuffmanLut[] theHuffmanLut = new HuffmanLut[4]; /// /// The accumulated bits to write to the stream. /// - private uint nBits; + private uint accumulatedBits; /// - /// The scaled quantization tables, in zig-zag order. + /// The accumulated bit count. /// - private readonly byte[][] quant = new byte[NQuantIndex][]; // [Block.blockSize]; + private uint bitCount; - // The compiled representations of theHuffmanSpec. - private readonly HuffmanLut[] theHuffmanLUT = new HuffmanLut[4]; + /// + /// The output stream. All attempted writes after the first error become no-ops. + /// + private Stream outputStream; /// /// The subsampling method to use. @@ -189,17 +192,17 @@ namespace ImageSharp.Formats } /// - /// Emits the least significant nBits bits of bits to the bit-stream. + /// Emits the least significant count of bits of bits to the bit-stream. /// The precondition is bits < 1<<nBits && nBits <= 16. /// - /// - /// - private void Emit(uint bits, uint nBits) + /// The packed bits. + /// The number of bits + private void Emit(uint bits, uint count) { - nBits += this.nBits; - bits <<= (int)(32 - nBits); - bits |= this.bits; - while (nBits >= 8) + count += this.bitCount; + bits <<= (int)(32 - count); + bits |= this.accumulatedBits; + while (count >= 8) { byte b = (byte)(bits >> 24); this.WriteByte(b); @@ -209,11 +212,11 @@ namespace ImageSharp.Formats } bits <<= 8; - nBits -= 8; + count -= 8; } - this.bits = bits; - this.nBits = nBits; + this.accumulatedBits = bits; + this.bitCount = count; } /// @@ -223,7 +226,7 @@ namespace ImageSharp.Formats /// The value to encode. private void EmitHuff(HuffIndex index, int value) { - uint x = this.theHuffmanLUT[(int)index].Values[value]; + uint x = this.theHuffmanLut[(int)index].Values[value]; this.Emit(x & ((1 << 24) - 1), x >> 24); } @@ -268,7 +271,7 @@ namespace ImageSharp.Formats /// The block to write. /// The quantization table index. /// The previous DC value. - /// + /// The private int WriteBlock(Block block, QuantIndex index, int prevDC) { FDCT.Transform(block); @@ -398,8 +401,15 @@ namespace ImageSharp.Formats 0x00 // Ah + Ah (Successive approximation bit position high + low) }; - // Encode writes the Image m to w in JPEG 4:2:0 baseline format with the given - // options. Default parameters are used if a nil *Options is passed. + /// + /// Encode writes the image to the jpeg baseline format with the given options. + /// + /// The pixel format. + /// The packed format. uint, long, float. + /// The image to write from. + /// The stream to write to. + /// The quality. + /// The subsampling mode. public void Encode(Image image, Stream stream, int quality, JpegSubsample sample) where TColor : struct, IPackedPixel where TPacked : struct @@ -419,7 +429,7 @@ namespace ImageSharp.Formats // TODO: This should be static should it not? for (int i = 0; i < this.theHuffmanSpec.Length; i++) { - this.theHuffmanLUT[i] = new HuffmanLut(this.theHuffmanSpec[i]); + this.theHuffmanLut[i] = new HuffmanLut(this.theHuffmanSpec[i]); } for (int i = 0; i < NQuantIndex; i++) @@ -516,7 +526,7 @@ namespace ImageSharp.Formats } /// - /// Writes the application header containing the Jfif identifier plus extra data. + /// Writes the application header containing the JFIF identifier plus extra data. /// /// The resolution of the image in the x- direction. /// The resolution of the image in the y- direction. @@ -564,12 +574,7 @@ namespace ImageSharp.Formats private void WriteProfile(ExifProfile exifProfile) { - if (exifProfile == null) - { - return; - } - - byte[] data = exifProfile.ToByteArray(); + byte[] data = exifProfile?.ToByteArray(); if (data == null || data.Length == 0) { return; @@ -774,7 +779,7 @@ namespace ImageSharp.Formats int xOff = (i & 1) * 8; int yOff = (i & 2) * 4; - this.ToYCbCr(pixels, x + xOff, y + yOff, b, cb[i], cr[i]); + this.ToYCbCr(pixels, x + xOff, y + yOff, b, cb[i], cr[i]); prevDCY = this.WriteBlock(b, QuantIndex.Luminance, prevDCY); } @@ -831,6 +836,33 @@ namespace ImageSharp.Formats Chrominance = 1, } + /// + /// The Huffman encoding specifications. + /// + private struct HuffmanSpec + { + /// + /// Gets count[i] - The number of codes of length i bits. + /// + public readonly byte[] Count; + + /// + /// Gets value[i] - The decoded value of the codeword at the given index. + /// + public readonly byte[] Values; + + /// + /// Initializes a new instance of the struct. + /// + /// The number of codes. + /// The decoded values. + public HuffmanSpec(byte[] count, byte[] values) + { + this.Count = count; + this.Values = values; + } + } + /// /// A compiled look-up table representation of a huffmanSpec. /// Each value maps to a uint32 of which the 8 most significant bits hold the @@ -879,32 +911,5 @@ namespace ImageSharp.Formats } } } - - /// - /// The Huffman encoding specifications. - /// - private struct HuffmanSpec - { - /// - /// Initializes a new instance of the struct. - /// - /// The number of codes. - /// The decoded values. - public HuffmanSpec(byte[] count, byte[] values) - { - this.Count = count; - this.Values = values; - } - - /// - /// Gets count[i] - The number of codes of length i bits. - /// - public readonly byte[] Count; - - /// - /// Gets value[i] - The decoded value of the i'th codeword. - /// - public readonly byte[] Values; - } } }