Browse Source

Reduced intermediate allocations: Profiles

pull/2415/head
Günther Foidl 4 years ago
parent
commit
5d65ef0afd
  1. 33
      src/ImageSharp/Metadata/Profiles/Exif/ExifReader.cs
  2. 4
      src/ImageSharp/Metadata/Profiles/Exif/Values/ExifByteArray.cs
  3. 14
      src/ImageSharp/Metadata/Profiles/ICC/IccProfile.cs

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

@ -86,10 +86,6 @@ internal class ExifReader : BaseExifReader
/// </summary> /// </summary>
internal abstract class BaseExifReader internal abstract class BaseExifReader
{ {
private readonly byte[] buf8 = new byte[8];
private readonly byte[] buf4 = new byte[4];
private readonly byte[] buf2 = new byte[2];
private readonly MemoryAllocator? allocator; private readonly MemoryAllocator? allocator;
private readonly Stream data; private readonly Stream data;
private List<ExifTag>? invalidTags; private List<ExifTag>? invalidTags;
@ -528,20 +524,33 @@ internal abstract class BaseExifReader
return read == length; return read == length;
} }
protected ulong ReadUInt64() => protected ulong ReadUInt64()
this.TryReadSpan(this.buf8) {
? this.ConvertToUInt64(this.buf8) Span<byte> buffer = stackalloc byte[8];
return this.TryReadSpan(buffer)
? this.ConvertToUInt64(buffer)
: default; : default;
}
// Known as Long in Exif Specification. // Known as Long in Exif Specification.
protected uint ReadUInt32() => protected uint ReadUInt32()
this.TryReadSpan(this.buf4) {
? this.ConvertToUInt32(this.buf4) Span<byte> buffer = stackalloc byte[4];
return this.TryReadSpan(buffer)
? this.ConvertToUInt32(buffer)
: default; : default;
}
protected ushort ReadUInt16() => this.TryReadSpan(this.buf2) protected ushort ReadUInt16()
? this.ConvertToShort(this.buf2) {
Span<byte> buffer = stackalloc byte[2];
return this.TryReadSpan(buffer)
? this.ConvertToShort(buffer)
: default; : default;
}
private long ConvertToInt64(ReadOnlySpan<byte> buffer) private long ConvertToInt64(ReadOnlySpan<byte> buffer)
{ {

4
src/ImageSharp/Metadata/Profiles/Exif/Values/ExifByteArray.cs

@ -45,12 +45,12 @@ internal sealed class ExifByteArray : ExifArrayValue<byte>
private bool TrySetSignedIntArray(int[] intArrayValue) private bool TrySetSignedIntArray(int[] intArrayValue)
{ {
if (Array.FindIndex(intArrayValue, x => x < byte.MinValue || x > byte.MaxValue) > -1) if (Array.FindIndex(intArrayValue, x => (uint)x > byte.MaxValue) >= 0)
{ {
return false; return false;
} }
var value = new byte[intArrayValue.Length]; byte[] value = new byte[intArrayValue.Length];
for (int i = 0; i < intArrayValue.Length; i++) for (int i = 0; i < intArrayValue.Length; i++)
{ {
int s = intArrayValue[i]; int s = intArrayValue[i];

14
src/ImageSharp/Metadata/Profiles/ICC/IccProfile.cs

@ -108,10 +108,10 @@ public sealed class IccProfile : IDeepCloneable<IccProfile>
const int profileIdPos = 84; const int profileIdPos = 84;
// need to copy some values because they need to be zero for the hashing // need to copy some values because they need to be zero for the hashing
byte[] temp = new byte[24]; Span<byte> temp = stackalloc byte[24];
Buffer.BlockCopy(data, profileFlagPos, temp, 0, 4); data.AsSpan(profileFlagPos, 4).CopyTo(temp);
Buffer.BlockCopy(data, renderingIntentPos, temp, 4, 4); data.AsSpan(renderingIntentPos, 4).CopyTo(temp.Slice(4));
Buffer.BlockCopy(data, profileIdPos, temp, 8, 16); data.AsSpan(profileIdPos, 16).CopyTo(temp.Slice(8));
try try
{ {
@ -131,9 +131,9 @@ public sealed class IccProfile : IDeepCloneable<IccProfile>
} }
finally finally
{ {
Buffer.BlockCopy(temp, 0, data, profileFlagPos, 4); temp.Slice(0, 4).CopyTo(data.AsSpan(profileFlagPos));
Buffer.BlockCopy(temp, 4, data, renderingIntentPos, 4); temp.Slice(4, 4).CopyTo(data.AsSpan(renderingIntentPos));
Buffer.BlockCopy(temp, 8, data, profileIdPos, 16); temp.Slice(8, 16).CopyTo(data.AsSpan(profileIdPos));
} }
} }

Loading…
Cancel
Save