diff --git a/src/ImageSharp/Bootstrapper.cs b/src/ImageSharp/Bootstrapper.cs index a73205a76..a30d206b0 100644 --- a/src/ImageSharp/Bootstrapper.cs +++ b/src/ImageSharp/Bootstrapper.cs @@ -38,6 +38,11 @@ namespace ImageSharp /// private readonly object syncRoot = new object(); + /// + /// The maximum header size of all formats. + /// + private int maxHeaderSize; + /// /// Prevents a default instance of the class from being created. /// @@ -50,6 +55,7 @@ namespace ImageSharp new PngFormat(), new GifFormat() }; + this.SetMaxHeaderSize(); this.parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }; } @@ -63,6 +69,11 @@ namespace ImageSharp /// public static ParallelOptions ParallelOptions => Instance.parallelOptions; + /// + /// Gets the maximum header size of all formats. + /// + internal static int MaxHeaderSize => Instance.maxHeaderSize; + /// /// Adds a new to the collection of supported image formats. /// @@ -86,6 +97,8 @@ namespace ImageSharp this.GuardDuplicate(format); this.imageFormats.Add(format); + + this.SetMaxHeaderSize(); } } @@ -114,5 +127,10 @@ namespace ImageSharp } } } + + private void SetMaxHeaderSize() + { + this.maxHeaderSize = imageFormats.Max(x => x.HeaderSize); + } } } diff --git a/src/ImageSharp/Image/Image.cs b/src/ImageSharp/Image/Image.cs index 93e247b32..6dfd1c6db 100644 --- a/src/ImageSharp/Image/Image.cs +++ b/src/ImageSharp/Image/Image.cs @@ -15,6 +15,7 @@ namespace ImageSharp using System.Threading.Tasks; using Formats; + using System.Buffers; /// /// Encapsulates an image, which consists of the pixel data for a graphics image and its attributes. @@ -399,25 +400,34 @@ namespace ImageSharp /// private bool Decode(Stream stream) { - int maxHeaderSize = Bootstrapper.ImageFormats.Max(x => x.HeaderSize); - if (maxHeaderSize > 0) + int maxHeaderSize = Bootstrapper.MaxHeaderSize; + if (maxHeaderSize <= 0) { - byte[] header = new byte[maxHeaderSize]; + return false; + } - stream.Position = 0; + IImageFormat format = null; + byte[] header = ArrayPool.Shared.Rent(maxHeaderSize); + try + { + long startPosition = stream.Position; stream.Read(header, 0, maxHeaderSize); stream.Position = 0; + format = Bootstrapper.ImageFormats.FirstOrDefault(x => x.IsSupportedFileFormat(header)); + } + finally + { + ArrayPool.Shared.Return(header); + } - IImageFormat format = Bootstrapper.ImageFormats.FirstOrDefault(x => x.IsSupportedFileFormat(header)); - if (format != null) - { - format.Decoder.Decode(this, stream); - this.CurrentImageFormat = format; - return true; - } + if (format == null) + { + return false; } - return false; + format.Decoder.Decode(this, stream); + this.CurrentImageFormat = format; + return true; } } }