Browse Source

WriteDefineHuffmanTables(...) no longer relies on external buffer for stream writes

pull/1632/head
Dmitry Pentin 5 years ago
parent
commit
86a6d8be97
  1. 44
      src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs

44
src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs

@ -41,12 +41,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
/// </summary> /// </summary>
private readonly byte[] emitBuffer = new byte[64]; private readonly byte[] emitBuffer = new byte[64];
/// <summary>
/// A buffer for reducing the number of stream writes when emitting Huffman tables. Max combined table lengths +
/// identifier.
/// </summary>
private readonly byte[] huffmanBuffer = new byte[179];
/// <summary> /// <summary>
/// Gets or sets the subsampling method to use. /// Gets or sets the subsampling method to use.
/// </summary> /// </summary>
@ -635,30 +629,40 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
markerlen += 1 + 16 + s.Values.Length; markerlen += 1 + 16 + s.Values.Length;
} }
// TODO: this magic constant (array size) should be defined by HuffmanSpec class
// This is a one-time call which can be stackalloc'ed or allocated directly in memory as method local array
// Allocation here would be better for GC so it won't live for entire encoding process
// TODO: if this is allocated on the heap - pin it right here or following copy code will corrupt memory
Span<byte> huffmanBuffer = stackalloc byte[179];
byte* huffmanBufferPtr = (byte*)Unsafe.AsPointer(ref MemoryMarshal.GetReference(huffmanBuffer));
this.WriteMarkerHeader(JpegConstants.Markers.DHT, markerlen); this.WriteMarkerHeader(JpegConstants.Markers.DHT, markerlen);
for (int i = 0; i < specs.Length; i++) for (int i = 0; i < specs.Length; i++)
{ {
ref HuffmanSpec spec = ref specs[i]; ref HuffmanSpec spec = ref specs[i];
int len = 0; int len = 0;
fixed (byte* huffman = this.huffmanBuffer) // header
fixed (byte* count = spec.Count) huffmanBuffer[len++] = headers[i];
fixed (byte* values = spec.Values)
{
huffman[len++] = headers[i];
for (int c = 0; c < spec.Count.Length; c++) // count
{ fixed (byte* countPtr = spec.Count)
huffman[len++] = count[c]; {
} int countLen = spec.Count.Length;
Unsafe.CopyBlockUnaligned(huffmanBufferPtr + len, countPtr, (uint)countLen);
len += countLen;
}
for (int v = 0; v < spec.Values.Length; v++) // values
{ fixed (byte* valuesPtr = spec.Values)
huffman[len++] = values[v]; {
} int valuesLen = spec.Values.Length;
Unsafe.CopyBlockUnaligned(huffmanBufferPtr + len, valuesPtr, (uint)valuesLen);
len += valuesLen;
} }
this.outputStream.Write(this.huffmanBuffer, 0, len); this.outputStream.Write(huffmanBuffer, 0, len);
} }
} }

Loading…
Cancel
Save