From e46266737b4eddd6ce727477f4e2b8c674267dfb Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 12 May 2016 21:58:47 +1000 Subject: [PATCH] Add Bootstrapper Former-commit-id: 3697a99fa9f1578be79fe7c25ab0c80621284486 Former-commit-id: dff38d2a7517949e251371504082ec4d767f257e Former-commit-id: daa364a34287743b2bc6cf667268c7059a9aa9f4 --- src/ImageProcessorCore/Bootstrapper.cs | 62 ++++++++++++++++++++ src/ImageProcessorCore/Image.cs | 71 +++++++++-------------- src/ImageProcessorCore/ImageExtensions.cs | 2 + 3 files changed, 93 insertions(+), 42 deletions(-) create mode 100644 src/ImageProcessorCore/Bootstrapper.cs diff --git a/src/ImageProcessorCore/Bootstrapper.cs b/src/ImageProcessorCore/Bootstrapper.cs new file mode 100644 index 000000000..3f1e5c1fe --- /dev/null +++ b/src/ImageProcessorCore/Bootstrapper.cs @@ -0,0 +1,62 @@ +// +// Copyright (c) James Jackson-South and contributors. +// Licensed under the Apache License, Version 2.0. +// + +namespace ImageProcessorCore +{ + using System; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using ImageProcessorCore.Formats; + + /// + /// Provides initialization code which allows extending the library. + /// + public class Bootstrapper + { + /// + /// A new instance Initializes a new instance of the class. + /// with lazy initialization. + /// + private static readonly Lazy Lazy = new Lazy(() => new Bootstrapper()); + + /// + /// The default list of supported + /// + private readonly List imageFormats; + + /// + /// Prevents a default instance of the class from being created. + /// + private Bootstrapper() + { + this.imageFormats = new List(new List + { + new BmpFormat(), + new JpegFormat(), + new PngFormat(), + new GifFormat() + }); + } + + /// + /// Gets the current bootstrapper instance. + /// + public static Bootstrapper Instance = Lazy.Value; + + /// + /// Gets the list of supported + /// + public IReadOnlyCollection ImageFormats => new ReadOnlyCollection(imageFormats); + + /// + /// Adds a new to the collection of supported image formats. + /// + /// The new format to add. + public void AddImageFormat(IImageFormat format) + { + this.imageFormats.Add(format); + } + } +} diff --git a/src/ImageProcessorCore/Image.cs b/src/ImageProcessorCore/Image.cs index e772ad2c0..acef0c4d3 100644 --- a/src/ImageProcessorCore/Image.cs +++ b/src/ImageProcessorCore/Image.cs @@ -7,6 +7,7 @@ namespace ImageProcessorCore { using System; using System.Collections.Generic; + using System.Collections.ObjectModel; using System.Diagnostics; using System.IO; using System.Linq; @@ -18,8 +19,8 @@ namespace ImageProcessorCore /// Encapsulates an image, which consists of the pixel data for a graphics image and its attributes. /// /// - /// The image data is always stored in BGRA format, where the blue, green, red, and - /// alpha values are simple bytes. + /// The image data is always stored in RGBA format, where the red, green, blue, and + /// alpha values are floats. /// [DebuggerDisplay("Image: {Width}x{Height}")] public class Image : ImageBase, IImage @@ -36,18 +37,6 @@ namespace ImageProcessorCore /// public const double DefaultVerticalResolution = 96; - /// - /// The default collection of . - /// - private static readonly Lazy> DefaultFormats = - new Lazy>(() => new List - { - new BmpFormat(), - new JpegFormat(), - new PngFormat(), - new GifFormat() - }); - /// /// Initializes a new instance of the class. /// @@ -55,7 +44,7 @@ namespace ImageProcessorCore { this.HorizontalResolution = DefaultHorizontalResolution; this.VerticalResolution = DefaultVerticalResolution; - this.CurrentImageFormat = DefaultFormats.Value.First(f => f.GetType() == typeof(PngFormat)); + this.CurrentImageFormat = Bootstrapper.Instance.ImageFormats.First(f => f.GetType() == typeof(PngFormat)); } /// @@ -69,7 +58,7 @@ namespace ImageProcessorCore { this.HorizontalResolution = DefaultHorizontalResolution; this.VerticalResolution = DefaultVerticalResolution; - this.CurrentImageFormat = DefaultFormats.Value.First(f => f.GetType() == typeof(PngFormat)); + this.CurrentImageFormat = Bootstrapper.Instance.ImageFormats.First(f => f.GetType() == typeof(PngFormat)); } /// @@ -92,6 +81,7 @@ namespace ImageProcessorCore this.RepeatCount = other.RepeatCount; this.HorizontalResolution = other.HorizontalResolution; this.VerticalResolution = other.VerticalResolution; + this.Formats = other.Formats; this.CurrentImageFormat = other.CurrentImageFormat; } @@ -112,7 +102,7 @@ namespace ImageProcessorCore // Most likely a gif // TODO: Should this be aproperty on ImageFrame? - this.CurrentImageFormat = DefaultFormats.Value.First(f => f.GetType() == typeof(GifFormat)); + this.CurrentImageFormat = Bootstrapper.Instance.ImageFormats.First(f => f.GetType() == typeof(GifFormat)); } /// @@ -125,7 +115,7 @@ namespace ImageProcessorCore public Image(Stream stream) { Guard.NotNull(stream, nameof(stream)); - this.Load(stream, Formats); + this.Load(stream, Bootstrapper.Instance.ImageFormats.ToList()); } /// @@ -141,13 +131,13 @@ namespace ImageProcessorCore public Image(Stream stream, params IImageFormat[] formats) { Guard.NotNull(stream, nameof(stream)); - this.Load(stream, formats); + this.Load(stream, formats.ToList()); } /// /// Gets a list of supported image formats. /// - public static IList Formats => DefaultFormats.Value; + public IReadOnlyCollection Formats { get; internal set; } = Bootstrapper.Instance.ImageFormats; /// public double HorizontalResolution { get; set; } @@ -258,24 +248,24 @@ namespace ImageProcessorCore this.Frames.Clear(); } } - + base.Dispose(disposing); } /// /// Loads the image from the given stream. /// - /// - /// The stream containing image information. - /// - /// - /// The collection of . - /// + /// The stream containing image information. + /// The collection of . /// /// Thrown if the stream is not readable nor seekable. /// private void Load(Stream stream, IList formats) { + if (!formats.Any()) { return; } + + this.Formats = new ReadOnlyCollection(formats); + if (!stream.CanRead) { throw new NotSupportedException("Cannot read from the stream."); @@ -286,24 +276,21 @@ namespace ImageProcessorCore throw new NotSupportedException("The stream does not support seeking."); } - if (formats.Count > 0) + int maxHeaderSize = formats.Max(x => x.Decoder.HeaderSize); + if (maxHeaderSize > 0) { - int maxHeaderSize = formats.Max(x => x.Decoder.HeaderSize); - if (maxHeaderSize > 0) - { - byte[] header = new byte[maxHeaderSize]; + byte[] header = new byte[maxHeaderSize]; - stream.Position = 0; - stream.Read(header, 0, maxHeaderSize); - stream.Position = 0; + stream.Position = 0; + stream.Read(header, 0, maxHeaderSize); + stream.Position = 0; - IImageFormat format = formats.FirstOrDefault(x => x.Decoder.IsSupportedFileFormat(header)); - if (format != null) - { - format.Decoder.Decode(this, stream); - this.CurrentImageFormat = format; - return; - } + IImageFormat format = formats.FirstOrDefault(x => x.Decoder.IsSupportedFileFormat(header)); + if (format != null) + { + format.Decoder.Decode(this, stream); + this.CurrentImageFormat = format; + return; } } diff --git a/src/ImageProcessorCore/ImageExtensions.cs b/src/ImageProcessorCore/ImageExtensions.cs index aa10a2b08..0e9603b51 100644 --- a/src/ImageProcessorCore/ImageExtensions.cs +++ b/src/ImageProcessorCore/ImageExtensions.cs @@ -144,8 +144,10 @@ namespace ImageProcessorCore : new Image { // Several properties require copying + // TODO: Check why we need to set these? HorizontalResolution = source.HorizontalResolution, VerticalResolution = source.VerticalResolution, + Formats = source.Formats, CurrentImageFormat = source.CurrentImageFormat, RepeatCount = source.RepeatCount };