Browse Source

Use ExifProfile for tiff frame metadata

pull/1570/head
Ildar Khayrutdinov 5 years ago
parent
commit
34fc4e8478
  1. 14
      src/ImageSharp/Formats/Tiff/Ifd/DirectoryReader.cs
  2. 15
      src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs
  3. 2
      src/ImageSharp/Formats/Tiff/TiffEncoderEntriesCollector.cs
  4. 27
      src/ImageSharp/Formats/Tiff/TiffFrameMetadata.cs
  5. 59
      src/ImageSharp/Formats/Tiff/TiffFrameMetadataExtensions.cs
  6. 4
      src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs

14
src/ImageSharp/Formats/Tiff/Ifd/DirectoryReader.cs

@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
this.tagReader = new EntryReader(stream); this.tagReader = new EntryReader(stream);
} }
public IEnumerable<IExifValue[]> Read() public IEnumerable<ExifProfile> Read()
{ {
if (this.ReadHeader()) if (this.ReadHeader())
{ {
@ -55,13 +55,13 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
return true; return true;
} }
private IEnumerable<IExifValue[]> ReadIfds() private IEnumerable<ExifProfile> ReadIfds()
{ {
var list = new List<IExifValue[]>(); var list = new List<ExifProfile>();
while (this.nextIfdOffset != 0) while (this.nextIfdOffset != 0)
{ {
this.stream.Seek(this.nextIfdOffset); this.stream.Seek(this.nextIfdOffset);
IExifValue[] ifd = this.ReadIfd(); ExifProfile ifd = this.ReadIfd();
list.Add(ifd); list.Add(ifd);
} }
@ -70,7 +70,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
return list; return list;
} }
private IExifValue[] ReadIfd() private ExifProfile ReadIfd()
{ {
long pos = this.stream.Position; long pos = this.stream.Position;
@ -99,7 +99,9 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
TiffThrowHelper.ThrowOutOfRange("IFD"); TiffThrowHelper.ThrowOutOfRange("IFD");
} }
return entries.ToArray(); var profile = new ExifProfile();
profile.InitializeInternal(entries);
return profile;
} }
} }
} }

15
src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs

@ -106,11 +106,11 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
TiffStream tiffStream = CreateStream(stream); TiffStream tiffStream = CreateStream(stream);
var reader = new DirectoryReader(tiffStream); var reader = new DirectoryReader(tiffStream);
IEnumerable<IExifValue[]> directories = reader.Read(); IEnumerable<ExifProfile> directories = reader.Read();
var frames = new List<ImageFrame<TPixel>>(); var frames = new List<ImageFrame<TPixel>>();
var framesMetadata = new List<TiffFrameMetadata>(); var framesMetadata = new List<TiffFrameMetadata>();
foreach (IExifValue[] ifd in directories) foreach (ExifProfile ifd in directories)
{ {
ImageFrame<TPixel> frame = this.DecodeFrame<TPixel>(ifd, out TiffFrameMetadata frameMetadata); ImageFrame<TPixel> frame = this.DecodeFrame<TPixel>(ifd, out TiffFrameMetadata frameMetadata);
frames.Add(frame); frames.Add(frame);
@ -144,13 +144,12 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
TiffStream tiffStream = CreateStream(stream); TiffStream tiffStream = CreateStream(stream);
var reader = new DirectoryReader(tiffStream); var reader = new DirectoryReader(tiffStream);
IEnumerable<IExifValue[]> directories = reader.Read(); IEnumerable<ExifProfile> directories = reader.Read();
var framesMetadata = new List<TiffFrameMetadata>(); var framesMetadata = new List<TiffFrameMetadata>();
foreach (IExifValue[] ifd in directories) foreach (ExifProfile ifd in directories)
{ {
var meta = new TiffFrameMetadata(); var meta = new TiffFrameMetadata() { FrameTags = ifd };
meta.FrameTags.AddRange(ifd);
framesMetadata.Add(meta); framesMetadata.Add(meta);
} }
@ -200,12 +199,12 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
/// <returns> /// <returns>
/// The tiff frame. /// The tiff frame.
/// </returns> /// </returns>
private ImageFrame<TPixel> DecodeFrame<TPixel>(IExifValue[] tags, out TiffFrameMetadata frameMetaData) private ImageFrame<TPixel> DecodeFrame<TPixel>(ExifProfile tags, out TiffFrameMetadata frameMetaData)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
var coreMetadata = new ImageFrameMetadata(); var coreMetadata = new ImageFrameMetadata();
frameMetaData = coreMetadata.GetTiffMetadata(); frameMetaData = coreMetadata.GetTiffMetadata();
frameMetaData.FrameTags.AddRange(tags); frameMetaData.FrameTags = tags;
this.VerifyAndParse(frameMetaData); this.VerifyAndParse(frameMetaData);

2
src/ImageSharp/Formats/Tiff/TiffEncoderEntriesCollector.cs

@ -134,7 +134,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
private void ProcessMetadata(TiffFrameMetadata frameMetadata) private void ProcessMetadata(TiffFrameMetadata frameMetadata)
{ {
foreach (IExifValue entry in frameMetadata.FrameTags) foreach (IExifValue entry in frameMetadata.FrameTags.Values)
{ {
// todo: skip subIfd // todo: skip subIfd
if (entry.DataType == ExifDataType.Ifd) if (entry.DataType == ExifDataType.Ifd)

27
src/ImageSharp/Formats/Tiff/TiffFrameMetadata.cs

@ -21,6 +21,8 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
private const TiffPredictor DefaultPredictor = TiffPredictor.None; private const TiffPredictor DefaultPredictor = TiffPredictor.None;
private ExifProfile frameTags;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="TiffFrameMetadata"/> class. /// Initializes a new instance of the <see cref="TiffFrameMetadata"/> class.
/// </summary> /// </summary>
@ -29,9 +31,13 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
} }
/// <summary> /// <summary>
/// Gets the Tiff directory tags list. /// Gets the Tiff directory tags.
/// </summary> /// </summary>
public List<IExifValue> FrameTags { get; internal set; } = new List<IExifValue>(); public ExifProfile FrameTags
{
get => this.frameTags ??= new ExifProfile();
internal set => this.frameTags = value;
}
/// <summary>Gets a general indication of the kind of data contained in this subfile.</summary> /// <summary>Gets a general indication of the kind of data contained in this subfile.</summary>
/// <value>A general indication of the kind of data contained in this subfile.</value> /// <value>A general indication of the kind of data contained in this subfile.</value>
@ -241,7 +247,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
public void ClearMetadata() public void ClearMetadata()
{ {
var tags = new List<IExifValue>(); var tags = new List<IExifValue>();
foreach (IExifValue entry in this.FrameTags) foreach (IExifValue entry in this.FrameTags.Values)
{ {
switch ((ExifTagValue)(ushort)entry.Tag) 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;
} }
/// <inheritdoc/> /// <inheritdoc/>
public IDeepCloneable DeepClone() public IDeepCloneable DeepClone() => new TiffFrameMetadata() { FrameTags = this.FrameTags.DeepClone() };
{
var tags = new List<IExifValue>();
foreach (IExifValue entry in this.FrameTags)
{
tags.Add(entry.DeepClone());
}
return new TiffFrameMetadata() { FrameTags = tags };
}
} }
} }

59
src/ImageSharp/Formats/Tiff/TiffFrameMetadataExtensions.cs

@ -31,7 +31,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
public static bool TryGetArray<T>(this TiffFrameMetadata meta, ExifTag tag, out T[] result) public static bool TryGetArray<T>(this TiffFrameMetadata meta, ExifTag tag, out T[] result)
where T : struct where T : struct
{ {
foreach (IExifValue entry in meta.FrameTags) foreach (IExifValue entry in meta.FrameTags.Values)
{ {
if (entry.Tag == tag) if (entry.Tag == tag)
{ {
@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
public static string GetString(this TiffFrameMetadata meta, ExifTag tag) 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) if (entry.Tag == tag)
{ {
@ -80,13 +80,8 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
return null; return null;
} }
public static bool SetString(this TiffFrameMetadata meta, ExifTag tag, string value) public static void SetString(this TiffFrameMetadata meta, ExifTag tag, string value) =>
{ meta.FrameTags.SetValueInternal(tag, value);
IExifValue obj = FindOrCreate(meta, tag);
DebugGuard.IsTrue(obj.DataType == ExifDataType.Ascii, "Expected string entry");
return obj.TrySetValue(value);
}
public static TEnum? GetSingleEnumNullable<TEnum, TTagValue>(this TiffFrameMetadata meta, ExifTag tag) public static TEnum? GetSingleEnumNullable<TEnum, TTagValue>(this TiffFrameMetadata meta, ExifTag tag)
where TEnum : struct where TEnum : struct
@ -105,15 +100,10 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
where TTagValue : struct where TTagValue : struct
=> meta.GetSingleEnumNullable<TEnum, TTagValue>(tag) ?? (defaultValue != null ? defaultValue.Value : throw TiffThrowHelper.TagNotFound(nameof(tag))); => meta.GetSingleEnumNullable<TEnum, TTagValue>(tag) ?? (defaultValue != null ? defaultValue.Value : throw TiffThrowHelper.TagNotFound(nameof(tag)));
public static bool SetSingleEnum<TEnum, TTagValue>(this TiffFrameMetadata meta, ExifTag tag, TEnum value) public static void SetSingleEnum<TEnum, TTagValue>(this TiffFrameMetadata meta, ExifTag tag, TEnum value)
where TEnum : struct where TEnum : struct
where TTagValue : struct where TTagValue : struct
{ => meta.FrameTags.SetValueInternal(tag, value);
IExifValue obj = FindOrCreate(meta, tag);
object val = (TTagValue)(object)value;
return obj.TrySetValue(val);
}
public static T GetSingle<T>(this TiffFrameMetadata meta, ExifTag tag) public static T GetSingle<T>(this TiffFrameMetadata meta, ExifTag tag)
where T : struct where T : struct
@ -129,7 +119,7 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
public static bool TryGetSingle<T>(this TiffFrameMetadata meta, ExifTag tag, out T result) public static bool TryGetSingle<T>(this TiffFrameMetadata meta, ExifTag tag, out T result)
where T : struct where T : struct
{ {
foreach (IExifValue entry in meta.FrameTags) foreach (IExifValue entry in meta.FrameTags.Values)
{ {
if (entry.Tag == tag) if (entry.Tag == tag)
{ {
@ -146,20 +136,14 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
return false; return false;
} }
public static bool SetSingle<T>(this TiffFrameMetadata meta, ExifTag tag, T value) public static void SetSingle<T>(this TiffFrameMetadata meta, ExifTag tag, T value)
where T : struct where T : struct
{ => meta.FrameTags.SetValueInternal(tag, value);
IExifValue obj = FindOrCreate(meta, tag);
DebugGuard.IsTrue(!obj.IsArray, "Expected non array entry");
object val = value;
return obj.TrySetValue(val);
}
public static bool Remove(this TiffFrameMetadata meta, ExifTag tag) public static bool Remove(this TiffFrameMetadata meta, ExifTag tag)
{ {
IExifValue obj = null; IExifValue obj = null;
foreach (IExifValue entry in meta.FrameTags) foreach (IExifValue entry in meta.FrameTags.Values)
{ {
if (entry.Tag == tag) if (entry.Tag == tag)
{ {
@ -170,31 +154,10 @@ namespace SixLabors.ImageSharp.Formats.Experimental.Tiff
if (obj != null) if (obj != null)
{ {
return meta.FrameTags.Remove(obj); return meta.FrameTags.RemoveValue(obj.Tag);
} }
return false; 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;
}
} }
} }

4
src/ImageSharp/Metadata/Profiles/Exif/ExifProfile.cs

@ -4,6 +4,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Metadata.Profiles.Exif namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
@ -258,6 +259,9 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
this.SyncResolution(ExifTag.YResolution, metadata.VerticalResolution); this.SyncResolution(ExifTag.YResolution, metadata.VerticalResolution);
} }
internal void InitializeInternal(List<IExifValue> values) =>
this.values = values;
private void SyncResolution(ExifTag<Rational> tag, double resolution) private void SyncResolution(ExifTag<Rational> tag, double resolution)
{ {
IExifValue<Rational> value = this.GetValue(tag); IExifValue<Rational> value = this.GetValue(tag);

Loading…
Cancel
Save