Browse Source

Merge pull request #1812 from SixLabors/af/InternalDetectFormat-DoNotAllocate

stackalloc header buffer in InternalDetectFormat
pull/1815/head
James Jackson-South 5 years ago
committed by GitHub
parent
commit
94b9962cca
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 25
      src/ImageSharp/Image.Decode.cs

25
src/ImageSharp/Image.Decode.cs

@ -58,9 +58,10 @@ namespace SixLabors.ImageSharp
return null; return null;
} }
using (IMemoryOwner<byte> buffer = config.MemoryAllocator.Allocate<byte>(headerSize, AllocationOptions.Clean)) // Header sizes are so small, that headersBuffer will be always stackalloc-ed in practice,
{ // and heap allocation will never happen, there is no need for the usual try-finally ArrayPool dance.
Span<byte> bufferSpan = buffer.GetSpan(); // The array case is only a safety mechanism following stackalloc best practices.
Span<byte> headersBuffer = headerSize > 512 ? new byte[headerSize] : stackalloc byte[headerSize];
long startPosition = stream.Position; long startPosition = stream.Position;
// Read doesn't always guarantee the full returned length so read a byte // Read doesn't always guarantee the full returned length so read a byte
@ -69,7 +70,7 @@ namespace SixLabors.ImageSharp
int i; int i;
do do
{ {
i = stream.Read(bufferSpan, n, headerSize - n); i = stream.Read(headersBuffer, n, headerSize - n);
n += i; n += i;
} }
while (n < headerSize && i > 0); while (n < headerSize && i > 0);
@ -79,11 +80,21 @@ namespace SixLabors.ImageSharp
// Does the given stream contain enough data to fit in the header for the format // Does the given stream contain enough data to fit in the header for the format
// and does that data match the format specification? // and does that data match the format specification?
// Individual formats should still check since they are public. // Individual formats should still check since they are public.
return config.ImageFormatsManager.FormatDetectors IImageFormat format = null;
.Where(x => x.HeaderSize <= headerSize) foreach (IImageFormatDetector formatDetector in config.ImageFormatsManager.FormatDetectors)
.Select(x => x.DetectFormat(buffer.GetSpan())).LastOrDefault(x => x != null); {
if (formatDetector.HeaderSize <= headerSize)
{
IImageFormat attemptFormat = formatDetector.DetectFormat(headersBuffer);
if (attemptFormat != null)
{
format = attemptFormat;
} }
} }
}
return format;
}
/// <summary> /// <summary>
/// By reading the header on the provided stream this calculates the images format. /// By reading the header on the provided stream this calculates the images format.

Loading…
Cancel
Save