diff --git a/src/ImageSharp.Formats.Tiff/ImageSharp.Formats.Tiff.csproj b/src/ImageSharp.Formats.Tiff/ImageSharp.Formats.Tiff.csproj
new file mode 100644
index 0000000000..23103c903b
--- /dev/null
+++ b/src/ImageSharp.Formats.Tiff/ImageSharp.Formats.Tiff.csproj
@@ -0,0 +1,7 @@
+
+
+
+ netstandard1.1
+
+
+
diff --git a/src/ImageSharp.Formats.Tiff/TiffTags.cs b/src/ImageSharp.Formats.Tiff/TiffTags.cs
new file mode 100644
index 0000000000..db4087d58c
--- /dev/null
+++ b/src/ImageSharp.Formats.Tiff/TiffTags.cs
@@ -0,0 +1,205 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Formats
+{
+ ///
+ /// Constants representing tag IDs in the Tiff file-format.
+ ///
+ public class TiffTags
+ {
+ // Section 8: Baseline Fields
+
+ public const int Artist = 315;
+ public const int BitsPerSample = 258;
+ public const int CellLength = 265;
+ public const int CellWidth = 264;
+ public const int ColorMap = 320;
+ public const int Compression = 259;
+ public const int Copyright = 33432;
+ public const int DateTime = 306;
+ public const int ExtraSamples = 338;
+ public const int FillOrder = 266;
+ public const int FreeByteCounts = 289;
+ public const int FreeOffsets = 288;
+ public const int GrayResponseCurve = 291;
+ public const int GrayResponseUnit = 290;
+ public const int HostComputer = 316;
+ public const int ImageDescription = 270;
+ public const int ImageLength = 257;
+ public const int ImageWidth = 256;
+ public const int Make = 271;
+ public const int MaxSampleValue = 281;
+ public const int MinSampleValue = 280;
+ public const int Model = 272;
+ public const int NewSubfileType = 254;
+ public const int Orientation = 274;
+ public const int PhotometricInterpretation = 262;
+ public const int PlanarConfiguration = 284;
+ public const int ResolutionUnit = 296;
+ public const int RowsPerStrip = 278;
+ public const int SamplesPerPixel = 277;
+ public const int Software = 305;
+ public const int StripByteCounts = 279;
+ public const int StripOffsets = 273;
+ public const int SubfileType = 255;
+ public const int Threshholding = 263;
+ public const int XResolution = 282;
+ public const int YResolution = 283;
+
+ // Section 11: CCITT Bilevel Encodings
+
+ public const int T4Options = 292;
+ public const int T6Options = 293;
+
+ // Section 12: Document Storage and Retrieval
+
+ public const int DocumentName = 269;
+ public const int PageName = 285;
+ public const int PageNumber = 297;
+ public const int XPosition = 286;
+ public const int YPosition = 287;
+
+ // Section 14: Differencing Predictor
+
+ public const int Predictor = 317;
+
+ // Section 15: Tiled Images
+
+ public const int TileWidth = 322;
+ public const int TileLength = 323;
+ public const int TileOffsets = 324;
+ public const int TileByteCounts = 325;
+
+ // Section 16: CMYK Images
+
+ public const int InkSet = 332;
+ public const int NumberOfInks = 334;
+ public const int InkNames = 333;
+ public const int DotRange = 336;
+ public const int TargetPrinter = 337;
+
+ // Section 17: Halftone Hints
+
+ public const int HalftoneHints = 321;
+
+ // Section 19: Data Sample Format
+
+ public const int SampleFormat = 339;
+ public const int SMinSampleValue = 340;
+ public const int SMaxSampleValue = 341;
+
+ // Section 20: RGB Image Colorimetry
+
+ public const int WhitePoint = 318;
+ public const int PrimaryChromaticities = 319;
+ public const int TransferFunction = 301;
+ public const int TransferRange = 342;
+ public const int ReferenceBlackWhite = 532;
+
+ // Section 21: YCbCr Images
+
+ public const int YCbCrCoefficients = 529;
+ public const int YCbCrSubSampling = 530;
+ public const int YCbCrPositioning = 531;
+
+ // Section 22: JPEG Compression
+
+ public const int JpegProc = 512;
+ public const int JpegInterchangeFormat = 513;
+ public const int JpegInterchangeFormatLength = 514;
+ public const int JpegRestartInterval = 515;
+ public const int JpegLosslessPredictors = 517;
+ public const int JpegPointTransforms = 518;
+ public const int JpegQTables = 519;
+ public const int JpegDCTables = 520;
+ public const int JpegACTables = 521;
+
+ // TIFF Supplement 1: Adobe Pagemaker 6.0
+
+ public const int SubIFDs = 330;
+ public const int ClipPath = 343;
+ public const int XClipPathUnits = 344;
+ public const int YClipPathUnits = 345;
+ public const int Indexed = 346;
+ public const int ImageID = 32781;
+ public const int OpiProxy = 351;
+
+ // TIFF Supplement 2: Adobe Photoshop
+
+ public const int ImageSourceData = 37724;
+
+ // TIFF/EP Specification: Additional Tags
+
+ public const int JPEGTables = 0x015B;
+ public const int CFARepeatPatternDim = 0x828D;
+ public const int BatteryLevel = 0x828F;
+ public const int Interlace = 0x8829;
+ public const int TimeZoneOffset = 0x882A;
+ public const int SelfTimerMode = 0x882B;
+ public const int Noise = 0x920D;
+ public const int ImageNumber = 0x9211;
+ public const int SecurityClassification = 0x9212;
+ public const int ImageHistory = 0x9213;
+ public const int TiffEPStandardID = 0x9216;
+
+ // TIFF-F/FX Specification (http://www.ietf.org/rfc/rfc2301.txt)
+
+ public const int BadFaxLines = 326;
+ public const int CleanFaxData = 327;
+ public const int ConsecutiveBadFaxLines = 328;
+ public const int GlobalParametersIFD = 400;
+ public const int ProfileType = 401;
+ public const int FaxProfile = 402;
+ public const int CodingMethod = 403;
+ public const int VersionYear = 404;
+ public const int ModeNumber = 405;
+ public const int Decode = 433;
+ public const int DefaultImageColor = 434;
+ public const int StripRowCounts = 559;
+ public const int ImageLayer = 34732;
+
+ // Embedded Metadata
+
+ public const int Xmp = 700;
+ public const int Iptc = 33723;
+ public const int Photoshop = 34377;
+ public const int ExifIFD = 34665;
+ public const int GpsIFD = 34853;
+ public const int InteroperabilityIFD = 40965;
+
+ // Other Private TIFF tags (http://www.awaresystems.be/imaging/tiff/tifftags/private.html)
+
+ public const int WangAnnotation = 32932;
+ public const int MDFileTag = 33445;
+ public const int MDScalePixel = 33446;
+ public const int MDColorTable = 33447;
+ public const int MDLabName = 33448;
+ public const int MDSampleInfo = 33449;
+ public const int MDPrepDate = 33450;
+ public const int MDPrepTime = 33451;
+ public const int MDFileUnits = 33452;
+ public const int ModelPixelScaleTag = 33550;
+ public const int IngrPacketDataTag = 33918;
+ public const int IngrFlagRegisters = 33919;
+ public const int IrasBTransformationMatrix = 33920;
+ public const int ModelTiePointTag = 33922;
+ public const int ModelTransformationTag = 34264;
+ public const int IccProfile = 34675;
+ public const int GeoKeyDirectoryTag = 34735;
+ public const int GeoDoubleParamsTag = 34736;
+ public const int GeoAsciiParamsTag = 34737;
+ public const int HylaFAXFaxRecvParams = 34908;
+ public const int HylaFAXFaxSubAddress = 34909;
+ public const int HylaFAXFaxRecvTime = 34910;
+ public const int GdalMetadata = 42112;
+ public const int GdalNodata = 42113;
+ public const int OceScanjobDescription = 50215;
+ public const int OceApplicationSelector = 50216;
+ public const int OceIdentificationNumber = 50217;
+ public const int OceImageLogicCharacteristics = 50218;
+ public const int AliasLayerMetadata = 50784;
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp.Formats.Tiff/TiffType.cs b/src/ImageSharp.Formats.Tiff/TiffType.cs
new file mode 100644
index 0000000000..1bb7f6cfbb
--- /dev/null
+++ b/src/ImageSharp.Formats.Tiff/TiffType.cs
@@ -0,0 +1,27 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Formats
+{
+ ///
+ /// Enumeration representing the data types understood by the Tiff file-format.
+ ///
+ public enum TiffType
+ {
+ Byte = 1,
+ Ascii = 2,
+ Short = 3,
+ Long = 4,
+ Rational = 5,
+ SByte = 6,
+ Undefined = 7,
+ SShort = 8,
+ SLong = 9,
+ SRational = 10,
+ Float = 11,
+ Double = 12,
+ Ifd = 13
+ }
+}
\ No newline at end of file
diff --git a/tests/ImageSharp.Formats.Tiff.Tests/ImageSharp.Formats.Tiff.Tests.csproj b/tests/ImageSharp.Formats.Tiff.Tests/ImageSharp.Formats.Tiff.Tests.csproj
new file mode 100644
index 0000000000..a20f1fd99f
--- /dev/null
+++ b/tests/ImageSharp.Formats.Tiff.Tests/ImageSharp.Formats.Tiff.Tests.csproj
@@ -0,0 +1,18 @@
+
+
+
+ Exe
+ netcoreapp1.0
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/ImageSharp.Formats.Tiff.Tests/TestUtilities/ByteArrayUtility.cs b/tests/ImageSharp.Formats.Tiff.Tests/TestUtilities/ByteArrayUtility.cs
new file mode 100644
index 0000000000..8021f53302
--- /dev/null
+++ b/tests/ImageSharp.Formats.Tiff.Tests/TestUtilities/ByteArrayUtility.cs
@@ -0,0 +1,28 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Tests
+{
+ using System;
+ using System.Collections.Generic;
+
+ public static class ByteArrayUtility
+ {
+ public static byte[] WithByteOrder(this byte[] bytes, bool isLittleEndian)
+ {
+ if (BitConverter.IsLittleEndian != isLittleEndian)
+ {
+ byte[] reversedBytes = new byte[bytes.Length];
+ Array.Copy(bytes, reversedBytes, bytes.Length);
+ Array.Reverse(reversedBytes);
+ return reversedBytes;
+ }
+ else
+ {
+ return bytes;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/ImageSharp.Formats.Tiff.Tests/TestUtilities/ByteBuffer.cs b/tests/ImageSharp.Formats.Tiff.Tests/TestUtilities/ByteBuffer.cs
new file mode 100644
index 0000000000..290c942f8b
--- /dev/null
+++ b/tests/ImageSharp.Formats.Tiff.Tests/TestUtilities/ByteBuffer.cs
@@ -0,0 +1,41 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Tests
+{
+ using System;
+ using System.Collections.Generic;
+
+ public class ByteBuffer
+ {
+ List bytes = new List();
+ bool isLittleEndian;
+
+ public ByteBuffer(bool isLittleEndian)
+ {
+ this.isLittleEndian = isLittleEndian;
+ }
+
+ public void AddByte(byte value)
+ {
+ bytes.Add(value);
+ }
+
+ public void AddUInt16(ushort value)
+ {
+ bytes.AddRange(BitConverter.GetBytes(value).WithByteOrder(isLittleEndian));
+ }
+
+ public void AddUInt32(uint value)
+ {
+ bytes.AddRange(BitConverter.GetBytes(value).WithByteOrder(isLittleEndian));
+ }
+
+ public byte[] ToArray()
+ {
+ return bytes.ToArray();
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/ImageSharp.Formats.Tiff.Tests/TestUtilities/Tiff/ITiffGenDataSource.cs b/tests/ImageSharp.Formats.Tiff.Tests/TestUtilities/Tiff/ITiffGenDataSource.cs
new file mode 100644
index 0000000000..33bf999244
--- /dev/null
+++ b/tests/ImageSharp.Formats.Tiff.Tests/TestUtilities/Tiff/ITiffGenDataSource.cs
@@ -0,0 +1,18 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Tests
+{
+ using System;
+ using System.Collections.Generic;
+
+ ///
+ /// An interface for any class within the Tiff generator that produces data to be included in the file.
+ ///
+ public interface ITiffGenDataSource
+ {
+ IEnumerable GetData(bool isLittleEndian);
+ }
+}
\ No newline at end of file
diff --git a/tests/ImageSharp.Formats.Tiff.Tests/TestUtilities/Tiff/TiffGenDataBlock.cs b/tests/ImageSharp.Formats.Tiff.Tests/TestUtilities/Tiff/TiffGenDataBlock.cs
new file mode 100644
index 0000000000..bbce120541
--- /dev/null
+++ b/tests/ImageSharp.Formats.Tiff.Tests/TestUtilities/Tiff/TiffGenDataBlock.cs
@@ -0,0 +1,31 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Tests
+{
+ using System;
+ using System.Collections.Generic;
+
+ ///
+ /// A utility data structure to represent an independent block of data in a Tiff file.
+ /// These may be located in any order within a Tiff file.
+ ///
+ public class TiffGenDataBlock
+ {
+ public TiffGenDataBlock(byte[] bytes)
+ {
+ this.Bytes = bytes;
+ this.References = new List();
+ }
+
+ public byte[] Bytes { get; }
+ public IList References { get; }
+
+ public void AddReference(byte[] bytes, int offset)
+ {
+ References.Add(new TiffGenDataReference(bytes, offset));
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/ImageSharp.Formats.Tiff.Tests/TestUtilities/Tiff/TiffGenDataReference.cs b/tests/ImageSharp.Formats.Tiff.Tests/TestUtilities/Tiff/TiffGenDataReference.cs
new file mode 100644
index 0000000000..ec4c0c5df4
--- /dev/null
+++ b/tests/ImageSharp.Formats.Tiff.Tests/TestUtilities/Tiff/TiffGenDataReference.cs
@@ -0,0 +1,25 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Tests
+{
+ using System;
+ using System.Collections.Generic;
+
+ ///
+ /// A utility data structure to represent a reference from one block of data to another in a Tiff file.
+ ///
+ public class TiffGenDataReference
+ {
+ public TiffGenDataReference(byte[] bytes, int offset)
+ {
+ this.Bytes = bytes;
+ this.Offset = offset;
+ }
+
+ public byte[] Bytes { get; }
+ public int Offset { get; }
+ }
+}
\ No newline at end of file
diff --git a/tests/ImageSharp.Formats.Tiff.Tests/TestUtilities/Tiff/TiffGenEntry.cs b/tests/ImageSharp.Formats.Tiff.Tests/TestUtilities/Tiff/TiffGenEntry.cs
new file mode 100644
index 0000000000..4f0ff868b1
--- /dev/null
+++ b/tests/ImageSharp.Formats.Tiff.Tests/TestUtilities/Tiff/TiffGenEntry.cs
@@ -0,0 +1,102 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Tests
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using ImageSharp.Formats;
+
+ ///
+ /// A utility data structure to represent Tiff IFD entries in unit tests.
+ ///
+ public abstract class TiffGenEntry : ITiffGenDataSource
+ {
+ private TiffGenEntry(ushort tag, TiffType type)
+ {
+ this.Tag = tag;
+ this.Type = type;
+ }
+
+ public ushort Tag { get; }
+ public TiffType Type { get; }
+
+ public abstract IEnumerable GetData(bool isLittleEndian);
+
+ public static TiffGenEntry Ascii(ushort tag, string value)
+ {
+ return new TiffGenEntryAscii(tag, value);
+ }
+
+ public static TiffGenEntry Integer(ushort tag, TiffType type, int value)
+ {
+ return TiffGenEntry.Integer(tag, type, new int[] {value});
+ }
+
+ public static TiffGenEntry Integer(ushort tag, TiffType type, int[] value)
+ {
+ if (type != TiffType.Byte && type != TiffType.Short && type != TiffType.Long &&
+ type != TiffType.SByte && type != TiffType.SShort && type != TiffType.SLong)
+ throw new ArgumentException(nameof(type), "The specified type is not an integer type.");
+
+ return new TiffGenEntryInteger(tag, type, value);
+ }
+
+ private class TiffGenEntryAscii : TiffGenEntry
+ {
+ public TiffGenEntryAscii(ushort tag, string value) : base(tag, TiffType.Ascii)
+ {
+ this.Value = value;
+ }
+
+ public string Value { get; }
+
+ public override IEnumerable GetData(bool isLittleEndian)
+ {
+ byte[] bytes = Encoding.ASCII.GetBytes($"{Value}\0");
+ return new[] { new TiffGenDataBlock(bytes) };
+ }
+ }
+
+ private class TiffGenEntryInteger : TiffGenEntry
+ {
+ public TiffGenEntryInteger(ushort tag, TiffType type, int[] value) : base(tag, type)
+ {
+ this.Value = value;
+ }
+
+ public int[] Value { get; }
+
+ public override IEnumerable GetData(bool isLittleEndian)
+ {
+ byte[] bytes = GetBytes().SelectMany(b => b.WithByteOrder(isLittleEndian)).ToArray();
+ return new[] { new TiffGenDataBlock(bytes) };
+ }
+
+ private IEnumerable GetBytes()
+ {
+ switch (Type)
+ {
+ case TiffType.Byte:
+ return Value.Select(i => new byte[] { (byte)i });
+ case TiffType.Short:
+ return Value.Select(i => BitConverter.GetBytes((ushort)i));
+ case TiffType.Long:
+ return Value.Select(i => BitConverter.GetBytes((uint)i));
+ case TiffType.SByte:
+ return Value.Select(i => BitConverter.GetBytes((sbyte)i));
+ case TiffType.SShort:
+ return Value.Select(i => BitConverter.GetBytes((short)i));
+ case TiffType.SLong:
+ return Value.Select(i => BitConverter.GetBytes((int)i));
+ default:
+ throw new InvalidOperationException();
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/ImageSharp.Formats.Tiff.Tests/TestUtilities/Tiff/TiffGenExtensions.cs b/tests/ImageSharp.Formats.Tiff.Tests/TestUtilities/Tiff/TiffGenExtensions.cs
new file mode 100644
index 0000000000..87ba621219
--- /dev/null
+++ b/tests/ImageSharp.Formats.Tiff.Tests/TestUtilities/Tiff/TiffGenExtensions.cs
@@ -0,0 +1,47 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Tests
+{
+ using System;
+ using System.IO;
+ using System.Linq;
+
+ ///
+ /// A utility class for generating in-memory Tiff files for use in unit tests.
+ ///
+ public static class TiffGenExtensions
+ {
+ public static byte[] ToBytes(this ITiffGenDataSource dataSource, bool isLittleEndian)
+ {
+ var dataBlocks = dataSource.GetData(isLittleEndian);
+
+ int offset = 0;
+
+ foreach (var dataBlock in dataBlocks)
+ {
+ byte[] offsetBytes = BitConverter.GetBytes(offset).WithByteOrder(isLittleEndian);
+
+ foreach (var reference in dataBlock.References)
+ {
+ reference.Bytes[reference.Offset + 0] = offsetBytes[0];
+ reference.Bytes[reference.Offset + 1] = offsetBytes[1];
+ reference.Bytes[reference.Offset + 2] = offsetBytes[2];
+ reference.Bytes[reference.Offset + 3] = offsetBytes[3];
+ }
+
+ offset += dataBlock.Bytes.Length;
+ }
+
+ return dataBlocks.SelectMany(b => b.Bytes).ToArray();
+ }
+
+ public static Stream ToStream(this ITiffGenDataSource dataSource, bool isLittleEndian)
+ {
+ var bytes = dataSource.ToBytes(isLittleEndian);
+ return new MemoryStream(bytes);
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/ImageSharp.Formats.Tiff.Tests/TestUtilities/Tiff/TiffGenHeader.cs b/tests/ImageSharp.Formats.Tiff.Tests/TestUtilities/Tiff/TiffGenHeader.cs
new file mode 100644
index 0000000000..b270ff2081
--- /dev/null
+++ b/tests/ImageSharp.Formats.Tiff.Tests/TestUtilities/Tiff/TiffGenHeader.cs
@@ -0,0 +1,42 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Tests
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+
+ ///
+ /// A utility data structure to represent a Tiff file-header.
+ ///
+ public class TiffGenHeader : ITiffGenDataSource
+ {
+ public TiffGenHeader()
+ {
+ this.MagicNumber = 42;
+ }
+
+ public ushort? ByteOrderMarker { get; set; }
+ public ushort MagicNumber { get; set; }
+ public TiffGenIfd FirstIfd { get; set; }
+
+ public IEnumerable GetData(bool isLittleEndian)
+ {
+ ByteBuffer bytes = new ByteBuffer(isLittleEndian);
+
+ bytes.AddUInt16(ByteOrderMarker ?? (isLittleEndian ? (ushort)0x4949 : (ushort)0x4D4D));
+ bytes.AddUInt16(MagicNumber);
+ bytes.AddUInt32(0);
+
+ var headerData = new TiffGenDataBlock(bytes.ToArray());
+ var firstIfdData = FirstIfd.GetData(isLittleEndian);
+
+ firstIfdData.First().AddReference(headerData.Bytes, 4);
+
+ return new [] { headerData }.Concat(firstIfdData);
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/ImageSharp.Formats.Tiff.Tests/TestUtilities/Tiff/TiffGenIfd.cs b/tests/ImageSharp.Formats.Tiff.Tests/TestUtilities/Tiff/TiffGenIfd.cs
new file mode 100644
index 0000000000..2e745df369
--- /dev/null
+++ b/tests/ImageSharp.Formats.Tiff.Tests/TestUtilities/Tiff/TiffGenIfd.cs
@@ -0,0 +1,91 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageSharp.Tests
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+
+ ///
+ /// A utility data structure to represent Tiff IFDs in unit tests.
+ ///
+ public class TiffGenIfd : ITiffGenDataSource
+ {
+ public TiffGenIfd()
+ {
+ this.Entries = new List();
+ }
+
+ public List Entries { get; }
+ public TiffGenIfd NextIfd { get; set; }
+
+ public IEnumerable GetData(bool isLittleEndian)
+ {
+ ByteBuffer bytes = new ByteBuffer(isLittleEndian);
+ List dataBlocks = new List();
+ List> entryReferences = new List>();
+
+ // Add the entry count
+
+ bytes.AddUInt16((ushort)Entries.Count);
+
+ // Add all IFD entries
+
+ int entryOffset = 2;
+
+ foreach (var entry in Entries)
+ {
+ var entryData = entry.GetData(isLittleEndian);
+ var entryBytes = entryData.First().Bytes;
+ var entryCount = entryBytes.Length;
+
+ bytes.AddUInt16(entry.Tag);
+ bytes.AddUInt16((ushort)entry.Type);
+ bytes.AddUInt32((uint)entryCount);
+
+ if (entryCount <=4)
+ {
+ bytes.AddByte(entryCount > 0 ? entryBytes[0] : (byte)0);
+ bytes.AddByte(entryCount > 1 ? entryBytes[1] : (byte)0);
+ bytes.AddByte(entryCount > 2 ? entryBytes[2] : (byte)0);
+ bytes.AddByte(entryCount > 3 ? entryBytes[3] : (byte)0);
+
+ dataBlocks.AddRange(entryData.Skip(1));
+ }
+ else
+ {
+ bytes.AddUInt32(0);
+ dataBlocks.AddRange(entryData);
+ entryReferences.Add(Tuple.Create(entryData.First(), entryOffset + 8));
+ }
+
+ entryOffset += 12;
+ }
+
+ // Add reference to next IFD
+
+ bytes.AddUInt32(0);
+
+ // Build the data
+
+ var ifdData = new TiffGenDataBlock(bytes.ToArray());
+
+ foreach (var entryReference in entryReferences)
+ {
+ entryReference.Item1.AddReference(ifdData.Bytes, entryReference.Item2);
+ }
+
+ IEnumerable nextIfdData = new TiffGenDataBlock[0];
+ if (NextIfd != null)
+ {
+ nextIfdData = NextIfd.GetData(isLittleEndian);
+ nextIfdData.First().AddReference(ifdData.Bytes, ifdData.Bytes.Length - 4);
+ }
+
+ return new [] { ifdData }.Concat(dataBlocks).Concat(nextIfdData);
+ }
+ }
+}
\ No newline at end of file