Browse Source

Moved stuff bytes injection to outer method

pull/1761/head
Dmitry Pentin 5 years ago
parent
commit
e83cb95cb3
  1. 46
      src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs

46
src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs

@ -35,6 +35,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder
/// </summary> /// </summary>
private readonly byte[] emitBuffer = new byte[EmitBufferSizeInBytes]; private readonly byte[] emitBuffer = new byte[EmitBufferSizeInBytes];
private readonly byte[] streamWriteBuffer = new byte[EmitBufferSizeInBytes * 2];
private const int BytesPerCodingUnit = 256 * 3;
/// <summary> /// <summary>
/// Number of filled bytes in <see cref="emitBuffer"/> buffer /// Number of filled bytes in <see cref="emitBuffer"/> buffer
/// </summary> /// </summary>
@ -116,6 +120,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder
ref pixelConverter.Cr, ref pixelConverter.Cr,
ref chrominanceQuantTable, ref chrominanceQuantTable,
ref unzig); ref unzig);
if (this.emitLen + BytesPerCodingUnit > EmitBufferSizeInBytes)
{
this.WriteToStream();
}
} }
} }
@ -326,28 +335,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder
byte b = (byte)(bits >> 24); byte b = (byte)(bits >> 24);
this.emitBuffer[this.emitLen++] = b; this.emitBuffer[this.emitLen++] = b;
// Adding stuff byte
// This is because by JPEG standard scan data can contain JPEG markers (indicated by the 0xFF byte, followed by a non-zero byte)
// Considering this every 0xFF byte must be followed by 0x00 padding byte to signal that this is not a marker
if (b == byte.MaxValue)
{
this.emitBuffer[this.emitLen++] = byte.MinValue;
}
bits <<= 8; bits <<= 8;
count -= 8; count -= 8;
} }
// 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.target.Write(this.emitBuffer, 0, this.emitLen);
this.emitLen = 0;
}
} }
this.accumulatedBits = bits; this.accumulatedBits = bits;
@ -520,5 +510,23 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder
return index; return index;
} }
} }
[MethodImpl(InliningOptions.ShortMethod)]
private void WriteToStream()
{
int writeIdx = 0;
for (int i = 0; i < this.emitLen; i++)
{
byte value = this.emitBuffer[i];
this.streamWriteBuffer[writeIdx++] = value;
if (value == 0xff)
{
this.streamWriteBuffer[writeIdx++] = 0x00;
}
}
this.target.Write(this.streamWriteBuffer, 0, writeIdx);
this.emitLen = 0;
}
} }
} }

Loading…
Cancel
Save