From 34fc4e84783b2c8f2830066c45d1ec0a14786338 Mon Sep 17 00:00:00 2001 From: Ildar Khayrutdinov Date: Fri, 18 Dec 2020 22:33:05 +0300 Subject: [PATCH] Use ExifProfile for tiff frame metadata --- .../Formats/Tiff/Ifd/DirectoryReader.cs | 14 +++-- .../Formats/Tiff/TiffDecoderCore.cs | 15 +++-- .../Tiff/TiffEncoderEntriesCollector.cs | 2 +- .../Formats/Tiff/TiffFrameMetadata.cs | 27 ++++----- .../Tiff/TiffFrameMetadataExtensions.cs | 59 ++++--------------- .../Metadata/Profiles/Exif/ExifProfile.cs | 4 ++ 6 files changed, 44 insertions(+), 77 deletions(-) diff --git a/src/ImageSharp/Formats/Tiff/Ifd/DirectoryReader.cs b/src/ImageSharp/Formats/Tiff/Ifd/DirectoryReader.cs index d5387166c..39931c4b6 100644 --- a/src/ImageSharp/Formats/Tiff/Ifd/DirectoryReader.cs +++ b/src/ImageSharp/Formats/Tiff/Ifd/DirectoryReader.cs @@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff this.tagReader = new EntryReader(stream); } - public IEnumerable Read() + public IEnumerable Read() { if (this.ReadHeader()) { @@ -55,13 +55,13 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff return true; } - private IEnumerable ReadIfds() + private IEnumerable ReadIfds() { - var list = new List(); + var list = new List(); while (this.nextIfdOffset != 0) { this.stream.Seek(this.nextIfdOffset); - IExifValue[] ifd = this.ReadIfd(); + ExifProfile ifd = this.ReadIfd(); list.Add(ifd); } @@ -70,7 +70,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff return list; } - private IExifValue[] ReadIfd() + private ExifProfile ReadIfd() { long pos = this.stream.Position; @@ -99,7 +99,9 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff TiffThrowHelper.ThrowOutOfRange("IFD"); } - return entries.ToArray(); + var profile = new ExifProfile(); + profile.InitializeInternal(entries); + return profile; } } } diff --git a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs index e6d5f873d..94a973b50 100644 --- a/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs +++ b/src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs @@ -106,11 +106,11 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff TiffStream tiffStream = CreateStream(stream); var reader = new DirectoryReader(tiffStream); - IEnumerable directories = reader.Read(); + IEnumerable directories = reader.Read(); var frames = new List>(); var framesMetadata = new List(); - foreach (IExifValue[] ifd in directories) + foreach (ExifProfile ifd in directories) { ImageFrame frame = this.DecodeFrame(ifd, out TiffFrameMetadata frameMetadata); frames.Add(frame); @@ -144,13 +144,12 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff TiffStream tiffStream = CreateStream(stream); var reader = new DirectoryReader(tiffStream); - IEnumerable directories = reader.Read(); + IEnumerable directories = reader.Read(); var framesMetadata = new List(); - foreach (IExifValue[] ifd in directories) + foreach (ExifProfile ifd in directories) { - var meta = new TiffFrameMetadata(); - meta.FrameTags.AddRange(ifd); + var meta = new TiffFrameMetadata() { FrameTags = ifd }; framesMetadata.Add(meta); } @@ -200,12 +199,12 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff /// /// The tiff frame. /// - private ImageFrame DecodeFrame(IExifValue[] tags, out TiffFrameMetadata frameMetaData) + private ImageFrame DecodeFrame(ExifProfile tags, out TiffFrameMetadata frameMetaData) where TPixel : unmanaged, IPixel { var coreMetadata = new ImageFrameMetadata(); frameMetaData = coreMetadata.GetTiffMetadata(); - frameMetaData.FrameTags.AddRange(tags); + frameMetaData.FrameTags = tags; this.VerifyAndParse(frameMetaData); diff --git a/src/ImageSharp/Formats/Tiff/TiffEncoderEntriesCollector.cs b/src/ImageSharp/Formats/Tiff/TiffEncoderEntriesCollector.cs index 5b26a8551..e440ae3dc 100644 --- a/src/ImageSharp/Formats/Tiff/TiffEncoderEntriesCollector.cs +++ b/src/ImageSharp/Formats/Tiff/TiffEncoderEntriesCollector.cs @@ -134,7 +134,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff private void ProcessMetadata(TiffFrameMetadata frameMetadata) { - foreach (IExifValue entry in frameMetadata.FrameTags) + foreach (IExifValue entry in frameMetadata.FrameTags.Values) { // todo: skip subIfd if (entry.DataType == ExifDataType.Ifd) diff --git a/src/ImageSharp/Formats/Tiff/TiffFrameMetadata.cs b/src/ImageSharp/Formats/Tiff/TiffFrameMetadata.cs index c9bab385a..6e61aa270 100644 --- a/src/ImageSharp/Formats/Tiff/TiffFrameMetadata.cs +++ b/src/ImageSharp/Formats/Tiff/TiffFrameMetadata.cs @@ -21,6 +21,8 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff private const TiffPredictor DefaultPredictor = TiffPredictor.None; + private ExifProfile frameTags; + /// /// Initializes a new instance of the class. /// @@ -29,9 +31,13 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff } /// - /// Gets the Tiff directory tags list. + /// Gets the Tiff directory tags. /// - public List FrameTags { get; internal set; } = new List(); + public ExifProfile FrameTags + { + get => this.frameTags ??= new ExifProfile(); + internal set => this.frameTags = value; + } /// Gets a general indication of the kind of data contained in this subfile. /// A general indication of the kind of data contained in this subfile. @@ -241,7 +247,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff public void ClearMetadata() { var tags = new List(); - foreach (IExifValue entry in this.FrameTags) + foreach (IExifValue entry in this.FrameTags.Values) { switch ((ExifTagValue)(ushort)entry.Tag) { @@ -261,19 +267,12 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff } } - this.FrameTags = tags; + var profile = new ExifProfile(); + profile.InitializeInternal(tags); + this.FrameTags = profile; } /// - public IDeepCloneable DeepClone() - { - var tags = new List(); - foreach (IExifValue entry in this.FrameTags) - { - tags.Add(entry.DeepClone()); - } - - return new TiffFrameMetadata() { FrameTags = tags }; - } + public IDeepCloneable DeepClone() => new TiffFrameMetadata() { FrameTags = this.FrameTags.DeepClone() }; } } diff --git a/src/ImageSharp/Formats/Tiff/TiffFrameMetadataExtensions.cs b/src/ImageSharp/Formats/Tiff/TiffFrameMetadataExtensions.cs index aea12dbe5..7229011f5 100644 --- a/src/ImageSharp/Formats/Tiff/TiffFrameMetadataExtensions.cs +++ b/src/ImageSharp/Formats/Tiff/TiffFrameMetadataExtensions.cs @@ -31,7 +31,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff public static bool TryGetArray(this TiffFrameMetadata meta, ExifTag tag, out T[] result) where T : struct { - foreach (IExifValue entry in meta.FrameTags) + foreach (IExifValue entry in meta.FrameTags.Values) { if (entry.Tag == tag) { @@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff public static string GetString(this TiffFrameMetadata meta, ExifTag tag) { - foreach (IExifValue entry in meta.FrameTags) + foreach (IExifValue entry in meta.FrameTags.Values) { if (entry.Tag == tag) { @@ -80,13 +80,8 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff return null; } - public static bool SetString(this TiffFrameMetadata meta, ExifTag tag, string value) - { - IExifValue obj = FindOrCreate(meta, tag); - DebugGuard.IsTrue(obj.DataType == ExifDataType.Ascii, "Expected string entry"); - - return obj.TrySetValue(value); - } + public static void SetString(this TiffFrameMetadata meta, ExifTag tag, string value) => + meta.FrameTags.SetValueInternal(tag, value); public static TEnum? GetSingleEnumNullable(this TiffFrameMetadata meta, ExifTag tag) where TEnum : struct @@ -105,15 +100,10 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff where TTagValue : struct => meta.GetSingleEnumNullable(tag) ?? (defaultValue != null ? defaultValue.Value : throw TiffThrowHelper.TagNotFound(nameof(tag))); - public static bool SetSingleEnum(this TiffFrameMetadata meta, ExifTag tag, TEnum value) + public static void SetSingleEnum(this TiffFrameMetadata meta, ExifTag tag, TEnum value) where TEnum : struct where TTagValue : struct - { - IExifValue obj = FindOrCreate(meta, tag); - - object val = (TTagValue)(object)value; - return obj.TrySetValue(val); - } + => meta.FrameTags.SetValueInternal(tag, value); public static T GetSingle(this TiffFrameMetadata meta, ExifTag tag) where T : struct @@ -129,7 +119,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff public static bool TryGetSingle(this TiffFrameMetadata meta, ExifTag tag, out T result) where T : struct { - foreach (IExifValue entry in meta.FrameTags) + foreach (IExifValue entry in meta.FrameTags.Values) { if (entry.Tag == tag) { @@ -146,20 +136,14 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff return false; } - public static bool SetSingle(this TiffFrameMetadata meta, ExifTag tag, T value) + public static void SetSingle(this TiffFrameMetadata meta, ExifTag tag, T value) where T : struct - { - IExifValue obj = FindOrCreate(meta, tag); - DebugGuard.IsTrue(!obj.IsArray, "Expected non array entry"); - - object val = value; - return obj.TrySetValue(val); - } + => meta.FrameTags.SetValueInternal(tag, value); public static bool Remove(this TiffFrameMetadata meta, ExifTag tag) { IExifValue obj = null; - foreach (IExifValue entry in meta.FrameTags) + foreach (IExifValue entry in meta.FrameTags.Values) { if (entry.Tag == tag) { @@ -170,31 +154,10 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff if (obj != null) { - return meta.FrameTags.Remove(obj); + return meta.FrameTags.RemoveValue(obj.Tag); } return false; } - - private static IExifValue FindOrCreate(TiffFrameMetadata meta, ExifTag tag) - { - IExifValue obj = null; - foreach (IExifValue entry in meta.FrameTags) - { - if (entry.Tag == tag) - { - obj = entry; - break; - } - } - - if (obj == null) - { - obj = ExifValues.Create(tag); - meta.FrameTags.Add(obj); - } - - return obj; - } } } diff --git a/src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs b/src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs index 55af45fb4..753b5d29c 100644 --- a/src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs +++ b/src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.IO; + using SixLabors.ImageSharp.PixelFormats; namespace SixLabors.ImageSharp.Metadata.Profiles.Exif @@ -258,6 +259,9 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif this.SyncResolution(ExifTag.YResolution, metadata.VerticalResolution); } + internal void InitializeInternal(List values) => + this.values = values; + private void SyncResolution(ExifTag tag, double resolution) { IExifValue value = this.GetValue(tag);