From 456369d6c222767afb8b67e66efe31d755a8aac0 Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Mon, 28 Aug 2023 20:22:14 +1000 Subject: [PATCH 1/4] Minor code formatting --- MetadataExtractor.Tools.FileProcessor/Program.cs | 2 +- MetadataExtractor/MetadataExtractor.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MetadataExtractor.Tools.FileProcessor/Program.cs b/MetadataExtractor.Tools.FileProcessor/Program.cs index 507ab98b3..6bd9e8ccd 100644 --- a/MetadataExtractor.Tools.FileProcessor/Program.cs +++ b/MetadataExtractor.Tools.FileProcessor/Program.cs @@ -90,7 +90,7 @@ private static int ProcessFileList(string[] argArray) } if (!markdownFormat) - Console.Out.WriteLine("Processed {0:#,##0.##} MB file in {1:#,##0.##} ms\n", new FileInfo(filePath).Length/(1024d*1024), stopwatch.Elapsed.TotalMilliseconds); + Console.Out.WriteLine("Processed {0:#,##0.##} MB file in {1:#,##0.##} ms\n", new FileInfo(filePath).Length / (1024d * 1024), stopwatch.Elapsed.TotalMilliseconds); if (markdownFormat) { diff --git a/MetadataExtractor/MetadataExtractor.csproj b/MetadataExtractor/MetadataExtractor.csproj index 23d5897fb..3a3f23364 100644 --- a/MetadataExtractor/MetadataExtractor.csproj +++ b/MetadataExtractor/MetadataExtractor.csproj @@ -24,7 +24,7 @@ Camera manufacturer specific support exists for Agfa, Canon, Casio, DJI, Epson, - + From 8a0edbce6691bb39c4aa92389a2ee76432b418e6 Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Mon, 28 Aug 2023 20:22:50 +1000 Subject: [PATCH 2/4] Use HIEF instead of HEIC for format short name This matches the Java library and seems more correct by the standard. --- MetadataExtractor/Util/FileType.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MetadataExtractor/Util/FileType.cs b/MetadataExtractor/Util/FileType.cs index 39dc343b7..18dcb6b02 100644 --- a/MetadataExtractor/Util/FileType.cs +++ b/MetadataExtractor/Util/FileType.cs @@ -121,7 +121,7 @@ public static class FileTypeExtensions "EPS", "TGA", "MP3", - "HEIC", + "HEIF", "MP4" }; From e6d4f72c4c448fedc808b94a77dffed55f0cd598 Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Mon, 28 Aug 2023 20:43:42 +1000 Subject: [PATCH 3/4] Support Apple run time makernote data This data is encoded as a bplist (binary property list). We add a `BplistReader` class with some basic support for this format -- enough to obtain what we need from the RunTime makernote data. Ported from the Java implementation. --- Directory.Build.props | 4 + .../Formats/Apple/BplistReader.cs | 200 ++++++++++++++++++ .../Formats/Exif/ExifTiffHandler.cs | 10 + .../AppleRunTimeMakernoteDescriptor.cs | 67 ++++++ .../AppleRunTimeMakernoteDirectory.cs | 100 +++++++++ .../PublicAPI/net35/PublicAPI.Unshipped.txt | 20 ++ .../PublicAPI/net45/PublicAPI.Unshipped.txt | 20 ++ .../netstandard1.3/PublicAPI.Unshipped.txt | 20 ++ .../netstandard2.0/PublicAPI.Unshipped.txt | 20 ++ 9 files changed, 461 insertions(+) create mode 100644 MetadataExtractor/Formats/Apple/BplistReader.cs create mode 100644 MetadataExtractor/Formats/Exif/Makernotes/AppleRunTimeMakernoteDescriptor.cs create mode 100644 MetadataExtractor/Formats/Exif/Makernotes/AppleRunTimeMakernoteDirectory.cs diff --git a/Directory.Build.props b/Directory.Build.props index c978f8bf6..a8f6613ed 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -40,6 +40,10 @@ + + all + runtime; build; native; contentfiles; analyzers + diff --git a/MetadataExtractor/Formats/Apple/BplistReader.cs b/MetadataExtractor/Formats/Apple/BplistReader.cs new file mode 100644 index 000000000..f715c9d50 --- /dev/null +++ b/MetadataExtractor/Formats/Apple/BplistReader.cs @@ -0,0 +1,200 @@ +// 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.Apple; + +/// +/// A limited-functionality binary property list (BPLIST) reader. +/// +public sealed class BplistReader +{ + // https://opensource.apple.com/source/CF/CF-550/ForFoundationOnly.h + // https://opensource.apple.com/source/CF/CF-550/CFBinaryPList.c + // https://synalysis.com/how-to-decode-apple-binary-property-list-files/ + + private static readonly byte[] _bplistHeader = { (byte)'b', (byte)'p', (byte)'l', (byte)'i', (byte)'s', (byte)'t', (byte)'0', (byte)'0' }; + + /// + /// Gets whether starts with the expected header bytes. + /// + public static bool IsValid(byte[] bplist) + { + if (bplist.Length < _bplistHeader.Length) + { + return false; + } + + for (int i = 0; i < _bplistHeader.Length; i++) + { + if (bplist[i] != _bplistHeader[i]) + { + return false; + } + } + + return true; + } + + public static PropertyListResults Parse(byte[] bplist) + { + if (!IsValid(bplist)) + { + throw new ArgumentException("Input is not a bplist.", nameof(bplist)); + } + + Trailer trailer = ReadTrailer(); + + SequentialByteArrayReader reader = new(bplist, baseIndex: checked((int)(trailer.OffsetTableOffset + trailer.TopObject))); + + int[] offsets = new int[(int)trailer.NumObjects]; + + for (long i = 0; i < trailer.NumObjects; i++) + { + if (trailer.OffsetIntSize == 1) + { + offsets[(int)i] = reader.GetByte(); + } + else if (trailer.OffsetIntSize == 2) + { + offsets[(int)i] = reader.GetUInt16(); + } + } + + List objects = new(); + + for (int i = 0; i < offsets.Length; i++) + { + reader = new SequentialByteArrayReader(bplist, offsets[i]); + + byte b = reader.GetByte(); + + byte objectFormat = (byte)((b >> 4) & 0x0F); + byte marker = (byte)(b & 0x0F); + + object obj = objectFormat switch + { + // dict + 0x0D => HandleDict(marker), + // string (ASCII) + 0x05 => reader.GetString(bytesRequested: marker & 0x0F, Encoding.ASCII), + // data + 0x04 => HandleData(marker), + // int + 0x01 => HandleInt(marker), + // unknown + _ => throw new NotSupportedException($"Unsupported object format {objectFormat:X2}.") + }; + + objects.Add(obj); + } + + return new PropertyListResults(objects, trailer); + + Trailer ReadTrailer() + { + SequentialByteArrayReader reader = new(bplist, bplist.Length - Trailer.SizeBytes); + + // Skip 5-byte unused values, 1-byte sort version. + reader.Skip(6); + + return new Trailer + { + OffsetIntSize = reader.GetByte(), + ObjectRefSize = reader.GetByte(), + NumObjects = reader.GetInt64(), + TopObject = reader.GetInt64(), + OffsetTableOffset = reader.GetInt64() + }; + } + + object HandleInt(byte marker) + { + return marker switch + { + 0 => (object)reader.GetByte(), + 1 => reader.GetInt16(), + 2 => reader.GetInt32(), + 3 => reader.GetInt64(), + _ => throw new NotSupportedException($"Unsupported int size {marker}.") + }; + } + + Dictionary HandleDict(byte count) + { + var keyRefs = new byte[count]; + + for (int j = 0; j < count; j++) + { + keyRefs[j] = reader.GetByte(); + } + + Dictionary map = new(); + + for (int j = 0; j < count; j++) + { + map.Add(keyRefs[j], reader.GetByte()); + } + + return map; + } + + object HandleData(byte marker) + { + int byteCount = marker; + + if (marker == 0x0F) + { + byte sizeMarker = reader.GetByte(); + + if (((sizeMarker >> 4) & 0x0F) != 1) + { + throw new NotSupportedException($"Invalid size marker {sizeMarker:X2}."); + } + + int sizeType = sizeMarker & 0x0F; + + if (sizeType == 0) + { + byteCount = reader.GetByte(); + } + else if (sizeType == 1) + { + byteCount = reader.GetUInt16(); + } + } + + return reader.GetBytes(byteCount); + } + } + + public sealed class PropertyListResults + { + private readonly List _objects; + private readonly Trailer _trailer; + + internal PropertyListResults(List objects, Trailer trailer) + { + _objects = objects; + _trailer = trailer; + } + + public Dictionary? GetTopObject() + { + return _objects[checked((int)_trailer.TopObject)] as Dictionary; + } + + public object Get(byte key) + { + return _objects[key]; + } + } + + internal class Trailer + { + public const int SizeBytes = 32; + public byte OffsetIntSize { get; init; } + public byte ObjectRefSize { get; init; } + public long NumObjects { get; init; } + public long TopObject { get; init; } + public long OffsetTableOffset { get; init; } + } +} diff --git a/MetadataExtractor/Formats/Exif/ExifTiffHandler.cs b/MetadataExtractor/Formats/Exif/ExifTiffHandler.cs index f6b336351..6a550e41e 100644 --- a/MetadataExtractor/Formats/Exif/ExifTiffHandler.cs +++ b/MetadataExtractor/Formats/Exif/ExifTiffHandler.cs @@ -210,6 +210,16 @@ public override bool CustomProcessTag(in TiffReaderContext context, int tagId, i return true; } + // Custom processing for Apple RunTime tag + if (tagId == AppleMakernoteDirectory.TagRunTime && CurrentDirectory is AppleMakernoteDirectory) + { + var bytes = context.Reader.GetBytes(valueOffset, byteCount); + var directory = AppleRunTimeMakernoteDirectory.Parse(bytes); + directory.Parent = CurrentDirectory; + Directories.Add(directory); + return true; + } + if (HandlePrintIM(CurrentDirectory!, tagId)) { var printIMDirectory = new PrintIMDirectory { Parent = CurrentDirectory }; diff --git a/MetadataExtractor/Formats/Exif/Makernotes/AppleRunTimeMakernoteDescriptor.cs b/MetadataExtractor/Formats/Exif/Makernotes/AppleRunTimeMakernoteDescriptor.cs new file mode 100644 index 000000000..ad7351b11 --- /dev/null +++ b/MetadataExtractor/Formats/Exif/Makernotes/AppleRunTimeMakernoteDescriptor.cs @@ -0,0 +1,67 @@ +// 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.Exif.Makernotes; + +public sealed class AppleRunTimeMakernoteDescriptor : TagDescriptor +{ + public AppleRunTimeMakernoteDescriptor(AppleRunTimeMakernoteDirectory directory) : base(directory) + { + } + + public override string? GetDescription(int tagType) + { + return tagType switch + { + AppleRunTimeMakernoteDirectory.TagFlags => GetFlagsDescription(), + AppleRunTimeMakernoteDirectory.TagValue => GetValueDescription(), + _ => base.GetDescription(tagType), + }; + } + + public string? GetFlagsDescription() + { + // flags bitmask details + // 0000 0001 = Valid + // 0000 0010 = Rounded + // 0000 0100 = Positive Infinity + // 0000 1000 = Negative Infinity + // 0001 0000 = Indefinite + + if (Directory.TryGetInt32(AppleRunTimeMakernoteDirectory.TagFlags, out var value)) + { + StringBuilder sb = new(); + + if ((value & 0x1) != 0) + sb.Append("Valid"); + else + sb.Append("Invalid"); + + if ((value & 0x2) != 0) + sb.Append(", rounded"); + + if ((value & 0x4) != 0) + sb.Append(", positive infinity"); + + if ((value & 0x8) != 0) + sb.Append(", negative infinity"); + + if ((value & 0x10) != 0) + sb.Append(", indefinite"); + + return sb.ToString(); + } + + return base.GetDescription(AppleRunTimeMakernoteDirectory.TagFlags); + } + + public string? GetValueDescription() + { + if (Directory.TryGetInt64(AppleRunTimeMakernoteDirectory.TagValue, out var value) && + Directory.TryGetInt64(AppleRunTimeMakernoteDirectory.TagScale, out var scale)) + { + return $"{value / scale} seconds"; + } + + return base.GetDescription(AppleRunTimeMakernoteDirectory.TagValue); + } +} diff --git a/MetadataExtractor/Formats/Exif/Makernotes/AppleRunTimeMakernoteDirectory.cs b/MetadataExtractor/Formats/Exif/Makernotes/AppleRunTimeMakernoteDirectory.cs new file mode 100644 index 000000000..1b86bc37d --- /dev/null +++ b/MetadataExtractor/Formats/Exif/Makernotes/AppleRunTimeMakernoteDirectory.cs @@ -0,0 +1,100 @@ +// 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 MetadataExtractor.Formats.Apple; + +namespace MetadataExtractor.Formats.Exif.Makernotes; + +public sealed class AppleRunTimeMakernoteDirectory : Directory +{ + public const int TagFlags = 1; + public const int TagEpoch = 2; + public const int TagScale = 3; + public const int TagValue = 4; + + private static readonly Dictionary _tagNameMap = new(); + + static AppleRunTimeMakernoteDirectory() + { + _tagNameMap[TagFlags] = "Flags"; + _tagNameMap[TagEpoch] = "Epoch"; + _tagNameMap[TagScale] = "Scale"; + _tagNameMap[TagValue] = "Value"; + } + + public AppleRunTimeMakernoteDirectory() : base(_tagNameMap) + { + SetDescriptor(new AppleRunTimeMakernoteDescriptor(this)); + } + + public override string Name => "Apple Run Time"; + + public static AppleRunTimeMakernoteDirectory Parse(byte[] bytes) + { + AppleRunTimeMakernoteDirectory directory = new(); + + if (!BplistReader.IsValid(bytes)) + { + directory.AddError("Input array is not a bplist."); + } + else + { + try + { + ProcessAppleRunTime(); + } + catch (IOException ex) + { + directory.AddError($"Error processing {nameof(AppleRunTimeMakernoteDirectory)}: {ex.Message}"); + } + } + + return directory; + + void ProcessAppleRunTime() + { + var results = BplistReader.Parse(bytes); + + var entrySet = results.GetTopObject(); + + if (entrySet is not null) + { + Dictionary values = new(entrySet.Count); + + foreach (var pair in entrySet) + { + var key = (string)results.Get(pair.Key); + var value = results.Get(pair.Value); + + values[key] = value; + } + + // https://developer.apple.com/documentation/coremedia/cmtime-u58 + + if (values.TryGetValue("flags", out var flagsObject)) + { + if (flagsObject is byte flags) + { + if ((flags & 0x1) == 0x1) + { + directory.Set(TagFlags, flags); + directory.Set(TagEpoch, (byte)values["epoch"]); + directory.Set(TagScale, (int)values["timescale"]); + directory.Set(TagValue, (long)values["value"]); + } + } + else if (flagsObject is string flagsString) + { + var parsedFlags = byte.Parse(flagsString); + if ((parsedFlags & 0x1) == 0x1) + { + directory.Set(TagFlags, parsedFlags); + directory.Set(TagEpoch, byte.Parse((string)values["epoch"])); + directory.Set(TagScale, int.Parse((string)values["timescale"])); + directory.Set(TagValue, long.Parse((string)values["value"])); + } + } + } + } + } + } +} diff --git a/MetadataExtractor/PublicAPI/net35/PublicAPI.Unshipped.txt b/MetadataExtractor/PublicAPI/net35/PublicAPI.Unshipped.txt index d961c0166..fabb1f02b 100644 --- a/MetadataExtractor/PublicAPI/net35/PublicAPI.Unshipped.txt +++ b/MetadataExtractor/PublicAPI/net35/PublicAPI.Unshipped.txt @@ -1,5 +1,9 @@ #nullable enable abstract MetadataExtractor.IO.IndexedReader.GetByteInternal(int index) -> byte +const MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory.TagEpoch = 2 -> int +const MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory.TagFlags = 1 -> int +const MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory.TagScale = 3 -> int +const MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory.TagValue = 4 -> int const MetadataExtractor.Formats.Exif.Makernotes.FujifilmMakernoteDirectory.TagImageNumber = 5176 -> int const MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl1Directory.TagBrightness = 52 -> int const MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl1Directory.TagContrast = 51 -> int @@ -34,6 +38,17 @@ const MetadataExtractor.Formats.Exif.Makernotes.NikonType2MakernoteDirectory.Tag const MetadataExtractor.Formats.Exif.Makernotes.NikonType2MakernoteDirectory.TagPictureControl2 = 189 -> int const MetadataExtractor.Formats.Exif.Makernotes.NikonType2MakernoteDirectory.TagRetouchInfo = 187 -> int const MetadataExtractor.Formats.Exif.Makernotes.NikonType2MakernoteDirectory.TagToningEffect = 179 -> int +MetadataExtractor.Formats.Apple.BplistReader +MetadataExtractor.Formats.Apple.BplistReader.BplistReader() -> void +MetadataExtractor.Formats.Apple.BplistReader.PropertyListResults +MetadataExtractor.Formats.Apple.BplistReader.PropertyListResults.Get(byte key) -> object! +MetadataExtractor.Formats.Apple.BplistReader.PropertyListResults.GetTopObject() -> System.Collections.Generic.Dictionary? +MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDescriptor +MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDescriptor.AppleRunTimeMakernoteDescriptor(MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory! directory) -> void +MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDescriptor.GetFlagsDescription() -> string? +MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDescriptor.GetValueDescription() -> string? +MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory +MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory.AppleRunTimeMakernoteDirectory() -> void MetadataExtractor.Formats.Exif.Makernotes.FujifilmMakernoteDescriptor.GetMakernoteVersionDescription() -> string? MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl1Descriptor MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl1Descriptor.GetFilterEffectDescription() -> string? @@ -50,9 +65,14 @@ MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl2Descriptor.NikonPi MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl2Directory MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl2Directory.NikonPictureControl2Directory() -> void MetadataExtractor.IO.IndexedReader.GetByte(int index) -> byte +override MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDescriptor.GetDescription(int tagType) -> string? +override MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory.Name.get -> string! override MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl1Descriptor.GetDescription(int tagType) -> string? override MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl1Directory.Name.get -> string! override MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl2Descriptor.GetDescription(int tagType) -> string? override MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl2Directory.Name.get -> string! override MetadataExtractor.IO.ByteArrayReader.GetByteInternal(int index) -> byte override MetadataExtractor.IO.IndexedSeekingReader.GetByteInternal(int index) -> byte +static MetadataExtractor.Formats.Apple.BplistReader.IsValid(byte[]! bplist) -> bool +static MetadataExtractor.Formats.Apple.BplistReader.Parse(byte[]! bplist) -> MetadataExtractor.Formats.Apple.BplistReader.PropertyListResults! +static MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory.Parse(byte[]! bytes) -> MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory! diff --git a/MetadataExtractor/PublicAPI/net45/PublicAPI.Unshipped.txt b/MetadataExtractor/PublicAPI/net45/PublicAPI.Unshipped.txt index d961c0166..fabb1f02b 100644 --- a/MetadataExtractor/PublicAPI/net45/PublicAPI.Unshipped.txt +++ b/MetadataExtractor/PublicAPI/net45/PublicAPI.Unshipped.txt @@ -1,5 +1,9 @@ #nullable enable abstract MetadataExtractor.IO.IndexedReader.GetByteInternal(int index) -> byte +const MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory.TagEpoch = 2 -> int +const MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory.TagFlags = 1 -> int +const MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory.TagScale = 3 -> int +const MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory.TagValue = 4 -> int const MetadataExtractor.Formats.Exif.Makernotes.FujifilmMakernoteDirectory.TagImageNumber = 5176 -> int const MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl1Directory.TagBrightness = 52 -> int const MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl1Directory.TagContrast = 51 -> int @@ -34,6 +38,17 @@ const MetadataExtractor.Formats.Exif.Makernotes.NikonType2MakernoteDirectory.Tag const MetadataExtractor.Formats.Exif.Makernotes.NikonType2MakernoteDirectory.TagPictureControl2 = 189 -> int const MetadataExtractor.Formats.Exif.Makernotes.NikonType2MakernoteDirectory.TagRetouchInfo = 187 -> int const MetadataExtractor.Formats.Exif.Makernotes.NikonType2MakernoteDirectory.TagToningEffect = 179 -> int +MetadataExtractor.Formats.Apple.BplistReader +MetadataExtractor.Formats.Apple.BplistReader.BplistReader() -> void +MetadataExtractor.Formats.Apple.BplistReader.PropertyListResults +MetadataExtractor.Formats.Apple.BplistReader.PropertyListResults.Get(byte key) -> object! +MetadataExtractor.Formats.Apple.BplistReader.PropertyListResults.GetTopObject() -> System.Collections.Generic.Dictionary? +MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDescriptor +MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDescriptor.AppleRunTimeMakernoteDescriptor(MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory! directory) -> void +MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDescriptor.GetFlagsDescription() -> string? +MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDescriptor.GetValueDescription() -> string? +MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory +MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory.AppleRunTimeMakernoteDirectory() -> void MetadataExtractor.Formats.Exif.Makernotes.FujifilmMakernoteDescriptor.GetMakernoteVersionDescription() -> string? MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl1Descriptor MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl1Descriptor.GetFilterEffectDescription() -> string? @@ -50,9 +65,14 @@ MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl2Descriptor.NikonPi MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl2Directory MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl2Directory.NikonPictureControl2Directory() -> void MetadataExtractor.IO.IndexedReader.GetByte(int index) -> byte +override MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDescriptor.GetDescription(int tagType) -> string? +override MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory.Name.get -> string! override MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl1Descriptor.GetDescription(int tagType) -> string? override MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl1Directory.Name.get -> string! override MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl2Descriptor.GetDescription(int tagType) -> string? override MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl2Directory.Name.get -> string! override MetadataExtractor.IO.ByteArrayReader.GetByteInternal(int index) -> byte override MetadataExtractor.IO.IndexedSeekingReader.GetByteInternal(int index) -> byte +static MetadataExtractor.Formats.Apple.BplistReader.IsValid(byte[]! bplist) -> bool +static MetadataExtractor.Formats.Apple.BplistReader.Parse(byte[]! bplist) -> MetadataExtractor.Formats.Apple.BplistReader.PropertyListResults! +static MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory.Parse(byte[]! bytes) -> MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory! diff --git a/MetadataExtractor/PublicAPI/netstandard1.3/PublicAPI.Unshipped.txt b/MetadataExtractor/PublicAPI/netstandard1.3/PublicAPI.Unshipped.txt index d961c0166..fabb1f02b 100644 --- a/MetadataExtractor/PublicAPI/netstandard1.3/PublicAPI.Unshipped.txt +++ b/MetadataExtractor/PublicAPI/netstandard1.3/PublicAPI.Unshipped.txt @@ -1,5 +1,9 @@ #nullable enable abstract MetadataExtractor.IO.IndexedReader.GetByteInternal(int index) -> byte +const MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory.TagEpoch = 2 -> int +const MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory.TagFlags = 1 -> int +const MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory.TagScale = 3 -> int +const MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory.TagValue = 4 -> int const MetadataExtractor.Formats.Exif.Makernotes.FujifilmMakernoteDirectory.TagImageNumber = 5176 -> int const MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl1Directory.TagBrightness = 52 -> int const MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl1Directory.TagContrast = 51 -> int @@ -34,6 +38,17 @@ const MetadataExtractor.Formats.Exif.Makernotes.NikonType2MakernoteDirectory.Tag const MetadataExtractor.Formats.Exif.Makernotes.NikonType2MakernoteDirectory.TagPictureControl2 = 189 -> int const MetadataExtractor.Formats.Exif.Makernotes.NikonType2MakernoteDirectory.TagRetouchInfo = 187 -> int const MetadataExtractor.Formats.Exif.Makernotes.NikonType2MakernoteDirectory.TagToningEffect = 179 -> int +MetadataExtractor.Formats.Apple.BplistReader +MetadataExtractor.Formats.Apple.BplistReader.BplistReader() -> void +MetadataExtractor.Formats.Apple.BplistReader.PropertyListResults +MetadataExtractor.Formats.Apple.BplistReader.PropertyListResults.Get(byte key) -> object! +MetadataExtractor.Formats.Apple.BplistReader.PropertyListResults.GetTopObject() -> System.Collections.Generic.Dictionary? +MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDescriptor +MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDescriptor.AppleRunTimeMakernoteDescriptor(MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory! directory) -> void +MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDescriptor.GetFlagsDescription() -> string? +MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDescriptor.GetValueDescription() -> string? +MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory +MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory.AppleRunTimeMakernoteDirectory() -> void MetadataExtractor.Formats.Exif.Makernotes.FujifilmMakernoteDescriptor.GetMakernoteVersionDescription() -> string? MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl1Descriptor MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl1Descriptor.GetFilterEffectDescription() -> string? @@ -50,9 +65,14 @@ MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl2Descriptor.NikonPi MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl2Directory MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl2Directory.NikonPictureControl2Directory() -> void MetadataExtractor.IO.IndexedReader.GetByte(int index) -> byte +override MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDescriptor.GetDescription(int tagType) -> string? +override MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory.Name.get -> string! override MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl1Descriptor.GetDescription(int tagType) -> string? override MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl1Directory.Name.get -> string! override MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl2Descriptor.GetDescription(int tagType) -> string? override MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl2Directory.Name.get -> string! override MetadataExtractor.IO.ByteArrayReader.GetByteInternal(int index) -> byte override MetadataExtractor.IO.IndexedSeekingReader.GetByteInternal(int index) -> byte +static MetadataExtractor.Formats.Apple.BplistReader.IsValid(byte[]! bplist) -> bool +static MetadataExtractor.Formats.Apple.BplistReader.Parse(byte[]! bplist) -> MetadataExtractor.Formats.Apple.BplistReader.PropertyListResults! +static MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory.Parse(byte[]! bytes) -> MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory! diff --git a/MetadataExtractor/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt b/MetadataExtractor/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt index d961c0166..fabb1f02b 100644 --- a/MetadataExtractor/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt +++ b/MetadataExtractor/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt @@ -1,5 +1,9 @@ #nullable enable abstract MetadataExtractor.IO.IndexedReader.GetByteInternal(int index) -> byte +const MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory.TagEpoch = 2 -> int +const MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory.TagFlags = 1 -> int +const MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory.TagScale = 3 -> int +const MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory.TagValue = 4 -> int const MetadataExtractor.Formats.Exif.Makernotes.FujifilmMakernoteDirectory.TagImageNumber = 5176 -> int const MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl1Directory.TagBrightness = 52 -> int const MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl1Directory.TagContrast = 51 -> int @@ -34,6 +38,17 @@ const MetadataExtractor.Formats.Exif.Makernotes.NikonType2MakernoteDirectory.Tag const MetadataExtractor.Formats.Exif.Makernotes.NikonType2MakernoteDirectory.TagPictureControl2 = 189 -> int const MetadataExtractor.Formats.Exif.Makernotes.NikonType2MakernoteDirectory.TagRetouchInfo = 187 -> int const MetadataExtractor.Formats.Exif.Makernotes.NikonType2MakernoteDirectory.TagToningEffect = 179 -> int +MetadataExtractor.Formats.Apple.BplistReader +MetadataExtractor.Formats.Apple.BplistReader.BplistReader() -> void +MetadataExtractor.Formats.Apple.BplistReader.PropertyListResults +MetadataExtractor.Formats.Apple.BplistReader.PropertyListResults.Get(byte key) -> object! +MetadataExtractor.Formats.Apple.BplistReader.PropertyListResults.GetTopObject() -> System.Collections.Generic.Dictionary? +MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDescriptor +MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDescriptor.AppleRunTimeMakernoteDescriptor(MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory! directory) -> void +MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDescriptor.GetFlagsDescription() -> string? +MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDescriptor.GetValueDescription() -> string? +MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory +MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory.AppleRunTimeMakernoteDirectory() -> void MetadataExtractor.Formats.Exif.Makernotes.FujifilmMakernoteDescriptor.GetMakernoteVersionDescription() -> string? MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl1Descriptor MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl1Descriptor.GetFilterEffectDescription() -> string? @@ -50,9 +65,14 @@ MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl2Descriptor.NikonPi MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl2Directory MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl2Directory.NikonPictureControl2Directory() -> void MetadataExtractor.IO.IndexedReader.GetByte(int index) -> byte +override MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDescriptor.GetDescription(int tagType) -> string? +override MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory.Name.get -> string! override MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl1Descriptor.GetDescription(int tagType) -> string? override MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl1Directory.Name.get -> string! override MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl2Descriptor.GetDescription(int tagType) -> string? override MetadataExtractor.Formats.Exif.Makernotes.NikonPictureControl2Directory.Name.get -> string! override MetadataExtractor.IO.ByteArrayReader.GetByteInternal(int index) -> byte override MetadataExtractor.IO.IndexedSeekingReader.GetByteInternal(int index) -> byte +static MetadataExtractor.Formats.Apple.BplistReader.IsValid(byte[]! bplist) -> bool +static MetadataExtractor.Formats.Apple.BplistReader.Parse(byte[]! bplist) -> MetadataExtractor.Formats.Apple.BplistReader.PropertyListResults! +static MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory.Parse(byte[]! bytes) -> MetadataExtractor.Formats.Exif.Makernotes.AppleRunTimeMakernoteDirectory! From 6d795615644b3199a3ac9f45116f9533bf32703e Mon Sep 17 00:00:00 2001 From: Drew Noakes Date: Mon, 28 Aug 2023 20:49:42 +1000 Subject: [PATCH 4/4] Add more spelling exceptions --- spelling.dic | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/spelling.dic b/spelling.dic index 575f6fec7..4f8daa5a9 100644 --- a/spelling.dic +++ b/spelling.dic @@ -1,12 +1,18 @@ async +avci +bplist Colour coloured Digilux +epsf exif Exiftool fffzzz Foveon ftyp +graymap +heic +heif ilst Imazen ints @@ -22,14 +28,19 @@ mvhd Netpbm Optio prfl +quicktime rationals Reconyx sbytes sszzz stdout +targa +Thunderscan tkhd trak trie +Truevision uncoloured uuid +webp Yakov