mirror of https://github.com/SixLabors/ImageSharp
13 changed files with 682 additions and 0 deletions
@ -0,0 +1,7 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard1.1</TargetFramework> |
|||
</PropertyGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,205 @@ |
|||
// <copyright file="TiffTags.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.Formats |
|||
{ |
|||
/// <summary>
|
|||
/// Constants representing tag IDs in the Tiff file-format.
|
|||
/// </summary>
|
|||
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; |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
// <copyright file="TiffType.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.Formats |
|||
{ |
|||
/// <summary>
|
|||
/// Enumeration representing the data types understood by the Tiff file-format.
|
|||
/// </summary>
|
|||
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 |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<OutputType>Exe</OutputType> |
|||
<TargetFramework>netcoreapp1.0</TargetFramework> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\src\ImageSharp.Formats.Tiff\ImageSharp.Formats.Tiff.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0-preview-20170123-02" /> |
|||
<PackageReference Include="xunit" Version="2.2.0-beta5-build3474" /> |
|||
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0-beta5-build1225" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,28 @@ |
|||
// <copyright file="ByteArrayUtility.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
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; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,41 @@ |
|||
// <copyright file="ByteBuffer.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.Tests |
|||
{ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
public class ByteBuffer |
|||
{ |
|||
List<byte> bytes = new List<byte>(); |
|||
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(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
// <copyright file="ITiffGenDataSource.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.Tests |
|||
{ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
/// <summary>
|
|||
/// An interface for any class within the Tiff generator that produces data to be included in the file.
|
|||
/// </summary>
|
|||
public interface ITiffGenDataSource |
|||
{ |
|||
IEnumerable<TiffGenDataBlock> GetData(bool isLittleEndian); |
|||
} |
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
// <copyright file="TiffGenDataBlock.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.Tests |
|||
{ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
/// <summary>
|
|||
/// 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.
|
|||
/// </summary>
|
|||
public class TiffGenDataBlock |
|||
{ |
|||
public TiffGenDataBlock(byte[] bytes) |
|||
{ |
|||
this.Bytes = bytes; |
|||
this.References = new List<TiffGenDataReference>(); |
|||
} |
|||
|
|||
public byte[] Bytes { get; } |
|||
public IList<TiffGenDataReference> References { get; } |
|||
|
|||
public void AddReference(byte[] bytes, int offset) |
|||
{ |
|||
References.Add(new TiffGenDataReference(bytes, offset)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
// <copyright file="TiffGenDataReference.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.Tests |
|||
{ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
/// <summary>
|
|||
/// A utility data structure to represent a reference from one block of data to another in a Tiff file.
|
|||
/// </summary>
|
|||
public class TiffGenDataReference |
|||
{ |
|||
public TiffGenDataReference(byte[] bytes, int offset) |
|||
{ |
|||
this.Bytes = bytes; |
|||
this.Offset = offset; |
|||
} |
|||
|
|||
public byte[] Bytes { get; } |
|||
public int Offset { get; } |
|||
} |
|||
} |
|||
@ -0,0 +1,102 @@ |
|||
// <copyright file="TiffGenEntry.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.Tests |
|||
{ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using ImageSharp.Formats; |
|||
|
|||
/// <summary>
|
|||
/// A utility data structure to represent Tiff IFD entries in unit tests.
|
|||
/// </summary>
|
|||
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<TiffGenDataBlock> 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<TiffGenDataBlock> 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<TiffGenDataBlock> GetData(bool isLittleEndian) |
|||
{ |
|||
byte[] bytes = GetBytes().SelectMany(b => b.WithByteOrder(isLittleEndian)).ToArray(); |
|||
return new[] { new TiffGenDataBlock(bytes) }; |
|||
} |
|||
|
|||
private IEnumerable<byte[]> 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(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,47 @@ |
|||
// <copyright file="TiffGenExtensions.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.Tests |
|||
{ |
|||
using System; |
|||
using System.IO; |
|||
using System.Linq; |
|||
|
|||
/// <summary>
|
|||
/// A utility class for generating in-memory Tiff files for use in unit tests.
|
|||
/// </summary>
|
|||
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); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
// <copyright file="TiffGenHeader.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.Tests |
|||
{ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
|
|||
/// <summary>
|
|||
/// A utility data structure to represent a Tiff file-header.
|
|||
/// </summary>
|
|||
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<TiffGenDataBlock> 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); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,91 @@ |
|||
// <copyright file="TiffGenIfd.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.Tests |
|||
{ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
|
|||
/// <summary>
|
|||
/// A utility data structure to represent Tiff IFDs in unit tests.
|
|||
/// </summary>
|
|||
public class TiffGenIfd : ITiffGenDataSource |
|||
{ |
|||
public TiffGenIfd() |
|||
{ |
|||
this.Entries = new List<TiffGenEntry>(); |
|||
} |
|||
|
|||
public List<TiffGenEntry> Entries { get; } |
|||
public TiffGenIfd NextIfd { get; set; } |
|||
|
|||
public IEnumerable<TiffGenDataBlock> GetData(bool isLittleEndian) |
|||
{ |
|||
ByteBuffer bytes = new ByteBuffer(isLittleEndian); |
|||
List<TiffGenDataBlock> dataBlocks = new List<TiffGenDataBlock>(); |
|||
List<Tuple<TiffGenDataBlock, int>> entryReferences = new List<Tuple<TiffGenDataBlock, int>>(); |
|||
|
|||
// 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<TiffGenDataBlock> 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); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue