Browse Source

Use MemoryAllocator

pull/1760/head
Ildar Khayrutdinov 4 years ago
parent
commit
e277a0dce6
  1. 11
      src/ImageSharp/Formats/Tiff/Ifd/DirectoryReader.cs
  2. 9
      src/ImageSharp/Formats/Tiff/Ifd/EntryReader.cs
  3. 4
      src/ImageSharp/Formats/Tiff/TiffDecoderCore.cs
  4. 52
      src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs

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

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using SixLabors.ImageSharp.Formats.Tiff.Constants;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Metadata.Profiles.Exif;
namespace SixLabors.ImageSharp.Formats.Tiff
@ -16,9 +17,15 @@ namespace SixLabors.ImageSharp.Formats.Tiff
{
private readonly Stream stream;
private readonly MemoryAllocator allocator;
private ulong nextIfdOffset;
public DirectoryReader(Stream stream) => this.stream = stream;
public DirectoryReader(Stream stream, MemoryAllocator allocator)
{
this.stream = stream;
this.allocator = allocator;
}
/// <summary>
/// Gets the byte order.
@ -64,7 +71,7 @@ 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);
var reader = new EntryReader(this.stream, this.ByteOrder, this.allocator);
reader.ReadTags(isBigTiff, this.nextIfdOffset);
if (reader.BigValues.Count > 0)

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

@ -5,17 +5,16 @@ using System.Collections.Generic;
using System.IO;
using SixLabors.ImageSharp.Formats.Tiff.Constants;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.Metadata.Profiles.Exif;
namespace SixLabors.ImageSharp.Formats.Tiff
{
internal class EntryReader : BaseExifReader
{
public EntryReader(Stream stream, ByteOrder byteOrder)
: base(stream)
{
public EntryReader(Stream stream, ByteOrder byteOrder, MemoryAllocator allocator)
: base(stream, allocator) =>
this.IsBigEndian = byteOrder == ByteOrder.BigEndian;
}
public List<IExifValue> Values { get; } = new List<IExifValue>();
@ -45,7 +44,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff
internal class HeaderReader : BaseExifReader
{
public HeaderReader(Stream stream, ByteOrder byteOrder)
: base(stream) =>
: base(stream, null) =>
this.IsBigEndian = byteOrder == ByteOrder.BigEndian;
public bool IsBigTiff { get; private set; }

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

@ -147,7 +147,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff
where TPixel : unmanaged, IPixel<TPixel>
{
this.inputStream = stream;
var reader = new DirectoryReader(stream);
var reader = new DirectoryReader(stream, this.Configuration.MemoryAllocator);
IEnumerable<ExifProfile> directories = reader.Read();
this.byteOrder = reader.ByteOrder;
@ -181,7 +181,7 @@ namespace SixLabors.ImageSharp.Formats.Tiff
public IImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken)
{
this.inputStream = stream;
var reader = new DirectoryReader(stream);
var reader = new DirectoryReader(stream, this.Configuration.MemoryAllocator);
IEnumerable<ExifProfile> directories = reader.Read();
ExifProfile rootFrameExifProfile = directories.First();

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

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Buffers.Binary;
using System.Collections.Generic;
using System.Collections.ObjectModel;
@ -9,13 +10,19 @@ using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using SixLabors.ImageSharp.Memory;
namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
{
internal class ExifReader : BaseExifReader
{
public ExifReader(byte[] exifData)
: base(new MemoryStream(exifData ?? throw new ArgumentNullException(nameof(exifData))))
: this(exifData, null)
{
}
public ExifReader(byte[] exifData, MemoryAllocator allocator)
: base(new MemoryStream(exifData ?? throw new ArgumentNullException(nameof(exifData))), allocator)
{
}
@ -83,13 +90,17 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
private readonly byte[] buf4 = new byte[4];
private readonly byte[] buf2 = new byte[2];
private readonly MemoryAllocator allocator;
private readonly Stream data;
private List<ExifTag> invalidTags;
private List<ulong> subIfds;
protected BaseExifReader(Stream stream) =>
protected BaseExifReader(Stream stream, MemoryAllocator allocator)
{
this.data = stream ?? throw new ArgumentNullException(nameof(stream));
this.allocator = allocator;
}
private delegate TDataType ConverterMethod<TDataType>(ReadOnlySpan<byte> data);
@ -110,7 +121,7 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
public bool IsBigEndian { get; protected set; }
public List<(ulong offset, ExifDataType dataType, ulong numberOfComponents, ExifValue exif)> BigValues { get; } = new ();
public List<(ulong offset, ExifDataType dataType, ulong numberOfComponents, ExifValue exif)> BigValues { get; } = new();
protected void ReadBigValues(List<IExifValue> values)
{
@ -119,22 +130,41 @@ namespace SixLabors.ImageSharp.Metadata.Profiles.Exif
return;
}
ulong maxSize = 0;
int maxSize = 0;
foreach ((ulong offset, ExifDataType dataType, ulong numberOfComponents, ExifValue exif) in this.BigValues)
{
ulong size = numberOfComponents * ExifDataTypes.GetSize(dataType);
if (size > maxSize)
if (size > int.MaxValue)
{
ThrowHelper.ThrowArgumentOutOfRangeExceptionForMustBeLessThanOrEqualTo<ulong>(size, int.MaxValue, nameof(size));
}
if ((int)size > maxSize)
{
maxSize = size;
maxSize = (int)size;
}
}
Span<byte> buf = new byte[maxSize];
foreach ((ulong offset, ExifDataType dataType, ulong numberOfComponents, ExifValue exif) tag in this.BigValues)
if (this.allocator != null)
{
ulong size = tag.numberOfComponents * ExifDataTypes.GetSize(tag.dataType);
this.ReadBigValue(values, tag, buf.Slice(0, (int)size));
// tiff, bigTiff
using IMemoryOwner<byte> memory = this.allocator.Allocate<byte>(maxSize);
Span<byte> buf = memory.GetSpan();
foreach ((ulong offset, ExifDataType dataType, ulong numberOfComponents, ExifValue exif) tag in this.BigValues)
{
ulong size = tag.numberOfComponents * ExifDataTypes.GetSize(tag.dataType);
this.ReadBigValue(values, tag, buf.Slice(0, (int)size));
}
}
else
{
// embedded exif
Span<byte> buf = maxSize <= 256 ? stackalloc byte[maxSize] : new byte[maxSize];
foreach ((ulong offset, ExifDataType dataType, ulong numberOfComponents, ExifValue exif) tag in this.BigValues)
{
ulong size = tag.numberOfComponents * ExifDataTypes.GetSize(tag.dataType);
this.ReadBigValue(values, tag, buf.Slice(0, (int)size));
}
}
this.BigValues.Clear();

Loading…
Cancel
Save