Browse Source

Reduced intermediate allocations: Tiff

pull/2415/head
Günther Foidl 3 years ago
parent
commit
b099bda98b
  1. 11
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero32FloatTiffColor{TPixel}.cs
  2. 23
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/RgbFloat323232TiffColor{TPixel}.cs
  3. 30
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/RgbaFloat32323232TiffColor{TPixel}.cs
  4. 9
      src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero32FloatTiffColor{TPixel}.cs
  5. 38
      src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs
  6. 44
      src/ImageSharp/Formats/Tiff/Writers/TiffStreamWriter.cs
  7. 4
      tests/ImageSharp.Tests/Formats/Tiff/BigTiffMetadataTests.cs
  8. 4
      tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderHeaderTests.cs
  9. 15
      tests/ImageSharp.Tests/Formats/Tiff/Utils/TiffWriterTests.cs

11
src/ImageSharp/Formats/Tiff/PhotometricInterpretation/BlackIsZero32FloatTiffColor{TPixel}.cs

@ -24,9 +24,9 @@ internal class BlackIsZero32FloatTiffColor<TPixel> : TiffBaseColorDecoder<TPixel
/// <inheritdoc/> /// <inheritdoc/>
public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, int left, int top, int width, int height) public override void Decode(ReadOnlySpan<byte> data, Buffer2D<TPixel> pixels, int left, int top, int width, int height)
{ {
var color = default(TPixel); TPixel color = default;
color.FromScaledVector4(Vector4.Zero); color.FromScaledVector4(Vector4.Zero);
byte[] buffer = new byte[4]; Span<byte> buffer = stackalloc byte[4];
int offset = 0; int offset = 0;
for (int y = top; y < top + height; y++) for (int y = top; y < top + height; y++)
@ -37,8 +37,8 @@ internal class BlackIsZero32FloatTiffColor<TPixel> : TiffBaseColorDecoder<TPixel
for (int x = 0; x < pixelRow.Length; x++) for (int x = 0; x < pixelRow.Length; x++)
{ {
data.Slice(offset, 4).CopyTo(buffer); data.Slice(offset, 4).CopyTo(buffer);
Array.Reverse(buffer); buffer.Reverse();
float intensity = BitConverter.ToSingle(buffer, 0); float intensity = BitConverter.ToSingle(buffer);
offset += 4; offset += 4;
var colorVector = new Vector4(intensity, intensity, intensity, 1.0f); var colorVector = new Vector4(intensity, intensity, intensity, 1.0f);
@ -50,8 +50,7 @@ internal class BlackIsZero32FloatTiffColor<TPixel> : TiffBaseColorDecoder<TPixel
{ {
for (int x = 0; x < pixelRow.Length; x++) for (int x = 0; x < pixelRow.Length; x++)
{ {
data.Slice(offset, 4).CopyTo(buffer); float intensity = BitConverter.ToSingle(data.Slice(offset, 4));
float intensity = BitConverter.ToSingle(buffer, 0);
offset += 4; offset += 4;
var colorVector = new Vector4(intensity, intensity, intensity, 1.0f); var colorVector = new Vector4(intensity, intensity, intensity, 1.0f);

23
src/ImageSharp/Formats/Tiff/PhotometricInterpretation/RgbFloat323232TiffColor{TPixel}.cs

@ -27,7 +27,7 @@ internal class RgbFloat323232TiffColor<TPixel> : TiffBaseColorDecoder<TPixel>
var color = default(TPixel); var color = default(TPixel);
color.FromScaledVector4(Vector4.Zero); color.FromScaledVector4(Vector4.Zero);
int offset = 0; int offset = 0;
byte[] buffer = new byte[4]; Span<byte> buffer = stackalloc byte[4];
for (int y = top; y < top + height; y++) for (int y = top; y < top + height; y++)
{ {
@ -38,18 +38,18 @@ internal class RgbFloat323232TiffColor<TPixel> : TiffBaseColorDecoder<TPixel>
for (int x = 0; x < pixelRow.Length; x++) for (int x = 0; x < pixelRow.Length; x++)
{ {
data.Slice(offset, 4).CopyTo(buffer); data.Slice(offset, 4).CopyTo(buffer);
Array.Reverse(buffer); buffer.Reverse();
float r = BitConverter.ToSingle(buffer, 0); float r = BitConverter.ToSingle(buffer);
offset += 4; offset += 4;
data.Slice(offset, 4).CopyTo(buffer); data.Slice(offset, 4).CopyTo(buffer);
Array.Reverse(buffer); buffer.Reverse();
float g = BitConverter.ToSingle(buffer, 0); float g = BitConverter.ToSingle(buffer);
offset += 4; offset += 4;
data.Slice(offset, 4).CopyTo(buffer); data.Slice(offset, 4).CopyTo(buffer);
Array.Reverse(buffer); buffer.Reverse();
float b = BitConverter.ToSingle(buffer, 0); float b = BitConverter.ToSingle(buffer);
offset += 4; offset += 4;
var colorVector = new Vector4(r, g, b, 1.0f); var colorVector = new Vector4(r, g, b, 1.0f);
@ -61,16 +61,13 @@ internal class RgbFloat323232TiffColor<TPixel> : TiffBaseColorDecoder<TPixel>
{ {
for (int x = 0; x < pixelRow.Length; x++) for (int x = 0; x < pixelRow.Length; x++)
{ {
data.Slice(offset, 4).CopyTo(buffer); float r = BitConverter.ToSingle(data.Slice(offset, 4));
float r = BitConverter.ToSingle(buffer, 0);
offset += 4; offset += 4;
data.Slice(offset, 4).CopyTo(buffer); float g = BitConverter.ToSingle(data.Slice(offset, 4));
float g = BitConverter.ToSingle(buffer, 0);
offset += 4; offset += 4;
data.Slice(offset, 4).CopyTo(buffer); float b = BitConverter.ToSingle(data.Slice(offset, 4));
float b = BitConverter.ToSingle(buffer, 0);
offset += 4; offset += 4;
var colorVector = new Vector4(r, g, b, 1.0f); var colorVector = new Vector4(r, g, b, 1.0f);

30
src/ImageSharp/Formats/Tiff/PhotometricInterpretation/RgbaFloat32323232TiffColor{TPixel}.cs

@ -27,7 +27,7 @@ internal class RgbaFloat32323232TiffColor<TPixel> : TiffBaseColorDecoder<TPixel>
var color = default(TPixel); var color = default(TPixel);
color.FromScaledVector4(Vector4.Zero); color.FromScaledVector4(Vector4.Zero);
int offset = 0; int offset = 0;
byte[] buffer = new byte[4]; Span<byte> buffer = stackalloc byte[4];
for (int y = top; y < top + height; y++) for (int y = top; y < top + height; y++)
{ {
@ -38,23 +38,23 @@ internal class RgbaFloat32323232TiffColor<TPixel> : TiffBaseColorDecoder<TPixel>
for (int x = 0; x < pixelRow.Length; x++) for (int x = 0; x < pixelRow.Length; x++)
{ {
data.Slice(offset, 4).CopyTo(buffer); data.Slice(offset, 4).CopyTo(buffer);
Array.Reverse(buffer); buffer.Reverse();
float r = BitConverter.ToSingle(buffer, 0); float r = BitConverter.ToSingle(buffer);
offset += 4; offset += 4;
data.Slice(offset, 4).CopyTo(buffer); data.Slice(offset, 4).CopyTo(buffer);
Array.Reverse(buffer); buffer.Reverse();
float g = BitConverter.ToSingle(buffer, 0); float g = BitConverter.ToSingle(buffer);
offset += 4; offset += 4;
data.Slice(offset, 4).CopyTo(buffer); data.Slice(offset, 4).CopyTo(buffer);
Array.Reverse(buffer); buffer.Reverse();
float b = BitConverter.ToSingle(buffer, 0); float b = BitConverter.ToSingle(buffer);
offset += 4; offset += 4;
data.Slice(offset, 4).CopyTo(buffer); data.Slice(offset, 4).CopyTo(buffer);
Array.Reverse(buffer); buffer.Reverse();
float a = BitConverter.ToSingle(buffer, 0); float a = BitConverter.ToSingle(buffer);
offset += 4; offset += 4;
var colorVector = new Vector4(r, g, b, a); var colorVector = new Vector4(r, g, b, a);
@ -66,20 +66,16 @@ internal class RgbaFloat32323232TiffColor<TPixel> : TiffBaseColorDecoder<TPixel>
{ {
for (int x = 0; x < pixelRow.Length; x++) for (int x = 0; x < pixelRow.Length; x++)
{ {
data.Slice(offset, 4).CopyTo(buffer); float r = BitConverter.ToSingle(data.Slice(offset, 4));
float r = BitConverter.ToSingle(buffer, 0);
offset += 4; offset += 4;
data.Slice(offset, 4).CopyTo(buffer); float g = BitConverter.ToSingle(data.Slice(offset, 4));
float g = BitConverter.ToSingle(buffer, 0);
offset += 4; offset += 4;
data.Slice(offset, 4).CopyTo(buffer); float b = BitConverter.ToSingle(data.Slice(offset, 4));
float b = BitConverter.ToSingle(buffer, 0);
offset += 4; offset += 4;
data.Slice(offset, 4).CopyTo(buffer); float a = BitConverter.ToSingle(data.Slice(offset, 4));
float a = BitConverter.ToSingle(buffer, 0);
offset += 4; offset += 4;
var colorVector = new Vector4(r, g, b, a); var colorVector = new Vector4(r, g, b, a);

9
src/ImageSharp/Formats/Tiff/PhotometricInterpretation/WhiteIsZero32FloatTiffColor{TPixel}.cs

@ -26,7 +26,7 @@ internal class WhiteIsZero32FloatTiffColor<TPixel> : TiffBaseColorDecoder<TPixel
{ {
var color = default(TPixel); var color = default(TPixel);
color.FromScaledVector4(Vector4.Zero); color.FromScaledVector4(Vector4.Zero);
byte[] buffer = new byte[4]; Span<byte> buffer = stackalloc byte[4];
int offset = 0; int offset = 0;
for (int y = top; y < top + height; y++) for (int y = top; y < top + height; y++)
@ -37,8 +37,8 @@ internal class WhiteIsZero32FloatTiffColor<TPixel> : TiffBaseColorDecoder<TPixel
for (int x = 0; x < pixelRow.Length; x++) for (int x = 0; x < pixelRow.Length; x++)
{ {
data.Slice(offset, 4).CopyTo(buffer); data.Slice(offset, 4).CopyTo(buffer);
Array.Reverse(buffer); buffer.Reverse();
float intensity = 1.0f - BitConverter.ToSingle(buffer, 0); float intensity = 1.0f - BitConverter.ToSingle(buffer);
offset += 4; offset += 4;
var colorVector = new Vector4(intensity, intensity, intensity, 1.0f); var colorVector = new Vector4(intensity, intensity, intensity, 1.0f);
@ -50,8 +50,7 @@ internal class WhiteIsZero32FloatTiffColor<TPixel> : TiffBaseColorDecoder<TPixel
{ {
for (int x = 0; x < pixelRow.Length; x++) for (int x = 0; x < pixelRow.Length; x++)
{ {
data.Slice(offset, 4).CopyTo(buffer); float intensity = 1.0f - BitConverter.ToSingle(data.Slice(offset, 4));
float intensity = 1.0f - BitConverter.ToSingle(buffer, 0);
offset += 4; offset += 4;
var colorVector = new Vector4(intensity, intensity, intensity, 1.0f); var colorVector = new Vector4(intensity, intensity, intensity, 1.0f);

38
src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs

@ -29,11 +29,6 @@ internal sealed class TiffEncoderCore : IImageEncoderInternals
/// </summary> /// </summary>
private readonly MemoryAllocator memoryAllocator; private readonly MemoryAllocator memoryAllocator;
/// <summary>
/// A scratch buffer to reduce allocations.
/// </summary>
private readonly byte[] buffer = new byte[4];
/// <summary> /// <summary>
/// The global configuration. /// The global configuration.
/// </summary> /// </summary>
@ -157,7 +152,9 @@ internal sealed class TiffEncoderCore : IImageEncoderInternals
this.SanitizeAndSetEncoderOptions(bitsPerPixel, image.PixelType.BitsPerPixel, photometricInterpretation, compression, predictor); this.SanitizeAndSetEncoderOptions(bitsPerPixel, image.PixelType.BitsPerPixel, photometricInterpretation, compression, predictor);
using TiffStreamWriter writer = new(stream); using TiffStreamWriter writer = new(stream);
long ifdMarker = WriteHeader(writer); Span<byte> buffer = stackalloc byte[4];
long ifdMarker = WriteHeader(writer, buffer);
Image<TPixel> metadataImage = image; Image<TPixel> metadataImage = image;
foreach (ImageFrame<TPixel> frame in image.Frames) foreach (ImageFrame<TPixel> frame in image.Frames)
@ -171,7 +168,7 @@ internal sealed class TiffEncoderCore : IImageEncoderInternals
long currentOffset = writer.BaseStream.Position; long currentOffset = writer.BaseStream.Position;
foreach ((long, uint) marker in this.frameMarkers) foreach ((long, uint) marker in this.frameMarkers)
{ {
writer.WriteMarkerFast(marker.Item1, marker.Item2); writer.WriteMarkerFast(marker.Item1, marker.Item2, buffer);
} }
writer.BaseStream.Seek(currentOffset, SeekOrigin.Begin); writer.BaseStream.Seek(currentOffset, SeekOrigin.Begin);
@ -181,14 +178,15 @@ internal sealed class TiffEncoderCore : IImageEncoderInternals
/// Writes the TIFF file header. /// Writes the TIFF file header.
/// </summary> /// </summary>
/// <param name="writer">The <see cref="TiffStreamWriter" /> to write data to.</param> /// <param name="writer">The <see cref="TiffStreamWriter" /> to write data to.</param>
/// <param name="buffer">Scratch buffer with minimum size of 2.</param>
/// <returns> /// <returns>
/// The marker to write the first IFD offset. /// The marker to write the first IFD offset.
/// </returns> /// </returns>
public static long WriteHeader(TiffStreamWriter writer) public static long WriteHeader(TiffStreamWriter writer, Span<byte> buffer)
{ {
writer.Write(ByteOrderMarker); writer.Write(ByteOrderMarker, buffer);
writer.Write(TiffConstants.HeaderMagicNumber); writer.Write(TiffConstants.HeaderMagicNumber, buffer);
return writer.PlaceMarker(); return writer.PlaceMarker(buffer);
} }
/// <summary> /// <summary>
@ -307,20 +305,22 @@ internal sealed class TiffEncoderCore : IImageEncoderInternals
entries.Sort((a, b) => (ushort)a.Tag - (ushort)b.Tag); entries.Sort((a, b) => (ushort)a.Tag - (ushort)b.Tag);
writer.Write((ushort)entries.Count); Span<byte> buffer = stackalloc byte[4];
writer.Write((ushort)entries.Count, buffer);
foreach (IExifValue entry in entries) foreach (IExifValue entry in entries)
{ {
writer.Write((ushort)entry.Tag); writer.Write((ushort)entry.Tag, buffer);
writer.Write((ushort)entry.DataType); writer.Write((ushort)entry.DataType, buffer);
writer.Write(ExifWriter.GetNumberOfComponents(entry)); writer.Write(ExifWriter.GetNumberOfComponents(entry), buffer);
uint length = ExifWriter.GetLength(entry); uint length = ExifWriter.GetLength(entry);
if (length <= 4) if (length <= 4)
{ {
int sz = ExifWriter.WriteValue(entry, this.buffer, 0); int sz = ExifWriter.WriteValue(entry, buffer, 0);
DebugGuard.IsTrue(sz == length, "Incorrect number of bytes written"); DebugGuard.IsTrue(sz == length, "Incorrect number of bytes written");
writer.WritePadded(this.buffer.AsSpan(0, sz)); writer.WritePadded(buffer.Slice(0, sz));
} }
else else
{ {
@ -328,12 +328,12 @@ internal sealed class TiffEncoderCore : IImageEncoderInternals
int sz = ExifWriter.WriteValue(entry, raw, 0); int sz = ExifWriter.WriteValue(entry, raw, 0);
DebugGuard.IsTrue(sz == raw.Length, "Incorrect number of bytes written"); DebugGuard.IsTrue(sz == raw.Length, "Incorrect number of bytes written");
largeDataBlocks.Add(raw); largeDataBlocks.Add(raw);
writer.Write(dataOffset); writer.Write(dataOffset, buffer);
dataOffset += (uint)(raw.Length + (raw.Length % 2)); dataOffset += (uint)(raw.Length + (raw.Length % 2));
} }
} }
long nextIfdMarker = writer.PlaceMarker(); long nextIfdMarker = writer.PlaceMarker(buffer);
foreach (byte[] dataBlock in largeDataBlocks) foreach (byte[] dataBlock in largeDataBlocks)
{ {

44
src/ImageSharp/Formats/Tiff/Writers/TiffStreamWriter.cs

@ -10,13 +10,6 @@ namespace SixLabors.ImageSharp.Formats.Tiff.Writers;
/// </summary> /// </summary>
internal sealed class TiffStreamWriter : IDisposable internal sealed class TiffStreamWriter : IDisposable
{ {
private static readonly byte[] PaddingBytes = new byte[4];
/// <summary>
/// A scratch buffer to reduce allocations.
/// </summary>
private readonly byte[] buffer = new byte[4];
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="TiffStreamWriter"/> class. /// Initializes a new instance of the <see cref="TiffStreamWriter"/> class.
/// </summary> /// </summary>
@ -41,11 +34,12 @@ internal sealed class TiffStreamWriter : IDisposable
/// <summary> /// <summary>
/// Writes an empty four bytes to the stream, returning the offset to be written later. /// Writes an empty four bytes to the stream, returning the offset to be written later.
/// </summary> /// </summary>
/// <param name="buffer">Scratch buffer with minimum size of 4.</param>
/// <returns>The offset to be written later.</returns> /// <returns>The offset to be written later.</returns>
public long PlaceMarker() public long PlaceMarker(Span<byte> buffer)
{ {
long offset = this.BaseStream.Position; long offset = this.BaseStream.Position;
this.Write(0u); this.Write(0u, buffer);
return offset; return offset;
} }
@ -71,36 +65,38 @@ internal sealed class TiffStreamWriter : IDisposable
/// Writes a two-byte unsigned integer to the current stream. /// Writes a two-byte unsigned integer to the current stream.
/// </summary> /// </summary>
/// <param name="value">The two-byte unsigned integer to write.</param> /// <param name="value">The two-byte unsigned integer to write.</param>
public void Write(ushort value) /// <param name="buffer">Scratch buffer with minimum size of 2.</param>
public void Write(ushort value, Span<byte> buffer)
{ {
if (IsLittleEndian) if (IsLittleEndian)
{ {
BinaryPrimitives.WriteUInt16LittleEndian(this.buffer, value); BinaryPrimitives.WriteUInt16LittleEndian(buffer, value);
} }
else else
{ {
BinaryPrimitives.WriteUInt16BigEndian(this.buffer, value); BinaryPrimitives.WriteUInt16BigEndian(buffer, value);
} }
this.BaseStream.Write(this.buffer.AsSpan(0, 2)); this.BaseStream.Write(buffer.Slice(0, 2));
} }
/// <summary> /// <summary>
/// Writes a four-byte unsigned integer to the current stream. /// Writes a four-byte unsigned integer to the current stream.
/// </summary> /// </summary>
/// <param name="value">The four-byte unsigned integer to write.</param> /// <param name="value">The four-byte unsigned integer to write.</param>
public void Write(uint value) /// <param name="buffer">Scratch buffer with minimum size of 4.</param>
public void Write(uint value, Span<byte> buffer)
{ {
if (IsLittleEndian) if (IsLittleEndian)
{ {
BinaryPrimitives.WriteUInt32LittleEndian(this.buffer, value); BinaryPrimitives.WriteUInt32LittleEndian(buffer, value);
} }
else else
{ {
BinaryPrimitives.WriteUInt32BigEndian(this.buffer, value); BinaryPrimitives.WriteUInt32BigEndian(buffer, value);
} }
this.BaseStream.Write(this.buffer.AsSpan(0, 4)); this.BaseStream.Write(buffer.Slice(0, 4));
} }
/// <summary> /// <summary>
@ -113,7 +109,10 @@ internal sealed class TiffStreamWriter : IDisposable
if (value.Length % 4 != 0) if (value.Length % 4 != 0)
{ {
this.BaseStream.Write(PaddingBytes, 0, 4 - (value.Length % 4)); // No allocation occurs, refers directly to assembly's data segment.
ReadOnlySpan<byte> paddingBytes = new byte[4] { 0x00, 0x00, 0x00, 0x00 };
paddingBytes = paddingBytes[..(4 - (value.Length % 4))];
this.BaseStream.Write(paddingBytes);
} }
} }
@ -122,18 +121,19 @@ internal sealed class TiffStreamWriter : IDisposable
/// </summary> /// </summary>
/// <param name="offset">The offset returned when placing the marker</param> /// <param name="offset">The offset returned when placing the marker</param>
/// <param name="value">The four-byte unsigned integer to write.</param> /// <param name="value">The four-byte unsigned integer to write.</param>
public void WriteMarker(long offset, uint value) /// <param name="buffer">Scratch buffer.</param>
public void WriteMarker(long offset, uint value, Span<byte> buffer)
{ {
long back = this.BaseStream.Position; long back = this.BaseStream.Position;
this.BaseStream.Seek(offset, SeekOrigin.Begin); this.BaseStream.Seek(offset, SeekOrigin.Begin);
this.Write(value); this.Write(value, buffer);
this.BaseStream.Seek(back, SeekOrigin.Begin); this.BaseStream.Seek(back, SeekOrigin.Begin);
} }
public void WriteMarkerFast(long offset, uint value) public void WriteMarkerFast(long offset, uint value, Span<byte> buffer)
{ {
this.BaseStream.Seek(offset, SeekOrigin.Begin); this.BaseStream.Seek(offset, SeekOrigin.Begin);
this.Write(value); this.Write(value, buffer);
} }
/// <summary> /// <summary>

4
tests/ImageSharp.Tests/Formats/Tiff/BigTiffMetadataTests.cs

@ -211,8 +211,8 @@ public class BigTiffMetadataTests
foreach (IExifValue entry in values) foreach (IExifValue entry in values)
{ {
writer.Write((ushort)entry.Tag); writer.Write((ushort)entry.Tag, buffer);
writer.Write((ushort)entry.DataType); writer.Write((ushort)entry.DataType, buffer);
WriteLong8(writer, buffer, ExifWriter.GetNumberOfComponents(entry)); WriteLong8(writer, buffer, ExifWriter.GetNumberOfComponents(entry));
uint length = ExifWriter.GetLength(entry); uint length = ExifWriter.GetLength(entry);

4
tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderHeaderTests.cs

@ -19,7 +19,7 @@ public class TiffEncoderHeaderTests
using (TiffStreamWriter writer = new(stream)) using (TiffStreamWriter writer = new(stream))
{ {
long firstIfdMarker = TiffEncoderCore.WriteHeader(writer); long firstIfdMarker = TiffEncoderCore.WriteHeader(writer, stackalloc byte[4]);
} }
Assert.Equal(new byte[] { 0x49, 0x49, 42, 0, 0x00, 0x00, 0x00, 0x00 }, stream.ToArray()); Assert.Equal(new byte[] { 0x49, 0x49, 42, 0, 0x00, 0x00, 0x00, 0x00 }, stream.ToArray());
@ -32,7 +32,7 @@ public class TiffEncoderHeaderTests
TiffEncoderCore encoder = new(Encoder, Configuration.Default.MemoryAllocator); TiffEncoderCore encoder = new(Encoder, Configuration.Default.MemoryAllocator);
using TiffStreamWriter writer = new(stream); using TiffStreamWriter writer = new(stream);
long firstIfdMarker = TiffEncoderCore.WriteHeader(writer); long firstIfdMarker = TiffEncoderCore.WriteHeader(writer, stackalloc byte[4]);
Assert.Equal(4, firstIfdMarker); Assert.Equal(4, firstIfdMarker);
} }
} }

15
tests/ImageSharp.Tests/Formats/Tiff/Utils/TiffWriterTests.cs

@ -53,7 +53,7 @@ public class TiffWriterTests
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
using var writer = new TiffStreamWriter(stream); using var writer = new TiffStreamWriter(stream);
writer.Write(1234); writer.Write(1234, stackalloc byte[2]);
Assert.Equal(new byte[] { 0xD2, 0x04 }, stream.ToArray()); Assert.Equal(new byte[] { 0xD2, 0x04 }, stream.ToArray());
} }
@ -63,7 +63,7 @@ public class TiffWriterTests
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
using var writer = new TiffStreamWriter(stream); using var writer = new TiffStreamWriter(stream);
writer.Write(12345678U); writer.Write(12345678U, stackalloc byte[4]);
Assert.Equal(new byte[] { 0x4E, 0x61, 0xBC, 0x00 }, stream.ToArray()); Assert.Equal(new byte[] { 0x4E, 0x61, 0xBC, 0x00 }, stream.ToArray());
} }
@ -89,16 +89,17 @@ public class TiffWriterTests
public void WriteMarker_WritesToPlacedPosition() public void WriteMarker_WritesToPlacedPosition()
{ {
using var stream = new MemoryStream(); using var stream = new MemoryStream();
Span<byte> buffer = stackalloc byte[4];
using (var writer = new TiffStreamWriter(stream)) using (var writer = new TiffStreamWriter(stream))
{ {
writer.Write(0x11111111); writer.Write(0x11111111, buffer);
long marker = writer.PlaceMarker(); long marker = writer.PlaceMarker(buffer);
writer.Write(0x33333333); writer.Write(0x33333333, buffer);
writer.WriteMarker(marker, 0x12345678); writer.WriteMarker(marker, 0x12345678, buffer);
writer.Write(0x44444444); writer.Write(0x44444444, buffer);
} }
Assert.Equal( Assert.Equal(

Loading…
Cancel
Save