Browse Source

try improve reading ext

values
pull/1760/head
Ildar Khayrutdinov 5 years ago
parent
commit
ebb277a794
  1. 25
      src/ImageSharp/Formats/Tiff/Ifd/DirectoryReader.cs
  2. 10
      src/ImageSharp/Formats/Tiff/Ifd/EntryReader.cs
  3. 57
      src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs

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

@ -18,10 +18,6 @@ namespace SixLabors.ImageSharp.Formats.Tiff
private ulong nextIfdOffset; private ulong nextIfdOffset;
// used for sequential read big values (actual for multiframe big files)
// todo: different tags can link to the same data (stream offset) - investigate
private readonly SortedList<ulong, Action> lazyLoaders = new SortedList<ulong, Action>(new DuplicateKeyComparer<ulong>());
public DirectoryReader(Stream stream) => this.stream = stream; public DirectoryReader(Stream stream) => this.stream = stream;
/// <summary> /// <summary>
@ -68,23 +64,28 @@ namespace SixLabors.ImageSharp.Formats.Tiff
var readers = new List<EntryReader>(); var readers = new List<EntryReader>();
while (this.nextIfdOffset != 0 && this.nextIfdOffset < (ulong)this.stream.Length) while (this.nextIfdOffset != 0 && this.nextIfdOffset < (ulong)this.stream.Length)
{ {
var reader = new EntryReader(this.stream, this.ByteOrder, this.lazyLoaders); var reader = new EntryReader(this.stream, this.ByteOrder);
reader.ReadTags(isBigTiff, this.nextIfdOffset); reader.ReadTags(isBigTiff, this.nextIfdOffset);
this.nextIfdOffset = reader.NextIfdOffset; if (reader.ExtTags.Count > 0)
{
reader.ExtTags.Sort((t1, t2) => t1.offset.CompareTo(t2.offset));
readers.Add(reader); if (reader.ExtTags[0].offset < reader.NextIfdOffset)
} {
// this means that most likely all elements are placed before next IFD
reader.ReadExtValues();
}
}
// Sequential reading big values. this.nextIfdOffset = reader.NextIfdOffset;
foreach (Action loader in this.lazyLoaders.Values) readers.Add(reader);
{
loader();
} }
var list = new List<ExifProfile>(readers.Count); var list = new List<ExifProfile>(readers.Count);
foreach (EntryReader reader in readers) foreach (EntryReader reader in readers)
{ {
reader.ReadExtValues();
var profile = new ExifProfile(reader.Values, reader.InvalidTags); var profile = new ExifProfile(reader.Values, reader.InvalidTags);
list.Add(profile); list.Add(profile);
} }

10
src/ImageSharp/Formats/Tiff/Ifd/EntryReader.cs

@ -12,13 +12,10 @@ namespace SixLabors.ImageSharp.Formats.Tiff
{ {
internal class EntryReader : BaseExifReader internal class EntryReader : BaseExifReader
{ {
private readonly SortedList<ulong, Action> lazyLoaders; public EntryReader(Stream stream, ByteOrder byteOrder)
public EntryReader(Stream stream, ByteOrder byteOrder, SortedList<ulong, Action> lazyLoaders)
: base(stream) : base(stream)
{ {
this.IsBigEndian = byteOrder == ByteOrder.BigEndian; this.IsBigEndian = byteOrder == ByteOrder.BigEndian;
this.lazyLoaders = lazyLoaders;
} }
public List<IExifValue> Values { get; } = new List<IExifValue>(); public List<IExifValue> Values { get; } = new List<IExifValue>();
@ -43,8 +40,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff
} }
} }
protected override void RegisterExtLoader(ulong offset, Action reader) => public void ReadExtValues() => this.ReadExtValues(this.Values);
this.lazyLoaders.Add(offset, reader);
} }
internal class HeaderReader : BaseExifReader internal class HeaderReader : BaseExifReader
@ -81,7 +77,5 @@ namespace SixLabors.ImageSharp.Formats.Tiff
TiffThrowHelper.ThrowInvalidHeader(); TiffThrowHelper.ThrowInvalidHeader();
} }
protected override void RegisterExtLoader(ulong offset, Action reader) => throw new NotSupportedException();
} }
} }

57
src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs

@ -14,8 +14,6 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
{ {
internal class ExifReader : BaseExifReader internal class ExifReader : BaseExifReader
{ {
private readonly List<Action> loaders = new List<Action>();
public ExifReader(byte[] exifData) public ExifReader(byte[] exifData)
: base(new MemoryStream(exifData ?? throw new ArgumentNullException(nameof(exifData)))) : base(new MemoryStream(exifData ?? throw new ArgumentNullException(nameof(exifData))))
{ {
@ -41,22 +39,16 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
uint ifdOffset = this.ReadUInt32(); uint ifdOffset = this.ReadUInt32();
this.ReadValues(values, ifdOffset); this.ReadValues(values, ifdOffset);
this.ReadExtValues(values);
uint thumbnailOffset = this.ReadUInt32(); uint thumbnailOffset = this.ReadUInt32();
this.GetThumbnail(thumbnailOffset); this.GetThumbnail(thumbnailOffset);
this.ReadSubIfd(values); this.ReadSubIfd(values);
foreach (Action loader in this.loaders)
{
loader();
}
return values; return values;
} }
protected override void RegisterExtLoader(ulong offset, Action loader) => this.loaders.Add(loader);
private void GetThumbnail(uint offset) private void GetThumbnail(uint offset)
{ {
if (offset == 0) if (offset == 0)
@ -121,7 +113,17 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
public bool IsBigEndian { get; protected set; } public bool IsBigEndian { get; protected set; }
protected abstract void RegisterExtLoader(ulong offset, Action loader); public List<(ulong offset, ExifDataType dataType, ulong numberOfComponents, ExifValue exif)> ExtTags { get; } = new ();
protected void ReadExtValues(List<IExifValue> values)
{
foreach ((ulong offset, ExifDataType dataType, ulong numberOfComponents, ExifValue exif) tag in this.ExtTags)
{
this.ReadExtValue(values, tag);
}
this.ExtTags.Clear();
}
/// <summary> /// <summary>
/// Reads the values to the values collection. /// Reads the values to the values collection.
@ -173,6 +175,18 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
} }
} }
protected void ReadExtValue(IList<IExifValue> values, (ulong offset, ExifDataType dataType, ulong numberOfComponents, ExifValue exif) tag)
{
ulong size = tag.numberOfComponents * ExifDataTypes.GetSize(tag.dataType);
byte[] dataBuffer = new byte[size];
this.Seek(tag.offset);
if (this.TryReadSpan(dataBuffer))
{
object value = this.ConvertValue(tag.dataType, dataBuffer, tag.numberOfComponents);
this.Add(values, tag.exif, value);
}
}
protected void ReadSubIfd64(List<IExifValue> values) protected void ReadSubIfd64(List<IExifValue> values)
{ {
if (this.exifOffset != 0) if (this.exifOffset != 0)
@ -375,21 +389,11 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
return; return;
} }
this.RegisterExtLoader(newOffset, () => this.ExtTags.Add((newOffset, dataType, numberOfComponents, exifValue));
{
byte[] dataBuffer = new byte[size];
this.Seek(newOffset);
if (this.TryReadSpan(dataBuffer))
{
object value = this.ConvertValue(dataType, dataBuffer, numberOfComponents);
this.Add(values, exifValue, value);
}
});
} }
else else
{ {
object value = this.ConvertValue(dataType, this.offsetBuffer, numberOfComponents); object value = this.ConvertValue(dataType, this.offsetBuffer, numberOfComponents);
this.Add(values, exifValue, value); this.Add(values, exifValue, value);
} }
} }
@ -465,16 +469,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
return; return;
} }
this.RegisterExtLoader(newOffset, () => this.ExtTags.Add((newOffset, dataType, numberOfComponents, exifValue));
{
byte[] dataBuffer = new byte[size];
this.Seek(newOffset);
if (this.TryReadSpan(dataBuffer))
{
object value = this.ConvertValue(dataType, dataBuffer, numberOfComponents);
this.Add(values, exifValue, value);
}
});
} }
else else
{ {

Loading…
Cancel
Save