diff --git a/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrEncoder{TPixel}.cs b/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrEncoder{TPixel}.cs index a8411e218b..7412b4d91a 100644 --- a/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrEncoder{TPixel}.cs +++ b/src/ImageSharp/Formats/Jpeg/Components/Encoder/YCbCrEncoder{TPixel}.cs @@ -14,10 +14,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder { internal class YCbCrEncoder { + private const int EmitBufferSizeInBytes = 1024; + /// /// A buffer for reducing the number of stream writes when emitting Huffman tables. 64 seems to be enough. /// - private byte[] emitBuffer = new byte[64]; + private byte[] emitBuffer = new byte[EmitBufferSizeInBytes]; /// /// The accumulated bits to write to the stream. @@ -353,6 +355,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder // Pad the last byte with 1's. this.Emit(0x7f, 7); + this.outputStream.Write(this.emitBuffer, 0, this.emitLen); } /// @@ -420,8 +423,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder return dc; } + private int emitLen = 0; + /// - /// Emits the least significant count of bits of bits to the bit-stream. + /// Emits the least significant count of bits to the stream write buffer. /// The precondition is bits /// /// < 1<<nBits && nBits <= 16 @@ -442,23 +447,28 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder if (count >= 8) { // Track length - int len = 0; while (count >= 8) { byte b = (byte)(bits >> 24); - this.emitBuffer[len++] = b; + this.emitBuffer[this.emitLen++] = b; if (b == byte.MaxValue) { - this.emitBuffer[len++] = byte.MinValue; + this.emitBuffer[this.emitLen++] = byte.MinValue; } bits <<= 8; count -= 8; } - if (len > 0) + // This can emit 4 times of: + // 1 byte guaranteed + // 1 extra byte.MinValue byte if previous one was byte.MaxValue + // Thus writing (1 + 1) * 4 = 8 bytes max + // So we must check if emit buffer has extra 8 bytes, if not - call stream.Write + if (this.emitLen > EmitBufferSizeInBytes - 8) { - this.outputStream.Write(this.emitBuffer, 0, len); + this.outputStream.Write(this.emitBuffer, 0, this.emitLen); + this.emitLen = 0; } }