diff --git a/MetadataExtractor.sln.DotSettings b/MetadataExtractor.sln.DotSettings
index 9cfbc17fb..917df53a3 100644
--- a/MetadataExtractor.sln.DotSettings
+++ b/MetadataExtractor.sln.DotSettings
@@ -9,6 +9,7 @@
LV
MM
ND
+ NW
OS
RG
UI
@@ -71,6 +72,7 @@
True
True
True
+ True
True
True
True
diff --git a/MetadataExtractor/Directory.cs b/MetadataExtractor/Directory.cs
index 73babace4..c562d870c 100644
--- a/MetadataExtractor/Directory.cs
+++ b/MetadataExtractor/Directory.cs
@@ -152,6 +152,19 @@ public virtual void Set(int tagType, object value)
#endregion
+ public void RemoveTag(int tagId)
+ {
+ if (_tagMap.Remove(tagId))
+ {
+ var index = _definedTagList.FindIndex(tag => tag.Type == tagId);
+
+ if (index != -1)
+ {
+ _definedTagList.RemoveAt(index);
+ }
+ }
+ }
+
/// Returns the name of a specified tag as a String.
/// the tag type identifier
/// the tag's name as a String
diff --git a/MetadataExtractor/Formats/Exif/ExifDescriptorBase.cs b/MetadataExtractor/Formats/Exif/ExifDescriptorBase.cs
index 0b0afa356..3848bbe0f 100644
--- a/MetadataExtractor/Formats/Exif/ExifDescriptorBase.cs
+++ b/MetadataExtractor/Formats/Exif/ExifDescriptorBase.cs
@@ -101,6 +101,8 @@ protected ExifDescriptorBase(T directory)
TagCompression => GetCompressionDescription(),
TagJpegProc => GetJpegProcDescription(),
TagLensSpecification => GetLensSpecificationDescription(),
+ TagExtraSamples => GetExtraSamplesDescription(),
+ TagSampleFormat => GetSampleFormatDescription(),
_ => base.GetDescription(tagType),
};
@@ -954,5 +956,43 @@ internal static string GetWhiteBalanceDescription(int value)
_ => "Unknown (" + value + ")",
};
}
+
+ public string? GetExtraSamplesDescription()
+ {
+ return GetIndexedDescription(
+ TagExtraSamples,
+ "Unspecified",
+ "Associated alpha",
+ "Unassociated alpha");
+ }
+
+ public string? GetSampleFormatDescription()
+ {
+ var values = Directory.GetInt32Array(TagSampleFormat);
+
+ if (values is null)
+ return null;
+
+ var sb = new StringBuilder();
+
+ foreach (var value in values)
+ {
+ if (sb.Length != 0)
+ sb.Append(", ");
+
+ sb.Append(value switch
+ {
+ 1 => "Unsigned",
+ 2 => "Signed",
+ 3 => "Float",
+ 4 => "Undefined",
+ 5 => "Complex int",
+ 6 => "Complex float",
+ _ => $"Unknown ({value})"
+ });
+ }
+
+ return sb.ToString();
+ }
}
}
diff --git a/MetadataExtractor/Formats/Exif/ExifDirectoryBase.cs b/MetadataExtractor/Formats/Exif/ExifDirectoryBase.cs
index 7982b4364..19617405c 100644
--- a/MetadataExtractor/Formats/Exif/ExifDirectoryBase.cs
+++ b/MetadataExtractor/Formats/Exif/ExifDirectoryBase.cs
@@ -155,6 +155,9 @@ public abstract class ExifDirectoryBase : Directory
/// Seems to be used exclusively by raw formats, referencing one or two IFDs.
public const int TagSubIfdOffset = 0x014a;
+ public const int TagExtraSamples = 0x0152;
+ public const int TagSampleFormat = 0x0153;
+
public const int TagTransferRange = 0x0156;
public const int TagJpegTables = 0x015B;
@@ -206,12 +209,22 @@ public abstract class ExifDirectoryBase : Directory
/// The actual F-number(F-stop) of lens when the image was taken.
public const int TagFNumber = 0x829D;
+ public const int TagPixelScale = 0x830E;
+
public const int TagIptcNaa = 0x83BB;
+ public const int TagModelTiePoint = 0x8482;
+
public const int TagPhotoshopSettings = 0x8649;
public const int TagInterColorProfile = 0x8773;
+ public const int TagGeoTiffGeoKeys = 0x87af;
+
+ public const int TagGeoTiffGeoDoubleParams = 0x87b0;
+
+ public const int TagGeoTiffGeoAsciiParams = 0x87b1;
+
/// Exposure program that the camera used when image was taken.
///
/// '1' means
@@ -697,6 +710,9 @@ public abstract class ExifDirectoryBase : Directory
/// String.
public const int TagLensSerialNumber = 0xA435;
+ public const int TagGdalMetadata = 0xA480;
+ public const int TagGdalNoData = 0xA481;
+
/// Rational64u.
public const int TagGamma = 0xA500;
@@ -758,6 +774,8 @@ protected static void AddExifTagNames(Dictionary map)
map[TagTileOffsets] = "Tile Offsets";
map[TagTileByteCounts] = "Tile Byte Counts";
map[TagSubIfdOffset] = "Sub IFD Pointer(s)";
+ map[TagExtraSamples] = "Extra Samples";
+ map[TagSampleFormat] = "Sample Format";
map[TagTransferRange] = "Transfer Range";
map[TagJpegTables] = "JPEG Tables";
map[TagJpegProc] = "JPEG Proc";
@@ -785,7 +803,9 @@ protected static void AddExifTagNames(Dictionary map)
map[TagCopyright] = "Copyright";
map[TagExposureTime] = "Exposure Time";
map[TagFNumber] = "F-Number";
+ map[TagPixelScale] = "Pixel Scale";
map[TagIptcNaa] = "IPTC/NAA";
+ map[TagModelTiePoint] = "Model Tie Point";
map[TagPhotoshopSettings] = "Photoshop Settings";
map[TagInterColorProfile] = "Inter Color Profile";
map[TagExposureProgram] = "Exposure Program";
@@ -874,6 +894,8 @@ protected static void AddExifTagNames(Dictionary map)
map[TagLensMake] = "Lens Make";
map[TagLensModel] = "Lens Model";
map[TagLensSerialNumber] = "Lens Serial Number";
+ map[TagGdalMetadata] = "GDAL Metadata";
+ map[TagGdalNoData] = "GDAL No Data";
map[TagGamma] = "Gamma";
map[TagPrintImageMatchingInfo] = "Print Image Matching (PIM) Info";
map[TagPanasonicTitle] = "Panasonic Title";
diff --git a/MetadataExtractor/Formats/Exif/ExifTiffHandler.cs b/MetadataExtractor/Formats/Exif/ExifTiffHandler.cs
index 9fe23e7f7..bb52ae82e 100644
--- a/MetadataExtractor/Formats/Exif/ExifTiffHandler.cs
+++ b/MetadataExtractor/Formats/Exif/ExifTiffHandler.cs
@@ -7,6 +7,7 @@
using System.Linq;
using System.Text;
using MetadataExtractor.Formats.Exif.Makernotes;
+using MetadataExtractor.Formats.GeoTiff;
using MetadataExtractor.Formats.Icc;
using MetadataExtractor.Formats.Iptc;
using MetadataExtractor.Formats.Jpeg;
@@ -145,7 +146,7 @@ public override bool HasFollowerIfd()
}
}
- public override bool CustomProcessTag(int tagOffset, HashSet processedIfds, IndexedReader reader, int tagId, int byteCount, bool isBigTiff)
+ public override bool CustomProcessTag(in TiffReaderContext context, int tagId, int valueOffset, int byteCount)
{
// Some 0x0000 tags have a 0 byteCount. Determine whether it's bad.
if (tagId == 0)
@@ -163,15 +164,15 @@ public override bool CustomProcessTag(int tagOffset, HashSet proces
// Custom processing for the Makernote tag
if (tagId == ExifDirectoryBase.TagMakernote && CurrentDirectory is ExifSubIfdDirectory)
- return ProcessMakernote(tagOffset, processedIfds, reader, isBigTiff);
+ return ProcessMakernote(in context, valueOffset);
// Custom processing for embedded IPTC data
if (tagId == ExifDirectoryBase.TagIptcNaa && CurrentDirectory is ExifIfd0Directory)
{
// NOTE Adobe sets type 4 for IPTC instead of 7
- if (reader.GetSByte(tagOffset) == 0x1c)
+ if (context.Reader.GetSByte(valueOffset) == 0x1c)
{
- var iptcBytes = reader.GetBytes(tagOffset, byteCount);
+ var iptcBytes = context.Reader.GetBytes(valueOffset, byteCount);
var iptcDirectory = new IptcReader().Extract(new SequentialByteArrayReader(iptcBytes), iptcBytes.Length);
iptcDirectory.Parent = CurrentDirectory;
Directories.Add(iptcDirectory);
@@ -183,7 +184,7 @@ public override bool CustomProcessTag(int tagOffset, HashSet proces
// Custom processing for ICC Profile data
if (tagId == ExifDirectoryBase.TagInterColorProfile)
{
- var iccBytes = reader.GetBytes(tagOffset, byteCount);
+ var iccBytes = context.Reader.GetBytes(valueOffset, byteCount);
var iccDirectory = new IccReader().Extract(new ByteArrayReader(iccBytes));
iccDirectory.Parent = CurrentDirectory;
Directories.Add(iccDirectory);
@@ -193,7 +194,7 @@ public override bool CustomProcessTag(int tagOffset, HashSet proces
// Custom processing for Photoshop data
if (tagId == ExifDirectoryBase.TagPhotoshopSettings && CurrentDirectory is ExifIfd0Directory)
{
- var photoshopBytes = reader.GetBytes(tagOffset, byteCount);
+ var photoshopBytes = context.Reader.GetBytes(valueOffset, byteCount);
var photoshopDirectories = new PhotoshopReader().Extract(new SequentialByteArrayReader(photoshopBytes), byteCount);
if (photoshopDirectories.Count != 0)
{
@@ -207,7 +208,7 @@ public override bool CustomProcessTag(int tagOffset, HashSet proces
// Custom processing for embedded XMP data
if (tagId == ExifDirectoryBase.TagApplicationNotes && CurrentDirectory is ExifIfd0Directory or ExifSubIfdDirectory)
{
- var xmpDirectory = new XmpReader().Extract(reader.GetNullTerminatedBytes(tagOffset, byteCount));
+ var xmpDirectory = new XmpReader().Extract(context.Reader.GetNullTerminatedBytes(valueOffset, byteCount));
xmpDirectory.Parent = CurrentDirectory;
Directories.Add(xmpDirectory);
return true;
@@ -217,7 +218,7 @@ public override bool CustomProcessTag(int tagOffset, HashSet proces
{
var printIMDirectory = new PrintIMDirectory { Parent = CurrentDirectory };
Directories.Add(printIMDirectory);
- ProcessPrintIM(printIMDirectory, tagOffset, reader, byteCount);
+ ProcessPrintIM(printIMDirectory, valueOffset, context.Reader, byteCount);
return true;
}
@@ -229,35 +230,35 @@ public override bool CustomProcessTag(int tagOffset, HashSet proces
{
case OlympusMakernoteDirectory.TagEquipment:
PushDirectory(new OlympusEquipmentMakernoteDirectory());
- TiffReader.ProcessIfd(this, reader, processedIfds, tagOffset, isBigTiff);
+ TiffReader.ProcessIfd(this, context, valueOffset);
return true;
case OlympusMakernoteDirectory.TagCameraSettings:
PushDirectory(new OlympusCameraSettingsMakernoteDirectory());
- TiffReader.ProcessIfd(this, reader, processedIfds, tagOffset, isBigTiff);
+ TiffReader.ProcessIfd(this, context, valueOffset);
return true;
case OlympusMakernoteDirectory.TagRawDevelopment:
PushDirectory(new OlympusRawDevelopmentMakernoteDirectory());
- TiffReader.ProcessIfd(this, reader, processedIfds, tagOffset, isBigTiff);
+ TiffReader.ProcessIfd(this, context, valueOffset);
return true;
case OlympusMakernoteDirectory.TagRawDevelopment2:
PushDirectory(new OlympusRawDevelopment2MakernoteDirectory());
- TiffReader.ProcessIfd(this, reader, processedIfds, tagOffset, isBigTiff);
+ TiffReader.ProcessIfd(this, context, valueOffset);
return true;
case OlympusMakernoteDirectory.TagImageProcessing:
PushDirectory(new OlympusImageProcessingMakernoteDirectory());
- TiffReader.ProcessIfd(this, reader, processedIfds, tagOffset, isBigTiff);
+ TiffReader.ProcessIfd(this, context, valueOffset);
return true;
case OlympusMakernoteDirectory.TagFocusInfo:
PushDirectory(new OlympusFocusInfoMakernoteDirectory());
- TiffReader.ProcessIfd(this, reader, processedIfds, tagOffset, isBigTiff);
+ TiffReader.ProcessIfd(this, context, valueOffset);
return true;
case OlympusMakernoteDirectory.TagRawInfo:
PushDirectory(new OlympusRawInfoMakernoteDirectory());
- TiffReader.ProcessIfd(this, reader, processedIfds, tagOffset, isBigTiff);
+ TiffReader.ProcessIfd(this, context, valueOffset);
return true;
case OlympusMakernoteDirectory.TagMainInfo:
PushDirectory(new OlympusMakernoteDirectory());
- TiffReader.ProcessIfd(this, reader, processedIfds, tagOffset, isBigTiff);
+ TiffReader.ProcessIfd(this, context, valueOffset);
return true;
}
}
@@ -271,17 +272,17 @@ public override bool CustomProcessTag(int tagOffset, HashSet proces
case PanasonicRawIfd0Directory.TagWbInfo:
var dirWbInfo = new PanasonicRawWbInfoDirectory { Parent = CurrentDirectory };
Directories.Add(dirWbInfo);
- ProcessBinary(dirWbInfo, tagOffset, reader, byteCount, isSigned: false, arrayLength: 2);
+ ProcessBinary(dirWbInfo, valueOffset, context.Reader, byteCount, isSigned: false, arrayLength: 2);
return true;
case PanasonicRawIfd0Directory.TagWbInfo2:
var dirWbInfo2 = new PanasonicRawWbInfo2Directory { Parent = CurrentDirectory };
Directories.Add(dirWbInfo2);
- ProcessBinary(dirWbInfo2, tagOffset, reader, byteCount, isSigned: false, arrayLength: 3);
+ ProcessBinary(dirWbInfo2, valueOffset, context.Reader, byteCount, isSigned: false, arrayLength: 3);
return true;
case PanasonicRawIfd0Directory.TagDistortionInfo:
var dirDistort = new PanasonicRawDistortionDirectory { Parent = CurrentDirectory };
Directories.Add(dirDistort);
- ProcessBinary(dirDistort, tagOffset, reader, byteCount, isSigned: true, arrayLength: 1);
+ ProcessBinary(dirDistort, valueOffset, context.Reader, byteCount, isSigned: true, arrayLength: 1);
return true;
}
@@ -333,7 +334,7 @@ static void ProcessBinary(Directory directory, int tagValueOffset, IndexedReader
if (tagId == PanasonicRawIfd0Directory.TagJpgFromRaw && CurrentDirectory is PanasonicRawIfd0Directory)
{
// Extract information from embedded image since it is metadata-rich
- var bytes = reader.GetBytes(tagOffset, byteCount);
+ var bytes = context.Reader.GetBytes(valueOffset, byteCount);
var stream = new MemoryStream(bytes);
foreach (var directory in JpegMetadataReader.ReadMetadata(stream))
@@ -348,6 +349,98 @@ static void ProcessBinary(Directory directory, int tagValueOffset, IndexedReader
return false;
}
+ public override void EndingIfd(in TiffReaderContext context)
+ {
+ if (CurrentDirectory is ExifIfd0Directory directory)
+ {
+ if (directory.GetObject(ExifDirectoryBase.TagGeoTiffGeoKeys) is ushort[] geoKeys)
+ {
+ // GetTIFF stores data in its own format within TIFF. It is TIFF-like, but different.
+ // It can reference data frm tags that have not been visited yet, so we must unpack it
+ // once the directory is complete.
+ ProcessGeoTiff(geoKeys, directory);
+ }
+ }
+
+ base.EndingIfd(context);
+ }
+
+ private void ProcessGeoTiff(ushort[] geoKeys, ExifIfd0Directory sourceDirectory)
+ {
+ if (geoKeys.Length < 4)
+ return;
+
+ var geoTiffDirectory = new GeoTiffDirectory { Parent = CurrentDirectory };
+ Directories.Add(geoTiffDirectory);
+
+ var i = 0;
+
+ var directoryVersion = geoKeys[i++];
+ var revision = geoKeys[i++];
+ var minorRevision = geoKeys[i++];
+ var numberOfKeys = geoKeys[i++];
+
+ // TODO store these values in negative tag IDs
+
+ var sourceTags = new HashSet { ExifDirectoryBase.TagGeoTiffGeoKeys };
+
+ for (var j = 0; j < numberOfKeys; j++)
+ {
+ var keyId = geoKeys[i++];
+ var tiffTagLocation = geoKeys[i++];
+ var valueCount = geoKeys[i++];
+ var valueOffset = geoKeys[i++];
+
+ if (tiffTagLocation == 0)
+ {
+ // Identifies the tag containing the value. If zero, then the value is ushort and stored
+ // in valueOffset directly, and the value count is implied as 1.
+ geoTiffDirectory.Set(keyId, valueOffset);
+ }
+ else
+ {
+ // The value is stored in another tag.
+ var sourceTagId = tiffTagLocation;
+ sourceTags.Add(sourceTagId);
+ var sourceValue = sourceDirectory.GetObject(sourceTagId);
+ if (sourceValue is StringValue sourceString)
+ {
+ if (valueOffset + valueCount <= sourceString.Bytes.Length)
+ {
+ // ASCII values appear to have a | character and the end, so we trim it off here
+ geoTiffDirectory.Set(keyId, sourceString.ToString(valueOffset, valueCount).TrimEnd('|'));
+ }
+ else
+ {
+ geoTiffDirectory.AddError($"GeoTIFF key {keyId} with offset {valueOffset} and count {valueCount} extends beyond length of source value ({sourceString.Bytes.Length})");
+ }
+ }
+ else if (sourceValue is Array sourceArray)
+ {
+ if (valueOffset + valueCount < sourceArray.Length)
+ {
+ var array = Array.CreateInstance(sourceArray.GetType().GetElementType(), valueCount);
+ Array.Copy(sourceArray, valueOffset, array, 0, valueCount);
+ geoTiffDirectory.Set(keyId, array);
+ }
+ else
+ {
+ geoTiffDirectory.AddError($"GeoTIFF key {keyId} with offset {valueOffset} and count {valueCount} extends beyond length of source value ({sourceArray.Length})");
+ }
+ }
+ else
+ {
+ geoTiffDirectory.AddError($"GeoTIFF key {keyId} references tag {sourceTagId} which has unsupported type of {sourceValue?.GetType().ToString() ?? "null"}");
+ }
+ }
+ }
+
+ foreach (var sourceTag in sourceTags)
+ {
+ sourceDirectory.RemoveTag(sourceTag);
+ }
+ }
+
public override bool TryCustomProcessFormat(int tagId, TiffDataFormatCode formatCode, ulong componentCount, out ulong byteCount)
{
if ((ushort)formatCode == 13u)
@@ -368,23 +461,23 @@ public override bool TryCustomProcessFormat(int tagId, TiffDataFormatCode format
}
///
- private bool ProcessMakernote(int makernoteOffset, HashSet processedIfds, IndexedReader reader, bool isBigTiff)
+ private bool ProcessMakernote(in TiffReaderContext context, int makernoteOffset)
{
Debug.Assert(makernoteOffset >= 0, "makernoteOffset >= 0");
var cameraMake = Directories.OfType().FirstOrDefault()?.GetString(ExifDirectoryBase.TagMake);
#pragma warning disable format
- var firstTwoChars = reader.GetString(makernoteOffset, 2, Encoding.UTF8);
- var firstThreeChars = reader.GetString(makernoteOffset, 3, Encoding.UTF8);
- var firstFourChars = reader.GetString(makernoteOffset, 4, Encoding.UTF8);
- var firstFiveChars = reader.GetString(makernoteOffset, 5, Encoding.UTF8);
- var firstSixChars = reader.GetString(makernoteOffset, 6, Encoding.UTF8);
- var firstSevenChars = reader.GetString(makernoteOffset, 7, Encoding.UTF8);
- var firstEightChars = reader.GetString(makernoteOffset, 8, Encoding.UTF8);
- var firstNineChars = reader.GetString(makernoteOffset, 9, Encoding.UTF8);
- var firstTenChars = reader.GetString(makernoteOffset, 10, Encoding.UTF8);
- var firstTwelveChars = reader.GetString(makernoteOffset, 12, Encoding.UTF8);
+ var firstTwoChars = context.Reader.GetString(makernoteOffset, 2, Encoding.UTF8);
+ var firstThreeChars = context.Reader.GetString(makernoteOffset, 3, Encoding.UTF8);
+ var firstFourChars = context.Reader.GetString(makernoteOffset, 4, Encoding.UTF8);
+ var firstFiveChars = context.Reader.GetString(makernoteOffset, 5, Encoding.UTF8);
+ var firstSixChars = context.Reader.GetString(makernoteOffset, 6, Encoding.UTF8);
+ var firstSevenChars = context.Reader.GetString(makernoteOffset, 7, Encoding.UTF8);
+ var firstEightChars = context.Reader.GetString(makernoteOffset, 8, Encoding.UTF8);
+ var firstNineChars = context.Reader.GetString(makernoteOffset, 9, Encoding.UTF8);
+ var firstTenChars = context.Reader.GetString(makernoteOffset, 10, Encoding.UTF8);
+ var firstTwelveChars = context.Reader.GetString(makernoteOffset, 12, Encoding.UTF8);
#pragma warning restore format
if (string.Equals("OLYMP\0", firstSixChars, StringComparison.Ordinal) ||
@@ -394,7 +487,7 @@ private bool ProcessMakernote(int makernoteOffset, HashSet processe
// Olympus Makernote
// Epson and Agfa use Olympus makernote standard: http://www.ozhiker.com/electronics/pjmt/jpeg_info/
PushDirectory(new OlympusMakernoteDirectory());
- TiffReader.ProcessIfd(this, reader, processedIfds, makernoteOffset + 8, isBigTiff);
+ TiffReader.ProcessIfd(this, context, makernoteOffset + 8);
}
else if (string.Equals("OLYMPUS\0II", firstTenChars, StringComparison.Ordinal))
{
@@ -402,20 +495,20 @@ private bool ProcessMakernote(int makernoteOffset, HashSet processe
// Note that data is relative to the beginning of the makernote
// http://exiv2.org/makernote.html
PushDirectory(new OlympusMakernoteDirectory());
- TiffReader.ProcessIfd(this, reader.WithShiftedBaseOffset(makernoteOffset), processedIfds, 12, isBigTiff);
+ TiffReader.ProcessIfd(this, context.WithShiftedBaseOffset(makernoteOffset), 12);
}
else if (cameraMake != null && cameraMake.StartsWith("MINOLTA", StringComparison.OrdinalIgnoreCase))
{
// Cases seen with the model starting with MINOLTA in capitals seem to have a valid Olympus makernote
// area that commences immediately.
PushDirectory(new OlympusMakernoteDirectory());
- TiffReader.ProcessIfd(this, reader, processedIfds, makernoteOffset, isBigTiff);
+ TiffReader.ProcessIfd(this, context, makernoteOffset);
}
else if (cameraMake != null && cameraMake.TrimStart().StartsWith("NIKON", StringComparison.OrdinalIgnoreCase))
{
if (string.Equals("Nikon", firstFiveChars, StringComparison.Ordinal))
{
- switch (reader.GetByte(makernoteOffset + 6))
+ switch (context.Reader.GetByte(makernoteOffset + 6))
{
case 1:
{
@@ -428,13 +521,13 @@ private bool ProcessMakernote(int makernoteOffset, HashSet processe
* :0010: 00 08 00 1E 00 01 00 07-00 00 00 04 30 32 30 30 ............0200
*/
PushDirectory(new NikonType1MakernoteDirectory());
- TiffReader.ProcessIfd(this, reader, processedIfds, makernoteOffset + 8, isBigTiff);
+ TiffReader.ProcessIfd(this, context, makernoteOffset + 8);
break;
}
case 2:
{
PushDirectory(new NikonType2MakernoteDirectory());
- TiffReader.ProcessIfd(this, reader.WithShiftedBaseOffset(makernoteOffset + 10), processedIfds, 8, isBigTiff);
+ TiffReader.ProcessIfd(this, context.WithShiftedBaseOffset(makernoteOffset + 10), 8);
break;
}
default:
@@ -448,58 +541,58 @@ private bool ProcessMakernote(int makernoteOffset, HashSet processe
{
// The IFD begins with the first Makernote byte (no ASCII name). This occurs with CoolPix 775, E990 and D1 models.
PushDirectory(new NikonType2MakernoteDirectory());
- TiffReader.ProcessIfd(this, reader, processedIfds, makernoteOffset, isBigTiff);
+ TiffReader.ProcessIfd(this, context, makernoteOffset);
}
}
else if (string.Equals("SONY CAM", firstEightChars, StringComparison.Ordinal) ||
string.Equals("SONY DSC", firstEightChars, StringComparison.Ordinal))
{
PushDirectory(new SonyType1MakernoteDirectory());
- TiffReader.ProcessIfd(this, reader, processedIfds, makernoteOffset + 12, isBigTiff);
+ TiffReader.ProcessIfd(this, context, makernoteOffset + 12);
}
// Do this check LAST after most other Sony checks
else if (cameraMake != null && cameraMake.StartsWith("SONY", StringComparison.Ordinal) &&
- reader.GetBytes(makernoteOffset, 2) != new byte[] { 0x01, 0x00 })
+ (context.Reader.GetByte(makernoteOffset) != 0x01 || context.Reader.GetByte(makernoteOffset + 1) != 0x00))
{
// The IFD begins with the first Makernote byte (no ASCII name). Used in SR2 and ARW images
PushDirectory(new SonyType1MakernoteDirectory());
- TiffReader.ProcessIfd(this, reader, processedIfds, makernoteOffset, isBigTiff);
+ TiffReader.ProcessIfd(this, context, makernoteOffset);
}
else if (string.Equals("SEMC MS\u0000\u0000\u0000\u0000\u0000", firstTwelveChars, StringComparison.Ordinal))
{
// Force Motorola byte order for this directory
// skip 12 byte header + 2 for "MM" + 6
PushDirectory(new SonyType6MakernoteDirectory());
- TiffReader.ProcessIfd(this, reader.WithByteOrder(isMotorolaByteOrder: true), processedIfds, makernoteOffset + 20, isBigTiff);
+ TiffReader.ProcessIfd(this, context.WithByteOrder(isMotorolaByteOrder: true), makernoteOffset + 20);
}
else if (string.Equals("SIGMA\u0000\u0000\u0000", firstEightChars, StringComparison.Ordinal) ||
string.Equals("FOVEON\u0000\u0000", firstEightChars, StringComparison.Ordinal))
{
PushDirectory(new SigmaMakernoteDirectory());
- TiffReader.ProcessIfd(this, reader, processedIfds, makernoteOffset + 10, isBigTiff);
+ TiffReader.ProcessIfd(this, context, makernoteOffset + 10);
}
else if (string.Equals("KDK", firstThreeChars, StringComparison.Ordinal))
{
var directory = new KodakMakernoteDirectory();
Directories.Add(directory);
- ProcessKodakMakernote(directory, makernoteOffset, reader.WithByteOrder(isMotorolaByteOrder: firstSevenChars == "KDK INFO"));
+ ProcessKodakMakernote(directory, makernoteOffset, context.Reader.WithByteOrder(isMotorolaByteOrder: firstSevenChars == "KDK INFO"));
}
else if ("CANON".Equals(cameraMake, StringComparison.OrdinalIgnoreCase))
{
PushDirectory(new CanonMakernoteDirectory());
- TiffReader.ProcessIfd(this, reader, processedIfds, makernoteOffset, isBigTiff);
+ TiffReader.ProcessIfd(this, context, makernoteOffset);
}
else if (cameraMake != null && cameraMake.StartsWith("CASIO", StringComparison.OrdinalIgnoreCase))
{
if (string.Equals("QVC\u0000\u0000\u0000", firstSixChars, StringComparison.Ordinal))
{
PushDirectory(new CasioType2MakernoteDirectory());
- TiffReader.ProcessIfd(this, reader, processedIfds, makernoteOffset + 6, isBigTiff);
+ TiffReader.ProcessIfd(this, context, makernoteOffset + 6);
}
else
{
PushDirectory(new CasioType1MakernoteDirectory());
- TiffReader.ProcessIfd(this, reader, processedIfds, makernoteOffset, isBigTiff);
+ TiffReader.ProcessIfd(this, context, makernoteOffset);
}
}
else if (string.Equals("FUJIFILM", firstEightChars, StringComparison.Ordinal) ||
@@ -508,16 +601,16 @@ private bool ProcessMakernote(int makernoteOffset, HashSet processe
// Note that this also applies to certain Leica cameras, such as the Digilux-4.3.
// The 4 bytes after "FUJIFILM" in the makernote point to the start of the makernote
// IFD, though the offset is relative to the start of the makernote, not the TIFF header
- var makernoteReader = reader.WithShiftedBaseOffset(makernoteOffset).WithByteOrder(isMotorolaByteOrder: false);
- var ifdStart = makernoteReader.GetInt32(8);
+ var makernoteContext = context.WithShiftedBaseOffset(makernoteOffset).WithByteOrder(isMotorolaByteOrder: false);
+ var ifdStart = makernoteContext.Reader.GetInt32(8);
PushDirectory(new FujifilmMakernoteDirectory());
- TiffReader.ProcessIfd(this, makernoteReader, processedIfds, ifdStart, isBigTiff);
+ TiffReader.ProcessIfd(this, makernoteContext, ifdStart);
}
else if (string.Equals("KYOCERA", firstSevenChars, StringComparison.Ordinal))
{
// http://www.ozhiker.com/electronics/pjmt/jpeg_info/kyocera_mn.html
PushDirectory(new KyoceraMakernoteDirectory());
- TiffReader.ProcessIfd(this, reader, processedIfds, makernoteOffset + 22, isBigTiff);
+ TiffReader.ProcessIfd(this, context, makernoteOffset + 22);
}
else if (string.Equals("LEICA", firstFiveChars, StringComparison.Ordinal))
{
@@ -535,18 +628,18 @@ private bool ProcessMakernote(int makernoteOffset, HashSet processe
string.Equals("LEICA\0\x7\0", firstEightChars, StringComparison.Ordinal))
{
PushDirectory(new LeicaType5MakernoteDirectory());
- TiffReader.ProcessIfd(this, reader.WithShiftedBaseOffset(makernoteOffset), processedIfds, 8, isBigTiff);
+ TiffReader.ProcessIfd(this, context.WithShiftedBaseOffset(makernoteOffset), 8);
}
else if (string.Equals("Leica Camera AG", cameraMake, StringComparison.Ordinal))
{
PushDirectory(new LeicaMakernoteDirectory());
- TiffReader.ProcessIfd(this, reader.WithByteOrder(isMotorolaByteOrder: false), processedIfds, makernoteOffset + 8, isBigTiff);
+ TiffReader.ProcessIfd(this, context.WithByteOrder(isMotorolaByteOrder: false), makernoteOffset + 8);
}
else if (string.Equals("LEICA", cameraMake, StringComparison.Ordinal))
{
// Some Leica cameras use Panasonic makernote tags
PushDirectory(new PanasonicMakernoteDirectory());
- TiffReader.ProcessIfd(this, reader.WithByteOrder(isMotorolaByteOrder: false), processedIfds, makernoteOffset + 8, isBigTiff);
+ TiffReader.ProcessIfd(this, context.WithByteOrder(isMotorolaByteOrder: false), makernoteOffset + 8);
}
else
{
@@ -559,7 +652,7 @@ private bool ProcessMakernote(int makernoteOffset, HashSet processe
// Offsets are relative to the start of the TIFF header at the beginning of the EXIF segment
// more information here: http://www.ozhiker.com/electronics/pjmt/jpeg_info/panasonic_mn.html
PushDirectory(new PanasonicMakernoteDirectory());
- TiffReader.ProcessIfd(this, reader, processedIfds, makernoteOffset + 12, isBigTiff);
+ TiffReader.ProcessIfd(this, context, makernoteOffset + 12);
}
else if (string.Equals("AOC\u0000", firstFourChars, StringComparison.Ordinal))
{
@@ -569,7 +662,7 @@ private bool ProcessMakernote(int makernoteOffset, HashSet processe
// Observed for:
// - Pentax ist D
PushDirectory(new CasioType2MakernoteDirectory());
- TiffReader.ProcessIfd(this, reader.WithShiftedBaseOffset(makernoteOffset), processedIfds, 6, isBigTiff);
+ TiffReader.ProcessIfd(this, context.WithShiftedBaseOffset(makernoteOffset), 6);
}
else if (cameraMake != null && (cameraMake.StartsWith("PENTAX", StringComparison.OrdinalIgnoreCase) || cameraMake.StartsWith("ASAHI", StringComparison.OrdinalIgnoreCase)))
{
@@ -580,7 +673,7 @@ private bool ProcessMakernote(int makernoteOffset, HashSet processe
// - PENTAX Optio 330
// - PENTAX Optio 430
PushDirectory(new PentaxMakernoteDirectory());
- TiffReader.ProcessIfd(this, reader.WithShiftedBaseOffset(makernoteOffset), processedIfds, 0, isBigTiff);
+ TiffReader.ProcessIfd(this, context.WithShiftedBaseOffset(makernoteOffset), 0);
}
/*
else if ("KC" == firstTwoChars || "MINOL" == firstFiveChars || "MLY" == firstThreeChars || "+M+M+M+M" == firstEightChars)
@@ -594,7 +687,7 @@ private bool ProcessMakernote(int makernoteOffset, HashSet processe
else if (string.Equals("SANYO\x0\x1\x0", firstEightChars, StringComparison.Ordinal))
{
PushDirectory(new SanyoMakernoteDirectory());
- TiffReader.ProcessIfd(this, reader.WithShiftedBaseOffset(makernoteOffset), processedIfds, 8, isBigTiff);
+ TiffReader.ProcessIfd(this, context.WithShiftedBaseOffset(makernoteOffset), 8);
}
else if (cameraMake != null && cameraMake.StartsWith("RICOH", StringComparison.OrdinalIgnoreCase))
{
@@ -612,48 +705,48 @@ private bool ProcessMakernote(int makernoteOffset, HashSet processe
{
PushDirectory(new RicohMakernoteDirectory());
// Always in Motorola byte order
- TiffReader.ProcessIfd(this, reader.WithByteOrder(isMotorolaByteOrder: true).WithShiftedBaseOffset(makernoteOffset), processedIfds, 8, isBigTiff);
+ TiffReader.ProcessIfd(this, context.WithByteOrder(isMotorolaByteOrder: true).WithShiftedBaseOffset(makernoteOffset), 8);
}
}
else if (string.Equals(firstTenChars, "Apple iOS\0", StringComparison.Ordinal))
{
PushDirectory(new AppleMakernoteDirectory());
// Always in Motorola byte order
- TiffReader.ProcessIfd(this, reader.WithByteOrder(isMotorolaByteOrder: true).WithShiftedBaseOffset(makernoteOffset), processedIfds, 14, isBigTiff);
+ TiffReader.ProcessIfd(this, context.WithByteOrder(isMotorolaByteOrder: true).WithShiftedBaseOffset(makernoteOffset), 14);
}
- else if (reader.GetUInt16(makernoteOffset) == ReconyxHyperFireMakernoteDirectory.MakernoteVersion)
+ else if (context.Reader.GetUInt16(makernoteOffset) == ReconyxHyperFireMakernoteDirectory.MakernoteVersion)
{
var directory = new ReconyxHyperFireMakernoteDirectory();
Directories.Add(directory);
- ProcessReconyxHyperFireMakernote(directory, makernoteOffset, reader);
+ ProcessReconyxHyperFireMakernote(directory, makernoteOffset, context.Reader);
}
else if (string.Equals("RECONYXUF", firstNineChars, StringComparison.OrdinalIgnoreCase))
{
var directory = new ReconyxUltraFireMakernoteDirectory();
Directories.Add(directory);
- ProcessReconyxUltraFireMakernote(directory, makernoteOffset, reader);
+ ProcessReconyxUltraFireMakernote(directory, makernoteOffset, context.Reader);
}
else if (string.Equals("RECONYXH2", firstNineChars, StringComparison.OrdinalIgnoreCase))
{
var directory = new ReconyxHyperFire2MakernoteDirectory();
Directories.Add(directory);
- ProcessReconyxHyperFire2Makernote(directory, makernoteOffset, reader);
+ ProcessReconyxHyperFire2Makernote(directory, makernoteOffset, context.Reader);
}
else if (string.Equals("SAMSUNG", cameraMake, StringComparison.OrdinalIgnoreCase))
{
// Only handles Type2 notes correctly. Others aren't implemented, and it's complex to determine which ones to use
PushDirectory(new SamsungType2MakernoteDirectory());
- TiffReader.ProcessIfd(this, reader, processedIfds, makernoteOffset, isBigTiff);
+ TiffReader.ProcessIfd(this, context, makernoteOffset);
}
else if (string.Equals("DJI", cameraMake, StringComparison.Ordinal))
{
PushDirectory(new DjiMakernoteDirectory());
- TiffReader.ProcessIfd(this, reader, processedIfds, makernoteOffset, isBigTiff);
+ TiffReader.ProcessIfd(this, context, makernoteOffset);
}
else if (string.Equals("FLIR Systems", cameraMake, StringComparison.Ordinal))
{
PushDirectory(new FlirMakernoteDirectory());
- TiffReader.ProcessIfd(this, reader, processedIfds, makernoteOffset, isBigTiff);
+ TiffReader.ProcessIfd(this, context, makernoteOffset);
}
else
{
diff --git a/MetadataExtractor/Formats/GeoTiff/GeoTiffDescriptor.cs b/MetadataExtractor/Formats/GeoTiff/GeoTiffDescriptor.cs
new file mode 100644
index 000000000..0c2e85e50
--- /dev/null
+++ b/MetadataExtractor/Formats/GeoTiff/GeoTiffDescriptor.cs
@@ -0,0 +1,2116 @@
+// Copyright (c) Drew Noakes and contributors. All Rights Reserved. Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
+
+namespace MetadataExtractor.Formats.GeoTiff
+{
+ public sealed class GeoTiffDescriptor : TagDescriptor
+ {
+ public GeoTiffDescriptor(GeoTiffDirectory directory)
+ : base(directory)
+ {
+ }
+
+ public override string? GetDescription(int tagType)
+ {
+#pragma warning disable format
+
+ return tagType switch
+ {
+ GeoTiffDirectory.TagModelType => GetModelTypeDescription(),
+ GeoTiffDirectory.TagRasterType => GetRasterTypeDescription(),
+ GeoTiffDirectory.TagGeographicType => GetGeographicTypeDescription(),
+ GeoTiffDirectory.TagGeodeticDatum => GetGeodeticDatumDescription(),
+ GeoTiffDirectory.TagGeographicPrimeMeridian => GetPrimeMeridianDescription(),
+ GeoTiffDirectory.TagGeographicLinearUnits => GetGeoTiffUnitsDescription(GeoTiffDirectory.TagGeographicLinearUnits),
+ GeoTiffDirectory.TagGeographicAngularUnits => GetGeoTiffUnitsDescription(GeoTiffDirectory.TagGeographicAngularUnits),
+ GeoTiffDirectory.TagGeographicEllipsoid => GetGeographicEllipsoidDescription(),
+ GeoTiffDirectory.TagProjectedCSType => GetProjectedCoordinateSystemDescription(),
+ GeoTiffDirectory.TagProjection => GetProjectionDescription(),
+ GeoTiffDirectory.TagProjectedCoordinateTransform => GetProjectedCoordinateTransformDescription(),
+ GeoTiffDirectory.TagProjLinearUnits => GetGeoTiffUnitsDescription(GeoTiffDirectory.TagProjLinearUnits),
+ GeoTiffDirectory.TagVerticalCSType => GetGeoTiffVerticalCSDescription(GeoTiffDirectory.TagVerticalCSType),
+ GeoTiffDirectory.TagVerticalDatum => GetGeoTiffVerticalCSDescription(GeoTiffDirectory.TagVerticalDatum),
+ GeoTiffDirectory.TagVerticalUnits => GetGeoTiffUnitsDescription(GeoTiffDirectory.TagVerticalUnits),
+ GeoTiffDirectory.TagChartFormat => GetChartFormatDescription(),
+ GeoTiffDirectory.TagChartSoundingDatum => GetChartSoundingDatumDescription(),
+ GeoTiffDirectory.TagChartDepthUnits => GetGeoTiffUnitsDescription(GeoTiffDirectory.TagChartDepthUnits),
+
+ _ => base.GetDescription(tagType)
+ };
+
+#pragma warning restore format
+ }
+
+ private string? GetGeoTiffUnitsDescription(int tagType)
+ {
+ if (!Directory.TryGetUInt16(tagType, out ushort value))
+ return null;
+
+ return value switch
+ {
+ 9001 => "Linear Meter",
+ 9002 => "Linear Foot",
+ 9003 => "Linear Foot US Survey",
+ 9004 => "Linear Foot Modified American",
+ 9005 => "Linear Foot Clarke",
+ 9006 => "Linear Foot Indian",
+ 9007 => "Linear Link",
+ 9008 => "Linear Link Benoit",
+ 9009 => "Linear Link Sears",
+ 9010 => "Linear Chain Benoit",
+ 9011 => "Linear Chain Sears",
+ 9012 => "Linear Yard Sears",
+ 9013 => "Linear Yard Indian",
+ 9014 => "Linear Fathom",
+ 9015 => "Linear Mile International Nautical",
+ 9101 => "Angular Radian",
+ 9102 => "Angular Degree",
+ 9103 => "Angular Arc Minute",
+ 9104 => "Angular Arc Second",
+ 9105 => "Angular Grad",
+ 9106 => "Angular Gon",
+ 9107 => "Angular DMS",
+ 9108 => "Angular DMS Hemisphere",
+ 32767 => "User Defined",
+ _ => "Unknown (" + value + ")"
+ };
+ }
+
+ private string? GetGeoTiffVerticalCSDescription(int tagType)
+ {
+ if (!Directory.TryGetUInt16(tagType, out ushort value))
+ return null;
+
+ return value switch
+ {
+ 0 => "Undefined",
+ 5001 => "Airy 1830 ellipsoid",
+ 5002 => "Airy Modified 1849 ellipsoid",
+ 5003 => "ANS ellipsoid",
+ 5004 => "Bessel 1841 ellipsoid",
+ 5005 => "Bessel Modified ellipsoid",
+ 5006 => "Bessel Namibia ellipsoid",
+ 5007 => "Clarke 1858 ellipsoid",
+ 5008 => "Clarke 1866 ellipsoid",
+ 5010 => "Clarke 1880 Benoit ellipsoid",
+ 5011 => "Clarke 1880 IGN ellipsoid",
+ 5012 => "Clarke 1880 RGS ellipsoid",
+ 5013 => "Clarke 1880 Arc ellipsoid",
+ 5014 => "Clarke 1880 SGA 1922 ellipsoid",
+ 5015 => "Everest 1830 1937 Adjustment ellipsoid",
+ 5016 => "Everest 1830 1967 Definition ellipsoid",
+ 5017 => "Everest 1830 1975 Definition ellipsoid",
+ 5018 => "Everest 1830 Modified ellipsoid",
+ 5019 => "GRS 1980 ellipsoid",
+ 5020 => "Helmert 1906 ellipsoid",
+ 5021 => "INS ellipsoid",
+ 5022 => "International 1924 ellipsoid",
+ 5023 => "International 1967 ellipsoid",
+ 5024 => "Krassowsky 1940 ellipsoid",
+ 5025 => "NWL 9D ellipsoid",
+ 5026 => "NWL 10D ellipsoid",
+ 5027 => "Plessis 1817 ellipsoid",
+ 5028 => "Struve 1860 ellipsoid",
+ 5029 => "War Office ellipsoid",
+ 5030 => "WGS 84 ellipsoid",
+ 5031 => "GEM 10C ellipsoid",
+ 5032 => "OSU86F ellipsoid",
+ 5033 => "OSU91A ellipsoid",
+ 5101 => "Newlyn",
+ 5102 => "North American Vertical Datum 1929",
+ 5103 => "North American Vertical Datum 1988",
+ 5104 => "Yellow Sea 1956",
+ 5105 => "Baltic Sea",
+ 5106 => "Caspian Sea",
+ 32767 => "User Defined",
+ _ => "Unknown (" + value + ")"
+ };
+ }
+
+ public string? GetModelTypeDescription()
+ {
+ if (!Directory.TryGetUInt16(GeoTiffDirectory.TagModelType, out ushort value))
+ return null;
+
+ return value switch
+ {
+ 1 => "Projected",
+ 2 => "Geographic",
+ 3 => "Geocentric",
+ 32767 => "Geocentric",
+ _ => "Unknown (" + value + ")"
+ };
+ }
+
+ public string? GetRasterTypeDescription()
+ {
+ if (!Directory.TryGetUInt16(GeoTiffDirectory.TagRasterType, out ushort value))
+ return null;
+
+ return value switch
+ {
+ 1 => "Projected",
+ 2 => "Geographic",
+ 3 => "Geocentric",
+ 32767 => "Geocentric",
+ _ => "Unknown (" + value + ")"
+ };
+ }
+
+ public string? GetGeographicTypeDescription()
+ {
+ if (!Directory.TryGetUInt16(GeoTiffDirectory.TagGeographicType, out ushort value))
+ return null;
+
+ return value switch
+ {
+ 4001 => "Airy 1830",
+ 4002 => "Airy Modified 1849",
+ 4003 => "Australian National Spheroid",
+ 4004 => "Bessel 1841",
+ 4005 => "Bessel Modified",
+ 4006 => "Bessel Namibia",
+ 4007 => "Clarke 1858",
+ 4008 => "Clarke 1866",
+ 4009 => "Clarke 1866 Michigan",
+ 4010 => "Clarke 1880 Benoit",
+ 4011 => "Clarke 1880 IGN",
+ 4012 => "Clarke 1880 RGS",
+ 4013 => "Clarke 1880 Arc",
+ 4014 => "Clarke 1880 SGA 1922",
+ 4015 => "Everest 1830 1937 Adjustment",
+ 4016 => "Everest 1830 1967 Definition",
+ 4017 => "Everest 1830 1975 Definition",
+ 4018 => "Everest 1830 Modified",
+ 4019 => "GRS 1980",
+ 4020 => "Helmert 1906",
+ 4021 => "Indonesian National Spheroid",
+ 4022 => "International 1924",
+ 4023 => "International 1967",
+ 4024 => "Krassowsky 1940",
+ 4025 => "NWL9D",
+ 4026 => "NWL10D",
+ 4027 => "Plessis 1817",
+ 4028 => "Struve 1860",
+ 4029 => "War Office",
+ 4030 => "WGS84",
+ 4031 => "GEM10C",
+ 4032 => "OSU86F",
+ 4033 => "OSU91A",
+ 4034 => "Clarke 1880",
+ 4035 => "Sphere",
+ 4120 => "Greek",
+ 4121 => "GGRS87",
+ 4123 => "KKJ",
+ 4124 => "RT90",
+ 4133 => "EST92",
+ 4201 => "Adindan",
+ 4202 => "AGD66",
+ 4203 => "AGD84",
+ 4204 => "Ain el Abd",
+ 4205 => "Afgooye",
+ 4206 => "Agadez",
+ 4207 => "Lisbon",
+ 4208 => "Aratu",
+ 4209 => "Arc 1950",
+ 4210 => "Arc 1960",
+ 4211 => "Batavia",
+ 4212 => "Barbados",
+ 4213 => "Beduaram",
+ 4214 => "Beijing 1954",
+ 4215 => "Belge 1950",
+ 4216 => "Bermuda 1957",
+ 4217 => "Bern 1898",
+ 4218 => "Bogota",
+ 4219 => "Bukit Rimpah",
+ 4220 => "Camacupa",
+ 4221 => "Campo Inchauspe",
+ 4222 => "Cape",
+ 4223 => "Carthage",
+ 4224 => "Chua",
+ 4225 => "Corrego Alegre",
+ 4226 => "Cote d Ivoire",
+ 4227 => "Deir ez Zor",
+ 4228 => "Douala",
+ 4229 => "Egypt 1907",
+ 4230 => "ED50",
+ 4231 => "ED87",
+ 4232 => "Fahud",
+ 4233 => "Gandajika 1970",
+ 4234 => "Garoua",
+ 4235 => "Guyane Francaise",
+ 4236 => "Hu Tzu Shan",
+ 4237 => "HD72",
+ 4238 => "ID74",
+ 4239 => "Indian 1954",
+ 4240 => "Indian 1975",
+ 4241 => "Jamaica 1875",
+ 4242 => "JAD69",
+ 4243 => "Kalianpur",
+ 4244 => "Kandawala",
+ 4245 => "Kertau",
+ 4246 => "KOC",
+ 4247 => "La Canoa",
+ 4248 => "PSAD56",
+ 4249 => "Lake",
+ 4250 => "Leigon",
+ 4251 => "Liberia 1964",
+ 4252 => "Lome",
+ 4253 => "Luzon 1911",
+ 4254 => "Hito XVIII 1963",
+ 4255 => "Herat North",
+ 4256 => "Mahe 1971",
+ 4257 => "Makassar",
+ 4258 => "EUREF89",
+ 4259 => "Malongo 1987",
+ 4260 => "Manoca",
+ 4261 => "Merchich",
+ 4262 => "Massawa",
+ 4263 => "Minna",
+ 4264 => "Mhast",
+ 4265 => "Monte Mario",
+ 4266 => "M poraloko",
+ 4267 => "NAD27",
+ 4268 => "NAD Michigan",
+ 4269 => "NAD83",
+ 4270 => "Nahrwan 1967",
+ 4271 => "Naparima 1972",
+ 4272 => "GD49",
+ 4273 => "NGO 1948",
+ 4274 => "73",
+ 4275 => "NTF",
+ 4276 => "NSWC 9Z 2",
+ 4277 => "OSGB 1936",
+ 4278 => "OSGB70",
+ 4279 => "OS SN80",
+ 4280 => "Padang",
+ 4281 => "Palestine 1923",
+ 4282 => "Pointe Noire",
+ 4283 => "GDA94",
+ 4284 => "Pulkovo 1942",
+ 4285 => "Qatar",
+ 4286 => "Qatar 1948",
+ 4287 => "Qornoq",
+ 4288 => "Loma Quintana",
+ 4289 => "Amersfoort",
+ 4290 => "RT38",
+ 4291 => "SAD69",
+ 4292 => "Sapper Hill 1943",
+ 4293 => "Schwarzeck",
+ 4294 => "Segora",
+ 4295 => "Serindung",
+ 4296 => "Sudan",
+ 4297 => "Tananarive",
+ 4298 => "Timbalai 1948",
+ 4299 => "TM65",
+ 4300 => "TM75",
+ 4301 => "Tokyo",
+ 4302 => "Trinidad 1903",
+ 4303 => "TC 1948",
+ 4304 => "Voirol 1875",
+ 4305 => "Voirol Unifie",
+ 4306 => "Bern 1938",
+ 4307 => "Nord Sahara 1959",
+ 4308 => "Stockholm 1938",
+ 4309 => "Yacare",
+ 4310 => "Yoff",
+ 4311 => "Zanderij",
+ 4312 => "MGI",
+ 4313 => "Belge 1972",
+ 4314 => "DHDN",
+ 4315 => "Conakry 1905",
+ 4317 => "Dealul Piscului 1970",
+ 4322 => "WGS 72",
+ 4324 => "WGS 72BE",
+ 4326 => "WGS 84",
+ 4801 => "Bern 1898 Bern",
+ 4802 => "Bogota Bogota",
+ 4803 => "Lisbon Lisbon",
+ 4804 => "Makassar Jakarta",
+ 4805 => "MGI Ferro",
+ 4806 => "Monte Mario Rome",
+ 4807 => "NTF Paris",
+ 4808 => "Padang Jakarta",
+ 4809 => "Belge 1950 Brussels",
+ 4810 => "Tananarive Paris",
+ 4811 => "Voirol 1875 Paris",
+ 4812 => "Voirol Unifie Paris",
+ 4813 => "Batavia Jakarta",
+ 4815 => "Greek Athens",
+ 4901 => "ATF Paris",
+ 4902 => "NDG Paris",
+ 32767 => "User Defined",
+ _ => "Unknown (" + value + ")"
+ };
+ }
+
+ public string? GetGeodeticDatumDescription()
+ {
+ if (!Directory.TryGetUInt16(GeoTiffDirectory.TagGeodeticDatum, out ushort value))
+ return null;
+
+ return value switch
+ {
+ 6001 => "Airy 1830",
+ 6002 => "Airy Modified 1849",
+ 6003 => "Australian National Spheroid",
+ 6004 => "Bessel 1841",
+ 6005 => "Bessel Modified",
+ 6006 => "Bessel Namibia",
+ 6007 => "Clarke 1858",
+ 6008 => "Clarke 1866",
+ 6009 => "Clarke 1866 Michigan",
+ 6010 => "Clarke 1880 Benoit",
+ 6011 => "Clarke 1880 IGN",
+ 6012 => "Clarke 1880 RGS",
+ 6013 => "Clarke 1880 Arc",
+ 6014 => "Clarke 1880 SGA 1922",
+ 6015 => "Everest 1830 1937 Adjustment",
+ 6016 => "Everest 1830 1967 Definition",
+ 6017 => "Everest 1830 1975 Definition",
+ 6018 => "Everest 1830 Modified",
+ 6019 => "GRS 1980",
+ 6020 => "Helmert 1906",
+ 6021 => "Indonesian National Spheroid",
+ 6022 => "International 1924",
+ 6023 => "International 1967",
+ 6024 => "Krassowsky 1960",
+ 6025 => "NWL9D",
+ 6026 => "NWL10D",
+ 6027 => "Plessis 1817",
+ 6028 => "Struve 1860",
+ 6029 => "War Office",
+ 6030 => "WGS84",
+ 6031 => "GEM10C",
+ 6032 => "OSU86F",
+ 6033 => "OSU91A",
+ 6034 => "Clarke 1880",
+ 6035 => "Sphere",
+ 6201 => "Adindan",
+ 6202 => "Australian Geodetic Datum 1966",
+ 6203 => "Australian Geodetic Datum 1984",
+ 6204 => "Ain el Abd 1970",
+ 6205 => "Afgooye",
+ 6206 => "Agadez",
+ 6207 => "Lisbon",
+ 6208 => "Aratu",
+ 6209 => "Arc 1950",
+ 6210 => "Arc 1960",
+ 6211 => "Batavia",
+ 6212 => "Barbados",
+ 6213 => "Beduaram",
+ 6214 => "Beijing 1954",
+ 6215 => "Reseau National Belge 1950",
+ 6216 => "Bermuda 1957",
+ 6217 => "Bern 1898",
+ 6218 => "Bogota",
+ 6219 => "Bukit Rimpah",
+ 6220 => "Camacupa",
+ 6221 => "Campo Inchauspe",
+ 6222 => "Cape",
+ 6223 => "Carthage",
+ 6224 => "Chua",
+ 6225 => "Corrego Alegre",
+ 6226 => "Cote d Ivoire",
+ 6227 => "Deir ez Zor",
+ 6228 => "Douala",
+ 6229 => "Egypt 1907",
+ 6230 => "European Datum 1950",
+ 6231 => "European Datum 1987",
+ 6232 => "Fahud",
+ 6233 => "Gandajika 1970",
+ 6234 => "Garoua",
+ 6235 => "Guyane Francaise",
+ 6236 => "Hu Tzu Shan",
+ 6237 => "Hungarian Datum 1972",
+ 6238 => "Indonesian Datum 1974",
+ 6239 => "Indian 1954",
+ 6240 => "Indian 1975",
+ 6241 => "Jamaica 1875",
+ 6242 => "Jamaica 1969",
+ 6243 => "Kalianpur",
+ 6244 => "Kandawala",
+ 6245 => "Kertau",
+ 6246 => "Kuwait Oil Company",
+ 6247 => "La Canoa",
+ 6248 => "Provisional S American Datum 1956",
+ 6249 => "Lake",
+ 6250 => "Leigon",
+ 6251 => "Liberia 1964",
+ 6252 => "Lome",
+ 6253 => "Luzon 1911",
+ 6254 => "Hito XVIII 1963",
+ 6255 => "Herat North",
+ 6256 => "Mahe 1971",
+ 6257 => "Makassar",
+ 6258 => "European Reference System 1989",
+ 6259 => "Malongo 1987",
+ 6260 => "Manoca",
+ 6261 => "Merchich",
+ 6262 => "Massawa",
+ 6263 => "Minna",
+ 6264 => "Mhast",
+ 6265 => "Monte Mario",
+ 6266 => "M poraloko",
+ 6267 => "North American Datum 1927",
+ 6268 => "NAD Michigan",
+ 6269 => "North American Datum 1983",
+ 6270 => "Nahrwan 1967",
+ 6271 => "Naparima 1972",
+ 6272 => "New Zealand Geodetic Datum 1949",
+ 6273 => "NGO 1948",
+ 6274 => "Datum 73",
+ 6275 => "Nouvelle Triangulation Francaise",
+ 6276 => "NSWC 9Z 2",
+ 6277 => "OSGB 1936",
+ 6278 => "OSGB 1970 SN",
+ 6279 => "OS SN 1980",
+ 6280 => "Padang 1884",
+ 6281 => "Palestine 1923",
+ 6282 => "Pointe Noire",
+ 6283 => "Geocentric Datum of Australia 1994",
+ 6284 => "Pulkovo 1942",
+ 6285 => "Qatar",
+ 6286 => "Qatar 1948",
+ 6287 => "Qornoq",
+ 6288 => "Loma Quintana",
+ 6289 => "Amersfoort",
+ 6290 => "RT38",
+ 6291 => "South American Datum 1969",
+ 6292 => "Sapper Hill 1943",
+ 6293 => "Schwarzeck",
+ 6294 => "Segora",
+ 6295 => "Serindung",
+ 6296 => "Sudan",
+ 6297 => "Tananarive 1925",
+ 6298 => "Timbalai 1948",
+ 6299 => "TM65",
+ 6300 => "TM75",
+ 6301 => "Tokyo",
+ 6302 => "Trinidad 1903",
+ 6303 => "Trucial Coast 1948",
+ 6304 => "Voirol 1875",
+ 6305 => "Voirol Unifie 1960",
+ 6306 => "Bern 1938",
+ 6307 => "Nord Sahara 1959",
+ 6308 => "Stockholm 1938",
+ 6309 => "Yacare",
+ 6310 => "Yoff",
+ 6311 => "Zanderij",
+ 6312 => "Militar Geographische Institut",
+ 6313 => "Reseau National Belge 1972",
+ 6314 => "Deutsche Hauptdreiecksnetz",
+ 6315 => "Conakry 1905",
+ 6317 => "Dealul Piscului 1970",
+ 6322 => "WGS72",
+ 6324 => "WGS72 Transit Broadcast Ephemeris",
+ 6326 => "WGS84",
+ 6901 => "Ancienne Triangulation Francaise",
+ 6902 => "Nord de Guerre",
+ 32767 => "User Defined",
+ _ => "Unknown (" + value + ")"
+ };
+ }
+
+ public string? GetPrimeMeridianDescription()
+ {
+ if (!Directory.TryGetUInt16(GeoTiffDirectory.TagGeodeticDatum, out ushort value))
+ return null;
+
+ return value switch
+ {
+ 8901 => "Greenwich",
+ 8902 => "Lisbon",
+ 8903 => "Paris",
+ 8904 => "Bogota",
+ 8905 => "Madrid",
+ 8906 => "Rome",
+ 8907 => "Bern",
+ 8908 => "Jakarta",
+ 8909 => "Ferro",
+ 8910 => "Brussels",
+ 8911 => "Stockholm",
+ 32767 => "User Defined",
+ _ => "Unknown (" + value + ")"
+ };
+ }
+
+ public string? GetGeographicEllipsoidDescription()
+ {
+ if (!Directory.TryGetUInt16(GeoTiffDirectory.TagGeographicEllipsoid, out ushort value))
+ return null;
+
+ return value switch
+ {
+ 7001 => "Airy 1830",
+ 7002 => "Airy Modified 1849",
+ 7003 => "Australian National Spheroid",
+ 7004 => "Bessel 1841",
+ 7005 => "Bessel Modified",
+ 7006 => "Bessel Namibia",
+ 7007 => "Clarke 1858",
+ 7008 => "Clarke 1866",
+ 7009 => "Clarke 1866 Michigan",
+ 7010 => "Clarke 1880 Benoit",
+ 7011 => "Clarke 1880 IGN",
+ 7012 => "Clarke 1880 RGS",
+ 7013 => "Clarke 1880 Arc",
+ 7014 => "Clarke 1880 SGA 1922",
+ 7015 => "Everest 1830 1937 Adjustment",
+ 7016 => "Everest 1830 1967 Definition",
+ 7017 => "Everest 1830 1975 Definition",
+ 7018 => "Everest 1830 Modified",
+ 7019 => "GRS 1980",
+ 7020 => "Helmert 1906",
+ 7021 => "Indonesian National Spheroid",
+ 7022 => "International 1924",
+ 7023 => "International 1967",
+ 7024 => "Krassowsky 1940",
+ 7025 => "NWL 9D",
+ 7026 => "NWL 10D",
+ 7027 => "Plessis 1817",
+ 7028 => "Struve 1860",
+ 7029 => "War Office",
+ 7030 => "WGS 84",
+ 7031 => "GEM 10C",
+ 7032 => "OSU86F",
+ 7033 => "OSU91A",
+ 7034 => "Clarke 1880",
+ 7035 => "Sphere",
+ 32767 => "User Defined",
+ _ => "Unknown (" + value + ")"
+ };
+ }
+
+ public string? GetProjectedCoordinateSystemDescription()
+ {
+ if (!Directory.TryGetUInt16(GeoTiffDirectory.TagProjectedCSType, out ushort value))
+ return null;
+
+ return value switch
+ {
+ 2100 => "GGRS87 Greek Grid",
+ 2176 => "ETRS89 Poland CS2000 zone 5",
+ 2177 => "ETRS89 Poland CS2000 zone 7",
+ 2178 => "ETRS89 Poland CS2000 zone 8",
+ 2180 => "ETRS89 Poland CS92",
+ 2204 => "NAD27 Tennessee",
+ 2205 => "NAD83 Kentucky North",
+ 2391 => "KKJ Finland zone 1",
+ 2392 => "KKJ Finland zone 2",
+ 2393 => "KKJ Finland zone 3",
+ 2394 => "KKJ Finland zone 4",
+ 2400 => "RT90 2 5 gon W",
+ 2600 => "Lietuvos Koordinoei Sistema 1994",
+ 3053 => "Hjorsey 1955 Lambert",
+ 3057 => "ISN93 Lambert 1993",
+ 3300 => "Estonian Coordinate System of 1992",
+ 3786 => "Popular Visualisation CRS / Mercator",
+ 3857 => "WGS 84 / Pseudo-Mercator",
+ 20137 => "Adindan UTM zone 37N",
+ 20138 => "Adindan UTM zone 38N",
+ 20248 => "AGD66 AMG zone 48",
+ 20249 => "AGD66 AMG zone 49",
+ 20250 => "AGD66 AMG zone 50",
+ 20251 => "AGD66 AMG zone 51",
+ 20252 => "AGD66 AMG zone 52",
+ 20253 => "AGD66 AMG zone 53",
+ 20254 => "AGD66 AMG zone 54",
+ 20255 => "AGD66 AMG zone 55",
+ 20256 => "AGD66 AMG zone 56",
+ 20257 => "AGD66 AMG zone 57",
+ 20258 => "AGD66 AMG zone 58",
+ 20348 => "AGD84 AMG zone 48",
+ 20349 => "AGD84 AMG zone 49",
+ 20350 => "AGD84 AMG zone 50",
+ 20351 => "AGD84 AMG zone 51",
+ 20352 => "AGD84 AMG zone 52",
+ 20353 => "AGD84 AMG zone 53",
+ 20354 => "AGD84 AMG zone 54",
+ 20355 => "AGD84 AMG zone 55",
+ 20356 => "AGD84 AMG zone 56",
+ 20357 => "AGD84 AMG zone 57",
+ 20358 => "AGD84 AMG zone 58",
+ 20437 => "Ain el Abd UTM zone 37N",
+ 20438 => "Ain el Abd UTM zone 38N",
+ 20439 => "Ain el Abd UTM zone 39N",
+ 20499 => "Ain el Abd Bahrain Grid",
+ 20538 => "Afgooye UTM zone 38N",
+ 20539 => "Afgooye UTM zone 39N",
+ 20700 => "Lisbon Portuguese Grid",
+ 20822 => "Aratu UTM zone 22S",
+ 20823 => "Aratu UTM zone 23S",
+ 20824 => "Aratu UTM zone 24S",
+ 20973 => "Arc 1950 Lo13",
+ 20975 => "Arc 1950 Lo15",
+ 20977 => "Arc 1950 Lo17",
+ 20979 => "Arc 1950 Lo19",
+ 20981 => "Arc 1950 Lo21",
+ 20983 => "Arc 1950 Lo23",
+ 20985 => "Arc 1950 Lo25",
+ 20987 => "Arc 1950 Lo27",
+ 20989 => "Arc 1950 Lo29",
+ 20991 => "Arc 1950 Lo31",
+ 20993 => "Arc 1950 Lo33",
+ 20995 => "Arc 1950 Lo35",
+ 21100 => "Batavia NEIEZ",
+ 21148 => "Batavia UTM zone 48S",
+ 21149 => "Batavia UTM zone 49S",
+ 21150 => "Batavia UTM zone 50S",
+ 21413 => "Beijing Gauss zone 13",
+ 21414 => "Beijing Gauss zone 14",
+ 21415 => "Beijing Gauss zone 15",
+ 21416 => "Beijing Gauss zone 16",
+ 21417 => "Beijing Gauss zone 17",
+ 21418 => "Beijing Gauss zone 18",
+ 21419 => "Beijing Gauss zone 19",
+ 21420 => "Beijing Gauss zone 20",
+ 21421 => "Beijing Gauss zone 21",
+ 21422 => "Beijing Gauss zone 22",
+ 21423 => "Beijing Gauss zone 23",
+ 21473 => "Beijing Gauss 13N",
+ 21474 => "Beijing Gauss 14N",
+ 21475 => "Beijing Gauss 15N",
+ 21476 => "Beijing Gauss 16N",
+ 21477 => "Beijing Gauss 17N",
+ 21478 => "Beijing Gauss 18N",
+ 21479 => "Beijing Gauss 19N",
+ 21480 => "Beijing Gauss 20N",
+ 21481 => "Beijing Gauss 21N",
+ 21482 => "Beijing Gauss 22N",
+ 21483 => "Beijing Gauss 23N",
+ 21500 => "Belge Lambert 50",
+ 21790 => "Bern 1898 Swiss Old",
+ 21817 => "Bogota UTM zone 17N",
+ 21818 => "Bogota UTM zone 18N",
+ 21891 => "Bogota Colombia 3W",
+ 21892 => "Bogota Colombia Bogota",
+ 21893 => "Bogota Colombia 3E",
+ 21894 => "Bogota Colombia 6E",
+ 22032 => "Camacupa UTM 32S",
+ 22033 => "Camacupa UTM 33S",
+ 22191 => "C Inchauspe Argentina 1",
+ 22192 => "C Inchauspe Argentina 2",
+ 22193 => "C Inchauspe Argentina 3",
+ 22194 => "C Inchauspe Argentina 4",
+ 22195 => "C Inchauspe Argentina 5",
+ 22196 => "C Inchauspe Argentina 6",
+ 22197 => "C Inchauspe Argentina 7",
+ 22332 => "Carthage UTM zone 32N",
+ 22391 => "Carthage Nord Tunisie",
+ 22392 => "Carthage Sud Tunisie",
+ 22523 => "Corrego Alegre UTM 23S",
+ 22524 => "Corrego Alegre UTM 24S",
+ 22832 => "Douala UTM zone 32N",
+ 22992 => "Egypt 1907 Red Belt",
+ 22993 => "Egypt 1907 Purple Belt",
+ 22994 => "Egypt 1907 Ext Purple",
+ 23028 => "ED50 UTM zone 28N",
+ 23029 => "ED50 UTM zone 29N",
+ 23030 => "ED50 UTM zone 30N",
+ 23031 => "ED50 UTM zone 31N",
+ 23032 => "ED50 UTM zone 32N",
+ 23033 => "ED50 UTM zone 33N",
+ 23034 => "ED50 UTM zone 34N",
+ 23035 => "ED50 UTM zone 35N",
+ 23036 => "ED50 UTM zone 36N",
+ 23037 => "ED50 UTM zone 37N",
+ 23038 => "ED50 UTM zone 38N",
+ 23239 => "Fahud UTM zone 39N",
+ 23240 => "Fahud UTM zone 40N",
+ 23433 => "Garoua UTM zone 33N",
+ 23700 => "HD72 EOV",
+ 23846 => "ID74 UTM zone 46N",
+ 23847 => "ID74 UTM zone 47N",
+ 23848 => "ID74 UTM zone 48N",
+ 23849 => "ID74 UTM zone 49N",
+ 23850 => "ID74 UTM zone 50N",
+ 23851 => "ID74 UTM zone 51N",
+ 23852 => "ID74 UTM zone 52N",
+ 23853 => "ID74 UTM zone 53N",
+ 23886 => "ID74 UTM zone 46S",
+ 23887 => "ID74 UTM zone 47S",
+ 23888 => "ID74 UTM zone 48S",
+ 23889 => "ID74 UTM zone 49S",
+ 23890 => "ID74 UTM zone 50S",
+ 23891 => "ID74 UTM zone 51S",
+ 23892 => "ID74 UTM zone 52S",
+ 23893 => "ID74 UTM zone 53S",
+ 23894 => "ID74 UTM zone 54S",
+ 23947 => "Indian 1954 UTM 47N",
+ 23948 => "Indian 1954 UTM 48N",
+ 24047 => "Indian 1975 UTM 47N",
+ 24048 => "Indian 1975 UTM 48N",
+ 24100 => "Jamaica 1875 Old Grid",
+ 24200 => "JAD69 Jamaica Grid",
+ 24370 => "Kalianpur India 0",
+ 24371 => "Kalianpur India I",
+ 24372 => "Kalianpur India IIa",
+ 24373 => "Kalianpur India IIIa",
+ 24374 => "Kalianpur India IVa",
+ 24382 => "Kalianpur India IIb",
+ 24383 => "Kalianpur India IIIb",
+ 24384 => "Kalianpur India IVb",
+ 24500 => "Kertau Singapore Grid",
+ 24547 => "Kertau UTM zone 47N",
+ 24548 => "Kertau UTM zone 48N",
+ 24720 => "La Canoa UTM zone 20N",
+ 24721 => "La Canoa UTM zone 21N",
+ 24818 => "PSAD56 UTM zone 18N",
+ 24819 => "PSAD56 UTM zone 19N",
+ 24820 => "PSAD56 UTM zone 20N",
+ 24821 => "PSAD56 UTM zone 21N",
+ 24877 => "PSAD56 UTM zone 17S",
+ 24878 => "PSAD56 UTM zone 18S",
+ 24879 => "PSAD56 UTM zone 19S",
+ 24880 => "PSAD56 UTM zone 20S",
+ 24891 => "PSAD56 Peru west zone",
+ 24892 => "PSAD56 Peru central",
+ 24893 => "PSAD56 Peru east zone",
+ 25000 => "Leigon Ghana Grid",
+ 25231 => "Lome UTM zone 31N",
+ 25391 => "Luzon Philippines I",
+ 25392 => "Luzon Philippines II",
+ 25393 => "Luzon Philippines III",
+ 25394 => "Luzon Philippines IV",
+ 25395 => "Luzon Philippines V",
+ 25700 => "Makassar NEIEZ",
+ 25932 => "Malongo 1987 UTM 32S",
+ 26191 => "Merchich Nord Maroc",
+ 26192 => "Merchich Sud Maroc",
+ 26193 => "Merchich Sahara",
+ 26237 => "Massawa UTM zone 37N",
+ 26331 => "Minna UTM zone 31N",
+ 26332 => "Minna UTM zone 32N",
+ 26391 => "Minna Nigeria West",
+ 26392 => "Minna Nigeria Mid Belt",
+ 26393 => "Minna Nigeria East",
+ 26432 => "Mhast UTM zone 32S",
+ 26591 => "Monte Mario Italy 1",
+ 26592 => "Monte Mario Italy 2",
+ 26632 => "M poraloko UTM 32N",
+ 26692 => "M poraloko UTM 32S",
+ 26703 => "NAD27 UTM zone 3N",
+ 26704 => "NAD27 UTM zone 4N",
+ 26705 => "NAD27 UTM zone 5N",
+ 26706 => "NAD27 UTM zone 6N",
+ 26707 => "NAD27 UTM zone 7N",
+ 26708 => "NAD27 UTM zone 8N",
+ 26709 => "NAD27 UTM zone 9N",
+ 26710 => "NAD27 UTM zone 10N",
+ 26711 => "NAD27 UTM zone 11N",
+ 26712 => "NAD27 UTM zone 12N",
+ 26713 => "NAD27 UTM zone 13N",
+ 26714 => "NAD27 UTM zone 14N",
+ 26715 => "NAD27 UTM zone 15N",
+ 26716 => "NAD27 UTM zone 16N",
+ 26717 => "NAD27 UTM zone 17N",
+ 26718 => "NAD27 UTM zone 18N",
+ 26719 => "NAD27 UTM zone 19N",
+ 26720 => "NAD27 UTM zone 20N",
+ 26721 => "NAD27 UTM zone 21N",
+ 26722 => "NAD27 UTM zone 22N",
+ 26729 => "NAD27 Alabama East",
+ 26730 => "NAD27 Alabama West",
+ 26731 => "NAD27 Alaska zone 1",
+ 26732 => "NAD27 Alaska zone 2",
+ 26733 => "NAD27 Alaska zone 3",
+ 26734 => "NAD27 Alaska zone 4",
+ 26735 => "NAD27 Alaska zone 5",
+ 26736 => "NAD27 Alaska zone 6",
+ 26737 => "NAD27 Alaska zone 7",
+ 26738 => "NAD27 Alaska zone 8",
+ 26739 => "NAD27 Alaska zone 9",
+ 26740 => "NAD27 Alaska zone 10",
+ 26741 => "NAD27 California I",
+ 26742 => "NAD27 California II",
+ 26743 => "NAD27 California III",
+ 26744 => "NAD27 California IV",
+ 26745 => "NAD27 California V",
+ 26746 => "NAD27 California VI",
+ 26747 => "NAD27 California VII",
+ 26748 => "NAD27 Arizona East",
+ 26749 => "NAD27 Arizona Central",
+ 26750 => "NAD27 Arizona West",
+ 26751 => "NAD27 Arkansas North",
+ 26752 => "NAD27 Arkansas South",
+ 26753 => "NAD27 Colorado North",
+ 26754 => "NAD27 Colorado Central",
+ 26755 => "NAD27 Colorado South",
+ 26756 => "NAD27 Connecticut",
+ 26757 => "NAD27 Delaware",
+ 26758 => "NAD27 Florida East",
+ 26759 => "NAD27 Florida West",
+ 26760 => "NAD27 Florida North",
+ 26761 => "NAD27 Hawaii zone 1",
+ 26762 => "NAD27 Hawaii zone 2",
+ 26763 => "NAD27 Hawaii zone 3",
+ 26764 => "NAD27 Hawaii zone 4",
+ 26765 => "NAD27 Hawaii zone 5",
+ 26766 => "NAD27 Georgia East",
+ 26767 => "NAD27 Georgia West",
+ 26768 => "NAD27 Idaho East",
+ 26769 => "NAD27 Idaho Central",
+ 26770 => "NAD27 Idaho West",
+ 26771 => "NAD27 Illinois East",
+ 26772 => "NAD27 Illinois West",
+ 26773 => "NAD27 Indiana East",
+ 26774 => "NAD27 Indiana West",
+ 26775 => "NAD27 Iowa North",
+ 26776 => "NAD27 Iowa South",
+ 26777 => "NAD27 Kansas North",
+ 26778 => "NAD27 Kansas South",
+ 26779 => "NAD27 Kentucky North",
+ 26780 => "NAD27 Kentucky South",
+ 26781 => "NAD27 Louisiana North",
+ 26782 => "NAD27 Louisiana South",
+ 26783 => "NAD27 Maine East",
+ 26784 => "NAD27 Maine West",
+ 26785 => "NAD27 Maryland",
+ 26786 => "NAD27 Massachusetts",
+ 26787 => "NAD27 Massachusetts Is",
+ 26788 => "NAD27 Michigan North",
+ 26789 => "NAD27 Michigan Central",
+ 26790 => "NAD27 Michigan South",
+ 26791 => "NAD27 Minnesota North",
+ 26792 => "NAD27 Minnesota Cent",
+ 26793 => "NAD27 Minnesota South",
+ 26794 => "NAD27 Mississippi East",
+ 26795 => "NAD27 Mississippi West",
+ 26796 => "NAD27 Missouri East",
+ 26797 => "NAD27 Missouri Central",
+ 26798 => "NAD27 Missouri West",
+ 26801 => "NAD Michigan Michigan East",
+ 26802 => "NAD Michigan Michigan Old Central",
+ 26803 => "NAD Michigan Michigan West",
+ 26903 => "NAD83 UTM zone 3N",
+ 26904 => "NAD83 UTM zone 4N",
+ 26905 => "NAD83 UTM zone 5N",
+ 26906 => "NAD83 UTM zone 6N",
+ 26907 => "NAD83 UTM zone 7N",
+ 26908 => "NAD83 UTM zone 8N",
+ 26909 => "NAD83 UTM zone 9N",
+ 26910 => "NAD83 UTM zone 10N",
+ 26911 => "NAD83 UTM zone 11N",
+ 26912 => "NAD83 UTM zone 12N",
+ 26913 => "NAD83 UTM zone 13N",
+ 26914 => "NAD83 UTM zone 14N",
+ 26915 => "NAD83 UTM zone 15N",
+ 26916 => "NAD83 UTM zone 16N",
+ 26917 => "NAD83 UTM zone 17N",
+ 26918 => "NAD83 UTM zone 18N",
+ 26919 => "NAD83 UTM zone 19N",
+ 26920 => "NAD83 UTM zone 20N",
+ 26921 => "NAD83 UTM zone 21N",
+ 26922 => "NAD83 UTM zone 22N",
+ 26923 => "NAD83 UTM zone 23N",
+ 26929 => "NAD83 Alabama East",
+ 26930 => "NAD83 Alabama West",
+ 26931 => "NAD83 Alaska zone 1",
+ 26932 => "NAD83 Alaska zone 2",
+ 26933 => "NAD83 Alaska zone 3",
+ 26934 => "NAD83 Alaska zone 4",
+ 26935 => "NAD83 Alaska zone 5",
+ 26936 => "NAD83 Alaska zone 6",
+ 26937 => "NAD83 Alaska zone 7",
+ 26938 => "NAD83 Alaska zone 8",
+ 26939 => "NAD83 Alaska zone 9",
+ 26940 => "NAD83 Alaska zone 10",
+ 26941 => "NAD83 California 1",
+ 26942 => "NAD83 California 2",
+ 26943 => "NAD83 California 3",
+ 26944 => "NAD83 California 4",
+ 26945 => "NAD83 California 5",
+ 26946 => "NAD83 California 6",
+ 26948 => "NAD83 Arizona East",
+ 26949 => "NAD83 Arizona Central",
+ 26950 => "NAD83 Arizona West",
+ 26951 => "NAD83 Arkansas North",
+ 26952 => "NAD83 Arkansas South",
+ 26953 => "NAD83 Colorado North",
+ 26954 => "NAD83 Colorado Central",
+ 26955 => "NAD83 Colorado South",
+ 26956 => "NAD83 Connecticut",
+ 26957 => "NAD83 Delaware",
+ 26958 => "NAD83 Florida East",
+ 26959 => "NAD83 Florida West",
+ 26960 => "NAD83 Florida North",
+ 26961 => "NAD83 Hawaii zone 1",
+ 26962 => "NAD83 Hawaii zone 2",
+ 26963 => "NAD83 Hawaii zone 3",
+ 26964 => "NAD83 Hawaii zone 4",
+ 26965 => "NAD83 Hawaii zone 5",
+ 26966 => "NAD83 Georgia East",
+ 26967 => "NAD83 Georgia West",
+ 26968 => "NAD83 Idaho East",
+ 26969 => "NAD83 Idaho Central",
+ 26970 => "NAD83 Idaho West",
+ 26971 => "NAD83 Illinois East",
+ 26972 => "NAD83 Illinois West",
+ 26973 => "NAD83 Indiana East",
+ 26974 => "NAD83 Indiana West",
+ 26975 => "NAD83 Iowa North",
+ 26976 => "NAD83 Iowa South",
+ 26977 => "NAD83 Kansas North",
+ 26978 => "NAD83 Kansas South",
+ 26979 => "NAD83 Kentucky North",
+ 26980 => "NAD83 Kentucky South",
+ 26981 => "NAD83 Louisiana North",
+ 26982 => "NAD83 Louisiana South",
+ 26983 => "NAD83 Maine East",
+ 26984 => "NAD83 Maine West",
+ 26985 => "NAD83 Maryland",
+ 26986 => "NAD83 Massachusetts",
+ 26987 => "NAD83 Massachusetts Is",
+ 26988 => "NAD83 Michigan North",
+ 26989 => "NAD83 Michigan Central",
+ 26990 => "NAD83 Michigan South",
+ 26991 => "NAD83 Minnesota North",
+ 26992 => "NAD83 Minnesota Cent",
+ 26993 => "NAD83 Minnesota South",
+ 26994 => "NAD83 Mississippi East",
+ 26995 => "NAD83 Mississippi West",
+ 26996 => "NAD83 Missouri East",
+ 26997 => "NAD83 Missouri Central",
+ 26998 => "NAD83 Missouri West",
+ 27038 => "Nahrwan 1967 UTM 38N",
+ 27039 => "Nahrwan 1967 UTM 39N",
+ 27040 => "Nahrwan 1967 UTM 40N",
+ 27120 => "Naparima UTM 20N",
+ 27200 => "GD49 NZ Map Grid",
+ 27291 => "GD49 North Island Grid",
+ 27292 => "GD49 South Island Grid",
+ 27429 => "Datum 73 UTM zone 29N",
+ 27500 => "ATF Nord de Guerre",
+ 27581 => "NTF France I",
+ 27582 => "NTF France II",
+ 27583 => "NTF France III",
+ 27591 => "NTF Nord France",
+ 27592 => "NTF Centre France",
+ 27593 => "NTF Sud France",
+ 27700 => "British National Grid",
+ 28232 => "Point Noire UTM 32S",
+ 28348 => "GDA94 MGA zone 48",
+ 28349 => "GDA94 MGA zone 49",
+ 28350 => "GDA94 MGA zone 50",
+ 28351 => "GDA94 MGA zone 51",
+ 28352 => "GDA94 MGA zone 52",
+ 28353 => "GDA94 MGA zone 53",
+ 28354 => "GDA94 MGA zone 54",
+ 28355 => "GDA94 MGA zone 55",
+ 28356 => "GDA94 MGA zone 56",
+ 28357 => "GDA94 MGA zone 57",
+ 28358 => "GDA94 MGA zone 58",
+ 28404 => "Pulkovo Gauss zone 4",
+ 28405 => "Pulkovo Gauss zone 5",
+ 28406 => "Pulkovo Gauss zone 6",
+ 28407 => "Pulkovo Gauss zone 7",
+ 28408 => "Pulkovo Gauss zone 8",
+ 28409 => "Pulkovo Gauss zone 9",
+ 28410 => "Pulkovo Gauss zone 10",
+ 28411 => "Pulkovo Gauss zone 11",
+ 28412 => "Pulkovo Gauss zone 12",
+ 28413 => "Pulkovo Gauss zone 13",
+ 28414 => "Pulkovo Gauss zone 14",
+ 28415 => "Pulkovo Gauss zone 15",
+ 28416 => "Pulkovo Gauss zone 16",
+ 28417 => "Pulkovo Gauss zone 17",
+ 28418 => "Pulkovo Gauss zone 18",
+ 28419 => "Pulkovo Gauss zone 19",
+ 28420 => "Pulkovo Gauss zone 20",
+ 28421 => "Pulkovo Gauss zone 21",
+ 28422 => "Pulkovo Gauss zone 22",
+ 28423 => "Pulkovo Gauss zone 23",
+ 28424 => "Pulkovo Gauss zone 24",
+ 28425 => "Pulkovo Gauss zone 25",
+ 28426 => "Pulkovo Gauss zone 26",
+ 28427 => "Pulkovo Gauss zone 27",
+ 28428 => "Pulkovo Gauss zone 28",
+ 28429 => "Pulkovo Gauss zone 29",
+ 28430 => "Pulkovo Gauss zone 30",
+ 28431 => "Pulkovo Gauss zone 31",
+ 28432 => "Pulkovo Gauss zone 32",
+ 28464 => "Pulkovo Gauss 4N",
+ 28465 => "Pulkovo Gauss 5N",
+ 28466 => "Pulkovo Gauss 6N",
+ 28467 => "Pulkovo Gauss 7N",
+ 28468 => "Pulkovo Gauss 8N",
+ 28469 => "Pulkovo Gauss 9N",
+ 28470 => "Pulkovo Gauss 10N",
+ 28471 => "Pulkovo Gauss 11N",
+ 28472 => "Pulkovo Gauss 12N",
+ 28473 => "Pulkovo Gauss 13N",
+ 28474 => "Pulkovo Gauss 14N",
+ 28475 => "Pulkovo Gauss 15N",
+ 28476 => "Pulkovo Gauss 16N",
+ 28477 => "Pulkovo Gauss 17N",
+ 28478 => "Pulkovo Gauss 18N",
+ 28479 => "Pulkovo Gauss 19N",
+ 28480 => "Pulkovo Gauss 20N",
+ 28481 => "Pulkovo Gauss 21N",
+ 28482 => "Pulkovo Gauss 22N",
+ 28483 => "Pulkovo Gauss 23N",
+ 28484 => "Pulkovo Gauss 24N",
+ 28485 => "Pulkovo Gauss 25N",
+ 28486 => "Pulkovo Gauss 26N",
+ 28487 => "Pulkovo Gauss 27N",
+ 28488 => "Pulkovo Gauss 28N",
+ 28489 => "Pulkovo Gauss 29N",
+ 28490 => "Pulkovo Gauss 30N",
+ 28491 => "Pulkovo Gauss 31N",
+ 28492 => "Pulkovo Gauss 32N",
+ 28600 => "Qatar National Grid",
+ 28991 => "RD Netherlands Old",
+ 28992 => "RD Netherlands New",
+ 29118 => "SAD69 UTM zone 18N",
+ 29119 => "SAD69 UTM zone 19N",
+ 29120 => "SAD69 UTM zone 20N",
+ 29121 => "SAD69 UTM zone 21N",
+ 29122 => "SAD69 UTM zone 22N",
+ 29177 => "SAD69 UTM zone 17S",
+ 29178 => "SAD69 UTM zone 18S",
+ 29179 => "SAD69 UTM zone 19S",
+ 29180 => "SAD69 UTM zone 20S",
+ 29181 => "SAD69 UTM zone 21S",
+ 29182 => "SAD69 UTM zone 22S",
+ 29183 => "SAD69 UTM zone 23S",
+ 29184 => "SAD69 UTM zone 24S",
+ 29185 => "SAD69 UTM zone 25S",
+ 29220 => "Sapper Hill UTM 20S",
+ 29221 => "Sapper Hill UTM 21S",
+ 29333 => "Schwarzeck UTM 33S",
+ 29635 => "Sudan UTM zone 35N",
+ 29636 => "Sudan UTM zone 36N",
+ 29700 => "Tananarive Laborde",
+ 29738 => "Tananarive UTM 38S",
+ 29739 => "Tananarive UTM 39S",
+ 29800 => "Timbalai 1948 Borneo",
+ 29849 => "Timbalai 1948 UTM 49N",
+ 29850 => "Timbalai 1948 UTM 50N",
+ 29900 => "TM65 Irish Nat Grid",
+ 30200 => "Trinidad 1903 Trinidad",
+ 30339 => "TC 1948 UTM zone 39N",
+ 30340 => "TC 1948 UTM zone 40N",
+ 30491 => "Voirol N Algerie ancien",
+ 30492 => "Voirol S Algerie ancien",
+ 30591 => "Voirol Unifie N Algerie",
+ 30592 => "Voirol Unifie S Algerie",
+ 30600 => "Bern 1938 Swiss New",
+ 30729 => "Nord Sahara UTM 29N",
+ 30730 => "Nord Sahara UTM 30N",
+ 30731 => "Nord Sahara UTM 31N",
+ 30732 => "Nord Sahara UTM 32N",
+ 31028 => "Yoff UTM zone 28N",
+ 31121 => "Zanderij UTM zone 21N",
+ 31291 => "MGI Austria West",
+ 31292 => "MGI Austria Central",
+ 31293 => "MGI Austria East",
+ 31300 => "Belge Lambert 72",
+ 31491 => "DHDN Germany zone 1",
+ 31492 => "DHDN Germany zone 2",
+ 31493 => "DHDN Germany zone 3",
+ 31494 => "DHDN Germany zone 4",
+ 31495 => "DHDN Germany zone 5",
+ 31700 => "Dealul Piscului 1970 Stereo 70",
+ 32001 => "NAD27 Montana North",
+ 32002 => "NAD27 Montana Central",
+ 32003 => "NAD27 Montana South",
+ 32005 => "NAD27 Nebraska North",
+ 32006 => "NAD27 Nebraska South",
+ 32007 => "NAD27 Nevada East",
+ 32008 => "NAD27 Nevada Central",
+ 32009 => "NAD27 Nevada West",
+ 32010 => "NAD27 New Hampshire",
+ 32011 => "NAD27 New Jersey",
+ 32012 => "NAD27 New Mexico East",
+ 32013 => "NAD27 New Mexico Cent",
+ 32014 => "NAD27 New Mexico West",
+ 32015 => "NAD27 New York East",
+ 32016 => "NAD27 New York Central",
+ 32017 => "NAD27 New York West",
+ 32018 => "NAD27 New York Long Is",
+ 32019 => "NAD27 North Carolina",
+ 32020 => "NAD27 North Dakota N",
+ 32021 => "NAD27 North Dakota S",
+ 32022 => "NAD27 Ohio North",
+ 32023 => "NAD27 Ohio South",
+ 32024 => "NAD27 Oklahoma North",
+ 32025 => "NAD27 Oklahoma South",
+ 32026 => "NAD27 Oregon North",
+ 32027 => "NAD27 Oregon South",
+ 32028 => "NAD27 Pennsylvania N",
+ 32029 => "NAD27 Pennsylvania S",
+ 32030 => "NAD27 Rhode Island",
+ 32031 => "NAD27 South Carolina N",
+ 32033 => "NAD27 South Carolina S",
+ 32034 => "NAD27 South Dakota N",
+ 32035 => "NAD27 South Dakota S",
+ 32036 => "NAD27 Tennessee",
+ 32037 => "NAD27 Texas North",
+ 32038 => "NAD27 Texas North Cen",
+ 32039 => "NAD27 Texas Central",
+ 32040 => "NAD27 Texas South Cen",
+ 32041 => "NAD27 Texas South",
+ 32042 => "NAD27 Utah North",
+ 32043 => "NAD27 Utah Central",
+ 32044 => "NAD27 Utah South",
+ 32045 => "NAD27 Vermont",
+ 32046 => "NAD27 Virginia North",
+ 32047 => "NAD27 Virginia South",
+ 32048 => "NAD27 Washington North",
+ 32049 => "NAD27 Washington South",
+ 32050 => "NAD27 West Virginia N",
+ 32051 => "NAD27 West Virginia S",
+ 32052 => "NAD27 Wisconsin North",
+ 32053 => "NAD27 Wisconsin Cen",
+ 32054 => "NAD27 Wisconsin South",
+ 32055 => "NAD27 Wyoming East",
+ 32056 => "NAD27 Wyoming E Cen",
+ 32057 => "NAD27 Wyoming W Cen",
+ 32058 => "NAD27 Wyoming West",
+ 32059 => "NAD27 Puerto Rico",
+ 32060 => "NAD27 St Croix",
+ 32100 => "NAD83 Montana",
+ 32104 => "NAD83 Nebraska",
+ 32107 => "NAD83 Nevada East",
+ 32108 => "NAD83 Nevada Central",
+ 32109 => "NAD83 Nevada West",
+ 32110 => "NAD83 New Hampshire",
+ 32111 => "NAD83 New Jersey",
+ 32112 => "NAD83 New Mexico East",
+ 32113 => "NAD83 New Mexico Cent",
+ 32114 => "NAD83 New Mexico West",
+ 32115 => "NAD83 New York East",
+ 32116 => "NAD83 New York Central",
+ 32117 => "NAD83 New York West",
+ 32118 => "NAD83 New York Long Is",
+ 32119 => "NAD83 North Carolina",
+ 32120 => "NAD83 North Dakota N",
+ 32121 => "NAD83 North Dakota S",
+ 32122 => "NAD83 Ohio North",
+ 32123 => "NAD83 Ohio South",
+ 32124 => "NAD83 Oklahoma North",
+ 32125 => "NAD83 Oklahoma South",
+ 32126 => "NAD83 Oregon North",
+ 32127 => "NAD83 Oregon South",
+ 32128 => "NAD83 Pennsylvania N",
+ 32129 => "NAD83 Pennsylvania S",
+ 32130 => "NAD83 Rhode Island",
+ 32133 => "NAD83 South Carolina",
+ 32134 => "NAD83 South Dakota N",
+ 32135 => "NAD83 South Dakota S",
+ 32136 => "NAD83 Tennessee",
+ 32137 => "NAD83 Texas North",
+ 32138 => "NAD83 Texas North Cen",
+ 32139 => "NAD83 Texas Central",
+ 32140 => "NAD83 Texas South Cen",
+ 32141 => "NAD83 Texas South",
+ 32142 => "NAD83 Utah North",
+ 32143 => "NAD83 Utah Central",
+ 32144 => "NAD83 Utah South",
+ 32145 => "NAD83 Vermont",
+ 32146 => "NAD83 Virginia North",
+ 32147 => "NAD83 Virginia South",
+ 32148 => "NAD83 Washington North",
+ 32149 => "NAD83 Washington South",
+ 32150 => "NAD83 West Virginia N",
+ 32151 => "NAD83 West Virginia S",
+ 32152 => "NAD83 Wisconsin North",
+ 32153 => "NAD83 Wisconsin Cen",
+ 32154 => "NAD83 Wisconsin South",
+ 32155 => "NAD83 Wyoming East",
+ 32156 => "NAD83 Wyoming E Cen",
+ 32157 => "NAD83 Wyoming W Cen",
+ 32158 => "NAD83 Wyoming West",
+ 32161 => "NAD83 Puerto Rico Virgin Is",
+ 32201 => "WGS72 UTM zone 1N",
+ 32202 => "WGS72 UTM zone 2N",
+ 32203 => "WGS72 UTM zone 3N",
+ 32204 => "WGS72 UTM zone 4N",
+ 32205 => "WGS72 UTM zone 5N",
+ 32206 => "WGS72 UTM zone 6N",
+ 32207 => "WGS72 UTM zone 7N",
+ 32208 => "WGS72 UTM zone 8N",
+ 32209 => "WGS72 UTM zone 9N",
+ 32210 => "WGS72 UTM zone 10N",
+ 32211 => "WGS72 UTM zone 11N",
+ 32212 => "WGS72 UTM zone 12N",
+ 32213 => "WGS72 UTM zone 13N",
+ 32214 => "WGS72 UTM zone 14N",
+ 32215 => "WGS72 UTM zone 15N",
+ 32216 => "WGS72 UTM zone 16N",
+ 32217 => "WGS72 UTM zone 17N",
+ 32218 => "WGS72 UTM zone 18N",
+ 32219 => "WGS72 UTM zone 19N",
+ 32220 => "WGS72 UTM zone 20N",
+ 32221 => "WGS72 UTM zone 21N",
+ 32222 => "WGS72 UTM zone 22N",
+ 32223 => "WGS72 UTM zone 23N",
+ 32224 => "WGS72 UTM zone 24N",
+ 32225 => "WGS72 UTM zone 25N",
+ 32226 => "WGS72 UTM zone 26N",
+ 32227 => "WGS72 UTM zone 27N",
+ 32228 => "WGS72 UTM zone 28N",
+ 32229 => "WGS72 UTM zone 29N",
+ 32230 => "WGS72 UTM zone 30N",
+ 32231 => "WGS72 UTM zone 31N",
+ 32232 => "WGS72 UTM zone 32N",
+ 32233 => "WGS72 UTM zone 33N",
+ 32234 => "WGS72 UTM zone 34N",
+ 32235 => "WGS72 UTM zone 35N",
+ 32236 => "WGS72 UTM zone 36N",
+ 32237 => "WGS72 UTM zone 37N",
+ 32238 => "WGS72 UTM zone 38N",
+ 32239 => "WGS72 UTM zone 39N",
+ 32240 => "WGS72 UTM zone 40N",
+ 32241 => "WGS72 UTM zone 41N",
+ 32242 => "WGS72 UTM zone 42N",
+ 32243 => "WGS72 UTM zone 43N",
+ 32244 => "WGS72 UTM zone 44N",
+ 32245 => "WGS72 UTM zone 45N",
+ 32246 => "WGS72 UTM zone 46N",
+ 32247 => "WGS72 UTM zone 47N",
+ 32248 => "WGS72 UTM zone 48N",
+ 32249 => "WGS72 UTM zone 49N",
+ 32250 => "WGS72 UTM zone 50N",
+ 32251 => "WGS72 UTM zone 51N",
+ 32252 => "WGS72 UTM zone 52N",
+ 32253 => "WGS72 UTM zone 53N",
+ 32254 => "WGS72 UTM zone 54N",
+ 32255 => "WGS72 UTM zone 55N",
+ 32256 => "WGS72 UTM zone 56N",
+ 32257 => "WGS72 UTM zone 57N",
+ 32258 => "WGS72 UTM zone 58N",
+ 32259 => "WGS72 UTM zone 59N",
+ 32260 => "WGS72 UTM zone 60N",
+ 32301 => "WGS72 UTM zone 1S",
+ 32302 => "WGS72 UTM zone 2S",
+ 32303 => "WGS72 UTM zone 3S",
+ 32304 => "WGS72 UTM zone 4S",
+ 32305 => "WGS72 UTM zone 5S",
+ 32306 => "WGS72 UTM zone 6S",
+ 32307 => "WGS72 UTM zone 7S",
+ 32308 => "WGS72 UTM zone 8S",
+ 32309 => "WGS72 UTM zone 9S",
+ 32310 => "WGS72 UTM zone 10S",
+ 32311 => "WGS72 UTM zone 11S",
+ 32312 => "WGS72 UTM zone 12S",
+ 32313 => "WGS72 UTM zone 13S",
+ 32314 => "WGS72 UTM zone 14S",
+ 32315 => "WGS72 UTM zone 15S",
+ 32316 => "WGS72 UTM zone 16S",
+ 32317 => "WGS72 UTM zone 17S",
+ 32318 => "WGS72 UTM zone 18S",
+ 32319 => "WGS72 UTM zone 19S",
+ 32320 => "WGS72 UTM zone 20S",
+ 32321 => "WGS72 UTM zone 21S",
+ 32322 => "WGS72 UTM zone 22S",
+ 32323 => "WGS72 UTM zone 23S",
+ 32324 => "WGS72 UTM zone 24S",
+ 32325 => "WGS72 UTM zone 25S",
+ 32326 => "WGS72 UTM zone 26S",
+ 32327 => "WGS72 UTM zone 27S",
+ 32328 => "WGS72 UTM zone 28S",
+ 32329 => "WGS72 UTM zone 29S",
+ 32330 => "WGS72 UTM zone 30S",
+ 32331 => "WGS72 UTM zone 31S",
+ 32332 => "WGS72 UTM zone 32S",
+ 32333 => "WGS72 UTM zone 33S",
+ 32334 => "WGS72 UTM zone 34S",
+ 32335 => "WGS72 UTM zone 35S",
+ 32336 => "WGS72 UTM zone 36S",
+ 32337 => "WGS72 UTM zone 37S",
+ 32338 => "WGS72 UTM zone 38S",
+ 32339 => "WGS72 UTM zone 39S",
+ 32340 => "WGS72 UTM zone 40S",
+ 32341 => "WGS72 UTM zone 41S",
+ 32342 => "WGS72 UTM zone 42S",
+ 32343 => "WGS72 UTM zone 43S",
+ 32344 => "WGS72 UTM zone 44S",
+ 32345 => "WGS72 UTM zone 45S",
+ 32346 => "WGS72 UTM zone 46S",
+ 32347 => "WGS72 UTM zone 47S",
+ 32348 => "WGS72 UTM zone 48S",
+ 32349 => "WGS72 UTM zone 49S",
+ 32350 => "WGS72 UTM zone 50S",
+ 32351 => "WGS72 UTM zone 51S",
+ 32352 => "WGS72 UTM zone 52S",
+ 32353 => "WGS72 UTM zone 53S",
+ 32354 => "WGS72 UTM zone 54S",
+ 32355 => "WGS72 UTM zone 55S",
+ 32356 => "WGS72 UTM zone 56S",
+ 32357 => "WGS72 UTM zone 57S",
+ 32358 => "WGS72 UTM zone 58S",
+ 32359 => "WGS72 UTM zone 59S",
+ 32360 => "WGS72 UTM zone 60S",
+ 32401 => "WGS72BE UTM zone 1N",
+ 32402 => "WGS72BE UTM zone 2N",
+ 32403 => "WGS72BE UTM zone 3N",
+ 32404 => "WGS72BE UTM zone 4N",
+ 32405 => "WGS72BE UTM zone 5N",
+ 32406 => "WGS72BE UTM zone 6N",
+ 32407 => "WGS72BE UTM zone 7N",
+ 32408 => "WGS72BE UTM zone 8N",
+ 32409 => "WGS72BE UTM zone 9N",
+ 32410 => "WGS72BE UTM zone 10N",
+ 32411 => "WGS72BE UTM zone 11N",
+ 32412 => "WGS72BE UTM zone 12N",
+ 32413 => "WGS72BE UTM zone 13N",
+ 32414 => "WGS72BE UTM zone 14N",
+ 32415 => "WGS72BE UTM zone 15N",
+ 32416 => "WGS72BE UTM zone 16N",
+ 32417 => "WGS72BE UTM zone 17N",
+ 32418 => "WGS72BE UTM zone 18N",
+ 32419 => "WGS72BE UTM zone 19N",
+ 32420 => "WGS72BE UTM zone 20N",
+ 32421 => "WGS72BE UTM zone 21N",
+ 32422 => "WGS72BE UTM zone 22N",
+ 32423 => "WGS72BE UTM zone 23N",
+ 32424 => "WGS72BE UTM zone 24N",
+ 32425 => "WGS72BE UTM zone 25N",
+ 32426 => "WGS72BE UTM zone 26N",
+ 32427 => "WGS72BE UTM zone 27N",
+ 32428 => "WGS72BE UTM zone 28N",
+ 32429 => "WGS72BE UTM zone 29N",
+ 32430 => "WGS72BE UTM zone 30N",
+ 32431 => "WGS72BE UTM zone 31N",
+ 32432 => "WGS72BE UTM zone 32N",
+ 32433 => "WGS72BE UTM zone 33N",
+ 32434 => "WGS72BE UTM zone 34N",
+ 32435 => "WGS72BE UTM zone 35N",
+ 32436 => "WGS72BE UTM zone 36N",
+ 32437 => "WGS72BE UTM zone 37N",
+ 32438 => "WGS72BE UTM zone 38N",
+ 32439 => "WGS72BE UTM zone 39N",
+ 32440 => "WGS72BE UTM zone 40N",
+ 32441 => "WGS72BE UTM zone 41N",
+ 32442 => "WGS72BE UTM zone 42N",
+ 32443 => "WGS72BE UTM zone 43N",
+ 32444 => "WGS72BE UTM zone 44N",
+ 32445 => "WGS72BE UTM zone 45N",
+ 32446 => "WGS72BE UTM zone 46N",
+ 32447 => "WGS72BE UTM zone 47N",
+ 32448 => "WGS72BE UTM zone 48N",
+ 32449 => "WGS72BE UTM zone 49N",
+ 32450 => "WGS72BE UTM zone 50N",
+ 32451 => "WGS72BE UTM zone 51N",
+ 32452 => "WGS72BE UTM zone 52N",
+ 32453 => "WGS72BE UTM zone 53N",
+ 32454 => "WGS72BE UTM zone 54N",
+ 32455 => "WGS72BE UTM zone 55N",
+ 32456 => "WGS72BE UTM zone 56N",
+ 32457 => "WGS72BE UTM zone 57N",
+ 32458 => "WGS72BE UTM zone 58N",
+ 32459 => "WGS72BE UTM zone 59N",
+ 32460 => "WGS72BE UTM zone 60N",
+ 32501 => "WGS72BE UTM zone 1S",
+ 32502 => "WGS72BE UTM zone 2S",
+ 32503 => "WGS72BE UTM zone 3S",
+ 32504 => "WGS72BE UTM zone 4S",
+ 32505 => "WGS72BE UTM zone 5S",
+ 32506 => "WGS72BE UTM zone 6S",
+ 32507 => "WGS72BE UTM zone 7S",
+ 32508 => "WGS72BE UTM zone 8S",
+ 32509 => "WGS72BE UTM zone 9S",
+ 32510 => "WGS72BE UTM zone 10S",
+ 32511 => "WGS72BE UTM zone 11S",
+ 32512 => "WGS72BE UTM zone 12S",
+ 32513 => "WGS72BE UTM zone 13S",
+ 32514 => "WGS72BE UTM zone 14S",
+ 32515 => "WGS72BE UTM zone 15S",
+ 32516 => "WGS72BE UTM zone 16S",
+ 32517 => "WGS72BE UTM zone 17S",
+ 32518 => "WGS72BE UTM zone 18S",
+ 32519 => "WGS72BE UTM zone 19S",
+ 32520 => "WGS72BE UTM zone 20S",
+ 32521 => "WGS72BE UTM zone 21S",
+ 32522 => "WGS72BE UTM zone 22S",
+ 32523 => "WGS72BE UTM zone 23S",
+ 32524 => "WGS72BE UTM zone 24S",
+ 32525 => "WGS72BE UTM zone 25S",
+ 32526 => "WGS72BE UTM zone 26S",
+ 32527 => "WGS72BE UTM zone 27S",
+ 32528 => "WGS72BE UTM zone 28S",
+ 32529 => "WGS72BE UTM zone 29S",
+ 32530 => "WGS72BE UTM zone 30S",
+ 32531 => "WGS72BE UTM zone 31S",
+ 32532 => "WGS72BE UTM zone 32S",
+ 32533 => "WGS72BE UTM zone 33S",
+ 32534 => "WGS72BE UTM zone 34S",
+ 32535 => "WGS72BE UTM zone 35S",
+ 32536 => "WGS72BE UTM zone 36S",
+ 32537 => "WGS72BE UTM zone 37S",
+ 32538 => "WGS72BE UTM zone 38S",
+ 32539 => "WGS72BE UTM zone 39S",
+ 32540 => "WGS72BE UTM zone 40S",
+ 32541 => "WGS72BE UTM zone 41S",
+ 32542 => "WGS72BE UTM zone 42S",
+ 32543 => "WGS72BE UTM zone 43S",
+ 32544 => "WGS72BE UTM zone 44S",
+ 32545 => "WGS72BE UTM zone 45S",
+ 32546 => "WGS72BE UTM zone 46S",
+ 32547 => "WGS72BE UTM zone 47S",
+ 32548 => "WGS72BE UTM zone 48S",
+ 32549 => "WGS72BE UTM zone 49S",
+ 32550 => "WGS72BE UTM zone 50S",
+ 32551 => "WGS72BE UTM zone 51S",
+ 32552 => "WGS72BE UTM zone 52S",
+ 32553 => "WGS72BE UTM zone 53S",
+ 32554 => "WGS72BE UTM zone 54S",
+ 32555 => "WGS72BE UTM zone 55S",
+ 32556 => "WGS72BE UTM zone 56S",
+ 32557 => "WGS72BE UTM zone 57S",
+ 32558 => "WGS72BE UTM zone 58S",
+ 32559 => "WGS72BE UTM zone 59S",
+ 32560 => "WGS72BE UTM zone 60S",
+ 32601 => "WGS84 UTM zone 1N",
+ 32602 => "WGS84 UTM zone 2N",
+ 32603 => "WGS84 UTM zone 3N",
+ 32604 => "WGS84 UTM zone 4N",
+ 32605 => "WGS84 UTM zone 5N",
+ 32606 => "WGS84 UTM zone 6N",
+ 32607 => "WGS84 UTM zone 7N",
+ 32608 => "WGS84 UTM zone 8N",
+ 32609 => "WGS84 UTM zone 9N",
+ 32610 => "WGS84 UTM zone 10N",
+ 32611 => "WGS84 UTM zone 11N",
+ 32612 => "WGS84 UTM zone 12N",
+ 32613 => "WGS84 UTM zone 13N",
+ 32614 => "WGS84 UTM zone 14N",
+ 32615 => "WGS84 UTM zone 15N",
+ 32616 => "WGS84 UTM zone 16N",
+ 32617 => "WGS84 UTM zone 17N",
+ 32618 => "WGS84 UTM zone 18N",
+ 32619 => "WGS84 UTM zone 19N",
+ 32620 => "WGS84 UTM zone 20N",
+ 32621 => "WGS84 UTM zone 21N",
+ 32622 => "WGS84 UTM zone 22N",
+ 32623 => "WGS84 UTM zone 23N",
+ 32624 => "WGS84 UTM zone 24N",
+ 32625 => "WGS84 UTM zone 25N",
+ 32626 => "WGS84 UTM zone 26N",
+ 32627 => "WGS84 UTM zone 27N",
+ 32628 => "WGS84 UTM zone 28N",
+ 32629 => "WGS84 UTM zone 29N",
+ 32630 => "WGS84 UTM zone 30N",
+ 32631 => "WGS84 UTM zone 31N",
+ 32632 => "WGS84 UTM zone 32N",
+ 32633 => "WGS84 UTM zone 33N",
+ 32634 => "WGS84 UTM zone 34N",
+ 32635 => "WGS84 UTM zone 35N",
+ 32636 => "WGS84 UTM zone 36N",
+ 32637 => "WGS84 UTM zone 37N",
+ 32638 => "WGS84 UTM zone 38N",
+ 32639 => "WGS84 UTM zone 39N",
+ 32640 => "WGS84 UTM zone 40N",
+ 32641 => "WGS84 UTM zone 41N",
+ 32642 => "WGS84 UTM zone 42N",
+ 32643 => "WGS84 UTM zone 43N",
+ 32644 => "WGS84 UTM zone 44N",
+ 32645 => "WGS84 UTM zone 45N",
+ 32646 => "WGS84 UTM zone 46N",
+ 32647 => "WGS84 UTM zone 47N",
+ 32648 => "WGS84 UTM zone 48N",
+ 32649 => "WGS84 UTM zone 49N",
+ 32650 => "WGS84 UTM zone 50N",
+ 32651 => "WGS84 UTM zone 51N",
+ 32652 => "WGS84 UTM zone 52N",
+ 32653 => "WGS84 UTM zone 53N",
+ 32654 => "WGS84 UTM zone 54N",
+ 32655 => "WGS84 UTM zone 55N",
+ 32656 => "WGS84 UTM zone 56N",
+ 32657 => "WGS84 UTM zone 57N",
+ 32658 => "WGS84 UTM zone 58N",
+ 32659 => "WGS84 UTM zone 59N",
+ 32660 => "WGS84 UTM zone 60N",
+ 32701 => "WGS84 UTM zone 1S",
+ 32702 => "WGS84 UTM zone 2S",
+ 32703 => "WGS84 UTM zone 3S",
+ 32704 => "WGS84 UTM zone 4S",
+ 32705 => "WGS84 UTM zone 5S",
+ 32706 => "WGS84 UTM zone 6S",
+ 32707 => "WGS84 UTM zone 7S",
+ 32708 => "WGS84 UTM zone 8S",
+ 32709 => "WGS84 UTM zone 9S",
+ 32710 => "WGS84 UTM zone 10S",
+ 32711 => "WGS84 UTM zone 11S",
+ 32712 => "WGS84 UTM zone 12S",
+ 32713 => "WGS84 UTM zone 13S",
+ 32714 => "WGS84 UTM zone 14S",
+ 32715 => "WGS84 UTM zone 15S",
+ 32716 => "WGS84 UTM zone 16S",
+ 32717 => "WGS84 UTM zone 17S",
+ 32718 => "WGS84 UTM zone 18S",
+ 32719 => "WGS84 UTM zone 19S",
+ 32720 => "WGS84 UTM zone 20S",
+ 32721 => "WGS84 UTM zone 21S",
+ 32722 => "WGS84 UTM zone 22S",
+ 32723 => "WGS84 UTM zone 23S",
+ 32724 => "WGS84 UTM zone 24S",
+ 32725 => "WGS84 UTM zone 25S",
+ 32726 => "WGS84 UTM zone 26S",
+ 32727 => "WGS84 UTM zone 27S",
+ 32728 => "WGS84 UTM zone 28S",
+ 32729 => "WGS84 UTM zone 29S",
+ 32730 => "WGS84 UTM zone 30S",
+ 32731 => "WGS84 UTM zone 31S",
+ 32732 => "WGS84 UTM zone 32S",
+ 32733 => "WGS84 UTM zone 33S",
+ 32734 => "WGS84 UTM zone 34S",
+ 32735 => "WGS84 UTM zone 35S",
+ 32736 => "WGS84 UTM zone 36S",
+ 32737 => "WGS84 UTM zone 37S",
+ 32738 => "WGS84 UTM zone 38S",
+ 32739 => "WGS84 UTM zone 39S",
+ 32740 => "WGS84 UTM zone 40S",
+ 32741 => "WGS84 UTM zone 41S",
+ 32742 => "WGS84 UTM zone 42S",
+ 32743 => "WGS84 UTM zone 43S",
+ 32744 => "WGS84 UTM zone 44S",
+ 32745 => "WGS84 UTM zone 45S",
+ 32746 => "WGS84 UTM zone 46S",
+ 32747 => "WGS84 UTM zone 47S",
+ 32748 => "WGS84 UTM zone 48S",
+ 32749 => "WGS84 UTM zone 49S",
+ 32750 => "WGS84 UTM zone 50S",
+ 32751 => "WGS84 UTM zone 51S",
+ 32752 => "WGS84 UTM zone 52S",
+ 32753 => "WGS84 UTM zone 53S",
+ 32754 => "WGS84 UTM zone 54S",
+ 32755 => "WGS84 UTM zone 55S",
+ 32756 => "WGS84 UTM zone 56S",
+ 32757 => "WGS84 UTM zone 57S",
+ 32758 => "WGS84 UTM zone 58S",
+ 32759 => "WGS84 UTM zone 59S",
+ 32760 => "WGS84 UTM zone 60S",
+ 32767 => "User Defined",
+ _ => "Unknown (" + value + ")"
+ };
+ }
+
+ public string? GetProjectionDescription()
+ {
+ if (!Directory.TryGetUInt16(GeoTiffDirectory.TagProjection, out ushort value))
+ return null;
+
+ return value switch
+ {
+ 10101 => "Alabama CS27 East",
+ 10102 => "Alabama CS27 West",
+ 10131 => "Alabama CS83 East",
+ 10132 => "Alabama CS83 West",
+ 10201 => "Arizona Coordinate System east",
+ 10202 => "Arizona Coordinate System Central",
+ 10203 => "Arizona Coordinate System west",
+ 10231 => "Arizona CS83 east",
+ 10232 => "Arizona CS83 Central",
+ 10233 => "Arizona CS83 west",
+ 10301 => "Arkansas CS27 North",
+ 10302 => "Arkansas CS27 South",
+ 10331 => "Arkansas CS83 North",
+ 10332 => "Arkansas CS83 South",
+ 10401 => "California CS27 I",
+ 10402 => "California CS27 II",
+ 10403 => "California CS27 III",
+ 10404 => "California CS27 IV",
+ 10405 => "California CS27 V",
+ 10406 => "California CS27 VI",
+ 10407 => "California CS27 VII",
+ 10431 => "California CS83 1",
+ 10432 => "California CS83 2",
+ 10433 => "California CS83 3",
+ 10434 => "California CS83 4",
+ 10435 => "California CS83 5",
+ 10436 => "California CS83 6",
+ 10501 => "Colorado CS27 North",
+ 10502 => "Colorado CS27 Central",
+ 10503 => "Colorado CS27 South",
+ 10531 => "Colorado CS83 North",
+ 10532 => "Colorado CS83 Central",
+ 10533 => "Colorado CS83 South",
+ 10600 => "Connecticut CS27",
+ 10630 => "Connecticut CS83",
+ 10700 => "Delaware CS27",
+ 10730 => "Delaware CS83",
+ 10901 => "Florida CS27 East",
+ 10902 => "Florida CS27 West",
+ 10903 => "Florida CS27 North",
+ 10931 => "Florida CS83 East",
+ 10932 => "Florida CS83 West",
+ 10933 => "Florida CS83 North",
+ 11001 => "Georgia CS27 East",
+ 11002 => "Georgia CS27 West",
+ 11031 => "Georgia CS83 East",
+ 11032 => "Georgia CS83 West",
+ 11101 => "Idaho CS27 East",
+ 11102 => "Idaho CS27 Central",
+ 11103 => "Idaho CS27 West",
+ 11131 => "Idaho CS83 East",
+ 11132 => "Idaho CS83 Central",
+ 11133 => "Idaho CS83 West",
+ 11201 => "Illinois CS27 East",
+ 11202 => "Illinois CS27 West",
+ 11231 => "Illinois CS83 East",
+ 11232 => "Illinois CS83 West",
+ 11301 => "Indiana CS27 East",
+ 11302 => "Indiana CS27 West",
+ 11331 => "Indiana CS83 East",
+ 11332 => "Indiana CS83 West",
+ 11401 => "Iowa CS27 North",
+ 11402 => "Iowa CS27 South",
+ 11431 => "Iowa CS83 North",
+ 11432 => "Iowa CS83 South",
+ 11501 => "Kansas CS27 North",
+ 11502 => "Kansas CS27 South",
+ 11531 => "Kansas CS83 North",
+ 11532 => "Kansas CS83 South",
+ 11601 => "Kentucky CS27 North",
+ 11602 => "Kentucky CS27 South",
+ 11631 => "Kentucky CS83 North",
+ 11632 => "Kentucky CS83 South",
+ 11701 => "Louisiana CS27 North",
+ 11702 => "Louisiana CS27 South",
+ 11731 => "Louisiana CS83 North",
+ 11732 => "Louisiana CS83 South",
+ 11801 => "Maine CS27 East",
+ 11802 => "Maine CS27 West",
+ 11831 => "Maine CS83 East",
+ 11832 => "Maine CS83 West",
+ 11900 => "Maryland CS27",
+ 11930 => "Maryland CS83",
+ 12001 => "Massachusetts CS27 Mainland",
+ 12002 => "Massachusetts CS27 Island",
+ 12031 => "Massachusetts CS83 Mainland",
+ 12032 => "Massachusetts CS83 Island",
+ 12101 => "Michigan State Plane East",
+ 12102 => "Michigan State Plane Old Central",
+ 12103 => "Michigan State Plane West",
+ 12111 => "Michigan CS27 North",
+ 12112 => "Michigan CS27 Central",
+ 12113 => "Michigan CS27 South",
+ 12141 => "Michigan CS83 North",
+ 12142 => "Michigan CS83 Central",
+ 12143 => "Michigan CS83 South",
+ 12201 => "Minnesota CS27 North",
+ 12202 => "Minnesota CS27 Central",
+ 12203 => "Minnesota CS27 South",
+ 12231 => "Minnesota CS83 North",
+ 12232 => "Minnesota CS83 Central",
+ 12233 => "Minnesota CS83 South",
+ 12301 => "Mississippi CS27 East",
+ 12302 => "Mississippi CS27 West",
+ 12331 => "Mississippi CS83 East",
+ 12332 => "Mississippi CS83 West",
+ 12401 => "Missouri CS27 East",
+ 12402 => "Missouri CS27 Central",
+ 12403 => "Missouri CS27 West",
+ 12431 => "Missouri CS83 East",
+ 12432 => "Missouri CS83 Central",
+ 12433 => "Missouri CS83 West",
+ 12501 => "Montana CS27 North",
+ 12502 => "Montana CS27 Central",
+ 12503 => "Montana CS27 South",
+ 12530 => "Montana CS83",
+ 12601 => "Nebraska CS27 North",
+ 12602 => "Nebraska CS27 South",
+ 12630 => "Nebraska CS83",
+ 12701 => "Nevada CS27 East",
+ 12702 => "Nevada CS27 Central",
+ 12703 => "Nevada CS27 West",
+ 12731 => "Nevada CS83 East",
+ 12732 => "Nevada CS83 Central",
+ 12733 => "Nevada CS83 West",
+ 12800 => "New Hampshire CS27",
+ 12830 => "New Hampshire CS83",
+ 12900 => "New Jersey CS27",
+ 12930 => "New Jersey CS83",
+ 13001 => "New Mexico CS27 East",
+ 13002 => "New Mexico CS27 Central",
+ 13003 => "New Mexico CS27 West",
+ 13031 => "New Mexico CS83 East",
+ 13032 => "New Mexico CS83 Central",
+ 13033 => "New Mexico CS83 West",
+ 13101 => "New York CS27 East",
+ 13102 => "New York CS27 Central",
+ 13103 => "New York CS27 West",
+ 13104 => "New York CS27 Long Island",
+ 13131 => "New York CS83 East",
+ 13132 => "New York CS83 Central",
+ 13133 => "New York CS83 West",
+ 13134 => "New York CS83 Long Island",
+ 13200 => "North Carolina CS27",
+ 13230 => "North Carolina CS83",
+ 13301 => "North Dakota CS27 North",
+ 13302 => "North Dakota CS27 South",
+ 13331 => "North Dakota CS83 North",
+ 13332 => "North Dakota CS83 South",
+ 13401 => "Ohio CS27 North",
+ 13402 => "Ohio CS27 South",
+ 13431 => "Ohio CS83 North",
+ 13432 => "Ohio CS83 South",
+ 13501 => "Oklahoma CS27 North",
+ 13502 => "Oklahoma CS27 South",
+ 13531 => "Oklahoma CS83 North",
+ 13532 => "Oklahoma CS83 South",
+ 13601 => "Oregon CS27 North",
+ 13602 => "Oregon CS27 South",
+ 13631 => "Oregon CS83 North",
+ 13632 => "Oregon CS83 South",
+ 13701 => "Pennsylvania CS27 North",
+ 13702 => "Pennsylvania CS27 South",
+ 13731 => "Pennsylvania CS83 North",
+ 13732 => "Pennsylvania CS83 South",
+ 13800 => "Rhode Island CS27",
+ 13830 => "Rhode Island CS83",
+ 13901 => "South Carolina CS27 North",
+ 13902 => "South Carolina CS27 South",
+ 13930 => "South Carolina CS83",
+ 14001 => "South Dakota CS27 North",
+ 14002 => "South Dakota CS27 South",
+ 14031 => "South Dakota CS83 North",
+ 14032 => "South Dakota CS83 South",
+ 14100 => "Tennessee CS27",
+ 14130 => "Tennessee CS83",
+ 14201 => "Texas CS27 North",
+ 14202 => "Texas CS27 North Central",
+ 14203 => "Texas CS27 Central",
+ 14204 => "Texas CS27 South Central",
+ 14205 => "Texas CS27 South",
+ 14231 => "Texas CS83 North",
+ 14232 => "Texas CS83 North Central",
+ 14233 => "Texas CS83 Central",
+ 14234 => "Texas CS83 South Central",
+ 14235 => "Texas CS83 South",
+ 14301 => "Utah CS27 North",
+ 14302 => "Utah CS27 Central",
+ 14303 => "Utah CS27 South",
+ 14331 => "Utah CS83 North",
+ 14332 => "Utah CS83 Central",
+ 14333 => "Utah CS83 South",
+ 14400 => "Vermont CS27",
+ 14430 => "Vermont CS83",
+ 14501 => "Virginia CS27 North",
+ 14502 => "Virginia CS27 South",
+ 14531 => "Virginia CS83 North",
+ 14532 => "Virginia CS83 South",
+ 14601 => "Washington CS27 North",
+ 14602 => "Washington CS27 South",
+ 14631 => "Washington CS83 North",
+ 14632 => "Washington CS83 South",
+ 14701 => "West Virginia CS27 North",
+ 14702 => "West Virginia CS27 South",
+ 14731 => "West Virginia CS83 North",
+ 14732 => "West Virginia CS83 South",
+ 14801 => "Wisconsin CS27 North",
+ 14802 => "Wisconsin CS27 Central",
+ 14803 => "Wisconsin CS27 South",
+ 14831 => "Wisconsin CS83 North",
+ 14832 => "Wisconsin CS83 Central",
+ 14833 => "Wisconsin CS83 South",
+ 14901 => "Wyoming CS27 East",
+ 14902 => "Wyoming CS27 East Central",
+ 14903 => "Wyoming CS27 West Central",
+ 14904 => "Wyoming CS27 West",
+ 14931 => "Wyoming CS83 East",
+ 14932 => "Wyoming CS83 East Central",
+ 14933 => "Wyoming CS83 West Central",
+ 14934 => "Wyoming CS83 West",
+ 15001 => "Alaska CS27 1",
+ 15002 => "Alaska CS27 2",
+ 15003 => "Alaska CS27 3",
+ 15004 => "Alaska CS27 4",
+ 15005 => "Alaska CS27 5",
+ 15006 => "Alaska CS27 6",
+ 15007 => "Alaska CS27 7",
+ 15008 => "Alaska CS27 8",
+ 15009 => "Alaska CS27 9",
+ 15010 => "Alaska CS27 10",
+ 15031 => "Alaska CS83 1",
+ 15032 => "Alaska CS83 2",
+ 15033 => "Alaska CS83 3",
+ 15034 => "Alaska CS83 4",
+ 15035 => "Alaska CS83 5",
+ 15036 => "Alaska CS83 6",
+ 15037 => "Alaska CS83 7",
+ 15038 => "Alaska CS83 8",
+ 15039 => "Alaska CS83 9",
+ 15040 => "Alaska CS83 10",
+ 15101 => "Hawaii CS27 1",
+ 15102 => "Hawaii CS27 2",
+ 15103 => "Hawaii CS27 3",
+ 15104 => "Hawaii CS27 4",
+ 15105 => "Hawaii CS27 5",
+ 15131 => "Hawaii CS83 1",
+ 15132 => "Hawaii CS83 2",
+ 15133 => "Hawaii CS83 3",
+ 15134 => "Hawaii CS83 4",
+ 15135 => "Hawaii CS83 5",
+ 15201 => "Puerto Rico CS27",
+ 15202 => "St Croix",
+ 15230 => "Puerto Rico Virgin Is",
+ 15302 => "Kentucky CS27",
+ 15303 => "Kentucky CS83 North",
+ 15914 => "BLM 14N feet",
+ 15915 => "BLM 15N feet",
+ 15916 => "BLM 16N feet",
+ 15917 => "BLM 17N feet",
+ 16001 => "UTM zone 1N",
+ 16002 => "UTM zone 2N",
+ 16003 => "UTM zone 3N",
+ 16004 => "UTM zone 4N",
+ 16005 => "UTM zone 5N",
+ 16006 => "UTM zone 6N",
+ 16007 => "UTM zone 7N",
+ 16008 => "UTM zone 8N",
+ 16009 => "UTM zone 9N",
+ 16010 => "UTM zone 10N",
+ 16011 => "UTM zone 11N",
+ 16012 => "UTM zone 12N",
+ 16013 => "UTM zone 13N",
+ 16014 => "UTM zone 14N",
+ 16015 => "UTM zone 15N",
+ 16016 => "UTM zone 16N",
+ 16017 => "UTM zone 17N",
+ 16018 => "UTM zone 18N",
+ 16019 => "UTM zone 19N",
+ 16020 => "UTM zone 20N",
+ 16021 => "UTM zone 21N",
+ 16022 => "UTM zone 22N",
+ 16023 => "UTM zone 23N",
+ 16024 => "UTM zone 24N",
+ 16025 => "UTM zone 25N",
+ 16026 => "UTM zone 26N",
+ 16027 => "UTM zone 27N",
+ 16028 => "UTM zone 28N",
+ 16029 => "UTM zone 29N",
+ 16030 => "UTM zone 30N",
+ 16031 => "UTM zone 31N",
+ 16032 => "UTM zone 32N",
+ 16033 => "UTM zone 33N",
+ 16034 => "UTM zone 34N",
+ 16035 => "UTM zone 35N",
+ 16036 => "UTM zone 36N",
+ 16037 => "UTM zone 37N",
+ 16038 => "UTM zone 38N",
+ 16039 => "UTM zone 39N",
+ 16040 => "UTM zone 40N",
+ 16041 => "UTM zone 41N",
+ 16042 => "UTM zone 42N",
+ 16043 => "UTM zone 43N",
+ 16044 => "UTM zone 44N",
+ 16045 => "UTM zone 45N",
+ 16046 => "UTM zone 46N",
+ 16047 => "UTM zone 47N",
+ 16048 => "UTM zone 48N",
+ 16049 => "UTM zone 49N",
+ 16050 => "UTM zone 50N",
+ 16051 => "UTM zone 51N",
+ 16052 => "UTM zone 52N",
+ 16053 => "UTM zone 53N",
+ 16054 => "UTM zone 54N",
+ 16055 => "UTM zone 55N",
+ 16056 => "UTM zone 56N",
+ 16057 => "UTM zone 57N",
+ 16058 => "UTM zone 58N",
+ 16059 => "UTM zone 59N",
+ 16060 => "UTM zone 60N",
+ 16101 => "UTM zone 1S",
+ 16102 => "UTM zone 2S",
+ 16103 => "UTM zone 3S",
+ 16104 => "UTM zone 4S",
+ 16105 => "UTM zone 5S",
+ 16106 => "UTM zone 6S",
+ 16107 => "UTM zone 7S",
+ 16108 => "UTM zone 8S",
+ 16109 => "UTM zone 9S",
+ 16110 => "UTM zone 10S",
+ 16111 => "UTM zone 11S",
+ 16112 => "UTM zone 12S",
+ 16113 => "UTM zone 13S",
+ 16114 => "UTM zone 14S",
+ 16115 => "UTM zone 15S",
+ 16116 => "UTM zone 16S",
+ 16117 => "UTM zone 17S",
+ 16118 => "UTM zone 18S",
+ 16119 => "UTM zone 19S",
+ 16120 => "UTM zone 20S",
+ 16121 => "UTM zone 21S",
+ 16122 => "UTM zone 22S",
+ 16123 => "UTM zone 23S",
+ 16124 => "UTM zone 24S",
+ 16125 => "UTM zone 25S",
+ 16126 => "UTM zone 26S",
+ 16127 => "UTM zone 27S",
+ 16128 => "UTM zone 28S",
+ 16129 => "UTM zone 29S",
+ 16130 => "UTM zone 30S",
+ 16131 => "UTM zone 31S",
+ 16132 => "UTM zone 32S",
+ 16133 => "UTM zone 33S",
+ 16134 => "UTM zone 34S",
+ 16135 => "UTM zone 35S",
+ 16136 => "UTM zone 36S",
+ 16137 => "UTM zone 37S",
+ 16138 => "UTM zone 38S",
+ 16139 => "UTM zone 39S",
+ 16140 => "UTM zone 40S",
+ 16141 => "UTM zone 41S",
+ 16142 => "UTM zone 42S",
+ 16143 => "UTM zone 43S",
+ 16144 => "UTM zone 44S",
+ 16145 => "UTM zone 45S",
+ 16146 => "UTM zone 46S",
+ 16147 => "UTM zone 47S",
+ 16148 => "UTM zone 48S",
+ 16149 => "UTM zone 49S",
+ 16150 => "UTM zone 50S",
+ 16151 => "UTM zone 51S",
+ 16152 => "UTM zone 52S",
+ 16153 => "UTM zone 53S",
+ 16154 => "UTM zone 54S",
+ 16155 => "UTM zone 55S",
+ 16156 => "UTM zone 56S",
+ 16157 => "UTM zone 57S",
+ 16158 => "UTM zone 58S",
+ 16159 => "UTM zone 59S",
+ 16160 => "UTM zone 60S",
+ 16200 => "Gauss Kruger zone 0",
+ 16201 => "Gauss Kruger zone 1",
+ 16202 => "Gauss Kruger zone 2",
+ 16203 => "Gauss Kruger zone 3",
+ 16204 => "Gauss Kruger zone 4",
+ 16205 => "Gauss Kruger zone 5",
+ 17348 => "Map Grid of Australia 48",
+ 17349 => "Map Grid of Australia 49",
+ 17350 => "Map Grid of Australia 50",
+ 17351 => "Map Grid of Australia 51",
+ 17352 => "Map Grid of Australia 52",
+ 17353 => "Map Grid of Australia 53",
+ 17354 => "Map Grid of Australia 54",
+ 17355 => "Map Grid of Australia 55",
+ 17356 => "Map Grid of Australia 56",
+ 17357 => "Map Grid of Australia 57",
+ 17358 => "Map Grid of Australia 58",
+ 17448 => "Australian Map Grid 48",
+ 17449 => "Australian Map Grid 49",
+ 17450 => "Australian Map Grid 50",
+ 17451 => "Australian Map Grid 51",
+ 17452 => "Australian Map Grid 52",
+ 17453 => "Australian Map Grid 53",
+ 17454 => "Australian Map Grid 54",
+ 17455 => "Australian Map Grid 55",
+ 17456 => "Australian Map Grid 56",
+ 17457 => "Australian Map Grid 57",
+ 17458 => "Australian Map Grid 58",
+ 18031 => "Argentina 1",
+ 18032 => "Argentina 2",
+ 18033 => "Argentina 3",
+ 18034 => "Argentina 4",
+ 18035 => "Argentina 5",
+ 18036 => "Argentina 6",
+ 18037 => "Argentina 7",
+ 18051 => "Colombia 3W",
+ 18052 => "Colombia Bogota",
+ 18053 => "Colombia 3E",
+ 18054 => "Colombia 6E",
+ 18072 => "Egypt Red Belt",
+ 18073 => "Egypt Purple Belt",
+ 18074 => "Extended Purple Belt",
+ 18141 => "New Zealand North Island Nat Grid",
+ 18142 => "New Zealand South Island Nat Grid",
+ 19900 => "Bahrain Grid",
+ 19905 => "Netherlands E Indies Equatorial",
+ 19912 => "RSO Borneo",
+ 19926 => "Stereo 70",
+ 32767 => "User Defined",
+ _ => "Unknown (" + value + ")"
+ };
+ }
+
+ public string? GetProjectedCoordinateTransformDescription()
+ {
+ if (!Directory.TryGetUInt16(GeoTiffDirectory.TagProjectedCoordinateTransform, out ushort value))
+ return null;
+
+ return value switch
+ {
+ 1 => "Transverse Mercator",
+ 2 => "Transverse Mercator Modified Alaska",
+ 3 => "Oblique Mercator",
+ 4 => "Oblique Mercator Laborde",
+ 5 => "Oblique Mercator Rosenmund",
+ 6 => "Oblique Mercator Spherical",
+ 7 => "Mercator",
+ 8 => "Lambert Conf Conic 2SP",
+ 9 => "Lambert Conf Conic 1SP",
+ 10 => "Lambert Azim Equal Area",
+ 11 => "Albers Equal Area",
+ 12 => "Azimuthal Equidistant",
+ 13 => "Equidistant Conic",
+ 14 => "Stereographic",
+ 15 => "Polar Stereographic",
+ 16 => "Oblique Stereographic",
+ 17 => "Equirectangular",
+ 18 => "Cassini Soldner",
+ 19 => "Gnomonic",
+ 20 => "Miller Cylindrical",
+ 21 => "Orthographic",
+ 22 => "Polyconic",
+ 23 => "Robinson",
+ 24 => "Sinusoidal",
+ 25 => "VanDerGrinten",
+ 26 => "New Zealand Map Grid",
+ 27 => "Transverse Mercator South Orientated",
+ 28 => "Cylindrical Equal Area",
+ 32767 => "User Defined",
+ _ => "Unknown (" + value + ")"
+ };
+ }
+
+ public string? GetChartFormatDescription()
+ {
+ if (!Directory.TryGetUInt16(GeoTiffDirectory.TagChartFormat, out ushort value))
+ return null;
+
+ return value switch
+ {
+ 47500 => "General",
+ 47501 => "Coastal",
+ 47502 => "Harbor",
+ 47503 => "SailingInternational",
+ 47504 => "SmallCraft Route",
+ 47505 => "SmallCraftArea",
+ 47506 => "SmallCraftFolio",
+ 47507 => "Topographic",
+ 47508 => "Recreation",
+ 47509 => "Index",
+ 47510 => "Inset",
+ _ => "Unknown (" + value + ")"
+ };
+ }
+
+ public string? GetChartSoundingDatumDescription()
+ {
+ if (!Directory.TryGetUInt16(GeoTiffDirectory.TagChartSoundingDatum, out ushort value))
+ return null;
+
+ return value switch
+ {
+ 47600 => "Equatorial Spring Low Water",
+ 47601 => "Indian Spring Low Water",
+ 47602 => "Lowest Astronomical Tide",
+ 47603 => "Lowest Low Water",
+ 47604 => "Lowest Normal Low Water",
+ 47605 => "Mean Higher High Water",
+ 47606 => "Mean High Water",
+ 47607 => "Mean High Water Springs",
+ 47608 => "Mean Lower Low Water",
+ 47609 => "Mean Lower Low Water Springs",
+ 47610 => "Mean Low Water",
+ 47611 => "Mean Sea Level",
+ 47612 => "Tropic Higher High Water",
+ 47613 => "Tropic Lower Low Water",
+ _ => "Unknown (" + value + ")"
+ };
+ }
+ }
+}
diff --git a/MetadataExtractor/Formats/GeoTiff/GeoTiffDirectory.cs b/MetadataExtractor/Formats/GeoTiff/GeoTiffDirectory.cs
new file mode 100644
index 000000000..7b51937fa
--- /dev/null
+++ b/MetadataExtractor/Formats/GeoTiff/GeoTiffDirectory.cs
@@ -0,0 +1,153 @@
+// Copyright (c) Drew Noakes and contributors. All Rights Reserved. Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
+
+using System.Collections.Generic;
+
+namespace MetadataExtractor.Formats.GeoTiff
+{
+ public sealed class GeoTiffDirectory : Directory
+ {
+#pragma warning disable format
+
+ public const int TagModelType = 0x0400;
+ public const int TagRasterType = 0x0401;
+ public const int TagCitation = 0x0402;
+
+ public const int TagGeographicType = 0x0800;
+ public const int TagGeographicCitation = 0x0801;
+ public const int TagGeodeticDatum = 0x0802;
+ public const int TagGeographicPrimeMeridian = 0x0803;
+ public const int TagGeographicLinearUnits = 0x0804;
+ public const int TagGeographicLinearUnitSize = 0x0805;
+ public const int TagGeographicAngularUnits = 0x0806;
+ public const int TagGeographicAngularUnitSize = 0x0807;
+ public const int TagGeographicEllipsoid = 0x0808;
+ public const int TagGeographicSemiMajorAxis = 0x0809;
+ public const int TagGeographicSemiMinorAxis = 0x080a;
+ public const int TagGeographicInvFlattening = 0x080b;
+ public const int TagGeographicAzimuthUnits = 0x080c;
+ public const int TagGeographicPrimeMeridianLong = 0x080d;
+ public const int TagGeographicToWgs84 = 0x080e;
+
+ public const int TagProjectedCSType = 0x0c00;
+ public const int TagProjectedCSCitation = 0x0c01;
+ public const int TagProjection = 0x0c02;
+ public const int TagProjectedCoordinateTransform = 0x0c03;
+ public const int TagProjLinearUnits = 0x0c04;
+ public const int TagProjLinearUnitSize = 0x0c05;
+ public const int TagProjStdParallel1 = 0x0c06;
+ public const int TagProjStdParallel2 = 0x0c07;
+ public const int TagProjNatOriginLong = 0x0c08;
+ public const int TagProjNatOriginLat = 0x0c09;
+ public const int TagProjFalseEasting = 0x0c0a;
+ public const int TagProjFalseNorthing = 0x0c0b;
+ public const int TagProjFalseOriginLong = 0x0c0c;
+ public const int TagProjFalseOriginLat = 0x0c0d;
+ public const int TagProjFalseOriginEasting = 0x0c0e;
+ public const int TagProjFalseOriginNorthing = 0x0c0f;
+ public const int TagProjCenterLong = 0x0c10;
+ public const int TagProjCenterLat = 0x0c11;
+ public const int TagProjCenterEasting = 0x0c12;
+ public const int TagProjCenterNorthing = 0x0c13;
+ public const int TagProjScaleAtNatOrigin = 0x0c14;
+ public const int TagProjScaleAtCenter = 0x0c15;
+ public const int TagProjAzimuthAngle = 0x0c16;
+ public const int TagProjStraightVertPoleLong = 0x0c17;
+ public const int TagProjRectifiedGridAngle = 0x0c18;
+
+ public const int TagVerticalCSType = 0x1000;
+ public const int TagVerticalCitation = 0x1001;
+ public const int TagVerticalDatum = 0x1002;
+ public const int TagVerticalUnits = 0x1003;
+
+ public const int TagChartFormat = 0xb799;
+ public const int TagChartSource = 0xb79a;
+ public const int TagChartSourceEdition = 0xb79b;
+ public const int TagChartSourceDate = 0xb79c;
+ public const int TagChartCorrDate = 0xb79d;
+ public const int TagChartCountryOrigin = 0xb79e;
+ public const int TagChartRasterEdition = 0xb79f;
+ public const int TagChartSoundingDatum = 0xb7a0;
+ public const int TagChartDepthUnits = 0xb7a1;
+ public const int TagChartMagVar = 0xb7a2;
+ public const int TagChartMagVarYear = 0xb7a3;
+ public const int TagChartMagVarAnnChange = 0xb7a4;
+ public const int TagChartWGSNSShift = 0xb7a5;
+ public const int TagInsetNWPixelX = 0xb7a7;
+ public const int TagInsetNWPixelY = 0xb7a8;
+ public const int TagChartContourInterval = 0xb7a9;
+
+ private static readonly Dictionary _tagNameMap = new()
+ {
+ { TagModelType, "Model Type" },
+ { TagRasterType, "Raster Type" },
+ { TagCitation, "Citation" },
+ { TagGeographicType, "Geographic Type" },
+ { TagGeographicCitation, "Geographic Citation" },
+ { TagGeodeticDatum, "Geodetic Datum" },
+ { TagGeographicPrimeMeridian, "Prime Meridian" },
+ { TagGeographicLinearUnits, "Geographic Linear Units" },
+ { TagGeographicLinearUnitSize, "Geographic Linear Unit Size" },
+ { TagGeographicAngularUnits, "Geographic Angular Units" },
+ { TagGeographicAngularUnitSize, "Geographic Angular Unit Size" },
+ { TagGeographicEllipsoid, "Geographic Ellipsoid" },
+ { TagGeographicSemiMajorAxis, "Semi-major axis" },
+ { TagGeographicSemiMinorAxis, "Semi-minor axis" },
+ { TagGeographicInvFlattening, "Inv. Flattening" },
+ { TagGeographicAzimuthUnits, "Azimuth Units" },
+ { TagGeographicPrimeMeridianLong, "To WGS84" },
+ { TagGeographicToWgs84, "To WGS84" },
+ { TagProjectedCSType, "Projected Coordinate System Type" },
+ { TagProjectedCSCitation, "Projected Coordinate System Citation" },
+ { TagProjection, "Projection" },
+ { TagProjectedCoordinateTransform, "Projected Coordinate Transform" },
+ { TagProjLinearUnits, "Projection Linear Units" },
+ { TagProjLinearUnitSize, "Projection Linear Unit Size" },
+ { TagProjStdParallel1, "Projection Standard Parallel 1" },
+ { TagProjStdParallel2, "Projection Standard Parallel 2" },
+ { TagProjNatOriginLong, "Projection Natural Origin Longitude" },
+ { TagProjNatOriginLat, "Projection Natural Origin Latitude" },
+ { TagProjFalseEasting, "Projection False Easting" },
+ { TagProjFalseNorthing, "Projection False Northing" },
+ { TagProjFalseOriginLong, "Projection False Origin Longitude" },
+ { TagProjFalseOriginLat, "Projection False Origin Latitude" },
+ { TagProjFalseOriginEasting, "Projection False Origin Easting" },
+ { TagProjFalseOriginNorthing, "Projection False Origin Northing" },
+ { TagProjCenterLong, "Projection Center Longitude" },
+ { TagProjCenterLat, "Projection Center Latitude" },
+ { TagProjCenterEasting, "Projection Center Easting" },
+ { TagProjCenterNorthing, "Projection Center Northing" },
+ { TagProjScaleAtNatOrigin, "Projection Scale at Natural Origin" },
+ { TagProjScaleAtCenter, "Projection Scale at Center" },
+ { TagProjAzimuthAngle, "Projection Azimuth Angle" },
+ { TagProjStraightVertPoleLong, "Projection Straight Vertical Pole Longitude" },
+ { TagProjRectifiedGridAngle, "Projection Straight Vertical Pole Latitude" },
+ { TagVerticalCSType, "Vertical Coordinate System Type" },
+ { TagVerticalCitation, "Vertical Citation" },
+ { TagVerticalDatum, "Vertical Datum" },
+ { TagVerticalUnits, "Vertical Units" },
+ { TagChartFormat, "Chart Format" },
+ { TagChartSource, "Chart Source" },
+ { TagChartSourceEdition, "Chart Source Edition" },
+ { TagChartSourceDate, "Chart Source Date" },
+ { TagChartCorrDate, "Chart Corr Date" },
+ { TagChartCountryOrigin, "Chart Country Origin" },
+ { TagChartRasterEdition, "Chart Raster Edition" },
+ { TagChartSoundingDatum, "Chart Sounding Datum" },
+ { TagChartDepthUnits, "Chart Depth Units" },
+ { TagChartMagVar, "Chart Mag Var" },
+ { TagChartMagVarYear, "Chart Mag Var Year" },
+ { TagChartMagVarAnnChange, "Chart Mag Var Annual Change" },
+ { TagChartWGSNSShift, "Chart WGSNS Shift" },
+ { TagInsetNWPixelX, "Inset NW Pixel X" },
+ { TagInsetNWPixelY, "Inset NW Pixel Y" },
+ { TagChartContourInterval, "Chart Contour Interval" }
+ };
+
+ public GeoTiffDirectory() : base(_tagNameMap)
+ {
+ SetDescriptor(new GeoTiffDescriptor(this));
+ }
+
+ public override string Name => "GeoTIFF";
+ }
+}
diff --git a/MetadataExtractor/Formats/Photoshop/PhotoshopTiffHandler.cs b/MetadataExtractor/Formats/Photoshop/PhotoshopTiffHandler.cs
index b8a6741c7..7c16e451f 100644
--- a/MetadataExtractor/Formats/Photoshop/PhotoshopTiffHandler.cs
+++ b/MetadataExtractor/Formats/Photoshop/PhotoshopTiffHandler.cs
@@ -31,22 +31,22 @@ public PhotoshopTiffHandler(List directories)
{
}
- public override bool CustomProcessTag(int tagOffset, HashSet processedIfds, IndexedReader reader, int tagId, int byteCount, bool isBigTiff)
+ public override bool CustomProcessTag(in TiffReaderContext context, int tagId, int valueOffset, int byteCount)
{
switch (tagId)
{
case TagXmp:
- Directories.Add(new XmpReader().Extract(reader.GetBytes(tagOffset, byteCount)));
+ Directories.Add(new XmpReader().Extract(context.Reader.GetBytes(valueOffset, byteCount)));
return true;
case TagPhotoshopImageResources:
- Directories.AddRange(new PhotoshopReader().Extract(new SequentialByteArrayReader(reader.GetBytes(tagOffset, byteCount)), byteCount));
+ Directories.AddRange(new PhotoshopReader().Extract(new SequentialByteArrayReader(context.Reader.GetBytes(valueOffset, byteCount)), byteCount));
return true;
case TagIccProfiles:
- Directories.Add(new IccReader().Extract(new ByteArrayReader(reader.GetBytes(tagOffset, byteCount))));
+ Directories.Add(new IccReader().Extract(new ByteArrayReader(context.Reader.GetBytes(valueOffset, byteCount))));
return true;
}
- return base.CustomProcessTag(tagOffset, processedIfds, reader, tagId, byteCount, isBigTiff);
+ return base.CustomProcessTag(context, tagId, valueOffset, byteCount);
}
}
}
diff --git a/MetadataExtractor/Formats/Tiff/DirectoryTiffHandler.cs b/MetadataExtractor/Formats/Tiff/DirectoryTiffHandler.cs
index 824122569..8ba4b9b94 100644
--- a/MetadataExtractor/Formats/Tiff/DirectoryTiffHandler.cs
+++ b/MetadataExtractor/Formats/Tiff/DirectoryTiffHandler.cs
@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.Linq;
-using MetadataExtractor.IO;
namespace MetadataExtractor.Formats.Tiff
{
@@ -25,7 +24,7 @@ protected DirectoryTiffHandler(List directories)
Directories = directories;
}
- public void EndingIfd()
+ public virtual void EndingIfd(in TiffReaderContext context)
{
CurrentDirectory = _directoryStack.Count == 0 ? null : _directoryStack.Pop();
}
@@ -86,7 +85,7 @@ private Directory GetCurrentOrErrorDirectory()
#pragma warning restore format
- public abstract bool CustomProcessTag(int tagOffset, HashSet processedIfds, IndexedReader reader, int tagId, int byteCount, bool isBigTiff);
+ public abstract bool CustomProcessTag(in TiffReaderContext context, int tagId, int valueOffset, int byteCount);
public abstract bool TryCustomProcessFormat(int tagId, TiffDataFormatCode formatCode, ulong componentCount, out ulong byteCount);
diff --git a/MetadataExtractor/Formats/Tiff/ITiffHandler.cs b/MetadataExtractor/Formats/Tiff/ITiffHandler.cs
index c14bcf6c7..12d90e9be 100644
--- a/MetadataExtractor/Formats/Tiff/ITiffHandler.cs
+++ b/MetadataExtractor/Formats/Tiff/ITiffHandler.cs
@@ -1,8 +1,5 @@
// Copyright (c) Drew Noakes and contributors. All Rights Reserved. Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
-using System.Collections.Generic;
-using MetadataExtractor.IO;
-
namespace MetadataExtractor.Formats.Tiff
{
///
@@ -42,10 +39,18 @@ public interface ITiffHandler
bool HasFollowerIfd();
- void EndingIfd();
+ void EndingIfd(in TiffReaderContext context);
+ ///
+ /// Allows handlers to provide custom logic for a given tag.
+ ///
+ /// Context for the TIFF read operation.
+ /// The ID of the tag being processed.
+ /// The offset into the data stream at which the tag's value starts.
+ /// The number of bytes that the tag's value spans.
+ /// if processing was successful and default processing should be suppressed, otherwise .
///
- bool CustomProcessTag(int tagOffset, HashSet processedIfds, IndexedReader reader, int tagId, int byteCount, bool isBigTiff);
+ bool CustomProcessTag(in TiffReaderContext context, int tagId, int valueOffset, int byteCount);
bool TryCustomProcessFormat(int tagId, TiffDataFormatCode formatCode, ulong componentCount, out ulong byteCount);
diff --git a/MetadataExtractor/Formats/Tiff/TiffReader.cs b/MetadataExtractor/Formats/Tiff/TiffReader.cs
index 0301435b0..4ab5f8de4 100644
--- a/MetadataExtractor/Formats/Tiff/TiffReader.cs
+++ b/MetadataExtractor/Formats/Tiff/TiffReader.cs
@@ -1,6 +1,5 @@
// Copyright (c) Drew Noakes and contributors. All Rights Reserved. Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
-using System.Collections.Generic;
using MetadataExtractor.IO;
namespace MetadataExtractor.Formats.Tiff
@@ -91,19 +90,19 @@ public static void ProcessTiff(IndexedReader reader, ITiffHandler handler)
return;
}
- var processedIfdOffsets = new HashSet();
+ var context = new TiffReaderContext(reader, reader.IsMotorolaByteOrder, isBigTiff);
- ProcessIfd(handler, reader, processedIfdOffsets, firstIfdOffset, isBigTiff);
+ ProcessIfd(handler, context, firstIfdOffset);
}
- /// Processes a TIFF IFD.
- /// the that will coordinate processing and accept read values
- /// the from which the data should be read
- /// the set of visited IFDs, used to prevent processing endless loops
- /// the offset within reader at which the IFD data starts
- /// Whether the IFD uses the BigTIFF data format.
- /// an error occurred while accessing the required data
- public static void ProcessIfd(ITiffHandler handler, IndexedReader reader, HashSet processedIfds, int ifdOffset, bool isBigTiff)
+ ///
+ /// Processes a TIFF IFD.
+ ///
+ /// The that will coordinate processing and accept read values.
+ /// Context for the TIFF read operation.
+ /// The offset at which the IFD data starts.
+ /// An error occurred while accessing the required data.
+ public static void ProcessIfd(ITiffHandler handler, TiffReaderContext context, int ifdOffset)
{
// Standard TIFF
//
@@ -130,45 +129,42 @@ public static void ProcessIfd(ITiffHandler handler, IndexedReader reader, HashSe
try
{
// Check for directories we've already visited to avoid stack overflows when recursive/cyclic directory structures exist.
- // Note that we track these offsets in the global frame, not the reader's local frame.
- var globalIfdOffset = reader.ToUnshiftedOffset(ifdOffset);
-
- if (!processedIfds.Add(new(globalIfdOffset, handler.Kind)))
+ if (!context.TryVisitIfd(ifdOffset, handler.Kind))
return;
// Validate IFD offset
- if (ifdOffset >= reader.Length || ifdOffset < 0)
+ if (ifdOffset >= context.Reader.Length || ifdOffset < 0)
{
handler.Error("Ignored IFD marked to start outside data segment");
return;
}
// The number of tags in this directory
- var dirTagCount = isBigTiff
- ? checked((int)reader.GetUInt64(ifdOffset))
- : reader.GetUInt16(ifdOffset);
+ var dirTagCount = context.IsBigTiff
+ ? checked((int)context.Reader.GetUInt64(ifdOffset))
+ : context.Reader.GetUInt16(ifdOffset);
// Some software modifies the byte order of the file, but misses some IFDs (such as makernotes).
// The entire test image repository doesn't contain a single IFD with more than 255 entries.
// Here we detect switched bytes that suggest this problem, and temporarily swap the byte order.
// This was discussed in GitHub issue #136.
- if (!isBigTiff && dirTagCount > 0xFF && (dirTagCount & 0xFF) == 0)
+ if (!context.IsBigTiff && dirTagCount > 0xFF && (dirTagCount & 0xFF) == 0)
{
dirTagCount >>= 8;
- reader = reader.WithByteOrder(!reader.IsMotorolaByteOrder);
+ context = context.WithByteOrder(!context.Reader.IsMotorolaByteOrder);
}
- var dirLength = isBigTiff
+ var dirLength = context.IsBigTiff
? 8 + 20 * dirTagCount + 8
: 2 + 12 * dirTagCount + 4;
- if (dirLength + ifdOffset > checked((int)reader.Length))
+ if (dirLength + ifdOffset > checked((int)context.Reader.Length))
{
handler.Error("Illegally sized IFD");
return;
}
- var inlineValueSize = isBigTiff ? 8u : 4u;
+ var inlineValueSize = context.IsBigTiff ? 8u : 4u;
//
// Handle each tag in this directory
@@ -176,17 +172,17 @@ public static void ProcessIfd(ITiffHandler handler, IndexedReader reader, HashSe
var invalidTiffFormatCodeCount = 0;
for (var tagNumber = 0; tagNumber < dirTagCount; tagNumber++)
{
- var tagOffset = CalculateTagOffset(ifdOffset, tagNumber, isBigTiff);
+ var tagOffset = CalculateTagOffset(ifdOffset, tagNumber, context.IsBigTiff);
- int tagId = reader.GetUInt16(tagOffset);
+ int tagId = context.Reader.GetUInt16(tagOffset);
- var formatCode = (TiffDataFormatCode)reader.GetUInt16(tagOffset + 2);
+ var formatCode = (TiffDataFormatCode)context.Reader.GetUInt16(tagOffset + 2);
- var componentCount = isBigTiff
- ? reader.GetUInt64(tagOffset + 4)
- : reader.GetUInt32(tagOffset + 4);
+ var componentCount = context.IsBigTiff
+ ? context.Reader.GetUInt64(tagOffset + 4)
+ : context.Reader.GetUInt32(tagOffset + 4);
- var format = TiffDataFormat.FromTiffFormatCode(formatCode, isBigTiff);
+ var format = TiffDataFormat.FromTiffFormatCode(formatCode, context.IsBigTiff);
ulong byteCount;
if (format == null)
@@ -214,11 +210,11 @@ public static void ProcessIfd(ITiffHandler handler, IndexedReader reader, HashSe
if (byteCount > inlineValueSize)
{
// Value(s) are too big to fit inline. Follow the pointer.
- tagValueOffset = isBigTiff
- ? checked((uint)reader.GetUInt64(tagOffset + 12))
- : reader.GetUInt32(tagOffset + 8);
+ tagValueOffset = context.IsBigTiff
+ ? checked((uint)context.Reader.GetUInt64(tagOffset + 12))
+ : context.Reader.GetUInt32(tagOffset + 8);
- if (tagValueOffset + byteCount > checked((ulong)reader.Length))
+ if (tagValueOffset + byteCount > checked((ulong)context.Reader.Length))
{
// Bogus pointer offset and/or byteCount value
handler.Error("Illegal TIFF tag pointer offset");
@@ -228,12 +224,12 @@ public static void ProcessIfd(ITiffHandler handler, IndexedReader reader, HashSe
else
{
// Value(s) can fit inline.
- tagValueOffset = isBigTiff
+ tagValueOffset = context.IsBigTiff
? checked((uint)tagOffset + 12)
: checked((uint)tagOffset + 8);
}
- if (tagValueOffset > reader.Length)
+ if (tagValueOffset > context.Reader.Length)
{
handler.Error("Illegal TIFF tag pointer offset");
continue;
@@ -241,7 +237,7 @@ public static void ProcessIfd(ITiffHandler handler, IndexedReader reader, HashSe
// Check that this tag isn't going to allocate outside the bounds of the data array.
// This addresses an uncommon OutOfMemoryError.
- if (tagValueOffset + byteCount > checked((ulong)reader.Length))
+ if (tagValueOffset + byteCount > checked((ulong)context.Reader.Length))
{
handler.Error("Illegal number of bytes for TIFF tag data: " + byteCount);
continue;
@@ -256,32 +252,32 @@ public static void ProcessIfd(ITiffHandler handler, IndexedReader reader, HashSe
if (handler.TryEnterSubIfd(tagId))
{
isIfdPointer = true;
- var subDirOffset = reader.GetUInt32(checked((int)(tagValueOffset + i * 4)));
- ProcessIfd(handler, reader, processedIfds, (int)subDirOffset, isBigTiff);
+ var subDirOffset = context.Reader.GetUInt32(checked((int)(tagValueOffset + i * 4)));
+ ProcessIfd(handler, context, (int)subDirOffset);
}
}
}
// If it wasn't an IFD pointer, allow custom tag processing to occur
- if (!isIfdPointer && !handler.CustomProcessTag((int)tagValueOffset, processedIfds, reader, tagId, (int)byteCount, isBigTiff))
+ if (!isIfdPointer && !handler.CustomProcessTag(context, tagId, (int)tagValueOffset, (int)byteCount))
{
// If no custom processing occurred, process the tag in the standard fashion
- ProcessTag(handler, tagId, (int)tagValueOffset, (int)componentCount, formatCode, reader);
+ ProcessTag(handler, tagId, (int)tagValueOffset, (int)componentCount, formatCode, context.Reader);
}
}
// at the end of each IFD is an optional link to the next IFD
- var finalTagOffset = CalculateTagOffset(ifdOffset, dirTagCount, isBigTiff);
+ var finalTagOffset = CalculateTagOffset(ifdOffset, dirTagCount, context.IsBigTiff);
- var nextIfdOffsetLong = isBigTiff
- ? reader.GetUInt64(finalTagOffset)
- : reader.GetUInt32(finalTagOffset);
+ var nextIfdOffsetLong = context.IsBigTiff
+ ? context.Reader.GetUInt64(finalTagOffset)
+ : context.Reader.GetUInt32(finalTagOffset);
if (nextIfdOffsetLong != 0 && nextIfdOffsetLong <= int.MaxValue)
{
var nextIfdOffset = (int)nextIfdOffsetLong;
- if (nextIfdOffset >= reader.Length)
+ if (nextIfdOffset >= context.Reader.Length)
{
// Last 4 bytes of IFD reference another IFD with an address that is out of bounds
return;
@@ -295,13 +291,13 @@ public static void ProcessIfd(ITiffHandler handler, IndexedReader reader, HashSe
if (handler.HasFollowerIfd())
{
- ProcessIfd(handler, reader, processedIfds, nextIfdOffset, isBigTiff);
+ ProcessIfd(handler, context, nextIfdOffset);
}
}
}
finally
{
- handler.EndingIfd();
+ handler.EndingIfd(in context);
}
}
diff --git a/MetadataExtractor/Formats/Tiff/TiffReaderContext.cs b/MetadataExtractor/Formats/Tiff/TiffReaderContext.cs
new file mode 100644
index 000000000..6d3b7dda2
--- /dev/null
+++ b/MetadataExtractor/Formats/Tiff/TiffReaderContext.cs
@@ -0,0 +1,77 @@
+// Copyright (c) Drew Noakes and contributors. All Rights Reserved. Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
+
+using System.Collections.Generic;
+using MetadataExtractor.IO;
+
+namespace MetadataExtractor.Formats.Tiff
+{
+ ///
+ /// A set of data relating to a TIFF read operation.
+ ///
+ public readonly struct TiffReaderContext
+ {
+ ///
+ /// Gets an object via which TIFF data may be read by index.
+ ///
+ public IndexedReader Reader { get; }
+
+ ///
+ /// Gets whether the TIFF data advertises itself as having Motorola byte order.
+ /// Note that this value may differ from the byte order of
+ /// if during reading it is determined that the byte order should change for some reason.
+ ///
+ public bool IsMotorolaByteOrder { get; }
+
+ ///
+ /// Gets whether the TIFF data stream is encoded using the BigTIFF standard.
+ ///
+ public bool IsBigTiff { get; }
+
+ private readonly HashSet _visitedIfds;
+
+ public TiffReaderContext(IndexedReader reader, bool isMotorolaByteOrder, bool isBigTiff)
+ : this()
+ {
+ Reader = reader;
+ IsMotorolaByteOrder = isMotorolaByteOrder;
+ IsBigTiff = isBigTiff;
+
+ _visitedIfds = new();
+ }
+
+ ///
+ /// Gets whether the specified IFD should be processed or not, based on whether it has
+ /// been processed before.
+ ///
+ /// The offset at which the IFD starts.
+ /// The "kind" of the IFD according to .
+ /// if the IFD should be processed, otherwise .
+ public bool TryVisitIfd(int ifdOffset, object? kind)
+ {
+ // Note that we track these offsets in the global frame, not the reader's local frame.
+ var globalIfdOffset = Reader.ToUnshiftedOffset(ifdOffset);
+
+ return _visitedIfds.Add(new(globalIfdOffset, kind));
+ }
+
+ ///
+ /// Returns a copy of this context object with a reader observing the specified byte order.
+ ///
+ ///
+ /// Note that this method does not change the value of which
+ /// represents the advertised byte order at the start of the TIFF data stream.
+ ///
+ public TiffReaderContext WithByteOrder(bool isMotorolaByteOrder)
+ {
+ return new(Reader.WithByteOrder(isMotorolaByteOrder), IsMotorolaByteOrder, IsBigTiff);
+ }
+
+ ///
+ /// Returns a copy of this context object with a reader having a shifted base offset.
+ ///
+ public TiffReaderContext WithShiftedBaseOffset(int baseOffset)
+ {
+ return new(Reader.WithShiftedBaseOffset(baseOffset), IsMotorolaByteOrder, IsBigTiff);
+ }
+ }
+}
diff --git a/MetadataExtractor/PublicAPI/net35/PublicAPI.Shipped.txt b/MetadataExtractor/PublicAPI/net35/PublicAPI.Shipped.txt
index bdc67d19c..2ff73e235 100644
--- a/MetadataExtractor/PublicAPI/net35/PublicAPI.Shipped.txt
+++ b/MetadataExtractor/PublicAPI/net35/PublicAPI.Shipped.txt
@@ -1294,7 +1294,6 @@ MetadataExtractor.Formats.Tiff.DirectoryTiffHandler
MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.CurrentDirectory.get -> MetadataExtractor.Directory?
MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.Directories.get -> System.Collections.Generic.List!
MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.DirectoryTiffHandler(System.Collections.Generic.List! directories) -> void
-MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.EndingIfd() -> void
MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.Error(string! message) -> void
MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.PushDirectory(MetadataExtractor.Directory! directory) -> void
MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.SetByteArray(int tagId, byte[]! bytes) -> void
@@ -1319,7 +1318,6 @@ MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.SetRationalArray(int tagId,
MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.SetString(int tagId, MetadataExtractor.StringValue stringValue) -> void
MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.Warn(string! message) -> void
MetadataExtractor.Formats.Tiff.ITiffHandler
-MetadataExtractor.Formats.Tiff.ITiffHandler.EndingIfd() -> void
MetadataExtractor.Formats.Tiff.ITiffHandler.Error(string! message) -> void
MetadataExtractor.Formats.Tiff.ITiffHandler.HasFollowerIfd() -> bool
MetadataExtractor.Formats.Tiff.ITiffHandler.SetByteArray(int tagId, byte[]! bytes) -> void
diff --git a/MetadataExtractor/PublicAPI/net35/PublicAPI.Unshipped.txt b/MetadataExtractor/PublicAPI/net35/PublicAPI.Unshipped.txt
index e7c8a19ec..e87a7a3c8 100644
--- a/MetadataExtractor/PublicAPI/net35/PublicAPI.Unshipped.txt
+++ b/MetadataExtractor/PublicAPI/net35/PublicAPI.Unshipped.txt
@@ -2,9 +2,18 @@
abstract MetadataExtractor.Formats.Jpeg.JpegSegmentWithPreambleMetadataReader.Extract(byte[]! segmentBytes, int preambleLength) -> System.Collections.Generic.IEnumerable!
abstract MetadataExtractor.Formats.Jpeg.JpegSegmentWithPreambleMetadataReader.PreambleBytes.get -> byte[]!
abstract MetadataExtractor.Formats.Jpeg.JpegSegmentWithPreambleMetadataReader.SegmentTypes.get -> System.Collections.Generic.ICollection!
-abstract MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.CustomProcessTag(int tagOffset, System.Collections.Generic.HashSet! processedIfds, MetadataExtractor.IO.IndexedReader! reader, int tagId, int byteCount, bool isBigTiff) -> bool
+abstract MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.CustomProcessTag(in MetadataExtractor.Formats.Tiff.TiffReaderContext context, int tagId, int valueOffset, int byteCount) -> bool
abstract MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.ProcessTiffMarker(ushort marker) -> MetadataExtractor.Formats.Tiff.TiffStandard
abstract MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.TryCustomProcessFormat(int tagId, MetadataExtractor.Formats.Tiff.TiffDataFormatCode formatCode, ulong componentCount, out ulong byteCount) -> bool
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagExtraSamples = 338 -> int
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagGdalMetadata = 42112 -> int
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagGdalNoData = 42113 -> int
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagGeoTiffGeoAsciiParams = 34737 -> int
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagGeoTiffGeoDoubleParams = 34736 -> int
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagGeoTiffGeoKeys = 34735 -> int
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagModelTiePoint = 33922 -> int
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagPixelScale = 33550 -> int
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagSampleFormat = 339 -> int
const MetadataExtractor.Formats.Exif.Makernotes.FlirMakernoteDirectory.TagCameraTemperatureRangeMax = 6 -> int
const MetadataExtractor.Formats.Exif.Makernotes.FlirMakernoteDirectory.TagCameraTemperatureRangeMin = 5 -> int
const MetadataExtractor.Formats.Exif.Makernotes.FlirMakernoteDirectory.TagEmissivity = 3 -> int
@@ -61,7 +70,73 @@ const MetadataExtractor.Formats.Flir.FlirRawDataDirectory.TagRawThermalImageHeig
const MetadataExtractor.Formats.Flir.FlirRawDataDirectory.TagRawThermalImageType = 34 -> int
const MetadataExtractor.Formats.Flir.FlirRawDataDirectory.TagRawThermalImageWidth = 2 -> int
const MetadataExtractor.Formats.Flir.FlirReader.JpegSegmentPreamble = "FLIR\0" -> string!
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartContourInterval = 47017 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartCorrDate = 47005 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartCountryOrigin = 47006 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartDepthUnits = 47009 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartFormat = 47001 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartMagVar = 47010 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartMagVarAnnChange = 47012 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartMagVarYear = 47011 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartRasterEdition = 47007 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartSoundingDatum = 47008 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartSource = 47002 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartSourceDate = 47004 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartSourceEdition = 47003 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartWGSNSShift = 47013 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagCitation = 1026 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeodeticDatum = 2050 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicAngularUnits = 2054 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicAngularUnitSize = 2055 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicAzimuthUnits = 2060 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicCitation = 2049 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicEllipsoid = 2056 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicInvFlattening = 2059 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicLinearUnits = 2052 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicLinearUnitSize = 2053 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicPrimeMeridian = 2051 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicPrimeMeridianLong = 2061 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicSemiMajorAxis = 2057 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicSemiMinorAxis = 2058 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicToWgs84 = 2062 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicType = 2048 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagInsetNWPixelX = 47015 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagInsetNWPixelY = 47016 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagModelType = 1024 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjAzimuthAngle = 3094 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjCenterEasting = 3090 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjCenterLat = 3089 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjCenterLong = 3088 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjCenterNorthing = 3091 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjectedCoordinateTransform = 3075 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjectedCSCitation = 3073 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjectedCSType = 3072 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjection = 3074 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjFalseEasting = 3082 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjFalseNorthing = 3083 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjFalseOriginEasting = 3086 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjFalseOriginLat = 3085 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjFalseOriginLong = 3084 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjFalseOriginNorthing = 3087 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjLinearUnits = 3076 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjLinearUnitSize = 3077 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjNatOriginLat = 3081 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjNatOriginLong = 3080 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjRectifiedGridAngle = 3096 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjScaleAtCenter = 3093 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjScaleAtNatOrigin = 3092 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjStdParallel1 = 3078 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjStdParallel2 = 3079 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjStraightVertPoleLong = 3095 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagRasterType = 1025 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagVerticalCitation = 4097 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagVerticalCSType = 4096 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagVerticalDatum = 4098 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagVerticalUnits = 4099 -> int
MetadataExtractor.Directory.Directory(System.Collections.Generic.Dictionary? tagNameMap) -> void
+MetadataExtractor.Directory.RemoveTag(int tagId) -> void
+MetadataExtractor.Formats.Exif.ExifDescriptorBase.GetExtraSamplesDescription() -> string?
+MetadataExtractor.Formats.Exif.ExifDescriptorBase.GetSampleFormatDescription() -> string?
MetadataExtractor.Formats.Exif.ExifDirectoryBase.ExifDirectoryBase(System.Collections.Generic.Dictionary! tagNameMap) -> void
MetadataExtractor.Formats.Exif.Makernotes.AppleMakernoteDescriptor.GetAccelerationVectorDescription() -> string?
MetadataExtractor.Formats.Exif.Makernotes.AppleMakernoteDescriptor.GetHdrImageTypeDescription() -> string?
@@ -84,6 +159,21 @@ MetadataExtractor.Formats.Flir.FlirReader.ExtractRawThermalImage.set -> void
MetadataExtractor.Formats.Flir.FlirReader.FlirReader() -> void
MetadataExtractor.Formats.Flir.FlirReader.ReadJpegSegments(System.Collections.Generic.IEnumerable! segments) -> System.Collections.Generic.IEnumerable!
MetadataExtractor.Formats.Flir.FlirReader.SegmentTypes.get -> System.Collections.Generic.ICollection!
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GeoTiffDescriptor(MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory! directory) -> void
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetChartFormatDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetChartSoundingDatumDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetGeodeticDatumDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetGeographicEllipsoidDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetGeographicTypeDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetModelTypeDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetPrimeMeridianDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetProjectedCoordinateSystemDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetProjectedCoordinateTransformDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetProjectionDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetRasterTypeDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory
+MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.GeoTiffDirectory() -> void
MetadataExtractor.Formats.Jpeg.HuffmanTable.HuffmanTable() -> void
MetadataExtractor.Formats.Jpeg.JpegSegmentWithPreambleMetadataReader
MetadataExtractor.Formats.Jpeg.JpegSegmentWithPreambleMetadataReader.JpegSegmentWithPreambleMetadataReader() -> void
@@ -101,7 +191,8 @@ MetadataExtractor.Formats.Tiff.IfdIdentity
MetadataExtractor.Formats.Tiff.IfdIdentity.IfdIdentity() -> void
MetadataExtractor.Formats.Tiff.IfdIdentity.Kind.get -> object?
MetadataExtractor.Formats.Tiff.IfdIdentity.Offset.get -> int
-MetadataExtractor.Formats.Tiff.ITiffHandler.CustomProcessTag(int tagOffset, System.Collections.Generic.HashSet! processedIfds, MetadataExtractor.IO.IndexedReader! reader, int tagId, int byteCount, bool isBigTiff) -> bool
+MetadataExtractor.Formats.Tiff.ITiffHandler.CustomProcessTag(in MetadataExtractor.Formats.Tiff.TiffReaderContext context, int tagId, int valueOffset, int byteCount) -> bool
+MetadataExtractor.Formats.Tiff.ITiffHandler.EndingIfd(in MetadataExtractor.Formats.Tiff.TiffReaderContext context) -> void
MetadataExtractor.Formats.Tiff.ITiffHandler.Kind.get -> object?
MetadataExtractor.Formats.Tiff.ITiffHandler.ProcessTiffMarker(ushort marker) -> MetadataExtractor.Formats.Tiff.TiffStandard
MetadataExtractor.Formats.Tiff.ITiffHandler.SetInt64S(int tagId, long int64S) -> void
@@ -113,6 +204,15 @@ MetadataExtractor.Formats.Tiff.TiffDataFormat.ComponentSizeBytes.get -> byte
MetadataExtractor.Formats.Tiff.TiffDataFormatCode.Ifd8 = 18 -> MetadataExtractor.Formats.Tiff.TiffDataFormatCode
MetadataExtractor.Formats.Tiff.TiffDataFormatCode.Int64S = 17 -> MetadataExtractor.Formats.Tiff.TiffDataFormatCode
MetadataExtractor.Formats.Tiff.TiffDataFormatCode.Int64U = 16 -> MetadataExtractor.Formats.Tiff.TiffDataFormatCode
+MetadataExtractor.Formats.Tiff.TiffReaderContext
+MetadataExtractor.Formats.Tiff.TiffReaderContext.IsBigTiff.get -> bool
+MetadataExtractor.Formats.Tiff.TiffReaderContext.IsMotorolaByteOrder.get -> bool
+MetadataExtractor.Formats.Tiff.TiffReaderContext.Reader.get -> MetadataExtractor.IO.IndexedReader!
+MetadataExtractor.Formats.Tiff.TiffReaderContext.TiffReaderContext() -> void
+MetadataExtractor.Formats.Tiff.TiffReaderContext.TiffReaderContext(MetadataExtractor.IO.IndexedReader! reader, bool isMotorolaByteOrder, bool isBigTiff) -> void
+MetadataExtractor.Formats.Tiff.TiffReaderContext.TryVisitIfd(int ifdOffset, object? kind) -> bool
+MetadataExtractor.Formats.Tiff.TiffReaderContext.WithByteOrder(bool isMotorolaByteOrder) -> MetadataExtractor.Formats.Tiff.TiffReaderContext
+MetadataExtractor.Formats.Tiff.TiffReaderContext.WithShiftedBaseOffset(int baseOffset) -> MetadataExtractor.Formats.Tiff.TiffReaderContext
MetadataExtractor.Formats.Tiff.TiffStandard
MetadataExtractor.Formats.Tiff.TiffStandard.BigTiff = 1 -> MetadataExtractor.Formats.Tiff.TiffStandard
MetadataExtractor.Formats.Tiff.TiffStandard.Tiff = 0 -> MetadataExtractor.Formats.Tiff.TiffStandard
@@ -138,8 +238,10 @@ const MetadataExtractor.Formats.QuickTime.QuickTimeMetadataHeaderDirectory.TagOr
const MetadataExtractor.Formats.QuickTime.QuickTimeMetadataHeaderDirectory.TagPixelDensity = 33 -> int
MetadataExtractor.Rational.Rational() -> void
MetadataExtractor.StringValue.StringValue() -> void
+MetadataExtractor.StringValue.ToString(int index, int count) -> string!
override MetadataExtractor.Formats.Exif.ExifReader.SegmentTypes.get -> System.Collections.Generic.ICollection!
-override MetadataExtractor.Formats.Exif.ExifTiffHandler.CustomProcessTag(int tagOffset, System.Collections.Generic.HashSet! processedIfds, MetadataExtractor.IO.IndexedReader! reader, int tagId, int byteCount, bool isBigTiff) -> bool
+override MetadataExtractor.Formats.Exif.ExifTiffHandler.CustomProcessTag(in MetadataExtractor.Formats.Tiff.TiffReaderContext context, int tagId, int valueOffset, int byteCount) -> bool
+override MetadataExtractor.Formats.Exif.ExifTiffHandler.EndingIfd(in MetadataExtractor.Formats.Tiff.TiffReaderContext context) -> void
override MetadataExtractor.Formats.Exif.ExifTiffHandler.ProcessTiffMarker(ushort marker) -> MetadataExtractor.Formats.Tiff.TiffStandard
override MetadataExtractor.Formats.Exif.ExifTiffHandler.TryCustomProcessFormat(int tagId, MetadataExtractor.Formats.Tiff.TiffDataFormatCode formatCode, ulong componentCount, out ulong byteCount) -> bool
override MetadataExtractor.Formats.Exif.Makernotes.FlirMakernoteDirectory.Name.get -> string!
@@ -147,11 +249,13 @@ override MetadataExtractor.Formats.Flir.FlirCameraInfoDescriptor.GetDescription(
override MetadataExtractor.Formats.Flir.FlirCameraInfoDirectory.Name.get -> string!
override MetadataExtractor.Formats.Flir.FlirHeaderDirectory.Name.get -> string!
override MetadataExtractor.Formats.Flir.FlirRawDataDirectory.Name.get -> string!
+override MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetDescription(int tagType) -> string?
+override MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.Name.get -> string!
override MetadataExtractor.Formats.Jfif.JfifReader.SegmentTypes.get -> System.Collections.Generic.ICollection!
override MetadataExtractor.Formats.Jfxx.JfxxReader.SegmentTypes.get -> System.Collections.Generic.ICollection!
override MetadataExtractor.Formats.Jpeg.JpegSegment.ToString() -> string!
override MetadataExtractor.Formats.Photoshop.PhotoshopReader.SegmentTypes.get -> System.Collections.Generic.ICollection!
-override MetadataExtractor.Formats.Photoshop.PhotoshopTiffHandler.CustomProcessTag(int tagOffset, System.Collections.Generic.HashSet! processedIfds, MetadataExtractor.IO.IndexedReader! reader, int tagId, int byteCount, bool isBigTiff) -> bool
+override MetadataExtractor.Formats.Photoshop.PhotoshopTiffHandler.CustomProcessTag(in MetadataExtractor.Formats.Tiff.TiffReaderContext context, int tagId, int valueOffset, int byteCount) -> bool
override MetadataExtractor.Formats.QuickTime.QuickTimeMetadataHeaderDescriptor.GetDescription(int tagType) -> string?
override MetadataExtractor.Formats.QuickTime.QuickTimeTiffHandler.ProcessTiffMarker(ushort marker) -> MetadataExtractor.Formats.Tiff.TiffStandard
static MetadataExtractor.DirectoryExtensions.GetUInt64(this MetadataExtractor.Directory! directory, int tagType) -> ulong
@@ -159,9 +263,10 @@ static MetadataExtractor.DirectoryExtensions.TryGetUInt64(this MetadataExtractor
static MetadataExtractor.Formats.Exif.ExifReader.JpegSegmentPreambleLength.get -> int
static MetadataExtractor.Formats.Jpeg.JpegMetadataReader.AllReaders.get -> System.Collections.Generic.IEnumerable!
static MetadataExtractor.Formats.QuickTime.QuickTimeMetadataHeaderDirectory.TryGetTag(string! name, out int tagType) -> bool
-static MetadataExtractor.Formats.Tiff.TiffReader.ProcessIfd(MetadataExtractor.Formats.Tiff.ITiffHandler! handler, MetadataExtractor.IO.IndexedReader! reader, System.Collections.Generic.HashSet! processedIfds, int ifdOffset, bool isBigTiff) -> void
+static MetadataExtractor.Formats.Tiff.TiffReader.ProcessIfd(MetadataExtractor.Formats.Tiff.ITiffHandler! handler, MetadataExtractor.Formats.Tiff.TiffReaderContext context, int ifdOffset) -> void
static readonly MetadataExtractor.Formats.Png.PngChunkType.eXIf -> MetadataExtractor.Formats.Png.PngChunkType!
static readonly MetadataExtractor.Formats.Tiff.TiffDataFormat.Ifd8 -> MetadataExtractor.Formats.Tiff.TiffDataFormat!
static readonly MetadataExtractor.Formats.Tiff.TiffDataFormat.Int64S -> MetadataExtractor.Formats.Tiff.TiffDataFormat!
static readonly MetadataExtractor.Formats.Tiff.TiffDataFormat.Int64U -> MetadataExtractor.Formats.Tiff.TiffDataFormat!
virtual MetadataExtractor.Directory.TryGetTagName(int tagType, out string? tagName) -> bool
+virtual MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.EndingIfd(in MetadataExtractor.Formats.Tiff.TiffReaderContext context) -> void
diff --git a/MetadataExtractor/PublicAPI/net45/PublicAPI.Shipped.txt b/MetadataExtractor/PublicAPI/net45/PublicAPI.Shipped.txt
index c8ff0417a..00b55a649 100644
--- a/MetadataExtractor/PublicAPI/net45/PublicAPI.Shipped.txt
+++ b/MetadataExtractor/PublicAPI/net45/PublicAPI.Shipped.txt
@@ -1294,7 +1294,6 @@ MetadataExtractor.Formats.Tiff.DirectoryTiffHandler
MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.CurrentDirectory.get -> MetadataExtractor.Directory?
MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.Directories.get -> System.Collections.Generic.List!
MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.DirectoryTiffHandler(System.Collections.Generic.List! directories) -> void
-MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.EndingIfd() -> void
MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.Error(string! message) -> void
MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.PushDirectory(MetadataExtractor.Directory! directory) -> void
MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.SetByteArray(int tagId, byte[]! bytes) -> void
@@ -1319,7 +1318,6 @@ MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.SetRationalArray(int tagId,
MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.SetString(int tagId, MetadataExtractor.StringValue stringValue) -> void
MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.Warn(string! message) -> void
MetadataExtractor.Formats.Tiff.ITiffHandler
-MetadataExtractor.Formats.Tiff.ITiffHandler.EndingIfd() -> void
MetadataExtractor.Formats.Tiff.ITiffHandler.Error(string! message) -> void
MetadataExtractor.Formats.Tiff.ITiffHandler.HasFollowerIfd() -> bool
MetadataExtractor.Formats.Tiff.ITiffHandler.SetByteArray(int tagId, byte[]! bytes) -> void
diff --git a/MetadataExtractor/PublicAPI/net45/PublicAPI.Unshipped.txt b/MetadataExtractor/PublicAPI/net45/PublicAPI.Unshipped.txt
index e7c8a19ec..e87a7a3c8 100644
--- a/MetadataExtractor/PublicAPI/net45/PublicAPI.Unshipped.txt
+++ b/MetadataExtractor/PublicAPI/net45/PublicAPI.Unshipped.txt
@@ -2,9 +2,18 @@
abstract MetadataExtractor.Formats.Jpeg.JpegSegmentWithPreambleMetadataReader.Extract(byte[]! segmentBytes, int preambleLength) -> System.Collections.Generic.IEnumerable!
abstract MetadataExtractor.Formats.Jpeg.JpegSegmentWithPreambleMetadataReader.PreambleBytes.get -> byte[]!
abstract MetadataExtractor.Formats.Jpeg.JpegSegmentWithPreambleMetadataReader.SegmentTypes.get -> System.Collections.Generic.ICollection!
-abstract MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.CustomProcessTag(int tagOffset, System.Collections.Generic.HashSet! processedIfds, MetadataExtractor.IO.IndexedReader! reader, int tagId, int byteCount, bool isBigTiff) -> bool
+abstract MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.CustomProcessTag(in MetadataExtractor.Formats.Tiff.TiffReaderContext context, int tagId, int valueOffset, int byteCount) -> bool
abstract MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.ProcessTiffMarker(ushort marker) -> MetadataExtractor.Formats.Tiff.TiffStandard
abstract MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.TryCustomProcessFormat(int tagId, MetadataExtractor.Formats.Tiff.TiffDataFormatCode formatCode, ulong componentCount, out ulong byteCount) -> bool
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagExtraSamples = 338 -> int
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagGdalMetadata = 42112 -> int
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagGdalNoData = 42113 -> int
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagGeoTiffGeoAsciiParams = 34737 -> int
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagGeoTiffGeoDoubleParams = 34736 -> int
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagGeoTiffGeoKeys = 34735 -> int
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagModelTiePoint = 33922 -> int
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagPixelScale = 33550 -> int
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagSampleFormat = 339 -> int
const MetadataExtractor.Formats.Exif.Makernotes.FlirMakernoteDirectory.TagCameraTemperatureRangeMax = 6 -> int
const MetadataExtractor.Formats.Exif.Makernotes.FlirMakernoteDirectory.TagCameraTemperatureRangeMin = 5 -> int
const MetadataExtractor.Formats.Exif.Makernotes.FlirMakernoteDirectory.TagEmissivity = 3 -> int
@@ -61,7 +70,73 @@ const MetadataExtractor.Formats.Flir.FlirRawDataDirectory.TagRawThermalImageHeig
const MetadataExtractor.Formats.Flir.FlirRawDataDirectory.TagRawThermalImageType = 34 -> int
const MetadataExtractor.Formats.Flir.FlirRawDataDirectory.TagRawThermalImageWidth = 2 -> int
const MetadataExtractor.Formats.Flir.FlirReader.JpegSegmentPreamble = "FLIR\0" -> string!
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartContourInterval = 47017 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartCorrDate = 47005 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartCountryOrigin = 47006 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartDepthUnits = 47009 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartFormat = 47001 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartMagVar = 47010 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartMagVarAnnChange = 47012 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartMagVarYear = 47011 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartRasterEdition = 47007 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartSoundingDatum = 47008 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartSource = 47002 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartSourceDate = 47004 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartSourceEdition = 47003 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartWGSNSShift = 47013 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagCitation = 1026 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeodeticDatum = 2050 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicAngularUnits = 2054 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicAngularUnitSize = 2055 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicAzimuthUnits = 2060 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicCitation = 2049 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicEllipsoid = 2056 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicInvFlattening = 2059 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicLinearUnits = 2052 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicLinearUnitSize = 2053 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicPrimeMeridian = 2051 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicPrimeMeridianLong = 2061 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicSemiMajorAxis = 2057 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicSemiMinorAxis = 2058 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicToWgs84 = 2062 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicType = 2048 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagInsetNWPixelX = 47015 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagInsetNWPixelY = 47016 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagModelType = 1024 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjAzimuthAngle = 3094 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjCenterEasting = 3090 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjCenterLat = 3089 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjCenterLong = 3088 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjCenterNorthing = 3091 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjectedCoordinateTransform = 3075 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjectedCSCitation = 3073 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjectedCSType = 3072 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjection = 3074 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjFalseEasting = 3082 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjFalseNorthing = 3083 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjFalseOriginEasting = 3086 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjFalseOriginLat = 3085 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjFalseOriginLong = 3084 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjFalseOriginNorthing = 3087 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjLinearUnits = 3076 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjLinearUnitSize = 3077 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjNatOriginLat = 3081 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjNatOriginLong = 3080 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjRectifiedGridAngle = 3096 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjScaleAtCenter = 3093 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjScaleAtNatOrigin = 3092 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjStdParallel1 = 3078 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjStdParallel2 = 3079 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjStraightVertPoleLong = 3095 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagRasterType = 1025 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagVerticalCitation = 4097 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagVerticalCSType = 4096 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagVerticalDatum = 4098 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagVerticalUnits = 4099 -> int
MetadataExtractor.Directory.Directory(System.Collections.Generic.Dictionary? tagNameMap) -> void
+MetadataExtractor.Directory.RemoveTag(int tagId) -> void
+MetadataExtractor.Formats.Exif.ExifDescriptorBase.GetExtraSamplesDescription() -> string?
+MetadataExtractor.Formats.Exif.ExifDescriptorBase.GetSampleFormatDescription() -> string?
MetadataExtractor.Formats.Exif.ExifDirectoryBase.ExifDirectoryBase(System.Collections.Generic.Dictionary! tagNameMap) -> void
MetadataExtractor.Formats.Exif.Makernotes.AppleMakernoteDescriptor.GetAccelerationVectorDescription() -> string?
MetadataExtractor.Formats.Exif.Makernotes.AppleMakernoteDescriptor.GetHdrImageTypeDescription() -> string?
@@ -84,6 +159,21 @@ MetadataExtractor.Formats.Flir.FlirReader.ExtractRawThermalImage.set -> void
MetadataExtractor.Formats.Flir.FlirReader.FlirReader() -> void
MetadataExtractor.Formats.Flir.FlirReader.ReadJpegSegments(System.Collections.Generic.IEnumerable! segments) -> System.Collections.Generic.IEnumerable!
MetadataExtractor.Formats.Flir.FlirReader.SegmentTypes.get -> System.Collections.Generic.ICollection!
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GeoTiffDescriptor(MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory! directory) -> void
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetChartFormatDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetChartSoundingDatumDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetGeodeticDatumDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetGeographicEllipsoidDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetGeographicTypeDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetModelTypeDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetPrimeMeridianDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetProjectedCoordinateSystemDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetProjectedCoordinateTransformDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetProjectionDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetRasterTypeDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory
+MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.GeoTiffDirectory() -> void
MetadataExtractor.Formats.Jpeg.HuffmanTable.HuffmanTable() -> void
MetadataExtractor.Formats.Jpeg.JpegSegmentWithPreambleMetadataReader
MetadataExtractor.Formats.Jpeg.JpegSegmentWithPreambleMetadataReader.JpegSegmentWithPreambleMetadataReader() -> void
@@ -101,7 +191,8 @@ MetadataExtractor.Formats.Tiff.IfdIdentity
MetadataExtractor.Formats.Tiff.IfdIdentity.IfdIdentity() -> void
MetadataExtractor.Formats.Tiff.IfdIdentity.Kind.get -> object?
MetadataExtractor.Formats.Tiff.IfdIdentity.Offset.get -> int
-MetadataExtractor.Formats.Tiff.ITiffHandler.CustomProcessTag(int tagOffset, System.Collections.Generic.HashSet! processedIfds, MetadataExtractor.IO.IndexedReader! reader, int tagId, int byteCount, bool isBigTiff) -> bool
+MetadataExtractor.Formats.Tiff.ITiffHandler.CustomProcessTag(in MetadataExtractor.Formats.Tiff.TiffReaderContext context, int tagId, int valueOffset, int byteCount) -> bool
+MetadataExtractor.Formats.Tiff.ITiffHandler.EndingIfd(in MetadataExtractor.Formats.Tiff.TiffReaderContext context) -> void
MetadataExtractor.Formats.Tiff.ITiffHandler.Kind.get -> object?
MetadataExtractor.Formats.Tiff.ITiffHandler.ProcessTiffMarker(ushort marker) -> MetadataExtractor.Formats.Tiff.TiffStandard
MetadataExtractor.Formats.Tiff.ITiffHandler.SetInt64S(int tagId, long int64S) -> void
@@ -113,6 +204,15 @@ MetadataExtractor.Formats.Tiff.TiffDataFormat.ComponentSizeBytes.get -> byte
MetadataExtractor.Formats.Tiff.TiffDataFormatCode.Ifd8 = 18 -> MetadataExtractor.Formats.Tiff.TiffDataFormatCode
MetadataExtractor.Formats.Tiff.TiffDataFormatCode.Int64S = 17 -> MetadataExtractor.Formats.Tiff.TiffDataFormatCode
MetadataExtractor.Formats.Tiff.TiffDataFormatCode.Int64U = 16 -> MetadataExtractor.Formats.Tiff.TiffDataFormatCode
+MetadataExtractor.Formats.Tiff.TiffReaderContext
+MetadataExtractor.Formats.Tiff.TiffReaderContext.IsBigTiff.get -> bool
+MetadataExtractor.Formats.Tiff.TiffReaderContext.IsMotorolaByteOrder.get -> bool
+MetadataExtractor.Formats.Tiff.TiffReaderContext.Reader.get -> MetadataExtractor.IO.IndexedReader!
+MetadataExtractor.Formats.Tiff.TiffReaderContext.TiffReaderContext() -> void
+MetadataExtractor.Formats.Tiff.TiffReaderContext.TiffReaderContext(MetadataExtractor.IO.IndexedReader! reader, bool isMotorolaByteOrder, bool isBigTiff) -> void
+MetadataExtractor.Formats.Tiff.TiffReaderContext.TryVisitIfd(int ifdOffset, object? kind) -> bool
+MetadataExtractor.Formats.Tiff.TiffReaderContext.WithByteOrder(bool isMotorolaByteOrder) -> MetadataExtractor.Formats.Tiff.TiffReaderContext
+MetadataExtractor.Formats.Tiff.TiffReaderContext.WithShiftedBaseOffset(int baseOffset) -> MetadataExtractor.Formats.Tiff.TiffReaderContext
MetadataExtractor.Formats.Tiff.TiffStandard
MetadataExtractor.Formats.Tiff.TiffStandard.BigTiff = 1 -> MetadataExtractor.Formats.Tiff.TiffStandard
MetadataExtractor.Formats.Tiff.TiffStandard.Tiff = 0 -> MetadataExtractor.Formats.Tiff.TiffStandard
@@ -138,8 +238,10 @@ const MetadataExtractor.Formats.QuickTime.QuickTimeMetadataHeaderDirectory.TagOr
const MetadataExtractor.Formats.QuickTime.QuickTimeMetadataHeaderDirectory.TagPixelDensity = 33 -> int
MetadataExtractor.Rational.Rational() -> void
MetadataExtractor.StringValue.StringValue() -> void
+MetadataExtractor.StringValue.ToString(int index, int count) -> string!
override MetadataExtractor.Formats.Exif.ExifReader.SegmentTypes.get -> System.Collections.Generic.ICollection!
-override MetadataExtractor.Formats.Exif.ExifTiffHandler.CustomProcessTag(int tagOffset, System.Collections.Generic.HashSet! processedIfds, MetadataExtractor.IO.IndexedReader! reader, int tagId, int byteCount, bool isBigTiff) -> bool
+override MetadataExtractor.Formats.Exif.ExifTiffHandler.CustomProcessTag(in MetadataExtractor.Formats.Tiff.TiffReaderContext context, int tagId, int valueOffset, int byteCount) -> bool
+override MetadataExtractor.Formats.Exif.ExifTiffHandler.EndingIfd(in MetadataExtractor.Formats.Tiff.TiffReaderContext context) -> void
override MetadataExtractor.Formats.Exif.ExifTiffHandler.ProcessTiffMarker(ushort marker) -> MetadataExtractor.Formats.Tiff.TiffStandard
override MetadataExtractor.Formats.Exif.ExifTiffHandler.TryCustomProcessFormat(int tagId, MetadataExtractor.Formats.Tiff.TiffDataFormatCode formatCode, ulong componentCount, out ulong byteCount) -> bool
override MetadataExtractor.Formats.Exif.Makernotes.FlirMakernoteDirectory.Name.get -> string!
@@ -147,11 +249,13 @@ override MetadataExtractor.Formats.Flir.FlirCameraInfoDescriptor.GetDescription(
override MetadataExtractor.Formats.Flir.FlirCameraInfoDirectory.Name.get -> string!
override MetadataExtractor.Formats.Flir.FlirHeaderDirectory.Name.get -> string!
override MetadataExtractor.Formats.Flir.FlirRawDataDirectory.Name.get -> string!
+override MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetDescription(int tagType) -> string?
+override MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.Name.get -> string!
override MetadataExtractor.Formats.Jfif.JfifReader.SegmentTypes.get -> System.Collections.Generic.ICollection!
override MetadataExtractor.Formats.Jfxx.JfxxReader.SegmentTypes.get -> System.Collections.Generic.ICollection!
override MetadataExtractor.Formats.Jpeg.JpegSegment.ToString() -> string!
override MetadataExtractor.Formats.Photoshop.PhotoshopReader.SegmentTypes.get -> System.Collections.Generic.ICollection!
-override MetadataExtractor.Formats.Photoshop.PhotoshopTiffHandler.CustomProcessTag(int tagOffset, System.Collections.Generic.HashSet! processedIfds, MetadataExtractor.IO.IndexedReader! reader, int tagId, int byteCount, bool isBigTiff) -> bool
+override MetadataExtractor.Formats.Photoshop.PhotoshopTiffHandler.CustomProcessTag(in MetadataExtractor.Formats.Tiff.TiffReaderContext context, int tagId, int valueOffset, int byteCount) -> bool
override MetadataExtractor.Formats.QuickTime.QuickTimeMetadataHeaderDescriptor.GetDescription(int tagType) -> string?
override MetadataExtractor.Formats.QuickTime.QuickTimeTiffHandler.ProcessTiffMarker(ushort marker) -> MetadataExtractor.Formats.Tiff.TiffStandard
static MetadataExtractor.DirectoryExtensions.GetUInt64(this MetadataExtractor.Directory! directory, int tagType) -> ulong
@@ -159,9 +263,10 @@ static MetadataExtractor.DirectoryExtensions.TryGetUInt64(this MetadataExtractor
static MetadataExtractor.Formats.Exif.ExifReader.JpegSegmentPreambleLength.get -> int
static MetadataExtractor.Formats.Jpeg.JpegMetadataReader.AllReaders.get -> System.Collections.Generic.IEnumerable!
static MetadataExtractor.Formats.QuickTime.QuickTimeMetadataHeaderDirectory.TryGetTag(string! name, out int tagType) -> bool
-static MetadataExtractor.Formats.Tiff.TiffReader.ProcessIfd(MetadataExtractor.Formats.Tiff.ITiffHandler! handler, MetadataExtractor.IO.IndexedReader! reader, System.Collections.Generic.HashSet! processedIfds, int ifdOffset, bool isBigTiff) -> void
+static MetadataExtractor.Formats.Tiff.TiffReader.ProcessIfd(MetadataExtractor.Formats.Tiff.ITiffHandler! handler, MetadataExtractor.Formats.Tiff.TiffReaderContext context, int ifdOffset) -> void
static readonly MetadataExtractor.Formats.Png.PngChunkType.eXIf -> MetadataExtractor.Formats.Png.PngChunkType!
static readonly MetadataExtractor.Formats.Tiff.TiffDataFormat.Ifd8 -> MetadataExtractor.Formats.Tiff.TiffDataFormat!
static readonly MetadataExtractor.Formats.Tiff.TiffDataFormat.Int64S -> MetadataExtractor.Formats.Tiff.TiffDataFormat!
static readonly MetadataExtractor.Formats.Tiff.TiffDataFormat.Int64U -> MetadataExtractor.Formats.Tiff.TiffDataFormat!
virtual MetadataExtractor.Directory.TryGetTagName(int tagType, out string? tagName) -> bool
+virtual MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.EndingIfd(in MetadataExtractor.Formats.Tiff.TiffReaderContext context) -> void
diff --git a/MetadataExtractor/PublicAPI/netstandard1.3/PublicAPI.Shipped.txt b/MetadataExtractor/PublicAPI/netstandard1.3/PublicAPI.Shipped.txt
index 07aa753e2..bb9e93033 100644
--- a/MetadataExtractor/PublicAPI/netstandard1.3/PublicAPI.Shipped.txt
+++ b/MetadataExtractor/PublicAPI/netstandard1.3/PublicAPI.Shipped.txt
@@ -1291,7 +1291,6 @@ MetadataExtractor.Formats.Tiff.DirectoryTiffHandler
MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.CurrentDirectory.get -> MetadataExtractor.Directory?
MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.Directories.get -> System.Collections.Generic.List!
MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.DirectoryTiffHandler(System.Collections.Generic.List! directories) -> void
-MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.EndingIfd() -> void
MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.Error(string! message) -> void
MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.PushDirectory(MetadataExtractor.Directory! directory) -> void
MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.SetByteArray(int tagId, byte[]! bytes) -> void
@@ -1316,7 +1315,6 @@ MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.SetRationalArray(int tagId,
MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.SetString(int tagId, MetadataExtractor.StringValue stringValue) -> void
MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.Warn(string! message) -> void
MetadataExtractor.Formats.Tiff.ITiffHandler
-MetadataExtractor.Formats.Tiff.ITiffHandler.EndingIfd() -> void
MetadataExtractor.Formats.Tiff.ITiffHandler.Error(string! message) -> void
MetadataExtractor.Formats.Tiff.ITiffHandler.HasFollowerIfd() -> bool
MetadataExtractor.Formats.Tiff.ITiffHandler.SetByteArray(int tagId, byte[]! bytes) -> void
diff --git a/MetadataExtractor/PublicAPI/netstandard1.3/PublicAPI.Unshipped.txt b/MetadataExtractor/PublicAPI/netstandard1.3/PublicAPI.Unshipped.txt
index e7c8a19ec..e87a7a3c8 100644
--- a/MetadataExtractor/PublicAPI/netstandard1.3/PublicAPI.Unshipped.txt
+++ b/MetadataExtractor/PublicAPI/netstandard1.3/PublicAPI.Unshipped.txt
@@ -2,9 +2,18 @@
abstract MetadataExtractor.Formats.Jpeg.JpegSegmentWithPreambleMetadataReader.Extract(byte[]! segmentBytes, int preambleLength) -> System.Collections.Generic.IEnumerable!
abstract MetadataExtractor.Formats.Jpeg.JpegSegmentWithPreambleMetadataReader.PreambleBytes.get -> byte[]!
abstract MetadataExtractor.Formats.Jpeg.JpegSegmentWithPreambleMetadataReader.SegmentTypes.get -> System.Collections.Generic.ICollection!
-abstract MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.CustomProcessTag(int tagOffset, System.Collections.Generic.HashSet! processedIfds, MetadataExtractor.IO.IndexedReader! reader, int tagId, int byteCount, bool isBigTiff) -> bool
+abstract MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.CustomProcessTag(in MetadataExtractor.Formats.Tiff.TiffReaderContext context, int tagId, int valueOffset, int byteCount) -> bool
abstract MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.ProcessTiffMarker(ushort marker) -> MetadataExtractor.Formats.Tiff.TiffStandard
abstract MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.TryCustomProcessFormat(int tagId, MetadataExtractor.Formats.Tiff.TiffDataFormatCode formatCode, ulong componentCount, out ulong byteCount) -> bool
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagExtraSamples = 338 -> int
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagGdalMetadata = 42112 -> int
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagGdalNoData = 42113 -> int
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagGeoTiffGeoAsciiParams = 34737 -> int
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagGeoTiffGeoDoubleParams = 34736 -> int
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagGeoTiffGeoKeys = 34735 -> int
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagModelTiePoint = 33922 -> int
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagPixelScale = 33550 -> int
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagSampleFormat = 339 -> int
const MetadataExtractor.Formats.Exif.Makernotes.FlirMakernoteDirectory.TagCameraTemperatureRangeMax = 6 -> int
const MetadataExtractor.Formats.Exif.Makernotes.FlirMakernoteDirectory.TagCameraTemperatureRangeMin = 5 -> int
const MetadataExtractor.Formats.Exif.Makernotes.FlirMakernoteDirectory.TagEmissivity = 3 -> int
@@ -61,7 +70,73 @@ const MetadataExtractor.Formats.Flir.FlirRawDataDirectory.TagRawThermalImageHeig
const MetadataExtractor.Formats.Flir.FlirRawDataDirectory.TagRawThermalImageType = 34 -> int
const MetadataExtractor.Formats.Flir.FlirRawDataDirectory.TagRawThermalImageWidth = 2 -> int
const MetadataExtractor.Formats.Flir.FlirReader.JpegSegmentPreamble = "FLIR\0" -> string!
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartContourInterval = 47017 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartCorrDate = 47005 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartCountryOrigin = 47006 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartDepthUnits = 47009 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartFormat = 47001 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartMagVar = 47010 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartMagVarAnnChange = 47012 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartMagVarYear = 47011 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartRasterEdition = 47007 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartSoundingDatum = 47008 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartSource = 47002 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartSourceDate = 47004 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartSourceEdition = 47003 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartWGSNSShift = 47013 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagCitation = 1026 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeodeticDatum = 2050 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicAngularUnits = 2054 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicAngularUnitSize = 2055 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicAzimuthUnits = 2060 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicCitation = 2049 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicEllipsoid = 2056 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicInvFlattening = 2059 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicLinearUnits = 2052 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicLinearUnitSize = 2053 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicPrimeMeridian = 2051 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicPrimeMeridianLong = 2061 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicSemiMajorAxis = 2057 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicSemiMinorAxis = 2058 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicToWgs84 = 2062 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicType = 2048 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagInsetNWPixelX = 47015 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagInsetNWPixelY = 47016 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagModelType = 1024 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjAzimuthAngle = 3094 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjCenterEasting = 3090 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjCenterLat = 3089 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjCenterLong = 3088 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjCenterNorthing = 3091 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjectedCoordinateTransform = 3075 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjectedCSCitation = 3073 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjectedCSType = 3072 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjection = 3074 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjFalseEasting = 3082 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjFalseNorthing = 3083 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjFalseOriginEasting = 3086 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjFalseOriginLat = 3085 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjFalseOriginLong = 3084 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjFalseOriginNorthing = 3087 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjLinearUnits = 3076 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjLinearUnitSize = 3077 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjNatOriginLat = 3081 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjNatOriginLong = 3080 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjRectifiedGridAngle = 3096 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjScaleAtCenter = 3093 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjScaleAtNatOrigin = 3092 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjStdParallel1 = 3078 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjStdParallel2 = 3079 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjStraightVertPoleLong = 3095 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagRasterType = 1025 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagVerticalCitation = 4097 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagVerticalCSType = 4096 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagVerticalDatum = 4098 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagVerticalUnits = 4099 -> int
MetadataExtractor.Directory.Directory(System.Collections.Generic.Dictionary? tagNameMap) -> void
+MetadataExtractor.Directory.RemoveTag(int tagId) -> void
+MetadataExtractor.Formats.Exif.ExifDescriptorBase.GetExtraSamplesDescription() -> string?
+MetadataExtractor.Formats.Exif.ExifDescriptorBase.GetSampleFormatDescription() -> string?
MetadataExtractor.Formats.Exif.ExifDirectoryBase.ExifDirectoryBase(System.Collections.Generic.Dictionary! tagNameMap) -> void
MetadataExtractor.Formats.Exif.Makernotes.AppleMakernoteDescriptor.GetAccelerationVectorDescription() -> string?
MetadataExtractor.Formats.Exif.Makernotes.AppleMakernoteDescriptor.GetHdrImageTypeDescription() -> string?
@@ -84,6 +159,21 @@ MetadataExtractor.Formats.Flir.FlirReader.ExtractRawThermalImage.set -> void
MetadataExtractor.Formats.Flir.FlirReader.FlirReader() -> void
MetadataExtractor.Formats.Flir.FlirReader.ReadJpegSegments(System.Collections.Generic.IEnumerable! segments) -> System.Collections.Generic.IEnumerable!
MetadataExtractor.Formats.Flir.FlirReader.SegmentTypes.get -> System.Collections.Generic.ICollection!
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GeoTiffDescriptor(MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory! directory) -> void
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetChartFormatDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetChartSoundingDatumDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetGeodeticDatumDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetGeographicEllipsoidDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetGeographicTypeDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetModelTypeDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetPrimeMeridianDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetProjectedCoordinateSystemDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetProjectedCoordinateTransformDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetProjectionDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetRasterTypeDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory
+MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.GeoTiffDirectory() -> void
MetadataExtractor.Formats.Jpeg.HuffmanTable.HuffmanTable() -> void
MetadataExtractor.Formats.Jpeg.JpegSegmentWithPreambleMetadataReader
MetadataExtractor.Formats.Jpeg.JpegSegmentWithPreambleMetadataReader.JpegSegmentWithPreambleMetadataReader() -> void
@@ -101,7 +191,8 @@ MetadataExtractor.Formats.Tiff.IfdIdentity
MetadataExtractor.Formats.Tiff.IfdIdentity.IfdIdentity() -> void
MetadataExtractor.Formats.Tiff.IfdIdentity.Kind.get -> object?
MetadataExtractor.Formats.Tiff.IfdIdentity.Offset.get -> int
-MetadataExtractor.Formats.Tiff.ITiffHandler.CustomProcessTag(int tagOffset, System.Collections.Generic.HashSet! processedIfds, MetadataExtractor.IO.IndexedReader! reader, int tagId, int byteCount, bool isBigTiff) -> bool
+MetadataExtractor.Formats.Tiff.ITiffHandler.CustomProcessTag(in MetadataExtractor.Formats.Tiff.TiffReaderContext context, int tagId, int valueOffset, int byteCount) -> bool
+MetadataExtractor.Formats.Tiff.ITiffHandler.EndingIfd(in MetadataExtractor.Formats.Tiff.TiffReaderContext context) -> void
MetadataExtractor.Formats.Tiff.ITiffHandler.Kind.get -> object?
MetadataExtractor.Formats.Tiff.ITiffHandler.ProcessTiffMarker(ushort marker) -> MetadataExtractor.Formats.Tiff.TiffStandard
MetadataExtractor.Formats.Tiff.ITiffHandler.SetInt64S(int tagId, long int64S) -> void
@@ -113,6 +204,15 @@ MetadataExtractor.Formats.Tiff.TiffDataFormat.ComponentSizeBytes.get -> byte
MetadataExtractor.Formats.Tiff.TiffDataFormatCode.Ifd8 = 18 -> MetadataExtractor.Formats.Tiff.TiffDataFormatCode
MetadataExtractor.Formats.Tiff.TiffDataFormatCode.Int64S = 17 -> MetadataExtractor.Formats.Tiff.TiffDataFormatCode
MetadataExtractor.Formats.Tiff.TiffDataFormatCode.Int64U = 16 -> MetadataExtractor.Formats.Tiff.TiffDataFormatCode
+MetadataExtractor.Formats.Tiff.TiffReaderContext
+MetadataExtractor.Formats.Tiff.TiffReaderContext.IsBigTiff.get -> bool
+MetadataExtractor.Formats.Tiff.TiffReaderContext.IsMotorolaByteOrder.get -> bool
+MetadataExtractor.Formats.Tiff.TiffReaderContext.Reader.get -> MetadataExtractor.IO.IndexedReader!
+MetadataExtractor.Formats.Tiff.TiffReaderContext.TiffReaderContext() -> void
+MetadataExtractor.Formats.Tiff.TiffReaderContext.TiffReaderContext(MetadataExtractor.IO.IndexedReader! reader, bool isMotorolaByteOrder, bool isBigTiff) -> void
+MetadataExtractor.Formats.Tiff.TiffReaderContext.TryVisitIfd(int ifdOffset, object? kind) -> bool
+MetadataExtractor.Formats.Tiff.TiffReaderContext.WithByteOrder(bool isMotorolaByteOrder) -> MetadataExtractor.Formats.Tiff.TiffReaderContext
+MetadataExtractor.Formats.Tiff.TiffReaderContext.WithShiftedBaseOffset(int baseOffset) -> MetadataExtractor.Formats.Tiff.TiffReaderContext
MetadataExtractor.Formats.Tiff.TiffStandard
MetadataExtractor.Formats.Tiff.TiffStandard.BigTiff = 1 -> MetadataExtractor.Formats.Tiff.TiffStandard
MetadataExtractor.Formats.Tiff.TiffStandard.Tiff = 0 -> MetadataExtractor.Formats.Tiff.TiffStandard
@@ -138,8 +238,10 @@ const MetadataExtractor.Formats.QuickTime.QuickTimeMetadataHeaderDirectory.TagOr
const MetadataExtractor.Formats.QuickTime.QuickTimeMetadataHeaderDirectory.TagPixelDensity = 33 -> int
MetadataExtractor.Rational.Rational() -> void
MetadataExtractor.StringValue.StringValue() -> void
+MetadataExtractor.StringValue.ToString(int index, int count) -> string!
override MetadataExtractor.Formats.Exif.ExifReader.SegmentTypes.get -> System.Collections.Generic.ICollection!
-override MetadataExtractor.Formats.Exif.ExifTiffHandler.CustomProcessTag(int tagOffset, System.Collections.Generic.HashSet! processedIfds, MetadataExtractor.IO.IndexedReader! reader, int tagId, int byteCount, bool isBigTiff) -> bool
+override MetadataExtractor.Formats.Exif.ExifTiffHandler.CustomProcessTag(in MetadataExtractor.Formats.Tiff.TiffReaderContext context, int tagId, int valueOffset, int byteCount) -> bool
+override MetadataExtractor.Formats.Exif.ExifTiffHandler.EndingIfd(in MetadataExtractor.Formats.Tiff.TiffReaderContext context) -> void
override MetadataExtractor.Formats.Exif.ExifTiffHandler.ProcessTiffMarker(ushort marker) -> MetadataExtractor.Formats.Tiff.TiffStandard
override MetadataExtractor.Formats.Exif.ExifTiffHandler.TryCustomProcessFormat(int tagId, MetadataExtractor.Formats.Tiff.TiffDataFormatCode formatCode, ulong componentCount, out ulong byteCount) -> bool
override MetadataExtractor.Formats.Exif.Makernotes.FlirMakernoteDirectory.Name.get -> string!
@@ -147,11 +249,13 @@ override MetadataExtractor.Formats.Flir.FlirCameraInfoDescriptor.GetDescription(
override MetadataExtractor.Formats.Flir.FlirCameraInfoDirectory.Name.get -> string!
override MetadataExtractor.Formats.Flir.FlirHeaderDirectory.Name.get -> string!
override MetadataExtractor.Formats.Flir.FlirRawDataDirectory.Name.get -> string!
+override MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetDescription(int tagType) -> string?
+override MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.Name.get -> string!
override MetadataExtractor.Formats.Jfif.JfifReader.SegmentTypes.get -> System.Collections.Generic.ICollection!
override MetadataExtractor.Formats.Jfxx.JfxxReader.SegmentTypes.get -> System.Collections.Generic.ICollection!
override MetadataExtractor.Formats.Jpeg.JpegSegment.ToString() -> string!
override MetadataExtractor.Formats.Photoshop.PhotoshopReader.SegmentTypes.get -> System.Collections.Generic.ICollection!
-override MetadataExtractor.Formats.Photoshop.PhotoshopTiffHandler.CustomProcessTag(int tagOffset, System.Collections.Generic.HashSet! processedIfds, MetadataExtractor.IO.IndexedReader! reader, int tagId, int byteCount, bool isBigTiff) -> bool
+override MetadataExtractor.Formats.Photoshop.PhotoshopTiffHandler.CustomProcessTag(in MetadataExtractor.Formats.Tiff.TiffReaderContext context, int tagId, int valueOffset, int byteCount) -> bool
override MetadataExtractor.Formats.QuickTime.QuickTimeMetadataHeaderDescriptor.GetDescription(int tagType) -> string?
override MetadataExtractor.Formats.QuickTime.QuickTimeTiffHandler.ProcessTiffMarker(ushort marker) -> MetadataExtractor.Formats.Tiff.TiffStandard
static MetadataExtractor.DirectoryExtensions.GetUInt64(this MetadataExtractor.Directory! directory, int tagType) -> ulong
@@ -159,9 +263,10 @@ static MetadataExtractor.DirectoryExtensions.TryGetUInt64(this MetadataExtractor
static MetadataExtractor.Formats.Exif.ExifReader.JpegSegmentPreambleLength.get -> int
static MetadataExtractor.Formats.Jpeg.JpegMetadataReader.AllReaders.get -> System.Collections.Generic.IEnumerable!
static MetadataExtractor.Formats.QuickTime.QuickTimeMetadataHeaderDirectory.TryGetTag(string! name, out int tagType) -> bool
-static MetadataExtractor.Formats.Tiff.TiffReader.ProcessIfd(MetadataExtractor.Formats.Tiff.ITiffHandler! handler, MetadataExtractor.IO.IndexedReader! reader, System.Collections.Generic.HashSet! processedIfds, int ifdOffset, bool isBigTiff) -> void
+static MetadataExtractor.Formats.Tiff.TiffReader.ProcessIfd(MetadataExtractor.Formats.Tiff.ITiffHandler! handler, MetadataExtractor.Formats.Tiff.TiffReaderContext context, int ifdOffset) -> void
static readonly MetadataExtractor.Formats.Png.PngChunkType.eXIf -> MetadataExtractor.Formats.Png.PngChunkType!
static readonly MetadataExtractor.Formats.Tiff.TiffDataFormat.Ifd8 -> MetadataExtractor.Formats.Tiff.TiffDataFormat!
static readonly MetadataExtractor.Formats.Tiff.TiffDataFormat.Int64S -> MetadataExtractor.Formats.Tiff.TiffDataFormat!
static readonly MetadataExtractor.Formats.Tiff.TiffDataFormat.Int64U -> MetadataExtractor.Formats.Tiff.TiffDataFormat!
virtual MetadataExtractor.Directory.TryGetTagName(int tagType, out string? tagName) -> bool
+virtual MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.EndingIfd(in MetadataExtractor.Formats.Tiff.TiffReaderContext context) -> void
diff --git a/MetadataExtractor/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt b/MetadataExtractor/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt
index e6342f3bc..350d7db0e 100644
--- a/MetadataExtractor/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt
+++ b/MetadataExtractor/PublicAPI/netstandard2.0/PublicAPI.Shipped.txt
@@ -1294,7 +1294,6 @@ MetadataExtractor.Formats.Tiff.DirectoryTiffHandler
MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.CurrentDirectory.get -> MetadataExtractor.Directory?
MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.Directories.get -> System.Collections.Generic.List!
MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.DirectoryTiffHandler(System.Collections.Generic.List! directories) -> void
-MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.EndingIfd() -> void
MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.Error(string! message) -> void
MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.PushDirectory(MetadataExtractor.Directory! directory) -> void
MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.SetByteArray(int tagId, byte[]! bytes) -> void
@@ -1319,7 +1318,6 @@ MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.SetRationalArray(int tagId,
MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.SetString(int tagId, MetadataExtractor.StringValue stringValue) -> void
MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.Warn(string! message) -> void
MetadataExtractor.Formats.Tiff.ITiffHandler
-MetadataExtractor.Formats.Tiff.ITiffHandler.EndingIfd() -> void
MetadataExtractor.Formats.Tiff.ITiffHandler.Error(string! message) -> void
MetadataExtractor.Formats.Tiff.ITiffHandler.HasFollowerIfd() -> bool
MetadataExtractor.Formats.Tiff.ITiffHandler.SetByteArray(int tagId, byte[]! bytes) -> void
diff --git a/MetadataExtractor/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt b/MetadataExtractor/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt
index 78af04311..308c37652 100644
--- a/MetadataExtractor/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt
+++ b/MetadataExtractor/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt
@@ -2,9 +2,18 @@
abstract MetadataExtractor.Formats.Jpeg.JpegSegmentWithPreambleMetadataReader.Extract(byte[]! segmentBytes, int preambleLength) -> System.Collections.Generic.IEnumerable!
abstract MetadataExtractor.Formats.Jpeg.JpegSegmentWithPreambleMetadataReader.PreambleBytes.get -> byte[]!
abstract MetadataExtractor.Formats.Jpeg.JpegSegmentWithPreambleMetadataReader.SegmentTypes.get -> System.Collections.Generic.ICollection!
-abstract MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.CustomProcessTag(int tagOffset, System.Collections.Generic.HashSet! processedIfds, MetadataExtractor.IO.IndexedReader! reader, int tagId, int byteCount, bool isBigTiff) -> bool
+abstract MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.CustomProcessTag(in MetadataExtractor.Formats.Tiff.TiffReaderContext context, int tagId, int valueOffset, int byteCount) -> bool
abstract MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.ProcessTiffMarker(ushort marker) -> MetadataExtractor.Formats.Tiff.TiffStandard
abstract MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.TryCustomProcessFormat(int tagId, MetadataExtractor.Formats.Tiff.TiffDataFormatCode formatCode, ulong componentCount, out ulong byteCount) -> bool
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagExtraSamples = 338 -> int
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagGdalMetadata = 42112 -> int
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagGdalNoData = 42113 -> int
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagGeoTiffGeoAsciiParams = 34737 -> int
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagGeoTiffGeoDoubleParams = 34736 -> int
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagGeoTiffGeoKeys = 34735 -> int
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagModelTiePoint = 33922 -> int
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagPixelScale = 33550 -> int
+const MetadataExtractor.Formats.Exif.ExifDirectoryBase.TagSampleFormat = 339 -> int
const MetadataExtractor.Formats.Exif.Makernotes.FlirMakernoteDirectory.TagCameraTemperatureRangeMax = 6 -> int
const MetadataExtractor.Formats.Exif.Makernotes.FlirMakernoteDirectory.TagCameraTemperatureRangeMin = 5 -> int
const MetadataExtractor.Formats.Exif.Makernotes.FlirMakernoteDirectory.TagEmissivity = 3 -> int
@@ -61,7 +70,73 @@ const MetadataExtractor.Formats.Flir.FlirRawDataDirectory.TagRawThermalImageHeig
const MetadataExtractor.Formats.Flir.FlirRawDataDirectory.TagRawThermalImageType = 34 -> int
const MetadataExtractor.Formats.Flir.FlirRawDataDirectory.TagRawThermalImageWidth = 2 -> int
const MetadataExtractor.Formats.Flir.FlirReader.JpegSegmentPreamble = "FLIR\0" -> string!
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartContourInterval = 47017 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartCorrDate = 47005 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartCountryOrigin = 47006 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartDepthUnits = 47009 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartFormat = 47001 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartMagVar = 47010 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartMagVarAnnChange = 47012 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartMagVarYear = 47011 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartRasterEdition = 47007 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartSoundingDatum = 47008 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartSource = 47002 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartSourceDate = 47004 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartSourceEdition = 47003 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagChartWGSNSShift = 47013 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagCitation = 1026 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeodeticDatum = 2050 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicAngularUnits = 2054 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicAngularUnitSize = 2055 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicAzimuthUnits = 2060 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicCitation = 2049 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicEllipsoid = 2056 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicInvFlattening = 2059 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicLinearUnits = 2052 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicLinearUnitSize = 2053 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicPrimeMeridian = 2051 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicPrimeMeridianLong = 2061 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicSemiMajorAxis = 2057 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicSemiMinorAxis = 2058 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicToWgs84 = 2062 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagGeographicType = 2048 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagInsetNWPixelX = 47015 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagInsetNWPixelY = 47016 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagModelType = 1024 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjAzimuthAngle = 3094 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjCenterEasting = 3090 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjCenterLat = 3089 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjCenterLong = 3088 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjCenterNorthing = 3091 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjectedCoordinateTransform = 3075 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjectedCSCitation = 3073 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjectedCSType = 3072 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjection = 3074 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjFalseEasting = 3082 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjFalseNorthing = 3083 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjFalseOriginEasting = 3086 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjFalseOriginLat = 3085 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjFalseOriginLong = 3084 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjFalseOriginNorthing = 3087 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjLinearUnits = 3076 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjLinearUnitSize = 3077 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjNatOriginLat = 3081 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjNatOriginLong = 3080 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjRectifiedGridAngle = 3096 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjScaleAtCenter = 3093 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjScaleAtNatOrigin = 3092 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjStdParallel1 = 3078 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjStdParallel2 = 3079 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagProjStraightVertPoleLong = 3095 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagRasterType = 1025 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagVerticalCitation = 4097 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagVerticalCSType = 4096 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagVerticalDatum = 4098 -> int
+const MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.TagVerticalUnits = 4099 -> int
MetadataExtractor.Directory.Directory(System.Collections.Generic.Dictionary? tagNameMap) -> void
+MetadataExtractor.Directory.RemoveTag(int tagId) -> void
+MetadataExtractor.Formats.Exif.ExifDescriptorBase.GetExtraSamplesDescription() -> string?
+MetadataExtractor.Formats.Exif.ExifDescriptorBase.GetSampleFormatDescription() -> string?
MetadataExtractor.Formats.Exif.ExifDirectoryBase.ExifDirectoryBase(System.Collections.Generic.Dictionary! tagNameMap) -> void
MetadataExtractor.Formats.Exif.Makernotes.AppleMakernoteDescriptor.GetAccelerationVectorDescription() -> string?
MetadataExtractor.Formats.Exif.Makernotes.AppleMakernoteDescriptor.GetHdrImageTypeDescription() -> string?
@@ -84,6 +159,21 @@ MetadataExtractor.Formats.Flir.FlirReader.ExtractRawThermalImage.set -> void
MetadataExtractor.Formats.Flir.FlirReader.FlirReader() -> void
MetadataExtractor.Formats.Flir.FlirReader.ReadJpegSegments(System.Collections.Generic.IEnumerable! segments) -> System.Collections.Generic.IEnumerable!
MetadataExtractor.Formats.Flir.FlirReader.SegmentTypes.get -> System.Collections.Generic.ICollection!
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GeoTiffDescriptor(MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory! directory) -> void
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetChartFormatDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetChartSoundingDatumDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetGeodeticDatumDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetGeographicEllipsoidDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetGeographicTypeDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetModelTypeDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetPrimeMeridianDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetProjectedCoordinateSystemDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetProjectedCoordinateTransformDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetProjectionDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetRasterTypeDescription() -> string?
+MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory
+MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.GeoTiffDirectory() -> void
MetadataExtractor.Formats.Jpeg.HuffmanTable.HuffmanTable() -> void
MetadataExtractor.Formats.Jpeg.JpegSegmentWithPreambleMetadataReader
MetadataExtractor.Formats.Jpeg.JpegSegmentWithPreambleMetadataReader.JpegSegmentWithPreambleMetadataReader() -> void
@@ -101,7 +191,8 @@ MetadataExtractor.Formats.Tiff.IfdIdentity
MetadataExtractor.Formats.Tiff.IfdIdentity.IfdIdentity() -> void
MetadataExtractor.Formats.Tiff.IfdIdentity.Kind.get -> object?
MetadataExtractor.Formats.Tiff.IfdIdentity.Offset.get -> int
-MetadataExtractor.Formats.Tiff.ITiffHandler.CustomProcessTag(int tagOffset, System.Collections.Generic.HashSet! processedIfds, MetadataExtractor.IO.IndexedReader! reader, int tagId, int byteCount, bool isBigTiff) -> bool
+MetadataExtractor.Formats.Tiff.ITiffHandler.CustomProcessTag(in MetadataExtractor.Formats.Tiff.TiffReaderContext context, int tagId, int valueOffset, int byteCount) -> bool
+MetadataExtractor.Formats.Tiff.ITiffHandler.EndingIfd(in MetadataExtractor.Formats.Tiff.TiffReaderContext context) -> void
MetadataExtractor.Formats.Tiff.ITiffHandler.Kind.get -> object?
MetadataExtractor.Formats.Tiff.ITiffHandler.ProcessTiffMarker(ushort marker) -> MetadataExtractor.Formats.Tiff.TiffStandard
MetadataExtractor.Formats.Tiff.ITiffHandler.SetInt64S(int tagId, long int64S) -> void
@@ -113,6 +204,15 @@ MetadataExtractor.Formats.Tiff.TiffDataFormat.ComponentSizeBytes.get -> byte
MetadataExtractor.Formats.Tiff.TiffDataFormatCode.Ifd8 = 18 -> MetadataExtractor.Formats.Tiff.TiffDataFormatCode
MetadataExtractor.Formats.Tiff.TiffDataFormatCode.Int64S = 17 -> MetadataExtractor.Formats.Tiff.TiffDataFormatCode
MetadataExtractor.Formats.Tiff.TiffDataFormatCode.Int64U = 16 -> MetadataExtractor.Formats.Tiff.TiffDataFormatCode
+MetadataExtractor.Formats.Tiff.TiffReaderContext
+MetadataExtractor.Formats.Tiff.TiffReaderContext.IsBigTiff.get -> bool
+MetadataExtractor.Formats.Tiff.TiffReaderContext.IsMotorolaByteOrder.get -> bool
+MetadataExtractor.Formats.Tiff.TiffReaderContext.Reader.get -> MetadataExtractor.IO.IndexedReader!
+MetadataExtractor.Formats.Tiff.TiffReaderContext.TiffReaderContext() -> void
+MetadataExtractor.Formats.Tiff.TiffReaderContext.TiffReaderContext(MetadataExtractor.IO.IndexedReader! reader, bool isMotorolaByteOrder, bool isBigTiff) -> void
+MetadataExtractor.Formats.Tiff.TiffReaderContext.TryVisitIfd(int ifdOffset, object? kind) -> bool
+MetadataExtractor.Formats.Tiff.TiffReaderContext.WithByteOrder(bool isMotorolaByteOrder) -> MetadataExtractor.Formats.Tiff.TiffReaderContext
+MetadataExtractor.Formats.Tiff.TiffReaderContext.WithShiftedBaseOffset(int baseOffset) -> MetadataExtractor.Formats.Tiff.TiffReaderContext
MetadataExtractor.Formats.Tiff.TiffStandard
MetadataExtractor.Formats.Tiff.TiffStandard.BigTiff = 1 -> MetadataExtractor.Formats.Tiff.TiffStandard
MetadataExtractor.Formats.Tiff.TiffStandard.Tiff = 0 -> MetadataExtractor.Formats.Tiff.TiffStandard
@@ -138,8 +238,10 @@ const MetadataExtractor.Formats.QuickTime.QuickTimeMetadataHeaderDirectory.TagOr
const MetadataExtractor.Formats.QuickTime.QuickTimeMetadataHeaderDirectory.TagPixelDensity = 33 -> int
MetadataExtractor.Rational.Rational() -> void
MetadataExtractor.StringValue.StringValue() -> void
+MetadataExtractor.StringValue.ToString(int index, int count) -> string!
override MetadataExtractor.Formats.Exif.ExifReader.SegmentTypes.get -> System.Collections.Generic.ICollection!
-override MetadataExtractor.Formats.Exif.ExifTiffHandler.CustomProcessTag(int tagOffset, System.Collections.Generic.HashSet! processedIfds, MetadataExtractor.IO.IndexedReader! reader, int tagId, int byteCount, bool isBigTiff) -> bool
+override MetadataExtractor.Formats.Exif.ExifTiffHandler.CustomProcessTag(in MetadataExtractor.Formats.Tiff.TiffReaderContext context, int tagId, int valueOffset, int byteCount) -> bool
+override MetadataExtractor.Formats.Exif.ExifTiffHandler.EndingIfd(in MetadataExtractor.Formats.Tiff.TiffReaderContext context) -> void
override MetadataExtractor.Formats.Exif.ExifTiffHandler.ProcessTiffMarker(ushort marker) -> MetadataExtractor.Formats.Tiff.TiffStandard
override MetadataExtractor.Formats.Exif.ExifTiffHandler.TryCustomProcessFormat(int tagId, MetadataExtractor.Formats.Tiff.TiffDataFormatCode formatCode, ulong componentCount, out ulong byteCount) -> bool
override MetadataExtractor.Formats.Exif.Makernotes.FlirMakernoteDirectory.Name.get -> string!
@@ -147,12 +249,14 @@ override MetadataExtractor.Formats.Flir.FlirCameraInfoDescriptor.GetDescription(
override MetadataExtractor.Formats.Flir.FlirCameraInfoDirectory.Name.get -> string!
override MetadataExtractor.Formats.Flir.FlirHeaderDirectory.Name.get -> string!
override MetadataExtractor.Formats.Flir.FlirRawDataDirectory.Name.get -> string!
+override MetadataExtractor.Formats.GeoTiff.GeoTiffDescriptor.GetDescription(int tagType) -> string?
+override MetadataExtractor.Formats.GeoTiff.GeoTiffDirectory.Name.get -> string!
override MetadataExtractor.Formats.Jfif.JfifReader.SegmentTypes.get -> System.Collections.Generic.ICollection!
override MetadataExtractor.Formats.Jfxx.JfxxReader.SegmentTypes.get -> System.Collections.Generic.ICollection!
override MetadataExtractor.Formats.Jpeg.JpegSegment.ToString() -> string!
override MetadataExtractor.Formats.Photoshop.PhotoshopDescriptor.GetDescription(int tagType) -> string?
override MetadataExtractor.Formats.Photoshop.PhotoshopReader.SegmentTypes.get -> System.Collections.Generic.ICollection!
-override MetadataExtractor.Formats.Photoshop.PhotoshopTiffHandler.CustomProcessTag(int tagOffset, System.Collections.Generic.HashSet! processedIfds, MetadataExtractor.IO.IndexedReader! reader, int tagId, int byteCount, bool isBigTiff) -> bool
+override MetadataExtractor.Formats.Photoshop.PhotoshopTiffHandler.CustomProcessTag(in MetadataExtractor.Formats.Tiff.TiffReaderContext context, int tagId, int valueOffset, int byteCount) -> bool
override MetadataExtractor.Formats.QuickTime.QuickTimeMetadataHeaderDescriptor.GetDescription(int tagType) -> string?
override MetadataExtractor.Formats.QuickTime.QuickTimeTiffHandler.ProcessTiffMarker(ushort marker) -> MetadataExtractor.Formats.Tiff.TiffStandard
static MetadataExtractor.DirectoryExtensions.GetUInt64(this MetadataExtractor.Directory! directory, int tagType) -> ulong
@@ -160,9 +264,10 @@ static MetadataExtractor.DirectoryExtensions.TryGetUInt64(this MetadataExtractor
static MetadataExtractor.Formats.Exif.ExifReader.JpegSegmentPreambleLength.get -> int
static MetadataExtractor.Formats.Jpeg.JpegMetadataReader.AllReaders.get -> System.Collections.Generic.IEnumerable!
static MetadataExtractor.Formats.QuickTime.QuickTimeMetadataHeaderDirectory.TryGetTag(string! name, out int tagType) -> bool
-static MetadataExtractor.Formats.Tiff.TiffReader.ProcessIfd(MetadataExtractor.Formats.Tiff.ITiffHandler! handler, MetadataExtractor.IO.IndexedReader! reader, System.Collections.Generic.HashSet! processedIfds, int ifdOffset, bool isBigTiff) -> void
+static MetadataExtractor.Formats.Tiff.TiffReader.ProcessIfd(MetadataExtractor.Formats.Tiff.ITiffHandler! handler, MetadataExtractor.Formats.Tiff.TiffReaderContext context, int ifdOffset) -> void
static readonly MetadataExtractor.Formats.Png.PngChunkType.eXIf -> MetadataExtractor.Formats.Png.PngChunkType!
static readonly MetadataExtractor.Formats.Tiff.TiffDataFormat.Ifd8 -> MetadataExtractor.Formats.Tiff.TiffDataFormat!
static readonly MetadataExtractor.Formats.Tiff.TiffDataFormat.Int64S -> MetadataExtractor.Formats.Tiff.TiffDataFormat!
static readonly MetadataExtractor.Formats.Tiff.TiffDataFormat.Int64U -> MetadataExtractor.Formats.Tiff.TiffDataFormat!
virtual MetadataExtractor.Directory.TryGetTagName(int tagType, out string? tagName) -> bool
+virtual MetadataExtractor.Formats.Tiff.DirectoryTiffHandler.EndingIfd(in MetadataExtractor.Formats.Tiff.TiffReaderContext context) -> void
diff --git a/MetadataExtractor/StringValue.cs b/MetadataExtractor/StringValue.cs
index dd7ede9d0..aad7db5cc 100644
--- a/MetadataExtractor/StringValue.cs
+++ b/MetadataExtractor/StringValue.cs
@@ -115,6 +115,8 @@ uint IConvertible.ToUInt32(IFormatProvider? provider)
public string ToString(Encoding encoder) => encoder.GetString(Bytes, 0, Bytes.Length);
+ public string ToString(int index, int count) => (Encoding ?? DefaultEncoding).GetString(Bytes, index, count);
+
#endregion
}
}