Browse Source

First attempt writing uncompressed tiff

pull/1570/head
Brian Popow 6 years ago
parent
commit
838a1f7fd0
  1. 2
      src/ImageSharp/Formats/Tiff/README.md
  2. 3
      src/ImageSharp/Formats/Tiff/TiffEncoder.cs
  3. 166
      src/ImageSharp/Formats/Tiff/TiffEncoderCore.cs
  4. 70
      src/ImageSharp/Formats/Tiff/Utils/TiffWriter.cs
  5. 16
      tests/ImageSharp.Tests/Formats/Tiff/TiffEncoderHeaderTests.cs
  6. 87
      tests/ImageSharp.Tests/Formats/Tiff/Utils/TiffWriterTests.cs

2
src/ImageSharp/Formats/Tiff/README.md

@ -46,7 +46,7 @@
|CcittGroup3Fax | | Y | | |CcittGroup3Fax | | Y | |
|CcittGroup4Fax | | | | |CcittGroup4Fax | | | |
|Lzw | | Y | Based on ImageSharp GIF LZW implementation - this code could be modified to be (i) shared, or (ii) optimised for each case | |Lzw | | Y | Based on ImageSharp GIF LZW implementation - this code could be modified to be (i) shared, or (ii) optimised for each case |
|Old Jpeg | | | | |Old Jpeg | | | We should not even try to support this |
|Jpeg (Technote 2) | | | | |Jpeg (Technote 2) | | | |
|Deflate (Technote 2) | | Y | | |Deflate (Technote 2) | | Y | |
|Old Deflate (Technote 2) | | Y | | |Old Deflate (Technote 2) | | Y | |

3
src/ImageSharp/Formats/Tiff/TiffEncoder.cs

@ -4,6 +4,7 @@
using System.IO; using System.IO;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Tiff namespace SixLabors.ImageSharp.Formats.Tiff
@ -17,7 +18,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff
public void Encode<TPixel>(Image<TPixel> image, Stream stream) public void Encode<TPixel>(Image<TPixel> image, Stream stream)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
var encode = new TiffEncoderCore(this); var encode = new TiffEncoderCore(this, image.GetMemoryAllocator());
encode.Encode(image, stream); encode.Encode(image, stream);
} }

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

@ -4,7 +4,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using SixLabors.ImageSharp.Formats.Tiff; using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.Metadata.Profiles.Exif;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
@ -15,12 +16,29 @@ namespace SixLabors.ImageSharp.Formats.Tiff
/// </summary> /// </summary>
internal sealed class TiffEncoderCore internal sealed class TiffEncoderCore
{ {
/// <summary>
/// The amount to pad each row by in bytes.
/// </summary>
private int padding;
/// <summary>
/// Used for allocating memory during processing operations.
/// </summary>
private readonly MemoryAllocator memoryAllocator;
/// <summary>
/// The global configuration.
/// </summary>
private Configuration configuration;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="TiffEncoderCore"/> class. /// Initializes a new instance of the <see cref="TiffEncoderCore"/> class.
/// </summary> /// </summary>
/// <param name="options">The options for the encoder.</param> /// <param name="options">The options for the encoder.</param>
public TiffEncoderCore(ITiffEncoderOptions options) /// <param name="memoryAllocator">The memory allocator.</param>
public TiffEncoderCore(ITiffEncoderOptions options, MemoryAllocator memoryAllocator)
{ {
this.memoryAllocator = memoryAllocator;
options = options ?? new TiffEncoder(); options = options ?? new TiffEncoder();
} }
@ -46,10 +64,18 @@ namespace SixLabors.ImageSharp.Formats.Tiff
Guard.NotNull(image, nameof(image)); Guard.NotNull(image, nameof(image));
Guard.NotNull(stream, nameof(stream)); Guard.NotNull(stream, nameof(stream));
using (var writer = new TiffWriter(stream)) this.configuration = image.GetConfiguration();
// TODO: bits per pixel hardcoded to 24 for the start.
short bpp = 24;
int bytesPerLine = 4 * (((image.Width * bpp) + 31) / 32);
this.padding = bytesPerLine - (int)(image.Width * (bpp / 8F));
using (var writer = new TiffWriter(stream, this.memoryAllocator, this.configuration))
{ {
long firstIfdMarker = this.WriteHeader(writer); long firstIfdMarker = this.WriteHeader(writer);
//// todo: multiframing is not support
// TODO: multiframing is not support
long nextIfdMarker = this.WriteImage(writer, image, firstIfdMarker); long nextIfdMarker = this.WriteImage(writer, image, firstIfdMarker);
} }
} }
@ -72,6 +98,31 @@ namespace SixLabors.ImageSharp.Formats.Tiff
return firstIfdMarker; return firstIfdMarker;
} }
/// <summary>
/// Writes all data required to define an image.
/// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="writer">The <see cref="BinaryWriter"/> to write data to.</param>
/// <param name="image">The <see cref="Image{TPixel}"/> to encode from.</param>
/// <param name="ifdOffset">The marker to write this IFD offset.</param>
/// <returns>The marker to write the next IFD offset (if present).</returns>
public long WriteImage<TPixel>(TiffWriter writer, Image<TPixel> image, long ifdOffset)
where TPixel : unmanaged, IPixel<TPixel>
{
var ifdEntries = new List<IExifValue>();
// Write the image bytes to the steam.
var imageDataStart = (uint)writer.Position;
int imageData = writer.WriteRgbImageData(image, this.padding);
// Write info's about the image to the stream.
this.AddImageFormat(image, ifdEntries, imageDataStart, imageData);
writer.WriteMarker(ifdOffset, (uint)writer.Position);
long nextIfdMarker = this.WriteIfd(writer, ifdEntries);
return nextIfdMarker + imageData;
}
/// <summary> /// <summary>
/// Writes a TIFF IFD block. /// Writes a TIFF IFD block.
/// </summary> /// </summary>
@ -98,8 +149,8 @@ namespace SixLabors.ImageSharp.Formats.Tiff
writer.Write((ushort)entry.DataType); writer.Write((ushort)entry.DataType);
writer.Write(ExifWriter.GetNumberOfComponents(entry)); writer.Write(ExifWriter.GetNumberOfComponents(entry));
uint lenght = ExifWriter.GetLength(entry); uint length = ExifWriter.GetLength(entry);
var raw = new byte[lenght]; var raw = new byte[length];
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");
if (raw.Length <= 4) if (raw.Length <= 4)
@ -130,36 +181,95 @@ namespace SixLabors.ImageSharp.Formats.Tiff
} }
/// <summary> /// <summary>
/// Writes all data required to define an image /// Adds image format information to the specified IFD.
/// </summary> /// </summary>
/// <typeparam name="TPixel">The pixel format.</typeparam> /// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="writer">The <see cref="BinaryWriter"/> to write data to.</param>
/// <param name="image">The <see cref="Image{TPixel}"/> to encode from.</param> /// <param name="image">The <see cref="Image{TPixel}"/> to encode from.</param>
/// <param name="ifdOffset">The marker to write this IFD offset.</param> /// <param name="ifdEntries">The image format entries to add to the IFD.</param>
/// <returns>The marker to write the next IFD offset (if present).</returns> /// <param name="imageDataStartOffset">The start of the image data in the stream.</param>
public long WriteImage<TPixel>(TiffWriter writer, Image<TPixel> image, long ifdOffset) /// <param name="imageDataBytes">The image data in bytes to write.</param>
where TPixel : unmanaged, IPixel<TPixel> public void AddImageFormat<TPixel>(Image<TPixel> image, List<IExifValue> ifdEntries, uint imageDataStartOffset, int imageDataBytes)
where TPixel : unmanaged, IPixel<TPixel>
{ {
var ifdEntries = new List<IExifValue>(); var width = new ExifLong(ExifTagValue.ImageWidth)
{
Value = (uint)image.Width
};
this.AddImageFormat(image, ifdEntries); var height = new ExifLong(ExifTagValue.ImageLength)
{
Value = (uint)image.Height
};
writer.WriteMarker(ifdOffset, (uint)writer.Position); var bitPerSample = new ExifShortArray(ExifTagValue.BitsPerSample)
long nextIfdMarker = this.WriteIfd(writer, ifdEntries); {
Value = new ushort[] { 8, 8, 8 }
};
return nextIfdMarker; var compression = new ExifShort(ExifTagValue.Compression)
} {
// TODO: for the start, no compression is used.
Value = (ushort)TiffCompression.None
};
/// <summary> var photometricInterpretation = new ExifShort(ExifTagValue.PhotometricInterpretation)
/// Adds image format information to the specified IFD. {
/// </summary> // TODO: only rgb for now.
/// <typeparam name="TPixel">The pixel format.</typeparam> Value = (ushort)TiffPhotometricInterpretation.Rgb
/// <param name="image">The <see cref="Image{TPixel}"/> to encode from.</param> };
/// <param name="ifdEntries">The image format entries to add to the IFD.</param>
public void AddImageFormat<TPixel>(Image<TPixel> image, List<IExifValue> ifdEntries) var stripOffsets = new ExifLongArray(ExifTagValue.StripOffsets)
where TPixel : unmanaged, IPixel<TPixel> {
{ // TODO: we only write one image strip for the start.
throw new NotImplementedException(); Value = new uint[] { imageDataStartOffset }
};
var samplesPerPixel = new ExifLong(ExifTagValue.SamplesPerPixel)
{
Value = 3
};
var rowsPerStrip = new ExifLong(ExifTagValue.RowsPerStrip)
{
// TODO: all rows in one strip for the start
Value = (uint)image.Height
};
var stripByteCounts = new ExifLongArray(ExifTagValue.StripByteCounts)
{
Value = new[] { (uint)(imageDataBytes) }
};
var xResolution = new ExifRational(ExifTagValue.XResolution)
{
// TODO: what to use here as a default?
Value = Rational.FromDouble(1.0d)
};
var yResolution = new ExifRational(ExifTagValue.YResolution)
{
// TODO: what to use here as a default?
Value = Rational.FromDouble(1.0d)
};
var resolutionUnit = new ExifShort(ExifTagValue.ResolutionUnit)
{
// TODO: what to use here as default?
Value = 0
};
ifdEntries.Add(width);
ifdEntries.Add(height);
ifdEntries.Add(bitPerSample);
ifdEntries.Add(compression);
ifdEntries.Add(photometricInterpretation);
ifdEntries.Add(stripOffsets);
ifdEntries.Add(samplesPerPixel);
ifdEntries.Add(rowsPerStrip);
ifdEntries.Add(stripByteCounts);
ifdEntries.Add(xResolution);
ifdEntries.Add(yResolution);
ifdEntries.Add(resolutionUnit);
} }
} }
} }

70
src/ImageSharp/Formats/Tiff/Utils/TiffWriter.cs

@ -4,6 +4,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Formats.Tiff namespace SixLabors.ImageSharp.Formats.Tiff
{ {
@ -14,15 +16,25 @@ namespace SixLabors.ImageSharp.Formats.Tiff
{ {
private readonly Stream output; private readonly Stream output;
private readonly MemoryAllocator memoryAllocator;
private readonly Configuration configuration;
private readonly byte[] paddingBytes = new byte[4]; private readonly byte[] paddingBytes = new byte[4];
private readonly List<long> references = new List<long>(); private readonly List<long> references = new List<long>();
/// <summary>Initializes a new instance of the <see cref="TiffWriter"/> class.</summary> /// <summary>
/// Initializes a new instance of the <see cref="TiffWriter"/> class.
/// </summary>
/// <param name="output">The output stream.</param> /// <param name="output">The output stream.</param>
public TiffWriter(Stream output) /// <param name="memoryMemoryAllocator">The memory allocator.</param>
/// <param name="configuration">The configuration.</param>
public TiffWriter(Stream output, MemoryAllocator memoryMemoryAllocator, Configuration configuration)
{ {
this.output = output; this.output = output;
this.memoryAllocator = memoryMemoryAllocator;
this.configuration = configuration;
} }
/// <summary> /// <summary>
@ -35,7 +47,9 @@ namespace SixLabors.ImageSharp.Formats.Tiff
/// </summary> /// </summary>
public long Position => this.output.Position; public long Position => this.output.Position;
/// <summary>Writes an empty four bytes to the stream, returning the offset to be written later.</summary> /// <summary>
/// Writes an empty four bytes to the stream, returning the offset to be written later.
/// </summary>
/// <returns>The offset to be written later</returns> /// <returns>The offset to be written later</returns>
public long PlaceMarker() public long PlaceMarker()
{ {
@ -44,21 +58,27 @@ namespace SixLabors.ImageSharp.Formats.Tiff
return offset; return offset;
} }
/// <summary>Writes an array of bytes to the current stream.</summary> /// <summary>
/// Writes an array of bytes to the current stream.
/// </summary>
/// <param name="value">The bytes to write.</param> /// <param name="value">The bytes to write.</param>
public void Write(byte[] value) public void Write(byte[] value)
{ {
this.output.Write(value, 0, value.Length); this.output.Write(value, 0, value.Length);
} }
/// <summary>Writes a byte to the current stream.</summary> /// <summary>
/// Writes a byte to the current stream.
/// </summary>
/// <param name="value">The byte to write.</param> /// <param name="value">The byte to write.</param>
public void Write(byte value) public void Write(byte value)
{ {
this.output.Write(new byte[] { value }, 0, 1); this.output.Write(new byte[] { value }, 0, 1);
} }
/// <summary>Writes a two-byte unsigned integer to the current stream.</summary> /// <summary>
/// Writes a two-byte unsigned integer to the current stream.
/// </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) public void Write(ushort value)
{ {
@ -66,7 +86,9 @@ namespace SixLabors.ImageSharp.Formats.Tiff
this.output.Write(bytes, 0, 2); this.output.Write(bytes, 0, 2);
} }
/// <summary>Writes a four-byte unsigned integer to the current stream.</summary> /// <summary>
/// Writes a four-byte unsigned integer to the current stream.
/// </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) public void Write(uint value)
{ {
@ -74,7 +96,9 @@ namespace SixLabors.ImageSharp.Formats.Tiff
this.output.Write(bytes, 0, 4); this.output.Write(bytes, 0, 4);
} }
/// <summary>Writes an array of bytes to the current stream, padded to four-bytes.</summary> /// <summary>
/// Writes an array of bytes to the current stream, padded to four-bytes.
/// </summary>
/// <param name="value">The bytes to write.</param> /// <param name="value">The bytes to write.</param>
public void WritePadded(byte[] value) public void WritePadded(byte[] value)
{ {
@ -86,7 +110,9 @@ namespace SixLabors.ImageSharp.Formats.Tiff
} }
} }
/// <summary>Writes a four-byte unsigned integer to the specified marker in the stream.</summary> /// <summary>
/// Writes a four-byte unsigned integer to the specified marker in the stream.
/// </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) public void WriteMarker(long offset, uint value)
@ -97,6 +123,30 @@ namespace SixLabors.ImageSharp.Formats.Tiff
this.output.Seek(currentOffset, SeekOrigin.Begin); this.output.Seek(currentOffset, SeekOrigin.Begin);
} }
/// <summary>
/// Writes the image data as RGB to the stream.
/// </summary>
/// <typeparam name="TPixel">The pixel data.</typeparam>
/// <param name="image">The image to write to the stream.</param>
/// <param name="padding">The padding bytes for each row.</param>
/// <returns>The number of bytes written</returns>
public int WriteRgbImageData<TPixel>(Image<TPixel> image, int padding)
where TPixel : unmanaged, IPixel<TPixel>
{
using IManagedByteBuffer row = this.AllocateRow(image.Width, 3, padding);
Span<byte> rowSpan = row.GetSpan();
for (int y = 0; y < image.Height; y++)
{
Span<TPixel> pixelRow = image.GetPixelRowSpan(y);
PixelOperations<TPixel>.Instance.ToRgb24Bytes(this.configuration, pixelRow, rowSpan, pixelRow.Length);
this.output.Write(rowSpan);
}
return image.Width * image.Height * 3;
}
private IManagedByteBuffer AllocateRow(int width, int bytesPerPixel, int padding) => this.memoryAllocator.AllocatePaddedPixelRowBuffer(width, bytesPerPixel, padding);
/// <summary> /// <summary>
/// Disposes <see cref="TiffWriter"/> instance, ensuring any unwritten data is flushed. /// Disposes <see cref="TiffWriter"/> instance, ensuring any unwritten data is flushed.
/// </summary> /// </summary>
@ -105,4 +155,4 @@ namespace SixLabors.ImageSharp.Formats.Tiff
this.output.Flush(); this.output.Flush();
} }
} }
} }

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

@ -3,6 +3,7 @@
using System.IO; using System.IO;
using SixLabors.ImageSharp.Formats.Tiff; using SixLabors.ImageSharp.Formats.Tiff;
using SixLabors.ImageSharp.Memory;
using Xunit; using Xunit;
namespace SixLabors.ImageSharp.Tests.Formats.Tiff namespace SixLabors.ImageSharp.Tests.Formats.Tiff
@ -10,13 +11,16 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
[Trait("Category", "Tiff")] [Trait("Category", "Tiff")]
public class TiffEncoderHeaderTests public class TiffEncoderHeaderTests
{ {
private static readonly MemoryAllocator MemoryAllocator = new ArrayPoolMemoryAllocator();
private static readonly Configuration Configuration = Configuration.Default;
[Fact] [Fact]
public void WriteHeader_WritesValidHeader() public void WriteHeader_WritesValidHeader()
{ {
MemoryStream stream = new MemoryStream(); var stream = new MemoryStream();
TiffEncoderCore encoder = new TiffEncoderCore(null); var encoder = new TiffEncoderCore(null, MemoryAllocator);
using (TiffWriter writer = new TiffWriter(stream)) using (var writer = new TiffWriter(stream, MemoryAllocator, Configuration))
{ {
long firstIfdMarker = encoder.WriteHeader(writer); long firstIfdMarker = encoder.WriteHeader(writer);
} }
@ -27,10 +31,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
[Fact] [Fact]
public void WriteHeader_ReturnsFirstIfdMarker() public void WriteHeader_ReturnsFirstIfdMarker()
{ {
MemoryStream stream = new MemoryStream(); var stream = new MemoryStream();
TiffEncoderCore encoder = new TiffEncoderCore(null); var encoder = new TiffEncoderCore(null, MemoryAllocator);
using (TiffWriter writer = new TiffWriter(stream)) using (var writer = new TiffWriter(stream, MemoryAllocator, Configuration))
{ {
long firstIfdMarker = encoder.WriteHeader(writer); long firstIfdMarker = encoder.WriteHeader(writer);
Assert.Equal(4, firstIfdMarker); Assert.Equal(4, firstIfdMarker);

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

@ -3,6 +3,7 @@
using System.IO; using System.IO;
using SixLabors.ImageSharp.Formats.Tiff; using SixLabors.ImageSharp.Formats.Tiff;
using SixLabors.ImageSharp.Memory;
using Xunit; using Xunit;
namespace SixLabors.ImageSharp.Tests.Formats.Tiff namespace SixLabors.ImageSharp.Tests.Formats.Tiff
@ -10,41 +11,35 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
[Trait("Category", "Tiff")] [Trait("Category", "Tiff")]
public class TiffWriterTests public class TiffWriterTests
{ {
private static readonly MemoryAllocator MemoryAllocator = new ArrayPoolMemoryAllocator();
private static readonly Configuration Configuration = Configuration.Default;
[Fact] [Fact]
public void IsLittleEndian_IsTrueOnWindows() public void IsLittleEndian_IsTrueOnWindows()
{ {
MemoryStream stream = new MemoryStream(); using var stream = new MemoryStream();
using var writer = new TiffWriter(stream, MemoryAllocator, Configuration);
using (TiffWriter writer = new TiffWriter(stream)) Assert.True(writer.IsLittleEndian);
{
Assert.True(writer.IsLittleEndian);
}
} }
[Theory] [Theory]
[InlineData(new byte[] {}, 0)] [InlineData(new byte[] { }, 0)]
[InlineData(new byte[] { 42 }, 1)] [InlineData(new byte[] { 42 }, 1)]
[InlineData(new byte[] { 1, 2, 3, 4, 5 }, 5)] [InlineData(new byte[] { 1, 2, 3, 4, 5 }, 5)]
public void Position_EqualsTheStreamPosition(byte[] data, long expectedResult) public void Position_EqualsTheStreamPosition(byte[] data, long expectedResult)
{ {
MemoryStream stream = new MemoryStream(); using var stream = new MemoryStream();
using var writer = new TiffWriter(stream, MemoryAllocator, Configuration);
using (TiffWriter writer = new TiffWriter(stream)) writer.Write(data);
{ Assert.Equal(writer.Position, expectedResult);
writer.Write(data);
Assert.Equal(writer.Position, expectedResult);
}
} }
[Fact] [Fact]
public void Write_WritesByte() public void Write_WritesByte()
{ {
MemoryStream stream = new MemoryStream(); using var stream = new MemoryStream();
using var writer = new TiffWriter(stream, MemoryAllocator, Configuration);
using (TiffWriter writer = new TiffWriter(stream)) writer.Write((byte)42);
{
writer.Write((byte)42);
}
Assert.Equal(new byte[] { 42 }, stream.ToArray()); Assert.Equal(new byte[] { 42 }, stream.ToArray());
} }
@ -52,12 +47,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
[Fact] [Fact]
public void Write_WritesByteArray() public void Write_WritesByteArray()
{ {
MemoryStream stream = new MemoryStream(); using var stream = new MemoryStream();
using var writer = new TiffWriter(stream, MemoryAllocator, Configuration);
using (TiffWriter writer = new TiffWriter(stream)) writer.Write(new byte[] { 2, 4, 6, 8 });
{
writer.Write(new byte[] { 2, 4, 6, 8 });
}
Assert.Equal(new byte[] { 2, 4, 6, 8 }, stream.ToArray()); Assert.Equal(new byte[] { 2, 4, 6, 8 }, stream.ToArray());
} }
@ -65,12 +57,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
[Fact] [Fact]
public void Write_WritesUInt16() public void Write_WritesUInt16()
{ {
MemoryStream stream = new MemoryStream(); using var stream = new MemoryStream();
using var writer = new TiffWriter(stream, MemoryAllocator, Configuration);
using (TiffWriter writer = new TiffWriter(stream)) writer.Write((ushort)1234);
{
writer.Write((ushort)1234);
}
Assert.Equal(new byte[] { 0xD2, 0x04 }, stream.ToArray()); Assert.Equal(new byte[] { 0xD2, 0x04 }, stream.ToArray());
} }
@ -78,12 +67,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
[Fact] [Fact]
public void Write_WritesUInt32() public void Write_WritesUInt32()
{ {
MemoryStream stream = new MemoryStream(); using var stream = new MemoryStream();
using var writer = new TiffWriter(stream, MemoryAllocator, Configuration);
using (TiffWriter writer = new TiffWriter(stream)) writer.Write((uint)12345678);
{
writer.Write((uint)12345678);
}
Assert.Equal(new byte[] { 0x4E, 0x61, 0xBC, 0x00 }, stream.ToArray()); Assert.Equal(new byte[] { 0x4E, 0x61, 0xBC, 0x00 }, stream.ToArray());
} }
@ -97,12 +83,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
[InlineData(new byte[] { 2, 4, 6, 8, 10, 12 }, new byte[] { 2, 4, 6, 8, 10, 12 })] [InlineData(new byte[] { 2, 4, 6, 8, 10, 12 }, new byte[] { 2, 4, 6, 8, 10, 12 })]
public void WritePadded_WritesByteArray(byte[] bytes, byte[] expectedResult) public void WritePadded_WritesByteArray(byte[] bytes, byte[] expectedResult)
{ {
MemoryStream stream = new MemoryStream(); using var stream = new MemoryStream();
using var writer = new TiffWriter(stream, MemoryAllocator, Configuration);
using (TiffWriter writer = new TiffWriter(stream)) writer.WritePadded(bytes);
{
writer.WritePadded(bytes);
}
Assert.Equal(expectedResult, stream.ToArray()); Assert.Equal(expectedResult, stream.ToArray());
} }
@ -110,9 +93,9 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
[Fact] [Fact]
public void WriteMarker_WritesToPlacedPosition() public void WriteMarker_WritesToPlacedPosition()
{ {
MemoryStream stream = new MemoryStream(); using var stream = new MemoryStream();
using (TiffWriter writer = new TiffWriter(stream)) using (var writer = new TiffWriter(stream, MemoryAllocator, Configuration))
{ {
writer.Write((uint)0x11111111); writer.Write((uint)0x11111111);
long marker = writer.PlaceMarker(); long marker = writer.PlaceMarker();
@ -123,10 +106,14 @@ namespace SixLabors.ImageSharp.Tests.Formats.Tiff
writer.Write((uint)0x44444444); writer.Write((uint)0x44444444);
} }
Assert.Equal(new byte[] { 0x11, 0x11, 0x11, 0x11, Assert.Equal(
0x78, 0x56, 0x34, 0x12, new byte[]
0x33, 0x33, 0x33, 0x33, {
0x44, 0x44, 0x44, 0x44 }, stream.ToArray()); 0x11, 0x11, 0x11, 0x11,
0x78, 0x56, 0x34, 0x12,
0x33, 0x33, 0x33, 0x33,
0x44, 0x44, 0x44, 0x44
}, stream.ToArray());
} }
} }
} }

Loading…
Cancel
Save