Browse Source

try improve reading ext

values
pull/1760/head
Ildar Khayrutdinov 4 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;
// 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;
/// <summary>
@ -68,23 +64,28 @@ namespace SixLabors.ImageSharp.Formats.Tiff
var readers = new List<EntryReader>();
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);
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.
foreach (Action loader in this.lazyLoaders.Values)
{
loader();
this.nextIfdOffset = reader.NextIfdOffset;
readers.Add(reader);
}
var list = new List<ExifProfile>(readers.Count);
foreach (EntryReader reader in readers)
{
reader.ReadExtValues();
var profile = new ExifProfile(reader.Values, reader.InvalidTags);
list.Add(profile);
}

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

@ -12,13 +12,10 @@ namespace SixLabors.ImageSharp.Formats.Tiff
{
internal class EntryReader : BaseExifReader
{
private readonly SortedList<ulong, Action> lazyLoaders;
public EntryReader(Stream stream, ByteOrder byteOrder, SortedList<ulong, Action> lazyLoaders)
public EntryReader(Stream stream, ByteOrder byteOrder)
: base(stream)
{
this.IsBigEndian = byteOrder == ByteOrder.BigEndian;
this.lazyLoaders = lazyLoaders;
}
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) =>
this.lazyLoaders.Add(offset, reader);
public void ReadExtValues() => this.ReadExtValues(this.Values);
}
internal class HeaderReader : BaseExifReader
@ -81,7 +77,5 @@ namespace SixLabors.ImageSharp.Formats.Tiff
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
{
private readonly List<Action> loaders = new List<Action>();
public ExifReader(byte[] exifData)
: base(new MemoryStream(exifData ?? throw new ArgumentNullException(nameof(exifData))))
{
@ -41,22 +39,16 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
uint ifdOffset = this.ReadUInt32();
this.ReadValues(values, ifdOffset);
this.ReadExtValues(values);
uint thumbnailOffset = this.ReadUInt32();
this.GetThumbnail(thumbnailOffset);
this.ReadSubIfd(values);
foreach (Action loader in this.loaders)
{
loader();
}
return values;
}
protected override void RegisterExtLoader(ulong offset, Action loader) => this.loaders.Add(loader);
private void GetThumbnail(uint offset)
{
if (offset == 0)
@ -121,7 +113,17 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
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>
/// 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)
{
if (this.exifOffset != 0)
@ -375,21 +389,11 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
return;
}
this.RegisterExtLoader(newOffset, () =>
{
byte[] dataBuffer = new byte[size];
this.Seek(newOffset);
if (this.TryReadSpan(dataBuffer))
{
object value = this.ConvertValue(dataType, dataBuffer, numberOfComponents);
this.Add(values, exifValue, value);
}
});
this.ExtTags.Add((newOffset, dataType, numberOfComponents, exifValue));
}
else
{
object value = this.ConvertValue(dataType, this.offsetBuffer, numberOfComponents);
this.Add(values, exifValue, value);
}
}
@ -465,16 +469,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
return;
}
this.RegisterExtLoader(newOffset, () =>
{
byte[] dataBuffer = new byte[size];
this.Seek(newOffset);
if (this.TryReadSpan(dataBuffer))
{
object value = this.ConvertValue(dataType, dataBuffer, numberOfComponents);
this.Add(values, exifValue, value);
}
});
this.ExtTags.Add((newOffset, dataType, numberOfComponents, exifValue));
}
else
{

Loading…
Cancel
Save